@_linked/cli 1.15.0 → 1.16.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,80 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.16.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#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.
8
+
9
+ The web template used to install with yarn (and prompted for a package manager
10
+ when both were on PATH); it now always runs `npm install`, matching the
11
+ react-native template, and the next-steps message prints `npm start`. The empty
12
+ `yarn.lock` that create-app wrote to pin down Yarn's project-root search is no
13
+ longer created, so a new app has a single npm lockfile.
14
+
15
+ create-app also strips every yarn project file from the clone (the legacy
16
+ `yarnrc.yml.template` it used to rename into `.yarnrc.yml`, plus `.yarnrc.yml`,
17
+ `.yarn/` and any `yarn.lock` the template still carries), so a scaffolded app is
18
+ an npm project end to end.
19
+
20
+ ## 1.15.3
21
+
22
+ ### Patch Changes
23
+
24
+ - [#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
25
+ the current filenames still start.
26
+
27
+ - The app's linked config is now looked up as `linked.config.js` **or** the
28
+ legacy `lincd.config.js` (current name wins when both exist). Apps that never
29
+ renamed the file silently lost their whole `server` block — `cachePaths`,
30
+ `apiOnly` and the rest of LinkedServer's options — because only the new name
31
+ was read. The lookup is exposed as `resolveLinkedConfigPath()`.
32
+ - SSR page discovery also skips `*.d.ts` files in `src/pages/` (alongside the
33
+ existing `.test` / `.spec` skip). Type declarations have no runtime module,
34
+ so preloading them into the SSR graph only produced errors.
35
+ - The backend storage config is discovered under several legacy filenames
36
+ (`backend-storage-config.*`, `scripts/backend-storage-config.*`,
37
+ `scripts/storage-config.js`) in addition to `linked.backend.storage.*`.
38
+
39
+ ## 1.15.2
40
+
41
+ ### Patch Changes
42
+
43
+ - [#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
44
+ dev port (`PORT` env override, else `opts.port`), instead of Vite's shared
45
+ default `24678`.
46
+
47
+ Every app built on `createViteConfig` defaulted to `24678` for HMR, so running
48
+ two of them at once (parallel worktrees / multiple `@_linked` apps on one
49
+ machine) collided — `WebSocket server error: Port 24678 is already in use`, and
50
+ HMR silently broke for the loser. The port is now `24678 + (devPort - 4040)`, so
51
+ apps that already use distinct dev ports get distinct HMR ports for free.
52
+
53
+ The derivation lives in the new exported `hmrPortFor()` helper and is defensive
54
+ about its input: a `PORT` that is not a whole port number (`PORT=abc`, a
55
+ negative or out-of-range value) falls back to the `4040` default rather than
56
+ producing `NaN`, and the derived port is clamped into `1024`–`65535`. Apps can
57
+ still override via `server.hmr` in their own merged config.
58
+
59
+ ## 1.15.1
60
+
61
+ ### Patch Changes
62
+
63
+ - [#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.
64
+
65
+ `vite.watcher.on('change')` called `server.onSourceChange(pkg)` once per changed
66
+ file with no debounce and no queue. Since `onSourceChange` disposes a package's
67
+ providers and re-registers their Express routes, it mutates the shared router
68
+ stack — and a multi-file save, a format-on-save, or a branch switch ran several
69
+ of those dispose/re-register cycles concurrently against that same stack with
70
+ nothing ordering them.
71
+
72
+ Changed packages are now collected over a 150 ms window and their reload cycles
73
+ run one at a time on a promise chain. Reload failures are still logged per
74
+ package and no longer abort the cycles queued behind them.
75
+
76
+ No API change; dev-server behaviour only.
77
+
3
78
  ## 1.15.0
4
79
 
5
80
  ### Minor Changes
package/README.md CHANGED
@@ -145,7 +145,7 @@ Templates live in `defaults/`:
145
145
 
146
146
  ### `linked create-app` template structure
147
147
 
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.
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. Dependencies are installed with `npm install`, and the next-steps message tells you to run `npm start`.
149
149
 
150
150
  Storage configuration follows the two-layer pattern from [backlog 016](https://github.com/c### `linked create-app --template react-native`
151
151
 
@@ -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
 
@@ -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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"}
@@ -124,7 +124,7 @@ export const createApp = (name_1, ...args_1) => __awaiter(void 0, [name_1, ...ar
124
124
  // Scaffold from the canonical template repo (single source of truth; CN's
125
125
  // server-side createProject clones the same repo). Shallow clone, then drop
126
126
  // .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);
127
+ yield execPromise(`git clone --depth 1 https://github.com/linked-fw/app-template.git "${targetFolder}"`, false, false);
128
128
  fs.removeSync(path.join(targetFolder, '.git'));
129
129
  //make sure the data folder exists (even though its empty).. copying empty folders does not work with fs.copySync
130
130
  fs.mkdirSync(path.join(targetFolder, 'data'), { recursive: true });
@@ -137,19 +137,7 @@ export const createApp = (name_1, ...args_1) => __awaiter(void 0, [name_1, ...ar
137
137
  if (fs.existsSync(gitignoreTemplate)) {
138
138
  fs.renameSync(gitignoreTemplate, path.join(targetFolder, '.gitignore'));
139
139
  }
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
- }
140
+ stripYarnProjectFiles(targetFolder);
153
141
  // Seed the real (gitignored) Layer 2 config from the committed example so
154
142
  // the scaffolded app boots first try. Users can edit either file later.
155
143
  const datasetsExample = path.join(targetFolder, 'linked.backend.datasets.example.json');
@@ -165,17 +153,13 @@ export const createApp = (name_1, ...args_1) => __awaiter(void 0, [name_1, ...ar
165
153
  // create-app stamps this app's identity into the clone directly rather than
166
154
  // relying on ${var} substitution.
167
155
  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);
156
+ // New apps are npm apps: npm is the package manager the templates, the CI
157
+ // workflows and the published @_linked/* packages are all tested against, and
158
+ // the react-native template already installs with npm. Keeping a single
159
+ // package manager also keeps the scaffolded app to a single lockfile.
160
+ const pm = CREATE_APP_PACKAGE_MANAGER;
175
161
  if (!options.skipInstall) {
176
- const installCommand = pm === 'yarn'
177
- ? 'export NODE_OPTIONS="--no-network-family-autoselection" && yarn install'
178
- : 'npm install';
162
+ const installCommand = installCommandFor(pm);
179
163
  const spinner = ora({
180
164
  text: `Installing dependencies (${pm})...`,
181
165
  spinner: 'dots',
@@ -207,7 +191,7 @@ export const createApp = (name_1, ...args_1) => __awaiter(void 0, [name_1, ...ar
207
191
  }
208
192
  }
209
193
  }
210
- const startCommand = pm === 'yarn' ? 'yarn start' : 'npm start';
194
+ const startCommand = startCommandFor(pm);
211
195
  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
196
  });
213
197
  /**
@@ -391,9 +375,26 @@ function setEnvVar(envText, key, value) {
391
375
  * - `src/package.ts`: the runtime `linkedPackage` id — shape URIs derive from it.
392
376
  * - pm2 process names + the VS Code launch name (cosmetic, but should match).
393
377
  */
378
+ /**
379
+ * Scaffolded apps are npm apps, so the new app must not also look like a yarn
380
+ * project. Removes every yarn project file a template clone may still carry —
381
+ * including the legacy `yarnrc.yml.template` that create-app used to rename
382
+ * into `.yarnrc.yml`. (No empty `yarn.lock` is written any more either; that
383
+ * file only existed to pin down Yarn's project-root search.)
384
+ */
385
+ export function stripYarnProjectFiles(targetFolder) {
386
+ for (const yarnLeftover of [
387
+ 'yarnrc.yml.template',
388
+ '.yarnrc.yml',
389
+ '.yarn',
390
+ 'yarn.lock',
391
+ ]) {
392
+ fs.removeSync(path.join(targetFolder, yarnLeftover));
393
+ }
394
+ }
394
395
  function applyAppIdentity(targetFolder, ids) {
395
396
  const { appName, appPrefix, hyphenName } = ids;
396
- // 1. .env.example (+ seed .env from it so the first `yarn start` is correct).
397
+ // 1. .env.example (+ seed .env from it so the first `npm start` is correct).
397
398
  const envExample = path.join(targetFolder, '.env.example');
398
399
  if (fs.existsSync(envExample)) {
399
400
  let env = fs.readFileSync(envExample, 'utf8');
@@ -1240,48 +1241,20 @@ const replaceVariablesInFolder = function (folder) {
1240
1241
  const replaceVariablesInFilesWithRoot = function (root, ...files) {
1241
1242
  return replaceVariablesInFiles(...files.map((f) => path.join(root, f)));
1242
1243
  };
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
- });
1244
+ /**
1245
+ * The package manager `create-app` scaffolds with. Both templates (web and
1246
+ * react-native) install with npm, so a scaffolded app has exactly one lockfile.
1247
+ */
1248
+ export const CREATE_APP_PACKAGE_MANAGER = 'npm';
1249
+ /** The shell command that installs a scaffolded app's dependencies. */
1250
+ export function installCommandFor(pm) {
1251
+ return pm === 'yarn'
1252
+ ? 'export NODE_OPTIONS="--no-network-family-autoselection" && yarn install'
1253
+ : 'npm install';
1263
1254
  }
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
- });
1255
+ /** The command printed to the user for starting their new app. */
1256
+ export function startCommandFor(pm) {
1257
+ return pm === 'yarn' ? 'yarn start' : 'npm start';
1285
1258
  }
1286
1259
  const ensureFolderExists = function (...folders) {
1287
1260
  let target;