@workos/oagen 0.17.3 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.mjs +158 -44
- package/dist/cli/index.mjs.map +1 -1
- package/dist/compat/index.d.mts +2 -2
- package/dist/{diff-DLqJSVYR.mjs → diff-JU1bdT5_.mjs} +107 -17
- package/dist/{diff-DLqJSVYR.mjs.map → diff-JU1bdT5_.mjs.map} +1 -1
- package/dist/{differ-fdF9qogA.d.mts → differ-CC65Efzt.d.mts} +2 -2
- package/dist/{differ-fdF9qogA.d.mts.map → differ-CC65Efzt.d.mts.map} +1 -1
- package/dist/index.d.mts +34 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +53 -29
- package/dist/index.mjs.map +1 -1
- package/dist/scripts/smoke/baseline.mjs +52 -28
- package/dist/scripts/smoke/baseline.mjs.map +1 -1
- package/dist/smoke.d.mts +2 -0
- package/dist/smoke.d.mts.map +1 -1
- package/dist/smoke.mjs +52 -28
- package/dist/smoke.mjs.map +1 -1
- package/dist/tree-sitter-DcUvm0KA.mjs.map +1 -1
- package/dist/{types-BL762XqW.d.mts → types-Cjh39AGQ.d.mts} +3 -1
- package/dist/{types-BL762XqW.d.mts.map → types-Cjh39AGQ.d.mts.map} +1 -1
- package/dist/verify/index.d.mts +2 -2
- package/dist/verify/index.mjs +1 -1
- package/package.json +1 -1
package/dist/cli/index.mjs
CHANGED
|
@@ -937,13 +937,16 @@ function deriveInlineVariantMapping(variants, discriminatorProperty, contextName
|
|
|
937
937
|
return mapping;
|
|
938
938
|
}
|
|
939
939
|
function extractEnum(name, schema) {
|
|
940
|
+
const values = (schema.enum ?? []).map((v) => ({
|
|
941
|
+
name: toUpperSnakeCase(String(v)),
|
|
942
|
+
value: typeof v === "number" ? v : String(v),
|
|
943
|
+
description: void 0
|
|
944
|
+
}));
|
|
945
|
+
const rawDefault = schema.default;
|
|
940
946
|
return {
|
|
941
947
|
name,
|
|
942
|
-
values
|
|
943
|
-
|
|
944
|
-
value: typeof v === "number" ? v : String(v),
|
|
945
|
-
description: void 0
|
|
946
|
-
}))
|
|
948
|
+
values,
|
|
949
|
+
default: rawDefault !== void 0 && values.some((v) => v.value === rawDefault) ? rawDefault : void 0
|
|
947
950
|
};
|
|
948
951
|
}
|
|
949
952
|
function extractModel(name, schema, schemas) {
|
|
@@ -1808,7 +1811,7 @@ const HTTP_METHODS = [
|
|
|
1808
1811
|
"options",
|
|
1809
1812
|
"trace"
|
|
1810
1813
|
];
|
|
1811
|
-
function extractOperations(paths, operationIdTransform) {
|
|
1814
|
+
function extractOperations(paths, operationIdTransform, componentSchemas) {
|
|
1812
1815
|
if (!paths) return {
|
|
1813
1816
|
services: [],
|
|
1814
1817
|
inlineModels: []
|
|
@@ -1821,7 +1824,7 @@ function extractOperations(paths, operationIdTransform) {
|
|
|
1821
1824
|
const op = pathItem[method];
|
|
1822
1825
|
if (!op) continue;
|
|
1823
1826
|
const serviceName = inferServiceName(path, op.tags?.[0]);
|
|
1824
|
-
const { operation, inlineModels: opModels } = buildOperation(method, path, op, pathLevelParams, operationIdTransform, serviceName);
|
|
1827
|
+
const { operation, inlineModels: opModels } = buildOperation(method, path, op, pathLevelParams, operationIdTransform, serviceName, componentSchemas);
|
|
1825
1828
|
inlineModels.push(...opModels);
|
|
1826
1829
|
const ops = serviceMap.get(serviceName) ?? [];
|
|
1827
1830
|
ops.push(operation);
|
|
@@ -2064,14 +2067,14 @@ function extractBodyParameterGroups(op, operationContext) {
|
|
|
2064
2067
|
}
|
|
2065
2068
|
return groups.length > 0 ? groups : void 0;
|
|
2066
2069
|
}
|
|
2067
|
-
function buildOperation(method, path, op, pathLevelParams, operationIdTransform, serviceName) {
|
|
2070
|
+
function buildOperation(method, path, op, pathLevelParams, operationIdTransform, serviceName, componentSchemas) {
|
|
2068
2071
|
const allParams = [...pathLevelParams, ...op.parameters ?? []];
|
|
2069
2072
|
const hasIdempotencyHeader = allParams.some((p) => p.in === "header" && p.name.toLowerCase() === "idempotency-key");
|
|
2070
2073
|
const opContext = serviceName;
|
|
2071
|
-
const pathParams = extractParams(allParams, "path", opContext);
|
|
2072
|
-
const queryParams = extractParams(allParams, "query", opContext);
|
|
2073
|
-
const headerParams = extractParams(allParams, "header", opContext).filter((p) => p.name.toLowerCase() !== "idempotency-key");
|
|
2074
|
-
const cookieParams = extractParams(allParams, "cookie", opContext);
|
|
2074
|
+
const pathParams = extractParams(allParams, "path", opContext, componentSchemas);
|
|
2075
|
+
const queryParams = extractParams(allParams, "query", opContext, componentSchemas);
|
|
2076
|
+
const headerParams = extractParams(allParams, "header", opContext, componentSchemas).filter((p) => p.name.toLowerCase() !== "idempotency-key");
|
|
2077
|
+
const cookieParams = extractParams(allParams, "cookie", opContext, componentSchemas);
|
|
2075
2078
|
const reqBodyModels = [];
|
|
2076
2079
|
const { body: requestBody, encoding: requestBodyEncoding } = extractRequestBody(op.requestBody, op, reqBodyModels);
|
|
2077
2080
|
const { response, successResponses, errors, inlineModels, isPaginated, dataPath: responseDataPath, itemType: responseItemType } = extractResponses(op.responses, op, path, method);
|
|
@@ -2143,21 +2146,42 @@ function buildDescription(summary, description) {
|
|
|
2143
2146
|
if (summary && description && summary !== description) return `${summary}\n\n${description}`;
|
|
2144
2147
|
return description ?? summary;
|
|
2145
2148
|
}
|
|
2146
|
-
function extractParams(params, location, operationContext) {
|
|
2147
|
-
return params.filter((p) => p.in === location).map((p) =>
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
type:
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2149
|
+
function extractParams(params, location, operationContext, componentSchemas) {
|
|
2150
|
+
return params.filter((p) => p.in === location).map((p) => {
|
|
2151
|
+
const refTarget = resolveParamSchemaRef(p.schema, componentSchemas);
|
|
2152
|
+
return {
|
|
2153
|
+
name: p.name,
|
|
2154
|
+
type: p.schema ? schemaToTypeRef(p.schema, p.name, operationContext ? toPascalCase(operationContext) : void 0) : {
|
|
2155
|
+
kind: "primitive",
|
|
2156
|
+
type: "string"
|
|
2157
|
+
},
|
|
2158
|
+
required: p.required ?? false,
|
|
2159
|
+
description: p.description,
|
|
2160
|
+
deprecated: p.deprecated || p.schema?.deprecated || refTarget?.deprecated || void 0,
|
|
2161
|
+
default: p.schema?.default ?? refTarget?.default,
|
|
2162
|
+
example: p.example ?? p.schema?.example ?? refTarget?.example,
|
|
2163
|
+
style: p.style,
|
|
2164
|
+
explode: p.explode
|
|
2165
|
+
};
|
|
2166
|
+
});
|
|
2167
|
+
}
|
|
2168
|
+
/**
|
|
2169
|
+
* If a parameter's schema is a `$ref` to `#/components/schemas/X`, return the
|
|
2170
|
+
* referenced component schema. Used to surface schema-level metadata (default,
|
|
2171
|
+
* example, deprecated) that wouldn't otherwise be visible at the param level.
|
|
2172
|
+
*
|
|
2173
|
+
* Refs are not pre-resolved by the bundler (`dereference: false` in refs.ts),
|
|
2174
|
+
* so without this, a param like `schema: { $ref: '.../PaginationOrder' }`
|
|
2175
|
+
* silently loses the target's `default: desc` and the SDK stops emitting the
|
|
2176
|
+
* spec-mandated default value in generated method signatures.
|
|
2177
|
+
*/
|
|
2178
|
+
function resolveParamSchemaRef(schema, componentSchemas) {
|
|
2179
|
+
if (!schema || !componentSchemas) return void 0;
|
|
2180
|
+
const ref = schema.$ref;
|
|
2181
|
+
if (!ref) return void 0;
|
|
2182
|
+
const match = /^#\/components\/schemas\/(.+)$/.exec(ref);
|
|
2183
|
+
if (!match) return void 0;
|
|
2184
|
+
return componentSchemas[match[1]];
|
|
2161
2185
|
}
|
|
2162
2186
|
function extractRequestBody(body, op, inlineModels) {
|
|
2163
2187
|
if (!body?.content) return {};
|
|
@@ -2511,7 +2535,7 @@ async function parseSpec(specPath, options) {
|
|
|
2511
2535
|
const version = spec.openapi ?? "";
|
|
2512
2536
|
if (!version.startsWith("3.")) throw new SpecParseError(`Unsupported OpenAPI version: ${version}. oagen requires OpenAPI 3.x`, `Update the spec to OpenAPI 3.0 or 3.1. If you are using Swagger 2.x, convert it first with \`npx swagger2openapi ${specPath}\`.`);
|
|
2513
2537
|
const { models, enums } = extractSchemas(spec.components?.schemas, { schemaNameTransform: options?.schemaNameTransform });
|
|
2514
|
-
const { services, inlineModels } = extractOperations(spec.paths, options?.operationIdTransform);
|
|
2538
|
+
const { services, inlineModels } = extractOperations(spec.paths, options?.operationIdTransform, spec.components?.schemas);
|
|
2515
2539
|
clearSchemaNameTransform();
|
|
2516
2540
|
const finalModels = collapseJsonSuffixModels(mergeFieldInlineModels(mergeInlineResponseModels(models, inlineModels), extractInlineModelsFromSchemas(spec.components?.schemas)), services);
|
|
2517
2541
|
collectInlineEnumsFromModels(finalModels, enums);
|
|
@@ -6220,6 +6244,11 @@ function classifyFieldChange(kind, fieldName, isRequired) {
|
|
|
6220
6244
|
fieldName,
|
|
6221
6245
|
classification: "breaking"
|
|
6222
6246
|
};
|
|
6247
|
+
case "field-format-changed": return {
|
|
6248
|
+
kind,
|
|
6249
|
+
fieldName,
|
|
6250
|
+
classification: "additive"
|
|
6251
|
+
};
|
|
6223
6252
|
case "field-required-changed": return {
|
|
6224
6253
|
kind,
|
|
6225
6254
|
fieldName,
|
|
@@ -6250,11 +6279,21 @@ function classifyParamChange(kind, paramName, isRequired) {
|
|
|
6250
6279
|
paramName,
|
|
6251
6280
|
classification: "breaking"
|
|
6252
6281
|
};
|
|
6282
|
+
case "param-format-changed": return {
|
|
6283
|
+
kind,
|
|
6284
|
+
paramName,
|
|
6285
|
+
classification: "additive"
|
|
6286
|
+
};
|
|
6253
6287
|
case "param-required-changed": return {
|
|
6254
6288
|
kind,
|
|
6255
6289
|
paramName,
|
|
6256
6290
|
classification: isRequired ? "breaking" : "additive"
|
|
6257
6291
|
};
|
|
6292
|
+
case "param-default-changed": return {
|
|
6293
|
+
kind,
|
|
6294
|
+
paramName,
|
|
6295
|
+
classification: "breaking"
|
|
6296
|
+
};
|
|
6258
6297
|
}
|
|
6259
6298
|
}
|
|
6260
6299
|
//#endregion
|
|
@@ -6298,7 +6337,11 @@ function diffFields(oldModel, newModel) {
|
|
|
6298
6337
|
for (const [name, newField] of newByName) {
|
|
6299
6338
|
const oldField = oldByName.get(name);
|
|
6300
6339
|
if (!oldField) continue;
|
|
6301
|
-
if (!typeRefsEqual(oldField.type, newField.type)) changes.push({
|
|
6340
|
+
if (!typeRefsEqual(oldField.type, newField.type)) if (primitivesDifferOnlyByFormat(oldField.type, newField.type)) changes.push({
|
|
6341
|
+
...classifyFieldChange("field-format-changed", name),
|
|
6342
|
+
details: formatChangeDetails(oldField.type, newField.type)
|
|
6343
|
+
});
|
|
6344
|
+
else changes.push({
|
|
6302
6345
|
kind: "field-type-changed",
|
|
6303
6346
|
fieldName: name,
|
|
6304
6347
|
classification: "breaking",
|
|
@@ -6309,6 +6352,23 @@ function diffFields(oldModel, newModel) {
|
|
|
6309
6352
|
}
|
|
6310
6353
|
return changes;
|
|
6311
6354
|
}
|
|
6355
|
+
/**
|
|
6356
|
+
* True when both refs are primitives with the same base `type` but different
|
|
6357
|
+
* `format`. Used to downgrade format-only diffs from breaking type changes to
|
|
6358
|
+
* additive `field-format-changed` / `param-format-changed` events: the wire
|
|
6359
|
+
* base type is unchanged, so the diff is a hint to language emitters rather
|
|
6360
|
+
* than a source-level break.
|
|
6361
|
+
*/
|
|
6362
|
+
function primitivesDifferOnlyByFormat(a, b) {
|
|
6363
|
+
if (a.kind !== "primitive" || b.kind !== "primitive") return false;
|
|
6364
|
+
if (a.type !== b.type) return false;
|
|
6365
|
+
return (a.format ?? "") !== (b.format ?? "");
|
|
6366
|
+
}
|
|
6367
|
+
function formatChangeDetails(a, b) {
|
|
6368
|
+
const oldFmt = a.kind === "primitive" ? a.format : void 0;
|
|
6369
|
+
const newFmt = b.kind === "primitive" ? b.format : void 0;
|
|
6370
|
+
return `format ${oldFmt ?? "<unset>"} → ${newFmt ?? "<unset>"}`;
|
|
6371
|
+
}
|
|
6312
6372
|
function typeRefsEqual(a, b) {
|
|
6313
6373
|
if (a.kind !== b.kind) return false;
|
|
6314
6374
|
switch (a.kind) {
|
|
@@ -6410,28 +6470,57 @@ function classifyErrorsChange(oldErrors, newErrors) {
|
|
|
6410
6470
|
}
|
|
6411
6471
|
function diffParams(oldOp, newOp) {
|
|
6412
6472
|
const changes = [];
|
|
6473
|
+
const tagged = (loc, params) => params.map((p) => ({
|
|
6474
|
+
p,
|
|
6475
|
+
loc
|
|
6476
|
+
}));
|
|
6413
6477
|
const allOldParams = [
|
|
6414
|
-
...oldOp.pathParams,
|
|
6415
|
-
...oldOp.queryParams,
|
|
6416
|
-
...oldOp.headerParams
|
|
6478
|
+
...tagged("path", oldOp.pathParams),
|
|
6479
|
+
...tagged("query", oldOp.queryParams),
|
|
6480
|
+
...tagged("header", oldOp.headerParams)
|
|
6417
6481
|
];
|
|
6418
6482
|
const allNewParams = [
|
|
6419
|
-
...newOp.pathParams,
|
|
6420
|
-
...newOp.queryParams,
|
|
6421
|
-
...newOp.headerParams
|
|
6483
|
+
...tagged("path", newOp.pathParams),
|
|
6484
|
+
...tagged("query", newOp.queryParams),
|
|
6485
|
+
...tagged("header", newOp.headerParams)
|
|
6422
6486
|
];
|
|
6423
|
-
const oldByName = new Map(allOldParams.map((
|
|
6424
|
-
const newByName = new Map(allNewParams.map((
|
|
6425
|
-
for (const [name,
|
|
6487
|
+
const oldByName = new Map(allOldParams.map((e) => [e.p.name, e]));
|
|
6488
|
+
const newByName = new Map(allNewParams.map((e) => [e.p.name, e]));
|
|
6489
|
+
for (const [name, entry] of newByName) if (!oldByName.has(name)) changes.push(classifyParamChange("param-added", name, entry.p.required));
|
|
6426
6490
|
for (const [name] of oldByName) if (!newByName.has(name)) changes.push(classifyParamChange("param-removed", name));
|
|
6427
|
-
for (const [name,
|
|
6428
|
-
const
|
|
6429
|
-
if (!
|
|
6430
|
-
if (!typeRefsEqual(
|
|
6431
|
-
|
|
6491
|
+
for (const [name, newEntry] of newByName) {
|
|
6492
|
+
const oldEntry = oldByName.get(name);
|
|
6493
|
+
if (!oldEntry) continue;
|
|
6494
|
+
if (!typeRefsEqual(oldEntry.p.type, newEntry.p.type)) if (primitivesDifferOnlyByFormat(oldEntry.p.type, newEntry.p.type)) {
|
|
6495
|
+
const change = classifyParamChange("param-format-changed", name);
|
|
6496
|
+
change.details = formatChangeDetails(oldEntry.p.type, newEntry.p.type);
|
|
6497
|
+
changes.push(change);
|
|
6498
|
+
} else changes.push(classifyParamChange("param-type-changed", name));
|
|
6499
|
+
if (oldEntry.p.required !== newEntry.p.required) changes.push(classifyParamChange("param-required-changed", name, newEntry.p.required));
|
|
6500
|
+
const oldDefault = serializeDefault(oldEntry.p.default);
|
|
6501
|
+
const newDefault = serializeDefault(newEntry.p.default);
|
|
6502
|
+
if (oldDefault !== newDefault) {
|
|
6503
|
+
const change = classifyParamChange("param-default-changed", name);
|
|
6504
|
+
change.oldDefault = oldDefault;
|
|
6505
|
+
change.newDefault = newDefault;
|
|
6506
|
+
change.paramLocation = newEntry.loc;
|
|
6507
|
+
change.details = `default ${oldDefault ?? "<unset>"} → ${newDefault ?? "<unset>"}`;
|
|
6508
|
+
changes.push(change);
|
|
6509
|
+
}
|
|
6432
6510
|
}
|
|
6433
6511
|
return changes;
|
|
6434
6512
|
}
|
|
6513
|
+
function serializeDefault(value) {
|
|
6514
|
+
if (value === void 0) return null;
|
|
6515
|
+
if (value === null) return "null";
|
|
6516
|
+
if (typeof value === "string") return value;
|
|
6517
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
6518
|
+
try {
|
|
6519
|
+
return JSON.stringify(value);
|
|
6520
|
+
} catch {
|
|
6521
|
+
return String(value);
|
|
6522
|
+
}
|
|
6523
|
+
}
|
|
6435
6524
|
//#endregion
|
|
6436
6525
|
//#region src/differ/services.ts
|
|
6437
6526
|
function diffServices(oldServices, newServices) {
|
|
@@ -6463,13 +6552,38 @@ function diffSpecs(oldSpec, newSpec) {
|
|
|
6463
6552
|
...diffEnums(oldSpec.enums, newSpec.enums),
|
|
6464
6553
|
...diffServices(oldSpec.services, newSpec.services)
|
|
6465
6554
|
];
|
|
6555
|
+
const behaviorChanges = collectBehaviorChanges(changes);
|
|
6466
6556
|
return {
|
|
6467
6557
|
oldVersion: oldSpec.version,
|
|
6468
6558
|
newVersion: newSpec.version,
|
|
6469
6559
|
changes,
|
|
6470
|
-
|
|
6560
|
+
behaviorChanges,
|
|
6561
|
+
summary: {
|
|
6562
|
+
...summarize(changes),
|
|
6563
|
+
behaviorChanges: behaviorChanges.length
|
|
6564
|
+
}
|
|
6471
6565
|
};
|
|
6472
6566
|
}
|
|
6567
|
+
function collectBehaviorChanges(changes) {
|
|
6568
|
+
const out = [];
|
|
6569
|
+
for (const c of changes) {
|
|
6570
|
+
if (c.kind !== "operation-modified") continue;
|
|
6571
|
+
for (const pc of c.paramChanges) {
|
|
6572
|
+
if (pc.kind !== "param-default-changed") continue;
|
|
6573
|
+
out.push({
|
|
6574
|
+
kind: "param-default-changed",
|
|
6575
|
+
serviceName: c.serviceName,
|
|
6576
|
+
operationName: c.operationName,
|
|
6577
|
+
paramName: pc.paramName,
|
|
6578
|
+
paramLocation: pc.paramLocation ?? "query",
|
|
6579
|
+
oldDefault: pc.oldDefault ?? null,
|
|
6580
|
+
newDefault: pc.newDefault ?? null,
|
|
6581
|
+
classification: "breaking"
|
|
6582
|
+
});
|
|
6583
|
+
}
|
|
6584
|
+
}
|
|
6585
|
+
return out;
|
|
6586
|
+
}
|
|
6473
6587
|
function diffEnums(oldEnums, newEnums) {
|
|
6474
6588
|
const changes = [];
|
|
6475
6589
|
const oldByName = new Map(oldEnums.map((e) => [e.name, e]));
|