@_linked/cli 1.45.0 → 1.45.2

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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.45.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [#214](https://github.com/linked-fw/cli/pull/214) [`684cd26`](https://github.com/linked-fw/cli/commit/684cd26d626e63b42bd1b4b5aff0f35955cdc47e) Thanks [@carlenmy](https://github.com/carlenmy)! - The Node CSS loader now names package stylesheets in the mode the app actually runs in. It runs on Node's module-hooks thread, which copies `process.env` when `launch.js` registers it, before the CLI loads the app's `.env`. So a `NODE_ENV=development` that came only from `.env` (or `.env-cmdrc.json`) never reached it, and externalised packages such as `@_linked/primitives` were server-rendered with production class names while the dev client used dev names, which caused a hydration mismatch. `launch.js` now resolves the mode before registering the hooks (shell, then `.env`, then the `.env-cmdrc.json` profile, then `development` for `linked start`) and passes it to the loader through `register(url, {data})`. Production naming is unchanged.
8
+
9
+ ## 1.45.1
10
+
11
+ ### Patch Changes
12
+
13
+ - [#236](https://github.com/linked-fw/cli/pull/236) [`275c719`](https://github.com/linked-fw/cli/commit/275c719dc32985146299971803396f4755a8cf8c) Thanks [@flyon](https://github.com/flyon)! - `linked localize` no longer leaves a `package-lock.json` diff in the checkouts it reinstalls. Every install it runs inside a checkout (localize, `--adopt`, `--relink`'s reinstall, `--reinstall`) is now `npm install --no-save`: it installs what the checkout's committed lockfile says and writes neither its `package.json` nor its `package-lock.json`. A plain `npm install` rewrote the lockfile in the dialect of whichever npm was first on PATH — Node 22's bundled npm 10.9.9 dropped every `"libc"` field an npm 12 lockfile records — and synced any lockfile header a release had bumped. To change a checkout's dependencies, run `npm install <dep>` inside it on purpose.
14
+
3
15
  ## 1.45.0
4
16
 
5
17
  ### Minor Changes
package/lib/esm/launch.js CHANGED
@@ -8,9 +8,12 @@
8
8
  // ships legacy-signature property decorators and tsx/esbuild's default
9
9
  // otherwise emits TC39 standard decorators, breaking property
10
10
  // registration in user scripts.
11
- import { register } from 'node:module';
12
- register(new URL('./loaders/css-loader.mjs', import.meta.url));
13
- register(new URL('./loaders/ts-loader.mjs', import.meta.url));
11
+ //
12
+ // The hooks run on their own thread, which never sees the app's `.env`: the CLI
13
+ // loads it later. So the CSS loader is told its naming mode here, resolved
14
+ // before anything loads — see loader-mode.ts.
15
+ import { registerLoaders } from './loaders/register.js';
16
+ registerLoaders();
14
17
  import('./cli.js').catch((err) => {
15
18
  console.error(err);
16
19
  process.exit(1);
@@ -1 +1 @@
1
- {"version":3,"file":"launch.js","sourceRoot":"","sources":["../../src/launch.ts"],"names":[],"mappings":";AACA,uEAAuE;AACvE,yEAAyE;AACzE,+DAA+D;AAC/D,EAAE;AACF,0EAA0E;AAC1E,wEAAwE;AACxE,uEAAuE;AACvE,8DAA8D;AAC9D,gCAAgC;AAChC,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAErC,QAAQ,CAAC,IAAI,GAAG,CAAC,0BAA0B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,QAAQ,CAAC,IAAI,GAAG,CAAC,yBAAyB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE9D,MAAM,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC/B,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\n// Bootstrap entry for the `linked` bin. Registers Node module hooks at\n// the top level, then dynamically imports the CLI so any TS/CSS that the\n// CLI later loads from a user's app flows through these hooks.\n//\n// We use a custom ts-loader (based on esbuild) instead of `tsx` so we can\n// force `experimentalDecorators: true` on the transform — @_linked/core\n// ships legacy-signature property decorators and tsx/esbuild's default\n// otherwise emits TC39 standard decorators, breaking property\n// registration in user scripts.\nimport {register} from 'node:module';\n\nregister(new URL('./loaders/css-loader.mjs', import.meta.url));\nregister(new URL('./loaders/ts-loader.mjs', import.meta.url));\n\nimport('./cli.js').catch((err) => {\n console.error(err);\n process.exit(1);\n});\n"]}
1
+ {"version":3,"file":"launch.js","sourceRoot":"","sources":["../../src/launch.ts"],"names":[],"mappings":";AACA,uEAAuE;AACvE,yEAAyE;AACzE,+DAA+D;AAC/D,EAAE;AACF,0EAA0E;AAC1E,wEAAwE;AACxE,uEAAuE;AACvE,8DAA8D;AAC9D,gCAAgC;AAChC,EAAE;AACF,gFAAgF;AAChF,2EAA2E;AAC3E,8CAA8C;AAC9C,OAAO,EAAC,eAAe,EAAC,MAAM,uBAAuB,CAAC;AAEtD,eAAe,EAAE,CAAC;AAElB,MAAM,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC/B,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\n// Bootstrap entry for the `linked` bin. Registers Node module hooks at\n// the top level, then dynamically imports the CLI so any TS/CSS that the\n// CLI later loads from a user's app flows through these hooks.\n//\n// We use a custom ts-loader (based on esbuild) instead of `tsx` so we can\n// force `experimentalDecorators: true` on the transform — @_linked/core\n// ships legacy-signature property decorators and tsx/esbuild's default\n// otherwise emits TC39 standard decorators, breaking property\n// registration in user scripts.\n//\n// The hooks run on their own thread, which never sees the app's `.env`: the CLI\n// loads it later. So the CSS loader is told its naming mode here, resolved\n// before anything loads — see loader-mode.ts.\nimport {registerLoaders} from './loaders/register.js';\n\nregisterLoaders();\n\nimport('./cli.js').catch((err) => {\n console.error(err);\n process.exit(1);\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../src/lifecycle.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,iBAAiB,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,uBAAuB,GAClC,mBAAmB,MAAM,EAAE,KAC1B,OAAO,CAAC,IAAI,CA+Bd,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,qBAAqB,GAAI,SAAS;IAC7C,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;CACpB,KAAG,MAAM,EAeT,CAAC;AAgDF;;;;;GAKG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,GAAG,CAAC,CAyB7D;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,YAAa,SAAQ,cAAc;IAClD,+BAA+B;IAC/B,MAAM,EAAE,WAAW,GAAG,oBAAoB,CAAC;IAC3C,yDAAyD;IACzD,eAAe,EAAE,OAAO,CAAC;IACzB,2EAA2E;IAC3E,KAAK,EAAE,OAAO,CAAC;IACf,0EAA0E;IAC1E,cAAc,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AAEnD;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,SAAgB,GACvB,cAAc,EAAE,CAIlB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,SAAgB,EACxB,OAAO,GAAE;IAAC,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAM,GAC3E,YAAY,EAAE,CA4BhB;AAgJD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAMnE;AAED,mEAAmE;AACnE,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,2EAA2E;AAC3E,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACnC,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,QAAQ,SAAO,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,YAAY,CAkD5E"}
1
+ {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../src/lifecycle.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,iBAAiB,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,uBAAuB,GAClC,mBAAmB,MAAM,EAAE,KAC1B,OAAO,CAAC,IAAI,CA+Bd,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,qBAAqB,GAAI,SAAS;IAC7C,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;CACpB,KAAG,MAAM,EAeT,CAAC;AAyCF;;;;;GAKG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,GAAG,CAAC,CAyB7D;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,YAAa,SAAQ,cAAc;IAClD,+BAA+B;IAC/B,MAAM,EAAE,WAAW,GAAG,oBAAoB,CAAC;IAC3C,yDAAyD;IACzD,eAAe,EAAE,OAAO,CAAC;IACzB,2EAA2E;IAC3E,KAAK,EAAE,OAAO,CAAC;IACf,0EAA0E;IAC1E,cAAc,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AAEnD;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,SAAgB,GACvB,cAAc,EAAE,CAIlB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,SAAgB,EACxB,OAAO,GAAE;IAAC,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAM,GAC3E,YAAY,EAAE,CA4BhB;AAgJD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAMnE;AAED,mEAAmE;AACnE,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,2EAA2E;AAC3E,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACnC,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,QAAQ,SAAO,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,YAAY,CAkD5E"}
@@ -21,6 +21,8 @@ import { getPackageJSON } from './utils.js';
21
21
  import { isLinkedPackageJson } from './installed-packages.js';
22
22
  import { readManifest } from './localize/manifest.js';
23
23
  import { parseWorkspacePatterns, isWorkspacePathNegated } from './workspace-globs.js';
24
+ // Shared with the CSS loader's mode resolution, which must pick the same profiles.
25
+ import { readEnvNamesFromArgv } from './loader-mode.js';
24
26
  /**
25
27
  * Load the app's environment into `process.env`, then re-apply the original
26
28
  * shell env so it always wins on conflict. Idempotent — runs at most once.
@@ -132,13 +134,6 @@ const loadEnvCmdrc = (envCmdrcPath, environmentNames) => __awaiter(void 0, void
132
134
  console.log('No environment specified, using development');
133
135
  }
134
136
  });
135
- const readEnvNamesFromArgv = () => {
136
- const args = process.argv.slice(2);
137
- const envIndex = args.indexOf('--env');
138
- if (envIndex === -1)
139
- return [];
140
- return (args[envIndex + 1] || '').split(',').filter(Boolean);
141
- };
142
137
  /**
143
138
  * Discover and load the app's storage-config bootstrap file. Tries the
144
139
  * canonical `linked.backend.storage.{ts,js}` first, then legacy paths.
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/lifecycle.ts"],"names":[],"mappings":"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","sourcesContent":["// Lifecycle helpers shared by the Vite-based dev orchestrator.\n//\n// Extracted from cli-methods.ts so the SSR module graph (started from\n// `commands/start.ts`) doesn't have to walk the rest of that file. The\n// the older helpers in cli-methods.ts contain many dynamic\n// `import(<variable>)` calls Vite can't analyze statically and would\n// emit warnings about — even though startWithVite never calls them.\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport chalk from 'chalk';\nimport {getPackageJSON} from './utils.js';\nimport {isLinkedPackageJson} from './installed-packages.js';\nimport {readManifest} from './localize/manifest.js';\nimport {parseWorkspacePatterns, isWorkspacePathNegated} from './workspace-globs.js';\nimport type {PackageDetails} from './interfaces.js';\n\n/**\n * Load the app's environment into `process.env`, then re-apply the original\n * shell env so it always wins on conflict. Idempotent — runs at most once.\n *\n * Two sources, tried in this order:\n * 1. `.env` (Node-native `process.loadEnvFile`, no dependency) — a flat file.\n * This is what the app template ships and the only form that will survive.\n * `--env` is not consulted here: a flat `.env` has no profiles, so\n * NODE_ENV comes from the file or the shell.\n * 2. `.env-cmdrc.json` (DEPRECATED, via `env-cmd`) — profile-based; honours\n * `--env a,b` and merges `_main` + the named profiles. Still read when it\n * is the only file present, so no existing app breaks, but it warns.\n *\n * `.env` going first is what makes migrating a one-step job: add the flat file\n * and it takes over. The profile file can then be deleted whenever convenient.\n *\n * If neither file exists we skip silently — CN-hosted apps have their env\n * injected into the child process at spawn time, so there's nothing to read\n * from disk.\n */\nexport const ensureEnvironmentLoaded = async (\n environmentNames?: string[],\n): Promise<void> => {\n if (process.env.ENV_VARS_LOADED) return;\n const cwd = process.cwd();\n const envCmdrcPath = path.join(cwd, '.env-cmdrc.json');\n const dotEnvPath = path.join(cwd, '.env');\n\n // Snapshot the original shell env — it should always take priority over\n // whatever a file sets (so injected/production env wins over dev defaults).\n const shellEnv = {...process.env};\n\n const hasDotEnv = fs.existsSync(dotEnvPath);\n const hasEnvCmdrc = fs.existsSync(envCmdrcPath);\n\n for (const notice of envDeprecationNotices({hasEnvCmdrc, hasDotEnv})) {\n console.warn(chalk.yellow(notice));\n }\n\n if (hasDotEnv) {\n // Native flat-file loader (Node 20.12+). Populates process.env from `.env`.\n process.loadEnvFile(dotEnvPath);\n } else if (hasEnvCmdrc) {\n await loadEnvCmdrc(envCmdrcPath, environmentNames);\n } else {\n console.warn(\n 'No .env or .env-cmdrc.json found in this folder — relying on the ambient environment.',\n );\n }\n\n // Re-apply shell env so it always wins over file values.\n process.env = {...process.env, ...shellEnv};\n process.env.ENV_VARS_LOADED = 'true';\n};\n\n/**\n * What to tell an app about where its environment came from.\n *\n * `.env-cmdrc.json` is still read when it is the only file present, so no app\n * breaks today. But it is the only reason `--env` exists, and both are going\n * away.\n *\n * The case worth shouting about is an app holding both files: `.env` wins, so\n * the profile file and every `--env` name passed with it do nothing. That is\n * the intended migration path, but it is invisible from the outside — values\n * an app still believes it is getting from a profile are simply absent.\n *\n * Pure and exported so the messages can be asserted without a chdir.\n */\nexport const envDeprecationNotices = (sources: {\n hasEnvCmdrc: boolean;\n hasDotEnv: boolean;\n}): string[] => {\n if (!sources.hasEnvCmdrc) return [];\n const notices = [\n '.env-cmdrc.json is deprecated and will be removed in a future major release.',\n ' Move its values into a flat `.env`, and supply anything that differs per ' +\n 'deployment from the environment itself. `--env` goes away with it.',\n ];\n if (sources.hasDotEnv) {\n notices.push(\n ' This app has BOTH files. `.env` wins, so `.env-cmdrc.json` — and any ' +\n '`--env` profile named with it — is being ignored entirely. Delete it once ' +\n 'the flat file is complete.',\n );\n }\n return notices;\n};\n\n/**\n * Legacy loader: reads `.env-cmdrc.json`, merges `_main` plus the profile(s)\n * named by `--env a,b` (default `development`). Kept for CN and existing apps\n * until they migrate to a flat `.env`.\n */\nconst loadEnvCmdrc = async (\n envCmdrcPath: string,\n environmentNames?: string[],\n): Promise<void> => {\n // env-cmd ships ESM; literal specifier is fine for Vite's analyzer.\n const {GetEnvVars} = await import('env-cmd');\n const vars = await GetEnvVars({envFile: {filePath: envCmdrcPath}});\n const environments = Object.keys(vars);\n\n if (environments.includes('_main')) {\n process.env = {...process.env, ...vars._main};\n }\n // Callers that parsed `--env` themselves pass the names in. Commands that\n // have not been converted yet still have their names scraped off argv.\n const requested = environmentNames?.length\n ? environmentNames\n : readEnvNamesFromArgv();\n if (requested.length) {\n requested.forEach((name) => {\n if (environments.includes(name)) {\n console.log('Environment: ' + name);\n process.env = {...process.env, ...vars[name]};\n } else {\n console.warn(\n `Environment ${name} not found in .env-cmdrc.json. Available: ${environments.join(', ')}`,\n );\n }\n });\n } else {\n process.env = {...process.env, ...vars.development};\n console.log('No environment specified, using development');\n }\n};\n\nconst readEnvNamesFromArgv = (): string[] => {\n const args = process.argv.slice(2);\n const envIndex = args.indexOf('--env');\n if (envIndex === -1) return [];\n return (args[envIndex + 1] || '').split(',').filter(Boolean);\n};\n\n/**\n * Discover and load the app's storage-config bootstrap file. Tries the\n * canonical `linked.backend.storage.{ts,js}` first, then legacy paths.\n * Returns whatever the file's default export evaluates to, or undefined\n * if no candidate exists.\n */\nexport async function loadBackendStorageConfig(): Promise<any> {\n const cwd = process.cwd();\n const candidates = [\n path.join(cwd, 'linked.backend.storage.ts'),\n path.join(cwd, 'linked.backend.storage.js'),\n path.join(cwd, 'backend-storage-config.ts'),\n path.join(cwd, 'backend-storage-config.js'),\n path.join(cwd, 'scripts', 'backend-storage-config.js'),\n path.join(cwd, 'scripts', 'backend-storage-config.ts'),\n path.join(cwd, 'scripts', 'storage-config.js'),\n ];\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n // Variable specifier is intentional — we discover the path at\n // runtime by probing the candidate list, so static analysis is\n // impossible.\n return import(/* @vite-ignore */ candidate);\n }\n }\n console.warn(\n chalk.yellow(\n '[linked.backend.storage] no linked.backend.storage.{ts,js} found at app root.',\n ),\n );\n return undefined;\n}\n\n/**\n * A local package directory found by {@link discoverLocalPackages}, together\n * with the facts that decide what can be done with it.\n *\n * The facts are recorded rather than filtered on, because the bug this type\n * exists to fix was a SILENT filter: `build-all` discovered only packages\n * carrying `linkedPackage: true` and printed nothing about the rest, so\n * `@_linked/maps` — a shipped dependency that simply never got the flag — was\n * dropped from a green build for as long as nobody counted the names.\n */\nexport interface LocalPackage extends PackageDetails {\n /** Where the walk found it. */\n source: 'workspace' | 'local-packages-dir';\n /** `linkedPackage: true` — see `isLinkedPackageJson`. */\n isLinkedPackage: boolean;\n /** `linkedApp: true` — built by `linked build-app`, not `linked build`. */\n isApp: boolean;\n /** Has a `build` script of its own, which is what `build-all` invokes. */\n hasBuildScript: boolean;\n}\n\n/**\n * Directory holding localized checkouts (`linked localize`). It is\n * deliberately in NO workspace glob — that is the whole point of the design,\n * since npm learning about these checkouts is what made their predecessor\n * under `packages/` a trap — so any walk of `workspaces` alone cannot see it\n * and has to be told about it separately.\n */\nexport const LOCAL_PACKAGES_DIR = 'packages-local';\n\n/**\n * Walk the app's `package.json` `workspaces` field and return every\n * workspace package that declares `\"linkedPackage\": true`.\n *\n * Lives here (not in cli-methods.ts) so consumers like LinkedServer can\n * import it without dragging the rest of the legacy cli-methods flow into\n * Vite's SSR module graph.\n *\n * Kept deliberately narrow: this is the set the dev resolver and the runtime\n * treat as linked packages. Commands that want every *buildable* local\n * package — flag or no flag, workspace or localized checkout — want\n * {@link discoverLocalPackages} instead.\n */\nexport function getLincdPackages(\n rootPath = process.cwd(),\n): PackageDetails[] {\n return discoverLocalPackages(rootPath, {includeLocalPackagesDir: false})\n .filter((pkg) => pkg.isLinkedPackage)\n .map(({path: packagePath, packageName}) => ({path: packagePath, packageName}));\n}\n\n/**\n * Every local package directory this app can see, whether or not it declares\n * `linkedPackage: true`.\n *\n * Two sources, because the workspace globs are not the whole picture any more:\n *\n * 1. the `workspaces` field (negations honoured — see ./workspace-globs.js);\n * 2. `packages-local/`, the localized checkouts, which is in no glob.\n *\n * Nothing is filtered out here. Callers decide what they can act on and are\n * expected to SAY what they skipped and why.\n */\nexport function discoverLocalPackages(\n rootPath = process.cwd(),\n options: {includeLocalPackagesDir?: boolean; localPackagesDir?: string} = {},\n): LocalPackage[] {\n const {includeLocalPackagesDir = true, localPackagesDir = LOCAL_PACKAGES_DIR} =\n options;\n\n let pack = getPackageJSON(rootPath);\n if (!pack || !pack.workspaces) {\n const originalRoot = rootPath;\n for (let i = 0; i <= 3; i++) {\n rootPath = path.join(originalRoot, ...Array(i).fill('..'));\n pack = getPackageJSON(rootPath);\n if (pack && pack.workspaces) break;\n }\n if (!pack || !pack.workspaces) {\n // Standalone apps (scaffolded with `linked create-app`) don't have\n // workspaces — expected. Fall back to the original root so a\n // `packages-local/` beside it is still found.\n rootPath = originalRoot;\n }\n }\n\n const res: LocalPackage[] = [];\n if (pack && pack.workspaces) {\n checkWorkspaces(rootPath, pack.workspaces, res);\n }\n if (includeLocalPackagesDir) {\n checkLocalPackagesDir(rootPath, localPackagesDir, res);\n }\n return res;\n}\n\n/**\n * Add every immediate subdirectory of `packages-local/` that holds a\n * `package.json`. No glob, no negations: the directory has no `workspaces`\n * entry to interpret, its contents are there because a developer localized\n * them on purpose, and each one is a plain checkout.\n */\nfunction checkLocalPackagesDir(\n rootPath: string,\n localPackagesDir: string,\n res: LocalPackage[],\n) {\n const dir = path.join(rootPath, localPackagesDir);\n if (!fs.existsSync(dir)) return;\n const already = new Set(res.map((pkg) => path.resolve(pkg.path)));\n for (const entry of fs.readdirSync(dir)) {\n if (entry.startsWith('.')) continue;\n const packagePath = path.join(dir, entry);\n if (!fs.statSync(packagePath).isDirectory()) continue;\n // A checkout that some glob already picked up must not appear twice —\n // duplicates would be built twice and counted twice.\n if (already.has(path.resolve(packagePath))) continue;\n addPackage(packagePath, 'local-packages-dir', res);\n }\n}\n\nfunction checkWorkspaces(rootPath: string, workspaces: any, res: LocalPackage[]) {\n // Negated entries (\"!packages/core\") are excluded the way npm excludes them\n // — including from the exact-path branch below, which npm also subjects to\n // them. See ./workspace-globs.js.\n const {patterns, negatedPatterns} = parseWorkspacePatterns(workspaces);\n const checkUnlessNegated = (packagePath: string) => {\n const rel = path.relative(rootPath, packagePath).split(path.sep).join('/');\n if (isWorkspacePathNegated(rel, negatedPatterns)) return;\n checkPackagePath(rootPath, packagePath, res);\n };\n patterns.forEach((workspace: string) => {\n const workspacePath = path.join(rootPath, workspace.replace('/*', ''));\n if (workspace.indexOf('/*') !== -1) {\n if (fs.existsSync(workspacePath)) {\n const folders = fs.readdirSync(workspacePath);\n folders.forEach((folder: string) => {\n if (folder !== './' && folder !== '../') {\n checkUnlessNegated(path.join(workspacePath, folder));\n }\n });\n }\n } else {\n checkUnlessNegated(workspacePath);\n }\n });\n}\n\nfunction checkPackagePath(rootPath: string, packagePath: string, res: LocalPackage[]) {\n const packageJsonPath = path.join(packagePath, 'package.json');\n if (!fs.existsSync(packageJsonPath)) return;\n const pack = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));\n if (pack && pack.workspaces) {\n checkWorkspaces(packagePath, pack.workspaces, res);\n } else if (pack) {\n addPackage(packagePath, 'workspace', res, pack);\n }\n}\n\nfunction addPackage(\n packagePath: string,\n source: LocalPackage['source'],\n res: LocalPackage[],\n packageJson?: any,\n) {\n const pack = packageJson ?? getPackageJSON(packagePath);\n if (!pack || !pack.name) return;\n res.push({\n path: packagePath,\n packageName: pack.name,\n source,\n // The one definition, shared with `linked build-package`.\n isLinkedPackage: isLinkedPackageJson(pack),\n isApp: pack.linkedApp === true,\n hasBuildScript: !!pack.scripts?.build,\n });\n}\n\n/**\n * Filters packages to only include those in the dependency tree of the app root\n */\nfunction filterPackagesByDependencyTree(\n allPackages: Map<string, PackageDetails>,\n appRootPath: string,\n): Map<string, PackageDetails> {\n const appPackageJson = getPackageJSON(appRootPath);\n if (!appPackageJson) {\n return allPackages;\n }\n\n const relevantPackages = new Map<string, PackageDetails>();\n const packagesToCheck = new Set<string>();\n\n // Start with direct dependencies from app root, plus everything localized:\n // a package created locally is linked but cannot be declared until it is\n // published (an unpublished range fails `npm install`), and being localized\n // already says this app is developed against it.\n [\n ...Object.keys(appPackageJson.dependencies || {}),\n ...localizedPackageNames(appRootPath),\n ].forEach((dep) => {\n if (allPackages.has(dep)) {\n packagesToCheck.add(dep);\n }\n });\n\n // Recursively add dependencies\n const processedPackages = new Set<string>();\n\n while (packagesToCheck.size > 0) {\n const packageName = Array.from(packagesToCheck)[0];\n packagesToCheck.delete(packageName);\n\n if (processedPackages.has(packageName)) {\n continue;\n }\n\n processedPackages.add(packageName);\n const packageDetails = allPackages.get(packageName);\n\n if (packageDetails) {\n relevantPackages.set(packageName, packageDetails);\n\n // Get this package's dependencies\n const packageJson = getPackageJSON(packageDetails.path);\n if (packageJson && packageJson.dependencies) {\n Object.keys(packageJson.dependencies).forEach((dep) => {\n if (allPackages.has(dep) && !processedPackages.has(dep)) {\n packagesToCheck.add(dep);\n }\n });\n }\n }\n }\n\n return relevantPackages;\n}\n\n/**\n * The package names recorded in the app's `local-packages.json` — what\n * `linked localize` has linked — read with localize's own reader. Read\n * tolerantly: `linked localize` refuses a malformed file (and warns about a\n * malformed entry) loudly, so here a missing or unusable file is simply\n * \"nothing localized\", and a malformed entry is skipped without a word.\n */\nexport function localizedPackageNames(appRootPath: string): string[] {\n try {\n return Object.keys(readManifest(appRootPath, {warn: () => {}}).entries);\n } catch {\n return [];\n }\n}\n\n/** A package `build-all` found but will not build, and why not. */\nexport interface SkippedPackage {\n packageName: string;\n path: string;\n reason: string;\n}\n\n/** What `build-all` found, and what it decided to do with each package. */\nexport interface BuildAllPlan {\n build: Map<string, PackageDetails>;\n skipped: SkippedPackage[];\n}\n\n/**\n * Decide what `build-all` builds.\n *\n * Every discovered package lands in exactly one of `build` or `skipped`, and\n * `skipped` carries a reason — because the failure mode this replaces was not\n * a narrow scan, it was a SILENT one. `@_linked/maps` is a shipped Create Now\n * dependency that never got `linkedPackage: true`; `build-all` dropped it and\n * printed nothing, so a build covering half the workspace exited 0 and people\n * acted on it. A skip nobody can see is worse than a failure.\n *\n * What counts as buildable is a CAPABILITY, not a declaration: `build-all`\n * invokes each package's own `build` script, so anything with one can be\n * built whether or not it carries the flag. The flag is still reported when\n * it is missing, since the dev resolver and `linked build` do require it.\n */\nexport function planBuildAll(rootPath = './', appRoot?: string): BuildAllPlan {\n const build = new Map<string, PackageDetails>();\n const skipped: SkippedPackage[] = [];\n const buildable: LocalPackage[] = [];\n\n for (const pkg of discoverLocalPackages(rootPath)) {\n const detail = {path: pkg.path, packageName: pkg.packageName};\n // Packages reached through a `../` workspace glob live outside this\n // repository; building them was never in scope for `build-all`.\n if (pkg.path.indexOf('../') !== -1 || pkg.path.indexOf('..\\\\') !== -1) {\n skipped.push({...detail, reason: 'outside this repository'});\n } else if (pkg.isApp) {\n skipped.push({\n ...detail,\n reason: 'is a linked app — build it with `linked build-app`',\n });\n } else if (!pkg.hasBuildScript) {\n skipped.push({...detail, reason: 'has no `build` script'});\n } else {\n buildable.push(pkg);\n build.set(pkg.packageName, detail);\n }\n }\n\n // Narrow to what this app actually depends on, if we are inside one.\n if (appRoot) {\n const appPackageJson = getPackageJSON(appRoot);\n const isAppWithLinkedDeps =\n appPackageJson &&\n !isLinkedPackageJson(appPackageJson) &&\n [\n ...Object.keys(appPackageJson.dependencies || {}),\n ...localizedPackageNames(appRoot),\n ].some((dep) => build.has(dep));\n\n if (isAppWithLinkedDeps) {\n const inTree = filterPackagesByDependencyTree(build, appRoot);\n for (const pkg of buildable) {\n if (inTree.has(pkg.packageName)) continue;\n build.delete(pkg.packageName);\n skipped.push({\n path: pkg.path,\n packageName: pkg.packageName,\n reason: `not in ${appPackageJson.name || 'this app'}'s dependency tree`,\n });\n }\n }\n }\n\n return {build, skipped};\n}\n\n"]}
1
+ {"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/lifecycle.ts"],"names":[],"mappings":"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","sourcesContent":["// Lifecycle helpers shared by the Vite-based dev orchestrator.\n//\n// Extracted from cli-methods.ts so the SSR module graph (started from\n// `commands/start.ts`) doesn't have to walk the rest of that file. The\n// the older helpers in cli-methods.ts contain many dynamic\n// `import(<variable>)` calls Vite can't analyze statically and would\n// emit warnings about — even though startWithVite never calls them.\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport chalk from 'chalk';\nimport {getPackageJSON} from './utils.js';\nimport {isLinkedPackageJson} from './installed-packages.js';\nimport {readManifest} from './localize/manifest.js';\nimport {parseWorkspacePatterns, isWorkspacePathNegated} from './workspace-globs.js';\n// Shared with the CSS loader's mode resolution, which must pick the same profiles.\nimport {readEnvNamesFromArgv} from './loader-mode.js';\nimport type {PackageDetails} from './interfaces.js';\n\n/**\n * Load the app's environment into `process.env`, then re-apply the original\n * shell env so it always wins on conflict. Idempotent — runs at most once.\n *\n * Two sources, tried in this order:\n * 1. `.env` (Node-native `process.loadEnvFile`, no dependency) — a flat file.\n * This is what the app template ships and the only form that will survive.\n * `--env` is not consulted here: a flat `.env` has no profiles, so\n * NODE_ENV comes from the file or the shell.\n * 2. `.env-cmdrc.json` (DEPRECATED, via `env-cmd`) — profile-based; honours\n * `--env a,b` and merges `_main` + the named profiles. Still read when it\n * is the only file present, so no existing app breaks, but it warns.\n *\n * `.env` going first is what makes migrating a one-step job: add the flat file\n * and it takes over. The profile file can then be deleted whenever convenient.\n *\n * If neither file exists we skip silently — CN-hosted apps have their env\n * injected into the child process at spawn time, so there's nothing to read\n * from disk.\n */\nexport const ensureEnvironmentLoaded = async (\n environmentNames?: string[],\n): Promise<void> => {\n if (process.env.ENV_VARS_LOADED) return;\n const cwd = process.cwd();\n const envCmdrcPath = path.join(cwd, '.env-cmdrc.json');\n const dotEnvPath = path.join(cwd, '.env');\n\n // Snapshot the original shell env — it should always take priority over\n // whatever a file sets (so injected/production env wins over dev defaults).\n const shellEnv = {...process.env};\n\n const hasDotEnv = fs.existsSync(dotEnvPath);\n const hasEnvCmdrc = fs.existsSync(envCmdrcPath);\n\n for (const notice of envDeprecationNotices({hasEnvCmdrc, hasDotEnv})) {\n console.warn(chalk.yellow(notice));\n }\n\n if (hasDotEnv) {\n // Native flat-file loader (Node 20.12+). Populates process.env from `.env`.\n process.loadEnvFile(dotEnvPath);\n } else if (hasEnvCmdrc) {\n await loadEnvCmdrc(envCmdrcPath, environmentNames);\n } else {\n console.warn(\n 'No .env or .env-cmdrc.json found in this folder — relying on the ambient environment.',\n );\n }\n\n // Re-apply shell env so it always wins over file values.\n process.env = {...process.env, ...shellEnv};\n process.env.ENV_VARS_LOADED = 'true';\n};\n\n/**\n * What to tell an app about where its environment came from.\n *\n * `.env-cmdrc.json` is still read when it is the only file present, so no app\n * breaks today. But it is the only reason `--env` exists, and both are going\n * away.\n *\n * The case worth shouting about is an app holding both files: `.env` wins, so\n * the profile file and every `--env` name passed with it do nothing. That is\n * the intended migration path, but it is invisible from the outside — values\n * an app still believes it is getting from a profile are simply absent.\n *\n * Pure and exported so the messages can be asserted without a chdir.\n */\nexport const envDeprecationNotices = (sources: {\n hasEnvCmdrc: boolean;\n hasDotEnv: boolean;\n}): string[] => {\n if (!sources.hasEnvCmdrc) return [];\n const notices = [\n '.env-cmdrc.json is deprecated and will be removed in a future major release.',\n ' Move its values into a flat `.env`, and supply anything that differs per ' +\n 'deployment from the environment itself. `--env` goes away with it.',\n ];\n if (sources.hasDotEnv) {\n notices.push(\n ' This app has BOTH files. `.env` wins, so `.env-cmdrc.json` — and any ' +\n '`--env` profile named with it — is being ignored entirely. Delete it once ' +\n 'the flat file is complete.',\n );\n }\n return notices;\n};\n\n/**\n * Legacy loader: reads `.env-cmdrc.json`, merges `_main` plus the profile(s)\n * named by `--env a,b` (default `development`). Kept for CN and existing apps\n * until they migrate to a flat `.env`.\n */\nconst loadEnvCmdrc = async (\n envCmdrcPath: string,\n environmentNames?: string[],\n): Promise<void> => {\n // env-cmd ships ESM; literal specifier is fine for Vite's analyzer.\n const {GetEnvVars} = await import('env-cmd');\n const vars = await GetEnvVars({envFile: {filePath: envCmdrcPath}});\n const environments = Object.keys(vars);\n\n if (environments.includes('_main')) {\n process.env = {...process.env, ...vars._main};\n }\n // Callers that parsed `--env` themselves pass the names in. Commands that\n // have not been converted yet still have their names scraped off argv.\n const requested = environmentNames?.length\n ? environmentNames\n : readEnvNamesFromArgv();\n if (requested.length) {\n requested.forEach((name) => {\n if (environments.includes(name)) {\n console.log('Environment: ' + name);\n process.env = {...process.env, ...vars[name]};\n } else {\n console.warn(\n `Environment ${name} not found in .env-cmdrc.json. Available: ${environments.join(', ')}`,\n );\n }\n });\n } else {\n process.env = {...process.env, ...vars.development};\n console.log('No environment specified, using development');\n }\n};\n\n/**\n * Discover and load the app's storage-config bootstrap file. Tries the\n * canonical `linked.backend.storage.{ts,js}` first, then legacy paths.\n * Returns whatever the file's default export evaluates to, or undefined\n * if no candidate exists.\n */\nexport async function loadBackendStorageConfig(): Promise<any> {\n const cwd = process.cwd();\n const candidates = [\n path.join(cwd, 'linked.backend.storage.ts'),\n path.join(cwd, 'linked.backend.storage.js'),\n path.join(cwd, 'backend-storage-config.ts'),\n path.join(cwd, 'backend-storage-config.js'),\n path.join(cwd, 'scripts', 'backend-storage-config.js'),\n path.join(cwd, 'scripts', 'backend-storage-config.ts'),\n path.join(cwd, 'scripts', 'storage-config.js'),\n ];\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n // Variable specifier is intentional — we discover the path at\n // runtime by probing the candidate list, so static analysis is\n // impossible.\n return import(/* @vite-ignore */ candidate);\n }\n }\n console.warn(\n chalk.yellow(\n '[linked.backend.storage] no linked.backend.storage.{ts,js} found at app root.',\n ),\n );\n return undefined;\n}\n\n/**\n * A local package directory found by {@link discoverLocalPackages}, together\n * with the facts that decide what can be done with it.\n *\n * The facts are recorded rather than filtered on, because the bug this type\n * exists to fix was a SILENT filter: `build-all` discovered only packages\n * carrying `linkedPackage: true` and printed nothing about the rest, so\n * `@_linked/maps` — a shipped dependency that simply never got the flag — was\n * dropped from a green build for as long as nobody counted the names.\n */\nexport interface LocalPackage extends PackageDetails {\n /** Where the walk found it. */\n source: 'workspace' | 'local-packages-dir';\n /** `linkedPackage: true` — see `isLinkedPackageJson`. */\n isLinkedPackage: boolean;\n /** `linkedApp: true` — built by `linked build-app`, not `linked build`. */\n isApp: boolean;\n /** Has a `build` script of its own, which is what `build-all` invokes. */\n hasBuildScript: boolean;\n}\n\n/**\n * Directory holding localized checkouts (`linked localize`). It is\n * deliberately in NO workspace glob — that is the whole point of the design,\n * since npm learning about these checkouts is what made their predecessor\n * under `packages/` a trap — so any walk of `workspaces` alone cannot see it\n * and has to be told about it separately.\n */\nexport const LOCAL_PACKAGES_DIR = 'packages-local';\n\n/**\n * Walk the app's `package.json` `workspaces` field and return every\n * workspace package that declares `\"linkedPackage\": true`.\n *\n * Lives here (not in cli-methods.ts) so consumers like LinkedServer can\n * import it without dragging the rest of the legacy cli-methods flow into\n * Vite's SSR module graph.\n *\n * Kept deliberately narrow: this is the set the dev resolver and the runtime\n * treat as linked packages. Commands that want every *buildable* local\n * package — flag or no flag, workspace or localized checkout — want\n * {@link discoverLocalPackages} instead.\n */\nexport function getLincdPackages(\n rootPath = process.cwd(),\n): PackageDetails[] {\n return discoverLocalPackages(rootPath, {includeLocalPackagesDir: false})\n .filter((pkg) => pkg.isLinkedPackage)\n .map(({path: packagePath, packageName}) => ({path: packagePath, packageName}));\n}\n\n/**\n * Every local package directory this app can see, whether or not it declares\n * `linkedPackage: true`.\n *\n * Two sources, because the workspace globs are not the whole picture any more:\n *\n * 1. the `workspaces` field (negations honoured — see ./workspace-globs.js);\n * 2. `packages-local/`, the localized checkouts, which is in no glob.\n *\n * Nothing is filtered out here. Callers decide what they can act on and are\n * expected to SAY what they skipped and why.\n */\nexport function discoverLocalPackages(\n rootPath = process.cwd(),\n options: {includeLocalPackagesDir?: boolean; localPackagesDir?: string} = {},\n): LocalPackage[] {\n const {includeLocalPackagesDir = true, localPackagesDir = LOCAL_PACKAGES_DIR} =\n options;\n\n let pack = getPackageJSON(rootPath);\n if (!pack || !pack.workspaces) {\n const originalRoot = rootPath;\n for (let i = 0; i <= 3; i++) {\n rootPath = path.join(originalRoot, ...Array(i).fill('..'));\n pack = getPackageJSON(rootPath);\n if (pack && pack.workspaces) break;\n }\n if (!pack || !pack.workspaces) {\n // Standalone apps (scaffolded with `linked create-app`) don't have\n // workspaces — expected. Fall back to the original root so a\n // `packages-local/` beside it is still found.\n rootPath = originalRoot;\n }\n }\n\n const res: LocalPackage[] = [];\n if (pack && pack.workspaces) {\n checkWorkspaces(rootPath, pack.workspaces, res);\n }\n if (includeLocalPackagesDir) {\n checkLocalPackagesDir(rootPath, localPackagesDir, res);\n }\n return res;\n}\n\n/**\n * Add every immediate subdirectory of `packages-local/` that holds a\n * `package.json`. No glob, no negations: the directory has no `workspaces`\n * entry to interpret, its contents are there because a developer localized\n * them on purpose, and each one is a plain checkout.\n */\nfunction checkLocalPackagesDir(\n rootPath: string,\n localPackagesDir: string,\n res: LocalPackage[],\n) {\n const dir = path.join(rootPath, localPackagesDir);\n if (!fs.existsSync(dir)) return;\n const already = new Set(res.map((pkg) => path.resolve(pkg.path)));\n for (const entry of fs.readdirSync(dir)) {\n if (entry.startsWith('.')) continue;\n const packagePath = path.join(dir, entry);\n if (!fs.statSync(packagePath).isDirectory()) continue;\n // A checkout that some glob already picked up must not appear twice —\n // duplicates would be built twice and counted twice.\n if (already.has(path.resolve(packagePath))) continue;\n addPackage(packagePath, 'local-packages-dir', res);\n }\n}\n\nfunction checkWorkspaces(rootPath: string, workspaces: any, res: LocalPackage[]) {\n // Negated entries (\"!packages/core\") are excluded the way npm excludes them\n // — including from the exact-path branch below, which npm also subjects to\n // them. See ./workspace-globs.js.\n const {patterns, negatedPatterns} = parseWorkspacePatterns(workspaces);\n const checkUnlessNegated = (packagePath: string) => {\n const rel = path.relative(rootPath, packagePath).split(path.sep).join('/');\n if (isWorkspacePathNegated(rel, negatedPatterns)) return;\n checkPackagePath(rootPath, packagePath, res);\n };\n patterns.forEach((workspace: string) => {\n const workspacePath = path.join(rootPath, workspace.replace('/*', ''));\n if (workspace.indexOf('/*') !== -1) {\n if (fs.existsSync(workspacePath)) {\n const folders = fs.readdirSync(workspacePath);\n folders.forEach((folder: string) => {\n if (folder !== './' && folder !== '../') {\n checkUnlessNegated(path.join(workspacePath, folder));\n }\n });\n }\n } else {\n checkUnlessNegated(workspacePath);\n }\n });\n}\n\nfunction checkPackagePath(rootPath: string, packagePath: string, res: LocalPackage[]) {\n const packageJsonPath = path.join(packagePath, 'package.json');\n if (!fs.existsSync(packageJsonPath)) return;\n const pack = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));\n if (pack && pack.workspaces) {\n checkWorkspaces(packagePath, pack.workspaces, res);\n } else if (pack) {\n addPackage(packagePath, 'workspace', res, pack);\n }\n}\n\nfunction addPackage(\n packagePath: string,\n source: LocalPackage['source'],\n res: LocalPackage[],\n packageJson?: any,\n) {\n const pack = packageJson ?? getPackageJSON(packagePath);\n if (!pack || !pack.name) return;\n res.push({\n path: packagePath,\n packageName: pack.name,\n source,\n // The one definition, shared with `linked build-package`.\n isLinkedPackage: isLinkedPackageJson(pack),\n isApp: pack.linkedApp === true,\n hasBuildScript: !!pack.scripts?.build,\n });\n}\n\n/**\n * Filters packages to only include those in the dependency tree of the app root\n */\nfunction filterPackagesByDependencyTree(\n allPackages: Map<string, PackageDetails>,\n appRootPath: string,\n): Map<string, PackageDetails> {\n const appPackageJson = getPackageJSON(appRootPath);\n if (!appPackageJson) {\n return allPackages;\n }\n\n const relevantPackages = new Map<string, PackageDetails>();\n const packagesToCheck = new Set<string>();\n\n // Start with direct dependencies from app root, plus everything localized:\n // a package created locally is linked but cannot be declared until it is\n // published (an unpublished range fails `npm install`), and being localized\n // already says this app is developed against it.\n [\n ...Object.keys(appPackageJson.dependencies || {}),\n ...localizedPackageNames(appRootPath),\n ].forEach((dep) => {\n if (allPackages.has(dep)) {\n packagesToCheck.add(dep);\n }\n });\n\n // Recursively add dependencies\n const processedPackages = new Set<string>();\n\n while (packagesToCheck.size > 0) {\n const packageName = Array.from(packagesToCheck)[0];\n packagesToCheck.delete(packageName);\n\n if (processedPackages.has(packageName)) {\n continue;\n }\n\n processedPackages.add(packageName);\n const packageDetails = allPackages.get(packageName);\n\n if (packageDetails) {\n relevantPackages.set(packageName, packageDetails);\n\n // Get this package's dependencies\n const packageJson = getPackageJSON(packageDetails.path);\n if (packageJson && packageJson.dependencies) {\n Object.keys(packageJson.dependencies).forEach((dep) => {\n if (allPackages.has(dep) && !processedPackages.has(dep)) {\n packagesToCheck.add(dep);\n }\n });\n }\n }\n }\n\n return relevantPackages;\n}\n\n/**\n * The package names recorded in the app's `local-packages.json` — what\n * `linked localize` has linked — read with localize's own reader. Read\n * tolerantly: `linked localize` refuses a malformed file (and warns about a\n * malformed entry) loudly, so here a missing or unusable file is simply\n * \"nothing localized\", and a malformed entry is skipped without a word.\n */\nexport function localizedPackageNames(appRootPath: string): string[] {\n try {\n return Object.keys(readManifest(appRootPath, {warn: () => {}}).entries);\n } catch {\n return [];\n }\n}\n\n/** A package `build-all` found but will not build, and why not. */\nexport interface SkippedPackage {\n packageName: string;\n path: string;\n reason: string;\n}\n\n/** What `build-all` found, and what it decided to do with each package. */\nexport interface BuildAllPlan {\n build: Map<string, PackageDetails>;\n skipped: SkippedPackage[];\n}\n\n/**\n * Decide what `build-all` builds.\n *\n * Every discovered package lands in exactly one of `build` or `skipped`, and\n * `skipped` carries a reason — because the failure mode this replaces was not\n * a narrow scan, it was a SILENT one. `@_linked/maps` is a shipped Create Now\n * dependency that never got `linkedPackage: true`; `build-all` dropped it and\n * printed nothing, so a build covering half the workspace exited 0 and people\n * acted on it. A skip nobody can see is worse than a failure.\n *\n * What counts as buildable is a CAPABILITY, not a declaration: `build-all`\n * invokes each package's own `build` script, so anything with one can be\n * built whether or not it carries the flag. The flag is still reported when\n * it is missing, since the dev resolver and `linked build` do require it.\n */\nexport function planBuildAll(rootPath = './', appRoot?: string): BuildAllPlan {\n const build = new Map<string, PackageDetails>();\n const skipped: SkippedPackage[] = [];\n const buildable: LocalPackage[] = [];\n\n for (const pkg of discoverLocalPackages(rootPath)) {\n const detail = {path: pkg.path, packageName: pkg.packageName};\n // Packages reached through a `../` workspace glob live outside this\n // repository; building them was never in scope for `build-all`.\n if (pkg.path.indexOf('../') !== -1 || pkg.path.indexOf('..\\\\') !== -1) {\n skipped.push({...detail, reason: 'outside this repository'});\n } else if (pkg.isApp) {\n skipped.push({\n ...detail,\n reason: 'is a linked app — build it with `linked build-app`',\n });\n } else if (!pkg.hasBuildScript) {\n skipped.push({...detail, reason: 'has no `build` script'});\n } else {\n buildable.push(pkg);\n build.set(pkg.packageName, detail);\n }\n }\n\n // Narrow to what this app actually depends on, if we are inside one.\n if (appRoot) {\n const appPackageJson = getPackageJSON(appRoot);\n const isAppWithLinkedDeps =\n appPackageJson &&\n !isLinkedPackageJson(appPackageJson) &&\n [\n ...Object.keys(appPackageJson.dependencies || {}),\n ...localizedPackageNames(appRoot),\n ].some((dep) => build.has(dep));\n\n if (isAppWithLinkedDeps) {\n const inTree = filterPackagesByDependencyTree(build, appRoot);\n for (const pkg of buildable) {\n if (inTree.has(pkg.packageName)) continue;\n build.delete(pkg.packageName);\n skipped.push({\n path: pkg.path,\n packageName: pkg.packageName,\n reason: `not in ${appPackageJson.name || 'this app'}'s dependency tree`,\n });\n }\n }\n }\n\n return {build, skipped};\n}\n\n"]}
@@ -0,0 +1,37 @@
1
+ export type CssNamingMode = 'development' | 'production';
2
+ export interface LoaderModeResolution {
3
+ /** The NODE_ENV the CLI will run with, as far as it can be known before it loads. */
4
+ nodeEnv: string | undefined;
5
+ /** Where `nodeEnv` came from — for diagnostics and tests. */
6
+ source: 'shell' | '.env' | '.env-cmdrc.json' | 'vite-default' | 'unset';
7
+ mode: CssNamingMode;
8
+ }
9
+ /**
10
+ * Only `development` gets the dev names. Anything else — `production`,
11
+ * `staging`, unset — serves compiled output, whose stylesheet was written with
12
+ * the production names (see css-module-names.ts).
13
+ */
14
+ export declare const cssNamingModeFor: (nodeEnv: string | undefined) => CssNamingMode;
15
+ /** `--env a,b` → `['a', 'b']`. Shared with `lifecycle.ts`, which applies the same profiles. */
16
+ export declare const readEnvNamesFromArgv: (argv?: string[]) => string[];
17
+ /**
18
+ * The NODE_ENV the CLI is going to run with, read the way
19
+ * `lifecycle.ensureEnvironmentLoaded` will apply it:
20
+ *
21
+ * 1. the shell — it always wins over a file;
22
+ * 2. `.env`, when present — and then `.env-cmdrc.json` is ignored entirely;
23
+ * 3. `.env-cmdrc.json` — `_main`, then the `--env a,b` profiles, or
24
+ * `development` when none are named;
25
+ * 4. otherwise, for `linked start`, `development`: the command serves through
26
+ * a Vite dev server, and Vite sets `NODE_ENV=development` itself when it is
27
+ * unset and writes the client with the dev names;
28
+ * 5. otherwise unset, which names production.
29
+ *
30
+ * Pure apart from reading the two files, so it can be tested without a launch.
31
+ */
32
+ export declare const resolveLoaderMode: ({ env, cwd, argv, }?: {
33
+ env?: NodeJS.ProcessEnv;
34
+ cwd?: string;
35
+ argv?: string[];
36
+ }) => LoaderModeResolution;
37
+ //# sourceMappingURL=loader-mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader-mode.d.ts","sourceRoot":"","sources":["../../src/loader-mode.ts"],"names":[],"mappings":"AAmBA,MAAM,MAAM,aAAa,GAAG,aAAa,GAAG,YAAY,CAAC;AAEzD,MAAM,WAAW,oBAAoB;IACnC,qFAAqF;IACrF,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,6DAA6D;IAC7D,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,iBAAiB,GAAG,cAAc,GAAG,OAAO,CAAC;IACxE,IAAI,EAAE,aAAa,CAAC;CACrB;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,SAAS,MAAM,GAAG,SAAS,KAAG,aACL,CAAC;AAE3D,+FAA+F;AAC/F,eAAO,MAAM,oBAAoB,GAC/B,OAAM,MAAM,EAAiB,KAC5B,MAAM,EAKR,CAAC;AAoBF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,GAAI,sBAI/B;IACD,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACZ,KAAG,oBAsCR,CAAC"}
@@ -0,0 +1,100 @@
1
+ // Which CSS-module naming the Node CSS loader uses, decided before it starts.
2
+ //
3
+ // The loader (`loaders/css-loader.mts`) runs on Node's module-hooks thread,
4
+ // which is created by the first `register()` call in `launch.ts` and gets a
5
+ // COPY of `process.env` as it is at that moment. The CLI only loads the app's
6
+ // `.env` / `.env-cmdrc.json` afterwards (`lifecycle.ensureEnvironmentLoaded`,
7
+ // `commands/start.ts`), so a `NODE_ENV=development` that comes from a file never
8
+ // reaches the loader. It used to read `process.env.NODE_ENV` itself, saw nothing,
9
+ // and named every package stylesheet the production way while the dev client
10
+ // used the dev names: a hydration mismatch on every externalised component.
11
+ //
12
+ // So `launch.ts` resolves the mode here, on the main thread, from the same
13
+ // sources and in the same precedence the CLI applies later, and hands it to the
14
+ // loader through `register(url, {data})`. This module must stay light: it runs
15
+ // before the CLI itself is imported, so it uses node builtins only.
16
+ import fs from 'fs';
17
+ import path from 'path';
18
+ import util from 'util';
19
+ /**
20
+ * Only `development` gets the dev names. Anything else — `production`,
21
+ * `staging`, unset — serves compiled output, whose stylesheet was written with
22
+ * the production names (see css-module-names.ts).
23
+ */
24
+ export const cssNamingModeFor = (nodeEnv) => nodeEnv === 'development' ? 'development' : 'production';
25
+ /** `--env a,b` → `['a', 'b']`. Shared with `lifecycle.ts`, which applies the same profiles. */
26
+ export const readEnvNamesFromArgv = (argv = process.argv) => {
27
+ const args = argv.slice(2);
28
+ const envIndex = args.indexOf('--env');
29
+ if (envIndex === -1)
30
+ return [];
31
+ return (args[envIndex + 1] || '').split(',').filter(Boolean);
32
+ };
33
+ /** The CLI command being run: the first argument that is not an option. */
34
+ const commandFromArgv = (argv) => argv.slice(2).find((arg) => !arg.startsWith('-'));
35
+ const parseDotEnv = (source) => {
36
+ // `util.parseEnv` is the parser `process.loadEnvFile` uses (Node 20.12+/21.7+).
37
+ const parseEnv = util.parseEnv;
38
+ if (typeof parseEnv === 'function')
39
+ return parseEnv(source);
40
+ const vars = {};
41
+ for (const line of source.split(/\r?\n/)) {
42
+ const match = line.match(/^\s*(?:export\s+)?([\w.-]+)\s*=\s*(.*?)\s*$/);
43
+ if (match)
44
+ vars[match[1]] = match[2].replace(/^(['"`])(.*)\1$/, '$2');
45
+ }
46
+ return vars;
47
+ };
48
+ /**
49
+ * The NODE_ENV the CLI is going to run with, read the way
50
+ * `lifecycle.ensureEnvironmentLoaded` will apply it:
51
+ *
52
+ * 1. the shell — it always wins over a file;
53
+ * 2. `.env`, when present — and then `.env-cmdrc.json` is ignored entirely;
54
+ * 3. `.env-cmdrc.json` — `_main`, then the `--env a,b` profiles, or
55
+ * `development` when none are named;
56
+ * 4. otherwise, for `linked start`, `development`: the command serves through
57
+ * a Vite dev server, and Vite sets `NODE_ENV=development` itself when it is
58
+ * unset and writes the client with the dev names;
59
+ * 5. otherwise unset, which names production.
60
+ *
61
+ * Pure apart from reading the two files, so it can be tested without a launch.
62
+ */
63
+ export const resolveLoaderMode = ({ env = process.env, cwd = process.cwd(), argv = process.argv, } = {}) => {
64
+ var _a, _b, _c;
65
+ const resolved = (nodeEnv, source) => ({
66
+ nodeEnv,
67
+ source,
68
+ mode: cssNamingModeFor(nodeEnv),
69
+ });
70
+ if (env.NODE_ENV)
71
+ return resolved(env.NODE_ENV, 'shell');
72
+ const dotEnvPath = path.join(cwd, '.env');
73
+ const envCmdrcPath = path.join(cwd, '.env-cmdrc.json');
74
+ try {
75
+ if (fs.existsSync(dotEnvPath)) {
76
+ const fromFile = parseDotEnv(fs.readFileSync(dotEnvPath, 'utf8')).NODE_ENV;
77
+ if (fromFile)
78
+ return resolved(fromFile, '.env');
79
+ }
80
+ else if (fs.existsSync(envCmdrcPath)) {
81
+ const profiles = (_a = JSON.parse(fs.readFileSync(envCmdrcPath, 'utf8'))) !== null && _a !== void 0 ? _a : {};
82
+ const requested = readEnvNamesFromArgv(argv);
83
+ let fromFile = (_b = profiles._main) === null || _b === void 0 ? void 0 : _b.NODE_ENV;
84
+ for (const name of requested.length ? requested : ['development']) {
85
+ if (((_c = profiles[name]) === null || _c === void 0 ? void 0 : _c.NODE_ENV) !== undefined)
86
+ fromFile = profiles[name].NODE_ENV;
87
+ }
88
+ if (fromFile)
89
+ return resolved(String(fromFile), '.env-cmdrc.json');
90
+ }
91
+ }
92
+ catch (_d) {
93
+ // An unreadable file is reported by the CLI when it loads it; the loader
94
+ // falls through to the default rather than blocking the launch.
95
+ }
96
+ if (commandFromArgv(argv) === 'start')
97
+ return resolved('development', 'vite-default');
98
+ return resolved(undefined, 'unset');
99
+ };
100
+ //# sourceMappingURL=loader-mode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader-mode.js","sourceRoot":"","sources":["../../src/loader-mode.ts"],"names":[],"mappings":"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","sourcesContent":["// Which CSS-module naming the Node CSS loader uses, decided before it starts.\n//\n// The loader (`loaders/css-loader.mts`) runs on Node's module-hooks thread,\n// which is created by the first `register()` call in `launch.ts` and gets a\n// COPY of `process.env` as it is at that moment. The CLI only loads the app's\n// `.env` / `.env-cmdrc.json` afterwards (`lifecycle.ensureEnvironmentLoaded`,\n// `commands/start.ts`), so a `NODE_ENV=development` that comes from a file never\n// reaches the loader. It used to read `process.env.NODE_ENV` itself, saw nothing,\n// and named every package stylesheet the production way while the dev client\n// used the dev names: a hydration mismatch on every externalised component.\n//\n// So `launch.ts` resolves the mode here, on the main thread, from the same\n// sources and in the same precedence the CLI applies later, and hands it to the\n// loader through `register(url, {data})`. This module must stay light: it runs\n// before the CLI itself is imported, so it uses node builtins only.\nimport fs from 'fs';\nimport path from 'path';\nimport util from 'util';\n\nexport type CssNamingMode = 'development' | 'production';\n\nexport interface LoaderModeResolution {\n /** The NODE_ENV the CLI will run with, as far as it can be known before it loads. */\n nodeEnv: string | undefined;\n /** Where `nodeEnv` came from — for diagnostics and tests. */\n source: 'shell' | '.env' | '.env-cmdrc.json' | 'vite-default' | 'unset';\n mode: CssNamingMode;\n}\n\n/**\n * Only `development` gets the dev names. Anything else — `production`,\n * `staging`, unset — serves compiled output, whose stylesheet was written with\n * the production names (see css-module-names.ts).\n */\nexport const cssNamingModeFor = (nodeEnv: string | undefined): CssNamingMode =>\n nodeEnv === 'development' ? 'development' : 'production';\n\n/** `--env a,b` → `['a', 'b']`. Shared with `lifecycle.ts`, which applies the same profiles. */\nexport const readEnvNamesFromArgv = (\n argv: string[] = process.argv,\n): string[] => {\n const args = argv.slice(2);\n const envIndex = args.indexOf('--env');\n if (envIndex === -1) return [];\n return (args[envIndex + 1] || '').split(',').filter(Boolean);\n};\n\n/** The CLI command being run: the first argument that is not an option. */\nconst commandFromArgv = (argv: string[]): string | undefined =>\n argv.slice(2).find((arg) => !arg.startsWith('-'));\n\nconst parseDotEnv = (source: string): Record<string, string> => {\n // `util.parseEnv` is the parser `process.loadEnvFile` uses (Node 20.12+/21.7+).\n const parseEnv = (\n util as {parseEnv?: (content: string) => Record<string, string>}\n ).parseEnv;\n if (typeof parseEnv === 'function') return parseEnv(source);\n const vars: Record<string, string> = {};\n for (const line of source.split(/\\r?\\n/)) {\n const match = line.match(/^\\s*(?:export\\s+)?([\\w.-]+)\\s*=\\s*(.*?)\\s*$/);\n if (match) vars[match[1]] = match[2].replace(/^(['\"`])(.*)\\1$/, '$2');\n }\n return vars;\n};\n\n/**\n * The NODE_ENV the CLI is going to run with, read the way\n * `lifecycle.ensureEnvironmentLoaded` will apply it:\n *\n * 1. the shell — it always wins over a file;\n * 2. `.env`, when present — and then `.env-cmdrc.json` is ignored entirely;\n * 3. `.env-cmdrc.json` — `_main`, then the `--env a,b` profiles, or\n * `development` when none are named;\n * 4. otherwise, for `linked start`, `development`: the command serves through\n * a Vite dev server, and Vite sets `NODE_ENV=development` itself when it is\n * unset and writes the client with the dev names;\n * 5. otherwise unset, which names production.\n *\n * Pure apart from reading the two files, so it can be tested without a launch.\n */\nexport const resolveLoaderMode = ({\n env = process.env,\n cwd = process.cwd(),\n argv = process.argv,\n}: {\n env?: NodeJS.ProcessEnv;\n cwd?: string;\n argv?: string[];\n} = {}): LoaderModeResolution => {\n const resolved = (\n nodeEnv: string | undefined,\n source: LoaderModeResolution['source'],\n ): LoaderModeResolution => ({\n nodeEnv,\n source,\n mode: cssNamingModeFor(nodeEnv),\n });\n\n if (env.NODE_ENV) return resolved(env.NODE_ENV, 'shell');\n\n const dotEnvPath = path.join(cwd, '.env');\n const envCmdrcPath = path.join(cwd, '.env-cmdrc.json');\n try {\n if (fs.existsSync(dotEnvPath)) {\n const fromFile = parseDotEnv(\n fs.readFileSync(dotEnvPath, 'utf8'),\n ).NODE_ENV;\n if (fromFile) return resolved(fromFile, '.env');\n } else if (fs.existsSync(envCmdrcPath)) {\n const profiles = JSON.parse(fs.readFileSync(envCmdrcPath, 'utf8')) ?? {};\n const requested = readEnvNamesFromArgv(argv);\n let fromFile: unknown = profiles._main?.NODE_ENV;\n for (const name of requested.length ? requested : ['development']) {\n if (profiles[name]?.NODE_ENV !== undefined)\n fromFile = profiles[name].NODE_ENV;\n }\n if (fromFile) return resolved(String(fromFile), '.env-cmdrc.json');\n }\n } catch {\n // An unreadable file is reported by the CLI when it loads it; the loader\n // falls through to the default rather than blocking the launch.\n }\n\n if (commandFromArgv(argv) === 'start')\n return resolved('development', 'vite-default');\n return resolved(undefined, 'unset');\n};\n"]}
@@ -1,2 +1,6 @@
1
+ import { type CssNamingMode } from '../loader-mode.js';
2
+ export declare function initialize(data?: {
3
+ mode?: CssNamingMode;
4
+ }): Promise<void>;
1
5
  export declare const resolve: any, load: any;
2
6
  //# sourceMappingURL=css-loader.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"css-loader.d.mts","sourceRoot":"","sources":["../../../src/loaders/css-loader.mts"],"names":[],"mappings":"AAmFA,eAAO,MAAO,OAAO,OAAE,IAAI,KAAiC,CAAC"}
1
+ {"version":3,"file":"css-loader.d.mts","sourceRoot":"","sources":["../../../src/loaders/css-loader.mts"],"names":[],"mappings":"AAIA,OAAO,EAAmB,KAAK,aAAa,EAAC,MAAM,mBAAmB,CAAC;AASvE,wBAAsB,UAAU,CAAC,IAAI,CAAC,EAAE;IAAC,IAAI,CAAC,EAAE,aAAa,CAAA;CAAC,iBAI7D;AAiFD,eAAO,MAAO,OAAO,OAAE,IAAI,KAAiC,CAAC"}
@@ -1,7 +1,30 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
1
10
  import createLoader from 'create-esm-loader';
2
11
  // import parseCSS from 'css-parse';
3
12
  import { generateScopedName } from '../utils.js';
4
13
  import { cssModuleExports, generateScopedNameProduction } from '../css-module-names.js';
14
+ import { cssNamingModeFor } from '../loader-mode.js';
15
+ // Which names to produce. NOT read from `process.env` at transform time: this
16
+ // file runs on the module-hooks thread, whose env is a copy taken when the hooks
17
+ // were registered — before the CLI loads the app's `.env`. `launch.ts` resolves
18
+ // the mode up front and passes it in through `initialize`. The env fallback only
19
+ // serves someone registering this loader by hand without `data`.
20
+ let namingMode = cssNamingModeFor(process.env.NODE_ENV);
21
+ export function initialize(data) {
22
+ return __awaiter(this, void 0, void 0, function* () {
23
+ if ((data === null || data === void 0 ? void 0 : data.mode) === 'development' || (data === null || data === void 0 ? void 0 : data.mode) === 'production') {
24
+ namingMode = data.mode;
25
+ }
26
+ });
27
+ }
5
28
  const cssLoader = {
6
29
  resolve(specifier, opts) {
7
30
  //check if the url is css
@@ -45,7 +68,8 @@ function parseCssToObject(rawSource, filename) {
45
68
  // is written with Vite's. Anything but a development run serves compiled
46
69
  // output (see startServer), so only 'development' gets the dev names — a
47
70
  // `staging` or unset NODE_ENV must still match the production stylesheet.
48
- const output = cssModuleExports(rawSource, filename, process.env.NODE_ENV === 'development' ? generateScopedName : generateScopedNameProduction);
71
+ // `namingMode` carries that decision (see `initialize` above).
72
+ const output = cssModuleExports(rawSource, filename, namingMode === 'development' ? generateScopedName : generateScopedNameProduction);
49
73
  // console.log(myResults);
50
74
  // for (const rule of parseCSS(rawSource).stylesheet.rules) {
51
75
  // if(rule.selectors)
@@ -1 +1 @@
1
- {"version":3,"file":"css-loader.mjs","sourceRoot":"","sources":["../../../src/loaders/css-loader.mts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAC7C,oCAAoC;AACpC,OAAO,EAAC,kBAAkB,EAAC,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAC,gBAAgB,EAAE,4BAA4B,EAAC,MAAM,wBAAwB,CAAC;AAEtF,MAAM,SAAS,GAAG;IAChB,OAAO,CAAC,SAAS,EAAE,IAAI;QACrB,yBAAyB;QACzB,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/B,uDAAuD;YACvD,uEAAuE;YACvE,IAAI,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC9B,yGAAyG;gBACzG,IAAI,EAAC,SAAS,EAAC,GAAG,IAAI,CAAC;gBACvB,IAAI,GAAG,GAAG,IAAI,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC;gBAC7C,OAAO,EAAC,GAAG,EAAC,CAAC;YACf,CAAC;iBAAM,CAAC;gBACN,sDAAsD;YACxD,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,CAAC,GAAG,EAAE,IAAI;QACd,+CAA+C;QAC/C,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACzB,4FAA4F;YAE5F,OAAO,EAAC,MAAM,EAAE,QAAQ,EAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IACD,SAAS,CAAC,MAAM,EAAE,IAAI;QACpB,MAAM,EAAC,GAAG,EAAC,GAAG,IAAI,CAAC;QACnB,+CAA+C;QAC/C,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACzB,+FAA+F;YAC/F,iFAAiF;YACjF,yCAAyC;YACzC,IAAI,gBAAgB,GAAG,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;YAClE,IAAI,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAC5D,OAAO,EAAC,MAAM,EAAE,kBAAkB,WAAW,GAAG,EAAC,CAAC;QACpD,CAAC;IACH,CAAC;CACF,CAAC;AAEF,SAAS,gBAAgB,CAAC,SAAiB,EAAE,QAAQ;IACnD,yEAAyE;IACzE,8EAA8E;IAC9E,yEAAyE;IACzE,yEAAyE;IACzE,0EAA0E;IAC1E,MAAM,MAAM,GAAG,gBAAgB,CAC7B,SAAS,EACT,QAAQ,EACR,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,4BAA4B,CAC3F,CAAC;IACF,0BAA0B;IAC1B,6DAA6D;IAC7D,uBAAuB;IACvB,MAAM;IACN,mHAAmH;IACnH,iEAAiE;IACjE,EAAE;IACF,0BAA0B;IAC1B,8CAA8C;IAC9C,sFAAsF;IACtF,EAAE;IACF,0EAA0E;IAC1E,qBAAqB;IACrB,MAAM;IACN,IAAI;IAEJ,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,cAAc,CAAC,YAAY;IAClC,MAAM,MAAM,GAAG,EAAE,CAAC;IAElB,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;QACvC,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AACD,YAAY;AACZ,MAAM,CAAC,MAAM,EAAC,OAAO,EAAE,IAAI,EAAC,GAAG,MAAM,YAAY,CAAC,SAAS,CAAC,CAAC","sourcesContent":["import createLoader from 'create-esm-loader';\n// import parseCSS from 'css-parse';\nimport {generateScopedName} from '../utils.js';\nimport {cssModuleExports, generateScopedNameProduction} from '../css-module-names.js';\n\nconst cssLoader = {\n resolve(specifier, opts) {\n //check if the url is css\n if (specifier.endsWith('.css')) {\n // console.log(`##LOADER option resolve ${specifier}`);\n //and not a node_module (because we don't need to process node_modules)\n if (specifier.startsWith('.')) {\n // console.log(`##LOADER resolve ${specifier} - ${specifier.startsWith('.') ? 'local' : 'node_module'}`);\n let {parentURL} = opts;\n let url = new URL(specifier, parentURL).href;\n return {url};\n } else {\n // console.log(`##LOADER NOT RESOLVING ${specifier}`);\n }\n }\n },\n format(url, opts) {\n //check if the url is css and not a node_module\n if (url.endsWith('.css')) {\n // console.log(`##LOADER format ${url} - ${url.startsWith('.') ? 'local' : 'node_module'}`);\n\n return {format: 'module'};\n }\n },\n transform(source, opts) {\n const {url} = opts;\n //check if the url is css and not a node_module\n if (url.endsWith('.css')) {\n // console.log(`##LOADER transform ${url} - ${url.startsWith('.') ? 'local' : 'node_module'}`);\n //if yes, convert the CSS source to a JSON object with original selectors as keys\n //and the converted class names as values\n let cssClassesObject = parseCssToObject(String(source), opts.url);\n let finalSource = JSON.stringify(cssClassesObject, null, 2);\n return {source: `export default ${finalSource};`};\n }\n },\n};\n\nfunction parseCssToObject(rawSource: string, filename) {\n // Must produce the names the Vite builds produce for the same file — see\n // css-module-names.ts. The server renders with these; the client's stylesheet\n // is written with Vite's. Anything but a development run serves compiled\n // output (see startServer), so only 'development' gets the dev names — a\n // `staging` or unset NODE_ENV must still match the production stylesheet.\n const output = cssModuleExports(\n rawSource,\n filename,\n process.env.NODE_ENV === 'development' ? generateScopedName : generateScopedNameProduction,\n );\n // console.log(myResults);\n // for (const rule of parseCSS(rawSource).stylesheet.rules) {\n // if(rule.selectors)\n // {\n // let selector = rule['selectors'].at(-1); // Get right-most in the selector rule: `.Bar` in `.Foo > .Bar {…}`\n // if (selector[0] !== '.') break; // only care about classes\n //\n // selector = selector\n // .substring(1) // Skip the initial `.`\n // .match(/(\\w+)/)[1]; // Get only the classname: `Qux` in `.Qux[type=\"number\"]`\n //\n // output[selector] = selector;//getClassStyles(rule['declarations']);\n // // : selector;\n // }\n // }\n\n return output;\n}\n\nfunction getClassStyles(declarations) {\n const styles = {};\n\n for (const declaration of declarations) {\n styles[declaration['property']] = declaration['value'];\n }\n\n return styles;\n}\n//@ts-ignore\nexport const {resolve, load} = await createLoader(cssLoader);\n"]}
1
+ {"version":3,"file":"css-loader.mjs","sourceRoot":"","sources":["../../../src/loaders/css-loader.mts"],"names":[],"mappings":"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","sourcesContent":["import createLoader from 'create-esm-loader';\n// import parseCSS from 'css-parse';\nimport {generateScopedName} from '../utils.js';\nimport {cssModuleExports, generateScopedNameProduction} from '../css-module-names.js';\nimport {cssNamingModeFor, type CssNamingMode} from '../loader-mode.js';\n\n// Which names to produce. NOT read from `process.env` at transform time: this\n// file runs on the module-hooks thread, whose env is a copy taken when the hooks\n// were registered — before the CLI loads the app's `.env`. `launch.ts` resolves\n// the mode up front and passes it in through `initialize`. The env fallback only\n// serves someone registering this loader by hand without `data`.\nlet namingMode: CssNamingMode = cssNamingModeFor(process.env.NODE_ENV);\n\nexport async function initialize(data?: {mode?: CssNamingMode}) {\n if (data?.mode === 'development' || data?.mode === 'production') {\n namingMode = data.mode;\n }\n}\n\nconst cssLoader = {\n resolve(specifier, opts) {\n //check if the url is css\n if (specifier.endsWith('.css')) {\n // console.log(`##LOADER option resolve ${specifier}`);\n //and not a node_module (because we don't need to process node_modules)\n if (specifier.startsWith('.')) {\n // console.log(`##LOADER resolve ${specifier} - ${specifier.startsWith('.') ? 'local' : 'node_module'}`);\n let {parentURL} = opts;\n let url = new URL(specifier, parentURL).href;\n return {url};\n } else {\n // console.log(`##LOADER NOT RESOLVING ${specifier}`);\n }\n }\n },\n format(url, opts) {\n //check if the url is css and not a node_module\n if (url.endsWith('.css')) {\n // console.log(`##LOADER format ${url} - ${url.startsWith('.') ? 'local' : 'node_module'}`);\n\n return {format: 'module'};\n }\n },\n transform(source, opts) {\n const {url} = opts;\n //check if the url is css and not a node_module\n if (url.endsWith('.css')) {\n // console.log(`##LOADER transform ${url} - ${url.startsWith('.') ? 'local' : 'node_module'}`);\n //if yes, convert the CSS source to a JSON object with original selectors as keys\n //and the converted class names as values\n let cssClassesObject = parseCssToObject(String(source), opts.url);\n let finalSource = JSON.stringify(cssClassesObject, null, 2);\n return {source: `export default ${finalSource};`};\n }\n },\n};\n\nfunction parseCssToObject(rawSource: string, filename) {\n // Must produce the names the Vite builds produce for the same file — see\n // css-module-names.ts. The server renders with these; the client's stylesheet\n // is written with Vite's. Anything but a development run serves compiled\n // output (see startServer), so only 'development' gets the dev names — a\n // `staging` or unset NODE_ENV must still match the production stylesheet.\n // `namingMode` carries that decision (see `initialize` above).\n const output = cssModuleExports(\n rawSource,\n filename,\n namingMode === 'development' ? generateScopedName : generateScopedNameProduction,\n );\n // console.log(myResults);\n // for (const rule of parseCSS(rawSource).stylesheet.rules) {\n // if(rule.selectors)\n // {\n // let selector = rule['selectors'].at(-1); // Get right-most in the selector rule: `.Bar` in `.Foo > .Bar {…}`\n // if (selector[0] !== '.') break; // only care about classes\n //\n // selector = selector\n // .substring(1) // Skip the initial `.`\n // .match(/(\\w+)/)[1]; // Get only the classname: `Qux` in `.Qux[type=\"number\"]`\n //\n // output[selector] = selector;//getClassStyles(rule['declarations']);\n // // : selector;\n // }\n // }\n\n return output;\n}\n\nfunction getClassStyles(declarations) {\n const styles = {};\n\n for (const declaration of declarations) {\n styles[declaration['property']] = declaration['value'];\n }\n\n return styles;\n}\n//@ts-ignore\nexport const {resolve, load} = await createLoader(cssLoader);\n"]}
@@ -0,0 +1,14 @@
1
+ import { type LoaderModeResolution } from '../loader-mode.js';
2
+ /**
3
+ * Register the CSS and TS loaders, handing the CSS loader its naming mode.
4
+ *
5
+ * The mode travels as `register()`'s one-shot `data`, not over a MessagePort,
6
+ * on purpose. The hooks thread caches every module it transforms, so a mode that
7
+ * changed after the first stylesheet was loaded would not rename that one — the
8
+ * process would end up with both namings at once, which is the very mismatch
9
+ * this exists to prevent. The mode therefore has to be fixed before any module
10
+ * loads and hold for the life of the process. `resolveLoaderMode` reads it from
11
+ * the same sources, in the same precedence, the CLI applies afterwards.
12
+ */
13
+ export declare function registerLoaders(resolution?: LoaderModeResolution): LoaderModeResolution;
14
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../src/loaders/register.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoB,KAAK,oBAAoB,EAAC,MAAM,mBAAmB,CAAC;AAE/E;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,UAAU,GAAE,oBAA0C,GACrD,oBAAoB,CAMtB"}
@@ -0,0 +1,23 @@
1
+ // Registers the CLI's Node module hooks. Called by `launch.ts` before the CLI is
2
+ // imported, so every TS/CSS file the CLI later loads from an app flows through them.
3
+ import { register } from 'node:module';
4
+ import { resolveLoaderMode } from '../loader-mode.js';
5
+ /**
6
+ * Register the CSS and TS loaders, handing the CSS loader its naming mode.
7
+ *
8
+ * The mode travels as `register()`'s one-shot `data`, not over a MessagePort,
9
+ * on purpose. The hooks thread caches every module it transforms, so a mode that
10
+ * changed after the first stylesheet was loaded would not rename that one — the
11
+ * process would end up with both namings at once, which is the very mismatch
12
+ * this exists to prevent. The mode therefore has to be fixed before any module
13
+ * loads and hold for the life of the process. `resolveLoaderMode` reads it from
14
+ * the same sources, in the same precedence, the CLI applies afterwards.
15
+ */
16
+ export function registerLoaders(resolution = resolveLoaderMode()) {
17
+ register(new URL('./css-loader.mjs', import.meta.url), {
18
+ data: { mode: resolution.mode },
19
+ });
20
+ register(new URL('./ts-loader.mjs', import.meta.url));
21
+ return resolution;
22
+ }
23
+ //# sourceMappingURL=register.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.js","sourceRoot":"","sources":["../../../src/loaders/register.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,qFAAqF;AACrF,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AACrC,OAAO,EAAC,iBAAiB,EAA4B,MAAM,mBAAmB,CAAC;AAE/E;;;;;;;;;;GAUG;AACH,MAAM,UAAU,eAAe,CAC7B,aAAmC,iBAAiB,EAAE;IAEtD,QAAQ,CAAC,IAAI,GAAG,CAAC,kBAAkB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QACrD,IAAI,EAAE,EAAC,IAAI,EAAE,UAAU,CAAC,IAAI,EAAC;KAC9B,CAAC,CAAC;IACH,QAAQ,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACtD,OAAO,UAAU,CAAC;AACpB,CAAC","sourcesContent":["// Registers the CLI's Node module hooks. Called by `launch.ts` before the CLI is\n// imported, so every TS/CSS file the CLI later loads from an app flows through them.\nimport {register} from 'node:module';\nimport {resolveLoaderMode, type LoaderModeResolution} from '../loader-mode.js';\n\n/**\n * Register the CSS and TS loaders, handing the CSS loader its naming mode.\n *\n * The mode travels as `register()`'s one-shot `data`, not over a MessagePort,\n * on purpose. The hooks thread caches every module it transforms, so a mode that\n * changed after the first stylesheet was loaded would not rename that one — the\n * process would end up with both namings at once, which is the very mismatch\n * this exists to prevent. The mode therefore has to be fixed before any module\n * loads and hold for the life of the process. `resolveLoaderMode` reads it from\n * the same sources, in the same precedence, the CLI applies afterwards.\n */\nexport function registerLoaders(\n resolution: LoaderModeResolution = resolveLoaderMode(),\n): LoaderModeResolution {\n register(new URL('./css-loader.mjs', import.meta.url), {\n data: {mode: resolution.mode},\n });\n register(new URL('./ts-loader.mjs', import.meta.url));\n return resolution;\n}\n"]}
@@ -2,7 +2,16 @@ import type { ManifestEntry } from './manifest.js';
2
2
  import type { PruneOptions } from './prune.js';
3
3
  import type { Deps } from './run.js';
4
4
  /**
5
- * `npm install` inside the checkout at `entry.path`, then prune it.
5
+ * `npm install --no-save` inside the checkout at `entry.path`, then prune it.
6
+ *
7
+ * `--no-save` keeps the checkout's tracked files out of it: npm installs what
8
+ * the committed lockfile says and writes neither `package.json` nor
9
+ * `package-lock.json` (only the gitignored hidden lockfile). Without it every
10
+ * relink left a lockfile diff in each checkout it reinstalled, written in the
11
+ * dialect of whichever npm was first on PATH -- measured: Node 22's bundled
12
+ * npm 10.9.9 drops every `"libc"` field an npm 12 lockfile records, and any
13
+ * npm syncs a lockfile header the release workflow bumped. Changing a
14
+ * checkout's dependencies is a deliberate `npm install <dep>` inside it.
6
15
  *
7
16
  * The package's name is read from the checkout's own `package.json`; the
8
17
  * other localized packages (siblings) from the manifest, so a checkout being
@@ -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;;;;;;;;;GASG;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,CA0BR;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"}
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;;;;;;;;;;;;;;;;;;GAkBG;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"}
@@ -33,7 +33,16 @@ import { newPruneCache, planPrune, pruneProvided, prunesEntry, shouldPrune, } fr
33
33
  import { defaultDeps } from './run.js';
34
34
  import { reportError } from './localize.js';
35
35
  /**
36
- * `npm install` inside the checkout at `entry.path`, then prune it.
36
+ * `npm install --no-save` inside the checkout at `entry.path`, then prune it.
37
+ *
38
+ * `--no-save` keeps the checkout's tracked files out of it: npm installs what
39
+ * the committed lockfile says and writes neither `package.json` nor
40
+ * `package-lock.json` (only the gitignored hidden lockfile). Without it every
41
+ * relink left a lockfile diff in each checkout it reinstalled, written in the
42
+ * dialect of whichever npm was first on PATH -- measured: Node 22's bundled
43
+ * npm 10.9.9 drops every `"libc"` field an npm 12 lockfile records, and any
44
+ * npm syncs a lockfile header the release workflow bumped. Changing a
45
+ * checkout's dependencies is a deliberate `npm install <dep>` inside it.
37
46
  *
38
47
  * The package's name is read from the checkout's own `package.json`; the
39
48
  * other localized packages (siblings) from the manifest, so a checkout being
@@ -46,9 +55,7 @@ export function ensure(entry, deps, opts = {}) {
46
55
  var _a;
47
56
  const pkgDir = path.join(deps.appRoot, entry.path);
48
57
  deps.log(`[localize] npm install in ${entry.path}`);
49
- const install = deps.run('npm', ['install', '--no-audit', '--no-fund'], {
50
- cwd: pkgDir,
51
- });
58
+ const install = deps.run('npm', ['install', '--no-save', '--no-audit', '--no-fund'], { cwd: pkgDir });
52
59
  if (install.status !== 0) {
53
60
  throw new LocalizeError(`npm install failed in ${entry.path}:\n${(install.stderr || install.stdout).trim()}`, EXIT_INSTALL_FAILED);
54
61
  }
@@ -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` inside the checkout at `entry.path`, then prune 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('npm', ['install', '--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 * 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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@_linked/cli",
3
- "version": "1.45.0",
3
+ "version": "1.45.2",
4
4
  "packageManager": "npm@11.21.0",
5
5
  "description": "Command line tools for the @_linked/* packages and apps",
6
6
  "main": "lib/esm/index.js",