@_linked/cli 1.38.0 → 1.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +72 -8
  3. package/defaults/app-react-native/docker-compose.yml +1 -1
  4. package/lib/esm/cli-methods.d.ts +2 -1
  5. package/lib/esm/cli-methods.d.ts.map +1 -1
  6. package/lib/esm/cli-methods.js +219 -47
  7. package/lib/esm/cli-methods.js.map +1 -1
  8. package/lib/esm/cli.d.ts.map +1 -1
  9. package/lib/esm/cli.js +19 -5
  10. package/lib/esm/cli.js.map +1 -1
  11. package/lib/esm/commands/build-package.d.ts +1 -1
  12. package/lib/esm/commands/build-package.d.ts.map +1 -1
  13. package/lib/esm/commands/build-package.js +3 -2
  14. package/lib/esm/commands/build-package.js.map +1 -1
  15. package/lib/esm/commands/localize.d.ts +33 -0
  16. package/lib/esm/commands/localize.d.ts.map +1 -1
  17. package/lib/esm/commands/localize.js +72 -10
  18. package/lib/esm/commands/localize.js.map +1 -1
  19. package/lib/esm/installed-packages.d.ts +45 -5
  20. package/lib/esm/installed-packages.d.ts.map +1 -1
  21. package/lib/esm/installed-packages.js +90 -5
  22. package/lib/esm/installed-packages.js.map +1 -1
  23. package/lib/esm/lifecycle.d.ts +9 -2
  24. package/lib/esm/lifecycle.d.ts.map +1 -1
  25. package/lib/esm/lifecycle.js +45 -16
  26. package/lib/esm/lifecycle.js.map +1 -1
  27. package/lib/esm/localized-dedupe.d.ts +20 -0
  28. package/lib/esm/localized-dedupe.d.ts.map +1 -0
  29. package/lib/esm/localized-dedupe.js +182 -0
  30. package/lib/esm/localized-dedupe.js.map +1 -0
  31. package/lib/esm/utils/createPackageLocation.d.ts +76 -0
  32. package/lib/esm/utils/createPackageLocation.d.ts.map +1 -0
  33. package/lib/esm/utils/createPackageLocation.js +157 -0
  34. package/lib/esm/utils/createPackageLocation.js.map +1 -0
  35. package/lib/esm/utils.d.ts.map +1 -1
  36. package/lib/esm/utils.js +2 -1
  37. package/lib/esm/utils.js.map +1 -1
  38. package/lib/esm/vite-config.d.ts +8 -0
  39. package/lib/esm/vite-config.d.ts.map +1 -1
  40. package/lib/esm/vite-config.js +67 -48
  41. package/lib/esm/vite-config.js.map +1 -1
  42. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.40.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#211](https://github.com/linked-fw/cli/pull/211) [`c268b22`](https://github.com/linked-fw/cli/commit/c268b22efc68384470e90dc391729dcf5911d185) Thanks [@flyon](https://github.com/flyon)! - `linked localize` now leaves one copy of each framework package. A checkout's install leaves its own `@_linked/core` (pinned by the checkout's lockfile, often older than the app's) and a registry copy of any localized sibling in its `node_modules`, and plain Node and `tsx` loaded those: measured with three localized linked packages, three cores in one process, and a localized package that never saw its localized sibling. `@_linked/localize` 0.3.0 removes a checkout's copies of what the app provides after every install and on every `--relink`; this CLI requires it and tells it what the app provides: the linked packages it has installed (by their `linkedPackage` flag, not their scope), `react` and `react-dom`. A copy is removed only when the app's version satisfies the checkout's range (a localized sibling always counts); otherwise it is kept, with a warning. Measured afterwards: one core in Node, `tsx` and Vite SSR, and every checkout still builds — `npx linked build` in a checkout runs the app's `linked` — and passes its tests. `--no-prune` turns it off.
8
+
9
+ ### Patch Changes
10
+
11
+ - [#211](https://github.com/linked-fw/cli/pull/211) [`01d3dc0`](https://github.com/linked-fw/cli/commit/01d3dc02b68245b79e1bb2855e96f969d5942026) Thanks [@flyon](https://github.com/flyon)! - The dev resolver registers every localized package as source, including one that another localized package depends on. The dependency walk used to key "visited" on the package name and go depth-first, so reaching a checkout's own `node_modules` copy of a sibling (a lib-only registry install) first hid the app's localized checkout of that sibling: Vite served it from `lib/`, and the depending checkout's imports went to its nested copy. The walk is now breadth-first and keyed on the installed directory.
12
+
13
+ - [#211](https://github.com/linked-fw/cli/pull/211) [`c268b22`](https://github.com/linked-fw/cli/commit/c268b22efc68384470e90dc391729dcf5911d185) Thanks [@flyon](https://github.com/flyon)! - `createViteConfig` dedupes what localization can duplicate, in every mode: every localized package (from `local-packages.json`), every runtime dependency a localized checkout declares that the app has at a version satisfying that checkout's range, and `react`/`react-dom`. Before, it deduped only `@_linked/server-utils` and `@_linked/react`, and only in a standalone app, so an app with a localized package had Vite resolve `@_linked/core` from that checkout's own `node_modules`: its dev SSR backend loaded one core per copy (three, measured). A dependency whose range the app does not satisfy is left out and reported in the dev log, and so is a name a registry install nests its own copy of, because a dedupe hands every importer the app's copy without checking versions. A standalone app's `optimizeDeps.exclude` now picks linked packages by their `linkedPackage` flag rather than the `@_linked/` scope, and the legacy `lincd: true` flag is no longer read anywhere.
14
+
15
+ ## 1.39.0
16
+
17
+ ### Minor Changes
18
+
19
+ - [#199](https://github.com/linked-fw/cli/pull/199) [`dfdb1c5`](https://github.com/linked-fw/cli/commit/dfdb1c50547bab428540db149afb4b106c9f0c5c) Thanks [@flyon](https://github.com/flyon)! - `create-package` chooses where a package lives inside an app: `packages/` (part of the app's repository: a workspace member, added to its dependencies and installed at the app root) or `packages-local/` (its own git repository, under `linked localize`'s name for it, with `git init`, a first commit, an optional `--remote` and `--push`, then installed, built, linked and recorded by `linked localize --adopt`). Choose with `--location`, `--remote` and `--push`; with none of them you are asked, on a terminal only. An existing target folder is refused. Outside an app nothing changes.
20
+
21
+ `linked localize --adopt` links a checkout already in `packages-local/` without cloning it, and `build-all` builds packages recorded in `local-packages.json` even when the app does not declare them yet. Needs `@_linked/localize` 0.2.0.
22
+
3
23
  ## 1.38.0
4
24
 
5
25
  ### Minor Changes
package/README.md CHANGED
@@ -8,13 +8,16 @@ Command-line tools for the `@_linked/*` packages and apps.
8
8
  npm install --save-dev @_linked/cli
9
9
  ```
10
10
 
11
- ## Binaries
11
+ ## Binary
12
12
 
13
- Three executables ship in this package:
13
+ One executable ships in this package: `linked`. (`lnk`, `lincd` and `lincd-cli` were dropped in
14
+ [#40](https://github.com/linked-fw/cli/pull/40).)
14
15
 
15
- - `linked` — primary command
16
- - `lnk` — short alias for `linked`
17
- - `lincd` — deprecated alias; prints a warning and forwards to `linked`. Will be removed in a future major release.
16
+ In a project that has `@_linked/cli` installed — any linked app, including Create Now — run it as
17
+ `npx linked <command>`. Everywhere else, name the package: `npx @_linked/cli <command>`.
18
+ A bare `npx linked` outside such a project does **not** reach this CLI: npm resolves it to the
19
+ unrelated `linked` package on the registry, which has no binary, and fails with
20
+ `could not determine executable to run`.
18
21
 
19
22
  ## Commands
20
23
 
@@ -24,11 +27,31 @@ Run `linked --help` for the full list. The commonly used ones:
24
27
 
25
28
  ```bash
26
29
  linked create-app <name> # scaffold a new app (interactive)
27
- linked create-package <name> # scaffold a new linkedPackage
30
+ linked create-package <name> # scaffold a new linkedPackage (see below for where it goes)
28
31
  linked create-shape <name> # add a shape file to the current package
29
32
  linked create-component <name> # add a React component file
30
33
  ```
31
34
 
35
+ Inside an app (a `package.json` with `"linkedApp": true` above the current directory),
36
+ `create-package` puts the package in one of two places, and asks which on a terminal:
37
+
38
+ ```bash
39
+ linked create-package @_linked/foo --location packages # part of the app's repository
40
+ linked create-package @_linked/foo --location packages-local # a repository of its own
41
+ linked create-package @_linked/foo --remote <git-url> [--push] # the same, with an origin
42
+ ```
43
+
44
+ - `packages/foo` — a workspace member: added to the app's `dependencies` (and `packages/*` to its
45
+ `workspaces` if missing), installed at the app root.
46
+ - `packages-local/_linked-foo` — the name `linked localize` uses. `git init` and a first commit,
47
+ `origin` and `repository.url` from `--remote`, pushed with `--push`; then installed, built,
48
+ linked and recorded by `linked localize --adopt`. It is not added to the app's `dependencies`
49
+ until it is published. `--remote` or `--push` imply this location.
50
+
51
+ Any of the three flags skips the question. With none of them and no terminal, it exits 1 and says
52
+ which flag to pass. An existing target folder is refused. Outside an app nothing changes: the
53
+ package goes in `./packages/`, `./modules/` or the current directory, and installs on its own.
54
+
32
55
  ### Building
33
56
 
34
57
  ```bash
@@ -214,10 +237,18 @@ linked localize @_linked/rdfs # clone, install, build, symlink into node_mod
214
237
  linked localize # report what is localized (same as --list)
215
238
  linked localize --list --check # exit 1 when something recorded is not actually linked
216
239
  linked localize --relink # recreate the recorded symlinks — run this from postinstall
240
+ linked localize @_linked/rdfs --adopt # link a checkout already in packages-local/_linked-rdfs, no clone
217
241
  linked delocalize @_linked/rdfs # unlink and forget, keeping the checkout
218
242
  linked delocalize --purge # undo everything and delete the checkouts
219
243
  ```
220
244
 
245
+ Checkouts go in `packages-local/` under the npm name with the scope flattened:
246
+ `@_linked/rdfs` → `packages-local/_linked-rdfs`.
247
+
248
+ `npm install <name>` — with a package name — does not run the app's own `postinstall`, so it
249
+ replaces every localized link with the registry copy and prunes the checkouts' dependencies,
250
+ silently. Run `linked localize --relink` after it (a bare `npm install` runs the hook itself).
251
+
221
252
  Name packages exactly as npm names them (`@_linked/rdfs`, `lodash`): the
222
253
  repository is read from the package's published `repository` field, so there is
223
254
  no short-name expansion and no org guessing. `--dir` moves the checkout
@@ -226,9 +257,42 @@ published metadata does not point at the right place, and `--build "<cmd>"`
226
257
  replaces `linked build` (an empty string builds nothing). A failing build only
227
258
  warns — a package whose build is broken is usually why you localized it.
228
259
 
260
+ **One copy of each framework package.** A checkout's own install leaves its own
261
+ `@_linked/core` (pinned by the checkout's lockfile, often older than the app's)
262
+ and a registry copy of any localized sibling in its `node_modules`, and Node
263
+ loads those instead of the app's. So after installing, and on every `--relink`,
264
+ `linked localize` removes from every checkout's `node_modules` its own copy of
265
+ a linked package the app has installed, `react` and `react-dom` (plus its
266
+ peerDependencies) when the app has a version that satisfies the checkout's range; a localized sibling always
267
+ counts. A copy the app's version does not satisfy is kept, with a warning naming
268
+ the package, the range and the app's version. The checkout still builds and runs
269
+ its tests, resolving those packages from the app — this CLI included: npm puts
270
+ every ancestor's `node_modules/.bin` on the `PATH`, so `npx linked build` in a
271
+ checkout runs the app's `linked`. `--no-prune` keeps every checkout's
272
+ `node_modules` as npm left it. The
273
+ A linked package is one whose `package.json` says `"linkedPackage": true` — the
274
+ definition `build-all` and `linked build` use — whatever its npm scope;
275
+ `@_linked/localize`, a plain tool, is not one.
276
+
277
+ The dev server gets the same guarantee from Vite's `resolve.dedupe`, which
278
+ `createViteConfig` derives from what is localized: the localized packages
279
+ themselves, plus every runtime dependency a localized checkout declares that the
280
+ app has at a version satisfying the checkout's range, plus React. A dependency
281
+ whose range the app does not satisfy keeps the checkout's own copy (the dev log
282
+ says which), and so does a name some registry install nests its own copy of —
283
+ a dedupe hands every importer the app's copy without checking versions. With
284
+ nothing localized, only React is deduped. The dedupe covers what Vite loads; the
285
+ removal on disk covers plain Node, `tsx` and test runners, which never read it.
286
+
229
287
  The work is done by [`@_linked/localize`](https://www.npmjs.com/package/@_linked/localize),
230
- which is dependency-free and framework-agnostic; this CLI only supplies the
231
- build command.
288
+ which is dependency-free and framework-agnostic; this CLI supplies the
289
+ build command and the list of what an app provides. That package's own binary, `linked-localize`, is the same mechanism with
290
+ three differences: it builds nothing unless given `--build "<cmd>"`, it treats only localized
291
+ siblings and peerDependencies as provided unless given `--provided "<name>,…"`,
292
+ and its verbs are subcommands —
293
+ `linked-localize adopt <pkg>` and `linked-localize remove <pkg>` where this CLI has
294
+ `linked localize --adopt <pkg>` and `linked delocalize <pkg>`. In a linked app, use
295
+ `linked localize`.
232
296
 
233
297
  ### Registry / dev utilities
234
298
 
@@ -2,7 +2,7 @@
2
2
  # `npm run fuseki:up` starts it and waits for the healthcheck; `npm run fuseki:down` stops it (data persists).
3
3
  services:
4
4
  fuseki:
5
- image: secoresearch/fuseki:5.5.0
5
+ image: secoresearch/fuseki:5.6.0
6
6
  ports:
7
7
  # Override the host port when 3030 is taken (another project's Fuseki); set FUSEKI_BASE_URL to match.
8
8
  - "${FUSEKI_PORT:-3030}:3030"
@@ -1,3 +1,4 @@
1
+ import type { CreatePackageOptions } from './utils/createPackageLocation.js';
1
2
  import type { PackageDetails } from './interfaces.js';
2
3
  /**
3
4
  * Dynamically import the app's backend storage configuration. Tries the
@@ -130,7 +131,7 @@ export declare const startServer: (initOnly?: boolean, ServerClass?: any) => Pro
130
131
  */
131
132
  export declare const buildBackend: () => Promise<boolean>;
132
133
  export declare const upgradePackages: () => Promise<void>;
133
- export declare const createPackage: (name: any, uriBase?: any, basePath?: string) => Promise<void>;
134
+ export declare const createPackage: (name: any, uriBase?: any, basePath?: string, options?: CreatePackageOptions) => Promise<void>;
134
135
  export declare const register: (registryURL: any) => Promise<void>;
135
136
  export declare const buildPackage: (target: any, target2: any, packagePath?: string, logResults?: boolean) => Promise<boolean>;
136
137
  type BuildStep = {
@@ -1 +1 @@
1
- {"version":3,"file":"cli-methods.d.ts","sourceRoot":"","sources":["../../src/cli-methods.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli-methods.d.ts","sourceRoot":"","sources":["../../src/cli-methods.ts"],"names":[],"mappings":"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"}
@@ -17,12 +17,13 @@ import { createInterface } from 'readline';
17
17
  import { debugInfo, execp, execPromise, getFileImports, getFiles, getLastCommitTime, getPackageJSON, isImportOutsideOfPackage, isInternalLinkedImport, needsRebuilding, } from './utils.js';
18
18
  import { renameShippedDotfiles } from './utils/shippedDotfiles.js';
19
19
  import { planPackageSetup } from './utils/packageSetup.js';
20
+ import { bareName, CreatePackageError, decideCreatePackageTarget, ensureRelinkPostinstall, ensureWorkspaceGlob, findLinkedAppRoot, RELINK_COMMAND, repositoryUrlFor, } from './utils/createPackageLocation.js';
20
21
  import { detectPackageManager, execBinCommand, runScriptCommand, } from './utils/packageManager.js';
21
22
  import { rewriteExtensionlessImports } from './utils/esmSpecifiers.js';
22
23
  import { checkShapeNames } from './utils/shapeNames.js';
23
24
  import { checkShapeReferences, inspectShapeReferences, } from './utils/shapeReferences.js';
24
25
  import { checkShapesIndex, checkShapesSideEffects } from './utils/shapesIndex.js';
25
- import { spawn as spawnChild } from 'child_process';
26
+ import { spawn as spawnChild, spawnSync } from 'child_process';
26
27
  import { findNearestPackageJson } from 'find-nearest-package-json';
27
28
  import { statSync } from 'fs';
28
29
  // import pkg from 'lincd/utils/LinkedFileStorage';
@@ -1833,45 +1834,64 @@ export const upgradePackages = () => __awaiter(void 0, void 0, void 0, function*
1833
1834
  // })
1834
1835
  // });
1835
1836
  });
1836
- export const createPackage = (name_1, uriBase_1, ...args_1) => __awaiter(void 0, [name_1, uriBase_1, ...args_1], void 0, function* (name, uriBase, basePath = process.cwd()) {
1837
+ export const createPackage = (name_1, uriBase_1, ...args_1) => __awaiter(void 0, [name_1, uriBase_1, ...args_1], void 0, function* (name, uriBase, basePath = process.cwd(), options = {}) {
1837
1838
  if (!name) {
1838
1839
  console.warn('Please provide a name as the first argument');
1839
1840
  return;
1840
1841
  }
1841
- //if ran with npx, basePath will be the root directory of the repository, even if we're executing from a sub folder (the root directory is where node_modules lives and package.json with workspaces)
1842
- //so we manually find a packages folder, if it exists we go into that.
1843
- if (fs.existsSync(path.join(basePath, 'packages'))) {
1844
- basePath = path.join(basePath, 'packages');
1842
+ const appRoot = findLinkedAppRoot(basePath);
1843
+ const decided = decideCreatePackageTarget({
1844
+ appRoot,
1845
+ options,
1846
+ isTTY: !!(process.stdin.isTTY && process.stdout.isTTY),
1847
+ });
1848
+ if (decided.kind === 'refuse')
1849
+ throw new CreatePackageError(decided.message);
1850
+ const decision = decided.kind === 'ask' ? yield askPackageLocation(name) : decided;
1851
+ //let's remove scope for variable names
1852
+ const cleanPackageName = bareName(name);
1853
+ let targetFolder;
1854
+ if (decision.kind === 'outside') {
1855
+ //if ran with npx, basePath will be the root directory of the repository, even if we're executing from a sub folder (the root directory is where node_modules lives and package.json with workspaces)
1856
+ //so we manually find a packages folder, if it exists we go into that.
1857
+ if (fs.existsSync(path.join(basePath, 'packages'))) {
1858
+ basePath = path.join(basePath, 'packages');
1859
+ }
1860
+ //for lincd.org currently packages are stored in the modules folder
1861
+ else if (fs.existsSync(path.join(basePath, 'modules'))) {
1862
+ basePath = path.join(basePath, 'modules');
1863
+ }
1864
+ targetFolder = path.join(basePath, cleanPackageName);
1845
1865
  }
1846
- //for lincd.org currently packages are stored in the modules folder
1847
- else if (fs.existsSync(path.join(basePath, 'modules'))) {
1848
- basePath = path.join(basePath, 'modules');
1866
+ else if (decision.location === 'packages') {
1867
+ targetFolder = path.join(appRoot, 'packages', cleanPackageName);
1868
+ }
1869
+ else {
1870
+ // localize's own naming, so `linked localize` and this command can never
1871
+ // disagree about where a package lives.
1872
+ const { checkoutNameFor, DEFAULT_DIR } = yield import('@_linked/localize');
1873
+ targetFolder = path.join(appRoot, DEFAULT_DIR, checkoutNameFor(name));
1874
+ }
1875
+ if (fs.existsSync(targetFolder)) {
1876
+ throw new CreatePackageError(`${targetFolder} already exists. Refusing to write a new package over it.`);
1849
1877
  }
1850
- //let's remove scope for variable names
1851
- let [packageName, scope, cleanPackageName] = name.match(/(@[\w\-]+\/)?([\w\-]+)/);
1852
- let targetFolder = ensureFolderExists(basePath, cleanPackageName);
1853
1878
  if (!uriBase) {
1854
1879
  uriBase = defaultOntologyNamespace(name);
1855
1880
  }
1856
1881
  setVariable('uri_base', asNamespace(uriBase));
1857
- //find @scope and the next part between 2 slashes after
1858
- //so @dacore/some-mod/lib/file.js
1859
- // --> match[0] = @dacore/some-mod
1860
- // --> match[1] = @dacore
1861
- // --> match[2] = some-mod
1862
- //but save full scoped package name under ${package_name}
1882
+ //save the full scoped package name under ${package_name}
1863
1883
  setVariable('package_name', name);
1864
1884
  //extra variable for clarity (will be same as 'name')
1865
1885
  setVariable('output_file_name', name);
1866
- let { hyphenName, camelCaseName, underscoreName } = setNameVariables(cleanPackageName);
1886
+ const { hyphenName } = setNameVariables(cleanPackageName);
1867
1887
  log("Creating new linked package '" + name + "'");
1888
+ fs.mkdirSync(targetFolder, { recursive: true });
1868
1889
  fs.copySync(path.join(getScriptDir(), '..', '..', 'defaults', 'package'), targetFolder);
1869
1890
  renameShippedDotfiles(targetFolder);
1870
1891
  //replace variables in some of the copied files
1871
1892
  yield Promise.all([
1872
1893
  'src/index.ts',
1873
1894
  'package.json',
1874
- 'Gruntfile.js',
1875
1895
  'src/package.ts',
1876
1896
  'src/ontologies/example-ontology.ts',
1877
1897
  'src/ontologies/example-ontology.register.ts',
@@ -1898,37 +1918,189 @@ export const createPackage = (name_1, uriBase_1, ...args_1) => __awaiter(void 0,
1898
1918
  console.log('rename ', path.join(targetFolder, f), path.join(targetFolder, ...newParts, newName));
1899
1919
  fs.renameSync(path.join(targetFolder, f), path.join(targetFolder, ...newParts, newName));
1900
1920
  });
1901
- // npm is the default for a new package. yarn is only consulted when the new
1902
- // package lands inside an existing yarn project (a yarn-3 monorepo),
1903
- // where adding an npm lockfile would break the workspace.
1904
- const insideYarnProject = detectPackageManager(path.dirname(path.resolve(targetFolder))) === 'yarn';
1905
- let version = insideYarnProject
1906
- ? (yield execPromise('yarn --version').catch(() => {
1907
- console.log('yarn probably not working');
1908
- return '';
1909
- }))
1910
- : '';
1911
- const setup = planPackageSetup(version.toString(), path.join(getScriptDir(), 'launch.js'), process.execPath, insideYarnProject);
1912
- if (setup.yarnrc) {
1913
- fs.writeFileSync(path.join(targetFolder, '.yarnrc.yml'), setup.yarnrc);
1914
- }
1915
- const installed = yield execp(setup.installCommand, true, false, {
1916
- cwd: targetFolder,
1917
- })
1918
- .then(() => true)
1919
- .catch(() => {
1920
- console.warn(`Could not install dependencies (${setup.installCommand})`);
1921
- process.exitCode = 1;
1922
- return false;
1921
+ if (decision.kind === 'outside') {
1922
+ yield installStandalonePackage(targetFolder);
1923
+ }
1924
+ else if (decision.location === 'packages') {
1925
+ yield installWorkspacePackage(name, targetFolder, appRoot);
1926
+ }
1927
+ else {
1928
+ yield installOwnRepoPackage(name, targetFolder, appRoot, decision);
1929
+ }
1930
+ });
1931
+ /**
1932
+ * Ask where a new package goes — only ever on a terminal, and only when no
1933
+ * flag said so already.
1934
+ */
1935
+ function askPackageLocation(name) {
1936
+ return __awaiter(this, void 0, void 0, function* () {
1937
+ console.log(`\nWhere should ${chalk.magenta(name)} live?\n` +
1938
+ ` 1) packages/ part of this app's repository\n` +
1939
+ ` 2) packages-local/ its own git repository, linked into this app\n`);
1940
+ let answer = '';
1941
+ while (answer !== '1' && answer !== '2') {
1942
+ answer = yield promptUser('Choose 1 or 2: ');
1943
+ }
1944
+ if (answer === '1')
1945
+ return { kind: 'resolved', location: 'packages', push: false };
1946
+ const remote = yield promptUser('Remote git URL for its repository (optional, Enter to skip): ');
1947
+ const push = !!remote &&
1948
+ /^y(es)?$/i.test(yield promptUser(`Push the first commit to ${remote}? (y/N): `));
1949
+ return Object.assign(Object.assign({ kind: 'resolved', location: 'packages-local' }, (remote ? { remote } : {})), { push });
1950
+ });
1951
+ }
1952
+ /** The install + first build plan for a package, given where it installs from. */
1953
+ function packageSetupFor(installRoot) {
1954
+ return __awaiter(this, void 0, void 0, function* () {
1955
+ // npm is the default for a new package. yarn is only consulted when the new
1956
+ // package lands inside an existing yarn project (a yarn-3 monorepo),
1957
+ // where adding an npm lockfile would break the workspace.
1958
+ const insideYarnProject = detectPackageManager(installRoot) === 'yarn';
1959
+ let version = insideYarnProject
1960
+ ? (yield execPromise('yarn --version').catch(() => {
1961
+ console.log('yarn probably not working');
1962
+ return '';
1963
+ }))
1964
+ : '';
1965
+ return planPackageSetup(version.toString(), path.join(getScriptDir(), 'launch.js'), process.execPath, insideYarnProject);
1923
1966
  });
1924
- if (installed) {
1925
- yield execp(setup.buildCommand, true, false, { cwd: targetFolder }).catch(() => {
1926
- console.warn('Dependencies installed, but the initial build failed');
1967
+ }
1968
+ /**
1969
+ * Install `cwd` with `setup`, then build `targetFolder`. Failures set the exit
1970
+ * code; `installFailedHint` says what was already changed when the install fails.
1971
+ */
1972
+ function installThenBuild(setup_1, cwd_1, targetFolder_1) {
1973
+ return __awaiter(this, arguments, void 0, function* (setup, cwd, targetFolder, installFailedHint = '') {
1974
+ const installed = yield execp(setup.installCommand, true, false, { cwd })
1975
+ .then(() => true)
1976
+ .catch(() => {
1977
+ console.warn(`Could not install dependencies (${setup.installCommand})` +
1978
+ (installFailedHint ? `. ${installFailedHint}` : ''));
1927
1979
  process.exitCode = 1;
1980
+ return false;
1928
1981
  });
1982
+ if (installed) {
1983
+ yield execp(setup.buildCommand, true, false, { cwd: targetFolder }).catch(() => {
1984
+ console.warn('Dependencies installed, but the initial build failed');
1985
+ process.exitCode = 1;
1986
+ });
1987
+ }
1988
+ });
1989
+ }
1990
+ /** Outside an app: install inside the package itself, as this command always has. */
1991
+ function installStandalonePackage(targetFolder) {
1992
+ return __awaiter(this, void 0, void 0, function* () {
1993
+ const setup = yield packageSetupFor(path.dirname(path.resolve(targetFolder)));
1994
+ if (setup.yarnrc) {
1995
+ fs.writeFileSync(path.join(targetFolder, '.yarnrc.yml'), setup.yarnrc);
1996
+ }
1997
+ yield installThenBuild(setup, targetFolder, targetFolder);
1998
+ log(`Prepared a new linked package in ${chalk.magenta(targetFolder)}`, `Run ${chalk.blueBright(runScriptCommand(setup.packageManager, 'build'))} from this directory to build once`, `Or ${chalk.blueBright(runScriptCommand(setup.packageManager, 'start'))} to continuously rebuild on file changes`);
1999
+ });
2000
+ }
2001
+ /**
2002
+ * packages/: a workspace member of the app's own repository. The app's
2003
+ * workspaces must cover it and its dependencies declare it — npm links a
2004
+ * workspace member by name, and `build-all` builds what the app depends on —
2005
+ * and the install runs at the app root, where the workspace is.
2006
+ */
2007
+ function installWorkspacePackage(name, targetFolder, appRoot) {
2008
+ return __awaiter(this, void 0, void 0, function* () {
2009
+ const appPkgPath = path.join(appRoot, 'package.json');
2010
+ const appPkg = fs.readJsonSync(appPkgPath);
2011
+ const workspaces = ensureWorkspaceGlob(appPkg);
2012
+ if (workspaces.warning)
2013
+ console.warn(chalk.yellow(workspaces.warning));
2014
+ const version = fs.readJsonSync(path.join(targetFolder, 'package.json')).version;
2015
+ appPkg.dependencies = Object.assign(Object.assign({}, appPkg.dependencies), { [name]: `^${version}` });
2016
+ fs.writeJsonSync(appPkgPath, appPkg, { spaces: 2 });
2017
+ log(`Added ${name}@^${version} to ${path.relative(process.cwd(), appPkgPath) || 'package.json'}` +
2018
+ (workspaces.changed ? ' and packages/* to its workspaces' : ''));
2019
+ const setup = yield packageSetupFor(appRoot);
2020
+ yield installThenBuild(setup, appRoot, targetFolder, `The app's package.json already declares ${name}; run the install again at the app root once it is fixed.`);
2021
+ log(`Prepared a new linked package in ${chalk.magenta(targetFolder)}, part of this app's repository`, `Run ${chalk.blueBright(runScriptCommand(setup.packageManager, 'start'))} in it to continuously rebuild on file changes`);
2022
+ });
2023
+ }
2024
+ /**
2025
+ * packages-local/: a repository of its own. Its git history starts here, and
2026
+ * localize's `adopt` installs, builds, links and records it. The app's
2027
+ * dependencies are NOT touched: until the package is published a version range
2028
+ * fails `npm install` (E404 once a lockfile exists), and a `file:` path would
2029
+ * install cleanly for a teammate without the checkout and fail at runtime.
2030
+ */
2031
+ function installOwnRepoPackage(name, targetFolder, appRoot, decision) {
2032
+ return __awaiter(this, void 0, void 0, function* () {
2033
+ const { remote, push } = decision;
2034
+ const rel = path.relative(appRoot, targetFolder);
2035
+ const pkgPath = path.join(targetFolder, 'package.json');
2036
+ const fail = (message) => {
2037
+ console.warn(chalk.yellow(message));
2038
+ process.exitCode = 1;
2039
+ };
2040
+ if (!git(['init', '--quiet'], targetFolder)) {
2041
+ return fail(`git init failed in ${rel}; the package is scaffolded but not linked.`);
2042
+ }
2043
+ if (remote) {
2044
+ if (!git(['remote', 'add', 'origin', remote], targetFolder)) {
2045
+ return fail(`git remote add origin ${remote} failed in ${rel}; nothing was linked.`);
2046
+ }
2047
+ const pkg = fs.readJsonSync(pkgPath);
2048
+ pkg.repository = { type: 'git', url: repositoryUrlFor(remote) };
2049
+ fs.writeJsonSync(pkgPath, pkg, { spaces: 2 });
2050
+ }
2051
+ // Before adopt, never during it: adopt asserts the app's package.json did not
2052
+ // change while it ran.
2053
+ const appPkgPath = path.join(appRoot, 'package.json');
2054
+ const appPkg = fs.readJsonSync(appPkgPath);
2055
+ if (ensureRelinkPostinstall(appPkg)) {
2056
+ fs.writeJsonSync(appPkgPath, appPkg, { spaces: 2 });
2057
+ log(`Added \`${RELINK_COMMAND}\` to the app's postinstall, so npm install keeps the link`);
2058
+ }
2059
+ const { adoptPackage } = yield import('./commands/localize.js');
2060
+ const { EXIT_WARNED } = yield import('@_linked/localize');
2061
+ // Only the build command matters here: adopt always installs with npm, so
2062
+ // the package-manager half of the plan does not apply.
2063
+ const { buildCommand } = planPackageSetup('', path.join(getScriptDir(), 'launch.js'), process.execPath);
2064
+ const code = yield adoptPackage(name, { appRoot, build: buildCommand });
2065
+ if (code === EXIT_WARNED) {
2066
+ fail('The package is linked, but its initial build failed');
2067
+ }
2068
+ else if (code !== 0) {
2069
+ return fail(`Linking ${name} failed (localize exit ${code}). ${rel} is scaffolded with an uncommitted ` +
2070
+ `git init, and the app's postinstall relinks localized packages. Fix the cause and retry ` +
2071
+ `with: linked localize ${name} --adopt`);
2072
+ }
2073
+ const committed = git(['add', '-A'], targetFolder) &&
2074
+ git(['commit', '--quiet', '-m', `feat: scaffold ${name}`], targetFolder);
2075
+ if (!committed) {
2076
+ fail(`Could not make the first commit in ${rel} (is git's user.name/user.email set?). ` +
2077
+ `The package is linked; commit it yourself.`);
2078
+ }
2079
+ let pushed = false;
2080
+ if (push && committed) {
2081
+ pushed = git(['push', '--quiet', '-u', 'origin', 'HEAD'], targetFolder);
2082
+ if (!pushed)
2083
+ fail(`Could not push to ${remote}. Push it yourself: git push -u origin HEAD`);
2084
+ }
2085
+ const version = fs.readJsonSync(pkgPath).version;
2086
+ log(`Prepared ${name} in ${chalk.magenta(rel)}, in its own git repository` +
2087
+ (remote ? ` (origin ${remote}${pushed ? ', pushed' : ''})` : ' (no remote yet)'), `It is linked into node_modules and recorded in local-packages.json.`, `It is not in the app's dependencies: until it is published a version range would fail npm install.`, ` After publishing: ${chalk.blueBright(`npm install ${name}@^${version}`)}`);
2088
+ if (!remote) {
2089
+ log(`To add a remote later: ${chalk.blueBright('git remote add origin <url>')} in ${rel}, ` +
2090
+ `then ${chalk.blueBright(`linked localize ${name} --adopt`)} to record it.`);
2091
+ }
2092
+ });
2093
+ }
2094
+ /** Run git with arguments (no shell, so a URL is never re-parsed). Echoes failures. */
2095
+ function git(args, cwd) {
2096
+ var _a;
2097
+ const r = spawnSync('git', args, { cwd, encoding: 'utf8' });
2098
+ if (r.status !== 0) {
2099
+ console.warn((r.stderr || r.stdout || String((_a = r.error) !== null && _a !== void 0 ? _a : '')).trim());
2100
+ return false;
1929
2101
  }
1930
- log(`Prepared a new linked package in ${chalk.magenta(targetFolder)}`, `Run ${chalk.blueBright(runScriptCommand(setup.packageManager, 'build'))} from this directory to build once`, `Or ${chalk.blueBright(runScriptCommand(setup.packageManager, 'start'))} to continuously rebuild on file changes`);
1931
- });
2102
+ return true;
2103
+ }
1932
2104
  var getNextVersion = function (version) {
1933
2105
  let parts = version.split('.');
1934
2106
  return parts[0] + '.' + parts[1] + '.' + (parseInt(parts[2]) + 1).toString();