@_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 +75 -0
- package/README.md +1 -1
- package/defaults/app-react-native/README.md +1 -1
- package/defaults/app-react-native/apps/mobile/src/components/PersonOverview.tsx +1 -1
- package/defaults/app-react-native/apps/mobile/src/components/PersonPreview.tsx +1 -1
- package/lib/esm/cli-methods.d.ts +28 -0
- package/lib/esm/cli-methods.d.ts.map +1 -1
- package/lib/esm/cli-methods.js +40 -67
- package/lib/esm/cli-methods.js.map +1 -1
- package/lib/esm/cli.js +1 -1
- package/lib/esm/cli.js.map +1 -1
- package/lib/esm/commands/start.d.ts +12 -0
- package/lib/esm/commands/start.d.ts.map +1 -1
- package/lib/esm/commands/start.js +59 -9
- package/lib/esm/commands/start.js.map +1 -1
- package/lib/esm/vite-config.d.ts +17 -0
- package/lib/esm/vite-config.d.ts.map +1 -1
- package/lib/esm/vite-config.js +42 -8
- package/lib/esm/vite-config.js.map +1 -1
- package/package.json +2 -2
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-
|
|
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-
|
|
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-
|
|
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
|
|
package/lib/esm/cli-methods.d.ts
CHANGED
|
@@ -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":"AA2BA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,iBAAiB,CAAC;AAgBpD;;;;;;GAMG;AAKH,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,gBAAgB,EACjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAC,uBAAuB,EAAE,wBAAwB,EAAE,gBAAgB,EAAC,CAAC;AAoB7E,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,cAAc,CAAC;AAEjD,KAAK,WAAW,GAAG;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,SAAS,GAAU,SAAI,EAAE,iBAAwB,EAAE,UAAS;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,WAAW,CAAA;CAAM,
|
|
1
|
+
{"version":3,"file":"cli-methods.d.ts","sourceRoot":"","sources":["../../src/cli-methods.ts"],"names":[],"mappings":"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"}
|
package/lib/esm/cli-methods.js
CHANGED
|
@@ -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-
|
|
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
|
-
|
|
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
|
-
//
|
|
169
|
-
//
|
|
170
|
-
//
|
|
171
|
-
|
|
172
|
-
|
|
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
|
|
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
|
|
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 `
|
|
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
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
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
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
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;
|