renommage de lib, rendre buildable
This commit is contained in:
parent
1706c64713
commit
a89007a81b
9896 changed files with 478996 additions and 496 deletions
201
my-workspace/projects/sae-lib/node_modules/@scarf/scarf/LICENSE
generated
vendored
Normal file
201
my-workspace/projects/sae-lib/node_modules/@scarf/scarf/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2020 Scarf Systems, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
198
my-workspace/projects/sae-lib/node_modules/@scarf/scarf/README.md
generated
vendored
Normal file
198
my-workspace/projects/sae-lib/node_modules/@scarf/scarf/README.md
generated
vendored
Normal file
|
@ -0,0 +1,198 @@
|
|||
# scarf-js
|
||||
|
||||

|
||||
[](https://badge.fury.io/js/%40scarf%2Fscarf)
|
||||
<a href="https://www.npmjs.com/package/@scarf/scarf"></a>
|
||||
<img referrerpolicy="no-referrer-when-downgrade" src="https://static.scarf.sh/a.png?x-pxid=fc72d03c-c3a2-4736-b243-10eeff839778" />
|
||||
<a href="https://tinyurl.com/scarf-community-slack"><img src="https://img.shields.io/badge/Scarf%20Community%20-Slack-blue" alt="Join the Scarf Community Slack" />
|
||||
</a>
|
||||
|
||||
Scarf is like Google Analytics for your npm packages. By sending some basic
|
||||
details after installation, this package can help you can gain insight into how
|
||||
your packages are used and by which companies. Scarf aims to help open-source developers
|
||||
fund their work when it is used commercially.
|
||||
|
||||
To read more about why we wrote this library, check out [this post](https://github.com/scarf-sh/scarf-js/blob/master/WHY.org) on the topic.
|
||||
|
||||
### Features
|
||||
|
||||
- No dependencies.
|
||||
- Fully transparent to the user. Scarf will log its behavior to the console
|
||||
during installation. It will never silently report analytics for someone that
|
||||
hasn't explictly given permission to do so.
|
||||
- Never interrupts your package installation. Reporting is done on a best effort basis.
|
||||
|
||||
### Installing
|
||||
|
||||
You'll first need to create a library entry on [Scarf](https://scarf.sh). Once
|
||||
created, add a dependency on this library to your own:
|
||||
|
||||
```bash
|
||||
npm i --save @scarf/scarf
|
||||
```
|
||||
|
||||
Once your library is published to npm with this change, Scarf will automatically
|
||||
collect stats on install, no additional code is required!
|
||||
|
||||
Head to your package's dashboard on Scarf to see your reports when available.
|
||||
|
||||
### Configuring
|
||||
|
||||
Users of your package will be opted in by default and can opt out by setting the
|
||||
`SCARF_ANALYTICS=false` environment variable. If you'd like Scarf analytics to
|
||||
instead be opt-in, you can set this by adding an entry to your `package.json`
|
||||
|
||||
|
||||
```json5
|
||||
// your-package/package.json
|
||||
|
||||
{
|
||||
// ...
|
||||
"scarfSettings": {
|
||||
"defaultOptIn": false
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Scarf will now be opt-out by default, and users can set `SCARF_ANALYTICS=true`
|
||||
to opt in.
|
||||
|
||||
Regardless of the default state, Scarf will log what it is doing to users who
|
||||
haven't explictly opted in or out.
|
||||
|
||||
By default, scarf-js will only trigger analytics when your package is installed as a dependency of another package, or is being installed globally. This ensures that scarf-js analytics will not be triggered on `npm install` being run _within your project_. To change this, you can add:
|
||||
|
||||
```json5
|
||||
// your-package/package.json
|
||||
|
||||
{
|
||||
// ...
|
||||
"scarfSettings": {
|
||||
"allowTopLevel": true
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### Full Configuration Example
|
||||
|
||||
```json5
|
||||
// your-package/package.json
|
||||
|
||||
{
|
||||
// ...
|
||||
"scarfSettings": {
|
||||
// Toggles whether Scarf is enabled for this package
|
||||
"enabled": true,
|
||||
// Enables Scarf when users run npm install directly in your repository
|
||||
// Scarf will try to report the Git commit SHA of your repository if it can
|
||||
// be obtained.
|
||||
"allowTopLevel": true,
|
||||
// Users will be opted into analytics by default
|
||||
"defaultOptIn": true,
|
||||
// By default, Scarf searches for its own location in your build's dependency
|
||||
// graph to ensure reporting can be done for all packages using Scarf.
|
||||
// For large projects with lots of dependencies, generating that dependency
|
||||
// graph takes more time than Scarf allots for its entire process, so Scarf
|
||||
// will always time out. `skipTraversal` is an optional flag for large
|
||||
// applications to skip that traversal entirely. Use this flag with caution and
|
||||
// care, as it will break Scarf analytics for all other packages you depend
|
||||
// on in your build.
|
||||
"skipTraversal": false
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### FAQ
|
||||
|
||||
#### What information does scarf-js provide me as a package author?
|
||||
|
||||
- Understanding your user-base
|
||||
- Which companies are using your package?
|
||||
- Is your project growing or shrinking? Where? On which platforms?
|
||||
- Which versions of your package are being used?
|
||||
|
||||
#### As a user of a package using scarf-js, what information does scarf-js send about me?
|
||||
|
||||
*Scarf does not store personally identifying information.* Scarf aims to collect information that is helpful for:
|
||||
- Open Source package maintainence
|
||||
- Open Source commercialization
|
||||
|
||||
Specifically, scarf-js sends:
|
||||
|
||||
- The operating system you are using
|
||||
- Your IP address will be used to look up any available company information. _Scarf does not store the actual IP address_
|
||||
- Limited dependency tree information. Scarf sends the name and version of the package(s) that directly depend on scarf-js. Additionally, scarf-js will send SHA256-hashed name and version for the following packages in the dependency tree:
|
||||
- Packages that depend on a package that depends on scarf-js.
|
||||
- The root package of the dependency tree.
|
||||
This allows Scarf to provide information for maintainers about which public packages are using their own, without exposing identifying details of non-public packages.
|
||||
|
||||
You can have scarf-js print the exact JSON payload it sends by setting `SCARF_VERBOSE=true` in your environment.
|
||||
|
||||
#### As a user of a package using scarf-js, how can I opt out of analytics?
|
||||
|
||||
Scarf's analytics help support developers of the open source packages you are
|
||||
using, so enabling analytics is appreciated. However, if you'd like to opt out,
|
||||
you can add your preference to your project's `package.json`:
|
||||
|
||||
|
||||
```json5
|
||||
// your-package/package.json
|
||||
|
||||
{
|
||||
// ...
|
||||
"scarfSettings": {
|
||||
"enabled": false
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Alternatively, you can set this variable in your environment:
|
||||
|
||||
```shell
|
||||
export SCARF_ANALYTICS=false
|
||||
```
|
||||
|
||||
You can also set this variable in accordance to the [Console Do Not Track](https://consoledonottrack.com/) standard:
|
||||
```shell
|
||||
export DO_NOT_TRACK=1
|
||||
```
|
||||
|
||||
Either route will disable Scarf for all packages.
|
||||
|
||||
#### I distribute a package on npm, and scarf-js is in our dependency tree. Can I disable the analytics for my downstream dependents?
|
||||
|
||||
Yes. By opting out of analytics via `package.json`, any package upstream will have analytics disbabled.
|
||||
|
||||
```json5
|
||||
// your-package/package.json
|
||||
|
||||
{
|
||||
// ...
|
||||
"scarfSettings": {
|
||||
"enabled": false
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Installers of your packages will have scarf-js disabled for all dependencies upstream from yours.
|
||||
|
||||
|
||||
### Developing
|
||||
|
||||
Setting the environment variable `SCARF_LOCAL_PORT=8080` will configure Scarf to
|
||||
use http://localhost:8080 as the analytics endpoint host.
|
||||
|
||||
### Future work
|
||||
|
||||
Future releases of scarf-js will provide a module of utility functions to
|
||||
collect usage analytics in addition to the current installation analytics.
|
||||
|
||||
### Community
|
||||
|
||||
Join the [Scarf-Community workspace](https://tinyurl.com/scarf-community-slack) on Slack and find us in the #scarf-js channel. We'll keep an eye out for your questions and concerns.
|
36
my-workspace/projects/sae-lib/node_modules/@scarf/scarf/package.json
generated
vendored
Normal file
36
my-workspace/projects/sae-lib/node_modules/@scarf/scarf/package.json
generated
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"name": "@scarf/scarf",
|
||||
"version": "1.4.0",
|
||||
"description": "Scarf is like Google Analytics for your npm packages. Gain insights into how your packages are installed and used, and by which companies.",
|
||||
"main": "report.js",
|
||||
"homepage": "https://github.com/scarf-sh/scarf-js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/scarf-sh/scarf-js.git"
|
||||
},
|
||||
"files": [
|
||||
"report.js"
|
||||
],
|
||||
"scripts": {
|
||||
"postinstall": "node ./report.js",
|
||||
"test": "jest --verbose"
|
||||
},
|
||||
"author": "Scarf Systems",
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"jest": "^25.3.0",
|
||||
"minimist": "^1.2.2",
|
||||
"standard": "^14.3.1"
|
||||
},
|
||||
"standard": {
|
||||
"globals": [
|
||||
"expect",
|
||||
"test",
|
||||
"jest",
|
||||
"beforeAll",
|
||||
"afterAll",
|
||||
"fail",
|
||||
"describe"
|
||||
]
|
||||
}
|
||||
}
|
574
my-workspace/projects/sae-lib/node_modules/@scarf/scarf/report.js
generated
vendored
Normal file
574
my-workspace/projects/sae-lib/node_modules/@scarf/scarf/report.js
generated
vendored
Normal file
|
@ -0,0 +1,574 @@
|
|||
const path = require('path')
|
||||
const os = require('os')
|
||||
const exec = require('child_process').exec
|
||||
const localDevPort = process.env.SCARF_LOCAL_PORT
|
||||
const https = localDevPort ? require('http') : require('https')
|
||||
const fs = require('fs')
|
||||
const fsAsync = fs.promises
|
||||
const util = require('util')
|
||||
|
||||
const scarfHost = localDevPort ? 'localhost' : 'scarf.sh'
|
||||
const scarfLibName = '@scarf/scarf'
|
||||
const privatePackageRewrite = '@private/private'
|
||||
const privateVersionRewrite = '0'
|
||||
|
||||
const rootPath = process.env.INIT_CWD
|
||||
|
||||
// Pulled into a function for test mocking
|
||||
function tmpFileName () {
|
||||
// throttle per user
|
||||
const username = os.userInfo().username
|
||||
return path.join(os.tmpdir(), `scarf-js-history-${username}.log`)
|
||||
}
|
||||
|
||||
// Pulled into a function for test mocking
|
||||
function dirName () {
|
||||
return __dirname
|
||||
}
|
||||
|
||||
function npmExecPath () {
|
||||
return process.env.npm_execpath
|
||||
}
|
||||
|
||||
const userMessageThrottleTime = 1000 * 60 // 1 minute
|
||||
|
||||
const execTimeout = 3000
|
||||
|
||||
// In general, these keys should never change to remain backwards compatible
|
||||
// with previous versions of Scarf. If we need to update them, we'll need to
|
||||
// make sure we can read the previous values as well
|
||||
const optedInLogRateLimitKey = 'optedInLastLog'
|
||||
const optedOutLogRateLimitKey = 'optedOutLastLog'
|
||||
|
||||
const makeDefaultSettings = () => {
|
||||
return {
|
||||
defaultOptIn: true
|
||||
}
|
||||
}
|
||||
|
||||
function logIfVerbose (toLog, stream) {
|
||||
if (process.env.SCARF_VERBOSE === 'true') {
|
||||
(stream || console.log)(toLog)
|
||||
}
|
||||
}
|
||||
|
||||
// SCARF_NO_ANALYTICS was the original variable, we'll get rid of it eventually
|
||||
const userHasOptedOut = (rootPackage) => {
|
||||
return (rootPackage && rootPackage.scarfSettings && rootPackage.scarfSettings.enabled === false) ||
|
||||
(process.env.SCARF_ANALYTICS === 'false' || process.env.SCARF_NO_ANALYTICS === 'true' || process.env.DO_NOT_TRACK === '1')
|
||||
}
|
||||
|
||||
const userHasOptedIn = (rootPackage) => {
|
||||
return (rootPackage && rootPackage.scarfSettings && rootPackage.scarfSettings.enabled) || process.env.SCARF_ANALYTICS === 'true'
|
||||
}
|
||||
|
||||
// Packages that depend on Scarf can configure whether to should fire when
|
||||
// `npm install` is being run directly from within the package, rather than from a
|
||||
// dependent package
|
||||
function allowTopLevel (rootPackage) {
|
||||
return rootPackage && rootPackage.scarfSettings && rootPackage.scarfSettings.allowTopLevel
|
||||
}
|
||||
|
||||
function skipTraversal (rootPackage) {
|
||||
return rootPackage && rootPackage.scarfSettings && rootPackage.scarfSettings.skipTraversal
|
||||
}
|
||||
|
||||
function parentIsRoot (dependencyToReport) {
|
||||
const parent = dependencyToReport.parent
|
||||
const rootPackage = dependencyToReport.rootPackage
|
||||
|
||||
return parent && rootPackage && parent.name === rootPackage.name && parent.version === rootPackage.version
|
||||
}
|
||||
|
||||
function isTopLevel (dependencyToReport) {
|
||||
return parentIsRoot(dependencyToReport) && !process.env.npm_config_global
|
||||
}
|
||||
|
||||
function isGlobal (dependencyToReport) {
|
||||
return parentIsRoot(dependencyToReport) && !!process.env.npm_config_global
|
||||
}
|
||||
|
||||
function hashWithDefault (toHash, defaultReturn) {
|
||||
let crypto
|
||||
try {
|
||||
crypto = require('crypto')
|
||||
} catch (err) {
|
||||
logIfVerbose('node crypto module unavailable')
|
||||
}
|
||||
|
||||
if (crypto && toHash) {
|
||||
return crypto.createHash('sha256').update(toHash, 'utf-8').digest('hex')
|
||||
} else {
|
||||
return defaultReturn
|
||||
}
|
||||
}
|
||||
|
||||
// We don't send any paths, hash package names and versions
|
||||
function redactSensitivePackageInfo (dependencyInfo) {
|
||||
if (dependencyInfo.grandparent && dependencyInfo.grandparent.name) {
|
||||
dependencyInfo.grandparent.nameHash = hashWithDefault(dependencyInfo.grandparent.name, privatePackageRewrite)
|
||||
dependencyInfo.grandparent.versionHash = hashWithDefault(dependencyInfo.grandparent.version, privateVersionRewrite)
|
||||
}
|
||||
|
||||
if (dependencyInfo.rootPackage && dependencyInfo.rootPackage.name) {
|
||||
dependencyInfo.rootPackage.nameHash = hashWithDefault(dependencyInfo.rootPackage.name, privatePackageRewrite)
|
||||
dependencyInfo.rootPackage.versionHash = hashWithDefault(dependencyInfo.rootPackage.version, privateVersionRewrite)
|
||||
}
|
||||
|
||||
delete (dependencyInfo.rootPackage.packageJsonPath)
|
||||
delete (dependencyInfo.rootPackage.path)
|
||||
delete (dependencyInfo.rootPackage.name)
|
||||
delete (dependencyInfo.rootPackage.version)
|
||||
delete (dependencyInfo.parent.path)
|
||||
delete (dependencyInfo.scarf.path)
|
||||
if (dependencyInfo.grandparent) {
|
||||
delete (dependencyInfo.grandparent.path)
|
||||
delete (dependencyInfo.grandparent.name)
|
||||
delete (dependencyInfo.grandparent.version)
|
||||
}
|
||||
return dependencyInfo
|
||||
}
|
||||
|
||||
/*
|
||||
Scarf-js is automatically disabled when being run inside of a yarn install.
|
||||
The `npm_execpath` environment variable tells us which package manager is
|
||||
running our install
|
||||
*/
|
||||
function isYarn () {
|
||||
const execPath = module.exports.npmExecPath() || ''
|
||||
return ['yarn', 'yarn.js', 'yarnpkg', 'yarn.cmd', 'yarnpkg.cmd']
|
||||
.some(packageManBinName => execPath.endsWith(packageManBinName))
|
||||
}
|
||||
|
||||
function processDependencyTreeOutput (resolve, reject) {
|
||||
return function (error, stdout, stderr) {
|
||||
if (error && !stdout) {
|
||||
return reject(new Error(`Scarf received an error from npm -ls: ${error} | ${stderr}`))
|
||||
}
|
||||
|
||||
try {
|
||||
const output = JSON.parse(stdout)
|
||||
|
||||
const depsToScarf = findScarfInFullDependencyTree(output).filter(depChain => depChain.length >= 2)
|
||||
if (!depsToScarf.length) {
|
||||
return reject(new Error('No Scarf parent package found'))
|
||||
}
|
||||
const rootPackageDetails = rootPackageDepInfo(output)
|
||||
|
||||
const dependencyInfo = depsToScarf.map(depChain => {
|
||||
return {
|
||||
scarf: depChain[depChain.length - 1],
|
||||
parent: depChain[depChain.length - 2],
|
||||
grandparent: depChain[depChain.length - 3],
|
||||
rootPackage: rootPackageDetails,
|
||||
anyInChainDisabled: depChain.some(dep => {
|
||||
return (dep.scarfSettings || {}).enabled === false
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
dependencyInfo.forEach(d => {
|
||||
d.parent.scarfSettings = Object.assign(makeDefaultSettings(), d.parent.scarfSettings || {})
|
||||
})
|
||||
|
||||
// Here, we find the dependency chain that corresponds to the scarf package we're currently in
|
||||
const dependencyToReport = dependencyInfo.find(dep => (dep.scarf.path === module.exports.dirName())) || dependencyInfo[0]
|
||||
if (!dependencyToReport) {
|
||||
return reject(new Error(`Couldn't find dependency info for path ${module.exports.dirName()}`))
|
||||
}
|
||||
|
||||
// If any intermediate dependency in the chain of deps that leads to scarf
|
||||
// has disabled Scarf, we must respect that setting unless the user overrides it.
|
||||
if (dependencyToReport.anyInChainDisabled && !userHasOptedIn(dependencyToReport.rootPackage)) {
|
||||
return reject(new Error('Scarf has been disabled via a package.json in the dependency chain.'))
|
||||
}
|
||||
|
||||
if (isTopLevel(dependencyToReport) && !isGlobal(dependencyToReport) && !allowTopLevel(rootPackageDetails)) {
|
||||
return reject(new Error('The package depending on Scarf is the root package being installed, but Scarf is not configured to run in this case. To enable it, set `scarfSettings.allowTopLevel = true` in your package.json'))
|
||||
}
|
||||
|
||||
return resolve(dependencyToReport)
|
||||
} catch (err) {
|
||||
logIfVerbose(err, console.error)
|
||||
return reject(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function processGitRevParseOutput (resolve, reject) {
|
||||
return function (error, stdout, stderr) {
|
||||
if (error && !stdout) {
|
||||
return reject(new Error(`Scarf received an error from git rev-parse: ${error} | ${stderr}`))
|
||||
}
|
||||
|
||||
const output = String(stdout).trim()
|
||||
|
||||
if (output.length > 0) {
|
||||
return resolve(output)
|
||||
} else {
|
||||
return reject(new Error('Scarf did not receive usable output from git rev-parse'))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// packageJSONOverride: a test convenience to set a packageJSON explicitly.
|
||||
// Leave empty to use the actual root package.json.
|
||||
async function getDependencyInfo (packageJSONOverride) {
|
||||
try {
|
||||
const rootPackageJSON = require(packageJSONOverride || path.join(rootPath, 'package.json'))
|
||||
const scarfPackageJSON = require(path.join(dirName(), 'package.json'))
|
||||
|
||||
if (skipTraversal(rootPackageJSON)) {
|
||||
logIfVerbose('skipping dependency tree traversal')
|
||||
const rootInfoToReport = {
|
||||
name: rootPackageJSON.name,
|
||||
version: rootPackageJSON.version,
|
||||
scarfSettings: { ...makeDefaultSettings(), ...rootPackageJSON.scarfSettings }
|
||||
}
|
||||
const shallowDepInfo = {
|
||||
scarf: { name: '@scarf/scarf', version: scarfPackageJSON.version },
|
||||
parent: { ...rootInfoToReport },
|
||||
rootPackage: { ...rootInfoToReport },
|
||||
anyInChainDisabled: false,
|
||||
skippedTraversal: true
|
||||
}
|
||||
logIfVerbose(util.inspect(shallowDepInfo))
|
||||
return shallowDepInfo
|
||||
}
|
||||
} catch (err) {
|
||||
logIfVerbose(err, console.error)
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
exec(`cd ${rootPath} && npm ls @scarf/scarf --json --long`, { timeout: execTimeout, maxBuffer: 1024 * 1024 * 1024 }, processDependencyTreeOutput(resolve, reject))
|
||||
})
|
||||
}
|
||||
|
||||
async function getGitShaFromRootPath () {
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
exec(`cd ${rootPath} && git rev-parse HEAD`, { timeout: execTimeout, maxBuffer: 1024 * 1024 * 1024 }, processGitRevParseOutput(resolve, reject))
|
||||
})
|
||||
try {
|
||||
return await promise
|
||||
} catch (e) {
|
||||
logIfVerbose(e)
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
async function reportPostInstall () {
|
||||
const scarfApiToken = process.env.SCARF_API_TOKEN
|
||||
|
||||
const dependencyInfo = await module.exports.getDependencyInfo()
|
||||
logIfVerbose(dependencyInfo)
|
||||
if (!dependencyInfo.parent || !dependencyInfo.parent.name) {
|
||||
return Promise.reject(new Error('No parent found, nothing to report'))
|
||||
}
|
||||
|
||||
if (parentIsRoot(dependencyInfo) && allowTopLevel(dependencyInfo.rootPackage)) {
|
||||
const gitSha = await getGitShaFromRootPath()
|
||||
logIfVerbose(`Injecting sha to parent: ${gitSha}`)
|
||||
dependencyInfo.parent.gitSha = gitSha
|
||||
}
|
||||
|
||||
const rootPackage = dependencyInfo.rootPackage
|
||||
|
||||
if (!userHasOptedIn(rootPackage) && isYarn()) {
|
||||
return Promise.reject(new Error('Package manager is yarn. scarf-js is unable to inform user of analytics. Aborting.'))
|
||||
}
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
if (dependencyInfo.parent.scarfSettings.defaultOptIn) {
|
||||
if (userHasOptedOut(rootPackage)) {
|
||||
return reject(new Error('User has opted out'))
|
||||
}
|
||||
|
||||
if (!userHasOptedIn(rootPackage)) {
|
||||
rateLimitedUserLog(optedInLogRateLimitKey, `
|
||||
The dependency '${dependencyInfo.parent.name}' is tracking installation
|
||||
statistics using scarf-js (https://scarf.sh), which helps open-source developers
|
||||
fund and maintain their projects. Scarf securely logs basic installation
|
||||
details when this package is installed. The Scarf npm library is open source
|
||||
and permissively licensed at https://github.com/scarf-sh/scarf-js. For more
|
||||
details about your project's dependencies, try running 'npm ls'. To opt out of
|
||||
analytics, set the environment variable 'SCARF_ANALYTICS=false'.
|
||||
`)
|
||||
}
|
||||
resolve(dependencyInfo)
|
||||
} else {
|
||||
if (!userHasOptedIn(rootPackage)) {
|
||||
if (!userHasOptedOut(rootPackage)) {
|
||||
// We'll only print the 'please opt in' text if the user hasn't
|
||||
// already opted out, and our logging rate limit hasn't been reached
|
||||
if (hasHitRateLimit(optedOutLogRateLimitKey, getRateLimitedLogHistory())) {
|
||||
return reject(new Error('Analytics are opt-out by default, but rate limit already hit for prompting opt-in.'))
|
||||
}
|
||||
rateLimitedUserLog(optedOutLogRateLimitKey, `
|
||||
The dependency '${dependencyInfo.parent.name}' would like to track
|
||||
installation statistics using scarf-js (https://scarf.sh), which helps
|
||||
open-source developers fund and maintain their projects. Reporting is disabled
|
||||
by default for this package. When enabled, Scarf securely logs basic
|
||||
installation details when this package is installed. The Scarf npm library is
|
||||
open source and permissively licensed at https://github.com/scarf-sh/scarf-js.
|
||||
For more details about your project's dependencies, try running 'npm ls'.
|
||||
`
|
||||
)
|
||||
const stdin = process.stdin
|
||||
stdin.setEncoding('utf-8')
|
||||
|
||||
process.stdout.write(`Would you like to support ${dependencyInfo.parent.name} by sending analytics for this install? (y/N): `)
|
||||
|
||||
const timeout1 = setTimeout(() => {
|
||||
console.log('')
|
||||
console.log('No opt in received, skipping analytics')
|
||||
reject(new Error('Timeout waiting for user opt in'))
|
||||
}, 7000)
|
||||
|
||||
stdin.on('data', async function (data) {
|
||||
clearTimeout(timeout1)
|
||||
const enabled = data.trim().toLowerCase() === 'y'
|
||||
|
||||
const afterUserInput = (enabled, saved) => {
|
||||
if (enabled) {
|
||||
console.log('Thanks for enabling analytics!')
|
||||
}
|
||||
|
||||
if (!saved) {
|
||||
console.log('To prevent this message in the future, you can also set the `SCARF_ANALYTICS=true|false` environment variable')
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
return resolve(dependencyInfo)
|
||||
} else {
|
||||
return reject(new Error('Not enabled via cli'))
|
||||
}
|
||||
}
|
||||
|
||||
process.stdout.write('Save this preference to your project\'s package.json file? (y/N): ')
|
||||
|
||||
setTimeout(() => {
|
||||
console.log('')
|
||||
return afterUserInput(enabled, false)
|
||||
}, 15000)
|
||||
|
||||
stdin.removeAllListeners('data')
|
||||
stdin.on('data', async function (data) {
|
||||
try {
|
||||
const savePreference = data.trim().toLowerCase() === 'y'
|
||||
if (savePreference) {
|
||||
await savePreferencesToRootPackage(dependencyInfo.rootPackage.packageJsonPath, enabled)
|
||||
}
|
||||
return afterUserInput(enabled, savePreference)
|
||||
} catch (err) {
|
||||
logIfVerbose(err, console.error)
|
||||
return reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
} else {
|
||||
resolve(dependencyInfo)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
redactSensitivePackageInfo(dependencyInfo)
|
||||
|
||||
const infoPayload = {
|
||||
libraryType: 'npm',
|
||||
rawPlatform: os.platform(),
|
||||
rawArch: os.arch(),
|
||||
nodeVersion: process.versions.node,
|
||||
dependencyInfo: dependencyInfo
|
||||
}
|
||||
|
||||
const data = JSON.stringify(infoPayload)
|
||||
logIfVerbose(`Scarf payload: ${data}`)
|
||||
|
||||
const reqOptions = {
|
||||
host: scarfHost,
|
||||
port: localDevPort,
|
||||
method: 'POST',
|
||||
path: '/package-event/install',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Content-Length': data.length
|
||||
},
|
||||
timeout: execTimeout
|
||||
}
|
||||
|
||||
if (scarfApiToken) {
|
||||
const authToken = Buffer.from(`n/a:${scarfApiToken}`).toString('base64')
|
||||
reqOptions.headers.Authorization = `Basic ${authToken}`
|
||||
}
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
const req = https.request(reqOptions, (res) => {
|
||||
logIfVerbose(`Response status: ${res.statusCode}`)
|
||||
resolve()
|
||||
})
|
||||
|
||||
req.on('error', error => {
|
||||
logIfVerbose(error, console.error)
|
||||
reject(error)
|
||||
})
|
||||
|
||||
req.on('timeout', error => {
|
||||
logIfVerbose(error, console.error)
|
||||
reject(error)
|
||||
})
|
||||
|
||||
req.write(data)
|
||||
req.end()
|
||||
})
|
||||
}
|
||||
|
||||
// Find all paths to Scarf from the json output of npm ls @scarf/scarf --json in
|
||||
// the root package being installed by the user
|
||||
//
|
||||
// [{
|
||||
// scarf: {name: `@scarf/scarf`, version: '0.0.1'},
|
||||
// parent: { name: 'scarfed-library', version: '1.0.0', scarfSettings: { defaultOptIn: true } },
|
||||
// grandparent: { name: 'scarfed-lib-consumer', version: '1.0.0' }
|
||||
// }]
|
||||
function findScarfInSubDepTree (pathToDep, deps) {
|
||||
const depNames = Object.keys(deps || {})
|
||||
|
||||
if (!depNames) {
|
||||
return []
|
||||
}
|
||||
|
||||
const scarfFound = depNames.find(depName => depName === scarfLibName)
|
||||
const output = []
|
||||
if (scarfFound) {
|
||||
output.push(pathToDep.concat([{ name: scarfLibName, version: deps[scarfLibName].version, path: deps[scarfLibName].path }]))
|
||||
}
|
||||
for (let i = 0; i < depNames.length; i++) {
|
||||
const depName = depNames[i]
|
||||
const newPathToDep = pathToDep.concat([
|
||||
{
|
||||
name: depName,
|
||||
version: deps[depName].version,
|
||||
scarfSettings: deps[depName].scarfSettings,
|
||||
path: deps[depName].path
|
||||
}
|
||||
])
|
||||
const results = findScarfInSubDepTree(newPathToDep, deps[depName].dependencies)
|
||||
if (results) {
|
||||
for (let j = 0; j < results.length; j++) {
|
||||
output.push(results[j])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
function findScarfInFullDependencyTree (tree) {
|
||||
if (tree.name === scarfLibName) {
|
||||
return [[{ name: scarfLibName, version: tree.version }]]
|
||||
} else {
|
||||
return findScarfInSubDepTree([packageDetailsFromDepInfo(tree)], tree.dependencies)
|
||||
}
|
||||
}
|
||||
|
||||
function packageDetailsFromDepInfo (tree) {
|
||||
return {
|
||||
name: tree.name,
|
||||
version: tree.version,
|
||||
scarfSettings: tree.scarfSettings,
|
||||
path: tree.path
|
||||
}
|
||||
}
|
||||
|
||||
function rootPackageDepInfo (packageInfo) {
|
||||
if (process.env.npm_config_global) {
|
||||
packageInfo = Object.values(packageInfo.dependencies)[0]
|
||||
}
|
||||
const info = packageDetailsFromDepInfo(packageInfo)
|
||||
info.packageJsonPath = `${packageInfo.path}/package.json`
|
||||
return info
|
||||
}
|
||||
|
||||
async function savePreferencesToRootPackage (path, optIn) {
|
||||
const packageJsonString = await fsAsync.readFile(path)
|
||||
const parsed = JSON.parse(packageJsonString)
|
||||
parsed.scarfSettings = {
|
||||
enabled: optIn
|
||||
}
|
||||
await fsAsync.writeFile(path, JSON.stringify(parsed, null, 2))
|
||||
}
|
||||
|
||||
/*
|
||||
If Scarf-js appears in many different spots in a package's dependency tree, we
|
||||
want to avoid spamming the user with the same message informing them of
|
||||
Scarf's analytics. Rate limited logs will record timestamps of logging in a
|
||||
temp file. Before logging something to the user, we will verify we're not over
|
||||
the rate limit.
|
||||
*/
|
||||
function rateLimitedUserLog (rateLimitKey, toLog) {
|
||||
const history = getRateLimitedLogHistory()
|
||||
if (!hasHitRateLimit(rateLimitKey, history)) {
|
||||
writeCurrentTimeToLogHistory(rateLimitKey, history)
|
||||
console.log(toLog)
|
||||
} else {
|
||||
logIfVerbose(`[SUPPRESSED USER MESSAGE, RATE LIMIT HIT] ${toLog}`)
|
||||
}
|
||||
}
|
||||
|
||||
function getRateLimitedLogHistory () {
|
||||
let history
|
||||
try {
|
||||
history = JSON.parse(fs.readFileSync(module.exports.tmpFileName()))
|
||||
} catch (e) {
|
||||
logIfVerbose(e)
|
||||
}
|
||||
return history || {}
|
||||
}
|
||||
|
||||
// Current rate limit: 1/minute
|
||||
function hasHitRateLimit (rateLimitKey, history) {
|
||||
if (!history || !history[rateLimitKey]) {
|
||||
return false
|
||||
}
|
||||
|
||||
const lastLog = history[rateLimitKey]
|
||||
return (new Date().getTime() - lastLog) < userMessageThrottleTime
|
||||
}
|
||||
|
||||
function writeCurrentTimeToLogHistory (rateLimitKey, history) {
|
||||
history[rateLimitKey] = new Date().getTime()
|
||||
fs.writeFileSync(module.exports.tmpFileName(), JSON.stringify(history))
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
redactSensitivePackageInfo,
|
||||
hasHitRateLimit,
|
||||
getRateLimitedLogHistory,
|
||||
rateLimitedUserLog,
|
||||
tmpFileName,
|
||||
dirName,
|
||||
processDependencyTreeOutput,
|
||||
processGitRevParseOutput,
|
||||
npmExecPath,
|
||||
getDependencyInfo,
|
||||
getGitShaFromRootPath,
|
||||
reportPostInstall,
|
||||
hashWithDefault,
|
||||
findScarfInFullDependencyTree
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
try {
|
||||
reportPostInstall().catch(e => {
|
||||
// This is an optional, best effort attempt. If there are any errors in
|
||||
// Scarf, we must not interfere with whatever the user is doing
|
||||
logIfVerbose(`\n\n${e}`, console.error)
|
||||
}).finally(() => {
|
||||
process.exit(0)
|
||||
})
|
||||
} catch (e) {
|
||||
logIfVerbose(`\n\nTop level error: ${e}`, console.error)
|
||||
process.exit(0)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue