@workos/oagen-emitters 0.3.0 → 0.5.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/.github/workflows/ci.yml +1 -1
- package/.github/workflows/lint.yml +1 -1
- package/.github/workflows/release-please.yml +2 -2
- package/.github/workflows/release.yml +1 -1
- package/.husky/pre-push +11 -0
- package/.node-version +1 -1
- package/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +15 -0
- package/README.md +35 -224
- package/dist/index.d.mts +12 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -12737
- package/dist/plugin-BSop9f9z.mjs +21471 -0
- package/dist/plugin-BSop9f9z.mjs.map +1 -0
- package/dist/plugin.d.mts +7 -0
- package/dist/plugin.d.mts.map +1 -0
- package/dist/plugin.mjs +2 -0
- package/docs/sdk-architecture/dotnet.md +336 -0
- package/oagen.config.ts +5 -343
- package/package.json +10 -34
- package/smoke/sdk-dotnet.ts +45 -12
- 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 +248 -0
- package/src/dotnet/manifest.ts +36 -0
- package/src/dotnet/models.ts +320 -0
- package/src/dotnet/naming.ts +368 -0
- package/src/dotnet/resources.ts +943 -0
- package/src/dotnet/tests.ts +713 -0
- package/src/dotnet/type-map.ts +228 -0
- package/src/dotnet/wrappers.ts +197 -0
- package/src/go/client.ts +35 -3
- package/src/go/enums.ts +4 -0
- package/src/go/index.ts +15 -7
- package/src/go/models.ts +6 -1
- package/src/go/naming.ts +5 -17
- package/src/go/resources.ts +534 -73
- package/src/go/tests.ts +39 -3
- package/src/go/type-map.ts +8 -3
- package/src/go/wrappers.ts +79 -21
- package/src/index.ts +15 -0
- package/src/kotlin/client.ts +58 -0
- package/src/kotlin/enums.ts +189 -0
- package/src/kotlin/index.ts +92 -0
- package/src/kotlin/manifest.ts +55 -0
- package/src/kotlin/models.ts +486 -0
- package/src/kotlin/naming.ts +229 -0
- package/src/kotlin/overrides.ts +25 -0
- package/src/kotlin/resources.ts +998 -0
- package/src/kotlin/tests.ts +1133 -0
- package/src/kotlin/type-map.ts +123 -0
- package/src/kotlin/wrappers.ts +168 -0
- package/src/node/client.ts +84 -7
- package/src/node/field-plan.ts +12 -14
- package/src/node/fixtures.ts +39 -3
- package/src/node/index.ts +1 -0
- package/src/node/models.ts +281 -37
- package/src/node/resources.ts +319 -95
- package/src/node/tests.ts +108 -29
- package/src/node/type-map.ts +1 -31
- package/src/node/utils.ts +96 -6
- package/src/node/wrappers.ts +31 -1
- package/src/php/client.ts +11 -3
- package/src/php/models.ts +0 -33
- package/src/php/naming.ts +2 -21
- package/src/php/resources.ts +275 -19
- package/src/php/tests.ts +118 -18
- package/src/php/type-map.ts +16 -2
- package/src/php/wrappers.ts +7 -2
- package/src/plugin.ts +50 -0
- package/src/python/client.ts +50 -32
- package/src/python/enums.ts +35 -10
- package/src/python/index.ts +35 -27
- package/src/python/models.ts +139 -2
- package/src/python/naming.ts +2 -22
- package/src/python/resources.ts +234 -17
- package/src/python/tests.ts +260 -16
- package/src/python/type-map.ts +16 -2
- package/src/ruby/client.ts +238 -0
- package/src/ruby/enums.ts +149 -0
- package/src/ruby/index.ts +93 -0
- package/src/ruby/manifest.ts +35 -0
- package/src/ruby/models.ts +360 -0
- package/src/ruby/naming.ts +187 -0
- package/src/ruby/rbi.ts +313 -0
- package/src/ruby/resources.ts +799 -0
- package/src/ruby/tests.ts +459 -0
- package/src/ruby/type-map.ts +97 -0
- package/src/ruby/wrappers.ts +161 -0
- package/src/shared/model-utils.ts +357 -16
- package/src/shared/naming-utils.ts +83 -0
- package/src/shared/non-spec-services.ts +13 -0
- package/src/shared/resolved-ops.ts +75 -1
- package/src/shared/wrapper-utils.ts +12 -1
- 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 +258 -0
- package/test/dotnet/resources.test.ts +387 -0
- package/test/dotnet/tests.test.ts +202 -0
- package/test/entrypoint.test.ts +89 -0
- package/test/go/client.test.ts +6 -6
- package/test/go/resources.test.ts +156 -7
- package/test/kotlin/models.test.ts +135 -0
- package/test/kotlin/resources.test.ts +210 -0
- package/test/kotlin/tests.test.ts +176 -0
- package/test/node/client.test.ts +74 -0
- package/test/node/models.test.ts +134 -1
- package/test/node/resources.test.ts +343 -34
- package/test/node/utils.test.ts +140 -0
- package/test/php/client.test.ts +2 -1
- package/test/php/models.test.ts +5 -4
- package/test/php/resources.test.ts +103 -0
- package/test/php/tests.test.ts +67 -0
- package/test/plugin.test.ts +50 -0
- package/test/python/client.test.ts +56 -0
- package/test/python/models.test.ts +99 -0
- package/test/python/resources.test.ts +294 -0
- package/test/python/tests.test.ts +91 -0
- package/test/ruby/client.test.ts +81 -0
- package/test/ruby/resources.test.ts +386 -0
- package/test/shared/resolved-ops.test.ts +122 -0
- package/tsdown.config.ts +1 -1
- package/dist/index.mjs.map +0 -1
- package/scripts/generate-php.js +0 -13
- package/scripts/git-push-with-published-oagen.sh +0 -21
package/oagen.config.ts
CHANGED
|
@@ -1,347 +1,9 @@
|
|
|
1
|
-
import type { OagenConfig
|
|
2
|
-
import {
|
|
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 { nodeExtractor } from './src/compat/extractors/node.js';
|
|
8
|
-
import { rubyExtractor } from './src/compat/extractors/ruby.js';
|
|
9
|
-
import { pythonExtractor } from './src/compat/extractors/python.js';
|
|
10
|
-
import { phpExtractor } from './src/compat/extractors/php.js';
|
|
11
|
-
import { goExtractor } from './src/compat/extractors/go.js';
|
|
12
|
-
import { rustExtractor } from './src/compat/extractors/rust.js';
|
|
13
|
-
import { kotlinExtractor } from './src/compat/extractors/kotlin.js';
|
|
14
|
-
import { dotnetExtractor } from './src/compat/extractors/dotnet.js';
|
|
15
|
-
import { elixirExtractor } from './src/compat/extractors/elixir.js';
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* NestJS-style operationId transform. Strips "Controller" and extracts the
|
|
19
|
-
* action after the first underscore: `FooController_bar` → `bar`.
|
|
20
|
-
*/
|
|
21
|
-
function nestjsOperationIdTransform(id: string): string {
|
|
22
|
-
const stripped = id.replace(/Controller/g, '');
|
|
23
|
-
const idx = stripped.indexOf('_');
|
|
24
|
-
return idx !== -1 ? toCamelCase(stripped.slice(idx + 1)) : toCamelCase(stripped);
|
|
25
|
-
}
|
|
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
|
-
};
|
|
1
|
+
import type { OagenConfig } from '@workos/oagen';
|
|
2
|
+
import { workosEmittersPlugin } from './src/plugin.js';
|
|
300
3
|
|
|
4
|
+
// Minimal config for local emitter development.
|
|
5
|
+
// The canonical consumer config lives in openapi-spec/oagen.config.ts.
|
|
301
6
|
const config: OagenConfig = {
|
|
302
|
-
|
|
303
|
-
extractors: [
|
|
304
|
-
nodeExtractor,
|
|
305
|
-
rubyExtractor,
|
|
306
|
-
pythonExtractor,
|
|
307
|
-
phpExtractor,
|
|
308
|
-
goExtractor,
|
|
309
|
-
rustExtractor,
|
|
310
|
-
kotlinExtractor,
|
|
311
|
-
dotnetExtractor,
|
|
312
|
-
elixirExtractor,
|
|
313
|
-
],
|
|
314
|
-
smokeRunners: {
|
|
315
|
-
node: './smoke/sdk-node.ts',
|
|
316
|
-
ruby: './smoke/sdk-ruby.ts',
|
|
317
|
-
python: './smoke/sdk-python.ts',
|
|
318
|
-
php: './smoke/sdk-php.ts',
|
|
319
|
-
go: './smoke/sdk-go.ts',
|
|
320
|
-
rust: './smoke/sdk-rust.ts',
|
|
321
|
-
elixir: './smoke/sdk-elixir.ts',
|
|
322
|
-
kotlin: './smoke/sdk-kotlin.ts',
|
|
323
|
-
dotnet: './smoke/sdk-dotnet.ts',
|
|
324
|
-
},
|
|
325
|
-
docUrl: 'https://workos.com/docs',
|
|
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,
|
|
7
|
+
...workosEmittersPlugin,
|
|
346
8
|
};
|
|
347
9
|
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.5.0",
|
|
4
4
|
"description": "WorkOS' oagen emitters",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "WorkOS",
|
|
@@ -15,6 +15,10 @@
|
|
|
15
15
|
".": {
|
|
16
16
|
"types": "./dist/index.d.mts",
|
|
17
17
|
"import": "./dist/index.mjs"
|
|
18
|
+
},
|
|
19
|
+
"./plugin": {
|
|
20
|
+
"types": "./dist/plugin.d.mts",
|
|
21
|
+
"import": "./dist/plugin.mjs"
|
|
18
22
|
}
|
|
19
23
|
},
|
|
20
24
|
"scripts": {
|
|
@@ -28,45 +32,17 @@
|
|
|
28
32
|
"test": "vitest run",
|
|
29
33
|
"test:watch": "vitest",
|
|
30
34
|
"typecheck": "tsc --noEmit",
|
|
31
|
-
"git:push": "sh ./scripts/git-push-with-published-oagen.sh",
|
|
32
35
|
"oagen:build:local": "npm --prefix ../oagen run build",
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"prepare": "husky"
|
|
36
|
-
"sdk:generate:dotnet": "oagen generate --lang dotnet --output ./sdk-dotnet --namespace workos --api-surface ./sdk-dotnet-surface.json",
|
|
37
|
-
"sdk:verify:dotnet": "oagen verify --lang dotnet --output ./sdk-dotnet --api-surface ./sdk-dotnet-surface.json",
|
|
38
|
-
"sdk:extract:dotnet": "oagen extract --lang dotnet --sdk-path ../backend/workos-dotnet --output ./sdk-dotnet-surface.json",
|
|
39
|
-
"sdk:generate:elixir": "oagen generate --lang elixir --output ./sdk-elixir --namespace workos --api-surface ./sdk-elixir-surface.json",
|
|
40
|
-
"sdk:verify:elixir": "oagen verify --lang elixir --output ./sdk-elixir --api-surface ./sdk-elixir-surface.json",
|
|
41
|
-
"sdk:extract:elixir": "oagen extract --lang elixir --sdk-path ../backend/workos-elixir --output ./sdk-elixir-surface.json",
|
|
42
|
-
"sdk:generate:go": "oagen generate --lang go --output ./sdk-go --namespace workos --api-surface ./sdk-go-surface.json",
|
|
43
|
-
"sdk:verify:go": "oagen verify --lang go --output ./sdk-go --api-surface ./sdk-go-surface.json",
|
|
44
|
-
"sdk:extract:go": "oagen extract --lang go --sdk-path ../backend/workos-go --output ./sdk-go-surface.json",
|
|
45
|
-
"sdk:generate:kotlin": "oagen generate --lang kotlin --output ./sdk-kotlin --namespace workos --api-surface ./sdk-kotlin-surface.json",
|
|
46
|
-
"sdk:verify:kotlin": "oagen verify --lang kotlin --output ./sdk-kotlin --api-surface ./sdk-kotlin-surface.json",
|
|
47
|
-
"sdk:extract:kotlin": "oagen extract --lang kotlin --sdk-path ../backend/workos-kotlin --output ./sdk-kotlin-surface.json",
|
|
48
|
-
"sdk:generate:node": "oagen generate --lang node --output ./sdk-node --namespace workos --api-surface ./sdk-node-surface.json",
|
|
49
|
-
"sdk:verify:node": "oagen verify --lang node --output ./sdk-node --api-surface ./sdk-node-surface.json",
|
|
50
|
-
"sdk:extract:node": "oagen extract --lang node --sdk-path ../backend/workos-node --output ./sdk-node-surface.json",
|
|
51
|
-
"sdk:generate:php": "node scripts/generate-php.js",
|
|
52
|
-
"sdk:verify:php": "oagen verify --lang php --output ./sdk-php --api-surface ./sdk-php-surface.json",
|
|
53
|
-
"sdk:extract:php": "oagen extract --lang php --sdk-path ../backend/workos-php --output ./sdk-php-surface.json",
|
|
54
|
-
"sdk:generate:python": "oagen generate --lang python --output ./sdk-python --namespace workos --api-surface ./sdk-python-surface.json",
|
|
55
|
-
"sdk:verify:python": "oagen verify --lang python --output ./sdk-python --api-surface ./sdk-python-surface.json",
|
|
56
|
-
"sdk:extract:python": "oagen extract --lang python --sdk-path ../backend/workos-python --output ./sdk-python-surface.json",
|
|
57
|
-
"sdk:generate:ruby": "oagen generate --lang ruby --output ./sdk-ruby --namespace workos --api-surface ./sdk-ruby-surface.json",
|
|
58
|
-
"sdk:verify:ruby": "oagen verify --lang ruby --output ./sdk-ruby --api-surface ./sdk-ruby-surface.json",
|
|
59
|
-
"sdk:extract:ruby": "oagen extract --lang ruby --sdk-path ../backend/workos-ruby --output ./sdk-ruby-surface.json",
|
|
60
|
-
"sdk:generate:rust": "oagen generate --lang rust --output ./sdk-rust --namespace workos --api-surface ./sdk-rust-surface.json",
|
|
61
|
-
"sdk:verify:rust": "oagen verify --lang rust --output ./sdk-rust --api-surface ./sdk-rust-surface.json",
|
|
62
|
-
"sdk:extract:rust": "oagen extract --lang rust --sdk-path ../backend/workos-rust --output ./sdk-rust-surface.json"
|
|
36
|
+
"dev:link": "npm run oagen:build:local && npm link --prefix ../oagen && npm link @workos/oagen",
|
|
37
|
+
"dev:unlink": "npm install",
|
|
38
|
+
"prepare": "husky"
|
|
63
39
|
},
|
|
64
40
|
"devDependencies": {
|
|
65
41
|
"@commitlint/cli": "^20.5.0",
|
|
66
42
|
"@commitlint/config-conventional": "^20.5.0",
|
|
67
43
|
"@types/node": "^25.3.3",
|
|
68
44
|
"husky": "^9.1.7",
|
|
69
|
-
"oxfmt": "^0.
|
|
45
|
+
"oxfmt": "^0.45.0",
|
|
70
46
|
"oxlint": "^1.51.0",
|
|
71
47
|
"prettier": "^3.8.1",
|
|
72
48
|
"tsdown": "^0.21.5",
|
|
@@ -78,6 +54,6 @@
|
|
|
78
54
|
"node": ">=24.10.0"
|
|
79
55
|
},
|
|
80
56
|
"dependencies": {
|
|
81
|
-
"@workos/oagen": "^0.
|
|
57
|
+
"@workos/oagen": "^0.7.0"
|
|
82
58
|
}
|
|
83
59
|
}
|
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 });
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { ApiSpec, EmitterContext, GeneratedFile, Service } from '@workos/oagen';
|
|
2
|
+
import { toPascalCase, toSnakeCase } from '@workos/oagen';
|
|
3
|
+
import { resolveResourceClassName } from './resources.js';
|
|
4
|
+
import { className, serviceTypeName, humanize } from './naming.js';
|
|
5
|
+
import { getMountTarget } from '../shared/resolved-ops.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Generate the C# client file with service accessors.
|
|
9
|
+
* Produces: WorkOSClient.Generated.cs (partial class with service properties).
|
|
10
|
+
*/
|
|
11
|
+
export function generateClient(spec: ApiSpec, ctx: EmitterContext): GeneratedFile[] {
|
|
12
|
+
return [generateClientFile(spec, ctx)];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Deduplicate services by mount target.
|
|
17
|
+
*/
|
|
18
|
+
function deduplicateByMount(services: Service[], ctx: EmitterContext): Service[] {
|
|
19
|
+
const byTarget = new Map<string, Service>();
|
|
20
|
+
for (const s of services) {
|
|
21
|
+
const target = getMountTarget(s, ctx);
|
|
22
|
+
const existing = byTarget.get(target);
|
|
23
|
+
if (!existing || toPascalCase(s.name) === target) {
|
|
24
|
+
byTarget.set(target, s);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return [...byTarget.values()];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Build map of service name -> accessor property name.
|
|
32
|
+
*/
|
|
33
|
+
export function buildServiceAccessPaths(services: Service[], ctx: EmitterContext): Map<string, string> {
|
|
34
|
+
const topLevel = deduplicateByMount(services, ctx);
|
|
35
|
+
const paths = new Map<string, string>();
|
|
36
|
+
|
|
37
|
+
for (const service of topLevel) {
|
|
38
|
+
const resolvedName = resolveResourceClassName(service, ctx);
|
|
39
|
+
const prop = toSnakeCase(resolvedName);
|
|
40
|
+
paths.set(service.name, prop);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Also map mount targets
|
|
44
|
+
for (const service of services) {
|
|
45
|
+
const target = getMountTarget(service, ctx);
|
|
46
|
+
if (!paths.has(target)) {
|
|
47
|
+
const existing = paths.get(service.name);
|
|
48
|
+
if (existing) paths.set(target, existing);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return paths;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function generateClientFile(spec: ApiSpec, ctx: EmitterContext): GeneratedFile {
|
|
56
|
+
const topLevel = deduplicateByMount(spec.services, ctx);
|
|
57
|
+
const lines: string[] = [];
|
|
58
|
+
|
|
59
|
+
lines.push(`namespace ${ctx.namespacePascal}`);
|
|
60
|
+
lines.push('{');
|
|
61
|
+
lines.push(' /// <summary>');
|
|
62
|
+
lines.push(' /// Generated service accessors for WorkOSClient.');
|
|
63
|
+
lines.push(' /// </summary>');
|
|
64
|
+
lines.push(' public partial class WorkOSClient');
|
|
65
|
+
lines.push(' {');
|
|
66
|
+
|
|
67
|
+
// Service properties with lazy initialization
|
|
68
|
+
for (const service of topLevel) {
|
|
69
|
+
const resolvedName = resolveResourceClassName(service, ctx);
|
|
70
|
+
const propName = className(resolvedName);
|
|
71
|
+
const svcType = serviceTypeName(resolvedName);
|
|
72
|
+
const backingField = propName.charAt(0).toLowerCase() + propName.slice(1);
|
|
73
|
+
const human = humanize(resolvedName);
|
|
74
|
+
lines.push(` private ${svcType} ${backingField};`);
|
|
75
|
+
lines.push('');
|
|
76
|
+
lines.push(` /// <summary>Gets the <see cref="${svcType}"/> for ${human} API operations.</summary>`);
|
|
77
|
+
lines.push(` public virtual ${svcType} ${propName} => this.${backingField} ??= new ${svcType}(this);`);
|
|
78
|
+
lines.push('');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
lines.push(' }');
|
|
82
|
+
lines.push('}');
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
path: 'Client/WorkOSClient.Generated.cs',
|
|
86
|
+
content: lines.join('\n'),
|
|
87
|
+
overwriteExisting: true,
|
|
88
|
+
};
|
|
89
|
+
}
|