Merge remote-tracking branch 'origin/releases/v2' into v3
# Conflicts: # .github/workflows/versioning.ymlreleases/v3
commit
b4c28bf892
|
|
@ -0,0 +1,40 @@
|
||||||
|
# [2.4.0](https://github.com/TriPSs/conventional-changelog-action/compare/v2.3.3...v2.4.0) (2020-06-10)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add skip-on-empty feature ([153f866](https://github.com/TriPSs/conventional-changelog-action/commit/153f866251ba4d7c33881dbf082bb1e17974e2a1))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [2.3.3](https://github.com/TriPSs/conventional-changelog-action/compare/v2.3.2...v2.3.3) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Fixes for CI ([b0698e5](https://github.com/TriPSs/conventional-changelog-action/commit/b0698e5e9b298cc4a6d95889e38638d8d6fd35fa))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [2.3.2](https://github.com/TriPSs/conventional-changelog-action/compare/v2.3.1...v2.3.2) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Fixes for CI ([093fc9c](https://github.com/TriPSs/conventional-changelog-action/commit/093fc9c7c21c99f362e43df6c572f02b0bf6fc8e))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [2.3.1](https://github.com/TriPSs/conventional-changelog-action/compare/v2.3.0...v2.3.1) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [2.3.0](https://github.com/TriPSs/conventional-changelog-action/compare/v2.2.0...v2.3.0) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Added clean_changelog option ([7684c0e](https://github.com/TriPSs/conventional-changelog-action/commit/7684c0e755c006004c61d6a6c12e748fee34179d))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
../JSONStream/bin.js
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
../conventional-changelog-writer/cli.js
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
../conventional-commits-parser/cli.js
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
../conventional-recommended-bump/cli.js
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
../get-pkg-repo/cli.js
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
../git-raw-commits/cli.js
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
../git-semver-tags/cli.js
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
../handlebars/bin/handlebars
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
../normalize-package-data/node_modules/semver/bin/semver
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
../get-pkg-repo/node_modules/strip-indent/cli.js
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
../uglify-js/bin/uglifyjs
|
||||||
|
|
@ -0,0 +1,182 @@
|
||||||
|
{
|
||||||
|
"systemParams": "linux-x64-72",
|
||||||
|
"modulesFolders": [
|
||||||
|
"node_modules"
|
||||||
|
],
|
||||||
|
"flags": [
|
||||||
|
"production"
|
||||||
|
],
|
||||||
|
"linkedModules": [],
|
||||||
|
"topLevelPatterns": [
|
||||||
|
"@actions/core@1.2.3",
|
||||||
|
"@actions/exec@1.0.4",
|
||||||
|
"conventional-changelog@3.1.18",
|
||||||
|
"conventional-recommended-bump@6.0.5"
|
||||||
|
],
|
||||||
|
"lockfileEntries": {
|
||||||
|
"@actions/core@1.2.3": "https://registry.yarnpkg.com/@actions/core/-/core-1.2.3.tgz#e844b4fa0820e206075445079130868f95bfca95",
|
||||||
|
"@actions/exec@1.0.4": "https://registry.yarnpkg.com/@actions/exec/-/exec-1.0.4.tgz#99d75310e62e59fc37d2ee6dcff6d4bffadd3a5d",
|
||||||
|
"@actions/io@^1.0.1": "https://registry.yarnpkg.com/@actions/io/-/io-1.0.2.tgz#2f614b6e69ce14d191180451eb38e6576a6e6b27",
|
||||||
|
"JSONStream@^1.0.4": "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0",
|
||||||
|
"add-stream@^1.0.0": "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa",
|
||||||
|
"array-find-index@^1.0.1": "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1",
|
||||||
|
"array-ify@^1.0.0": "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece",
|
||||||
|
"arrify@^1.0.1": "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d",
|
||||||
|
"buffer-from@^1.0.0": "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef",
|
||||||
|
"camelcase-keys@^2.0.0": "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7",
|
||||||
|
"camelcase-keys@^4.0.0": "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77",
|
||||||
|
"camelcase@^2.0.0": "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f",
|
||||||
|
"camelcase@^4.1.0": "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd",
|
||||||
|
"commander@2.20.0": "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422",
|
||||||
|
"compare-func@^1.3.1": "https://registry.yarnpkg.com/compare-func/-/compare-func-1.3.2.tgz#99dd0ba457e1f9bc722b12c08ec33eeab31fa648",
|
||||||
|
"concat-stream@^2.0.0": "https://registry.yarnpkg.com/concat-stream/-/concat-stream-2.0.0.tgz#414cf5af790a48c60ab9be4527d56d5e41133cb1",
|
||||||
|
"conventional-changelog-angular@^5.0.6": "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.6.tgz#269540c624553aded809c29a3508fdc2b544c059",
|
||||||
|
"conventional-changelog-atom@^2.0.3": "https://registry.yarnpkg.com/conventional-changelog-atom/-/conventional-changelog-atom-2.0.3.tgz#3bd14280aa09fe3ec49a0e8fe97b5002db02aad4",
|
||||||
|
"conventional-changelog-codemirror@^2.0.3": "https://registry.yarnpkg.com/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.3.tgz#ebc088154684f8f5171446b8d546ba6b460d46f2",
|
||||||
|
"conventional-changelog-conventionalcommits@^4.2.3": "https://registry.yarnpkg.com/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.2.3.tgz#22855b32d57d0328951c1c2dc01b172a5f24ea37",
|
||||||
|
"conventional-changelog-core@^4.1.4": "https://registry.yarnpkg.com/conventional-changelog-core/-/conventional-changelog-core-4.1.4.tgz#39be27fca6ef20a0f998d7a3a1e97cfa8a055cb6",
|
||||||
|
"conventional-changelog-ember@^2.0.4": "https://registry.yarnpkg.com/conventional-changelog-ember/-/conventional-changelog-ember-2.0.4.tgz#c29b78e4af7825cbecb6c3fd6086ca5c09471ac1",
|
||||||
|
"conventional-changelog-eslint@^3.0.4": "https://registry.yarnpkg.com/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.4.tgz#8f4736a23e0cd97e890e76fccc287db2f205f2ff",
|
||||||
|
"conventional-changelog-express@^2.0.1": "https://registry.yarnpkg.com/conventional-changelog-express/-/conventional-changelog-express-2.0.1.tgz#fea2231d99a5381b4e6badb0c1c40a41fcacb755",
|
||||||
|
"conventional-changelog-jquery@^3.0.6": "https://registry.yarnpkg.com/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.6.tgz#460236ad8fb1d29ff932a14fe4e3a45379b63c5e",
|
||||||
|
"conventional-changelog-jshint@^2.0.3": "https://registry.yarnpkg.com/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.3.tgz#ef6e2caf2ee6ffdfda78fcdf7ce87cf6c512d728",
|
||||||
|
"conventional-changelog-preset-loader@^2.3.0": "https://registry.yarnpkg.com/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.0.tgz#580fa8ab02cef22c24294d25e52d7ccd247a9a6a",
|
||||||
|
"conventional-changelog-writer@^4.0.11": "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-4.0.11.tgz#9f56d2122d20c96eb48baae0bf1deffaed1edba4",
|
||||||
|
"conventional-changelog@3.1.18": "https://registry.yarnpkg.com/conventional-changelog/-/conventional-changelog-3.1.18.tgz#7da0a5ab34a604b920b8bf71c6cf5d952f0e805e",
|
||||||
|
"conventional-commits-filter@^2.0.2": "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-2.0.2.tgz#f122f89fbcd5bb81e2af2fcac0254d062d1039c1",
|
||||||
|
"conventional-commits-parser@^3.0.8": "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.0.8.tgz#23310a9bda6c93c874224375e72b09fb275fe710",
|
||||||
|
"conventional-recommended-bump@6.0.5": "https://registry.yarnpkg.com/conventional-recommended-bump/-/conventional-recommended-bump-6.0.5.tgz#be7ec24b43bef57108042ea1d49758b58beabc03",
|
||||||
|
"core-util-is@~1.0.0": "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7",
|
||||||
|
"currently-unhandled@^0.4.1": "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea",
|
||||||
|
"dargs@^4.0.1": "https://registry.yarnpkg.com/dargs/-/dargs-4.1.0.tgz#03a9dbb4b5c2f139bf14ae53f0b8a2a6a86f4e17",
|
||||||
|
"dateformat@^3.0.0": "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae",
|
||||||
|
"decamelize-keys@^1.0.0": "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9",
|
||||||
|
"decamelize@^1.1.0": "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290",
|
||||||
|
"decamelize@^1.1.2": "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290",
|
||||||
|
"dot-prop@^3.0.0": "https://registry.yarnpkg.com/dot-prop/-/dot-prop-3.0.0.tgz#1b708af094a49c9a0e7dbcad790aba539dac1177",
|
||||||
|
"error-ex@^1.2.0": "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf",
|
||||||
|
"error-ex@^1.3.1": "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf",
|
||||||
|
"find-up@^1.0.0": "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f",
|
||||||
|
"find-up@^2.0.0": "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7",
|
||||||
|
"get-pkg-repo@^1.0.0": "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz#c73b489c06d80cc5536c2c853f9e05232056972d",
|
||||||
|
"get-stdin@^4.0.1": "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe",
|
||||||
|
"git-raw-commits@2.0.0": "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.0.tgz#d92addf74440c14bcc5c83ecce3fb7f8a79118b5",
|
||||||
|
"git-remote-origin-url@^2.0.0": "https://registry.yarnpkg.com/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz#5282659dae2107145a11126112ad3216ec5fa65f",
|
||||||
|
"git-semver-tags@^3.0.1": "https://registry.yarnpkg.com/git-semver-tags/-/git-semver-tags-3.0.1.tgz#9cb9e4974437de1f71f32da3bfe74f4d35afb1b9",
|
||||||
|
"gitconfiglocal@^1.0.0": "https://registry.yarnpkg.com/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz#41d045f3851a5ea88f03f24ca1c6178114464b9b",
|
||||||
|
"graceful-fs@^4.1.2": "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02",
|
||||||
|
"handlebars@^4.4.0": "https://registry.yarnpkg.com/handlebars/-/handlebars-4.4.3.tgz#180bae52c1d0e9ec0c15d7e82a4362d662762f6e",
|
||||||
|
"hosted-git-info@^2.1.4": "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c",
|
||||||
|
"indent-string@^2.1.0": "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80",
|
||||||
|
"indent-string@^3.0.0": "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289",
|
||||||
|
"inherits@^2.0.3": "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c",
|
||||||
|
"inherits@~2.0.3": "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c",
|
||||||
|
"ini@^1.3.2": "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927",
|
||||||
|
"is-arrayish@^0.2.1": "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d",
|
||||||
|
"is-finite@^1.0.0": "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa",
|
||||||
|
"is-obj@^1.0.0": "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f",
|
||||||
|
"is-plain-obj@^1.1.0": "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e",
|
||||||
|
"is-text-path@^1.0.1": "https://registry.yarnpkg.com/is-text-path/-/is-text-path-1.0.1.tgz#4e1aa0fb51bfbcb3e92688001397202c1775b66e",
|
||||||
|
"is-utf8@^0.2.0": "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72",
|
||||||
|
"isarray@~1.0.0": "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11",
|
||||||
|
"json-parse-better-errors@^1.0.1": "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9",
|
||||||
|
"json-stringify-safe@^5.0.1": "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb",
|
||||||
|
"jsonparse@^1.2.0": "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280",
|
||||||
|
"load-json-file@^1.0.0": "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0",
|
||||||
|
"load-json-file@^4.0.0": "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b",
|
||||||
|
"locate-path@^2.0.0": "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e",
|
||||||
|
"lodash._reinterpolate@^3.0.0": "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d",
|
||||||
|
"lodash.ismatch@^4.4.0": "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37",
|
||||||
|
"lodash.template@^4.0.2": "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab",
|
||||||
|
"lodash.templatesettings@^4.0.0": "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33",
|
||||||
|
"lodash@^4.17.15": "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548",
|
||||||
|
"loud-rejection@^1.0.0": "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f",
|
||||||
|
"map-obj@^1.0.0": "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d",
|
||||||
|
"map-obj@^1.0.1": "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d",
|
||||||
|
"map-obj@^2.0.0": "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9",
|
||||||
|
"meow@^3.3.0": "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb",
|
||||||
|
"meow@^4.0.0": "https://registry.yarnpkg.com/meow/-/meow-4.0.1.tgz#d48598f6f4b1472f35bf6317a95945ace347f975",
|
||||||
|
"meow@^5.0.0": "https://registry.yarnpkg.com/meow/-/meow-5.0.0.tgz#dfc73d63a9afc714a5e371760eb5c88b91078aa4",
|
||||||
|
"minimist-options@^3.0.1": "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954",
|
||||||
|
"minimist@^1.1.3": "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284",
|
||||||
|
"minimist@~0.0.1": "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf",
|
||||||
|
"modify-values@^1.0.0": "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022",
|
||||||
|
"neo-async@^2.6.0": "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c",
|
||||||
|
"normalize-package-data@^2.3.0": "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8",
|
||||||
|
"normalize-package-data@^2.3.2": "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8",
|
||||||
|
"normalize-package-data@^2.3.4": "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8",
|
||||||
|
"normalize-package-data@^2.3.5": "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8",
|
||||||
|
"number-is-nan@^1.0.0": "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d",
|
||||||
|
"object-assign@^4.0.1": "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863",
|
||||||
|
"optimist@^0.6.1": "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686",
|
||||||
|
"p-limit@^1.1.0": "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8",
|
||||||
|
"p-locate@^2.0.0": "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43",
|
||||||
|
"p-try@^1.0.0": "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3",
|
||||||
|
"parse-github-repo-url@^1.3.0": "https://registry.yarnpkg.com/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz#9e7d8bb252a6cb6ba42595060b7bf6df3dbc1f50",
|
||||||
|
"parse-json@^2.2.0": "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9",
|
||||||
|
"parse-json@^4.0.0": "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0",
|
||||||
|
"path-exists@^2.0.0": "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b",
|
||||||
|
"path-exists@^3.0.0": "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515",
|
||||||
|
"path-parse@^1.0.6": "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c",
|
||||||
|
"path-type@^1.0.0": "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441",
|
||||||
|
"path-type@^3.0.0": "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f",
|
||||||
|
"pify@^2.0.0": "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c",
|
||||||
|
"pify@^2.3.0": "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c",
|
||||||
|
"pify@^3.0.0": "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176",
|
||||||
|
"pinkie-promise@^2.0.0": "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa",
|
||||||
|
"pinkie@^2.0.0": "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870",
|
||||||
|
"process-nextick-args@~2.0.0": "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2",
|
||||||
|
"q@^1.5.1": "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7",
|
||||||
|
"quick-lru@^1.0.0": "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8",
|
||||||
|
"read-pkg-up@^1.0.1": "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02",
|
||||||
|
"read-pkg-up@^3.0.0": "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07",
|
||||||
|
"read-pkg@^1.0.0": "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28",
|
||||||
|
"read-pkg@^3.0.0": "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389",
|
||||||
|
"readable-stream@2 || 3": "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc",
|
||||||
|
"readable-stream@^3.0.2": "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc",
|
||||||
|
"readable-stream@~2.3.6": "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf",
|
||||||
|
"redent@^1.0.0": "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde",
|
||||||
|
"redent@^2.0.0": "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa",
|
||||||
|
"repeating@^2.0.0": "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda",
|
||||||
|
"resolve@^1.10.0": "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6",
|
||||||
|
"safe-buffer@~5.1.0": "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d",
|
||||||
|
"safe-buffer@~5.1.1": "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d",
|
||||||
|
"safe-buffer@~5.2.0": "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519",
|
||||||
|
"semver@2 || 3 || 4 || 5": "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7",
|
||||||
|
"semver@^6.0.0": "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d",
|
||||||
|
"signal-exit@^3.0.0": "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d",
|
||||||
|
"source-map@^0.6.1": "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263",
|
||||||
|
"source-map@~0.6.1": "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263",
|
||||||
|
"spdx-correct@^3.0.0": "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4",
|
||||||
|
"spdx-exceptions@^2.1.0": "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977",
|
||||||
|
"spdx-expression-parse@^3.0.0": "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0",
|
||||||
|
"spdx-license-ids@^3.0.0": "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654",
|
||||||
|
"split2@^2.0.0": "https://registry.yarnpkg.com/split2/-/split2-2.2.0.tgz#186b2575bcf83e85b7d18465756238ee4ee42493",
|
||||||
|
"split@^1.0.0": "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9",
|
||||||
|
"string_decoder@^1.1.1": "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e",
|
||||||
|
"string_decoder@~1.1.1": "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8",
|
||||||
|
"strip-bom@^2.0.0": "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e",
|
||||||
|
"strip-bom@^3.0.0": "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3",
|
||||||
|
"strip-indent@^1.0.1": "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2",
|
||||||
|
"strip-indent@^2.0.0": "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68",
|
||||||
|
"text-extensions@^1.0.0": "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26",
|
||||||
|
"through2@^2.0.0": "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd",
|
||||||
|
"through2@^2.0.2": "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd",
|
||||||
|
"through2@^3.0.0": "https://registry.yarnpkg.com/through2/-/through2-3.0.1.tgz#39276e713c3302edf9e388dd9c812dd3b825bd5a",
|
||||||
|
"through@2": "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5",
|
||||||
|
"through@>=2.2.7 <3": "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5",
|
||||||
|
"trim-newlines@^1.0.0": "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613",
|
||||||
|
"trim-newlines@^2.0.0": "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20",
|
||||||
|
"trim-off-newlines@^1.0.0": "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3",
|
||||||
|
"typedarray@^0.0.6": "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777",
|
||||||
|
"uglify-js@^3.1.4": "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.2.tgz#fd8048c86d990ddd29fe99d3300e0cb329103f4d",
|
||||||
|
"util-deprecate@^1.0.1": "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf",
|
||||||
|
"util-deprecate@~1.0.1": "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf",
|
||||||
|
"validate-npm-package-license@^3.0.1": "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a",
|
||||||
|
"wordwrap@~0.0.2": "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107",
|
||||||
|
"xtend@~4.0.1": "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54",
|
||||||
|
"yargs-parser@^10.0.0": "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8"
|
||||||
|
},
|
||||||
|
"files": [],
|
||||||
|
"artifacts": {}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,146 @@
|
||||||
|
# `@actions/core`
|
||||||
|
|
||||||
|
> Core functions for setting results, logging, registering secrets and exporting variables across actions
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Import the package
|
||||||
|
|
||||||
|
```js
|
||||||
|
// javascript
|
||||||
|
const core = require('@actions/core');
|
||||||
|
|
||||||
|
// typescript
|
||||||
|
import * as core from '@actions/core';
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Inputs/Outputs
|
||||||
|
|
||||||
|
Action inputs can be read with `getInput`. Outputs can be set with `setOutput` which makes them available to be mapped into inputs of other actions to ensure they are decoupled.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const myInput = core.getInput('inputName', { required: true });
|
||||||
|
|
||||||
|
core.setOutput('outputKey', 'outputVal');
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Exporting variables
|
||||||
|
|
||||||
|
Since each step runs in a separate process, you can use `exportVariable` to add it to this step and future steps environment blocks.
|
||||||
|
|
||||||
|
```js
|
||||||
|
core.exportVariable('envVar', 'Val');
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Setting a secret
|
||||||
|
|
||||||
|
Setting a secret registers the secret with the runner to ensure it is masked in logs.
|
||||||
|
|
||||||
|
```js
|
||||||
|
core.setSecret('myPassword');
|
||||||
|
```
|
||||||
|
|
||||||
|
#### PATH Manipulation
|
||||||
|
|
||||||
|
To make a tool's path available in the path for the remainder of the job (without altering the machine or containers state), use `addPath`. The runner will prepend the path given to the jobs PATH.
|
||||||
|
|
||||||
|
```js
|
||||||
|
core.addPath('/path/to/mytool');
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Exit codes
|
||||||
|
|
||||||
|
You should use this library to set the failing exit code for your action. If status is not set and the script runs to completion, that will lead to a success.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const core = require('@actions/core');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Do stuff
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
// setFailed logs the message and sets a failing exit code
|
||||||
|
core.setFailed(`Action failed with error ${err}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
Note that `setNeutral` is not yet implemented in actions V2 but equivalent functionality is being planned.
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Logging
|
||||||
|
|
||||||
|
Finally, this library provides some utilities for logging. Note that debug logging is hidden from the logs by default. This behavior can be toggled by enabling the [Step Debug Logs](../../docs/action-debugging.md#step-debug-logs).
|
||||||
|
|
||||||
|
```js
|
||||||
|
const core = require('@actions/core');
|
||||||
|
|
||||||
|
const myInput = core.getInput('input');
|
||||||
|
try {
|
||||||
|
core.debug('Inside try block');
|
||||||
|
|
||||||
|
if (!myInput) {
|
||||||
|
core.warning('myInput was not set');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (core.isDebug()) {
|
||||||
|
// curl -v https://github.com
|
||||||
|
} else {
|
||||||
|
// curl https://github.com
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do stuff
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
core.error(`Error ${err}, action may still succeed though`);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This library can also wrap chunks of output in foldable groups.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const core = require('@actions/core')
|
||||||
|
|
||||||
|
// Manually wrap output
|
||||||
|
core.startGroup('Do some function')
|
||||||
|
doSomeFunction()
|
||||||
|
core.endGroup()
|
||||||
|
|
||||||
|
// Wrap an asynchronous function call
|
||||||
|
const result = await core.group('Do something async', async () => {
|
||||||
|
const response = await doSomeHTTPRequest()
|
||||||
|
return response
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Action state
|
||||||
|
|
||||||
|
You can use this library to save state and get state for sharing information between a given wrapper action:
|
||||||
|
|
||||||
|
**action.yml**
|
||||||
|
```yaml
|
||||||
|
name: 'Wrapper action sample'
|
||||||
|
inputs:
|
||||||
|
name:
|
||||||
|
default: 'GitHub'
|
||||||
|
runs:
|
||||||
|
using: 'node12'
|
||||||
|
main: 'main.js'
|
||||||
|
post: 'cleanup.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
In action's `main.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const core = require('@actions/core');
|
||||||
|
|
||||||
|
core.saveState("pidToKill", 12345);
|
||||||
|
```
|
||||||
|
|
||||||
|
In action's `cleanup.js`:
|
||||||
|
```js
|
||||||
|
const core = require('@actions/core');
|
||||||
|
|
||||||
|
var pid = core.getState("pidToKill");
|
||||||
|
|
||||||
|
process.kill(pid);
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
interface CommandProperties {
|
||||||
|
[key: string]: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Commands
|
||||||
|
*
|
||||||
|
* Command Format:
|
||||||
|
* ::name key=value,key=value::message
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
* ::warning::This is the message
|
||||||
|
* ::set-env name=MY_VAR::some value
|
||||||
|
*/
|
||||||
|
export declare function issueCommand(command: string, properties: CommandProperties, message: string): void;
|
||||||
|
export declare function issue(name: string, message?: string): void;
|
||||||
|
export {};
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
"use strict";
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||||
|
result["default"] = mod;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const os = __importStar(require("os"));
|
||||||
|
/**
|
||||||
|
* Commands
|
||||||
|
*
|
||||||
|
* Command Format:
|
||||||
|
* ::name key=value,key=value::message
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
* ::warning::This is the message
|
||||||
|
* ::set-env name=MY_VAR::some value
|
||||||
|
*/
|
||||||
|
function issueCommand(command, properties, message) {
|
||||||
|
const cmd = new Command(command, properties, message);
|
||||||
|
process.stdout.write(cmd.toString() + os.EOL);
|
||||||
|
}
|
||||||
|
exports.issueCommand = issueCommand;
|
||||||
|
function issue(name, message = '') {
|
||||||
|
issueCommand(name, {}, message);
|
||||||
|
}
|
||||||
|
exports.issue = issue;
|
||||||
|
const CMD_STRING = '::';
|
||||||
|
class Command {
|
||||||
|
constructor(command, properties, message) {
|
||||||
|
if (!command) {
|
||||||
|
command = 'missing.command';
|
||||||
|
}
|
||||||
|
this.command = command;
|
||||||
|
this.properties = properties;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
toString() {
|
||||||
|
let cmdStr = CMD_STRING + this.command;
|
||||||
|
if (this.properties && Object.keys(this.properties).length > 0) {
|
||||||
|
cmdStr += ' ';
|
||||||
|
let first = true;
|
||||||
|
for (const key in this.properties) {
|
||||||
|
if (this.properties.hasOwnProperty(key)) {
|
||||||
|
const val = this.properties[key];
|
||||||
|
if (val) {
|
||||||
|
if (first) {
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cmdStr += ',';
|
||||||
|
}
|
||||||
|
cmdStr += `${key}=${escapeProperty(val)}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cmdStr += `${CMD_STRING}${escapeData(this.message)}`;
|
||||||
|
return cmdStr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function escapeData(s) {
|
||||||
|
return (s || '')
|
||||||
|
.replace(/%/g, '%25')
|
||||||
|
.replace(/\r/g, '%0D')
|
||||||
|
.replace(/\n/g, '%0A');
|
||||||
|
}
|
||||||
|
function escapeProperty(s) {
|
||||||
|
return (s || '')
|
||||||
|
.replace(/%/g, '%25')
|
||||||
|
.replace(/\r/g, '%0D')
|
||||||
|
.replace(/\n/g, '%0A')
|
||||||
|
.replace(/:/g, '%3A')
|
||||||
|
.replace(/,/g, '%2C');
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=command.js.map
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"command.js","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":";;;;;;;;;AAAA,uCAAwB;AAQxB;;;;;;;;;GASG;AACH,SAAgB,YAAY,CAC1B,OAAe,EACf,UAA6B,EAC7B,OAAe;IAEf,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAA;IACrD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAA;AAC/C,CAAC;AAPD,oCAOC;AAED,SAAgB,KAAK,CAAC,IAAY,EAAE,UAAkB,EAAE;IACtD,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,OAAO,CAAC,CAAA;AACjC,CAAC;AAFD,sBAEC;AAED,MAAM,UAAU,GAAG,IAAI,CAAA;AAEvB,MAAM,OAAO;IAKX,YAAY,OAAe,EAAE,UAA6B,EAAE,OAAe;QACzE,IAAI,CAAC,OAAO,EAAE;YACZ,OAAO,GAAG,iBAAiB,CAAA;SAC5B;QAED,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;QAC5B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;IAED,QAAQ;QACN,IAAI,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC,OAAO,CAAA;QAEtC,IAAI,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;YAC9D,MAAM,IAAI,GAAG,CAAA;YACb,IAAI,KAAK,GAAG,IAAI,CAAA;YAChB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,UAAU,EAAE;gBACjC,IAAI,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE;oBACvC,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;oBAChC,IAAI,GAAG,EAAE;wBACP,IAAI,KAAK,EAAE;4BACT,KAAK,GAAG,KAAK,CAAA;yBACd;6BAAM;4BACL,MAAM,IAAI,GAAG,CAAA;yBACd;wBAED,MAAM,IAAI,GAAG,GAAG,IAAI,cAAc,CAAC,GAAG,CAAC,EAAE,CAAA;qBAC1C;iBACF;aACF;SACF;QAED,MAAM,IAAI,GAAG,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAA;QACpD,OAAO,MAAM,CAAA;IACf,CAAC;CACF;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;SACb,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;AAC1B,CAAC;AAED,SAAS,cAAc,CAAC,CAAS;IAC/B,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;SACb,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;AACzB,CAAC"}
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
/**
|
||||||
|
* Interface for getInput options
|
||||||
|
*/
|
||||||
|
export interface InputOptions {
|
||||||
|
/** Optional. Whether the input is required. If required and not present, will throw. Defaults to false */
|
||||||
|
required?: boolean;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The code to exit an action
|
||||||
|
*/
|
||||||
|
export declare enum ExitCode {
|
||||||
|
/**
|
||||||
|
* A code indicating that the action was successful
|
||||||
|
*/
|
||||||
|
Success = 0,
|
||||||
|
/**
|
||||||
|
* A code indicating that the action was a failure
|
||||||
|
*/
|
||||||
|
Failure = 1
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Sets env variable for this action and future actions in the job
|
||||||
|
* @param name the name of the variable to set
|
||||||
|
* @param val the value of the variable
|
||||||
|
*/
|
||||||
|
export declare function exportVariable(name: string, val: string): void;
|
||||||
|
/**
|
||||||
|
* Registers a secret which will get masked from logs
|
||||||
|
* @param secret value of the secret
|
||||||
|
*/
|
||||||
|
export declare function setSecret(secret: string): void;
|
||||||
|
/**
|
||||||
|
* Prepends inputPath to the PATH (for this action and future actions)
|
||||||
|
* @param inputPath
|
||||||
|
*/
|
||||||
|
export declare function addPath(inputPath: string): void;
|
||||||
|
/**
|
||||||
|
* Gets the value of an input. The value is also trimmed.
|
||||||
|
*
|
||||||
|
* @param name name of the input to get
|
||||||
|
* @param options optional. See InputOptions.
|
||||||
|
* @returns string
|
||||||
|
*/
|
||||||
|
export declare function getInput(name: string, options?: InputOptions): string;
|
||||||
|
/**
|
||||||
|
* Sets the value of an output.
|
||||||
|
*
|
||||||
|
* @param name name of the output to set
|
||||||
|
* @param value value to store
|
||||||
|
*/
|
||||||
|
export declare function setOutput(name: string, value: string): void;
|
||||||
|
/**
|
||||||
|
* Sets the action status to failed.
|
||||||
|
* When the action exits it will be with an exit code of 1
|
||||||
|
* @param message add error issue message
|
||||||
|
*/
|
||||||
|
export declare function setFailed(message: string): void;
|
||||||
|
/**
|
||||||
|
* Gets whether Actions Step Debug is on or not
|
||||||
|
*/
|
||||||
|
export declare function isDebug(): boolean;
|
||||||
|
/**
|
||||||
|
* Writes debug message to user log
|
||||||
|
* @param message debug message
|
||||||
|
*/
|
||||||
|
export declare function debug(message: string): void;
|
||||||
|
/**
|
||||||
|
* Adds an error issue
|
||||||
|
* @param message error issue message
|
||||||
|
*/
|
||||||
|
export declare function error(message: string): void;
|
||||||
|
/**
|
||||||
|
* Adds an warning issue
|
||||||
|
* @param message warning issue message
|
||||||
|
*/
|
||||||
|
export declare function warning(message: string): void;
|
||||||
|
/**
|
||||||
|
* Writes info to log with console.log.
|
||||||
|
* @param message info message
|
||||||
|
*/
|
||||||
|
export declare function info(message: string): void;
|
||||||
|
/**
|
||||||
|
* Begin an output group.
|
||||||
|
*
|
||||||
|
* Output until the next `groupEnd` will be foldable in this group
|
||||||
|
*
|
||||||
|
* @param name The name of the output group
|
||||||
|
*/
|
||||||
|
export declare function startGroup(name: string): void;
|
||||||
|
/**
|
||||||
|
* End an output group.
|
||||||
|
*/
|
||||||
|
export declare function endGroup(): void;
|
||||||
|
/**
|
||||||
|
* Wrap an asynchronous function call in a group.
|
||||||
|
*
|
||||||
|
* Returns the same type as the function itself.
|
||||||
|
*
|
||||||
|
* @param name The name of the group
|
||||||
|
* @param fn The function to wrap in the group
|
||||||
|
*/
|
||||||
|
export declare function group<T>(name: string, fn: () => Promise<T>): Promise<T>;
|
||||||
|
/**
|
||||||
|
* Saves state for current action, the state can only be retrieved by this action's post job execution.
|
||||||
|
*
|
||||||
|
* @param name name of the state to store
|
||||||
|
* @param value value to store
|
||||||
|
*/
|
||||||
|
export declare function saveState(name: string, value: string): void;
|
||||||
|
/**
|
||||||
|
* Gets the value of an state set by this action's main execution.
|
||||||
|
*
|
||||||
|
* @param name name of the state to get
|
||||||
|
* @returns string
|
||||||
|
*/
|
||||||
|
export declare function getState(name: string): string;
|
||||||
|
|
@ -0,0 +1,209 @@
|
||||||
|
"use strict";
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||||
|
result["default"] = mod;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const command_1 = require("./command");
|
||||||
|
const os = __importStar(require("os"));
|
||||||
|
const path = __importStar(require("path"));
|
||||||
|
/**
|
||||||
|
* The code to exit an action
|
||||||
|
*/
|
||||||
|
var ExitCode;
|
||||||
|
(function (ExitCode) {
|
||||||
|
/**
|
||||||
|
* A code indicating that the action was successful
|
||||||
|
*/
|
||||||
|
ExitCode[ExitCode["Success"] = 0] = "Success";
|
||||||
|
/**
|
||||||
|
* A code indicating that the action was a failure
|
||||||
|
*/
|
||||||
|
ExitCode[ExitCode["Failure"] = 1] = "Failure";
|
||||||
|
})(ExitCode = exports.ExitCode || (exports.ExitCode = {}));
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// Variables
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* Sets env variable for this action and future actions in the job
|
||||||
|
* @param name the name of the variable to set
|
||||||
|
* @param val the value of the variable
|
||||||
|
*/
|
||||||
|
function exportVariable(name, val) {
|
||||||
|
process.env[name] = val;
|
||||||
|
command_1.issueCommand('set-env', { name }, val);
|
||||||
|
}
|
||||||
|
exports.exportVariable = exportVariable;
|
||||||
|
/**
|
||||||
|
* Registers a secret which will get masked from logs
|
||||||
|
* @param secret value of the secret
|
||||||
|
*/
|
||||||
|
function setSecret(secret) {
|
||||||
|
command_1.issueCommand('add-mask', {}, secret);
|
||||||
|
}
|
||||||
|
exports.setSecret = setSecret;
|
||||||
|
/**
|
||||||
|
* Prepends inputPath to the PATH (for this action and future actions)
|
||||||
|
* @param inputPath
|
||||||
|
*/
|
||||||
|
function addPath(inputPath) {
|
||||||
|
command_1.issueCommand('add-path', {}, inputPath);
|
||||||
|
process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`;
|
||||||
|
}
|
||||||
|
exports.addPath = addPath;
|
||||||
|
/**
|
||||||
|
* Gets the value of an input. The value is also trimmed.
|
||||||
|
*
|
||||||
|
* @param name name of the input to get
|
||||||
|
* @param options optional. See InputOptions.
|
||||||
|
* @returns string
|
||||||
|
*/
|
||||||
|
function getInput(name, options) {
|
||||||
|
const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || '';
|
||||||
|
if (options && options.required && !val) {
|
||||||
|
throw new Error(`Input required and not supplied: ${name}`);
|
||||||
|
}
|
||||||
|
return val.trim();
|
||||||
|
}
|
||||||
|
exports.getInput = getInput;
|
||||||
|
/**
|
||||||
|
* Sets the value of an output.
|
||||||
|
*
|
||||||
|
* @param name name of the output to set
|
||||||
|
* @param value value to store
|
||||||
|
*/
|
||||||
|
function setOutput(name, value) {
|
||||||
|
command_1.issueCommand('set-output', { name }, value);
|
||||||
|
}
|
||||||
|
exports.setOutput = setOutput;
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// Results
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* Sets the action status to failed.
|
||||||
|
* When the action exits it will be with an exit code of 1
|
||||||
|
* @param message add error issue message
|
||||||
|
*/
|
||||||
|
function setFailed(message) {
|
||||||
|
process.exitCode = ExitCode.Failure;
|
||||||
|
error(message);
|
||||||
|
}
|
||||||
|
exports.setFailed = setFailed;
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// Logging Commands
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* Gets whether Actions Step Debug is on or not
|
||||||
|
*/
|
||||||
|
function isDebug() {
|
||||||
|
return process.env['RUNNER_DEBUG'] === '1';
|
||||||
|
}
|
||||||
|
exports.isDebug = isDebug;
|
||||||
|
/**
|
||||||
|
* Writes debug message to user log
|
||||||
|
* @param message debug message
|
||||||
|
*/
|
||||||
|
function debug(message) {
|
||||||
|
command_1.issueCommand('debug', {}, message);
|
||||||
|
}
|
||||||
|
exports.debug = debug;
|
||||||
|
/**
|
||||||
|
* Adds an error issue
|
||||||
|
* @param message error issue message
|
||||||
|
*/
|
||||||
|
function error(message) {
|
||||||
|
command_1.issue('error', message);
|
||||||
|
}
|
||||||
|
exports.error = error;
|
||||||
|
/**
|
||||||
|
* Adds an warning issue
|
||||||
|
* @param message warning issue message
|
||||||
|
*/
|
||||||
|
function warning(message) {
|
||||||
|
command_1.issue('warning', message);
|
||||||
|
}
|
||||||
|
exports.warning = warning;
|
||||||
|
/**
|
||||||
|
* Writes info to log with console.log.
|
||||||
|
* @param message info message
|
||||||
|
*/
|
||||||
|
function info(message) {
|
||||||
|
process.stdout.write(message + os.EOL);
|
||||||
|
}
|
||||||
|
exports.info = info;
|
||||||
|
/**
|
||||||
|
* Begin an output group.
|
||||||
|
*
|
||||||
|
* Output until the next `groupEnd` will be foldable in this group
|
||||||
|
*
|
||||||
|
* @param name The name of the output group
|
||||||
|
*/
|
||||||
|
function startGroup(name) {
|
||||||
|
command_1.issue('group', name);
|
||||||
|
}
|
||||||
|
exports.startGroup = startGroup;
|
||||||
|
/**
|
||||||
|
* End an output group.
|
||||||
|
*/
|
||||||
|
function endGroup() {
|
||||||
|
command_1.issue('endgroup');
|
||||||
|
}
|
||||||
|
exports.endGroup = endGroup;
|
||||||
|
/**
|
||||||
|
* Wrap an asynchronous function call in a group.
|
||||||
|
*
|
||||||
|
* Returns the same type as the function itself.
|
||||||
|
*
|
||||||
|
* @param name The name of the group
|
||||||
|
* @param fn The function to wrap in the group
|
||||||
|
*/
|
||||||
|
function group(name, fn) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
startGroup(name);
|
||||||
|
let result;
|
||||||
|
try {
|
||||||
|
result = yield fn();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
endGroup();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.group = group;
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// Wrapper action state
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* Saves state for current action, the state can only be retrieved by this action's post job execution.
|
||||||
|
*
|
||||||
|
* @param name name of the state to store
|
||||||
|
* @param value value to store
|
||||||
|
*/
|
||||||
|
function saveState(name, value) {
|
||||||
|
command_1.issueCommand('save-state', { name }, value);
|
||||||
|
}
|
||||||
|
exports.saveState = saveState;
|
||||||
|
/**
|
||||||
|
* Gets the value of an state set by this action's main execution.
|
||||||
|
*
|
||||||
|
* @param name name of the state to get
|
||||||
|
* @returns string
|
||||||
|
*/
|
||||||
|
function getState(name) {
|
||||||
|
return process.env[`STATE_${name}`] || '';
|
||||||
|
}
|
||||||
|
exports.getState = getState;
|
||||||
|
//# sourceMappingURL=core.js.map
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,uCAA6C;AAE7C,uCAAwB;AACxB,2CAA4B;AAU5B;;GAEG;AACH,IAAY,QAUX;AAVD,WAAY,QAAQ;IAClB;;OAEG;IACH,6CAAW,CAAA;IAEX;;OAEG;IACH,6CAAW,CAAA;AACb,CAAC,EAVW,QAAQ,GAAR,gBAAQ,KAAR,gBAAQ,QAUnB;AAED,yEAAyE;AACzE,YAAY;AACZ,yEAAyE;AAEzE;;;;GAIG;AACH,SAAgB,cAAc,CAAC,IAAY,EAAE,GAAW;IACtD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,CAAA;IACvB,sBAAY,CAAC,SAAS,EAAE,EAAC,IAAI,EAAC,EAAE,GAAG,CAAC,CAAA;AACtC,CAAC;AAHD,wCAGC;AAED;;;GAGG;AACH,SAAgB,SAAS,CAAC,MAAc;IACtC,sBAAY,CAAC,UAAU,EAAE,EAAE,EAAE,MAAM,CAAC,CAAA;AACtC,CAAC;AAFD,8BAEC;AAED;;;GAGG;AACH,SAAgB,OAAO,CAAC,SAAiB;IACvC,sBAAY,CAAC,UAAU,EAAE,EAAE,EAAE,SAAS,CAAC,CAAA;IACvC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,GAAG,SAAS,GAAG,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAA;AAC7E,CAAC;AAHD,0BAGC;AAED;;;;;;GAMG;AACH,SAAgB,QAAQ,CAAC,IAAY,EAAE,OAAsB;IAC3D,MAAM,GAAG,GACP,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,IAAI,EAAE,CAAA;IACrE,IAAI,OAAO,IAAI,OAAO,CAAC,QAAQ,IAAI,CAAC,GAAG,EAAE;QACvC,MAAM,IAAI,KAAK,CAAC,oCAAoC,IAAI,EAAE,CAAC,CAAA;KAC5D;IAED,OAAO,GAAG,CAAC,IAAI,EAAE,CAAA;AACnB,CAAC;AARD,4BAQC;AAED;;;;;GAKG;AACH,SAAgB,SAAS,CAAC,IAAY,EAAE,KAAa;IACnD,sBAAY,CAAC,YAAY,EAAE,EAAC,IAAI,EAAC,EAAE,KAAK,CAAC,CAAA;AAC3C,CAAC;AAFD,8BAEC;AAED,yEAAyE;AACzE,UAAU;AACV,yEAAyE;AAEzE;;;;GAIG;AACH,SAAgB,SAAS,CAAC,OAAe;IACvC,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAA;IACnC,KAAK,CAAC,OAAO,CAAC,CAAA;AAChB,CAAC;AAHD,8BAGC;AAED,yEAAyE;AACzE,mBAAmB;AACnB,yEAAyE;AAEzE;;GAEG;AACH,SAAgB,OAAO;IACrB,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,GAAG,CAAA;AAC5C,CAAC;AAFD,0BAEC;AAED;;;GAGG;AACH,SAAgB,KAAK,CAAC,OAAe;IACnC,sBAAY,CAAC,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,CAAA;AACpC,CAAC;AAFD,sBAEC;AAED;;;GAGG;AACH,SAAgB,KAAK,CAAC,OAAe;IACnC,eAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AACzB,CAAC;AAFD,sBAEC;AAED;;;GAGG;AACH,SAAgB,OAAO,CAAC,OAAe;IACrC,eAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;AAC3B,CAAC;AAFD,0BAEC;AAED;;;GAGG;AACH,SAAgB,IAAI,CAAC,OAAe;IAClC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,CAAA;AACxC,CAAC;AAFD,oBAEC;AAED;;;;;;GAMG;AACH,SAAgB,UAAU,CAAC,IAAY;IACrC,eAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;AACtB,CAAC;AAFD,gCAEC;AAED;;GAEG;AACH,SAAgB,QAAQ;IACtB,eAAK,CAAC,UAAU,CAAC,CAAA;AACnB,CAAC;AAFD,4BAEC;AAED;;;;;;;GAOG;AACH,SAAsB,KAAK,CAAI,IAAY,EAAE,EAAoB;;QAC/D,UAAU,CAAC,IAAI,CAAC,CAAA;QAEhB,IAAI,MAAS,CAAA;QAEb,IAAI;YACF,MAAM,GAAG,MAAM,EAAE,EAAE,CAAA;SACpB;gBAAS;YACR,QAAQ,EAAE,CAAA;SACX;QAED,OAAO,MAAM,CAAA;IACf,CAAC;CAAA;AAZD,sBAYC;AAED,yEAAyE;AACzE,uBAAuB;AACvB,yEAAyE;AAEzE;;;;;GAKG;AACH,SAAgB,SAAS,CAAC,IAAY,EAAE,KAAa;IACnD,sBAAY,CAAC,YAAY,EAAE,EAAC,IAAI,EAAC,EAAE,KAAK,CAAC,CAAA;AAC3C,CAAC;AAFD,8BAEC;AAED;;;;;GAKG;AACH,SAAgB,QAAQ,CAAC,IAAY;IACnC,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,IAAI,EAAE,CAAA;AAC3C,CAAC;AAFD,4BAEC"}
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
{
|
||||||
|
"name": "@actions/core",
|
||||||
|
"version": "1.2.3",
|
||||||
|
"description": "Actions core lib",
|
||||||
|
"keywords": [
|
||||||
|
"github",
|
||||||
|
"actions",
|
||||||
|
"core"
|
||||||
|
],
|
||||||
|
"homepage": "https://github.com/actions/toolkit/tree/master/packages/core",
|
||||||
|
"license": "MIT",
|
||||||
|
"main": "lib/core.js",
|
||||||
|
"types": "lib/core.d.ts",
|
||||||
|
"directories": {
|
||||||
|
"lib": "lib",
|
||||||
|
"test": "__tests__"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"lib"
|
||||||
|
],
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/actions/toolkit.git",
|
||||||
|
"directory": "packages/core"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"audit-moderate": "npm install && npm audit --audit-level=moderate",
|
||||||
|
"test": "echo \"Error: run tests from root\" && exit 1",
|
||||||
|
"tsc": "tsc"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/actions/toolkit/issues"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^12.0.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
# `@actions/exec`
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
#### Basic
|
||||||
|
|
||||||
|
You can use this package to execute tools in a cross platform way:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const exec = require('@actions/exec');
|
||||||
|
|
||||||
|
await exec.exec('node index.js');
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Args
|
||||||
|
|
||||||
|
You can also pass in arg arrays:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const exec = require('@actions/exec');
|
||||||
|
|
||||||
|
await exec.exec('node', ['index.js', 'foo=bar']);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Output/options
|
||||||
|
|
||||||
|
Capture output or specify [other options](https://github.com/actions/toolkit/blob/d9347d4ab99fd507c0b9104b2cf79fb44fcc827d/packages/exec/src/interfaces.ts#L5):
|
||||||
|
|
||||||
|
```js
|
||||||
|
const exec = require('@actions/exec');
|
||||||
|
|
||||||
|
let myOutput = '';
|
||||||
|
let myError = '';
|
||||||
|
|
||||||
|
const options = {};
|
||||||
|
options.listeners = {
|
||||||
|
stdout: (data: Buffer) => {
|
||||||
|
myOutput += data.toString();
|
||||||
|
},
|
||||||
|
stderr: (data: Buffer) => {
|
||||||
|
myError += data.toString();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
options.cwd = './lib';
|
||||||
|
|
||||||
|
await exec.exec('node', ['index.js', 'foo=bar'], options);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Exec tools not in the PATH
|
||||||
|
|
||||||
|
You can specify the full path for tools not in the PATH:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const exec = require('@actions/exec');
|
||||||
|
|
||||||
|
await exec.exec('"/path/to/my-tool"', ['arg1']);
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { ExecOptions } from './interfaces';
|
||||||
|
export { ExecOptions };
|
||||||
|
/**
|
||||||
|
* Exec a command.
|
||||||
|
* Output will be streamed to the live console.
|
||||||
|
* Returns promise with return code
|
||||||
|
*
|
||||||
|
* @param commandLine command to execute (can include additional args). Must be correctly escaped.
|
||||||
|
* @param args optional arguments for tool. Escaping is handled by the lib.
|
||||||
|
* @param options optional exec options. See ExecOptions
|
||||||
|
* @returns Promise<number> exit code
|
||||||
|
*/
|
||||||
|
export declare function exec(commandLine: string, args?: string[], options?: ExecOptions): Promise<number>;
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
"use strict";
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||||
|
result["default"] = mod;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const tr = __importStar(require("./toolrunner"));
|
||||||
|
/**
|
||||||
|
* Exec a command.
|
||||||
|
* Output will be streamed to the live console.
|
||||||
|
* Returns promise with return code
|
||||||
|
*
|
||||||
|
* @param commandLine command to execute (can include additional args). Must be correctly escaped.
|
||||||
|
* @param args optional arguments for tool. Escaping is handled by the lib.
|
||||||
|
* @param options optional exec options. See ExecOptions
|
||||||
|
* @returns Promise<number> exit code
|
||||||
|
*/
|
||||||
|
function exec(commandLine, args, options) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
const commandArgs = tr.argStringToArray(commandLine);
|
||||||
|
if (commandArgs.length === 0) {
|
||||||
|
throw new Error(`Parameter 'commandLine' cannot be null or empty.`);
|
||||||
|
}
|
||||||
|
// Path to tool to execute should be first arg
|
||||||
|
const toolPath = commandArgs[0];
|
||||||
|
args = commandArgs.slice(1).concat(args || []);
|
||||||
|
const runner = new tr.ToolRunner(toolPath, args, options);
|
||||||
|
return runner.exec();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.exec = exec;
|
||||||
|
//# sourceMappingURL=exec.js.map
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../src/exec.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AACA,iDAAkC;AAIlC;;;;;;;;;GASG;AACH,SAAsB,IAAI,CACxB,WAAmB,EACnB,IAAe,EACf,OAAqB;;QAErB,MAAM,WAAW,GAAG,EAAE,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAA;QACpD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE;YAC5B,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAA;SACpE;QACD,8CAA8C;QAC9C,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,CAAA;QAC/B,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAA;QAC9C,MAAM,MAAM,GAAkB,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;QACxE,OAAO,MAAM,CAAC,IAAI,EAAE,CAAA;IACtB,CAAC;CAAA;AAdD,oBAcC"}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
/// <reference types="node" />
|
||||||
|
import * as stream from 'stream';
|
||||||
|
/**
|
||||||
|
* Interface for exec options
|
||||||
|
*/
|
||||||
|
export interface ExecOptions {
|
||||||
|
/** optional working directory. defaults to current */
|
||||||
|
cwd?: string;
|
||||||
|
/** optional envvar dictionary. defaults to current process's env */
|
||||||
|
env?: {
|
||||||
|
[key: string]: string;
|
||||||
|
};
|
||||||
|
/** optional. defaults to false */
|
||||||
|
silent?: boolean;
|
||||||
|
/** optional out stream to use. Defaults to process.stdout */
|
||||||
|
outStream?: stream.Writable;
|
||||||
|
/** optional err stream to use. Defaults to process.stderr */
|
||||||
|
errStream?: stream.Writable;
|
||||||
|
/** optional. whether to skip quoting/escaping arguments if needed. defaults to false. */
|
||||||
|
windowsVerbatimArguments?: boolean;
|
||||||
|
/** optional. whether to fail if output to stderr. defaults to false */
|
||||||
|
failOnStdErr?: boolean;
|
||||||
|
/** optional. defaults to failing on non zero. ignore will not fail leaving it up to the caller */
|
||||||
|
ignoreReturnCode?: boolean;
|
||||||
|
/** optional. How long in ms to wait for STDIO streams to close after the exit event of the process before terminating. defaults to 10000 */
|
||||||
|
delay?: number;
|
||||||
|
/** optional. input to write to the process on STDIN. */
|
||||||
|
input?: Buffer;
|
||||||
|
/** optional. Listeners for output. Callback functions that will be called on these events */
|
||||||
|
listeners?: {
|
||||||
|
stdout?: (data: Buffer) => void;
|
||||||
|
stderr?: (data: Buffer) => void;
|
||||||
|
stdline?: (data: string) => void;
|
||||||
|
errline?: (data: string) => void;
|
||||||
|
debug?: (data: string) => void;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
//# sourceMappingURL=interfaces.js.map
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":""}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
/// <reference types="node" />
|
||||||
|
import * as events from 'events';
|
||||||
|
import * as im from './interfaces';
|
||||||
|
export declare class ToolRunner extends events.EventEmitter {
|
||||||
|
constructor(toolPath: string, args?: string[], options?: im.ExecOptions);
|
||||||
|
private toolPath;
|
||||||
|
private args;
|
||||||
|
private options;
|
||||||
|
private _debug;
|
||||||
|
private _getCommandString;
|
||||||
|
private _processLineBuffer;
|
||||||
|
private _getSpawnFileName;
|
||||||
|
private _getSpawnArgs;
|
||||||
|
private _endsWith;
|
||||||
|
private _isCmdFile;
|
||||||
|
private _windowsQuoteCmdArg;
|
||||||
|
private _uvQuoteCmdArg;
|
||||||
|
private _cloneExecOptions;
|
||||||
|
private _getSpawnOptions;
|
||||||
|
/**
|
||||||
|
* Exec a tool.
|
||||||
|
* Output will be streamed to the live console.
|
||||||
|
* Returns promise with return code
|
||||||
|
*
|
||||||
|
* @param tool path to tool to exec
|
||||||
|
* @param options optional exec options. See ExecOptions
|
||||||
|
* @returns number
|
||||||
|
*/
|
||||||
|
exec(): Promise<number>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Convert an arg string to an array of args. Handles escaping
|
||||||
|
*
|
||||||
|
* @param argString string of arguments
|
||||||
|
* @returns string[] array of arguments
|
||||||
|
*/
|
||||||
|
export declare function argStringToArray(argString: string): string[];
|
||||||
|
|
@ -0,0 +1,600 @@
|
||||||
|
"use strict";
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||||
|
result["default"] = mod;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const os = __importStar(require("os"));
|
||||||
|
const events = __importStar(require("events"));
|
||||||
|
const child = __importStar(require("child_process"));
|
||||||
|
const path = __importStar(require("path"));
|
||||||
|
const io = __importStar(require("@actions/io"));
|
||||||
|
const ioUtil = __importStar(require("@actions/io/lib/io-util"));
|
||||||
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
|
const IS_WINDOWS = process.platform === 'win32';
|
||||||
|
/*
|
||||||
|
* Class for running command line tools. Handles quoting and arg parsing in a platform agnostic way.
|
||||||
|
*/
|
||||||
|
class ToolRunner extends events.EventEmitter {
|
||||||
|
constructor(toolPath, args, options) {
|
||||||
|
super();
|
||||||
|
if (!toolPath) {
|
||||||
|
throw new Error("Parameter 'toolPath' cannot be null or empty.");
|
||||||
|
}
|
||||||
|
this.toolPath = toolPath;
|
||||||
|
this.args = args || [];
|
||||||
|
this.options = options || {};
|
||||||
|
}
|
||||||
|
_debug(message) {
|
||||||
|
if (this.options.listeners && this.options.listeners.debug) {
|
||||||
|
this.options.listeners.debug(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_getCommandString(options, noPrefix) {
|
||||||
|
const toolPath = this._getSpawnFileName();
|
||||||
|
const args = this._getSpawnArgs(options);
|
||||||
|
let cmd = noPrefix ? '' : '[command]'; // omit prefix when piped to a second tool
|
||||||
|
if (IS_WINDOWS) {
|
||||||
|
// Windows + cmd file
|
||||||
|
if (this._isCmdFile()) {
|
||||||
|
cmd += toolPath;
|
||||||
|
for (const a of args) {
|
||||||
|
cmd += ` ${a}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Windows + verbatim
|
||||||
|
else if (options.windowsVerbatimArguments) {
|
||||||
|
cmd += `"${toolPath}"`;
|
||||||
|
for (const a of args) {
|
||||||
|
cmd += ` ${a}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Windows (regular)
|
||||||
|
else {
|
||||||
|
cmd += this._windowsQuoteCmdArg(toolPath);
|
||||||
|
for (const a of args) {
|
||||||
|
cmd += ` ${this._windowsQuoteCmdArg(a)}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// OSX/Linux - this can likely be improved with some form of quoting.
|
||||||
|
// creating processes on Unix is fundamentally different than Windows.
|
||||||
|
// on Unix, execvp() takes an arg array.
|
||||||
|
cmd += toolPath;
|
||||||
|
for (const a of args) {
|
||||||
|
cmd += ` ${a}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
_processLineBuffer(data, strBuffer, onLine) {
|
||||||
|
try {
|
||||||
|
let s = strBuffer + data.toString();
|
||||||
|
let n = s.indexOf(os.EOL);
|
||||||
|
while (n > -1) {
|
||||||
|
const line = s.substring(0, n);
|
||||||
|
onLine(line);
|
||||||
|
// the rest of the string ...
|
||||||
|
s = s.substring(n + os.EOL.length);
|
||||||
|
n = s.indexOf(os.EOL);
|
||||||
|
}
|
||||||
|
strBuffer = s;
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
// streaming lines to console is best effort. Don't fail a build.
|
||||||
|
this._debug(`error processing line. Failed with error ${err}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_getSpawnFileName() {
|
||||||
|
if (IS_WINDOWS) {
|
||||||
|
if (this._isCmdFile()) {
|
||||||
|
return process.env['COMSPEC'] || 'cmd.exe';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.toolPath;
|
||||||
|
}
|
||||||
|
_getSpawnArgs(options) {
|
||||||
|
if (IS_WINDOWS) {
|
||||||
|
if (this._isCmdFile()) {
|
||||||
|
let argline = `/D /S /C "${this._windowsQuoteCmdArg(this.toolPath)}`;
|
||||||
|
for (const a of this.args) {
|
||||||
|
argline += ' ';
|
||||||
|
argline += options.windowsVerbatimArguments
|
||||||
|
? a
|
||||||
|
: this._windowsQuoteCmdArg(a);
|
||||||
|
}
|
||||||
|
argline += '"';
|
||||||
|
return [argline];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.args;
|
||||||
|
}
|
||||||
|
_endsWith(str, end) {
|
||||||
|
return str.endsWith(end);
|
||||||
|
}
|
||||||
|
_isCmdFile() {
|
||||||
|
const upperToolPath = this.toolPath.toUpperCase();
|
||||||
|
return (this._endsWith(upperToolPath, '.CMD') ||
|
||||||
|
this._endsWith(upperToolPath, '.BAT'));
|
||||||
|
}
|
||||||
|
_windowsQuoteCmdArg(arg) {
|
||||||
|
// for .exe, apply the normal quoting rules that libuv applies
|
||||||
|
if (!this._isCmdFile()) {
|
||||||
|
return this._uvQuoteCmdArg(arg);
|
||||||
|
}
|
||||||
|
// otherwise apply quoting rules specific to the cmd.exe command line parser.
|
||||||
|
// the libuv rules are generic and are not designed specifically for cmd.exe
|
||||||
|
// command line parser.
|
||||||
|
//
|
||||||
|
// for a detailed description of the cmd.exe command line parser, refer to
|
||||||
|
// http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/7970912#7970912
|
||||||
|
// need quotes for empty arg
|
||||||
|
if (!arg) {
|
||||||
|
return '""';
|
||||||
|
}
|
||||||
|
// determine whether the arg needs to be quoted
|
||||||
|
const cmdSpecialChars = [
|
||||||
|
' ',
|
||||||
|
'\t',
|
||||||
|
'&',
|
||||||
|
'(',
|
||||||
|
')',
|
||||||
|
'[',
|
||||||
|
']',
|
||||||
|
'{',
|
||||||
|
'}',
|
||||||
|
'^',
|
||||||
|
'=',
|
||||||
|
';',
|
||||||
|
'!',
|
||||||
|
"'",
|
||||||
|
'+',
|
||||||
|
',',
|
||||||
|
'`',
|
||||||
|
'~',
|
||||||
|
'|',
|
||||||
|
'<',
|
||||||
|
'>',
|
||||||
|
'"'
|
||||||
|
];
|
||||||
|
let needsQuotes = false;
|
||||||
|
for (const char of arg) {
|
||||||
|
if (cmdSpecialChars.some(x => x === char)) {
|
||||||
|
needsQuotes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// short-circuit if quotes not needed
|
||||||
|
if (!needsQuotes) {
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
// the following quoting rules are very similar to the rules that by libuv applies.
|
||||||
|
//
|
||||||
|
// 1) wrap the string in quotes
|
||||||
|
//
|
||||||
|
// 2) double-up quotes - i.e. " => ""
|
||||||
|
//
|
||||||
|
// this is different from the libuv quoting rules. libuv replaces " with \", which unfortunately
|
||||||
|
// doesn't work well with a cmd.exe command line.
|
||||||
|
//
|
||||||
|
// note, replacing " with "" also works well if the arg is passed to a downstream .NET console app.
|
||||||
|
// for example, the command line:
|
||||||
|
// foo.exe "myarg:""my val"""
|
||||||
|
// is parsed by a .NET console app into an arg array:
|
||||||
|
// [ "myarg:\"my val\"" ]
|
||||||
|
// which is the same end result when applying libuv quoting rules. although the actual
|
||||||
|
// command line from libuv quoting rules would look like:
|
||||||
|
// foo.exe "myarg:\"my val\""
|
||||||
|
//
|
||||||
|
// 3) double-up slashes that precede a quote,
|
||||||
|
// e.g. hello \world => "hello \world"
|
||||||
|
// hello\"world => "hello\\""world"
|
||||||
|
// hello\\"world => "hello\\\\""world"
|
||||||
|
// hello world\ => "hello world\\"
|
||||||
|
//
|
||||||
|
// technically this is not required for a cmd.exe command line, or the batch argument parser.
|
||||||
|
// the reasons for including this as a .cmd quoting rule are:
|
||||||
|
//
|
||||||
|
// a) this is optimized for the scenario where the argument is passed from the .cmd file to an
|
||||||
|
// external program. many programs (e.g. .NET console apps) rely on the slash-doubling rule.
|
||||||
|
//
|
||||||
|
// b) it's what we've been doing previously (by deferring to node default behavior) and we
|
||||||
|
// haven't heard any complaints about that aspect.
|
||||||
|
//
|
||||||
|
// note, a weakness of the quoting rules chosen here, is that % is not escaped. in fact, % cannot be
|
||||||
|
// escaped when used on the command line directly - even though within a .cmd file % can be escaped
|
||||||
|
// by using %%.
|
||||||
|
//
|
||||||
|
// the saving grace is, on the command line, %var% is left as-is if var is not defined. this contrasts
|
||||||
|
// the line parsing rules within a .cmd file, where if var is not defined it is replaced with nothing.
|
||||||
|
//
|
||||||
|
// one option that was explored was replacing % with ^% - i.e. %var% => ^%var^%. this hack would
|
||||||
|
// often work, since it is unlikely that var^ would exist, and the ^ character is removed when the
|
||||||
|
// variable is used. the problem, however, is that ^ is not removed when %* is used to pass the args
|
||||||
|
// to an external program.
|
||||||
|
//
|
||||||
|
// an unexplored potential solution for the % escaping problem, is to create a wrapper .cmd file.
|
||||||
|
// % can be escaped within a .cmd file.
|
||||||
|
let reverse = '"';
|
||||||
|
let quoteHit = true;
|
||||||
|
for (let i = arg.length; i > 0; i--) {
|
||||||
|
// walk the string in reverse
|
||||||
|
reverse += arg[i - 1];
|
||||||
|
if (quoteHit && arg[i - 1] === '\\') {
|
||||||
|
reverse += '\\'; // double the slash
|
||||||
|
}
|
||||||
|
else if (arg[i - 1] === '"') {
|
||||||
|
quoteHit = true;
|
||||||
|
reverse += '"'; // double the quote
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
quoteHit = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reverse += '"';
|
||||||
|
return reverse
|
||||||
|
.split('')
|
||||||
|
.reverse()
|
||||||
|
.join('');
|
||||||
|
}
|
||||||
|
_uvQuoteCmdArg(arg) {
|
||||||
|
// Tool runner wraps child_process.spawn() and needs to apply the same quoting as
|
||||||
|
// Node in certain cases where the undocumented spawn option windowsVerbatimArguments
|
||||||
|
// is used.
|
||||||
|
//
|
||||||
|
// Since this function is a port of quote_cmd_arg from Node 4.x (technically, lib UV,
|
||||||
|
// see https://github.com/nodejs/node/blob/v4.x/deps/uv/src/win/process.c for details),
|
||||||
|
// pasting copyright notice from Node within this function:
|
||||||
|
//
|
||||||
|
// Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to
|
||||||
|
// deal in the Software without restriction, including without limitation the
|
||||||
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
// sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
// IN THE SOFTWARE.
|
||||||
|
if (!arg) {
|
||||||
|
// Need double quotation for empty argument
|
||||||
|
return '""';
|
||||||
|
}
|
||||||
|
if (!arg.includes(' ') && !arg.includes('\t') && !arg.includes('"')) {
|
||||||
|
// No quotation needed
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
if (!arg.includes('"') && !arg.includes('\\')) {
|
||||||
|
// No embedded double quotes or backslashes, so I can just wrap
|
||||||
|
// quote marks around the whole thing.
|
||||||
|
return `"${arg}"`;
|
||||||
|
}
|
||||||
|
// Expected input/output:
|
||||||
|
// input : hello"world
|
||||||
|
// output: "hello\"world"
|
||||||
|
// input : hello""world
|
||||||
|
// output: "hello\"\"world"
|
||||||
|
// input : hello\world
|
||||||
|
// output: hello\world
|
||||||
|
// input : hello\\world
|
||||||
|
// output: hello\\world
|
||||||
|
// input : hello\"world
|
||||||
|
// output: "hello\\\"world"
|
||||||
|
// input : hello\\"world
|
||||||
|
// output: "hello\\\\\"world"
|
||||||
|
// input : hello world\
|
||||||
|
// output: "hello world\\" - note the comment in libuv actually reads "hello world\"
|
||||||
|
// but it appears the comment is wrong, it should be "hello world\\"
|
||||||
|
let reverse = '"';
|
||||||
|
let quoteHit = true;
|
||||||
|
for (let i = arg.length; i > 0; i--) {
|
||||||
|
// walk the string in reverse
|
||||||
|
reverse += arg[i - 1];
|
||||||
|
if (quoteHit && arg[i - 1] === '\\') {
|
||||||
|
reverse += '\\';
|
||||||
|
}
|
||||||
|
else if (arg[i - 1] === '"') {
|
||||||
|
quoteHit = true;
|
||||||
|
reverse += '\\';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
quoteHit = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reverse += '"';
|
||||||
|
return reverse
|
||||||
|
.split('')
|
||||||
|
.reverse()
|
||||||
|
.join('');
|
||||||
|
}
|
||||||
|
_cloneExecOptions(options) {
|
||||||
|
options = options || {};
|
||||||
|
const result = {
|
||||||
|
cwd: options.cwd || process.cwd(),
|
||||||
|
env: options.env || process.env,
|
||||||
|
silent: options.silent || false,
|
||||||
|
windowsVerbatimArguments: options.windowsVerbatimArguments || false,
|
||||||
|
failOnStdErr: options.failOnStdErr || false,
|
||||||
|
ignoreReturnCode: options.ignoreReturnCode || false,
|
||||||
|
delay: options.delay || 10000
|
||||||
|
};
|
||||||
|
result.outStream = options.outStream || process.stdout;
|
||||||
|
result.errStream = options.errStream || process.stderr;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
_getSpawnOptions(options, toolPath) {
|
||||||
|
options = options || {};
|
||||||
|
const result = {};
|
||||||
|
result.cwd = options.cwd;
|
||||||
|
result.env = options.env;
|
||||||
|
result['windowsVerbatimArguments'] =
|
||||||
|
options.windowsVerbatimArguments || this._isCmdFile();
|
||||||
|
if (options.windowsVerbatimArguments) {
|
||||||
|
result.argv0 = `"${toolPath}"`;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Exec a tool.
|
||||||
|
* Output will be streamed to the live console.
|
||||||
|
* Returns promise with return code
|
||||||
|
*
|
||||||
|
* @param tool path to tool to exec
|
||||||
|
* @param options optional exec options. See ExecOptions
|
||||||
|
* @returns number
|
||||||
|
*/
|
||||||
|
exec() {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
// root the tool path if it is unrooted and contains relative pathing
|
||||||
|
if (!ioUtil.isRooted(this.toolPath) &&
|
||||||
|
(this.toolPath.includes('/') ||
|
||||||
|
(IS_WINDOWS && this.toolPath.includes('\\')))) {
|
||||||
|
// prefer options.cwd if it is specified, however options.cwd may also need to be rooted
|
||||||
|
this.toolPath = path.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath);
|
||||||
|
}
|
||||||
|
// if the tool is only a file name, then resolve it from the PATH
|
||||||
|
// otherwise verify it exists (add extension on Windows if necessary)
|
||||||
|
this.toolPath = yield io.which(this.toolPath, true);
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this._debug(`exec tool: ${this.toolPath}`);
|
||||||
|
this._debug('arguments:');
|
||||||
|
for (const arg of this.args) {
|
||||||
|
this._debug(` ${arg}`);
|
||||||
|
}
|
||||||
|
const optionsNonNull = this._cloneExecOptions(this.options);
|
||||||
|
if (!optionsNonNull.silent && optionsNonNull.outStream) {
|
||||||
|
optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL);
|
||||||
|
}
|
||||||
|
const state = new ExecState(optionsNonNull, this.toolPath);
|
||||||
|
state.on('debug', (message) => {
|
||||||
|
this._debug(message);
|
||||||
|
});
|
||||||
|
const fileName = this._getSpawnFileName();
|
||||||
|
const cp = child.spawn(fileName, this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(this.options, fileName));
|
||||||
|
const stdbuffer = '';
|
||||||
|
if (cp.stdout) {
|
||||||
|
cp.stdout.on('data', (data) => {
|
||||||
|
if (this.options.listeners && this.options.listeners.stdout) {
|
||||||
|
this.options.listeners.stdout(data);
|
||||||
|
}
|
||||||
|
if (!optionsNonNull.silent && optionsNonNull.outStream) {
|
||||||
|
optionsNonNull.outStream.write(data);
|
||||||
|
}
|
||||||
|
this._processLineBuffer(data, stdbuffer, (line) => {
|
||||||
|
if (this.options.listeners && this.options.listeners.stdline) {
|
||||||
|
this.options.listeners.stdline(line);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const errbuffer = '';
|
||||||
|
if (cp.stderr) {
|
||||||
|
cp.stderr.on('data', (data) => {
|
||||||
|
state.processStderr = true;
|
||||||
|
if (this.options.listeners && this.options.listeners.stderr) {
|
||||||
|
this.options.listeners.stderr(data);
|
||||||
|
}
|
||||||
|
if (!optionsNonNull.silent &&
|
||||||
|
optionsNonNull.errStream &&
|
||||||
|
optionsNonNull.outStream) {
|
||||||
|
const s = optionsNonNull.failOnStdErr
|
||||||
|
? optionsNonNull.errStream
|
||||||
|
: optionsNonNull.outStream;
|
||||||
|
s.write(data);
|
||||||
|
}
|
||||||
|
this._processLineBuffer(data, errbuffer, (line) => {
|
||||||
|
if (this.options.listeners && this.options.listeners.errline) {
|
||||||
|
this.options.listeners.errline(line);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
cp.on('error', (err) => {
|
||||||
|
state.processError = err.message;
|
||||||
|
state.processExited = true;
|
||||||
|
state.processClosed = true;
|
||||||
|
state.CheckComplete();
|
||||||
|
});
|
||||||
|
cp.on('exit', (code) => {
|
||||||
|
state.processExitCode = code;
|
||||||
|
state.processExited = true;
|
||||||
|
this._debug(`Exit code ${code} received from tool '${this.toolPath}'`);
|
||||||
|
state.CheckComplete();
|
||||||
|
});
|
||||||
|
cp.on('close', (code) => {
|
||||||
|
state.processExitCode = code;
|
||||||
|
state.processExited = true;
|
||||||
|
state.processClosed = true;
|
||||||
|
this._debug(`STDIO streams have closed for tool '${this.toolPath}'`);
|
||||||
|
state.CheckComplete();
|
||||||
|
});
|
||||||
|
state.on('done', (error, exitCode) => {
|
||||||
|
if (stdbuffer.length > 0) {
|
||||||
|
this.emit('stdline', stdbuffer);
|
||||||
|
}
|
||||||
|
if (errbuffer.length > 0) {
|
||||||
|
this.emit('errline', errbuffer);
|
||||||
|
}
|
||||||
|
cp.removeAllListeners();
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resolve(exitCode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (this.options.input) {
|
||||||
|
if (!cp.stdin) {
|
||||||
|
throw new Error('child process missing stdin');
|
||||||
|
}
|
||||||
|
cp.stdin.end(this.options.input);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.ToolRunner = ToolRunner;
|
||||||
|
/**
|
||||||
|
* Convert an arg string to an array of args. Handles escaping
|
||||||
|
*
|
||||||
|
* @param argString string of arguments
|
||||||
|
* @returns string[] array of arguments
|
||||||
|
*/
|
||||||
|
function argStringToArray(argString) {
|
||||||
|
const args = [];
|
||||||
|
let inQuotes = false;
|
||||||
|
let escaped = false;
|
||||||
|
let arg = '';
|
||||||
|
function append(c) {
|
||||||
|
// we only escape double quotes.
|
||||||
|
if (escaped && c !== '"') {
|
||||||
|
arg += '\\';
|
||||||
|
}
|
||||||
|
arg += c;
|
||||||
|
escaped = false;
|
||||||
|
}
|
||||||
|
for (let i = 0; i < argString.length; i++) {
|
||||||
|
const c = argString.charAt(i);
|
||||||
|
if (c === '"') {
|
||||||
|
if (!escaped) {
|
||||||
|
inQuotes = !inQuotes;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
append(c);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c === '\\' && escaped) {
|
||||||
|
append(c);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c === '\\' && inQuotes) {
|
||||||
|
escaped = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c === ' ' && !inQuotes) {
|
||||||
|
if (arg.length > 0) {
|
||||||
|
args.push(arg);
|
||||||
|
arg = '';
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
append(c);
|
||||||
|
}
|
||||||
|
if (arg.length > 0) {
|
||||||
|
args.push(arg.trim());
|
||||||
|
}
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
exports.argStringToArray = argStringToArray;
|
||||||
|
class ExecState extends events.EventEmitter {
|
||||||
|
constructor(options, toolPath) {
|
||||||
|
super();
|
||||||
|
this.processClosed = false; // tracks whether the process has exited and stdio is closed
|
||||||
|
this.processError = '';
|
||||||
|
this.processExitCode = 0;
|
||||||
|
this.processExited = false; // tracks whether the process has exited
|
||||||
|
this.processStderr = false; // tracks whether stderr was written to
|
||||||
|
this.delay = 10000; // 10 seconds
|
||||||
|
this.done = false;
|
||||||
|
this.timeout = null;
|
||||||
|
if (!toolPath) {
|
||||||
|
throw new Error('toolPath must not be empty');
|
||||||
|
}
|
||||||
|
this.options = options;
|
||||||
|
this.toolPath = toolPath;
|
||||||
|
if (options.delay) {
|
||||||
|
this.delay = options.delay;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CheckComplete() {
|
||||||
|
if (this.done) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.processClosed) {
|
||||||
|
this._setResult();
|
||||||
|
}
|
||||||
|
else if (this.processExited) {
|
||||||
|
this.timeout = setTimeout(ExecState.HandleTimeout, this.delay, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_debug(message) {
|
||||||
|
this.emit('debug', message);
|
||||||
|
}
|
||||||
|
_setResult() {
|
||||||
|
// determine whether there is an error
|
||||||
|
let error;
|
||||||
|
if (this.processExited) {
|
||||||
|
if (this.processError) {
|
||||||
|
error = new Error(`There was an error when attempting to execute the process '${this.toolPath}'. This may indicate the process failed to start. Error: ${this.processError}`);
|
||||||
|
}
|
||||||
|
else if (this.processExitCode !== 0 && !this.options.ignoreReturnCode) {
|
||||||
|
error = new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`);
|
||||||
|
}
|
||||||
|
else if (this.processStderr && this.options.failOnStdErr) {
|
||||||
|
error = new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// clear the timeout
|
||||||
|
if (this.timeout) {
|
||||||
|
clearTimeout(this.timeout);
|
||||||
|
this.timeout = null;
|
||||||
|
}
|
||||||
|
this.done = true;
|
||||||
|
this.emit('done', error, this.processExitCode);
|
||||||
|
}
|
||||||
|
static HandleTimeout(state) {
|
||||||
|
if (state.done) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!state.processClosed && state.processExited) {
|
||||||
|
const message = `The STDIO streams did not close within ${state.delay /
|
||||||
|
1000} seconds of the exit event from process '${state.toolPath}'. This may indicate a child process inherited the STDIO streams and has not yet exited.`;
|
||||||
|
state._debug(message);
|
||||||
|
}
|
||||||
|
state._setResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=toolrunner.js.map
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,40 @@
|
||||||
|
{
|
||||||
|
"name": "@actions/exec",
|
||||||
|
"version": "1.0.4",
|
||||||
|
"description": "Actions exec lib",
|
||||||
|
"keywords": [
|
||||||
|
"github",
|
||||||
|
"actions",
|
||||||
|
"exec"
|
||||||
|
],
|
||||||
|
"homepage": "https://github.com/actions/toolkit/tree/master/packages/exec",
|
||||||
|
"license": "MIT",
|
||||||
|
"main": "lib/exec.js",
|
||||||
|
"types": "lib/exec.d.ts",
|
||||||
|
"directories": {
|
||||||
|
"lib": "lib",
|
||||||
|
"test": "__tests__"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"lib"
|
||||||
|
],
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/actions/toolkit.git",
|
||||||
|
"directory": "packages/exec"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"audit-moderate": "npm install && npm audit --audit-level=moderate",
|
||||||
|
"test": "echo \"Error: run tests from root\" && exit 1",
|
||||||
|
"tsc": "tsc"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/actions/toolkit/issues"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@actions/io": "^1.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
# `@actions/io`
|
||||||
|
|
||||||
|
> Core functions for cli filesystem scenarios
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
#### mkdir -p
|
||||||
|
|
||||||
|
Recursively make a directory. Follows rules specified in [man mkdir](https://linux.die.net/man/1/mkdir) with the `-p` option specified:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const io = require('@actions/io');
|
||||||
|
|
||||||
|
await io.mkdirP('path/to/make');
|
||||||
|
```
|
||||||
|
|
||||||
|
#### cp/mv
|
||||||
|
|
||||||
|
Copy or move files or folders. Follows rules specified in [man cp](https://linux.die.net/man/1/cp) and [man mv](https://linux.die.net/man/1/mv):
|
||||||
|
|
||||||
|
```js
|
||||||
|
const io = require('@actions/io');
|
||||||
|
|
||||||
|
// Recursive must be true for directories
|
||||||
|
const options = { recursive: true, force: false }
|
||||||
|
|
||||||
|
await io.cp('path/to/directory', 'path/to/dest', options);
|
||||||
|
await io.mv('path/to/file', 'path/to/dest');
|
||||||
|
```
|
||||||
|
|
||||||
|
#### rm -rf
|
||||||
|
|
||||||
|
Remove a file or folder recursively. Follows rules specified in [man rm](https://linux.die.net/man/1/rm) with the `-r` and `-f` rules specified.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const io = require('@actions/io');
|
||||||
|
|
||||||
|
await io.rmRF('path/to/directory');
|
||||||
|
await io.rmRF('path/to/file');
|
||||||
|
```
|
||||||
|
|
||||||
|
#### which
|
||||||
|
|
||||||
|
Get the path to a tool and resolves via paths. Follows the rules specified in [man which](https://linux.die.net/man/1/which).
|
||||||
|
|
||||||
|
```js
|
||||||
|
const exec = require('@actions/exec');
|
||||||
|
const io = require('@actions/io');
|
||||||
|
|
||||||
|
const pythonPath: string = await io.which('python', true)
|
||||||
|
|
||||||
|
await exec.exec(`"${pythonPath}"`, ['main.py']);
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
/// <reference types="node" />
|
||||||
|
import * as fs from 'fs';
|
||||||
|
export declare const chmod: typeof fs.promises.chmod, copyFile: typeof fs.promises.copyFile, lstat: typeof fs.promises.lstat, mkdir: typeof fs.promises.mkdir, readdir: typeof fs.promises.readdir, readlink: typeof fs.promises.readlink, rename: typeof fs.promises.rename, rmdir: typeof fs.promises.rmdir, stat: typeof fs.promises.stat, symlink: typeof fs.promises.symlink, unlink: typeof fs.promises.unlink;
|
||||||
|
export declare const IS_WINDOWS: boolean;
|
||||||
|
export declare function exists(fsPath: string): Promise<boolean>;
|
||||||
|
export declare function isDirectory(fsPath: string, useStat?: boolean): Promise<boolean>;
|
||||||
|
/**
|
||||||
|
* On OSX/Linux, true if path starts with '/'. On Windows, true for paths like:
|
||||||
|
* \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases).
|
||||||
|
*/
|
||||||
|
export declare function isRooted(p: string): boolean;
|
||||||
|
/**
|
||||||
|
* Recursively create a directory at `fsPath`.
|
||||||
|
*
|
||||||
|
* This implementation is optimistic, meaning it attempts to create the full
|
||||||
|
* path first, and backs up the path stack from there.
|
||||||
|
*
|
||||||
|
* @param fsPath The path to create
|
||||||
|
* @param maxDepth The maximum recursion depth
|
||||||
|
* @param depth The current recursion depth
|
||||||
|
*/
|
||||||
|
export declare function mkdirP(fsPath: string, maxDepth?: number, depth?: number): Promise<void>;
|
||||||
|
/**
|
||||||
|
* Best effort attempt to determine whether a file exists and is executable.
|
||||||
|
* @param filePath file path to check
|
||||||
|
* @param extensions additional file extensions to try
|
||||||
|
* @return if file exists and is executable, returns the file path. otherwise empty string.
|
||||||
|
*/
|
||||||
|
export declare function tryGetExecutablePath(filePath: string, extensions: string[]): Promise<string>;
|
||||||
|
|
@ -0,0 +1,195 @@
|
||||||
|
"use strict";
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var _a;
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const assert_1 = require("assert");
|
||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
_a = fs.promises, exports.chmod = _a.chmod, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.readdir = _a.readdir, exports.readlink = _a.readlink, exports.rename = _a.rename, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.symlink = _a.symlink, exports.unlink = _a.unlink;
|
||||||
|
exports.IS_WINDOWS = process.platform === 'win32';
|
||||||
|
function exists(fsPath) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
try {
|
||||||
|
yield exports.stat(fsPath);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
if (err.code === 'ENOENT') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.exists = exists;
|
||||||
|
function isDirectory(fsPath, useStat = false) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
const stats = useStat ? yield exports.stat(fsPath) : yield exports.lstat(fsPath);
|
||||||
|
return stats.isDirectory();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.isDirectory = isDirectory;
|
||||||
|
/**
|
||||||
|
* On OSX/Linux, true if path starts with '/'. On Windows, true for paths like:
|
||||||
|
* \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases).
|
||||||
|
*/
|
||||||
|
function isRooted(p) {
|
||||||
|
p = normalizeSeparators(p);
|
||||||
|
if (!p) {
|
||||||
|
throw new Error('isRooted() parameter "p" cannot be empty');
|
||||||
|
}
|
||||||
|
if (exports.IS_WINDOWS) {
|
||||||
|
return (p.startsWith('\\') || /^[A-Z]:/i.test(p) // e.g. \ or \hello or \\hello
|
||||||
|
); // e.g. C: or C:\hello
|
||||||
|
}
|
||||||
|
return p.startsWith('/');
|
||||||
|
}
|
||||||
|
exports.isRooted = isRooted;
|
||||||
|
/**
|
||||||
|
* Recursively create a directory at `fsPath`.
|
||||||
|
*
|
||||||
|
* This implementation is optimistic, meaning it attempts to create the full
|
||||||
|
* path first, and backs up the path stack from there.
|
||||||
|
*
|
||||||
|
* @param fsPath The path to create
|
||||||
|
* @param maxDepth The maximum recursion depth
|
||||||
|
* @param depth The current recursion depth
|
||||||
|
*/
|
||||||
|
function mkdirP(fsPath, maxDepth = 1000, depth = 1) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
assert_1.ok(fsPath, 'a path argument must be provided');
|
||||||
|
fsPath = path.resolve(fsPath);
|
||||||
|
if (depth >= maxDepth)
|
||||||
|
return exports.mkdir(fsPath);
|
||||||
|
try {
|
||||||
|
yield exports.mkdir(fsPath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
switch (err.code) {
|
||||||
|
case 'ENOENT': {
|
||||||
|
yield mkdirP(path.dirname(fsPath), maxDepth, depth + 1);
|
||||||
|
yield exports.mkdir(fsPath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
let stats;
|
||||||
|
try {
|
||||||
|
stats = yield exports.stat(fsPath);
|
||||||
|
}
|
||||||
|
catch (err2) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
if (!stats.isDirectory())
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.mkdirP = mkdirP;
|
||||||
|
/**
|
||||||
|
* Best effort attempt to determine whether a file exists and is executable.
|
||||||
|
* @param filePath file path to check
|
||||||
|
* @param extensions additional file extensions to try
|
||||||
|
* @return if file exists and is executable, returns the file path. otherwise empty string.
|
||||||
|
*/
|
||||||
|
function tryGetExecutablePath(filePath, extensions) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
let stats = undefined;
|
||||||
|
try {
|
||||||
|
// test file exists
|
||||||
|
stats = yield exports.stat(filePath);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
if (err.code !== 'ENOENT') {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stats && stats.isFile()) {
|
||||||
|
if (exports.IS_WINDOWS) {
|
||||||
|
// on Windows, test for valid extension
|
||||||
|
const upperExt = path.extname(filePath).toUpperCase();
|
||||||
|
if (extensions.some(validExt => validExt.toUpperCase() === upperExt)) {
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (isUnixExecutable(stats)) {
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// try each extension
|
||||||
|
const originalFilePath = filePath;
|
||||||
|
for (const extension of extensions) {
|
||||||
|
filePath = originalFilePath + extension;
|
||||||
|
stats = undefined;
|
||||||
|
try {
|
||||||
|
stats = yield exports.stat(filePath);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
if (err.code !== 'ENOENT') {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stats && stats.isFile()) {
|
||||||
|
if (exports.IS_WINDOWS) {
|
||||||
|
// preserve the case of the actual file (since an extension was appended)
|
||||||
|
try {
|
||||||
|
const directory = path.dirname(filePath);
|
||||||
|
const upperName = path.basename(filePath).toUpperCase();
|
||||||
|
for (const actualName of yield exports.readdir(directory)) {
|
||||||
|
if (upperName === actualName.toUpperCase()) {
|
||||||
|
filePath = path.join(directory, actualName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`);
|
||||||
|
}
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (isUnixExecutable(stats)) {
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.tryGetExecutablePath = tryGetExecutablePath;
|
||||||
|
function normalizeSeparators(p) {
|
||||||
|
p = p || '';
|
||||||
|
if (exports.IS_WINDOWS) {
|
||||||
|
// convert slashes on Windows
|
||||||
|
p = p.replace(/\//g, '\\');
|
||||||
|
// remove redundant slashes
|
||||||
|
return p.replace(/\\\\+/g, '\\');
|
||||||
|
}
|
||||||
|
// remove redundant slashes
|
||||||
|
return p.replace(/\/\/+/g, '/');
|
||||||
|
}
|
||||||
|
// on Mac/Linux, test the execute bit
|
||||||
|
// R W X R W X R W X
|
||||||
|
// 256 128 64 32 16 8 4 2 1
|
||||||
|
function isUnixExecutable(stats) {
|
||||||
|
return ((stats.mode & 1) > 0 ||
|
||||||
|
((stats.mode & 8) > 0 && stats.gid === process.getgid()) ||
|
||||||
|
((stats.mode & 64) > 0 && stats.uid === process.getuid()));
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=io-util.js.map
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"io-util.js","sourceRoot":"","sources":["../src/io-util.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,mCAAyB;AACzB,yBAAwB;AACxB,6BAA4B;AAEf,gBAYE,qTAAA;AAEF,QAAA,UAAU,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAA;AAEtD,SAAsB,MAAM,CAAC,MAAc;;QACzC,IAAI;YACF,MAAM,YAAI,CAAC,MAAM,CAAC,CAAA;SACnB;QAAC,OAAO,GAAG,EAAE;YACZ,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE;gBACzB,OAAO,KAAK,CAAA;aACb;YAED,MAAM,GAAG,CAAA;SACV;QAED,OAAO,IAAI,CAAA;IACb,CAAC;CAAA;AAZD,wBAYC;AAED,SAAsB,WAAW,CAC/B,MAAc,EACd,UAAmB,KAAK;;QAExB,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,MAAM,YAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,aAAK,CAAC,MAAM,CAAC,CAAA;QAChE,OAAO,KAAK,CAAC,WAAW,EAAE,CAAA;IAC5B,CAAC;CAAA;AAND,kCAMC;AAED;;;GAGG;AACH,SAAgB,QAAQ,CAAC,CAAS;IAChC,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAA;IAC1B,IAAI,CAAC,CAAC,EAAE;QACN,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAA;KAC5D;IAED,IAAI,kBAAU,EAAE;QACd,OAAO,CACL,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,8BAA8B;SACxE,CAAA,CAAC,sBAAsB;KACzB;IAED,OAAO,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;AAC1B,CAAC;AAbD,4BAaC;AAED;;;;;;;;;GASG;AACH,SAAsB,MAAM,CAC1B,MAAc,EACd,WAAmB,IAAI,EACvB,QAAgB,CAAC;;QAEjB,WAAE,CAAC,MAAM,EAAE,kCAAkC,CAAC,CAAA;QAE9C,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QAE7B,IAAI,KAAK,IAAI,QAAQ;YAAE,OAAO,aAAK,CAAC,MAAM,CAAC,CAAA;QAE3C,IAAI;YACF,MAAM,aAAK,CAAC,MAAM,CAAC,CAAA;YACnB,OAAM;SACP;QAAC,OAAO,GAAG,EAAE;YACZ,QAAQ,GAAG,CAAC,IAAI,EAAE;gBAChB,KAAK,QAAQ,CAAC,CAAC;oBACb,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,KAAK,GAAG,CAAC,CAAC,CAAA;oBACvD,MAAM,aAAK,CAAC,MAAM,CAAC,CAAA;oBACnB,OAAM;iBACP;gBACD,OAAO,CAAC,CAAC;oBACP,IAAI,KAAe,CAAA;oBAEnB,IAAI;wBACF,KAAK,GAAG,MAAM,YAAI,CAAC,MAAM,CAAC,CAAA;qBAC3B;oBAAC,OAAO,IAAI,EAAE;wBACb,MAAM,GAAG,CAAA;qBACV;oBAED,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;wBAAE,MAAM,GAAG,CAAA;iBACpC;aACF;SACF;IACH,CAAC;CAAA;AAlCD,wBAkCC;AAED;;;;;GAKG;AACH,SAAsB,oBAAoB,CACxC,QAAgB,EAChB,UAAoB;;QAEpB,IAAI,KAAK,GAAyB,SAAS,CAAA;QAC3C,IAAI;YACF,mBAAmB;YACnB,KAAK,GAAG,MAAM,YAAI,CAAC,QAAQ,CAAC,CAAA;SAC7B;QAAC,OAAO,GAAG,EAAE;YACZ,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE;gBACzB,sCAAsC;gBACtC,OAAO,CAAC,GAAG,CACT,uEAAuE,QAAQ,MAAM,GAAG,EAAE,CAC3F,CAAA;aACF;SACF;QACD,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE;YAC3B,IAAI,kBAAU,EAAE;gBACd,uCAAuC;gBACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAA;gBACrD,IAAI,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,QAAQ,CAAC,EAAE;oBACpE,OAAO,QAAQ,CAAA;iBAChB;aACF;iBAAM;gBACL,IAAI,gBAAgB,CAAC,KAAK,CAAC,EAAE;oBAC3B,OAAO,QAAQ,CAAA;iBAChB;aACF;SACF;QAED,qBAAqB;QACrB,MAAM,gBAAgB,GAAG,QAAQ,CAAA;QACjC,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE;YAClC,QAAQ,GAAG,gBAAgB,GAAG,SAAS,CAAA;YAEvC,KAAK,GAAG,SAAS,CAAA;YACjB,IAAI;gBACF,KAAK,GAAG,MAAM,YAAI,CAAC,QAAQ,CAAC,CAAA;aAC7B;YAAC,OAAO,GAAG,EAAE;gBACZ,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE;oBACzB,sCAAsC;oBACtC,OAAO,CAAC,GAAG,CACT,uEAAuE,QAAQ,MAAM,GAAG,EAAE,CAC3F,CAAA;iBACF;aACF;YAED,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE;gBAC3B,IAAI,kBAAU,EAAE;oBACd,yEAAyE;oBACzE,IAAI;wBACF,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;wBACxC,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAA;wBACvD,KAAK,MAAM,UAAU,IAAI,MAAM,eAAO,CAAC,SAAS,CAAC,EAAE;4BACjD,IAAI,SAAS,KAAK,UAAU,CAAC,WAAW,EAAE,EAAE;gCAC1C,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAA;gCAC3C,MAAK;6BACN;yBACF;qBACF;oBAAC,OAAO,GAAG,EAAE;wBACZ,sCAAsC;wBACtC,OAAO,CAAC,GAAG,CACT,yEAAyE,QAAQ,MAAM,GAAG,EAAE,CAC7F,CAAA;qBACF;oBAED,OAAO,QAAQ,CAAA;iBAChB;qBAAM;oBACL,IAAI,gBAAgB,CAAC,KAAK,CAAC,EAAE;wBAC3B,OAAO,QAAQ,CAAA;qBAChB;iBACF;aACF;SACF;QAED,OAAO,EAAE,CAAA;IACX,CAAC;CAAA;AA5ED,oDA4EC;AAED,SAAS,mBAAmB,CAAC,CAAS;IACpC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAA;IACX,IAAI,kBAAU,EAAE;QACd,6BAA6B;QAC7B,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QAE1B,2BAA2B;QAC3B,OAAO,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;KACjC;IAED,2BAA2B;IAC3B,OAAO,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAA;AACjC,CAAC;AAED,qCAAqC;AACrC,6BAA6B;AAC7B,6BAA6B;AAC7B,SAAS,gBAAgB,CAAC,KAAe;IACvC,OAAO,CACL,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC;QACpB,CAAC,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;QACxD,CAAC,CAAC,KAAK,CAAC,IAAI,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAC1D,CAAA;AACH,CAAC"}
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
/**
|
||||||
|
* Interface for cp/mv options
|
||||||
|
*/
|
||||||
|
export interface CopyOptions {
|
||||||
|
/** Optional. Whether to recursively copy all subdirectories. Defaults to false */
|
||||||
|
recursive?: boolean;
|
||||||
|
/** Optional. Whether to overwrite existing files in the destination. Defaults to true */
|
||||||
|
force?: boolean;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Interface for cp/mv options
|
||||||
|
*/
|
||||||
|
export interface MoveOptions {
|
||||||
|
/** Optional. Whether to overwrite existing files in the destination. Defaults to true */
|
||||||
|
force?: boolean;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Copies a file or folder.
|
||||||
|
* Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js
|
||||||
|
*
|
||||||
|
* @param source source path
|
||||||
|
* @param dest destination path
|
||||||
|
* @param options optional. See CopyOptions.
|
||||||
|
*/
|
||||||
|
export declare function cp(source: string, dest: string, options?: CopyOptions): Promise<void>;
|
||||||
|
/**
|
||||||
|
* Moves a path.
|
||||||
|
*
|
||||||
|
* @param source source path
|
||||||
|
* @param dest destination path
|
||||||
|
* @param options optional. See MoveOptions.
|
||||||
|
*/
|
||||||
|
export declare function mv(source: string, dest: string, options?: MoveOptions): Promise<void>;
|
||||||
|
/**
|
||||||
|
* Remove a path recursively with force
|
||||||
|
*
|
||||||
|
* @param inputPath path to remove
|
||||||
|
*/
|
||||||
|
export declare function rmRF(inputPath: string): Promise<void>;
|
||||||
|
/**
|
||||||
|
* Make a directory. Creates the full path with folders in between
|
||||||
|
* Will throw if it fails
|
||||||
|
*
|
||||||
|
* @param fsPath path to create
|
||||||
|
* @returns Promise<void>
|
||||||
|
*/
|
||||||
|
export declare function mkdirP(fsPath: string): Promise<void>;
|
||||||
|
/**
|
||||||
|
* Returns path of a tool had the tool actually been invoked. Resolves via paths.
|
||||||
|
* If you check and the tool does not exist, it will throw.
|
||||||
|
*
|
||||||
|
* @param tool name of the tool
|
||||||
|
* @param check whether to check if tool exists
|
||||||
|
* @returns Promise<string> path to tool
|
||||||
|
*/
|
||||||
|
export declare function which(tool: string, check?: boolean): Promise<string>;
|
||||||
|
|
@ -0,0 +1,290 @@
|
||||||
|
"use strict";
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const childProcess = require("child_process");
|
||||||
|
const path = require("path");
|
||||||
|
const util_1 = require("util");
|
||||||
|
const ioUtil = require("./io-util");
|
||||||
|
const exec = util_1.promisify(childProcess.exec);
|
||||||
|
/**
|
||||||
|
* Copies a file or folder.
|
||||||
|
* Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js
|
||||||
|
*
|
||||||
|
* @param source source path
|
||||||
|
* @param dest destination path
|
||||||
|
* @param options optional. See CopyOptions.
|
||||||
|
*/
|
||||||
|
function cp(source, dest, options = {}) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
const { force, recursive } = readCopyOptions(options);
|
||||||
|
const destStat = (yield ioUtil.exists(dest)) ? yield ioUtil.stat(dest) : null;
|
||||||
|
// Dest is an existing file, but not forcing
|
||||||
|
if (destStat && destStat.isFile() && !force) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If dest is an existing directory, should copy inside.
|
||||||
|
const newDest = destStat && destStat.isDirectory()
|
||||||
|
? path.join(dest, path.basename(source))
|
||||||
|
: dest;
|
||||||
|
if (!(yield ioUtil.exists(source))) {
|
||||||
|
throw new Error(`no such file or directory: ${source}`);
|
||||||
|
}
|
||||||
|
const sourceStat = yield ioUtil.stat(source);
|
||||||
|
if (sourceStat.isDirectory()) {
|
||||||
|
if (!recursive) {
|
||||||
|
throw new Error(`Failed to copy. ${source} is a directory, but tried to copy without recursive flag.`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
yield cpDirRecursive(source, newDest, 0, force);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (path.relative(source, newDest) === '') {
|
||||||
|
// a file cannot be copied to itself
|
||||||
|
throw new Error(`'${newDest}' and '${source}' are the same file`);
|
||||||
|
}
|
||||||
|
yield copyFile(source, newDest, force);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.cp = cp;
|
||||||
|
/**
|
||||||
|
* Moves a path.
|
||||||
|
*
|
||||||
|
* @param source source path
|
||||||
|
* @param dest destination path
|
||||||
|
* @param options optional. See MoveOptions.
|
||||||
|
*/
|
||||||
|
function mv(source, dest, options = {}) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
if (yield ioUtil.exists(dest)) {
|
||||||
|
let destExists = true;
|
||||||
|
if (yield ioUtil.isDirectory(dest)) {
|
||||||
|
// If dest is directory copy src into dest
|
||||||
|
dest = path.join(dest, path.basename(source));
|
||||||
|
destExists = yield ioUtil.exists(dest);
|
||||||
|
}
|
||||||
|
if (destExists) {
|
||||||
|
if (options.force == null || options.force) {
|
||||||
|
yield rmRF(dest);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Error('Destination already exists');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yield mkdirP(path.dirname(dest));
|
||||||
|
yield ioUtil.rename(source, dest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.mv = mv;
|
||||||
|
/**
|
||||||
|
* Remove a path recursively with force
|
||||||
|
*
|
||||||
|
* @param inputPath path to remove
|
||||||
|
*/
|
||||||
|
function rmRF(inputPath) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
if (ioUtil.IS_WINDOWS) {
|
||||||
|
// Node doesn't provide a delete operation, only an unlink function. This means that if the file is being used by another
|
||||||
|
// program (e.g. antivirus), it won't be deleted. To address this, we shell out the work to rd/del.
|
||||||
|
try {
|
||||||
|
if (yield ioUtil.isDirectory(inputPath, true)) {
|
||||||
|
yield exec(`rd /s /q "${inputPath}"`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
yield exec(`del /f /a "${inputPath}"`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
// if you try to delete a file that doesn't exist, desired result is achieved
|
||||||
|
// other errors are valid
|
||||||
|
if (err.code !== 'ENOENT')
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
// Shelling out fails to remove a symlink folder with missing source, this unlink catches that
|
||||||
|
try {
|
||||||
|
yield ioUtil.unlink(inputPath);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
// if you try to delete a file that doesn't exist, desired result is achieved
|
||||||
|
// other errors are valid
|
||||||
|
if (err.code !== 'ENOENT')
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let isDir = false;
|
||||||
|
try {
|
||||||
|
isDir = yield ioUtil.isDirectory(inputPath);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
// if you try to delete a file that doesn't exist, desired result is achieved
|
||||||
|
// other errors are valid
|
||||||
|
if (err.code !== 'ENOENT')
|
||||||
|
throw err;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isDir) {
|
||||||
|
yield exec(`rm -rf "${inputPath}"`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
yield ioUtil.unlink(inputPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.rmRF = rmRF;
|
||||||
|
/**
|
||||||
|
* Make a directory. Creates the full path with folders in between
|
||||||
|
* Will throw if it fails
|
||||||
|
*
|
||||||
|
* @param fsPath path to create
|
||||||
|
* @returns Promise<void>
|
||||||
|
*/
|
||||||
|
function mkdirP(fsPath) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
yield ioUtil.mkdirP(fsPath);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.mkdirP = mkdirP;
|
||||||
|
/**
|
||||||
|
* Returns path of a tool had the tool actually been invoked. Resolves via paths.
|
||||||
|
* If you check and the tool does not exist, it will throw.
|
||||||
|
*
|
||||||
|
* @param tool name of the tool
|
||||||
|
* @param check whether to check if tool exists
|
||||||
|
* @returns Promise<string> path to tool
|
||||||
|
*/
|
||||||
|
function which(tool, check) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
if (!tool) {
|
||||||
|
throw new Error("parameter 'tool' is required");
|
||||||
|
}
|
||||||
|
// recursive when check=true
|
||||||
|
if (check) {
|
||||||
|
const result = yield which(tool, false);
|
||||||
|
if (!result) {
|
||||||
|
if (ioUtil.IS_WINDOWS) {
|
||||||
|
throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// build the list of extensions to try
|
||||||
|
const extensions = [];
|
||||||
|
if (ioUtil.IS_WINDOWS && process.env.PATHEXT) {
|
||||||
|
for (const extension of process.env.PATHEXT.split(path.delimiter)) {
|
||||||
|
if (extension) {
|
||||||
|
extensions.push(extension);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if it's rooted, return it if exists. otherwise return empty.
|
||||||
|
if (ioUtil.isRooted(tool)) {
|
||||||
|
const filePath = yield ioUtil.tryGetExecutablePath(tool, extensions);
|
||||||
|
if (filePath) {
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
// if any path separators, return empty
|
||||||
|
if (tool.includes('/') || (ioUtil.IS_WINDOWS && tool.includes('\\'))) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
// build the list of directories
|
||||||
|
//
|
||||||
|
// Note, technically "where" checks the current directory on Windows. From a toolkit perspective,
|
||||||
|
// it feels like we should not do this. Checking the current directory seems like more of a use
|
||||||
|
// case of a shell, and the which() function exposed by the toolkit should strive for consistency
|
||||||
|
// across platforms.
|
||||||
|
const directories = [];
|
||||||
|
if (process.env.PATH) {
|
||||||
|
for (const p of process.env.PATH.split(path.delimiter)) {
|
||||||
|
if (p) {
|
||||||
|
directories.push(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// return the first match
|
||||||
|
for (const directory of directories) {
|
||||||
|
const filePath = yield ioUtil.tryGetExecutablePath(directory + path.sep + tool, extensions);
|
||||||
|
if (filePath) {
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
throw new Error(`which failed with message ${err.message}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.which = which;
|
||||||
|
function readCopyOptions(options) {
|
||||||
|
const force = options.force == null ? true : options.force;
|
||||||
|
const recursive = Boolean(options.recursive);
|
||||||
|
return { force, recursive };
|
||||||
|
}
|
||||||
|
function cpDirRecursive(sourceDir, destDir, currentDepth, force) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
// Ensure there is not a run away recursive copy
|
||||||
|
if (currentDepth >= 255)
|
||||||
|
return;
|
||||||
|
currentDepth++;
|
||||||
|
yield mkdirP(destDir);
|
||||||
|
const files = yield ioUtil.readdir(sourceDir);
|
||||||
|
for (const fileName of files) {
|
||||||
|
const srcFile = `${sourceDir}/${fileName}`;
|
||||||
|
const destFile = `${destDir}/${fileName}`;
|
||||||
|
const srcFileStat = yield ioUtil.lstat(srcFile);
|
||||||
|
if (srcFileStat.isDirectory()) {
|
||||||
|
// Recurse
|
||||||
|
yield cpDirRecursive(srcFile, destFile, currentDepth, force);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
yield copyFile(srcFile, destFile, force);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Change the mode for the newly created directory
|
||||||
|
yield ioUtil.chmod(destDir, (yield ioUtil.stat(sourceDir)).mode);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Buffered file copy
|
||||||
|
function copyFile(srcFile, destFile, force) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
if ((yield ioUtil.lstat(srcFile)).isSymbolicLink()) {
|
||||||
|
// unlink/re-link it
|
||||||
|
try {
|
||||||
|
yield ioUtil.lstat(destFile);
|
||||||
|
yield ioUtil.unlink(destFile);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
// Try to override file permission
|
||||||
|
if (e.code === 'EPERM') {
|
||||||
|
yield ioUtil.chmod(destFile, '0666');
|
||||||
|
yield ioUtil.unlink(destFile);
|
||||||
|
}
|
||||||
|
// other errors = it doesn't exist, no work to do
|
||||||
|
}
|
||||||
|
// Copy over symlink
|
||||||
|
const symlinkFull = yield ioUtil.readlink(srcFile);
|
||||||
|
yield ioUtil.symlink(symlinkFull, destFile, ioUtil.IS_WINDOWS ? 'junction' : null);
|
||||||
|
}
|
||||||
|
else if (!(yield ioUtil.exists(destFile)) || force) {
|
||||||
|
yield ioUtil.copyFile(srcFile, destFile);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=io.js.map
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,37 @@
|
||||||
|
{
|
||||||
|
"name": "@actions/io",
|
||||||
|
"version": "1.0.2",
|
||||||
|
"description": "Actions io lib",
|
||||||
|
"keywords": [
|
||||||
|
"github",
|
||||||
|
"actions",
|
||||||
|
"io"
|
||||||
|
],
|
||||||
|
"homepage": "https://github.com/actions/toolkit/tree/master/packages/io",
|
||||||
|
"license": "MIT",
|
||||||
|
"main": "lib/io.js",
|
||||||
|
"types": "lib/io.d.ts",
|
||||||
|
"directories": {
|
||||||
|
"lib": "lib",
|
||||||
|
"test": "__tests__"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"lib"
|
||||||
|
],
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/actions/toolkit.git",
|
||||||
|
"directory": "packages/io"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"audit-moderate": "npm install && npm audit --audit-level=moderate",
|
||||||
|
"test": "echo \"Error: run tests from root\" && exit 1",
|
||||||
|
"tsc": "tsc"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/actions/toolkit/issues"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
language: node_js
|
||||||
|
node_js:
|
||||||
|
- 4
|
||||||
|
- 5
|
||||||
|
- 6
|
||||||
|
sudo: false
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
Apache License, Version 2.0
|
||||||
|
|
||||||
|
Copyright (c) 2011 Dominic Tarr
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
The MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2011 Dominic Tarr
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge,
|
||||||
|
to any person obtaining a copy of this software and
|
||||||
|
associated documentation files (the "Software"), to
|
||||||
|
deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify,
|
||||||
|
merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom
|
||||||
|
the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice
|
||||||
|
shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||||
|
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
#! /usr/bin/env node
|
||||||
|
|
||||||
|
var JSONStream = require('./')
|
||||||
|
|
||||||
|
if(!module.parent && process.title !== 'browser') {
|
||||||
|
process.stdin
|
||||||
|
.pipe(JSONStream.parse(process.argv[2]))
|
||||||
|
.pipe(JSONStream.stringify('[', ',\n', ']\n', 2))
|
||||||
|
.pipe(process.stdout)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
var request = require('request')
|
||||||
|
, JSONStream = require('JSONStream')
|
||||||
|
, es = require('event-stream')
|
||||||
|
|
||||||
|
var parser = JSONStream.parse(['rows', true]) //emit parts that match this path (any element of the rows array)
|
||||||
|
, req = request({url: 'http://isaacs.couchone.com/registry/_all_docs'})
|
||||||
|
, logger = es.mapSync(function (data) { //create a stream that logs to stderr,
|
||||||
|
console.error(data)
|
||||||
|
return data
|
||||||
|
})
|
||||||
|
|
||||||
|
req.pipe(parser)
|
||||||
|
parser.pipe(logger)
|
||||||
|
|
@ -0,0 +1,247 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
var Parser = require('jsonparse')
|
||||||
|
, through = require('through')
|
||||||
|
|
||||||
|
var bufferFrom = Buffer.from && Buffer.from !== Uint8Array.from
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
the value of this.stack that creationix's jsonparse has is weird.
|
||||||
|
|
||||||
|
it makes this code ugly, but his problem is way harder that mine,
|
||||||
|
so i'll forgive him.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports.parse = function (path, map) {
|
||||||
|
var header, footer
|
||||||
|
var parser = new Parser()
|
||||||
|
var stream = through(function (chunk) {
|
||||||
|
if('string' === typeof chunk)
|
||||||
|
chunk = bufferFrom ? Buffer.from(chunk) : new Buffer(chunk)
|
||||||
|
parser.write(chunk)
|
||||||
|
},
|
||||||
|
function (data) {
|
||||||
|
if(data)
|
||||||
|
stream.write(data)
|
||||||
|
if (header)
|
||||||
|
stream.emit('header', header)
|
||||||
|
if (footer)
|
||||||
|
stream.emit('footer', footer)
|
||||||
|
stream.queue(null)
|
||||||
|
})
|
||||||
|
|
||||||
|
if('string' === typeof path)
|
||||||
|
path = path.split('.').map(function (e) {
|
||||||
|
if (e === '$*')
|
||||||
|
return {emitKey: true}
|
||||||
|
else if (e === '*')
|
||||||
|
return true
|
||||||
|
else if (e === '') // '..'.split('.') returns an empty string
|
||||||
|
return {recurse: true}
|
||||||
|
else
|
||||||
|
return e
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
var count = 0, _key
|
||||||
|
if(!path || !path.length)
|
||||||
|
path = null
|
||||||
|
|
||||||
|
parser.onValue = function (value) {
|
||||||
|
if (!this.root)
|
||||||
|
stream.root = value
|
||||||
|
|
||||||
|
if(! path) return
|
||||||
|
|
||||||
|
var i = 0 // iterates on path
|
||||||
|
var j = 0 // iterates on stack
|
||||||
|
var emitKey = false;
|
||||||
|
var emitPath = false;
|
||||||
|
while (i < path.length) {
|
||||||
|
var key = path[i]
|
||||||
|
var c
|
||||||
|
j++
|
||||||
|
|
||||||
|
if (key && !key.recurse) {
|
||||||
|
c = (j === this.stack.length) ? this : this.stack[j]
|
||||||
|
if (!c) return
|
||||||
|
if (! check(key, c.key)) {
|
||||||
|
setHeaderFooter(c.key, value)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
emitKey = !!key.emitKey;
|
||||||
|
emitPath = !!key.emitPath;
|
||||||
|
i++
|
||||||
|
} else {
|
||||||
|
i++
|
||||||
|
var nextKey = path[i]
|
||||||
|
if (! nextKey) return
|
||||||
|
while (true) {
|
||||||
|
c = (j === this.stack.length) ? this : this.stack[j]
|
||||||
|
if (!c) return
|
||||||
|
if (check(nextKey, c.key)) {
|
||||||
|
i++;
|
||||||
|
if (!Object.isFrozen(this.stack[j]))
|
||||||
|
this.stack[j].value = null
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
setHeaderFooter(c.key, value)
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// emit header
|
||||||
|
if (header) {
|
||||||
|
stream.emit('header', header);
|
||||||
|
header = false;
|
||||||
|
}
|
||||||
|
if (j !== this.stack.length) return
|
||||||
|
|
||||||
|
count ++
|
||||||
|
var actualPath = this.stack.slice(1).map(function(element) { return element.key }).concat([this.key])
|
||||||
|
var data = value
|
||||||
|
if(null != data)
|
||||||
|
if(null != (data = map ? map(data, actualPath) : data)) {
|
||||||
|
if (emitKey || emitPath) {
|
||||||
|
data = { value: data };
|
||||||
|
if (emitKey)
|
||||||
|
data["key"] = this.key;
|
||||||
|
if (emitPath)
|
||||||
|
data["path"] = actualPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.queue(data)
|
||||||
|
}
|
||||||
|
if (this.value) delete this.value[this.key]
|
||||||
|
for(var k in this.stack)
|
||||||
|
if (!Object.isFrozen(this.stack[k]))
|
||||||
|
this.stack[k].value = null
|
||||||
|
}
|
||||||
|
parser._onToken = parser.onToken;
|
||||||
|
|
||||||
|
parser.onToken = function (token, value) {
|
||||||
|
parser._onToken(token, value);
|
||||||
|
if (this.stack.length === 0) {
|
||||||
|
if (stream.root) {
|
||||||
|
if(!path)
|
||||||
|
stream.queue(stream.root)
|
||||||
|
count = 0;
|
||||||
|
stream.root = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.onError = function (err) {
|
||||||
|
if(err.message.indexOf("at position") > -1)
|
||||||
|
err.message = "Invalid JSON (" + err.message + ")";
|
||||||
|
stream.emit('error', err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream
|
||||||
|
|
||||||
|
function setHeaderFooter(key, value) {
|
||||||
|
// header has not been emitted yet
|
||||||
|
if (header !== false) {
|
||||||
|
header = header || {}
|
||||||
|
header[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// footer has not been emitted yet but header has
|
||||||
|
if (footer !== false && header === false) {
|
||||||
|
footer = footer || {}
|
||||||
|
footer[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function check (x, y) {
|
||||||
|
if ('string' === typeof x)
|
||||||
|
return y == x
|
||||||
|
else if (x && 'function' === typeof x.exec)
|
||||||
|
return x.exec(y)
|
||||||
|
else if ('boolean' === typeof x || 'object' === typeof x)
|
||||||
|
return x
|
||||||
|
else if ('function' === typeof x)
|
||||||
|
return x(y)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.stringify = function (op, sep, cl, indent) {
|
||||||
|
indent = indent || 0
|
||||||
|
if (op === false){
|
||||||
|
op = ''
|
||||||
|
sep = '\n'
|
||||||
|
cl = ''
|
||||||
|
} else if (op == null) {
|
||||||
|
|
||||||
|
op = '[\n'
|
||||||
|
sep = '\n,\n'
|
||||||
|
cl = '\n]\n'
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//else, what ever you like
|
||||||
|
|
||||||
|
var stream
|
||||||
|
, first = true
|
||||||
|
, anyData = false
|
||||||
|
stream = through(function (data) {
|
||||||
|
anyData = true
|
||||||
|
try {
|
||||||
|
var json = JSON.stringify(data, null, indent)
|
||||||
|
} catch (err) {
|
||||||
|
return stream.emit('error', err)
|
||||||
|
}
|
||||||
|
if(first) { first = false ; stream.queue(op + json)}
|
||||||
|
else stream.queue(sep + json)
|
||||||
|
},
|
||||||
|
function (data) {
|
||||||
|
if(!anyData)
|
||||||
|
stream.queue(op)
|
||||||
|
stream.queue(cl)
|
||||||
|
stream.queue(null)
|
||||||
|
})
|
||||||
|
|
||||||
|
return stream
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.stringifyObject = function (op, sep, cl, indent) {
|
||||||
|
indent = indent || 0
|
||||||
|
if (op === false){
|
||||||
|
op = ''
|
||||||
|
sep = '\n'
|
||||||
|
cl = ''
|
||||||
|
} else if (op == null) {
|
||||||
|
|
||||||
|
op = '{\n'
|
||||||
|
sep = '\n,\n'
|
||||||
|
cl = '\n}\n'
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//else, what ever you like
|
||||||
|
|
||||||
|
var first = true
|
||||||
|
var anyData = false
|
||||||
|
var stream = through(function (data) {
|
||||||
|
anyData = true
|
||||||
|
var json = JSON.stringify(data[0]) + ':' + JSON.stringify(data[1], null, indent)
|
||||||
|
if(first) { first = false ; this.queue(op + json)}
|
||||||
|
else this.queue(sep + json)
|
||||||
|
},
|
||||||
|
function (data) {
|
||||||
|
if(!anyData) this.queue(op)
|
||||||
|
this.queue(cl)
|
||||||
|
|
||||||
|
this.queue(null)
|
||||||
|
})
|
||||||
|
|
||||||
|
return stream
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
{
|
||||||
|
"name": "JSONStream",
|
||||||
|
"version": "1.3.5",
|
||||||
|
"description": "rawStream.pipe(JSONStream.parse()).pipe(streamOfObjects)",
|
||||||
|
"homepage": "http://github.com/dominictarr/JSONStream",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/dominictarr/JSONStream.git"
|
||||||
|
},
|
||||||
|
"license": "(MIT OR Apache-2.0)",
|
||||||
|
"keywords": [
|
||||||
|
"json",
|
||||||
|
"stream",
|
||||||
|
"streaming",
|
||||||
|
"parser",
|
||||||
|
"async",
|
||||||
|
"parsing"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"jsonparse": "^1.2.0",
|
||||||
|
"through": ">=2.2.7 <3"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"it-is": "~1",
|
||||||
|
"assertions": "~2.2.2",
|
||||||
|
"render": "~0.1.1",
|
||||||
|
"trees": "~0.0.3",
|
||||||
|
"event-stream": "~0.7.0",
|
||||||
|
"tape": "~2.12.3"
|
||||||
|
},
|
||||||
|
"bin": "./bin.js",
|
||||||
|
"author": "Dominic Tarr <dominic.tarr@gmail.com> (http://bit.ly/dominictarr)",
|
||||||
|
"scripts": {
|
||||||
|
"test": "node test/run.js"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,207 @@
|
||||||
|
# JSONStream
|
||||||
|
|
||||||
|
streaming JSON.parse and stringify
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## install
|
||||||
|
```npm install JSONStream```
|
||||||
|
|
||||||
|
## example
|
||||||
|
|
||||||
|
``` js
|
||||||
|
|
||||||
|
var request = require('request')
|
||||||
|
, JSONStream = require('JSONStream')
|
||||||
|
, es = require('event-stream')
|
||||||
|
|
||||||
|
request({url: 'http://isaacs.couchone.com/registry/_all_docs'})
|
||||||
|
.pipe(JSONStream.parse('rows.*'))
|
||||||
|
.pipe(es.mapSync(function (data) {
|
||||||
|
console.error(data)
|
||||||
|
return data
|
||||||
|
}))
|
||||||
|
```
|
||||||
|
|
||||||
|
## JSONStream.parse(path)
|
||||||
|
|
||||||
|
parse stream of values that match a path
|
||||||
|
|
||||||
|
``` js
|
||||||
|
JSONStream.parse('rows.*.doc')
|
||||||
|
```
|
||||||
|
|
||||||
|
The `..` operator is the recursive descent operator from [JSONPath](http://goessner.net/articles/JsonPath/), which will match a child at any depth (see examples below).
|
||||||
|
|
||||||
|
If your keys have keys that include `.` or `*` etc, use an array instead.
|
||||||
|
`['row', true, /^doc/]`.
|
||||||
|
|
||||||
|
If you use an array, `RegExp`s, booleans, and/or functions. The `..` operator is also available in array representation, using `{recurse: true}`.
|
||||||
|
any object that matches the path will be emitted as 'data' (and `pipe`d down stream)
|
||||||
|
|
||||||
|
If `path` is empty or null, no 'data' events are emitted.
|
||||||
|
|
||||||
|
If you want to have keys emitted, you can prefix your `*` operator with `$`: `obj.$*` - in this case the data passed to the stream is an object with a `key` holding the key and a `value` property holding the data.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
query a couchdb view:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
curl -sS localhost:5984/tests/_all_docs&include_docs=true
|
||||||
|
```
|
||||||
|
you will get something like this:
|
||||||
|
|
||||||
|
``` js
|
||||||
|
{"total_rows":129,"offset":0,"rows":[
|
||||||
|
{ "id":"change1_0.6995461115147918"
|
||||||
|
, "key":"change1_0.6995461115147918"
|
||||||
|
, "value":{"rev":"1-e240bae28c7bb3667f02760f6398d508"}
|
||||||
|
, "doc":{
|
||||||
|
"_id": "change1_0.6995461115147918"
|
||||||
|
, "_rev": "1-e240bae28c7bb3667f02760f6398d508","hello":1}
|
||||||
|
},
|
||||||
|
{ "id":"change2_0.6995461115147918"
|
||||||
|
, "key":"change2_0.6995461115147918"
|
||||||
|
, "value":{"rev":"1-13677d36b98c0c075145bb8975105153"}
|
||||||
|
, "doc":{
|
||||||
|
"_id":"change2_0.6995461115147918"
|
||||||
|
, "_rev":"1-13677d36b98c0c075145bb8975105153"
|
||||||
|
, "hello":2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
we are probably most interested in the `rows.*.doc`
|
||||||
|
|
||||||
|
create a `Stream` that parses the documents from the feed like this:
|
||||||
|
|
||||||
|
``` js
|
||||||
|
var stream = JSONStream.parse(['rows', true, 'doc']) //rows, ANYTHING, doc
|
||||||
|
|
||||||
|
stream.on('data', function(data) {
|
||||||
|
console.log('received:', data);
|
||||||
|
});
|
||||||
|
//emits anything from _before_ the first match
|
||||||
|
stream.on('header', function (data) {
|
||||||
|
console.log('header:', data) // => {"total_rows":129,"offset":0}
|
||||||
|
})
|
||||||
|
|
||||||
|
```
|
||||||
|
awesome!
|
||||||
|
|
||||||
|
In case you wanted the contents the doc emitted:
|
||||||
|
|
||||||
|
``` js
|
||||||
|
var stream = JSONStream.parse(['rows', true, 'doc', {emitKey: true}]) //rows, ANYTHING, doc, items in docs with keys
|
||||||
|
|
||||||
|
stream.on('data', function(data) {
|
||||||
|
console.log('key:', data.key);
|
||||||
|
console.log('value:', data.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also emit the path:
|
||||||
|
|
||||||
|
``` js
|
||||||
|
var stream = JSONStream.parse(['rows', true, 'doc', {emitPath: true}]) //rows, ANYTHING, doc, items in docs with keys
|
||||||
|
|
||||||
|
stream.on('data', function(data) {
|
||||||
|
console.log('path:', data.path);
|
||||||
|
console.log('value:', data.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### recursive patterns (..)
|
||||||
|
|
||||||
|
`JSONStream.parse('docs..value')`
|
||||||
|
(or `JSONStream.parse(['docs', {recurse: true}, 'value'])` using an array)
|
||||||
|
will emit every `value` object that is a child, grand-child, etc. of the
|
||||||
|
`docs` object. In this example, it will match exactly 5 times at various depth
|
||||||
|
levels, emitting 0, 1, 2, 3 and 4 as results.
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
"total": 5,
|
||||||
|
"docs": [
|
||||||
|
{
|
||||||
|
"key": {
|
||||||
|
"value": 0,
|
||||||
|
"some": "property"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{"value": 1},
|
||||||
|
{"value": 2},
|
||||||
|
{"blbl": [{}, {"a":0, "b":1, "value":3}, 10]},
|
||||||
|
{"value": 4}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## JSONStream.parse(pattern, map)
|
||||||
|
|
||||||
|
provide a function that can be used to map or filter
|
||||||
|
the json output. `map` is passed the value at that node of the pattern,
|
||||||
|
if `map` return non-nullish (anything but `null` or `undefined`)
|
||||||
|
that value will be emitted in the stream. If it returns a nullish value,
|
||||||
|
nothing will be emitted.
|
||||||
|
|
||||||
|
`JSONStream` also emits `'header'` and `'footer'` events,
|
||||||
|
the `'header'` event contains anything in the output that was before
|
||||||
|
the first match, and the `'footer'`, is anything after the last match.
|
||||||
|
|
||||||
|
## JSONStream.stringify(open, sep, close)
|
||||||
|
|
||||||
|
Create a writable stream.
|
||||||
|
|
||||||
|
you may pass in custom `open`, `close`, and `seperator` strings.
|
||||||
|
But, by default, `JSONStream.stringify()` will create an array,
|
||||||
|
(with default options `open='[\n', sep='\n,\n', close='\n]\n'`)
|
||||||
|
|
||||||
|
If you call `JSONStream.stringify(false)`
|
||||||
|
the elements will only be seperated by a newline.
|
||||||
|
|
||||||
|
If you only write one item this will be valid JSON.
|
||||||
|
|
||||||
|
If you write many items,
|
||||||
|
you can use a `RegExp` to split it into valid chunks.
|
||||||
|
|
||||||
|
## JSONStream.stringifyObject(open, sep, close)
|
||||||
|
|
||||||
|
Very much like `JSONStream.stringify`,
|
||||||
|
but creates a writable stream for objects instead of arrays.
|
||||||
|
|
||||||
|
Accordingly, `open='{\n', sep='\n,\n', close='\n}\n'`.
|
||||||
|
|
||||||
|
When you `.write()` to the stream you must supply an array with `[ key, data ]`
|
||||||
|
as the first argument.
|
||||||
|
|
||||||
|
## unix tool
|
||||||
|
|
||||||
|
query npm to see all the modules that browserify has ever depended on.
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
curl https://registry.npmjs.org/browserify | JSONStream 'versions.*.dependencies'
|
||||||
|
```
|
||||||
|
|
||||||
|
## numbers
|
||||||
|
|
||||||
|
numbers will be emitted as numbers.
|
||||||
|
huge numbers that cannot be represented in memory as javascript numbers will be emitted as strings.
|
||||||
|
cf https://github.com/creationix/jsonparse/commit/044b268f01c4b8f97fb936fc85d3bcfba179e5bb for details.
|
||||||
|
|
||||||
|
## Acknowlegements
|
||||||
|
|
||||||
|
this module depends on https://github.com/creationix/jsonparse
|
||||||
|
by Tim Caswell
|
||||||
|
and also thanks to Florent Jaby for teaching me about parsing with:
|
||||||
|
https://github.com/Floby/node-json-streams
|
||||||
|
|
||||||
|
## license
|
||||||
|
|
||||||
|
Dual-licensed under the MIT License or the Apache License, version 2.0
|
||||||
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
|
||||||
|
var fs = require ('fs')
|
||||||
|
, join = require('path').join
|
||||||
|
, file = join(__dirname, 'fixtures','all_npm.json')
|
||||||
|
, JSONStream = require('../')
|
||||||
|
, it = require('it-is').style('colour')
|
||||||
|
|
||||||
|
function randomObj () {
|
||||||
|
return (
|
||||||
|
Math.random () < 0.4
|
||||||
|
? {hello: 'eonuhckmqjk',
|
||||||
|
whatever: 236515,
|
||||||
|
lies: true,
|
||||||
|
nothing: [null],
|
||||||
|
// stuff: [Math.random(),Math.random(),Math.random()]
|
||||||
|
}
|
||||||
|
: ['AOREC', 'reoubaor', {ouec: 62642}, [[[], {}, 53]]]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var expected = []
|
||||||
|
, stringify = JSONStream.stringify()
|
||||||
|
, es = require('event-stream')
|
||||||
|
, stringified = ''
|
||||||
|
, called = 0
|
||||||
|
, count = 10
|
||||||
|
, ended = false
|
||||||
|
|
||||||
|
while (count --)
|
||||||
|
expected.push(randomObj())
|
||||||
|
|
||||||
|
es.connect(
|
||||||
|
es.readArray(expected),
|
||||||
|
stringify,
|
||||||
|
JSONStream.parse([true]),
|
||||||
|
es.writeArray(function (err, lines) {
|
||||||
|
|
||||||
|
it(lines).has(expected)
|
||||||
|
console.error('PASSED')
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
var test = require('tape')
|
||||||
|
var JSONStream = require('../')
|
||||||
|
var testData = '{"rows":[{"hello":"world"}, {"foo": "bar"}]}'
|
||||||
|
|
||||||
|
test('basic parsing', function (t) {
|
||||||
|
t.plan(2)
|
||||||
|
var parsed = JSONStream.parse("rows.*")
|
||||||
|
var parsedKeys = {}
|
||||||
|
parsed.on('data', function(match) {
|
||||||
|
parsedKeys[Object.keys(match)[0]] = true
|
||||||
|
})
|
||||||
|
parsed.on('end', function() {
|
||||||
|
t.equal(!!parsedKeys['hello'], true)
|
||||||
|
t.equal(!!parsedKeys['foo'], true)
|
||||||
|
})
|
||||||
|
parsed.write(testData)
|
||||||
|
parsed.end()
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
var fs = require ('fs');
|
||||||
|
var net = require('net');
|
||||||
|
var join = require('path').join;
|
||||||
|
var file = join(__dirname, 'fixtures','all_npm.json');
|
||||||
|
var JSONStream = require('../');
|
||||||
|
|
||||||
|
|
||||||
|
var server = net.createServer(function(client) {
|
||||||
|
var parser = JSONStream.parse([]);
|
||||||
|
parser.on('end', function() {
|
||||||
|
console.log('close')
|
||||||
|
console.error('PASSED');
|
||||||
|
server.close();
|
||||||
|
});
|
||||||
|
client.pipe(parser);
|
||||||
|
var n = 4
|
||||||
|
client.on('data', function () {
|
||||||
|
if(--n) return
|
||||||
|
client.end();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
server.listen(9999);
|
||||||
|
|
||||||
|
|
||||||
|
var client = net.connect({ port : 9999 }, function() {
|
||||||
|
fs.createReadStream(file).pipe(client).on('data', console.log) //.resume();
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
var fs = require ('fs')
|
||||||
|
, join = require('path').join
|
||||||
|
, file = join(__dirname, 'fixtures','all_npm.json')
|
||||||
|
, JSONStream = require('../')
|
||||||
|
, it = require('it-is')
|
||||||
|
|
||||||
|
var expected = JSON.parse(fs.readFileSync(file))
|
||||||
|
, parser = JSONStream.parse('rows..rev')
|
||||||
|
, called = 0
|
||||||
|
, ended = false
|
||||||
|
, parsed = []
|
||||||
|
|
||||||
|
fs.createReadStream(file).pipe(parser)
|
||||||
|
|
||||||
|
parser.on('data', function (data) {
|
||||||
|
called ++
|
||||||
|
parsed.push(data)
|
||||||
|
})
|
||||||
|
|
||||||
|
parser.on('end', function () {
|
||||||
|
ended = true
|
||||||
|
})
|
||||||
|
|
||||||
|
process.on('exit', function () {
|
||||||
|
it(called).equal(expected.rows.length)
|
||||||
|
for (var i = 0 ; i < expected.rows.length ; i++)
|
||||||
|
it(parsed[i]).deepEqual(expected.rows[i].value.rev)
|
||||||
|
console.error('PASSED')
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
var fs = require ('fs')
|
||||||
|
, join = require('path').join
|
||||||
|
, file = join(__dirname, 'fixtures','depth.json')
|
||||||
|
, JSONStream = require('../')
|
||||||
|
, it = require('it-is')
|
||||||
|
|
||||||
|
var expected = JSON.parse(fs.readFileSync(file))
|
||||||
|
, parser = JSONStream.parse(['docs', {recurse: true}, 'value'])
|
||||||
|
, called = 0
|
||||||
|
, ended = false
|
||||||
|
, parsed = []
|
||||||
|
|
||||||
|
fs.createReadStream(file).pipe(parser)
|
||||||
|
|
||||||
|
parser.on('data', function (data) {
|
||||||
|
called ++
|
||||||
|
parsed.push(data)
|
||||||
|
})
|
||||||
|
|
||||||
|
parser.on('end', function () {
|
||||||
|
ended = true
|
||||||
|
})
|
||||||
|
|
||||||
|
process.on('exit', function () {
|
||||||
|
var expectedValues = [0, [1], {"a": 2}, "3", 4]
|
||||||
|
it(called).equal(expectedValues.length)
|
||||||
|
for (var i = 0 ; i < 5 ; i++)
|
||||||
|
it(parsed[i]).deepEqual(expectedValues[i])
|
||||||
|
console.error('PASSED')
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
var JSONStream = require('../')
|
||||||
|
, stream = require('stream')
|
||||||
|
, it = require('it-is')
|
||||||
|
|
||||||
|
var output = [ [], [] ]
|
||||||
|
|
||||||
|
var parser1 = JSONStream.parse(['docs', /./])
|
||||||
|
parser1.on('data', function(data) {
|
||||||
|
output[0].push(data)
|
||||||
|
})
|
||||||
|
|
||||||
|
var parser2 = JSONStream.parse(['docs', /./])
|
||||||
|
parser2.on('data', function(data) {
|
||||||
|
output[1].push(data)
|
||||||
|
})
|
||||||
|
|
||||||
|
var pending = 2
|
||||||
|
function onend () {
|
||||||
|
if (--pending > 0) return
|
||||||
|
it(output).deepEqual([
|
||||||
|
[], [{hello: 'world'}]
|
||||||
|
])
|
||||||
|
console.error('PASSED')
|
||||||
|
}
|
||||||
|
parser1.on('end', onend)
|
||||||
|
parser2.on('end', onend)
|
||||||
|
|
||||||
|
function makeReadableStream() {
|
||||||
|
var readStream = new stream.Stream()
|
||||||
|
readStream.readable = true
|
||||||
|
readStream.write = function (data) { this.emit('data', data) }
|
||||||
|
readStream.end = function (data) { this.emit('end') }
|
||||||
|
return readStream
|
||||||
|
}
|
||||||
|
|
||||||
|
var emptyArray = makeReadableStream()
|
||||||
|
emptyArray.pipe(parser1)
|
||||||
|
emptyArray.write('{"docs":[]}')
|
||||||
|
emptyArray.end()
|
||||||
|
|
||||||
|
var objectArray = makeReadableStream()
|
||||||
|
objectArray.pipe(parser2)
|
||||||
|
objectArray.write('{"docs":[{"hello":"world"}]}')
|
||||||
|
objectArray.end()
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
|
||||||
|
|
||||||
|
var fs = require ('fs')
|
||||||
|
, join = require('path').join
|
||||||
|
, file = join(__dirname, 'fixtures','error.json')
|
||||||
|
, JSONStream = require('../')
|
||||||
|
, it = require('it-is')
|
||||||
|
|
||||||
|
var expected = JSON.parse(fs.readFileSync(file))
|
||||||
|
, parser = JSONStream.parse(['rows'])
|
||||||
|
, called = 0
|
||||||
|
, headerCalled = 0
|
||||||
|
, footerCalled = 0
|
||||||
|
, ended = false
|
||||||
|
, parsed = []
|
||||||
|
|
||||||
|
fs.createReadStream(file).pipe(parser)
|
||||||
|
|
||||||
|
parser.on('header', function (data) {
|
||||||
|
headerCalled ++
|
||||||
|
it(data).deepEqual({
|
||||||
|
error: 'error_code',
|
||||||
|
message: 'this is an error message'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
parser.on('footer', function (data) {
|
||||||
|
footerCalled ++
|
||||||
|
})
|
||||||
|
|
||||||
|
parser.on('data', function (data) {
|
||||||
|
called ++
|
||||||
|
parsed.push(data)
|
||||||
|
})
|
||||||
|
|
||||||
|
parser.on('end', function () {
|
||||||
|
ended = true
|
||||||
|
})
|
||||||
|
|
||||||
|
process.on('exit', function () {
|
||||||
|
it(called).equal(0)
|
||||||
|
it(headerCalled).equal(1)
|
||||||
|
it(footerCalled).equal(0)
|
||||||
|
console.error('PASSED')
|
||||||
|
})
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,18 @@
|
||||||
|
{"total_rows":129,"offset":0,"rows":[
|
||||||
|
{ "id":"change1_0.6995461115147918"
|
||||||
|
, "key":"change1_0.6995461115147918"
|
||||||
|
, "value":{"rev":"1-e240bae28c7bb3667f02760f6398d508"}
|
||||||
|
, "doc":{
|
||||||
|
"_id": "change1_0.6995461115147918"
|
||||||
|
, "_rev": "1-e240bae28c7bb3667f02760f6398d508","hello":1}
|
||||||
|
},
|
||||||
|
{ "id":"change2_0.6995461115147918"
|
||||||
|
, "key":"change2_0.6995461115147918"
|
||||||
|
, "value":{"rev":"1-13677d36b98c0c075145bb8975105153"}
|
||||||
|
, "doc":{
|
||||||
|
"_id":"change2_0.6995461115147918"
|
||||||
|
, "_rev":"1-13677d36b98c0c075145bb8975105153"
|
||||||
|
, "hello":2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"total": 5,
|
||||||
|
"docs": [
|
||||||
|
{
|
||||||
|
"key": {
|
||||||
|
"value": 0,
|
||||||
|
"some": "property"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{"value": [1]},
|
||||||
|
{"value": {"a":2}},
|
||||||
|
{"blbl": [{}, {"a":0, "b":1, "value":"3"}, 10]},
|
||||||
|
{"value": 4}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
{"error": "error_code", "message": "this is an error message"}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
{"total_rows":129,"offset":0,"rows":[
|
||||||
|
{ "id":"change1_0.6995461115147918"
|
||||||
|
, "key":"change1_0.6995461115147918"
|
||||||
|
, "value":{"rev":"1-e240bae28c7bb3667f02760f6398d508"}
|
||||||
|
, "doc":{
|
||||||
|
"_id": "change1_0.6995461115147918"
|
||||||
|
, "_rev": "1-e240bae28c7bb3667f02760f6398d508","hello":1}
|
||||||
|
},
|
||||||
|
{ "id":"change2_0.6995461115147918"
|
||||||
|
, "key":"change2_0.6995461115147918"
|
||||||
|
, "value":{"rev":"1-13677d36b98c0c075145bb8975105153"}
|
||||||
|
, "doc":{
|
||||||
|
"_id":"change2_0.6995461115147918"
|
||||||
|
, "_rev":"1-13677d36b98c0c075145bb8975105153"
|
||||||
|
, "hello":2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foo": {"bar": "baz"}}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
|
||||||
|
|
||||||
|
var fs = require ('fs')
|
||||||
|
, join = require('path').join
|
||||||
|
, file = join(__dirname, 'fixtures','all_npm.json')
|
||||||
|
, JSONStream = require('../')
|
||||||
|
, it = require('it-is')
|
||||||
|
|
||||||
|
function fn (s) {
|
||||||
|
return !isNaN(parseInt(s, 10))
|
||||||
|
}
|
||||||
|
|
||||||
|
var expected = JSON.parse(fs.readFileSync(file))
|
||||||
|
, parser = JSONStream.parse(['rows', fn])
|
||||||
|
, called = 0
|
||||||
|
, ended = false
|
||||||
|
, parsed = []
|
||||||
|
|
||||||
|
fs.createReadStream(file).pipe(parser)
|
||||||
|
|
||||||
|
parser.on('data', function (data) {
|
||||||
|
called ++
|
||||||
|
it.has({
|
||||||
|
id: it.typeof('string'),
|
||||||
|
value: {rev: it.typeof('string')},
|
||||||
|
key:it.typeof('string')
|
||||||
|
})
|
||||||
|
parsed.push(data)
|
||||||
|
})
|
||||||
|
|
||||||
|
parser.on('end', function () {
|
||||||
|
ended = true
|
||||||
|
})
|
||||||
|
|
||||||
|
process.on('exit', function () {
|
||||||
|
it(called).equal(expected.rows.length)
|
||||||
|
it(parsed).deepEqual(expected.rows)
|
||||||
|
console.error('PASSED')
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
return // dont run this test for now since tape is weird and broken on 0.10
|
||||||
|
|
||||||
|
var fs = require('fs')
|
||||||
|
var JSONStream = require('../')
|
||||||
|
var file = process.argv[2] || '/tmp/JSONStream-test-large.json'
|
||||||
|
var size = Number(process.argv[3] || 100000)
|
||||||
|
var tape = require('tape')
|
||||||
|
// if (process.title !== 'browser') {
|
||||||
|
tape('out of mem', function (t) {
|
||||||
|
t.plan(1)
|
||||||
|
//////////////////////////////////////////////////////
|
||||||
|
// Produces a random number between arg1 and arg2
|
||||||
|
//////////////////////////////////////////////////////
|
||||||
|
var randomNumber = function (min, max) {
|
||||||
|
var number = Math.floor(Math.random() * (max - min + 1) + min);
|
||||||
|
return number;
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////
|
||||||
|
// Produces a random string of a length between arg1 and arg2
|
||||||
|
//////////////////////////////////////////////////////
|
||||||
|
var randomString = function (min, max) {
|
||||||
|
|
||||||
|
// add several spaces to increase chanses of creating 'words'
|
||||||
|
var chars = ' 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||||
|
var result = '';
|
||||||
|
|
||||||
|
var randomLength = randomNumber(min, max);
|
||||||
|
|
||||||
|
for (var i = randomLength; i > 0; --i) {
|
||||||
|
result += chars[Math.round(Math.random() * (chars.length - 1))];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////
|
||||||
|
// Produces a random JSON document, as a string
|
||||||
|
//////////////////////////////////////////////////////
|
||||||
|
var randomJsonDoc = function () {
|
||||||
|
|
||||||
|
var doc = {
|
||||||
|
"CrashOccurenceID": randomNumber(10000, 50000),
|
||||||
|
"CrashID": randomNumber(1000, 10000),
|
||||||
|
"SiteName": randomString(10, 25),
|
||||||
|
"MachineName": randomString(10, 25),
|
||||||
|
"Date": randomString(26, 26),
|
||||||
|
"ProcessDuration": randomString(18, 18),
|
||||||
|
"ThreadIdentityName": null,
|
||||||
|
"WindowsIdentityName": randomString(15, 40),
|
||||||
|
"OperatingSystemName": randomString(35, 65),
|
||||||
|
"DetailedExceptionInformation": randomString(100, 800)
|
||||||
|
};
|
||||||
|
|
||||||
|
doc = JSON.stringify(doc);
|
||||||
|
doc = doc.replace(/\,/g, ',\n'); // add new lines after each attribute
|
||||||
|
return doc;
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////
|
||||||
|
// generates test data
|
||||||
|
//////////////////////////////////////////////////////
|
||||||
|
var generateTestData = function (cb) {
|
||||||
|
|
||||||
|
console.log('generating large data file...');
|
||||||
|
|
||||||
|
var stream = fs.createWriteStream(file, {
|
||||||
|
encoding: 'utf8'
|
||||||
|
});
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
var max = size;
|
||||||
|
var writing = false
|
||||||
|
var split = ',\n';
|
||||||
|
var doc = randomJsonDoc();
|
||||||
|
stream.write('[');
|
||||||
|
|
||||||
|
function write () {
|
||||||
|
if(writing) return
|
||||||
|
writing = true
|
||||||
|
while(++i < max) {
|
||||||
|
if(Math.random() < 0.001)
|
||||||
|
console.log('generate..', i + ' / ' + size)
|
||||||
|
if(!stream.write(doc + split)) {
|
||||||
|
writing = false
|
||||||
|
return stream.once('drain', write)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stream.write(doc + ']')
|
||||||
|
stream.end();
|
||||||
|
console.log('END')
|
||||||
|
}
|
||||||
|
write()
|
||||||
|
stream.on('close', cb)
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////
|
||||||
|
// Shows that parsing 100000 instances using JSONStream fails
|
||||||
|
//
|
||||||
|
// After several seconds, you will get this crash
|
||||||
|
// FATAL ERROR: JS Allocation failed - process out of memory
|
||||||
|
//////////////////////////////////////////////////////
|
||||||
|
var testJSONStreamParse_causesOutOfMem = function (done) {
|
||||||
|
var items = 0
|
||||||
|
console.log('parsing data files using JSONStream...');
|
||||||
|
|
||||||
|
var parser = JSONStream.parse([true]);
|
||||||
|
var stream = fs.createReadStream(file);
|
||||||
|
stream.pipe(parser);
|
||||||
|
|
||||||
|
parser.on('data', function (data) {
|
||||||
|
items++
|
||||||
|
if(Math.random() < 0.01) console.log(items, '...')
|
||||||
|
});
|
||||||
|
|
||||||
|
parser.on('end', function () {
|
||||||
|
t.equal(items, size)
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////
|
||||||
|
// main
|
||||||
|
//////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
fs.stat(file, function (err, stat) {
|
||||||
|
console.log(stat)
|
||||||
|
if(err)
|
||||||
|
generateTestData(testJSONStreamParse_causesOutOfMem);
|
||||||
|
else
|
||||||
|
testJSONStreamParse_causesOutOfMem()
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
|
||||||
|
|
||||||
|
var fs = require ('fs')
|
||||||
|
, join = require('path').join
|
||||||
|
, file = join(__dirname, 'fixtures','header_footer.json')
|
||||||
|
, JSONStream = require('../')
|
||||||
|
, it = require('it-is')
|
||||||
|
|
||||||
|
var expected = JSON.parse(fs.readFileSync(file))
|
||||||
|
, parser = JSONStream.parse(['rows', /\d+/ /*, 'value'*/])
|
||||||
|
, called = 0
|
||||||
|
, headerCalled = 0
|
||||||
|
, footerCalled = 0
|
||||||
|
, ended = false
|
||||||
|
, parsed = []
|
||||||
|
|
||||||
|
fs.createReadStream(file).pipe(parser)
|
||||||
|
|
||||||
|
parser.on('header', function (data) {
|
||||||
|
headerCalled ++
|
||||||
|
it(data).deepEqual({
|
||||||
|
total_rows: 129,
|
||||||
|
offset: 0
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
parser.on('footer', function (data) {
|
||||||
|
footerCalled ++
|
||||||
|
it(data).deepEqual({
|
||||||
|
foo: { bar: 'baz' }
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
parser.on('data', function (data) {
|
||||||
|
called ++
|
||||||
|
it.has({
|
||||||
|
id: it.typeof('string'),
|
||||||
|
value: {rev: it.typeof('string')},
|
||||||
|
key:it.typeof('string')
|
||||||
|
})
|
||||||
|
it(headerCalled).equal(1)
|
||||||
|
parsed.push(data)
|
||||||
|
})
|
||||||
|
|
||||||
|
parser.on('end', function () {
|
||||||
|
ended = true
|
||||||
|
})
|
||||||
|
|
||||||
|
process.on('exit', function () {
|
||||||
|
it(called).equal(expected.rows.length)
|
||||||
|
it(headerCalled).equal(1)
|
||||||
|
it(footerCalled).equal(1)
|
||||||
|
it(parsed).deepEqual(expected.rows)
|
||||||
|
console.error('PASSED')
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
var JSONStream = require('../');
|
||||||
|
var test = require('tape')
|
||||||
|
|
||||||
|
test('#66', function (t) {
|
||||||
|
var error = 0;
|
||||||
|
var stream = JSONStream
|
||||||
|
.parse()
|
||||||
|
.on('error', function (err) {
|
||||||
|
t.ok(err);
|
||||||
|
error++;
|
||||||
|
})
|
||||||
|
.on('end', function () {
|
||||||
|
t.ok(error === 1);
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.write('["foo":bar[');
|
||||||
|
stream.end();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test('#81 - failure to parse nested objects', function (t) {
|
||||||
|
var stream = JSONStream
|
||||||
|
.parse('.bar.foo')
|
||||||
|
.on('error', function (err) {
|
||||||
|
t.error(err);
|
||||||
|
})
|
||||||
|
.on('end', function () {
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.write('{"bar":{"foo":"baz"}}');
|
||||||
|
stream.end();
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
var test = require('tape');
|
||||||
|
var fs = require ('fs');
|
||||||
|
var join = require('path').join;
|
||||||
|
var couch_sample_file = join(__dirname, 'fixtures','couch_sample.json');
|
||||||
|
var JSONStream = require('../');
|
||||||
|
|
||||||
|
var fixture = {
|
||||||
|
obj: {
|
||||||
|
one: 1,
|
||||||
|
two: 2,
|
||||||
|
three: 3
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function assertFixtureKeys(stream, t) {
|
||||||
|
var keys = [];
|
||||||
|
var values = [];
|
||||||
|
stream.on('data', function(data) {
|
||||||
|
keys.push(data.key);
|
||||||
|
values.push(data.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('end', function() {
|
||||||
|
t.deepEqual(keys, ['one', 'two', 'three']);
|
||||||
|
t.deepEqual(values, [1,2,3]);
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
stream.write(JSON.stringify(fixture));
|
||||||
|
stream.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
test('keys via string', function(t) {
|
||||||
|
var stream = JSONStream.parse('obj.$*');
|
||||||
|
assertFixtureKeys(stream, t);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('keys via array', function(t) {
|
||||||
|
var stream = JSONStream.parse(['obj',{emitKey: true}]);
|
||||||
|
assertFixtureKeys(stream, t);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('path via array', function(t) {
|
||||||
|
var stream = JSONStream.parse(['obj',{emitPath: true}]);
|
||||||
|
|
||||||
|
var paths = [];
|
||||||
|
var values = [];
|
||||||
|
stream.on('data', function(data) {
|
||||||
|
console.log(JSON.stringify(data));
|
||||||
|
paths.push(data.path);
|
||||||
|
values.push(data.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('end', function() {
|
||||||
|
t.deepEqual(paths, [['obj', 'one'], ['obj', 'two'], ['obj', 'three']]);
|
||||||
|
t.deepEqual(values, [1,2,3]);
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
stream.write(JSON.stringify(fixture));
|
||||||
|
stream.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('advanced keys', function(t) {
|
||||||
|
var advanced = fs.readFileSync(couch_sample_file);
|
||||||
|
var stream = JSONStream.parse(['rows', true, 'doc', {emitKey: true}]);
|
||||||
|
|
||||||
|
var keys = [];
|
||||||
|
var values = [];
|
||||||
|
stream.on('data', function(data) {
|
||||||
|
keys.push(data.key);
|
||||||
|
values.push(data.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('end', function() {
|
||||||
|
t.deepEqual(keys, [
|
||||||
|
'_id', '_rev', 'hello',
|
||||||
|
'_id', '_rev', 'hello'
|
||||||
|
]);
|
||||||
|
t.deepEqual(values, [
|
||||||
|
"change1_0.6995461115147918", "1-e240bae28c7bb3667f02760f6398d508", 1,
|
||||||
|
"change2_0.6995461115147918", "1-13677d36b98c0c075145bb8975105153", 2
|
||||||
|
]);
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
stream.write(advanced);
|
||||||
|
stream.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('parent keys', function(t) {
|
||||||
|
var stream = JSONStream.parse('$*');
|
||||||
|
var d = null;
|
||||||
|
stream.on('data', function(data) {
|
||||||
|
if(d) t.fail('should only be called once');
|
||||||
|
d = data;
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('end', function() {
|
||||||
|
t.deepEqual(d,{
|
||||||
|
key: 'obj',
|
||||||
|
value: fixture.obj
|
||||||
|
});
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
stream.write(JSON.stringify(fixture));
|
||||||
|
stream.end();
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
|
||||||
|
var test = require('tape')
|
||||||
|
|
||||||
|
var JSONStream = require('../')
|
||||||
|
|
||||||
|
test('map function', function (t) {
|
||||||
|
|
||||||
|
var actual = []
|
||||||
|
|
||||||
|
stream = JSONStream.parse([true], function (e) { return e*10 })
|
||||||
|
stream.on('data', function (v) { actual.push(v)})
|
||||||
|
stream.on('end', function () {
|
||||||
|
t.deepEqual(actual, [10,20,30,40,50,60])
|
||||||
|
t.end()
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
stream.write(JSON.stringify([1,2,3,4,5,6], null, 2))
|
||||||
|
stream.end()
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
test('filter function', function (t) {
|
||||||
|
|
||||||
|
var actual = []
|
||||||
|
|
||||||
|
stream = JSONStream
|
||||||
|
.parse([true], function (e) { return e%2 ? e : null})
|
||||||
|
.on('data', function (v) { actual.push(v)})
|
||||||
|
.on('end', function () {
|
||||||
|
t.deepEqual(actual, [1,3,5])
|
||||||
|
t.end()
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
stream.write(JSON.stringify([1,2,3,4,5,6], null, 2))
|
||||||
|
stream.end()
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
var fs = require ('fs');
|
||||||
|
var net = require('net');
|
||||||
|
var join = require('path').join;
|
||||||
|
var file = join(__dirname, 'fixtures','all_npm.json');
|
||||||
|
var it = require('it-is');
|
||||||
|
var JSONStream = require('../');
|
||||||
|
|
||||||
|
var str = fs.readFileSync(file);
|
||||||
|
|
||||||
|
var datas = {}
|
||||||
|
|
||||||
|
var server = net.createServer(function(client) {
|
||||||
|
var data_calls = 0;
|
||||||
|
var parser = JSONStream.parse(['rows', true, 'key']);
|
||||||
|
parser.on('data', function(data) {
|
||||||
|
++ data_calls;
|
||||||
|
datas[data] = (datas[data] || 0) + 1
|
||||||
|
it(data).typeof('string')
|
||||||
|
});
|
||||||
|
|
||||||
|
parser.on('end', function() {
|
||||||
|
console.log('END')
|
||||||
|
var min = Infinity
|
||||||
|
for (var d in datas)
|
||||||
|
min = min > datas[d] ? datas[d] : min
|
||||||
|
it(min).equal(3);
|
||||||
|
server.close();
|
||||||
|
});
|
||||||
|
client.pipe(parser);
|
||||||
|
});
|
||||||
|
server.listen(9999);
|
||||||
|
|
||||||
|
var client = net.connect({ port : 9999 }, function() {
|
||||||
|
var msgs = str + ' ' + str + '\n\n' + str
|
||||||
|
client.end(msgs);
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
var fs = require ('fs');
|
||||||
|
var net = require('net');
|
||||||
|
var join = require('path').join;
|
||||||
|
var file = join(__dirname, 'fixtures','all_npm.json');
|
||||||
|
var it = require('it-is');
|
||||||
|
var JSONStream = require('../');
|
||||||
|
|
||||||
|
var str = fs.readFileSync(file);
|
||||||
|
|
||||||
|
var server = net.createServer(function(client) {
|
||||||
|
var data_calls = 0;
|
||||||
|
var parser = JSONStream.parse();
|
||||||
|
parser.on('error', function(err) {
|
||||||
|
console.log(err);
|
||||||
|
server.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
parser.on('end', function() {
|
||||||
|
console.log('END');
|
||||||
|
server.close();
|
||||||
|
});
|
||||||
|
client.pipe(parser);
|
||||||
|
});
|
||||||
|
server.listen(9999);
|
||||||
|
|
||||||
|
var client = net.connect({ port : 9999 }, function() {
|
||||||
|
var msgs = str + '}';
|
||||||
|
client.end(msgs);
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
var JSONStream = require('../')
|
||||||
|
|
||||||
|
var data = [
|
||||||
|
{ID: 1, optional: null},
|
||||||
|
{ID: 2, optional: null},
|
||||||
|
{ID: 3, optional: 20},
|
||||||
|
{ID: 4, optional: null},
|
||||||
|
{ID: 5, optional: 'hello'},
|
||||||
|
{ID: 6, optional: null}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
var test = require('tape')
|
||||||
|
|
||||||
|
test ('null properties', function (t) {
|
||||||
|
var actual = []
|
||||||
|
var stream =
|
||||||
|
|
||||||
|
JSONStream.parse('*.optional')
|
||||||
|
.on('data', function (v) { actual.push(v) })
|
||||||
|
.on('end', function () {
|
||||||
|
t.deepEqual(actual, [20, 'hello'])
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
stream.write(JSON.stringify(data, null, 2))
|
||||||
|
stream.end()
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
sometimes jsonparse changes numbers slightly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var r = Math.random()
|
||||||
|
, Parser = require('jsonparse')
|
||||||
|
, p = new Parser()
|
||||||
|
, assert = require('assert')
|
||||||
|
, times = 20
|
||||||
|
, bufferFrom = Buffer.from && Buffer.from !== Uint8Array.from
|
||||||
|
, str
|
||||||
|
|
||||||
|
while (times --) {
|
||||||
|
|
||||||
|
assert.equal(JSON.parse(JSON.stringify(r)), r, 'core JSON')
|
||||||
|
|
||||||
|
p.onValue = function (v) {
|
||||||
|
console.error('parsed', v)
|
||||||
|
assert.equal(v,r)
|
||||||
|
}
|
||||||
|
console.error('correct', r)
|
||||||
|
str = JSON.stringify([r])
|
||||||
|
p.write (bufferFrom ? Buffer.from(str) : new Buffer(str))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
var readdirSync = require('fs').readdirSync
|
||||||
|
var spawnSync = require('child_process').spawnSync
|
||||||
|
var extname = require('path').extname
|
||||||
|
|
||||||
|
var files = readdirSync(__dirname)
|
||||||
|
files.forEach(function(file){
|
||||||
|
if (extname(file) !== '.js' || file === 'run.js')
|
||||||
|
return
|
||||||
|
console.log(`*** ${file} ***`)
|
||||||
|
var result = spawnSync(process.argv0, [file], { stdio: 'inherit', cwd: __dirname} )
|
||||||
|
if (result.status !== 0)
|
||||||
|
process.exit(result.status)
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
|
||||||
|
var fs = require ('fs')
|
||||||
|
, join = require('path').join
|
||||||
|
, file = join(__dirname, 'fixtures','all_npm.json')
|
||||||
|
, JSONStream = require('../')
|
||||||
|
, it = require('it-is').style('colour')
|
||||||
|
|
||||||
|
function randomObj () {
|
||||||
|
return (
|
||||||
|
Math.random () < 0.4
|
||||||
|
? {hello: 'eonuhckmqjk',
|
||||||
|
whatever: 236515,
|
||||||
|
lies: true,
|
||||||
|
nothing: [null],
|
||||||
|
stuff: [Math.random(),Math.random(),Math.random()]
|
||||||
|
}
|
||||||
|
: ['AOREC', 'reoubaor', {ouec: 62642}, [[[], {}, 53]]]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var expected = []
|
||||||
|
, stringify = JSONStream.stringify()
|
||||||
|
, es = require('event-stream')
|
||||||
|
, stringified = ''
|
||||||
|
, called = 0
|
||||||
|
, count = 10
|
||||||
|
, ended = false
|
||||||
|
|
||||||
|
while (count --)
|
||||||
|
expected.push(randomObj())
|
||||||
|
|
||||||
|
es.connect(
|
||||||
|
es.readArray(expected),
|
||||||
|
stringify,
|
||||||
|
//JSONStream.parse([/./]),
|
||||||
|
es.writeArray(function (err, lines) {
|
||||||
|
|
||||||
|
it(JSON.parse(lines.join(''))).deepEqual(expected)
|
||||||
|
console.error('PASSED')
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
|
||||||
|
var fs = require ('fs')
|
||||||
|
, join = require('path').join
|
||||||
|
, file = join(__dirname, 'fixtures','all_npm.json')
|
||||||
|
, JSONStream = require('../')
|
||||||
|
, it = require('it-is').style('colour')
|
||||||
|
, es = require('event-stream')
|
||||||
|
, pending = 10
|
||||||
|
, passed = true
|
||||||
|
|
||||||
|
function randomObj () {
|
||||||
|
return (
|
||||||
|
Math.random () < 0.4
|
||||||
|
? {hello: 'eonuhckmqjk',
|
||||||
|
whatever: 236515,
|
||||||
|
lies: true,
|
||||||
|
nothing: [null],
|
||||||
|
stuff: [Math.random(),Math.random(),Math.random()]
|
||||||
|
}
|
||||||
|
: ['AOREC', 'reoubaor', {ouec: 62642}, [[[], {}, 53]]]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var ix = 0; ix < pending; ix++) (function (count) {
|
||||||
|
var expected = {}
|
||||||
|
, stringify = JSONStream.stringifyObject()
|
||||||
|
|
||||||
|
es.connect(
|
||||||
|
stringify,
|
||||||
|
es.writeArray(function (err, lines) {
|
||||||
|
it(JSON.parse(lines.join(''))).deepEqual(expected)
|
||||||
|
if (--pending === 0) {
|
||||||
|
console.error('PASSED')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
while (count --) {
|
||||||
|
var key = Math.random().toString(16).slice(2)
|
||||||
|
expected[key] = randomObj()
|
||||||
|
stringify.write([ key, expected[key] ])
|
||||||
|
}
|
||||||
|
|
||||||
|
process.nextTick(function () {
|
||||||
|
stringify.end()
|
||||||
|
})
|
||||||
|
})(ix)
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
|
||||||
|
|
||||||
|
var fs = require ('fs')
|
||||||
|
, join = require('path').join
|
||||||
|
, file = join(__dirname, 'fixtures','all_npm.json')
|
||||||
|
, JSONStream = require('../')
|
||||||
|
, it = require('it-is')
|
||||||
|
|
||||||
|
var expected = JSON.parse(fs.readFileSync(file))
|
||||||
|
, parser = JSONStream.parse(['rows', /\d+/ /*, 'value'*/])
|
||||||
|
, called = 0
|
||||||
|
, ended = false
|
||||||
|
, parsed = []
|
||||||
|
|
||||||
|
fs.createReadStream(file).pipe(parser)
|
||||||
|
|
||||||
|
parser.on('data', function (data) {
|
||||||
|
called ++
|
||||||
|
it.has({
|
||||||
|
id: it.typeof('string'),
|
||||||
|
value: {rev: it.typeof('string')},
|
||||||
|
key:it.typeof('string')
|
||||||
|
})
|
||||||
|
parsed.push(data)
|
||||||
|
})
|
||||||
|
|
||||||
|
parser.on('end', function () {
|
||||||
|
ended = true
|
||||||
|
})
|
||||||
|
|
||||||
|
process.on('exit', function () {
|
||||||
|
it(called).equal(expected.rows.length)
|
||||||
|
it(parsed).deepEqual(expected.rows)
|
||||||
|
console.error('PASSED')
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
|
||||||
|
|
||||||
|
var fs = require ('fs')
|
||||||
|
, join = require('path').join
|
||||||
|
, file = join(__dirname, '..','package.json')
|
||||||
|
, JSONStream = require('../')
|
||||||
|
, it = require('it-is')
|
||||||
|
|
||||||
|
var expected = JSON.parse(fs.readFileSync(file))
|
||||||
|
, parser = JSONStream.parse([])
|
||||||
|
, called = 0
|
||||||
|
, ended = false
|
||||||
|
, parsed = []
|
||||||
|
|
||||||
|
fs.createReadStream(file).pipe(parser)
|
||||||
|
|
||||||
|
parser.on('data', function (data) {
|
||||||
|
called ++
|
||||||
|
it(data).deepEqual(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
parser.on('end', function () {
|
||||||
|
ended = true
|
||||||
|
})
|
||||||
|
|
||||||
|
process.on('exit', function () {
|
||||||
|
it(called).equal(1)
|
||||||
|
console.error('PASSED')
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
|
||||||
|
var fs = require ('fs')
|
||||||
|
, join = require('path').join
|
||||||
|
, file = join(__dirname, 'fixtures','all_npm.json')
|
||||||
|
, JSONStream = require('../')
|
||||||
|
, it = require('it-is').style('colour')
|
||||||
|
|
||||||
|
function randomObj () {
|
||||||
|
return (
|
||||||
|
Math.random () < 0.4
|
||||||
|
? {hello: 'eonuhckmqjk',
|
||||||
|
whatever: 236515,
|
||||||
|
lies: true,
|
||||||
|
nothing: [null],
|
||||||
|
// stuff: [Math.random(),Math.random(),Math.random()]
|
||||||
|
}
|
||||||
|
: ['AOREC', 'reoubaor', {ouec: 62642}, [[[], {}, 53]]]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var expected = []
|
||||||
|
, stringify = JSONStream.stringify()
|
||||||
|
, es = require('event-stream')
|
||||||
|
, stringified = ''
|
||||||
|
, called = 0
|
||||||
|
, count = 10
|
||||||
|
, ended = false
|
||||||
|
|
||||||
|
while (count --)
|
||||||
|
expected.push(randomObj())
|
||||||
|
|
||||||
|
es.connect(
|
||||||
|
es.readArray(expected),
|
||||||
|
stringify,
|
||||||
|
JSONStream.parse([/./]),
|
||||||
|
es.writeArray(function (err, lines) {
|
||||||
|
|
||||||
|
it(lines).has(expected)
|
||||||
|
console.error('PASSED')
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"node": true,
|
||||||
|
"bitwise": false,
|
||||||
|
"camelcase": true,
|
||||||
|
"eqeqeq": true,
|
||||||
|
"forin": true,
|
||||||
|
"freeze": true,
|
||||||
|
"immed": true,
|
||||||
|
"indent": 4,
|
||||||
|
"latedef": "nofunc",
|
||||||
|
"newcap": true,
|
||||||
|
"noarg": true,
|
||||||
|
"quotmark": "single",
|
||||||
|
"undef": true,
|
||||||
|
"unused": true,
|
||||||
|
"strict": true,
|
||||||
|
"trailing": true,
|
||||||
|
"smarttabs": true,
|
||||||
|
"globals": {
|
||||||
|
"describe": false,
|
||||||
|
"it": false,
|
||||||
|
"beforeEach": false,
|
||||||
|
"afterEach": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
/.idea
|
||||||
|
/atlassian-ide-plugin.xml
|
||||||
|
*.iml
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
/node_modules
|
||||||
|
/coverage
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
language: node_js
|
||||||
|
node_js:
|
||||||
|
- "0.11"
|
||||||
|
- "0.10"
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
# add-stream [](https://travis-ci.org/wilsonjackson/add-stream)
|
||||||
|
|
||||||
|
> Append the contents of one stream onto another.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
var fs = require('fs');
|
||||||
|
var es = require('event-stream');
|
||||||
|
var addStream = require('add-stream');
|
||||||
|
|
||||||
|
// Append strings/buffers
|
||||||
|
fs.createReadStream('1.txt') // 1.txt contains: number1
|
||||||
|
.pipe(addStream(fs.createReadStream('2.txt'))) // 2.txt contains: number2
|
||||||
|
.pipe(fs.createWriteStream('appended.txt')); // appended.txt contains: number1number2
|
||||||
|
|
||||||
|
// Append object streams
|
||||||
|
es.readArray([1, 2, 3])
|
||||||
|
.pipe(addStream.obj(es.readArray([4, 5, 6])))
|
||||||
|
.pipe(es.writeArray(function (err, array) {
|
||||||
|
console.log(array); // [ 1, 2, 3, 4, 5, 6 ]
|
||||||
|
}));
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### var transformStream = addStream(stream, opts = {})
|
||||||
|
|
||||||
|
Create a transform stream that appends the contents of `stream` onto whatever
|
||||||
|
is piped into it. Options are passed to the transform stream's constructor.
|
||||||
|
|
||||||
|
### var transformStream = addStream.obj(stream, opts = {})
|
||||||
|
|
||||||
|
A convenient shortcut for `addStream(stream, {objectMode: true})`.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var PassThrough = require('stream').PassThrough;
|
||||||
|
var Writable = require('stream').Writable;
|
||||||
|
var util = require('util');
|
||||||
|
|
||||||
|
util.inherits(Appendee, PassThrough);
|
||||||
|
util.inherits(Appender, Writable);
|
||||||
|
|
||||||
|
function Appendee(factory, opts) {
|
||||||
|
PassThrough.call(this, opts);
|
||||||
|
this.factory = factory;
|
||||||
|
this.opts = opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
//noinspection JSUnusedGlobalSymbols
|
||||||
|
Appendee.prototype._flush = function (end) {
|
||||||
|
var stream = this.factory();
|
||||||
|
stream.pipe(new Appender(this, this.opts))
|
||||||
|
.on('finish', end);
|
||||||
|
stream.resume();
|
||||||
|
};
|
||||||
|
|
||||||
|
function Appender(target, opts) {
|
||||||
|
Writable.call(this, opts);
|
||||||
|
this.target = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
//noinspection JSUnusedGlobalSymbols
|
||||||
|
Appender.prototype._write = function (chunk, enc, cb) {
|
||||||
|
this.target.push(chunk);
|
||||||
|
cb();
|
||||||
|
};
|
||||||
|
|
||||||
|
function addStream(stream, opts) {
|
||||||
|
opts = opts || {};
|
||||||
|
var factory;
|
||||||
|
if (typeof stream === 'function') {
|
||||||
|
factory = stream;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stream.pause();
|
||||||
|
factory = function () {
|
||||||
|
return stream;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return new Appendee(factory, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
addStream.obj = function (stream, opts) {
|
||||||
|
opts = opts || {};
|
||||||
|
opts.objectMode = true;
|
||||||
|
return addStream(stream, opts);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = addStream;
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"name": "add-stream",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Append the contents of one stream onto another.",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "mocha",
|
||||||
|
"cover": "istanbul cover node_modules/.bin/_mocha -- -u exports -R spec"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/wilsonjackson/add-stream"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"stream",
|
||||||
|
"append",
|
||||||
|
"add",
|
||||||
|
"concat",
|
||||||
|
"gulpfriendly"
|
||||||
|
],
|
||||||
|
"author": "Majid Burney <moocow@euphoricsoup.com>",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/wilsonjackson/add-stream/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/wilsonjackson/add-stream",
|
||||||
|
"dependencies": {},
|
||||||
|
"devDependencies": {
|
||||||
|
"chai": "^1.10.0",
|
||||||
|
"event-stream": "^3.1.7",
|
||||||
|
"istanbul": "^0.3.4",
|
||||||
|
"mocha": "^2.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var chai = require('chai');
|
||||||
|
var expect = chai.expect;
|
||||||
|
var es = require('event-stream');
|
||||||
|
var addStream = require('../');
|
||||||
|
|
||||||
|
describe('add-stream', function () {
|
||||||
|
function emit(chunks) {
|
||||||
|
var mutableChunks = [].concat(chunks);
|
||||||
|
return es.readable(function (count, callback) {
|
||||||
|
if (mutableChunks.length === 0) {
|
||||||
|
return this.emit('end');
|
||||||
|
}
|
||||||
|
callback(null, mutableChunks.shift());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('buffer mode', function () {
|
||||||
|
it('should append a stream', function (done) {
|
||||||
|
var firstChunks = ['abc', 'def'];
|
||||||
|
var secondChunks = ['ghi', 'jkl'];
|
||||||
|
emit(firstChunks)
|
||||||
|
.pipe(addStream(emit(secondChunks)))
|
||||||
|
.pipe(es.wait(function (err, buffer) {
|
||||||
|
expect(buffer.toString()).to.equal(firstChunks.concat(secondChunks).join(''));
|
||||||
|
done();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should append a stream from a factory function', function (done) {
|
||||||
|
var firstChunks = ['abc', 'def'];
|
||||||
|
var secondChunks = ['ghi', 'jkl'];
|
||||||
|
emit(firstChunks)
|
||||||
|
.pipe(addStream(function () {
|
||||||
|
return emit(secondChunks);
|
||||||
|
}))
|
||||||
|
.pipe(es.wait(function (err, buffer) {
|
||||||
|
expect(buffer.toString()).to.equal(firstChunks.concat(secondChunks).join(''));
|
||||||
|
done();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('object mode', function () {
|
||||||
|
it('should append a stream', function (done) {
|
||||||
|
es.readArray([{p: 1}, {p: 2}, {p: 3}])
|
||||||
|
.pipe(addStream.obj(es.readArray([{p: 4}, {p: 5}, {p: 6}])))
|
||||||
|
.pipe(es.writeArray(function (err, array) {
|
||||||
|
expect(array).to.eql([{p: 1}, {p: 2}, {p: 3}, {p: 4}, {p: 5}, {p: 6}]);
|
||||||
|
done();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should append a stream from a factory function', function (done) {
|
||||||
|
es.readArray([{p: 1}, {p: 2}, {p: 3}])
|
||||||
|
.pipe(addStream.obj(function () {return es.readArray([{p: 4}, {p: 5}, {p: 6}])}))
|
||||||
|
.pipe(es.writeArray(function (err, array) {
|
||||||
|
expect(array).to.eql([{p: 1}, {p: 2}, {p: 3}, {p: 4}, {p: 5}, {p: 6}]);
|
||||||
|
done();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
'use strict';
|
||||||
|
module.exports = function (arr, predicate, ctx) {
|
||||||
|
if (typeof Array.prototype.findIndex === 'function') {
|
||||||
|
return arr.findIndex(predicate, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof predicate !== 'function') {
|
||||||
|
throw new TypeError('predicate must be a function');
|
||||||
|
}
|
||||||
|
|
||||||
|
var list = Object(arr);
|
||||||
|
var len = list.length;
|
||||||
|
|
||||||
|
if (len === 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < len; i++) {
|
||||||
|
if (predicate.call(ctx, list[i], i, list)) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
{
|
||||||
|
"name": "array-find-index",
|
||||||
|
"version": "1.0.2",
|
||||||
|
"description": "ES2015 `Array#findIndex()` ponyfill",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": "sindresorhus/array-find-index",
|
||||||
|
"author": {
|
||||||
|
"name": "Sindre Sorhus",
|
||||||
|
"email": "sindresorhus@gmail.com",
|
||||||
|
"url": "sindresorhus.com"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "xo && ava"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"index.js"
|
||||||
|
],
|
||||||
|
"keywords": [
|
||||||
|
"es2015",
|
||||||
|
"ponyfill",
|
||||||
|
"polyfill",
|
||||||
|
"shim",
|
||||||
|
"find",
|
||||||
|
"index",
|
||||||
|
"findindex",
|
||||||
|
"array"
|
||||||
|
],
|
||||||
|
"devDependencies": {
|
||||||
|
"ava": "*",
|
||||||
|
"xo": "*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
# array-find-index [](https://travis-ci.org/sindresorhus/array-find-index)
|
||||||
|
|
||||||
|
> ES2015 [`Array#findIndex()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex) [ponyfill](https://ponyfill.com)
|
||||||
|
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npm install --save array-find-index
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
const arrayFindIndex = require('array-find-index');
|
||||||
|
|
||||||
|
arrayFindIndex(['rainbow', 'unicorn', 'pony'], x => x === 'unicorn');
|
||||||
|
//=> 1
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
Same as `Array#findIndex()`, but with the input array as the first argument.
|
||||||
|
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
# [![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Dependency Status][daviddm-image]][daviddm-url] [![Coverage Status][coveralls-image]][coveralls-url]
|
||||||
|
|
||||||
|
> Turn anything into an array
|
||||||
|
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm install --save array-ify
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
var arrayify = require('array-ify');
|
||||||
|
|
||||||
|
arrayify('unicorn');
|
||||||
|
//=> ['unicorn']
|
||||||
|
|
||||||
|
arrayify(['unicorn']);
|
||||||
|
//=> ['unicorn']
|
||||||
|
|
||||||
|
arrayify(null);
|
||||||
|
//=> [null]
|
||||||
|
|
||||||
|
arrayify(undefined);
|
||||||
|
//=> [undefined]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [arrify](https://github.com/sindresorhus/arrify) - Convert a value to an array
|
||||||
|
|
||||||
|
The difference that is this module does **NOT** turn `null` or `undefined` to an empty array.
|
||||||
|
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT © [Steve Mao](https://github.com/stevemao)
|
||||||
|
|
||||||
|
|
||||||
|
[npm-image]: https://badge.fury.io/js/array-ify.svg
|
||||||
|
[npm-url]: https://npmjs.org/package/array-ify
|
||||||
|
[travis-image]: https://travis-ci.org/stevemao/array-ify.svg?branch=master
|
||||||
|
[travis-url]: https://travis-ci.org/stevemao/array-ify
|
||||||
|
[daviddm-image]: https://david-dm.org/stevemao/array-ify.svg?theme=shields.io
|
||||||
|
[daviddm-url]: https://david-dm.org/stevemao/array-ify
|
||||||
|
[coveralls-image]: https://coveralls.io/repos/stevemao/array-ify/badge.svg
|
||||||
|
[coveralls-url]: https://coveralls.io/r/stevemao/array-ify
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
'use strict';
|
||||||
|
module.exports = function(val) {
|
||||||
|
return Array.isArray(val) ? val : [val];
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
{
|
||||||
|
"name": "array-ify",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Turn anything into an array",
|
||||||
|
"homepage": "https://github.com/stevemao/array-ify",
|
||||||
|
"author": {
|
||||||
|
"name": "Steve Mao",
|
||||||
|
"email": "maochenyan@gmail.com",
|
||||||
|
"url": "https://github.com/stevemao"
|
||||||
|
},
|
||||||
|
"repository": "stevemao/array-ify",
|
||||||
|
"license": "MIT",
|
||||||
|
"files": [
|
||||||
|
"index.js"
|
||||||
|
],
|
||||||
|
"keywords": [
|
||||||
|
"array-ify",
|
||||||
|
"array",
|
||||||
|
"arr",
|
||||||
|
"arrify",
|
||||||
|
"arrayify",
|
||||||
|
"convert",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"devDependencies": {
|
||||||
|
"coveralls": "^2.11.2",
|
||||||
|
"istanbul": "^0.3.8",
|
||||||
|
"jscs": "^1.11.3",
|
||||||
|
"jshint": "^2.6.3",
|
||||||
|
"mocha": "*"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"coverage": "istanbul cover _mocha -- -R spec && rm -rf ./coverage",
|
||||||
|
"lint": "jshint *.js --exclude node_modules && jscs *.js",
|
||||||
|
"test": "npm run-script lint && mocha"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
'use strict';
|
||||||
|
module.exports = function (val) {
|
||||||
|
if (val === null || val === undefined) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array.isArray(val) ? val : [val];
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"name": "arrify",
|
||||||
|
"version": "1.0.1",
|
||||||
|
"description": "Convert a value to an array",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": "sindresorhus/arrify",
|
||||||
|
"author": {
|
||||||
|
"name": "Sindre Sorhus",
|
||||||
|
"email": "sindresorhus@gmail.com",
|
||||||
|
"url": "sindresorhus.com"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "xo && ava"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"index.js"
|
||||||
|
],
|
||||||
|
"keywords": [
|
||||||
|
"array",
|
||||||
|
"arr",
|
||||||
|
"arrify",
|
||||||
|
"arrayify",
|
||||||
|
"convert",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"devDependencies": {
|
||||||
|
"ava": "*",
|
||||||
|
"xo": "*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
# arrify [](https://travis-ci.org/sindresorhus/arrify)
|
||||||
|
|
||||||
|
> Convert a value to an array
|
||||||
|
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npm install --save arrify
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
const arrify = require('arrify');
|
||||||
|
|
||||||
|
arrify('unicorn');
|
||||||
|
//=> ['unicorn']
|
||||||
|
|
||||||
|
arrify(['unicorn']);
|
||||||
|
//=> ['unicorn']
|
||||||
|
|
||||||
|
arrify(null);
|
||||||
|
//=> []
|
||||||
|
|
||||||
|
arrify(undefined);
|
||||||
|
//=> []
|
||||||
|
```
|
||||||
|
|
||||||
|
*Supplying `null` or `undefined` results in an empty array.*
|
||||||
|
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT © [Sindre Sorhus](http://sindresorhus.com)
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2016, 2018 Linus Unnebäck
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
var toString = Object.prototype.toString
|
||||||
|
|
||||||
|
var isModern = (
|
||||||
|
typeof Buffer.alloc === 'function' &&
|
||||||
|
typeof Buffer.allocUnsafe === 'function' &&
|
||||||
|
typeof Buffer.from === 'function'
|
||||||
|
)
|
||||||
|
|
||||||
|
function isArrayBuffer (input) {
|
||||||
|
return toString.call(input).slice(8, -1) === 'ArrayBuffer'
|
||||||
|
}
|
||||||
|
|
||||||
|
function fromArrayBuffer (obj, byteOffset, length) {
|
||||||
|
byteOffset >>>= 0
|
||||||
|
|
||||||
|
var maxLength = obj.byteLength - byteOffset
|
||||||
|
|
||||||
|
if (maxLength < 0) {
|
||||||
|
throw new RangeError("'offset' is out of bounds")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length === undefined) {
|
||||||
|
length = maxLength
|
||||||
|
} else {
|
||||||
|
length >>>= 0
|
||||||
|
|
||||||
|
if (length > maxLength) {
|
||||||
|
throw new RangeError("'length' is out of bounds")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return isModern
|
||||||
|
? Buffer.from(obj.slice(byteOffset, byteOffset + length))
|
||||||
|
: new Buffer(new Uint8Array(obj.slice(byteOffset, byteOffset + length)))
|
||||||
|
}
|
||||||
|
|
||||||
|
function fromString (string, encoding) {
|
||||||
|
if (typeof encoding !== 'string' || encoding === '') {
|
||||||
|
encoding = 'utf8'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Buffer.isEncoding(encoding)) {
|
||||||
|
throw new TypeError('"encoding" must be a valid string encoding')
|
||||||
|
}
|
||||||
|
|
||||||
|
return isModern
|
||||||
|
? Buffer.from(string, encoding)
|
||||||
|
: new Buffer(string, encoding)
|
||||||
|
}
|
||||||
|
|
||||||
|
function bufferFrom (value, encodingOrOffset, length) {
|
||||||
|
if (typeof value === 'number') {
|
||||||
|
throw new TypeError('"value" argument must not be a number')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isArrayBuffer(value)) {
|
||||||
|
return fromArrayBuffer(value, encodingOrOffset, length)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
return fromString(value, encodingOrOffset)
|
||||||
|
}
|
||||||
|
|
||||||
|
return isModern
|
||||||
|
? Buffer.from(value)
|
||||||
|
: new Buffer(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = bufferFrom
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"name": "buffer-from",
|
||||||
|
"version": "1.1.1",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": "LinusU/buffer-from",
|
||||||
|
"files": [
|
||||||
|
"index.js"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"test": "standard && node test"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"standard": "^7.1.2"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"buffer",
|
||||||
|
"buffer from"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
# Buffer From
|
||||||
|
|
||||||
|
A [ponyfill](https://ponyfill.com) for `Buffer.from`, uses native implementation if available.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install --save buffer-from
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
const bufferFrom = require('buffer-from')
|
||||||
|
|
||||||
|
console.log(bufferFrom([1, 2, 3, 4]))
|
||||||
|
//=> <Buffer 01 02 03 04>
|
||||||
|
|
||||||
|
const arr = new Uint8Array([1, 2, 3, 4])
|
||||||
|
console.log(bufferFrom(arr.buffer, 1, 2))
|
||||||
|
//=> <Buffer 02 03>
|
||||||
|
|
||||||
|
console.log(bufferFrom('test', 'utf8'))
|
||||||
|
//=> <Buffer 74 65 73 74>
|
||||||
|
|
||||||
|
const buf = bufferFrom('test')
|
||||||
|
console.log(bufferFrom(buf))
|
||||||
|
//=> <Buffer 74 65 73 74>
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### bufferFrom(array)
|
||||||
|
|
||||||
|
- `array` <Array>
|
||||||
|
|
||||||
|
Allocates a new `Buffer` using an `array` of octets.
|
||||||
|
|
||||||
|
### bufferFrom(arrayBuffer[, byteOffset[, length]])
|
||||||
|
|
||||||
|
- `arrayBuffer` <ArrayBuffer> The `.buffer` property of a TypedArray or ArrayBuffer
|
||||||
|
- `byteOffset` <Integer> Where to start copying from `arrayBuffer`. **Default:** `0`
|
||||||
|
- `length` <Integer> How many bytes to copy from `arrayBuffer`. **Default:** `arrayBuffer.length - byteOffset`
|
||||||
|
|
||||||
|
When passed a reference to the `.buffer` property of a TypedArray instance, the
|
||||||
|
newly created `Buffer` will share the same allocated memory as the TypedArray.
|
||||||
|
|
||||||
|
The optional `byteOffset` and `length` arguments specify a memory range within
|
||||||
|
the `arrayBuffer` that will be shared by the `Buffer`.
|
||||||
|
|
||||||
|
### bufferFrom(buffer)
|
||||||
|
|
||||||
|
- `buffer` <Buffer> An existing `Buffer` to copy data from
|
||||||
|
|
||||||
|
Copies the passed `buffer` data onto a new `Buffer` instance.
|
||||||
|
|
||||||
|
### bufferFrom(string[, encoding])
|
||||||
|
|
||||||
|
- `string` <String> A string to encode.
|
||||||
|
- `encoding` <String> The encoding of `string`. **Default:** `'utf8'`
|
||||||
|
|
||||||
|
Creates a new `Buffer` containing the given JavaScript string `string`. If
|
||||||
|
provided, the `encoding` parameter identifies the character encoding of
|
||||||
|
`string`.
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
- [buffer-alloc](https://github.com/LinusU/buffer-alloc) A ponyfill for `Buffer.alloc`
|
||||||
|
- [buffer-alloc-unsafe](https://github.com/LinusU/buffer-alloc-unsafe) A ponyfill for `Buffer.allocUnsafe`
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
'use strict';
|
||||||
|
const mapObj = require('map-obj');
|
||||||
|
const camelCase = require('camelcase');
|
||||||
|
const QuickLru = require('quick-lru');
|
||||||
|
|
||||||
|
const has = (arr, key) => arr.some(x => typeof x === 'string' ? x === key : x.test(key));
|
||||||
|
const cache = new QuickLru({maxSize: 100000});
|
||||||
|
|
||||||
|
const camelCaseConvert = (input, opts) => {
|
||||||
|
opts = Object.assign({
|
||||||
|
deep: false
|
||||||
|
}, opts);
|
||||||
|
|
||||||
|
const exclude = opts.exclude;
|
||||||
|
|
||||||
|
return mapObj(input, (key, val) => {
|
||||||
|
if (!(exclude && has(exclude, key))) {
|
||||||
|
if (cache.has(key)) {
|
||||||
|
key = cache.get(key);
|
||||||
|
} else {
|
||||||
|
const ret = camelCase(key);
|
||||||
|
|
||||||
|
if (key.length < 100) { // Prevent abuse
|
||||||
|
cache.set(key, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
key = ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [key, val];
|
||||||
|
}, {deep: opts.deep});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = (input, opts) => {
|
||||||
|
if (Array.isArray(input)) {
|
||||||
|
return Object.keys(input).map(key => camelCaseConvert(input[key], opts));
|
||||||
|
}
|
||||||
|
return camelCaseConvert(input, opts);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue