@kithinji/pod 1.0.42 → 1.0.47
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 +1089 -344
- package/dist/index.js.map +3 -3
- package/dist/types/index.d.ts +1 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/macros/expand_macros.d.ts.map +1 -1
- package/dist/types/plugins/analyzers/graph.d.ts.map +1 -1
- package/dist/types/plugins/generators/generate_controller.d.ts +5 -1
- package/dist/types/plugins/generators/generate_controller.d.ts.map +1 -1
- package/dist/types/plugins/generators/generate_rpc.d.ts.map +1 -1
- package/dist/types/plugins/generators/utils.d.ts +46 -4
- package/dist/types/plugins/generators/utils.d.ts.map +1 -1
- package/dist/types/plugins/my.d.ts.map +1 -1
- package/dist/types/plugins/transformers/j2d.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/cli.js +0 -6780
- package/dist/cli.js.map +0 -7
- package/dist/types/cli.d.ts +0 -3
- package/dist/types/cli.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
1
2
|
var __defProp = Object.defineProperty;
|
|
2
3
|
var __export = (target, all) => {
|
|
3
4
|
for (var name in all)
|
|
@@ -499,7 +500,7 @@ function resolveImportFullPath(symbolName, sourceFile, compilerOptions) {
|
|
|
499
500
|
};
|
|
500
501
|
}
|
|
501
502
|
function isNpmPackage(importPath) {
|
|
502
|
-
return !importPath.startsWith(".") && !importPath.startsWith("/") && !path3.isAbsolute(importPath);
|
|
503
|
+
return !importPath.startsWith(".") && !importPath.startsWith("/") && !importPath.startsWith("@/") && !path3.isAbsolute(importPath);
|
|
503
504
|
}
|
|
504
505
|
function findVariableDeclarationInFile(variableName, sourceFile) {
|
|
505
506
|
let found;
|
|
@@ -929,6 +930,7 @@ async function expandMacros(source, filePath, projectRoot = process.cwd()) {
|
|
|
929
930
|
|
|
930
931
|
// src/plugins/generators/generate_controller.ts
|
|
931
932
|
import * as path4 from "path";
|
|
933
|
+
import { printSync } from "@swc/core";
|
|
932
934
|
|
|
933
935
|
// src/plugins/generators/utils.ts
|
|
934
936
|
import {
|
|
@@ -963,8 +965,20 @@ function hasInjectableDecorator(decorators) {
|
|
|
963
965
|
return expr.type === "Identifier" && expr.value === "Injectable" || expr.type === "CallExpression" && expr.callee.type === "Identifier" && expr.callee.value === "Injectable";
|
|
964
966
|
});
|
|
965
967
|
}
|
|
968
|
+
function isClassMethod(member) {
|
|
969
|
+
return member.type === "ClassMethod";
|
|
970
|
+
}
|
|
971
|
+
function isClassProperty(member) {
|
|
972
|
+
return member.type === "ClassProperty";
|
|
973
|
+
}
|
|
974
|
+
function isConstructor(member) {
|
|
975
|
+
return member.type === "Constructor";
|
|
976
|
+
}
|
|
966
977
|
function isPublicMethod(member) {
|
|
967
|
-
return member.type === "ClassMethod" && (member.accessibility === "public" ||
|
|
978
|
+
return member.type === "ClassMethod" && (member.accessibility === "public" || member.accessibility === void 0);
|
|
979
|
+
}
|
|
980
|
+
function isPrivateMethod(member) {
|
|
981
|
+
return member.type === "ClassMethod" && member.accessibility === "private";
|
|
968
982
|
}
|
|
969
983
|
function getMethodName(method) {
|
|
970
984
|
if (method.key.type === "Identifier") {
|
|
@@ -1026,23 +1040,36 @@ function analyzeReturnType(method) {
|
|
|
1026
1040
|
isSubjectLike: false
|
|
1027
1041
|
};
|
|
1028
1042
|
}
|
|
1043
|
+
function stringifyEntityName(node) {
|
|
1044
|
+
if (!node) return "any";
|
|
1045
|
+
switch (node.type) {
|
|
1046
|
+
case "Identifier":
|
|
1047
|
+
return node.value;
|
|
1048
|
+
case "TsQualifiedName":
|
|
1049
|
+
return `${stringifyEntityName(node.left)}.${stringifyEntityName(
|
|
1050
|
+
node.right
|
|
1051
|
+
)}`;
|
|
1052
|
+
default:
|
|
1053
|
+
return "any";
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1029
1056
|
function stringifyType(node) {
|
|
1030
1057
|
if (!node) return "any";
|
|
1031
1058
|
switch (node.type) {
|
|
1032
1059
|
case "TsKeywordType":
|
|
1033
1060
|
return node.kind;
|
|
1034
|
-
case "TsTypeReference":
|
|
1035
|
-
|
|
1036
|
-
const base = node.typeName.value;
|
|
1061
|
+
case "TsTypeReference": {
|
|
1062
|
+
const base = stringifyEntityName(node.typeName);
|
|
1037
1063
|
const args = node.typeParams?.params ? `<${node.typeParams.params.map(stringifyType).join(", ")}>` : "";
|
|
1038
1064
|
return base + args;
|
|
1065
|
+
}
|
|
1039
1066
|
case "TsArrayType":
|
|
1040
1067
|
return `${stringifyType(node.elemType)}[]`;
|
|
1041
1068
|
case "TsUnionType":
|
|
1042
1069
|
return node.types.map(stringifyType).join(" | ");
|
|
1043
1070
|
case "TsIntersectionType":
|
|
1044
1071
|
return node.types.map(stringifyType).join(" & ");
|
|
1045
|
-
case "TsTypeLiteral":
|
|
1072
|
+
case "TsTypeLiteral": {
|
|
1046
1073
|
const props = node.members.map((member) => {
|
|
1047
1074
|
if (member.type === "TsPropertySignature") {
|
|
1048
1075
|
const key = member.key.type === "Identifier" ? member.key.value : "";
|
|
@@ -1052,10 +1079,55 @@ function stringifyType(node) {
|
|
|
1052
1079
|
return "";
|
|
1053
1080
|
}).filter(Boolean);
|
|
1054
1081
|
return `{ ${props.join("; ")} }`;
|
|
1082
|
+
}
|
|
1055
1083
|
default:
|
|
1056
1084
|
return "any";
|
|
1057
1085
|
}
|
|
1058
1086
|
}
|
|
1087
|
+
function stringifyDecorator(decorator) {
|
|
1088
|
+
const expr = decorator.expression;
|
|
1089
|
+
if (expr.type === "Identifier") {
|
|
1090
|
+
return `@${expr.value}`;
|
|
1091
|
+
}
|
|
1092
|
+
if (expr.type === "CallExpression" && expr.callee.type === "Identifier") {
|
|
1093
|
+
const args = expr.arguments.map((arg) => stringifyExpression(arg.expression)).join(", ");
|
|
1094
|
+
return args ? `@${expr.callee.value}(${args})` : `@${expr.callee.value}()`;
|
|
1095
|
+
}
|
|
1096
|
+
return "@Unknown";
|
|
1097
|
+
}
|
|
1098
|
+
function shouldLiftDecorator(decoratorString) {
|
|
1099
|
+
const match = decoratorString.match(/^@(_)?([A-Za-z0-9]+)/);
|
|
1100
|
+
if (!match) return false;
|
|
1101
|
+
const prefix = match[1];
|
|
1102
|
+
return !prefix;
|
|
1103
|
+
}
|
|
1104
|
+
function extractMethodDecorators(method) {
|
|
1105
|
+
const decorators = [];
|
|
1106
|
+
if (method.function.decorators) {
|
|
1107
|
+
for (const decorator of method.function.decorators) {
|
|
1108
|
+
decorators.push(stringifyDecorator(decorator));
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
return decorators;
|
|
1112
|
+
}
|
|
1113
|
+
function extractParamDecorators(param) {
|
|
1114
|
+
const decorators = [];
|
|
1115
|
+
if (param.decorators) {
|
|
1116
|
+
for (const decorator of param.decorators) {
|
|
1117
|
+
decorators.push(stringifyDecorator(decorator));
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
return decorators;
|
|
1121
|
+
}
|
|
1122
|
+
function extractPropertyDecorators(property) {
|
|
1123
|
+
const decorators = [];
|
|
1124
|
+
if (property.decorators) {
|
|
1125
|
+
for (const decorator of property.decorators) {
|
|
1126
|
+
decorators.push(stringifyDecorator(decorator));
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
return decorators;
|
|
1130
|
+
}
|
|
1059
1131
|
function extractMethodParams(params) {
|
|
1060
1132
|
return params.map((p) => {
|
|
1061
1133
|
const pat = p.pat;
|
|
@@ -1063,17 +1135,222 @@ function extractMethodParams(params) {
|
|
|
1063
1135
|
return {
|
|
1064
1136
|
name: "param",
|
|
1065
1137
|
type: "any",
|
|
1066
|
-
decorators:
|
|
1138
|
+
decorators: extractParamDecorators(p)
|
|
1067
1139
|
};
|
|
1068
1140
|
}
|
|
1069
1141
|
return {
|
|
1070
1142
|
name: pat.value,
|
|
1071
1143
|
type: pat.typeAnnotation ? stringifyType(pat.typeAnnotation.typeAnnotation) : "any",
|
|
1072
|
-
decorators:
|
|
1144
|
+
decorators: extractParamDecorators(p)
|
|
1073
1145
|
};
|
|
1074
1146
|
});
|
|
1075
1147
|
}
|
|
1076
|
-
function
|
|
1148
|
+
function extractIdentifiersFromQualifiedName(node) {
|
|
1149
|
+
const identifiers = [];
|
|
1150
|
+
if (node.type === "Identifier") {
|
|
1151
|
+
identifiers.push(node.value);
|
|
1152
|
+
} else if (node.type === "TsQualifiedName") {
|
|
1153
|
+
identifiers.push(...extractIdentifiersFromQualifiedName(node.left));
|
|
1154
|
+
identifiers.push(...extractIdentifiersFromQualifiedName(node.right));
|
|
1155
|
+
}
|
|
1156
|
+
return identifiers;
|
|
1157
|
+
}
|
|
1158
|
+
function extractIdentifiersFromType(node) {
|
|
1159
|
+
if (!node) return [];
|
|
1160
|
+
const identifiers = [];
|
|
1161
|
+
switch (node.type) {
|
|
1162
|
+
case "TsKeywordType":
|
|
1163
|
+
return [];
|
|
1164
|
+
case "TsTypeReference": {
|
|
1165
|
+
if (node.typeName.type === "Identifier") {
|
|
1166
|
+
identifiers.push(node.typeName.value);
|
|
1167
|
+
} else if (node.typeName.type === "TsQualifiedName") {
|
|
1168
|
+
identifiers.push(...extractIdentifiersFromQualifiedName(node.typeName));
|
|
1169
|
+
}
|
|
1170
|
+
if (node.typeParams?.params) {
|
|
1171
|
+
for (const param of node.typeParams.params) {
|
|
1172
|
+
identifiers.push(...extractIdentifiersFromType(param));
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
break;
|
|
1176
|
+
}
|
|
1177
|
+
case "TsArrayType":
|
|
1178
|
+
identifiers.push(...extractIdentifiersFromType(node.elemType));
|
|
1179
|
+
break;
|
|
1180
|
+
case "TsUnionType":
|
|
1181
|
+
case "TsIntersectionType":
|
|
1182
|
+
for (const type of node.types) {
|
|
1183
|
+
identifiers.push(...extractIdentifiersFromType(type));
|
|
1184
|
+
}
|
|
1185
|
+
break;
|
|
1186
|
+
case "TsTypeLiteral":
|
|
1187
|
+
for (const member of node.members) {
|
|
1188
|
+
if (member.type === "TsPropertySignature" && member.typeAnnotation) {
|
|
1189
|
+
identifiers.push(
|
|
1190
|
+
...extractIdentifiersFromType(member.typeAnnotation.typeAnnotation)
|
|
1191
|
+
);
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
break;
|
|
1195
|
+
case "TsTupleType":
|
|
1196
|
+
if (node.elemTypes) {
|
|
1197
|
+
for (const elem of node.elemTypes) {
|
|
1198
|
+
identifiers.push(...extractIdentifiersFromType(elem));
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
break;
|
|
1202
|
+
}
|
|
1203
|
+
return identifiers;
|
|
1204
|
+
}
|
|
1205
|
+
function extractIdentifiersFromDecorator(decorator) {
|
|
1206
|
+
const identifiers = [];
|
|
1207
|
+
const expr = decorator.expression;
|
|
1208
|
+
if (expr.type === "Identifier") {
|
|
1209
|
+
identifiers.push(expr.value);
|
|
1210
|
+
} else if (expr.type === "CallExpression") {
|
|
1211
|
+
if (expr.callee.type === "Identifier") {
|
|
1212
|
+
identifiers.push(expr.callee.value);
|
|
1213
|
+
}
|
|
1214
|
+
for (const arg of expr.arguments) {
|
|
1215
|
+
identifiers.push(...extractIdentifiersFromExpression(arg.expression));
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
return identifiers;
|
|
1219
|
+
}
|
|
1220
|
+
function extractIdentifiersFromExpression(expr) {
|
|
1221
|
+
if (!expr) return [];
|
|
1222
|
+
const identifiers = [];
|
|
1223
|
+
switch (expr.type) {
|
|
1224
|
+
case "Identifier":
|
|
1225
|
+
identifiers.push(expr.value);
|
|
1226
|
+
break;
|
|
1227
|
+
case "MemberExpression":
|
|
1228
|
+
identifiers.push(...extractIdentifiersFromExpression(expr.object));
|
|
1229
|
+
if (expr.property.type === "Identifier") {
|
|
1230
|
+
identifiers.push(expr.property.value);
|
|
1231
|
+
}
|
|
1232
|
+
break;
|
|
1233
|
+
case "CallExpression":
|
|
1234
|
+
identifiers.push(...extractIdentifiersFromExpression(expr.callee));
|
|
1235
|
+
for (const arg of expr.arguments) {
|
|
1236
|
+
identifiers.push(...extractIdentifiersFromExpression(arg.expression));
|
|
1237
|
+
}
|
|
1238
|
+
break;
|
|
1239
|
+
}
|
|
1240
|
+
return identifiers;
|
|
1241
|
+
}
|
|
1242
|
+
function resolveImports(identifiers, importMap) {
|
|
1243
|
+
const imports = [];
|
|
1244
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1245
|
+
for (const identifier of identifiers) {
|
|
1246
|
+
if (seen.has(identifier)) continue;
|
|
1247
|
+
const source = importMap[identifier];
|
|
1248
|
+
if (source) {
|
|
1249
|
+
imports.push({ identifier, source });
|
|
1250
|
+
seen.add(identifier);
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
return imports;
|
|
1254
|
+
}
|
|
1255
|
+
function extractClassProperties(classDecl, importMap) {
|
|
1256
|
+
const properties = [];
|
|
1257
|
+
if (!classDecl.body || !Array.isArray(classDecl.body)) {
|
|
1258
|
+
return properties;
|
|
1259
|
+
}
|
|
1260
|
+
for (const member of classDecl.body) {
|
|
1261
|
+
if (!isClassProperty(member)) continue;
|
|
1262
|
+
const property = member;
|
|
1263
|
+
if (property.key.type !== "Identifier") continue;
|
|
1264
|
+
const propertyName = property.key.value;
|
|
1265
|
+
const propertyType = property.typeAnnotation ? stringifyType(property.typeAnnotation.typeAnnotation) : "any";
|
|
1266
|
+
const identifiers = [];
|
|
1267
|
+
if (property.typeAnnotation) {
|
|
1268
|
+
identifiers.push(
|
|
1269
|
+
...extractIdentifiersFromType(property.typeAnnotation.typeAnnotation)
|
|
1270
|
+
);
|
|
1271
|
+
}
|
|
1272
|
+
if (property.decorators) {
|
|
1273
|
+
for (const decorator of property.decorators) {
|
|
1274
|
+
identifiers.push(...extractIdentifiersFromDecorator(decorator));
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
const imports = resolveImports(identifiers, importMap);
|
|
1278
|
+
properties.push({
|
|
1279
|
+
name: propertyName,
|
|
1280
|
+
type: propertyType,
|
|
1281
|
+
isReadonly: property.readonly || false,
|
|
1282
|
+
isStatic: property.isStatic || false,
|
|
1283
|
+
accessibility: property.accessibility,
|
|
1284
|
+
decorators: extractPropertyDecorators(property),
|
|
1285
|
+
hasInitializer: !!property.value,
|
|
1286
|
+
imports
|
|
1287
|
+
});
|
|
1288
|
+
}
|
|
1289
|
+
return properties;
|
|
1290
|
+
}
|
|
1291
|
+
function extractConstructorParams(classDecl, importMap) {
|
|
1292
|
+
const params = [];
|
|
1293
|
+
if (!classDecl.body || !Array.isArray(classDecl.body)) {
|
|
1294
|
+
return params;
|
|
1295
|
+
}
|
|
1296
|
+
for (const member of classDecl.body) {
|
|
1297
|
+
if (!isConstructor(member)) continue;
|
|
1298
|
+
const constructor = member;
|
|
1299
|
+
for (const param of constructor.params) {
|
|
1300
|
+
if (param.type === "TsParameterProperty") {
|
|
1301
|
+
const tsParam = param;
|
|
1302
|
+
const pat = tsParam.param;
|
|
1303
|
+
if (pat.type !== "Identifier") continue;
|
|
1304
|
+
const identifiers = [];
|
|
1305
|
+
if (pat.typeAnnotation) {
|
|
1306
|
+
identifiers.push(
|
|
1307
|
+
...extractIdentifiersFromType(pat.typeAnnotation.typeAnnotation)
|
|
1308
|
+
);
|
|
1309
|
+
}
|
|
1310
|
+
if (tsParam.decorators) {
|
|
1311
|
+
for (const decorator of tsParam.decorators) {
|
|
1312
|
+
identifiers.push(...extractIdentifiersFromDecorator(decorator));
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
const imports = resolveImports(identifiers, importMap);
|
|
1316
|
+
params.push({
|
|
1317
|
+
name: pat.value,
|
|
1318
|
+
type: pat.typeAnnotation ? stringifyType(pat.typeAnnotation.typeAnnotation) : "any",
|
|
1319
|
+
accessibility: tsParam.accessibility,
|
|
1320
|
+
isReadonly: tsParam.readonly || false,
|
|
1321
|
+
decorators: extractParamDecorators(tsParam),
|
|
1322
|
+
imports
|
|
1323
|
+
});
|
|
1324
|
+
} else if (param.type === "Parameter") {
|
|
1325
|
+
const regularParam = param;
|
|
1326
|
+
const pat = regularParam.pat;
|
|
1327
|
+
if (pat.type !== "Identifier") continue;
|
|
1328
|
+
const identifiers = [];
|
|
1329
|
+
if (pat.typeAnnotation) {
|
|
1330
|
+
identifiers.push(
|
|
1331
|
+
...extractIdentifiersFromType(pat.typeAnnotation.typeAnnotation)
|
|
1332
|
+
);
|
|
1333
|
+
}
|
|
1334
|
+
if (regularParam.decorators) {
|
|
1335
|
+
for (const decorator of regularParam.decorators) {
|
|
1336
|
+
identifiers.push(...extractIdentifiersFromDecorator(decorator));
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
const imports = resolveImports(identifiers, importMap);
|
|
1340
|
+
params.push({
|
|
1341
|
+
name: pat.value,
|
|
1342
|
+
type: pat.typeAnnotation ? stringifyType(pat.typeAnnotation.typeAnnotation) : "any",
|
|
1343
|
+
accessibility: void 0,
|
|
1344
|
+
isReadonly: false,
|
|
1345
|
+
decorators: extractParamDecorators(regularParam),
|
|
1346
|
+
imports
|
|
1347
|
+
});
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
return params;
|
|
1352
|
+
}
|
|
1353
|
+
function extractSignature(decorators, paramCount, className, methodName, filePath) {
|
|
1077
1354
|
if (!decorators) return { paramSchemas: [] };
|
|
1078
1355
|
for (const decorator of decorators) {
|
|
1079
1356
|
const expr = decorator.expression;
|
|
@@ -1083,6 +1360,14 @@ function extractSignature(decorators, paramCount) {
|
|
|
1083
1360
|
const schemaStrings = args.map(
|
|
1084
1361
|
(arg) => stringifyExpression(arg.expression)
|
|
1085
1362
|
);
|
|
1363
|
+
if (paramCount === 0 && args.length === 1) {
|
|
1364
|
+
return { paramSchemas: [], returnSchema: schemaStrings[0] };
|
|
1365
|
+
}
|
|
1366
|
+
if (args.length !== paramCount + 1) {
|
|
1367
|
+
console.warn(
|
|
1368
|
+
`Warning: Method ${className}.${methodName} has ${paramCount} parameter(s) but @Signature has ${args.length} argument(s). Expected ${paramCount + 1} (${paramCount} param schema(s) + 1 return schema).`
|
|
1369
|
+
);
|
|
1370
|
+
}
|
|
1086
1371
|
if (args.length === 1) {
|
|
1087
1372
|
return { paramSchemas: [], returnSchema: schemaStrings[0] };
|
|
1088
1373
|
}
|
|
@@ -1110,15 +1395,36 @@ function stringifyExpression(expr) {
|
|
|
1110
1395
|
}
|
|
1111
1396
|
return "any";
|
|
1112
1397
|
}
|
|
1113
|
-
function extractMethods(classDecl, filePath, includeSignatures = true) {
|
|
1398
|
+
function extractMethods(classDecl, filePath, includeSignatures = true, includeHeaders = false) {
|
|
1114
1399
|
const methods = [];
|
|
1115
1400
|
const className = classDecl.identifier?.value || "UnknownClass";
|
|
1401
|
+
if (!classDecl.body || !Array.isArray(classDecl.body)) {
|
|
1402
|
+
return methods;
|
|
1403
|
+
}
|
|
1116
1404
|
for (const member of classDecl.body) {
|
|
1117
|
-
if (!
|
|
1405
|
+
if (!isClassMethod(member)) continue;
|
|
1118
1406
|
const method = member;
|
|
1119
1407
|
const methodName = getMethodName(method);
|
|
1120
1408
|
if (!methodName) continue;
|
|
1409
|
+
const endsWithHeaders = methodName.endsWith("Headers");
|
|
1121
1410
|
const returnTypeInfo = analyzeReturnType(method);
|
|
1411
|
+
if (isPrivateMethod(member) && includeHeaders && endsWithHeaders) {
|
|
1412
|
+
methods.push({
|
|
1413
|
+
name: methodName,
|
|
1414
|
+
params: extractMethodParams(method.function.params),
|
|
1415
|
+
returnType: returnTypeInfo.type,
|
|
1416
|
+
isAsync: method.function.async,
|
|
1417
|
+
isStreamable: returnTypeInfo.isStreamable,
|
|
1418
|
+
streamType: returnTypeInfo.streamType,
|
|
1419
|
+
paramSchemas: [],
|
|
1420
|
+
returnSchema: void 0,
|
|
1421
|
+
decorators: void 0,
|
|
1422
|
+
lift: true,
|
|
1423
|
+
ast: method
|
|
1424
|
+
});
|
|
1425
|
+
continue;
|
|
1426
|
+
}
|
|
1427
|
+
if (!isPublicMethod(member)) continue;
|
|
1122
1428
|
if (!returnTypeInfo.isStreamable && !method.function.async) {
|
|
1123
1429
|
throw {
|
|
1124
1430
|
type: "validation",
|
|
@@ -1131,7 +1437,10 @@ function extractMethods(classDecl, filePath, includeSignatures = true) {
|
|
|
1131
1437
|
}
|
|
1132
1438
|
const signatures = includeSignatures ? extractSignature(
|
|
1133
1439
|
method.function.decorators,
|
|
1134
|
-
method.function.params.length
|
|
1440
|
+
method.function.params.length,
|
|
1441
|
+
className,
|
|
1442
|
+
methodName,
|
|
1443
|
+
filePath
|
|
1135
1444
|
) : { paramSchemas: [] };
|
|
1136
1445
|
methods.push({
|
|
1137
1446
|
name: methodName,
|
|
@@ -1141,11 +1450,41 @@ function extractMethods(classDecl, filePath, includeSignatures = true) {
|
|
|
1141
1450
|
isStreamable: returnTypeInfo.isStreamable,
|
|
1142
1451
|
streamType: returnTypeInfo.streamType,
|
|
1143
1452
|
paramSchemas: signatures.paramSchemas,
|
|
1144
|
-
returnSchema: signatures.returnSchema
|
|
1453
|
+
returnSchema: signatures.returnSchema,
|
|
1454
|
+
decorators: extractMethodDecorators(method),
|
|
1455
|
+
lift: false,
|
|
1456
|
+
ast: method
|
|
1145
1457
|
});
|
|
1146
1458
|
}
|
|
1147
1459
|
return methods;
|
|
1148
1460
|
}
|
|
1461
|
+
function removeLiftedDecoratorsFromAST(ast) {
|
|
1462
|
+
const clonedAst = JSON.parse(JSON.stringify(ast));
|
|
1463
|
+
for (const item of clonedAst.body) {
|
|
1464
|
+
if (item.type === "ExportDeclaration" && item.declaration?.type === "ClassDeclaration") {
|
|
1465
|
+
const classDecl = item.declaration;
|
|
1466
|
+
if (hasInjectableDecorator(classDecl.decorators)) {
|
|
1467
|
+
for (const member of classDecl.body) {
|
|
1468
|
+
if (member.type === "ClassMethod" && (member.accessibility === "public" || member.accessibility === void 0)) {
|
|
1469
|
+
const method = member;
|
|
1470
|
+
if (method.function.decorators) {
|
|
1471
|
+
method.function.decorators = method.function.decorators.filter(
|
|
1472
|
+
(decorator) => {
|
|
1473
|
+
const decoratorStr = stringifyDecorator(decorator);
|
|
1474
|
+
return !shouldLiftDecorator(decoratorStr);
|
|
1475
|
+
}
|
|
1476
|
+
);
|
|
1477
|
+
if (method.function.decorators.length === 0) {
|
|
1478
|
+
delete method.function.decorators;
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
return clonedAst;
|
|
1487
|
+
}
|
|
1149
1488
|
function serviceNameToPath(serviceName) {
|
|
1150
1489
|
return serviceName.replace(/Service$/, "").replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
1151
1490
|
}
|
|
@@ -1169,23 +1508,43 @@ function validateServiceInfo(serviceInfo, filePath) {
|
|
|
1169
1508
|
);
|
|
1170
1509
|
}
|
|
1171
1510
|
serviceInfo.methods.forEach((method) => {
|
|
1172
|
-
if (method.params.length > 0 && method.paramSchemas?.length === 0) {
|
|
1511
|
+
if (method.params.length > 0 && method.paramSchemas?.length === 0 && !method.returnSchema) {
|
|
1173
1512
|
console.warn(
|
|
1174
|
-
`Warning: Method ${serviceInfo.className}.${method.name} has
|
|
1513
|
+
`Warning: Method ${serviceInfo.className}.${method.name} has ${method.params.length} parameter(s) but no @Signature validation`
|
|
1175
1514
|
);
|
|
1176
1515
|
}
|
|
1177
1516
|
});
|
|
1178
1517
|
}
|
|
1179
|
-
function extractServiceInfo(ast, filePath, includeSignatures = true) {
|
|
1518
|
+
function extractServiceInfo(ast, filePath, includeSignatures = true, includeHeaders = false, includeFields = false) {
|
|
1180
1519
|
try {
|
|
1181
1520
|
const serviceClass = findInjectableClass(ast);
|
|
1182
1521
|
const importMap = extractImportMap(ast);
|
|
1183
1522
|
if (!serviceClass?.identifier) {
|
|
1184
1523
|
return null;
|
|
1185
1524
|
}
|
|
1525
|
+
if (!serviceClass.body) {
|
|
1526
|
+
console.warn(
|
|
1527
|
+
`Warning: Service class ${serviceClass.identifier.value} has no body`
|
|
1528
|
+
);
|
|
1529
|
+
return {
|
|
1530
|
+
className: serviceClass.identifier.value,
|
|
1531
|
+
methods: [],
|
|
1532
|
+
properties: [],
|
|
1533
|
+
constructorParams: [],
|
|
1534
|
+
hasInjectable: true,
|
|
1535
|
+
importMap
|
|
1536
|
+
};
|
|
1537
|
+
}
|
|
1186
1538
|
return {
|
|
1187
1539
|
className: serviceClass.identifier.value,
|
|
1188
|
-
methods: extractMethods(
|
|
1540
|
+
methods: extractMethods(
|
|
1541
|
+
serviceClass,
|
|
1542
|
+
filePath,
|
|
1543
|
+
includeSignatures,
|
|
1544
|
+
includeHeaders
|
|
1545
|
+
),
|
|
1546
|
+
properties: includeFields ? extractClassProperties(serviceClass, importMap) : [],
|
|
1547
|
+
constructorParams: includeFields ? extractConstructorParams(serviceClass, importMap) : [],
|
|
1189
1548
|
hasInjectable: true,
|
|
1190
1549
|
importMap
|
|
1191
1550
|
};
|
|
@@ -1203,12 +1562,18 @@ function extractServiceInfo(ast, filePath, includeSignatures = true) {
|
|
|
1203
1562
|
function generateController(filePath, code) {
|
|
1204
1563
|
try {
|
|
1205
1564
|
const ast = parseTypeScript(filePath, code);
|
|
1206
|
-
const serviceInfo = extractServiceInfo(ast, filePath, true);
|
|
1565
|
+
const serviceInfo = extractServiceInfo(ast, filePath, true, false);
|
|
1207
1566
|
if (!serviceInfo || !serviceInfo.hasInjectable) {
|
|
1208
1567
|
return null;
|
|
1209
1568
|
}
|
|
1210
1569
|
validateServiceInfo(serviceInfo, filePath);
|
|
1211
|
-
|
|
1570
|
+
const transformedAst = removeLiftedDecoratorsFromAST(ast);
|
|
1571
|
+
const transformedServiceCode = printSync(transformedAst).code;
|
|
1572
|
+
const controllerCode = generateControllerCode(serviceInfo, filePath);
|
|
1573
|
+
return {
|
|
1574
|
+
controllerCode,
|
|
1575
|
+
transformedServiceCode
|
|
1576
|
+
};
|
|
1212
1577
|
} catch (error) {
|
|
1213
1578
|
if (error.type) {
|
|
1214
1579
|
throw error;
|
|
@@ -1231,7 +1596,7 @@ function generateControllerCode(serviceInfo, filePath) {
|
|
|
1231
1596
|
const serviceInstance = toInstanceName(serviceName);
|
|
1232
1597
|
return `${imports}
|
|
1233
1598
|
|
|
1234
|
-
@Controller("/${controllerPath}", {
|
|
1599
|
+
@Controller("/api/${controllerPath}", {
|
|
1235
1600
|
providedIn: "root",
|
|
1236
1601
|
})
|
|
1237
1602
|
export class ${controllerName} {
|
|
@@ -1276,16 +1641,40 @@ function generateImports(serviceInfo, serviceName, serviceImportPath) {
|
|
|
1276
1641
|
const hasStreamableWithParams = serviceInfo.methods.some(
|
|
1277
1642
|
(m) => m.isStreamable && m.params.length > 0
|
|
1278
1643
|
);
|
|
1279
|
-
const
|
|
1644
|
+
const hasFileUpload = serviceInfo.methods.some((m) => hasMulterFileParams(m));
|
|
1645
|
+
const hasSingleFileUpload = serviceInfo.methods.some(
|
|
1646
|
+
(m) => getFileParams(m).length === 1 && !isArrayFileParam(getFileParams(m)[0])
|
|
1647
|
+
);
|
|
1648
|
+
const hasMultipleFilesUpload = serviceInfo.methods.some(
|
|
1649
|
+
(m) => getFileParams(m).length === 1 && isArrayFileParam(getFileParams(m)[0])
|
|
1650
|
+
);
|
|
1651
|
+
const hasMultipleFileFields = serviceInfo.methods.some(
|
|
1652
|
+
(m) => getFileParams(m).length > 1
|
|
1653
|
+
);
|
|
1654
|
+
const decorators = ["Controller", "Req"];
|
|
1280
1655
|
if (hasPost) decorators.push("Post");
|
|
1281
1656
|
if (hasGet) decorators.push("Get");
|
|
1282
1657
|
if (hasPost) decorators.push("Body");
|
|
1283
1658
|
if (hasSse) decorators.push("Sse");
|
|
1284
1659
|
if (hasStreamableWithParams) decorators.push("Query");
|
|
1660
|
+
if (hasFileUpload) decorators.push("UseInterceptors");
|
|
1661
|
+
if (hasSingleFileUpload) decorators.push("UploadedFile");
|
|
1662
|
+
if (hasMultipleFilesUpload || hasMultipleFileFields)
|
|
1663
|
+
decorators.push("UploadedFiles");
|
|
1285
1664
|
let importStrings = `import { ${decorators.join(
|
|
1286
1665
|
", "
|
|
1287
1666
|
)} } from "@kithinji/orca";
|
|
1288
1667
|
`;
|
|
1668
|
+
if (hasFileUpload) {
|
|
1669
|
+
const interceptors = [];
|
|
1670
|
+
if (hasSingleFileUpload) interceptors.push("FileInterceptor");
|
|
1671
|
+
if (hasMultipleFilesUpload) interceptors.push("FilesInterceptor");
|
|
1672
|
+
if (hasMultipleFileFields) interceptors.push("FileFieldsInterceptor");
|
|
1673
|
+
importStrings += `import { ${interceptors.join(
|
|
1674
|
+
", "
|
|
1675
|
+
)} } from "@kithinji/express";
|
|
1676
|
+
`;
|
|
1677
|
+
}
|
|
1289
1678
|
importGroups.forEach((ids, source) => {
|
|
1290
1679
|
const filteredIds = Array.from(ids).filter((id) => id !== serviceName);
|
|
1291
1680
|
if (filteredIds.length > 0) {
|
|
@@ -1297,32 +1686,175 @@ function generateImports(serviceInfo, serviceName, serviceImportPath) {
|
|
|
1297
1686
|
});
|
|
1298
1687
|
return importStrings;
|
|
1299
1688
|
}
|
|
1689
|
+
function hasMulterFileParams(method) {
|
|
1690
|
+
return method.params.some((param) => {
|
|
1691
|
+
return param.type === "Array<Express.Multer.File>" || param.type === "Express.Multer.File[]" || param.type === "Express.Multer.File";
|
|
1692
|
+
});
|
|
1693
|
+
}
|
|
1694
|
+
function getFileParams(method) {
|
|
1695
|
+
return method.params.filter(
|
|
1696
|
+
(p) => p.type === "Array<Express.Multer.File>" || p.type === "Express.Multer.File[]" || p.type === "Express.Multer.File"
|
|
1697
|
+
).map((p) => ({
|
|
1698
|
+
name: p.name,
|
|
1699
|
+
type: p.type,
|
|
1700
|
+
isArray: p.type.includes("Array") || p.type.includes("[]")
|
|
1701
|
+
}));
|
|
1702
|
+
}
|
|
1703
|
+
function isArrayFileParam(param) {
|
|
1704
|
+
return param.isArray;
|
|
1705
|
+
}
|
|
1706
|
+
function getNonFileParams(method) {
|
|
1707
|
+
return method.params.filter(
|
|
1708
|
+
(p) => p.type !== "Array<Express.Multer.File>" && p.type !== "Express.Multer.File[]" && p.type !== "Express.Multer.File"
|
|
1709
|
+
);
|
|
1710
|
+
}
|
|
1300
1711
|
function generateMethods(serviceInfo) {
|
|
1301
1712
|
return serviceInfo.methods.map((m) => generateMethod(m, serviceInfo.className)).join("\n\n");
|
|
1302
1713
|
}
|
|
1303
1714
|
function generateMethod(method, serviceName) {
|
|
1304
1715
|
const hasParams = method.params.length > 0;
|
|
1305
1716
|
const serviceInstance = toInstanceName(serviceName);
|
|
1717
|
+
const fileParams = getFileParams(method);
|
|
1718
|
+
const hasFileParams = fileParams.length > 0;
|
|
1719
|
+
const liftedDecorators = method.decorators?.filter(shouldLiftDecorator).map((d) => ` ${d}`).join("\n") || "";
|
|
1306
1720
|
if (method.isStreamable) {
|
|
1721
|
+
if (hasFileParams) {
|
|
1722
|
+
throw new Error(
|
|
1723
|
+
`Method '${method.name}' cannot have file parameters for streaming endpoints`
|
|
1724
|
+
);
|
|
1725
|
+
}
|
|
1726
|
+
const reqParam2 = `@Req() request: Request`;
|
|
1307
1727
|
const queryParams = hasParams ? method.params.map((p) => `@Query('${p.name}') ${p.name}: ${p.type}`).join(", ") : "";
|
|
1728
|
+
const allParams2 = [reqParam2, queryParams].filter(Boolean).join(", ");
|
|
1308
1729
|
const body2 = generateMethodBody(method, serviceInstance, false);
|
|
1309
1730
|
const returnTypeName = method.streamType || "Observable";
|
|
1310
|
-
|
|
1311
|
-
|
|
1731
|
+
const decoratorPrefix2 = liftedDecorators ? `${liftedDecorators}
|
|
1732
|
+
` : "";
|
|
1733
|
+
return `${decoratorPrefix2} @Sse("${method.name}")
|
|
1734
|
+
${method.name}(${allParams2}): ${returnTypeName}<${method.returnType}> {
|
|
1312
1735
|
${body2}
|
|
1313
1736
|
}`;
|
|
1314
1737
|
}
|
|
1738
|
+
if (hasFileParams) {
|
|
1739
|
+
return generateFileUploadMethod(
|
|
1740
|
+
method,
|
|
1741
|
+
serviceInstance,
|
|
1742
|
+
fileParams,
|
|
1743
|
+
liftedDecorators
|
|
1744
|
+
);
|
|
1745
|
+
}
|
|
1315
1746
|
const decorator = hasParams ? "Post" : "Get";
|
|
1747
|
+
const reqParam = `@Req() request: Request`;
|
|
1316
1748
|
const bodyParam = hasParams ? `@Body() body: any` : "";
|
|
1749
|
+
const allParams = [reqParam, bodyParam].filter(Boolean).join(", ");
|
|
1317
1750
|
const body = generateMethodBody(method, serviceInstance, true);
|
|
1318
|
-
|
|
1319
|
-
|
|
1751
|
+
const decoratorPrefix = liftedDecorators ? `${liftedDecorators}
|
|
1752
|
+
` : "";
|
|
1753
|
+
return `${decoratorPrefix} @${decorator}("${method.name}")
|
|
1754
|
+
async ${method.name}(${allParams}): Promise<${method.returnType}> {
|
|
1320
1755
|
${body}
|
|
1321
1756
|
}`;
|
|
1322
1757
|
}
|
|
1758
|
+
function generateFileUploadMethod(method, serviceInstance, fileParams, liftedDecorators) {
|
|
1759
|
+
const nonFileParams = getNonFileParams(method);
|
|
1760
|
+
const interceptorDecorator = generateInterceptorDecorator(fileParams);
|
|
1761
|
+
const methodParams = generateFileMethodParams(fileParams, nonFileParams);
|
|
1762
|
+
const allParams = [`@Req() request: Request`, methodParams].filter(Boolean).join(", ");
|
|
1763
|
+
const body = generateFileMethodBody(
|
|
1764
|
+
method,
|
|
1765
|
+
serviceInstance,
|
|
1766
|
+
fileParams,
|
|
1767
|
+
nonFileParams
|
|
1768
|
+
);
|
|
1769
|
+
const decoratorPrefix = liftedDecorators ? `${liftedDecorators}
|
|
1770
|
+
` : "";
|
|
1771
|
+
return `${decoratorPrefix}${interceptorDecorator} @Post("${method.name}")
|
|
1772
|
+
async ${method.name}(${allParams}): Promise<${method.returnType}> {
|
|
1773
|
+
${body}
|
|
1774
|
+
}`;
|
|
1775
|
+
}
|
|
1776
|
+
function generateInterceptorDecorator(fileParams) {
|
|
1777
|
+
if (fileParams.length === 1) {
|
|
1778
|
+
const param = fileParams[0];
|
|
1779
|
+
if (param.isArray) {
|
|
1780
|
+
return ` @UseInterceptors(FilesInterceptor("${param.name}"))
|
|
1781
|
+
`;
|
|
1782
|
+
} else {
|
|
1783
|
+
return ` @UseInterceptors(FileInterceptor("${param.name}"))
|
|
1784
|
+
`;
|
|
1785
|
+
}
|
|
1786
|
+
} else {
|
|
1787
|
+
const fields = fileParams.map((p) => `{ name: "${p.name}" }`).join(", ");
|
|
1788
|
+
return ` @UseInterceptors(FileFieldsInterceptor([${fields}]))
|
|
1789
|
+
`;
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
function generateFileMethodParams(fileParams, nonFileParams) {
|
|
1793
|
+
const params = [];
|
|
1794
|
+
if (fileParams.length === 1) {
|
|
1795
|
+
const param = fileParams[0];
|
|
1796
|
+
const decorator = param.isArray ? "@UploadedFiles()" : "@UploadedFile()";
|
|
1797
|
+
params.push(`${decorator} ${param.name}: ${param.type}`);
|
|
1798
|
+
} else if (fileParams.length > 1) {
|
|
1799
|
+
params.push(
|
|
1800
|
+
`@UploadedFiles() files: Record<string, Express.Multer.File[]>`
|
|
1801
|
+
);
|
|
1802
|
+
}
|
|
1803
|
+
if (nonFileParams.length > 0) {
|
|
1804
|
+
params.push(`@Body() body: any`);
|
|
1805
|
+
}
|
|
1806
|
+
return params.join(", ");
|
|
1807
|
+
}
|
|
1808
|
+
function generateFileMethodBody(method, serviceInstance, fileParams, nonFileParams) {
|
|
1809
|
+
const lines = [];
|
|
1810
|
+
lines.push(` this.${serviceInstance}.request = request;`);
|
|
1811
|
+
if (fileParams.length > 1) {
|
|
1812
|
+
fileParams.forEach((p) => {
|
|
1813
|
+
if (p.isArray) {
|
|
1814
|
+
lines.push(` const ${p.name} = files["${p.name}"] || [];`);
|
|
1815
|
+
} else {
|
|
1816
|
+
lines.push(
|
|
1817
|
+
` const ${p.name} = files["${p.name}"]?.[0] || files["${p.name}"];`
|
|
1818
|
+
);
|
|
1819
|
+
}
|
|
1820
|
+
});
|
|
1821
|
+
}
|
|
1822
|
+
if (nonFileParams.length > 0) {
|
|
1823
|
+
const nonFileSchemas = method.paramSchemas.filter((_, i) => {
|
|
1824
|
+
const param = method.params[i];
|
|
1825
|
+
return !fileParams.some((fp) => fp.name === param.name);
|
|
1826
|
+
});
|
|
1827
|
+
if (nonFileSchemas.length > 0 && nonFileSchemas.some((s) => s)) {
|
|
1828
|
+
lines.push(
|
|
1829
|
+
` const b = typeof body === 'object' && body !== null ? body : {};`
|
|
1830
|
+
);
|
|
1831
|
+
nonFileParams.forEach((p) => {
|
|
1832
|
+
const schemaIndex = method.params.findIndex((mp) => mp.name === p.name);
|
|
1833
|
+
if (method.paramSchemas[schemaIndex]) {
|
|
1834
|
+
lines.push(
|
|
1835
|
+
` const ${p.name} = ${method.paramSchemas[schemaIndex]}.parse(b.${p.name});`
|
|
1836
|
+
);
|
|
1837
|
+
}
|
|
1838
|
+
});
|
|
1839
|
+
} else {
|
|
1840
|
+
const paramNames = nonFileParams.map((p) => p.name).join(", ");
|
|
1841
|
+
lines.push(` const { ${paramNames} } = body || {};`);
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
const callArgs = method.params.map((p) => p.name).join(", ");
|
|
1845
|
+
const serviceCall = `${serviceInstance}.${method.name}(${callArgs})`;
|
|
1846
|
+
if (method.returnSchema) {
|
|
1847
|
+
lines.push(` const res = await this.${serviceCall};`);
|
|
1848
|
+
lines.push(` return ${method.returnSchema}.parse(res);`);
|
|
1849
|
+
} else {
|
|
1850
|
+
lines.push(` return this.${serviceCall};`);
|
|
1851
|
+
}
|
|
1852
|
+
return lines.join("\n");
|
|
1853
|
+
}
|
|
1323
1854
|
function generateMethodBody(method, serviceInstance, isAsync) {
|
|
1324
1855
|
const lines = [];
|
|
1325
1856
|
const hasParams = method.params.length > 0;
|
|
1857
|
+
lines.push(` this.${serviceInstance}.request = request;`);
|
|
1326
1858
|
if (hasParams && method.isStreamable && method.paramSchemas.length > 0) {
|
|
1327
1859
|
method.params.forEach((p, i) => {
|
|
1328
1860
|
lines.push(
|
|
@@ -1366,7 +1898,7 @@ function generateMethodBody(method, serviceInstance, isAsync) {
|
|
|
1366
1898
|
// src/plugins/generators/tsx_server_stub.ts
|
|
1367
1899
|
import * as path5 from "path";
|
|
1368
1900
|
import { createHash } from "crypto";
|
|
1369
|
-
import { parseSync as parseSync2, printSync } from "@swc/core";
|
|
1901
|
+
import { parseSync as parseSync2, printSync as printSync2 } from "@swc/core";
|
|
1370
1902
|
function generateServerStub(filePath, code) {
|
|
1371
1903
|
const hash = createHash("md5").update(filePath).digest("hex").slice(0, 8);
|
|
1372
1904
|
const relativeFromSrc = filePath.split("/src/")[1];
|
|
@@ -1412,7 +1944,7 @@ function generateServerStub(filePath, code) {
|
|
|
1412
1944
|
preservedNodes.push(item);
|
|
1413
1945
|
}
|
|
1414
1946
|
}
|
|
1415
|
-
const preservedCode = preservedNodes.length > 0 ?
|
|
1947
|
+
const preservedCode = preservedNodes.length > 0 ? printSync2({
|
|
1416
1948
|
type: "Module",
|
|
1417
1949
|
span: ast.span,
|
|
1418
1950
|
body: preservedNodes,
|
|
@@ -1445,7 +1977,7 @@ function extractClassStub(classDecl) {
|
|
|
1445
1977
|
const constructorParams = [];
|
|
1446
1978
|
if (classDecl.decorators) {
|
|
1447
1979
|
for (const dec of classDecl.decorators) {
|
|
1448
|
-
const str =
|
|
1980
|
+
const str = stringifyDecorator2(dec);
|
|
1449
1981
|
if (str) decorators.push(str);
|
|
1450
1982
|
}
|
|
1451
1983
|
}
|
|
@@ -1468,8 +2000,8 @@ function extractClassStub(classDecl) {
|
|
|
1468
2000
|
constructorParams
|
|
1469
2001
|
};
|
|
1470
2002
|
}
|
|
1471
|
-
function
|
|
1472
|
-
const exprCode =
|
|
2003
|
+
function stringifyDecorator2(decorator) {
|
|
2004
|
+
const exprCode = printSync2({
|
|
1473
2005
|
type: "Module",
|
|
1474
2006
|
span: { start: 0, end: 0, ctxt: 0 },
|
|
1475
2007
|
body: [
|
|
@@ -1504,7 +2036,7 @@ function stringifyParam(param) {
|
|
|
1504
2036
|
let decorators = [];
|
|
1505
2037
|
if (param.decorators) {
|
|
1506
2038
|
for (const d of param.decorators) {
|
|
1507
|
-
const str =
|
|
2039
|
+
const str = stringifyDecorator2(d);
|
|
1508
2040
|
if (str) decorators.push(str);
|
|
1509
2041
|
}
|
|
1510
2042
|
}
|
|
@@ -1607,9 +2139,6 @@ var NodeTypeGuards = class {
|
|
|
1607
2139
|
isSignalMember(expr) {
|
|
1608
2140
|
return this.t.isMemberExpression(expr) && this.t.isIdentifier(expr.property, { name: "value" });
|
|
1609
2141
|
}
|
|
1610
|
-
isBehaviorSubjectMember(expr) {
|
|
1611
|
-
return this.t.isMemberExpression(expr) && this.t.isIdentifier(expr.property, { name: "$value" });
|
|
1612
|
-
}
|
|
1613
2142
|
};
|
|
1614
2143
|
var ASTUtilities = class {
|
|
1615
2144
|
constructor(t, guards) {
|
|
@@ -1617,7 +2146,7 @@ var ASTUtilities = class {
|
|
|
1617
2146
|
this.guards = guards;
|
|
1618
2147
|
}
|
|
1619
2148
|
getObject(expr) {
|
|
1620
|
-
if (this.guards.isSignalMember(expr)
|
|
2149
|
+
if (this.guards.isSignalMember(expr)) {
|
|
1621
2150
|
return expr.object;
|
|
1622
2151
|
}
|
|
1623
2152
|
return expr;
|
|
@@ -1655,24 +2184,12 @@ var ASTUtilities = class {
|
|
|
1655
2184
|
}
|
|
1656
2185
|
return expr;
|
|
1657
2186
|
}
|
|
1658
|
-
insertBeforeReturn(body, statements) {
|
|
1659
|
-
const returnIndex = body.findIndex(
|
|
1660
|
-
(stmt) => this.t.isReturnStatement(stmt)
|
|
1661
|
-
);
|
|
1662
|
-
if (returnIndex !== -1) {
|
|
1663
|
-
body.splice(returnIndex, 0, ...statements);
|
|
1664
|
-
} else {
|
|
1665
|
-
body.push(...statements);
|
|
1666
|
-
}
|
|
1667
|
-
}
|
|
1668
2187
|
addEffectCleanup(scope, effectCall) {
|
|
1669
2188
|
const cleanupId = scope.generateUidIdentifier("cleanup");
|
|
1670
2189
|
return [
|
|
1671
|
-
// const _cleanup1 = $effect(...)
|
|
1672
2190
|
this.t.variableDeclaration("const", [
|
|
1673
2191
|
this.t.variableDeclarator(cleanupId, effectCall)
|
|
1674
2192
|
]),
|
|
1675
|
-
// self.__cleanup = [...(self.__cleanup || []), _cleanup1]
|
|
1676
2193
|
this.t.expressionStatement(
|
|
1677
2194
|
this.t.assignmentExpression(
|
|
1678
2195
|
"=",
|
|
@@ -1785,81 +2302,12 @@ var JSXUtilities = class {
|
|
|
1785
2302
|
return svgTags.has(tag);
|
|
1786
2303
|
}
|
|
1787
2304
|
};
|
|
1788
|
-
var ObservableManager = class {
|
|
1789
|
-
constructor(t, guards) {
|
|
1790
|
-
this.t = t;
|
|
1791
|
-
this.guards = guards;
|
|
1792
|
-
}
|
|
1793
|
-
getObservableKey(expr) {
|
|
1794
|
-
return this.stringifyNode(expr);
|
|
1795
|
-
}
|
|
1796
|
-
stringifyNode(node) {
|
|
1797
|
-
if (!node) return "";
|
|
1798
|
-
if (this.t.isThisExpression(node)) return "this";
|
|
1799
|
-
if (this.t.isIdentifier(node)) return node.name;
|
|
1800
|
-
if (this.t.isMemberExpression(node)) {
|
|
1801
|
-
const obj = this.stringifyNode(node.object);
|
|
1802
|
-
const prop = node.computed ? `[${this.stringifyNode(node.property)}]` : `.${node.property.name}`;
|
|
1803
|
-
return obj + prop;
|
|
1804
|
-
}
|
|
1805
|
-
if (this.t.isCallExpression(node)) {
|
|
1806
|
-
const callee = this.stringifyNode(node.callee);
|
|
1807
|
-
const args = node.arguments.map((arg) => this.stringifyNode(arg)).join(",");
|
|
1808
|
-
return `${callee}(${args})`;
|
|
1809
|
-
}
|
|
1810
|
-
if (this.t.isStringLiteral(node)) return `"${node.value}"`;
|
|
1811
|
-
if (this.t.isNumericLiteral(node)) return String(node.value);
|
|
1812
|
-
return node.type + JSON.stringify(node.name || node.value || "");
|
|
1813
|
-
}
|
|
1814
|
-
collectObservables(node, observables, astUtils) {
|
|
1815
|
-
this.walkNode(node, (n) => {
|
|
1816
|
-
if (this.guards.isBehaviorSubjectMember(n)) {
|
|
1817
|
-
const observable = astUtils.replaceThisWithSelf(
|
|
1818
|
-
n.object
|
|
1819
|
-
);
|
|
1820
|
-
const key = this.getObservableKey(observable);
|
|
1821
|
-
if (!observables.has(key)) {
|
|
1822
|
-
observables.set(key, observable);
|
|
1823
|
-
}
|
|
1824
|
-
}
|
|
1825
|
-
});
|
|
1826
|
-
}
|
|
1827
|
-
replaceObservablesWithSignals(node, observableSignals, astUtils) {
|
|
1828
|
-
const cloned = this.t.cloneNode(node, true);
|
|
1829
|
-
this.walkNode(cloned, (n) => {
|
|
1830
|
-
if (this.guards.isBehaviorSubjectMember(n)) {
|
|
1831
|
-
const observable = astUtils.replaceThisWithSelf(n.object);
|
|
1832
|
-
const key = this.getObservableKey(observable);
|
|
1833
|
-
const signalId = observableSignals.get(key);
|
|
1834
|
-
if (signalId) {
|
|
1835
|
-
n.object = signalId;
|
|
1836
|
-
n.property = this.t.identifier("value");
|
|
1837
|
-
}
|
|
1838
|
-
}
|
|
1839
|
-
});
|
|
1840
|
-
return cloned;
|
|
1841
|
-
}
|
|
1842
|
-
walkNode(node, callback) {
|
|
1843
|
-
if (!node || typeof node !== "object") return;
|
|
1844
|
-
callback(node);
|
|
1845
|
-
for (const key in node) {
|
|
1846
|
-
if (["loc", "start", "end", "extra"].includes(key)) continue;
|
|
1847
|
-
const value = node[key];
|
|
1848
|
-
if (Array.isArray(value)) {
|
|
1849
|
-
value.forEach((item) => this.walkNode(item, callback));
|
|
1850
|
-
} else if (value && typeof value === "object") {
|
|
1851
|
-
this.walkNode(value, callback);
|
|
1852
|
-
}
|
|
1853
|
-
}
|
|
1854
|
-
}
|
|
1855
|
-
};
|
|
1856
2305
|
var ElementTransformer = class {
|
|
1857
|
-
constructor(t, guards, astUtils, jsxUtils
|
|
2306
|
+
constructor(t, guards, astUtils, jsxUtils) {
|
|
1858
2307
|
this.t = t;
|
|
1859
2308
|
this.guards = guards;
|
|
1860
2309
|
this.astUtils = astUtils;
|
|
1861
2310
|
this.jsxUtils = jsxUtils;
|
|
1862
|
-
this.observableManager = observableManager;
|
|
1863
2311
|
}
|
|
1864
2312
|
transformElement(path17, scope, context2) {
|
|
1865
2313
|
if (this.t.isJSXFragment(path17.node)) {
|
|
@@ -2030,18 +2478,10 @@ var ElementTransformer = class {
|
|
|
2030
2478
|
processComponentAttributes(attributes, props, context2) {
|
|
2031
2479
|
for (const attr of attributes) {
|
|
2032
2480
|
if (this.t.isJSXSpreadAttribute(attr)) {
|
|
2033
|
-
this.observableManager.collectObservables(
|
|
2034
|
-
attr.argument,
|
|
2035
|
-
context2.observables,
|
|
2036
|
-
this.astUtils
|
|
2037
|
-
);
|
|
2038
|
-
const replaced = this.observableManager.replaceObservablesWithSignals(
|
|
2039
|
-
attr.argument,
|
|
2040
|
-
context2.observableSignals,
|
|
2041
|
-
this.astUtils
|
|
2042
|
-
);
|
|
2043
2481
|
props.push(
|
|
2044
|
-
this.t.spreadElement(
|
|
2482
|
+
this.t.spreadElement(
|
|
2483
|
+
this.astUtils.replaceThisWithSelf(attr.argument)
|
|
2484
|
+
)
|
|
2045
2485
|
);
|
|
2046
2486
|
continue;
|
|
2047
2487
|
}
|
|
@@ -2050,39 +2490,22 @@ var ElementTransformer = class {
|
|
|
2050
2490
|
props.push(this.t.objectProperty(this.t.identifier(key), attr.value));
|
|
2051
2491
|
} else if (this.t.isJSXExpressionContainer(attr.value)) {
|
|
2052
2492
|
const expr = attr.value.expression;
|
|
2053
|
-
this.
|
|
2054
|
-
expr,
|
|
2055
|
-
context2.observables,
|
|
2056
|
-
this.astUtils
|
|
2057
|
-
);
|
|
2058
|
-
if (this.guards.isSignalMember(expr) || this.guards.isBehaviorSubjectMember(expr)) {
|
|
2059
|
-
const replaced = this.observableManager.replaceObservablesWithSignals(
|
|
2060
|
-
expr,
|
|
2061
|
-
context2.observableSignals,
|
|
2062
|
-
this.astUtils
|
|
2063
|
-
);
|
|
2493
|
+
if (this.guards.isSignalMember(expr)) {
|
|
2064
2494
|
props.push(
|
|
2065
2495
|
this.t.objectMethod(
|
|
2066
2496
|
"get",
|
|
2067
2497
|
this.t.identifier(key),
|
|
2068
2498
|
[],
|
|
2069
2499
|
this.t.blockStatement([
|
|
2070
|
-
this.t.returnStatement(
|
|
2071
|
-
this.astUtils.replaceThisWithSelf(replaced)
|
|
2072
|
-
)
|
|
2500
|
+
this.t.returnStatement(this.astUtils.replaceThisWithSelf(expr))
|
|
2073
2501
|
])
|
|
2074
2502
|
)
|
|
2075
2503
|
);
|
|
2076
2504
|
} else {
|
|
2077
|
-
const replaced = this.observableManager.replaceObservablesWithSignals(
|
|
2078
|
-
expr,
|
|
2079
|
-
context2.observableSignals,
|
|
2080
|
-
this.astUtils
|
|
2081
|
-
);
|
|
2082
2505
|
props.push(
|
|
2083
2506
|
this.t.objectProperty(
|
|
2084
2507
|
this.t.identifier(key),
|
|
2085
|
-
this.astUtils.replaceThisWithSelf(
|
|
2508
|
+
this.astUtils.replaceThisWithSelf(expr)
|
|
2086
2509
|
)
|
|
2087
2510
|
);
|
|
2088
2511
|
}
|
|
@@ -2105,22 +2528,12 @@ var ElementTransformer = class {
|
|
|
2105
2528
|
let hrefValue = null;
|
|
2106
2529
|
for (const attr of attributes) {
|
|
2107
2530
|
if (this.t.isJSXSpreadAttribute(attr)) {
|
|
2108
|
-
this.observableManager.collectObservables(
|
|
2109
|
-
attr.argument,
|
|
2110
|
-
context2.observables,
|
|
2111
|
-
this.astUtils
|
|
2112
|
-
);
|
|
2113
|
-
const replaced = this.observableManager.replaceObservablesWithSignals(
|
|
2114
|
-
attr.argument,
|
|
2115
|
-
context2.observableSignals,
|
|
2116
|
-
this.astUtils
|
|
2117
|
-
);
|
|
2118
2531
|
const effectCall = this.t.callExpression(this.t.identifier("$effect"), [
|
|
2119
2532
|
this.t.arrowFunctionExpression(
|
|
2120
2533
|
[],
|
|
2121
2534
|
this.t.callExpression(this.t.identifier("$spread"), [
|
|
2122
2535
|
elId,
|
|
2123
|
-
this.astUtils.replaceThisWithSelf(
|
|
2536
|
+
this.astUtils.replaceThisWithSelf(attr.argument)
|
|
2124
2537
|
])
|
|
2125
2538
|
)
|
|
2126
2539
|
]);
|
|
@@ -2135,34 +2548,18 @@ var ElementTransformer = class {
|
|
|
2135
2548
|
if (key === "ref") {
|
|
2136
2549
|
hasRef = true;
|
|
2137
2550
|
if (this.t.isJSXExpressionContainer(attr.value)) {
|
|
2138
|
-
this.
|
|
2139
|
-
attr.value.expression
|
|
2140
|
-
context2.observables,
|
|
2141
|
-
this.astUtils
|
|
2142
|
-
);
|
|
2143
|
-
const replaced = this.observableManager.replaceObservablesWithSignals(
|
|
2144
|
-
attr.value.expression,
|
|
2145
|
-
context2.observableSignals,
|
|
2146
|
-
this.astUtils
|
|
2551
|
+
refValue = this.astUtils.replaceThisWithSelf(
|
|
2552
|
+
attr.value.expression
|
|
2147
2553
|
);
|
|
2148
|
-
refValue = this.astUtils.replaceThisWithSelf(replaced);
|
|
2149
2554
|
}
|
|
2150
2555
|
continue;
|
|
2151
2556
|
}
|
|
2152
2557
|
if (key === "dangerouslySetInnerHTML") {
|
|
2153
2558
|
hasDangerousHTML = true;
|
|
2154
2559
|
if (this.t.isJSXExpressionContainer(attr.value)) {
|
|
2155
|
-
this.
|
|
2156
|
-
attr.value.expression
|
|
2157
|
-
context2.observables,
|
|
2158
|
-
this.astUtils
|
|
2560
|
+
dangerousHTMLValue = this.astUtils.replaceThisWithSelf(
|
|
2561
|
+
attr.value.expression
|
|
2159
2562
|
);
|
|
2160
|
-
const replaced = this.observableManager.replaceObservablesWithSignals(
|
|
2161
|
-
attr.value.expression,
|
|
2162
|
-
context2.observableSignals,
|
|
2163
|
-
this.astUtils
|
|
2164
|
-
);
|
|
2165
|
-
dangerousHTMLValue = this.astUtils.replaceThisWithSelf(replaced);
|
|
2166
2563
|
}
|
|
2167
2564
|
continue;
|
|
2168
2565
|
}
|
|
@@ -2180,9 +2577,9 @@ var ElementTransformer = class {
|
|
|
2180
2577
|
this.processStyleAttribute(attr, elId, statements, scope, context2);
|
|
2181
2578
|
continue;
|
|
2182
2579
|
}
|
|
2183
|
-
this.processRegularAttribute(key, attr, elId, statements, context2);
|
|
2580
|
+
this.processRegularAttribute(key, attr, elId, statements, scope, context2);
|
|
2184
2581
|
}
|
|
2185
|
-
if (tag === "a" && !hasClickHandler
|
|
2582
|
+
if (tag === "a" && !hasClickHandler) {
|
|
2186
2583
|
statements.push(
|
|
2187
2584
|
this.t.expressionStatement(
|
|
2188
2585
|
this.t.callExpression(
|
|
@@ -2193,13 +2590,25 @@ var ElementTransformer = class {
|
|
|
2193
2590
|
[
|
|
2194
2591
|
this.t.stringLiteral("click"),
|
|
2195
2592
|
this.t.arrowFunctionExpression(
|
|
2196
|
-
[this.t.identifier("
|
|
2593
|
+
[this.t.identifier("e")],
|
|
2197
2594
|
this.t.callExpression(
|
|
2198
2595
|
this.t.memberExpression(
|
|
2199
2596
|
this.t.identifier("Orca"),
|
|
2200
2597
|
this.t.identifier("navigate")
|
|
2201
2598
|
),
|
|
2202
|
-
[
|
|
2599
|
+
[
|
|
2600
|
+
this.t.identifier("e"),
|
|
2601
|
+
this.t.callExpression(
|
|
2602
|
+
this.t.memberExpression(
|
|
2603
|
+
this.t.memberExpression(
|
|
2604
|
+
this.t.identifier("e"),
|
|
2605
|
+
this.t.identifier("currentTarget")
|
|
2606
|
+
),
|
|
2607
|
+
this.t.identifier("getAttribute")
|
|
2608
|
+
),
|
|
2609
|
+
[this.t.stringLiteral("href")]
|
|
2610
|
+
)
|
|
2611
|
+
]
|
|
2203
2612
|
)
|
|
2204
2613
|
)
|
|
2205
2614
|
]
|
|
@@ -2224,17 +2633,9 @@ var ElementTransformer = class {
|
|
|
2224
2633
|
const eventName = key.slice(2).toLowerCase();
|
|
2225
2634
|
let handler = this.t.nullLiteral();
|
|
2226
2635
|
if (this.t.isJSXExpressionContainer(attr.value)) {
|
|
2227
|
-
this.
|
|
2228
|
-
attr.value.expression
|
|
2229
|
-
context2.observables,
|
|
2230
|
-
this.astUtils
|
|
2231
|
-
);
|
|
2232
|
-
const replaced = this.observableManager.replaceObservablesWithSignals(
|
|
2233
|
-
attr.value.expression,
|
|
2234
|
-
context2.observableSignals,
|
|
2235
|
-
this.astUtils
|
|
2636
|
+
handler = this.astUtils.replaceThisWithSelf(
|
|
2637
|
+
attr.value.expression
|
|
2236
2638
|
);
|
|
2237
|
-
handler = this.astUtils.replaceThisWithSelf(replaced);
|
|
2238
2639
|
}
|
|
2239
2640
|
statements.push(
|
|
2240
2641
|
this.t.expressionStatement(
|
|
@@ -2247,56 +2648,63 @@ var ElementTransformer = class {
|
|
|
2247
2648
|
}
|
|
2248
2649
|
processStyleAttribute(attr, elId, statements, scope, context2) {
|
|
2249
2650
|
if (!this.t.isJSXExpressionContainer(attr.value)) return;
|
|
2250
|
-
this.observableManager.collectObservables(
|
|
2251
|
-
attr.value.expression,
|
|
2252
|
-
context2.observables,
|
|
2253
|
-
this.astUtils
|
|
2254
|
-
);
|
|
2255
|
-
const replaced = this.observableManager.replaceObservablesWithSignals(
|
|
2256
|
-
attr.value.expression,
|
|
2257
|
-
context2.observableSignals,
|
|
2258
|
-
this.astUtils
|
|
2259
|
-
);
|
|
2260
2651
|
const effectCall = this.t.callExpression(this.t.identifier("$effect"), [
|
|
2261
2652
|
this.t.arrowFunctionExpression(
|
|
2262
2653
|
[],
|
|
2263
2654
|
this.t.callExpression(this.t.identifier("$style"), [
|
|
2264
2655
|
elId,
|
|
2265
|
-
this.astUtils.replaceThisWithSelf(
|
|
2656
|
+
this.astUtils.replaceThisWithSelf(
|
|
2657
|
+
attr.value.expression
|
|
2658
|
+
)
|
|
2266
2659
|
])
|
|
2267
2660
|
)
|
|
2268
2661
|
]);
|
|
2269
2662
|
const cleanupStatements = this.astUtils.addEffectCleanup(scope, effectCall);
|
|
2270
2663
|
statements.push(...cleanupStatements);
|
|
2271
2664
|
}
|
|
2272
|
-
processRegularAttribute(key, attr, elId, statements, context2) {
|
|
2665
|
+
processRegularAttribute(key, attr, elId, statements, scope, context2) {
|
|
2273
2666
|
const attrName = key === "className" ? "class" : key;
|
|
2274
2667
|
let value;
|
|
2668
|
+
let isReactive = false;
|
|
2275
2669
|
if (this.t.isStringLiteral(attr.value)) {
|
|
2276
2670
|
value = attr.value;
|
|
2277
2671
|
} else if (this.t.isJSXExpressionContainer(attr.value)) {
|
|
2278
|
-
this.
|
|
2279
|
-
attr.value.expression
|
|
2280
|
-
context2.observables,
|
|
2281
|
-
this.astUtils
|
|
2672
|
+
const expr = this.astUtils.replaceThisWithSelf(
|
|
2673
|
+
attr.value.expression
|
|
2282
2674
|
);
|
|
2283
|
-
|
|
2284
|
-
attr.value.expression
|
|
2285
|
-
context2.observableSignals,
|
|
2286
|
-
this.astUtils
|
|
2675
|
+
isReactive = this.guards.isSignalMember(
|
|
2676
|
+
attr.value.expression
|
|
2287
2677
|
);
|
|
2288
|
-
value =
|
|
2678
|
+
value = expr;
|
|
2289
2679
|
} else {
|
|
2290
2680
|
value = this.t.booleanLiteral(true);
|
|
2291
2681
|
}
|
|
2292
|
-
|
|
2293
|
-
this.t.
|
|
2294
|
-
this.t.
|
|
2295
|
-
|
|
2296
|
-
|
|
2682
|
+
if (isReactive) {
|
|
2683
|
+
const effectCall = this.t.callExpression(this.t.identifier("$effect"), [
|
|
2684
|
+
this.t.arrowFunctionExpression(
|
|
2685
|
+
[],
|
|
2686
|
+
this.t.assignmentExpression(
|
|
2687
|
+
"=",
|
|
2688
|
+
this.t.memberExpression(elId, this.t.identifier(attrName)),
|
|
2689
|
+
value
|
|
2690
|
+
)
|
|
2297
2691
|
)
|
|
2298
|
-
)
|
|
2299
|
-
|
|
2692
|
+
]);
|
|
2693
|
+
const cleanupStatements = this.astUtils.addEffectCleanup(
|
|
2694
|
+
scope,
|
|
2695
|
+
effectCall
|
|
2696
|
+
);
|
|
2697
|
+
statements.push(...cleanupStatements);
|
|
2698
|
+
} else {
|
|
2699
|
+
statements.push(
|
|
2700
|
+
this.t.expressionStatement(
|
|
2701
|
+
this.t.callExpression(
|
|
2702
|
+
this.t.memberExpression(elId, this.t.identifier("setAttribute")),
|
|
2703
|
+
[this.t.stringLiteral(attrName), value]
|
|
2704
|
+
)
|
|
2705
|
+
)
|
|
2706
|
+
);
|
|
2707
|
+
}
|
|
2300
2708
|
}
|
|
2301
2709
|
processChildren(children, childExpressions, statements, scope, context2) {
|
|
2302
2710
|
for (const child of children) {
|
|
@@ -2306,17 +2714,9 @@ var ElementTransformer = class {
|
|
|
2306
2714
|
} else if (this.t.isJSXExpressionContainer(child)) {
|
|
2307
2715
|
const expr = child.expression;
|
|
2308
2716
|
if (!this.t.isJSXEmptyExpression(expr)) {
|
|
2309
|
-
|
|
2310
|
-
expr
|
|
2311
|
-
context2.observables,
|
|
2312
|
-
this.astUtils
|
|
2717
|
+
childExpressions.push(
|
|
2718
|
+
this.astUtils.replaceThisWithSelf(expr)
|
|
2313
2719
|
);
|
|
2314
|
-
const replaced = this.observableManager.replaceObservablesWithSignals(
|
|
2315
|
-
expr,
|
|
2316
|
-
context2.observableSignals,
|
|
2317
|
-
this.astUtils
|
|
2318
|
-
);
|
|
2319
|
-
childExpressions.push(this.astUtils.replaceThisWithSelf(replaced));
|
|
2320
2720
|
}
|
|
2321
2721
|
} else if (this.t.isJSXElement(child) || this.t.isJSXFragment(child)) {
|
|
2322
2722
|
const childEl = this.transformElement({ node: child }, scope, context2);
|
|
@@ -2341,42 +2741,43 @@ var ElementTransformer = class {
|
|
|
2341
2741
|
} else if (this.t.isJSXExpressionContainer(child)) {
|
|
2342
2742
|
const expr = child.expression;
|
|
2343
2743
|
if (this.t.isJSXEmptyExpression(expr)) continue;
|
|
2344
|
-
this.
|
|
2345
|
-
|
|
2346
|
-
context2.observables,
|
|
2347
|
-
this.astUtils
|
|
2348
|
-
);
|
|
2349
|
-
let insertedValue;
|
|
2350
|
-
if (this.guards.isSignalMember(expr)) {
|
|
2351
|
-
insertedValue = this.astUtils.getObject(
|
|
2352
|
-
expr
|
|
2353
|
-
);
|
|
2354
|
-
} else if (this.guards.isBehaviorSubjectMember(expr)) {
|
|
2355
|
-
const replaced = this.observableManager.replaceObservablesWithSignals(
|
|
2744
|
+
if (this.t.isLogicalExpression(expr, { operator: "&&" })) {
|
|
2745
|
+
this.processConditionalAnd(
|
|
2356
2746
|
expr,
|
|
2357
|
-
|
|
2358
|
-
|
|
2747
|
+
parentId,
|
|
2748
|
+
statements,
|
|
2749
|
+
scope,
|
|
2750
|
+
context2
|
|
2359
2751
|
);
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
const replaced = this.observableManager.replaceObservablesWithSignals(
|
|
2752
|
+
} else if (this.t.isConditionalExpression(expr)) {
|
|
2753
|
+
this.processConditionalTernary(
|
|
2363
2754
|
expr,
|
|
2364
|
-
|
|
2365
|
-
|
|
2755
|
+
parentId,
|
|
2756
|
+
statements,
|
|
2757
|
+
scope,
|
|
2758
|
+
context2
|
|
2366
2759
|
);
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2760
|
+
} else {
|
|
2761
|
+
let insertedValue;
|
|
2762
|
+
if (this.guards.isSignalMember(expr)) {
|
|
2763
|
+
insertedValue = this.astUtils.getObject(
|
|
2764
|
+
expr
|
|
2765
|
+
);
|
|
2766
|
+
} else {
|
|
2767
|
+
insertedValue = this.t.arrowFunctionExpression(
|
|
2768
|
+
[],
|
|
2769
|
+
this.astUtils.replaceThisWithSelf(expr)
|
|
2770
|
+
);
|
|
2771
|
+
}
|
|
2772
|
+
statements.push(
|
|
2773
|
+
this.t.expressionStatement(
|
|
2774
|
+
this.t.callExpression(this.t.identifier("$insert"), [
|
|
2775
|
+
parentId,
|
|
2776
|
+
insertedValue
|
|
2777
|
+
])
|
|
2778
|
+
)
|
|
2370
2779
|
);
|
|
2371
2780
|
}
|
|
2372
|
-
statements.push(
|
|
2373
|
-
this.t.expressionStatement(
|
|
2374
|
-
this.t.callExpression(this.t.identifier("$insert"), [
|
|
2375
|
-
parentId,
|
|
2376
|
-
insertedValue
|
|
2377
|
-
])
|
|
2378
|
-
)
|
|
2379
|
-
);
|
|
2380
2781
|
} else if (this.t.isJSXElement(child) || this.t.isJSXFragment(child)) {
|
|
2381
2782
|
const childEl = this.transformElement({ node: child }, scope, context2);
|
|
2382
2783
|
statements.push(...childEl.statements);
|
|
@@ -2391,18 +2792,137 @@ var ElementTransformer = class {
|
|
|
2391
2792
|
}
|
|
2392
2793
|
}
|
|
2393
2794
|
}
|
|
2795
|
+
processConditionalAnd(expr, parentId, statements, scope, context2) {
|
|
2796
|
+
const condition = expr.left;
|
|
2797
|
+
const consequent = expr.right;
|
|
2798
|
+
const computedId = scope.generateUidIdentifier("c");
|
|
2799
|
+
const branchExpr = this.transformExpressionToBranch(
|
|
2800
|
+
consequent,
|
|
2801
|
+
scope,
|
|
2802
|
+
context2
|
|
2803
|
+
);
|
|
2804
|
+
statements.push(
|
|
2805
|
+
this.t.expressionStatement(
|
|
2806
|
+
this.t.callExpression(this.t.identifier("$insert"), [
|
|
2807
|
+
parentId,
|
|
2808
|
+
this.t.callExpression(
|
|
2809
|
+
this.t.arrowFunctionExpression(
|
|
2810
|
+
[],
|
|
2811
|
+
this.t.blockStatement([
|
|
2812
|
+
this.t.variableDeclaration("var", [
|
|
2813
|
+
this.t.variableDeclarator(
|
|
2814
|
+
computedId,
|
|
2815
|
+
this.t.callExpression(this.t.identifier("$computed"), [
|
|
2816
|
+
this.t.arrowFunctionExpression(
|
|
2817
|
+
[],
|
|
2818
|
+
this.astUtils.replaceThisWithSelf(condition)
|
|
2819
|
+
)
|
|
2820
|
+
])
|
|
2821
|
+
)
|
|
2822
|
+
]),
|
|
2823
|
+
this.t.returnStatement(
|
|
2824
|
+
this.t.arrowFunctionExpression(
|
|
2825
|
+
[],
|
|
2826
|
+
this.t.logicalExpression(
|
|
2827
|
+
"&&",
|
|
2828
|
+
this.t.memberExpression(
|
|
2829
|
+
computedId,
|
|
2830
|
+
this.t.identifier("value")
|
|
2831
|
+
),
|
|
2832
|
+
this.t.callExpression(branchExpr, [])
|
|
2833
|
+
)
|
|
2834
|
+
)
|
|
2835
|
+
)
|
|
2836
|
+
])
|
|
2837
|
+
),
|
|
2838
|
+
[]
|
|
2839
|
+
)
|
|
2840
|
+
])
|
|
2841
|
+
)
|
|
2842
|
+
);
|
|
2843
|
+
}
|
|
2844
|
+
processConditionalTernary(expr, parentId, statements, scope, context2) {
|
|
2845
|
+
const condition = expr.test;
|
|
2846
|
+
const consequent = expr.consequent;
|
|
2847
|
+
const alternate = expr.alternate;
|
|
2848
|
+
const computedId = scope.generateUidIdentifier("c");
|
|
2849
|
+
const trueBranchExpr = this.transformExpressionToBranch(
|
|
2850
|
+
consequent,
|
|
2851
|
+
scope,
|
|
2852
|
+
context2
|
|
2853
|
+
);
|
|
2854
|
+
const falseBranchExpr = this.transformExpressionToBranch(
|
|
2855
|
+
alternate,
|
|
2856
|
+
scope,
|
|
2857
|
+
context2
|
|
2858
|
+
);
|
|
2859
|
+
statements.push(
|
|
2860
|
+
this.t.expressionStatement(
|
|
2861
|
+
this.t.callExpression(this.t.identifier("$insert"), [
|
|
2862
|
+
parentId,
|
|
2863
|
+
this.t.callExpression(
|
|
2864
|
+
this.t.arrowFunctionExpression(
|
|
2865
|
+
[],
|
|
2866
|
+
this.t.blockStatement([
|
|
2867
|
+
this.t.variableDeclaration("var", [
|
|
2868
|
+
this.t.variableDeclarator(
|
|
2869
|
+
computedId,
|
|
2870
|
+
this.t.callExpression(this.t.identifier("$computed"), [
|
|
2871
|
+
this.t.arrowFunctionExpression(
|
|
2872
|
+
[],
|
|
2873
|
+
this.astUtils.replaceThisWithSelf(condition)
|
|
2874
|
+
)
|
|
2875
|
+
])
|
|
2876
|
+
)
|
|
2877
|
+
]),
|
|
2878
|
+
this.t.returnStatement(
|
|
2879
|
+
this.t.arrowFunctionExpression(
|
|
2880
|
+
[],
|
|
2881
|
+
this.t.conditionalExpression(
|
|
2882
|
+
this.t.memberExpression(
|
|
2883
|
+
computedId,
|
|
2884
|
+
this.t.identifier("value")
|
|
2885
|
+
),
|
|
2886
|
+
this.t.callExpression(trueBranchExpr, []),
|
|
2887
|
+
this.t.callExpression(falseBranchExpr, [])
|
|
2888
|
+
)
|
|
2889
|
+
)
|
|
2890
|
+
)
|
|
2891
|
+
])
|
|
2892
|
+
),
|
|
2893
|
+
[]
|
|
2894
|
+
)
|
|
2895
|
+
])
|
|
2896
|
+
)
|
|
2897
|
+
);
|
|
2898
|
+
}
|
|
2899
|
+
transformExpressionToBranch(node, scope, context2) {
|
|
2900
|
+
if (this.t.isJSXElement(node) || this.t.isJSXFragment(node)) {
|
|
2901
|
+
const { id, statements } = this.transformElement(
|
|
2902
|
+
{ node },
|
|
2903
|
+
scope,
|
|
2904
|
+
context2
|
|
2905
|
+
);
|
|
2906
|
+
return this.t.arrowFunctionExpression(
|
|
2907
|
+
[],
|
|
2908
|
+
this.t.blockStatement([...statements, this.t.returnStatement(id)])
|
|
2909
|
+
);
|
|
2910
|
+
}
|
|
2911
|
+
return this.t.arrowFunctionExpression(
|
|
2912
|
+
[],
|
|
2913
|
+
this.astUtils.replaceThisWithSelf(node)
|
|
2914
|
+
);
|
|
2915
|
+
}
|
|
2394
2916
|
};
|
|
2395
2917
|
function j2d({ types: t }) {
|
|
2396
2918
|
const guards = new NodeTypeGuards(t);
|
|
2397
2919
|
const astUtils = new ASTUtilities(t, guards);
|
|
2398
2920
|
const jsxUtils = new JSXUtilities(t);
|
|
2399
|
-
const observableManager = new ObservableManager(t, guards);
|
|
2400
2921
|
const elementTransformer = new ElementTransformer(
|
|
2401
2922
|
t,
|
|
2402
2923
|
guards,
|
|
2403
2924
|
astUtils,
|
|
2404
|
-
jsxUtils
|
|
2405
|
-
observableManager
|
|
2925
|
+
jsxUtils
|
|
2406
2926
|
);
|
|
2407
2927
|
return {
|
|
2408
2928
|
name: "jsx-to-dom",
|
|
@@ -2415,8 +2935,8 @@ function j2d({ types: t }) {
|
|
|
2415
2935
|
{ local: "$createComponent", imported: "createComponent" },
|
|
2416
2936
|
{ local: "$style", imported: "style" },
|
|
2417
2937
|
{ local: "$spread", imported: "spread" },
|
|
2418
|
-
{ local: "$
|
|
2419
|
-
{ local: "$
|
|
2938
|
+
{ local: "$effect", imported: "effect" },
|
|
2939
|
+
{ local: "$computed", imported: "computed" }
|
|
2420
2940
|
];
|
|
2421
2941
|
for (const helper of helpers) {
|
|
2422
2942
|
path17.unshiftContainer(
|
|
@@ -2450,49 +2970,12 @@ function j2d({ types: t }) {
|
|
|
2450
2970
|
path17.setData("processed", true);
|
|
2451
2971
|
const body = path17.node.body;
|
|
2452
2972
|
if (!t.isBlockStatement(body)) return;
|
|
2453
|
-
const observables = /* @__PURE__ */ new Map();
|
|
2454
|
-
path17.traverse({
|
|
2455
|
-
JSXElement(jsxPath) {
|
|
2456
|
-
observableManager.collectObservables(
|
|
2457
|
-
jsxPath.node,
|
|
2458
|
-
observables,
|
|
2459
|
-
astUtils
|
|
2460
|
-
);
|
|
2461
|
-
},
|
|
2462
|
-
JSXFragment(jsxPath) {
|
|
2463
|
-
observableManager.collectObservables(
|
|
2464
|
-
jsxPath.node,
|
|
2465
|
-
observables,
|
|
2466
|
-
astUtils
|
|
2467
|
-
);
|
|
2468
|
-
}
|
|
2469
|
-
});
|
|
2470
2973
|
body.body.unshift(
|
|
2471
2974
|
t.variableDeclaration("const", [
|
|
2472
2975
|
t.variableDeclarator(t.identifier("self"), t.thisExpression())
|
|
2473
2976
|
])
|
|
2474
2977
|
);
|
|
2475
|
-
const
|
|
2476
|
-
const signalDeclarations = [];
|
|
2477
|
-
for (const [key, observable] of observables) {
|
|
2478
|
-
const signalId = path17.scope.generateUidIdentifier("sig");
|
|
2479
|
-
observableSignals.set(key, signalId);
|
|
2480
|
-
signalDeclarations.push(
|
|
2481
|
-
t.variableDeclaration("const", [
|
|
2482
|
-
t.variableDeclarator(
|
|
2483
|
-
signalId,
|
|
2484
|
-
t.callExpression(t.identifier("$toSignal"), [
|
|
2485
|
-
observable,
|
|
2486
|
-
t.identifier("self")
|
|
2487
|
-
])
|
|
2488
|
-
)
|
|
2489
|
-
])
|
|
2490
|
-
);
|
|
2491
|
-
}
|
|
2492
|
-
if (signalDeclarations.length > 0) {
|
|
2493
|
-
astUtils.insertBeforeReturn(body.body, signalDeclarations);
|
|
2494
|
-
}
|
|
2495
|
-
const context2 = { observables, observableSignals };
|
|
2978
|
+
const context2 = { signals: /* @__PURE__ */ new Map() };
|
|
2496
2979
|
path17.traverse({
|
|
2497
2980
|
JSXElement(jsxPath) {
|
|
2498
2981
|
if (jsxPath.getData("processed")) return;
|
|
@@ -2537,7 +3020,7 @@ function j2d({ types: t }) {
|
|
|
2537
3020
|
}
|
|
2538
3021
|
|
|
2539
3022
|
// src/plugins/generators/generate_server_component.ts
|
|
2540
|
-
import { parseSync as parseSync3, printSync as
|
|
3023
|
+
import { parseSync as parseSync3, printSync as printSync3 } from "@swc/core";
|
|
2541
3024
|
function generateServerComponent(filePath, code) {
|
|
2542
3025
|
const ast = parseSync3(code, {
|
|
2543
3026
|
syntax: "typescript",
|
|
@@ -2579,7 +3062,7 @@ function generateServerComponent(filePath, code) {
|
|
|
2579
3062
|
preservedNodes.push(item);
|
|
2580
3063
|
}
|
|
2581
3064
|
}
|
|
2582
|
-
const preservedCode = preservedNodes.length > 0 ?
|
|
3065
|
+
const preservedCode = preservedNodes.length > 0 ? printSync3({
|
|
2583
3066
|
type: "Module",
|
|
2584
3067
|
span: ast.span,
|
|
2585
3068
|
body: preservedNodes,
|
|
@@ -2614,7 +3097,7 @@ function extractClassStub2(classDecl) {
|
|
|
2614
3097
|
const constructorParams = [];
|
|
2615
3098
|
if (classDecl.decorators) {
|
|
2616
3099
|
for (const dec of classDecl.decorators) {
|
|
2617
|
-
const str =
|
|
3100
|
+
const str = stringifyDecorator3(dec);
|
|
2618
3101
|
if (str) decorators.push(str);
|
|
2619
3102
|
}
|
|
2620
3103
|
}
|
|
@@ -2639,8 +3122,8 @@ function extractClassStub2(classDecl) {
|
|
|
2639
3122
|
methods
|
|
2640
3123
|
};
|
|
2641
3124
|
}
|
|
2642
|
-
function
|
|
2643
|
-
const exprCode =
|
|
3125
|
+
function stringifyDecorator3(decorator) {
|
|
3126
|
+
const exprCode = printSync3({
|
|
2644
3127
|
type: "Module",
|
|
2645
3128
|
span: { start: 0, end: 0, ctxt: 0 },
|
|
2646
3129
|
body: [
|
|
@@ -2675,7 +3158,7 @@ function stringifyParam2(param) {
|
|
|
2675
3158
|
let decorators = [];
|
|
2676
3159
|
if (param.decorators) {
|
|
2677
3160
|
for (const d of param.decorators) {
|
|
2678
|
-
const str =
|
|
3161
|
+
const str = stringifyDecorator3(d);
|
|
2679
3162
|
if (str) decorators.push(str);
|
|
2680
3163
|
}
|
|
2681
3164
|
}
|
|
@@ -2870,10 +3353,11 @@ ${decoratorsStr}export class ${className} extends _OrcaComponent {
|
|
|
2870
3353
|
}
|
|
2871
3354
|
|
|
2872
3355
|
// src/plugins/generators/generate_rpc.ts
|
|
3356
|
+
import { printSync as printSync4 } from "@swc/core";
|
|
2873
3357
|
function generateRpcStub(filePath, code) {
|
|
2874
3358
|
try {
|
|
2875
3359
|
const ast = parseTypeScript(filePath, code);
|
|
2876
|
-
const serviceInfo = extractServiceInfo(ast, filePath, false);
|
|
3360
|
+
const serviceInfo = extractServiceInfo(ast, filePath, false, true, true);
|
|
2877
3361
|
if (!serviceInfo) {
|
|
2878
3362
|
throw {
|
|
2879
3363
|
type: "validation",
|
|
@@ -2881,7 +3365,6 @@ function generateRpcStub(filePath, code) {
|
|
|
2881
3365
|
filePath
|
|
2882
3366
|
};
|
|
2883
3367
|
}
|
|
2884
|
-
validateServiceInfo(serviceInfo, filePath);
|
|
2885
3368
|
return generateStubCode2(serviceInfo);
|
|
2886
3369
|
} catch (error) {
|
|
2887
3370
|
if (error.type) {
|
|
@@ -2895,32 +3378,143 @@ function generateRpcStub(filePath, code) {
|
|
|
2895
3378
|
};
|
|
2896
3379
|
}
|
|
2897
3380
|
}
|
|
3381
|
+
function hasMulterFileParams2(method) {
|
|
3382
|
+
return method.params.some((param) => {
|
|
3383
|
+
return param.type === "Array<Express.Multer.File>" || param.type === "Express.Multer.File[]" || param.type === "Express.Multer.File";
|
|
3384
|
+
});
|
|
3385
|
+
}
|
|
3386
|
+
function getFileParams2(method) {
|
|
3387
|
+
return method.params.filter(
|
|
3388
|
+
(p) => p.type === "Array<Express.Multer.File>" || p.type === "Express.Multer.File[]" || p.type === "Express.Multer.File"
|
|
3389
|
+
).map((p) => ({
|
|
3390
|
+
name: p.name,
|
|
3391
|
+
type: p.type,
|
|
3392
|
+
isArray: p.type.includes("Array") || p.type.includes("[]")
|
|
3393
|
+
}));
|
|
3394
|
+
}
|
|
3395
|
+
function getNonFileParams2(method) {
|
|
3396
|
+
return method.params.filter(
|
|
3397
|
+
(p) => p.type !== "Array<Express.Multer.File>" && p.type !== "Express.Multer.File[]" && p.type !== "Express.Multer.File"
|
|
3398
|
+
);
|
|
3399
|
+
}
|
|
3400
|
+
function collectSharedImports(serviceInfo) {
|
|
3401
|
+
const allImports = [];
|
|
3402
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3403
|
+
const sharedParams = serviceInfo.constructorParams.filter(
|
|
3404
|
+
(c) => c.decorators?.some((d) => d === "@Shared()")
|
|
3405
|
+
);
|
|
3406
|
+
for (const param of sharedParams) {
|
|
3407
|
+
if (param.imports) {
|
|
3408
|
+
for (const imp of param.imports) {
|
|
3409
|
+
const key = `${imp.identifier}:${imp.source}`;
|
|
3410
|
+
if (!seen.has(key)) {
|
|
3411
|
+
allImports.push(imp);
|
|
3412
|
+
seen.add(key);
|
|
3413
|
+
}
|
|
3414
|
+
}
|
|
3415
|
+
}
|
|
3416
|
+
}
|
|
3417
|
+
return allImports;
|
|
3418
|
+
}
|
|
3419
|
+
function generateImportStatements(imports) {
|
|
3420
|
+
const importsBySource = /* @__PURE__ */ new Map();
|
|
3421
|
+
for (const imp of imports) {
|
|
3422
|
+
if (!importsBySource.has(imp.source)) {
|
|
3423
|
+
importsBySource.set(imp.source, /* @__PURE__ */ new Set());
|
|
3424
|
+
}
|
|
3425
|
+
importsBySource.get(imp.source).add(imp.identifier);
|
|
3426
|
+
}
|
|
3427
|
+
const statements = [];
|
|
3428
|
+
for (const [source, identifiers] of importsBySource) {
|
|
3429
|
+
const identifierList = Array.from(identifiers).sort().join(", ");
|
|
3430
|
+
statements.push(`import { ${identifierList} } from "${source}";`);
|
|
3431
|
+
}
|
|
3432
|
+
return statements.sort().join("\n");
|
|
3433
|
+
}
|
|
2898
3434
|
function generateStubCode2(serviceInfo) {
|
|
2899
3435
|
const className = serviceInfo.className;
|
|
2900
3436
|
const basePath = serviceNameToPath(className);
|
|
2901
3437
|
const methods = serviceInfo.methods.map((method) => generateMethod2(method, basePath, className)).join("\n\n");
|
|
2902
3438
|
const hasStreamable = serviceInfo.methods.some((m) => m.isStreamable);
|
|
2903
|
-
const
|
|
3439
|
+
const sharedImports = collectSharedImports(serviceInfo);
|
|
3440
|
+
const imports = generateImports2(hasStreamable, sharedImports);
|
|
3441
|
+
let clientConstructorFields = serviceInfo.constructorParams.filter((c) => c.decorators?.some((d) => d === "@Shared()")).map((c) => {
|
|
3442
|
+
const filteredDecorators = c.decorators?.filter((d) => d !== "@Shared()") || [];
|
|
3443
|
+
const decoratorStr = filteredDecorators.length > 0 ? filteredDecorators.join("\n") + "\n" : "";
|
|
3444
|
+
return `${decoratorStr}${c.accessibility}${c.isReadonly ? " readonly " : " "}${c.name}: ${c.type},`;
|
|
3445
|
+
}).join("\n");
|
|
2904
3446
|
return `${imports}
|
|
2905
3447
|
|
|
2906
3448
|
@Injectable()
|
|
2907
3449
|
export class ${className} {
|
|
3450
|
+
constructor(
|
|
3451
|
+
${clientConstructorFields}
|
|
3452
|
+
) {}
|
|
3453
|
+
|
|
2908
3454
|
${methods}
|
|
2909
3455
|
}`;
|
|
2910
3456
|
}
|
|
2911
|
-
function generateImports2(hasStreamable) {
|
|
3457
|
+
function generateImports2(hasStreamable, sharedImports) {
|
|
2912
3458
|
let imports = `import { Injectable } from "@kithinji/orca";
|
|
2913
3459
|
`;
|
|
2914
3460
|
if (hasStreamable) {
|
|
2915
|
-
imports += `import { Observable } from "
|
|
3461
|
+
imports += `import { Observable } from "rxjs";
|
|
2916
3462
|
`;
|
|
2917
3463
|
}
|
|
3464
|
+
if (sharedImports.length > 0) {
|
|
3465
|
+
const sharedImportStatements = generateImportStatements(sharedImports);
|
|
3466
|
+
if (sharedImportStatements) {
|
|
3467
|
+
imports += sharedImportStatements + "\n";
|
|
3468
|
+
}
|
|
3469
|
+
}
|
|
2918
3470
|
return imports;
|
|
2919
3471
|
}
|
|
2920
3472
|
function generateMethod2(method, basePath, serviceName) {
|
|
3473
|
+
if (method.lift) {
|
|
3474
|
+
const classWrapper = {
|
|
3475
|
+
type: "Module",
|
|
3476
|
+
span: { start: 0, end: 0 },
|
|
3477
|
+
body: [
|
|
3478
|
+
{
|
|
3479
|
+
type: "ClassDeclaration",
|
|
3480
|
+
span: { start: 0, end: 0 },
|
|
3481
|
+
declare: false,
|
|
3482
|
+
ctxt: 0,
|
|
3483
|
+
identifier: {
|
|
3484
|
+
type: "Identifier",
|
|
3485
|
+
value: "",
|
|
3486
|
+
optional: false,
|
|
3487
|
+
span: { start: 0, end: 0 },
|
|
3488
|
+
ctxt: 0
|
|
3489
|
+
},
|
|
3490
|
+
body: [JSON.parse(JSON.stringify(method.ast))],
|
|
3491
|
+
decorators: [],
|
|
3492
|
+
superClass: null
|
|
3493
|
+
}
|
|
3494
|
+
],
|
|
3495
|
+
shebang: null
|
|
3496
|
+
};
|
|
3497
|
+
let { code } = printSync4(classWrapper);
|
|
3498
|
+
const lines = code.split("\n");
|
|
3499
|
+
lines.shift();
|
|
3500
|
+
lines.pop();
|
|
3501
|
+
lines.pop();
|
|
3502
|
+
const methodCode = lines.join("\n");
|
|
3503
|
+
return methodCode;
|
|
3504
|
+
}
|
|
2921
3505
|
if (method.isStreamable) {
|
|
3506
|
+
if (hasMulterFileParams2(method)) {
|
|
3507
|
+
throw new Error(
|
|
3508
|
+
`Method '${method.name}' cannot have file parameters for streaming endpoints`
|
|
3509
|
+
);
|
|
3510
|
+
}
|
|
2922
3511
|
return generateSseMethod(method, basePath);
|
|
2923
3512
|
}
|
|
3513
|
+
const fileParams = getFileParams2(method);
|
|
3514
|
+
const hasFileParams = fileParams.length > 0;
|
|
3515
|
+
if (hasFileParams) {
|
|
3516
|
+
return generateFileUploadMethod2(method, basePath, fileParams);
|
|
3517
|
+
}
|
|
2924
3518
|
const params = method.params.map((p) => `${p.name}: ${p.type}`).join(", ");
|
|
2925
3519
|
const hasParams = method.params.length > 0;
|
|
2926
3520
|
if (!hasParams) {
|
|
@@ -2928,36 +3522,130 @@ function generateMethod2(method, basePath, serviceName) {
|
|
|
2928
3522
|
}
|
|
2929
3523
|
return generatePostMethod(method, basePath, params);
|
|
2930
3524
|
}
|
|
3525
|
+
function generateFileUploadMethod2(method, basePath, fileParams) {
|
|
3526
|
+
const allParams = method.params.map((p) => `${p.name}: ${p.type}`).join(", ");
|
|
3527
|
+
const nonFileParams = getNonFileParams2(method);
|
|
3528
|
+
const returnType = `Promise<${method.returnType}>`;
|
|
3529
|
+
const lines = [];
|
|
3530
|
+
lines.push(` const formData = new FormData();`);
|
|
3531
|
+
lines.push(``);
|
|
3532
|
+
fileParams.forEach((fp) => {
|
|
3533
|
+
if (fp.isArray) {
|
|
3534
|
+
lines.push(` if (${fp.name} && Array.isArray(${fp.name})) {`);
|
|
3535
|
+
lines.push(` ${fp.name}.forEach((file) => {`);
|
|
3536
|
+
lines.push(` formData.append('${fp.name}', file);`);
|
|
3537
|
+
lines.push(` });`);
|
|
3538
|
+
lines.push(` }`);
|
|
3539
|
+
} else {
|
|
3540
|
+
lines.push(` if (${fp.name}) {`);
|
|
3541
|
+
lines.push(` formData.append('${fp.name}', ${fp.name});`);
|
|
3542
|
+
lines.push(` }`);
|
|
3543
|
+
}
|
|
3544
|
+
});
|
|
3545
|
+
if (nonFileParams.length > 0) {
|
|
3546
|
+
lines.push(``);
|
|
3547
|
+
nonFileParams.forEach((p) => {
|
|
3548
|
+
lines.push(` if (${p.name} !== undefined) {`);
|
|
3549
|
+
lines.push(
|
|
3550
|
+
` formData.append('${p.name}', typeof ${p.name} === 'object' ? JSON.stringify(${p.name}) : String(${p.name}));`
|
|
3551
|
+
);
|
|
3552
|
+
lines.push(` }`);
|
|
3553
|
+
});
|
|
3554
|
+
}
|
|
3555
|
+
lines.push(``);
|
|
3556
|
+
lines.push(` let headers = this.${method.name}Headers?.() || {};`);
|
|
3557
|
+
lines.push(``);
|
|
3558
|
+
lines.push(` if(headers instanceof Promise) {`);
|
|
3559
|
+
lines.push(` headers = await headers;`);
|
|
3560
|
+
lines.push(` }`);
|
|
3561
|
+
lines.push(``);
|
|
3562
|
+
lines.push(
|
|
3563
|
+
` const response = await fetch(\`/api/${basePath}/${method.name}\`, {`
|
|
3564
|
+
);
|
|
3565
|
+
lines.push(` method: 'POST',`);
|
|
3566
|
+
lines.push(` headers: {`);
|
|
3567
|
+
lines.push(` ...headers`);
|
|
3568
|
+
lines.push(` },`);
|
|
3569
|
+
lines.push(` body: formData,`);
|
|
3570
|
+
lines.push(` });`);
|
|
3571
|
+
lines.push(``);
|
|
3572
|
+
lines.push(` if (!response.ok) {`);
|
|
3573
|
+
lines.push(
|
|
3574
|
+
` throw new Error(\`HTTP error! status: \${response.status}\`);`
|
|
3575
|
+
);
|
|
3576
|
+
lines.push(` }`);
|
|
3577
|
+
lines.push(``);
|
|
3578
|
+
lines.push(` return response.json();`);
|
|
3579
|
+
return ` async ${method.name}(${allParams}): ${returnType} {
|
|
3580
|
+
${lines.join("\n")}
|
|
3581
|
+
}`;
|
|
3582
|
+
}
|
|
2931
3583
|
function generateSseMethod(method, basePath) {
|
|
2932
3584
|
const params = method.params.map((p) => `${p.name}: ${p.type}`).join(", ");
|
|
2933
3585
|
const hasParams = method.params.length > 0;
|
|
2934
3586
|
let urlBuilder;
|
|
3587
|
+
const headerCheck = `this.${method.name}Headers`;
|
|
2935
3588
|
if (hasParams) {
|
|
2936
3589
|
const queryParams = method.params.map((p) => `${p.name}=\${encodeURIComponent(${p.name})}`).join("&");
|
|
2937
|
-
urlBuilder =
|
|
3590
|
+
urlBuilder = `\`/api/${basePath}/${method.name}?${queryParams}\``;
|
|
2938
3591
|
} else {
|
|
2939
|
-
urlBuilder =
|
|
3592
|
+
urlBuilder = `\`/api/${basePath}/${method.name}\``;
|
|
2940
3593
|
}
|
|
2941
3594
|
return ` ${method.name}(${params}): Observable<${method.returnType}> {
|
|
2942
3595
|
return new Observable((observer) => {
|
|
2943
|
-
|
|
3596
|
+
let url = ${urlBuilder};
|
|
2944
3597
|
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
3598
|
+
// Get headers and append them as query parameters for SSE
|
|
3599
|
+
const getHeaders = async () => {
|
|
3600
|
+
let headers = ${headerCheck}?.() || {};
|
|
3601
|
+
|
|
3602
|
+
if (headers instanceof Promise) {
|
|
3603
|
+
headers = await headers;
|
|
3604
|
+
}
|
|
3605
|
+
|
|
3606
|
+
// Convert headers to query parameters for EventSource
|
|
3607
|
+
const headerParams = new URLSearchParams();
|
|
3608
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
3609
|
+
headerParams.append(key, String(value));
|
|
2951
3610
|
}
|
|
3611
|
+
|
|
3612
|
+
const headerString = headerParams.toString();
|
|
3613
|
+
if (headerString) {
|
|
3614
|
+
url += ${hasParams ? "`&${headerString}`" : "`?${headerString}`"};
|
|
3615
|
+
}
|
|
3616
|
+
|
|
3617
|
+
const eventSource = new EventSource(url);
|
|
3618
|
+
|
|
3619
|
+
eventSource.onmessage = (event) => {
|
|
3620
|
+
try {
|
|
3621
|
+
const data = JSON.parse(event.data);
|
|
3622
|
+
observer.next(data);
|
|
3623
|
+
} catch (error) {
|
|
3624
|
+
observer.error?.(error);
|
|
3625
|
+
}
|
|
3626
|
+
};
|
|
3627
|
+
|
|
3628
|
+
eventSource.onerror = (error) => {
|
|
3629
|
+
observer.error?.(error);
|
|
3630
|
+
eventSource.close();
|
|
3631
|
+
};
|
|
3632
|
+
|
|
3633
|
+
return () => {
|
|
3634
|
+
eventSource.close();
|
|
3635
|
+
};
|
|
2952
3636
|
};
|
|
2953
3637
|
|
|
2954
|
-
|
|
3638
|
+
getHeaders().then((cleanup) => {
|
|
3639
|
+
// Store cleanup function for unsubscribe
|
|
3640
|
+
if (cleanup) {
|
|
3641
|
+
observer.add(cleanup);
|
|
3642
|
+
}
|
|
3643
|
+
}).catch((error) => {
|
|
2955
3644
|
observer.error?.(error);
|
|
2956
|
-
|
|
2957
|
-
};
|
|
3645
|
+
});
|
|
2958
3646
|
|
|
2959
3647
|
return () => {
|
|
2960
|
-
|
|
3648
|
+
// Cleanup handled in getHeaders
|
|
2961
3649
|
};
|
|
2962
3650
|
});
|
|
2963
3651
|
}`;
|
|
@@ -2966,10 +3654,17 @@ function generateGetMethod(method, basePath) {
|
|
|
2966
3654
|
const params = method.params.map((p) => `${p.name}: ${p.type}`).join(", ");
|
|
2967
3655
|
const returnType = `Promise<${method.returnType}>`;
|
|
2968
3656
|
return ` async ${method.name}(${params}): ${returnType} {
|
|
2969
|
-
|
|
3657
|
+
let headers = this.${method.name}Headers?.() || {};
|
|
3658
|
+
|
|
3659
|
+
if(headers instanceof Promise) {
|
|
3660
|
+
headers = await headers;
|
|
3661
|
+
}
|
|
3662
|
+
|
|
3663
|
+
const response = await fetch(\`/api/${basePath}/${method.name}\`, {
|
|
2970
3664
|
method: 'GET',
|
|
2971
3665
|
headers: {
|
|
2972
3666
|
'Content-Type': 'application/json',
|
|
3667
|
+
...headers
|
|
2973
3668
|
}
|
|
2974
3669
|
});
|
|
2975
3670
|
|
|
@@ -2984,10 +3679,17 @@ function generatePostMethod(method, basePath, params) {
|
|
|
2984
3679
|
const paramNames = method.params.map((p) => p.name).join(", ");
|
|
2985
3680
|
const returnType = `Promise<${method.returnType}>`;
|
|
2986
3681
|
return ` async ${method.name}(${params}): ${returnType} {
|
|
2987
|
-
|
|
3682
|
+
let headers = this.${method.name}Headers?.() || {};
|
|
3683
|
+
|
|
3684
|
+
if(headers instanceof Promise) {
|
|
3685
|
+
headers = await headers;
|
|
3686
|
+
}
|
|
3687
|
+
|
|
3688
|
+
const response = await fetch(\`/api/${basePath}/${method.name}\`, {
|
|
2988
3689
|
method: 'POST',
|
|
2989
3690
|
headers: {
|
|
2990
3691
|
'Content-Type': 'application/json',
|
|
3692
|
+
...headers
|
|
2991
3693
|
},
|
|
2992
3694
|
body: JSON.stringify({ ${paramNames} }),
|
|
2993
3695
|
});
|
|
@@ -3044,11 +3746,11 @@ function parseFileMetadata(source, path17) {
|
|
|
3044
3746
|
}
|
|
3045
3747
|
var ServerBuildTransformer = class {
|
|
3046
3748
|
async transformPublicFile(source, path17) {
|
|
3047
|
-
const
|
|
3048
|
-
if (
|
|
3049
|
-
source = `${
|
|
3749
|
+
const result = generateController(path17, source);
|
|
3750
|
+
if (result) {
|
|
3751
|
+
source = `${result.transformedServiceCode}
|
|
3050
3752
|
|
|
3051
|
-
${controllerCode}
|
|
3753
|
+
${result.controllerCode}
|
|
3052
3754
|
`;
|
|
3053
3755
|
}
|
|
3054
3756
|
return swcTransform(source, path17);
|
|
@@ -3183,7 +3885,48 @@ function useMyPlugin(options) {
|
|
|
3183
3885
|
import { parseSync as parseSync4 } from "@swc/core";
|
|
3184
3886
|
import * as fs3 from "fs";
|
|
3185
3887
|
import * as path7 from "path";
|
|
3888
|
+
function findProjectRoot(startPath) {
|
|
3889
|
+
let currentDir = path7.dirname(startPath);
|
|
3890
|
+
while (currentDir !== path7.parse(currentDir).root) {
|
|
3891
|
+
const packageJsonPath = path7.join(currentDir, "package.json");
|
|
3892
|
+
if (fs3.existsSync(packageJsonPath)) {
|
|
3893
|
+
return currentDir;
|
|
3894
|
+
}
|
|
3895
|
+
currentDir = path7.dirname(currentDir);
|
|
3896
|
+
}
|
|
3897
|
+
return process.cwd();
|
|
3898
|
+
}
|
|
3899
|
+
function resolvePathAlias(importPath, projectRoot) {
|
|
3900
|
+
if (importPath.startsWith("@/")) {
|
|
3901
|
+
const possiblePaths = [
|
|
3902
|
+
path7.join(projectRoot, "src", importPath.slice(2)),
|
|
3903
|
+
path7.join(projectRoot, importPath.slice(2))
|
|
3904
|
+
];
|
|
3905
|
+
for (const possiblePath of possiblePaths) {
|
|
3906
|
+
const extensions = ["", ".ts", ".tsx", ".js", ".jsx"];
|
|
3907
|
+
for (const ext of extensions) {
|
|
3908
|
+
const fullPath = possiblePath + ext;
|
|
3909
|
+
if (fs3.existsSync(fullPath) && fs3.statSync(fullPath).isFile()) {
|
|
3910
|
+
return fullPath;
|
|
3911
|
+
}
|
|
3912
|
+
}
|
|
3913
|
+
const indexFiles = ["/index.ts", "/index.tsx", "/index.js", "/index.jsx"];
|
|
3914
|
+
for (const indexFile of indexFiles) {
|
|
3915
|
+
const fullPath = possiblePath + indexFile;
|
|
3916
|
+
if (fs3.existsSync(fullPath) && fs3.statSync(fullPath).isFile()) {
|
|
3917
|
+
return fullPath;
|
|
3918
|
+
}
|
|
3919
|
+
}
|
|
3920
|
+
}
|
|
3921
|
+
}
|
|
3922
|
+
return null;
|
|
3923
|
+
}
|
|
3186
3924
|
function resolveFilePath(fromFile, importPath) {
|
|
3925
|
+
if (importPath.startsWith("@/")) {
|
|
3926
|
+
const projectRoot = findProjectRoot(fromFile);
|
|
3927
|
+
const aliasResolved = resolvePathAlias(importPath, projectRoot);
|
|
3928
|
+
if (aliasResolved) return aliasResolved;
|
|
3929
|
+
}
|
|
3187
3930
|
if (!importPath.startsWith(".")) return null;
|
|
3188
3931
|
const dir = path7.dirname(fromFile);
|
|
3189
3932
|
const basePath = path7.resolve(dir, importPath);
|
|
@@ -3606,7 +4349,7 @@ export async function navigate(event, url) {
|
|
|
3606
4349
|
const injector = getCurrentInjector();
|
|
3607
4350
|
|
|
3608
4351
|
if (injector) {
|
|
3609
|
-
const navigate = injector.resolve(Navigate);
|
|
4352
|
+
const navigate = await injector.resolve(Navigate);
|
|
3610
4353
|
navigate.go(url);
|
|
3611
4354
|
} else {
|
|
3612
4355
|
window.location.href = url;
|
|
@@ -3669,7 +4412,7 @@ var HotReloadManager = class {
|
|
|
3669
4412
|
});
|
|
3670
4413
|
});
|
|
3671
4414
|
this.logger.info(
|
|
3672
|
-
`Hot
|
|
4415
|
+
`Hot reloads servers listening on ws://localhost:${this.port}`
|
|
3673
4416
|
);
|
|
3674
4417
|
}
|
|
3675
4418
|
reload() {
|
|
@@ -4891,7 +5634,7 @@ function createPage(name) {
|
|
|
4891
5634
|
import { ${listComponent} } from "./components/${name}-list.component";
|
|
4892
5635
|
|
|
4893
5636
|
@Component({
|
|
4894
|
-
|
|
5637
|
+
inject: [${listComponent}]
|
|
4895
5638
|
})
|
|
4896
5639
|
export class ${pageName} {
|
|
4897
5640
|
build() {
|
|
@@ -4987,7 +5730,8 @@ function genPackageJson(name) {
|
|
|
4987
5730
|
"reflect-metadata": "latest",
|
|
4988
5731
|
zod: "^4.2.1",
|
|
4989
5732
|
"@kithinji/orca": "latest",
|
|
4990
|
-
"@kithinji/arcane": "latest"
|
|
5733
|
+
"@kithinji/arcane": "latest",
|
|
5734
|
+
rxjs: "latest"
|
|
4991
5735
|
},
|
|
4992
5736
|
devDependencies: {
|
|
4993
5737
|
"@types/node": "^20.19.27",
|
|
@@ -5010,6 +5754,7 @@ function gentsconfig() {
|
|
|
5010
5754
|
jsxImportSource: "@kithinji/orca",
|
|
5011
5755
|
experimentalDecorators: true,
|
|
5012
5756
|
emitDecoratorMetadata: true,
|
|
5757
|
+
strictPropertyInitialization: false,
|
|
5013
5758
|
baseUrl: ".",
|
|
5014
5759
|
paths: {
|
|
5015
5760
|
"@/*": ["src/*"]
|
|
@@ -5056,7 +5801,7 @@ function genIndexHtml(name) {
|
|
|
5056
5801
|
<meta charset="UTF-8" />
|
|
5057
5802
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
5058
5803
|
<title>${name} app</title>
|
|
5059
|
-
<link rel="stylesheet" href="index.css" />
|
|
5804
|
+
<link rel="stylesheet" href="/index.css" />
|
|
5060
5805
|
</head>
|
|
5061
5806
|
<body>
|
|
5062
5807
|
<div id="root"></div>
|
|
@@ -5078,7 +5823,7 @@ import {
|
|
|
5078
5823
|
} from "@kithinji/orca";
|
|
5079
5824
|
|
|
5080
5825
|
@Component({
|
|
5081
|
-
|
|
5826
|
+
inject: [RouterOutlet],
|
|
5082
5827
|
})
|
|
5083
5828
|
class AppComponent {
|
|
5084
5829
|
build() {
|
|
@@ -5093,8 +5838,8 @@ class AppComponent {
|
|
|
5093
5838
|
})
|
|
5094
5839
|
class AppModule {}
|
|
5095
5840
|
|
|
5096
|
-
export function bootstrap() {
|
|
5097
|
-
BrowserFactory.create(AppModule, document.getElementById("root")!);
|
|
5841
|
+
export async function bootstrap() {
|
|
5842
|
+
await BrowserFactory.create(AppModule, document.getElementById("root")!);
|
|
5098
5843
|
}
|
|
5099
5844
|
|
|
5100
5845
|
bootstrap();
|
|
@@ -6769,7 +7514,7 @@ async function compileFiles(entryPoints) {
|
|
|
6769
7514
|
|
|
6770
7515
|
// src/index.ts
|
|
6771
7516
|
var program = new Command();
|
|
6772
|
-
program.name("pod").description("Pod cli tool").version("1.0.
|
|
7517
|
+
program.name("pod").description("Pod cli tool").version("1.0.46");
|
|
6773
7518
|
program.command("new <name> [type]").description("Start a new Orca Project").action(async (name, type) => {
|
|
6774
7519
|
const orca = async () => {
|
|
6775
7520
|
await addNew(name);
|
|
@@ -6836,6 +7581,7 @@ program.command("deploy").description("Deploy to a target environment").argument
|
|
|
6836
7581
|
process.exit(1);
|
|
6837
7582
|
}
|
|
6838
7583
|
});
|
|
7584
|
+
program.parse(process.argv);
|
|
6839
7585
|
export {
|
|
6840
7586
|
config_exports as config,
|
|
6841
7587
|
expandMacros,
|
|
@@ -6846,7 +7592,6 @@ export {
|
|
|
6846
7592
|
macros_exports as macros,
|
|
6847
7593
|
mergeConfig,
|
|
6848
7594
|
plugins_exports as plugins,
|
|
6849
|
-
program,
|
|
6850
7595
|
resetGlobalMacroGraph,
|
|
6851
7596
|
store_exports as store,
|
|
6852
7597
|
stylePlugin,
|