@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.
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "0.15.0"
2
+ ".": "0.15.2"
3
3
  }
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-CO4RFgAW.mjs";
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(/\bAutoPaginatable<\s*([A-Za-z_$][\w$]*)/)?.[1];
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 (!returnType || !itemType || !preferred || preferred === itemType) return returnType;
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
- for (const p of PAGINATION_PARAM_NAMES) lines.push(` ${p}: options.${p},`);
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 returnType = preferredBaselineReturnType(ctx, baselineMethod?.returnType) ?? `Promise<AutoPaginatable<${itemType}>>`;
5542
- const listOptionsExpr = op.queryParams.filter((p) => !PAGINATION_PARAM_NAMES.has(p.name)).some((p) => fieldName$6(p.name) !== wireFieldName(p.name)) ? `options ? serialize${optionParam.type}(options) : undefined` : "paginationOptions";
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(` paginationOptions,`);
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 serializerArg = extraParams.some((p) => fieldName$6(p.name) !== wireFieldName(p.name)) ? `, serialize${optionsType}` : "";
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
- lines.push(` async ${method}(${allParams}): Promise<AutoPaginatable<${itemType}, ${optionsType}>> {`);
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(` options,`);
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)) ownedDirNames.add(resolveDir(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
- for (const field of shape.baseFields) pushFieldLine(lines, field, isWire);
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 symbols = [];
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
- if (wire !== domain) symbols.push(wire);
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
- if (symbols.length === 0) return [];
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-CO4RFgAW.mjs.map
28421
+ //# sourceMappingURL=plugin-Xkr83G9A.mjs.map