@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/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/index.ts
2
- import fs20 from "fs";
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 fs3 from "fs";
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/helper/header-format.ts
131
- var HEADER_COMMENT = "/** auto generated, do not edit */";
132
- function ensureHeaderComment(source) {
133
- let text = source.startsWith("\uFEFF") ? source.slice(1) : source;
134
- while (text.startsWith(HEADER_COMMENT)) {
135
- text = text.slice(HEADER_COMMENT.length);
136
- text = stripLeadingNewlines(text);
137
- }
138
- const trimmed = stripLeadingNewlines(text);
139
- if (trimmed.length === 0) {
140
- return `${HEADER_COMMENT}
141
- `;
142
- }
143
- return `${HEADER_COMMENT}
144
- ${trimmed}`;
133
+ // src/commands/db/gen-dbschema/transforms/core.ts
134
+ import { IndentationText, Project, QuoteKind } from "ts-morph";
135
+
136
+ // src/commands/db/gen-dbschema/transforms/types.ts
137
+ function createEmptyStats() {
138
+ return {
139
+ patchedDefects: 0,
140
+ removedPgSchemas: 0,
141
+ convertedSchemaCalls: 0,
142
+ renamedIdentifiers: [],
143
+ replacedUnknown: 0,
144
+ fallbackToText: 0,
145
+ unmatchedUnknown: [],
146
+ replacedTimestamp: 0,
147
+ replacedDefaultNow: 0,
148
+ removedSystemFields: 0,
149
+ addedImports: [],
150
+ removedImports: []
151
+ };
145
152
  }
146
- function stripLeadingNewlines(value) {
147
- let current = value;
148
- while (current.startsWith("\r\n") || current.startsWith("\n")) {
149
- current = current.startsWith("\r\n") ? current.slice(2) : current.slice(1);
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
- return current;
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 collapseExtraBlankLines(text) {
154
- return text.replace(/\n{3,}/g, "\n\n");
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
- // src/commands/db/gen-dbschema/helper/schema-conversion.ts
158
- function removePgSchemaDeclarations(source) {
159
- return source.replace(/export const \w+ = pgSchema\([\s\S]*?\);\n*/g, "");
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/helper/table-rename.ts
196
+ // src/commands/db/gen-dbschema/utils/identifier.ts
187
197
  import { pinyin } from "pinyin-pro";
188
- function renamePgTableConstants(source) {
189
- const pgTableRegex = /export const\s+([^\s=]+)\s*=\s*(pgTable|pgView|pgMaterializedView|pgEnum|pgSequence)\(\s*["'`]([^"'`]+)["'`]/gu;
190
- const renames = [];
191
- const updated = source.replace(pgTableRegex, (match, currentName, factory, tableName) => {
192
- const sanitized = sanitizeIdentifier(tableName);
193
- if (sanitized === currentName) {
194
- return match;
195
- }
196
- renames.push({ from: currentName, to: sanitized });
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
- function toAsciiName(name) {
246
- if (!/[^\x00-\x7F]/.test(name)) {
247
- return name;
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
- try {
250
- const transliterated = pinyin(name, { toneType: "none", type: "array" }).join("_");
251
- return transliterated || name;
252
- } catch (error) {
253
- return name;
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/helper/custom-types.ts
258
- var CUSTOM_TYPE_PATTERN = /\/\/ TODO: failed to parse database type '(?:\w+\.)?(user_profile|file_attachment)(\[\])?'/;
259
- var UNKNOWN_TYPE_TODO_PATTERN = /\/\/ TODO: failed to parse database type '([^']+)'/;
260
- function replaceUnknownColumns(source) {
261
- const lines = source.split("\n");
262
- const result = [];
263
- let replaced = 0;
264
- let fallbackToText = 0;
265
- const unmatched = [];
266
- for (let i = 0; i < lines.length; i += 1) {
267
- const line = lines[i];
268
- const knownMatch = line.match(CUSTOM_TYPE_PATTERN);
269
- if (knownMatch) {
270
- const typeName = knownMatch[1];
271
- const factory = typeName === "user_profile" ? "userProfile" : "fileAttachment";
272
- const replacedLine = replaceFollowingUnknown(lines[i + 1], factory);
273
- if (replacedLine) {
274
- result.push(replacedLine);
275
- replaced += 1;
276
- i += 1;
277
- } else {
278
- unmatched.push(line.trim());
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 unknownMatch = line.match(UNKNOWN_TYPE_TODO_PATTERN);
284
- if (unknownMatch) {
285
- const replacedLine = replaceFollowingUnknown(lines[i + 1], "text");
286
- if (replacedLine) {
287
- result.push(replacedLine);
288
- fallbackToText += 1;
289
- i += 1;
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
- unmatched.push(line.trim());
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
- if (line.includes("unknown(")) {
297
- unmatched.push(line.trim());
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
- function replaceFollowingUnknown(nextLine, factory) {
309
- if (!nextLine || !nextLine.includes("unknown(")) {
310
- return void 0;
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
- return nextLine.replace("unknown(", `${factory}(`);
313
- }
553
+ };
314
554
 
315
- // src/commands/db/gen-dbschema/helper/imports.ts
316
- import fs from "fs";
317
- import { fileURLToPath } from "url";
318
- function tweakImports(source) {
319
- const importRegex = /import \{([^}]*)\} from "drizzle-orm\/pg-core";?/;
320
- const match = source.match(importRegex);
321
- if (!match) {
322
- return source;
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
- const identifiers = match[1].split(",").map((id) => id.trim()).filter(Boolean).filter((id) => id !== "pgSchema" && id !== "customType");
325
- const filteredIdentifiers = identifiers.filter((id) => {
326
- if (id === "timestamp") {
327
- const timestampUsageRegex = /timestamp\s*\(/;
328
- return timestampUsageRegex.test(source);
329
- }
330
- return true;
331
- });
332
- if (source.includes("pgTable(") && !filteredIdentifiers.includes("pgTable")) {
333
- filteredIdentifiers.push("pgTable");
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
- if (source.includes("pgView(") && !filteredIdentifiers.includes("pgView")) {
336
- filteredIdentifiers.push("pgView");
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
- if (source.includes("pgMaterializedView(") && !filteredIdentifiers.includes("pgMaterializedView")) {
339
- filteredIdentifiers.push("pgMaterializedView");
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
- if (source.includes("pgEnum(") && !filteredIdentifiers.includes("pgEnum")) {
342
- filteredIdentifiers.push("pgEnum");
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
- if (source.includes("pgSequence(") && !filteredIdentifiers.includes("pgSequence")) {
345
- filteredIdentifiers.push("pgSequence");
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
- const unique = Array.from(new Set(filteredIdentifiers));
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
- const text = source.replace(/import \{[^}]*\} from ["']\.\/types["'];?\n*/g, "");
844
+ let text = source.replace(/import \{[^}]*\} from ["']\.\/types["'];?\n*/g, "");
353
845
  const templatePath = resolveTemplateTypesPath();
354
846
  if (!templatePath) {
355
- console.warn("[postprocess-drizzle-schema] Template types file not found.");
847
+ console.warn("[text/inline-types] Template types file not found.");
356
848
  return text;
357
849
  }
358
- return inlineFromTemplateContent(text, fs.readFileSync(templatePath, "utf8"));
850
+ const templateContent = fs.readFileSync(templatePath, "utf8");
851
+ return inlineFromTemplate(text, templateContent);
359
852
  }
360
- function inlineFromTemplateContent(text, templateContent) {
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 && !text.includes("from 'drizzle-orm'") && !text.includes('from "drizzle-orm"')) {
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 = `${HEADER_COMMENT}
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("../template/types.ts", import.meta.url),
409
- new URL("./gen-dbschema-template/types.ts", import.meta.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/helper/system-fields.ts
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 appendTableAliases(source) {
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/helper/system-objects-filter.ts
567
- var SYSTEM_OBJECTS = [
568
- // pg_stat_statements 扩展
569
- "pg_stat_statements",
570
- "pg_stat_statements_info",
571
- // pg_partman 扩展
572
- "part_config",
573
- "part_config_sub",
574
- // 系统权限视图
575
- "table_privs"
576
- ];
577
- function removeSystemObjects(source, additionalObjects = []) {
578
- const objectsToFilter = [...SYSTEM_OBJECTS, ...additionalObjects];
579
- const removed = [];
580
- const lines = source.split("\n");
581
- const result = [];
582
- let skipUntilNextExport = false;
583
- let currentSystemObject = null;
584
- for (let i = 0; i < lines.length; i++) {
585
- const line = lines[i];
586
- if (!skipUntilNextExport) {
587
- const exportMatch = line.match(/^export const (\w+)\s*=/);
588
- if (exportMatch) {
589
- const objName = exportMatch[1];
590
- if (objectsToFilter.includes(objName)) {
591
- skipUntilNextExport = true;
592
- currentSystemObject = objName;
593
- continue;
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
- if (skipUntilNextExport) {
598
- if (line.match(/^\}\);/) || line.match(/\.as\([^)]*\);$/)) {
599
- skipUntilNextExport = false;
600
- if (currentSystemObject) {
601
- removed.push(currentSystemObject);
602
- currentSystemObject = null;
603
- }
604
- continue;
605
- }
606
- continue;
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
- return { text: result.join("\n"), removed };
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/postprocess.ts
1014
+ // src/commands/db/gen-dbschema/index.ts
614
1015
  function postprocessDrizzleSchema(targetPath) {
615
1016
  const resolvedPath = path.resolve(targetPath);
616
- if (!fs2.existsSync(resolvedPath)) {
1017
+ if (!fs3.existsSync(resolvedPath)) {
617
1018
  console.warn(`[postprocess-drizzle-schema] File not found: ${resolvedPath}`);
618
1019
  return void 0;
619
1020
  }
620
- let text = fs2.readFileSync(resolvedPath, "utf8");
621
- text = ensureHeaderComment(text);
622
- const patchResult = patchDrizzleKitDefects(text);
623
- text = patchResult.text;
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: replacement.replaced,
673
- fallbackToText: replacement.fallbackToText,
674
- unmatchedUnknown: replacement.unmatched,
675
- patchedDefects: patchResult.fixed,
676
- replacedTimestamps: timestampReplacement.replaced,
677
- replacedDefaultNow: defaultNowReplacement.replaced,
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 Project(projectOptions);
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 && Node.isCallExpression(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 (!Node.isObjectLiteralExpression(fieldsArg)) {
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 (Node.isPropertyAssignment(prop)) {
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 && Node.isCallExpression(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 (Node.isCallExpression(current)) {
1535
+ while (Node9.isCallExpression(current)) {
1183
1536
  baseCall = current;
1184
1537
  const expression2 = current.getExpression();
1185
- if (Node.isPropertyAccessExpression(expression2)) {
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 (Node.isPropertyAccessExpression(expression)) {
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 (Node.isStringLiteral(firstArg)) {
1558
+ if (Node9.isStringLiteral(firstArg)) {
1206
1559
  fieldInfo.columnName = firstArg.getLiteralText();
1207
- } else if (Node.isObjectLiteralExpression(firstArg)) {
1560
+ } else if (Node9.isObjectLiteralExpression(firstArg)) {
1208
1561
  this.parseTypeConfig(firstArg, fieldInfo);
1209
- } else if (Node.isArrayLiteralExpression(firstArg)) {
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 && Node.isObjectLiteralExpression(args[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 (!Node.isObjectLiteralExpression(objLiteral)) {
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 (Node.isPropertyAssignment(prop)) {
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 (Node.isCallExpression(current)) {
1608
+ while (Node9.isCallExpression(current)) {
1256
1609
  const expression = current.getExpression();
1257
- if (Node.isPropertyAccessExpression(expression)) {
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 (fs3.existsSync(envPath2)) {
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) => fs3.existsSync(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 (fs3.existsSync(pkgJsonPath)) {
1387
- const pkgJsonRaw = fs3.readFileSync(pkgJsonPath, "utf8");
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 (!fs3.existsSync(generatedSchema)) {
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
- fs3.mkdirSync(path2.dirname(SCHEMA_FILE), { recursive: true });
1432
- fs3.copyFileSync(generatedSchema, SCHEMA_FILE);
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 (fs3.existsSync(OUT_DIR)) {
1454
- fs3.rmSync(OUT_DIR, { recursive: true, force: true });
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 fs5 from "fs";
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 fs4 from "fs";
1890
+ import fs5 from "fs";
1538
1891
  import path3 from "path";
1539
1892
  function removeLineFromFile(filePath, pattern) {
1540
- if (!fs4.existsSync(filePath)) {
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 = fs4.readFileSync(filePath, "utf-8");
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
- fs4.writeFileSync(filePath, filteredLines.join("\n"));
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 (!fs5.existsSync(userPackageJson)) {
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 (!fs5.existsSync(srcPath)) {
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 (!fs5.existsSync(destDir)) {
1633
- fs5.mkdirSync(destDir, { recursive: true });
1985
+ if (!fs6.existsSync(destDir)) {
1986
+ fs6.mkdirSync(destDir, { recursive: true });
1634
1987
  }
1635
- if (fs5.existsSync(dest) && !overwrite) {
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
- fs5.copyFileSync(src, dest);
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 (!fs5.existsSync(dest)) {
1644
- fs5.mkdirSync(dest, { recursive: true });
1996
+ if (!fs6.existsSync(dest)) {
1997
+ fs6.mkdirSync(dest, { recursive: true });
1645
1998
  }
1646
- const files = fs5.readdirSync(src);
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 = fs5.statSync(srcFile);
2004
+ const stats = fs6.statSync(srcFile);
1652
2005
  if (stats.isDirectory()) {
1653
2006
  syncDirectory(srcFile, destFile, overwrite);
1654
2007
  } else {
1655
- if (overwrite || !fs5.existsSync(destFile)) {
1656
- fs5.copyFileSync(srcFile, destFile);
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 = fs5.readFileSync(src, "utf-8");
2020
+ const content = fs6.readFileSync(src, "utf-8");
1668
2021
  let existingContent = "";
1669
- if (fs5.existsSync(dest)) {
1670
- existingContent = fs5.readFileSync(dest, "utf-8");
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
- fs5.appendFileSync(dest, content);
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 (fs5.existsSync(scriptsDir)) {
1684
- const files = fs5.readdirSync(scriptsDir);
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
- fs5.chmodSync(filePath, mode);
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 (fs5.existsSync(filePath)) {
1697
- fs5.unlinkSync(filePath);
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 (fs5.existsSync(dirPath)) {
1705
- fs5.rmSync(dirPath, { recursive: true });
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 fs6 from "fs";
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 (!fs6.existsSync(pkgPath)) {
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 = fs6.readFileSync(pkgPath, "utf-8");
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
- fs6.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
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 (!fs6.existsSync(pkgJsonPath)) {
2149
+ if (!fs7.existsSync(pkgJsonPath)) {
1797
2150
  return null;
1798
2151
  }
1799
2152
  try {
1800
- const content = fs6.readFileSync(pkgJsonPath, "utf-8");
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 (!fs6.existsSync(pkgJsonPath)) {
2162
+ if (!fs7.existsSync(pkgJsonPath)) {
1810
2163
  return null;
1811
2164
  }
1812
2165
  try {
1813
- const content = fs6.readFileSync(pkgJsonPath, "utf-8");
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 (!fs6.existsSync(scopeDir)) {
1824
- fs6.mkdirSync(scopeDir, { recursive: true });
2176
+ if (!fs7.existsSync(scopeDir)) {
2177
+ fs7.mkdirSync(scopeDir, { recursive: true });
1825
2178
  }
1826
- if (fs6.existsSync(targetDir)) {
1827
- fs6.rmSync(targetDir, { recursive: true });
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 (fs6.existsSync(tempDir)) {
1831
- fs6.rmSync(tempDir, { recursive: true });
2183
+ if (fs7.existsSync(tempDir)) {
2184
+ fs7.rmSync(tempDir, { recursive: true });
1832
2185
  }
1833
- fs6.mkdirSync(tempDir, { recursive: true });
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 (fs6.existsSync(extractedDir)) {
1838
- fs6.renameSync(extractedDir, targetDir);
2190
+ if (fs7.existsSync(extractedDir)) {
2191
+ fs7.renameSync(extractedDir, targetDir);
1839
2192
  } else {
1840
- const files = fs6.readdirSync(tempDir);
2193
+ const files = fs7.readdirSync(tempDir);
1841
2194
  if (files.length === 1) {
1842
- fs6.renameSync(path5.join(tempDir, files[0]), targetDir);
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 (fs6.existsSync(tempDir)) {
1850
- fs6.rmSync(tempDir, { recursive: true });
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 (!fs6.existsSync(depPath)) {
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 (fs6.existsSync(pluginPath)) {
1887
- fs6.rmSync(pluginPath, { recursive: true });
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 fs7 from "fs";
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 (!fs7.existsSync(cacheDir)) {
1988
- fs7.mkdirSync(cacheDir, { recursive: true });
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
- fs7.writeFileSync(tgzPath, tgzBuffer);
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 (fs7.existsSync(tgzPath)) {
2022
- fs7.unlinkSync(tgzPath);
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 fs8 from "fs";
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 fs8.existsSync(getCapabilitiesDir());
2727
+ return fs9.existsSync(getCapabilitiesDir());
2375
2728
  }
2376
2729
  function listCapabilityIds() {
2377
2730
  const dir = getCapabilitiesDir();
2378
- if (!fs8.existsSync(dir)) {
2731
+ if (!fs9.existsSync(dir)) {
2379
2732
  return [];
2380
2733
  }
2381
- const files = fs8.readdirSync(dir);
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 (!fs8.existsSync(filePath)) {
2739
+ if (!fs9.existsSync(filePath)) {
2387
2740
  throw new Error(`Capability not found: ${id}`);
2388
2741
  }
2389
2742
  try {
2390
- const content = fs8.readFileSync(filePath, "utf-8");
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 (!fs8.existsSync(manifestPath)) {
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 = fs8.readFileSync(manifestPath, "utf-8");
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 fs9 from "fs";
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 (!fs9.existsSync(pkgPath)) {
2957
+ if (!fs10.existsSync(pkgPath)) {
2605
2958
  throw new Error("package.json not found");
2606
2959
  }
2607
- const pkg2 = JSON.parse(fs9.readFileSync(pkgPath, "utf-8"));
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(fs9.readFileSync(pkgPath, "utf-8"));
2965
+ const pkg2 = JSON.parse(fs10.readFileSync(pkgPath, "utf-8"));
2613
2966
  pkg2[VERSION_FIELD] = version;
2614
- fs9.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
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 fs11 from "fs";
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 fs10 from "fs";
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 (!fs11.existsSync(oldFilePath)) {
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 = fs11.readFileSync(oldFilePath, "utf-8");
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 fs12 from "fs";
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 (!fs12.existsSync(capabilitiesDir)) {
3281
+ if (!fs13.existsSync(capabilitiesDir)) {
2929
3282
  return [];
2930
3283
  }
2931
- const files = fs12.readdirSync(capabilitiesDir);
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 = fs12.readFileSync(filePath, "utf-8");
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
- fs12.writeFileSync(filePath, content, "utf-8");
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 fs13 from "fs";
3364
+ import fs14 from "fs";
3012
3365
  function isPluginInstalled2(pluginKey) {
3013
3366
  const actionPlugins = readActionPlugins();
3014
3367
  const manifestPath = getPluginManifestPath2(pluginKey);
3015
- return fs13.existsSync(manifestPath) && !!actionPlugins[pluginKey];
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 Project2 } from "ts-morph";
3445
+ import { Project as Project3 } from "ts-morph";
3093
3446
 
3094
3447
  // src/commands/migration/versions/v001_capability/code-migrator/scanner.ts
3095
- import fs14 from "fs";
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 = fs14.readdirSync(dir, { withFileTypes: true });
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 (!fs14.existsSync(serverDir)) {
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 = fs14.readFileSync(filePath, "utf-8");
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(SyntaxKind.CallExpression);
3560
+ const callExpressions = sourceFile.getDescendantsOfKind(SyntaxKind6.CallExpression);
3208
3561
  for (const callExpr of callExpressions) {
3209
3562
  const expression = callExpr.getExpression();
3210
- if (expression.getKind() === SyntaxKind.Identifier) {
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() === SyntaxKind.PropertyAccessExpression) {
3224
- const propAccess = expression.asKind(SyntaxKind.PropertyAccessExpression);
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() === SyntaxKind.Identifier) {
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 SyntaxKind2 } from "ts-morph";
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(SyntaxKind2.CallExpression);
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() === SyntaxKind2.Identifier) {
3829
+ if (expression.getKind() === SyntaxKind7.Identifier) {
3477
3830
  const functionName = expression.getText();
3478
3831
  importInfo = importMap.get(functionName);
3479
- } else if (expression.getKind() === SyntaxKind2.PropertyAccessExpression) {
3480
- const propAccess = expression.asKind(SyntaxKind2.PropertyAccessExpression);
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() === SyntaxKind2.Identifier) {
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 Project2({
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 fs15 from "fs";
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 (fs15.existsSync(oldJsonPath)) {
3987
+ if (fs16.existsSync(oldJsonPath)) {
3635
3988
  try {
3636
3989
  if (!dryRun) {
3637
- fs15.unlinkSync(oldJsonPath);
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 (fs15.existsSync(tsFilePath)) {
3999
+ if (fs16.existsSync(tsFilePath)) {
3647
4000
  try {
3648
4001
  if (!dryRun) {
3649
- fs15.unlinkSync(tsFilePath);
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 fs16 from "fs";
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 (!fs16.existsSync(logDir)) {
4182
+ if (!fs17.existsSync(logDir)) {
3830
4183
  return;
3831
4184
  }
3832
4185
  const reportDir = path15.join(logDir, "migration");
3833
- if (!fs16.existsSync(reportDir)) {
3834
- fs16.mkdirSync(reportDir, { recursive: true });
4186
+ if (!fs17.existsSync(reportDir)) {
4187
+ fs17.mkdirSync(reportDir, { recursive: true });
3835
4188
  }
3836
4189
  const reportPath = path15.join(reportDir, REPORT_FILE);
3837
- fs16.writeFileSync(reportPath, lines.join("\n"), "utf-8");
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 fs17 from "fs";
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 = fs17.statSync(filePath);
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 = fs17.openSync(filePath, "r");
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
- fs17.readSync(fd, buffer, 0, length, position);
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
- fs17.closeSync(fd);
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 fs18 from "fs";
4836
+ import fs19 from "fs";
4484
4837
  function fileExists(filePath) {
4485
4838
  try {
4486
- fs18.accessSync(filePath, fs18.constants.F_OK | fs18.constants.R_OK);
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 = fs18.statSync(filePath);
4846
+ const stat = fs19.statSync(filePath);
4494
4847
  if (stat.size === 0) {
4495
4848
  return [];
4496
4849
  }
4497
- const fd = fs18.openSync(filePath, "r");
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
- fs18.readSync(fd, buffer, 0, length, position);
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
- fs18.closeSync(fd);
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 = fs18.statSync(filePath);
4882
+ const stat = fs19.statSync(filePath);
4530
4883
  if (stat.size === 0) {
4531
4884
  return { lines: [], totalLinesCount: 0 };
4532
4885
  }
4533
- const fd = fs18.openSync(filePath, "r");
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
- fs18.readSync(fd, buffer, 0, length, position);
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
- fs18.closeSync(fd);
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 fs19 from "fs";
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 = fs19.statSync(filePath);
5082
+ const stat = fs20.statSync(filePath);
4730
5083
  if (stat.size === 0) {
4731
5084
  return { lines: [], totalLinesCount: 0 };
4732
5085
  }
4733
- const fd = fs19.openSync(filePath, "r");
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
- fs19.readSync(fd, buffer, 0, length, position);
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
- fs19.closeSync(fd);
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 = fs19.statSync(filePath);
5206
+ const stat = fs20.statSync(filePath);
4854
5207
  if (stat.size === 0) {
4855
5208
  return { lines: [], totalLinesCount: 0 };
4856
5209
  }
4857
- const fd = fs19.openSync(filePath, "r");
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
- fs19.readSync(fd, buffer, 0, length, position);
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
- fs19.closeSync(fd);
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 = fs19.statSync(filePath);
5285
+ const stat = fs20.statSync(filePath);
4933
5286
  if (stat.size === 0) {
4934
5287
  return { lines: [], totalLinesCount: 0 };
4935
5288
  }
4936
- const fd = fs19.openSync(filePath, "r");
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
- fs19.readSync(fd, buffer, 0, length, position);
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
- fs19.closeSync(fd);
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 (fs20.existsSync(envPath)) {
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(fs20.readFileSync(path17.join(__dirname, "../package.json"), "utf-8"));
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();