@_linked/cli 1.45.3 → 1.45.5
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/CHANGELOG.md +12 -0
- package/lib/esm/cli-methods.d.ts.map +1 -1
- package/lib/esm/cli-methods.js +18 -3
- package/lib/esm/cli-methods.js.map +1 -1
- package/lib/esm/localize/ensure.d.ts +7 -0
- package/lib/esm/localize/ensure.d.ts.map +1 -1
- package/lib/esm/localize/ensure.js +8 -1
- package/lib/esm/localize/ensure.js.map +1 -1
- package/package.json +2 -2
|
@@ -13,6 +13,13 @@ import type { Deps } from './run.js';
|
|
|
13
13
|
* npm syncs a lockfile header the release workflow bumped. Changing a
|
|
14
14
|
* checkout's dependencies is a deliberate `npm install <dep>` inside it.
|
|
15
15
|
*
|
|
16
|
+
* `--include=dev` because this runs from the app's npm lifecycle hooks, and
|
|
17
|
+
* npm exports the outer command's config to them as `npm_config_*`: measured,
|
|
18
|
+
* `npm install --omit=dev` at the app root arrives as `npm_config_omit=dev`,
|
|
19
|
+
* and an inner install that inherits it skips the checkout's
|
|
20
|
+
* devDependencies, so the checkout no longer builds. A checkout is a
|
|
21
|
+
* development copy; it always needs them.
|
|
22
|
+
*
|
|
16
23
|
* The package's name is read from the checkout's own `package.json`; the
|
|
17
24
|
* other localized packages (siblings) from the manifest, so a checkout being
|
|
18
25
|
* localized right now prunes before the manifest records it.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ensure.d.ts","sourceRoot":"","sources":["../../../src/localize/ensure.ts"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,eAAe,CAAC;AASjD,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,YAAY,CAAC;AAE7C,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,UAAU,CAAC;AAGnC
|
|
1
|
+
{"version":3,"file":"ensure.d.ts","sourceRoot":"","sources":["../../../src/localize/ensure.ts"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,eAAe,CAAC;AASjD,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,YAAY,CAAC;AAE7C,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,UAAU,CAAC;AAGnC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,MAAM,CACpB,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC,EACvD,IAAI,EAAE,IAAI,EACV,IAAI,GAAE,YAAiB,GACtB,MAAM,CA4BR;AAED,8EAA8E;AAC9E,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,IAAI,GACT,MAAM,CAoBR;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,OAAO,GAAE,MAAsB,EAC/B,IAAI,GAAE,IAAI,CAAC,IAAI,EAAE,KAAK,GAAG,MAAM,CAAwB,GACtD;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAC,CAwCpB"}
|
|
@@ -44,6 +44,13 @@ import { reportError } from './localize.js';
|
|
|
44
44
|
* npm syncs a lockfile header the release workflow bumped. Changing a
|
|
45
45
|
* checkout's dependencies is a deliberate `npm install <dep>` inside it.
|
|
46
46
|
*
|
|
47
|
+
* `--include=dev` because this runs from the app's npm lifecycle hooks, and
|
|
48
|
+
* npm exports the outer command's config to them as `npm_config_*`: measured,
|
|
49
|
+
* `npm install --omit=dev` at the app root arrives as `npm_config_omit=dev`,
|
|
50
|
+
* and an inner install that inherits it skips the checkout's
|
|
51
|
+
* devDependencies, so the checkout no longer builds. A checkout is a
|
|
52
|
+
* development copy; it always needs them.
|
|
53
|
+
*
|
|
47
54
|
* The package's name is read from the checkout's own `package.json`; the
|
|
48
55
|
* other localized packages (siblings) from the manifest, so a checkout being
|
|
49
56
|
* localized right now prunes before the manifest records it.
|
|
@@ -55,7 +62,7 @@ export function ensure(entry, deps, opts = {}) {
|
|
|
55
62
|
var _a;
|
|
56
63
|
const pkgDir = path.join(deps.appRoot, entry.path);
|
|
57
64
|
deps.log(`[localize] npm install in ${entry.path}`);
|
|
58
|
-
const install = deps.run('npm', ['install', '--no-save', '--no-audit', '--no-fund'], { cwd: pkgDir });
|
|
65
|
+
const install = deps.run('npm', ['install', '--no-save', '--include=dev', '--no-audit', '--no-fund'], { cwd: pkgDir });
|
|
59
66
|
if (install.status !== 0) {
|
|
60
67
|
throw new LocalizeError(`npm install failed in ${entry.path}:\n${(install.stderr || install.stdout).trim()}`, EXIT_INSTALL_FAILED);
|
|
61
68
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ensure.js","sourceRoot":"","sources":["../../../src/localize/ensure.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * One copy, always: every package the app provides loads once, whichever tool\n * runs the code -- Vite, `tsc`, plain Node, `tsx`, a test runner.\n *\n * Two halves:\n *\n * - **`ensure(entry)`** -- the ONLY way a checkout gets installed: `npm\n * install` inside it, then prune it (prune.ts). localize's install step,\n * `--relink`'s reinstall and `linked localize --reinstall <pkg>` all go\n * through it, so the copies an install puts back exist only until it\n * returns. Hand-running `npm install` in a checkout is what `--reinstall`\n * replaces.\n * - **`checkOneCopy(appRoot)`** -- the run-time check. Before `linked start`,\n * `script`, `call` and `build-all` (a commander `preAction` in cli.ts), and\n * as `linked localize --ensure` for an app's npm `pre*` scripts. It plans\n * the prune (prune.ts `planPrune`) without touching anything -- per-owner\n * candidates, the same range guard, the same \"would its dependencies\n * resolve elsewhere\" check -- and only when that plan removes something does\n * it prune, and say so in one line on stderr. A copy prune would keep costs\n * a stat and, at most, one requirement index per `node_modules` (read from\n * npm's hidden lockfile), so a tree full of kept copies stays cheap. It\n * never runs npm, prints nothing when there is nothing to do (or no\n * manifest), skips a checkout recorded with `prune: false`, and never\n * throws: a run command must not fail over a developer's private checkout\n * state.\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport {\n EXIT_INSTALL_FAILED,\n EXIT_REFUSED,\n EXIT_WARNED,\n LocalizeError,\n} from './errors.js';\nimport {manifestPath, readManifest} from './manifest.js';\nimport type {ManifestEntry} from './manifest.js';\nimport {readJson} from './fsops.js';\nimport {\n newPruneCache,\n planPrune,\n pruneProvided,\n prunesEntry,\n shouldPrune,\n} from './prune.js';\nimport type {PruneOptions} from './prune.js';\nimport {defaultDeps} from './run.js';\nimport type {Deps} from './run.js';\nimport {reportError} from './localize.js';\n\n/**\n * `npm install --no-save` inside the checkout at `entry.path`, then prune it.\n *\n * `--no-save` keeps the checkout's tracked files out of it: npm installs what\n * the committed lockfile says and writes neither `package.json` nor\n * `package-lock.json` (only the gitignored hidden lockfile). Without it every\n * relink left a lockfile diff in each checkout it reinstalled, written in the\n * dialect of whichever npm was first on PATH -- measured: Node 22's bundled\n * npm 10.9.9 drops every `\"libc\"` field an npm 12 lockfile records, and any\n * npm syncs a lockfile header the release workflow bumped. Changing a\n * checkout's dependencies is a deliberate `npm install <dep>` inside it.\n *\n * The package's name is read from the checkout's own `package.json`; the\n * other localized packages (siblings) from the manifest, so a checkout being\n * localized right now prunes before the manifest records it.\n *\n * @returns 0, or `EXIT_WARNED` when the prune failed (the install stands).\n * @throws {LocalizeError} `EXIT_INSTALL_FAILED` when `npm install` fails.\n */\nexport function ensure(\n entry: Pick<ManifestEntry, 'path' | 'subdir' | 'prune'>,\n deps: Deps,\n opts: PruneOptions = {},\n): number {\n const pkgDir = path.join(deps.appRoot, entry.path);\n deps.log(`[localize] npm install in ${entry.path}`);\n const install = deps.run(\n 'npm',\n ['install', '--no-save', '--no-audit', '--no-fund'],\n {cwd: pkgDir},\n );\n if (install.status !== 0) {\n throw new LocalizeError(\n `npm install failed in ${entry.path}:\\n${(install.stderr || install.stdout).trim()}`,\n EXIT_INSTALL_FAILED,\n );\n }\n if (!shouldPrune(opts) || !prunesEntry(entry)) return 0;\n\n const name = readJson(path.join(pkgDir, 'package.json'))?.name;\n if (typeof name !== 'string') return 0;\n try {\n const entries = {...recordedEntries(deps), [name]: entry as ManifestEntry};\n pruneProvided(entries, opts, deps, {owners: [name]});\n return 0;\n } catch (e) {\n deps.warn(\n `[localize] pruning ${entry.path} failed, its node_modules are as npm left them: ${e.message}`,\n );\n return EXIT_WARNED;\n }\n}\n\n/** `linked localize --reinstall <pkg>`: `ensure` for one recorded package. */\nexport function reinstall(\n name: string,\n opts: PruneOptions,\n deps: Deps,\n): number {\n try {\n const entry = readManifest(deps.appRoot, deps).entries[name];\n if (!entry) {\n throw new LocalizeError(\n `${name} is not localized here, so there is no checkout to reinstall. ` +\n '`linked localize --list` shows what is.',\n EXIT_REFUSED,\n );\n }\n if (!fs.existsSync(path.join(deps.appRoot, entry.path, 'package.json'))) {\n throw new LocalizeError(\n `${name} is recorded at ${entry.path}, which has no package.json.`,\n EXIT_REFUSED,\n );\n }\n return ensure(entry, deps, opts);\n } catch (e) {\n return reportError(e, deps);\n }\n}\n\n/**\n * The run-time check: remove every recorded checkout's own copy of what the\n * app provides -- exactly what `pruneProvided` would remove, decided first\n * without it, so the common case (nothing to remove, some copies kept) never\n * reaches the prune.\n *\n * @returns what was removed, as `<checkout>/node_modules/<name>@<version>`.\n */\nexport function checkOneCopy(\n appRoot: string = process.cwd(),\n deps: Pick<Deps, 'log' | 'warn'> = defaultDeps(appRoot),\n): {pruned: string[]} {\n try {\n if (!fs.existsSync(manifestPath(appRoot))) return {pruned: []};\n const entries = readManifest(appRoot, {warn: () => {}}).entries;\n const owners = Object.keys(entries);\n if (!owners.length) return {pruned: []};\n\n if (!Object.values(entries).some(prunesEntry)) return {pruned: []};\n\n const cache = newPruneCache();\n const plan = planPrune(entries, {appRoot}, {}, cache);\n if (!plan.remove.length) return {pruned: []};\n\n // Prune's own report is per checkout and also speaks of what it keeps;\n // here only what went is worth a line, on every run command.\n const quiet = {appRoot, log: () => {}, warn: () => {}};\n const {removed} = pruneProvided(\n entries,\n {},\n quiet,\n {\n owners: [...new Set(plan.remove.map((d) => d.ownerName))],\n deps: [...new Set(plan.remove.map((d) => d.dep))],\n },\n cache,\n );\n const pruned = removed.map((r) => `${r.where}@${r.version}`);\n if (pruned.length) {\n deps.warn(\n `[localize] one copy: removed ${pruned.join(', ')} — the app provides ` +\n `${pruned.length === 1 ? 'it' : 'them'}.`,\n );\n }\n return {pruned};\n } catch (e) {\n deps.warn(\n `[localize] one-copy check failed, nothing more was removed: ${e?.message ?? e}`,\n );\n return {pruned: []};\n }\n}\n\nfunction recordedEntries(deps: Deps): Record<string, ManifestEntry> {\n try {\n return readManifest(deps.appRoot, {warn: () => {}}).entries;\n } catch {\n return {};\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ensure.js","sourceRoot":"","sources":["../../../src/localize/ensure.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * One copy, always: every package the app provides loads once, whichever tool\n * runs the code -- Vite, `tsc`, plain Node, `tsx`, a test runner.\n *\n * Two halves:\n *\n * - **`ensure(entry)`** -- the ONLY way a checkout gets installed: `npm\n * install` inside it, then prune it (prune.ts). localize's install step,\n * `--relink`'s reinstall and `linked localize --reinstall <pkg>` all go\n * through it, so the copies an install puts back exist only until it\n * returns. Hand-running `npm install` in a checkout is what `--reinstall`\n * replaces.\n * - **`checkOneCopy(appRoot)`** -- the run-time check. Before `linked start`,\n * `script`, `call` and `build-all` (a commander `preAction` in cli.ts), and\n * as `linked localize --ensure` for an app's npm `pre*` scripts. It plans\n * the prune (prune.ts `planPrune`) without touching anything -- per-owner\n * candidates, the same range guard, the same \"would its dependencies\n * resolve elsewhere\" check -- and only when that plan removes something does\n * it prune, and say so in one line on stderr. A copy prune would keep costs\n * a stat and, at most, one requirement index per `node_modules` (read from\n * npm's hidden lockfile), so a tree full of kept copies stays cheap. It\n * never runs npm, prints nothing when there is nothing to do (or no\n * manifest), skips a checkout recorded with `prune: false`, and never\n * throws: a run command must not fail over a developer's private checkout\n * state.\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport {\n EXIT_INSTALL_FAILED,\n EXIT_REFUSED,\n EXIT_WARNED,\n LocalizeError,\n} from './errors.js';\nimport {manifestPath, readManifest} from './manifest.js';\nimport type {ManifestEntry} from './manifest.js';\nimport {readJson} from './fsops.js';\nimport {\n newPruneCache,\n planPrune,\n pruneProvided,\n prunesEntry,\n shouldPrune,\n} from './prune.js';\nimport type {PruneOptions} from './prune.js';\nimport {defaultDeps} from './run.js';\nimport type {Deps} from './run.js';\nimport {reportError} from './localize.js';\n\n/**\n * `npm install --no-save` inside the checkout at `entry.path`, then prune it.\n *\n * `--no-save` keeps the checkout's tracked files out of it: npm installs what\n * the committed lockfile says and writes neither `package.json` nor\n * `package-lock.json` (only the gitignored hidden lockfile). Without it every\n * relink left a lockfile diff in each checkout it reinstalled, written in the\n * dialect of whichever npm was first on PATH -- measured: Node 22's bundled\n * npm 10.9.9 drops every `\"libc\"` field an npm 12 lockfile records, and any\n * npm syncs a lockfile header the release workflow bumped. Changing a\n * checkout's dependencies is a deliberate `npm install <dep>` inside it.\n *\n * `--include=dev` because this runs from the app's npm lifecycle hooks, and\n * npm exports the outer command's config to them as `npm_config_*`: measured,\n * `npm install --omit=dev` at the app root arrives as `npm_config_omit=dev`,\n * and an inner install that inherits it skips the checkout's\n * devDependencies, so the checkout no longer builds. A checkout is a\n * development copy; it always needs them.\n *\n * The package's name is read from the checkout's own `package.json`; the\n * other localized packages (siblings) from the manifest, so a checkout being\n * localized right now prunes before the manifest records it.\n *\n * @returns 0, or `EXIT_WARNED` when the prune failed (the install stands).\n * @throws {LocalizeError} `EXIT_INSTALL_FAILED` when `npm install` fails.\n */\nexport function ensure(\n entry: Pick<ManifestEntry, 'path' | 'subdir' | 'prune'>,\n deps: Deps,\n opts: PruneOptions = {},\n): number {\n const pkgDir = path.join(deps.appRoot, entry.path);\n deps.log(`[localize] npm install in ${entry.path}`);\n const install = deps.run(\n 'npm',\n ['install', '--no-save', '--include=dev', '--no-audit', '--no-fund'],\n {cwd: pkgDir},\n );\n if (install.status !== 0) {\n throw new LocalizeError(\n `npm install failed in ${entry.path}:\\n${(install.stderr || install.stdout).trim()}`,\n EXIT_INSTALL_FAILED,\n );\n }\n if (!shouldPrune(opts) || !prunesEntry(entry)) return 0;\n\n const name = readJson(path.join(pkgDir, 'package.json'))?.name;\n if (typeof name !== 'string') return 0;\n try {\n const entries = {...recordedEntries(deps), [name]: entry as ManifestEntry};\n pruneProvided(entries, opts, deps, {owners: [name]});\n return 0;\n } catch (e) {\n deps.warn(\n `[localize] pruning ${entry.path} failed, its node_modules are as npm left them: ${e.message}`,\n );\n return EXIT_WARNED;\n }\n}\n\n/** `linked localize --reinstall <pkg>`: `ensure` for one recorded package. */\nexport function reinstall(\n name: string,\n opts: PruneOptions,\n deps: Deps,\n): number {\n try {\n const entry = readManifest(deps.appRoot, deps).entries[name];\n if (!entry) {\n throw new LocalizeError(\n `${name} is not localized here, so there is no checkout to reinstall. ` +\n '`linked localize --list` shows what is.',\n EXIT_REFUSED,\n );\n }\n if (!fs.existsSync(path.join(deps.appRoot, entry.path, 'package.json'))) {\n throw new LocalizeError(\n `${name} is recorded at ${entry.path}, which has no package.json.`,\n EXIT_REFUSED,\n );\n }\n return ensure(entry, deps, opts);\n } catch (e) {\n return reportError(e, deps);\n }\n}\n\n/**\n * The run-time check: remove every recorded checkout's own copy of what the\n * app provides -- exactly what `pruneProvided` would remove, decided first\n * without it, so the common case (nothing to remove, some copies kept) never\n * reaches the prune.\n *\n * @returns what was removed, as `<checkout>/node_modules/<name>@<version>`.\n */\nexport function checkOneCopy(\n appRoot: string = process.cwd(),\n deps: Pick<Deps, 'log' | 'warn'> = defaultDeps(appRoot),\n): {pruned: string[]} {\n try {\n if (!fs.existsSync(manifestPath(appRoot))) return {pruned: []};\n const entries = readManifest(appRoot, {warn: () => {}}).entries;\n const owners = Object.keys(entries);\n if (!owners.length) return {pruned: []};\n\n if (!Object.values(entries).some(prunesEntry)) return {pruned: []};\n\n const cache = newPruneCache();\n const plan = planPrune(entries, {appRoot}, {}, cache);\n if (!plan.remove.length) return {pruned: []};\n\n // Prune's own report is per checkout and also speaks of what it keeps;\n // here only what went is worth a line, on every run command.\n const quiet = {appRoot, log: () => {}, warn: () => {}};\n const {removed} = pruneProvided(\n entries,\n {},\n quiet,\n {\n owners: [...new Set(plan.remove.map((d) => d.ownerName))],\n deps: [...new Set(plan.remove.map((d) => d.dep))],\n },\n cache,\n );\n const pruned = removed.map((r) => `${r.where}@${r.version}`);\n if (pruned.length) {\n deps.warn(\n `[localize] one copy: removed ${pruned.join(', ')} — the app provides ` +\n `${pruned.length === 1 ? 'it' : 'them'}.`,\n );\n }\n return {pruned};\n } catch (e) {\n deps.warn(\n `[localize] one-copy check failed, nothing more was removed: ${e?.message ?? e}`,\n );\n return {pruned: []};\n }\n}\n\nfunction recordedEntries(deps: Deps): Record<string, ManifestEntry> {\n try {\n return readManifest(deps.appRoot, {warn: () => {}}).entries;\n } catch {\n return {};\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@_linked/cli",
|
|
3
|
-
"version": "1.45.
|
|
4
|
-
"packageManager": "npm@
|
|
3
|
+
"version": "1.45.5",
|
|
4
|
+
"packageManager": "npm@12.2.0",
|
|
5
5
|
"description": "Command line tools for the @_linked/* packages and apps",
|
|
6
6
|
"main": "lib/esm/index.js",
|
|
7
7
|
"types": "index.d.ts",
|