@workos/oagen-emitters 0.7.5 → 0.8.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/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +19 -0
- package/dist/index.mjs +1 -1
- package/dist/{plugin-BoTAX4nl.mjs → plugin-DOE0FqrZ.mjs} +164 -17
- package/dist/plugin-DOE0FqrZ.mjs.map +1 -0
- package/dist/plugin.mjs +1 -1
- package/package.json +2 -2
- package/src/dotnet/index.ts +8 -4
- package/src/dotnet/models.ts +101 -1
- package/src/dotnet/type-map.ts +12 -3
- package/src/go/fixtures.ts +10 -2
- package/src/go/models.ts +67 -1
- package/src/go/resources.ts +5 -3
- package/src/go/type-map.ts +24 -1
- package/src/kotlin/type-map.ts +11 -2
- package/src/php/models.ts +12 -0
- package/src/python/client.ts +4 -6
- package/src/python/models.ts +45 -1
- package/src/ruby/models.ts +24 -5
- package/test/go/resources.test.ts +37 -1
- package/test/kotlin/resources.test.ts +29 -0
- package/dist/plugin-BoTAX4nl.mjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.8.1](https://github.com/workos/oagen-emitters/compare/v0.8.0...v0.8.1) (2026-05-05)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **emitters:** repair regressions surfaced by shared-schema spec rev ([#84](https://github.com/workos/oagen-emitters/issues/84)) ([a04d317](https://github.com/workos/oagen-emitters/commit/a04d3170707adea21f19632f2a149b735be91d50))
|
|
9
|
+
|
|
10
|
+
## [0.8.0](https://github.com/workos/oagen-emitters/compare/v0.7.5...v0.8.0) (2026-05-05)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* **emitters:** dispatch field-level discriminated unions and drop dead request bodies ([#81](https://github.com/workos/oagen-emitters/issues/81)) ([4d38d24](https://github.com/workos/oagen-emitters/commit/4d38d249dcc7079e2a61d8faeabb681d6798618f))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* **go:** stop SSO auth code leaking into request URL ([#83](https://github.com/workos/oagen-emitters/issues/83)) ([bc520e6](https://github.com/workos/oagen-emitters/commit/bc520e6a3d966abdf785262e5c49736b5e105b92))
|
|
21
|
+
|
|
3
22
|
## [0.7.5](https://github.com/workos/oagen-emitters/compare/v0.7.4...v0.7.5) (2026-05-03)
|
|
4
23
|
|
|
5
24
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as nodeEmitter, a as rustExtractor, c as pythonExtractor, d as rubyEmitter, f as kotlinEmitter, g as pythonEmitter, h as phpEmitter, i as kotlinExtractor, l as rubyExtractor, m as goEmitter, n as elixirExtractor, o as goExtractor, p as dotnetEmitter, r as dotnetExtractor, s as phpExtractor, t as workosEmittersPlugin, u as nodeExtractor } from "./plugin-
|
|
1
|
+
import { _ as nodeEmitter, a as rustExtractor, c as pythonExtractor, d as rubyEmitter, f as kotlinEmitter, g as pythonEmitter, h as phpEmitter, i as kotlinExtractor, l as rubyExtractor, m as goEmitter, n as elixirExtractor, o as goExtractor, p as dotnetEmitter, r as dotnetExtractor, s as phpExtractor, t as workosEmittersPlugin, u as nodeExtractor } from "./plugin-DOE0FqrZ.mjs";
|
|
2
2
|
export { dotnetEmitter, dotnetExtractor, elixirExtractor, goEmitter, goExtractor, kotlinEmitter, kotlinExtractor, nodeEmitter, nodeExtractor, phpEmitter, phpExtractor, pythonEmitter, pythonExtractor, rubyEmitter, rubyExtractor, rustExtractor, workosEmittersPlugin };
|
|
@@ -7456,6 +7456,12 @@ function generateModels$5(models, ctx) {
|
|
|
7456
7456
|
const dirName = mountDirMap.get(service.name) ?? resolveDir(service.name);
|
|
7457
7457
|
serviceDirModelPaths.add(`src/${ctx.namespace}/${dirName}/models`);
|
|
7458
7458
|
}
|
|
7459
|
+
for (const dirPath of serviceDirModelPaths) if (!symbolsByDir.has(dirPath)) files.push({
|
|
7460
|
+
path: `${dirPath}/__init__.py`,
|
|
7461
|
+
content: "",
|
|
7462
|
+
integrateTarget: true,
|
|
7463
|
+
overwriteExisting: true
|
|
7464
|
+
});
|
|
7459
7465
|
for (const [dirPath, names] of symbolsByDir) {
|
|
7460
7466
|
const uniqueNames = [...new Set(names)].sort();
|
|
7461
7467
|
const importLines = [];
|
|
@@ -7633,6 +7639,17 @@ function deserializeField(ref, accessor, isRequired, walrusVar = "_v") {
|
|
|
7633
7639
|
case "union": {
|
|
7634
7640
|
const modelVariants = (ref.variants ?? []).filter((v) => v.kind === "model");
|
|
7635
7641
|
const uniqueModels = [...new Set(modelVariants.map((v) => v.name))];
|
|
7642
|
+
if (ref.discriminator && ref.discriminator.mapping) {
|
|
7643
|
+
const entries = Object.entries(ref.discriminator.mapping);
|
|
7644
|
+
if (entries.length > 0) {
|
|
7645
|
+
const dispatchMap = entries.map(([value, modelName]) => `"${value}": ${className$5(modelName)}`).join(", ");
|
|
7646
|
+
const dataExpr = isRequired ? accessor : walrusVar;
|
|
7647
|
+
const dataCast = `cast(Dict[str, Any], ${dataExpr})`;
|
|
7648
|
+
const branch = `(_disc.from_dict(${dataCast}) if (_disc := ${`{${dispatchMap}}.get(cast(str, ${dataCast}.get("${ref.discriminator.property}")))`}) is not None else ${dataExpr})`;
|
|
7649
|
+
if (isRequired) return branch;
|
|
7650
|
+
return `(${branch}) if (${walrusVar} := ${accessor}) is not None else None`;
|
|
7651
|
+
}
|
|
7652
|
+
}
|
|
7636
7653
|
if (uniqueModels.length === 1) return deserializeField({
|
|
7637
7654
|
kind: "model",
|
|
7638
7655
|
name: uniqueModels[0]
|
|
@@ -7654,6 +7671,7 @@ function serializeField(ref, accessor) {
|
|
|
7654
7671
|
case "union": {
|
|
7655
7672
|
const modelVariants = (ref.variants ?? []).filter((v) => v.kind === "model");
|
|
7656
7673
|
if ([...new Set(modelVariants.map((v) => v.name))].length === 1) return `${accessor}.to_dict()`;
|
|
7674
|
+
if (ref.discriminator && ref.discriminator.mapping && modelVariants.length > 0) return `${accessor}.to_dict() if hasattr(${accessor}, "to_dict") else ${accessor}`;
|
|
7657
7675
|
return accessor;
|
|
7658
7676
|
}
|
|
7659
7677
|
default: return accessor;
|
|
@@ -9056,11 +9074,6 @@ function generateServiceInits(spec, ctx) {
|
|
|
9056
9074
|
integrateTarget: true,
|
|
9057
9075
|
overwriteExisting: true
|
|
9058
9076
|
});
|
|
9059
|
-
files.push({
|
|
9060
|
-
path: `src/${ctx.namespace}/${dirName}/models/__init__.py`,
|
|
9061
|
-
content: "",
|
|
9062
|
-
skipIfExists: true
|
|
9063
|
-
});
|
|
9064
9077
|
}
|
|
9065
9078
|
return files;
|
|
9066
9079
|
}
|
|
@@ -10781,6 +10794,13 @@ function generateFromArrayValue(ref, accessor) {
|
|
|
10781
10794
|
return accessor;
|
|
10782
10795
|
case "nullable": return generateFromArrayValue(ref.inner, accessor);
|
|
10783
10796
|
case "union": {
|
|
10797
|
+
if (ref.discriminator && ref.discriminator.mapping) {
|
|
10798
|
+
const entries = Object.entries(ref.discriminator.mapping);
|
|
10799
|
+
if (entries.length > 0) {
|
|
10800
|
+
const arms = entries.map(([value, modelName]) => `'${value}' => ${className$4(modelName)}::fromArray(${accessor})`).join(", ");
|
|
10801
|
+
return `match (${accessor}['${ref.discriminator.property}'] ?? null) { ${arms}, default => ${accessor} }`;
|
|
10802
|
+
}
|
|
10803
|
+
}
|
|
10784
10804
|
const resolved = resolveDegenerateUnion(ref);
|
|
10785
10805
|
if (resolved) return generateFromArrayValue(resolved, accessor);
|
|
10786
10806
|
return accessor;
|
|
@@ -12442,11 +12462,70 @@ function joinUnionVariants$2(_ref, variants) {
|
|
|
12442
12462
|
if (_ref.compositionKind === "allOf") return variants[0] ?? "interface{}";
|
|
12443
12463
|
const unique = [...new Set(variants)];
|
|
12444
12464
|
if (unique.length === 1) return unique[0];
|
|
12465
|
+
if (_ref.discriminator && _ref.discriminator.mapping) {
|
|
12466
|
+
const resolverName = unionResolverName(_ref);
|
|
12467
|
+
if (resolverName) return resolverName;
|
|
12468
|
+
}
|
|
12445
12469
|
return "interface{}";
|
|
12446
12470
|
}
|
|
12471
|
+
/**
|
|
12472
|
+
* Pick a stable type name for a discriminated union's runtime resolver. Today
|
|
12473
|
+
* we emit no resolver struct, so we treat the union's first model variant as
|
|
12474
|
+
* the public type — matching the pre-discriminator behavior where Go just
|
|
12475
|
+
* referenced one variant directly. The Owner field stays typed, callers
|
|
12476
|
+
* can still inspect Type to detect the user variant (data loss on
|
|
12477
|
+
* non-overlapping fields like organization_id is documented in the SDK
|
|
12478
|
+
* compat report rather than fixed in the emitter — Go callers who need the
|
|
12479
|
+
* user-only fields can json.Unmarshal the raw payload manually).
|
|
12480
|
+
*/
|
|
12481
|
+
function unionResolverName(ref) {
|
|
12482
|
+
for (const v of ref.variants) if (v.kind === "model") return `*${className$3(v.name)}`;
|
|
12483
|
+
return null;
|
|
12484
|
+
}
|
|
12447
12485
|
//#endregion
|
|
12448
12486
|
//#region src/go/models.ts
|
|
12449
12487
|
/**
|
|
12488
|
+
* Collect names of models that are referenced **only** as a named request body
|
|
12489
|
+
* model on an operation, with no other consumers (response types, pagination
|
|
12490
|
+
* item types, error types, or fields on other models).
|
|
12491
|
+
*
|
|
12492
|
+
* The Go emitter synthesizes a `{Service}{Method}Params` struct from those
|
|
12493
|
+
* request bodies (see `resources.ts:392`), and the method signature uses the
|
|
12494
|
+
* synthesized struct — never the named model. So emitting the named model in
|
|
12495
|
+
* `models.go` would leave callers with a duplicate, unused struct (the bug
|
|
12496
|
+
* surfaced in workos-go#544 with `CreateUserAPIKey` /
|
|
12497
|
+
* `UserManagementCreateAPIKeyParams`).
|
|
12498
|
+
*
|
|
12499
|
+
* Models in this set are skipped during model emission. Callers parameterize
|
|
12500
|
+
* the API surface through `*Params` exclusively, which is the sole consumer
|
|
12501
|
+
* of the spec's named request body schema.
|
|
12502
|
+
*/
|
|
12503
|
+
function collectRequestBodyOnlyModelNames$1(services, models) {
|
|
12504
|
+
const requestBodyNames = /* @__PURE__ */ new Set();
|
|
12505
|
+
const otherReferences = /* @__PURE__ */ new Set();
|
|
12506
|
+
const collect = (ref, into) => {
|
|
12507
|
+
if (!ref) return;
|
|
12508
|
+
walkTypeRef(ref, { model: (r) => into.add(r.name) });
|
|
12509
|
+
};
|
|
12510
|
+
for (const service of services) for (const op of service.operations) {
|
|
12511
|
+
if (op.requestBody?.kind === "model") requestBodyNames.add(op.requestBody.name);
|
|
12512
|
+
collect(op.response, otherReferences);
|
|
12513
|
+
if (op.pagination) collect(op.pagination.itemType, otherReferences);
|
|
12514
|
+
for (const p of [
|
|
12515
|
+
...op.pathParams,
|
|
12516
|
+
...op.queryParams,
|
|
12517
|
+
...op.headerParams,
|
|
12518
|
+
...op.cookieParams ?? []
|
|
12519
|
+
]) collect(p.type, otherReferences);
|
|
12520
|
+
if (op.successResponses) for (const sr of op.successResponses) collect(sr.type, otherReferences);
|
|
12521
|
+
for (const err of op.errors) if (err.type) collect(err.type, otherReferences);
|
|
12522
|
+
}
|
|
12523
|
+
for (const model of models) for (const field of model.fields) collect(field.type, otherReferences);
|
|
12524
|
+
const result = /* @__PURE__ */ new Set();
|
|
12525
|
+
for (const name of requestBodyNames) if (!otherReferences.has(name)) result.add(name);
|
|
12526
|
+
return result;
|
|
12527
|
+
}
|
|
12528
|
+
/**
|
|
12450
12529
|
* Generate Go struct definitions from IR Models.
|
|
12451
12530
|
* All models go into a single models.go file for the flat package.
|
|
12452
12531
|
*/
|
|
@@ -12456,10 +12535,12 @@ function generateModels$3(models, ctx) {
|
|
|
12456
12535
|
const lines = [];
|
|
12457
12536
|
lines.push(`package ${ctx.namespace}`);
|
|
12458
12537
|
lines.push("");
|
|
12538
|
+
const requestBodyOnly = collectRequestBodyOnlyModelNames$1(ctx.spec.services, models);
|
|
12459
12539
|
const modelHashMap = /* @__PURE__ */ new Map();
|
|
12460
12540
|
const hashGroups = /* @__PURE__ */ new Map();
|
|
12461
12541
|
for (const model of models) {
|
|
12462
12542
|
if (isListWrapperModel(model) || isListMetadataModel(model)) continue;
|
|
12543
|
+
if (requestBodyOnly.has(model.name)) continue;
|
|
12463
12544
|
const hash = structuralHash$2(model);
|
|
12464
12545
|
modelHashMap.set(model.name, hash);
|
|
12465
12546
|
if (!hashGroups.has(hash)) hashGroups.set(hash, []);
|
|
@@ -12476,6 +12557,7 @@ function generateModels$3(models, ctx) {
|
|
|
12476
12557
|
const batchedAliases = /* @__PURE__ */ new Set();
|
|
12477
12558
|
for (const model of models) {
|
|
12478
12559
|
if (isListWrapperModel(model) || isListMetadataModel(model)) continue;
|
|
12560
|
+
if (requestBodyOnly.has(model.name)) continue;
|
|
12479
12561
|
const structName = className$3(model.name);
|
|
12480
12562
|
const canonicalName = aliasOf.get(model.name);
|
|
12481
12563
|
if (canonicalName) {
|
|
@@ -13242,7 +13324,7 @@ function generateParamsStruct(mountName, method, op, plan, ctx, resolvedOp) {
|
|
|
13242
13324
|
emittedFields.add(goField);
|
|
13243
13325
|
const goType = !field.required ? makeOptional(mapTypeRef$3(field.type)) : mapTypeRef$3(field.type);
|
|
13244
13326
|
const jsonTag = field.required ? `json:"${field.name}"` : `json:"${field.name},omitempty"`;
|
|
13245
|
-
const urlTag =
|
|
13327
|
+
const urlTag = " url:\"-\"";
|
|
13246
13328
|
if (field.description) {
|
|
13247
13329
|
const fdLines = field.description.split("\n").filter((l) => l.trim());
|
|
13248
13330
|
lines.push(`\t// ${fieldDocComment(goField, fdLines[0])}`);
|
|
@@ -13991,12 +14073,16 @@ function generateFixtures$1(spec) {
|
|
|
13991
14073
|
content: JSON.stringify(fixture, null, 2)
|
|
13992
14074
|
});
|
|
13993
14075
|
}
|
|
14076
|
+
const seenListPaths = /* @__PURE__ */ new Set();
|
|
13994
14077
|
for (const service of spec.services) for (const op of service.operations) if (op.pagination) {
|
|
13995
14078
|
let itemModel = op.pagination.itemType.kind === "model" ? modelMap.get(op.pagination.itemType.name) : null;
|
|
13996
14079
|
if (itemModel) {
|
|
13997
14080
|
const unwrapped = unwrapListModel$1(itemModel, modelMap);
|
|
13998
14081
|
if (unwrapped) itemModel = unwrapped;
|
|
13999
14082
|
if (itemModel.fields.length === 0) continue;
|
|
14083
|
+
const path = `testdata/list_${fileName$1(itemModel.name)}.json`;
|
|
14084
|
+
if (seenListPaths.has(path)) continue;
|
|
14085
|
+
seenListPaths.add(path);
|
|
14000
14086
|
const listFixture = {
|
|
14001
14087
|
data: [generateModelFixture$1(itemModel, modelMap, enumMap)],
|
|
14002
14088
|
list_metadata: {
|
|
@@ -14005,7 +14091,7 @@ function generateFixtures$1(spec) {
|
|
|
14005
14091
|
}
|
|
14006
14092
|
};
|
|
14007
14093
|
files.push({
|
|
14008
|
-
path
|
|
14094
|
+
path,
|
|
14009
14095
|
content: JSON.stringify(listFixture, null, 2)
|
|
14010
14096
|
});
|
|
14011
14097
|
}
|
|
@@ -15094,9 +15180,8 @@ const discriminatedUnions$1 = /* @__PURE__ */ new Map();
|
|
|
15094
15180
|
function joinUnionVariants$1(_ref, variants) {
|
|
15095
15181
|
if (_ref.compositionKind === "allOf") return variants[0] ?? "object";
|
|
15096
15182
|
const unique = [...new Set(variants)];
|
|
15097
|
-
if (unique.length === 1) return unique[0];
|
|
15098
15183
|
if (_ref.discriminator && _ref.discriminator.mapping) {
|
|
15099
|
-
const baseName = unique[0];
|
|
15184
|
+
const baseName = _ref.variants.filter((v) => v.kind === "model").map((v) => v.kind === "model" ? v.name : "").filter(Boolean)[0] ?? unique[0];
|
|
15100
15185
|
discriminatedUnions$1.set(baseName, {
|
|
15101
15186
|
property: _ref.discriminator.property,
|
|
15102
15187
|
mapping: _ref.discriminator.mapping,
|
|
@@ -15104,6 +15189,7 @@ function joinUnionVariants$1(_ref, variants) {
|
|
|
15104
15189
|
});
|
|
15105
15190
|
return "object";
|
|
15106
15191
|
}
|
|
15192
|
+
if (unique.length === 1) return unique[0];
|
|
15107
15193
|
if (unique.length >= 2 && unique.length <= 9) return `OneOf.OneOf<${unique.join(", ")}>`;
|
|
15108
15194
|
if (unique.length >= 10) console.warn(`[oagen:dotnet] Union with ${unique.length} variants exceeds OneOf<T0..T8> arity; falling back to object. Variants: ${unique.join(", ")}`);
|
|
15109
15195
|
return "object";
|
|
@@ -15121,6 +15207,7 @@ function generateModels$2(models, ctx, discCtx) {
|
|
|
15121
15207
|
for (const e of ctx.spec.enums) if (e.values.length === 1) enumConstByName.set(e.name, String(e.values[0].value));
|
|
15122
15208
|
const files = [];
|
|
15123
15209
|
primeModelAliases(models);
|
|
15210
|
+
const requestBodyOnlyNames = collectRequestBodyOnlyModelNames(ctx.spec.services, models);
|
|
15124
15211
|
const baseFieldLookup = /* @__PURE__ */ new Map();
|
|
15125
15212
|
if (discCtx) {
|
|
15126
15213
|
for (const model of models) if (discCtx.discriminatorBases.has(model.name)) {
|
|
@@ -15131,6 +15218,7 @@ function generateModels$2(models, ctx, discCtx) {
|
|
|
15131
15218
|
}
|
|
15132
15219
|
for (const model of models) {
|
|
15133
15220
|
if (isListWrapperModel(model) || isListMetadataModel(model)) continue;
|
|
15221
|
+
if (requestBodyOnlyNames.has(model.name)) continue;
|
|
15134
15222
|
const csClassName = modelClassName(model.name);
|
|
15135
15223
|
if (isModelAlias(model.name)) continue;
|
|
15136
15224
|
const lines = [];
|
|
@@ -15209,6 +15297,8 @@ function generateModels$2(models, ctx, discCtx) {
|
|
|
15209
15297
|
}
|
|
15210
15298
|
const isRequiredEnum = field.required && isEnumRef(field.type) && constInit === null;
|
|
15211
15299
|
lines.push(...emitJsonPropertyAttributes(field.name, { isRequiredEnum }));
|
|
15300
|
+
const discriminatedUnionConverter = discriminatedUnionConverterName(field.type);
|
|
15301
|
+
if (discriminatedUnionConverter) lines.push(` [Newtonsoft.Json.JsonConverter(typeof(${discriminatedUnionConverter}))]`);
|
|
15212
15302
|
const newMod = useNewModifier ? "new " : "";
|
|
15213
15303
|
lines.push(` public ${newMod}${csType} ${csFieldName} { get; ${setterModifier}set; }${initializer}`);
|
|
15214
15304
|
if (isDictionaryOfObject(csType) && !field.deprecated) dictObjectFields.push({
|
|
@@ -15274,6 +15364,23 @@ function generateModels$2(models, ctx, discCtx) {
|
|
|
15274
15364
|
return files;
|
|
15275
15365
|
}
|
|
15276
15366
|
/**
|
|
15367
|
+
* Compute the name of the discriminator converter class for a field whose
|
|
15368
|
+
* type is a discriminated union, mirroring the keying used in
|
|
15369
|
+
* `joinUnionVariants` (first IR model variant name + "DiscriminatorConverter").
|
|
15370
|
+
* Returns null when the type isn't a discriminated union with a populated
|
|
15371
|
+
* mapping. Also walks through `nullable` so an optional discriminated field
|
|
15372
|
+
* still gets the converter applied.
|
|
15373
|
+
*/
|
|
15374
|
+
function discriminatedUnionConverterName(ref) {
|
|
15375
|
+
const inner = ref.kind === "nullable" ? ref.inner : ref;
|
|
15376
|
+
if (inner.kind !== "union") return null;
|
|
15377
|
+
if (!inner.discriminator || !inner.discriminator.mapping) return null;
|
|
15378
|
+
if (Object.keys(inner.discriminator.mapping).length === 0) return null;
|
|
15379
|
+
const firstModel = inner.variants.find((v) => v.kind === "model");
|
|
15380
|
+
if (!firstModel || firstModel.kind !== "model") return null;
|
|
15381
|
+
return `${modelClassName(firstModel.name)}DiscriminatorConverter`;
|
|
15382
|
+
}
|
|
15383
|
+
/**
|
|
15277
15384
|
* Whether the emitted C# type is `Dictionary<string, object>` or its
|
|
15278
15385
|
* nullable variant — the usual shape of metadata / additional-properties
|
|
15279
15386
|
* fields that get typed accessors.
|
|
@@ -15375,6 +15482,39 @@ function normalizeTypeForHash$1(ref, aliasOf) {
|
|
|
15375
15482
|
function structuralHash$1(model, aliasOf = /* @__PURE__ */ new Map()) {
|
|
15376
15483
|
return model.fields.map((f) => `${f.name}:${JSON.stringify(normalizeTypeForHash$1(f.type, aliasOf))}:${f.required}`).sort().join("|");
|
|
15377
15484
|
}
|
|
15485
|
+
/**
|
|
15486
|
+
* Names of models referenced **only** as a named operation request body —
|
|
15487
|
+
* i.e. never appearing in a response, an error, a paginated item type, or as
|
|
15488
|
+
* a field type on another model. The .NET wrapper generator emits a
|
|
15489
|
+
* per-operation `*Options` class containing the same fields, so the named
|
|
15490
|
+
* entity is never instantiated by callers and just clutters the SDK
|
|
15491
|
+
* (workos-dotnet#248: `CreateUserApiKey` vs `UserManagementCreateApiKeyOptions`).
|
|
15492
|
+
*/
|
|
15493
|
+
function collectRequestBodyOnlyModelNames(services, models) {
|
|
15494
|
+
const requestBodyNames = /* @__PURE__ */ new Set();
|
|
15495
|
+
const otherReferences = /* @__PURE__ */ new Set();
|
|
15496
|
+
const collect = (ref, into) => {
|
|
15497
|
+
if (!ref) return;
|
|
15498
|
+
walkTypeRef(ref, { model: (r) => into.add(resolveModelName(r.name)) });
|
|
15499
|
+
};
|
|
15500
|
+
for (const service of services) for (const op of service.operations) {
|
|
15501
|
+
if (op.requestBody?.kind === "model") requestBodyNames.add(resolveModelName(op.requestBody.name));
|
|
15502
|
+
collect(op.response, otherReferences);
|
|
15503
|
+
if (op.pagination) collect(op.pagination.itemType, otherReferences);
|
|
15504
|
+
for (const p of [
|
|
15505
|
+
...op.pathParams,
|
|
15506
|
+
...op.queryParams,
|
|
15507
|
+
...op.headerParams,
|
|
15508
|
+
...op.cookieParams ?? []
|
|
15509
|
+
]) collect(p.type, otherReferences);
|
|
15510
|
+
if (op.successResponses) for (const sr of op.successResponses) collect(sr.type, otherReferences);
|
|
15511
|
+
for (const err of op.errors) if (err.type) collect(err.type, otherReferences);
|
|
15512
|
+
}
|
|
15513
|
+
for (const model of models) for (const field of model.fields) collect(field.type, otherReferences);
|
|
15514
|
+
const result = /* @__PURE__ */ new Set();
|
|
15515
|
+
for (const name of requestBodyNames) if (!otherReferences.has(name)) result.add(name);
|
|
15516
|
+
return result;
|
|
15517
|
+
}
|
|
15378
15518
|
//#endregion
|
|
15379
15519
|
//#region src/dotnet/enums.ts
|
|
15380
15520
|
/**
|
|
@@ -17093,14 +17233,14 @@ const dotnetEmitter = {
|
|
|
17093
17233
|
lines.push(" {");
|
|
17094
17234
|
lines.push(" public override bool CanConvert(Type objectType) => objectType == typeof(object);");
|
|
17095
17235
|
lines.push("");
|
|
17096
|
-
lines.push(" public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object? existingValue, Newtonsoft.Json.JsonSerializer serializer)");
|
|
17236
|
+
lines.push(" public override object? ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object? existingValue, Newtonsoft.Json.JsonSerializer serializer)");
|
|
17097
17237
|
lines.push(" {");
|
|
17098
17238
|
lines.push(" var jObject = JObject.Load(reader);");
|
|
17099
17239
|
lines.push(` var discriminatorValue = jObject["${disc.property}"]?.ToString();`);
|
|
17100
17240
|
lines.push(" switch (discriminatorValue)");
|
|
17101
17241
|
lines.push(" {");
|
|
17102
17242
|
for (const [value, modelName] of Object.entries(disc.mapping)) {
|
|
17103
|
-
const csName = modelClassName(modelName);
|
|
17243
|
+
const csName = modelClassName(resolveModelName(modelName));
|
|
17104
17244
|
lines.push(` case "${value}": return jObject.ToObject<${csName}>(serializer);`);
|
|
17105
17245
|
}
|
|
17106
17246
|
lines.push(" default: return jObject.ToObject<object>(serializer);");
|
|
@@ -17139,7 +17279,7 @@ const dotnetEmitter = {
|
|
|
17139
17279
|
lines.push("");
|
|
17140
17280
|
lines.push(` public override bool CanConvert(Type objectType) => typeof(${baseClass}).IsAssignableFrom(objectType);`);
|
|
17141
17281
|
lines.push("");
|
|
17142
|
-
lines.push(" public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object? existingValue, Newtonsoft.Json.JsonSerializer serializer)");
|
|
17282
|
+
lines.push(" public override object? ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object? existingValue, Newtonsoft.Json.JsonSerializer serializer)");
|
|
17143
17283
|
lines.push(" {");
|
|
17144
17284
|
lines.push(" var jObject = JObject.Load(reader);");
|
|
17145
17285
|
lines.push(` var discriminatorValue = jObject["${disc.property}"]?.ToString();`);
|
|
@@ -17585,9 +17725,8 @@ const discriminatedUnions = /* @__PURE__ */ new Map();
|
|
|
17585
17725
|
function joinUnionVariants(ref, variants) {
|
|
17586
17726
|
if (ref.compositionKind === "allOf") return variants[0] ?? "Any";
|
|
17587
17727
|
const unique = [...new Set(variants)];
|
|
17588
|
-
if (unique.length === 1) return unique[0];
|
|
17589
17728
|
if (ref.discriminator && ref.discriminator.mapping) {
|
|
17590
|
-
const baseName = unique[0];
|
|
17729
|
+
const baseName = ref.variants.filter((v) => v.kind === "model").map((v) => v.kind === "model" ? v.name : "").filter(Boolean)[0] ?? unique[0];
|
|
17591
17730
|
discriminatedUnions.set(baseName, {
|
|
17592
17731
|
property: ref.discriminator.property,
|
|
17593
17732
|
mapping: ref.discriminator.mapping,
|
|
@@ -17595,6 +17734,7 @@ function joinUnionVariants(ref, variants) {
|
|
|
17595
17734
|
});
|
|
17596
17735
|
return baseName;
|
|
17597
17736
|
}
|
|
17737
|
+
if (unique.length === 1) return unique[0];
|
|
17598
17738
|
return "Any";
|
|
17599
17739
|
}
|
|
17600
17740
|
/** Kotlin imports implied by a given type expression. Caller collects into a set. */
|
|
@@ -20095,8 +20235,15 @@ function deserializeExpression(accessor, ref, required, enumNames, modelNames) {
|
|
|
20095
20235
|
}
|
|
20096
20236
|
if (ref.kind === "enum" && enumNames.has(ref.name)) return accessor;
|
|
20097
20237
|
if (ref.kind === "union") {
|
|
20098
|
-
|
|
20099
|
-
|
|
20238
|
+
if (ref.discriminator && ref.discriminator.mapping) {
|
|
20239
|
+
const entries = Object.entries(ref.discriminator.mapping).filter(([, name]) => modelNames.has(name));
|
|
20240
|
+
if (entries.length > 0) return `${accessor} ? ${`(case ${rubyHashAccessor(accessor, ref.discriminator.property)} ${entries.map(([value, modelName]) => {
|
|
20241
|
+
const cls = `WorkOS::${className(modelName)}`;
|
|
20242
|
+
return `when ${JSON.stringify(value)} then ${cls}.new(${accessor})`;
|
|
20243
|
+
}).join(" ")} else ${accessor} end)`} : nil`;
|
|
20244
|
+
}
|
|
20245
|
+
const firstModelVariant = ref.variants.find((v) => v.kind === "model" && modelNames.has(v.name));
|
|
20246
|
+
if (firstModelVariant && firstModelVariant.kind === "model") return `${accessor} ? ${`WorkOS::${className(firstModelVariant.name)}`}.new(${accessor}) : nil`;
|
|
20100
20247
|
return accessor;
|
|
20101
20248
|
}
|
|
20102
20249
|
if (ref.kind === "literal") return accessor;
|
|
@@ -22153,4 +22300,4 @@ const workosEmittersPlugin = {
|
|
|
22153
22300
|
//#endregion
|
|
22154
22301
|
export { nodeEmitter as _, rustExtractor as a, pythonExtractor as c, rubyEmitter as d, kotlinEmitter as f, pythonEmitter as g, phpEmitter as h, kotlinExtractor as i, rubyExtractor as l, goEmitter as m, elixirExtractor as n, goExtractor as o, dotnetEmitter as p, dotnetExtractor as r, phpExtractor as s, workosEmittersPlugin as t, nodeExtractor as u };
|
|
22155
22302
|
|
|
22156
|
-
//# sourceMappingURL=plugin-
|
|
22303
|
+
//# sourceMappingURL=plugin-DOE0FqrZ.mjs.map
|