@axiomify/cli 6.1.0 → 6.2.0
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 +14 -15
- package/dist/{dist-SYWHGZLI.mjs → dist-IQQ2XGG4.mjs} +30 -10
- package/dist/index.js +2108 -667
- package/dist/index.mjs +2079 -658
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3302,7 +3302,7 @@ function escapeHtml(s) {
|
|
|
3302
3302
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
3303
3303
|
}
|
|
3304
3304
|
function escapeJsString(s) {
|
|
3305
|
-
return s.replace(
|
|
3305
|
+
return JSON.stringify(s).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
3306
3306
|
}
|
|
3307
3307
|
function defineSecuritySchemes(schemes) {
|
|
3308
3308
|
return {
|
|
@@ -3427,7 +3427,7 @@ function useOpenAPI(app, options) {
|
|
|
3427
3427
|
<script>
|
|
3428
3428
|
window.onload = () => {
|
|
3429
3429
|
window.ui = SwaggerUIBundle({
|
|
3430
|
-
url:
|
|
3430
|
+
url: ${escapeJsString(specUrl)},
|
|
3431
3431
|
dom_id: '#swagger-ui',
|
|
3432
3432
|
});
|
|
3433
3433
|
};
|
|
@@ -3491,7 +3491,8 @@ var init_dist = __esm({
|
|
|
3491
3491
|
if (s.callbacks) operation.callbacks = s.callbacks;
|
|
3492
3492
|
const body = this.extractBody(route);
|
|
3493
3493
|
if (body) {
|
|
3494
|
-
if (s.requestBodyDescription)
|
|
3494
|
+
if (s.requestBodyDescription)
|
|
3495
|
+
body.description = s.requestBodyDescription;
|
|
3495
3496
|
operation.requestBody = body;
|
|
3496
3497
|
}
|
|
3497
3498
|
paths[openApiPath][method] = operation;
|
|
@@ -3505,14 +3506,23 @@ var init_dist = __esm({
|
|
|
3505
3506
|
extractParameters(route) {
|
|
3506
3507
|
const parameters = [];
|
|
3507
3508
|
if (route.schema?.params) {
|
|
3508
|
-
const paramSchema = zodSchemaToOpenApi(
|
|
3509
|
+
const paramSchema = zodSchemaToOpenApi(
|
|
3510
|
+
route.schema.params
|
|
3511
|
+
);
|
|
3509
3512
|
const properties = paramSchema.properties ?? {};
|
|
3510
3513
|
for (const [key, prop] of Object.entries(properties)) {
|
|
3511
|
-
parameters.push({
|
|
3514
|
+
parameters.push({
|
|
3515
|
+
name: key,
|
|
3516
|
+
in: "path",
|
|
3517
|
+
required: true,
|
|
3518
|
+
schema: prop
|
|
3519
|
+
});
|
|
3512
3520
|
}
|
|
3513
3521
|
}
|
|
3514
3522
|
if (route.schema?.query) {
|
|
3515
|
-
const querySchema = zodSchemaToOpenApi(
|
|
3523
|
+
const querySchema = zodSchemaToOpenApi(
|
|
3524
|
+
route.schema.query
|
|
3525
|
+
);
|
|
3516
3526
|
const properties = querySchema.properties ?? {};
|
|
3517
3527
|
const required = querySchema.required ?? [];
|
|
3518
3528
|
for (const [key, prop] of Object.entries(properties)) {
|
|
@@ -3556,11 +3566,18 @@ var init_dist = __esm({
|
|
|
3556
3566
|
if (!route.schema?.body && !route.schema?.files) return void 0;
|
|
3557
3567
|
const hasFiles = !!route.schema.files;
|
|
3558
3568
|
const contentType = hasFiles ? "multipart/form-data" : "application/json";
|
|
3559
|
-
let finalSchema = {
|
|
3569
|
+
let finalSchema = {
|
|
3570
|
+
type: "object",
|
|
3571
|
+
properties: {}
|
|
3572
|
+
};
|
|
3560
3573
|
if (route.schema.body) {
|
|
3561
|
-
const bodySchema = zodSchemaToOpenApi(
|
|
3574
|
+
const bodySchema = zodSchemaToOpenApi(
|
|
3575
|
+
route.schema.body
|
|
3576
|
+
);
|
|
3562
3577
|
if (bodySchema.type === "object") {
|
|
3563
|
-
finalSchema.properties = {
|
|
3578
|
+
finalSchema.properties = {
|
|
3579
|
+
...bodySchema.properties
|
|
3580
|
+
};
|
|
3564
3581
|
if (bodySchema.required) finalSchema.required = bodySchema.required;
|
|
3565
3582
|
if (bodySchema.additionalProperties !== void 0) {
|
|
3566
3583
|
finalSchema.additionalProperties = bodySchema.additionalProperties;
|
|
@@ -3582,7 +3599,10 @@ var init_dist = __esm({
|
|
|
3582
3599
|
}
|
|
3583
3600
|
finalSchema.properties = props;
|
|
3584
3601
|
}
|
|
3585
|
-
return {
|
|
3602
|
+
return {
|
|
3603
|
+
required: true,
|
|
3604
|
+
content: { [contentType]: { schema: finalSchema } }
|
|
3605
|
+
};
|
|
3586
3606
|
}
|
|
3587
3607
|
extractResponses(route) {
|
|
3588
3608
|
const descriptions = route.schema?.responseDescriptions ?? {};
|
|
@@ -3645,7 +3665,7 @@ var {
|
|
|
3645
3665
|
|
|
3646
3666
|
// package.json
|
|
3647
3667
|
var package_default = {
|
|
3648
|
-
version: "6.
|
|
3668
|
+
version: "6.2.0"};
|
|
3649
3669
|
var ALWAYS_EXTERNAL = ["uWebSockets.js"];
|
|
3650
3670
|
function getUserExternals(cwd) {
|
|
3651
3671
|
let pkgExternals = [];
|
|
@@ -3787,7 +3807,9 @@ function renderTable(columns, rows, terminalWidth = process.stdout.columns || 10
|
|
|
3787
3807
|
}
|
|
3788
3808
|
const lines = [];
|
|
3789
3809
|
lines.push(
|
|
3790
|
-
columns.map(
|
|
3810
|
+
columns.map(
|
|
3811
|
+
(c, i) => pc__default.default.bold(pc__default.default.gray(pad(c.header, widths[i], c.align ?? "left")))
|
|
3812
|
+
).join(" ")
|
|
3791
3813
|
);
|
|
3792
3814
|
const dividerLine = pc__default.default.dim("\u2500".repeat(total));
|
|
3793
3815
|
lines.push(dividerLine);
|
|
@@ -3947,7 +3969,11 @@ function checkHealthCheck(ctx) {
|
|
|
3947
3969
|
)
|
|
3948
3970
|
);
|
|
3949
3971
|
if (hasHealth) {
|
|
3950
|
-
add(ctx, {
|
|
3972
|
+
add(ctx, {
|
|
3973
|
+
severity: "ok",
|
|
3974
|
+
area: "ops",
|
|
3975
|
+
message: "health-check route registered"
|
|
3976
|
+
});
|
|
3951
3977
|
} else {
|
|
3952
3978
|
add(ctx, {
|
|
3953
3979
|
severity: "warn",
|
|
@@ -4068,7 +4094,10 @@ async function runCheck(entry) {
|
|
|
4068
4094
|
const tag = pc__default.default.dim(`[${f.area}]`);
|
|
4069
4095
|
console.log(` ${sym[f.severity]} ${tag} ${f.message}`);
|
|
4070
4096
|
if (f.hint && f.severity !== "ok") {
|
|
4071
|
-
const wrapped = f.hint.replace(
|
|
4097
|
+
const wrapped = f.hint.replace(
|
|
4098
|
+
/(.{1,80})(\s+|$)/g,
|
|
4099
|
+
"\n " + pc__default.default.dim("$1")
|
|
4100
|
+
);
|
|
4072
4101
|
console.log(wrapped);
|
|
4073
4102
|
}
|
|
4074
4103
|
}
|
|
@@ -4135,7 +4164,10 @@ var PluginRunner = class {
|
|
|
4135
4164
|
try {
|
|
4136
4165
|
await plugin.onBeforeGenerate(target, schema);
|
|
4137
4166
|
} catch (err) {
|
|
4138
|
-
console.error(
|
|
4167
|
+
console.error(
|
|
4168
|
+
`Plugin "${plugin.name}" onBeforeGenerate failed:`,
|
|
4169
|
+
err
|
|
4170
|
+
);
|
|
4139
4171
|
}
|
|
4140
4172
|
}
|
|
4141
4173
|
}
|
|
@@ -4192,14 +4224,18 @@ var Analyzer = class {
|
|
|
4192
4224
|
}
|
|
4193
4225
|
for (const ep of this.schema.endpoints) {
|
|
4194
4226
|
const ctx = `endpoint ${ep.operationId}`;
|
|
4195
|
-
for (const p of ep.pathParams || [])
|
|
4196
|
-
|
|
4197
|
-
for (const p of ep.
|
|
4227
|
+
for (const p of ep.pathParams || [])
|
|
4228
|
+
checkRef(p.type, `${ctx} path param ${p.name}`);
|
|
4229
|
+
for (const p of ep.queryParams || [])
|
|
4230
|
+
checkRef(p.type, `${ctx} query param ${p.name}`);
|
|
4231
|
+
for (const p of ep.headerParams || [])
|
|
4232
|
+
checkRef(p.type, `${ctx} header param ${p.name}`);
|
|
4198
4233
|
if (ep.requestBody) checkRef(ep.requestBody.type, `${ctx} request body`);
|
|
4199
4234
|
for (const [sc, resp] of Object.entries(ep.responses || {})) {
|
|
4200
4235
|
checkRef(resp.type, `${ctx} response ${sc}`);
|
|
4201
4236
|
}
|
|
4202
|
-
if (ep.streaming?.itemType)
|
|
4237
|
+
if (ep.streaming?.itemType)
|
|
4238
|
+
checkRef(ep.streaming.itemType, `${ctx} streaming item`);
|
|
4203
4239
|
if (ep.streaming?.eventTypes) {
|
|
4204
4240
|
for (const [evt, ref] of Object.entries(ep.streaming.eventTypes)) {
|
|
4205
4241
|
checkRef(ref, `${ctx} streaming event ${evt}`);
|
|
@@ -4236,7 +4272,11 @@ var Analyzer = class {
|
|
|
4236
4272
|
}
|
|
4237
4273
|
}
|
|
4238
4274
|
if (typeof type.additionalProperties === "object" && "ref" in type.additionalProperties) {
|
|
4239
|
-
this.checkFieldRef(
|
|
4275
|
+
this.checkFieldRef(
|
|
4276
|
+
type.additionalProperties,
|
|
4277
|
+
`${ctx}.additionalProperties`,
|
|
4278
|
+
depth + 1
|
|
4279
|
+
);
|
|
4240
4280
|
}
|
|
4241
4281
|
break;
|
|
4242
4282
|
case "array":
|
|
@@ -4277,8 +4317,18 @@ var Analyzer = class {
|
|
|
4277
4317
|
case "generic":
|
|
4278
4318
|
this.checkFieldRef(type.baseType, `${ctx}.base`, depth + 1);
|
|
4279
4319
|
for (const tp of type.typeParameters) {
|
|
4280
|
-
if (tp.constraint)
|
|
4281
|
-
|
|
4320
|
+
if (tp.constraint)
|
|
4321
|
+
this.checkFieldRef(
|
|
4322
|
+
tp.constraint,
|
|
4323
|
+
`${ctx}.${tp.name}.constraint`,
|
|
4324
|
+
depth + 1
|
|
4325
|
+
);
|
|
4326
|
+
if (tp.defaultType)
|
|
4327
|
+
this.checkFieldRef(
|
|
4328
|
+
tp.defaultType,
|
|
4329
|
+
`${ctx}.${tp.name}.default`,
|
|
4330
|
+
depth + 1
|
|
4331
|
+
);
|
|
4282
4332
|
}
|
|
4283
4333
|
break;
|
|
4284
4334
|
case "enum":
|
|
@@ -4332,7 +4382,9 @@ var Analyzer = class {
|
|
|
4332
4382
|
});
|
|
4333
4383
|
}
|
|
4334
4384
|
if (ep.transport === "rest" && Object.keys(ep.responses || {}).length > 0) {
|
|
4335
|
-
const hasSuccess = Object.keys(ep.responses || {}).some(
|
|
4385
|
+
const hasSuccess = Object.keys(ep.responses || {}).some(
|
|
4386
|
+
(c) => c.startsWith("2")
|
|
4387
|
+
);
|
|
4336
4388
|
if (!hasSuccess) {
|
|
4337
4389
|
this.diagnostics.push({
|
|
4338
4390
|
severity: "warning",
|
|
@@ -4342,8 +4394,12 @@ var Analyzer = class {
|
|
|
4342
4394
|
}
|
|
4343
4395
|
}
|
|
4344
4396
|
if (ep.path) {
|
|
4345
|
-
const pathParamNames = [...ep.path.matchAll(/\{([^}]+)\}/g)].map(
|
|
4346
|
-
|
|
4397
|
+
const pathParamNames = [...ep.path.matchAll(/\{([^}]+)\}/g)].map(
|
|
4398
|
+
(m) => m[1]
|
|
4399
|
+
);
|
|
4400
|
+
const declaredParams = new Set(
|
|
4401
|
+
(ep.pathParams || []).map((p) => p.name)
|
|
4402
|
+
);
|
|
4347
4403
|
for (const name of pathParamNames) {
|
|
4348
4404
|
if (!declaredParams.has(name)) {
|
|
4349
4405
|
this.diagnostics.push({
|
|
@@ -4386,7 +4442,9 @@ var Analyzer = class {
|
|
|
4386
4442
|
for (const member of type.members) {
|
|
4387
4443
|
const resolved = member.ref ? this.schema.types.get(member.ref) : member.inline;
|
|
4388
4444
|
if (resolved?.kind === "object") {
|
|
4389
|
-
const hasField = resolved.fields.some(
|
|
4445
|
+
const hasField = resolved.fields.some(
|
|
4446
|
+
(f) => f.name === disc.propertyName
|
|
4447
|
+
);
|
|
4390
4448
|
if (!hasField) {
|
|
4391
4449
|
this.diagnostics.push({
|
|
4392
4450
|
severity: "warning",
|
|
@@ -4454,7 +4512,10 @@ var Analyzer = class {
|
|
|
4454
4512
|
if (type.kind === "object") {
|
|
4455
4513
|
for (const field of type.fields) {
|
|
4456
4514
|
if (field.constraints?.pattern) {
|
|
4457
|
-
this.checkRegexSafety(
|
|
4515
|
+
this.checkRegexSafety(
|
|
4516
|
+
field.constraints.pattern,
|
|
4517
|
+
`${id}.${field.name}`
|
|
4518
|
+
);
|
|
4458
4519
|
}
|
|
4459
4520
|
}
|
|
4460
4521
|
}
|
|
@@ -4584,10 +4645,18 @@ var Normalizer = class {
|
|
|
4584
4645
|
if (member.ref) {
|
|
4585
4646
|
const target = this.schema.types.get(member.ref);
|
|
4586
4647
|
if (target) {
|
|
4587
|
-
toReplace.set(id, {
|
|
4648
|
+
toReplace.set(id, {
|
|
4649
|
+
...target,
|
|
4650
|
+
id,
|
|
4651
|
+
description: type.description ?? target.description
|
|
4652
|
+
});
|
|
4588
4653
|
}
|
|
4589
4654
|
} else if (member.inline) {
|
|
4590
|
-
toReplace.set(id, {
|
|
4655
|
+
toReplace.set(id, {
|
|
4656
|
+
...member.inline,
|
|
4657
|
+
id,
|
|
4658
|
+
description: type.description ?? member.inline.description
|
|
4659
|
+
});
|
|
4591
4660
|
}
|
|
4592
4661
|
}
|
|
4593
4662
|
if (type.kind === "union" && type.members.length === 1) {
|
|
@@ -4595,10 +4664,18 @@ var Normalizer = class {
|
|
|
4595
4664
|
if (member.ref) {
|
|
4596
4665
|
const target = this.schema.types.get(member.ref);
|
|
4597
4666
|
if (target) {
|
|
4598
|
-
toReplace.set(id, {
|
|
4667
|
+
toReplace.set(id, {
|
|
4668
|
+
...target,
|
|
4669
|
+
id,
|
|
4670
|
+
description: type.description ?? target.description
|
|
4671
|
+
});
|
|
4599
4672
|
}
|
|
4600
4673
|
} else if (member.inline) {
|
|
4601
|
-
toReplace.set(id, {
|
|
4674
|
+
toReplace.set(id, {
|
|
4675
|
+
...member.inline,
|
|
4676
|
+
id,
|
|
4677
|
+
description: type.description ?? member.inline.description
|
|
4678
|
+
});
|
|
4602
4679
|
}
|
|
4603
4680
|
}
|
|
4604
4681
|
if (type.kind === "intersection" && type.members.length > 1) {
|
|
@@ -4661,7 +4738,10 @@ var Normalizer = class {
|
|
|
4661
4738
|
for (const ep of this.schema.endpoints) {
|
|
4662
4739
|
const opPascal = toPascalCase(ep.operationId);
|
|
4663
4740
|
if (ep.requestBody?.type.inline) {
|
|
4664
|
-
ep.requestBody.type = promoteRef(
|
|
4741
|
+
ep.requestBody.type = promoteRef(
|
|
4742
|
+
ep.requestBody.type,
|
|
4743
|
+
`${opPascal}Request`
|
|
4744
|
+
);
|
|
4665
4745
|
}
|
|
4666
4746
|
for (const [code, resp] of Object.entries(ep.responses)) {
|
|
4667
4747
|
if (resp.type?.inline) {
|
|
@@ -4672,7 +4752,10 @@ var Normalizer = class {
|
|
|
4672
4752
|
const promoteParams = (params, prefix) => {
|
|
4673
4753
|
for (const param of params) {
|
|
4674
4754
|
if (param.type.inline && (param.type.inline.kind === "object" || param.type.inline.kind === "enum")) {
|
|
4675
|
-
param.type = promoteRef(
|
|
4755
|
+
param.type = promoteRef(
|
|
4756
|
+
param.type,
|
|
4757
|
+
`${opPascal}${toPascalCase(param.name)}${prefix}`
|
|
4758
|
+
);
|
|
4676
4759
|
}
|
|
4677
4760
|
}
|
|
4678
4761
|
};
|
|
@@ -4680,6 +4763,30 @@ var Normalizer = class {
|
|
|
4680
4763
|
promoteParams(ep.queryParams, "Query");
|
|
4681
4764
|
promoteParams(ep.headerParams, "Header");
|
|
4682
4765
|
}
|
|
4766
|
+
if (this.schema.events) {
|
|
4767
|
+
for (const event of this.schema.events) {
|
|
4768
|
+
const evPascal = toPascalCase(event.name);
|
|
4769
|
+
if (event.payload?.inline) {
|
|
4770
|
+
event.payload = promoteRef(event.payload, `${evPascal}Payload`);
|
|
4771
|
+
}
|
|
4772
|
+
if (event.ackPayload?.inline) {
|
|
4773
|
+
event.ackPayload = promoteRef(
|
|
4774
|
+
event.ackPayload,
|
|
4775
|
+
`${evPascal}AckPayload`
|
|
4776
|
+
);
|
|
4777
|
+
}
|
|
4778
|
+
if (event.headers) {
|
|
4779
|
+
for (const header of event.headers) {
|
|
4780
|
+
if (header.type.inline && (header.type.inline.kind === "object" || header.type.inline.kind === "enum")) {
|
|
4781
|
+
header.type = promoteRef(
|
|
4782
|
+
header.type,
|
|
4783
|
+
`${evPascal}${toPascalCase(header.name)}Header`
|
|
4784
|
+
);
|
|
4785
|
+
}
|
|
4786
|
+
}
|
|
4787
|
+
}
|
|
4788
|
+
}
|
|
4789
|
+
}
|
|
4683
4790
|
if (promoted > 0) {
|
|
4684
4791
|
this.diagnostics.push({
|
|
4685
4792
|
severity: "info",
|
|
@@ -4720,6 +4827,11 @@ var Normalizer = class {
|
|
|
4720
4827
|
for (const ep of this.schema.endpoints) {
|
|
4721
4828
|
this.walkEndpointRefs(ep, replaceRef);
|
|
4722
4829
|
}
|
|
4830
|
+
if (this.schema.events) {
|
|
4831
|
+
for (const event of this.schema.events) {
|
|
4832
|
+
this.walkEventRefs(event, replaceRef);
|
|
4833
|
+
}
|
|
4834
|
+
}
|
|
4723
4835
|
for (const id of toInline.keys()) {
|
|
4724
4836
|
this.schema.types.delete(id);
|
|
4725
4837
|
}
|
|
@@ -4759,6 +4871,11 @@ var Normalizer = class {
|
|
|
4759
4871
|
for (const ep of this.schema.endpoints) {
|
|
4760
4872
|
this.walkEndpointRefs(ep, replaceRef);
|
|
4761
4873
|
}
|
|
4874
|
+
if (this.schema.events) {
|
|
4875
|
+
for (const event of this.schema.events) {
|
|
4876
|
+
this.walkEventRefs(event, replaceRef);
|
|
4877
|
+
}
|
|
4878
|
+
}
|
|
4762
4879
|
for (const id of mergeMap.keys()) {
|
|
4763
4880
|
this.schema.types.delete(id);
|
|
4764
4881
|
}
|
|
@@ -4802,6 +4919,11 @@ var Normalizer = class {
|
|
|
4802
4919
|
for (const ep of this.schema.endpoints) {
|
|
4803
4920
|
this.walkEndpointRefs(ep, replaceRef);
|
|
4804
4921
|
}
|
|
4922
|
+
if (this.schema.events) {
|
|
4923
|
+
for (const event of this.schema.events) {
|
|
4924
|
+
this.walkEventRefs(event, replaceRef);
|
|
4925
|
+
}
|
|
4926
|
+
}
|
|
4805
4927
|
}
|
|
4806
4928
|
for (const [, type] of this.schema.types) {
|
|
4807
4929
|
if (type.kind === "object") {
|
|
@@ -4818,10 +4940,13 @@ var Normalizer = class {
|
|
|
4818
4940
|
case "object":
|
|
4819
4941
|
for (const field of type.fields) {
|
|
4820
4942
|
field.type = transform(field.type);
|
|
4821
|
-
if (field.type.inline)
|
|
4943
|
+
if (field.type.inline)
|
|
4944
|
+
this.walkTypeRefs(field.type.inline, transform);
|
|
4822
4945
|
}
|
|
4823
4946
|
if (typeof type.additionalProperties === "object" && "ref" in type.additionalProperties) {
|
|
4824
|
-
type.additionalProperties = transform(
|
|
4947
|
+
type.additionalProperties = transform(
|
|
4948
|
+
type.additionalProperties
|
|
4949
|
+
);
|
|
4825
4950
|
}
|
|
4826
4951
|
break;
|
|
4827
4952
|
case "array":
|
|
@@ -4858,22 +4983,52 @@ var Normalizer = class {
|
|
|
4858
4983
|
for (const resp of Object.values(ep.responses)) {
|
|
4859
4984
|
if (resp.type) resp.type = transform(resp.type);
|
|
4860
4985
|
}
|
|
4861
|
-
if (ep.streaming?.itemType)
|
|
4986
|
+
if (ep.streaming?.itemType)
|
|
4987
|
+
ep.streaming.itemType = transform(ep.streaming.itemType);
|
|
4862
4988
|
if (ep.streaming?.eventTypes) {
|
|
4863
4989
|
for (const [evt, ref] of Object.entries(ep.streaming.eventTypes)) {
|
|
4864
4990
|
ep.streaming.eventTypes[evt] = transform(ref);
|
|
4865
4991
|
}
|
|
4866
4992
|
}
|
|
4867
4993
|
}
|
|
4994
|
+
/** Walk all type refs within an event and apply a transform. */
|
|
4995
|
+
walkEventRefs(event, transform) {
|
|
4996
|
+
if (event.payload) {
|
|
4997
|
+
event.payload = transform(event.payload);
|
|
4998
|
+
if (event.payload.inline)
|
|
4999
|
+
this.walkTypeRefs(event.payload.inline, transform);
|
|
5000
|
+
}
|
|
5001
|
+
if (event.ackPayload) {
|
|
5002
|
+
event.ackPayload = transform(event.ackPayload);
|
|
5003
|
+
if (event.ackPayload.inline)
|
|
5004
|
+
this.walkTypeRefs(event.ackPayload.inline, transform);
|
|
5005
|
+
}
|
|
5006
|
+
if (event.headers) {
|
|
5007
|
+
for (const h of event.headers) {
|
|
5008
|
+
h.type = transform(h.type);
|
|
5009
|
+
if (h.type.inline) this.walkTypeRefs(h.type.inline, transform);
|
|
5010
|
+
}
|
|
5011
|
+
}
|
|
5012
|
+
}
|
|
4868
5013
|
/**
|
|
4869
5014
|
* Compute a canonical hash for a type, ignoring `id` and `description`
|
|
4870
5015
|
* so that structurally identical types with different names are merged.
|
|
4871
5016
|
*/
|
|
4872
5017
|
canonicalHash(type) {
|
|
4873
|
-
const {
|
|
5018
|
+
const {
|
|
5019
|
+
id: _id,
|
|
5020
|
+
description: _desc,
|
|
5021
|
+
metadata: _meta,
|
|
5022
|
+
lineage: _lin,
|
|
5023
|
+
...canonical
|
|
5024
|
+
} = type;
|
|
4874
5025
|
const str = JSON.stringify(canonical, (key, value) => {
|
|
4875
5026
|
if (value instanceof Map) {
|
|
4876
|
-
return Object.fromEntries(
|
|
5027
|
+
return Object.fromEntries(
|
|
5028
|
+
[...value.entries()].sort(
|
|
5029
|
+
(a, b) => String(a[0]).localeCompare(String(b[0]))
|
|
5030
|
+
)
|
|
5031
|
+
);
|
|
4877
5032
|
}
|
|
4878
5033
|
if (value instanceof Set) return [...value].sort();
|
|
4879
5034
|
return value;
|
|
@@ -5198,7 +5353,13 @@ var TypeGraph = class _TypeGraph {
|
|
|
5198
5353
|
const key = `${edge.from}->${edge.to}:${edge.relation}`;
|
|
5199
5354
|
if (!thisEdgeSet.has(key)) removedEdges.push(edge);
|
|
5200
5355
|
}
|
|
5201
|
-
return {
|
|
5356
|
+
return {
|
|
5357
|
+
addedNodes,
|
|
5358
|
+
removedNodes,
|
|
5359
|
+
addedEdges,
|
|
5360
|
+
removedEdges,
|
|
5361
|
+
modifiedNodes
|
|
5362
|
+
};
|
|
5202
5363
|
}
|
|
5203
5364
|
// ─── Serialization ──────────────────────────────────────────────────
|
|
5204
5365
|
/** Serialize the graph structure for caching (excludes full type data). */
|
|
@@ -5356,7 +5517,8 @@ var Optimizer = class {
|
|
|
5356
5517
|
if (resolved && resolved.kind === "scalar") {
|
|
5357
5518
|
const scalarType = resolved;
|
|
5358
5519
|
if (scalarType.scalar === "string") hasStringScalar = true;
|
|
5359
|
-
if (scalarType.scalar === "number" || scalarType.scalar === "integer")
|
|
5520
|
+
if (scalarType.scalar === "number" || scalarType.scalar === "integer")
|
|
5521
|
+
hasNumberScalar = true;
|
|
5360
5522
|
if (scalarType.scalar === "boolean") hasBooleanScalar = true;
|
|
5361
5523
|
}
|
|
5362
5524
|
}
|
|
@@ -5676,6 +5838,261 @@ var GeneratorRegistry = class {
|
|
|
5676
5838
|
}
|
|
5677
5839
|
};
|
|
5678
5840
|
|
|
5841
|
+
// src/sdk/ingest/asyncapi.ts
|
|
5842
|
+
var MAX_REF_DEPTH = 64;
|
|
5843
|
+
function ingestAsyncApi(spec, options = {}) {
|
|
5844
|
+
const as = spec;
|
|
5845
|
+
const diagnostics = [];
|
|
5846
|
+
const types = /* @__PURE__ */ new Map();
|
|
5847
|
+
const securitySchemes = /* @__PURE__ */ new Map();
|
|
5848
|
+
const events = [];
|
|
5849
|
+
const refStack = /* @__PURE__ */ new Set();
|
|
5850
|
+
let anonCounter2 = 0;
|
|
5851
|
+
function resolveRef(schema, depth = 0) {
|
|
5852
|
+
if (depth > MAX_REF_DEPTH) {
|
|
5853
|
+
diagnostics.push({
|
|
5854
|
+
severity: "error",
|
|
5855
|
+
code: "REF_DEPTH_EXCEEDED",
|
|
5856
|
+
message: `$ref resolution exceeded max depth (${MAX_REF_DEPTH})`
|
|
5857
|
+
});
|
|
5858
|
+
return { type: "object" };
|
|
5859
|
+
}
|
|
5860
|
+
if (!schema || typeof schema !== "object" || !schema.$ref) return schema;
|
|
5861
|
+
const ref = schema.$ref;
|
|
5862
|
+
if (refStack.has(ref)) return schema;
|
|
5863
|
+
refStack.add(ref);
|
|
5864
|
+
try {
|
|
5865
|
+
const resolved = resolveJsonPointer(
|
|
5866
|
+
as,
|
|
5867
|
+
ref
|
|
5868
|
+
);
|
|
5869
|
+
if (!resolved) {
|
|
5870
|
+
diagnostics.push({
|
|
5871
|
+
severity: "warning",
|
|
5872
|
+
code: "UNRESOLVED_REF",
|
|
5873
|
+
message: `Cannot resolve $ref: ${ref}`,
|
|
5874
|
+
location: ref
|
|
5875
|
+
});
|
|
5876
|
+
return { type: "object" };
|
|
5877
|
+
}
|
|
5878
|
+
const { $ref, ...rest } = schema;
|
|
5879
|
+
return { ...resolveRef(resolved, depth + 1), ...rest };
|
|
5880
|
+
} finally {
|
|
5881
|
+
refStack.delete(ref);
|
|
5882
|
+
}
|
|
5883
|
+
}
|
|
5884
|
+
function resolveJsonPointer(root, pointer) {
|
|
5885
|
+
const path12 = pointer.replace(/^#\//, "").split("/").map((s) => s.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
5886
|
+
let cur = root;
|
|
5887
|
+
for (const seg of path12) {
|
|
5888
|
+
if (cur === null || cur === void 0 || typeof cur !== "object")
|
|
5889
|
+
return void 0;
|
|
5890
|
+
cur = cur[seg];
|
|
5891
|
+
}
|
|
5892
|
+
return cur;
|
|
5893
|
+
}
|
|
5894
|
+
function refToTypeName(ref) {
|
|
5895
|
+
return ref.split("/").pop();
|
|
5896
|
+
}
|
|
5897
|
+
function capitalize2(s) {
|
|
5898
|
+
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
5899
|
+
}
|
|
5900
|
+
function schemaToTypeRef(schema, ctx) {
|
|
5901
|
+
if (!schema)
|
|
5902
|
+
return { inline: { id: "_any", kind: "scalar", scalar: "any" } };
|
|
5903
|
+
if (schema.$ref) {
|
|
5904
|
+
return { ref: refToTypeName(schema.$ref), nullable: schema.nullable };
|
|
5905
|
+
}
|
|
5906
|
+
const t = schemaToType(schema, ctx);
|
|
5907
|
+
if (t && types.has(t.id) && t.id !== ctx)
|
|
5908
|
+
return { ref: t.id, nullable: schema.nullable };
|
|
5909
|
+
return {
|
|
5910
|
+
inline: t ?? { id: "_unknown", kind: "scalar", scalar: "any" },
|
|
5911
|
+
nullable: schema.nullable
|
|
5912
|
+
};
|
|
5913
|
+
}
|
|
5914
|
+
function schemaToType(raw, ctx) {
|
|
5915
|
+
const s = resolveRef(raw);
|
|
5916
|
+
if (!s) return void 0;
|
|
5917
|
+
if (s.allOf?.length) {
|
|
5918
|
+
const name = ctx ?? `Intersection${++anonCounter2}`;
|
|
5919
|
+
return {
|
|
5920
|
+
id: name,
|
|
5921
|
+
kind: "intersection",
|
|
5922
|
+
members: s.allOf.map(
|
|
5923
|
+
(x, i) => schemaToTypeRef(x, `${name}_AllOf${i}`)
|
|
5924
|
+
),
|
|
5925
|
+
description: s.description,
|
|
5926
|
+
deprecated: s.deprecated
|
|
5927
|
+
};
|
|
5928
|
+
}
|
|
5929
|
+
if (s.oneOf?.length) {
|
|
5930
|
+
const name = ctx ?? `Union${++anonCounter2}`;
|
|
5931
|
+
return {
|
|
5932
|
+
id: name,
|
|
5933
|
+
kind: "union",
|
|
5934
|
+
members: s.oneOf.map(
|
|
5935
|
+
(x, i) => schemaToTypeRef(x, `${name}_OneOf${i}`)
|
|
5936
|
+
),
|
|
5937
|
+
description: s.description,
|
|
5938
|
+
deprecated: s.deprecated
|
|
5939
|
+
};
|
|
5940
|
+
}
|
|
5941
|
+
if (s.enum?.length) {
|
|
5942
|
+
const name = ctx ?? `Enum${++anonCounter2}`;
|
|
5943
|
+
const vt = typeof s.enum[0] === "number" ? "number" : "string";
|
|
5944
|
+
return {
|
|
5945
|
+
id: name,
|
|
5946
|
+
kind: "enum",
|
|
5947
|
+
valueType: vt,
|
|
5948
|
+
values: s.enum.map((v) => ({
|
|
5949
|
+
name: String(v),
|
|
5950
|
+
value: v
|
|
5951
|
+
})),
|
|
5952
|
+
description: s.description,
|
|
5953
|
+
deprecated: s.deprecated
|
|
5954
|
+
};
|
|
5955
|
+
}
|
|
5956
|
+
const st = Array.isArray(s.type) ? s.type[0] : s.type;
|
|
5957
|
+
if (st === "object" || s.properties) {
|
|
5958
|
+
const name = ctx ?? `Object${++anonCounter2}`;
|
|
5959
|
+
const reqSet = new Set(s.required ?? []);
|
|
5960
|
+
const fields = Object.entries(s.properties ?? {}).map(
|
|
5961
|
+
([pn, ps]) => {
|
|
5962
|
+
const rs = resolveRef(ps);
|
|
5963
|
+
return {
|
|
5964
|
+
name: pn,
|
|
5965
|
+
type: schemaToTypeRef(rs, `${name}_${capitalize2(pn)}`),
|
|
5966
|
+
required: reqSet.has(pn),
|
|
5967
|
+
description: rs.description,
|
|
5968
|
+
deprecated: rs.deprecated
|
|
5969
|
+
};
|
|
5970
|
+
}
|
|
5971
|
+
);
|
|
5972
|
+
return {
|
|
5973
|
+
id: name,
|
|
5974
|
+
kind: "object",
|
|
5975
|
+
fields,
|
|
5976
|
+
description: s.description,
|
|
5977
|
+
deprecated: s.deprecated
|
|
5978
|
+
};
|
|
5979
|
+
}
|
|
5980
|
+
if (st === "array") {
|
|
5981
|
+
const name = ctx ?? `Array${++anonCounter2}`;
|
|
5982
|
+
const items = s.items ? schemaToTypeRef(s.items, `${name}_Item`) : {
|
|
5983
|
+
inline: {
|
|
5984
|
+
id: "_any",
|
|
5985
|
+
kind: "scalar",
|
|
5986
|
+
scalar: "any"
|
|
5987
|
+
}
|
|
5988
|
+
};
|
|
5989
|
+
return {
|
|
5990
|
+
id: name,
|
|
5991
|
+
kind: "array",
|
|
5992
|
+
items,
|
|
5993
|
+
description: s.description
|
|
5994
|
+
};
|
|
5995
|
+
}
|
|
5996
|
+
if (st) {
|
|
5997
|
+
const name = ctx ?? `Scalar${++anonCounter2}`;
|
|
5998
|
+
return {
|
|
5999
|
+
id: name,
|
|
6000
|
+
kind: "scalar",
|
|
6001
|
+
scalar: st === "integer" ? "integer" : st === "number" ? "number" : st === "boolean" ? "boolean" : "string",
|
|
6002
|
+
format: s.format,
|
|
6003
|
+
description: s.description
|
|
6004
|
+
};
|
|
6005
|
+
}
|
|
6006
|
+
return {
|
|
6007
|
+
id: ctx ?? `Unknown${++anonCounter2}`,
|
|
6008
|
+
kind: "scalar",
|
|
6009
|
+
scalar: "any"
|
|
6010
|
+
};
|
|
6011
|
+
}
|
|
6012
|
+
if (as.components?.schemas) {
|
|
6013
|
+
for (const [name, schema] of Object.entries(as.components.schemas)) {
|
|
6014
|
+
const t = schemaToType(schema, name);
|
|
6015
|
+
if (t) types.set(name, t);
|
|
6016
|
+
}
|
|
6017
|
+
}
|
|
6018
|
+
if (as.channels) {
|
|
6019
|
+
for (const [channelName, channel] of Object.entries(as.channels)) {
|
|
6020
|
+
let transport = "event";
|
|
6021
|
+
const wsBinding = channel.bindings?.ws || channel.bindings?.websocket;
|
|
6022
|
+
if (wsBinding) {
|
|
6023
|
+
transport = "websocket";
|
|
6024
|
+
}
|
|
6025
|
+
const operations = [
|
|
6026
|
+
{ op: channel.publish, dir: "outbound", suffix: "Publish" },
|
|
6027
|
+
{ op: channel.subscribe, dir: "inbound", suffix: "Subscribe" }
|
|
6028
|
+
];
|
|
6029
|
+
for (const { op, dir, suffix } of operations) {
|
|
6030
|
+
if (!op) continue;
|
|
6031
|
+
const resolvedOp = resolveRef(op);
|
|
6032
|
+
const resolvedMsg = resolveRef(resolvedOp.message);
|
|
6033
|
+
if (resolvedMsg) {
|
|
6034
|
+
const payloadSchema = resolvedMsg.payload ? resolveRef(resolvedMsg.payload) : void 0;
|
|
6035
|
+
const payloadRef = payloadSchema ? schemaToTypeRef(
|
|
6036
|
+
payloadSchema,
|
|
6037
|
+
`${capitalize2(channelName.replace(/[^a-zA-Z0-9]/g, ""))}${suffix}Payload`
|
|
6038
|
+
) : void 0;
|
|
6039
|
+
const headers = [];
|
|
6040
|
+
if (channel.parameters) {
|
|
6041
|
+
for (const [pName, pVal] of Object.entries(channel.parameters)) {
|
|
6042
|
+
const rp = resolveRef(pVal);
|
|
6043
|
+
headers.push({
|
|
6044
|
+
name: pName,
|
|
6045
|
+
location: "header",
|
|
6046
|
+
type: schemaToTypeRef(rp?.schema || rp, `${pName}Param`),
|
|
6047
|
+
required: true,
|
|
6048
|
+
description: rp.description
|
|
6049
|
+
});
|
|
6050
|
+
}
|
|
6051
|
+
}
|
|
6052
|
+
events.push({
|
|
6053
|
+
name: resolvedOp.operationId || resolvedMsg.name || `${channelName.replace(/[^a-zA-Z0-9]/g, "_")}_${dir}`,
|
|
6054
|
+
description: resolvedOp.description || resolvedMsg.description || channel.description,
|
|
6055
|
+
transport,
|
|
6056
|
+
channel: channelName,
|
|
6057
|
+
direction: dir,
|
|
6058
|
+
payload: payloadRef,
|
|
6059
|
+
tags: resolvedMsg.tags?.map((t) => t.name) || [],
|
|
6060
|
+
security: []
|
|
6061
|
+
});
|
|
6062
|
+
}
|
|
6063
|
+
}
|
|
6064
|
+
}
|
|
6065
|
+
}
|
|
6066
|
+
const servers = [];
|
|
6067
|
+
if (as.servers) {
|
|
6068
|
+
for (const [sName, sVal] of Object.entries(as.servers)) {
|
|
6069
|
+
servers.push({
|
|
6070
|
+
url: sVal.url,
|
|
6071
|
+
description: `${sName} - ${sVal.description || sVal.protocol}`
|
|
6072
|
+
});
|
|
6073
|
+
}
|
|
6074
|
+
}
|
|
6075
|
+
return {
|
|
6076
|
+
schema: {
|
|
6077
|
+
info: {
|
|
6078
|
+
title: options.title ?? as.info.title,
|
|
6079
|
+
version: options.version ?? as.info.version,
|
|
6080
|
+
description: as.info.description,
|
|
6081
|
+
sourceFormat: "event",
|
|
6082
|
+
sourceVersion: as.asyncapi
|
|
6083
|
+
},
|
|
6084
|
+
types,
|
|
6085
|
+
endpoints: [],
|
|
6086
|
+
securitySchemes,
|
|
6087
|
+
servers,
|
|
6088
|
+
globalSecurity: [],
|
|
6089
|
+
events,
|
|
6090
|
+
reactiveContracts: []
|
|
6091
|
+
},
|
|
6092
|
+
diagnostics
|
|
6093
|
+
};
|
|
6094
|
+
}
|
|
6095
|
+
|
|
5679
6096
|
// src/sdk/ingest/axiomify-app.ts
|
|
5680
6097
|
function zodToJsonSchema(schema) {
|
|
5681
6098
|
const s = schema;
|
|
@@ -5702,7 +6119,7 @@ function synthesiseOperationId(method, path12) {
|
|
|
5702
6119
|
const parts = [];
|
|
5703
6120
|
for (const seg of path12.split("/")) {
|
|
5704
6121
|
if (!seg) continue;
|
|
5705
|
-
|
|
6122
|
+
const normalized = seg.replace(/^:/, "By-").replace(/\*/g, "All");
|
|
5706
6123
|
const cleanSeg = normalized.split(/[^a-zA-Z0-9]+/).filter(Boolean).map(capitalize).join("");
|
|
5707
6124
|
if (cleanSeg) parts.push(cleanSeg);
|
|
5708
6125
|
}
|
|
@@ -5720,17 +6137,22 @@ function jsonSchemaToIRType(js, ctx) {
|
|
|
5720
6137
|
id: ctx,
|
|
5721
6138
|
kind: "enum",
|
|
5722
6139
|
valueType: vt,
|
|
5723
|
-
values: jsEnum.map((v) => ({
|
|
6140
|
+
values: jsEnum.map((v) => ({
|
|
6141
|
+
name: String(v),
|
|
6142
|
+
value: v
|
|
6143
|
+
}))
|
|
5724
6144
|
};
|
|
5725
6145
|
}
|
|
5726
6146
|
if (jsType === "object" || jsProps) {
|
|
5727
6147
|
const reqSet = new Set(jsRequired ?? []);
|
|
5728
|
-
const fields = Object.entries(jsProps ?? {}).map(
|
|
5729
|
-
name,
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
6148
|
+
const fields = Object.entries(jsProps ?? {}).map(
|
|
6149
|
+
([name, prop]) => ({
|
|
6150
|
+
name,
|
|
6151
|
+
type: jsonSchemaToTypeRef(prop, `${ctx}_${capitalize(name)}`),
|
|
6152
|
+
required: reqSet.has(name),
|
|
6153
|
+
description: prop.description
|
|
6154
|
+
})
|
|
6155
|
+
);
|
|
5734
6156
|
return { id: ctx, kind: "object", fields };
|
|
5735
6157
|
}
|
|
5736
6158
|
if (jsType === "array" && jsItems) {
|
|
@@ -5740,8 +6162,16 @@ function jsonSchemaToIRType(js, ctx) {
|
|
|
5740
6162
|
items: jsonSchemaToTypeRef(jsItems, `${ctx}_Item`)
|
|
5741
6163
|
};
|
|
5742
6164
|
}
|
|
5743
|
-
const scalar = mapJsonSchemaScalar(
|
|
5744
|
-
|
|
6165
|
+
const scalar = mapJsonSchemaScalar(
|
|
6166
|
+
jsType ?? "any",
|
|
6167
|
+
js.format
|
|
6168
|
+
);
|
|
6169
|
+
return {
|
|
6170
|
+
id: ctx,
|
|
6171
|
+
kind: "scalar",
|
|
6172
|
+
scalar,
|
|
6173
|
+
format: js.format
|
|
6174
|
+
};
|
|
5745
6175
|
}
|
|
5746
6176
|
function jsonSchemaToTypeRef(js, ctx) {
|
|
5747
6177
|
const t = jsonSchemaToIRType(js, ctx);
|
|
@@ -5791,7 +6221,7 @@ function ingestAxiomifyApp(app, options = {}) {
|
|
|
5791
6221
|
const method = route.method ?? "GET";
|
|
5792
6222
|
const path12 = route.path ?? "/";
|
|
5793
6223
|
const schema = route.schema ?? {};
|
|
5794
|
-
|
|
6224
|
+
const rawOpId = schema.operationId ?? synthesiseOperationId(method, path12);
|
|
5795
6225
|
let opId = sanitizeIdentifier(rawOpId);
|
|
5796
6226
|
if (seenOps.has(opId)) {
|
|
5797
6227
|
let i = 2;
|
|
@@ -5851,7 +6281,9 @@ function ingestAxiomifyApp(app, options = {}) {
|
|
|
5851
6281
|
type: { ref: respType.id }
|
|
5852
6282
|
};
|
|
5853
6283
|
} else if (typeof schema.response === "object" && schema.response !== null && !isZodSchema(schema.response)) {
|
|
5854
|
-
for (const [code, zodSchema] of Object.entries(
|
|
6284
|
+
for (const [code, zodSchema] of Object.entries(
|
|
6285
|
+
schema.response
|
|
6286
|
+
)) {
|
|
5855
6287
|
if (isZodSchema(zodSchema)) {
|
|
5856
6288
|
const js = zodToJsonSchema(zodSchema);
|
|
5857
6289
|
const respType = jsonSchemaToIRType(js, `${opId}Response${code}`);
|
|
@@ -5866,7 +6298,10 @@ function ingestAxiomifyApp(app, options = {}) {
|
|
|
5866
6298
|
}
|
|
5867
6299
|
}
|
|
5868
6300
|
if (!Object.keys(responses).length) {
|
|
5869
|
-
responses["200"] = {
|
|
6301
|
+
responses["200"] = {
|
|
6302
|
+
statusCode: "200",
|
|
6303
|
+
description: "Successful response"
|
|
6304
|
+
};
|
|
5870
6305
|
}
|
|
5871
6306
|
const security = (schema.security ?? []).map(
|
|
5872
6307
|
(s) => {
|
|
@@ -5999,7 +6434,10 @@ async function ingestGraphQL(sdl, options = {}) {
|
|
|
5999
6434
|
ID: "string"
|
|
6000
6435
|
};
|
|
6001
6436
|
if (scalarMap[name]) {
|
|
6002
|
-
return {
|
|
6437
|
+
return {
|
|
6438
|
+
inline: { id: name, kind: "scalar", scalar: scalarMap[name] },
|
|
6439
|
+
nullable: true
|
|
6440
|
+
};
|
|
6003
6441
|
}
|
|
6004
6442
|
return { ref: name, nullable: true };
|
|
6005
6443
|
}
|
|
@@ -6008,17 +6446,19 @@ async function ingestGraphQL(sdl, options = {}) {
|
|
|
6008
6446
|
if (["String", "Int", "Float", "Boolean", "ID"].includes(name)) continue;
|
|
6009
6447
|
if (isObjectType(gqlType) || isInputObjectType(gqlType) || isInterfaceType(gqlType)) {
|
|
6010
6448
|
const gqlFields = gqlType.getFields();
|
|
6011
|
-
const fields = Object.entries(gqlFields).map(
|
|
6012
|
-
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6449
|
+
const fields = Object.entries(gqlFields).map(
|
|
6450
|
+
([fieldName, field]) => {
|
|
6451
|
+
const typeRef = gqlTypeToRef(field.type);
|
|
6452
|
+
return {
|
|
6453
|
+
name: fieldName,
|
|
6454
|
+
type: typeRef,
|
|
6455
|
+
required: !typeRef.nullable,
|
|
6456
|
+
description: field.description ?? void 0,
|
|
6457
|
+
deprecated: !!field.deprecationReason,
|
|
6458
|
+
deprecationReason: field.deprecationReason ?? void 0
|
|
6459
|
+
};
|
|
6460
|
+
}
|
|
6461
|
+
);
|
|
6022
6462
|
const irType = {
|
|
6023
6463
|
id: name,
|
|
6024
6464
|
kind: "object",
|
|
@@ -6119,7 +6559,7 @@ async function ingestGraphQL(sdl, options = {}) {
|
|
|
6119
6559
|
}
|
|
6120
6560
|
|
|
6121
6561
|
// src/sdk/ingest/openapi.ts
|
|
6122
|
-
var
|
|
6562
|
+
var MAX_REF_DEPTH2 = 64;
|
|
6123
6563
|
function ingestOpenApi(spec, options = {}) {
|
|
6124
6564
|
const oa = spec;
|
|
6125
6565
|
const diagnostics = [];
|
|
@@ -6129,11 +6569,11 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
6129
6569
|
const refStack = /* @__PURE__ */ new Set();
|
|
6130
6570
|
let anonCounter2 = 0;
|
|
6131
6571
|
function resolveRef(schema, depth = 0) {
|
|
6132
|
-
if (depth >
|
|
6572
|
+
if (depth > MAX_REF_DEPTH2) {
|
|
6133
6573
|
diagnostics.push({
|
|
6134
6574
|
severity: "error",
|
|
6135
6575
|
code: "REF_DEPTH_EXCEEDED",
|
|
6136
|
-
message: `$ref resolution exceeded max depth (${
|
|
6576
|
+
message: `$ref resolution exceeded max depth (${MAX_REF_DEPTH2})`
|
|
6137
6577
|
});
|
|
6138
6578
|
return { type: "object" };
|
|
6139
6579
|
}
|
|
@@ -6142,7 +6582,10 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
6142
6582
|
if (refStack.has(ref)) return schema;
|
|
6143
6583
|
refStack.add(ref);
|
|
6144
6584
|
try {
|
|
6145
|
-
const resolved = resolveJsonPointer(
|
|
6585
|
+
const resolved = resolveJsonPointer(
|
|
6586
|
+
oa,
|
|
6587
|
+
ref
|
|
6588
|
+
);
|
|
6146
6589
|
if (!resolved) {
|
|
6147
6590
|
diagnostics.push({
|
|
6148
6591
|
severity: "warning",
|
|
@@ -6161,7 +6604,8 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
6161
6604
|
const path12 = pointer.replace(/^#\//, "").split("/").map((s) => s.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
6162
6605
|
let cur = root;
|
|
6163
6606
|
for (const seg of path12) {
|
|
6164
|
-
if (cur === null || cur === void 0 || typeof cur !== "object")
|
|
6607
|
+
if (cur === null || cur === void 0 || typeof cur !== "object")
|
|
6608
|
+
return void 0;
|
|
6165
6609
|
cur = cur[seg];
|
|
6166
6610
|
}
|
|
6167
6611
|
return cur;
|
|
@@ -6192,8 +6636,12 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
6192
6636
|
return { ref: refToTypeName(schema.$ref), nullable: schema.nullable };
|
|
6193
6637
|
}
|
|
6194
6638
|
const t = schemaToType(schema, ctx);
|
|
6195
|
-
if (t && types.has(t.id) && t.id !== ctx)
|
|
6196
|
-
|
|
6639
|
+
if (t && types.has(t.id) && t.id !== ctx)
|
|
6640
|
+
return { ref: t.id, nullable: schema.nullable };
|
|
6641
|
+
return {
|
|
6642
|
+
inline: t ?? { id: "_unknown", kind: "scalar", scalar: "any" },
|
|
6643
|
+
nullable: schema.nullable
|
|
6644
|
+
};
|
|
6197
6645
|
}
|
|
6198
6646
|
function schemaToType(raw, ctx) {
|
|
6199
6647
|
const s = resolveRef(raw);
|
|
@@ -6237,7 +6685,10 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
6237
6685
|
id: name,
|
|
6238
6686
|
kind: "enum",
|
|
6239
6687
|
valueType: vt,
|
|
6240
|
-
values: s.enum.map((v) => ({
|
|
6688
|
+
values: s.enum.map((v) => ({
|
|
6689
|
+
name: String(v),
|
|
6690
|
+
value: v
|
|
6691
|
+
})),
|
|
6241
6692
|
description: s.description,
|
|
6242
6693
|
deprecated: s.deprecated
|
|
6243
6694
|
};
|
|
@@ -6246,24 +6697,29 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
6246
6697
|
if (st === "object" || s.properties) {
|
|
6247
6698
|
const name = ctx ?? `Object${++anonCounter2}`;
|
|
6248
6699
|
const reqSet = new Set(s.required ?? []);
|
|
6249
|
-
const fields = Object.entries(s.properties ?? {}).map(
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
|
|
6253
|
-
|
|
6254
|
-
|
|
6255
|
-
|
|
6256
|
-
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
|
|
6263
|
-
|
|
6700
|
+
const fields = Object.entries(s.properties ?? {}).map(
|
|
6701
|
+
([pn, ps]) => {
|
|
6702
|
+
const rs = resolveRef(ps);
|
|
6703
|
+
const constraints = extractConstraints(rs);
|
|
6704
|
+
return {
|
|
6705
|
+
name: pn,
|
|
6706
|
+
type: schemaToTypeRef(rs, `${name}_${capitalize2(pn)}`),
|
|
6707
|
+
required: reqSet.has(pn),
|
|
6708
|
+
description: rs.description,
|
|
6709
|
+
deprecated: rs.deprecated,
|
|
6710
|
+
readOnly: rs.readOnly,
|
|
6711
|
+
writeOnly: rs.writeOnly,
|
|
6712
|
+
example: rs.example,
|
|
6713
|
+
constraints: Object.keys(constraints).length ? constraints : void 0
|
|
6714
|
+
};
|
|
6715
|
+
}
|
|
6716
|
+
);
|
|
6264
6717
|
let ap;
|
|
6265
6718
|
if (s.additionalProperties !== void 0) {
|
|
6266
|
-
ap = typeof s.additionalProperties === "boolean" ? s.additionalProperties : schemaToTypeRef(
|
|
6719
|
+
ap = typeof s.additionalProperties === "boolean" ? s.additionalProperties : schemaToTypeRef(
|
|
6720
|
+
s.additionalProperties,
|
|
6721
|
+
`${name}_AdditionalProps`
|
|
6722
|
+
);
|
|
6267
6723
|
}
|
|
6268
6724
|
return {
|
|
6269
6725
|
id: name,
|
|
@@ -6280,7 +6736,13 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
6280
6736
|
}
|
|
6281
6737
|
if (st === "array") {
|
|
6282
6738
|
const name = ctx ?? `Array${++anonCounter2}`;
|
|
6283
|
-
const items = s.items ? schemaToTypeRef(s.items, `${name}_Item`) : {
|
|
6739
|
+
const items = s.items ? schemaToTypeRef(s.items, `${name}_Item`) : {
|
|
6740
|
+
inline: {
|
|
6741
|
+
id: "_any",
|
|
6742
|
+
kind: "scalar",
|
|
6743
|
+
scalar: "any"
|
|
6744
|
+
}
|
|
6745
|
+
};
|
|
6284
6746
|
return {
|
|
6285
6747
|
id: name,
|
|
6286
6748
|
kind: "array",
|
|
@@ -6305,7 +6767,11 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
6305
6767
|
constraints: Object.keys(constraints).length ? constraints : void 0
|
|
6306
6768
|
};
|
|
6307
6769
|
}
|
|
6308
|
-
return {
|
|
6770
|
+
return {
|
|
6771
|
+
id: ctx ?? `Unknown${++anonCounter2}`,
|
|
6772
|
+
kind: "scalar",
|
|
6773
|
+
scalar: "any"
|
|
6774
|
+
};
|
|
6309
6775
|
}
|
|
6310
6776
|
function mapScalar(type, format) {
|
|
6311
6777
|
switch (type) {
|
|
@@ -6348,8 +6814,10 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
6348
6814
|
if (s.pattern !== void 0) c.pattern = s.pattern;
|
|
6349
6815
|
if (s.minimum !== void 0) c.minimum = s.minimum;
|
|
6350
6816
|
if (s.maximum !== void 0) c.maximum = s.maximum;
|
|
6351
|
-
if (s.exclusiveMinimum !== void 0)
|
|
6352
|
-
|
|
6817
|
+
if (s.exclusiveMinimum !== void 0)
|
|
6818
|
+
c.exclusiveMinimum = s.exclusiveMinimum;
|
|
6819
|
+
if (s.exclusiveMaximum !== void 0)
|
|
6820
|
+
c.exclusiveMaximum = s.exclusiveMaximum;
|
|
6353
6821
|
if (s.multipleOf !== void 0) c.multipleOf = s.multipleOf;
|
|
6354
6822
|
return c;
|
|
6355
6823
|
}
|
|
@@ -6357,7 +6825,9 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
6357
6825
|
const t = schemaToType(schema, name);
|
|
6358
6826
|
if (t) types.set(name, t);
|
|
6359
6827
|
}
|
|
6360
|
-
for (const [name, scheme] of Object.entries(
|
|
6828
|
+
for (const [name, scheme] of Object.entries(
|
|
6829
|
+
oa.components?.securitySchemes ?? {}
|
|
6830
|
+
)) {
|
|
6361
6831
|
securitySchemes.set(name, {
|
|
6362
6832
|
name,
|
|
6363
6833
|
type: scheme.type,
|
|
@@ -6371,7 +6841,15 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
6371
6841
|
}
|
|
6372
6842
|
const seenOps = /* @__PURE__ */ new Set();
|
|
6373
6843
|
for (const [path12, pathItem] of Object.entries(oa.paths ?? {})) {
|
|
6374
|
-
for (const method of [
|
|
6844
|
+
for (const method of [
|
|
6845
|
+
"get",
|
|
6846
|
+
"post",
|
|
6847
|
+
"put",
|
|
6848
|
+
"patch",
|
|
6849
|
+
"delete",
|
|
6850
|
+
"options",
|
|
6851
|
+
"head"
|
|
6852
|
+
]) {
|
|
6375
6853
|
const op = pathItem[method];
|
|
6376
6854
|
if (!op) continue;
|
|
6377
6855
|
let opId = op.operationId ?? synthesiseOperationId2(method, path12);
|
|
@@ -6423,12 +6901,18 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
6423
6901
|
let successResponse;
|
|
6424
6902
|
let streamingContract = void 0;
|
|
6425
6903
|
for (const [sc, resp] of Object.entries(op.responses ?? {})) {
|
|
6426
|
-
const irR = {
|
|
6904
|
+
const irR = {
|
|
6905
|
+
statusCode: sc,
|
|
6906
|
+
description: resp.description ?? `Response ${sc}`
|
|
6907
|
+
};
|
|
6427
6908
|
if (resp.content) {
|
|
6428
6909
|
const [ct, mt] = Object.entries(resp.content)[0] ?? [];
|
|
6429
6910
|
if (ct && mt?.schema) {
|
|
6430
6911
|
irR.contentType = ct;
|
|
6431
|
-
irR.type = schemaToTypeRef(
|
|
6912
|
+
irR.type = schemaToTypeRef(
|
|
6913
|
+
resolveRef(mt.schema),
|
|
6914
|
+
`${opId}Response${sc}`
|
|
6915
|
+
);
|
|
6432
6916
|
if (ct === "text/event-stream") {
|
|
6433
6917
|
streamingContract = {
|
|
6434
6918
|
transport: "sse",
|
|
@@ -6442,7 +6926,13 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
6442
6926
|
irR.headers = Object.entries(resp.headers).map(([n, h]) => ({
|
|
6443
6927
|
name: n,
|
|
6444
6928
|
location: "header",
|
|
6445
|
-
type: h.schema ? schemaToTypeRef(resolveRef(h.schema)) : {
|
|
6929
|
+
type: h.schema ? schemaToTypeRef(resolveRef(h.schema)) : {
|
|
6930
|
+
inline: {
|
|
6931
|
+
id: "_string",
|
|
6932
|
+
kind: "scalar",
|
|
6933
|
+
scalar: "string"
|
|
6934
|
+
}
|
|
6935
|
+
},
|
|
6446
6936
|
required: false,
|
|
6447
6937
|
description: h.description
|
|
6448
6938
|
}));
|
|
@@ -6521,7 +7011,9 @@ var DartTypeEmitter = class {
|
|
|
6521
7011
|
const sortedIds = this.graph.topologicalSort();
|
|
6522
7012
|
emitter.line(`// GENERATED CODE - DO NOT MODIFY BY HAND`);
|
|
6523
7013
|
emitter.line();
|
|
6524
|
-
emitter.line(
|
|
7014
|
+
emitter.line(
|
|
7015
|
+
`import 'package:freezed_annotation/freezed_annotation.dart';`
|
|
7016
|
+
);
|
|
6525
7017
|
emitter.line();
|
|
6526
7018
|
emitter.line(`part 'types.freezed.dart';`);
|
|
6527
7019
|
emitter.line(`part 'types.g.dart';`);
|
|
@@ -6541,26 +7033,36 @@ var DartTypeEmitter = class {
|
|
|
6541
7033
|
case "object":
|
|
6542
7034
|
emitter.line(`@freezed`);
|
|
6543
7035
|
emitter.block(`class ${type.id} with _$${type.id} {`, `}`, () => {
|
|
6544
|
-
emitter.block(
|
|
6545
|
-
|
|
6546
|
-
|
|
6547
|
-
|
|
6548
|
-
const
|
|
6549
|
-
|
|
6550
|
-
|
|
6551
|
-
|
|
7036
|
+
emitter.block(
|
|
7037
|
+
`const factory ${type.id}({`,
|
|
7038
|
+
`}) = _${type.id};`,
|
|
7039
|
+
() => {
|
|
7040
|
+
for (const field of type.fields) {
|
|
7041
|
+
if (field.description) this.emitDoc(emitter, field.description);
|
|
7042
|
+
const dartType = this.renderTypeRef(field.type);
|
|
7043
|
+
const opt = field.required ? "" : "?";
|
|
7044
|
+
const req = field.required ? "required " : "";
|
|
7045
|
+
if (field.name !== this.toCamelCase(field.name)) {
|
|
7046
|
+
emitter.line(`@JsonKey(name: '${field.name}')`);
|
|
7047
|
+
}
|
|
7048
|
+
emitter.line(
|
|
7049
|
+
`${req}${dartType}${opt} ${this.toCamelCase(field.name)},`
|
|
7050
|
+
);
|
|
6552
7051
|
}
|
|
6553
|
-
emitter.line(`${req}${dartType}${opt} ${this.toCamelCase(field.name)},`);
|
|
6554
7052
|
}
|
|
6555
|
-
|
|
7053
|
+
);
|
|
6556
7054
|
emitter.line();
|
|
6557
|
-
emitter.line(
|
|
7055
|
+
emitter.line(
|
|
7056
|
+
`factory ${type.id}.fromJson(Map<String, dynamic> json) => _$${type.id}FromJson(json);`
|
|
7057
|
+
);
|
|
6558
7058
|
});
|
|
6559
7059
|
break;
|
|
6560
7060
|
case "enum":
|
|
6561
7061
|
emitter.block(`enum ${type.id} {`, `}`, () => {
|
|
6562
7062
|
for (const v of type.values) {
|
|
6563
|
-
emitter.line(
|
|
7063
|
+
emitter.line(
|
|
7064
|
+
`@JsonValue(${typeof v.value === "string" ? `'${v.value}'` : v.value})`
|
|
7065
|
+
);
|
|
6564
7066
|
emitter.line(`${this.toCamelCase(v.name)},`);
|
|
6565
7067
|
}
|
|
6566
7068
|
});
|
|
@@ -6572,23 +7074,31 @@ var DartTypeEmitter = class {
|
|
|
6572
7074
|
const member = type.members[i];
|
|
6573
7075
|
const name = member.ref ? member.ref : `Value${i}`;
|
|
6574
7076
|
const memberType = this.renderTypeRef(member);
|
|
6575
|
-
emitter.line(
|
|
7077
|
+
emitter.line(
|
|
7078
|
+
`const factory ${type.id}.${this.toCamelCase(name)}(${memberType} value) = _${type.id}${name};`
|
|
7079
|
+
);
|
|
6576
7080
|
}
|
|
6577
7081
|
emitter.line();
|
|
6578
|
-
emitter.line(
|
|
7082
|
+
emitter.line(
|
|
7083
|
+
`factory ${type.id}.fromJson(Map<String, dynamic> json) => _$${type.id}FromJson(json);`
|
|
7084
|
+
);
|
|
6579
7085
|
});
|
|
6580
7086
|
break;
|
|
6581
7087
|
case "intersection":
|
|
6582
7088
|
emitter.line(`typedef ${type.id} = Map<String, dynamic>;`);
|
|
6583
7089
|
break;
|
|
6584
7090
|
case "array":
|
|
6585
|
-
emitter.line(
|
|
7091
|
+
emitter.line(
|
|
7092
|
+
`typedef ${type.id} = List<${this.renderTypeRef(type.items)}>;`
|
|
7093
|
+
);
|
|
6586
7094
|
break;
|
|
6587
7095
|
case "scalar":
|
|
6588
7096
|
emitter.line(`typedef ${type.id} = ${this.renderScalar(type.scalar)};`);
|
|
6589
7097
|
break;
|
|
6590
7098
|
case "map":
|
|
6591
|
-
emitter.line(
|
|
7099
|
+
emitter.line(
|
|
7100
|
+
`typedef ${type.id} = Map<String, ${this.renderTypeRef(type.valueType)}>;`
|
|
7101
|
+
);
|
|
6592
7102
|
break;
|
|
6593
7103
|
case "tuple":
|
|
6594
7104
|
emitter.line(`typedef ${type.id} = List<dynamic>; // Tuple`);
|
|
@@ -6602,8 +7112,10 @@ var DartTypeEmitter = class {
|
|
|
6602
7112
|
let t = "dynamic";
|
|
6603
7113
|
if (ref.ref) t = ref.ref;
|
|
6604
7114
|
else if (ref.inline) {
|
|
6605
|
-
if (ref.inline.kind === "scalar")
|
|
6606
|
-
|
|
7115
|
+
if (ref.inline.kind === "scalar")
|
|
7116
|
+
t = this.renderScalar(ref.inline.scalar);
|
|
7117
|
+
else if (ref.inline.kind === "array")
|
|
7118
|
+
t = `List<${this.renderTypeRef(ref.inline.items)}>`;
|
|
6607
7119
|
}
|
|
6608
7120
|
if (ref.isArray) t = `List<${t}>`;
|
|
6609
7121
|
return t;
|
|
@@ -6652,18 +7164,28 @@ var DartClientEmitter = class {
|
|
|
6652
7164
|
emitter.line(`import 'package:riverpod/riverpod.dart';`);
|
|
6653
7165
|
emitter.line(`import 'types.dart';`);
|
|
6654
7166
|
emitter.line();
|
|
6655
|
-
emitter.line(
|
|
6656
|
-
|
|
7167
|
+
emitter.line(
|
|
7168
|
+
`final apiClientProvider = Provider<${this.className}>((ref) {`
|
|
7169
|
+
);
|
|
7170
|
+
emitter.line(
|
|
7171
|
+
` throw UnimplementedError('Configure and override apiClientProvider in your provider container');`
|
|
7172
|
+
);
|
|
6657
7173
|
emitter.line(`});`);
|
|
6658
7174
|
emitter.line();
|
|
6659
7175
|
emitter.block(`class ${this.className} {`, `}`, () => {
|
|
6660
7176
|
emitter.line(`final Dio _dio;`);
|
|
6661
7177
|
emitter.line();
|
|
6662
|
-
emitter.block(
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
7178
|
+
emitter.block(
|
|
7179
|
+
`${this.className}({required String baseUrl, String? token, Dio? dio}) : _dio = dio ?? Dio(BaseOptions(baseUrl: baseUrl)) {`,
|
|
7180
|
+
`}`,
|
|
7181
|
+
() => {
|
|
7182
|
+
emitter.block(`if (token != null) {`, `}`, () => {
|
|
7183
|
+
emitter.line(
|
|
7184
|
+
`_dio.options.headers['Authorization'] = 'Bearer $token';`
|
|
7185
|
+
);
|
|
7186
|
+
});
|
|
7187
|
+
}
|
|
7188
|
+
);
|
|
6667
7189
|
emitter.line();
|
|
6668
7190
|
for (const ep of this.schema.endpoints) {
|
|
6669
7191
|
if (ep.transport !== "rest") continue;
|
|
@@ -6675,51 +7197,69 @@ var DartClientEmitter = class {
|
|
|
6675
7197
|
}
|
|
6676
7198
|
emitMethod(emitter, ep) {
|
|
6677
7199
|
const methodName = this.toCamelCase(ep.operationId);
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
7200
|
+
const reqArgs = ep.pathParams.map(
|
|
7201
|
+
(p) => `required ${this.renderTypeRef(p.type)} ${this.toCamelCase(p.name)}`
|
|
7202
|
+
);
|
|
7203
|
+
const optArgs = ep.queryParams.map(
|
|
7204
|
+
(p) => `${this.renderTypeRef(p.type)}? ${this.toCamelCase(p.name)}`
|
|
7205
|
+
);
|
|
7206
|
+
if (ep.requestBody)
|
|
7207
|
+
reqArgs.push(`required ${this.renderTypeRef(ep.requestBody.type)} body`);
|
|
6681
7208
|
const allArgs = [...reqArgs, ...optArgs].join(", ");
|
|
6682
7209
|
const retType = this.buildResponseType(ep);
|
|
6683
|
-
emitter.block(
|
|
6684
|
-
|
|
6685
|
-
|
|
6686
|
-
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
emitter.
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
7210
|
+
emitter.block(
|
|
7211
|
+
`Future<${retType}> ${methodName}(${allArgs.length > 0 ? "{" + allArgs + "}" : ""}) async {`,
|
|
7212
|
+
`}`,
|
|
7213
|
+
() => {
|
|
7214
|
+
const method = ep.method?.toUpperCase() || "GET";
|
|
7215
|
+
const pathTemplate = ep.path || "/";
|
|
7216
|
+
let pathExpr = pathTemplate;
|
|
7217
|
+
for (const p of ep.pathParams) {
|
|
7218
|
+
pathExpr = pathExpr.replace(
|
|
7219
|
+
`{${p.name}}`,
|
|
7220
|
+
`$${this.toCamelCase(p.name)}`
|
|
7221
|
+
);
|
|
7222
|
+
}
|
|
7223
|
+
if (ep.queryParams.length > 0) {
|
|
7224
|
+
emitter.line(`final queryParameters = <String, dynamic>{`);
|
|
7225
|
+
for (const q of ep.queryParams) {
|
|
7226
|
+
emitter.line(` '${q.name}': ${this.toCamelCase(q.name)},`);
|
|
7227
|
+
}
|
|
7228
|
+
emitter.line(`};`);
|
|
7229
|
+
}
|
|
7230
|
+
emitter.block(`try {`, `}`, () => {
|
|
7231
|
+
const queryArg = ep.queryParams.length > 0 ? ", queryParameters: queryParameters" : "";
|
|
7232
|
+
const bodyArg = ep.requestBody ? ", data: body.toJson()" : "";
|
|
7233
|
+
emitter.line(`final response = await _dio.request(`);
|
|
7234
|
+
emitter.line(` '${pathExpr}',`);
|
|
7235
|
+
emitter.line(` options: Options(method: '${method}'),`);
|
|
7236
|
+
emitter.line(` ${queryArg}${bodyArg}`);
|
|
7237
|
+
emitter.line(`);`);
|
|
7238
|
+
if (retType !== "void") {
|
|
7239
|
+
const success = ep.successResponse;
|
|
7240
|
+
const ref = success && ep.responses[success]?.type?.ref;
|
|
7241
|
+
if (ref) {
|
|
7242
|
+
if (ep.responses[success].type?.isArray) {
|
|
7243
|
+
emitter.line(
|
|
7244
|
+
`return (response.data as List).map((e) => ${ref}.fromJson(e as Map<String, dynamic>)).toList();`
|
|
7245
|
+
);
|
|
7246
|
+
} else {
|
|
7247
|
+
emitter.line(
|
|
7248
|
+
`return ${ref}.fromJson(response.data as Map<String, dynamic>);`
|
|
7249
|
+
);
|
|
7250
|
+
}
|
|
6711
7251
|
} else {
|
|
6712
|
-
emitter.line(`return
|
|
7252
|
+
emitter.line(`return response.data;`);
|
|
6713
7253
|
}
|
|
6714
|
-
} else {
|
|
6715
|
-
emitter.line(`return response.data;`);
|
|
6716
7254
|
}
|
|
6717
|
-
}
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
7255
|
+
});
|
|
7256
|
+
emitter.block(`on DioException catch (e) {`, `}`, () => {
|
|
7257
|
+
emitter.line(
|
|
7258
|
+
`throw Exception('Request ${methodName} failed: \${e.message}');`
|
|
7259
|
+
);
|
|
7260
|
+
});
|
|
7261
|
+
}
|
|
7262
|
+
);
|
|
6723
7263
|
}
|
|
6724
7264
|
buildResponseType(ep) {
|
|
6725
7265
|
const success = ep.successResponse;
|
|
@@ -6754,7 +7294,9 @@ var DartGenerator = class extends Generator {
|
|
|
6754
7294
|
this.addFile("lib/types.dart", typeEmitter.emitAll());
|
|
6755
7295
|
const clientEmitter = new DartClientEmitter(this.schema, "ApiClient");
|
|
6756
7296
|
this.addFile("lib/client.dart", clientEmitter.emitAll());
|
|
6757
|
-
this.addFile(
|
|
7297
|
+
this.addFile(
|
|
7298
|
+
"pubspec.yaml",
|
|
7299
|
+
`name: ${this.options.packageName}
|
|
6758
7300
|
version: ${this.options.version || "1.0.0"}
|
|
6759
7301
|
environment:
|
|
6760
7302
|
sdk: '>=3.0.0 <4.0.0'
|
|
@@ -6769,7 +7311,8 @@ dev_dependencies:
|
|
|
6769
7311
|
build_runner: ^2.4.6
|
|
6770
7312
|
freezed: ^2.4.5
|
|
6771
7313
|
json_serializable: ^6.7.1
|
|
6772
|
-
`
|
|
7314
|
+
`
|
|
7315
|
+
);
|
|
6773
7316
|
return this.files;
|
|
6774
7317
|
}
|
|
6775
7318
|
};
|
|
@@ -6816,7 +7359,9 @@ var GoTypeEmitter = class {
|
|
|
6816
7359
|
emitter.line(`${this.capitalize(field.name)} ${goType} ${tag}`);
|
|
6817
7360
|
}
|
|
6818
7361
|
if (type.additionalProperties) {
|
|
6819
|
-
emitter.line(
|
|
7362
|
+
emitter.line(
|
|
7363
|
+
`AdditionalProperties map[string]interface{} \`json:"-"\``
|
|
7364
|
+
);
|
|
6820
7365
|
}
|
|
6821
7366
|
});
|
|
6822
7367
|
break;
|
|
@@ -6826,7 +7371,9 @@ var GoTypeEmitter = class {
|
|
|
6826
7371
|
emitter.block(`const (`, `)`, () => {
|
|
6827
7372
|
for (const v of type.values) {
|
|
6828
7373
|
const val = typeof v.value === "string" ? `"${v.value}"` : v.value;
|
|
6829
|
-
emitter.line(
|
|
7374
|
+
emitter.line(
|
|
7375
|
+
`${type.id}_${this.capitalize(v.name)} ${type.id} = ${val}`
|
|
7376
|
+
);
|
|
6830
7377
|
}
|
|
6831
7378
|
});
|
|
6832
7379
|
break;
|
|
@@ -6835,22 +7382,36 @@ var GoTypeEmitter = class {
|
|
|
6835
7382
|
emitter.line(`Value interface{}`);
|
|
6836
7383
|
});
|
|
6837
7384
|
emitter.line();
|
|
6838
|
-
emitter.block(
|
|
6839
|
-
|
|
6840
|
-
|
|
7385
|
+
emitter.block(
|
|
7386
|
+
`func (u ${type.id}) MarshalJSON() ([]byte, error) {`,
|
|
7387
|
+
`}`,
|
|
7388
|
+
() => {
|
|
7389
|
+
emitter.line(`return json.Marshal(u.Value)`);
|
|
7390
|
+
}
|
|
7391
|
+
);
|
|
6841
7392
|
emitter.line();
|
|
6842
|
-
emitter.block(
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
|
|
6847
|
-
|
|
6848
|
-
|
|
6849
|
-
emitter.line(`
|
|
6850
|
-
|
|
7393
|
+
emitter.block(
|
|
7394
|
+
`func (u *${type.id}) UnmarshalJSON(data []byte) error {`,
|
|
7395
|
+
`}`,
|
|
7396
|
+
() => {
|
|
7397
|
+
for (let i = 0; i < type.members.length; i++) {
|
|
7398
|
+
const member = type.members[i];
|
|
7399
|
+
const memberType = this.renderTypeRef(member);
|
|
7400
|
+
emitter.line(`var val${i} ${memberType}`);
|
|
7401
|
+
emitter.block(
|
|
7402
|
+
`if err := json.Unmarshal(data, &val${i}); err == nil {`,
|
|
7403
|
+
`}`,
|
|
7404
|
+
() => {
|
|
7405
|
+
emitter.line(`u.Value = val${i}`);
|
|
7406
|
+
emitter.line(`return nil`);
|
|
7407
|
+
}
|
|
7408
|
+
);
|
|
7409
|
+
}
|
|
7410
|
+
emitter.line(
|
|
7411
|
+
`return errors.New("cannot unmarshal into any union member of ${type.id}")`
|
|
7412
|
+
);
|
|
6851
7413
|
}
|
|
6852
|
-
|
|
6853
|
-
});
|
|
7414
|
+
);
|
|
6854
7415
|
break;
|
|
6855
7416
|
case "intersection":
|
|
6856
7417
|
emitter.line(`type ${type.id} map[string]interface{}`);
|
|
@@ -6870,8 +7431,10 @@ var GoTypeEmitter = class {
|
|
|
6870
7431
|
let t = "interface{}";
|
|
6871
7432
|
if (ref.ref) t = ref.ref;
|
|
6872
7433
|
else if (ref.inline) {
|
|
6873
|
-
if (ref.inline.kind === "scalar")
|
|
6874
|
-
|
|
7434
|
+
if (ref.inline.kind === "scalar")
|
|
7435
|
+
t = this.renderScalar(ref.inline.scalar);
|
|
7436
|
+
else if (ref.inline.kind === "array")
|
|
7437
|
+
t = `[]${this.renderTypeRef(ref.inline.items)}`;
|
|
6875
7438
|
}
|
|
6876
7439
|
if (ref.isArray) t = `[]${t}`;
|
|
6877
7440
|
if (ref.nullable) t = `*${t}`;
|
|
@@ -6938,11 +7501,15 @@ var GoClientEmitter = class {
|
|
|
6938
7501
|
emitter.line();
|
|
6939
7502
|
emitter.line(`type ClientOption func(*Client)`);
|
|
6940
7503
|
emitter.line();
|
|
6941
|
-
emitter.block(
|
|
6942
|
-
|
|
6943
|
-
|
|
6944
|
-
|
|
6945
|
-
|
|
7504
|
+
emitter.block(
|
|
7505
|
+
`func WithHTTPClient(hc *http.Client) ClientOption {`,
|
|
7506
|
+
`}`,
|
|
7507
|
+
() => {
|
|
7508
|
+
emitter.block(`return func(c *Client) {`, `}`, () => {
|
|
7509
|
+
emitter.line(`c.HTTPClient = hc`);
|
|
7510
|
+
});
|
|
7511
|
+
}
|
|
7512
|
+
);
|
|
6946
7513
|
emitter.line();
|
|
6947
7514
|
emitter.block(`func WithToken(token string) ClientOption {`, `}`, () => {
|
|
6948
7515
|
emitter.block(`return func(c *Client) {`, `}`, () => {
|
|
@@ -6950,11 +7517,17 @@ var GoClientEmitter = class {
|
|
|
6950
7517
|
});
|
|
6951
7518
|
});
|
|
6952
7519
|
emitter.line();
|
|
6953
|
-
emitter.block(
|
|
6954
|
-
|
|
6955
|
-
|
|
6956
|
-
|
|
6957
|
-
|
|
7520
|
+
emitter.block(
|
|
7521
|
+
`func NewClient(baseURL string, opts ...ClientOption) *Client {`,
|
|
7522
|
+
`}`,
|
|
7523
|
+
() => {
|
|
7524
|
+
emitter.line(
|
|
7525
|
+
`c := &Client{BaseURL: baseURL, HTTPClient: &http.Client{}}`
|
|
7526
|
+
);
|
|
7527
|
+
emitter.line(`for _, opt := range opts { opt(c) }`);
|
|
7528
|
+
emitter.line(`return c`);
|
|
7529
|
+
}
|
|
7530
|
+
);
|
|
6958
7531
|
emitter.line();
|
|
6959
7532
|
for (const ep of this.schema.endpoints) {
|
|
6960
7533
|
if (ep.transport !== "rest") continue;
|
|
@@ -6970,10 +7543,14 @@ var GoClientEmitter = class {
|
|
|
6970
7543
|
if (hasParams) {
|
|
6971
7544
|
emitter.block(`type ${reqStructName} struct {`, `}`, () => {
|
|
6972
7545
|
for (const p of ep.pathParams) {
|
|
6973
|
-
emitter.line(
|
|
7546
|
+
emitter.line(
|
|
7547
|
+
`${this.capitalize(p.name)} ${this.renderTypeRef(p.type)}`
|
|
7548
|
+
);
|
|
6974
7549
|
}
|
|
6975
7550
|
for (const p of ep.queryParams) {
|
|
6976
|
-
emitter.line(
|
|
7551
|
+
emitter.line(
|
|
7552
|
+
`${this.capitalize(p.name)} ${this.renderTypeRef(p.type)}`
|
|
7553
|
+
);
|
|
6977
7554
|
}
|
|
6978
7555
|
if (ep.requestBody) {
|
|
6979
7556
|
emitter.line(`Body ${this.renderTypeRef(ep.requestBody.type)}`);
|
|
@@ -6983,58 +7560,78 @@ var GoClientEmitter = class {
|
|
|
6983
7560
|
}
|
|
6984
7561
|
const retType = this.buildResponseType(ep);
|
|
6985
7562
|
const args = hasParams ? `req *${reqStructName}` : ``;
|
|
6986
|
-
emitter.block(
|
|
6987
|
-
|
|
6988
|
-
|
|
6989
|
-
|
|
6990
|
-
|
|
6991
|
-
|
|
6992
|
-
|
|
6993
|
-
|
|
6994
|
-
|
|
7563
|
+
emitter.block(
|
|
7564
|
+
`func (c *Client) ${methodName}(ctx context.Context${hasParams ? ", " + args : ""}) (*${retType}, error) {`,
|
|
7565
|
+
`}`,
|
|
7566
|
+
() => {
|
|
7567
|
+
const method = ep.method?.toUpperCase() || "GET";
|
|
7568
|
+
const pathTemplate = ep.path || "/";
|
|
7569
|
+
emitter.line(`reqURL := c.BaseURL + "${pathTemplate}"`);
|
|
7570
|
+
for (const p of ep.pathParams) {
|
|
7571
|
+
emitter.line(
|
|
7572
|
+
`reqURL = strings.ReplaceAll(reqURL, "{${p.name}}", fmt.Sprintf("%v", req.${this.capitalize(p.name)}))`
|
|
7573
|
+
);
|
|
7574
|
+
}
|
|
7575
|
+
if (ep.queryParams.length > 0) {
|
|
7576
|
+
emitter.line(`u, err := url.Parse(reqURL)`);
|
|
7577
|
+
emitter.line(`if err != nil { return nil, err }`);
|
|
7578
|
+
emitter.line(`q := u.Query()`);
|
|
7579
|
+
for (const q of ep.queryParams) {
|
|
7580
|
+
const capName = this.capitalize(q.name);
|
|
7581
|
+
emitter.line(
|
|
7582
|
+
`q.Set("${q.name}", fmt.Sprintf("%v", req.${capName}))`
|
|
7583
|
+
);
|
|
7584
|
+
}
|
|
7585
|
+
emitter.line(`u.RawQuery = q.Encode()`);
|
|
7586
|
+
emitter.line(`reqURL = u.String()`);
|
|
7587
|
+
}
|
|
7588
|
+
if (ep.requestBody) {
|
|
7589
|
+
emitter.line(`bodyBytes, err := json.Marshal(req.Body)`);
|
|
7590
|
+
emitter.line(`if err != nil { return nil, err }`);
|
|
7591
|
+
emitter.line(
|
|
7592
|
+
`httpReq, err := http.NewRequestWithContext(ctx, "${method}", reqURL, bytes.NewReader(bodyBytes))`
|
|
7593
|
+
);
|
|
7594
|
+
} else {
|
|
7595
|
+
emitter.line(
|
|
7596
|
+
`httpReq, err := http.NewRequestWithContext(ctx, "${method}", reqURL, nil)`
|
|
7597
|
+
);
|
|
7598
|
+
}
|
|
6995
7599
|
emitter.line(`if err != nil { return nil, err }`);
|
|
6996
|
-
emitter.line(
|
|
6997
|
-
|
|
6998
|
-
|
|
6999
|
-
|
|
7600
|
+
emitter.line();
|
|
7601
|
+
emitter.line(`if c.Token != "" {`);
|
|
7602
|
+
emitter.line(
|
|
7603
|
+
` httpReq.Header.Set("Authorization", "Bearer "+c.Token)`
|
|
7604
|
+
);
|
|
7605
|
+
emitter.line(`}`);
|
|
7606
|
+
if (ep.requestBody) {
|
|
7607
|
+
emitter.line(
|
|
7608
|
+
`httpReq.Header.Set("Content-Type", "application/json")`
|
|
7609
|
+
);
|
|
7000
7610
|
}
|
|
7001
|
-
emitter.line(
|
|
7002
|
-
emitter.line(`
|
|
7003
|
-
}
|
|
7004
|
-
if (ep.requestBody) {
|
|
7005
|
-
emitter.line(`bodyBytes, err := json.Marshal(req.Body)`);
|
|
7611
|
+
emitter.line();
|
|
7612
|
+
emitter.line(`resp, err := c.HTTPClient.Do(httpReq)`);
|
|
7006
7613
|
emitter.line(`if err != nil { return nil, err }`);
|
|
7007
|
-
emitter.line(`
|
|
7008
|
-
|
|
7009
|
-
emitter.line(`
|
|
7010
|
-
|
|
7011
|
-
|
|
7012
|
-
|
|
7013
|
-
emitter.line(`if c.Token != "" {`);
|
|
7014
|
-
emitter.line(` httpReq.Header.Set("Authorization", "Bearer "+c.Token)`);
|
|
7015
|
-
emitter.line(`}`);
|
|
7016
|
-
if (ep.requestBody) {
|
|
7017
|
-
emitter.line(`httpReq.Header.Set("Content-Type", "application/json")`);
|
|
7018
|
-
}
|
|
7019
|
-
emitter.line();
|
|
7020
|
-
emitter.line(`resp, err := c.HTTPClient.Do(httpReq)`);
|
|
7021
|
-
emitter.line(`if err != nil { return nil, err }`);
|
|
7022
|
-
emitter.line(`defer resp.Body.Close()`);
|
|
7023
|
-
emitter.line();
|
|
7024
|
-
emitter.line(`if resp.StatusCode >= 400 {`);
|
|
7025
|
-
emitter.line(` return nil, fmt.Errorf("API Error: %d", resp.StatusCode)`);
|
|
7026
|
-
emitter.line(`}`);
|
|
7027
|
-
emitter.line();
|
|
7028
|
-
if (retType !== "interface{}") {
|
|
7029
|
-
emitter.line(`var res ${retType}`);
|
|
7030
|
-
emitter.line(`if err := json.NewDecoder(resp.Body).Decode(&res); err != nil {`);
|
|
7031
|
-
emitter.line(` return nil, err`);
|
|
7614
|
+
emitter.line(`defer resp.Body.Close()`);
|
|
7615
|
+
emitter.line();
|
|
7616
|
+
emitter.line(`if resp.StatusCode >= 400 {`);
|
|
7617
|
+
emitter.line(
|
|
7618
|
+
` return nil, fmt.Errorf("API Error: %d", resp.StatusCode)`
|
|
7619
|
+
);
|
|
7032
7620
|
emitter.line(`}`);
|
|
7033
|
-
emitter.line(
|
|
7034
|
-
|
|
7035
|
-
|
|
7621
|
+
emitter.line();
|
|
7622
|
+
if (retType !== "interface{}") {
|
|
7623
|
+
emitter.line(`var res ${retType}`);
|
|
7624
|
+
emitter.line(
|
|
7625
|
+
`if err := json.NewDecoder(resp.Body).Decode(&res); err != nil {`
|
|
7626
|
+
);
|
|
7627
|
+
emitter.line(` return nil, err`);
|
|
7628
|
+
emitter.line(`}`);
|
|
7629
|
+
emitter.line(`return &res, nil`);
|
|
7630
|
+
} else {
|
|
7631
|
+
emitter.line(`return nil, nil`);
|
|
7632
|
+
}
|
|
7036
7633
|
}
|
|
7037
|
-
|
|
7634
|
+
);
|
|
7038
7635
|
}
|
|
7039
7636
|
buildResponseType(ep) {
|
|
7040
7637
|
const success = ep.successResponse;
|
|
@@ -7047,7 +7644,8 @@ var GoClientEmitter = class {
|
|
|
7047
7644
|
renderTypeRef(ref) {
|
|
7048
7645
|
let t = "interface{}";
|
|
7049
7646
|
if (ref.ref) t = ref.ref;
|
|
7050
|
-
else if (ref.inline && ref.inline.kind === "scalar")
|
|
7647
|
+
else if (ref.inline && ref.inline.kind === "scalar")
|
|
7648
|
+
t = ref.inline.scalar === "number" ? "float64" : "string";
|
|
7051
7649
|
if (ref.isArray) t = `[]${t}`;
|
|
7052
7650
|
if (ref.nullable) t = `*${t}`;
|
|
7053
7651
|
return t;
|
|
@@ -7096,16 +7694,20 @@ var TsTypeEmitter = class {
|
|
|
7096
7694
|
return emitter.toString();
|
|
7097
7695
|
}
|
|
7098
7696
|
emitType(emitter, type) {
|
|
7099
|
-
if (type.description)
|
|
7697
|
+
if (type.description)
|
|
7698
|
+
this.emitDoc(emitter, type.description, type.deprecated);
|
|
7100
7699
|
switch (type.kind) {
|
|
7101
7700
|
case "object":
|
|
7102
7701
|
emitter.block(`export interface ${type.id} {`, `}`, () => {
|
|
7103
7702
|
const formatProp = (name) => /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name) ? name : `'${name}'`;
|
|
7104
7703
|
for (const field of type.fields) {
|
|
7105
|
-
if (field.description)
|
|
7704
|
+
if (field.description)
|
|
7705
|
+
this.emitDoc(emitter, field.description, field.deprecated);
|
|
7106
7706
|
const q = field.required ? "" : "?";
|
|
7107
7707
|
const ro = field.readOnly ? "readonly " : "";
|
|
7108
|
-
emitter.line(
|
|
7708
|
+
emitter.line(
|
|
7709
|
+
`${ro}${formatProp(field.name)}${q}: ${this.renderTypeRef(field.type)};`
|
|
7710
|
+
);
|
|
7109
7711
|
}
|
|
7110
7712
|
if (type.additionalProperties) {
|
|
7111
7713
|
const valType = typeof type.additionalProperties === "boolean" ? "any" : this.renderTypeRef(type.additionalProperties);
|
|
@@ -7118,7 +7720,8 @@ var TsTypeEmitter = class {
|
|
|
7118
7720
|
emitter.block(`export enum ${type.id} {`, `}`, () => {
|
|
7119
7721
|
const formatProp = (name) => /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name) ? name : `'${name}'`;
|
|
7120
7722
|
for (const v of type.values) {
|
|
7121
|
-
if (v.description)
|
|
7723
|
+
if (v.description)
|
|
7724
|
+
this.emitDoc(emitter, v.description, v.deprecated);
|
|
7122
7725
|
emitter.line(`${formatProp(v.name)} = ${v.value},`);
|
|
7123
7726
|
}
|
|
7124
7727
|
});
|
|
@@ -7126,29 +7729,42 @@ var TsTypeEmitter = class {
|
|
|
7126
7729
|
emitter.block(`export enum ${type.id} {`, `}`, () => {
|
|
7127
7730
|
const formatProp = (name) => /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name) ? name : `'${name}'`;
|
|
7128
7731
|
for (const v of type.values) {
|
|
7129
|
-
if (v.description)
|
|
7732
|
+
if (v.description)
|
|
7733
|
+
this.emitDoc(emitter, v.description, v.deprecated);
|
|
7130
7734
|
emitter.line(`${formatProp(v.name)} = "${v.value}",`);
|
|
7131
7735
|
}
|
|
7132
7736
|
});
|
|
7133
7737
|
}
|
|
7134
7738
|
break;
|
|
7135
7739
|
case "union":
|
|
7136
|
-
emitter.line(
|
|
7740
|
+
emitter.line(
|
|
7741
|
+
`export type ${type.id} = ${type.members.map((m) => this.renderTypeRef(m)).join(" | ")};`
|
|
7742
|
+
);
|
|
7137
7743
|
break;
|
|
7138
7744
|
case "intersection":
|
|
7139
|
-
emitter.line(
|
|
7745
|
+
emitter.line(
|
|
7746
|
+
`export type ${type.id} = ${type.members.map((m) => this.renderTypeRef(m)).join(" & ")};`
|
|
7747
|
+
);
|
|
7140
7748
|
break;
|
|
7141
7749
|
case "array":
|
|
7142
|
-
emitter.line(
|
|
7750
|
+
emitter.line(
|
|
7751
|
+
`export type ${type.id} = ${this.renderTypeRef(type.items)}[];`
|
|
7752
|
+
);
|
|
7143
7753
|
break;
|
|
7144
7754
|
case "scalar":
|
|
7145
|
-
emitter.line(
|
|
7755
|
+
emitter.line(
|
|
7756
|
+
`export type ${type.id} = ${this.renderScalar(type.scalar)};`
|
|
7757
|
+
);
|
|
7146
7758
|
break;
|
|
7147
7759
|
case "map":
|
|
7148
|
-
emitter.line(
|
|
7760
|
+
emitter.line(
|
|
7761
|
+
`export type ${type.id} = Record<string, ${this.renderTypeRef(type.valueType)}>;`
|
|
7762
|
+
);
|
|
7149
7763
|
break;
|
|
7150
7764
|
case "tuple":
|
|
7151
|
-
emitter.line(
|
|
7765
|
+
emitter.line(
|
|
7766
|
+
`export type ${type.id} = [${type.elements.map((e) => this.renderTypeRef(e)).join(", ")}];`
|
|
7767
|
+
);
|
|
7152
7768
|
break;
|
|
7153
7769
|
case "literal":
|
|
7154
7770
|
const val = typeof type.value === "string" ? `"${type.value}"` : String(type.value);
|
|
@@ -7160,8 +7776,10 @@ var TsTypeEmitter = class {
|
|
|
7160
7776
|
let t = "any";
|
|
7161
7777
|
if (ref.ref) t = ref.ref;
|
|
7162
7778
|
else if (ref.inline) {
|
|
7163
|
-
if (ref.inline.kind === "scalar")
|
|
7164
|
-
|
|
7779
|
+
if (ref.inline.kind === "scalar")
|
|
7780
|
+
t = this.renderScalar(ref.inline.scalar);
|
|
7781
|
+
else if (ref.inline.kind === "array")
|
|
7782
|
+
t = `${this.renderTypeRef(ref.inline.items)}[]`;
|
|
7165
7783
|
}
|
|
7166
7784
|
if (ref.isArray) t = `${t}[]`;
|
|
7167
7785
|
if (ref.nullable) t = `${t} | null`;
|
|
@@ -7222,7 +7840,9 @@ var JsClientEmitter = class {
|
|
|
7222
7840
|
emitter.line(" */");
|
|
7223
7841
|
emitter.block(`class ${this.className} extends BaseClient {`, `}`, () => {
|
|
7224
7842
|
emitter.line("/**");
|
|
7225
|
-
emitter.line(
|
|
7843
|
+
emitter.line(
|
|
7844
|
+
' * @param {import("@axiomify/sdk-runtime").ClientConfig} config'
|
|
7845
|
+
);
|
|
7226
7846
|
emitter.line(" */");
|
|
7227
7847
|
emitter.block(`constructor(config) {`, `}`, () => {
|
|
7228
7848
|
emitter.line(`super(config);`);
|
|
@@ -7256,7 +7876,7 @@ var JsClientEmitter = class {
|
|
|
7256
7876
|
emitter.block(methodSignature, `}`, () => {
|
|
7257
7877
|
const method = ep.method?.toUpperCase() || "GET";
|
|
7258
7878
|
const pathTemplate = ep.path || "/";
|
|
7259
|
-
|
|
7879
|
+
const pathExpr = `\`${pathTemplate.replace(/\{([^}]+)\}/g, "${request.$1}")}\``;
|
|
7260
7880
|
let reqOpts = `method: '${method}', path: ${pathExpr}`;
|
|
7261
7881
|
const isValidJSIdentifier = (name) => /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
|
|
7262
7882
|
if (ep.queryParams.length > 0) {
|
|
@@ -7277,11 +7897,22 @@ var JsClientEmitter = class {
|
|
|
7277
7897
|
buildRequestType(ep) {
|
|
7278
7898
|
const props = [];
|
|
7279
7899
|
const formatProp = (name) => /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name) ? name : `'${name}'`;
|
|
7280
|
-
for (const p of ep.pathParams)
|
|
7281
|
-
|
|
7282
|
-
|
|
7900
|
+
for (const p of ep.pathParams)
|
|
7901
|
+
props.push(
|
|
7902
|
+
`${formatProp(p.name)}${p.required ? "" : "?"}: ${this.renderTypeRef(p.type)}`
|
|
7903
|
+
);
|
|
7904
|
+
for (const p of ep.queryParams)
|
|
7905
|
+
props.push(
|
|
7906
|
+
`${formatProp(p.name)}${p.required ? "" : "?"}: ${this.renderTypeRef(p.type)}`
|
|
7907
|
+
);
|
|
7908
|
+
for (const p of ep.headerParams)
|
|
7909
|
+
props.push(
|
|
7910
|
+
`${formatProp(p.name)}${p.required ? "" : "?"}: ${this.renderTypeRef(p.type)}`
|
|
7911
|
+
);
|
|
7283
7912
|
if (ep.requestBody) {
|
|
7284
|
-
props.push(
|
|
7913
|
+
props.push(
|
|
7914
|
+
`body${ep.requestBody.required ? "" : "?"}: ${this.renderTypeRef(ep.requestBody.type)}`
|
|
7915
|
+
);
|
|
7285
7916
|
}
|
|
7286
7917
|
if (props.length === 0) return null;
|
|
7287
7918
|
return `{ ${props.join(", ")} }`;
|
|
@@ -7299,7 +7930,8 @@ var JsClientEmitter = class {
|
|
|
7299
7930
|
if (ref.ref) t = `import("./types").${ref.ref}`;
|
|
7300
7931
|
else if (ref.inline) {
|
|
7301
7932
|
if (ref.inline.kind === "scalar") {
|
|
7302
|
-
if (ref.inline.scalar === "integer" || ref.inline.scalar === "number")
|
|
7933
|
+
if (ref.inline.scalar === "integer" || ref.inline.scalar === "number")
|
|
7934
|
+
t = "number";
|
|
7303
7935
|
else if (ref.inline.scalar === "boolean") t = "boolean";
|
|
7304
7936
|
else t = "string";
|
|
7305
7937
|
} else if (ref.inline.kind === "array") {
|
|
@@ -7320,19 +7952,32 @@ var JavaScriptGenerator = class extends Generator {
|
|
|
7320
7952
|
this.addFile("types.d.ts", typeEmitter.emitAll());
|
|
7321
7953
|
const clientEmitter = new JsClientEmitter(this.schema, "ApiClient");
|
|
7322
7954
|
this.addFile("client.js", clientEmitter.emitAll());
|
|
7323
|
-
this.addFile(
|
|
7955
|
+
this.addFile(
|
|
7956
|
+
"index.js",
|
|
7957
|
+
`const { ApiClient } = require('./client');
|
|
7324
7958
|
module.exports = { ApiClient };
|
|
7325
|
-
`
|
|
7326
|
-
|
|
7959
|
+
`
|
|
7960
|
+
);
|
|
7961
|
+
this.addFile(
|
|
7962
|
+
"index.d.ts",
|
|
7963
|
+
`export * from './types';
|
|
7327
7964
|
export { ApiClient } from './client';
|
|
7328
|
-
`
|
|
7329
|
-
|
|
7330
|
-
|
|
7331
|
-
|
|
7332
|
-
|
|
7333
|
-
|
|
7334
|
-
|
|
7335
|
-
|
|
7965
|
+
`
|
|
7966
|
+
);
|
|
7967
|
+
this.addFile(
|
|
7968
|
+
"package.json",
|
|
7969
|
+
JSON.stringify(
|
|
7970
|
+
{
|
|
7971
|
+
name: this.options.packageName,
|
|
7972
|
+
version: this.options.version || "1.0.0",
|
|
7973
|
+
main: "index.js",
|
|
7974
|
+
types: "index.d.ts",
|
|
7975
|
+
dependencies: {}
|
|
7976
|
+
},
|
|
7977
|
+
null,
|
|
7978
|
+
2
|
|
7979
|
+
)
|
|
7980
|
+
);
|
|
7336
7981
|
return this.files;
|
|
7337
7982
|
}
|
|
7338
7983
|
};
|
|
@@ -7381,7 +8026,9 @@ var KotlinTypeEmitter = class {
|
|
|
7381
8026
|
const ktType = this.renderTypeRef(field.type);
|
|
7382
8027
|
const opt = field.required ? "" : "? = null";
|
|
7383
8028
|
const comma = i < type.fields.length - 1 ? "," : "";
|
|
7384
|
-
emitter.line(
|
|
8029
|
+
emitter.line(
|
|
8030
|
+
`@SerialName("${field.name}") val ${this.toCamelCase(field.name)}: ${ktType}${opt}${comma}`
|
|
8031
|
+
);
|
|
7385
8032
|
}
|
|
7386
8033
|
});
|
|
7387
8034
|
break;
|
|
@@ -7389,7 +8036,9 @@ var KotlinTypeEmitter = class {
|
|
|
7389
8036
|
emitter.line(`@Serializable`);
|
|
7390
8037
|
emitter.block(`enum class ${type.id} {`, `}`, () => {
|
|
7391
8038
|
for (const v of type.values) {
|
|
7392
|
-
emitter.line(
|
|
8039
|
+
emitter.line(
|
|
8040
|
+
`@SerialName("${v.value}") ${this.toUpperSnakeCase(v.name)},`
|
|
8041
|
+
);
|
|
7393
8042
|
}
|
|
7394
8043
|
});
|
|
7395
8044
|
break;
|
|
@@ -7401,27 +8050,41 @@ var KotlinTypeEmitter = class {
|
|
|
7401
8050
|
const name = member.ref ? member.ref : `Value${i}`;
|
|
7402
8051
|
const memberType = this.renderTypeRef(member);
|
|
7403
8052
|
emitter.line(`@Serializable`);
|
|
7404
|
-
emitter.line(
|
|
8053
|
+
emitter.line(
|
|
8054
|
+
`data class ${name}(val value: ${memberType}): ${type.id}`
|
|
8055
|
+
);
|
|
7405
8056
|
}
|
|
7406
8057
|
});
|
|
7407
8058
|
break;
|
|
7408
8059
|
case "intersection":
|
|
7409
|
-
emitter.line(
|
|
8060
|
+
emitter.line(
|
|
8061
|
+
`typealias ${type.id} = Map<String, kotlinx.serialization.json.JsonElement>`
|
|
8062
|
+
);
|
|
7410
8063
|
break;
|
|
7411
8064
|
case "array":
|
|
7412
|
-
emitter.line(
|
|
8065
|
+
emitter.line(
|
|
8066
|
+
`typealias ${type.id} = List<${this.renderTypeRef(type.items)}>`
|
|
8067
|
+
);
|
|
7413
8068
|
break;
|
|
7414
8069
|
case "scalar":
|
|
7415
|
-
emitter.line(
|
|
8070
|
+
emitter.line(
|
|
8071
|
+
`typealias ${type.id} = ${this.renderScalar(type.scalar)}`
|
|
8072
|
+
);
|
|
7416
8073
|
break;
|
|
7417
8074
|
case "map":
|
|
7418
|
-
emitter.line(
|
|
8075
|
+
emitter.line(
|
|
8076
|
+
`typealias ${type.id} = Map<String, ${this.renderTypeRef(type.valueType)}>`
|
|
8077
|
+
);
|
|
7419
8078
|
break;
|
|
7420
8079
|
case "tuple":
|
|
7421
|
-
emitter.line(
|
|
8080
|
+
emitter.line(
|
|
8081
|
+
`typealias ${type.id} = List<kotlinx.serialization.json.JsonElement>`
|
|
8082
|
+
);
|
|
7422
8083
|
break;
|
|
7423
8084
|
case "literal":
|
|
7424
|
-
emitter.line(
|
|
8085
|
+
emitter.line(
|
|
8086
|
+
`typealias ${type.id} = kotlinx.serialization.json.JsonPrimitive`
|
|
8087
|
+
);
|
|
7425
8088
|
break;
|
|
7426
8089
|
}
|
|
7427
8090
|
}
|
|
@@ -7429,8 +8092,10 @@ var KotlinTypeEmitter = class {
|
|
|
7429
8092
|
let t = "Any";
|
|
7430
8093
|
if (ref.ref) t = ref.ref;
|
|
7431
8094
|
else if (ref.inline) {
|
|
7432
|
-
if (ref.inline.kind === "scalar")
|
|
7433
|
-
|
|
8095
|
+
if (ref.inline.kind === "scalar")
|
|
8096
|
+
t = this.renderScalar(ref.inline.scalar);
|
|
8097
|
+
else if (ref.inline.kind === "array")
|
|
8098
|
+
t = `List<${this.renderTypeRef(ref.inline.items)}>`;
|
|
7434
8099
|
}
|
|
7435
8100
|
if (ref.isArray) t = `List<${t}>`;
|
|
7436
8101
|
return t;
|
|
@@ -7487,7 +8152,9 @@ var KotlinClientEmitter = class {
|
|
|
7487
8152
|
emitter.line();
|
|
7488
8153
|
emitter.line(`import okhttp3.OkHttpClient`);
|
|
7489
8154
|
emitter.line(`import retrofit2.Retrofit`);
|
|
7490
|
-
emitter.line(
|
|
8155
|
+
emitter.line(
|
|
8156
|
+
`import retrofit2.converter.kotlinx.serialization.asConverterFactory`
|
|
8157
|
+
);
|
|
7491
8158
|
emitter.line(`import retrofit2.http.*`);
|
|
7492
8159
|
emitter.line(`import kotlinx.serialization.json.Json`);
|
|
7493
8160
|
emitter.line(`import okhttp3.MediaType.Companion.toMediaType`);
|
|
@@ -7500,26 +8167,42 @@ var KotlinClientEmitter = class {
|
|
|
7500
8167
|
}
|
|
7501
8168
|
});
|
|
7502
8169
|
emitter.line();
|
|
7503
|
-
emitter.block(
|
|
7504
|
-
|
|
7505
|
-
|
|
7506
|
-
|
|
7507
|
-
|
|
7508
|
-
|
|
7509
|
-
|
|
7510
|
-
|
|
7511
|
-
|
|
7512
|
-
|
|
7513
|
-
|
|
7514
|
-
|
|
7515
|
-
|
|
7516
|
-
|
|
7517
|
-
|
|
7518
|
-
|
|
7519
|
-
|
|
7520
|
-
|
|
7521
|
-
|
|
7522
|
-
|
|
8170
|
+
emitter.block(
|
|
8171
|
+
`class ${this.className}(private val baseUrl: String, private val token: String? = null) {`,
|
|
8172
|
+
`}`,
|
|
8173
|
+
() => {
|
|
8174
|
+
emitter.block(
|
|
8175
|
+
`private val client = OkHttpClient.Builder().apply {`,
|
|
8176
|
+
`}.build()`,
|
|
8177
|
+
() => {
|
|
8178
|
+
emitter.block(`if (token != null) {`, `}`, () => {
|
|
8179
|
+
emitter.block(`addInterceptor { chain ->`, `}`, () => {
|
|
8180
|
+
emitter.line(`val request = chain.request().newBuilder()`);
|
|
8181
|
+
emitter.line(` .header("Authorization", "Bearer $token")`);
|
|
8182
|
+
emitter.line(` .build()`);
|
|
8183
|
+
emitter.line(`chain.proceed(request)`);
|
|
8184
|
+
});
|
|
8185
|
+
});
|
|
8186
|
+
}
|
|
8187
|
+
);
|
|
8188
|
+
emitter.line();
|
|
8189
|
+
emitter.block(
|
|
8190
|
+
`private val retrofit = Retrofit.Builder()`,
|
|
8191
|
+
`.build()`,
|
|
8192
|
+
() => {
|
|
8193
|
+
emitter.line(`.baseUrl(baseUrl)`);
|
|
8194
|
+
emitter.line(`.client(client)`);
|
|
8195
|
+
emitter.line(
|
|
8196
|
+
`.addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))`
|
|
8197
|
+
);
|
|
8198
|
+
}
|
|
8199
|
+
);
|
|
8200
|
+
emitter.line();
|
|
8201
|
+
emitter.line(
|
|
8202
|
+
`val api: ApiService = retrofit.create(ApiService::class.java)`
|
|
8203
|
+
);
|
|
8204
|
+
}
|
|
8205
|
+
);
|
|
7523
8206
|
return emitter.toString();
|
|
7524
8207
|
}
|
|
7525
8208
|
emitRetrofitMethod(emitter, ep) {
|
|
@@ -7528,13 +8211,17 @@ var KotlinClientEmitter = class {
|
|
|
7528
8211
|
const pathExpr = pathTemplate.replace(/\{([^}]+)\}/g, "{$1}");
|
|
7529
8212
|
emitter.line(`@${method}("${pathExpr}")`);
|
|
7530
8213
|
const methodName = this.toCamelCase(ep.operationId);
|
|
7531
|
-
|
|
8214
|
+
const args = [];
|
|
7532
8215
|
for (const p of ep.pathParams) {
|
|
7533
|
-
args.push(
|
|
8216
|
+
args.push(
|
|
8217
|
+
`@Path("${p.name}") ${this.toCamelCase(p.name)}: ${this.renderTypeRef(p.type)}`
|
|
8218
|
+
);
|
|
7534
8219
|
}
|
|
7535
8220
|
for (const p of ep.queryParams) {
|
|
7536
8221
|
const defaultValue = p.required ? "" : "? = null";
|
|
7537
|
-
args.push(
|
|
8222
|
+
args.push(
|
|
8223
|
+
`@Query("${p.name}") ${this.toCamelCase(p.name)}: ${this.renderTypeRef(p.type)}${defaultValue}`
|
|
8224
|
+
);
|
|
7538
8225
|
}
|
|
7539
8226
|
if (ep.requestBody) {
|
|
7540
8227
|
args.push(`@Body body: ${this.renderTypeRef(ep.requestBody.type)}`);
|
|
@@ -7574,9 +8261,15 @@ var KotlinGenerator = class extends Generator {
|
|
|
7574
8261
|
const pkgName = this.options.packageName.replace(/[^a-zA-Z0-9_.]/g, "").toLowerCase() || "com.axiomify.sdk";
|
|
7575
8262
|
const typeEmitter = new KotlinTypeEmitter(this.schema, graph, pkgName);
|
|
7576
8263
|
this.addFile("src/main/kotlin/Types.kt", typeEmitter.emitAll());
|
|
7577
|
-
const clientEmitter = new KotlinClientEmitter(
|
|
8264
|
+
const clientEmitter = new KotlinClientEmitter(
|
|
8265
|
+
this.schema,
|
|
8266
|
+
pkgName,
|
|
8267
|
+
"ApiClient"
|
|
8268
|
+
);
|
|
7578
8269
|
this.addFile("src/main/kotlin/Client.kt", clientEmitter.emitAll());
|
|
7579
|
-
this.addFile(
|
|
8270
|
+
this.addFile(
|
|
8271
|
+
"build.gradle.kts",
|
|
8272
|
+
`plugins {
|
|
7580
8273
|
kotlin("jvm") version "1.9.0"
|
|
7581
8274
|
kotlin("plugin.serialization") version "1.9.0"
|
|
7582
8275
|
}
|
|
@@ -7592,7 +8285,8 @@ dependencies {
|
|
|
7592
8285
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0")
|
|
7593
8286
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
|
|
7594
8287
|
}
|
|
7595
|
-
`
|
|
8288
|
+
`
|
|
8289
|
+
);
|
|
7596
8290
|
return this.files;
|
|
7597
8291
|
}
|
|
7598
8292
|
};
|
|
@@ -7628,7 +8322,9 @@ var PythonTypeEmitter = class {
|
|
|
7628
8322
|
case "object":
|
|
7629
8323
|
emitter.block(`class ${type.id}(BaseModel):`, ``, () => {
|
|
7630
8324
|
if (type.description) this.emitDoc(emitter, type.description);
|
|
7631
|
-
emitter.line(
|
|
8325
|
+
emitter.line(
|
|
8326
|
+
`model_config = ConfigDict(populate_by_name=True, protected_namespaces=())`
|
|
8327
|
+
);
|
|
7632
8328
|
emitter.line();
|
|
7633
8329
|
if (type.fields.length === 0) {
|
|
7634
8330
|
emitter.line("pass");
|
|
@@ -7639,9 +8335,13 @@ var PythonTypeEmitter = class {
|
|
|
7639
8335
|
const alias = field.name !== this.toSnakeCase(field.name) ? `, alias="${field.name}"` : "";
|
|
7640
8336
|
const desc = field.description ? `, description="${field.description.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"` : "";
|
|
7641
8337
|
if (field.required) {
|
|
7642
|
-
emitter.line(
|
|
8338
|
+
emitter.line(
|
|
8339
|
+
`${this.toSnakeCase(field.name)}: ${pyType} = Field(...${alias}${desc})`
|
|
8340
|
+
);
|
|
7643
8341
|
} else {
|
|
7644
|
-
emitter.line(
|
|
8342
|
+
emitter.line(
|
|
8343
|
+
`${this.toSnakeCase(field.name)}: Optional[${pyType}] = Field(default=None${alias}${desc})`
|
|
8344
|
+
);
|
|
7645
8345
|
}
|
|
7646
8346
|
}
|
|
7647
8347
|
});
|
|
@@ -7657,7 +8357,9 @@ var PythonTypeEmitter = class {
|
|
|
7657
8357
|
});
|
|
7658
8358
|
break;
|
|
7659
8359
|
case "union":
|
|
7660
|
-
emitter.line(
|
|
8360
|
+
emitter.line(
|
|
8361
|
+
`${type.id} = Union[${type.members.map((m) => this.renderTypeRef(m)).join(", ")}]`
|
|
8362
|
+
);
|
|
7661
8363
|
break;
|
|
7662
8364
|
case "intersection":
|
|
7663
8365
|
emitter.line(`${type.id} = Any`);
|
|
@@ -7669,10 +8371,14 @@ var PythonTypeEmitter = class {
|
|
|
7669
8371
|
emitter.line(`${type.id} = ${this.renderScalar(type.scalar)}`);
|
|
7670
8372
|
break;
|
|
7671
8373
|
case "map":
|
|
7672
|
-
emitter.line(
|
|
8374
|
+
emitter.line(
|
|
8375
|
+
`${type.id} = Dict[str, ${this.renderTypeRef(type.valueType)}]`
|
|
8376
|
+
);
|
|
7673
8377
|
break;
|
|
7674
8378
|
case "tuple":
|
|
7675
|
-
emitter.line(
|
|
8379
|
+
emitter.line(
|
|
8380
|
+
`${type.id} = tuple[${type.elements.map((e) => this.renderTypeRef(e)).join(", ")}]`
|
|
8381
|
+
);
|
|
7676
8382
|
break;
|
|
7677
8383
|
case "literal":
|
|
7678
8384
|
const literalVal = typeof type.value === "string" ? `"${type.value}"` : type.value;
|
|
@@ -7684,8 +8390,10 @@ var PythonTypeEmitter = class {
|
|
|
7684
8390
|
let t = "Any";
|
|
7685
8391
|
if (ref.ref) t = `"${ref.ref}"`;
|
|
7686
8392
|
else if (ref.inline) {
|
|
7687
|
-
if (ref.inline.kind === "scalar")
|
|
7688
|
-
|
|
8393
|
+
if (ref.inline.kind === "scalar")
|
|
8394
|
+
t = this.renderScalar(ref.inline.scalar);
|
|
8395
|
+
else if (ref.inline.kind === "array")
|
|
8396
|
+
t = `List[${this.renderTypeRef(ref.inline.items)}]`;
|
|
7689
8397
|
}
|
|
7690
8398
|
if (ref.isArray) t = `List[${t}]`;
|
|
7691
8399
|
if (ref.nullable) t = `Optional[${t}]`;
|
|
@@ -7736,11 +8444,19 @@ var PythonClientEmitter = class {
|
|
|
7736
8444
|
emitter.line(`from . import types`);
|
|
7737
8445
|
emitter.line();
|
|
7738
8446
|
emitter.block(`class ${this.className}:`, ``, () => {
|
|
7739
|
-
emitter.block(
|
|
7740
|
-
|
|
7741
|
-
|
|
7742
|
-
|
|
7743
|
-
|
|
8447
|
+
emitter.block(
|
|
8448
|
+
`def __init__(self, base_url: str, token: Optional[str] = None):`,
|
|
8449
|
+
``,
|
|
8450
|
+
() => {
|
|
8451
|
+
emitter.line(`self.base_url = base_url`);
|
|
8452
|
+
emitter.line(
|
|
8453
|
+
`self.headers = {"Authorization": f"Bearer {token}"} if token else {}`
|
|
8454
|
+
);
|
|
8455
|
+
emitter.line(
|
|
8456
|
+
`self.client = httpx.AsyncClient(base_url=self.base_url, headers=self.headers)`
|
|
8457
|
+
);
|
|
8458
|
+
}
|
|
8459
|
+
);
|
|
7744
8460
|
emitter.block(`async def close(self):`, ``, () => {
|
|
7745
8461
|
emitter.line(`await self.client.aclose()`);
|
|
7746
8462
|
});
|
|
@@ -7755,7 +8471,8 @@ var PythonClientEmitter = class {
|
|
|
7755
8471
|
emitMethod(emitter, ep) {
|
|
7756
8472
|
const methodName = this.toSnakeCase(ep.operationId);
|
|
7757
8473
|
let args = `self`;
|
|
7758
|
-
for (const p of ep.pathParams)
|
|
8474
|
+
for (const p of ep.pathParams)
|
|
8475
|
+
args += `, ${this.toSnakeCase(p.name)}: ${this.renderTypeRef(p.type)}`;
|
|
7759
8476
|
for (const p of ep.queryParams) {
|
|
7760
8477
|
const defaultValue = p.required ? "" : " = None";
|
|
7761
8478
|
args += `, ${this.toSnakeCase(p.name)}: Optional[${this.renderTypeRef(p.type)}]${defaultValue}`;
|
|
@@ -7764,47 +8481,58 @@ var PythonClientEmitter = class {
|
|
|
7764
8481
|
args += `, body: ${this.renderTypeRef(ep.requestBody.type)}`;
|
|
7765
8482
|
}
|
|
7766
8483
|
const returnType = this.buildResponseType(ep);
|
|
7767
|
-
emitter.block(
|
|
7768
|
-
|
|
7769
|
-
|
|
7770
|
-
|
|
7771
|
-
if (ep.
|
|
7772
|
-
|
|
7773
|
-
|
|
7774
|
-
|
|
7775
|
-
|
|
7776
|
-
|
|
7777
|
-
|
|
7778
|
-
|
|
7779
|
-
|
|
7780
|
-
|
|
7781
|
-
|
|
7782
|
-
|
|
7783
|
-
|
|
7784
|
-
|
|
7785
|
-
const snakeName = this.toSnakeCase(q.name);
|
|
7786
|
-
emitter.line(` "${q.name}": ${snakeName},`);
|
|
8484
|
+
emitter.block(
|
|
8485
|
+
`async def ${methodName}(${args}) -> ${returnType}:`,
|
|
8486
|
+
``,
|
|
8487
|
+
() => {
|
|
8488
|
+
if (ep.summary || ep.description) {
|
|
8489
|
+
emitter.line(`"""`);
|
|
8490
|
+
if (ep.summary) emitter.line(ep.summary);
|
|
8491
|
+
if (ep.description) emitter.line(ep.description);
|
|
8492
|
+
emitter.line(`"""`);
|
|
8493
|
+
}
|
|
8494
|
+
const method = ep.method?.toLowerCase() || "get";
|
|
8495
|
+
const pathTemplate = ep.path || "/";
|
|
8496
|
+
let pathExpr = pathTemplate;
|
|
8497
|
+
for (const p of ep.pathParams) {
|
|
8498
|
+
pathExpr = pathExpr.replace(
|
|
8499
|
+
`{${p.name}}`,
|
|
8500
|
+
`{${this.toSnakeCase(p.name)}}`
|
|
8501
|
+
);
|
|
7787
8502
|
}
|
|
7788
|
-
emitter.line(`}`);
|
|
7789
|
-
reqOpts
|
|
7790
|
-
|
|
7791
|
-
|
|
7792
|
-
|
|
7793
|
-
|
|
7794
|
-
|
|
7795
|
-
|
|
7796
|
-
|
|
7797
|
-
|
|
7798
|
-
|
|
7799
|
-
if (
|
|
7800
|
-
emitter.line(
|
|
8503
|
+
emitter.line(`url = f"${pathExpr}"`);
|
|
8504
|
+
let reqOpts = `url`;
|
|
8505
|
+
if (ep.queryParams.length > 0) {
|
|
8506
|
+
emitter.line(`params = {`);
|
|
8507
|
+
for (const q of ep.queryParams) {
|
|
8508
|
+
const snakeName = this.toSnakeCase(q.name);
|
|
8509
|
+
emitter.line(` "${q.name}": ${snakeName},`);
|
|
8510
|
+
}
|
|
8511
|
+
emitter.line(`}`);
|
|
8512
|
+
reqOpts += `, params={k: v for k, v in params.items() if v is not None}`;
|
|
8513
|
+
}
|
|
8514
|
+
if (ep.requestBody) {
|
|
8515
|
+
emitter.line(
|
|
8516
|
+
`req_body = body.model_dump(by_alias=True) if hasattr(body, 'model_dump') else body`
|
|
8517
|
+
);
|
|
8518
|
+
reqOpts += `, json=req_body`;
|
|
8519
|
+
}
|
|
8520
|
+
emitter.line(`response = await self.client.${method}(${reqOpts})`);
|
|
8521
|
+
emitter.line(`response.raise_for_status()`);
|
|
8522
|
+
if (returnType !== "None") {
|
|
8523
|
+
const rawType = ep.successResponse && ep.responses[ep.successResponse]?.type?.ref;
|
|
8524
|
+
if (rawType) {
|
|
8525
|
+
emitter.line(
|
|
8526
|
+
`return types.${rawType}.model_validate(response.json())`
|
|
8527
|
+
);
|
|
8528
|
+
} else {
|
|
8529
|
+
emitter.line(`return response.json()`);
|
|
8530
|
+
}
|
|
7801
8531
|
} else {
|
|
7802
|
-
emitter.line(`return
|
|
8532
|
+
emitter.line(`return None`);
|
|
7803
8533
|
}
|
|
7804
|
-
} else {
|
|
7805
|
-
emitter.line(`return None`);
|
|
7806
8534
|
}
|
|
7807
|
-
|
|
8535
|
+
);
|
|
7808
8536
|
}
|
|
7809
8537
|
buildResponseType(ep) {
|
|
7810
8538
|
const success = ep.successResponse;
|
|
@@ -7819,7 +8547,8 @@ var PythonClientEmitter = class {
|
|
|
7819
8547
|
if (ref.ref) t = `types.${ref.ref}`;
|
|
7820
8548
|
else if (ref.inline) {
|
|
7821
8549
|
if (ref.inline.kind === "scalar") {
|
|
7822
|
-
if (ref.inline.scalar === "integer" || ref.inline.scalar === "number")
|
|
8550
|
+
if (ref.inline.scalar === "integer" || ref.inline.scalar === "number")
|
|
8551
|
+
t = "float";
|
|
7823
8552
|
else if (ref.inline.scalar === "boolean") t = "bool";
|
|
7824
8553
|
else t = "str";
|
|
7825
8554
|
} else if (ref.inline.kind === "array") {
|
|
@@ -7843,10 +8572,15 @@ var PythonGenerator = class extends Generator {
|
|
|
7843
8572
|
this.addFile("types.py", typeEmitter.emitAll());
|
|
7844
8573
|
const clientEmitter = new PythonClientEmitter(this.schema, "ApiClient");
|
|
7845
8574
|
this.addFile("client.py", clientEmitter.emitAll());
|
|
7846
|
-
this.addFile(
|
|
8575
|
+
this.addFile(
|
|
8576
|
+
"__init__.py",
|
|
8577
|
+
`from .types import *
|
|
7847
8578
|
from .client import ApiClient
|
|
7848
|
-
`
|
|
7849
|
-
|
|
8579
|
+
`
|
|
8580
|
+
);
|
|
8581
|
+
this.addFile(
|
|
8582
|
+
"setup.py",
|
|
8583
|
+
`from setuptools import setup, find_packages
|
|
7850
8584
|
|
|
7851
8585
|
setup(
|
|
7852
8586
|
name="${this.options.packageName}",
|
|
@@ -7858,7 +8592,8 @@ setup(
|
|
|
7858
8592
|
],
|
|
7859
8593
|
python_requires=">=3.8",
|
|
7860
8594
|
)
|
|
7861
|
-
`
|
|
8595
|
+
`
|
|
8596
|
+
);
|
|
7862
8597
|
return this.files;
|
|
7863
8598
|
}
|
|
7864
8599
|
};
|
|
@@ -7897,14 +8632,20 @@ var SwiftTypeEmitter = class {
|
|
|
7897
8632
|
if (field.description) this.emitDoc(emitter, field.description);
|
|
7898
8633
|
const swiftType = this.renderTypeRef(field.type);
|
|
7899
8634
|
const opt = field.required ? "" : "?";
|
|
7900
|
-
emitter.line(
|
|
8635
|
+
emitter.line(
|
|
8636
|
+
`public var ${this.toCamelCase(field.name)}: ${swiftType}${opt}`
|
|
8637
|
+
);
|
|
7901
8638
|
}
|
|
7902
|
-
const needsCustomCodingKeys = type.fields.some(
|
|
8639
|
+
const needsCustomCodingKeys = type.fields.some(
|
|
8640
|
+
(f) => f.name !== this.toCamelCase(f.name)
|
|
8641
|
+
);
|
|
7903
8642
|
if (needsCustomCodingKeys && type.fields.length > 0) {
|
|
7904
8643
|
emitter.line();
|
|
7905
8644
|
emitter.block(`enum CodingKeys: String, CodingKey {`, `}`, () => {
|
|
7906
8645
|
for (const field of type.fields) {
|
|
7907
|
-
emitter.line(
|
|
8646
|
+
emitter.line(
|
|
8647
|
+
`case ${this.toCamelCase(field.name)} = "${field.name}"`
|
|
8648
|
+
);
|
|
7908
8649
|
}
|
|
7909
8650
|
});
|
|
7910
8651
|
}
|
|
@@ -7912,12 +8653,16 @@ var SwiftTypeEmitter = class {
|
|
|
7912
8653
|
break;
|
|
7913
8654
|
case "enum":
|
|
7914
8655
|
const rawType = type.valueType === "number" ? "Int" : "String";
|
|
7915
|
-
emitter.block(
|
|
7916
|
-
|
|
7917
|
-
|
|
7918
|
-
|
|
8656
|
+
emitter.block(
|
|
8657
|
+
`public enum ${type.id}: ${rawType}, Codable {`,
|
|
8658
|
+
`}`,
|
|
8659
|
+
() => {
|
|
8660
|
+
for (const v of type.values) {
|
|
8661
|
+
const val = typeof v.value === "string" ? `"${v.value}"` : v.value;
|
|
8662
|
+
emitter.line(`case ${this.toCamelCase(v.name)} = ${val}`);
|
|
8663
|
+
}
|
|
7919
8664
|
}
|
|
7920
|
-
|
|
8665
|
+
);
|
|
7921
8666
|
break;
|
|
7922
8667
|
case "union":
|
|
7923
8668
|
emitter.block(`public enum ${type.id}: Codable {`, `}`, () => {
|
|
@@ -7928,51 +8673,79 @@ var SwiftTypeEmitter = class {
|
|
|
7928
8673
|
emitter.line(`case ${this.toCamelCase(name)}(${memberType})`);
|
|
7929
8674
|
}
|
|
7930
8675
|
emitter.line();
|
|
7931
|
-
emitter.block(
|
|
7932
|
-
|
|
7933
|
-
|
|
7934
|
-
|
|
7935
|
-
|
|
7936
|
-
|
|
7937
|
-
|
|
7938
|
-
emitter.line(`self = .${this.toCamelCase(name)}(value)`);
|
|
7939
|
-
emitter.line(`return`);
|
|
7940
|
-
});
|
|
7941
|
-
}
|
|
7942
|
-
emitter.line(`throw DecodingError.typeMismatch(${type.id}.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "No matching union type"))`);
|
|
7943
|
-
});
|
|
7944
|
-
emitter.line();
|
|
7945
|
-
emitter.block(`public func encode(to encoder: Encoder) throws {`, `}`, () => {
|
|
7946
|
-
emitter.line(`var container = encoder.singleValueContainer()`);
|
|
7947
|
-
emitter.block(`switch self {`, `}`, () => {
|
|
8676
|
+
emitter.block(
|
|
8677
|
+
`public init(from decoder: Decoder) throws {`,
|
|
8678
|
+
`}`,
|
|
8679
|
+
() => {
|
|
8680
|
+
emitter.line(
|
|
8681
|
+
`let container = try decoder.singleValueContainer()`
|
|
8682
|
+
);
|
|
7948
8683
|
for (let i = 0; i < type.members.length; i++) {
|
|
7949
8684
|
const member = type.members[i];
|
|
7950
8685
|
const name = member.ref ? member.ref : `value${i}`;
|
|
7951
|
-
|
|
7952
|
-
|
|
7953
|
-
|
|
8686
|
+
const memberType = this.renderTypeRef(member);
|
|
8687
|
+
emitter.block(
|
|
8688
|
+
`if let value = try? container.decode(${memberType}.self) {`,
|
|
8689
|
+
`}`,
|
|
8690
|
+
() => {
|
|
8691
|
+
emitter.line(`self = .${this.toCamelCase(name)}(value)`);
|
|
8692
|
+
emitter.line(`return`);
|
|
8693
|
+
}
|
|
8694
|
+
);
|
|
7954
8695
|
}
|
|
7955
|
-
|
|
7956
|
-
|
|
8696
|
+
emitter.line(
|
|
8697
|
+
`throw DecodingError.typeMismatch(${type.id}.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "No matching union type"))`
|
|
8698
|
+
);
|
|
8699
|
+
}
|
|
8700
|
+
);
|
|
8701
|
+
emitter.line();
|
|
8702
|
+
emitter.block(
|
|
8703
|
+
`public func encode(to encoder: Encoder) throws {`,
|
|
8704
|
+
`}`,
|
|
8705
|
+
() => {
|
|
8706
|
+
emitter.line(`var container = encoder.singleValueContainer()`);
|
|
8707
|
+
emitter.block(`switch self {`, `}`, () => {
|
|
8708
|
+
for (let i = 0; i < type.members.length; i++) {
|
|
8709
|
+
const member = type.members[i];
|
|
8710
|
+
const name = member.ref ? member.ref : `value${i}`;
|
|
8711
|
+
emitter.block(
|
|
8712
|
+
`case .${this.toCamelCase(name)}(let value):`,
|
|
8713
|
+
``,
|
|
8714
|
+
() => {
|
|
8715
|
+
emitter.line(`try container.encode(value)`);
|
|
8716
|
+
}
|
|
8717
|
+
);
|
|
8718
|
+
}
|
|
8719
|
+
});
|
|
8720
|
+
}
|
|
8721
|
+
);
|
|
7957
8722
|
});
|
|
7958
8723
|
break;
|
|
7959
8724
|
case "intersection":
|
|
7960
8725
|
emitter.line(`public typealias ${type.id} = [String: AnyCodable]`);
|
|
7961
8726
|
break;
|
|
7962
8727
|
case "array":
|
|
7963
|
-
emitter.line(
|
|
8728
|
+
emitter.line(
|
|
8729
|
+
`public typealias ${type.id} = [${this.renderTypeRef(type.items)}]`
|
|
8730
|
+
);
|
|
7964
8731
|
break;
|
|
7965
8732
|
case "scalar":
|
|
7966
|
-
emitter.line(
|
|
8733
|
+
emitter.line(
|
|
8734
|
+
`public typealias ${type.id} = ${this.renderScalar(type.scalar)}`
|
|
8735
|
+
);
|
|
7967
8736
|
break;
|
|
7968
8737
|
case "map":
|
|
7969
|
-
emitter.line(
|
|
8738
|
+
emitter.line(
|
|
8739
|
+
`public typealias ${type.id} = [String: ${this.renderTypeRef(type.valueType)}]`
|
|
8740
|
+
);
|
|
7970
8741
|
break;
|
|
7971
8742
|
case "tuple":
|
|
7972
8743
|
emitter.line(`public typealias ${type.id} = [AnyCodable]`);
|
|
7973
8744
|
break;
|
|
7974
8745
|
case "literal":
|
|
7975
|
-
emitter.line(
|
|
8746
|
+
emitter.line(
|
|
8747
|
+
`public typealias ${type.id} = AnyCodable // Literal: ${type.value}`
|
|
8748
|
+
);
|
|
7976
8749
|
break;
|
|
7977
8750
|
}
|
|
7978
8751
|
}
|
|
@@ -7980,8 +8753,10 @@ var SwiftTypeEmitter = class {
|
|
|
7980
8753
|
let t = "AnyCodable";
|
|
7981
8754
|
if (ref.ref) t = ref.ref;
|
|
7982
8755
|
else if (ref.inline) {
|
|
7983
|
-
if (ref.inline.kind === "scalar")
|
|
7984
|
-
|
|
8756
|
+
if (ref.inline.kind === "scalar")
|
|
8757
|
+
t = this.renderScalar(ref.inline.scalar);
|
|
8758
|
+
else if (ref.inline.kind === "array")
|
|
8759
|
+
t = `[${this.renderTypeRef(ref.inline.items)}]`;
|
|
7985
8760
|
}
|
|
7986
8761
|
if (ref.isArray) t = `[${t}]`;
|
|
7987
8762
|
return t;
|
|
@@ -8020,22 +8795,48 @@ var SwiftTypeEmitter = class {
|
|
|
8020
8795
|
emitter.line(` public init(_ value: Any) { self.value = value }`);
|
|
8021
8796
|
emitter.line(` public init(from decoder: Decoder) throws {`);
|
|
8022
8797
|
emitter.line(` let container = try decoder.singleValueContainer()`);
|
|
8023
|
-
emitter.line(
|
|
8024
|
-
|
|
8025
|
-
|
|
8026
|
-
emitter.line(
|
|
8027
|
-
|
|
8028
|
-
|
|
8029
|
-
emitter.line(
|
|
8798
|
+
emitter.line(
|
|
8799
|
+
` if let x = try? container.decode(Bool.self) { self.value = x }`
|
|
8800
|
+
);
|
|
8801
|
+
emitter.line(
|
|
8802
|
+
` else if let x = try? container.decode(Int.self) { self.value = x }`
|
|
8803
|
+
);
|
|
8804
|
+
emitter.line(
|
|
8805
|
+
` else if let x = try? container.decode(Double.self) { self.value = x }`
|
|
8806
|
+
);
|
|
8807
|
+
emitter.line(
|
|
8808
|
+
` else if let x = try? container.decode(String.self) { self.value = x }`
|
|
8809
|
+
);
|
|
8810
|
+
emitter.line(
|
|
8811
|
+
` else if let x = try? container.decode([String: AnyCodable].self) { self.value = x.mapValues { $0.value } }`
|
|
8812
|
+
);
|
|
8813
|
+
emitter.line(
|
|
8814
|
+
` else if let x = try? container.decode([AnyCodable].self) { self.value = x.map { $0.value } }`
|
|
8815
|
+
);
|
|
8816
|
+
emitter.line(
|
|
8817
|
+
` else { throw DecodingError.typeMismatch(AnyCodable.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type")) }`
|
|
8818
|
+
);
|
|
8030
8819
|
emitter.line(` }`);
|
|
8031
8820
|
emitter.line(` public func encode(to encoder: Encoder) throws {`);
|
|
8032
8821
|
emitter.line(` var container = encoder.singleValueContainer()`);
|
|
8033
|
-
emitter.line(
|
|
8034
|
-
|
|
8035
|
-
|
|
8036
|
-
emitter.line(
|
|
8037
|
-
|
|
8038
|
-
|
|
8822
|
+
emitter.line(
|
|
8823
|
+
` if let x = value as? Bool { try container.encode(x) }`
|
|
8824
|
+
);
|
|
8825
|
+
emitter.line(
|
|
8826
|
+
` else if let x = value as? Int { try container.encode(x) }`
|
|
8827
|
+
);
|
|
8828
|
+
emitter.line(
|
|
8829
|
+
` else if let x = value as? Double { try container.encode(x) }`
|
|
8830
|
+
);
|
|
8831
|
+
emitter.line(
|
|
8832
|
+
` else if let x = value as? String { try container.encode(x) }`
|
|
8833
|
+
);
|
|
8834
|
+
emitter.line(
|
|
8835
|
+
` else if let x = value as? [String: Any] { try container.encode(x.mapValues { AnyCodable($0) }) }`
|
|
8836
|
+
);
|
|
8837
|
+
emitter.line(
|
|
8838
|
+
` else if let x = value as? [Any] { try container.encode(x.map { AnyCodable($0) }) }`
|
|
8839
|
+
);
|
|
8039
8840
|
emitter.line(` }`);
|
|
8040
8841
|
emitter.line(`}`);
|
|
8041
8842
|
}
|
|
@@ -8058,11 +8859,15 @@ var SwiftClientEmitter = class {
|
|
|
8058
8859
|
emitter.line(`public var token: String?`);
|
|
8059
8860
|
emitter.line(`private let session: URLSession`);
|
|
8060
8861
|
emitter.line();
|
|
8061
|
-
emitter.block(
|
|
8062
|
-
|
|
8063
|
-
|
|
8064
|
-
|
|
8065
|
-
|
|
8862
|
+
emitter.block(
|
|
8863
|
+
`public init(baseURL: URL, token: String? = nil, session: URLSession = .shared) {`,
|
|
8864
|
+
`}`,
|
|
8865
|
+
() => {
|
|
8866
|
+
emitter.line(`self.baseURL = baseURL`);
|
|
8867
|
+
emitter.line(`self.token = token`);
|
|
8868
|
+
emitter.line(`self.session = session`);
|
|
8869
|
+
}
|
|
8870
|
+
);
|
|
8066
8871
|
for (const ep of this.schema.endpoints) {
|
|
8067
8872
|
if (ep.transport !== "rest") continue;
|
|
8068
8873
|
emitter.line();
|
|
@@ -8073,52 +8878,79 @@ var SwiftClientEmitter = class {
|
|
|
8073
8878
|
}
|
|
8074
8879
|
emitMethod(emitter, ep) {
|
|
8075
8880
|
const methodName = this.toCamelCase(ep.operationId);
|
|
8076
|
-
|
|
8881
|
+
const args = [];
|
|
8077
8882
|
for (const p of ep.pathParams) {
|
|
8078
8883
|
args.push(`${this.toCamelCase(p.name)}: ${this.renderTypeRef(p.type)}`);
|
|
8079
8884
|
}
|
|
8080
8885
|
for (const p of ep.queryParams) {
|
|
8081
|
-
args.push(
|
|
8886
|
+
args.push(
|
|
8887
|
+
`${this.toCamelCase(p.name)}: ${this.renderTypeRef(p.type)}? = nil`
|
|
8888
|
+
);
|
|
8082
8889
|
}
|
|
8083
8890
|
if (ep.requestBody) {
|
|
8084
8891
|
args.push(`body: ${this.renderTypeRef(ep.requestBody.type)}`);
|
|
8085
8892
|
}
|
|
8086
8893
|
const retType = this.buildResponseType(ep);
|
|
8087
|
-
emitter.block(
|
|
8088
|
-
|
|
8089
|
-
|
|
8090
|
-
|
|
8091
|
-
|
|
8092
|
-
|
|
8093
|
-
|
|
8094
|
-
|
|
8095
|
-
|
|
8096
|
-
|
|
8097
|
-
|
|
8098
|
-
|
|
8099
|
-
|
|
8100
|
-
|
|
8101
|
-
})
|
|
8894
|
+
emitter.block(
|
|
8895
|
+
`public func ${methodName}(${args.join(", ")}) async throws -> ${retType} {`,
|
|
8896
|
+
`}`,
|
|
8897
|
+
() => {
|
|
8898
|
+
const method = ep.method?.toUpperCase() || "GET";
|
|
8899
|
+
const pathTemplate = ep.path || "/";
|
|
8900
|
+
let pathExpr = pathTemplate;
|
|
8901
|
+
for (const p of ep.pathParams) {
|
|
8902
|
+
pathExpr = pathExpr.replace(
|
|
8903
|
+
`{${p.name}}`,
|
|
8904
|
+
`\\(${this.toCamelCase(p.name)})`
|
|
8905
|
+
);
|
|
8906
|
+
}
|
|
8907
|
+
emitter.line(
|
|
8908
|
+
`var components = URLComponents(url: baseURL.appendingPathComponent("${pathExpr}"), resolvingAgainstBaseURL: true)!`
|
|
8909
|
+
);
|
|
8910
|
+
if (ep.queryParams.length > 0) {
|
|
8911
|
+
emitter.line(`var queryItems: [URLQueryItem] = []`);
|
|
8912
|
+
for (const q of ep.queryParams) {
|
|
8913
|
+
const camelName = this.toCamelCase(q.name);
|
|
8914
|
+
emitter.block(`if let val = ${camelName} {`, `}`, () => {
|
|
8915
|
+
emitter.line(
|
|
8916
|
+
`queryItems.append(URLQueryItem(name: "${q.name}", value: String(describing: val)))`
|
|
8917
|
+
);
|
|
8918
|
+
});
|
|
8919
|
+
}
|
|
8920
|
+
emitter.line(
|
|
8921
|
+
`components.queryItems = queryItems.isEmpty ? nil : queryItems`
|
|
8922
|
+
);
|
|
8923
|
+
}
|
|
8924
|
+
emitter.line(`var request = URLRequest(url: components.url!)`);
|
|
8925
|
+
emitter.line(`request.httpMethod = "${method}"`);
|
|
8926
|
+
emitter.block(`if let token = self.token {`, `}`, () => {
|
|
8927
|
+
emitter.line(
|
|
8928
|
+
`request.addValue("Bearer \\(token)", forHTTPHeaderField: "Authorization")`
|
|
8929
|
+
);
|
|
8930
|
+
});
|
|
8931
|
+
if (ep.requestBody) {
|
|
8932
|
+
emitter.line(
|
|
8933
|
+
`request.addValue("application/json", forHTTPHeaderField: "Content-Type")`
|
|
8934
|
+
);
|
|
8935
|
+
emitter.line(`request.httpBody = try JSONEncoder().encode(body)`);
|
|
8936
|
+
}
|
|
8937
|
+
emitter.line(
|
|
8938
|
+
`let (data, response) = try await session.data(for: request)`
|
|
8939
|
+
);
|
|
8940
|
+
emitter.block(
|
|
8941
|
+
"guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {",
|
|
8942
|
+
"}",
|
|
8943
|
+
() => {
|
|
8944
|
+
emitter.line("throw URLError(.badServerResponse)");
|
|
8945
|
+
}
|
|
8946
|
+
);
|
|
8947
|
+
if (retType !== "Void") {
|
|
8948
|
+
emitter.line(
|
|
8949
|
+
`return try JSONDecoder().decode(${retType}.self, from: data)`
|
|
8950
|
+
);
|
|
8102
8951
|
}
|
|
8103
|
-
emitter.line(`components.queryItems = queryItems.isEmpty ? nil : queryItems`);
|
|
8104
|
-
}
|
|
8105
|
-
emitter.line(`var request = URLRequest(url: components.url!)`);
|
|
8106
|
-
emitter.line(`request.httpMethod = "${method}"`);
|
|
8107
|
-
emitter.block(`if let token = self.token {`, `}`, () => {
|
|
8108
|
-
emitter.line(`request.addValue("Bearer \\(token)", forHTTPHeaderField: "Authorization")`);
|
|
8109
|
-
});
|
|
8110
|
-
if (ep.requestBody) {
|
|
8111
|
-
emitter.line(`request.addValue("application/json", forHTTPHeaderField: "Content-Type")`);
|
|
8112
|
-
emitter.line(`request.httpBody = try JSONEncoder().encode(body)`);
|
|
8113
|
-
}
|
|
8114
|
-
emitter.line(`let (data, response) = try await session.data(for: request)`);
|
|
8115
|
-
emitter.block("guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {", "}", () => {
|
|
8116
|
-
emitter.line("throw URLError(.badServerResponse)");
|
|
8117
|
-
});
|
|
8118
|
-
if (retType !== "Void") {
|
|
8119
|
-
emitter.line(`return try JSONDecoder().decode(${retType}.self, from: data)`);
|
|
8120
8952
|
}
|
|
8121
|
-
|
|
8953
|
+
);
|
|
8122
8954
|
}
|
|
8123
8955
|
buildResponseType(ep) {
|
|
8124
8956
|
const success = ep.successResponse;
|
|
@@ -8132,7 +8964,8 @@ var SwiftClientEmitter = class {
|
|
|
8132
8964
|
let t = "AnyCodable";
|
|
8133
8965
|
if (ref.ref) t = ref.ref;
|
|
8134
8966
|
else if (ref.inline && ref.inline.kind === "scalar") {
|
|
8135
|
-
if (ref.inline.scalar === "integer" || ref.inline.scalar === "number")
|
|
8967
|
+
if (ref.inline.scalar === "integer" || ref.inline.scalar === "number")
|
|
8968
|
+
t = "Double";
|
|
8136
8969
|
else if (ref.inline.scalar === "boolean") t = "Bool";
|
|
8137
8970
|
else t = "String";
|
|
8138
8971
|
}
|
|
@@ -8152,7 +8985,9 @@ var SwiftGenerator = class extends Generator {
|
|
|
8152
8985
|
this.addFile("Types.swift", typeEmitter.emitAll());
|
|
8153
8986
|
const clientEmitter = new SwiftClientEmitter(this.schema, "ApiClient");
|
|
8154
8987
|
this.addFile("Client.swift", clientEmitter.emitAll());
|
|
8155
|
-
this.addFile(
|
|
8988
|
+
this.addFile(
|
|
8989
|
+
"Package.swift",
|
|
8990
|
+
`// swift-tools-version:5.5
|
|
8156
8991
|
import PackageDescription
|
|
8157
8992
|
|
|
8158
8993
|
let package = Package(
|
|
@@ -8163,7 +8998,8 @@ let package = Package(
|
|
|
8163
8998
|
targets: [
|
|
8164
8999
|
.target(name: "${this.options.packageName}", path: ".")
|
|
8165
9000
|
]
|
|
8166
|
-
)`
|
|
9001
|
+
)`
|
|
9002
|
+
);
|
|
8167
9003
|
return this.files;
|
|
8168
9004
|
}
|
|
8169
9005
|
};
|
|
@@ -8179,19 +9015,199 @@ var TsClientEmitter = class {
|
|
|
8179
9015
|
className;
|
|
8180
9016
|
emitAll() {
|
|
8181
9017
|
const emitter = new Emitter();
|
|
8182
|
-
emitter.line(
|
|
9018
|
+
emitter.line(
|
|
9019
|
+
`import { BaseClient, WebSocketClient, type ClientConfig, type WebSocketClientOptions } from '@axiomify/sdk-runtime';`
|
|
9020
|
+
);
|
|
8183
9021
|
emitter.line(`import type * as Types from './types';`);
|
|
8184
9022
|
emitter.line();
|
|
8185
|
-
emitter.block(
|
|
8186
|
-
|
|
8187
|
-
|
|
8188
|
-
|
|
8189
|
-
|
|
8190
|
-
|
|
8191
|
-
|
|
8192
|
-
|
|
9023
|
+
emitter.block(
|
|
9024
|
+
`export class ${this.className} extends BaseClient {`,
|
|
9025
|
+
`}`,
|
|
9026
|
+
() => {
|
|
9027
|
+
emitter.block(`constructor(config: ClientConfig) {`, `}`, () => {
|
|
9028
|
+
emitter.line(`super(config);`);
|
|
9029
|
+
});
|
|
9030
|
+
for (const ep of this.schema.endpoints) {
|
|
9031
|
+
if (ep.transport !== "rest") continue;
|
|
9032
|
+
emitter.line();
|
|
9033
|
+
this.emitMethod(emitter, ep);
|
|
9034
|
+
}
|
|
9035
|
+
const channels2 = /* @__PURE__ */ new Map();
|
|
9036
|
+
if (this.schema.events) {
|
|
9037
|
+
for (const event of this.schema.events) {
|
|
9038
|
+
const list = channels2.get(event.channel || "/") || [];
|
|
9039
|
+
list.push(event);
|
|
9040
|
+
channels2.set(event.channel || "/", list);
|
|
9041
|
+
}
|
|
9042
|
+
}
|
|
9043
|
+
for (const [channelName, events] of channels2.entries()) {
|
|
9044
|
+
const className = toClassName(channelName);
|
|
9045
|
+
const clientClassName = `${className}ChannelClient`;
|
|
9046
|
+
const params = extractParams(channelName);
|
|
9047
|
+
emitter.line();
|
|
9048
|
+
if (params.length > 0) {
|
|
9049
|
+
const paramSignature = `params: { ${params.map((p) => `${p}: string`).join(", ")} }, options?: WebSocketClientOptions`;
|
|
9050
|
+
emitter.block(
|
|
9051
|
+
`public ${toMethodName(className)}(${paramSignature}): ${clientClassName} {`,
|
|
9052
|
+
`}`,
|
|
9053
|
+
() => {
|
|
9054
|
+
emitter.line(
|
|
9055
|
+
`const wsBase = this.config.baseUrl.replace(/^http/, 'ws');`
|
|
9056
|
+
);
|
|
9057
|
+
let pathExpr = channelName;
|
|
9058
|
+
for (const p of params) {
|
|
9059
|
+
pathExpr = pathExpr.replace(`{${p}}`, `\${params.${p}}`).replace(`:${p}`, `\${params.${p}}`);
|
|
9060
|
+
}
|
|
9061
|
+
emitter.line(
|
|
9062
|
+
`return new ${clientClassName}(\`\${wsBase}${pathExpr}\`, options);`
|
|
9063
|
+
);
|
|
9064
|
+
}
|
|
9065
|
+
);
|
|
9066
|
+
} else {
|
|
9067
|
+
emitter.block(
|
|
9068
|
+
`public ${toMethodName(className)}(options?: WebSocketClientOptions): ${clientClassName} {`,
|
|
9069
|
+
`}`,
|
|
9070
|
+
() => {
|
|
9071
|
+
emitter.line(
|
|
9072
|
+
`const wsBase = this.config.baseUrl.replace(/^http/, 'ws');`
|
|
9073
|
+
);
|
|
9074
|
+
emitter.line(
|
|
9075
|
+
`return new ${clientClassName}(\`\${wsBase}${channelName}\`, options);`
|
|
9076
|
+
);
|
|
9077
|
+
}
|
|
9078
|
+
);
|
|
9079
|
+
}
|
|
9080
|
+
}
|
|
8193
9081
|
}
|
|
8194
|
-
|
|
9082
|
+
);
|
|
9083
|
+
const channels = /* @__PURE__ */ new Map();
|
|
9084
|
+
if (this.schema.events) {
|
|
9085
|
+
for (const event of this.schema.events) {
|
|
9086
|
+
const list = channels.get(event.channel || "/") || [];
|
|
9087
|
+
list.push(event);
|
|
9088
|
+
channels.set(event.channel || "/", list);
|
|
9089
|
+
}
|
|
9090
|
+
}
|
|
9091
|
+
for (const [channelName, events] of channels.entries()) {
|
|
9092
|
+
const className = toClassName(channelName);
|
|
9093
|
+
const clientClassName = `${className}ChannelClient`;
|
|
9094
|
+
emitter.line();
|
|
9095
|
+
emitter.block(`export class ${clientClassName} {`, `}`, () => {
|
|
9096
|
+
emitter.line(`private ws: WebSocketClient;`);
|
|
9097
|
+
emitter.line(
|
|
9098
|
+
`private listeners = new Map<string, Set<(data: any) => void>>();`
|
|
9099
|
+
);
|
|
9100
|
+
emitter.line();
|
|
9101
|
+
emitter.block(
|
|
9102
|
+
`constructor(url: string, options?: WebSocketClientOptions) {`,
|
|
9103
|
+
`}`,
|
|
9104
|
+
() => {
|
|
9105
|
+
emitter.block(`this.ws = new WebSocketClient(url, {`, `});`, () => {
|
|
9106
|
+
emitter.line(`...options,`);
|
|
9107
|
+
emitter.block(`onMessage: (data: string) => {`, `},`, () => {
|
|
9108
|
+
emitter.line(`options?.onMessage?.(data);`);
|
|
9109
|
+
emitter.block(`try {`, `} catch (e) {`, () => {
|
|
9110
|
+
emitter.line(`const parsed = JSON.parse(data);`);
|
|
9111
|
+
emitter.line(
|
|
9112
|
+
`const eventName = String(parsed.event || parsed.type || parsed.action || '').toLowerCase();`
|
|
9113
|
+
);
|
|
9114
|
+
emitter.line(`let matched = false;`);
|
|
9115
|
+
emitter.block(
|
|
9116
|
+
`for (const [registeredName, list] of this.listeners.entries()) {`,
|
|
9117
|
+
`}`,
|
|
9118
|
+
() => {
|
|
9119
|
+
emitter.block(
|
|
9120
|
+
`if (registeredName.toLowerCase() === eventName) {`,
|
|
9121
|
+
`}`,
|
|
9122
|
+
() => {
|
|
9123
|
+
emitter.line(
|
|
9124
|
+
`const payload = parsed.data !== undefined ? parsed.data : (parsed.payload !== undefined ? parsed.payload : parsed);`
|
|
9125
|
+
);
|
|
9126
|
+
emitter.block(`for (const cb of list) {`, `}`, () => {
|
|
9127
|
+
emitter.line(`cb(payload);`);
|
|
9128
|
+
});
|
|
9129
|
+
emitter.line(`matched = true;`);
|
|
9130
|
+
}
|
|
9131
|
+
);
|
|
9132
|
+
}
|
|
9133
|
+
);
|
|
9134
|
+
emitter.block(`if (!matched) {`, `}`, () => {
|
|
9135
|
+
emitter.block(
|
|
9136
|
+
`for (const list of this.listeners.values()) {`,
|
|
9137
|
+
`}`,
|
|
9138
|
+
() => {
|
|
9139
|
+
emitter.block(`for (const cb of list) {`, `}`, () => {
|
|
9140
|
+
emitter.line(`cb(parsed);`);
|
|
9141
|
+
});
|
|
9142
|
+
}
|
|
9143
|
+
);
|
|
9144
|
+
});
|
|
9145
|
+
});
|
|
9146
|
+
emitter.block(``, `}`, () => {
|
|
9147
|
+
emitter.block(
|
|
9148
|
+
`for (const list of this.listeners.values()) {`,
|
|
9149
|
+
`}`,
|
|
9150
|
+
() => {
|
|
9151
|
+
emitter.block(`for (const cb of list) {`, `}`, () => {
|
|
9152
|
+
emitter.line(`cb(data);`);
|
|
9153
|
+
});
|
|
9154
|
+
}
|
|
9155
|
+
);
|
|
9156
|
+
});
|
|
9157
|
+
});
|
|
9158
|
+
});
|
|
9159
|
+
}
|
|
9160
|
+
);
|
|
9161
|
+
emitter.line();
|
|
9162
|
+
emitter.block(`public connect(): void {`, `}`, () => {
|
|
9163
|
+
emitter.line(`this.ws.connect();`);
|
|
9164
|
+
});
|
|
9165
|
+
emitter.line();
|
|
9166
|
+
emitter.block(`public disconnect(): void {`, `}`, () => {
|
|
9167
|
+
emitter.line(`this.ws.disconnect();`);
|
|
9168
|
+
});
|
|
9169
|
+
for (const event of events) {
|
|
9170
|
+
const eventName = event.name;
|
|
9171
|
+
const payloadType = event.payload ? this.renderTypeRef(event.payload) : "any";
|
|
9172
|
+
const capEventName = eventName.charAt(0).toUpperCase() + eventName.slice(1);
|
|
9173
|
+
const direction = event.direction;
|
|
9174
|
+
if (direction === "inbound" || direction === "bidirectional") {
|
|
9175
|
+
emitter.line();
|
|
9176
|
+
emitter.block(
|
|
9177
|
+
`public on${capEventName}(callback: (payload: ${payloadType}) => void): () => void {`,
|
|
9178
|
+
`}`,
|
|
9179
|
+
() => {
|
|
9180
|
+
emitter.line(`let list = this.listeners.get('${eventName}');`);
|
|
9181
|
+
emitter.block(`if (!list) {`, `}`, () => {
|
|
9182
|
+
emitter.line(`list = new Set();`);
|
|
9183
|
+
emitter.line(`this.listeners.set('${eventName}', list);`);
|
|
9184
|
+
});
|
|
9185
|
+
emitter.line(`list.add(callback);`);
|
|
9186
|
+
emitter.block(`return () => {`, `};`, () => {
|
|
9187
|
+
emitter.line(`list.delete(callback);`);
|
|
9188
|
+
});
|
|
9189
|
+
}
|
|
9190
|
+
);
|
|
9191
|
+
}
|
|
9192
|
+
if (direction === "outbound" || direction === "bidirectional") {
|
|
9193
|
+
emitter.line();
|
|
9194
|
+
const paramSig = event.payload ? `payload: ${payloadType}` : `payload?: any`;
|
|
9195
|
+
emitter.block(
|
|
9196
|
+
`public send${capEventName}(${paramSig}): void {`,
|
|
9197
|
+
`}`,
|
|
9198
|
+
() => {
|
|
9199
|
+
emitter.block(`this.ws.send(JSON.stringify({`, `}));`, () => {
|
|
9200
|
+
emitter.line(`event: '${eventName}',`);
|
|
9201
|
+
emitter.line(
|
|
9202
|
+
`data: ${event.payload ? "payload" : "undefined"}`
|
|
9203
|
+
);
|
|
9204
|
+
});
|
|
9205
|
+
}
|
|
9206
|
+
);
|
|
9207
|
+
}
|
|
9208
|
+
}
|
|
9209
|
+
});
|
|
9210
|
+
}
|
|
8195
9211
|
return emitter.toString();
|
|
8196
9212
|
}
|
|
8197
9213
|
emitMethod(emitter, ep) {
|
|
@@ -8215,7 +9231,7 @@ var TsClientEmitter = class {
|
|
|
8215
9231
|
emitter.block(methodSignature, `}`, () => {
|
|
8216
9232
|
const method = ep.method?.toUpperCase() || "GET";
|
|
8217
9233
|
const pathTemplate = ep.path || "/";
|
|
8218
|
-
|
|
9234
|
+
const pathExpr = `\`${pathTemplate.replace(/\{([^}]+)\}/g, "${request.$1}")}\``;
|
|
8219
9235
|
let reqOpts = `method: '${method}', path: ${pathExpr}`;
|
|
8220
9236
|
const isValidTSIdentifier = (name) => /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
|
|
8221
9237
|
if (ep.queryParams.length > 0) {
|
|
@@ -8236,11 +9252,22 @@ var TsClientEmitter = class {
|
|
|
8236
9252
|
buildRequestType(ep) {
|
|
8237
9253
|
const props = [];
|
|
8238
9254
|
const formatProp = (name) => /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name) ? name : `'${name}'`;
|
|
8239
|
-
for (const p of ep.pathParams)
|
|
8240
|
-
|
|
8241
|
-
|
|
9255
|
+
for (const p of ep.pathParams)
|
|
9256
|
+
props.push(
|
|
9257
|
+
`${formatProp(p.name)}${p.required ? "" : "?"}: ${this.renderTypeRef(p.type)}`
|
|
9258
|
+
);
|
|
9259
|
+
for (const p of ep.queryParams)
|
|
9260
|
+
props.push(
|
|
9261
|
+
`${formatProp(p.name)}${p.required ? "" : "?"}: ${this.renderTypeRef(p.type)}`
|
|
9262
|
+
);
|
|
9263
|
+
for (const p of ep.headerParams)
|
|
9264
|
+
props.push(
|
|
9265
|
+
`${formatProp(p.name)}${p.required ? "" : "?"}: ${this.renderTypeRef(p.type)}`
|
|
9266
|
+
);
|
|
8242
9267
|
if (ep.requestBody) {
|
|
8243
|
-
props.push(
|
|
9268
|
+
props.push(
|
|
9269
|
+
`body${ep.requestBody.required ? "" : "?"}: ${this.renderTypeRef(ep.requestBody.type)}`
|
|
9270
|
+
);
|
|
8244
9271
|
}
|
|
8245
9272
|
if (props.length === 0) return null;
|
|
8246
9273
|
return `{ ${props.join(", ")} }`;
|
|
@@ -8258,7 +9285,8 @@ var TsClientEmitter = class {
|
|
|
8258
9285
|
if (ref.ref) t = `Types.${ref.ref}`;
|
|
8259
9286
|
else if (ref.inline) {
|
|
8260
9287
|
if (ref.inline.kind === "scalar") {
|
|
8261
|
-
if (ref.inline.scalar === "integer" || ref.inline.scalar === "number")
|
|
9288
|
+
if (ref.inline.scalar === "integer" || ref.inline.scalar === "number")
|
|
9289
|
+
t = "number";
|
|
8262
9290
|
else if (ref.inline.scalar === "boolean") t = "boolean";
|
|
8263
9291
|
else t = "string";
|
|
8264
9292
|
} else if (ref.inline.kind === "array") {
|
|
@@ -8270,6 +9298,25 @@ var TsClientEmitter = class {
|
|
|
8270
9298
|
return t;
|
|
8271
9299
|
}
|
|
8272
9300
|
};
|
|
9301
|
+
function toClassName(channel) {
|
|
9302
|
+
const parts = channel.split("/").filter(Boolean).map((p) => p.replace(/[{}]/g, "")).map((p) => p.replace(/[^a-zA-Z0-9]/g, "")).map((p) => p.charAt(0).toUpperCase() + p.slice(1));
|
|
9303
|
+
return parts.join("") || "Root";
|
|
9304
|
+
}
|
|
9305
|
+
function toMethodName(className) {
|
|
9306
|
+
return className.charAt(0).toLowerCase() + className.slice(1);
|
|
9307
|
+
}
|
|
9308
|
+
function extractParams(channel) {
|
|
9309
|
+
const params = [];
|
|
9310
|
+
const braceMatches = channel.matchAll(/\{([^}]+)\}/g);
|
|
9311
|
+
for (const m of braceMatches) {
|
|
9312
|
+
params.push(m[1]);
|
|
9313
|
+
}
|
|
9314
|
+
const colonMatches = channel.matchAll(/:([a-zA-Z0-9_]+)/g);
|
|
9315
|
+
for (const m of colonMatches) {
|
|
9316
|
+
params.push(m[1]);
|
|
9317
|
+
}
|
|
9318
|
+
return params;
|
|
9319
|
+
}
|
|
8273
9320
|
|
|
8274
9321
|
// src/sdk/generator/targets/typescript/validator-emitter.ts
|
|
8275
9322
|
var TsValidatorEmitter = class {
|
|
@@ -8296,29 +9343,45 @@ var TsValidatorEmitter = class {
|
|
|
8296
9343
|
emitValidator(emitter, type) {
|
|
8297
9344
|
switch (type.kind) {
|
|
8298
9345
|
case "object":
|
|
8299
|
-
emitter.block(
|
|
8300
|
-
|
|
8301
|
-
|
|
8302
|
-
|
|
8303
|
-
|
|
9346
|
+
emitter.block(
|
|
9347
|
+
`export const ${type.id}Schema = z.object({`,
|
|
9348
|
+
`});`,
|
|
9349
|
+
() => {
|
|
9350
|
+
for (const field of type.fields) {
|
|
9351
|
+
const zodChain = this.renderZodChain(field.type);
|
|
9352
|
+
const req = field.required ? "" : ".optional()";
|
|
9353
|
+
emitter.line(`${field.name}: ${zodChain}${req},`);
|
|
9354
|
+
}
|
|
8304
9355
|
}
|
|
8305
|
-
|
|
9356
|
+
);
|
|
8306
9357
|
break;
|
|
8307
9358
|
case "enum":
|
|
8308
|
-
type.values.map(
|
|
8309
|
-
|
|
9359
|
+
type.values.map(
|
|
9360
|
+
(v) => typeof v.value === "string" ? `"${v.value}"` : v.value
|
|
9361
|
+
).join(", ");
|
|
9362
|
+
emitter.line(
|
|
9363
|
+
`export const ${type.id}Schema = z.union([${type.values.map((v) => typeof v.value === "string" ? `z.literal("${v.value}")` : `z.literal(${v.value})`).join(", ")}]);`
|
|
9364
|
+
);
|
|
8310
9365
|
break;
|
|
8311
9366
|
case "union":
|
|
8312
|
-
emitter.line(
|
|
9367
|
+
emitter.line(
|
|
9368
|
+
`export const ${type.id}Schema = z.union([${type.members.map((m) => this.renderZodChain(m)).join(", ")}]);`
|
|
9369
|
+
);
|
|
8313
9370
|
break;
|
|
8314
9371
|
case "intersection":
|
|
8315
|
-
emitter.line(
|
|
9372
|
+
emitter.line(
|
|
9373
|
+
`export const ${type.id}Schema = z.intersection(${type.members.map((m) => this.renderZodChain(m)).join(", ")});`
|
|
9374
|
+
);
|
|
8316
9375
|
break;
|
|
8317
9376
|
case "array":
|
|
8318
|
-
emitter.line(
|
|
9377
|
+
emitter.line(
|
|
9378
|
+
`export const ${type.id}Schema = z.array(${this.renderZodChain(type.items)});`
|
|
9379
|
+
);
|
|
8319
9380
|
break;
|
|
8320
9381
|
case "scalar":
|
|
8321
|
-
emitter.line(
|
|
9382
|
+
emitter.line(
|
|
9383
|
+
`export const ${type.id}Schema = ${this.renderScalarZod(type.scalar)};`
|
|
9384
|
+
);
|
|
8322
9385
|
break;
|
|
8323
9386
|
default:
|
|
8324
9387
|
emitter.line(`export const ${type.id}Schema = z.any();`);
|
|
@@ -8329,8 +9392,10 @@ var TsValidatorEmitter = class {
|
|
|
8329
9392
|
let t = "z.any()";
|
|
8330
9393
|
if (ref.ref) t = `${ref.ref}Schema`;
|
|
8331
9394
|
else if (ref.inline) {
|
|
8332
|
-
if (ref.inline.kind === "scalar")
|
|
8333
|
-
|
|
9395
|
+
if (ref.inline.kind === "scalar")
|
|
9396
|
+
t = this.renderScalarZod(ref.inline.scalar);
|
|
9397
|
+
else if (ref.inline.kind === "array")
|
|
9398
|
+
t = `z.array(${this.renderZodChain(ref.inline.items)})`;
|
|
8334
9399
|
}
|
|
8335
9400
|
if (ref.isArray) t = `z.array(${t})`;
|
|
8336
9401
|
if (ref.nullable) t = `${t}.nullable()`;
|
|
@@ -8367,7 +9432,9 @@ var TsReactQueryEmitter = class {
|
|
|
8367
9432
|
schema;
|
|
8368
9433
|
emitAll(clientClassName = "ApiClient") {
|
|
8369
9434
|
const emitter = new Emitter();
|
|
8370
|
-
emitter.line(
|
|
9435
|
+
emitter.line(
|
|
9436
|
+
`import { useQuery, useMutation, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';`
|
|
9437
|
+
);
|
|
8371
9438
|
emitter.line(`import { ${clientClassName} } from './client';`);
|
|
8372
9439
|
emitter.line(`import type * as Types from './types';`);
|
|
8373
9440
|
emitter.line();
|
|
@@ -8390,12 +9457,18 @@ var TsReactQueryEmitter = class {
|
|
|
8390
9457
|
if (isMutation) {
|
|
8391
9458
|
const mutationFnArg = reqType ? `req` : ``;
|
|
8392
9459
|
const clientCallArg = reqType ? `req` : ``;
|
|
8393
|
-
emitter.block(
|
|
8394
|
-
|
|
8395
|
-
|
|
8396
|
-
|
|
8397
|
-
|
|
8398
|
-
|
|
9460
|
+
emitter.block(
|
|
9461
|
+
`use${operationName.charAt(0).toUpperCase()}${operationName.slice(1)}(options?: UseMutationOptions<${resType}, Error, ${reqType || "void"}>) {`,
|
|
9462
|
+
`}`,
|
|
9463
|
+
() => {
|
|
9464
|
+
emitter.block(`return useMutation({`, `});`, () => {
|
|
9465
|
+
emitter.line(
|
|
9466
|
+
`mutationFn: (${mutationFnArg}) => this.client.${operationName}(${clientCallArg}),`
|
|
9467
|
+
);
|
|
9468
|
+
emitter.line(`...options,`);
|
|
9469
|
+
});
|
|
9470
|
+
}
|
|
9471
|
+
);
|
|
8399
9472
|
} else {
|
|
8400
9473
|
const queryKeyParts = [`"${operationName}"`];
|
|
8401
9474
|
if (reqType) {
|
|
@@ -8406,7 +9479,9 @@ var TsReactQueryEmitter = class {
|
|
|
8406
9479
|
emitter.block(`${hookName}(${argsSignature}) {`, `}`, () => {
|
|
8407
9480
|
emitter.block(`return useQuery({`, `});`, () => {
|
|
8408
9481
|
emitter.line(`queryKey: [${queryKeyParts.join(", ")}],`);
|
|
8409
|
-
emitter.line(
|
|
9482
|
+
emitter.line(
|
|
9483
|
+
`queryFn: () => this.client.${operationName}(${clientCallArg}),`
|
|
9484
|
+
);
|
|
8410
9485
|
emitter.line(`...options,`);
|
|
8411
9486
|
});
|
|
8412
9487
|
});
|
|
@@ -8415,11 +9490,22 @@ var TsReactQueryEmitter = class {
|
|
|
8415
9490
|
buildRequestType(ep) {
|
|
8416
9491
|
const props = [];
|
|
8417
9492
|
const formatProp = (name) => /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name) ? name : `'${name}'`;
|
|
8418
|
-
for (const p of ep.pathParams)
|
|
8419
|
-
|
|
8420
|
-
|
|
9493
|
+
for (const p of ep.pathParams)
|
|
9494
|
+
props.push(
|
|
9495
|
+
`${formatProp(p.name)}${p.required ? "" : "?"}: ${this.renderTypeRef(p.type)}`
|
|
9496
|
+
);
|
|
9497
|
+
for (const p of ep.queryParams)
|
|
9498
|
+
props.push(
|
|
9499
|
+
`${formatProp(p.name)}${p.required ? "" : "?"}: ${this.renderTypeRef(p.type)}`
|
|
9500
|
+
);
|
|
9501
|
+
for (const p of ep.headerParams)
|
|
9502
|
+
props.push(
|
|
9503
|
+
`${formatProp(p.name)}${p.required ? "" : "?"}: ${this.renderTypeRef(p.type)}`
|
|
9504
|
+
);
|
|
8421
9505
|
if (ep.requestBody) {
|
|
8422
|
-
props.push(
|
|
9506
|
+
props.push(
|
|
9507
|
+
`body${ep.requestBody.required ? "" : "?"}: ${this.renderTypeRef(ep.requestBody.type)}`
|
|
9508
|
+
);
|
|
8423
9509
|
}
|
|
8424
9510
|
if (props.length === 0) return null;
|
|
8425
9511
|
return `{ ${props.join(", ")} }`;
|
|
@@ -8437,7 +9523,8 @@ var TsReactQueryEmitter = class {
|
|
|
8437
9523
|
if (ref.ref) t = `Types.${ref.ref}`;
|
|
8438
9524
|
else if (ref.inline) {
|
|
8439
9525
|
if (ref.inline.kind === "scalar") {
|
|
8440
|
-
if (ref.inline.scalar === "integer" || ref.inline.scalar === "number")
|
|
9526
|
+
if (ref.inline.scalar === "integer" || ref.inline.scalar === "number")
|
|
9527
|
+
t = "number";
|
|
8441
9528
|
else if (ref.inline.scalar === "boolean") t = "boolean";
|
|
8442
9529
|
else t = "string";
|
|
8443
9530
|
} else if (ref.inline.kind === "array") {
|
|
@@ -8462,21 +9549,31 @@ var TypeScriptGenerator = class extends Generator {
|
|
|
8462
9549
|
this.addFile("validators.ts", validatorEmitter.emitAll());
|
|
8463
9550
|
const hooksEmitter = new TsReactQueryEmitter(this.schema);
|
|
8464
9551
|
this.addFile("hooks.ts", hooksEmitter.emitAll("ApiClient"));
|
|
8465
|
-
this.addFile(
|
|
9552
|
+
this.addFile(
|
|
9553
|
+
"index.ts",
|
|
9554
|
+
`export * from './types';
|
|
8466
9555
|
export * from './client';
|
|
8467
9556
|
export * from './validators';
|
|
8468
9557
|
export * from './hooks';
|
|
8469
|
-
`
|
|
8470
|
-
|
|
8471
|
-
|
|
8472
|
-
|
|
8473
|
-
|
|
8474
|
-
|
|
8475
|
-
|
|
8476
|
-
|
|
8477
|
-
|
|
8478
|
-
|
|
8479
|
-
|
|
9558
|
+
`
|
|
9559
|
+
);
|
|
9560
|
+
this.addFile(
|
|
9561
|
+
"package.json",
|
|
9562
|
+
JSON.stringify(
|
|
9563
|
+
{
|
|
9564
|
+
name: this.options.packageName,
|
|
9565
|
+
version: this.options.version || "1.0.0",
|
|
9566
|
+
main: "index.ts",
|
|
9567
|
+
dependencies: {
|
|
9568
|
+
...this.options.runtime ? { "@axiomify/sdk-runtime": "latest" } : {},
|
|
9569
|
+
zod: "^3.22.0",
|
|
9570
|
+
"@tanstack/react-query": "^5.0.0"
|
|
9571
|
+
}
|
|
9572
|
+
},
|
|
9573
|
+
null,
|
|
9574
|
+
2
|
|
9575
|
+
)
|
|
9576
|
+
);
|
|
8480
9577
|
return this.files;
|
|
8481
9578
|
}
|
|
8482
9579
|
};
|
|
@@ -8488,18 +9585,37 @@ async function generateSdk(opts) {
|
|
|
8488
9585
|
console.log(`
|
|
8489
9586
|
${symbols.info} Initializing SDK compilation...
|
|
8490
9587
|
`);
|
|
9588
|
+
const projectRoot = path8__default.default.resolve(process.cwd());
|
|
9589
|
+
const resolvedOutput = path8__default.default.resolve(projectRoot, opts.output);
|
|
9590
|
+
const relative = path8__default.default.relative(projectRoot, resolvedOutput);
|
|
9591
|
+
if (relative.startsWith("..") || path8__default.default.isAbsolute(relative)) {
|
|
9592
|
+
console.error(
|
|
9593
|
+
pc__default.default.red(
|
|
9594
|
+
`\u2717 Output directory "${opts.output}" must be contained within the project root directory ("${projectRoot}").`
|
|
9595
|
+
)
|
|
9596
|
+
);
|
|
9597
|
+
if (opts.exitOnError !== false) process.exit(1);
|
|
9598
|
+
return false;
|
|
9599
|
+
}
|
|
8491
9600
|
let ingestionResult;
|
|
8492
9601
|
const inputExt = path8__default.default.extname(opts.input).toLowerCase();
|
|
8493
9602
|
try {
|
|
8494
9603
|
if (inputExt === ".ts" || inputExt === ".js") {
|
|
8495
|
-
console.log(
|
|
9604
|
+
console.log(
|
|
9605
|
+
` ${symbols.bullet} Ingesting Axiomify app from ${pc__default.default.cyan(opts.input)}...`
|
|
9606
|
+
);
|
|
8496
9607
|
const rootAbs = path8__default.default.resolve(process.cwd(), opts.input);
|
|
8497
9608
|
const { app, cleanup } = await loadApp(rootAbs);
|
|
8498
|
-
ingestionResult = ingestAxiomifyApp(app, {
|
|
9609
|
+
ingestionResult = ingestAxiomifyApp(app, {
|
|
9610
|
+
title: opts.name,
|
|
9611
|
+
version: opts.version
|
|
9612
|
+
});
|
|
8499
9613
|
await cleanup();
|
|
8500
9614
|
} else if (inputExt === ".json" || inputExt === ".yaml" || inputExt === ".yml") {
|
|
8501
|
-
|
|
8502
|
-
|
|
9615
|
+
const raw = await fs6__default.default.readFile(
|
|
9616
|
+
path8__default.default.resolve(process.cwd(), opts.input),
|
|
9617
|
+
"utf8"
|
|
9618
|
+
);
|
|
8503
9619
|
let parsed;
|
|
8504
9620
|
if (inputExt === ".json") {
|
|
8505
9621
|
parsed = JSON.parse(raw);
|
|
@@ -8507,13 +9623,41 @@ ${symbols.info} Initializing SDK compilation...
|
|
|
8507
9623
|
const yaml = __require("yaml");
|
|
8508
9624
|
parsed = yaml.parse(raw);
|
|
8509
9625
|
}
|
|
8510
|
-
|
|
9626
|
+
if (parsed && typeof parsed === "object" && "asyncapi" in parsed) {
|
|
9627
|
+
console.log(
|
|
9628
|
+
` ${symbols.bullet} Ingesting AsyncAPI spec from ${pc__default.default.cyan(opts.input)}...`
|
|
9629
|
+
);
|
|
9630
|
+
ingestionResult = ingestAsyncApi(parsed, {
|
|
9631
|
+
title: opts.name,
|
|
9632
|
+
version: opts.version
|
|
9633
|
+
});
|
|
9634
|
+
} else {
|
|
9635
|
+
console.log(
|
|
9636
|
+
` ${symbols.bullet} Ingesting OpenAPI spec from ${pc__default.default.cyan(opts.input)}...`
|
|
9637
|
+
);
|
|
9638
|
+
ingestionResult = ingestOpenApi(parsed, {
|
|
9639
|
+
title: opts.name,
|
|
9640
|
+
version: opts.version
|
|
9641
|
+
});
|
|
9642
|
+
}
|
|
8511
9643
|
} else if (inputExt === ".graphql" || inputExt === ".gql") {
|
|
8512
|
-
console.log(
|
|
8513
|
-
|
|
8514
|
-
|
|
9644
|
+
console.log(
|
|
9645
|
+
` ${symbols.bullet} Ingesting GraphQL SDL from ${pc__default.default.cyan(opts.input)}...`
|
|
9646
|
+
);
|
|
9647
|
+
const raw = await fs6__default.default.readFile(
|
|
9648
|
+
path8__default.default.resolve(process.cwd(), opts.input),
|
|
9649
|
+
"utf8"
|
|
9650
|
+
);
|
|
9651
|
+
ingestionResult = await ingestGraphQL(raw, {
|
|
9652
|
+
title: opts.name,
|
|
9653
|
+
version: opts.version
|
|
9654
|
+
});
|
|
8515
9655
|
} else {
|
|
8516
|
-
console.error(
|
|
9656
|
+
console.error(
|
|
9657
|
+
pc__default.default.red(
|
|
9658
|
+
`\u2717 Unsupported input type: ${inputExt}. Use .ts (App), .json/.yaml (OpenAPI), or .graphql (GraphQL)`
|
|
9659
|
+
)
|
|
9660
|
+
);
|
|
8517
9661
|
if (opts.exitOnError !== false) process.exit(1);
|
|
8518
9662
|
return false;
|
|
8519
9663
|
}
|
|
@@ -8524,8 +9668,10 @@ ${symbols.info} Initializing SDK compilation...
|
|
|
8524
9668
|
}
|
|
8525
9669
|
if (ingestionResult.diagnostics.length > 0) {
|
|
8526
9670
|
for (const d of ingestionResult.diagnostics) {
|
|
8527
|
-
if (d.severity === "error")
|
|
8528
|
-
|
|
9671
|
+
if (d.severity === "error")
|
|
9672
|
+
console.error(pc__default.default.red(` [Error] ${d.code}: ${d.message}`));
|
|
9673
|
+
else if (d.severity === "warning")
|
|
9674
|
+
console.warn(pc__default.default.yellow(` [Warn] ${d.code}: ${d.message}`));
|
|
8529
9675
|
}
|
|
8530
9676
|
if (ingestionResult.diagnostics.some((d) => d.severity === "error")) {
|
|
8531
9677
|
if (opts.exitOnError !== false) process.exit(1);
|
|
@@ -8537,21 +9683,30 @@ ${symbols.info} Initializing SDK compilation...
|
|
|
8537
9683
|
const compilation = await compiler.compile(ingestionResult.schema);
|
|
8538
9684
|
if (compilation.hasErrors) {
|
|
8539
9685
|
for (const d of compilation.diagnostics) {
|
|
8540
|
-
if (d.severity === "error")
|
|
9686
|
+
if (d.severity === "error")
|
|
9687
|
+
console.error(pc__default.default.red(` [Error] ${d.code}: ${d.message}`));
|
|
8541
9688
|
}
|
|
8542
9689
|
console.error(pc__default.default.red(`
|
|
8543
9690
|
\u2717 Compilation failed.`));
|
|
8544
9691
|
if (opts.exitOnError !== false) process.exit(1);
|
|
8545
9692
|
return false;
|
|
8546
9693
|
}
|
|
8547
|
-
console.log(
|
|
8548
|
-
|
|
9694
|
+
console.log(
|
|
9695
|
+
` ${symbols.ok} IR compiled successfully in ${compilation.durationMs}ms`
|
|
9696
|
+
);
|
|
9697
|
+
console.log(
|
|
9698
|
+
pc__default.default.dim(
|
|
9699
|
+
` (${compilation.schema.endpoints.length} endpoints, ${compilation.schema.types.size} types)`
|
|
9700
|
+
)
|
|
9701
|
+
);
|
|
8549
9702
|
for (const t of opts.target) {
|
|
8550
9703
|
const GeneratorClass = GeneratorRegistry.get(t);
|
|
8551
9704
|
if (!GeneratorClass) {
|
|
8552
9705
|
console.error(pc__default.default.red(`
|
|
8553
9706
|
\u2717 Unknown generator target: "${t}"`));
|
|
8554
|
-
console.error(
|
|
9707
|
+
console.error(
|
|
9708
|
+
` Available targets: ${GeneratorRegistry.targets().join(", ")}`
|
|
9709
|
+
);
|
|
8555
9710
|
continue;
|
|
8556
9711
|
}
|
|
8557
9712
|
console.log(`
|
|
@@ -8566,8 +9721,11 @@ ${symbols.info} Initializing SDK compilation...
|
|
|
8566
9721
|
try {
|
|
8567
9722
|
const files = await generator.generate();
|
|
8568
9723
|
if (opts.dryRun) {
|
|
8569
|
-
console.log(
|
|
8570
|
-
|
|
9724
|
+
console.log(
|
|
9725
|
+
` ${symbols.ok} [Dry Run] Would write ${files.length} files to ${path8__default.default.relative(process.cwd(), outDir)}`
|
|
9726
|
+
);
|
|
9727
|
+
for (const f of files)
|
|
9728
|
+
console.log(pc__default.default.dim(` - ${f.path} (${f.content.length} bytes)`));
|
|
8571
9729
|
} else {
|
|
8572
9730
|
await fs6__default.default.mkdir(outDir, { recursive: true });
|
|
8573
9731
|
for (const f of files) {
|
|
@@ -8576,7 +9734,9 @@ ${symbols.info} Initializing SDK compilation...
|
|
|
8576
9734
|
await fs6__default.default.writeFile(fullPath, f.content, "utf8");
|
|
8577
9735
|
console.log(pc__default.default.dim(` Wrote ${f.path}`));
|
|
8578
9736
|
}
|
|
8579
|
-
console.log(
|
|
9737
|
+
console.log(
|
|
9738
|
+
` ${symbols.ok} Wrote ${files.length} files to ${path8__default.default.relative(process.cwd(), outDir)}`
|
|
9739
|
+
);
|
|
8580
9740
|
}
|
|
8581
9741
|
} catch (err) {
|
|
8582
9742
|
console.error(pc__default.default.red(` \u2717 Generator failed: ${err.message}`));
|
|
@@ -8758,7 +9918,9 @@ function checkDependencyDrift(findings) {
|
|
|
8758
9918
|
return;
|
|
8759
9919
|
}
|
|
8760
9920
|
const versions = new Set(
|
|
8761
|
-
axiomifyDeps.map(
|
|
9921
|
+
axiomifyDeps.map(
|
|
9922
|
+
([, v]) => v.replace(/^[\^~]/, "").replace(/^\*$/, "workspace")
|
|
9923
|
+
)
|
|
8762
9924
|
);
|
|
8763
9925
|
if (versions.size > 1) {
|
|
8764
9926
|
add2(findings, {
|
|
@@ -8876,7 +10038,10 @@ async function runDoctor() {
|
|
|
8876
10038
|
const tag = pc__default.default.dim(`[${f.area}]`);
|
|
8877
10039
|
console.log(` ${sym[f.severity]} ${tag} ${f.message}`);
|
|
8878
10040
|
if (f.hint && f.severity !== "ok") {
|
|
8879
|
-
const wrapped = f.hint.replace(
|
|
10041
|
+
const wrapped = f.hint.replace(
|
|
10042
|
+
/(.{1,80})(\s+|$)/g,
|
|
10043
|
+
"\n " + pc__default.default.dim("$1")
|
|
10044
|
+
);
|
|
8880
10045
|
console.log(wrapped);
|
|
8881
10046
|
}
|
|
8882
10047
|
}
|
|
@@ -9212,11 +10377,20 @@ var RULES = [
|
|
|
9212
10377
|
];
|
|
9213
10378
|
async function listSourceFiles(rootAbs) {
|
|
9214
10379
|
const out = [];
|
|
9215
|
-
const skip = /* @__PURE__ */ new Set([
|
|
10380
|
+
const skip = /* @__PURE__ */ new Set([
|
|
10381
|
+
"node_modules",
|
|
10382
|
+
".git",
|
|
10383
|
+
"dist",
|
|
10384
|
+
"build",
|
|
10385
|
+
".axiomify",
|
|
10386
|
+
"coverage"
|
|
10387
|
+
]);
|
|
9216
10388
|
const walk = async (dir) => {
|
|
9217
10389
|
let entries;
|
|
9218
10390
|
try {
|
|
9219
|
-
entries = await fs6__default.default.readdir(dir, {
|
|
10391
|
+
entries = await fs6__default.default.readdir(dir, {
|
|
10392
|
+
withFileTypes: true
|
|
10393
|
+
});
|
|
9220
10394
|
} catch {
|
|
9221
10395
|
return;
|
|
9222
10396
|
}
|
|
@@ -9305,7 +10479,9 @@ async function runMigrate(opts = {}) {
|
|
|
9305
10479
|
)
|
|
9306
10480
|
);
|
|
9307
10481
|
if (results.length === 0) {
|
|
9308
|
-
console.log(
|
|
10482
|
+
console.log(
|
|
10483
|
+
` ${symbols.ok} Nothing to migrate \u2014 all patterns look up to date.`
|
|
10484
|
+
);
|
|
9309
10485
|
console.log();
|
|
9310
10486
|
return;
|
|
9311
10487
|
}
|
|
@@ -9318,9 +10494,7 @@ async function runMigrate(opts = {}) {
|
|
|
9318
10494
|
for (const rule of RULES) {
|
|
9319
10495
|
const count = totalsByRule[rule.id];
|
|
9320
10496
|
if (!count) continue;
|
|
9321
|
-
console.log(
|
|
9322
|
-
` ${pc__default.default.cyan(rule.id)} ${pc__default.default.dim("\u2014")} ${rule.description}`
|
|
9323
|
-
);
|
|
10497
|
+
console.log(` ${pc__default.default.cyan(rule.id)} ${pc__default.default.dim("\u2014")} ${rule.description}`);
|
|
9324
10498
|
console.log(
|
|
9325
10499
|
` ${symbols.bullet} ${pluralise(count, "change")} across ${pluralise(
|
|
9326
10500
|
results.filter((r) => r.counts[rule.id]).length,
|
|
@@ -9348,7 +10522,9 @@ async function runMigrate(opts = {}) {
|
|
|
9348
10522
|
}
|
|
9349
10523
|
for (const r of results) {
|
|
9350
10524
|
await fs6__default.default.writeFile(r.file, r.updated, "utf8");
|
|
9351
|
-
console.log(
|
|
10525
|
+
console.log(
|
|
10526
|
+
` ${symbols.ok} ${pc__default.default.green("Updated")} ${path8__default.default.relative(process.cwd(), r.file)}`
|
|
10527
|
+
);
|
|
9352
10528
|
}
|
|
9353
10529
|
console.log();
|
|
9354
10530
|
console.log(
|
|
@@ -9391,7 +10567,9 @@ async function runMigrate(opts = {}) {
|
|
|
9391
10567
|
);
|
|
9392
10568
|
console.log();
|
|
9393
10569
|
console.log(
|
|
9394
|
-
` See ${pc__default.default.cyan("docs/migration-v4-to-v5.md")} for the full guide and ` + pc__default.default.cyan("axiomify check") + " to verify the migrated app.\n" + pc__default.default.yellow(
|
|
10570
|
+
` See ${pc__default.default.cyan("docs/migration-v4-to-v5.md")} for the full guide and ` + pc__default.default.cyan("axiomify check") + " to verify the migrated app.\n" + pc__default.default.yellow(
|
|
10571
|
+
" Note: `openapi:` / `meta:` merges into `schema:` require manual review \u2014 check TODO comments."
|
|
10572
|
+
)
|
|
9395
10573
|
);
|
|
9396
10574
|
console.log();
|
|
9397
10575
|
}
|
|
@@ -9408,8 +10586,10 @@ async function jsonToYaml(obj) {
|
|
|
9408
10586
|
}
|
|
9409
10587
|
if (Array.isArray(v)) {
|
|
9410
10588
|
if (v.length === 0) return "[]";
|
|
9411
|
-
return v.map(
|
|
9412
|
-
|
|
10589
|
+
return v.map(
|
|
10590
|
+
(item) => `
|
|
10591
|
+
${pad2}- ${emit(item, indent + 1).replace(/^/gm, " ").trimStart()}`
|
|
10592
|
+
).join("");
|
|
9413
10593
|
}
|
|
9414
10594
|
if (typeof v === "object") {
|
|
9415
10595
|
const keys = Object.keys(v);
|
|
@@ -9468,7 +10648,9 @@ async function emitOpenApi(entry, opts = {}) {
|
|
|
9468
10648
|
await fs6__default.default.writeFile(outPath, serialised + "\n", "utf8");
|
|
9469
10649
|
const routeCount = (app.registeredRoutes ?? []).length;
|
|
9470
10650
|
console.log(
|
|
9471
|
-
`${pc__default.default.green("\u2713")} OpenAPI spec written to ${pc__default.default.cyan(opts.output)} ` + pc__default.default.dim(
|
|
10651
|
+
`${pc__default.default.green("\u2713")} OpenAPI spec written to ${pc__default.default.cyan(opts.output)} ` + pc__default.default.dim(
|
|
10652
|
+
`(${routeCount} route${routeCount === 1 ? "" : "s"}, ${format})`
|
|
10653
|
+
)
|
|
9472
10654
|
);
|
|
9473
10655
|
} else {
|
|
9474
10656
|
process.stdout.write(serialised + "\n");
|
|
@@ -9587,14 +10769,20 @@ async function inspectRoutes(entry, opts = {}) {
|
|
|
9587
10769
|
];
|
|
9588
10770
|
const rows = filtered.map((r) => {
|
|
9589
10771
|
const method = colourMethod(r.method);
|
|
9590
|
-
const highlightedPath = r.path.replace(
|
|
10772
|
+
const highlightedPath = r.path.replace(
|
|
10773
|
+
/:[a-zA-Z0-9_]+/g,
|
|
10774
|
+
(match) => pc__default.default.yellow(match)
|
|
10775
|
+
);
|
|
9591
10776
|
const path12 = r.deprecated ? pc__default.default.strikethrough(highlightedPath) + " " + badge.deprecated() : highlightedPath;
|
|
9592
10777
|
const validation = r.validation.length > 0 ? r.validation.map(badge.validation).join(pc__default.default.dim(",")) : pc__default.default.dim("\u2014");
|
|
9593
10778
|
const metaBits = [];
|
|
9594
10779
|
if (r.operationId) metaBits.push(pc__default.default.dim(`op:`) + r.operationId);
|
|
9595
10780
|
if (r.tags.length) metaBits.push(badge.tags(r.tags));
|
|
9596
10781
|
if (r.timeout !== void 0) metaBits.push(badge.timeout(r.timeout));
|
|
9597
|
-
if (r.plugins > 0)
|
|
10782
|
+
if (r.plugins > 0)
|
|
10783
|
+
metaBits.push(
|
|
10784
|
+
pc__default.default.dim(`+${r.plugins} plugin${r.plugins === 1 ? "" : "s"}`)
|
|
10785
|
+
);
|
|
9598
10786
|
const meta = metaBits.length ? metaBits.join(" ") : pc__default.default.dim("\u2014");
|
|
9599
10787
|
return [method, path12, validation, meta];
|
|
9600
10788
|
});
|
|
@@ -9753,10 +10941,7 @@ async function scaffoldRoute(method, routePath, opts = {}) {
|
|
|
9753
10941
|
process.exit(1);
|
|
9754
10942
|
}
|
|
9755
10943
|
if (!routePath.startsWith("/")) {
|
|
9756
|
-
console.error(
|
|
9757
|
-
pc__default.default.red('\u2717 Path must start with "/".'),
|
|
9758
|
-
`Got: ${routePath}`
|
|
9759
|
-
);
|
|
10944
|
+
console.error(pc__default.default.red('\u2717 Path must start with "/".'), `Got: ${routePath}`);
|
|
9760
10945
|
process.exit(1);
|
|
9761
10946
|
}
|
|
9762
10947
|
const dir = opts.dir ?? "src/routes";
|
|
@@ -9764,8 +10949,10 @@ async function scaffoldRoute(method, routePath, opts = {}) {
|
|
|
9764
10949
|
const fileAbs = path8__default.default.resolve(process.cwd(), dir, filename);
|
|
9765
10950
|
const source = generateRouteSource(upperMethod, routePath, opts);
|
|
9766
10951
|
if (opts.dryRun) {
|
|
9767
|
-
console.log(
|
|
9768
|
-
|
|
10952
|
+
console.log(
|
|
10953
|
+
pc__default.default.dim(`# would write ${path8__default.default.relative(process.cwd(), fileAbs)}
|
|
10954
|
+
`)
|
|
10955
|
+
);
|
|
9769
10956
|
console.log(source);
|
|
9770
10957
|
return;
|
|
9771
10958
|
}
|
|
@@ -9792,8 +10979,10 @@ async function scaffoldRoute(method, routePath, opts = {}) {
|
|
|
9792
10979
|
console.log(pc__default.default.dim(" Next steps:"));
|
|
9793
10980
|
console.log(
|
|
9794
10981
|
` 1. Wire it into your entry file:
|
|
9795
|
-
` + pc__default.default.dim(
|
|
9796
|
-
`
|
|
10982
|
+
` + pc__default.default.dim(
|
|
10983
|
+
` import { registerRoute } from './routes/${pathToFilename(routePath)}';
|
|
10984
|
+
`
|
|
10985
|
+
) + pc__default.default.dim(` registerRoute(app);`)
|
|
9797
10986
|
);
|
|
9798
10987
|
console.log(
|
|
9799
10988
|
` 2. Fill in the TODOs in ${pc__default.default.cyan(path8__default.default.relative(process.cwd(), fileAbs))}.`
|
|
@@ -9813,17 +11002,30 @@ var SchemaDiffer = class {
|
|
|
9813
11002
|
for (const [id, oldEp] of oldOps) {
|
|
9814
11003
|
const newEp = newOps.get(id);
|
|
9815
11004
|
if (!newEp) {
|
|
9816
|
-
result.endpoints[id] = {
|
|
11005
|
+
result.endpoints[id] = {
|
|
11006
|
+
type: "removed",
|
|
11007
|
+
oldEndpoint: oldEp,
|
|
11008
|
+
changes: []
|
|
11009
|
+
};
|
|
9817
11010
|
} else {
|
|
9818
11011
|
const changes = this.diffEndpoints(oldEp, newEp);
|
|
9819
11012
|
if (changes.length > 0) {
|
|
9820
|
-
result.endpoints[id] = {
|
|
11013
|
+
result.endpoints[id] = {
|
|
11014
|
+
type: "modified",
|
|
11015
|
+
oldEndpoint: oldEp,
|
|
11016
|
+
newEndpoint: newEp,
|
|
11017
|
+
changes
|
|
11018
|
+
};
|
|
9821
11019
|
}
|
|
9822
11020
|
}
|
|
9823
11021
|
}
|
|
9824
11022
|
for (const [id, newEp] of newOps) {
|
|
9825
11023
|
if (!oldOps.has(id)) {
|
|
9826
|
-
result.endpoints[id] = {
|
|
11024
|
+
result.endpoints[id] = {
|
|
11025
|
+
type: "added",
|
|
11026
|
+
newEndpoint: newEp,
|
|
11027
|
+
changes: []
|
|
11028
|
+
};
|
|
9827
11029
|
}
|
|
9828
11030
|
}
|
|
9829
11031
|
for (const [id, oldType] of oldSchema.types) {
|
|
@@ -9847,10 +11049,20 @@ var SchemaDiffer = class {
|
|
|
9847
11049
|
diffEndpoints(oldEp, newEp) {
|
|
9848
11050
|
const changes = [];
|
|
9849
11051
|
if (oldEp.path !== newEp.path) {
|
|
9850
|
-
changes.push({
|
|
11052
|
+
changes.push({
|
|
11053
|
+
path: "path",
|
|
11054
|
+
type: "modified",
|
|
11055
|
+
oldValue: oldEp.path,
|
|
11056
|
+
newValue: newEp.path
|
|
11057
|
+
});
|
|
9851
11058
|
}
|
|
9852
11059
|
if (oldEp.method !== newEp.method) {
|
|
9853
|
-
changes.push({
|
|
11060
|
+
changes.push({
|
|
11061
|
+
path: "method",
|
|
11062
|
+
type: "modified",
|
|
11063
|
+
oldValue: oldEp.method,
|
|
11064
|
+
newValue: newEp.method
|
|
11065
|
+
});
|
|
9854
11066
|
}
|
|
9855
11067
|
const diffParams = (oldParams = [], newParams = [], typeName) => {
|
|
9856
11068
|
const oldMap = new Map((oldParams || []).map((p) => [p.name, p]));
|
|
@@ -9858,19 +11070,37 @@ var SchemaDiffer = class {
|
|
|
9858
11070
|
for (const [name, oldP] of oldMap) {
|
|
9859
11071
|
const newP = newMap.get(name);
|
|
9860
11072
|
if (!newP) {
|
|
9861
|
-
changes.push({
|
|
11073
|
+
changes.push({
|
|
11074
|
+
path: `${typeName}.${name}`,
|
|
11075
|
+
type: "removed",
|
|
11076
|
+
oldValue: oldP
|
|
11077
|
+
});
|
|
9862
11078
|
} else {
|
|
9863
11079
|
if (JSON.stringify(oldP.type) !== JSON.stringify(newP.type)) {
|
|
9864
|
-
changes.push({
|
|
11080
|
+
changes.push({
|
|
11081
|
+
path: `${typeName}.${name}.type`,
|
|
11082
|
+
type: "modified",
|
|
11083
|
+
oldValue: oldP.type,
|
|
11084
|
+
newValue: newP.type
|
|
11085
|
+
});
|
|
9865
11086
|
}
|
|
9866
11087
|
if (oldP.required !== newP.required) {
|
|
9867
|
-
changes.push({
|
|
11088
|
+
changes.push({
|
|
11089
|
+
path: `${typeName}.${name}.required`,
|
|
11090
|
+
type: "modified",
|
|
11091
|
+
oldValue: oldP.required,
|
|
11092
|
+
newValue: newP.required
|
|
11093
|
+
});
|
|
9868
11094
|
}
|
|
9869
11095
|
}
|
|
9870
11096
|
}
|
|
9871
11097
|
for (const [name, newP] of newMap) {
|
|
9872
11098
|
if (!oldMap.has(name)) {
|
|
9873
|
-
changes.push({
|
|
11099
|
+
changes.push({
|
|
11100
|
+
path: `${typeName}.${name}`,
|
|
11101
|
+
type: "added",
|
|
11102
|
+
newValue: newP
|
|
11103
|
+
});
|
|
9874
11104
|
}
|
|
9875
11105
|
}
|
|
9876
11106
|
};
|
|
@@ -9878,15 +11108,33 @@ var SchemaDiffer = class {
|
|
|
9878
11108
|
diffParams(oldEp.queryParams, newEp.queryParams, "queryParams");
|
|
9879
11109
|
diffParams(oldEp.headerParams, newEp.headerParams, "headerParams");
|
|
9880
11110
|
if (oldEp.requestBody && !newEp.requestBody) {
|
|
9881
|
-
changes.push({
|
|
11111
|
+
changes.push({
|
|
11112
|
+
path: "requestBody",
|
|
11113
|
+
type: "removed",
|
|
11114
|
+
oldValue: oldEp.requestBody
|
|
11115
|
+
});
|
|
9882
11116
|
} else if (!oldEp.requestBody && newEp.requestBody) {
|
|
9883
|
-
changes.push({
|
|
11117
|
+
changes.push({
|
|
11118
|
+
path: "requestBody",
|
|
11119
|
+
type: "added",
|
|
11120
|
+
newValue: newEp.requestBody
|
|
11121
|
+
});
|
|
9884
11122
|
} else if (oldEp.requestBody && newEp.requestBody) {
|
|
9885
11123
|
if (JSON.stringify(oldEp.requestBody.type) !== JSON.stringify(newEp.requestBody.type)) {
|
|
9886
|
-
changes.push({
|
|
11124
|
+
changes.push({
|
|
11125
|
+
path: "requestBody.type",
|
|
11126
|
+
type: "modified",
|
|
11127
|
+
oldValue: oldEp.requestBody.type,
|
|
11128
|
+
newValue: newEp.requestBody.type
|
|
11129
|
+
});
|
|
9887
11130
|
}
|
|
9888
11131
|
if (oldEp.requestBody.required !== newEp.requestBody.required) {
|
|
9889
|
-
changes.push({
|
|
11132
|
+
changes.push({
|
|
11133
|
+
path: "requestBody.required",
|
|
11134
|
+
type: "modified",
|
|
11135
|
+
oldValue: oldEp.requestBody.required,
|
|
11136
|
+
newValue: newEp.requestBody.required
|
|
11137
|
+
});
|
|
9890
11138
|
}
|
|
9891
11139
|
}
|
|
9892
11140
|
return changes;
|
|
@@ -9894,7 +11142,12 @@ var SchemaDiffer = class {
|
|
|
9894
11142
|
diffTypes(oldType, newType) {
|
|
9895
11143
|
const changes = [];
|
|
9896
11144
|
if (oldType.kind !== newType.kind) {
|
|
9897
|
-
changes.push({
|
|
11145
|
+
changes.push({
|
|
11146
|
+
path: "kind",
|
|
11147
|
+
type: "modified",
|
|
11148
|
+
oldValue: oldType.kind,
|
|
11149
|
+
newValue: newType.kind
|
|
11150
|
+
});
|
|
9898
11151
|
return changes;
|
|
9899
11152
|
}
|
|
9900
11153
|
if (oldType.kind === "object" && newType.kind === "object") {
|
|
@@ -9903,19 +11156,37 @@ var SchemaDiffer = class {
|
|
|
9903
11156
|
for (const [name, oldF] of oldFields) {
|
|
9904
11157
|
const newF = newFields.get(name);
|
|
9905
11158
|
if (!newF) {
|
|
9906
|
-
changes.push({
|
|
11159
|
+
changes.push({
|
|
11160
|
+
path: `fields.${name}`,
|
|
11161
|
+
type: "removed",
|
|
11162
|
+
oldValue: oldF
|
|
11163
|
+
});
|
|
9907
11164
|
} else {
|
|
9908
11165
|
if (JSON.stringify(oldF.type) !== JSON.stringify(newF.type)) {
|
|
9909
|
-
changes.push({
|
|
11166
|
+
changes.push({
|
|
11167
|
+
path: `fields.${name}.type`,
|
|
11168
|
+
type: "modified",
|
|
11169
|
+
oldValue: oldF.type,
|
|
11170
|
+
newValue: newF.type
|
|
11171
|
+
});
|
|
9910
11172
|
}
|
|
9911
11173
|
if (oldF.required !== newF.required) {
|
|
9912
|
-
changes.push({
|
|
11174
|
+
changes.push({
|
|
11175
|
+
path: `fields.${name}.required`,
|
|
11176
|
+
type: "modified",
|
|
11177
|
+
oldValue: oldF.required,
|
|
11178
|
+
newValue: newF.required
|
|
11179
|
+
});
|
|
9913
11180
|
}
|
|
9914
11181
|
}
|
|
9915
11182
|
}
|
|
9916
11183
|
for (const [name, newF] of newFields) {
|
|
9917
11184
|
if (!oldFields.has(name)) {
|
|
9918
|
-
changes.push({
|
|
11185
|
+
changes.push({
|
|
11186
|
+
path: `fields.${name}`,
|
|
11187
|
+
type: "added",
|
|
11188
|
+
newValue: newF
|
|
11189
|
+
});
|
|
9919
11190
|
}
|
|
9920
11191
|
}
|
|
9921
11192
|
}
|
|
@@ -10182,20 +11453,32 @@ function registerSdkDiffCommand(program3) {
|
|
|
10182
11453
|
const analyzer = new BreakingChangeAnalyzer();
|
|
10183
11454
|
const report = analyzer.analyze(diffs);
|
|
10184
11455
|
const breaking = report.issues.filter((i) => i.severity === "breaking");
|
|
10185
|
-
const nonBreaking = report.issues.filter(
|
|
11456
|
+
const nonBreaking = report.issues.filter(
|
|
11457
|
+
(i) => i.severity !== "breaking"
|
|
11458
|
+
);
|
|
10186
11459
|
if (breaking.length === 0 && nonBreaking.length === 0) {
|
|
10187
11460
|
console.log(pc__default.default.green(" \u2713 No changes detected between schemas."));
|
|
10188
11461
|
} else {
|
|
10189
11462
|
if (breaking.length > 0) {
|
|
10190
|
-
console.log(
|
|
10191
|
-
|
|
11463
|
+
console.log(
|
|
11464
|
+
pc__default.default.red(` \u2717 Found ${breaking.length} breaking changes:`)
|
|
11465
|
+
);
|
|
11466
|
+
breaking.forEach(
|
|
11467
|
+
(b) => console.log(pc__default.default.red(` - ${b.description}`))
|
|
11468
|
+
);
|
|
10192
11469
|
} else {
|
|
10193
11470
|
console.log(pc__default.default.green(" \u2713 No breaking changes detected."));
|
|
10194
11471
|
}
|
|
10195
11472
|
if (nonBreaking.length > 0) {
|
|
10196
|
-
console.log(
|
|
10197
|
-
|
|
10198
|
-
|
|
11473
|
+
console.log(
|
|
11474
|
+
pc__default.default.yellow(
|
|
11475
|
+
`
|
|
11476
|
+
\u26A0 Found ${nonBreaking.length} non-breaking changes:`
|
|
11477
|
+
)
|
|
11478
|
+
);
|
|
11479
|
+
nonBreaking.forEach(
|
|
11480
|
+
(nb) => console.log(pc__default.default.yellow(` - ${nb.description}`))
|
|
11481
|
+
);
|
|
10199
11482
|
}
|
|
10200
11483
|
}
|
|
10201
11484
|
console.log(pc__default.default.green("\n\u2713 Done."));
|
|
@@ -10210,7 +11493,10 @@ function registerSdkDiffCommand(program3) {
|
|
|
10210
11493
|
});
|
|
10211
11494
|
}
|
|
10212
11495
|
function registerSdkValidateCommand(program3) {
|
|
10213
|
-
program3.command("validate").description("Validate an API schema against the Axiomify SDK compiler").argument(
|
|
11496
|
+
program3.command("validate").description("Validate an API schema against the Axiomify SDK compiler").argument(
|
|
11497
|
+
"<input>",
|
|
11498
|
+
"The input schema file (e.g. spec.json, schema.graphql)"
|
|
11499
|
+
).action(async (input) => {
|
|
10214
11500
|
try {
|
|
10215
11501
|
console.log(pc__default.default.blue("\u2139 Initializing SDK validator...\n"));
|
|
10216
11502
|
console.log(pc__default.default.dim(` \u2022 Loading ${input}...`));
|
|
@@ -10241,7 +11527,12 @@ function registerSdkValidateCommand(program3) {
|
|
|
10241
11527
|
});
|
|
10242
11528
|
}
|
|
10243
11529
|
function registerSdkBuildCommand(program3) {
|
|
10244
|
-
program3.command("build").description(
|
|
11530
|
+
program3.command("build").description(
|
|
11531
|
+
"Build, validate, and check API schema compile target readiness"
|
|
11532
|
+
).argument(
|
|
11533
|
+
"<input>",
|
|
11534
|
+
"The input schema file (e.g. spec.json, schema.graphql)"
|
|
11535
|
+
).action(async (input) => {
|
|
10245
11536
|
try {
|
|
10246
11537
|
console.log(pc__default.default.blue("\u2139 Initializing SDK build...\n"));
|
|
10247
11538
|
const ext = input.split(".").pop()?.toLowerCase() || "";
|
|
@@ -10270,7 +11561,9 @@ function registerSdkBuildCommand(program3) {
|
|
|
10270
11561
|
}
|
|
10271
11562
|
console.log(pc__default.default.green(`
|
|
10272
11563
|
\u2713 Build succeeded!`));
|
|
10273
|
-
console.log(
|
|
11564
|
+
console.log(
|
|
11565
|
+
pc__default.default.dim(` Endpoints: ${result.schema.endpoints.length}`)
|
|
11566
|
+
);
|
|
10274
11567
|
console.log(pc__default.default.dim(` Types: ${result.schema.types.size}`));
|
|
10275
11568
|
console.log(pc__default.default.dim(` Duration: ${result.durationMs}ms`));
|
|
10276
11569
|
} catch (err) {
|
|
@@ -10281,12 +11574,24 @@ function registerSdkBuildCommand(program3) {
|
|
|
10281
11574
|
});
|
|
10282
11575
|
}
|
|
10283
11576
|
function registerSdkPublishCommand(program3) {
|
|
10284
|
-
program3.command("publish").description(
|
|
11577
|
+
program3.command("publish").description(
|
|
11578
|
+
"Publish generated SDK packages to package registries (dry-run by default)"
|
|
11579
|
+
).option("--dry-run", "Simulate publishing without uploading", true).option("--registry <url>", "Override registry URL").action(async (options) => {
|
|
10285
11580
|
try {
|
|
10286
11581
|
console.log(pc__default.default.blue("\u2139 Initializing SDK publishing...\n"));
|
|
10287
|
-
const targets = [
|
|
11582
|
+
const targets = [
|
|
11583
|
+
"typescript",
|
|
11584
|
+
"javascript",
|
|
11585
|
+
"python",
|
|
11586
|
+
"go",
|
|
11587
|
+
"kotlin",
|
|
11588
|
+
"swift",
|
|
11589
|
+
"dart"
|
|
11590
|
+
];
|
|
10288
11591
|
for (const target of targets) {
|
|
10289
|
-
console.log(
|
|
11592
|
+
console.log(
|
|
11593
|
+
pc__default.default.cyan(` \u2022 Preparing publishing for target [${target}]`)
|
|
11594
|
+
);
|
|
10290
11595
|
let cmd = "";
|
|
10291
11596
|
switch (target) {
|
|
10292
11597
|
case "typescript":
|
|
@@ -10312,7 +11617,9 @@ function registerSdkPublishCommand(program3) {
|
|
|
10312
11617
|
if (options.dryRun) {
|
|
10313
11618
|
console.log(pc__default.default.dim(` [Simulated] Would run: ${cmd}`));
|
|
10314
11619
|
} else {
|
|
10315
|
-
console.log(
|
|
11620
|
+
console.log(
|
|
11621
|
+
pc__default.default.yellow(` [Action] Executing publishing command: ${cmd}`)
|
|
11622
|
+
);
|
|
10316
11623
|
}
|
|
10317
11624
|
}
|
|
10318
11625
|
console.log(pc__default.default.green("\n\u2713 Publish simulation complete."));
|
|
@@ -10324,15 +11631,29 @@ function registerSdkPublishCommand(program3) {
|
|
|
10324
11631
|
});
|
|
10325
11632
|
}
|
|
10326
11633
|
function registerSdkDoctorCommand(program3) {
|
|
10327
|
-
program3.command("doctor").description(
|
|
11634
|
+
program3.command("doctor").description(
|
|
11635
|
+
"Verify and diagnose local toolchains required for SDK targets"
|
|
11636
|
+
).action(async () => {
|
|
10328
11637
|
console.log(pc__default.default.blue("\u2139 Diagnosing local SDK target toolchains...\n"));
|
|
10329
11638
|
const toolchains = [
|
|
10330
|
-
{
|
|
10331
|
-
|
|
11639
|
+
{
|
|
11640
|
+
name: "TypeScript/JavaScript (Node.js)",
|
|
11641
|
+
cmd: "node --version",
|
|
11642
|
+
req: "Node.js"
|
|
11643
|
+
},
|
|
11644
|
+
{
|
|
11645
|
+
name: "Python (pip/pydantic)",
|
|
11646
|
+
cmd: "python3 --version",
|
|
11647
|
+
req: "Python 3"
|
|
11648
|
+
},
|
|
10332
11649
|
{ name: "Go (compiler)", cmd: "go version", req: "Go SDK" },
|
|
10333
11650
|
{ name: "Dart (flutter/pub)", cmd: "dart --version", req: "Dart SDK" },
|
|
10334
11651
|
{ name: "Kotlin (gradle/java)", cmd: "java -version", req: "Java JDK" },
|
|
10335
|
-
{
|
|
11652
|
+
{
|
|
11653
|
+
name: "Swift (swiftc/xcode)",
|
|
11654
|
+
cmd: "swift --version",
|
|
11655
|
+
req: "Swift / Xcode Command Line Tools"
|
|
11656
|
+
}
|
|
10336
11657
|
];
|
|
10337
11658
|
let allOk = true;
|
|
10338
11659
|
for (const tc of toolchains) {
|
|
@@ -10345,18 +11666,34 @@ function registerSdkDoctorCommand(program3) {
|
|
|
10345
11666
|
}
|
|
10346
11667
|
}
|
|
10347
11668
|
if (allOk) {
|
|
10348
|
-
console.log(
|
|
11669
|
+
console.log(
|
|
11670
|
+
pc__default.default.green("\n\u2713 Doctor check passed. All toolchains are available.")
|
|
11671
|
+
);
|
|
10349
11672
|
} else {
|
|
10350
|
-
console.log(
|
|
11673
|
+
console.log(
|
|
11674
|
+
pc__default.default.yellow(
|
|
11675
|
+
"\n\u26A0 Some toolchains are missing. You may not be able to build or publish certain targets."
|
|
11676
|
+
)
|
|
11677
|
+
);
|
|
10351
11678
|
}
|
|
10352
11679
|
});
|
|
10353
11680
|
}
|
|
10354
11681
|
function registerSdkBenchmarkCommand(program3) {
|
|
10355
11682
|
program3.command("benchmark").description("Benchmark the compiler and code generator throughput").action(async () => {
|
|
10356
|
-
console.log(
|
|
10357
|
-
|
|
11683
|
+
console.log(
|
|
11684
|
+
pc__default.default.blue(
|
|
11685
|
+
"\u2139 Initializing SDK compiler & generator performance benchmark...\n"
|
|
11686
|
+
)
|
|
11687
|
+
);
|
|
11688
|
+
console.log(
|
|
11689
|
+
pc__default.default.dim(" \u2022 Synthesizing mock schema (50 endpoints, 100 types)...")
|
|
11690
|
+
);
|
|
10358
11691
|
const mockSchema = {
|
|
10359
|
-
info: {
|
|
11692
|
+
info: {
|
|
11693
|
+
title: "Benchmark API",
|
|
11694
|
+
version: "2.0.0",
|
|
11695
|
+
sourceFormat: "openapi"
|
|
11696
|
+
},
|
|
10360
11697
|
types: /* @__PURE__ */ new Map(),
|
|
10361
11698
|
endpoints: [],
|
|
10362
11699
|
securitySchemes: /* @__PURE__ */ new Map(),
|
|
@@ -10371,10 +11708,34 @@ function registerSdkBenchmarkCommand(program3) {
|
|
|
10371
11708
|
id: typeId,
|
|
10372
11709
|
kind: "object",
|
|
10373
11710
|
fields: [
|
|
10374
|
-
{
|
|
10375
|
-
|
|
10376
|
-
|
|
10377
|
-
|
|
11711
|
+
{
|
|
11712
|
+
name: "id",
|
|
11713
|
+
required: true,
|
|
11714
|
+
type: {
|
|
11715
|
+
inline: { id: "_string", kind: "scalar", scalar: "string" }
|
|
11716
|
+
}
|
|
11717
|
+
},
|
|
11718
|
+
{
|
|
11719
|
+
name: "name",
|
|
11720
|
+
required: true,
|
|
11721
|
+
type: {
|
|
11722
|
+
inline: { id: "_string", kind: "scalar", scalar: "string" }
|
|
11723
|
+
}
|
|
11724
|
+
},
|
|
11725
|
+
{
|
|
11726
|
+
name: "age",
|
|
11727
|
+
required: false,
|
|
11728
|
+
type: {
|
|
11729
|
+
inline: { id: "_number", kind: "scalar", scalar: "number" }
|
|
11730
|
+
}
|
|
11731
|
+
},
|
|
11732
|
+
{
|
|
11733
|
+
name: "createdAt",
|
|
11734
|
+
required: true,
|
|
11735
|
+
type: {
|
|
11736
|
+
inline: { id: "_datetime", kind: "scalar", scalar: "datetime" }
|
|
11737
|
+
}
|
|
11738
|
+
}
|
|
10378
11739
|
]
|
|
10379
11740
|
});
|
|
10380
11741
|
}
|
|
@@ -10386,7 +11747,14 @@ function registerSdkBenchmarkCommand(program3) {
|
|
|
10386
11747
|
method: "GET",
|
|
10387
11748
|
path: `/resource/${i}/{id}`,
|
|
10388
11749
|
pathParams: [
|
|
10389
|
-
{
|
|
11750
|
+
{
|
|
11751
|
+
name: "id",
|
|
11752
|
+
location: "path",
|
|
11753
|
+
required: true,
|
|
11754
|
+
type: {
|
|
11755
|
+
inline: { id: "_string", kind: "scalar", scalar: "string" }
|
|
11756
|
+
}
|
|
11757
|
+
}
|
|
10390
11758
|
],
|
|
10391
11759
|
queryParams: [],
|
|
10392
11760
|
headerParams: [],
|
|
@@ -10430,16 +11798,38 @@ function registerSdkBenchmarkCommand(program3) {
|
|
|
10430
11798
|
console.log();
|
|
10431
11799
|
console.log(pc__default.default.bold("Results Summary:"));
|
|
10432
11800
|
console.log(pc__default.default.dim(` - Compilation Time: ${compileTime}ms`));
|
|
10433
|
-
console.log(
|
|
11801
|
+
console.log(
|
|
11802
|
+
pc__default.default.dim(
|
|
11803
|
+
` - Generation Time (all ${targets.length} targets): ${genTime}ms`
|
|
11804
|
+
)
|
|
11805
|
+
);
|
|
10434
11806
|
console.log(pc__default.default.dim(` - Total files generated: ${totalFiles}`));
|
|
10435
|
-
console.log(
|
|
10436
|
-
|
|
11807
|
+
console.log(
|
|
11808
|
+
pc__default.default.dim(
|
|
11809
|
+
` - Compilation Throughput: ${(50 / (compileTime / 1e3)).toFixed(2)} endpoints/sec`
|
|
11810
|
+
)
|
|
11811
|
+
);
|
|
11812
|
+
console.log(
|
|
11813
|
+
pc__default.default.dim(
|
|
11814
|
+
` - Generation Throughput: ${(totalFiles / (genTime / 1e3)).toFixed(2)} files/sec`
|
|
11815
|
+
)
|
|
11816
|
+
);
|
|
10437
11817
|
});
|
|
10438
11818
|
}
|
|
10439
11819
|
function registerSdkWatchCommand(program3) {
|
|
10440
|
-
program3.command("watch").description(
|
|
11820
|
+
program3.command("watch").description(
|
|
11821
|
+
"Watch the input API schema file and regenerate SDK targets automatically on changes"
|
|
11822
|
+
).argument(
|
|
11823
|
+
"<input>",
|
|
11824
|
+
"The input schema file (e.g. spec.json, schema.graphql)"
|
|
11825
|
+
).requiredOption(
|
|
11826
|
+
"-t, --target <langs...>",
|
|
11827
|
+
"Target languages (e.g. typescript python)"
|
|
11828
|
+
).option("-o, --output <dir>", "Output directory", "generated-sdks").action(async (input, options) => {
|
|
10441
11829
|
console.log(pc__default.default.blue(`\u2139 Starting watch mode on [${input}]`));
|
|
10442
|
-
console.log(
|
|
11830
|
+
console.log(
|
|
11831
|
+
pc__default.default.dim(` \u2022 Targets to generate: ${options.target.join(", ")}`)
|
|
11832
|
+
);
|
|
10443
11833
|
console.log(pc__default.default.dim(` \u2022 Output directory: ${options.output}`));
|
|
10444
11834
|
try {
|
|
10445
11835
|
await generateSdk({ input, ...options, exitOnError: false });
|
|
@@ -10450,8 +11840,12 @@ function registerSdkWatchCommand(program3) {
|
|
|
10450
11840
|
if (eventType === "change") {
|
|
10451
11841
|
if (debounceTimeout) clearTimeout(debounceTimeout);
|
|
10452
11842
|
debounceTimeout = setTimeout(async () => {
|
|
10453
|
-
console.log(
|
|
10454
|
-
|
|
11843
|
+
console.log(
|
|
11844
|
+
pc__default.default.cyan(
|
|
11845
|
+
`
|
|
11846
|
+
\u2022 File change detected on [${input}], regenerating...`
|
|
11847
|
+
)
|
|
11848
|
+
);
|
|
10455
11849
|
try {
|
|
10456
11850
|
await generateSdk({ input, ...options, exitOnError: false });
|
|
10457
11851
|
} catch (err) {
|
|
@@ -10478,7 +11872,9 @@ var MigrationEngine = class {
|
|
|
10478
11872
|
description: `The method "${id}" has been removed from the client. Identify alternatives or remove calls to it.`
|
|
10479
11873
|
});
|
|
10480
11874
|
} else if (epDiff.type === "modified") {
|
|
10481
|
-
const signatureChanges = epDiff.changes.filter(
|
|
11875
|
+
const signatureChanges = epDiff.changes.filter(
|
|
11876
|
+
(c) => c.path.startsWith("pathParams.") || c.path.startsWith("queryParams.") || c.path.startsWith("requestBody")
|
|
11877
|
+
);
|
|
10482
11878
|
if (signatureChanges.length > 0) {
|
|
10483
11879
|
steps.push({
|
|
10484
11880
|
target: `client.${id}`,
|
|
@@ -10496,7 +11892,9 @@ var MigrationEngine = class {
|
|
|
10496
11892
|
description: `The interface/struct "${id}" is no longer exported by the SDK. inspect usage.`
|
|
10497
11893
|
});
|
|
10498
11894
|
} else if (typeDiff.type === "modified") {
|
|
10499
|
-
const removedFields = typeDiff.changes.filter(
|
|
11895
|
+
const removedFields = typeDiff.changes.filter(
|
|
11896
|
+
(c) => c.type === "removed" && c.path.startsWith("fields.")
|
|
11897
|
+
);
|
|
10500
11898
|
for (const change of removedFields) {
|
|
10501
11899
|
const fieldName = change.path.split(".").pop() || "";
|
|
10502
11900
|
steps.push({
|
|
@@ -10511,59 +11909,75 @@ var MigrationEngine = class {
|
|
|
10511
11909
|
}
|
|
10512
11910
|
};
|
|
10513
11911
|
function registerSdkMigrateCommand(program3) {
|
|
10514
|
-
program3.command("migrate").description(
|
|
10515
|
-
|
|
10516
|
-
|
|
10517
|
-
|
|
10518
|
-
|
|
10519
|
-
|
|
10520
|
-
|
|
10521
|
-
|
|
10522
|
-
|
|
10523
|
-
if (ext === "json" || ext === "yaml" || ext === "yml") {
|
|
10524
|
-
const parsed = ext === "json" ? JSON.parse(raw) : __require("yaml").parse(raw);
|
|
10525
|
-
ingested = ingestOpenApi(parsed, {});
|
|
10526
|
-
} else if (ext === "graphql" || ext === "gql") {
|
|
10527
|
-
ingested = await ingestGraphQL(raw, {});
|
|
10528
|
-
} else {
|
|
10529
|
-
throw new Error(`Unsupported schema format for ${filePath}`);
|
|
11912
|
+
program3.command("migrate").description(
|
|
11913
|
+
"Generate client migration steps and guides between two API schemas"
|
|
11914
|
+
).argument("<old>", "The old/previous schema file").argument("<new>", "The new/current schema file").option("--json", "Output migration guide as JSON", false).action(
|
|
11915
|
+
async (oldFile, newFile, options) => {
|
|
11916
|
+
try {
|
|
11917
|
+
if (!options.json) {
|
|
11918
|
+
console.log(
|
|
11919
|
+
pc__default.default.blue("\u2139 Initializing SDK client migration generator...\n")
|
|
11920
|
+
);
|
|
10530
11921
|
}
|
|
10531
|
-
|
|
10532
|
-
|
|
10533
|
-
|
|
10534
|
-
|
|
10535
|
-
|
|
10536
|
-
|
|
10537
|
-
|
|
10538
|
-
|
|
10539
|
-
|
|
10540
|
-
|
|
10541
|
-
|
|
10542
|
-
|
|
10543
|
-
|
|
10544
|
-
|
|
10545
|
-
|
|
10546
|
-
|
|
10547
|
-
|
|
10548
|
-
|
|
11922
|
+
const loadSchema = async (filePath) => {
|
|
11923
|
+
const ext = filePath.split(".").pop()?.toLowerCase() || "";
|
|
11924
|
+
const raw = fs.readFileSync(filePath, "utf8");
|
|
11925
|
+
let ingested;
|
|
11926
|
+
if (ext === "json" || ext === "yaml" || ext === "yml") {
|
|
11927
|
+
const parsed = ext === "json" ? JSON.parse(raw) : __require("yaml").parse(raw);
|
|
11928
|
+
ingested = ingestOpenApi(parsed, {});
|
|
11929
|
+
} else if (ext === "graphql" || ext === "gql") {
|
|
11930
|
+
ingested = await ingestGraphQL(raw, {});
|
|
11931
|
+
} else {
|
|
11932
|
+
throw new Error(`Unsupported schema format for ${filePath}`);
|
|
11933
|
+
}
|
|
11934
|
+
return (await new CompilerPipeline().compile(ingested.schema)).schema;
|
|
11935
|
+
};
|
|
11936
|
+
const oldSchema = await loadSchema(oldFile);
|
|
11937
|
+
const newSchema = await loadSchema(newFile);
|
|
11938
|
+
const differ = new SchemaDiffer();
|
|
11939
|
+
const diffs = differ.diff(oldSchema, newSchema);
|
|
11940
|
+
const analyzer = new BreakingChangeAnalyzer();
|
|
11941
|
+
const report = analyzer.analyze(diffs);
|
|
11942
|
+
const migrator = new MigrationEngine();
|
|
11943
|
+
const steps = migrator.generateMigrationGuide(diffs, report);
|
|
11944
|
+
if (options.json) {
|
|
11945
|
+
console.log(JSON.stringify(steps, null, 2));
|
|
10549
11946
|
} else {
|
|
10550
|
-
|
|
10551
|
-
|
|
10552
|
-
|
|
10553
|
-
|
|
10554
|
-
console.log(
|
|
11947
|
+
console.log(pc__default.default.bold(`Migration Guide: ${oldFile} \u2192 ${newFile}`));
|
|
11948
|
+
console.log(pc__default.default.dim(`Total action items: ${steps.length}
|
|
11949
|
+
`));
|
|
11950
|
+
if (steps.length === 0) {
|
|
11951
|
+
console.log(
|
|
11952
|
+
pc__default.default.green(
|
|
11953
|
+
" \u2713 No client code migration is necessary. Upgrade is fully backward compatible."
|
|
11954
|
+
)
|
|
11955
|
+
);
|
|
11956
|
+
} else {
|
|
11957
|
+
for (const step of steps) {
|
|
11958
|
+
const symbol = step.action === "remove" ? "\u274C" : "\u26A0\uFE0F";
|
|
11959
|
+
console.log(
|
|
11960
|
+
` ${symbol} [${step.action.toUpperCase()}] Target: ${pc__default.default.cyan(step.target)}`
|
|
11961
|
+
);
|
|
11962
|
+
console.log(` ${step.description}`);
|
|
11963
|
+
console.log();
|
|
11964
|
+
}
|
|
10555
11965
|
}
|
|
10556
11966
|
}
|
|
11967
|
+
} catch (err) {
|
|
11968
|
+
console.error(
|
|
11969
|
+
pc__default.default.red(`
|
|
11970
|
+
\u2717 Migration generation failed: ${err.message}`)
|
|
11971
|
+
);
|
|
11972
|
+
process.exit(1);
|
|
10557
11973
|
}
|
|
10558
|
-
} catch (err) {
|
|
10559
|
-
console.error(pc__default.default.red(`
|
|
10560
|
-
\u2717 Migration generation failed: ${err.message}`));
|
|
10561
|
-
process.exit(1);
|
|
10562
11974
|
}
|
|
10563
|
-
|
|
11975
|
+
);
|
|
10564
11976
|
}
|
|
10565
11977
|
function registerSdkUpgradeCommand(program3) {
|
|
10566
|
-
program3.command("upgrade").description(
|
|
11978
|
+
program3.command("upgrade").description(
|
|
11979
|
+
"Upgrade the local SDK generation target tool and runtime dependencies"
|
|
11980
|
+
).option("--dry-run", "Show command simulation without installing", false).action(async (options) => {
|
|
10567
11981
|
console.log(pc__default.default.blue("\u2139 Checking for SDK runtime upgrades...\n"));
|
|
10568
11982
|
const cmd = "npm install @axiomify/sdk-runtime@latest --save";
|
|
10569
11983
|
if (options.dryRun) {
|
|
@@ -10587,25 +12001,31 @@ program2.name("axiomify").description("The official CLI for the Axiomify framewo
|
|
|
10587
12001
|
program2.command("init").description("Bootstrap a new Axiomify project").argument("[directory]", "Target directory").option("-f, --force", "Overwrite existing project files", false).action(
|
|
10588
12002
|
(directory, options) => initProject(directory, options)
|
|
10589
12003
|
);
|
|
10590
|
-
program2.command("dev").description("Start the development server with hot-reload").argument("[entry]", "Entry file", "src/index.ts").option(
|
|
12004
|
+
program2.command("dev").description("Start the development server with hot-reload").argument("[entry]", "Entry file", "src/index.ts").option(
|
|
12005
|
+
"--watch-sdk <langs...>",
|
|
12006
|
+
"Target languages to automatically regenerate SDKs on changes"
|
|
12007
|
+
).action((entry, options) => devServer(entry, options));
|
|
10591
12008
|
program2.command("build").description("Compile the application for production").argument("[entry]", "Entry file", "src/index.ts").action(buildProject);
|
|
10592
|
-
program2.command("routes").description("Inspect and list all registered HTTP + WebSocket routes").argument("[entry]", "Entry file", "src/index.ts").option(
|
|
12009
|
+
program2.command("routes").description("Inspect and list all registered HTTP + WebSocket routes").argument("[entry]", "Entry file", "src/index.ts").option(
|
|
12010
|
+
"--json",
|
|
12011
|
+
"Emit machine-readable JSON instead of the formatted table",
|
|
12012
|
+
false
|
|
12013
|
+
).option(
|
|
10593
12014
|
"-m, --method <list>",
|
|
10594
12015
|
"Comma-separated list of methods to include (e.g. GET,POST,WS)"
|
|
10595
12016
|
).option(
|
|
10596
12017
|
"-f, --filter <pattern>",
|
|
10597
12018
|
'Path filter \u2014 substring match, or glob with "*" (e.g. /api/v1/*)'
|
|
10598
|
-
).option(
|
|
10599
|
-
"-s, --sort <by>",
|
|
10600
|
-
'Sort routes by "method" or "path"',
|
|
10601
|
-
"path"
|
|
10602
|
-
).action(
|
|
12019
|
+
).option("-s, --sort <by>", 'Sort routes by "method" or "path"', "path").action(
|
|
10603
12020
|
(entry, options) => inspectRoutes(entry, options)
|
|
10604
12021
|
);
|
|
10605
12022
|
program2.command("openapi").description("Generate the OpenAPI spec from the app and emit it").argument("[entry]", "Entry file", "src/index.ts").option(
|
|
10606
12023
|
"-o, --output <file>",
|
|
10607
12024
|
"Write the spec to this file path instead of stdout"
|
|
10608
|
-
).option("--format <fmt>", 'Output format: "json" (default) or "yaml"', "json").option("--minify", "Minified JSON (single line). Ignored for yaml.", false).option("--title <title>", "Override info.title in the generated spec").option(
|
|
12025
|
+
).option("--format <fmt>", 'Output format: "json" (default) or "yaml"', "json").option("--minify", "Minified JSON (single line). Ignored for yaml.", false).option("--title <title>", "Override info.title in the generated spec").option(
|
|
12026
|
+
"--spec-version <version>",
|
|
12027
|
+
"Override info.version in the generated spec"
|
|
12028
|
+
).action(
|
|
10609
12029
|
(entry, options) => emitOpenApi(entry, {
|
|
10610
12030
|
...options,
|
|
10611
12031
|
// Map the CLI flag name (`spec-version` → camel `specVersion`) onto
|
|
@@ -10616,14 +12036,35 @@ program2.command("openapi").description("Generate the OpenAPI spec from the app
|
|
|
10616
12036
|
program2.command("check").description("Run a static production-readiness audit against the app").argument("[entry]", "Entry file", "src/index.ts").action(runCheck);
|
|
10617
12037
|
program2.command("doctor").description("Diagnose the host environment (Node, uWS, ports, dep drift)").action(runDoctor);
|
|
10618
12038
|
var scaffold = program2.command("scaffold").description("Generate boilerplate (routes, modules, plugins)");
|
|
10619
|
-
scaffold.command("route <method> <path>").description("Create a new route file under src/routes/").option("--auth", "Include `requireAuth` plugin and import", false).option("--rate-limit", "Include a default rate-limit plugin", false).option("--dry-run", "Print the generated source without writing", false).option("--force", "Overwrite the file if it already exists", false).option(
|
|
12039
|
+
scaffold.command("route <method> <path>").description("Create a new route file under src/routes/").option("--auth", "Include `requireAuth` plugin and import", false).option("--rate-limit", "Include a default rate-limit plugin", false).option("--dry-run", "Print the generated source without writing", false).option("--force", "Overwrite the file if it already exists", false).option(
|
|
12040
|
+
"--dir <dir>",
|
|
12041
|
+
"Directory under cwd to create the file in",
|
|
12042
|
+
"src/routes"
|
|
12043
|
+
).action(
|
|
10620
12044
|
(method, routePath, options) => scaffoldRoute(method, routePath, options)
|
|
10621
12045
|
);
|
|
10622
|
-
program2.command("migrate").description(
|
|
12046
|
+
program2.command("migrate").description(
|
|
12047
|
+
"v5 \u2192 v6 codemod: merge meta: fields into schema:, fix routePrefix \u2192 prefix, etc"
|
|
12048
|
+
).option("--dry-run", "Show the unified diff without writing", false).option(
|
|
12049
|
+
"--report-only",
|
|
12050
|
+
"Print a migration report and exit; do not write",
|
|
12051
|
+
false
|
|
12052
|
+
).option("--dir <dir>", "Directory to scan recursively", "src").action(
|
|
10623
12053
|
(options) => runMigrate(options)
|
|
10624
12054
|
);
|
|
10625
12055
|
var sdk = program2.command("sdk").description("Manage, generate, and diff type-safe SDKs");
|
|
10626
|
-
sdk.command("generate").description(
|
|
12056
|
+
sdk.command("generate").description(
|
|
12057
|
+
"Generate type-safe SDKs from an Axiomify app, OpenAPI spec, or GraphQL schema"
|
|
12058
|
+
).argument(
|
|
12059
|
+
"<input>",
|
|
12060
|
+
"Input file (e.g. src/index.ts, spec.json, schema.graphql)"
|
|
12061
|
+
).requiredOption(
|
|
12062
|
+
"-t, --target <langs...>",
|
|
12063
|
+
"Target languages (e.g. typescript python)"
|
|
12064
|
+
).option("-o, --output <dir>", "Output directory", "generated-sdks").option("-n, --name <name>", "Package name (e.g. my-api-sdk)").option("-v, --version <version>", "Package version (e.g. 1.0.0)").option(
|
|
12065
|
+
"--no-runtime",
|
|
12066
|
+
"Do not include runtime dependencies (generate pure types)"
|
|
12067
|
+
).option("--dry-run", "Print generated files instead of writing them to disk").action(async (input, options) => {
|
|
10627
12068
|
await generateSdk({ input, ...options });
|
|
10628
12069
|
});
|
|
10629
12070
|
registerSdkDiffCommand(sdk);
|