npmdata 0.2.1 → 0.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.
package/README.md CHANGED
@@ -1,8 +1,368 @@
1
- # npmdata — Developer Notes
1
+ # npmdata
2
2
 
3
- This document covers the internal architecture for contributors working on this library.
3
+ Publish folders as npm packages and extract them in any workspace. Use it to distribute shared assets — ML datasets, documentation, ADRs, configuration files — across multiple projects through any npm-compatible registry.
4
4
 
5
- ## Module overview
5
+ ## How it works
6
+
7
+ - **Publisher**: a project that has folders to share. Running `init` prepares its `package.json` so those folders are included when the package is published.
8
+ - **Consumer**: any project that installs that package and runs `extract` to download the files locally. A `.publisher` marker file is written alongside the managed files to track ownership and enable safe updates.
9
+
10
+ ## Quick start
11
+
12
+ ### 1. Prepare the publisher package
13
+
14
+ In the project whose folders you want to share:
15
+
16
+ ```sh
17
+ # share specific folders by glob pattern (required)
18
+ pnpm dlx npmdata init --files "docs/**,data/**,configs/**"
19
+
20
+ # also bundle an additional package so consumers get data from both sources
21
+ pnpm dlx npmdata init --files "docs/**" --packages shared-configs@^1.0.0
22
+
23
+ # share multiple additional packages at once
24
+ pnpm dlx npmdata init --files "docs/**" --packages "shared-configs@^1.0.0,base-templates@2.x"
25
+
26
+ # skip .gitignore entries for managed files (gitignore is enabled by default)
27
+ pnpm dlx npmdata init --files "docs/**,data/**" --no-gitignore
28
+
29
+ # mark extracted files as unmanaged so consumers can edit them freely;
30
+ # files won't be tracked, made read-only, or added to .gitignore
31
+ pnpm dlx npmdata init --files "templates/**" --unmanaged
32
+ ```
33
+
34
+ `init` updates `package.json` with the right `files`, `bin`, and `dependencies` fields so those folders are included when the package is published, and writes a thin `bin/npmdata.js` entry point. Then publish normally:
35
+
36
+ ```sh
37
+ npm publish
38
+ ```
39
+
40
+ ### 2. Extract files in a consumer project
41
+
42
+ ```sh
43
+ # extract all files from the package
44
+ npx npmdata extract --packages my-shared-assets --output ./data
45
+
46
+ # extract from a specific version
47
+ npx npmdata extract --packages my-shared-assets@^2.0.0 --output ./data
48
+
49
+ # extract from multiple packages at once
50
+ npx npmdata extract --packages "my-shared-assets@^2.0.0,another-pkg@1.x" --output ./data
51
+
52
+ # extract only markdown files
53
+ npx npmdata extract --packages my-shared-assets --files "**/*.md" --output ./docs
54
+
55
+ # extract only files whose content matches a regex
56
+ npx npmdata extract --packages my-shared-assets --content-regex "env: production" --output ./configs
57
+
58
+ # overwrite files that are unmanaged or owned by a different package;
59
+ # the new package takes ownership in the marker file
60
+ npx npmdata extract --packages my-shared-assets --output ./data --force
61
+
62
+ # skip .gitignore entries for managed files (gitignore is enabled by default)
63
+ npx npmdata extract --packages my-shared-assets --output ./data --no-gitignore
64
+
65
+ # write files without a .npmdata marker or .gitignore entry; files won't be read-only
66
+ # and won't be tracked by npmdata; existing files are left unchanged
67
+ npx npmdata extract --packages my-shared-assets --output ./data --unmanaged
68
+
69
+ # preview what would change without writing any files
70
+ npx npmdata extract --packages my-shared-assets --output ./data --dry-run
71
+
72
+ # force-reinstall the package even if already installed (e.g. after a floating tag moves)
73
+ npx npmdata extract --packages my-shared-assets@latest --output ./data --upgrade
74
+ ```
75
+
76
+ `extract` logs every file change as it happens:
77
+
78
+ ```
79
+ A data/users-dataset/user1.json
80
+ M data/configs/app.config.json
81
+ D data/old-file.json
82
+ ```
83
+
84
+ If the published package includes its own bin script (normally when it's prepared using "init") you can also call it directly so it extracts data that is inside the package itself:
85
+
86
+ ```sh
87
+ npx my-shared-assets extract --output ./data
88
+ npx my-shared-assets check --output ./data
89
+ ```
90
+
91
+ When the data package defines multiple `npmdata` entries in its `package.json`, you can limit which entries are processed using the `--tags` option. Only entries whose `tags` list includes at least one of the requested tags will be extracted; entries with no tags are skipped when a tag filter is active.
92
+
93
+ ```sh
94
+ # run only entries tagged with "prod"
95
+ npx my-shared-assets --tags prod
96
+
97
+ # run entries tagged with either "prod" or "staging"
98
+ npx my-shared-assets --tags prod,staging
99
+ ```
100
+
101
+ To use tags, add a `tags` array to each `npmdata` entry in the data package's `package.json`:
102
+
103
+ ```json
104
+ {
105
+ "npmdata": [
106
+ { "package": "my-shared-assets", "outputDir": "./data", "tags": ["prod"] },
107
+ { "package": "my-dev-assets", "outputDir": "./dev-data", "tags": ["dev", "staging"] }
108
+ ]
109
+ }
110
+ ```
111
+
112
+ Check the /examples folder to see this in action
113
+
114
+ ### 3. Check files are in sync
115
+
116
+ ```sh
117
+ npx npmdata check --packages my-shared-assets --output ./data
118
+ # exit 0 = in sync, exit 2 = differences found
119
+
120
+ # check multiple packages
121
+ npx npmdata check --packages "my-shared-assets,another-pkg" --output ./data
122
+ ```
123
+
124
+ The check command reports differences per package:
125
+
126
+ ```
127
+ my-shared-assets@^2.0.0 FAIL
128
+ missing: data/new-file.json
129
+ modified: data/configs/app.config.json
130
+ extra: data/old-file.json
131
+ ```
132
+
133
+ ### 4. List managed files
134
+
135
+ ```sh
136
+ # list all files managed by npmdata in an output directory
137
+ npx npmdata list --output ./data
138
+ ```
139
+
140
+ Output is grouped by package:
141
+
142
+ ```
143
+ my-shared-assets@2.1.0
144
+ data/users-dataset/user1.json
145
+ data/configs/app.config.json
146
+
147
+ another-pkg@1.0.0
148
+ data/other-file.txt
149
+ ```
150
+
151
+ ### 5. Purge managed files
152
+
153
+ Remove all files previously extracted by one or more packages without touching any other files in the output directory. No network access or package installation is required — only the local `.npmdata` marker state is used.
154
+
155
+ ```sh
156
+ # remove all files managed by a package
157
+ npx npmdata purge --packages my-shared-assets --output ./data
158
+
159
+ # purge multiple packages at once
160
+ npx npmdata purge --packages "my-shared-assets,another-pkg" --output ./data
161
+
162
+ # preview what would be deleted without removing anything
163
+ npx npmdata purge --packages my-shared-assets --output ./data --dry-run
164
+ ```
165
+
166
+ After a purge, the corresponding entries are removed from the `.npmdata` marker file and any empty directories are cleaned up. `.gitignore` sections written by `extract` are also removed.
167
+
168
+ ## CLI reference
169
+
170
+ ```
171
+ Usage:
172
+ npx npmdata [init|extract|check|list|purge] [options]
173
+
174
+ Commands:
175
+ init Set up publishing configuration in a package
176
+ extract Extract files from a published package into a local directory
177
+ check Verify local files are in sync with the published package
178
+ list List all files managed by npmdata in an output directory
179
+ purge Remove all managed files previously extracted by given packages
180
+
181
+ Global options:
182
+ --help, -h Show help
183
+ --version, -v Show version
184
+
185
+ Init options:
186
+ --files <patterns> Comma-separated glob patterns of files to publish (required)
187
+ e.g. "docs/**,data/**,configs/*.json"
188
+ --packages <specs> Comma-separated additional package specs to bundle as data sources.
189
+ Each spec is "name" or "name@version", e.g.
190
+ "shared-configs@^1.0.0,base-templates@2.x".
191
+ Listed under `npmdata.additionalPackages` in package.json and
192
+ added to `dependencies` so consumers pull data from all of them.
193
+ --no-gitignore Skip adding .gitignore entries for managed files
194
+ (gitignore is enabled by default)
195
+ --unmanaged Mark all generated npmdata entries as unmanaged: extracted files
196
+ are written without a .npmdata marker, without updating .gitignore,
197
+ and without being made read-only. Existing files are skipped.
198
+
199
+ Extract options:
200
+ --packages <specs> Comma-separated package specs (required).
201
+ Each spec is "name" or "name@version", e.g.
202
+ "my-pkg@^1.0.0,other-pkg@2.x"
203
+ --output, -o <dir> Output directory (default: current directory)
204
+ --force Overwrite existing unmanaged files or files owned by a different package
205
+ --no-gitignore Skip creating/updating .gitignore (gitignore is enabled by default)
206
+ --unmanaged Write files without a .npmdata marker, .gitignore update, or read-only
207
+ flag. Existing files are skipped. Files can be freely edited afterwards
208
+ and are not tracked by npmdata.
209
+ --files <patterns> Comma-separated glob patterns to filter files
210
+ --content-regex <regex> Regex to filter files by content
211
+ --dry-run Preview changes without writing any files
212
+ --upgrade Reinstall the package even if already present
213
+
214
+ Check options:
215
+ --packages <specs> Same format as extract (required)
216
+ --output, -o <dir> Output directory to check (default: current directory)
217
+
218
+ Purge options:
219
+ --packages <specs> Comma-separated package names whose managed files should be removed
220
+ --output, -o <dir> Output directory to purge from (default: current directory)
221
+ --dry-run Simulate purge without removing any files
222
+ --silent Suppress per-file output
223
+
224
+ List options:
225
+ --output, -o <dir> Output directory to inspect (default: current directory)
226
+ ```
227
+
228
+ ## Library usage
229
+
230
+ `npmdata` also exports a programmatic API:
231
+
232
+ ```typescript
233
+ import { extract, check, list, purge, initPublisher, parsePackageSpec, isBinaryFile } from 'npmdata';
234
+ import type { ConsumerConfig, ConsumerResult, CheckResult, PurgeConfig, ProgressEvent } from 'npmdata';
235
+
236
+ // extract files from one package
237
+ const result = await extract({
238
+ packages: ['my-shared-assets@^2.0.0'],
239
+ outputDir: './data',
240
+ gitignore: true,
241
+ });
242
+ console.log(result.added, result.modified, result.deleted);
243
+
244
+ // dry-run: preview changes without writing files
245
+ const preview = await extract({
246
+ packages: ['my-shared-assets@^2.0.0'],
247
+ outputDir: './data',
248
+ dryRun: true,
249
+ });
250
+ console.log('Would add', preview.added, 'files');
251
+
252
+ // force-reinstall the package even if already present
253
+ await extract({
254
+ packages: ['my-shared-assets@latest'],
255
+ outputDir: './data',
256
+ upgrade: true,
257
+ });
258
+
259
+ // extract without npmdata tracking: files are writable, no .npmdata marker is written,
260
+ // no .gitignore entry is created. Existing files are left untouched (skipped).
261
+ await extract({
262
+ packages: ['shared-templates'],
263
+ outputDir: './templates',
264
+ unmanaged: true,
265
+ });
266
+
267
+ // track progress file-by-file
268
+ await extract({
269
+ packages: ['my-shared-assets@^2.0.0'],
270
+ outputDir: './data',
271
+ onProgress: (event: ProgressEvent) => {
272
+ if (event.type === 'file-added') console.log('A', event.file);
273
+ if (event.type === 'file-modified') console.log('M', event.file);
274
+ if (event.type === 'file-deleted') console.log('D', event.file);
275
+ },
276
+ });
277
+
278
+ // extract files from multiple packages into the same output directory
279
+ const multiResult = await extract({
280
+ packages: ['my-shared-assets@^2.0.0', 'another-pkg@1.x'],
281
+ outputDir: './data',
282
+ });
283
+
284
+ // check sync status — per-package breakdown
285
+ const status = await check({
286
+ packages: ['my-shared-assets'],
287
+ outputDir: './data',
288
+ });
289
+ if (!status.ok) {
290
+ console.log('Overall differences:', status.differences);
291
+ for (const pkg of status.sourcePackages) {
292
+ if (!pkg.ok) {
293
+ console.log(pkg.name, 'missing:', pkg.differences.missing);
294
+ console.log(pkg.name, 'modified:', pkg.differences.modified);
295
+ console.log(pkg.name, 'extra:', pkg.differences.extra);
296
+ }
297
+ }
298
+ }
299
+
300
+ // remove all files previously extracted by a package (no network required)
301
+ await purge({
302
+ packages: ['my-shared-assets'],
303
+ outputDir: './data',
304
+ });
305
+
306
+ // dry-run: preview what would be deleted without removing anything
307
+ const purgePreview = await purge({
308
+ packages: ['my-shared-assets'],
309
+ outputDir: './data',
310
+ dryRun: true,
311
+ });
312
+ console.log('Would delete', purgePreview.deleted, 'files');
313
+
314
+ // track progress during purge
315
+ await purge({
316
+ packages: ['my-shared-assets'],
317
+ outputDir: './data',
318
+ onProgress: (event: ProgressEvent) => {
319
+ if (event.type === 'file-deleted') console.log('D', event.file);
320
+ },
321
+ });
322
+
323
+ // list all files managed by npmdata in an output directory
324
+ const managed = await list('./data');
325
+ // managed is Record<string, string[]> keyed by "package@version"
326
+
327
+ // initialize a publisher package
328
+ await initPublisher(['docs', 'data'], { workingDir: './my-package' });
329
+
330
+ // utility: parse a package spec string
331
+ const { name, version } = parsePackageSpec('my-pkg@^1.0.0');
332
+
333
+ // utility: detect whether a file is binary
334
+ const binary = isBinaryFile('/path/to/file.bin');
335
+ ```
336
+
337
+ ### `ProgressEvent` type
338
+
339
+ ```typescript
340
+ type ProgressEvent =
341
+ | { type: 'package-start'; packageName: string; packageVersion: string }
342
+ | { type: 'package-end'; packageName: string; packageVersion: string }
343
+ | { type: 'file-added'; packageName: string; file: string }
344
+ | { type: 'file-modified'; packageName: string; file: string }
345
+ | { type: 'file-deleted'; packageName: string; file: string }
346
+ | { type: 'file-skipped'; packageName: string; file: string };
347
+ ```
348
+
349
+ See [lib/README.md](lib/README.md) for the full API reference.
350
+
351
+ ## Managed file tracking
352
+
353
+ Extracted files are set read-only (`444`) and tracked in a `.publisher` marker file in each output directory. On subsequent extractions:
354
+
355
+ - Unchanged files are skipped.
356
+ - Updated files are overwritten.
357
+ - Files removed from the package are deleted locally.
358
+
359
+ The marker file uses a `|`-delimited format; files written by older versions of `npmdata` using the comma-delimited format are read correctly for backward compatibility.
360
+
361
+ Multiple packages can coexist in the same output directory; each owns its own files.
362
+
363
+ ## Developer Notes
364
+
365
+ ### Module overview
6
366
 
7
367
  | Module | Purpose |
8
368
  |---|---|
@@ -13,11 +373,11 @@ This document covers the internal architecture for contributors working on this
13
373
  | `utils.ts` | File I/O helpers: glob matching via `minimatch`, SHA-256 hashing, CSV marker read/write, package manager detection |
14
374
  | `types.ts` | Shared TypeScript types and constants (e.g. `DEFAULT_FILENAME_PATTERNS`) |
15
375
 
16
- ## Publish side (`publisher.ts`)
376
+ ### Publish side (`publisher.ts`)
17
377
 
18
378
  `initPublisher()` modifies the target `package.json` to include `files`, `bin`, and `dependencies` fields, then writes a thin `bin/npmdata.js` that calls `runner.run(__dirname)`. The generated script is kept minimal on purpose — all logic lives in this library.
19
379
 
20
- ## Consumer side (`consumer.ts`)
380
+ ### Consumer side (`consumer.ts`)
21
381
 
22
382
  `extract()` flow:
23
383
  1. Detects the package manager (`pnpm` / `yarn` / `npm`) via lock-file presence.
@@ -28,19 +388,18 @@ This document covers the internal architecture for contributors working on this
28
388
 
29
389
  `check()` performs the same resolution for each package in `config.packages` but compares SHA-256 hashes without writing any files.
30
390
 
31
- ## Marker file (`.publisher`)
391
+ ### Marker file (`.publisher`)
32
392
 
33
393
  Each output directory that contains managed files gets a `.publisher` CSV file. Columns: `path`, `packageName`, `packageVersion`, `sha256`. This is the source of truth for drift detection and clean removal.
34
394
 
35
- ## Key design decisions
395
+ ### Key design decisions
36
396
 
37
397
  - No runtime dependencies beyond `semver` and `minimatch` to keep the consumer install footprint small.
38
398
  - File identity is tracked by path + hash, not by timestamp, to be deterministic across machines.
39
399
  - The bin script generated by `initPublisher` contains no logic; all behaviour is versioned inside this library.
40
400
 
41
- ## Dev workflow
401
+ ### Dev workflow
42
402
 
43
403
  ```
44
404
  make build lint-fix test
45
405
  ```
46
-
package/bin/npmdata.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+
3
+ // DON'T EDIT THIS FILE MANUALLY - this script is generated by "npmdata init" command
4
+ require('npmdata/dist/runner.js').run(__dirname);
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAaA;;GAEG;AAEH,wBAAsB,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAwPhE"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAaA;;GAEG;AAEH,wBAAsB,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAgVhE"}
package/dist/cli.js CHANGED
@@ -37,39 +37,53 @@ async function cli(processArgs) {
37
37
  // Handle init command
38
38
  if (command === 'init') {
39
39
  // eslint-disable-next-line functional/no-let
40
- let sourceFoldersFlag;
40
+ let sourceFilesFlag;
41
41
  // eslint-disable-next-line functional/no-let
42
42
  let additionalPackagesFlag;
43
- // Parse args for --folders and --packages flags
43
+ // eslint-disable-next-line functional/no-let
44
+ let initGitignore = true;
45
+ // eslint-disable-next-line functional/no-let
46
+ let initUnmanaged = false;
47
+ // Parse args for --files and --packages flags
44
48
  // eslint-disable-next-line functional/no-let
45
49
  for (let i = 1; i < args.length; i += 1) {
46
- if (args[i] === '--folders') {
50
+ if (args[i] === '--files') {
47
51
  // eslint-disable-next-line no-plusplus
48
- sourceFoldersFlag = args[++i];
52
+ sourceFilesFlag = args[++i];
49
53
  }
50
54
  else if (args[i] === '--packages') {
51
55
  // eslint-disable-next-line no-plusplus
52
56
  additionalPackagesFlag = args[++i];
53
57
  }
58
+ else if (args[i] === '--no-gitignore') {
59
+ initGitignore = false;
60
+ }
61
+ else if (args[i] === '--unmanaged') {
62
+ initUnmanaged = true;
63
+ }
54
64
  }
55
- // --folders is required
56
- if (!sourceFoldersFlag) {
57
- console.error('Error: --folders option is required for init command');
65
+ // --files is required
66
+ if (!sourceFilesFlag) {
67
+ console.error('Error: --files option is required for init command');
58
68
  printUsage();
59
69
  return 1;
60
70
  }
61
- const folders = sourceFoldersFlag.split(',').map((f) => f.trim());
71
+ const fileGlobs = sourceFilesFlag.split(',').map((f) => f.trim());
62
72
  const additionalPackages = additionalPackagesFlag
63
73
  ? additionalPackagesFlag.split(',').map((p) => p.trim())
64
74
  : [];
65
- const result = await (0, publisher_1.initPublisher)(folders, { additionalPackages });
75
+ const result = await (0, publisher_1.initPublisher)(fileGlobs, {
76
+ additionalPackages,
77
+ gitignore: initGitignore,
78
+ ...(initUnmanaged ? { unmanaged: true } : {}),
79
+ });
66
80
  if (!result.success) {
67
81
  console.error(`\nError: ${result.message}`);
68
82
  return 1;
69
83
  }
70
84
  console.log(`\n${result.message}`);
71
- if (result.publishedFolders) {
72
- console.log(`\nThe following folders will be published: ${result.publishedFolders.join(', ')}`);
85
+ if (result.publishedFiles) {
86
+ console.log(`\nThe following file patterns will be published: ${result.publishedFiles.join(', ')}`);
73
87
  }
74
88
  if (result.additionalPackages && result.additionalPackages.length > 0) {
75
89
  console.log(`\nAdditional data source packages: ${result.additionalPackages.join(', ')}`);
@@ -106,19 +120,85 @@ async function cli(processArgs) {
106
120
  }
107
121
  return 0;
108
122
  }
123
+ // Handle purge command
124
+ if (command === 'purge') {
125
+ let purgePackageSpecs;
126
+ let purgeOutDir = process.cwd();
127
+ let purgeOutputFlagProvided = false;
128
+ let purgeDryRun = false;
129
+ let purgeSilent = false;
130
+ for (let i = 1; i < args.length; i++) {
131
+ if (args[i] === '--packages') {
132
+ purgePackageSpecs = args[++i];
133
+ }
134
+ else if (args[i] === '--output' || args[i] === '-o') {
135
+ purgeOutDir = args[++i];
136
+ purgeOutputFlagProvided = true;
137
+ }
138
+ else if (args[i] === '--dry-run') {
139
+ purgeDryRun = true;
140
+ }
141
+ else if (args[i] === '--silent') {
142
+ purgeSilent = true;
143
+ }
144
+ else if (!args[i].startsWith('-')) {
145
+ purgeOutDir = args[i];
146
+ purgeOutputFlagProvided = true;
147
+ }
148
+ }
149
+ if (!purgePackageSpecs) {
150
+ console.error(`Error: --packages option is required for 'purge' command`);
151
+ printUsage();
152
+ return 1;
153
+ }
154
+ if (!purgeOutputFlagProvided && !purgeSilent) {
155
+ console.info(`No --output specified. Using current directory: ${purgeOutDir}`);
156
+ }
157
+ const purgePackages = purgePackageSpecs.split(',').map((s) => s.trim());
158
+ const purgeOnProgress = purgeSilent
159
+ ? // eslint-disable-next-line no-undefined
160
+ undefined
161
+ : (event) => {
162
+ switch (event.type) {
163
+ case 'package-start':
164
+ console.log(`\n>> Package ${event.packageName}`);
165
+ break;
166
+ case 'file-deleted':
167
+ console.log(`D\t${event.file}`);
168
+ break;
169
+ default:
170
+ break;
171
+ }
172
+ };
173
+ if (!purgeSilent) {
174
+ if (purgeDryRun)
175
+ console.info('Dry run: simulating purge (no files will be removed)...');
176
+ else
177
+ console.info('Purging managed files...');
178
+ }
179
+ const purgeResult = await (0, consumer_1.purge)({
180
+ packages: purgePackages,
181
+ outputDir: node_path_1.default.resolve(purgeOutDir),
182
+ dryRun: purgeDryRun,
183
+ onProgress: purgeOnProgress,
184
+ });
185
+ console.log(`\nPurge complete: ${purgeResult.deleted.length} deleted${purgeDryRun ? ' (dry run)' : ''}`);
186
+ return 0;
187
+ }
109
188
  // Consumer commands (extract, check)
110
189
  if (!['extract', 'check'].includes(command)) {
111
- console.error(`Error: unknown command '${command}'. Use 'init', 'extract', 'check', or 'list'`);
190
+ console.error(`Error: unknown command '${command}'. Use 'init', 'extract', 'check', 'purge', or 'list'`);
112
191
  printUsage();
113
192
  return 1;
114
193
  }
115
194
  // Parse options common to extract and check
116
195
  let packageSpecs;
117
196
  let force = false;
118
- let gitignore = false;
197
+ let gitignore = true;
119
198
  let dryRun = false;
120
199
  let upgrade = false;
121
200
  let silent = false;
201
+ let unmanaged = false;
122
202
  let filenamePatterns;
123
203
  let contentRegexes;
124
204
  let outDir = process.cwd();
@@ -133,8 +213,8 @@ async function cli(processArgs) {
133
213
  else if (args[i] === '--silent') {
134
214
  silent = true;
135
215
  }
136
- else if (args[i] === '--gitignore') {
137
- gitignore = true;
216
+ else if (args[i] === '--no-gitignore') {
217
+ gitignore = false;
138
218
  }
139
219
  else if (args[i] === '--dry-run') {
140
220
  dryRun = true;
@@ -142,6 +222,9 @@ async function cli(processArgs) {
142
222
  else if (args[i] === '--upgrade') {
143
223
  upgrade = true;
144
224
  }
225
+ else if (args[i] === '--unmanaged') {
226
+ unmanaged = true;
227
+ }
145
228
  else if (args[i] === '--files') {
146
229
  filenamePatterns = args[++i];
147
230
  }
@@ -195,6 +278,7 @@ async function cli(processArgs) {
195
278
  gitignore,
196
279
  dryRun,
197
280
  upgrade,
281
+ unmanaged,
198
282
  onProgress,
199
283
  filenamePatterns: filenamePatterns
200
284
  ? filenamePatterns.split(',')
@@ -250,12 +334,13 @@ function printUsage() {
250
334
  npmdata
251
335
 
252
336
  Usage:
253
- npx npmdata [init|extract|check|list] [options]
337
+ npx npmdata [init|extract|check|purge|list] [options]
254
338
 
255
339
  Commands:
256
340
  init Initialize publishing configuration
257
341
  extract Extract files from one or more published packages
258
342
  check Verify if local files are in sync with packages
343
+ purge Remove all managed files written by given packages
259
344
  list List all managed files in the output directory
260
345
 
261
346
  Global Options:
@@ -263,10 +348,12 @@ Global Options:
263
348
  --version, -v Show version
264
349
 
265
350
  Init Options:
266
- --folders <folders> Comma-separated list of source folders to publish (required)
351
+ --files <patterns> Comma-separated glob patterns of files to publish (required)
352
+ e.g. "docs/**,data/**,configs/*.json"
267
353
  --packages <specs> Comma-separated additional package specs to use as data sources.
268
354
  Each spec is "name" or "name@version"
269
355
  e.g. "shared-data@^1.0.0,other-pkg@2.x"
356
+ --unmanaged Mark all npmdata entries as unmanaged (see Extract options)
270
357
 
271
358
  Extract / Check Options:
272
359
  --packages <specs> Comma-separated package specs to extract from (required).
@@ -274,18 +361,27 @@ Extract / Check Options:
274
361
  e.g. "my-pkg@^1.2.3,other-pkg@2.x"
275
362
  --output, -o <dir> Output directory (default: current directory, with a warning)
276
363
  --force Allow overwriting existing unmanaged files
277
- --gitignore Create/update .gitignore to ignore managed files and .publisher
364
+ --no-gitignore Skip creating/updating .gitignore (gitignore is enabled by default)
365
+ --unmanaged Write files without a .npmdata marker, .gitignore update, or
366
+ read-only flag. Existing files are skipped. Files can be freely
367
+ edited afterwards and are not tracked by npmdata.
278
368
  --dry-run Simulate extraction without writing any files
279
369
  --upgrade Re-install packages even when a satisfying version is installed
280
370
  --silent Print only the final result line, suppressing package and file listing
281
371
  --files <pattern> Comma-separated shell glob patterns to filter files
282
372
  --content-regex <regex> Regex pattern to match file contents
283
373
 
374
+ Purge Options:
375
+ --packages <specs> Comma-separated package names whose managed files should be removed
376
+ --output, -o <dir> Output directory to purge from (default: current directory)
377
+ --dry-run Simulate purge without removing any files
378
+ --silent Suppress per-file output
379
+
284
380
  List Options:
285
381
  --output, -o <dir> Directory to inspect (default: current directory)
286
382
 
287
383
  Examples:
288
- npx npmdata init --folders "data,docs,config"
384
+ npx npmdata init --files "data/**,docs/**,configs/*.json"
289
385
  npx npmdata extract --packages mydataset --output ./data
290
386
  npx npmdata extract --packages mydataset@^2.0.0 --output ./data
291
387
  npx npmdata extract --packages "mydataset@^2.0.0,otherpkg@1.x" --output ./data
@@ -296,6 +392,8 @@ Examples:
296
392
  npx npmdata check --packages mydataset --output ./data
297
393
  npx npmdata check --packages "mydataset,otherpkg" --output ./data
298
394
  npx npmdata list --output ./data
395
+ npx npmdata purge --packages mydataset --output ./data
396
+ npx npmdata purge --packages "mydataset,otherpkg" --output ./data
299
397
  `);
300
398
  }
301
399
  //# sourceMappingURL=cli.js.map