├── .babelrc.js ├── .eslintrc.js ├── .gitattributes ├── .github ├── dependabot.yml └── workflows │ └── ci.yml ├── .gitignore ├── .prettierrc ├── .yarn ├── releases │ └── yarn-2.4.2.cjs └── sdks │ ├── eslint │ ├── bin │ │ └── eslint.js │ ├── lib │ │ └── api.js │ └── package.json │ ├── integrations.yml │ ├── prettier │ ├── index.js │ └── package.json │ └── typescript │ ├── bin │ ├── tsc │ └── tsserver │ ├── lib │ ├── tsc.js │ ├── tsserver.js │ ├── tsserverlibrary.js │ └── typescript.js │ └── package.json ├── .yarnrc.yml ├── README.md ├── jest.config.js ├── jest.setup.js ├── package.json ├── renovate.json ├── src ├── __fixtures__ │ ├── yarn-lock1.txt │ └── yarn-lock2.txt ├── __nock-fixtures__ │ ├── yarn-lock1-offline.json │ ├── yarn-lock1.json │ └── yarn-lock2.json ├── __snapshots__ │ ├── convert.test.ts.snap │ └── stringify.test.ts.snap ├── convert.test.ts ├── convert.ts ├── index.ts ├── package-info.ts ├── stringify.test.ts ├── stringify.ts ├── v1lock.ts ├── v2lock.ts └── validation.ts ├── tsconfig.build.json ├── tsconfig.json └── yarn.lock /.babelrc.js: -------------------------------------------------------------------------------- 1 | /** @type {import('@babel/core').TransformOptions} */ 2 | const config = { 3 | presets: [ 4 | [ 5 | "@babel/preset-env", 6 | { 7 | targets: { 8 | node: "12", 9 | }, 10 | shippedProposals: true, 11 | }, 12 | ], 13 | "@babel/preset-typescript", 14 | ], 15 | plugins: [ 16 | [ 17 | "@babel/plugin-transform-runtime", 18 | { 19 | corejs: { version: 3, proposals: true }, 20 | version: "^7.13.15", 21 | }, 22 | ], 23 | ], 24 | }; 25 | 26 | module.exports = config; 27 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | /** @type {import('eslint').Linter.Config} */ 2 | const config = { 3 | parser: "@typescript-eslint/parser", 4 | parserOptions: { 5 | project: "tsconfig.json", 6 | }, 7 | extends: [ 8 | "eslint:recommended", 9 | "plugin:@typescript-eslint/recommended", 10 | "plugin:@typescript-eslint/recommended-requiring-type-checking", 11 | "plugin:jest/recommended", 12 | "prettier", 13 | ], 14 | ignorePatterns: ["dist/**/*", "!.babelrc.js"], 15 | rules: { 16 | "@typescript-eslint/no-unused-vars": [ 17 | "warn", 18 | { 19 | varsIgnorePattern: "^_", 20 | argsIgnorePattern: "^_", 21 | caughtErrorsIgnorePattern: "^_", 22 | }, 23 | ], 24 | }, 25 | overrides: [ 26 | { 27 | files: [".eslintrc.js", ".babelrc.js", "jest.config.js", "jest.setup.js"], 28 | env: { 29 | node: true, 30 | }, 31 | rules: { 32 | "@typescript-eslint/no-var-requires": "off", 33 | }, 34 | }, 35 | ], 36 | }; 37 | 38 | module.exports = config; 39 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | /src/__fixtures__/caches/** linguist-vendored 2 | /.yarn/releases/** linguist-vendored 3 | /.yarn/sdks/** linguist-vendored 4 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "npm" 9 | directory: "/" 10 | schedule: 11 | interval: "daily" 12 | reviewers: ["qnighy"] 13 | - package-ecosystem: "github-actions" 14 | directory: "/" 15 | schedule: 16 | interval: "daily" 17 | reviewers: ["qnighy"] 18 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: build and test 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | test: 7 | runs-on: ubuntu-latest 8 | strategy: 9 | matrix: 10 | node-version: [12.x, 14.x, 16.x] 11 | 12 | steps: 13 | - uses: actions/checkout@v2.3.4 14 | - uses: actions/setup-node@v2.2.0 15 | with: 16 | node-version: ${{ matrix.node-version }} 17 | - run: yarn install --immutable 18 | - run: yarn build 19 | - run: yarn tsc 20 | - run: yarn test 21 | - run: yarn lint 22 | - run: yarn fmt:check 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # Snowpack dependency directory (https://snowpack.dev/) 45 | web_modules/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | .parcel-cache 78 | 79 | # Next.js build output 80 | .next 81 | out 82 | 83 | # Nuxt.js build / generate output 84 | .nuxt 85 | dist 86 | 87 | # Gatsby files 88 | .cache/ 89 | # Comment in the public line in if your project uses Gatsby and not Next.js 90 | # https://nextjs.org/blog/next-9-1#public-directory-support 91 | # public 92 | 93 | # vuepress build output 94 | .vuepress/dist 95 | 96 | # Serverless directories 97 | .serverless/ 98 | 99 | # FuseBox cache 100 | .fusebox/ 101 | 102 | # DynamoDB Local files 103 | .dynamodb/ 104 | 105 | # TernJS port file 106 | .tern-port 107 | 108 | # Stores VSCode versions used for testing VSCode extensions 109 | .vscode-test 110 | 111 | # yarn v2 112 | .yarn/cache 113 | .yarn/unplugged 114 | .yarn/build-state.yml 115 | .yarn/install-state.gz 116 | .pnp.* 117 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /.yarn/sdks/eslint/bin/eslint.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const {existsSync} = require(`fs`); 4 | const {createRequire, createRequireFromPath} = require(`module`); 5 | const {resolve} = require(`path`); 6 | 7 | const relPnpApiPath = "../../../../.pnp.js"; 8 | 9 | const absPnpApiPath = resolve(__dirname, relPnpApiPath); 10 | const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath); 11 | 12 | if (existsSync(absPnpApiPath)) { 13 | if (!process.versions.pnp) { 14 | // Setup the environment to be able to require eslint/bin/eslint.js 15 | require(absPnpApiPath).setup(); 16 | } 17 | } 18 | 19 | // Defer to the real eslint/bin/eslint.js your application uses 20 | module.exports = absRequire(`eslint/bin/eslint.js`); 21 | -------------------------------------------------------------------------------- /.yarn/sdks/eslint/lib/api.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const {existsSync} = require(`fs`); 4 | const {createRequire, createRequireFromPath} = require(`module`); 5 | const {resolve} = require(`path`); 6 | 7 | const relPnpApiPath = "../../../../.pnp.js"; 8 | 9 | const absPnpApiPath = resolve(__dirname, relPnpApiPath); 10 | const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath); 11 | 12 | if (existsSync(absPnpApiPath)) { 13 | if (!process.versions.pnp) { 14 | // Setup the environment to be able to require eslint/lib/api.js 15 | require(absPnpApiPath).setup(); 16 | } 17 | } 18 | 19 | // Defer to the real eslint/lib/api.js your application uses 20 | module.exports = absRequire(`eslint/lib/api.js`); 21 | -------------------------------------------------------------------------------- /.yarn/sdks/eslint/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint", 3 | "version": "7.30.0-pnpify", 4 | "main": "./lib/api.js", 5 | "type": "commonjs" 6 | } 7 | -------------------------------------------------------------------------------- /.yarn/sdks/integrations.yml: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by PnPify. 2 | # Manual changes will be lost! 3 | 4 | integrations: 5 | - vscode 6 | -------------------------------------------------------------------------------- /.yarn/sdks/prettier/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const {existsSync} = require(`fs`); 4 | const {createRequire, createRequireFromPath} = require(`module`); 5 | const {resolve} = require(`path`); 6 | 7 | const relPnpApiPath = "../../../.pnp.js"; 8 | 9 | const absPnpApiPath = resolve(__dirname, relPnpApiPath); 10 | const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath); 11 | 12 | if (existsSync(absPnpApiPath)) { 13 | if (!process.versions.pnp) { 14 | // Setup the environment to be able to require prettier/index.js 15 | require(absPnpApiPath).setup(); 16 | } 17 | } 18 | 19 | // Defer to the real prettier/index.js your application uses 20 | module.exports = absRequire(`prettier/index.js`); 21 | -------------------------------------------------------------------------------- /.yarn/sdks/prettier/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "prettier", 3 | "version": "2.3.2-pnpify", 4 | "main": "./index.js", 5 | "type": "commonjs" 6 | } 7 | -------------------------------------------------------------------------------- /.yarn/sdks/typescript/bin/tsc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const {existsSync} = require(`fs`); 4 | const {createRequire, createRequireFromPath} = require(`module`); 5 | const {resolve} = require(`path`); 6 | 7 | const relPnpApiPath = "../../../../.pnp.js"; 8 | 9 | const absPnpApiPath = resolve(__dirname, relPnpApiPath); 10 | const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath); 11 | 12 | if (existsSync(absPnpApiPath)) { 13 | if (!process.versions.pnp) { 14 | // Setup the environment to be able to require typescript/bin/tsc 15 | require(absPnpApiPath).setup(); 16 | } 17 | } 18 | 19 | // Defer to the real typescript/bin/tsc your application uses 20 | module.exports = absRequire(`typescript/bin/tsc`); 21 | -------------------------------------------------------------------------------- /.yarn/sdks/typescript/bin/tsserver: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const {existsSync} = require(`fs`); 4 | const {createRequire, createRequireFromPath} = require(`module`); 5 | const {resolve} = require(`path`); 6 | 7 | const relPnpApiPath = "../../../../.pnp.js"; 8 | 9 | const absPnpApiPath = resolve(__dirname, relPnpApiPath); 10 | const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath); 11 | 12 | if (existsSync(absPnpApiPath)) { 13 | if (!process.versions.pnp) { 14 | // Setup the environment to be able to require typescript/bin/tsserver 15 | require(absPnpApiPath).setup(); 16 | } 17 | } 18 | 19 | // Defer to the real typescript/bin/tsserver your application uses 20 | module.exports = absRequire(`typescript/bin/tsserver`); 21 | -------------------------------------------------------------------------------- /.yarn/sdks/typescript/lib/tsc.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const {existsSync} = require(`fs`); 4 | const {createRequire, createRequireFromPath} = require(`module`); 5 | const {resolve} = require(`path`); 6 | 7 | const relPnpApiPath = "../../../../.pnp.js"; 8 | 9 | const absPnpApiPath = resolve(__dirname, relPnpApiPath); 10 | const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath); 11 | 12 | if (existsSync(absPnpApiPath)) { 13 | if (!process.versions.pnp) { 14 | // Setup the environment to be able to require typescript/lib/tsc.js 15 | require(absPnpApiPath).setup(); 16 | } 17 | } 18 | 19 | // Defer to the real typescript/lib/tsc.js your application uses 20 | module.exports = absRequire(`typescript/lib/tsc.js`); 21 | -------------------------------------------------------------------------------- /.yarn/sdks/typescript/lib/tsserver.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const {existsSync} = require(`fs`); 4 | const {createRequire, createRequireFromPath} = require(`module`); 5 | const {resolve} = require(`path`); 6 | 7 | const relPnpApiPath = "../../../../.pnp.js"; 8 | 9 | const absPnpApiPath = resolve(__dirname, relPnpApiPath); 10 | const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath); 11 | 12 | const moduleWrapper = tsserver => { 13 | if (!process.versions.pnp) { 14 | return tsserver; 15 | } 16 | 17 | const {isAbsolute} = require(`path`); 18 | const pnpApi = require(`pnpapi`); 19 | 20 | const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//); 21 | const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`); 22 | 23 | const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => { 24 | return `${locator.name}@${locator.reference}`; 25 | })); 26 | 27 | // VSCode sends the zip paths to TS using the "zip://" prefix, that TS 28 | // doesn't understand. This layer makes sure to remove the protocol 29 | // before forwarding it to TS, and to add it back on all returned paths. 30 | 31 | function toEditorPath(str) { 32 | // We add the `zip:` prefix to both `.zip/` paths and virtual paths 33 | if (isAbsolute(str) && !str.match(/^\^zip:/) && (str.match(/\.zip\//) || isVirtual(str))) { 34 | // We also take the opportunity to turn virtual paths into physical ones; 35 | // this makes it much easier to work with workspaces that list peer 36 | // dependencies, since otherwise Ctrl+Click would bring us to the virtual 37 | // file instances instead of the real ones. 38 | // 39 | // We only do this to modules owned by the the dependency tree roots. 40 | // This avoids breaking the resolution when jumping inside a vendor 41 | // with peer dep (otherwise jumping into react-dom would show resolution 42 | // errors on react). 43 | // 44 | const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str; 45 | if (resolved) { 46 | const locator = pnpApi.findPackageLocator(resolved); 47 | if (locator && dependencyTreeRoots.has(`${locator.name}@${locator.reference}`)) { 48 | str = resolved; 49 | } 50 | } 51 | 52 | str = normalize(str); 53 | 54 | if (str.match(/\.zip\//)) { 55 | switch (hostInfo) { 56 | // Absolute VSCode `Uri.fsPath`s need to start with a slash. 57 | // VSCode only adds it automatically for supported schemes, 58 | // so we have to do it manually for the `zip` scheme. 59 | // The path needs to start with a caret otherwise VSCode doesn't handle the protocol 60 | // 61 | // Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910 62 | // 63 | case `vscode`: { 64 | str = `^zip:${str}`; 65 | } break; 66 | 67 | // To make "go to definition" work, 68 | // We have to resolve the actual file system path from virtual path 69 | // and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip) 70 | case `coc-nvim`: { 71 | str = normalize(resolved).replace(/\.zip\//, `.zip::`); 72 | str = resolve(`zipfile:${str}`); 73 | } break; 74 | 75 | default: { 76 | str = `zip:${str}`; 77 | } break; 78 | } 79 | } 80 | } 81 | 82 | return str; 83 | } 84 | 85 | function fromEditorPath(str) { 86 | return process.platform === `win32` 87 | ? str.replace(/^\^?zip:\//, ``) 88 | : str.replace(/^\^?zip:/, ``); 89 | } 90 | 91 | // Force enable 'allowLocalPluginLoads' 92 | // TypeScript tries to resolve plugins using a path relative to itself 93 | // which doesn't work when using the global cache 94 | // https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238 95 | // VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but 96 | // TypeScript already does local loads and if this code is running the user trusts the workspace 97 | // https://github.com/microsoft/vscode/issues/45856 98 | const ConfiguredProject = tsserver.server.ConfiguredProject; 99 | const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype; 100 | ConfiguredProject.prototype.enablePluginsWithOptions = function() { 101 | this.projectService.allowLocalPluginLoads = true; 102 | return originalEnablePluginsWithOptions.apply(this, arguments); 103 | }; 104 | 105 | // And here is the point where we hijack the VSCode <-> TS communications 106 | // by adding ourselves in the middle. We locate everything that looks 107 | // like an absolute path of ours and normalize it. 108 | 109 | const Session = tsserver.server.Session; 110 | const {onMessage: originalOnMessage, send: originalSend} = Session.prototype; 111 | let hostInfo = `unknown`; 112 | 113 | Object.assign(Session.prototype, { 114 | onMessage(/** @type {string} */ message) { 115 | const parsedMessage = JSON.parse(message) 116 | 117 | if ( 118 | parsedMessage != null && 119 | typeof parsedMessage === `object` && 120 | parsedMessage.arguments && 121 | typeof parsedMessage.arguments.hostInfo === `string` 122 | ) { 123 | hostInfo = parsedMessage.arguments.hostInfo; 124 | } 125 | 126 | return originalOnMessage.call(this, JSON.stringify(parsedMessage, (key, value) => { 127 | return typeof value === `string` ? fromEditorPath(value) : value; 128 | })); 129 | }, 130 | 131 | send(/** @type {any} */ msg) { 132 | return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => { 133 | return typeof value === `string` ? toEditorPath(value) : value; 134 | }))); 135 | } 136 | }); 137 | 138 | return tsserver; 139 | }; 140 | 141 | if (existsSync(absPnpApiPath)) { 142 | if (!process.versions.pnp) { 143 | // Setup the environment to be able to require typescript/lib/tsserver.js 144 | require(absPnpApiPath).setup(); 145 | } 146 | } 147 | 148 | // Defer to the real typescript/lib/tsserver.js your application uses 149 | module.exports = moduleWrapper(absRequire(`typescript/lib/tsserver.js`)); 150 | -------------------------------------------------------------------------------- /.yarn/sdks/typescript/lib/tsserverlibrary.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const {existsSync} = require(`fs`); 4 | const {createRequire, createRequireFromPath} = require(`module`); 5 | const {resolve} = require(`path`); 6 | 7 | const relPnpApiPath = "../../../../.pnp.js"; 8 | 9 | const absPnpApiPath = resolve(__dirname, relPnpApiPath); 10 | const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath); 11 | 12 | const moduleWrapper = tsserver => { 13 | if (!process.versions.pnp) { 14 | return tsserver; 15 | } 16 | 17 | const {isAbsolute} = require(`path`); 18 | const pnpApi = require(`pnpapi`); 19 | 20 | const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//); 21 | const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`); 22 | 23 | const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => { 24 | return `${locator.name}@${locator.reference}`; 25 | })); 26 | 27 | // VSCode sends the zip paths to TS using the "zip://" prefix, that TS 28 | // doesn't understand. This layer makes sure to remove the protocol 29 | // before forwarding it to TS, and to add it back on all returned paths. 30 | 31 | function toEditorPath(str) { 32 | // We add the `zip:` prefix to both `.zip/` paths and virtual paths 33 | if (isAbsolute(str) && !str.match(/^\^zip:/) && (str.match(/\.zip\//) || isVirtual(str))) { 34 | // We also take the opportunity to turn virtual paths into physical ones; 35 | // this makes it much easier to work with workspaces that list peer 36 | // dependencies, since otherwise Ctrl+Click would bring us to the virtual 37 | // file instances instead of the real ones. 38 | // 39 | // We only do this to modules owned by the the dependency tree roots. 40 | // This avoids breaking the resolution when jumping inside a vendor 41 | // with peer dep (otherwise jumping into react-dom would show resolution 42 | // errors on react). 43 | // 44 | const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str; 45 | if (resolved) { 46 | const locator = pnpApi.findPackageLocator(resolved); 47 | if (locator && dependencyTreeRoots.has(`${locator.name}@${locator.reference}`)) { 48 | str = resolved; 49 | } 50 | } 51 | 52 | str = normalize(str); 53 | 54 | if (str.match(/\.zip\//)) { 55 | switch (hostInfo) { 56 | // Absolute VSCode `Uri.fsPath`s need to start with a slash. 57 | // VSCode only adds it automatically for supported schemes, 58 | // so we have to do it manually for the `zip` scheme. 59 | // The path needs to start with a caret otherwise VSCode doesn't handle the protocol 60 | // 61 | // Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910 62 | // 63 | case `vscode`: { 64 | str = `^zip:${str}`; 65 | } break; 66 | 67 | // To make "go to definition" work, 68 | // We have to resolve the actual file system path from virtual path 69 | // and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip) 70 | case `coc-nvim`: { 71 | str = normalize(resolved).replace(/\.zip\//, `.zip::`); 72 | str = resolve(`zipfile:${str}`); 73 | } break; 74 | 75 | default: { 76 | str = `zip:${str}`; 77 | } break; 78 | } 79 | } 80 | } 81 | 82 | return str; 83 | } 84 | 85 | function fromEditorPath(str) { 86 | return process.platform === `win32` 87 | ? str.replace(/^\^?zip:\//, ``) 88 | : str.replace(/^\^?zip:/, ``); 89 | } 90 | 91 | // Force enable 'allowLocalPluginLoads' 92 | // TypeScript tries to resolve plugins using a path relative to itself 93 | // which doesn't work when using the global cache 94 | // https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238 95 | // VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but 96 | // TypeScript already does local loads and if this code is running the user trusts the workspace 97 | // https://github.com/microsoft/vscode/issues/45856 98 | const ConfiguredProject = tsserver.server.ConfiguredProject; 99 | const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype; 100 | ConfiguredProject.prototype.enablePluginsWithOptions = function() { 101 | this.projectService.allowLocalPluginLoads = true; 102 | return originalEnablePluginsWithOptions.apply(this, arguments); 103 | }; 104 | 105 | // And here is the point where we hijack the VSCode <-> TS communications 106 | // by adding ourselves in the middle. We locate everything that looks 107 | // like an absolute path of ours and normalize it. 108 | 109 | const Session = tsserver.server.Session; 110 | const {onMessage: originalOnMessage, send: originalSend} = Session.prototype; 111 | let hostInfo = `unknown`; 112 | 113 | Object.assign(Session.prototype, { 114 | onMessage(/** @type {string} */ message) { 115 | const parsedMessage = JSON.parse(message) 116 | 117 | if ( 118 | parsedMessage != null && 119 | typeof parsedMessage === `object` && 120 | parsedMessage.arguments && 121 | typeof parsedMessage.arguments.hostInfo === `string` 122 | ) { 123 | hostInfo = parsedMessage.arguments.hostInfo; 124 | } 125 | 126 | return originalOnMessage.call(this, JSON.stringify(parsedMessage, (key, value) => { 127 | return typeof value === `string` ? fromEditorPath(value) : value; 128 | })); 129 | }, 130 | 131 | send(/** @type {any} */ msg) { 132 | return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => { 133 | return typeof value === `string` ? toEditorPath(value) : value; 134 | }))); 135 | } 136 | }); 137 | 138 | return tsserver; 139 | }; 140 | 141 | if (existsSync(absPnpApiPath)) { 142 | if (!process.versions.pnp) { 143 | // Setup the environment to be able to require typescript/lib/tsserverlibrary.js 144 | require(absPnpApiPath).setup(); 145 | } 146 | } 147 | 148 | // Defer to the real typescript/lib/tsserverlibrary.js your application uses 149 | module.exports = moduleWrapper(absRequire(`typescript/lib/tsserverlibrary.js`)); 150 | -------------------------------------------------------------------------------- /.yarn/sdks/typescript/lib/typescript.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const {existsSync} = require(`fs`); 4 | const {createRequire, createRequireFromPath} = require(`module`); 5 | const {resolve} = require(`path`); 6 | 7 | const relPnpApiPath = "../../../../.pnp.js"; 8 | 9 | const absPnpApiPath = resolve(__dirname, relPnpApiPath); 10 | const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath); 11 | 12 | if (existsSync(absPnpApiPath)) { 13 | if (!process.versions.pnp) { 14 | // Setup the environment to be able to require typescript/lib/typescript.js 15 | require(absPnpApiPath).setup(); 16 | } 17 | } 18 | 19 | // Defer to the real typescript/lib/typescript.js your application uses 20 | module.exports = absRequire(`typescript/lib/typescript.js`); 21 | -------------------------------------------------------------------------------- /.yarn/sdks/typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typescript", 3 | "version": "4.2.4-pnpify", 4 | "main": "./lib/typescript.js", 5 | "type": "commonjs" 6 | } 7 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | packageExtensions: 2 | jest-circus@^27.0.0: 3 | dependencies: 4 | slash: ^3.0.0 5 | jest-util@^27.0.0: 6 | dependencies: 7 | jest-runner: ^27.0.0 8 | 9 | yarnPath: .yarn/releases/yarn-2.4.2.cjs 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Downgrade your `yarn.lock` to v1 2 | 3 | ## Purpose 4 | 5 | Not intended to be used daily, because Yarn V2 is great. 6 | 7 | However, we are always fearful when upgrading something important. 8 | With `yarn-lock-v1` you can say "don't worry, we can always go back to Yarn V1 if something goes wrong". 9 | 10 | ## Usage 11 | 12 | ``` 13 | $ npx yarn-lock-v1 14 | ``` 15 | 16 | `yarn-lock-v1` automatically generates a back up if the destination (`yarn.lock` by default) already exists. 17 | 18 | You can specify a different input or a different output. 19 | 20 | ``` 21 | $ npx yarn-lock-v1 -f yarn.lock.v2 -o yarn.lock.v1 22 | ``` 23 | 24 | `yarn-lock-v1` also sees your `.yarnrc.yml` for credentials if necessary. You can specify a different location for the rc. 25 | 26 | ``` 27 | $ npx yarn-lock-v1 -c ../somewhere/.yarnrc.yml 28 | ``` 29 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('@jest/types').Config.InitialOptions} */ 2 | const config = { 3 | rootDir: "src", 4 | setupFilesAfterEnv: ["../jest.setup.js"], 5 | }; 6 | 7 | module.exports = config; 8 | -------------------------------------------------------------------------------- /jest.setup.js: -------------------------------------------------------------------------------- 1 | const { afterEach, beforeEach } = require("@jest/globals"); 2 | const nock = require("nock"); 3 | 4 | beforeEach(() => { 5 | if (!nock.isActive) nock.activate(); 6 | }); 7 | afterEach(() => { 8 | nock.restore(); 9 | }); 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yarn-lock-v1", 3 | "version": "0.1.0", 4 | "description": "A tool to downgrade your yarn.lock", 5 | "main": "dist/index.js", 6 | "repository": "https://github.com/qnighy/yarn-lock-v1", 7 | "author": "Masaki Hara ", 8 | "license": "MIT", 9 | "files": [ 10 | "dist/**/*" 11 | ], 12 | "scripts": { 13 | "build": "tsc -p tsconfig.build.json && babel src -d dist -x .ts --ignore \"src/**/*.test.ts\"", 14 | "fmt": "$npm_execpath run fmt:runprettier -w", 15 | "fmt:check": "$npm_execpath run fmt:runprettier -c", 16 | "fmt:runprettier": "prettier \"src/**/*.ts\" .babelrc.js .eslintrc.js jest.config.js tsconfig.json tsconfig.build.json", 17 | "lint": "eslint . --ext .js,.ts", 18 | "lint:fix": "$npm_execpath run lint --fix", 19 | "prepack": "$npm_execpath run build", 20 | "start": "$npm_node_execpath dist/index.js", 21 | "start:dev": "babel-node -x .ts -- src/index.ts", 22 | "test": "jest", 23 | "tsc": "tsc" 24 | }, 25 | "dependencies": { 26 | "@babel/runtime-corejs3": "^7.14.9", 27 | "js-yaml": "^4.1.0", 28 | "node-fetch": "^2.6.1", 29 | "yargs": "^17.0.1" 30 | }, 31 | "devDependencies": { 32 | "@babel/cli": "^7.14.8", 33 | "@babel/core": "^7.14.8", 34 | "@babel/node": "^7.14.9", 35 | "@babel/plugin-transform-runtime": "^7.14.5", 36 | "@babel/preset-env": "^7.14.9", 37 | "@babel/preset-typescript": "^7.14.5", 38 | "@jest/globals": "^27.0.6", 39 | "@jest/types": "^27.0.6", 40 | "@types/babel__core": "^7.1.15", 41 | "@types/eslint": "^7.28.0", 42 | "@types/js-yaml": "^4.0.3", 43 | "@types/node": "^15.3.1", 44 | "@types/node-fetch": "^2.5.12", 45 | "@types/yargs": "^17.0.2", 46 | "@typescript-eslint/eslint-plugin": "^4.28.5", 47 | "@typescript-eslint/parser": "^4.28.5", 48 | "@yarnpkg/pnpify": "^3.0.0-rc.10", 49 | "babel-jest": "^27.0.6", 50 | "eslint": "^7.32.0", 51 | "eslint-config-prettier": "^8.3.0", 52 | "eslint-plugin-jest": "^24.4.0", 53 | "jest": "^27.0.6", 54 | "nock": "^13.1.1", 55 | "nock-record": "^0.3.9", 56 | "prettier": "^2.3.2", 57 | "typescript": "^4.3.5" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ], 5 | "reviewers": ["qnighy"], 6 | "packageRules": [ 7 | { 8 | "matchPaths": ["**"], 9 | "enabled": false 10 | }, 11 | { 12 | "matchPaths": ["package.json"], 13 | "enabled": true, 14 | "labels": ["dependencies", "javascript"], 15 | "rangeStrategy": "bump", 16 | "postUpdateOptions": ["yarnDedupeHighest"] 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /src/__fixtures__/yarn-lock1.txt: -------------------------------------------------------------------------------- 1 | # This file is generated by running "yarn install" inside your project. 2 | # Manual changes might be lost - proceed with caution! 3 | 4 | __metadata: 5 | version: 4 6 | cacheKey: 7 7 | 8 | "call-bind@npm:^1.0.2": 9 | version: 1.0.2 10 | resolution: "call-bind@npm:1.0.2" 11 | dependencies: 12 | function-bind: ^1.1.1 13 | get-intrinsic: ^1.0.2 14 | checksum: 18cc6107a1f028247f2b505dae73ad1c63b737addfcd43ff75159f072c5c827300c1fb66f26ee0ec70fc2fdd005ce68d65c05a2a34b74bab08c3b1921954ada9 15 | languageName: node 16 | linkType: hard 17 | 18 | "foo@workspace:.": 19 | version: 0.0.0-use.local 20 | resolution: "foo@workspace:." 21 | dependencies: 22 | "is-regex": ^1.1.2 23 | languageName: unknown 24 | linkType: soft 25 | 26 | "has-symbols@npm:^1.0.1": 27 | version: 1.0.2 28 | resolution: "has-symbols@npm:1.0.2" 29 | checksum: 1b73928752fa9ca993fa48f7b3832c95ea408c0ec635b2d6cbaf011b94a7e6a704a9254ae6d8ecc913d4dd92f2ff760dc43aad7c7e790ddb3f627005614d8e28 30 | languageName: node 31 | linkType: hard 32 | 33 | "is-regex@npm:^1.1.2": 34 | version: 1.1.2 35 | resolution: "is-regex@npm:1.1.2" 36 | dependencies: 37 | call-bind: ^1.0.2 38 | has-symbols: ^1.0.1 39 | checksum: 5e2f80f495f5297d1295730820a4be31f3848ca92357cfef1b2a61c09fe0fcd3f68c34f3042a5b81885e249cd50eac8efac472ad6da7ecb497bb2d7bad402a9a 40 | languageName: node 41 | linkType: hard 42 | -------------------------------------------------------------------------------- /src/__fixtures__/yarn-lock2.txt: -------------------------------------------------------------------------------- 1 | # This file is generated by running "yarn install" inside your project. 2 | # Manual changes might be lost - proceed with caution! 3 | 4 | __metadata: 5 | version: 4 6 | cacheKey: 7 7 | 8 | "@babel/code-frame@npm:^7.0.0": 9 | version: 7.12.13 10 | resolution: "@babel/code-frame@npm:7.12.13" 11 | dependencies: 12 | "@babel/highlight": ^7.12.13 13 | checksum: 471532bb7cb4a300bd1a3201e75e7c0c83ebfb4e0e6610fdb53270521505d7efe0961258de61e7b1970ef3092a97ed675248ee1a44597912a1f61f903d85ef41 14 | languageName: node 15 | linkType: hard 16 | 17 | "@babel/helper-validator-identifier@npm:^7.14.0": 18 | version: 7.14.0 19 | resolution: "@babel/helper-validator-identifier@npm:7.14.0" 20 | checksum: bd67b4a1a49eba151aa0fe95508579638287fee0a3e7a3bf8c5ab480de8eaad4b4231c523d7db401eb0cecc7cf03b76ee72453fab53bab8cb8ccd154bb67feb7 21 | languageName: node 22 | linkType: hard 23 | 24 | "@babel/highlight@npm:^7.0.0, @babel/highlight@npm:^7.12.13": 25 | version: 7.14.0 26 | resolution: "@babel/highlight@npm:7.14.0" 27 | dependencies: 28 | "@babel/helper-validator-identifier": ^7.14.0 29 | chalk: ^2.0.0 30 | js-tokens: ^4.0.0 31 | checksum: 0122fcd3cd6e81bfa002227d6c9dfff91d388d48dc188cd13e3f60c46e5450ebad65aa133ac8f525cb3cfa3b70766484e4a93c40b2837ce16f12083ebd2b0824 32 | languageName: node 33 | linkType: hard 34 | 35 | "ansi-styles@npm:^3.2.1": 36 | version: 3.2.1 37 | resolution: "ansi-styles@npm:3.2.1" 38 | dependencies: 39 | color-convert: ^1.9.0 40 | checksum: 456e1c23d9277512a47718da75e7fbb0a5ee215ef893c2f76d6b3efe8fceabc861121b80b0362146f5f995d21a1633f05a19bbf6283ae66ac11dc3b9c0bed779 41 | languageName: node 42 | linkType: hard 43 | 44 | "chalk@npm:^2.0.0": 45 | version: 2.4.2 46 | resolution: "chalk@npm:2.4.2" 47 | dependencies: 48 | ansi-styles: ^3.2.1 49 | escape-string-regexp: ^1.0.5 50 | supports-color: ^5.3.0 51 | checksum: 22c7b7b5bc761c882bb6516454a1a671923f1c53ff972860065aa0b28a195f230163c1d46ee88bcc7a03e5539177d896457d8bc727de7f244c6e87032743038e 52 | languageName: node 53 | linkType: hard 54 | 55 | "color-convert@npm:^1.9.0": 56 | version: 1.9.3 57 | resolution: "color-convert@npm:1.9.3" 58 | dependencies: 59 | color-name: 1.1.3 60 | checksum: 5f244daa3d1fe1f216d48878c550465067d15268688308554e613b7640a068f96588096d51f0b98b68f15d6ff6bb8ad24e172582ac8c0ad43fa4d3da60fd1b79 61 | languageName: node 62 | linkType: hard 63 | 64 | "color-name@npm:1.1.3": 65 | version: 1.1.3 66 | resolution: "color-name@npm:1.1.3" 67 | checksum: d8b91bb90aefc05b6ff568cf8889566dcc6269824df6f3c9b8ca842b18d7f4d089c07dc166808d33f22092d4a79167aa56a96a5ff0d21efab548bf44614db43b 68 | languageName: node 69 | linkType: hard 70 | 71 | "escape-string-regexp@npm:^1.0.5": 72 | version: 1.0.5 73 | resolution: "escape-string-regexp@npm:1.0.5" 74 | checksum: f9484b8b4c8827d816e0fd905c25ed4b561376a9c220e1430403ea84619bf680c76a883a48cff8b8e091daf55d6a497e37479f9787b9f15f3c421b6054289744 75 | languageName: node 76 | linkType: hard 77 | 78 | "foo@workspace:.": 79 | version: 0.0.0-use.local 80 | resolution: "foo@workspace:." 81 | dependencies: 82 | "@babel/code-frame": ^7.0.0 83 | "@babel/highlight": ^7.0.0 84 | languageName: unknown 85 | linkType: soft 86 | 87 | "has-flag@npm:^3.0.0": 88 | version: 3.0.0 89 | resolution: "has-flag@npm:3.0.0" 90 | checksum: 63aade480d27aeedb3b5b63a2e069d47d0006bf182338d662e7941cdc024e68a28418e0efa8dc5df30db9c4ee2407f39e6ea3f16cfbc6b83848b450826a28aa0 91 | languageName: node 92 | linkType: hard 93 | 94 | "js-tokens@npm:^4.0.0": 95 | version: 4.0.0 96 | resolution: "js-tokens@npm:4.0.0" 97 | checksum: 1fc4e4667ac2d972aba65148b9cbf9c17566b2394d3504238d8492bbd3e68f496c657eab06b26b40b17db5cac0a34d153a12130e2d2d2bb6dc2cdc8a4764eb1b 98 | languageName: node 99 | linkType: hard 100 | 101 | "supports-color@npm:^5.3.0": 102 | version: 5.5.0 103 | resolution: "supports-color@npm:5.5.0" 104 | dependencies: 105 | has-flag: ^3.0.0 106 | checksum: edacee6425498440744c418be94b0660181aad2a1828bcf2be85c42bd385da2fd8b2b358d9b62b0c5b03ff5cd3e992458d7b8f879d9fb42f2201fe05a4848a29 107 | languageName: node 108 | linkType: hard 109 | -------------------------------------------------------------------------------- /src/__nock-fixtures__/yarn-lock1-offline.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "scope": "https://registry.yarnpkg.com:443", 4 | "method": "GET", 5 | "path": "/call-bind/1.0.2", 6 | "body": "", 7 | "status": 200, 8 | "response": [ 9 | "1f8b080000000000040395560973e23a12fe2b2e76ebcdcc121b1f982355533586808170863379bccd936df9005b3692cd35f5fefbb60c4c32a9795bbb142452abbbd5d7d7adef0582225cb82fd8280c452b204ee1aeb0c794053101aa22c9920a1407339b06497aa13ec556c6d2f024fc297131898b7dfef2a78004372376ce74578850c035c0113e4a1b064af0318969ca0af7df0b52e1fef7efa0d5455998029754fac1f7d7ddfbdd1f7cc72f69c419d8f651eac709bf2197fc89924b27c8de220f0347ee9254fa89004217d772bb128a93cc0a03e683510cb958bc6ec510a598a5e04518106e31667c2188223ea65f41f79d146d98200103e8c859ef0b2489049a112117b92b702a1363129e409e9c6c214509163e7172e95f9f40f283d83b7ed01ab3f47a8e3207ee4d68ec64b760bf650c65692cda3e221e0e634ff8ed37c10b5201398ed0ec1843b3d51f9952c493cc15febf623775761c45a05514492c62275f411511e7769e224f105d615dd8fff333891d2c881836764c581c6209ecfa4cf12e0b28fefce9e7747cfa225d6dfab22ec097e7145212b3208d2984ed7b213d25bc5cc129f021a3e1655df4d33461f7a512d0fdcc92c0c052b8f111b5f2e2c90b5be232a06f8b4f87983a90efdf0b1bb44797f483366c47ef36bc62f3b2e515750546becc0bf12e070cb05c4fac77d41b8c38b7783b78870ccc4464b194223b2d408542c6fc9872dfae50ec817588081db01ee578c48025eee8c5a36f1edf7217b937a0d70988c7c52fd1f8452458c2234fd935245c2c0c6c4c188fe4a03be36e645e0e80bfd5f1319aa580b10ce7a0f3e30827803050f68bcb3f0afe8362e440cbe14d65ff8013281b4cec0054810bdfaedc17748950316e00be15fead54254d9241088a3fdf4b8aa4e5dbf7e5ce4f5449951438b9a8e094aa04d25c163097cbcaa08b77b55f019cdf05bacb70cce1c9f975d82b3c68ce076b6f39bd24fc2ac9eff6702a4277a00161c1e5cabc8f828a9fe1c95d8eb334c97847f980cf1447096f3a70b2c510df1f9806fd19a138c488", 10 | "6188858b4286a11c7348f603c0e50f9a059dcf0dc2f067aa1f38b849396c0bf729cd305805c8e84056e0aab26a69b6e55a725dafe9724d5591eda89aae625b4535db91ddaaabd71c8747f335e002972287eefded362b5e39e2176f23a42c297a1ecf57e8876ff48aa4c00957e404d05821121031ecd120e5ed91f9485754b13a2ab6ad66e0d386be34adf6338ca1f410cd1e11aed051d03d476725b0295ef68a3232aafd9e9bedfc168bd5599dd889dd4ecf83497a5eb9eac43433e03267cf6c478daf5fe156b88165115c65294e19d7eab852ab294addd6ec3aaacb1a7234195996ea56505da95b58b34126e5900c39146f854eb107d6d39304be6d981453efade194c4b7b59847474abd33a8819ce026340cf05a517936f944c2ce343843b69572b55c835a4d2291051e416946790d88fcd36899dda13036c7c2b46b0e8dd9fca995d3d7744dae91bd1746002960819924ec013392a2f1e326d40726e9bd70b33c06b6c44b2e46730efe3bb0b6dd305a8da6614c1a939e5b1af6abcd27a33e5bb0a9415e96c8330c4bdb8e4b4ad41a2f3727add1ea94fb48a347e2af499a8cca4bd959990b34b2c879537a6a2e1a6716e297fa16cd0cc3315b752722fea47a08c2928aceb26f0cd82138e2d85a93debcf3104d55f7c5189d95ce62d41ad44db9511a112b74e61bbd5b3276d4ad9ebaac3b4e7646da3fa2b26b6ab573299b34d6a4532256ab970d0f935dc85a7a10fa93f359eb9d5a35e3682e124df3b2eaa89f94ebeeb252968bf67e0853972c936ddc70d6a445ababe149099f5957298ece4fb395bdab85735d636ed5281f71449bc5a5da591e67adc76daff7a8690b2f0c8c583b9e2a6bb273949e3e1ec9cf5b75d03c658ed78b5d4fdb3db874c80cf77929b7edb0d81d561759fbe1b09dea01a547dd5ddaed788ed7c42c2f9ba75adda8449bb8f2525507694f8fc8a35ff777cfede2f8254efacaec61da6a04acebed4ec3d5634f9e8ca6a7feec505e1317c967f5acd8d35eb5ad85f6f210c9f381e359d5d6b8f8a812bc7b18bcd4bda96ed9c6483d755acc31cfe1c156ed76f8bc268d7d735b29cf8e416bb1181cf4a523cbc9bed96c0c2a8faed6f6f7de6eb332baba7270e69381dde810cf6c9ab50156e56e674d360b3a9f4c2724aed2e1e42532eb66a23fb176d7df6fa62a350e7e7dbc2b66c5d57cf274eef7277ea647c929ee695a755e5a93595cda6c07db513f5626f5f9763f5fede489921eb47d71fe7228312529d7fa5b734f5393b4578bfeecbc522b0662d565dc5a93677bb85b35d0b0b9db0de3de8b328ed3d42a7ae3e6609bf4e6b432b656be3b788080048fa362cb79ec850dd3794e0fe616eeb690aef37affeaa6a727bec861d41a3efc0db878f7e7ed6bcef0fb497d995680e8ff36a11d78e7d8f07cb98c3850c45fc629fca045e60fdaebd8ff1f94fd71b102104e117f66a3b00b3d93c27fde3f7d78d1f1d6a9c13b88b78f5b6f12af0f5efea249a30458e0ef5b6b7acd5bd3ab5251e4b25caec89a5e565e6144aa55b922d72b75bda2d6ca7ab99ac7009ae6d487b9b63d50049af2e1f3d77f00d90604e9450c0000" 11 | ], 12 | "rawHeaders": [ 13 | "Date", 14 | "Sat, 01 May 2021 09:02:08 GMT", 15 | "Content-Type", 16 | "application/json", 17 | "Transfer-Encoding", 18 | "chunked", 19 | "Connection", 20 | "close", 21 | "Set-Cookie", 22 | "__cfduid=d4a7ba78f275388ebf2e4882de60f8d8f1619859727; expires=Mon, 31-May-21 09:02:07 GMT; path=/; domain=.registry.yarnpkg.com; HttpOnly; SameSite=Lax", 23 | "CF-Ray", 24 | "6487d4408d7b0e76-NRT", 25 | "Cache-Control", 26 | "max-age=300", 27 | "Content-Encoding", 28 | "gzip", 29 | "Vary", 30 | "accept-encoding, accept", 31 | "CF-Cache-Status", 32 | "DYNAMIC", 33 | "cf-request-id", 34 | "09c8c2fc5600000e76df83f000000001", 35 | "Expect-CT", 36 | "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"", 37 | "Server", 38 | "cloudflare" 39 | ], 40 | "responseIsBinary": false 41 | }, 42 | { 43 | "scope": "https://registry.yarnpkg.com:443", 44 | "method": "GET", 45 | "path": "/has-symbols/1.0.2", 46 | "body": "", 47 | "status": 200, 48 | "response": [ 49 | "1f8b0800000000000403ad57fb6fe24812fe572cdf6a775604bf310f29a70163204080f026c76cd4d86d63b0dba66df3c868fff7abb6c984c9657e58e92292d8d555d5d555f57d5d7ce7090a305fe3b7282ec6976013fa317fc71f318dbd90805c16244101094a936d48f9daf737836e486d44b80ea21b446cd0c001f27cb0f0775b907d75d9ab6085012ca5942d6c9324aa8962be0e2b368ef9bfef782725b6475ce6fa5d2f0645d74bb6e986b910e328247148e3ab3133b34292506f932620e66bfff97fc7f5ed8e87f82cea45499e88264e300d3c8239cfe1922de6ba130e93a347431260927090406e9225908bd3280a69227093fc21e6e2085b775c48b9788b82588094f89e8549cc32fff8308577c8164bb7476c7c1676ac06f9e670b6ef7c4471946e7c2fde824a8c1c5cbcbe167d94e038016d50c99e6a3c89028ea6842b1663cf6791f91e611a1f96d96b5c0c897f61d6619c5cd7516a836944433bb5b2a3e79657d577f74cbd1627a1b5e77eff9d7bdbf42a452e54f47fe5ecf0d7487253380eb9581c815ee0b2fdf3cd6031f370bb5c2c425b0521b94074187a35d7f8d92af3ff1ee28f0ce451b1d59a8b93f044e07811a6c9e5daf1b7917e666485146735b97174957d3880981558648bc55d9c17f2c6e8d3dd6f4fc974af3e40b708a1b25264b1bec133779a15b5c6e3983db0949c93fb5d7c17ec628eb5d73b8001b861d1da22e2623fcc6a02b8e2906d7346a73e689bfd615b08187e590ffc53339638e60e301ac0bf629184456c674f402bc47e5b87627145875bf3c7dfbe64c52e62780108c7a18f0588eb0bc587d4a3f8cb1f8218216b8f5c0ce70cc91f7f0ad798fe5cf3f061c8073084b107b8bf306c249788a108a28033e40402cf3fd38747180013a88878c37302b3017f7b7c3901993116e1730483a7772e641b840e1341036579f22f8ee7fbf04850e21d313c5ceb0d4fe644e733ee3836710419c0c4f280e720d0af39f18979c98a7078c703d6e3ff92cb424990c116a097bd0bb2a065afb795632b8aa0648a6fdb65225d901941", 50 | "e76e99565950244102d1af3a882949425528810ec02fdb5312d48ce73f63175097af312528cbf65f25884462c9630d0b2d98d13764851d359389374cb6a1e129861b8525d8c3e7c80774883a5c2cc20ffa72a0f64e78165526852588ec4d24973ed5249ebb4d32f2b2b6340cb0a83135393ff955c4f270b3c9556a2182a077ee78862b2432931ba55c48004fa001d940d4cb5dff88d58b90fd217c2fda86e4e399e05aa4a16717afc7072f0aff0d528609b063de130c0b90b07fdf7312941cd67e462b6b9b304da23401a50f704d7010b19060658f3160e60de210764a28f6318a31f49383fc18b30e6508ed7bf0e7876c0340639dfcb374ebd9d8a00cc57c2da12986a85c8a3161bbe06c02f05c021564d57c6b44762c40530723d6c1aab29175a456a4aabd51379b8da6abb65392644bad5634a4aaaa2357cb5547854837a99b81e39737ffe7d015bd384ef3f1610bb58f802e605f36607c181c3e37ff17854061ecb9e35f3c16f00d297c7d1b785e586de6ef73104034efad17b8ebdee50cbb3a38b23db886a15cc0c6d8a55e02dcc408a3242b40be4b54aed2be3833949ebf94cbbb503d8edbaf127a450bf35c4ada8767b7140dd5c1ec6276e70db96c3fd2f4c97f358ca1333b9abebbed594149ae6a8586313e7acaf828b64ff7f7b02bec10a7016c25eb255b95ca922549aa542d9714242baa8eb472555565ac22aba43bb2a6b094276c6203fa7acf17c52e444f2f029c0c2ead90bab73429166fdf8a597e84c47d05570cf04698c278519335d6768cbab13df15ea11c72452ae94030510083880b5499b29ee18beca761b61f06dca83de2260fed417d3a1b9b997c4dd7e49adb1a3704fe0415b807b823e3055965cb0634324c3535eeadda005812b9511e38d360bfa7b86535ea66c3a8d79f1a4f5d7748461d635caf4ee7f1a44e9e17c8add70b89391295aa1e6985decad20edd3e5d4ae979b526cd7a854a95c5d0589cc883d939e94b79282bcb49aba1d9d2e6715a978f0fcf66dd17db61bc79d44ec7b93dd4ba8b153af70b6b52c79540699f07bb57b5b78c4f076d62f6b727a762e9e7bdfaa454b543c79be1c6c5399e7bdaf0e45c7a97e7b2f7a0adc85c5c136d37155b66a13ef40707bb3e54bdd7b61354b5d9a2b2945d519f28cb8ad29d9e7bc4f5657115d6871499bba45958b614674d4653abaf4d824bd82f9fa7d3c764640e27cb71bd5156574a0f0f362da36262998ac79964e8ca636cc5ada6bed85aaadfd1d6049da7b2654d66c3ca6ae624fd57fbb1bb52c7faeed0aa3cf7eae7325dd9a351d3dc079ad3151febf1a91a3df57a4e596e12d8bb595f35eaedb8d5b8cce66d8ac6ee627996e4933e20f3c1a6736834367d7fda93b1d48d8c239d44fb56b414f78e398eccc69a6c516b66554879d27cc0f596dbf06ce43e943aabce69330bfcd1fe59d307cb67ab2f9dfb8fe7ca64b0bc8c8f0f41bc1c8e4bc19a90b93ec6f3fea43b12e7c1b4b5da0de7692b4ef072a60c93f273423a17110f4795c572952e88a418e9a16514bccab975266b622e8dc3543d19f27063b7f6f3aaa92cdaf3a7a8a1cf9459d835bcf1537728f576a302a2076ba228affdc2c3b2e9b6cf5444d06b1547c3749118d349f7903657d5c2a83c37269b5d7b7a76827d4aeacb99757a344c6feef4adcae944ddc2b1d36da913d75b13e5e9b01cdb8354eef63aeda54322d20d64ba53c2e779552c3def564fad46c1c08bc7b234bdf4e80a4fdd4bdc962254b994d6c4aa140aacdfefbb8695357e062373d0fc05b8d81dc3086c06f731a3abebb7bf7c340144fff24b1cd8d970475b3076e5f30c08d87796047ef3abfd9f38fb96470108a730428504f90fc09b14feb3a0b630890253c42a4c718c3edef8a9789d0cb3ef1041042a4910dd92d34b464e2fb22e", 51 | "6b9aa66aba5292ca2f30d954244d2f49521508093e95529605a0cec9967a647fa2087c65f7e4dfff05205680b7100f0000" 52 | ], 53 | "rawHeaders": [ 54 | "Date", 55 | "Sat, 01 May 2021 09:02:08 GMT", 56 | "Content-Type", 57 | "application/json", 58 | "Transfer-Encoding", 59 | "chunked", 60 | "Connection", 61 | "close", 62 | "Set-Cookie", 63 | "__cfduid=da9ddbb8ebae1c0c17d9f790192fcf64b1619859727; expires=Mon, 31-May-21 09:02:07 GMT; path=/; domain=.registry.yarnpkg.com; HttpOnly; SameSite=Lax", 64 | "CF-Ray", 65 | "6487d440ead75f3b-NRT", 66 | "Cache-Control", 67 | "max-age=300", 68 | "Content-Encoding", 69 | "gzip", 70 | "Vary", 71 | "accept-encoding, accept", 72 | "CF-Cache-Status", 73 | "DYNAMIC", 74 | "cf-request-id", 75 | "09c8c2fc9000005f3b4aa67000000001", 76 | "Expect-CT", 77 | "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"", 78 | "Server", 79 | "cloudflare" 80 | ], 81 | "responseIsBinary": false 82 | } 83 | ] -------------------------------------------------------------------------------- /src/__nock-fixtures__/yarn-lock1.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "scope": "https://registry.yarnpkg.com:443", 4 | "method": "GET", 5 | "path": "/is-regex/1.1.2", 6 | "body": "", 7 | "status": 200, 8 | "response": [ 9 | "1f8b080000000000040395570d73a24813fe2b94f5d6dddeba802020a66aef5dbfe2573446fc8aaf7ba911860f8519c2004aaeeebf5f0f9a64776befadba5414a6a7bba7bbe7e967c63f2b0445b87253099898600f9f2b9f2a394e5840090815499154903898d94910a717e99009a91f302147618605248c2ca134fdafb0a6c99109764219f786c2480edc04fc7f12107104f0120729167a96217cf992522b4d02e22d90072ba02cf56952b9f9f3359e114d1c4484014af6600b1a384241083185071f645f3c3e946c1a55fefa547133e2802b6e9e255cc94fd398ddc8b217a47eb6e76a328b29613461f2c501370b031b13c6b39f0c17b004b8e45907c4c167e9c04072499b71c77182e36c1f06cc0715865c2c5e87628852cc52d00695f2eda642e2484832228401e1133f48f99089948485f0cb2fc2ab2e97de406e1125c5d5e6a204eb91c2160875b0507aba387cd3fd665a14af0e0451c44c6429f2a02eaf563165e95b286701650ea8c5097532bbdc5a5e1188f7a682197f11240803dbb68fed2317daa5b01c0a1fa13ec2c78f72f9fc5d901d9ccb240b43b078870f6c2a156d1f110f87d4e3b9c27e08c87184cea035edf7eeeefb52c4f79607f66fcd5eddc1de46e055140915b153be01e2006ed7e5a00482e80abb4afe9f0f6509450c039b8321c412c4f521c1cf5990e00fbf4a728cec23f2302447c9afbf49d7987edb55e09f230630405990d2a4e090488b98830792821c2ec083f7ef61171016633b150f4c7e6d31891b80b37de695c8fa47c8fec4169cb00c336eeed308c7102c44f013b8ffc416823ce2e2048d05cbfe0f72b9b47bf98c6132e088875116a244c06740332b79e04d08d3df88bf725e88a1d298d801840405b151188a7be81f88e90f45aa95e4e123006211ed69083a17b1c2e307c8747fb0ff72e94df9823f1136c90da0abc1a821e9520dd607cc5e9c2852bd1c7e8b303ea34aaaa4f0404bb45e24e64552829a4b1a92d22cbdb91458cae60d0d763549073be8343e546a52bd8cfe679dcee7811935504f510981", 10 | "3f74189759f1fe823e29b9c80d425e97b2fd2f7cb24fe88901bdf2fa0750cb1002900d585a7a231117a0e8d2b35ce7529882455e450ad4e0279a24f0fc34e49c61fb098042d6b81a64c06daf221546df985ea5362208a0fca942639c20999b802194e25df4fd92173d82cf1cf1501a940497d5dec20f62e4fc905110fb94fc9826907a420347bc5604bca895af800a4c80b12e68e2dd0ad5fbfdb350835ac3dcf77cc20147b334ce3863fd4028298e621e12cc1c3174c91b0941d81949708811c3802417850c43914a0eb90b8048de647ba002d8c0f07ba91f38b893709ea9dca44986212ae8e601461c968aaaea9a51b775d55534c5d4b0a93511323553d5b1ab35b4bae2187b63cf4fd4a7801bbc32c297d783f689e7bc7a3f7f3509f69ce3ec094e8977b9212930c377c909e0e48142005d632f0952e0a50af391aea8223ae78ebfd763c7efad16fef3e8e571739a84ab6c7bea546f6fd56e6cdffb0bab5ac8e661f5aca5c9b99879ae7d1a9e87e3a0c0d95d683d3c8e8fd112cd1e46e6b6a715d3f1a6eb7dfe0cabc20a2c8b602953b14dbc77b0e6ec154d7555db556cbdeedaa6e11848d31ba6a91a86aaf3864cf9490e07c43b5b01d540f44921416e0726d1c47ba348597c7b15cbda48a9f7024e78477568c60f29a5c6b792133676ace005b65a3555ad091d1c47220b3c82d22ce10010f95fbbd71f4e85597f2658c3feb4b558ce7ba57c97ecc8b5ae37c23db019a8f0a32de7eda7d4f97407c081497a23bcb22c340189bdf81232d7e09f13bbb5dbad5ebbd36a3db41f465e7f90679d79abb95831ab45b66be4b55a2fbe3793037dd135ec6873a29d3ad14e7adc9077641e222f9d1c37674bf76b8bad73fbdcbbb3ce0f72af3feddbf28a6a6ef33ed06f972c2b529cf7ddc699d187b4659c7bc17c4772771eed5fa27b25c6fe801c87ddf6cc4a46e4919d6db38df3a083d6e67d778ffa273cb9cdf3a23e3e4ee6997ec4b7537d47f4a8d7315ac3e93ebca3237fa9ae94e9bdaa2ea2d371bb4e75ef9caa48b15f904bd681b589f2972e9a1874d67b0c879bc58ef8fbe9a2e6ebeee1c527b7ba065785cd649a113a983622ea6fa3d14c5d84679ac4f7567acab2dcaf6641b457d481a942e40b5a85ad7bd494f9a63f569cc7ed416e4fe4c1b0936fb7eadd4b119a7aa4daa666b589465e366d63b64ebaa86f1a27bbb523eda591c759d4773b2ba7f5dc51e970d1a6cde7b08f12cb19bb64accad3f5fcf6394962eb6ccc1aa6713f0d6d6ffe7cea3fecc8042b74d35a4cddc7e7977642ac226834578e9537f3eadcb1fda6b556ee6ab5e9d199591646676db46a8eefee36ad6ab33bd91154d359d8491756bfda216430cedbee7a7b3f6ea75936f41f1ecc6d7530b81b2bf64257d76d363fde4eaae170564c5433f577646cb1f1c469655b640cc97620b7872c60876c7058b61b33b5656f67de72bade2ada29d0f560eb6ff7db7163519093aa9c60c764ba5f2f6aa3ac73a82bdd6a3d544f6ed6ddd48a46d51e9a6947d1bcf17649bc81891f86b3e7bb62d31919d9a3a2e6f3ea8e28a95f2d4e83d5a8b0e9b6e6c58632f3b5c7de6cb94826abd5f87e39e802c0eb4a7f19e4b2aed4c3565f4dba39d56a05445e9d1e5b1cef9ff3dec1e22f651bf5a6dd7f682ecedb9cbc9670ec71a2bafedcb85ec281efffcfb5de81a3d086cbd6e576018ef8053d85cfe504fd37cebe5ea2800e4f10bfeba270088c99c09307e5c3fd9313671dee6e9c3e5e9949bcde07f9c5288d625081ef37667a2a99e9493180f795465d35d4baf904771ec3aca90d4d531b4dad6e2a465901204ccb879f3bc75382c04f79eefcf537fb82fe477d0d0000" 11 | ], 12 | "rawHeaders": [ 13 | "Date", 14 | "Thu, 29 Apr 2021 13:29:59 GMT", 15 | "Content-Type", 16 | "application/json", 17 | "Transfer-Encoding", 18 | "chunked", 19 | "Connection", 20 | "keep-alive", 21 | "Set-Cookie", 22 | "__cfduid=de793f3880ca3326f9aab8369a58dfe1c1619702998; expires=Sat, 29-May-21 13:29:58 GMT; path=/; domain=.registry.yarnpkg.com; HttpOnly; SameSite=Lax", 23 | "CF-Ray", 24 | "6478e1dfbbc91d7f-NRT", 25 | "Cache-Control", 26 | "max-age=300", 27 | "Content-Encoding", 28 | "gzip", 29 | "Vary", 30 | "accept-encoding, accept", 31 | "CF-Cache-Status", 32 | "DYNAMIC", 33 | "cf-request-id", 34 | "09bf6b7fd000001d7f28a94000000001", 35 | "Expect-CT", 36 | "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"", 37 | "Server", 38 | "cloudflare" 39 | ], 40 | "responseIsBinary": false 41 | }, 42 | { 43 | "scope": "https://registry.yarnpkg.com:443", 44 | "method": "GET", 45 | "path": "/call-bind/1.0.2", 46 | "body": "", 47 | "status": 200, 48 | "response": [ 49 | "1f8b080000000000040395560973e23a12fe2b2e76ebcdcc121b1f982355533586808170863379bccd936df9005b3692cd35f5fefbb60c4c32a9795bbb142452abbbd5d7d7adef0582225cb82fd8280c452b204ee1aeb0c794053101aa22c9920a1407339b06497aa13ec556c6d2f024fc297131898b7dfef2a78004372376ce74578850c035c0113e4a1b064af0318969ca0af7df0b52e1fef7efa0d5455998029754fac1f7d7ddfbdd1f7cc72f69c419d8f651eac709bf2197fc89924b27c8de220f0347ee9254fa89004217d772bb128a93cc0a03e683510cb958bc6ec510a598a5e04518106e31667c2188223ea65f41f79d146d98200103e8c859ef0b2489049a112117b92b702a1363129e409e9c6c214509163e7172e95f9f40f283d83b7ed01ab3f47a8e3207ee4d68ec64b760bf650c65692cda3e221e0e634ff8ed37c10b5201398ed0ec1843b3d51f9952c493cc15febf623775761c45a05514492c62275f411511e7769e224f105d615dd8fff333891d2c881836764c581c6209ecfa4cf12e0b28fefce9e7747cfa225d6dfab22ec097e7145212b3208d2984ed7b213d25bc5cc129f021a3e1655df4d33461f7a512d0fdcc92c0c052b8f111b5f2e2c90b5be232a06f8b4f87983a90efdf0b1bb44797f483366c47ef36bc62f3b2e515750546becc0bf12e070cb05c4fac77d41b8c38b7783b78870ccc4464b194223b2d408542c6fc9872dfae50ec817588081db01ee578c48025eee8c5a36f1edf7217b937a0d70988c7c52fd1f8452458c2234fd935245c2c0c6c4c188fe4a03be36e645e0e80bfd5f1319aa580b10ce7a0f3e30827803050f68bcb3f0afe8362e440cbe14d65ff8013281b4cec0054810bdfaedc17748950316e00be15fead54254d9241088a3fdf4b8aa4e5dbf7e5ce4f5449951438b9a8e094aa04d25c163097cbcaa08b77b55f019cdf05bacb70cce1c9f975d82b3c68ce076b6f39bd24fc2ac9eff6702a4277a00161c1e5cabc8f828a9fe1c95d8eb334c97847f980cf1447096f3a70b2c510df1f9806fd", 50 | "19a138c4886188858b4286a11c7348f603c0e50f9a059dcf0dc2f067aa1f38b849396c0bf729cd305805c8e84056e0aab26a69b6e55a725dafe9724d5591eda89aae625b4535db91ddaaabd71c8747f335e002972287eefded362b5e39e2176f23a42c297a1ecf57e8876ff48aa4c00957e404d05821121031ecd120e5ed91f9485754b13a2ab6ad66e0d386be34adf6338ca1f410cd1e11aed051d03d476725b0295ef68a3232aafd9e9bedfc168bd5599dd889dd4ecf83497a5eb9eac43433e03267cf6c478daf5fe156b88165115c65294e19d7eab852ab294addd6ec3aaacb1a7234195996ea56505da95b58b34126e5900c39146f854eb107d6d39304be6d981453efade194c4b7b59847474abd33a8819ce026340cf05a517936f944c2ce343843b69572b55c835a4d2291051e416946790d88fcd36899dda13036c7c2b46b0e8dd9fca995d3d7744dae91bd1746002960819924ec013392a2f1e326d40726e9bd70b33c06b6c44b2e46730efe3bb0b6dd305a8da6614c1a939e5b1af6abcd27a33e5bb0a9415e96c8330c4bdb8e4b4ad41a2f3727add1ea94fb48a347e2af499a8cca4bd959990b34b2c879537a6a2e1a6716e297fa16cd0cc3315b752722fea47a08c2928aceb26f0cd82138e2d85a93debcf3104d55f7c5189d95ce62d41ad44db9511a112b74e61bbd5b3276d4ad9ebaac3b4e7646da3fa2b26b6ab573299b34d6a4532256ab970d0f935dc85a7a10fa93f359eb9d5a35e3682e124df3b2eaa89f94ebeeb252968bf67e0853972c936ddc70d6a445ababe149099f5957298ece4fb395bdab85735d636ed5281f71449bc5a5da591e67adc76daff7a8690b2f0c8c583b9e2a6bb273949e3e1ec9cf5b75d03c658ed78b5d4fdb3db874c80cf77929b7edb0d81d561759fbe1b09dea01a547dd5ddaed788ed7c42c2f9ba75adda8449bb8f2525507694f8fc8a35ff777cfede2f8254efacaec61da6a04acebed4ec3d5634f9e8ca6a7feec505e1317c967f5acd8d35eb5ad85f6f210c9f381e359d5d6b8f8a812bc7b18bcd4bda96ed9c6483d755acc31cfe1c156ed76f8bc268d7d735b29cf8e416bb1181cf4a523cbc9bed96c0c2a8faed6f6f7de6eb332baba7270e69381dde810cf6c9ab50156e56e674d360b3a9f4c2724aed2e1e42532eb66a23fb176d7df6fa62a350e7e7dbc2b66c5d57cf274eef7277ea647c929ee695a755e5a93595cda6c07db513f5626f5f9763f5fede489921eb47d71fe7228312529d7fa5b734f5393b4578bfeecbc522b0662d565dc5a93677bb85b35d0b0b9db0de3de8b328ed3d42a7ae3e6609bf4e6b432b656be3b788080048fa362cb79ec850dd3794e0fe616eeb690aef37affeaa6a727bec861d41a3efc0db878f7e7ed6bcef0fb497d995680e8ff36a11d78e7d8f07cb98c3850c45fc629fca045e60fdaebd8ff1f94fd71b102104e117f66a3b00b3d93c27fde3f7d78d1f1d6a9c13b88b78f5b6f12af0f5efea249a30458e0ef5b6b7acd5bd3ab5251e4b25caec89a5e565e6144aa55b922d72b75bda2d6ca7ab99ac7009ae6d487b9b63d50049af2e1f3d77f00d90604e9450c0000" 51 | ], 52 | "rawHeaders": [ 53 | "Date", 54 | "Thu, 29 Apr 2021 13:29:59 GMT", 55 | "Content-Type", 56 | "application/json", 57 | "Transfer-Encoding", 58 | "chunked", 59 | "Connection", 60 | "keep-alive", 61 | "Set-Cookie", 62 | "__cfduid=d74db7ae3db9eb774ff3e24379daeb0b71619702999; expires=Sat, 29-May-21 13:29:59 GMT; path=/; domain=.registry.yarnpkg.com; HttpOnly; SameSite=Lax", 63 | "CF-Ray", 64 | "6478e1e00ec8f8cf-NRT", 65 | "Cache-Control", 66 | "max-age=300", 67 | "Content-Encoding", 68 | "gzip", 69 | "Vary", 70 | "accept-encoding, accept", 71 | "CF-Cache-Status", 72 | "DYNAMIC", 73 | "cf-request-id", 74 | "09bf6b80010000f8cf61aa8000000001", 75 | "Expect-CT", 76 | "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"", 77 | "Server", 78 | "cloudflare" 79 | ], 80 | "responseIsBinary": false 81 | }, 82 | { 83 | "scope": "https://registry.yarnpkg.com:443", 84 | "method": "GET", 85 | "path": "/has-symbols/1.0.2", 86 | "body": "", 87 | "status": 200, 88 | "response": [ 89 | "1f8b0800000000000403ad57fb6fe24812fe572cdf6a775604bf310f29a70163204080f026c76cd4d86d63b0dba66df3c868fff7abb6c984c9657e58e92292d8d555d5d555f57d5d7ce7090a305fe3b7282ec6976013fa317fc71f318dbd90805c16244101094a936d48f9daf737836e486d44b80ea21b446cd0c001f27cb0f0775b907d75d9ab6085012ca5942d6c9324aa8962be0e2b368ef9bfef782725b6475ce6fa5d2f0645d74bb6e986b910e328247148e3ab3133b34292506f932620e66bfff97fc7f5ed8e87f82cea45499e88264e300d3c8239cfe1922de6ba130e93a347431260927090406e9225908bd3280a69227093fc21e6e2085b775c48b9788b82588094f89e8549cc32fff8308577c8164bb7476c7c1676ac06f9e670b6ef7c4471946e7c2fde824a8c1c5cbcbe167d94e038016d50c99e6a3c89028ea6842b1663cf6791f91e611a1f96d96b5c0c897f61d6619c5cd7516a836944433bb5b2a3e79657d577f74cbd1627a1b5e77eff9d7bdbf42a452e54f47fe5ecf0d7487253380eb9581c815ee0b2fdf3cd6031f370bb5c2c425b0521b94074187a35d7f8d92af3ff1ee28f0ce451b1d59a8b93f044e07811a6c9e5daf1b7917e666485146735b97174957d3880981558648bc55d9c17f2c6e8d3dd6f4fc974af3e40b708a1b25264b1bec133779a15b5c6e3983db0949c93fb5d7c17ec628eb5d73b8001b861d1da22e2623fcc6a02b8e2906d7346a73e689bfd615b08187e590ffc53339638e60e301ac0bf629184456c674f402bc47e5b87627145875bf3c7dfbe64c52e62780108c7a18f0588eb0bc587d4a3f8cb1f8218216b8f5c0ce70cc91f7f0ad798fe5cf3f061c8073084b107b8bf306c249788a108a28033e40402cf3fd38747180013a88878c37302b3017f7b7c3901993116e1730483a7772e641b840e1341036579f22f8ee7fbf04850e21d313c5ceb0d4fe644e733ee3836710419c0c4f280e720d0af39f18979c98a7078c703d6e3ff92cb424990c116a097bd0bb2a065afb795632b8aa0648a6fdb65", 90 | "225d901941e76e99565950244102d1af3a882949425528810ec02fdb5312d48ce73f63175097af312528cbf65f25884462c9630d0b2d98d13764851d359389374cb6a1e129861b8525d8c3e7c80774883a5c2cc20ffa72a0f64e78165526852588ec4d24973ed5249ebb4d32f2b2b6340cb0a83135393ff955c4f270b3c9556a2182a077ee78862b2432931ba55c48004fa001d940d4cb5dff88d58b90fd217c2fda86e4e399e05aa4a16717afc7072f0aff0d528609b063de130c0b90b07fdf7312941cd67e462b6b9b304da23401a50f704d7010b19060658f3160e60de210764a28f6318a31f49383fc18b30e6508ed7bf0e7876c0340639dfcb374ebd9d8a00cc57c2da12986a85c8a3161bbe06c02f05c021564d57c6b44762c40530723d6c1aab29175a456a4aabd51379b8da6abb65392644bad5634a4aaaa2357cb5547854837a99b81e39737ffe7d015bd384ef3f1610bb58f802e605f36607c181c3e37ff17854061ecb9e35f3c16f00d297c7d1b785e586de6ef73104034efad17b8ebdee50cbb3a38b23db886a15cc0c6d8a55e02dcc408a3242b40be4b54aed2be3833949ebf94cbbb503d8edbaf127a450bf35c4ada8767b7140dd5c1ec6276e70db96c3fd2f4c97f358ca1333b9abebbed594149ae6a8586313e7acaf828b64ff7f7b02bec10a7016c25eb255b95ca922549aa542d9714242baa8eb472555565ac22aba43bb2a6b094276c6203fa7acf17c52e444f2f029c0c2ead90bab73429166fdf8a597e84c47d05570cf04698c278519335d6768cbab13df15ea11c72452ae94030510083880b5499b29ee18beca761b61f06dca83de2260fed417d3a1b9b997c4dd7e49adb1a3704fe0415b807b823e3055965cb0634324c3535eeadda005812b9511e38d360bfa7b86535ea66c3a8d79f1a4f5d7748461d635caf4ee7f1a44e9e17c8add70b89391295aa1e6985decad20edd3e5d4ae979b526cd7a854a95c5d0589cc883d939e94b79282bcb49aba1d9d2e6715a978f0fcf66dd17db61bc79d44ec7b93dd4ba8b153af70b6b52c79540699f07bb57b5b78c4f076d62f6b727a762e9e7bdfaa454b543c79be1c6c5399e7bdaf0e45c7a97e7b2f7a0adc85c5c136d37155b66a13ef40707bb3e54bdd7b61354b5d9a2b2945d519f28cb8ad29d9e7bc4f5657115d6871499bba45958b614674d4653abaf4d824bd82f9fa7d3c764640e27cb71bd5156574a0f0f362da36262998ac79964e8ca636cc5ada6bed85aaadfd1d6049da7b2654d66c3ca6ae624fd57fbb1bb52c7faeed0aa3cf7eae7325dd9a351d3dc079ad3151febf1a91a3df57a4e596e12d8bb595f35eaedb8d5b8cce66d8ac6ee627996e4933e20f3c1a6736834367d7fda93b1d48d8c239d44fb56b414f78e398eccc69a6c516b66554879d27cc0f596dbf06ce43e943aabce69330bfcd1fe59d307cb67ab2f9dfb8fe7ca64b0bc8c8f0f41bc1c8e4bc19a90b93ec6f3fea43b12e7c1b4b5da0de7692b4ef072a60c93f273423a17110f4795c572952e88a418e9a16514bccab975266b622e8dc3543d19f27063b7f6f3aaa92cdaf3a7a8a1cf9459d835bcf1537728f576a302a2076ba228affdc2c3b2e9b6cf5444d06b1547c3749118d349f7903657d5c2a83c37269b5d7b7a76827d4aeacb99757a344c6feef4adcae944ddc2b1d36da913d75b13e5e9b01cdb8354eef63aeda54322d20d64ba53c2e779552c3def564fad46c1c08bc7b234bdf4e80a4fdd4bdc962254b994d6c4aa140aacdfefbb8695357e062373d0fc05b8d81dc3086c06f731a3abebb7bf7c340144fff24b1cd8d970475b3076e5f30c08d87796047ef3abfd9f38fb96470108a730428504f90fc09b14feb3a0b630890253c42a4c718c3edef8a9789d0cb3ef1041042a4910dd92d34b", 91 | "464e2fb22e6b9aa66aba5292ca2f30d954244d2f49521508093e95529605a0cec9967a647fa2087c65f7e4dfff05205680b7100f0000" 92 | ], 93 | "rawHeaders": [ 94 | "Date", 95 | "Thu, 29 Apr 2021 13:29:59 GMT", 96 | "Content-Type", 97 | "application/json", 98 | "Transfer-Encoding", 99 | "chunked", 100 | "Connection", 101 | "keep-alive", 102 | "Set-Cookie", 103 | "__cfduid=dcc3feda7d906c1b51f22020993dd4dbe1619702999; expires=Sat, 29-May-21 13:29:59 GMT; path=/; domain=.registry.yarnpkg.com; HttpOnly; SameSite=Lax", 104 | "CF-Ray", 105 | "6478e1e0189f0af8-NRT", 106 | "Cache-Control", 107 | "max-age=300", 108 | "Content-Encoding", 109 | "gzip", 110 | "Vary", 111 | "accept-encoding, accept", 112 | "CF-Cache-Status", 113 | "DYNAMIC", 114 | "cf-request-id", 115 | "09bf6b801200000af84eb00000000001", 116 | "Expect-CT", 117 | "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"", 118 | "Server", 119 | "cloudflare" 120 | ], 121 | "responseIsBinary": false 122 | } 123 | ] -------------------------------------------------------------------------------- /src/__nock-fixtures__/yarn-lock2.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "scope": "https://registry.yarnpkg.com:443", 4 | "method": "GET", 5 | "path": "/@babel/code-frame/7.12.13", 6 | "body": "", 7 | "status": 200, 8 | "response": [ 9 | "1f8b08000000000004039d566b93a2cc15fe2b96559b2fae72f7329549062f3038e3056f38c464aa81161aa11b6910716aff7b1a5d37bed9a45215ab40387dce739eee73e3ab8e410ceb4ff517073830e25ce2c1e63ead64dfeb27985244305bedb404b125484ce641eaa628c96e721d6298820cd6609a9294d6b200643597e00c205c03ecc983b52bda6d25210867b58cd428c95317d622e2820a89b61832c8b380a4ccd9123a806608e0dac47d83f88260edcf143ab17b78f16380a2964be2bf308380c430017ec53ec8b2843e71dc75132d0f9e388fb8948398c3f09cddc4cd3feccdc97dfa60e8a32cc89d0af9a6fcf38e28cd21fd6b9eedbbcfdf46e2b7dee05b4ffad3f119d16f927a5d6c5c1f49023163142117625a119a182bf69ee44e84683020788ffcfad3571db82ea495dfeb8a5bfff1bd9ec284509491b4ac14b232a9cc191d669ea7d1ffa4d8baa97a2885ee0da49e00f7c08e85febe6de68e1d6015d008391cc21e3cb742ca3c79906dc083d84590b1fbba674380fc206257c62cfe71cf0106c20e78f8ef161573cab901880e95b6d8e25b3c43fe4d4033963e4d8029aad4e4ab1a83fc441e7bff2d0b5fee5e995344198faf3a0d00cd63a6ecb97bb72bb61d08f76d05761457e1a128785257ea781dafa7747a5dcf6b2b5dc682a51df45394b133aeec15416cbe6e8441cc9b929d2683454fca0ed6ec03e51f86ff7eb6b7b6b6d1c58dffd698f4ad707db45739f6f2c4d99f45b005e9362f9437a280891b6663df5952f9b4d6fb4be5d4f69f9f99b70ca40e881e6397429fb14fcb164ee290b648ea73bf6d956b3e545ff3e7be5b997f61887b14c101c9313b0099e505ae420cbd25bab064e974dbedef7506dca4c8c720cbd32a839ad5af3fd28d696daecf6b4b439faaabf5627495efd21ddedc8afba93663a1672a2c116a2789854390aae501896388b3a7dabdb4aa144ffce4c6bed2a8ae826a6e5f1df507aa6af6cdb1afeff774b0507bab0d5daad8b680afaa8dd03555e3e8bf1573256f90cdd949e44ba8953bec081f82be5a1cb5039c5861b63695523a29391c5ef47720f4e08cf0a5a96833cb1002c1f2616296", 10 | "b1323a7dbcba81bcc3af56bed56d7165a63952de82e9188b1b45dd34baed253f3384c3543b783297ac045040f9e47a8ed6180fc6f67b01b9f50e6be47d33b63fb4a94c27035ce09e1c75cbfec1948d537aee2cf663a7abadc6bc7fe0c4f8ad982cd6efae12e3d9a11871871dd60d837b3fe372c09b9b425f4d94a373d9db96629e4f83a03f530eebcb124bc1d14b8421d4ec14cf469de2a8538143e10e2f902180a5a6268df55aa52b3c0fa9551e87eb8e63f56dc974b37eee72ca42d347aa3b318024f453295f6e9dccf04f3bdce80fcfbd62d3b6232b74c711e183ed181fca41af08b7b04b6541f590735991198acdbecc15e0b5dbb7f5ade69ea7f60ecfe633d0984d078590f227c50fd4ad6d25720747b329bf15a376a6bdbf66ea87153b4bcf6fcce9c2445b3347cb923f0c7638e9a4ee715c2c2e1c0c49070efcad96f4e7c376f47171dad087f9ccdef297b5f26ec5a572da8ce2502f11547a470f31e64338c1842324debfc5a6686c57072c6c1ac1d032e6235bd27a4707a3d0d858ab76d996d61cd5e792a9951f0bc36a777778bc192d4a6564cdbaf3d7ec5c1c1c6775ead257d376b43eec682a11f524b243df9e04e3a9b198f1baef87a8373c773e862c62c713a7495c248d2c8f680c7c1cbc05aed85bc9f28cf3d076acaeb7ac26e4ada16641275e2a59ac6c063ec8a7677387c363deabf2fdf918aa49f5702da3d174f85f8aab6aec9fac24d714b289f6751fb218b92422cd143920f708ab6b58cd3356adb785d6cf857f8db90ae7deda6fad9909aa165e0d5856c0f5a7bffd020f2ee41132402f01c469c9a4d5586348bf3423e203bca77199050f1c1ea47f20f0cbcc031856cde84e9abd2318bd64d40daa5192b2b9fbe8059e59cb632d04013603e3073b07fbb220fe671fffcf09fd221846419163ffc1157a09831c60bfc5be677efcfd1613d6efd8270bfbea0091c1c642cafeab1005a41a2f752ab1cf88aa99de5b76f33e4e196c16274c85dd1f3af5e7cf4efd29b4055112e4362ff37ce7934d3f456e2bb22ccabca2c81d3695ae49c186d73248113e142960607b1051f8e39f56fba70186090000" 11 | ], 12 | "rawHeaders": [ 13 | "Date", 14 | "Sat, 01 May 2021 07:19:46 GMT", 15 | "Content-Type", 16 | "application/json", 17 | "Transfer-Encoding", 18 | "chunked", 19 | "Connection", 20 | "keep-alive", 21 | "Set-Cookie", 22 | "__cfduid=d766bc3ab35a62537e9c52a2d770cb8351619853586; expires=Mon, 31-May-21 07:19:46 GMT; path=/; domain=.registry.yarnpkg.com; HttpOnly; SameSite=Lax", 23 | "CF-Ray", 24 | "64873e528f2b1d67-NRT", 25 | "Content-Encoding", 26 | "gzip", 27 | "Vary", 28 | "Accept-Encoding", 29 | "CF-Cache-Status", 30 | "DYNAMIC", 31 | "cf-request-id", 32 | "09c865479600001d671bb27000000001", 33 | "Expect-CT", 34 | "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"", 35 | "Server", 36 | "cloudflare" 37 | ], 38 | "responseIsBinary": false 39 | }, 40 | { 41 | "scope": "https://registry.yarnpkg.com:443", 42 | "method": "GET", 43 | "path": "/chalk/2.4.2", 44 | "body": "", 45 | "status": 200, 46 | "response": [ 47 | "1f8b08000000000004037d56796fea4812ff2a8895e68fe161f085215256c365200173987b9917f968ec06bb6ddcedd826fbbefb569b64ded34a3389e8a3aabaaaba8e5ffba34aac10559faa8e6f05d7eab7ea3b4a288e085024411124a0b8883a098ed983ba464988891554284b30f1602a023ebb114195047b3e8323017610a15ced6cb2867d82e28862162545f5e9a3ca8a98b33ccc45d32478ac6b3e63317d6a3480eea7b6e04461a374ea310a5cfcc7b72a221e2688723d2472b99e7f3f2b9cf170b26430441930f2a8f2db6f15469d4abd1e27d10539acc26d534e3e075106f4d0caeb999510b8027d6e7206299c8af56e816b36228e0f7a428b812395721b5ac955b850e03a1184ca0a02b058e567f81d13062a1f0b943c3394b37a007295ff567e4a83ab57546451e2c2c9ff809a204a4a7541947e2d126e807d46ba64121a0588af020ce323f68f058c16a10f6a51caf094408440032b603c4709dc80c10d619378368c92da8291fa280860ceb9259883884bc00811e62bc8406811b70ef9e5a6f975aa7ff27a8811712136f891066ebdfe69f3a9fa5d1624410471a81a2b46c0e0650241f1501e43a8be8b425350814fd398078cd61f11008e2ac84293a7d245ef83ff37021979aafe5e7af533ee60ac0947c0588e1c2ef0bd29744a024f6fddc6bc8e81d66a97441c728bf5738228cfeb77e9f3f423c10f51ad948484f2adc89de53d0027a2e01dc1d128e40ce5f364594e65773cf4c115403a8f60f73bbf49c9874d393730842d175c81f1e470a10f28e7f7b20cca5afe560d23a8341e64ec91088cf20ae1d5dc78e317e285f7276885561823cb05bd1d4d6b599285545bb5454d941ce72cb614b165abea59d190aaa9565b3cdb1db067a71ea8fbf86cb87f6eb606a63405eb60cb8f42145b1e6fb47f3ef3af045c0228f9567dc3dcb5b277fff80291371287dbbfa0a525a86598dff8b57f92c5a620f212001520bea12829dbfc015014a2c7d390f8290f1f0a2dcc91e357f21f1e2772e428ab087314f8a862c2909760e80590f62d", 48 | "5594ea33866be74e10bf184ea62b6cb76d37e6c97acd74d13b02a7addf82a2eb423f5a81a3eff4e54e976a86d71f9bfee5dab76b13bd37bd75ecf4980dc5dcb92e374a8ccc74f9fc0c7e81059af21a715c455221159a66a98a2ccbce197696d2119b6d475464c95614a7a3480a9c6156620392c0a1af1043bb80f74921401c2e548812ef130beb8fb95ec65560de1d8e9f7180fa514ae0b61a002a892de78a5c13df216952ab2329dfaaa0a64ea1a62c96263c9575fed71b8e264665315a54ccc9c8e8ae37ab61493f2527f29994a7ca1c9a1d44a0f42aefbcdb14ceed033220c29e2a5ffe4620157bf1c3552ec17f19d59d5e77d8eb77bbcbdef2c59919c3acbfea76d65b6a76c9716779dd6e186f96dd17af7f2c3cabb7efdc082e5eb4c3563f91f9fed6e91985d333c9b858b9ea8158d1bc35ee69e8e237664aff70182d6eaeb96ccef7c3abc890116a78e18ffcc8b17727d24443c76b7a946cd7de75f39aabb11cb51571fb5ab859a149fac09b77762f97d7505af61b61961ec6bdce75a2ddaf37d93f91ab75ddf58c51f09adbafc6615fd3f2a6d2dbe7e2b8ad13b16f0e1b0d5196d325d9eceeb39661ee934d16e3e3fa9eb13d06cf0b7b68a697f3ebad95b7067970a0ebb5e9acfdfe267297cb350df249e222b3bd38e6cba9b8baf533f262cec6b82d92c9892c566acfd8dadde1614e8f69d66e87c690392d3a06b036e4a3be0d8e993e4895e3805ebd6886f7c7edbbb68c5bddbd6d40665c7a17d1a531efe96eb6395f4c51c35e343ec8742ed7b4489ea4ba6ef5f73325b89a43e99e6a9d99d4d5c6cdd1b4b93a918d539c67e2bcdf202b67eaa161c126839e39ef7ac850186534730bcbd39772eb5284e87553dc6b37b579c73dc747c5891c49be988d0e83d9eb3aaf85485e8fe2b36cda176cc2eb700cdba3e96ee1afa6f6f532195817ddd1c94d1a1ff79bb43105dbb1abbf4c7637f282fda4e3e6395e98b9ebde8e34b61b2f91140ea4da646ae4abf9b1a7d6c83d0ca664db585042ec7cc6a36634f161b0642d83ed1dd418cdf59945a719cbb07b1ee7ed9e52d8e1dcdec836b3434fdb6a73af56cbe3ad57f3c513599ebb7d16c56d7a2cb6861cb4d4773f22fd1047b7d89c2e1768789dbd6723a3d5d032dc147b2bac6e27cac01db209622732768c29aff7e7014a967c5176d1d018fc4d6f717002a0220c7e008980f1f00e7cc21916ac50b8e1fc172883ee7d202090e1e84fd9bf81bebfe47fe5577fc0a3e2e204be81a2e4f17083171c66a1c1138b7fdc59c10490328199a3a61f95df5054862f328e1e5f8854e7e802ef41f97d11f2179d85f10394de4a507a1355a5a53565519544b9fd068fbdda142519fe3b6aa7d551dafcfa6f8092a60f5f06d72cb140c9d90a28faf13fbf0efc578d0a0000" 49 | ], 50 | "rawHeaders": [ 51 | "Date", 52 | "Sat, 01 May 2021 07:19:46 GMT", 53 | "Content-Type", 54 | "application/json", 55 | "Transfer-Encoding", 56 | "chunked", 57 | "Connection", 58 | "keep-alive", 59 | "Set-Cookie", 60 | "__cfduid=d20138a9aeaabc73df9e17eceb05b68641619853586; expires=Mon, 31-May-21 07:19:46 GMT; path=/; domain=.registry.yarnpkg.com; HttpOnly; SameSite=Lax", 61 | "CF-Ray", 62 | "64873e528b450e76-NRT", 63 | "Cache-Control", 64 | "max-age=300", 65 | "Content-Encoding", 66 | "gzip", 67 | "Vary", 68 | "accept-encoding, accept", 69 | "CF-Cache-Status", 70 | "DYNAMIC", 71 | "cf-request-id", 72 | "09c865479800000e761f1f7000000001", 73 | "Expect-CT", 74 | "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"", 75 | "Server", 76 | "cloudflare" 77 | ], 78 | "responseIsBinary": false 79 | }, 80 | { 81 | "scope": "https://registry.yarnpkg.com:443", 82 | "method": "GET", 83 | "path": "/js-tokens/4.0.0", 84 | "body": "", 85 | "status": 200, 86 | "response": [ 87 | "1f8b08000000000004038d54db6edb300cfd154303fab2f81ec7718002ddd20d6dbaaeedda6c288622902dda56e3db24b96b12f4df47d973b20d7be8436085e2210f0f49ed48454b2033f2284d55afa19264449e40485e57681d5b8ee5a085b62aaf0599ed06f75b5ed695f169c3a028c8cb88143c41ac0e74797e8700063211bc517d987786800c9e0d9553657469f816a4b1a04ff4b673b310b286cdcf5a304966dfc9e1062f1e35a70e357c118dc72e267918919417d0c178c5e0d9427f340a686ac9552d369ab6da349a5cc615025b51f4e7b7b9528d9cd936daf336b692bab48bae267baf87a53158615f0fa6c16020150628eb24a78669b6dc508c615c908de02535314c4385ce57d50c8c7fcc86650f3c0d40a9372ae75586ac6d9081263f2271cb0b36c033a8405005e6804207064ffaba290dd15646e76e1c1d19dad09143bee8720a0da02255c2b53c3b92d4690abf1b8370cf722df7401b2d43bbffa2857617c7c047cfae62fc1f74638149509b33a09aaa03f1042246017ccf9d383476d2844661144f5812b9d48d22370e3d27e9aacb3a3a7d1b5ed1029b4bd962099830af4b6868a6b57d05f08d407238de23b2e29ae4bea92743a52b94eceb7edc036bd28dfb4af7ed609e5a9135d641d07929e1cf3de8a705efa0a45c4f95d48b61f5e6934c1bf55469ea8ceba9d9115e29c80457389744e634703df30b5b2cd322f9e027cbed05bffc7193c979eb4c3e5eb7d1929d2fae9c18eee3ebfcecf3783da14db6503c4deab9ba8be2e4f9aab97faf9a536f3dbf9cdcc6db6c3ca7adfc665f5fdc1c1f232fcc20db1253b991e7f8691c44d809964653f0a9370d9dc061e3c9384c18d0d4f7c651841845454c71af0f1ae3aa217bb1b150814769d5223b2c886d1ece66a7aba5b2adae18abaf14fe505f5ceafddbf16acd1e7ac9af1a3dfff892d0e21cb513f8d53ae675b785d2c7fd455ae6c0d16c68b2c611e95e8db2c12a54d9fc8fe2ca0ddcd01d3ba11fba536f85231e3861e879be339d0691e7457dd70424f88af42bf4f2f20be2", 88 | "d20d0d31050000" 89 | ], 90 | "rawHeaders": [ 91 | "Date", 92 | "Sat, 01 May 2021 07:19:46 GMT", 93 | "Content-Type", 94 | "application/json", 95 | "Transfer-Encoding", 96 | "chunked", 97 | "Connection", 98 | "keep-alive", 99 | "Set-Cookie", 100 | "__cfduid=d099bf2a92fcb910591e4ec15278f32411619853586; expires=Mon, 31-May-21 07:19:46 GMT; path=/; domain=.registry.yarnpkg.com; HttpOnly; SameSite=Lax", 101 | "CF-Ray", 102 | "64873e528ecca5b2-NRT", 103 | "Cache-Control", 104 | "max-age=300", 105 | "Content-Encoding", 106 | "gzip", 107 | "Vary", 108 | "accept-encoding, accept", 109 | "CF-Cache-Status", 110 | "DYNAMIC", 111 | "cf-request-id", 112 | "09c86547990000a5b260307000000001", 113 | "Expect-CT", 114 | "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"", 115 | "Server", 116 | "cloudflare" 117 | ], 118 | "responseIsBinary": false 119 | }, 120 | { 121 | "scope": "https://registry.yarnpkg.com:443", 122 | "method": "GET", 123 | "path": "/supports-color/5.5.0", 124 | "body": "", 125 | "status": 200, 126 | "response": [ 127 | "1f8b08000000000004038d566b8fea3812fd2b8895e60b0d49c8bba5bb9a40f37e13e8342cb32d27711e9017764280abfbdfb71cbae7f65ced6a072971a82a1f97ab4e95fdbd9ea018d79febb4c8b294e4b4e9a4514aea4ff50b26344c1350c92db9c583c4c5d42161963fa42f38c74e5e2b039c0798d4502dc7240e1314d53ea16a9f5051e8e084b25566a30d00119ca534cc5372ab3f7fafe7b78ca9fc30075541a2c77723c8f38c3e731cc883c26e3969cc39018a4edc27fcc3d3169bf7e3a98e8a3c00bf01ef63436698b804d7cc94040505641ca39061d34a4e2bf1ef3e1332ec3f97feaaae14808d133f4c30adc0539739fbcf6f125bf4118f4a91639a83e29ad67efbad862e88a9bd3062b3fe558725f1b575646ed8242d2926eccf1f4ff513be9529712ba3cf68b1b16019a8046cce67642b5942d308b3af2884374a281b687e634b81697e8337f16d78b76585a9021c45305e190a8cb0d918256e33822d31f523ef3fbf188a83326487515881b955a2419a93027f3a292831f3dfc51986bd254ef8084f8068d38b900f91f8b7d8e281361006175f5e7eb163010213bed57e502b8c19f99a1ec134608a7635179c4e3fcc3ea03ea207c22f717c62dc1962e482585565dd730451b6051bf3aa63ab922008aae6aab6801c51744545f5b0a3c176ecc2af32f7a0dcdfa41b17525ac05e615b411ae30cf98c0e7f73f23f083809d5f6547f0f99b37f65f2ef9f75f69e64f1eb97ea53aaea7b4f807a3fc55a4b105a228302eb2d30ea0bf5bf72182cfe0ff359864246deefc0d31cfb84a51d9c0b902cb49babe3ebb174df46b9c46bb351689cbb6f52ba9d507fdbee9d8dc19db697d92996d06a671fe3c6be67f51c4b32bdfe7c43a46236dfc788c737c993237f4a4e1d1ebdf1ab595a7efb067ec10ab4886129dcc68a8e2409399aaab63d55430276781b92a868baeb29b2c863cfd13c9893236223e0f3cf9813ec83f7e4d682381c692b25fe2f1d826bfe226856816ee5fe1d00598d76d32281fdcbd07e920c3927ec9ae11df2aa2822ff54", 128 | "07dc260dfd04e50561c96eb25fa73718cd6bcbc1b2668e067363b35df72af9811c928f243dd716501c6002b55ebbb06a9098b60bf58793fcb9f6499a14ac323f7bf8ce2cd853d2bed3317a9dae61ac3aabb18d4fd6babb36f4cd2b358d646f21df300c4e5a19a368722c8c32bc6b5a2fddaaca74b83b243dcb6af0e2208d96ca0d67fc2ed0c7a61aef14c7554a2b4d277bb117fb67db7a894d64cdfa7c7cc1f34511f0c57df27248567d4e27a7f0e6a977c8c034d0893a5a8c3706d7293d7bb0ecaeefa3f6ed4d1aa828568395ae6dd54eb4a48bfdfa98728744a6f649de9958bebd26921338d248ee4f87722213a7515e1b93e9b9b111afb91108772c34a6ce31ea3828d9663ddd468764ccc98a6f9ec399e0edc9355e8bc2e4d4918e4134386dcd7261d11b94b4519a8bf5253172bea7b8a7cbec28ead69ea487c486ad6e649fbf6b2eb9d0894fb96ca1eb5d772adc8ec7c93030cb1077df4c844ba1fd321c5a376eb79124796577df568784bb591d3f9f2afdd3657bb904541deb74510ed3cea8bf31a57b4013a1115f47a1d6c6b9d5458d41bb1862672cded7ca15f26a58527a9eae49e98efb77adbbf344c939a395ee25a7198aa4b7fbcb9e1b28fd701507f9b6d7f7fab3b3908da63374168033d619758ec5528cb57bbc6d9f17dbf584478bf19cbb8a8bb9e7bfc47230942fc5694c67c67423df56eb624ea3f3ce2a2f87a4e868f795b6182a0d5316a5d125b22db4baee787126ad43ee4d4b83d5cbdc3d0e67c120f18d8979eb0eba6fbe6d8873a21f12e3d2d0e65d8f18bdd9682cabab345c661b5ae89dfb623b3ee67b372ef3cc3187fb747f7c75c390e81d47caa2f692bb01d75e976279136683f3667ab746dd7dd71ed9e5d035ccd96c70d99cbad7b2ad4ef6996e2fcec3adbac77dabd0a38d77d6b91e44ed2cefee8cefdf84659eb28faa8a7af397ff515bacf1c2999de4f0408b84c3f5fb9ffd2d6ca1b8750eaf7f39d53f6e032086a93f6dbfb6c8ff66ff555ffff1076b9104ae3b29791c74e005ebbb50e004b1fb108a46d03a098cac8d06697517a0225c5f58f7f86c514dd65ce0c4a80eea38835e92c7d92fcde9bd6a4eef02e45115754d56db82f00ea79f2eaba2a0e98aa6886a5b113416887768a06640c2e4541204701e8a28fef11f0005c737d3090000" 129 | ], 130 | "rawHeaders": [ 131 | "Date", 132 | "Sat, 01 May 2021 07:19:46 GMT", 133 | "Content-Type", 134 | "application/json", 135 | "Transfer-Encoding", 136 | "chunked", 137 | "Connection", 138 | "keep-alive", 139 | "Set-Cookie", 140 | "__cfduid=d766bc3ab35a62537e9c52a2d770cb8351619853586; expires=Mon, 31-May-21 07:19:46 GMT; path=/; domain=.registry.yarnpkg.com; HttpOnly; SameSite=Lax", 141 | "CF-Ray", 142 | "64873e543b461d67-NRT", 143 | "Cache-Control", 144 | "max-age=300", 145 | "Content-Encoding", 146 | "gzip", 147 | "Vary", 148 | "accept-encoding, accept", 149 | "CF-Cache-Status", 150 | "DYNAMIC", 151 | "cf-request-id", 152 | "09c86548a100001d67cf0d1000000001", 153 | "Expect-CT", 154 | "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"", 155 | "Server", 156 | "cloudflare" 157 | ], 158 | "responseIsBinary": false 159 | }, 160 | { 161 | "scope": "https://registry.yarnpkg.com:443", 162 | "method": "GET", 163 | "path": "/ansi-styles/3.2.1", 164 | "body": "", 165 | "status": 200, 166 | "response": [ 167 | "1f8b08000000000004038d556d6fdb3610fe2b8206b4c012c97a8f6dc0438376c1b2a14917a729daa135288996584ba24c5289dc20ff7dcfc971a21603d60f96a87be3dd73cf9defed86d5dc9edbacd1c2d16657716d1fdbb75c69211bc84337707d4872ae33255ab3979e5e2ccf2d4858cbad4c4267ada5b2c85d3405de0a2f6d89c63225b70c57b56858852895c878a3e9beb7e7d7f856bc955a18a976f6fcde36bb965485305075aada9f8f4a635a3d9f4c202fbbd4cd643dc94a566d26a39c5d727a38b659674aa928d8635d4bd1e48a5b4ba9ca8e2ae3351314580f723d885f1524a4c04ff78ed58302b179538806f05070d48c20bf2d22ba748fcca0305c1b287a69bd7861b15b8680d072145d4a52e8dbc2213c2cc7c175356bf2c54b0a663d5bbd844e7666f12c71e10561cbf21cb82e429cef446eca451ce358725194669032b3f03dcf83b0914ed6299447f9ad057575fe8f8d9a79ef7ed5f6e7637bc3777752e5839c80a44c0fedcf6405cf639bdedde1a008be512f33d968597132abf6ded475b2313b3cf7ecc001cca899317b9d2a52888238c15397bc2252f41414ef4a92379e80994e8f0039e014dd62786f28f19cb71c753499d8f76248166836202d41fcc57767ae4775e7fcf6cd0fc6d492b9fd2bc2a52ce595d3ca6a077888115f123708e188c41e9be450615060028619e8e5e08bc843987bd077db09454cf8211a4c40c83f38cba1cbf9491c9cb06992f9d93a9acdbc24f5781a06cccbb91f79413e8d665996059454570c34da93ff67883f115a7700023796b2e62d2b289d9ff1fc45213dccfeb1bd1294e6689a5e1da67ed5b4f5cdd32e88dd64c067458c7d164f8177446160fc5ef3f1f48dc70816ff337cd43241f3730fa61a5e28012661664a16fb817373ed7d3a4f369faef2eb72fa71f7e75db87c9b7eac27ddd1c576ad4ffbdfdb0f97debbf54c6fa7133e8b3ef4fd65fbeeaf7e7676e59f55bbd7e6f2e6cdc5e5df47d3c654dbb35e5c65472ade9e2e16c80b37e8aec65591bf4ed3c00ba290c75eea0729f7d6", 168 | "5e944e739ea76b0f6df4323e8dfc1c3e86a9940dc43980ad7881ecd5ce050e5fb52b5531de501367fce50c08bba6f88650349faf65d7a0f2088baf6959b6e1f9527c432b67e1890f5cb0a01a831f7a8141be7f4252b8ac76b7a2ff6e853dae3e88418b67db7133fecb7eacb71f3e533314cfb09cf783862ca8c3972d578cfe0658758e26295aec68582987c5a7432c6a58390730b0b5b20d48392c8fba05c6a66ec748ac0624567eeccf66d330f1bc240e569e7b92c449148651708247344d88e02bb4695962cb6cee1443a835ab347ff817902b544ec3060000" 169 | ], 170 | "rawHeaders": [ 171 | "Date", 172 | "Sat, 01 May 2021 07:19:46 GMT", 173 | "Content-Type", 174 | "application/json", 175 | "Transfer-Encoding", 176 | "chunked", 177 | "Connection", 178 | "keep-alive", 179 | "Set-Cookie", 180 | "__cfduid=dc52712a993d424976e8b3bc54a186d051619853586; expires=Mon, 31-May-21 07:19:46 GMT; path=/; domain=.registry.yarnpkg.com; HttpOnly; SameSite=Lax", 181 | "CF-Ray", 182 | "64873e528d6d5f3b-NRT", 183 | "Cache-Control", 184 | "max-age=300", 185 | "Content-Encoding", 186 | "gzip", 187 | "Vary", 188 | "accept-encoding, accept", 189 | "CF-Cache-Status", 190 | "DYNAMIC", 191 | "cf-request-id", 192 | "09c865479700005f3b5b2db000000001", 193 | "Expect-CT", 194 | "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"", 195 | "Server", 196 | "cloudflare" 197 | ], 198 | "responseIsBinary": false 199 | }, 200 | { 201 | "scope": "https://registry.yarnpkg.com:443", 202 | "method": "GET", 203 | "path": "/has-flag/3.0.0", 204 | "body": "", 205 | "status": 200, 206 | "response": [ 207 | "1f8b08000000000004039d54df8fd3300cfe57aa22dd036cddfa6b5d26814e8207ee01f170c00b3a4d69eab6d9b54994a463e374ff3b76bb8d3d2071f0523b76ecf8b33ff72954bc877013b6dccdeb8e37e12cdc8375522b34a6d1325aa2a50227ac347eb2be6f413c06b20eb86df60106063c700684aca5084e393a2940394afce9ee0b66b060b4935edb63b8790afdd190ab911e5d83ed26fd4debbd719bc502eded504642f70b275565c169db0e6e71ae31a2c0e759c807df6a4b094f20eec7dbc1fd781d5343cf2525bfce72db9091925fdebe768f0ecc0daa910adc985c5754edbbb7193d3a75627478701e1d071ddcdc047ccfc95dcb8ea2be87580a1ca29d0b1f66e1231c7f685b8d7604810f0bea21ca0a3c08ea82d0ca73a9c857632889691aa293a3bbefb9aae61d168547ea3c0a63b50047316898bea7c3d083a2b4681f553237e0b521632f95ec25d63e0bd130a9586505fb0f6000eb56424ed009d4267c8d170f7a54102136ff23f00a8feb3211bc80154b5129b2a44c589da48cc52c5b1645b9ca4a56d7c53ac6f07268c6964dc37ee9a017d2b9012bc1575bdd83e1cd48d517d2e495c53291dcb3702ba9dc337d6ecfb4de3a340d3dbacabccaf2ac1249cc188724c9578cd569b62a20e7cba24e4b96e725af692cdbda2275366144ba32fdb7cbb624519c4731a1dd2aa4cc6f4716ada3ec74fdab836bc65e530f6ffc85b0d8878ae6868cff9fd23db725ef6821ce03b0d0603e7b8c10c8ce45da3697255bcc2fea7c6c58e49b9f34095c9f91aa881b797ed9bd7f457209dc954a0add71a2f919ff8e1b031d32fef600a5e4d3523e4c0dff6cc072fa15f1ee4e79b028a921ad1e97d1a5f8034134f333b4b9e1e21189431be07b83e0f1fb0768db388f33962c19ca78bd5d4669caf2354b923463ebac58e72981afa4c57dd576da8fe7e75f0d6bd8a440050000" 208 | ], 209 | "rawHeaders": [ 210 | "Date", 211 | "Sat, 01 May 2021 07:19:46 GMT", 212 | "Content-Type", 213 | "application/json", 214 | "Transfer-Encoding", 215 | "chunked", 216 | "Connection", 217 | "keep-alive", 218 | "Set-Cookie", 219 | "__cfduid=daed8a993022ce7f983399520c575d7861619853586; expires=Mon, 31-May-21 07:19:46 GMT; path=/; domain=.registry.yarnpkg.com; HttpOnly; SameSite=Lax", 220 | "CF-Ray", 221 | "64873e528c841d93-NRT", 222 | "Cache-Control", 223 | "max-age=300", 224 | "Content-Encoding", 225 | "gzip", 226 | "Vary", 227 | "accept-encoding, accept", 228 | "CF-Cache-Status", 229 | "DYNAMIC", 230 | "cf-request-id", 231 | "09c865479800001d93408ef000000001", 232 | "Expect-CT", 233 | "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"", 234 | "Server", 235 | "cloudflare" 236 | ], 237 | "responseIsBinary": false 238 | }, 239 | { 240 | "scope": "https://registry.yarnpkg.com:443", 241 | "method": "GET", 242 | "path": "/color-name/1.1.3", 243 | "body": "", 244 | "status": 200, 245 | "response": [ 246 | "1f8b08000000000004039d534d8f9b3010fd2bc8d726c67cc590532af5d03d54bdb495aaaa8a0c36e05dc0c83669d328ffbd33b0f9586955b53d00f630ef79deccf3890ca257644b2ad319bb9e372b7250d669334038a2114dc88a48e52aab47bf44df069d763e307530c30284b9400c32d0de0507d14dca01a8171a39f420d54ffa889185c491ed8978e53cfc1c8c5401ae31e1bc22568dc6696fec714e3a8e585ca33d8027db2deb37ceb5db3084e80e9e762a6965fa50d69555c2eb830a6f62284281f6491d7f182be1e46f2fa5cea940be409ed3607f597d5f1131f9d6582ce7b957efbe4282027558cfedd85d8321ac054fec74a50687d57f78f804f9e5d4ccba1715adf7a35b34fcb1fe503b87cd04c2d6f46a140d32fe2d1a8e05fdef959000aa4a2ed34d5c948cd52ac9b34d5af334128cf3a2de0899a732678c8b18407b3d03ae96d85d6cb077ad70530f6c824b96657929f3a24ae39a179994699cc43990b23c892a9125651567c8565b68c996505c0f63ffe5eaae946e683447c105b7700ea69bcb80e4cf4eddb7fed66d80dd46402fa37f3903092ec5b9fd4fd55ed8527438e14bb7ad6a80cf1e2994f5e8a8b1cd9dd1c2f5dd663df78bfae6170e0eaf8187076483fdae2efa1729e042ecdcc7515970b81944f7307865e18bf25a335f259780a1206b7d29743d8aea091c8337cff7234881f7ab65eea38cb128e32ce631e37b46c11dd1264d8b8c1769c4608ca0436aab2ab8991a08b7a7f3f937fd304b323c040000" 247 | ], 248 | "rawHeaders": [ 249 | "Date", 250 | "Sat, 01 May 2021 07:19:46 GMT", 251 | "Content-Type", 252 | "application/json", 253 | "Transfer-Encoding", 254 | "chunked", 255 | "Connection", 256 | "keep-alive", 257 | "Set-Cookie", 258 | "__cfduid=d3b448c5839ffd4b07fdd90efb84f801a1619853586; expires=Mon, 31-May-21 07:19:46 GMT; path=/; domain=.registry.yarnpkg.com; HttpOnly; SameSite=Lax", 259 | "CF-Ray", 260 | "64873e528a685f53-NRT", 261 | "Cache-Control", 262 | "max-age=300", 263 | "Content-Encoding", 264 | "gzip", 265 | "Vary", 266 | "accept-encoding, accept", 267 | "CF-Cache-Status", 268 | "DYNAMIC", 269 | "cf-request-id", 270 | "09c865479800005f532a811000000001", 271 | "Expect-CT", 272 | "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"", 273 | "Server", 274 | "cloudflare" 275 | ], 276 | "responseIsBinary": false 277 | }, 278 | { 279 | "scope": "https://registry.yarnpkg.com:443", 280 | "method": "GET", 281 | "path": "/color-convert/1.9.3", 282 | "body": "", 283 | "status": 200, 284 | "response": [ 285 | "1f8b08000000000004038d567b8faac812ff2a13ef9f8ef24698e42407c107be1fe8e85c3793165a40a5c1a6517472befbad769c3d7736bbc96a6cdaea7a77d5aff8a81094e0ca4bc54f8f29adf9293963ca2acf9500e73e8d3316a7044e27471493a73b0fac9c278783a75d417cce9183c08306cc52ddac2b4041058b525a79f9f8b2d1c58845983e59944505050e9ca0f808123b74c5e84efc197252dd4f93caafe7ca31f631c9b97b43d7037e8ab3348f594aaf5c2bbb66fc288cb9bf05e58a605f8d18cbf21741807d546cb92a611a9735e15b84752e05163e83ccb9ba8c628673065aca14143ef6240df013df0b5b94c77e7d9f73b103be5e521a80dc7f3f3307025cff3daadf497cec308ff577dae00f0db7b046f9f1be9ef97ae1143fb91ee081481e3f1e925ef9e3b9b28b8ff86e2c26012eb913ffaf307f10f2bcf6e5d82785a605c37c0b2a202808921677451f70bf3b541c59cd473cbfe27385a4b5981c6382a10892041306f6809c669822c8788d1f6d29460720ff821404f8ece00c833fc48fb9731f153f4247388602802f78c84d56c4ba24d5659eb4e0afecf7927bd41f975138175c0cd4490092a619f85a8024b9112881d408c4ddce08240599a6b60be4404768ab8a2a4260695b84770f3eabe05f558010e779017e83c9284d7086425e4cff4af43f908600bae6b9f21e7347bf55d6cfaff27f2759b2fc6c14e0d1213e914bf082fa4d36eb70702767c922874281343e32728a4b38f86a91b88e923a90be374810f382fda8c484e190c60cfaa292474893e4da74672d58503db7038bb5a7be6dd8f675cda4ddfab59c9facb82ffb7347bf394d63a4f859de6a5ae7599999b77127d43bc2bcdbedad2dcf30047413dcc2e958837cb4dc76c21f3fc027b090170998da6e1b92a189ba2962692729baa63702accb26dc8ea636a4000748f5256c800c43748b8ebc47bf524c7108ded36b1df2b4cfeb290dbfb7a8f09796addd135b67e10dd4f186b0d38240f40d687e9221ff8083797c834b94755357a1a0b3a496c72141aca0fc", 286 | "6a6bfcd36c75dcd1d3a433799abb9d91e52d66ad3b7d4337e4712b2f4f63286b6081c6793a2b75b1aef253fbb32b5e9ebefc87ce2059987dbace39f8ef92b7fda6d56ada96356d4e7bdb68a429f6cc32bd653eb7c8db2b0a2d6ba8ab53ab3f12ecd95488f5b3dc63afcb83956e37846dd3de7c959313123c39bd7957575b9070b50e4e87aaa2acda526b8c3d7baa42835cc5dbfa600cd9d039181ddb1d8b1b82faddce2d0a6dedd85fafd6bdaa6eb504d11644b53108426f716a6dd734be7887b587a4f635bd858361180587e6e0706c6f88e5b4de147c8c4efbc2ee8d222cd86e77672d9b7404d0d760c658bf45d3b54034e562e96c618ef4b07792671ad90f071b226cfb6dad57b656faccf5daa5aded4f8b29f6afce4e2ad64c6c0aa2db9bb6aec73c1819bdd3880e74f74657fb812bafb20d511ab7ae36911a567094af27b7b8b8e929d93b65e1b57d6b6f89f2eb68b2571d31328ca8616b8764799e6ba5d2b6ab8eba21ebe59b7571fbf609b7d97accbce1391d44ab40790bfdc678de0aabfd416c2e66a65d4ee9449505d968c66258bc75ec026dc8782f7854d7c5855acdfb545b9b6c16642da3a76959225c5a83096133d3bb2cf7c6899c8caa6de25d6a444e39ec78e686f4aa9d574a3b166b7527804fb9faaa8c852bd1a6bbd7d522b9ba051e850d7bdf0ed71d390b8797797fbc0cfbf9d2afc6d30d99e8c2d6c90f0a2e5b73c01f8fcd4a4b09ddbedc30a7ee8c9dd655752877978da33f508e269944b163a8522a035c41dc4bd71fc53365ee28436c51cd69be9d7afd51209d4a6730b32c627ba3c18e4e9ba51675d92a4ccc8bd3a76f232f189770dfd9e2ec9691e36d0f7dd74a7673cb5577d95b79c9e713499ccc86dd80cd668983a2b785b9b8ee3570a6df72a23149d96943faed06e6f5fe632eba0dbeb977516be4fc436f719885c94e18fc0013616e7efc096dc9cf244dcb7acca7ee03fb3801447ef3fc0dfcfdc9cc81f2d71f305f628a7d18559fd3080c7204865e86f905ef28e8e80248527872c08cd2fba4cf157851e040f10546350e2470157cc0b22403d880f53b2ebddf71e85dd2144d555445334c457917eba2626ab2d8505413e6932e2ab2c6637e07a89c473426870b45a06e878e39fef53f0711fdc676090000" 287 | ], 288 | "rawHeaders": [ 289 | "Date", 290 | "Sat, 01 May 2021 07:19:46 GMT", 291 | "Content-Type", 292 | "application/json", 293 | "Transfer-Encoding", 294 | "chunked", 295 | "Connection", 296 | "keep-alive", 297 | "Set-Cookie", 298 | "__cfduid=d31558479875e4ac0d8ec01a62ba20c581619853586; expires=Mon, 31-May-21 07:19:46 GMT; path=/; domain=.registry.yarnpkg.com; HttpOnly; SameSite=Lax", 299 | "CF-Ray", 300 | "64873e528ebc1d5b-NRT", 301 | "Cache-Control", 302 | "max-age=300", 303 | "Content-Encoding", 304 | "gzip", 305 | "Vary", 306 | "accept-encoding, accept", 307 | "CF-Cache-Status", 308 | "DYNAMIC", 309 | "cf-request-id", 310 | "09c865479600001d5b36856000000001", 311 | "Expect-CT", 312 | "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"", 313 | "Server", 314 | "cloudflare" 315 | ], 316 | "responseIsBinary": false 317 | }, 318 | { 319 | "scope": "https://registry.yarnpkg.com:443", 320 | "method": "GET", 321 | "path": "/@babel/highlight/7.14.0", 322 | "body": "", 323 | "status": 200, 324 | "response": [ 325 | "1f8b08000000000004039d566b93a2c812fd2b865f1de52962c7ce4623f87e838fd1ebbd1d051450020556018a13f3dfb7687bdcded9dd2fd70854b2f271aa32f3647daf6310c3fa4bfdd506368cb800f941c49eacfea55e40425182d962a725c82d9e895c481d82d2ec21b64a9c815bed69539b800258ef0a359a11847d5af312524bf22ccdb31ac2b50c92186110d1167306f22c4808734f73274029aafd16c3d78fff2d27897f673a4112c314f815c220cb52fac271ef405b2e2c38377128073187e12d7b889b4f2ccc36420ec4b4329d8f37ec3dcded08d1404fb087fcfacbf73a701c48295b7f5f71ea3fbed4094c138ab28494954256a695b98faae3c849f409059305b95dc17c44fe80f550751181cec3493d054ec83640ff0690458b01aa8e37423687b00b6fad3365815c9842f6861d0419b8efcfd4c02885a4598008b980396f22a693210fc1ea0cfff7cc91138028ac24628b7f4fda9936b32464475109591e9990c5660768fc1aa8da2fe5fee6a0ca65da0498a2bf7878432e7bffb5705e9f405c44b30a3f0d00cd63a62a09dd0e943aed8e20404fb13d5592a1d2717917404755a1ecc98a20488ec7ce00e10cfa04652c0d957d5b109b074b5f5e6fc5e6d01fcfad21e8aded766818544f52c345db21bda4204b256f198de586385a5be126eeeff678979796abe9edfe5ebf58fbfda6e091ad48e6d9ecb89b9eeb7ffdcaa26580d820fa9c5e027d869e942d9cc667da4a88cffdba51aef967b7341f9b6e65fe9db9f35004f524c76cf732ab1b5c9500742d7467c524abbcf4a5cebc3629f231c872525558b3faf4fac3f1a2b61aae6ad678b8d0365bb3ff2e3f9113de3d7af1a5b664b5c15458a5d40a89e55290aa653d8963560c2fb59f4d9230b5d44f1fd02b8deab9d281d3d3fa3d5dd3d6bdf5c447b7a9ab9b5a77b3a396868f7be06b9a770bd7da98036713ac809549dda87199a3033ae1731c450b6d38484639e779ca398fceb3617f6a8c2fd7707db8148778eb84ab42b455d7e3aebe60eaebf0b6c3b772b30d4e58217cc3b0b5abb92f8a52ca85cec2d7269ebc3d8e948550b6772b63b49548b6e493a376cd8938bb", 326 | "2d70bc5987b94166273c2df5d5801cad4963810ec2cabe1f2f03e8c8c2b789e8c460b55d5aaed009a6e2ce500f055e1d26bd680dedcd5cc7c5ee8485ce1c633d922d71a2b6c54d771022e332f0d4c6d4e92387824cee8823675c4c792b9cdb8ab958e6a616aee2b37c084f7820532d3d224d3f0a432b39daba38dd7cf38c91a340f73a76caf5c62bf51bede5c24ce407637beb8ed482bbcdee3a714fb8982e2d72dd8f6f1699cfa813f891c3773b7c19b961fb1b1daf3661dcbf998ee0b60fc60d5e0673b56b1703d0df4bf3ce099b5129dcbb3d6d2089d8d395705dd206dadcfcc96e35ca4b7d349c699bd5a237b734e40be237651f0674a870f915eb2cb6ba1848cbf87c49d3be339c22c151ad60419582746e474e5dcfcfd6859039df08fbfd46ffecadd3d168aceeb8b1e0de8e27563e67a0d9f0ba8bfda1897afb6da2227d8277cbe9ccdb09a32e84bb7bbaefa6b66fa274325496a3b31d86a1ec9adee8845de00ff4c96c9c4fd258df0adcfa6ccaabbd2a1ff918ddf5424992aeb6eeaaaa434cf56aece2924bf999b11f4e9d9421ef0cb667e3786fc86df1b02ee629bc22a52daf9c4156a46d7fb933bca572d71b5ccfe34819995b6ee08fc0761d89fec664cdb232b9aadebf6e4ccea8febcb7517f61fc4b735574f8c65a724b2b2afdfe732462e42451d224c806b99bb0be868caf2b92782cb43e165efd4a5c4d82775afda0fe07777f707cc6789e3570fde53f4fe7c13df9ec3240af01c4a464d20f4f4fcd28f101f6685c66c1270c9fa47f01f03473018615193d41a7f16bc60ab01a34848d4f06f6a90b6f8cecaa61c2660b8d3f19d9d89705f19f03fc3fc7f38c788e826b8efd4fa1d0eb39c801f65bec3af2e3bf8f8430b223a0ba6c8068cc060261bf557e82a41a2c752ab1db40c5a43fc9baf973d632b7599c3215f6fd2749bf3d48fa4d50d81c123b3cdf1679fe8d6fc98aa24872471615455554a9fb5e0e6c665901bbc284570298278fdd59e08f3f00521ff80d2e090000" 327 | ], 328 | "rawHeaders": [ 329 | "Date", 330 | "Sat, 01 May 2021 07:19:46 GMT", 331 | "Content-Type", 332 | "application/json", 333 | "Transfer-Encoding", 334 | "chunked", 335 | "Connection", 336 | "keep-alive", 337 | "Set-Cookie", 338 | "__cfduid=d8ce18cdd5472317b09b2a416ddcd269c1619853586; expires=Mon, 31-May-21 07:19:46 GMT; path=/; domain=.registry.yarnpkg.com; HttpOnly; SameSite=Lax", 339 | "CF-Ray", 340 | "64873e529c060b93-NRT", 341 | "Content-Encoding", 342 | "gzip", 343 | "Vary", 344 | "Accept-Encoding", 345 | "CF-Cache-Status", 346 | "DYNAMIC", 347 | "cf-request-id", 348 | "09c865479f00000b933a333000000001", 349 | "Expect-CT", 350 | "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"", 351 | "Server", 352 | "cloudflare" 353 | ], 354 | "responseIsBinary": false 355 | }, 356 | { 357 | "scope": "https://registry.yarnpkg.com:443", 358 | "method": "GET", 359 | "path": "/@babel/helper-validator-identifier/7.14.0", 360 | "body": "", 361 | "status": 200, 362 | "response": [ 363 | "1f8b08000000000004039d56e98ea3b8167e9552fea6036187925a2a429622a9aca4c87233d332e080590cb1210969f5bb8fa954d7adab99db339a4880737c569fe5f3f71606196c3db69e3ce0c1948f605a40d239831405a0cc4907051097e88820697d699d21a128c78c5de30499eb325200a94f5051dec9ee5d0e3efc578c4f607dc949401fde2c7d691158e41431dd75ebf17babac8bc67c884aa6ac22295b476559d0479e67b4a8f2383fcff8bb736f6feece1a2002fdbb925601fc048490ded93abf8ae1c797568a7c886963746aaf99d1a2f25244232bc74714362e01df8794b2fdb71dbfc56432809aa8393e451e8f7000af5c4c992cbc1639291bde3f6d05f0dc870564bcd84790b17cff0767dcf1008529c28d77b8c81eff3e2b4f2c135d4e66be3c5518f97900f9f76f4790b82ecbd163eb77812d54c6e2315fa20c90a4218a9cf026e7478034724d14bf77399189b088bfa180fdff67f6df2b01d1b2899246805619130e44d507810e64cd571551573d41098e82226b92600025e87afe51d4445d678e215cc290a092954423af0862c7954aaadda64ea5a44774d9f4ddcd6dd51fd9b3768aadc16b00b661e93e8fc3174f202360aaf194943d63900db417413fe6dbb13dd05f316ff2913a1b1f47cb8287c25836bf7e65d64a403c907e2e350243e63da93976e831e57212f27f1f3adff955bb74ee2dc295e18d993ca2145a7985d90969acce7153b23070d08d655ad07541f8d2e4bb43518841599126ff9de6d71bb0901f16a3c583638f66e6fa753578a31fc801bbf76e7c7c98b332632cac241fce4dce05a9d9b6f22c63bdfbf8f0b39f72c65684c53dbe86a3792e74e8f7cc41cf32cd656f390ed175b2b256a6b176a963e2fd0684a67996f5058fe2829f83899af3936cbde77da95c1e7025f2aad45feaa7eede3ce77cb81f9f24f7228e8549a489a0862758977a6d0481e0b595e9646e2d636aa9a46c6fd1f3019b6a3edb654b3bdd9d50d65ef5dc0befddb69b5e55a2d3f505a8b14cf7b43c8af3f9be306fba4e8709d1f7868c94cbf0804359b1cfd27eaecd2fea3a98585ea18f669b9d1f0e62a3aacde4a42fcf44ac", 364 | "73bb7b356a2b927a6835e195239d460165b6f555548bc1601359db40af7b43d78e2f9339e25f83ade220a1f2aba55d2f6e8a6ac7f130d405bf3c69f6688c82809d9ae404c3f54ed625de22643f9bc63a289df3c25a04b367ea66d05d864bd38ed761e2d3eb44202046e7ab6d78064dbc03de79d679f602c5b1ed4d4e5224acf4859f75678603b4e755a61ce120d6e9f6ba7026b49fb82f6da9aa0d52dd366037d81d70ef589cf0c217d6d2745a9e7afa3547ae6438ed651926db011d808b11efe3d0d9a51359dbf6b3fd2adb3eeb9b67a78dab03b6755ccacadc4a14374eb2a939112ff0b6371c9ef6c64a5cedbc3a85ce68678e4c081caf0ee35b31eaca478432b438e017d1ad648b207d309313cc8ea31eae9e9d4c4c7a5a3c227c7c7552776edafc6e317d7595ab164c361bd95eb6377a211db07833919cc4dd7aa68de5be77e2f55eb6269a153c8fb3dd2e44da4413241f5c4d73282638502d37ab61dbbf85fd6273c028a4d5c908a5b666ebf111ed8783d96eee4f6fa7b32eccdd29df7b0dac494283d0d46709aac8d08ccbaeedf6af7d6ab26eb0a6cba6debff227316f166f6d3498f5ff4f73bdcd40d692af94211f9b6aef30d98cd834ef10e4812ac8596343060dcd24b96f70ef1b4f61436ea0abd1f313abee30f00e27258314d6c0adc7ff7c288f6ef96795117a8a202635a3be6bfae04cf310e023cdea32fae4c327eaff38f02116000c9b69f4e174913d95d48f1a44235c0099b31fbcf0ca266283fd0cd269f649c8639d27887f6de0df1ccf87c5388d2e150e3f99424f7154011c72ec8af2e337064a2c216cd811d05c37406a33d420ecdbe427ca1bf46951895d1c9a49fa73a2777e5e0e98da322b180b7bff6a6e7fbbcfed6f822a189aa81a86c456dfba1c4330addbedca82de95044552df0a84419d131184930b014cf711a414fef803ce051f4454090000" 365 | ], 366 | "rawHeaders": [ 367 | "Date", 368 | "Sat, 01 May 2021 07:19:47 GMT", 369 | "Content-Type", 370 | "application/json", 371 | "Transfer-Encoding", 372 | "chunked", 373 | "Connection", 374 | "keep-alive", 375 | "Set-Cookie", 376 | "__cfduid=d2aa179844073dea8561badcb7ec9b51b1619853586; expires=Mon, 31-May-21 07:19:46 GMT; path=/; domain=.registry.yarnpkg.com; HttpOnly; SameSite=Lax", 377 | "CF-Ray", 378 | "64873e528d030ae4-NRT", 379 | "Content-Encoding", 380 | "gzip", 381 | "Vary", 382 | "Accept-Encoding", 383 | "CF-Cache-Status", 384 | "DYNAMIC", 385 | "cf-request-id", 386 | "09c865479700000ae4ae111000000001", 387 | "Expect-CT", 388 | "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"", 389 | "Server", 390 | "cloudflare" 391 | ], 392 | "responseIsBinary": false 393 | }, 394 | { 395 | "scope": "https://registry.yarnpkg.com:443", 396 | "method": "GET", 397 | "path": "/escape-string-regexp/1.0.5", 398 | "body": "", 399 | "status": 200, 400 | "response": [ 401 | "1f8b08000000000004039d544b6fdb300cfe2b810e3d0c89223bb61307d8d0c30aac8761c0baed520c012d33b6523f04496e9315f9efa3e436cb2140871e6cd37c7d14f951cfac8316d99aa195a071669d515d353358e15eb3297b446355df9143c4054f495392a751da8dda9b1036f98ed5cd5e4fac46a9a099c81a0c4847b114d028899df5185f6f7fd0bf41dd5be57a7360eb67e60eda9b2ae5c8349886e4da396dd7f339e9eaa1e0b26fe75675a541db9b7ab0f38ba51ea70c0657f7c6277d39d35d889adc85304a8f2d280f709eedbaf24a0f72c23f370703e526a7ced1e38fb4be3f219cbbbe0d709c9e027745a764df803a8bda81d6d8b4d05defb1503042ffa6b2bb8a800997a2fbd277ebd347c1575c302a6c1c46303ab48e8cfb7e7275358147f0e6ad6a7ce43da356e09eef2ca3840f7878ea4d19f46333a98a30f2d7af1fbdc1f16f68c090447ca0090432106aa0096949f0ef71ee249d4d9e804a7cfc8c1a09ba936a3c81af6bcd3e90ebbe0f02154983fe8250d26f594471020b8c00302fb33c96c92acf31892195995ce022ce112016145e0c5538f5fb393357d60e54155550f72d6aa87c6fdfc5be29db285fff256a5ebf6ecec6d6608796dca2228ba448b338ca05accaed36035c14452cb722164242b410c52a2b133ae6666b889a6bc6bddce9f6d76921631e253c8a839e68f1cf90f098672fee3f2d9e6fc47fd38e66a73c9b9ed97b8a76600a68ce7799d845f9cc81d3117696f7a6bab8c6f3d945f52cb490bbea8f1f966fc3378d06fc1d04cd6d47170d7d7db1751f5640837ca069da593e7ba2a5e0b4bbc1e5057d5c76d76aea2bbddf80dc44499a89345f44b158261bc19771922e92244f532156c972e96b2a95414977dac8f2e3f12f4701cd0758050000" 402 | ], 403 | "rawHeaders": [ 404 | "Date", 405 | "Sat, 01 May 2021 07:19:47 GMT", 406 | "Content-Type", 407 | "application/json", 408 | "Transfer-Encoding", 409 | "chunked", 410 | "Connection", 411 | "keep-alive", 412 | "Set-Cookie", 413 | "__cfduid=d1d6c2b681da94690be5ba6306e3deff01619853586; expires=Mon, 31-May-21 07:19:46 GMT; path=/; domain=.registry.yarnpkg.com; HttpOnly; SameSite=Lax", 414 | "CF-Ray", 415 | "64873e529edf94f7-NRT", 416 | "Cache-Control", 417 | "max-age=300", 418 | "Content-Encoding", 419 | "gzip", 420 | "Vary", 421 | "accept-encoding, accept", 422 | "CF-Cache-Status", 423 | "DYNAMIC", 424 | "cf-request-id", 425 | "09c86547a3000094f79b146000000001", 426 | "Expect-CT", 427 | "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"", 428 | "Server", 429 | "cloudflare" 430 | ], 431 | "responseIsBinary": false 432 | } 433 | ] -------------------------------------------------------------------------------- /src/__snapshots__/convert.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`convertLockfile convers normal dependencies 1`] = ` 4 | "# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 5 | # yarn lockfile v1 6 | 7 | 8 | call-bind@^1.0.2: 9 | version \\"1.0.2\\" 10 | resolved \\"https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c\\" 11 | integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== 12 | dependencies: 13 | function-bind \\"^1.1.1\\" 14 | get-intrinsic \\"^1.0.2\\" 15 | 16 | has-symbols@^1.0.1: 17 | version \\"1.0.2\\" 18 | resolved \\"https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423\\" 19 | integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== 20 | 21 | is-regex@^1.1.2: 22 | version \\"1.1.2\\" 23 | resolved \\"https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.2.tgz#81c8ebde4db142f2cf1c53fc86d6a45788266251\\" 24 | integrity sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg== 25 | dependencies: 26 | call-bind \\"^1.0.2\\" 27 | has-symbols \\"^1.0.1\\" 28 | " 29 | `; 30 | 31 | exports[`convertLockfile converts confluent dependencies 1`] = ` 32 | "# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 33 | # yarn lockfile v1 34 | 35 | 36 | \\"@babel/code-frame@^7.0.0\\": 37 | version \\"7.12.13\\" 38 | resolved \\"https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658\\" 39 | integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g== 40 | dependencies: 41 | \\"@babel/highlight\\" \\"^7.12.13\\" 42 | 43 | \\"@babel/helper-validator-identifier@^7.14.0\\": 44 | version \\"7.14.0\\" 45 | resolved \\"https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz#d26cad8a47c65286b15df1547319a5d0bcf27288\\" 46 | integrity sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A== 47 | 48 | \\"@babel/highlight@^7.0.0\\", \\"@babel/highlight@^7.12.13\\": 49 | version \\"7.14.0\\" 50 | resolved \\"https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.0.tgz#3197e375711ef6bf834e67d0daec88e4f46113cf\\" 51 | integrity sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg== 52 | dependencies: 53 | \\"@babel/helper-validator-identifier\\" \\"^7.14.0\\" 54 | chalk \\"^2.0.0\\" 55 | js-tokens \\"^4.0.0\\" 56 | 57 | ansi-styles@^3.2.1: 58 | version \\"3.2.1\\" 59 | resolved \\"https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d\\" 60 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 61 | dependencies: 62 | color-convert \\"^1.9.0\\" 63 | 64 | chalk@^2.0.0: 65 | version \\"2.4.2\\" 66 | resolved \\"https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424\\" 67 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 68 | dependencies: 69 | ansi-styles \\"^3.2.1\\" 70 | escape-string-regexp \\"^1.0.5\\" 71 | supports-color \\"^5.3.0\\" 72 | 73 | color-convert@^1.9.0: 74 | version \\"1.9.3\\" 75 | resolved \\"https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8\\" 76 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 77 | dependencies: 78 | color-name \\"1.1.3\\" 79 | 80 | color-name@1.1.3: 81 | version \\"1.1.3\\" 82 | resolved \\"https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25\\" 83 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= 84 | 85 | escape-string-regexp@^1.0.5: 86 | version \\"1.0.5\\" 87 | resolved \\"https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4\\" 88 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 89 | 90 | has-flag@^3.0.0: 91 | version \\"3.0.0\\" 92 | resolved \\"https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd\\" 93 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= 94 | 95 | js-tokens@^4.0.0: 96 | version \\"4.0.0\\" 97 | resolved \\"https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499\\" 98 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 99 | 100 | supports-color@^5.3.0: 101 | version \\"5.5.0\\" 102 | resolved \\"https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f\\" 103 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 104 | dependencies: 105 | has-flag \\"^3.0.0\\" 106 | " 107 | `; 108 | 109 | exports[`convertLockfile falls back to offline inference if fetch failed 1`] = ` 110 | "# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 111 | # yarn lockfile v1 112 | 113 | 114 | call-bind@^1.0.2: 115 | version \\"1.0.2\\" 116 | resolved \\"https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c\\" 117 | integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== 118 | dependencies: 119 | function-bind \\"^1.1.1\\" 120 | get-intrinsic \\"^1.0.2\\" 121 | 122 | has-symbols@^1.0.1: 123 | version \\"1.0.2\\" 124 | resolved \\"https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423\\" 125 | integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== 126 | 127 | is-regex@^1.1.2: 128 | version \\"1.1.2\\" 129 | resolved \\"https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.2.tgz\\" 130 | dependencies: 131 | call-bind \\"^1.0.2\\" 132 | has-symbols \\"^1.0.1\\" 133 | " 134 | `; 135 | 136 | exports[`convertLockfile sends Bearer token when requested 1`] = ` 137 | "# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 138 | # yarn lockfile v1 139 | 140 | 141 | call-bind@^1.0.2: 142 | version \\"1.0.2\\" 143 | resolved \\"https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c\\" 144 | integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== 145 | dependencies: 146 | function-bind \\"^1.1.1\\" 147 | get-intrinsic \\"^1.0.2\\" 148 | 149 | has-symbols@^1.0.1: 150 | version \\"1.0.2\\" 151 | resolved \\"https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423\\" 152 | integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== 153 | 154 | is-regex@^1.1.2: 155 | version \\"1.1.2\\" 156 | resolved \\"https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.2.tgz#81c8ebde4db142f2cf1c53fc86d6a45788266251\\" 157 | integrity sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg== 158 | dependencies: 159 | call-bind \\"^1.0.2\\" 160 | has-symbols \\"^1.0.1\\" 161 | " 162 | `; 163 | -------------------------------------------------------------------------------- /src/__snapshots__/stringify.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`stringify doesn't unify equivalent objects 1`] = ` 4 | "foo: 5 | bar: 6 | something 42 7 | foo: 8 | something 42 9 | " 10 | `; 11 | 12 | exports[`stringify doesn't unify same primitives 1`] = ` 13 | "foo: 14 | bar 42 15 | foo 42 16 | " 17 | `; 18 | 19 | exports[`stringify stringifies an empty object 1`] = `""`; 20 | 21 | exports[`stringify stringifies an object with a single key 1`] = ` 22 | "foo: 23 | " 24 | `; 25 | 26 | exports[`stringify stringifies package info 1`] = ` 27 | "call-bind@^1.0.2: 28 | version \\"1.0.2\\" 29 | resolved \\"https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c\\" 30 | integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== 31 | dependencies: 32 | function-bind \\"^1.1.1\\" 33 | get-intrinsic \\"^1.0.2\\" 34 | 35 | has-symbols@^1.0.1: 36 | version \\"1.0.2\\" 37 | resolved \\"https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423\\" 38 | integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== 39 | 40 | is-regex@^1.1.2: 41 | version \\"1.1.2\\" 42 | resolved \\"https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.2.tgz#81c8ebde4db142f2cf1c53fc86d6a45788266251\\" 43 | integrity sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg== 44 | dependencies: 45 | call-bind \\"^1.0.2\\" 46 | has-symbols \\"^1.0.1\\" 47 | " 48 | `; 49 | 50 | exports[`stringify stringifies simple values 1`] = ` 51 | "foo: 52 | boolean false 53 | numeric 42 54 | s baz 55 | s2 \\"baz baz\\" 56 | sboolean \\"true\\" 57 | snumeric \\"42\\" 58 | " 59 | `; 60 | 61 | exports[`stringify unifies identical objects 1`] = ` 62 | "foo: 63 | bar, foo: 64 | something 42 65 | " 66 | `; 67 | 68 | exports[`stringify unifies identical toplevel objects 1`] = ` 69 | "foo@^0.1.0, foo@^0.1.1: 70 | version \\"0.1.2\\" 71 | 72 | foo@^0.2.0: 73 | version \\"0.2.0\\" 74 | " 75 | `; 76 | -------------------------------------------------------------------------------- /src/convert.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it, jest } from "@jest/globals"; 2 | import fs from "fs"; 3 | import path from "path"; 4 | import { setupRecorder } from "nock-record"; 5 | import nodeFetch, { Headers, Response } from "node-fetch"; 6 | 7 | import { convertLockfile, Fetcher } from "./convert"; 8 | 9 | const record = setupRecorder({ 10 | mode: process.env.NOCK_BACK_MODE === "record" ? "record" : "lockdown", 11 | }); 12 | 13 | describe("convertLockfile", () => { 14 | it("convers normal dependencies", async () => { 15 | const { completeRecording, assertScopesFinished } = await record( 16 | "yarn-lock1" 17 | ); 18 | 19 | const lockV2 = fs.readFileSync( 20 | path.resolve(__dirname, "./__fixtures__/yarn-lock1.txt"), 21 | "utf-8" 22 | ); 23 | const lockV1 = await convertLockfile(lockV2); 24 | expect(lockV1).toMatchSnapshot(); 25 | 26 | completeRecording(); 27 | assertScopesFinished(); 28 | }); 29 | 30 | it("converts confluent dependencies", async () => { 31 | const { completeRecording, assertScopesFinished } = await record( 32 | "yarn-lock2" 33 | ); 34 | 35 | const lockV2 = fs.readFileSync( 36 | path.resolve(__dirname, "./__fixtures__/yarn-lock2.txt"), 37 | "utf-8" 38 | ); 39 | const lockV1 = await convertLockfile(lockV2); 40 | expect(lockV1).toMatchSnapshot(); 41 | 42 | completeRecording(); 43 | assertScopesFinished(); 44 | }); 45 | 46 | it("falls back to offline inference if fetch failed", async () => { 47 | const fetch: Fetcher = async (url) => { 48 | if (/is-regex\/1\.1\.2/.test(url)) { 49 | return new Response("", { status: 503, url }); 50 | } else { 51 | return nodeFetch(url); 52 | } 53 | }; 54 | const interaction = { 55 | warn: jest.fn(), 56 | }; 57 | const { completeRecording, assertScopesFinished } = await record( 58 | "yarn-lock1-offline" 59 | ); 60 | 61 | const lockV2 = fs.readFileSync( 62 | path.resolve(__dirname, "./__fixtures__/yarn-lock1.txt"), 63 | "utf-8" 64 | ); 65 | const lockV1 = await convertLockfile(lockV2, { fetch, interaction }); 66 | expect(lockV1).toMatchSnapshot(); 67 | 68 | completeRecording(); 69 | assertScopesFinished(); 70 | 71 | expect(interaction.warn.mock.calls).toEqual([ 72 | [ 73 | "Error reading is-regex/1.1.2: Got 503 from https://registry.yarnpkg.com/is-regex/1.1.2", 74 | ], 75 | ]); 76 | }); 77 | 78 | it("sends Bearer token when requested", async () => { 79 | const token = "8dd79e01-d0a4-446b-b261-d6d6408227d2"; 80 | const fetch: Fetcher = async (url, init) => { 81 | const { headers = new Headers() } = init ?? {}; 82 | if (/is-regex\/1\.1\.2/.test(url)) { 83 | if (headers.get("Authorization") === `Bearer ${token}`) { 84 | return nodeFetch(url); 85 | } else { 86 | return new Response("", { 87 | status: headers.get("Authorization") ? 403 : 401, 88 | url, 89 | }); 90 | } 91 | } else { 92 | return nodeFetch(url); 93 | } 94 | }; 95 | const interaction = { 96 | warn: jest.fn(), 97 | }; 98 | const { completeRecording, assertScopesFinished } = await record( 99 | "yarn-lock1" 100 | ); 101 | 102 | const lockV2 = fs.readFileSync( 103 | path.resolve(__dirname, "./__fixtures__/yarn-lock1.txt"), 104 | "utf-8" 105 | ); 106 | const lockV1 = await convertLockfile(lockV2, { 107 | fetch, 108 | interaction, 109 | yarnrc: { npmAuthToken: token }, 110 | }); 111 | expect(lockV1).toMatchSnapshot(); 112 | 113 | completeRecording(); 114 | assertScopesFinished(); 115 | 116 | expect(interaction.warn.mock.calls).toEqual([]); 117 | }); 118 | }); 119 | -------------------------------------------------------------------------------- /src/convert.ts: -------------------------------------------------------------------------------- 1 | import yaml from "js-yaml"; 2 | import https from "https"; 3 | import nodeFetch, { Headers, Response } from "node-fetch"; 4 | 5 | import { stringify } from "./stringify"; 6 | import { V1LockfileObject, V1LockManifest } from "./v1lock"; 7 | import { 8 | assertLockfileShallow, 9 | assertManifest, 10 | V2Dependencies, 11 | V2DependenciesMeta, 12 | } from "./v2lock"; 13 | import { assertPackageInfo } from "./package-info"; 14 | 15 | export interface Interaction { 16 | warn(msg: string): void; 17 | } 18 | 19 | const defaultInteraction: Interaction = { 20 | warn(msg) { 21 | console.warn(msg); 22 | }, 23 | }; 24 | 25 | interface Options { 26 | yarnrc?: YarnRc; 27 | fetch?: Fetcher; 28 | interaction?: Interaction; 29 | } 30 | export type Fetcher = ( 31 | url: string, 32 | init?: { headers?: Headers } 33 | ) => Promise; 34 | 35 | export interface YarnRc { 36 | npmAlwaysAuth?: boolean; 37 | npmAuthIdent?: string; 38 | npmAuthToken?: string; 39 | npmRegistries?: Record; 40 | } 41 | 42 | export interface RegistryConfig { 43 | npmAlwaysAuth?: boolean; 44 | npmAuthIdent?: string; 45 | npmAuthToken?: string; 46 | } 47 | 48 | export async function convertLockfile( 49 | lockV2: string, 50 | options: Options = {} 51 | ): Promise { 52 | let cleanup: () => void = () => { 53 | /* do nothing */ 54 | }; 55 | let fetch: Fetcher; 56 | if (options.fetch) { 57 | fetch = options.fetch; 58 | } else { 59 | const agent = new https.Agent({ keepAlive: true, maxTotalSockets: 10 }); 60 | fetch = (url, init = {}) => nodeFetch(url, { ...init, agent }); 61 | cleanup = () => { 62 | agent.destroy(); 63 | }; 64 | } 65 | const result = await convertLockfileInner(lockV2, fetch, options); 66 | cleanup(); 67 | return result; 68 | } 69 | 70 | async function convertLockfileInner( 71 | lockV2: string, 72 | fetch: Fetcher, 73 | options: Options = {} 74 | ): Promise { 75 | const { yarnrc = {}, interaction = defaultInteraction } = options; 76 | const lockV2Obj: unknown = yaml.load(lockV2); 77 | const lockV1Obj: V1LockfileObject = {}; 78 | 79 | assertLockfileShallow(lockV2Obj); 80 | 81 | const clausePromises = Object.entries(lockV2Obj).map( 82 | async ([packageKey, packageData]) => { 83 | if (packageKey === "__metadata") return; 84 | if (/@(?:patch|workspace):/.test(packageKey)) return; 85 | 86 | await convertEntry( 87 | lockV1Obj, 88 | packageKey, 89 | packageData, 90 | yarnrc, 91 | fetch, 92 | interaction 93 | ); 94 | } 95 | ); 96 | 97 | await Promise.all(clausePromises); 98 | 99 | return ( 100 | "# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n" + 101 | "# yarn lockfile v1\n" + 102 | "\n" + 103 | "\n" + 104 | stringify(lockV1Obj) 105 | ); 106 | } 107 | 108 | async function convertEntry( 109 | lockV1: V1LockfileObject, 110 | keyV2: string, 111 | manifestV2: unknown, 112 | yarnrc: YarnRc, 113 | fetch: Fetcher, 114 | interaction: Interaction 115 | ): Promise { 116 | const manifestV1 = await convertManifest( 117 | manifestV2, 118 | yarnrc, 119 | fetch, 120 | interaction 121 | ); 122 | 123 | for (const k of keyV2.split(", ")) { 124 | lockV1[k.replace("@npm:", "@")] = manifestV1; 125 | } 126 | } 127 | 128 | async function convertManifest( 129 | manifestV2: unknown, 130 | yarnrc: YarnRc, 131 | fetch: Fetcher, 132 | interaction: Interaction 133 | ): Promise { 134 | assertManifest(manifestV2); 135 | const manifest: V1LockManifest = { 136 | version: manifestV2.version, 137 | }; 138 | convertDependencies( 139 | manifestV2.dependencies, 140 | manifestV2.dependenciesMeta, 141 | manifest 142 | ); 143 | if (manifestV2.resolution) 144 | await convertResolution( 145 | manifestV2.resolution, 146 | manifest, 147 | yarnrc, 148 | fetch, 149 | interaction 150 | ); 151 | return manifest; 152 | } 153 | 154 | function convertDependencies( 155 | dependencies: V2Dependencies = {}, 156 | dependenciesMeta: V2DependenciesMeta = {}, 157 | manifestV1: V1LockManifest 158 | ) { 159 | const isOptional = (pkg: string) => 160 | Boolean( 161 | Object.prototype.hasOwnProperty.call(dependenciesMeta, pkg) && 162 | dependenciesMeta[pkg]?.optional 163 | ); 164 | 165 | for (const [depKey, depValue] of Object.entries(dependencies)) { 166 | const depListType = isOptional(depKey) 167 | ? "optionalDependencies" 168 | : "dependencies"; 169 | const depList = (manifestV1[depListType] ||= {}); 170 | depList[depKey] = String(depValue); 171 | } 172 | } 173 | 174 | async function convertResolution( 175 | resolutionV2: string, 176 | manifestV1: V1LockManifest, 177 | yarnrc: YarnRc, 178 | fetch: Fetcher, 179 | interaction: Interaction 180 | ): Promise { 181 | const [packageName, packageResolution] = resolutionV2.split(/(?!^@)@/, 2); 182 | const packageBaseName = packageName.split("/").reverse()[0]; 183 | const [protocol, protocolValue] = packageResolution.split(":", 2); 184 | switch (protocol) { 185 | case "npm": { 186 | const version = protocolValue; 187 | let anchor = ""; 188 | try { 189 | const packageInfo = await requestRegistry( 190 | `https://registry.yarnpkg.com/${packageName}/${version}`, 191 | yarnrc, 192 | fetch 193 | ); 194 | assertPackageInfo(packageInfo); 195 | if (packageInfo.dist?.shasum) anchor = `#${packageInfo.dist.shasum}`; 196 | manifestV1.integrity = packageInfo.dist?.integrity; 197 | if (!manifestV1.integrity && packageInfo.dist?.shasum) { 198 | const bytes = Array.from( 199 | packageInfo.dist.shasum.matchAll(/[0-9a-f]{2}/gi) 200 | ).map(([text]) => parseInt(text, 16)); 201 | manifestV1.integrity = `sha1-${Buffer.from(bytes).toString( 202 | "base64" 203 | )}`; 204 | } 205 | } catch (e) { 206 | interaction.warn( 207 | `Error reading ${packageName}/${version}: ${ 208 | e instanceof Error ? e.message : "" 209 | }` 210 | ); 211 | } 212 | manifestV1.resolved = `https://registry.yarnpkg.com/${packageName}/-/${packageBaseName}-${version}.tgz${anchor}`; 213 | break; 214 | } 215 | default: 216 | throw new Error(`unknown package protocol: ${JSON.stringify(protocol)}`); 217 | } 218 | } 219 | 220 | async function requestRegistry( 221 | url: string, 222 | yarnrc: YarnRc, 223 | fetch: Fetcher 224 | ): Promise { 225 | let registryConfig: RegistryConfig = yarnrc; 226 | const { npmRegistries = {} } = yarnrc; 227 | for (const [regMatcher, regConfig] of Object.entries(npmRegistries)) { 228 | if (!regMatcher.startsWith("//")) continue; 229 | if ( 230 | url.startsWith(`https:${regMatcher}`) || 231 | url.startsWith(`http:${regMatcher}`) 232 | ) { 233 | registryConfig = regConfig; 234 | break; 235 | } 236 | } 237 | // TODO: replace env vars 238 | const { npmAlwaysAuth, npmAuthIdent, npmAuthToken } = registryConfig; 239 | const hasAuth = Boolean(npmAuthIdent || npmAuthToken); 240 | if (!npmAlwaysAuth || !hasAuth) { 241 | const resp = await fetch(url); 242 | if (resp.ok) { 243 | // eslint-disable-next-line @typescript-eslint/no-unsafe-return 244 | return await resp.json(); 245 | } else if (!hasAuth || resp.status !== 401) { 246 | throw new Error(`Got ${resp.status} from ${resp.url}`); 247 | } 248 | } 249 | if (npmAuthIdent) { 250 | const resp = await fetch(url, { 251 | headers: new Headers({ 252 | Authorization: `Basic ${Buffer.from(evalEnv(npmAuthIdent)).toString( 253 | "base64" 254 | )}`, 255 | }), 256 | }); 257 | if (!resp.ok) { 258 | throw new Error(`Got ${resp.status} from ${resp.url}`); 259 | } 260 | // eslint-disable-next-line @typescript-eslint/no-unsafe-return 261 | return await resp.json(); 262 | } else { 263 | const resp = await fetch(url, { 264 | headers: new Headers({ 265 | Authorization: `Bearer ${evalEnv(npmAuthToken ?? "")}`, 266 | }), 267 | }); 268 | if (!resp.ok) { 269 | throw new Error(`Got ${resp.status} from ${resp.url}`); 270 | } 271 | // eslint-disable-next-line @typescript-eslint/no-unsafe-return 272 | return await resp.json(); 273 | } 274 | } 275 | 276 | function evalEnv(s: string): string { 277 | return s.replaceAll(/\$\{([\w_][\w\d_]*)(:?-[^}]*)?\}/g, (...args) => { 278 | const [_match, name, fallback, _offset, _string] = args as [ 279 | string, 280 | string, 281 | string | undefined, 282 | number, 283 | string 284 | ]; 285 | const value = Object.prototype.hasOwnProperty.call(process.env, name) 286 | ? process.env[name] 287 | : undefined; 288 | if (value && (value !== "" || !fallback || !fallback.startsWith(":-"))) 289 | return value; 290 | if (!fallback) { 291 | throw new Error(`${name} is not defined`); 292 | } else if (fallback.startsWith(":-")) { 293 | return fallback.substring(2); 294 | } else { 295 | return fallback.substring(1); 296 | } 297 | }); 298 | } 299 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import process from "process"; 3 | import yargs from "yargs"; 4 | import yaml from "js-yaml"; 5 | import { convertLockfile, YarnRc } from "./convert"; 6 | 7 | const V1_HEADER = 8 | "# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n# yarn lockfile v1\n"; 9 | 10 | (async () => { 11 | const { 12 | f: inputPath, 13 | o: outputPath, 14 | c: yarnrcPath, 15 | } = await yargs 16 | .scriptName("yarn-lock-v1") 17 | .option("f", { 18 | alias: "file", 19 | describe: "input yarn.lock file (v2)", 20 | default: "yarn.lock", 21 | type: "string", 22 | }) 23 | .option("o", { 24 | alias: "output", 25 | describe: "output yarn.lock file (v1)", 26 | default: "yarn.lock", 27 | type: "string", 28 | }) 29 | .option("c", { 30 | alias: "yarnrc", 31 | describe: "path to .yarnrc.yml", 32 | default: ".yarnrc.yml", 33 | type: "string", 34 | }) 35 | .strict() 36 | .help().argv; 37 | 38 | let yarnrc: YarnRc | undefined = undefined; 39 | if (fs.existsSync(yarnrcPath)) { 40 | yarnrc = yaml.load( 41 | await fs.promises.readFile(yarnrcPath, "utf-8") 42 | ) as YarnRc; 43 | } 44 | const lockV2 = await fs.promises.readFile(inputPath, "utf-8"); 45 | if (lockV2.startsWith(V1_HEADER)) { 46 | throw new Error("yarn.lock is already v1"); 47 | } 48 | const lockV1 = await convertLockfile(lockV2, { yarnrc }); 49 | if (fs.existsSync(outputPath)) { 50 | await fs.promises.copyFile(outputPath, `${outputPath}.bak`); 51 | } 52 | await fs.promises.writeFile(outputPath, lockV1); 53 | })().catch((e) => { 54 | console.error(e); 55 | process.exit(1); 56 | }); 57 | -------------------------------------------------------------------------------- /src/package-info.ts: -------------------------------------------------------------------------------- 1 | import { assertObject, assertString } from "./validation"; 2 | 3 | export type PackageInfo = { 4 | dist?: PackageDist; 5 | }; 6 | 7 | export type PackageDist = { 8 | shasum?: string; 9 | integrity?: string; 10 | }; 11 | 12 | export function assertPackageInfo(obj: unknown): asserts obj is PackageInfo { 13 | assertObject(obj, "package"); 14 | if (obj.dist !== undefined) assertPackageDist(obj.dist); 15 | } 16 | 17 | function assertPackageDist(obj: unknown): asserts obj is PackageDist { 18 | assertObject(obj, "package.dist"); 19 | if (obj.shasum !== undefined) assertString(obj.shasum, "package.dist.shasum"); 20 | if (obj.integrity !== undefined) 21 | assertString(obj.integrity, "package.dist.integrity"); 22 | } 23 | -------------------------------------------------------------------------------- /src/stringify.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from "@jest/globals"; 2 | 3 | import { sortWithPriority, stringify, wrapKey } from "./stringify"; 4 | 5 | describe("stringify", () => { 6 | it("stringifies an empty object", () => { 7 | const s = stringify({}); 8 | expect(s).toMatchSnapshot(); 9 | }); 10 | 11 | it("stringifies an object with a single key", () => { 12 | const s = stringify({ 13 | foo: {}, 14 | }); 15 | expect(s).toMatchSnapshot(); 16 | }); 17 | 18 | it("stringifies simple values", () => { 19 | const s = stringify({ 20 | foo: { 21 | numeric: 42, 22 | snumeric: "42", 23 | boolean: false, 24 | sboolean: "true", 25 | s: "baz", 26 | s2: "baz baz", 27 | }, 28 | }); 29 | expect(s).toMatchSnapshot(); 30 | }); 31 | 32 | it("stringifies package info", () => { 33 | const s = stringify({ 34 | "call-bind@^1.0.2": { 35 | version: "1.0.2", 36 | resolved: 37 | "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c", 38 | integrity: 39 | "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 40 | dependencies: { 41 | "function-bind": "^1.1.1", 42 | "get-intrinsic": "^1.0.2", 43 | }, 44 | }, 45 | "has-symbols@^1.0.1": { 46 | version: "1.0.2", 47 | resolved: 48 | "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423", 49 | integrity: 50 | "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", 51 | }, 52 | "is-regex@^1.1.2": { 53 | version: "1.1.2", 54 | resolved: 55 | "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.2.tgz#81c8ebde4db142f2cf1c53fc86d6a45788266251", 56 | integrity: 57 | "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", 58 | dependencies: { 59 | "call-bind": "^1.0.2", 60 | "has-symbols": "^1.0.1", 61 | }, 62 | }, 63 | }); 64 | expect(s).toMatchSnapshot(); 65 | }); 66 | 67 | it("doesn't unify same primitives", () => { 68 | const s = stringify({ 69 | foo: { 70 | foo: 42, 71 | bar: 42, 72 | }, 73 | }); 74 | expect(s).toMatchSnapshot(); 75 | }); 76 | 77 | it("doesn't unify equivalent objects", () => { 78 | const s = stringify({ 79 | foo: { 80 | foo: { something: 42 }, 81 | bar: { something: 42 }, 82 | }, 83 | }); 84 | expect(s).toMatchSnapshot(); 85 | }); 86 | 87 | it("unifies identical objects", () => { 88 | const obj = { something: 42 }; 89 | const s = stringify({ 90 | foo: { 91 | foo: obj, 92 | bar: obj, 93 | }, 94 | }); 95 | expect(s).toMatchSnapshot(); 96 | }); 97 | 98 | it("unifies identical toplevel objects", () => { 99 | const obj = { 100 | version: "0.1.2", 101 | }; 102 | const s = stringify({ 103 | "foo@^0.1.0": obj, 104 | "foo@^0.1.1": obj, 105 | "foo@^0.2.0": { 106 | version: "0.2.0", 107 | }, 108 | }); 109 | expect(s).toMatchSnapshot(); 110 | }); 111 | }); 112 | 113 | describe("wrapKey", () => { 114 | it("wraps key conditionally", () => { 115 | const src: (string | number | boolean)[] = [ 116 | 1234, 117 | "1234", 118 | "foo", 119 | "@babel/core", 120 | "webpack@^4.46.0", 121 | "webpack@4.x || 5.x", 122 | "https://example.com/", 123 | true, 124 | "true", 125 | "trues", 126 | "atrue", 127 | false, 128 | "false", 129 | "falsey", 130 | "afalse", 131 | "a\nb", 132 | "foo[bar]", 133 | "a\\b", 134 | ]; 135 | const wrapped = src.map((k) => [k, wrapKey(k)] as const); 136 | expect(wrapped).toEqual([ 137 | [1234, "1234"], 138 | ["1234", '"1234"'], 139 | ["foo", "foo"], 140 | ["@babel/core", '"@babel/core"'], 141 | ["webpack@^4.46.0", "webpack@^4.46.0"], 142 | ["webpack@4.x || 5.x", '"webpack@4.x || 5.x"'], 143 | ["https://example.com/", '"https://example.com/"'], 144 | [true, "true"], 145 | ["true", '"true"'], 146 | ["trues", '"trues"'], 147 | ["atrue", "atrue"], 148 | [false, "false"], 149 | ["false", '"false"'], 150 | ["falsey", '"falsey"'], 151 | ["afalse", "afalse"], 152 | ["a\nb", '"a\\nb"'], 153 | ["foo[bar]", '"foo[bar]"'], 154 | ["a\\b", '"a\\\\b"'], 155 | ]); 156 | }); 157 | }); 158 | 159 | describe("cmpAlpha", () => { 160 | it("Sorts strings alphabetically", () => { 161 | const sorted = sortWithPriority([ 162 | "foo", 163 | "name", 164 | "ばー", 165 | "valueOf", 166 | "uid", 167 | "registry", 168 | "баз", 169 | "version", 170 | "dependencies", 171 | "hasOwnProperty", 172 | "resolved", 173 | "isPrototypeOf", 174 | "integrity", 175 | ]); 176 | expect(sorted).toEqual([ 177 | "name", 178 | "version", 179 | "uid", 180 | "resolved", 181 | "integrity", 182 | "registry", 183 | "dependencies", 184 | "foo", 185 | "hasOwnProperty", 186 | "isPrototypeOf", 187 | "valueOf", 188 | "баз", 189 | "ばー", 190 | ]); 191 | }); 192 | }); 193 | -------------------------------------------------------------------------------- /src/stringify.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/ban-types */ 2 | // Based on https://github.com/yarnpkg/yarn/blob/v1.22.10/src/lockfile/stringify.js 3 | 4 | const INDENT = " "; 5 | 6 | export function stringify(obj: object): string { 7 | const lines: string[] = []; 8 | stringifyPush(obj, "", true, lines); 9 | return lines.join(""); 10 | } 11 | 12 | function stringifyPush( 13 | obj: object, 14 | indent: string, 15 | topLevel: boolean, 16 | lines: string[] 17 | ) { 18 | const identicalKeys = new Map(); 19 | for (const [k, v] of Object.entries(obj)) { 20 | if (typeof v === "object" && v !== null) { 21 | const keys = identicalKeys.get(v); 22 | if (keys) keys.push(k); 23 | else identicalKeys.set(v, [k]); 24 | } 25 | } 26 | 27 | let isFirst = true; 28 | const addSeparator = () => { 29 | if (!isFirst && topLevel) { 30 | lines.push("\n"); 31 | } 32 | isFirst = false; 33 | }; 34 | for (const [primaryKey, v] of sortEntriesWithPriority( 35 | Object.entries(obj) 36 | )) { 37 | switch (typeof v) { 38 | case "boolean": 39 | case "number": 40 | case "string": 41 | addSeparator(); 42 | lines.push(`${indent}${wrapKey(primaryKey)} ${wrapKey(v)}\n`); 43 | continue; 44 | case "function": 45 | case "object": 46 | if (v === null) continue; 47 | break; 48 | case "undefined": 49 | continue; 50 | default: 51 | // symbol or bigint 52 | throw new Error(`Cannot stringify ${typeof v}`); 53 | } 54 | 55 | const keys = identicalKeys.get(v); 56 | if (keys === undefined) continue; 57 | identicalKeys.delete(v); 58 | 59 | const joinedKeys = keys.sort().map(wrapKey).join(", "); 60 | addSeparator(); 61 | lines.push(`${indent}${joinedKeys}:\n`); 62 | stringifyPush(v, indent + INDENT, false, lines); 63 | } 64 | } 65 | 66 | function shouldWrapKey(s: string): boolean { 67 | return /^true|^false|^[0-9]|[:\s\n\\",[\]]/.test(s) || !/^[a-zA-Z]/.test(s); 68 | } 69 | 70 | export function wrapKey(s: string | boolean | number): string { 71 | if (typeof s === "boolean" || typeof s === "number" || shouldWrapKey(s)) { 72 | return JSON.stringify(s); 73 | } else { 74 | return s; 75 | } 76 | } 77 | 78 | const priorities: Readonly> = { 79 | name: 1, 80 | version: 2, 81 | uid: 3, 82 | resolved: 4, 83 | integrity: 5, 84 | registry: 6, 85 | dependencies: 7, 86 | }; 87 | 88 | export function sortEntriesWithPriority(keys: [string, T][]): [string, T][] { 89 | return keys.sort(([ak], [bk]) => cmpWithPriority(ak, bk)); 90 | } 91 | 92 | export function sortWithPriority(keys: string[]): string[] { 93 | return keys.sort(cmpWithPriority); 94 | } 95 | 96 | function cmpWithPriority(a: string, b: string): number { 97 | const ap = Object.prototype.hasOwnProperty.call(priorities, a) 98 | ? priorities[a] 99 | : 100; 100 | const bp = Object.prototype.hasOwnProperty.call(priorities, b) 101 | ? priorities[b] 102 | : 100; 103 | if (ap !== bp) return ap - bp; 104 | return cmpAlpha(a, b); 105 | } 106 | 107 | // UCS-2 (UTF-16) lexcographical ordering 108 | function cmpAlpha(a: string, b: string): number { 109 | const minLen = Math.min(a.length, b.length); 110 | for (let i = 0; i < minLen; ++i) { 111 | const ai = a.charCodeAt(i); 112 | const bi = b.charCodeAt(i); 113 | if (ai !== bi) return ai - bi; 114 | } 115 | return a.length - b.length; 116 | } 117 | -------------------------------------------------------------------------------- /src/v1lock.ts: -------------------------------------------------------------------------------- 1 | // https://github.com/yarnpkg/yarn/blob/v1.22.10/src/lockfile/index.js 2 | 3 | export type V1LockfileObject = Record; 4 | 5 | export type V1LockManifest = { 6 | name?: string; 7 | version: string; 8 | resolved?: string; 9 | integrity?: string; 10 | registry?: "npm" | "yarn"; 11 | uid?: string; 12 | permissions?: Record; 13 | optionalDependencies?: V1Dependencies; 14 | dependencies?: V1Dependencies; 15 | }; 16 | 17 | export type V1Dependencies = Record; 18 | -------------------------------------------------------------------------------- /src/v2lock.ts: -------------------------------------------------------------------------------- 1 | import { 2 | assertObject, 3 | assertNumber, 4 | assertString, 5 | assertBoolean, 6 | } from "./validation"; 7 | 8 | export type V2LockfileObject = { 9 | __metadata: V2Metadata; 10 | [key: string]: M | V2Metadata; 11 | }; 12 | 13 | export type V2Metadata = { 14 | version: number; 15 | cacheKey: number; 16 | }; 17 | 18 | export type V2LockManifest = { 19 | version: string; 20 | name?: string; 21 | resolution?: string; 22 | dependencies?: V2Dependencies; 23 | dependenciesMeta?: V2DependenciesMeta; 24 | }; 25 | 26 | export type V2Dependencies = Record; 27 | 28 | export type V2DependenciesMeta = Record; 29 | 30 | export type V2DependencyMeta = { 31 | optional?: boolean; 32 | }; 33 | 34 | export function assertLockfileShallow( 35 | obj: unknown 36 | ): asserts obj is V2LockfileObject { 37 | assertObject(obj, "lockfile"); 38 | assertMetadata(obj.__metadata, "__metadata"); 39 | } 40 | 41 | export function assertMetadata( 42 | obj: unknown, 43 | path: string 44 | ): asserts obj is V2Metadata { 45 | assertObject(obj, path); 46 | assertNumber(obj.version, `${path}.version`); 47 | assertNumber(obj.cacheKey, `${path}.version`); 48 | } 49 | 50 | export function assertManifest(obj: unknown): asserts obj is V2LockManifest { 51 | assertObject(obj, "package"); 52 | assertString(obj.version, "package.version"); 53 | if (obj.name !== undefined) assertString(obj.name, "package.name"); 54 | if (obj.resolution !== undefined) 55 | assertString(obj.resolution, "package.resolution"); 56 | if (obj.dependencies !== undefined) 57 | assertDependencies(obj.dependencies, "package.dependencies"); 58 | if (obj.dependenciesMeta !== undefined) 59 | assertDependenciesMeta(obj.dependenciesMeta, "package.dependenciesMeta"); 60 | } 61 | 62 | function assertDependencies( 63 | obj: unknown, 64 | path: string 65 | ): asserts obj is V2Dependencies { 66 | assertObject(obj, path); 67 | for (const [k, v] of Object.entries(obj)) { 68 | assertString(v, `${path}[${JSON.stringify(k)}]`); 69 | } 70 | } 71 | 72 | function assertDependenciesMeta( 73 | obj: unknown, 74 | path: string 75 | ): asserts obj is V2DependenciesMeta { 76 | assertObject(obj, path); 77 | for (const [k, v] of Object.entries(obj)) { 78 | assertDependencyMeta(v, `${path}[${JSON.stringify(k)}]`); 79 | } 80 | } 81 | 82 | function assertDependencyMeta( 83 | obj: unknown, 84 | path: string 85 | ): asserts obj is V2DependencyMeta { 86 | assertObject(obj, path); 87 | if (obj.optional !== undefined) 88 | assertBoolean(obj.optional, `${path}.optional`); 89 | } 90 | -------------------------------------------------------------------------------- /src/validation.ts: -------------------------------------------------------------------------------- 1 | export function assertObject( 2 | obj: unknown, 3 | path: string 4 | ): asserts obj is Record { 5 | if (typeof obj !== "object" || obj === null || Array.isArray(obj)) { 6 | throw new Error( 7 | `Invalid ${path}: expected object, got ${detailedTypeOf(obj)}` 8 | ); 9 | } 10 | } 11 | 12 | export function assertNumber( 13 | obj: unknown, 14 | path: string 15 | ): asserts obj is number { 16 | if (typeof obj !== "number") { 17 | throw new Error( 18 | `Invalid ${path}: expected number, got ${detailedTypeOf(obj)}` 19 | ); 20 | } 21 | } 22 | 23 | export function assertString( 24 | obj: unknown, 25 | path: string 26 | ): asserts obj is string { 27 | if (typeof obj !== "string") { 28 | throw new Error( 29 | `Invalid ${path}: expected string, got ${detailedTypeOf(obj)}` 30 | ); 31 | } 32 | } 33 | 34 | export function assertBoolean( 35 | obj: unknown, 36 | path: string 37 | ): asserts obj is boolean { 38 | if (typeof obj !== "boolean") { 39 | throw new Error( 40 | `Invalid ${path}: expected boolean, got ${detailedTypeOf(obj)}` 41 | ); 42 | } 43 | } 44 | 45 | export function detailedTypeOf(obj: unknown): string { 46 | if (Array.isArray(obj)) return "array"; 47 | else if (obj === null) return "null"; 48 | else return typeof obj; 49 | } 50 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "rootDir": "./src", 6 | "noEmit": false, 7 | "emitDeclarationOnly": true 8 | }, 9 | "exclude": ["src/**/*.test.ts"], 10 | "include": ["src/**/*"] 11 | } 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "commonjs", 5 | "lib": ["ESNext"], 6 | "allowJs": true, 7 | "checkJs": true, 8 | "rootDir": ".", 9 | "composite": true, 10 | "isolatedModules": true, 11 | "strict": true, 12 | "moduleResolution": "node", 13 | "esModuleInterop": true, 14 | "skipLibCheck": true, 15 | "noEmit": true, 16 | "forceConsistentCasingInFileNames": true 17 | }, 18 | "exclude": ["dist"], 19 | "include": ["**/*", ".babelrc.js", ".eslintrc.js"] 20 | } 21 | --------------------------------------------------------------------------------