@lark-apaas/fullstack-cli 1.1.16-alpha.0 → 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/config/drizzle.config.js +24 -1
- package/dist/index.js +919 -566
- 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,104 +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
|
-
|
|
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
|
+
};
|
|
145
152
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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
|
|
150
161
|
}
|
|
151
|
-
|
|
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 };
|
|
152
170
|
}
|
|
153
|
-
function
|
|
154
|
-
|
|
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;
|
|
155
182
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
function convertSchemaTableInvocations(source) {
|
|
162
|
-
let converted = 0;
|
|
163
|
-
let text = source.replace(/([A-Za-z0-9_]+)\.table\(/g, () => {
|
|
164
|
-
converted += 1;
|
|
165
|
-
return "pgTable(";
|
|
166
|
-
});
|
|
167
|
-
text = text.replace(/([A-Za-z0-9_]+)\.view\(/g, () => {
|
|
168
|
-
converted += 1;
|
|
169
|
-
return "pgView(";
|
|
170
|
-
});
|
|
171
|
-
text = text.replace(/([A-Za-z0-9_]+)\.materializedView\(/g, () => {
|
|
172
|
-
converted += 1;
|
|
173
|
-
return "pgMaterializedView(";
|
|
174
|
-
});
|
|
175
|
-
text = text.replace(/([A-Za-z0-9_]+)\.enum\(/g, () => {
|
|
176
|
-
converted += 1;
|
|
177
|
-
return "pgEnum(";
|
|
183
|
+
function formatSourceFile(sourceFile) {
|
|
184
|
+
sourceFile.formatText({
|
|
185
|
+
indentSize: 2,
|
|
186
|
+
convertTabsToSpaces: true
|
|
178
187
|
});
|
|
179
|
-
text = text.replace(/([A-Za-z0-9_]+)\.sequence\(/g, () => {
|
|
180
|
-
converted += 1;
|
|
181
|
-
return "pgSequence(";
|
|
182
|
-
});
|
|
183
|
-
return { text, converted };
|
|
184
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";
|
|
185
195
|
|
|
186
|
-
// src/commands/db/gen-dbschema/
|
|
196
|
+
// src/commands/db/gen-dbschema/utils/identifier.ts
|
|
187
197
|
import { pinyin } from "pinyin-pro";
|
|
188
|
-
function
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
const equalsIndex = match.indexOf("=");
|
|
198
|
-
const suffix = equalsIndex >= 0 ? match.slice(equalsIndex) : ` = ${factory}("${tableName}"`;
|
|
199
|
-
const normalizedSuffix = suffix.trimStart();
|
|
200
|
-
return `export const ${sanitized} ${normalizedSuffix}`;
|
|
201
|
-
});
|
|
202
|
-
return { text: updated, renames };
|
|
203
|
-
}
|
|
204
|
-
function updateTableReferenceIdentifiers(source, renames) {
|
|
205
|
-
if (renames.length === 0) {
|
|
206
|
-
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;
|
|
207
207
|
}
|
|
208
|
-
return renames.reduce((acc, rename) => {
|
|
209
|
-
if (!rename.from || rename.from === rename.to) {
|
|
210
|
-
return acc;
|
|
211
|
-
}
|
|
212
|
-
const pattern = new RegExp(`\\b${escapeRegExp(rename.from)}(\\s*[.(])`, "g");
|
|
213
|
-
return acc.replace(pattern, `${rename.to}$1`);
|
|
214
|
-
}, source);
|
|
215
|
-
}
|
|
216
|
-
function escapeRegExp(value) {
|
|
217
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\//g, "\\/");
|
|
218
208
|
}
|
|
219
209
|
function toCamelCase(str) {
|
|
220
210
|
const words = str.split(/[_\-\s]+/).filter(Boolean);
|
|
@@ -242,136 +232,640 @@ function sanitizeIdentifier(name) {
|
|
|
242
232
|
}
|
|
243
233
|
return sanitized;
|
|
244
234
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
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;
|
|
248
253
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
return
|
|
252
|
-
}
|
|
253
|
-
|
|
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();
|
|
254
261
|
}
|
|
262
|
+
return void 0;
|
|
255
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
|
+
};
|
|
256
327
|
|
|
257
|
-
// src/commands/db/gen-dbschema/
|
|
258
|
-
|
|
259
|
-
var
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
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;
|
|
338
|
+
}
|
|
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
|
+
}
|
|
280
350
|
}
|
|
281
|
-
continue;
|
|
282
351
|
}
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
352
|
+
for (const statement of statementsToRemove.reverse()) {
|
|
353
|
+
statement.remove();
|
|
354
|
+
}
|
|
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++;
|
|
290
465
|
} else {
|
|
291
|
-
|
|
292
|
-
result.push(line);
|
|
466
|
+
stats.fallbackToText++;
|
|
293
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)) {
|
|
294
485
|
continue;
|
|
295
486
|
}
|
|
296
|
-
|
|
297
|
-
|
|
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
|
+
}
|
|
298
498
|
}
|
|
299
|
-
result.push(line);
|
|
300
499
|
}
|
|
301
|
-
return
|
|
302
|
-
text: result.join("\n"),
|
|
303
|
-
replaced,
|
|
304
|
-
fallbackToText,
|
|
305
|
-
unmatched
|
|
306
|
-
};
|
|
500
|
+
return hasWithTimezone && hasModeString;
|
|
307
501
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
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
|
+
}
|
|
311
552
|
}
|
|
312
|
-
|
|
313
|
-
}
|
|
553
|
+
};
|
|
314
554
|
|
|
315
|
-
// src/commands/db/gen-dbschema/
|
|
316
|
-
import
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
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
|
+
});
|
|
323
580
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
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
|
+
});
|
|
334
663
|
}
|
|
335
|
-
|
|
336
|
-
|
|
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
|
+
}
|
|
337
737
|
}
|
|
338
|
-
|
|
339
|
-
|
|
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}.`);
|
|
340
784
|
}
|
|
341
|
-
|
|
342
|
-
|
|
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
|
+
}
|
|
343
803
|
}
|
|
344
|
-
|
|
345
|
-
|
|
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;
|
|
346
836
|
}
|
|
347
|
-
|
|
348
|
-
const replacement = `import { ${unique.join(", ")} } from "drizzle-orm/pg-core"`;
|
|
349
|
-
return source.replace(importRegex, replacement);
|
|
837
|
+
return lines.join("\n");
|
|
350
838
|
}
|
|
839
|
+
|
|
840
|
+
// src/commands/db/gen-dbschema/transforms/text/inline-types.ts
|
|
841
|
+
import fs from "fs";
|
|
842
|
+
import { fileURLToPath } from "url";
|
|
351
843
|
function inlineCustomTypes(source) {
|
|
352
|
-
|
|
844
|
+
let text = source.replace(/import \{[^}]*\} from ["']\.\/types["'];?\n*/g, "");
|
|
353
845
|
const templatePath = resolveTemplateTypesPath();
|
|
354
846
|
if (!templatePath) {
|
|
355
|
-
console.warn("[
|
|
847
|
+
console.warn("[text/inline-types] Template types file not found.");
|
|
356
848
|
return text;
|
|
357
849
|
}
|
|
358
|
-
|
|
850
|
+
const templateContent = fs.readFileSync(templatePath, "utf8");
|
|
851
|
+
return inlineFromTemplate(text, templateContent);
|
|
359
852
|
}
|
|
360
|
-
function
|
|
853
|
+
function inlineFromTemplate(source, templateContent) {
|
|
361
854
|
const typeDefinitions = templateContent.replace(/^import\s+.*;\r?\n*/gm, "").trim();
|
|
855
|
+
let text = source;
|
|
362
856
|
const needsSql = typeDefinitions.includes("sql`") && !text.includes("from 'drizzle-orm'") && !text.includes('from "drizzle-orm"');
|
|
363
857
|
const needsCustomType = typeDefinitions.includes("customType<") && !text.includes("customType");
|
|
364
858
|
if (needsCustomType) {
|
|
365
859
|
text = ensureImportIdentifier(text, "drizzle-orm/pg-core", "customType");
|
|
366
860
|
}
|
|
367
|
-
if (needsSql
|
|
861
|
+
if (needsSql) {
|
|
368
862
|
const importMatch = text.match(/^import [\s\S]*?from ["']drizzle-orm\/pg-core["'];?\n/m);
|
|
369
863
|
if (importMatch) {
|
|
370
864
|
const insertPoint = text.indexOf(importMatch[0]) + importMatch[0].length;
|
|
371
865
|
text = text.slice(0, insertPoint) + "import { sql } from 'drizzle-orm';\n" + text.slice(insertPoint);
|
|
372
866
|
}
|
|
373
867
|
}
|
|
374
|
-
const headerPrefix = `${
|
|
868
|
+
const headerPrefix = `${FULL_HEADER}
|
|
375
869
|
`;
|
|
376
870
|
let insertionPoint = 0;
|
|
377
871
|
if (text.startsWith(headerPrefix)) {
|
|
@@ -405,8 +899,8 @@ function ensureImportIdentifier(source, packageName, identifier) {
|
|
|
405
899
|
}
|
|
406
900
|
function resolveTemplateTypesPath() {
|
|
407
901
|
const candidates = [
|
|
408
|
-
new URL("
|
|
409
|
-
new URL("
|
|
902
|
+
new URL("../../template/types.ts", import.meta.url),
|
|
903
|
+
new URL("../template/types.ts", import.meta.url)
|
|
410
904
|
];
|
|
411
905
|
for (const url of candidates) {
|
|
412
906
|
const p = fileURLToPath(url);
|
|
@@ -417,131 +911,9 @@ function resolveTemplateTypesPath() {
|
|
|
417
911
|
return void 0;
|
|
418
912
|
}
|
|
419
913
|
|
|
420
|
-
// src/commands/db/gen-dbschema/
|
|
421
|
-
function addSystemFieldComments(source) {
|
|
422
|
-
const commentMap = {
|
|
423
|
-
"_created_at": "Creation time",
|
|
424
|
-
"_created_by": "Creator",
|
|
425
|
-
"_updated_at": "Update time",
|
|
426
|
-
"_updated_by": "Updater"
|
|
427
|
-
};
|
|
428
|
-
const lines = source.split("\n");
|
|
429
|
-
for (let i = 0; i < lines.length; i += 1) {
|
|
430
|
-
const line = lines[i];
|
|
431
|
-
const entry = Object.entries(commentMap).find(([key]) => line.includes(`"${key}"`));
|
|
432
|
-
if (!entry) {
|
|
433
|
-
continue;
|
|
434
|
-
}
|
|
435
|
-
const [, description] = entry;
|
|
436
|
-
const previousLine = lines[i - 1]?.trim() ?? "";
|
|
437
|
-
if (previousLine.startsWith("//") && previousLine.includes("System field")) {
|
|
438
|
-
continue;
|
|
439
|
-
}
|
|
440
|
-
const indentMatch = line.match(/^\s*/);
|
|
441
|
-
const indent = indentMatch ? indentMatch[0] : "";
|
|
442
|
-
const comment = `${indent}// System field: ${description} (auto-filled, do not modify)`;
|
|
443
|
-
lines.splice(i, 0, comment);
|
|
444
|
-
i += 1;
|
|
445
|
-
}
|
|
446
|
-
return lines.join("\n");
|
|
447
|
-
}
|
|
448
|
-
function removeConflictingSystemFields(source) {
|
|
449
|
-
const systemFieldMap = {
|
|
450
|
-
"_created_at": "created_at",
|
|
451
|
-
"_created_by": "created_by",
|
|
452
|
-
"_updated_at": "updated_at",
|
|
453
|
-
"_updated_by": "updated_by"
|
|
454
|
-
};
|
|
455
|
-
const lines = source.split("\n");
|
|
456
|
-
const result = [];
|
|
457
|
-
let inTable = false;
|
|
458
|
-
let tableStartLine = -1;
|
|
459
|
-
const tableBusinessFields = /* @__PURE__ */ new Set();
|
|
460
|
-
let bracketDepth = 0;
|
|
461
|
-
for (let i = 0; i < lines.length; i += 1) {
|
|
462
|
-
const line = lines[i];
|
|
463
|
-
if (!inTable && /=\s*(pgTable|pgView|pgMaterializedView)\s*\(/.test(line)) {
|
|
464
|
-
inTable = true;
|
|
465
|
-
tableStartLine = result.length;
|
|
466
|
-
tableBusinessFields.clear();
|
|
467
|
-
bracketDepth = 0;
|
|
468
|
-
}
|
|
469
|
-
if (inTable) {
|
|
470
|
-
for (const char of line) {
|
|
471
|
-
if (char === "{") bracketDepth++;
|
|
472
|
-
if (char === "}") bracketDepth--;
|
|
473
|
-
}
|
|
474
|
-
for (const businessField of Object.values(systemFieldMap)) {
|
|
475
|
-
if (line.includes(`"${businessField}"`) || line.includes(`'${businessField}'`)) {
|
|
476
|
-
tableBusinessFields.add(businessField);
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
if (bracketDepth === 0 && line.includes(");")) {
|
|
480
|
-
inTable = false;
|
|
481
|
-
const tableEndLine = result.length;
|
|
482
|
-
for (let j = tableStartLine; j <= tableEndLine; j++) {
|
|
483
|
-
const tableLine = result[j] || "";
|
|
484
|
-
let shouldRemove = false;
|
|
485
|
-
for (const [systemField, businessField] of Object.entries(systemFieldMap)) {
|
|
486
|
-
if (tableBusinessFields.has(businessField)) {
|
|
487
|
-
if (tableLine.includes(`"${systemField}"`) || tableLine.includes(`'${systemField}'`)) {
|
|
488
|
-
shouldRemove = true;
|
|
489
|
-
if (j > 0 && result[j - 1]?.includes("// System field:")) {
|
|
490
|
-
result[j - 1] = null;
|
|
491
|
-
}
|
|
492
|
-
break;
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
if (shouldRemove) {
|
|
497
|
-
result[j] = null;
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
result.push(line);
|
|
503
|
-
}
|
|
504
|
-
return result.filter((line) => line !== null).join("\n");
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
// src/commands/db/gen-dbschema/helper/patch-helper.ts
|
|
508
|
-
function patchDrizzleKitDefects(source) {
|
|
509
|
-
let fixed = 0;
|
|
510
|
-
const text = source.replace(/\.default\('\)/g, () => {
|
|
511
|
-
fixed += 1;
|
|
512
|
-
return `.default('')`;
|
|
513
|
-
});
|
|
514
|
-
return { text, fixed };
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
// src/commands/db/gen-dbschema/helper/timestamp-replacement.ts
|
|
518
|
-
function replaceTimestampWithCustomTypes(source) {
|
|
519
|
-
let replaced = 0;
|
|
520
|
-
const pattern = /timestamp\((['"])(.*?)\1,\s*(\{[^}]*\})\)/g;
|
|
521
|
-
const text = source.replace(pattern, (match, quote, fieldName, options) => {
|
|
522
|
-
const hasWithTimezone = /withTimezone:\s*true/.test(options);
|
|
523
|
-
const hasModeString = /mode:\s*['"]string['"]/.test(options);
|
|
524
|
-
if (hasWithTimezone && hasModeString) {
|
|
525
|
-
replaced += 1;
|
|
526
|
-
return `customTimestamptz(${quote}${fieldName}${quote})`;
|
|
527
|
-
}
|
|
528
|
-
return match;
|
|
529
|
-
});
|
|
530
|
-
return { text, replaced };
|
|
531
|
-
}
|
|
532
|
-
function replaceDefaultNowWithSql(source) {
|
|
533
|
-
let replaced = 0;
|
|
534
|
-
const pattern = /\.defaultNow\(\)/g;
|
|
535
|
-
const text = source.replace(pattern, () => {
|
|
536
|
-
replaced += 1;
|
|
537
|
-
return ".default(sql`CURRENT_TIMESTAMP`)";
|
|
538
|
-
});
|
|
539
|
-
return { text, replaced };
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
// src/commands/db/gen-dbschema/helper/appendTableAliases.ts
|
|
914
|
+
// src/commands/db/gen-dbschema/transforms/text/table-aliases.ts
|
|
543
915
|
var TABLE_ALIAS_MARKER = "// table aliases";
|
|
544
|
-
function
|
|
916
|
+
function generateTableAliases(source) {
|
|
545
917
|
const markerIndex = source.indexOf(`
|
|
546
918
|
${TABLE_ALIAS_MARKER}`);
|
|
547
919
|
const base = markerIndex === -1 ? source : source.slice(0, markerIndex);
|
|
@@ -563,119 +935,100 @@ ${aliasLines}
|
|
|
563
935
|
`;
|
|
564
936
|
}
|
|
565
937
|
|
|
566
|
-
// src/commands/db/gen-dbschema/
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
"
|
|
570
|
-
"
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
const
|
|
580
|
-
|
|
581
|
-
const
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
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
|
+
|
|
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}`);
|
|
596
983
|
}
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
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}`);
|
|
607
995
|
}
|
|
608
|
-
result.push(line);
|
|
609
996
|
}
|
|
610
|
-
|
|
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
|
+
}
|
|
611
1012
|
}
|
|
612
1013
|
|
|
613
|
-
// src/commands/db/gen-dbschema/
|
|
1014
|
+
// src/commands/db/gen-dbschema/index.ts
|
|
614
1015
|
function postprocessDrizzleSchema(targetPath) {
|
|
615
1016
|
const resolvedPath = path.resolve(targetPath);
|
|
616
|
-
if (!
|
|
1017
|
+
if (!fs3.existsSync(resolvedPath)) {
|
|
617
1018
|
console.warn(`[postprocess-drizzle-schema] File not found: ${resolvedPath}`);
|
|
618
1019
|
return void 0;
|
|
619
1020
|
}
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
text = removePgSchemaDeclarations(text);
|
|
625
|
-
const tableConversion = convertSchemaTableInvocations(text);
|
|
626
|
-
text = tableConversion.text;
|
|
627
|
-
const systemObjectsResult = removeSystemObjects(text);
|
|
628
|
-
text = systemObjectsResult.text;
|
|
629
|
-
const renameResult = renamePgTableConstants(text);
|
|
630
|
-
text = renameResult.text;
|
|
631
|
-
text = updateTableReferenceIdentifiers(text, renameResult.renames);
|
|
632
|
-
const replacement = replaceUnknownColumns(text);
|
|
633
|
-
text = replacement.text;
|
|
634
|
-
const timestampReplacement = replaceTimestampWithCustomTypes(text);
|
|
635
|
-
text = timestampReplacement.text;
|
|
636
|
-
const defaultNowReplacement = replaceDefaultNowWithSql(text);
|
|
637
|
-
text = defaultNowReplacement.text;
|
|
638
|
-
text = removeConflictingSystemFields(text);
|
|
639
|
-
text = addSystemFieldComments(text);
|
|
640
|
-
text = tweakImports(text);
|
|
641
|
-
text = inlineCustomTypes(text);
|
|
642
|
-
text = appendTableAliases(text);
|
|
643
|
-
text = text.replace(/\r?\n/g, "\n");
|
|
644
|
-
text = collapseExtraBlankLines(text);
|
|
645
|
-
fs2.writeFileSync(resolvedPath, text, "utf8");
|
|
646
|
-
if (patchResult.fixed > 0) {
|
|
647
|
-
console.info(`[postprocess-drizzle-schema] Patched ${patchResult.fixed} drizzle-kit defects (.default(') -> .default(''))`);
|
|
648
|
-
}
|
|
649
|
-
if (replacement.replaced > 0) {
|
|
650
|
-
console.info(`[postprocess-drizzle-schema] Replaced ${replacement.replaced} unknown columns with custom types`);
|
|
651
|
-
}
|
|
652
|
-
if (replacement.fallbackToText > 0) {
|
|
653
|
-
console.info(`[postprocess-drizzle-schema] Replaced ${replacement.fallbackToText} unknown columns with text (fallback)`);
|
|
654
|
-
}
|
|
655
|
-
if (replacement.unmatched.length > 0) {
|
|
656
|
-
console.warn("[postprocess-drizzle-schema] Unmatched unknown columns:", replacement.unmatched.length);
|
|
657
|
-
replacement.unmatched.forEach((line) => console.warn(` ${line}`));
|
|
658
|
-
}
|
|
659
|
-
if (tableConversion.converted > 0) {
|
|
660
|
-
console.info(`[postprocess-drizzle-schema] Converted ${tableConversion.converted} schema.table invocations to pgTable`);
|
|
661
|
-
}
|
|
662
|
-
if (timestampReplacement.replaced > 0) {
|
|
663
|
-
console.info(`[postprocess-drizzle-schema] Replaced ${timestampReplacement.replaced} timestamp fields with customTimestamptz`);
|
|
664
|
-
}
|
|
665
|
-
if (defaultNowReplacement.replaced > 0) {
|
|
666
|
-
console.info(`[postprocess-drizzle-schema] Replaced ${defaultNowReplacement.replaced} .defaultNow() with .default(sql\`CURRENT_TIMESTAMP\`)`);
|
|
667
|
-
}
|
|
668
|
-
if (systemObjectsResult.removed.length > 0) {
|
|
669
|
-
console.info(`[postprocess-drizzle-schema] Removed ${systemObjectsResult.removed.length} system objects: ${systemObjectsResult.removed.join(", ")}`);
|
|
670
|
-
}
|
|
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]");
|
|
671
1025
|
return {
|
|
672
|
-
replacedUnknown:
|
|
673
|
-
fallbackToText:
|
|
674
|
-
unmatchedUnknown:
|
|
675
|
-
patchedDefects:
|
|
676
|
-
replacedTimestamps:
|
|
677
|
-
replacedDefaultNow:
|
|
678
|
-
removedSystemObjects: systemObjectsResult.removed
|
|
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
|
|
679
1032
|
};
|
|
680
1033
|
}
|
|
681
1034
|
|
|
@@ -1097,10 +1450,10 @@ export class ${className}Module {}
|
|
|
1097
1450
|
}
|
|
1098
1451
|
|
|
1099
1452
|
// src/commands/db/gen-nest-resource/schema-parser.ts
|
|
1100
|
-
import { Project, Node } from "ts-morph";
|
|
1453
|
+
import { Project as Project2, Node as Node9 } from "ts-morph";
|
|
1101
1454
|
var DrizzleSchemaParser = class {
|
|
1102
1455
|
constructor(projectOptions) {
|
|
1103
|
-
this.project = new
|
|
1456
|
+
this.project = new Project2(projectOptions);
|
|
1104
1457
|
}
|
|
1105
1458
|
parseSchemaFile(filePath) {
|
|
1106
1459
|
const sourceFile = this.project.addSourceFileAtPath(filePath);
|
|
@@ -1110,7 +1463,7 @@ var DrizzleSchemaParser = class {
|
|
|
1110
1463
|
const declarations = statement.getDeclarations();
|
|
1111
1464
|
for (const declaration of declarations) {
|
|
1112
1465
|
const initializer = declaration.getInitializer();
|
|
1113
|
-
if (initializer &&
|
|
1466
|
+
if (initializer && Node9.isCallExpression(initializer)) {
|
|
1114
1467
|
const expression = initializer.getExpression();
|
|
1115
1468
|
if (expression.getText() === "pgTable") {
|
|
1116
1469
|
const tableInfo = this.parsePgTable(
|
|
@@ -1133,13 +1486,13 @@ var DrizzleSchemaParser = class {
|
|
|
1133
1486
|
}
|
|
1134
1487
|
const tableName = args[0].getText().replace(/['"]/g, "");
|
|
1135
1488
|
const fieldsArg = args[1];
|
|
1136
|
-
if (!
|
|
1489
|
+
if (!Node9.isObjectLiteralExpression(fieldsArg)) {
|
|
1137
1490
|
return null;
|
|
1138
1491
|
}
|
|
1139
1492
|
const fields = [];
|
|
1140
1493
|
const properties = fieldsArg.getProperties();
|
|
1141
1494
|
for (const prop of properties) {
|
|
1142
|
-
if (
|
|
1495
|
+
if (Node9.isPropertyAssignment(prop)) {
|
|
1143
1496
|
const fieldName = prop.getName();
|
|
1144
1497
|
const initializer = prop.getInitializer();
|
|
1145
1498
|
const leadingComments = prop.getLeadingCommentRanges();
|
|
@@ -1147,7 +1500,7 @@ var DrizzleSchemaParser = class {
|
|
|
1147
1500
|
if (leadingComments.length > 0) {
|
|
1148
1501
|
comment = leadingComments.map((c) => c.getText()).join("\n").replace(/\/\//g, "").trim();
|
|
1149
1502
|
}
|
|
1150
|
-
if (initializer &&
|
|
1503
|
+
if (initializer && Node9.isCallExpression(initializer)) {
|
|
1151
1504
|
const fieldInfo = this.parseField(fieldName, initializer, comment);
|
|
1152
1505
|
fields.push(fieldInfo);
|
|
1153
1506
|
}
|
|
@@ -1179,10 +1532,10 @@ var DrizzleSchemaParser = class {
|
|
|
1179
1532
|
parseBaseType(callExpr, fieldInfo) {
|
|
1180
1533
|
let current = callExpr;
|
|
1181
1534
|
let baseCall = null;
|
|
1182
|
-
while (
|
|
1535
|
+
while (Node9.isCallExpression(current)) {
|
|
1183
1536
|
baseCall = current;
|
|
1184
1537
|
const expression2 = current.getExpression();
|
|
1185
|
-
if (
|
|
1538
|
+
if (Node9.isPropertyAccessExpression(expression2)) {
|
|
1186
1539
|
current = expression2.getExpression();
|
|
1187
1540
|
} else {
|
|
1188
1541
|
break;
|
|
@@ -1193,7 +1546,7 @@ var DrizzleSchemaParser = class {
|
|
|
1193
1546
|
}
|
|
1194
1547
|
const expression = baseCall.getExpression();
|
|
1195
1548
|
let typeName = "";
|
|
1196
|
-
if (
|
|
1549
|
+
if (Node9.isPropertyAccessExpression(expression)) {
|
|
1197
1550
|
typeName = expression.getName();
|
|
1198
1551
|
} else {
|
|
1199
1552
|
typeName = expression.getText();
|
|
@@ -1202,25 +1555,25 @@ var DrizzleSchemaParser = class {
|
|
|
1202
1555
|
const args = baseCall.getArguments();
|
|
1203
1556
|
if (args.length > 0) {
|
|
1204
1557
|
const firstArg = args[0];
|
|
1205
|
-
if (
|
|
1558
|
+
if (Node9.isStringLiteral(firstArg)) {
|
|
1206
1559
|
fieldInfo.columnName = firstArg.getLiteralText();
|
|
1207
|
-
} else if (
|
|
1560
|
+
} else if (Node9.isObjectLiteralExpression(firstArg)) {
|
|
1208
1561
|
this.parseTypeConfig(firstArg, fieldInfo);
|
|
1209
|
-
} else if (
|
|
1562
|
+
} else if (Node9.isArrayLiteralExpression(firstArg)) {
|
|
1210
1563
|
fieldInfo.enumValues = firstArg.getElements().map((el) => el.getText().replace(/['"]/g, ""));
|
|
1211
1564
|
}
|
|
1212
1565
|
}
|
|
1213
|
-
if (args.length > 1 &&
|
|
1566
|
+
if (args.length > 1 && Node9.isObjectLiteralExpression(args[1])) {
|
|
1214
1567
|
this.parseTypeConfig(args[1], fieldInfo);
|
|
1215
1568
|
}
|
|
1216
1569
|
}
|
|
1217
1570
|
parseTypeConfig(objLiteral, fieldInfo) {
|
|
1218
|
-
if (!
|
|
1571
|
+
if (!Node9.isObjectLiteralExpression(objLiteral)) {
|
|
1219
1572
|
return;
|
|
1220
1573
|
}
|
|
1221
1574
|
const properties = objLiteral.getProperties();
|
|
1222
1575
|
for (const prop of properties) {
|
|
1223
|
-
if (
|
|
1576
|
+
if (Node9.isPropertyAssignment(prop)) {
|
|
1224
1577
|
const propName = prop.getName();
|
|
1225
1578
|
const value = prop.getInitializer()?.getText();
|
|
1226
1579
|
switch (propName) {
|
|
@@ -1252,9 +1605,9 @@ var DrizzleSchemaParser = class {
|
|
|
1252
1605
|
}
|
|
1253
1606
|
parseCallChain(callExpr, fieldInfo) {
|
|
1254
1607
|
let current = callExpr;
|
|
1255
|
-
while (
|
|
1608
|
+
while (Node9.isCallExpression(current)) {
|
|
1256
1609
|
const expression = current.getExpression();
|
|
1257
|
-
if (
|
|
1610
|
+
if (Node9.isPropertyAccessExpression(expression)) {
|
|
1258
1611
|
const methodName = expression.getName();
|
|
1259
1612
|
const args = current.getArguments();
|
|
1260
1613
|
switch (methodName) {
|
|
@@ -1351,7 +1704,7 @@ var require2 = createRequire(import.meta.url);
|
|
|
1351
1704
|
async function run(options = {}) {
|
|
1352
1705
|
let exitCode = 0;
|
|
1353
1706
|
const envPath2 = path2.resolve(process.cwd(), ".env");
|
|
1354
|
-
if (
|
|
1707
|
+
if (fs4.existsSync(envPath2)) {
|
|
1355
1708
|
loadEnv({ path: envPath2 });
|
|
1356
1709
|
console.log("[gen-db-schema] \u2713 Loaded .env file");
|
|
1357
1710
|
}
|
|
@@ -1371,7 +1724,7 @@ async function run(options = {}) {
|
|
|
1371
1724
|
path2.resolve(__dirname2, "../../config/drizzle.config.js"),
|
|
1372
1725
|
path2.resolve(__dirname2, "../../../dist/config/drizzle.config.js")
|
|
1373
1726
|
];
|
|
1374
|
-
const configPath = configPathCandidates.find((p) =>
|
|
1727
|
+
const configPath = configPathCandidates.find((p) => fs4.existsSync(p));
|
|
1375
1728
|
console.log("[gen-db-schema] Using drizzle config from:", configPath ?? "(not found)");
|
|
1376
1729
|
if (!configPath) {
|
|
1377
1730
|
console.error("[gen-db-schema] Error: drizzle config not found in CLI package");
|
|
@@ -1383,8 +1736,8 @@ async function run(options = {}) {
|
|
|
1383
1736
|
let lastDir = null;
|
|
1384
1737
|
while (currentDir !== lastDir) {
|
|
1385
1738
|
const pkgJsonPath = path2.join(currentDir, "package.json");
|
|
1386
|
-
if (
|
|
1387
|
-
const pkgJsonRaw =
|
|
1739
|
+
if (fs4.existsSync(pkgJsonPath)) {
|
|
1740
|
+
const pkgJsonRaw = fs4.readFileSync(pkgJsonPath, "utf8");
|
|
1388
1741
|
const pkgJson = JSON.parse(pkgJsonRaw);
|
|
1389
1742
|
if (pkgJson.name === "drizzle-kit") {
|
|
1390
1743
|
const binField = pkgJson.bin;
|
|
@@ -1419,7 +1772,7 @@ async function run(options = {}) {
|
|
|
1419
1772
|
throw new Error(`drizzle-kit introspect failed with status ${result.status}`);
|
|
1420
1773
|
}
|
|
1421
1774
|
const generatedSchema = path2.join(OUT_DIR, "schema.ts");
|
|
1422
|
-
if (!
|
|
1775
|
+
if (!fs4.existsSync(generatedSchema)) {
|
|
1423
1776
|
console.error("[gen-db-schema] schema.ts not generated");
|
|
1424
1777
|
throw new Error("drizzle-kit introspect failed to generate schema.ts");
|
|
1425
1778
|
}
|
|
@@ -1428,8 +1781,8 @@ async function run(options = {}) {
|
|
|
1428
1781
|
console.warn("[gen-db-schema] Unmatched custom types detected:", stats.unmatchedUnknown);
|
|
1429
1782
|
}
|
|
1430
1783
|
console.log("[gen-db-schema] \u2713 Postprocessed schema");
|
|
1431
|
-
|
|
1432
|
-
|
|
1784
|
+
fs4.mkdirSync(path2.dirname(SCHEMA_FILE), { recursive: true });
|
|
1785
|
+
fs4.copyFileSync(generatedSchema, SCHEMA_FILE);
|
|
1433
1786
|
console.log(`[gen-db-schema] \u2713 Copied to ${outputPath}`);
|
|
1434
1787
|
try {
|
|
1435
1788
|
if (options.enableNestModuleGenerate) {
|
|
@@ -1450,8 +1803,8 @@ async function run(options = {}) {
|
|
|
1450
1803
|
console.error("[gen-db-schema] Failed:", err instanceof Error ? err.message : String(err));
|
|
1451
1804
|
exitCode = 1;
|
|
1452
1805
|
} finally {
|
|
1453
|
-
if (
|
|
1454
|
-
|
|
1806
|
+
if (fs4.existsSync(OUT_DIR)) {
|
|
1807
|
+
fs4.rmSync(OUT_DIR, { recursive: true, force: true });
|
|
1455
1808
|
}
|
|
1456
1809
|
process.exit(exitCode);
|
|
1457
1810
|
}
|
|
@@ -1470,7 +1823,7 @@ var genDbSchemaCommand = {
|
|
|
1470
1823
|
|
|
1471
1824
|
// src/commands/sync/run.handler.ts
|
|
1472
1825
|
import path4 from "path";
|
|
1473
|
-
import
|
|
1826
|
+
import fs6 from "fs";
|
|
1474
1827
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
1475
1828
|
|
|
1476
1829
|
// src/config/sync.ts
|
|
@@ -1534,14 +1887,14 @@ function genSyncConfig(perms = {}) {
|
|
|
1534
1887
|
}
|
|
1535
1888
|
|
|
1536
1889
|
// src/utils/file-ops.ts
|
|
1537
|
-
import
|
|
1890
|
+
import fs5 from "fs";
|
|
1538
1891
|
import path3 from "path";
|
|
1539
1892
|
function removeLineFromFile(filePath, pattern) {
|
|
1540
|
-
if (!
|
|
1893
|
+
if (!fs5.existsSync(filePath)) {
|
|
1541
1894
|
console.log(`[fullstack-cli] \u25CB ${path3.basename(filePath)} (not found)`);
|
|
1542
1895
|
return false;
|
|
1543
1896
|
}
|
|
1544
|
-
const content =
|
|
1897
|
+
const content = fs5.readFileSync(filePath, "utf-8");
|
|
1545
1898
|
const lines = content.split("\n");
|
|
1546
1899
|
const trimmedPattern = pattern.trim();
|
|
1547
1900
|
const filteredLines = lines.filter((line) => line.trim() !== trimmedPattern);
|
|
@@ -1549,7 +1902,7 @@ function removeLineFromFile(filePath, pattern) {
|
|
|
1549
1902
|
console.log(`[fullstack-cli] \u25CB ${path3.basename(filePath)} (pattern not found: ${pattern})`);
|
|
1550
1903
|
return false;
|
|
1551
1904
|
}
|
|
1552
|
-
|
|
1905
|
+
fs5.writeFileSync(filePath, filteredLines.join("\n"));
|
|
1553
1906
|
console.log(`[fullstack-cli] \u2713 ${path3.basename(filePath)} (removed: ${pattern})`);
|
|
1554
1907
|
return true;
|
|
1555
1908
|
}
|
|
@@ -1565,7 +1918,7 @@ async function run2(options) {
|
|
|
1565
1918
|
process.exit(0);
|
|
1566
1919
|
}
|
|
1567
1920
|
const userPackageJson = path4.join(userProjectRoot, "package.json");
|
|
1568
|
-
if (!
|
|
1921
|
+
if (!fs6.existsSync(userPackageJson)) {
|
|
1569
1922
|
console.log("[fullstack-cli] Skip syncing (not a valid npm project)");
|
|
1570
1923
|
process.exit(0);
|
|
1571
1924
|
}
|
|
@@ -1611,7 +1964,7 @@ async function syncRule(rule, pluginRoot, userProjectRoot) {
|
|
|
1611
1964
|
}
|
|
1612
1965
|
const srcPath = path4.join(pluginRoot, rule.from);
|
|
1613
1966
|
const destPath = path4.join(userProjectRoot, rule.to);
|
|
1614
|
-
if (!
|
|
1967
|
+
if (!fs6.existsSync(srcPath)) {
|
|
1615
1968
|
console.warn(`[fullstack-cli] Source not found: ${rule.from}`);
|
|
1616
1969
|
return;
|
|
1617
1970
|
}
|
|
@@ -1629,31 +1982,31 @@ async function syncRule(rule, pluginRoot, userProjectRoot) {
|
|
|
1629
1982
|
}
|
|
1630
1983
|
function syncFile(src, dest, overwrite = true) {
|
|
1631
1984
|
const destDir = path4.dirname(dest);
|
|
1632
|
-
if (!
|
|
1633
|
-
|
|
1985
|
+
if (!fs6.existsSync(destDir)) {
|
|
1986
|
+
fs6.mkdirSync(destDir, { recursive: true });
|
|
1634
1987
|
}
|
|
1635
|
-
if (
|
|
1988
|
+
if (fs6.existsSync(dest) && !overwrite) {
|
|
1636
1989
|
console.log(`[fullstack-cli] \u25CB ${path4.basename(dest)} (skipped, already exists)`);
|
|
1637
1990
|
return;
|
|
1638
1991
|
}
|
|
1639
|
-
|
|
1992
|
+
fs6.copyFileSync(src, dest);
|
|
1640
1993
|
console.log(`[fullstack-cli] \u2713 ${path4.basename(dest)}`);
|
|
1641
1994
|
}
|
|
1642
1995
|
function syncDirectory(src, dest, overwrite = true) {
|
|
1643
|
-
if (!
|
|
1644
|
-
|
|
1996
|
+
if (!fs6.existsSync(dest)) {
|
|
1997
|
+
fs6.mkdirSync(dest, { recursive: true });
|
|
1645
1998
|
}
|
|
1646
|
-
const files =
|
|
1999
|
+
const files = fs6.readdirSync(src);
|
|
1647
2000
|
let count = 0;
|
|
1648
2001
|
files.forEach((file) => {
|
|
1649
2002
|
const srcFile = path4.join(src, file);
|
|
1650
2003
|
const destFile = path4.join(dest, file);
|
|
1651
|
-
const stats =
|
|
2004
|
+
const stats = fs6.statSync(srcFile);
|
|
1652
2005
|
if (stats.isDirectory()) {
|
|
1653
2006
|
syncDirectory(srcFile, destFile, overwrite);
|
|
1654
2007
|
} else {
|
|
1655
|
-
if (overwrite || !
|
|
1656
|
-
|
|
2008
|
+
if (overwrite || !fs6.existsSync(destFile)) {
|
|
2009
|
+
fs6.copyFileSync(srcFile, destFile);
|
|
1657
2010
|
console.log(`[fullstack-cli] \u2713 ${path4.relative(dest, destFile)}`);
|
|
1658
2011
|
count++;
|
|
1659
2012
|
}
|
|
@@ -1664,28 +2017,28 @@ function syncDirectory(src, dest, overwrite = true) {
|
|
|
1664
2017
|
}
|
|
1665
2018
|
}
|
|
1666
2019
|
function appendToFile(src, dest) {
|
|
1667
|
-
const content =
|
|
2020
|
+
const content = fs6.readFileSync(src, "utf-8");
|
|
1668
2021
|
let existingContent = "";
|
|
1669
|
-
if (
|
|
1670
|
-
existingContent =
|
|
2022
|
+
if (fs6.existsSync(dest)) {
|
|
2023
|
+
existingContent = fs6.readFileSync(dest, "utf-8");
|
|
1671
2024
|
}
|
|
1672
2025
|
if (existingContent.includes(content.trim())) {
|
|
1673
2026
|
console.log(`[fullstack-cli] \u25CB ${path4.basename(dest)} (already contains content)`);
|
|
1674
2027
|
return;
|
|
1675
2028
|
}
|
|
1676
|
-
|
|
2029
|
+
fs6.appendFileSync(dest, content);
|
|
1677
2030
|
console.log(`[fullstack-cli] \u2713 ${path4.basename(dest)} (appended)`);
|
|
1678
2031
|
}
|
|
1679
2032
|
function setPermissions(permissions, projectRoot) {
|
|
1680
2033
|
for (const [pattern, mode] of Object.entries(permissions)) {
|
|
1681
2034
|
if (pattern === "**/*.sh") {
|
|
1682
2035
|
const scriptsDir = path4.join(projectRoot, "scripts");
|
|
1683
|
-
if (
|
|
1684
|
-
const files =
|
|
2036
|
+
if (fs6.existsSync(scriptsDir)) {
|
|
2037
|
+
const files = fs6.readdirSync(scriptsDir);
|
|
1685
2038
|
files.forEach((file) => {
|
|
1686
2039
|
if (file.endsWith(".sh")) {
|
|
1687
2040
|
const filePath = path4.join(scriptsDir, file);
|
|
1688
|
-
|
|
2041
|
+
fs6.chmodSync(filePath, mode);
|
|
1689
2042
|
}
|
|
1690
2043
|
});
|
|
1691
2044
|
}
|
|
@@ -1693,16 +2046,16 @@ function setPermissions(permissions, projectRoot) {
|
|
|
1693
2046
|
}
|
|
1694
2047
|
}
|
|
1695
2048
|
function deleteFile(filePath) {
|
|
1696
|
-
if (
|
|
1697
|
-
|
|
2049
|
+
if (fs6.existsSync(filePath)) {
|
|
2050
|
+
fs6.unlinkSync(filePath);
|
|
1698
2051
|
console.log(`[fullstack-cli] \u2713 ${path4.basename(filePath)} (deleted)`);
|
|
1699
2052
|
} else {
|
|
1700
2053
|
console.log(`[fullstack-cli] \u25CB ${path4.basename(filePath)} (not found)`);
|
|
1701
2054
|
}
|
|
1702
2055
|
}
|
|
1703
2056
|
function deleteDirectory(dirPath) {
|
|
1704
|
-
if (
|
|
1705
|
-
|
|
2057
|
+
if (fs6.existsSync(dirPath)) {
|
|
2058
|
+
fs6.rmSync(dirPath, { recursive: true });
|
|
1706
2059
|
console.log(`[fullstack-cli] \u2713 ${path4.basename(dirPath)} (deleted)`);
|
|
1707
2060
|
} else {
|
|
1708
2061
|
console.log(`[fullstack-cli] \u25CB ${path4.basename(dirPath)} (not found)`);
|
|
@@ -1721,7 +2074,7 @@ var syncCommand = {
|
|
|
1721
2074
|
};
|
|
1722
2075
|
|
|
1723
2076
|
// src/commands/action-plugin/utils.ts
|
|
1724
|
-
import
|
|
2077
|
+
import fs7 from "fs";
|
|
1725
2078
|
import path5 from "path";
|
|
1726
2079
|
import { spawnSync as spawnSync2, execSync } from "child_process";
|
|
1727
2080
|
function parsePluginName(input) {
|
|
@@ -1747,11 +2100,11 @@ function getPluginPath(pluginName) {
|
|
|
1747
2100
|
}
|
|
1748
2101
|
function readPackageJson() {
|
|
1749
2102
|
const pkgPath = getPackageJsonPath();
|
|
1750
|
-
if (!
|
|
2103
|
+
if (!fs7.existsSync(pkgPath)) {
|
|
1751
2104
|
throw new Error("package.json not found in current directory");
|
|
1752
2105
|
}
|
|
1753
2106
|
try {
|
|
1754
|
-
const content =
|
|
2107
|
+
const content = fs7.readFileSync(pkgPath, "utf-8");
|
|
1755
2108
|
return JSON.parse(content);
|
|
1756
2109
|
} catch {
|
|
1757
2110
|
throw new Error("Failed to parse package.json");
|
|
@@ -1759,7 +2112,7 @@ function readPackageJson() {
|
|
|
1759
2112
|
}
|
|
1760
2113
|
function writePackageJson(pkg2) {
|
|
1761
2114
|
const pkgPath = getPackageJsonPath();
|
|
1762
|
-
|
|
2115
|
+
fs7.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
|
|
1763
2116
|
}
|
|
1764
2117
|
function readActionPlugins() {
|
|
1765
2118
|
const pkg2 = readPackageJson();
|
|
@@ -1793,11 +2146,11 @@ function npmInstall(tgzPath) {
|
|
|
1793
2146
|
}
|
|
1794
2147
|
function getPackageVersion(pluginName) {
|
|
1795
2148
|
const pkgJsonPath = path5.join(getPluginPath(pluginName), "package.json");
|
|
1796
|
-
if (!
|
|
2149
|
+
if (!fs7.existsSync(pkgJsonPath)) {
|
|
1797
2150
|
return null;
|
|
1798
2151
|
}
|
|
1799
2152
|
try {
|
|
1800
|
-
const content =
|
|
2153
|
+
const content = fs7.readFileSync(pkgJsonPath, "utf-8");
|
|
1801
2154
|
const pkg2 = JSON.parse(content);
|
|
1802
2155
|
return pkg2.version || null;
|
|
1803
2156
|
} catch {
|
|
@@ -1806,11 +2159,11 @@ function getPackageVersion(pluginName) {
|
|
|
1806
2159
|
}
|
|
1807
2160
|
function readPluginPackageJson(pluginPath) {
|
|
1808
2161
|
const pkgJsonPath = path5.join(pluginPath, "package.json");
|
|
1809
|
-
if (!
|
|
2162
|
+
if (!fs7.existsSync(pkgJsonPath)) {
|
|
1810
2163
|
return null;
|
|
1811
2164
|
}
|
|
1812
2165
|
try {
|
|
1813
|
-
const content =
|
|
2166
|
+
const content = fs7.readFileSync(pkgJsonPath, "utf-8");
|
|
1814
2167
|
return JSON.parse(content);
|
|
1815
2168
|
} catch {
|
|
1816
2169
|
return null;
|
|
@@ -1820,34 +2173,34 @@ function extractTgzToNodeModules(tgzPath, pluginName) {
|
|
|
1820
2173
|
const nodeModulesPath = path5.join(getProjectRoot(), "node_modules");
|
|
1821
2174
|
const targetDir = path5.join(nodeModulesPath, pluginName);
|
|
1822
2175
|
const scopeDir = path5.dirname(targetDir);
|
|
1823
|
-
if (!
|
|
1824
|
-
|
|
2176
|
+
if (!fs7.existsSync(scopeDir)) {
|
|
2177
|
+
fs7.mkdirSync(scopeDir, { recursive: true });
|
|
1825
2178
|
}
|
|
1826
|
-
if (
|
|
1827
|
-
|
|
2179
|
+
if (fs7.existsSync(targetDir)) {
|
|
2180
|
+
fs7.rmSync(targetDir, { recursive: true });
|
|
1828
2181
|
}
|
|
1829
2182
|
const tempDir = path5.join(nodeModulesPath, ".cache", "fullstack-cli", "extract-temp");
|
|
1830
|
-
if (
|
|
1831
|
-
|
|
2183
|
+
if (fs7.existsSync(tempDir)) {
|
|
2184
|
+
fs7.rmSync(tempDir, { recursive: true });
|
|
1832
2185
|
}
|
|
1833
|
-
|
|
2186
|
+
fs7.mkdirSync(tempDir, { recursive: true });
|
|
1834
2187
|
try {
|
|
1835
2188
|
execSync(`tar -xzf "${tgzPath}" -C "${tempDir}"`, { stdio: "pipe" });
|
|
1836
2189
|
const extractedDir = path5.join(tempDir, "package");
|
|
1837
|
-
if (
|
|
1838
|
-
|
|
2190
|
+
if (fs7.existsSync(extractedDir)) {
|
|
2191
|
+
fs7.renameSync(extractedDir, targetDir);
|
|
1839
2192
|
} else {
|
|
1840
|
-
const files =
|
|
2193
|
+
const files = fs7.readdirSync(tempDir);
|
|
1841
2194
|
if (files.length === 1) {
|
|
1842
|
-
|
|
2195
|
+
fs7.renameSync(path5.join(tempDir, files[0]), targetDir);
|
|
1843
2196
|
} else {
|
|
1844
2197
|
throw new Error("Unexpected tgz structure");
|
|
1845
2198
|
}
|
|
1846
2199
|
}
|
|
1847
2200
|
return targetDir;
|
|
1848
2201
|
} finally {
|
|
1849
|
-
if (
|
|
1850
|
-
|
|
2202
|
+
if (fs7.existsSync(tempDir)) {
|
|
2203
|
+
fs7.rmSync(tempDir, { recursive: true });
|
|
1851
2204
|
}
|
|
1852
2205
|
}
|
|
1853
2206
|
}
|
|
@@ -1859,7 +2212,7 @@ function checkMissingPeerDeps(peerDeps) {
|
|
|
1859
2212
|
const nodeModulesPath = path5.join(getProjectRoot(), "node_modules");
|
|
1860
2213
|
for (const [depName, _version] of Object.entries(peerDeps)) {
|
|
1861
2214
|
const depPath = path5.join(nodeModulesPath, depName);
|
|
1862
|
-
if (!
|
|
2215
|
+
if (!fs7.existsSync(depPath)) {
|
|
1863
2216
|
missing.push(depName);
|
|
1864
2217
|
}
|
|
1865
2218
|
}
|
|
@@ -1883,15 +2236,15 @@ function installMissingDeps(deps) {
|
|
|
1883
2236
|
}
|
|
1884
2237
|
function removePluginDirectory(pluginName) {
|
|
1885
2238
|
const pluginPath = getPluginPath(pluginName);
|
|
1886
|
-
if (
|
|
1887
|
-
|
|
2239
|
+
if (fs7.existsSync(pluginPath)) {
|
|
2240
|
+
fs7.rmSync(pluginPath, { recursive: true });
|
|
1888
2241
|
console.log(`[action-plugin] Removed ${pluginName}`);
|
|
1889
2242
|
}
|
|
1890
2243
|
}
|
|
1891
2244
|
|
|
1892
2245
|
// src/commands/action-plugin/api-client.ts
|
|
1893
2246
|
import { HttpClient as HttpClient2 } from "@lark-apaas/http-client";
|
|
1894
|
-
import
|
|
2247
|
+
import fs8 from "fs";
|
|
1895
2248
|
import path6 from "path";
|
|
1896
2249
|
|
|
1897
2250
|
// src/utils/http-client.ts
|
|
@@ -1984,8 +2337,8 @@ function getPluginCacheDir() {
|
|
|
1984
2337
|
}
|
|
1985
2338
|
function ensureCacheDir() {
|
|
1986
2339
|
const cacheDir = getPluginCacheDir();
|
|
1987
|
-
if (!
|
|
1988
|
-
|
|
2340
|
+
if (!fs8.existsSync(cacheDir)) {
|
|
2341
|
+
fs8.mkdirSync(cacheDir, { recursive: true });
|
|
1989
2342
|
}
|
|
1990
2343
|
}
|
|
1991
2344
|
function getTempFilePath(pluginKey, version) {
|
|
@@ -2008,7 +2361,7 @@ async function downloadPlugin(pluginKey, requestedVersion) {
|
|
|
2008
2361
|
tgzBuffer = await downloadFromPublic(pluginInfo.downloadURL);
|
|
2009
2362
|
}
|
|
2010
2363
|
const tgzPath = getTempFilePath(pluginKey, pluginInfo.version);
|
|
2011
|
-
|
|
2364
|
+
fs8.writeFileSync(tgzPath, tgzBuffer);
|
|
2012
2365
|
console.log(`[action-plugin] Downloaded to ${tgzPath} (${(tgzBuffer.length / 1024).toFixed(2)} KB)`);
|
|
2013
2366
|
return {
|
|
2014
2367
|
tgzPath,
|
|
@@ -2018,8 +2371,8 @@ async function downloadPlugin(pluginKey, requestedVersion) {
|
|
|
2018
2371
|
}
|
|
2019
2372
|
function cleanupTempFile(tgzPath) {
|
|
2020
2373
|
try {
|
|
2021
|
-
if (
|
|
2022
|
-
|
|
2374
|
+
if (fs8.existsSync(tgzPath)) {
|
|
2375
|
+
fs8.unlinkSync(tgzPath);
|
|
2023
2376
|
}
|
|
2024
2377
|
} catch {
|
|
2025
2378
|
}
|
|
@@ -2355,7 +2708,7 @@ var actionPluginCommandGroup = {
|
|
|
2355
2708
|
};
|
|
2356
2709
|
|
|
2357
2710
|
// src/commands/capability/utils.ts
|
|
2358
|
-
import
|
|
2711
|
+
import fs9 from "fs";
|
|
2359
2712
|
import path7 from "path";
|
|
2360
2713
|
var CAPABILITIES_DIR = "server/capabilities";
|
|
2361
2714
|
function getProjectRoot2() {
|
|
@@ -2371,23 +2724,23 @@ function getPluginManifestPath(pluginKey) {
|
|
|
2371
2724
|
return path7.join(getProjectRoot2(), "node_modules", pluginKey, "manifest.json");
|
|
2372
2725
|
}
|
|
2373
2726
|
function capabilitiesDirExists() {
|
|
2374
|
-
return
|
|
2727
|
+
return fs9.existsSync(getCapabilitiesDir());
|
|
2375
2728
|
}
|
|
2376
2729
|
function listCapabilityIds() {
|
|
2377
2730
|
const dir = getCapabilitiesDir();
|
|
2378
|
-
if (!
|
|
2731
|
+
if (!fs9.existsSync(dir)) {
|
|
2379
2732
|
return [];
|
|
2380
2733
|
}
|
|
2381
|
-
const files =
|
|
2734
|
+
const files = fs9.readdirSync(dir);
|
|
2382
2735
|
return files.filter((f) => f.endsWith(".json") && f !== "capabilities.json").map((f) => f.replace(/\.json$/, ""));
|
|
2383
2736
|
}
|
|
2384
2737
|
function readCapability(id) {
|
|
2385
2738
|
const filePath = getCapabilityPath(id);
|
|
2386
|
-
if (!
|
|
2739
|
+
if (!fs9.existsSync(filePath)) {
|
|
2387
2740
|
throw new Error(`Capability not found: ${id}`);
|
|
2388
2741
|
}
|
|
2389
2742
|
try {
|
|
2390
|
-
const content =
|
|
2743
|
+
const content = fs9.readFileSync(filePath, "utf-8");
|
|
2391
2744
|
return JSON.parse(content);
|
|
2392
2745
|
} catch (error) {
|
|
2393
2746
|
if (error instanceof SyntaxError) {
|
|
@@ -2414,11 +2767,11 @@ function readAllCapabilities() {
|
|
|
2414
2767
|
}
|
|
2415
2768
|
function readPluginManifest(pluginKey) {
|
|
2416
2769
|
const manifestPath = getPluginManifestPath(pluginKey);
|
|
2417
|
-
if (!
|
|
2770
|
+
if (!fs9.existsSync(manifestPath)) {
|
|
2418
2771
|
throw new Error(`Plugin not installed: ${pluginKey} (manifest.json not found)`);
|
|
2419
2772
|
}
|
|
2420
2773
|
try {
|
|
2421
|
-
const content =
|
|
2774
|
+
const content = fs9.readFileSync(manifestPath, "utf-8");
|
|
2422
2775
|
return JSON.parse(content);
|
|
2423
2776
|
} catch (error) {
|
|
2424
2777
|
if (error instanceof SyntaxError) {
|
|
@@ -2592,7 +2945,7 @@ var capabilityCommandGroup = {
|
|
|
2592
2945
|
};
|
|
2593
2946
|
|
|
2594
2947
|
// src/commands/migration/version-manager.ts
|
|
2595
|
-
import
|
|
2948
|
+
import fs10 from "fs";
|
|
2596
2949
|
import path8 from "path";
|
|
2597
2950
|
var PACKAGE_JSON = "package.json";
|
|
2598
2951
|
var VERSION_FIELD = "migrationVersion";
|
|
@@ -2601,25 +2954,25 @@ function getPackageJsonPath2() {
|
|
|
2601
2954
|
}
|
|
2602
2955
|
function getCurrentVersion() {
|
|
2603
2956
|
const pkgPath = getPackageJsonPath2();
|
|
2604
|
-
if (!
|
|
2957
|
+
if (!fs10.existsSync(pkgPath)) {
|
|
2605
2958
|
throw new Error("package.json not found");
|
|
2606
2959
|
}
|
|
2607
|
-
const pkg2 = JSON.parse(
|
|
2960
|
+
const pkg2 = JSON.parse(fs10.readFileSync(pkgPath, "utf-8"));
|
|
2608
2961
|
return pkg2[VERSION_FIELD] ?? 0;
|
|
2609
2962
|
}
|
|
2610
2963
|
function setCurrentVersion(version) {
|
|
2611
2964
|
const pkgPath = getPackageJsonPath2();
|
|
2612
|
-
const pkg2 = JSON.parse(
|
|
2965
|
+
const pkg2 = JSON.parse(fs10.readFileSync(pkgPath, "utf-8"));
|
|
2613
2966
|
pkg2[VERSION_FIELD] = version;
|
|
2614
|
-
|
|
2967
|
+
fs10.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
|
|
2615
2968
|
}
|
|
2616
2969
|
|
|
2617
2970
|
// src/commands/migration/versions/v001_capability/json-migrator/detector.ts
|
|
2618
|
-
import
|
|
2971
|
+
import fs12 from "fs";
|
|
2619
2972
|
import path10 from "path";
|
|
2620
2973
|
|
|
2621
2974
|
// src/commands/migration/versions/v001_capability/utils.ts
|
|
2622
|
-
import
|
|
2975
|
+
import fs11 from "fs";
|
|
2623
2976
|
import path9 from "path";
|
|
2624
2977
|
var CAPABILITIES_DIR2 = "server/capabilities";
|
|
2625
2978
|
function getProjectRoot3() {
|
|
@@ -2636,14 +2989,14 @@ function getPluginManifestPath2(pluginKey) {
|
|
|
2636
2989
|
function detectJsonMigration() {
|
|
2637
2990
|
const capabilitiesDir = getCapabilitiesDir2();
|
|
2638
2991
|
const oldFilePath = path10.join(capabilitiesDir, "capabilities.json");
|
|
2639
|
-
if (!
|
|
2992
|
+
if (!fs12.existsSync(oldFilePath)) {
|
|
2640
2993
|
return {
|
|
2641
2994
|
needsMigration: false,
|
|
2642
2995
|
reason: "capabilities.json not found"
|
|
2643
2996
|
};
|
|
2644
2997
|
}
|
|
2645
2998
|
try {
|
|
2646
|
-
const content =
|
|
2999
|
+
const content = fs12.readFileSync(oldFilePath, "utf-8");
|
|
2647
3000
|
const parsed = JSON.parse(content);
|
|
2648
3001
|
if (!Array.isArray(parsed)) {
|
|
2649
3002
|
return {
|
|
@@ -2694,7 +3047,7 @@ async function check(options) {
|
|
|
2694
3047
|
}
|
|
2695
3048
|
|
|
2696
3049
|
// src/commands/migration/versions/v001_capability/json-migrator/index.ts
|
|
2697
|
-
import
|
|
3050
|
+
import fs13 from "fs";
|
|
2698
3051
|
import path11 from "path";
|
|
2699
3052
|
|
|
2700
3053
|
// src/commands/migration/versions/v001_capability/mapping.ts
|
|
@@ -2925,10 +3278,10 @@ function transformCapabilities(oldCapabilities) {
|
|
|
2925
3278
|
// src/commands/migration/versions/v001_capability/json-migrator/index.ts
|
|
2926
3279
|
function loadExistingCapabilities() {
|
|
2927
3280
|
const capabilitiesDir = getCapabilitiesDir2();
|
|
2928
|
-
if (!
|
|
3281
|
+
if (!fs13.existsSync(capabilitiesDir)) {
|
|
2929
3282
|
return [];
|
|
2930
3283
|
}
|
|
2931
|
-
const files =
|
|
3284
|
+
const files = fs13.readdirSync(capabilitiesDir);
|
|
2932
3285
|
const capabilities = [];
|
|
2933
3286
|
for (const file of files) {
|
|
2934
3287
|
if (file === "capabilities.json" || !file.endsWith(".json")) {
|
|
@@ -2936,7 +3289,7 @@ function loadExistingCapabilities() {
|
|
|
2936
3289
|
}
|
|
2937
3290
|
try {
|
|
2938
3291
|
const filePath = path11.join(capabilitiesDir, file);
|
|
2939
|
-
const content =
|
|
3292
|
+
const content = fs13.readFileSync(filePath, "utf-8");
|
|
2940
3293
|
const capability = JSON.parse(content);
|
|
2941
3294
|
if (capability.id && capability.pluginKey) {
|
|
2942
3295
|
capabilities.push(capability);
|
|
@@ -2996,7 +3349,7 @@ async function migrateJsonFiles(options) {
|
|
|
2996
3349
|
for (const cap of newCapabilities) {
|
|
2997
3350
|
const filePath = path11.join(capabilitiesDir, `${cap.id}.json`);
|
|
2998
3351
|
const content = JSON.stringify(cap, null, 2);
|
|
2999
|
-
|
|
3352
|
+
fs13.writeFileSync(filePath, content, "utf-8");
|
|
3000
3353
|
console.log(` \u2713 Created: ${cap.id}.json`);
|
|
3001
3354
|
}
|
|
3002
3355
|
return {
|
|
@@ -3008,11 +3361,11 @@ async function migrateJsonFiles(options) {
|
|
|
3008
3361
|
}
|
|
3009
3362
|
|
|
3010
3363
|
// src/commands/migration/versions/v001_capability/plugin-installer/detector.ts
|
|
3011
|
-
import
|
|
3364
|
+
import fs14 from "fs";
|
|
3012
3365
|
function isPluginInstalled2(pluginKey) {
|
|
3013
3366
|
const actionPlugins = readActionPlugins();
|
|
3014
3367
|
const manifestPath = getPluginManifestPath2(pluginKey);
|
|
3015
|
-
return
|
|
3368
|
+
return fs14.existsSync(manifestPath) && !!actionPlugins[pluginKey];
|
|
3016
3369
|
}
|
|
3017
3370
|
function detectPluginsToInstall(capabilities) {
|
|
3018
3371
|
const pluginKeys = /* @__PURE__ */ new Set();
|
|
@@ -3089,10 +3442,10 @@ async function installPlugins(capabilities, options) {
|
|
|
3089
3442
|
|
|
3090
3443
|
// src/commands/migration/versions/v001_capability/code-migrator/index.ts
|
|
3091
3444
|
import path13 from "path";
|
|
3092
|
-
import { Project as
|
|
3445
|
+
import { Project as Project3 } from "ts-morph";
|
|
3093
3446
|
|
|
3094
3447
|
// src/commands/migration/versions/v001_capability/code-migrator/scanner.ts
|
|
3095
|
-
import
|
|
3448
|
+
import fs15 from "fs";
|
|
3096
3449
|
import path12 from "path";
|
|
3097
3450
|
var EXCLUDED_DIRS = [
|
|
3098
3451
|
"node_modules",
|
|
@@ -3108,7 +3461,7 @@ var EXCLUDED_PATTERNS = [
|
|
|
3108
3461
|
/\.d\.ts$/
|
|
3109
3462
|
];
|
|
3110
3463
|
function scanDirectory(dir, files = []) {
|
|
3111
|
-
const entries =
|
|
3464
|
+
const entries = fs15.readdirSync(dir, { withFileTypes: true });
|
|
3112
3465
|
for (const entry of entries) {
|
|
3113
3466
|
const fullPath = path12.join(dir, entry.name);
|
|
3114
3467
|
if (entry.isDirectory()) {
|
|
@@ -3127,13 +3480,13 @@ function scanDirectory(dir, files = []) {
|
|
|
3127
3480
|
}
|
|
3128
3481
|
function scanServerFiles() {
|
|
3129
3482
|
const serverDir = path12.join(getProjectRoot3(), "server");
|
|
3130
|
-
if (!
|
|
3483
|
+
if (!fs15.existsSync(serverDir)) {
|
|
3131
3484
|
return [];
|
|
3132
3485
|
}
|
|
3133
3486
|
return scanDirectory(serverDir);
|
|
3134
3487
|
}
|
|
3135
3488
|
function hasCapabilityImport(filePath) {
|
|
3136
|
-
const content =
|
|
3489
|
+
const content = fs15.readFileSync(filePath, "utf-8");
|
|
3137
3490
|
return /import\s+.*from\s+['"][^'"]*capabilities[^'"]*['"]/.test(content);
|
|
3138
3491
|
}
|
|
3139
3492
|
function scanFilesToMigrate() {
|
|
@@ -3197,17 +3550,17 @@ function analyzeImports(sourceFile) {
|
|
|
3197
3550
|
}
|
|
3198
3551
|
|
|
3199
3552
|
// src/commands/migration/versions/v001_capability/code-migrator/analyzers/call-site-analyzer.ts
|
|
3200
|
-
import { SyntaxKind } from "ts-morph";
|
|
3553
|
+
import { SyntaxKind as SyntaxKind6 } from "ts-morph";
|
|
3201
3554
|
function analyzeCallSites(sourceFile, imports) {
|
|
3202
3555
|
const callSites = [];
|
|
3203
3556
|
const importMap = /* @__PURE__ */ new Map();
|
|
3204
3557
|
for (const imp of imports) {
|
|
3205
3558
|
importMap.set(imp.importName, imp.capabilityId);
|
|
3206
3559
|
}
|
|
3207
|
-
const callExpressions = sourceFile.getDescendantsOfKind(
|
|
3560
|
+
const callExpressions = sourceFile.getDescendantsOfKind(SyntaxKind6.CallExpression);
|
|
3208
3561
|
for (const callExpr of callExpressions) {
|
|
3209
3562
|
const expression = callExpr.getExpression();
|
|
3210
|
-
if (expression.getKind() ===
|
|
3563
|
+
if (expression.getKind() === SyntaxKind6.Identifier) {
|
|
3211
3564
|
const functionName = expression.getText();
|
|
3212
3565
|
const capabilityId = importMap.get(functionName);
|
|
3213
3566
|
if (capabilityId) {
|
|
@@ -3220,11 +3573,11 @@ function analyzeCallSites(sourceFile, imports) {
|
|
|
3220
3573
|
text: callExpr.getText()
|
|
3221
3574
|
});
|
|
3222
3575
|
}
|
|
3223
|
-
} else if (expression.getKind() ===
|
|
3224
|
-
const propAccess = expression.asKind(
|
|
3576
|
+
} else if (expression.getKind() === SyntaxKind6.PropertyAccessExpression) {
|
|
3577
|
+
const propAccess = expression.asKind(SyntaxKind6.PropertyAccessExpression);
|
|
3225
3578
|
if (propAccess) {
|
|
3226
3579
|
const objectExpr = propAccess.getExpression();
|
|
3227
|
-
if (objectExpr.getKind() ===
|
|
3580
|
+
if (objectExpr.getKind() === SyntaxKind6.Identifier) {
|
|
3228
3581
|
const objectName = objectExpr.getText();
|
|
3229
3582
|
const capabilityId = importMap.get(objectName);
|
|
3230
3583
|
if (capabilityId) {
|
|
@@ -3453,7 +3806,7 @@ function addInjection(sourceFile) {
|
|
|
3453
3806
|
}
|
|
3454
3807
|
|
|
3455
3808
|
// src/commands/migration/versions/v001_capability/code-migrator/transformers/call-site-transformer.ts
|
|
3456
|
-
import { SyntaxKind as
|
|
3809
|
+
import { SyntaxKind as SyntaxKind7 } from "ts-morph";
|
|
3457
3810
|
var DEFAULT_ACTION_NAME = "run";
|
|
3458
3811
|
function generateNewCallText(capabilityId, actionName, args) {
|
|
3459
3812
|
const argsText = args.trim() || "{}";
|
|
@@ -3468,19 +3821,19 @@ function transformCallSites(sourceFile, imports) {
|
|
|
3468
3821
|
});
|
|
3469
3822
|
}
|
|
3470
3823
|
let replacedCount = 0;
|
|
3471
|
-
const callExpressions = sourceFile.getDescendantsOfKind(
|
|
3824
|
+
const callExpressions = sourceFile.getDescendantsOfKind(SyntaxKind7.CallExpression);
|
|
3472
3825
|
const sortedCalls = [...callExpressions].sort((a, b) => b.getStart() - a.getStart());
|
|
3473
3826
|
for (const callExpr of sortedCalls) {
|
|
3474
3827
|
const expression = callExpr.getExpression();
|
|
3475
3828
|
let importInfo;
|
|
3476
|
-
if (expression.getKind() ===
|
|
3829
|
+
if (expression.getKind() === SyntaxKind7.Identifier) {
|
|
3477
3830
|
const functionName = expression.getText();
|
|
3478
3831
|
importInfo = importMap.get(functionName);
|
|
3479
|
-
} else if (expression.getKind() ===
|
|
3480
|
-
const propAccess = expression.asKind(
|
|
3832
|
+
} else if (expression.getKind() === SyntaxKind7.PropertyAccessExpression) {
|
|
3833
|
+
const propAccess = expression.asKind(SyntaxKind7.PropertyAccessExpression);
|
|
3481
3834
|
if (propAccess) {
|
|
3482
3835
|
const objectExpr = propAccess.getExpression();
|
|
3483
|
-
if (objectExpr.getKind() ===
|
|
3836
|
+
if (objectExpr.getKind() === SyntaxKind7.Identifier) {
|
|
3484
3837
|
const objectName = objectExpr.getText();
|
|
3485
3838
|
importInfo = importMap.get(objectName);
|
|
3486
3839
|
}
|
|
@@ -3581,7 +3934,7 @@ async function migrateCode(options, capabilities) {
|
|
|
3581
3934
|
console.log(" No files need code migration.\n");
|
|
3582
3935
|
return result;
|
|
3583
3936
|
}
|
|
3584
|
-
const project = new
|
|
3937
|
+
const project = new Project3({
|
|
3585
3938
|
skipAddingFilesFromTsConfig: true,
|
|
3586
3939
|
compilerOptions: {
|
|
3587
3940
|
allowJs: true
|
|
@@ -3624,17 +3977,17 @@ function getSuggestion(analysis) {
|
|
|
3624
3977
|
}
|
|
3625
3978
|
|
|
3626
3979
|
// src/commands/migration/versions/v001_capability/cleanup.ts
|
|
3627
|
-
import
|
|
3980
|
+
import fs16 from "fs";
|
|
3628
3981
|
import path14 from "path";
|
|
3629
3982
|
function cleanupOldFiles(capabilities, dryRun) {
|
|
3630
3983
|
const deletedFiles = [];
|
|
3631
3984
|
const errors = [];
|
|
3632
3985
|
const capabilitiesDir = getCapabilitiesDir2();
|
|
3633
3986
|
const oldJsonPath = path14.join(capabilitiesDir, "capabilities.json");
|
|
3634
|
-
if (
|
|
3987
|
+
if (fs16.existsSync(oldJsonPath)) {
|
|
3635
3988
|
try {
|
|
3636
3989
|
if (!dryRun) {
|
|
3637
|
-
|
|
3990
|
+
fs16.unlinkSync(oldJsonPath);
|
|
3638
3991
|
}
|
|
3639
3992
|
deletedFiles.push("capabilities.json");
|
|
3640
3993
|
} catch (error) {
|
|
@@ -3643,10 +3996,10 @@ function cleanupOldFiles(capabilities, dryRun) {
|
|
|
3643
3996
|
}
|
|
3644
3997
|
for (const cap of capabilities) {
|
|
3645
3998
|
const tsFilePath = path14.join(capabilitiesDir, `${cap.id}.ts`);
|
|
3646
|
-
if (
|
|
3999
|
+
if (fs16.existsSync(tsFilePath)) {
|
|
3647
4000
|
try {
|
|
3648
4001
|
if (!dryRun) {
|
|
3649
|
-
|
|
4002
|
+
fs16.unlinkSync(tsFilePath);
|
|
3650
4003
|
}
|
|
3651
4004
|
deletedFiles.push(`${cap.id}.ts`);
|
|
3652
4005
|
} catch (error) {
|
|
@@ -3662,7 +4015,7 @@ function cleanupOldFiles(capabilities, dryRun) {
|
|
|
3662
4015
|
}
|
|
3663
4016
|
|
|
3664
4017
|
// src/commands/migration/versions/v001_capability/report-generator.ts
|
|
3665
|
-
import
|
|
4018
|
+
import fs17 from "fs";
|
|
3666
4019
|
import path15 from "path";
|
|
3667
4020
|
var REPORT_FILE = "capability-migration-report.md";
|
|
3668
4021
|
function printSummary(result) {
|
|
@@ -3826,15 +4179,15 @@ async function generateReport(result) {
|
|
|
3826
4179
|
}
|
|
3827
4180
|
lines.push("");
|
|
3828
4181
|
const logDir = process.env.LOG_DIR || "logs";
|
|
3829
|
-
if (!
|
|
4182
|
+
if (!fs17.existsSync(logDir)) {
|
|
3830
4183
|
return;
|
|
3831
4184
|
}
|
|
3832
4185
|
const reportDir = path15.join(logDir, "migration");
|
|
3833
|
-
if (!
|
|
3834
|
-
|
|
4186
|
+
if (!fs17.existsSync(reportDir)) {
|
|
4187
|
+
fs17.mkdirSync(reportDir, { recursive: true });
|
|
3835
4188
|
}
|
|
3836
4189
|
const reportPath = path15.join(reportDir, REPORT_FILE);
|
|
3837
|
-
|
|
4190
|
+
fs17.writeFileSync(reportPath, lines.join("\n"), "utf-8");
|
|
3838
4191
|
console.log(`\u{1F4C4} Report generated: ${reportPath}`);
|
|
3839
4192
|
}
|
|
3840
4193
|
|
|
@@ -4369,7 +4722,7 @@ var migrationCommand = {
|
|
|
4369
4722
|
import path16 from "path";
|
|
4370
4723
|
|
|
4371
4724
|
// src/commands/read-logs/std-utils.ts
|
|
4372
|
-
import
|
|
4725
|
+
import fs18 from "fs";
|
|
4373
4726
|
function formatStdPrefixTime(localTime) {
|
|
4374
4727
|
const match = localTime.match(/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/);
|
|
4375
4728
|
if (!match) return localTime;
|
|
@@ -4399,11 +4752,11 @@ function stripPrefixFromStdLine(line) {
|
|
|
4399
4752
|
return `[${time}] ${content}`;
|
|
4400
4753
|
}
|
|
4401
4754
|
function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarker) {
|
|
4402
|
-
const stat =
|
|
4755
|
+
const stat = fs18.statSync(filePath);
|
|
4403
4756
|
if (stat.size === 0) {
|
|
4404
4757
|
return { lines: [], markerFound: false, totalLinesCount: 0 };
|
|
4405
4758
|
}
|
|
4406
|
-
const fd =
|
|
4759
|
+
const fd = fs18.openSync(filePath, "r");
|
|
4407
4760
|
const chunkSize = 64 * 1024;
|
|
4408
4761
|
let position = stat.size;
|
|
4409
4762
|
let remainder = "";
|
|
@@ -4417,7 +4770,7 @@ function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarke
|
|
|
4417
4770
|
const length = Math.min(chunkSize, position);
|
|
4418
4771
|
position -= length;
|
|
4419
4772
|
const buffer = Buffer.alloc(length);
|
|
4420
|
-
|
|
4773
|
+
fs18.readSync(fd, buffer, 0, length, position);
|
|
4421
4774
|
let chunk = buffer.toString("utf8");
|
|
4422
4775
|
if (remainder) {
|
|
4423
4776
|
chunk += remainder;
|
|
@@ -4459,7 +4812,7 @@ function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarke
|
|
|
4459
4812
|
}
|
|
4460
4813
|
}
|
|
4461
4814
|
} finally {
|
|
4462
|
-
|
|
4815
|
+
fs18.closeSync(fd);
|
|
4463
4816
|
}
|
|
4464
4817
|
return { lines: collected.reverse(), markerFound, totalLinesCount };
|
|
4465
4818
|
}
|
|
@@ -4480,21 +4833,21 @@ function readServerStdSegment(filePath, maxLines, offset) {
|
|
|
4480
4833
|
}
|
|
4481
4834
|
|
|
4482
4835
|
// src/commands/read-logs/tail.ts
|
|
4483
|
-
import
|
|
4836
|
+
import fs19 from "fs";
|
|
4484
4837
|
function fileExists(filePath) {
|
|
4485
4838
|
try {
|
|
4486
|
-
|
|
4839
|
+
fs19.accessSync(filePath, fs19.constants.F_OK | fs19.constants.R_OK);
|
|
4487
4840
|
return true;
|
|
4488
4841
|
} catch {
|
|
4489
4842
|
return false;
|
|
4490
4843
|
}
|
|
4491
4844
|
}
|
|
4492
4845
|
function readFileTailLines(filePath, maxLines) {
|
|
4493
|
-
const stat =
|
|
4846
|
+
const stat = fs19.statSync(filePath);
|
|
4494
4847
|
if (stat.size === 0) {
|
|
4495
4848
|
return [];
|
|
4496
4849
|
}
|
|
4497
|
-
const fd =
|
|
4850
|
+
const fd = fs19.openSync(filePath, "r");
|
|
4498
4851
|
const chunkSize = 64 * 1024;
|
|
4499
4852
|
const chunks = [];
|
|
4500
4853
|
let position = stat.size;
|
|
@@ -4504,13 +4857,13 @@ function readFileTailLines(filePath, maxLines) {
|
|
|
4504
4857
|
const length = Math.min(chunkSize, position);
|
|
4505
4858
|
position -= length;
|
|
4506
4859
|
const buffer = Buffer.alloc(length);
|
|
4507
|
-
|
|
4860
|
+
fs19.readSync(fd, buffer, 0, length, position);
|
|
4508
4861
|
chunks.unshift(buffer.toString("utf8"));
|
|
4509
4862
|
const chunkLines = buffer.toString("utf8").split("\n").length - 1;
|
|
4510
4863
|
collectedLines += chunkLines;
|
|
4511
4864
|
}
|
|
4512
4865
|
} finally {
|
|
4513
|
-
|
|
4866
|
+
fs19.closeSync(fd);
|
|
4514
4867
|
}
|
|
4515
4868
|
const content = chunks.join("");
|
|
4516
4869
|
const allLines = content.split("\n");
|
|
@@ -4526,11 +4879,11 @@ function readFileTailLines(filePath, maxLines) {
|
|
|
4526
4879
|
return allLines.slice(allLines.length - maxLines);
|
|
4527
4880
|
}
|
|
4528
4881
|
function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
|
|
4529
|
-
const stat =
|
|
4882
|
+
const stat = fs19.statSync(filePath);
|
|
4530
4883
|
if (stat.size === 0) {
|
|
4531
4884
|
return { lines: [], totalLinesCount: 0 };
|
|
4532
4885
|
}
|
|
4533
|
-
const fd =
|
|
4886
|
+
const fd = fs19.openSync(filePath, "r");
|
|
4534
4887
|
const chunkSize = 64 * 1024;
|
|
4535
4888
|
let position = stat.size;
|
|
4536
4889
|
let remainder = "";
|
|
@@ -4542,7 +4895,7 @@ function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
|
|
|
4542
4895
|
const length = Math.min(chunkSize, position);
|
|
4543
4896
|
position -= length;
|
|
4544
4897
|
const buffer = Buffer.alloc(length);
|
|
4545
|
-
|
|
4898
|
+
fs19.readSync(fd, buffer, 0, length, position);
|
|
4546
4899
|
let chunk = buffer.toString("utf8");
|
|
4547
4900
|
if (remainder) {
|
|
4548
4901
|
chunk += remainder;
|
|
@@ -4573,7 +4926,7 @@ function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
|
|
|
4573
4926
|
}
|
|
4574
4927
|
}
|
|
4575
4928
|
} finally {
|
|
4576
|
-
|
|
4929
|
+
fs19.closeSync(fd);
|
|
4577
4930
|
}
|
|
4578
4931
|
return { lines: collected.reverse(), totalLinesCount };
|
|
4579
4932
|
}
|
|
@@ -4675,7 +5028,7 @@ function extractClientStdSegment(lines, maxLines, offset) {
|
|
|
4675
5028
|
}
|
|
4676
5029
|
|
|
4677
5030
|
// src/commands/read-logs/json-lines.ts
|
|
4678
|
-
import
|
|
5031
|
+
import fs20 from "fs";
|
|
4679
5032
|
function normalizePid(value) {
|
|
4680
5033
|
if (typeof value === "number") {
|
|
4681
5034
|
return String(value);
|
|
@@ -4726,11 +5079,11 @@ function buildWantedLevelSet(levels) {
|
|
|
4726
5079
|
return set.size > 0 ? set : null;
|
|
4727
5080
|
}
|
|
4728
5081
|
function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
|
|
4729
|
-
const stat =
|
|
5082
|
+
const stat = fs20.statSync(filePath);
|
|
4730
5083
|
if (stat.size === 0) {
|
|
4731
5084
|
return { lines: [], totalLinesCount: 0 };
|
|
4732
5085
|
}
|
|
4733
|
-
const fd =
|
|
5086
|
+
const fd = fs20.openSync(filePath, "r");
|
|
4734
5087
|
const chunkSize = 64 * 1024;
|
|
4735
5088
|
let position = stat.size;
|
|
4736
5089
|
let remainder = "";
|
|
@@ -4745,7 +5098,7 @@ function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
|
|
|
4745
5098
|
const length = Math.min(chunkSize, position);
|
|
4746
5099
|
position -= length;
|
|
4747
5100
|
const buffer = Buffer.alloc(length);
|
|
4748
|
-
|
|
5101
|
+
fs20.readSync(fd, buffer, 0, length, position);
|
|
4749
5102
|
let chunk = buffer.toString("utf8");
|
|
4750
5103
|
if (remainder) {
|
|
4751
5104
|
chunk += remainder;
|
|
@@ -4807,7 +5160,7 @@ function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
|
|
|
4807
5160
|
}
|
|
4808
5161
|
}
|
|
4809
5162
|
} finally {
|
|
4810
|
-
|
|
5163
|
+
fs20.closeSync(fd);
|
|
4811
5164
|
}
|
|
4812
5165
|
return { lines: collected.reverse(), totalLinesCount };
|
|
4813
5166
|
}
|
|
@@ -4850,11 +5203,11 @@ function extractTraceId(obj) {
|
|
|
4850
5203
|
function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
|
|
4851
5204
|
const wanted = traceId.trim();
|
|
4852
5205
|
if (!wanted) return { lines: [], totalLinesCount: 0 };
|
|
4853
|
-
const stat =
|
|
5206
|
+
const stat = fs20.statSync(filePath);
|
|
4854
5207
|
if (stat.size === 0) {
|
|
4855
5208
|
return { lines: [], totalLinesCount: 0 };
|
|
4856
5209
|
}
|
|
4857
|
-
const fd =
|
|
5210
|
+
const fd = fs20.openSync(filePath, "r");
|
|
4858
5211
|
const chunkSize = 64 * 1024;
|
|
4859
5212
|
let position = stat.size;
|
|
4860
5213
|
let remainder = "";
|
|
@@ -4867,7 +5220,7 @@ function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
|
|
|
4867
5220
|
const length = Math.min(chunkSize, position);
|
|
4868
5221
|
position -= length;
|
|
4869
5222
|
const buffer = Buffer.alloc(length);
|
|
4870
|
-
|
|
5223
|
+
fs20.readSync(fd, buffer, 0, length, position);
|
|
4871
5224
|
let chunk = buffer.toString("utf8");
|
|
4872
5225
|
if (remainder) {
|
|
4873
5226
|
chunk += remainder;
|
|
@@ -4920,7 +5273,7 @@ function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
|
|
|
4920
5273
|
}
|
|
4921
5274
|
}
|
|
4922
5275
|
} finally {
|
|
4923
|
-
|
|
5276
|
+
fs20.closeSync(fd);
|
|
4924
5277
|
}
|
|
4925
5278
|
return { lines: collected.reverse(), totalLinesCount };
|
|
4926
5279
|
}
|
|
@@ -4929,11 +5282,11 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
|
|
|
4929
5282
|
if (!wantedLevelSet) {
|
|
4930
5283
|
return { lines: [], totalLinesCount: 0 };
|
|
4931
5284
|
}
|
|
4932
|
-
const stat =
|
|
5285
|
+
const stat = fs20.statSync(filePath);
|
|
4933
5286
|
if (stat.size === 0) {
|
|
4934
5287
|
return { lines: [], totalLinesCount: 0 };
|
|
4935
5288
|
}
|
|
4936
|
-
const fd =
|
|
5289
|
+
const fd = fs20.openSync(filePath, "r");
|
|
4937
5290
|
const chunkSize = 64 * 1024;
|
|
4938
5291
|
let position = stat.size;
|
|
4939
5292
|
let remainder = "";
|
|
@@ -4945,7 +5298,7 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
|
|
|
4945
5298
|
const length = Math.min(chunkSize, position);
|
|
4946
5299
|
position -= length;
|
|
4947
5300
|
const buffer = Buffer.alloc(length);
|
|
4948
|
-
|
|
5301
|
+
fs20.readSync(fd, buffer, 0, length, position);
|
|
4949
5302
|
let chunk = buffer.toString("utf8");
|
|
4950
5303
|
if (remainder) {
|
|
4951
5304
|
chunk += remainder;
|
|
@@ -4992,7 +5345,7 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
|
|
|
4992
5345
|
}
|
|
4993
5346
|
}
|
|
4994
5347
|
} finally {
|
|
4995
|
-
|
|
5348
|
+
fs20.closeSync(fd);
|
|
4996
5349
|
}
|
|
4997
5350
|
return { lines: collected.reverse(), totalLinesCount };
|
|
4998
5351
|
}
|
|
@@ -5213,11 +5566,11 @@ var commands = [
|
|
|
5213
5566
|
|
|
5214
5567
|
// src/index.ts
|
|
5215
5568
|
var envPath = path17.join(process.cwd(), ".env");
|
|
5216
|
-
if (
|
|
5569
|
+
if (fs21.existsSync(envPath)) {
|
|
5217
5570
|
dotenvConfig({ path: envPath });
|
|
5218
5571
|
}
|
|
5219
5572
|
var __dirname = path17.dirname(fileURLToPath4(import.meta.url));
|
|
5220
|
-
var pkg = JSON.parse(
|
|
5573
|
+
var pkg = JSON.parse(fs21.readFileSync(path17.join(__dirname, "../package.json"), "utf-8"));
|
|
5221
5574
|
var cli = new FullstackCLI(pkg.version);
|
|
5222
5575
|
cli.useAll(commands);
|
|
5223
5576
|
cli.run();
|