@lark-apaas/fullstack-cli 1.1.19 → 1.1.20-alpha.1
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/gen-dbschema-template/types.ts +54 -0
- package/dist/index.js +594 -111
- package/package.json +6 -1
|
@@ -38,6 +38,60 @@ export const fileAttachment = customType<{
|
|
|
38
38
|
},
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
+
/** Escape single quotes in SQL string literals */
|
|
42
|
+
function escapeLiteral(str: string): string {
|
|
43
|
+
return `'${str.replace(/'/g, "''")}'`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const userProfileArray = customType<{
|
|
47
|
+
data: string[];
|
|
48
|
+
driverData: string;
|
|
49
|
+
}>({
|
|
50
|
+
dataType() {
|
|
51
|
+
return 'user_profile[]';
|
|
52
|
+
},
|
|
53
|
+
toDriver(value: string[]) {
|
|
54
|
+
if (!value || value.length === 0) {
|
|
55
|
+
return sql`'{}'::user_profile[]`;
|
|
56
|
+
}
|
|
57
|
+
const elements = value.map(id => `ROW(${escapeLiteral(id)})::user_profile`).join(',');
|
|
58
|
+
return sql.raw(`ARRAY[${elements}]::user_profile[]`);
|
|
59
|
+
},
|
|
60
|
+
fromDriver(value: string): string[] {
|
|
61
|
+
if (!value || value === '{}') return [];
|
|
62
|
+
const inner = value.slice(1, -1);
|
|
63
|
+
const matches = inner.match(/\([^)]*\)/g) || [];
|
|
64
|
+
return matches.map(m => m.slice(1, -1).split(',')[0].trim());
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
export const fileAttachmentArray = customType<{
|
|
69
|
+
data: FileAttachment[];
|
|
70
|
+
driverData: string;
|
|
71
|
+
}>({
|
|
72
|
+
dataType() {
|
|
73
|
+
return 'file_attachment[]';
|
|
74
|
+
},
|
|
75
|
+
toDriver(value: FileAttachment[]) {
|
|
76
|
+
if (!value || value.length === 0) {
|
|
77
|
+
return sql`'{}'::file_attachment[]`;
|
|
78
|
+
}
|
|
79
|
+
const elements = value.map(f =>
|
|
80
|
+
`ROW(${escapeLiteral(f.bucket_id)},${escapeLiteral(f.file_path)})::file_attachment`
|
|
81
|
+
).join(',');
|
|
82
|
+
return sql.raw(`ARRAY[${elements}]::file_attachment[]`);
|
|
83
|
+
},
|
|
84
|
+
fromDriver(value: string): FileAttachment[] {
|
|
85
|
+
if (!value || value === '{}') return [];
|
|
86
|
+
const inner = value.slice(1, -1);
|
|
87
|
+
const matches = inner.match(/\([^)]*\)/g) || [];
|
|
88
|
+
return matches.map(m => {
|
|
89
|
+
const [bucketId, filePath] = m.slice(1, -1).split(',');
|
|
90
|
+
return { bucket_id: bucketId.trim(), file_path: filePath.trim() };
|
|
91
|
+
});
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
|
|
41
95
|
export const customTimestamptz = customType<{
|
|
42
96
|
data: Date;
|
|
43
97
|
driverData: string;
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import fs22 from "fs";
|
|
3
|
+
import path18 from "path";
|
|
4
4
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
5
5
|
import { config as dotenvConfig } from "dotenv";
|
|
6
6
|
|
|
@@ -472,6 +472,10 @@ var KNOWN_TYPE_FACTORIES = {
|
|
|
472
472
|
user_profile: "userProfile",
|
|
473
473
|
file_attachment: "fileAttachment"
|
|
474
474
|
};
|
|
475
|
+
var KNOWN_ARRAY_TYPE_FACTORIES = {
|
|
476
|
+
user_profile: "userProfileArray",
|
|
477
|
+
file_attachment: "fileAttachmentArray"
|
|
478
|
+
};
|
|
475
479
|
var replaceUnknownTransform = {
|
|
476
480
|
name: "replace-unknown",
|
|
477
481
|
transform(ctx) {
|
|
@@ -490,12 +494,17 @@ var replaceUnknownTransform = {
|
|
|
490
494
|
const lines = textBefore.split("\n");
|
|
491
495
|
let factoryName = "text";
|
|
492
496
|
let foundKnownType = false;
|
|
497
|
+
let isArrayType = false;
|
|
493
498
|
for (let i = lines.length - 1; i >= Math.max(0, lines.length - 5); i--) {
|
|
494
499
|
const line = lines[i];
|
|
495
500
|
const todoMatch = line.match(/\/\/ TODO: failed to parse database type '(?:\w+\.)?([\w_]+)(\[\])?'/);
|
|
496
501
|
if (todoMatch) {
|
|
497
502
|
const typeName = todoMatch[1];
|
|
498
|
-
|
|
503
|
+
isArrayType = todoMatch[2] === "[]";
|
|
504
|
+
if (isArrayType && KNOWN_ARRAY_TYPE_FACTORIES[typeName]) {
|
|
505
|
+
factoryName = KNOWN_ARRAY_TYPE_FACTORIES[typeName];
|
|
506
|
+
foundKnownType = true;
|
|
507
|
+
} else if (KNOWN_TYPE_FACTORIES[typeName]) {
|
|
499
508
|
factoryName = KNOWN_TYPE_FACTORIES[typeName];
|
|
500
509
|
foundKnownType = true;
|
|
501
510
|
}
|
|
@@ -503,6 +512,15 @@ var replaceUnknownTransform = {
|
|
|
503
512
|
}
|
|
504
513
|
}
|
|
505
514
|
expression.replaceWithText(factoryName);
|
|
515
|
+
if (isArrayType && foundKnownType) {
|
|
516
|
+
const parent = node.getParent();
|
|
517
|
+
if (Node5.isPropertyAccessExpression(parent) && parent.getName() === "array") {
|
|
518
|
+
const grandParent = parent.getParent();
|
|
519
|
+
if (Node5.isCallExpression(grandParent)) {
|
|
520
|
+
grandParent.replaceWithText(node.getText());
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
506
524
|
if (foundKnownType) {
|
|
507
525
|
stats.replacedUnknown++;
|
|
508
526
|
} else {
|
|
@@ -1005,6 +1023,139 @@ function resolveTemplateTypesPath() {
|
|
|
1005
1023
|
return void 0;
|
|
1006
1024
|
}
|
|
1007
1025
|
|
|
1026
|
+
// src/commands/db/gen-dbschema/utils/fetch-column-comments.ts
|
|
1027
|
+
import postgres from "postgres";
|
|
1028
|
+
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
1029
|
+
async function fetchColumnComments(connectionString, options = {}) {
|
|
1030
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
1031
|
+
const url = new URL(connectionString);
|
|
1032
|
+
const schemaName = url.searchParams.get("schema") ?? "public";
|
|
1033
|
+
const sql = postgres(connectionString, {
|
|
1034
|
+
connect_timeout: Math.ceil(timeoutMs / 1e3),
|
|
1035
|
+
idle_timeout: Math.ceil(timeoutMs / 1e3)
|
|
1036
|
+
});
|
|
1037
|
+
try {
|
|
1038
|
+
const queryPromise = sql`
|
|
1039
|
+
SELECT
|
|
1040
|
+
c.table_name AS "tableName",
|
|
1041
|
+
c.column_name AS "columnName",
|
|
1042
|
+
pgd.description AS "comment"
|
|
1043
|
+
FROM information_schema.columns c
|
|
1044
|
+
JOIN pg_catalog.pg_statio_all_tables st
|
|
1045
|
+
ON c.table_name = st.relname AND c.table_schema = st.schemaname
|
|
1046
|
+
JOIN pg_catalog.pg_description pgd
|
|
1047
|
+
ON pgd.objoid = st.relid AND pgd.objsubid = c.ordinal_position
|
|
1048
|
+
WHERE c.table_schema = ${schemaName}
|
|
1049
|
+
AND pgd.description IS NOT NULL
|
|
1050
|
+
AND pgd.description != ''
|
|
1051
|
+
`;
|
|
1052
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
1053
|
+
setTimeout(() => reject(new Error(`Timeout after ${timeoutMs}ms`)), timeoutMs);
|
|
1054
|
+
});
|
|
1055
|
+
const result = await Promise.race([queryPromise, timeoutPromise]);
|
|
1056
|
+
const commentMap = /* @__PURE__ */ new Map();
|
|
1057
|
+
for (const row of result) {
|
|
1058
|
+
const key = `${row.tableName}.${row.columnName}`;
|
|
1059
|
+
commentMap.set(key, row.comment);
|
|
1060
|
+
}
|
|
1061
|
+
return commentMap;
|
|
1062
|
+
} finally {
|
|
1063
|
+
await sql.end().catch(() => {
|
|
1064
|
+
});
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
function extractTypeAnnotation(comment) {
|
|
1068
|
+
const typeStart = comment.indexOf("@type");
|
|
1069
|
+
if (typeStart === -1) return null;
|
|
1070
|
+
const afterType = comment.slice(typeStart + 5).trimStart();
|
|
1071
|
+
if (!afterType.startsWith("{")) return null;
|
|
1072
|
+
let depth = 0;
|
|
1073
|
+
let endIndex = 0;
|
|
1074
|
+
for (let i = 0; i < afterType.length; i++) {
|
|
1075
|
+
if (afterType[i] === "{") depth++;
|
|
1076
|
+
if (afterType[i] === "}") depth--;
|
|
1077
|
+
if (depth === 0) {
|
|
1078
|
+
endIndex = i + 1;
|
|
1079
|
+
break;
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
if (endIndex === 0) return null;
|
|
1083
|
+
return afterType.slice(0, endIndex);
|
|
1084
|
+
}
|
|
1085
|
+
function parseColumnComment(comment) {
|
|
1086
|
+
const typeValue = extractTypeAnnotation(comment);
|
|
1087
|
+
if (typeValue) {
|
|
1088
|
+
const descMatch = comment.match(/@description\s+([^@]+)/);
|
|
1089
|
+
return {
|
|
1090
|
+
type: typeValue,
|
|
1091
|
+
description: descMatch?.[1]?.trim()
|
|
1092
|
+
};
|
|
1093
|
+
}
|
|
1094
|
+
return { description: comment.trim() };
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
// src/commands/db/gen-dbschema/transforms/text/jsonb-comments.ts
|
|
1098
|
+
function addJsonbTypeComments(source, columnComments) {
|
|
1099
|
+
if (!columnComments || columnComments.size === 0) {
|
|
1100
|
+
return { text: source, added: 0 };
|
|
1101
|
+
}
|
|
1102
|
+
const lines = source.split("\n");
|
|
1103
|
+
const result = [];
|
|
1104
|
+
let added = 0;
|
|
1105
|
+
let currentTableName = null;
|
|
1106
|
+
const tableDefRegex = /export const\s+\w+\s*=\s*pgTable\(\s*["'`]([^"'`]+)["'`]/;
|
|
1107
|
+
const jsonFieldWithNameRegex = /^\s*(\w+):\s*(?:json|jsonb)\(\s*["'`]([^"'`]+)["'`]\)/;
|
|
1108
|
+
const jsonFieldNoNameRegex = /^\s*(\w+):\s*(?:json|jsonb)\(\s*\)/;
|
|
1109
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1110
|
+
const line = lines[i];
|
|
1111
|
+
const tableMatch = line.match(tableDefRegex);
|
|
1112
|
+
if (tableMatch) {
|
|
1113
|
+
currentTableName = tableMatch[1];
|
|
1114
|
+
}
|
|
1115
|
+
let columnName = null;
|
|
1116
|
+
const jsonMatchWithName = line.match(jsonFieldWithNameRegex);
|
|
1117
|
+
const jsonMatchNoName = line.match(jsonFieldNoNameRegex);
|
|
1118
|
+
if (jsonMatchWithName) {
|
|
1119
|
+
columnName = jsonMatchWithName[2];
|
|
1120
|
+
} else if (jsonMatchNoName) {
|
|
1121
|
+
columnName = jsonMatchNoName[1];
|
|
1122
|
+
}
|
|
1123
|
+
if (columnName && currentTableName) {
|
|
1124
|
+
const commentKey = `${currentTableName}.${columnName}`;
|
|
1125
|
+
const comment = columnComments.get(commentKey);
|
|
1126
|
+
if (comment) {
|
|
1127
|
+
const parsed = parseColumnComment(comment);
|
|
1128
|
+
const indentMatch = line.match(/^\s*/);
|
|
1129
|
+
const indent = indentMatch ? indentMatch[0] : "";
|
|
1130
|
+
const prevLine = result[result.length - 1]?.trim() ?? "";
|
|
1131
|
+
if (!prevLine.startsWith("/**") && !prevLine.startsWith("*") && !prevLine.startsWith("//")) {
|
|
1132
|
+
const commentLines = [];
|
|
1133
|
+
commentLines.push(`${indent}/**`);
|
|
1134
|
+
if (parsed.description) {
|
|
1135
|
+
const safeDesc = parsed.description.replace(/[\r\n]+/g, " ").trim();
|
|
1136
|
+
commentLines.push(`${indent} * ${safeDesc}`);
|
|
1137
|
+
}
|
|
1138
|
+
if (parsed.type) {
|
|
1139
|
+
if (parsed.description) {
|
|
1140
|
+
commentLines.push(`${indent} *`);
|
|
1141
|
+
}
|
|
1142
|
+
const safeType = parsed.type.replace(/[\r\n]+/g, " ").trim();
|
|
1143
|
+
commentLines.push(`${indent} * @type ${safeType}`);
|
|
1144
|
+
}
|
|
1145
|
+
commentLines.push(`${indent} */`);
|
|
1146
|
+
result.push(...commentLines);
|
|
1147
|
+
added++;
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
if (line.match(/^\}\);?\s*$/) || line.match(/^}\s*,\s*\{/)) {
|
|
1152
|
+
currentTableName = null;
|
|
1153
|
+
}
|
|
1154
|
+
result.push(line);
|
|
1155
|
+
}
|
|
1156
|
+
return { text: result.join("\n"), added };
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1008
1159
|
// src/commands/db/gen-dbschema/transforms/text/table-aliases.ts
|
|
1009
1160
|
var TABLE_ALIAS_MARKER = "// table aliases";
|
|
1010
1161
|
function generateTableAliases(source) {
|
|
@@ -1041,7 +1192,7 @@ function formatSource(source) {
|
|
|
1041
1192
|
}
|
|
1042
1193
|
|
|
1043
1194
|
// src/commands/db/gen-dbschema/postprocess.ts
|
|
1044
|
-
function postprocessSchema(rawSource) {
|
|
1195
|
+
function postprocessSchema(rawSource, options = {}) {
|
|
1045
1196
|
const patchResult = patchDefects(rawSource);
|
|
1046
1197
|
let source = patchResult.text;
|
|
1047
1198
|
const { sourceFile } = parseSource(source);
|
|
@@ -1051,12 +1202,15 @@ function postprocessSchema(rawSource) {
|
|
|
1051
1202
|
source = ensureHeader(source);
|
|
1052
1203
|
source = addSystemFieldComments(source);
|
|
1053
1204
|
source = inlineCustomTypes(source);
|
|
1205
|
+
const jsonbCommentsResult = addJsonbTypeComments(source, options.columnComments);
|
|
1206
|
+
source = jsonbCommentsResult.text;
|
|
1054
1207
|
source = generateTableAliases(source);
|
|
1055
1208
|
source = formatSource(source);
|
|
1056
1209
|
return {
|
|
1057
1210
|
source,
|
|
1058
1211
|
astStats,
|
|
1059
|
-
patchedDefects: patchResult.fixed
|
|
1212
|
+
patchedDefects: patchResult.fixed,
|
|
1213
|
+
addedJsonbComments: jsonbCommentsResult.added
|
|
1060
1214
|
};
|
|
1061
1215
|
}
|
|
1062
1216
|
function logStats(result, prefix = "[postprocess]") {
|
|
@@ -1103,17 +1257,20 @@ function logStats(result, prefix = "[postprocess]") {
|
|
|
1103
1257
|
if (astStats.removedImports.length > 0) {
|
|
1104
1258
|
console.info(`${prefix} Removed imports: ${astStats.removedImports.join(", ")}`);
|
|
1105
1259
|
}
|
|
1260
|
+
if (result.addedJsonbComments > 0) {
|
|
1261
|
+
console.info(`${prefix} Added ${result.addedJsonbComments} JSDoc comments for jsonb fields`);
|
|
1262
|
+
}
|
|
1106
1263
|
}
|
|
1107
1264
|
|
|
1108
1265
|
// src/commands/db/gen-dbschema/index.ts
|
|
1109
|
-
function postprocessDrizzleSchema(targetPath) {
|
|
1266
|
+
async function postprocessDrizzleSchema(targetPath, options = {}) {
|
|
1110
1267
|
const resolvedPath = path.resolve(targetPath);
|
|
1111
1268
|
if (!fs3.existsSync(resolvedPath)) {
|
|
1112
1269
|
console.warn(`[postprocess-drizzle-schema] File not found: ${resolvedPath}`);
|
|
1113
1270
|
return void 0;
|
|
1114
1271
|
}
|
|
1115
1272
|
const rawSource = fs3.readFileSync(resolvedPath, "utf8");
|
|
1116
|
-
const result = postprocessSchema(rawSource);
|
|
1273
|
+
const result = postprocessSchema(rawSource, { columnComments: options.columnComments });
|
|
1117
1274
|
fs3.writeFileSync(resolvedPath, result.source, "utf8");
|
|
1118
1275
|
logStats(result, "[postprocess-drizzle-schema]");
|
|
1119
1276
|
return {
|
|
@@ -1122,7 +1279,8 @@ function postprocessDrizzleSchema(targetPath) {
|
|
|
1122
1279
|
unmatchedUnknown: result.astStats.unmatchedUnknown,
|
|
1123
1280
|
patchedDefects: result.patchedDefects,
|
|
1124
1281
|
replacedTimestamps: result.astStats.replacedTimestamp,
|
|
1125
|
-
replacedDefaultNow: result.astStats.replacedDefaultNow
|
|
1282
|
+
replacedDefaultNow: result.astStats.replacedDefaultNow,
|
|
1283
|
+
addedJsonbComments: result.addedJsonbComments
|
|
1126
1284
|
};
|
|
1127
1285
|
}
|
|
1128
1286
|
|
|
@@ -1847,6 +2005,16 @@ async function run(options = {}) {
|
|
|
1847
2005
|
}
|
|
1848
2006
|
throw new Error("Unable to locate drizzle-kit package root");
|
|
1849
2007
|
};
|
|
2008
|
+
let columnComments;
|
|
2009
|
+
try {
|
|
2010
|
+
columnComments = await fetchColumnComments(databaseUrl, { timeoutMs: 1e4 });
|
|
2011
|
+
console.log(`[gen-db-schema] \u2713 Fetched ${columnComments.size} column comments`);
|
|
2012
|
+
} catch (err) {
|
|
2013
|
+
console.warn(
|
|
2014
|
+
"[gen-db-schema] \u26A0 Failed to fetch column comments (skipping):",
|
|
2015
|
+
err instanceof Error ? err.message : String(err)
|
|
2016
|
+
);
|
|
2017
|
+
}
|
|
1850
2018
|
try {
|
|
1851
2019
|
const env = {
|
|
1852
2020
|
...process.env,
|
|
@@ -1870,7 +2038,9 @@ async function run(options = {}) {
|
|
|
1870
2038
|
console.error("[gen-db-schema] schema.ts not generated");
|
|
1871
2039
|
throw new Error("drizzle-kit introspect failed to generate schema.ts");
|
|
1872
2040
|
}
|
|
1873
|
-
const stats = postprocessDrizzleSchema(generatedSchema
|
|
2041
|
+
const stats = await postprocessDrizzleSchema(generatedSchema, {
|
|
2042
|
+
columnComments
|
|
2043
|
+
});
|
|
1874
2044
|
if (stats?.unmatchedUnknown?.length) {
|
|
1875
2045
|
console.warn("[gen-db-schema] Unmatched custom types detected:", stats.unmatchedUnknown);
|
|
1876
2046
|
}
|
|
@@ -3282,59 +3452,344 @@ var capabilityCommandGroup = {
|
|
|
3282
3452
|
commands: [listCommand2]
|
|
3283
3453
|
};
|
|
3284
3454
|
|
|
3285
|
-
// src/commands/
|
|
3455
|
+
// src/commands/component/registry-preparer.ts
|
|
3286
3456
|
import fs10 from "fs";
|
|
3287
3457
|
import path8 from "path";
|
|
3458
|
+
import os from "os";
|
|
3459
|
+
|
|
3460
|
+
// src/commands/component/service.ts
|
|
3461
|
+
import { mapValues } from "es-toolkit";
|
|
3462
|
+
|
|
3463
|
+
// src/commands/component/utils.ts
|
|
3464
|
+
import createDebug from "debug";
|
|
3465
|
+
var debug = createDebug("component");
|
|
3466
|
+
|
|
3467
|
+
// src/commands/component/service.ts
|
|
3468
|
+
async function getComponents(keys) {
|
|
3469
|
+
const client = getHttpClient();
|
|
3470
|
+
debug("\u8C03\u7528 /components/batch_get %o", keys);
|
|
3471
|
+
const response = await client.post(
|
|
3472
|
+
`/api/v1/studio/innerapi/components/batch_get?keys=${keys.join(",")}`
|
|
3473
|
+
);
|
|
3474
|
+
if (response.status !== 200) {
|
|
3475
|
+
throw new Error(
|
|
3476
|
+
`\u83B7\u53D6\u7EC4\u4EF6\u4FE1\u606F\u5931\u8D25\uFF1A${response.status} ${response.statusText}`
|
|
3477
|
+
);
|
|
3478
|
+
}
|
|
3479
|
+
const result = await response.json();
|
|
3480
|
+
if (result.status_code !== "0") {
|
|
3481
|
+
debug("\u63A5\u53E3\u8FD4\u56DE\u9519\u8BEF\uFF1A%o", result);
|
|
3482
|
+
throw new Error(`\u83B7\u53D6\u7EC4\u4EF6\u4FE1\u606F\u5931\u8D25\uFF1A${result.error_msg}`);
|
|
3483
|
+
}
|
|
3484
|
+
return mapValues(result.data.components, ([component]) => component);
|
|
3485
|
+
}
|
|
3486
|
+
async function getRegistryItem(url) {
|
|
3487
|
+
const client = getHttpClient();
|
|
3488
|
+
debug("\u4E0B\u8F7D registry-item.json\uFF1A%s", url);
|
|
3489
|
+
const response = await client.get(url);
|
|
3490
|
+
if (!response.ok) {
|
|
3491
|
+
throw new Error(
|
|
3492
|
+
`\u4E0B\u8F7D registry-item.json \u5931\u8D25\uFF1A${response.status} ${response.statusText}`
|
|
3493
|
+
);
|
|
3494
|
+
}
|
|
3495
|
+
const item = await response.json();
|
|
3496
|
+
return item;
|
|
3497
|
+
}
|
|
3498
|
+
async function sendInstallEvent(key) {
|
|
3499
|
+
const client = getHttpClient();
|
|
3500
|
+
await client.post("/api/v1/studio/innerapi/resource_events", {
|
|
3501
|
+
events: [
|
|
3502
|
+
{
|
|
3503
|
+
resourceType: "component",
|
|
3504
|
+
resourceKey: key,
|
|
3505
|
+
eventType: "install",
|
|
3506
|
+
details: {}
|
|
3507
|
+
}
|
|
3508
|
+
]
|
|
3509
|
+
});
|
|
3510
|
+
}
|
|
3511
|
+
|
|
3512
|
+
// src/commands/component/registry-preparer.ts
|
|
3513
|
+
var REGISTRY_TEMP_DIR = path8.join(os.tmpdir(), "miaoda-registry");
|
|
3514
|
+
function parseComponentKey(key) {
|
|
3515
|
+
const match = key.match(/^@([^/]+)\/(.+)$/);
|
|
3516
|
+
if (!match) {
|
|
3517
|
+
throw new Error(
|
|
3518
|
+
`Invalid component key format: ${key}. Expected format: @scope/name`
|
|
3519
|
+
);
|
|
3520
|
+
}
|
|
3521
|
+
return { scope: match[1], name: match[2] };
|
|
3522
|
+
}
|
|
3523
|
+
function getLocalRegistryPath(key) {
|
|
3524
|
+
const { scope, name } = parseComponentKey(key);
|
|
3525
|
+
return path8.join(REGISTRY_TEMP_DIR, scope, `${name}.json`);
|
|
3526
|
+
}
|
|
3527
|
+
function ensureDir(dirPath) {
|
|
3528
|
+
if (!fs10.existsSync(dirPath)) {
|
|
3529
|
+
fs10.mkdirSync(dirPath, { recursive: true });
|
|
3530
|
+
}
|
|
3531
|
+
}
|
|
3532
|
+
async function prepareRecursive(key, visited) {
|
|
3533
|
+
if (visited.has(key)) {
|
|
3534
|
+
debug("\u8DF3\u8FC7\u5DF2\u5904\u7406\u7684\u7EC4\u4EF6: %s", key);
|
|
3535
|
+
return;
|
|
3536
|
+
}
|
|
3537
|
+
visited.add(key);
|
|
3538
|
+
debug("\u5904\u7406\u7EC4\u4EF6: %s", key);
|
|
3539
|
+
debug("\u83B7\u53D6\u7EC4\u4EF6\u4E0B\u8F7D\u4FE1\u606F...");
|
|
3540
|
+
const infoMap = await getComponents([key]);
|
|
3541
|
+
const info = infoMap[key];
|
|
3542
|
+
debug("\u7EC4\u4EF6\u4FE1\u606F: %o", info);
|
|
3543
|
+
if (!info) {
|
|
3544
|
+
throw new Error(`Component not found: ${key}`);
|
|
3545
|
+
}
|
|
3546
|
+
if (info.status !== "active") {
|
|
3547
|
+
throw new Error(`Component is not active: ${key}`);
|
|
3548
|
+
}
|
|
3549
|
+
debug("\u4E0B\u8F7D registry item: %s", info.downloadURL);
|
|
3550
|
+
const registryItem = await getRegistryItem(info.downloadURL);
|
|
3551
|
+
debug("registry item \u5185\u5BB9: %o", registryItem);
|
|
3552
|
+
const deps = registryItem.registryDependencies || [];
|
|
3553
|
+
debug("\u4F9D\u8D56\u5217\u8868: %o", deps);
|
|
3554
|
+
for (const dep of deps) {
|
|
3555
|
+
await prepareRecursive(dep, visited);
|
|
3556
|
+
}
|
|
3557
|
+
const rewrittenItem = {
|
|
3558
|
+
...registryItem,
|
|
3559
|
+
registryDependencies: deps.map((dep) => getLocalRegistryPath(dep))
|
|
3560
|
+
};
|
|
3561
|
+
const localPath = getLocalRegistryPath(key);
|
|
3562
|
+
ensureDir(path8.dirname(localPath));
|
|
3563
|
+
fs10.writeFileSync(localPath, JSON.stringify(rewrittenItem, null, 2), "utf-8");
|
|
3564
|
+
debug("\u4FDD\u5B58\u5230: %s", localPath);
|
|
3565
|
+
}
|
|
3566
|
+
async function prepareComponentRegistryItems(id) {
|
|
3567
|
+
const visited = /* @__PURE__ */ new Set();
|
|
3568
|
+
await prepareRecursive(id, visited);
|
|
3569
|
+
return getLocalRegistryPath(id);
|
|
3570
|
+
}
|
|
3571
|
+
function cleanupTempDir() {
|
|
3572
|
+
try {
|
|
3573
|
+
if (fs10.existsSync(REGISTRY_TEMP_DIR)) {
|
|
3574
|
+
fs10.rmSync(REGISTRY_TEMP_DIR, { recursive: true, force: true });
|
|
3575
|
+
}
|
|
3576
|
+
} catch {
|
|
3577
|
+
}
|
|
3578
|
+
}
|
|
3579
|
+
function getDownloadedRegistryItem(itemId) {
|
|
3580
|
+
const localPath = getLocalRegistryPath(itemId);
|
|
3581
|
+
if (!fs10.existsSync(localPath)) {
|
|
3582
|
+
return null;
|
|
3583
|
+
}
|
|
3584
|
+
const content = fs10.readFileSync(localPath, "utf-8");
|
|
3585
|
+
return JSON.parse(content);
|
|
3586
|
+
}
|
|
3587
|
+
|
|
3588
|
+
// src/commands/component/shadcn-executor.ts
|
|
3589
|
+
import * as pty from "@lydell/node-pty";
|
|
3590
|
+
function parseOutput(output) {
|
|
3591
|
+
const state = {
|
|
3592
|
+
currentSection: null,
|
|
3593
|
+
files: /* @__PURE__ */ new Set()
|
|
3594
|
+
};
|
|
3595
|
+
const lines = output.split("\n");
|
|
3596
|
+
for (const line of lines) {
|
|
3597
|
+
const trimmedLine = line.trim();
|
|
3598
|
+
if (/Created \d+ files?:/.test(trimmedLine)) {
|
|
3599
|
+
state.currentSection = "created";
|
|
3600
|
+
continue;
|
|
3601
|
+
}
|
|
3602
|
+
if (/Updated \d+ files?:/.test(trimmedLine)) {
|
|
3603
|
+
state.currentSection = "updated";
|
|
3604
|
+
continue;
|
|
3605
|
+
}
|
|
3606
|
+
if (/Skipped \d+ files?:/.test(trimmedLine)) {
|
|
3607
|
+
state.currentSection = "skipped";
|
|
3608
|
+
continue;
|
|
3609
|
+
}
|
|
3610
|
+
if (state.currentSection && trimmedLine.startsWith("- ")) {
|
|
3611
|
+
const filePath = trimmedLine.slice(2).trim();
|
|
3612
|
+
if (filePath && filePath.includes("/")) {
|
|
3613
|
+
state.files.add(filePath);
|
|
3614
|
+
}
|
|
3615
|
+
}
|
|
3616
|
+
if (state.currentSection && trimmedLine.length > 1 && !trimmedLine.startsWith("- ")) {
|
|
3617
|
+
state.currentSection = null;
|
|
3618
|
+
}
|
|
3619
|
+
}
|
|
3620
|
+
return Array.from(state.files);
|
|
3621
|
+
}
|
|
3622
|
+
function toFileInfo(filePath) {
|
|
3623
|
+
const name = filePath.split("/").pop() || filePath;
|
|
3624
|
+
return { name, path: filePath };
|
|
3625
|
+
}
|
|
3626
|
+
var PROMPT_PATTERNS = [
|
|
3627
|
+
// 文件覆盖确认 - 回答 n(不覆盖)
|
|
3628
|
+
{ pattern: /overwrite/i, answer: "n\n" },
|
|
3629
|
+
// 主题/样式选择 - 回答 n(不安装额外主题)
|
|
3630
|
+
{ pattern: /theme/i, answer: "n\n" },
|
|
3631
|
+
{ pattern: /style/i, answer: "n\n" },
|
|
3632
|
+
// 继续确认 - 回答 y
|
|
3633
|
+
{ pattern: /continue\?/i, answer: "y\n" },
|
|
3634
|
+
{ pattern: /proceed\?/i, answer: "y\n" }
|
|
3635
|
+
];
|
|
3636
|
+
async function executeShadcnAdd(registryItemPath) {
|
|
3637
|
+
return new Promise((resolve) => {
|
|
3638
|
+
let output = "";
|
|
3639
|
+
const args = ["--yes", "shadcn@3.8.2", "add", registryItemPath];
|
|
3640
|
+
const ptyProcess = pty.spawn("npx", args, {
|
|
3641
|
+
name: "xterm-color",
|
|
3642
|
+
cols: 120,
|
|
3643
|
+
rows: 30,
|
|
3644
|
+
cwd: process.cwd(),
|
|
3645
|
+
env: {
|
|
3646
|
+
...process.env,
|
|
3647
|
+
// 禁用颜色输出以便解析
|
|
3648
|
+
NO_COLOR: "1",
|
|
3649
|
+
FORCE_COLOR: "0"
|
|
3650
|
+
}
|
|
3651
|
+
});
|
|
3652
|
+
ptyProcess.onData((data) => {
|
|
3653
|
+
output += data;
|
|
3654
|
+
for (const { pattern, answer } of PROMPT_PATTERNS) {
|
|
3655
|
+
if (pattern.test(data)) {
|
|
3656
|
+
ptyProcess.write(answer);
|
|
3657
|
+
return;
|
|
3658
|
+
}
|
|
3659
|
+
}
|
|
3660
|
+
});
|
|
3661
|
+
const timeoutId = setTimeout(() => {
|
|
3662
|
+
ptyProcess.kill();
|
|
3663
|
+
resolve({
|
|
3664
|
+
success: false,
|
|
3665
|
+
files: [],
|
|
3666
|
+
error: "\u6267\u884C\u8D85\u65F6"
|
|
3667
|
+
});
|
|
3668
|
+
}, 3 * 60 * 1e3);
|
|
3669
|
+
ptyProcess.onExit(({ exitCode }) => {
|
|
3670
|
+
clearTimeout(timeoutId);
|
|
3671
|
+
const success = exitCode === 0;
|
|
3672
|
+
const filePaths = parseOutput(output);
|
|
3673
|
+
const files = filePaths.map(toFileInfo);
|
|
3674
|
+
resolve({
|
|
3675
|
+
success,
|
|
3676
|
+
files,
|
|
3677
|
+
error: success ? void 0 : output || `Process exited with code ${exitCode}`
|
|
3678
|
+
});
|
|
3679
|
+
});
|
|
3680
|
+
});
|
|
3681
|
+
}
|
|
3682
|
+
|
|
3683
|
+
// src/commands/component/add.handler.ts
|
|
3684
|
+
function printResult(result) {
|
|
3685
|
+
console.log(JSON.stringify(result, null, 2));
|
|
3686
|
+
}
|
|
3687
|
+
async function addComponent(key) {
|
|
3688
|
+
debug("\u5F00\u59CB\u5B89\u88C5\u7EC4\u4EF6: %s", key);
|
|
3689
|
+
debug("\u51C6\u5907 registry items...");
|
|
3690
|
+
const registryItemPath = await prepareComponentRegistryItems(key);
|
|
3691
|
+
debug("registry item \u8DEF\u5F84: %s", registryItemPath);
|
|
3692
|
+
const registryItem = getDownloadedRegistryItem(key);
|
|
3693
|
+
debug("\u83B7\u53D6\u5230 registry item: %o", registryItem);
|
|
3694
|
+
debug("\u6267\u884C shadcn add...");
|
|
3695
|
+
const executeResult = await executeShadcnAdd(registryItemPath);
|
|
3696
|
+
debug("shadcn \u6267\u884C\u7ED3\u679C: %o", executeResult);
|
|
3697
|
+
if (!executeResult.success) {
|
|
3698
|
+
throw new Error(executeResult.error || "\u5B89\u88C5\u5931\u8D25\uFF0C\u672A\u77E5\u539F\u56E0");
|
|
3699
|
+
}
|
|
3700
|
+
return {
|
|
3701
|
+
success: true,
|
|
3702
|
+
name: key,
|
|
3703
|
+
description: registryItem?.description || "",
|
|
3704
|
+
files: executeResult.files,
|
|
3705
|
+
docs: registryItem?.docs || ""
|
|
3706
|
+
};
|
|
3707
|
+
}
|
|
3708
|
+
async function add(key) {
|
|
3709
|
+
try {
|
|
3710
|
+
const result = await addComponent(key);
|
|
3711
|
+
printResult(result);
|
|
3712
|
+
void sendInstallEvent(key);
|
|
3713
|
+
} catch (error) {
|
|
3714
|
+
const errorMessage = error instanceof Error ? error.message : "\u5B89\u88C5\u5931\u8D25\uFF0C\u539F\u56E0\u672A\u77E5";
|
|
3715
|
+
printResult({
|
|
3716
|
+
success: false,
|
|
3717
|
+
errors: [{ message: errorMessage }]
|
|
3718
|
+
});
|
|
3719
|
+
} finally {
|
|
3720
|
+
cleanupTempDir();
|
|
3721
|
+
}
|
|
3722
|
+
}
|
|
3723
|
+
|
|
3724
|
+
// src/commands/component/index.ts
|
|
3725
|
+
var addCommand = {
|
|
3726
|
+
name: "add",
|
|
3727
|
+
description: "\u5B89\u88C5\u5999\u642D\u7EC4\u4EF6\u5E02\u573A\u4E2D\u7684\u7EC4\u4EF6",
|
|
3728
|
+
register(program) {
|
|
3729
|
+
program.command(this.name).description(this.description).argument("<component>", "\u7EC4\u4EF6 ID (\u4F8B\u5982 @miaoda/button)").action(async (component) => {
|
|
3730
|
+
await add(component);
|
|
3731
|
+
});
|
|
3732
|
+
}
|
|
3733
|
+
};
|
|
3734
|
+
var componentCommandGroup = {
|
|
3735
|
+
name: "component",
|
|
3736
|
+
description: "\u7EC4\u4EF6\u76F8\u5173\u547D\u4EE4",
|
|
3737
|
+
commands: [addCommand]
|
|
3738
|
+
};
|
|
3739
|
+
|
|
3740
|
+
// src/commands/migration/version-manager.ts
|
|
3741
|
+
import fs11 from "fs";
|
|
3742
|
+
import path9 from "path";
|
|
3288
3743
|
var PACKAGE_JSON = "package.json";
|
|
3289
3744
|
var VERSION_FIELD = "migrationVersion";
|
|
3290
3745
|
function getPackageJsonPath2() {
|
|
3291
|
-
return
|
|
3746
|
+
return path9.join(process.cwd(), PACKAGE_JSON);
|
|
3292
3747
|
}
|
|
3293
3748
|
function getCurrentVersion() {
|
|
3294
3749
|
const pkgPath = getPackageJsonPath2();
|
|
3295
|
-
if (!
|
|
3750
|
+
if (!fs11.existsSync(pkgPath)) {
|
|
3296
3751
|
throw new Error("package.json not found");
|
|
3297
3752
|
}
|
|
3298
|
-
const pkg2 = JSON.parse(
|
|
3753
|
+
const pkg2 = JSON.parse(fs11.readFileSync(pkgPath, "utf-8"));
|
|
3299
3754
|
return pkg2[VERSION_FIELD] ?? 0;
|
|
3300
3755
|
}
|
|
3301
3756
|
function setCurrentVersion(version) {
|
|
3302
3757
|
const pkgPath = getPackageJsonPath2();
|
|
3303
|
-
const pkg2 = JSON.parse(
|
|
3758
|
+
const pkg2 = JSON.parse(fs11.readFileSync(pkgPath, "utf-8"));
|
|
3304
3759
|
pkg2[VERSION_FIELD] = version;
|
|
3305
|
-
|
|
3760
|
+
fs11.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
|
|
3306
3761
|
}
|
|
3307
3762
|
|
|
3308
3763
|
// src/commands/migration/versions/v001_capability/json-migrator/detector.ts
|
|
3309
|
-
import
|
|
3310
|
-
import
|
|
3764
|
+
import fs13 from "fs";
|
|
3765
|
+
import path11 from "path";
|
|
3311
3766
|
|
|
3312
3767
|
// src/commands/migration/versions/v001_capability/utils.ts
|
|
3313
|
-
import
|
|
3314
|
-
import
|
|
3768
|
+
import fs12 from "fs";
|
|
3769
|
+
import path10 from "path";
|
|
3315
3770
|
var CAPABILITIES_DIR2 = "server/capabilities";
|
|
3316
3771
|
function getProjectRoot3() {
|
|
3317
3772
|
return process.cwd();
|
|
3318
3773
|
}
|
|
3319
3774
|
function getCapabilitiesDir2() {
|
|
3320
|
-
return
|
|
3775
|
+
return path10.join(getProjectRoot3(), CAPABILITIES_DIR2);
|
|
3321
3776
|
}
|
|
3322
3777
|
function getPluginManifestPath2(pluginKey) {
|
|
3323
|
-
return
|
|
3778
|
+
return path10.join(getProjectRoot3(), "node_modules", pluginKey, "manifest.json");
|
|
3324
3779
|
}
|
|
3325
3780
|
|
|
3326
3781
|
// src/commands/migration/versions/v001_capability/json-migrator/detector.ts
|
|
3327
3782
|
function detectJsonMigration() {
|
|
3328
3783
|
const capabilitiesDir = getCapabilitiesDir2();
|
|
3329
|
-
const oldFilePath =
|
|
3330
|
-
if (!
|
|
3784
|
+
const oldFilePath = path11.join(capabilitiesDir, "capabilities.json");
|
|
3785
|
+
if (!fs13.existsSync(oldFilePath)) {
|
|
3331
3786
|
return {
|
|
3332
3787
|
needsMigration: false,
|
|
3333
3788
|
reason: "capabilities.json not found"
|
|
3334
3789
|
};
|
|
3335
3790
|
}
|
|
3336
3791
|
try {
|
|
3337
|
-
const content =
|
|
3792
|
+
const content = fs13.readFileSync(oldFilePath, "utf-8");
|
|
3338
3793
|
const parsed = JSON.parse(content);
|
|
3339
3794
|
if (!Array.isArray(parsed)) {
|
|
3340
3795
|
return {
|
|
@@ -3385,8 +3840,8 @@ async function check(options) {
|
|
|
3385
3840
|
}
|
|
3386
3841
|
|
|
3387
3842
|
// src/commands/migration/versions/v001_capability/json-migrator/index.ts
|
|
3388
|
-
import
|
|
3389
|
-
import
|
|
3843
|
+
import fs14 from "fs";
|
|
3844
|
+
import path12 from "path";
|
|
3390
3845
|
|
|
3391
3846
|
// src/commands/migration/versions/v001_capability/mapping.ts
|
|
3392
3847
|
var DEFAULT_PLUGIN_VERSION = "1.0.0";
|
|
@@ -3616,18 +4071,18 @@ function transformCapabilities(oldCapabilities) {
|
|
|
3616
4071
|
// src/commands/migration/versions/v001_capability/json-migrator/index.ts
|
|
3617
4072
|
function loadExistingCapabilities() {
|
|
3618
4073
|
const capabilitiesDir = getCapabilitiesDir2();
|
|
3619
|
-
if (!
|
|
4074
|
+
if (!fs14.existsSync(capabilitiesDir)) {
|
|
3620
4075
|
return [];
|
|
3621
4076
|
}
|
|
3622
|
-
const files =
|
|
4077
|
+
const files = fs14.readdirSync(capabilitiesDir);
|
|
3623
4078
|
const capabilities = [];
|
|
3624
4079
|
for (const file of files) {
|
|
3625
4080
|
if (file === "capabilities.json" || !file.endsWith(".json")) {
|
|
3626
4081
|
continue;
|
|
3627
4082
|
}
|
|
3628
4083
|
try {
|
|
3629
|
-
const filePath =
|
|
3630
|
-
const content =
|
|
4084
|
+
const filePath = path12.join(capabilitiesDir, file);
|
|
4085
|
+
const content = fs14.readFileSync(filePath, "utf-8");
|
|
3631
4086
|
const capability = JSON.parse(content);
|
|
3632
4087
|
if (capability.id && capability.pluginKey) {
|
|
3633
4088
|
capabilities.push(capability);
|
|
@@ -3685,9 +4140,9 @@ async function migrateJsonFiles(options) {
|
|
|
3685
4140
|
}
|
|
3686
4141
|
const capabilitiesDir = getCapabilitiesDir2();
|
|
3687
4142
|
for (const cap of newCapabilities) {
|
|
3688
|
-
const filePath =
|
|
4143
|
+
const filePath = path12.join(capabilitiesDir, `${cap.id}.json`);
|
|
3689
4144
|
const content = JSON.stringify(cap, null, 2);
|
|
3690
|
-
|
|
4145
|
+
fs14.writeFileSync(filePath, content, "utf-8");
|
|
3691
4146
|
console.log(` \u2713 Created: ${cap.id}.json`);
|
|
3692
4147
|
}
|
|
3693
4148
|
return {
|
|
@@ -3699,11 +4154,11 @@ async function migrateJsonFiles(options) {
|
|
|
3699
4154
|
}
|
|
3700
4155
|
|
|
3701
4156
|
// src/commands/migration/versions/v001_capability/plugin-installer/detector.ts
|
|
3702
|
-
import
|
|
4157
|
+
import fs15 from "fs";
|
|
3703
4158
|
function isPluginInstalled2(pluginKey) {
|
|
3704
4159
|
const actionPlugins = readActionPlugins();
|
|
3705
4160
|
const manifestPath = getPluginManifestPath2(pluginKey);
|
|
3706
|
-
return
|
|
4161
|
+
return fs15.existsSync(manifestPath) && !!actionPlugins[pluginKey];
|
|
3707
4162
|
}
|
|
3708
4163
|
function detectPluginsToInstall(capabilities) {
|
|
3709
4164
|
const pluginKeys = /* @__PURE__ */ new Set();
|
|
@@ -3779,12 +4234,12 @@ async function installPlugins(capabilities, options) {
|
|
|
3779
4234
|
}
|
|
3780
4235
|
|
|
3781
4236
|
// src/commands/migration/versions/v001_capability/code-migrator/index.ts
|
|
3782
|
-
import
|
|
4237
|
+
import path14 from "path";
|
|
3783
4238
|
import { Project as Project3 } from "ts-morph";
|
|
3784
4239
|
|
|
3785
4240
|
// src/commands/migration/versions/v001_capability/code-migrator/scanner.ts
|
|
3786
|
-
import
|
|
3787
|
-
import
|
|
4241
|
+
import fs16 from "fs";
|
|
4242
|
+
import path13 from "path";
|
|
3788
4243
|
var EXCLUDED_DIRS = [
|
|
3789
4244
|
"node_modules",
|
|
3790
4245
|
"dist",
|
|
@@ -3799,9 +4254,9 @@ var EXCLUDED_PATTERNS = [
|
|
|
3799
4254
|
/\.d\.ts$/
|
|
3800
4255
|
];
|
|
3801
4256
|
function scanDirectory(dir, files = []) {
|
|
3802
|
-
const entries =
|
|
4257
|
+
const entries = fs16.readdirSync(dir, { withFileTypes: true });
|
|
3803
4258
|
for (const entry of entries) {
|
|
3804
|
-
const fullPath =
|
|
4259
|
+
const fullPath = path13.join(dir, entry.name);
|
|
3805
4260
|
if (entry.isDirectory()) {
|
|
3806
4261
|
if (EXCLUDED_DIRS.includes(entry.name)) {
|
|
3807
4262
|
continue;
|
|
@@ -3817,14 +4272,14 @@ function scanDirectory(dir, files = []) {
|
|
|
3817
4272
|
return files;
|
|
3818
4273
|
}
|
|
3819
4274
|
function scanServerFiles() {
|
|
3820
|
-
const serverDir =
|
|
3821
|
-
if (!
|
|
4275
|
+
const serverDir = path13.join(getProjectRoot3(), "server");
|
|
4276
|
+
if (!fs16.existsSync(serverDir)) {
|
|
3822
4277
|
return [];
|
|
3823
4278
|
}
|
|
3824
4279
|
return scanDirectory(serverDir);
|
|
3825
4280
|
}
|
|
3826
4281
|
function hasCapabilityImport(filePath) {
|
|
3827
|
-
const content =
|
|
4282
|
+
const content = fs16.readFileSync(filePath, "utf-8");
|
|
3828
4283
|
return /import\s+.*from\s+['"][^'"]*capabilities[^'"]*['"]/.test(content);
|
|
3829
4284
|
}
|
|
3830
4285
|
function scanFilesToMigrate() {
|
|
@@ -4201,7 +4656,7 @@ function analyzeFile(project, filePath, actionNameMap) {
|
|
|
4201
4656
|
const callSites = analyzeCallSites(sourceFile, imports);
|
|
4202
4657
|
const classInfo = analyzeClass(sourceFile);
|
|
4203
4658
|
const { canMigrate, reason } = canAutoMigrate(classInfo);
|
|
4204
|
-
const relativePath =
|
|
4659
|
+
const relativePath = path14.relative(getProjectRoot3(), filePath);
|
|
4205
4660
|
return {
|
|
4206
4661
|
filePath: relativePath,
|
|
4207
4662
|
imports,
|
|
@@ -4212,7 +4667,7 @@ function analyzeFile(project, filePath, actionNameMap) {
|
|
|
4212
4667
|
};
|
|
4213
4668
|
}
|
|
4214
4669
|
function migrateFile(project, analysis, dryRun) {
|
|
4215
|
-
const absolutePath =
|
|
4670
|
+
const absolutePath = path14.join(getProjectRoot3(), analysis.filePath);
|
|
4216
4671
|
if (!analysis.canAutoMigrate) {
|
|
4217
4672
|
return {
|
|
4218
4673
|
filePath: analysis.filePath,
|
|
@@ -4315,17 +4770,17 @@ function getSuggestion(analysis) {
|
|
|
4315
4770
|
}
|
|
4316
4771
|
|
|
4317
4772
|
// src/commands/migration/versions/v001_capability/cleanup.ts
|
|
4318
|
-
import
|
|
4319
|
-
import
|
|
4773
|
+
import fs17 from "fs";
|
|
4774
|
+
import path15 from "path";
|
|
4320
4775
|
function cleanupOldFiles(capabilities, dryRun) {
|
|
4321
4776
|
const deletedFiles = [];
|
|
4322
4777
|
const errors = [];
|
|
4323
4778
|
const capabilitiesDir = getCapabilitiesDir2();
|
|
4324
|
-
const oldJsonPath =
|
|
4325
|
-
if (
|
|
4779
|
+
const oldJsonPath = path15.join(capabilitiesDir, "capabilities.json");
|
|
4780
|
+
if (fs17.existsSync(oldJsonPath)) {
|
|
4326
4781
|
try {
|
|
4327
4782
|
if (!dryRun) {
|
|
4328
|
-
|
|
4783
|
+
fs17.unlinkSync(oldJsonPath);
|
|
4329
4784
|
}
|
|
4330
4785
|
deletedFiles.push("capabilities.json");
|
|
4331
4786
|
} catch (error) {
|
|
@@ -4333,11 +4788,11 @@ function cleanupOldFiles(capabilities, dryRun) {
|
|
|
4333
4788
|
}
|
|
4334
4789
|
}
|
|
4335
4790
|
for (const cap of capabilities) {
|
|
4336
|
-
const tsFilePath =
|
|
4337
|
-
if (
|
|
4791
|
+
const tsFilePath = path15.join(capabilitiesDir, `${cap.id}.ts`);
|
|
4792
|
+
if (fs17.existsSync(tsFilePath)) {
|
|
4338
4793
|
try {
|
|
4339
4794
|
if (!dryRun) {
|
|
4340
|
-
|
|
4795
|
+
fs17.unlinkSync(tsFilePath);
|
|
4341
4796
|
}
|
|
4342
4797
|
deletedFiles.push(`${cap.id}.ts`);
|
|
4343
4798
|
} catch (error) {
|
|
@@ -4353,8 +4808,8 @@ function cleanupOldFiles(capabilities, dryRun) {
|
|
|
4353
4808
|
}
|
|
4354
4809
|
|
|
4355
4810
|
// src/commands/migration/versions/v001_capability/report-generator.ts
|
|
4356
|
-
import
|
|
4357
|
-
import
|
|
4811
|
+
import fs18 from "fs";
|
|
4812
|
+
import path16 from "path";
|
|
4358
4813
|
var REPORT_FILE = "capability-migration-report.md";
|
|
4359
4814
|
function printSummary(result) {
|
|
4360
4815
|
const { jsonMigration, pluginInstallation, codeMigration, cleanup } = result;
|
|
@@ -4517,15 +4972,15 @@ async function generateReport(result) {
|
|
|
4517
4972
|
}
|
|
4518
4973
|
lines.push("");
|
|
4519
4974
|
const logDir = process.env.LOG_DIR || "logs";
|
|
4520
|
-
if (!
|
|
4975
|
+
if (!fs18.existsSync(logDir)) {
|
|
4521
4976
|
return;
|
|
4522
4977
|
}
|
|
4523
|
-
const reportDir =
|
|
4524
|
-
if (!
|
|
4525
|
-
|
|
4978
|
+
const reportDir = path16.join(logDir, "migration");
|
|
4979
|
+
if (!fs18.existsSync(reportDir)) {
|
|
4980
|
+
fs18.mkdirSync(reportDir, { recursive: true });
|
|
4526
4981
|
}
|
|
4527
|
-
const reportPath =
|
|
4528
|
-
|
|
4982
|
+
const reportPath = path16.join(reportDir, REPORT_FILE);
|
|
4983
|
+
fs18.writeFileSync(reportPath, lines.join("\n"), "utf-8");
|
|
4529
4984
|
console.log(`\u{1F4C4} Report generated: ${reportPath}`);
|
|
4530
4985
|
}
|
|
4531
4986
|
|
|
@@ -5057,10 +5512,10 @@ var migrationCommand = {
|
|
|
5057
5512
|
};
|
|
5058
5513
|
|
|
5059
5514
|
// src/commands/read-logs/index.ts
|
|
5060
|
-
import
|
|
5515
|
+
import path17 from "path";
|
|
5061
5516
|
|
|
5062
5517
|
// src/commands/read-logs/std-utils.ts
|
|
5063
|
-
import
|
|
5518
|
+
import fs19 from "fs";
|
|
5064
5519
|
function formatStdPrefixTime(localTime) {
|
|
5065
5520
|
const match = localTime.match(/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/);
|
|
5066
5521
|
if (!match) return localTime;
|
|
@@ -5090,11 +5545,11 @@ function stripPrefixFromStdLine(line) {
|
|
|
5090
5545
|
return `[${time}] ${content}`;
|
|
5091
5546
|
}
|
|
5092
5547
|
function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarker) {
|
|
5093
|
-
const stat =
|
|
5548
|
+
const stat = fs19.statSync(filePath);
|
|
5094
5549
|
if (stat.size === 0) {
|
|
5095
5550
|
return { lines: [], markerFound: false, totalLinesCount: 0 };
|
|
5096
5551
|
}
|
|
5097
|
-
const fd =
|
|
5552
|
+
const fd = fs19.openSync(filePath, "r");
|
|
5098
5553
|
const chunkSize = 64 * 1024;
|
|
5099
5554
|
let position = stat.size;
|
|
5100
5555
|
let remainder = "";
|
|
@@ -5108,7 +5563,7 @@ function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarke
|
|
|
5108
5563
|
const length = Math.min(chunkSize, position);
|
|
5109
5564
|
position -= length;
|
|
5110
5565
|
const buffer = Buffer.alloc(length);
|
|
5111
|
-
|
|
5566
|
+
fs19.readSync(fd, buffer, 0, length, position);
|
|
5112
5567
|
let chunk = buffer.toString("utf8");
|
|
5113
5568
|
if (remainder) {
|
|
5114
5569
|
chunk += remainder;
|
|
@@ -5150,7 +5605,7 @@ function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarke
|
|
|
5150
5605
|
}
|
|
5151
5606
|
}
|
|
5152
5607
|
} finally {
|
|
5153
|
-
|
|
5608
|
+
fs19.closeSync(fd);
|
|
5154
5609
|
}
|
|
5155
5610
|
return { lines: collected.reverse(), markerFound, totalLinesCount };
|
|
5156
5611
|
}
|
|
@@ -5171,21 +5626,21 @@ function readServerStdSegment(filePath, maxLines, offset) {
|
|
|
5171
5626
|
}
|
|
5172
5627
|
|
|
5173
5628
|
// src/commands/read-logs/tail.ts
|
|
5174
|
-
import
|
|
5629
|
+
import fs20 from "fs";
|
|
5175
5630
|
function fileExists(filePath) {
|
|
5176
5631
|
try {
|
|
5177
|
-
|
|
5632
|
+
fs20.accessSync(filePath, fs20.constants.F_OK | fs20.constants.R_OK);
|
|
5178
5633
|
return true;
|
|
5179
5634
|
} catch {
|
|
5180
5635
|
return false;
|
|
5181
5636
|
}
|
|
5182
5637
|
}
|
|
5183
5638
|
function readFileTailLines(filePath, maxLines) {
|
|
5184
|
-
const stat =
|
|
5639
|
+
const stat = fs20.statSync(filePath);
|
|
5185
5640
|
if (stat.size === 0) {
|
|
5186
5641
|
return [];
|
|
5187
5642
|
}
|
|
5188
|
-
const fd =
|
|
5643
|
+
const fd = fs20.openSync(filePath, "r");
|
|
5189
5644
|
const chunkSize = 64 * 1024;
|
|
5190
5645
|
const chunks = [];
|
|
5191
5646
|
let position = stat.size;
|
|
@@ -5195,13 +5650,13 @@ function readFileTailLines(filePath, maxLines) {
|
|
|
5195
5650
|
const length = Math.min(chunkSize, position);
|
|
5196
5651
|
position -= length;
|
|
5197
5652
|
const buffer = Buffer.alloc(length);
|
|
5198
|
-
|
|
5653
|
+
fs20.readSync(fd, buffer, 0, length, position);
|
|
5199
5654
|
chunks.unshift(buffer.toString("utf8"));
|
|
5200
5655
|
const chunkLines = buffer.toString("utf8").split("\n").length - 1;
|
|
5201
5656
|
collectedLines += chunkLines;
|
|
5202
5657
|
}
|
|
5203
5658
|
} finally {
|
|
5204
|
-
|
|
5659
|
+
fs20.closeSync(fd);
|
|
5205
5660
|
}
|
|
5206
5661
|
const content = chunks.join("");
|
|
5207
5662
|
const allLines = content.split("\n");
|
|
@@ -5217,11 +5672,11 @@ function readFileTailLines(filePath, maxLines) {
|
|
|
5217
5672
|
return allLines.slice(allLines.length - maxLines);
|
|
5218
5673
|
}
|
|
5219
5674
|
function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
|
|
5220
|
-
const stat =
|
|
5675
|
+
const stat = fs20.statSync(filePath);
|
|
5221
5676
|
if (stat.size === 0) {
|
|
5222
5677
|
return { lines: [], totalLinesCount: 0 };
|
|
5223
5678
|
}
|
|
5224
|
-
const fd =
|
|
5679
|
+
const fd = fs20.openSync(filePath, "r");
|
|
5225
5680
|
const chunkSize = 64 * 1024;
|
|
5226
5681
|
let position = stat.size;
|
|
5227
5682
|
let remainder = "";
|
|
@@ -5233,7 +5688,7 @@ function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
|
|
|
5233
5688
|
const length = Math.min(chunkSize, position);
|
|
5234
5689
|
position -= length;
|
|
5235
5690
|
const buffer = Buffer.alloc(length);
|
|
5236
|
-
|
|
5691
|
+
fs20.readSync(fd, buffer, 0, length, position);
|
|
5237
5692
|
let chunk = buffer.toString("utf8");
|
|
5238
5693
|
if (remainder) {
|
|
5239
5694
|
chunk += remainder;
|
|
@@ -5264,7 +5719,7 @@ function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
|
|
|
5264
5719
|
}
|
|
5265
5720
|
}
|
|
5266
5721
|
} finally {
|
|
5267
|
-
|
|
5722
|
+
fs20.closeSync(fd);
|
|
5268
5723
|
}
|
|
5269
5724
|
return { lines: collected.reverse(), totalLinesCount };
|
|
5270
5725
|
}
|
|
@@ -5277,13 +5732,19 @@ function readClientStdSegment(filePath, maxLines, offset) {
|
|
|
5277
5732
|
function extractClientStdSegment(lines, maxLines, offset) {
|
|
5278
5733
|
const bodyLines = lines.map(stripPrefixFromStdLine);
|
|
5279
5734
|
const hotStartMarkers = [
|
|
5735
|
+
// Webpack markers
|
|
5280
5736
|
/file change detected\..*incremental compilation/i,
|
|
5281
5737
|
/starting incremental compilation/i,
|
|
5282
5738
|
/starting compilation/i,
|
|
5283
5739
|
/\bcompiling\b/i,
|
|
5284
|
-
/\brecompil/i
|
|
5740
|
+
/\brecompil/i,
|
|
5741
|
+
// Vite markers - format: "3:11:46 PM [vite] (client) hmr update ..."
|
|
5742
|
+
/VITE v[\d.]+.*ready/i,
|
|
5743
|
+
/\[vite\].*page reload/i,
|
|
5744
|
+
/\[vite\].*hmr update/i
|
|
5285
5745
|
];
|
|
5286
5746
|
const hotEndMarkers = [
|
|
5747
|
+
// Webpack markers
|
|
5287
5748
|
/file change detected\..*incremental compilation/i,
|
|
5288
5749
|
/\bwebpack compiled\b/i,
|
|
5289
5750
|
/compiled successfully/i,
|
|
@@ -5294,14 +5755,25 @@ function extractClientStdSegment(lines, maxLines, offset) {
|
|
|
5294
5755
|
/\bhmr\b/i,
|
|
5295
5756
|
/hot update/i,
|
|
5296
5757
|
/\bhot reload\b/i,
|
|
5297
|
-
/\bhmr update\b/i
|
|
5758
|
+
/\bhmr update\b/i,
|
|
5759
|
+
// Vite markers
|
|
5760
|
+
/VITE v[\d.]+.*ready/i,
|
|
5761
|
+
/\[vite\].*page reload/i,
|
|
5762
|
+
/\[vite\].*hmr update/i,
|
|
5763
|
+
/\[vite\].*hmr invalidate/i,
|
|
5764
|
+
/\[vite\].*internal server error/i,
|
|
5765
|
+
/\[vite\].*pre-transform error/i
|
|
5298
5766
|
];
|
|
5299
5767
|
const compiledMarkers = [
|
|
5768
|
+
// Webpack markers
|
|
5300
5769
|
/\bwebpack compiled\b/i,
|
|
5301
5770
|
/compiled successfully/i,
|
|
5302
5771
|
/compiled with warnings/i,
|
|
5303
5772
|
/compiled with errors/i,
|
|
5304
|
-
/failed to compile/i
|
|
5773
|
+
/failed to compile/i,
|
|
5774
|
+
// Vite markers
|
|
5775
|
+
/VITE v[\d.]+.*ready/i,
|
|
5776
|
+
/\[vite\].*hmr update/i
|
|
5305
5777
|
];
|
|
5306
5778
|
let startIndex = -1;
|
|
5307
5779
|
for (let i = bodyLines.length - 1; i >= 0; i -= 1) {
|
|
@@ -5354,14 +5826,15 @@ function extractClientStdSegment(lines, maxLines, offset) {
|
|
|
5354
5826
|
}
|
|
5355
5827
|
const segment = startIndex === -1 ? bodyLines : bodyLines.slice(startIndex);
|
|
5356
5828
|
if (segment.length === 0) {
|
|
5357
|
-
return { lines: [], totalLinesCount: 0 };
|
|
5829
|
+
return { lines: [], totalLinesCount: 0, allLines: [] };
|
|
5358
5830
|
}
|
|
5359
5831
|
const totalLinesCount = segment.length;
|
|
5360
5832
|
const endExclusive = Math.max(0, segment.length - offset);
|
|
5361
5833
|
const start = Math.max(0, endExclusive - maxLines);
|
|
5362
5834
|
return {
|
|
5363
5835
|
lines: segment.slice(start, endExclusive),
|
|
5364
|
-
totalLinesCount
|
|
5836
|
+
totalLinesCount,
|
|
5837
|
+
allLines: segment
|
|
5365
5838
|
};
|
|
5366
5839
|
}
|
|
5367
5840
|
|
|
@@ -5388,7 +5861,7 @@ function readDevStdSegment(filePath, maxLines, offset) {
|
|
|
5388
5861
|
}
|
|
5389
5862
|
|
|
5390
5863
|
// src/commands/read-logs/json-lines.ts
|
|
5391
|
-
import
|
|
5864
|
+
import fs21 from "fs";
|
|
5392
5865
|
function normalizePid(value) {
|
|
5393
5866
|
if (typeof value === "number") {
|
|
5394
5867
|
return String(value);
|
|
@@ -5439,11 +5912,11 @@ function buildWantedLevelSet(levels) {
|
|
|
5439
5912
|
return set.size > 0 ? set : null;
|
|
5440
5913
|
}
|
|
5441
5914
|
function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
|
|
5442
|
-
const stat =
|
|
5915
|
+
const stat = fs21.statSync(filePath);
|
|
5443
5916
|
if (stat.size === 0) {
|
|
5444
5917
|
return { lines: [], totalLinesCount: 0 };
|
|
5445
5918
|
}
|
|
5446
|
-
const fd =
|
|
5919
|
+
const fd = fs21.openSync(filePath, "r");
|
|
5447
5920
|
const chunkSize = 64 * 1024;
|
|
5448
5921
|
let position = stat.size;
|
|
5449
5922
|
let remainder = "";
|
|
@@ -5458,7 +5931,7 @@ function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
|
|
|
5458
5931
|
const length = Math.min(chunkSize, position);
|
|
5459
5932
|
position -= length;
|
|
5460
5933
|
const buffer = Buffer.alloc(length);
|
|
5461
|
-
|
|
5934
|
+
fs21.readSync(fd, buffer, 0, length, position);
|
|
5462
5935
|
let chunk = buffer.toString("utf8");
|
|
5463
5936
|
if (remainder) {
|
|
5464
5937
|
chunk += remainder;
|
|
@@ -5520,7 +5993,7 @@ function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
|
|
|
5520
5993
|
}
|
|
5521
5994
|
}
|
|
5522
5995
|
} finally {
|
|
5523
|
-
|
|
5996
|
+
fs21.closeSync(fd);
|
|
5524
5997
|
}
|
|
5525
5998
|
return { lines: collected.reverse(), totalLinesCount };
|
|
5526
5999
|
}
|
|
@@ -5563,11 +6036,11 @@ function extractTraceId(obj) {
|
|
|
5563
6036
|
function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
|
|
5564
6037
|
const wanted = traceId.trim();
|
|
5565
6038
|
if (!wanted) return { lines: [], totalLinesCount: 0 };
|
|
5566
|
-
const stat =
|
|
6039
|
+
const stat = fs21.statSync(filePath);
|
|
5567
6040
|
if (stat.size === 0) {
|
|
5568
6041
|
return { lines: [], totalLinesCount: 0 };
|
|
5569
6042
|
}
|
|
5570
|
-
const fd =
|
|
6043
|
+
const fd = fs21.openSync(filePath, "r");
|
|
5571
6044
|
const chunkSize = 64 * 1024;
|
|
5572
6045
|
let position = stat.size;
|
|
5573
6046
|
let remainder = "";
|
|
@@ -5580,7 +6053,7 @@ function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
|
|
|
5580
6053
|
const length = Math.min(chunkSize, position);
|
|
5581
6054
|
position -= length;
|
|
5582
6055
|
const buffer = Buffer.alloc(length);
|
|
5583
|
-
|
|
6056
|
+
fs21.readSync(fd, buffer, 0, length, position);
|
|
5584
6057
|
let chunk = buffer.toString("utf8");
|
|
5585
6058
|
if (remainder) {
|
|
5586
6059
|
chunk += remainder;
|
|
@@ -5633,7 +6106,7 @@ function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
|
|
|
5633
6106
|
}
|
|
5634
6107
|
}
|
|
5635
6108
|
} finally {
|
|
5636
|
-
|
|
6109
|
+
fs21.closeSync(fd);
|
|
5637
6110
|
}
|
|
5638
6111
|
return { lines: collected.reverse(), totalLinesCount };
|
|
5639
6112
|
}
|
|
@@ -5642,11 +6115,11 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
|
|
|
5642
6115
|
if (!wantedLevelSet) {
|
|
5643
6116
|
return { lines: [], totalLinesCount: 0 };
|
|
5644
6117
|
}
|
|
5645
|
-
const stat =
|
|
6118
|
+
const stat = fs21.statSync(filePath);
|
|
5646
6119
|
if (stat.size === 0) {
|
|
5647
6120
|
return { lines: [], totalLinesCount: 0 };
|
|
5648
6121
|
}
|
|
5649
|
-
const fd =
|
|
6122
|
+
const fd = fs21.openSync(filePath, "r");
|
|
5650
6123
|
const chunkSize = 64 * 1024;
|
|
5651
6124
|
let position = stat.size;
|
|
5652
6125
|
let remainder = "";
|
|
@@ -5658,7 +6131,7 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
|
|
|
5658
6131
|
const length = Math.min(chunkSize, position);
|
|
5659
6132
|
position -= length;
|
|
5660
6133
|
const buffer = Buffer.alloc(length);
|
|
5661
|
-
|
|
6134
|
+
fs21.readSync(fd, buffer, 0, length, position);
|
|
5662
6135
|
let chunk = buffer.toString("utf8");
|
|
5663
6136
|
if (remainder) {
|
|
5664
6137
|
chunk += remainder;
|
|
@@ -5705,7 +6178,7 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
|
|
|
5705
6178
|
}
|
|
5706
6179
|
}
|
|
5707
6180
|
} finally {
|
|
5708
|
-
|
|
6181
|
+
fs21.closeSync(fd);
|
|
5709
6182
|
}
|
|
5710
6183
|
return { lines: collected.reverse(), totalLinesCount };
|
|
5711
6184
|
}
|
|
@@ -5898,12 +6371,21 @@ async function readLatestLogLinesMeta(options) {
|
|
|
5898
6371
|
return { lines: [], totalLinesCount: 0 };
|
|
5899
6372
|
}
|
|
5900
6373
|
async function readLogsJsonResult(options) {
|
|
5901
|
-
const { lines, totalLinesCount } = await readLatestLogLinesMeta(options);
|
|
6374
|
+
const { lines, totalLinesCount, allLines } = await readLatestLogLinesMeta(options);
|
|
5902
6375
|
if (options.type === "server-std" || options.type === "client-std" || options.type === "dev" || options.type === "dev-std" || options.type === "install-dep-std") {
|
|
6376
|
+
const linesForErrorCheck = allLines ?? lines;
|
|
6377
|
+
const stackTracePattern = /\bat\s+\S+\s+\([^)]+:\d+:\d+\)/;
|
|
6378
|
+
const linesToFilter = allLines ?? lines;
|
|
6379
|
+
const filteredLines = linesToFilter.filter((line) => !stackTracePattern.test(line));
|
|
6380
|
+
const maxLines = options.maxLines ?? 30;
|
|
6381
|
+
const offset = options.offset ?? 0;
|
|
6382
|
+
const endExclusive = Math.max(0, filteredLines.length - offset);
|
|
6383
|
+
const start = Math.max(0, endExclusive - maxLines);
|
|
6384
|
+
const paginatedLogs = filteredLines.slice(start, endExclusive);
|
|
5903
6385
|
return {
|
|
5904
|
-
hasError: hasErrorInStdLines(
|
|
5905
|
-
totalLinesCount,
|
|
5906
|
-
logs:
|
|
6386
|
+
hasError: hasErrorInStdLines(linesForErrorCheck),
|
|
6387
|
+
totalLinesCount: filteredLines.length,
|
|
6388
|
+
logs: paginatedLogs
|
|
5907
6389
|
};
|
|
5908
6390
|
}
|
|
5909
6391
|
const logs = [];
|
|
@@ -5930,30 +6412,30 @@ async function readLogsJsonResult(options) {
|
|
|
5930
6412
|
};
|
|
5931
6413
|
}
|
|
5932
6414
|
function resolveLogFilePath(logDir, type) {
|
|
5933
|
-
const base =
|
|
6415
|
+
const base = path17.isAbsolute(logDir) ? logDir : path17.join(process.cwd(), logDir);
|
|
5934
6416
|
if (type === "server") {
|
|
5935
|
-
return
|
|
6417
|
+
return path17.join(base, "server.log");
|
|
5936
6418
|
}
|
|
5937
6419
|
if (type === "trace") {
|
|
5938
|
-
return
|
|
6420
|
+
return path17.join(base, "trace.log");
|
|
5939
6421
|
}
|
|
5940
6422
|
if (type === "server-std") {
|
|
5941
|
-
return
|
|
6423
|
+
return path17.join(base, "server.std.log");
|
|
5942
6424
|
}
|
|
5943
6425
|
if (type === "client-std") {
|
|
5944
|
-
return
|
|
6426
|
+
return path17.join(base, "client.std.log");
|
|
5945
6427
|
}
|
|
5946
6428
|
if (type === "dev") {
|
|
5947
|
-
return
|
|
6429
|
+
return path17.join(base, "dev.log");
|
|
5948
6430
|
}
|
|
5949
6431
|
if (type === "dev-std") {
|
|
5950
|
-
return
|
|
6432
|
+
return path17.join(base, "dev.std.log");
|
|
5951
6433
|
}
|
|
5952
6434
|
if (type === "install-dep-std") {
|
|
5953
|
-
return
|
|
6435
|
+
return path17.join(base, "install-dep.std.log");
|
|
5954
6436
|
}
|
|
5955
6437
|
if (type === "browser") {
|
|
5956
|
-
return
|
|
6438
|
+
return path17.join(base, "browser.log");
|
|
5957
6439
|
}
|
|
5958
6440
|
throw new Error(`Unsupported log type: ${type}`);
|
|
5959
6441
|
}
|
|
@@ -6015,17 +6497,18 @@ var commands = [
|
|
|
6015
6497
|
syncCommand,
|
|
6016
6498
|
actionPluginCommandGroup,
|
|
6017
6499
|
capabilityCommandGroup,
|
|
6500
|
+
componentCommandGroup,
|
|
6018
6501
|
migrationCommand,
|
|
6019
6502
|
readLogsCommand
|
|
6020
6503
|
];
|
|
6021
6504
|
|
|
6022
6505
|
// src/index.ts
|
|
6023
|
-
var envPath =
|
|
6024
|
-
if (
|
|
6506
|
+
var envPath = path18.join(process.cwd(), ".env");
|
|
6507
|
+
if (fs22.existsSync(envPath)) {
|
|
6025
6508
|
dotenvConfig({ path: envPath });
|
|
6026
6509
|
}
|
|
6027
|
-
var __dirname =
|
|
6028
|
-
var pkg = JSON.parse(
|
|
6510
|
+
var __dirname = path18.dirname(fileURLToPath4(import.meta.url));
|
|
6511
|
+
var pkg = JSON.parse(fs22.readFileSync(path18.join(__dirname, "../package.json"), "utf-8"));
|
|
6029
6512
|
var cli = new FullstackCLI(pkg.version);
|
|
6030
6513
|
cli.useAll(commands);
|
|
6031
6514
|
cli.run();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lark-apaas/fullstack-cli",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.20-alpha.1",
|
|
4
4
|
"description": "CLI tool for fullstack template management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -32,18 +32,23 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@lark-apaas/http-client": "^0.1.2",
|
|
35
|
+
"@lydell/node-pty": "1.1.0",
|
|
35
36
|
"@vercel/nft": "^0.30.3",
|
|
36
37
|
"commander": "^13.0.0",
|
|
38
|
+
"debug": "^4.4.3",
|
|
37
39
|
"dotenv": "^16.0.0",
|
|
38
40
|
"drizzle-kit": "0.31.5",
|
|
39
41
|
"drizzle-orm": "0.44.6",
|
|
42
|
+
"es-toolkit": "^1.44.0",
|
|
40
43
|
"inflection": "^3.0.2",
|
|
41
44
|
"pinyin-pro": "^3.27.0",
|
|
42
45
|
"postgres": "^3.4.3",
|
|
46
|
+
"shadcn": "3.8.2",
|
|
43
47
|
"ts-morph": "^27.0.0",
|
|
44
48
|
"zod-to-json-schema": "^3.24.1"
|
|
45
49
|
},
|
|
46
50
|
"devDependencies": {
|
|
51
|
+
"@types/debug": "^4",
|
|
47
52
|
"@types/node": "^22.0.0",
|
|
48
53
|
"tsup": "^8.3.5",
|
|
49
54
|
"typescript": "^5.9.2",
|