@workos/oagen-emitters 0.15.0 → 0.15.2
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 +14 -0
- package/dist/index.mjs +1 -1
- package/dist/{plugin-CO4RFgAW.mjs → plugin-Xkr83G9A.mjs} +90 -30
- package/dist/plugin-Xkr83G9A.mjs.map +1 -0
- package/dist/plugin.mjs +1 -1
- package/package.json +1 -1
- package/src/node/client.ts +40 -1
- package/src/node/discriminated-models.ts +60 -24
- package/src/node/resources.ts +27 -9
- package/dist/plugin-CO4RFgAW.mjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.15.2](https://github.com/workos/oagen-emitters/compare/v0.15.1...v0.15.2) (2026-06-01)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **node:** align AutoPaginatable type param with serialized runtime shape ([#134](https://github.com/workos/oagen-emitters/issues/134)) ([43ddd64](https://github.com/workos/oagen-emitters/commit/43ddd64d5d56b4ff2e7ae19bfa1ee895d24cb60d))
|
|
9
|
+
|
|
10
|
+
## [0.15.1](https://github.com/workos/oagen-emitters/compare/v0.15.0...v0.15.1) (2026-06-01)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* **node:** resolve emitter bugs blocking service ownership migration ([#132](https://github.com/workos/oagen-emitters/issues/132)) ([e63cc06](https://github.com/workos/oagen-emitters/commit/e63cc06f948657965563a0d582ebbd9bedb1eb5f))
|
|
16
|
+
|
|
3
17
|
## [0.15.0](https://github.com/workos/oagen-emitters/compare/v0.14.4...v0.15.0) (2026-06-01)
|
|
4
18
|
|
|
5
19
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as pythonEmitter, a as rustExtractor, c as pythonExtractor, d as rustEmitter, f as rubyEmitter, g as phpEmitter, h as goEmitter, i as kotlinExtractor, l as rubyExtractor, m as dotnetEmitter, n as elixirExtractor, o as goExtractor, p as kotlinEmitter, r as dotnetExtractor, s as phpExtractor, t as workosEmittersPlugin, u as nodeExtractor, v as nodeEmitter } from "./plugin-
|
|
1
|
+
import { _ as pythonEmitter, a as rustExtractor, c as pythonExtractor, d as rustEmitter, f as rubyEmitter, g as phpEmitter, h as goEmitter, i as kotlinExtractor, l as rubyExtractor, m as dotnetEmitter, n as elixirExtractor, o as goExtractor, p as kotlinEmitter, r as dotnetExtractor, s as phpExtractor, t as workosEmittersPlugin, u as nodeExtractor, v as nodeEmitter } from "./plugin-Xkr83G9A.mjs";
|
|
2
2
|
export { dotnetEmitter, dotnetExtractor, elixirExtractor, goEmitter, goExtractor, kotlinEmitter, kotlinExtractor, nodeEmitter, nodeExtractor, phpEmitter, phpExtractor, pythonEmitter, pythonExtractor, rubyEmitter, rubyExtractor, rustEmitter, rustExtractor, workosEmittersPlugin };
|
|
@@ -4781,7 +4781,7 @@ function renderOptionsParam(param) {
|
|
|
4781
4781
|
return `options${param.optional ? "?" : ""}: ${param.type}`;
|
|
4782
4782
|
}
|
|
4783
4783
|
function autoPaginatableItemType$1(returnType) {
|
|
4784
|
-
return returnType?.match(/\
|
|
4784
|
+
return returnType?.match(/\b(?:AutoPaginatable|List)<\s*([A-Za-z_$][\w$]*)/)?.[1];
|
|
4785
4785
|
}
|
|
4786
4786
|
function baselineTypeSourceFile(ctx, typeName) {
|
|
4787
4787
|
const surface = ctx.apiSurface;
|
|
@@ -4799,9 +4799,12 @@ function preferredBaselineTypeName(ctx, typeName) {
|
|
|
4799
4799
|
return typeName;
|
|
4800
4800
|
}
|
|
4801
4801
|
function preferredBaselineReturnType(ctx, returnType) {
|
|
4802
|
+
if (!returnType) return void 0;
|
|
4803
|
+
if (!/\bAutoPaginatable\b/.test(returnType)) return void 0;
|
|
4802
4804
|
const itemType = autoPaginatableItemType$1(returnType);
|
|
4805
|
+
if (!itemType) return void 0;
|
|
4803
4806
|
const preferred = preferredBaselineTypeName(ctx, itemType);
|
|
4804
|
-
if (!
|
|
4807
|
+
if (!preferred || preferred === itemType) return returnType;
|
|
4805
4808
|
return returnType.replace(new RegExp(`\\b${itemType}\\b`, "g"), preferred);
|
|
4806
4809
|
}
|
|
4807
4810
|
function requestEntityType(bodyExpr, requestType) {
|
|
@@ -5233,7 +5236,11 @@ function generateResourceClass(service, ctx) {
|
|
|
5233
5236
|
const serializerName = `serialize${optionsName}`;
|
|
5234
5237
|
lines.push(`const ${serializerName} = (options: ${optionsName}): PaginationOptions => {`);
|
|
5235
5238
|
lines.push(" const wire: Record<string, unknown> = {");
|
|
5236
|
-
|
|
5239
|
+
const baselineFields = (ctx.apiSurface?.interfaces)?.[optionsName]?.fields;
|
|
5240
|
+
for (const p of PAGINATION_PARAM_NAMES) {
|
|
5241
|
+
if (baselineFields && !(p in baselineFields) && !baselineFields[toCamelCase(p)]) continue;
|
|
5242
|
+
lines.push(` ${p}: options.${p},`);
|
|
5243
|
+
}
|
|
5237
5244
|
lines.push(" };");
|
|
5238
5245
|
for (const param of extraParams) {
|
|
5239
5246
|
const camel = fieldName$6(param.name);
|
|
@@ -5466,7 +5473,7 @@ function renderMethod$2(op, plan, method, service, ctx, modelMap, specEnumNames,
|
|
|
5466
5473
|
const unwrapped = unwrapListModel$4(pModel, modelMap);
|
|
5467
5474
|
if (unwrapped) itemRawName = unwrapped.name;
|
|
5468
5475
|
}
|
|
5469
|
-
const itemTypeName = resolveInterfaceName(itemRawName, ctx);
|
|
5476
|
+
const itemTypeName = preferredBaselineTypeName(ctx, autoPaginatableItemType$1(baselineClassMethod?.returnType) ?? autoPaginatableItemType$1(overlayMethod?.returnType)) ?? resolveInterfaceName(itemRawName, ctx);
|
|
5470
5477
|
docParts.push(`@returns {Promise<AutoPaginatable<${itemTypeName}>>}`);
|
|
5471
5478
|
} else if (responseModel) {
|
|
5472
5479
|
const returnTypeDoc = plan.isArrayResponse ? `${responseModel}[]` : responseModel;
|
|
@@ -5538,10 +5545,12 @@ function renderOptionsObjectMethod(lines, op, plan, method, service, ctx, modelM
|
|
|
5538
5545
|
const itemType = preferredBaselineTypeName(ctx, autoPaginatableItemType$1(baselineMethod?.returnType)) ?? (itemRawName ? resolveInterfaceName(itemRawName, ctx) : responseModel);
|
|
5539
5546
|
if (!itemType) return false;
|
|
5540
5547
|
const wireType = wireInterfaceName(itemType);
|
|
5541
|
-
const
|
|
5542
|
-
const
|
|
5548
|
+
const needsWireSerializer = op.queryParams.filter((p) => !PAGINATION_PARAM_NAMES.has(p.name)).some((p) => fieldName$6(p.name) !== wireFieldName(p.name));
|
|
5549
|
+
const paginationType = needsWireSerializer ? "PaginationOptions" : optionParam.type;
|
|
5550
|
+
const returnType = needsWireSerializer ? `Promise<AutoPaginatable<${itemType}, ${paginationType}>>` : preferredBaselineReturnType(ctx, baselineMethod?.returnType) ?? `Promise<AutoPaginatable<${itemType}, ${paginationType}>>`;
|
|
5551
|
+
const listOptionsExpr = needsWireSerializer ? `options ? serialize${optionParam.type}(options) : undefined` : "paginationOptions";
|
|
5543
5552
|
lines.push(` async ${method}(${renderOptionsParam(optionParam)}): ${returnType} {`);
|
|
5544
|
-
renderOptionsObjectDestructure(lines, pathBindings, "paginationOptions");
|
|
5553
|
+
renderOptionsObjectDestructure(lines, pathBindings, needsWireSerializer ? void 0 : "paginationOptions");
|
|
5545
5554
|
lines.push(` return new AutoPaginatable(`);
|
|
5546
5555
|
lines.push(` await fetchAndDeserialize<${wireType}, ${itemType}>(`);
|
|
5547
5556
|
lines.push(` this.workos,`);
|
|
@@ -5556,7 +5565,7 @@ function renderOptionsObjectMethod(lines, op, plan, method, service, ctx, modelM
|
|
|
5556
5565
|
lines.push(` deserialize${itemType},`);
|
|
5557
5566
|
lines.push(` params,`);
|
|
5558
5567
|
lines.push(` ),`);
|
|
5559
|
-
lines.push(`
|
|
5568
|
+
lines.push(` ${listOptionsExpr},`);
|
|
5560
5569
|
lines.push(` );`);
|
|
5561
5570
|
lines.push(" }");
|
|
5562
5571
|
return true;
|
|
@@ -5688,12 +5697,14 @@ function resolveOptionsObjectField$1(localName, optionType, ctx) {
|
|
|
5688
5697
|
function renderPaginatedMethod(lines, op, plan, method, itemType, pathStr, resolvedServiceName, specEnumNames) {
|
|
5689
5698
|
const extraParams = op.queryParams.filter((p) => !PAGINATION_PARAM_NAMES.has(p.name));
|
|
5690
5699
|
const optionsType = extraParams.length > 0 ? paginatedOptionsName(method, resolvedServiceName) : "PaginationOptions";
|
|
5691
|
-
const
|
|
5700
|
+
const needsWireSerializer = extraParams.some((p) => fieldName$6(p.name) !== wireFieldName(p.name));
|
|
5701
|
+
const serializerArg = needsWireSerializer ? `, serialize${optionsType}` : "";
|
|
5692
5702
|
const pathParams = buildPathParams(op, specEnumNames);
|
|
5693
5703
|
const allParams = pathParams ? `${pathParams}, options?: ${optionsType}` : `options?: ${optionsType}`;
|
|
5694
5704
|
const wireType = wireInterfaceName(itemType);
|
|
5695
5705
|
const serializeCall = serializerArg ? `options ? serialize${optionsType}(options) : undefined` : "options";
|
|
5696
|
-
|
|
5706
|
+
const paginationType = needsWireSerializer ? "PaginationOptions" : optionsType;
|
|
5707
|
+
lines.push(` async ${method}(${allParams}): Promise<AutoPaginatable<${itemType}, ${paginationType}>> {`);
|
|
5697
5708
|
lines.push(` return new AutoPaginatable(`);
|
|
5698
5709
|
lines.push(` await fetchAndDeserialize<${wireType}, ${itemType}>(`);
|
|
5699
5710
|
lines.push(` this.workos,`);
|
|
@@ -5708,7 +5719,7 @@ function renderPaginatedMethod(lines, op, plan, method, itemType, pathStr, resol
|
|
|
5708
5719
|
lines.push(` deserialize${itemType},`);
|
|
5709
5720
|
lines.push(` params,`);
|
|
5710
5721
|
lines.push(` ),`);
|
|
5711
|
-
lines.push(`
|
|
5722
|
+
lines.push(` ${serializeCall},`);
|
|
5712
5723
|
lines.push(` );`);
|
|
5713
5724
|
lines.push(" }");
|
|
5714
5725
|
}
|
|
@@ -7128,7 +7139,14 @@ function generateServiceBarrels(spec, ctx) {
|
|
|
7128
7139
|
const dirExports = /* @__PURE__ */ new Map();
|
|
7129
7140
|
const dirSymbols = /* @__PURE__ */ new Map();
|
|
7130
7141
|
const ownedDirNames = /* @__PURE__ */ new Set();
|
|
7131
|
-
for (const service of spec.services) if (isNodeOwnedService(ctx, service.name))
|
|
7142
|
+
for (const service of spec.services) if (isNodeOwnedService(ctx, service.name)) {
|
|
7143
|
+
const dir = resolveDir(service.name);
|
|
7144
|
+
ownedDirNames.add(dir);
|
|
7145
|
+
if (!dirExports.has(dir)) {
|
|
7146
|
+
dirExports.set(dir, []);
|
|
7147
|
+
if (!dirSymbols.has(dir)) dirSymbols.set(dir, /* @__PURE__ */ new Set());
|
|
7148
|
+
}
|
|
7149
|
+
}
|
|
7132
7150
|
const dirSymbolsFromBaseline = /* @__PURE__ */ new Map();
|
|
7133
7151
|
const seedFromBaseline = (sourceFile, name) => {
|
|
7134
7152
|
const match = sourceFile.match(/^src\/([^/]+)\/interfaces\/(.+)\.ts$/);
|
|
@@ -7294,6 +7312,28 @@ function generateServiceBarrels(spec, ctx) {
|
|
|
7294
7312
|
} catch {}
|
|
7295
7313
|
}
|
|
7296
7314
|
}
|
|
7315
|
+
const ownedScanRoot = ctx.targetDir ?? ctx.outputDir;
|
|
7316
|
+
if (ownedScanRoot && isDirOwned) {
|
|
7317
|
+
const interfacesDir = path.join(ownedScanRoot, "src", dirName, "interfaces");
|
|
7318
|
+
const symbols = dirSymbols.get(dirName) ?? /* @__PURE__ */ new Set();
|
|
7319
|
+
try {
|
|
7320
|
+
for (const entry of fs.readdirSync(interfacesDir)) {
|
|
7321
|
+
if (entry === "index.ts") continue;
|
|
7322
|
+
if (!entry.endsWith(".ts")) continue;
|
|
7323
|
+
const exportLine = `export * from './${entry.replace(/\.ts$/, "")}';`;
|
|
7324
|
+
if (exportSet.has(exportLine)) continue;
|
|
7325
|
+
const content = fs.readFileSync(path.join(interfacesDir, entry), "utf-8");
|
|
7326
|
+
const exportedNames = [];
|
|
7327
|
+
for (const m of content.matchAll(/export\s+(?:interface|type|enum|class|const|function)\s+(\w+)/g)) exportedNames.push(m[1]);
|
|
7328
|
+
if (exportedNames.some((name) => globalExistingSymbols.has(name))) continue;
|
|
7329
|
+
for (const name of exportedNames) {
|
|
7330
|
+
symbols.add(name);
|
|
7331
|
+
globalExistingSymbols.add(name);
|
|
7332
|
+
}
|
|
7333
|
+
exportSet.add(exportLine);
|
|
7334
|
+
}
|
|
7335
|
+
} catch {}
|
|
7336
|
+
}
|
|
7297
7337
|
const uniqueExports = [...exportSet];
|
|
7298
7338
|
uniqueExports.sort();
|
|
7299
7339
|
if (ctx.apiSurface) files.push({
|
|
@@ -8494,13 +8534,29 @@ function planDiscriminatedModels(models, ctx) {
|
|
|
8494
8534
|
if (!spec?.components?.schemas) return plans;
|
|
8495
8535
|
const rawSchemas = spec.components.schemas;
|
|
8496
8536
|
const { modelToService, resolveDir } = createServiceDirResolver(models, ctx.spec.services, ctx);
|
|
8537
|
+
const irModelDir = /* @__PURE__ */ new Map();
|
|
8538
|
+
for (const model of models) irModelDir.set(model.name, resolveDir(modelToService.get(model.name)));
|
|
8539
|
+
const depDirMap = /* @__PURE__ */ new Map();
|
|
8540
|
+
for (const rawName of Object.keys(rawSchemas)) {
|
|
8541
|
+
if (irModelDir.has(rawName)) {
|
|
8542
|
+
depDirMap.set(rawName, irModelDir.get(rawName));
|
|
8543
|
+
continue;
|
|
8544
|
+
}
|
|
8545
|
+
const stripped = rawName.replace(/Dto/g, "").replace(/DTO/g, "").replace(/Json$/, "");
|
|
8546
|
+
if (stripped !== rawName && irModelDir.has(stripped)) depDirMap.set(rawName, irModelDir.get(stripped));
|
|
8547
|
+
}
|
|
8497
8548
|
for (const model of models) {
|
|
8498
8549
|
const shape = detectDiscriminatedShape(model.name, rawSchemas);
|
|
8499
8550
|
if (!shape) continue;
|
|
8551
|
+
const allDeps = /* @__PURE__ */ new Set();
|
|
8552
|
+
for (const field of shape.baseFields) for (const d of field.modelDeps) allDeps.add(d);
|
|
8553
|
+
for (const variant of shape.variants) for (const field of variant.fields) for (const d of field.modelDeps) allDeps.add(d);
|
|
8554
|
+
if ([...allDeps].some((dep) => !depDirMap.has(dep) && !irModelDir.has(dep))) continue;
|
|
8500
8555
|
const modelDir = resolveDir(modelToService.get(model.name));
|
|
8501
8556
|
plans.set(model.name, {
|
|
8502
8557
|
shape,
|
|
8503
|
-
modelDir
|
|
8558
|
+
modelDir,
|
|
8559
|
+
depDirMap
|
|
8504
8560
|
});
|
|
8505
8561
|
}
|
|
8506
8562
|
return plans;
|
|
@@ -8545,7 +8601,12 @@ function buildInterfaceFile(plan, _ctx) {
|
|
|
8545
8601
|
function buildInterfaceBody(name, shape, variant, isWire) {
|
|
8546
8602
|
const lines = [];
|
|
8547
8603
|
lines.push(`export interface ${name} {`);
|
|
8548
|
-
|
|
8604
|
+
const variantFieldNames = new Set(variant.fields.map((f) => f.name));
|
|
8605
|
+
for (const field of shape.baseFields) {
|
|
8606
|
+
if (variantFieldNames.has(field.name)) continue;
|
|
8607
|
+
if (field.name === shape.discriminatorProperty) continue;
|
|
8608
|
+
pushFieldLine(lines, field, isWire);
|
|
8609
|
+
}
|
|
8549
8610
|
const discKey = isWire ? shape.discriminatorProperty : shape.discriminatorPropertyDomain;
|
|
8550
8611
|
if (shape.discriminatorDescription) lines.push(` /** ${shape.discriminatorDescription} */`);
|
|
8551
8612
|
lines.push(` ${discKey}: '${variant.discriminatorValue}';`);
|
|
@@ -8564,25 +8625,24 @@ function collectImports$2(plan) {
|
|
|
8564
8625
|
const deps = /* @__PURE__ */ new Set();
|
|
8565
8626
|
for (const field of plan.shape.baseFields) for (const d of field.modelDeps) deps.add(d);
|
|
8566
8627
|
for (const variant of plan.shape.variants) for (const field of variant.fields) for (const d of field.modelDeps) deps.add(d);
|
|
8567
|
-
const
|
|
8628
|
+
const result = [];
|
|
8568
8629
|
for (const dep of [...deps].sort()) {
|
|
8569
8630
|
const domain = toPascalCase(dep);
|
|
8570
|
-
symbols.push(domain);
|
|
8571
8631
|
const wire = wireInterfaceName(domain);
|
|
8572
|
-
|
|
8632
|
+
const symbols = wire !== domain ? [domain, wire] : [domain];
|
|
8633
|
+
const depDir = plan.depDirMap.get(dep);
|
|
8634
|
+
const baseName = fileName$3(toSnakeFromPascal(domain));
|
|
8635
|
+
let importPath;
|
|
8636
|
+
if (!depDir || depDir === plan.modelDir) importPath = `./${baseName}.interface`;
|
|
8637
|
+
else importPath = `../../${depDir}/interfaces/${baseName}.interface`;
|
|
8638
|
+
const existing = result.find((a) => a.path === importPath);
|
|
8639
|
+
if (existing) existing.symbols.push(...symbols);
|
|
8640
|
+
else result.push({
|
|
8641
|
+
path: importPath,
|
|
8642
|
+
symbols
|
|
8643
|
+
});
|
|
8573
8644
|
}
|
|
8574
|
-
|
|
8575
|
-
return symbols.map((sym) => {
|
|
8576
|
-
return {
|
|
8577
|
-
path: `./${fileName$3(toSnakeFromPascal(sym.replace(/Response$/, "")))}.interface`,
|
|
8578
|
-
symbols: [sym]
|
|
8579
|
-
};
|
|
8580
|
-
}).reduce((acc, cur) => {
|
|
8581
|
-
const existing = acc.find((a) => a.path === cur.path);
|
|
8582
|
-
if (existing) existing.symbols.push(...cur.symbols);
|
|
8583
|
-
else acc.push(cur);
|
|
8584
|
-
return acc;
|
|
8585
|
-
}, []);
|
|
8645
|
+
return result;
|
|
8586
8646
|
}
|
|
8587
8647
|
function toSnakeFromPascal(s) {
|
|
8588
8648
|
return s.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2").toLowerCase();
|
|
@@ -28358,4 +28418,4 @@ const workosEmittersPlugin = {
|
|
|
28358
28418
|
//#endregion
|
|
28359
28419
|
export { pythonEmitter as _, rustExtractor as a, pythonExtractor as c, rustEmitter as d, rubyEmitter as f, phpEmitter as g, goEmitter as h, kotlinExtractor as i, rubyExtractor as l, dotnetEmitter as m, elixirExtractor as n, goExtractor as o, kotlinEmitter as p, dotnetExtractor as r, phpExtractor as s, workosEmittersPlugin as t, nodeExtractor as u, nodeEmitter as v };
|
|
28360
28420
|
|
|
28361
|
-
//# sourceMappingURL=plugin-
|
|
28421
|
+
//# sourceMappingURL=plugin-Xkr83G9A.mjs.map
|