@rushstack/rundown 1.2.14 → 1.3.1

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 (52) hide show
  1. package/CHANGELOG.json +46 -0
  2. package/CHANGELOG.md +15 -1
  3. package/bin/rundown +1 -1
  4. package/lib-esm/LauncherTypes.js +8 -0
  5. package/lib-esm/LauncherTypes.js.map +1 -0
  6. package/lib-esm/Rundown.js +122 -0
  7. package/lib-esm/Rundown.js.map +1 -0
  8. package/lib-esm/cli/BaseReportAction.js +36 -0
  9. package/lib-esm/cli/BaseReportAction.js.map +1 -0
  10. package/lib-esm/cli/InspectAction.js +25 -0
  11. package/lib-esm/cli/InspectAction.js.map +1 -0
  12. package/lib-esm/cli/RundownCommandLine.js +17 -0
  13. package/lib-esm/cli/RundownCommandLine.js.map +1 -0
  14. package/lib-esm/cli/SnapshotAction.js +20 -0
  15. package/lib-esm/cli/SnapshotAction.js.map +1 -0
  16. package/lib-esm/launcher.js +107 -0
  17. package/lib-esm/launcher.js.map +1 -0
  18. package/lib-esm/start.js +13 -0
  19. package/lib-esm/start.js.map +1 -0
  20. package/package.json +24 -4
  21. /package/{lib → lib-commonjs}/LauncherTypes.js +0 -0
  22. /package/{lib → lib-commonjs}/LauncherTypes.js.map +0 -0
  23. /package/{lib → lib-commonjs}/Rundown.js +0 -0
  24. /package/{lib → lib-commonjs}/Rundown.js.map +0 -0
  25. /package/{lib → lib-commonjs}/cli/BaseReportAction.js +0 -0
  26. /package/{lib → lib-commonjs}/cli/BaseReportAction.js.map +0 -0
  27. /package/{lib → lib-commonjs}/cli/InspectAction.js +0 -0
  28. /package/{lib → lib-commonjs}/cli/InspectAction.js.map +0 -0
  29. /package/{lib → lib-commonjs}/cli/RundownCommandLine.js +0 -0
  30. /package/{lib → lib-commonjs}/cli/RundownCommandLine.js.map +0 -0
  31. /package/{lib → lib-commonjs}/cli/SnapshotAction.js +0 -0
  32. /package/{lib → lib-commonjs}/cli/SnapshotAction.js.map +0 -0
  33. /package/{lib → lib-commonjs}/launcher.js +0 -0
  34. /package/{lib → lib-commonjs}/launcher.js.map +0 -0
  35. /package/{lib → lib-commonjs}/start.js +0 -0
  36. /package/{lib → lib-commonjs}/start.js.map +0 -0
  37. /package/{lib → lib-dts}/LauncherTypes.d.ts +0 -0
  38. /package/{lib → lib-dts}/LauncherTypes.d.ts.map +0 -0
  39. /package/{lib → lib-dts}/Rundown.d.ts +0 -0
  40. /package/{lib → lib-dts}/Rundown.d.ts.map +0 -0
  41. /package/{lib → lib-dts}/cli/BaseReportAction.d.ts +0 -0
  42. /package/{lib → lib-dts}/cli/BaseReportAction.d.ts.map +0 -0
  43. /package/{lib → lib-dts}/cli/InspectAction.d.ts +0 -0
  44. /package/{lib → lib-dts}/cli/InspectAction.d.ts.map +0 -0
  45. /package/{lib → lib-dts}/cli/RundownCommandLine.d.ts +0 -0
  46. /package/{lib → lib-dts}/cli/RundownCommandLine.d.ts.map +0 -0
  47. /package/{lib → lib-dts}/cli/SnapshotAction.d.ts +0 -0
  48. /package/{lib → lib-dts}/cli/SnapshotAction.d.ts.map +0 -0
  49. /package/{lib → lib-dts}/launcher.d.ts +0 -0
  50. /package/{lib → lib-dts}/launcher.d.ts.map +0 -0
  51. /package/{lib → lib-dts}/start.d.ts +0 -0
  52. /package/{lib → lib-dts}/start.d.ts.map +0 -0
package/CHANGELOG.json CHANGED
@@ -1,6 +1,52 @@
1
1
  {
2
2
  "name": "@rushstack/rundown",
3
3
  "entries": [
4
+ {
5
+ "version": "1.3.1",
6
+ "tag": "@rushstack/rundown_v1.3.1",
7
+ "date": "Fri, 20 Feb 2026 00:15:04 GMT",
8
+ "comments": {
9
+ "patch": [
10
+ {
11
+ "comment": "Add `\"node\"` condition before `\"import\"` in the `\"exports\"` map so that Node.js uses the CJS output (which handles extensionless imports), while bundlers still use ESM via `\"import\"`. Fixes https://github.com/microsoft/rushstack/issues/5644."
12
+ }
13
+ ],
14
+ "dependency": [
15
+ {
16
+ "comment": "Updating dependency \"@rushstack/node-core-library\" to `5.20.1`"
17
+ },
18
+ {
19
+ "comment": "Updating dependency \"@rushstack/ts-command-line\" to `5.3.1`"
20
+ },
21
+ {
22
+ "comment": "Updating dependency \"@rushstack/heft\" to `1.2.1`"
23
+ }
24
+ ]
25
+ }
26
+ },
27
+ {
28
+ "version": "1.3.0",
29
+ "tag": "@rushstack/rundown_v1.3.0",
30
+ "date": "Thu, 19 Feb 2026 00:04:53 GMT",
31
+ "comments": {
32
+ "minor": [
33
+ {
34
+ "comment": "Normalize package layout. CommonJS is now under `lib-commonjs`, DTS is now under `lib-dts`, and ESM is now under `lib-esm`. Imports to `lib` still work as before, handled by the `\"exports\"` field in `package.json`."
35
+ }
36
+ ],
37
+ "dependency": [
38
+ {
39
+ "comment": "Updating dependency \"@rushstack/node-core-library\" to `5.20.0`"
40
+ },
41
+ {
42
+ "comment": "Updating dependency \"@rushstack/ts-command-line\" to `5.3.0`"
43
+ },
44
+ {
45
+ "comment": "Updating dependency \"@rushstack/heft\" to `1.2.0`"
46
+ }
47
+ ]
48
+ }
49
+ },
4
50
  {
5
51
  "version": "1.2.14",
6
52
  "tag": "@rushstack/rundown_v1.2.14",
package/CHANGELOG.md CHANGED
@@ -1,6 +1,20 @@
1
1
  # Change Log - @rushstack/rundown
2
2
 
3
- This log was last generated on Sat, 07 Feb 2026 01:13:26 GMT and should not be manually modified.
3
+ This log was last generated on Fri, 20 Feb 2026 00:15:04 GMT and should not be manually modified.
4
+
5
+ ## 1.3.1
6
+ Fri, 20 Feb 2026 00:15:04 GMT
7
+
8
+ ### Patches
9
+
10
+ - Add `"node"` condition before `"import"` in the `"exports"` map so that Node.js uses the CJS output (which handles extensionless imports), while bundlers still use ESM via `"import"`. Fixes https://github.com/microsoft/rushstack/issues/5644.
11
+
12
+ ## 1.3.0
13
+ Thu, 19 Feb 2026 00:04:53 GMT
14
+
15
+ ### Minor changes
16
+
17
+ - Normalize package layout. CommonJS is now under `lib-commonjs`, DTS is now under `lib-dts`, and ESM is now under `lib-esm`. Imports to `lib` still work as before, handled by the `"exports"` field in `package.json`.
4
18
 
5
19
  ## 1.2.14
6
20
  Sat, 07 Feb 2026 01:13:26 GMT
package/bin/rundown CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- require('../lib/start.js');
2
+ require('../lib-commonjs/start.js');
@@ -0,0 +1,8 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+ export var LauncherAction;
4
+ (function (LauncherAction) {
5
+ LauncherAction["Snapshot"] = "snapshot";
6
+ LauncherAction["Inspect"] = "inspect";
7
+ })(LauncherAction || (LauncherAction = {}));
8
+ //# sourceMappingURL=LauncherTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LauncherTypes.js","sourceRoot":"","sources":["../src/LauncherTypes.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,2DAA2D;AAE3D,MAAM,CAAN,IAAY,cAGX;AAHD,WAAY,cAAc;IACxB,uCAAqB,CAAA;IACrB,qCAAmB,CAAA;AACrB,CAAC,EAHW,cAAc,KAAd,cAAc,QAGzB","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nexport enum LauncherAction {\n Snapshot = 'snapshot',\n Inspect = 'inspect'\n}\n\nexport interface IIpcTraceRecord {\n importedModule: string;\n callingModule: string;\n}\n\nexport interface IIpcTrace {\n id: 'trace';\n records: IIpcTraceRecord[];\n}\n\nexport interface IIpcDone {\n id: 'done';\n}\n\nexport type IpcMessage = IIpcTrace | IIpcDone;\n"]}
@@ -0,0 +1,122 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+ import * as child_process from 'node:child_process';
4
+ import * as path from 'node:path';
5
+ import stringArgv from 'string-argv';
6
+ import { FileSystem, PackageJsonLookup, Sort, Text } from '@rushstack/node-core-library';
7
+ export class Rundown {
8
+ constructor() {
9
+ // Map from required path --> caller path
10
+ this._importedModuleMap = new Map();
11
+ }
12
+ async invokeAsync(scriptPath, args, quiet, ignoreExitCode) {
13
+ if (!FileSystem.exists(scriptPath)) {
14
+ throw new Error('The specified script path does not exist: ' + scriptPath);
15
+ }
16
+ const absoluteScriptPath = path.resolve(scriptPath);
17
+ const expandedArgs = args === undefined ? [] : stringArgv(args);
18
+ console.log('Starting process: ' + [absoluteScriptPath, ...expandedArgs].join(' '));
19
+ console.log();
20
+ // Example process.argv:
21
+ // ["path/to/launcher.js", "path/to/target-script.js", "first-target-arg"]
22
+ const nodeArgs = [path.join(__dirname, 'launcher.js'), absoluteScriptPath, ...expandedArgs];
23
+ await this._spawnLauncherAsync(nodeArgs, quiet, ignoreExitCode);
24
+ if (!quiet) {
25
+ console.log();
26
+ }
27
+ }
28
+ writeSnapshotReport() {
29
+ const reportPath = 'rundown-snapshot.log';
30
+ console.log('Writing report file: ' + reportPath);
31
+ const packageJsonLookup = new PackageJsonLookup();
32
+ const importedPaths = [...this._importedModuleMap.keys()];
33
+ const importedPackageFolders = new Set();
34
+ for (const importedPath of importedPaths) {
35
+ const importedPackageFolder = packageJsonLookup.tryGetPackageFolderFor(importedPath);
36
+ if (importedPackageFolder) {
37
+ if (/[\\/]node_modules[\\/]/i.test(importedPackageFolder)) {
38
+ importedPackageFolders.add(path.basename(importedPackageFolder));
39
+ }
40
+ else {
41
+ const relativePath = path.relative(process.cwd(), importedPackageFolder);
42
+ importedPackageFolders.add(Text.replaceAll(relativePath, '\\', '/'));
43
+ }
44
+ }
45
+ else {
46
+ // If the importedPath does not belong to an NPM package, then rundown-snapshot.log can ignore it.
47
+ // In other words, treat it the same way as the local project's source files.
48
+ }
49
+ }
50
+ Sort.sortSet(importedPackageFolders);
51
+ const data = [...importedPackageFolders].join('\n') + '\n';
52
+ FileSystem.writeFile(reportPath, data);
53
+ }
54
+ writeInspectReport(traceImports) {
55
+ const reportPath = 'rundown-inspect.log';
56
+ console.log('Writing report file: ' + reportPath);
57
+ const importedPaths = [...this._importedModuleMap.keys()];
58
+ importedPaths.sort();
59
+ let data = '';
60
+ if (traceImports) {
61
+ for (const importedPath of importedPaths) {
62
+ data += importedPath + '\n';
63
+ let current = importedPath;
64
+ const visited = new Set();
65
+ for (;;) {
66
+ const callerPath = this._importedModuleMap.get(current);
67
+ if (!callerPath) {
68
+ break;
69
+ }
70
+ if (visited.has(callerPath)) {
71
+ break;
72
+ }
73
+ visited.add(callerPath);
74
+ data += ' imported by ' + callerPath + '\n';
75
+ current = callerPath;
76
+ }
77
+ data += '\n';
78
+ }
79
+ }
80
+ else {
81
+ data = importedPaths.join('\n') + '\n';
82
+ }
83
+ FileSystem.writeFile(reportPath, data);
84
+ }
85
+ async _spawnLauncherAsync(nodeArgs, quiet, ignoreExitCode) {
86
+ const childProcess = child_process.spawn(process.execPath, nodeArgs, {
87
+ stdio: quiet ? ['inherit', 'ignore', 'ignore', 'ipc'] : ['inherit', 'inherit', 'inherit', 'ipc']
88
+ });
89
+ let completedNormally = false;
90
+ childProcess.on('message', (message) => {
91
+ switch (message.id) {
92
+ case 'trace':
93
+ for (const record of message.records) {
94
+ this._importedModuleMap.set(record.importedModule, record.callingModule);
95
+ }
96
+ break;
97
+ case 'done':
98
+ completedNormally = true;
99
+ break;
100
+ default:
101
+ throw new Error('Unknown IPC message: ' + JSON.stringify(message));
102
+ }
103
+ });
104
+ await new Promise((resolve, reject) => {
105
+ childProcess.on('close', (exitCode, signal) => {
106
+ if (signal) {
107
+ reject(new Error('Child process terminated by ' + signal));
108
+ }
109
+ else if (exitCode !== 0 && !ignoreExitCode) {
110
+ reject(new Error('Child process terminated with exit code ' + exitCode));
111
+ }
112
+ else if (!completedNormally) {
113
+ reject(new Error('Child process terminated without completing IPC handshake'));
114
+ }
115
+ else {
116
+ resolve();
117
+ }
118
+ });
119
+ });
120
+ }
121
+ }
122
+ //# sourceMappingURL=Rundown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Rundown.js","sourceRoot":"","sources":["../src/Rundown.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport * as child_process from 'node:child_process';\nimport * as path from 'node:path';\n\nimport stringArgv from 'string-argv';\n\nimport { FileSystem, PackageJsonLookup, Sort, Text } from '@rushstack/node-core-library';\n\nimport type { IpcMessage } from './LauncherTypes';\n\nexport class Rundown {\n // Map from required path --> caller path\n private _importedModuleMap: Map<string, string> = new Map();\n\n public async invokeAsync(\n scriptPath: string,\n args: string | undefined,\n quiet: boolean,\n ignoreExitCode: boolean\n ): Promise<void> {\n if (!FileSystem.exists(scriptPath)) {\n throw new Error('The specified script path does not exist: ' + scriptPath);\n }\n const absoluteScriptPath: string = path.resolve(scriptPath);\n\n const expandedArgs: string[] = args === undefined ? [] : stringArgv(args);\n\n console.log('Starting process: ' + [absoluteScriptPath, ...expandedArgs].join(' '));\n console.log();\n\n // Example process.argv:\n // [\"path/to/launcher.js\", \"path/to/target-script.js\", \"first-target-arg\"]\n const nodeArgs: string[] = [path.join(__dirname, 'launcher.js'), absoluteScriptPath, ...expandedArgs];\n\n await this._spawnLauncherAsync(nodeArgs, quiet, ignoreExitCode);\n\n if (!quiet) {\n console.log();\n }\n }\n\n public writeSnapshotReport(): void {\n const reportPath: string = 'rundown-snapshot.log';\n console.log('Writing report file: ' + reportPath);\n\n const packageJsonLookup: PackageJsonLookup = new PackageJsonLookup();\n const importedPaths: string[] = [...this._importedModuleMap.keys()];\n const importedPackageFolders: Set<string> = new Set();\n\n for (const importedPath of importedPaths) {\n const importedPackageFolder: string | undefined =\n packageJsonLookup.tryGetPackageFolderFor(importedPath);\n if (importedPackageFolder) {\n if (/[\\\\/]node_modules[\\\\/]/i.test(importedPackageFolder)) {\n importedPackageFolders.add(path.basename(importedPackageFolder));\n } else {\n const relativePath: string = path.relative(process.cwd(), importedPackageFolder);\n importedPackageFolders.add(Text.replaceAll(relativePath, '\\\\', '/'));\n }\n } else {\n // If the importedPath does not belong to an NPM package, then rundown-snapshot.log can ignore it.\n // In other words, treat it the same way as the local project's source files.\n }\n }\n\n Sort.sortSet(importedPackageFolders);\n const data: string = [...importedPackageFolders].join('\\n') + '\\n';\n\n FileSystem.writeFile(reportPath, data);\n }\n\n public writeInspectReport(traceImports: boolean): void {\n const reportPath: string = 'rundown-inspect.log';\n console.log('Writing report file: ' + reportPath);\n\n const importedPaths: string[] = [...this._importedModuleMap.keys()];\n importedPaths.sort();\n\n let data: string = '';\n\n if (traceImports) {\n for (const importedPath of importedPaths) {\n data += importedPath + '\\n';\n\n let current: string = importedPath;\n const visited: Set<string> = new Set();\n for (;;) {\n const callerPath: string | undefined = this._importedModuleMap.get(current);\n if (!callerPath) {\n break;\n }\n if (visited.has(callerPath)) {\n break;\n }\n visited.add(callerPath);\n data += ' imported by ' + callerPath + '\\n';\n current = callerPath;\n }\n data += '\\n';\n }\n } else {\n data = importedPaths.join('\\n') + '\\n';\n }\n\n FileSystem.writeFile(reportPath, data);\n }\n\n private async _spawnLauncherAsync(\n nodeArgs: string[],\n quiet: boolean,\n ignoreExitCode: boolean\n ): Promise<void> {\n const childProcess: child_process.ChildProcess = child_process.spawn(process.execPath, nodeArgs, {\n stdio: quiet ? ['inherit', 'ignore', 'ignore', 'ipc'] : ['inherit', 'inherit', 'inherit', 'ipc']\n });\n\n let completedNormally: boolean = false;\n\n childProcess.on('message', (message: IpcMessage): void => {\n switch (message.id) {\n case 'trace':\n for (const record of message.records) {\n this._importedModuleMap.set(record.importedModule, record.callingModule);\n }\n break;\n case 'done':\n completedNormally = true;\n break;\n default:\n throw new Error('Unknown IPC message: ' + JSON.stringify(message));\n }\n });\n\n await new Promise<void>((resolve, reject) => {\n childProcess.on('close', (exitCode: number | null, signal: NodeJS.Signals | null): void => {\n if (signal) {\n reject(new Error('Child process terminated by ' + signal));\n } else if (exitCode !== 0 && !ignoreExitCode) {\n reject(new Error('Child process terminated with exit code ' + exitCode));\n } else if (!completedNormally) {\n reject(new Error('Child process terminated without completing IPC handshake'));\n } else {\n resolve();\n }\n });\n });\n }\n}\n"]}
@@ -0,0 +1,36 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
4
+ // See LICENSE in the project root for license information.
5
+ import { CommandLineAction } from '@rushstack/ts-command-line';
6
+ export class BaseReportAction extends CommandLineAction {
7
+ constructor(options) {
8
+ super(options);
9
+ this.scriptParameter = this.defineStringParameter({
10
+ parameterLongName: '--script',
11
+ parameterShortName: '-s',
12
+ argumentName: 'PATH',
13
+ description: 'The path to a .js file that will be the entry point for the target Node.js process',
14
+ required: true
15
+ });
16
+ this.argsParameter = this.defineStringParameter({
17
+ parameterLongName: '--args',
18
+ parameterShortName: '-a',
19
+ argumentName: 'STRING',
20
+ description: 'Specifies command-line arguments to be passed to the target Node.js process. The value' +
21
+ ' should be a single text string delimited by spaces.' +
22
+ ' Example: rundown inspect --scripts ./example.js --args="--flag --option=123"'
23
+ });
24
+ this.quietParameter = this.defineFlagParameter({
25
+ parameterLongName: '--quiet',
26
+ parameterShortName: '-q',
27
+ description: 'Suppress STDOUT/STDERR for the target Node.js process'
28
+ });
29
+ this.ignoreExitCodeParameter = this.defineFlagParameter({
30
+ parameterLongName: '--ignore-exit-code',
31
+ parameterShortName: '-i',
32
+ description: 'Do not report an error if the target Node.js process returns a nonzero exit code'
33
+ });
34
+ }
35
+ }
36
+ //# sourceMappingURL=BaseReportAction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseReportAction.js","sourceRoot":"","sources":["../../src/cli/BaseReportAction.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,2DAA2D;AAE3D,4FAA4F;AAC5F,2DAA2D;AAE3D,OAAO,EACL,iBAAiB,EAKlB,MAAM,4BAA4B,CAAC;AAEpC,MAAM,OAAgB,gBAAiB,SAAQ,iBAAiB;IAM9D,YAAmB,OAAkC;QACnD,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,qBAAqB,CAAC;YAChD,iBAAiB,EAAE,UAAU;YAC7B,kBAAkB,EAAE,IAAI;YACxB,YAAY,EAAE,MAAM;YACpB,WAAW,EAAE,oFAAoF;YACjG,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;QACH,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,qBAAqB,CAAC;YAC9C,iBAAiB,EAAE,QAAQ;YAC3B,kBAAkB,EAAE,IAAI;YACxB,YAAY,EAAE,QAAQ;YACtB,WAAW,EACT,yFAAyF;gBACzF,sDAAsD;gBACtD,+EAA+E;SAClF,CAAC,CAAC;QACH,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,mBAAmB,CAAC;YAC7C,iBAAiB,EAAE,SAAS;YAC5B,kBAAkB,EAAE,IAAI;YACxB,WAAW,EAAE,uDAAuD;SACrE,CAAC,CAAC;QACH,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC,mBAAmB,CAAC;YACtD,iBAAiB,EAAE,oBAAoB;YACvC,kBAAkB,EAAE,IAAI;YACxB,WAAW,EAAE,kFAAkF;SAChG,CAAC,CAAC;IACL,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\n// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport {\n CommandLineAction,\n type ICommandLineActionOptions,\n type CommandLineStringParameter,\n type CommandLineFlagParameter,\n type IRequiredCommandLineStringParameter\n} from '@rushstack/ts-command-line';\n\nexport abstract class BaseReportAction extends CommandLineAction {\n protected readonly scriptParameter: IRequiredCommandLineStringParameter;\n protected readonly argsParameter: CommandLineStringParameter;\n protected readonly quietParameter: CommandLineFlagParameter;\n protected readonly ignoreExitCodeParameter: CommandLineFlagParameter;\n\n public constructor(options: ICommandLineActionOptions) {\n super(options);\n\n this.scriptParameter = this.defineStringParameter({\n parameterLongName: '--script',\n parameterShortName: '-s',\n argumentName: 'PATH',\n description: 'The path to a .js file that will be the entry point for the target Node.js process',\n required: true\n });\n this.argsParameter = this.defineStringParameter({\n parameterLongName: '--args',\n parameterShortName: '-a',\n argumentName: 'STRING',\n description:\n 'Specifies command-line arguments to be passed to the target Node.js process. The value' +\n ' should be a single text string delimited by spaces.' +\n ' Example: rundown inspect --scripts ./example.js --args=\"--flag --option=123\"'\n });\n this.quietParameter = this.defineFlagParameter({\n parameterLongName: '--quiet',\n parameterShortName: '-q',\n description: 'Suppress STDOUT/STDERR for the target Node.js process'\n });\n this.ignoreExitCodeParameter = this.defineFlagParameter({\n parameterLongName: '--ignore-exit-code',\n parameterShortName: '-i',\n description: 'Do not report an error if the target Node.js process returns a nonzero exit code'\n });\n }\n}\n"]}
@@ -0,0 +1,25 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+ import { BaseReportAction } from './BaseReportAction';
4
+ import { Rundown } from '../Rundown';
5
+ export class InspectAction extends BaseReportAction {
6
+ constructor() {
7
+ super({
8
+ actionName: 'inspect',
9
+ summary: 'Invoke a Node.js script and generate detailed diagnostic output',
10
+ documentation: 'Invoke a Node.js script and generate detailed diagnostic output. This command is used' +
11
+ ' to inspect performance regressions.'
12
+ });
13
+ this._traceParameter = this.defineFlagParameter({
14
+ parameterLongName: '--trace-imports',
15
+ parameterShortName: '-t',
16
+ description: 'Reports the call chain for each module path, showing how it was imported'
17
+ });
18
+ }
19
+ async onExecuteAsync() {
20
+ const rundown = new Rundown();
21
+ await rundown.invokeAsync(this.scriptParameter.value, this.argsParameter.value, this.quietParameter.value, this.ignoreExitCodeParameter.value);
22
+ rundown.writeInspectReport(this._traceParameter.value);
23
+ }
24
+ }
25
+ //# sourceMappingURL=InspectAction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InspectAction.js","sourceRoot":"","sources":["../../src/cli/InspectAction.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,2DAA2D;AAI3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,MAAM,OAAO,aAAc,SAAQ,gBAAgB;IAGjD;QACE,KAAK,CAAC;YACJ,UAAU,EAAE,SAAS;YACrB,OAAO,EAAE,iEAAiE;YAC1E,aAAa,EACX,wFAAwF;gBACxF,sCAAsC;SACzC,CAAC,CAAC;QAEH,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,mBAAmB,CAAC;YAC9C,iBAAiB,EAAE,iBAAiB;YACpC,kBAAkB,EAAE,IAAI;YACxB,WAAW,EAAE,0EAA0E;SACxF,CAAC,CAAC;IACL,CAAC;IAEkB,KAAK,CAAC,cAAc;QACrC,MAAM,OAAO,GAAY,IAAI,OAAO,EAAE,CAAC;QACvC,MAAM,OAAO,CAAC,WAAW,CACvB,IAAI,CAAC,eAAe,CAAC,KAAK,EAC1B,IAAI,CAAC,aAAa,CAAC,KAAK,EACxB,IAAI,CAAC,cAAc,CAAC,KAAK,EACzB,IAAI,CAAC,uBAAuB,CAAC,KAAK,CACnC,CAAC;QACF,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IACzD,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type { CommandLineFlagParameter } from '@rushstack/ts-command-line';\n\nimport { BaseReportAction } from './BaseReportAction';\nimport { Rundown } from '../Rundown';\n\nexport class InspectAction extends BaseReportAction {\n private readonly _traceParameter: CommandLineFlagParameter;\n\n public constructor() {\n super({\n actionName: 'inspect',\n summary: 'Invoke a Node.js script and generate detailed diagnostic output',\n documentation:\n 'Invoke a Node.js script and generate detailed diagnostic output. This command is used' +\n ' to inspect performance regressions.'\n });\n\n this._traceParameter = this.defineFlagParameter({\n parameterLongName: '--trace-imports',\n parameterShortName: '-t',\n description: 'Reports the call chain for each module path, showing how it was imported'\n });\n }\n\n protected override async onExecuteAsync(): Promise<void> {\n const rundown: Rundown = new Rundown();\n await rundown.invokeAsync(\n this.scriptParameter.value,\n this.argsParameter.value,\n this.quietParameter.value,\n this.ignoreExitCodeParameter.value\n );\n rundown.writeInspectReport(this._traceParameter.value);\n }\n}\n"]}
@@ -0,0 +1,17 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+ import { CommandLineParser } from '@rushstack/ts-command-line';
4
+ import { SnapshotAction } from './SnapshotAction';
5
+ import { InspectAction } from './InspectAction';
6
+ export class RundownCommandLine extends CommandLineParser {
7
+ constructor() {
8
+ super({
9
+ toolFilename: 'rundown',
10
+ toolDescription: 'Detect load time regressions by running an app, tracing require() calls,' +
11
+ ' and generating a deterministic report'
12
+ });
13
+ this.addAction(new SnapshotAction());
14
+ this.addAction(new InspectAction());
15
+ }
16
+ }
17
+ //# sourceMappingURL=RundownCommandLine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RundownCommandLine.js","sourceRoot":"","sources":["../../src/cli/RundownCommandLine.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,2DAA2D;AAE3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAE/D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,OAAO,kBAAmB,SAAQ,iBAAiB;IACvD;QACE,KAAK,CAAC;YACJ,YAAY,EAAE,SAAS;YACvB,eAAe,EACb,0EAA0E;gBAC1E,wCAAwC;SAC3C,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,CAAC,IAAI,cAAc,EAAE,CAAC,CAAC;QACrC,IAAI,CAAC,SAAS,CAAC,IAAI,aAAa,EAAE,CAAC,CAAC;IACtC,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { CommandLineParser } from '@rushstack/ts-command-line';\n\nimport { SnapshotAction } from './SnapshotAction';\nimport { InspectAction } from './InspectAction';\n\nexport class RundownCommandLine extends CommandLineParser {\n public constructor() {\n super({\n toolFilename: 'rundown',\n toolDescription:\n 'Detect load time regressions by running an app, tracing require() calls,' +\n ' and generating a deterministic report'\n });\n\n this.addAction(new SnapshotAction());\n this.addAction(new InspectAction());\n }\n}\n"]}
@@ -0,0 +1,20 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+ import { BaseReportAction } from './BaseReportAction';
4
+ import { Rundown } from '../Rundown';
5
+ export class SnapshotAction extends BaseReportAction {
6
+ constructor() {
7
+ super({
8
+ actionName: 'snapshot',
9
+ summary: 'Invoke a Node.js script and generate a test snapshot',
10
+ documentation: 'Invoke a Node.js script and generate a test snapshot. This command creates a concise report that can be' +
11
+ ' added to Git, so that its diff can be used to detect performance regressions'
12
+ });
13
+ }
14
+ async onExecuteAsync() {
15
+ const rundown = new Rundown();
16
+ await rundown.invokeAsync(this.scriptParameter.value, this.argsParameter.value, this.quietParameter.value, this.ignoreExitCodeParameter.value);
17
+ rundown.writeSnapshotReport();
18
+ }
19
+ }
20
+ //# sourceMappingURL=SnapshotAction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SnapshotAction.js","sourceRoot":"","sources":["../../src/cli/SnapshotAction.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,2DAA2D;AAE3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,MAAM,OAAO,cAAe,SAAQ,gBAAgB;IAClD;QACE,KAAK,CAAC;YACJ,UAAU,EAAE,UAAU;YACtB,OAAO,EAAE,sDAAsD;YAC/D,aAAa,EACX,0GAA0G;gBAC1G,+EAA+E;SAClF,CAAC,CAAC;IACL,CAAC;IAEkB,KAAK,CAAC,cAAc;QACrC,MAAM,OAAO,GAAY,IAAI,OAAO,EAAE,CAAC;QACvC,MAAM,OAAO,CAAC,WAAW,CACvB,IAAI,CAAC,eAAe,CAAC,KAAK,EAC1B,IAAI,CAAC,aAAa,CAAC,KAAK,EACxB,IAAI,CAAC,cAAc,CAAC,KAAK,EACzB,IAAI,CAAC,uBAAuB,CAAC,KAAK,CACnC,CAAC;QACF,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAChC,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { BaseReportAction } from './BaseReportAction';\nimport { Rundown } from '../Rundown';\n\nexport class SnapshotAction extends BaseReportAction {\n public constructor() {\n super({\n actionName: 'snapshot',\n summary: 'Invoke a Node.js script and generate a test snapshot',\n documentation:\n 'Invoke a Node.js script and generate a test snapshot. This command creates a concise report that can be' +\n ' added to Git, so that its diff can be used to detect performance regressions'\n });\n }\n\n protected override async onExecuteAsync(): Promise<void> {\n const rundown: Rundown = new Rundown();\n await rundown.invokeAsync(\n this.scriptParameter.value,\n this.argsParameter.value,\n this.quietParameter.value,\n this.ignoreExitCodeParameter.value\n );\n rundown.writeSnapshotReport();\n }\n}\n"]}
@@ -0,0 +1,107 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+ import process from 'node:process';
4
+ import { LauncherAction } from './LauncherTypes'; // "import type" doesn't work with const enums
5
+ // The _ipcTraceRecordsBatch will get transmitted when this many items are accumulated
6
+ const IPC_BATCH_SIZE = 300;
7
+ class Launcher {
8
+ constructor() {
9
+ this.action = LauncherAction.Inspect;
10
+ this.targetScriptPathArg = '';
11
+ this.reportPath = '';
12
+ this._importedModules = new Set();
13
+ this._importedModulePaths = new Set();
14
+ this._ipcTraceRecordsBatch = [];
15
+ }
16
+ transformArgs(argv) {
17
+ let nodeArg;
18
+ let remainderArgs;
19
+ // Example process.argv:
20
+ // ["path/to/node.exe", "path/to/launcher.js", "path/to/target-script.js", "first-target-arg"]
21
+ [nodeArg, , this.targetScriptPathArg, ...remainderArgs] = argv;
22
+ // Example process.argv:
23
+ // ["path/to/node.exe", "path/to/target-script.js", "first-target-arg"]
24
+ return [nodeArg, this.targetScriptPathArg, ...remainderArgs];
25
+ }
26
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
27
+ static _copyProperties(dst, src) {
28
+ for (const prop of Object.keys(src)) {
29
+ dst[prop] = src[prop];
30
+ }
31
+ }
32
+ _sendIpcTraceBatch() {
33
+ if (this._ipcTraceRecordsBatch.length > 0) {
34
+ const batch = [...this._ipcTraceRecordsBatch];
35
+ this._ipcTraceRecordsBatch.length = 0;
36
+ process.send({
37
+ id: 'trace',
38
+ records: batch
39
+ });
40
+ }
41
+ }
42
+ installHook() {
43
+ const realRequire = moduleApi.Module.prototype.require;
44
+ const importedModules = this._importedModules; // for closure
45
+ const importedModulePaths = this._importedModulePaths; // for closure
46
+ const ipcTraceRecordsBatch = this._ipcTraceRecordsBatch; // for closure
47
+ const sendIpcTraceBatch = this._sendIpcTraceBatch.bind(this); // for closure
48
+ function hookedRequire(moduleName) {
49
+ // NOTE: The "this" pointer is the calling NodeModule, so we rely on closure
50
+ // variable here.
51
+ const callingModuleInfo = this;
52
+ // Paranoidly use "arguments" in case some implementor passes additional undocumented arguments
53
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
54
+ const importedModule = realRequire.apply(callingModuleInfo, arguments);
55
+ if (!importedModules.has(importedModule)) {
56
+ importedModules.add(importedModule);
57
+ // Find the info for the imported module
58
+ let importedModuleInfo = undefined;
59
+ const children = callingModuleInfo.children || [];
60
+ for (const child of children) {
61
+ if (child.exports === importedModule) {
62
+ importedModuleInfo = child;
63
+ break;
64
+ }
65
+ }
66
+ if (importedModuleInfo === undefined) {
67
+ // It's a built-in module like "os"
68
+ }
69
+ else {
70
+ if (!importedModuleInfo.filename) {
71
+ throw new Error('Missing filename for ' + moduleName);
72
+ }
73
+ if (!importedModulePaths.has(importedModuleInfo.filename)) {
74
+ importedModulePaths.add(importedModuleInfo.filename);
75
+ ipcTraceRecordsBatch.push({
76
+ importedModule: importedModuleInfo.filename,
77
+ callingModule: callingModuleInfo.filename
78
+ });
79
+ if (ipcTraceRecordsBatch.length >= IPC_BATCH_SIZE) {
80
+ sendIpcTraceBatch();
81
+ }
82
+ }
83
+ }
84
+ }
85
+ return importedModule;
86
+ }
87
+ moduleApi.Module.prototype.require = hookedRequire;
88
+ Launcher._copyProperties(hookedRequire, realRequire);
89
+ process.on('exit', () => {
90
+ this._sendIpcTraceBatch();
91
+ process.send({
92
+ id: 'done'
93
+ });
94
+ });
95
+ }
96
+ }
97
+ if (!process.send) {
98
+ throw new Error('launcher.js must be invoked via IPC');
99
+ }
100
+ const launcher = new Launcher();
101
+ const originalArgv = [...process.argv];
102
+ process.argv.length = 0;
103
+ process.argv.push(...launcher.transformArgs(originalArgv));
104
+ launcher.installHook();
105
+ // Start the app
106
+ require(launcher.targetScriptPathArg);
107
+ //# sourceMappingURL=launcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launcher.js","sourceRoot":"","sources":["../src/launcher.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport moduleApi = require('module');\nimport process from 'node:process';\n\nimport { LauncherAction } from './LauncherTypes'; // \"import type\" doesn't work with const enums\nimport type { IIpcTrace, IIpcDone, IIpcTraceRecord } from './LauncherTypes';\n\n// The _ipcTraceRecordsBatch will get transmitted when this many items are accumulated\nconst IPC_BATCH_SIZE: number = 300;\n\nclass Launcher {\n public action: LauncherAction = LauncherAction.Inspect;\n public targetScriptPathArg: string = '';\n public reportPath: string = '';\n private _importedModules: Set<unknown> = new Set();\n private _importedModulePaths: Set<string> = new Set();\n private _ipcTraceRecordsBatch: IIpcTraceRecord[] = [];\n\n public transformArgs(argv: ReadonlyArray<string>): string[] {\n let nodeArg: string;\n let remainderArgs: string[];\n\n // Example process.argv:\n // [\"path/to/node.exe\", \"path/to/launcher.js\", \"path/to/target-script.js\", \"first-target-arg\"]\n [nodeArg, , this.targetScriptPathArg, ...remainderArgs] = argv;\n\n // Example process.argv:\n // [\"path/to/node.exe\", \"path/to/target-script.js\", \"first-target-arg\"]\n return [nodeArg, this.targetScriptPathArg, ...remainderArgs];\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private static _copyProperties(dst: any, src: any): void {\n for (const prop of Object.keys(src)) {\n dst[prop] = src[prop];\n }\n }\n\n private _sendIpcTraceBatch(): void {\n if (this._ipcTraceRecordsBatch.length > 0) {\n const batch: IIpcTraceRecord[] = [...this._ipcTraceRecordsBatch];\n this._ipcTraceRecordsBatch.length = 0;\n\n process.send!({\n id: 'trace',\n records: batch\n } as IIpcTrace);\n }\n }\n\n public installHook(): void {\n const realRequire: typeof moduleApi.Module.prototype.require = moduleApi.Module.prototype.require;\n\n const importedModules: Set<unknown> = this._importedModules; // for closure\n const importedModulePaths: Set<string> = this._importedModulePaths; // for closure\n const ipcTraceRecordsBatch: IIpcTraceRecord[] = this._ipcTraceRecordsBatch; // for closure\n const sendIpcTraceBatch: () => void = this._sendIpcTraceBatch.bind(this); // for closure\n\n function hookedRequire(this: NodeModule, moduleName: string): unknown {\n // NOTE: The \"this\" pointer is the calling NodeModule, so we rely on closure\n // variable here.\n const callingModuleInfo: NodeModule = this;\n\n // Paranoidly use \"arguments\" in case some implementor passes additional undocumented arguments\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const importedModule: unknown = (realRequire as any).apply(callingModuleInfo, arguments);\n\n if (!importedModules.has(importedModule)) {\n importedModules.add(importedModule);\n\n // Find the info for the imported module\n let importedModuleInfo: NodeModule | undefined = undefined;\n const children: NodeModule[] = callingModuleInfo.children || [];\n for (const child of children) {\n if (child.exports === importedModule) {\n importedModuleInfo = child;\n break;\n }\n }\n\n if (importedModuleInfo === undefined) {\n // It's a built-in module like \"os\"\n } else {\n if (!importedModuleInfo.filename) {\n throw new Error('Missing filename for ' + moduleName);\n }\n\n if (!importedModulePaths.has(importedModuleInfo.filename)) {\n importedModulePaths.add(importedModuleInfo.filename);\n ipcTraceRecordsBatch.push({\n importedModule: importedModuleInfo.filename,\n callingModule: callingModuleInfo.filename\n });\n if (ipcTraceRecordsBatch.length >= IPC_BATCH_SIZE) {\n sendIpcTraceBatch();\n }\n }\n }\n }\n\n return importedModule;\n }\n\n moduleApi.Module.prototype.require = hookedRequire as NodeJS.Require;\n Launcher._copyProperties(hookedRequire, realRequire);\n\n process.on('exit', () => {\n this._sendIpcTraceBatch();\n process.send!({\n id: 'done'\n } as IIpcDone);\n });\n }\n}\n\nif (!process.send) {\n throw new Error('launcher.js must be invoked via IPC');\n}\n\nconst launcher: Launcher = new Launcher();\n\nconst originalArgv: ReadonlyArray<string> = [...process.argv];\nprocess.argv.length = 0;\nprocess.argv.push(...launcher.transformArgs(originalArgv));\n\nlauncher.installHook();\n\n// Start the app\nrequire(launcher.targetScriptPathArg);\n"]}
@@ -0,0 +1,13 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+ import { PackageJsonLookup } from '@rushstack/node-core-library';
4
+ import { RundownCommandLine } from './cli/RundownCommandLine';
5
+ const toolVersion = PackageJsonLookup.loadOwnPackageJson(__dirname).version;
6
+ console.log();
7
+ console.log(`Rundown ${toolVersion} - https://rushstack.io`);
8
+ console.log();
9
+ const commandLine = new RundownCommandLine();
10
+ commandLine.executeAsync().catch((error) => {
11
+ console.error(error);
12
+ });
13
+ //# sourceMappingURL=start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../src/start.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,2DAA2D;AAE3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE9D,MAAM,WAAW,GAAW,iBAAiB,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC;AAEpF,OAAO,CAAC,GAAG,EAAE,CAAC;AACd,OAAO,CAAC,GAAG,CAAC,WAAW,WAAW,yBAAyB,CAAC,CAAC;AAC7D,OAAO,CAAC,GAAG,EAAE,CAAC;AAEd,MAAM,WAAW,GAAuB,IAAI,kBAAkB,EAAE,CAAC;AACjE,WAAW,CAAC,YAAY,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACzC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { PackageJsonLookup } from '@rushstack/node-core-library';\n\nimport { RundownCommandLine } from './cli/RundownCommandLine';\n\nconst toolVersion: string = PackageJsonLookup.loadOwnPackageJson(__dirname).version;\n\nconsole.log();\nconsole.log(`Rundown ${toolVersion} - https://rushstack.io`);\nconsole.log();\n\nconst commandLine: RundownCommandLine = new RundownCommandLine();\ncommandLine.executeAsync().catch((error) => {\n console.error(error);\n});\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rushstack/rundown",
3
- "version": "1.2.14",
3
+ "version": "1.3.1",
4
4
  "description": "Detect load time regressions by running an app, tracing require() calls, and generating a deterministic report",
5
5
  "repository": {
6
6
  "type": "git",
@@ -18,14 +18,34 @@
18
18
  "license": "MIT",
19
19
  "dependencies": {
20
20
  "string-argv": "~0.3.1",
21
- "@rushstack/node-core-library": "5.19.1",
22
- "@rushstack/ts-command-line": "5.2.0"
21
+ "@rushstack/node-core-library": "5.20.1",
22
+ "@rushstack/ts-command-line": "5.3.1"
23
23
  },
24
24
  "devDependencies": {
25
25
  "eslint": "~9.37.0",
26
- "@rushstack/heft": "1.1.14",
26
+ "@rushstack/heft": "1.2.1",
27
27
  "local-node-rig": "1.0.0"
28
28
  },
29
+ "exports": {
30
+ "./lib/*": {
31
+ "types": "./lib-dts/*.d.ts",
32
+ "node": "./lib-commonjs/*.js",
33
+ "import": "./lib-esm/*.js",
34
+ "require": "./lib-commonjs/*.js"
35
+ },
36
+ "./package.json": "./package.json"
37
+ },
38
+ "typesVersions": {
39
+ "*": {
40
+ "lib/*": [
41
+ "lib-dts/*"
42
+ ]
43
+ }
44
+ },
45
+ "sideEffects": [
46
+ "lib-commonjs/start.js",
47
+ "lib-esm/start.js"
48
+ ],
29
49
  "scripts": {
30
50
  "build": "heft build --clean",
31
51
  "_phase:build": "heft run --only build -- --clean"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes