@lark-apaas/fullstack-cli 1.1.16-alpha.1 → 1.1.16-alpha.2
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/dist/index.js +922 -532
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import
|
|
2
|
+
import fs21 from "fs";
|
|
3
3
|
import path17 from "path";
|
|
4
4
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
5
5
|
import { config as dotenvConfig } from "dotenv";
|
|
@@ -117,120 +117,94 @@ Command "${ctx.commandName}" completed in ${elapsed}ms`);
|
|
|
117
117
|
|
|
118
118
|
// src/commands/db/schema.handler.ts
|
|
119
119
|
import path2 from "path";
|
|
120
|
-
import
|
|
120
|
+
import fs4 from "fs";
|
|
121
121
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
122
122
|
import { spawnSync } from "child_process";
|
|
123
123
|
import { createRequire } from "module";
|
|
124
124
|
import { config as loadEnv } from "dotenv";
|
|
125
125
|
|
|
126
|
+
// src/commands/db/gen-dbschema/index.ts
|
|
127
|
+
import fs3 from "fs";
|
|
128
|
+
import path from "path";
|
|
129
|
+
|
|
126
130
|
// src/commands/db/gen-dbschema/postprocess.ts
|
|
127
131
|
import fs2 from "fs";
|
|
128
|
-
import path from "path";
|
|
129
132
|
|
|
130
|
-
// src/commands/db/gen-dbschema/
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
`;
|
|
150
|
-
}
|
|
151
|
-
return `${ESLINT_DISABLE}
|
|
152
|
-
${HEADER_COMMENT}
|
|
153
|
-
${trimmed}`;
|
|
133
|
+
// src/commands/db/gen-dbschema/transforms/core.ts
|
|
134
|
+
import { IndentationText, Project, QuoteKind } from "ts-morph";
|
|
135
|
+
|
|
136
|
+
// src/commands/db/gen-dbschema/transforms/types.ts
|
|
137
|
+
function createEmptyStats() {
|
|
138
|
+
return {
|
|
139
|
+
patchedDefects: 0,
|
|
140
|
+
removedPgSchemas: 0,
|
|
141
|
+
convertedSchemaCalls: 0,
|
|
142
|
+
renamedIdentifiers: [],
|
|
143
|
+
replacedUnknown: 0,
|
|
144
|
+
fallbackToText: 0,
|
|
145
|
+
unmatchedUnknown: [],
|
|
146
|
+
replacedTimestamp: 0,
|
|
147
|
+
replacedDefaultNow: 0,
|
|
148
|
+
removedSystemFields: 0,
|
|
149
|
+
addedImports: [],
|
|
150
|
+
removedImports: []
|
|
151
|
+
};
|
|
154
152
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
153
|
+
|
|
154
|
+
// src/commands/db/gen-dbschema/transforms/core.ts
|
|
155
|
+
var PROJECT_OPTIONS = {
|
|
156
|
+
skipAddingFilesFromTsConfig: true,
|
|
157
|
+
skipFileDependencyResolution: true,
|
|
158
|
+
manipulationSettings: {
|
|
159
|
+
indentationText: IndentationText.TwoSpaces,
|
|
160
|
+
quoteKind: QuoteKind.Single
|
|
159
161
|
}
|
|
160
|
-
|
|
162
|
+
};
|
|
163
|
+
function parseSource(source, fileName = "schema.ts") {
|
|
164
|
+
const project = new Project({
|
|
165
|
+
...PROJECT_OPTIONS,
|
|
166
|
+
useInMemoryFileSystem: true
|
|
167
|
+
});
|
|
168
|
+
const sourceFile = project.createSourceFile(fileName, source);
|
|
169
|
+
return { project, sourceFile };
|
|
161
170
|
}
|
|
162
|
-
function
|
|
163
|
-
|
|
171
|
+
function applyTransforms(sourceFile, transforms) {
|
|
172
|
+
const stats = createEmptyStats();
|
|
173
|
+
for (const transform of transforms) {
|
|
174
|
+
try {
|
|
175
|
+
transform.transform({ sourceFile, stats });
|
|
176
|
+
} catch (error) {
|
|
177
|
+
console.error(`[ast] Transform "${transform.name}" failed:`, error);
|
|
178
|
+
throw error;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return stats;
|
|
164
182
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
}
|
|
170
|
-
function convertSchemaTableInvocations(source) {
|
|
171
|
-
let converted = 0;
|
|
172
|
-
let text = source.replace(/([A-Za-z0-9_]+)\.table\(/g, () => {
|
|
173
|
-
converted += 1;
|
|
174
|
-
return "pgTable(";
|
|
183
|
+
function formatSourceFile(sourceFile) {
|
|
184
|
+
sourceFile.formatText({
|
|
185
|
+
indentSize: 2,
|
|
186
|
+
convertTabsToSpaces: true
|
|
175
187
|
});
|
|
176
|
-
text = text.replace(/([A-Za-z0-9_]+)\.view\(/g, () => {
|
|
177
|
-
converted += 1;
|
|
178
|
-
return "pgView(";
|
|
179
|
-
});
|
|
180
|
-
text = text.replace(/([A-Za-z0-9_]+)\.materializedView\(/g, () => {
|
|
181
|
-
converted += 1;
|
|
182
|
-
return "pgMaterializedView(";
|
|
183
|
-
});
|
|
184
|
-
text = text.replace(/([A-Za-z0-9_]+)\.enum\(/g, () => {
|
|
185
|
-
converted += 1;
|
|
186
|
-
return "pgEnum(";
|
|
187
|
-
});
|
|
188
|
-
text = text.replace(/([A-Za-z0-9_]+)\.sequence\(/g, () => {
|
|
189
|
-
converted += 1;
|
|
190
|
-
return "pgSequence(";
|
|
191
|
-
});
|
|
192
|
-
return { text, converted };
|
|
193
188
|
}
|
|
189
|
+
function printSourceFile(sourceFile) {
|
|
190
|
+
return sourceFile.getFullText();
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// src/commands/db/gen-dbschema/transforms/ast/rename-identifiers.ts
|
|
194
|
+
import { Node } from "ts-morph";
|
|
194
195
|
|
|
195
|
-
// src/commands/db/gen-dbschema/
|
|
196
|
+
// src/commands/db/gen-dbschema/utils/identifier.ts
|
|
196
197
|
import { pinyin } from "pinyin-pro";
|
|
197
|
-
function
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
const originalRef = quote === '"' ? currentName : currentName;
|
|
207
|
-
renames.push({ from: originalRef, to: sanitized });
|
|
208
|
-
const equalsIndex = match.indexOf("=");
|
|
209
|
-
const suffix = equalsIndex >= 0 ? match.slice(equalsIndex) : ` = ${factory}("${tableName}"`;
|
|
210
|
-
const normalizedSuffix = suffix.trimStart();
|
|
211
|
-
return `export const ${sanitized} ${normalizedSuffix}`;
|
|
212
|
-
});
|
|
213
|
-
return { text: updated, renames };
|
|
214
|
-
}
|
|
215
|
-
function updateTableReferenceIdentifiers(source, renames) {
|
|
216
|
-
if (renames.length === 0) {
|
|
217
|
-
return source;
|
|
198
|
+
function toAsciiName(name) {
|
|
199
|
+
if (!/[^\x00-\x7F]/.test(name)) {
|
|
200
|
+
return name;
|
|
201
|
+
}
|
|
202
|
+
try {
|
|
203
|
+
const transliterated = pinyin(name, { toneType: "none", type: "array" }).join("_");
|
|
204
|
+
return transliterated || name;
|
|
205
|
+
} catch {
|
|
206
|
+
return name;
|
|
218
207
|
}
|
|
219
|
-
return renames.reduce((acc, rename) => {
|
|
220
|
-
if (!rename.from || rename.from === rename.to) {
|
|
221
|
-
return acc;
|
|
222
|
-
}
|
|
223
|
-
const pattern = new RegExp(`\\b${escapeRegExp(rename.from)}(\\s*[.(])`, "g");
|
|
224
|
-
let result = acc.replace(pattern, `${rename.to}$1`);
|
|
225
|
-
const quotedCallPattern = new RegExp(`"${escapeRegExp(rename.from)}"(\\s*\\()`, "g");
|
|
226
|
-
result = result.replace(quotedCallPattern, `${rename.to}$1`);
|
|
227
|
-
const quotedDotPattern = new RegExp(`"${escapeRegExp(rename.from)}"(\\s*\\.)`, "g");
|
|
228
|
-
result = result.replace(quotedDotPattern, `${rename.to}$1`);
|
|
229
|
-
return result;
|
|
230
|
-
}, source);
|
|
231
|
-
}
|
|
232
|
-
function escapeRegExp(value) {
|
|
233
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\//g, "\\/");
|
|
234
208
|
}
|
|
235
209
|
function toCamelCase(str) {
|
|
236
210
|
const words = str.split(/[_\-\s]+/).filter(Boolean);
|
|
@@ -258,129 +232,633 @@ function sanitizeIdentifier(name) {
|
|
|
258
232
|
}
|
|
259
233
|
return sanitized;
|
|
260
234
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
235
|
+
|
|
236
|
+
// src/commands/db/gen-dbschema/transforms/ast/rename-identifiers.ts
|
|
237
|
+
var PG_FACTORIES = [
|
|
238
|
+
"pgTable",
|
|
239
|
+
"pgView",
|
|
240
|
+
"pgMaterializedView",
|
|
241
|
+
"pgEnum",
|
|
242
|
+
"pgSequence",
|
|
243
|
+
// Also match schema.xxx() format (before conversion)
|
|
244
|
+
"table",
|
|
245
|
+
"view",
|
|
246
|
+
"materializedView",
|
|
247
|
+
"enum",
|
|
248
|
+
"sequence"
|
|
249
|
+
];
|
|
250
|
+
function extractFactoryName(initializer) {
|
|
251
|
+
if (!Node.isCallExpression(initializer)) {
|
|
252
|
+
return void 0;
|
|
264
253
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
return
|
|
268
|
-
}
|
|
269
|
-
|
|
254
|
+
const args = initializer.getArguments();
|
|
255
|
+
if (args.length === 0) {
|
|
256
|
+
return void 0;
|
|
257
|
+
}
|
|
258
|
+
const firstArg = args[0];
|
|
259
|
+
if (Node.isStringLiteral(firstArg)) {
|
|
260
|
+
return firstArg.getLiteralText();
|
|
270
261
|
}
|
|
262
|
+
return void 0;
|
|
271
263
|
}
|
|
264
|
+
function isPgFactoryCall(initializer) {
|
|
265
|
+
if (!Node.isCallExpression(initializer)) {
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
const expression = initializer.getExpression();
|
|
269
|
+
const exprText = expression.getText();
|
|
270
|
+
if (PG_FACTORIES.includes(exprText)) {
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
if (Node.isPropertyAccessExpression(expression)) {
|
|
274
|
+
const propName = expression.getName();
|
|
275
|
+
if (PG_FACTORIES.includes(propName)) {
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
function getCurrentName(decl) {
|
|
282
|
+
const name = decl.getName();
|
|
283
|
+
return name.replace(/^"|"$/g, "");
|
|
284
|
+
}
|
|
285
|
+
var renameIdentifiersTransform = {
|
|
286
|
+
name: "rename-identifiers",
|
|
287
|
+
transform(ctx) {
|
|
288
|
+
const { sourceFile, stats } = ctx;
|
|
289
|
+
const renames = [];
|
|
290
|
+
for (const statement of sourceFile.getStatements()) {
|
|
291
|
+
if (!Node.isVariableStatement(statement)) {
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
if (!statement.hasExportKeyword()) {
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
for (const decl of statement.getDeclarations()) {
|
|
298
|
+
const initializer = decl.getInitializer();
|
|
299
|
+
if (!initializer) {
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
if (!isPgFactoryCall(initializer)) {
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
const tableName = extractFactoryName(initializer);
|
|
306
|
+
if (!tableName) {
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
const currentName = getCurrentName(decl);
|
|
310
|
+
const sanitized = sanitizeIdentifier(tableName);
|
|
311
|
+
if (sanitized !== currentName) {
|
|
312
|
+
renames.push({ decl, from: currentName, to: sanitized });
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
for (const { decl, from, to } of renames.reverse()) {
|
|
317
|
+
try {
|
|
318
|
+
decl.rename(to);
|
|
319
|
+
stats.renamedIdentifiers.push({ from, to });
|
|
320
|
+
} catch (error) {
|
|
321
|
+
console.warn(`[rename-identifiers] Failed to rename "${from}" to "${to}":`, error);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
stats.renamedIdentifiers.reverse();
|
|
325
|
+
}
|
|
326
|
+
};
|
|
272
327
|
|
|
273
|
-
// src/commands/db/gen-dbschema/
|
|
274
|
-
|
|
275
|
-
var
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
const line = lines[i];
|
|
284
|
-
const knownMatch = line.match(CUSTOM_TYPE_PATTERN);
|
|
285
|
-
if (knownMatch) {
|
|
286
|
-
const typeName = knownMatch[1];
|
|
287
|
-
const factory = typeName === "user_profile" ? "userProfile" : "fileAttachment";
|
|
288
|
-
const replacedLine = replaceFollowingUnknown(lines[i + 1], factory);
|
|
289
|
-
if (replacedLine) {
|
|
290
|
-
result.push(replacedLine);
|
|
291
|
-
replaced += 1;
|
|
292
|
-
i += 1;
|
|
293
|
-
} else {
|
|
294
|
-
unmatched.push(line.trim());
|
|
295
|
-
result.push(line);
|
|
328
|
+
// src/commands/db/gen-dbschema/transforms/ast/remove-pg-schema.ts
|
|
329
|
+
import { Node as Node2 } from "ts-morph";
|
|
330
|
+
var removePgSchemaTransform = {
|
|
331
|
+
name: "remove-pg-schema",
|
|
332
|
+
transform(ctx) {
|
|
333
|
+
const { sourceFile, stats } = ctx;
|
|
334
|
+
const statementsToRemove = [];
|
|
335
|
+
for (const statement of sourceFile.getStatements()) {
|
|
336
|
+
if (!Node2.isVariableStatement(statement)) {
|
|
337
|
+
continue;
|
|
296
338
|
}
|
|
297
|
-
|
|
339
|
+
for (const decl of statement.getDeclarations()) {
|
|
340
|
+
const initializer = decl.getInitializer();
|
|
341
|
+
if (!initializer || !Node2.isCallExpression(initializer)) {
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
const calleeText = initializer.getExpression().getText();
|
|
345
|
+
if (calleeText === "pgSchema") {
|
|
346
|
+
statementsToRemove.push(statement);
|
|
347
|
+
stats.removedPgSchemas++;
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
for (const statement of statementsToRemove.reverse()) {
|
|
353
|
+
statement.remove();
|
|
298
354
|
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
// src/commands/db/gen-dbschema/transforms/ast/convert-schema-calls.ts
|
|
359
|
+
import { Node as Node3 } from "ts-morph";
|
|
360
|
+
var SCHEMA_METHOD_TO_PG = {
|
|
361
|
+
table: "pgTable",
|
|
362
|
+
view: "pgView",
|
|
363
|
+
materializedView: "pgMaterializedView",
|
|
364
|
+
enum: "pgEnum",
|
|
365
|
+
sequence: "pgSequence"
|
|
366
|
+
};
|
|
367
|
+
var convertSchemaCallsTransform = {
|
|
368
|
+
name: "convert-schema-calls",
|
|
369
|
+
transform(ctx) {
|
|
370
|
+
const { sourceFile, stats } = ctx;
|
|
371
|
+
sourceFile.forEachDescendant((node) => {
|
|
372
|
+
if (!Node3.isCallExpression(node)) {
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
const expression = node.getExpression();
|
|
376
|
+
if (!Node3.isPropertyAccessExpression(expression)) {
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
const objectExpr = expression.getExpression();
|
|
380
|
+
const methodName = expression.getName();
|
|
381
|
+
const pgFactoryName = SCHEMA_METHOD_TO_PG[methodName];
|
|
382
|
+
if (!pgFactoryName) {
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
if (!Node3.isIdentifier(objectExpr)) {
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
expression.replaceWithText(pgFactoryName);
|
|
389
|
+
stats.convertedSchemaCalls++;
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
// src/commands/db/gen-dbschema/transforms/ast/patch-defects.ts
|
|
395
|
+
import { Node as Node4 } from "ts-morph";
|
|
396
|
+
var patchDefectsTransform = {
|
|
397
|
+
name: "patch-defects",
|
|
398
|
+
transform(ctx) {
|
|
399
|
+
const { sourceFile, stats } = ctx;
|
|
400
|
+
sourceFile.forEachDescendant((node) => {
|
|
401
|
+
if (!Node4.isCallExpression(node)) {
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
const expr = node.getExpression();
|
|
405
|
+
if (!Node4.isPropertyAccessExpression(expr)) {
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
if (expr.getName() !== "default") {
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
const args = node.getArguments();
|
|
412
|
+
if (args.length !== 1) {
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
const arg = args[0];
|
|
416
|
+
if (Node4.isStringLiteral(arg)) {
|
|
417
|
+
const text = arg.getLiteralText();
|
|
418
|
+
if (text === "") {
|
|
419
|
+
stats.patchedDefects++;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
// src/commands/db/gen-dbschema/transforms/ast/replace-unknown.ts
|
|
427
|
+
import { Node as Node5 } from "ts-morph";
|
|
428
|
+
var KNOWN_TYPE_FACTORIES = {
|
|
429
|
+
user_profile: "userProfile",
|
|
430
|
+
file_attachment: "fileAttachment"
|
|
431
|
+
};
|
|
432
|
+
var replaceUnknownTransform = {
|
|
433
|
+
name: "replace-unknown",
|
|
434
|
+
transform(ctx) {
|
|
435
|
+
const { sourceFile, stats } = ctx;
|
|
436
|
+
const fullText = sourceFile.getFullText();
|
|
437
|
+
sourceFile.forEachDescendant((node) => {
|
|
438
|
+
if (!Node5.isCallExpression(node)) {
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
const expression = node.getExpression();
|
|
442
|
+
if (!Node5.isIdentifier(expression) || expression.getText() !== "unknown") {
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
const nodeStart = node.getStart();
|
|
446
|
+
const textBefore = fullText.slice(Math.max(0, nodeStart - 500), nodeStart);
|
|
447
|
+
const lines = textBefore.split("\n");
|
|
448
|
+
let factoryName = "text";
|
|
449
|
+
let foundKnownType = false;
|
|
450
|
+
for (let i = lines.length - 1; i >= Math.max(0, lines.length - 5); i--) {
|
|
451
|
+
const line = lines[i];
|
|
452
|
+
const todoMatch = line.match(/\/\/ TODO: failed to parse database type '(?:\w+\.)?([\w_]+)(\[\])?'/);
|
|
453
|
+
if (todoMatch) {
|
|
454
|
+
const typeName = todoMatch[1];
|
|
455
|
+
if (KNOWN_TYPE_FACTORIES[typeName]) {
|
|
456
|
+
factoryName = KNOWN_TYPE_FACTORIES[typeName];
|
|
457
|
+
foundKnownType = true;
|
|
458
|
+
}
|
|
459
|
+
break;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
expression.replaceWithText(factoryName);
|
|
463
|
+
if (foundKnownType) {
|
|
464
|
+
stats.replacedUnknown++;
|
|
306
465
|
} else {
|
|
307
|
-
|
|
308
|
-
result.push(line);
|
|
466
|
+
stats.fallbackToText++;
|
|
309
467
|
}
|
|
468
|
+
});
|
|
469
|
+
const todoCommentRegex = /\/\/ TODO: failed to parse database type '[^']+'\s*\n/g;
|
|
470
|
+
const currentText = sourceFile.getFullText();
|
|
471
|
+
const cleanedText = currentText.replace(todoCommentRegex, "");
|
|
472
|
+
if (cleanedText !== currentText) {
|
|
473
|
+
sourceFile.replaceWithText(cleanedText);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
// src/commands/db/gen-dbschema/transforms/ast/replace-timestamp.ts
|
|
479
|
+
import { Node as Node6 } from "ts-morph";
|
|
480
|
+
function checkTimestampOptions(optionsArg) {
|
|
481
|
+
let hasWithTimezone = false;
|
|
482
|
+
let hasModeString = false;
|
|
483
|
+
for (const prop of optionsArg.getProperties()) {
|
|
484
|
+
if (!Node6.isPropertyAssignment(prop)) {
|
|
310
485
|
continue;
|
|
311
486
|
}
|
|
312
|
-
|
|
313
|
-
|
|
487
|
+
const propName = prop.getName();
|
|
488
|
+
const initializer = prop.getInitializer();
|
|
489
|
+
if (propName === "withTimezone") {
|
|
490
|
+
if (Node6.isTrueLiteral(initializer)) {
|
|
491
|
+
hasWithTimezone = true;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
if (propName === "mode") {
|
|
495
|
+
if (Node6.isStringLiteral(initializer) && initializer.getLiteralText() === "string") {
|
|
496
|
+
hasModeString = true;
|
|
497
|
+
}
|
|
314
498
|
}
|
|
315
|
-
result.push(line);
|
|
316
499
|
}
|
|
317
|
-
return
|
|
318
|
-
text: result.join("\n"),
|
|
319
|
-
replaced,
|
|
320
|
-
fallbackToText,
|
|
321
|
-
unmatched
|
|
322
|
-
};
|
|
500
|
+
return hasWithTimezone && hasModeString;
|
|
323
501
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
502
|
+
var replaceTimestampTransform = {
|
|
503
|
+
name: "replace-timestamp",
|
|
504
|
+
transform(ctx) {
|
|
505
|
+
const { sourceFile, stats } = ctx;
|
|
506
|
+
const replacements = [];
|
|
507
|
+
sourceFile.forEachDescendant((node) => {
|
|
508
|
+
if (!Node6.isCallExpression(node)) {
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
const expression = node.getExpression();
|
|
512
|
+
if (!Node6.isIdentifier(expression) || expression.getText() !== "timestamp") {
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
const args = node.getArguments();
|
|
516
|
+
if (args.length === 2) {
|
|
517
|
+
const [fieldArg, optionsArg] = args;
|
|
518
|
+
if (!Node6.isStringLiteral(fieldArg)) {
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
if (!Node6.isObjectLiteralExpression(optionsArg)) {
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
if (checkTimestampOptions(optionsArg)) {
|
|
525
|
+
const quote = fieldArg.getQuoteKind() === 1 ? '"' : "'";
|
|
526
|
+
const fieldName = fieldArg.getLiteralText();
|
|
527
|
+
replacements.push({
|
|
528
|
+
node,
|
|
529
|
+
replacement: `customTimestamptz(${quote}${fieldName}${quote})`
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
if (args.length === 1) {
|
|
535
|
+
const [optionsArg] = args;
|
|
536
|
+
if (!Node6.isObjectLiteralExpression(optionsArg)) {
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
if (checkTimestampOptions(optionsArg)) {
|
|
540
|
+
replacements.push({
|
|
541
|
+
node,
|
|
542
|
+
replacement: "customTimestamptz()"
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
});
|
|
548
|
+
for (const { node, replacement } of replacements.reverse()) {
|
|
549
|
+
node.replaceWithText(replacement);
|
|
550
|
+
stats.replacedTimestamp++;
|
|
551
|
+
}
|
|
327
552
|
}
|
|
328
|
-
|
|
329
|
-
}
|
|
553
|
+
};
|
|
330
554
|
|
|
331
|
-
// src/commands/db/gen-dbschema/
|
|
332
|
-
import
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
555
|
+
// src/commands/db/gen-dbschema/transforms/ast/replace-default-now.ts
|
|
556
|
+
import { Node as Node7 } from "ts-morph";
|
|
557
|
+
var replaceDefaultNowTransform = {
|
|
558
|
+
name: "replace-default-now",
|
|
559
|
+
transform(ctx) {
|
|
560
|
+
const { sourceFile, stats } = ctx;
|
|
561
|
+
sourceFile.forEachDescendant((node) => {
|
|
562
|
+
if (!Node7.isCallExpression(node)) {
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
const expression = node.getExpression();
|
|
566
|
+
if (!Node7.isPropertyAccessExpression(expression)) {
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
569
|
+
if (expression.getName() !== "defaultNow") {
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
if (node.getArguments().length !== 0) {
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
const objectExpr = expression.getExpression();
|
|
576
|
+
const objectText = objectExpr.getText();
|
|
577
|
+
node.replaceWithText(`${objectText}.default(sql\`CURRENT_TIMESTAMP\`)`);
|
|
578
|
+
stats.replacedDefaultNow++;
|
|
579
|
+
});
|
|
339
580
|
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
581
|
+
};
|
|
582
|
+
|
|
583
|
+
// src/commands/db/gen-dbschema/transforms/ast/remove-system-fields.ts
|
|
584
|
+
import { Node as Node8 } from "ts-morph";
|
|
585
|
+
var SYSTEM_TO_BUSINESS = {
|
|
586
|
+
_created_at: "created_at",
|
|
587
|
+
_created_by: "created_by",
|
|
588
|
+
_updated_at: "updated_at",
|
|
589
|
+
_updated_by: "updated_by"
|
|
590
|
+
};
|
|
591
|
+
var TABLE_FACTORIES = ["pgTable", "pgView", "pgMaterializedView", "table", "view", "materializedView"];
|
|
592
|
+
var removeSystemFieldsTransform = {
|
|
593
|
+
name: "remove-system-fields",
|
|
594
|
+
transform(ctx) {
|
|
595
|
+
const { sourceFile, stats } = ctx;
|
|
596
|
+
sourceFile.forEachDescendant((node) => {
|
|
597
|
+
if (!Node8.isCallExpression(node)) {
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
const expression = node.getExpression();
|
|
601
|
+
let factoryName = "";
|
|
602
|
+
if (Node8.isIdentifier(expression)) {
|
|
603
|
+
factoryName = expression.getText();
|
|
604
|
+
} else if (Node8.isPropertyAccessExpression(expression)) {
|
|
605
|
+
factoryName = expression.getName();
|
|
606
|
+
}
|
|
607
|
+
if (!TABLE_FACTORIES.includes(factoryName)) {
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
const args = node.getArguments();
|
|
611
|
+
if (args.length < 2) {
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
const columnsArg = args[1];
|
|
615
|
+
if (!Node8.isObjectLiteralExpression(columnsArg)) {
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
const fieldNames = /* @__PURE__ */ new Set();
|
|
619
|
+
const properties = columnsArg.getProperties();
|
|
620
|
+
for (const prop of properties) {
|
|
621
|
+
if (!Node8.isPropertyAssignment(prop)) {
|
|
622
|
+
continue;
|
|
623
|
+
}
|
|
624
|
+
const nameNode = prop.getNameNode();
|
|
625
|
+
let fieldName = "";
|
|
626
|
+
if (Node8.isStringLiteral(nameNode)) {
|
|
627
|
+
fieldName = nameNode.getLiteralText();
|
|
628
|
+
} else if (Node8.isIdentifier(nameNode)) {
|
|
629
|
+
fieldName = nameNode.getText();
|
|
630
|
+
}
|
|
631
|
+
if (fieldName) {
|
|
632
|
+
fieldNames.add(fieldName);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
const propsToRemove = [];
|
|
636
|
+
for (const prop of properties) {
|
|
637
|
+
if (!Node8.isPropertyAssignment(prop)) {
|
|
638
|
+
continue;
|
|
639
|
+
}
|
|
640
|
+
const nameNode = prop.getNameNode();
|
|
641
|
+
let fieldName = "";
|
|
642
|
+
if (Node8.isStringLiteral(nameNode)) {
|
|
643
|
+
fieldName = nameNode.getLiteralText();
|
|
644
|
+
} else if (Node8.isIdentifier(nameNode)) {
|
|
645
|
+
fieldName = nameNode.getText();
|
|
646
|
+
}
|
|
647
|
+
const businessField = SYSTEM_TO_BUSINESS[fieldName];
|
|
648
|
+
if (businessField && fieldNames.has(businessField)) {
|
|
649
|
+
propsToRemove.push(prop);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
for (const prop of propsToRemove) {
|
|
653
|
+
const leadingCommentRanges = prop.getLeadingCommentRanges();
|
|
654
|
+
for (const comment of leadingCommentRanges) {
|
|
655
|
+
const commentText = comment.getText();
|
|
656
|
+
if (commentText.includes("System field:")) {
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
prop.remove();
|
|
660
|
+
stats.removedSystemFields++;
|
|
661
|
+
}
|
|
662
|
+
});
|
|
350
663
|
}
|
|
351
|
-
|
|
352
|
-
|
|
664
|
+
};
|
|
665
|
+
|
|
666
|
+
// src/commands/db/gen-dbschema/transforms/ast/tweak-imports.ts
|
|
667
|
+
var REMOVE_IMPORTS = ["pgSchema", "customType"];
|
|
668
|
+
var PG_FACTORIES2 = ["pgTable", "pgView", "pgMaterializedView", "pgEnum", "pgSequence"];
|
|
669
|
+
var tweakImportsTransform = {
|
|
670
|
+
name: "tweak-imports",
|
|
671
|
+
transform(ctx) {
|
|
672
|
+
const { sourceFile, stats } = ctx;
|
|
673
|
+
const fullText = sourceFile.getFullText();
|
|
674
|
+
const imports = sourceFile.getImportDeclarations();
|
|
675
|
+
const pgCoreImport = imports.find((imp) => {
|
|
676
|
+
const moduleSpec = imp.getModuleSpecifierValue();
|
|
677
|
+
return moduleSpec === "drizzle-orm/pg-core";
|
|
678
|
+
});
|
|
679
|
+
if (!pgCoreImport) {
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
const namedImports = pgCoreImport.getNamedImports();
|
|
683
|
+
const currentImports = namedImports.map((ni) => ni.getName());
|
|
684
|
+
const toRemove = [];
|
|
685
|
+
const toAdd = [];
|
|
686
|
+
for (const identifier of REMOVE_IMPORTS) {
|
|
687
|
+
if (currentImports.includes(identifier)) {
|
|
688
|
+
toRemove.push(identifier);
|
|
689
|
+
stats.removedImports.push(identifier);
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
if (currentImports.includes("timestamp")) {
|
|
693
|
+
const timestampUsed = /timestamp\s*\(/.test(fullText);
|
|
694
|
+
if (!timestampUsed) {
|
|
695
|
+
toRemove.push("timestamp");
|
|
696
|
+
stats.removedImports.push("timestamp");
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
for (const factory of PG_FACTORIES2) {
|
|
700
|
+
if (!currentImports.includes(factory)) {
|
|
701
|
+
const pattern = new RegExp(`${factory}\\s*\\(`);
|
|
702
|
+
if (pattern.test(fullText)) {
|
|
703
|
+
toAdd.push(factory);
|
|
704
|
+
stats.addedImports.push(factory);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
for (const identifier of toRemove) {
|
|
709
|
+
const freshNamedImports = pgCoreImport.getNamedImports();
|
|
710
|
+
const namedImport = freshNamedImports.find((ni) => ni.getName() === identifier);
|
|
711
|
+
if (namedImport) {
|
|
712
|
+
namedImport.remove();
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
for (const identifier of toAdd) {
|
|
716
|
+
pgCoreImport.addNamedImport(identifier);
|
|
717
|
+
}
|
|
718
|
+
if (fullText.includes("sql`CURRENT_TIMESTAMP`")) {
|
|
719
|
+
const drizzleOrmImport = imports.find((imp) => {
|
|
720
|
+
const moduleSpec = imp.getModuleSpecifierValue();
|
|
721
|
+
return moduleSpec === "drizzle-orm";
|
|
722
|
+
});
|
|
723
|
+
if (!drizzleOrmImport) {
|
|
724
|
+
sourceFile.addImportDeclaration({
|
|
725
|
+
moduleSpecifier: "drizzle-orm",
|
|
726
|
+
namedImports: ["sql"]
|
|
727
|
+
});
|
|
728
|
+
stats.addedImports.push("sql");
|
|
729
|
+
} else {
|
|
730
|
+
const hasSql = drizzleOrmImport.getNamedImports().some((ni) => ni.getName() === "sql");
|
|
731
|
+
if (!hasSql) {
|
|
732
|
+
drizzleOrmImport.addNamedImport("sql");
|
|
733
|
+
stats.addedImports.push("sql");
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
}
|
|
353
737
|
}
|
|
354
|
-
|
|
355
|
-
|
|
738
|
+
};
|
|
739
|
+
|
|
740
|
+
// src/commands/db/gen-dbschema/transforms/ast/index.ts
|
|
741
|
+
var defaultTransforms = [
|
|
742
|
+
patchDefectsTransform,
|
|
743
|
+
// #2 Fix syntax errors first
|
|
744
|
+
removePgSchemaTransform,
|
|
745
|
+
// #3 Remove pgSchema declarations
|
|
746
|
+
convertSchemaCallsTransform,
|
|
747
|
+
// #4 Convert schema.xxx() to pgXxx()
|
|
748
|
+
renameIdentifiersTransform,
|
|
749
|
+
// #5+#6 Rename identifiers (auto-updates refs)
|
|
750
|
+
replaceUnknownTransform,
|
|
751
|
+
// #7 Replace unknown types
|
|
752
|
+
replaceTimestampTransform,
|
|
753
|
+
// #8 Replace timestamp
|
|
754
|
+
replaceDefaultNowTransform,
|
|
755
|
+
// #9 Replace .defaultNow()
|
|
756
|
+
removeSystemFieldsTransform,
|
|
757
|
+
// #10 Remove conflicting system fields
|
|
758
|
+
tweakImportsTransform
|
|
759
|
+
// #12 Adjust imports
|
|
760
|
+
];
|
|
761
|
+
|
|
762
|
+
// src/commands/db/gen-dbschema/transforms/text/patch-defects.ts
|
|
763
|
+
function patchDefects(source) {
|
|
764
|
+
let fixed = 0;
|
|
765
|
+
const renamedQuotedExports = [];
|
|
766
|
+
let text = source;
|
|
767
|
+
text = text.replace(/\.default\('\)/g, () => {
|
|
768
|
+
fixed += 1;
|
|
769
|
+
return `.default('')`;
|
|
770
|
+
});
|
|
771
|
+
const quotedExportPattern = /export const\s+"([^"]+)"\s*=/g;
|
|
772
|
+
text = text.replace(quotedExportPattern, (match, quotedName) => {
|
|
773
|
+
const sanitized = sanitizeIdentifier(quotedName);
|
|
774
|
+
renamedQuotedExports.push({ from: quotedName, to: sanitized });
|
|
775
|
+
fixed += 1;
|
|
776
|
+
return `export const ${sanitized} =`;
|
|
777
|
+
});
|
|
778
|
+
for (const { from, to } of renamedQuotedExports) {
|
|
779
|
+
const escaped = from.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
780
|
+
const callPattern = new RegExp(`"${escaped}"\\s*\\(`, "g");
|
|
781
|
+
text = text.replace(callPattern, `${to}(`);
|
|
782
|
+
const dotPattern = new RegExp(`"${escaped}"\\s*\\.`, "g");
|
|
783
|
+
text = text.replace(dotPattern, `${to}.`);
|
|
356
784
|
}
|
|
357
|
-
|
|
358
|
-
|
|
785
|
+
return { text, fixed, renamedQuotedExports };
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
// src/commands/db/gen-dbschema/transforms/text/header.ts
|
|
789
|
+
var ESLINT_DISABLE = "/* eslint-disable */";
|
|
790
|
+
var HEADER_COMMENT = "/** auto generated, do not edit */";
|
|
791
|
+
var FULL_HEADER = `${ESLINT_DISABLE}
|
|
792
|
+
${HEADER_COMMENT}`;
|
|
793
|
+
function ensureHeader(source) {
|
|
794
|
+
let trimmed = source;
|
|
795
|
+
const headerPatterns = [
|
|
796
|
+
/^\/\*\s*eslint-disable\s*\*\/\s*\n?/,
|
|
797
|
+
/^\/\*\*\s*auto generated[^*]*\*\/\s*\n?/
|
|
798
|
+
];
|
|
799
|
+
for (const pattern of headerPatterns) {
|
|
800
|
+
while (pattern.test(trimmed)) {
|
|
801
|
+
trimmed = trimmed.replace(pattern, "");
|
|
802
|
+
}
|
|
359
803
|
}
|
|
360
|
-
|
|
361
|
-
|
|
804
|
+
trimmed = trimmed.trimStart();
|
|
805
|
+
return `${FULL_HEADER}
|
|
806
|
+
${trimmed}`;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
// src/commands/db/gen-dbschema/transforms/text/system-comments.ts
|
|
810
|
+
var SYSTEM_FIELD_COMMENTS = {
|
|
811
|
+
_created_at: "Creation time",
|
|
812
|
+
_created_by: "Creator",
|
|
813
|
+
_updated_at: "Update time",
|
|
814
|
+
_updated_by: "Updater"
|
|
815
|
+
};
|
|
816
|
+
function addSystemFieldComments(source) {
|
|
817
|
+
const lines = source.split("\n");
|
|
818
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
819
|
+
const line = lines[i];
|
|
820
|
+
const entry = Object.entries(SYSTEM_FIELD_COMMENTS).find(
|
|
821
|
+
([key]) => line.includes(`"${key}"`) || line.includes(`'${key}'`)
|
|
822
|
+
);
|
|
823
|
+
if (!entry) {
|
|
824
|
+
continue;
|
|
825
|
+
}
|
|
826
|
+
const [, description] = entry;
|
|
827
|
+
const previousLine = lines[i - 1]?.trim() ?? "";
|
|
828
|
+
if (previousLine.startsWith("//") && previousLine.includes("System field")) {
|
|
829
|
+
continue;
|
|
830
|
+
}
|
|
831
|
+
const indentMatch = line.match(/^\s*/);
|
|
832
|
+
const indent = indentMatch ? indentMatch[0] : "";
|
|
833
|
+
const comment = `${indent}// System field: ${description} (auto-filled, do not modify)`;
|
|
834
|
+
lines.splice(i, 0, comment);
|
|
835
|
+
i += 1;
|
|
362
836
|
}
|
|
363
|
-
|
|
364
|
-
const replacement = `import { ${unique.join(", ")} } from "drizzle-orm/pg-core"`;
|
|
365
|
-
return source.replace(importRegex, replacement);
|
|
837
|
+
return lines.join("\n");
|
|
366
838
|
}
|
|
839
|
+
|
|
840
|
+
// src/commands/db/gen-dbschema/transforms/text/inline-types.ts
|
|
841
|
+
import fs from "fs";
|
|
842
|
+
import { fileURLToPath } from "url";
|
|
367
843
|
function inlineCustomTypes(source) {
|
|
368
|
-
|
|
844
|
+
let text = source.replace(/import \{[^}]*\} from ["']\.\/types["'];?\n*/g, "");
|
|
369
845
|
const templatePath = resolveTemplateTypesPath();
|
|
370
846
|
if (!templatePath) {
|
|
371
|
-
console.warn("[
|
|
847
|
+
console.warn("[text/inline-types] Template types file not found.");
|
|
372
848
|
return text;
|
|
373
849
|
}
|
|
374
|
-
|
|
850
|
+
const templateContent = fs.readFileSync(templatePath, "utf8");
|
|
851
|
+
return inlineFromTemplate(text, templateContent);
|
|
375
852
|
}
|
|
376
|
-
function
|
|
853
|
+
function inlineFromTemplate(source, templateContent) {
|
|
377
854
|
const typeDefinitions = templateContent.replace(/^import\s+.*;\r?\n*/gm, "").trim();
|
|
855
|
+
let text = source;
|
|
378
856
|
const needsSql = typeDefinitions.includes("sql`") && !text.includes("from 'drizzle-orm'") && !text.includes('from "drizzle-orm"');
|
|
379
857
|
const needsCustomType = typeDefinitions.includes("customType<") && !text.includes("customType");
|
|
380
858
|
if (needsCustomType) {
|
|
381
859
|
text = ensureImportIdentifier(text, "drizzle-orm/pg-core", "customType");
|
|
382
860
|
}
|
|
383
|
-
if (needsSql
|
|
861
|
+
if (needsSql) {
|
|
384
862
|
const importMatch = text.match(/^import [\s\S]*?from ["']drizzle-orm\/pg-core["'];?\n/m);
|
|
385
863
|
if (importMatch) {
|
|
386
864
|
const insertPoint = text.indexOf(importMatch[0]) + importMatch[0].length;
|
|
@@ -421,8 +899,8 @@ function ensureImportIdentifier(source, packageName, identifier) {
|
|
|
421
899
|
}
|
|
422
900
|
function resolveTemplateTypesPath() {
|
|
423
901
|
const candidates = [
|
|
424
|
-
new URL("
|
|
425
|
-
new URL("
|
|
902
|
+
new URL("../../template/types.ts", import.meta.url),
|
|
903
|
+
new URL("../template/types.ts", import.meta.url)
|
|
426
904
|
];
|
|
427
905
|
for (const url of candidates) {
|
|
428
906
|
const p = fileURLToPath(url);
|
|
@@ -433,131 +911,9 @@ function resolveTemplateTypesPath() {
|
|
|
433
911
|
return void 0;
|
|
434
912
|
}
|
|
435
913
|
|
|
436
|
-
// src/commands/db/gen-dbschema/
|
|
437
|
-
function addSystemFieldComments(source) {
|
|
438
|
-
const commentMap = {
|
|
439
|
-
"_created_at": "Creation time",
|
|
440
|
-
"_created_by": "Creator",
|
|
441
|
-
"_updated_at": "Update time",
|
|
442
|
-
"_updated_by": "Updater"
|
|
443
|
-
};
|
|
444
|
-
const lines = source.split("\n");
|
|
445
|
-
for (let i = 0; i < lines.length; i += 1) {
|
|
446
|
-
const line = lines[i];
|
|
447
|
-
const entry = Object.entries(commentMap).find(([key]) => line.includes(`"${key}"`));
|
|
448
|
-
if (!entry) {
|
|
449
|
-
continue;
|
|
450
|
-
}
|
|
451
|
-
const [, description] = entry;
|
|
452
|
-
const previousLine = lines[i - 1]?.trim() ?? "";
|
|
453
|
-
if (previousLine.startsWith("//") && previousLine.includes("System field")) {
|
|
454
|
-
continue;
|
|
455
|
-
}
|
|
456
|
-
const indentMatch = line.match(/^\s*/);
|
|
457
|
-
const indent = indentMatch ? indentMatch[0] : "";
|
|
458
|
-
const comment = `${indent}// System field: ${description} (auto-filled, do not modify)`;
|
|
459
|
-
lines.splice(i, 0, comment);
|
|
460
|
-
i += 1;
|
|
461
|
-
}
|
|
462
|
-
return lines.join("\n");
|
|
463
|
-
}
|
|
464
|
-
function removeConflictingSystemFields(source) {
|
|
465
|
-
const systemFieldMap = {
|
|
466
|
-
"_created_at": "created_at",
|
|
467
|
-
"_created_by": "created_by",
|
|
468
|
-
"_updated_at": "updated_at",
|
|
469
|
-
"_updated_by": "updated_by"
|
|
470
|
-
};
|
|
471
|
-
const lines = source.split("\n");
|
|
472
|
-
const result = [];
|
|
473
|
-
let inTable = false;
|
|
474
|
-
let tableStartLine = -1;
|
|
475
|
-
const tableBusinessFields = /* @__PURE__ */ new Set();
|
|
476
|
-
let bracketDepth = 0;
|
|
477
|
-
for (let i = 0; i < lines.length; i += 1) {
|
|
478
|
-
const line = lines[i];
|
|
479
|
-
if (!inTable && /=\s*(pgTable|pgView|pgMaterializedView)\s*\(/.test(line)) {
|
|
480
|
-
inTable = true;
|
|
481
|
-
tableStartLine = result.length;
|
|
482
|
-
tableBusinessFields.clear();
|
|
483
|
-
bracketDepth = 0;
|
|
484
|
-
}
|
|
485
|
-
if (inTable) {
|
|
486
|
-
for (const char of line) {
|
|
487
|
-
if (char === "{") bracketDepth++;
|
|
488
|
-
if (char === "}") bracketDepth--;
|
|
489
|
-
}
|
|
490
|
-
for (const businessField of Object.values(systemFieldMap)) {
|
|
491
|
-
if (line.includes(`"${businessField}"`) || line.includes(`'${businessField}'`)) {
|
|
492
|
-
tableBusinessFields.add(businessField);
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
if (bracketDepth === 0 && line.includes(");")) {
|
|
496
|
-
inTable = false;
|
|
497
|
-
const tableEndLine = result.length;
|
|
498
|
-
for (let j = tableStartLine; j <= tableEndLine; j++) {
|
|
499
|
-
const tableLine = result[j] || "";
|
|
500
|
-
let shouldRemove = false;
|
|
501
|
-
for (const [systemField, businessField] of Object.entries(systemFieldMap)) {
|
|
502
|
-
if (tableBusinessFields.has(businessField)) {
|
|
503
|
-
if (tableLine.includes(`"${systemField}"`) || tableLine.includes(`'${systemField}'`)) {
|
|
504
|
-
shouldRemove = true;
|
|
505
|
-
if (j > 0 && result[j - 1]?.includes("// System field:")) {
|
|
506
|
-
result[j - 1] = null;
|
|
507
|
-
}
|
|
508
|
-
break;
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
if (shouldRemove) {
|
|
513
|
-
result[j] = null;
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
result.push(line);
|
|
519
|
-
}
|
|
520
|
-
return result.filter((line) => line !== null).join("\n");
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
// src/commands/db/gen-dbschema/helper/patch-helper.ts
|
|
524
|
-
function patchDrizzleKitDefects(source) {
|
|
525
|
-
let fixed = 0;
|
|
526
|
-
const text = source.replace(/\.default\('\)/g, () => {
|
|
527
|
-
fixed += 1;
|
|
528
|
-
return `.default('')`;
|
|
529
|
-
});
|
|
530
|
-
return { text, fixed };
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
// src/commands/db/gen-dbschema/helper/timestamp-replacement.ts
|
|
534
|
-
function replaceTimestampWithCustomTypes(source) {
|
|
535
|
-
let replaced = 0;
|
|
536
|
-
const pattern = /timestamp\((['"])(.*?)\1,\s*(\{[^}]*\})\)/g;
|
|
537
|
-
const text = source.replace(pattern, (match, quote, fieldName, options) => {
|
|
538
|
-
const hasWithTimezone = /withTimezone:\s*true/.test(options);
|
|
539
|
-
const hasModeString = /mode:\s*['"]string['"]/.test(options);
|
|
540
|
-
if (hasWithTimezone && hasModeString) {
|
|
541
|
-
replaced += 1;
|
|
542
|
-
return `customTimestamptz(${quote}${fieldName}${quote})`;
|
|
543
|
-
}
|
|
544
|
-
return match;
|
|
545
|
-
});
|
|
546
|
-
return { text, replaced };
|
|
547
|
-
}
|
|
548
|
-
function replaceDefaultNowWithSql(source) {
|
|
549
|
-
let replaced = 0;
|
|
550
|
-
const pattern = /\.defaultNow\(\)/g;
|
|
551
|
-
const text = source.replace(pattern, () => {
|
|
552
|
-
replaced += 1;
|
|
553
|
-
return ".default(sql`CURRENT_TIMESTAMP`)";
|
|
554
|
-
});
|
|
555
|
-
return { text, replaced };
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
// src/commands/db/gen-dbschema/helper/appendTableAliases.ts
|
|
914
|
+
// src/commands/db/gen-dbschema/transforms/text/table-aliases.ts
|
|
559
915
|
var TABLE_ALIAS_MARKER = "// table aliases";
|
|
560
|
-
function
|
|
916
|
+
function generateTableAliases(source) {
|
|
561
917
|
const markerIndex = source.indexOf(`
|
|
562
918
|
${TABLE_ALIAS_MARKER}`);
|
|
563
919
|
const base = markerIndex === -1 ? source : source.slice(0, markerIndex);
|
|
@@ -579,66 +935,100 @@ ${aliasLines}
|
|
|
579
935
|
`;
|
|
580
936
|
}
|
|
581
937
|
|
|
938
|
+
// src/commands/db/gen-dbschema/transforms/text/format.ts
|
|
939
|
+
function formatSource(source) {
|
|
940
|
+
let text = source;
|
|
941
|
+
text = text.replace(/\r\n/g, "\n");
|
|
942
|
+
text = text.replace(/\n{3,}/g, "\n\n");
|
|
943
|
+
if (!text.endsWith("\n")) {
|
|
944
|
+
text += "\n";
|
|
945
|
+
}
|
|
946
|
+
return text;
|
|
947
|
+
}
|
|
948
|
+
|
|
582
949
|
// src/commands/db/gen-dbschema/postprocess.ts
|
|
950
|
+
function postprocessSchema(rawSource) {
|
|
951
|
+
const patchResult = patchDefects(rawSource);
|
|
952
|
+
let source = patchResult.text;
|
|
953
|
+
const { sourceFile } = parseSource(source);
|
|
954
|
+
const astStats = applyTransforms(sourceFile, defaultTransforms);
|
|
955
|
+
formatSourceFile(sourceFile);
|
|
956
|
+
source = printSourceFile(sourceFile);
|
|
957
|
+
source = ensureHeader(source);
|
|
958
|
+
source = addSystemFieldComments(source);
|
|
959
|
+
source = inlineCustomTypes(source);
|
|
960
|
+
source = generateTableAliases(source);
|
|
961
|
+
source = formatSource(source);
|
|
962
|
+
return {
|
|
963
|
+
source,
|
|
964
|
+
astStats,
|
|
965
|
+
patchedDefects: patchResult.fixed
|
|
966
|
+
};
|
|
967
|
+
}
|
|
968
|
+
function logStats(result, prefix = "[postprocess]") {
|
|
969
|
+
const { astStats, patchedDefects } = result;
|
|
970
|
+
if (patchedDefects > 0) {
|
|
971
|
+
console.info(`${prefix} Patched ${patchedDefects} syntax defects`);
|
|
972
|
+
}
|
|
973
|
+
if (astStats.removedPgSchemas > 0) {
|
|
974
|
+
console.info(`${prefix} Removed ${astStats.removedPgSchemas} pgSchema declarations`);
|
|
975
|
+
}
|
|
976
|
+
if (astStats.convertedSchemaCalls > 0) {
|
|
977
|
+
console.info(`${prefix} Converted ${astStats.convertedSchemaCalls} schema.xxx() calls`);
|
|
978
|
+
}
|
|
979
|
+
if (astStats.renamedIdentifiers.length > 0) {
|
|
980
|
+
console.info(`${prefix} Renamed ${astStats.renamedIdentifiers.length} identifiers:`);
|
|
981
|
+
for (const { from, to } of astStats.renamedIdentifiers) {
|
|
982
|
+
console.info(`${prefix} ${from} -> ${to}`);
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
if (astStats.replacedUnknown > 0) {
|
|
986
|
+
console.info(`${prefix} Replaced ${astStats.replacedUnknown} unknown types with custom types`);
|
|
987
|
+
}
|
|
988
|
+
if (astStats.fallbackToText > 0) {
|
|
989
|
+
console.info(`${prefix} Replaced ${astStats.fallbackToText} unknown types with text (fallback)`);
|
|
990
|
+
}
|
|
991
|
+
if (astStats.unmatchedUnknown.length > 0) {
|
|
992
|
+
console.warn(`${prefix} Unmatched unknown types:`);
|
|
993
|
+
for (const line of astStats.unmatchedUnknown) {
|
|
994
|
+
console.warn(`${prefix} ${line}`);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
if (astStats.replacedTimestamp > 0) {
|
|
998
|
+
console.info(`${prefix} Replaced ${astStats.replacedTimestamp} timestamp with customTimestamptz`);
|
|
999
|
+
}
|
|
1000
|
+
if (astStats.replacedDefaultNow > 0) {
|
|
1001
|
+
console.info(`${prefix} Replaced ${astStats.replacedDefaultNow} .defaultNow() calls`);
|
|
1002
|
+
}
|
|
1003
|
+
if (astStats.removedSystemFields > 0) {
|
|
1004
|
+
console.info(`${prefix} Removed ${astStats.removedSystemFields} conflicting system fields`);
|
|
1005
|
+
}
|
|
1006
|
+
if (astStats.addedImports.length > 0) {
|
|
1007
|
+
console.info(`${prefix} Added imports: ${astStats.addedImports.join(", ")}`);
|
|
1008
|
+
}
|
|
1009
|
+
if (astStats.removedImports.length > 0) {
|
|
1010
|
+
console.info(`${prefix} Removed imports: ${astStats.removedImports.join(", ")}`);
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
// src/commands/db/gen-dbschema/index.ts
|
|
583
1015
|
function postprocessDrizzleSchema(targetPath) {
|
|
584
1016
|
const resolvedPath = path.resolve(targetPath);
|
|
585
|
-
if (!
|
|
1017
|
+
if (!fs3.existsSync(resolvedPath)) {
|
|
586
1018
|
console.warn(`[postprocess-drizzle-schema] File not found: ${resolvedPath}`);
|
|
587
1019
|
return void 0;
|
|
588
1020
|
}
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
text = removePgSchemaDeclarations(text);
|
|
594
|
-
const tableConversion = convertSchemaTableInvocations(text);
|
|
595
|
-
text = tableConversion.text;
|
|
596
|
-
const renameResult = renamePgTableConstants(text);
|
|
597
|
-
text = renameResult.text;
|
|
598
|
-
text = updateTableReferenceIdentifiers(text, renameResult.renames);
|
|
599
|
-
const replacement = replaceUnknownColumns(text);
|
|
600
|
-
text = replacement.text;
|
|
601
|
-
const timestampReplacement = replaceTimestampWithCustomTypes(text);
|
|
602
|
-
text = timestampReplacement.text;
|
|
603
|
-
const defaultNowReplacement = replaceDefaultNowWithSql(text);
|
|
604
|
-
text = defaultNowReplacement.text;
|
|
605
|
-
text = removeConflictingSystemFields(text);
|
|
606
|
-
text = addSystemFieldComments(text);
|
|
607
|
-
text = tweakImports(text);
|
|
608
|
-
text = inlineCustomTypes(text);
|
|
609
|
-
text = appendTableAliases(text);
|
|
610
|
-
text = text.replace(/\r?\n/g, "\n");
|
|
611
|
-
text = collapseExtraBlankLines(text);
|
|
612
|
-
fs2.writeFileSync(resolvedPath, text, "utf8");
|
|
613
|
-
if (patchResult.fixed > 0) {
|
|
614
|
-
console.info(`[postprocess-drizzle-schema] Patched ${patchResult.fixed} drizzle-kit defects (.default(') -> .default(''))`);
|
|
615
|
-
}
|
|
616
|
-
if (replacement.replaced > 0) {
|
|
617
|
-
console.info(`[postprocess-drizzle-schema] Replaced ${replacement.replaced} unknown columns with custom types`);
|
|
618
|
-
}
|
|
619
|
-
if (replacement.fallbackToText > 0) {
|
|
620
|
-
console.info(`[postprocess-drizzle-schema] Replaced ${replacement.fallbackToText} unknown columns with text (fallback)`);
|
|
621
|
-
}
|
|
622
|
-
if (replacement.unmatched.length > 0) {
|
|
623
|
-
console.warn("[postprocess-drizzle-schema] Unmatched unknown columns:", replacement.unmatched.length);
|
|
624
|
-
replacement.unmatched.forEach((line) => console.warn(` ${line}`));
|
|
625
|
-
}
|
|
626
|
-
if (tableConversion.converted > 0) {
|
|
627
|
-
console.info(`[postprocess-drizzle-schema] Converted ${tableConversion.converted} schema.table invocations to pgTable`);
|
|
628
|
-
}
|
|
629
|
-
if (timestampReplacement.replaced > 0) {
|
|
630
|
-
console.info(`[postprocess-drizzle-schema] Replaced ${timestampReplacement.replaced} timestamp fields with customTimestamptz`);
|
|
631
|
-
}
|
|
632
|
-
if (defaultNowReplacement.replaced > 0) {
|
|
633
|
-
console.info(`[postprocess-drizzle-schema] Replaced ${defaultNowReplacement.replaced} .defaultNow() with .default(sql\`CURRENT_TIMESTAMP\`)`);
|
|
634
|
-
}
|
|
1021
|
+
const rawSource = fs3.readFileSync(resolvedPath, "utf8");
|
|
1022
|
+
const result = postprocessSchema(rawSource);
|
|
1023
|
+
fs3.writeFileSync(resolvedPath, result.source, "utf8");
|
|
1024
|
+
logStats(result, "[postprocess-drizzle-schema]");
|
|
635
1025
|
return {
|
|
636
|
-
replacedUnknown:
|
|
637
|
-
fallbackToText:
|
|
638
|
-
unmatchedUnknown:
|
|
639
|
-
patchedDefects:
|
|
640
|
-
replacedTimestamps:
|
|
641
|
-
replacedDefaultNow:
|
|
1026
|
+
replacedUnknown: result.astStats.replacedUnknown,
|
|
1027
|
+
fallbackToText: result.astStats.fallbackToText,
|
|
1028
|
+
unmatchedUnknown: result.astStats.unmatchedUnknown,
|
|
1029
|
+
patchedDefects: result.patchedDefects,
|
|
1030
|
+
replacedTimestamps: result.astStats.replacedTimestamp,
|
|
1031
|
+
replacedDefaultNow: result.astStats.replacedDefaultNow
|
|
642
1032
|
};
|
|
643
1033
|
}
|
|
644
1034
|
|
|
@@ -1060,10 +1450,10 @@ export class ${className}Module {}
|
|
|
1060
1450
|
}
|
|
1061
1451
|
|
|
1062
1452
|
// src/commands/db/gen-nest-resource/schema-parser.ts
|
|
1063
|
-
import { Project, Node } from "ts-morph";
|
|
1453
|
+
import { Project as Project2, Node as Node9 } from "ts-morph";
|
|
1064
1454
|
var DrizzleSchemaParser = class {
|
|
1065
1455
|
constructor(projectOptions) {
|
|
1066
|
-
this.project = new
|
|
1456
|
+
this.project = new Project2(projectOptions);
|
|
1067
1457
|
}
|
|
1068
1458
|
parseSchemaFile(filePath) {
|
|
1069
1459
|
const sourceFile = this.project.addSourceFileAtPath(filePath);
|
|
@@ -1073,7 +1463,7 @@ var DrizzleSchemaParser = class {
|
|
|
1073
1463
|
const declarations = statement.getDeclarations();
|
|
1074
1464
|
for (const declaration of declarations) {
|
|
1075
1465
|
const initializer = declaration.getInitializer();
|
|
1076
|
-
if (initializer &&
|
|
1466
|
+
if (initializer && Node9.isCallExpression(initializer)) {
|
|
1077
1467
|
const expression = initializer.getExpression();
|
|
1078
1468
|
if (expression.getText() === "pgTable") {
|
|
1079
1469
|
const tableInfo = this.parsePgTable(
|
|
@@ -1096,13 +1486,13 @@ var DrizzleSchemaParser = class {
|
|
|
1096
1486
|
}
|
|
1097
1487
|
const tableName = args[0].getText().replace(/['"]/g, "");
|
|
1098
1488
|
const fieldsArg = args[1];
|
|
1099
|
-
if (!
|
|
1489
|
+
if (!Node9.isObjectLiteralExpression(fieldsArg)) {
|
|
1100
1490
|
return null;
|
|
1101
1491
|
}
|
|
1102
1492
|
const fields = [];
|
|
1103
1493
|
const properties = fieldsArg.getProperties();
|
|
1104
1494
|
for (const prop of properties) {
|
|
1105
|
-
if (
|
|
1495
|
+
if (Node9.isPropertyAssignment(prop)) {
|
|
1106
1496
|
const fieldName = prop.getName();
|
|
1107
1497
|
const initializer = prop.getInitializer();
|
|
1108
1498
|
const leadingComments = prop.getLeadingCommentRanges();
|
|
@@ -1110,7 +1500,7 @@ var DrizzleSchemaParser = class {
|
|
|
1110
1500
|
if (leadingComments.length > 0) {
|
|
1111
1501
|
comment = leadingComments.map((c) => c.getText()).join("\n").replace(/\/\//g, "").trim();
|
|
1112
1502
|
}
|
|
1113
|
-
if (initializer &&
|
|
1503
|
+
if (initializer && Node9.isCallExpression(initializer)) {
|
|
1114
1504
|
const fieldInfo = this.parseField(fieldName, initializer, comment);
|
|
1115
1505
|
fields.push(fieldInfo);
|
|
1116
1506
|
}
|
|
@@ -1142,10 +1532,10 @@ var DrizzleSchemaParser = class {
|
|
|
1142
1532
|
parseBaseType(callExpr, fieldInfo) {
|
|
1143
1533
|
let current = callExpr;
|
|
1144
1534
|
let baseCall = null;
|
|
1145
|
-
while (
|
|
1535
|
+
while (Node9.isCallExpression(current)) {
|
|
1146
1536
|
baseCall = current;
|
|
1147
1537
|
const expression2 = current.getExpression();
|
|
1148
|
-
if (
|
|
1538
|
+
if (Node9.isPropertyAccessExpression(expression2)) {
|
|
1149
1539
|
current = expression2.getExpression();
|
|
1150
1540
|
} else {
|
|
1151
1541
|
break;
|
|
@@ -1156,7 +1546,7 @@ var DrizzleSchemaParser = class {
|
|
|
1156
1546
|
}
|
|
1157
1547
|
const expression = baseCall.getExpression();
|
|
1158
1548
|
let typeName = "";
|
|
1159
|
-
if (
|
|
1549
|
+
if (Node9.isPropertyAccessExpression(expression)) {
|
|
1160
1550
|
typeName = expression.getName();
|
|
1161
1551
|
} else {
|
|
1162
1552
|
typeName = expression.getText();
|
|
@@ -1165,25 +1555,25 @@ var DrizzleSchemaParser = class {
|
|
|
1165
1555
|
const args = baseCall.getArguments();
|
|
1166
1556
|
if (args.length > 0) {
|
|
1167
1557
|
const firstArg = args[0];
|
|
1168
|
-
if (
|
|
1558
|
+
if (Node9.isStringLiteral(firstArg)) {
|
|
1169
1559
|
fieldInfo.columnName = firstArg.getLiteralText();
|
|
1170
|
-
} else if (
|
|
1560
|
+
} else if (Node9.isObjectLiteralExpression(firstArg)) {
|
|
1171
1561
|
this.parseTypeConfig(firstArg, fieldInfo);
|
|
1172
|
-
} else if (
|
|
1562
|
+
} else if (Node9.isArrayLiteralExpression(firstArg)) {
|
|
1173
1563
|
fieldInfo.enumValues = firstArg.getElements().map((el) => el.getText().replace(/['"]/g, ""));
|
|
1174
1564
|
}
|
|
1175
1565
|
}
|
|
1176
|
-
if (args.length > 1 &&
|
|
1566
|
+
if (args.length > 1 && Node9.isObjectLiteralExpression(args[1])) {
|
|
1177
1567
|
this.parseTypeConfig(args[1], fieldInfo);
|
|
1178
1568
|
}
|
|
1179
1569
|
}
|
|
1180
1570
|
parseTypeConfig(objLiteral, fieldInfo) {
|
|
1181
|
-
if (!
|
|
1571
|
+
if (!Node9.isObjectLiteralExpression(objLiteral)) {
|
|
1182
1572
|
return;
|
|
1183
1573
|
}
|
|
1184
1574
|
const properties = objLiteral.getProperties();
|
|
1185
1575
|
for (const prop of properties) {
|
|
1186
|
-
if (
|
|
1576
|
+
if (Node9.isPropertyAssignment(prop)) {
|
|
1187
1577
|
const propName = prop.getName();
|
|
1188
1578
|
const value = prop.getInitializer()?.getText();
|
|
1189
1579
|
switch (propName) {
|
|
@@ -1215,9 +1605,9 @@ var DrizzleSchemaParser = class {
|
|
|
1215
1605
|
}
|
|
1216
1606
|
parseCallChain(callExpr, fieldInfo) {
|
|
1217
1607
|
let current = callExpr;
|
|
1218
|
-
while (
|
|
1608
|
+
while (Node9.isCallExpression(current)) {
|
|
1219
1609
|
const expression = current.getExpression();
|
|
1220
|
-
if (
|
|
1610
|
+
if (Node9.isPropertyAccessExpression(expression)) {
|
|
1221
1611
|
const methodName = expression.getName();
|
|
1222
1612
|
const args = current.getArguments();
|
|
1223
1613
|
switch (methodName) {
|
|
@@ -1314,7 +1704,7 @@ var require2 = createRequire(import.meta.url);
|
|
|
1314
1704
|
async function run(options = {}) {
|
|
1315
1705
|
let exitCode = 0;
|
|
1316
1706
|
const envPath2 = path2.resolve(process.cwd(), ".env");
|
|
1317
|
-
if (
|
|
1707
|
+
if (fs4.existsSync(envPath2)) {
|
|
1318
1708
|
loadEnv({ path: envPath2 });
|
|
1319
1709
|
console.log("[gen-db-schema] \u2713 Loaded .env file");
|
|
1320
1710
|
}
|
|
@@ -1334,7 +1724,7 @@ async function run(options = {}) {
|
|
|
1334
1724
|
path2.resolve(__dirname2, "../../config/drizzle.config.js"),
|
|
1335
1725
|
path2.resolve(__dirname2, "../../../dist/config/drizzle.config.js")
|
|
1336
1726
|
];
|
|
1337
|
-
const configPath = configPathCandidates.find((p) =>
|
|
1727
|
+
const configPath = configPathCandidates.find((p) => fs4.existsSync(p));
|
|
1338
1728
|
console.log("[gen-db-schema] Using drizzle config from:", configPath ?? "(not found)");
|
|
1339
1729
|
if (!configPath) {
|
|
1340
1730
|
console.error("[gen-db-schema] Error: drizzle config not found in CLI package");
|
|
@@ -1346,8 +1736,8 @@ async function run(options = {}) {
|
|
|
1346
1736
|
let lastDir = null;
|
|
1347
1737
|
while (currentDir !== lastDir) {
|
|
1348
1738
|
const pkgJsonPath = path2.join(currentDir, "package.json");
|
|
1349
|
-
if (
|
|
1350
|
-
const pkgJsonRaw =
|
|
1739
|
+
if (fs4.existsSync(pkgJsonPath)) {
|
|
1740
|
+
const pkgJsonRaw = fs4.readFileSync(pkgJsonPath, "utf8");
|
|
1351
1741
|
const pkgJson = JSON.parse(pkgJsonRaw);
|
|
1352
1742
|
if (pkgJson.name === "drizzle-kit") {
|
|
1353
1743
|
const binField = pkgJson.bin;
|
|
@@ -1382,7 +1772,7 @@ async function run(options = {}) {
|
|
|
1382
1772
|
throw new Error(`drizzle-kit introspect failed with status ${result.status}`);
|
|
1383
1773
|
}
|
|
1384
1774
|
const generatedSchema = path2.join(OUT_DIR, "schema.ts");
|
|
1385
|
-
if (!
|
|
1775
|
+
if (!fs4.existsSync(generatedSchema)) {
|
|
1386
1776
|
console.error("[gen-db-schema] schema.ts not generated");
|
|
1387
1777
|
throw new Error("drizzle-kit introspect failed to generate schema.ts");
|
|
1388
1778
|
}
|
|
@@ -1391,8 +1781,8 @@ async function run(options = {}) {
|
|
|
1391
1781
|
console.warn("[gen-db-schema] Unmatched custom types detected:", stats.unmatchedUnknown);
|
|
1392
1782
|
}
|
|
1393
1783
|
console.log("[gen-db-schema] \u2713 Postprocessed schema");
|
|
1394
|
-
|
|
1395
|
-
|
|
1784
|
+
fs4.mkdirSync(path2.dirname(SCHEMA_FILE), { recursive: true });
|
|
1785
|
+
fs4.copyFileSync(generatedSchema, SCHEMA_FILE);
|
|
1396
1786
|
console.log(`[gen-db-schema] \u2713 Copied to ${outputPath}`);
|
|
1397
1787
|
try {
|
|
1398
1788
|
if (options.enableNestModuleGenerate) {
|
|
@@ -1413,8 +1803,8 @@ async function run(options = {}) {
|
|
|
1413
1803
|
console.error("[gen-db-schema] Failed:", err instanceof Error ? err.message : String(err));
|
|
1414
1804
|
exitCode = 1;
|
|
1415
1805
|
} finally {
|
|
1416
|
-
if (
|
|
1417
|
-
|
|
1806
|
+
if (fs4.existsSync(OUT_DIR)) {
|
|
1807
|
+
fs4.rmSync(OUT_DIR, { recursive: true, force: true });
|
|
1418
1808
|
}
|
|
1419
1809
|
process.exit(exitCode);
|
|
1420
1810
|
}
|
|
@@ -1433,7 +1823,7 @@ var genDbSchemaCommand = {
|
|
|
1433
1823
|
|
|
1434
1824
|
// src/commands/sync/run.handler.ts
|
|
1435
1825
|
import path4 from "path";
|
|
1436
|
-
import
|
|
1826
|
+
import fs6 from "fs";
|
|
1437
1827
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
1438
1828
|
|
|
1439
1829
|
// src/config/sync.ts
|
|
@@ -1497,14 +1887,14 @@ function genSyncConfig(perms = {}) {
|
|
|
1497
1887
|
}
|
|
1498
1888
|
|
|
1499
1889
|
// src/utils/file-ops.ts
|
|
1500
|
-
import
|
|
1890
|
+
import fs5 from "fs";
|
|
1501
1891
|
import path3 from "path";
|
|
1502
1892
|
function removeLineFromFile(filePath, pattern) {
|
|
1503
|
-
if (!
|
|
1893
|
+
if (!fs5.existsSync(filePath)) {
|
|
1504
1894
|
console.log(`[fullstack-cli] \u25CB ${path3.basename(filePath)} (not found)`);
|
|
1505
1895
|
return false;
|
|
1506
1896
|
}
|
|
1507
|
-
const content =
|
|
1897
|
+
const content = fs5.readFileSync(filePath, "utf-8");
|
|
1508
1898
|
const lines = content.split("\n");
|
|
1509
1899
|
const trimmedPattern = pattern.trim();
|
|
1510
1900
|
const filteredLines = lines.filter((line) => line.trim() !== trimmedPattern);
|
|
@@ -1512,7 +1902,7 @@ function removeLineFromFile(filePath, pattern) {
|
|
|
1512
1902
|
console.log(`[fullstack-cli] \u25CB ${path3.basename(filePath)} (pattern not found: ${pattern})`);
|
|
1513
1903
|
return false;
|
|
1514
1904
|
}
|
|
1515
|
-
|
|
1905
|
+
fs5.writeFileSync(filePath, filteredLines.join("\n"));
|
|
1516
1906
|
console.log(`[fullstack-cli] \u2713 ${path3.basename(filePath)} (removed: ${pattern})`);
|
|
1517
1907
|
return true;
|
|
1518
1908
|
}
|
|
@@ -1528,7 +1918,7 @@ async function run2(options) {
|
|
|
1528
1918
|
process.exit(0);
|
|
1529
1919
|
}
|
|
1530
1920
|
const userPackageJson = path4.join(userProjectRoot, "package.json");
|
|
1531
|
-
if (!
|
|
1921
|
+
if (!fs6.existsSync(userPackageJson)) {
|
|
1532
1922
|
console.log("[fullstack-cli] Skip syncing (not a valid npm project)");
|
|
1533
1923
|
process.exit(0);
|
|
1534
1924
|
}
|
|
@@ -1574,7 +1964,7 @@ async function syncRule(rule, pluginRoot, userProjectRoot) {
|
|
|
1574
1964
|
}
|
|
1575
1965
|
const srcPath = path4.join(pluginRoot, rule.from);
|
|
1576
1966
|
const destPath = path4.join(userProjectRoot, rule.to);
|
|
1577
|
-
if (!
|
|
1967
|
+
if (!fs6.existsSync(srcPath)) {
|
|
1578
1968
|
console.warn(`[fullstack-cli] Source not found: ${rule.from}`);
|
|
1579
1969
|
return;
|
|
1580
1970
|
}
|
|
@@ -1592,31 +1982,31 @@ async function syncRule(rule, pluginRoot, userProjectRoot) {
|
|
|
1592
1982
|
}
|
|
1593
1983
|
function syncFile(src, dest, overwrite = true) {
|
|
1594
1984
|
const destDir = path4.dirname(dest);
|
|
1595
|
-
if (!
|
|
1596
|
-
|
|
1985
|
+
if (!fs6.existsSync(destDir)) {
|
|
1986
|
+
fs6.mkdirSync(destDir, { recursive: true });
|
|
1597
1987
|
}
|
|
1598
|
-
if (
|
|
1988
|
+
if (fs6.existsSync(dest) && !overwrite) {
|
|
1599
1989
|
console.log(`[fullstack-cli] \u25CB ${path4.basename(dest)} (skipped, already exists)`);
|
|
1600
1990
|
return;
|
|
1601
1991
|
}
|
|
1602
|
-
|
|
1992
|
+
fs6.copyFileSync(src, dest);
|
|
1603
1993
|
console.log(`[fullstack-cli] \u2713 ${path4.basename(dest)}`);
|
|
1604
1994
|
}
|
|
1605
1995
|
function syncDirectory(src, dest, overwrite = true) {
|
|
1606
|
-
if (!
|
|
1607
|
-
|
|
1996
|
+
if (!fs6.existsSync(dest)) {
|
|
1997
|
+
fs6.mkdirSync(dest, { recursive: true });
|
|
1608
1998
|
}
|
|
1609
|
-
const files =
|
|
1999
|
+
const files = fs6.readdirSync(src);
|
|
1610
2000
|
let count = 0;
|
|
1611
2001
|
files.forEach((file) => {
|
|
1612
2002
|
const srcFile = path4.join(src, file);
|
|
1613
2003
|
const destFile = path4.join(dest, file);
|
|
1614
|
-
const stats =
|
|
2004
|
+
const stats = fs6.statSync(srcFile);
|
|
1615
2005
|
if (stats.isDirectory()) {
|
|
1616
2006
|
syncDirectory(srcFile, destFile, overwrite);
|
|
1617
2007
|
} else {
|
|
1618
|
-
if (overwrite || !
|
|
1619
|
-
|
|
2008
|
+
if (overwrite || !fs6.existsSync(destFile)) {
|
|
2009
|
+
fs6.copyFileSync(srcFile, destFile);
|
|
1620
2010
|
console.log(`[fullstack-cli] \u2713 ${path4.relative(dest, destFile)}`);
|
|
1621
2011
|
count++;
|
|
1622
2012
|
}
|
|
@@ -1627,28 +2017,28 @@ function syncDirectory(src, dest, overwrite = true) {
|
|
|
1627
2017
|
}
|
|
1628
2018
|
}
|
|
1629
2019
|
function appendToFile(src, dest) {
|
|
1630
|
-
const content =
|
|
2020
|
+
const content = fs6.readFileSync(src, "utf-8");
|
|
1631
2021
|
let existingContent = "";
|
|
1632
|
-
if (
|
|
1633
|
-
existingContent =
|
|
2022
|
+
if (fs6.existsSync(dest)) {
|
|
2023
|
+
existingContent = fs6.readFileSync(dest, "utf-8");
|
|
1634
2024
|
}
|
|
1635
2025
|
if (existingContent.includes(content.trim())) {
|
|
1636
2026
|
console.log(`[fullstack-cli] \u25CB ${path4.basename(dest)} (already contains content)`);
|
|
1637
2027
|
return;
|
|
1638
2028
|
}
|
|
1639
|
-
|
|
2029
|
+
fs6.appendFileSync(dest, content);
|
|
1640
2030
|
console.log(`[fullstack-cli] \u2713 ${path4.basename(dest)} (appended)`);
|
|
1641
2031
|
}
|
|
1642
2032
|
function setPermissions(permissions, projectRoot) {
|
|
1643
2033
|
for (const [pattern, mode] of Object.entries(permissions)) {
|
|
1644
2034
|
if (pattern === "**/*.sh") {
|
|
1645
2035
|
const scriptsDir = path4.join(projectRoot, "scripts");
|
|
1646
|
-
if (
|
|
1647
|
-
const files =
|
|
2036
|
+
if (fs6.existsSync(scriptsDir)) {
|
|
2037
|
+
const files = fs6.readdirSync(scriptsDir);
|
|
1648
2038
|
files.forEach((file) => {
|
|
1649
2039
|
if (file.endsWith(".sh")) {
|
|
1650
2040
|
const filePath = path4.join(scriptsDir, file);
|
|
1651
|
-
|
|
2041
|
+
fs6.chmodSync(filePath, mode);
|
|
1652
2042
|
}
|
|
1653
2043
|
});
|
|
1654
2044
|
}
|
|
@@ -1656,16 +2046,16 @@ function setPermissions(permissions, projectRoot) {
|
|
|
1656
2046
|
}
|
|
1657
2047
|
}
|
|
1658
2048
|
function deleteFile(filePath) {
|
|
1659
|
-
if (
|
|
1660
|
-
|
|
2049
|
+
if (fs6.existsSync(filePath)) {
|
|
2050
|
+
fs6.unlinkSync(filePath);
|
|
1661
2051
|
console.log(`[fullstack-cli] \u2713 ${path4.basename(filePath)} (deleted)`);
|
|
1662
2052
|
} else {
|
|
1663
2053
|
console.log(`[fullstack-cli] \u25CB ${path4.basename(filePath)} (not found)`);
|
|
1664
2054
|
}
|
|
1665
2055
|
}
|
|
1666
2056
|
function deleteDirectory(dirPath) {
|
|
1667
|
-
if (
|
|
1668
|
-
|
|
2057
|
+
if (fs6.existsSync(dirPath)) {
|
|
2058
|
+
fs6.rmSync(dirPath, { recursive: true });
|
|
1669
2059
|
console.log(`[fullstack-cli] \u2713 ${path4.basename(dirPath)} (deleted)`);
|
|
1670
2060
|
} else {
|
|
1671
2061
|
console.log(`[fullstack-cli] \u25CB ${path4.basename(dirPath)} (not found)`);
|
|
@@ -1684,7 +2074,7 @@ var syncCommand = {
|
|
|
1684
2074
|
};
|
|
1685
2075
|
|
|
1686
2076
|
// src/commands/action-plugin/utils.ts
|
|
1687
|
-
import
|
|
2077
|
+
import fs7 from "fs";
|
|
1688
2078
|
import path5 from "path";
|
|
1689
2079
|
import { spawnSync as spawnSync2, execSync } from "child_process";
|
|
1690
2080
|
function parsePluginName(input) {
|
|
@@ -1710,11 +2100,11 @@ function getPluginPath(pluginName) {
|
|
|
1710
2100
|
}
|
|
1711
2101
|
function readPackageJson() {
|
|
1712
2102
|
const pkgPath = getPackageJsonPath();
|
|
1713
|
-
if (!
|
|
2103
|
+
if (!fs7.existsSync(pkgPath)) {
|
|
1714
2104
|
throw new Error("package.json not found in current directory");
|
|
1715
2105
|
}
|
|
1716
2106
|
try {
|
|
1717
|
-
const content =
|
|
2107
|
+
const content = fs7.readFileSync(pkgPath, "utf-8");
|
|
1718
2108
|
return JSON.parse(content);
|
|
1719
2109
|
} catch {
|
|
1720
2110
|
throw new Error("Failed to parse package.json");
|
|
@@ -1722,7 +2112,7 @@ function readPackageJson() {
|
|
|
1722
2112
|
}
|
|
1723
2113
|
function writePackageJson(pkg2) {
|
|
1724
2114
|
const pkgPath = getPackageJsonPath();
|
|
1725
|
-
|
|
2115
|
+
fs7.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
|
|
1726
2116
|
}
|
|
1727
2117
|
function readActionPlugins() {
|
|
1728
2118
|
const pkg2 = readPackageJson();
|
|
@@ -1756,11 +2146,11 @@ function npmInstall(tgzPath) {
|
|
|
1756
2146
|
}
|
|
1757
2147
|
function getPackageVersion(pluginName) {
|
|
1758
2148
|
const pkgJsonPath = path5.join(getPluginPath(pluginName), "package.json");
|
|
1759
|
-
if (!
|
|
2149
|
+
if (!fs7.existsSync(pkgJsonPath)) {
|
|
1760
2150
|
return null;
|
|
1761
2151
|
}
|
|
1762
2152
|
try {
|
|
1763
|
-
const content =
|
|
2153
|
+
const content = fs7.readFileSync(pkgJsonPath, "utf-8");
|
|
1764
2154
|
const pkg2 = JSON.parse(content);
|
|
1765
2155
|
return pkg2.version || null;
|
|
1766
2156
|
} catch {
|
|
@@ -1769,11 +2159,11 @@ function getPackageVersion(pluginName) {
|
|
|
1769
2159
|
}
|
|
1770
2160
|
function readPluginPackageJson(pluginPath) {
|
|
1771
2161
|
const pkgJsonPath = path5.join(pluginPath, "package.json");
|
|
1772
|
-
if (!
|
|
2162
|
+
if (!fs7.existsSync(pkgJsonPath)) {
|
|
1773
2163
|
return null;
|
|
1774
2164
|
}
|
|
1775
2165
|
try {
|
|
1776
|
-
const content =
|
|
2166
|
+
const content = fs7.readFileSync(pkgJsonPath, "utf-8");
|
|
1777
2167
|
return JSON.parse(content);
|
|
1778
2168
|
} catch {
|
|
1779
2169
|
return null;
|
|
@@ -1783,34 +2173,34 @@ function extractTgzToNodeModules(tgzPath, pluginName) {
|
|
|
1783
2173
|
const nodeModulesPath = path5.join(getProjectRoot(), "node_modules");
|
|
1784
2174
|
const targetDir = path5.join(nodeModulesPath, pluginName);
|
|
1785
2175
|
const scopeDir = path5.dirname(targetDir);
|
|
1786
|
-
if (!
|
|
1787
|
-
|
|
2176
|
+
if (!fs7.existsSync(scopeDir)) {
|
|
2177
|
+
fs7.mkdirSync(scopeDir, { recursive: true });
|
|
1788
2178
|
}
|
|
1789
|
-
if (
|
|
1790
|
-
|
|
2179
|
+
if (fs7.existsSync(targetDir)) {
|
|
2180
|
+
fs7.rmSync(targetDir, { recursive: true });
|
|
1791
2181
|
}
|
|
1792
2182
|
const tempDir = path5.join(nodeModulesPath, ".cache", "fullstack-cli", "extract-temp");
|
|
1793
|
-
if (
|
|
1794
|
-
|
|
2183
|
+
if (fs7.existsSync(tempDir)) {
|
|
2184
|
+
fs7.rmSync(tempDir, { recursive: true });
|
|
1795
2185
|
}
|
|
1796
|
-
|
|
2186
|
+
fs7.mkdirSync(tempDir, { recursive: true });
|
|
1797
2187
|
try {
|
|
1798
2188
|
execSync(`tar -xzf "${tgzPath}" -C "${tempDir}"`, { stdio: "pipe" });
|
|
1799
2189
|
const extractedDir = path5.join(tempDir, "package");
|
|
1800
|
-
if (
|
|
1801
|
-
|
|
2190
|
+
if (fs7.existsSync(extractedDir)) {
|
|
2191
|
+
fs7.renameSync(extractedDir, targetDir);
|
|
1802
2192
|
} else {
|
|
1803
|
-
const files =
|
|
2193
|
+
const files = fs7.readdirSync(tempDir);
|
|
1804
2194
|
if (files.length === 1) {
|
|
1805
|
-
|
|
2195
|
+
fs7.renameSync(path5.join(tempDir, files[0]), targetDir);
|
|
1806
2196
|
} else {
|
|
1807
2197
|
throw new Error("Unexpected tgz structure");
|
|
1808
2198
|
}
|
|
1809
2199
|
}
|
|
1810
2200
|
return targetDir;
|
|
1811
2201
|
} finally {
|
|
1812
|
-
if (
|
|
1813
|
-
|
|
2202
|
+
if (fs7.existsSync(tempDir)) {
|
|
2203
|
+
fs7.rmSync(tempDir, { recursive: true });
|
|
1814
2204
|
}
|
|
1815
2205
|
}
|
|
1816
2206
|
}
|
|
@@ -1822,7 +2212,7 @@ function checkMissingPeerDeps(peerDeps) {
|
|
|
1822
2212
|
const nodeModulesPath = path5.join(getProjectRoot(), "node_modules");
|
|
1823
2213
|
for (const [depName, _version] of Object.entries(peerDeps)) {
|
|
1824
2214
|
const depPath = path5.join(nodeModulesPath, depName);
|
|
1825
|
-
if (!
|
|
2215
|
+
if (!fs7.existsSync(depPath)) {
|
|
1826
2216
|
missing.push(depName);
|
|
1827
2217
|
}
|
|
1828
2218
|
}
|
|
@@ -1846,15 +2236,15 @@ function installMissingDeps(deps) {
|
|
|
1846
2236
|
}
|
|
1847
2237
|
function removePluginDirectory(pluginName) {
|
|
1848
2238
|
const pluginPath = getPluginPath(pluginName);
|
|
1849
|
-
if (
|
|
1850
|
-
|
|
2239
|
+
if (fs7.existsSync(pluginPath)) {
|
|
2240
|
+
fs7.rmSync(pluginPath, { recursive: true });
|
|
1851
2241
|
console.log(`[action-plugin] Removed ${pluginName}`);
|
|
1852
2242
|
}
|
|
1853
2243
|
}
|
|
1854
2244
|
|
|
1855
2245
|
// src/commands/action-plugin/api-client.ts
|
|
1856
2246
|
import { HttpClient as HttpClient2 } from "@lark-apaas/http-client";
|
|
1857
|
-
import
|
|
2247
|
+
import fs8 from "fs";
|
|
1858
2248
|
import path6 from "path";
|
|
1859
2249
|
|
|
1860
2250
|
// src/utils/http-client.ts
|
|
@@ -1947,8 +2337,8 @@ function getPluginCacheDir() {
|
|
|
1947
2337
|
}
|
|
1948
2338
|
function ensureCacheDir() {
|
|
1949
2339
|
const cacheDir = getPluginCacheDir();
|
|
1950
|
-
if (!
|
|
1951
|
-
|
|
2340
|
+
if (!fs8.existsSync(cacheDir)) {
|
|
2341
|
+
fs8.mkdirSync(cacheDir, { recursive: true });
|
|
1952
2342
|
}
|
|
1953
2343
|
}
|
|
1954
2344
|
function getTempFilePath(pluginKey, version) {
|
|
@@ -1971,7 +2361,7 @@ async function downloadPlugin(pluginKey, requestedVersion) {
|
|
|
1971
2361
|
tgzBuffer = await downloadFromPublic(pluginInfo.downloadURL);
|
|
1972
2362
|
}
|
|
1973
2363
|
const tgzPath = getTempFilePath(pluginKey, pluginInfo.version);
|
|
1974
|
-
|
|
2364
|
+
fs8.writeFileSync(tgzPath, tgzBuffer);
|
|
1975
2365
|
console.log(`[action-plugin] Downloaded to ${tgzPath} (${(tgzBuffer.length / 1024).toFixed(2)} KB)`);
|
|
1976
2366
|
return {
|
|
1977
2367
|
tgzPath,
|
|
@@ -1981,8 +2371,8 @@ async function downloadPlugin(pluginKey, requestedVersion) {
|
|
|
1981
2371
|
}
|
|
1982
2372
|
function cleanupTempFile(tgzPath) {
|
|
1983
2373
|
try {
|
|
1984
|
-
if (
|
|
1985
|
-
|
|
2374
|
+
if (fs8.existsSync(tgzPath)) {
|
|
2375
|
+
fs8.unlinkSync(tgzPath);
|
|
1986
2376
|
}
|
|
1987
2377
|
} catch {
|
|
1988
2378
|
}
|
|
@@ -2318,7 +2708,7 @@ var actionPluginCommandGroup = {
|
|
|
2318
2708
|
};
|
|
2319
2709
|
|
|
2320
2710
|
// src/commands/capability/utils.ts
|
|
2321
|
-
import
|
|
2711
|
+
import fs9 from "fs";
|
|
2322
2712
|
import path7 from "path";
|
|
2323
2713
|
var CAPABILITIES_DIR = "server/capabilities";
|
|
2324
2714
|
function getProjectRoot2() {
|
|
@@ -2334,23 +2724,23 @@ function getPluginManifestPath(pluginKey) {
|
|
|
2334
2724
|
return path7.join(getProjectRoot2(), "node_modules", pluginKey, "manifest.json");
|
|
2335
2725
|
}
|
|
2336
2726
|
function capabilitiesDirExists() {
|
|
2337
|
-
return
|
|
2727
|
+
return fs9.existsSync(getCapabilitiesDir());
|
|
2338
2728
|
}
|
|
2339
2729
|
function listCapabilityIds() {
|
|
2340
2730
|
const dir = getCapabilitiesDir();
|
|
2341
|
-
if (!
|
|
2731
|
+
if (!fs9.existsSync(dir)) {
|
|
2342
2732
|
return [];
|
|
2343
2733
|
}
|
|
2344
|
-
const files =
|
|
2734
|
+
const files = fs9.readdirSync(dir);
|
|
2345
2735
|
return files.filter((f) => f.endsWith(".json") && f !== "capabilities.json").map((f) => f.replace(/\.json$/, ""));
|
|
2346
2736
|
}
|
|
2347
2737
|
function readCapability(id) {
|
|
2348
2738
|
const filePath = getCapabilityPath(id);
|
|
2349
|
-
if (!
|
|
2739
|
+
if (!fs9.existsSync(filePath)) {
|
|
2350
2740
|
throw new Error(`Capability not found: ${id}`);
|
|
2351
2741
|
}
|
|
2352
2742
|
try {
|
|
2353
|
-
const content =
|
|
2743
|
+
const content = fs9.readFileSync(filePath, "utf-8");
|
|
2354
2744
|
return JSON.parse(content);
|
|
2355
2745
|
} catch (error) {
|
|
2356
2746
|
if (error instanceof SyntaxError) {
|
|
@@ -2377,11 +2767,11 @@ function readAllCapabilities() {
|
|
|
2377
2767
|
}
|
|
2378
2768
|
function readPluginManifest(pluginKey) {
|
|
2379
2769
|
const manifestPath = getPluginManifestPath(pluginKey);
|
|
2380
|
-
if (!
|
|
2770
|
+
if (!fs9.existsSync(manifestPath)) {
|
|
2381
2771
|
throw new Error(`Plugin not installed: ${pluginKey} (manifest.json not found)`);
|
|
2382
2772
|
}
|
|
2383
2773
|
try {
|
|
2384
|
-
const content =
|
|
2774
|
+
const content = fs9.readFileSync(manifestPath, "utf-8");
|
|
2385
2775
|
return JSON.parse(content);
|
|
2386
2776
|
} catch (error) {
|
|
2387
2777
|
if (error instanceof SyntaxError) {
|
|
@@ -2555,7 +2945,7 @@ var capabilityCommandGroup = {
|
|
|
2555
2945
|
};
|
|
2556
2946
|
|
|
2557
2947
|
// src/commands/migration/version-manager.ts
|
|
2558
|
-
import
|
|
2948
|
+
import fs10 from "fs";
|
|
2559
2949
|
import path8 from "path";
|
|
2560
2950
|
var PACKAGE_JSON = "package.json";
|
|
2561
2951
|
var VERSION_FIELD = "migrationVersion";
|
|
@@ -2564,25 +2954,25 @@ function getPackageJsonPath2() {
|
|
|
2564
2954
|
}
|
|
2565
2955
|
function getCurrentVersion() {
|
|
2566
2956
|
const pkgPath = getPackageJsonPath2();
|
|
2567
|
-
if (!
|
|
2957
|
+
if (!fs10.existsSync(pkgPath)) {
|
|
2568
2958
|
throw new Error("package.json not found");
|
|
2569
2959
|
}
|
|
2570
|
-
const pkg2 = JSON.parse(
|
|
2960
|
+
const pkg2 = JSON.parse(fs10.readFileSync(pkgPath, "utf-8"));
|
|
2571
2961
|
return pkg2[VERSION_FIELD] ?? 0;
|
|
2572
2962
|
}
|
|
2573
2963
|
function setCurrentVersion(version) {
|
|
2574
2964
|
const pkgPath = getPackageJsonPath2();
|
|
2575
|
-
const pkg2 = JSON.parse(
|
|
2965
|
+
const pkg2 = JSON.parse(fs10.readFileSync(pkgPath, "utf-8"));
|
|
2576
2966
|
pkg2[VERSION_FIELD] = version;
|
|
2577
|
-
|
|
2967
|
+
fs10.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
|
|
2578
2968
|
}
|
|
2579
2969
|
|
|
2580
2970
|
// src/commands/migration/versions/v001_capability/json-migrator/detector.ts
|
|
2581
|
-
import
|
|
2971
|
+
import fs12 from "fs";
|
|
2582
2972
|
import path10 from "path";
|
|
2583
2973
|
|
|
2584
2974
|
// src/commands/migration/versions/v001_capability/utils.ts
|
|
2585
|
-
import
|
|
2975
|
+
import fs11 from "fs";
|
|
2586
2976
|
import path9 from "path";
|
|
2587
2977
|
var CAPABILITIES_DIR2 = "server/capabilities";
|
|
2588
2978
|
function getProjectRoot3() {
|
|
@@ -2599,14 +2989,14 @@ function getPluginManifestPath2(pluginKey) {
|
|
|
2599
2989
|
function detectJsonMigration() {
|
|
2600
2990
|
const capabilitiesDir = getCapabilitiesDir2();
|
|
2601
2991
|
const oldFilePath = path10.join(capabilitiesDir, "capabilities.json");
|
|
2602
|
-
if (!
|
|
2992
|
+
if (!fs12.existsSync(oldFilePath)) {
|
|
2603
2993
|
return {
|
|
2604
2994
|
needsMigration: false,
|
|
2605
2995
|
reason: "capabilities.json not found"
|
|
2606
2996
|
};
|
|
2607
2997
|
}
|
|
2608
2998
|
try {
|
|
2609
|
-
const content =
|
|
2999
|
+
const content = fs12.readFileSync(oldFilePath, "utf-8");
|
|
2610
3000
|
const parsed = JSON.parse(content);
|
|
2611
3001
|
if (!Array.isArray(parsed)) {
|
|
2612
3002
|
return {
|
|
@@ -2657,7 +3047,7 @@ async function check(options) {
|
|
|
2657
3047
|
}
|
|
2658
3048
|
|
|
2659
3049
|
// src/commands/migration/versions/v001_capability/json-migrator/index.ts
|
|
2660
|
-
import
|
|
3050
|
+
import fs13 from "fs";
|
|
2661
3051
|
import path11 from "path";
|
|
2662
3052
|
|
|
2663
3053
|
// src/commands/migration/versions/v001_capability/mapping.ts
|
|
@@ -2888,10 +3278,10 @@ function transformCapabilities(oldCapabilities) {
|
|
|
2888
3278
|
// src/commands/migration/versions/v001_capability/json-migrator/index.ts
|
|
2889
3279
|
function loadExistingCapabilities() {
|
|
2890
3280
|
const capabilitiesDir = getCapabilitiesDir2();
|
|
2891
|
-
if (!
|
|
3281
|
+
if (!fs13.existsSync(capabilitiesDir)) {
|
|
2892
3282
|
return [];
|
|
2893
3283
|
}
|
|
2894
|
-
const files =
|
|
3284
|
+
const files = fs13.readdirSync(capabilitiesDir);
|
|
2895
3285
|
const capabilities = [];
|
|
2896
3286
|
for (const file of files) {
|
|
2897
3287
|
if (file === "capabilities.json" || !file.endsWith(".json")) {
|
|
@@ -2899,7 +3289,7 @@ function loadExistingCapabilities() {
|
|
|
2899
3289
|
}
|
|
2900
3290
|
try {
|
|
2901
3291
|
const filePath = path11.join(capabilitiesDir, file);
|
|
2902
|
-
const content =
|
|
3292
|
+
const content = fs13.readFileSync(filePath, "utf-8");
|
|
2903
3293
|
const capability = JSON.parse(content);
|
|
2904
3294
|
if (capability.id && capability.pluginKey) {
|
|
2905
3295
|
capabilities.push(capability);
|
|
@@ -2959,7 +3349,7 @@ async function migrateJsonFiles(options) {
|
|
|
2959
3349
|
for (const cap of newCapabilities) {
|
|
2960
3350
|
const filePath = path11.join(capabilitiesDir, `${cap.id}.json`);
|
|
2961
3351
|
const content = JSON.stringify(cap, null, 2);
|
|
2962
|
-
|
|
3352
|
+
fs13.writeFileSync(filePath, content, "utf-8");
|
|
2963
3353
|
console.log(` \u2713 Created: ${cap.id}.json`);
|
|
2964
3354
|
}
|
|
2965
3355
|
return {
|
|
@@ -2971,11 +3361,11 @@ async function migrateJsonFiles(options) {
|
|
|
2971
3361
|
}
|
|
2972
3362
|
|
|
2973
3363
|
// src/commands/migration/versions/v001_capability/plugin-installer/detector.ts
|
|
2974
|
-
import
|
|
3364
|
+
import fs14 from "fs";
|
|
2975
3365
|
function isPluginInstalled2(pluginKey) {
|
|
2976
3366
|
const actionPlugins = readActionPlugins();
|
|
2977
3367
|
const manifestPath = getPluginManifestPath2(pluginKey);
|
|
2978
|
-
return
|
|
3368
|
+
return fs14.existsSync(manifestPath) && !!actionPlugins[pluginKey];
|
|
2979
3369
|
}
|
|
2980
3370
|
function detectPluginsToInstall(capabilities) {
|
|
2981
3371
|
const pluginKeys = /* @__PURE__ */ new Set();
|
|
@@ -3052,10 +3442,10 @@ async function installPlugins(capabilities, options) {
|
|
|
3052
3442
|
|
|
3053
3443
|
// src/commands/migration/versions/v001_capability/code-migrator/index.ts
|
|
3054
3444
|
import path13 from "path";
|
|
3055
|
-
import { Project as
|
|
3445
|
+
import { Project as Project3 } from "ts-morph";
|
|
3056
3446
|
|
|
3057
3447
|
// src/commands/migration/versions/v001_capability/code-migrator/scanner.ts
|
|
3058
|
-
import
|
|
3448
|
+
import fs15 from "fs";
|
|
3059
3449
|
import path12 from "path";
|
|
3060
3450
|
var EXCLUDED_DIRS = [
|
|
3061
3451
|
"node_modules",
|
|
@@ -3071,7 +3461,7 @@ var EXCLUDED_PATTERNS = [
|
|
|
3071
3461
|
/\.d\.ts$/
|
|
3072
3462
|
];
|
|
3073
3463
|
function scanDirectory(dir, files = []) {
|
|
3074
|
-
const entries =
|
|
3464
|
+
const entries = fs15.readdirSync(dir, { withFileTypes: true });
|
|
3075
3465
|
for (const entry of entries) {
|
|
3076
3466
|
const fullPath = path12.join(dir, entry.name);
|
|
3077
3467
|
if (entry.isDirectory()) {
|
|
@@ -3090,13 +3480,13 @@ function scanDirectory(dir, files = []) {
|
|
|
3090
3480
|
}
|
|
3091
3481
|
function scanServerFiles() {
|
|
3092
3482
|
const serverDir = path12.join(getProjectRoot3(), "server");
|
|
3093
|
-
if (!
|
|
3483
|
+
if (!fs15.existsSync(serverDir)) {
|
|
3094
3484
|
return [];
|
|
3095
3485
|
}
|
|
3096
3486
|
return scanDirectory(serverDir);
|
|
3097
3487
|
}
|
|
3098
3488
|
function hasCapabilityImport(filePath) {
|
|
3099
|
-
const content =
|
|
3489
|
+
const content = fs15.readFileSync(filePath, "utf-8");
|
|
3100
3490
|
return /import\s+.*from\s+['"][^'"]*capabilities[^'"]*['"]/.test(content);
|
|
3101
3491
|
}
|
|
3102
3492
|
function scanFilesToMigrate() {
|
|
@@ -3160,17 +3550,17 @@ function analyzeImports(sourceFile) {
|
|
|
3160
3550
|
}
|
|
3161
3551
|
|
|
3162
3552
|
// src/commands/migration/versions/v001_capability/code-migrator/analyzers/call-site-analyzer.ts
|
|
3163
|
-
import { SyntaxKind } from "ts-morph";
|
|
3553
|
+
import { SyntaxKind as SyntaxKind6 } from "ts-morph";
|
|
3164
3554
|
function analyzeCallSites(sourceFile, imports) {
|
|
3165
3555
|
const callSites = [];
|
|
3166
3556
|
const importMap = /* @__PURE__ */ new Map();
|
|
3167
3557
|
for (const imp of imports) {
|
|
3168
3558
|
importMap.set(imp.importName, imp.capabilityId);
|
|
3169
3559
|
}
|
|
3170
|
-
const callExpressions = sourceFile.getDescendantsOfKind(
|
|
3560
|
+
const callExpressions = sourceFile.getDescendantsOfKind(SyntaxKind6.CallExpression);
|
|
3171
3561
|
for (const callExpr of callExpressions) {
|
|
3172
3562
|
const expression = callExpr.getExpression();
|
|
3173
|
-
if (expression.getKind() ===
|
|
3563
|
+
if (expression.getKind() === SyntaxKind6.Identifier) {
|
|
3174
3564
|
const functionName = expression.getText();
|
|
3175
3565
|
const capabilityId = importMap.get(functionName);
|
|
3176
3566
|
if (capabilityId) {
|
|
@@ -3183,11 +3573,11 @@ function analyzeCallSites(sourceFile, imports) {
|
|
|
3183
3573
|
text: callExpr.getText()
|
|
3184
3574
|
});
|
|
3185
3575
|
}
|
|
3186
|
-
} else if (expression.getKind() ===
|
|
3187
|
-
const propAccess = expression.asKind(
|
|
3576
|
+
} else if (expression.getKind() === SyntaxKind6.PropertyAccessExpression) {
|
|
3577
|
+
const propAccess = expression.asKind(SyntaxKind6.PropertyAccessExpression);
|
|
3188
3578
|
if (propAccess) {
|
|
3189
3579
|
const objectExpr = propAccess.getExpression();
|
|
3190
|
-
if (objectExpr.getKind() ===
|
|
3580
|
+
if (objectExpr.getKind() === SyntaxKind6.Identifier) {
|
|
3191
3581
|
const objectName = objectExpr.getText();
|
|
3192
3582
|
const capabilityId = importMap.get(objectName);
|
|
3193
3583
|
if (capabilityId) {
|
|
@@ -3416,7 +3806,7 @@ function addInjection(sourceFile) {
|
|
|
3416
3806
|
}
|
|
3417
3807
|
|
|
3418
3808
|
// src/commands/migration/versions/v001_capability/code-migrator/transformers/call-site-transformer.ts
|
|
3419
|
-
import { SyntaxKind as
|
|
3809
|
+
import { SyntaxKind as SyntaxKind7 } from "ts-morph";
|
|
3420
3810
|
var DEFAULT_ACTION_NAME = "run";
|
|
3421
3811
|
function generateNewCallText(capabilityId, actionName, args) {
|
|
3422
3812
|
const argsText = args.trim() || "{}";
|
|
@@ -3431,19 +3821,19 @@ function transformCallSites(sourceFile, imports) {
|
|
|
3431
3821
|
});
|
|
3432
3822
|
}
|
|
3433
3823
|
let replacedCount = 0;
|
|
3434
|
-
const callExpressions = sourceFile.getDescendantsOfKind(
|
|
3824
|
+
const callExpressions = sourceFile.getDescendantsOfKind(SyntaxKind7.CallExpression);
|
|
3435
3825
|
const sortedCalls = [...callExpressions].sort((a, b) => b.getStart() - a.getStart());
|
|
3436
3826
|
for (const callExpr of sortedCalls) {
|
|
3437
3827
|
const expression = callExpr.getExpression();
|
|
3438
3828
|
let importInfo;
|
|
3439
|
-
if (expression.getKind() ===
|
|
3829
|
+
if (expression.getKind() === SyntaxKind7.Identifier) {
|
|
3440
3830
|
const functionName = expression.getText();
|
|
3441
3831
|
importInfo = importMap.get(functionName);
|
|
3442
|
-
} else if (expression.getKind() ===
|
|
3443
|
-
const propAccess = expression.asKind(
|
|
3832
|
+
} else if (expression.getKind() === SyntaxKind7.PropertyAccessExpression) {
|
|
3833
|
+
const propAccess = expression.asKind(SyntaxKind7.PropertyAccessExpression);
|
|
3444
3834
|
if (propAccess) {
|
|
3445
3835
|
const objectExpr = propAccess.getExpression();
|
|
3446
|
-
if (objectExpr.getKind() ===
|
|
3836
|
+
if (objectExpr.getKind() === SyntaxKind7.Identifier) {
|
|
3447
3837
|
const objectName = objectExpr.getText();
|
|
3448
3838
|
importInfo = importMap.get(objectName);
|
|
3449
3839
|
}
|
|
@@ -3544,7 +3934,7 @@ async function migrateCode(options, capabilities) {
|
|
|
3544
3934
|
console.log(" No files need code migration.\n");
|
|
3545
3935
|
return result;
|
|
3546
3936
|
}
|
|
3547
|
-
const project = new
|
|
3937
|
+
const project = new Project3({
|
|
3548
3938
|
skipAddingFilesFromTsConfig: true,
|
|
3549
3939
|
compilerOptions: {
|
|
3550
3940
|
allowJs: true
|
|
@@ -3587,17 +3977,17 @@ function getSuggestion(analysis) {
|
|
|
3587
3977
|
}
|
|
3588
3978
|
|
|
3589
3979
|
// src/commands/migration/versions/v001_capability/cleanup.ts
|
|
3590
|
-
import
|
|
3980
|
+
import fs16 from "fs";
|
|
3591
3981
|
import path14 from "path";
|
|
3592
3982
|
function cleanupOldFiles(capabilities, dryRun) {
|
|
3593
3983
|
const deletedFiles = [];
|
|
3594
3984
|
const errors = [];
|
|
3595
3985
|
const capabilitiesDir = getCapabilitiesDir2();
|
|
3596
3986
|
const oldJsonPath = path14.join(capabilitiesDir, "capabilities.json");
|
|
3597
|
-
if (
|
|
3987
|
+
if (fs16.existsSync(oldJsonPath)) {
|
|
3598
3988
|
try {
|
|
3599
3989
|
if (!dryRun) {
|
|
3600
|
-
|
|
3990
|
+
fs16.unlinkSync(oldJsonPath);
|
|
3601
3991
|
}
|
|
3602
3992
|
deletedFiles.push("capabilities.json");
|
|
3603
3993
|
} catch (error) {
|
|
@@ -3606,10 +3996,10 @@ function cleanupOldFiles(capabilities, dryRun) {
|
|
|
3606
3996
|
}
|
|
3607
3997
|
for (const cap of capabilities) {
|
|
3608
3998
|
const tsFilePath = path14.join(capabilitiesDir, `${cap.id}.ts`);
|
|
3609
|
-
if (
|
|
3999
|
+
if (fs16.existsSync(tsFilePath)) {
|
|
3610
4000
|
try {
|
|
3611
4001
|
if (!dryRun) {
|
|
3612
|
-
|
|
4002
|
+
fs16.unlinkSync(tsFilePath);
|
|
3613
4003
|
}
|
|
3614
4004
|
deletedFiles.push(`${cap.id}.ts`);
|
|
3615
4005
|
} catch (error) {
|
|
@@ -3625,7 +4015,7 @@ function cleanupOldFiles(capabilities, dryRun) {
|
|
|
3625
4015
|
}
|
|
3626
4016
|
|
|
3627
4017
|
// src/commands/migration/versions/v001_capability/report-generator.ts
|
|
3628
|
-
import
|
|
4018
|
+
import fs17 from "fs";
|
|
3629
4019
|
import path15 from "path";
|
|
3630
4020
|
var REPORT_FILE = "capability-migration-report.md";
|
|
3631
4021
|
function printSummary(result) {
|
|
@@ -3789,15 +4179,15 @@ async function generateReport(result) {
|
|
|
3789
4179
|
}
|
|
3790
4180
|
lines.push("");
|
|
3791
4181
|
const logDir = process.env.LOG_DIR || "logs";
|
|
3792
|
-
if (!
|
|
4182
|
+
if (!fs17.existsSync(logDir)) {
|
|
3793
4183
|
return;
|
|
3794
4184
|
}
|
|
3795
4185
|
const reportDir = path15.join(logDir, "migration");
|
|
3796
|
-
if (!
|
|
3797
|
-
|
|
4186
|
+
if (!fs17.existsSync(reportDir)) {
|
|
4187
|
+
fs17.mkdirSync(reportDir, { recursive: true });
|
|
3798
4188
|
}
|
|
3799
4189
|
const reportPath = path15.join(reportDir, REPORT_FILE);
|
|
3800
|
-
|
|
4190
|
+
fs17.writeFileSync(reportPath, lines.join("\n"), "utf-8");
|
|
3801
4191
|
console.log(`\u{1F4C4} Report generated: ${reportPath}`);
|
|
3802
4192
|
}
|
|
3803
4193
|
|
|
@@ -4332,7 +4722,7 @@ var migrationCommand = {
|
|
|
4332
4722
|
import path16 from "path";
|
|
4333
4723
|
|
|
4334
4724
|
// src/commands/read-logs/std-utils.ts
|
|
4335
|
-
import
|
|
4725
|
+
import fs18 from "fs";
|
|
4336
4726
|
function formatStdPrefixTime(localTime) {
|
|
4337
4727
|
const match = localTime.match(/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/);
|
|
4338
4728
|
if (!match) return localTime;
|
|
@@ -4362,11 +4752,11 @@ function stripPrefixFromStdLine(line) {
|
|
|
4362
4752
|
return `[${time}] ${content}`;
|
|
4363
4753
|
}
|
|
4364
4754
|
function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarker) {
|
|
4365
|
-
const stat =
|
|
4755
|
+
const stat = fs18.statSync(filePath);
|
|
4366
4756
|
if (stat.size === 0) {
|
|
4367
4757
|
return { lines: [], markerFound: false, totalLinesCount: 0 };
|
|
4368
4758
|
}
|
|
4369
|
-
const fd =
|
|
4759
|
+
const fd = fs18.openSync(filePath, "r");
|
|
4370
4760
|
const chunkSize = 64 * 1024;
|
|
4371
4761
|
let position = stat.size;
|
|
4372
4762
|
let remainder = "";
|
|
@@ -4380,7 +4770,7 @@ function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarke
|
|
|
4380
4770
|
const length = Math.min(chunkSize, position);
|
|
4381
4771
|
position -= length;
|
|
4382
4772
|
const buffer = Buffer.alloc(length);
|
|
4383
|
-
|
|
4773
|
+
fs18.readSync(fd, buffer, 0, length, position);
|
|
4384
4774
|
let chunk = buffer.toString("utf8");
|
|
4385
4775
|
if (remainder) {
|
|
4386
4776
|
chunk += remainder;
|
|
@@ -4422,7 +4812,7 @@ function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarke
|
|
|
4422
4812
|
}
|
|
4423
4813
|
}
|
|
4424
4814
|
} finally {
|
|
4425
|
-
|
|
4815
|
+
fs18.closeSync(fd);
|
|
4426
4816
|
}
|
|
4427
4817
|
return { lines: collected.reverse(), markerFound, totalLinesCount };
|
|
4428
4818
|
}
|
|
@@ -4443,21 +4833,21 @@ function readServerStdSegment(filePath, maxLines, offset) {
|
|
|
4443
4833
|
}
|
|
4444
4834
|
|
|
4445
4835
|
// src/commands/read-logs/tail.ts
|
|
4446
|
-
import
|
|
4836
|
+
import fs19 from "fs";
|
|
4447
4837
|
function fileExists(filePath) {
|
|
4448
4838
|
try {
|
|
4449
|
-
|
|
4839
|
+
fs19.accessSync(filePath, fs19.constants.F_OK | fs19.constants.R_OK);
|
|
4450
4840
|
return true;
|
|
4451
4841
|
} catch {
|
|
4452
4842
|
return false;
|
|
4453
4843
|
}
|
|
4454
4844
|
}
|
|
4455
4845
|
function readFileTailLines(filePath, maxLines) {
|
|
4456
|
-
const stat =
|
|
4846
|
+
const stat = fs19.statSync(filePath);
|
|
4457
4847
|
if (stat.size === 0) {
|
|
4458
4848
|
return [];
|
|
4459
4849
|
}
|
|
4460
|
-
const fd =
|
|
4850
|
+
const fd = fs19.openSync(filePath, "r");
|
|
4461
4851
|
const chunkSize = 64 * 1024;
|
|
4462
4852
|
const chunks = [];
|
|
4463
4853
|
let position = stat.size;
|
|
@@ -4467,13 +4857,13 @@ function readFileTailLines(filePath, maxLines) {
|
|
|
4467
4857
|
const length = Math.min(chunkSize, position);
|
|
4468
4858
|
position -= length;
|
|
4469
4859
|
const buffer = Buffer.alloc(length);
|
|
4470
|
-
|
|
4860
|
+
fs19.readSync(fd, buffer, 0, length, position);
|
|
4471
4861
|
chunks.unshift(buffer.toString("utf8"));
|
|
4472
4862
|
const chunkLines = buffer.toString("utf8").split("\n").length - 1;
|
|
4473
4863
|
collectedLines += chunkLines;
|
|
4474
4864
|
}
|
|
4475
4865
|
} finally {
|
|
4476
|
-
|
|
4866
|
+
fs19.closeSync(fd);
|
|
4477
4867
|
}
|
|
4478
4868
|
const content = chunks.join("");
|
|
4479
4869
|
const allLines = content.split("\n");
|
|
@@ -4489,11 +4879,11 @@ function readFileTailLines(filePath, maxLines) {
|
|
|
4489
4879
|
return allLines.slice(allLines.length - maxLines);
|
|
4490
4880
|
}
|
|
4491
4881
|
function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
|
|
4492
|
-
const stat =
|
|
4882
|
+
const stat = fs19.statSync(filePath);
|
|
4493
4883
|
if (stat.size === 0) {
|
|
4494
4884
|
return { lines: [], totalLinesCount: 0 };
|
|
4495
4885
|
}
|
|
4496
|
-
const fd =
|
|
4886
|
+
const fd = fs19.openSync(filePath, "r");
|
|
4497
4887
|
const chunkSize = 64 * 1024;
|
|
4498
4888
|
let position = stat.size;
|
|
4499
4889
|
let remainder = "";
|
|
@@ -4505,7 +4895,7 @@ function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
|
|
|
4505
4895
|
const length = Math.min(chunkSize, position);
|
|
4506
4896
|
position -= length;
|
|
4507
4897
|
const buffer = Buffer.alloc(length);
|
|
4508
|
-
|
|
4898
|
+
fs19.readSync(fd, buffer, 0, length, position);
|
|
4509
4899
|
let chunk = buffer.toString("utf8");
|
|
4510
4900
|
if (remainder) {
|
|
4511
4901
|
chunk += remainder;
|
|
@@ -4536,7 +4926,7 @@ function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
|
|
|
4536
4926
|
}
|
|
4537
4927
|
}
|
|
4538
4928
|
} finally {
|
|
4539
|
-
|
|
4929
|
+
fs19.closeSync(fd);
|
|
4540
4930
|
}
|
|
4541
4931
|
return { lines: collected.reverse(), totalLinesCount };
|
|
4542
4932
|
}
|
|
@@ -4638,7 +5028,7 @@ function extractClientStdSegment(lines, maxLines, offset) {
|
|
|
4638
5028
|
}
|
|
4639
5029
|
|
|
4640
5030
|
// src/commands/read-logs/json-lines.ts
|
|
4641
|
-
import
|
|
5031
|
+
import fs20 from "fs";
|
|
4642
5032
|
function normalizePid(value) {
|
|
4643
5033
|
if (typeof value === "number") {
|
|
4644
5034
|
return String(value);
|
|
@@ -4689,11 +5079,11 @@ function buildWantedLevelSet(levels) {
|
|
|
4689
5079
|
return set.size > 0 ? set : null;
|
|
4690
5080
|
}
|
|
4691
5081
|
function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
|
|
4692
|
-
const stat =
|
|
5082
|
+
const stat = fs20.statSync(filePath);
|
|
4693
5083
|
if (stat.size === 0) {
|
|
4694
5084
|
return { lines: [], totalLinesCount: 0 };
|
|
4695
5085
|
}
|
|
4696
|
-
const fd =
|
|
5086
|
+
const fd = fs20.openSync(filePath, "r");
|
|
4697
5087
|
const chunkSize = 64 * 1024;
|
|
4698
5088
|
let position = stat.size;
|
|
4699
5089
|
let remainder = "";
|
|
@@ -4708,7 +5098,7 @@ function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
|
|
|
4708
5098
|
const length = Math.min(chunkSize, position);
|
|
4709
5099
|
position -= length;
|
|
4710
5100
|
const buffer = Buffer.alloc(length);
|
|
4711
|
-
|
|
5101
|
+
fs20.readSync(fd, buffer, 0, length, position);
|
|
4712
5102
|
let chunk = buffer.toString("utf8");
|
|
4713
5103
|
if (remainder) {
|
|
4714
5104
|
chunk += remainder;
|
|
@@ -4770,7 +5160,7 @@ function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
|
|
|
4770
5160
|
}
|
|
4771
5161
|
}
|
|
4772
5162
|
} finally {
|
|
4773
|
-
|
|
5163
|
+
fs20.closeSync(fd);
|
|
4774
5164
|
}
|
|
4775
5165
|
return { lines: collected.reverse(), totalLinesCount };
|
|
4776
5166
|
}
|
|
@@ -4813,11 +5203,11 @@ function extractTraceId(obj) {
|
|
|
4813
5203
|
function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
|
|
4814
5204
|
const wanted = traceId.trim();
|
|
4815
5205
|
if (!wanted) return { lines: [], totalLinesCount: 0 };
|
|
4816
|
-
const stat =
|
|
5206
|
+
const stat = fs20.statSync(filePath);
|
|
4817
5207
|
if (stat.size === 0) {
|
|
4818
5208
|
return { lines: [], totalLinesCount: 0 };
|
|
4819
5209
|
}
|
|
4820
|
-
const fd =
|
|
5210
|
+
const fd = fs20.openSync(filePath, "r");
|
|
4821
5211
|
const chunkSize = 64 * 1024;
|
|
4822
5212
|
let position = stat.size;
|
|
4823
5213
|
let remainder = "";
|
|
@@ -4830,7 +5220,7 @@ function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
|
|
|
4830
5220
|
const length = Math.min(chunkSize, position);
|
|
4831
5221
|
position -= length;
|
|
4832
5222
|
const buffer = Buffer.alloc(length);
|
|
4833
|
-
|
|
5223
|
+
fs20.readSync(fd, buffer, 0, length, position);
|
|
4834
5224
|
let chunk = buffer.toString("utf8");
|
|
4835
5225
|
if (remainder) {
|
|
4836
5226
|
chunk += remainder;
|
|
@@ -4883,7 +5273,7 @@ function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
|
|
|
4883
5273
|
}
|
|
4884
5274
|
}
|
|
4885
5275
|
} finally {
|
|
4886
|
-
|
|
5276
|
+
fs20.closeSync(fd);
|
|
4887
5277
|
}
|
|
4888
5278
|
return { lines: collected.reverse(), totalLinesCount };
|
|
4889
5279
|
}
|
|
@@ -4892,11 +5282,11 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
|
|
|
4892
5282
|
if (!wantedLevelSet) {
|
|
4893
5283
|
return { lines: [], totalLinesCount: 0 };
|
|
4894
5284
|
}
|
|
4895
|
-
const stat =
|
|
5285
|
+
const stat = fs20.statSync(filePath);
|
|
4896
5286
|
if (stat.size === 0) {
|
|
4897
5287
|
return { lines: [], totalLinesCount: 0 };
|
|
4898
5288
|
}
|
|
4899
|
-
const fd =
|
|
5289
|
+
const fd = fs20.openSync(filePath, "r");
|
|
4900
5290
|
const chunkSize = 64 * 1024;
|
|
4901
5291
|
let position = stat.size;
|
|
4902
5292
|
let remainder = "";
|
|
@@ -4908,7 +5298,7 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
|
|
|
4908
5298
|
const length = Math.min(chunkSize, position);
|
|
4909
5299
|
position -= length;
|
|
4910
5300
|
const buffer = Buffer.alloc(length);
|
|
4911
|
-
|
|
5301
|
+
fs20.readSync(fd, buffer, 0, length, position);
|
|
4912
5302
|
let chunk = buffer.toString("utf8");
|
|
4913
5303
|
if (remainder) {
|
|
4914
5304
|
chunk += remainder;
|
|
@@ -4955,7 +5345,7 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
|
|
|
4955
5345
|
}
|
|
4956
5346
|
}
|
|
4957
5347
|
} finally {
|
|
4958
|
-
|
|
5348
|
+
fs20.closeSync(fd);
|
|
4959
5349
|
}
|
|
4960
5350
|
return { lines: collected.reverse(), totalLinesCount };
|
|
4961
5351
|
}
|
|
@@ -5176,11 +5566,11 @@ var commands = [
|
|
|
5176
5566
|
|
|
5177
5567
|
// src/index.ts
|
|
5178
5568
|
var envPath = path17.join(process.cwd(), ".env");
|
|
5179
|
-
if (
|
|
5569
|
+
if (fs21.existsSync(envPath)) {
|
|
5180
5570
|
dotenvConfig({ path: envPath });
|
|
5181
5571
|
}
|
|
5182
5572
|
var __dirname = path17.dirname(fileURLToPath4(import.meta.url));
|
|
5183
|
-
var pkg = JSON.parse(
|
|
5573
|
+
var pkg = JSON.parse(fs21.readFileSync(path17.join(__dirname, "../package.json"), "utf-8"));
|
|
5184
5574
|
var cli = new FullstackCLI(pkg.version);
|
|
5185
5575
|
cli.useAll(commands);
|
|
5186
5576
|
cli.run();
|