@lenne.tech/cli 1.37.1 → 1.38.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/build/commands/dev/prune.js +12 -3
- package/build/commands/dev/up.js +1 -1
- package/build/lib/dev-prune.js +51 -0
- package/package.json +10 -51
|
@@ -26,7 +26,12 @@ const workspace_integration_1 = require("../../lib/workspace-integration");
|
|
|
26
26
|
* `lt ticket stop --keep-db` are never touched.
|
|
27
27
|
* 2. STALE SHARD TEST DATABASES (`<base>-test-<n>` from `lt dev test --shard`)
|
|
28
28
|
* when no test session is running — they are reset on every run anyway.
|
|
29
|
-
* 3.
|
|
29
|
+
* 3. ORPHANED SMOKE-TEST DATABASES (global): the `/lt-dev:fullstack:smoke-test`
|
|
30
|
+
* throwaway projects use the reserved `lt-smoke-test` slug; their DBs are
|
|
31
|
+
* ephemeral by convention. Leftovers (e.g. a blocked drop during the run's
|
|
32
|
+
* cleanup) would be REUSED by the next run's stack and leak state between
|
|
33
|
+
* test runs — swept here whenever no live smoke-test run is registered.
|
|
34
|
+
* 4. DEAD REGISTRY ENTRIES (all projects): path no longer exists → the entry and
|
|
30
35
|
* its reserved ports are reclaimed. Databases of dead MAIN projects are NEVER
|
|
31
36
|
* dropped (a deleted folder is not consent to destroy data).
|
|
32
37
|
*
|
|
@@ -62,9 +67,9 @@ const PruneCommand = {
|
|
|
62
67
|
projectDevDb,
|
|
63
68
|
slug,
|
|
64
69
|
});
|
|
65
|
-
const dbTargets = [...new Set([...plan.orphan.targets, ...plan.shardTargets])];
|
|
70
|
+
const dbTargets = [...new Set([...plan.orphan.targets, ...plan.shardTargets, ...plan.smokeTargets])];
|
|
66
71
|
if (dbTargets.length === 0 && plan.registryPrune.length === 0) {
|
|
67
|
-
success('Nothing to prune — no orphaned ticket DBs, no stale shard DBs, no dead registry entries.');
|
|
72
|
+
success('Nothing to prune — no orphaned ticket DBs, no stale shard DBs, no smoke-test DBs, no dead registry entries.');
|
|
68
73
|
if (plan.orphan.protected.length > 0) {
|
|
69
74
|
info(colors.dim(` kept (registry keptDbs / referenced): ${plan.orphan.protected.join(', ')}`));
|
|
70
75
|
}
|
|
@@ -80,6 +85,10 @@ const PruneCommand = {
|
|
|
80
85
|
info(colors.bold('Stale shard test databases (no test session running):'));
|
|
81
86
|
plan.shardTargets.forEach((db) => info(colors.dim(` • ${db}`)));
|
|
82
87
|
}
|
|
88
|
+
if (plan.smokeTargets.length > 0) {
|
|
89
|
+
info(colors.bold('Orphaned smoke-test databases (reserved lt-smoke-test prefix, no live run):'));
|
|
90
|
+
plan.smokeTargets.forEach((db) => info(colors.dim(` • ${db}`)));
|
|
91
|
+
}
|
|
83
92
|
if (plan.orphan.protected.length > 0) {
|
|
84
93
|
info(colors.dim(`Kept (recorded via --keep-db or still referenced): ${plan.orphan.protected.join(', ')}`));
|
|
85
94
|
}
|
package/build/commands/dev/up.js
CHANGED
|
@@ -458,7 +458,7 @@ const UpCommand = {
|
|
|
458
458
|
projectDevDb: (0, dev_project_1.deriveDbName)(mainLayout.apiDir, baseSlug),
|
|
459
459
|
slug: baseSlug,
|
|
460
460
|
});
|
|
461
|
-
const dbTargets = [...new Set([...plan.orphan.targets, ...plan.shardTargets])];
|
|
461
|
+
const dbTargets = [...new Set([...plan.orphan.targets, ...plan.shardTargets, ...plan.smokeTargets])];
|
|
462
462
|
if (dbTargets.length > 0) {
|
|
463
463
|
const { dropped, reason } = (0, dev_ticket_1.dropDatabases)(dbTargets, undefined, [mainLayout.apiDir, mainRepoRoot]);
|
|
464
464
|
if (dropped.length > 0) {
|
package/build/lib/dev-prune.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SMOKE_TEST_DB_PREFIX = void 0;
|
|
3
4
|
exports.collectDevPrunePlan = collectDevPrunePlan;
|
|
4
5
|
exports.listLiveTicketIds = listLiveTicketIds;
|
|
5
6
|
exports.listPastTicketIds = listPastTicketIds;
|
|
6
7
|
exports.planOrphanTicketDbSweep = planOrphanTicketDbSweep;
|
|
7
8
|
exports.planRegistryPrune = planRegistryPrune;
|
|
9
|
+
exports.planSmokeTestDbSweep = planSmokeTestDbSweep;
|
|
8
10
|
exports.planStaleShardDbSweep = planStaleShardDbSweep;
|
|
9
11
|
/**
|
|
10
12
|
* Garbage collection for `lt dev` / `lt ticket` leftovers.
|
|
@@ -44,6 +46,13 @@ const dev_project_1 = require("./dev-project");
|
|
|
44
46
|
const dev_ticket_1 = require("./dev-ticket");
|
|
45
47
|
/** Branch prefix `lt ticket start` creates worktrees on. */
|
|
46
48
|
const TICKET_BRANCH_PREFIX = 'feat/';
|
|
49
|
+
/**
|
|
50
|
+
* Slug convention of the lt-dev fullstack smoke test (`/lt-dev:fullstack:smoke-test`).
|
|
51
|
+
* Its throwaway projects are named `lt-smoke-test`, so every database under this
|
|
52
|
+
* prefix is ephemeral BY CONVENTION — reserve the prefix for smoke-test runs and
|
|
53
|
+
* never name a real project like this.
|
|
54
|
+
*/
|
|
55
|
+
exports.SMOKE_TEST_DB_PREFIX = 'lt-smoke-test';
|
|
47
56
|
/**
|
|
48
57
|
* Collect the full prune plan for one project. Reads the registry and the Mongo
|
|
49
58
|
* database listing; performs NO destructive action.
|
|
@@ -66,6 +75,7 @@ function collectDevPrunePlan(args) {
|
|
|
66
75
|
projectDevDb,
|
|
67
76
|
projectRoot: mainRepoRoot,
|
|
68
77
|
}),
|
|
78
|
+
smokeTargets: planSmokeTestDbSweep({ observedDbNames, registry }),
|
|
69
79
|
};
|
|
70
80
|
}
|
|
71
81
|
/** Ticket ids that still have a live environment (worktree and/or live registry entry). */
|
|
@@ -182,6 +192,47 @@ function planRegistryPrune(registry) {
|
|
|
182
192
|
.filter(([, entry]) => entry.path && !(0, fs_1.existsSync)(entry.path))
|
|
183
193
|
.map(([key]) => key);
|
|
184
194
|
}
|
|
195
|
+
/**
|
|
196
|
+
* Orphaned smoke-test databases. The `/lt-dev:fullstack:smoke-test` command
|
|
197
|
+
* scaffolds throwaway projects under the reserved {@link SMOKE_TEST_DB_PREFIX}
|
|
198
|
+
* slug; their databases (`lt-smoke-test-local`, `lt-smoke-test-test`, ticket
|
|
199
|
+
* variants, …) are ephemeral by convention. When the run's cleanup could not
|
|
200
|
+
* drop them (e.g. a blocking policy hook) they linger and — worse — get
|
|
201
|
+
* REUSED by the next run's stack, leaking state between test runs (observed:
|
|
202
|
+
* a previous run's user made a fresh sign-up probe fail with
|
|
203
|
+
* "Email already registered").
|
|
204
|
+
*
|
|
205
|
+
* Fail-closed gates, in line with the rest of this module:
|
|
206
|
+
* - No server listing → empty plan.
|
|
207
|
+
* - A LIVE registry entry under the prefix (path exists ⇒ a smoke test is
|
|
208
|
+
* running right now) → empty plan; never pull the DB out from under an
|
|
209
|
+
* active run.
|
|
210
|
+
* - Names recorded as kept (`keptDbs`) or referenced by any live entry's
|
|
211
|
+
* `dbName` are never touched.
|
|
212
|
+
*/
|
|
213
|
+
function planSmokeTestDbSweep(args) {
|
|
214
|
+
var _a;
|
|
215
|
+
const { observedDbNames, registry } = args;
|
|
216
|
+
if (!observedDbNames || observedDbNames.length === 0)
|
|
217
|
+
return [];
|
|
218
|
+
const entries = Object.entries(registry.projects);
|
|
219
|
+
const smokeRunLive = entries.some(([key, entry]) => (key === exports.SMOKE_TEST_DB_PREFIX || key.startsWith(`${exports.SMOKE_TEST_DB_PREFIX}-`)) &&
|
|
220
|
+
entry.path &&
|
|
221
|
+
(0, fs_1.existsSync)(entry.path));
|
|
222
|
+
if (smokeRunLive)
|
|
223
|
+
return [];
|
|
224
|
+
const protectedNames = new Set();
|
|
225
|
+
for (const [, entry] of entries) {
|
|
226
|
+
if (entry.dbName && entry.path && (0, fs_1.existsSync)(entry.path)) {
|
|
227
|
+
protectedNames.add(entry.dbName);
|
|
228
|
+
protectedNames.add((0, dev_project_1.deriveTestDbName)(entry.dbName));
|
|
229
|
+
}
|
|
230
|
+
for (const kept of (_a = entry.keptDbs) !== null && _a !== void 0 ? _a : []) {
|
|
231
|
+
protectedNames.add(kept);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return observedDbNames.filter((name) => (name === exports.SMOKE_TEST_DB_PREFIX || name.startsWith(`${exports.SMOKE_TEST_DB_PREFIX}-`)) && !protectedNames.has(name));
|
|
235
|
+
}
|
|
185
236
|
/**
|
|
186
237
|
* Stale sharded-test databases of the project itself (`<base>-test-<n>` from
|
|
187
238
|
* `lt dev test --shard`). They are ephemeral by definition — every shard run
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lenne.tech/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.38.0",
|
|
4
4
|
"description": "lenne.Tech CLI: lt",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"lenne.Tech",
|
|
@@ -61,19 +61,19 @@
|
|
|
61
61
|
"bin"
|
|
62
62
|
],
|
|
63
63
|
"dependencies": {
|
|
64
|
-
"@aws-sdk/client-s3": "3.
|
|
64
|
+
"@aws-sdk/client-s3": "3.1090.0",
|
|
65
65
|
"@lenne.tech/cli-plugin-helper": "0.0.14",
|
|
66
|
-
"axios": "1.
|
|
66
|
+
"axios": "1.18.1",
|
|
67
67
|
"bcrypt": "6.0.0",
|
|
68
|
-
"defuddle": "0.
|
|
68
|
+
"defuddle": "0.19.1",
|
|
69
69
|
"glob": "13.0.6",
|
|
70
70
|
"gluegun": "5.2.2",
|
|
71
71
|
"js-sha256": "0.11.1",
|
|
72
|
-
"js-yaml": "4.
|
|
72
|
+
"js-yaml": "4.3.0",
|
|
73
73
|
"jsdom": "29.1.1",
|
|
74
74
|
"lodash": "4.18.1",
|
|
75
75
|
"open": "11.0.0",
|
|
76
|
-
"playwright-core": "1.
|
|
76
|
+
"playwright-core": "1.61.1",
|
|
77
77
|
"ts-morph": "28.0.0",
|
|
78
78
|
"ts-node": "10.9.2",
|
|
79
79
|
"turndown": "7.2.4",
|
|
@@ -88,9 +88,9 @@
|
|
|
88
88
|
"@types/js-yaml": "4.0.9",
|
|
89
89
|
"@types/jsdom": "28.0.1",
|
|
90
90
|
"@types/lodash": "4.17.24",
|
|
91
|
-
"@types/node": "
|
|
91
|
+
"@types/node": "26.1.1",
|
|
92
92
|
"@types/turndown": "5.0.6",
|
|
93
|
-
"ejs": "
|
|
93
|
+
"ejs": "6.0.1",
|
|
94
94
|
"eslint": "9.39.4",
|
|
95
95
|
"husky": "9.1.7",
|
|
96
96
|
"jest": "30.4.2",
|
|
@@ -100,20 +100,10 @@
|
|
|
100
100
|
"ts-jest": "29.4.11"
|
|
101
101
|
},
|
|
102
102
|
"//overrides": {
|
|
103
|
-
"
|
|
104
|
-
"semver@*": "Force latest semver 7.x across all sub-deps; gluegun@5.2.2 pins semver@7.7.0 which is stale - remove once gluegun updates its dep.",
|
|
105
|
-
"js-yaml": "Security fix: GHSA-h67p-54hq-rp68 (quadratic-complexity DoS in merge-key handling) in js-yaml <=4.1.1. Forces 4.2.0 everywhere, incl. the 3.14.2 pulled transitively by @istanbuljs/load-nyc-config under babel-plugin-istanbul (jest coverage); that loader only runs js-yaml when reading a YAML nyc config, which this project does not use. Remove once the jest toolchain resolves js-yaml >=4.2.0 itself.",
|
|
106
|
-
"form-data": "Security fix: GHSA-hmw2-7cc7-3qxx (CRLF injection via unescaped multipart field names) in form-data 4.0.0-4.0.5 - transitive via axios. Remove once axios pins form-data >=4.0.6.",
|
|
107
|
-
"@babel/core": "Security fix: GHSA-4x5r-pxfx-6jf8 (arbitrary file read via sourceMappingURL) in @babel/core <=7.29.0 - transitive via the jest toolchain. Remove once jest resolves @babel/core >=7.29.6.",
|
|
108
|
-
"undici": "Security fix: GHSA-vmh5-mc38-953g (TLS certificate validation bypass via dropped requestTls in SOCKS5 ProxyAgent) and GHSA-pr7r-676h-xcf6 (cross-user info disclosure via shared cache whitespace bypass) in undici 7.0.0-7.27.2 - transitive via jsdom (jest test environment). Forces 7.28.0, which satisfies jsdom's ^7.25.0 range. Remove once jsdom resolves undici >=7.28.0."
|
|
103
|
+
"semver@*": "Force latest semver 7.x across all sub-deps; gluegun@5.2.2 pins semver@7.7.0 which is stale - remove once gluegun updates its dep."
|
|
109
104
|
},
|
|
110
105
|
"overrides": {
|
|
111
|
-
"
|
|
112
|
-
"brace-expansion@5.0.2 - 5.0.5": "5.0.6",
|
|
113
|
-
"form-data": "4.0.6",
|
|
114
|
-
"js-yaml": "4.2.0",
|
|
115
|
-
"semver@*": "7.8.1",
|
|
116
|
-
"undici": "7.28.0"
|
|
106
|
+
"semver@*": "7.8.5"
|
|
117
107
|
},
|
|
118
108
|
"jest": {
|
|
119
109
|
"testEnvironment": "node",
|
|
@@ -130,36 +120,5 @@
|
|
|
130
120
|
}
|
|
131
121
|
]
|
|
132
122
|
}
|
|
133
|
-
},
|
|
134
|
-
"pnpm": {
|
|
135
|
-
"overrides": {
|
|
136
|
-
"@apollo/server": "5.5.1",
|
|
137
|
-
"@babel/plugin-transform-modules-systemjs": "7.29.4",
|
|
138
|
-
"@hono/node-server": "1.19.14",
|
|
139
|
-
"@protobufjs/utf8": "1.1.1",
|
|
140
|
-
"ajv": "8.20.0",
|
|
141
|
-
"axios": "1.16.0",
|
|
142
|
-
"brace-expansion@<1.1.13": "1.1.14",
|
|
143
|
-
"brace-expansion@>=2.0.0 <2.0.3": "2.1.0",
|
|
144
|
-
"brace-expansion@>=5.0.0 <5.0.6": "5.0.6",
|
|
145
|
-
"effect": "3.21.2",
|
|
146
|
-
"fast-uri": "3.1.2",
|
|
147
|
-
"hono": "4.12.22",
|
|
148
|
-
"lodash": "4.18.1",
|
|
149
|
-
"picomatch": "4.0.4",
|
|
150
|
-
"qs": "6.15.2",
|
|
151
|
-
"uuid": "14.0.0",
|
|
152
|
-
"vite": "8.0.10",
|
|
153
|
-
"ws@>=8.0.0 <8.20.1": "8.21.0"
|
|
154
|
-
},
|
|
155
|
-
"onlyBuiltDependencies": [
|
|
156
|
-
"@apollo/protobufjs",
|
|
157
|
-
"@compodoc/compodoc",
|
|
158
|
-
"@nestjs/core",
|
|
159
|
-
"@scarf/scarf",
|
|
160
|
-
"@swc/core",
|
|
161
|
-
"bcrypt",
|
|
162
|
-
"esbuild"
|
|
163
|
-
]
|
|
164
123
|
}
|
|
165
124
|
}
|