@workos/oagen-emitters 0.18.0 → 0.18.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-DAa-HsN5.mjs → plugin-bqfwowQ3.mjs} +61 -12
- package/dist/plugin-bqfwowQ3.mjs.map +1 -0
- package/dist/plugin.mjs +1 -1
- package/package.json +1 -1
- package/src/node/client.ts +2 -2
- package/src/node/enums.ts +23 -0
- package/src/node/models.ts +44 -5
- package/src/node/options.ts +23 -0
- package/src/node/resources.ts +50 -3
- package/src/node/tests.ts +5 -3
- package/test/node/enums.test.ts +138 -2
- package/test/node/resources.test.ts +101 -65
- package/dist/plugin-DAa-HsN5.mjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.18.2](https://github.com/workos/oagen-emitters/compare/v0.18.1...v0.18.2) (2026-06-17)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **node:** adopt spec request interface for owned inline-literal params; dedupe common enums ([#154](https://github.com/workos/oagen-emitters/issues/154)) ([71e2d4f](https://github.com/workos/oagen-emitters/commit/71e2d4f4e05441a41217286b92a555237c3fd794))
|
|
9
|
+
|
|
10
|
+
## [0.18.1](https://github.com/workos/oagen-emitters/compare/v0.18.0...v0.18.1) (2026-06-17)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* **node:** support owning services with hand-owned generic types ([#152](https://github.com/workos/oagen-emitters/issues/152)) ([aa8223d](https://github.com/workos/oagen-emitters/commit/aa8223dbb6b56f5c2ab12ac42e5a1fc9f9e99943))
|
|
16
|
+
|
|
3
17
|
## [0.18.0](https://github.com/workos/oagen-emitters/compare/v0.17.0...v0.18.0) (2026-06-16)
|
|
4
18
|
|
|
5
19
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as fieldName$4, B as servicePropertyName, C as apiClassName, D as dotnetEmitter, E as propertyName, F as fieldName$3, H as fieldName$1, I as methodName, L as trimMountedResourceFromMethod, M as trimMountedResourceFromMethod$1, N as goEmitter, O as appendAsyncSuffix, P as className, R as phpEmitter, S as kotlinEmitter, T as packageSegment, U as safeParamName$1, V as pythonEmitter, W as nodeEmitter, _ as rubyEmitter, a as rustExtractor, b as resolveServiceTarget, c as pythonExtractor, d as rustEmitter, f as fieldName$5, g as typeName, h as resourceAccessorName, i as kotlinExtractor, j as methodName$1, k as className$1, l as rubyExtractor, m as moduleName, n as elixirExtractor, o as goExtractor, p as methodName$3, r as dotnetExtractor, s as phpExtractor, t as workosEmittersPlugin, u as nodeExtractor, v as buildExportedClassNameSet, w as methodName$2, x as safeParamName, y as fieldName, z as fieldName$2 } from "./plugin-
|
|
1
|
+
import { A as fieldName$4, B as servicePropertyName, C as apiClassName, D as dotnetEmitter, E as propertyName, F as fieldName$3, H as fieldName$1, I as methodName, L as trimMountedResourceFromMethod, M as trimMountedResourceFromMethod$1, N as goEmitter, O as appendAsyncSuffix, P as className, R as phpEmitter, S as kotlinEmitter, T as packageSegment, U as safeParamName$1, V as pythonEmitter, W as nodeEmitter, _ as rubyEmitter, a as rustExtractor, b as resolveServiceTarget, c as pythonExtractor, d as rustEmitter, f as fieldName$5, g as typeName, h as resourceAccessorName, i as kotlinExtractor, j as methodName$1, k as className$1, l as rubyExtractor, m as moduleName, n as elixirExtractor, o as goExtractor, p as methodName$3, r as dotnetExtractor, s as phpExtractor, t as workosEmittersPlugin, u as nodeExtractor, v as buildExportedClassNameSet, w as methodName$2, x as safeParamName, y as fieldName, z as fieldName$2 } from "./plugin-bqfwowQ3.mjs";
|
|
2
2
|
import { collectSnippetArgs, collectWrapperArgs, toSnakeCase } from "@workos/oagen";
|
|
3
3
|
//#region src/snippets/ruby.ts
|
|
4
4
|
const INDENT$6 = " ";
|
|
@@ -3626,6 +3626,17 @@ function isNodeOwnedService(ctx, ...names) {
|
|
|
3626
3626
|
const owned = new Set(configured.map(normalizeServiceName));
|
|
3627
3627
|
return names.some((name) => name !== void 0 ? ownedLookupNames(name).some((candidate) => owned.has(normalizeServiceName(candidate))) : false);
|
|
3628
3628
|
}
|
|
3629
|
+
/**
|
|
3630
|
+
* True when `name` is a hand-owned type (see {@link NodeEmitterOptions.handOwnedTypes}).
|
|
3631
|
+
* Hand-owned types are never generated; the emitter defers to the existing
|
|
3632
|
+
* hand-written declaration and routes imports/barrel exports to it.
|
|
3633
|
+
*/
|
|
3634
|
+
function isHandOwnedType(ctx, name) {
|
|
3635
|
+
if (name === void 0) return false;
|
|
3636
|
+
const configured = nodeOptions(ctx).handOwnedTypes;
|
|
3637
|
+
if (!configured || configured.length === 0) return false;
|
|
3638
|
+
return configured.includes(name);
|
|
3639
|
+
}
|
|
3629
3640
|
//#endregion
|
|
3630
3641
|
//#region src/node/live-surface.ts
|
|
3631
3642
|
const SRC_DIR = "src";
|
|
@@ -4662,6 +4673,16 @@ function assignEnumsToServices(enums, services, models = [], ctx) {
|
|
|
4662
4673
|
for (const name of collectFieldDependencies(model).enums) if (enumNames.has(name) && !enumToService.has(name)) enumToService.set(name, service);
|
|
4663
4674
|
}
|
|
4664
4675
|
}
|
|
4676
|
+
if (ctx) {
|
|
4677
|
+
const serviceNameMap = buildServiceNameMap(services, ctx);
|
|
4678
|
+
const toUnassign = [];
|
|
4679
|
+
for (const [name, service] of enumToService) {
|
|
4680
|
+
if (!isNodeOwnedService(ctx, service, serviceNameMap.get(service))) continue;
|
|
4681
|
+
const home = (ctx.apiSurface?.enums?.[name])?.sourceFile ?? (ctx.apiSurface?.typeAliases?.[name])?.sourceFile ?? liveSurfaceInterfacePath(name);
|
|
4682
|
+
if (home && home.startsWith("src/common/")) toUnassign.push(name);
|
|
4683
|
+
}
|
|
4684
|
+
for (const name of toUnassign) enumToService.delete(name);
|
|
4685
|
+
}
|
|
4665
4686
|
return enumToService;
|
|
4666
4687
|
}
|
|
4667
4688
|
//#endregion
|
|
@@ -5573,7 +5594,18 @@ function operationHasOptionsInput(op, plan, resolvedOp) {
|
|
|
5573
5594
|
}
|
|
5574
5595
|
function optionsObjectInfo(service, method, op, plan, ctx, baselineMethod, resolvedOp) {
|
|
5575
5596
|
const baseline = optionsObjectParam$1(baselineMethod);
|
|
5576
|
-
if (baseline)
|
|
5597
|
+
if (baseline) {
|
|
5598
|
+
if (baseline.type.trimStart().startsWith("{") && isNodeOwnedService(ctx, service.name, resolveResourceClassName$3(service, ctx))) {
|
|
5599
|
+
const body = extractRequestBodyType(op, ctx);
|
|
5600
|
+
if (body?.kind === "model") return {
|
|
5601
|
+
name: "options",
|
|
5602
|
+
type: resolveInterfaceName(body.name, ctx),
|
|
5603
|
+
optional: optionsObjectShouldBeOptional(op, plan, resolvedOp),
|
|
5604
|
+
generated: false
|
|
5605
|
+
};
|
|
5606
|
+
}
|
|
5607
|
+
return baseline;
|
|
5608
|
+
}
|
|
5577
5609
|
const overrideType = operationOverrideFor$1(ctx, op)?.optionsType;
|
|
5578
5610
|
if (overrideType) return {
|
|
5579
5611
|
name: "options",
|
|
@@ -5582,9 +5614,15 @@ function optionsObjectInfo(service, method, op, plan, ctx, baselineMethod, resol
|
|
|
5582
5614
|
generated: baselineTypeSourceFile(ctx, overrideType) === void 0
|
|
5583
5615
|
};
|
|
5584
5616
|
if (!operationHasOptionsInput(op, plan, resolvedOp)) return void 0;
|
|
5617
|
+
const resolvedService = resolveResourceClassName$3(service, ctx);
|
|
5618
|
+
let optionsType = methodOptionsName$1(method, resolvedService);
|
|
5619
|
+
if (method !== "list") {
|
|
5620
|
+
const baselineDir = baselineTypeSourceFile(ctx, optionsType)?.match(/^src\/([^/]+)\//)?.[1];
|
|
5621
|
+
if (baselineDir && baselineDir !== resolveResourceDir(service, ctx)) optionsType = `${toPascalCase(resolvedService)}${toPascalCase(method)}Options`;
|
|
5622
|
+
}
|
|
5585
5623
|
return {
|
|
5586
5624
|
name: "options",
|
|
5587
|
-
type:
|
|
5625
|
+
type: optionsType,
|
|
5588
5626
|
optional: optionsObjectShouldBeOptional(op, plan, resolvedOp),
|
|
5589
5627
|
generated: true
|
|
5590
5628
|
};
|
|
@@ -6079,7 +6117,7 @@ function generateResourceClass(service, ctx) {
|
|
|
6079
6117
|
const resolved = lookupResolved(op, resolvedLookup);
|
|
6080
6118
|
const optionInfo = optionsObjectInfo(service, method, op, plan, ctx, baselineMethodFor$1(service, method, ctx), resolved);
|
|
6081
6119
|
if (plan.isPaginated) {
|
|
6082
|
-
const extraParams = op.queryParams.filter((p) => !PAGINATION_PARAM_NAMES.has(p.name));
|
|
6120
|
+
const extraParams = op.queryParams.filter((p) => !PAGINATION_PARAM_NAMES.has(p.name) && !p.deprecated);
|
|
6083
6121
|
if (extraParams.length > 0) {
|
|
6084
6122
|
const optionsName = optionInfo?.type ?? paginatedOptionsName(method, resolvedName);
|
|
6085
6123
|
if (extraParams.some((p) => fieldName$6(p.name) !== wireFieldName(p.name))) {
|
|
@@ -7336,6 +7374,7 @@ function generateModels$7(models, ctx, shared) {
|
|
|
7336
7374
|
if (isListMetadataModel(model) && !listMetadataNeeded.has(model.name)) continue;
|
|
7337
7375
|
if (isListWrapperModel(model) && !nonPaginatedRefs.has(model.name)) continue;
|
|
7338
7376
|
if (discriminatedSkip?.has(model.name)) continue;
|
|
7377
|
+
if (isHandOwnedType(ctx, model.name) || isHandOwnedType(ctx, resolveInterfaceName(model.name, ctx, { skipTypeAlias: true }))) continue;
|
|
7339
7378
|
const service = modelToService.get(model.name);
|
|
7340
7379
|
const isOwnedModel = isNodeOwnedService(ctx, service);
|
|
7341
7380
|
if (!isOwnedModel && !modelHasNewFields(model, ctx) && !forceGenerate.has(model.name)) continue;
|
|
@@ -7410,6 +7449,7 @@ function generateModels$7(models, ctx, shared) {
|
|
|
7410
7449
|
const crossServiceImports = /* @__PURE__ */ new Map();
|
|
7411
7450
|
const unresolvableNames = /* @__PURE__ */ new Set();
|
|
7412
7451
|
const enumToService = assignEnumsToServices(ctx.spec.enums, ctx.spec.services, ctx.spec.models, ctx);
|
|
7452
|
+
const serviceNameMap = buildServiceNameMap(ctx.spec.services, ctx);
|
|
7413
7453
|
const resolvedEnumNames = /* @__PURE__ */ new Map();
|
|
7414
7454
|
for (const e of ctx.spec.enums) resolvedEnumNames.set(resolveInterfaceName(e.name, ctx), e.name);
|
|
7415
7455
|
for (const field of model.fields) {
|
|
@@ -7429,7 +7469,7 @@ function generateModels$7(models, ctx, shared) {
|
|
|
7429
7469
|
const eDir = resolveDir(eService);
|
|
7430
7470
|
const bEnum = ctx.apiSurface?.enums?.[irEnumName];
|
|
7431
7471
|
const bAlias = ctx.apiSurface?.typeAliases?.[irEnumName];
|
|
7432
|
-
const bSrc = isNodeOwnedService(ctx, eService) ? void 0 : bEnum?.sourceFile ?? bAlias?.sourceFile;
|
|
7472
|
+
const bSrc = isNodeOwnedService(ctx, eService, eService ? serviceNameMap.get(eService) : void 0) ? void 0 : bEnum?.sourceFile ?? bAlias?.sourceFile;
|
|
7433
7473
|
const gPath = `src/${eDir}/interfaces/${fileName$3(irEnumName)}.interface.ts`;
|
|
7434
7474
|
const cPath = `src/${dirName}/interfaces/${fileName$3(model.name)}.interface.ts`;
|
|
7435
7475
|
if (bSrc === cPath) {
|
|
@@ -7474,7 +7514,7 @@ function generateModels$7(models, ctx, shared) {
|
|
|
7474
7514
|
const baselineEnum = ctx.apiSurface?.enums?.[dep];
|
|
7475
7515
|
const baselineAlias = ctx.apiSurface?.typeAliases?.[dep];
|
|
7476
7516
|
const depService = enumToService.get(dep);
|
|
7477
|
-
const baselineSrc = isNodeOwnedService(ctx, depService) ? void 0 : baselineEnum?.sourceFile ?? baselineAlias?.sourceFile ?? liveSurfaceInterfacePath(dep);
|
|
7517
|
+
const baselineSrc = isNodeOwnedService(ctx, depService, depService ? serviceNameMap.get(depService) : void 0) ? void 0 : baselineEnum?.sourceFile ?? baselineAlias?.sourceFile ?? liveSurfaceInterfacePath(dep);
|
|
7478
7518
|
const depDir = resolveDir(depService);
|
|
7479
7519
|
const generatedPath = `src/${depDir}/interfaces/${fileName$3(dep)}.interface.ts`;
|
|
7480
7520
|
const currentFilePath = `src/${dirName}/interfaces/${fileName$3(model.name)}.interface.ts`;
|
|
@@ -7697,6 +7737,7 @@ function generateSerializers(models, ctx, shared) {
|
|
|
7697
7737
|
if (isListMetadataModel(model) && !serializerListMetadataNeeded.has(model.name)) continue;
|
|
7698
7738
|
if (isListWrapperModel(model) && !serializerNonPaginatedRefs.has(model.name)) continue;
|
|
7699
7739
|
if (discriminatedSerializerSkip?.has(model.name)) continue;
|
|
7740
|
+
if (isHandOwnedType(ctx, model.name) || isHandOwnedType(ctx, resolveInterfaceName(model.name, ctx, { skipTypeAlias: true }))) continue;
|
|
7700
7741
|
if (!isNodeOwnedService(ctx, modelToService.get(model.name)) && !modelHasNewFields(model, ctx) && !forceGenerateSerializer.has(model.name)) continue;
|
|
7701
7742
|
eligibleModels.push(model);
|
|
7702
7743
|
}
|
|
@@ -7780,12 +7821,20 @@ function generateSerializers(models, ctx, shared) {
|
|
|
7780
7821
|
}
|
|
7781
7822
|
const liveRootForBarrel = ctx.outputDir ?? ctx.targetDir;
|
|
7782
7823
|
for (const [dir, stems] of serializersByDir) {
|
|
7783
|
-
if (liveRootForBarrel
|
|
7824
|
+
if (liveRootForBarrel) {
|
|
7825
|
+
const dirIsOwned = isNodeOwnedService(ctx, dir);
|
|
7784
7826
|
const serializersDir = path.join(liveRootForBarrel, "src", dir, "serializers");
|
|
7785
7827
|
try {
|
|
7786
7828
|
for (const entry of fs.readdirSync(serializersDir)) {
|
|
7787
7829
|
if (!entry.endsWith(".serializer.ts")) continue;
|
|
7788
|
-
|
|
7830
|
+
const stem = entry.replace(/\.serializer\.ts$/, "");
|
|
7831
|
+
if (stems.has(stem)) continue;
|
|
7832
|
+
if (dirIsOwned) {
|
|
7833
|
+
const content = fs.readFileSync(path.join(serializersDir, entry), "utf-8");
|
|
7834
|
+
if (/auto-generated by oagen/i.test(content.slice(0, 400))) continue;
|
|
7835
|
+
if (![...content.matchAll(/export\s+(?:const|function)\s+((?:de)?serialize[A-Za-z0-9_]+)/g)].map((m) => m[1].replace(/^(?:de)?serialize/, "")).some((typeName) => isHandOwnedType(ctx, typeName))) continue;
|
|
7836
|
+
}
|
|
7837
|
+
stems.add(stem);
|
|
7789
7838
|
}
|
|
7790
7839
|
} catch {}
|
|
7791
7840
|
}
|
|
@@ -8069,12 +8118,12 @@ function exportedNamesForSource(ctx, sourceFile) {
|
|
|
8069
8118
|
*/
|
|
8070
8119
|
function generateServiceBarrels(spec, ctx) {
|
|
8071
8120
|
const files = [];
|
|
8072
|
-
const { modelToService, resolveDir } = createServiceDirResolver(spec.models, spec.services, ctx);
|
|
8121
|
+
const { modelToService, resolveDir, serviceNameMap } = createServiceDirResolver(spec.models, spec.services, ctx);
|
|
8073
8122
|
const enumToService = assignEnumsToServices(spec.enums, spec.services, spec.models, ctx);
|
|
8074
8123
|
const dirExports = /* @__PURE__ */ new Map();
|
|
8075
8124
|
const dirSymbols = /* @__PURE__ */ new Map();
|
|
8076
8125
|
const ownedDirNames = /* @__PURE__ */ new Set();
|
|
8077
|
-
for (const service of spec.services) if (isNodeOwnedService(ctx, service.name)) {
|
|
8126
|
+
for (const service of spec.services) if (isNodeOwnedService(ctx, service.name, serviceNameMap.get(service.name))) {
|
|
8078
8127
|
const dir = resolveDir(service.name);
|
|
8079
8128
|
ownedDirNames.add(dir);
|
|
8080
8129
|
if (!dirExports.has(dir)) {
|
|
@@ -8845,12 +8894,12 @@ function buildOptionsObjectTestArg(op, plan, baselineMethod, modelMap, ctx) {
|
|
|
8845
8894
|
entries.push(`${optionField}: ${JSON.stringify(pathParamTestValue(param, localName))}`);
|
|
8846
8895
|
}
|
|
8847
8896
|
if (plan.isPaginated) entries.push("order: 'desc'");
|
|
8848
|
-
const queryParams = plan.isPaginated ? op.queryParams.filter((param) => ![
|
|
8897
|
+
const queryParams = (plan.isPaginated ? op.queryParams.filter((param) => ![
|
|
8849
8898
|
"limit",
|
|
8850
8899
|
"before",
|
|
8851
8900
|
"after",
|
|
8852
8901
|
"order"
|
|
8853
|
-
].includes(param.name)) : op.queryParams;
|
|
8902
|
+
].includes(param.name)) : op.queryParams).filter((param) => !param.deprecated);
|
|
8854
8903
|
for (const param of queryParams) {
|
|
8855
8904
|
const localName = fieldName$6(param.name);
|
|
8856
8905
|
const value = queryParamTestValue(param, modelMap);
|
|
@@ -29869,4 +29918,4 @@ const workosEmittersPlugin = {
|
|
|
29869
29918
|
//#endregion
|
|
29870
29919
|
export { fieldName$2 as A, servicePropertyName$2 as B, apiClassName as C, dotnetEmitter as D, propertyName as E, fieldName$3 as F, fieldName$5 as H, methodName$3 as I, trimMountedResourceFromMethod$2 as L, trimMountedResourceFromMethod$1 as M, goEmitter as N, appendAsyncSuffix as O, className$3 as P, phpEmitter as R, kotlinEmitter as S, packageSegment as T, safeParamName$1 as U, pythonEmitter as V, nodeEmitter as W, rubyEmitter as _, rustExtractor as a, resolveServiceTarget as b, pythonExtractor as c, rustEmitter as d, fieldName as f, typeName as g, resourceAccessorName as h, kotlinExtractor as i, methodName$2 as j, className$2 as k, rubyExtractor as l, moduleName as m, elixirExtractor as n, goExtractor as o, methodName as p, dotnetExtractor as r, phpExtractor as s, workosEmittersPlugin as t, nodeExtractor as u, buildExportedClassNameSet as v, methodName$1 as w, safeParamName as x, fieldName$1 as y, fieldName$4 as z };
|
|
29871
29920
|
|
|
29872
|
-
//# sourceMappingURL=plugin-
|
|
29921
|
+
//# sourceMappingURL=plugin-bqfwowQ3.mjs.map
|