@_linked/cli 1.46.2 → 1.47.1

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 +44 -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 +168 -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 +48 -189
  88. package/lib/esm/localize/list.js.map +1 -1
  89. package/lib/esm/localize/localize.d.ts +41 -62
  90. package/lib/esm/localize/localize.d.ts.map +1 -1
  91. package/lib/esm/localize/localize.js +398 -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 -182
  153. package/lib/esm/localize/prune.d.ts.map +0 -1
  154. package/lib/esm/localize/prune.js +0 -703
  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 -181
  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
@@ -1 +1 @@
1
- {"version":3,"file":"localize.js","sourceRoot":"","sources":["../../../src/localize/localize.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `localize` -- turn an npm-installed dependency into an editable git checkout.\n *\n * The loop, in five steps, none of which involve npm learning anything:\n *\n * 1. npm name -> registry `repository` (see resolve.ts)\n * 2. `git clone` into `<dir>/<name>`\n * 3. **`npm install` INSIDE the checkout**, then prune it (`ensure`)\n * 4. `fs.symlink` node_modules/<name> -> the checkout\n * 5. record it in a gitignored manifest\n *\n * `adopt` (adopt.ts) enters at step 3 with a checkout that is already there,\n * and shares everything from there on: `forEachName` and `installLinkAndRecord`\n * below.\n *\n * Step 3 is the one that is easy to \"simplify\" and must not be. Installing\n * from the parent instead -- `npm install <path> --no-save` -- hard-failed an\n * app's boot on a missing peer dependency, because module resolution happens\n * from the symlink's REAL path, whose ancestors have no `node_modules`. The\n * checkout needs its own installed tree. `tests/unit/localize/real-localize.test.ts` runs a\n * real clone and a real install and asserts the dependency landed inside the\n * checkout, so a reimplementation that moves the install back out fails there.\n *\n * A clone, not a copy: a published tarball has no `src/`, so copying the\n * installed package cannot give you something to edit.\n *\n * What localize NEVER does: run an install at the consumer root, or edit\n * `package-lock.json`, `.gitignore`, `workspaces`, dependencies or any\n * bundler config. It asserts the work did not touch `package.json` or\n * `package-lock.json` before exiting 0.\n *\n * The one deliberate edit, made after that assertion: when a run records a\n * package, the app's `postinstall` and `dependencies` scripts get\n * `linked localize --relink` if they lack it (`../utils/relinkHooks.ts`\n * explains why npm needs both). Without them the next npm command silently\n * undoes the link this run just made.\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport {\n EXIT_INSTALL_FAILED,\n EXIT_NOT_FOUND,\n EXIT_MANIFEST_DIRTY,\n EXIT_REFUSED,\n EXIT_WARNED,\n LocalizeError,\n} from './errors.js';\nimport {\n DEFAULT_DIR,\n SCHEMA_VERSION,\n readManifest,\n writeManifest,\n} from './manifest.js';\nimport type {ManifestEntry} from './manifest.js';\nimport type {Deps} from './run.js';\nimport {checkoutNameFor, resolvePackage} from './resolve.js';\nimport {pruneProvided, shouldPrune} from './prune.js';\nimport {ensure} from './ensure.js';\nimport type {PruneOptions} from './prune.js';\nimport {ensureRelinkHooksInFile, RELINK_COMMAND} from '../utils/relinkHooks.js';\nimport {\n diffManifests,\n isGitCheckout,\n isInside,\n isSymlink,\n readJson,\n snapshotManifests,\n writeLink,\n} from './fsops.js';\n\n/**\n * @param {string[]} names full npm package names\n * @param {object} opts `{force, dir, repo, subdir, build, prune}` -- `prune`\n * defaults to true; see prune.ts\n * @param {object} deps `{appRoot, run, log, warn, error}`\n * @returns {number} the process exit code: the HIGHEST of the per-name codes,\n * since each name is atomic and a failure on name 2 does not undo name 1.\n */\nexport interface LocalizeOptions extends PruneOptions {\n force?: boolean;\n /** Where checkouts live, relative to the app root (default `packages-local`). */\n dir?: string;\n repo?: string;\n subdir?: string;\n /** Run in the checkout after installing; absent or empty runs nothing. */\n build?: string;\n}\n\n/** What one name's work returns to the shared loop. */\nexport interface OneResult {\n code: number;\n entry?: {name: string; value: ManifestEntry};\n}\n\nexport type OneName = (\n name: string,\n dir: string,\n recorded: ManifestEntry | undefined,\n opts: LocalizeOptions,\n deps: Deps,\n) => OneResult;\n\nexport function localize(\n names: string[],\n opts: LocalizeOptions,\n deps: Deps,\n): number {\n return forEachName(names, opts, deps, localizeOne);\n}\n\n/**\n * The loop `localize` and `adopt` share: read the manifest once, run `one` per\n * name, write the manifest after each, then assert the links and the\n * consumer's untouched manifests.\n *\n * @param {(name: string, dir: string, recorded: object|undefined, opts: object, deps: object)\n * => {code: number, entry?: {name: string, value: object}}} one\n */\nexport function forEachName(\n names: string[],\n opts: LocalizeOptions,\n deps: Deps,\n one: OneName,\n): number {\n // Taken BEFORE anything runs: the post-condition is about what THIS run\n // changed, not about what the tree looked like at HEAD.\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 = opts.dir ?? manifest.dir ?? DEFAULT_DIR;\n const entries = {...manifest.entries};\n let code = 0;\n let recorded = false;\n\n for (const name of names) {\n try {\n const result = one(name, dir, entries[name], opts, deps);\n if (result.entry) {\n entries[result.entry.name] = result.entry.value;\n recorded = true;\n }\n code = Math.max(code, result.code);\n // Written after EACH name, so an interruption keeps what already worked.\n writeManifest(deps.appRoot, {\n version: SCHEMA_VERSION,\n dir,\n packages: entries,\n });\n } catch (e) {\n code = Math.max(code, reportError(e, deps));\n }\n }\n\n // Over EVERY localized checkout, not just the ones named: localizing `B`\n // is what makes `A`'s registry copy of `B` redundant.\n if (shouldPrune(opts)) {\n try {\n pruneProvided(entries, opts, deps);\n } catch (e) {\n deps.warn(\n `[localize] pruning failed, the checkouts' node_modules are as npm left them: ${e.message}`,\n );\n code = Math.max(code, EXIT_WARNED);\n }\n }\n\n code = Math.max(code, assertLinked(entries, deps));\n code = Math.max(code, assertManifestsUntouched(before, deps));\n // After the assertion, so it still covers everything the work itself did.\n if (recorded) ensureRelinkHooksIn(deps);\n return code;\n}\n\n/** Add the relink hooks to the app's package.json when it lacks them. See relinkHooks.ts. */\nfunction ensureRelinkHooksIn(deps: Deps): void {\n const added = ensureRelinkHooksInFile(\n path.join(deps.appRoot, 'package.json'),\n );\n if (!added.length) return;\n deps.log(\n `[localize] Added \\`${RELINK_COMMAND}\\` to the app's ${added.join(' and ')} ` +\n `script${added.length > 1 ? 's' : ''} so npm keeps the links`,\n );\n}\n\nfunction localizeOne(\n name: string,\n dir: string,\n recorded: ManifestEntry | undefined,\n opts: LocalizeOptions,\n deps: Deps,\n): OneResult {\n // An override recorded by an earlier run is reused, so `--repo` is a\n // one-time cost rather than something to remember on every invocation.\n const override = opts.repo\n ? {repo: opts.repo, subdir: opts.subdir}\n : recorded?.repo && !looksLikeOrgSlug(recorded.repo)\n ? {repo: recorded.repo, subdir: recorded.subdir}\n : undefined;\n\n const resolved = resolveOrSuggestAdopt(name, dir, override, deps);\n let code = 0;\n\n const relClone = path.join(dir, resolved.checkoutName);\n const clone = path.join(deps.appRoot, relClone);\n // When the repository holds more than this package, the CHECKOUT is the\n // clone but the PACKAGE is a directory inside it: that is where the install\n // runs and that is what the symlink points at.\n const relPkg = resolved.subdir\n ? path.join(relClone, resolved.subdir)\n : relClone;\n const pkgDir = path.join(deps.appRoot, relPkg);\n\n guardForeignLink(resolved.npmName, dir, opts, deps);\n\n if (isGitCheckout(clone)) {\n code = Math.max(code, refresh(relClone, clone, deps));\n if (code === EXIT_WARNED) return {code}; // a non-fast-forward is reported, never forced\n } else {\n fs.mkdirSync(path.dirname(clone), {recursive: true});\n deps.log(`[localize] cloning ${resolved.repo} -> ${relClone}`);\n const r = deps.run('git', ['clone', resolved.repo, clone]);\n if (r.status !== 0) {\n throw new LocalizeError(\n `git clone ${resolved.repo} failed:\\n${(r.stderr || r.stdout).trim()}`,\n EXIT_REFUSED,\n );\n }\n }\n\n if (!fs.existsSync(path.join(pkgDir, 'package.json'))) {\n throw new LocalizeError(\n `${relPkg} has no package.json, so it is not the package \"${name}\".\\n` +\n (resolved.subdir\n ? `The registry says \"${name}\" lives in \"${resolved.subdir}\" of ${resolved.repo}, and it does not.`\n : `${resolved.repo} looks like a monorepo root. Say where the package lives:\\n` +\n ` linked localize ${name} --repo ${resolved.repo} --subdir <path-inside-the-repo>`),\n EXIT_REFUSED,\n );\n }\n\n // The checkout's own package.json is authoritative about the name: a\n // mismatch means the symlink would be written under a name nothing imports.\n const declared = readJson(path.join(pkgDir, 'package.json'))?.name;\n if (declared && declared !== resolved.npmName) {\n throw new LocalizeError(\n `${relPkg} declares itself as \"${declared}\", not \"${name}\".\\n` +\n (resolved.subdir\n ? `The registry's repository.directory for \"${name}\" points at the wrong package.`\n : `${resolved.repo} is probably a monorepo. Point at the right directory:\\n` +\n ` linked localize ${name} --repo ${resolved.repo} --subdir <path-inside-the-repo>`),\n EXIT_REFUSED,\n );\n }\n\n return installLinkAndRecord(\n {\n npmName: resolved.npmName,\n clone,\n relPkg,\n pkgDir,\n repo: resolved.repo,\n subdir: resolved.subdir,\n },\n opts,\n deps,\n code,\n );\n}\n\n/**\n * Everything after the checkout exists, shared by `localize` and `adopt`:\n * install inside it, run the configured build, link it, and describe the\n * manifest entry. Nothing here knows how the checkout got there.\n *\n * `repo` may be absent -- an adopted checkout with no remote is recorded\n * without one.\n */\nexport function installLinkAndRecord(\n {\n npmName,\n clone,\n relPkg,\n pkgDir,\n repo,\n subdir,\n }: {\n npmName: string;\n clone: string;\n relPkg: string;\n pkgDir: string;\n repo?: string;\n subdir?: string;\n },\n opts: LocalizeOptions,\n deps: Deps,\n code = 0,\n): {code: number; entry: {name: string; value: ManifestEntry}} {\n // THE constraint. Read the module header before changing this. `ensure`\n // installs inside the checkout and prunes it as one step (ensure.ts).\n try {\n code = Math.max(code, ensure({path: relPkg, subdir}, deps, opts));\n } catch (e) {\n if (e instanceof LocalizeError && e.code === EXIT_INSTALL_FAILED)\n e.message += `\\nThe checkout is left on disk. Nothing was linked and nothing was recorded.`;\n throw e;\n }\n\n // The build is the one thing localize does not know how to do, so it is\n // configuration rather than behaviour. A failure is a WARNING: a package\n // whose build is broken is exactly what you are about to fix, and refusing\n // to link it would be perverse.\n if (runBuild(relPkg, pkgDir, opts, deps) === 'failed')\n code = Math.max(code, EXIT_WARNED);\n\n writeLink(deps.appRoot, npmName, pkgDir);\n const branch = currentBranch(clone, deps);\n deps.log(`[localize] linked ${npmName} -> ${relPkg} (branch ${branch})`);\n\n const range = declaredRange(npmName, deps);\n return {\n code,\n entry: {\n name: npmName,\n value: {\n ...(repo ? {repo} : {}),\n path: relPkg,\n branch,\n ...(subdir ? {subdir} : {}),\n ...(range ? {range} : {}),\n // `--no-prune` is remembered, so the run-time check and `--relink` honour it too.\n ...(shouldPrune(opts) ? {} : {prune: false as const}),\n },\n },\n };\n}\n\n/**\n * A registry lookup that fails while a git checkout already sits where the\n * clone would go is almost always a package that was never published -- one\n * made locally. Say how to link it as it is rather than leave the developer\n * guessing at a `--repo`.\n */\nfunction resolveOrSuggestAdopt(name, dir, override, deps) {\n try {\n return resolvePackage(name, deps, override);\n } catch (e) {\n const relClone = path.join(dir, checkoutNameFor(name));\n if (\n e instanceof LocalizeError &&\n e.code === EXIT_NOT_FOUND &&\n isGitCheckout(path.join(deps.appRoot, relClone))\n ) {\n e.message +=\n `\\n${relClone} is already a git checkout. To link it as it is, with no registry lookup:\\n` +\n ` linked localize ${name} --adopt`;\n }\n throw e;\n }\n}\n\n/** Older manifests recorded `owner/repo`; those are re-resolved rather than cloned blind. */\nfunction looksLikeOrgSlug(repo) {\n return /^[\\w.-]+\\/[\\w.-]+$/.test(repo);\n}\n\n/**\n * Reuse an existing clone. A dirty tree is reused WITHOUT pulling and said so;\n * a clean one is fast-forwarded; a non-fast-forward is reported and skipped\n * rather than forced, because the developer's commits are the entire point.\n */\nfunction refresh(relPath, clone, deps) {\n const status = deps.run('git', ['status', '--porcelain'], {cwd: clone});\n const modified = status.stdout.split('\\n').filter((l) => l.trim()).length;\n if (modified > 0) {\n deps.log(\n `[localize] ${relPath}: ${modified} modified file${modified === 1 ? '' : 's'} — not pulling`,\n );\n return 0;\n }\n const pull = deps.run('git', ['pull', '--ff-only'], {cwd: clone});\n if (pull.status !== 0) {\n deps.warn(\n `[localize] ${relPath}: \\`git pull --ff-only\\` failed (not a fast-forward) — skipped, not ` +\n `forced. Reconcile it by hand:\\n${(pull.stderr || pull.stdout).trim()}`,\n );\n return EXIT_WARNED;\n }\n return 0;\n}\n\n/**\n * Run the configured build command, if there is one.\n *\n * localize has no opinion about how a checkout is built, and does not look for\n * a builder. `--build \"<cmd>\"`, or a `build` field in the manifest, or\n * `{build}` in the programmatic options. Absent -- the common case, and the\n * case for anything whose dev loop reads source directly -- nothing runs and\n * nothing is said.\n */\nfunction runBuild(relPath, pkgDir, opts, deps) {\n const cmd = opts.build;\n if (!cmd) return 'skipped';\n deps.log(`[localize] ${relPath}: ${cmd}`);\n const r = deps.run(cmd, [], {cwd: pkgDir, shell: true});\n if (r.status !== 0) {\n deps.warn(\n `[localize] ${relPath}: \\`${cmd}\\` failed. The package is linked and recorded anyway — ` +\n `a package whose build is broken is exactly what you are about to fix.\\n` +\n `${(r.stderr || r.stdout).trim()}`,\n );\n return 'failed';\n }\n return 'ok';\n}\n\n/** Refuse when `node_modules/<name>` is already a symlink pointing outside `<dir>`. */\nexport function guardForeignLink(\n npmName: string,\n dir: string,\n opts: {force?: boolean},\n deps: Deps,\n): void {\n const link = path.join(deps.appRoot, 'node_modules', npmName);\n if (!isSymlink(link)) return;\n let target;\n try {\n target = fs.realpathSync(link);\n } catch {\n return; // a dangling link is ours to replace\n }\n if (isInside(target, path.join(deps.appRoot, dir))) return;\n if (opts.force) {\n deps.warn(\n `[localize] --force: overwriting the existing link ${npmName} -> ${target}`,\n );\n return;\n }\n throw new LocalizeError(\n `node_modules/${npmName} is already a symlink to ${target}, which is outside ${dir}.\\n` +\n `Refusing to overwrite someone else's link. Pass --force to replace it.`,\n EXIT_REFUSED,\n );\n}\n\n/** Every recorded package is actually linked where the manifest says it is. */\nfunction assertLinked(entries: Record<string, ManifestEntry>, deps: Deps) {\n let code = 0;\n for (const [name, entry] of Object.entries(entries)) {\n const link = path.join(deps.appRoot, 'node_modules', name);\n const expected = path.join(deps.appRoot, entry.path);\n if (!isSymlink(link)) {\n deps.warn(\n `[localize] ${name} is recorded but node_modules/${name} is not a symlink.`,\n );\n code = Math.max(code, EXIT_WARNED);\n continue;\n }\n if (!fs.existsSync(expected)) continue; // \"checkout missing\" is a --list state, not a failure\n if (fs.realpathSync(link) !== fs.realpathSync(expected)) {\n deps.warn(\n `[localize] ${name} links to ${fs.realpathSync(link)} but the manifest records ${entry.path}.`,\n );\n code = Math.max(code, EXIT_WARNED);\n }\n }\n return code;\n}\n\n/**\n * The property the whole design rests on: this run changed neither manifest.\n *\n * Content hashes, not `git status`. `git status` compares against HEAD, so in\n * any tree with an uncommitted `package.json` it reports a modification the\n * command did not make -- an earlier tool shipped exactly that and reported\n * correct runs as failures.\n */\nexport function assertManifestsUntouched(\n before: Record<string, string | null>,\n deps: Deps,\n): number {\n const changed = diffManifests(before, snapshotManifests(deps.appRoot));\n if (!changed.length) return 0;\n deps.error(\n `[localize] the consumer's manifests changed while this command ran:\\n` +\n changed.map((c) => ` ${c}`).join('\\n') +\n `\\nThis is the exact failure localize exists to prevent. Revert those files; nothing in ` +\n `localize is supposed to touch them.`,\n );\n return EXIT_MANIFEST_DIRTY;\n}\n\nexport function reportError(e: unknown, deps: Pick<Deps, 'error'>): number {\n if (e instanceof LocalizeError) {\n deps.error(`[localize] ${e.message}`);\n return e.code;\n }\n throw e;\n}\n\n/**\n * The checked-out branch, or `HEAD` when detached. `symbolic-ref` first,\n * because it also names the branch of a repository with no commits yet --\n * `rev-parse --abbrev-ref` fails there, and `create-package` adopts a fresh\n * `git init` before its first commit.\n */\nexport function currentBranch(clone: string, deps: Deps): string {\n const sym = deps.run('git', ['symbolic-ref', '--short', '-q', 'HEAD'], {\n cwd: clone,\n });\n if (sym.status === 0 && sym.stdout.trim()) return sym.stdout.trim();\n const r = deps.run('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {\n cwd: clone,\n });\n const b = r.stdout.trim();\n return r.status === 0 && b ? b : 'HEAD';\n}\n\nexport function declaredRange(\n name: string,\n deps: Pick<Deps, 'appRoot'>,\n): string | undefined {\n const pkg = readJson(path.join(deps.appRoot, 'package.json'));\n if (!pkg) return undefined;\n return (\n pkg.dependencies?.[name] ??\n pkg.devDependencies?.[name] ??\n pkg.optionalDependencies?.[name]\n );\n}\n"]}
1
+ {"version":3,"file":"localize.js","sourceRoot":"","sources":["../../../src/localize/localize.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `localize` -- turn an npm-installed dependency into an editable git checkout\n * that npm itself links.\n *\n * A checkout in `packages-local/` is a workspace member: the app's\n * `workspaces` holds `\"packages-local/*\"`, so `npm install` links\n * `node_modules/<name>` to it and dedupes everything below it like any other\n * member. The committed `package-lock.json` is put back after every install by\n * `hooks/lock-at-rest.cjs`, so the working tree stays clean.\n *\n * One run, for every name at once:\n *\n * 1. refuse an `overrides` key naming a package being localized or already\n * in `packages-local/` (npm fails with `EOVERRIDE` on a member's name);\n * nothing is changed then;\n * 2. the one-time app setup (app-setup.ts), reported line by line so the\n * developer commits it; when it changed `package.json`, the lockfile\n * that goes with it is made now, before anything is cloned, and written\n * back after the install (`captureSetupLockfile`);\n * 3. per name: a parked checkout (`linked delocalize`) moves back; an\n * existing directory is refused with an `--adopt` hint; anything else is\n * resolved through the registry's `repository` (or `--repo`) and cloned;\n * 4. the git hooks (git-hooks.ts), or the lines to add under\n * `core.hooksPath`;\n * 5. ONE `npm install` at the app root -- a checkout's dependencies arrive\n * with it, so it comes before any build;\n * 6. build each new checkout: `--build`, else `linked build`, else for the\n * cli its own `npm run build` (the cli is what `linked build` runs, and a\n * fresh cli checkout has no `lib/` yet). The cli builds first and then\n * gets its bin linked (`npm rebuild`), since the others' `linked build`\n * runs it. A failing build warns: a package whose build is broken is\n * usually what you localized it to fix.\n *\n * `adopt` (adopt.ts) replaces step 3 with \"the checkout is already there\", and\n * `--parked` with \"every parked checkout\". Steps 1, 2 and 4-6 are `runLocalize`.\n *\n * A package inside a monorepo (`--subdir`, or a registry `repository.directory`)\n * is cloned whole into `packages-local/.repos/<checkout>` -- a dot directory,\n * which the `packages-local/*` glob skips -- and `packages-local/<checkout>` is\n * a link to the package inside it. npm follows the link like a directory.\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport {conflictingOverrides, ensureAppSetup} from './app-setup.js';\nimport type {SetupChange} from './app-setup.js';\nimport {describeDrift, driftProblems} from './drift.js';\nimport {\n EXIT_INSTALL_FAILED,\n EXIT_REFUSED,\n EXIT_USAGE,\n EXIT_WARNED,\n LocalizeError,\n} from './errors.js';\nimport {existsOrLink, moveEntry, readJson} from './fsops.js';\nimport {installGitHooks} from './git-hooks.js';\nimport type {HookInstall} from './git-hooks.js';\nimport {LOCAL_DIR, localMembers, parkedMembers} from './members.js';\nimport {setupLockfileByEdit} from './setup-lockfile.js';\nimport type {Member} from './members.js';\nimport {checkoutNameFor, resolvePackage} from './resolve.js';\nimport type {Deps, RunResult} from './run.js';\nimport {linkDirectory} from '../utils/platform.js';\n\n/** What a new checkout is built with when `--build` does not say. */\nexport const DEFAULT_BUILD_COMMAND = 'linked build';\n/** The cli builds itself: `linked build` IS the cli, and a fresh checkout of it has no `lib/`. */\nconst CLI_PACKAGE = '@_linked/cli';\nconst CLI_BUILD_COMMAND = 'npm run build';\n/** The one install a run makes, at the app root. */\nexport const INSTALL_ARGS = ['install', '--no-audit', '--no-fund'];\n/** Where a cloned monorepo lives, inside `packages-local/` but outside its glob. */\nconst REPOS_DIR = `${LOCAL_DIR}/.repos`;\n/**\n * Where the set-up's lockfile run puts the checkouts while npm makes it:\n * inside the gitignored `packages-local/`, outside its glob (npm skips dot\n * directories). A run interrupted there leaves them in it; the next\n * `localize`, `delocalize` or `--list` moves them back (`restoreSetAside`).\n */\nconst SETUP_ASIDE_DIR = `${LOCAL_DIR}/.setup-aside`;\n/** The app's lockfile, kept clean of checkouts. */\nexport const LOCKFILE = 'package-lock.json';\n\nexport interface LocalizeOptions {\n /** Where checkouts live. Only `packages-local` is accepted: the workspace glob names it. */\n dir?: string;\n repo?: string;\n subdir?: string;\n /** Run in each new checkout after the install. Absent: the default; empty: no build. */\n build?: string;\n}\n\n/** A checkout ready for the install. */\nexport interface Prepared {\n name: string;\n /** App-relative, `/`-separated: `packages-local/_linked-core`. */\n dir: string;\n /** Build it after the install: a new clone or an adopted checkout, not a returning parked one. */\n build: boolean;\n}\n\n/** How one name becomes a checkout in `packages-local/`; null when there is nothing to do. */\nexport type Prepare = (\n name: string,\n opts: LocalizeOptions,\n deps: Deps,\n) => Prepared | null;\n\n/**\n * @param names full npm package names\n * @returns the process exit code: the highest of the per-name codes and the\n * install's, since a failure on name 2 does not undo name 1.\n */\nexport function localize(\n names: string[],\n opts: LocalizeOptions,\n deps: Deps,\n): number {\n return runLocalize(names, opts, deps, prepareClone);\n}\n\n/**\n * The run `localize`, `adopt` and `--parked` share: everything except how a\n * name becomes a checkout. See the module header for the steps.\n */\nexport function runLocalize(\n names: string[],\n opts: LocalizeOptions,\n deps: Deps,\n prepare: Prepare,\n): number {\n let setupLock: string | undefined;\n try {\n restoreSetAside(deps);\n checkDir(opts.dir);\n // The checkouts already there count too: the one install below covers them all.\n const localized = new Set([\n ...names,\n ...localMembers(deps.appRoot).map((m) => m.name),\n ]);\n const conflicts = conflictingOverrides(deps.appRoot, [...localized]);\n if (conflicts.length) {\n throw new LocalizeError(\n `package.json \"overrides\" names a localized package: ${conflicts\n .map((k) => `\"${k}\"`)\n .join(', ')}.\\n` +\n `npm refuses an override on a workspace member's name (EOVERRIDE), and a nested one ` +\n `would replace the checkout. Remove ${conflicts.length === 1 ? 'that key' : 'those keys'} ` +\n `from \"overrides\", then run this again. Nothing was changed.`,\n EXIT_REFUSED,\n );\n }\n const workspacesBefore = readJson(\n path.join(deps.appRoot, 'package.json'),\n )?.workspaces;\n const changes = ensureAppSetup(deps.appRoot);\n reportSetup(changes, deps);\n if (changes.some((c) => c.file === 'package.json'))\n setupLock =\n captureSetupLockfile(changes, workspacesBefore, deps) ?? undefined;\n } catch (e) {\n return reportError(e, deps);\n }\n\n let code = 0;\n const prepared: Prepared[] = [];\n for (const name of names) {\n try {\n const p = prepare(name, opts, deps);\n if (p) prepared.push(p);\n } catch (e) {\n code = Math.max(code, reportError(e, deps));\n }\n }\n if (!prepared.length) {\n // Nothing was installed: the work tree holds the set-up's lockfile as captured.\n if (setupLock !== undefined) commitHint(deps);\n return code;\n }\n return Math.max(code, installAndBuild(prepared, opts, deps, setupLock));\n}\n\n/**\n * Steps 4-6: git hooks, one root install, then the builds. `setupLock` is the\n * lockfile the set-up captured (see `captureSetupLockfile`), written back\n * over what the install left.\n */\nexport function installAndBuild(\n prepared: Prepared[],\n opts: Pick<LocalizeOptions, 'build'>,\n deps: Deps,\n setupLock?: string,\n): number {\n reportHooks(installGitHooks(deps.appRoot), deps);\n\n deps.log(`[localize] npm ${INSTALL_ARGS.join(' ')} (app root)`);\n const install = deps.run('npm', INSTALL_ARGS, {cwd: deps.appRoot});\n if (setupLock !== undefined) restoreSetupLockfile(setupLock, deps);\n if (install.status !== 0) {\n deps.error(\n `[localize] npm install failed at the app root. The checkout${prepared.length === 1 ? ' stays' : 's stay'} ` +\n `in ${LOCAL_DIR}/; fix the cause and run \\`npm install\\`.\\n` +\n tail(install.stderr || install.stdout),\n );\n return EXIT_INSTALL_FAILED;\n }\n\n let code = 0;\n // The cli first: the other builds run `linked build`, which is the cli.\n const ordered = [\n ...prepared.filter((p) => p.name === CLI_PACKAGE),\n ...prepared.filter((p) => p.name !== CLI_PACKAGE),\n ];\n for (const p of ordered) {\n const pkgDir = path.join(deps.appRoot, p.dir);\n const built = p.build ? runBuild(p, pkgDir, opts, deps) : 'skipped';\n if (built === 'failed') code = EXIT_WARNED;\n if (built === 'ok' && p.name === CLI_PACKAGE) linkCliBin(deps);\n deps.log(\n `[localize] ${p.name} -> ${p.dir} (branch ${currentBranch(pkgDir, deps)})`,\n );\n }\n for (const d of driftProblems(deps.appRoot))\n deps.warn(`[localize] drift: ${describeDrift(d)}`);\n return code;\n}\n\n/**\n * npm links a package's bin only when its target exists, and a fresh cli\n * checkout has no `lib/` at install time: without this, `node_modules/.bin/linked`\n * is missing after the build, and `npx linked` would fetch the unrelated npm\n * package named `linked`. `--ignore-scripts`: only the bin links are wanted.\n */\nfunction linkCliBin(deps: Deps): void {\n const r = deps.run('npm', ['rebuild', CLI_PACKAGE, '--ignore-scripts'], {\n cwd: deps.appRoot,\n });\n if (r.status !== 0) {\n deps.warn(\n `[localize] npm rebuild ${CLI_PACKAGE} failed, so \\`linked\\` may not be on the app's ` +\n `bin path. Run it yourself.\\n` +\n tail(r.stderr || r.stdout),\n );\n }\n}\n\n/** Step 3 for `localize`: take back a parked checkout, else clone. */\nfunction prepareClone(\n name: string,\n opts: LocalizeOptions,\n deps: Deps,\n): Prepared | null {\n const parked = parkedMembers(deps.appRoot).find((m) => m.name === name);\n if (parked) return unpark(parked, deps);\n\n const member = localMembers(deps.appRoot).find((m) => m.name === name);\n if (member) {\n throw new LocalizeError(\n `${name} is already in ${member.dir}. To install and build it as it is:\\n` +\n ` linked localize ${name} --adopt`,\n EXIT_REFUSED,\n );\n }\n\n const relDir = `${LOCAL_DIR}/${checkoutNameFor(name)}`;\n const target = path.join(deps.appRoot, relDir);\n if (existsOrLink(target)) {\n throw new LocalizeError(\n `${relDir} already exists. localize never clones over a directory. If it is ${name}'s ` +\n `checkout, install and build it as it is:\\n linked localize ${name} --adopt`,\n EXIT_REFUSED,\n );\n }\n\n const resolved = resolvePackage(\n name,\n deps,\n opts.repo ? {repo: opts.repo, subdir: opts.subdir} : undefined,\n );\n\n // A monorepo is cloned whole outside the glob; the member is a link to the package.\n const relClone = resolved.subdir\n ? `${REPOS_DIR}/${checkoutNameFor(name)}`\n : relDir;\n const clone = path.join(deps.appRoot, relClone);\n if (existsOrLink(clone)) {\n throw new LocalizeError(\n `${relClone} already exists. Remove it, or move it out of the way, and run this again.`,\n EXIT_REFUSED,\n );\n }\n fs.mkdirSync(path.dirname(clone), {recursive: true});\n deps.log(`[localize] cloning ${resolved.repo} -> ${relClone}`);\n const r = deps.run('git', ['clone', '--', resolved.repo, clone]);\n if (r.status !== 0) {\n throw new LocalizeError(\n `git clone ${resolved.repo} failed:\\n${(r.stderr || r.stdout).trim()}`,\n EXIT_REFUSED,\n );\n }\n\n const pkgDir = resolved.subdir ? path.join(clone, resolved.subdir) : clone;\n const relPkg = resolved.subdir ? `${relClone}/${resolved.subdir}` : relClone;\n // A clone that is not the package must not stay: in packages-local/ it\n // would be a workspace member under the wrong name.\n const declared = readJson(path.join(pkgDir, 'package.json'))?.name;\n if (declared !== name) {\n fs.rmSync(clone, {recursive: true, force: true});\n const where = resolved.subdir\n ? `The registry's repository.directory for \"${name}\" points at the wrong place.`\n : `${resolved.repo} looks like a monorepo. Say where the package lives:\\n` +\n ` linked localize ${name} --repo ${resolved.repo} --subdir <path-inside-the-repo>`;\n throw new LocalizeError(\n (declared\n ? `${relPkg} declares itself as \"${declared}\", not \"${name}\".\\n`\n : `${relPkg} has no package.json naming it, so it is not the package \"${name}\".\\n`) +\n `${where}\\nThe clone was removed.`,\n EXIT_REFUSED,\n );\n }\n\n if (resolved.subdir) {\n linkDirectory(pkgDir, target);\n deps.log(`[localize] ${relDir} -> ${relPkg}`);\n }\n return {name, dir: relDir, build: true};\n}\n\n/** Move a parked checkout back into `packages-local/`. No clone, no build: it is as it was. */\nexport function unpark(member: Member, deps: Deps): Prepared {\n const entry = path.basename(member.dir);\n const relDir = `${LOCAL_DIR}/${entry}`;\n const to = path.join(deps.appRoot, relDir);\n if (existsOrLink(to)) {\n throw new LocalizeError(\n `${member.name} is parked in ${member.dir}, but ${relDir} already exists. Move one of ` +\n `them out of the way and run this again.`,\n EXIT_REFUSED,\n );\n }\n // npm refuses two workspace members of one name, so the install would fail.\n const same = localMembers(deps.appRoot).find((m) => m.name === member.name);\n if (same) {\n throw new LocalizeError(\n `${member.name} is parked in ${member.dir}, but ${same.dir} is ${member.name} already. ` +\n `Keep one: delete or move the other out of the way, and run this again.`,\n EXIT_REFUSED,\n );\n }\n moveEntry(path.join(deps.appRoot, member.dir), to);\n deps.log(`[localize] ${member.dir} -> ${relDir}`);\n return {name: member.name, dir: relDir, build: false};\n}\n\n/** `--dir` is kept for scripts that pass the default; anything else is not a workspace member. */\nfunction checkDir(dir: string | undefined): void {\n if (dir === undefined || dir.replace(/\\/+$/, '') === LOCAL_DIR) return;\n throw new LocalizeError(\n `--dir ${dir}: checkouts live in ${LOCAL_DIR}/, the directory the app's ` +\n `\"workspaces\" glob and the lock-at-rest hook name. Move them there.`,\n EXIT_USAGE,\n );\n}\n\nfunction reportSetup(changes: SetupChange[], deps: Deps): void {\n if (!changes.length) return;\n deps.log(`[localize] set up this app for checkouts (commit these):`);\n for (const c of changes) deps.log(` ${c.file}: ${c.what}`);\n}\n\n/** What `captureSetupLockfile` runs: the lockfile for the new `package.json`, nothing installed. */\nconst SETUP_LOCK_ARGS = [\n 'install',\n '--package-lock-only',\n '--ignore-scripts',\n '--no-audit',\n '--no-fund',\n];\n\n/**\n * The set-up changed `package.json`, so the lockfile must change with it\n * (the root entry's `workspaces`) -- and it must be a lockfile with no\n * checkout in it, which the install below cannot give: it lists them, and\n * lock-at-rest leaves it so while `package.json` differs from HEAD. So,\n * before anything is cloned, make that lockfile, keep it, and write it back\n * after the install. When the root entry already has `workspaces` and\n * `hasInstallScript`, it is an edit of that entry (setup-lockfile.ts: exact,\n * offline); otherwise npm makes the lockfile alone, with checkouts already in\n * `packages-local/` (an adopted one) moved into `SETUP_ASIDE_DIR` for that\n * one call.\n *\n * @returns the lockfile to write back, or null when it could not be made (the\n * manual steps are printed instead).\n */\nfunction captureSetupLockfile(\n changes: SetupChange[],\n workspacesBefore: unknown,\n deps: Deps,\n): string | null {\n const lockfile = path.join(deps.appRoot, LOCKFILE);\n const edited = editedSetupLockfile(lockfile, workspacesBefore, deps);\n if (edited !== null) return edited;\n const moveAside = localMembers(deps.appRoot).length > 0;\n deps.log(\n `[localize] npm ${SETUP_LOCK_ARGS.join(' ')} (the set-up's lockfile)`,\n );\n if (moveAside) setAside(deps);\n let r: RunResult;\n try {\n r = deps.run('npm', SETUP_LOCK_ARGS, {cwd: deps.appRoot});\n } finally {\n if (moveAside) moveBack(deps);\n }\n let text: string | null = null;\n try {\n text = fs.readFileSync(lockfile, 'utf8');\n } catch {\n /* none written */\n }\n if (r.status !== 0 || text === null) {\n manualSetupSteps(\n changes,\n r.status !== 0\n ? `npm could not write it:\\n${tail(r.stderr || r.stdout)}`\n : `npm wrote no ${LOCKFILE}`,\n deps,\n );\n return null;\n }\n return text;\n}\n\n/**\n * Every entry of `packages-local/` but the dot directories, moved into\n * `SETUP_ASIDE_DIR` as it is (a link keeps its text and works again once back).\n */\nfunction setAside(deps: Pick<Deps, 'appRoot'>): void {\n const local = path.join(deps.appRoot, LOCAL_DIR);\n const aside = path.join(deps.appRoot, SETUP_ASIDE_DIR);\n fs.mkdirSync(aside, {recursive: true});\n for (const entry of fs.readdirSync(local)) {\n if (entry.startsWith('.')) continue;\n fs.renameSync(path.join(local, entry), path.join(aside, entry));\n }\n}\n\n/** Everything in `SETUP_ASIDE_DIR` back into `packages-local/`; the directory goes. */\nfunction moveBack(deps: Pick<Deps, 'appRoot'>): number {\n const local = path.join(deps.appRoot, LOCAL_DIR);\n const aside = path.join(deps.appRoot, SETUP_ASIDE_DIR);\n const entries = fs.readdirSync(aside);\n for (const entry of entries)\n fs.renameSync(path.join(aside, entry), path.join(local, entry));\n fs.rmdirSync(aside);\n return entries.length;\n}\n\n/**\n * A set-up run that was interrupted while the checkouts were in\n * `SETUP_ASIDE_DIR` left them there, where npm does not see them: move them\n * back, saying so. Refuses, moving nothing, when `packages-local/` already\n * has an entry of the same name.\n */\nexport function restoreSetAside(deps: Pick<Deps, 'appRoot' | 'log'>): void {\n const aside = path.join(deps.appRoot, SETUP_ASIDE_DIR);\n if (!existsOrLink(aside)) return;\n let entries: string[];\n try {\n entries = fs.readdirSync(aside);\n } catch {\n throw new LocalizeError(\n `${SETUP_ASIDE_DIR} is not a directory. Remove it and run this again.`,\n EXIT_REFUSED,\n );\n }\n const clashes = entries.filter((e) =>\n existsOrLink(path.join(deps.appRoot, LOCAL_DIR, e)),\n );\n if (clashes.length) {\n throw new LocalizeError(\n `${SETUP_ASIDE_DIR}/ holds checkouts an interrupted set-up left there, but ` +\n `${clashes.map((e) => `${LOCAL_DIR}/${e}`).join(', ')} now exist${clashes.length === 1 ? 's' : ''} ` +\n `too. Keep one of each, move the other out of ${LOCAL_DIR}/, and run this again. ` +\n `Nothing was moved.`,\n EXIT_REFUSED,\n );\n }\n const n = moveBack(deps);\n if (n)\n deps.log(\n `[localize] moved ${n} checkout${n === 1 ? '' : 's'} back from ${SETUP_ASIDE_DIR}/ into ` +\n `${LOCAL_DIR}/, where an interrupted set-up left ${n === 1 ? 'it' : 'them'}.`,\n );\n}\n\n/** The set-up's lockfile as an edit of the root entry, written now; null when npm must make it. */\nfunction editedSetupLockfile(\n lockfile: string,\n workspacesBefore: unknown,\n deps: Deps,\n): string | null {\n let current: string;\n try {\n current = fs.readFileSync(lockfile, 'utf8');\n } catch {\n return null;\n }\n const text = setupLockfileByEdit(\n current,\n readJson(path.join(deps.appRoot, 'package.json')),\n workspacesBefore,\n );\n if (text === null) return null;\n fs.writeFileSync(lockfile, text);\n deps.log(\n `[localize] ${LOCKFILE}: the root entry's \"workspaces\" now matches package.json (the set-up's lockfile)`,\n );\n return text;\n}\n\n/** Put the captured set-up lockfile back after the install rewrote it. */\nfunction restoreSetupLockfile(text: string, deps: Deps): void {\n fs.writeFileSync(path.join(deps.appRoot, LOCKFILE), text);\n deps.log(\n `[localize] ${LOCKFILE}: put back the set-up's lockfile, which lists no checkout (any ` +\n `lock-at-rest warning above was about the one the install wrote).`,\n );\n commitHint(deps);\n}\n\nfunction commitHint(deps: Deps): void {\n deps.log(\n `[localize] commit the set-up now -- package.json, ${LOCKFILE}, .gitignore:\\n` +\n ` git add package.json ${LOCKFILE} .gitignore && git commit -m \"chore: set up linked localize\"`,\n );\n}\n\n/** The set-up's lockfile could not be made in one step: how to make it by hand. */\nfunction manualSetupSteps(\n changes: SetupChange[],\n why: string,\n deps: Deps,\n): void {\n const files = [...new Set([...changes.map((c) => c.file), LOCKFILE])];\n deps.warn(\n `[localize] could not make the set-up's ${LOCKFILE} in one step: ${why}\\n` +\n `Commit the set-up with a lockfile from an install with no checkout present:\\n` +\n ` npx linked delocalize\\n` +\n ` npm install\\n` +\n ` git add ${files.join(' ')} && git commit -m \"chore: set up linked localize\"\\n` +\n ` npx linked localize --parked`,\n );\n}\n\n/** Tell the developer what `installGitHooks` did not do. */\nfunction reportHooks(hooks: HookInstall, deps: Deps): void {\n for (const file of hooks.skipped) {\n deps.warn(\n `[localize] ${path.relative(deps.appRoot, file)} is not ours, so it was left alone. Without ` +\n `the localize hook there, run \\`npm install\\` yourself after a pull or branch switch that ` +\n `changes dependencies.`,\n );\n }\n if (hooks.hooksPath !== null) {\n deps.warn(\n `[localize] core.hooksPath is set (${hooks.hooksPath}), so no git hooks were written. Add ` +\n `each line below to the hook named before it, an \\`sh\\` script (not, say, a Python hook ` +\n `the pre-commit framework writes); they do nothing where the cli is not installed:`,\n );\n for (const m of hooks.manual) deps.warn(` ${m.file}:\\n ${m.line}`);\n }\n if (hooks.sharedWithWorktrees) {\n deps.warn(\n `[localize] this is a linked worktree: git hooks are shared by every worktree of the ` +\n `repository. They act only in a work tree whose ${LOCAL_DIR}/ has checkouts.`,\n );\n }\n}\n\n/**\n * Run the build for one new checkout. `opts.build` wins, including `''` for\n * no build; otherwise the cli builds itself and everything else gets\n * `linked build`.\n */\nfunction runBuild(\n p: Prepared,\n pkgDir: string,\n opts: Pick<LocalizeOptions, 'build'>,\n deps: Deps,\n): 'skipped' | 'ok' | 'failed' {\n const cmd = buildCommandFor(p.name, opts);\n if (!cmd) return 'skipped';\n deps.log(`[localize] ${p.dir}: ${cmd}`);\n const r = deps.run(cmd, [], {cwd: pkgDir, shell: true});\n if (r.status !== 0) {\n deps.warn(\n `[localize] ${p.dir}: \\`${cmd}\\` failed. It is installed and linked anyway -- a package ` +\n `whose build is broken is usually what you localized it to fix.\\n` +\n tail(r.stderr || r.stdout),\n );\n return 'failed';\n }\n return 'ok';\n}\n\nfunction buildCommandFor(\n name: string,\n opts: Pick<LocalizeOptions, 'build'>,\n): string {\n if (opts.build !== undefined) return opts.build;\n return name === CLI_PACKAGE ? CLI_BUILD_COMMAND : DEFAULT_BUILD_COMMAND;\n}\n\nexport function reportError(e: unknown, deps: Pick<Deps, 'error'>): number {\n if (e instanceof LocalizeError) {\n deps.error(`[localize] ${e.message}`);\n return e.code;\n }\n throw e;\n}\n\n/**\n * The checked-out branch, or `HEAD` when detached. `symbolic-ref` first,\n * because it also names the branch of a repository with no commits yet --\n * `rev-parse --abbrev-ref` fails there, and `create-package` adopts a fresh\n * `git init` before its first commit.\n */\nexport function currentBranch(\n checkout: string,\n deps: Pick<Deps, 'run'>,\n): string {\n const sym = deps.run('git', ['symbolic-ref', '--short', '-q', 'HEAD'], {\n cwd: checkout,\n });\n if (sym.status === 0 && sym.stdout.trim()) return sym.stdout.trim();\n const r = deps.run('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {\n cwd: checkout,\n });\n const b = r.stdout.trim();\n return r.status === 0 && b ? b : 'HEAD';\n}\n\n/** The last lines of a subprocess's output: enough to see the error, not the whole log. */\nexport function tail(output: string, lines = 20): string {\n return output.trim().split('\\n').slice(-lines).join('\\n');\n}\n"]}
@@ -0,0 +1,13 @@
1
+ export declare const LOCAL_DIR = "packages-local";
2
+ export declare const PARKED_DIR = ".packages-local.parked";
3
+ export interface Member {
4
+ name: string;
5
+ version: string;
6
+ /** Relative to the app root, `/`-separated: `packages-local/_linked-core`. */
7
+ dir: string;
8
+ }
9
+ /** The checkouts npm links: every directory in `packages-local/` with a named `package.json`. */
10
+ export declare function localMembers(appRoot: string): Member[];
11
+ /** The checkouts `linked delocalize` parked. */
12
+ export declare function parkedMembers(appRoot: string): Member[];
13
+ //# sourceMappingURL=members.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"members.d.ts","sourceRoot":"","sources":["../../../src/localize/members.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,SAAS,mBAAmB,CAAC;AAC1C,eAAO,MAAM,UAAU,2BAA2B,CAAC;AAEnD,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,GAAG,EAAE,MAAM,CAAC;CACb;AAED,iGAAiG;AACjG,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAEtD;AAED,gDAAgD;AAChD,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAEvD"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * The record of what is localized: the directories themselves.
3
+ *
4
+ * A checkout in `packages-local/` is a workspace member (the app's
5
+ * `workspaces` holds `"packages-local/*"`), so npm links it whatever any file
6
+ * says; a separate record of it could only drift from what npm does. A parked
7
+ * checkout (`linked delocalize`) sits in `.packages-local.parked/`, outside the
8
+ * glob, until `linked localize` takes it back.
9
+ */
10
+ import fs from 'node:fs';
11
+ import path from 'node:path';
12
+ import { readJson } from './fsops.js';
13
+ export const LOCAL_DIR = 'packages-local';
14
+ export const PARKED_DIR = '.packages-local.parked';
15
+ /** The checkouts npm links: every directory in `packages-local/` with a named `package.json`. */
16
+ export function localMembers(appRoot) {
17
+ return membersIn(appRoot, LOCAL_DIR);
18
+ }
19
+ /** The checkouts `linked delocalize` parked. */
20
+ export function parkedMembers(appRoot) {
21
+ return membersIn(appRoot, PARKED_DIR);
22
+ }
23
+ function membersIn(appRoot, dir) {
24
+ let entries;
25
+ try {
26
+ entries = fs.readdirSync(path.join(appRoot, dir));
27
+ }
28
+ catch (_a) {
29
+ return [];
30
+ }
31
+ const out = [];
32
+ for (const entry of entries) {
33
+ if (entry.startsWith('.'))
34
+ continue;
35
+ const pkg = readJson(path.join(appRoot, dir, entry, 'package.json'));
36
+ if (typeof (pkg === null || pkg === void 0 ? void 0 : pkg.name) !== 'string' || !pkg.name)
37
+ continue;
38
+ out.push({
39
+ name: pkg.name,
40
+ version: typeof pkg.version === 'string' ? pkg.version : '',
41
+ dir: `${dir}/${entry}`,
42
+ });
43
+ }
44
+ return out.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
45
+ }
46
+ //# sourceMappingURL=members.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"members.js","sourceRoot":"","sources":["../../../src/localize/members.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAC;AAEpC,MAAM,CAAC,MAAM,SAAS,GAAG,gBAAgB,CAAC;AAC1C,MAAM,CAAC,MAAM,UAAU,GAAG,wBAAwB,CAAC;AASnD,iGAAiG;AACjG,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,OAAO,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;AACvC,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,OAAO,SAAS,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,SAAS,CAAC,OAAe,EAAE,GAAW;IAC7C,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;IACpD,CAAC;IAAC,WAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QACpC,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC;QACrE,IAAI,OAAO,CAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,IAAI,CAAA,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,IAAI;YAAE,SAAS;QACzD,GAAG,CAAC,IAAI,CAAC;YACP,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,OAAO,EAAE,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;YAC3D,GAAG,EAAE,GAAG,GAAG,IAAI,KAAK,EAAE;SACvB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9E,CAAC","sourcesContent":["/**\n * The record of what is localized: the directories themselves.\n *\n * A checkout in `packages-local/` is a workspace member (the app's\n * `workspaces` holds `\"packages-local/*\"`), so npm links it whatever any file\n * says; a separate record of it could only drift from what npm does. A parked\n * checkout (`linked delocalize`) sits in `.packages-local.parked/`, outside the\n * glob, until `linked localize` takes it back.\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport {readJson} from './fsops.js';\n\nexport const LOCAL_DIR = 'packages-local';\nexport const PARKED_DIR = '.packages-local.parked';\n\nexport interface Member {\n name: string;\n version: string;\n /** Relative to the app root, `/`-separated: `packages-local/_linked-core`. */\n dir: string;\n}\n\n/** The checkouts npm links: every directory in `packages-local/` with a named `package.json`. */\nexport function localMembers(appRoot: string): Member[] {\n return membersIn(appRoot, LOCAL_DIR);\n}\n\n/** The checkouts `linked delocalize` parked. */\nexport function parkedMembers(appRoot: string): Member[] {\n return membersIn(appRoot, PARKED_DIR);\n}\n\nfunction membersIn(appRoot: string, dir: string): Member[] {\n let entries: string[];\n try {\n entries = fs.readdirSync(path.join(appRoot, dir));\n } catch {\n return [];\n }\n const out: Member[] = [];\n for (const entry of entries) {\n if (entry.startsWith('.')) continue;\n const pkg = readJson(path.join(appRoot, dir, entry, 'package.json'));\n if (typeof pkg?.name !== 'string' || !pkg.name) continue;\n out.push({\n name: pkg.name,\n version: typeof pkg.version === 'string' ? pkg.version : '',\n dir: `${dir}/${entry}`,\n });\n }\n return out.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));\n}\n"]}
@@ -21,8 +21,7 @@ export interface Resolved {
21
21
  /**
22
22
  * @param {string} name a full npm package name (`lodash`, `@scope/thing`)
23
23
  * @param {object} deps
24
- * @param {object} [override] `{repo, subdir}` from `--repo`/`--subdir` or from
25
- * a manifest entry recorded by an earlier run
24
+ * @param {object} [override] `{repo, subdir}` from `--repo`/`--subdir`
26
25
  * @returns {Resolved}
27
26
  * @throws {LocalizeError} code 4 when the registry has no usable `repository`.
28
27
  */
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../../src/localize/resolve.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,UAAU,CAAC;AAEnC,MAAM,WAAW,QAAQ;IACvB,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,+FAA+F;IAC/F,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;GAQG;AAEH;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,EACvB,QAAQ,CAAC,EAAE;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAC,GAC1C,QAAQ,CAmBV;AAyED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAWnD;AAkBD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAIvD"}
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../../src/localize/resolve.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,UAAU,CAAC;AAEnC,MAAM,WAAW,QAAQ;IACvB,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,+FAA+F;IAC/F,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;GAQG;AAEH;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,EACvB,QAAQ,CAAC,EAAE;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAC,GAC1C,QAAQ,CAmBV;AAwED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAWnD;AAkBD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAIvD"}
@@ -33,8 +33,7 @@ import { EXIT_NOT_FOUND, LocalizeError } from './errors.js';
33
33
  /**
34
34
  * @param {string} name a full npm package name (`lodash`, `@scope/thing`)
35
35
  * @param {object} deps
36
- * @param {object} [override] `{repo, subdir}` from `--repo`/`--subdir` or from
37
- * a manifest entry recorded by an earlier run
36
+ * @param {object} [override] `{repo, subdir}` from `--repo`/`--subdir`
38
37
  * @returns {Resolved}
39
38
  * @throws {LocalizeError} code 4 when the registry has no usable `repository`.
40
39
  */
@@ -86,9 +85,8 @@ function readRepositoryField(meta, name) {
86
85
  if (node && typeof node === 'object' && 'repository' in node)
87
86
  node = node.repository;
88
87
  const missing = () => new LocalizeError(`"${name}" publishes no usable "repository" field, so there is nothing to clone.\n` +
89
- `localize never guesses at a repository URL. Pass it once:\n` +
90
- ` linked localize ${name} --repo <git-url> [--subdir <path-inside-the-repo>]\n` +
91
- `It is recorded in local-packages.json, so you only pass it the first time.`, EXIT_NOT_FOUND);
88
+ `localize never guesses at a repository URL. Pass it:\n` +
89
+ ` linked localize ${name} --repo <git-url> [--subdir <path-inside-the-repo>]`, EXIT_NOT_FOUND);
92
90
  if (!node)
93
91
  throw missing();
94
92
  let raw;
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../../src/localize/resolve.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * npm package name -> git repository.\n *\n * There is exactly ONE resolution path, and keeping it to one is the design:\n *\n * npm name -> registry metadata -> `repository` (+ `directory`) -> clone\n *\n * No org probing, no name guessing, no mapping table, no pluggable resolver.\n * The `repository` field is data the package already published, so it is the\n * authoritative answer rather than an inference -- and an inference that is\n * wrong here costs a clone and a full install of the wrong repository.\n *\n * A consumer that wants to accept short names, or to search several GitHub\n * orgs, resolves that to a full package name ITSELF and then calls localize.\n * That behaviour is specific to whoever has it, and localize deliberately\n * offers no seam for it.\n *\n * Metadata is read with `npm view`, not with an HTTP request to\n * registry.npmjs.org, so a private registry, a scoped registry, a proxy and an\n * auth token all work without localize knowing any of them exist.\n */\nimport path from 'node:path';\n\nimport {EXIT_NOT_FOUND, LocalizeError} from './errors.js';\nimport type {Deps} from './run.js';\n\nexport interface Resolved {\n /** The package name, as it is imported and as `node_modules/<npmName>` is spelled. */\n npmName: string;\n /** A git URL that `git clone` accepts. */\n repo: string;\n /** Directory name for the clone. */\n checkoutName: string;\n /** Package location inside the clone, when the repository holds more than this one package. */\n subdir?: string;\n}\n\n/**\n * @typedef {object} Resolved\n * @property {string} npmName the package name, as it is imported and as\n * `node_modules/<npmName>` is spelled\n * @property {string} repo a git URL that `git clone` accepts\n * @property {string} checkoutName directory name for the clone\n * @property {string} [subdir] package location inside the clone, when the\n * repository holds more than this one package\n */\n\n/**\n * @param {string} name a full npm package name (`lodash`, `@scope/thing`)\n * @param {object} deps\n * @param {object} [override] `{repo, subdir}` from `--repo`/`--subdir` or from\n * a manifest entry recorded by an earlier run\n * @returns {Resolved}\n * @throws {LocalizeError} code 4 when the registry has no usable `repository`.\n */\nexport function resolvePackage(\n name: string,\n deps: Pick<Deps, 'run'>,\n override?: {repo?: string; subdir?: string},\n): Resolved {\n if (override?.repo) {\n return {\n npmName: name,\n repo: override.repo,\n checkoutName: checkoutNameFor(name),\n ...(override.subdir ? {subdir: normalizeSubdir(override.subdir)} : {}),\n };\n }\n\n const meta = fetchMetadata(name, deps);\n const {url, directory} = readRepositoryField(meta, name);\n\n return {\n npmName: name,\n repo: url,\n checkoutName: checkoutNameFor(name),\n ...(directory ? {subdir: directory} : {}),\n };\n}\n\n/** Ask npm for the published metadata. `npm view` inherits the user's registry config. */\nfunction fetchMetadata(name, deps) {\n const r = deps.run('npm', ['view', name, 'repository', 'name', '--json']);\n if (r.status !== 0) {\n throw new LocalizeError(\n `cannot read registry metadata for \"${name}\":\\n${(r.stderr || r.stdout).trim()}\\n` +\n `localize resolves a repository only from the published package. If the package is not ` +\n `published, or you are not authenticated for its registry, pass the repository ` +\n `explicitly: linked localize ${name} --repo <git-url>`,\n EXIT_NOT_FOUND,\n );\n }\n // A published package with no `repository` field at all: npm exits 0 and\n // prints nothing. That is \"missing\", not \"malformed\" -- let the caller's\n // missing-field refusal handle it, since it is the one that names the fix.\n if (r.stdout.trim() === '') return null;\n try {\n return JSON.parse(r.stdout);\n } catch (e) {\n throw new LocalizeError(\n `npm returned metadata for \"${name}\" that is not JSON (${e.message}).`,\n EXIT_NOT_FOUND,\n );\n }\n}\n\n/**\n * Pull the repository out of the metadata and normalise it to something\n * `git clone` accepts.\n *\n * Refuses rather than guesses when the field is absent. Plenty of published\n * packages have no `repository` at all, and there is no honest way to find\n * their source from the registry -- so the answer is an explicit override, not\n * a search.\n */\nfunction readRepositoryField(meta, name) {\n // `npm view <name> <field> --json` returns the bare field value; with several\n // fields it returns an object keyed by field name. Accept either, and accept\n // the array npm returns when several versions match.\n let node = meta;\n if (Array.isArray(node)) node = node[0];\n if (node && typeof node === 'object' && 'repository' in node)\n node = node.repository;\n\n const missing = () =>\n new LocalizeError(\n `\"${name}\" publishes no usable \"repository\" field, so there is nothing to clone.\\n` +\n `localize never guesses at a repository URL. Pass it once:\\n` +\n ` linked localize ${name} --repo <git-url> [--subdir <path-inside-the-repo>]\\n` +\n `It is recorded in local-packages.json, so you only pass it the first time.`,\n EXIT_NOT_FOUND,\n );\n\n if (!node) throw missing();\n\n let raw;\n let directory;\n if (typeof node === 'string') {\n raw = node;\n } else if (typeof node === 'object') {\n raw = typeof node.url === 'string' ? node.url : undefined;\n directory = typeof node.directory === 'string' ? node.directory : undefined;\n }\n if (!raw) throw missing();\n\n return {\n url: normalizeGitUrl(raw),\n directory: directory ? normalizeSubdir(directory) : undefined,\n };\n}\n\n/**\n * npm accepts several spellings in `repository.url`; `git clone` accepts fewer.\n *\n * Handled: the `git+` prefix npm recommends, the `git://` scheme many older\n * packages still carry, and the `github:owner/repo` / bare `owner/repo`\n * shorthands npm normalises on publish but not always in a package's source.\n */\nexport function normalizeGitUrl(raw: string): string {\n let url = raw.trim();\n if (url.startsWith('git+')) url = url.slice(4);\n if (url.endsWith('.git/')) url = url.slice(0, -1);\n\n const shorthand = /^(?:github:)?([\\w.-]+)\\/([\\w.-]+)$/.exec(url);\n if (shorthand)\n return `https://github.com/${shorthand[1]}/${shorthand[2]}.git`;\n\n if (url.startsWith('git://')) return 'https://' + url.slice('git://'.length);\n return url;\n}\n\n/** A repo-relative POSIX path with no leading `./` and no escape. */\nfunction normalizeSubdir(dir) {\n const clean = path.posix\n .normalize(dir.replace(/\\\\/g, '/'))\n .replace(/^\\.\\//, '')\n .replace(/\\/+$/, '');\n if (clean === '.' || clean === '') return undefined;\n if (clean.startsWith('..') || path.posix.isAbsolute(clean)) {\n throw new LocalizeError(\n `the package directory \"${dir}\" points outside the repository. Refusing to use it.`,\n EXIT_NOT_FOUND,\n );\n }\n return clean;\n}\n\n/**\n * Directory name for the clone. The scope is flattened rather than dropped, so\n * `@a/thing` and `@b/thing` can both be localized in one tree -- dropping it\n * would make the second clone silently reuse the first.\n */\nexport function checkoutNameFor(npmName: string): string {\n return npmName.startsWith('@')\n ? npmName.slice(1).replace(/\\//g, '-')\n : npmName;\n}\n"]}
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../../src/localize/resolve.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * npm package name -> git repository.\n *\n * There is exactly ONE resolution path, and keeping it to one is the design:\n *\n * npm name -> registry metadata -> `repository` (+ `directory`) -> clone\n *\n * No org probing, no name guessing, no mapping table, no pluggable resolver.\n * The `repository` field is data the package already published, so it is the\n * authoritative answer rather than an inference -- and an inference that is\n * wrong here costs a clone and a full install of the wrong repository.\n *\n * A consumer that wants to accept short names, or to search several GitHub\n * orgs, resolves that to a full package name ITSELF and then calls localize.\n * That behaviour is specific to whoever has it, and localize deliberately\n * offers no seam for it.\n *\n * Metadata is read with `npm view`, not with an HTTP request to\n * registry.npmjs.org, so a private registry, a scoped registry, a proxy and an\n * auth token all work without localize knowing any of them exist.\n */\nimport path from 'node:path';\n\nimport {EXIT_NOT_FOUND, LocalizeError} from './errors.js';\nimport type {Deps} from './run.js';\n\nexport interface Resolved {\n /** The package name, as it is imported and as `node_modules/<npmName>` is spelled. */\n npmName: string;\n /** A git URL that `git clone` accepts. */\n repo: string;\n /** Directory name for the clone. */\n checkoutName: string;\n /** Package location inside the clone, when the repository holds more than this one package. */\n subdir?: string;\n}\n\n/**\n * @typedef {object} Resolved\n * @property {string} npmName the package name, as it is imported and as\n * `node_modules/<npmName>` is spelled\n * @property {string} repo a git URL that `git clone` accepts\n * @property {string} checkoutName directory name for the clone\n * @property {string} [subdir] package location inside the clone, when the\n * repository holds more than this one package\n */\n\n/**\n * @param {string} name a full npm package name (`lodash`, `@scope/thing`)\n * @param {object} deps\n * @param {object} [override] `{repo, subdir}` from `--repo`/`--subdir`\n * @returns {Resolved}\n * @throws {LocalizeError} code 4 when the registry has no usable `repository`.\n */\nexport function resolvePackage(\n name: string,\n deps: Pick<Deps, 'run'>,\n override?: {repo?: string; subdir?: string},\n): Resolved {\n if (override?.repo) {\n return {\n npmName: name,\n repo: override.repo,\n checkoutName: checkoutNameFor(name),\n ...(override.subdir ? {subdir: normalizeSubdir(override.subdir)} : {}),\n };\n }\n\n const meta = fetchMetadata(name, deps);\n const {url, directory} = readRepositoryField(meta, name);\n\n return {\n npmName: name,\n repo: url,\n checkoutName: checkoutNameFor(name),\n ...(directory ? {subdir: directory} : {}),\n };\n}\n\n/** Ask npm for the published metadata. `npm view` inherits the user's registry config. */\nfunction fetchMetadata(name, deps) {\n const r = deps.run('npm', ['view', name, 'repository', 'name', '--json']);\n if (r.status !== 0) {\n throw new LocalizeError(\n `cannot read registry metadata for \"${name}\":\\n${(r.stderr || r.stdout).trim()}\\n` +\n `localize resolves a repository only from the published package. If the package is not ` +\n `published, or you are not authenticated for its registry, pass the repository ` +\n `explicitly: linked localize ${name} --repo <git-url>`,\n EXIT_NOT_FOUND,\n );\n }\n // A published package with no `repository` field at all: npm exits 0 and\n // prints nothing. That is \"missing\", not \"malformed\" -- let the caller's\n // missing-field refusal handle it, since it is the one that names the fix.\n if (r.stdout.trim() === '') return null;\n try {\n return JSON.parse(r.stdout);\n } catch (e) {\n throw new LocalizeError(\n `npm returned metadata for \"${name}\" that is not JSON (${e.message}).`,\n EXIT_NOT_FOUND,\n );\n }\n}\n\n/**\n * Pull the repository out of the metadata and normalise it to something\n * `git clone` accepts.\n *\n * Refuses rather than guesses when the field is absent. Plenty of published\n * packages have no `repository` at all, and there is no honest way to find\n * their source from the registry -- so the answer is an explicit override, not\n * a search.\n */\nfunction readRepositoryField(meta, name) {\n // `npm view <name> <field> --json` returns the bare field value; with several\n // fields it returns an object keyed by field name. Accept either, and accept\n // the array npm returns when several versions match.\n let node = meta;\n if (Array.isArray(node)) node = node[0];\n if (node && typeof node === 'object' && 'repository' in node)\n node = node.repository;\n\n const missing = () =>\n new LocalizeError(\n `\"${name}\" publishes no usable \"repository\" field, so there is nothing to clone.\\n` +\n `localize never guesses at a repository URL. Pass it:\\n` +\n ` linked localize ${name} --repo <git-url> [--subdir <path-inside-the-repo>]`,\n EXIT_NOT_FOUND,\n );\n\n if (!node) throw missing();\n\n let raw;\n let directory;\n if (typeof node === 'string') {\n raw = node;\n } else if (typeof node === 'object') {\n raw = typeof node.url === 'string' ? node.url : undefined;\n directory = typeof node.directory === 'string' ? node.directory : undefined;\n }\n if (!raw) throw missing();\n\n return {\n url: normalizeGitUrl(raw),\n directory: directory ? normalizeSubdir(directory) : undefined,\n };\n}\n\n/**\n * npm accepts several spellings in `repository.url`; `git clone` accepts fewer.\n *\n * Handled: the `git+` prefix npm recommends, the `git://` scheme many older\n * packages still carry, and the `github:owner/repo` / bare `owner/repo`\n * shorthands npm normalises on publish but not always in a package's source.\n */\nexport function normalizeGitUrl(raw: string): string {\n let url = raw.trim();\n if (url.startsWith('git+')) url = url.slice(4);\n if (url.endsWith('.git/')) url = url.slice(0, -1);\n\n const shorthand = /^(?:github:)?([\\w.-]+)\\/([\\w.-]+)$/.exec(url);\n if (shorthand)\n return `https://github.com/${shorthand[1]}/${shorthand[2]}.git`;\n\n if (url.startsWith('git://')) return 'https://' + url.slice('git://'.length);\n return url;\n}\n\n/** A repo-relative POSIX path with no leading `./` and no escape. */\nfunction normalizeSubdir(dir) {\n const clean = path.posix\n .normalize(dir.replace(/\\\\/g, '/'))\n .replace(/^\\.\\//, '')\n .replace(/\\/+$/, '');\n if (clean === '.' || clean === '') return undefined;\n if (clean.startsWith('..') || path.posix.isAbsolute(clean)) {\n throw new LocalizeError(\n `the package directory \"${dir}\" points outside the repository. Refusing to use it.`,\n EXIT_NOT_FOUND,\n );\n }\n return clean;\n}\n\n/**\n * Directory name for the clone. The scope is flattened rather than dropped, so\n * `@a/thing` and `@b/thing` can both be localized in one tree -- dropping it\n * would make the second clone silently reuse the first.\n */\nexport function checkoutNameFor(npmName: string): string {\n return npmName.startsWith('@')\n ? npmName.slice(1).replace(/\\//g, '-')\n : npmName;\n}\n"]}
@@ -10,6 +10,7 @@
10
10
  export interface RunOptions {
11
11
  cwd?: string;
12
12
  env?: NodeJS.ProcessEnv;
13
+ /** `cmd` is one command line for the platform's shell; `args` must be empty. */
13
14
  shell?: boolean;
14
15
  }
15
16
  export interface RunResult {
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/localize/run.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,UAAU,KAAK,SAAS,CAAC;AAEhF;;;GAGG;AACH,MAAM,WAAW,IAAI;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,GAAG,CAAC;IACT,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED,wBAAgB,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAe/C;AAED,+DAA+D;AAC/D,wBAAgB,WAAW,CAAC,OAAO,GAAE,MAAsB,GAAG,IAAI,CAQjE"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/localize/run.ts"],"names":[],"mappings":"AAKA;;;;;;;;GAQG;AACH,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,gFAAgF;IAChF,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,UAAU,KAAK,SAAS,CAAC;AAEhF;;;GAGG;AACH,MAAM,WAAW,IAAI;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,GAAG,CAAC;IACT,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED,wBAAgB,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAmB/C;AAED,+DAA+D;AAC/D,wBAAgB,WAAW,CAAC,OAAO,GAAE,MAAsB,GAAG,IAAI,CAQjE"}
@@ -1,19 +1,24 @@
1
1
  import { spawnSync } from 'node:child_process';
2
2
  import process from 'node:process';
3
+ import { spawnCommandSync } from '../utils/spawn.js';
3
4
  export function makeRun(defaultCwd) {
4
5
  return function run(cmd, args, opts = {}) {
5
- var _a, _b, _c, _d, _e;
6
- const r = spawnSync(cmd, args, {
6
+ var _a, _b, _c, _d;
7
+ const options = {
7
8
  cwd: (_a = opts.cwd) !== null && _a !== void 0 ? _a : defaultCwd,
8
9
  encoding: 'utf8',
9
10
  env: (_b = opts.env) !== null && _b !== void 0 ? _b : process.env,
10
- shell: (_c = opts.shell) !== null && _c !== void 0 ? _c : false,
11
11
  maxBuffer: 64 * 1024 * 1024,
12
- });
12
+ };
13
+ // Without a shell, `npm` and the other shims go through the one helper
14
+ // that knows how to start them on Windows.
15
+ const r = opts.shell
16
+ ? spawnSync(cmd, args, Object.assign(Object.assign({}, options), { shell: true }))
17
+ : spawnCommandSync(cmd, args, options);
13
18
  return {
14
19
  status: r.status === null ? 1 : r.status,
15
- stdout: (_d = r.stdout) !== null && _d !== void 0 ? _d : '',
16
- stderr: (_e = r.stderr) !== null && _e !== void 0 ? _e : (r.error ? String(r.error.message) : ''),
20
+ stdout: (_c = r.stdout) !== null && _c !== void 0 ? _c : '',
21
+ stderr: (_d = r.stderr) !== null && _d !== void 0 ? _d : (r.error ? String(r.error.message) : ''),
17
22
  };
18
23
  };
19
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/localize/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,oBAAoB,CAAC;AAC7C,OAAO,OAAO,MAAM,cAAc,CAAC;AAqCnC,MAAM,UAAU,OAAO,CAAC,UAAkB;IACxC,OAAO,SAAS,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,OAAmB,EAAE;;QAClD,MAAM,CAAC,GAAG,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE;YAC7B,GAAG,EAAE,MAAA,IAAI,CAAC,GAAG,mCAAI,UAAU;YAC3B,QAAQ,EAAE,MAAM;YAChB,GAAG,EAAE,MAAA,IAAI,CAAC,GAAG,mCAAI,OAAO,CAAC,GAAG;YAC5B,KAAK,EAAE,MAAA,IAAI,CAAC,KAAK,mCAAI,KAAK;YAC1B,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;SAC5B,CAAC,CAAC;QACH,OAAO;YACL,MAAM,EAAE,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM;YACxC,MAAM,EAAE,MAAA,CAAC,CAAC,MAAM,mCAAI,EAAE;YACtB,MAAM,EAAE,MAAA,CAAC,CAAC,MAAM,mCAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;SAC7D,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,WAAW,CAAC,UAAkB,OAAO,CAAC,GAAG,EAAE;IACzD,OAAO;QACL,OAAO;QACP,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC;QACrB,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1B,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5B,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;KAC/B,CAAC;AACJ,CAAC","sourcesContent":["import {spawnSync} from 'node:child_process';\nimport process from 'node:process';\n\n/**\n * The single seam through which localize reaches the outside world.\n *\n * Every subprocess -- `git`, `npm`, a configured build command -- goes through\n * the `run` function on the deps object. Tests may replace it, but note that\n * the real-localize test deliberately does NOT: a stubbed runner cannot show\n * that `npm install` ran in the right directory, which is the one property\n * this tool has to get right.\n */\nexport interface RunOptions {\n cwd?: string;\n env?: NodeJS.ProcessEnv;\n shell?: boolean;\n}\n\nexport interface RunResult {\n status: number;\n stdout: string;\n stderr: string;\n}\n\nexport type Run = (cmd: string, args: string[], opts?: RunOptions) => RunResult;\n\n/**\n * Everything localize needs from the outside world. A public contract: callers\n * pass their own to point localize at another root or capture its output.\n */\nexport interface Deps {\n appRoot: string;\n run: Run;\n log: (message: string) => void;\n warn: (message: string) => void;\n error: (message: string) => void;\n}\n\nexport function makeRun(defaultCwd: string): Run {\n return function run(cmd, args, opts: RunOptions = {}) {\n const r = spawnSync(cmd, args, {\n cwd: opts.cwd ?? defaultCwd,\n encoding: 'utf8',\n env: opts.env ?? process.env,\n shell: opts.shell ?? false,\n maxBuffer: 64 * 1024 * 1024,\n });\n return {\n status: r.status === null ? 1 : r.status,\n stdout: r.stdout ?? '',\n stderr: r.stderr ?? (r.error ? String(r.error.message) : ''),\n };\n };\n}\n\n/** Build the default dependency bundle for a consumer root. */\nexport function defaultDeps(appRoot: string = process.cwd()): Deps {\n return {\n appRoot,\n run: makeRun(appRoot),\n log: (m) => console.log(m),\n warn: (m) => console.warn(m),\n error: (m) => console.error(m),\n };\n}\n"]}
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/localize/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,oBAAoB,CAAC;AAC7C,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC,OAAO,EAAC,gBAAgB,EAAC,MAAM,mBAAmB,CAAC;AAsCnD,MAAM,UAAU,OAAO,CAAC,UAAkB;IACxC,OAAO,SAAS,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,OAAmB,EAAE;;QAClD,MAAM,OAAO,GAAG;YACd,GAAG,EAAE,MAAA,IAAI,CAAC,GAAG,mCAAI,UAAU;YAC3B,QAAQ,EAAE,MAAe;YACzB,GAAG,EAAE,MAAA,IAAI,CAAC,GAAG,mCAAI,OAAO,CAAC,GAAG;YAC5B,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;SAC5B,CAAC;QACF,uEAAuE;QACvE,2CAA2C;QAC3C,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK;YAClB,CAAC,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,kCAAM,OAAO,KAAE,KAAK,EAAE,IAAI,IAAE;YACjD,CAAC,CAAC,gBAAgB,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QACzC,OAAO;YACL,MAAM,EAAE,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM;YACxC,MAAM,EAAE,MAAA,CAAC,CAAC,MAAM,mCAAI,EAAE;YACtB,MAAM,EAAE,MAAA,CAAC,CAAC,MAAM,mCAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;SAC7D,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,WAAW,CAAC,UAAkB,OAAO,CAAC,GAAG,EAAE;IACzD,OAAO;QACL,OAAO;QACP,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC;QACrB,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1B,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5B,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;KAC/B,CAAC;AACJ,CAAC","sourcesContent":["import {spawnSync} from 'node:child_process';\nimport process from 'node:process';\n\nimport {spawnCommandSync} from '../utils/spawn.js';\n\n/**\n * The single seam through which localize reaches the outside world.\n *\n * Every subprocess -- `git`, `npm`, a configured build command -- goes through\n * the `run` function on the deps object. Tests may replace it, but note that\n * the real-localize test deliberately does NOT: a stubbed runner cannot show\n * that `npm install` ran in the right directory, which is the one property\n * this tool has to get right.\n */\nexport interface RunOptions {\n cwd?: string;\n env?: NodeJS.ProcessEnv;\n /** `cmd` is one command line for the platform's shell; `args` must be empty. */\n shell?: boolean;\n}\n\nexport interface RunResult {\n status: number;\n stdout: string;\n stderr: string;\n}\n\nexport type Run = (cmd: string, args: string[], opts?: RunOptions) => RunResult;\n\n/**\n * Everything localize needs from the outside world. A public contract: callers\n * pass their own to point localize at another root or capture its output.\n */\nexport interface Deps {\n appRoot: string;\n run: Run;\n log: (message: string) => void;\n warn: (message: string) => void;\n error: (message: string) => void;\n}\n\nexport function makeRun(defaultCwd: string): Run {\n return function run(cmd, args, opts: RunOptions = {}) {\n const options = {\n cwd: opts.cwd ?? defaultCwd,\n encoding: 'utf8' as const,\n env: opts.env ?? process.env,\n maxBuffer: 64 * 1024 * 1024,\n };\n // Without a shell, `npm` and the other shims go through the one helper\n // that knows how to start them on Windows.\n const r = opts.shell\n ? spawnSync(cmd, args, {...options, shell: true})\n : spawnCommandSync(cmd, args, options);\n return {\n status: r.status === null ? 1 : r.status,\n stdout: r.stdout ?? '',\n stderr: r.stderr ?? (r.error ? String(r.error.message) : ''),\n };\n };\n}\n\n/** Build the default dependency bundle for a consumer root. */\nexport function defaultDeps(appRoot: string = process.cwd()): Deps {\n return {\n appRoot,\n run: makeRun(appRoot),\n log: (m) => console.log(m),\n warn: (m) => console.warn(m),\n error: (m) => console.error(m),\n };\n}\n"]}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @param lockText the current `package-lock.json`
3
+ * @param pkg the app's `package.json` after the set-up
4
+ * @param workspacesBefore `package.json`'s `workspaces` before the set-up
5
+ * @returns the lockfile with the root entry's `workspaces` set to `pkg`'s, or
6
+ * null when the edit could not be exact: no v2/v3 root entry, no
7
+ * `workspaces` or `hasInstallScript` in it yet (npm decides where a new key
8
+ * goes), a root `workspaces` that is not `workspacesBefore`, dependency
9
+ * fields that do not match (`package.json` has unlocked changes npm must
10
+ * resolve), or a layout `JSON.stringify` would not reproduce.
11
+ */
12
+ export declare function setupLockfileByEdit(lockText: string, pkg: any, workspacesBefore: unknown): string | null;
13
+ //# sourceMappingURL=setup-lockfile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup-lockfile.d.ts","sourceRoot":"","sources":["../../../src/localize/setup-lockfile.ts"],"names":[],"mappings":"AA+BA;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,GAAG,EACR,gBAAgB,EAAE,OAAO,GACxB,MAAM,GAAG,IAAI,CA2Bf"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * The set-up's lockfile made without npm, when that is exact.
3
+ *
4
+ * The set-up changes `package.json` in two places: `workspaces` gains
5
+ * `packages-local/*`, and `postinstall`/`dependencies` run the lock-at-rest
6
+ * hook. In the lockfile, those show up only in the root entry
7
+ * (`packages[""]`): its `workspaces` is a verbatim copy of `package.json`'s,
8
+ * and `hasInstallScript` is true once any install script exists. With
9
+ * `packages-local/` empty, nothing else in the tree changes.
10
+ *
11
+ * `npm install --package-lock-only` is not a substitute. It resolves afresh,
12
+ * and on a real app it does more than that one hunk: on a large app (npm 11
13
+ * and 12) it adds the bundled dependencies of an optional package for another
14
+ * platform, which a full install never records, and npm 12 refuses it outright
15
+ * (`EALLOWREMOTE`, fetching that package's tarball to read them). So when the
16
+ * root entry already has both fields in place -- any app with workspaces and
17
+ * an install script -- the edit is made here, and `null` sends the caller to
18
+ * npm for the rest. The edit replaces only the glob list, so it is exact only
19
+ * when the root entry's `workspaces` is what `package.json` had before the
20
+ * set-up; a lockfile already behind `package.json` there goes to npm too.
21
+ */
22
+ import { isDeepStrictEqual } from 'node:util';
23
+ /** The dependency fields npm copies into the root entry; they must already agree. */
24
+ const DEP_FIELDS = [
25
+ 'dependencies',
26
+ 'devDependencies',
27
+ 'optionalDependencies',
28
+ 'peerDependencies',
29
+ ];
30
+ /**
31
+ * @param lockText the current `package-lock.json`
32
+ * @param pkg the app's `package.json` after the set-up
33
+ * @param workspacesBefore `package.json`'s `workspaces` before the set-up
34
+ * @returns the lockfile with the root entry's `workspaces` set to `pkg`'s, or
35
+ * null when the edit could not be exact: no v2/v3 root entry, no
36
+ * `workspaces` or `hasInstallScript` in it yet (npm decides where a new key
37
+ * goes), a root `workspaces` that is not `workspacesBefore`, dependency
38
+ * fields that do not match (`package.json` has unlocked changes npm must
39
+ * resolve), or a layout `JSON.stringify` would not reproduce.
40
+ */
41
+ export function setupLockfileByEdit(lockText, pkg, workspacesBefore) {
42
+ var _a, _b, _c;
43
+ let lock;
44
+ try {
45
+ lock = JSON.parse(lockText);
46
+ }
47
+ catch (_d) {
48
+ return null;
49
+ }
50
+ const root = (_a = lock === null || lock === void 0 ? void 0 : lock.packages) === null || _a === void 0 ? void 0 : _a[''];
51
+ if (!root || typeof root !== 'object' || !(lock.lockfileVersion >= 2))
52
+ return null;
53
+ if (!('workspaces' in root) || root.hasInstallScript !== true)
54
+ return null;
55
+ if (!pkg || pkg.workspaces === undefined)
56
+ return null;
57
+ if (!isDeepStrictEqual(root.workspaces, workspacesBefore))
58
+ return null;
59
+ for (const field of DEP_FIELDS) {
60
+ if (!sameDeps(pkg[field], root[field]))
61
+ return null;
62
+ }
63
+ const eol = lockText.includes('\r\n') ? '\r\n' : '\n';
64
+ const indent = (_c = (_b = /^\{\r?\n([ \t]+)"/.exec(lockText)) === null || _b === void 0 ? void 0 : _b[1]) !== null && _c !== void 0 ? _c : ' ';
65
+ const format = (value) => JSON.stringify(value, null, indent).replace(/\n/g, eol) +
66
+ (/\r?\n$/.test(lockText) ? eol : '');
67
+ // Only a file this formatting reproduces byte for byte is rewritten.
68
+ if (format(lock) !== lockText)
69
+ return null;
70
+ root.workspaces = pkg.workspaces;
71
+ return format(lock);
72
+ }
73
+ /** npm leaves an empty dependency object out of the root entry. */
74
+ function sameDeps(a, b) {
75
+ const norm = (v) => v && typeof v === 'object' && Object.keys(v).length
76
+ ? JSON.stringify(v)
77
+ : '';
78
+ return norm(a) === norm(b);
79
+ }
80
+ //# sourceMappingURL=setup-lockfile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup-lockfile.js","sourceRoot":"","sources":["../../../src/localize/setup-lockfile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAC,iBAAiB,EAAC,MAAM,WAAW,CAAC;AAE5C,qFAAqF;AACrF,MAAM,UAAU,GAAG;IACjB,cAAc;IACd,iBAAiB;IACjB,sBAAsB;IACtB,kBAAkB;CACV,CAAC;AAEX;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAAgB,EAChB,GAAQ,EACR,gBAAyB;;IAEzB,IAAI,IAAS,CAAC;IACd,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC9B,CAAC;IAAC,WAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,IAAI,GAAG,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,QAAQ,0CAAG,EAAE,CAAC,CAAC;IAClC,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,CAAC;QACnE,OAAO,IAAI,CAAC;IACd,IAAI,CAAC,CAAC,YAAY,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,gBAAgB,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC3E,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACtD,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,UAAU,EAAE,gBAAgB,CAAC;QAAE,OAAO,IAAI,CAAC;IACvE,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;QAC/B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;IACtD,CAAC;IAED,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IACtD,MAAM,MAAM,GAAG,MAAA,MAAA,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,0CAAG,CAAC,CAAC,mCAAI,IAAI,CAAC;IAC/D,MAAM,MAAM,GAAG,CAAC,KAAc,EAAE,EAAE,CAChC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;QACvD,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACvC,qEAAqE;IACrE,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAE3C,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC,UAAU,CAAC;IACjC,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAED,mEAAmE;AACnE,SAAS,QAAQ,CAAC,CAAU,EAAE,CAAU;IACtC,MAAM,IAAI,GAAG,CAAC,CAAU,EAAE,EAAE,CAC1B,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM;QACjD,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;QACnB,CAAC,CAAC,EAAE,CAAC;IACT,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC;AAC7B,CAAC","sourcesContent":["/**\n * The set-up's lockfile made without npm, when that is exact.\n *\n * The set-up changes `package.json` in two places: `workspaces` gains\n * `packages-local/*`, and `postinstall`/`dependencies` run the lock-at-rest\n * hook. In the lockfile, those show up only in the root entry\n * (`packages[\"\"]`): its `workspaces` is a verbatim copy of `package.json`'s,\n * and `hasInstallScript` is true once any install script exists. With\n * `packages-local/` empty, nothing else in the tree changes.\n *\n * `npm install --package-lock-only` is not a substitute. It resolves afresh,\n * and on a real app it does more than that one hunk: on a large app (npm 11\n * and 12) it adds the bundled dependencies of an optional package for another\n * platform, which a full install never records, and npm 12 refuses it outright\n * (`EALLOWREMOTE`, fetching that package's tarball to read them). So when the\n * root entry already has both fields in place -- any app with workspaces and\n * an install script -- the edit is made here, and `null` sends the caller to\n * npm for the rest. The edit replaces only the glob list, so it is exact only\n * when the root entry's `workspaces` is what `package.json` had before the\n * set-up; a lockfile already behind `package.json` there goes to npm too.\n */\nimport {isDeepStrictEqual} from 'node:util';\n\n/** The dependency fields npm copies into the root entry; they must already agree. */\nconst DEP_FIELDS = [\n 'dependencies',\n 'devDependencies',\n 'optionalDependencies',\n 'peerDependencies',\n] as const;\n\n/**\n * @param lockText the current `package-lock.json`\n * @param pkg the app's `package.json` after the set-up\n * @param workspacesBefore `package.json`'s `workspaces` before the set-up\n * @returns the lockfile with the root entry's `workspaces` set to `pkg`'s, or\n * null when the edit could not be exact: no v2/v3 root entry, no\n * `workspaces` or `hasInstallScript` in it yet (npm decides where a new key\n * goes), a root `workspaces` that is not `workspacesBefore`, dependency\n * fields that do not match (`package.json` has unlocked changes npm must\n * resolve), or a layout `JSON.stringify` would not reproduce.\n */\nexport function setupLockfileByEdit(\n lockText: string,\n pkg: any,\n workspacesBefore: unknown,\n): string | null {\n let lock: any;\n try {\n lock = JSON.parse(lockText);\n } catch {\n return null;\n }\n const root = lock?.packages?.[''];\n if (!root || typeof root !== 'object' || !(lock.lockfileVersion >= 2))\n return null;\n if (!('workspaces' in root) || root.hasInstallScript !== true) return null;\n if (!pkg || pkg.workspaces === undefined) return null;\n if (!isDeepStrictEqual(root.workspaces, workspacesBefore)) return null;\n for (const field of DEP_FIELDS) {\n if (!sameDeps(pkg[field], root[field])) return null;\n }\n\n const eol = lockText.includes('\\r\\n') ? '\\r\\n' : '\\n';\n const indent = /^\\{\\r?\\n([ \\t]+)\"/.exec(lockText)?.[1] ?? ' ';\n const format = (value: unknown) =>\n JSON.stringify(value, null, indent).replace(/\\n/g, eol) +\n (/\\r?\\n$/.test(lockText) ? eol : '');\n // Only a file this formatting reproduces byte for byte is rewritten.\n if (format(lock) !== lockText) return null;\n\n root.workspaces = pkg.workspaces;\n return format(lock);\n}\n\n/** npm leaves an empty dependency object out of the root entry. */\nfunction sameDeps(a: unknown, b: unknown): boolean {\n const norm = (v: unknown) =>\n v && typeof v === 'object' && Object.keys(v).length\n ? JSON.stringify(v)\n : '';\n return norm(a) === norm(b);\n}\n"]}
@@ -64,25 +64,16 @@ export declare function isPackageLocation(value: string): value is PackageLocati
64
64
  /** `@scope/foo-bar` → `foo-bar`: the folder name under `packages/`. */
65
65
  export declare function bareName(name: string): string;
66
66
  /**
67
- * Make sure the app's `workspaces` covers `packages/*`, so a package created
68
- * there is a workspace member. Mutates `pkg`.
67
+ * Make sure the app's `workspaces` covers `<location>/*` (default
68
+ * `packages/*`), so a package created there is a workspace member. Mutates
69
+ * `pkg`.
69
70
  *
70
71
  * @returns whether it changed, and a warning when it cannot tell.
71
72
  */
72
- export declare function ensureWorkspaceGlob(pkg: Record<string, any>): {
73
+ export declare function ensureWorkspaceGlob(pkg: Record<string, any>, location?: PackageLocation): {
73
74
  changed: boolean;
74
75
  warning?: string;
75
76
  };
76
- export { RELINK_COMMAND, ensureRelinkHooks } from './relinkHooks.js';
77
- /**
78
- * Make sure the app's `postinstall` AND `dependencies` scripts recreate
79
- * localize's links -- see `./relinkHooks.js` for why npm needs both. Kept
80
- * under its old name for existing callers; prefer `ensureRelinkHooks`.
81
- * Mutates `pkg`.
82
- *
83
- * @returns true when it changed `pkg`.
84
- */
85
- export declare function ensureRelinkPostinstall(pkg: Record<string, any>): boolean;
86
77
  /**
87
78
  * A git remote as npm wants it in `repository.url`: `git+https://…`, or
88
79
  * `git+ssh://git@host/path` for the scp-like `git@host:path` form.
@@ -1 +1 @@
1
- {"version":3,"file":"createPackageLocation.d.ts","sourceRoot":"","sources":["../../../src/utils/createPackageLocation.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAGlD,eAAO,MAAM,iBAAiB,yCAA0C,CAAC;AACzE,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjE,MAAM,WAAW,oBAAoB;IACnC,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;OAGG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,0DAA0D;IAC1D,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GACtB;IAAC,IAAI,EAAE,SAAS,CAAA;CAAC,GACjB;IAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,eAAe,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAC,GAC7E;IAAC,IAAI,EAAE,KAAK,CAAA;CAAC,GACb;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CAAC;AAEtC,gEAAgE;AAChE,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAgB9D;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,EACxC,OAAO,EACP,OAAO,EACP,KAAK,GACN,EAAE;IACD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,oBAAoB,CAAC;IAC9B,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,cAAc,CAwCjB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,eAAe,CAEzE;AAMD,uEAAuE;AACvE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM7C;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG;IAC7D,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAsBA;AAED,OAAO,EAAC,cAAc,EAAE,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAEnE;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAEzE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAOvD"}
1
+ {"version":3,"file":"createPackageLocation.d.ts","sourceRoot":"","sources":["../../../src/utils/createPackageLocation.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAElD,eAAO,MAAM,iBAAiB,yCAA0C,CAAC;AACzE,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjE,MAAM,WAAW,oBAAoB;IACnC,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;OAGG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,0DAA0D;IAC1D,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GACtB;IAAC,IAAI,EAAE,SAAS,CAAA;CAAC,GACjB;IAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,eAAe,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAC,GAC7E;IAAC,IAAI,EAAE,KAAK,CAAA;CAAC,GACb;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CAAC;AAEtC,gEAAgE;AAChE,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAgB9D;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,EACxC,OAAO,EACP,OAAO,EACP,KAAK,GACN,EAAE;IACD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,oBAAoB,CAAC;IAC9B,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,cAAc,CAwCjB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,eAAe,CAEzE;AAMD,uEAAuE;AACvE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM7C;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACxB,QAAQ,GAAE,eAA4B,GACrC;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAuBA;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAOvD"}