@_linked/cli 1.15.0 → 1.17.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 (36) hide show
  1. package/CHANGELOG.md +119 -0
  2. package/README.md +4 -5
  3. package/defaults/app-react-native/README.md +1 -1
  4. package/defaults/app-react-native/apps/mobile/src/components/PersonOverview.tsx +1 -1
  5. package/defaults/app-react-native/apps/mobile/src/components/PersonPreview.tsx +1 -1
  6. package/defaults/package/package.json +6 -6
  7. package/lib/esm/cli-methods.d.ts +28 -0
  8. package/lib/esm/cli-methods.d.ts.map +1 -1
  9. package/lib/esm/cli-methods.js +89 -93
  10. package/lib/esm/cli-methods.js.map +1 -1
  11. package/lib/esm/cli.js +1 -1
  12. package/lib/esm/cli.js.map +1 -1
  13. package/lib/esm/commands/build-package.d.ts.map +1 -1
  14. package/lib/esm/commands/build-package.js +18 -10
  15. package/lib/esm/commands/build-package.js.map +1 -1
  16. package/lib/esm/commands/start.d.ts +12 -0
  17. package/lib/esm/commands/start.d.ts.map +1 -1
  18. package/lib/esm/commands/start.js +59 -9
  19. package/lib/esm/commands/start.js.map +1 -1
  20. package/lib/esm/config-webpack.js +2 -2
  21. package/lib/esm/config-webpack.js.map +1 -1
  22. package/lib/esm/utils/packageManager.d.ts +22 -0
  23. package/lib/esm/utils/packageManager.d.ts.map +1 -0
  24. package/lib/esm/utils/packageManager.js +48 -0
  25. package/lib/esm/utils/packageManager.js.map +1 -0
  26. package/lib/esm/utils/packageSetup.d.ts +6 -1
  27. package/lib/esm/utils/packageSetup.d.ts.map +1 -1
  28. package/lib/esm/utils/packageSetup.js +14 -3
  29. package/lib/esm/utils/packageSetup.js.map +1 -1
  30. package/lib/esm/utils.js +1 -1
  31. package/lib/esm/utils.js.map +1 -1
  32. package/lib/esm/vite-config.d.ts +17 -0
  33. package/lib/esm/vite-config.d.ts.map +1 -1
  34. package/lib/esm/vite-config.js +42 -8
  35. package/lib/esm/vite-config.js.map +1 -1
  36. package/package.json +10 -9
package/CHANGELOG.md CHANGED
@@ -1,5 +1,124 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.17.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#94](https://github.com/linked-fw/cli/pull/94) [`b4140fd`](https://github.com/linked-fw/cli/commit/b4140fdb7ed0face4978d5436e0cee2876eb1d09) Thanks [@flyon](https://github.com/flyon)! - npm is now the CLI's default package manager; yarn is detected, not assumed.
8
+
9
+ A new `detectPackageManager()` walks up from the directory being acted on and
10
+ only reports `yarn` when the tree actually is a yarn project (`yarn.lock`,
11
+ `.yarnrc.yml`, a vendored `.yarn/releases/`). The nearest marker wins, so an npm
12
+ package checked out inside a yarn workspace is treated as npm. Everything else
13
+ is npm. Existing yarn monorepos keep working; `linked yarn` (safe-yarn) is
14
+ unchanged.
15
+
16
+ What changed per command:
17
+
18
+ - `linked build-workspace` runs each package's build with `npm run build`
19
+ instead of always `yarn build` (still `yarn build` inside a yarn workspace).
20
+ - `linked build <path>` (the editor hook) invokes the `linked` binary via
21
+ `npx --no-install` instead of always `yarn exec` (yarn, including a vendored
22
+ release, is still used inside a yarn workspace).
23
+ - `linked create-package` installs with npm unless the new package lands inside
24
+ an existing yarn project. `planPackageSetup()` gained an
25
+ `insideYarnProject` argument; having yarn on `PATH` no longer selects it. The
26
+ closing hint now names the package manager that was actually used.
27
+ - `linked publish` uses `npm version … --no-git-tag-version && npm publish`
28
+ outside a yarn project (Berry's `yarn version` / `yarn npm publish` is kept
29
+ inside one).
30
+ - The backend TS compile step uses `npx --no-install tsc` outside a yarn
31
+ project.
32
+ - Capacitor setup installs with npm and writes `npx cap …` / `npm run …`
33
+ scripts instead of `yarn cap …`.
34
+ - The `create-package` template (`defaults/package/package.json`) builds with
35
+ `npm run …` and bare local bins, so a scaffolded package no longer needs yarn.
36
+
37
+ Also: the CLI's own `build`, `dev`, `test` and `format` scripts no longer shell
38
+ out to `yarn`, so `npm run build` works without yarn installed (previously it
39
+ failed under Yarn Berry with "the nearest package directory doesn't seem to be
40
+ part of the project", and needed a Yarn 1 shim). Stale yarn mentions in the
41
+ README, help text and comments now say npm.
42
+
43
+ ### Patch Changes
44
+
45
+ - [#94](https://github.com/linked-fw/cli/pull/94) [`2ec3601`](https://github.com/linked-fw/cli/commit/2ec3601cd473ffbcbd6bfd5fdf4031c28efb48ab) Thanks [@flyon](https://github.com/flyon)! - Declare npm as the package manager for this repo and mark `package-lock.json` as a generated file.
46
+
47
+ ## 1.16.0
48
+
49
+ ### Minor Changes
50
+
51
+ - [#93](https://github.com/linked-fw/cli/pull/93) [`4b944dc`](https://github.com/linked-fw/cli/commit/4b944dc5a0a37b7858cb8f34d078879965f8b648) Thanks [@flyon](https://github.com/flyon)! - `create-app` now scaffolds web apps with npm.
52
+
53
+ The web template used to install with yarn (and prompted for a package manager
54
+ when both were on PATH); it now always runs `npm install`, matching the
55
+ react-native template, and the next-steps message prints `npm start`. The empty
56
+ `yarn.lock` that create-app wrote to pin down Yarn's project-root search is no
57
+ longer created, so a new app has a single npm lockfile.
58
+
59
+ create-app also strips every yarn project file from the clone (the legacy
60
+ `yarnrc.yml.template` it used to rename into `.yarnrc.yml`, plus `.yarnrc.yml`,
61
+ `.yarn/` and any `yarn.lock` the template still carries), so a scaffolded app is
62
+ an npm project end to end.
63
+
64
+ ## 1.15.3
65
+
66
+ ### Patch Changes
67
+
68
+ - [#73](https://github.com/linked-cm/cli/pull/73) [`92e8f6b`](https://github.com/linked-cm/cli/commit/92e8f6ba07b80f3a72adae9238bd855fc94869b6) Thanks [@abdipramana](https://github.com/abdipramana)! - `linked start --vite`: widen development config discovery so apps that predate
69
+ the current filenames still start.
70
+
71
+ - The app's linked config is now looked up as `linked.config.js` **or** the
72
+ legacy `lincd.config.js` (current name wins when both exist). Apps that never
73
+ renamed the file silently lost their whole `server` block — `cachePaths`,
74
+ `apiOnly` and the rest of LinkedServer's options — because only the new name
75
+ was read. The lookup is exposed as `resolveLinkedConfigPath()`.
76
+ - SSR page discovery also skips `*.d.ts` files in `src/pages/` (alongside the
77
+ existing `.test` / `.spec` skip). Type declarations have no runtime module,
78
+ so preloading them into the SSR graph only produced errors.
79
+ - The backend storage config is discovered under several legacy filenames
80
+ (`backend-storage-config.*`, `scripts/backend-storage-config.*`,
81
+ `scripts/storage-config.js`) in addition to `linked.backend.storage.*`.
82
+
83
+ ## 1.15.2
84
+
85
+ ### Patch Changes
86
+
87
+ - [#71](https://github.com/linked-cm/cli/pull/71) [`b3e482b`](https://github.com/linked-cm/cli/commit/b3e482bdd55a43fb5fe9a11ab58d06e6bea66f5d) Thanks [@carlenmy](https://github.com/carlenmy)! - `createViteConfig`: give each app a unique HMR websocket port, derived from its
88
+ dev port (`PORT` env override, else `opts.port`), instead of Vite's shared
89
+ default `24678`.
90
+
91
+ Every app built on `createViteConfig` defaulted to `24678` for HMR, so running
92
+ two of them at once (parallel worktrees / multiple `@_linked` apps on one
93
+ machine) collided — `WebSocket server error: Port 24678 is already in use`, and
94
+ HMR silently broke for the loser. The port is now `24678 + (devPort - 4040)`, so
95
+ apps that already use distinct dev ports get distinct HMR ports for free.
96
+
97
+ The derivation lives in the new exported `hmrPortFor()` helper and is defensive
98
+ about its input: a `PORT` that is not a whole port number (`PORT=abc`, a
99
+ negative or out-of-range value) falls back to the `4040` default rather than
100
+ producing `NaN`, and the derived port is clamped into `1024`–`65535`. Apps can
101
+ still override via `server.hmr` in their own merged config.
102
+
103
+ ## 1.15.1
104
+
105
+ ### Patch Changes
106
+
107
+ - [#72](https://github.com/linked-cm/cli/pull/72) [`3bab3ab`](https://github.com/linked-cm/cli/commit/3bab3ab287ad72dff74c21f15d93a6229702b0e6) Thanks [@flyon](https://github.com/flyon)! - Backend provider HMR reloads are now debounced and serialised.
108
+
109
+ `vite.watcher.on('change')` called `server.onSourceChange(pkg)` once per changed
110
+ file with no debounce and no queue. Since `onSourceChange` disposes a package's
111
+ providers and re-registers their Express routes, it mutates the shared router
112
+ stack — and a multi-file save, a format-on-save, or a branch switch ran several
113
+ of those dispose/re-register cycles concurrently against that same stack with
114
+ nothing ordering them.
115
+
116
+ Changed packages are now collected over a 150 ms window and their reload cycles
117
+ run one at a time on a promise chain. Reload failures are still logged per
118
+ package and no longer abort the cycles queued behind them.
119
+
120
+ No API change; dev-server behaviour only.
121
+
3
122
  ## 1.15.0
4
123
 
5
124
  ### Minor Changes
package/README.md CHANGED
@@ -6,8 +6,6 @@ Command-line tools for the `@_linked/*` packages and apps.
6
6
 
7
7
  ```bash
8
8
  npm install --save-dev @_linked/cli
9
- # or
10
- yarn add -D @_linked/cli
11
9
  ```
12
10
 
13
11
  ## Binaries
@@ -129,7 +127,8 @@ API-only mode is never inferred: a web app without a `vite.config.*` and without
129
127
 
130
128
  ```bash
131
129
  cd packages/cli
132
- yarn build
130
+ npm install
131
+ npm run build
133
132
  ```
134
133
 
135
134
  Dual ESM + CJS build via `tsconfig-to-dual-package`. Sources in `src/`, output in `lib/esm/` and `lib/cjs/`.
@@ -145,7 +144,7 @@ Templates live in `defaults/`:
145
144
 
146
145
  ### `linked create-app` template structure
147
146
 
148
- `linked create-app <name>` copies `defaults/app-with-backend/` to the new app's folder, substitutes `${name}` / `${hyphen_name}` / `${app_prefix}` / `${app_domain}` placeholders in selected files, and copies `linked.backend.datasets.example.json` → `linked.backend.datasets.json` so first boot works zero-config.
147
+ `linked create-app <name>` copies `defaults/app-with-backend/` to the new app's folder, substitutes `${name}` / `${hyphen_name}` / `${app_prefix}` / `${app_domain}` placeholders in selected files, and copies `linked.backend.datasets.example.json` → `linked.backend.datasets.json` so first boot works zero-config. Dependencies are installed with `npm install`, and the next-steps message tells you to run `npm start`.
149
148
 
150
149
  Storage configuration follows the two-layer pattern from [backlog 016](https://github.com/c### `linked create-app --template react-native`
151
150
 
@@ -208,7 +207,7 @@ cd apps/mobile && npx expo export --platform ios --output-dir /tmp/export
208
207
 
209
208
  To run it: `npm run fuseki:up`, `npm run api`, then `cd apps/mobile && npx expo run:ios`.
210
209
 
211
- Tests for this template in this repo: `yarn test:unit` covers the scaffold offline, using the fixture in
210
+ Tests for this template in this repo: `npm run test:unit` covers the scaffold offline, using the fixture in
212
211
  `tests/fixtures/app-react-native-min` and the real template. `npm run test:template` runs the built CLI with
213
212
  install, then checks the generated files, `check:react`, lint, typecheck, `npm test`, the shapes build and a
214
213
  Metro iOS bundle. It builds nothing itself, needs network and takes several minutes.
@@ -1,6 +1,6 @@
1
1
  # Linked React Native monorepo
2
2
 
3
- An npm-workspaces monorepo for a [Linked](https://github.com/linked-cm) app on Expo SDK 57 / React Native 0.86 /
3
+ An npm-workspaces monorepo for a [Linked](https://github.com/linked-fw) app on Expo SDK 57 / React Native 0.86 /
4
4
  React 19.2, with an API-only Linked backend on Fuseki.
5
5
 
6
6
  ```
@@ -2,7 +2,7 @@
2
2
  // linkedSetComponent for the list (auto-runs the query, injects results and
3
3
  // an injected _refresh); linkedComponent for each row (see PersonPreview).
4
4
  // After Person.create the form calls _refresh() to re-run the list query.
5
- // A React Native port of the web app-template's example (linked-cm/app-template).
5
+ // A React Native port of the web app-template's example (linked-fw/app-template).
6
6
  //
7
7
  // `linkedSetComponent` checks LinkedStorage when this module loads, so storage is imported first.
8
8
  // Replace or extend this with your own shapes (see https://linked.cm).
@@ -3,7 +3,7 @@
3
3
  // result keys + `source` + `_refresh` into the render function. _refresh
4
4
  // patches local query state for optimistic UI; on delete, the parent
5
5
  // list re-runs via the PersonListRefresh context.
6
- // A React Native port of the web app-template's example (linked-cm/app-template).
6
+ // A React Native port of the web app-template's example (linked-fw/app-template).
7
7
  // Storage is imported first, so the row's queries go to the API store however this module is reached.
8
8
  import '../shell/storage';
9
9
 
@@ -17,12 +17,12 @@
17
17
  "types": "lib/esm/index.d.ts",
18
18
  "license": "ISC",
19
19
  "scripts": {
20
- "start": "yarn linked dev",
21
- "build": "rimraf ./lib && yarn build-esm && yarn build-cjs && yarn copy-to-lib && yarn dual-package",
22
- "build-esm": "echo \"compiling ESM\" && rimraf ./lib/esm && yarn tsc -p tsconfig-esm.json",
23
- "build-cjs": "echo \"compiling CJS\" && rimraf ./lib/cjs && yarn tsc -p tsconfig-cjs.json",
24
- "copy-to-lib": "echo 'copying CSS + JSON assets to lib folder' && yarn copyfiles -u 1 'src/**/*.css' 'src/**/*.json' lib/esm && yarn copyfiles -u 1 'src/**/*.css' 'src/**/*.json' lib/cjs",
25
- "dual-package": "echo 'adding package.json to each lib folder for dual output support' && yarn tsconfig-to-dual-package ./tsconfig-cjs.json ./tsconfig-esm.json"
20
+ "start": "linked dev",
21
+ "build": "rimraf ./lib && npm run build-esm && npm run build-cjs && npm run copy-to-lib && npm run dual-package",
22
+ "build-esm": "echo \"compiling ESM\" && rimraf ./lib/esm && tsc -p tsconfig-esm.json",
23
+ "build-cjs": "echo \"compiling CJS\" && rimraf ./lib/cjs && tsc -p tsconfig-cjs.json",
24
+ "copy-to-lib": "echo 'copying CSS + JSON assets to lib folder' && copyfiles -u 1 'src/**/*.css' 'src/**/*.json' lib/esm && copyfiles -u 1 'src/**/*.css' 'src/**/*.json' lib/cjs",
25
+ "dual-package": "echo 'adding package.json to each lib folder for dual output support' && tsconfig-to-dual-package ./tsconfig-cjs.json ./tsconfig-esm.json"
26
26
  },
27
27
  "keywords": [
28
28
  "linked",
@@ -52,6 +52,24 @@ export declare function scaffoldReactNativeApp(targetFolder: string, id: AppIden
52
52
  export declare const reactNativeInternals: {
53
53
  scaffoldReactNativeApp: typeof scaffoldReactNativeApp;
54
54
  };
55
+ /**
56
+ * Stamp the new app's identity into the freshly-cloned template. The template
57
+ * ships without `${var}` placeholders (so a raw CN clone boots on defaults), so
58
+ * create-app writes the real per-app values here:
59
+ * - `.env.example` (committed defaults for this app) + `.env` (local): APP_NAME
60
+ * drives the display name; APP_PREFIX names data files.
61
+ * - `package.json`: `name` (hyphenated id) + `displayName` (human name).
62
+ * - `src/package.ts`: the runtime `linkedPackage` id — shape URIs derive from it.
63
+ * - pm2 process names + the VS Code launch name (cosmetic, but should match).
64
+ */
65
+ /**
66
+ * Scaffolded apps are npm apps, so the new app must not also look like a yarn
67
+ * project. Removes every yarn project file a template clone may still carry —
68
+ * including the legacy `yarnrc.yml.template` that create-app used to rename
69
+ * into `.yarnrc.yml`. (No empty `yarn.lock` is written any more either; that
70
+ * file only existed to pin down Yarn's project-root search.)
71
+ */
72
+ export declare function stripYarnProjectFiles(targetFolder: string): void;
55
73
  export declare function warn(...messages: any[]): void;
56
74
  export declare function logError(...errors: any[]): void;
57
75
  export declare function developPackage(target: any, mode: any): void;
@@ -60,6 +78,16 @@ export declare function buildAll(options: any): void;
60
78
  export declare const createOntology: (prefix: any, uriBase?: any, basePath?: string) => Promise<void>;
61
79
  export declare const addShapeToBarrel: (shapeHyphenName: string, root?: string) => string;
62
80
  export declare const addLineToIndex: (line: any, insertMatchString: string, root?: string, insertAtStart?: boolean) => string;
81
+ export type PackageManager = 'npm' | 'yarn';
82
+ /**
83
+ * The package manager `create-app` scaffolds with. Both templates (web and
84
+ * react-native) install with npm, so a scaffolded app has exactly one lockfile.
85
+ */
86
+ export declare const CREATE_APP_PACKAGE_MANAGER: PackageManager;
87
+ /** The shell command that installs a scaffolded app's dependencies. */
88
+ export declare function installCommandFor(pm: PackageManager): string;
89
+ /** The command printed to the user for starting their new app. */
90
+ export declare function startCommandFor(pm: PackageManager): string;
63
91
  export declare const setNameVariables: (name: any) => {
64
92
  hyphenName: any;
65
93
  camelCaseName: any;
@@ -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,6 +17,7 @@ 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 { detectPackageManager, execBinCommand, runScriptCommand, } from './utils/packageManager.js';
20
21
  import { rewriteExtensionlessImports } from './utils/esmSpecifiers.js';
21
22
  import { spawn as spawnChild } from 'child_process';
22
23
  import { findNearestPackageJson } from 'find-nearest-package-json';
@@ -124,7 +125,7 @@ export const createApp = (name_1, ...args_1) => __awaiter(void 0, [name_1, ...ar
124
125
  // Scaffold from the canonical template repo (single source of truth; CN's
125
126
  // server-side createProject clones the same repo). Shallow clone, then drop
126
127
  // .git so the new app starts with clean history.
127
- yield execPromise(`git clone --depth 1 https://github.com/linked-cm/app-template.git "${targetFolder}"`, false, false);
128
+ yield execPromise(`git clone --depth 1 https://github.com/linked-fw/app-template.git "${targetFolder}"`, false, false);
128
129
  fs.removeSync(path.join(targetFolder, '.git'));
129
130
  //make sure the data folder exists (even though its empty).. copying empty folders does not work with fs.copySync
130
131
  fs.mkdirSync(path.join(targetFolder, 'data'), { recursive: true });
@@ -137,19 +138,7 @@ export const createApp = (name_1, ...args_1) => __awaiter(void 0, [name_1, ...ar
137
138
  if (fs.existsSync(gitignoreTemplate)) {
138
139
  fs.renameSync(gitignoreTemplate, path.join(targetFolder, '.gitignore'));
139
140
  }
140
- const yarnrcTemplate = path.join(targetFolder, 'yarnrc.yml.template');
141
- if (fs.existsSync(yarnrcTemplate)) {
142
- fs.renameSync(yarnrcTemplate, path.join(targetFolder, '.yarnrc.yml'));
143
- }
144
- // Mark the new app as a self-contained Yarn project root. Without this,
145
- // Yarn climbs ancestor dirs looking for the project root and may decide
146
- // a stray yarn.lock further up the tree is "the project" — aborting
147
- // install with "the nearest package directory doesn't seem to be part
148
- // of the project declared in <ancestor>".
149
- const yarnLockPath = path.join(targetFolder, 'yarn.lock');
150
- if (!fs.existsSync(yarnLockPath)) {
151
- fs.writeFileSync(yarnLockPath, '');
152
- }
141
+ stripYarnProjectFiles(targetFolder);
153
142
  // Seed the real (gitignored) Layer 2 config from the committed example so
154
143
  // the scaffolded app boots first try. Users can edit either file later.
155
144
  const datasetsExample = path.join(targetFolder, 'linked.backend.datasets.example.json');
@@ -165,17 +154,13 @@ export const createApp = (name_1, ...args_1) => __awaiter(void 0, [name_1, ...ar
165
154
  // create-app stamps this app's identity into the clone directly rather than
166
155
  // relying on ${var} substitution.
167
156
  applyAppIdentity(targetFolder, { appName, appPrefix, hyphenName });
168
- // Pick a package manager. When both are available and the user is running
169
- // create-app interactively, ask. Carry the choice through both the install
170
- // step AND the final "next command" message so the user can copy-paste.
171
- const interactive = !(options.appName ||
172
- options.appPrefix ||
173
- options.appDomain);
174
- const pm = yield choosePackageManager(interactive);
157
+ // New apps are npm apps: npm is the package manager the templates, the CI
158
+ // workflows and the published @_linked/* packages are all tested against, and
159
+ // the react-native template already installs with npm. Keeping a single
160
+ // package manager also keeps the scaffolded app to a single lockfile.
161
+ const pm = CREATE_APP_PACKAGE_MANAGER;
175
162
  if (!options.skipInstall) {
176
- const installCommand = pm === 'yarn'
177
- ? 'export NODE_OPTIONS="--no-network-family-autoselection" && yarn install'
178
- : 'npm install';
163
+ const installCommand = installCommandFor(pm);
179
164
  const spinner = ora({
180
165
  text: `Installing dependencies (${pm})...`,
181
166
  spinner: 'dots',
@@ -207,7 +192,7 @@ export const createApp = (name_1, ...args_1) => __awaiter(void 0, [name_1, ...ar
207
192
  }
208
193
  }
209
194
  }
210
- const startCommand = pm === 'yarn' ? 'yarn start' : 'npm start';
195
+ const startCommand = startCommandFor(pm);
211
196
  log(`Your Linked app is ready at ${chalk.blueBright(targetFolder)}`, `\nStorage: linked.backend.storage.ts wires aliases to stores; linked.backend.datasets.json holds endpoints.`, `Defaults to Fuseki at ${chalk.cyan('http://localhost:3030')} (auto-creates the dataset on first boot).`, `Make sure Fuseki is running, e.g.:`, ` ${chalk.blueBright('docker run -d --rm -p 3030:3030 --name fuseki stain/jena-fuseki')}`, `Edit ${chalk.cyan('linked.backend.datasets.json')} to change endpoints or credentials.`, `Mirror file for the frontend: ${chalk.cyan('src/linked.frontend.storage.ts')} + ${chalk.cyan('src/linked.frontend.datasets.json')}.`, `\nTo start:`, ` ${chalk.blueBright(`cd ${hyphenName} && ${startCommand}`)}`);
212
197
  });
213
198
  /**
@@ -391,9 +376,26 @@ function setEnvVar(envText, key, value) {
391
376
  * - `src/package.ts`: the runtime `linkedPackage` id — shape URIs derive from it.
392
377
  * - pm2 process names + the VS Code launch name (cosmetic, but should match).
393
378
  */
379
+ /**
380
+ * Scaffolded apps are npm apps, so the new app must not also look like a yarn
381
+ * project. Removes every yarn project file a template clone may still carry —
382
+ * including the legacy `yarnrc.yml.template` that create-app used to rename
383
+ * into `.yarnrc.yml`. (No empty `yarn.lock` is written any more either; that
384
+ * file only existed to pin down Yarn's project-root search.)
385
+ */
386
+ export function stripYarnProjectFiles(targetFolder) {
387
+ for (const yarnLeftover of [
388
+ 'yarnrc.yml.template',
389
+ '.yarnrc.yml',
390
+ '.yarn',
391
+ 'yarn.lock',
392
+ ]) {
393
+ fs.removeSync(path.join(targetFolder, yarnLeftover));
394
+ }
395
+ }
394
396
  function applyAppIdentity(targetFolder, ids) {
395
397
  const { appName, appPrefix, hyphenName } = ids;
396
- // 1. .env.example (+ seed .env from it so the first `yarn start` is correct).
398
+ // 1. .env.example (+ seed .env from it so the first `npm start` is correct).
397
399
  const envExample = path.join(targetFolder, '.env.example');
398
400
  if (fs.existsSync(envExample)) {
399
401
  let env = fs.readFileSync(envExample, 'utf8');
@@ -432,7 +434,7 @@ function applyAppIdentity(targetFolder, ids) {
432
434
  }
433
435
  }
434
436
  function logHelp() {
435
- execp('yarn exec lincd help');
437
+ execp(execBinCommand(detectPackageManager(), 'linked help'));
436
438
  }
437
439
  function log(...messages) {
438
440
  messages.forEach((message) => {
@@ -883,10 +885,13 @@ export function buildAll(options) {
883
885
  }
884
886
  //unless told otherwise, build the package
885
887
  if (!command) {
886
- // Invoke the package's own `yarn build` script. This lets each package
888
+ // Invoke the package's own `build` script. This lets each package
887
889
  // own its build pipeline — e.g. @_linked/core uses direct tsc, pure-CSS
888
890
  // packages may have no-op builds, and linkedPackage: true packages
889
- // typically call `yarn linked build` internally.
891
+ // typically call `linked build` internally.
892
+ //
893
+ // npm is the default; the package manager is detected per package so
894
+ // packages inside an existing yarn workspace still build with yarn.
890
895
  const pkgDir = path.join(process.cwd(), pkg.path);
891
896
  const pkgJson = getPackageJSON(pkgDir);
892
897
  const hasBuildScript = !!((_a = pkgJson === null || pkgJson === void 0 ? void 0 : pkgJson.scripts) === null || _a === void 0 ? void 0 : _a.build);
@@ -895,7 +900,8 @@ export function buildAll(options) {
895
900
  command = Promise.resolve(true);
896
901
  }
897
902
  else {
898
- command = execPromise('yarn build', false, false, {
903
+ const buildCmd = runScriptCommand(detectPackageManager(pkgDir), 'build');
904
+ command = execPromise(buildCmd, false, false, {
899
905
  cwd: pkgDir,
900
906
  })
901
907
  .then((res) => res === '' || typeof res === 'string')
@@ -1240,48 +1246,20 @@ const replaceVariablesInFolder = function (folder) {
1240
1246
  const replaceVariablesInFilesWithRoot = function (root, ...files) {
1241
1247
  return replaceVariablesInFiles(...files.map((f) => path.join(root, f)));
1242
1248
  };
1243
- function isAvailable(cmd) {
1244
- return __awaiter(this, void 0, void 0, function* () {
1245
- try {
1246
- const out = (yield execPromise(`${cmd} --version`, false, false));
1247
- return /\d+/.test(String(out));
1248
- }
1249
- catch (_a) {
1250
- return false;
1251
- }
1252
- });
1253
- }
1254
- function detectPackageManagers() {
1255
- return __awaiter(this, void 0, void 0, function* () {
1256
- const found = [];
1257
- if (yield isAvailable('npm'))
1258
- found.push('npm');
1259
- if (yield isAvailable('yarn'))
1260
- found.push('yarn');
1261
- return found;
1262
- });
1249
+ /**
1250
+ * The package manager `create-app` scaffolds with. Both templates (web and
1251
+ * react-native) install with npm, so a scaffolded app has exactly one lockfile.
1252
+ */
1253
+ export const CREATE_APP_PACKAGE_MANAGER = 'npm';
1254
+ /** The shell command that installs a scaffolded app's dependencies. */
1255
+ export function installCommandFor(pm) {
1256
+ return pm === 'yarn'
1257
+ ? 'export NODE_OPTIONS="--no-network-family-autoselection" && yarn install'
1258
+ : 'npm install';
1263
1259
  }
1264
- function choosePackageManager(interactive) {
1265
- return __awaiter(this, void 0, void 0, function* () {
1266
- const available = yield detectPackageManagers();
1267
- if (available.length === 0) {
1268
- throw new Error('Neither npm nor yarn is available on PATH. Install one and retry.');
1269
- }
1270
- if (available.length === 1)
1271
- return available[0];
1272
- if (!interactive) {
1273
- // Match the historical default: prefer yarn when both are installed.
1274
- return available.includes('yarn') ? 'yarn' : 'npm';
1275
- }
1276
- const fallback = available.includes('yarn') ? 'yarn' : 'npm';
1277
- const answer = yield promptUser(`Package manager [${available.join('/')}] (default: ${chalk.gray(fallback)}): `);
1278
- const choice = answer.trim().toLowerCase();
1279
- if (choice === 'npm' || choice === 'yarn') {
1280
- if (available.includes(choice))
1281
- return choice;
1282
- }
1283
- return fallback;
1284
- });
1260
+ /** The command printed to the user for starting their new app. */
1261
+ export function startCommandFor(pm) {
1262
+ return pm === 'yarn' ? 'yarn start' : 'npm start';
1285
1263
  }
1286
1264
  const ensureFolderExists = function (...folders) {
1287
1265
  let target;
@@ -1665,7 +1643,7 @@ export const runMethod = (packageName, method, options) => __awaiter(void 0, voi
1665
1643
  if (error.code === 'ECONNREFUSED' ||
1666
1644
  ((_a = error.cause) === null || _a === void 0 ? void 0 : _a.code) === 'ECONNREFUSED') {
1667
1645
  console.error(chalk.red('Could not connect to the backend server. Is it running?'));
1668
- console.error(`Make sure you ${chalk.magenta('run "yarn start" in a separate process')} before calling this method.`);
1646
+ console.error(`Make sure you ${chalk.magenta('run "npm start" in a separate process')} before calling this method.`);
1669
1647
  }
1670
1648
  else {
1671
1649
  console.error('Error during backend call:', error);
@@ -1860,7 +1838,7 @@ export const buildBackend = () => __awaiter(void 0, void 0, void 0, function* ()
1860
1838
  text: 'Compiling backend TS files',
1861
1839
  }).start();
1862
1840
  try {
1863
- yield execPromise(`yarn exec tsc`);
1841
+ yield execPromise(execBinCommand(detectPackageManager(), 'tsc'));
1864
1842
  compileSpinner.succeed('Backend TS files compiled');
1865
1843
  }
1866
1844
  catch (e) {
@@ -2098,11 +2076,17 @@ export const createPackage = (name_1, uriBase_1, ...args_1) => __awaiter(void 0,
2098
2076
  console.log('rename ', path.join(targetFolder, f), path.join(targetFolder, ...newParts, newName));
2099
2077
  fs.renameSync(path.join(targetFolder, f), path.join(targetFolder, ...newParts, newName));
2100
2078
  });
2101
- let version = (yield execPromise('yarn --version').catch((err) => {
2102
- console.log('yarn probably not working');
2103
- return '';
2104
- }));
2105
- const setup = planPackageSetup(version.toString(), path.join(getScriptDir(), 'launch.js'));
2079
+ // npm is the default for a new package. yarn is only consulted when the new
2080
+ // package lands inside an existing yarn project (an mrgit/yarn-3 monorepo),
2081
+ // where adding an npm lockfile would break the workspace.
2082
+ const insideYarnProject = detectPackageManager(path.dirname(path.resolve(targetFolder))) === 'yarn';
2083
+ let version = insideYarnProject
2084
+ ? (yield execPromise('yarn --version').catch(() => {
2085
+ console.log('yarn probably not working');
2086
+ return '';
2087
+ }))
2088
+ : '';
2089
+ const setup = planPackageSetup(version.toString(), path.join(getScriptDir(), 'launch.js'), process.execPath, insideYarnProject);
2106
2090
  if (setup.yarnrc) {
2107
2091
  fs.writeFileSync(path.join(targetFolder, '.yarnrc.yml'), setup.yarnrc);
2108
2092
  }
@@ -2121,7 +2105,7 @@ export const createPackage = (name_1, uriBase_1, ...args_1) => __awaiter(void 0,
2121
2105
  process.exitCode = 1;
2122
2106
  });
2123
2107
  }
2124
- log(`Prepared a new LINCD package in ${chalk.magenta(targetFolder)}`, `Run ${chalk.blueBright('yarn build')} from this directory to build once`, `Or ${chalk.blueBright('yarn dev')} to continuously rebuild on file changes`);
2108
+ log(`Prepared a new LINCD 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`);
2125
2109
  });
2126
2110
  var getNextVersion = function (version) {
2127
2111
  let parts = version.split('.');
@@ -2676,7 +2660,13 @@ export var publishPackage = function (pkg, test, info, publishVersion) {
2676
2660
  console.log(chalk.blue('publishing ' + pkg.packageName + ' ' + publishVersion));
2677
2661
  //looking for an .env.json file in our workspace, which may store our NPM AUTH key
2678
2662
  let envJsonPath = yield getEnvJsonPath(pkg.path);
2679
- return execPromise(`cd ${pkg.path} && ${envJsonPath ? `env-cmd -f ${envJsonPath} --use-shell "` : ''}yarn version ${publishVersion} && yarn npm publish${envJsonPath ? `"` : ''}`, true, false, {}, true)
2663
+ // `yarn version` / `yarn npm publish` is Yarn Berry syntax. Only use it when
2664
+ // the package really lives in a yarn project; otherwise publish with npm.
2665
+ const publishPm = detectPackageManager(pkg.path);
2666
+ const versionAndPublish = publishPm === 'yarn'
2667
+ ? `yarn version ${publishVersion} && yarn npm publish`
2668
+ : `npm version ${publishVersion} --no-git-tag-version && npm publish`;
2669
+ return execPromise(`cd ${pkg.path} && ${envJsonPath ? `env-cmd -f ${envJsonPath} --use-shell "` : ''}${versionAndPublish}${envJsonPath ? `"` : ''}`, true, false, {}, true)
2680
2670
  .then((res) => {
2681
2671
  if (res.indexOf('Aborted due to warnings') !== -1 ||
2682
2672
  res.indexOf('Could not publish') !== -1 ||
@@ -2885,18 +2875,18 @@ export var addCapacitor = function () {
2885
2875
  'env-cmd -e _main, staging node scripts/build.js';
2886
2876
  pack.scripts['fix-app'] = 'node scripts/fix-namespace.js';
2887
2877
  pack.scripts['app'] =
2888
- 'env-cmd -e _main,production,app-main node scripts/build.js && npx cap sync && yarn run fix-app';
2878
+ 'env-cmd -e _main,production,app-main node scripts/build.js && npx cap sync && npm run fix-app';
2889
2879
  pack.scripts['app-local-ios'] =
2890
- 'env-cmd -e _main,development,app-main,app-local-ios node scripts/build.js && npx cap sync && yarn run fix-app';
2880
+ 'env-cmd -e _main,development,app-main,app-local-ios node scripts/build.js && npx cap sync && npm run fix-app';
2891
2881
  pack.scripts['app-local-android'] =
2892
- 'env-cmd -e _main,development,app-main,app-local-android node scripts/build.js && npx cap sync && yarn run fix-app';
2893
- pack.scripts['cap:android'] = 'yarn cap open android';
2894
- pack.scripts['cap:ios'] = 'yarn cap open ios';
2895
- pack.scripts['cap:sync'] = 'yarn cap sync';
2882
+ 'env-cmd -e _main,development,app-main,app-local-android node scripts/build.js && npx cap sync && npm run fix-app';
2883
+ pack.scripts['cap:android'] = 'npx cap open android';
2884
+ pack.scripts['cap:ios'] = 'npx cap open ios';
2885
+ pack.scripts['cap:sync'] = 'npx cap sync';
2896
2886
  fs.writeFile(path.resolve(basePath, 'package.json'), JSON.stringify(pack, null, 2));
2897
2887
  log('Added new run script to package.json');
2898
- yield execPromise(`yarn add -D @capacitor/cli`, true, false, null, true);
2899
- yield execPromise(`yarn add @capacitor/android @capacitor/core @capacitor/app @capacitor/ios`, false, false, null, true);
2888
+ yield execPromise(`npm install --save-dev @capacitor/cli`, true, false, null, true);
2889
+ yield execPromise(`npm install @capacitor/android @capacitor/core @capacitor/app @capacitor/ios`, false, false, null, true);
2900
2890
  // TODO: Do we need to add `npx cap init`? If yes, we should not copy capacitor config.ts yet
2901
2891
  // await execPromise(`npx cap init`, true, false, null, true);
2902
2892
  // got error:
@@ -2905,21 +2895,27 @@ export var addCapacitor = function () {
2905
2895
  // [error] Non-interactive shell detected.
2906
2896
  // Run the command with --help to see a list of arguments that must be provided.
2907
2897
  log(`Done! Now update your Capacitor configuration by providing an app name, app ID, and web directory at ${chalk.blue('capacitor.config.ts')}`);
2908
- log(`And then run ${chalk.magenta('yarn cap add android')} and/or ${chalk.magenta('yarn cap add ios')}')`);
2909
- log(`Last, run ${chalk.magenta('yarn app')} or ${chalk.magenta('yarn app-local-ios')} or ${chalk.magenta('yarn app-local-android')}`);
2898
+ log(`And then run ${chalk.magenta('npx cap add android')} and/or ${chalk.magenta('npx cap add ios')}')`);
2899
+ log(`Last, run ${chalk.magenta('npm run app')} or ${chalk.magenta('npm run app-local-ios')} or ${chalk.magenta('npm run app-local-android')}`);
2910
2900
  });
2911
2901
  };
2912
2902
  export var executeCommandForPackage = function (packageName, command) {
2913
2903
  let packageDetails = getLincdPackages().find((modDetails) => modDetails.packageName.indexOf(packageName) !== -1 ||
2914
2904
  modDetails.packageName.indexOf(packageName) !== -1);
2915
2905
  if (packageDetails) {
2906
+ // npm is the default; only a package inside a yarn project is driven with
2907
+ // yarn (`yarn linked <cmd>` resolves the bin from the yarn workspace).
2908
+ const pm = detectPackageManager(packageDetails.path);
2909
+ // Windows quirk: the shim is `yarn.cmd` / `npx.cmd`.
2910
+ const isWin = process.platform === 'win32';
2911
+ const runner = pm === 'yarn' ? (isWin ? 'yarn.cmd' : 'yarn') : isWin ? 'npx.cmd' : 'npx';
2912
+ const runnerArgs = pm === 'yarn' ? ['linked'] : ['--no-install', 'linked'];
2916
2913
  log("Executing 'cd " +
2917
2914
  packageDetails.path +
2918
- ' && yarn lincd' +
2915
+ ` && ${runner} linked` +
2919
2916
  (command ? ' ' + command : '') +
2920
2917
  "'");
2921
- spawnChild(process.platform === 'win32' ? 'yarn.cmd' : 'yarn', // Windows quirk
2922
- ['lincd', command || null], {
2918
+ spawnChild(runner, [...runnerArgs, command || null], {
2923
2919
  cwd: packageDetails.path,
2924
2920
  stdio: 'inherit',
2925
2921
  });