@_linked/cli 1.46.1 → 1.47.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 (167) hide show
  1. package/CHANGELOG.md +113 -0
  2. package/README.md +48 -36
  3. package/hooks/drift.cjs +169 -0
  4. package/hooks/git-hook.cjs +170 -0
  5. package/hooks/hook-shim.cjs +63 -0
  6. package/hooks/lock-at-rest.cjs +268 -0
  7. package/hooks/manifests.cjs +216 -0
  8. package/hooks/platform.cjs +25 -0
  9. package/lib/esm/app-release/build-backend.d.ts.map +1 -1
  10. package/lib/esm/app-release/build-backend.js +2 -1
  11. package/lib/esm/app-release/build-backend.js.map +1 -1
  12. package/lib/esm/cli-methods.d.ts.map +1 -1
  13. package/lib/esm/cli-methods.js +166 -150
  14. package/lib/esm/cli-methods.js.map +1 -1
  15. package/lib/esm/cli.js +20 -22
  16. package/lib/esm/cli.js.map +1 -1
  17. package/lib/esm/commands/build-app.d.ts.map +1 -1
  18. package/lib/esm/commands/build-app.js +2 -1
  19. package/lib/esm/commands/build-app.js.map +1 -1
  20. package/lib/esm/commands/build-package.d.ts.map +1 -1
  21. package/lib/esm/commands/build-package.js +6 -2
  22. package/lib/esm/commands/build-package.js.map +1 -1
  23. package/lib/esm/commands/localize.d.ts +9 -15
  24. package/lib/esm/commands/localize.d.ts.map +1 -1
  25. package/lib/esm/commands/localize.js +43 -74
  26. package/lib/esm/commands/localize.js.map +1 -1
  27. package/lib/esm/commands/setup-publish.d.ts.map +1 -1
  28. package/lib/esm/commands/setup-publish.js +22 -15
  29. package/lib/esm/commands/setup-publish.js.map +1 -1
  30. package/lib/esm/commands/start.d.ts +8 -0
  31. package/lib/esm/commands/start.d.ts.map +1 -1
  32. package/lib/esm/commands/start.js +20 -8
  33. package/lib/esm/commands/start.js.map +1 -1
  34. package/lib/esm/installed-packages.d.ts +5 -13
  35. package/lib/esm/installed-packages.d.ts.map +1 -1
  36. package/lib/esm/installed-packages.js +5 -38
  37. package/lib/esm/installed-packages.js.map +1 -1
  38. package/lib/esm/lifecycle.d.ts +35 -22
  39. package/lib/esm/lifecycle.d.ts.map +1 -1
  40. package/lib/esm/lifecycle.js +62 -36
  41. package/lib/esm/lifecycle.js.map +1 -1
  42. package/lib/esm/localize/adopt.d.ts +5 -5
  43. package/lib/esm/localize/adopt.d.ts.map +1 -1
  44. package/lib/esm/localize/adopt.js +46 -55
  45. package/lib/esm/localize/adopt.js.map +1 -1
  46. package/lib/esm/localize/app-root.d.ts +16 -0
  47. package/lib/esm/localize/app-root.d.ts.map +1 -0
  48. package/lib/esm/localize/app-root.js +94 -0
  49. package/lib/esm/localize/app-root.js.map +1 -0
  50. package/lib/esm/localize/app-setup.d.ts +21 -0
  51. package/lib/esm/localize/app-setup.d.ts.map +1 -0
  52. package/lib/esm/localize/app-setup.js +178 -0
  53. package/lib/esm/localize/app-setup.js.map +1 -0
  54. package/lib/esm/localize/delocalize.d.ts.map +1 -1
  55. package/lib/esm/localize/delocalize.js +169 -104
  56. package/lib/esm/localize/delocalize.js.map +1 -1
  57. package/lib/esm/localize/drift-hook.d.ts +18 -0
  58. package/lib/esm/localize/drift-hook.d.ts.map +1 -0
  59. package/lib/esm/localize/drift-hook.js +37 -0
  60. package/lib/esm/localize/drift-hook.js.map +1 -0
  61. package/lib/esm/localize/drift.d.ts +36 -0
  62. package/lib/esm/localize/drift.d.ts.map +1 -0
  63. package/lib/esm/localize/drift.js +34 -0
  64. package/lib/esm/localize/drift.js.map +1 -0
  65. package/lib/esm/localize/errors.d.ts +14 -8
  66. package/lib/esm/localize/errors.d.ts.map +1 -1
  67. package/lib/esm/localize/errors.js +14 -8
  68. package/lib/esm/localize/errors.js.map +1 -1
  69. package/lib/esm/localize/fsops.d.ts +11 -27
  70. package/lib/esm/localize/fsops.d.ts.map +1 -1
  71. package/lib/esm/localize/fsops.js +40 -115
  72. package/lib/esm/localize/fsops.js.map +1 -1
  73. package/lib/esm/localize/git-hooks.d.ts +33 -0
  74. package/lib/esm/localize/git-hooks.d.ts.map +1 -0
  75. package/lib/esm/localize/git-hooks.js +146 -0
  76. package/lib/esm/localize/git-hooks.js.map +1 -0
  77. package/lib/esm/localize/hook-module.d.ts +6 -0
  78. package/lib/esm/localize/hook-module.d.ts.map +1 -0
  79. package/lib/esm/localize/hook-module.js +37 -0
  80. package/lib/esm/localize/hook-module.js.map +1 -0
  81. package/lib/esm/localize/index.d.ts +14 -15
  82. package/lib/esm/localize/index.d.ts.map +1 -1
  83. package/lib/esm/localize/index.js +8 -9
  84. package/lib/esm/localize/index.js.map +1 -1
  85. package/lib/esm/localize/list.d.ts +6 -10
  86. package/lib/esm/localize/list.d.ts.map +1 -1
  87. package/lib/esm/localize/list.js +49 -189
  88. package/lib/esm/localize/list.js.map +1 -1
  89. package/lib/esm/localize/localize.d.ts +46 -62
  90. package/lib/esm/localize/localize.d.ts.map +1 -1
  91. package/lib/esm/localize/localize.js +411 -285
  92. package/lib/esm/localize/localize.js.map +1 -1
  93. package/lib/esm/localize/members.d.ts +13 -0
  94. package/lib/esm/localize/members.d.ts.map +1 -0
  95. package/lib/esm/localize/members.js +46 -0
  96. package/lib/esm/localize/members.js.map +1 -0
  97. package/lib/esm/localize/resolve.d.ts +1 -2
  98. package/lib/esm/localize/resolve.d.ts.map +1 -1
  99. package/lib/esm/localize/resolve.js +3 -5
  100. package/lib/esm/localize/resolve.js.map +1 -1
  101. package/lib/esm/localize/run.d.ts +1 -0
  102. package/lib/esm/localize/run.d.ts.map +1 -1
  103. package/lib/esm/localize/run.js +11 -6
  104. package/lib/esm/localize/run.js.map +1 -1
  105. package/lib/esm/localize/setup-lockfile.d.ts +13 -0
  106. package/lib/esm/localize/setup-lockfile.d.ts.map +1 -0
  107. package/lib/esm/localize/setup-lockfile.js +80 -0
  108. package/lib/esm/localize/setup-lockfile.js.map +1 -0
  109. package/lib/esm/utils/createPackageLocation.d.ts +4 -13
  110. package/lib/esm/utils/createPackageLocation.d.ts.map +1 -1
  111. package/lib/esm/utils/createPackageLocation.js +12 -21
  112. package/lib/esm/utils/createPackageLocation.js.map +1 -1
  113. package/lib/esm/utils/packageSetup.d.ts +5 -2
  114. package/lib/esm/utils/packageSetup.d.ts.map +1 -1
  115. package/lib/esm/utils/packageSetup.js +9 -3
  116. package/lib/esm/utils/packageSetup.js.map +1 -1
  117. package/lib/esm/utils/platform.d.ts +24 -0
  118. package/lib/esm/utils/platform.d.ts.map +1 -0
  119. package/lib/esm/utils/platform.js +62 -0
  120. package/lib/esm/utils/platform.js.map +1 -0
  121. package/lib/esm/utils/shapeReferences.d.ts.map +1 -1
  122. package/lib/esm/utils/shapeReferences.js +3 -2
  123. package/lib/esm/utils/shapeReferences.js.map +1 -1
  124. package/lib/esm/utils/spawn.d.ts +65 -0
  125. package/lib/esm/utils/spawn.d.ts.map +1 -0
  126. package/lib/esm/utils/spawn.js +181 -0
  127. package/lib/esm/utils/spawn.js.map +1 -0
  128. package/lib/esm/utils.d.ts.map +1 -1
  129. package/lib/esm/utils.js +19 -5
  130. package/lib/esm/utils.js.map +1 -1
  131. package/lib/esm/vite-config.d.ts +5 -12
  132. package/lib/esm/vite-config.d.ts.map +1 -1
  133. package/lib/esm/vite-config.js +41 -33
  134. package/lib/esm/vite-config.js.map +1 -1
  135. package/package.json +4 -3
  136. package/lib/esm/localize/ensure.d.ts +0 -44
  137. package/lib/esm/localize/ensure.d.ts.map +0 -1
  138. package/lib/esm/localize/ensure.js +0 -151
  139. package/lib/esm/localize/ensure.js.map +0 -1
  140. package/lib/esm/localize/manifest.d.ts +0 -63
  141. package/lib/esm/localize/manifest.d.ts.map +0 -1
  142. package/lib/esm/localize/manifest.js +0 -133
  143. package/lib/esm/localize/manifest.js.map +0 -1
  144. package/lib/esm/localize/one-copy-hook.d.ts +0 -16
  145. package/lib/esm/localize/one-copy-hook.d.ts.map +0 -1
  146. package/lib/esm/localize/one-copy-hook.js +0 -20
  147. package/lib/esm/localize/one-copy-hook.js.map +0 -1
  148. package/lib/esm/localize/provided.d.ts +0 -28
  149. package/lib/esm/localize/provided.d.ts.map +0 -1
  150. package/lib/esm/localize/provided.js +0 -89
  151. package/lib/esm/localize/provided.js.map +0 -1
  152. package/lib/esm/localize/prune.d.ts +0 -165
  153. package/lib/esm/localize/prune.d.ts.map +0 -1
  154. package/lib/esm/localize/prune.js +0 -619
  155. package/lib/esm/localize/prune.js.map +0 -1
  156. package/lib/esm/localize/relink.d.ts +0 -13
  157. package/lib/esm/localize/relink.d.ts.map +0 -1
  158. package/lib/esm/localize/relink.js +0 -179
  159. package/lib/esm/localize/relink.js.map +0 -1
  160. package/lib/esm/localized-dedupe.d.ts +0 -26
  161. package/lib/esm/localized-dedupe.d.ts.map +0 -1
  162. package/lib/esm/localized-dedupe.js +0 -139
  163. package/lib/esm/localized-dedupe.js.map +0 -1
  164. package/lib/esm/utils/relinkHooks.d.ts +0 -19
  165. package/lib/esm/utils/relinkHooks.d.ts.map +0 -1
  166. package/lib/esm/utils/relinkHooks.js +0 -74
  167. package/lib/esm/utils/relinkHooks.js.map +0 -1
@@ -24,6 +24,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
24
24
  import path from 'node:path';
25
25
  import fs from 'node:fs/promises';
26
26
  import { spawn } from 'node:child_process';
27
+ import { importFile, isPathInside } from '../utils/platform.js';
27
28
  import fsExtra from 'fs-extra';
28
29
  import { parseWorkspacePatterns, isWorkspacePathNegated } from '../workspace-globs.js';
29
30
  export const VITE_CONFIG_FILES = ['vite.config.ts', 'vite.config.js', 'vite.config.mjs'];
@@ -231,19 +232,30 @@ function isInsideNodeModules(p) {
231
232
  }
232
233
  function workspacePackageForPath(filepath, pkgs) {
233
234
  for (const p of pkgs) {
234
- if (filepath.startsWith(p.srcDir + path.sep) || filepath === p.srcDir) {
235
+ // The watcher's path may use `/` on Windows, and differ in case there.
236
+ if (isPathInside(filepath, p.srcDir)) {
235
237
  return p.name;
236
238
  }
237
239
  }
238
240
  return null;
239
241
  }
242
+ /**
243
+ * The command that opens `url` in the default browser. Windows' `start` is a
244
+ * cmd.exe built-in, not a program, so there it is `explorer.exe <url>`.
245
+ */
246
+ export function browserCommand(url, platform = process.platform) {
247
+ if (platform === 'darwin')
248
+ return { command: 'open', args: [url] };
249
+ if (platform === 'win32')
250
+ return { command: 'explorer.exe', args: [url] };
251
+ return { command: 'xdg-open', args: [url] };
252
+ }
240
253
  function openBrowser(url) {
241
- const cmd = process.platform === 'darwin'
242
- ? 'open'
243
- : process.platform === 'win32'
244
- ? 'start'
245
- : 'xdg-open';
246
- spawn(cmd, [url], { detached: true, stdio: 'ignore' }).unref();
254
+ const { command, args } = browserCommand(url);
255
+ const child = spawn(command, args, { detached: true, stdio: 'ignore' });
256
+ // A missing opener must not take the dev server down.
257
+ child.on('error', (e) => console.warn(`[linked] could not open ${url}: ${e.message}`));
258
+ child.unref();
247
259
  }
248
260
  function installShortcuts(opts) {
249
261
  if (!process.stdin.isTTY)
@@ -329,7 +341,7 @@ export function startWithVite() {
329
341
  const linkedConfigPath = resolveLinkedConfigPath(cwd);
330
342
  let linkedConfig = {};
331
343
  if (fsExtra.existsSync(linkedConfigPath)) {
332
- linkedConfig = (_a = (yield import(linkedConfigPath)).default) !== null && _a !== void 0 ? _a : {};
344
+ linkedConfig = (_a = (yield importFile(linkedConfigPath)).default) !== null && _a !== void 0 ? _a : {};
333
345
  }
334
346
  linkedConfig.server = linkedConfig.server || {};
335
347
  const apiOnly = isApiOnly(opts, linkedConfig);
@@ -1 +1 @@
1
- {"version":3,"file":"start.js","sourceRoot":"","sources":["../../../src/commands/start.ts"],"names":[],"mappings":"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","sourcesContent":["// `linked start --vite` orchestrator.\n//\n// Follows the existing startServer() flow from cli-methods.ts but injects\n// a Vite dev server in middleware mode + overrides loadAppComponent /\n// loadRoutes to use vite.ssrLoadModule. This means LinkedServer's existing\n// initialization works unchanged; we just route module loading through\n// Vite instead of loading modules through Node directly.\n//\n// What's different vs the plain startServer():\n// - LinkedServer renders through the Vite middleware when viteMiddleware is set\n// - Vite handles the client transform + HMR\n// - ssrLoadModule handles the server transform (decorators, jsx, ts)\n// - Server changes still need full process restart for now (server HMR\n// deferred to vite-node migration)\nimport path from 'node:path';\nimport fs from 'node:fs/promises';\nimport {spawn} from 'node:child_process';\nimport fsExtra from 'fs-extra';\nimport {parseWorkspacePatterns, isWorkspacePathNegated} from '../workspace-globs.js';\n\nimport type {InlineConfig, UserConfigExport, ViteDevServer} from 'vite';\n\nexport interface StartOptions {\n env?: string;\n port?: number;\n /**\n * Serve only the backend API (`/call/...`, `/api/...`, provider routes).\n * No `vite.config.*`, `src/App.tsx` or `src/routes.tsx` is needed, and page\n * requests get a 404 instead of server-side rendering.\n */\n apiOnly?: boolean;\n}\n\nexport const VITE_CONFIG_FILES = ['vite.config.ts', 'vite.config.js', 'vite.config.mjs'];\n\n/**\n * Names for the app's linked config, in priority order. `lincd.config.js` is\n * the legacy name: apps predating the rename still ship it, and dropping it\n * would silently discard their whole `server` config (cachePaths, `apiOnly`, …).\n */\nexport const LINKED_CONFIG_FILES = ['linked.config.js', 'lincd.config.js'];\n\n/**\n * Absolute path to the app's linked config. Returns the first name that exists;\n * when none does, the current name — the caller still `existsSync`-guards the\n * import, so this is simply the \"no config here\" path, not a promise of a file.\n */\nexport function resolveLinkedConfigPath(cwd: string): string {\n return (\n LINKED_CONFIG_FILES.map((name) => path.join(cwd, name)).find((candidate) =>\n fsExtra.existsSync(candidate),\n ) ?? path.join(cwd, LINKED_CONFIG_FILES[0])\n );\n}\n\n/**\n * API-only mode is explicit: `linked start --api-only`, or `server.apiOnly: true`\n * in `linked.config.js`. It is never inferred from missing frontend files, so a\n * web app that lost its `vite.config.ts` still fails loudly instead of silently\n * serving no pages.\n */\nexport function isApiOnly(opts: StartOptions, linkedConfig: any): boolean {\n return opts.apiOnly === true || linkedConfig?.server?.apiOnly === true;\n}\n\n/**\n * The Vite dev-server config for `linked start`.\n *\n * With a `vite.config.*` in `cwd`, Vite loads it itself. Without one, API-only\n * mode uses `createViteConfig()`'s defaults inline — Vite is still needed on the\n * backend to transform TypeScript, decorators and extensionless imports of\n * source-only shape packages. Without one in page mode, it is an error.\n */\nexport async function resolveViteServerConfig(\n cwd: string,\n apiOnly: boolean,\n): Promise<InlineConfig> {\n const base: InlineConfig = {\n root: cwd,\n server: {middlewareMode: true},\n appType: 'custom',\n };\n if (VITE_CONFIG_FILES.some((c) => fsExtra.existsSync(path.join(cwd, c)))) {\n return base;\n }\n if (!apiOnly) {\n throw new Error(\n `[linked start] no vite.config.{ts,js,mjs} found in ${cwd}. Add one:\\n\\n import {createViteConfig} from '@_linked/cli/vite-config';\\n export default createViteConfig({port: 4040, cssMode: 'tailwind'});\\n\\nFor a backend without a web frontend, run \\`linked start --api-only\\` instead.\\n`,\n );\n }\n const {createViteConfig} = await import('../vite-config.js');\n const exported: UserConfigExport = createViteConfig();\n const defaults =\n typeof exported === 'function'\n ? await exported({command: 'serve', mode: 'development'})\n : await exported;\n return {\n ...defaults,\n ...base,\n configFile: false,\n server: {...defaults.server, ...base.server},\n // No browser client: skip the client dependency scan, whose entry\n // (`src/index.tsx`) does not exist in a backend.\n optimizeDeps: {...defaults.optimizeDeps, noDiscovery: true},\n };\n}\n\n/**\n * Inject Vite into LinkedServer's config:\n * - vite: handle for ssrLoadModule (used to load app's backend.ts via self-reference)\n * and, unless API-only (where `apiOnly` makes LinkedServer skip page rendering):\n * - viteMiddleware: mounted as the dev-server middleware\n * - loadAppComponent / loadRoutes: route through vite.ssrLoadModule for SSR transform\n * - viteSsrPreload: page modules to preload for SSR CSS collection\n */\nexport function configureLinkedServer(\n serverConfig: any,\n vite: Pick<ViteDevServer, 'middlewares' | 'ssrLoadModule'>,\n cwd: string,\n apiOnly: boolean,\n): void {\n serverConfig.vite = vite;\n if (apiOnly) {\n serverConfig.apiOnly = true;\n return;\n }\n serverConfig.viteMiddleware = vite.middlewares;\n serverConfig.loadAppComponent = async () => {\n const mod = await vite.ssrLoadModule('/src/App.tsx');\n return mod.default;\n };\n serverConfig.loadRoutes = async () => {\n return await vite.ssrLoadModule('/src/routes.tsx');\n };\n\n // Vite SSR CSS collection support:\n // List all `src/pages/*.{ts,tsx}` files so LinkedServer can ssrLoadModule\n // each into Vite's moduleGraph BEFORE the first render of a session.\n // React.lazy() doesn't auto-fire — without this, only App's eager\n // imports' CSS is collected; lazy pages' CSS arrives after hydration\n // causing an unstyled flash. After the first preload sweep, all\n // subsequent renders have full CSS available.\n serverConfig.viteSsrPreload = async () => {\n const pagesDir = path.join(cwd, 'src', 'pages');\n if (!fsExtra.existsSync(pagesDir)) return [];\n const files = fsExtra.readdirSync(pagesDir, {withFileTypes: true});\n const paths: string[] = [];\n for (const file of files) {\n // Test files live beside pages but call vi.mock() at module scope,\n // which throws outside Vitest — never load them into the SSR graph.\n // `.d.ts` files are types only: they have no runtime module to load.\n if (\n file.isFile() &&\n /\\.(tsx|ts)$/.test(file.name) &&\n !/\\.(test|spec)\\.(tsx|ts)$/.test(file.name) &&\n !file.name.endsWith('.d.ts')\n ) {\n paths.push(`/src/pages/${file.name}`);\n }\n }\n return paths;\n };\n}\n\ninterface WorkspacePackage {\n name: string;\n root: string;\n srcDir: string;\n}\n\n/**\n * Discover the packages whose sources `linked start` watches for HMR, from two\n * sources. No hand-maintained list anywhere.\n *\n * 1. The app's `package.json` `workspaces` field — adding a new linked package\n * = appearing in the right glob.\n * 2. The app's linked dependencies that are installed as SOURCE — the same rule\n * the Vite resolver table uses (`discoverLinkedSourceDependencies`), so the\n * two lists cannot disagree about what is source. This covers a LOCALIZED\n * checkout (`packages-local/<pkg>`), which is deliberately in no workspace\n * glob and reachable only through its `node_modules` symlink. Without it\n * `workspacePackageForPath` returns null for the checkout, so a saved backend\n * edit is reloaded by Vite and then never re-indexed: the registered provider\n * instance is never replaced.\n *\n * Returns each package's npm `name` (so we can call `onSourceChange(name)`), its\n * absolute root, and its `src/` directory for fast prefix matching. Dependency\n * roots are realpathed by the shared discovery, matching the ids Vite reports.\n */\nexport async function discoverWorkspacePackages(cwd: string): Promise<WorkspacePackage[]> {\n const pkgJsonPath = path.join(cwd, 'package.json');\n if (!(await fsExtra.pathExists(pkgJsonPath))) return [];\n const pkgJson = await fsExtra.readJson(pkgJsonPath);\n const {patterns, negatedPatterns} = parseWorkspacePatterns(pkgJson.workspaces);\n const out: WorkspacePackage[] = [];\n\n // Include the root app itself so edits to <cwd>/src/* trigger HMR for\n // the app's own providers (e.g. CN's src/backend.ts which registers ~25\n // Express routes).\n if (pkgJson.name && (await fsExtra.pathExists(path.join(cwd, 'src')))) {\n out.push({name: pkgJson.name, root: cwd, srcDir: path.join(cwd, 'src')});\n }\n for (const glob of patterns) {\n // Positive patterns are expanded by directory listing rather than with a\n // full glob library, so only a trailing /* is honoured. Negated entries\n // (\"!packages/core\") are honoured in full — watching an excluded directory\n // would trigger HMR for a package the app does not actually resolve.\n const m = glob.match(/^(.+?)\\/\\*$/);\n const candidates: string[] = [];\n if (m) {\n const parent = path.join(cwd, m[1]);\n if (await fsExtra.pathExists(parent)) {\n const entries = await fs.readdir(parent, {withFileTypes: true});\n for (const dirent of entries) {\n if (dirent.isDirectory() || dirent.isSymbolicLink()) {\n candidates.push(path.join(parent, dirent.name));\n }\n }\n }\n } else {\n candidates.push(path.join(cwd, glob));\n }\n for (const root of candidates) {\n const rel = path.relative(cwd, root).split(path.sep).join('/');\n if (isWorkspacePathNegated(rel, negatedPatterns)) continue;\n const pkgPath = path.join(root, 'package.json');\n if (!(await fsExtra.pathExists(pkgPath))) continue;\n try {\n const sub = await fsExtra.readJson(pkgPath);\n if (sub.name) {\n out.push({name: sub.name, root, srcDir: path.join(root, 'src')});\n }\n } catch {\n // ignore broken package.json\n }\n }\n }\n\n // Linked deps installed as source, realpathed — a localized checkout is here\n // and nowhere else. Imported lazily because vite-config pulls in Vite itself.\n const {discoverLinkedSourceDependencies} = await import('../vite-config.js');\n const names = new Set(out.map((p) => p.name));\n for (const entry of await discoverLinkedSourceDependencies(cwd)) {\n if (names.has(entry.name)) continue;\n // Only working copies. Some PUBLISHED packages ship `src/` in their tarball,\n // so the resolver registers them (it serves that source) — but they stay\n // inside `node_modules`, which Vite's watcher ignores, so no change event\n // can ever match them. Listing them would inflate the count printed at boot\n // with packages nothing watches. A localized checkout, a workspace clone and\n // an `npm link` all realpath to a directory outside `node_modules`.\n if (isInsideNodeModules(entry.srcDir)) continue;\n names.add(entry.name);\n out.push({name: entry.name, root: path.dirname(entry.srcDir), srcDir: entry.srcDir});\n }\n return out;\n}\n\nfunction isInsideNodeModules(p: string): boolean {\n return p.split(path.sep).includes('node_modules');\n}\n\nfunction workspacePackageForPath(\n filepath: string,\n pkgs: WorkspacePackage[],\n): string | null {\n for (const p of pkgs) {\n if (filepath.startsWith(p.srcDir + path.sep) || filepath === p.srcDir) {\n return p.name;\n }\n }\n return null;\n}\n\nfunction openBrowser(url: string): void {\n const cmd =\n process.platform === 'darwin'\n ? 'open'\n : process.platform === 'win32'\n ? 'start'\n : 'xdg-open';\n spawn(cmd, [url], {detached: true, stdio: 'ignore'}).unref();\n}\n\nfunction installShortcuts(opts: {url: string; onRestart: () => void}): void {\n if (!process.stdin.isTTY) return;\n let buf = '';\n try {\n process.stdin.setRawMode(true);\n } catch {\n return;\n }\n process.stdin.resume();\n process.stdin.setEncoding('utf8');\n const cleanup = () => {\n try {\n process.stdin.setRawMode(false);\n } catch {}\n };\n process.on('exit', cleanup);\n process.stdin.on('data', (chunk: string) => {\n for (const ch of chunk) {\n // Ctrl-C → graceful exit, restore terminal first.\n if (ch === '\u0003') {\n cleanup();\n process.exit(0);\n }\n if (ch === '\\r' || ch === '\\n') {\n const cmd = buf.trim();\n buf = '';\n if (cmd === 'r') {\n console.log('[linked] restarting…');\n opts.onRestart();\n } else if (cmd === 'o') {\n console.log(`[linked] opening ${opts.url}`);\n openBrowser(opts.url);\n }\n } else {\n buf += ch;\n }\n }\n });\n console.log(\n `[linked] press r<enter> to restart · o<enter> to open ${opts.url}`,\n );\n}\n\nfunction restartProcess(): void {\n // nodemon-style respawn: launch a fresh process from the same argv,\n // then exit. The new process inherits stdio so the dev experience is\n // continuous.\n const [node, ...argv] = process.argv;\n const child = spawn(node, argv, {\n stdio: 'inherit',\n detached: true,\n env: process.env,\n });\n child.unref();\n process.exit(0);\n}\n\nexport async function startWithVite(opts: StartOptions = {}): Promise<void> {\n const cwd = process.cwd();\n\n // Load the app's own `.env` (Node 20.12+ `process.loadEnvFile`) if present — the\n // standard, dependency-free env source for a linked app. Node does NOT override\n // vars already set in the environment, so CN's injected per-(project,branch) vars\n // (PORT, FUSEKI_DATASET, CN_APP_ADMIN_SECRET, …) take precedence over the file.\n try {\n const envPath = path.join(cwd, '.env');\n if (\n (await fsExtra.pathExists(envPath)) &&\n typeof (process as {loadEnvFile?: (p: string) => void}).loadEnvFile === 'function'\n ) {\n (process as {loadEnvFile: (p: string) => void}).loadEnvFile(envPath);\n }\n } catch {\n // best-effort — a missing/invalid .env never blocks start\n }\n\n // `--env` still loads env-cmd (`.env-cmdrc.json`) for CN's own start:local flow.\n const {ensureEnvironmentLoaded} = await import('../lifecycle.js');\n await ensureEnvironmentLoaded();\n\n // Load user's linked.config.js (legacy hook). It still drives things\n // like server.cachePaths and the rest of LinkedServer's options.\n const linkedConfigPath = resolveLinkedConfigPath(cwd);\n let linkedConfig: any = {};\n if (fsExtra.existsSync(linkedConfigPath)) {\n linkedConfig = (await import(linkedConfigPath)).default ?? {};\n }\n linkedConfig.server = linkedConfig.server || {};\n const apiOnly = isApiOnly(opts, linkedConfig);\n\n const {createServer: createViteServer} = await import('vite');\n const vite = await createViteServer(await resolveViteServerConfig(cwd, apiOnly));\n configureLinkedServer(linkedConfig.server, vite, cwd, apiOnly);\n\n // Load the storage config through Vite SSR so it\n // configures the SAME LinkedStorage instance the rest of the SSR graph\n // (LinkedServer, CN providers) uses. Replaces the former Node-direct\n // `loadBackendStorageConfig()` (which resolved @_linked/core via the\n // `default`→lib condition, a SEPARATE instance). Safe now that core's lib\n // `initTree` is idempotent. `loadBackendStorageConfig` stays in\n // lifecycle.ts for the Node-only CLI commands (`script`/`call`) that have no\n // Vite server (contract C5).\n // The first two names are current; the rest are legacy filenames kept so\n // older apps that never renamed their storage config still start.\n for (const rel of [\n '/linked.backend.storage.ts',\n '/linked.backend.storage.js',\n '/backend-storage-config.ts',\n '/backend-storage-config.js',\n '/scripts/backend-storage-config.ts',\n '/scripts/backend-storage-config.js',\n '/scripts/storage-config.js',\n ]) {\n if (fsExtra.existsSync(path.join(cwd, rel.slice(1)))) {\n await vite.ssrLoadModule(rel);\n break;\n }\n }\n\n // Load LinkedServer through Vite SSR so it shares the SAME\n // module instances as everything else in the SSR call graph. Without\n // this, LinkedServer is loaded by Node (→ lib/esm) while CN's App.tsx +\n // its transitive imports are loaded by Vite (→ src/). React contexts\n // created in one tree don't reach consumers in the other, causing\n // \"Cannot destructure property 'isNativeApp' of useAppContext()\" type\n // errors on every SSR render.\n // Loading this entry through Vite is why `@_linked/server` is in\n // `SSR_ENTRY_PACKAGES` (vite-config.ts): the package's bare imports must go\n // through Vite as well, or some of its files evaluate once per loader.\n const ServerClass = (\n await vite.ssrLoadModule('@_linked/server/shapes/LinkedServer')\n ).LinkedServer;\n\n const server = new (ServerClass as any)(linkedConfig);\n\n // Surface stack traces from Vite ssrLoadModule failures cleanly.\n process.on('unhandledRejection', (err: any) => {\n if (err && err.stack) {\n try {\n vite.ssrFixStacktrace(err);\n } catch {\n // ignore\n }\n }\n console.error(err);\n });\n\n await server.start();\n\n // Watcher → onSourceChange wiring.\n //\n // Discover workspace packages once at boot. On each change, look up\n // which workspace package the file belongs to and call onSourceChange\n // with that package's npm name. LinkedServer disposes the old providers,\n // re-imports via vite.ssrLoadModule (transparent because Vite invalidated\n // the module already), and re-instantiates. No process restart.\n const workspacePackages = await discoverWorkspacePackages(cwd);\n if (workspacePackages.length > 0) {\n console.log(\n `[linked] watching ${workspacePackages.length} workspace packages for HMR`,\n );\n }\n // Reloads are DEBOUNCED and SERIALISED. `onSourceChange` disposes a\n // package's providers and re-registers their express routes, i.e. it mutates\n // the shared router stack. Firing it per file change (a multi-file save, a\n // format-on-save, a branch switch) ran overlapping dispose/re-register\n // cycles against that same stack with nothing ordering them. Collect the\n // affected packages over a short window, then run the cycles one at a time.\n const RELOAD_DEBOUNCE_MS = 150;\n const pendingReloads = new Set<string>();\n let reloadTimer: NodeJS.Timeout | undefined;\n // Tail of the reload chain — each flush appends, so cycles never interleave.\n let reloadChain: Promise<void> = Promise.resolve();\n\n const flushReloads = () => {\n const pkgs = [...pendingReloads];\n pendingReloads.clear();\n reloadChain = reloadChain.then(async () => {\n for (const pkg of pkgs) {\n try {\n await (server as any).onSourceChange(pkg);\n } catch (err: any) {\n console.warn(\n `[linked] reload of ${pkg} failed: ${err?.message ?? err}`,\n );\n }\n }\n });\n };\n\n vite.watcher.on('change', (filepath: string) => {\n if (!/\\.(tsx?|jsx?)$/.test(filepath)) return;\n const pkg = workspacePackageForPath(filepath, workspacePackages);\n if (!pkg) return;\n if (typeof (server as any).onSourceChange !== 'function') return;\n pendingReloads.add(pkg);\n clearTimeout(reloadTimer);\n reloadTimer = setTimeout(flushReloads, RELOAD_DEBOUNCE_MS);\n });\n\n // r/o keyboard shortcuts.\n const port = (linkedConfig.server as any).port ?? opts.port ?? 4040;\n installShortcuts({\n url: `http://localhost:${port}/`,\n onRestart: restartProcess,\n });\n}\n"]}
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../../../src/commands/start.ts"],"names":[],"mappings":"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","sourcesContent":["// `linked start --vite` orchestrator.\n//\n// Follows the existing startServer() flow from cli-methods.ts but injects\n// a Vite dev server in middleware mode + overrides loadAppComponent /\n// loadRoutes to use vite.ssrLoadModule. This means LinkedServer's existing\n// initialization works unchanged; we just route module loading through\n// Vite instead of loading modules through Node directly.\n//\n// What's different vs the plain startServer():\n// - LinkedServer renders through the Vite middleware when viteMiddleware is set\n// - Vite handles the client transform + HMR\n// - ssrLoadModule handles the server transform (decorators, jsx, ts)\n// - Server changes still need full process restart for now (server HMR\n// deferred to vite-node migration)\nimport path from 'node:path';\nimport fs from 'node:fs/promises';\nimport {spawn} from 'node:child_process';\nimport {importFile, isPathInside} from '../utils/platform.js';\nimport fsExtra from 'fs-extra';\nimport {parseWorkspacePatterns, isWorkspacePathNegated} from '../workspace-globs.js';\n\nimport type {InlineConfig, UserConfigExport, ViteDevServer} from 'vite';\n\nexport interface StartOptions {\n env?: string;\n port?: number;\n /**\n * Serve only the backend API (`/call/...`, `/api/...`, provider routes).\n * No `vite.config.*`, `src/App.tsx` or `src/routes.tsx` is needed, and page\n * requests get a 404 instead of server-side rendering.\n */\n apiOnly?: boolean;\n}\n\nexport const VITE_CONFIG_FILES = ['vite.config.ts', 'vite.config.js', 'vite.config.mjs'];\n\n/**\n * Names for the app's linked config, in priority order. `lincd.config.js` is\n * the legacy name: apps predating the rename still ship it, and dropping it\n * would silently discard their whole `server` config (cachePaths, `apiOnly`, …).\n */\nexport const LINKED_CONFIG_FILES = ['linked.config.js', 'lincd.config.js'];\n\n/**\n * Absolute path to the app's linked config. Returns the first name that exists;\n * when none does, the current name — the caller still `existsSync`-guards the\n * import, so this is simply the \"no config here\" path, not a promise of a file.\n */\nexport function resolveLinkedConfigPath(cwd: string): string {\n return (\n LINKED_CONFIG_FILES.map((name) => path.join(cwd, name)).find((candidate) =>\n fsExtra.existsSync(candidate),\n ) ?? path.join(cwd, LINKED_CONFIG_FILES[0])\n );\n}\n\n/**\n * API-only mode is explicit: `linked start --api-only`, or `server.apiOnly: true`\n * in `linked.config.js`. It is never inferred from missing frontend files, so a\n * web app that lost its `vite.config.ts` still fails loudly instead of silently\n * serving no pages.\n */\nexport function isApiOnly(opts: StartOptions, linkedConfig: any): boolean {\n return opts.apiOnly === true || linkedConfig?.server?.apiOnly === true;\n}\n\n/**\n * The Vite dev-server config for `linked start`.\n *\n * With a `vite.config.*` in `cwd`, Vite loads it itself. Without one, API-only\n * mode uses `createViteConfig()`'s defaults inline — Vite is still needed on the\n * backend to transform TypeScript, decorators and extensionless imports of\n * source-only shape packages. Without one in page mode, it is an error.\n */\nexport async function resolveViteServerConfig(\n cwd: string,\n apiOnly: boolean,\n): Promise<InlineConfig> {\n const base: InlineConfig = {\n root: cwd,\n server: {middlewareMode: true},\n appType: 'custom',\n };\n if (VITE_CONFIG_FILES.some((c) => fsExtra.existsSync(path.join(cwd, c)))) {\n return base;\n }\n if (!apiOnly) {\n throw new Error(\n `[linked start] no vite.config.{ts,js,mjs} found in ${cwd}. Add one:\\n\\n import {createViteConfig} from '@_linked/cli/vite-config';\\n export default createViteConfig({port: 4040, cssMode: 'tailwind'});\\n\\nFor a backend without a web frontend, run \\`linked start --api-only\\` instead.\\n`,\n );\n }\n const {createViteConfig} = await import('../vite-config.js');\n const exported: UserConfigExport = createViteConfig();\n const defaults =\n typeof exported === 'function'\n ? await exported({command: 'serve', mode: 'development'})\n : await exported;\n return {\n ...defaults,\n ...base,\n configFile: false,\n server: {...defaults.server, ...base.server},\n // No browser client: skip the client dependency scan, whose entry\n // (`src/index.tsx`) does not exist in a backend.\n optimizeDeps: {...defaults.optimizeDeps, noDiscovery: true},\n };\n}\n\n/**\n * Inject Vite into LinkedServer's config:\n * - vite: handle for ssrLoadModule (used to load app's backend.ts via self-reference)\n * and, unless API-only (where `apiOnly` makes LinkedServer skip page rendering):\n * - viteMiddleware: mounted as the dev-server middleware\n * - loadAppComponent / loadRoutes: route through vite.ssrLoadModule for SSR transform\n * - viteSsrPreload: page modules to preload for SSR CSS collection\n */\nexport function configureLinkedServer(\n serverConfig: any,\n vite: Pick<ViteDevServer, 'middlewares' | 'ssrLoadModule'>,\n cwd: string,\n apiOnly: boolean,\n): void {\n serverConfig.vite = vite;\n if (apiOnly) {\n serverConfig.apiOnly = true;\n return;\n }\n serverConfig.viteMiddleware = vite.middlewares;\n serverConfig.loadAppComponent = async () => {\n const mod = await vite.ssrLoadModule('/src/App.tsx');\n return mod.default;\n };\n serverConfig.loadRoutes = async () => {\n return await vite.ssrLoadModule('/src/routes.tsx');\n };\n\n // Vite SSR CSS collection support:\n // List all `src/pages/*.{ts,tsx}` files so LinkedServer can ssrLoadModule\n // each into Vite's moduleGraph BEFORE the first render of a session.\n // React.lazy() doesn't auto-fire — without this, only App's eager\n // imports' CSS is collected; lazy pages' CSS arrives after hydration\n // causing an unstyled flash. After the first preload sweep, all\n // subsequent renders have full CSS available.\n serverConfig.viteSsrPreload = async () => {\n const pagesDir = path.join(cwd, 'src', 'pages');\n if (!fsExtra.existsSync(pagesDir)) return [];\n const files = fsExtra.readdirSync(pagesDir, {withFileTypes: true});\n const paths: string[] = [];\n for (const file of files) {\n // Test files live beside pages but call vi.mock() at module scope,\n // which throws outside Vitest — never load them into the SSR graph.\n // `.d.ts` files are types only: they have no runtime module to load.\n if (\n file.isFile() &&\n /\\.(tsx|ts)$/.test(file.name) &&\n !/\\.(test|spec)\\.(tsx|ts)$/.test(file.name) &&\n !file.name.endsWith('.d.ts')\n ) {\n paths.push(`/src/pages/${file.name}`);\n }\n }\n return paths;\n };\n}\n\ninterface WorkspacePackage {\n name: string;\n root: string;\n srcDir: string;\n}\n\n/**\n * Discover the packages whose sources `linked start` watches for HMR, from two\n * sources. No hand-maintained list anywhere.\n *\n * 1. The app's `package.json` `workspaces` field — adding a new linked package\n * = appearing in the right glob.\n * 2. The app's linked dependencies that are installed as SOURCE — the same rule\n * the Vite resolver table uses (`discoverLinkedSourceDependencies`), so the\n * two lists cannot disagree about what is source. This covers a LOCALIZED\n * checkout (`packages-local/<pkg>`), which is deliberately in no workspace\n * glob and reachable only through its `node_modules` symlink. Without it\n * `workspacePackageForPath` returns null for the checkout, so a saved backend\n * edit is reloaded by Vite and then never re-indexed: the registered provider\n * instance is never replaced.\n *\n * Returns each package's npm `name` (so we can call `onSourceChange(name)`), its\n * absolute root, and its `src/` directory for fast prefix matching. Dependency\n * roots are realpathed by the shared discovery, matching the ids Vite reports.\n */\nexport async function discoverWorkspacePackages(cwd: string): Promise<WorkspacePackage[]> {\n const pkgJsonPath = path.join(cwd, 'package.json');\n if (!(await fsExtra.pathExists(pkgJsonPath))) return [];\n const pkgJson = await fsExtra.readJson(pkgJsonPath);\n const {patterns, negatedPatterns} = parseWorkspacePatterns(pkgJson.workspaces);\n const out: WorkspacePackage[] = [];\n\n // Include the root app itself so edits to <cwd>/src/* trigger HMR for\n // the app's own providers (e.g. CN's src/backend.ts which registers ~25\n // Express routes).\n if (pkgJson.name && (await fsExtra.pathExists(path.join(cwd, 'src')))) {\n out.push({name: pkgJson.name, root: cwd, srcDir: path.join(cwd, 'src')});\n }\n for (const glob of patterns) {\n // Positive patterns are expanded by directory listing rather than with a\n // full glob library, so only a trailing /* is honoured. Negated entries\n // (\"!packages/core\") are honoured in full — watching an excluded directory\n // would trigger HMR for a package the app does not actually resolve.\n const m = glob.match(/^(.+?)\\/\\*$/);\n const candidates: string[] = [];\n if (m) {\n const parent = path.join(cwd, m[1]);\n if (await fsExtra.pathExists(parent)) {\n const entries = await fs.readdir(parent, {withFileTypes: true});\n for (const dirent of entries) {\n if (dirent.isDirectory() || dirent.isSymbolicLink()) {\n candidates.push(path.join(parent, dirent.name));\n }\n }\n }\n } else {\n candidates.push(path.join(cwd, glob));\n }\n for (const root of candidates) {\n const rel = path.relative(cwd, root).split(path.sep).join('/');\n if (isWorkspacePathNegated(rel, negatedPatterns)) continue;\n const pkgPath = path.join(root, 'package.json');\n if (!(await fsExtra.pathExists(pkgPath))) continue;\n try {\n const sub = await fsExtra.readJson(pkgPath);\n if (sub.name) {\n out.push({name: sub.name, root, srcDir: path.join(root, 'src')});\n }\n } catch {\n // ignore broken package.json\n }\n }\n }\n\n // Linked deps installed as source, realpathed — a localized checkout is here\n // and nowhere else. Imported lazily because vite-config pulls in Vite itself.\n const {discoverLinkedSourceDependencies} = await import('../vite-config.js');\n const names = new Set(out.map((p) => p.name));\n for (const entry of await discoverLinkedSourceDependencies(cwd)) {\n if (names.has(entry.name)) continue;\n // Only working copies. Some PUBLISHED packages ship `src/` in their tarball,\n // so the resolver registers them (it serves that source) — but they stay\n // inside `node_modules`, which Vite's watcher ignores, so no change event\n // can ever match them. Listing them would inflate the count printed at boot\n // with packages nothing watches. A localized checkout, a workspace clone and\n // an `npm link` all realpath to a directory outside `node_modules`.\n if (isInsideNodeModules(entry.srcDir)) continue;\n names.add(entry.name);\n out.push({name: entry.name, root: path.dirname(entry.srcDir), srcDir: entry.srcDir});\n }\n return out;\n}\n\nfunction isInsideNodeModules(p: string): boolean {\n return p.split(path.sep).includes('node_modules');\n}\n\nfunction workspacePackageForPath(\n filepath: string,\n pkgs: WorkspacePackage[],\n): string | null {\n for (const p of pkgs) {\n // The watcher's path may use `/` on Windows, and differ in case there.\n if (isPathInside(filepath, p.srcDir)) {\n return p.name;\n }\n }\n return null;\n}\n\n/**\n * The command that opens `url` in the default browser. Windows' `start` is a\n * cmd.exe built-in, not a program, so there it is `explorer.exe <url>`.\n */\nexport function browserCommand(\n url: string,\n platform: NodeJS.Platform = process.platform,\n): {command: string; args: string[]} {\n if (platform === 'darwin') return {command: 'open', args: [url]};\n if (platform === 'win32') return {command: 'explorer.exe', args: [url]};\n return {command: 'xdg-open', args: [url]};\n}\n\nfunction openBrowser(url: string): void {\n const {command, args} = browserCommand(url);\n const child = spawn(command, args, {detached: true, stdio: 'ignore'});\n // A missing opener must not take the dev server down.\n child.on('error', (e) => console.warn(`[linked] could not open ${url}: ${e.message}`));\n child.unref();\n}\n\nfunction installShortcuts(opts: {url: string; onRestart: () => void}): void {\n if (!process.stdin.isTTY) return;\n let buf = '';\n try {\n process.stdin.setRawMode(true);\n } catch {\n return;\n }\n process.stdin.resume();\n process.stdin.setEncoding('utf8');\n const cleanup = () => {\n try {\n process.stdin.setRawMode(false);\n } catch {}\n };\n process.on('exit', cleanup);\n process.stdin.on('data', (chunk: string) => {\n for (const ch of chunk) {\n // Ctrl-C → graceful exit, restore terminal first.\n if (ch === '\u0003') {\n cleanup();\n process.exit(0);\n }\n if (ch === '\\r' || ch === '\\n') {\n const cmd = buf.trim();\n buf = '';\n if (cmd === 'r') {\n console.log('[linked] restarting…');\n opts.onRestart();\n } else if (cmd === 'o') {\n console.log(`[linked] opening ${opts.url}`);\n openBrowser(opts.url);\n }\n } else {\n buf += ch;\n }\n }\n });\n console.log(\n `[linked] press r<enter> to restart · o<enter> to open ${opts.url}`,\n );\n}\n\nfunction restartProcess(): void {\n // nodemon-style respawn: launch a fresh process from the same argv,\n // then exit. The new process inherits stdio so the dev experience is\n // continuous.\n const [node, ...argv] = process.argv;\n const child = spawn(node, argv, {\n stdio: 'inherit',\n detached: true,\n env: process.env,\n });\n child.unref();\n process.exit(0);\n}\n\nexport async function startWithVite(opts: StartOptions = {}): Promise<void> {\n const cwd = process.cwd();\n\n // Load the app's own `.env` (Node 20.12+ `process.loadEnvFile`) if present — the\n // standard, dependency-free env source for a linked app. Node does NOT override\n // vars already set in the environment, so CN's injected per-(project,branch) vars\n // (PORT, FUSEKI_DATASET, CN_APP_ADMIN_SECRET, …) take precedence over the file.\n try {\n const envPath = path.join(cwd, '.env');\n if (\n (await fsExtra.pathExists(envPath)) &&\n typeof (process as {loadEnvFile?: (p: string) => void}).loadEnvFile === 'function'\n ) {\n (process as {loadEnvFile: (p: string) => void}).loadEnvFile(envPath);\n }\n } catch {\n // best-effort — a missing/invalid .env never blocks start\n }\n\n // `--env` still loads env-cmd (`.env-cmdrc.json`) for CN's own start:local flow.\n const {ensureEnvironmentLoaded} = await import('../lifecycle.js');\n await ensureEnvironmentLoaded();\n\n // Load user's linked.config.js (legacy hook). It still drives things\n // like server.cachePaths and the rest of LinkedServer's options.\n const linkedConfigPath = resolveLinkedConfigPath(cwd);\n let linkedConfig: any = {};\n if (fsExtra.existsSync(linkedConfigPath)) {\n linkedConfig = (await importFile(linkedConfigPath)).default ?? {};\n }\n linkedConfig.server = linkedConfig.server || {};\n const apiOnly = isApiOnly(opts, linkedConfig);\n\n const {createServer: createViteServer} = await import('vite');\n const vite = await createViteServer(await resolveViteServerConfig(cwd, apiOnly));\n configureLinkedServer(linkedConfig.server, vite, cwd, apiOnly);\n\n // Load the storage config through Vite SSR so it\n // configures the SAME LinkedStorage instance the rest of the SSR graph\n // (LinkedServer, CN providers) uses. Replaces the former Node-direct\n // `loadBackendStorageConfig()` (which resolved @_linked/core via the\n // `default`→lib condition, a SEPARATE instance). Safe now that core's lib\n // `initTree` is idempotent. `loadBackendStorageConfig` stays in\n // lifecycle.ts for the Node-only CLI commands (`script`/`call`) that have no\n // Vite server (contract C5).\n // The first two names are current; the rest are legacy filenames kept so\n // older apps that never renamed their storage config still start.\n for (const rel of [\n '/linked.backend.storage.ts',\n '/linked.backend.storage.js',\n '/backend-storage-config.ts',\n '/backend-storage-config.js',\n '/scripts/backend-storage-config.ts',\n '/scripts/backend-storage-config.js',\n '/scripts/storage-config.js',\n ]) {\n if (fsExtra.existsSync(path.join(cwd, rel.slice(1)))) {\n await vite.ssrLoadModule(rel);\n break;\n }\n }\n\n // Load LinkedServer through Vite SSR so it shares the SAME\n // module instances as everything else in the SSR call graph. Without\n // this, LinkedServer is loaded by Node (→ lib/esm) while CN's App.tsx +\n // its transitive imports are loaded by Vite (→ src/). React contexts\n // created in one tree don't reach consumers in the other, causing\n // \"Cannot destructure property 'isNativeApp' of useAppContext()\" type\n // errors on every SSR render.\n // Loading this entry through Vite is why `@_linked/server` is in\n // `SSR_ENTRY_PACKAGES` (vite-config.ts): the package's bare imports must go\n // through Vite as well, or some of its files evaluate once per loader.\n const ServerClass = (\n await vite.ssrLoadModule('@_linked/server/shapes/LinkedServer')\n ).LinkedServer;\n\n const server = new (ServerClass as any)(linkedConfig);\n\n // Surface stack traces from Vite ssrLoadModule failures cleanly.\n process.on('unhandledRejection', (err: any) => {\n if (err && err.stack) {\n try {\n vite.ssrFixStacktrace(err);\n } catch {\n // ignore\n }\n }\n console.error(err);\n });\n\n await server.start();\n\n // Watcher → onSourceChange wiring.\n //\n // Discover workspace packages once at boot. On each change, look up\n // which workspace package the file belongs to and call onSourceChange\n // with that package's npm name. LinkedServer disposes the old providers,\n // re-imports via vite.ssrLoadModule (transparent because Vite invalidated\n // the module already), and re-instantiates. No process restart.\n const workspacePackages = await discoverWorkspacePackages(cwd);\n if (workspacePackages.length > 0) {\n console.log(\n `[linked] watching ${workspacePackages.length} workspace packages for HMR`,\n );\n }\n // Reloads are DEBOUNCED and SERIALISED. `onSourceChange` disposes a\n // package's providers and re-registers their express routes, i.e. it mutates\n // the shared router stack. Firing it per file change (a multi-file save, a\n // format-on-save, a branch switch) ran overlapping dispose/re-register\n // cycles against that same stack with nothing ordering them. Collect the\n // affected packages over a short window, then run the cycles one at a time.\n const RELOAD_DEBOUNCE_MS = 150;\n const pendingReloads = new Set<string>();\n let reloadTimer: NodeJS.Timeout | undefined;\n // Tail of the reload chain — each flush appends, so cycles never interleave.\n let reloadChain: Promise<void> = Promise.resolve();\n\n const flushReloads = () => {\n const pkgs = [...pendingReloads];\n pendingReloads.clear();\n reloadChain = reloadChain.then(async () => {\n for (const pkg of pkgs) {\n try {\n await (server as any).onSourceChange(pkg);\n } catch (err: any) {\n console.warn(\n `[linked] reload of ${pkg} failed: ${err?.message ?? err}`,\n );\n }\n }\n });\n };\n\n vite.watcher.on('change', (filepath: string) => {\n if (!/\\.(tsx?|jsx?)$/.test(filepath)) return;\n const pkg = workspacePackageForPath(filepath, workspacePackages);\n if (!pkg) return;\n if (typeof (server as any).onSourceChange !== 'function') return;\n pendingReloads.add(pkg);\n clearTimeout(reloadTimer);\n reloadTimer = setTimeout(flushReloads, RELOAD_DEBOUNCE_MS);\n });\n\n // r/o keyboard shortcuts.\n const port = (linkedConfig.server as any).port ?? opts.port ?? 4040;\n installShortcuts({\n url: `http://localhost:${port}/`,\n onRestart: restartProcess,\n });\n}\n"]}
@@ -16,15 +16,6 @@ export declare function readInstalledPkg(name: string, fromDir: string): Promise
16
16
  root: string;
17
17
  json: any;
18
18
  } | null>;
19
- /**
20
- * {@link readInstalledPkg}, synchronously, for callers on a hot path that must
21
- * not go async (the one-copy check before every `linked start`). Same walk,
22
- * same stop at the workspace root.
23
- */
24
- export declare function readInstalledPkgSync(name: string, fromDir: string): {
25
- root: string;
26
- json: any;
27
- } | null;
28
19
  /**
29
20
  * THE definition of a linked package: its own `package.json` says
30
21
  * `"linkedPackage": true`. Not its npm scope — a linked package can be
@@ -49,10 +40,11 @@ export interface InstalledLinkedPackage {
49
40
  *
50
41
  * Walked breadth-first and keyed on the installed directory, not the name, so
51
42
  * the app's own copy of a package is settled before any copy a dependency
52
- * installed for itself. A localized checkout's own `node_modules` holds a
53
- * published copy of any sibling it depends on; keyed on the name and walked
54
- * depth-first, reaching that copy first hid the app's localized checkout of
55
- * it. The same name can therefore appear more than once, once per copy.
43
+ * installed for itself. A checkout's own `node_modules` can hold a
44
+ * published copy of a sibling it depends on (npm nests one when the sibling's
45
+ * checkout misses its range); keyed on the name and walked depth-first,
46
+ * reaching that copy first hid the app's checkout of it. The same name can
47
+ * therefore appear more than once, once per copy.
56
48
  */
57
49
  export declare function discoverInstalledLinkedPackages(cwd?: string): Promise<InstalledLinkedPackage[]>;
58
50
  //# sourceMappingURL=installed-packages.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"installed-packages.d.ts","sourceRoot":"","sources":["../../src/installed-packages.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAM,EAA+B,CAAC;AAC3E,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,KAAG,OACM,CAAC;AAUrD,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOnE;AAED,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,GAAG,CAAA;CAAC,GAAG,IAAI,CAAC,CAgB3C;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,GAAG,CAAA;CAAC,GAAG,IAAI,CAgBlC;AAWD;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,GAAI,MAAM,GAAG,KAAG,OAClB,CAAC;AAE/B,wFAAwF;AACxF,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,GAAG,CAAC;CACX;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,+BAA+B,CACnD,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,sBAAsB,EAAE,CAAC,CA+BnC"}
1
+ {"version":3,"file":"installed-packages.d.ts","sourceRoot":"","sources":["../../src/installed-packages.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAM,EAA+B,CAAC;AAC3E,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,KAAG,OACM,CAAC;AAUrD,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOnE;AAED,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,GAAG,CAAA;CAAC,GAAG,IAAI,CAAC,CAgB3C;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,GAAI,MAAM,GAAG,KAAG,OAClB,CAAC;AAE/B,wFAAwF;AACxF,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,GAAG,CAAC;CACX;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,+BAA+B,CACnD,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,sBAAsB,EAAE,CAAC,CA+BnC"}
@@ -10,7 +10,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  // Locating installed packages the way Node does, shared by the Vite config
11
11
  // helper and `linked app-doctor`.
12
12
  import fsExtra from 'fs-extra';
13
- import fs from 'node:fs';
14
13
  import path from 'node:path';
15
14
  /**
16
15
  * Framework packages that MUST be single-instance per runtime — they hold
@@ -65,39 +64,6 @@ export function readInstalledPkg(name, fromDir) {
65
64
  }
66
65
  });
67
66
  }
68
- /**
69
- * {@link readInstalledPkg}, synchronously, for callers on a hot path that must
70
- * not go async (the one-copy check before every `linked start`). Same walk,
71
- * same stop at the workspace root.
72
- */
73
- export function readInstalledPkgSync(name, fromDir) {
74
- let dir = path.resolve(fromDir);
75
- while (true) {
76
- const root = path.join(dir, 'node_modules', name);
77
- const pkgJson = path.join(root, 'package.json');
78
- if (fs.existsSync(pkgJson)) {
79
- try {
80
- return { root, json: JSON.parse(fs.readFileSync(pkgJson, 'utf8')) };
81
- }
82
- catch (_a) {
83
- return null;
84
- }
85
- }
86
- const parent = path.dirname(dir);
87
- if (parent === dir || isWorkspaceRootSync(dir))
88
- return null;
89
- dir = parent;
90
- }
91
- }
92
- function isWorkspaceRootSync(dir) {
93
- try {
94
- return !!JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf8'))
95
- .workspaces;
96
- }
97
- catch (_a) {
98
- return false;
99
- }
100
- }
101
67
  /**
102
68
  * THE definition of a linked package: its own `package.json` says
103
69
  * `"linkedPackage": true`. Not its npm scope — a linked package can be
@@ -115,10 +81,11 @@ export const isLinkedPackageJson = (json) => (json === null || json === void 0 ?
115
81
  *
116
82
  * Walked breadth-first and keyed on the installed directory, not the name, so
117
83
  * the app's own copy of a package is settled before any copy a dependency
118
- * installed for itself. A localized checkout's own `node_modules` holds a
119
- * published copy of any sibling it depends on; keyed on the name and walked
120
- * depth-first, reaching that copy first hid the app's localized checkout of
121
- * it. The same name can therefore appear more than once, once per copy.
84
+ * installed for itself. A checkout's own `node_modules` can hold a
85
+ * published copy of a sibling it depends on (npm nests one when the sibling's
86
+ * checkout misses its range); keyed on the name and walked depth-first,
87
+ * reaching that copy first hid the app's checkout of it. The same name can
88
+ * therefore appear more than once, once per copy.
122
89
  */
123
90
  export function discoverInstalledLinkedPackages() {
124
91
  return __awaiter(this, arguments, void 0, function* (cwd = process.cwd()) {
@@ -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 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"]}
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 * 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 checkout's own `node_modules` can hold a\n * published copy of a sibling it depends on (npm nests one when the sibling's\n * checkout misses its range); keyed on the name and walked depth-first,\n * reaching that copy first hid the app's checkout of it. The same name can\n * 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"]}
@@ -66,11 +66,10 @@ export interface LocalPackage extends PackageDetails {
66
66
  hasBuildScript: boolean;
67
67
  }
68
68
  /**
69
- * Directory holding localized checkouts (`linked localize`). It is
70
- * deliberately in NO workspace glob — that is the whole point of the design,
71
- * since npm learning about these checkouts is what made their predecessor
72
- * under `packages/` a trap — so any walk of `workspaces` alone cannot see it
73
- * and has to be told about it separately.
69
+ * Directory holding localized checkouts (`linked localize`). An app set up by
70
+ * `linked localize` lists `packages-local/*` in its `workspaces`, so a walk of
71
+ * the globs finds them as workspace members; it is still walked on its own for
72
+ * an app that has not been set up yet (no glob, or no `workspaces` at all).
74
73
  */
75
74
  export declare const LOCAL_PACKAGES_DIR = "packages-local";
76
75
  /**
@@ -93,8 +92,10 @@ export declare function getLincdPackages(rootPath?: string): PackageDetails[];
93
92
  *
94
93
  * Two sources, because the workspace globs are not the whole picture any more:
95
94
  *
96
- * 1. the `workspaces` field (negations honoured — see ./workspace-globs.js);
97
- * 2. `packages-local/`, the localized checkouts, which is in no glob.
95
+ * 1. the `workspaces` field (negations honoured — see ./workspace-globs.js),
96
+ * which includes `packages-local/*` in an app set up for localizing;
97
+ * 2. `packages-local/`, the localized checkouts, for an app whose globs do
98
+ * not reach it. A checkout a glob already found is not added twice.
98
99
  *
99
100
  * Nothing is filtered out here. Callers decide what they can act on and are
100
101
  * expected to SAY what they skipped and why.
@@ -104,11 +105,9 @@ export declare function discoverLocalPackages(rootPath?: string, options?: {
104
105
  localPackagesDir?: string;
105
106
  }): LocalPackage[];
106
107
  /**
107
- * The package names recorded in the app's `local-packages.json` — what
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.
108
+ * The names of the app's localized checkouts — every directory in
109
+ * `packages-local/` with a named `package.json` (localize/members.ts). Nothing
110
+ * there is simply "nothing localized".
112
111
  */
113
112
  export declare function localizedPackageNames(appRootPath: string): string[];
114
113
  /** A package `build-all` found but will not build, and why not. */
@@ -124,31 +123,45 @@ export interface BuildAllPlan {
124
123
  }
125
124
  /** The package whose `linked` bin the other packages' build scripts run. */
126
125
  export declare const BUILD_TOOL_PACKAGE = "@_linked/cli";
126
+ /** Where `build-all` starts: everything in the groups before it is passed over. */
127
+ export type BuildToolStart = 'pre' | 'tool' | 'rest';
127
128
  /** How `build-all` orders the build tool against everything else. */
128
129
  export interface BuildToolOrder {
130
+ /**
131
+ * What the build tool depends on, transitively, among the packages to build
132
+ * (a localized `@_linked/core`), in dependency order. Built before it.
133
+ */
134
+ pre: Map<string, PackageDetails>;
129
135
  /** The build tool, when it is among the packages to build. */
130
136
  tool?: PackageDetails;
131
- /** Whether to build `tool` now, alone, before anything else starts. */
132
- buildToolFirst: boolean;
133
137
  /** Everything else, built afterwards in dependency order. */
134
138
  rest: Map<string, PackageDetails>;
135
- /** The `--from` to apply to `rest`: cleared once it has been reached at the tool. */
139
+ /** The first group to build; the groups before it are passed over (`--from`). */
140
+ start: BuildToolStart;
141
+ /** The `--from` to apply inside `start` (`pre` or `rest`); unset when the build starts at its top. */
136
142
  from?: string;
137
143
  }
138
144
  /**
139
- * Take the build tool (`@_linked/cli`) out of the dependency-ordered build.
145
+ * Split the build around the build tool (`@_linked/cli`).
140
146
  *
141
147
  * Every other package's `build` script runs `linked build`, which is THIS
142
148
  * package's `lib/`. Built in parallel with them, its `rimraf ./lib` pulled that
143
149
  * `lib/` out from under their builds (`ENOENT …/lib/esm/installed-packages.js`),
144
150
  * and whatever was built before it ran a stale cli. So when it is in the set it
145
- * is built first and alone, and the rest only once it has succeeded.
146
- *
147
- * `--from` reads the tool as the first package in the order: `--from` the tool
148
- * builds it and then everything; `--from` anything else resumes past it, so it
149
- * is not rebuilt.
151
+ * is built alone, and the rest only once it has succeeded.
152
+ *
153
+ * It cannot be built FIRST, though: a localized `@_linked/core` it depends on
154
+ * must have its `lib/` before the tool's `tsc` runs. So the tool's own
155
+ * dependencies among the packages to build (`pre`, the transitive closure of
156
+ * `dependencies`) go before it, in dependency order. They build with the tool
157
+ * as it was before this run, which is what a fresh checkout's `npm run build`
158
+ * does too.
159
+ *
160
+ * `--from` reads the order as `pre`, then the tool, then `rest`: it resumes
161
+ * inside whichever group holds the package and passes over the groups before
162
+ * it. A name in none of them goes to `rest`, which reports it.
150
163
  */
151
- export declare function orderBuildToolFirst(packages: Map<string, PackageDetails>, from?: string): BuildToolOrder;
164
+ export declare function orderBuildToolFirst(packages: Map<string, PackageDetails>, from?: string, dependenciesOf?: (pkg: PackageDetails) => string[]): BuildToolOrder;
152
165
  /**
153
166
  * Decide what `build-all` builds.
154
167
  *
@@ -1 +1 @@
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,4EAA4E;AAC5E,eAAO,MAAM,kBAAkB,iBAAiB,CAAC;AAEjD,qEAAqE;AACrE,MAAM,WAAW,cAAc;IAC7B,8DAA8D;IAC9D,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,uEAAuE;IACvE,cAAc,EAAE,OAAO,CAAC;IACxB,6DAA6D;IAC7D,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAClC,qFAAqF;IACrF,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,EACrC,IAAI,CAAC,EAAE,MAAM,GACZ,cAAc,CAUhB;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;AAGpD;;;;;;;;;;;;;;;;;;;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;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,mBAAY,CAAC;AAE5C;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,SAAgB,GACvB,cAAc,EAAE,CAIlB;AAED;;;;;;;;;;;;;GAaG;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;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAEnE;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,4EAA4E;AAC5E,eAAO,MAAM,kBAAkB,iBAAiB,CAAC;AAEjD,mFAAmF;AACnF,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAErD,qEAAqE;AACrE,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACjC,8DAA8D;IAC9D,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,6DAA6D;IAC7D,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAClC,iFAAiF;IACjF,KAAK,EAAE,cAAc,CAAC;IACtB,sGAAsG;IACtG,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAOD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,EACrC,IAAI,CAAC,EAAE,MAAM,EACb,cAAc,GAAE,CAAC,GAAG,EAAE,cAAc,KAAK,MAAM,EAAyB,GACvE,cAAc,CA6BhB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,QAAQ,SAAO,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,YAAY,CAkD5E"}