From bcaffc6c12f332be5fb0ac81f30dd8acf7f2fdb7 Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Wed, 6 Mar 2019 21:04:36 +0200 Subject: [PATCH] refactor: move @pnpm/local-resolver to monorepo --- packages/git-resolver/tsconfig.json | 2 +- packages/local-resolver/LICENSE | 21 +++ packages/local-resolver/README.md | 38 ++++++ .../local-resolver/example-package/README.md | 1 + .../example-package/package.json | 4 + packages/local-resolver/example.js | 5 + packages/local-resolver/package.json | 62 +++++++++ packages/local-resolver/src/index.ts | 77 +++++++++++ packages/local-resolver/src/parsePref.ts | 101 ++++++++++++++ packages/local-resolver/test/index.ts | 124 ++++++++++++++++++ .../test/pnpm-local-resolver-0.1.1.tgz | Bin 0 -> 4458 bytes packages/local-resolver/tsconfig.json | 24 ++++ packages/local-resolver/tslint.json | 3 + packages/local-resolver/typings/index.d.ts | 24 ++++ pnpm-lock.yaml | 72 ++++++---- 15 files changed, 535 insertions(+), 23 deletions(-) create mode 100644 packages/local-resolver/LICENSE create mode 100644 packages/local-resolver/README.md create mode 100644 packages/local-resolver/example-package/README.md create mode 100644 packages/local-resolver/example-package/package.json create mode 100644 packages/local-resolver/example.js create mode 100644 packages/local-resolver/package.json create mode 100644 packages/local-resolver/src/index.ts create mode 100644 packages/local-resolver/src/parsePref.ts create mode 100644 packages/local-resolver/test/index.ts create mode 100644 packages/local-resolver/test/pnpm-local-resolver-0.1.1.tgz create mode 100644 packages/local-resolver/tsconfig.json create mode 100644 packages/local-resolver/tslint.json create mode 100644 packages/local-resolver/typings/index.d.ts diff --git a/packages/git-resolver/tsconfig.json b/packages/git-resolver/tsconfig.json index e1c5b75154..88257b3393 100644 --- a/packages/git-resolver/tsconfig.json +++ b/packages/git-resolver/tsconfig.json @@ -9,7 +9,7 @@ "suppressImplicitAnyIndexErrors": true, "allowSyntheticDefaultImports": true, "strictNullChecks": true, - "target": "es6", + "target": "es2017", "outDir": "lib", "module": "commonjs", "moduleResolution": "node" diff --git a/packages/local-resolver/LICENSE b/packages/local-resolver/LICENSE new file mode 100644 index 0000000000..328ee580c8 --- /dev/null +++ b/packages/local-resolver/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017-2019 Zoltan Kochan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/local-resolver/README.md b/packages/local-resolver/README.md new file mode 100644 index 0000000000..61cd6ac6ef --- /dev/null +++ b/packages/local-resolver/README.md @@ -0,0 +1,38 @@ +# @pnpm/local-resolver + +> Resolver for local packages + + +[![npm version](https://img.shields.io/npm/v/@pnpm/local-resolver.svg)](https://www.npmjs.com/package/@pnpm/local-resolver) + + +## Install + +Install it via npm. + + npm install @pnpm/local-resolver + +## Usage + +```js +'use strict' +const resolveFromLocal = require('@pnpm/local-resolver').default + +resolveFromLocal({pref: './example-package'}, {prefix: process.cwd()}) + .then(resolveResult => console.log(resolveResult)) +//> { id: 'link:example-package', +// normalizedPref: 'link:example-package', +// package: +// { name: 'foo', +// version: '1.0.0', +// readme: '# foo\n', +// readmeFilename: 'README.md', +// description: '', +// _id: 'foo@1.0.0' }, +// resolution: { directory: 'example-package', type: 'directory' } +// resolvedVia: 'local-filesystem' } +``` + +## License + +[MIT](./LICENSE) © [Zoltan Kochan](https://www.kochan.io/) diff --git a/packages/local-resolver/example-package/README.md b/packages/local-resolver/example-package/README.md new file mode 100644 index 0000000000..c2a839280e --- /dev/null +++ b/packages/local-resolver/example-package/README.md @@ -0,0 +1 @@ +# foo diff --git a/packages/local-resolver/example-package/package.json b/packages/local-resolver/example-package/package.json new file mode 100644 index 0000000000..da86787ad3 --- /dev/null +++ b/packages/local-resolver/example-package/package.json @@ -0,0 +1,4 @@ +{ + "name": "foo", + "version": "1.0.0" +} diff --git a/packages/local-resolver/example.js b/packages/local-resolver/example.js new file mode 100644 index 0000000000..aba26d2c3b --- /dev/null +++ b/packages/local-resolver/example.js @@ -0,0 +1,5 @@ +'use strict' +const resolveFromLocal = require('@pnpm/local-resolver').default + +resolveFromLocal({pref: './example-package'}, {prefix: process.cwd()}) + .then(resolveResult => console.log(resolveResult)) diff --git a/packages/local-resolver/package.json b/packages/local-resolver/package.json new file mode 100644 index 0000000000..e603966dde --- /dev/null +++ b/packages/local-resolver/package.json @@ -0,0 +1,62 @@ +{ + "name": "@pnpm/local-resolver", + "version": "1.0.5", + "description": "Resolver for local packages", + "main": "lib/index.js", + "typings": "lib/index.d.ts", + "files": [ + "lib" + ], + "engines": { + "node": ">=8" + }, + "scripts": { + "lint": "tslint -c tslint.json --project .", + "tsc": "tsc", + "test": "npm run tsc && npm run lint && ts-node test --ts-node", + "md": "mos", + "prepublishOnly": "npm run tsc", + "fix": "tslint -c tslint.json --project . --fix" + }, + "repository": "https://github.com/pnpm/pnpm/blob/master/packages/local-resolver", + "keywords": [ + "pnpm", + "resolver", + "npm" + ], + "author": "Zoltan Kochan (https://www.kochan.io/)", + "license": "MIT", + "bugs": { + "url": "https://github.com/pnpm/pnpm/issues" + }, + "homepage": "https://github.com/pnpm/pnpm/blob/master/packages/local-resolver#readme", + "dependencies": { + "@pnpm/read-package-json": "1.1.1", + "@pnpm/resolver-base": "^2.1.0", + "@pnpm/types": "^2.0.0", + "@types/graceful-fs": "^4.1.2", + "@types/node": "^10.0.6", + "graceful-fs": "4.1.15", + "normalize-path": "3.0.0", + "ssri": "6.0.1" + }, + "devDependencies": { + "@pnpm/local-resolver": "link:", + "@pnpm/tslint-config": "0.0.0", + "@types/tape": "^4.2.31", + "mos": "^2.0.0-alpha.3", + "mos-plugin-readme": "^1.0.4", + "tape": "^4.8.0", + "ts-node": "^8.0.2", + "tslint": "^5.8.0", + "typescript": "^3.0.0" + }, + "mos": { + "plugins": [ + "readme" + ], + "installation": { + "useShortAlias": true + } + } +} diff --git a/packages/local-resolver/src/index.ts b/packages/local-resolver/src/index.ts new file mode 100644 index 0000000000..6aa806e15d --- /dev/null +++ b/packages/local-resolver/src/index.ts @@ -0,0 +1,77 @@ +import readPackageJson from '@pnpm/read-package-json' +import { ResolveResult } from '@pnpm/resolver-base' +import { PackageJson } from '@pnpm/types' +import fs = require('graceful-fs') +import path = require('path') +import ssri = require('ssri') +import parsePref from './parsePref' + +/** + * Resolves a package hosted on the local filesystem + */ +export default async function resolveLocal ( + wantedDependency: {pref: string}, + opts: { + prefix: string, + shrinkwrapDirectory?: string, + }, +): Promise<(ResolveResult & { + id: string, + normalizedPref: string, + resolution: {tarball: string}, +} | { + id: string, + normalizedPref: string, + package: PackageJson, + resolution: {directory: string, type: 'directory'}, +}) | null> { + const spec = parsePref(wantedDependency.pref, opts.prefix, opts.shrinkwrapDirectory || opts.prefix) + if (!spec) return null + + if (spec.type === 'file') { + return { + id: spec.id, + normalizedPref: spec.normalizedPref, + resolution: { + integrity: await getFileIntegrity(spec.fetchSpec), + tarball: spec.id, + }, + resolvedVia: 'local-filesystem', + } + } + + let localPkg!: PackageJson + try { + localPkg = await readPackageJson(path.join(spec.fetchSpec, 'package.json')) + } catch (internalErr) { + switch (internalErr.code) { + case 'ENOTDIR': { + const err = new Error(`Could not install from "${spec.fetchSpec}" as it is not a directory.`) + err['code'] = 'ERR_PNPM_NOT_PACKAGE_DIRECTORY' // tslint:disable-line:no-string-literal + throw err + } + case 'ENOENT': { + const err = new Error(`Could not install from "${spec.fetchSpec}" as it does not contain a package.json file.`) + err['code'] = 'ERR_PNPM_DIRECTORY_HAS_NO_PACKAGE_JSON' // tslint:disable-line:no-string-literal + throw err + } + default: { + throw internalErr + } + } + } + return { + id: spec.id, + normalizedPref: spec.normalizedPref, + package: localPkg, + resolution: { + directory: spec.dependencyPath, + type: 'directory', + }, + resolvedVia: 'local-filesystem', + } +} + +async function getFileIntegrity (filename: string) { + return (await ssri.fromStream(fs.createReadStream(filename))).toString() +} diff --git a/packages/local-resolver/src/parsePref.ts b/packages/local-resolver/src/parsePref.ts new file mode 100644 index 0000000000..700c67da50 --- /dev/null +++ b/packages/local-resolver/src/parsePref.ts @@ -0,0 +1,101 @@ +import normalize = require('normalize-path') +import os = require('os') +import path = require('path') + +// tslint:disable-next-line +const isWindows = process.platform === 'win32' || global['FAKE_WINDOWS'] +const isFilespec = isWindows ? /^(?:[.]|~[/]|[/\\]|[a-zA-Z]:)/ : /^(?:[.]|~[/]|[/]|[a-zA-Z]:)/ +const isFilename = /[.](?:tgz|tar.gz|tar)$/i +const isAbsolutePath = /^[/]|^[A-Za-z]:/ + +export interface LocalPackageSpec { + dependencyPath: string, + fetchSpec: string, + id: string, + type: 'directory' | 'file', + normalizedPref: string, +} + +export default function parsePref ( + pref: string, + importerPrefix: string, + shrinkwrapDirectory: string, +): LocalPackageSpec | null { + if (pref.startsWith('link:')) { + return fromLocal(pref, importerPrefix, shrinkwrapDirectory, 'directory') + } + if (pref.endsWith('.tgz') + || pref.endsWith('.tar.gz') + || pref.endsWith('.tar') + || pref.includes(path.sep) + || pref.startsWith('file:') + || isFilespec.test(pref) + ) { + const type = isFilename.test(pref) ? 'file' : 'directory' + return fromLocal(pref, importerPrefix, shrinkwrapDirectory, type) + } + if (pref.startsWith('path:')) { + const err = new Error('Local dependencies via `path:` protocol are not supported. ' + + 'Use the `link:` protocol for folder dependencies and `file:` for local tarballs') + // tslint:disable:no-string-literal + err['code'] = 'ERR_PNPM_PATH_IS_UNSUPPORTED_PROTOCOL' + err['pref'] = pref + err['protocol'] = 'path:' + // tslint:enable:no-string-literal + throw err + } + return null +} + +function fromLocal ( + pref: string, + importerPrefix: string, + shrinkwrapDirectory: string, + type: 'file' | 'directory', +): LocalPackageSpec { + if (!importerPrefix) importerPrefix = process.cwd() + + const spec = pref.replace(/\\/g, '/') + .replace(/^(file|link):[/]*([A-Za-z]:)/, '$2') // drive name paths on windows + .replace(/^(file|link):(?:[/]*([~./]))?/, '$2') + + const protocol = type === 'directory' ? 'link:' : 'file:' + let fetchSpec!: string + let normalizedPref!: string + if (/^~[/]/.test(spec)) { + // this is needed for windows and for file:~/foo/bar + fetchSpec = resolvePath(os.homedir(), spec.slice(2)) + normalizedPref = `${protocol}${spec}` + } else { + fetchSpec = resolvePath(importerPrefix, spec) + if (isAbsolute(spec)) { + normalizedPref = `${protocol}${spec}` + } else { + normalizedPref = `${protocol}${path.relative(importerPrefix, fetchSpec)}` + } + } + + const dependencyPath = normalize(path.relative(importerPrefix, fetchSpec)) + const id = type === 'directory' || importerPrefix === shrinkwrapDirectory + ? `${protocol}${dependencyPath}` + : `${protocol}${normalize(path.relative(shrinkwrapDirectory, fetchSpec))}` + + return { + dependencyPath, + fetchSpec, + id, + normalizedPref, + type, + } +} + +function resolvePath (where: string, spec: string) { + if (isAbsolutePath.test(spec)) return spec + return path.resolve(where, spec) +} + +function isAbsolute (dir: string) { + if (dir[0] === '/') return true + if (/^[A-Za-z]:/.test(dir)) return true + return false +} diff --git a/packages/local-resolver/test/index.ts b/packages/local-resolver/test/index.ts new file mode 100644 index 0000000000..48b27e540f --- /dev/null +++ b/packages/local-resolver/test/index.ts @@ -0,0 +1,124 @@ +import path = require('path') +import test = require('tape') +import resolveFromLocal from '@pnpm/local-resolver' + +test('resolve directory', async t => { + const resolveResult = await resolveFromLocal({pref: '..'}, {prefix: __dirname}) + t.equal(resolveResult!.id, 'link:..') + t.equal(resolveResult!.normalizedPref, 'link:..') + t.equal(resolveResult!['package']!.name, '@pnpm/local-resolver') + t.equal(resolveResult!.resolution!['directory'], '..') + t.equal(resolveResult!.resolution!['type'], 'directory') + t.end() +}) + +test('resolve directory specified using the file: protocol', async t => { + const resolveResult = await resolveFromLocal({pref: 'file:..'}, {prefix: __dirname}) + t.equal(resolveResult!.id, 'link:..') + t.equal(resolveResult!.normalizedPref, 'link:..') + t.equal(resolveResult!['package']!.name, '@pnpm/local-resolver') + t.equal(resolveResult!.resolution!['directory'], '..') + t.equal(resolveResult!.resolution!['type'], 'directory') + t.end() +}) + +test('resolve directoty specified using the link: protocol', async t => { + const resolveResult = await resolveFromLocal({pref: 'link:..'}, {prefix: __dirname}) + t.equal(resolveResult!.id, 'link:..') + t.equal(resolveResult!.normalizedPref, 'link:..') + t.equal(resolveResult!['package']!.name, '@pnpm/local-resolver') + t.equal(resolveResult!.resolution!['directory'], '..') + t.equal(resolveResult!.resolution!['type'], 'directory') + t.end() +}) + +test('resolve file', async t => { + const wantedDependency = {pref: './pnpm-local-resolver-0.1.1.tgz'} + const resolveResult = await resolveFromLocal(wantedDependency, {prefix: __dirname}) + + t.deepEqual(resolveResult, { + id: 'file:pnpm-local-resolver-0.1.1.tgz', + normalizedPref: 'file:pnpm-local-resolver-0.1.1.tgz', + resolution: { + integrity: 'sha512-UHd2zKRT/w70KKzFlj4qcT81A1Q0H7NM9uKxLzIZ/VZqJXzt5Hnnp2PYPb5Ezq/hAamoYKIn5g7fuv69kP258w==', + tarball: 'file:pnpm-local-resolver-0.1.1.tgz', + }, + resolvedVia: 'local-filesystem', + }) + + t.end() +}) + +test("resolve file when shrinkwrap directory differs from the package's dir", async t => { + const wantedDependency = {pref: './pnpm-local-resolver-0.1.1.tgz'} + const resolveResult = await resolveFromLocal(wantedDependency, { + prefix: __dirname, + shrinkwrapDirectory: path.join(__dirname, '..'), + }) + + t.deepEqual(resolveResult, { + id: 'file:test/pnpm-local-resolver-0.1.1.tgz', + normalizedPref: 'file:pnpm-local-resolver-0.1.1.tgz', + resolution: { + integrity: 'sha512-UHd2zKRT/w70KKzFlj4qcT81A1Q0H7NM9uKxLzIZ/VZqJXzt5Hnnp2PYPb5Ezq/hAamoYKIn5g7fuv69kP258w==', + tarball: 'file:test/pnpm-local-resolver-0.1.1.tgz', + }, + resolvedVia: 'local-filesystem', + }) + + t.end() +}) + +test('resolve tarball specified with file: protocol', async t => { + const wantedDependency = {pref: 'file:./pnpm-local-resolver-0.1.1.tgz'} + const resolveResult = await resolveFromLocal(wantedDependency, {prefix: __dirname}) + + t.deepEqual(resolveResult, { + id: 'file:pnpm-local-resolver-0.1.1.tgz', + normalizedPref: 'file:pnpm-local-resolver-0.1.1.tgz', + resolution: { + integrity: 'sha512-UHd2zKRT/w70KKzFlj4qcT81A1Q0H7NM9uKxLzIZ/VZqJXzt5Hnnp2PYPb5Ezq/hAamoYKIn5g7fuv69kP258w==', + tarball: 'file:pnpm-local-resolver-0.1.1.tgz', + }, + resolvedVia: 'local-filesystem', + }) + + t.end() +}) + +test("fail when resolving tarball specified with the link: protocol", async t => { + try { + const wantedDependency = {pref: 'link:./pnpm-local-resolver-0.1.1.tgz'} + const resolveResult = await resolveFromLocal(wantedDependency, {prefix: __dirname}) + t.fail() + } catch (err) { + t.ok(err) + t.equal(err.code, 'ERR_PNPM_NOT_PACKAGE_DIRECTORY') + t.end() + } +}) + +test("fail when resolving from not existing directory", async t => { + try { + const wantedDependency = {pref: 'link:./dir-does-not-exist'} + const resolveResult = await resolveFromLocal(wantedDependency, {prefix: __dirname}) + t.fail() + } catch (err) { + t.ok(err) + t.equal(err.code, 'ERR_PNPM_DIRECTORY_HAS_NO_PACKAGE_JSON') + t.end() + } +}) + +test('throw error when the path: protocol is used', async t => { + try { + await resolveFromLocal({pref: 'path:..'}, {prefix: __dirname}) + t.fail() + } catch (err) { + t.ok(err) + t.equal(err.code, 'ERR_PNPM_PATH_IS_UNSUPPORTED_PROTOCOL') + t.equal(err.pref, 'path:..') + t.equal(err.protocol, 'path:') + t.end() + } +}) diff --git a/packages/local-resolver/test/pnpm-local-resolver-0.1.1.tgz b/packages/local-resolver/test/pnpm-local-resolver-0.1.1.tgz new file mode 100644 index 0000000000000000000000000000000000000000..247bf2b2c4c2ecc9ddfc8204588955a1555b805a GIT binary patch literal 4458 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' resolution: integrity: sha512-AeAxhTVNNtB7u5hVyojTnFsJi/iE/w13t23aQ3wMdpIEIDFVO6nukk8eZShDWlRCTTHjvfON1LpwHqQDRsT0dA== - /@pnpm/local-resolver/1.0.5: - dependencies: - '@pnpm/read-package-json': 1.1.1 - '@pnpm/resolver-base': 2.1.0 - '@pnpm/types': 2.0.0 - '@types/graceful-fs': 4.1.3 - '@types/node': 10.12.29 - graceful-fs: 4.1.15 - normalize-path: 3.0.0 - ssri: 6.0.1 - engines: - node: '>=6' - resolution: - integrity: sha512-I8aRPY//PnFAGF+ndj/UE9iox9zdKv7T4F7wrh3AH19w7JFC2FhHbTRB2AvJaTEygvCzjsamvXNGPLVTe8zfpA== /@pnpm/logger/2.1.0: dependencies: '@types/node': 10.12.29 @@ -2484,6 +2508,7 @@ packages: /@pnpm/resolver-base/2.1.0: dependencies: '@pnpm/types': 2.0.0 + dev: false engines: node: '>=6' resolution: @@ -2522,22 +2547,22 @@ packages: node: '>=4' resolution: integrity: sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow== - /@sinonjs/commons/1.3.1: + /@sinonjs/commons/1.4.0: dependencies: type-detect: 4.0.8 dev: true resolution: - integrity: sha512-rgmZk5CrBGAMATk0HlHOFvo8V44/r+On6cKS80tqid0Eljd+fFBWBOXZp9H2/EB3faxdNdzXTx6QZIKLkbJ7mA== + integrity: sha512-9jHK3YF/8HtJ9wCAbG+j8cD0i0+ATS9A7gXFqS36TblLPNy6rEEc+SB0imo91eCboGaBYGV/MT1/br/J+EE7Tw== /@sinonjs/formatio/3.2.1: dependencies: - '@sinonjs/commons': 1.3.1 + '@sinonjs/commons': 1.4.0 '@sinonjs/samsam': 3.2.0 dev: true resolution: integrity: sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ== /@sinonjs/samsam/3.2.0: dependencies: - '@sinonjs/commons': 1.3.1 + '@sinonjs/commons': 1.4.0 array-from: 2.1.1 lodash: 4.17.11 dev: true @@ -2595,7 +2620,8 @@ packages: integrity: sha512-0AbIQzpqQafYPFg26nwg5PfNgPLYwHeTP6z5F1u+5oypLIdpx34o5r8wYTTj3X3YYF2yPHtZPO/KYwlI8Nu/hQ== /@types/graceful-fs/4.1.3: dependencies: - '@types/node': 11.9.5 + '@types/node': 10.12.29 + dev: false resolution: integrity: sha512-AiHRaEB50LQg0pZmm659vNBb9f4SJ0qrAnteuzhSeAUcJKxoYgEnprg/83kppCnc2zvtCKbdZry1a5pVY3lOTQ== /@types/http-proxy-agent/2.0.1: @@ -4948,6 +4974,7 @@ packages: resolution: integrity: sha1-oB6c2cnkkXFcmKdaQtXwu9EH/3Y= /figgy-pudding/3.5.1: + dev: false resolution: integrity: sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w== /figures/1.7.0: @@ -8929,7 +8956,7 @@ packages: integrity: sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= /sinon/7.2.6: dependencies: - '@sinonjs/commons': 1.3.1 + '@sinonjs/commons': 1.4.0 '@sinonjs/formatio': 3.2.1 '@sinonjs/samsam': 3.2.0 diff: 3.5.0 @@ -9151,6 +9178,7 @@ packages: /ssri/6.0.1: dependencies: figgy-pudding: 3.5.1 + dev: false resolution: integrity: sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== /stacktracey/1.2.106: