@_linked/cli 1.41.1 → 1.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +21 -54
  3. package/lib/esm/cli-methods.js +2 -2
  4. package/lib/esm/cli-methods.js.map +1 -1
  5. package/lib/esm/cli.js +13 -1
  6. package/lib/esm/cli.js.map +1 -1
  7. package/lib/esm/commands/localize.d.ts +6 -15
  8. package/lib/esm/commands/localize.d.ts.map +1 -1
  9. package/lib/esm/commands/localize.js +26 -35
  10. package/lib/esm/commands/localize.js.map +1 -1
  11. package/lib/esm/installed-packages.d.ts +12 -12
  12. package/lib/esm/installed-packages.d.ts.map +1 -1
  13. package/lib/esm/installed-packages.js +37 -27
  14. package/lib/esm/installed-packages.js.map +1 -1
  15. package/lib/esm/lifecycle.d.ts +4 -3
  16. package/lib/esm/lifecycle.d.ts.map +1 -1
  17. package/lib/esm/lifecycle.js +6 -14
  18. package/lib/esm/lifecycle.js.map +1 -1
  19. package/lib/esm/localize/adopt.d.ts +10 -0
  20. package/lib/esm/localize/adopt.d.ts.map +1 -0
  21. package/lib/esm/localize/adopt.js +76 -0
  22. package/lib/esm/localize/adopt.js.map +1 -0
  23. package/lib/esm/localize/delocalize.d.ts +6 -0
  24. package/lib/esm/localize/delocalize.d.ts.map +1 -0
  25. package/lib/esm/localize/delocalize.js +138 -0
  26. package/lib/esm/localize/delocalize.js.map +1 -0
  27. package/lib/esm/localize/ensure.d.ts +26 -0
  28. package/lib/esm/localize/ensure.d.ts.map +1 -0
  29. package/lib/esm/localize/ensure.js +152 -0
  30. package/lib/esm/localize/ensure.js.map +1 -0
  31. package/lib/esm/localize/errors.d.ts +23 -0
  32. package/lib/esm/localize/errors.d.ts.map +1 -0
  33. package/lib/esm/localize/errors.js +26 -0
  34. package/lib/esm/localize/errors.js.map +1 -0
  35. package/lib/esm/localize/fsops.d.ts +36 -0
  36. package/lib/esm/localize/fsops.d.ts.map +1 -0
  37. package/lib/esm/localize/fsops.js +155 -0
  38. package/lib/esm/localize/fsops.js.map +1 -0
  39. package/lib/esm/localize/index.d.ts +29 -0
  40. package/lib/esm/localize/index.d.ts.map +1 -0
  41. package/lib/esm/localize/index.js +22 -0
  42. package/lib/esm/localize/index.js.map +1 -0
  43. package/lib/esm/localize/list.d.ts +18 -0
  44. package/lib/esm/localize/list.d.ts.map +1 -0
  45. package/lib/esm/localize/list.js +174 -0
  46. package/lib/esm/localize/list.js.map +1 -0
  47. package/lib/esm/localize/localize.d.ts +84 -0
  48. package/lib/esm/localize/localize.d.ts.map +1 -0
  49. package/lib/esm/localize/localize.js +354 -0
  50. package/lib/esm/localize/localize.js.map +1 -0
  51. package/lib/esm/localize/manifest.d.ts +54 -0
  52. package/lib/esm/localize/manifest.d.ts.map +1 -0
  53. package/lib/esm/localize/manifest.js +133 -0
  54. package/lib/esm/localize/manifest.js.map +1 -0
  55. package/lib/esm/localize/provided.d.ts +28 -0
  56. package/lib/esm/localize/provided.d.ts.map +1 -0
  57. package/lib/esm/localize/provided.js +89 -0
  58. package/lib/esm/localize/provided.js.map +1 -0
  59. package/lib/esm/localize/prune.d.ts +58 -0
  60. package/lib/esm/localize/prune.d.ts.map +1 -0
  61. package/lib/esm/localize/prune.js +390 -0
  62. package/lib/esm/localize/prune.js.map +1 -0
  63. package/lib/esm/localize/relink.d.ts +11 -0
  64. package/lib/esm/localize/relink.d.ts.map +1 -0
  65. package/lib/esm/localize/relink.js +174 -0
  66. package/lib/esm/localize/relink.js.map +1 -0
  67. package/lib/esm/localize/resolve.d.ts +47 -0
  68. package/lib/esm/localize/resolve.d.ts.map +1 -0
  69. package/lib/esm/localize/resolve.js +153 -0
  70. package/lib/esm/localize/resolve.js.map +1 -0
  71. package/lib/esm/localize/run.d.ts +35 -0
  72. package/lib/esm/localize/run.d.ts.map +1 -0
  73. package/lib/esm/localize/run.js +30 -0
  74. package/lib/esm/localize/run.js.map +1 -0
  75. package/lib/esm/localized-dedupe.d.ts +6 -0
  76. package/lib/esm/localized-dedupe.d.ts.map +1 -1
  77. package/lib/esm/localized-dedupe.js +23 -66
  78. package/lib/esm/localized-dedupe.js.map +1 -1
  79. package/package.json +1 -2
@@ -1 +1 @@
1
- {"version":3,"file":"installed-packages.js","sourceRoot":"","sources":["../../src/installed-packages.ts"],"names":[],"mappings":"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","sourcesContent":["// Locating installed packages the way Node does, shared by the Vite config\n// helper and `linked app-doctor`.\nimport fsExtra from 'fs-extra';\nimport path from 'node:path';\n\n/**\n * Framework packages that MUST be single-instance per runtime — they hold\n * module-level state (`@_linked/core`'s shape registry, `LinkedStorage`, the query\n * context) or register shapes into it. Two copies in one runtime split that state\n * and mangle shape identity (`Person`→`Person2`).\n *\n * A NAME check, used only by `client-dep-includes` (alongside the flag). Deciding\n * whether an installed package is linked goes by its `package.json` instead —\n * {@link isLinkedPackageJson} — which is what the source walk, the standalone\n * `optimizeDeps.exclude` and `linked localize` use.\n */\nexport const FRAMEWORK_PKG_PATTERNS: RegExp[] = [/^@_linked\\//, /^lincd-/];\nexport const isFrameworkPkg = (name: string): boolean =>\n FRAMEWORK_PKG_PATTERNS.some((re) => re.test(name));\n\n// Resolve a dependency name to its installed package.json the way Node does:\n// look in `<dir>/node_modules/<name>`, then each parent directory's\n// node_modules, starting from the requiring package's directory. This finds\n// deps that npm/yarn workspaces HOISTED to the monorepo root (an app under\n// `services/api` whose dep lives in `<root>/node_modules`). The walk stops\n// after the nearest directory whose package.json declares `workspaces` (the\n// workspace root), or at the filesystem root. Returns null when the package\n// isn't installed (e.g. an optional dep) — we skip rather than throw.\nexport async function isWorkspaceRoot(dir: string): Promise<boolean> {\n try {\n const json = await fsExtra.readJson(path.join(dir, 'package.json'));\n return !!json.workspaces;\n } catch {\n return false;\n }\n}\n\nexport async function readInstalledPkg(\n name: string,\n fromDir: string,\n): Promise<{root: string; json: any} | null> {\n let dir = path.resolve(fromDir);\n while (true) {\n const root = path.join(dir, 'node_modules', name);\n const pkgJson = path.join(root, 'package.json');\n if (await fsExtra.pathExists(pkgJson)) {\n try {\n return {root, json: await fsExtra.readJson(pkgJson)};\n } catch {\n return null;\n }\n }\n const parent = path.dirname(dir);\n if (parent === dir || (await isWorkspaceRoot(dir))) return null;\n dir = parent;\n }\n}\n\n/**\n * THE definition of a linked package: its own `package.json` says\n * `\"linkedPackage\": true`. Not its npm scope — a linked package can be\n * published under any scope, and not everything under `@_linked/` is one\n * (`@_linked/localize` is a plain tool). The pre-rename `\"lincd\": true` is not\n * read: the packages that still carry it are the old `lincd-*` framework,\n * which cannot share a runtime with `@_linked/core`. `lifecycle.ts`\n * (`build-all`, `getLincdPackages`) and `linked build-package` use this too.\n */\nexport const isLinkedPackageJson = (json: any): boolean =>\n json?.linkedPackage === true;\n\n/** An installed linked package, as {@link discoverInstalledLinkedPackages} finds it. */\nexport interface InstalledLinkedPackage {\n name: string;\n /** The installed directory, realpathed: a localized checkout's own path. */\n realRoot: string;\n json: any;\n}\n\n/**\n * Every installed linked package an app depends on: its `dependencies` and\n * `devDependencies`, and recursively the `dependencies` of each linked package\n * found, keeping those {@link isLinkedPackageJson} says are linked.\n *\n * Walked breadth-first and keyed on the installed directory, not the name, so\n * the app's own copy of a package is settled before any copy a dependency\n * installed for itself. A localized checkout's own `node_modules` holds a\n * published copy of any sibling it depends on; keyed on the name and walked\n * depth-first, reaching that copy first hid the app's localized checkout of\n * it. The same name can therefore appear more than once, once per copy.\n */\nexport async function discoverInstalledLinkedPackages(\n cwd: string = process.cwd(),\n): Promise<InstalledLinkedPackage[]> {\n const pkgPath = path.join(cwd, 'package.json');\n if (!(await fsExtra.pathExists(pkgPath))) return [];\n const appPkg = await fsExtra.readJson(pkgPath);\n const out: InstalledLinkedPackage[] = [];\n const visited = new Set<string>();\n let level: {deps: Record<string, string> | undefined; fromDir: string}[] = [\n {deps: appPkg.dependencies, fromDir: cwd},\n {deps: appPkg.devDependencies, fromDir: cwd},\n ];\n while (level.length > 0) {\n const next: typeof level = [];\n for (const {deps, fromDir} of level) {\n for (const name of Object.keys(deps ?? {})) {\n const resolved = await readInstalledPkg(name, fromDir);\n if (!resolved || !isLinkedPackageJson(resolved.json)) continue;\n let realRoot = resolved.root;\n try {\n realRoot = await fsExtra.realpath(resolved.root);\n } catch {}\n if (visited.has(realRoot)) continue;\n visited.add(realRoot);\n out.push({name, realRoot, json: resolved.json});\n // Recurse from the real location, so a symlinked clone resolves its own\n // dependencies from its source dir.\n next.push({deps: resolved.json.dependencies, fromDir: realRoot});\n }\n }\n level = next;\n }\n return out;\n}\n\n/**\n * The names of the linked packages an app itself provides: those\n * {@link discoverInstalledLinkedPackages} finds that resolve from the app root\n * (not only from inside some dependency's own `node_modules`), plus `react` and\n * `react-dom` when they do. These are what must load once per runtime: what\n * `linked localize` tells localize the app provides, so a checkout's own copy of\n * one is removed.\n */\nexport async function appProvidedPackages(\n cwd: string = process.cwd(),\n): Promise<string[]> {\n const names = new Set<string>();\n for (const pkg of await discoverInstalledLinkedPackages(cwd)) {\n if (names.has(pkg.name)) continue;\n if (await readInstalledPkg(pkg.name, cwd)) names.add(pkg.name);\n }\n for (const name of ['react', 'react-dom']) {\n if (await readInstalledPkg(name, cwd)) names.add(name);\n }\n return [...names].sort();\n}\n"]}
1
+ {"version":3,"file":"installed-packages.js","sourceRoot":"","sources":["../../src/installed-packages.ts"],"names":[],"mappings":"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","sourcesContent":["// Locating installed packages the way Node does, shared by the Vite config\n// helper and `linked app-doctor`.\nimport fsExtra from 'fs-extra';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\n/**\n * Framework packages that MUST be single-instance per runtime — they hold\n * module-level state (`@_linked/core`'s shape registry, `LinkedStorage`, the query\n * context) or register shapes into it. Two copies in one runtime split that state\n * and mangle shape identity (`Person`→`Person2`).\n *\n * A NAME check, used only by `client-dep-includes` (alongside the flag). Deciding\n * whether an installed package is linked goes by its `package.json` instead —\n * {@link isLinkedPackageJson} — which is what the source walk and the standalone\n * `optimizeDeps.exclude` use.\n */\nexport const FRAMEWORK_PKG_PATTERNS: RegExp[] = [/^@_linked\\//, /^lincd-/];\nexport const isFrameworkPkg = (name: string): boolean =>\n FRAMEWORK_PKG_PATTERNS.some((re) => re.test(name));\n\n// Resolve a dependency name to its installed package.json the way Node does:\n// look in `<dir>/node_modules/<name>`, then each parent directory's\n// node_modules, starting from the requiring package's directory. This finds\n// deps that npm/yarn workspaces HOISTED to the monorepo root (an app under\n// `services/api` whose dep lives in `<root>/node_modules`). The walk stops\n// after the nearest directory whose package.json declares `workspaces` (the\n// workspace root), or at the filesystem root. Returns null when the package\n// isn't installed (e.g. an optional dep) — we skip rather than throw.\nexport async function isWorkspaceRoot(dir: string): Promise<boolean> {\n try {\n const json = await fsExtra.readJson(path.join(dir, 'package.json'));\n return !!json.workspaces;\n } catch {\n return false;\n }\n}\n\nexport async function readInstalledPkg(\n name: string,\n fromDir: string,\n): Promise<{root: string; json: any} | null> {\n let dir = path.resolve(fromDir);\n while (true) {\n const root = path.join(dir, 'node_modules', name);\n const pkgJson = path.join(root, 'package.json');\n if (await fsExtra.pathExists(pkgJson)) {\n try {\n return {root, json: await fsExtra.readJson(pkgJson)};\n } catch {\n return null;\n }\n }\n const parent = path.dirname(dir);\n if (parent === dir || (await isWorkspaceRoot(dir))) return null;\n dir = parent;\n }\n}\n\n/**\n * {@link readInstalledPkg}, synchronously, for callers on a hot path that must\n * not go async (the one-copy check before every `linked start`). Same walk,\n * same stop at the workspace root.\n */\nexport function readInstalledPkgSync(\n name: string,\n fromDir: string,\n): {root: string; json: any} | null {\n let dir = path.resolve(fromDir);\n while (true) {\n const root = path.join(dir, 'node_modules', name);\n const pkgJson = path.join(root, 'package.json');\n if (fs.existsSync(pkgJson)) {\n try {\n return {root, json: JSON.parse(fs.readFileSync(pkgJson, 'utf8'))};\n } catch {\n return null;\n }\n }\n const parent = path.dirname(dir);\n if (parent === dir || isWorkspaceRootSync(dir)) return null;\n dir = parent;\n }\n}\n\nfunction isWorkspaceRootSync(dir: string): boolean {\n try {\n return !!JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf8'))\n .workspaces;\n } catch {\n return false;\n }\n}\n\n/**\n * THE definition of a linked package: its own `package.json` says\n * `\"linkedPackage\": true`. Not its npm scope — a linked package can be\n * published under any scope, and not everything under `@_linked/` is one\n * (a plain tool need not be). The pre-rename `\"lincd\": true` is not\n * read: the packages that still carry it are the old `lincd-*` framework,\n * which cannot share a runtime with `@_linked/core`. `lifecycle.ts`\n * (`build-all`, `getLincdPackages`) and `linked build-package` use this too.\n */\nexport const isLinkedPackageJson = (json: any): boolean =>\n json?.linkedPackage === true;\n\n/** An installed linked package, as {@link discoverInstalledLinkedPackages} finds it. */\nexport interface InstalledLinkedPackage {\n name: string;\n /** The installed directory, realpathed: a localized checkout's own path. */\n realRoot: string;\n json: any;\n}\n\n/**\n * Every installed linked package an app depends on: its `dependencies` and\n * `devDependencies`, and recursively the `dependencies` of each linked package\n * found, keeping those {@link isLinkedPackageJson} says are linked.\n *\n * Walked breadth-first and keyed on the installed directory, not the name, so\n * the app's own copy of a package is settled before any copy a dependency\n * installed for itself. A localized checkout's own `node_modules` holds a\n * published copy of any sibling it depends on; keyed on the name and walked\n * depth-first, reaching that copy first hid the app's localized checkout of\n * it. The same name can therefore appear more than once, once per copy.\n */\nexport async function discoverInstalledLinkedPackages(\n cwd: string = process.cwd(),\n): Promise<InstalledLinkedPackage[]> {\n const pkgPath = path.join(cwd, 'package.json');\n if (!(await fsExtra.pathExists(pkgPath))) return [];\n const appPkg = await fsExtra.readJson(pkgPath);\n const out: InstalledLinkedPackage[] = [];\n const visited = new Set<string>();\n let level: {deps: Record<string, string> | undefined; fromDir: string}[] = [\n {deps: appPkg.dependencies, fromDir: cwd},\n {deps: appPkg.devDependencies, fromDir: cwd},\n ];\n while (level.length > 0) {\n const next: typeof level = [];\n for (const {deps, fromDir} of level) {\n for (const name of Object.keys(deps ?? {})) {\n const resolved = await readInstalledPkg(name, fromDir);\n if (!resolved || !isLinkedPackageJson(resolved.json)) continue;\n let realRoot = resolved.root;\n try {\n realRoot = await fsExtra.realpath(resolved.root);\n } catch {}\n if (visited.has(realRoot)) continue;\n visited.add(realRoot);\n out.push({name, realRoot, json: resolved.json});\n // Recurse from the real location, so a symlinked clone resolves its own\n // dependencies from its source dir.\n next.push({deps: resolved.json.dependencies, fromDir: realRoot});\n }\n }\n level = next;\n }\n return out;\n}\n"]}
@@ -105,9 +105,10 @@ export declare function discoverLocalPackages(rootPath?: string, options?: {
105
105
  }): LocalPackage[];
106
106
  /**
107
107
  * The package names recorded in the app's `local-packages.json` — what
108
- * `linked localize` has linked. Read tolerantly: localize owns that file and
109
- * refuses a malformed one loudly, so here a missing or unreadable file is
110
- * simply "nothing localized".
108
+ * `linked localize` has linked — read with localize's own reader. Read
109
+ * tolerantly: `linked localize` refuses a malformed file (and warns about a
110
+ * malformed entry) loudly, so here a missing or unusable file is simply
111
+ * "nothing localized", and a malformed entry is skipped without a word.
111
112
  */
112
113
  export declare function localizedPackageNames(appRootPath: string): string[];
113
114
  /** A package `build-all` found but will not build, and why not. */
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../src/lifecycle.ts"],"names":[],"mappings":"AAcA,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;AAuJD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAYnE;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":"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"}
@@ -19,6 +19,7 @@ import path from 'path';
19
19
  import chalk from 'chalk';
20
20
  import { getPackageJSON } from './utils.js';
21
21
  import { isLinkedPackageJson } from './installed-packages.js';
22
+ import { readManifest } from './localize/manifest.js';
22
23
  import { parseWorkspacePatterns, isWorkspacePathNegated } from './workspace-globs.js';
23
24
  /**
24
25
  * Load the app's environment into `process.env`, then re-apply the original
@@ -359,25 +360,16 @@ function filterPackagesByDependencyTree(allPackages, appRootPath) {
359
360
  }
360
361
  return relevantPackages;
361
362
  }
362
- /**
363
- * localize's manifest filename (`MANIFEST_FILENAME` in `@_linked/localize`).
364
- * Repeated rather than imported: that package is ESM-only and loaded lazily,
365
- * and this runs synchronously while planning a build.
366
- */
367
- const LOCALIZE_MANIFEST = 'local-packages.json';
368
363
  /**
369
364
  * The package names recorded in the app's `local-packages.json` — what
370
- * `linked localize` has linked. Read tolerantly: localize owns that file and
371
- * refuses a malformed one loudly, so here a missing or unreadable file is
372
- * simply "nothing localized".
365
+ * `linked localize` has linked — read with localize's own reader. Read
366
+ * tolerantly: `linked localize` refuses a malformed file (and warns about a
367
+ * malformed entry) loudly, so here a missing or unusable file is simply
368
+ * "nothing localized", and a malformed entry is skipped without a word.
373
369
  */
374
370
  export function localizedPackageNames(appRootPath) {
375
371
  try {
376
- const manifest = JSON.parse(fs.readFileSync(path.join(appRootPath, LOCALIZE_MANIFEST), 'utf8'));
377
- const packages = manifest === null || manifest === void 0 ? void 0 : manifest.packages;
378
- return packages && typeof packages === 'object' && !Array.isArray(packages)
379
- ? Object.keys(packages)
380
- : [];
372
+ return Object.keys(readManifest(appRootPath, { warn: () => { } }).entries);
381
373
  }
382
374
  catch (_a) {
383
375
  return [];
@@ -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 {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 * localize's manifest filename (`MANIFEST_FILENAME` in `@_linked/localize`).\n * Repeated rather than imported: that package is ESM-only and loaded lazily,\n * and this runs synchronously while planning a build.\n */\nconst LOCALIZE_MANIFEST = 'local-packages.json';\n\n/**\n * The package names recorded in the app's `local-packages.json` — what\n * `linked localize` has linked. Read tolerantly: localize owns that file and\n * refuses a malformed one loudly, so here a missing or unreadable file is\n * simply \"nothing localized\".\n */\nexport function localizedPackageNames(appRootPath: string): string[] {\n try {\n const manifest = JSON.parse(\n fs.readFileSync(path.join(appRootPath, LOCALIZE_MANIFEST), 'utf8'),\n );\n const packages = manifest?.packages;\n return packages && typeof packages === 'object' && !Array.isArray(packages)\n ? Object.keys(packages)\n : [];\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';\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"]}
@@ -0,0 +1,10 @@
1
+ import type { LocalizeOptions } from './localize.js';
2
+ import type { Deps } from './run.js';
3
+ /**
4
+ * @param {string[]} names full npm package names
5
+ * @param {object} opts `{dir, repo, build, force}`
6
+ * @param {object} deps `{appRoot, run, log, warn, error}`
7
+ * @returns {number} the process exit code, as `localize` returns it.
8
+ */
9
+ export declare function adopt(names: string[], opts: Omit<LocalizeOptions, 'subdir'>, deps: Deps): number;
10
+ //# sourceMappingURL=adopt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adopt.d.ts","sourceRoot":"","sources":["../../../src/localize/adopt.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAC,eAAe,EAAY,MAAM,eAAe,CAAC;AAG9D,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,UAAU,CAAC;AAGnC;;;;;GAKG;AACH,wBAAgB,KAAK,CACnB,KAAK,EAAE,MAAM,EAAE,EACf,IAAI,EAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,CAAC,EACrC,IAAI,EAAE,IAAI,GACT,MAAM,CAWR"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * `adopt` -- localize a checkout that is ALREADY in the checkout directory,
3
+ * without asking the registry or a remote anything.
4
+ *
5
+ * `localize` gets its checkout by resolving the published `repository` and
6
+ * cloning it. That cannot work for two kinds of checkout that nonetheless
7
+ * belong in `<dir>`:
8
+ *
9
+ * - a package created locally and never published, which may not even have a
10
+ * remote yet;
11
+ * - a clone that was put there by hand.
12
+ *
13
+ * `adopt` takes the checkout as it finds it -- no clone, no pull, no fetch --
14
+ * and runs the same tail as `localize`: install inside it, build, symlink,
15
+ * record. The checkout has to be a git checkout at `<dir>/<checkoutName>`, so
16
+ * that `localize` and `adopt` can never disagree about where a package lives.
17
+ *
18
+ * The recorded `repo` is `--repo` when given, else the checkout's `origin`,
19
+ * else what an earlier run recorded, else absent. Absent is fine: `relink`,
20
+ * `--list` and `remove` never need it.
21
+ */
22
+ import fs from 'node:fs';
23
+ import path from 'node:path';
24
+ import { EXIT_REFUSED, LocalizeError } from './errors.js';
25
+ import { forEachName, guardForeignLink, installLinkAndRecord, reportError, } from './localize.js';
26
+ import { checkoutNameFor, normalizeGitUrl } from './resolve.js';
27
+ import { isGitCheckout, readJson } from './fsops.js';
28
+ /**
29
+ * @param {string[]} names full npm package names
30
+ * @param {object} opts `{dir, repo, build, force}`
31
+ * @param {object} deps `{appRoot, run, log, warn, error}`
32
+ * @returns {number} the process exit code, as `localize` returns it.
33
+ */
34
+ export function adopt(names, opts, deps) {
35
+ if (opts.repo && names.length > 1) {
36
+ return reportError(new LocalizeError(`--repo names one repository, so it can only be used when adopting one package.`, EXIT_REFUSED), deps);
37
+ }
38
+ return forEachName(names, opts, deps, adoptOne);
39
+ }
40
+ function adoptOne(name, dir, recorded, opts, deps) {
41
+ var _a, _b;
42
+ const relPkg = path.join(dir, checkoutNameFor(name));
43
+ const pkgDir = path.join(deps.appRoot, relPkg);
44
+ if (!fs.existsSync(pkgDir)) {
45
+ throw new LocalizeError(`there is nothing to adopt at ${relPkg}.\n` +
46
+ `adopt links a checkout that is already there. To clone a published package instead:\n` +
47
+ ` linked localize ${name}`, EXIT_REFUSED);
48
+ }
49
+ if (!isGitCheckout(pkgDir)) {
50
+ throw new LocalizeError(`${relPkg} is not a git checkout. Run \`git init\` in it first -- localize tracks a ` +
51
+ `checkout's branch, and a checkout without history has none.`, EXIT_REFUSED);
52
+ }
53
+ const declared = (_a = readJson(path.join(pkgDir, 'package.json'))) === null || _a === void 0 ? void 0 : _a.name;
54
+ if (declared !== name) {
55
+ throw new LocalizeError(declared
56
+ ? `${relPkg} declares itself as "${declared}", not "${name}".`
57
+ : `${relPkg} has no package.json naming it, so it is not the package "${name}".`, EXIT_REFUSED);
58
+ }
59
+ if (recorded === null || recorded === void 0 ? void 0 : recorded.subdir) {
60
+ deps.warn(`[localize] ${name} was recorded inside a monorepo (${recorded.path}); adopt replaces that ` +
61
+ `with ${relPkg}.`);
62
+ }
63
+ guardForeignLink(name, dir, opts, deps);
64
+ const repo = opts.repo
65
+ ? normalizeGitUrl(opts.repo)
66
+ : ((_b = originOf(pkgDir, deps)) !== null && _b !== void 0 ? _b : recorded === null || recorded === void 0 ? void 0 : recorded.repo);
67
+ deps.log(`[localize] adopting ${relPkg}${repo ? ` (${repo})` : ' (no remote)'}`);
68
+ return installLinkAndRecord({ npmName: name, clone: pkgDir, relPkg, pkgDir, repo }, opts, deps);
69
+ }
70
+ /** The checkout's `origin` URL, or undefined when it has none. Read, never fetched. */
71
+ function originOf(pkgDir, deps) {
72
+ const r = deps.run('git', ['remote', 'get-url', 'origin'], { cwd: pkgDir });
73
+ const url = r.stdout.trim();
74
+ return r.status === 0 && url ? normalizeGitUrl(url) : undefined;
75
+ }
76
+ //# sourceMappingURL=adopt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adopt.js","sourceRoot":"","sources":["../../../src/localize/adopt.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `adopt` -- localize a checkout that is ALREADY in the checkout directory,\n * without asking the registry or a remote anything.\n *\n * `localize` gets its checkout by resolving the published `repository` and\n * cloning it. That cannot work for two kinds of checkout that nonetheless\n * belong in `<dir>`:\n *\n * - a package created locally and never published, which may not even have a\n * remote yet;\n * - a clone that was put there by hand.\n *\n * `adopt` takes the checkout as it finds it -- no clone, no pull, no fetch --\n * and runs the same tail as `localize`: install inside it, build, symlink,\n * record. The checkout has to be a git checkout at `<dir>/<checkoutName>`, so\n * that `localize` and `adopt` can never disagree about where a package lives.\n *\n * The recorded `repo` is `--repo` when given, else the checkout's `origin`,\n * else what an earlier run recorded, else absent. Absent is fine: `relink`,\n * `--list` and `remove` never need it.\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport {EXIT_REFUSED, LocalizeError} from './errors.js';\nimport {\n forEachName,\n guardForeignLink,\n installLinkAndRecord,\n reportError,\n} from './localize.js';\nimport type {LocalizeOptions, OneResult} from './localize.js';\nimport type {ManifestEntry} from './manifest.js';\nimport {checkoutNameFor, normalizeGitUrl} from './resolve.js';\nimport type {Deps} from './run.js';\nimport {isGitCheckout, readJson} from './fsops.js';\n\n/**\n * @param {string[]} names full npm package names\n * @param {object} opts `{dir, repo, build, force}`\n * @param {object} deps `{appRoot, run, log, warn, error}`\n * @returns {number} the process exit code, as `localize` returns it.\n */\nexport function adopt(\n names: string[],\n opts: Omit<LocalizeOptions, 'subdir'>,\n deps: Deps,\n): number {\n if (opts.repo && names.length > 1) {\n return reportError(\n new LocalizeError(\n `--repo names one repository, so it can only be used when adopting one package.`,\n EXIT_REFUSED,\n ),\n deps,\n );\n }\n return forEachName(names, opts, deps, adoptOne);\n}\n\nfunction adoptOne(\n name: string,\n dir: string,\n recorded: ManifestEntry | undefined,\n opts: LocalizeOptions,\n deps: Deps,\n): OneResult {\n const relPkg = path.join(dir, checkoutNameFor(name));\n const pkgDir = path.join(deps.appRoot, relPkg);\n\n if (!fs.existsSync(pkgDir)) {\n throw new LocalizeError(\n `there is nothing to adopt at ${relPkg}.\\n` +\n `adopt links a checkout that is already there. To clone a published package instead:\\n` +\n ` linked localize ${name}`,\n EXIT_REFUSED,\n );\n }\n if (!isGitCheckout(pkgDir)) {\n throw new LocalizeError(\n `${relPkg} is not a git checkout. Run \\`git init\\` in it first -- localize tracks a ` +\n `checkout's branch, and a checkout without history has none.`,\n EXIT_REFUSED,\n );\n }\n\n const declared = readJson(path.join(pkgDir, 'package.json'))?.name;\n if (declared !== name) {\n throw new LocalizeError(\n declared\n ? `${relPkg} declares itself as \"${declared}\", not \"${name}\".`\n : `${relPkg} has no package.json naming it, so it is not the package \"${name}\".`,\n EXIT_REFUSED,\n );\n }\n\n if (recorded?.subdir) {\n deps.warn(\n `[localize] ${name} was recorded inside a monorepo (${recorded.path}); adopt replaces that ` +\n `with ${relPkg}.`,\n );\n }\n\n guardForeignLink(name, dir, opts, deps);\n\n const repo = opts.repo\n ? normalizeGitUrl(opts.repo)\n : (originOf(pkgDir, deps) ?? recorded?.repo);\n deps.log(\n `[localize] adopting ${relPkg}${repo ? ` (${repo})` : ' (no remote)'}`,\n );\n\n return installLinkAndRecord(\n {npmName: name, clone: pkgDir, relPkg, pkgDir, repo},\n opts,\n deps,\n );\n}\n\n/** The checkout's `origin` URL, or undefined when it has none. Read, never fetched. */\nfunction originOf(pkgDir, deps) {\n const r = deps.run('git', ['remote', 'get-url', 'origin'], {cwd: pkgDir});\n const url = r.stdout.trim();\n return r.status === 0 && url ? normalizeGitUrl(url) : undefined;\n}\n"]}
@@ -0,0 +1,6 @@
1
+ import type { Deps } from './run.js';
2
+ export declare function delocalize(names: string[], opts: {
3
+ purge?: boolean;
4
+ force?: boolean;
5
+ }, deps: Deps): number;
6
+ //# sourceMappingURL=delocalize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delocalize.d.ts","sourceRoot":"","sources":["../../../src/localize/delocalize.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,UAAU,CAAC;AAEnC,wBAAgB,UAAU,CACxB,KAAK,EAAE,MAAM,EAAE,EACf,IAAI,EAAE;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAC,EACxC,IAAI,EAAE,IAAI,GACT,MAAM,CAuER"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * `delocalize` -- reverse a localize WITHOUT deleting work.
3
+ *
4
+ * With no names, every recorded entry is delocalized, so there is one revert
5
+ * verb rather than two.
6
+ *
7
+ * The checkout is LEFT ON DISK by default: uncommitted work lives there.
8
+ * `--purge` deletes it, and refuses on uncommitted changes or unpushed commits
9
+ * unless `--force`.
10
+ *
11
+ * The restore command is PRINTED, not run. localize never invokes an install
12
+ * at the consumer root -- that is the rule the whole design rests on, and it
13
+ * does not get an exception for the convenient case. The printed line carries
14
+ * `--no-save`, which is load-bearing rather than tidy: a plain
15
+ * `npm install <name>@<range>` rewrites the range in package.json to whatever
16
+ * it resolved and rewrites the lockfile with it, so a developer following the
17
+ * tool's own advice would end the cycle with the exact diff the tool exists to
18
+ * prevent.
19
+ */
20
+ import fs from 'node:fs';
21
+ import path from 'node:path';
22
+ import { EXIT_WARNED } from './errors.js';
23
+ import { SCHEMA_VERSION, readManifest, writeManifest } from './manifest.js';
24
+ import { isInside, isSymlink, snapshotManifests } from './fsops.js';
25
+ import { assertManifestsUntouched, declaredRange, reportError, } from './localize.js';
26
+ export function delocalize(names, opts, deps) {
27
+ var _a;
28
+ const before = snapshotManifests(deps.appRoot);
29
+ let manifest;
30
+ try {
31
+ manifest = readManifest(deps.appRoot, deps);
32
+ }
33
+ catch (e) {
34
+ return reportError(e, deps);
35
+ }
36
+ const dir = manifest.dir;
37
+ const entries = Object.assign({}, manifest.entries);
38
+ const targets = names.length
39
+ ? names.map((n) => toRecordedName(n, entries))
40
+ : Object.keys(entries);
41
+ let code = 0;
42
+ for (const name of targets) {
43
+ const entry = entries[name];
44
+ if (!entry) {
45
+ deps.warn(`[localize] ${name} is not recorded — nothing to do.`);
46
+ code = Math.max(code, EXIT_WARNED);
47
+ continue;
48
+ }
49
+ code = Math.max(code, unlink(name, dir, deps));
50
+ const checkout = path.join(deps.appRoot, entry.path);
51
+ if (opts.purge) {
52
+ const refusal = purgeRefusal(checkout, deps);
53
+ if (refusal && !opts.force) {
54
+ deps.warn(`[localize] ${entry.path}: not deleting — ${refusal}. Pass --force to delete it anyway.`);
55
+ code = Math.max(code, EXIT_WARNED);
56
+ }
57
+ else {
58
+ if (refusal)
59
+ deps.warn(`[localize] --force: deleting ${entry.path} despite ${refusal}`);
60
+ fs.rmSync(checkout, { recursive: true, force: true });
61
+ deps.log(`[localize] removed ${entry.path}`);
62
+ }
63
+ }
64
+ else if (fs.existsSync(checkout)) {
65
+ deps.log(`[localize] ${entry.path} left on disk (uncommitted work lives there). --purge removes it.`);
66
+ }
67
+ delete entries[name];
68
+ const range = (_a = entry.range) !== null && _a !== void 0 ? _a : declaredRange(name, deps);
69
+ if (!range && !entry.repo) {
70
+ // An adopted package that was never published: there is no registry copy
71
+ // to go back to, and `@latest` would only 404.
72
+ deps.log(`[localize] ${name} was never declared or published — there is no registry copy to restore.`);
73
+ }
74
+ else {
75
+ deps.log(`[localize] restore the registry copy with: npm install --no-save ${name}@${range !== null && range !== void 0 ? range : 'latest'}`);
76
+ }
77
+ }
78
+ writeManifest(deps.appRoot, {
79
+ version: SCHEMA_VERSION,
80
+ dir,
81
+ packages: entries,
82
+ });
83
+ return Math.max(code, assertManifestsUntouched(before, deps));
84
+ }
85
+ /** Remove the link only when it is a symlink INTO the configured dir. */
86
+ function unlink(name, dir, deps) {
87
+ const link = path.join(deps.appRoot, 'node_modules', name);
88
+ if (!fs.existsSync(link) && !isSymlink(link))
89
+ return 0;
90
+ if (!isSymlink(link)) {
91
+ deps.warn(`[localize] node_modules/${name} is a real directory, not a link — left alone. ` +
92
+ `That is the registry copy; nothing to unlink.`);
93
+ return EXIT_WARNED;
94
+ }
95
+ let target;
96
+ try {
97
+ target = fs.realpathSync(link);
98
+ }
99
+ catch (_a) {
100
+ fs.unlinkSync(link); // dangling, and ours by elimination
101
+ deps.log(`[localize] unlinked ${name} (its target was already gone)`);
102
+ return 0;
103
+ }
104
+ if (!isInside(target, path.join(deps.appRoot, dir))) {
105
+ deps.warn(`[localize] node_modules/${name} links to ${target}, outside ${dir} — left alone. ` +
106
+ `delocalize only removes links it could have made.`);
107
+ return EXIT_WARNED;
108
+ }
109
+ fs.unlinkSync(link);
110
+ deps.log(`[localize] unlinked ${name}`);
111
+ return 0;
112
+ }
113
+ /** @returns {string|null} the reason a purge must be refused. */
114
+ function purgeRefusal(checkout, deps) {
115
+ if (!fs.existsSync(checkout))
116
+ return null;
117
+ const status = deps.run('git', ['status', '--porcelain'], { cwd: checkout });
118
+ if (status.stdout.trim()) {
119
+ const n = status.stdout.split('\n').filter((l) => l.trim()).length;
120
+ return `it has ${n} uncommitted change${n === 1 ? '' : 's'}`;
121
+ }
122
+ const unpushed = deps.run('git', ['log', '--oneline', '@{u}..HEAD'], {
123
+ cwd: checkout,
124
+ });
125
+ if (unpushed.status === 0 && unpushed.stdout.trim()) {
126
+ const n = unpushed.stdout.split('\n').filter((l) => l.trim()).length;
127
+ return `it has ${n} unpushed commit${n === 1 ? '' : 's'}`;
128
+ }
129
+ return null;
130
+ }
131
+ /** Accept a short name where the manifest records a scoped one. */
132
+ function toRecordedName(name, entries) {
133
+ var _a;
134
+ if (entries[name])
135
+ return name;
136
+ return (_a = Object.keys(entries).find((k) => k.split('/').pop() === name)) !== null && _a !== void 0 ? _a : name;
137
+ }
138
+ //# sourceMappingURL=delocalize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delocalize.js","sourceRoot":"","sources":["../../../src/localize/delocalize.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `delocalize` -- reverse a localize WITHOUT deleting work.\n *\n * With no names, every recorded entry is delocalized, so there is one revert\n * verb rather than two.\n *\n * The checkout is LEFT ON DISK by default: uncommitted work lives there.\n * `--purge` deletes it, and refuses on uncommitted changes or unpushed commits\n * unless `--force`.\n *\n * The restore command is PRINTED, not run. localize never invokes an install\n * at the consumer root -- that is the rule the whole design rests on, and it\n * does not get an exception for the convenient case. The printed line carries\n * `--no-save`, which is load-bearing rather than tidy: a plain\n * `npm install <name>@<range>` rewrites the range in package.json to whatever\n * it resolved and rewrites the lockfile with it, so a developer following the\n * tool's own advice would end the cycle with the exact diff the tool exists to\n * prevent.\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport {EXIT_WARNED} from './errors.js';\nimport {SCHEMA_VERSION, readManifest, writeManifest} from './manifest.js';\nimport {isInside, isSymlink, snapshotManifests} from './fsops.js';\nimport {\n assertManifestsUntouched,\n declaredRange,\n reportError,\n} from './localize.js';\nimport type {Deps} from './run.js';\n\nexport function delocalize(\n names: string[],\n opts: {purge?: boolean; force?: boolean},\n deps: Deps,\n): number {\n const before = snapshotManifests(deps.appRoot);\n\n let manifest;\n try {\n manifest = readManifest(deps.appRoot, deps);\n } catch (e) {\n return reportError(e, deps);\n }\n\n const dir = manifest.dir;\n const entries = {...manifest.entries};\n const targets = names.length\n ? names.map((n) => toRecordedName(n, entries))\n : Object.keys(entries);\n let code = 0;\n\n for (const name of targets) {\n const entry = entries[name];\n if (!entry) {\n deps.warn(`[localize] ${name} is not recorded — nothing to do.`);\n code = Math.max(code, EXIT_WARNED);\n continue;\n }\n\n code = Math.max(code, unlink(name, dir, deps));\n\n const checkout = path.join(deps.appRoot, entry.path);\n if (opts.purge) {\n const refusal = purgeRefusal(checkout, deps);\n if (refusal && !opts.force) {\n deps.warn(\n `[localize] ${entry.path}: not deleting — ${refusal}. Pass --force to delete it anyway.`,\n );\n code = Math.max(code, EXIT_WARNED);\n } else {\n if (refusal)\n deps.warn(\n `[localize] --force: deleting ${entry.path} despite ${refusal}`,\n );\n fs.rmSync(checkout, {recursive: true, force: true});\n deps.log(`[localize] removed ${entry.path}`);\n }\n } else if (fs.existsSync(checkout)) {\n deps.log(\n `[localize] ${entry.path} left on disk (uncommitted work lives there). --purge removes it.`,\n );\n }\n\n delete entries[name];\n\n const range = entry.range ?? declaredRange(name, deps);\n if (!range && !entry.repo) {\n // An adopted package that was never published: there is no registry copy\n // to go back to, and `@latest` would only 404.\n deps.log(\n `[localize] ${name} was never declared or published — there is no registry copy to restore.`,\n );\n } else {\n deps.log(\n `[localize] restore the registry copy with: npm install --no-save ${name}@${range ?? 'latest'}`,\n );\n }\n }\n\n writeManifest(deps.appRoot, {\n version: SCHEMA_VERSION,\n dir,\n packages: entries,\n });\n return Math.max(code, assertManifestsUntouched(before, deps));\n}\n\n/** Remove the link only when it is a symlink INTO the configured dir. */\nfunction unlink(name, dir, deps) {\n const link = path.join(deps.appRoot, 'node_modules', name);\n if (!fs.existsSync(link) && !isSymlink(link)) return 0;\n\n if (!isSymlink(link)) {\n deps.warn(\n `[localize] node_modules/${name} is a real directory, not a link — left alone. ` +\n `That is the registry copy; nothing to unlink.`,\n );\n return EXIT_WARNED;\n }\n\n let target;\n try {\n target = fs.realpathSync(link);\n } catch {\n fs.unlinkSync(link); // dangling, and ours by elimination\n deps.log(`[localize] unlinked ${name} (its target was already gone)`);\n return 0;\n }\n\n if (!isInside(target, path.join(deps.appRoot, dir))) {\n deps.warn(\n `[localize] node_modules/${name} links to ${target}, outside ${dir} — left alone. ` +\n `delocalize only removes links it could have made.`,\n );\n return EXIT_WARNED;\n }\n\n fs.unlinkSync(link);\n deps.log(`[localize] unlinked ${name}`);\n return 0;\n}\n\n/** @returns {string|null} the reason a purge must be refused. */\nfunction purgeRefusal(checkout, deps) {\n if (!fs.existsSync(checkout)) return null;\n const status = deps.run('git', ['status', '--porcelain'], {cwd: checkout});\n if (status.stdout.trim()) {\n const n = status.stdout.split('\\n').filter((l) => l.trim()).length;\n return `it has ${n} uncommitted change${n === 1 ? '' : 's'}`;\n }\n const unpushed = deps.run('git', ['log', '--oneline', '@{u}..HEAD'], {\n cwd: checkout,\n });\n if (unpushed.status === 0 && unpushed.stdout.trim()) {\n const n = unpushed.stdout.split('\\n').filter((l) => l.trim()).length;\n return `it has ${n} unpushed commit${n === 1 ? '' : 's'}`;\n }\n return null;\n}\n\n/** Accept a short name where the manifest records a scoped one. */\nfunction toRecordedName(name, entries) {\n if (entries[name]) return name;\n return Object.keys(entries).find((k) => k.split('/').pop() === name) ?? name;\n}\n"]}
@@ -0,0 +1,26 @@
1
+ import type { ManifestEntry } from './manifest.js';
2
+ import type { PruneOptions } from './prune.js';
3
+ import type { Deps } from './run.js';
4
+ /**
5
+ * `npm install` inside the checkout at `entry.path`, then prune it.
6
+ *
7
+ * The package's name is read from the checkout's own `package.json`; the
8
+ * other localized packages (siblings) from the manifest, so a checkout being
9
+ * localized right now prunes before the manifest records it.
10
+ *
11
+ * @returns 0, or `EXIT_WARNED` when the prune failed (the install stands).
12
+ * @throws {LocalizeError} `EXIT_INSTALL_FAILED` when `npm install` fails.
13
+ */
14
+ export declare function ensure(entry: Pick<ManifestEntry, 'path' | 'subdir'>, deps: Deps, opts?: PruneOptions): number;
15
+ /** `linked localize --reinstall <pkg>`: `ensure` for one recorded package. */
16
+ export declare function reinstall(name: string, opts: PruneOptions, deps: Deps): number;
17
+ /**
18
+ * The run-time check: remove every recorded checkout's own copy of what the
19
+ * app provides. Stat-only until there is something to remove.
20
+ *
21
+ * @returns what was removed, as `<checkout>/node_modules/<name>@<version>`.
22
+ */
23
+ export declare function checkOneCopy(appRoot?: string, deps?: Pick<Deps, 'log' | 'warn'>): {
24
+ pruned: string[];
25
+ };
26
+ //# sourceMappingURL=ensure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ensure.d.ts","sourceRoot":"","sources":["../../../src/localize/ensure.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,eAAe,CAAC;AAQjD,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,YAAY,CAAC;AAG7C,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,UAAU,CAAC;AAGnC;;;;;;;;;GASG;AACH,wBAAgB,MAAM,CACpB,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,QAAQ,CAAC,EAC7C,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;;;;;GAKG;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,CAsDpB"}