@lark-apaas/fullstack-cli 1.1.16-alpha.2 → 1.1.16-alpha.4

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 fs21 from "fs";
2
+ import fs20 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,94 +117,104 @@ 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 fs4 from "fs";
120
+ import fs3 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
-
130
126
  // src/commands/db/gen-dbschema/postprocess.ts
131
127
  import fs2 from "fs";
128
+ import path from "path";
132
129
 
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
- };
152
- }
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
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
+ `;
161
142
  }
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 };
143
+ return `${HEADER_COMMENT}
144
+ ${trimmed}`;
170
145
  }
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
- }
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);
180
150
  }
181
- return stats;
182
- }
183
- function formatSourceFile(sourceFile) {
184
- sourceFile.formatText({
185
- indentSize: 2,
186
- convertTabsToSpaces: true
187
- });
151
+ return current;
188
152
  }
189
- function printSourceFile(sourceFile) {
190
- return sourceFile.getFullText();
153
+ function collapseExtraBlankLines(text) {
154
+ return text.replace(/\n{3,}/g, "\n\n");
191
155
  }
192
156
 
193
- // src/commands/db/gen-dbschema/transforms/ast/rename-identifiers.ts
194
- import { Node } from "ts-morph";
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(";
178
+ });
179
+ text = text.replace(/([A-Za-z0-9_]+)\.sequence\(/g, () => {
180
+ converted += 1;
181
+ return "pgSequence(";
182
+ });
183
+ return { text, converted };
184
+ }
195
185
 
196
- // src/commands/db/gen-dbschema/utils/identifier.ts
186
+ // src/commands/db/gen-dbschema/helper/table-rename.ts
197
187
  import { pinyin } from "pinyin-pro";
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;
188
+ function renamePgTableConstants(source) {
189
+ const pgTableRegex = /export const\s+([^\s=]+)\s*=\s*(pgTable|pgView|pgMaterializedView)\(\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;
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, "\\/");
208
218
  }
209
219
  function toCamelCase(str) {
210
220
  const words = str.split(/[_\-\s]+/).filter(Boolean);
@@ -232,640 +242,120 @@ function sanitizeIdentifier(name) {
232
242
  }
233
243
  return sanitized;
234
244
  }
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;
253
- }
254
- const args = initializer.getArguments();
255
- if (args.length === 0) {
256
- return void 0;
257
- }
258
- const firstArg = args[0];
259
- if (Node.isStringLiteral(firstArg)) {
260
- return firstArg.getLiteralText();
261
- }
262
- return void 0;
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;
245
+ function toAsciiName(name) {
246
+ if (!/[^\x00-\x7F]/.test(name)) {
247
+ return name;
272
248
  }
273
- if (Node.isPropertyAccessExpression(expression)) {
274
- const propName = expression.getName();
275
- if (PG_FACTORIES.includes(propName)) {
276
- return true;
277
- }
249
+ try {
250
+ const transliterated = pinyin(name, { toneType: "none", type: "array" }).join("_");
251
+ return transliterated || name;
252
+ } catch (error) {
253
+ return name;
278
254
  }
279
- return false;
280
255
  }
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
- };
327
-
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
- }
350
- }
351
- }
352
- for (const statement of statementsToRemove.reverse()) {
353
- statement.remove();
354
- }
355
- }
356
- };
357
256
 
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++;
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
+ function replaceUnknownColumns(source) {
260
+ const lines = source.split("\n");
261
+ const result = [];
262
+ let replaced = 0;
263
+ const unmatched = [];
264
+ for (let i = 0; i < lines.length; i += 1) {
265
+ const line = lines[i];
266
+ const match = line.match(CUSTOM_TYPE_PATTERN);
267
+ if (match) {
268
+ const typeName = match[1];
269
+ const factory = typeName === "user_profile" ? "userProfile" : "fileAttachment";
270
+ const replacedLine = replaceFollowingUnknown(lines[i + 1], factory);
271
+ if (replacedLine) {
272
+ result.push(replacedLine);
273
+ replaced += 1;
274
+ i += 1;
465
275
  } else {
466
- stats.fallbackToText++;
276
+ unmatched.push(line.trim());
277
+ result.push(line);
467
278
  }
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)) {
485
279
  continue;
486
280
  }
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
- }
281
+ if (line.includes("unknown(")) {
282
+ unmatched.push(line.trim());
498
283
  }
284
+ result.push(line);
499
285
  }
500
- return hasWithTimezone && hasModeString;
286
+ return {
287
+ text: result.join("\n"),
288
+ replaced,
289
+ unmatched
290
+ };
501
291
  }
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
- }
552
- }
553
- };
554
-
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
- });
292
+ function replaceFollowingUnknown(nextLine, factory) {
293
+ if (!nextLine || !nextLine.includes("unknown(")) {
294
+ return void 0;
580
295
  }
581
- };
296
+ return nextLine.replace("unknown(", `${factory}(`);
297
+ }
582
298
 
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
- });
299
+ // src/commands/db/gen-dbschema/helper/imports.ts
300
+ import fs from "fs";
301
+ import { fileURLToPath } from "url";
302
+ function tweakImports(source) {
303
+ const importRegex = /import \{([^}]*)\} from "drizzle-orm\/pg-core";?/;
304
+ const match = source.match(importRegex);
305
+ if (!match) {
306
+ return source;
663
307
  }
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
- }
308
+ const identifiers = match[1].split(",").map((id) => id.trim()).filter(Boolean).filter((id) => id !== "pgSchema" && id !== "customType");
309
+ const filteredIdentifiers = identifiers.filter((id) => {
310
+ if (id === "timestamp") {
311
+ const timestampUsageRegex = /timestamp\s*\(/;
312
+ return timestampUsageRegex.test(source);
736
313
  }
737
- }
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} =`;
314
+ return true;
777
315
  });
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}.`);
316
+ if (source.includes("pgTable(") && !filteredIdentifiers.includes("pgTable")) {
317
+ filteredIdentifiers.push("pgTable");
784
318
  }
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
- }
319
+ if (source.includes("pgView(") && !filteredIdentifiers.includes("pgView")) {
320
+ filteredIdentifiers.push("pgView");
803
321
  }
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;
322
+ if (source.includes("pgMaterializedView(") && !filteredIdentifiers.includes("pgMaterializedView")) {
323
+ filteredIdentifiers.push("pgMaterializedView");
836
324
  }
837
- return lines.join("\n");
325
+ if (source.includes("pgEnum(") && !filteredIdentifiers.includes("pgEnum")) {
326
+ filteredIdentifiers.push("pgEnum");
327
+ }
328
+ if (source.includes("pgSequence(") && !filteredIdentifiers.includes("pgSequence")) {
329
+ filteredIdentifiers.push("pgSequence");
330
+ }
331
+ const unique = Array.from(new Set(filteredIdentifiers));
332
+ const replacement = `import { ${unique.join(", ")} } from "drizzle-orm/pg-core"`;
333
+ return source.replace(importRegex, replacement);
838
334
  }
839
-
840
- // src/commands/db/gen-dbschema/transforms/text/inline-types.ts
841
- import fs from "fs";
842
- import { fileURLToPath } from "url";
843
335
  function inlineCustomTypes(source) {
844
- let text = source.replace(/import \{[^}]*\} from ["']\.\/types["'];?\n*/g, "");
336
+ const text = source.replace(/import \{[^}]*\} from ["']\.\/types["'];?\n*/g, "");
845
337
  const templatePath = resolveTemplateTypesPath();
846
338
  if (!templatePath) {
847
- console.warn("[text/inline-types] Template types file not found.");
339
+ console.warn("[postprocess-drizzle-schema] Template types file not found.");
848
340
  return text;
849
341
  }
850
- const templateContent = fs.readFileSync(templatePath, "utf8");
851
- return inlineFromTemplate(text, templateContent);
342
+ return inlineFromTemplateContent(text, fs.readFileSync(templatePath, "utf8"));
852
343
  }
853
- function inlineFromTemplate(source, templateContent) {
344
+ function inlineFromTemplateContent(text, templateContent) {
854
345
  const typeDefinitions = templateContent.replace(/^import\s+.*;\r?\n*/gm, "").trim();
855
- let text = source;
856
346
  const needsSql = typeDefinitions.includes("sql`") && !text.includes("from 'drizzle-orm'") && !text.includes('from "drizzle-orm"');
857
347
  const needsCustomType = typeDefinitions.includes("customType<") && !text.includes("customType");
858
348
  if (needsCustomType) {
859
349
  text = ensureImportIdentifier(text, "drizzle-orm/pg-core", "customType");
860
350
  }
861
- if (needsSql) {
351
+ if (needsSql && !text.includes("from 'drizzle-orm'") && !text.includes('from "drizzle-orm"')) {
862
352
  const importMatch = text.match(/^import [\s\S]*?from ["']drizzle-orm\/pg-core["'];?\n/m);
863
353
  if (importMatch) {
864
354
  const insertPoint = text.indexOf(importMatch[0]) + importMatch[0].length;
865
355
  text = text.slice(0, insertPoint) + "import { sql } from 'drizzle-orm';\n" + text.slice(insertPoint);
866
356
  }
867
357
  }
868
- const headerPrefix = `${FULL_HEADER}
358
+ const headerPrefix = `${HEADER_COMMENT}
869
359
  `;
870
360
  let insertionPoint = 0;
871
361
  if (text.startsWith(headerPrefix)) {
@@ -899,8 +389,8 @@ function ensureImportIdentifier(source, packageName, identifier) {
899
389
  }
900
390
  function resolveTemplateTypesPath() {
901
391
  const candidates = [
902
- new URL("../../template/types.ts", import.meta.url),
903
- new URL("../template/types.ts", import.meta.url)
392
+ new URL("../template/types.ts", import.meta.url),
393
+ new URL("./gen-dbschema-template/types.ts", import.meta.url)
904
394
  ];
905
395
  for (const url of candidates) {
906
396
  const p = fileURLToPath(url);
@@ -911,9 +401,131 @@ function resolveTemplateTypesPath() {
911
401
  return void 0;
912
402
  }
913
403
 
914
- // src/commands/db/gen-dbschema/transforms/text/table-aliases.ts
404
+ // src/commands/db/gen-dbschema/helper/system-fields.ts
405
+ function addSystemFieldComments(source) {
406
+ const commentMap = {
407
+ "_created_at": "Creation time",
408
+ "_created_by": "Creator",
409
+ "_updated_at": "Update time",
410
+ "_updated_by": "Updater"
411
+ };
412
+ const lines = source.split("\n");
413
+ for (let i = 0; i < lines.length; i += 1) {
414
+ const line = lines[i];
415
+ const entry = Object.entries(commentMap).find(([key]) => line.includes(`"${key}"`));
416
+ if (!entry) {
417
+ continue;
418
+ }
419
+ const [, description] = entry;
420
+ const previousLine = lines[i - 1]?.trim() ?? "";
421
+ if (previousLine.startsWith("//") && previousLine.includes("System field")) {
422
+ continue;
423
+ }
424
+ const indentMatch = line.match(/^\s*/);
425
+ const indent = indentMatch ? indentMatch[0] : "";
426
+ const comment = `${indent}// System field: ${description} (auto-filled, do not modify)`;
427
+ lines.splice(i, 0, comment);
428
+ i += 1;
429
+ }
430
+ return lines.join("\n");
431
+ }
432
+ function removeConflictingSystemFields(source) {
433
+ const systemFieldMap = {
434
+ "_created_at": "created_at",
435
+ "_created_by": "created_by",
436
+ "_updated_at": "updated_at",
437
+ "_updated_by": "updated_by"
438
+ };
439
+ const lines = source.split("\n");
440
+ const result = [];
441
+ let inTable = false;
442
+ let tableStartLine = -1;
443
+ const tableBusinessFields = /* @__PURE__ */ new Set();
444
+ let bracketDepth = 0;
445
+ for (let i = 0; i < lines.length; i += 1) {
446
+ const line = lines[i];
447
+ if (!inTable && /=\s*(pgTable|pgView|pgMaterializedView)\s*\(/.test(line)) {
448
+ inTable = true;
449
+ tableStartLine = result.length;
450
+ tableBusinessFields.clear();
451
+ bracketDepth = 0;
452
+ }
453
+ if (inTable) {
454
+ for (const char of line) {
455
+ if (char === "{") bracketDepth++;
456
+ if (char === "}") bracketDepth--;
457
+ }
458
+ for (const businessField of Object.values(systemFieldMap)) {
459
+ if (line.includes(`"${businessField}"`) || line.includes(`'${businessField}'`)) {
460
+ tableBusinessFields.add(businessField);
461
+ }
462
+ }
463
+ if (bracketDepth === 0 && line.includes(");")) {
464
+ inTable = false;
465
+ const tableEndLine = result.length;
466
+ for (let j = tableStartLine; j <= tableEndLine; j++) {
467
+ const tableLine = result[j] || "";
468
+ let shouldRemove = false;
469
+ for (const [systemField, businessField] of Object.entries(systemFieldMap)) {
470
+ if (tableBusinessFields.has(businessField)) {
471
+ if (tableLine.includes(`"${systemField}"`) || tableLine.includes(`'${systemField}'`)) {
472
+ shouldRemove = true;
473
+ if (j > 0 && result[j - 1]?.includes("// System field:")) {
474
+ result[j - 1] = null;
475
+ }
476
+ break;
477
+ }
478
+ }
479
+ }
480
+ if (shouldRemove) {
481
+ result[j] = null;
482
+ }
483
+ }
484
+ }
485
+ }
486
+ result.push(line);
487
+ }
488
+ return result.filter((line) => line !== null).join("\n");
489
+ }
490
+
491
+ // src/commands/db/gen-dbschema/helper/patch-helper.ts
492
+ function patchDrizzleKitDefects(source) {
493
+ let fixed = 0;
494
+ const text = source.replace(/\.default\('\)/g, () => {
495
+ fixed += 1;
496
+ return `.default('')`;
497
+ });
498
+ return { text, fixed };
499
+ }
500
+
501
+ // src/commands/db/gen-dbschema/helper/timestamp-replacement.ts
502
+ function replaceTimestampWithCustomTypes(source) {
503
+ let replaced = 0;
504
+ const pattern = /timestamp\((['"])(.*?)\1,\s*(\{[^}]*\})\)/g;
505
+ const text = source.replace(pattern, (match, quote, fieldName, options) => {
506
+ const hasWithTimezone = /withTimezone:\s*true/.test(options);
507
+ const hasModeString = /mode:\s*['"]string['"]/.test(options);
508
+ if (hasWithTimezone && hasModeString) {
509
+ replaced += 1;
510
+ return `customTimestamptz(${quote}${fieldName}${quote})`;
511
+ }
512
+ return match;
513
+ });
514
+ return { text, replaced };
515
+ }
516
+ function replaceDefaultNowWithSql(source) {
517
+ let replaced = 0;
518
+ const pattern = /\.defaultNow\(\)/g;
519
+ const text = source.replace(pattern, () => {
520
+ replaced += 1;
521
+ return ".default(sql`CURRENT_TIMESTAMP`)";
522
+ });
523
+ return { text, replaced };
524
+ }
525
+
526
+ // src/commands/db/gen-dbschema/helper/appendTableAliases.ts
915
527
  var TABLE_ALIAS_MARKER = "// table aliases";
916
- function generateTableAliases(source) {
528
+ function appendTableAliases(source) {
917
529
  const markerIndex = source.indexOf(`
918
530
  ${TABLE_ALIAS_MARKER}`);
919
531
  const base = markerIndex === -1 ? source : source.slice(0, markerIndex);
@@ -935,100 +547,62 @@ ${aliasLines}
935
547
  `;
936
548
  }
937
549
 
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
550
  // src/commands/db/gen-dbschema/postprocess.ts
950
- function postprocessSchema(rawSource) {
951
- const patchResult = patchDefects(rawSource);
952
- let source = patchResult.text;
953
- const { sourceFile } = parseSource(source);
954
- const astStats = applyTransforms(sourceFile, defaultTransforms);
955
- formatSourceFile(sourceFile);
956
- source = printSourceFile(sourceFile);
957
- source = ensureHeader(source);
958
- source = addSystemFieldComments(source);
959
- source = inlineCustomTypes(source);
960
- source = generateTableAliases(source);
961
- source = formatSource(source);
962
- return {
963
- source,
964
- astStats,
965
- patchedDefects: patchResult.fixed
966
- };
967
- }
968
- function logStats(result, prefix = "[postprocess]") {
969
- const { astStats, patchedDefects } = result;
970
- if (patchedDefects > 0) {
971
- console.info(`${prefix} Patched ${patchedDefects} syntax defects`);
972
- }
973
- if (astStats.removedPgSchemas > 0) {
974
- console.info(`${prefix} Removed ${astStats.removedPgSchemas} pgSchema declarations`);
975
- }
976
- if (astStats.convertedSchemaCalls > 0) {
977
- console.info(`${prefix} Converted ${astStats.convertedSchemaCalls} schema.xxx() calls`);
978
- }
979
- if (astStats.renamedIdentifiers.length > 0) {
980
- console.info(`${prefix} Renamed ${astStats.renamedIdentifiers.length} identifiers:`);
981
- for (const { from, to } of astStats.renamedIdentifiers) {
982
- console.info(`${prefix} ${from} -> ${to}`);
983
- }
984
- }
985
- if (astStats.replacedUnknown > 0) {
986
- console.info(`${prefix} Replaced ${astStats.replacedUnknown} unknown types with custom types`);
987
- }
988
- if (astStats.fallbackToText > 0) {
989
- console.info(`${prefix} Replaced ${astStats.fallbackToText} unknown types with text (fallback)`);
990
- }
991
- if (astStats.unmatchedUnknown.length > 0) {
992
- console.warn(`${prefix} Unmatched unknown types:`);
993
- for (const line of astStats.unmatchedUnknown) {
994
- console.warn(`${prefix} ${line}`);
995
- }
996
- }
997
- if (astStats.replacedTimestamp > 0) {
998
- console.info(`${prefix} Replaced ${astStats.replacedTimestamp} timestamp with customTimestamptz`);
999
- }
1000
- if (astStats.replacedDefaultNow > 0) {
1001
- console.info(`${prefix} Replaced ${astStats.replacedDefaultNow} .defaultNow() calls`);
1002
- }
1003
- if (astStats.removedSystemFields > 0) {
1004
- console.info(`${prefix} Removed ${astStats.removedSystemFields} conflicting system fields`);
1005
- }
1006
- if (astStats.addedImports.length > 0) {
1007
- console.info(`${prefix} Added imports: ${astStats.addedImports.join(", ")}`);
1008
- }
1009
- if (astStats.removedImports.length > 0) {
1010
- console.info(`${prefix} Removed imports: ${astStats.removedImports.join(", ")}`);
1011
- }
1012
- }
1013
-
1014
- // src/commands/db/gen-dbschema/index.ts
1015
551
  function postprocessDrizzleSchema(targetPath) {
1016
552
  const resolvedPath = path.resolve(targetPath);
1017
- if (!fs3.existsSync(resolvedPath)) {
553
+ if (!fs2.existsSync(resolvedPath)) {
1018
554
  console.warn(`[postprocess-drizzle-schema] File not found: ${resolvedPath}`);
1019
555
  return void 0;
1020
556
  }
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]");
557
+ let text = fs2.readFileSync(resolvedPath, "utf8");
558
+ text = ensureHeaderComment(text);
559
+ const patchResult = patchDrizzleKitDefects(text);
560
+ text = patchResult.text;
561
+ text = removePgSchemaDeclarations(text);
562
+ const tableConversion = convertSchemaTableInvocations(text);
563
+ text = tableConversion.text;
564
+ const renameResult = renamePgTableConstants(text);
565
+ text = renameResult.text;
566
+ text = updateTableReferenceIdentifiers(text, renameResult.renames);
567
+ const replacement = replaceUnknownColumns(text);
568
+ text = replacement.text;
569
+ const timestampReplacement = replaceTimestampWithCustomTypes(text);
570
+ text = timestampReplacement.text;
571
+ const defaultNowReplacement = replaceDefaultNowWithSql(text);
572
+ text = defaultNowReplacement.text;
573
+ text = removeConflictingSystemFields(text);
574
+ text = addSystemFieldComments(text);
575
+ text = tweakImports(text);
576
+ text = inlineCustomTypes(text);
577
+ text = appendTableAliases(text);
578
+ text = text.replace(/\r?\n/g, "\n");
579
+ text = collapseExtraBlankLines(text);
580
+ fs2.writeFileSync(resolvedPath, text, "utf8");
581
+ if (patchResult.fixed > 0) {
582
+ console.info(`[postprocess-drizzle-schema] Patched ${patchResult.fixed} drizzle-kit defects (.default(') -> .default(''))`);
583
+ }
584
+ if (replacement.replaced > 0) {
585
+ console.info(`[postprocess-drizzle-schema] Replaced ${replacement.replaced} unknown columns`);
586
+ }
587
+ if (replacement.unmatched.length > 0) {
588
+ console.warn("[postprocess-drizzle-schema] Unmatched custom types:", replacement.unmatched.length);
589
+ replacement.unmatched.forEach((line) => console.warn(` ${line}`));
590
+ }
591
+ if (tableConversion.converted > 0) {
592
+ console.info(`[postprocess-drizzle-schema] Converted ${tableConversion.converted} schema.table invocations to pgTable`);
593
+ }
594
+ if (timestampReplacement.replaced > 0) {
595
+ console.info(`[postprocess-drizzle-schema] Replaced ${timestampReplacement.replaced} timestamp fields with customTimestamptz`);
596
+ }
597
+ if (defaultNowReplacement.replaced > 0) {
598
+ console.info(`[postprocess-drizzle-schema] Replaced ${defaultNowReplacement.replaced} .defaultNow() with .default(sql\`CURRENT_TIMESTAMP\`)`);
599
+ }
1025
600
  return {
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
601
+ replacedUnknown: replacement.replaced,
602
+ unmatchedUnknown: replacement.unmatched,
603
+ patchedDefects: patchResult.fixed,
604
+ replacedTimestamps: timestampReplacement.replaced,
605
+ replacedDefaultNow: defaultNowReplacement.replaced
1032
606
  };
1033
607
  }
1034
608
 
@@ -1450,10 +1024,10 @@ export class ${className}Module {}
1450
1024
  }
1451
1025
 
1452
1026
  // src/commands/db/gen-nest-resource/schema-parser.ts
1453
- import { Project as Project2, Node as Node9 } from "ts-morph";
1027
+ import { Project, Node } from "ts-morph";
1454
1028
  var DrizzleSchemaParser = class {
1455
1029
  constructor(projectOptions) {
1456
- this.project = new Project2(projectOptions);
1030
+ this.project = new Project(projectOptions);
1457
1031
  }
1458
1032
  parseSchemaFile(filePath) {
1459
1033
  const sourceFile = this.project.addSourceFileAtPath(filePath);
@@ -1463,7 +1037,7 @@ var DrizzleSchemaParser = class {
1463
1037
  const declarations = statement.getDeclarations();
1464
1038
  for (const declaration of declarations) {
1465
1039
  const initializer = declaration.getInitializer();
1466
- if (initializer && Node9.isCallExpression(initializer)) {
1040
+ if (initializer && Node.isCallExpression(initializer)) {
1467
1041
  const expression = initializer.getExpression();
1468
1042
  if (expression.getText() === "pgTable") {
1469
1043
  const tableInfo = this.parsePgTable(
@@ -1486,13 +1060,13 @@ var DrizzleSchemaParser = class {
1486
1060
  }
1487
1061
  const tableName = args[0].getText().replace(/['"]/g, "");
1488
1062
  const fieldsArg = args[1];
1489
- if (!Node9.isObjectLiteralExpression(fieldsArg)) {
1063
+ if (!Node.isObjectLiteralExpression(fieldsArg)) {
1490
1064
  return null;
1491
1065
  }
1492
1066
  const fields = [];
1493
1067
  const properties = fieldsArg.getProperties();
1494
1068
  for (const prop of properties) {
1495
- if (Node9.isPropertyAssignment(prop)) {
1069
+ if (Node.isPropertyAssignment(prop)) {
1496
1070
  const fieldName = prop.getName();
1497
1071
  const initializer = prop.getInitializer();
1498
1072
  const leadingComments = prop.getLeadingCommentRanges();
@@ -1500,7 +1074,7 @@ var DrizzleSchemaParser = class {
1500
1074
  if (leadingComments.length > 0) {
1501
1075
  comment = leadingComments.map((c) => c.getText()).join("\n").replace(/\/\//g, "").trim();
1502
1076
  }
1503
- if (initializer && Node9.isCallExpression(initializer)) {
1077
+ if (initializer && Node.isCallExpression(initializer)) {
1504
1078
  const fieldInfo = this.parseField(fieldName, initializer, comment);
1505
1079
  fields.push(fieldInfo);
1506
1080
  }
@@ -1532,10 +1106,10 @@ var DrizzleSchemaParser = class {
1532
1106
  parseBaseType(callExpr, fieldInfo) {
1533
1107
  let current = callExpr;
1534
1108
  let baseCall = null;
1535
- while (Node9.isCallExpression(current)) {
1109
+ while (Node.isCallExpression(current)) {
1536
1110
  baseCall = current;
1537
1111
  const expression2 = current.getExpression();
1538
- if (Node9.isPropertyAccessExpression(expression2)) {
1112
+ if (Node.isPropertyAccessExpression(expression2)) {
1539
1113
  current = expression2.getExpression();
1540
1114
  } else {
1541
1115
  break;
@@ -1546,7 +1120,7 @@ var DrizzleSchemaParser = class {
1546
1120
  }
1547
1121
  const expression = baseCall.getExpression();
1548
1122
  let typeName = "";
1549
- if (Node9.isPropertyAccessExpression(expression)) {
1123
+ if (Node.isPropertyAccessExpression(expression)) {
1550
1124
  typeName = expression.getName();
1551
1125
  } else {
1552
1126
  typeName = expression.getText();
@@ -1555,25 +1129,25 @@ var DrizzleSchemaParser = class {
1555
1129
  const args = baseCall.getArguments();
1556
1130
  if (args.length > 0) {
1557
1131
  const firstArg = args[0];
1558
- if (Node9.isStringLiteral(firstArg)) {
1132
+ if (Node.isStringLiteral(firstArg)) {
1559
1133
  fieldInfo.columnName = firstArg.getLiteralText();
1560
- } else if (Node9.isObjectLiteralExpression(firstArg)) {
1134
+ } else if (Node.isObjectLiteralExpression(firstArg)) {
1561
1135
  this.parseTypeConfig(firstArg, fieldInfo);
1562
- } else if (Node9.isArrayLiteralExpression(firstArg)) {
1136
+ } else if (Node.isArrayLiteralExpression(firstArg)) {
1563
1137
  fieldInfo.enumValues = firstArg.getElements().map((el) => el.getText().replace(/['"]/g, ""));
1564
1138
  }
1565
1139
  }
1566
- if (args.length > 1 && Node9.isObjectLiteralExpression(args[1])) {
1140
+ if (args.length > 1 && Node.isObjectLiteralExpression(args[1])) {
1567
1141
  this.parseTypeConfig(args[1], fieldInfo);
1568
1142
  }
1569
1143
  }
1570
1144
  parseTypeConfig(objLiteral, fieldInfo) {
1571
- if (!Node9.isObjectLiteralExpression(objLiteral)) {
1145
+ if (!Node.isObjectLiteralExpression(objLiteral)) {
1572
1146
  return;
1573
1147
  }
1574
1148
  const properties = objLiteral.getProperties();
1575
1149
  for (const prop of properties) {
1576
- if (Node9.isPropertyAssignment(prop)) {
1150
+ if (Node.isPropertyAssignment(prop)) {
1577
1151
  const propName = prop.getName();
1578
1152
  const value = prop.getInitializer()?.getText();
1579
1153
  switch (propName) {
@@ -1605,9 +1179,9 @@ var DrizzleSchemaParser = class {
1605
1179
  }
1606
1180
  parseCallChain(callExpr, fieldInfo) {
1607
1181
  let current = callExpr;
1608
- while (Node9.isCallExpression(current)) {
1182
+ while (Node.isCallExpression(current)) {
1609
1183
  const expression = current.getExpression();
1610
- if (Node9.isPropertyAccessExpression(expression)) {
1184
+ if (Node.isPropertyAccessExpression(expression)) {
1611
1185
  const methodName = expression.getName();
1612
1186
  const args = current.getArguments();
1613
1187
  switch (methodName) {
@@ -1704,7 +1278,7 @@ var require2 = createRequire(import.meta.url);
1704
1278
  async function run(options = {}) {
1705
1279
  let exitCode = 0;
1706
1280
  const envPath2 = path2.resolve(process.cwd(), ".env");
1707
- if (fs4.existsSync(envPath2)) {
1281
+ if (fs3.existsSync(envPath2)) {
1708
1282
  loadEnv({ path: envPath2 });
1709
1283
  console.log("[gen-db-schema] \u2713 Loaded .env file");
1710
1284
  }
@@ -1724,7 +1298,7 @@ async function run(options = {}) {
1724
1298
  path2.resolve(__dirname2, "../../config/drizzle.config.js"),
1725
1299
  path2.resolve(__dirname2, "../../../dist/config/drizzle.config.js")
1726
1300
  ];
1727
- const configPath = configPathCandidates.find((p) => fs4.existsSync(p));
1301
+ const configPath = configPathCandidates.find((p) => fs3.existsSync(p));
1728
1302
  console.log("[gen-db-schema] Using drizzle config from:", configPath ?? "(not found)");
1729
1303
  if (!configPath) {
1730
1304
  console.error("[gen-db-schema] Error: drizzle config not found in CLI package");
@@ -1736,8 +1310,8 @@ async function run(options = {}) {
1736
1310
  let lastDir = null;
1737
1311
  while (currentDir !== lastDir) {
1738
1312
  const pkgJsonPath = path2.join(currentDir, "package.json");
1739
- if (fs4.existsSync(pkgJsonPath)) {
1740
- const pkgJsonRaw = fs4.readFileSync(pkgJsonPath, "utf8");
1313
+ if (fs3.existsSync(pkgJsonPath)) {
1314
+ const pkgJsonRaw = fs3.readFileSync(pkgJsonPath, "utf8");
1741
1315
  const pkgJson = JSON.parse(pkgJsonRaw);
1742
1316
  if (pkgJson.name === "drizzle-kit") {
1743
1317
  const binField = pkgJson.bin;
@@ -1772,7 +1346,7 @@ async function run(options = {}) {
1772
1346
  throw new Error(`drizzle-kit introspect failed with status ${result.status}`);
1773
1347
  }
1774
1348
  const generatedSchema = path2.join(OUT_DIR, "schema.ts");
1775
- if (!fs4.existsSync(generatedSchema)) {
1349
+ if (!fs3.existsSync(generatedSchema)) {
1776
1350
  console.error("[gen-db-schema] schema.ts not generated");
1777
1351
  throw new Error("drizzle-kit introspect failed to generate schema.ts");
1778
1352
  }
@@ -1781,8 +1355,8 @@ async function run(options = {}) {
1781
1355
  console.warn("[gen-db-schema] Unmatched custom types detected:", stats.unmatchedUnknown);
1782
1356
  }
1783
1357
  console.log("[gen-db-schema] \u2713 Postprocessed schema");
1784
- fs4.mkdirSync(path2.dirname(SCHEMA_FILE), { recursive: true });
1785
- fs4.copyFileSync(generatedSchema, SCHEMA_FILE);
1358
+ fs3.mkdirSync(path2.dirname(SCHEMA_FILE), { recursive: true });
1359
+ fs3.copyFileSync(generatedSchema, SCHEMA_FILE);
1786
1360
  console.log(`[gen-db-schema] \u2713 Copied to ${outputPath}`);
1787
1361
  try {
1788
1362
  if (options.enableNestModuleGenerate) {
@@ -1803,8 +1377,8 @@ async function run(options = {}) {
1803
1377
  console.error("[gen-db-schema] Failed:", err instanceof Error ? err.message : String(err));
1804
1378
  exitCode = 1;
1805
1379
  } finally {
1806
- if (fs4.existsSync(OUT_DIR)) {
1807
- fs4.rmSync(OUT_DIR, { recursive: true, force: true });
1380
+ if (fs3.existsSync(OUT_DIR)) {
1381
+ fs3.rmSync(OUT_DIR, { recursive: true, force: true });
1808
1382
  }
1809
1383
  process.exit(exitCode);
1810
1384
  }
@@ -1823,7 +1397,7 @@ var genDbSchemaCommand = {
1823
1397
 
1824
1398
  // src/commands/sync/run.handler.ts
1825
1399
  import path4 from "path";
1826
- import fs6 from "fs";
1400
+ import fs5 from "fs";
1827
1401
  import { fileURLToPath as fileURLToPath3 } from "url";
1828
1402
 
1829
1403
  // src/config/sync.ts
@@ -1887,14 +1461,14 @@ function genSyncConfig(perms = {}) {
1887
1461
  }
1888
1462
 
1889
1463
  // src/utils/file-ops.ts
1890
- import fs5 from "fs";
1464
+ import fs4 from "fs";
1891
1465
  import path3 from "path";
1892
1466
  function removeLineFromFile(filePath, pattern) {
1893
- if (!fs5.existsSync(filePath)) {
1467
+ if (!fs4.existsSync(filePath)) {
1894
1468
  console.log(`[fullstack-cli] \u25CB ${path3.basename(filePath)} (not found)`);
1895
1469
  return false;
1896
1470
  }
1897
- const content = fs5.readFileSync(filePath, "utf-8");
1471
+ const content = fs4.readFileSync(filePath, "utf-8");
1898
1472
  const lines = content.split("\n");
1899
1473
  const trimmedPattern = pattern.trim();
1900
1474
  const filteredLines = lines.filter((line) => line.trim() !== trimmedPattern);
@@ -1902,7 +1476,7 @@ function removeLineFromFile(filePath, pattern) {
1902
1476
  console.log(`[fullstack-cli] \u25CB ${path3.basename(filePath)} (pattern not found: ${pattern})`);
1903
1477
  return false;
1904
1478
  }
1905
- fs5.writeFileSync(filePath, filteredLines.join("\n"));
1479
+ fs4.writeFileSync(filePath, filteredLines.join("\n"));
1906
1480
  console.log(`[fullstack-cli] \u2713 ${path3.basename(filePath)} (removed: ${pattern})`);
1907
1481
  return true;
1908
1482
  }
@@ -1918,7 +1492,7 @@ async function run2(options) {
1918
1492
  process.exit(0);
1919
1493
  }
1920
1494
  const userPackageJson = path4.join(userProjectRoot, "package.json");
1921
- if (!fs6.existsSync(userPackageJson)) {
1495
+ if (!fs5.existsSync(userPackageJson)) {
1922
1496
  console.log("[fullstack-cli] Skip syncing (not a valid npm project)");
1923
1497
  process.exit(0);
1924
1498
  }
@@ -1964,7 +1538,7 @@ async function syncRule(rule, pluginRoot, userProjectRoot) {
1964
1538
  }
1965
1539
  const srcPath = path4.join(pluginRoot, rule.from);
1966
1540
  const destPath = path4.join(userProjectRoot, rule.to);
1967
- if (!fs6.existsSync(srcPath)) {
1541
+ if (!fs5.existsSync(srcPath)) {
1968
1542
  console.warn(`[fullstack-cli] Source not found: ${rule.from}`);
1969
1543
  return;
1970
1544
  }
@@ -1982,31 +1556,31 @@ async function syncRule(rule, pluginRoot, userProjectRoot) {
1982
1556
  }
1983
1557
  function syncFile(src, dest, overwrite = true) {
1984
1558
  const destDir = path4.dirname(dest);
1985
- if (!fs6.existsSync(destDir)) {
1986
- fs6.mkdirSync(destDir, { recursive: true });
1559
+ if (!fs5.existsSync(destDir)) {
1560
+ fs5.mkdirSync(destDir, { recursive: true });
1987
1561
  }
1988
- if (fs6.existsSync(dest) && !overwrite) {
1562
+ if (fs5.existsSync(dest) && !overwrite) {
1989
1563
  console.log(`[fullstack-cli] \u25CB ${path4.basename(dest)} (skipped, already exists)`);
1990
1564
  return;
1991
1565
  }
1992
- fs6.copyFileSync(src, dest);
1566
+ fs5.copyFileSync(src, dest);
1993
1567
  console.log(`[fullstack-cli] \u2713 ${path4.basename(dest)}`);
1994
1568
  }
1995
1569
  function syncDirectory(src, dest, overwrite = true) {
1996
- if (!fs6.existsSync(dest)) {
1997
- fs6.mkdirSync(dest, { recursive: true });
1570
+ if (!fs5.existsSync(dest)) {
1571
+ fs5.mkdirSync(dest, { recursive: true });
1998
1572
  }
1999
- const files = fs6.readdirSync(src);
1573
+ const files = fs5.readdirSync(src);
2000
1574
  let count = 0;
2001
1575
  files.forEach((file) => {
2002
1576
  const srcFile = path4.join(src, file);
2003
1577
  const destFile = path4.join(dest, file);
2004
- const stats = fs6.statSync(srcFile);
1578
+ const stats = fs5.statSync(srcFile);
2005
1579
  if (stats.isDirectory()) {
2006
1580
  syncDirectory(srcFile, destFile, overwrite);
2007
1581
  } else {
2008
- if (overwrite || !fs6.existsSync(destFile)) {
2009
- fs6.copyFileSync(srcFile, destFile);
1582
+ if (overwrite || !fs5.existsSync(destFile)) {
1583
+ fs5.copyFileSync(srcFile, destFile);
2010
1584
  console.log(`[fullstack-cli] \u2713 ${path4.relative(dest, destFile)}`);
2011
1585
  count++;
2012
1586
  }
@@ -2017,28 +1591,28 @@ function syncDirectory(src, dest, overwrite = true) {
2017
1591
  }
2018
1592
  }
2019
1593
  function appendToFile(src, dest) {
2020
- const content = fs6.readFileSync(src, "utf-8");
1594
+ const content = fs5.readFileSync(src, "utf-8");
2021
1595
  let existingContent = "";
2022
- if (fs6.existsSync(dest)) {
2023
- existingContent = fs6.readFileSync(dest, "utf-8");
1596
+ if (fs5.existsSync(dest)) {
1597
+ existingContent = fs5.readFileSync(dest, "utf-8");
2024
1598
  }
2025
1599
  if (existingContent.includes(content.trim())) {
2026
1600
  console.log(`[fullstack-cli] \u25CB ${path4.basename(dest)} (already contains content)`);
2027
1601
  return;
2028
1602
  }
2029
- fs6.appendFileSync(dest, content);
1603
+ fs5.appendFileSync(dest, content);
2030
1604
  console.log(`[fullstack-cli] \u2713 ${path4.basename(dest)} (appended)`);
2031
1605
  }
2032
1606
  function setPermissions(permissions, projectRoot) {
2033
1607
  for (const [pattern, mode] of Object.entries(permissions)) {
2034
1608
  if (pattern === "**/*.sh") {
2035
1609
  const scriptsDir = path4.join(projectRoot, "scripts");
2036
- if (fs6.existsSync(scriptsDir)) {
2037
- const files = fs6.readdirSync(scriptsDir);
1610
+ if (fs5.existsSync(scriptsDir)) {
1611
+ const files = fs5.readdirSync(scriptsDir);
2038
1612
  files.forEach((file) => {
2039
1613
  if (file.endsWith(".sh")) {
2040
1614
  const filePath = path4.join(scriptsDir, file);
2041
- fs6.chmodSync(filePath, mode);
1615
+ fs5.chmodSync(filePath, mode);
2042
1616
  }
2043
1617
  });
2044
1618
  }
@@ -2046,16 +1620,16 @@ function setPermissions(permissions, projectRoot) {
2046
1620
  }
2047
1621
  }
2048
1622
  function deleteFile(filePath) {
2049
- if (fs6.existsSync(filePath)) {
2050
- fs6.unlinkSync(filePath);
1623
+ if (fs5.existsSync(filePath)) {
1624
+ fs5.unlinkSync(filePath);
2051
1625
  console.log(`[fullstack-cli] \u2713 ${path4.basename(filePath)} (deleted)`);
2052
1626
  } else {
2053
1627
  console.log(`[fullstack-cli] \u25CB ${path4.basename(filePath)} (not found)`);
2054
1628
  }
2055
1629
  }
2056
1630
  function deleteDirectory(dirPath) {
2057
- if (fs6.existsSync(dirPath)) {
2058
- fs6.rmSync(dirPath, { recursive: true });
1631
+ if (fs5.existsSync(dirPath)) {
1632
+ fs5.rmSync(dirPath, { recursive: true });
2059
1633
  console.log(`[fullstack-cli] \u2713 ${path4.basename(dirPath)} (deleted)`);
2060
1634
  } else {
2061
1635
  console.log(`[fullstack-cli] \u25CB ${path4.basename(dirPath)} (not found)`);
@@ -2074,7 +1648,7 @@ var syncCommand = {
2074
1648
  };
2075
1649
 
2076
1650
  // src/commands/action-plugin/utils.ts
2077
- import fs7 from "fs";
1651
+ import fs6 from "fs";
2078
1652
  import path5 from "path";
2079
1653
  import { spawnSync as spawnSync2, execSync } from "child_process";
2080
1654
  function parsePluginName(input) {
@@ -2100,11 +1674,11 @@ function getPluginPath(pluginName) {
2100
1674
  }
2101
1675
  function readPackageJson() {
2102
1676
  const pkgPath = getPackageJsonPath();
2103
- if (!fs7.existsSync(pkgPath)) {
1677
+ if (!fs6.existsSync(pkgPath)) {
2104
1678
  throw new Error("package.json not found in current directory");
2105
1679
  }
2106
1680
  try {
2107
- const content = fs7.readFileSync(pkgPath, "utf-8");
1681
+ const content = fs6.readFileSync(pkgPath, "utf-8");
2108
1682
  return JSON.parse(content);
2109
1683
  } catch {
2110
1684
  throw new Error("Failed to parse package.json");
@@ -2112,7 +1686,7 @@ function readPackageJson() {
2112
1686
  }
2113
1687
  function writePackageJson(pkg2) {
2114
1688
  const pkgPath = getPackageJsonPath();
2115
- fs7.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
1689
+ fs6.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
2116
1690
  }
2117
1691
  function readActionPlugins() {
2118
1692
  const pkg2 = readPackageJson();
@@ -2146,11 +1720,11 @@ function npmInstall(tgzPath) {
2146
1720
  }
2147
1721
  function getPackageVersion(pluginName) {
2148
1722
  const pkgJsonPath = path5.join(getPluginPath(pluginName), "package.json");
2149
- if (!fs7.existsSync(pkgJsonPath)) {
1723
+ if (!fs6.existsSync(pkgJsonPath)) {
2150
1724
  return null;
2151
1725
  }
2152
1726
  try {
2153
- const content = fs7.readFileSync(pkgJsonPath, "utf-8");
1727
+ const content = fs6.readFileSync(pkgJsonPath, "utf-8");
2154
1728
  const pkg2 = JSON.parse(content);
2155
1729
  return pkg2.version || null;
2156
1730
  } catch {
@@ -2159,11 +1733,11 @@ function getPackageVersion(pluginName) {
2159
1733
  }
2160
1734
  function readPluginPackageJson(pluginPath) {
2161
1735
  const pkgJsonPath = path5.join(pluginPath, "package.json");
2162
- if (!fs7.existsSync(pkgJsonPath)) {
1736
+ if (!fs6.existsSync(pkgJsonPath)) {
2163
1737
  return null;
2164
1738
  }
2165
1739
  try {
2166
- const content = fs7.readFileSync(pkgJsonPath, "utf-8");
1740
+ const content = fs6.readFileSync(pkgJsonPath, "utf-8");
2167
1741
  return JSON.parse(content);
2168
1742
  } catch {
2169
1743
  return null;
@@ -2173,34 +1747,34 @@ function extractTgzToNodeModules(tgzPath, pluginName) {
2173
1747
  const nodeModulesPath = path5.join(getProjectRoot(), "node_modules");
2174
1748
  const targetDir = path5.join(nodeModulesPath, pluginName);
2175
1749
  const scopeDir = path5.dirname(targetDir);
2176
- if (!fs7.existsSync(scopeDir)) {
2177
- fs7.mkdirSync(scopeDir, { recursive: true });
1750
+ if (!fs6.existsSync(scopeDir)) {
1751
+ fs6.mkdirSync(scopeDir, { recursive: true });
2178
1752
  }
2179
- if (fs7.existsSync(targetDir)) {
2180
- fs7.rmSync(targetDir, { recursive: true });
1753
+ if (fs6.existsSync(targetDir)) {
1754
+ fs6.rmSync(targetDir, { recursive: true });
2181
1755
  }
2182
1756
  const tempDir = path5.join(nodeModulesPath, ".cache", "fullstack-cli", "extract-temp");
2183
- if (fs7.existsSync(tempDir)) {
2184
- fs7.rmSync(tempDir, { recursive: true });
1757
+ if (fs6.existsSync(tempDir)) {
1758
+ fs6.rmSync(tempDir, { recursive: true });
2185
1759
  }
2186
- fs7.mkdirSync(tempDir, { recursive: true });
1760
+ fs6.mkdirSync(tempDir, { recursive: true });
2187
1761
  try {
2188
1762
  execSync(`tar -xzf "${tgzPath}" -C "${tempDir}"`, { stdio: "pipe" });
2189
1763
  const extractedDir = path5.join(tempDir, "package");
2190
- if (fs7.existsSync(extractedDir)) {
2191
- fs7.renameSync(extractedDir, targetDir);
1764
+ if (fs6.existsSync(extractedDir)) {
1765
+ fs6.renameSync(extractedDir, targetDir);
2192
1766
  } else {
2193
- const files = fs7.readdirSync(tempDir);
1767
+ const files = fs6.readdirSync(tempDir);
2194
1768
  if (files.length === 1) {
2195
- fs7.renameSync(path5.join(tempDir, files[0]), targetDir);
1769
+ fs6.renameSync(path5.join(tempDir, files[0]), targetDir);
2196
1770
  } else {
2197
1771
  throw new Error("Unexpected tgz structure");
2198
1772
  }
2199
1773
  }
2200
1774
  return targetDir;
2201
1775
  } finally {
2202
- if (fs7.existsSync(tempDir)) {
2203
- fs7.rmSync(tempDir, { recursive: true });
1776
+ if (fs6.existsSync(tempDir)) {
1777
+ fs6.rmSync(tempDir, { recursive: true });
2204
1778
  }
2205
1779
  }
2206
1780
  }
@@ -2212,7 +1786,7 @@ function checkMissingPeerDeps(peerDeps) {
2212
1786
  const nodeModulesPath = path5.join(getProjectRoot(), "node_modules");
2213
1787
  for (const [depName, _version] of Object.entries(peerDeps)) {
2214
1788
  const depPath = path5.join(nodeModulesPath, depName);
2215
- if (!fs7.existsSync(depPath)) {
1789
+ if (!fs6.existsSync(depPath)) {
2216
1790
  missing.push(depName);
2217
1791
  }
2218
1792
  }
@@ -2236,15 +1810,15 @@ function installMissingDeps(deps) {
2236
1810
  }
2237
1811
  function removePluginDirectory(pluginName) {
2238
1812
  const pluginPath = getPluginPath(pluginName);
2239
- if (fs7.existsSync(pluginPath)) {
2240
- fs7.rmSync(pluginPath, { recursive: true });
1813
+ if (fs6.existsSync(pluginPath)) {
1814
+ fs6.rmSync(pluginPath, { recursive: true });
2241
1815
  console.log(`[action-plugin] Removed ${pluginName}`);
2242
1816
  }
2243
1817
  }
2244
1818
 
2245
1819
  // src/commands/action-plugin/api-client.ts
2246
1820
  import { HttpClient as HttpClient2 } from "@lark-apaas/http-client";
2247
- import fs8 from "fs";
1821
+ import fs7 from "fs";
2248
1822
  import path6 from "path";
2249
1823
 
2250
1824
  // src/utils/http-client.ts
@@ -2258,13 +1832,10 @@ function getHttpClient() {
2258
1832
  enabled: true
2259
1833
  }
2260
1834
  });
2261
- const canaryEnv = process.env.FORCE_FRAMEWORK_CLI_CANARY_ENV;
2262
- if (canaryEnv) {
2263
- clientInstance.interceptors.request.use((req) => {
2264
- req.headers["x-tt-env"] = canaryEnv;
2265
- return req;
2266
- });
2267
- }
1835
+ clientInstance.interceptors.request.use((req) => {
1836
+ req.headers["x-tt-env"] = "boe_miaoda_plugin";
1837
+ return req;
1838
+ });
2268
1839
  }
2269
1840
  return clientInstance;
2270
1841
  }
@@ -2337,8 +1908,8 @@ function getPluginCacheDir() {
2337
1908
  }
2338
1909
  function ensureCacheDir() {
2339
1910
  const cacheDir = getPluginCacheDir();
2340
- if (!fs8.existsSync(cacheDir)) {
2341
- fs8.mkdirSync(cacheDir, { recursive: true });
1911
+ if (!fs7.existsSync(cacheDir)) {
1912
+ fs7.mkdirSync(cacheDir, { recursive: true });
2342
1913
  }
2343
1914
  }
2344
1915
  function getTempFilePath(pluginKey, version) {
@@ -2361,7 +1932,7 @@ async function downloadPlugin(pluginKey, requestedVersion) {
2361
1932
  tgzBuffer = await downloadFromPublic(pluginInfo.downloadURL);
2362
1933
  }
2363
1934
  const tgzPath = getTempFilePath(pluginKey, pluginInfo.version);
2364
- fs8.writeFileSync(tgzPath, tgzBuffer);
1935
+ fs7.writeFileSync(tgzPath, tgzBuffer);
2365
1936
  console.log(`[action-plugin] Downloaded to ${tgzPath} (${(tgzBuffer.length / 1024).toFixed(2)} KB)`);
2366
1937
  return {
2367
1938
  tgzPath,
@@ -2371,8 +1942,8 @@ async function downloadPlugin(pluginKey, requestedVersion) {
2371
1942
  }
2372
1943
  function cleanupTempFile(tgzPath) {
2373
1944
  try {
2374
- if (fs8.existsSync(tgzPath)) {
2375
- fs8.unlinkSync(tgzPath);
1945
+ if (fs7.existsSync(tgzPath)) {
1946
+ fs7.unlinkSync(tgzPath);
2376
1947
  }
2377
1948
  } catch {
2378
1949
  }
@@ -2708,7 +2279,7 @@ var actionPluginCommandGroup = {
2708
2279
  };
2709
2280
 
2710
2281
  // src/commands/capability/utils.ts
2711
- import fs9 from "fs";
2282
+ import fs8 from "fs";
2712
2283
  import path7 from "path";
2713
2284
  var CAPABILITIES_DIR = "server/capabilities";
2714
2285
  function getProjectRoot2() {
@@ -2724,23 +2295,23 @@ function getPluginManifestPath(pluginKey) {
2724
2295
  return path7.join(getProjectRoot2(), "node_modules", pluginKey, "manifest.json");
2725
2296
  }
2726
2297
  function capabilitiesDirExists() {
2727
- return fs9.existsSync(getCapabilitiesDir());
2298
+ return fs8.existsSync(getCapabilitiesDir());
2728
2299
  }
2729
2300
  function listCapabilityIds() {
2730
2301
  const dir = getCapabilitiesDir();
2731
- if (!fs9.existsSync(dir)) {
2302
+ if (!fs8.existsSync(dir)) {
2732
2303
  return [];
2733
2304
  }
2734
- const files = fs9.readdirSync(dir);
2735
- return files.filter((f) => f.endsWith(".json") && f !== "capabilities.json").map((f) => f.replace(/\.json$/, ""));
2305
+ const files = fs8.readdirSync(dir);
2306
+ return files.filter((f) => f.endsWith(".json")).map((f) => f.replace(/\.json$/, ""));
2736
2307
  }
2737
2308
  function readCapability(id) {
2738
2309
  const filePath = getCapabilityPath(id);
2739
- if (!fs9.existsSync(filePath)) {
2310
+ if (!fs8.existsSync(filePath)) {
2740
2311
  throw new Error(`Capability not found: ${id}`);
2741
2312
  }
2742
2313
  try {
2743
- const content = fs9.readFileSync(filePath, "utf-8");
2314
+ const content = fs8.readFileSync(filePath, "utf-8");
2744
2315
  return JSON.parse(content);
2745
2316
  } catch (error) {
2746
2317
  if (error instanceof SyntaxError) {
@@ -2751,27 +2322,15 @@ function readCapability(id) {
2751
2322
  }
2752
2323
  function readAllCapabilities() {
2753
2324
  const ids = listCapabilityIds();
2754
- const capabilities = [];
2755
- for (const id of ids) {
2756
- try {
2757
- const capability = readCapability(id);
2758
- if (!capability.pluginKey) {
2759
- continue;
2760
- }
2761
- capabilities.push(capability);
2762
- } catch {
2763
- continue;
2764
- }
2765
- }
2766
- return capabilities;
2325
+ return ids.map((id) => readCapability(id));
2767
2326
  }
2768
2327
  function readPluginManifest(pluginKey) {
2769
2328
  const manifestPath = getPluginManifestPath(pluginKey);
2770
- if (!fs9.existsSync(manifestPath)) {
2329
+ if (!fs8.existsSync(manifestPath)) {
2771
2330
  throw new Error(`Plugin not installed: ${pluginKey} (manifest.json not found)`);
2772
2331
  }
2773
2332
  try {
2774
- const content = fs9.readFileSync(manifestPath, "utf-8");
2333
+ const content = fs8.readFileSync(manifestPath, "utf-8");
2775
2334
  return JSON.parse(content);
2776
2335
  } catch (error) {
2777
2336
  if (error instanceof SyntaxError) {
@@ -2945,7 +2504,7 @@ var capabilityCommandGroup = {
2945
2504
  };
2946
2505
 
2947
2506
  // src/commands/migration/version-manager.ts
2948
- import fs10 from "fs";
2507
+ import fs9 from "fs";
2949
2508
  import path8 from "path";
2950
2509
  var PACKAGE_JSON = "package.json";
2951
2510
  var VERSION_FIELD = "migrationVersion";
@@ -2954,25 +2513,25 @@ function getPackageJsonPath2() {
2954
2513
  }
2955
2514
  function getCurrentVersion() {
2956
2515
  const pkgPath = getPackageJsonPath2();
2957
- if (!fs10.existsSync(pkgPath)) {
2516
+ if (!fs9.existsSync(pkgPath)) {
2958
2517
  throw new Error("package.json not found");
2959
2518
  }
2960
- const pkg2 = JSON.parse(fs10.readFileSync(pkgPath, "utf-8"));
2519
+ const pkg2 = JSON.parse(fs9.readFileSync(pkgPath, "utf-8"));
2961
2520
  return pkg2[VERSION_FIELD] ?? 0;
2962
2521
  }
2963
2522
  function setCurrentVersion(version) {
2964
2523
  const pkgPath = getPackageJsonPath2();
2965
- const pkg2 = JSON.parse(fs10.readFileSync(pkgPath, "utf-8"));
2524
+ const pkg2 = JSON.parse(fs9.readFileSync(pkgPath, "utf-8"));
2966
2525
  pkg2[VERSION_FIELD] = version;
2967
- fs10.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
2526
+ fs9.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
2968
2527
  }
2969
2528
 
2970
2529
  // src/commands/migration/versions/v001_capability/json-migrator/detector.ts
2971
- import fs12 from "fs";
2530
+ import fs11 from "fs";
2972
2531
  import path10 from "path";
2973
2532
 
2974
2533
  // src/commands/migration/versions/v001_capability/utils.ts
2975
- import fs11 from "fs";
2534
+ import fs10 from "fs";
2976
2535
  import path9 from "path";
2977
2536
  var CAPABILITIES_DIR2 = "server/capabilities";
2978
2537
  function getProjectRoot3() {
@@ -2989,30 +2548,19 @@ function getPluginManifestPath2(pluginKey) {
2989
2548
  function detectJsonMigration() {
2990
2549
  const capabilitiesDir = getCapabilitiesDir2();
2991
2550
  const oldFilePath = path10.join(capabilitiesDir, "capabilities.json");
2992
- if (!fs12.existsSync(oldFilePath)) {
2551
+ if (!fs11.existsSync(oldFilePath)) {
2993
2552
  return {
2994
2553
  needsMigration: false,
2995
2554
  reason: "capabilities.json not found"
2996
2555
  };
2997
2556
  }
2998
2557
  try {
2999
- const content = fs12.readFileSync(oldFilePath, "utf-8");
2558
+ const content = fs11.readFileSync(oldFilePath, "utf-8");
3000
2559
  const parsed = JSON.parse(content);
3001
- if (!Array.isArray(parsed)) {
3002
- return {
3003
- needsMigration: false,
3004
- reason: "capabilities.json is not a valid array"
3005
- };
3006
- }
3007
- if (parsed.length === 0) {
3008
- return {
3009
- needsMigration: false,
3010
- reason: "capabilities.json is an empty array"
3011
- };
3012
- }
2560
+ const capabilities = Array.isArray(parsed) ? parsed : [];
3013
2561
  return {
3014
2562
  needsMigration: true,
3015
- oldCapabilities: parsed,
2563
+ oldCapabilities: capabilities,
3016
2564
  oldFilePath
3017
2565
  };
3018
2566
  } catch (error) {
@@ -3047,7 +2595,7 @@ async function check(options) {
3047
2595
  }
3048
2596
 
3049
2597
  // src/commands/migration/versions/v001_capability/json-migrator/index.ts
3050
- import fs13 from "fs";
2598
+ import fs12 from "fs";
3051
2599
  import path11 from "path";
3052
2600
 
3053
2601
  // src/commands/migration/versions/v001_capability/mapping.ts
@@ -3278,10 +2826,10 @@ function transformCapabilities(oldCapabilities) {
3278
2826
  // src/commands/migration/versions/v001_capability/json-migrator/index.ts
3279
2827
  function loadExistingCapabilities() {
3280
2828
  const capabilitiesDir = getCapabilitiesDir2();
3281
- if (!fs13.existsSync(capabilitiesDir)) {
2829
+ if (!fs12.existsSync(capabilitiesDir)) {
3282
2830
  return [];
3283
2831
  }
3284
- const files = fs13.readdirSync(capabilitiesDir);
2832
+ const files = fs12.readdirSync(capabilitiesDir);
3285
2833
  const capabilities = [];
3286
2834
  for (const file of files) {
3287
2835
  if (file === "capabilities.json" || !file.endsWith(".json")) {
@@ -3289,7 +2837,7 @@ function loadExistingCapabilities() {
3289
2837
  }
3290
2838
  try {
3291
2839
  const filePath = path11.join(capabilitiesDir, file);
3292
- const content = fs13.readFileSync(filePath, "utf-8");
2840
+ const content = fs12.readFileSync(filePath, "utf-8");
3293
2841
  const capability = JSON.parse(content);
3294
2842
  if (capability.id && capability.pluginKey) {
3295
2843
  capabilities.push(capability);
@@ -3349,7 +2897,7 @@ async function migrateJsonFiles(options) {
3349
2897
  for (const cap of newCapabilities) {
3350
2898
  const filePath = path11.join(capabilitiesDir, `${cap.id}.json`);
3351
2899
  const content = JSON.stringify(cap, null, 2);
3352
- fs13.writeFileSync(filePath, content, "utf-8");
2900
+ fs12.writeFileSync(filePath, content, "utf-8");
3353
2901
  console.log(` \u2713 Created: ${cap.id}.json`);
3354
2902
  }
3355
2903
  return {
@@ -3361,11 +2909,11 @@ async function migrateJsonFiles(options) {
3361
2909
  }
3362
2910
 
3363
2911
  // src/commands/migration/versions/v001_capability/plugin-installer/detector.ts
3364
- import fs14 from "fs";
2912
+ import fs13 from "fs";
3365
2913
  function isPluginInstalled2(pluginKey) {
3366
2914
  const actionPlugins = readActionPlugins();
3367
2915
  const manifestPath = getPluginManifestPath2(pluginKey);
3368
- return fs14.existsSync(manifestPath) && !!actionPlugins[pluginKey];
2916
+ return fs13.existsSync(manifestPath) && !!actionPlugins[pluginKey];
3369
2917
  }
3370
2918
  function detectPluginsToInstall(capabilities) {
3371
2919
  const pluginKeys = /* @__PURE__ */ new Set();
@@ -3442,10 +2990,10 @@ async function installPlugins(capabilities, options) {
3442
2990
 
3443
2991
  // src/commands/migration/versions/v001_capability/code-migrator/index.ts
3444
2992
  import path13 from "path";
3445
- import { Project as Project3 } from "ts-morph";
2993
+ import { Project as Project2 } from "ts-morph";
3446
2994
 
3447
2995
  // src/commands/migration/versions/v001_capability/code-migrator/scanner.ts
3448
- import fs15 from "fs";
2996
+ import fs14 from "fs";
3449
2997
  import path12 from "path";
3450
2998
  var EXCLUDED_DIRS = [
3451
2999
  "node_modules",
@@ -3461,7 +3009,7 @@ var EXCLUDED_PATTERNS = [
3461
3009
  /\.d\.ts$/
3462
3010
  ];
3463
3011
  function scanDirectory(dir, files = []) {
3464
- const entries = fs15.readdirSync(dir, { withFileTypes: true });
3012
+ const entries = fs14.readdirSync(dir, { withFileTypes: true });
3465
3013
  for (const entry of entries) {
3466
3014
  const fullPath = path12.join(dir, entry.name);
3467
3015
  if (entry.isDirectory()) {
@@ -3480,13 +3028,13 @@ function scanDirectory(dir, files = []) {
3480
3028
  }
3481
3029
  function scanServerFiles() {
3482
3030
  const serverDir = path12.join(getProjectRoot3(), "server");
3483
- if (!fs15.existsSync(serverDir)) {
3031
+ if (!fs14.existsSync(serverDir)) {
3484
3032
  return [];
3485
3033
  }
3486
3034
  return scanDirectory(serverDir);
3487
3035
  }
3488
3036
  function hasCapabilityImport(filePath) {
3489
- const content = fs15.readFileSync(filePath, "utf-8");
3037
+ const content = fs14.readFileSync(filePath, "utf-8");
3490
3038
  return /import\s+.*from\s+['"][^'"]*capabilities[^'"]*['"]/.test(content);
3491
3039
  }
3492
3040
  function scanFilesToMigrate() {
@@ -3550,17 +3098,17 @@ function analyzeImports(sourceFile) {
3550
3098
  }
3551
3099
 
3552
3100
  // src/commands/migration/versions/v001_capability/code-migrator/analyzers/call-site-analyzer.ts
3553
- import { SyntaxKind as SyntaxKind6 } from "ts-morph";
3101
+ import { SyntaxKind } from "ts-morph";
3554
3102
  function analyzeCallSites(sourceFile, imports) {
3555
3103
  const callSites = [];
3556
3104
  const importMap = /* @__PURE__ */ new Map();
3557
3105
  for (const imp of imports) {
3558
3106
  importMap.set(imp.importName, imp.capabilityId);
3559
3107
  }
3560
- const callExpressions = sourceFile.getDescendantsOfKind(SyntaxKind6.CallExpression);
3108
+ const callExpressions = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression);
3561
3109
  for (const callExpr of callExpressions) {
3562
3110
  const expression = callExpr.getExpression();
3563
- if (expression.getKind() === SyntaxKind6.Identifier) {
3111
+ if (expression.getKind() === SyntaxKind.Identifier) {
3564
3112
  const functionName = expression.getText();
3565
3113
  const capabilityId = importMap.get(functionName);
3566
3114
  if (capabilityId) {
@@ -3573,11 +3121,11 @@ function analyzeCallSites(sourceFile, imports) {
3573
3121
  text: callExpr.getText()
3574
3122
  });
3575
3123
  }
3576
- } else if (expression.getKind() === SyntaxKind6.PropertyAccessExpression) {
3577
- const propAccess = expression.asKind(SyntaxKind6.PropertyAccessExpression);
3124
+ } else if (expression.getKind() === SyntaxKind.PropertyAccessExpression) {
3125
+ const propAccess = expression.asKind(SyntaxKind.PropertyAccessExpression);
3578
3126
  if (propAccess) {
3579
3127
  const objectExpr = propAccess.getExpression();
3580
- if (objectExpr.getKind() === SyntaxKind6.Identifier) {
3128
+ if (objectExpr.getKind() === SyntaxKind.Identifier) {
3581
3129
  const objectName = objectExpr.getText();
3582
3130
  const capabilityId = importMap.get(objectName);
3583
3131
  if (capabilityId) {
@@ -3613,15 +3161,13 @@ function analyzeClass(sourceFile) {
3613
3161
  if (!name) continue;
3614
3162
  const isInjectable = hasDecorator(classDecl, "Injectable");
3615
3163
  const isController = hasDecorator(classDecl, "Controller");
3616
- const isAutomation = hasDecorator(classDecl, "Automation");
3617
- if (classInfo && classInfo.isInjectable && !isInjectable && !isController && !isAutomation) {
3164
+ if (classInfo && classInfo.isInjectable && !isInjectable && !isController) {
3618
3165
  continue;
3619
3166
  }
3620
3167
  const info = {
3621
3168
  name,
3622
3169
  isInjectable,
3623
3170
  isController,
3624
- isAutomation,
3625
3171
  constructorParamCount: 0
3626
3172
  };
3627
3173
  const classBody = classDecl.getChildSyntaxListOrThrow();
@@ -3640,7 +3186,7 @@ function analyzeClass(sourceFile) {
3640
3186
  info.constructorParamsEnd = ctor.getStart();
3641
3187
  }
3642
3188
  }
3643
- if (isInjectable || isController || isAutomation || !classInfo) {
3189
+ if (isInjectable || isController || !classInfo) {
3644
3190
  classInfo = info;
3645
3191
  }
3646
3192
  }
@@ -3653,10 +3199,10 @@ function canAutoMigrate(classInfo) {
3653
3199
  reason: "No class found in file"
3654
3200
  };
3655
3201
  }
3656
- if (!classInfo.isInjectable && !classInfo.isController && !classInfo.isAutomation) {
3202
+ if (!classInfo.isInjectable && !classInfo.isController) {
3657
3203
  return {
3658
3204
  canMigrate: false,
3659
- reason: `Class "${classInfo.name}" is not @Injectable, @Controller or @Automation`
3205
+ reason: `Class "${classInfo.name}" is not @Injectable or @Controller`
3660
3206
  };
3661
3207
  }
3662
3208
  return { canMigrate: true };
@@ -3806,7 +3352,7 @@ function addInjection(sourceFile) {
3806
3352
  }
3807
3353
 
3808
3354
  // src/commands/migration/versions/v001_capability/code-migrator/transformers/call-site-transformer.ts
3809
- import { SyntaxKind as SyntaxKind7 } from "ts-morph";
3355
+ import { SyntaxKind as SyntaxKind2 } from "ts-morph";
3810
3356
  var DEFAULT_ACTION_NAME = "run";
3811
3357
  function generateNewCallText(capabilityId, actionName, args) {
3812
3358
  const argsText = args.trim() || "{}";
@@ -3821,19 +3367,19 @@ function transformCallSites(sourceFile, imports) {
3821
3367
  });
3822
3368
  }
3823
3369
  let replacedCount = 0;
3824
- const callExpressions = sourceFile.getDescendantsOfKind(SyntaxKind7.CallExpression);
3370
+ const callExpressions = sourceFile.getDescendantsOfKind(SyntaxKind2.CallExpression);
3825
3371
  const sortedCalls = [...callExpressions].sort((a, b) => b.getStart() - a.getStart());
3826
3372
  for (const callExpr of sortedCalls) {
3827
3373
  const expression = callExpr.getExpression();
3828
3374
  let importInfo;
3829
- if (expression.getKind() === SyntaxKind7.Identifier) {
3375
+ if (expression.getKind() === SyntaxKind2.Identifier) {
3830
3376
  const functionName = expression.getText();
3831
3377
  importInfo = importMap.get(functionName);
3832
- } else if (expression.getKind() === SyntaxKind7.PropertyAccessExpression) {
3833
- const propAccess = expression.asKind(SyntaxKind7.PropertyAccessExpression);
3378
+ } else if (expression.getKind() === SyntaxKind2.PropertyAccessExpression) {
3379
+ const propAccess = expression.asKind(SyntaxKind2.PropertyAccessExpression);
3834
3380
  if (propAccess) {
3835
3381
  const objectExpr = propAccess.getExpression();
3836
- if (objectExpr.getKind() === SyntaxKind7.Identifier) {
3382
+ if (objectExpr.getKind() === SyntaxKind2.Identifier) {
3837
3383
  const objectName = objectExpr.getText();
3838
3384
  importInfo = importMap.get(objectName);
3839
3385
  }
@@ -3934,7 +3480,7 @@ async function migrateCode(options, capabilities) {
3934
3480
  console.log(" No files need code migration.\n");
3935
3481
  return result;
3936
3482
  }
3937
- const project = new Project3({
3483
+ const project = new Project2({
3938
3484
  skipAddingFilesFromTsConfig: true,
3939
3485
  compilerOptions: {
3940
3486
  allowJs: true
@@ -3977,17 +3523,17 @@ function getSuggestion(analysis) {
3977
3523
  }
3978
3524
 
3979
3525
  // src/commands/migration/versions/v001_capability/cleanup.ts
3980
- import fs16 from "fs";
3526
+ import fs15 from "fs";
3981
3527
  import path14 from "path";
3982
3528
  function cleanupOldFiles(capabilities, dryRun) {
3983
3529
  const deletedFiles = [];
3984
3530
  const errors = [];
3985
3531
  const capabilitiesDir = getCapabilitiesDir2();
3986
3532
  const oldJsonPath = path14.join(capabilitiesDir, "capabilities.json");
3987
- if (fs16.existsSync(oldJsonPath)) {
3533
+ if (fs15.existsSync(oldJsonPath)) {
3988
3534
  try {
3989
3535
  if (!dryRun) {
3990
- fs16.unlinkSync(oldJsonPath);
3536
+ fs15.unlinkSync(oldJsonPath);
3991
3537
  }
3992
3538
  deletedFiles.push("capabilities.json");
3993
3539
  } catch (error) {
@@ -3996,10 +3542,10 @@ function cleanupOldFiles(capabilities, dryRun) {
3996
3542
  }
3997
3543
  for (const cap of capabilities) {
3998
3544
  const tsFilePath = path14.join(capabilitiesDir, `${cap.id}.ts`);
3999
- if (fs16.existsSync(tsFilePath)) {
3545
+ if (fs15.existsSync(tsFilePath)) {
4000
3546
  try {
4001
3547
  if (!dryRun) {
4002
- fs16.unlinkSync(tsFilePath);
3548
+ fs15.unlinkSync(tsFilePath);
4003
3549
  }
4004
3550
  deletedFiles.push(`${cap.id}.ts`);
4005
3551
  } catch (error) {
@@ -4015,7 +3561,7 @@ function cleanupOldFiles(capabilities, dryRun) {
4015
3561
  }
4016
3562
 
4017
3563
  // src/commands/migration/versions/v001_capability/report-generator.ts
4018
- import fs17 from "fs";
3564
+ import fs16 from "fs";
4019
3565
  import path15 from "path";
4020
3566
  var REPORT_FILE = "capability-migration-report.md";
4021
3567
  function printSummary(result) {
@@ -4179,15 +3725,15 @@ async function generateReport(result) {
4179
3725
  }
4180
3726
  lines.push("");
4181
3727
  const logDir = process.env.LOG_DIR || "logs";
4182
- if (!fs17.existsSync(logDir)) {
3728
+ if (!fs16.existsSync(logDir)) {
4183
3729
  return;
4184
3730
  }
4185
3731
  const reportDir = path15.join(logDir, "migration");
4186
- if (!fs17.existsSync(reportDir)) {
4187
- fs17.mkdirSync(reportDir, { recursive: true });
3732
+ if (!fs16.existsSync(reportDir)) {
3733
+ fs16.mkdirSync(reportDir, { recursive: true });
4188
3734
  }
4189
3735
  const reportPath = path15.join(reportDir, REPORT_FILE);
4190
- fs17.writeFileSync(reportPath, lines.join("\n"), "utf-8");
3736
+ fs16.writeFileSync(reportPath, lines.join("\n"), "utf-8");
4191
3737
  console.log(`\u{1F4C4} Report generated: ${reportPath}`);
4192
3738
  }
4193
3739
 
@@ -4722,7 +4268,7 @@ var migrationCommand = {
4722
4268
  import path16 from "path";
4723
4269
 
4724
4270
  // src/commands/read-logs/std-utils.ts
4725
- import fs18 from "fs";
4271
+ import fs17 from "fs";
4726
4272
  function formatStdPrefixTime(localTime) {
4727
4273
  const match = localTime.match(/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/);
4728
4274
  if (!match) return localTime;
@@ -4752,11 +4298,11 @@ function stripPrefixFromStdLine(line) {
4752
4298
  return `[${time}] ${content}`;
4753
4299
  }
4754
4300
  function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarker) {
4755
- const stat = fs18.statSync(filePath);
4301
+ const stat = fs17.statSync(filePath);
4756
4302
  if (stat.size === 0) {
4757
4303
  return { lines: [], markerFound: false, totalLinesCount: 0 };
4758
4304
  }
4759
- const fd = fs18.openSync(filePath, "r");
4305
+ const fd = fs17.openSync(filePath, "r");
4760
4306
  const chunkSize = 64 * 1024;
4761
4307
  let position = stat.size;
4762
4308
  let remainder = "";
@@ -4770,7 +4316,7 @@ function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarke
4770
4316
  const length = Math.min(chunkSize, position);
4771
4317
  position -= length;
4772
4318
  const buffer = Buffer.alloc(length);
4773
- fs18.readSync(fd, buffer, 0, length, position);
4319
+ fs17.readSync(fd, buffer, 0, length, position);
4774
4320
  let chunk = buffer.toString("utf8");
4775
4321
  if (remainder) {
4776
4322
  chunk += remainder;
@@ -4812,7 +4358,7 @@ function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarke
4812
4358
  }
4813
4359
  }
4814
4360
  } finally {
4815
- fs18.closeSync(fd);
4361
+ fs17.closeSync(fd);
4816
4362
  }
4817
4363
  return { lines: collected.reverse(), markerFound, totalLinesCount };
4818
4364
  }
@@ -4833,21 +4379,21 @@ function readServerStdSegment(filePath, maxLines, offset) {
4833
4379
  }
4834
4380
 
4835
4381
  // src/commands/read-logs/tail.ts
4836
- import fs19 from "fs";
4382
+ import fs18 from "fs";
4837
4383
  function fileExists(filePath) {
4838
4384
  try {
4839
- fs19.accessSync(filePath, fs19.constants.F_OK | fs19.constants.R_OK);
4385
+ fs18.accessSync(filePath, fs18.constants.F_OK | fs18.constants.R_OK);
4840
4386
  return true;
4841
4387
  } catch {
4842
4388
  return false;
4843
4389
  }
4844
4390
  }
4845
4391
  function readFileTailLines(filePath, maxLines) {
4846
- const stat = fs19.statSync(filePath);
4392
+ const stat = fs18.statSync(filePath);
4847
4393
  if (stat.size === 0) {
4848
4394
  return [];
4849
4395
  }
4850
- const fd = fs19.openSync(filePath, "r");
4396
+ const fd = fs18.openSync(filePath, "r");
4851
4397
  const chunkSize = 64 * 1024;
4852
4398
  const chunks = [];
4853
4399
  let position = stat.size;
@@ -4857,13 +4403,13 @@ function readFileTailLines(filePath, maxLines) {
4857
4403
  const length = Math.min(chunkSize, position);
4858
4404
  position -= length;
4859
4405
  const buffer = Buffer.alloc(length);
4860
- fs19.readSync(fd, buffer, 0, length, position);
4406
+ fs18.readSync(fd, buffer, 0, length, position);
4861
4407
  chunks.unshift(buffer.toString("utf8"));
4862
4408
  const chunkLines = buffer.toString("utf8").split("\n").length - 1;
4863
4409
  collectedLines += chunkLines;
4864
4410
  }
4865
4411
  } finally {
4866
- fs19.closeSync(fd);
4412
+ fs18.closeSync(fd);
4867
4413
  }
4868
4414
  const content = chunks.join("");
4869
4415
  const allLines = content.split("\n");
@@ -4879,11 +4425,11 @@ function readFileTailLines(filePath, maxLines) {
4879
4425
  return allLines.slice(allLines.length - maxLines);
4880
4426
  }
4881
4427
  function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
4882
- const stat = fs19.statSync(filePath);
4428
+ const stat = fs18.statSync(filePath);
4883
4429
  if (stat.size === 0) {
4884
4430
  return { lines: [], totalLinesCount: 0 };
4885
4431
  }
4886
- const fd = fs19.openSync(filePath, "r");
4432
+ const fd = fs18.openSync(filePath, "r");
4887
4433
  const chunkSize = 64 * 1024;
4888
4434
  let position = stat.size;
4889
4435
  let remainder = "";
@@ -4895,7 +4441,7 @@ function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
4895
4441
  const length = Math.min(chunkSize, position);
4896
4442
  position -= length;
4897
4443
  const buffer = Buffer.alloc(length);
4898
- fs19.readSync(fd, buffer, 0, length, position);
4444
+ fs18.readSync(fd, buffer, 0, length, position);
4899
4445
  let chunk = buffer.toString("utf8");
4900
4446
  if (remainder) {
4901
4447
  chunk += remainder;
@@ -4926,7 +4472,7 @@ function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
4926
4472
  }
4927
4473
  }
4928
4474
  } finally {
4929
- fs19.closeSync(fd);
4475
+ fs18.closeSync(fd);
4930
4476
  }
4931
4477
  return { lines: collected.reverse(), totalLinesCount };
4932
4478
  }
@@ -5028,7 +4574,7 @@ function extractClientStdSegment(lines, maxLines, offset) {
5028
4574
  }
5029
4575
 
5030
4576
  // src/commands/read-logs/json-lines.ts
5031
- import fs20 from "fs";
4577
+ import fs19 from "fs";
5032
4578
  function normalizePid(value) {
5033
4579
  if (typeof value === "number") {
5034
4580
  return String(value);
@@ -5079,11 +4625,11 @@ function buildWantedLevelSet(levels) {
5079
4625
  return set.size > 0 ? set : null;
5080
4626
  }
5081
4627
  function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
5082
- const stat = fs20.statSync(filePath);
4628
+ const stat = fs19.statSync(filePath);
5083
4629
  if (stat.size === 0) {
5084
4630
  return { lines: [], totalLinesCount: 0 };
5085
4631
  }
5086
- const fd = fs20.openSync(filePath, "r");
4632
+ const fd = fs19.openSync(filePath, "r");
5087
4633
  const chunkSize = 64 * 1024;
5088
4634
  let position = stat.size;
5089
4635
  let remainder = "";
@@ -5098,7 +4644,7 @@ function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
5098
4644
  const length = Math.min(chunkSize, position);
5099
4645
  position -= length;
5100
4646
  const buffer = Buffer.alloc(length);
5101
- fs20.readSync(fd, buffer, 0, length, position);
4647
+ fs19.readSync(fd, buffer, 0, length, position);
5102
4648
  let chunk = buffer.toString("utf8");
5103
4649
  if (remainder) {
5104
4650
  chunk += remainder;
@@ -5160,7 +4706,7 @@ function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
5160
4706
  }
5161
4707
  }
5162
4708
  } finally {
5163
- fs20.closeSync(fd);
4709
+ fs19.closeSync(fd);
5164
4710
  }
5165
4711
  return { lines: collected.reverse(), totalLinesCount };
5166
4712
  }
@@ -5203,11 +4749,11 @@ function extractTraceId(obj) {
5203
4749
  function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
5204
4750
  const wanted = traceId.trim();
5205
4751
  if (!wanted) return { lines: [], totalLinesCount: 0 };
5206
- const stat = fs20.statSync(filePath);
4752
+ const stat = fs19.statSync(filePath);
5207
4753
  if (stat.size === 0) {
5208
4754
  return { lines: [], totalLinesCount: 0 };
5209
4755
  }
5210
- const fd = fs20.openSync(filePath, "r");
4756
+ const fd = fs19.openSync(filePath, "r");
5211
4757
  const chunkSize = 64 * 1024;
5212
4758
  let position = stat.size;
5213
4759
  let remainder = "";
@@ -5220,7 +4766,7 @@ function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
5220
4766
  const length = Math.min(chunkSize, position);
5221
4767
  position -= length;
5222
4768
  const buffer = Buffer.alloc(length);
5223
- fs20.readSync(fd, buffer, 0, length, position);
4769
+ fs19.readSync(fd, buffer, 0, length, position);
5224
4770
  let chunk = buffer.toString("utf8");
5225
4771
  if (remainder) {
5226
4772
  chunk += remainder;
@@ -5273,7 +4819,7 @@ function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
5273
4819
  }
5274
4820
  }
5275
4821
  } finally {
5276
- fs20.closeSync(fd);
4822
+ fs19.closeSync(fd);
5277
4823
  }
5278
4824
  return { lines: collected.reverse(), totalLinesCount };
5279
4825
  }
@@ -5282,11 +4828,11 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
5282
4828
  if (!wantedLevelSet) {
5283
4829
  return { lines: [], totalLinesCount: 0 };
5284
4830
  }
5285
- const stat = fs20.statSync(filePath);
4831
+ const stat = fs19.statSync(filePath);
5286
4832
  if (stat.size === 0) {
5287
4833
  return { lines: [], totalLinesCount: 0 };
5288
4834
  }
5289
- const fd = fs20.openSync(filePath, "r");
4835
+ const fd = fs19.openSync(filePath, "r");
5290
4836
  const chunkSize = 64 * 1024;
5291
4837
  let position = stat.size;
5292
4838
  let remainder = "";
@@ -5298,7 +4844,7 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
5298
4844
  const length = Math.min(chunkSize, position);
5299
4845
  position -= length;
5300
4846
  const buffer = Buffer.alloc(length);
5301
- fs20.readSync(fd, buffer, 0, length, position);
4847
+ fs19.readSync(fd, buffer, 0, length, position);
5302
4848
  let chunk = buffer.toString("utf8");
5303
4849
  if (remainder) {
5304
4850
  chunk += remainder;
@@ -5345,13 +4891,97 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
5345
4891
  }
5346
4892
  }
5347
4893
  } finally {
5348
- fs20.closeSync(fd);
4894
+ fs19.closeSync(fd);
5349
4895
  }
5350
4896
  return { lines: collected.reverse(), totalLinesCount };
5351
4897
  }
5352
4898
 
5353
4899
  // src/commands/read-logs/index.ts
5354
4900
  var LOG_TYPES = ["server", "trace", "server-std", "client-std", "browser"];
4901
+ function normalizeObjectKey(key) {
4902
+ return key.toLowerCase().replace(/_/g, "");
4903
+ }
4904
+ function formatIsoWithLocalOffset(date, includeMilliseconds) {
4905
+ const pad2 = (n) => String(n).padStart(2, "0");
4906
+ const pad3 = (n) => String(n).padStart(3, "0");
4907
+ const year = date.getFullYear();
4908
+ const month = pad2(date.getMonth() + 1);
4909
+ const day = pad2(date.getDate());
4910
+ const hour = pad2(date.getHours());
4911
+ const minute = pad2(date.getMinutes());
4912
+ const second = pad2(date.getSeconds());
4913
+ const ms = pad3(date.getMilliseconds());
4914
+ const tzOffsetMinutes = -date.getTimezoneOffset();
4915
+ const sign = tzOffsetMinutes >= 0 ? "+" : "-";
4916
+ const abs = Math.abs(tzOffsetMinutes);
4917
+ const offsetHH = pad2(Math.floor(abs / 60));
4918
+ const offsetMM = pad2(abs % 60);
4919
+ const msPart = includeMilliseconds ? `.${ms}` : "";
4920
+ return `${year}-${month}-${day}T${hour}:${minute}:${second}${msPart}${sign}${offsetHH}:${offsetMM}`;
4921
+ }
4922
+ function formatLocalDateTimeStringWithOffset(input) {
4923
+ const match = input.match(/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/);
4924
+ if (!match) return input;
4925
+ const year = Number(match[1]);
4926
+ const month = Number(match[2]);
4927
+ const day = Number(match[3]);
4928
+ const hour = Number(match[4]);
4929
+ const minute = Number(match[5]);
4930
+ const second = Number(match[6]);
4931
+ const date = new Date(year, month - 1, day, hour, minute, second, 0);
4932
+ if (Number.isNaN(date.getTime())) return input;
4933
+ return formatIsoWithLocalOffset(date, false);
4934
+ }
4935
+ function formatIsoNoTzStringWithOffset(input) {
4936
+ const match = input.match(
4937
+ /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,3}))?$/
4938
+ );
4939
+ if (!match) return input;
4940
+ const year = Number(match[1]);
4941
+ const month = Number(match[2]);
4942
+ const day = Number(match[3]);
4943
+ const hour = Number(match[4]);
4944
+ const minute = Number(match[5]);
4945
+ const second = Number(match[6]);
4946
+ const msRaw = match[7];
4947
+ const ms = typeof msRaw === "string" ? Number(msRaw.padEnd(3, "0")) : 0;
4948
+ const date = new Date(year, month - 1, day, hour, minute, second, ms);
4949
+ if (Number.isNaN(date.getTime())) return input;
4950
+ return formatIsoWithLocalOffset(date, typeof msRaw === "string");
4951
+ }
4952
+ function normalizeTimeString(input) {
4953
+ const localDateTime = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
4954
+ if (localDateTime.test(input)) {
4955
+ return formatLocalDateTimeStringWithOffset(input);
4956
+ }
4957
+ const isoWithTz = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?(?:Z|[+-]\d{2}:\d{2})$/i;
4958
+ if (isoWithTz.test(input)) {
4959
+ const date = new Date(input);
4960
+ if (Number.isNaN(date.getTime())) return input;
4961
+ const includeMs = /\.\d{1,3}/.test(input);
4962
+ return formatIsoWithLocalOffset(date, includeMs);
4963
+ }
4964
+ const isoNoTz = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?$/;
4965
+ if (isoNoTz.test(input)) {
4966
+ return formatIsoNoTzStringWithOffset(input);
4967
+ }
4968
+ return input;
4969
+ }
4970
+ function normalizeTimezonesInValue(value, keyNormalized) {
4971
+ if (typeof value === "string" && (keyNormalized === "time" || keyNormalized === "servertime")) {
4972
+ return normalizeTimeString(value);
4973
+ }
4974
+ if (!value || typeof value !== "object") return value;
4975
+ if (Array.isArray(value)) {
4976
+ return value.map((item) => normalizeTimezonesInValue(item));
4977
+ }
4978
+ const obj = value;
4979
+ const result = {};
4980
+ for (const [key, child] of Object.entries(obj)) {
4981
+ result[key] = normalizeTimezonesInValue(child, normalizeObjectKey(key));
4982
+ }
4983
+ return result;
4984
+ }
5355
4985
  function sanitizeStructuredLog(value) {
5356
4986
  if (!value || typeof value !== "object") return value;
5357
4987
  if (Array.isArray(value)) return value;
@@ -5456,16 +5086,17 @@ async function readLogsJsonResult(options) {
5456
5086
  const logs = [];
5457
5087
  let hasError = false;
5458
5088
  for (const line of lines) {
5459
- if (!hasError && hasErrorInStdLines([line])) {
5460
- hasError = true;
5461
- }
5462
5089
  try {
5463
5090
  const parsed = JSON.parse(line);
5464
- logs.push(sanitizeStructuredLog(parsed));
5091
+ const normalized = normalizeTimezonesInValue(parsed);
5092
+ logs.push(sanitizeStructuredLog(normalized));
5465
5093
  if (!hasError && hasErrorInLogObject(parsed)) {
5466
5094
  hasError = true;
5467
5095
  }
5468
5096
  } catch {
5097
+ if (!hasError && hasErrorInStdLines([line])) {
5098
+ hasError = true;
5099
+ }
5469
5100
  continue;
5470
5101
  }
5471
5102
  }
@@ -5495,15 +5126,8 @@ function resolveLogFilePath(logDir, type) {
5495
5126
  throw new Error(`Unsupported log type: ${type}`);
5496
5127
  }
5497
5128
  async function run4(options) {
5498
- try {
5499
- const result = await readLogsJsonResult(options);
5500
- process.stdout.write(JSON.stringify(result) + "\n");
5501
- } catch (error) {
5502
- const message = error instanceof Error ? error.message : String(error);
5503
- const result = { hasError: true, totalLinesCount: 0, logs: [message] };
5504
- process.stdout.write(JSON.stringify(result) + "\n");
5505
- process.exitCode = 1;
5506
- }
5129
+ const result = await readLogsJsonResult(options);
5130
+ process.stdout.write(JSON.stringify(result) + "\n");
5507
5131
  }
5508
5132
  function parseLogType(input) {
5509
5133
  const value = typeof input === "string" ? input.trim() : "";
@@ -5535,9 +5159,9 @@ var readLogsCommand = {
5535
5159
  name: "read-logs",
5536
5160
  description: "Read latest logs from log files",
5537
5161
  register(program) {
5538
- program.command(this.name).description(this.description).option("--dir <path>", "Logs directory", "logs").option("--type <type>", `Log type: ${LOG_TYPES.join("|")}`, "server-std").option("--max-lines <lines>", "Max lines to return", "30").option("--offset <lines>", "Skip latest N lines for pagination", "0").option("--trace-id <id>", "Filter structured logs by trace id").option("--level <levels>", "Filter structured logs by level (comma-separated)").action(async (rawOptions) => {
5162
+ program.command(this.name).description(this.description).option("--dir <path>", "Logs directory", "/tmp").option("--type <type>", `Log type: ${LOG_TYPES.join("|")}`, "server-std").option("--max-lines <lines>", "Max lines to return", "30").option("--offset <lines>", "Skip latest N lines for pagination", "0").option("--trace-id <id>", "Filter structured logs by trace id").option("--level <levels>", "Filter structured logs by level (comma-separated)").action(async (rawOptions) => {
5539
5163
  try {
5540
- const logDir = typeof rawOptions.dir === "string" ? rawOptions.dir : "logs";
5164
+ const logDir = typeof rawOptions.dir === "string" ? rawOptions.dir : "/tmp";
5541
5165
  const type = parseLogType(rawOptions.type);
5542
5166
  const maxLines = parsePositiveInt(rawOptions.maxLines, "--max-lines");
5543
5167
  const offset = parseNonNegativeInt(rawOptions.offset, "--offset");
@@ -5546,8 +5170,7 @@ var readLogsCommand = {
5546
5170
  await run4({ logDir, type, maxLines, offset, traceId, levels });
5547
5171
  } catch (error) {
5548
5172
  const message = error instanceof Error ? error.message : String(error);
5549
- const result = { hasError: true, totalLinesCount: 0, logs: [message] };
5550
- process.stdout.write(JSON.stringify(result) + "\n");
5173
+ process.stderr.write(message + "\n");
5551
5174
  process.exitCode = 1;
5552
5175
  }
5553
5176
  });
@@ -5566,11 +5189,11 @@ var commands = [
5566
5189
 
5567
5190
  // src/index.ts
5568
5191
  var envPath = path17.join(process.cwd(), ".env");
5569
- if (fs21.existsSync(envPath)) {
5192
+ if (fs20.existsSync(envPath)) {
5570
5193
  dotenvConfig({ path: envPath });
5571
5194
  }
5572
5195
  var __dirname = path17.dirname(fileURLToPath4(import.meta.url));
5573
- var pkg = JSON.parse(fs21.readFileSync(path17.join(__dirname, "../package.json"), "utf-8"));
5196
+ var pkg = JSON.parse(fs20.readFileSync(path17.join(__dirname, "../package.json"), "utf-8"));
5574
5197
  var cli = new FullstackCLI(pkg.version);
5575
5198
  cli.useAll(commands);
5576
5199
  cli.run();