@workos/oagen-emitters 0.2.1 → 0.4.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/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +15 -0
- package/README.md +129 -0
- package/dist/index.d.mts +13 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +14549 -3385
- package/dist/index.mjs.map +1 -1
- package/docs/sdk-architecture/dotnet.md +336 -0
- 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 +328 -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 +45 -12
- package/smoke/sdk-go.ts +116 -42
- package/smoke/sdk-php.ts +28 -26
- package/smoke/sdk-python.ts +5 -2
- package/src/dotnet/client.ts +89 -0
- package/src/dotnet/enums.ts +323 -0
- package/src/dotnet/fixtures.ts +236 -0
- package/src/dotnet/index.ts +246 -0
- package/src/dotnet/manifest.ts +36 -0
- package/src/dotnet/models.ts +344 -0
- package/src/dotnet/naming.ts +330 -0
- package/src/dotnet/resources.ts +622 -0
- package/src/dotnet/tests.ts +693 -0
- package/src/dotnet/type-map.ts +201 -0
- package/src/dotnet/wrappers.ts +186 -0
- 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 +84 -0
- package/src/go/manifest.ts +36 -0
- package/src/go/models.ts +254 -0
- package/src/go/naming.ts +179 -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 +4 -0
- package/src/kotlin/client.ts +53 -0
- package/src/kotlin/enums.ts +162 -0
- package/src/kotlin/index.ts +92 -0
- package/src/kotlin/manifest.ts +55 -0
- package/src/kotlin/models.ts +395 -0
- package/src/kotlin/naming.ts +223 -0
- package/src/kotlin/overrides.ts +25 -0
- package/src/kotlin/resources.ts +667 -0
- package/src/kotlin/tests.ts +1019 -0
- package/src/kotlin/type-map.ts +123 -0
- package/src/kotlin/wrappers.ts +168 -0
- package/src/node/client.ts +128 -115
- package/src/node/enums.ts +9 -0
- package/src/node/errors.ts +37 -232
- package/src/node/field-plan.ts +726 -0
- package/src/node/fixtures.ts +9 -1
- package/src/node/index.ts +3 -9
- package/src/node/models.ts +178 -21
- package/src/node/naming.ts +49 -111
- package/src/node/resources.ts +527 -397
- package/src/node/sdk-errors.ts +41 -0
- package/src/node/tests.ts +69 -19
- package/src/node/type-map.ts +4 -2
- package/src/node/utils.ts +13 -71
- package/src/node/wrappers.ts +151 -0
- package/src/php/client.ts +179 -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 +279 -0
- package/src/php/resources.ts +636 -0
- package/src/php/tests.ts +609 -0
- package/src/php/type-map.ts +90 -0
- package/src/php/utils.ts +18 -0
- package/src/php/wrappers.ts +152 -0
- package/src/python/client.ts +345 -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 +189 -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 +472 -0
- package/src/shared/naming-utils.ts +154 -0
- package/src/shared/non-spec-services.ts +54 -0
- package/src/shared/resolved-ops.ts +109 -0
- package/src/shared/wrapper-utils.ts +70 -0
- package/test/dotnet/client.test.ts +121 -0
- package/test/dotnet/enums.test.ts +193 -0
- package/test/dotnet/errors.test.ts +9 -0
- package/test/dotnet/manifest.test.ts +82 -0
- package/test/dotnet/models.test.ts +260 -0
- package/test/dotnet/resources.test.ts +255 -0
- package/test/dotnet/tests.test.ts +202 -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/kotlin/models.test.ts +135 -0
- package/test/kotlin/tests.test.ts +176 -0
- package/test/node/client.test.ts +92 -12
- package/test/node/enums.test.ts +2 -0
- package/test/node/errors.test.ts +2 -41
- package/test/node/models.test.ts +2 -0
- package/test/node/naming.test.ts +23 -0
- package/test/node/resources.test.ts +315 -84
- package/test/node/serializers.test.ts +3 -1
- package/test/node/type-map.test.ts +11 -0
- package/test/php/client.test.ts +95 -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 +682 -0
- package/test/php/tests.test.ts +185 -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 -746
package/oagen.config.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
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';
|
|
7
|
+
import { dotnetEmitter } from './src/dotnet/index.js';
|
|
8
|
+
import { kotlinEmitter } from './src/kotlin/index.js';
|
|
4
9
|
import { nodeExtractor } from './src/compat/extractors/node.js';
|
|
5
10
|
import { rubyExtractor } from './src/compat/extractors/ruby.js';
|
|
6
11
|
import { pythonExtractor } from './src/compat/extractors/python.js';
|
|
@@ -21,8 +26,310 @@ function nestjsOperationIdTransform(id: string): string {
|
|
|
21
26
|
return idx !== -1 ? toCamelCase(stripped.slice(idx + 1)) : toCamelCase(stripped);
|
|
22
27
|
}
|
|
23
28
|
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Operation hints — per-operation overrides for the operation resolver.
|
|
31
|
+
// Keyed by "METHOD /path". Only operations that need overrides are listed;
|
|
32
|
+
// the algorithm handles the rest.
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
const operationHints: Record<string, OperationHint> = {
|
|
35
|
+
// ── Radar ────────────────────────────────────────────────────────────────
|
|
36
|
+
'POST /radar/lists/{type}/{action}': { name: 'add_list_entry' },
|
|
37
|
+
'DELETE /radar/lists/{type}/{action}': { name: 'remove_list_entry' },
|
|
38
|
+
|
|
39
|
+
// ── SSO ──────────────────────────────────────────────────────────────────
|
|
40
|
+
'GET /sso/authorize': {
|
|
41
|
+
name: 'get_authorization_url',
|
|
42
|
+
defaults: { response_type: 'code' },
|
|
43
|
+
inferFromClient: ['client_id'],
|
|
44
|
+
urlBuilder: true,
|
|
45
|
+
},
|
|
46
|
+
'GET /sso/logout': { name: 'get_logout_url', urlBuilder: true },
|
|
47
|
+
'GET /sso/profile': { name: 'get_profile' },
|
|
48
|
+
'POST /sso/token': {
|
|
49
|
+
name: 'get_profile_and_token',
|
|
50
|
+
defaults: { grant_type: 'authorization_code' },
|
|
51
|
+
inferFromClient: ['client_id', 'client_secret'],
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
// ── SSO / JWKS (mounted on UserManagement via mountRules) ────────────────
|
|
55
|
+
'GET /sso/jwks/{clientId}': { name: 'get_jwks' },
|
|
56
|
+
|
|
57
|
+
// ── User Management — auth ──────────────────────────────────────────────
|
|
58
|
+
'GET /user_management/authorize': {
|
|
59
|
+
name: 'get_authorization_url',
|
|
60
|
+
defaults: { response_type: 'code' },
|
|
61
|
+
inferFromClient: ['client_id'],
|
|
62
|
+
urlBuilder: true,
|
|
63
|
+
},
|
|
64
|
+
'GET /user_management/sessions/logout': { name: 'get_logout_url', urlBuilder: true },
|
|
65
|
+
|
|
66
|
+
// ── User Management — org membership actions ────────────────────────────
|
|
67
|
+
'PUT /user_management/organization_memberships/{id}/deactivate': {
|
|
68
|
+
name: 'deactivate_organization_membership',
|
|
69
|
+
},
|
|
70
|
+
'PUT /user_management/organization_memberships/{id}/reactivate': {
|
|
71
|
+
name: 'reactivate_organization_membership',
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
// ── Admin Portal ────────────────────────────────────────────────────────
|
|
75
|
+
'POST /portal/generate_link': { name: 'generate_link' },
|
|
76
|
+
|
|
77
|
+
// ── Feature Flags — disambiguate co-mounted list operations ─────────────
|
|
78
|
+
'GET /organizations/{organizationId}/feature-flags': { name: 'list_organization_feature_flags' },
|
|
79
|
+
'GET /user_management/users/{userId}/feature-flags': { name: 'list_user_feature_flags' },
|
|
80
|
+
|
|
81
|
+
// ── External ID lookups (not derivable from path) ──────────────────────
|
|
82
|
+
'GET /organizations/external_id/{external_id}': { name: 'get_organization_by_external_id' },
|
|
83
|
+
'GET /user_management/users/external_id/{external_id}': { name: 'get_user_by_external_id' },
|
|
84
|
+
|
|
85
|
+
// ── Authorization — environment-scoped roles ─────────────────────────────
|
|
86
|
+
'GET /authorization/roles': { name: 'list_environment_roles' },
|
|
87
|
+
'POST /authorization/roles': { name: 'create_environment_role' },
|
|
88
|
+
'GET /authorization/roles/{slug}': { name: 'get_environment_role' },
|
|
89
|
+
'PATCH /authorization/roles/{slug}': { name: 'update_environment_role' },
|
|
90
|
+
'PUT /authorization/roles/{slug}/permissions': {
|
|
91
|
+
name: 'set_environment_role_permissions',
|
|
92
|
+
},
|
|
93
|
+
'POST /authorization/roles/{slug}/permissions': {
|
|
94
|
+
name: 'add_environment_role_permission',
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
// ── Authorization — singularized/shortened names ────────────────────────
|
|
98
|
+
'POST /authorization/permissions': { name: 'create_permission' },
|
|
99
|
+
'POST /authorization/resources': { name: 'create_resource' },
|
|
100
|
+
'POST /authorization/organization_memberships/{organization_membership_id}/check': {
|
|
101
|
+
name: 'check',
|
|
102
|
+
},
|
|
103
|
+
'POST /authorization/organization_memberships/{organization_membership_id}/role_assignments': {
|
|
104
|
+
name: 'assign_role',
|
|
105
|
+
},
|
|
106
|
+
'DELETE /authorization/organization_memberships/{organization_membership_id}/role_assignments': {
|
|
107
|
+
name: 'remove_role',
|
|
108
|
+
},
|
|
109
|
+
'POST /authorization/organizations/{organizationId}/roles': {
|
|
110
|
+
name: 'create_organization_role',
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
// ── Authorization — env-scoped resource memberships ────────────────────
|
|
114
|
+
'GET /authorization/resources/{resource_id}/organization_memberships': { name: 'list_memberships_for_resource' },
|
|
115
|
+
|
|
116
|
+
// ── User Management — singularized/shortened names ─────────────────────
|
|
117
|
+
'POST /user_management/users': { name: 'create_user' },
|
|
118
|
+
'POST /user_management/organization_memberships': {
|
|
119
|
+
name: 'create_organization_membership',
|
|
120
|
+
},
|
|
121
|
+
'POST /user_management/invitations': { name: 'send_invitation' },
|
|
122
|
+
'GET /user_management/invitations/by_token/{token}': {
|
|
123
|
+
name: 'find_invitation_by_token',
|
|
124
|
+
},
|
|
125
|
+
'POST /user_management/users/{id}/email_verification/send': {
|
|
126
|
+
name: 'send_verification_email',
|
|
127
|
+
},
|
|
128
|
+
'POST /user_management/users/{id}/email_verification/confirm': {
|
|
129
|
+
name: 'verify_email',
|
|
130
|
+
},
|
|
131
|
+
'POST /user_management/password_reset': { name: 'reset_password' },
|
|
132
|
+
'POST /user_management/password_reset/confirm': {
|
|
133
|
+
name: 'confirm_password_reset',
|
|
134
|
+
},
|
|
135
|
+
'GET /user_management/users/{id}/sessions': { name: 'list_sessions' },
|
|
136
|
+
'GET /user_management/users/{id}/identities': { name: 'get_user_identities' },
|
|
137
|
+
'POST /user_management/cors_origins': { name: 'create_cors_origin' },
|
|
138
|
+
'POST /user_management/redirect_uris': { name: 'create_redirect_uri' },
|
|
139
|
+
|
|
140
|
+
// ── Organizations — singularized names ─────────────────────────────────
|
|
141
|
+
'POST /organizations': { name: 'create_organization' },
|
|
142
|
+
|
|
143
|
+
// ── Directory Sync — shortened names ───────────────────────────────────
|
|
144
|
+
'GET /directory_groups': { name: 'list_groups' },
|
|
145
|
+
'GET /directory_groups/{id}': { name: 'get_group' },
|
|
146
|
+
'GET /directory_users': { name: 'list_users' },
|
|
147
|
+
'GET /directory_users/{id}': { name: 'get_user' },
|
|
148
|
+
|
|
149
|
+
// ── Audit Logs — singularized names ────────────────────────────────────
|
|
150
|
+
'POST /audit_logs/events': { name: 'create_event' },
|
|
151
|
+
'POST /audit_logs/exports': { name: 'create_export' },
|
|
152
|
+
'POST /audit_logs/actions/{actionName}/schemas': { name: 'create_schema' },
|
|
153
|
+
|
|
154
|
+
// ── Feature Flags — match SDK conventions ──────────────────────────────
|
|
155
|
+
'POST /feature-flags/{slug}/targets/{resourceId}': { name: 'add_flag_target' },
|
|
156
|
+
'DELETE /feature-flags/{slug}/targets/{resourceId}': {
|
|
157
|
+
name: 'remove_flag_target',
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
// ── Organizations — audit log config (singular fetch, not a list) ───────
|
|
161
|
+
'GET /organizations/{id}/audit_log_configuration': {
|
|
162
|
+
name: 'get_audit_log_configuration',
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
// ── Organizations — audit logs retention (mounted on AuditLogs) ─────────
|
|
166
|
+
'GET /organizations/{id}/audit_logs_retention': {
|
|
167
|
+
name: 'get_organization_audit_logs_retention',
|
|
168
|
+
mountOn: 'AuditLogs',
|
|
169
|
+
},
|
|
170
|
+
'PUT /organizations/{id}/audit_logs_retention': { mountOn: 'AuditLogs' },
|
|
171
|
+
|
|
172
|
+
// ── Union split: POST /user_management/authenticate (8 variants) ────────
|
|
173
|
+
// Common optional fields appended to every variant's exposedParams so the
|
|
174
|
+
// generated wrappers cover the full spec body shape (fraud/audit context the
|
|
175
|
+
// server consumes when present).
|
|
176
|
+
'POST /user_management/authenticate': {
|
|
177
|
+
split: [
|
|
178
|
+
{
|
|
179
|
+
name: 'authenticate_with_password',
|
|
180
|
+
targetVariant: 'PasswordSessionAuthenticateRequest',
|
|
181
|
+
defaults: { grant_type: 'password' },
|
|
182
|
+
inferFromClient: ['client_id', 'client_secret'],
|
|
183
|
+
exposedParams: ['email', 'password', 'invitation_token', 'ip_address', 'device_id', 'user_agent'],
|
|
184
|
+
optionalParams: ['invitation_token', 'ip_address', 'device_id', 'user_agent'],
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
name: 'authenticate_with_code',
|
|
188
|
+
targetVariant: 'CodeSessionAuthenticateRequest',
|
|
189
|
+
defaults: { grant_type: 'authorization_code' },
|
|
190
|
+
inferFromClient: ['client_id', 'client_secret'],
|
|
191
|
+
exposedParams: ['code', 'ip_address', 'device_id', 'user_agent'],
|
|
192
|
+
optionalParams: ['ip_address', 'device_id', 'user_agent'],
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
name: 'authenticate_with_refresh_token',
|
|
196
|
+
targetVariant: 'RefreshTokenSessionAuthenticateRequest',
|
|
197
|
+
defaults: { grant_type: 'refresh_token' },
|
|
198
|
+
inferFromClient: ['client_id', 'client_secret'],
|
|
199
|
+
exposedParams: ['refresh_token', 'organization_id', 'ip_address', 'device_id', 'user_agent'],
|
|
200
|
+
optionalParams: ['organization_id', 'ip_address', 'device_id', 'user_agent'],
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
name: 'authenticate_with_magic_auth',
|
|
204
|
+
targetVariant: 'MagicAuthSessionAuthenticateRequest',
|
|
205
|
+
defaults: { grant_type: 'urn:workos:oauth:grant-type:magic-auth:code' },
|
|
206
|
+
inferFromClient: ['client_id', 'client_secret'],
|
|
207
|
+
exposedParams: ['code', 'email', 'invitation_token', 'ip_address', 'device_id', 'user_agent'],
|
|
208
|
+
optionalParams: ['invitation_token', 'ip_address', 'device_id', 'user_agent'],
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
name: 'authenticate_with_email_verification',
|
|
212
|
+
targetVariant: 'EmailVerificationSessionAuthenticateRequest',
|
|
213
|
+
defaults: { grant_type: 'urn:workos:oauth:grant-type:email-verification:code' },
|
|
214
|
+
inferFromClient: ['client_id', 'client_secret'],
|
|
215
|
+
exposedParams: ['code', 'pending_authentication_token', 'ip_address', 'device_id', 'user_agent'],
|
|
216
|
+
optionalParams: ['pending_authentication_token', 'ip_address', 'device_id', 'user_agent'],
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
name: 'authenticate_with_totp',
|
|
220
|
+
targetVariant: 'TotpSessionAuthenticateRequest',
|
|
221
|
+
defaults: { grant_type: 'urn:workos:oauth:grant-type:mfa-totp' },
|
|
222
|
+
inferFromClient: ['client_id', 'client_secret'],
|
|
223
|
+
exposedParams: [
|
|
224
|
+
'code',
|
|
225
|
+
'pending_authentication_token',
|
|
226
|
+
'authentication_challenge_id',
|
|
227
|
+
'ip_address',
|
|
228
|
+
'device_id',
|
|
229
|
+
'user_agent',
|
|
230
|
+
],
|
|
231
|
+
optionalParams: ['ip_address', 'device_id', 'user_agent'],
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
name: 'authenticate_with_organization_selection',
|
|
235
|
+
targetVariant: 'OrganizationSelectionSessionAuthenticateRequest',
|
|
236
|
+
defaults: { grant_type: 'urn:workos:oauth:grant-type:organization-selection' },
|
|
237
|
+
inferFromClient: ['client_id', 'client_secret'],
|
|
238
|
+
exposedParams: ['pending_authentication_token', 'organization_id', 'ip_address', 'device_id', 'user_agent'],
|
|
239
|
+
optionalParams: ['ip_address', 'device_id', 'user_agent'],
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
name: 'authenticate_with_device_code',
|
|
243
|
+
targetVariant: 'DeviceCodeSessionAuthenticateRequest',
|
|
244
|
+
defaults: { grant_type: 'urn:ietf:params:oauth:grant-type:device_code' },
|
|
245
|
+
inferFromClient: ['client_id'],
|
|
246
|
+
exposedParams: ['device_code', 'ip_address', 'device_id', 'user_agent'],
|
|
247
|
+
optionalParams: ['ip_address', 'device_id', 'user_agent'],
|
|
248
|
+
},
|
|
249
|
+
],
|
|
250
|
+
},
|
|
251
|
+
|
|
252
|
+
// ── Union split: POST /connect/applications (2 variants) ────────────────
|
|
253
|
+
'POST /connect/applications': {
|
|
254
|
+
split: [
|
|
255
|
+
{
|
|
256
|
+
name: 'create_oauth_application',
|
|
257
|
+
targetVariant: 'CreateOAuthApplication',
|
|
258
|
+
defaults: { application_type: 'oauth' },
|
|
259
|
+
exposedParams: [
|
|
260
|
+
'name',
|
|
261
|
+
'is_first_party',
|
|
262
|
+
'description',
|
|
263
|
+
'scopes',
|
|
264
|
+
'redirect_uris',
|
|
265
|
+
'uses_pkce',
|
|
266
|
+
'organization_id',
|
|
267
|
+
],
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
name: 'create_m2m_application',
|
|
271
|
+
targetVariant: 'CreateM2MApplication',
|
|
272
|
+
defaults: { application_type: 'm2m' },
|
|
273
|
+
exposedParams: ['name', 'organization_id', 'description', 'scopes'],
|
|
274
|
+
},
|
|
275
|
+
],
|
|
276
|
+
},
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
// ---------------------------------------------------------------------------
|
|
280
|
+
// Mount rules — service-level remounting. Maps IR service name → target
|
|
281
|
+
// service/namespace (PascalCase). All operations in the source service are
|
|
282
|
+
// mounted on the target unless overridden per-operation in operationHints.
|
|
283
|
+
// ---------------------------------------------------------------------------
|
|
284
|
+
const mountRules: Record<string, string> = {
|
|
285
|
+
// MFA sub-services → MultiFactorAuth
|
|
286
|
+
MultiFactorAuthChallenges: 'MultiFactorAuth',
|
|
287
|
+
|
|
288
|
+
// RBAC permissions → Authorization
|
|
289
|
+
Permissions: 'Authorization',
|
|
290
|
+
|
|
291
|
+
// Connect sub-services → Connect
|
|
292
|
+
WorkosConnect: 'Connect',
|
|
293
|
+
Applications: 'Connect',
|
|
294
|
+
ApplicationClientSecrets: 'Connect',
|
|
295
|
+
|
|
296
|
+
// SSO connections → SSO
|
|
297
|
+
Connections: 'SSO',
|
|
298
|
+
|
|
299
|
+
// Directory Sync sub-services → DirectorySync
|
|
300
|
+
Directories: 'DirectorySync',
|
|
301
|
+
DirectoryGroups: 'DirectorySync',
|
|
302
|
+
DirectoryUsers: 'DirectorySync',
|
|
303
|
+
|
|
304
|
+
// Feature flag sub-services → FeatureFlags
|
|
305
|
+
FeatureFlagsTargets: 'FeatureFlags',
|
|
306
|
+
OrganizationsFeatureFlags: 'FeatureFlags',
|
|
307
|
+
UserManagementUsersFeatureFlags: 'FeatureFlags',
|
|
308
|
+
|
|
309
|
+
// Org API keys → ApiKeys
|
|
310
|
+
OrganizationsApiKeys: 'ApiKeys',
|
|
311
|
+
|
|
312
|
+
// User Management sub-services → UserManagement
|
|
313
|
+
UserManagementSessionTokens: 'UserManagement',
|
|
314
|
+
UserManagementAuthentication: 'UserManagement',
|
|
315
|
+
UserManagementCorsOrigins: 'UserManagement',
|
|
316
|
+
UserManagementUsers: 'UserManagement',
|
|
317
|
+
UserManagementInvitations: 'UserManagement',
|
|
318
|
+
UserManagementJWTTemplate: 'UserManagement',
|
|
319
|
+
UserManagementMagicAuth: 'UserManagement',
|
|
320
|
+
UserManagementOrganizationMembership: 'UserManagement',
|
|
321
|
+
UserManagementRedirectUris: 'UserManagement',
|
|
322
|
+
UserManagementUsersAuthorizedApplications: 'UserManagement',
|
|
323
|
+
|
|
324
|
+
// Pipes / Data Providers → Pipes
|
|
325
|
+
UserManagementDataProviders: 'Pipes',
|
|
326
|
+
|
|
327
|
+
// User Management MFA → MultiFactorAuth
|
|
328
|
+
UserManagementMultiFactorAuthentication: 'MultiFactorAuth',
|
|
329
|
+
};
|
|
330
|
+
|
|
24
331
|
const config: OagenConfig = {
|
|
25
|
-
emitters: [nodeEmitter],
|
|
332
|
+
emitters: [nodeEmitter, pythonEmitter, phpEmitter, goEmitter, dotnetEmitter, kotlinEmitter],
|
|
26
333
|
extractors: [
|
|
27
334
|
nodeExtractor,
|
|
28
335
|
rubyExtractor,
|
|
@@ -47,5 +354,24 @@ const config: OagenConfig = {
|
|
|
47
354
|
},
|
|
48
355
|
docUrl: 'https://workos.com/docs',
|
|
49
356
|
operationIdTransform: nestjsOperationIdTransform,
|
|
357
|
+
schemaNameTransform: (name: string) => {
|
|
358
|
+
// Explicit renames for Dto models that collide with response models
|
|
359
|
+
const COLLISION_RENAMES: Record<string, string> = {
|
|
360
|
+
OrganizationDto: 'OrganizationInput',
|
|
361
|
+
RedirectUriDto: 'RedirectUriInput',
|
|
362
|
+
// Generic list-derived names that need domain-specific identifiers
|
|
363
|
+
ListData: 'Role',
|
|
364
|
+
ListModel: 'RoleList',
|
|
365
|
+
// Double-List naming artifact
|
|
366
|
+
EventListListMetadata: 'EventListMetadata',
|
|
367
|
+
};
|
|
368
|
+
if (COLLISION_RENAMES[name]) return COLLISION_RENAMES[name];
|
|
369
|
+
return name
|
|
370
|
+
.replace(/Dto/g, '')
|
|
371
|
+
.replace(/DTO/g, '')
|
|
372
|
+
.replace(/^Urn(?:IetfParams|Workos)O[Aa]uthGrantType/, '');
|
|
373
|
+
},
|
|
374
|
+
operationHints,
|
|
375
|
+
mountRules,
|
|
50
376
|
};
|
|
51
377
|
export default config;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workos/oagen-emitters",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.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": "
|
|
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.3.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.6.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 "$@"
|
package/smoke/sdk-dotnet.ts
CHANGED
|
@@ -405,14 +405,33 @@ function buildBatchedCSharpScript(port: number, ns: string, calls: PlannedCall[]
|
|
|
405
405
|
// ---------------------------------------------------------------------------
|
|
406
406
|
|
|
407
407
|
/**
|
|
408
|
-
* Find the .csproj file in the SDK directory.
|
|
408
|
+
* Find the .csproj file in the SDK directory. Searches the root first, then
|
|
409
|
+
* common subdirectory patterns (src/{Name}/) used by the generated SDK layout.
|
|
409
410
|
*/
|
|
410
411
|
function findCsproj(sdkPath: string): string {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
412
|
+
// Check root directory first
|
|
413
|
+
const rootFiles = readdirSync(sdkPath).filter((f) => f.endsWith('.csproj'));
|
|
414
|
+
if (rootFiles.length > 0) {
|
|
415
|
+
return resolve(sdkPath, rootFiles[0]);
|
|
414
416
|
}
|
|
415
|
-
|
|
417
|
+
|
|
418
|
+
// Check src/ subdirectories (generated SDK layout: src/WorkOS.net/WorkOS.net.csproj)
|
|
419
|
+
const srcDir = resolve(sdkPath, 'src');
|
|
420
|
+
if (existsSync(srcDir)) {
|
|
421
|
+
for (const subdir of readdirSync(srcDir)) {
|
|
422
|
+
const subdirPath = resolve(srcDir, subdir);
|
|
423
|
+
try {
|
|
424
|
+
const subFiles = readdirSync(subdirPath).filter((f) => f.endsWith('.csproj'));
|
|
425
|
+
if (subFiles.length > 0) {
|
|
426
|
+
return resolve(subdirPath, subFiles[0]);
|
|
427
|
+
}
|
|
428
|
+
} catch {
|
|
429
|
+
// Not a directory, skip
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
throw new Error(`No .csproj file found in ${sdkPath} or ${sdkPath}/src/*/`);
|
|
416
435
|
}
|
|
417
436
|
|
|
418
437
|
/**
|
|
@@ -429,6 +448,18 @@ function detectNamespace(sdkPath: string): string {
|
|
|
429
448
|
return base.replace('.csproj', '');
|
|
430
449
|
}
|
|
431
450
|
|
|
451
|
+
/**
|
|
452
|
+
* Detect the assembly name from the .csproj file's AssemblyName property.
|
|
453
|
+
* Falls back to namespace if not found.
|
|
454
|
+
*/
|
|
455
|
+
function detectAssemblyName(sdkPath: string): string {
|
|
456
|
+
const csprojPath = findCsproj(sdkPath);
|
|
457
|
+
const content = readFileSync(csprojPath, 'utf-8');
|
|
458
|
+
const match = content.match(/<AssemblyName>([^<]+)<\/AssemblyName>/);
|
|
459
|
+
if (match) return match[1];
|
|
460
|
+
return detectNamespace(sdkPath);
|
|
461
|
+
}
|
|
462
|
+
|
|
432
463
|
// ---------------------------------------------------------------------------
|
|
433
464
|
// .NET project generation
|
|
434
465
|
// ---------------------------------------------------------------------------
|
|
@@ -590,9 +621,10 @@ async function main(): Promise<void> {
|
|
|
590
621
|
const spec = await parseSpec(specPath);
|
|
591
622
|
console.log(`Spec: ${spec.name} v${spec.version}`);
|
|
592
623
|
|
|
593
|
-
// Detect SDK namespace
|
|
624
|
+
// Detect SDK namespace and assembly name
|
|
594
625
|
const ns = detectNamespace(sdkPath);
|
|
595
|
-
|
|
626
|
+
const assemblyName = detectAssemblyName(sdkPath);
|
|
627
|
+
console.log(`SDK namespace: ${ns}, assembly: ${assemblyName}`);
|
|
596
628
|
|
|
597
629
|
// Load manifest
|
|
598
630
|
const manifest = loadManifest(sdkPath);
|
|
@@ -620,10 +652,12 @@ async function main(): Promise<void> {
|
|
|
620
652
|
|
|
621
653
|
// Step 1: Build the SDK project to a DLL
|
|
622
654
|
const sdkCsprojPath = findCsproj(sdkPath);
|
|
655
|
+
const sdkCsprojDir = sdkCsprojPath.substring(0, sdkCsprojPath.lastIndexOf('/'));
|
|
656
|
+
const sdkDllDir = resolve(sdkPath, 'bin/Release');
|
|
623
657
|
console.log('Building SDK...');
|
|
624
658
|
try {
|
|
625
|
-
execSync(`dotnet build "${sdkCsprojPath}" -c Release -o "${
|
|
626
|
-
cwd:
|
|
659
|
+
execSync(`dotnet build "${sdkCsprojPath}" -c Release -o "${sdkDllDir}"`, {
|
|
660
|
+
cwd: sdkCsprojDir,
|
|
627
661
|
timeout: 120000,
|
|
628
662
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
629
663
|
env: { ...process.env, DOTNET_NOLOGO: '1' },
|
|
@@ -635,9 +669,8 @@ async function main(): Promise<void> {
|
|
|
635
669
|
process.exit(1);
|
|
636
670
|
}
|
|
637
671
|
|
|
638
|
-
// Find the SDK DLL
|
|
639
|
-
const
|
|
640
|
-
const sdkDll = resolve(sdkDllDir, `${ns}.dll`);
|
|
672
|
+
// Find the SDK DLL (use AssemblyName, not namespace)
|
|
673
|
+
const sdkDll = resolve(sdkDllDir, `${assemblyName}.dll`);
|
|
641
674
|
|
|
642
675
|
// Step 2: Bootstrap the driver project referencing the built DLL
|
|
643
676
|
mkdirSync(tmpDir, { recursive: true });
|