This commit is contained in:
Garrett Serack 2018-10-03 10:04:34 -07:00
Родитель 62125037c4
Коммит b76c9f82cc
27 изменённых файлов: 2825 добавлений и 0 удалений

5
.gitattributes поставляемый Normal file
Просмотреть файл

@ -0,0 +1,5 @@
# Don't allow people to merge changes to these generated files, because the result
# may be invalid. You need to run "rush update" again.
shrinkwrap.yaml merge=binary
npm-shrinkwrap.json merge=binary
yarn.lock merge=binary

12
common/config/rush/.npmrc Normal file
Просмотреть файл

@ -0,0 +1,12 @@
# Rush uses this file to configure the package registry, regardless of whether the
# package manager is PNPM, NPM, or Yarn. Prior to invoking the package manager,
# Rush will always copy this file to the folder where installation is performed.
# When NPM is the package manager, Rush works around NPM's processing of
# undefined environment variables by deleting any lines that reference undefined
# environment variables.
#
# DO NOT SPECIFY AUTHENTICATION CREDENTIALS IN THIS FILE. It should only be used
# to configure registry sources.
registry=https://registry.npmjs.org/
always-auth=false

Просмотреть файл

@ -0,0 +1,177 @@
/**
* This configuration file defines custom commands for the "rush" command-line.
* For full documentation, please see https://rushjs.io
*/
{
"$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json",
/**
* Custom "commands" introduce new verbs for the command-line. To see the help for these
* example commands, try "rush --help", "rush my-bulk-command --help", or
* "rush my-global-command --help".
*/
"commands": [
// {
// /**
// * (Required) Determines the type of custom command.
// * Rush's "bulk" commands are invoked separately for each project. Rush will look in
// * each project's package.json file for a "scripts" entry whose name matches the
// * command name. By default, the command will run for every project in the repo,
// * according to the dependency graph (similar to how "rush build" works).
// * The set of projects can be restricted e.g. using the "--to" or "--from" parameters.
// */
// "commandKind": "bulk",
//
// /**
// * (Required) The name that will be typed as part of the command line. This is also the name
// * of the "scripts" hook in the project's package.json file.
// * The name should be comprised of lower case words separated by hyphens.
// */
// "name": "my-bulk-command",
//
// /**
// * (Required) A short summary of the custom command to be shown when printing command line
// * help, e.g. "rush --help".
// */
// "summary": "Example bulk custom command",
//
// /**
// * A detailed description of the command to be shown when printing command line
// * help (e.g. "rush --help my-command").
// * If omitted, the "summary" text will be shown instead.
// *
// * Whenever you introduce commands/parameters, taking a little time to write meaningful
// * documentation can make a big difference for the developer experience in your repo.
// */
// "description": "This is an example custom command that runs separately for each project",
//
// /**
// * (Required) If true, then this command is safe to be run in parallel, i.e. executed
// * simultaneously for multiple projects. Similar to "rush build", regardless of parallelism
// * projects will not start processing until their dependencies have completed processing.
// */
// "enableParallelism": false,
//
// /**
// * Normally Rush requires that each project's package.json has a "scripts" entry matching
// * the custom command name. To disable this check, set "ignoreMissingScript" to true;
// * projects with a missing definition will be skipped.
// */
// "ignoreMissingScript": false
// },
//
// {
// /**
// * (Required) Determines the type of custom command.
// * Rush's "global" commands are invoked once for the entire repo.
// */
// "commandKind": "global",
//
// "name": "my-global-command",
// "summary": "Example global custom command",
// "description": "This is an example custom command that runs once for the entire repo",
//
// /**
// * A script that will be invoked using the OS shell. The working directory will be the folder
// * that contains rush.json. If custom parameters are associated with this command, their
// * values will be appended to the end of this string.
// */
// "shellCommand": "node common/scripts/my-global-command.js"
// }
],
/**
* Custom "parameters" introduce new parameters for specified Rush command-line commands.
* For example, you might define a "--production" parameter for the "rush build" command.
*/
"parameters": [
// {
// /**
// * (Required) Determines the type of custom parameter.
// * A "flag" is a custom command-line parameter whose presence acts as an on/off switch.
// */
// "parameterKind": "flag",
//
// /**
// * (Required) The long name of the parameter. It must be lower-case and use dash delimiters.
// */
// "longName": "--my-flag",
//
// /**
// * An optional alternative short name for the parameter. It must be a dash followed by a single
// * lower-case or upper-case letter, which is case-sensitive.
// *
// * NOTE: The Rush developers recommend that automation scripts should always use the long name
// * to improve readability. The short name is only intended as a convenience for humans.
// * The alphabet letters run out quickly, and are difficult to memorize, so *only* use
// * a short name if you expect the parameter to be needed very often in everyday operations.
// */
// "shortName": "-m",
//
// /**
// * (Required) A long description to be shown in the command-line help.
// *
// * Whenever you introduce commands/parameters, taking a little time to write meaningful
// * documentation can make a big difference for the developer experience in your repo.
// */
// "description": "A custom flag parameter that is passed to the scripts that are invoked when building projects",
//
// /**
// * (Required) A list of custom commands and/or built-in Rush commands that this parameter may
// * be used with. The parameter will be appended to the shell command that Rush invokes.
// */
// "associatedCommands": [ "build", "rebuild" ]
// },
//
// {
// /**
// * (Required) Determines the type of custom parameter.
// * A "flag" is a custom command-line parameter whose presence acts as an on/off switch.
// */
// "parameterKind": "choice",
// "longName": "--my-choice",
// "description": "A custom choice parameter for the \"my-global-command\" custom command",
//
// "associatedCommands": [ "my-global-command" ],
//
// /**
// * Normally if a parameter is omitted from the command line, it will not be passed
// * to the shell command. this value will be inserted by default. Whereas if a "defaultValue"
// * is defined, the parameter will always be passed to the shell command, and will use the
// * default value if unspecified. The value must be one of the defined alternatives.
// */
// "defaultValue": "vanilla",
//
// /**
// * (Required) A list of alternative argument values that can be chosen for this parameter.
// */
// "alternatives": [
// {
// /**
// * A token that is one of the alternatives that can be used with the choice parameter,
// * e.g. "vanilla" in "--flavor vanilla".
// */
// "name": "vanilla",
//
// /**
// * A detailed description for the alternative that can be shown in the command-line help.
// *
// * Whenever you introduce commands/parameters, taking a little time to write meaningful
// * documentation can make a big difference for the developer experience in your repo.
// */
// "description": "Use the vanilla flavor (the default)"
// },
//
// {
// "name": "chocolate",
// "description": "Use the chocolate flavor"
// },
//
// {
// "name": "strawberry",
// "description": "Use the strawberry flavor"
// }
// ]
// }
]
}

Просмотреть файл

@ -0,0 +1,43 @@
/**
* This configuration file specifies NPM dependency version selections that affect all projects
* in a Rush repo. For full documentation, please see https://rushjs.io
*/
{
"$schema": "https://developer.microsoft.com/json-schemas/rush/v5/common-versions.schema.json",
/**
* A table that specifies a "preferred version" for a dependency package. The "preferred version"
* is typically used to hold an indirect dependency back to a specific version, however generally
* it can be any SemVer range specifier (e.g. "~1.2.3"), and it will narrow any (compatible)
* SemVer range specifier. See the Rush documentation for details about this feature.
*/
"preferredVersions": {
/**
* When someone asks for "^1.0.0" make sure they get "1.2.3" when working in this repo,
* instead of the latest version.
*/
// "some-library": "1.2.3"
},
/**
* The "rush check" command can be used to enforce that every project in the repo must specify
* the same SemVer range for a given dependency. However, sometimes exceptions are needed.
* The allowedAlternativeVersions table allows you to list other SemVer ranges that will be
* accepted by "rush check" for a given dependency.
*
* IMPORTANT: THIS TABLE IS FOR *ADDITIONAL* VERSION RANGES THAT ARE ALTERNATIVES TO THE
* USUAL VERSION (WHICH IS INFERRED BY LOOKING AT ALL PROJECTS IN THE REPO).
* This design avoids unnecessary churn in this file.
*/
"allowedAlternativeVersions": {
/**
* For example, allow some projects to use an older TypeScript compiler
* (in addition to whatever "usual" version is being used by other projects in the repo):
*/
// "typescript": [
// "~2.4.0"
// ]
}
}

Просмотреть файл

@ -0,0 +1,39 @@
"use strict";
/**
* When using the PNPM package manager, you can use pnpmfile.js to workaround
* dependencies that have mistakes in their package.json file. (This feature is
* functionally similar to Yarn's "resolutions".)
*
* For details, see the PNPM documentation:
* https://pnpm.js.org/docs/en/hooks.html
*
* IMPORTANT: SINCE THIS FILE CONTAINS EXECUTABLE CODE, MODIFYING IT IS LIKELY
* TO INVALIDATE ANY CACHED DEPENDENCY ANALYSIS. We recommend to run "rush update --full"
* after any modification to pnpmfile.js.
*
*/
module.exports = {
hooks: {
readPackage
}
};
/**
* This hook is invoked during installation before a package's dependencies
* are selected.
* The `packageJson` parameter is the deserialized package.json
* contents for the package that is about to be installed.
* The `context` parameter provides a log() function.
* The return value is the updated object.
*/
function readPackage(packageJson, context) {
// // The karma types have a missing dependency on typings from the log4js package.
// if (packageJson.name === '@types/karma') {
// context.log('Fixed up dependencies for @types/karma');
// packageJson.dependencies['log4js'] = '0.6.38';
// }
return packageJson;
}

Просмотреть файл

@ -0,0 +1,690 @@
dependencies:
'@rush-temp/tasks': 'file:projects/tasks.tgz'
'@types/mocha': 5.2.5
'@types/node': 10.11.3
mocha: 5.2.0
mocha-typescript: 1.1.17
source-map-support: 0.5.9
typescript: 3.1.1
packages:
/@types/mocha/5.2.5:
dev: false
resolution:
integrity: sha512-lAVp+Kj54ui/vLUFxsJTMtWvZraZxum3w3Nwkble2dNuV5VnPA+Mi2oGX9XYJAaIvZi3tn3cbjS/qcJXRb6Bww==
/@types/node/10.11.3:
dev: false
resolution:
integrity: sha512-3AvcEJAh9EMatxs+OxAlvAEs7OTy6AG94mcH1iqyVDwVVndekLxzwkWQ/Z4SDbY6GO2oyUXyWW8tQ4rENSSQVQ==
/ansi-regex/2.1.1:
dev: false
engines:
node: '>=0.10.0'
resolution:
integrity: sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
/ansi-regex/3.0.0:
dev: false
engines:
node: '>=4'
resolution:
integrity: sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
/ansi-styles/3.2.1:
dependencies:
color-convert: 1.9.3
dev: false
engines:
node: '>=4'
resolution:
integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
/balanced-match/1.0.0:
dev: false
resolution:
integrity: sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
/brace-expansion/1.1.11:
dependencies:
balanced-match: 1.0.0
concat-map: 0.0.1
dev: false
resolution:
integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
/browser-stdout/1.3.1:
dev: false
resolution:
integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==
/buffer-from/1.1.1:
dev: false
resolution:
integrity: sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
/camelcase/4.1.0:
dev: false
engines:
node: '>=4'
resolution:
integrity: sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=
/chalk/2.4.1:
dependencies:
ansi-styles: 3.2.1
escape-string-regexp: 1.0.5
supports-color: 5.5.0
dev: false
engines:
node: '>=4'
resolution:
integrity: sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==
/cliui/4.1.0:
dependencies:
string-width: 2.1.1
strip-ansi: 4.0.0
wrap-ansi: 2.1.0
dev: false
resolution:
integrity: sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==
/code-point-at/1.1.0:
dev: false
engines:
node: '>=0.10.0'
resolution:
integrity: sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
/color-convert/1.9.3:
dependencies:
color-name: 1.1.3
dev: false
resolution:
integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
/color-name/1.1.3:
dev: false
resolution:
integrity: sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
/commander/2.15.1:
dev: false
resolution:
integrity: sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==
tarball: 'http://registry.npmjs.org/commander/-/commander-2.15.1.tgz'
/concat-map/0.0.1:
dev: false
resolution:
integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
/cross-spawn/5.1.0:
dependencies:
lru-cache: 4.1.3
shebang-command: 1.2.0
which: 1.3.1
dev: false
resolution:
integrity: sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=
/cross-spawn/6.0.5:
dependencies:
nice-try: 1.0.5
path-key: 2.0.1
semver: 5.5.1
shebang-command: 1.2.0
which: 1.3.1
dev: false
engines:
node: '>=4.8'
resolution:
integrity: sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
/debug/3.1.0:
dependencies:
ms: 2.0.0
dev: false
resolution:
integrity: sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
/decamelize/1.2.0:
dev: false
engines:
node: '>=0.10.0'
resolution:
integrity: sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
/diff/3.5.0:
dev: false
engines:
node: '>=0.3.1'
resolution:
integrity: sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
/es6-object-assign/1.1.0:
dev: false
resolution:
integrity: sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=
/escape-string-regexp/1.0.5:
dev: false
engines:
node: '>=0.8.0'
resolution:
integrity: sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
/execa/0.7.0:
dependencies:
cross-spawn: 5.1.0
get-stream: 3.0.0
is-stream: 1.1.0
npm-run-path: 2.0.2
p-finally: 1.0.0
signal-exit: 3.0.2
strip-eof: 1.0.0
dev: false
engines:
node: '>=4'
resolution:
integrity: sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=
/find-up/2.1.0:
dependencies:
locate-path: 2.0.0
dev: false
engines:
node: '>=4'
resolution:
integrity: sha1-RdG35QbHF93UgndaK3eSCjwMV6c=
/fs.realpath/1.0.0:
dev: false
resolution:
integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
/get-caller-file/1.0.3:
dev: false
resolution:
integrity: sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==
/get-stream/3.0.0:
dev: false
engines:
node: '>=4'
resolution:
integrity: sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=
tarball: 'http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz'
/glob/7.1.2:
dependencies:
fs.realpath: 1.0.0
inflight: 1.0.6
inherits: 2.0.3
minimatch: 3.0.4
once: 1.4.0
path-is-absolute: 1.0.1
dev: false
resolution:
integrity: sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==
/glob/7.1.3:
dependencies:
fs.realpath: 1.0.0
inflight: 1.0.6
inherits: 2.0.3
minimatch: 3.0.4
once: 1.4.0
path-is-absolute: 1.0.1
dev: false
resolution:
integrity: sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==
/growl/1.10.5:
dev: false
engines:
node: '>=4.x'
resolution:
integrity: sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==
/has-flag/3.0.0:
dev: false
engines:
node: '>=4'
resolution:
integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
/he/1.1.1:
dev: false
hasBin: true
resolution:
integrity: sha1-k0EP0hsAlzUVH4howvJx80J+I/0=
/inflight/1.0.6:
dependencies:
once: 1.4.0
wrappy: 1.0.2
dev: false
resolution:
integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
/inherits/2.0.3:
dev: false
resolution:
integrity: sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
/interpret/1.1.0:
dev: false
resolution:
integrity: sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=
/invert-kv/1.0.0:
dev: false
engines:
node: '>=0.10.0'
resolution:
integrity: sha1-EEqOSqym09jNFXqO+L+rLXo//bY=
/is-fullwidth-code-point/1.0.0:
dependencies:
number-is-nan: 1.0.1
dev: false
engines:
node: '>=0.10.0'
resolution:
integrity: sha1-754xOG8DGn8NZDr4L95QxFfvAMs=
/is-fullwidth-code-point/2.0.0:
dev: false
engines:
node: '>=4'
resolution:
integrity: sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
/is-stream/1.1.0:
dev: false
engines:
node: '>=0.10.0'
resolution:
integrity: sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
/isexe/2.0.0:
dev: false
resolution:
integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
/lcid/1.0.0:
dependencies:
invert-kv: 1.0.0
dev: false
engines:
node: '>=0.10.0'
resolution:
integrity: sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=
/locate-path/2.0.0:
dependencies:
p-locate: 2.0.0
path-exists: 3.0.0
dev: false
engines:
node: '>=4'
resolution:
integrity: sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=
/lru-cache/4.1.3:
dependencies:
pseudomap: 1.0.2
yallist: 2.1.2
dev: false
resolution:
integrity: sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==
/mem/1.1.0:
dependencies:
mimic-fn: 1.2.0
dev: false
engines:
node: '>=4'
resolution:
integrity: sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=
/mimic-fn/1.2.0:
dev: false
engines:
node: '>=4'
resolution:
integrity: sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==
/minimatch/3.0.4:
dependencies:
brace-expansion: 1.1.11
dev: false
resolution:
integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
/minimist/0.0.8:
dev: false
resolution:
integrity: sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
tarball: 'http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz'
/minimist/1.2.0:
dev: false
resolution:
integrity: sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
tarball: 'http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz'
/mkdirp/0.5.1:
dependencies:
minimist: 0.0.8
dev: false
hasBin: true
resolution:
integrity: sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
tarball: 'http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz'
/mocha-typescript/1.1.17:
dependencies:
'@types/mocha': 5.2.5
chalk: 2.4.1
cross-spawn: 6.0.5
yargs: 11.1.0
dev: false
hasBin: true
resolution:
integrity: sha512-Ge6pCQkZumkkhxVNdAf3JxunskShgaynCb30HYD7TT1Yhog/7NW2+6w5RcRHI+nuQrCMTX6z1+qf2pD8qwCoQA==
/mocha/5.2.0:
dependencies:
browser-stdout: 1.3.1
commander: 2.15.1
debug: 3.1.0
diff: 3.5.0
escape-string-regexp: 1.0.5
glob: 7.1.2
growl: 1.10.5
he: 1.1.1
minimatch: 3.0.4
mkdirp: 0.5.1
supports-color: 5.4.0
dev: false
engines:
node: '>= 4.0.0'
hasBin: true
resolution:
integrity: sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==
/ms/2.0.0:
dev: false
resolution:
integrity: sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
/nice-try/1.0.5:
dev: false
resolution:
integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
/npm-run-path/2.0.2:
dependencies:
path-key: 2.0.1
dev: false
engines:
node: '>=4'
resolution:
integrity: sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=
/number-is-nan/1.0.1:
dev: false
engines:
node: '>=0.10.0'
resolution:
integrity: sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
/once/1.4.0:
dependencies:
wrappy: 1.0.2
dev: false
resolution:
integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
/os-locale/2.1.0:
dependencies:
execa: 0.7.0
lcid: 1.0.0
mem: 1.1.0
dev: false
engines:
node: '>=4'
resolution:
integrity: sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==
/p-finally/1.0.0:
dev: false
engines:
node: '>=4'
resolution:
integrity: sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
/p-limit/1.3.0:
dependencies:
p-try: 1.0.0
dev: false
engines:
node: '>=4'
resolution:
integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==
/p-locate/2.0.0:
dependencies:
p-limit: 1.3.0
dev: false
engines:
node: '>=4'
resolution:
integrity: sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=
/p-try/1.0.0:
dev: false
engines:
node: '>=4'
resolution:
integrity: sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=
/path-exists/3.0.0:
dev: false
engines:
node: '>=4'
resolution:
integrity: sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=
/path-is-absolute/1.0.1:
dev: false
engines:
node: '>=0.10.0'
resolution:
integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
/path-key/2.0.1:
dev: false
engines:
node: '>=4'
resolution:
integrity: sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
/path-parse/1.0.6:
dev: false
resolution:
integrity: sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
/pseudomap/1.0.2:
dev: false
resolution:
integrity: sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
/rechoir/0.6.2:
dependencies:
resolve: 1.8.1
dev: false
engines:
node: '>= 0.10'
resolution:
integrity: sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=
/require-directory/2.1.1:
dev: false
engines:
node: '>=0.10.0'
resolution:
integrity: sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
/require-main-filename/1.0.1:
dev: false
resolution:
integrity: sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=
/resolve/1.8.1:
dependencies:
path-parse: 1.0.6
dev: false
resolution:
integrity: sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==
/semver/5.5.1:
dev: false
hasBin: true
resolution:
integrity: sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==
/set-blocking/2.0.0:
dev: false
resolution:
integrity: sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
/shebang-command/1.2.0:
dependencies:
shebang-regex: 1.0.0
dev: false
engines:
node: '>=0.10.0'
resolution:
integrity: sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=
/shebang-regex/1.0.0:
dev: false
engines:
node: '>=0.10.0'
resolution:
integrity: sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
/shelljs/0.7.8:
dependencies:
glob: 7.1.3
interpret: 1.1.0
rechoir: 0.6.2
dev: false
engines:
node: '>=0.11.0'
hasBin: true
resolution:
integrity: sha1-3svPh0sNHl+3LhSxZKloMEjprLM=
/shx/0.2.2:
dependencies:
es6-object-assign: 1.1.0
minimist: 1.2.0
shelljs: 0.7.8
dev: false
hasBin: true
resolution:
integrity: sha1-CjBNAgsO3xMGrYFXDoDwNG31ijk=
/signal-exit/3.0.2:
dev: false
resolution:
integrity: sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
/source-map-support/0.5.9:
dependencies:
buffer-from: 1.1.1
source-map: 0.6.1
dev: false
resolution:
integrity: sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==
/source-map/0.6.1:
dev: false
engines:
node: '>=0.10.0'
resolution:
integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
/string-width/1.0.2:
dependencies:
code-point-at: 1.1.0
is-fullwidth-code-point: 1.0.0
strip-ansi: 3.0.1
dev: false
engines:
node: '>=0.10.0'
resolution:
integrity: sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
/string-width/2.1.1:
dependencies:
is-fullwidth-code-point: 2.0.0
strip-ansi: 4.0.0
dev: false
engines:
node: '>=4'
resolution:
integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
/strip-ansi/3.0.1:
dependencies:
ansi-regex: 2.1.1
dev: false
engines:
node: '>=0.10.0'
resolution:
integrity: sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
tarball: 'http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz'
/strip-ansi/4.0.0:
dependencies:
ansi-regex: 3.0.0
dev: false
engines:
node: '>=4'
resolution:
integrity: sha1-qEeQIusaw2iocTibY1JixQXuNo8=
/strip-eof/1.0.0:
dev: false
engines:
node: '>=0.10.0'
resolution:
integrity: sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
/supports-color/5.4.0:
dependencies:
has-flag: 3.0.0
dev: false
engines:
node: '>=4'
resolution:
integrity: sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==
/supports-color/5.5.0:
dependencies:
has-flag: 3.0.0
dev: false
engines:
node: '>=4'
resolution:
integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
/typescript/3.1.1:
dev: false
engines:
node: '>=4.2.0'
hasBin: true
resolution:
integrity: sha512-Veu0w4dTc/9wlWNf2jeRInNodKlcdLgemvPsrNpfu5Pq39sgfFjvIIgTsvUHCoLBnMhPoUA+tFxsXjU6VexVRQ==
/which-module/2.0.0:
dev: false
resolution:
integrity: sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
/which/1.3.1:
dependencies:
isexe: 2.0.0
dev: false
hasBin: true
resolution:
integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
/wrap-ansi/2.1.0:
dependencies:
string-width: 1.0.2
strip-ansi: 3.0.1
dev: false
engines:
node: '>=0.10.0'
resolution:
integrity: sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=
tarball: 'http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz'
/wrappy/1.0.2:
dev: false
resolution:
integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
/y18n/3.2.1:
dev: false
resolution:
integrity: sha1-bRX7qITAhnnA136I53WegR4H+kE=
/yallist/2.1.2:
dev: false
resolution:
integrity: sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
/yargs-parser/9.0.2:
dependencies:
camelcase: 4.1.0
dev: false
resolution:
integrity: sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=
/yargs/11.1.0:
dependencies:
cliui: 4.1.0
decamelize: 1.2.0
find-up: 2.1.0
get-caller-file: 1.0.3
os-locale: 2.1.0
require-directory: 2.1.1
require-main-filename: 1.0.1
set-blocking: 2.0.0
string-width: 2.1.1
which-module: 2.0.0
y18n: 3.2.1
yargs-parser: 9.0.2
dev: false
resolution:
integrity: sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==
tarball: 'http://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz'
'file:projects/tasks.tgz':
dependencies:
'@types/mocha': 5.2.5
'@types/node': 10.11.3
mocha: 5.2.0
mocha-typescript: 1.1.17
semver: 5.5.1
shx: 0.2.2
source-map-support: 0.5.9
typescript: 3.1.1
dev: false
name: '@rush-temp/tasks'
resolution:
integrity: sha512-g9hzjCvZjH9YxJc/75moXJAgS4jhT9SWmfh7VRdNeLz8glSBwYAnGO8O+UcYOuRNuoClz1ts+YvpUXYA7anN5A==
tarball: 'file:projects/tasks.tgz'
version: 0.0.0
registry: 'https://registry.npmjs.org/'
shrinkwrapMinorVersion: 9
shrinkwrapVersion: 3
specifiers:
'@rush-temp/tasks': 'file:./projects/tasks.tgz'
'@types/mocha': 5.2.5
'@types/node': 10.11.3
mocha: 5.2.0
mocha-typescript: 1.1.17
source-map-support: 0.5.9
typescript: ^3.1.1

Просмотреть файл

@ -0,0 +1,81 @@
/**
* This is configuration file is used for advanced publishing configurations with Rush.
* For full documentation, please see https://rushjs.io
*/
/**
* A list of version policy definitions. A "version policy" is a custom package versioning
* strategy that affets "rush change", "rush version", and "rush publish". The strategy applies
* to a set of projects that are specified using the "versionPolicyName" field in rush.json.
*/
[
// {
// /**
// * (Required) Indicates the kind of version policy being defined ("lockStepVersion" or "individualVersion").
// *
// * The "lockStepVersion" mode specifies that the projects will use "lock-step versioning". This
// * strategy is appropriate for a set of packages that act as selectable components of a
// * unified product. The entire set of packages are always published together, and always share
// * the same NPM version number. When the packages depend on other packages in the set, the
// * SemVer range is usually restricted to a single version.
// */
// "definitionName": "lockStepVersion",
//
// /**
// * (Required) The name that will be used for the "versionPolicyName" field in rush.json.
// * This name is also used command-line parameters such as "--version-policy"
// * and "--to-version-policy".
// */
// "policyName": "MyBigFramework",
//
// /**
// * (Required) The current version. All packages belonging to the set should have this version
// * in the current branch. When bumping versions, Rush uses this to determine the next version.
// * (The "version" field in package.json is NOT considered.)
// */
// "version": "1.0.0",
//
// /**
// * (Required) The type of bump that will be performed when publishing the next release.
// * When creating a release branch in Git, this field should be updated according to the
// * type of release.
// *
// * Valid values are: "prerelease", "release", "minor", "patch", "major"
// */
// "nextBump": "prerelease",
//
// /**
// * (Optional) If specified, all packages in the set share a common CHANGELOG.md file.
// * This file is stored with the specified "main" project, which must be a member of the set.
// *
// * If this field is omitted, then a separate CHANGELOG.md file will be maintained for each
// * package in the set.
// */
// "mainProject": "my-app"
// },
//
// {
// /**
// * (Required) Indicates the kind of version policy being defined ("lockStepVersion" or "individualVersion").
// *
// * The "individualVersion" mode specifies that the projects will use "individual versioning".
// * This is the typical NPM model where each package has an independent version number
// * and CHANGELOG.md file. Although a single CI definition is responsible for publishing the
// * packages, they otherwise don't have any special relationship. The version bumping will
// * depend on how developers answer the "rush change" questions for each package that
// * is changed.
// */
// "definitionName": "individualVersion",
//
// "policyName": "MyRandomLibraries",
//
// /**
// * (Optional) This can be used to enforce that all packages in the set must share a common
// * major version number, e.g. because they are from the same major release branch.
// * It can also be used to discourage people from accidentally making "MAJOR" SemVer changes
// * inappropriately. The minor/patch version parts will be bumped independently according
// * to the types of changes made to each project, according to the "rush change" command.
// */
// "lockedMajor": 3
// }
]

Просмотреть файл

@ -0,0 +1,51 @@
"use strict";
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See the @microsoft/rush package's LICENSE file for license information.
Object.defineProperty(exports, "__esModule", { value: true });
// THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED.
//
// This script is intended for usage in an automated build environment where the Rush command may not have
// been preinstalled, or may have an unpredictable version. This script will automatically install the version of Rush
// specified in the rush.json configuration file (if not already installed), and then pass a command-line to it.
// An example usage would be:
//
// node common/scripts/install-run-rush.js install
//
// For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/
const path = require("path");
const fs = require("fs");
const install_run_1 = require("./install-run");
const PACKAGE_NAME = '@microsoft/rush';
function getRushVersion() {
const rushJsonFolder = install_run_1.findRushJsonFolder();
const rushJsonPath = path.join(rushJsonFolder, install_run_1.RUSH_JSON_FILENAME);
try {
const rushJsonContents = fs.readFileSync(rushJsonPath, 'utf-8');
// Use a regular expression to parse out the rushVersion value because rush.json supports comments,
// but JSON.parse does not and we don't want to pull in more dependencies than we need to in this script.
const rushJsonMatches = rushJsonContents.match(/\"rushVersion\"\s*\:\s*\"([0-9a-zA-Z.+\-]+)\"/);
return rushJsonMatches[1];
}
catch (e) {
throw new Error(`Unable to determine the required version of Rush from rush.json (${rushJsonFolder}). ` +
'The \'rushVersion\' field is either not assigned in rush.json or was specified ' +
'using an unexpected syntax.');
}
}
function run() {
const [nodePath, /* Ex: /bin/node */ // tslint:disable-line:no-unused-variable
scriptPath, /* /repo/common/scripts/install-run-rush.js */ // tslint:disable-line:no-unused-variable
...packageBinArgs /* [build, --to, myproject] */] = process.argv;
if (process.argv.length < 3) {
console.log('Usage: install-run-rush.js <command> [args...]');
console.log('Example: install-run-rush.js build --to myproject');
process.exit(1);
}
install_run_1.runWithErrorAndStatusCode(() => {
const version = getRushVersion();
console.log(`The rush.json configuration requests Rush version ${version}`);
return install_run_1.installAndRun(PACKAGE_NAME, version, 'rush', packageBinArgs);
});
}
run();
//# sourceMappingURL=install-run-rush.js.map

Просмотреть файл

@ -0,0 +1,397 @@
"use strict";
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See the @microsoft/rush package's LICENSE file for license information.
Object.defineProperty(exports, "__esModule", { value: true });
// THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED.
//
// This script is intended for usage in an automated build environment where a Node tool may not have
// been preinstalled, or may have an unpredictable version. This script will automatically install the specified
// version of the specified tool (if not already installed), and then pass a command-line to it.
// An example usage would be:
//
// node common/scripts/install-run.js rimraf@2.6.2 rimraf -f project1/lib
//
// For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/
const childProcess = require("child_process");
const fs = require("fs");
const os = require("os");
const path = require("path");
exports.RUSH_JSON_FILENAME = 'rush.json';
const INSTALLED_FLAG_FILENAME = 'installed.flag';
const NODE_MODULES_FOLDER_NAME = 'node_modules';
const PACKAGE_JSON_FILENAME = 'package.json';
/**
* Parse a package specifier (in the form of name\@version) into name and version parts.
*/
function parsePackageSpecifier(rawPackageSpecifier) {
rawPackageSpecifier = (rawPackageSpecifier || '').trim();
const separatorIndex = rawPackageSpecifier.lastIndexOf('@');
let name;
let version = undefined;
if (separatorIndex === 0) {
// The specifier starts with a scope and doesn't have a version specified
name = rawPackageSpecifier;
}
else if (separatorIndex === -1) {
// The specifier doesn't have a version
name = rawPackageSpecifier;
}
else {
name = rawPackageSpecifier.substring(0, separatorIndex);
version = rawPackageSpecifier.substring(separatorIndex + 1);
}
if (!name) {
throw new Error(`Invalid package specifier: ${rawPackageSpecifier}`);
}
return { name, version };
}
/**
* Resolve a package specifier to a static version
*/
function resolvePackageVersion(rushCommonFolder, { name, version }) {
if (!version) {
version = '*'; // If no version is specified, use the latest version
}
if (version.match(/^[a-zA-Z0-9\-\+\.]+$/)) {
// If the version contains only characters that we recognize to be used in static version specifiers,
// pass the version through
return version;
}
else {
// version resolves to
try {
const rushTempFolder = ensureAndJoinPath(rushCommonFolder, 'temp');
const sourceNpmrcFolder = path.join(rushCommonFolder, 'config', 'rush');
syncNpmrc(sourceNpmrcFolder, rushTempFolder);
const npmPath = getNpmPath();
// This returns something that looks like:
// @microsoft/rush@3.0.0 '3.0.0'
// @microsoft/rush@3.0.1 '3.0.1'
// ...
// @microsoft/rush@3.0.20 '3.0.20'
// <blank line>
const npmVersionSpawnResult = childProcess.spawnSync(npmPath, ['view', `${name}@${version}`, 'version', '--no-update-notifier'], {
cwd: rushTempFolder,
stdio: []
});
if (npmVersionSpawnResult.status !== 0) {
throw new Error(`"npm view" returned error code ${npmVersionSpawnResult.status}`);
}
const npmViewVersionOutput = npmVersionSpawnResult.stdout.toString();
const versionLines = npmViewVersionOutput.split('\n').filter((line) => !!line);
const latestVersion = versionLines[versionLines.length - 1];
if (!latestVersion) {
throw new Error('No versions found for the specified version range.');
}
const versionMatches = latestVersion.match(/^.+\s\'(.+)\'$/);
if (!versionMatches) {
throw new Error(`Invalid npm output ${latestVersion}`);
}
return versionMatches[1];
}
catch (e) {
throw new Error(`Unable to resolve version ${version} of package ${name}: ${e}`);
}
}
}
let _npmPath = undefined;
/**
* Get the absolute path to the npm executable
*/
function getNpmPath() {
if (!_npmPath) {
try {
if (os.platform() === 'win32') {
// We're on Windows
const whereOutput = childProcess.execSync('where npm', { stdio: [] }).toString();
const lines = whereOutput.split(os.EOL).filter((line) => !!line);
// take the last result, we are looking for a .cmd command
// see https://github.com/Microsoft/web-build-tools/issues/759
_npmPath = lines[lines.length - 1];
}
else {
// We aren't on Windows - assume we're on *NIX or Darwin
_npmPath = childProcess.execSync('which npm', { stdio: [] }).toString();
}
}
catch (e) {
throw new Error(`Unable to determine the path to the NPM tool: ${e}`);
}
_npmPath = _npmPath.trim();
if (!fs.existsSync(_npmPath)) {
throw new Error('The NPM executable does not exist');
}
}
return _npmPath;
}
exports.getNpmPath = getNpmPath;
let _rushJsonFolder;
/**
* Find the absolute path to the folder containing rush.json
*/
function findRushJsonFolder() {
if (!_rushJsonFolder) {
let basePath = __dirname;
let tempPath = __dirname;
do {
const testRushJsonPath = path.join(basePath, exports.RUSH_JSON_FILENAME);
if (fs.existsSync(testRushJsonPath)) {
_rushJsonFolder = basePath;
break;
}
else {
basePath = tempPath;
}
} while (basePath !== (tempPath = path.dirname(basePath))); // Exit the loop when we hit the disk root
if (!_rushJsonFolder) {
throw new Error('Unable to find rush.json.');
}
}
return _rushJsonFolder;
}
exports.findRushJsonFolder = findRushJsonFolder;
/**
* Create missing directories under the specified base directory, and return the resolved directory.
*
* Does not support "." or ".." path segments.
* Assumes the baseFolder exists.
*/
function ensureAndJoinPath(baseFolder, ...pathSegments) {
let joinedPath = baseFolder;
try {
for (let pathSegment of pathSegments) {
pathSegment = pathSegment.replace(/[\\\/]/g, '+');
joinedPath = path.join(joinedPath, pathSegment);
if (!fs.existsSync(joinedPath)) {
fs.mkdirSync(joinedPath);
}
}
}
catch (e) {
throw new Error(`Error building local installation folder (${path.join(baseFolder, ...pathSegments)}): ${e}`);
}
return joinedPath;
}
/**
* As a workaround, _syncNpmrc() copies the .npmrc file to the target folder, and also trims
* unusable lines from the .npmrc file. If the source .npmrc file not exist, then _syncNpmrc()
* will delete an .npmrc that is found in the target folder.
*
* Why are we trimming the .npmrc lines? NPM allows environment variables to be specified in
* the .npmrc file to provide different authentication tokens for different registry.
* However, if the environment variable is undefined, it expands to an empty string, which
* produces a valid-looking mapping with an invalid URL that causes an error. Instead,
* we'd prefer to skip that line and continue looking in other places such as the user's
* home directory.
*
* IMPORTANT: THIS CODE SHOULD BE KEPT UP TO DATE WITH Utilities._syncNpmrc()
*/
function syncNpmrc(sourceNpmrcFolder, targetNpmrcFolder) {
const sourceNpmrcPath = path.join(sourceNpmrcFolder, '.npmrc');
const targetNpmrcPath = path.join(targetNpmrcFolder, '.npmrc');
try {
if (fs.existsSync(sourceNpmrcPath)) {
let npmrcFileLines = fs.readFileSync(sourceNpmrcPath).toString().split('\n');
npmrcFileLines = npmrcFileLines.map((line) => (line || '').trim());
const resultLines = [];
// Trim out lines that reference environment variables that aren't defined
for (const line of npmrcFileLines) {
// This finds environment variable tokens that look like "${VAR_NAME}"
const regex = /\$\{([^\}]+)\}/g;
const environmentVariables = line.match(regex);
let lineShouldBeTrimmed = false;
if (environmentVariables) {
for (const token of environmentVariables) {
// Remove the leading "${" and the trailing "}" from the token
const environmentVariableName = token.substring(2, token.length - 1);
if (!process.env[environmentVariableName]) {
lineShouldBeTrimmed = true;
break;
}
}
}
if (lineShouldBeTrimmed) {
// Example output:
// "; MISSING ENVIRONMENT VARIABLE: //my-registry.com/npm/:_authToken=${MY_AUTH_TOKEN}"
resultLines.push('; MISSING ENVIRONMENT VARIABLE: ' + line);
}
else {
resultLines.push(line);
}
}
fs.writeFileSync(targetNpmrcPath, resultLines.join(os.EOL));
}
else if (fs.existsSync(targetNpmrcPath)) {
// If the source .npmrc doesn't exist and there is one in the target, delete the one in the target
fs.unlinkSync(targetNpmrcPath);
}
}
catch (e) {
throw new Error(`Error syncing .npmrc file: ${e}`);
}
}
/**
* Detects if the package in the specified directory is installed
*/
function isPackageAlreadyInstalled(packageInstallFolder) {
try {
const flagFilePath = path.join(packageInstallFolder, INSTALLED_FLAG_FILENAME);
if (!fs.existsSync(flagFilePath)) {
return false;
}
const fileContents = fs.readFileSync(flagFilePath).toString();
return fileContents.trim() === process.version;
}
catch (e) {
return false;
}
}
/**
* Removes the following files and directories under the specified folder path:
* - installed.flag
* -
* - node_modules
*/
function cleanInstallFolder(rushCommonFolder, packageInstallFolder) {
try {
const flagFile = path.resolve(packageInstallFolder, INSTALLED_FLAG_FILENAME);
if (fs.existsSync(flagFile)) {
fs.unlinkSync(flagFile);
}
const packageLockFile = path.resolve(packageInstallFolder, 'package-lock.json');
if (fs.existsSync(packageLockFile)) {
fs.unlinkSync(packageLockFile);
}
const nodeModulesFolder = path.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME);
if (fs.existsSync(nodeModulesFolder)) {
const rushRecyclerFolder = ensureAndJoinPath(rushCommonFolder, 'temp', 'rush-recycler', `install-run-${Date.now().toString()}`);
fs.renameSync(nodeModulesFolder, rushRecyclerFolder);
}
}
catch (e) {
throw new Error(`Error cleaning the package install folder (${packageInstallFolder}): ${e}`);
}
}
function createPackageJson(packageInstallFolder, name, version) {
try {
const packageJsonContents = {
'name': 'ci-rush',
'version': '0.0.0',
'dependencies': {
[name]: version
},
'description': 'DON\'T WARN',
'repository': 'DON\'T WARN',
'license': 'MIT'
};
const packageJsonPath = path.join(packageInstallFolder, PACKAGE_JSON_FILENAME);
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJsonContents, undefined, 2));
}
catch (e) {
throw new Error(`Unable to create package.json: ${e}`);
}
}
/**
* Run "npm install" in the package install folder.
*/
function installPackage(packageInstallFolder, name, version) {
try {
console.log(`Installing ${name}...`);
const npmPath = getNpmPath();
const result = childProcess.spawnSync(npmPath, ['install'], {
stdio: 'inherit',
cwd: packageInstallFolder,
env: process.env
});
if (result.status !== 0) {
throw new Error('"npm install" encountered an error');
}
console.log(`Successfully installed ${name}@${version}`);
}
catch (e) {
throw new Error(`Unable to install package: ${e}`);
}
}
/**
* Get the ".bin" path for the package.
*/
function getBinPath(packageInstallFolder, binName) {
const binFolderPath = path.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME, '.bin');
const resolvedBinName = (os.platform() === 'win32') ? `${binName}.cmd` : binName;
return path.resolve(binFolderPath, resolvedBinName);
}
/**
* Write a flag file to the package's install directory, signifying that the install was successful.
*/
function writeFlagFile(packageInstallFolder) {
try {
const flagFilePath = path.join(packageInstallFolder, INSTALLED_FLAG_FILENAME);
fs.writeFileSync(flagFilePath, process.version);
}
catch (e) {
throw new Error(`Unable to create installed.flag file in ${packageInstallFolder}`);
}
}
function installAndRun(packageName, packageVersion, packageBinName, packageBinArgs) {
const rushJsonFolder = findRushJsonFolder();
const rushCommonFolder = path.join(rushJsonFolder, 'common');
const packageInstallFolder = ensureAndJoinPath(rushCommonFolder, 'temp', 'install-run', `${packageName}@${packageVersion}`);
if (!isPackageAlreadyInstalled(packageInstallFolder)) {
// The package isn't already installed
cleanInstallFolder(rushCommonFolder, packageInstallFolder);
const sourceNpmrcFolder = path.join(rushCommonFolder, 'config', 'rush');
syncNpmrc(sourceNpmrcFolder, packageInstallFolder);
createPackageJson(packageInstallFolder, packageName, packageVersion);
installPackage(packageInstallFolder, packageName, packageVersion);
writeFlagFile(packageInstallFolder);
}
const statusMessage = `Invoking "${packageBinName} ${packageBinArgs.join(' ')}"`;
const statusMessageLine = new Array(statusMessage.length + 1).join('-');
console.log(os.EOL + statusMessage + os.EOL + statusMessageLine + os.EOL);
const binPath = getBinPath(packageInstallFolder, packageBinName);
const result = childProcess.spawnSync(binPath, packageBinArgs, {
stdio: 'inherit',
cwd: process.cwd(),
env: process.env
});
return result.status;
}
exports.installAndRun = installAndRun;
function runWithErrorAndStatusCode(fn) {
process.exitCode = 1;
try {
const exitCode = fn();
process.exitCode = exitCode;
}
catch (e) {
console.error(os.EOL + os.EOL + e.toString() + os.EOL + os.EOL);
}
}
exports.runWithErrorAndStatusCode = runWithErrorAndStatusCode;
function run() {
const [nodePath, /* Ex: /bin/node */ // tslint:disable-line:no-unused-variable
scriptPath, /* /repo/common/scripts/install-run-rush.js */ rawPackageSpecifier, /* rimraf@^2.0.0 */ packageBinName, /* rimraf */ ...packageBinArgs /* [-f, myproject/lib] */] = process.argv;
if (path.basename(scriptPath).toLowerCase() !== 'install-run.js') {
// If install-run.js wasn't directly invoked, don't execute the rest of this function. Return control
// to the script that (presumably) imported this file
return;
}
if (process.argv.length < 4) {
console.log('Usage: install-run.js <package>@<version> <command> [args...]');
console.log('Example: install-run.js rimraf@2.6.2 rimraf -f project1/lib');
process.exit(1);
}
runWithErrorAndStatusCode(() => {
const rushJsonFolder = findRushJsonFolder();
const rushCommonFolder = ensureAndJoinPath(rushJsonFolder, 'common');
const packageSpecifier = parsePackageSpecifier(rawPackageSpecifier);
const name = packageSpecifier.name;
const version = resolvePackageVersion(rushCommonFolder, packageSpecifier);
if (packageSpecifier.version !== version) {
console.log(`Resolved to ${name}@${version}`);
}
return installAndRun(name, version, packageBinName, packageBinArgs);
});
}
run();
//# sourceMappingURL=install-run.js.map

Просмотреть файл

@ -0,0 +1,11 @@
!dist/**/*
test/
dist/test/
package/
.npmignore
tsconfig.json
*.ts
!*.d.ts
*.tgz
.vscode
.scripts

Просмотреть файл

@ -0,0 +1,59 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export class Exception extends Error {
constructor(message: string, public exitCode: number = 1) {
super(message);
Object.setPrototypeOf(this, Exception.prototype);
}
}
export class TypeException extends Exception {
constructor(code: string, name: string, expectedType: string, instance?: any) {
super(instance ? `${code} - '${name}' is not expected type '${expectedType}' (instance: '${instance}') .` : `${code} - '${name}' is not expected type '${expectedType}'.`, 1);
Object.setPrototypeOf(this, TypeException.prototype);
}
}
export class OperationCanceledException extends Exception {
constructor(message: string = "Cancelation Requested", public exitCode: number = 1) {
super(message, exitCode);
Object.setPrototypeOf(this, OperationCanceledException.prototype);
}
}
export class OutstandingTaskAlreadyCompletedException extends Exception {
constructor() {
super("The OutstandingTaskAwaiter is already completed, may not Enter() again.", 1);
Object.setPrototypeOf(this, OutstandingTaskAlreadyCompletedException.prototype);
}
}
export class OperationAbortedException extends Exception {
constructor() {
super("Error occurred. Exiting.", 1);
Object.setPrototypeOf(this, OperationAbortedException.prototype);
}
}
export class AggregateException extends Exception {
constructor(public errors: Array<any>) {
super("Multiple Exceptions caught.", 1);
Object.setPrototypeOf(this, AggregateException.prototype);
}
}
export class ExclusiveLockUnavailableException extends Exception {
constructor(resource: string, timeout: number) {
super(`Unable to acquire exclusive lock on '${resource}' before timeout ${timeout} msec.`, 1);
Object.setPrototypeOf(this, ExclusiveLockUnavailableException.prototype);
}
}
export class SharedLockUnavailableException extends Exception {
constructor(resource: string, timeout: number) {
super(`Unable to acquire shared lock on '${resource}' before timeout ${timeout} msec.`, 1);
Object.setPrototypeOf(this, SharedLockUnavailableException.prototype);
}
}

Просмотреть файл

@ -0,0 +1,364 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Server, ListenOptions } from 'net';
import { ManualPromise } from "./manual-promise"
import { Delay, When } from "./task-functions"
import { ExclusiveLockUnavailableException, SharedLockUnavailableException } from "./exception"
import { promisify } from "./node-promisify";
import { tmpdir } from "os"
import { unlink as fs_unlink, readFile as fs_readFile, writeFile as fs_writeFile } from 'fs';
import { createHash } from 'crypto';
const unlink = promisify(fs_unlink);
const readFile = promisify(fs_readFile);
const writeFile = promisify(fs_writeFile);
function sanitize(input: string, replacement: string = '_') {
const illegalCharacters = /[\/\?<>\\:\*\|":]/g;
const controlCharacters = /[\x00-\x1f\x80-\x9f]/g;
const reservedCharacters = /^\.+$/;
const reservedNames = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$/i;
const trailingSpaces = /[\. ]+$/;
return input
.replace(illegalCharacters, replacement)
.replace(controlCharacters, replacement)
.replace(reservedCharacters, replacement)
.replace(reservedNames, replacement)
.replace(trailingSpaces, replacement);
}
function distill(content: any) {
const hash = createHash('sha256').update(JSON.stringify(content)).digest();
const port = hash.readUInt16BE(2) | 4096; // 4096+
let host = `${(hash.readUInt16BE(4) | 0x10) + 0x7f000000}`;
if (process.platform === "darwin") {
host = `${0x7f000001}`;
}
return { port, host };
}
/**
* An interface for Exclusive Locking objects.
*/
export interface IExclusive {
/**
* Acquire an exclusive lock to the resource.
*
* @throws ExclusiveLockUnavailableException - if the timeout is reached before the lock can be acquired.
* @param timeoutMS - the length of time in miliiseconds to wait for a lock.
* @param delayMS - the length of time in milliseconds to retry the lock.
* @returns - the release function to release the lock.
*/
acquire(timeoutMS?: number, delayMS?: number): Promise<() => Promise<void>>;
}
/**
* An system-wide Exclusive lock for a named resource.
*
* This is implemented using an exclusive named pipe.
*/
export class Mutex implements IExclusive {
/*@internal*/public readonly pipe: string;
/*@internal*/public readonly options: ListenOptions;
/**
*
* @param name - the resource name to create a Mutex for. Multiple instances (across processes) using the same name are operating on the same lock.
*/
public constructor(private name: string) {
if (process.platform === "win32") {
this.pipe = `\\\\.\\pipe\\${sanitize(name)}`;
this.options = { path: this.pipe, exclusive: true };
} else {
const pretendName = `${tmpdir()}/pipe_${sanitize(name)}`;
this.options = { ...distill(pretendName), exclusive: true };
this.pipe = `${tmpdir()}/pipe_${sanitize(name)}:${this.options.port}`;
}
}
/**
* Asynchronously acquires the lock. Will wait for up {@link timeoutMS} milliseconds
* @throws ExclusiveLockUnavailableException - if the timeout is reached before the lock can be acquired.
* @param timeoutMS - the length of time in miliiseconds to wait for a lock.
* @param delayMS - the length of time in milliseconds to retry the lock.
* @returns - the release function to release the lock.
*/
public async acquire(timeoutMS: number = 20000, delayMS: number = 100): Promise<() => Promise<void>> {
const fail = Date.now() + timeoutMS;
do {
try {
// try to get the lock to the pipe
const server = new Server();
// possible events after listen
const completed = When(server, 'listening', 'error');
// listening will trigger when we've acquired the pipe handle
server.listen(this.options);
// don't let this keep the process alive.
server.unref();
// wait to see if we can listen to the pipe or fail trying.
await completed;
// yes, we did, setup the release function
const closedServer = new ManualPromise<void>();
// the release function is returned to the consumer
return async () => {
// ensure that releasing twice isn't harmful.
if (!closedServer.isCompleted) {
server.close(() => closedServer.resolve());
await closedServer;
}
};
} catch {
// not really releavent why it failed. Pause for a moment.
await Delay(delayMS);
}
// check if we're past the allowable time.
} while (fail > Date.now())
// we were unable to get the lock before the timeout.
throw new ExclusiveLockUnavailableException(this.name, timeoutMS);
}
}
/**
* A process-local exclusive lock, bound to the object instance.
*/
export class CriticalSection implements IExclusive {
private promise: ManualPromise<void> | undefined;
/**
* @constructor - Creates an instance of a CriticalSection
*
* @param name - a cosmetic name for the 'resource'. Note: multiple CriticalSection instances with the same do not offer exclusivity, it's tied to the object instance.
*/
public constructor(private name: string = "unnamed") {
}
/**
* Asynchronously acquires the lock. Will wait for up {@link timeoutMS} milliseconds
* @throws ExclusiveLockUnavailableException - if the timeout is reached before the lock can be acquired.
* @param timeoutMS - the length of time in miliiseconds to wait for a lock.
* @param delayMS - unused.
* @returns - the release function to release the lock.
*/
public async acquire(timeoutMS: number = 20000, delayMS: number = 100): Promise<() => Promise<void>> {
// delayMS isn't really relavent in this case, since all aqui
const fail = Date.now() + timeoutMS;
if (this.promise) {
do {
// wait for its release, or we use up what's left of the timeout.
// since multiple consumers can be waiting for the promise to fulfil,
// the previous promise holder can resolve, someone else can take it's place
// before we get a chance to act.
await Promise.race([this.promise, Delay(fail - Date.now())]);
} while (this.promise && fail > Date.now())
}
// check to see if the promise is still around, which indicates
// that we must have timed out.
if (this.promise) {
throw new ExclusiveLockUnavailableException(this.name, timeoutMS);
}
// there is no outstanding promise now, we can create one
const myPromise = new ManualPromise<void>();
this.promise = myPromise;
// the release function is returned to the consumer
return async () => {
// ensure that releasing twice isn't harmful.
if (!myPromise.isCompleted) {
this.promise = undefined
myPromise.resolve();
}
};
}
}
/**
* Offers a lock where many consumers can acquire, but an exclusive lock can only be gained if
* the consumer is the only one who has a shared lock.
*/
export class SharedLock {
private readonly exclusiveLock: Mutex;
private readonly busyLock: Mutex;
private readonly personalLock: Mutex;
private readonly file: string;
public constructor(private name: string) {
this.exclusiveLock = new Mutex(`${sanitize(name)}.exclusive-lock`);
this.busyLock = new Mutex(`${sanitize(name)}.busy-lock`);
this.personalLock = new Mutex(`${sanitize(name)}.${Math.random() * 10000}.personal-lock`);
this.file = `${tmpdir()}/${sanitize(name)}.lock`;
}
private async readConnections(): Promise<Array<ListenOptions>> {
// get the list of names.
let connections = new Array<ListenOptions>();
try {
const list = JSON.parse(await readFile(this.file, 'utf8'));
for (const each of list) {
if (await this.isLocked(each)) {
connections.push(each);
}
}
} catch {
}
return connections;
}
private async writeConnections(connections: Array<ListenOptions>): Promise<void> {
// write the list of names.
if (connections && connections.length > 0) {
// write the list of names into the file.
await writeFile(this.file, JSON.stringify(connections, null, 2));
} else {
try {
// no names in list, file should be deleted
await unlink(this.file)
} catch {
// shh!
}
}
}
private async isLocked(options: ListenOptions): Promise<boolean> {
const server = new Server();
try {
// possible events after listen
const completed = When(server, 'listening', 'error');
// listening will trigger when we've acquired the pipe handle
server.listen(options);
// wait to see if we can listen to the pipe or fail trying.
await completed;
// the pipe opened! It's not locked
await server.close()
return false;
} catch {
server.close();
}
// the pipe is locked
return true;
}
/**
* Asynchronously acquires a shared lock. Will wait for up {@link timeoutMS} milliseconds
* @throws SharedLockUnavailableException - if the timeout is reached before the lock can be acquired.
* @param timeoutMS - the length of time in miliiseconds to wait for a lock.
* @param delayMS - the polling interval for the exclusive lock during initialization.
* @returns - the release function to release the shared lock.
*/
public async acquire(timeoutMS: number = 20000, delayMS: number = 100): Promise<() => Promise<void>> {
// ensure we're the only one that can muck with things for now.
const releaseBusy = await this.busyLock.acquire(timeoutMS, delayMS);
try {
// get our personal lock
const releasePersonal = await this.personalLock.acquire();
const activeLocks = await this.readConnections();
activeLocks.push(this.personalLock.options);
await this.writeConnections(activeLocks);
await releaseBusy();
return async () => {
// release our personal lock
await releasePersonal();
// try to remove our name from the list
try {
const releaseBusy = await this.busyLock.acquire(timeoutMS, delayMS);
try {
await this.writeConnections(await this.readConnections());
} finally {
// regardless, release the busy lock!
await releaseBusy();
}
} catch {
// if it fails no, worry, someone else can clean it up.
}
}
} catch (e) {
throw new SharedLockUnavailableException(this.name, timeoutMS);
} finally {
// release the busy lock!
await releaseBusy();
}
}
public get activeLockCount(): Promise<number> {
return (async () => {
return (await this.readConnections()).length;
})();
}
public get isExclusiveLocked(): Promise<boolean> {
return (async () => {
try {
// try to lock it
const release = (await this.exclusive(0));
await release();
return false;
} catch {
}
return true;
})();
}
/**
* Asynchronously acquires an exclusive lock. Will wait for up {@link timeoutMS} milliseconds
*
* Will only permit a lock if there are no other shared locks
*
* @throws ExclusibveLockUnavailableException - if the timeout is reached before the lock can be acquired.
* @param timeoutMS - the length of time in miliiseconds to wait for a lock.
* @param delayMS - the polling interval for the exclusive lock during initialization.
* @returns - the release function to release the exclusive lock.
*/
public async exclusive(timeoutMS: number = 20000, delayMS: number = 100): Promise<() => Promise<void>> {
const busyRelease = await this.busyLock.acquire(timeoutMS, delayMS);
// ensure we're the only one that can muck with things for now.
const exclusiveRelease = await this.exclusiveLock.acquire(timeoutMS, delayMS);
try {
// make sure we're the only one who has an shared lock
const activeLocks = await this.readConnections();
if (activeLocks.length === 0 || (activeLocks.length === 1 && JSON.stringify(activeLocks[0]) === JSON.stringify(this.personalLock.options))) {
return async () => {
await exclusiveRelease();
await busyRelease();
}
}
} catch {
}
// we didn't return the exclusive Lock,
// release it and throw...
await exclusiveRelease();
await busyRelease();
throw new ExclusiveLockUnavailableException(this.name, timeoutMS);
}
}

Просмотреть файл

@ -0,0 +1,30 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export class LazyPromise<T> implements Promise<T> {
private promise: Promise<T> | null = null;
public constructor(private factory: () => Promise<T>) {
}
private get Value(): Promise<T> {
if (this.promise === null) {
this.promise = this.factory();
}
return this.promise;
}
get [Symbol.toStringTag]() {
return this.Value[Symbol.toStringTag];
}
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2> {
return this.Value.then(onfulfilled, onrejected);
};
catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult> {
return this.Value.catch(onrejected);
}
}

Просмотреть файл

@ -0,0 +1,18 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export class Lazy<T> {
private promise: { obj: T } | null = null;
public constructor(private factory: () => T) {
}
public get Value(): T {
if (this.promise === null) {
this.promise = { obj: this.factory() };
}
return this.promise.obj;
}
}

Просмотреть файл

@ -0,0 +1,70 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/**
* A manually (or externally) controlled asynchronous Promise implementation
*/
export class ManualPromise<T> implements Promise<T> {
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined): Promise<TResult1 | TResult2> {
return this.p.then(onfulfilled, onrejected);
}
/**
* Attaches a callback for only the rejection of the Promise.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of the callback.
*/
catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null | undefined): Promise<T | TResult> {
return this.p.catch(onrejected);
}
readonly [Symbol.toStringTag]: "Promise";
private p: Promise<T>;
/**
* A method to manually resolve the Promise.
*/
public resolve: (value?: T | PromiseLike<T> | undefined) => void = (v) => { };
/**
* A method to manually reject the Promise
*/
public reject: (e: any) => void = (e) => { };
private state: "pending" | "resolved" | "rejected" = "pending";
/**
* Returns true of the Promise has been Resolved or Rejected
*/
public get isCompleted(): boolean {
return this.state !== "pending";
}
/**
* Returns true if the Promise has been Resolved.
*/
public get isResolved(): boolean {
return this.state === "resolved";
}
/**
* Returns true if the Promise has been Rejected.
*/
public get isRejected(): boolean {
return this.state === "rejected";
}
public constructor() {
this.p = new Promise<T>((r, j) => {
this.resolve = (v: T | PromiseLike<T> | undefined) => { this.state = "resolved"; r(v); };
this.reject = (e: any) => { this.state = "rejected"; j(e); };
});
}
}

Просмотреть файл

@ -0,0 +1,109 @@
import { TypeException } from "./exception"
import { ManualPromise } from "./manual-promise"
import { promisify as util_promisify } from 'util'
const kCustomPromisifiedSymbol = Symbol('util.promisify.custom');
const kCustomPromisifyArgsSymbol = Symbol('customPromisifyArgs');
declare global {
interface ObjectConstructor {
getOwnPropertyDescriptors(o: any): PropertyDescriptorMap;
}
}
/**
* Add polyfill for Object.getOwnPropertyDescriptors
*
* Origin: https://github.com/tc39/proposal-object-getownpropertydescriptors
*/
if (!Object.hasOwnProperty('getOwnPropertyDescriptors')) {
Object.defineProperty(
Object,
'getOwnPropertyDescriptors',
{
configurable: true,
writable: true,
value: function getOwnPropertyDescriptors(object: any) {
return Reflect.ownKeys(object).reduce((descriptors, key) => {
return Object.defineProperty(
descriptors,
key,
{
configurable: true,
enumerable: true,
writable: true,
value: Object.getOwnPropertyDescriptor(object, key)
}
);
}, {});
}
}
);
}
/**
* Promisify Implementation acquired from node8 and adapted to node7/typescript
*
* @param original original method declaration
*/
function _promisify(original: any) {
if (typeof original !== 'function')
throw new TypeException('ERR_INVALID_ARG_TYPE', 'original', 'Function');
if (original[kCustomPromisifiedSymbol]) {
const fn = original[kCustomPromisifiedSymbol];
if (typeof fn !== 'function') {
throw new TypeException('ERR_INVALID_ARG_TYPE',
'util.promisify.custom',
'Function',
fn);
}
Object.defineProperty(fn, kCustomPromisifiedSymbol, {
value: fn, enumerable: false, writable: false, configurable: true
});
return fn;
}
// Names to create an object from in case the callback receives multiple
// arguments, e.g. ['stdout', 'stderr'] for child_process.exec.
const argumentNames = original[kCustomPromisifyArgsSymbol];
function fn(this: any, ...args: any[]): Promise<any> {
const promise = new ManualPromise();
try {
original.call(this, ...args, (err: any, ...values: any[]) => {
if (err) {
promise.reject(err);
} else if (argumentNames !== undefined && values.length > 1) {
const obj: any = {};
for (var i = 0; i < argumentNames.length; i++)
obj[argumentNames[i]] = values[i];
promise.resolve(obj);
} else {
promise.resolve(values[0]);
}
});
} catch (err) {
promise.reject(err);
}
return promise;
}
Object.setPrototypeOf(fn, Object.getPrototypeOf(original));
Object.defineProperty(fn, kCustomPromisifiedSymbol, {
value: fn, enumerable: false, writable: false, configurable: true
});
return Object.defineProperties(
fn,
Object.getOwnPropertyDescriptors(original)
);
}
(<any>_promisify).custom = kCustomPromisifiedSymbol;
/**
* Promisify implementation, will use built-in version in node if available, falls back to local implementation borrowed from node8.
*/
export const promisify = util_promisify || _promisify;

Просмотреть файл

@ -0,0 +1,35 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { OutstandingTaskAlreadyCompletedException, AggregateException } from "./exception";
export class OutstandingTaskAwaiter {
private locked: boolean = false;
private outstandingTasks: Promise<any>[] = [];
private errors: Array<any> = [];
public async Wait(): Promise<void> {
this.locked = true;
await Promise.all(this.outstandingTasks);
if (this.errors.length) {
if (this.errors.length == 1) {
throw this.errors[0];
}
throw new AggregateException(this.errors);
}
}
public async Await<T>(task: Promise<T>): Promise<T> {
if (this.locked) {
throw new OutstandingTaskAlreadyCompletedException();
}
this.outstandingTasks.push(task.catch((e) => {
console.error("Yes. errors in the await.")
this.errors.push(e)
}));
return task;
}
}

Просмотреть файл

@ -0,0 +1,29 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/**
* Creates a shallow copy of a given object by copying the properties to a new object
* Note: this does not copy the method prototypes, so it's a shallow data copy only.
*
* @param {input} any javascript object
* @param {filter} Array<string> of properties to filter out from the copy.
*/
export function shallowCopy(input: any, ...filter: Array<string>): any {
if (!input) {
return input;
}
const keys = input.Keys ? input.Keys : Object.getOwnPropertyNames(input);
const result: any = {};
for (const key of keys) {
if (filter.indexOf(key) == -1) {
const value = input[key];
if (value !== undefined) {
result[key] = value;
}
}
}
return result;
}

Просмотреть файл

@ -0,0 +1,81 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { EventEmitter } from "events"
import { ManualPromise } from "./manual-promise"
import { promisify } from "./node-promisify"
/**
* Creates a promise that resolves after a delay
*
* @param delayMS the length of time to delay in milliseconds.
*/
export function Delay(delayMS: number): Promise<void> {
return new Promise<void>(res => setTimeout(res, delayMS));
}
/**
* Asynchronously waits for the predicate condition to turn false, with a delay between checks
* @param predicate - a fn that returns a boolean
* @param delay - number of milliseconds to async delay between checks.
*/
export async function While(predicate: () => boolean, delay: number = 50): Promise<void> {
while (predicate()) {
await Delay(delay);
}
}
/**
* Asynchronously waits for the predicate condition to turn true, with a delay between checks
* @param predicate - a fn that returns a boolean
* @param delay - number of milliseconds to async delay between checks.
*/
export async function Until(predicate: () => boolean, delay: number = 50): Promise<void> {
while (predicate()) {
await Delay(delay);
}
}
/**
* An async wrapper for waiting for an event to trigger once
* @param emitter - an event emitter
* @param event - the name of the event to wait for.
*/
export function When<T>(emitter: EventEmitter, successEvent?: string, errorEvent?: string): Promise<T> {
const result = new ManualPromise<T>();
if (errorEvent) {
// errors after a previous completion are ignored.
emitter.once(errorEvent, (e: any) => {
if (!result.isCompleted) {
result.reject(e);
}
});
}
if (successEvent) {
// success after a previous completion is ignored.
emitter.once(successEvent, (v: T) => {
if (!result.isCompleted) {
result.resolve(v);
}
});
}
return result;
}
export function Async<T>(fn: () => T, msec: number = 1): Promise<T> {
return new Promise((r, j) => setTimeout(() => {
try { r(fn()) } catch (E) { j(E) }
}, msec));
}
export async function Timeout<T>(p: Promise<T>, msec: number): Promise<T> {
let enabled = false;
const value = await Promise.race([p, Async(() => { if (enabled) throw new Error("timed out") }, msec)]);
enabled = false;
return value as T;
}

14
libraries/tasks/main.ts Normal file
Просмотреть файл

@ -0,0 +1,14 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export * from './lib/exception'
export * from './lib/outstanding-task-awaiter'
export * from "./lib/lazy-promise"
export * from "./lib/lazy"
export * from "./lib/manual-promise"
export * from "./lib/exclusive-locks"
export * from "./lib/task-functions"
export * from "./lib/polyfill"

Просмотреть файл

@ -0,0 +1,43 @@
{
"name": "@microsoft.azure/tasks",
"version": "2.0.27",
"description": "Async tasks, exceptions for Azure Open Source Projects",
"engines": {
"node": ">=7.10.0"
},
"main": "./dist/main.js",
"typings": "./dist/main.d.ts",
"repository": {
"type": "git",
"url": "git+https://github.com/Azure/perks.tasks.git"
},
"scripts": {
"build": "tsc -p .",
"prepare": "npm run build",
"test": "npm run build && _mocha dist/test",
"testci": "npm run build && mocha dist/test"
},
"keywords": [
"perks",
"tasks",
"autorest",
"azure",
"typescript"
],
"author": "Microsoft",
"license": "MIT",
"bugs": {
"url": "https://github.com/Azure/perks.tasks/issues"
},
"homepage": "https://github.com/Azure/perks.tasks#readme",
"readme": "https://github.com/Azure/perks.tasks/readme.md",
"devDependencies": {
"@types/node": "10.11.3",
"@types/mocha": "5.2.5",
"mocha": "5.2.0",
"mocha-typescript": "1.1.17",
"typescript": "^3.1.1",
"source-map-support": "0.5.9"
},
"dependencies": {}
}

15
libraries/tasks/readme.md Normal file
Просмотреть файл

@ -0,0 +1,15 @@
# Project: @microsoft.azure/tasks
This package contains common code for the developer tools for generating Azure SDKs.
Including:
- AutoRest
### Description
Task and Exception support for AutoRest and related tools.
----
# Contributing
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.

Просмотреть файл

@ -0,0 +1,3 @@
import * as Mocha from 'mocha';
declare type MochaDone = Mocha.Done;

Просмотреть файл

@ -0,0 +1,29 @@
import { suite, test, slow, timeout, skip, only } from "mocha-typescript";
import * as assert from "assert";
import { While, CriticalSection, Async } from "../main";
// pull in source-map support for stack traces.
require('source-map-support').install({ hookRequire: true });
@suite class TestFunctions {
@test async "Test While"() {
let i = 10;
await While(() => --i ? true : false);
assert.equal(i, 0, "While should run until condition is false.")
}
@test async "Async"() {
let x = 0;
const done = Async(() => {
x = 100;
})
assert.equal(x, 0, "should not run async until after this point.")
await done;
assert.equal(x, 100, "it should have run it.")
}
}

Просмотреть файл

@ -0,0 +1,123 @@
import { suite, test, slow, timeout, skip, only } from "mocha-typescript";
import * as assert from "assert";
import { CriticalSection, Mutex, SharedLock, ManualPromise, Delay, Async } from "../main"
// pull in source-map support for stack traces.
require('source-map-support').install({ hookRequire: true });
@suite class TestLocks {
@test async "CriticalSection"() {
const cs = new CriticalSection();
const status = new Array<string>();
const first = Async(async () => {
const r = await cs.acquire();
console.log("1. acquired");
status.push("A");
await Delay(200);
console.log("2. releasing")
status.push("B");
await r();
console.log("3.released")
status.push("C");
})
const second = Async(async () => {
const r = await cs.acquire();
console.log("4. acquired");
status.push("D");
await Delay(10);
console.log("5. releasing")
status.push("E");
await r();
console.log("6.released")
status.push("F");
})
await Promise.all([first, second]);
assert.equal(status.join(""), "ABCDEF", "Correct Order.")
}
@test async "Mutex"() {
const status = new Array<string>();
const first = Async(async () => {
const mutex = new Mutex("garrett");
const r = await mutex.acquire();
console.log("1. acquired");
status.push("A");
await Delay(200);
console.log("2. releasing")
status.push("B");
await r();
console.log("3.released")
status.push("C");
})
const second = Async(async () => {
try {
const mutex = new Mutex("garrett");
const r = await mutex.acquire();
console.log("4. acquired");
status.push("D");
await Delay(10);
console.log("5. releasing")
status.push("E");
await r();
console.log("6.released")
status.push("F");
} catch (E) {
console.log(E);
}
}, 1)
await Promise.all([first, second]);
assert.equal(status.join(""), "ABCDEF", "Correct Order.")
}
@test async "SharedLock-simple"() {
const sharedLock = new SharedLock("/tmp/testJqqE6h/install-pkguByBYI/echo-cli@1.0.8/bla/bla/bla");
const release = await sharedLock.acquire();
try {
assert.equal(await sharedLock.activeLockCount, 1, "should be one active lock")
assert.equal(await sharedLock.isExclusiveLocked, false, "should not be exclusive");
const ex_release = await sharedLock.exclusive();
assert.equal(await sharedLock.isExclusiveLocked, true, "should be exclusive");
const anotherShared = new SharedLock("/tmp/testJqqE6h/install-pkguByBYI/echo-cli@1.0.8/bla/bla/bla");
let success = false;
try {
await anotherShared.acquire(2)
} catch {
success = true;
}
assert.equal(success, true, "should not be able to get shared lock");
await ex_release();
success = false;
try {
await (await anotherShared.acquire(2))()
success = true;
} catch {
success = false;
}
assert.equal(success, true, "should be able to get shared lock");
} finally {
await release();
}
}
}

Просмотреть файл

@ -0,0 +1,30 @@
{
"compilerOptions": {
"outDir": "dist",
"alwaysStrict": true,
"forceConsistentCasingInFileNames": false,
"module": "commonjs",
"noEmitOnError": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"sourceMap": true,
"strict": true,
"declaration": true,
"stripInternal": true,
"noEmitHelpers": false,
"target": "es2017",
"types": [
"node"
],
"lib": [
"es2017"
],
"experimentalDecorators": true,
"newLine": "LF"
},
"exclude": [
"dist",
"node_modules"
]
}

267
rush.json Normal file
Просмотреть файл

@ -0,0 +1,267 @@
/**
* This is the main configuration file for Rush.
* For full documentation, please see https://rushjs.io
*/
{
"$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush.schema.json",
/**
* (Required) This specifies the version of the Rush engine to be used in this repo.
* Rush's "version selector" feature ensures that the globally installed tool will
* behave like this release, regardless of which version is installed globally.
*
* The common/scripts/install-run-rush.js automation script also uses this version.
*
* NOTE: If you upgrade to a new major version of Rush, you should replace the "v5"
* path segment in the "$schema" field for all your Rush config files. This will ensure
* correct error-underlining and tab-completion for editors such as VS Code.
*/
"rushVersion": "5.3.1",
/**
* The next field selects which package manager should be installed and determines its version.
* Rush installs its own local copy of the package manager to ensure that your build process
* is fully isolated from whatever tools are present in the local environment.
*
* Specify one of: "pnpmVersion", "npmVersion", or "yarnVersion". See the Rush documentation
* for details about these alternatives.
*/
"pnpmVersion": "2.15.1",
// "npmVersion": "4.5.0",
// "yarnVersion": "1.9.4",
/**
* Options that are only used when the PNPM package manager is selected
*/
"pnpmOptions": {
/**
* If true, then Rush will add the "--strict-peer-dependencies" option when invoking PNPM.
* This causes "rush install" to fail if there are unsatisfied peer dependencies, which is
* an invalid state that can cause build failures or incompatible dependency versions.
* (For historical reasons, JavaScript package managers generally do not treat this invalid
* state as an error.)
*
* The default value is false to avoid legacy compatibility issues.
* It is strongly recommended to set strictPeerDependencies=true.
*/
"strictPeerDependencies": true
},
/**
* Older releases of the NodeJS engine may be missing features required by your system.
* Other releases may have bugs. In particular, the "latest" version will not be a
* Long Term Support (LTS) version and is likely to have regressions.
*
* Specify a SemVer range to ensure developers use a NodeJS version that is appropriate
* for your repo.
*/
"nodeSupportedVersionRange": ">=8.9.4 <11.0.0",
/**
* If you would like the version specifiers for your dependencies to be consistent, then
* uncomment this line. This is effectively similar to running "rush check" before any
* of the following commands:
*
* rush install, rush update, rush link, rush version, rush publish
*
* In some cases you may want this turned on, but need to allow certain packages to use a different
* version. In those cases, you will need to add an entry to the "allowedAlternateVersions"
* section of the common-versions.json.
*/
"ensureConsistentVersions": true,
/**
* Large monorepos can become intimidating for newcomers if project folder paths don't follow
* a consistent and recognizable pattern. When the system allows nested folder trees,
* we've found that teams will often use subfolders to create islands that isolate
* their work from others ("shipping the org"). This hinders collaboration and code sharing.
*
* The Rush developers recommend a "category folder" model, where buildable project folders
* must always be exactly two levels below the repo root. The parent folder acts as the category.
* This provides a basic facility for grouping related projects (e.g. "apps", "libaries",
* "tools", "prototypes") while still encouraging teams to organize their projects into
* a unified taxonomy. Limiting to 2 levels seems very restrictive at first, but if you have
* 20 categories and 20 projects in each category, this scheme can easily accommodate hundreds
* of projects. In practice, you will find that the folder hierarchy needs to be rebalanced
* occasionally, but if that's painful, it's a warning sign that your development style may
* discourage refactoring. Reorganizing the categories should be an enlightening discussion
* that brings people together, and maybe also identifies poor coding practices (e.g. file
* references that reach into other project's folders without using NodeJS module resolution).
*
* The defaults are projectFolderMinDepth=1 and projectFolderMaxDepth=2.
*
* To remove these restrictions, you could set projectFolderMinDepth=1
* and set projectFolderMaxDepth to a large number.
*/
"projectFolderMinDepth": 2,
"projectFolderMaxDepth": 2,
/**
* This feature helps you to review and approve new packages before they are introduced
* to your monorepo. For example, you may be concerned about licensing, code quality,
* performance, or simply accumulating too many libraries with overlapping functionality.
* The approvals are tracked in two config files "browser-approved-packages.json"
* and "nonbrowser-approved-packages.json". See the Rush documentation for details.
*/
// "approvedPackagesPolicy": {
// /**
// * The review categories allow you to say for example "This library is approved for usage
// * in prototypes, but not in production code."
// *
// * Each project can be associated with one review category, by assigning the "reviewCategory" field
// * in the "projects" section of rush.json. The approval is then recorded in the files
// * "common/config/rush/browser-approved-packages.json" and "nonbrowser-approved-packages.json"
// * which are automatically generated during "rush update".
// *
// * Designate categories with whatever granularity is appropriate for your review process,
// * or you could just have a single category called "default".
// */
// "reviewCategories": [
// // Some example categories:
// "production", // projects that ship to production
// "tools", // non-shipping projects that are part of the developer toolchain
// "prototypes" // experiments that should mostly be ignored by the review process
// ],
//
// /**
// * A list of NPM package scopes that will be excluded from review.
// * We recommend to exclude TypeScript typings (the "@types" scope), because
// * if the underlying package was already approved, this would imply that the typings
// * are also approved.
// */
// // "ignoredNpmScopes": [ "@types" ]
// },
/**
* If you use Git as your version control system, this section has some additional
* optional features you can use.
*/
"gitPolicy": {
/**
* Work at a big company? Tired of finding Git commits at work with unprofessional Git
* emails such as "beer-lover@my-college.edu"? Rush can validate people's Git email address
* before they get started.
*
* Define a list of regular expressions describing allowable e-mail patterns for Git commits.
* They are case-insensitive anchored JavaScript RegExps. Example: ".*@example\.com"
*
* IMPORTANT: Because these are regular expressions encoded as JSON string literals,
* RegExp escapes need two backspashes, and ordinary periods should be "\\.".
*/
// "allowedEmailRegExps": [
// "[^@]+@users\\.noreply\\.github\\.com",
// "travis@example\\.org"
// ],
/**
* When Rush reports that the address is malformed, the notice can include an example
* of a recommended email. Make sure it conforms to one of the allowedEmailRegExps
* expressions.
*/
// "sampleEmail": "mrexample@users.noreply.github.com"
},
"repository": {
/**
* This setting is sometimes needed when using "rush change" with multiple Git remotes.
* It specifies the remote url for the official Git repository. If this URL is provided,
* "rush change" will use it to find the right remote to compare against.
*/
// "url": "https://github.com/Microsoft/rush-example"
},
/**
* Event hooks are customized script actions that Rush executes when specific events occur
*/
"eventHooks": {
/**
* The list of shell commands to run before the Rush installation starts
*/
"preRushInstall": [
// "common/scripts/pre-rush-install.js"
],
/**
* The list of shell commands to run after the Rush installation finishes
*/
"postRushInstall": [],
/**
* The list of shell commands to run before the Rush build command starts
*/
"preRushBuild": [],
/**
* The list of shell commands to run after the Rush build command finishes
*/
"postRushBuild": []
},
/**
* Rush can collect anonymous telemetry about everyday developer activity such as
* success/failure of installs, builds, and other operations. You can use this to identify
* problems with your toolchain or Rush itself. THIS TELEMETRY IS NOT SHARED WITH MICROSOFT.
* It is written into JSON files in the common/temp folder. It's up to you to write scripts
* that read these JSON files and do something with them. These scripts are typically registered
* in the "eventHooks" section.
*/
"telemetryEnabled": false,
/**
* Allows creation of hotfix changes. This feature is experimental so it is disabled by default.
*/
// "hotfixChangeEnabled": false,
/**
* (Required) This is the inventory of projects to be managed by Rush.
*
* Rush does not automatically scan for projects using wildcards, for a few reasons:
* 1. Depth-first scans are expensive, particularly when tools need to repeatedly collect the list.
* 2. On a caching CI machine, scans can accidentally pick up files left behind from a previous build.
* 3. It's useful to have a centralized inventory of all projects and their important metadata.
*/
"projects": [
// {
// /**
// * The NPM package name of the project (must match package.json)
// */
// "packageName": "my-app",
//
// /**
// * The path to the project folder, relative to the rush.json config file.
// */
// "projectFolder": "apps/my-app",
//
// /**
// * An optional category for usage in the "browser-approved-packages.json"
// * and "nonbrowser-approved-packages.json" files. The value must be one of the
// * strings from the "reviewCategories" defined above.
// */
// "reviewCategory": "production",
//
// /**
// * A list of local projects that appear as devDependencies for this project, but cannot be
// * locally linked because it would create a cyclic dependency; instead, the last published
// * version will be installed in the Common folder.
// */
// "cyclicDependencyProjects": [
// // "my-toolchain"
// ],
//
// /**
// * If true, then this project will be ignored by the "rush check" command.
// * The default value is false.
// */
// // "skipRushCheck": false,
//
// /**
// * A flag indicating that changes to this project will be published to npm, which affects
// * the Rush change and publish workflows. The default value is false.
// * NOTE: "versionPolicyName" and "shouldPublish" are alternatives; you cannot specify them both.
// */
// // "shouldPublish": false,
//
// /**
// * An optional version policy associated with the project. Version policies are defined
// * in "version-policies.json" file. See the "rush publish" documentation for more info.
// * NOTE: "versionPolicyName" and "shouldPublish" are alternatives; you cannot specify them both.
// */
// // "versionPolicyName": ""
// },
//
{
"packageName": "@microsoft.azure/tasks",
"projectFolder": "libraries/tasks",
"reviewCategory": "production"
},
//
// {
// "packageName": "my-toolchain",
// "projectFolder": "tools/my-toolchain",
// "reviewCategory": "tools"
// }
]
}