@bobfrankston/npmglobalize 1.0.80 → 1.0.81
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/cli.js +51 -75
- package/lib.d.ts +2 -0
- package/lib.js +28 -1
- package/package.json +1 -1
package/cli.js
CHANGED
|
@@ -5,41 +5,10 @@
|
|
|
5
5
|
import { globalize, globalizeWorkspace, readConfig, readPackageJson, writeConfig, writePackageJson } from './lib.js';
|
|
6
6
|
import fs from 'fs';
|
|
7
7
|
import path from 'path';
|
|
8
|
-
import { fileURLToPath } from 'url';
|
|
9
8
|
import { styleText } from 'util';
|
|
10
9
|
import JSON5 from 'json5';
|
|
11
|
-
//
|
|
12
|
-
const __dirname =
|
|
13
|
-
// Check all .ts files in the directory
|
|
14
|
-
const tsFiles = ['lib.ts', 'cli.ts', 'index.ts'];
|
|
15
|
-
const outOfSync = [];
|
|
16
|
-
for (const tsFile of tsFiles) {
|
|
17
|
-
const tsPath = path.join(__dirname, tsFile);
|
|
18
|
-
const jsPath = path.join(__dirname, tsFile.replace('.ts', '.js'));
|
|
19
|
-
if (fs.existsSync(tsPath) && fs.existsSync(jsPath)) {
|
|
20
|
-
const tsStat = fs.statSync(tsPath);
|
|
21
|
-
const jsStat = fs.statSync(jsPath);
|
|
22
|
-
if (jsStat.mtime < tsStat.mtime) {
|
|
23
|
-
outOfSync.push(tsFile);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
if (outOfSync.length > 0 && !process.argv.includes('--force')) {
|
|
28
|
-
console.error('\n' + styleText('red', '❌ Build check failed:'));
|
|
29
|
-
console.error(styleText('red', ` ${outOfSync.length} file(s) need compilation in ${__dirname}:`));
|
|
30
|
-
outOfSync.forEach(f => {
|
|
31
|
-
const tsPath = path.join(__dirname, f);
|
|
32
|
-
const jsPath = path.join(__dirname, f.replace('.ts', '.js'));
|
|
33
|
-
const tsMtime = fs.statSync(tsPath).mtime;
|
|
34
|
-
const jsMtime = fs.statSync(jsPath).mtime;
|
|
35
|
-
const fmt = (d) => d.toLocaleString();
|
|
36
|
-
console.error(styleText('red', ` - ${tsPath}`));
|
|
37
|
-
console.error(styleText('red', ` .ts: ${fmt(tsMtime)} .js: ${fmt(jsMtime)}`));
|
|
38
|
-
});
|
|
39
|
-
console.error('\n' + styleText('yellow', ' Please run: tsc'));
|
|
40
|
-
console.error(styleText('yellow', ' Or use --force to skip this check') + '\n');
|
|
41
|
-
process.exit(1);
|
|
42
|
-
}
|
|
10
|
+
// npmglobalize install directory (for --version)
|
|
11
|
+
const __dirname = import.meta.dirname;
|
|
43
12
|
function printHelp() {
|
|
44
13
|
console.log(`
|
|
45
14
|
npmglobalize - Transform file: dependencies to npm versions for publishing
|
|
@@ -68,6 +37,7 @@ Install Options:
|
|
|
68
37
|
--install, -i Global install after publish (from registry)
|
|
69
38
|
--link Global install via symlink (npm install -g .)
|
|
70
39
|
--wsl Also install globally in WSL
|
|
40
|
+
--once Don't persist flags to .globalize.json5
|
|
71
41
|
|
|
72
42
|
Mode Options:
|
|
73
43
|
--files Keep file: paths after publish (default)
|
|
@@ -300,6 +270,9 @@ function parseArgs(args) {
|
|
|
300
270
|
case '-pkg':
|
|
301
271
|
options.package = true;
|
|
302
272
|
break;
|
|
273
|
+
case '--once':
|
|
274
|
+
options.once = true;
|
|
275
|
+
break;
|
|
303
276
|
default:
|
|
304
277
|
if (arg.startsWith('-')) {
|
|
305
278
|
unrecognized.push(arg);
|
|
@@ -329,52 +302,11 @@ export async function main() {
|
|
|
329
302
|
process.exit(0);
|
|
330
303
|
}
|
|
331
304
|
if (cliOptions.version) {
|
|
332
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
333
|
-
const __dirname = path.dirname(__filename);
|
|
334
305
|
const pkgPath = path.join(__dirname, 'package.json');
|
|
335
306
|
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
336
307
|
console.log(pkg.version);
|
|
337
308
|
process.exit(0);
|
|
338
309
|
}
|
|
339
|
-
// Check if TypeScript files are compiled (unless --force or --help/--version)
|
|
340
|
-
if (!cliOptions.force && !cliOptions.help && !cliOptions.version) {
|
|
341
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
342
|
-
const __dirname = path.dirname(__filename);
|
|
343
|
-
// Check for noEmit in tsconfig.json
|
|
344
|
-
let noEmit = false;
|
|
345
|
-
try {
|
|
346
|
-
const tsconfigPath = path.join(__dirname, 'tsconfig.json');
|
|
347
|
-
const content = fs.readFileSync(tsconfigPath, 'utf-8');
|
|
348
|
-
const tsconfig = JSON5.parse(content);
|
|
349
|
-
noEmit = tsconfig.compilerOptions?.noEmit === true;
|
|
350
|
-
}
|
|
351
|
-
catch (error) {
|
|
352
|
-
// If we can't read tsconfig, assume we need to check
|
|
353
|
-
}
|
|
354
|
-
if (!noEmit) {
|
|
355
|
-
// Check if this .js file is older than its .ts source
|
|
356
|
-
const jsFile = __filename;
|
|
357
|
-
const tsFile = jsFile.replace(/\.js$/, '.ts');
|
|
358
|
-
if (fs.existsSync(tsFile)) {
|
|
359
|
-
if (!fs.existsSync(jsFile)) {
|
|
360
|
-
console.error('\n❌ Error: TypeScript files not compiled');
|
|
361
|
-
console.error(`Missing: ${path.basename(jsFile)}`);
|
|
362
|
-
console.error('\nPlease run: npm run build');
|
|
363
|
-
console.error('Or use --force to skip this check\n');
|
|
364
|
-
process.exit(1);
|
|
365
|
-
}
|
|
366
|
-
const tsStat = fs.statSync(tsFile);
|
|
367
|
-
const jsStat = fs.statSync(jsFile);
|
|
368
|
-
if (jsStat.mtime < tsStat.mtime) {
|
|
369
|
-
console.error('\n❌ Error: TypeScript files not compiled');
|
|
370
|
-
console.error(`${path.basename(jsFile)} is older than ${path.basename(tsFile)}`);
|
|
371
|
-
console.error('\nPlease run: npm run build');
|
|
372
|
-
console.error('Or use --force to skip this check\n');
|
|
373
|
-
process.exit(1);
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
310
|
if (cliOptions.error) {
|
|
379
311
|
console.error(`Error: ${cliOptions.error}`);
|
|
380
312
|
console.error('Run with --help for usage.');
|
|
@@ -393,6 +325,50 @@ export async function main() {
|
|
|
393
325
|
process.exit(1);
|
|
394
326
|
}
|
|
395
327
|
}
|
|
328
|
+
// Check if TypeScript files in target project are compiled
|
|
329
|
+
if (!cliOptions.force) {
|
|
330
|
+
let noEmit = false;
|
|
331
|
+
try {
|
|
332
|
+
const tsconfigPath = path.join(cwd, 'tsconfig.json');
|
|
333
|
+
const content = fs.readFileSync(tsconfigPath, 'utf-8');
|
|
334
|
+
const tsconfig = JSON5.parse(content);
|
|
335
|
+
noEmit = tsconfig.compilerOptions?.noEmit === true;
|
|
336
|
+
}
|
|
337
|
+
catch (error) {
|
|
338
|
+
// No tsconfig or can't parse — skip check
|
|
339
|
+
noEmit = true;
|
|
340
|
+
}
|
|
341
|
+
if (!noEmit) {
|
|
342
|
+
const outOfSync = [];
|
|
343
|
+
const jsFiles = fs.readdirSync(cwd).filter(f => f.endsWith('.js') && !f.endsWith('.min.js'));
|
|
344
|
+
for (const jsFile of jsFiles) {
|
|
345
|
+
const tsFile = jsFile.replace(/\.js$/, '.ts');
|
|
346
|
+
const tsPath = path.join(cwd, tsFile);
|
|
347
|
+
const jsPath = path.join(cwd, jsFile);
|
|
348
|
+
if (fs.existsSync(tsPath)) {
|
|
349
|
+
const tsStat = fs.statSync(tsPath);
|
|
350
|
+
const jsStat = fs.statSync(jsPath);
|
|
351
|
+
if (jsStat.mtime < tsStat.mtime) {
|
|
352
|
+
outOfSync.push(tsFile);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
if (outOfSync.length > 0) {
|
|
357
|
+
console.error('\n' + styleText('red', '❌ Build check failed:'));
|
|
358
|
+
console.error(styleText('red', ` ${outOfSync.length} file(s) need compilation in ${cwd}:`));
|
|
359
|
+
outOfSync.forEach(f => {
|
|
360
|
+
const tsPath = path.join(cwd, f);
|
|
361
|
+
const jsPath = path.join(cwd, f.replace('.ts', '.js'));
|
|
362
|
+
const fmt = (d) => d.toLocaleString();
|
|
363
|
+
console.error(styleText('red', ` - ${f}`));
|
|
364
|
+
console.error(styleText('red', ` .ts: ${fmt(fs.statSync(tsPath).mtime)} .js: ${fmt(fs.statSync(jsPath).mtime)}`));
|
|
365
|
+
});
|
|
366
|
+
console.error('\n' + styleText('yellow', ' Please run: tsc'));
|
|
367
|
+
console.error(styleText('yellow', ' Or use --force to skip this check') + '\n');
|
|
368
|
+
process.exit(1);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
396
372
|
// Handle --package: update scripts in target package.json
|
|
397
373
|
if (cliOptions.package) {
|
|
398
374
|
const pkg = readPackageJson(cwd);
|
|
@@ -419,7 +395,7 @@ export async function main() {
|
|
|
419
395
|
const configOptions = readConfig(cwd);
|
|
420
396
|
const options = { ...configOptions, ...cliOptions };
|
|
421
397
|
// Persist explicitly set CLI flags to .globalize.json5
|
|
422
|
-
if (cliOptions.explicitKeys.size > 0) {
|
|
398
|
+
if (cliOptions.explicitKeys.size > 0 && !cliOptions.once) {
|
|
423
399
|
const persistable = { ...configOptions };
|
|
424
400
|
for (const key of cliOptions.explicitKeys) {
|
|
425
401
|
persistable[key] = options[key];
|
package/lib.d.ts
CHANGED
|
@@ -69,6 +69,8 @@ export interface GlobalizeOptions {
|
|
|
69
69
|
continueOnError?: boolean;
|
|
70
70
|
/** Update package.json scripts to use npmglobalize */
|
|
71
71
|
package?: boolean;
|
|
72
|
+
/** Don't persist CLI flags to .globalize.json5 */
|
|
73
|
+
once?: boolean;
|
|
72
74
|
/** Internal: signals this call is from workspace orchestrator */
|
|
73
75
|
_fromWorkspace?: boolean;
|
|
74
76
|
}
|
package/lib.js
CHANGED
|
@@ -110,7 +110,7 @@ export function writeConfig(dir, config, explicitKeys) {
|
|
|
110
110
|
const existing = readConfig(dir);
|
|
111
111
|
// Filter out temporary flags and default values (unless explicitly set)
|
|
112
112
|
const filtered = {};
|
|
113
|
-
const omitKeys = new Set(['noPublish', 'cleanup', 'init', 'dryRun', 'message', 'conform', 'asis', 'help', 'error', 'updateDeps', 'updateMajor', 'publishDeps', 'forcePublish']);
|
|
113
|
+
const omitKeys = new Set(['noPublish', 'cleanup', 'init', 'dryRun', 'message', 'conform', 'asis', 'help', 'error', 'updateDeps', 'updateMajor', 'publishDeps', 'forcePublish', 'once']);
|
|
114
114
|
for (const [key, value] of Object.entries(config)) {
|
|
115
115
|
if (omitKeys.has(key))
|
|
116
116
|
continue;
|
|
@@ -719,6 +719,27 @@ export function fixVersionTagMismatch(cwd, pkg, verbose = false) {
|
|
|
719
719
|
}
|
|
720
720
|
return deletedAny;
|
|
721
721
|
}
|
|
722
|
+
/** Wait for a package version to appear on the npm registry */
|
|
723
|
+
function waitForNpmVersion(pkgName, version, maxWaitMs = 60000) {
|
|
724
|
+
const interval = 3000;
|
|
725
|
+
const maxAttempts = Math.ceil(maxWaitMs / interval);
|
|
726
|
+
process.stdout.write(`Waiting for ${pkgName}@${version} on npm registry`);
|
|
727
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
728
|
+
const result = spawnSync('npm', ['view', `${pkgName}@${version}`, 'version'], {
|
|
729
|
+
shell: process.platform === 'win32',
|
|
730
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
731
|
+
encoding: 'utf-8'
|
|
732
|
+
});
|
|
733
|
+
if (result.status === 0 && result.stdout?.trim() === version) {
|
|
734
|
+
process.stdout.write(' ready\n');
|
|
735
|
+
return true;
|
|
736
|
+
}
|
|
737
|
+
process.stdout.write('.');
|
|
738
|
+
spawnSync(process.platform === 'win32' ? 'timeout' : 'sleep', process.platform === 'win32' ? ['/t', '3', '/nobreak'] : ['3'], { stdio: 'pipe', shell: process.platform === 'win32' });
|
|
739
|
+
}
|
|
740
|
+
process.stdout.write(' timed out\n');
|
|
741
|
+
return false;
|
|
742
|
+
}
|
|
722
743
|
/** Run a command and return success status */
|
|
723
744
|
export function runCommand(cmd, args, options = {}) {
|
|
724
745
|
const { silent = false, cwd } = options;
|
|
@@ -2053,6 +2074,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
2053
2074
|
}
|
|
2054
2075
|
}
|
|
2055
2076
|
else if (install) {
|
|
2077
|
+
waitForNpmVersion(pkgName, pkgVersion);
|
|
2056
2078
|
console.log(`Installing ${pkgName}@${pkgVersion} globally from registry...`);
|
|
2057
2079
|
const registryInstallResult = runCommand('npm', ['install', '-g', `${pkgName}@${pkgVersion}`], { cwd, silent: false });
|
|
2058
2080
|
if (registryInstallResult.success) {
|
|
@@ -2065,6 +2087,8 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
2065
2087
|
}
|
|
2066
2088
|
if (wsl) {
|
|
2067
2089
|
const wslArgs = link ? ['npm', 'install', '-g', '.'] : ['npm', 'install', '-g', `${pkgName}@${pkgVersion}`];
|
|
2090
|
+
if (!link && !install)
|
|
2091
|
+
waitForNpmVersion(pkgName, pkgVersion);
|
|
2068
2092
|
console.log(`Installing ${pkgName} in WSL${link ? ' (link)' : ' from registry'}...`);
|
|
2069
2093
|
const wslInstallResult = runCommand('wsl', wslArgs, { cwd, silent: false });
|
|
2070
2094
|
if (wslInstallResult.success) {
|
|
@@ -2510,6 +2534,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
2510
2534
|
else if (install) {
|
|
2511
2535
|
console.log(`Installing globally from registry: ${pkgName}@${pkgVersion}...`);
|
|
2512
2536
|
if (!dryRun) {
|
|
2537
|
+
waitForNpmVersion(pkgName, pkgVersion);
|
|
2513
2538
|
const installResult = runCommand('npm', ['install', '-g', `${pkgName}@${pkgVersion}`], { cwd, silent: false });
|
|
2514
2539
|
if (installResult.success) {
|
|
2515
2540
|
console.log(colors.green(`✓ Installed globally: ${pkgName}@${pkgVersion}`));
|
|
@@ -2525,6 +2550,8 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
2525
2550
|
}
|
|
2526
2551
|
if (wsl) {
|
|
2527
2552
|
const wslArgs = link ? ['npm', 'install', '-g', '.'] : ['npm', 'install', '-g', `${pkgName}@${pkgVersion}`];
|
|
2553
|
+
if (!link && !install)
|
|
2554
|
+
waitForNpmVersion(pkgName, pkgVersion);
|
|
2528
2555
|
console.log(`Installing in WSL${link ? ' (link)' : ' from registry'}: ${pkgName}@${pkgVersion}...`);
|
|
2529
2556
|
if (!dryRun) {
|
|
2530
2557
|
const wslResult = runCommand('wsl', wslArgs, { cwd, silent: false });
|