@workos/oagen-emitters 0.7.0 → 0.7.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/dist/plugin.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { t as workosEmittersPlugin } from "./plugin-Bp46oZIh.mjs";
1
+ import { t as workosEmittersPlugin } from "./plugin-CGPujyaL.mjs";
2
2
  export { workosEmittersPlugin };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workos/oagen-emitters",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "description": "WorkOS' oagen emitters",
5
5
  "license": "MIT",
6
6
  "author": "WorkOS",
package/src/php/models.ts CHANGED
@@ -133,6 +133,31 @@ export function generateModels(models: Model[], ctx: EmitterContext): GeneratedF
133
133
  return files;
134
134
  }
135
135
 
136
+ /**
137
+ * Resolve a degenerate union to a single TypeRef when possible.
138
+ * - allOf: PHP collapses to the first variant (mirrors `mapTypeRef`).
139
+ * - oneOf/anyOf where every variant has the same generated PHP type: collapse
140
+ * to that variant (e.g. discriminated unions whose branches the IR pinned to
141
+ * one model name).
142
+ * Returns null when the union is genuinely polymorphic.
143
+ */
144
+ function resolveDegenerateUnion(ref: TypeRef): TypeRef | null {
145
+ if (ref.kind !== 'union') return null;
146
+ if (ref.compositionKind === 'allOf') return ref.variants[0] ?? null;
147
+ if (ref.variants.length === 0) return null;
148
+ const signature = (v: TypeRef): string => {
149
+ if (v.kind === 'model') return `model:${v.name}`;
150
+ if (v.kind === 'enum') return `enum:${v.name}`;
151
+ return `kind:${v.kind}`;
152
+ };
153
+ const first = ref.variants[0];
154
+ const firstSig = signature(first);
155
+ for (const v of ref.variants) {
156
+ if (signature(v) !== firstSig) return null;
157
+ }
158
+ return first;
159
+ }
160
+
136
161
  /**
137
162
  * Generate the fromArray accessor expression for a field.
138
163
  */
@@ -194,8 +219,11 @@ function generateFromArrayValue(ref: TypeRef, accessor: string): string {
194
219
  return accessor;
195
220
  case 'nullable':
196
221
  return generateFromArrayValue(ref.inner, accessor);
197
- case 'union':
222
+ case 'union': {
223
+ const resolved = resolveDegenerateUnion(ref);
224
+ if (resolved) return generateFromArrayValue(resolved, accessor);
198
225
  return accessor;
226
+ }
199
227
  case 'map':
200
228
  return accessor;
201
229
  case 'literal':
@@ -225,6 +253,10 @@ function isComplexType(ref: TypeRef): boolean {
225
253
  return isComplexType(ref.items);
226
254
  case 'nullable':
227
255
  return isComplexType(ref.inner);
256
+ case 'union': {
257
+ const resolved = resolveDegenerateUnion(ref);
258
+ return resolved ? isComplexType(resolved) : false;
259
+ }
228
260
  default:
229
261
  return false;
230
262
  }
@@ -266,8 +298,11 @@ function generateToArrayValue(ref: TypeRef, accessor: string, nullable = false):
266
298
  return generateToArrayValue(ref.inner, accessor, true);
267
299
  case 'map':
268
300
  return accessor;
269
- case 'union':
301
+ case 'union': {
302
+ const resolved = resolveDegenerateUnion(ref);
303
+ if (resolved) return generateToArrayValue(resolved, accessor, nullable);
270
304
  return accessor;
305
+ }
271
306
  case 'literal':
272
307
  return accessor;
273
308
  }
@@ -270,8 +270,13 @@ function generateServiceInits(spec: ApiSpec, ctx: EmitterContext): GeneratedFile
270
270
  const ops = mountGroups.get(mountTarget)?.operations ?? service.operations;
271
271
  const groupClassNames = collectParameterGroupClassNames(ops);
272
272
 
273
+ // Use `X as X` re-export form (PEP 484) so pyright recognizes these as
274
+ // public re-exports. Otherwise consumers importing
275
+ // `from workos.user_management import RoleSingle` get a private-import
276
+ // warning under strict mode. Models barrel uses the same convention.
273
277
  const resourceImports = [resolvedName, `Async${resolvedName}`, ...groupClassNames];
274
- lines.push(`from ._resource import ${resourceImports.join(', ')}`);
278
+ const aliasedImports = resourceImports.map((n) => `${n} as ${n}`);
279
+ lines.push(`from ._resource import ${aliasedImports.join(', ')}`);
275
280
  lines.push('from .models import *');
276
281
 
277
282
  files.push({
@@ -103,7 +103,9 @@ describe('generateClient', () => {
103
103
 
104
104
  const serviceInit = files.find((f) => f.path === 'src/workos/organizations/__init__.py');
105
105
  expect(serviceInit).toBeDefined();
106
- expect(serviceInit!.content).toContain('from ._resource import Organizations, AsyncOrganizations');
106
+ expect(serviceInit!.content).toContain(
107
+ 'from ._resource import Organizations as Organizations, AsyncOrganizations as AsyncOrganizations',
108
+ );
107
109
  });
108
110
 
109
111
  it('generates flat directory structure for services (no nested namespaces)', () => {
@@ -193,7 +195,7 @@ describe('generateClient', () => {
193
195
  expect(serviceInit!.content).toContain('RoleSingle');
194
196
  expect(serviceInit!.content).toContain('RoleMultiple');
195
197
  expect(serviceInit!.content).toContain(
196
- 'from ._resource import UserManagement, AsyncUserManagement, RoleSingle, RoleMultiple',
198
+ 'from ._resource import UserManagement as UserManagement, AsyncUserManagement as AsyncUserManagement, RoleSingle as RoleSingle, RoleMultiple as RoleMultiple',
197
199
  );
198
200
  });
199
201