@bobfrankston/npmglobalize 1.0.153 → 1.0.155
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 +30 -3
- package/cli.js +39 -8
- package/lib/config.js +5 -1
- package/lib/types.d.ts +5 -0
- package/lib.d.ts +16 -1
- package/lib.js +107 -26
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -301,6 +301,8 @@ Publishing requires being on a branch so commits and tags can be properly tracke
|
|
|
301
301
|
-force-publish Republish dependencies even if version exists
|
|
302
302
|
-fix Run npm audit fix after transformation
|
|
303
303
|
-no-fix Don't run npm audit
|
|
304
|
+
-no-use-paths, -nup Declare package standalone; do not resolve file: deps
|
|
305
|
+
from sibling checkouts (see Configuration File)
|
|
304
306
|
```
|
|
305
307
|
|
|
306
308
|
### Install Options
|
|
@@ -323,10 +325,21 @@ Publishing requires being on a branch so commits and tags can be properly tracke
|
|
|
323
325
|
-git private Set GitHub repo to private (default for new repos)
|
|
324
326
|
-git public Set GitHub repo to public (requires confirmation)
|
|
325
327
|
Works on both new and existing repos
|
|
326
|
-
-npm
|
|
327
|
-
|
|
328
|
+
-npm <values> Comma-separated list of npm options:
|
|
329
|
+
private (default) | public — package visibility
|
|
330
|
+
ts — keep .ts source (and *.map,
|
|
331
|
+
tsconfig.json) in npm tarball
|
|
332
|
+
nts — exclude .ts source
|
|
333
|
+
(default for non-noEmit projects)
|
|
334
|
+
Example: -npm public,ts
|
|
328
335
|
```
|
|
329
336
|
|
|
337
|
+
`ts` is already the default on git (source is tracked). Pass `-npm ts` to ship
|
|
338
|
+
the same files to npm — useful for debugging installed packages or "source on
|
|
339
|
+
demand" packages. `noEmit` projects automatically ship `.ts` files (they *are*
|
|
340
|
+
the runtime); pass `-npm nts` to override. `allowTs` persists to
|
|
341
|
+
`.globalize.json5`.
|
|
342
|
+
|
|
330
343
|
### Workspace Options
|
|
331
344
|
```
|
|
332
345
|
-w, -workspace <pkg> Filter to specific package (repeatable)
|
|
@@ -400,12 +413,26 @@ Settings can be saved in `.globalize.json5`:
|
|
|
400
413
|
"fix": true, // Auto-run npm audit fix
|
|
401
414
|
"verbose": false, // Show detailed output
|
|
402
415
|
"gitVisibility": "private",
|
|
403
|
-
"npmVisibility": "public"
|
|
416
|
+
"npmVisibility": "public",
|
|
417
|
+
"usePaths": true // Resolve file: deps from sibling checkouts (see below)
|
|
404
418
|
}
|
|
405
419
|
```
|
|
406
420
|
|
|
407
421
|
Configuration persists across runs. CLI flags override config file.
|
|
408
422
|
|
|
423
|
+
### `usePaths` — Standalone packages
|
|
424
|
+
|
|
425
|
+
Default: `true`. Set to `false` (or pass `-no-use-paths` / `-nup`) to mark a
|
|
426
|
+
package as **standalone** — one that should be publishable/installable on a
|
|
427
|
+
machine that does not have sibling `file:` dep checkouts available. Example:
|
|
428
|
+
a backup/recovery utility you want to `npm install -g` on any host.
|
|
429
|
+
|
|
430
|
+
Currently this setting is **declarative** — it is parsed, persisted to
|
|
431
|
+
`.globalize.json5`, and surfaced in the settings banner, but the tool does
|
|
432
|
+
not yet change its behavior based on it. Behavior wiring (e.g. resolving
|
|
433
|
+
`file:` deps to the latest published npm version instead of walking siblings)
|
|
434
|
+
is planned.
|
|
435
|
+
|
|
409
436
|
## Common Workflows
|
|
410
437
|
|
|
411
438
|
### Standard Release
|
package/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* npmglobalize CLI - Transform file: dependencies to npm versions for publishing
|
|
4
4
|
*/
|
|
5
|
-
import { globalize, globalizeWorkspace, installCleanupHandlers, readConfig, readPackageJson, readUserNpmConfig, writeConfig, writePackageJson, confirm, getBuildIssues, clearBuildIssues, recordBuildIssue, extractFirstTscError } from './lib.js';
|
|
5
|
+
import { globalize, globalizeWorkspace, installCleanupHandlers, readConfig, readPackageJson, readUserNpmConfig, writeConfig, writePackageJson, confirm, getBuildIssues, clearBuildIssues, recordBuildIssue, extractFirstTscError, ensureFileDepModules } from './lib.js';
|
|
6
6
|
import fs from 'fs';
|
|
7
7
|
import path from 'path';
|
|
8
8
|
import { styleText } from 'util';
|
|
@@ -37,6 +37,9 @@ Dependency Options:
|
|
|
37
37
|
-no-prescan, -nps Skip upfront dep-graph prescan
|
|
38
38
|
-force-publish Republish dependencies even if version exists
|
|
39
39
|
-fix Run npm audit fix after transformation
|
|
40
|
+
-no-use-paths, -nup Declare this package standalone — file: deps shouldn't
|
|
41
|
+
be resolved from sibling checkouts (persisted as
|
|
42
|
+
usePaths:false in .globalize.json5; FYI for now)
|
|
40
43
|
|
|
41
44
|
Install Options:
|
|
42
45
|
-install, -i Global install after publish (from registry)
|
|
@@ -57,8 +60,12 @@ Git/npm Visibility:
|
|
|
57
60
|
-git private Set GitHub repo to private (default for new repos)
|
|
58
61
|
-git public Set GitHub repo to public (requires confirmation)
|
|
59
62
|
Works on both new and existing repos
|
|
60
|
-
-npm
|
|
61
|
-
|
|
63
|
+
-npm <values> Comma-separated list of npm options:
|
|
64
|
+
private (default) | public — package visibility
|
|
65
|
+
ts — keep .ts source in npm tarball
|
|
66
|
+
nts — exclude .ts source (default for
|
|
67
|
+
non-noEmit projects)
|
|
68
|
+
Example: -npm public,ts
|
|
62
69
|
|
|
63
70
|
Workspace Options:
|
|
64
71
|
-w, -workspace <pkg> Filter to specific package (repeatable)
|
|
@@ -214,12 +221,30 @@ function parseArgs(args) {
|
|
|
214
221
|
break;
|
|
215
222
|
case '-npm':
|
|
216
223
|
i++;
|
|
217
|
-
if (args[i]
|
|
218
|
-
options.
|
|
219
|
-
|
|
224
|
+
if (!args[i]) {
|
|
225
|
+
options.error = `-npm requires a value (private|public, ts, nts — comma-separated)`;
|
|
226
|
+
break;
|
|
220
227
|
}
|
|
221
|
-
|
|
222
|
-
|
|
228
|
+
{
|
|
229
|
+
const tokens = args[i].split(',').map(t => t.trim()).filter(t => t);
|
|
230
|
+
for (const tok of tokens) {
|
|
231
|
+
if (tok === 'private' || tok === 'public') {
|
|
232
|
+
options.npmVisibility = tok;
|
|
233
|
+
options.explicitKeys.add('npmVisibility');
|
|
234
|
+
}
|
|
235
|
+
else if (tok === 'ts') {
|
|
236
|
+
options.allowTs = true;
|
|
237
|
+
options.explicitKeys.add('allowTs');
|
|
238
|
+
}
|
|
239
|
+
else if (tok === 'nts') {
|
|
240
|
+
options.allowTs = false;
|
|
241
|
+
options.explicitKeys.add('allowTs');
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
options.error = `-npm: unknown value '${tok}' (expected private|public|ts|nts)`;
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
223
248
|
}
|
|
224
249
|
break;
|
|
225
250
|
case '-message':
|
|
@@ -266,6 +291,11 @@ function parseArgs(args) {
|
|
|
266
291
|
case '-npd':
|
|
267
292
|
options.publishDeps = false; // Disable auto-publishing
|
|
268
293
|
break;
|
|
294
|
+
case '-no-use-paths':
|
|
295
|
+
case '-nup':
|
|
296
|
+
options.usePaths = false; // Skip sibling-path resolution; use latest npm version for file: deps
|
|
297
|
+
options.explicitKeys.add('usePaths');
|
|
298
|
+
break;
|
|
269
299
|
case '-no-prescan':
|
|
270
300
|
case '-nps':
|
|
271
301
|
options.noPrescan = true;
|
|
@@ -423,6 +453,7 @@ export async function main() {
|
|
|
423
453
|
}
|
|
424
454
|
}
|
|
425
455
|
if (pkg.scripts?.build) {
|
|
456
|
+
ensureFileDepModules(cwd, !!cliOptions.verbose);
|
|
426
457
|
const { spawnSync } = await import('child_process');
|
|
427
458
|
console.log(`Building ${cwd}...`);
|
|
428
459
|
const buildResult = spawnSync('npm', ['run', 'build'], {
|
package/lib/config.js
CHANGED
|
@@ -58,7 +58,8 @@ export function writeConfig(dir, config, explicitKeys) {
|
|
|
58
58
|
wsl: false,
|
|
59
59
|
force: false,
|
|
60
60
|
verbose: false,
|
|
61
|
-
freeze: false
|
|
61
|
+
freeze: false,
|
|
62
|
+
usePaths: true
|
|
62
63
|
};
|
|
63
64
|
// Read existing config to preserve values
|
|
64
65
|
const existing = readConfig(dir);
|
|
@@ -119,6 +120,8 @@ export function writeConfig(dir, config, explicitKeys) {
|
|
|
119
120
|
comment = ' // Transform but don\'t publish';
|
|
120
121
|
else if (key === 'freeze')
|
|
121
122
|
comment = ' // Freeze node_modules (replace symlinks with real copies)';
|
|
123
|
+
else if (key === 'usePaths')
|
|
124
|
+
comment = ' // Resolve file: deps from sibling checkouts (set false for standalone packages)';
|
|
122
125
|
lines.push(` "${key}": ${jsonValue}${comma}${comment}`);
|
|
123
126
|
});
|
|
124
127
|
lines.push('');
|
|
@@ -139,6 +142,7 @@ export function writeConfig(dir, config, explicitKeys) {
|
|
|
139
142
|
lines.push(' // "local": false // Local install only (skip transform/publish)');
|
|
140
143
|
lines.push(' // "noPublish": false // Transform but don\'t publish');
|
|
141
144
|
lines.push(' // "freeze": false // Freeze node_modules (replace symlinks with real copies)');
|
|
145
|
+
lines.push(' // "usePaths": true // Resolve file: deps from siblings; false = use latest npm version (standalone)');
|
|
142
146
|
lines.push('}');
|
|
143
147
|
fs.writeFileSync(configPath, lines.join('\n') + '\n');
|
|
144
148
|
}
|
package/lib/types.d.ts
CHANGED
|
@@ -78,6 +78,11 @@ export interface GlobalizeOptions {
|
|
|
78
78
|
once?: boolean;
|
|
79
79
|
/** Run importgen to update import maps before publishing */
|
|
80
80
|
importgen?: boolean;
|
|
81
|
+
/** Use filesystem paths for `file:` deps (default true). Set false to
|
|
82
|
+
* mark a package as publishable/installable even when sibling checkouts
|
|
83
|
+
* are absent. Currently declarative (recorded in config and displayed);
|
|
84
|
+
* the actual conversion path is TODO. */
|
|
85
|
+
usePaths?: boolean;
|
|
81
86
|
/** Local install only — skip transform/publish, just npm install -g . */
|
|
82
87
|
local?: boolean;
|
|
83
88
|
/** Freeze node_modules: replace symlinks/junctions with real copies for network share use */
|
package/lib.d.ts
CHANGED
|
@@ -55,6 +55,10 @@ export interface GlobalizeOptions {
|
|
|
55
55
|
gitVisibility?: 'private' | 'public';
|
|
56
56
|
/** npm visibility: private (default) or public */
|
|
57
57
|
npmVisibility?: 'private' | 'public';
|
|
58
|
+
/** Allow .ts source files (and *.map, tsconfig.json) in the published npm tarball.
|
|
59
|
+
* undefined: follow noEmit detection (noEmit → allow). true: always allow.
|
|
60
|
+
* false: always exclude via .npmignore. Set via `-npm ts` / `-npm nts`. */
|
|
61
|
+
allowTs?: boolean;
|
|
58
62
|
/** Custom commit message */
|
|
59
63
|
message?: string;
|
|
60
64
|
/** Check and update ignore files to conform to best practices */
|
|
@@ -91,6 +95,11 @@ export interface GlobalizeOptions {
|
|
|
91
95
|
once?: boolean;
|
|
92
96
|
/** Run importgen to update import maps before publishing */
|
|
93
97
|
importgen?: boolean;
|
|
98
|
+
/** Use filesystem paths for `file:` deps (default true). Set false to
|
|
99
|
+
* mark a package as publishable/installable even when sibling checkouts
|
|
100
|
+
* are absent. Currently declarative (recorded in config and displayed);
|
|
101
|
+
* the actual conversion path is TODO. */
|
|
102
|
+
usePaths?: boolean;
|
|
94
103
|
/** Local install only — skip transform/publish, just npm install -g . */
|
|
95
104
|
local?: boolean;
|
|
96
105
|
/** Freeze node_modules: replace symlinks/junctions with real copies for network share use */
|
|
@@ -234,6 +243,12 @@ export declare function parseVersionTag(tag: string): number[] | null;
|
|
|
234
243
|
export declare function compareVersions(a: number[], b: number[]): number;
|
|
235
244
|
/** Fix version/tag mismatches */
|
|
236
245
|
export declare function fixVersionTagMismatch(cwd: string, pkg: any, verbose?: boolean): boolean;
|
|
246
|
+
/** Walk `file:` deps transitively and run `npm install` in any target whose
|
|
247
|
+
* package.json declares deps but has no `node_modules/`. Recovers from prior
|
|
248
|
+
* aborted runs (or pre-1.0.153 `--clean-nested-modules` damage) so the
|
|
249
|
+
* upcoming build/pack can resolve transitive package imports.
|
|
250
|
+
* Cycle-safe via the shared `visited` set. */
|
|
251
|
+
export declare function ensureFileDepModules(cwd: string, verbose?: boolean, visited?: Set<string>): void;
|
|
237
252
|
/** Run a command and return success status */
|
|
238
253
|
export declare function runCommand(cmd: string, args: string[], options?: {
|
|
239
254
|
silent?: boolean;
|
|
@@ -272,7 +287,7 @@ export declare function promptText(message: string, defaultValue?: string): Prom
|
|
|
272
287
|
/** Prompt user for multiple choice */
|
|
273
288
|
export declare function promptChoice(message: string, choices: string[]): Promise<string | null>;
|
|
274
289
|
/** Initialize git repository */
|
|
275
|
-
export declare function initGit(cwd: string, visibility: 'private' | 'public', dryRun: boolean): Promise<boolean>;
|
|
290
|
+
export declare function initGit(cwd: string, visibility: 'private' | 'public', dryRun: boolean, allowTs?: boolean): Promise<boolean>;
|
|
276
291
|
/** Main globalize function */
|
|
277
292
|
/** Run npm audit and optionally fix vulnerabilities */
|
|
278
293
|
export declare function runNpmAudit(cwd: string, fix?: boolean, verbose?: boolean): {
|
package/lib.js
CHANGED
|
@@ -230,7 +230,8 @@ export function writeConfig(dir, config, explicitKeys) {
|
|
|
230
230
|
wsl: false,
|
|
231
231
|
force: false,
|
|
232
232
|
verbose: false,
|
|
233
|
-
freeze: false
|
|
233
|
+
freeze: false,
|
|
234
|
+
usePaths: true
|
|
234
235
|
};
|
|
235
236
|
// Read existing config to preserve values
|
|
236
237
|
const existing = readConfig(dir);
|
|
@@ -291,6 +292,10 @@ export function writeConfig(dir, config, explicitKeys) {
|
|
|
291
292
|
comment = ' // Transform but don\'t publish';
|
|
292
293
|
else if (key === 'freeze')
|
|
293
294
|
comment = ' // Freeze node_modules (replace symlinks with real copies)';
|
|
295
|
+
else if (key === 'usePaths')
|
|
296
|
+
comment = ' // Resolve file: deps from sibling checkouts (set false for standalone packages)';
|
|
297
|
+
else if (key === 'allowTs')
|
|
298
|
+
comment = ' // Keep .ts source (and *.map, tsconfig.json) in the published npm tarball';
|
|
294
299
|
lines.push(` "${key}": ${jsonValue}${comma}${comment}`);
|
|
295
300
|
});
|
|
296
301
|
lines.push('');
|
|
@@ -311,6 +316,8 @@ export function writeConfig(dir, config, explicitKeys) {
|
|
|
311
316
|
lines.push(' // "local": false // Local install only (skip transform/publish)');
|
|
312
317
|
lines.push(' // "noPublish": false // Transform but don\'t publish');
|
|
313
318
|
lines.push(' // "freeze": false // Freeze node_modules (replace symlinks with real copies)');
|
|
319
|
+
lines.push(' // "usePaths": true // Resolve file: deps from siblings; false = use latest npm version (standalone)');
|
|
320
|
+
lines.push(' // "allowTs": false // Include .ts source in npm tarball (auto-true for noEmit projects)');
|
|
314
321
|
lines.push('}');
|
|
315
322
|
fs.writeFileSync(configPath, lines.join('\n') + '\n');
|
|
316
323
|
}
|
|
@@ -1315,6 +1322,56 @@ function restoreNestedDepModules(stashed, verbose) {
|
|
|
1315
1322
|
}
|
|
1316
1323
|
}
|
|
1317
1324
|
}
|
|
1325
|
+
/** Walk `file:` deps transitively and run `npm install` in any target whose
|
|
1326
|
+
* package.json declares deps but has no `node_modules/`. Recovers from prior
|
|
1327
|
+
* aborted runs (or pre-1.0.153 `--clean-nested-modules` damage) so the
|
|
1328
|
+
* upcoming build/pack can resolve transitive package imports.
|
|
1329
|
+
* Cycle-safe via the shared `visited` set. */
|
|
1330
|
+
export function ensureFileDepModules(cwd, verbose = false, visited = new Set()) {
|
|
1331
|
+
const abs = path.resolve(cwd);
|
|
1332
|
+
if (visited.has(abs))
|
|
1333
|
+
return;
|
|
1334
|
+
visited.add(abs);
|
|
1335
|
+
let pkg;
|
|
1336
|
+
try {
|
|
1337
|
+
pkg = readPackageJson(cwd);
|
|
1338
|
+
}
|
|
1339
|
+
catch {
|
|
1340
|
+
return;
|
|
1341
|
+
}
|
|
1342
|
+
for (const key of ['dependencies', 'devDependencies']) {
|
|
1343
|
+
const deps = pkg?.[key];
|
|
1344
|
+
if (!deps || typeof deps !== 'object')
|
|
1345
|
+
continue;
|
|
1346
|
+
for (const [name, spec] of Object.entries(deps)) {
|
|
1347
|
+
if (typeof spec !== 'string' || !spec.startsWith('file:'))
|
|
1348
|
+
continue;
|
|
1349
|
+
const target = path.resolve(cwd, spec.slice('file:'.length));
|
|
1350
|
+
if (!fs.existsSync(path.join(target, 'package.json')))
|
|
1351
|
+
continue;
|
|
1352
|
+
let targetPkg;
|
|
1353
|
+
try {
|
|
1354
|
+
targetPkg = readPackageJson(target);
|
|
1355
|
+
}
|
|
1356
|
+
catch {
|
|
1357
|
+
continue;
|
|
1358
|
+
}
|
|
1359
|
+
const hasDeps = (targetPkg?.dependencies && Object.keys(targetPkg.dependencies).length > 0) ||
|
|
1360
|
+
(targetPkg?.devDependencies && Object.keys(targetPkg.devDependencies).length > 0);
|
|
1361
|
+
const nm = path.join(target, 'node_modules');
|
|
1362
|
+
if (hasDeps && !fs.existsSync(nm)) {
|
|
1363
|
+
console.log(colors.yellow(`↻ restoring node_modules in ${name} (${target})`));
|
|
1364
|
+
const r = runCommand('npm', ['install'], { cwd: target, silent: !verbose });
|
|
1365
|
+
if (!r.success) {
|
|
1366
|
+
console.error(colors.red(` ✗ npm install failed in ${target}`));
|
|
1367
|
+
if (r.stderr)
|
|
1368
|
+
console.error(colors.dim(r.stderr.split('\n').slice(0, 5).join('\n')));
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
ensureFileDepModules(target, verbose, visited);
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1318
1375
|
/** Run npm install -g with retries for registry propagation delay */
|
|
1319
1376
|
function installGlobalWithRetry(pkgSpec, cwd, maxRetries = 3) {
|
|
1320
1377
|
let result = runCommand('npm', ['install', '-g', pkgSpec], { cwd, silent: false, showCommand: true });
|
|
@@ -1808,9 +1865,16 @@ function isNoEmitProject(cwd) {
|
|
|
1808
1865
|
return false;
|
|
1809
1866
|
}
|
|
1810
1867
|
}
|
|
1811
|
-
/**
|
|
1812
|
-
|
|
1813
|
-
|
|
1868
|
+
/** Resolve whether .ts source files should be kept in the published tarball.
|
|
1869
|
+
* Explicit allowTs wins; otherwise noEmit projects default to including .ts. */
|
|
1870
|
+
function resolveAllowTs(cwd, allowTs) {
|
|
1871
|
+
if (allowTs !== undefined)
|
|
1872
|
+
return allowTs;
|
|
1873
|
+
return isNoEmitProject(cwd);
|
|
1874
|
+
}
|
|
1875
|
+
/** Get applicable npmignore patterns, excluding TS patterns when .ts files should ship */
|
|
1876
|
+
function getApplicableNpmignorePatterns(cwd, allowTs) {
|
|
1877
|
+
if (resolveAllowTs(cwd, allowTs)) {
|
|
1814
1878
|
return ALL_NPMIGNORE.filter(p => !TS_NPMIGNORE_PATTERNS.has(p));
|
|
1815
1879
|
}
|
|
1816
1880
|
return ALL_NPMIGNORE;
|
|
@@ -2173,7 +2237,7 @@ function checkIgnoreFiles(cwd, options) {
|
|
|
2173
2237
|
if (fs.existsSync(npmignorePath)) {
|
|
2174
2238
|
const content = fs.readFileSync(npmignorePath, 'utf-8');
|
|
2175
2239
|
const lines = content.split('\n').map(l => l.trim());
|
|
2176
|
-
const applicableNpm = getApplicableNpmignorePatterns(cwd);
|
|
2240
|
+
const applicableNpm = getApplicableNpmignorePatterns(cwd, options.allowTs);
|
|
2177
2241
|
for (const pattern of applicableNpm) {
|
|
2178
2242
|
if (!lineHasPattern(lines, pattern)) {
|
|
2179
2243
|
if (securityNpm.has(pattern)) {
|
|
@@ -2184,13 +2248,21 @@ function checkIgnoreFiles(cwd, options) {
|
|
|
2184
2248
|
}
|
|
2185
2249
|
}
|
|
2186
2250
|
}
|
|
2251
|
+
// If .ts should ship, flag TS patterns already in .npmignore for removal
|
|
2252
|
+
if (resolveAllowTs(cwd, options.allowTs)) {
|
|
2253
|
+
for (const ts of TS_NPMIGNORE_PATTERNS) {
|
|
2254
|
+
if (lineHasPattern(lines, ts)) {
|
|
2255
|
+
changes.push(` .npmignore has (should remove): ${ts}`);
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
}
|
|
2187
2259
|
}
|
|
2188
2260
|
const needsUpdate = changes.length > 0 || securityChanges.length > 0;
|
|
2189
2261
|
return { needsUpdate, changes, securityChanges };
|
|
2190
2262
|
}
|
|
2191
2263
|
/** Update ignore files to conform to best practices.
|
|
2192
2264
|
* securityOnly: if true, only add security patterns (auto-fix without prompting). */
|
|
2193
|
-
function conformIgnoreFiles(cwd, securityOnly = false) {
|
|
2265
|
+
function conformIgnoreFiles(cwd, securityOnly = false, allowTs) {
|
|
2194
2266
|
if (!securityOnly) {
|
|
2195
2267
|
// Ensure .gitattributes for LF line endings (use proper helper)
|
|
2196
2268
|
ensureGitattributes(cwd);
|
|
@@ -2209,8 +2281,8 @@ function conformIgnoreFiles(cwd, securityOnly = false) {
|
|
|
2209
2281
|
}
|
|
2210
2282
|
}
|
|
2211
2283
|
const patternsGit = securityOnly ? getSecurityGitignorePatterns() : getApplicableGitignorePatterns(cwd);
|
|
2212
|
-
const patternsNpm = securityOnly ? getSecurityNpmignorePatterns() : getApplicableNpmignorePatterns(cwd);
|
|
2213
|
-
const
|
|
2284
|
+
const patternsNpm = securityOnly ? getSecurityNpmignorePatterns() : getApplicableNpmignorePatterns(cwd, allowTs);
|
|
2285
|
+
const shipTs = resolveAllowTs(cwd, allowTs);
|
|
2214
2286
|
// Update .gitignore
|
|
2215
2287
|
const gitignorePath = path.join(cwd, '.gitignore');
|
|
2216
2288
|
if (fs.existsSync(gitignorePath)) {
|
|
@@ -2237,8 +2309,8 @@ function conformIgnoreFiles(cwd, securityOnly = false) {
|
|
|
2237
2309
|
const lines = content.split('\n').map(l => l.trim());
|
|
2238
2310
|
const newLines = new Set(lines.filter(l => l));
|
|
2239
2311
|
let updated = false;
|
|
2240
|
-
if (!securityOnly && !
|
|
2241
|
-
// Add TypeScript exclusions (only in full conform, skip
|
|
2312
|
+
if (!securityOnly && !shipTs) {
|
|
2313
|
+
// Add TypeScript exclusions (only in full conform, skip when .ts should ship)
|
|
2242
2314
|
for (const ts of ['*.ts', '!*.d.ts', '*.map']) {
|
|
2243
2315
|
if (!newLines.has(ts)) {
|
|
2244
2316
|
newLines.add(ts);
|
|
@@ -2246,8 +2318,8 @@ function conformIgnoreFiles(cwd, securityOnly = false) {
|
|
|
2246
2318
|
}
|
|
2247
2319
|
}
|
|
2248
2320
|
}
|
|
2249
|
-
//
|
|
2250
|
-
if (
|
|
2321
|
+
// When .ts should ship (noEmit or allowTs=true), remove TS patterns
|
|
2322
|
+
if (shipTs) {
|
|
2251
2323
|
for (const ts of TS_NPMIGNORE_PATTERNS) {
|
|
2252
2324
|
if (newLines.has(ts)) {
|
|
2253
2325
|
newLines.delete(ts);
|
|
@@ -2264,8 +2336,9 @@ function conformIgnoreFiles(cwd, securityOnly = false) {
|
|
|
2264
2336
|
if (updated) {
|
|
2265
2337
|
const newContent = Array.from(newLines).join('\n') + '\n';
|
|
2266
2338
|
fs.writeFileSync(npmignorePath, newContent);
|
|
2267
|
-
if (
|
|
2268
|
-
|
|
2339
|
+
if (shipTs) {
|
|
2340
|
+
const reason = allowTs === true ? 'allowTs' : 'noEmit';
|
|
2341
|
+
console.log(colors.cyan(` ✓ .npmignore updated (${reason}: kept *.ts files)`));
|
|
2269
2342
|
}
|
|
2270
2343
|
else {
|
|
2271
2344
|
console.log(colors.cyan(' ✓ Auto-added security patterns to .npmignore'));
|
|
@@ -2324,11 +2397,11 @@ function ensureGitignore(cwd) {
|
|
|
2324
2397
|
}
|
|
2325
2398
|
}
|
|
2326
2399
|
/** Ensure .npmignore exists with recommended patterns */
|
|
2327
|
-
function ensureNpmignore(cwd) {
|
|
2400
|
+
function ensureNpmignore(cwd, allowTs) {
|
|
2328
2401
|
const npmignorePath = path.join(cwd, '.npmignore');
|
|
2329
2402
|
if (!fs.existsSync(npmignorePath)) {
|
|
2330
2403
|
console.log(' Creating .npmignore...');
|
|
2331
|
-
const patterns = getApplicableNpmignorePatterns(cwd);
|
|
2404
|
+
const patterns = getApplicableNpmignorePatterns(cwd, allowTs);
|
|
2332
2405
|
const content = patterns.join('\n') + '\n';
|
|
2333
2406
|
fs.writeFileSync(npmignorePath, content);
|
|
2334
2407
|
console.log(colors.green(' ✓ .npmignore created'));
|
|
@@ -2355,7 +2428,7 @@ function ensureGitattributes(cwd) {
|
|
|
2355
2428
|
}
|
|
2356
2429
|
}
|
|
2357
2430
|
/** Initialize git repository */
|
|
2358
|
-
export async function initGit(cwd, visibility, dryRun) {
|
|
2431
|
+
export async function initGit(cwd, visibility, dryRun, allowTs) {
|
|
2359
2432
|
const pkg = readPackageJson(cwd);
|
|
2360
2433
|
const repoName = pkg.name.replace(/^@[^/]+\//, ''); // Remove scope
|
|
2361
2434
|
console.log('Initializing git repository...');
|
|
@@ -2378,7 +2451,7 @@ export async function initGit(cwd, visibility, dryRun) {
|
|
|
2378
2451
|
// Ensure .gitignore exists and includes node_modules
|
|
2379
2452
|
ensureGitignore(cwd);
|
|
2380
2453
|
// Ensure .npmignore exists with recommended patterns
|
|
2381
|
-
ensureNpmignore(cwd);
|
|
2454
|
+
ensureNpmignore(cwd, allowTs);
|
|
2382
2455
|
// Ensure .gitattributes exists for LF line endings
|
|
2383
2456
|
ensureGitattributes(cwd);
|
|
2384
2457
|
// git init
|
|
@@ -2643,7 +2716,7 @@ async function doLocalInstall(cwd, options) {
|
|
|
2643
2716
|
export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
2644
2717
|
const { bump = 'patch', noPublish = false, cleanup = false, install = false, link = false, wsl = false, force = false, files = true, dryRun = false, quiet = true, verbose = false, init = false, gitVisibility = 'private', npmVisibility = 'private', message, conform = false, asis = false, updateDeps = false, updateMajor = false, publishDeps = true, // Default to publishing deps for safety
|
|
2645
2718
|
publishDepsYes = false, // -pd: auto-yes to dep-cascade prompts (private only)
|
|
2646
|
-
noPrescan = false, forcePublish = false, fix = true, fixTags = false, rebase = false, show = false, local = false, freeze = false } = options;
|
|
2719
|
+
noPrescan = false, forcePublish = false, fix = true, fixTags = false, rebase = false, show = false, local = false, freeze = false, usePaths = true, allowTs } = options;
|
|
2647
2720
|
// Show tool version only for recursive dep calls (CLI already prints it at startup)
|
|
2648
2721
|
const toolVersion = getToolVersion();
|
|
2649
2722
|
if (!options._fromWorkspace && !options._fromCli) {
|
|
@@ -2702,6 +2775,12 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
2702
2775
|
settings.push('-local');
|
|
2703
2776
|
if (configOptions.freeze)
|
|
2704
2777
|
settings.push('-freeze');
|
|
2778
|
+
if (configOptions.usePaths === false)
|
|
2779
|
+
settings.push('--no-use-paths');
|
|
2780
|
+
if (configOptions.allowTs === true)
|
|
2781
|
+
settings.push('-npm ts');
|
|
2782
|
+
if (configOptions.allowTs === false)
|
|
2783
|
+
settings.push('-npm nts');
|
|
2705
2784
|
if (settings.length > 0) {
|
|
2706
2785
|
console.log(colors.dim(`Settings from .globalize.json5: ${settings.join(', ')}`));
|
|
2707
2786
|
}
|
|
@@ -2782,7 +2861,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
2782
2861
|
}
|
|
2783
2862
|
// Check ignore files first (unless cleanup mode)
|
|
2784
2863
|
if (!cleanup && !asis) {
|
|
2785
|
-
const checkResult = checkIgnoreFiles(cwd, { conform, asis, verbose });
|
|
2864
|
+
const checkResult = checkIgnoreFiles(cwd, { conform, asis, verbose, allowTs });
|
|
2786
2865
|
// Auto-add security patterns without prompting
|
|
2787
2866
|
if (checkResult.securityChanges.length > 0) {
|
|
2788
2867
|
const secGit = [];
|
|
@@ -2795,7 +2874,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
2795
2874
|
secNpm.push(change.replace(' .npmignore missing: ', '').trim());
|
|
2796
2875
|
}
|
|
2797
2876
|
}
|
|
2798
|
-
conformIgnoreFiles(cwd, true);
|
|
2877
|
+
conformIgnoreFiles(cwd, true, allowTs);
|
|
2799
2878
|
if (secGit.length > 0) {
|
|
2800
2879
|
console.log(colors.cyan(' .gitignore: auto-added ') + secGit.join(', '));
|
|
2801
2880
|
}
|
|
@@ -2826,7 +2905,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
2826
2905
|
console.log('');
|
|
2827
2906
|
if (conform) {
|
|
2828
2907
|
console.log('Applying changes (--conform)...');
|
|
2829
|
-
conformIgnoreFiles(cwd);
|
|
2908
|
+
conformIgnoreFiles(cwd, false, allowTs);
|
|
2830
2909
|
console.log('');
|
|
2831
2910
|
}
|
|
2832
2911
|
else {
|
|
@@ -2838,7 +2917,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
2838
2917
|
const choice = await promptChoice('Your choice [ok/asis/abort]:', ['ok', 'asis', 'abort']);
|
|
2839
2918
|
if (choice === 'ok') {
|
|
2840
2919
|
console.log('Applying changes...');
|
|
2841
|
-
conformIgnoreFiles(cwd);
|
|
2920
|
+
conformIgnoreFiles(cwd, false, allowTs);
|
|
2842
2921
|
console.log(colors.green('✓ Ignore files updated'));
|
|
2843
2922
|
console.log('');
|
|
2844
2923
|
}
|
|
@@ -2896,13 +2975,13 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
2896
2975
|
options.autoInit = true;
|
|
2897
2976
|
}
|
|
2898
2977
|
// choice is '1', 'a', or '' (default)
|
|
2899
|
-
const success = await initGit(cwd, gitVisibility, dryRun);
|
|
2978
|
+
const success = await initGit(cwd, gitVisibility, dryRun, allowTs);
|
|
2900
2979
|
if (!success)
|
|
2901
2980
|
return false;
|
|
2902
2981
|
justInitialized = true;
|
|
2903
2982
|
}
|
|
2904
2983
|
else {
|
|
2905
|
-
const success = await initGit(cwd, gitVisibility, dryRun);
|
|
2984
|
+
const success = await initGit(cwd, gitVisibility, dryRun, allowTs);
|
|
2906
2985
|
if (!success)
|
|
2907
2986
|
return false;
|
|
2908
2987
|
justInitialized = true;
|
|
@@ -2925,7 +3004,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
2925
3004
|
options.autoInit = true;
|
|
2926
3005
|
}
|
|
2927
3006
|
}
|
|
2928
|
-
const success = await initGit(cwd, gitVisibility, dryRun);
|
|
3007
|
+
const success = await initGit(cwd, gitVisibility, dryRun, allowTs);
|
|
2929
3008
|
if (!success)
|
|
2930
3009
|
return false;
|
|
2931
3010
|
justInitialized = true;
|
|
@@ -3061,6 +3140,8 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
3061
3140
|
const pkg = readPackageJson(cwd);
|
|
3062
3141
|
// Run build step if package.json has a build script (skip if CLI already built)
|
|
3063
3142
|
if (pkg.scripts?.build && !options._fromCli) {
|
|
3143
|
+
if (!dryRun)
|
|
3144
|
+
ensureFileDepModules(cwd, verbose);
|
|
3064
3145
|
console.log(`${timestamp()} Running build...`);
|
|
3065
3146
|
if (!dryRun) {
|
|
3066
3147
|
// Always capture output so we can extract tsc errors for the summary
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bobfrankston/npmglobalize",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.155",
|
|
4
4
|
"description": "Transform file: dependencies to npm versions for publishing",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@bobfrankston/freezepak": "^0.1.7",
|
|
35
35
|
"@bobfrankston/importgen": "^0.1.34",
|
|
36
|
+
"@bobfrankston/npmglobalize": "^1.0.153",
|
|
36
37
|
"@bobfrankston/themecolors": "^0.1.5",
|
|
37
38
|
"@bobfrankston/userconfig": "^1.0.7",
|
|
38
39
|
"@npmcli/package-json": "^7.0.4",
|
|
@@ -48,6 +49,7 @@
|
|
|
48
49
|
".dependencies": {
|
|
49
50
|
"@bobfrankston/freezepak": "file:../freezepak",
|
|
50
51
|
"@bobfrankston/importgen": "file:../importgen",
|
|
52
|
+
"@bobfrankston/npmglobalize": "^1.0.153",
|
|
51
53
|
"@bobfrankston/themecolors": "file:../themecolors",
|
|
52
54
|
"@bobfrankston/userconfig": "file:../userconfig",
|
|
53
55
|
"@npmcli/package-json": "^7.0.4",
|
|
@@ -61,6 +63,7 @@
|
|
|
61
63
|
"dependencies": {
|
|
62
64
|
"@bobfrankston/freezepak": "^0.1.7",
|
|
63
65
|
"@bobfrankston/importgen": "^0.1.34",
|
|
66
|
+
"@bobfrankston/npmglobalize": "^1.0.153",
|
|
64
67
|
"@bobfrankston/themecolors": "^0.1.5",
|
|
65
68
|
"@bobfrankston/userconfig": "^1.0.7",
|
|
66
69
|
"@npmcli/package-json": "^7.0.4",
|