@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.
Files changed (110) hide show
  1. package/.husky/pre-commit +1 -0
  2. package/.oxfmtrc.json +8 -1
  3. package/.release-please-manifest.json +1 -1
  4. package/CHANGELOG.md +15 -0
  5. package/README.md +129 -0
  6. package/dist/index.d.mts +10 -1
  7. package/dist/index.d.mts.map +1 -1
  8. package/dist/index.mjs +11943 -2728
  9. package/dist/index.mjs.map +1 -1
  10. package/docs/sdk-architecture/go.md +338 -0
  11. package/docs/sdk-architecture/php.md +315 -0
  12. package/docs/sdk-architecture/python.md +511 -0
  13. package/oagen.config.ts +298 -2
  14. package/package.json +9 -5
  15. package/scripts/generate-php.js +13 -0
  16. package/scripts/git-push-with-published-oagen.sh +21 -0
  17. package/smoke/sdk-dotnet.ts +17 -3
  18. package/smoke/sdk-elixir.ts +17 -3
  19. package/smoke/sdk-go.ts +137 -46
  20. package/smoke/sdk-kotlin.ts +23 -4
  21. package/smoke/sdk-node.ts +15 -3
  22. package/smoke/sdk-php.ts +28 -26
  23. package/smoke/sdk-python.ts +5 -2
  24. package/smoke/sdk-ruby.ts +17 -3
  25. package/smoke/sdk-rust.ts +16 -3
  26. package/src/go/client.ts +141 -0
  27. package/src/go/enums.ts +196 -0
  28. package/src/go/fixtures.ts +212 -0
  29. package/src/go/index.ts +81 -0
  30. package/src/go/manifest.ts +36 -0
  31. package/src/go/models.ts +254 -0
  32. package/src/go/naming.ts +191 -0
  33. package/src/go/resources.ts +827 -0
  34. package/src/go/tests.ts +751 -0
  35. package/src/go/type-map.ts +82 -0
  36. package/src/go/wrappers.ts +261 -0
  37. package/src/index.ts +3 -0
  38. package/src/node/client.ts +167 -122
  39. package/src/node/enums.ts +13 -4
  40. package/src/node/errors.ts +42 -233
  41. package/src/node/field-plan.ts +726 -0
  42. package/src/node/fixtures.ts +15 -5
  43. package/src/node/index.ts +65 -16
  44. package/src/node/models.ts +264 -96
  45. package/src/node/naming.ts +52 -25
  46. package/src/node/resources.ts +621 -172
  47. package/src/node/sdk-errors.ts +41 -0
  48. package/src/node/tests.ts +71 -27
  49. package/src/node/type-map.ts +4 -2
  50. package/src/node/utils.ts +56 -64
  51. package/src/node/wrappers.ts +151 -0
  52. package/src/php/client.ts +171 -0
  53. package/src/php/enums.ts +67 -0
  54. package/src/php/errors.ts +9 -0
  55. package/src/php/fixtures.ts +181 -0
  56. package/src/php/index.ts +96 -0
  57. package/src/php/manifest.ts +36 -0
  58. package/src/php/models.ts +310 -0
  59. package/src/php/naming.ts +298 -0
  60. package/src/php/resources.ts +561 -0
  61. package/src/php/tests.ts +533 -0
  62. package/src/php/type-map.ts +90 -0
  63. package/src/php/utils.ts +18 -0
  64. package/src/php/wrappers.ts +151 -0
  65. package/src/python/client.ts +337 -0
  66. package/src/python/enums.ts +313 -0
  67. package/src/python/fixtures.ts +196 -0
  68. package/src/python/index.ts +95 -0
  69. package/src/python/manifest.ts +38 -0
  70. package/src/python/models.ts +688 -0
  71. package/src/python/naming.ts +209 -0
  72. package/src/python/resources.ts +1322 -0
  73. package/src/python/tests.ts +1335 -0
  74. package/src/python/type-map.ts +93 -0
  75. package/src/python/wrappers.ts +191 -0
  76. package/src/shared/model-utils.ts +255 -0
  77. package/src/shared/naming-utils.ts +107 -0
  78. package/src/shared/non-spec-services.ts +54 -0
  79. package/src/shared/resolved-ops.ts +109 -0
  80. package/src/shared/wrapper-utils.ts +59 -0
  81. package/test/go/client.test.ts +92 -0
  82. package/test/go/enums.test.ts +132 -0
  83. package/test/go/errors.test.ts +9 -0
  84. package/test/go/models.test.ts +265 -0
  85. package/test/go/resources.test.ts +408 -0
  86. package/test/go/tests.test.ts +143 -0
  87. package/test/node/client.test.ts +199 -94
  88. package/test/node/enums.test.ts +75 -3
  89. package/test/node/errors.test.ts +2 -41
  90. package/test/node/models.test.ts +109 -20
  91. package/test/node/naming.test.ts +37 -4
  92. package/test/node/resources.test.ts +662 -30
  93. package/test/node/serializers.test.ts +36 -7
  94. package/test/node/type-map.test.ts +11 -0
  95. package/test/php/client.test.ts +94 -0
  96. package/test/php/enums.test.ts +173 -0
  97. package/test/php/errors.test.ts +9 -0
  98. package/test/php/models.test.ts +497 -0
  99. package/test/php/resources.test.ts +644 -0
  100. package/test/php/tests.test.ts +118 -0
  101. package/test/python/client.test.ts +200 -0
  102. package/test/python/enums.test.ts +228 -0
  103. package/test/python/errors.test.ts +16 -0
  104. package/test/python/manifest.test.ts +74 -0
  105. package/test/python/models.test.ts +716 -0
  106. package/test/python/resources.test.ts +617 -0
  107. package/test/python/tests.test.ts +202 -0
  108. package/src/node/common.ts +0 -273
  109. package/src/node/config.ts +0 -71
  110. package/src/node/serializers.ts +0 -744
package/oagen.config.ts CHANGED
@@ -1,6 +1,9 @@
1
- import type { OagenConfig } from '@workos/oagen';
1
+ import type { OagenConfig, OperationHint } from '@workos/oagen';
2
2
  import { toCamelCase } from '@workos/oagen';
3
3
  import { nodeEmitter } from './src/node/index.js';
4
+ import { pythonEmitter } from './src/python/index.js';
5
+ import { phpEmitter } from './src/php/index.js';
6
+ import { goEmitter } from './src/go/index.js';
4
7
  import { nodeExtractor } from './src/compat/extractors/node.js';
5
8
  import { rubyExtractor } from './src/compat/extractors/ruby.js';
6
9
  import { pythonExtractor } from './src/compat/extractors/python.js';
@@ -21,8 +24,282 @@ function nestjsOperationIdTransform(id: string): string {
21
24
  return idx !== -1 ? toCamelCase(stripped.slice(idx + 1)) : toCamelCase(stripped);
22
25
  }
23
26
 
27
+ // ---------------------------------------------------------------------------
28
+ // Operation hints — per-operation overrides for the operation resolver.
29
+ // Keyed by "METHOD /path". Only operations that need overrides are listed;
30
+ // the algorithm handles the rest.
31
+ // ---------------------------------------------------------------------------
32
+ const operationHints: Record<string, OperationHint> = {
33
+ // ── Radar ────────────────────────────────────────────────────────────────
34
+ 'POST /radar/lists/{type}/{action}': { name: 'add_list_entry' },
35
+ 'DELETE /radar/lists/{type}/{action}': { name: 'remove_list_entry' },
36
+
37
+ // ── SSO ──────────────────────────────────────────────────────────────────
38
+ 'GET /sso/authorize': {
39
+ name: 'get_authorization_url',
40
+ defaults: { response_type: 'code' },
41
+ inferFromClient: ['client_id'],
42
+ },
43
+ 'GET /sso/logout': { name: 'get_logout_url' },
44
+ 'GET /sso/profile': { name: 'get_profile' },
45
+ 'POST /sso/token': {
46
+ name: 'get_profile_and_token',
47
+ defaults: { grant_type: 'authorization_code' },
48
+ inferFromClient: ['client_id', 'client_secret'],
49
+ },
50
+
51
+ // ── SSO / JWKS (mounted on UserManagement via mountRules) ────────────────
52
+ 'GET /sso/jwks/{clientId}': { name: 'get_jwks' },
53
+
54
+ // ── User Management — auth ──────────────────────────────────────────────
55
+ 'GET /user_management/authorize': {
56
+ name: 'get_authorization_url',
57
+ defaults: { response_type: 'code' },
58
+ inferFromClient: ['client_id'],
59
+ },
60
+ 'GET /user_management/sessions/logout': { name: 'get_logout_url' },
61
+
62
+ // ── User Management — org membership actions ────────────────────────────
63
+ 'PUT /user_management/organization_memberships/{id}/deactivate': {
64
+ name: 'deactivate_organization_membership',
65
+ },
66
+ 'PUT /user_management/organization_memberships/{id}/reactivate': {
67
+ name: 'reactivate_organization_membership',
68
+ },
69
+
70
+ // ── Admin Portal ────────────────────────────────────────────────────────
71
+ 'POST /portal/generate_link': { name: 'generate_link' },
72
+
73
+ // ── Feature Flags — disambiguate co-mounted list operations ─────────────
74
+ 'GET /organizations/{organizationId}/feature-flags': { name: 'list_organization_feature_flags' },
75
+ 'GET /user_management/users/{userId}/feature-flags': { name: 'list_user_feature_flags' },
76
+
77
+ // ── External ID lookups (not derivable from path) ──────────────────────
78
+ 'GET /organizations/external_id/{external_id}': { name: 'get_organization_by_external_id' },
79
+ 'GET /user_management/users/external_id/{external_id}': { name: 'get_user_by_external_id' },
80
+
81
+ // ── Authorization — environment-scoped roles ─────────────────────────────
82
+ 'GET /authorization/roles': { name: 'list_environment_roles' },
83
+ 'POST /authorization/roles': { name: 'create_environment_role' },
84
+ 'GET /authorization/roles/{slug}': { name: 'get_environment_role' },
85
+ 'PATCH /authorization/roles/{slug}': { name: 'update_environment_role' },
86
+ 'PUT /authorization/roles/{slug}/permissions': {
87
+ name: 'set_environment_role_permissions',
88
+ },
89
+ 'POST /authorization/roles/{slug}/permissions': {
90
+ name: 'add_environment_role_permission',
91
+ },
92
+
93
+ // ── Authorization — singularized/shortened names ────────────────────────
94
+ 'POST /authorization/permissions': { name: 'create_permission' },
95
+ 'POST /authorization/resources': { name: 'create_resource' },
96
+ 'POST /authorization/organization_memberships/{organization_membership_id}/check': {
97
+ name: 'check',
98
+ },
99
+ 'POST /authorization/organization_memberships/{organization_membership_id}/role_assignments': {
100
+ name: 'assign_role',
101
+ },
102
+ 'DELETE /authorization/organization_memberships/{organization_membership_id}/role_assignments': {
103
+ name: 'remove_role',
104
+ },
105
+ 'POST /authorization/organizations/{organizationId}/roles': {
106
+ name: 'create_organization_role',
107
+ },
108
+
109
+ // ── Authorization — env-scoped resource memberships ────────────────────
110
+ 'GET /authorization/resources/{resource_id}/organization_memberships': { name: 'list_memberships_for_resource' },
111
+
112
+ // ── User Management — singularized/shortened names ─────────────────────
113
+ 'POST /user_management/users': { name: 'create_user' },
114
+ 'POST /user_management/organization_memberships': {
115
+ name: 'create_organization_membership',
116
+ },
117
+ 'POST /user_management/invitations': { name: 'send_invitation' },
118
+ 'GET /user_management/invitations/by_token/{token}': {
119
+ name: 'find_invitation_by_token',
120
+ },
121
+ 'POST /user_management/users/{id}/email_verification/send': {
122
+ name: 'send_verification_email',
123
+ },
124
+ 'POST /user_management/users/{id}/email_verification/confirm': {
125
+ name: 'verify_email',
126
+ },
127
+ 'POST /user_management/password_reset': { name: 'reset_password' },
128
+ 'POST /user_management/password_reset/confirm': {
129
+ name: 'confirm_password_reset',
130
+ },
131
+ 'GET /user_management/users/{id}/sessions': { name: 'list_sessions' },
132
+ 'GET /user_management/users/{id}/identities': { name: 'get_user_identities' },
133
+ 'POST /user_management/cors_origins': { name: 'create_cors_origin' },
134
+ 'POST /user_management/redirect_uris': { name: 'create_redirect_uri' },
135
+
136
+ // ── Organizations — singularized names ─────────────────────────────────
137
+ 'POST /organizations': { name: 'create_organization' },
138
+
139
+ // ── Directory Sync — shortened names ───────────────────────────────────
140
+ 'GET /directory_groups': { name: 'list_groups' },
141
+ 'GET /directory_groups/{id}': { name: 'get_group' },
142
+ 'GET /directory_users': { name: 'list_users' },
143
+ 'GET /directory_users/{id}': { name: 'get_user' },
144
+
145
+ // ── Audit Logs — singularized names ────────────────────────────────────
146
+ 'POST /audit_logs/events': { name: 'create_event' },
147
+ 'POST /audit_logs/exports': { name: 'create_export' },
148
+ 'POST /audit_logs/actions/{actionName}/schemas': { name: 'create_schema' },
149
+
150
+ // ── Feature Flags — match SDK conventions ──────────────────────────────
151
+ 'POST /feature-flags/{slug}/targets/{resourceId}': { name: 'add_flag_target' },
152
+ 'DELETE /feature-flags/{slug}/targets/{resourceId}': {
153
+ name: 'remove_flag_target',
154
+ },
155
+
156
+ // ── Organizations — audit logs retention (mounted on AuditLogs) ─────────
157
+ 'GET /organizations/{id}/audit_logs_retention': { mountOn: 'AuditLogs' },
158
+ 'PUT /organizations/{id}/audit_logs_retention': { mountOn: 'AuditLogs' },
159
+
160
+ // ── Union split: POST /user_management/authenticate (8 variants) ────────
161
+ 'POST /user_management/authenticate': {
162
+ split: [
163
+ {
164
+ name: 'authenticate_with_password',
165
+ targetVariant: 'PasswordSessionAuthenticateRequest',
166
+ defaults: { grant_type: 'password' },
167
+ inferFromClient: ['client_id', 'client_secret'],
168
+ exposedParams: ['email', 'password', 'invitation_token'],
169
+ },
170
+ {
171
+ name: 'authenticate_with_code',
172
+ targetVariant: 'CodeSessionAuthenticateRequest',
173
+ defaults: { grant_type: 'authorization_code' },
174
+ inferFromClient: ['client_id', 'client_secret'],
175
+ exposedParams: ['code'],
176
+ },
177
+ {
178
+ name: 'authenticate_with_refresh_token',
179
+ targetVariant: 'RefreshTokenSessionAuthenticateRequest',
180
+ defaults: { grant_type: 'refresh_token' },
181
+ inferFromClient: ['client_id', 'client_secret'],
182
+ exposedParams: ['refresh_token', 'organization_id'],
183
+ },
184
+ {
185
+ name: 'authenticate_with_magic_auth',
186
+ targetVariant: 'MagicAuthSessionAuthenticateRequest',
187
+ defaults: { grant_type: 'urn:workos:oauth:grant-type:magic-auth:code' },
188
+ inferFromClient: ['client_id', 'client_secret'],
189
+ exposedParams: ['code', 'email', 'invitation_token'],
190
+ },
191
+ {
192
+ name: 'authenticate_with_email_verification',
193
+ targetVariant: 'EmailVerificationSessionAuthenticateRequest',
194
+ defaults: { grant_type: 'urn:workos:oauth:grant-type:email-verification:code' },
195
+ inferFromClient: ['client_id', 'client_secret'],
196
+ exposedParams: ['code', 'pending_authentication_token'],
197
+ },
198
+ {
199
+ name: 'authenticate_with_totp',
200
+ targetVariant: 'TotpSessionAuthenticateRequest',
201
+ defaults: { grant_type: 'urn:workos:oauth:grant-type:mfa-totp' },
202
+ inferFromClient: ['client_id', 'client_secret'],
203
+ exposedParams: ['code', 'pending_authentication_token', 'authentication_challenge_id'],
204
+ },
205
+ {
206
+ name: 'authenticate_with_organization_selection',
207
+ targetVariant: 'OrganizationSelectionSessionAuthenticateRequest',
208
+ defaults: { grant_type: 'urn:workos:oauth:grant-type:organization-selection' },
209
+ inferFromClient: ['client_id', 'client_secret'],
210
+ exposedParams: ['pending_authentication_token', 'organization_id'],
211
+ },
212
+ {
213
+ name: 'authenticate_with_device_code',
214
+ targetVariant: 'DeviceCodeSessionAuthenticateRequest',
215
+ defaults: { grant_type: 'urn:ietf:params:oauth:grant-type:device_code' },
216
+ inferFromClient: ['client_id'],
217
+ exposedParams: ['device_code'],
218
+ },
219
+ ],
220
+ },
221
+
222
+ // ── Union split: POST /connect/applications (2 variants) ────────────────
223
+ 'POST /connect/applications': {
224
+ split: [
225
+ {
226
+ name: 'create_oauth_application',
227
+ targetVariant: 'CreateOAuthApplication',
228
+ defaults: { application_type: 'oauth' },
229
+ exposedParams: [
230
+ 'name',
231
+ 'is_first_party',
232
+ 'description',
233
+ 'scopes',
234
+ 'redirect_uris',
235
+ 'uses_pkce',
236
+ 'organization_id',
237
+ ],
238
+ },
239
+ {
240
+ name: 'create_m2m_application',
241
+ targetVariant: 'CreateM2MApplication',
242
+ defaults: { application_type: 'm2m' },
243
+ exposedParams: ['name', 'organization_id', 'description', 'scopes'],
244
+ },
245
+ ],
246
+ },
247
+ };
248
+
249
+ // ---------------------------------------------------------------------------
250
+ // Mount rules — service-level remounting. Maps IR service name → target
251
+ // service/namespace (PascalCase). All operations in the source service are
252
+ // mounted on the target unless overridden per-operation in operationHints.
253
+ // ---------------------------------------------------------------------------
254
+ const mountRules: Record<string, string> = {
255
+ // MFA sub-services → MultiFactorAuth
256
+ MultiFactorAuthChallenges: 'MultiFactorAuth',
257
+
258
+ // RBAC permissions → Authorization
259
+ Permissions: 'Authorization',
260
+
261
+ // Connect sub-services → Connect
262
+ WorkosConnect: 'Connect',
263
+ Applications: 'Connect',
264
+ ApplicationClientSecrets: 'Connect',
265
+
266
+ // SSO connections → SSO
267
+ Connections: 'SSO',
268
+
269
+ // Directory Sync sub-services → DirectorySync
270
+ Directories: 'DirectorySync',
271
+ DirectoryGroups: 'DirectorySync',
272
+ DirectoryUsers: 'DirectorySync',
273
+
274
+ // Feature flag sub-services → FeatureFlags
275
+ FeatureFlagsTargets: 'FeatureFlags',
276
+ OrganizationsFeatureFlags: 'FeatureFlags',
277
+ UserManagementUsersFeatureFlags: 'FeatureFlags',
278
+
279
+ // Org API keys → ApiKeys
280
+ OrganizationsApiKeys: 'ApiKeys',
281
+
282
+ // User Management sub-services → UserManagement
283
+ UserManagementSessionTokens: 'UserManagement',
284
+ UserManagementAuthentication: 'UserManagement',
285
+ UserManagementCorsOrigins: 'UserManagement',
286
+ UserManagementUsers: 'UserManagement',
287
+ UserManagementInvitations: 'UserManagement',
288
+ UserManagementJWTTemplate: 'UserManagement',
289
+ UserManagementMagicAuth: 'UserManagement',
290
+ UserManagementOrganizationMembership: 'UserManagement',
291
+ UserManagementRedirectUris: 'UserManagement',
292
+ UserManagementUsersAuthorizedApplications: 'UserManagement',
293
+
294
+ // Pipes / Data Providers → Pipes
295
+ UserManagementDataProviders: 'Pipes',
296
+
297
+ // User Management MFA → MultiFactorAuth
298
+ UserManagementMultiFactorAuthentication: 'MultiFactorAuth',
299
+ };
300
+
24
301
  const config: OagenConfig = {
25
- emitters: [nodeEmitter],
302
+ emitters: [nodeEmitter, pythonEmitter, phpEmitter, goEmitter],
26
303
  extractors: [
27
304
  nodeExtractor,
28
305
  rubyExtractor,
@@ -47,5 +324,24 @@ const config: OagenConfig = {
47
324
  },
48
325
  docUrl: 'https://workos.com/docs',
49
326
  operationIdTransform: nestjsOperationIdTransform,
327
+ schemaNameTransform: (name: string) => {
328
+ // Explicit renames for Dto models that collide with response models
329
+ const COLLISION_RENAMES: Record<string, string> = {
330
+ OrganizationDto: 'OrganizationInput',
331
+ RedirectUriDto: 'RedirectUriInput',
332
+ // Generic list-derived names that need domain-specific identifiers
333
+ ListData: 'Role',
334
+ ListModel: 'RoleList',
335
+ // Double-List naming artifact
336
+ EventListListMetadata: 'EventListMetadata',
337
+ };
338
+ if (COLLISION_RENAMES[name]) return COLLISION_RENAMES[name];
339
+ return name
340
+ .replace(/Dto/g, '')
341
+ .replace(/DTO/g, '')
342
+ .replace(/^Urn(?:IetfParams|Workos)O[Aa]uthGrantType/, '');
343
+ },
344
+ operationHints,
345
+ mountRules,
50
346
  };
51
347
  export default config;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workos/oagen-emitters",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "WorkOS' oagen emitters",
5
5
  "license": "MIT",
6
6
  "author": "WorkOS",
@@ -28,6 +28,10 @@
28
28
  "test": "vitest run",
29
29
  "test:watch": "vitest",
30
30
  "typecheck": "tsc --noEmit",
31
+ "git:push": "sh ./scripts/git-push-with-published-oagen.sh",
32
+ "oagen:build:local": "npm --prefix ../oagen run build",
33
+ "oagen:use:local": "npm run oagen:build:local && npm link ../oagen",
34
+ "oagen:use:published": "sh -c 'npm unlink @workos/oagen >/dev/null 2>&1 || true; npm install --ignore-scripts @workos/oagen@^0.4.0'",
31
35
  "prepare": "husky",
32
36
  "sdk:generate:dotnet": "oagen generate --lang dotnet --output ./sdk-dotnet --namespace workos --api-surface ./sdk-dotnet-surface.json",
33
37
  "sdk:verify:dotnet": "oagen verify --lang dotnet --output ./sdk-dotnet --api-surface ./sdk-dotnet-surface.json",
@@ -44,7 +48,7 @@
44
48
  "sdk:generate:node": "oagen generate --lang node --output ./sdk-node --namespace workos --api-surface ./sdk-node-surface.json",
45
49
  "sdk:verify:node": "oagen verify --lang node --output ./sdk-node --api-surface ./sdk-node-surface.json",
46
50
  "sdk:extract:node": "oagen extract --lang node --sdk-path ../backend/workos-node --output ./sdk-node-surface.json",
47
- "sdk:generate:php": "oagen generate --lang php --output ./sdk-php --namespace workos --api-surface ./sdk-php-surface.json",
51
+ "sdk:generate:php": "node scripts/generate-php.js",
48
52
  "sdk:verify:php": "oagen verify --lang php --output ./sdk-php --api-surface ./sdk-php-surface.json",
49
53
  "sdk:extract:php": "oagen extract --lang php --sdk-path ../backend/workos-php --output ./sdk-php-surface.json",
50
54
  "sdk:generate:python": "oagen generate --lang python --output ./sdk-python --namespace workos --api-surface ./sdk-python-surface.json",
@@ -57,9 +61,6 @@
57
61
  "sdk:verify:rust": "oagen verify --lang rust --output ./sdk-rust --api-surface ./sdk-rust-surface.json",
58
62
  "sdk:extract:rust": "oagen extract --lang rust --sdk-path ../backend/workos-rust --output ./sdk-rust-surface.json"
59
63
  },
60
- "dependencies": {
61
- "@workos/oagen": "^0.2.0"
62
- },
63
64
  "devDependencies": {
64
65
  "@commitlint/cli": "^20.5.0",
65
66
  "@commitlint/config-conventional": "^20.5.0",
@@ -75,5 +76,8 @@
75
76
  },
76
77
  "engines": {
77
78
  "node": ">=24.10.0"
79
+ },
80
+ "dependencies": {
81
+ "@workos/oagen": "^0.5.0"
78
82
  }
79
83
  }
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * PHP SDK generation wrapper.
4
+ */
5
+ import { execSync } from 'node:child_process';
6
+
7
+ // Build oagen command with all passed arguments
8
+ const extraArgs = process.argv.slice(2).join(' ');
9
+ const baseCmd = 'oagen generate --lang php --output ./sdk-php --namespace WorkOS --api-surface ./sdk-php-surface.json';
10
+ const fullCmd = extraArgs ? `${baseCmd} ${extraArgs}` : baseCmd;
11
+
12
+ // Run oagen generate
13
+ execSync(fullCmd, { stdio: 'inherit' });
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env sh
2
+ set -eu
3
+
4
+ repo_root="$(git rev-parse --show-toplevel)"
5
+ cd "$repo_root"
6
+
7
+ restore_local() {
8
+ echo "push wrapper: restoring local ../oagen link"
9
+ npm run oagen:use:local
10
+ }
11
+
12
+ cleanup() {
13
+ restore_local
14
+ }
15
+
16
+ trap cleanup EXIT INT TERM HUP
17
+
18
+ echo "push wrapper: switching @workos/oagen to the published package"
19
+ npm run oagen:use:published
20
+
21
+ git push "$@"
@@ -115,7 +115,12 @@ function createProxyServer(apiKey: string, captures: ProxyCapture[]): Promise<{
115
115
  }
116
116
 
117
117
  captures.push({
118
- request: { method: req.method!, path: url.pathname, queryParams, body },
118
+ request: {
119
+ method: req.method!,
120
+ path: url.pathname,
121
+ queryParams,
122
+ body,
123
+ },
119
124
  response: { status: proxyRes.statusCode!, body: resBody },
120
125
  });
121
126
 
@@ -689,7 +694,11 @@ async function main(): Promise<void> {
689
694
 
690
695
  // Build planned calls for this wave, resolving methods
691
696
  const plannedCalls: PlannedCall[] = [];
692
- const waveSkipped: Array<{ op: Operation; irService: string; reason: string }> = [];
697
+ const waveSkipped: Array<{
698
+ op: Operation;
699
+ irService: string;
700
+ reason: string;
701
+ }> = [];
693
702
 
694
703
  for (const { op, irService, pathParams } of wave.calls) {
695
704
  const resolution = resolveMethod(op, irService, manifest);
@@ -858,7 +867,12 @@ function makeSkippedExchange(op: Operation, service: string, reason: string): Ca
858
867
  operationId: op.name,
859
868
  service,
860
869
  operationName: op.name,
861
- request: { method: op.httpMethod.toUpperCase(), path: op.path, queryParams: {}, body: null },
870
+ request: {
871
+ method: op.httpMethod.toUpperCase(),
872
+ path: op.path,
873
+ queryParams: {},
874
+ body: null,
875
+ },
862
876
  response: { status: 0, body: null },
863
877
  outcome: 'skipped',
864
878
  error: reason,
@@ -103,7 +103,12 @@ function startProxy(
103
103
  }
104
104
  }
105
105
 
106
- const capturedReq: CapturedRequest = { method, path, queryParams, body: reqBody };
106
+ const capturedReq: CapturedRequest = {
107
+ method,
108
+ path,
109
+ queryParams,
110
+ body: reqBody,
111
+ };
107
112
 
108
113
  // Forward to real API
109
114
  const forwardHeaders: Record<string, string> = {
@@ -467,7 +472,11 @@ async function main(): Promise<void> {
467
472
 
468
473
  // Build planned calls for this wave, resolving methods
469
474
  const plannedCalls: PlannedCall[] = [];
470
- const waveSkipped: Array<{ op: Operation; irService: string; reason: string }> = [];
475
+ const waveSkipped: Array<{
476
+ op: Operation;
477
+ irService: string;
478
+ reason: string;
479
+ }> = [];
471
480
 
472
481
  for (const { op, irService, pathParams } of wave.calls) {
473
482
  const resolution = resolveMethod(op, irService, manifest);
@@ -726,7 +735,12 @@ function makeSkippedExchange(op: Operation, service: string, reason: string): Ca
726
735
  operationId: op.name,
727
736
  service,
728
737
  operationName: op.name,
729
- request: { method: op.httpMethod.toUpperCase(), path: op.path, queryParams: {}, body: null },
738
+ request: {
739
+ method: op.httpMethod.toUpperCase(),
740
+ path: op.path,
741
+ queryParams: {},
742
+ body: null,
743
+ },
730
744
  response: { status: 0, body: null },
731
745
  outcome: 'skipped',
732
746
  error: reason,