@servicetitan/install 36.3.0 → 36.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/package-manager/npm-package-manager.d.ts +4 -0
  2. package/dist/package-manager/npm-package-manager.d.ts.map +1 -1
  3. package/dist/package-manager/npm-package-manager.js +18 -13
  4. package/dist/package-manager/npm-package-manager.js.map +1 -1
  5. package/dist/package-manager/package-manager.d.ts +8 -0
  6. package/dist/package-manager/package-manager.d.ts.map +1 -1
  7. package/dist/package-manager/package-manager.js +44 -1
  8. package/dist/package-manager/package-manager.js.map +1 -1
  9. package/dist/package-manager/pnpm-package-manager.d.ts +1 -0
  10. package/dist/package-manager/pnpm-package-manager.d.ts.map +1 -1
  11. package/dist/package-manager/pnpm-package-manager.js +10 -3
  12. package/dist/package-manager/pnpm-package-manager.js.map +1 -1
  13. package/dist/utils/get-packages-with-install-scripts.d.ts.map +1 -1
  14. package/dist/utils/get-packages-with-install-scripts.js +6 -2
  15. package/dist/utils/get-packages-with-install-scripts.js.map +1 -1
  16. package/dist/utils/index.d.ts +0 -1
  17. package/dist/utils/index.d.ts.map +1 -1
  18. package/dist/utils/index.js +0 -1
  19. package/dist/utils/index.js.map +1 -1
  20. package/dist/utils/warn-untrusted-install-scripts.d.ts +1 -5
  21. package/dist/utils/warn-untrusted-install-scripts.d.ts.map +1 -1
  22. package/dist/utils/warn-untrusted-install-scripts.js +1 -6
  23. package/dist/utils/warn-untrusted-install-scripts.js.map +1 -1
  24. package/package.json +3 -3
  25. package/src/package-manager/npm-package-manager.ts +21 -16
  26. package/src/package-manager/package-manager.ts +39 -1
  27. package/src/package-manager/pnpm-package-manager.ts +11 -3
  28. package/src/utils/get-packages-with-install-scripts.ts +7 -2
  29. package/src/utils/index.ts +0 -1
  30. package/src/utils/warn-untrusted-install-scripts.ts +1 -15
  31. package/dist/utils/has-lockfile-changed.d.ts +0 -2
  32. package/dist/utils/has-lockfile-changed.d.ts.map +0 -1
  33. package/dist/utils/has-lockfile-changed.js +0 -27
  34. package/dist/utils/has-lockfile-changed.js.map +0 -1
  35. package/src/utils/has-lockfile-changed.ts +0 -10
@@ -3,6 +3,8 @@ import type { DeclaredVersionQuery, InstallArgs, ResolvedVersionQuery } from './
3
3
  import { PackageManager } from './package-manager';
4
4
  interface NpmLockFileEntry {
5
5
  version?: string;
6
+ resolved?: string;
7
+ link?: boolean;
6
8
  dependencies?: Record<string, string>;
7
9
  peerDependencies?: Record<string, string>;
8
10
  }
@@ -22,6 +24,8 @@ export declare class NpmPackageManager extends PackageManager<NpmLockFile> {
22
24
  * to the hoisted root entry. `workspacePackage` is the package's relative
23
25
  * path from the repo root; the empty string `''` denotes the root
24
26
  * workspace package itself, matching npm's own lockfile key convention.
27
+ * Follows link entries to the resolved workspace package, so callers see
28
+ * the workspace package's own metadata rather than the symlink stub.
25
29
  */
26
30
  private findEntry;
27
31
  private runRebuild;
@@ -1 +1 @@
1
- {"version":3,"file":"npm-package-manager.d.ts","sourceRoot":"","sources":["../../src/package-manager/npm-package-manager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAQ,UAAU,EAA+B,MAAM,UAAU,CAAC;AACzE,OAAO,KAAK,EAAE,oBAAoB,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACjG,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAQnD,UAAU,gBAAgB;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,WAAW;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAC/C;AAED,qBAAa,iBAAkB,SAAQ,cAAc,CAAC,WAAW,CAAC;IAC9D,QAAQ,CAAC,OAAO,SAAS;IACzB,QAAQ,CAAC,YAAY,uBAAuB;IAE5C,UAAU;IAIV,kBAAkB,CAAC,EACf,gBAAgB,EAChB,UAAU,EACV,UAAU,GACb,EAAE,oBAAoB,GAAG,MAAM,GAAG,SAAS;IAK5C,kBAAkB,CAAC,EAAE,gBAAgB,EAAE,UAAU,EAAE,EAAE,oBAAoB,GAAG,MAAM,GAAG,SAAS;IAI9F,eAAe,CAAC,IAAI,GAAE,WAAgB,EAAE,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;IA6DlF,SAAS,CAAC,aAAa,IAAI,WAAW,GAAG,SAAS;IAQlD;;;;;OAKG;IACH,OAAO,CAAC,SAAS;IAcjB,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,qBAAqB;CAOhC"}
1
+ {"version":3,"file":"npm-package-manager.d.ts","sourceRoot":"","sources":["../../src/package-manager/npm-package-manager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAQ,UAAU,EAA+B,MAAM,UAAU,CAAC;AACzE,OAAO,KAAK,EAAE,oBAAoB,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACjG,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAQnD,UAAU,gBAAgB;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,WAAW;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAC/C;AAED,qBAAa,iBAAkB,SAAQ,cAAc,CAAC,WAAW,CAAC;IAC9D,QAAQ,CAAC,OAAO,SAAS;IACzB,QAAQ,CAAC,YAAY,uBAAuB;IAE5C,UAAU;IAIV,kBAAkB,CAAC,EACf,gBAAgB,EAChB,UAAU,EACV,UAAU,GACb,EAAE,oBAAoB,GAAG,MAAM,GAAG,SAAS;IAK5C,kBAAkB,CAAC,EAAE,gBAAgB,EAAE,UAAU,EAAE,EAAE,oBAAoB,GAAG,MAAM,GAAG,SAAS;IAI9F,eAAe,CAAC,IAAI,GAAE,WAAgB,EAAE,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;IAuDlF,SAAS,CAAC,aAAa,IAAI,WAAW,GAAG,SAAS;IAYlD;;;;;;;OAOG;IACH,OAAO,CAAC,SAAS;IAiBjB,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,qBAAqB;CAOhC"}
@@ -32,7 +32,7 @@ function _interop_require_default(obj) {
32
32
  }
33
33
  class NpmPackageManager extends _packagemanager.PackageManager {
34
34
  clearCache() {
35
- (0, _utils.runCommand)('npm', [
35
+ (0, _utils.runCommand)(this.command, [
36
36
  'cache',
37
37
  'clear',
38
38
  '--force'
@@ -56,14 +56,11 @@ class NpmPackageManager extends _packagemanager.PackageManager {
56
56
  }
57
57
  installPackages(args = {}, options) {
58
58
  var _args_allowScripts;
59
- /*
60
- * The `true` fallback allows projects a grace period to identify and
61
- * allowlist trusted scripts. Remove the fallback when the grace period expires.
62
- */ const allowScripts = (0, _utils1.resolveAllowScripts)((_args_allowScripts = args.allowScripts) !== null && _args_allowScripts !== void 0 ? _args_allowScripts : true);
59
+ const allowScripts = (0, _utils1.resolveAllowScripts)((_args_allowScripts = args.allowScripts) !== null && _args_allowScripts !== void 0 ? _args_allowScripts : []);
63
60
  if (!args.quiet) {
64
61
  (0, _utils1.logAllowedScripts)(allowScripts);
65
62
  }
66
- (0, _utils.runCommand)('npm', [
63
+ (0, _utils.runCommand)(this.command, [
67
64
  (0, _utils.isCI)() ? 'ci' : 'i',
68
65
  '--audit=false',
69
66
  '--fund=false',
@@ -92,9 +89,7 @@ class NpmPackageManager extends _packagemanager.PackageManager {
92
89
  * scripts they should add to --allow-scripts. Skip when the user
93
90
  * explicitly opted out (`false`); they made an informed choice.
94
91
  */ if (allowScripts !== false) {
95
- (0, _utils.warnUntrustedInstallScripts)(Array.isArray(allowScripts) ? allowScripts : _utils1.DEFAULT_ALLOWED_SCRIPTS, this.lockFileName, {
96
- force: true
97
- });
92
+ (0, _utils.warnUntrustedInstallScripts)(Array.isArray(allowScripts) ? allowScripts : _utils1.DEFAULT_ALLOWED_SCRIPTS);
98
93
  }
99
94
  /*
100
95
  * When allowScripts is `true`, npm already ran project postinstall.
@@ -108,8 +103,12 @@ class NpmPackageManager extends _packagemanager.PackageManager {
108
103
  }
109
104
  }
110
105
  parseLockFile() {
106
+ const lockFilePath = this.getLockFilePath();
107
+ if (!lockFilePath) {
108
+ return undefined;
109
+ }
111
110
  try {
112
- return JSON.parse(_fs.default.readFileSync(this.lockFileName, 'utf-8'));
111
+ return JSON.parse(_fs.default.readFileSync(lockFilePath, 'utf-8'));
113
112
  } catch (unused) {
114
113
  return undefined;
115
114
  }
@@ -119,15 +118,21 @@ class NpmPackageManager extends _packagemanager.PackageManager {
119
118
  * to the hoisted root entry. `workspacePackage` is the package's relative
120
119
  * path from the repo root; the empty string `''` denotes the root
121
120
  * workspace package itself, matching npm's own lockfile key convention.
121
+ * Follows link entries to the resolved workspace package, so callers see
122
+ * the workspace package's own metadata rather than the symlink stub.
122
123
  */ findEntry({ workspacePackage, package: packageName }) {
123
124
  var _ref;
124
125
  var _this_getLockFile;
125
126
  const packages = (_this_getLockFile = this.getLockFile()) === null || _this_getLockFile === void 0 ? void 0 : _this_getLockFile.packages;
126
- return (_ref = packages === null || packages === void 0 ? void 0 : packages[`${workspacePackage}/node_modules/${packageName}`]) !== null && _ref !== void 0 ? _ref : packages === null || packages === void 0 ? void 0 : packages[`node_modules/${packageName}`];
127
+ const entry = (_ref = packages === null || packages === void 0 ? void 0 : packages[`${workspacePackage}/node_modules/${packageName}`]) !== null && _ref !== void 0 ? _ref : packages === null || packages === void 0 ? void 0 : packages[`node_modules/${packageName}`];
128
+ if ((entry === null || entry === void 0 ? void 0 : entry.link) && entry.resolved) {
129
+ return packages === null || packages === void 0 ? void 0 : packages[entry.resolved];
130
+ }
131
+ return entry;
127
132
  }
128
133
  runRebuild(scripts) {
129
134
  try {
130
- (0, _utils.runCommand)('npm', [
135
+ (0, _utils.runCommand)(this.command, [
131
136
  'rebuild',
132
137
  ...scripts
133
138
  ]);
@@ -138,7 +143,7 @@ class NpmPackageManager extends _packagemanager.PackageManager {
138
143
  }
139
144
  runProjectPostinstall(options) {
140
145
  try {
141
- (0, _utils.runCommand)('npm', [
146
+ (0, _utils.runCommand)(this.command, [
142
147
  'run',
143
148
  'postinstall',
144
149
  '--if-present'
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/package-manager/npm-package-manager.ts"],"sourcesContent":["/* eslint-disable no-console */\nimport fs from 'fs';\nimport { isCI, runCommand, warnUntrustedInstallScripts } from '../utils';\nimport type { DeclaredVersionQuery, InstallArgs, ResolvedVersionQuery } from './package-manager';\nimport { PackageManager } from './package-manager';\nimport {\n DEFAULT_ALLOWED_SCRIPTS,\n logAllowedScripts,\n resolveAllowScripts,\n shouldIgnoreScripts,\n} from './utils';\n\ninterface NpmLockFileEntry {\n version?: string;\n dependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n}\n\nexport interface NpmLockFile {\n packages?: Record<string, NpmLockFileEntry>;\n}\n\nexport class NpmPackageManager extends PackageManager<NpmLockFile> {\n readonly command = 'npm';\n readonly lockFileName = 'package-lock.json';\n\n clearCache() {\n runCommand('npm', ['cache', 'clear', '--force']);\n }\n\n getDeclaredVersion({\n workspacePackage,\n declaredBy,\n dependency,\n }: DeclaredVersionQuery): string | undefined {\n const entry = this.findEntry({ workspacePackage, package: declaredBy });\n return entry?.dependencies?.[dependency] ?? entry?.peerDependencies?.[dependency];\n }\n\n getResolvedVersion({ workspacePackage, dependency }: ResolvedVersionQuery): string | undefined {\n return this.findEntry({ workspacePackage, package: dependency })?.version;\n }\n\n installPackages(args: InstallArgs = {}, options?: Parameters<typeof runCommand>[2]) {\n /*\n * The `true` fallback allows projects a grace period to identify and\n * allowlist trusted scripts. Remove the fallback when the grace period expires.\n */\n const allowScripts = resolveAllowScripts(args.allowScripts ?? true);\n\n if (!args.quiet) {\n logAllowedScripts(allowScripts);\n }\n\n runCommand(\n 'npm',\n [\n isCI() ? 'ci' : 'i',\n '--audit=false',\n '--fund=false',\n '--legacy-peer-deps',\n ...(shouldIgnoreScripts(allowScripts) ? ['--ignore-scripts'] : []),\n ...(args.fix ? ['--package-lock-only', '--prefer-dedupe'] : []),\n ],\n options\n );\n\n try {\n if (args.fix) {\n return;\n }\n /*\n * Rebuild applies when allowScripts is an explicit list:\n * `true` means npm install already ran every script, `false`\n * means the user opted out.\n */\n if (Array.isArray(allowScripts)) {\n this.runRebuild(allowScripts);\n }\n /*\n * Warn against the effective allowlist so teams can see which\n * scripts they should add to --allow-scripts. Skip when the user\n * explicitly opted out (`false`); they made an informed choice.\n */\n if (allowScripts !== false) {\n warnUntrustedInstallScripts(\n Array.isArray(allowScripts) ? allowScripts : DEFAULT_ALLOWED_SCRIPTS,\n this.lockFileName,\n { force: true }\n );\n }\n /*\n * When allowScripts is `true`, npm already ran project postinstall.\n * In other cases, we run it manually. Note, `false` only ignores\n * package scripts, the project postinstall is always trusted.\n */\n if (allowScripts !== true) {\n this.runProjectPostinstall(options);\n }\n } finally {\n this.reset();\n }\n }\n\n protected parseLockFile(): NpmLockFile | undefined {\n try {\n return JSON.parse(fs.readFileSync(this.lockFileName, 'utf-8'));\n } catch {\n return undefined;\n }\n }\n\n /**\n * Looks up a lockfile entry for the given workspace package, falling back\n * to the hoisted root entry. `workspacePackage` is the package's relative\n * path from the repo root; the empty string `''` denotes the root\n * workspace package itself, matching npm's own lockfile key convention.\n */\n private findEntry({\n workspacePackage,\n package: packageName,\n }: {\n workspacePackage: string;\n package: string;\n }): NpmLockFileEntry | undefined {\n const packages = this.getLockFile()?.packages;\n return (\n packages?.[`${workspacePackage}/node_modules/${packageName}`] ??\n packages?.[`node_modules/${packageName}`]\n );\n }\n\n private runRebuild(scripts: string[]) {\n try {\n runCommand('npm', ['rebuild', ...scripts]);\n } catch {\n console.error(`Failed to run allowed scripts: ${scripts.join(', ')}`);\n process.exitCode = 1;\n }\n }\n\n private runProjectPostinstall(options?: Parameters<typeof runCommand>[2]) {\n try {\n runCommand('npm', ['run', 'postinstall', '--if-present'], options);\n } catch {\n process.exitCode = 1;\n }\n }\n}\n"],"names":["NpmPackageManager","PackageManager","clearCache","runCommand","getDeclaredVersion","workspacePackage","declaredBy","dependency","entry","findEntry","package","dependencies","peerDependencies","getResolvedVersion","version","installPackages","args","options","allowScripts","resolveAllowScripts","quiet","logAllowedScripts","isCI","shouldIgnoreScripts","fix","Array","isArray","runRebuild","warnUntrustedInstallScripts","DEFAULT_ALLOWED_SCRIPTS","lockFileName","force","runProjectPostinstall","reset","parseLockFile","JSON","parse","fs","readFileSync","undefined","packageName","packages","getLockFile","scripts","console","error","join","process","exitCode","command"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/package-manager/npm-package-manager.ts"],"sourcesContent":["/* eslint-disable no-console */\nimport fs from 'fs';\nimport { isCI, runCommand, warnUntrustedInstallScripts } from '../utils';\nimport type { DeclaredVersionQuery, InstallArgs, ResolvedVersionQuery } from './package-manager';\nimport { PackageManager } from './package-manager';\nimport {\n DEFAULT_ALLOWED_SCRIPTS,\n logAllowedScripts,\n resolveAllowScripts,\n shouldIgnoreScripts,\n} from './utils';\n\ninterface NpmLockFileEntry {\n version?: string;\n resolved?: string;\n link?: boolean;\n dependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n}\n\nexport interface NpmLockFile {\n packages?: Record<string, NpmLockFileEntry>;\n}\n\nexport class NpmPackageManager extends PackageManager<NpmLockFile> {\n readonly command = 'npm';\n readonly lockFileName = 'package-lock.json';\n\n clearCache() {\n runCommand(this.command, ['cache', 'clear', '--force']);\n }\n\n getDeclaredVersion({\n workspacePackage,\n declaredBy,\n dependency,\n }: DeclaredVersionQuery): string | undefined {\n const entry = this.findEntry({ workspacePackage, package: declaredBy });\n return entry?.dependencies?.[dependency] ?? entry?.peerDependencies?.[dependency];\n }\n\n getResolvedVersion({ workspacePackage, dependency }: ResolvedVersionQuery): string | undefined {\n return this.findEntry({ workspacePackage, package: dependency })?.version;\n }\n\n installPackages(args: InstallArgs = {}, options?: Parameters<typeof runCommand>[2]) {\n const allowScripts = resolveAllowScripts(args.allowScripts ?? []);\n\n if (!args.quiet) {\n logAllowedScripts(allowScripts);\n }\n\n runCommand(\n this.command,\n [\n isCI() ? 'ci' : 'i',\n '--audit=false',\n '--fund=false',\n '--legacy-peer-deps',\n ...(shouldIgnoreScripts(allowScripts) ? ['--ignore-scripts'] : []),\n ...(args.fix ? ['--package-lock-only', '--prefer-dedupe'] : []),\n ],\n options\n );\n\n try {\n if (args.fix) {\n return;\n }\n /*\n * Rebuild applies when allowScripts is an explicit list:\n * `true` means npm install already ran every script, `false`\n * means the user opted out.\n */\n if (Array.isArray(allowScripts)) {\n this.runRebuild(allowScripts);\n }\n /*\n * Warn against the effective allowlist so teams can see which\n * scripts they should add to --allow-scripts. Skip when the user\n * explicitly opted out (`false`); they made an informed choice.\n */\n if (allowScripts !== false) {\n warnUntrustedInstallScripts(\n Array.isArray(allowScripts) ? allowScripts : DEFAULT_ALLOWED_SCRIPTS\n );\n }\n /*\n * When allowScripts is `true`, npm already ran project postinstall.\n * In other cases, we run it manually. Note, `false` only ignores\n * package scripts, the project postinstall is always trusted.\n */\n if (allowScripts !== true) {\n this.runProjectPostinstall(options);\n }\n } finally {\n this.reset();\n }\n }\n\n protected parseLockFile(): NpmLockFile | undefined {\n const lockFilePath = this.getLockFilePath();\n if (!lockFilePath) {\n return undefined;\n }\n try {\n return JSON.parse(fs.readFileSync(lockFilePath, 'utf-8'));\n } catch {\n return undefined;\n }\n }\n\n /**\n * Looks up a lockfile entry for the given workspace package, falling back\n * to the hoisted root entry. `workspacePackage` is the package's relative\n * path from the repo root; the empty string `''` denotes the root\n * workspace package itself, matching npm's own lockfile key convention.\n * Follows link entries to the resolved workspace package, so callers see\n * the workspace package's own metadata rather than the symlink stub.\n */\n private findEntry({\n workspacePackage,\n package: packageName,\n }: {\n workspacePackage: string;\n package: string;\n }): NpmLockFileEntry | undefined {\n const packages = this.getLockFile()?.packages;\n const entry =\n packages?.[`${workspacePackage}/node_modules/${packageName}`] ??\n packages?.[`node_modules/${packageName}`];\n if (entry?.link && entry.resolved) {\n return packages?.[entry.resolved];\n }\n return entry;\n }\n\n private runRebuild(scripts: string[]) {\n try {\n runCommand(this.command, ['rebuild', ...scripts]);\n } catch {\n console.error(`Failed to run allowed scripts: ${scripts.join(', ')}`);\n process.exitCode = 1;\n }\n }\n\n private runProjectPostinstall(options?: Parameters<typeof runCommand>[2]) {\n try {\n runCommand(this.command, ['run', 'postinstall', '--if-present'], options);\n } catch {\n process.exitCode = 1;\n }\n }\n}\n"],"names":["NpmPackageManager","PackageManager","clearCache","runCommand","command","getDeclaredVersion","workspacePackage","declaredBy","dependency","entry","findEntry","package","dependencies","peerDependencies","getResolvedVersion","version","installPackages","args","options","allowScripts","resolveAllowScripts","quiet","logAllowedScripts","isCI","shouldIgnoreScripts","fix","Array","isArray","runRebuild","warnUntrustedInstallScripts","DEFAULT_ALLOWED_SCRIPTS","runProjectPostinstall","reset","parseLockFile","lockFilePath","getLockFilePath","undefined","JSON","parse","fs","readFileSync","packageName","packages","getLockFile","link","resolved","scripts","console","error","join","process","exitCode","lockFileName"],"mappings":"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"}
@@ -19,8 +19,16 @@ export declare abstract class PackageManager<LockFile = unknown> {
19
19
  abstract readonly command: string;
20
20
  abstract readonly lockFileName: string;
21
21
  hasValidLockFile(): boolean;
22
+ getLockFilePath(): string | undefined;
23
+ /**
24
+ * Returns the lockfile key for a package given its absolute or
25
+ * cwd-relative directory. Both npm and pnpm key their lockfile entries
26
+ * by the package's path relative to the workspace root.
27
+ */
28
+ getWorkspacePackage(packageDir?: string): string;
22
29
  protected getLockFile(): LockFile | undefined;
23
30
  protected reset(): void;
31
+ protected get rootWorkspacePackage(): string;
24
32
  abstract clearCache(): void;
25
33
  abstract getDeclaredVersion(query: DeclaredVersionQuery): string | undefined;
26
34
  abstract getResolvedVersion(query: ResolvedVersionQuery): string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"package-manager.d.ts","sourceRoot":"","sources":["../../src/package-manager/package-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,KAAK,GAAG,MAAM,EAAE,CAAC;AAEnD,MAAM,WAAW,WAAW;IACxB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACjC,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACjC,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,8BAAsB,cAAc,CAAC,QAAQ,GAAG,OAAO;;IACnD,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAKvC,gBAAgB,IAAI,OAAO;IAI3B,SAAS,CAAC,WAAW,IAAI,QAAQ,GAAG,SAAS;IAQ7C,SAAS,CAAC,KAAK;IAKf,QAAQ,CAAC,UAAU,IAAI,IAAI;IAC3B,QAAQ,CAAC,kBAAkB,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,GAAG,SAAS;IAC5E,QAAQ,CAAC,kBAAkB,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,GAAG,SAAS;IAC5E,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;IAE9F,SAAS,CAAC,QAAQ,CAAC,aAAa,IAAI,QAAQ,GAAG,SAAS;CAC3D"}
1
+ {"version":3,"file":"package-manager.d.ts","sourceRoot":"","sources":["../../src/package-manager/package-manager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAU,UAAU,EAAE,MAAM,UAAU,CAAC;AAE9C,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,KAAK,GAAG,MAAM,EAAE,CAAC;AAEnD,MAAM,WAAW,WAAW;IACxB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACjC,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACjC,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,8BAAsB,cAAc,CAAC,QAAQ,GAAG,OAAO;;IACnD,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAOvC,gBAAgB,IAAI,OAAO;IAI3B,eAAe,IAAI,MAAM,GAAG,SAAS;IAWrC;;;;OAIG;IACH,mBAAmB,CAAC,UAAU,SAAgB,GAAG,MAAM;IAYvD,SAAS,CAAC,WAAW,IAAI,QAAQ,GAAG,SAAS;IAQ7C,SAAS,CAAC,KAAK;IAOf,SAAS,KAAK,oBAAoB,IAAI,MAAM,CAE3C;IAED,QAAQ,CAAC,UAAU,IAAI,IAAI;IAC3B,QAAQ,CAAC,kBAAkB,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,GAAG,SAAS;IAC5E,QAAQ,CAAC,kBAAkB,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,GAAG,SAAS;IAC5E,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;IAE9F,SAAS,CAAC,QAAQ,CAAC,aAAa,IAAI,QAAQ,GAAG,SAAS;CAC3D"}
@@ -8,6 +8,9 @@ Object.defineProperty(exports, "PackageManager", {
8
8
  return PackageManager;
9
9
  }
10
10
  });
11
+ const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
12
+ const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
13
+ const _utils = require("../utils");
11
14
  function _check_private_redeclaration(obj, privateCollection) {
12
15
  if (privateCollection.has(obj)) {
13
16
  throw new TypeError("Cannot initialize the same private elements twice on an object");
@@ -48,11 +51,38 @@ function _class_private_field_set(receiver, privateMap, value) {
48
51
  _class_apply_descriptor_set(receiver, descriptor, value);
49
52
  return value;
50
53
  }
51
- var _lockFile = /*#__PURE__*/ new WeakMap(), _lockFileLoaded = /*#__PURE__*/ new WeakMap();
54
+ function _interop_require_default(obj) {
55
+ return obj && obj.__esModule ? obj : {
56
+ default: obj
57
+ };
58
+ }
59
+ var _lockFile = /*#__PURE__*/ new WeakMap(), _lockFileLoaded = /*#__PURE__*/ new WeakMap(), _lockFilePath = /*#__PURE__*/ new WeakMap(), _lockFilePathLoaded = /*#__PURE__*/ new WeakMap();
52
60
  class PackageManager {
53
61
  hasValidLockFile() {
54
62
  return this.getLockFile() !== undefined;
55
63
  }
64
+ getLockFilePath() {
65
+ if (!_class_private_field_get(this, _lockFilePathLoaded)) {
66
+ _class_private_field_set(this, _lockFilePath, (0, _utils.findUp)((directory)=>{
67
+ const candidate = _nodepath.default.join(directory, this.lockFileName);
68
+ return _fs.default.existsSync(candidate) ? candidate : undefined;
69
+ }));
70
+ _class_private_field_set(this, _lockFilePathLoaded, true);
71
+ }
72
+ return _class_private_field_get(this, _lockFilePath);
73
+ }
74
+ /**
75
+ * Returns the lockfile key for a package given its absolute or
76
+ * cwd-relative directory. Both npm and pnpm key their lockfile entries
77
+ * by the package's path relative to the workspace root.
78
+ */ getWorkspacePackage(packageDir = process.cwd()) {
79
+ const lockFilePath = this.getLockFilePath();
80
+ if (!lockFilePath) {
81
+ return this.rootWorkspacePackage;
82
+ }
83
+ const relative = _nodepath.default.relative(_nodepath.default.dirname(lockFilePath), _nodepath.default.resolve(packageDir)).split(_nodepath.default.sep).join('/');
84
+ return relative === '' ? this.rootWorkspacePackage : relative;
85
+ }
56
86
  getLockFile() {
57
87
  if (!_class_private_field_get(this, _lockFileLoaded)) {
58
88
  _class_private_field_set(this, _lockFile, this.parseLockFile());
@@ -63,6 +93,11 @@ class PackageManager {
63
93
  reset() {
64
94
  _class_private_field_set(this, _lockFile, undefined);
65
95
  _class_private_field_set(this, _lockFileLoaded, false);
96
+ _class_private_field_set(this, _lockFilePath, undefined);
97
+ _class_private_field_set(this, _lockFilePathLoaded, false);
98
+ }
99
+ get rootWorkspacePackage() {
100
+ return '';
66
101
  }
67
102
  constructor(){
68
103
  _class_private_field_init(this, _lockFile, {
@@ -73,6 +108,14 @@ class PackageManager {
73
108
  writable: true,
74
109
  value: false
75
110
  });
111
+ _class_private_field_init(this, _lockFilePath, {
112
+ writable: true,
113
+ value: void 0
114
+ });
115
+ _class_private_field_init(this, _lockFilePathLoaded, {
116
+ writable: true,
117
+ value: false
118
+ });
76
119
  }
77
120
  }
78
121
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/package-manager/package-manager.ts"],"sourcesContent":["import { runCommand } from '../utils';\n\nexport type AllowScripts = true | false | string[];\n\nexport interface InstallArgs {\n allowScripts?: AllowScripts;\n fix?: boolean;\n quiet?: boolean;\n}\n\nexport interface DeclaredVersionQuery {\n workspacePackage: string;\n declaredBy: string;\n dependency: string;\n}\n\nexport interface ResolvedVersionQuery {\n workspacePackage: string;\n dependency: string;\n}\n\nexport abstract class PackageManager<LockFile = unknown> {\n abstract readonly command: string;\n abstract readonly lockFileName: string;\n\n #lockFile: LockFile | undefined;\n #lockFileLoaded = false;\n\n hasValidLockFile(): boolean {\n return this.getLockFile() !== undefined;\n }\n\n protected getLockFile(): LockFile | undefined {\n if (!this.#lockFileLoaded) {\n this.#lockFile = this.parseLockFile();\n this.#lockFileLoaded = true;\n }\n return this.#lockFile;\n }\n\n protected reset() {\n this.#lockFile = undefined;\n this.#lockFileLoaded = false;\n }\n\n abstract clearCache(): void;\n abstract getDeclaredVersion(query: DeclaredVersionQuery): string | undefined;\n abstract getResolvedVersion(query: ResolvedVersionQuery): string | undefined;\n abstract installPackages(args?: InstallArgs, options?: Parameters<typeof runCommand>[2]): void;\n\n protected abstract parseLockFile(): LockFile | undefined;\n}\n"],"names":["PackageManager","hasValidLockFile","getLockFile","undefined","parseLockFile","reset"],"mappings":";;;;+BAqBsBA;;;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAIlB,yCACA;AALG,MAAeA;IAOlBC,mBAA4B;QACxB,OAAO,IAAI,CAACC,WAAW,OAAOC;IAClC;IAEUD,cAAoC;QAC1C,IAAI,0BAAC,IAAI,EAAC,kBAAiB;2CAClB,WAAY,IAAI,CAACE,aAAa;2CAC9B,iBAAkB;QAC3B;QACA,gCAAO,IAAI,EAAC;IAChB;IAEUC,QAAQ;uCACT,WAAYF;uCACZ,iBAAkB;IAC3B;;QAlBA,gCAAA;;mBAAA,KAAA;;QACA,gCAAA;;mBAAkB;;;AAyBtB"}
1
+ {"version":3,"sources":["../../src/package-manager/package-manager.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'node:path';\nimport { findUp, runCommand } from '../utils';\n\nexport type AllowScripts = true | false | string[];\n\nexport interface InstallArgs {\n allowScripts?: AllowScripts;\n fix?: boolean;\n quiet?: boolean;\n}\n\nexport interface DeclaredVersionQuery {\n workspacePackage: string;\n declaredBy: string;\n dependency: string;\n}\n\nexport interface ResolvedVersionQuery {\n workspacePackage: string;\n dependency: string;\n}\n\nexport abstract class PackageManager<LockFile = unknown> {\n abstract readonly command: string;\n abstract readonly lockFileName: string;\n\n #lockFile: LockFile | undefined;\n #lockFileLoaded = false;\n #lockFilePath: string | undefined;\n #lockFilePathLoaded = false;\n\n hasValidLockFile(): boolean {\n return this.getLockFile() !== undefined;\n }\n\n getLockFilePath(): string | undefined {\n if (!this.#lockFilePathLoaded) {\n this.#lockFilePath = findUp(directory => {\n const candidate = path.join(directory, this.lockFileName);\n return fs.existsSync(candidate) ? candidate : undefined;\n });\n this.#lockFilePathLoaded = true;\n }\n return this.#lockFilePath;\n }\n\n /**\n * Returns the lockfile key for a package given its absolute or\n * cwd-relative directory. Both npm and pnpm key their lockfile entries\n * by the package's path relative to the workspace root.\n */\n getWorkspacePackage(packageDir = process.cwd()): string {\n const lockFilePath = this.getLockFilePath();\n if (!lockFilePath) {\n return this.rootWorkspacePackage;\n }\n const relative = path\n .relative(path.dirname(lockFilePath), path.resolve(packageDir))\n .split(path.sep)\n .join('/');\n return relative === '' ? this.rootWorkspacePackage : relative;\n }\n\n protected getLockFile(): LockFile | undefined {\n if (!this.#lockFileLoaded) {\n this.#lockFile = this.parseLockFile();\n this.#lockFileLoaded = true;\n }\n return this.#lockFile;\n }\n\n protected reset() {\n this.#lockFile = undefined;\n this.#lockFileLoaded = false;\n this.#lockFilePath = undefined;\n this.#lockFilePathLoaded = false;\n }\n\n protected get rootWorkspacePackage(): string {\n return '';\n }\n\n abstract clearCache(): void;\n abstract getDeclaredVersion(query: DeclaredVersionQuery): string | undefined;\n abstract getResolvedVersion(query: ResolvedVersionQuery): string | undefined;\n abstract installPackages(args?: InstallArgs, options?: Parameters<typeof runCommand>[2]): void;\n\n protected abstract parseLockFile(): LockFile | undefined;\n}\n"],"names":["PackageManager","hasValidLockFile","getLockFile","undefined","getLockFilePath","findUp","directory","candidate","path","join","lockFileName","fs","existsSync","getWorkspacePackage","packageDir","process","cwd","lockFilePath","rootWorkspacePackage","relative","dirname","resolve","split","sep","parseLockFile","reset"],"mappings":";;;;+BAuBsBA;;;eAAAA;;;2DAvBP;iEACE;uBACkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAyB/B,yCACA,+CACA,6CACA;AAPG,MAAeA;IASlBC,mBAA4B;QACxB,OAAO,IAAI,CAACC,WAAW,OAAOC;IAClC;IAEAC,kBAAsC;QAClC,IAAI,0BAAC,IAAI,EAAC,sBAAqB;2CACtB,eAAgBC,IAAAA,aAAM,EAACC,CAAAA;gBACxB,MAAMC,YAAYC,iBAAI,CAACC,IAAI,CAACH,WAAW,IAAI,CAACI,YAAY;gBACxD,OAAOC,WAAE,CAACC,UAAU,CAACL,aAAaA,YAAYJ;YAClD;2CACK,qBAAsB;QAC/B;QACA,gCAAO,IAAI,EAAC;IAChB;IAEA;;;;KAIC,GACDU,oBAAoBC,aAAaC,QAAQC,GAAG,EAAE,EAAU;QACpD,MAAMC,eAAe,IAAI,CAACb,eAAe;QACzC,IAAI,CAACa,cAAc;YACf,OAAO,IAAI,CAACC,oBAAoB;QACpC;QACA,MAAMC,WAAWX,iBAAI,CAChBW,QAAQ,CAACX,iBAAI,CAACY,OAAO,CAACH,eAAeT,iBAAI,CAACa,OAAO,CAACP,aAClDQ,KAAK,CAACd,iBAAI,CAACe,GAAG,EACdd,IAAI,CAAC;QACV,OAAOU,aAAa,KAAK,IAAI,CAACD,oBAAoB,GAAGC;IACzD;IAEUjB,cAAoC;QAC1C,IAAI,0BAAC,IAAI,EAAC,kBAAiB;2CAClB,WAAY,IAAI,CAACsB,aAAa;2CAC9B,iBAAkB;QAC3B;QACA,gCAAO,IAAI,EAAC;IAChB;IAEUC,QAAQ;uCACT,WAAYtB;uCACZ,iBAAkB;uCAClB,eAAgBA;uCAChB,qBAAsB;IAC/B;IAEA,IAAce,uBAA+B;QACzC,OAAO;IACX;;QAtDA,gCAAA;;mBAAA,KAAA;;QACA,gCAAA;;mBAAkB;;QAClB,gCAAA;;mBAAA,KAAA;;QACA,gCAAA;;mBAAsB;;;AA2D1B"}
@@ -21,6 +21,7 @@ export interface PnpmLockFile {
21
21
  export declare class PnpmPackageManager extends PackageManager<PnpmLockFile> {
22
22
  readonly command = "pnpm";
23
23
  readonly lockFileName = "pnpm-lock.yaml";
24
+ protected get rootWorkspacePackage(): string;
24
25
  clearCache(): void;
25
26
  getDeclaredVersion({ workspacePackage, declaredBy, dependency, }: DeclaredVersionQuery): string | undefined;
26
27
  getResolvedVersion({ workspacePackage, dependency }: ResolvedVersionQuery): string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"pnpm-package-manager.d.ts","sourceRoot":"","sources":["../../src/package-manager/pnpm-package-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,UAAU,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,oBAAoB,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACjG,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,UAAU,iBAAiB;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,YAAY;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACjD,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACpD,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;CAC5D;AAED,UAAU,YAAY;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,YAAY;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CAC5C;AAED,qBAAa,kBAAmB,SAAQ,cAAc,CAAC,YAAY,CAAC;IAChE,QAAQ,CAAC,OAAO,UAAU;IAC1B,QAAQ,CAAC,YAAY,oBAAoB;IAEzC,UAAU;IAIV,kBAAkB,CAAC,EACf,gBAAgB,EAChB,UAAU,EACV,UAAU,GACb,EAAE,oBAAoB,GAAG,MAAM,GAAG,SAAS;IAS5C,kBAAkB,CAAC,EAAE,gBAAgB,EAAE,UAAU,EAAE,EAAE,oBAAoB,GAAG,MAAM,GAAG,SAAS;IAI9F,eAAe,CAAC,IAAI,GAAE,WAAgB,EAAE,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;IAgBlF,SAAS,CAAC,aAAa,IAAI,YAAY,GAAG,SAAS;IAanD,OAAO,CAAC,cAAc;CAQzB"}
1
+ {"version":3,"file":"pnpm-package-manager.d.ts","sourceRoot":"","sources":["../../src/package-manager/pnpm-package-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,UAAU,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,oBAAoB,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACjG,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,UAAU,iBAAiB;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,YAAY;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACjD,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACpD,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;CAC5D;AAED,UAAU,YAAY;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,YAAY;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CAC5C;AAED,qBAAa,kBAAmB,SAAQ,cAAc,CAAC,YAAY,CAAC;IAChE,QAAQ,CAAC,OAAO,UAAU;IAC1B,QAAQ,CAAC,YAAY,oBAAoB;IAEzC,cAAuB,oBAAoB,IAAI,MAAM,CAEpD;IAED,UAAU;IAIV,kBAAkB,CAAC,EACf,gBAAgB,EAChB,UAAU,EACV,UAAU,GACb,EAAE,oBAAoB,GAAG,MAAM,GAAG,SAAS;IAS5C,kBAAkB,CAAC,EAAE,gBAAgB,EAAE,UAAU,EAAE,EAAE,oBAAoB,GAAG,MAAM,GAAG,SAAS;IAI9F,eAAe,CAAC,IAAI,GAAE,WAAgB,EAAE,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;IAgBlF,SAAS,CAAC,aAAa,IAAI,YAAY,GAAG,SAAS;IAiBnD,OAAO,CAAC,cAAc;CAQzB"}
@@ -30,8 +30,11 @@ function _interop_require_default(obj) {
30
30
  };
31
31
  }
32
32
  class PnpmPackageManager extends _packagemanager.PackageManager {
33
+ get rootWorkspacePackage() {
34
+ return '.';
35
+ }
33
36
  clearCache() {
34
- (0, _utils.runCommand)('pnpm', [
37
+ (0, _utils.runCommand)(this.command, [
35
38
  'store',
36
39
  'prune'
37
40
  ]);
@@ -51,7 +54,7 @@ class PnpmPackageManager extends _packagemanager.PackageManager {
51
54
  }
52
55
  installPackages(args = {}, options) {
53
56
  try {
54
- (0, _utils.runCommand)('pnpm', [
57
+ (0, _utils.runCommand)(this.command, [
55
58
  'install',
56
59
  ...(0, _utils.isCI)() ? [
57
60
  '--frozen-lockfile'
@@ -65,12 +68,16 @@ class PnpmPackageManager extends _packagemanager.PackageManager {
65
68
  }
66
69
  }
67
70
  parseLockFile() {
71
+ const lockFilePath = this.getLockFilePath();
72
+ if (!lockFilePath) {
73
+ return undefined;
74
+ }
68
75
  /*
69
76
  * js-yaml is an optional peer; let MODULE_NOT_FOUND surface so a caller
70
77
  * missing the dep gets a clear error instead of silent `undefined`.
71
78
  */ const yaml = require('js-yaml');
72
79
  try {
73
- return yaml.load(_fs.default.readFileSync(this.lockFileName, 'utf-8'));
80
+ return yaml.load(_fs.default.readFileSync(lockFilePath, 'utf-8'));
74
81
  } catch (unused) {
75
82
  return undefined;
76
83
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/package-manager/pnpm-package-manager.ts"],"sourcesContent":["import fs from 'fs';\nimport { isCI, runCommand } from '../utils';\nimport type { DeclaredVersionQuery, InstallArgs, ResolvedVersionQuery } from './package-manager';\nimport { PackageManager } from './package-manager';\n\ninterface PnpmImporterEntry {\n specifier: string;\n version: string;\n}\n\ninterface PnpmImporter {\n dependencies?: Record<string, PnpmImporterEntry>;\n devDependencies?: Record<string, PnpmImporterEntry>;\n optionalDependencies?: Record<string, PnpmImporterEntry>;\n}\n\ninterface PnpmSnapshot {\n dependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n}\n\nexport interface PnpmLockFile {\n importers?: Record<string, PnpmImporter>;\n snapshots?: Record<string, PnpmSnapshot>;\n}\n\nexport class PnpmPackageManager extends PackageManager<PnpmLockFile> {\n readonly command = 'pnpm';\n readonly lockFileName = 'pnpm-lock.yaml';\n\n clearCache() {\n runCommand('pnpm', ['store', 'prune']);\n }\n\n getDeclaredVersion({\n workspacePackage,\n declaredBy,\n dependency,\n }: DeclaredVersionQuery): string | undefined {\n const declaredByVersion = this.resolveVersion(workspacePackage, declaredBy);\n if (!declaredByVersion) {\n return undefined;\n }\n const snapshot = this.getLockFile()?.snapshots?.[`${declaredBy}@${declaredByVersion}`];\n return snapshot?.dependencies?.[dependency] ?? snapshot?.peerDependencies?.[dependency];\n }\n\n getResolvedVersion({ workspacePackage, dependency }: ResolvedVersionQuery): string | undefined {\n return this.resolveVersion(workspacePackage, dependency);\n }\n\n installPackages(args: InstallArgs = {}, options?: Parameters<typeof runCommand>[2]) {\n try {\n runCommand(\n 'pnpm',\n [\n 'install',\n ...(isCI() ? ['--frozen-lockfile'] : []),\n ...(args.fix ? ['--lockfile-only'] : []),\n ],\n options\n );\n } finally {\n this.reset();\n }\n }\n\n protected parseLockFile(): PnpmLockFile | undefined {\n /*\n * js-yaml is an optional peer; let MODULE_NOT_FOUND surface so a caller\n * missing the dep gets a clear error instead of silent `undefined`.\n */\n const yaml = require('js-yaml');\n try {\n return yaml.load(fs.readFileSync(this.lockFileName, 'utf-8'));\n } catch {\n return undefined;\n }\n }\n\n private resolveVersion(workspacePackage: string, dependency: string): string | undefined {\n const importer = this.getLockFile()?.importers?.[workspacePackage];\n const entry =\n importer?.dependencies?.[dependency] ??\n importer?.devDependencies?.[dependency] ??\n importer?.optionalDependencies?.[dependency];\n return entry ? stripPeerDependencySuffix(entry.version) : undefined;\n }\n}\n\nfunction stripPeerDependencySuffix(version: string): string {\n // e.g., \"1.2.3(react@18.2.0)(react-dom@18.2.0)\" → \"1.2.3\"\n return version.split('(')[0];\n}\n"],"names":["PnpmPackageManager","PackageManager","clearCache","runCommand","getDeclaredVersion","workspacePackage","declaredBy","dependency","snapshot","declaredByVersion","resolveVersion","undefined","getLockFile","snapshots","dependencies","peerDependencies","getResolvedVersion","installPackages","args","options","isCI","fix","reset","parseLockFile","yaml","require","load","fs","readFileSync","lockFileName","importer","importers","entry","devDependencies","optionalDependencies","stripPeerDependencySuffix","version","command","split"],"mappings":";;;;+BA0BaA;;;eAAAA;;;2DA1BE;uBACkB;gCAEF;;;;;;;;;;;;;;;;;;;AAuBxB,MAAMA,2BAA2BC,8BAAc;IAIlDC,aAAa;QACTC,IAAAA,iBAAU,EAAC,QAAQ;YAAC;YAAS;SAAQ;IACzC;IAEAC,mBAAmB,EACfC,gBAAgB,EAChBC,UAAU,EACVC,UAAU,EACS,EAAsB;;YAKxB,6BAAA,mBACVC,wBAAwCA;QAL/C,MAAMC,oBAAoB,IAAI,CAACC,cAAc,CAACL,kBAAkBC;QAChE,IAAI,CAACG,mBAAmB;YACpB,OAAOE;QACX;QACA,MAAMH,YAAW,oBAAA,IAAI,CAACI,WAAW,gBAAhB,yCAAA,8BAAA,kBAAoBC,SAAS,cAA7B,kDAAA,2BAA+B,CAAC,GAAGP,WAAW,CAAC,EAAEG,mBAAmB,CAAC;QACtF,eAAOD,qBAAAA,gCAAAA,yBAAAA,SAAUM,YAAY,cAAtBN,6CAAAA,sBAAwB,CAACD,WAAW,uCAAIC,qBAAAA,gCAAAA,6BAAAA,SAAUO,gBAAgB,cAA1BP,iDAAAA,0BAA4B,CAACD,WAAW;IAC3F;IAEAS,mBAAmB,EAAEX,gBAAgB,EAAEE,UAAU,EAAwB,EAAsB;QAC3F,OAAO,IAAI,CAACG,cAAc,CAACL,kBAAkBE;IACjD;IAEAU,gBAAgBC,OAAoB,CAAC,CAAC,EAAEC,OAA0C,EAAE;QAChF,IAAI;YACAhB,IAAAA,iBAAU,EACN,QACA;gBACI;mBACIiB,IAAAA,WAAI,MAAK;oBAAC;iBAAoB,GAAG,EAAE;mBACnCF,KAAKG,GAAG,GAAG;oBAAC;iBAAkB,GAAG,EAAE;aAC1C,EACDF;QAER,SAAU;YACN,IAAI,CAACG,KAAK;QACd;IACJ;IAEUC,gBAA0C;QAChD;;;SAGC,GACD,MAAMC,OAAOC,QAAQ;QACrB,IAAI;YACA,OAAOD,KAAKE,IAAI,CAACC,WAAE,CAACC,YAAY,CAAC,IAAI,CAACC,YAAY,EAAE;QACxD,EAAE,eAAM;YACJ,OAAOlB;QACX;IACJ;IAEQD,eAAeL,gBAAwB,EAAEE,UAAkB,EAAsB;YAGjFuB;YAFa,6BAAA,mBAEbA,wBACAA,2BACAA;QAJJ,MAAMA,YAAW,oBAAA,IAAI,CAAClB,WAAW,gBAAhB,yCAAA,8BAAA,kBAAoBmB,SAAS,cAA7B,kDAAA,2BAA+B,CAAC1B,iBAAiB;QAClE,MAAM2B,SACFF,gBAAAA,qBAAAA,gCAAAA,yBAAAA,SAAUhB,YAAY,cAAtBgB,6CAAAA,sBAAwB,CAACvB,WAAW,yCACpCuB,qBAAAA,gCAAAA,4BAAAA,SAAUG,eAAe,cAAzBH,gDAAAA,yBAA2B,CAACvB,WAAW,cADvCuB,kBAAAA,OAEAA,qBAAAA,gCAAAA,iCAAAA,SAAUI,oBAAoB,cAA9BJ,qDAAAA,8BAAgC,CAACvB,WAAW;QAChD,OAAOyB,QAAQG,0BAA0BH,MAAMI,OAAO,IAAIzB;IAC9D;;QA7DG,gBACH,uBAAS0B,WAAU,SACnB,uBAASR,gBAAe;;AA4D5B;AAEA,SAASM,0BAA0BC,OAAe;IAC9C,0DAA0D;IAC1D,OAAOA,QAAQE,KAAK,CAAC,IAAI,CAAC,EAAE;AAChC"}
1
+ {"version":3,"sources":["../../src/package-manager/pnpm-package-manager.ts"],"sourcesContent":["import fs from 'fs';\nimport { isCI, runCommand } from '../utils';\nimport type { DeclaredVersionQuery, InstallArgs, ResolvedVersionQuery } from './package-manager';\nimport { PackageManager } from './package-manager';\n\ninterface PnpmImporterEntry {\n specifier: string;\n version: string;\n}\n\ninterface PnpmImporter {\n dependencies?: Record<string, PnpmImporterEntry>;\n devDependencies?: Record<string, PnpmImporterEntry>;\n optionalDependencies?: Record<string, PnpmImporterEntry>;\n}\n\ninterface PnpmSnapshot {\n dependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n}\n\nexport interface PnpmLockFile {\n importers?: Record<string, PnpmImporter>;\n snapshots?: Record<string, PnpmSnapshot>;\n}\n\nexport class PnpmPackageManager extends PackageManager<PnpmLockFile> {\n readonly command = 'pnpm';\n readonly lockFileName = 'pnpm-lock.yaml';\n\n protected override get rootWorkspacePackage(): string {\n return '.';\n }\n\n clearCache() {\n runCommand(this.command, ['store', 'prune']);\n }\n\n getDeclaredVersion({\n workspacePackage,\n declaredBy,\n dependency,\n }: DeclaredVersionQuery): string | undefined {\n const declaredByVersion = this.resolveVersion(workspacePackage, declaredBy);\n if (!declaredByVersion) {\n return undefined;\n }\n const snapshot = this.getLockFile()?.snapshots?.[`${declaredBy}@${declaredByVersion}`];\n return snapshot?.dependencies?.[dependency] ?? snapshot?.peerDependencies?.[dependency];\n }\n\n getResolvedVersion({ workspacePackage, dependency }: ResolvedVersionQuery): string | undefined {\n return this.resolveVersion(workspacePackage, dependency);\n }\n\n installPackages(args: InstallArgs = {}, options?: Parameters<typeof runCommand>[2]) {\n try {\n runCommand(\n this.command,\n [\n 'install',\n ...(isCI() ? ['--frozen-lockfile'] : []),\n ...(args.fix ? ['--lockfile-only'] : []),\n ],\n options\n );\n } finally {\n this.reset();\n }\n }\n\n protected parseLockFile(): PnpmLockFile | undefined {\n const lockFilePath = this.getLockFilePath();\n if (!lockFilePath) {\n return undefined;\n }\n /*\n * js-yaml is an optional peer; let MODULE_NOT_FOUND surface so a caller\n * missing the dep gets a clear error instead of silent `undefined`.\n */\n const yaml = require('js-yaml');\n try {\n return yaml.load(fs.readFileSync(lockFilePath, 'utf-8'));\n } catch {\n return undefined;\n }\n }\n\n private resolveVersion(workspacePackage: string, dependency: string): string | undefined {\n const importer = this.getLockFile()?.importers?.[workspacePackage];\n const entry =\n importer?.dependencies?.[dependency] ??\n importer?.devDependencies?.[dependency] ??\n importer?.optionalDependencies?.[dependency];\n return entry ? stripPeerDependencySuffix(entry.version) : undefined;\n }\n}\n\nfunction stripPeerDependencySuffix(version: string): string {\n // e.g., \"1.2.3(react@18.2.0)(react-dom@18.2.0)\" → \"1.2.3\"\n return version.split('(')[0];\n}\n"],"names":["PnpmPackageManager","PackageManager","rootWorkspacePackage","clearCache","runCommand","command","getDeclaredVersion","workspacePackage","declaredBy","dependency","snapshot","declaredByVersion","resolveVersion","undefined","getLockFile","snapshots","dependencies","peerDependencies","getResolvedVersion","installPackages","args","options","isCI","fix","reset","parseLockFile","lockFilePath","getLockFilePath","yaml","require","load","fs","readFileSync","importer","importers","entry","devDependencies","optionalDependencies","stripPeerDependencySuffix","version","lockFileName","split"],"mappings":";;;;+BA0BaA;;;eAAAA;;;2DA1BE;uBACkB;gCAEF;;;;;;;;;;;;;;;;;;;AAuBxB,MAAMA,2BAA2BC,8BAAc;IAIlD,IAAuBC,uBAA+B;QAClD,OAAO;IACX;IAEAC,aAAa;QACTC,IAAAA,iBAAU,EAAC,IAAI,CAACC,OAAO,EAAE;YAAC;YAAS;SAAQ;IAC/C;IAEAC,mBAAmB,EACfC,gBAAgB,EAChBC,UAAU,EACVC,UAAU,EACS,EAAsB;;YAKxB,6BAAA,mBACVC,wBAAwCA;QAL/C,MAAMC,oBAAoB,IAAI,CAACC,cAAc,CAACL,kBAAkBC;QAChE,IAAI,CAACG,mBAAmB;YACpB,OAAOE;QACX;QACA,MAAMH,YAAW,oBAAA,IAAI,CAACI,WAAW,gBAAhB,yCAAA,8BAAA,kBAAoBC,SAAS,cAA7B,kDAAA,2BAA+B,CAAC,GAAGP,WAAW,CAAC,EAAEG,mBAAmB,CAAC;QACtF,eAAOD,qBAAAA,gCAAAA,yBAAAA,SAAUM,YAAY,cAAtBN,6CAAAA,sBAAwB,CAACD,WAAW,uCAAIC,qBAAAA,gCAAAA,6BAAAA,SAAUO,gBAAgB,cAA1BP,iDAAAA,0BAA4B,CAACD,WAAW;IAC3F;IAEAS,mBAAmB,EAAEX,gBAAgB,EAAEE,UAAU,EAAwB,EAAsB;QAC3F,OAAO,IAAI,CAACG,cAAc,CAACL,kBAAkBE;IACjD;IAEAU,gBAAgBC,OAAoB,CAAC,CAAC,EAAEC,OAA0C,EAAE;QAChF,IAAI;YACAjB,IAAAA,iBAAU,EACN,IAAI,CAACC,OAAO,EACZ;gBACI;mBACIiB,IAAAA,WAAI,MAAK;oBAAC;iBAAoB,GAAG,EAAE;mBACnCF,KAAKG,GAAG,GAAG;oBAAC;iBAAkB,GAAG,EAAE;aAC1C,EACDF;QAER,SAAU;YACN,IAAI,CAACG,KAAK;QACd;IACJ;IAEUC,gBAA0C;QAChD,MAAMC,eAAe,IAAI,CAACC,eAAe;QACzC,IAAI,CAACD,cAAc;YACf,OAAOb;QACX;QACA;;;SAGC,GACD,MAAMe,OAAOC,QAAQ;QACrB,IAAI;YACA,OAAOD,KAAKE,IAAI,CAACC,WAAE,CAACC,YAAY,CAACN,cAAc;QACnD,EAAE,eAAM;YACJ,OAAOb;QACX;IACJ;IAEQD,eAAeL,gBAAwB,EAAEE,UAAkB,EAAsB;YAGjFwB;YAFa,6BAAA,mBAEbA,wBACAA,2BACAA;QAJJ,MAAMA,YAAW,oBAAA,IAAI,CAACnB,WAAW,gBAAhB,yCAAA,8BAAA,kBAAoBoB,SAAS,cAA7B,kDAAA,2BAA+B,CAAC3B,iBAAiB;QAClE,MAAM4B,SACFF,gBAAAA,qBAAAA,gCAAAA,yBAAAA,SAAUjB,YAAY,cAAtBiB,6CAAAA,sBAAwB,CAACxB,WAAW,yCACpCwB,qBAAAA,gCAAAA,4BAAAA,SAAUG,eAAe,cAAzBH,gDAAAA,yBAA2B,CAACxB,WAAW,cADvCwB,kBAAAA,OAEAA,qBAAAA,gCAAAA,iCAAAA,SAAUI,oBAAoB,cAA9BJ,qDAAAA,8BAAgC,CAACxB,WAAW;QAChD,OAAO0B,QAAQG,0BAA0BH,MAAMI,OAAO,IAAI1B;IAC9D;;QArEG,gBACH,uBAASR,WAAU,SACnB,uBAASmC,gBAAe;;AAoE5B;AAEA,SAASF,0BAA0BC,OAAe;IAC9C,0DAA0D;IAC1D,OAAOA,QAAQE,KAAK,CAAC,IAAI,CAAC,EAAE;AAChC"}
@@ -1 +1 @@
1
- {"version":3,"file":"get-packages-with-install-scripts.d.ts","sourceRoot":"","sources":["../../src/utils/get-packages-with-install-scripts.ts"],"names":[],"mappings":"AAEA,UAAU,iBAAiB;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACnB;AAMD,wBAAgB,6BAA6B,IAAI,iBAAiB,EAAE,CAWnE"}
1
+ {"version":3,"file":"get-packages-with-install-scripts.d.ts","sourceRoot":"","sources":["../../src/utils/get-packages-with-install-scripts.ts"],"names":[],"mappings":"AAEA,UAAU,iBAAiB;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACnB;AAWD,wBAAgB,6BAA6B,IAAI,iBAAiB,EAAE,CAWnE"}
@@ -9,11 +9,15 @@ Object.defineProperty(exports, "getPackagesWithInstallScripts", {
9
9
  }
10
10
  });
11
11
  const _os = require("./os");
12
- const SELECTORS = [
12
+ /*
13
+ * Keep this selector free of whitespace. On Windows npm runs through a shell (npm.CMD) and
14
+ * execFileSync passes args unquoted, so a space would split the selector at the shell and npm
15
+ * query would receive a truncated, invalid selector.
16
+ */ const SELECTORS = [
13
17
  'preinstall',
14
18
  'install',
15
19
  'postinstall'
16
- ].map((script)=>`:attr(scripts, [${script}])`).join(', ');
20
+ ].map((script)=>`:attr(scripts,[${script}])`).join(',');
17
21
  function getPackagesWithInstallScripts() {
18
22
  try {
19
23
  const result = (0, _os.runCommand)('npm', [
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/get-packages-with-install-scripts.ts"],"sourcesContent":["import { runCommand } from './os';\n\ninterface PackageWithScript {\n location: string;\n name: string;\n version: string;\n}\n\nconst SELECTORS = ['preinstall', 'install', 'postinstall']\n .map(script => `:attr(scripts, [${script}])`)\n .join(', ');\n\nexport function getPackagesWithInstallScripts(): PackageWithScript[] {\n try {\n const result = runCommand('npm', ['query', SELECTORS, '--json']);\n return JSON.parse(result).map(({ location, name, version }: PackageWithScript) => ({\n location,\n name,\n version,\n }));\n } catch {\n return [];\n }\n}\n"],"names":["getPackagesWithInstallScripts","SELECTORS","map","script","join","result","runCommand","JSON","parse","location","name","version"],"mappings":";;;;+BAYgBA;;;eAAAA;;;oBAZW;AAQ3B,MAAMC,YAAY;IAAC;IAAc;IAAW;CAAc,CACrDC,GAAG,CAACC,CAAAA,SAAU,CAAC,gBAAgB,EAAEA,OAAO,EAAE,CAAC,EAC3CC,IAAI,CAAC;AAEH,SAASJ;IACZ,IAAI;QACA,MAAMK,SAASC,IAAAA,cAAU,EAAC,OAAO;YAAC;YAASL;YAAW;SAAS;QAC/D,OAAOM,KAAKC,KAAK,CAACH,QAAQH,GAAG,CAAC,CAAC,EAAEO,QAAQ,EAAEC,IAAI,EAAEC,OAAO,EAAqB,GAAM,CAAA;gBAC/EF;gBACAC;gBACAC;YACJ,CAAA;IACJ,EAAE,eAAM;QACJ,OAAO,EAAE;IACb;AACJ"}
1
+ {"version":3,"sources":["../../src/utils/get-packages-with-install-scripts.ts"],"sourcesContent":["import { runCommand } from './os';\n\ninterface PackageWithScript {\n location: string;\n name: string;\n version: string;\n}\n\n/*\n * Keep this selector free of whitespace. On Windows npm runs through a shell (npm.CMD) and\n * execFileSync passes args unquoted, so a space would split the selector at the shell and npm\n * query would receive a truncated, invalid selector.\n */\nconst SELECTORS = ['preinstall', 'install', 'postinstall']\n .map(script => `:attr(scripts,[${script}])`)\n .join(',');\n\nexport function getPackagesWithInstallScripts(): PackageWithScript[] {\n try {\n const result = runCommand('npm', ['query', SELECTORS, '--json']);\n return JSON.parse(result).map(({ location, name, version }: PackageWithScript) => ({\n location,\n name,\n version,\n }));\n } catch {\n return [];\n }\n}\n"],"names":["getPackagesWithInstallScripts","SELECTORS","map","script","join","result","runCommand","JSON","parse","location","name","version"],"mappings":";;;;+BAiBgBA;;;eAAAA;;;oBAjBW;AAQ3B;;;;CAIC,GACD,MAAMC,YAAY;IAAC;IAAc;IAAW;CAAc,CACrDC,GAAG,CAACC,CAAAA,SAAU,CAAC,eAAe,EAAEA,OAAO,EAAE,CAAC,EAC1CC,IAAI,CAAC;AAEH,SAASJ;IACZ,IAAI;QACA,MAAMK,SAASC,IAAAA,cAAU,EAAC,OAAO;YAAC;YAASL;YAAW;SAAS;QAC/D,OAAOM,KAAKC,KAAK,CAACH,QAAQH,GAAG,CAAC,CAAC,EAAEO,QAAQ,EAAEC,IAAI,EAAEC,OAAO,EAAqB,GAAM,CAAA;gBAC/EF;gBACAC;gBACAC;YACJ,CAAA;IACJ,EAAE,eAAM;QACJ,OAAO,EAAE;IACb;AACJ"}
@@ -4,7 +4,6 @@ export * from './find-up';
4
4
  export * from './get-packages-with-install-scripts';
5
5
  export * from './get-version';
6
6
  export * from './git';
7
- export * from './has-lockfile-changed';
8
7
  export * from './npm';
9
8
  export * from './os';
10
9
  export * from './read-json';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,MAAM,CAAC;AACrB,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,qCAAqC,CAAC;AACpD,cAAc,eAAe,CAAC;AAC9B,cAAc,OAAO,CAAC;AACtB,cAAc,wBAAwB,CAAC;AACvC,cAAc,OAAO,CAAC;AACtB,cAAc,MAAM,CAAC;AACrB,cAAc,aAAa,CAAC;AAC5B,cAAc,kCAAkC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,MAAM,CAAC;AACrB,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,qCAAqC,CAAC;AACpD,cAAc,eAAe,CAAC;AAC9B,cAAc,OAAO,CAAC;AACtB,cAAc,OAAO,CAAC;AACtB,cAAc,MAAM,CAAC;AACrB,cAAc,aAAa,CAAC;AAC5B,cAAc,kCAAkC,CAAC"}
@@ -8,7 +8,6 @@ _export_star(require("./find-up"), exports);
8
8
  _export_star(require("./get-packages-with-install-scripts"), exports);
9
9
  _export_star(require("./get-version"), exports);
10
10
  _export_star(require("./git"), exports);
11
- _export_star(require("./has-lockfile-changed"), exports);
12
11
  _export_star(require("./npm"), exports);
13
12
  _export_star(require("./os"), exports);
14
13
  _export_star(require("./read-json"), exports);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/index.ts"],"sourcesContent":["export * from './ci';\nexport * from './debug';\nexport * from './find-up';\nexport * from './get-packages-with-install-scripts';\nexport * from './get-version';\nexport * from './git';\nexport * from './has-lockfile-changed';\nexport * from './npm';\nexport * from './os';\nexport * from './read-json';\nexport * from './warn-untrusted-install-scripts';\n"],"names":[],"mappings":";;;;qBAAc;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA"}
1
+ {"version":3,"sources":["../../src/utils/index.ts"],"sourcesContent":["export * from './ci';\nexport * from './debug';\nexport * from './find-up';\nexport * from './get-packages-with-install-scripts';\nexport * from './get-version';\nexport * from './git';\nexport * from './npm';\nexport * from './os';\nexport * from './read-json';\nexport * from './warn-untrusted-install-scripts';\n"],"names":[],"mappings":";;;;qBAAc;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA"}
@@ -1,6 +1,2 @@
1
- interface Options {
2
- force?: boolean;
3
- }
4
- export declare function warnUntrustedInstallScripts(allowedScripts: string[], lockFileName: string, { force }?: Options): void;
5
- export {};
1
+ export declare function warnUntrustedInstallScripts(allowedScripts: string[]): void;
6
2
  //# sourceMappingURL=warn-untrusted-install-scripts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"warn-untrusted-install-scripts.d.ts","sourceRoot":"","sources":["../../src/utils/warn-untrusted-install-scripts.ts"],"names":[],"mappings":"AAuBA,UAAU,OAAO;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,2BAA2B,CACvC,cAAc,EAAE,MAAM,EAAE,EACxB,YAAY,EAAE,MAAM,EACpB,EAAE,KAAK,EAAE,GAAE,OAAY,QAyB1B"}
1
+ {"version":3,"file":"warn-untrusted-install-scripts.d.ts","sourceRoot":"","sources":["../../src/utils/warn-untrusted-install-scripts.ts"],"names":[],"mappings":"AAsBA,wBAAgB,2BAA2B,CAAC,cAAc,EAAE,MAAM,EAAE,QAmBnE"}
@@ -9,7 +9,6 @@ Object.defineProperty(exports, "warnUntrustedInstallScripts", {
9
9
  }
10
10
  });
11
11
  const _getpackageswithinstallscripts = require("./get-packages-with-install-scripts");
12
- const _haslockfilechanged = require("./has-lockfile-changed");
13
12
  // These packages have scripts, but don't need them to function correctly.
14
13
  const IGNORE = [
15
14
  '@parcel/watcher',
@@ -27,10 +26,7 @@ const IGNORE = [
27
26
  'tree-sitter-json',
28
27
  'unrs-resolver'
29
28
  ];
30
- function warnUntrustedInstallScripts(allowedScripts, lockFileName, { force } = {}) {
31
- if (!force && !(0, _haslockfilechanged.hasLockfileChanged)(lockFileName)) {
32
- return;
33
- }
29
+ function warnUntrustedInstallScripts(allowedScripts) {
34
30
  const packages = (0, _getpackageswithinstallscripts.getPackagesWithInstallScripts)();
35
31
  const trustedOrIgnored = new Set([
36
32
  ...allowedScripts,
@@ -45,7 +41,6 @@ function warnUntrustedInstallScripts(allowedScripts, lockFileName, { force } = {
45
41
  const list = untrusted.map(({ name, version })=>` - ${name}@${version}`).join('\n');
46
42
  console.warn([
47
43
  'WARNING: The following packages have untrusted install scripts.',
48
- 'A future release will block them by default.',
49
44
  'Review and add trusted packages to --allow-scripts:',
50
45
  list
51
46
  ].join('\n'));
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/warn-untrusted-install-scripts.ts"],"sourcesContent":["/* eslint-disable no-console */\nimport { getPackagesWithInstallScripts } from './get-packages-with-install-scripts';\nimport { hasLockfileChanged } from './has-lockfile-changed';\n\n// These packages have scripts, but don't need them to function correctly.\n\nconst IGNORE = [\n '@parcel/watcher', // Installs platform-specific binary via optionalDependencies, install script is a legacy fallback\n '@progress/kendo-licensing', // Validates Kendo UI license key, not needed for functionality\n '@scarf/scarf', // Sends anonymous analytics/telemetry to Scarf, usage-tracking mechanism with no functional purpose\n '@swc/core', // Installs platform-specific binary via optionalDependencies, postinstall is a legacy fallback\n '@tree-sitter-grammars/tree-sitter-yaml', // Ships prebuilds for all supported targets via node-gyp-build, install script is a source-compile fallback\n '@vaadin/vaadin-usage-statistics', // Toggles Vaadin's development-time telemetry, no effect on functionality\n 'contentful', // v9 printed a message announcing that v10 was available, no functional purpose\n 'core-js-pure', // Prints a donation/sponsorship banner to the console, no functional purpose\n 'core-js', // Prints a donation/sponsorship banner to the console, no functional purpose\n 'es5-ext', // Displays politically motivated message targeted at Russian developers, no effect on functionality\n 'esbuild', // Installs platform-specific binary via optionalDependencies, postinstall is a legacy fallback\n 'less', // Installs Playwright browsers for Less's own test suite\n 'tree-sitter-json', // Ships prebuilds for all supported targets via node-gyp-build, install script is a source-compile fallback\n 'unrs-resolver', // Installs platform-specific binary via optionalDependencies, postinstall is a legacy fallback\n];\n\ninterface Options {\n force?: boolean;\n}\n\nexport function warnUntrustedInstallScripts(\n allowedScripts: string[],\n lockFileName: string,\n { force }: Options = {}\n) {\n if (!force && !hasLockfileChanged(lockFileName)) {\n return;\n }\n\n const packages = getPackagesWithInstallScripts();\n const trustedOrIgnored = new Set([...allowedScripts, ...IGNORE]);\n const untrusted = packages.filter(({ location, name }) => {\n return !!location && !trustedOrIgnored.has(name);\n });\n\n if (untrusted.length === 0) {\n return;\n }\n\n const list = untrusted.map(({ name, version }) => ` - ${name}@${version}`).join('\\n');\n console.warn(\n [\n 'WARNING: The following packages have untrusted install scripts.',\n 'A future release will block them by default.',\n 'Review and add trusted packages to --allow-scripts:',\n list,\n ].join('\\n')\n );\n}\n"],"names":["warnUntrustedInstallScripts","IGNORE","allowedScripts","lockFileName","force","hasLockfileChanged","packages","getPackagesWithInstallScripts","trustedOrIgnored","Set","untrusted","filter","location","name","has","length","list","map","version","join","console","warn"],"mappings":"AAAA,6BAA6B;;;;+BA2BbA;;;eAAAA;;;+CA1B8B;oCACX;AAEnC,0EAA0E;AAE1E,MAAMC,SAAS;IACX;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACH;AAMM,SAASD,4BACZE,cAAwB,EACxBC,YAAoB,EACpB,EAAEC,KAAK,EAAW,GAAG,CAAC,CAAC;IAEvB,IAAI,CAACA,SAAS,CAACC,IAAAA,sCAAkB,EAACF,eAAe;QAC7C;IACJ;IAEA,MAAMG,WAAWC,IAAAA,4DAA6B;IAC9C,MAAMC,mBAAmB,IAAIC,IAAI;WAAIP;WAAmBD;KAAO;IAC/D,MAAMS,YAAYJ,SAASK,MAAM,CAAC,CAAC,EAAEC,QAAQ,EAAEC,IAAI,EAAE;QACjD,OAAO,CAAC,CAACD,YAAY,CAACJ,iBAAiBM,GAAG,CAACD;IAC/C;IAEA,IAAIH,UAAUK,MAAM,KAAK,GAAG;QACxB;IACJ;IAEA,MAAMC,OAAON,UAAUO,GAAG,CAAC,CAAC,EAAEJ,IAAI,EAAEK,OAAO,EAAE,GAAK,CAAC,IAAI,EAAEL,KAAK,CAAC,EAAEK,SAAS,EAAEC,IAAI,CAAC;IACjFC,QAAQC,IAAI,CACR;QACI;QACA;QACA;QACAL;KACH,CAACG,IAAI,CAAC;AAEf"}
1
+ {"version":3,"sources":["../../src/utils/warn-untrusted-install-scripts.ts"],"sourcesContent":["/* eslint-disable no-console */\nimport { getPackagesWithInstallScripts } from './get-packages-with-install-scripts';\n\n// These packages have scripts, but don't need them to function correctly.\n\nconst IGNORE = [\n '@parcel/watcher', // Installs platform-specific binary via optionalDependencies, install script is a legacy fallback\n '@progress/kendo-licensing', // Validates Kendo UI license key, not needed for functionality\n '@scarf/scarf', // Sends anonymous analytics/telemetry to Scarf, usage-tracking mechanism with no functional purpose\n '@swc/core', // Installs platform-specific binary via optionalDependencies, postinstall is a legacy fallback\n '@tree-sitter-grammars/tree-sitter-yaml', // Ships prebuilds for all supported targets via node-gyp-build, install script is a source-compile fallback\n '@vaadin/vaadin-usage-statistics', // Toggles Vaadin's development-time telemetry, no effect on functionality\n 'contentful', // v9 printed a message announcing that v10 was available, no functional purpose\n 'core-js-pure', // Prints a donation/sponsorship banner to the console, no functional purpose\n 'core-js', // Prints a donation/sponsorship banner to the console, no functional purpose\n 'es5-ext', // Displays politically motivated message targeted at Russian developers, no effect on functionality\n 'esbuild', // Installs platform-specific binary via optionalDependencies, postinstall is a legacy fallback\n 'less', // Installs Playwright browsers for Less's own test suite\n 'tree-sitter-json', // Ships prebuilds for all supported targets via node-gyp-build, install script is a source-compile fallback\n 'unrs-resolver', // Installs platform-specific binary via optionalDependencies, postinstall is a legacy fallback\n];\n\nexport function warnUntrustedInstallScripts(allowedScripts: string[]) {\n const packages = getPackagesWithInstallScripts();\n const trustedOrIgnored = new Set([...allowedScripts, ...IGNORE]);\n const untrusted = packages.filter(({ location, name }) => {\n return !!location && !trustedOrIgnored.has(name);\n });\n\n if (untrusted.length === 0) {\n return;\n }\n\n const list = untrusted.map(({ name, version }) => ` - ${name}@${version}`).join('\\n');\n console.warn(\n [\n 'WARNING: The following packages have untrusted install scripts.',\n 'Review and add trusted packages to --allow-scripts:',\n list,\n ].join('\\n')\n );\n}\n"],"names":["warnUntrustedInstallScripts","IGNORE","allowedScripts","packages","getPackagesWithInstallScripts","trustedOrIgnored","Set","untrusted","filter","location","name","has","length","list","map","version","join","console","warn"],"mappings":"AAAA,6BAA6B;;;;+BAsBbA;;;eAAAA;;;+CArB8B;AAE9C,0EAA0E;AAE1E,MAAMC,SAAS;IACX;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACH;AAEM,SAASD,4BAA4BE,cAAwB;IAChE,MAAMC,WAAWC,IAAAA,4DAA6B;IAC9C,MAAMC,mBAAmB,IAAIC,IAAI;WAAIJ;WAAmBD;KAAO;IAC/D,MAAMM,YAAYJ,SAASK,MAAM,CAAC,CAAC,EAAEC,QAAQ,EAAEC,IAAI,EAAE;QACjD,OAAO,CAAC,CAACD,YAAY,CAACJ,iBAAiBM,GAAG,CAACD;IAC/C;IAEA,IAAIH,UAAUK,MAAM,KAAK,GAAG;QACxB;IACJ;IAEA,MAAMC,OAAON,UAAUO,GAAG,CAAC,CAAC,EAAEJ,IAAI,EAAEK,OAAO,EAAE,GAAK,CAAC,IAAI,EAAEL,KAAK,CAAC,EAAEK,SAAS,EAAEC,IAAI,CAAC;IACjFC,QAAQC,IAAI,CACR;QACI;QACA;QACAL;KACH,CAACG,IAAI,CAAC;AAEf"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@servicetitan/install",
3
- "version": "36.3.0",
3
+ "version": "36.4.0",
4
4
  "description": "Lightweight wrapper around npm install that configures access to private packages",
5
5
  "homepage": "https://docs.st.dev/docs/frontend/uikit/install",
6
6
  "repository": {
@@ -30,7 +30,7 @@
30
30
  "webpack": false
31
31
  },
32
32
  "peerDependencies": {
33
- "js-yaml": "~4.1.1"
33
+ "js-yaml": "~4.2.0"
34
34
  },
35
35
  "peerDependenciesMeta": {
36
36
  "js-yaml": {
@@ -40,5 +40,5 @@
40
40
  "devDependencies": {
41
41
  "ts-node": "~10.9.2"
42
42
  },
43
- "gitHead": "5c664540fe1fa530da3b311b28941e2fb26c6cff"
43
+ "gitHead": "8beab9ae3a70ce381e8cd53f2de8691640e96c6e"
44
44
  }
@@ -12,6 +12,8 @@ import {
12
12
 
13
13
  interface NpmLockFileEntry {
14
14
  version?: string;
15
+ resolved?: string;
16
+ link?: boolean;
15
17
  dependencies?: Record<string, string>;
16
18
  peerDependencies?: Record<string, string>;
17
19
  }
@@ -25,7 +27,7 @@ export class NpmPackageManager extends PackageManager<NpmLockFile> {
25
27
  readonly lockFileName = 'package-lock.json';
26
28
 
27
29
  clearCache() {
28
- runCommand('npm', ['cache', 'clear', '--force']);
30
+ runCommand(this.command, ['cache', 'clear', '--force']);
29
31
  }
30
32
 
31
33
  getDeclaredVersion({
@@ -42,18 +44,14 @@ export class NpmPackageManager extends PackageManager<NpmLockFile> {
42
44
  }
43
45
 
44
46
  installPackages(args: InstallArgs = {}, options?: Parameters<typeof runCommand>[2]) {
45
- /*
46
- * The `true` fallback allows projects a grace period to identify and
47
- * allowlist trusted scripts. Remove the fallback when the grace period expires.
48
- */
49
- const allowScripts = resolveAllowScripts(args.allowScripts ?? true);
47
+ const allowScripts = resolveAllowScripts(args.allowScripts ?? []);
50
48
 
51
49
  if (!args.quiet) {
52
50
  logAllowedScripts(allowScripts);
53
51
  }
54
52
 
55
53
  runCommand(
56
- 'npm',
54
+ this.command,
57
55
  [
58
56
  isCI() ? 'ci' : 'i',
59
57
  '--audit=false',
@@ -84,9 +82,7 @@ export class NpmPackageManager extends PackageManager<NpmLockFile> {
84
82
  */
85
83
  if (allowScripts !== false) {
86
84
  warnUntrustedInstallScripts(
87
- Array.isArray(allowScripts) ? allowScripts : DEFAULT_ALLOWED_SCRIPTS,
88
- this.lockFileName,
89
- { force: true }
85
+ Array.isArray(allowScripts) ? allowScripts : DEFAULT_ALLOWED_SCRIPTS
90
86
  );
91
87
  }
92
88
  /*
@@ -103,8 +99,12 @@ export class NpmPackageManager extends PackageManager<NpmLockFile> {
103
99
  }
104
100
 
105
101
  protected parseLockFile(): NpmLockFile | undefined {
102
+ const lockFilePath = this.getLockFilePath();
103
+ if (!lockFilePath) {
104
+ return undefined;
105
+ }
106
106
  try {
107
- return JSON.parse(fs.readFileSync(this.lockFileName, 'utf-8'));
107
+ return JSON.parse(fs.readFileSync(lockFilePath, 'utf-8'));
108
108
  } catch {
109
109
  return undefined;
110
110
  }
@@ -115,6 +115,8 @@ export class NpmPackageManager extends PackageManager<NpmLockFile> {
115
115
  * to the hoisted root entry. `workspacePackage` is the package's relative
116
116
  * path from the repo root; the empty string `''` denotes the root
117
117
  * workspace package itself, matching npm's own lockfile key convention.
118
+ * Follows link entries to the resolved workspace package, so callers see
119
+ * the workspace package's own metadata rather than the symlink stub.
118
120
  */
119
121
  private findEntry({
120
122
  workspacePackage,
@@ -124,15 +126,18 @@ export class NpmPackageManager extends PackageManager<NpmLockFile> {
124
126
  package: string;
125
127
  }): NpmLockFileEntry | undefined {
126
128
  const packages = this.getLockFile()?.packages;
127
- return (
129
+ const entry =
128
130
  packages?.[`${workspacePackage}/node_modules/${packageName}`] ??
129
- packages?.[`node_modules/${packageName}`]
130
- );
131
+ packages?.[`node_modules/${packageName}`];
132
+ if (entry?.link && entry.resolved) {
133
+ return packages?.[entry.resolved];
134
+ }
135
+ return entry;
131
136
  }
132
137
 
133
138
  private runRebuild(scripts: string[]) {
134
139
  try {
135
- runCommand('npm', ['rebuild', ...scripts]);
140
+ runCommand(this.command, ['rebuild', ...scripts]);
136
141
  } catch {
137
142
  console.error(`Failed to run allowed scripts: ${scripts.join(', ')}`);
138
143
  process.exitCode = 1;
@@ -141,7 +146,7 @@ export class NpmPackageManager extends PackageManager<NpmLockFile> {
141
146
 
142
147
  private runProjectPostinstall(options?: Parameters<typeof runCommand>[2]) {
143
148
  try {
144
- runCommand('npm', ['run', 'postinstall', '--if-present'], options);
149
+ runCommand(this.command, ['run', 'postinstall', '--if-present'], options);
145
150
  } catch {
146
151
  process.exitCode = 1;
147
152
  }
@@ -1,4 +1,6 @@
1
- import { runCommand } from '../utils';
1
+ import fs from 'fs';
2
+ import path from 'node:path';
3
+ import { findUp, runCommand } from '../utils';
2
4
 
3
5
  export type AllowScripts = true | false | string[];
4
6
 
@@ -25,11 +27,41 @@ export abstract class PackageManager<LockFile = unknown> {
25
27
 
26
28
  #lockFile: LockFile | undefined;
27
29
  #lockFileLoaded = false;
30
+ #lockFilePath: string | undefined;
31
+ #lockFilePathLoaded = false;
28
32
 
29
33
  hasValidLockFile(): boolean {
30
34
  return this.getLockFile() !== undefined;
31
35
  }
32
36
 
37
+ getLockFilePath(): string | undefined {
38
+ if (!this.#lockFilePathLoaded) {
39
+ this.#lockFilePath = findUp(directory => {
40
+ const candidate = path.join(directory, this.lockFileName);
41
+ return fs.existsSync(candidate) ? candidate : undefined;
42
+ });
43
+ this.#lockFilePathLoaded = true;
44
+ }
45
+ return this.#lockFilePath;
46
+ }
47
+
48
+ /**
49
+ * Returns the lockfile key for a package given its absolute or
50
+ * cwd-relative directory. Both npm and pnpm key their lockfile entries
51
+ * by the package's path relative to the workspace root.
52
+ */
53
+ getWorkspacePackage(packageDir = process.cwd()): string {
54
+ const lockFilePath = this.getLockFilePath();
55
+ if (!lockFilePath) {
56
+ return this.rootWorkspacePackage;
57
+ }
58
+ const relative = path
59
+ .relative(path.dirname(lockFilePath), path.resolve(packageDir))
60
+ .split(path.sep)
61
+ .join('/');
62
+ return relative === '' ? this.rootWorkspacePackage : relative;
63
+ }
64
+
33
65
  protected getLockFile(): LockFile | undefined {
34
66
  if (!this.#lockFileLoaded) {
35
67
  this.#lockFile = this.parseLockFile();
@@ -41,6 +73,12 @@ export abstract class PackageManager<LockFile = unknown> {
41
73
  protected reset() {
42
74
  this.#lockFile = undefined;
43
75
  this.#lockFileLoaded = false;
76
+ this.#lockFilePath = undefined;
77
+ this.#lockFilePathLoaded = false;
78
+ }
79
+
80
+ protected get rootWorkspacePackage(): string {
81
+ return '';
44
82
  }
45
83
 
46
84
  abstract clearCache(): void;
@@ -28,8 +28,12 @@ export class PnpmPackageManager extends PackageManager<PnpmLockFile> {
28
28
  readonly command = 'pnpm';
29
29
  readonly lockFileName = 'pnpm-lock.yaml';
30
30
 
31
+ protected override get rootWorkspacePackage(): string {
32
+ return '.';
33
+ }
34
+
31
35
  clearCache() {
32
- runCommand('pnpm', ['store', 'prune']);
36
+ runCommand(this.command, ['store', 'prune']);
33
37
  }
34
38
 
35
39
  getDeclaredVersion({
@@ -52,7 +56,7 @@ export class PnpmPackageManager extends PackageManager<PnpmLockFile> {
52
56
  installPackages(args: InstallArgs = {}, options?: Parameters<typeof runCommand>[2]) {
53
57
  try {
54
58
  runCommand(
55
- 'pnpm',
59
+ this.command,
56
60
  [
57
61
  'install',
58
62
  ...(isCI() ? ['--frozen-lockfile'] : []),
@@ -66,13 +70,17 @@ export class PnpmPackageManager extends PackageManager<PnpmLockFile> {
66
70
  }
67
71
 
68
72
  protected parseLockFile(): PnpmLockFile | undefined {
73
+ const lockFilePath = this.getLockFilePath();
74
+ if (!lockFilePath) {
75
+ return undefined;
76
+ }
69
77
  /*
70
78
  * js-yaml is an optional peer; let MODULE_NOT_FOUND surface so a caller
71
79
  * missing the dep gets a clear error instead of silent `undefined`.
72
80
  */
73
81
  const yaml = require('js-yaml');
74
82
  try {
75
- return yaml.load(fs.readFileSync(this.lockFileName, 'utf-8'));
83
+ return yaml.load(fs.readFileSync(lockFilePath, 'utf-8'));
76
84
  } catch {
77
85
  return undefined;
78
86
  }
@@ -6,9 +6,14 @@ interface PackageWithScript {
6
6
  version: string;
7
7
  }
8
8
 
9
+ /*
10
+ * Keep this selector free of whitespace. On Windows npm runs through a shell (npm.CMD) and
11
+ * execFileSync passes args unquoted, so a space would split the selector at the shell and npm
12
+ * query would receive a truncated, invalid selector.
13
+ */
9
14
  const SELECTORS = ['preinstall', 'install', 'postinstall']
10
- .map(script => `:attr(scripts, [${script}])`)
11
- .join(', ');
15
+ .map(script => `:attr(scripts,[${script}])`)
16
+ .join(',');
12
17
 
13
18
  export function getPackagesWithInstallScripts(): PackageWithScript[] {
14
19
  try {
@@ -4,7 +4,6 @@ export * from './find-up';
4
4
  export * from './get-packages-with-install-scripts';
5
5
  export * from './get-version';
6
6
  export * from './git';
7
- export * from './has-lockfile-changed';
8
7
  export * from './npm';
9
8
  export * from './os';
10
9
  export * from './read-json';
@@ -1,6 +1,5 @@
1
1
  /* eslint-disable no-console */
2
2
  import { getPackagesWithInstallScripts } from './get-packages-with-install-scripts';
3
- import { hasLockfileChanged } from './has-lockfile-changed';
4
3
 
5
4
  // These packages have scripts, but don't need them to function correctly.
6
5
 
@@ -21,19 +20,7 @@ const IGNORE = [
21
20
  'unrs-resolver', // Installs platform-specific binary via optionalDependencies, postinstall is a legacy fallback
22
21
  ];
23
22
 
24
- interface Options {
25
- force?: boolean;
26
- }
27
-
28
- export function warnUntrustedInstallScripts(
29
- allowedScripts: string[],
30
- lockFileName: string,
31
- { force }: Options = {}
32
- ) {
33
- if (!force && !hasLockfileChanged(lockFileName)) {
34
- return;
35
- }
36
-
23
+ export function warnUntrustedInstallScripts(allowedScripts: string[]) {
37
24
  const packages = getPackagesWithInstallScripts();
38
25
  const trustedOrIgnored = new Set([...allowedScripts, ...IGNORE]);
39
26
  const untrusted = packages.filter(({ location, name }) => {
@@ -48,7 +35,6 @@ export function warnUntrustedInstallScripts(
48
35
  console.warn(
49
36
  [
50
37
  'WARNING: The following packages have untrusted install scripts.',
51
- 'A future release will block them by default.',
52
38
  'Review and add trusted packages to --allow-scripts:',
53
39
  list,
54
40
  ].join('\n')
@@ -1,2 +0,0 @@
1
- export declare function hasLockfileChanged(lockFileName: string): boolean;
2
- //# sourceMappingURL=has-lockfile-changed.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"has-lockfile-changed.d.ts","sourceRoot":"","sources":["../../src/utils/has-lockfile-changed.ts"],"names":[],"mappings":"AAEA,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,WAOtD"}
@@ -1,27 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "hasLockfileChanged", {
6
- enumerable: true,
7
- get: function() {
8
- return hasLockfileChanged;
9
- }
10
- });
11
- const _os = require("./os");
12
- function hasLockfileChanged(lockFileName) {
13
- try {
14
- const result = (0, _os.runCommand)('git', [
15
- 'diff',
16
- '--name-only',
17
- 'HEAD',
18
- '--',
19
- lockFileName
20
- ]);
21
- return result.trim().length > 0;
22
- } catch (unused) {
23
- return true;
24
- }
25
- }
26
-
27
- //# sourceMappingURL=has-lockfile-changed.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/utils/has-lockfile-changed.ts"],"sourcesContent":["import { runCommand } from './os';\n\nexport function hasLockfileChanged(lockFileName: string) {\n try {\n const result = runCommand('git', ['diff', '--name-only', 'HEAD', '--', lockFileName]);\n return result.trim().length > 0;\n } catch {\n return true;\n }\n}\n"],"names":["hasLockfileChanged","lockFileName","result","runCommand","trim","length"],"mappings":";;;;+BAEgBA;;;eAAAA;;;oBAFW;AAEpB,SAASA,mBAAmBC,YAAoB;IACnD,IAAI;QACA,MAAMC,SAASC,IAAAA,cAAU,EAAC,OAAO;YAAC;YAAQ;YAAe;YAAQ;YAAMF;SAAa;QACpF,OAAOC,OAAOE,IAAI,GAAGC,MAAM,GAAG;IAClC,EAAE,eAAM;QACJ,OAAO;IACX;AACJ"}
@@ -1,10 +0,0 @@
1
- import { runCommand } from './os';
2
-
3
- export function hasLockfileChanged(lockFileName: string) {
4
- try {
5
- const result = runCommand('git', ['diff', '--name-only', 'HEAD', '--', lockFileName]);
6
- return result.trim().length > 0;
7
- } catch {
8
- return true;
9
- }
10
- }