@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.mjs
CHANGED
|
@@ -3220,7 +3220,7 @@ var {
|
|
|
3220
3220
|
|
|
3221
3221
|
// package.json
|
|
3222
3222
|
var package_default = {
|
|
3223
|
-
version: "6.
|
|
3223
|
+
version: "6.2.0"};
|
|
3224
3224
|
var ALWAYS_EXTERNAL = ["uWebSockets.js"];
|
|
3225
3225
|
function getUserExternals(cwd) {
|
|
3226
3226
|
let pkgExternals = [];
|
|
@@ -3362,7 +3362,9 @@ function renderTable(columns, rows, terminalWidth = process.stdout.columns || 10
|
|
|
3362
3362
|
}
|
|
3363
3363
|
const lines = [];
|
|
3364
3364
|
lines.push(
|
|
3365
|
-
columns.map(
|
|
3365
|
+
columns.map(
|
|
3366
|
+
(c, i) => pc.bold(pc.gray(pad(c.header, widths[i], c.align ?? "left")))
|
|
3367
|
+
).join(" ")
|
|
3366
3368
|
);
|
|
3367
3369
|
const dividerLine = pc.dim("\u2500".repeat(total));
|
|
3368
3370
|
lines.push(dividerLine);
|
|
@@ -3522,7 +3524,11 @@ function checkHealthCheck(ctx) {
|
|
|
3522
3524
|
)
|
|
3523
3525
|
);
|
|
3524
3526
|
if (hasHealth) {
|
|
3525
|
-
add(ctx, {
|
|
3527
|
+
add(ctx, {
|
|
3528
|
+
severity: "ok",
|
|
3529
|
+
area: "ops",
|
|
3530
|
+
message: "health-check route registered"
|
|
3531
|
+
});
|
|
3526
3532
|
} else {
|
|
3527
3533
|
add(ctx, {
|
|
3528
3534
|
severity: "warn",
|
|
@@ -3643,7 +3649,10 @@ async function runCheck(entry) {
|
|
|
3643
3649
|
const tag = pc.dim(`[${f.area}]`);
|
|
3644
3650
|
console.log(` ${sym[f.severity]} ${tag} ${f.message}`);
|
|
3645
3651
|
if (f.hint && f.severity !== "ok") {
|
|
3646
|
-
const wrapped = f.hint.replace(
|
|
3652
|
+
const wrapped = f.hint.replace(
|
|
3653
|
+
/(.{1,80})(\s+|$)/g,
|
|
3654
|
+
"\n " + pc.dim("$1")
|
|
3655
|
+
);
|
|
3647
3656
|
console.log(wrapped);
|
|
3648
3657
|
}
|
|
3649
3658
|
}
|
|
@@ -3710,7 +3719,10 @@ var PluginRunner = class {
|
|
|
3710
3719
|
try {
|
|
3711
3720
|
await plugin.onBeforeGenerate(target, schema);
|
|
3712
3721
|
} catch (err) {
|
|
3713
|
-
console.error(
|
|
3722
|
+
console.error(
|
|
3723
|
+
`Plugin "${plugin.name}" onBeforeGenerate failed:`,
|
|
3724
|
+
err
|
|
3725
|
+
);
|
|
3714
3726
|
}
|
|
3715
3727
|
}
|
|
3716
3728
|
}
|
|
@@ -3767,14 +3779,18 @@ var Analyzer = class {
|
|
|
3767
3779
|
}
|
|
3768
3780
|
for (const ep of this.schema.endpoints) {
|
|
3769
3781
|
const ctx = `endpoint ${ep.operationId}`;
|
|
3770
|
-
for (const p of ep.pathParams || [])
|
|
3771
|
-
|
|
3772
|
-
for (const p of ep.
|
|
3782
|
+
for (const p of ep.pathParams || [])
|
|
3783
|
+
checkRef(p.type, `${ctx} path param ${p.name}`);
|
|
3784
|
+
for (const p of ep.queryParams || [])
|
|
3785
|
+
checkRef(p.type, `${ctx} query param ${p.name}`);
|
|
3786
|
+
for (const p of ep.headerParams || [])
|
|
3787
|
+
checkRef(p.type, `${ctx} header param ${p.name}`);
|
|
3773
3788
|
if (ep.requestBody) checkRef(ep.requestBody.type, `${ctx} request body`);
|
|
3774
3789
|
for (const [sc, resp] of Object.entries(ep.responses || {})) {
|
|
3775
3790
|
checkRef(resp.type, `${ctx} response ${sc}`);
|
|
3776
3791
|
}
|
|
3777
|
-
if (ep.streaming?.itemType)
|
|
3792
|
+
if (ep.streaming?.itemType)
|
|
3793
|
+
checkRef(ep.streaming.itemType, `${ctx} streaming item`);
|
|
3778
3794
|
if (ep.streaming?.eventTypes) {
|
|
3779
3795
|
for (const [evt, ref] of Object.entries(ep.streaming.eventTypes)) {
|
|
3780
3796
|
checkRef(ref, `${ctx} streaming event ${evt}`);
|
|
@@ -3811,7 +3827,11 @@ var Analyzer = class {
|
|
|
3811
3827
|
}
|
|
3812
3828
|
}
|
|
3813
3829
|
if (typeof type.additionalProperties === "object" && "ref" in type.additionalProperties) {
|
|
3814
|
-
this.checkFieldRef(
|
|
3830
|
+
this.checkFieldRef(
|
|
3831
|
+
type.additionalProperties,
|
|
3832
|
+
`${ctx}.additionalProperties`,
|
|
3833
|
+
depth + 1
|
|
3834
|
+
);
|
|
3815
3835
|
}
|
|
3816
3836
|
break;
|
|
3817
3837
|
case "array":
|
|
@@ -3852,8 +3872,18 @@ var Analyzer = class {
|
|
|
3852
3872
|
case "generic":
|
|
3853
3873
|
this.checkFieldRef(type.baseType, `${ctx}.base`, depth + 1);
|
|
3854
3874
|
for (const tp of type.typeParameters) {
|
|
3855
|
-
if (tp.constraint)
|
|
3856
|
-
|
|
3875
|
+
if (tp.constraint)
|
|
3876
|
+
this.checkFieldRef(
|
|
3877
|
+
tp.constraint,
|
|
3878
|
+
`${ctx}.${tp.name}.constraint`,
|
|
3879
|
+
depth + 1
|
|
3880
|
+
);
|
|
3881
|
+
if (tp.defaultType)
|
|
3882
|
+
this.checkFieldRef(
|
|
3883
|
+
tp.defaultType,
|
|
3884
|
+
`${ctx}.${tp.name}.default`,
|
|
3885
|
+
depth + 1
|
|
3886
|
+
);
|
|
3857
3887
|
}
|
|
3858
3888
|
break;
|
|
3859
3889
|
case "enum":
|
|
@@ -3907,7 +3937,9 @@ var Analyzer = class {
|
|
|
3907
3937
|
});
|
|
3908
3938
|
}
|
|
3909
3939
|
if (ep.transport === "rest" && Object.keys(ep.responses || {}).length > 0) {
|
|
3910
|
-
const hasSuccess = Object.keys(ep.responses || {}).some(
|
|
3940
|
+
const hasSuccess = Object.keys(ep.responses || {}).some(
|
|
3941
|
+
(c) => c.startsWith("2")
|
|
3942
|
+
);
|
|
3911
3943
|
if (!hasSuccess) {
|
|
3912
3944
|
this.diagnostics.push({
|
|
3913
3945
|
severity: "warning",
|
|
@@ -3917,8 +3949,12 @@ var Analyzer = class {
|
|
|
3917
3949
|
}
|
|
3918
3950
|
}
|
|
3919
3951
|
if (ep.path) {
|
|
3920
|
-
const pathParamNames = [...ep.path.matchAll(/\{([^}]+)\}/g)].map(
|
|
3921
|
-
|
|
3952
|
+
const pathParamNames = [...ep.path.matchAll(/\{([^}]+)\}/g)].map(
|
|
3953
|
+
(m) => m[1]
|
|
3954
|
+
);
|
|
3955
|
+
const declaredParams = new Set(
|
|
3956
|
+
(ep.pathParams || []).map((p) => p.name)
|
|
3957
|
+
);
|
|
3922
3958
|
for (const name of pathParamNames) {
|
|
3923
3959
|
if (!declaredParams.has(name)) {
|
|
3924
3960
|
this.diagnostics.push({
|
|
@@ -3961,7 +3997,9 @@ var Analyzer = class {
|
|
|
3961
3997
|
for (const member of type.members) {
|
|
3962
3998
|
const resolved = member.ref ? this.schema.types.get(member.ref) : member.inline;
|
|
3963
3999
|
if (resolved?.kind === "object") {
|
|
3964
|
-
const hasField = resolved.fields.some(
|
|
4000
|
+
const hasField = resolved.fields.some(
|
|
4001
|
+
(f) => f.name === disc.propertyName
|
|
4002
|
+
);
|
|
3965
4003
|
if (!hasField) {
|
|
3966
4004
|
this.diagnostics.push({
|
|
3967
4005
|
severity: "warning",
|
|
@@ -4029,7 +4067,10 @@ var Analyzer = class {
|
|
|
4029
4067
|
if (type.kind === "object") {
|
|
4030
4068
|
for (const field of type.fields) {
|
|
4031
4069
|
if (field.constraints?.pattern) {
|
|
4032
|
-
this.checkRegexSafety(
|
|
4070
|
+
this.checkRegexSafety(
|
|
4071
|
+
field.constraints.pattern,
|
|
4072
|
+
`${id}.${field.name}`
|
|
4073
|
+
);
|
|
4033
4074
|
}
|
|
4034
4075
|
}
|
|
4035
4076
|
}
|
|
@@ -4159,10 +4200,18 @@ var Normalizer = class {
|
|
|
4159
4200
|
if (member.ref) {
|
|
4160
4201
|
const target = this.schema.types.get(member.ref);
|
|
4161
4202
|
if (target) {
|
|
4162
|
-
toReplace.set(id, {
|
|
4203
|
+
toReplace.set(id, {
|
|
4204
|
+
...target,
|
|
4205
|
+
id,
|
|
4206
|
+
description: type.description ?? target.description
|
|
4207
|
+
});
|
|
4163
4208
|
}
|
|
4164
4209
|
} else if (member.inline) {
|
|
4165
|
-
toReplace.set(id, {
|
|
4210
|
+
toReplace.set(id, {
|
|
4211
|
+
...member.inline,
|
|
4212
|
+
id,
|
|
4213
|
+
description: type.description ?? member.inline.description
|
|
4214
|
+
});
|
|
4166
4215
|
}
|
|
4167
4216
|
}
|
|
4168
4217
|
if (type.kind === "union" && type.members.length === 1) {
|
|
@@ -4170,10 +4219,18 @@ var Normalizer = class {
|
|
|
4170
4219
|
if (member.ref) {
|
|
4171
4220
|
const target = this.schema.types.get(member.ref);
|
|
4172
4221
|
if (target) {
|
|
4173
|
-
toReplace.set(id, {
|
|
4222
|
+
toReplace.set(id, {
|
|
4223
|
+
...target,
|
|
4224
|
+
id,
|
|
4225
|
+
description: type.description ?? target.description
|
|
4226
|
+
});
|
|
4174
4227
|
}
|
|
4175
4228
|
} else if (member.inline) {
|
|
4176
|
-
toReplace.set(id, {
|
|
4229
|
+
toReplace.set(id, {
|
|
4230
|
+
...member.inline,
|
|
4231
|
+
id,
|
|
4232
|
+
description: type.description ?? member.inline.description
|
|
4233
|
+
});
|
|
4177
4234
|
}
|
|
4178
4235
|
}
|
|
4179
4236
|
if (type.kind === "intersection" && type.members.length > 1) {
|
|
@@ -4236,7 +4293,10 @@ var Normalizer = class {
|
|
|
4236
4293
|
for (const ep of this.schema.endpoints) {
|
|
4237
4294
|
const opPascal = toPascalCase(ep.operationId);
|
|
4238
4295
|
if (ep.requestBody?.type.inline) {
|
|
4239
|
-
ep.requestBody.type = promoteRef(
|
|
4296
|
+
ep.requestBody.type = promoteRef(
|
|
4297
|
+
ep.requestBody.type,
|
|
4298
|
+
`${opPascal}Request`
|
|
4299
|
+
);
|
|
4240
4300
|
}
|
|
4241
4301
|
for (const [code, resp] of Object.entries(ep.responses)) {
|
|
4242
4302
|
if (resp.type?.inline) {
|
|
@@ -4247,7 +4307,10 @@ var Normalizer = class {
|
|
|
4247
4307
|
const promoteParams = (params, prefix) => {
|
|
4248
4308
|
for (const param of params) {
|
|
4249
4309
|
if (param.type.inline && (param.type.inline.kind === "object" || param.type.inline.kind === "enum")) {
|
|
4250
|
-
param.type = promoteRef(
|
|
4310
|
+
param.type = promoteRef(
|
|
4311
|
+
param.type,
|
|
4312
|
+
`${opPascal}${toPascalCase(param.name)}${prefix}`
|
|
4313
|
+
);
|
|
4251
4314
|
}
|
|
4252
4315
|
}
|
|
4253
4316
|
};
|
|
@@ -4255,6 +4318,30 @@ var Normalizer = class {
|
|
|
4255
4318
|
promoteParams(ep.queryParams, "Query");
|
|
4256
4319
|
promoteParams(ep.headerParams, "Header");
|
|
4257
4320
|
}
|
|
4321
|
+
if (this.schema.events) {
|
|
4322
|
+
for (const event of this.schema.events) {
|
|
4323
|
+
const evPascal = toPascalCase(event.name);
|
|
4324
|
+
if (event.payload?.inline) {
|
|
4325
|
+
event.payload = promoteRef(event.payload, `${evPascal}Payload`);
|
|
4326
|
+
}
|
|
4327
|
+
if (event.ackPayload?.inline) {
|
|
4328
|
+
event.ackPayload = promoteRef(
|
|
4329
|
+
event.ackPayload,
|
|
4330
|
+
`${evPascal}AckPayload`
|
|
4331
|
+
);
|
|
4332
|
+
}
|
|
4333
|
+
if (event.headers) {
|
|
4334
|
+
for (const header of event.headers) {
|
|
4335
|
+
if (header.type.inline && (header.type.inline.kind === "object" || header.type.inline.kind === "enum")) {
|
|
4336
|
+
header.type = promoteRef(
|
|
4337
|
+
header.type,
|
|
4338
|
+
`${evPascal}${toPascalCase(header.name)}Header`
|
|
4339
|
+
);
|
|
4340
|
+
}
|
|
4341
|
+
}
|
|
4342
|
+
}
|
|
4343
|
+
}
|
|
4344
|
+
}
|
|
4258
4345
|
if (promoted > 0) {
|
|
4259
4346
|
this.diagnostics.push({
|
|
4260
4347
|
severity: "info",
|
|
@@ -4295,6 +4382,11 @@ var Normalizer = class {
|
|
|
4295
4382
|
for (const ep of this.schema.endpoints) {
|
|
4296
4383
|
this.walkEndpointRefs(ep, replaceRef);
|
|
4297
4384
|
}
|
|
4385
|
+
if (this.schema.events) {
|
|
4386
|
+
for (const event of this.schema.events) {
|
|
4387
|
+
this.walkEventRefs(event, replaceRef);
|
|
4388
|
+
}
|
|
4389
|
+
}
|
|
4298
4390
|
for (const id of toInline.keys()) {
|
|
4299
4391
|
this.schema.types.delete(id);
|
|
4300
4392
|
}
|
|
@@ -4334,6 +4426,11 @@ var Normalizer = class {
|
|
|
4334
4426
|
for (const ep of this.schema.endpoints) {
|
|
4335
4427
|
this.walkEndpointRefs(ep, replaceRef);
|
|
4336
4428
|
}
|
|
4429
|
+
if (this.schema.events) {
|
|
4430
|
+
for (const event of this.schema.events) {
|
|
4431
|
+
this.walkEventRefs(event, replaceRef);
|
|
4432
|
+
}
|
|
4433
|
+
}
|
|
4337
4434
|
for (const id of mergeMap.keys()) {
|
|
4338
4435
|
this.schema.types.delete(id);
|
|
4339
4436
|
}
|
|
@@ -4377,6 +4474,11 @@ var Normalizer = class {
|
|
|
4377
4474
|
for (const ep of this.schema.endpoints) {
|
|
4378
4475
|
this.walkEndpointRefs(ep, replaceRef);
|
|
4379
4476
|
}
|
|
4477
|
+
if (this.schema.events) {
|
|
4478
|
+
for (const event of this.schema.events) {
|
|
4479
|
+
this.walkEventRefs(event, replaceRef);
|
|
4480
|
+
}
|
|
4481
|
+
}
|
|
4380
4482
|
}
|
|
4381
4483
|
for (const [, type] of this.schema.types) {
|
|
4382
4484
|
if (type.kind === "object") {
|
|
@@ -4393,10 +4495,13 @@ var Normalizer = class {
|
|
|
4393
4495
|
case "object":
|
|
4394
4496
|
for (const field of type.fields) {
|
|
4395
4497
|
field.type = transform(field.type);
|
|
4396
|
-
if (field.type.inline)
|
|
4498
|
+
if (field.type.inline)
|
|
4499
|
+
this.walkTypeRefs(field.type.inline, transform);
|
|
4397
4500
|
}
|
|
4398
4501
|
if (typeof type.additionalProperties === "object" && "ref" in type.additionalProperties) {
|
|
4399
|
-
type.additionalProperties = transform(
|
|
4502
|
+
type.additionalProperties = transform(
|
|
4503
|
+
type.additionalProperties
|
|
4504
|
+
);
|
|
4400
4505
|
}
|
|
4401
4506
|
break;
|
|
4402
4507
|
case "array":
|
|
@@ -4433,22 +4538,52 @@ var Normalizer = class {
|
|
|
4433
4538
|
for (const resp of Object.values(ep.responses)) {
|
|
4434
4539
|
if (resp.type) resp.type = transform(resp.type);
|
|
4435
4540
|
}
|
|
4436
|
-
if (ep.streaming?.itemType)
|
|
4541
|
+
if (ep.streaming?.itemType)
|
|
4542
|
+
ep.streaming.itemType = transform(ep.streaming.itemType);
|
|
4437
4543
|
if (ep.streaming?.eventTypes) {
|
|
4438
4544
|
for (const [evt, ref] of Object.entries(ep.streaming.eventTypes)) {
|
|
4439
4545
|
ep.streaming.eventTypes[evt] = transform(ref);
|
|
4440
4546
|
}
|
|
4441
4547
|
}
|
|
4442
4548
|
}
|
|
4549
|
+
/** Walk all type refs within an event and apply a transform. */
|
|
4550
|
+
walkEventRefs(event, transform) {
|
|
4551
|
+
if (event.payload) {
|
|
4552
|
+
event.payload = transform(event.payload);
|
|
4553
|
+
if (event.payload.inline)
|
|
4554
|
+
this.walkTypeRefs(event.payload.inline, transform);
|
|
4555
|
+
}
|
|
4556
|
+
if (event.ackPayload) {
|
|
4557
|
+
event.ackPayload = transform(event.ackPayload);
|
|
4558
|
+
if (event.ackPayload.inline)
|
|
4559
|
+
this.walkTypeRefs(event.ackPayload.inline, transform);
|
|
4560
|
+
}
|
|
4561
|
+
if (event.headers) {
|
|
4562
|
+
for (const h of event.headers) {
|
|
4563
|
+
h.type = transform(h.type);
|
|
4564
|
+
if (h.type.inline) this.walkTypeRefs(h.type.inline, transform);
|
|
4565
|
+
}
|
|
4566
|
+
}
|
|
4567
|
+
}
|
|
4443
4568
|
/**
|
|
4444
4569
|
* Compute a canonical hash for a type, ignoring `id` and `description`
|
|
4445
4570
|
* so that structurally identical types with different names are merged.
|
|
4446
4571
|
*/
|
|
4447
4572
|
canonicalHash(type) {
|
|
4448
|
-
const {
|
|
4573
|
+
const {
|
|
4574
|
+
id: _id,
|
|
4575
|
+
description: _desc,
|
|
4576
|
+
metadata: _meta,
|
|
4577
|
+
lineage: _lin,
|
|
4578
|
+
...canonical
|
|
4579
|
+
} = type;
|
|
4449
4580
|
const str = JSON.stringify(canonical, (key, value) => {
|
|
4450
4581
|
if (value instanceof Map) {
|
|
4451
|
-
return Object.fromEntries(
|
|
4582
|
+
return Object.fromEntries(
|
|
4583
|
+
[...value.entries()].sort(
|
|
4584
|
+
(a, b) => String(a[0]).localeCompare(String(b[0]))
|
|
4585
|
+
)
|
|
4586
|
+
);
|
|
4452
4587
|
}
|
|
4453
4588
|
if (value instanceof Set) return [...value].sort();
|
|
4454
4589
|
return value;
|
|
@@ -4773,7 +4908,13 @@ var TypeGraph = class _TypeGraph {
|
|
|
4773
4908
|
const key = `${edge.from}->${edge.to}:${edge.relation}`;
|
|
4774
4909
|
if (!thisEdgeSet.has(key)) removedEdges.push(edge);
|
|
4775
4910
|
}
|
|
4776
|
-
return {
|
|
4911
|
+
return {
|
|
4912
|
+
addedNodes,
|
|
4913
|
+
removedNodes,
|
|
4914
|
+
addedEdges,
|
|
4915
|
+
removedEdges,
|
|
4916
|
+
modifiedNodes
|
|
4917
|
+
};
|
|
4777
4918
|
}
|
|
4778
4919
|
// ─── Serialization ──────────────────────────────────────────────────
|
|
4779
4920
|
/** Serialize the graph structure for caching (excludes full type data). */
|
|
@@ -4931,7 +5072,8 @@ var Optimizer = class {
|
|
|
4931
5072
|
if (resolved && resolved.kind === "scalar") {
|
|
4932
5073
|
const scalarType = resolved;
|
|
4933
5074
|
if (scalarType.scalar === "string") hasStringScalar = true;
|
|
4934
|
-
if (scalarType.scalar === "number" || scalarType.scalar === "integer")
|
|
5075
|
+
if (scalarType.scalar === "number" || scalarType.scalar === "integer")
|
|
5076
|
+
hasNumberScalar = true;
|
|
4935
5077
|
if (scalarType.scalar === "boolean") hasBooleanScalar = true;
|
|
4936
5078
|
}
|
|
4937
5079
|
}
|
|
@@ -5251,6 +5393,261 @@ var GeneratorRegistry = class {
|
|
|
5251
5393
|
}
|
|
5252
5394
|
};
|
|
5253
5395
|
|
|
5396
|
+
// src/sdk/ingest/asyncapi.ts
|
|
5397
|
+
var MAX_REF_DEPTH = 64;
|
|
5398
|
+
function ingestAsyncApi(spec, options = {}) {
|
|
5399
|
+
const as = spec;
|
|
5400
|
+
const diagnostics = [];
|
|
5401
|
+
const types = /* @__PURE__ */ new Map();
|
|
5402
|
+
const securitySchemes = /* @__PURE__ */ new Map();
|
|
5403
|
+
const events = [];
|
|
5404
|
+
const refStack = /* @__PURE__ */ new Set();
|
|
5405
|
+
let anonCounter2 = 0;
|
|
5406
|
+
function resolveRef(schema, depth = 0) {
|
|
5407
|
+
if (depth > MAX_REF_DEPTH) {
|
|
5408
|
+
diagnostics.push({
|
|
5409
|
+
severity: "error",
|
|
5410
|
+
code: "REF_DEPTH_EXCEEDED",
|
|
5411
|
+
message: `$ref resolution exceeded max depth (${MAX_REF_DEPTH})`
|
|
5412
|
+
});
|
|
5413
|
+
return { type: "object" };
|
|
5414
|
+
}
|
|
5415
|
+
if (!schema || typeof schema !== "object" || !schema.$ref) return schema;
|
|
5416
|
+
const ref = schema.$ref;
|
|
5417
|
+
if (refStack.has(ref)) return schema;
|
|
5418
|
+
refStack.add(ref);
|
|
5419
|
+
try {
|
|
5420
|
+
const resolved = resolveJsonPointer(
|
|
5421
|
+
as,
|
|
5422
|
+
ref
|
|
5423
|
+
);
|
|
5424
|
+
if (!resolved) {
|
|
5425
|
+
diagnostics.push({
|
|
5426
|
+
severity: "warning",
|
|
5427
|
+
code: "UNRESOLVED_REF",
|
|
5428
|
+
message: `Cannot resolve $ref: ${ref}`,
|
|
5429
|
+
location: ref
|
|
5430
|
+
});
|
|
5431
|
+
return { type: "object" };
|
|
5432
|
+
}
|
|
5433
|
+
const { $ref, ...rest } = schema;
|
|
5434
|
+
return { ...resolveRef(resolved, depth + 1), ...rest };
|
|
5435
|
+
} finally {
|
|
5436
|
+
refStack.delete(ref);
|
|
5437
|
+
}
|
|
5438
|
+
}
|
|
5439
|
+
function resolveJsonPointer(root, pointer) {
|
|
5440
|
+
const path12 = pointer.replace(/^#\//, "").split("/").map((s) => s.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
5441
|
+
let cur = root;
|
|
5442
|
+
for (const seg of path12) {
|
|
5443
|
+
if (cur === null || cur === void 0 || typeof cur !== "object")
|
|
5444
|
+
return void 0;
|
|
5445
|
+
cur = cur[seg];
|
|
5446
|
+
}
|
|
5447
|
+
return cur;
|
|
5448
|
+
}
|
|
5449
|
+
function refToTypeName(ref) {
|
|
5450
|
+
return ref.split("/").pop();
|
|
5451
|
+
}
|
|
5452
|
+
function capitalize2(s) {
|
|
5453
|
+
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
5454
|
+
}
|
|
5455
|
+
function schemaToTypeRef(schema, ctx) {
|
|
5456
|
+
if (!schema)
|
|
5457
|
+
return { inline: { id: "_any", kind: "scalar", scalar: "any" } };
|
|
5458
|
+
if (schema.$ref) {
|
|
5459
|
+
return { ref: refToTypeName(schema.$ref), nullable: schema.nullable };
|
|
5460
|
+
}
|
|
5461
|
+
const t = schemaToType(schema, ctx);
|
|
5462
|
+
if (t && types.has(t.id) && t.id !== ctx)
|
|
5463
|
+
return { ref: t.id, nullable: schema.nullable };
|
|
5464
|
+
return {
|
|
5465
|
+
inline: t ?? { id: "_unknown", kind: "scalar", scalar: "any" },
|
|
5466
|
+
nullable: schema.nullable
|
|
5467
|
+
};
|
|
5468
|
+
}
|
|
5469
|
+
function schemaToType(raw, ctx) {
|
|
5470
|
+
const s = resolveRef(raw);
|
|
5471
|
+
if (!s) return void 0;
|
|
5472
|
+
if (s.allOf?.length) {
|
|
5473
|
+
const name = ctx ?? `Intersection${++anonCounter2}`;
|
|
5474
|
+
return {
|
|
5475
|
+
id: name,
|
|
5476
|
+
kind: "intersection",
|
|
5477
|
+
members: s.allOf.map(
|
|
5478
|
+
(x, i) => schemaToTypeRef(x, `${name}_AllOf${i}`)
|
|
5479
|
+
),
|
|
5480
|
+
description: s.description,
|
|
5481
|
+
deprecated: s.deprecated
|
|
5482
|
+
};
|
|
5483
|
+
}
|
|
5484
|
+
if (s.oneOf?.length) {
|
|
5485
|
+
const name = ctx ?? `Union${++anonCounter2}`;
|
|
5486
|
+
return {
|
|
5487
|
+
id: name,
|
|
5488
|
+
kind: "union",
|
|
5489
|
+
members: s.oneOf.map(
|
|
5490
|
+
(x, i) => schemaToTypeRef(x, `${name}_OneOf${i}`)
|
|
5491
|
+
),
|
|
5492
|
+
description: s.description,
|
|
5493
|
+
deprecated: s.deprecated
|
|
5494
|
+
};
|
|
5495
|
+
}
|
|
5496
|
+
if (s.enum?.length) {
|
|
5497
|
+
const name = ctx ?? `Enum${++anonCounter2}`;
|
|
5498
|
+
const vt = typeof s.enum[0] === "number" ? "number" : "string";
|
|
5499
|
+
return {
|
|
5500
|
+
id: name,
|
|
5501
|
+
kind: "enum",
|
|
5502
|
+
valueType: vt,
|
|
5503
|
+
values: s.enum.map((v) => ({
|
|
5504
|
+
name: String(v),
|
|
5505
|
+
value: v
|
|
5506
|
+
})),
|
|
5507
|
+
description: s.description,
|
|
5508
|
+
deprecated: s.deprecated
|
|
5509
|
+
};
|
|
5510
|
+
}
|
|
5511
|
+
const st = Array.isArray(s.type) ? s.type[0] : s.type;
|
|
5512
|
+
if (st === "object" || s.properties) {
|
|
5513
|
+
const name = ctx ?? `Object${++anonCounter2}`;
|
|
5514
|
+
const reqSet = new Set(s.required ?? []);
|
|
5515
|
+
const fields = Object.entries(s.properties ?? {}).map(
|
|
5516
|
+
([pn, ps]) => {
|
|
5517
|
+
const rs = resolveRef(ps);
|
|
5518
|
+
return {
|
|
5519
|
+
name: pn,
|
|
5520
|
+
type: schemaToTypeRef(rs, `${name}_${capitalize2(pn)}`),
|
|
5521
|
+
required: reqSet.has(pn),
|
|
5522
|
+
description: rs.description,
|
|
5523
|
+
deprecated: rs.deprecated
|
|
5524
|
+
};
|
|
5525
|
+
}
|
|
5526
|
+
);
|
|
5527
|
+
return {
|
|
5528
|
+
id: name,
|
|
5529
|
+
kind: "object",
|
|
5530
|
+
fields,
|
|
5531
|
+
description: s.description,
|
|
5532
|
+
deprecated: s.deprecated
|
|
5533
|
+
};
|
|
5534
|
+
}
|
|
5535
|
+
if (st === "array") {
|
|
5536
|
+
const name = ctx ?? `Array${++anonCounter2}`;
|
|
5537
|
+
const items = s.items ? schemaToTypeRef(s.items, `${name}_Item`) : {
|
|
5538
|
+
inline: {
|
|
5539
|
+
id: "_any",
|
|
5540
|
+
kind: "scalar",
|
|
5541
|
+
scalar: "any"
|
|
5542
|
+
}
|
|
5543
|
+
};
|
|
5544
|
+
return {
|
|
5545
|
+
id: name,
|
|
5546
|
+
kind: "array",
|
|
5547
|
+
items,
|
|
5548
|
+
description: s.description
|
|
5549
|
+
};
|
|
5550
|
+
}
|
|
5551
|
+
if (st) {
|
|
5552
|
+
const name = ctx ?? `Scalar${++anonCounter2}`;
|
|
5553
|
+
return {
|
|
5554
|
+
id: name,
|
|
5555
|
+
kind: "scalar",
|
|
5556
|
+
scalar: st === "integer" ? "integer" : st === "number" ? "number" : st === "boolean" ? "boolean" : "string",
|
|
5557
|
+
format: s.format,
|
|
5558
|
+
description: s.description
|
|
5559
|
+
};
|
|
5560
|
+
}
|
|
5561
|
+
return {
|
|
5562
|
+
id: ctx ?? `Unknown${++anonCounter2}`,
|
|
5563
|
+
kind: "scalar",
|
|
5564
|
+
scalar: "any"
|
|
5565
|
+
};
|
|
5566
|
+
}
|
|
5567
|
+
if (as.components?.schemas) {
|
|
5568
|
+
for (const [name, schema] of Object.entries(as.components.schemas)) {
|
|
5569
|
+
const t = schemaToType(schema, name);
|
|
5570
|
+
if (t) types.set(name, t);
|
|
5571
|
+
}
|
|
5572
|
+
}
|
|
5573
|
+
if (as.channels) {
|
|
5574
|
+
for (const [channelName, channel] of Object.entries(as.channels)) {
|
|
5575
|
+
let transport = "event";
|
|
5576
|
+
const wsBinding = channel.bindings?.ws || channel.bindings?.websocket;
|
|
5577
|
+
if (wsBinding) {
|
|
5578
|
+
transport = "websocket";
|
|
5579
|
+
}
|
|
5580
|
+
const operations = [
|
|
5581
|
+
{ op: channel.publish, dir: "outbound", suffix: "Publish" },
|
|
5582
|
+
{ op: channel.subscribe, dir: "inbound", suffix: "Subscribe" }
|
|
5583
|
+
];
|
|
5584
|
+
for (const { op, dir, suffix } of operations) {
|
|
5585
|
+
if (!op) continue;
|
|
5586
|
+
const resolvedOp = resolveRef(op);
|
|
5587
|
+
const resolvedMsg = resolveRef(resolvedOp.message);
|
|
5588
|
+
if (resolvedMsg) {
|
|
5589
|
+
const payloadSchema = resolvedMsg.payload ? resolveRef(resolvedMsg.payload) : void 0;
|
|
5590
|
+
const payloadRef = payloadSchema ? schemaToTypeRef(
|
|
5591
|
+
payloadSchema,
|
|
5592
|
+
`${capitalize2(channelName.replace(/[^a-zA-Z0-9]/g, ""))}${suffix}Payload`
|
|
5593
|
+
) : void 0;
|
|
5594
|
+
const headers = [];
|
|
5595
|
+
if (channel.parameters) {
|
|
5596
|
+
for (const [pName, pVal] of Object.entries(channel.parameters)) {
|
|
5597
|
+
const rp = resolveRef(pVal);
|
|
5598
|
+
headers.push({
|
|
5599
|
+
name: pName,
|
|
5600
|
+
location: "header",
|
|
5601
|
+
type: schemaToTypeRef(rp?.schema || rp, `${pName}Param`),
|
|
5602
|
+
required: true,
|
|
5603
|
+
description: rp.description
|
|
5604
|
+
});
|
|
5605
|
+
}
|
|
5606
|
+
}
|
|
5607
|
+
events.push({
|
|
5608
|
+
name: resolvedOp.operationId || resolvedMsg.name || `${channelName.replace(/[^a-zA-Z0-9]/g, "_")}_${dir}`,
|
|
5609
|
+
description: resolvedOp.description || resolvedMsg.description || channel.description,
|
|
5610
|
+
transport,
|
|
5611
|
+
channel: channelName,
|
|
5612
|
+
direction: dir,
|
|
5613
|
+
payload: payloadRef,
|
|
5614
|
+
tags: resolvedMsg.tags?.map((t) => t.name) || [],
|
|
5615
|
+
security: []
|
|
5616
|
+
});
|
|
5617
|
+
}
|
|
5618
|
+
}
|
|
5619
|
+
}
|
|
5620
|
+
}
|
|
5621
|
+
const servers = [];
|
|
5622
|
+
if (as.servers) {
|
|
5623
|
+
for (const [sName, sVal] of Object.entries(as.servers)) {
|
|
5624
|
+
servers.push({
|
|
5625
|
+
url: sVal.url,
|
|
5626
|
+
description: `${sName} - ${sVal.description || sVal.protocol}`
|
|
5627
|
+
});
|
|
5628
|
+
}
|
|
5629
|
+
}
|
|
5630
|
+
return {
|
|
5631
|
+
schema: {
|
|
5632
|
+
info: {
|
|
5633
|
+
title: options.title ?? as.info.title,
|
|
5634
|
+
version: options.version ?? as.info.version,
|
|
5635
|
+
description: as.info.description,
|
|
5636
|
+
sourceFormat: "event",
|
|
5637
|
+
sourceVersion: as.asyncapi
|
|
5638
|
+
},
|
|
5639
|
+
types,
|
|
5640
|
+
endpoints: [],
|
|
5641
|
+
securitySchemes,
|
|
5642
|
+
servers,
|
|
5643
|
+
globalSecurity: [],
|
|
5644
|
+
events,
|
|
5645
|
+
reactiveContracts: []
|
|
5646
|
+
},
|
|
5647
|
+
diagnostics
|
|
5648
|
+
};
|
|
5649
|
+
}
|
|
5650
|
+
|
|
5254
5651
|
// src/sdk/ingest/axiomify-app.ts
|
|
5255
5652
|
function zodToJsonSchema(schema) {
|
|
5256
5653
|
const s = schema;
|
|
@@ -5277,7 +5674,7 @@ function synthesiseOperationId(method, path12) {
|
|
|
5277
5674
|
const parts = [];
|
|
5278
5675
|
for (const seg of path12.split("/")) {
|
|
5279
5676
|
if (!seg) continue;
|
|
5280
|
-
|
|
5677
|
+
const normalized = seg.replace(/^:/, "By-").replace(/\*/g, "All");
|
|
5281
5678
|
const cleanSeg = normalized.split(/[^a-zA-Z0-9]+/).filter(Boolean).map(capitalize).join("");
|
|
5282
5679
|
if (cleanSeg) parts.push(cleanSeg);
|
|
5283
5680
|
}
|
|
@@ -5295,17 +5692,22 @@ function jsonSchemaToIRType(js, ctx) {
|
|
|
5295
5692
|
id: ctx,
|
|
5296
5693
|
kind: "enum",
|
|
5297
5694
|
valueType: vt,
|
|
5298
|
-
values: jsEnum.map((v) => ({
|
|
5695
|
+
values: jsEnum.map((v) => ({
|
|
5696
|
+
name: String(v),
|
|
5697
|
+
value: v
|
|
5698
|
+
}))
|
|
5299
5699
|
};
|
|
5300
5700
|
}
|
|
5301
5701
|
if (jsType === "object" || jsProps) {
|
|
5302
5702
|
const reqSet = new Set(jsRequired ?? []);
|
|
5303
|
-
const fields = Object.entries(jsProps ?? {}).map(
|
|
5304
|
-
name,
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5703
|
+
const fields = Object.entries(jsProps ?? {}).map(
|
|
5704
|
+
([name, prop]) => ({
|
|
5705
|
+
name,
|
|
5706
|
+
type: jsonSchemaToTypeRef(prop, `${ctx}_${capitalize(name)}`),
|
|
5707
|
+
required: reqSet.has(name),
|
|
5708
|
+
description: prop.description
|
|
5709
|
+
})
|
|
5710
|
+
);
|
|
5309
5711
|
return { id: ctx, kind: "object", fields };
|
|
5310
5712
|
}
|
|
5311
5713
|
if (jsType === "array" && jsItems) {
|
|
@@ -5315,8 +5717,16 @@ function jsonSchemaToIRType(js, ctx) {
|
|
|
5315
5717
|
items: jsonSchemaToTypeRef(jsItems, `${ctx}_Item`)
|
|
5316
5718
|
};
|
|
5317
5719
|
}
|
|
5318
|
-
const scalar = mapJsonSchemaScalar(
|
|
5319
|
-
|
|
5720
|
+
const scalar = mapJsonSchemaScalar(
|
|
5721
|
+
jsType ?? "any",
|
|
5722
|
+
js.format
|
|
5723
|
+
);
|
|
5724
|
+
return {
|
|
5725
|
+
id: ctx,
|
|
5726
|
+
kind: "scalar",
|
|
5727
|
+
scalar,
|
|
5728
|
+
format: js.format
|
|
5729
|
+
};
|
|
5320
5730
|
}
|
|
5321
5731
|
function jsonSchemaToTypeRef(js, ctx) {
|
|
5322
5732
|
const t = jsonSchemaToIRType(js, ctx);
|
|
@@ -5366,7 +5776,7 @@ function ingestAxiomifyApp(app, options = {}) {
|
|
|
5366
5776
|
const method = route.method ?? "GET";
|
|
5367
5777
|
const path12 = route.path ?? "/";
|
|
5368
5778
|
const schema = route.schema ?? {};
|
|
5369
|
-
|
|
5779
|
+
const rawOpId = schema.operationId ?? synthesiseOperationId(method, path12);
|
|
5370
5780
|
let opId = sanitizeIdentifier(rawOpId);
|
|
5371
5781
|
if (seenOps.has(opId)) {
|
|
5372
5782
|
let i = 2;
|
|
@@ -5426,7 +5836,9 @@ function ingestAxiomifyApp(app, options = {}) {
|
|
|
5426
5836
|
type: { ref: respType.id }
|
|
5427
5837
|
};
|
|
5428
5838
|
} else if (typeof schema.response === "object" && schema.response !== null && !isZodSchema(schema.response)) {
|
|
5429
|
-
for (const [code, zodSchema] of Object.entries(
|
|
5839
|
+
for (const [code, zodSchema] of Object.entries(
|
|
5840
|
+
schema.response
|
|
5841
|
+
)) {
|
|
5430
5842
|
if (isZodSchema(zodSchema)) {
|
|
5431
5843
|
const js = zodToJsonSchema(zodSchema);
|
|
5432
5844
|
const respType = jsonSchemaToIRType(js, `${opId}Response${code}`);
|
|
@@ -5441,7 +5853,10 @@ function ingestAxiomifyApp(app, options = {}) {
|
|
|
5441
5853
|
}
|
|
5442
5854
|
}
|
|
5443
5855
|
if (!Object.keys(responses).length) {
|
|
5444
|
-
responses["200"] = {
|
|
5856
|
+
responses["200"] = {
|
|
5857
|
+
statusCode: "200",
|
|
5858
|
+
description: "Successful response"
|
|
5859
|
+
};
|
|
5445
5860
|
}
|
|
5446
5861
|
const security = (schema.security ?? []).map(
|
|
5447
5862
|
(s) => {
|
|
@@ -5574,7 +5989,10 @@ async function ingestGraphQL(sdl, options = {}) {
|
|
|
5574
5989
|
ID: "string"
|
|
5575
5990
|
};
|
|
5576
5991
|
if (scalarMap[name]) {
|
|
5577
|
-
return {
|
|
5992
|
+
return {
|
|
5993
|
+
inline: { id: name, kind: "scalar", scalar: scalarMap[name] },
|
|
5994
|
+
nullable: true
|
|
5995
|
+
};
|
|
5578
5996
|
}
|
|
5579
5997
|
return { ref: name, nullable: true };
|
|
5580
5998
|
}
|
|
@@ -5583,17 +6001,19 @@ async function ingestGraphQL(sdl, options = {}) {
|
|
|
5583
6001
|
if (["String", "Int", "Float", "Boolean", "ID"].includes(name)) continue;
|
|
5584
6002
|
if (isObjectType(gqlType) || isInputObjectType(gqlType) || isInterfaceType(gqlType)) {
|
|
5585
6003
|
const gqlFields = gqlType.getFields();
|
|
5586
|
-
const fields = Object.entries(gqlFields).map(
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
6004
|
+
const fields = Object.entries(gqlFields).map(
|
|
6005
|
+
([fieldName, field]) => {
|
|
6006
|
+
const typeRef = gqlTypeToRef(field.type);
|
|
6007
|
+
return {
|
|
6008
|
+
name: fieldName,
|
|
6009
|
+
type: typeRef,
|
|
6010
|
+
required: !typeRef.nullable,
|
|
6011
|
+
description: field.description ?? void 0,
|
|
6012
|
+
deprecated: !!field.deprecationReason,
|
|
6013
|
+
deprecationReason: field.deprecationReason ?? void 0
|
|
6014
|
+
};
|
|
6015
|
+
}
|
|
6016
|
+
);
|
|
5597
6017
|
const irType = {
|
|
5598
6018
|
id: name,
|
|
5599
6019
|
kind: "object",
|
|
@@ -5694,7 +6114,7 @@ async function ingestGraphQL(sdl, options = {}) {
|
|
|
5694
6114
|
}
|
|
5695
6115
|
|
|
5696
6116
|
// src/sdk/ingest/openapi.ts
|
|
5697
|
-
var
|
|
6117
|
+
var MAX_REF_DEPTH2 = 64;
|
|
5698
6118
|
function ingestOpenApi(spec, options = {}) {
|
|
5699
6119
|
const oa = spec;
|
|
5700
6120
|
const diagnostics = [];
|
|
@@ -5704,11 +6124,11 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
5704
6124
|
const refStack = /* @__PURE__ */ new Set();
|
|
5705
6125
|
let anonCounter2 = 0;
|
|
5706
6126
|
function resolveRef(schema, depth = 0) {
|
|
5707
|
-
if (depth >
|
|
6127
|
+
if (depth > MAX_REF_DEPTH2) {
|
|
5708
6128
|
diagnostics.push({
|
|
5709
6129
|
severity: "error",
|
|
5710
6130
|
code: "REF_DEPTH_EXCEEDED",
|
|
5711
|
-
message: `$ref resolution exceeded max depth (${
|
|
6131
|
+
message: `$ref resolution exceeded max depth (${MAX_REF_DEPTH2})`
|
|
5712
6132
|
});
|
|
5713
6133
|
return { type: "object" };
|
|
5714
6134
|
}
|
|
@@ -5717,7 +6137,10 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
5717
6137
|
if (refStack.has(ref)) return schema;
|
|
5718
6138
|
refStack.add(ref);
|
|
5719
6139
|
try {
|
|
5720
|
-
const resolved = resolveJsonPointer(
|
|
6140
|
+
const resolved = resolveJsonPointer(
|
|
6141
|
+
oa,
|
|
6142
|
+
ref
|
|
6143
|
+
);
|
|
5721
6144
|
if (!resolved) {
|
|
5722
6145
|
diagnostics.push({
|
|
5723
6146
|
severity: "warning",
|
|
@@ -5736,7 +6159,8 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
5736
6159
|
const path12 = pointer.replace(/^#\//, "").split("/").map((s) => s.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
5737
6160
|
let cur = root;
|
|
5738
6161
|
for (const seg of path12) {
|
|
5739
|
-
if (cur === null || cur === void 0 || typeof cur !== "object")
|
|
6162
|
+
if (cur === null || cur === void 0 || typeof cur !== "object")
|
|
6163
|
+
return void 0;
|
|
5740
6164
|
cur = cur[seg];
|
|
5741
6165
|
}
|
|
5742
6166
|
return cur;
|
|
@@ -5767,8 +6191,12 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
5767
6191
|
return { ref: refToTypeName(schema.$ref), nullable: schema.nullable };
|
|
5768
6192
|
}
|
|
5769
6193
|
const t = schemaToType(schema, ctx);
|
|
5770
|
-
if (t && types.has(t.id) && t.id !== ctx)
|
|
5771
|
-
|
|
6194
|
+
if (t && types.has(t.id) && t.id !== ctx)
|
|
6195
|
+
return { ref: t.id, nullable: schema.nullable };
|
|
6196
|
+
return {
|
|
6197
|
+
inline: t ?? { id: "_unknown", kind: "scalar", scalar: "any" },
|
|
6198
|
+
nullable: schema.nullable
|
|
6199
|
+
};
|
|
5772
6200
|
}
|
|
5773
6201
|
function schemaToType(raw, ctx) {
|
|
5774
6202
|
const s = resolveRef(raw);
|
|
@@ -5812,7 +6240,10 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
5812
6240
|
id: name,
|
|
5813
6241
|
kind: "enum",
|
|
5814
6242
|
valueType: vt,
|
|
5815
|
-
values: s.enum.map((v) => ({
|
|
6243
|
+
values: s.enum.map((v) => ({
|
|
6244
|
+
name: String(v),
|
|
6245
|
+
value: v
|
|
6246
|
+
})),
|
|
5816
6247
|
description: s.description,
|
|
5817
6248
|
deprecated: s.deprecated
|
|
5818
6249
|
};
|
|
@@ -5821,24 +6252,29 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
5821
6252
|
if (st === "object" || s.properties) {
|
|
5822
6253
|
const name = ctx ?? `Object${++anonCounter2}`;
|
|
5823
6254
|
const reqSet = new Set(s.required ?? []);
|
|
5824
|
-
const fields = Object.entries(s.properties ?? {}).map(
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
6255
|
+
const fields = Object.entries(s.properties ?? {}).map(
|
|
6256
|
+
([pn, ps]) => {
|
|
6257
|
+
const rs = resolveRef(ps);
|
|
6258
|
+
const constraints = extractConstraints(rs);
|
|
6259
|
+
return {
|
|
6260
|
+
name: pn,
|
|
6261
|
+
type: schemaToTypeRef(rs, `${name}_${capitalize2(pn)}`),
|
|
6262
|
+
required: reqSet.has(pn),
|
|
6263
|
+
description: rs.description,
|
|
6264
|
+
deprecated: rs.deprecated,
|
|
6265
|
+
readOnly: rs.readOnly,
|
|
6266
|
+
writeOnly: rs.writeOnly,
|
|
6267
|
+
example: rs.example,
|
|
6268
|
+
constraints: Object.keys(constraints).length ? constraints : void 0
|
|
6269
|
+
};
|
|
6270
|
+
}
|
|
6271
|
+
);
|
|
5839
6272
|
let ap;
|
|
5840
6273
|
if (s.additionalProperties !== void 0) {
|
|
5841
|
-
ap = typeof s.additionalProperties === "boolean" ? s.additionalProperties : schemaToTypeRef(
|
|
6274
|
+
ap = typeof s.additionalProperties === "boolean" ? s.additionalProperties : schemaToTypeRef(
|
|
6275
|
+
s.additionalProperties,
|
|
6276
|
+
`${name}_AdditionalProps`
|
|
6277
|
+
);
|
|
5842
6278
|
}
|
|
5843
6279
|
return {
|
|
5844
6280
|
id: name,
|
|
@@ -5855,7 +6291,13 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
5855
6291
|
}
|
|
5856
6292
|
if (st === "array") {
|
|
5857
6293
|
const name = ctx ?? `Array${++anonCounter2}`;
|
|
5858
|
-
const items = s.items ? schemaToTypeRef(s.items, `${name}_Item`) : {
|
|
6294
|
+
const items = s.items ? schemaToTypeRef(s.items, `${name}_Item`) : {
|
|
6295
|
+
inline: {
|
|
6296
|
+
id: "_any",
|
|
6297
|
+
kind: "scalar",
|
|
6298
|
+
scalar: "any"
|
|
6299
|
+
}
|
|
6300
|
+
};
|
|
5859
6301
|
return {
|
|
5860
6302
|
id: name,
|
|
5861
6303
|
kind: "array",
|
|
@@ -5880,7 +6322,11 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
5880
6322
|
constraints: Object.keys(constraints).length ? constraints : void 0
|
|
5881
6323
|
};
|
|
5882
6324
|
}
|
|
5883
|
-
return {
|
|
6325
|
+
return {
|
|
6326
|
+
id: ctx ?? `Unknown${++anonCounter2}`,
|
|
6327
|
+
kind: "scalar",
|
|
6328
|
+
scalar: "any"
|
|
6329
|
+
};
|
|
5884
6330
|
}
|
|
5885
6331
|
function mapScalar(type, format) {
|
|
5886
6332
|
switch (type) {
|
|
@@ -5923,8 +6369,10 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
5923
6369
|
if (s.pattern !== void 0) c.pattern = s.pattern;
|
|
5924
6370
|
if (s.minimum !== void 0) c.minimum = s.minimum;
|
|
5925
6371
|
if (s.maximum !== void 0) c.maximum = s.maximum;
|
|
5926
|
-
if (s.exclusiveMinimum !== void 0)
|
|
5927
|
-
|
|
6372
|
+
if (s.exclusiveMinimum !== void 0)
|
|
6373
|
+
c.exclusiveMinimum = s.exclusiveMinimum;
|
|
6374
|
+
if (s.exclusiveMaximum !== void 0)
|
|
6375
|
+
c.exclusiveMaximum = s.exclusiveMaximum;
|
|
5928
6376
|
if (s.multipleOf !== void 0) c.multipleOf = s.multipleOf;
|
|
5929
6377
|
return c;
|
|
5930
6378
|
}
|
|
@@ -5932,7 +6380,9 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
5932
6380
|
const t = schemaToType(schema, name);
|
|
5933
6381
|
if (t) types.set(name, t);
|
|
5934
6382
|
}
|
|
5935
|
-
for (const [name, scheme] of Object.entries(
|
|
6383
|
+
for (const [name, scheme] of Object.entries(
|
|
6384
|
+
oa.components?.securitySchemes ?? {}
|
|
6385
|
+
)) {
|
|
5936
6386
|
securitySchemes.set(name, {
|
|
5937
6387
|
name,
|
|
5938
6388
|
type: scheme.type,
|
|
@@ -5946,7 +6396,15 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
5946
6396
|
}
|
|
5947
6397
|
const seenOps = /* @__PURE__ */ new Set();
|
|
5948
6398
|
for (const [path12, pathItem] of Object.entries(oa.paths ?? {})) {
|
|
5949
|
-
for (const method of [
|
|
6399
|
+
for (const method of [
|
|
6400
|
+
"get",
|
|
6401
|
+
"post",
|
|
6402
|
+
"put",
|
|
6403
|
+
"patch",
|
|
6404
|
+
"delete",
|
|
6405
|
+
"options",
|
|
6406
|
+
"head"
|
|
6407
|
+
]) {
|
|
5950
6408
|
const op = pathItem[method];
|
|
5951
6409
|
if (!op) continue;
|
|
5952
6410
|
let opId = op.operationId ?? synthesiseOperationId2(method, path12);
|
|
@@ -5998,12 +6456,18 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
5998
6456
|
let successResponse;
|
|
5999
6457
|
let streamingContract = void 0;
|
|
6000
6458
|
for (const [sc, resp] of Object.entries(op.responses ?? {})) {
|
|
6001
|
-
const irR = {
|
|
6459
|
+
const irR = {
|
|
6460
|
+
statusCode: sc,
|
|
6461
|
+
description: resp.description ?? `Response ${sc}`
|
|
6462
|
+
};
|
|
6002
6463
|
if (resp.content) {
|
|
6003
6464
|
const [ct, mt] = Object.entries(resp.content)[0] ?? [];
|
|
6004
6465
|
if (ct && mt?.schema) {
|
|
6005
6466
|
irR.contentType = ct;
|
|
6006
|
-
irR.type = schemaToTypeRef(
|
|
6467
|
+
irR.type = schemaToTypeRef(
|
|
6468
|
+
resolveRef(mt.schema),
|
|
6469
|
+
`${opId}Response${sc}`
|
|
6470
|
+
);
|
|
6007
6471
|
if (ct === "text/event-stream") {
|
|
6008
6472
|
streamingContract = {
|
|
6009
6473
|
transport: "sse",
|
|
@@ -6017,7 +6481,13 @@ function ingestOpenApi(spec, options = {}) {
|
|
|
6017
6481
|
irR.headers = Object.entries(resp.headers).map(([n, h]) => ({
|
|
6018
6482
|
name: n,
|
|
6019
6483
|
location: "header",
|
|
6020
|
-
type: h.schema ? schemaToTypeRef(resolveRef(h.schema)) : {
|
|
6484
|
+
type: h.schema ? schemaToTypeRef(resolveRef(h.schema)) : {
|
|
6485
|
+
inline: {
|
|
6486
|
+
id: "_string",
|
|
6487
|
+
kind: "scalar",
|
|
6488
|
+
scalar: "string"
|
|
6489
|
+
}
|
|
6490
|
+
},
|
|
6021
6491
|
required: false,
|
|
6022
6492
|
description: h.description
|
|
6023
6493
|
}));
|
|
@@ -6096,7 +6566,9 @@ var DartTypeEmitter = class {
|
|
|
6096
6566
|
const sortedIds = this.graph.topologicalSort();
|
|
6097
6567
|
emitter.line(`// GENERATED CODE - DO NOT MODIFY BY HAND`);
|
|
6098
6568
|
emitter.line();
|
|
6099
|
-
emitter.line(
|
|
6569
|
+
emitter.line(
|
|
6570
|
+
`import 'package:freezed_annotation/freezed_annotation.dart';`
|
|
6571
|
+
);
|
|
6100
6572
|
emitter.line();
|
|
6101
6573
|
emitter.line(`part 'types.freezed.dart';`);
|
|
6102
6574
|
emitter.line(`part 'types.g.dart';`);
|
|
@@ -6116,26 +6588,36 @@ var DartTypeEmitter = class {
|
|
|
6116
6588
|
case "object":
|
|
6117
6589
|
emitter.line(`@freezed`);
|
|
6118
6590
|
emitter.block(`class ${type.id} with _$${type.id} {`, `}`, () => {
|
|
6119
|
-
emitter.block(
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
const
|
|
6124
|
-
|
|
6125
|
-
|
|
6126
|
-
|
|
6591
|
+
emitter.block(
|
|
6592
|
+
`const factory ${type.id}({`,
|
|
6593
|
+
`}) = _${type.id};`,
|
|
6594
|
+
() => {
|
|
6595
|
+
for (const field of type.fields) {
|
|
6596
|
+
if (field.description) this.emitDoc(emitter, field.description);
|
|
6597
|
+
const dartType = this.renderTypeRef(field.type);
|
|
6598
|
+
const opt = field.required ? "" : "?";
|
|
6599
|
+
const req = field.required ? "required " : "";
|
|
6600
|
+
if (field.name !== this.toCamelCase(field.name)) {
|
|
6601
|
+
emitter.line(`@JsonKey(name: '${field.name}')`);
|
|
6602
|
+
}
|
|
6603
|
+
emitter.line(
|
|
6604
|
+
`${req}${dartType}${opt} ${this.toCamelCase(field.name)},`
|
|
6605
|
+
);
|
|
6127
6606
|
}
|
|
6128
|
-
emitter.line(`${req}${dartType}${opt} ${this.toCamelCase(field.name)},`);
|
|
6129
6607
|
}
|
|
6130
|
-
|
|
6608
|
+
);
|
|
6131
6609
|
emitter.line();
|
|
6132
|
-
emitter.line(
|
|
6610
|
+
emitter.line(
|
|
6611
|
+
`factory ${type.id}.fromJson(Map<String, dynamic> json) => _$${type.id}FromJson(json);`
|
|
6612
|
+
);
|
|
6133
6613
|
});
|
|
6134
6614
|
break;
|
|
6135
6615
|
case "enum":
|
|
6136
6616
|
emitter.block(`enum ${type.id} {`, `}`, () => {
|
|
6137
6617
|
for (const v of type.values) {
|
|
6138
|
-
emitter.line(
|
|
6618
|
+
emitter.line(
|
|
6619
|
+
`@JsonValue(${typeof v.value === "string" ? `'${v.value}'` : v.value})`
|
|
6620
|
+
);
|
|
6139
6621
|
emitter.line(`${this.toCamelCase(v.name)},`);
|
|
6140
6622
|
}
|
|
6141
6623
|
});
|
|
@@ -6147,23 +6629,31 @@ var DartTypeEmitter = class {
|
|
|
6147
6629
|
const member = type.members[i];
|
|
6148
6630
|
const name = member.ref ? member.ref : `Value${i}`;
|
|
6149
6631
|
const memberType = this.renderTypeRef(member);
|
|
6150
|
-
emitter.line(
|
|
6632
|
+
emitter.line(
|
|
6633
|
+
`const factory ${type.id}.${this.toCamelCase(name)}(${memberType} value) = _${type.id}${name};`
|
|
6634
|
+
);
|
|
6151
6635
|
}
|
|
6152
6636
|
emitter.line();
|
|
6153
|
-
emitter.line(
|
|
6637
|
+
emitter.line(
|
|
6638
|
+
`factory ${type.id}.fromJson(Map<String, dynamic> json) => _$${type.id}FromJson(json);`
|
|
6639
|
+
);
|
|
6154
6640
|
});
|
|
6155
6641
|
break;
|
|
6156
6642
|
case "intersection":
|
|
6157
6643
|
emitter.line(`typedef ${type.id} = Map<String, dynamic>;`);
|
|
6158
6644
|
break;
|
|
6159
6645
|
case "array":
|
|
6160
|
-
emitter.line(
|
|
6646
|
+
emitter.line(
|
|
6647
|
+
`typedef ${type.id} = List<${this.renderTypeRef(type.items)}>;`
|
|
6648
|
+
);
|
|
6161
6649
|
break;
|
|
6162
6650
|
case "scalar":
|
|
6163
6651
|
emitter.line(`typedef ${type.id} = ${this.renderScalar(type.scalar)};`);
|
|
6164
6652
|
break;
|
|
6165
6653
|
case "map":
|
|
6166
|
-
emitter.line(
|
|
6654
|
+
emitter.line(
|
|
6655
|
+
`typedef ${type.id} = Map<String, ${this.renderTypeRef(type.valueType)}>;`
|
|
6656
|
+
);
|
|
6167
6657
|
break;
|
|
6168
6658
|
case "tuple":
|
|
6169
6659
|
emitter.line(`typedef ${type.id} = List<dynamic>; // Tuple`);
|
|
@@ -6177,8 +6667,10 @@ var DartTypeEmitter = class {
|
|
|
6177
6667
|
let t = "dynamic";
|
|
6178
6668
|
if (ref.ref) t = ref.ref;
|
|
6179
6669
|
else if (ref.inline) {
|
|
6180
|
-
if (ref.inline.kind === "scalar")
|
|
6181
|
-
|
|
6670
|
+
if (ref.inline.kind === "scalar")
|
|
6671
|
+
t = this.renderScalar(ref.inline.scalar);
|
|
6672
|
+
else if (ref.inline.kind === "array")
|
|
6673
|
+
t = `List<${this.renderTypeRef(ref.inline.items)}>`;
|
|
6182
6674
|
}
|
|
6183
6675
|
if (ref.isArray) t = `List<${t}>`;
|
|
6184
6676
|
return t;
|
|
@@ -6227,18 +6719,28 @@ var DartClientEmitter = class {
|
|
|
6227
6719
|
emitter.line(`import 'package:riverpod/riverpod.dart';`);
|
|
6228
6720
|
emitter.line(`import 'types.dart';`);
|
|
6229
6721
|
emitter.line();
|
|
6230
|
-
emitter.line(
|
|
6231
|
-
|
|
6722
|
+
emitter.line(
|
|
6723
|
+
`final apiClientProvider = Provider<${this.className}>((ref) {`
|
|
6724
|
+
);
|
|
6725
|
+
emitter.line(
|
|
6726
|
+
` throw UnimplementedError('Configure and override apiClientProvider in your provider container');`
|
|
6727
|
+
);
|
|
6232
6728
|
emitter.line(`});`);
|
|
6233
6729
|
emitter.line();
|
|
6234
6730
|
emitter.block(`class ${this.className} {`, `}`, () => {
|
|
6235
6731
|
emitter.line(`final Dio _dio;`);
|
|
6236
6732
|
emitter.line();
|
|
6237
|
-
emitter.block(
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6733
|
+
emitter.block(
|
|
6734
|
+
`${this.className}({required String baseUrl, String? token, Dio? dio}) : _dio = dio ?? Dio(BaseOptions(baseUrl: baseUrl)) {`,
|
|
6735
|
+
`}`,
|
|
6736
|
+
() => {
|
|
6737
|
+
emitter.block(`if (token != null) {`, `}`, () => {
|
|
6738
|
+
emitter.line(
|
|
6739
|
+
`_dio.options.headers['Authorization'] = 'Bearer $token';`
|
|
6740
|
+
);
|
|
6741
|
+
});
|
|
6742
|
+
}
|
|
6743
|
+
);
|
|
6242
6744
|
emitter.line();
|
|
6243
6745
|
for (const ep of this.schema.endpoints) {
|
|
6244
6746
|
if (ep.transport !== "rest") continue;
|
|
@@ -6250,51 +6752,69 @@ var DartClientEmitter = class {
|
|
|
6250
6752
|
}
|
|
6251
6753
|
emitMethod(emitter, ep) {
|
|
6252
6754
|
const methodName = this.toCamelCase(ep.operationId);
|
|
6253
|
-
|
|
6254
|
-
|
|
6255
|
-
|
|
6755
|
+
const reqArgs = ep.pathParams.map(
|
|
6756
|
+
(p) => `required ${this.renderTypeRef(p.type)} ${this.toCamelCase(p.name)}`
|
|
6757
|
+
);
|
|
6758
|
+
const optArgs = ep.queryParams.map(
|
|
6759
|
+
(p) => `${this.renderTypeRef(p.type)}? ${this.toCamelCase(p.name)}`
|
|
6760
|
+
);
|
|
6761
|
+
if (ep.requestBody)
|
|
6762
|
+
reqArgs.push(`required ${this.renderTypeRef(ep.requestBody.type)} body`);
|
|
6256
6763
|
const allArgs = [...reqArgs, ...optArgs].join(", ");
|
|
6257
6764
|
const retType = this.buildResponseType(ep);
|
|
6258
|
-
emitter.block(
|
|
6259
|
-
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
|
|
6269
|
-
|
|
6270
|
-
|
|
6271
|
-
|
|
6272
|
-
|
|
6273
|
-
|
|
6274
|
-
|
|
6275
|
-
|
|
6276
|
-
|
|
6277
|
-
|
|
6278
|
-
emitter.
|
|
6279
|
-
|
|
6280
|
-
|
|
6281
|
-
|
|
6282
|
-
|
|
6283
|
-
|
|
6284
|
-
|
|
6285
|
-
|
|
6765
|
+
emitter.block(
|
|
6766
|
+
`Future<${retType}> ${methodName}(${allArgs.length > 0 ? "{" + allArgs + "}" : ""}) async {`,
|
|
6767
|
+
`}`,
|
|
6768
|
+
() => {
|
|
6769
|
+
const method = ep.method?.toUpperCase() || "GET";
|
|
6770
|
+
const pathTemplate = ep.path || "/";
|
|
6771
|
+
let pathExpr = pathTemplate;
|
|
6772
|
+
for (const p of ep.pathParams) {
|
|
6773
|
+
pathExpr = pathExpr.replace(
|
|
6774
|
+
`{${p.name}}`,
|
|
6775
|
+
`$${this.toCamelCase(p.name)}`
|
|
6776
|
+
);
|
|
6777
|
+
}
|
|
6778
|
+
if (ep.queryParams.length > 0) {
|
|
6779
|
+
emitter.line(`final queryParameters = <String, dynamic>{`);
|
|
6780
|
+
for (const q of ep.queryParams) {
|
|
6781
|
+
emitter.line(` '${q.name}': ${this.toCamelCase(q.name)},`);
|
|
6782
|
+
}
|
|
6783
|
+
emitter.line(`};`);
|
|
6784
|
+
}
|
|
6785
|
+
emitter.block(`try {`, `}`, () => {
|
|
6786
|
+
const queryArg = ep.queryParams.length > 0 ? ", queryParameters: queryParameters" : "";
|
|
6787
|
+
const bodyArg = ep.requestBody ? ", data: body.toJson()" : "";
|
|
6788
|
+
emitter.line(`final response = await _dio.request(`);
|
|
6789
|
+
emitter.line(` '${pathExpr}',`);
|
|
6790
|
+
emitter.line(` options: Options(method: '${method}'),`);
|
|
6791
|
+
emitter.line(` ${queryArg}${bodyArg}`);
|
|
6792
|
+
emitter.line(`);`);
|
|
6793
|
+
if (retType !== "void") {
|
|
6794
|
+
const success = ep.successResponse;
|
|
6795
|
+
const ref = success && ep.responses[success]?.type?.ref;
|
|
6796
|
+
if (ref) {
|
|
6797
|
+
if (ep.responses[success].type?.isArray) {
|
|
6798
|
+
emitter.line(
|
|
6799
|
+
`return (response.data as List).map((e) => ${ref}.fromJson(e as Map<String, dynamic>)).toList();`
|
|
6800
|
+
);
|
|
6801
|
+
} else {
|
|
6802
|
+
emitter.line(
|
|
6803
|
+
`return ${ref}.fromJson(response.data as Map<String, dynamic>);`
|
|
6804
|
+
);
|
|
6805
|
+
}
|
|
6286
6806
|
} else {
|
|
6287
|
-
emitter.line(`return
|
|
6807
|
+
emitter.line(`return response.data;`);
|
|
6288
6808
|
}
|
|
6289
|
-
} else {
|
|
6290
|
-
emitter.line(`return response.data;`);
|
|
6291
6809
|
}
|
|
6292
|
-
}
|
|
6293
|
-
|
|
6294
|
-
|
|
6295
|
-
|
|
6296
|
-
|
|
6297
|
-
|
|
6810
|
+
});
|
|
6811
|
+
emitter.block(`on DioException catch (e) {`, `}`, () => {
|
|
6812
|
+
emitter.line(
|
|
6813
|
+
`throw Exception('Request ${methodName} failed: \${e.message}');`
|
|
6814
|
+
);
|
|
6815
|
+
});
|
|
6816
|
+
}
|
|
6817
|
+
);
|
|
6298
6818
|
}
|
|
6299
6819
|
buildResponseType(ep) {
|
|
6300
6820
|
const success = ep.successResponse;
|
|
@@ -6329,7 +6849,9 @@ var DartGenerator = class extends Generator {
|
|
|
6329
6849
|
this.addFile("lib/types.dart", typeEmitter.emitAll());
|
|
6330
6850
|
const clientEmitter = new DartClientEmitter(this.schema, "ApiClient");
|
|
6331
6851
|
this.addFile("lib/client.dart", clientEmitter.emitAll());
|
|
6332
|
-
this.addFile(
|
|
6852
|
+
this.addFile(
|
|
6853
|
+
"pubspec.yaml",
|
|
6854
|
+
`name: ${this.options.packageName}
|
|
6333
6855
|
version: ${this.options.version || "1.0.0"}
|
|
6334
6856
|
environment:
|
|
6335
6857
|
sdk: '>=3.0.0 <4.0.0'
|
|
@@ -6344,7 +6866,8 @@ dev_dependencies:
|
|
|
6344
6866
|
build_runner: ^2.4.6
|
|
6345
6867
|
freezed: ^2.4.5
|
|
6346
6868
|
json_serializable: ^6.7.1
|
|
6347
|
-
`
|
|
6869
|
+
`
|
|
6870
|
+
);
|
|
6348
6871
|
return this.files;
|
|
6349
6872
|
}
|
|
6350
6873
|
};
|
|
@@ -6391,7 +6914,9 @@ var GoTypeEmitter = class {
|
|
|
6391
6914
|
emitter.line(`${this.capitalize(field.name)} ${goType} ${tag}`);
|
|
6392
6915
|
}
|
|
6393
6916
|
if (type.additionalProperties) {
|
|
6394
|
-
emitter.line(
|
|
6917
|
+
emitter.line(
|
|
6918
|
+
`AdditionalProperties map[string]interface{} \`json:"-"\``
|
|
6919
|
+
);
|
|
6395
6920
|
}
|
|
6396
6921
|
});
|
|
6397
6922
|
break;
|
|
@@ -6401,7 +6926,9 @@ var GoTypeEmitter = class {
|
|
|
6401
6926
|
emitter.block(`const (`, `)`, () => {
|
|
6402
6927
|
for (const v of type.values) {
|
|
6403
6928
|
const val = typeof v.value === "string" ? `"${v.value}"` : v.value;
|
|
6404
|
-
emitter.line(
|
|
6929
|
+
emitter.line(
|
|
6930
|
+
`${type.id}_${this.capitalize(v.name)} ${type.id} = ${val}`
|
|
6931
|
+
);
|
|
6405
6932
|
}
|
|
6406
6933
|
});
|
|
6407
6934
|
break;
|
|
@@ -6410,22 +6937,36 @@ var GoTypeEmitter = class {
|
|
|
6410
6937
|
emitter.line(`Value interface{}`);
|
|
6411
6938
|
});
|
|
6412
6939
|
emitter.line();
|
|
6413
|
-
emitter.block(
|
|
6414
|
-
|
|
6415
|
-
|
|
6940
|
+
emitter.block(
|
|
6941
|
+
`func (u ${type.id}) MarshalJSON() ([]byte, error) {`,
|
|
6942
|
+
`}`,
|
|
6943
|
+
() => {
|
|
6944
|
+
emitter.line(`return json.Marshal(u.Value)`);
|
|
6945
|
+
}
|
|
6946
|
+
);
|
|
6416
6947
|
emitter.line();
|
|
6417
|
-
emitter.block(
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
emitter.line(`
|
|
6425
|
-
|
|
6948
|
+
emitter.block(
|
|
6949
|
+
`func (u *${type.id}) UnmarshalJSON(data []byte) error {`,
|
|
6950
|
+
`}`,
|
|
6951
|
+
() => {
|
|
6952
|
+
for (let i = 0; i < type.members.length; i++) {
|
|
6953
|
+
const member = type.members[i];
|
|
6954
|
+
const memberType = this.renderTypeRef(member);
|
|
6955
|
+
emitter.line(`var val${i} ${memberType}`);
|
|
6956
|
+
emitter.block(
|
|
6957
|
+
`if err := json.Unmarshal(data, &val${i}); err == nil {`,
|
|
6958
|
+
`}`,
|
|
6959
|
+
() => {
|
|
6960
|
+
emitter.line(`u.Value = val${i}`);
|
|
6961
|
+
emitter.line(`return nil`);
|
|
6962
|
+
}
|
|
6963
|
+
);
|
|
6964
|
+
}
|
|
6965
|
+
emitter.line(
|
|
6966
|
+
`return errors.New("cannot unmarshal into any union member of ${type.id}")`
|
|
6967
|
+
);
|
|
6426
6968
|
}
|
|
6427
|
-
|
|
6428
|
-
});
|
|
6969
|
+
);
|
|
6429
6970
|
break;
|
|
6430
6971
|
case "intersection":
|
|
6431
6972
|
emitter.line(`type ${type.id} map[string]interface{}`);
|
|
@@ -6445,8 +6986,10 @@ var GoTypeEmitter = class {
|
|
|
6445
6986
|
let t = "interface{}";
|
|
6446
6987
|
if (ref.ref) t = ref.ref;
|
|
6447
6988
|
else if (ref.inline) {
|
|
6448
|
-
if (ref.inline.kind === "scalar")
|
|
6449
|
-
|
|
6989
|
+
if (ref.inline.kind === "scalar")
|
|
6990
|
+
t = this.renderScalar(ref.inline.scalar);
|
|
6991
|
+
else if (ref.inline.kind === "array")
|
|
6992
|
+
t = `[]${this.renderTypeRef(ref.inline.items)}`;
|
|
6450
6993
|
}
|
|
6451
6994
|
if (ref.isArray) t = `[]${t}`;
|
|
6452
6995
|
if (ref.nullable) t = `*${t}`;
|
|
@@ -6513,11 +7056,15 @@ var GoClientEmitter = class {
|
|
|
6513
7056
|
emitter.line();
|
|
6514
7057
|
emitter.line(`type ClientOption func(*Client)`);
|
|
6515
7058
|
emitter.line();
|
|
6516
|
-
emitter.block(
|
|
6517
|
-
|
|
6518
|
-
|
|
6519
|
-
|
|
6520
|
-
|
|
7059
|
+
emitter.block(
|
|
7060
|
+
`func WithHTTPClient(hc *http.Client) ClientOption {`,
|
|
7061
|
+
`}`,
|
|
7062
|
+
() => {
|
|
7063
|
+
emitter.block(`return func(c *Client) {`, `}`, () => {
|
|
7064
|
+
emitter.line(`c.HTTPClient = hc`);
|
|
7065
|
+
});
|
|
7066
|
+
}
|
|
7067
|
+
);
|
|
6521
7068
|
emitter.line();
|
|
6522
7069
|
emitter.block(`func WithToken(token string) ClientOption {`, `}`, () => {
|
|
6523
7070
|
emitter.block(`return func(c *Client) {`, `}`, () => {
|
|
@@ -6525,11 +7072,17 @@ var GoClientEmitter = class {
|
|
|
6525
7072
|
});
|
|
6526
7073
|
});
|
|
6527
7074
|
emitter.line();
|
|
6528
|
-
emitter.block(
|
|
6529
|
-
|
|
6530
|
-
|
|
6531
|
-
|
|
6532
|
-
|
|
7075
|
+
emitter.block(
|
|
7076
|
+
`func NewClient(baseURL string, opts ...ClientOption) *Client {`,
|
|
7077
|
+
`}`,
|
|
7078
|
+
() => {
|
|
7079
|
+
emitter.line(
|
|
7080
|
+
`c := &Client{BaseURL: baseURL, HTTPClient: &http.Client{}}`
|
|
7081
|
+
);
|
|
7082
|
+
emitter.line(`for _, opt := range opts { opt(c) }`);
|
|
7083
|
+
emitter.line(`return c`);
|
|
7084
|
+
}
|
|
7085
|
+
);
|
|
6533
7086
|
emitter.line();
|
|
6534
7087
|
for (const ep of this.schema.endpoints) {
|
|
6535
7088
|
if (ep.transport !== "rest") continue;
|
|
@@ -6545,10 +7098,14 @@ var GoClientEmitter = class {
|
|
|
6545
7098
|
if (hasParams) {
|
|
6546
7099
|
emitter.block(`type ${reqStructName} struct {`, `}`, () => {
|
|
6547
7100
|
for (const p of ep.pathParams) {
|
|
6548
|
-
emitter.line(
|
|
7101
|
+
emitter.line(
|
|
7102
|
+
`${this.capitalize(p.name)} ${this.renderTypeRef(p.type)}`
|
|
7103
|
+
);
|
|
6549
7104
|
}
|
|
6550
7105
|
for (const p of ep.queryParams) {
|
|
6551
|
-
emitter.line(
|
|
7106
|
+
emitter.line(
|
|
7107
|
+
`${this.capitalize(p.name)} ${this.renderTypeRef(p.type)}`
|
|
7108
|
+
);
|
|
6552
7109
|
}
|
|
6553
7110
|
if (ep.requestBody) {
|
|
6554
7111
|
emitter.line(`Body ${this.renderTypeRef(ep.requestBody.type)}`);
|
|
@@ -6558,58 +7115,78 @@ var GoClientEmitter = class {
|
|
|
6558
7115
|
}
|
|
6559
7116
|
const retType = this.buildResponseType(ep);
|
|
6560
7117
|
const args = hasParams ? `req *${reqStructName}` : ``;
|
|
6561
|
-
emitter.block(
|
|
6562
|
-
|
|
6563
|
-
|
|
6564
|
-
|
|
6565
|
-
|
|
6566
|
-
|
|
6567
|
-
|
|
6568
|
-
|
|
6569
|
-
|
|
7118
|
+
emitter.block(
|
|
7119
|
+
`func (c *Client) ${methodName}(ctx context.Context${hasParams ? ", " + args : ""}) (*${retType}, error) {`,
|
|
7120
|
+
`}`,
|
|
7121
|
+
() => {
|
|
7122
|
+
const method = ep.method?.toUpperCase() || "GET";
|
|
7123
|
+
const pathTemplate = ep.path || "/";
|
|
7124
|
+
emitter.line(`reqURL := c.BaseURL + "${pathTemplate}"`);
|
|
7125
|
+
for (const p of ep.pathParams) {
|
|
7126
|
+
emitter.line(
|
|
7127
|
+
`reqURL = strings.ReplaceAll(reqURL, "{${p.name}}", fmt.Sprintf("%v", req.${this.capitalize(p.name)}))`
|
|
7128
|
+
);
|
|
7129
|
+
}
|
|
7130
|
+
if (ep.queryParams.length > 0) {
|
|
7131
|
+
emitter.line(`u, err := url.Parse(reqURL)`);
|
|
7132
|
+
emitter.line(`if err != nil { return nil, err }`);
|
|
7133
|
+
emitter.line(`q := u.Query()`);
|
|
7134
|
+
for (const q of ep.queryParams) {
|
|
7135
|
+
const capName = this.capitalize(q.name);
|
|
7136
|
+
emitter.line(
|
|
7137
|
+
`q.Set("${q.name}", fmt.Sprintf("%v", req.${capName}))`
|
|
7138
|
+
);
|
|
7139
|
+
}
|
|
7140
|
+
emitter.line(`u.RawQuery = q.Encode()`);
|
|
7141
|
+
emitter.line(`reqURL = u.String()`);
|
|
7142
|
+
}
|
|
7143
|
+
if (ep.requestBody) {
|
|
7144
|
+
emitter.line(`bodyBytes, err := json.Marshal(req.Body)`);
|
|
7145
|
+
emitter.line(`if err != nil { return nil, err }`);
|
|
7146
|
+
emitter.line(
|
|
7147
|
+
`httpReq, err := http.NewRequestWithContext(ctx, "${method}", reqURL, bytes.NewReader(bodyBytes))`
|
|
7148
|
+
);
|
|
7149
|
+
} else {
|
|
7150
|
+
emitter.line(
|
|
7151
|
+
`httpReq, err := http.NewRequestWithContext(ctx, "${method}", reqURL, nil)`
|
|
7152
|
+
);
|
|
7153
|
+
}
|
|
6570
7154
|
emitter.line(`if err != nil { return nil, err }`);
|
|
6571
|
-
emitter.line(
|
|
6572
|
-
|
|
6573
|
-
|
|
6574
|
-
|
|
7155
|
+
emitter.line();
|
|
7156
|
+
emitter.line(`if c.Token != "" {`);
|
|
7157
|
+
emitter.line(
|
|
7158
|
+
` httpReq.Header.Set("Authorization", "Bearer "+c.Token)`
|
|
7159
|
+
);
|
|
7160
|
+
emitter.line(`}`);
|
|
7161
|
+
if (ep.requestBody) {
|
|
7162
|
+
emitter.line(
|
|
7163
|
+
`httpReq.Header.Set("Content-Type", "application/json")`
|
|
7164
|
+
);
|
|
6575
7165
|
}
|
|
6576
|
-
emitter.line(
|
|
6577
|
-
emitter.line(`
|
|
6578
|
-
}
|
|
6579
|
-
if (ep.requestBody) {
|
|
6580
|
-
emitter.line(`bodyBytes, err := json.Marshal(req.Body)`);
|
|
7166
|
+
emitter.line();
|
|
7167
|
+
emitter.line(`resp, err := c.HTTPClient.Do(httpReq)`);
|
|
6581
7168
|
emitter.line(`if err != nil { return nil, err }`);
|
|
6582
|
-
emitter.line(`
|
|
6583
|
-
|
|
6584
|
-
emitter.line(`
|
|
6585
|
-
|
|
6586
|
-
|
|
6587
|
-
|
|
6588
|
-
emitter.line(`if c.Token != "" {`);
|
|
6589
|
-
emitter.line(` httpReq.Header.Set("Authorization", "Bearer "+c.Token)`);
|
|
6590
|
-
emitter.line(`}`);
|
|
6591
|
-
if (ep.requestBody) {
|
|
6592
|
-
emitter.line(`httpReq.Header.Set("Content-Type", "application/json")`);
|
|
6593
|
-
}
|
|
6594
|
-
emitter.line();
|
|
6595
|
-
emitter.line(`resp, err := c.HTTPClient.Do(httpReq)`);
|
|
6596
|
-
emitter.line(`if err != nil { return nil, err }`);
|
|
6597
|
-
emitter.line(`defer resp.Body.Close()`);
|
|
6598
|
-
emitter.line();
|
|
6599
|
-
emitter.line(`if resp.StatusCode >= 400 {`);
|
|
6600
|
-
emitter.line(` return nil, fmt.Errorf("API Error: %d", resp.StatusCode)`);
|
|
6601
|
-
emitter.line(`}`);
|
|
6602
|
-
emitter.line();
|
|
6603
|
-
if (retType !== "interface{}") {
|
|
6604
|
-
emitter.line(`var res ${retType}`);
|
|
6605
|
-
emitter.line(`if err := json.NewDecoder(resp.Body).Decode(&res); err != nil {`);
|
|
6606
|
-
emitter.line(` return nil, err`);
|
|
7169
|
+
emitter.line(`defer resp.Body.Close()`);
|
|
7170
|
+
emitter.line();
|
|
7171
|
+
emitter.line(`if resp.StatusCode >= 400 {`);
|
|
7172
|
+
emitter.line(
|
|
7173
|
+
` return nil, fmt.Errorf("API Error: %d", resp.StatusCode)`
|
|
7174
|
+
);
|
|
6607
7175
|
emitter.line(`}`);
|
|
6608
|
-
emitter.line(
|
|
6609
|
-
|
|
6610
|
-
|
|
7176
|
+
emitter.line();
|
|
7177
|
+
if (retType !== "interface{}") {
|
|
7178
|
+
emitter.line(`var res ${retType}`);
|
|
7179
|
+
emitter.line(
|
|
7180
|
+
`if err := json.NewDecoder(resp.Body).Decode(&res); err != nil {`
|
|
7181
|
+
);
|
|
7182
|
+
emitter.line(` return nil, err`);
|
|
7183
|
+
emitter.line(`}`);
|
|
7184
|
+
emitter.line(`return &res, nil`);
|
|
7185
|
+
} else {
|
|
7186
|
+
emitter.line(`return nil, nil`);
|
|
7187
|
+
}
|
|
6611
7188
|
}
|
|
6612
|
-
|
|
7189
|
+
);
|
|
6613
7190
|
}
|
|
6614
7191
|
buildResponseType(ep) {
|
|
6615
7192
|
const success = ep.successResponse;
|
|
@@ -6622,7 +7199,8 @@ var GoClientEmitter = class {
|
|
|
6622
7199
|
renderTypeRef(ref) {
|
|
6623
7200
|
let t = "interface{}";
|
|
6624
7201
|
if (ref.ref) t = ref.ref;
|
|
6625
|
-
else if (ref.inline && ref.inline.kind === "scalar")
|
|
7202
|
+
else if (ref.inline && ref.inline.kind === "scalar")
|
|
7203
|
+
t = ref.inline.scalar === "number" ? "float64" : "string";
|
|
6626
7204
|
if (ref.isArray) t = `[]${t}`;
|
|
6627
7205
|
if (ref.nullable) t = `*${t}`;
|
|
6628
7206
|
return t;
|
|
@@ -6671,16 +7249,20 @@ var TsTypeEmitter = class {
|
|
|
6671
7249
|
return emitter.toString();
|
|
6672
7250
|
}
|
|
6673
7251
|
emitType(emitter, type) {
|
|
6674
|
-
if (type.description)
|
|
7252
|
+
if (type.description)
|
|
7253
|
+
this.emitDoc(emitter, type.description, type.deprecated);
|
|
6675
7254
|
switch (type.kind) {
|
|
6676
7255
|
case "object":
|
|
6677
7256
|
emitter.block(`export interface ${type.id} {`, `}`, () => {
|
|
6678
7257
|
const formatProp = (name) => /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name) ? name : `'${name}'`;
|
|
6679
7258
|
for (const field of type.fields) {
|
|
6680
|
-
if (field.description)
|
|
7259
|
+
if (field.description)
|
|
7260
|
+
this.emitDoc(emitter, field.description, field.deprecated);
|
|
6681
7261
|
const q = field.required ? "" : "?";
|
|
6682
7262
|
const ro = field.readOnly ? "readonly " : "";
|
|
6683
|
-
emitter.line(
|
|
7263
|
+
emitter.line(
|
|
7264
|
+
`${ro}${formatProp(field.name)}${q}: ${this.renderTypeRef(field.type)};`
|
|
7265
|
+
);
|
|
6684
7266
|
}
|
|
6685
7267
|
if (type.additionalProperties) {
|
|
6686
7268
|
const valType = typeof type.additionalProperties === "boolean" ? "any" : this.renderTypeRef(type.additionalProperties);
|
|
@@ -6693,7 +7275,8 @@ var TsTypeEmitter = class {
|
|
|
6693
7275
|
emitter.block(`export enum ${type.id} {`, `}`, () => {
|
|
6694
7276
|
const formatProp = (name) => /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name) ? name : `'${name}'`;
|
|
6695
7277
|
for (const v of type.values) {
|
|
6696
|
-
if (v.description)
|
|
7278
|
+
if (v.description)
|
|
7279
|
+
this.emitDoc(emitter, v.description, v.deprecated);
|
|
6697
7280
|
emitter.line(`${formatProp(v.name)} = ${v.value},`);
|
|
6698
7281
|
}
|
|
6699
7282
|
});
|
|
@@ -6701,29 +7284,42 @@ var TsTypeEmitter = class {
|
|
|
6701
7284
|
emitter.block(`export enum ${type.id} {`, `}`, () => {
|
|
6702
7285
|
const formatProp = (name) => /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name) ? name : `'${name}'`;
|
|
6703
7286
|
for (const v of type.values) {
|
|
6704
|
-
if (v.description)
|
|
7287
|
+
if (v.description)
|
|
7288
|
+
this.emitDoc(emitter, v.description, v.deprecated);
|
|
6705
7289
|
emitter.line(`${formatProp(v.name)} = "${v.value}",`);
|
|
6706
7290
|
}
|
|
6707
7291
|
});
|
|
6708
7292
|
}
|
|
6709
7293
|
break;
|
|
6710
7294
|
case "union":
|
|
6711
|
-
emitter.line(
|
|
7295
|
+
emitter.line(
|
|
7296
|
+
`export type ${type.id} = ${type.members.map((m) => this.renderTypeRef(m)).join(" | ")};`
|
|
7297
|
+
);
|
|
6712
7298
|
break;
|
|
6713
7299
|
case "intersection":
|
|
6714
|
-
emitter.line(
|
|
7300
|
+
emitter.line(
|
|
7301
|
+
`export type ${type.id} = ${type.members.map((m) => this.renderTypeRef(m)).join(" & ")};`
|
|
7302
|
+
);
|
|
6715
7303
|
break;
|
|
6716
7304
|
case "array":
|
|
6717
|
-
emitter.line(
|
|
7305
|
+
emitter.line(
|
|
7306
|
+
`export type ${type.id} = ${this.renderTypeRef(type.items)}[];`
|
|
7307
|
+
);
|
|
6718
7308
|
break;
|
|
6719
7309
|
case "scalar":
|
|
6720
|
-
emitter.line(
|
|
7310
|
+
emitter.line(
|
|
7311
|
+
`export type ${type.id} = ${this.renderScalar(type.scalar)};`
|
|
7312
|
+
);
|
|
6721
7313
|
break;
|
|
6722
7314
|
case "map":
|
|
6723
|
-
emitter.line(
|
|
7315
|
+
emitter.line(
|
|
7316
|
+
`export type ${type.id} = Record<string, ${this.renderTypeRef(type.valueType)}>;`
|
|
7317
|
+
);
|
|
6724
7318
|
break;
|
|
6725
7319
|
case "tuple":
|
|
6726
|
-
emitter.line(
|
|
7320
|
+
emitter.line(
|
|
7321
|
+
`export type ${type.id} = [${type.elements.map((e) => this.renderTypeRef(e)).join(", ")}];`
|
|
7322
|
+
);
|
|
6727
7323
|
break;
|
|
6728
7324
|
case "literal":
|
|
6729
7325
|
const val = typeof type.value === "string" ? `"${type.value}"` : String(type.value);
|
|
@@ -6735,8 +7331,10 @@ var TsTypeEmitter = class {
|
|
|
6735
7331
|
let t = "any";
|
|
6736
7332
|
if (ref.ref) t = ref.ref;
|
|
6737
7333
|
else if (ref.inline) {
|
|
6738
|
-
if (ref.inline.kind === "scalar")
|
|
6739
|
-
|
|
7334
|
+
if (ref.inline.kind === "scalar")
|
|
7335
|
+
t = this.renderScalar(ref.inline.scalar);
|
|
7336
|
+
else if (ref.inline.kind === "array")
|
|
7337
|
+
t = `${this.renderTypeRef(ref.inline.items)}[]`;
|
|
6740
7338
|
}
|
|
6741
7339
|
if (ref.isArray) t = `${t}[]`;
|
|
6742
7340
|
if (ref.nullable) t = `${t} | null`;
|
|
@@ -6797,7 +7395,9 @@ var JsClientEmitter = class {
|
|
|
6797
7395
|
emitter.line(" */");
|
|
6798
7396
|
emitter.block(`class ${this.className} extends BaseClient {`, `}`, () => {
|
|
6799
7397
|
emitter.line("/**");
|
|
6800
|
-
emitter.line(
|
|
7398
|
+
emitter.line(
|
|
7399
|
+
' * @param {import("@axiomify/sdk-runtime").ClientConfig} config'
|
|
7400
|
+
);
|
|
6801
7401
|
emitter.line(" */");
|
|
6802
7402
|
emitter.block(`constructor(config) {`, `}`, () => {
|
|
6803
7403
|
emitter.line(`super(config);`);
|
|
@@ -6831,7 +7431,7 @@ var JsClientEmitter = class {
|
|
|
6831
7431
|
emitter.block(methodSignature, `}`, () => {
|
|
6832
7432
|
const method = ep.method?.toUpperCase() || "GET";
|
|
6833
7433
|
const pathTemplate = ep.path || "/";
|
|
6834
|
-
|
|
7434
|
+
const pathExpr = `\`${pathTemplate.replace(/\{([^}]+)\}/g, "${request.$1}")}\``;
|
|
6835
7435
|
let reqOpts = `method: '${method}', path: ${pathExpr}`;
|
|
6836
7436
|
const isValidJSIdentifier = (name) => /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
|
|
6837
7437
|
if (ep.queryParams.length > 0) {
|
|
@@ -6852,11 +7452,22 @@ var JsClientEmitter = class {
|
|
|
6852
7452
|
buildRequestType(ep) {
|
|
6853
7453
|
const props = [];
|
|
6854
7454
|
const formatProp = (name) => /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name) ? name : `'${name}'`;
|
|
6855
|
-
for (const p of ep.pathParams)
|
|
6856
|
-
|
|
6857
|
-
|
|
7455
|
+
for (const p of ep.pathParams)
|
|
7456
|
+
props.push(
|
|
7457
|
+
`${formatProp(p.name)}${p.required ? "" : "?"}: ${this.renderTypeRef(p.type)}`
|
|
7458
|
+
);
|
|
7459
|
+
for (const p of ep.queryParams)
|
|
7460
|
+
props.push(
|
|
7461
|
+
`${formatProp(p.name)}${p.required ? "" : "?"}: ${this.renderTypeRef(p.type)}`
|
|
7462
|
+
);
|
|
7463
|
+
for (const p of ep.headerParams)
|
|
7464
|
+
props.push(
|
|
7465
|
+
`${formatProp(p.name)}${p.required ? "" : "?"}: ${this.renderTypeRef(p.type)}`
|
|
7466
|
+
);
|
|
6858
7467
|
if (ep.requestBody) {
|
|
6859
|
-
props.push(
|
|
7468
|
+
props.push(
|
|
7469
|
+
`body${ep.requestBody.required ? "" : "?"}: ${this.renderTypeRef(ep.requestBody.type)}`
|
|
7470
|
+
);
|
|
6860
7471
|
}
|
|
6861
7472
|
if (props.length === 0) return null;
|
|
6862
7473
|
return `{ ${props.join(", ")} }`;
|
|
@@ -6874,7 +7485,8 @@ var JsClientEmitter = class {
|
|
|
6874
7485
|
if (ref.ref) t = `import("./types").${ref.ref}`;
|
|
6875
7486
|
else if (ref.inline) {
|
|
6876
7487
|
if (ref.inline.kind === "scalar") {
|
|
6877
|
-
if (ref.inline.scalar === "integer" || ref.inline.scalar === "number")
|
|
7488
|
+
if (ref.inline.scalar === "integer" || ref.inline.scalar === "number")
|
|
7489
|
+
t = "number";
|
|
6878
7490
|
else if (ref.inline.scalar === "boolean") t = "boolean";
|
|
6879
7491
|
else t = "string";
|
|
6880
7492
|
} else if (ref.inline.kind === "array") {
|
|
@@ -6895,19 +7507,32 @@ var JavaScriptGenerator = class extends Generator {
|
|
|
6895
7507
|
this.addFile("types.d.ts", typeEmitter.emitAll());
|
|
6896
7508
|
const clientEmitter = new JsClientEmitter(this.schema, "ApiClient");
|
|
6897
7509
|
this.addFile("client.js", clientEmitter.emitAll());
|
|
6898
|
-
this.addFile(
|
|
7510
|
+
this.addFile(
|
|
7511
|
+
"index.js",
|
|
7512
|
+
`const { ApiClient } = require('./client');
|
|
6899
7513
|
module.exports = { ApiClient };
|
|
6900
|
-
`
|
|
6901
|
-
|
|
7514
|
+
`
|
|
7515
|
+
);
|
|
7516
|
+
this.addFile(
|
|
7517
|
+
"index.d.ts",
|
|
7518
|
+
`export * from './types';
|
|
6902
7519
|
export { ApiClient } from './client';
|
|
6903
|
-
`
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
|
|
6908
|
-
|
|
6909
|
-
|
|
6910
|
-
|
|
7520
|
+
`
|
|
7521
|
+
);
|
|
7522
|
+
this.addFile(
|
|
7523
|
+
"package.json",
|
|
7524
|
+
JSON.stringify(
|
|
7525
|
+
{
|
|
7526
|
+
name: this.options.packageName,
|
|
7527
|
+
version: this.options.version || "1.0.0",
|
|
7528
|
+
main: "index.js",
|
|
7529
|
+
types: "index.d.ts",
|
|
7530
|
+
dependencies: {}
|
|
7531
|
+
},
|
|
7532
|
+
null,
|
|
7533
|
+
2
|
|
7534
|
+
)
|
|
7535
|
+
);
|
|
6911
7536
|
return this.files;
|
|
6912
7537
|
}
|
|
6913
7538
|
};
|
|
@@ -6956,7 +7581,9 @@ var KotlinTypeEmitter = class {
|
|
|
6956
7581
|
const ktType = this.renderTypeRef(field.type);
|
|
6957
7582
|
const opt = field.required ? "" : "? = null";
|
|
6958
7583
|
const comma = i < type.fields.length - 1 ? "," : "";
|
|
6959
|
-
emitter.line(
|
|
7584
|
+
emitter.line(
|
|
7585
|
+
`@SerialName("${field.name}") val ${this.toCamelCase(field.name)}: ${ktType}${opt}${comma}`
|
|
7586
|
+
);
|
|
6960
7587
|
}
|
|
6961
7588
|
});
|
|
6962
7589
|
break;
|
|
@@ -6964,7 +7591,9 @@ var KotlinTypeEmitter = class {
|
|
|
6964
7591
|
emitter.line(`@Serializable`);
|
|
6965
7592
|
emitter.block(`enum class ${type.id} {`, `}`, () => {
|
|
6966
7593
|
for (const v of type.values) {
|
|
6967
|
-
emitter.line(
|
|
7594
|
+
emitter.line(
|
|
7595
|
+
`@SerialName("${v.value}") ${this.toUpperSnakeCase(v.name)},`
|
|
7596
|
+
);
|
|
6968
7597
|
}
|
|
6969
7598
|
});
|
|
6970
7599
|
break;
|
|
@@ -6976,27 +7605,41 @@ var KotlinTypeEmitter = class {
|
|
|
6976
7605
|
const name = member.ref ? member.ref : `Value${i}`;
|
|
6977
7606
|
const memberType = this.renderTypeRef(member);
|
|
6978
7607
|
emitter.line(`@Serializable`);
|
|
6979
|
-
emitter.line(
|
|
7608
|
+
emitter.line(
|
|
7609
|
+
`data class ${name}(val value: ${memberType}): ${type.id}`
|
|
7610
|
+
);
|
|
6980
7611
|
}
|
|
6981
7612
|
});
|
|
6982
7613
|
break;
|
|
6983
7614
|
case "intersection":
|
|
6984
|
-
emitter.line(
|
|
7615
|
+
emitter.line(
|
|
7616
|
+
`typealias ${type.id} = Map<String, kotlinx.serialization.json.JsonElement>`
|
|
7617
|
+
);
|
|
6985
7618
|
break;
|
|
6986
7619
|
case "array":
|
|
6987
|
-
emitter.line(
|
|
7620
|
+
emitter.line(
|
|
7621
|
+
`typealias ${type.id} = List<${this.renderTypeRef(type.items)}>`
|
|
7622
|
+
);
|
|
6988
7623
|
break;
|
|
6989
7624
|
case "scalar":
|
|
6990
|
-
emitter.line(
|
|
7625
|
+
emitter.line(
|
|
7626
|
+
`typealias ${type.id} = ${this.renderScalar(type.scalar)}`
|
|
7627
|
+
);
|
|
6991
7628
|
break;
|
|
6992
7629
|
case "map":
|
|
6993
|
-
emitter.line(
|
|
7630
|
+
emitter.line(
|
|
7631
|
+
`typealias ${type.id} = Map<String, ${this.renderTypeRef(type.valueType)}>`
|
|
7632
|
+
);
|
|
6994
7633
|
break;
|
|
6995
7634
|
case "tuple":
|
|
6996
|
-
emitter.line(
|
|
7635
|
+
emitter.line(
|
|
7636
|
+
`typealias ${type.id} = List<kotlinx.serialization.json.JsonElement>`
|
|
7637
|
+
);
|
|
6997
7638
|
break;
|
|
6998
7639
|
case "literal":
|
|
6999
|
-
emitter.line(
|
|
7640
|
+
emitter.line(
|
|
7641
|
+
`typealias ${type.id} = kotlinx.serialization.json.JsonPrimitive`
|
|
7642
|
+
);
|
|
7000
7643
|
break;
|
|
7001
7644
|
}
|
|
7002
7645
|
}
|
|
@@ -7004,8 +7647,10 @@ var KotlinTypeEmitter = class {
|
|
|
7004
7647
|
let t = "Any";
|
|
7005
7648
|
if (ref.ref) t = ref.ref;
|
|
7006
7649
|
else if (ref.inline) {
|
|
7007
|
-
if (ref.inline.kind === "scalar")
|
|
7008
|
-
|
|
7650
|
+
if (ref.inline.kind === "scalar")
|
|
7651
|
+
t = this.renderScalar(ref.inline.scalar);
|
|
7652
|
+
else if (ref.inline.kind === "array")
|
|
7653
|
+
t = `List<${this.renderTypeRef(ref.inline.items)}>`;
|
|
7009
7654
|
}
|
|
7010
7655
|
if (ref.isArray) t = `List<${t}>`;
|
|
7011
7656
|
return t;
|
|
@@ -7062,7 +7707,9 @@ var KotlinClientEmitter = class {
|
|
|
7062
7707
|
emitter.line();
|
|
7063
7708
|
emitter.line(`import okhttp3.OkHttpClient`);
|
|
7064
7709
|
emitter.line(`import retrofit2.Retrofit`);
|
|
7065
|
-
emitter.line(
|
|
7710
|
+
emitter.line(
|
|
7711
|
+
`import retrofit2.converter.kotlinx.serialization.asConverterFactory`
|
|
7712
|
+
);
|
|
7066
7713
|
emitter.line(`import retrofit2.http.*`);
|
|
7067
7714
|
emitter.line(`import kotlinx.serialization.json.Json`);
|
|
7068
7715
|
emitter.line(`import okhttp3.MediaType.Companion.toMediaType`);
|
|
@@ -7075,26 +7722,42 @@ var KotlinClientEmitter = class {
|
|
|
7075
7722
|
}
|
|
7076
7723
|
});
|
|
7077
7724
|
emitter.line();
|
|
7078
|
-
emitter.block(
|
|
7079
|
-
|
|
7080
|
-
|
|
7081
|
-
|
|
7082
|
-
|
|
7083
|
-
|
|
7084
|
-
|
|
7085
|
-
|
|
7086
|
-
|
|
7087
|
-
|
|
7088
|
-
|
|
7089
|
-
|
|
7090
|
-
|
|
7091
|
-
|
|
7092
|
-
|
|
7093
|
-
|
|
7094
|
-
|
|
7095
|
-
|
|
7096
|
-
|
|
7097
|
-
|
|
7725
|
+
emitter.block(
|
|
7726
|
+
`class ${this.className}(private val baseUrl: String, private val token: String? = null) {`,
|
|
7727
|
+
`}`,
|
|
7728
|
+
() => {
|
|
7729
|
+
emitter.block(
|
|
7730
|
+
`private val client = OkHttpClient.Builder().apply {`,
|
|
7731
|
+
`}.build()`,
|
|
7732
|
+
() => {
|
|
7733
|
+
emitter.block(`if (token != null) {`, `}`, () => {
|
|
7734
|
+
emitter.block(`addInterceptor { chain ->`, `}`, () => {
|
|
7735
|
+
emitter.line(`val request = chain.request().newBuilder()`);
|
|
7736
|
+
emitter.line(` .header("Authorization", "Bearer $token")`);
|
|
7737
|
+
emitter.line(` .build()`);
|
|
7738
|
+
emitter.line(`chain.proceed(request)`);
|
|
7739
|
+
});
|
|
7740
|
+
});
|
|
7741
|
+
}
|
|
7742
|
+
);
|
|
7743
|
+
emitter.line();
|
|
7744
|
+
emitter.block(
|
|
7745
|
+
`private val retrofit = Retrofit.Builder()`,
|
|
7746
|
+
`.build()`,
|
|
7747
|
+
() => {
|
|
7748
|
+
emitter.line(`.baseUrl(baseUrl)`);
|
|
7749
|
+
emitter.line(`.client(client)`);
|
|
7750
|
+
emitter.line(
|
|
7751
|
+
`.addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))`
|
|
7752
|
+
);
|
|
7753
|
+
}
|
|
7754
|
+
);
|
|
7755
|
+
emitter.line();
|
|
7756
|
+
emitter.line(
|
|
7757
|
+
`val api: ApiService = retrofit.create(ApiService::class.java)`
|
|
7758
|
+
);
|
|
7759
|
+
}
|
|
7760
|
+
);
|
|
7098
7761
|
return emitter.toString();
|
|
7099
7762
|
}
|
|
7100
7763
|
emitRetrofitMethod(emitter, ep) {
|
|
@@ -7103,13 +7766,17 @@ var KotlinClientEmitter = class {
|
|
|
7103
7766
|
const pathExpr = pathTemplate.replace(/\{([^}]+)\}/g, "{$1}");
|
|
7104
7767
|
emitter.line(`@${method}("${pathExpr}")`);
|
|
7105
7768
|
const methodName = this.toCamelCase(ep.operationId);
|
|
7106
|
-
|
|
7769
|
+
const args = [];
|
|
7107
7770
|
for (const p of ep.pathParams) {
|
|
7108
|
-
args.push(
|
|
7771
|
+
args.push(
|
|
7772
|
+
`@Path("${p.name}") ${this.toCamelCase(p.name)}: ${this.renderTypeRef(p.type)}`
|
|
7773
|
+
);
|
|
7109
7774
|
}
|
|
7110
7775
|
for (const p of ep.queryParams) {
|
|
7111
7776
|
const defaultValue = p.required ? "" : "? = null";
|
|
7112
|
-
args.push(
|
|
7777
|
+
args.push(
|
|
7778
|
+
`@Query("${p.name}") ${this.toCamelCase(p.name)}: ${this.renderTypeRef(p.type)}${defaultValue}`
|
|
7779
|
+
);
|
|
7113
7780
|
}
|
|
7114
7781
|
if (ep.requestBody) {
|
|
7115
7782
|
args.push(`@Body body: ${this.renderTypeRef(ep.requestBody.type)}`);
|
|
@@ -7149,9 +7816,15 @@ var KotlinGenerator = class extends Generator {
|
|
|
7149
7816
|
const pkgName = this.options.packageName.replace(/[^a-zA-Z0-9_.]/g, "").toLowerCase() || "com.axiomify.sdk";
|
|
7150
7817
|
const typeEmitter = new KotlinTypeEmitter(this.schema, graph, pkgName);
|
|
7151
7818
|
this.addFile("src/main/kotlin/Types.kt", typeEmitter.emitAll());
|
|
7152
|
-
const clientEmitter = new KotlinClientEmitter(
|
|
7819
|
+
const clientEmitter = new KotlinClientEmitter(
|
|
7820
|
+
this.schema,
|
|
7821
|
+
pkgName,
|
|
7822
|
+
"ApiClient"
|
|
7823
|
+
);
|
|
7153
7824
|
this.addFile("src/main/kotlin/Client.kt", clientEmitter.emitAll());
|
|
7154
|
-
this.addFile(
|
|
7825
|
+
this.addFile(
|
|
7826
|
+
"build.gradle.kts",
|
|
7827
|
+
`plugins {
|
|
7155
7828
|
kotlin("jvm") version "1.9.0"
|
|
7156
7829
|
kotlin("plugin.serialization") version "1.9.0"
|
|
7157
7830
|
}
|
|
@@ -7167,7 +7840,8 @@ dependencies {
|
|
|
7167
7840
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0")
|
|
7168
7841
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
|
|
7169
7842
|
}
|
|
7170
|
-
`
|
|
7843
|
+
`
|
|
7844
|
+
);
|
|
7171
7845
|
return this.files;
|
|
7172
7846
|
}
|
|
7173
7847
|
};
|
|
@@ -7203,7 +7877,9 @@ var PythonTypeEmitter = class {
|
|
|
7203
7877
|
case "object":
|
|
7204
7878
|
emitter.block(`class ${type.id}(BaseModel):`, ``, () => {
|
|
7205
7879
|
if (type.description) this.emitDoc(emitter, type.description);
|
|
7206
|
-
emitter.line(
|
|
7880
|
+
emitter.line(
|
|
7881
|
+
`model_config = ConfigDict(populate_by_name=True, protected_namespaces=())`
|
|
7882
|
+
);
|
|
7207
7883
|
emitter.line();
|
|
7208
7884
|
if (type.fields.length === 0) {
|
|
7209
7885
|
emitter.line("pass");
|
|
@@ -7214,9 +7890,13 @@ var PythonTypeEmitter = class {
|
|
|
7214
7890
|
const alias = field.name !== this.toSnakeCase(field.name) ? `, alias="${field.name}"` : "";
|
|
7215
7891
|
const desc = field.description ? `, description="${field.description.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"` : "";
|
|
7216
7892
|
if (field.required) {
|
|
7217
|
-
emitter.line(
|
|
7893
|
+
emitter.line(
|
|
7894
|
+
`${this.toSnakeCase(field.name)}: ${pyType} = Field(...${alias}${desc})`
|
|
7895
|
+
);
|
|
7218
7896
|
} else {
|
|
7219
|
-
emitter.line(
|
|
7897
|
+
emitter.line(
|
|
7898
|
+
`${this.toSnakeCase(field.name)}: Optional[${pyType}] = Field(default=None${alias}${desc})`
|
|
7899
|
+
);
|
|
7220
7900
|
}
|
|
7221
7901
|
}
|
|
7222
7902
|
});
|
|
@@ -7232,7 +7912,9 @@ var PythonTypeEmitter = class {
|
|
|
7232
7912
|
});
|
|
7233
7913
|
break;
|
|
7234
7914
|
case "union":
|
|
7235
|
-
emitter.line(
|
|
7915
|
+
emitter.line(
|
|
7916
|
+
`${type.id} = Union[${type.members.map((m) => this.renderTypeRef(m)).join(", ")}]`
|
|
7917
|
+
);
|
|
7236
7918
|
break;
|
|
7237
7919
|
case "intersection":
|
|
7238
7920
|
emitter.line(`${type.id} = Any`);
|
|
@@ -7244,10 +7926,14 @@ var PythonTypeEmitter = class {
|
|
|
7244
7926
|
emitter.line(`${type.id} = ${this.renderScalar(type.scalar)}`);
|
|
7245
7927
|
break;
|
|
7246
7928
|
case "map":
|
|
7247
|
-
emitter.line(
|
|
7929
|
+
emitter.line(
|
|
7930
|
+
`${type.id} = Dict[str, ${this.renderTypeRef(type.valueType)}]`
|
|
7931
|
+
);
|
|
7248
7932
|
break;
|
|
7249
7933
|
case "tuple":
|
|
7250
|
-
emitter.line(
|
|
7934
|
+
emitter.line(
|
|
7935
|
+
`${type.id} = tuple[${type.elements.map((e) => this.renderTypeRef(e)).join(", ")}]`
|
|
7936
|
+
);
|
|
7251
7937
|
break;
|
|
7252
7938
|
case "literal":
|
|
7253
7939
|
const literalVal = typeof type.value === "string" ? `"${type.value}"` : type.value;
|
|
@@ -7259,8 +7945,10 @@ var PythonTypeEmitter = class {
|
|
|
7259
7945
|
let t = "Any";
|
|
7260
7946
|
if (ref.ref) t = `"${ref.ref}"`;
|
|
7261
7947
|
else if (ref.inline) {
|
|
7262
|
-
if (ref.inline.kind === "scalar")
|
|
7263
|
-
|
|
7948
|
+
if (ref.inline.kind === "scalar")
|
|
7949
|
+
t = this.renderScalar(ref.inline.scalar);
|
|
7950
|
+
else if (ref.inline.kind === "array")
|
|
7951
|
+
t = `List[${this.renderTypeRef(ref.inline.items)}]`;
|
|
7264
7952
|
}
|
|
7265
7953
|
if (ref.isArray) t = `List[${t}]`;
|
|
7266
7954
|
if (ref.nullable) t = `Optional[${t}]`;
|
|
@@ -7311,11 +7999,19 @@ var PythonClientEmitter = class {
|
|
|
7311
7999
|
emitter.line(`from . import types`);
|
|
7312
8000
|
emitter.line();
|
|
7313
8001
|
emitter.block(`class ${this.className}:`, ``, () => {
|
|
7314
|
-
emitter.block(
|
|
7315
|
-
|
|
7316
|
-
|
|
7317
|
-
|
|
7318
|
-
|
|
8002
|
+
emitter.block(
|
|
8003
|
+
`def __init__(self, base_url: str, token: Optional[str] = None):`,
|
|
8004
|
+
``,
|
|
8005
|
+
() => {
|
|
8006
|
+
emitter.line(`self.base_url = base_url`);
|
|
8007
|
+
emitter.line(
|
|
8008
|
+
`self.headers = {"Authorization": f"Bearer {token}"} if token else {}`
|
|
8009
|
+
);
|
|
8010
|
+
emitter.line(
|
|
8011
|
+
`self.client = httpx.AsyncClient(base_url=self.base_url, headers=self.headers)`
|
|
8012
|
+
);
|
|
8013
|
+
}
|
|
8014
|
+
);
|
|
7319
8015
|
emitter.block(`async def close(self):`, ``, () => {
|
|
7320
8016
|
emitter.line(`await self.client.aclose()`);
|
|
7321
8017
|
});
|
|
@@ -7330,7 +8026,8 @@ var PythonClientEmitter = class {
|
|
|
7330
8026
|
emitMethod(emitter, ep) {
|
|
7331
8027
|
const methodName = this.toSnakeCase(ep.operationId);
|
|
7332
8028
|
let args = `self`;
|
|
7333
|
-
for (const p of ep.pathParams)
|
|
8029
|
+
for (const p of ep.pathParams)
|
|
8030
|
+
args += `, ${this.toSnakeCase(p.name)}: ${this.renderTypeRef(p.type)}`;
|
|
7334
8031
|
for (const p of ep.queryParams) {
|
|
7335
8032
|
const defaultValue = p.required ? "" : " = None";
|
|
7336
8033
|
args += `, ${this.toSnakeCase(p.name)}: Optional[${this.renderTypeRef(p.type)}]${defaultValue}`;
|
|
@@ -7339,47 +8036,58 @@ var PythonClientEmitter = class {
|
|
|
7339
8036
|
args += `, body: ${this.renderTypeRef(ep.requestBody.type)}`;
|
|
7340
8037
|
}
|
|
7341
8038
|
const returnType = this.buildResponseType(ep);
|
|
7342
|
-
emitter.block(
|
|
7343
|
-
|
|
7344
|
-
|
|
7345
|
-
|
|
7346
|
-
if (ep.
|
|
7347
|
-
|
|
7348
|
-
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
|
|
7353
|
-
|
|
7354
|
-
|
|
7355
|
-
|
|
7356
|
-
|
|
7357
|
-
|
|
7358
|
-
|
|
7359
|
-
|
|
7360
|
-
const snakeName = this.toSnakeCase(q.name);
|
|
7361
|
-
emitter.line(` "${q.name}": ${snakeName},`);
|
|
8039
|
+
emitter.block(
|
|
8040
|
+
`async def ${methodName}(${args}) -> ${returnType}:`,
|
|
8041
|
+
``,
|
|
8042
|
+
() => {
|
|
8043
|
+
if (ep.summary || ep.description) {
|
|
8044
|
+
emitter.line(`"""`);
|
|
8045
|
+
if (ep.summary) emitter.line(ep.summary);
|
|
8046
|
+
if (ep.description) emitter.line(ep.description);
|
|
8047
|
+
emitter.line(`"""`);
|
|
8048
|
+
}
|
|
8049
|
+
const method = ep.method?.toLowerCase() || "get";
|
|
8050
|
+
const pathTemplate = ep.path || "/";
|
|
8051
|
+
let pathExpr = pathTemplate;
|
|
8052
|
+
for (const p of ep.pathParams) {
|
|
8053
|
+
pathExpr = pathExpr.replace(
|
|
8054
|
+
`{${p.name}}`,
|
|
8055
|
+
`{${this.toSnakeCase(p.name)}}`
|
|
8056
|
+
);
|
|
7362
8057
|
}
|
|
7363
|
-
emitter.line(`}`);
|
|
7364
|
-
reqOpts
|
|
7365
|
-
|
|
7366
|
-
|
|
7367
|
-
|
|
7368
|
-
|
|
7369
|
-
|
|
7370
|
-
|
|
7371
|
-
|
|
7372
|
-
|
|
7373
|
-
|
|
7374
|
-
if (
|
|
7375
|
-
emitter.line(
|
|
8058
|
+
emitter.line(`url = f"${pathExpr}"`);
|
|
8059
|
+
let reqOpts = `url`;
|
|
8060
|
+
if (ep.queryParams.length > 0) {
|
|
8061
|
+
emitter.line(`params = {`);
|
|
8062
|
+
for (const q of ep.queryParams) {
|
|
8063
|
+
const snakeName = this.toSnakeCase(q.name);
|
|
8064
|
+
emitter.line(` "${q.name}": ${snakeName},`);
|
|
8065
|
+
}
|
|
8066
|
+
emitter.line(`}`);
|
|
8067
|
+
reqOpts += `, params={k: v for k, v in params.items() if v is not None}`;
|
|
8068
|
+
}
|
|
8069
|
+
if (ep.requestBody) {
|
|
8070
|
+
emitter.line(
|
|
8071
|
+
`req_body = body.model_dump(by_alias=True) if hasattr(body, 'model_dump') else body`
|
|
8072
|
+
);
|
|
8073
|
+
reqOpts += `, json=req_body`;
|
|
8074
|
+
}
|
|
8075
|
+
emitter.line(`response = await self.client.${method}(${reqOpts})`);
|
|
8076
|
+
emitter.line(`response.raise_for_status()`);
|
|
8077
|
+
if (returnType !== "None") {
|
|
8078
|
+
const rawType = ep.successResponse && ep.responses[ep.successResponse]?.type?.ref;
|
|
8079
|
+
if (rawType) {
|
|
8080
|
+
emitter.line(
|
|
8081
|
+
`return types.${rawType}.model_validate(response.json())`
|
|
8082
|
+
);
|
|
8083
|
+
} else {
|
|
8084
|
+
emitter.line(`return response.json()`);
|
|
8085
|
+
}
|
|
7376
8086
|
} else {
|
|
7377
|
-
emitter.line(`return
|
|
8087
|
+
emitter.line(`return None`);
|
|
7378
8088
|
}
|
|
7379
|
-
} else {
|
|
7380
|
-
emitter.line(`return None`);
|
|
7381
8089
|
}
|
|
7382
|
-
|
|
8090
|
+
);
|
|
7383
8091
|
}
|
|
7384
8092
|
buildResponseType(ep) {
|
|
7385
8093
|
const success = ep.successResponse;
|
|
@@ -7394,7 +8102,8 @@ var PythonClientEmitter = class {
|
|
|
7394
8102
|
if (ref.ref) t = `types.${ref.ref}`;
|
|
7395
8103
|
else if (ref.inline) {
|
|
7396
8104
|
if (ref.inline.kind === "scalar") {
|
|
7397
|
-
if (ref.inline.scalar === "integer" || ref.inline.scalar === "number")
|
|
8105
|
+
if (ref.inline.scalar === "integer" || ref.inline.scalar === "number")
|
|
8106
|
+
t = "float";
|
|
7398
8107
|
else if (ref.inline.scalar === "boolean") t = "bool";
|
|
7399
8108
|
else t = "str";
|
|
7400
8109
|
} else if (ref.inline.kind === "array") {
|
|
@@ -7418,10 +8127,15 @@ var PythonGenerator = class extends Generator {
|
|
|
7418
8127
|
this.addFile("types.py", typeEmitter.emitAll());
|
|
7419
8128
|
const clientEmitter = new PythonClientEmitter(this.schema, "ApiClient");
|
|
7420
8129
|
this.addFile("client.py", clientEmitter.emitAll());
|
|
7421
|
-
this.addFile(
|
|
8130
|
+
this.addFile(
|
|
8131
|
+
"__init__.py",
|
|
8132
|
+
`from .types import *
|
|
7422
8133
|
from .client import ApiClient
|
|
7423
|
-
`
|
|
7424
|
-
|
|
8134
|
+
`
|
|
8135
|
+
);
|
|
8136
|
+
this.addFile(
|
|
8137
|
+
"setup.py",
|
|
8138
|
+
`from setuptools import setup, find_packages
|
|
7425
8139
|
|
|
7426
8140
|
setup(
|
|
7427
8141
|
name="${this.options.packageName}",
|
|
@@ -7433,7 +8147,8 @@ setup(
|
|
|
7433
8147
|
],
|
|
7434
8148
|
python_requires=">=3.8",
|
|
7435
8149
|
)
|
|
7436
|
-
`
|
|
8150
|
+
`
|
|
8151
|
+
);
|
|
7437
8152
|
return this.files;
|
|
7438
8153
|
}
|
|
7439
8154
|
};
|
|
@@ -7472,14 +8187,20 @@ var SwiftTypeEmitter = class {
|
|
|
7472
8187
|
if (field.description) this.emitDoc(emitter, field.description);
|
|
7473
8188
|
const swiftType = this.renderTypeRef(field.type);
|
|
7474
8189
|
const opt = field.required ? "" : "?";
|
|
7475
|
-
emitter.line(
|
|
8190
|
+
emitter.line(
|
|
8191
|
+
`public var ${this.toCamelCase(field.name)}: ${swiftType}${opt}`
|
|
8192
|
+
);
|
|
7476
8193
|
}
|
|
7477
|
-
const needsCustomCodingKeys = type.fields.some(
|
|
8194
|
+
const needsCustomCodingKeys = type.fields.some(
|
|
8195
|
+
(f) => f.name !== this.toCamelCase(f.name)
|
|
8196
|
+
);
|
|
7478
8197
|
if (needsCustomCodingKeys && type.fields.length > 0) {
|
|
7479
8198
|
emitter.line();
|
|
7480
8199
|
emitter.block(`enum CodingKeys: String, CodingKey {`, `}`, () => {
|
|
7481
8200
|
for (const field of type.fields) {
|
|
7482
|
-
emitter.line(
|
|
8201
|
+
emitter.line(
|
|
8202
|
+
`case ${this.toCamelCase(field.name)} = "${field.name}"`
|
|
8203
|
+
);
|
|
7483
8204
|
}
|
|
7484
8205
|
});
|
|
7485
8206
|
}
|
|
@@ -7487,12 +8208,16 @@ var SwiftTypeEmitter = class {
|
|
|
7487
8208
|
break;
|
|
7488
8209
|
case "enum":
|
|
7489
8210
|
const rawType = type.valueType === "number" ? "Int" : "String";
|
|
7490
|
-
emitter.block(
|
|
7491
|
-
|
|
7492
|
-
|
|
7493
|
-
|
|
8211
|
+
emitter.block(
|
|
8212
|
+
`public enum ${type.id}: ${rawType}, Codable {`,
|
|
8213
|
+
`}`,
|
|
8214
|
+
() => {
|
|
8215
|
+
for (const v of type.values) {
|
|
8216
|
+
const val = typeof v.value === "string" ? `"${v.value}"` : v.value;
|
|
8217
|
+
emitter.line(`case ${this.toCamelCase(v.name)} = ${val}`);
|
|
8218
|
+
}
|
|
7494
8219
|
}
|
|
7495
|
-
|
|
8220
|
+
);
|
|
7496
8221
|
break;
|
|
7497
8222
|
case "union":
|
|
7498
8223
|
emitter.block(`public enum ${type.id}: Codable {`, `}`, () => {
|
|
@@ -7503,51 +8228,79 @@ var SwiftTypeEmitter = class {
|
|
|
7503
8228
|
emitter.line(`case ${this.toCamelCase(name)}(${memberType})`);
|
|
7504
8229
|
}
|
|
7505
8230
|
emitter.line();
|
|
7506
|
-
emitter.block(
|
|
7507
|
-
|
|
7508
|
-
|
|
7509
|
-
|
|
7510
|
-
|
|
7511
|
-
|
|
7512
|
-
|
|
7513
|
-
emitter.line(`self = .${this.toCamelCase(name)}(value)`);
|
|
7514
|
-
emitter.line(`return`);
|
|
7515
|
-
});
|
|
7516
|
-
}
|
|
7517
|
-
emitter.line(`throw DecodingError.typeMismatch(${type.id}.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "No matching union type"))`);
|
|
7518
|
-
});
|
|
7519
|
-
emitter.line();
|
|
7520
|
-
emitter.block(`public func encode(to encoder: Encoder) throws {`, `}`, () => {
|
|
7521
|
-
emitter.line(`var container = encoder.singleValueContainer()`);
|
|
7522
|
-
emitter.block(`switch self {`, `}`, () => {
|
|
8231
|
+
emitter.block(
|
|
8232
|
+
`public init(from decoder: Decoder) throws {`,
|
|
8233
|
+
`}`,
|
|
8234
|
+
() => {
|
|
8235
|
+
emitter.line(
|
|
8236
|
+
`let container = try decoder.singleValueContainer()`
|
|
8237
|
+
);
|
|
7523
8238
|
for (let i = 0; i < type.members.length; i++) {
|
|
7524
8239
|
const member = type.members[i];
|
|
7525
8240
|
const name = member.ref ? member.ref : `value${i}`;
|
|
7526
|
-
|
|
7527
|
-
|
|
7528
|
-
|
|
8241
|
+
const memberType = this.renderTypeRef(member);
|
|
8242
|
+
emitter.block(
|
|
8243
|
+
`if let value = try? container.decode(${memberType}.self) {`,
|
|
8244
|
+
`}`,
|
|
8245
|
+
() => {
|
|
8246
|
+
emitter.line(`self = .${this.toCamelCase(name)}(value)`);
|
|
8247
|
+
emitter.line(`return`);
|
|
8248
|
+
}
|
|
8249
|
+
);
|
|
7529
8250
|
}
|
|
7530
|
-
|
|
7531
|
-
|
|
8251
|
+
emitter.line(
|
|
8252
|
+
`throw DecodingError.typeMismatch(${type.id}.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "No matching union type"))`
|
|
8253
|
+
);
|
|
8254
|
+
}
|
|
8255
|
+
);
|
|
8256
|
+
emitter.line();
|
|
8257
|
+
emitter.block(
|
|
8258
|
+
`public func encode(to encoder: Encoder) throws {`,
|
|
8259
|
+
`}`,
|
|
8260
|
+
() => {
|
|
8261
|
+
emitter.line(`var container = encoder.singleValueContainer()`);
|
|
8262
|
+
emitter.block(`switch self {`, `}`, () => {
|
|
8263
|
+
for (let i = 0; i < type.members.length; i++) {
|
|
8264
|
+
const member = type.members[i];
|
|
8265
|
+
const name = member.ref ? member.ref : `value${i}`;
|
|
8266
|
+
emitter.block(
|
|
8267
|
+
`case .${this.toCamelCase(name)}(let value):`,
|
|
8268
|
+
``,
|
|
8269
|
+
() => {
|
|
8270
|
+
emitter.line(`try container.encode(value)`);
|
|
8271
|
+
}
|
|
8272
|
+
);
|
|
8273
|
+
}
|
|
8274
|
+
});
|
|
8275
|
+
}
|
|
8276
|
+
);
|
|
7532
8277
|
});
|
|
7533
8278
|
break;
|
|
7534
8279
|
case "intersection":
|
|
7535
8280
|
emitter.line(`public typealias ${type.id} = [String: AnyCodable]`);
|
|
7536
8281
|
break;
|
|
7537
8282
|
case "array":
|
|
7538
|
-
emitter.line(
|
|
8283
|
+
emitter.line(
|
|
8284
|
+
`public typealias ${type.id} = [${this.renderTypeRef(type.items)}]`
|
|
8285
|
+
);
|
|
7539
8286
|
break;
|
|
7540
8287
|
case "scalar":
|
|
7541
|
-
emitter.line(
|
|
8288
|
+
emitter.line(
|
|
8289
|
+
`public typealias ${type.id} = ${this.renderScalar(type.scalar)}`
|
|
8290
|
+
);
|
|
7542
8291
|
break;
|
|
7543
8292
|
case "map":
|
|
7544
|
-
emitter.line(
|
|
8293
|
+
emitter.line(
|
|
8294
|
+
`public typealias ${type.id} = [String: ${this.renderTypeRef(type.valueType)}]`
|
|
8295
|
+
);
|
|
7545
8296
|
break;
|
|
7546
8297
|
case "tuple":
|
|
7547
8298
|
emitter.line(`public typealias ${type.id} = [AnyCodable]`);
|
|
7548
8299
|
break;
|
|
7549
8300
|
case "literal":
|
|
7550
|
-
emitter.line(
|
|
8301
|
+
emitter.line(
|
|
8302
|
+
`public typealias ${type.id} = AnyCodable // Literal: ${type.value}`
|
|
8303
|
+
);
|
|
7551
8304
|
break;
|
|
7552
8305
|
}
|
|
7553
8306
|
}
|
|
@@ -7555,8 +8308,10 @@ var SwiftTypeEmitter = class {
|
|
|
7555
8308
|
let t = "AnyCodable";
|
|
7556
8309
|
if (ref.ref) t = ref.ref;
|
|
7557
8310
|
else if (ref.inline) {
|
|
7558
|
-
if (ref.inline.kind === "scalar")
|
|
7559
|
-
|
|
8311
|
+
if (ref.inline.kind === "scalar")
|
|
8312
|
+
t = this.renderScalar(ref.inline.scalar);
|
|
8313
|
+
else if (ref.inline.kind === "array")
|
|
8314
|
+
t = `[${this.renderTypeRef(ref.inline.items)}]`;
|
|
7560
8315
|
}
|
|
7561
8316
|
if (ref.isArray) t = `[${t}]`;
|
|
7562
8317
|
return t;
|
|
@@ -7595,22 +8350,48 @@ var SwiftTypeEmitter = class {
|
|
|
7595
8350
|
emitter.line(` public init(_ value: Any) { self.value = value }`);
|
|
7596
8351
|
emitter.line(` public init(from decoder: Decoder) throws {`);
|
|
7597
8352
|
emitter.line(` let container = try decoder.singleValueContainer()`);
|
|
7598
|
-
emitter.line(
|
|
7599
|
-
|
|
7600
|
-
|
|
7601
|
-
emitter.line(
|
|
7602
|
-
|
|
7603
|
-
|
|
7604
|
-
emitter.line(
|
|
8353
|
+
emitter.line(
|
|
8354
|
+
` if let x = try? container.decode(Bool.self) { self.value = x }`
|
|
8355
|
+
);
|
|
8356
|
+
emitter.line(
|
|
8357
|
+
` else if let x = try? container.decode(Int.self) { self.value = x }`
|
|
8358
|
+
);
|
|
8359
|
+
emitter.line(
|
|
8360
|
+
` else if let x = try? container.decode(Double.self) { self.value = x }`
|
|
8361
|
+
);
|
|
8362
|
+
emitter.line(
|
|
8363
|
+
` else if let x = try? container.decode(String.self) { self.value = x }`
|
|
8364
|
+
);
|
|
8365
|
+
emitter.line(
|
|
8366
|
+
` else if let x = try? container.decode([String: AnyCodable].self) { self.value = x.mapValues { $0.value } }`
|
|
8367
|
+
);
|
|
8368
|
+
emitter.line(
|
|
8369
|
+
` else if let x = try? container.decode([AnyCodable].self) { self.value = x.map { $0.value } }`
|
|
8370
|
+
);
|
|
8371
|
+
emitter.line(
|
|
8372
|
+
` else { throw DecodingError.typeMismatch(AnyCodable.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type")) }`
|
|
8373
|
+
);
|
|
7605
8374
|
emitter.line(` }`);
|
|
7606
8375
|
emitter.line(` public func encode(to encoder: Encoder) throws {`);
|
|
7607
8376
|
emitter.line(` var container = encoder.singleValueContainer()`);
|
|
7608
|
-
emitter.line(
|
|
7609
|
-
|
|
7610
|
-
|
|
7611
|
-
emitter.line(
|
|
7612
|
-
|
|
7613
|
-
|
|
8377
|
+
emitter.line(
|
|
8378
|
+
` if let x = value as? Bool { try container.encode(x) }`
|
|
8379
|
+
);
|
|
8380
|
+
emitter.line(
|
|
8381
|
+
` else if let x = value as? Int { try container.encode(x) }`
|
|
8382
|
+
);
|
|
8383
|
+
emitter.line(
|
|
8384
|
+
` else if let x = value as? Double { try container.encode(x) }`
|
|
8385
|
+
);
|
|
8386
|
+
emitter.line(
|
|
8387
|
+
` else if let x = value as? String { try container.encode(x) }`
|
|
8388
|
+
);
|
|
8389
|
+
emitter.line(
|
|
8390
|
+
` else if let x = value as? [String: Any] { try container.encode(x.mapValues { AnyCodable($0) }) }`
|
|
8391
|
+
);
|
|
8392
|
+
emitter.line(
|
|
8393
|
+
` else if let x = value as? [Any] { try container.encode(x.map { AnyCodable($0) }) }`
|
|
8394
|
+
);
|
|
7614
8395
|
emitter.line(` }`);
|
|
7615
8396
|
emitter.line(`}`);
|
|
7616
8397
|
}
|
|
@@ -7633,11 +8414,15 @@ var SwiftClientEmitter = class {
|
|
|
7633
8414
|
emitter.line(`public var token: String?`);
|
|
7634
8415
|
emitter.line(`private let session: URLSession`);
|
|
7635
8416
|
emitter.line();
|
|
7636
|
-
emitter.block(
|
|
7637
|
-
|
|
7638
|
-
|
|
7639
|
-
|
|
7640
|
-
|
|
8417
|
+
emitter.block(
|
|
8418
|
+
`public init(baseURL: URL, token: String? = nil, session: URLSession = .shared) {`,
|
|
8419
|
+
`}`,
|
|
8420
|
+
() => {
|
|
8421
|
+
emitter.line(`self.baseURL = baseURL`);
|
|
8422
|
+
emitter.line(`self.token = token`);
|
|
8423
|
+
emitter.line(`self.session = session`);
|
|
8424
|
+
}
|
|
8425
|
+
);
|
|
7641
8426
|
for (const ep of this.schema.endpoints) {
|
|
7642
8427
|
if (ep.transport !== "rest") continue;
|
|
7643
8428
|
emitter.line();
|
|
@@ -7648,52 +8433,79 @@ var SwiftClientEmitter = class {
|
|
|
7648
8433
|
}
|
|
7649
8434
|
emitMethod(emitter, ep) {
|
|
7650
8435
|
const methodName = this.toCamelCase(ep.operationId);
|
|
7651
|
-
|
|
8436
|
+
const args = [];
|
|
7652
8437
|
for (const p of ep.pathParams) {
|
|
7653
8438
|
args.push(`${this.toCamelCase(p.name)}: ${this.renderTypeRef(p.type)}`);
|
|
7654
8439
|
}
|
|
7655
8440
|
for (const p of ep.queryParams) {
|
|
7656
|
-
args.push(
|
|
8441
|
+
args.push(
|
|
8442
|
+
`${this.toCamelCase(p.name)}: ${this.renderTypeRef(p.type)}? = nil`
|
|
8443
|
+
);
|
|
7657
8444
|
}
|
|
7658
8445
|
if (ep.requestBody) {
|
|
7659
8446
|
args.push(`body: ${this.renderTypeRef(ep.requestBody.type)}`);
|
|
7660
8447
|
}
|
|
7661
8448
|
const retType = this.buildResponseType(ep);
|
|
7662
|
-
emitter.block(
|
|
7663
|
-
|
|
7664
|
-
|
|
7665
|
-
|
|
7666
|
-
|
|
7667
|
-
|
|
7668
|
-
|
|
7669
|
-
|
|
7670
|
-
|
|
7671
|
-
|
|
7672
|
-
|
|
7673
|
-
|
|
7674
|
-
|
|
7675
|
-
|
|
7676
|
-
})
|
|
8449
|
+
emitter.block(
|
|
8450
|
+
`public func ${methodName}(${args.join(", ")}) async throws -> ${retType} {`,
|
|
8451
|
+
`}`,
|
|
8452
|
+
() => {
|
|
8453
|
+
const method = ep.method?.toUpperCase() || "GET";
|
|
8454
|
+
const pathTemplate = ep.path || "/";
|
|
8455
|
+
let pathExpr = pathTemplate;
|
|
8456
|
+
for (const p of ep.pathParams) {
|
|
8457
|
+
pathExpr = pathExpr.replace(
|
|
8458
|
+
`{${p.name}}`,
|
|
8459
|
+
`\\(${this.toCamelCase(p.name)})`
|
|
8460
|
+
);
|
|
8461
|
+
}
|
|
8462
|
+
emitter.line(
|
|
8463
|
+
`var components = URLComponents(url: baseURL.appendingPathComponent("${pathExpr}"), resolvingAgainstBaseURL: true)!`
|
|
8464
|
+
);
|
|
8465
|
+
if (ep.queryParams.length > 0) {
|
|
8466
|
+
emitter.line(`var queryItems: [URLQueryItem] = []`);
|
|
8467
|
+
for (const q of ep.queryParams) {
|
|
8468
|
+
const camelName = this.toCamelCase(q.name);
|
|
8469
|
+
emitter.block(`if let val = ${camelName} {`, `}`, () => {
|
|
8470
|
+
emitter.line(
|
|
8471
|
+
`queryItems.append(URLQueryItem(name: "${q.name}", value: String(describing: val)))`
|
|
8472
|
+
);
|
|
8473
|
+
});
|
|
8474
|
+
}
|
|
8475
|
+
emitter.line(
|
|
8476
|
+
`components.queryItems = queryItems.isEmpty ? nil : queryItems`
|
|
8477
|
+
);
|
|
8478
|
+
}
|
|
8479
|
+
emitter.line(`var request = URLRequest(url: components.url!)`);
|
|
8480
|
+
emitter.line(`request.httpMethod = "${method}"`);
|
|
8481
|
+
emitter.block(`if let token = self.token {`, `}`, () => {
|
|
8482
|
+
emitter.line(
|
|
8483
|
+
`request.addValue("Bearer \\(token)", forHTTPHeaderField: "Authorization")`
|
|
8484
|
+
);
|
|
8485
|
+
});
|
|
8486
|
+
if (ep.requestBody) {
|
|
8487
|
+
emitter.line(
|
|
8488
|
+
`request.addValue("application/json", forHTTPHeaderField: "Content-Type")`
|
|
8489
|
+
);
|
|
8490
|
+
emitter.line(`request.httpBody = try JSONEncoder().encode(body)`);
|
|
8491
|
+
}
|
|
8492
|
+
emitter.line(
|
|
8493
|
+
`let (data, response) = try await session.data(for: request)`
|
|
8494
|
+
);
|
|
8495
|
+
emitter.block(
|
|
8496
|
+
"guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {",
|
|
8497
|
+
"}",
|
|
8498
|
+
() => {
|
|
8499
|
+
emitter.line("throw URLError(.badServerResponse)");
|
|
8500
|
+
}
|
|
8501
|
+
);
|
|
8502
|
+
if (retType !== "Void") {
|
|
8503
|
+
emitter.line(
|
|
8504
|
+
`return try JSONDecoder().decode(${retType}.self, from: data)`
|
|
8505
|
+
);
|
|
7677
8506
|
}
|
|
7678
|
-
emitter.line(`components.queryItems = queryItems.isEmpty ? nil : queryItems`);
|
|
7679
|
-
}
|
|
7680
|
-
emitter.line(`var request = URLRequest(url: components.url!)`);
|
|
7681
|
-
emitter.line(`request.httpMethod = "${method}"`);
|
|
7682
|
-
emitter.block(`if let token = self.token {`, `}`, () => {
|
|
7683
|
-
emitter.line(`request.addValue("Bearer \\(token)", forHTTPHeaderField: "Authorization")`);
|
|
7684
|
-
});
|
|
7685
|
-
if (ep.requestBody) {
|
|
7686
|
-
emitter.line(`request.addValue("application/json", forHTTPHeaderField: "Content-Type")`);
|
|
7687
|
-
emitter.line(`request.httpBody = try JSONEncoder().encode(body)`);
|
|
7688
|
-
}
|
|
7689
|
-
emitter.line(`let (data, response) = try await session.data(for: request)`);
|
|
7690
|
-
emitter.block("guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {", "}", () => {
|
|
7691
|
-
emitter.line("throw URLError(.badServerResponse)");
|
|
7692
|
-
});
|
|
7693
|
-
if (retType !== "Void") {
|
|
7694
|
-
emitter.line(`return try JSONDecoder().decode(${retType}.self, from: data)`);
|
|
7695
8507
|
}
|
|
7696
|
-
|
|
8508
|
+
);
|
|
7697
8509
|
}
|
|
7698
8510
|
buildResponseType(ep) {
|
|
7699
8511
|
const success = ep.successResponse;
|
|
@@ -7707,7 +8519,8 @@ var SwiftClientEmitter = class {
|
|
|
7707
8519
|
let t = "AnyCodable";
|
|
7708
8520
|
if (ref.ref) t = ref.ref;
|
|
7709
8521
|
else if (ref.inline && ref.inline.kind === "scalar") {
|
|
7710
|
-
if (ref.inline.scalar === "integer" || ref.inline.scalar === "number")
|
|
8522
|
+
if (ref.inline.scalar === "integer" || ref.inline.scalar === "number")
|
|
8523
|
+
t = "Double";
|
|
7711
8524
|
else if (ref.inline.scalar === "boolean") t = "Bool";
|
|
7712
8525
|
else t = "String";
|
|
7713
8526
|
}
|
|
@@ -7727,7 +8540,9 @@ var SwiftGenerator = class extends Generator {
|
|
|
7727
8540
|
this.addFile("Types.swift", typeEmitter.emitAll());
|
|
7728
8541
|
const clientEmitter = new SwiftClientEmitter(this.schema, "ApiClient");
|
|
7729
8542
|
this.addFile("Client.swift", clientEmitter.emitAll());
|
|
7730
|
-
this.addFile(
|
|
8543
|
+
this.addFile(
|
|
8544
|
+
"Package.swift",
|
|
8545
|
+
`// swift-tools-version:5.5
|
|
7731
8546
|
import PackageDescription
|
|
7732
8547
|
|
|
7733
8548
|
let package = Package(
|
|
@@ -7738,7 +8553,8 @@ let package = Package(
|
|
|
7738
8553
|
targets: [
|
|
7739
8554
|
.target(name: "${this.options.packageName}", path: ".")
|
|
7740
8555
|
]
|
|
7741
|
-
)`
|
|
8556
|
+
)`
|
|
8557
|
+
);
|
|
7742
8558
|
return this.files;
|
|
7743
8559
|
}
|
|
7744
8560
|
};
|
|
@@ -7754,19 +8570,199 @@ var TsClientEmitter = class {
|
|
|
7754
8570
|
className;
|
|
7755
8571
|
emitAll() {
|
|
7756
8572
|
const emitter = new Emitter();
|
|
7757
|
-
emitter.line(
|
|
8573
|
+
emitter.line(
|
|
8574
|
+
`import { BaseClient, WebSocketClient, type ClientConfig, type WebSocketClientOptions } from '@axiomify/sdk-runtime';`
|
|
8575
|
+
);
|
|
7758
8576
|
emitter.line(`import type * as Types from './types';`);
|
|
7759
8577
|
emitter.line();
|
|
7760
|
-
emitter.block(
|
|
7761
|
-
|
|
7762
|
-
|
|
7763
|
-
|
|
7764
|
-
|
|
7765
|
-
|
|
7766
|
-
|
|
7767
|
-
|
|
8578
|
+
emitter.block(
|
|
8579
|
+
`export class ${this.className} extends BaseClient {`,
|
|
8580
|
+
`}`,
|
|
8581
|
+
() => {
|
|
8582
|
+
emitter.block(`constructor(config: ClientConfig) {`, `}`, () => {
|
|
8583
|
+
emitter.line(`super(config);`);
|
|
8584
|
+
});
|
|
8585
|
+
for (const ep of this.schema.endpoints) {
|
|
8586
|
+
if (ep.transport !== "rest") continue;
|
|
8587
|
+
emitter.line();
|
|
8588
|
+
this.emitMethod(emitter, ep);
|
|
8589
|
+
}
|
|
8590
|
+
const channels2 = /* @__PURE__ */ new Map();
|
|
8591
|
+
if (this.schema.events) {
|
|
8592
|
+
for (const event of this.schema.events) {
|
|
8593
|
+
const list = channels2.get(event.channel || "/") || [];
|
|
8594
|
+
list.push(event);
|
|
8595
|
+
channels2.set(event.channel || "/", list);
|
|
8596
|
+
}
|
|
8597
|
+
}
|
|
8598
|
+
for (const [channelName, events] of channels2.entries()) {
|
|
8599
|
+
const className = toClassName(channelName);
|
|
8600
|
+
const clientClassName = `${className}ChannelClient`;
|
|
8601
|
+
const params = extractParams(channelName);
|
|
8602
|
+
emitter.line();
|
|
8603
|
+
if (params.length > 0) {
|
|
8604
|
+
const paramSignature = `params: { ${params.map((p) => `${p}: string`).join(", ")} }, options?: WebSocketClientOptions`;
|
|
8605
|
+
emitter.block(
|
|
8606
|
+
`public ${toMethodName(className)}(${paramSignature}): ${clientClassName} {`,
|
|
8607
|
+
`}`,
|
|
8608
|
+
() => {
|
|
8609
|
+
emitter.line(
|
|
8610
|
+
`const wsBase = this.config.baseUrl.replace(/^http/, 'ws');`
|
|
8611
|
+
);
|
|
8612
|
+
let pathExpr = channelName;
|
|
8613
|
+
for (const p of params) {
|
|
8614
|
+
pathExpr = pathExpr.replace(`{${p}}`, `\${params.${p}}`).replace(`:${p}`, `\${params.${p}}`);
|
|
8615
|
+
}
|
|
8616
|
+
emitter.line(
|
|
8617
|
+
`return new ${clientClassName}(\`\${wsBase}${pathExpr}\`, options);`
|
|
8618
|
+
);
|
|
8619
|
+
}
|
|
8620
|
+
);
|
|
8621
|
+
} else {
|
|
8622
|
+
emitter.block(
|
|
8623
|
+
`public ${toMethodName(className)}(options?: WebSocketClientOptions): ${clientClassName} {`,
|
|
8624
|
+
`}`,
|
|
8625
|
+
() => {
|
|
8626
|
+
emitter.line(
|
|
8627
|
+
`const wsBase = this.config.baseUrl.replace(/^http/, 'ws');`
|
|
8628
|
+
);
|
|
8629
|
+
emitter.line(
|
|
8630
|
+
`return new ${clientClassName}(\`\${wsBase}${channelName}\`, options);`
|
|
8631
|
+
);
|
|
8632
|
+
}
|
|
8633
|
+
);
|
|
8634
|
+
}
|
|
8635
|
+
}
|
|
7768
8636
|
}
|
|
7769
|
-
|
|
8637
|
+
);
|
|
8638
|
+
const channels = /* @__PURE__ */ new Map();
|
|
8639
|
+
if (this.schema.events) {
|
|
8640
|
+
for (const event of this.schema.events) {
|
|
8641
|
+
const list = channels.get(event.channel || "/") || [];
|
|
8642
|
+
list.push(event);
|
|
8643
|
+
channels.set(event.channel || "/", list);
|
|
8644
|
+
}
|
|
8645
|
+
}
|
|
8646
|
+
for (const [channelName, events] of channels.entries()) {
|
|
8647
|
+
const className = toClassName(channelName);
|
|
8648
|
+
const clientClassName = `${className}ChannelClient`;
|
|
8649
|
+
emitter.line();
|
|
8650
|
+
emitter.block(`export class ${clientClassName} {`, `}`, () => {
|
|
8651
|
+
emitter.line(`private ws: WebSocketClient;`);
|
|
8652
|
+
emitter.line(
|
|
8653
|
+
`private listeners = new Map<string, Set<(data: any) => void>>();`
|
|
8654
|
+
);
|
|
8655
|
+
emitter.line();
|
|
8656
|
+
emitter.block(
|
|
8657
|
+
`constructor(url: string, options?: WebSocketClientOptions) {`,
|
|
8658
|
+
`}`,
|
|
8659
|
+
() => {
|
|
8660
|
+
emitter.block(`this.ws = new WebSocketClient(url, {`, `});`, () => {
|
|
8661
|
+
emitter.line(`...options,`);
|
|
8662
|
+
emitter.block(`onMessage: (data: string) => {`, `},`, () => {
|
|
8663
|
+
emitter.line(`options?.onMessage?.(data);`);
|
|
8664
|
+
emitter.block(`try {`, `} catch (e) {`, () => {
|
|
8665
|
+
emitter.line(`const parsed = JSON.parse(data);`);
|
|
8666
|
+
emitter.line(
|
|
8667
|
+
`const eventName = String(parsed.event || parsed.type || parsed.action || '').toLowerCase();`
|
|
8668
|
+
);
|
|
8669
|
+
emitter.line(`let matched = false;`);
|
|
8670
|
+
emitter.block(
|
|
8671
|
+
`for (const [registeredName, list] of this.listeners.entries()) {`,
|
|
8672
|
+
`}`,
|
|
8673
|
+
() => {
|
|
8674
|
+
emitter.block(
|
|
8675
|
+
`if (registeredName.toLowerCase() === eventName) {`,
|
|
8676
|
+
`}`,
|
|
8677
|
+
() => {
|
|
8678
|
+
emitter.line(
|
|
8679
|
+
`const payload = parsed.data !== undefined ? parsed.data : (parsed.payload !== undefined ? parsed.payload : parsed);`
|
|
8680
|
+
);
|
|
8681
|
+
emitter.block(`for (const cb of list) {`, `}`, () => {
|
|
8682
|
+
emitter.line(`cb(payload);`);
|
|
8683
|
+
});
|
|
8684
|
+
emitter.line(`matched = true;`);
|
|
8685
|
+
}
|
|
8686
|
+
);
|
|
8687
|
+
}
|
|
8688
|
+
);
|
|
8689
|
+
emitter.block(`if (!matched) {`, `}`, () => {
|
|
8690
|
+
emitter.block(
|
|
8691
|
+
`for (const list of this.listeners.values()) {`,
|
|
8692
|
+
`}`,
|
|
8693
|
+
() => {
|
|
8694
|
+
emitter.block(`for (const cb of list) {`, `}`, () => {
|
|
8695
|
+
emitter.line(`cb(parsed);`);
|
|
8696
|
+
});
|
|
8697
|
+
}
|
|
8698
|
+
);
|
|
8699
|
+
});
|
|
8700
|
+
});
|
|
8701
|
+
emitter.block(``, `}`, () => {
|
|
8702
|
+
emitter.block(
|
|
8703
|
+
`for (const list of this.listeners.values()) {`,
|
|
8704
|
+
`}`,
|
|
8705
|
+
() => {
|
|
8706
|
+
emitter.block(`for (const cb of list) {`, `}`, () => {
|
|
8707
|
+
emitter.line(`cb(data);`);
|
|
8708
|
+
});
|
|
8709
|
+
}
|
|
8710
|
+
);
|
|
8711
|
+
});
|
|
8712
|
+
});
|
|
8713
|
+
});
|
|
8714
|
+
}
|
|
8715
|
+
);
|
|
8716
|
+
emitter.line();
|
|
8717
|
+
emitter.block(`public connect(): void {`, `}`, () => {
|
|
8718
|
+
emitter.line(`this.ws.connect();`);
|
|
8719
|
+
});
|
|
8720
|
+
emitter.line();
|
|
8721
|
+
emitter.block(`public disconnect(): void {`, `}`, () => {
|
|
8722
|
+
emitter.line(`this.ws.disconnect();`);
|
|
8723
|
+
});
|
|
8724
|
+
for (const event of events) {
|
|
8725
|
+
const eventName = event.name;
|
|
8726
|
+
const payloadType = event.payload ? this.renderTypeRef(event.payload) : "any";
|
|
8727
|
+
const capEventName = eventName.charAt(0).toUpperCase() + eventName.slice(1);
|
|
8728
|
+
const direction = event.direction;
|
|
8729
|
+
if (direction === "inbound" || direction === "bidirectional") {
|
|
8730
|
+
emitter.line();
|
|
8731
|
+
emitter.block(
|
|
8732
|
+
`public on${capEventName}(callback: (payload: ${payloadType}) => void): () => void {`,
|
|
8733
|
+
`}`,
|
|
8734
|
+
() => {
|
|
8735
|
+
emitter.line(`let list = this.listeners.get('${eventName}');`);
|
|
8736
|
+
emitter.block(`if (!list) {`, `}`, () => {
|
|
8737
|
+
emitter.line(`list = new Set();`);
|
|
8738
|
+
emitter.line(`this.listeners.set('${eventName}', list);`);
|
|
8739
|
+
});
|
|
8740
|
+
emitter.line(`list.add(callback);`);
|
|
8741
|
+
emitter.block(`return () => {`, `};`, () => {
|
|
8742
|
+
emitter.line(`list.delete(callback);`);
|
|
8743
|
+
});
|
|
8744
|
+
}
|
|
8745
|
+
);
|
|
8746
|
+
}
|
|
8747
|
+
if (direction === "outbound" || direction === "bidirectional") {
|
|
8748
|
+
emitter.line();
|
|
8749
|
+
const paramSig = event.payload ? `payload: ${payloadType}` : `payload?: any`;
|
|
8750
|
+
emitter.block(
|
|
8751
|
+
`public send${capEventName}(${paramSig}): void {`,
|
|
8752
|
+
`}`,
|
|
8753
|
+
() => {
|
|
8754
|
+
emitter.block(`this.ws.send(JSON.stringify({`, `}));`, () => {
|
|
8755
|
+
emitter.line(`event: '${eventName}',`);
|
|
8756
|
+
emitter.line(
|
|
8757
|
+
`data: ${event.payload ? "payload" : "undefined"}`
|
|
8758
|
+
);
|
|
8759
|
+
});
|
|
8760
|
+
}
|
|
8761
|
+
);
|
|
8762
|
+
}
|
|
8763
|
+
}
|
|
8764
|
+
});
|
|
8765
|
+
}
|
|
7770
8766
|
return emitter.toString();
|
|
7771
8767
|
}
|
|
7772
8768
|
emitMethod(emitter, ep) {
|
|
@@ -7790,7 +8786,7 @@ var TsClientEmitter = class {
|
|
|
7790
8786
|
emitter.block(methodSignature, `}`, () => {
|
|
7791
8787
|
const method = ep.method?.toUpperCase() || "GET";
|
|
7792
8788
|
const pathTemplate = ep.path || "/";
|
|
7793
|
-
|
|
8789
|
+
const pathExpr = `\`${pathTemplate.replace(/\{([^}]+)\}/g, "${request.$1}")}\``;
|
|
7794
8790
|
let reqOpts = `method: '${method}', path: ${pathExpr}`;
|
|
7795
8791
|
const isValidTSIdentifier = (name) => /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
|
|
7796
8792
|
if (ep.queryParams.length > 0) {
|
|
@@ -7811,11 +8807,22 @@ var TsClientEmitter = class {
|
|
|
7811
8807
|
buildRequestType(ep) {
|
|
7812
8808
|
const props = [];
|
|
7813
8809
|
const formatProp = (name) => /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name) ? name : `'${name}'`;
|
|
7814
|
-
for (const p of ep.pathParams)
|
|
7815
|
-
|
|
7816
|
-
|
|
8810
|
+
for (const p of ep.pathParams)
|
|
8811
|
+
props.push(
|
|
8812
|
+
`${formatProp(p.name)}${p.required ? "" : "?"}: ${this.renderTypeRef(p.type)}`
|
|
8813
|
+
);
|
|
8814
|
+
for (const p of ep.queryParams)
|
|
8815
|
+
props.push(
|
|
8816
|
+
`${formatProp(p.name)}${p.required ? "" : "?"}: ${this.renderTypeRef(p.type)}`
|
|
8817
|
+
);
|
|
8818
|
+
for (const p of ep.headerParams)
|
|
8819
|
+
props.push(
|
|
8820
|
+
`${formatProp(p.name)}${p.required ? "" : "?"}: ${this.renderTypeRef(p.type)}`
|
|
8821
|
+
);
|
|
7817
8822
|
if (ep.requestBody) {
|
|
7818
|
-
props.push(
|
|
8823
|
+
props.push(
|
|
8824
|
+
`body${ep.requestBody.required ? "" : "?"}: ${this.renderTypeRef(ep.requestBody.type)}`
|
|
8825
|
+
);
|
|
7819
8826
|
}
|
|
7820
8827
|
if (props.length === 0) return null;
|
|
7821
8828
|
return `{ ${props.join(", ")} }`;
|
|
@@ -7833,7 +8840,8 @@ var TsClientEmitter = class {
|
|
|
7833
8840
|
if (ref.ref) t = `Types.${ref.ref}`;
|
|
7834
8841
|
else if (ref.inline) {
|
|
7835
8842
|
if (ref.inline.kind === "scalar") {
|
|
7836
|
-
if (ref.inline.scalar === "integer" || ref.inline.scalar === "number")
|
|
8843
|
+
if (ref.inline.scalar === "integer" || ref.inline.scalar === "number")
|
|
8844
|
+
t = "number";
|
|
7837
8845
|
else if (ref.inline.scalar === "boolean") t = "boolean";
|
|
7838
8846
|
else t = "string";
|
|
7839
8847
|
} else if (ref.inline.kind === "array") {
|
|
@@ -7845,6 +8853,25 @@ var TsClientEmitter = class {
|
|
|
7845
8853
|
return t;
|
|
7846
8854
|
}
|
|
7847
8855
|
};
|
|
8856
|
+
function toClassName(channel) {
|
|
8857
|
+
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));
|
|
8858
|
+
return parts.join("") || "Root";
|
|
8859
|
+
}
|
|
8860
|
+
function toMethodName(className) {
|
|
8861
|
+
return className.charAt(0).toLowerCase() + className.slice(1);
|
|
8862
|
+
}
|
|
8863
|
+
function extractParams(channel) {
|
|
8864
|
+
const params = [];
|
|
8865
|
+
const braceMatches = channel.matchAll(/\{([^}]+)\}/g);
|
|
8866
|
+
for (const m of braceMatches) {
|
|
8867
|
+
params.push(m[1]);
|
|
8868
|
+
}
|
|
8869
|
+
const colonMatches = channel.matchAll(/:([a-zA-Z0-9_]+)/g);
|
|
8870
|
+
for (const m of colonMatches) {
|
|
8871
|
+
params.push(m[1]);
|
|
8872
|
+
}
|
|
8873
|
+
return params;
|
|
8874
|
+
}
|
|
7848
8875
|
|
|
7849
8876
|
// src/sdk/generator/targets/typescript/validator-emitter.ts
|
|
7850
8877
|
var TsValidatorEmitter = class {
|
|
@@ -7871,29 +8898,45 @@ var TsValidatorEmitter = class {
|
|
|
7871
8898
|
emitValidator(emitter, type) {
|
|
7872
8899
|
switch (type.kind) {
|
|
7873
8900
|
case "object":
|
|
7874
|
-
emitter.block(
|
|
7875
|
-
|
|
7876
|
-
|
|
7877
|
-
|
|
7878
|
-
|
|
8901
|
+
emitter.block(
|
|
8902
|
+
`export const ${type.id}Schema = z.object({`,
|
|
8903
|
+
`});`,
|
|
8904
|
+
() => {
|
|
8905
|
+
for (const field of type.fields) {
|
|
8906
|
+
const zodChain = this.renderZodChain(field.type);
|
|
8907
|
+
const req = field.required ? "" : ".optional()";
|
|
8908
|
+
emitter.line(`${field.name}: ${zodChain}${req},`);
|
|
8909
|
+
}
|
|
7879
8910
|
}
|
|
7880
|
-
|
|
8911
|
+
);
|
|
7881
8912
|
break;
|
|
7882
8913
|
case "enum":
|
|
7883
|
-
type.values.map(
|
|
7884
|
-
|
|
8914
|
+
type.values.map(
|
|
8915
|
+
(v) => typeof v.value === "string" ? `"${v.value}"` : v.value
|
|
8916
|
+
).join(", ");
|
|
8917
|
+
emitter.line(
|
|
8918
|
+
`export const ${type.id}Schema = z.union([${type.values.map((v) => typeof v.value === "string" ? `z.literal("${v.value}")` : `z.literal(${v.value})`).join(", ")}]);`
|
|
8919
|
+
);
|
|
7885
8920
|
break;
|
|
7886
8921
|
case "union":
|
|
7887
|
-
emitter.line(
|
|
8922
|
+
emitter.line(
|
|
8923
|
+
`export const ${type.id}Schema = z.union([${type.members.map((m) => this.renderZodChain(m)).join(", ")}]);`
|
|
8924
|
+
);
|
|
7888
8925
|
break;
|
|
7889
8926
|
case "intersection":
|
|
7890
|
-
emitter.line(
|
|
8927
|
+
emitter.line(
|
|
8928
|
+
`export const ${type.id}Schema = z.intersection(${type.members.map((m) => this.renderZodChain(m)).join(", ")});`
|
|
8929
|
+
);
|
|
7891
8930
|
break;
|
|
7892
8931
|
case "array":
|
|
7893
|
-
emitter.line(
|
|
8932
|
+
emitter.line(
|
|
8933
|
+
`export const ${type.id}Schema = z.array(${this.renderZodChain(type.items)});`
|
|
8934
|
+
);
|
|
7894
8935
|
break;
|
|
7895
8936
|
case "scalar":
|
|
7896
|
-
emitter.line(
|
|
8937
|
+
emitter.line(
|
|
8938
|
+
`export const ${type.id}Schema = ${this.renderScalarZod(type.scalar)};`
|
|
8939
|
+
);
|
|
7897
8940
|
break;
|
|
7898
8941
|
default:
|
|
7899
8942
|
emitter.line(`export const ${type.id}Schema = z.any();`);
|
|
@@ -7904,8 +8947,10 @@ var TsValidatorEmitter = class {
|
|
|
7904
8947
|
let t = "z.any()";
|
|
7905
8948
|
if (ref.ref) t = `${ref.ref}Schema`;
|
|
7906
8949
|
else if (ref.inline) {
|
|
7907
|
-
if (ref.inline.kind === "scalar")
|
|
7908
|
-
|
|
8950
|
+
if (ref.inline.kind === "scalar")
|
|
8951
|
+
t = this.renderScalarZod(ref.inline.scalar);
|
|
8952
|
+
else if (ref.inline.kind === "array")
|
|
8953
|
+
t = `z.array(${this.renderZodChain(ref.inline.items)})`;
|
|
7909
8954
|
}
|
|
7910
8955
|
if (ref.isArray) t = `z.array(${t})`;
|
|
7911
8956
|
if (ref.nullable) t = `${t}.nullable()`;
|
|
@@ -7942,7 +8987,9 @@ var TsReactQueryEmitter = class {
|
|
|
7942
8987
|
schema;
|
|
7943
8988
|
emitAll(clientClassName = "ApiClient") {
|
|
7944
8989
|
const emitter = new Emitter();
|
|
7945
|
-
emitter.line(
|
|
8990
|
+
emitter.line(
|
|
8991
|
+
`import { useQuery, useMutation, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';`
|
|
8992
|
+
);
|
|
7946
8993
|
emitter.line(`import { ${clientClassName} } from './client';`);
|
|
7947
8994
|
emitter.line(`import type * as Types from './types';`);
|
|
7948
8995
|
emitter.line();
|
|
@@ -7965,12 +9012,18 @@ var TsReactQueryEmitter = class {
|
|
|
7965
9012
|
if (isMutation) {
|
|
7966
9013
|
const mutationFnArg = reqType ? `req` : ``;
|
|
7967
9014
|
const clientCallArg = reqType ? `req` : ``;
|
|
7968
|
-
emitter.block(
|
|
7969
|
-
|
|
7970
|
-
|
|
7971
|
-
|
|
7972
|
-
|
|
7973
|
-
|
|
9015
|
+
emitter.block(
|
|
9016
|
+
`use${operationName.charAt(0).toUpperCase()}${operationName.slice(1)}(options?: UseMutationOptions<${resType}, Error, ${reqType || "void"}>) {`,
|
|
9017
|
+
`}`,
|
|
9018
|
+
() => {
|
|
9019
|
+
emitter.block(`return useMutation({`, `});`, () => {
|
|
9020
|
+
emitter.line(
|
|
9021
|
+
`mutationFn: (${mutationFnArg}) => this.client.${operationName}(${clientCallArg}),`
|
|
9022
|
+
);
|
|
9023
|
+
emitter.line(`...options,`);
|
|
9024
|
+
});
|
|
9025
|
+
}
|
|
9026
|
+
);
|
|
7974
9027
|
} else {
|
|
7975
9028
|
const queryKeyParts = [`"${operationName}"`];
|
|
7976
9029
|
if (reqType) {
|
|
@@ -7981,7 +9034,9 @@ var TsReactQueryEmitter = class {
|
|
|
7981
9034
|
emitter.block(`${hookName}(${argsSignature}) {`, `}`, () => {
|
|
7982
9035
|
emitter.block(`return useQuery({`, `});`, () => {
|
|
7983
9036
|
emitter.line(`queryKey: [${queryKeyParts.join(", ")}],`);
|
|
7984
|
-
emitter.line(
|
|
9037
|
+
emitter.line(
|
|
9038
|
+
`queryFn: () => this.client.${operationName}(${clientCallArg}),`
|
|
9039
|
+
);
|
|
7985
9040
|
emitter.line(`...options,`);
|
|
7986
9041
|
});
|
|
7987
9042
|
});
|
|
@@ -7990,11 +9045,22 @@ var TsReactQueryEmitter = class {
|
|
|
7990
9045
|
buildRequestType(ep) {
|
|
7991
9046
|
const props = [];
|
|
7992
9047
|
const formatProp = (name) => /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name) ? name : `'${name}'`;
|
|
7993
|
-
for (const p of ep.pathParams)
|
|
7994
|
-
|
|
7995
|
-
|
|
9048
|
+
for (const p of ep.pathParams)
|
|
9049
|
+
props.push(
|
|
9050
|
+
`${formatProp(p.name)}${p.required ? "" : "?"}: ${this.renderTypeRef(p.type)}`
|
|
9051
|
+
);
|
|
9052
|
+
for (const p of ep.queryParams)
|
|
9053
|
+
props.push(
|
|
9054
|
+
`${formatProp(p.name)}${p.required ? "" : "?"}: ${this.renderTypeRef(p.type)}`
|
|
9055
|
+
);
|
|
9056
|
+
for (const p of ep.headerParams)
|
|
9057
|
+
props.push(
|
|
9058
|
+
`${formatProp(p.name)}${p.required ? "" : "?"}: ${this.renderTypeRef(p.type)}`
|
|
9059
|
+
);
|
|
7996
9060
|
if (ep.requestBody) {
|
|
7997
|
-
props.push(
|
|
9061
|
+
props.push(
|
|
9062
|
+
`body${ep.requestBody.required ? "" : "?"}: ${this.renderTypeRef(ep.requestBody.type)}`
|
|
9063
|
+
);
|
|
7998
9064
|
}
|
|
7999
9065
|
if (props.length === 0) return null;
|
|
8000
9066
|
return `{ ${props.join(", ")} }`;
|
|
@@ -8012,7 +9078,8 @@ var TsReactQueryEmitter = class {
|
|
|
8012
9078
|
if (ref.ref) t = `Types.${ref.ref}`;
|
|
8013
9079
|
else if (ref.inline) {
|
|
8014
9080
|
if (ref.inline.kind === "scalar") {
|
|
8015
|
-
if (ref.inline.scalar === "integer" || ref.inline.scalar === "number")
|
|
9081
|
+
if (ref.inline.scalar === "integer" || ref.inline.scalar === "number")
|
|
9082
|
+
t = "number";
|
|
8016
9083
|
else if (ref.inline.scalar === "boolean") t = "boolean";
|
|
8017
9084
|
else t = "string";
|
|
8018
9085
|
} else if (ref.inline.kind === "array") {
|
|
@@ -8037,21 +9104,31 @@ var TypeScriptGenerator = class extends Generator {
|
|
|
8037
9104
|
this.addFile("validators.ts", validatorEmitter.emitAll());
|
|
8038
9105
|
const hooksEmitter = new TsReactQueryEmitter(this.schema);
|
|
8039
9106
|
this.addFile("hooks.ts", hooksEmitter.emitAll("ApiClient"));
|
|
8040
|
-
this.addFile(
|
|
9107
|
+
this.addFile(
|
|
9108
|
+
"index.ts",
|
|
9109
|
+
`export * from './types';
|
|
8041
9110
|
export * from './client';
|
|
8042
9111
|
export * from './validators';
|
|
8043
9112
|
export * from './hooks';
|
|
8044
|
-
`
|
|
8045
|
-
|
|
8046
|
-
|
|
8047
|
-
|
|
8048
|
-
|
|
8049
|
-
|
|
8050
|
-
|
|
8051
|
-
|
|
8052
|
-
|
|
8053
|
-
|
|
8054
|
-
|
|
9113
|
+
`
|
|
9114
|
+
);
|
|
9115
|
+
this.addFile(
|
|
9116
|
+
"package.json",
|
|
9117
|
+
JSON.stringify(
|
|
9118
|
+
{
|
|
9119
|
+
name: this.options.packageName,
|
|
9120
|
+
version: this.options.version || "1.0.0",
|
|
9121
|
+
main: "index.ts",
|
|
9122
|
+
dependencies: {
|
|
9123
|
+
...this.options.runtime ? { "@axiomify/sdk-runtime": "latest" } : {},
|
|
9124
|
+
zod: "^3.22.0",
|
|
9125
|
+
"@tanstack/react-query": "^5.0.0"
|
|
9126
|
+
}
|
|
9127
|
+
},
|
|
9128
|
+
null,
|
|
9129
|
+
2
|
|
9130
|
+
)
|
|
9131
|
+
);
|
|
8055
9132
|
return this.files;
|
|
8056
9133
|
}
|
|
8057
9134
|
};
|
|
@@ -8063,18 +9140,37 @@ async function generateSdk(opts) {
|
|
|
8063
9140
|
console.log(`
|
|
8064
9141
|
${symbols.info} Initializing SDK compilation...
|
|
8065
9142
|
`);
|
|
9143
|
+
const projectRoot = path8.resolve(process.cwd());
|
|
9144
|
+
const resolvedOutput = path8.resolve(projectRoot, opts.output);
|
|
9145
|
+
const relative = path8.relative(projectRoot, resolvedOutput);
|
|
9146
|
+
if (relative.startsWith("..") || path8.isAbsolute(relative)) {
|
|
9147
|
+
console.error(
|
|
9148
|
+
pc.red(
|
|
9149
|
+
`\u2717 Output directory "${opts.output}" must be contained within the project root directory ("${projectRoot}").`
|
|
9150
|
+
)
|
|
9151
|
+
);
|
|
9152
|
+
if (opts.exitOnError !== false) process.exit(1);
|
|
9153
|
+
return false;
|
|
9154
|
+
}
|
|
8066
9155
|
let ingestionResult;
|
|
8067
9156
|
const inputExt = path8.extname(opts.input).toLowerCase();
|
|
8068
9157
|
try {
|
|
8069
9158
|
if (inputExt === ".ts" || inputExt === ".js") {
|
|
8070
|
-
console.log(
|
|
9159
|
+
console.log(
|
|
9160
|
+
` ${symbols.bullet} Ingesting Axiomify app from ${pc.cyan(opts.input)}...`
|
|
9161
|
+
);
|
|
8071
9162
|
const rootAbs = path8.resolve(process.cwd(), opts.input);
|
|
8072
9163
|
const { app, cleanup } = await loadApp(rootAbs);
|
|
8073
|
-
ingestionResult = ingestAxiomifyApp(app, {
|
|
9164
|
+
ingestionResult = ingestAxiomifyApp(app, {
|
|
9165
|
+
title: opts.name,
|
|
9166
|
+
version: opts.version
|
|
9167
|
+
});
|
|
8074
9168
|
await cleanup();
|
|
8075
9169
|
} else if (inputExt === ".json" || inputExt === ".yaml" || inputExt === ".yml") {
|
|
8076
|
-
|
|
8077
|
-
|
|
9170
|
+
const raw = await fs6.readFile(
|
|
9171
|
+
path8.resolve(process.cwd(), opts.input),
|
|
9172
|
+
"utf8"
|
|
9173
|
+
);
|
|
8078
9174
|
let parsed;
|
|
8079
9175
|
if (inputExt === ".json") {
|
|
8080
9176
|
parsed = JSON.parse(raw);
|
|
@@ -8082,13 +9178,41 @@ ${symbols.info} Initializing SDK compilation...
|
|
|
8082
9178
|
const yaml = __require("yaml");
|
|
8083
9179
|
parsed = yaml.parse(raw);
|
|
8084
9180
|
}
|
|
8085
|
-
|
|
9181
|
+
if (parsed && typeof parsed === "object" && "asyncapi" in parsed) {
|
|
9182
|
+
console.log(
|
|
9183
|
+
` ${symbols.bullet} Ingesting AsyncAPI spec from ${pc.cyan(opts.input)}...`
|
|
9184
|
+
);
|
|
9185
|
+
ingestionResult = ingestAsyncApi(parsed, {
|
|
9186
|
+
title: opts.name,
|
|
9187
|
+
version: opts.version
|
|
9188
|
+
});
|
|
9189
|
+
} else {
|
|
9190
|
+
console.log(
|
|
9191
|
+
` ${symbols.bullet} Ingesting OpenAPI spec from ${pc.cyan(opts.input)}...`
|
|
9192
|
+
);
|
|
9193
|
+
ingestionResult = ingestOpenApi(parsed, {
|
|
9194
|
+
title: opts.name,
|
|
9195
|
+
version: opts.version
|
|
9196
|
+
});
|
|
9197
|
+
}
|
|
8086
9198
|
} else if (inputExt === ".graphql" || inputExt === ".gql") {
|
|
8087
|
-
console.log(
|
|
8088
|
-
|
|
8089
|
-
|
|
9199
|
+
console.log(
|
|
9200
|
+
` ${symbols.bullet} Ingesting GraphQL SDL from ${pc.cyan(opts.input)}...`
|
|
9201
|
+
);
|
|
9202
|
+
const raw = await fs6.readFile(
|
|
9203
|
+
path8.resolve(process.cwd(), opts.input),
|
|
9204
|
+
"utf8"
|
|
9205
|
+
);
|
|
9206
|
+
ingestionResult = await ingestGraphQL(raw, {
|
|
9207
|
+
title: opts.name,
|
|
9208
|
+
version: opts.version
|
|
9209
|
+
});
|
|
8090
9210
|
} else {
|
|
8091
|
-
console.error(
|
|
9211
|
+
console.error(
|
|
9212
|
+
pc.red(
|
|
9213
|
+
`\u2717 Unsupported input type: ${inputExt}. Use .ts (App), .json/.yaml (OpenAPI), or .graphql (GraphQL)`
|
|
9214
|
+
)
|
|
9215
|
+
);
|
|
8092
9216
|
if (opts.exitOnError !== false) process.exit(1);
|
|
8093
9217
|
return false;
|
|
8094
9218
|
}
|
|
@@ -8099,8 +9223,10 @@ ${symbols.info} Initializing SDK compilation...
|
|
|
8099
9223
|
}
|
|
8100
9224
|
if (ingestionResult.diagnostics.length > 0) {
|
|
8101
9225
|
for (const d of ingestionResult.diagnostics) {
|
|
8102
|
-
if (d.severity === "error")
|
|
8103
|
-
|
|
9226
|
+
if (d.severity === "error")
|
|
9227
|
+
console.error(pc.red(` [Error] ${d.code}: ${d.message}`));
|
|
9228
|
+
else if (d.severity === "warning")
|
|
9229
|
+
console.warn(pc.yellow(` [Warn] ${d.code}: ${d.message}`));
|
|
8104
9230
|
}
|
|
8105
9231
|
if (ingestionResult.diagnostics.some((d) => d.severity === "error")) {
|
|
8106
9232
|
if (opts.exitOnError !== false) process.exit(1);
|
|
@@ -8112,21 +9238,30 @@ ${symbols.info} Initializing SDK compilation...
|
|
|
8112
9238
|
const compilation = await compiler.compile(ingestionResult.schema);
|
|
8113
9239
|
if (compilation.hasErrors) {
|
|
8114
9240
|
for (const d of compilation.diagnostics) {
|
|
8115
|
-
if (d.severity === "error")
|
|
9241
|
+
if (d.severity === "error")
|
|
9242
|
+
console.error(pc.red(` [Error] ${d.code}: ${d.message}`));
|
|
8116
9243
|
}
|
|
8117
9244
|
console.error(pc.red(`
|
|
8118
9245
|
\u2717 Compilation failed.`));
|
|
8119
9246
|
if (opts.exitOnError !== false) process.exit(1);
|
|
8120
9247
|
return false;
|
|
8121
9248
|
}
|
|
8122
|
-
console.log(
|
|
8123
|
-
|
|
9249
|
+
console.log(
|
|
9250
|
+
` ${symbols.ok} IR compiled successfully in ${compilation.durationMs}ms`
|
|
9251
|
+
);
|
|
9252
|
+
console.log(
|
|
9253
|
+
pc.dim(
|
|
9254
|
+
` (${compilation.schema.endpoints.length} endpoints, ${compilation.schema.types.size} types)`
|
|
9255
|
+
)
|
|
9256
|
+
);
|
|
8124
9257
|
for (const t of opts.target) {
|
|
8125
9258
|
const GeneratorClass = GeneratorRegistry.get(t);
|
|
8126
9259
|
if (!GeneratorClass) {
|
|
8127
9260
|
console.error(pc.red(`
|
|
8128
9261
|
\u2717 Unknown generator target: "${t}"`));
|
|
8129
|
-
console.error(
|
|
9262
|
+
console.error(
|
|
9263
|
+
` Available targets: ${GeneratorRegistry.targets().join(", ")}`
|
|
9264
|
+
);
|
|
8130
9265
|
continue;
|
|
8131
9266
|
}
|
|
8132
9267
|
console.log(`
|
|
@@ -8141,8 +9276,11 @@ ${symbols.info} Initializing SDK compilation...
|
|
|
8141
9276
|
try {
|
|
8142
9277
|
const files = await generator.generate();
|
|
8143
9278
|
if (opts.dryRun) {
|
|
8144
|
-
console.log(
|
|
8145
|
-
|
|
9279
|
+
console.log(
|
|
9280
|
+
` ${symbols.ok} [Dry Run] Would write ${files.length} files to ${path8.relative(process.cwd(), outDir)}`
|
|
9281
|
+
);
|
|
9282
|
+
for (const f of files)
|
|
9283
|
+
console.log(pc.dim(` - ${f.path} (${f.content.length} bytes)`));
|
|
8146
9284
|
} else {
|
|
8147
9285
|
await fs6.mkdir(outDir, { recursive: true });
|
|
8148
9286
|
for (const f of files) {
|
|
@@ -8151,7 +9289,9 @@ ${symbols.info} Initializing SDK compilation...
|
|
|
8151
9289
|
await fs6.writeFile(fullPath, f.content, "utf8");
|
|
8152
9290
|
console.log(pc.dim(` Wrote ${f.path}`));
|
|
8153
9291
|
}
|
|
8154
|
-
console.log(
|
|
9292
|
+
console.log(
|
|
9293
|
+
` ${symbols.ok} Wrote ${files.length} files to ${path8.relative(process.cwd(), outDir)}`
|
|
9294
|
+
);
|
|
8155
9295
|
}
|
|
8156
9296
|
} catch (err) {
|
|
8157
9297
|
console.error(pc.red(` \u2717 Generator failed: ${err.message}`));
|
|
@@ -8333,7 +9473,9 @@ function checkDependencyDrift(findings) {
|
|
|
8333
9473
|
return;
|
|
8334
9474
|
}
|
|
8335
9475
|
const versions = new Set(
|
|
8336
|
-
axiomifyDeps.map(
|
|
9476
|
+
axiomifyDeps.map(
|
|
9477
|
+
([, v]) => v.replace(/^[\^~]/, "").replace(/^\*$/, "workspace")
|
|
9478
|
+
)
|
|
8337
9479
|
);
|
|
8338
9480
|
if (versions.size > 1) {
|
|
8339
9481
|
add2(findings, {
|
|
@@ -8451,7 +9593,10 @@ async function runDoctor() {
|
|
|
8451
9593
|
const tag = pc.dim(`[${f.area}]`);
|
|
8452
9594
|
console.log(` ${sym[f.severity]} ${tag} ${f.message}`);
|
|
8453
9595
|
if (f.hint && f.severity !== "ok") {
|
|
8454
|
-
const wrapped = f.hint.replace(
|
|
9596
|
+
const wrapped = f.hint.replace(
|
|
9597
|
+
/(.{1,80})(\s+|$)/g,
|
|
9598
|
+
"\n " + pc.dim("$1")
|
|
9599
|
+
);
|
|
8455
9600
|
console.log(wrapped);
|
|
8456
9601
|
}
|
|
8457
9602
|
}
|
|
@@ -8787,11 +9932,20 @@ var RULES = [
|
|
|
8787
9932
|
];
|
|
8788
9933
|
async function listSourceFiles(rootAbs) {
|
|
8789
9934
|
const out = [];
|
|
8790
|
-
const skip = /* @__PURE__ */ new Set([
|
|
9935
|
+
const skip = /* @__PURE__ */ new Set([
|
|
9936
|
+
"node_modules",
|
|
9937
|
+
".git",
|
|
9938
|
+
"dist",
|
|
9939
|
+
"build",
|
|
9940
|
+
".axiomify",
|
|
9941
|
+
"coverage"
|
|
9942
|
+
]);
|
|
8791
9943
|
const walk = async (dir) => {
|
|
8792
9944
|
let entries;
|
|
8793
9945
|
try {
|
|
8794
|
-
entries = await fs6.readdir(dir, {
|
|
9946
|
+
entries = await fs6.readdir(dir, {
|
|
9947
|
+
withFileTypes: true
|
|
9948
|
+
});
|
|
8795
9949
|
} catch {
|
|
8796
9950
|
return;
|
|
8797
9951
|
}
|
|
@@ -8880,7 +10034,9 @@ async function runMigrate(opts = {}) {
|
|
|
8880
10034
|
)
|
|
8881
10035
|
);
|
|
8882
10036
|
if (results.length === 0) {
|
|
8883
|
-
console.log(
|
|
10037
|
+
console.log(
|
|
10038
|
+
` ${symbols.ok} Nothing to migrate \u2014 all patterns look up to date.`
|
|
10039
|
+
);
|
|
8884
10040
|
console.log();
|
|
8885
10041
|
return;
|
|
8886
10042
|
}
|
|
@@ -8893,9 +10049,7 @@ async function runMigrate(opts = {}) {
|
|
|
8893
10049
|
for (const rule of RULES) {
|
|
8894
10050
|
const count = totalsByRule[rule.id];
|
|
8895
10051
|
if (!count) continue;
|
|
8896
|
-
console.log(
|
|
8897
|
-
` ${pc.cyan(rule.id)} ${pc.dim("\u2014")} ${rule.description}`
|
|
8898
|
-
);
|
|
10052
|
+
console.log(` ${pc.cyan(rule.id)} ${pc.dim("\u2014")} ${rule.description}`);
|
|
8899
10053
|
console.log(
|
|
8900
10054
|
` ${symbols.bullet} ${pluralise(count, "change")} across ${pluralise(
|
|
8901
10055
|
results.filter((r) => r.counts[rule.id]).length,
|
|
@@ -8923,7 +10077,9 @@ async function runMigrate(opts = {}) {
|
|
|
8923
10077
|
}
|
|
8924
10078
|
for (const r of results) {
|
|
8925
10079
|
await fs6.writeFile(r.file, r.updated, "utf8");
|
|
8926
|
-
console.log(
|
|
10080
|
+
console.log(
|
|
10081
|
+
` ${symbols.ok} ${pc.green("Updated")} ${path8.relative(process.cwd(), r.file)}`
|
|
10082
|
+
);
|
|
8927
10083
|
}
|
|
8928
10084
|
console.log();
|
|
8929
10085
|
console.log(
|
|
@@ -8966,7 +10122,9 @@ async function runMigrate(opts = {}) {
|
|
|
8966
10122
|
);
|
|
8967
10123
|
console.log();
|
|
8968
10124
|
console.log(
|
|
8969
|
-
` See ${pc.cyan("docs/migration-v4-to-v5.md")} for the full guide and ` + pc.cyan("axiomify check") + " to verify the migrated app.\n" + pc.yellow(
|
|
10125
|
+
` See ${pc.cyan("docs/migration-v4-to-v5.md")} for the full guide and ` + pc.cyan("axiomify check") + " to verify the migrated app.\n" + pc.yellow(
|
|
10126
|
+
" Note: `openapi:` / `meta:` merges into `schema:` require manual review \u2014 check TODO comments."
|
|
10127
|
+
)
|
|
8970
10128
|
);
|
|
8971
10129
|
console.log();
|
|
8972
10130
|
}
|
|
@@ -8983,8 +10141,10 @@ async function jsonToYaml(obj) {
|
|
|
8983
10141
|
}
|
|
8984
10142
|
if (Array.isArray(v)) {
|
|
8985
10143
|
if (v.length === 0) return "[]";
|
|
8986
|
-
return v.map(
|
|
8987
|
-
|
|
10144
|
+
return v.map(
|
|
10145
|
+
(item) => `
|
|
10146
|
+
${pad2}- ${emit(item, indent + 1).replace(/^/gm, " ").trimStart()}`
|
|
10147
|
+
).join("");
|
|
8988
10148
|
}
|
|
8989
10149
|
if (typeof v === "object") {
|
|
8990
10150
|
const keys = Object.keys(v);
|
|
@@ -9018,7 +10178,7 @@ async function emitOpenApi(entry, opts = {}) {
|
|
|
9018
10178
|
try {
|
|
9019
10179
|
let OpenApiGenerator;
|
|
9020
10180
|
try {
|
|
9021
|
-
({ OpenApiGenerator } = await import('./dist-
|
|
10181
|
+
({ OpenApiGenerator } = await import('./dist-IQQ2XGG4.mjs'));
|
|
9022
10182
|
} catch {
|
|
9023
10183
|
console.error(
|
|
9024
10184
|
pc.red("\u2717 @axiomify/openapi is not installed."),
|
|
@@ -9043,7 +10203,9 @@ async function emitOpenApi(entry, opts = {}) {
|
|
|
9043
10203
|
await fs6.writeFile(outPath, serialised + "\n", "utf8");
|
|
9044
10204
|
const routeCount = (app.registeredRoutes ?? []).length;
|
|
9045
10205
|
console.log(
|
|
9046
|
-
`${pc.green("\u2713")} OpenAPI spec written to ${pc.cyan(opts.output)} ` + pc.dim(
|
|
10206
|
+
`${pc.green("\u2713")} OpenAPI spec written to ${pc.cyan(opts.output)} ` + pc.dim(
|
|
10207
|
+
`(${routeCount} route${routeCount === 1 ? "" : "s"}, ${format})`
|
|
10208
|
+
)
|
|
9047
10209
|
);
|
|
9048
10210
|
} else {
|
|
9049
10211
|
process.stdout.write(serialised + "\n");
|
|
@@ -9162,14 +10324,20 @@ async function inspectRoutes(entry, opts = {}) {
|
|
|
9162
10324
|
];
|
|
9163
10325
|
const rows = filtered.map((r) => {
|
|
9164
10326
|
const method = colourMethod(r.method);
|
|
9165
|
-
const highlightedPath = r.path.replace(
|
|
10327
|
+
const highlightedPath = r.path.replace(
|
|
10328
|
+
/:[a-zA-Z0-9_]+/g,
|
|
10329
|
+
(match) => pc.yellow(match)
|
|
10330
|
+
);
|
|
9166
10331
|
const path12 = r.deprecated ? pc.strikethrough(highlightedPath) + " " + badge.deprecated() : highlightedPath;
|
|
9167
10332
|
const validation = r.validation.length > 0 ? r.validation.map(badge.validation).join(pc.dim(",")) : pc.dim("\u2014");
|
|
9168
10333
|
const metaBits = [];
|
|
9169
10334
|
if (r.operationId) metaBits.push(pc.dim(`op:`) + r.operationId);
|
|
9170
10335
|
if (r.tags.length) metaBits.push(badge.tags(r.tags));
|
|
9171
10336
|
if (r.timeout !== void 0) metaBits.push(badge.timeout(r.timeout));
|
|
9172
|
-
if (r.plugins > 0)
|
|
10337
|
+
if (r.plugins > 0)
|
|
10338
|
+
metaBits.push(
|
|
10339
|
+
pc.dim(`+${r.plugins} plugin${r.plugins === 1 ? "" : "s"}`)
|
|
10340
|
+
);
|
|
9173
10341
|
const meta = metaBits.length ? metaBits.join(" ") : pc.dim("\u2014");
|
|
9174
10342
|
return [method, path12, validation, meta];
|
|
9175
10343
|
});
|
|
@@ -9328,10 +10496,7 @@ async function scaffoldRoute(method, routePath, opts = {}) {
|
|
|
9328
10496
|
process.exit(1);
|
|
9329
10497
|
}
|
|
9330
10498
|
if (!routePath.startsWith("/")) {
|
|
9331
|
-
console.error(
|
|
9332
|
-
pc.red('\u2717 Path must start with "/".'),
|
|
9333
|
-
`Got: ${routePath}`
|
|
9334
|
-
);
|
|
10499
|
+
console.error(pc.red('\u2717 Path must start with "/".'), `Got: ${routePath}`);
|
|
9335
10500
|
process.exit(1);
|
|
9336
10501
|
}
|
|
9337
10502
|
const dir = opts.dir ?? "src/routes";
|
|
@@ -9339,8 +10504,10 @@ async function scaffoldRoute(method, routePath, opts = {}) {
|
|
|
9339
10504
|
const fileAbs = path8.resolve(process.cwd(), dir, filename);
|
|
9340
10505
|
const source = generateRouteSource(upperMethod, routePath, opts);
|
|
9341
10506
|
if (opts.dryRun) {
|
|
9342
|
-
console.log(
|
|
9343
|
-
|
|
10507
|
+
console.log(
|
|
10508
|
+
pc.dim(`# would write ${path8.relative(process.cwd(), fileAbs)}
|
|
10509
|
+
`)
|
|
10510
|
+
);
|
|
9344
10511
|
console.log(source);
|
|
9345
10512
|
return;
|
|
9346
10513
|
}
|
|
@@ -9367,8 +10534,10 @@ async function scaffoldRoute(method, routePath, opts = {}) {
|
|
|
9367
10534
|
console.log(pc.dim(" Next steps:"));
|
|
9368
10535
|
console.log(
|
|
9369
10536
|
` 1. Wire it into your entry file:
|
|
9370
|
-
` + pc.dim(
|
|
9371
|
-
`
|
|
10537
|
+
` + pc.dim(
|
|
10538
|
+
` import { registerRoute } from './routes/${pathToFilename(routePath)}';
|
|
10539
|
+
`
|
|
10540
|
+
) + pc.dim(` registerRoute(app);`)
|
|
9372
10541
|
);
|
|
9373
10542
|
console.log(
|
|
9374
10543
|
` 2. Fill in the TODOs in ${pc.cyan(path8.relative(process.cwd(), fileAbs))}.`
|
|
@@ -9388,17 +10557,30 @@ var SchemaDiffer = class {
|
|
|
9388
10557
|
for (const [id, oldEp] of oldOps) {
|
|
9389
10558
|
const newEp = newOps.get(id);
|
|
9390
10559
|
if (!newEp) {
|
|
9391
|
-
result.endpoints[id] = {
|
|
10560
|
+
result.endpoints[id] = {
|
|
10561
|
+
type: "removed",
|
|
10562
|
+
oldEndpoint: oldEp,
|
|
10563
|
+
changes: []
|
|
10564
|
+
};
|
|
9392
10565
|
} else {
|
|
9393
10566
|
const changes = this.diffEndpoints(oldEp, newEp);
|
|
9394
10567
|
if (changes.length > 0) {
|
|
9395
|
-
result.endpoints[id] = {
|
|
10568
|
+
result.endpoints[id] = {
|
|
10569
|
+
type: "modified",
|
|
10570
|
+
oldEndpoint: oldEp,
|
|
10571
|
+
newEndpoint: newEp,
|
|
10572
|
+
changes
|
|
10573
|
+
};
|
|
9396
10574
|
}
|
|
9397
10575
|
}
|
|
9398
10576
|
}
|
|
9399
10577
|
for (const [id, newEp] of newOps) {
|
|
9400
10578
|
if (!oldOps.has(id)) {
|
|
9401
|
-
result.endpoints[id] = {
|
|
10579
|
+
result.endpoints[id] = {
|
|
10580
|
+
type: "added",
|
|
10581
|
+
newEndpoint: newEp,
|
|
10582
|
+
changes: []
|
|
10583
|
+
};
|
|
9402
10584
|
}
|
|
9403
10585
|
}
|
|
9404
10586
|
for (const [id, oldType] of oldSchema.types) {
|
|
@@ -9422,10 +10604,20 @@ var SchemaDiffer = class {
|
|
|
9422
10604
|
diffEndpoints(oldEp, newEp) {
|
|
9423
10605
|
const changes = [];
|
|
9424
10606
|
if (oldEp.path !== newEp.path) {
|
|
9425
|
-
changes.push({
|
|
10607
|
+
changes.push({
|
|
10608
|
+
path: "path",
|
|
10609
|
+
type: "modified",
|
|
10610
|
+
oldValue: oldEp.path,
|
|
10611
|
+
newValue: newEp.path
|
|
10612
|
+
});
|
|
9426
10613
|
}
|
|
9427
10614
|
if (oldEp.method !== newEp.method) {
|
|
9428
|
-
changes.push({
|
|
10615
|
+
changes.push({
|
|
10616
|
+
path: "method",
|
|
10617
|
+
type: "modified",
|
|
10618
|
+
oldValue: oldEp.method,
|
|
10619
|
+
newValue: newEp.method
|
|
10620
|
+
});
|
|
9429
10621
|
}
|
|
9430
10622
|
const diffParams = (oldParams = [], newParams = [], typeName) => {
|
|
9431
10623
|
const oldMap = new Map((oldParams || []).map((p) => [p.name, p]));
|
|
@@ -9433,19 +10625,37 @@ var SchemaDiffer = class {
|
|
|
9433
10625
|
for (const [name, oldP] of oldMap) {
|
|
9434
10626
|
const newP = newMap.get(name);
|
|
9435
10627
|
if (!newP) {
|
|
9436
|
-
changes.push({
|
|
10628
|
+
changes.push({
|
|
10629
|
+
path: `${typeName}.${name}`,
|
|
10630
|
+
type: "removed",
|
|
10631
|
+
oldValue: oldP
|
|
10632
|
+
});
|
|
9437
10633
|
} else {
|
|
9438
10634
|
if (JSON.stringify(oldP.type) !== JSON.stringify(newP.type)) {
|
|
9439
|
-
changes.push({
|
|
10635
|
+
changes.push({
|
|
10636
|
+
path: `${typeName}.${name}.type`,
|
|
10637
|
+
type: "modified",
|
|
10638
|
+
oldValue: oldP.type,
|
|
10639
|
+
newValue: newP.type
|
|
10640
|
+
});
|
|
9440
10641
|
}
|
|
9441
10642
|
if (oldP.required !== newP.required) {
|
|
9442
|
-
changes.push({
|
|
10643
|
+
changes.push({
|
|
10644
|
+
path: `${typeName}.${name}.required`,
|
|
10645
|
+
type: "modified",
|
|
10646
|
+
oldValue: oldP.required,
|
|
10647
|
+
newValue: newP.required
|
|
10648
|
+
});
|
|
9443
10649
|
}
|
|
9444
10650
|
}
|
|
9445
10651
|
}
|
|
9446
10652
|
for (const [name, newP] of newMap) {
|
|
9447
10653
|
if (!oldMap.has(name)) {
|
|
9448
|
-
changes.push({
|
|
10654
|
+
changes.push({
|
|
10655
|
+
path: `${typeName}.${name}`,
|
|
10656
|
+
type: "added",
|
|
10657
|
+
newValue: newP
|
|
10658
|
+
});
|
|
9449
10659
|
}
|
|
9450
10660
|
}
|
|
9451
10661
|
};
|
|
@@ -9453,15 +10663,33 @@ var SchemaDiffer = class {
|
|
|
9453
10663
|
diffParams(oldEp.queryParams, newEp.queryParams, "queryParams");
|
|
9454
10664
|
diffParams(oldEp.headerParams, newEp.headerParams, "headerParams");
|
|
9455
10665
|
if (oldEp.requestBody && !newEp.requestBody) {
|
|
9456
|
-
changes.push({
|
|
10666
|
+
changes.push({
|
|
10667
|
+
path: "requestBody",
|
|
10668
|
+
type: "removed",
|
|
10669
|
+
oldValue: oldEp.requestBody
|
|
10670
|
+
});
|
|
9457
10671
|
} else if (!oldEp.requestBody && newEp.requestBody) {
|
|
9458
|
-
changes.push({
|
|
10672
|
+
changes.push({
|
|
10673
|
+
path: "requestBody",
|
|
10674
|
+
type: "added",
|
|
10675
|
+
newValue: newEp.requestBody
|
|
10676
|
+
});
|
|
9459
10677
|
} else if (oldEp.requestBody && newEp.requestBody) {
|
|
9460
10678
|
if (JSON.stringify(oldEp.requestBody.type) !== JSON.stringify(newEp.requestBody.type)) {
|
|
9461
|
-
changes.push({
|
|
10679
|
+
changes.push({
|
|
10680
|
+
path: "requestBody.type",
|
|
10681
|
+
type: "modified",
|
|
10682
|
+
oldValue: oldEp.requestBody.type,
|
|
10683
|
+
newValue: newEp.requestBody.type
|
|
10684
|
+
});
|
|
9462
10685
|
}
|
|
9463
10686
|
if (oldEp.requestBody.required !== newEp.requestBody.required) {
|
|
9464
|
-
changes.push({
|
|
10687
|
+
changes.push({
|
|
10688
|
+
path: "requestBody.required",
|
|
10689
|
+
type: "modified",
|
|
10690
|
+
oldValue: oldEp.requestBody.required,
|
|
10691
|
+
newValue: newEp.requestBody.required
|
|
10692
|
+
});
|
|
9465
10693
|
}
|
|
9466
10694
|
}
|
|
9467
10695
|
return changes;
|
|
@@ -9469,7 +10697,12 @@ var SchemaDiffer = class {
|
|
|
9469
10697
|
diffTypes(oldType, newType) {
|
|
9470
10698
|
const changes = [];
|
|
9471
10699
|
if (oldType.kind !== newType.kind) {
|
|
9472
|
-
changes.push({
|
|
10700
|
+
changes.push({
|
|
10701
|
+
path: "kind",
|
|
10702
|
+
type: "modified",
|
|
10703
|
+
oldValue: oldType.kind,
|
|
10704
|
+
newValue: newType.kind
|
|
10705
|
+
});
|
|
9473
10706
|
return changes;
|
|
9474
10707
|
}
|
|
9475
10708
|
if (oldType.kind === "object" && newType.kind === "object") {
|
|
@@ -9478,19 +10711,37 @@ var SchemaDiffer = class {
|
|
|
9478
10711
|
for (const [name, oldF] of oldFields) {
|
|
9479
10712
|
const newF = newFields.get(name);
|
|
9480
10713
|
if (!newF) {
|
|
9481
|
-
changes.push({
|
|
10714
|
+
changes.push({
|
|
10715
|
+
path: `fields.${name}`,
|
|
10716
|
+
type: "removed",
|
|
10717
|
+
oldValue: oldF
|
|
10718
|
+
});
|
|
9482
10719
|
} else {
|
|
9483
10720
|
if (JSON.stringify(oldF.type) !== JSON.stringify(newF.type)) {
|
|
9484
|
-
changes.push({
|
|
10721
|
+
changes.push({
|
|
10722
|
+
path: `fields.${name}.type`,
|
|
10723
|
+
type: "modified",
|
|
10724
|
+
oldValue: oldF.type,
|
|
10725
|
+
newValue: newF.type
|
|
10726
|
+
});
|
|
9485
10727
|
}
|
|
9486
10728
|
if (oldF.required !== newF.required) {
|
|
9487
|
-
changes.push({
|
|
10729
|
+
changes.push({
|
|
10730
|
+
path: `fields.${name}.required`,
|
|
10731
|
+
type: "modified",
|
|
10732
|
+
oldValue: oldF.required,
|
|
10733
|
+
newValue: newF.required
|
|
10734
|
+
});
|
|
9488
10735
|
}
|
|
9489
10736
|
}
|
|
9490
10737
|
}
|
|
9491
10738
|
for (const [name, newF] of newFields) {
|
|
9492
10739
|
if (!oldFields.has(name)) {
|
|
9493
|
-
changes.push({
|
|
10740
|
+
changes.push({
|
|
10741
|
+
path: `fields.${name}`,
|
|
10742
|
+
type: "added",
|
|
10743
|
+
newValue: newF
|
|
10744
|
+
});
|
|
9494
10745
|
}
|
|
9495
10746
|
}
|
|
9496
10747
|
}
|
|
@@ -9757,20 +11008,32 @@ function registerSdkDiffCommand(program3) {
|
|
|
9757
11008
|
const analyzer = new BreakingChangeAnalyzer();
|
|
9758
11009
|
const report = analyzer.analyze(diffs);
|
|
9759
11010
|
const breaking = report.issues.filter((i) => i.severity === "breaking");
|
|
9760
|
-
const nonBreaking = report.issues.filter(
|
|
11011
|
+
const nonBreaking = report.issues.filter(
|
|
11012
|
+
(i) => i.severity !== "breaking"
|
|
11013
|
+
);
|
|
9761
11014
|
if (breaking.length === 0 && nonBreaking.length === 0) {
|
|
9762
11015
|
console.log(pc.green(" \u2713 No changes detected between schemas."));
|
|
9763
11016
|
} else {
|
|
9764
11017
|
if (breaking.length > 0) {
|
|
9765
|
-
console.log(
|
|
9766
|
-
|
|
11018
|
+
console.log(
|
|
11019
|
+
pc.red(` \u2717 Found ${breaking.length} breaking changes:`)
|
|
11020
|
+
);
|
|
11021
|
+
breaking.forEach(
|
|
11022
|
+
(b) => console.log(pc.red(` - ${b.description}`))
|
|
11023
|
+
);
|
|
9767
11024
|
} else {
|
|
9768
11025
|
console.log(pc.green(" \u2713 No breaking changes detected."));
|
|
9769
11026
|
}
|
|
9770
11027
|
if (nonBreaking.length > 0) {
|
|
9771
|
-
console.log(
|
|
9772
|
-
|
|
9773
|
-
|
|
11028
|
+
console.log(
|
|
11029
|
+
pc.yellow(
|
|
11030
|
+
`
|
|
11031
|
+
\u26A0 Found ${nonBreaking.length} non-breaking changes:`
|
|
11032
|
+
)
|
|
11033
|
+
);
|
|
11034
|
+
nonBreaking.forEach(
|
|
11035
|
+
(nb) => console.log(pc.yellow(` - ${nb.description}`))
|
|
11036
|
+
);
|
|
9774
11037
|
}
|
|
9775
11038
|
}
|
|
9776
11039
|
console.log(pc.green("\n\u2713 Done."));
|
|
@@ -9785,7 +11048,10 @@ function registerSdkDiffCommand(program3) {
|
|
|
9785
11048
|
});
|
|
9786
11049
|
}
|
|
9787
11050
|
function registerSdkValidateCommand(program3) {
|
|
9788
|
-
program3.command("validate").description("Validate an API schema against the Axiomify SDK compiler").argument(
|
|
11051
|
+
program3.command("validate").description("Validate an API schema against the Axiomify SDK compiler").argument(
|
|
11052
|
+
"<input>",
|
|
11053
|
+
"The input schema file (e.g. spec.json, schema.graphql)"
|
|
11054
|
+
).action(async (input) => {
|
|
9789
11055
|
try {
|
|
9790
11056
|
console.log(pc.blue("\u2139 Initializing SDK validator...\n"));
|
|
9791
11057
|
console.log(pc.dim(` \u2022 Loading ${input}...`));
|
|
@@ -9816,7 +11082,12 @@ function registerSdkValidateCommand(program3) {
|
|
|
9816
11082
|
});
|
|
9817
11083
|
}
|
|
9818
11084
|
function registerSdkBuildCommand(program3) {
|
|
9819
|
-
program3.command("build").description(
|
|
11085
|
+
program3.command("build").description(
|
|
11086
|
+
"Build, validate, and check API schema compile target readiness"
|
|
11087
|
+
).argument(
|
|
11088
|
+
"<input>",
|
|
11089
|
+
"The input schema file (e.g. spec.json, schema.graphql)"
|
|
11090
|
+
).action(async (input) => {
|
|
9820
11091
|
try {
|
|
9821
11092
|
console.log(pc.blue("\u2139 Initializing SDK build...\n"));
|
|
9822
11093
|
const ext = input.split(".").pop()?.toLowerCase() || "";
|
|
@@ -9845,7 +11116,9 @@ function registerSdkBuildCommand(program3) {
|
|
|
9845
11116
|
}
|
|
9846
11117
|
console.log(pc.green(`
|
|
9847
11118
|
\u2713 Build succeeded!`));
|
|
9848
|
-
console.log(
|
|
11119
|
+
console.log(
|
|
11120
|
+
pc.dim(` Endpoints: ${result.schema.endpoints.length}`)
|
|
11121
|
+
);
|
|
9849
11122
|
console.log(pc.dim(` Types: ${result.schema.types.size}`));
|
|
9850
11123
|
console.log(pc.dim(` Duration: ${result.durationMs}ms`));
|
|
9851
11124
|
} catch (err) {
|
|
@@ -9856,12 +11129,24 @@ function registerSdkBuildCommand(program3) {
|
|
|
9856
11129
|
});
|
|
9857
11130
|
}
|
|
9858
11131
|
function registerSdkPublishCommand(program3) {
|
|
9859
|
-
program3.command("publish").description(
|
|
11132
|
+
program3.command("publish").description(
|
|
11133
|
+
"Publish generated SDK packages to package registries (dry-run by default)"
|
|
11134
|
+
).option("--dry-run", "Simulate publishing without uploading", true).option("--registry <url>", "Override registry URL").action(async (options) => {
|
|
9860
11135
|
try {
|
|
9861
11136
|
console.log(pc.blue("\u2139 Initializing SDK publishing...\n"));
|
|
9862
|
-
const targets = [
|
|
11137
|
+
const targets = [
|
|
11138
|
+
"typescript",
|
|
11139
|
+
"javascript",
|
|
11140
|
+
"python",
|
|
11141
|
+
"go",
|
|
11142
|
+
"kotlin",
|
|
11143
|
+
"swift",
|
|
11144
|
+
"dart"
|
|
11145
|
+
];
|
|
9863
11146
|
for (const target of targets) {
|
|
9864
|
-
console.log(
|
|
11147
|
+
console.log(
|
|
11148
|
+
pc.cyan(` \u2022 Preparing publishing for target [${target}]`)
|
|
11149
|
+
);
|
|
9865
11150
|
let cmd = "";
|
|
9866
11151
|
switch (target) {
|
|
9867
11152
|
case "typescript":
|
|
@@ -9887,7 +11172,9 @@ function registerSdkPublishCommand(program3) {
|
|
|
9887
11172
|
if (options.dryRun) {
|
|
9888
11173
|
console.log(pc.dim(` [Simulated] Would run: ${cmd}`));
|
|
9889
11174
|
} else {
|
|
9890
|
-
console.log(
|
|
11175
|
+
console.log(
|
|
11176
|
+
pc.yellow(` [Action] Executing publishing command: ${cmd}`)
|
|
11177
|
+
);
|
|
9891
11178
|
}
|
|
9892
11179
|
}
|
|
9893
11180
|
console.log(pc.green("\n\u2713 Publish simulation complete."));
|
|
@@ -9899,15 +11186,29 @@ function registerSdkPublishCommand(program3) {
|
|
|
9899
11186
|
});
|
|
9900
11187
|
}
|
|
9901
11188
|
function registerSdkDoctorCommand(program3) {
|
|
9902
|
-
program3.command("doctor").description(
|
|
11189
|
+
program3.command("doctor").description(
|
|
11190
|
+
"Verify and diagnose local toolchains required for SDK targets"
|
|
11191
|
+
).action(async () => {
|
|
9903
11192
|
console.log(pc.blue("\u2139 Diagnosing local SDK target toolchains...\n"));
|
|
9904
11193
|
const toolchains = [
|
|
9905
|
-
{
|
|
9906
|
-
|
|
11194
|
+
{
|
|
11195
|
+
name: "TypeScript/JavaScript (Node.js)",
|
|
11196
|
+
cmd: "node --version",
|
|
11197
|
+
req: "Node.js"
|
|
11198
|
+
},
|
|
11199
|
+
{
|
|
11200
|
+
name: "Python (pip/pydantic)",
|
|
11201
|
+
cmd: "python3 --version",
|
|
11202
|
+
req: "Python 3"
|
|
11203
|
+
},
|
|
9907
11204
|
{ name: "Go (compiler)", cmd: "go version", req: "Go SDK" },
|
|
9908
11205
|
{ name: "Dart (flutter/pub)", cmd: "dart --version", req: "Dart SDK" },
|
|
9909
11206
|
{ name: "Kotlin (gradle/java)", cmd: "java -version", req: "Java JDK" },
|
|
9910
|
-
{
|
|
11207
|
+
{
|
|
11208
|
+
name: "Swift (swiftc/xcode)",
|
|
11209
|
+
cmd: "swift --version",
|
|
11210
|
+
req: "Swift / Xcode Command Line Tools"
|
|
11211
|
+
}
|
|
9911
11212
|
];
|
|
9912
11213
|
let allOk = true;
|
|
9913
11214
|
for (const tc of toolchains) {
|
|
@@ -9920,18 +11221,34 @@ function registerSdkDoctorCommand(program3) {
|
|
|
9920
11221
|
}
|
|
9921
11222
|
}
|
|
9922
11223
|
if (allOk) {
|
|
9923
|
-
console.log(
|
|
11224
|
+
console.log(
|
|
11225
|
+
pc.green("\n\u2713 Doctor check passed. All toolchains are available.")
|
|
11226
|
+
);
|
|
9924
11227
|
} else {
|
|
9925
|
-
console.log(
|
|
11228
|
+
console.log(
|
|
11229
|
+
pc.yellow(
|
|
11230
|
+
"\n\u26A0 Some toolchains are missing. You may not be able to build or publish certain targets."
|
|
11231
|
+
)
|
|
11232
|
+
);
|
|
9926
11233
|
}
|
|
9927
11234
|
});
|
|
9928
11235
|
}
|
|
9929
11236
|
function registerSdkBenchmarkCommand(program3) {
|
|
9930
11237
|
program3.command("benchmark").description("Benchmark the compiler and code generator throughput").action(async () => {
|
|
9931
|
-
console.log(
|
|
9932
|
-
|
|
11238
|
+
console.log(
|
|
11239
|
+
pc.blue(
|
|
11240
|
+
"\u2139 Initializing SDK compiler & generator performance benchmark...\n"
|
|
11241
|
+
)
|
|
11242
|
+
);
|
|
11243
|
+
console.log(
|
|
11244
|
+
pc.dim(" \u2022 Synthesizing mock schema (50 endpoints, 100 types)...")
|
|
11245
|
+
);
|
|
9933
11246
|
const mockSchema = {
|
|
9934
|
-
info: {
|
|
11247
|
+
info: {
|
|
11248
|
+
title: "Benchmark API",
|
|
11249
|
+
version: "2.0.0",
|
|
11250
|
+
sourceFormat: "openapi"
|
|
11251
|
+
},
|
|
9935
11252
|
types: /* @__PURE__ */ new Map(),
|
|
9936
11253
|
endpoints: [],
|
|
9937
11254
|
securitySchemes: /* @__PURE__ */ new Map(),
|
|
@@ -9946,10 +11263,34 @@ function registerSdkBenchmarkCommand(program3) {
|
|
|
9946
11263
|
id: typeId,
|
|
9947
11264
|
kind: "object",
|
|
9948
11265
|
fields: [
|
|
9949
|
-
{
|
|
9950
|
-
|
|
9951
|
-
|
|
9952
|
-
|
|
11266
|
+
{
|
|
11267
|
+
name: "id",
|
|
11268
|
+
required: true,
|
|
11269
|
+
type: {
|
|
11270
|
+
inline: { id: "_string", kind: "scalar", scalar: "string" }
|
|
11271
|
+
}
|
|
11272
|
+
},
|
|
11273
|
+
{
|
|
11274
|
+
name: "name",
|
|
11275
|
+
required: true,
|
|
11276
|
+
type: {
|
|
11277
|
+
inline: { id: "_string", kind: "scalar", scalar: "string" }
|
|
11278
|
+
}
|
|
11279
|
+
},
|
|
11280
|
+
{
|
|
11281
|
+
name: "age",
|
|
11282
|
+
required: false,
|
|
11283
|
+
type: {
|
|
11284
|
+
inline: { id: "_number", kind: "scalar", scalar: "number" }
|
|
11285
|
+
}
|
|
11286
|
+
},
|
|
11287
|
+
{
|
|
11288
|
+
name: "createdAt",
|
|
11289
|
+
required: true,
|
|
11290
|
+
type: {
|
|
11291
|
+
inline: { id: "_datetime", kind: "scalar", scalar: "datetime" }
|
|
11292
|
+
}
|
|
11293
|
+
}
|
|
9953
11294
|
]
|
|
9954
11295
|
});
|
|
9955
11296
|
}
|
|
@@ -9961,7 +11302,14 @@ function registerSdkBenchmarkCommand(program3) {
|
|
|
9961
11302
|
method: "GET",
|
|
9962
11303
|
path: `/resource/${i}/{id}`,
|
|
9963
11304
|
pathParams: [
|
|
9964
|
-
{
|
|
11305
|
+
{
|
|
11306
|
+
name: "id",
|
|
11307
|
+
location: "path",
|
|
11308
|
+
required: true,
|
|
11309
|
+
type: {
|
|
11310
|
+
inline: { id: "_string", kind: "scalar", scalar: "string" }
|
|
11311
|
+
}
|
|
11312
|
+
}
|
|
9965
11313
|
],
|
|
9966
11314
|
queryParams: [],
|
|
9967
11315
|
headerParams: [],
|
|
@@ -10005,16 +11353,38 @@ function registerSdkBenchmarkCommand(program3) {
|
|
|
10005
11353
|
console.log();
|
|
10006
11354
|
console.log(pc.bold("Results Summary:"));
|
|
10007
11355
|
console.log(pc.dim(` - Compilation Time: ${compileTime}ms`));
|
|
10008
|
-
console.log(
|
|
11356
|
+
console.log(
|
|
11357
|
+
pc.dim(
|
|
11358
|
+
` - Generation Time (all ${targets.length} targets): ${genTime}ms`
|
|
11359
|
+
)
|
|
11360
|
+
);
|
|
10009
11361
|
console.log(pc.dim(` - Total files generated: ${totalFiles}`));
|
|
10010
|
-
console.log(
|
|
10011
|
-
|
|
11362
|
+
console.log(
|
|
11363
|
+
pc.dim(
|
|
11364
|
+
` - Compilation Throughput: ${(50 / (compileTime / 1e3)).toFixed(2)} endpoints/sec`
|
|
11365
|
+
)
|
|
11366
|
+
);
|
|
11367
|
+
console.log(
|
|
11368
|
+
pc.dim(
|
|
11369
|
+
` - Generation Throughput: ${(totalFiles / (genTime / 1e3)).toFixed(2)} files/sec`
|
|
11370
|
+
)
|
|
11371
|
+
);
|
|
10012
11372
|
});
|
|
10013
11373
|
}
|
|
10014
11374
|
function registerSdkWatchCommand(program3) {
|
|
10015
|
-
program3.command("watch").description(
|
|
11375
|
+
program3.command("watch").description(
|
|
11376
|
+
"Watch the input API schema file and regenerate SDK targets automatically on changes"
|
|
11377
|
+
).argument(
|
|
11378
|
+
"<input>",
|
|
11379
|
+
"The input schema file (e.g. spec.json, schema.graphql)"
|
|
11380
|
+
).requiredOption(
|
|
11381
|
+
"-t, --target <langs...>",
|
|
11382
|
+
"Target languages (e.g. typescript python)"
|
|
11383
|
+
).option("-o, --output <dir>", "Output directory", "generated-sdks").action(async (input, options) => {
|
|
10016
11384
|
console.log(pc.blue(`\u2139 Starting watch mode on [${input}]`));
|
|
10017
|
-
console.log(
|
|
11385
|
+
console.log(
|
|
11386
|
+
pc.dim(` \u2022 Targets to generate: ${options.target.join(", ")}`)
|
|
11387
|
+
);
|
|
10018
11388
|
console.log(pc.dim(` \u2022 Output directory: ${options.output}`));
|
|
10019
11389
|
try {
|
|
10020
11390
|
await generateSdk({ input, ...options, exitOnError: false });
|
|
@@ -10025,8 +11395,12 @@ function registerSdkWatchCommand(program3) {
|
|
|
10025
11395
|
if (eventType === "change") {
|
|
10026
11396
|
if (debounceTimeout) clearTimeout(debounceTimeout);
|
|
10027
11397
|
debounceTimeout = setTimeout(async () => {
|
|
10028
|
-
console.log(
|
|
10029
|
-
|
|
11398
|
+
console.log(
|
|
11399
|
+
pc.cyan(
|
|
11400
|
+
`
|
|
11401
|
+
\u2022 File change detected on [${input}], regenerating...`
|
|
11402
|
+
)
|
|
11403
|
+
);
|
|
10030
11404
|
try {
|
|
10031
11405
|
await generateSdk({ input, ...options, exitOnError: false });
|
|
10032
11406
|
} catch (err) {
|
|
@@ -10053,7 +11427,9 @@ var MigrationEngine = class {
|
|
|
10053
11427
|
description: `The method "${id}" has been removed from the client. Identify alternatives or remove calls to it.`
|
|
10054
11428
|
});
|
|
10055
11429
|
} else if (epDiff.type === "modified") {
|
|
10056
|
-
const signatureChanges = epDiff.changes.filter(
|
|
11430
|
+
const signatureChanges = epDiff.changes.filter(
|
|
11431
|
+
(c) => c.path.startsWith("pathParams.") || c.path.startsWith("queryParams.") || c.path.startsWith("requestBody")
|
|
11432
|
+
);
|
|
10057
11433
|
if (signatureChanges.length > 0) {
|
|
10058
11434
|
steps.push({
|
|
10059
11435
|
target: `client.${id}`,
|
|
@@ -10071,7 +11447,9 @@ var MigrationEngine = class {
|
|
|
10071
11447
|
description: `The interface/struct "${id}" is no longer exported by the SDK. inspect usage.`
|
|
10072
11448
|
});
|
|
10073
11449
|
} else if (typeDiff.type === "modified") {
|
|
10074
|
-
const removedFields = typeDiff.changes.filter(
|
|
11450
|
+
const removedFields = typeDiff.changes.filter(
|
|
11451
|
+
(c) => c.type === "removed" && c.path.startsWith("fields.")
|
|
11452
|
+
);
|
|
10075
11453
|
for (const change of removedFields) {
|
|
10076
11454
|
const fieldName = change.path.split(".").pop() || "";
|
|
10077
11455
|
steps.push({
|
|
@@ -10086,59 +11464,75 @@ var MigrationEngine = class {
|
|
|
10086
11464
|
}
|
|
10087
11465
|
};
|
|
10088
11466
|
function registerSdkMigrateCommand(program3) {
|
|
10089
|
-
program3.command("migrate").description(
|
|
10090
|
-
|
|
10091
|
-
|
|
10092
|
-
|
|
10093
|
-
|
|
10094
|
-
|
|
10095
|
-
|
|
10096
|
-
|
|
10097
|
-
|
|
10098
|
-
if (ext === "json" || ext === "yaml" || ext === "yml") {
|
|
10099
|
-
const parsed = ext === "json" ? JSON.parse(raw) : __require("yaml").parse(raw);
|
|
10100
|
-
ingested = ingestOpenApi(parsed, {});
|
|
10101
|
-
} else if (ext === "graphql" || ext === "gql") {
|
|
10102
|
-
ingested = await ingestGraphQL(raw, {});
|
|
10103
|
-
} else {
|
|
10104
|
-
throw new Error(`Unsupported schema format for ${filePath}`);
|
|
11467
|
+
program3.command("migrate").description(
|
|
11468
|
+
"Generate client migration steps and guides between two API schemas"
|
|
11469
|
+
).argument("<old>", "The old/previous schema file").argument("<new>", "The new/current schema file").option("--json", "Output migration guide as JSON", false).action(
|
|
11470
|
+
async (oldFile, newFile, options) => {
|
|
11471
|
+
try {
|
|
11472
|
+
if (!options.json) {
|
|
11473
|
+
console.log(
|
|
11474
|
+
pc.blue("\u2139 Initializing SDK client migration generator...\n")
|
|
11475
|
+
);
|
|
10105
11476
|
}
|
|
10106
|
-
|
|
10107
|
-
|
|
10108
|
-
|
|
10109
|
-
|
|
10110
|
-
|
|
10111
|
-
|
|
10112
|
-
|
|
10113
|
-
|
|
10114
|
-
|
|
10115
|
-
|
|
10116
|
-
|
|
10117
|
-
|
|
10118
|
-
|
|
10119
|
-
|
|
10120
|
-
|
|
10121
|
-
|
|
10122
|
-
|
|
10123
|
-
|
|
11477
|
+
const loadSchema = async (filePath) => {
|
|
11478
|
+
const ext = filePath.split(".").pop()?.toLowerCase() || "";
|
|
11479
|
+
const raw = readFileSync(filePath, "utf8");
|
|
11480
|
+
let ingested;
|
|
11481
|
+
if (ext === "json" || ext === "yaml" || ext === "yml") {
|
|
11482
|
+
const parsed = ext === "json" ? JSON.parse(raw) : __require("yaml").parse(raw);
|
|
11483
|
+
ingested = ingestOpenApi(parsed, {});
|
|
11484
|
+
} else if (ext === "graphql" || ext === "gql") {
|
|
11485
|
+
ingested = await ingestGraphQL(raw, {});
|
|
11486
|
+
} else {
|
|
11487
|
+
throw new Error(`Unsupported schema format for ${filePath}`);
|
|
11488
|
+
}
|
|
11489
|
+
return (await new CompilerPipeline().compile(ingested.schema)).schema;
|
|
11490
|
+
};
|
|
11491
|
+
const oldSchema = await loadSchema(oldFile);
|
|
11492
|
+
const newSchema = await loadSchema(newFile);
|
|
11493
|
+
const differ = new SchemaDiffer();
|
|
11494
|
+
const diffs = differ.diff(oldSchema, newSchema);
|
|
11495
|
+
const analyzer = new BreakingChangeAnalyzer();
|
|
11496
|
+
const report = analyzer.analyze(diffs);
|
|
11497
|
+
const migrator = new MigrationEngine();
|
|
11498
|
+
const steps = migrator.generateMigrationGuide(diffs, report);
|
|
11499
|
+
if (options.json) {
|
|
11500
|
+
console.log(JSON.stringify(steps, null, 2));
|
|
10124
11501
|
} else {
|
|
10125
|
-
|
|
10126
|
-
|
|
10127
|
-
|
|
10128
|
-
|
|
10129
|
-
console.log(
|
|
11502
|
+
console.log(pc.bold(`Migration Guide: ${oldFile} \u2192 ${newFile}`));
|
|
11503
|
+
console.log(pc.dim(`Total action items: ${steps.length}
|
|
11504
|
+
`));
|
|
11505
|
+
if (steps.length === 0) {
|
|
11506
|
+
console.log(
|
|
11507
|
+
pc.green(
|
|
11508
|
+
" \u2713 No client code migration is necessary. Upgrade is fully backward compatible."
|
|
11509
|
+
)
|
|
11510
|
+
);
|
|
11511
|
+
} else {
|
|
11512
|
+
for (const step of steps) {
|
|
11513
|
+
const symbol = step.action === "remove" ? "\u274C" : "\u26A0\uFE0F";
|
|
11514
|
+
console.log(
|
|
11515
|
+
` ${symbol} [${step.action.toUpperCase()}] Target: ${pc.cyan(step.target)}`
|
|
11516
|
+
);
|
|
11517
|
+
console.log(` ${step.description}`);
|
|
11518
|
+
console.log();
|
|
11519
|
+
}
|
|
10130
11520
|
}
|
|
10131
11521
|
}
|
|
11522
|
+
} catch (err) {
|
|
11523
|
+
console.error(
|
|
11524
|
+
pc.red(`
|
|
11525
|
+
\u2717 Migration generation failed: ${err.message}`)
|
|
11526
|
+
);
|
|
11527
|
+
process.exit(1);
|
|
10132
11528
|
}
|
|
10133
|
-
} catch (err) {
|
|
10134
|
-
console.error(pc.red(`
|
|
10135
|
-
\u2717 Migration generation failed: ${err.message}`));
|
|
10136
|
-
process.exit(1);
|
|
10137
11529
|
}
|
|
10138
|
-
|
|
11530
|
+
);
|
|
10139
11531
|
}
|
|
10140
11532
|
function registerSdkUpgradeCommand(program3) {
|
|
10141
|
-
program3.command("upgrade").description(
|
|
11533
|
+
program3.command("upgrade").description(
|
|
11534
|
+
"Upgrade the local SDK generation target tool and runtime dependencies"
|
|
11535
|
+
).option("--dry-run", "Show command simulation without installing", false).action(async (options) => {
|
|
10142
11536
|
console.log(pc.blue("\u2139 Checking for SDK runtime upgrades...\n"));
|
|
10143
11537
|
const cmd = "npm install @axiomify/sdk-runtime@latest --save";
|
|
10144
11538
|
if (options.dryRun) {
|
|
@@ -10162,25 +11556,31 @@ program2.name("axiomify").description("The official CLI for the Axiomify framewo
|
|
|
10162
11556
|
program2.command("init").description("Bootstrap a new Axiomify project").argument("[directory]", "Target directory").option("-f, --force", "Overwrite existing project files", false).action(
|
|
10163
11557
|
(directory, options) => initProject(directory, options)
|
|
10164
11558
|
);
|
|
10165
|
-
program2.command("dev").description("Start the development server with hot-reload").argument("[entry]", "Entry file", "src/index.ts").option(
|
|
11559
|
+
program2.command("dev").description("Start the development server with hot-reload").argument("[entry]", "Entry file", "src/index.ts").option(
|
|
11560
|
+
"--watch-sdk <langs...>",
|
|
11561
|
+
"Target languages to automatically regenerate SDKs on changes"
|
|
11562
|
+
).action((entry, options) => devServer(entry, options));
|
|
10166
11563
|
program2.command("build").description("Compile the application for production").argument("[entry]", "Entry file", "src/index.ts").action(buildProject);
|
|
10167
|
-
program2.command("routes").description("Inspect and list all registered HTTP + WebSocket routes").argument("[entry]", "Entry file", "src/index.ts").option(
|
|
11564
|
+
program2.command("routes").description("Inspect and list all registered HTTP + WebSocket routes").argument("[entry]", "Entry file", "src/index.ts").option(
|
|
11565
|
+
"--json",
|
|
11566
|
+
"Emit machine-readable JSON instead of the formatted table",
|
|
11567
|
+
false
|
|
11568
|
+
).option(
|
|
10168
11569
|
"-m, --method <list>",
|
|
10169
11570
|
"Comma-separated list of methods to include (e.g. GET,POST,WS)"
|
|
10170
11571
|
).option(
|
|
10171
11572
|
"-f, --filter <pattern>",
|
|
10172
11573
|
'Path filter \u2014 substring match, or glob with "*" (e.g. /api/v1/*)'
|
|
10173
|
-
).option(
|
|
10174
|
-
"-s, --sort <by>",
|
|
10175
|
-
'Sort routes by "method" or "path"',
|
|
10176
|
-
"path"
|
|
10177
|
-
).action(
|
|
11574
|
+
).option("-s, --sort <by>", 'Sort routes by "method" or "path"', "path").action(
|
|
10178
11575
|
(entry, options) => inspectRoutes(entry, options)
|
|
10179
11576
|
);
|
|
10180
11577
|
program2.command("openapi").description("Generate the OpenAPI spec from the app and emit it").argument("[entry]", "Entry file", "src/index.ts").option(
|
|
10181
11578
|
"-o, --output <file>",
|
|
10182
11579
|
"Write the spec to this file path instead of stdout"
|
|
10183
|
-
).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(
|
|
11580
|
+
).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(
|
|
11581
|
+
"--spec-version <version>",
|
|
11582
|
+
"Override info.version in the generated spec"
|
|
11583
|
+
).action(
|
|
10184
11584
|
(entry, options) => emitOpenApi(entry, {
|
|
10185
11585
|
...options,
|
|
10186
11586
|
// Map the CLI flag name (`spec-version` → camel `specVersion`) onto
|
|
@@ -10191,14 +11591,35 @@ program2.command("openapi").description("Generate the OpenAPI spec from the app
|
|
|
10191
11591
|
program2.command("check").description("Run a static production-readiness audit against the app").argument("[entry]", "Entry file", "src/index.ts").action(runCheck);
|
|
10192
11592
|
program2.command("doctor").description("Diagnose the host environment (Node, uWS, ports, dep drift)").action(runDoctor);
|
|
10193
11593
|
var scaffold = program2.command("scaffold").description("Generate boilerplate (routes, modules, plugins)");
|
|
10194
|
-
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(
|
|
11594
|
+
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(
|
|
11595
|
+
"--dir <dir>",
|
|
11596
|
+
"Directory under cwd to create the file in",
|
|
11597
|
+
"src/routes"
|
|
11598
|
+
).action(
|
|
10195
11599
|
(method, routePath, options) => scaffoldRoute(method, routePath, options)
|
|
10196
11600
|
);
|
|
10197
|
-
program2.command("migrate").description(
|
|
11601
|
+
program2.command("migrate").description(
|
|
11602
|
+
"v5 \u2192 v6 codemod: merge meta: fields into schema:, fix routePrefix \u2192 prefix, etc"
|
|
11603
|
+
).option("--dry-run", "Show the unified diff without writing", false).option(
|
|
11604
|
+
"--report-only",
|
|
11605
|
+
"Print a migration report and exit; do not write",
|
|
11606
|
+
false
|
|
11607
|
+
).option("--dir <dir>", "Directory to scan recursively", "src").action(
|
|
10198
11608
|
(options) => runMigrate(options)
|
|
10199
11609
|
);
|
|
10200
11610
|
var sdk = program2.command("sdk").description("Manage, generate, and diff type-safe SDKs");
|
|
10201
|
-
sdk.command("generate").description(
|
|
11611
|
+
sdk.command("generate").description(
|
|
11612
|
+
"Generate type-safe SDKs from an Axiomify app, OpenAPI spec, or GraphQL schema"
|
|
11613
|
+
).argument(
|
|
11614
|
+
"<input>",
|
|
11615
|
+
"Input file (e.g. src/index.ts, spec.json, schema.graphql)"
|
|
11616
|
+
).requiredOption(
|
|
11617
|
+
"-t, --target <langs...>",
|
|
11618
|
+
"Target languages (e.g. typescript python)"
|
|
11619
|
+
).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(
|
|
11620
|
+
"--no-runtime",
|
|
11621
|
+
"Do not include runtime dependencies (generate pure types)"
|
|
11622
|
+
).option("--dry-run", "Print generated files instead of writing them to disk").action(async (input, options) => {
|
|
10202
11623
|
await generateSdk({ input, ...options });
|
|
10203
11624
|
});
|
|
10204
11625
|
registerSdkDiffCommand(sdk);
|