adorn-api 1.0.6 → 1.0.8
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/README.md +66 -2
- package/dist/adapter/express/bootstrap.d.ts +1 -0
- package/dist/adapter/express/bootstrap.d.ts.map +1 -1
- package/dist/adapter/express/index.d.ts +11 -0
- package/dist/adapter/express/index.d.ts.map +1 -1
- package/dist/cli.cjs +141 -34
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +140 -33
- package/dist/cli.js.map +1 -1
- package/dist/compiler/analyze/extractQueryStyle.d.ts +8 -0
- package/dist/compiler/analyze/extractQueryStyle.d.ts.map +1 -0
- package/dist/compiler/manifest/emit.d.ts.map +1 -1
- package/dist/compiler/schema/openapi.d.ts.map +1 -1
- package/dist/compiler/schema/typeToJsonSchema.d.ts.map +1 -1
- package/dist/express.cjs +327 -60
- package/dist/express.cjs.map +1 -1
- package/dist/express.js +327 -60
- package/dist/express.js.map +1 -1
- package/dist/http.d.ts +4 -1
- package/dist/http.d.ts.map +1 -1
- package/dist/index.cjs +7 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -5
- package/dist/index.js.map +1 -1
- package/dist/metal/index.d.ts +1 -0
- package/dist/metal/index.d.ts.map +1 -1
- package/dist/metal/searchWhere.d.ts +42 -0
- package/dist/metal/searchWhere.d.ts.map +1 -0
- package/package.json +4 -4
package/dist/cli.js
CHANGED
|
@@ -197,7 +197,8 @@ function classifyParameters(parameters, httpMethod, pathParamIndices, checker) {
|
|
|
197
197
|
for (let i = 0; i < parameters.length; i++) {
|
|
198
198
|
const param = parameters[i];
|
|
199
199
|
if (usedIndices.has(i)) continue;
|
|
200
|
-
const
|
|
200
|
+
const nonNullableType = checker.getNonNullableType(param.type);
|
|
201
|
+
const typeStr = getTypeName(param.type) || getTypeName(nonNullableType);
|
|
201
202
|
if (typeStr === "Body") {
|
|
202
203
|
bodyParamIndex = i;
|
|
203
204
|
usedIndices.add(i);
|
|
@@ -223,7 +224,7 @@ function classifyParameters(parameters, httpMethod, pathParamIndices, checker) {
|
|
|
223
224
|
usedIndices.add(i);
|
|
224
225
|
continue;
|
|
225
226
|
}
|
|
226
|
-
const isObj = isObjectType(
|
|
227
|
+
const isObj = isObjectType(nonNullableType, checker);
|
|
227
228
|
if (isObj && queryObjectParamIndex === null && !isBodyMethod) {
|
|
228
229
|
queryObjectParamIndex = i;
|
|
229
230
|
usedIndices.add(i);
|
|
@@ -252,6 +253,12 @@ function isObjectType(type, checker) {
|
|
|
252
253
|
if (callSignatures && callSignatures.length > 0) return false;
|
|
253
254
|
return true;
|
|
254
255
|
}
|
|
256
|
+
function getTypeName(type) {
|
|
257
|
+
const aliasSymbol = type.aliasSymbol ?? type.aliasSymbol;
|
|
258
|
+
if (aliasSymbol) return aliasSymbol.getName();
|
|
259
|
+
const symbol = type.getSymbol();
|
|
260
|
+
return symbol?.getName() ?? "";
|
|
261
|
+
}
|
|
255
262
|
function findDecorator(node, name) {
|
|
256
263
|
const decorators = ts2.getDecorators(node);
|
|
257
264
|
if (!decorators) return null;
|
|
@@ -286,7 +293,7 @@ function unwrapPromise(type, checker) {
|
|
|
286
293
|
}
|
|
287
294
|
|
|
288
295
|
// src/compiler/schema/openapi.ts
|
|
289
|
-
import
|
|
296
|
+
import ts6 from "typescript";
|
|
290
297
|
|
|
291
298
|
// src/compiler/schema/typeToJsonSchema.ts
|
|
292
299
|
import ts3 from "typescript";
|
|
@@ -298,6 +305,9 @@ function typeToJsonSchema(type, ctx, typeNode) {
|
|
|
298
305
|
if (type.flags & ts3.TypeFlags.Null) {
|
|
299
306
|
return { type: "null" };
|
|
300
307
|
}
|
|
308
|
+
if (isDateType(type, checker)) {
|
|
309
|
+
return { type: "string", format: "date-time" };
|
|
310
|
+
}
|
|
301
311
|
if (type.flags & ts3.TypeFlags.String) {
|
|
302
312
|
return { type: "string" };
|
|
303
313
|
}
|
|
@@ -347,6 +357,19 @@ function typeToJsonSchema(type, ctx, typeNode) {
|
|
|
347
357
|
}
|
|
348
358
|
return {};
|
|
349
359
|
}
|
|
360
|
+
function isDateType(type, checker) {
|
|
361
|
+
const symbol = type.getSymbol();
|
|
362
|
+
const aliasSymbol = type.aliasSymbol;
|
|
363
|
+
if (aliasSymbol && aliasSymbol.flags & ts3.SymbolFlags.Alias) {
|
|
364
|
+
const aliased = checker.getAliasedSymbol(aliasSymbol);
|
|
365
|
+
return aliased?.getName() === "Date";
|
|
366
|
+
}
|
|
367
|
+
if (symbol && symbol.flags & ts3.SymbolFlags.Alias) {
|
|
368
|
+
const aliased = checker.getAliasedSymbol(symbol);
|
|
369
|
+
return aliased?.getName() === "Date";
|
|
370
|
+
}
|
|
371
|
+
return symbol?.getName() === "Date";
|
|
372
|
+
}
|
|
350
373
|
function isSetType(type, checker) {
|
|
351
374
|
const symbol = type.getSymbol();
|
|
352
375
|
if (!symbol) return false;
|
|
@@ -744,6 +767,56 @@ function mergeFragments(base, ...frags) {
|
|
|
744
767
|
return result;
|
|
745
768
|
}
|
|
746
769
|
|
|
770
|
+
// src/compiler/analyze/extractQueryStyle.ts
|
|
771
|
+
import ts5 from "typescript";
|
|
772
|
+
function extractQueryStyleOptions(checker, method) {
|
|
773
|
+
if (!ts5.canHaveDecorators(method)) return null;
|
|
774
|
+
const decorators = ts5.getDecorators(method);
|
|
775
|
+
if (!decorators || decorators.length === 0) return null;
|
|
776
|
+
for (const decorator of decorators) {
|
|
777
|
+
const expr = decorator.expression;
|
|
778
|
+
const isCall = ts5.isCallExpression(expr);
|
|
779
|
+
const callee = isCall ? expr.expression : expr;
|
|
780
|
+
const args = isCall ? expr.arguments : ts5.factory.createNodeArray([]);
|
|
781
|
+
const sym = checker.getSymbolAtLocation(callee);
|
|
782
|
+
if (!sym) continue;
|
|
783
|
+
const resolved = sym.flags & ts5.SymbolFlags.Alias ? checker.getAliasedSymbol(sym) : sym;
|
|
784
|
+
const name = resolved.getName();
|
|
785
|
+
if (name !== "QueryStyle") continue;
|
|
786
|
+
const optsNode = args[0];
|
|
787
|
+
if (!optsNode || !ts5.isObjectLiteralExpression(optsNode)) {
|
|
788
|
+
return {};
|
|
789
|
+
}
|
|
790
|
+
return parseQueryStyleOptions(optsNode);
|
|
791
|
+
}
|
|
792
|
+
return null;
|
|
793
|
+
}
|
|
794
|
+
function parseQueryStyleOptions(node) {
|
|
795
|
+
const opts = {};
|
|
796
|
+
for (const prop of node.properties) {
|
|
797
|
+
if (!ts5.isPropertyAssignment(prop)) continue;
|
|
798
|
+
const name = getPropName(prop.name);
|
|
799
|
+
if (!name) continue;
|
|
800
|
+
if (name === "style" && ts5.isStringLiteral(prop.initializer)) {
|
|
801
|
+
const style = prop.initializer.text;
|
|
802
|
+
opts.style = style;
|
|
803
|
+
} else if (name === "explode" && isBooleanLiteral(prop.initializer)) {
|
|
804
|
+
opts.explode = prop.initializer.kind === ts5.SyntaxKind.TrueKeyword;
|
|
805
|
+
} else if (name === "allowReserved" && isBooleanLiteral(prop.initializer)) {
|
|
806
|
+
opts.allowReserved = prop.initializer.kind === ts5.SyntaxKind.TrueKeyword;
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
return opts;
|
|
810
|
+
}
|
|
811
|
+
function getPropName(name) {
|
|
812
|
+
if (ts5.isIdentifier(name)) return name.text;
|
|
813
|
+
if (ts5.isStringLiteral(name)) return name.text;
|
|
814
|
+
return null;
|
|
815
|
+
}
|
|
816
|
+
function isBooleanLiteral(node) {
|
|
817
|
+
return node.kind === ts5.SyntaxKind.TrueKeyword || node.kind === ts5.SyntaxKind.FalseKeyword;
|
|
818
|
+
}
|
|
819
|
+
|
|
747
820
|
// src/compiler/schema/openapi.ts
|
|
748
821
|
function generateOpenAPI(controllers, checker, options = {}) {
|
|
749
822
|
const components = /* @__PURE__ */ new Map();
|
|
@@ -835,12 +908,12 @@ function mergeBodySchemaAnnotations(bodyParam, ctx, schema) {
|
|
|
835
908
|
const declarations = typeSymbol.getDeclarations();
|
|
836
909
|
if (!declarations || declarations.length === 0) return schema;
|
|
837
910
|
const classDecl = declarations[0];
|
|
838
|
-
if (!
|
|
911
|
+
if (!ts6.isClassDeclaration(classDecl)) return schema;
|
|
839
912
|
const result = { ...schema };
|
|
840
913
|
const props = { ...result.properties };
|
|
841
914
|
for (const member of classDecl.members) {
|
|
842
|
-
if (!
|
|
843
|
-
const propName =
|
|
915
|
+
if (!ts6.isPropertyDeclaration(member) || !member.name) continue;
|
|
916
|
+
const propName = ts6.isIdentifier(member.name) ? member.name.text : null;
|
|
844
917
|
if (!propName) continue;
|
|
845
918
|
if (!props[propName]) continue;
|
|
846
919
|
const frags = extractPropertySchemaFragments(ctx.checker, member);
|
|
@@ -875,19 +948,36 @@ function buildQueryParameters(operation, ctx, parameters) {
|
|
|
875
948
|
if (operation.queryObjectParamIndex !== null) {
|
|
876
949
|
const queryParam = operation.parameters[operation.queryObjectParamIndex];
|
|
877
950
|
if (!queryParam) return;
|
|
951
|
+
const queryStyle = extractQueryStyleOptions(ctx.checker, operation.methodDeclaration);
|
|
878
952
|
const querySchema = typeToJsonSchema(queryParam.type, ctx);
|
|
879
|
-
if (
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
const serialization = determineQuerySerialization(propSchema.type);
|
|
884
|
-
parameters.push({
|
|
885
|
-
name: propName,
|
|
953
|
+
if (queryStyle?.style === "deepObject") {
|
|
954
|
+
const explode = queryStyle.explode ?? true;
|
|
955
|
+
const deepParam = {
|
|
956
|
+
name: queryParam.name,
|
|
886
957
|
in: "query",
|
|
887
|
-
required:
|
|
888
|
-
schema:
|
|
889
|
-
|
|
890
|
-
|
|
958
|
+
required: !queryParam.isOptional,
|
|
959
|
+
schema: querySchema.$ref ? { $ref: querySchema.$ref } : querySchema,
|
|
960
|
+
style: "deepObject",
|
|
961
|
+
explode
|
|
962
|
+
};
|
|
963
|
+
if (queryStyle.allowReserved !== void 0) {
|
|
964
|
+
deepParam.allowReserved = queryStyle.allowReserved;
|
|
965
|
+
}
|
|
966
|
+
parameters.push(deepParam);
|
|
967
|
+
} else {
|
|
968
|
+
if (!querySchema.properties) return;
|
|
969
|
+
const queryObjProps = querySchema.properties;
|
|
970
|
+
for (const [propName, propSchema] of Object.entries(queryObjProps)) {
|
|
971
|
+
const isRequired = querySchema.required?.includes(propName) ?? false;
|
|
972
|
+
const serialization = determineQuerySerialization(propSchema.type);
|
|
973
|
+
parameters.push({
|
|
974
|
+
name: propName,
|
|
975
|
+
in: "query",
|
|
976
|
+
required: isRequired,
|
|
977
|
+
schema: propSchema,
|
|
978
|
+
...Object.keys(serialization).length > 0 ? serialization : {}
|
|
979
|
+
});
|
|
980
|
+
}
|
|
891
981
|
}
|
|
892
982
|
}
|
|
893
983
|
for (const paramIndex of operation.queryParamIndices) {
|
|
@@ -957,7 +1047,7 @@ function buildCookieParameters(operation, ctx, parameters) {
|
|
|
957
1047
|
}
|
|
958
1048
|
|
|
959
1049
|
// src/compiler/manifest/emit.ts
|
|
960
|
-
import
|
|
1050
|
+
import ts7 from "typescript";
|
|
961
1051
|
function generateManifest(controllers, checker, version, validationMode = "ajv-runtime") {
|
|
962
1052
|
const components = /* @__PURE__ */ new Map();
|
|
963
1053
|
const ctx = {
|
|
@@ -978,7 +1068,7 @@ function generateManifest(controllers, checker, version, validationMode = "ajv-r
|
|
|
978
1068
|
generator: {
|
|
979
1069
|
name: "adorn-api",
|
|
980
1070
|
version,
|
|
981
|
-
typescript:
|
|
1071
|
+
typescript: ts7.version
|
|
982
1072
|
},
|
|
983
1073
|
schemas: {
|
|
984
1074
|
kind: "openapi-3.1",
|
|
@@ -1063,21 +1153,38 @@ function buildQueryArgs(op, ctx, args) {
|
|
|
1063
1153
|
if (op.queryObjectParamIndex !== null) {
|
|
1064
1154
|
const queryParam = op.parameters[op.queryObjectParamIndex];
|
|
1065
1155
|
if (queryParam) {
|
|
1156
|
+
const queryStyle = extractQueryStyleOptions(ctx.checker, op.methodDeclaration);
|
|
1066
1157
|
const querySchema = typeToJsonSchema(queryParam.type, ctx);
|
|
1067
|
-
if (
|
|
1068
|
-
|
|
1069
|
-
const isRequired = querySchema.required?.includes(propName) ?? false;
|
|
1070
|
-
let schemaRef = propSchema.$ref;
|
|
1071
|
-
if (!schemaRef) {
|
|
1072
|
-
schemaRef = "#/components/schemas/InlineQueryParam";
|
|
1073
|
-
}
|
|
1158
|
+
if (queryStyle?.style === "deepObject") {
|
|
1159
|
+
const schemaRef = querySchema.$ref ?? "#/components/schemas/InlineQueryParam";
|
|
1074
1160
|
args.query.push({
|
|
1075
|
-
name:
|
|
1161
|
+
name: queryParam.name,
|
|
1076
1162
|
index: queryParam.index,
|
|
1077
|
-
required: !
|
|
1163
|
+
required: !queryParam.isOptional,
|
|
1078
1164
|
schemaRef,
|
|
1079
|
-
schemaType:
|
|
1165
|
+
schemaType: querySchema.type,
|
|
1166
|
+
serialization: {
|
|
1167
|
+
style: "deepObject",
|
|
1168
|
+
explode: queryStyle.explode ?? true,
|
|
1169
|
+
allowReserved: queryStyle.allowReserved
|
|
1170
|
+
}
|
|
1080
1171
|
});
|
|
1172
|
+
} else {
|
|
1173
|
+
if (!querySchema.properties) return;
|
|
1174
|
+
for (const [propName, propSchema] of Object.entries(querySchema.properties)) {
|
|
1175
|
+
const isRequired = querySchema.required?.includes(propName) ?? false;
|
|
1176
|
+
let schemaRef = propSchema.$ref;
|
|
1177
|
+
if (!schemaRef) {
|
|
1178
|
+
schemaRef = "#/components/schemas/InlineQueryParam";
|
|
1179
|
+
}
|
|
1180
|
+
args.query.push({
|
|
1181
|
+
name: propName,
|
|
1182
|
+
index: queryParam.index,
|
|
1183
|
+
required: !isRequired,
|
|
1184
|
+
schemaRef,
|
|
1185
|
+
schemaType: propSchema.type
|
|
1186
|
+
});
|
|
1187
|
+
}
|
|
1081
1188
|
}
|
|
1082
1189
|
}
|
|
1083
1190
|
}
|
|
@@ -1386,7 +1493,7 @@ async function isStale(params) {
|
|
|
1386
1493
|
// src/compiler/cache/writeCache.ts
|
|
1387
1494
|
import fs3 from "fs";
|
|
1388
1495
|
import path3 from "path";
|
|
1389
|
-
import
|
|
1496
|
+
import ts9 from "typescript";
|
|
1390
1497
|
function statMtimeMs2(p) {
|
|
1391
1498
|
return fs3.statSync(p).mtimeMs;
|
|
1392
1499
|
}
|
|
@@ -1419,7 +1526,7 @@ function writeCache(params) {
|
|
|
1419
1526
|
generator: {
|
|
1420
1527
|
name: "adorn-api",
|
|
1421
1528
|
version: params.adornVersion,
|
|
1422
|
-
typescript:
|
|
1529
|
+
typescript: ts9.version
|
|
1423
1530
|
},
|
|
1424
1531
|
project: {
|
|
1425
1532
|
tsconfigPath: params.tsconfigAbs,
|
|
@@ -1432,7 +1539,7 @@ function writeCache(params) {
|
|
|
1432
1539
|
}
|
|
1433
1540
|
|
|
1434
1541
|
// src/cli.ts
|
|
1435
|
-
import
|
|
1542
|
+
import ts10 from "typescript";
|
|
1436
1543
|
import process from "process";
|
|
1437
1544
|
var ADORN_VERSION = "0.1.0";
|
|
1438
1545
|
function log(msg) {
|
|
@@ -1460,7 +1567,7 @@ async function buildCommand(args) {
|
|
|
1460
1567
|
outDir: outputDir,
|
|
1461
1568
|
project: projectPath,
|
|
1462
1569
|
adornVersion: ADORN_VERSION,
|
|
1463
|
-
typescriptVersion:
|
|
1570
|
+
typescriptVersion: ts10.version
|
|
1464
1571
|
});
|
|
1465
1572
|
if (!stale.stale) {
|
|
1466
1573
|
log("adorn-api: artifacts up-to-date");
|