@lenne.tech/cli 1.33.0 → 1.35.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/README.md +6 -5
- package/build/commands/codex/codex.js +23 -0
- package/build/commands/codex/plugins.js +103 -0
- package/build/commands/codex/shortcuts.js +110 -0
- package/build/commands/config/validate.js +0 -4
- package/build/commands/deployment/create.js +218 -213
- package/build/commands/dev/init.js +2 -1
- package/build/commands/dev/status.js +2 -0
- package/build/commands/dev/test.js +12 -6
- package/build/commands/dev/up.js +17 -7
- package/build/commands/frontend/nuxt.js +4 -7
- package/build/commands/fullstack/add-api.js +6 -9
- package/build/commands/fullstack/add-app.js +5 -7
- package/build/commands/fullstack/init.js +34 -20
- package/build/commands/status.js +2 -0
- package/build/commands/ticket/list.js +2 -0
- package/build/commands/ticket/start.js +6 -4
- package/build/extensions/frontend-helper.js +44 -39
- package/build/extensions/server.js +354 -22
- package/build/lib/angular-environments.js +108 -0
- package/build/lib/codex-cli.js +56 -0
- package/build/lib/codex-plugin-utils.js +102 -0
- package/build/lib/dev-identity.js +38 -18
- package/build/lib/dev-package-manager.js +89 -0
- package/build/lib/dev-patches.js +4 -1
- package/build/lib/dev-project.js +20 -7
- package/build/lib/dev-state.js +17 -1
- package/build/lib/dev-test-session.js +61 -19
- package/build/lib/dev-ticket.js +12 -6
- package/build/lib/ensure-root-dockerignore.js +92 -0
- package/build/lib/fs-utils.js +19 -0
- package/build/lib/hoist-workspace-pnpm-config.js +2 -11
- package/build/lib/remove-nested-lockfiles.js +53 -0
- package/build/lib/turboops-config.js +93 -0
- package/build/lib/vendor-claude-md.js +7 -2
- package/build/lib/workspace-integration.js +96 -3
- package/build/templates/deployment/turboops.json.ejs +3 -0
- package/build/templates/vendor-scripts/migrate-store.js +25 -0
- package/docs/LT-ECOSYSTEM-GUIDE.md +1 -1
- package/docs/commands.md +30 -9
- package/docs/lt.config.md +9 -19
- package/package.json +1 -1
- package/build/templates/deployment/.github/workflows/pre-release.yml.ejs +0 -41
- package/build/templates/deployment/.github/workflows/release.yml.ejs +0 -41
- package/build/templates/deployment/.gitlab-ci.yml.ejs +0 -181
- package/build/templates/deployment/Dockerfile.app.ejs +0 -13
- package/build/templates/deployment/Dockerfile.ejs +0 -18
- package/build/templates/deployment/docker-compose.dev.yml.ejs +0 -99
- package/build/templates/deployment/docker-compose.prod.yml.ejs +0 -92
- package/build/templates/deployment/docker-compose.test.yml.ejs +0 -98
- package/build/templates/deployment/scripts/build-push.sh.ejs +0 -20
- package/build/templates/deployment/scripts/deploy.sh.ejs +0 -7
package/build/commands/dev/up.js
CHANGED
|
@@ -14,6 +14,7 @@ const path_1 = require("path");
|
|
|
14
14
|
const caddy_1 = require("../../lib/caddy");
|
|
15
15
|
const dev_env_1 = require("../../lib/dev-env");
|
|
16
16
|
const dev_env_bridge_1 = require("../../lib/dev-env-bridge");
|
|
17
|
+
const dev_package_manager_1 = require("../../lib/dev-package-manager");
|
|
17
18
|
const dev_patches_1 = require("../../lib/dev-patches");
|
|
18
19
|
const dev_process_1 = require("../../lib/dev-process");
|
|
19
20
|
const dev_project_1 = require("../../lib/dev-project");
|
|
@@ -85,7 +86,8 @@ const UpCommand = {
|
|
|
85
86
|
const { filesystem, parameters, print: { colors, error, info, success, warning }, } = toolbox;
|
|
86
87
|
const layout = (0, dev_project_1.resolveLayout)(filesystem.cwd(), filesystem);
|
|
87
88
|
if (!layout.apiDir && !layout.appDir) {
|
|
88
|
-
error('No
|
|
89
|
+
error('No lt project detected at this path. Expected an API (src/config.env.ts or nest-cli.json), ' +
|
|
90
|
+
'an App (nuxt.config.ts), or a monorepo with projects/api and/or projects/app.');
|
|
89
91
|
if (!parameters.options.fromGluegunMenu)
|
|
90
92
|
process.exit(1);
|
|
91
93
|
return 'dev up: not a project';
|
|
@@ -270,7 +272,9 @@ const UpCommand = {
|
|
|
270
272
|
apiUpstreamPort: existingEntry === null || existingEntry === void 0 ? void 0 : existingEntry.internalPorts.api,
|
|
271
273
|
appHostname: (_d = identity.subdomains.app) === null || _d === void 0 ? void 0 : _d.hostname,
|
|
272
274
|
appUpstreamPort: existingEntry === null || existingEntry === void 0 ? void 0 : existingEntry.internalPorts.app,
|
|
273
|
-
|
|
275
|
+
// App-only projects have no database — don't advertise a Mongo URL
|
|
276
|
+
// that nothing listens on.
|
|
277
|
+
dbName: identity.subdomains.api ? ((_e = existingEntry === null || existingEntry === void 0 ? void 0 : existingEntry.dbName) !== null && _e !== void 0 ? _e : dbName) : undefined,
|
|
274
278
|
});
|
|
275
279
|
info('Run `lt dev down` first to force a full restart.');
|
|
276
280
|
if (!parameters.options.fromGluegunMenu)
|
|
@@ -316,7 +320,8 @@ const UpCommand = {
|
|
|
316
320
|
info(` app: https://${identity.subdomains.app.hostname} → 127.0.0.1:${appPort}`);
|
|
317
321
|
if (identity.subdomains.api)
|
|
318
322
|
info(` api: https://${identity.subdomains.api.hostname} → 127.0.0.1:${apiPort}`);
|
|
319
|
-
|
|
323
|
+
if (identity.subdomains.api)
|
|
324
|
+
info(` db: mongodb://127.0.0.1/${dbName}`);
|
|
320
325
|
info('');
|
|
321
326
|
// Build env per process.
|
|
322
327
|
const devEnv = (0, dev_env_1.buildDevEnv)({
|
|
@@ -326,7 +331,6 @@ const UpCommand = {
|
|
|
326
331
|
dbName,
|
|
327
332
|
identity,
|
|
328
333
|
});
|
|
329
|
-
const pnpmBin = process.env.LT_PNPM_BIN || 'pnpm';
|
|
330
334
|
const pids = {};
|
|
331
335
|
const rotationNotes = [];
|
|
332
336
|
const started = [];
|
|
@@ -350,7 +354,12 @@ const UpCommand = {
|
|
|
350
354
|
}
|
|
351
355
|
else {
|
|
352
356
|
yield reclaimPort(existingSession === null || existingSession === void 0 ? void 0 : existingSession.pids.api, apiPort, apiHealth !== null && apiHealth !== void 0 ? apiHealth : 'dead');
|
|
353
|
-
|
|
357
|
+
// Per-component PM detection: a monorepo may have an npm api and a
|
|
358
|
+
// pnpm app, and the legacy hard-coded `pnpm start` would silently
|
|
359
|
+
// regenerate a foreign lockfile + crash on un-approved build
|
|
360
|
+
// scripts when run against an npm-only project.
|
|
361
|
+
const apiPm = (0, dev_package_manager_1.pickPackageManager)(layout.apiDir);
|
|
362
|
+
const apiResult = (0, dev_process_1.spawnDetached)(apiPm.bin, apiPm.runScript('start'), {
|
|
354
363
|
cwd: layout.apiDir,
|
|
355
364
|
env: devEnv.api.env,
|
|
356
365
|
logFile: (0, path_1.join)(layout.root, '.lt-dev', 'api.log'),
|
|
@@ -371,7 +380,8 @@ const UpCommand = {
|
|
|
371
380
|
}
|
|
372
381
|
else {
|
|
373
382
|
yield reclaimPort(existingSession === null || existingSession === void 0 ? void 0 : existingSession.pids.app, appPort, appHealth !== null && appHealth !== void 0 ? appHealth : 'dead');
|
|
374
|
-
const
|
|
383
|
+
const appPm = (0, dev_package_manager_1.pickPackageManager)(layout.appDir);
|
|
384
|
+
const appResult = (0, dev_process_1.spawnDetached)(appPm.bin, appPm.runScript('dev'), {
|
|
375
385
|
cwd: layout.appDir,
|
|
376
386
|
env: devEnv.app.env,
|
|
377
387
|
logFile: (0, path_1.join)(layout.root, '.lt-dev', 'app.log'),
|
|
@@ -408,7 +418,7 @@ const UpCommand = {
|
|
|
408
418
|
apiUpstreamPort: apiPort,
|
|
409
419
|
appHostname: (_l = identity.subdomains.app) === null || _l === void 0 ? void 0 : _l.hostname,
|
|
410
420
|
appUpstreamPort: appPort,
|
|
411
|
-
dbName,
|
|
421
|
+
dbName: identity.subdomains.api ? dbName : undefined,
|
|
412
422
|
});
|
|
413
423
|
info(colors.dim('Logs: <root>/.lt-dev/api.log, <root>/.lt-dev/app.log'));
|
|
414
424
|
for (const note of rotationNotes)
|
|
@@ -15,7 +15,7 @@ const workspace_integration_1 = require("../../lib/workspace-integration");
|
|
|
15
15
|
* Create a new nuxt workspace
|
|
16
16
|
*
|
|
17
17
|
* Standalone counterpart to `lt fullstack init` / `lt fullstack add-app`
|
|
18
|
-
* for Nuxt: clones nuxt-base-starter
|
|
18
|
+
* for Nuxt: clones nuxt-base-starter into
|
|
19
19
|
* a brand-new directory. Mirrors the same surface area as add-app where
|
|
20
20
|
* applicable so behaviour is consistent across the four flows.
|
|
21
21
|
*/
|
|
@@ -170,7 +170,7 @@ const NewCommand = {
|
|
|
170
170
|
info('Dry-run plan:');
|
|
171
171
|
info(` name: ${projName}`);
|
|
172
172
|
info(` projectDir: ${projectDir}`);
|
|
173
|
-
info(` branch: ${branch || '(default
|
|
173
|
+
info(` branch: ${branch || '(default branch)'}`);
|
|
174
174
|
info(` copy: ${copyPath || '(none)'}`);
|
|
175
175
|
info(` link: ${linkPath || '(none)'}`);
|
|
176
176
|
info(` frontendFrameworkMode: ${frontendFrameworkMode}`);
|
|
@@ -183,11 +183,8 @@ const NewCommand = {
|
|
|
183
183
|
else if (copyPath) {
|
|
184
184
|
info(` 1. copy ${copyPath} → ./${projectDir}`);
|
|
185
185
|
}
|
|
186
|
-
else if (branch) {
|
|
187
|
-
info(` 1. clone nuxt-base-starter (branch: ${branch}) → ./${projectDir}`);
|
|
188
|
-
}
|
|
189
186
|
else {
|
|
190
|
-
info(` 1.
|
|
187
|
+
info(` 1. clone nuxt-base-starter (${branch ? `branch: ${branch}` : 'default branch'}) → ./${projectDir}`);
|
|
191
188
|
}
|
|
192
189
|
if (frontendFrameworkMode === 'vendor') {
|
|
193
190
|
info(` 2. clone @lenne.tech/nuxt-extensions → /tmp`);
|
|
@@ -206,7 +203,7 @@ const NewCommand = {
|
|
|
206
203
|
branch,
|
|
207
204
|
copyPath,
|
|
208
205
|
linkPath,
|
|
209
|
-
skipInstall:
|
|
206
|
+
skipInstall: false, // clone-based setup installs here (create-nuxt-base no longer used)
|
|
210
207
|
});
|
|
211
208
|
if (!result.success) {
|
|
212
209
|
baseSpinner.fail(`Failed to setup nuxt workspace: ${result.path}`);
|
|
@@ -10,7 +10,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.help = void 0;
|
|
13
|
-
const hoist_workspace_pnpm_config_1 = require("../../lib/hoist-workspace-pnpm-config");
|
|
14
13
|
const workspace_integration_1 = require("../../lib/workspace-integration");
|
|
15
14
|
/**
|
|
16
15
|
* Add an API (`projects/api/`) to a fullstack workspace that currently
|
|
@@ -320,14 +319,12 @@ const NewCommand = {
|
|
|
320
319
|
if (apiResult.method !== 'link') {
|
|
321
320
|
(0, workspace_integration_1.writeApiConfig)({ apiDir: apiDest, apiMode, filesystem, frameworkMode });
|
|
322
321
|
}
|
|
323
|
-
//
|
|
324
|
-
//
|
|
325
|
-
// ignores
|
|
326
|
-
(
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
subProjects: ['projects/api', 'projects/app'],
|
|
330
|
-
});
|
|
322
|
+
// Normalize the workspace root: hoist pnpm config out of the sub-projects
|
|
323
|
+
// (`setupServerForFullstack` may have left `pnpm.overrides` etc. at a
|
|
324
|
+
// non-root level pnpm ignores), drop nested lockfiles the root supersedes,
|
|
325
|
+
// and guarantee a root `.dockerignore` (Docker never reads a sub-project's
|
|
326
|
+
// own when building from the root context).
|
|
327
|
+
(0, workspace_integration_1.finalizeWorkspaceRoot)({ filesystem, projectDir: workspaceDir });
|
|
331
328
|
// Run install + format unless explicitly skipped (CI/agents may
|
|
332
329
|
// want to chain multiple add-* calls before installing once).
|
|
333
330
|
if (!skipInstall && !experimental) {
|
|
@@ -10,7 +10,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.help = void 0;
|
|
13
|
-
const hoist_workspace_pnpm_config_1 = require("../../lib/hoist-workspace-pnpm-config");
|
|
14
13
|
const workspace_integration_1 = require("../../lib/workspace-integration");
|
|
15
14
|
/**
|
|
16
15
|
* Add a frontend app (`projects/app/`) to a fullstack workspace that
|
|
@@ -249,12 +248,11 @@ const NewCommand = {
|
|
|
249
248
|
warning('Continuing with npm mode for frontend.');
|
|
250
249
|
}
|
|
251
250
|
}
|
|
252
|
-
//
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
});
|
|
251
|
+
// Normalize the workspace root: hoist pnpm config (frontend templates may
|
|
252
|
+
// carry pnpm.overrides too), drop the frontend starter's standalone
|
|
253
|
+
// pnpm-lock.yaml the root supersedes, and guarantee a root `.dockerignore`
|
|
254
|
+
// (else the image inherits the host's node_modules, .output and .env).
|
|
255
|
+
(0, workspace_integration_1.finalizeWorkspaceRoot)({ filesystem, projectDir: workspaceDir });
|
|
258
256
|
if (!skipInstall) {
|
|
259
257
|
const installSpinner = spin('Install workspace packages');
|
|
260
258
|
try {
|
|
@@ -16,7 +16,6 @@ const gluegun_1 = require("gluegun");
|
|
|
16
16
|
const caddy_1 = require("../../lib/caddy");
|
|
17
17
|
const dev_migrate_helper_1 = require("../../lib/dev-migrate-helper");
|
|
18
18
|
const dev_project_1 = require("../../lib/dev-project");
|
|
19
|
-
const hoist_workspace_pnpm_config_1 = require("../../lib/hoist-workspace-pnpm-config");
|
|
20
19
|
const package_name_1 = require("../../lib/package-name");
|
|
21
20
|
const vendor_claude_md_1 = require("../../lib/vendor-claude-md");
|
|
22
21
|
const workspace_integration_1 = require("../../lib/workspace-integration");
|
|
@@ -33,7 +32,7 @@ const NewCommand = {
|
|
|
33
32
|
run: (toolbox) => __awaiter(void 0, void 0, void 0, function* () {
|
|
34
33
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0;
|
|
35
34
|
// Retrieve the tools we need
|
|
36
|
-
const { config, filesystem, frontendHelper, git, helper, parameters, patching, print: { colors, error, info, spin, success }, prompt: { ask, confirm }, server, strings: { kebabCase }, system, template, } = toolbox;
|
|
35
|
+
const { config, filesystem, frontendHelper, git, helper, parameters, patching, print: { colors, error, info, spin, success, warning }, prompt: { ask, confirm }, server, strings: { kebabCase }, system, template, } = toolbox;
|
|
37
36
|
// Start timer
|
|
38
37
|
const timer = system.startTimer();
|
|
39
38
|
// Info
|
|
@@ -209,7 +208,9 @@ const NewCommand = {
|
|
|
209
208
|
// `/lt-dev:backend:update-nest-server-core`; local patches are logged
|
|
210
209
|
// in src/core/VENDOR.md.
|
|
211
210
|
//
|
|
212
|
-
// Default is
|
|
211
|
+
// Default is 'vendor' — the lt CLI integrates the framework core directly
|
|
212
|
+
// (clones the starter, vendors core into src/core/), which is the
|
|
213
|
+
// recommended setup; pass `--framework-mode npm` for the classic npm dep.
|
|
213
214
|
let frameworkMode;
|
|
214
215
|
if (experimental) {
|
|
215
216
|
frameworkMode = 'npm';
|
|
@@ -226,16 +227,16 @@ const NewCommand = {
|
|
|
226
227
|
info(`Using framework mode from lt.config: ${frameworkMode}`);
|
|
227
228
|
}
|
|
228
229
|
else if (noConfirm) {
|
|
229
|
-
frameworkMode = '
|
|
230
|
-
info('Using default framework mode:
|
|
230
|
+
frameworkMode = 'vendor';
|
|
231
|
+
info('Using default framework mode: vendor (noConfirm mode)');
|
|
231
232
|
}
|
|
232
233
|
else {
|
|
233
234
|
const frameworkModeChoice = yield ask({
|
|
234
235
|
choices: [
|
|
235
236
|
'npm - @lenne.tech/nest-server as npm dependency (classic, stable)',
|
|
236
|
-
'vendor - framework core vendored into projects/api/src/core/ (
|
|
237
|
+
'vendor - framework core vendored into projects/api/src/core/ (default, allows local patches)',
|
|
237
238
|
],
|
|
238
|
-
initial:
|
|
239
|
+
initial: 1,
|
|
239
240
|
message: 'Framework consumption mode?',
|
|
240
241
|
name: 'frameworkMode',
|
|
241
242
|
type: 'select',
|
|
@@ -257,11 +258,11 @@ const NewCommand = {
|
|
|
257
258
|
info(`Using frontend framework mode from lt.config: ${frontendFrameworkMode}`);
|
|
258
259
|
}
|
|
259
260
|
else if (noConfirm) {
|
|
260
|
-
frontendFrameworkMode = '
|
|
261
|
+
frontendFrameworkMode = 'vendor';
|
|
261
262
|
}
|
|
262
263
|
else {
|
|
263
|
-
// Default to
|
|
264
|
-
frontendFrameworkMode = '
|
|
264
|
+
// Default to vendor without asking (unless user sets it explicitly)
|
|
265
|
+
frontendFrameworkMode = 'vendor';
|
|
265
266
|
}
|
|
266
267
|
// Determine remote push settings with priority: CLI > config > interactive
|
|
267
268
|
// Git is always initialized; the question is whether to push to a remote
|
|
@@ -273,8 +274,13 @@ const NewCommand = {
|
|
|
273
274
|
if (pushToRemote) {
|
|
274
275
|
gitLink = cliGitLink || configGitLink;
|
|
275
276
|
if (!gitLink) {
|
|
276
|
-
|
|
277
|
-
|
|
277
|
+
// Git is always initialized locally (dev branch + initial commit);
|
|
278
|
+
// --git only controls the remote push. Without a link there is
|
|
279
|
+
// nothing to push to, so degrade to a local-only init instead of
|
|
280
|
+
// aborting the whole scaffold — consistent with the config and
|
|
281
|
+
// interactive branches below.
|
|
282
|
+
warning('--git true without --git-link: initializing local git only (no remote push).');
|
|
283
|
+
pushToRemote = false;
|
|
278
284
|
}
|
|
279
285
|
}
|
|
280
286
|
}
|
|
@@ -314,6 +320,14 @@ const NewCommand = {
|
|
|
314
320
|
}
|
|
315
321
|
}
|
|
316
322
|
}
|
|
323
|
+
else if (noConfirm) {
|
|
324
|
+
// Default in noConfirm mode: git true. Git is always initialized locally
|
|
325
|
+
// (dev branch + initial commit); push to a remote only when a gitLink is
|
|
326
|
+
// configured, otherwise stay local-only (nothing to push to).
|
|
327
|
+
gitLink = configGitLink;
|
|
328
|
+
pushToRemote = !!gitLink;
|
|
329
|
+
info(`Using default git: true${gitLink ? ' (push to configured gitLink)' : ' (local only — no --git-link configured)'}`);
|
|
330
|
+
}
|
|
317
331
|
// Determine branches and copy/link paths with priority: CLI > config
|
|
318
332
|
const apiBranch = cliApiBranch || configApiBranch;
|
|
319
333
|
// Under `--next`, default the nuxt-base-starter ref to the `next`
|
|
@@ -606,14 +620,14 @@ const NewCommand = {
|
|
|
606
620
|
else {
|
|
607
621
|
serverSpinner.warn('Nest Server Starter not integrated');
|
|
608
622
|
}
|
|
609
|
-
//
|
|
610
|
-
// honors `pnpm.overrides
|
|
611
|
-
//
|
|
612
|
-
//
|
|
613
|
-
//
|
|
614
|
-
//
|
|
615
|
-
//
|
|
616
|
-
(0,
|
|
623
|
+
// Normalize the workspace root. Hoists workspace-scoped pnpm config out
|
|
624
|
+
// of the sub-projects (pnpm only honors `pnpm.overrides` etc. at the
|
|
625
|
+
// root — otherwise CVE overrides are silently disabled), drops the
|
|
626
|
+
// starters' standalone pnpm-lock.yaml files the root supersedes, and
|
|
627
|
+
// guarantees a root `.dockerignore` (else the images carry the host's
|
|
628
|
+
// node_modules, a stale .output, and a local .env that `nuxt build`
|
|
629
|
+
// bakes in).
|
|
630
|
+
(0, workspace_integration_1.finalizeWorkspaceRoot)({ filesystem, projectDir });
|
|
617
631
|
// Install all packages
|
|
618
632
|
if (!experimental) {
|
|
619
633
|
const installSpinner = spin('Install all packages');
|
package/build/commands/status.js
CHANGED
|
@@ -251,6 +251,8 @@ const StatusCommand = {
|
|
|
251
251
|
for (const [sub, host] of Object.entries(entry.subdomains)) {
|
|
252
252
|
info(` ${sub.padEnd(6)} https://${host}`);
|
|
253
253
|
}
|
|
254
|
+
// `loadRegistry` strips dbName from API-less entries, so its
|
|
255
|
+
// presence alone means there is a database to advertise.
|
|
254
256
|
if (entry.dbName)
|
|
255
257
|
info(` db mongodb://127.0.0.1/${entry.dbName}`);
|
|
256
258
|
const session = (0, dev_state_1.loadSession)(registryRoot);
|
|
@@ -61,6 +61,8 @@ const ListCommand = {
|
|
|
61
61
|
if (entry) {
|
|
62
62
|
for (const [sub, host] of Object.entries(entry.subdomains))
|
|
63
63
|
info(` ${sub.padEnd(4)} https://${host}`);
|
|
64
|
+
// `loadRegistry` strips dbName from API-less entries, so its presence
|
|
65
|
+
// alone means there is a database to show.
|
|
64
66
|
if (entry.dbName)
|
|
65
67
|
info(` db mongodb://127.0.0.1/${entry.dbName}`);
|
|
66
68
|
}
|
|
@@ -97,14 +97,16 @@ const StartCommand = {
|
|
|
97
97
|
}
|
|
98
98
|
// 2. tag the worktree with its ticket id (makes lt dev * ticket-aware).
|
|
99
99
|
(0, dev_ticket_1.writeTicketMarker)(worktreePath, id);
|
|
100
|
-
// 3. install deps
|
|
100
|
+
// 3. install deps. Auto-detects pnpm/yarn/npm from the worktree's
|
|
101
|
+
// lockfile so an npm-only repo doesn't get a foreign pnpm-lock
|
|
102
|
+
// injected on every ticket start.
|
|
101
103
|
if (parameters.options.install !== false) {
|
|
102
|
-
info(colors.dim('Installing dependencies
|
|
104
|
+
info(colors.dim('Installing dependencies …'));
|
|
103
105
|
try {
|
|
104
|
-
(0, dev_ticket_1.
|
|
106
|
+
(0, dev_ticket_1.installWorktreeDeps)(worktreePath);
|
|
105
107
|
}
|
|
106
108
|
catch (e) {
|
|
107
|
-
warning(`
|
|
109
|
+
warning(`install failed (${e.message}) — continuing; run it manually in the worktree.`);
|
|
108
110
|
}
|
|
109
111
|
}
|
|
110
112
|
// 4. bring the isolated stack up (re-invokes THIS lt build so the marker is
|
|
@@ -141,49 +141,54 @@ class FrontendHelper {
|
|
|
141
141
|
return __awaiter(this, arguments, void 0, function* (dest, options = {}) {
|
|
142
142
|
const { system, templateHelper } = this.toolbox;
|
|
143
143
|
const { branch, copyPath, linkPath, skipInstall } = options;
|
|
144
|
-
//
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
164
|
-
// Run install if not skipped and not a symlink
|
|
165
|
-
if (!skipInstall && result.method !== 'link') {
|
|
166
|
-
try {
|
|
167
|
-
const { pm } = this.toolbox;
|
|
168
|
-
yield system.run(`cd "${dest}" && ${pm.install(pm.detect(dest))}`);
|
|
169
|
-
}
|
|
170
|
-
catch (err) {
|
|
171
|
-
return { method: result.method, path: dest, success: false };
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
return { method: result.method, path: result.path, success: true };
|
|
144
|
+
// Source the Nuxt app from the nuxt-base-starter repo (priority:
|
|
145
|
+
// link > copy > clone), mirroring the backend (nest-server-starter)
|
|
146
|
+
// flow. The default — no link/copy/branch — clones the repo's default
|
|
147
|
+
// branch, so a fresh init always integrates the CURRENT GitHub template.
|
|
148
|
+
//
|
|
149
|
+
// This deliberately replaces the former `create-nuxt-base@latest` npx
|
|
150
|
+
// path: that package is marked `private` and is no longer published
|
|
151
|
+
// (nuxt-base-starter commit b534af2 — "distribute via lt CLI fullstack
|
|
152
|
+
// template"), so `@latest` was frozen at an outdated copy and the
|
|
153
|
+
// bundled template drifted from GitHub. Cloning the repo directly is
|
|
154
|
+
// the same mechanism the backend already uses and removes that drift.
|
|
155
|
+
const result = yield templateHelper.setup(dest, {
|
|
156
|
+
branch,
|
|
157
|
+
copyPath,
|
|
158
|
+
isNuxt: true,
|
|
159
|
+
linkPath,
|
|
160
|
+
repoUrl: linkPath || copyPath ? undefined : 'https://github.com/lenneTech/nuxt-base-starter.git',
|
|
161
|
+
});
|
|
162
|
+
if (!result.success) {
|
|
163
|
+
return { method: result.method, path: result.path, success: false };
|
|
175
164
|
}
|
|
176
|
-
//
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
165
|
+
// After a clone, flatten the wrapper layout so `dest` IS the Nuxt app
|
|
166
|
+
// (the cloned root carries the scaffolder; the app lives in
|
|
167
|
+
// `nuxt-base-template/` — see flattenNuxtBaseTemplate). Skip on link
|
|
168
|
+
// mode: a symlink points at the user's checkout and must not be torn out.
|
|
169
|
+
if (result.method === 'clone') {
|
|
170
|
+
yield this.flattenNuxtBaseTemplate(dest);
|
|
171
|
+
}
|
|
172
|
+
// Normalize the sub-project package name to a stable, valid workspace
|
|
173
|
+
// name ("app"). The template ships as `nuxt-base-template`; the former
|
|
174
|
+
// create-nuxt-base path renamed it the same way. Skip link mode — a
|
|
175
|
+
// symlinked checkout is shared with upstream and must not be mutated.
|
|
176
|
+
if (result.method !== 'link') {
|
|
181
177
|
yield this.fixPackageName(dest);
|
|
182
|
-
return { method: 'npx', path: dest, success: true };
|
|
183
178
|
}
|
|
184
|
-
|
|
185
|
-
|
|
179
|
+
// Run install unless skipped or a symlink. Fullstack init installs at
|
|
180
|
+
// the monorepo level (skipInstall: true); standalone `lt frontend nuxt`
|
|
181
|
+
// installs here (create-nuxt-base used to handle that).
|
|
182
|
+
if (!skipInstall && result.method !== 'link') {
|
|
183
|
+
try {
|
|
184
|
+
const { pm } = this.toolbox;
|
|
185
|
+
yield system.run(`cd "${dest}" && ${pm.install(pm.detect(dest))}`);
|
|
186
|
+
}
|
|
187
|
+
catch (_a) {
|
|
188
|
+
return { method: result.method, path: dest, success: false };
|
|
189
|
+
}
|
|
186
190
|
}
|
|
191
|
+
return { method: result.method, path: result.path, success: true };
|
|
187
192
|
});
|
|
188
193
|
}
|
|
189
194
|
/**
|