npmdata 0.11.0 → 0.13.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 (160) hide show
  1. package/README.md +47 -42
  2. package/dist/cli/actions/check.d.ts +6 -0
  3. package/dist/cli/actions/check.d.ts.map +1 -0
  4. package/dist/cli/actions/check.js +45 -0
  5. package/dist/cli/actions/check.js.map +1 -0
  6. package/dist/cli/actions/extract.d.ts +7 -0
  7. package/dist/cli/actions/extract.d.ts.map +1 -0
  8. package/dist/cli/actions/extract.js +67 -0
  9. package/dist/cli/actions/extract.js.map +1 -0
  10. package/dist/cli/actions/init.d.ts +6 -0
  11. package/dist/cli/actions/init.d.ts.map +1 -0
  12. package/dist/cli/actions/init.js +30 -0
  13. package/dist/cli/actions/init.js.map +1 -0
  14. package/dist/cli/actions/list.d.ts +7 -0
  15. package/dist/cli/actions/list.d.ts.map +1 -0
  16. package/dist/cli/actions/list.js +36 -0
  17. package/dist/cli/actions/list.js.map +1 -0
  18. package/dist/cli/actions/purge.d.ts +6 -0
  19. package/dist/cli/actions/purge.d.ts.map +1 -0
  20. package/dist/cli/actions/purge.js +33 -0
  21. package/dist/cli/actions/purge.js.map +1 -0
  22. package/dist/cli/argv.d.ts +35 -0
  23. package/dist/cli/argv.d.ts.map +1 -0
  24. package/dist/cli/argv.js +125 -0
  25. package/dist/cli/argv.js.map +1 -0
  26. package/dist/cli/bin.d.ts +3 -0
  27. package/dist/cli/bin.d.ts.map +1 -0
  28. package/dist/cli/bin.js +11 -0
  29. package/dist/cli/bin.js.map +1 -0
  30. package/dist/cli/binpkg.d.ts +8 -0
  31. package/dist/cli/binpkg.d.ts.map +1 -0
  32. package/dist/cli/binpkg.js +24 -0
  33. package/dist/cli/binpkg.js.map +1 -0
  34. package/dist/cli/cli.d.ts +10 -0
  35. package/dist/cli/cli.d.ts.map +1 -0
  36. package/dist/cli/cli.js +72 -0
  37. package/dist/cli/cli.js.map +1 -0
  38. package/dist/cli/usage.d.ts +6 -0
  39. package/dist/cli/usage.d.ts.map +1 -0
  40. package/dist/cli/usage.js +126 -0
  41. package/dist/cli/usage.js.map +1 -0
  42. package/dist/fileset/check.d.ts +15 -0
  43. package/dist/fileset/check.d.ts.map +1 -0
  44. package/dist/fileset/check.js +68 -0
  45. package/dist/fileset/check.js.map +1 -0
  46. package/dist/fileset/constants.d.ts +13 -0
  47. package/dist/fileset/constants.d.ts.map +1 -0
  48. package/dist/fileset/constants.js +22 -0
  49. package/dist/fileset/constants.js.map +1 -0
  50. package/dist/fileset/diff.d.ts +16 -0
  51. package/dist/fileset/diff.d.ts.map +1 -0
  52. package/dist/fileset/diff.js +116 -0
  53. package/dist/fileset/diff.js.map +1 -0
  54. package/dist/fileset/execute.d.ts +29 -0
  55. package/dist/fileset/execute.d.ts.map +1 -0
  56. package/dist/fileset/execute.js +136 -0
  57. package/dist/fileset/execute.js.map +1 -0
  58. package/dist/fileset/gitignore.d.ts +16 -0
  59. package/dist/fileset/gitignore.d.ts.map +1 -0
  60. package/dist/fileset/gitignore.js +82 -0
  61. package/dist/fileset/gitignore.js.map +1 -0
  62. package/dist/fileset/index.d.ts +5 -0
  63. package/dist/fileset/index.d.ts.map +1 -0
  64. package/dist/fileset/index.js +21 -0
  65. package/dist/fileset/index.js.map +1 -0
  66. package/dist/fileset/list.d.ts +6 -0
  67. package/dist/fileset/list.d.ts.map +1 -0
  68. package/dist/fileset/list.js +11 -0
  69. package/dist/fileset/list.js.map +1 -0
  70. package/dist/fileset/markers.d.ts +22 -0
  71. package/dist/fileset/markers.d.ts.map +1 -0
  72. package/dist/fileset/markers.js +68 -0
  73. package/dist/fileset/markers.js.map +1 -0
  74. package/dist/fileset/package-files.d.ts +14 -0
  75. package/dist/fileset/package-files.d.ts.map +1 -0
  76. package/dist/fileset/package-files.js +81 -0
  77. package/dist/fileset/package-files.js.map +1 -0
  78. package/dist/fileset/purge.d.ts +12 -0
  79. package/dist/fileset/purge.d.ts.map +1 -0
  80. package/dist/fileset/purge.js +95 -0
  81. package/dist/fileset/purge.js.map +1 -0
  82. package/dist/fileset/test-utils.d.ts +12 -0
  83. package/dist/fileset/test-utils.d.ts.map +1 -0
  84. package/dist/fileset/test-utils.js +65 -0
  85. package/dist/fileset/test-utils.js.map +1 -0
  86. package/dist/index.d.ts +10 -8
  87. package/dist/index.d.ts.map +1 -1
  88. package/dist/index.js +12 -20
  89. package/dist/index.js.map +1 -1
  90. package/dist/npmdata-0.0.1.tgz +0 -0
  91. package/dist/package/action-check.d.ts +20 -0
  92. package/dist/package/action-check.d.ts.map +1 -0
  93. package/dist/package/action-check.js +61 -0
  94. package/dist/package/action-check.js.map +1 -0
  95. package/dist/package/action-extract.d.ts +21 -0
  96. package/dist/package/action-extract.d.ts.map +1 -0
  97. package/dist/package/action-extract.js +186 -0
  98. package/dist/package/action-extract.js.map +1 -0
  99. package/dist/package/action-init.d.ts +13 -0
  100. package/dist/package/action-init.d.ts.map +1 -0
  101. package/dist/package/action-init.js +77 -0
  102. package/dist/package/action-init.js.map +1 -0
  103. package/dist/package/action-list.d.ts +14 -0
  104. package/dist/package/action-list.d.ts.map +1 -0
  105. package/dist/package/action-list.js +46 -0
  106. package/dist/package/action-list.js.map +1 -0
  107. package/dist/package/action-purge.d.ts +21 -0
  108. package/dist/package/action-purge.d.ts.map +1 -0
  109. package/dist/package/action-purge.js +60 -0
  110. package/dist/package/action-purge.js.map +1 -0
  111. package/dist/package/config-merge.d.ts +18 -0
  112. package/dist/package/config-merge.d.ts.map +1 -0
  113. package/dist/package/config-merge.js +48 -0
  114. package/dist/package/config-merge.js.map +1 -0
  115. package/dist/package/config.d.ts +13 -0
  116. package/dist/package/config.d.ts.map +1 -0
  117. package/dist/package/config.js +29 -0
  118. package/dist/package/config.js.map +1 -0
  119. package/dist/package/content-replacements.d.ts +21 -0
  120. package/dist/package/content-replacements.d.ts.map +1 -0
  121. package/dist/package/content-replacements.js +96 -0
  122. package/dist/package/content-replacements.js.map +1 -0
  123. package/dist/package/index.d.ts +10 -0
  124. package/dist/package/index.d.ts.map +1 -0
  125. package/dist/package/index.js +16 -0
  126. package/dist/package/index.js.map +1 -0
  127. package/dist/package/symlinks.d.ts +17 -0
  128. package/dist/package/symlinks.d.ts.map +1 -0
  129. package/dist/package/symlinks.js +125 -0
  130. package/dist/package/symlinks.js.map +1 -0
  131. package/dist/types.d.ts +181 -277
  132. package/dist/types.d.ts.map +1 -1
  133. package/dist/types.js +0 -12
  134. package/dist/types.js.map +1 -1
  135. package/dist/utils.d.ts +25 -55
  136. package/dist/utils.d.ts.map +1 -1
  137. package/dist/utils.js +82 -181
  138. package/dist/utils.js.map +1 -1
  139. package/package.json +5 -3
  140. package/bin/npmdata.js +0 -4
  141. package/dist/cli.d.ts +0 -6
  142. package/dist/cli.d.ts.map +0 -1
  143. package/dist/cli.js +0 -570
  144. package/dist/cli.js.map +0 -1
  145. package/dist/consumer.d.ts +0 -74
  146. package/dist/consumer.d.ts.map +0 -1
  147. package/dist/consumer.js +0 -820
  148. package/dist/consumer.js.map +0 -1
  149. package/dist/main.d.ts +0 -3
  150. package/dist/main.d.ts.map +0 -1
  151. package/dist/main.js +0 -21
  152. package/dist/main.js.map +0 -1
  153. package/dist/publisher.d.ts +0 -38
  154. package/dist/publisher.d.ts.map +0 -1
  155. package/dist/publisher.js +0 -164
  156. package/dist/publisher.js.map +0 -1
  157. package/dist/runner.d.ts +0 -117
  158. package/dist/runner.d.ts.map +0 -1
  159. package/dist/runner.js +0 -812
  160. package/dist/runner.js.map +0 -1
package/dist/runner.js DELETED
@@ -1,812 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.buildCheckCommand = buildCheckCommand;
7
- exports.buildListCommand = buildListCommand;
8
- exports.buildPurgeCommand = buildPurgeCommand;
9
- exports.collectAllTags = collectAllTags;
10
- exports.printHelp = printHelp;
11
- exports.parseOutputFromArgv = parseOutputFromArgv;
12
- exports.parseDryRunFromArgv = parseDryRunFromArgv;
13
- exports.parseSilentFromArgv = parseSilentFromArgv;
14
- exports.parseVerboseFromArgv = parseVerboseFromArgv;
15
- exports.parseNoGitignoreFromArgv = parseNoGitignoreFromArgv;
16
- exports.parseUnmanagedFromArgv = parseUnmanagedFromArgv;
17
- exports.parseTagsFromArgv = parseTagsFromArgv;
18
- exports.filterEntriesByTags = filterEntriesByTags;
19
- exports.applySymlinks = applySymlinks;
20
- exports.applyContentReplacements = applyContentReplacements;
21
- exports.checkContentReplacements = checkContentReplacements;
22
- exports.runEntries = runEntries;
23
- exports.run = run;
24
- /* eslint-disable no-restricted-syntax */
25
- const node_child_process_1 = require("node:child_process");
26
- const node_fs_1 = __importDefault(require("node:fs"));
27
- const node_path_1 = __importDefault(require("node:path"));
28
- const minimatch_1 = require("minimatch");
29
- const utils_1 = require("./utils");
30
- /**
31
- * Extract just the package name (without version specifier) from a package spec string.
32
- * Delegates to the shared parsePackageSpec utility.
33
- */
34
- function parseEntryPackageName(spec) {
35
- const { name } = (0, utils_1.parsePackageSpec)(spec);
36
- return { name };
37
- }
38
- function buildExtractCommand(cliPath, entry, cwd = process.cwd()) {
39
- const outputFlag = ` --output "${node_path_1.default.resolve(cwd, entry.outputDir)}"`;
40
- const forceFlag = entry.force ? ' --force' : '';
41
- const keepExistingFlag = entry.keepExisting ? ' --keep-existing' : '';
42
- const gitignoreFlag = entry.gitignore === false ? ' --no-gitignore' : '';
43
- const unmanagedFlag = entry.unmanaged ? ' --unmanaged' : '';
44
- const silentFlag = entry.silent ? ' --silent' : '';
45
- const verboseFlag = entry.verbose ? ' --verbose' : '';
46
- const dryRunFlag = entry.dryRun ? ' --dry-run' : '';
47
- const upgradeFlag = entry.upgrade ? ' --upgrade' : '';
48
- const filesFlag = entry.files && entry.files.length > 0 ? ` --files "${entry.files.join(',')}"` : '';
49
- const contentRegexFlag = entry.contentRegexes && entry.contentRegexes.length > 0
50
- ? ` --content-regex "${entry.contentRegexes.join(',')}"`
51
- : '';
52
- return `node "${cliPath}" extract --packages "${entry.package}"${outputFlag}${forceFlag}${keepExistingFlag}${gitignoreFlag}${unmanagedFlag}${silentFlag}${verboseFlag}${dryRunFlag}${upgradeFlag}${filesFlag}${contentRegexFlag}`;
53
- }
54
- /**
55
- * Build a CLI command string that checks whether local files are in sync with the entry's package.
56
- */
57
- function buildCheckCommand(cliPath, entry, cwd = process.cwd()) {
58
- const outputFlag = ` --output "${node_path_1.default.resolve(cwd, entry.outputDir)}"`;
59
- const verboseFlag = entry.verbose ? ' --verbose' : '';
60
- const filesFlag = entry.files && entry.files.length > 0 ? ` --files "${entry.files.join(',')}"` : '';
61
- const contentRegexFlag = entry.contentRegexes && entry.contentRegexes.length > 0
62
- ? ` --content-regex "${entry.contentRegexes.join(',')}"`
63
- : '';
64
- return `node "${cliPath}" check --packages "${entry.package}"${outputFlag}${verboseFlag}${filesFlag}${contentRegexFlag}`;
65
- }
66
- /**
67
- * Build a CLI command string that lists all managed files in the given output directory.
68
- */
69
- function buildListCommand(cliPath, outputDir, cwd = process.cwd(), verbose = false) {
70
- const resolvedOutput = node_path_1.default.resolve(cwd, outputDir);
71
- const verboseFlag = verbose ? ' --verbose' : '';
72
- return `node "${cliPath}" list --output "${resolvedOutput}"${verboseFlag}`;
73
- }
74
- /**
75
- * Build a CLI command string that purges (removes) all managed files for the entry's package
76
- * from its output directory. No package installation is required.
77
- */
78
- function buildPurgeCommand(cliPath, entry, cwd = process.cwd()) {
79
- const { name } = parseEntryPackageName(entry.package);
80
- const outputFlag = ` --output "${node_path_1.default.resolve(cwd, entry.outputDir)}"`;
81
- // Propagate silent/dry-run/verbose settings from the entry if present.
82
- const silentFlag = entry.silent ? ' --silent' : '';
83
- const verboseFlag = entry.verbose ? ' --verbose' : '';
84
- const dryRunFlag = entry.dryRun ? ' --dry-run' : '';
85
- return `node "${cliPath}" purge --packages "${name}"${outputFlag}${silentFlag}${verboseFlag}${dryRunFlag}`;
86
- }
87
- /**
88
- * Collects all unique tags that appear across the given npmdata entries, sorted alphabetically.
89
- */
90
- function collectAllTags(entries) {
91
- const tagSet = new Set();
92
- for (const entry of entries) {
93
- if (entry.tags) {
94
- for (const tag of entry.tags) {
95
- tagSet.add(tag);
96
- }
97
- }
98
- }
99
- return Array.from(tagSet).sort();
100
- }
101
- /**
102
- * Prints a help message to stdout, listing the extract action, all options, and available tags.
103
- */
104
- function printHelp(packageName, availableTags) {
105
- const tagsLine = availableTags.length > 0 ? availableTags.join(', ') : '(none defined in package.json)';
106
- const exampleTag = availableTags.length > 0 ? availableTags[0] : 'my-tag';
107
- process.stdout.write([
108
- `Usage: ${packageName} <action> [options]`,
109
- '',
110
- 'Actions:',
111
- ' extract Extract files from the source package(s) defined in package.json',
112
- ' check Verify local files are in sync with the source package(s)',
113
- ' list List all files managed by npmdata in the output directories',
114
- ' purge Remove all managed files previously extracted',
115
- '',
116
- 'Options:',
117
- ' --help Show this help message',
118
- ' --output, -o <dir> Base directory for resolving all outputDir paths (default: cwd)',
119
- ' --dry-run Simulate changes without writing or deleting any files',
120
- ' --tags <tag1,tag2> Limit to entries whose tags overlap (comma-separated)',
121
- ' --no-gitignore Disable .gitignore management for every entry (overrides per-entry setting)',
122
- ' --unmanaged Run every entry in unmanaged mode (overrides per-entry setting)',
123
- ' --verbose, -v Print detailed progress information for each step',
124
- '',
125
- `Available tags: ${tagsLine}`,
126
- '',
127
- 'Examples:',
128
- ` ${packageName} extract`,
129
- ' Extract files for all entries defined in package.json',
130
- '',
131
- ` ${packageName} extract --output <dir>`,
132
- ' Extract files, resolving all outputDir paths relative to <dir> instead of cwd',
133
- '',
134
- ` ${packageName} extract --dry-run`,
135
- ' Preview what would be extracted without writing any files',
136
- '',
137
- ` ${packageName} extract --tags ${exampleTag}`,
138
- ` Extract files only for entries tagged "${exampleTag}"`,
139
- '',
140
- ` ${packageName} check`,
141
- ' Check if local files are in sync with the source packages',
142
- '',
143
- ` ${packageName} list`,
144
- ' List all files managed by npmdata in the output directories',
145
- '',
146
- ` ${packageName} purge`,
147
- ' Remove all managed files from the output directories',
148
- '',
149
- ].join('\n'));
150
- }
151
- /**
152
- * Parses --output (or -o) from an argv array and returns the path string.
153
- * Returns undefined when the flag is not present.
154
- */
155
- function parseOutputFromArgv(argv) {
156
- const idx = argv.findIndex((a) => a === '--output' || a === '-o');
157
- if (idx === -1 || idx + 1 >= argv.length) {
158
- // eslint-disable-next-line no-undefined
159
- return undefined;
160
- }
161
- return argv[idx + 1];
162
- }
163
- /**
164
- * Returns true when --dry-run appears in the argv array.
165
- */
166
- function parseDryRunFromArgv(argv) {
167
- return argv.includes('--dry-run');
168
- }
169
- /**
170
- * Returns true when --silent appears in the argv array.
171
- */
172
- function parseSilentFromArgv(argv) {
173
- return argv.includes('--silent');
174
- }
175
- /**
176
- * Returns true when --verbose or -v appears in the argv array.
177
- */
178
- function parseVerboseFromArgv(argv) {
179
- return argv.includes('--verbose') || argv.includes('-v');
180
- }
181
- /**
182
- * Returns true when --no-gitignore appears in the argv array.
183
- * When true, overrides the gitignore setting of every entry to false.
184
- */
185
- function parseNoGitignoreFromArgv(argv) {
186
- return argv.includes('--no-gitignore');
187
- }
188
- /**
189
- * Returns true when --unmanaged appears in the argv array.
190
- * When true, overrides the unmanaged setting of every entry to true.
191
- */
192
- function parseUnmanagedFromArgv(argv) {
193
- return argv.includes('--unmanaged');
194
- }
195
- /**
196
- * Parses --tags from an argv array and returns the list of requested tags (split by comma).
197
- * Returns an empty array when --tags is not present.
198
- */
199
- function parseTagsFromArgv(argv) {
200
- const idx = argv.indexOf('--tags');
201
- if (idx === -1 || idx + 1 >= argv.length) {
202
- return [];
203
- }
204
- return argv[idx + 1]
205
- .split(',')
206
- .map((t) => t.trim())
207
- .filter(Boolean);
208
- }
209
- /**
210
- * Filter entries by requested tags. When no tags are requested all entries pass through.
211
- * When tags are requested only entries that share at least one tag with the requested list
212
- * are included.
213
- */
214
- function filterEntriesByTags(entries, requestedTags) {
215
- if (requestedTags.length === 0) {
216
- return entries;
217
- }
218
- return entries.filter((entry) => entry.tags && entry.tags.some((t) => requestedTags.includes(t)));
219
- }
220
- // ─── Managed path helpers ──────────────────────────────────────────────────────
221
- /**
222
- * From the flat list of managed file paths (relative to outputDir) recorded in
223
- * the .npmdata marker, derive every unique path that can be symlinked: each
224
- * file itself plus every intermediate ancestor directory.
225
- *
226
- * Example: 'skills/skill-a/README.md' yields
227
- * 'skills', 'skills/skill-a', 'skills/skill-a/README.md'
228
- */
229
- function managedPathsWithAncestors(managedFiles) {
230
- const paths = new Set();
231
- for (const mf of managedFiles) {
232
- // eslint-disable-next-line functional/immutable-data
233
- paths.add(mf.path);
234
- const parts = mf.path.split('/');
235
- // Add each ancestor directory by accumulating path segments.
236
- parts.slice(0, -1).reduce((prefix, seg) => {
237
- const ancestor = prefix ? `${prefix}/${seg}` : seg;
238
- // eslint-disable-next-line functional/immutable-data
239
- paths.add(ancestor);
240
- return ancestor;
241
- }, '');
242
- }
243
- return Array.from(paths);
244
- }
245
- /**
246
- * Read the .npmdata marker from outputDir and return managed file metadata.
247
- * Returns an empty array when the marker does not exist.
248
- */
249
- function readManagedFiles(outputDir) {
250
- const markerPath = node_path_1.default.join(outputDir, '.npmdata');
251
- return node_fs_1.default.existsSync(markerPath) ? (0, utils_1.readCsvMarker)(markerPath) : [];
252
- }
253
- /**
254
- * Collect all existing symlinks in `targetDir` whose resolved (or as-written)
255
- * link target starts with `outputDir`. Returns a map of basename → resolved
256
- * target path. Dead symlinks that still point into outputDir are included so
257
- * that they can be cleaned up.
258
- */
259
- function collectManagedSymlinks(targetDir, outputDir) {
260
- const owned = new Map();
261
- if (!node_fs_1.default.existsSync(targetDir))
262
- return owned;
263
- // Resolve outputDir through any intermediate symlinks (e.g. /var → /private/var on macOS)
264
- // so prefix comparisons work correctly on all platforms.
265
- // eslint-disable-next-line functional/no-let, functional/no-try-statements
266
- let resolvedOutputDir = outputDir;
267
- // eslint-disable-next-line functional/no-try-statements
268
- try {
269
- resolvedOutputDir = node_fs_1.default.realpathSync(outputDir);
270
- }
271
- catch {
272
- // If outputDir does not exist, fall back to the raw path.
273
- }
274
- const normalizedOutput = resolvedOutputDir.endsWith(node_path_1.default.sep)
275
- ? resolvedOutputDir
276
- : `${resolvedOutputDir}${node_path_1.default.sep}`;
277
- for (const name of node_fs_1.default.readdirSync(targetDir)) {
278
- const symlinkPath = node_path_1.default.join(targetDir, name);
279
- const lstat = node_fs_1.default.lstatSync(symlinkPath);
280
- if (lstat.isSymbolicLink()) {
281
- // Try to resolve (handles live symlinks).
282
- // eslint-disable-next-line functional/no-try-statements
283
- try {
284
- const resolved = node_fs_1.default.realpathSync(symlinkPath);
285
- if (resolved === resolvedOutputDir || resolved.startsWith(normalizedOutput)) {
286
- owned.set(name, resolved);
287
- }
288
- }
289
- catch {
290
- // Dead symlink – read the raw link target to see if it points into outputDir.
291
- const rawTarget = node_fs_1.default.readlinkSync(symlinkPath);
292
- const absTarget = node_path_1.default.resolve(targetDir, rawTarget);
293
- const resolvedAbsTarget = absTarget; // raw path is enough for dead-link check
294
- if (resolvedAbsTarget === outputDir ||
295
- resolvedAbsTarget.startsWith(`${outputDir}${node_path_1.default.sep}`)) {
296
- owned.set(name, absTarget);
297
- }
298
- }
299
- }
300
- }
301
- return owned;
302
- }
303
- /**
304
- * Determine the symlink action for a single target path.
305
- * Returns 'create' when the path does not exist, 'update' when an out-of-date
306
- * managed symlink exists, or 'skip' when nothing should be done.
307
- */
308
- function symlinkAction(symlinkPath, sourcePath, isManaged) {
309
- // eslint-disable-next-line functional/no-try-statements
310
- try {
311
- const lstat = node_fs_1.default.lstatSync(symlinkPath);
312
- if (!lstat.isSymbolicLink())
313
- return 'skip'; // Non-symlink – never clobber.
314
- if (!isManaged)
315
- return 'skip'; // Not managed by npmdata – leave alone.
316
- // Managed symlink: only recreate if the target has drifted.
317
- // eslint-disable-next-line functional/no-try-statements
318
- try {
319
- return node_fs_1.default.realpathSync(symlinkPath) === sourcePath ? 'skip' : 'update';
320
- }
321
- catch {
322
- return 'update'; // Dead link – recreate.
323
- }
324
- }
325
- catch {
326
- return 'create'; // Path does not exist.
327
- }
328
- }
329
- // ─── Post-extract operations ───────────────────────────────────────────────────
330
- /**
331
- * Apply the symlink configs from an extraction entry.
332
- *
333
- * For each config:
334
- * 1. Expands the `source` glob inside the resolved `outputDir`.
335
- * 2. Ensures the `target` directory exists.
336
- * 3. Removes stale symlinks from the target dir that previously pointed into
337
- * outputDir but are no longer matched by the current glob result.
338
- * 4. Creates (or updates) symlinks for every matched file/directory.
339
- *
340
- * Only symlinks whose targets live inside outputDir are managed; any other
341
- * symlinks in the target directory are left untouched.
342
- */
343
- function applySymlinks(entry, cwd = process.cwd()) {
344
- if (!entry.symlinks || entry.symlinks.length === 0)
345
- return;
346
- const outputDir = node_path_1.default.resolve(cwd, entry.outputDir);
347
- const allManagedPaths = managedPathsWithAncestors(readManagedFiles(outputDir));
348
- for (const cfg of entry.symlinks) {
349
- const targetDir = node_path_1.default.resolve(cwd, cfg.target);
350
- node_fs_1.default.mkdirSync(targetDir, { recursive: true });
351
- // Build desired symlink map from managed paths (files + ancestor dirs) matching the source pattern.
352
- const desired = new Map();
353
- for (const relPath of allManagedPaths) {
354
- if ((0, minimatch_1.minimatch)(relPath, cfg.source, { dot: true })) {
355
- const absMatch = node_path_1.default.join(outputDir, relPath);
356
- desired.set(node_path_1.default.basename(absMatch), absMatch);
357
- }
358
- }
359
- // Remove stale managed symlinks that are no longer in the desired set.
360
- const existing = collectManagedSymlinks(targetDir, outputDir);
361
- for (const [basename] of existing) {
362
- if (!desired.has(basename)) {
363
- const symlinkPath = node_path_1.default.join(targetDir, basename);
364
- node_fs_1.default.unlinkSync(symlinkPath);
365
- if (!entry.silent) {
366
- // eslint-disable-next-line no-console
367
- console.log(`D\t${node_path_1.default.relative(cwd, symlinkPath)}`);
368
- }
369
- }
370
- }
371
- // Create or update symlinks.
372
- for (const [basename, sourcePath] of desired) {
373
- const symlinkPath = node_path_1.default.join(targetDir, basename);
374
- const action = symlinkAction(symlinkPath, sourcePath, existing.has(basename));
375
- if (action === 'update') {
376
- node_fs_1.default.unlinkSync(symlinkPath);
377
- node_fs_1.default.symlinkSync(sourcePath, symlinkPath);
378
- if (!entry.silent) {
379
- // eslint-disable-next-line no-console
380
- console.log(`M\t${node_path_1.default.relative(cwd, symlinkPath)}`);
381
- }
382
- }
383
- else if (action === 'create') {
384
- node_fs_1.default.symlinkSync(sourcePath, symlinkPath);
385
- if (!entry.silent) {
386
- // eslint-disable-next-line no-console
387
- console.log(`A\t${node_path_1.default.relative(cwd, symlinkPath)}`);
388
- }
389
- }
390
- // 'skip' → do nothing
391
- }
392
- }
393
- }
394
- /**
395
- * Apply the content-replacement configs from an extraction entry.
396
- *
397
- * For each config:
398
- * 1. Expands the `files` glob inside `cwd`.
399
- * 2. Reads each matched file.
400
- * 3. Applies the regex replacement (global, multiline).
401
- * 4. Writes the file back only when the content changed.
402
- */
403
- function applyContentReplacements(entry, cwd = process.cwd()) {
404
- if (!entry.contentReplacements || entry.contentReplacements.length === 0)
405
- return;
406
- const outputDir = node_path_1.default.resolve(cwd, entry.outputDir);
407
- const managedFiles = readManagedFiles(outputDir);
408
- for (const cfg of entry.contentReplacements) {
409
- const regex = new RegExp(cfg.match, 'gm');
410
- for (const mf of managedFiles) {
411
- if ((0, minimatch_1.minimatch)(mf.path, cfg.files, { dot: true })) {
412
- const filePath = node_path_1.default.join(outputDir, mf.path);
413
- if (node_fs_1.default.existsSync(filePath)) {
414
- const original = node_fs_1.default.readFileSync(filePath, 'utf8');
415
- const updated = original.replace(regex, cfg.replace);
416
- if (updated !== original) {
417
- node_fs_1.default.writeFileSync(filePath, updated, 'utf8');
418
- }
419
- }
420
- }
421
- }
422
- }
423
- }
424
- /**
425
- * Check whether the content-replacement configs from an extraction entry are
426
- * currently in effect in the workspace.
427
- *
428
- * Returns a list of file paths where the replacement pattern still matches
429
- * (i.e. the replacement has not been applied or has drifted). An empty list
430
- * means everything is in sync.
431
- */
432
- function checkContentReplacements(entry, cwd = process.cwd()) {
433
- if (!entry.contentReplacements || entry.contentReplacements.length === 0)
434
- return [];
435
- const outputDir = node_path_1.default.resolve(cwd, entry.outputDir);
436
- const managedFiles = readManagedFiles(outputDir);
437
- const outOfSync = [];
438
- for (const cfg of entry.contentReplacements) {
439
- const regex = new RegExp(cfg.match, 'gm');
440
- for (const mf of managedFiles) {
441
- if ((0, minimatch_1.minimatch)(mf.path, cfg.files, { dot: true })) {
442
- const filePath = node_path_1.default.join(outputDir, mf.path);
443
- if (node_fs_1.default.existsSync(filePath)) {
444
- const content = node_fs_1.default.readFileSync(filePath, 'utf8');
445
- // A file is out of sync when applying the replacement would change it.
446
- const expected = content.replace(regex, cfg.replace);
447
- if (expected !== content) {
448
- // eslint-disable-next-line functional/immutable-data
449
- outOfSync.push(filePath);
450
- }
451
- }
452
- }
453
- }
454
- }
455
- return outOfSync;
456
- }
457
- // ─── Action handlers ───────────────────────────────────────────────────────────
458
- /**
459
- * Run a shell command, capturing its stdout while inheriting stderr.
460
- * The captured stdout is immediately written to process.stdout so the caller
461
- * sees it in real time (well, after the child exits). Returns the full
462
- * captured stdout string and the child's exit code. Non-zero exit codes do
463
- * NOT throw; callers are responsible for checking exitCode.
464
- */
465
- function runCommandCapture(command, cwd) {
466
- // eslint-disable-next-line functional/no-try-statements
467
- try {
468
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
469
- const stdout = (0, node_child_process_1.execSync)(command, {
470
- encoding: 'utf8',
471
- cwd,
472
- stdio: ['inherit', 'pipe', 'inherit'],
473
- }) ?? '';
474
- process.stdout.write(stdout);
475
- return { stdout, exitCode: 0 };
476
- }
477
- catch (error) {
478
- const err = error;
479
- const stdout = err.stdout ?? '';
480
- process.stdout.write(stdout);
481
- return { stdout, exitCode: err.status ?? 1 };
482
- }
483
- }
484
- // eslint-disable-next-line complexity
485
- function runExtract(entries, excludedEntries, cliPath, runCwd, dryRunFromArgv, silentFromArgv, verboseFromArgv, noGitignoreFromArgv, unmanagedFromArgv) {
486
- if (verboseFromArgv) {
487
- // eslint-disable-next-line no-console
488
- console.log(`[verbose] extract: processing ${entries.length} entr${entries.length === 1 ? 'y' : 'ies'} (cwd: ${runCwd})`);
489
- }
490
- // eslint-disable-next-line functional/no-let
491
- let totalAdded = 0;
492
- // eslint-disable-next-line functional/no-let
493
- let totalModified = 0;
494
- // eslint-disable-next-line functional/no-let
495
- let totalDeleted = 0;
496
- // eslint-disable-next-line functional/no-let
497
- let totalSkipped = 0;
498
- // eslint-disable-next-line functional/no-let
499
- let entryIndex = 0;
500
- for (const entry of entries) {
501
- const effectiveSilent = entry.silent || silentFromArgv;
502
- if (entryIndex > 0 && !effectiveSilent) {
503
- process.stdout.write('\n');
504
- }
505
- entryIndex += 1;
506
- const effectiveEntry = {
507
- ...entry,
508
- dryRun: entry.dryRun || dryRunFromArgv,
509
- silent: effectiveSilent,
510
- verbose: entry.verbose || verboseFromArgv,
511
- ...(noGitignoreFromArgv ? { gitignore: false } : {}),
512
- ...(unmanagedFromArgv ? { unmanaged: true } : {}),
513
- };
514
- if (verboseFromArgv) {
515
- // eslint-disable-next-line no-console
516
- console.log(`[verbose] extract: entry package=${entry.package} outputDir=${entry.outputDir}`);
517
- }
518
- node_fs_1.default.mkdirSync(node_path_1.default.resolve(runCwd, entry.outputDir), { recursive: true });
519
- const command = buildExtractCommand(cliPath, effectiveEntry, runCwd);
520
- if (verboseFromArgv) {
521
- // eslint-disable-next-line no-console
522
- console.log(`[verbose] extract: running command: ${command}`);
523
- }
524
- const { stdout: extractStdout, exitCode: extractExitCode } = runCommandCapture(command, runCwd);
525
- if (extractExitCode !== 0) {
526
- throw Object.assign(new Error('extract failed'), { status: extractExitCode });
527
- }
528
- const extractMatch = extractStdout.match(/Extraction complete:\s*(\d+) added,\s*(\d+) modified,\s*(\d+) deleted,\s*(\d+) skipped/);
529
- if (extractMatch) {
530
- totalAdded += Number.parseInt(extractMatch[1], 10);
531
- totalModified += Number.parseInt(extractMatch[2], 10);
532
- totalDeleted += Number.parseInt(extractMatch[3], 10);
533
- totalSkipped += Number.parseInt(extractMatch[4], 10);
534
- }
535
- if (!effectiveEntry.dryRun) {
536
- if (verboseFromArgv) {
537
- // eslint-disable-next-line no-console
538
- console.log(`[verbose] extract: applying symlinks for ${entry.package}`);
539
- }
540
- applySymlinks(effectiveEntry, runCwd);
541
- if (verboseFromArgv) {
542
- // eslint-disable-next-line no-console
543
- console.log(`[verbose] extract: applying content replacements for ${entry.package}`);
544
- }
545
- applyContentReplacements(entry, runCwd);
546
- }
547
- }
548
- // When a tag filter is active, purge managed files from excluded entries so that
549
- // the output directory contains only files from the currently active tag group.
550
- // Suppress the "Purging managed files..." banner for these implicit purges.
551
- for (const entry of excludedEntries) {
552
- if (verboseFromArgv) {
553
- // eslint-disable-next-line no-console
554
- console.log(`[verbose] extract: purging excluded entry ${entry.package} (tag filter active)`);
555
- }
556
- const effectiveEntry = {
557
- ...entry,
558
- dryRun: entry.dryRun || dryRunFromArgv,
559
- silent: true,
560
- };
561
- const command = buildPurgeCommand(cliPath, effectiveEntry, runCwd);
562
- (0, node_child_process_1.execSync)(command, { stdio: 'inherit', cwd: runCwd });
563
- }
564
- if (!silentFromArgv && entries.length > 1) {
565
- process.stdout.write(`\nTotal extracted: ${totalAdded} added, ${totalModified} modified, ${totalDeleted} deleted, ${totalSkipped} skipped${dryRunFromArgv ? ' (dry run)' : ''}\n`);
566
- }
567
- }
568
- function runCheck(entries, cliPath, runCwd, verboseFromArgv, unmanagedFromArgv) {
569
- const managedEntries = entries.filter((entry) => {
570
- const isUnmanaged = entry.unmanaged || unmanagedFromArgv;
571
- if (isUnmanaged && verboseFromArgv) {
572
- // eslint-disable-next-line no-console
573
- console.log(`[verbose] check: skipping unmanaged entry package=${entry.package} outputDir=${entry.outputDir}`);
574
- }
575
- return !isUnmanaged;
576
- });
577
- if (verboseFromArgv) {
578
- // eslint-disable-next-line no-console
579
- console.log(`[verbose] check: verifying ${managedEntries.length} entr${managedEntries.length === 1 ? 'y' : 'ies'} (cwd: ${runCwd})`);
580
- }
581
- // eslint-disable-next-line functional/no-let
582
- let outOfSyncFiles = [];
583
- // eslint-disable-next-line functional/no-let
584
- let checkIndex = 0;
585
- for (const entry of managedEntries) {
586
- if (checkIndex > 0) {
587
- process.stdout.write('\n');
588
- }
589
- checkIndex += 1;
590
- if (verboseFromArgv) {
591
- // eslint-disable-next-line no-console
592
- console.log(`[verbose] check: checking package=${entry.package} outputDir=${entry.outputDir}`);
593
- }
594
- const effectiveEntry = {
595
- ...entry,
596
- verbose: entry.verbose || verboseFromArgv,
597
- };
598
- const command = buildCheckCommand(cliPath, effectiveEntry, runCwd);
599
- if (verboseFromArgv) {
600
- // eslint-disable-next-line no-console
601
- console.log(`[verbose] check: running command: ${command}`);
602
- }
603
- const { exitCode: checkExitCode } = runCommandCapture(command, runCwd);
604
- if (checkExitCode !== 0) {
605
- throw Object.assign(new Error('check failed'), { status: checkExitCode });
606
- }
607
- if (verboseFromArgv) {
608
- // eslint-disable-next-line no-console
609
- console.log(`[verbose] check: checking content replacements for ${entry.package}`);
610
- }
611
- const entryOutOfSync = checkContentReplacements(entry, runCwd);
612
- for (const f of entryOutOfSync) {
613
- process.stderr.write(`content-replacement out of sync: ${f}\n`);
614
- }
615
- // eslint-disable-next-line functional/immutable-data
616
- outOfSyncFiles = [...outOfSyncFiles, ...entryOutOfSync];
617
- }
618
- if (outOfSyncFiles.length > 0) {
619
- throw Object.assign(new Error('content-replacements out of sync'), { status: 1 });
620
- }
621
- if (managedEntries.length > 1) {
622
- process.stdout.write(`\nTotal checked: ${managedEntries.length} packages\n`);
623
- }
624
- }
625
- function runList(allEntries, cliPath, runCwd, verboseFromArgv) {
626
- // Collect unique resolved output dirs (tag filter not applied; list is informational).
627
- const seenDirs = new Set();
628
- if (verboseFromArgv) {
629
- // eslint-disable-next-line no-console
630
- console.log(`[verbose] list: listing managed files across ${allEntries.length} entr${allEntries.length === 1 ? 'y' : 'ies'} (cwd: ${runCwd})`);
631
- }
632
- for (const entry of allEntries) {
633
- const resolvedDir = node_path_1.default.resolve(runCwd, entry.outputDir);
634
- if (!seenDirs.has(resolvedDir)) {
635
- seenDirs.add(resolvedDir);
636
- if (verboseFromArgv) {
637
- // eslint-disable-next-line no-console
638
- console.log(`[verbose] list: scanning directory ${resolvedDir}`);
639
- }
640
- const command = buildListCommand(cliPath, entry.outputDir, runCwd, verboseFromArgv);
641
- (0, node_child_process_1.execSync)(command, { stdio: 'inherit', cwd: runCwd });
642
- }
643
- }
644
- }
645
- // eslint-disable-next-line complexity
646
- function runPurge(entries, cliPath, runCwd, dryRunFromArgv, silentFromArgv, verboseFromArgv) {
647
- if (verboseFromArgv) {
648
- // eslint-disable-next-line no-console
649
- console.log(`[verbose] purge: processing ${entries.length} entr${entries.length === 1 ? 'y' : 'ies'} (cwd: ${runCwd})`);
650
- }
651
- // eslint-disable-next-line functional/no-let
652
- let totalDeleted = 0;
653
- // eslint-disable-next-line functional/no-let
654
- let purgeIndex = 0;
655
- for (const entry of entries) {
656
- const effectiveSilent = entry.silent || silentFromArgv;
657
- if (purgeIndex > 0 && !effectiveSilent) {
658
- process.stdout.write('\n');
659
- }
660
- purgeIndex += 1;
661
- const effectiveEntry = {
662
- ...entry,
663
- dryRun: entry.dryRun || dryRunFromArgv,
664
- silent: effectiveSilent,
665
- verbose: entry.verbose || verboseFromArgv,
666
- };
667
- if (verboseFromArgv) {
668
- // eslint-disable-next-line no-console
669
- console.log(`[verbose] purge: entry package=${entry.package} outputDir=${entry.outputDir}`);
670
- }
671
- const command = buildPurgeCommand(cliPath, effectiveEntry, runCwd);
672
- if (verboseFromArgv) {
673
- // eslint-disable-next-line no-console
674
- console.log(`[verbose] purge: running command: ${command}`);
675
- }
676
- const { stdout: purgeStdout, exitCode: purgeExitCode } = runCommandCapture(command, runCwd);
677
- if (purgeExitCode !== 0) {
678
- throw Object.assign(new Error('purge failed'), { status: purgeExitCode });
679
- }
680
- const purgeMatch = purgeStdout.match(/Purge complete:\s*(\d+) deleted/);
681
- if (purgeMatch) {
682
- totalDeleted += Number.parseInt(purgeMatch[1], 10);
683
- }
684
- if (!effectiveEntry.dryRun) {
685
- if (verboseFromArgv) {
686
- // eslint-disable-next-line no-console
687
- console.log(`[verbose] purge: cleaning up symlinks for ${entry.package}`);
688
- }
689
- applySymlinks(effectiveEntry, runCwd);
690
- }
691
- }
692
- if (!silentFromArgv && entries.length > 1) {
693
- process.stdout.write(`\nTotal purged: ${totalDeleted}${dryRunFromArgv ? ' (dry run)' : ''}\n`);
694
- }
695
- }
696
- /**
697
- * Run a given action for a list of pre-loaded npmdata entries.
698
- * Parses common flags (--tags, --output, --dry-run, --silent, --verbose, --no-gitignore,
699
- * --unmanaged) from argv and delegates to the appropriate action handler.
700
- *
701
- * Called from the CLI when a cosmiconfig configuration file is found and --packages is not
702
- * provided, so the same runner logic used by embedded data-package runners is reused.
703
- *
704
- * @param allEntries - Array of NpmdataExtractEntry loaded from the configuration.
705
- * @param action - One of 'extract', 'check', 'list', 'purge'.
706
- * @param argv - Full process.argv (or equivalent); [0] and [1] are the node binary and
707
- * script path which are sliced off internally.
708
- * @param cliPath - Absolute path to the npmdata CLI main.js that sub-processes will invoke.
709
- */
710
- function runEntries(allEntries, action, argv, cliPath) {
711
- const userArgs = argv.slice(2);
712
- const requestedTags = parseTagsFromArgv(argv);
713
- const entries = filterEntriesByTags(allEntries, requestedTags);
714
- const excludedEntries = requestedTags.length > 0 ? allEntries.filter((e) => !entries.includes(e)) : [];
715
- const parsedOutput = parseOutputFromArgv(userArgs);
716
- const runCwd = parsedOutput ? node_path_1.default.resolve(process.cwd(), parsedOutput) : process.cwd();
717
- const dryRunFromArgv = parseDryRunFromArgv(userArgs);
718
- const silentFromArgv = parseSilentFromArgv(userArgs);
719
- const verboseFromArgv = parseVerboseFromArgv(userArgs);
720
- const noGitignoreFromArgv = parseNoGitignoreFromArgv(userArgs);
721
- const unmanagedFromArgv = parseUnmanagedFromArgv(userArgs);
722
- if (verboseFromArgv) {
723
- // eslint-disable-next-line no-console
724
- console.log(`[verbose] runner: action=${action} entries=${entries.length} cwd=${runCwd}`);
725
- }
726
- // eslint-disable-next-line functional/no-try-statements
727
- try {
728
- if (action === 'extract') {
729
- runExtract(entries, excludedEntries, cliPath, runCwd, dryRunFromArgv, silentFromArgv, verboseFromArgv, noGitignoreFromArgv, unmanagedFromArgv);
730
- }
731
- else if (action === 'check') {
732
- runCheck(entries, cliPath, runCwd, verboseFromArgv, unmanagedFromArgv);
733
- }
734
- else if (action === 'list') {
735
- runList(allEntries, cliPath, runCwd, verboseFromArgv);
736
- }
737
- else if (action === 'purge') {
738
- runPurge(entries, cliPath, runCwd, dryRunFromArgv, silentFromArgv, verboseFromArgv);
739
- }
740
- }
741
- catch (error) {
742
- // The child process already printed the error via stdio:inherit.
743
- // Exit with the child's exit code to suppress the Node.js stack trace.
744
- const status = error?.status;
745
- // eslint-disable-next-line unicorn/no-process-exit
746
- process.exit(status ?? 1);
747
- }
748
- }
749
- /**
750
- * Runs extraction for each entry defined in the publishable package's package.json "npmdata" array.
751
- * Invokes the npmdata CLI once per entry so that all CLI output and error handling is preserved.
752
- * Called from the minimal generated bin script with its own __dirname as binDir.
753
- *
754
- * Pass --tags <tag1,tag2> to limit processing to entries whose tags overlap with the given list.
755
- */
756
- function run(binDir, argv = process.argv) {
757
- const pkgJsonPath = node_path_1.default.join(binDir, '../package.json');
758
- const pkg = JSON.parse(node_fs_1.default.readFileSync(pkgJsonPath).toString());
759
- const allEntries = pkg.npmdata?.sets && pkg.npmdata.sets.length > 0
760
- ? pkg.npmdata.sets
761
- : [{ package: pkg.name, outputDir: '.' }];
762
- const userArgs = argv.slice(2);
763
- if (userArgs.includes('--help')) {
764
- printHelp(pkg.name, collectAllTags(allEntries));
765
- return;
766
- }
767
- // Default to 'extract' when no action is provided or the first arg is a flag.
768
- const action = userArgs.length === 0 || userArgs[0].startsWith('-') ? 'extract' : userArgs[0];
769
- if (!['extract', 'check', 'list', 'purge'].includes(action)) {
770
- process.stderr.write(`Error: unknown action '${action}'. Use 'extract', 'check', 'list', or 'purge'.\n\n`);
771
- printHelp(pkg.name, collectAllTags(allEntries));
772
- return;
773
- }
774
- const requestedTags = parseTagsFromArgv(argv);
775
- const entries = filterEntriesByTags(allEntries, requestedTags);
776
- const excludedEntries = requestedTags.length > 0 ? allEntries.filter((e) => !entries.includes(e)) : [];
777
- const cliPath = require.resolve('npmdata/dist/main.js', { paths: [binDir] });
778
- const parsedOutput = parseOutputFromArgv(userArgs);
779
- const runCwd = parsedOutput ? node_path_1.default.resolve(process.cwd(), parsedOutput) : process.cwd();
780
- const dryRunFromArgv = parseDryRunFromArgv(userArgs);
781
- const silentFromArgv = parseSilentFromArgv(userArgs);
782
- const verboseFromArgv = parseVerboseFromArgv(userArgs);
783
- const noGitignoreFromArgv = parseNoGitignoreFromArgv(userArgs);
784
- const unmanagedFromArgv = parseUnmanagedFromArgv(userArgs);
785
- if (verboseFromArgv) {
786
- // eslint-disable-next-line no-console
787
- console.log(`[verbose] runner: action=${action} entries=${entries.length} cwd=${runCwd}`);
788
- }
789
- // eslint-disable-next-line functional/no-try-statements
790
- try {
791
- if (action === 'extract') {
792
- runExtract(entries, excludedEntries, cliPath, runCwd, dryRunFromArgv, silentFromArgv, verboseFromArgv, noGitignoreFromArgv, unmanagedFromArgv);
793
- }
794
- else if (action === 'check') {
795
- runCheck(entries, cliPath, runCwd, verboseFromArgv, unmanagedFromArgv);
796
- }
797
- else if (action === 'list') {
798
- runList(allEntries, cliPath, runCwd, verboseFromArgv);
799
- }
800
- else if (action === 'purge') {
801
- runPurge(entries, cliPath, runCwd, dryRunFromArgv, silentFromArgv, verboseFromArgv);
802
- }
803
- }
804
- catch (error) {
805
- // The child process already printed the error via stdio:inherit.
806
- // Exit with the child's exit code to suppress the Node.js stack trace.
807
- const status = error?.status;
808
- // eslint-disable-next-line unicorn/no-process-exit
809
- process.exit(status ?? 1);
810
- }
811
- }
812
- //# sourceMappingURL=runner.js.map