@workos/oagen-emitters 0.2.0 → 0.3.0
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/.husky/pre-commit +1 -0
- package/.oxfmtrc.json +8 -1
- package/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +15 -0
- package/README.md +129 -0
- package/dist/index.d.mts +10 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +11943 -2728
- package/dist/index.mjs.map +1 -1
- package/docs/sdk-architecture/go.md +338 -0
- package/docs/sdk-architecture/php.md +315 -0
- package/docs/sdk-architecture/python.md +511 -0
- package/oagen.config.ts +298 -2
- package/package.json +9 -5
- package/scripts/generate-php.js +13 -0
- package/scripts/git-push-with-published-oagen.sh +21 -0
- package/smoke/sdk-dotnet.ts +17 -3
- package/smoke/sdk-elixir.ts +17 -3
- package/smoke/sdk-go.ts +137 -46
- package/smoke/sdk-kotlin.ts +23 -4
- package/smoke/sdk-node.ts +15 -3
- package/smoke/sdk-php.ts +28 -26
- package/smoke/sdk-python.ts +5 -2
- package/smoke/sdk-ruby.ts +17 -3
- package/smoke/sdk-rust.ts +16 -3
- package/src/go/client.ts +141 -0
- package/src/go/enums.ts +196 -0
- package/src/go/fixtures.ts +212 -0
- package/src/go/index.ts +81 -0
- package/src/go/manifest.ts +36 -0
- package/src/go/models.ts +254 -0
- package/src/go/naming.ts +191 -0
- package/src/go/resources.ts +827 -0
- package/src/go/tests.ts +751 -0
- package/src/go/type-map.ts +82 -0
- package/src/go/wrappers.ts +261 -0
- package/src/index.ts +3 -0
- package/src/node/client.ts +167 -122
- package/src/node/enums.ts +13 -4
- package/src/node/errors.ts +42 -233
- package/src/node/field-plan.ts +726 -0
- package/src/node/fixtures.ts +15 -5
- package/src/node/index.ts +65 -16
- package/src/node/models.ts +264 -96
- package/src/node/naming.ts +52 -25
- package/src/node/resources.ts +621 -172
- package/src/node/sdk-errors.ts +41 -0
- package/src/node/tests.ts +71 -27
- package/src/node/type-map.ts +4 -2
- package/src/node/utils.ts +56 -64
- package/src/node/wrappers.ts +151 -0
- package/src/php/client.ts +171 -0
- package/src/php/enums.ts +67 -0
- package/src/php/errors.ts +9 -0
- package/src/php/fixtures.ts +181 -0
- package/src/php/index.ts +96 -0
- package/src/php/manifest.ts +36 -0
- package/src/php/models.ts +310 -0
- package/src/php/naming.ts +298 -0
- package/src/php/resources.ts +561 -0
- package/src/php/tests.ts +533 -0
- package/src/php/type-map.ts +90 -0
- package/src/php/utils.ts +18 -0
- package/src/php/wrappers.ts +151 -0
- package/src/python/client.ts +337 -0
- package/src/python/enums.ts +313 -0
- package/src/python/fixtures.ts +196 -0
- package/src/python/index.ts +95 -0
- package/src/python/manifest.ts +38 -0
- package/src/python/models.ts +688 -0
- package/src/python/naming.ts +209 -0
- package/src/python/resources.ts +1322 -0
- package/src/python/tests.ts +1335 -0
- package/src/python/type-map.ts +93 -0
- package/src/python/wrappers.ts +191 -0
- package/src/shared/model-utils.ts +255 -0
- package/src/shared/naming-utils.ts +107 -0
- package/src/shared/non-spec-services.ts +54 -0
- package/src/shared/resolved-ops.ts +109 -0
- package/src/shared/wrapper-utils.ts +59 -0
- package/test/go/client.test.ts +92 -0
- package/test/go/enums.test.ts +132 -0
- package/test/go/errors.test.ts +9 -0
- package/test/go/models.test.ts +265 -0
- package/test/go/resources.test.ts +408 -0
- package/test/go/tests.test.ts +143 -0
- package/test/node/client.test.ts +199 -94
- package/test/node/enums.test.ts +75 -3
- package/test/node/errors.test.ts +2 -41
- package/test/node/models.test.ts +109 -20
- package/test/node/naming.test.ts +37 -4
- package/test/node/resources.test.ts +662 -30
- package/test/node/serializers.test.ts +36 -7
- package/test/node/type-map.test.ts +11 -0
- package/test/php/client.test.ts +94 -0
- package/test/php/enums.test.ts +173 -0
- package/test/php/errors.test.ts +9 -0
- package/test/php/models.test.ts +497 -0
- package/test/php/resources.test.ts +644 -0
- package/test/php/tests.test.ts +118 -0
- package/test/python/client.test.ts +200 -0
- package/test/python/enums.test.ts +228 -0
- package/test/python/errors.test.ts +16 -0
- package/test/python/manifest.test.ts +74 -0
- package/test/python/models.test.ts +716 -0
- package/test/python/resources.test.ts +617 -0
- package/test/python/tests.test.ts +202 -0
- package/src/node/common.ts +0 -273
- package/src/node/config.ts +0 -71
- package/src/node/serializers.ts +0 -744
package/src/node/naming.ts
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import type { Operation, Service, EmitterContext } from '@workos/oagen';
|
|
2
2
|
import { toPascalCase, toCamelCase, toKebabCase, toSnakeCase } from '@workos/oagen';
|
|
3
|
+
import { buildResolvedLookup, lookupMethodName } from '../shared/resolved-ops.js';
|
|
4
|
+
import { stripUrnPrefix } from '../shared/naming-utils.js';
|
|
5
|
+
|
|
6
|
+
/** Strip spec-noise suffixes (e.g., "Dto") from an IR name. */
|
|
7
|
+
export function stripNoiseSuffixes(name: string): string {
|
|
8
|
+
return name.replace(/Dto$/i, '');
|
|
9
|
+
}
|
|
3
10
|
|
|
4
11
|
/** PascalCase class/interface name. */
|
|
5
12
|
export function className(name: string): string {
|
|
6
|
-
return toPascalCase(name);
|
|
13
|
+
return toPascalCase(stripUrnPrefix(name));
|
|
7
14
|
}
|
|
8
15
|
|
|
9
16
|
/** kebab-case file name (without extension). */
|
|
10
17
|
export function fileName(name: string): string {
|
|
11
|
-
return toKebabCase(name);
|
|
18
|
+
return toKebabCase(stripUrnPrefix(name));
|
|
12
19
|
}
|
|
13
20
|
|
|
14
21
|
/** camelCase method name. */
|
|
@@ -66,33 +73,33 @@ export function buildServiceNameMap(services: Service[], ctx: EmitterContext): M
|
|
|
66
73
|
return map;
|
|
67
74
|
}
|
|
68
75
|
|
|
69
|
-
/**
|
|
76
|
+
/**
|
|
77
|
+
* Resolve the output directory for a service.
|
|
78
|
+
* Mount rules already handle directory placement, so this is a simple kebab-case conversion.
|
|
79
|
+
*/
|
|
80
|
+
export function resolveServiceDir(resolvedServiceName: string): string {
|
|
81
|
+
return serviceDirName(resolvedServiceName);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Resolve the SDK method name for an operation, using resolved operations first. */
|
|
70
85
|
export function resolveMethodName(op: Operation, _service: Service, ctx: EmitterContext): string {
|
|
86
|
+
const lookup = buildResolvedLookup(ctx);
|
|
87
|
+
const resolved = lookupMethodName(op, lookup);
|
|
88
|
+
if (resolved) return toCamelCase(resolved);
|
|
89
|
+
// Fallback to overlay, then spec-derived
|
|
71
90
|
const httpKey = `${op.httpMethod.toUpperCase()} ${op.path}`;
|
|
72
91
|
const existing = ctx.overlayLookup?.methodByOperation?.get(httpKey);
|
|
73
|
-
if (existing)
|
|
74
|
-
// Fix: when the path ends with a path parameter (single-resource operation)
|
|
75
|
-
// and the overlay method name is plural, prefer the singular form.
|
|
76
|
-
// E.g., getUsers → getUser when path is /user_management/users/{id}
|
|
77
|
-
const isSingleResource = /\/\{[^}]+\}$/.test(op.path);
|
|
78
|
-
if (isSingleResource && existing.methodName.endsWith('s') && !existing.methodName.endsWith('ss')) {
|
|
79
|
-
const singular = existing.methodName.slice(0, -1);
|
|
80
|
-
// Only singularize if it looks like a typical pluralization (ends in 's')
|
|
81
|
-
// and the spec-derived name agrees it should be singular
|
|
82
|
-
const specDerived = toCamelCase(op.name);
|
|
83
|
-
if (specDerived === singular || specDerived.endsWith(singular.slice(singular.length - 4))) {
|
|
84
|
-
return singular;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
return existing.methodName;
|
|
88
|
-
}
|
|
92
|
+
if (existing) return existing.methodName;
|
|
89
93
|
return toCamelCase(op.name);
|
|
90
94
|
}
|
|
91
95
|
|
|
92
|
-
/** Resolve the SDK class name for a service,
|
|
96
|
+
/** Resolve the SDK class name for a service, using resolved ops mountOn as canonical. */
|
|
93
97
|
export function resolveClassName(service: Service, ctx: EmitterContext): string {
|
|
94
|
-
//
|
|
95
|
-
|
|
98
|
+
// Use resolved ops mountOn as canonical class name
|
|
99
|
+
for (const r of ctx.resolvedOperations ?? []) {
|
|
100
|
+
if (r.service.name === service.name) return r.mountOn;
|
|
101
|
+
}
|
|
102
|
+
// Fallback to overlay
|
|
96
103
|
if (ctx.overlayLookup?.methodByOperation) {
|
|
97
104
|
for (const op of service.operations) {
|
|
98
105
|
const httpKey = `${op.httpMethod.toUpperCase()} ${op.path}`;
|
|
@@ -103,9 +110,29 @@ export function resolveClassName(service: Service, ctx: EmitterContext): string
|
|
|
103
110
|
return toPascalCase(service.name);
|
|
104
111
|
}
|
|
105
112
|
|
|
106
|
-
/** Resolve the interface name for a model, checking overlay first.
|
|
107
|
-
|
|
113
|
+
/** Resolve the interface name for a model, checking overlay first.
|
|
114
|
+
*
|
|
115
|
+
* @param opts.skipTypeAlias - When true, skip apiSurface typeAlias resolution.
|
|
116
|
+
* Use this for dedup models to ensure the file exports match the import
|
|
117
|
+
* names (preserved files export the raw name, not the resolved alias).
|
|
118
|
+
*/
|
|
119
|
+
export function resolveInterfaceName(name: string, ctx: EmitterContext, opts?: { skipTypeAlias?: boolean }): string {
|
|
108
120
|
const existing = ctx.overlayLookup?.interfaceByName?.get(name);
|
|
109
121
|
if (existing) return existing;
|
|
110
|
-
|
|
122
|
+
|
|
123
|
+
// If the model name is a type alias that points to a canonical interface,
|
|
124
|
+
// use the canonical name. This prevents the merger from generating unused
|
|
125
|
+
// backward-compat aliases (e.g., `type FlagOwner = FeatureFlagOwner`).
|
|
126
|
+
if (!opts?.skipTypeAlias && ctx.apiSurface?.typeAliases) {
|
|
127
|
+
const alias = ctx.apiSurface.typeAliases[name] as { value?: string } | undefined;
|
|
128
|
+
if (alias?.value && ctx.apiSurface.interfaces?.[alias.value]) {
|
|
129
|
+
return alias.value;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Strip spec-noise suffixes (e.g., "Dto") only for models without a
|
|
134
|
+
// baseline. When an overlay exists (Scenario A), the overlay check above
|
|
135
|
+
// handles existing models. New models (no overlay entry) get clean names.
|
|
136
|
+
const cleaned = ctx.apiSurface ? name : stripNoiseSuffixes(name);
|
|
137
|
+
return toPascalCase(stripUrnPrefix(cleaned));
|
|
111
138
|
}
|