workos 0.11.2 → 0.12.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 (186) hide show
  1. package/README.md +165 -6
  2. package/dist/bin.js +22 -1
  3. package/dist/bin.js.map +1 -1
  4. package/dist/check-coverage.ts +237 -0
  5. package/dist/commands/debug.js +0 -1
  6. package/dist/commands/debug.js.map +1 -1
  7. package/dist/commands/dev.d.ts +23 -0
  8. package/dist/commands/dev.js +139 -0
  9. package/dist/commands/dev.js.map +1 -0
  10. package/dist/commands/emulate.d.ts +6 -0
  11. package/dist/commands/emulate.js +64 -0
  12. package/dist/commands/emulate.js.map +1 -0
  13. package/dist/commands/login.js +0 -4
  14. package/dist/commands/login.js.map +1 -1
  15. package/dist/emulate/core/id.d.ts +48 -0
  16. package/dist/emulate/core/id.js +73 -0
  17. package/dist/emulate/core/id.js.map +1 -0
  18. package/dist/emulate/core/index.d.ts +8 -0
  19. package/dist/emulate/core/index.js +8 -0
  20. package/dist/emulate/core/index.js.map +1 -0
  21. package/dist/emulate/core/jwt.d.ts +28 -0
  22. package/dist/emulate/core/jwt.js +78 -0
  23. package/dist/emulate/core/jwt.js.map +1 -0
  24. package/dist/emulate/core/middleware/auth.d.ts +15 -0
  25. package/dist/emulate/core/middleware/auth.js +17 -0
  26. package/dist/emulate/core/middleware/auth.js.map +1 -0
  27. package/dist/emulate/core/middleware/error-handler.d.ts +22 -0
  28. package/dist/emulate/core/middleware/error-handler.js +72 -0
  29. package/dist/emulate/core/middleware/error-handler.js.map +1 -0
  30. package/dist/emulate/core/pagination.d.ts +27 -0
  31. package/dist/emulate/core/pagination.js +43 -0
  32. package/dist/emulate/core/pagination.js.map +1 -0
  33. package/dist/emulate/core/plugin.d.ts +15 -0
  34. package/dist/emulate/core/plugin.js +2 -0
  35. package/dist/emulate/core/plugin.js.map +1 -0
  36. package/dist/emulate/core/server.d.ts +17 -0
  37. package/dist/emulate/core/server.js +90 -0
  38. package/dist/emulate/core/server.js.map +1 -0
  39. package/dist/emulate/core/store.d.ts +44 -0
  40. package/dist/emulate/core/store.js +169 -0
  41. package/dist/emulate/core/store.js.map +1 -0
  42. package/dist/emulate/index.d.ts +25 -0
  43. package/dist/emulate/index.js +47 -0
  44. package/dist/emulate/index.js.map +1 -0
  45. package/dist/emulate/workos/constants.d.ts +56 -0
  46. package/dist/emulate/workos/constants.js +56 -0
  47. package/dist/emulate/workos/constants.js.map +1 -0
  48. package/dist/emulate/workos/entities.d.ts +360 -0
  49. package/dist/emulate/workos/entities.js +2 -0
  50. package/dist/emulate/workos/entities.js.map +1 -0
  51. package/dist/emulate/workos/event-bus.d.ts +17 -0
  52. package/dist/emulate/workos/event-bus.js +70 -0
  53. package/dist/emulate/workos/event-bus.js.map +1 -0
  54. package/dist/emulate/workos/helpers.d.ts +72 -0
  55. package/dist/emulate/workos/helpers.js +211 -0
  56. package/dist/emulate/workos/helpers.js.map +1 -0
  57. package/dist/emulate/workos/index.d.ts +91 -0
  58. package/dist/emulate/workos/index.js +322 -0
  59. package/dist/emulate/workos/index.js.map +1 -0
  60. package/dist/emulate/workos/role-helpers.d.ts +21 -0
  61. package/dist/emulate/workos/role-helpers.js +130 -0
  62. package/dist/emulate/workos/role-helpers.js.map +1 -0
  63. package/dist/emulate/workos/routes/api-keys.d.ts +2 -0
  64. package/dist/emulate/workos/routes/api-keys.js +32 -0
  65. package/dist/emulate/workos/routes/api-keys.js.map +1 -0
  66. package/dist/emulate/workos/routes/audit-logs.d.ts +2 -0
  67. package/dist/emulate/workos/routes/audit-logs.js +104 -0
  68. package/dist/emulate/workos/routes/audit-logs.js.map +1 -0
  69. package/dist/emulate/workos/routes/auth-challenges.d.ts +2 -0
  70. package/dist/emulate/workos/routes/auth-challenges.js +51 -0
  71. package/dist/emulate/workos/routes/auth-challenges.js.map +1 -0
  72. package/dist/emulate/workos/routes/auth-factors.d.ts +2 -0
  73. package/dist/emulate/workos/routes/auth-factors.js +51 -0
  74. package/dist/emulate/workos/routes/auth-factors.js.map +1 -0
  75. package/dist/emulate/workos/routes/auth.d.ts +2 -0
  76. package/dist/emulate/workos/routes/auth.js +350 -0
  77. package/dist/emulate/workos/routes/auth.js.map +1 -0
  78. package/dist/emulate/workos/routes/authorization-checks.d.ts +10 -0
  79. package/dist/emulate/workos/routes/authorization-checks.js +123 -0
  80. package/dist/emulate/workos/routes/authorization-checks.js.map +1 -0
  81. package/dist/emulate/workos/routes/authorization-org-roles.d.ts +2 -0
  82. package/dist/emulate/workos/routes/authorization-org-roles.js +64 -0
  83. package/dist/emulate/workos/routes/authorization-org-roles.js.map +1 -0
  84. package/dist/emulate/workos/routes/authorization-permissions.d.ts +2 -0
  85. package/dist/emulate/workos/routes/authorization-permissions.js +67 -0
  86. package/dist/emulate/workos/routes/authorization-permissions.js.map +1 -0
  87. package/dist/emulate/workos/routes/authorization-resources.d.ts +2 -0
  88. package/dist/emulate/workos/routes/authorization-resources.js +117 -0
  89. package/dist/emulate/workos/routes/authorization-resources.js.map +1 -0
  90. package/dist/emulate/workos/routes/authorization-roles.d.ts +2 -0
  91. package/dist/emulate/workos/routes/authorization-roles.js +13 -0
  92. package/dist/emulate/workos/routes/authorization-roles.js.map +1 -0
  93. package/dist/emulate/workos/routes/config.d.ts +2 -0
  94. package/dist/emulate/workos/routes/config.js +57 -0
  95. package/dist/emulate/workos/routes/config.js.map +1 -0
  96. package/dist/emulate/workos/routes/connect.d.ts +2 -0
  97. package/dist/emulate/workos/routes/connect.js +65 -0
  98. package/dist/emulate/workos/routes/connect.js.map +1 -0
  99. package/dist/emulate/workos/routes/connections.d.ts +2 -0
  100. package/dist/emulate/workos/routes/connections.js +73 -0
  101. package/dist/emulate/workos/routes/connections.js.map +1 -0
  102. package/dist/emulate/workos/routes/data-integrations.d.ts +2 -0
  103. package/dist/emulate/workos/routes/data-integrations.js +55 -0
  104. package/dist/emulate/workos/routes/data-integrations.js.map +1 -0
  105. package/dist/emulate/workos/routes/directories.d.ts +2 -0
  106. package/dist/emulate/workos/routes/directories.js +90 -0
  107. package/dist/emulate/workos/routes/directories.js.map +1 -0
  108. package/dist/emulate/workos/routes/email-verification.d.ts +2 -0
  109. package/dist/emulate/workos/routes/email-verification.js +49 -0
  110. package/dist/emulate/workos/routes/email-verification.js.map +1 -0
  111. package/dist/emulate/workos/routes/events.d.ts +2 -0
  112. package/dist/emulate/workos/routes/events.js +18 -0
  113. package/dist/emulate/workos/routes/events.js.map +1 -0
  114. package/dist/emulate/workos/routes/feature-flags.d.ts +2 -0
  115. package/dist/emulate/workos/routes/feature-flags.js +103 -0
  116. package/dist/emulate/workos/routes/feature-flags.js.map +1 -0
  117. package/dist/emulate/workos/routes/invitations.d.ts +2 -0
  118. package/dist/emulate/workos/routes/invitations.js +122 -0
  119. package/dist/emulate/workos/routes/invitations.js.map +1 -0
  120. package/dist/emulate/workos/routes/legacy-mfa.d.ts +2 -0
  121. package/dist/emulate/workos/routes/legacy-mfa.js +75 -0
  122. package/dist/emulate/workos/routes/legacy-mfa.js.map +1 -0
  123. package/dist/emulate/workos/routes/magic-auth.d.ts +2 -0
  124. package/dist/emulate/workos/routes/magic-auth.js +32 -0
  125. package/dist/emulate/workos/routes/magic-auth.js.map +1 -0
  126. package/dist/emulate/workos/routes/memberships.d.ts +2 -0
  127. package/dist/emulate/workos/routes/memberships.js +114 -0
  128. package/dist/emulate/workos/routes/memberships.js.map +1 -0
  129. package/dist/emulate/workos/routes/organization-domains.d.ts +2 -0
  130. package/dist/emulate/workos/routes/organization-domains.js +58 -0
  131. package/dist/emulate/workos/routes/organization-domains.js.map +1 -0
  132. package/dist/emulate/workos/routes/organizations.d.ts +2 -0
  133. package/dist/emulate/workos/routes/organizations.js +131 -0
  134. package/dist/emulate/workos/routes/organizations.js.map +1 -0
  135. package/dist/emulate/workos/routes/password-reset.d.ts +2 -0
  136. package/dist/emulate/workos/routes/password-reset.js +61 -0
  137. package/dist/emulate/workos/routes/password-reset.js.map +1 -0
  138. package/dist/emulate/workos/routes/pipes.d.ts +2 -0
  139. package/dist/emulate/workos/routes/pipes.js +82 -0
  140. package/dist/emulate/workos/routes/pipes.js.map +1 -0
  141. package/dist/emulate/workos/routes/portal.d.ts +2 -0
  142. package/dist/emulate/workos/routes/portal.js +18 -0
  143. package/dist/emulate/workos/routes/portal.js.map +1 -0
  144. package/dist/emulate/workos/routes/radar.d.ts +2 -0
  145. package/dist/emulate/workos/routes/radar.js +41 -0
  146. package/dist/emulate/workos/routes/radar.js.map +1 -0
  147. package/dist/emulate/workos/routes/sessions.d.ts +2 -0
  148. package/dist/emulate/workos/routes/sessions.js +51 -0
  149. package/dist/emulate/workos/routes/sessions.js.map +1 -0
  150. package/dist/emulate/workos/routes/sso.d.ts +2 -0
  151. package/dist/emulate/workos/routes/sso.js +161 -0
  152. package/dist/emulate/workos/routes/sso.js.map +1 -0
  153. package/dist/emulate/workos/routes/user-features.d.ts +2 -0
  154. package/dist/emulate/workos/routes/user-features.js +50 -0
  155. package/dist/emulate/workos/routes/user-features.js.map +1 -0
  156. package/dist/emulate/workos/routes/users.d.ts +2 -0
  157. package/dist/emulate/workos/routes/users.js +129 -0
  158. package/dist/emulate/workos/routes/users.js.map +1 -0
  159. package/dist/emulate/workos/routes/webhook-endpoints.d.ts +2 -0
  160. package/dist/emulate/workos/routes/webhook-endpoints.js +66 -0
  161. package/dist/emulate/workos/routes/webhook-endpoints.js.map +1 -0
  162. package/dist/emulate/workos/routes/widgets.d.ts +2 -0
  163. package/dist/emulate/workos/routes/widgets.js +27 -0
  164. package/dist/emulate/workos/routes/widgets.js.map +1 -0
  165. package/dist/emulate/workos/store.d.ts +48 -0
  166. package/dist/emulate/workos/store.js +102 -0
  167. package/dist/emulate/workos/store.js.map +1 -0
  168. package/dist/emulate/workos/webhook-signer.d.ts +1 -0
  169. package/dist/emulate/workos/webhook-signer.js +8 -0
  170. package/dist/emulate/workos/webhook-signer.js.map +1 -0
  171. package/dist/gen-routes-lib.spec.ts +659 -0
  172. package/dist/gen-routes-lib.ts +647 -0
  173. package/dist/gen-routes.ts +96 -0
  174. package/dist/lib/dev-command.d.ts +26 -0
  175. package/dist/lib/dev-command.js +122 -0
  176. package/dist/lib/dev-command.js.map +1 -0
  177. package/dist/lib/run-with-core.js +0 -3
  178. package/dist/lib/run-with-core.js.map +1 -1
  179. package/dist/lib/settings.js +1 -1
  180. package/dist/lib/settings.js.map +1 -1
  181. package/dist/utils/help-json.js +1 -0
  182. package/dist/utils/help-json.js.map +1 -1
  183. package/dist/utils/register-subcommand.d.ts +5 -2
  184. package/dist/utils/register-subcommand.js +16 -19
  185. package/dist/utils/register-subcommand.js.map +1 -1
  186. package/package.json +21 -8
@@ -0,0 +1,211 @@
1
+ import { randomBytes, createHash, createCipheriv } from 'node:crypto';
2
+ import { WorkOSApiError } from '../core/index.js';
3
+ const INTERNAL_FIELDS = new Set(['password_hash', 'code_challenge', 'code_challenge_method']);
4
+ export function formatEntity(entity, opts) {
5
+ const exclude = opts?.exclude ?? INTERNAL_FIELDS;
6
+ const result = {};
7
+ for (const [key, value] of Object.entries(entity)) {
8
+ if (!exclude.has(key))
9
+ result[key] = value;
10
+ }
11
+ return result;
12
+ }
13
+ export function formatListResponse(result, formatter) {
14
+ return {
15
+ object: 'list',
16
+ data: result.data.map(formatter),
17
+ list_metadata: result.list_metadata,
18
+ };
19
+ }
20
+ export function formatOrganization(org, ws, opts) {
21
+ const domains = (opts?.domains ?? ws.organizationDomains.findBy('organization_id', org.id)).map(formatDomain);
22
+ return {
23
+ object: 'organization',
24
+ id: org.id,
25
+ name: org.name,
26
+ external_id: org.external_id,
27
+ metadata: org.metadata,
28
+ domains,
29
+ stripe_customer_id: org.stripe_customer_id,
30
+ created_at: org.created_at,
31
+ updated_at: org.updated_at,
32
+ };
33
+ }
34
+ export function formatDomain(domain) {
35
+ return formatEntity(domain);
36
+ }
37
+ export function formatMembership(m) {
38
+ return formatEntity(m);
39
+ }
40
+ const USER_EXCLUDE = new Set([...INTERNAL_FIELDS, 'impersonator']);
41
+ export function formatUser(user) {
42
+ return formatEntity(user, { exclude: USER_EXCLUDE });
43
+ }
44
+ export function formatSession(s) {
45
+ return formatEntity(s);
46
+ }
47
+ export function formatEmailVerification(ev) {
48
+ return formatEntity(ev);
49
+ }
50
+ export function formatPasswordReset(pr) {
51
+ return formatEntity(pr);
52
+ }
53
+ export function formatMagicAuth(ma) {
54
+ return formatEntity(ma);
55
+ }
56
+ export function formatAuthFactor(f) {
57
+ return formatEntity(f);
58
+ }
59
+ export function formatIdentity(i) {
60
+ return formatEntity(i);
61
+ }
62
+ export function generateVerificationToken() {
63
+ return randomBytes(16).toString('hex');
64
+ }
65
+ export function generateCode() {
66
+ return String(Math.floor(100000 + Math.random() * 900000));
67
+ }
68
+ export function hashPassword(password) {
69
+ return createHash('sha256').update(password).digest('hex');
70
+ }
71
+ export function verifyPassword(password, hash) {
72
+ return hashPassword(password) === hash;
73
+ }
74
+ export function expiresIn(minutes) {
75
+ return new Date(Date.now() + minutes * 60 * 1000).toISOString();
76
+ }
77
+ export function isExpired(expiresAt) {
78
+ return new Date(expiresAt).getTime() < Date.now();
79
+ }
80
+ export function formatConnection(conn) {
81
+ return formatEntity(conn);
82
+ }
83
+ export function formatSSOProfile(p) {
84
+ return formatEntity(p);
85
+ }
86
+ export function formatPipeConnection(pc) {
87
+ return formatEntity(pc);
88
+ }
89
+ export function formatInvitation(inv) {
90
+ return formatEntity(inv);
91
+ }
92
+ export function formatRedirectUri(r) {
93
+ return formatEntity(r);
94
+ }
95
+ export function formatCorsOrigin(o) {
96
+ return formatEntity(o);
97
+ }
98
+ export function formatAuthorizedApplication(a) {
99
+ return formatEntity(a);
100
+ }
101
+ export function formatConnectedAccount(a) {
102
+ return formatEntity(a);
103
+ }
104
+ /** Allowed redirect URI hosts for the emulator's authorize endpoints. */
105
+ const ALLOWED_REDIRECT_HOSTS = new Set(['localhost', '127.0.0.1', '[::1]']);
106
+ /**
107
+ * Validate that a redirect_uri points to a localhost origin.
108
+ * Prevents the emulator from being used as an open redirect.
109
+ */
110
+ export function assertLocalRedirectUri(uri) {
111
+ let parsed;
112
+ try {
113
+ parsed = new URL(uri);
114
+ }
115
+ catch {
116
+ throw new WorkOSApiError(400, 'Invalid redirect_uri', 'invalid_redirect_uri');
117
+ }
118
+ if (!ALLOWED_REDIRECT_HOSTS.has(parsed.hostname)) {
119
+ throw new WorkOSApiError(400, `redirect_uri must point to localhost, got ${parsed.hostname}`, 'invalid_redirect_uri');
120
+ }
121
+ }
122
+ const AUTH_CHALLENGE_EXCLUDE = new Set([...INTERNAL_FIELDS, 'code']);
123
+ export function formatAuthChallenge(c) {
124
+ return formatEntity(c, { exclude: AUTH_CHALLENGE_EXCLUDE });
125
+ }
126
+ export function formatRole(role) {
127
+ return formatEntity(role);
128
+ }
129
+ export function formatPermission(p) {
130
+ return formatEntity(p);
131
+ }
132
+ export function formatAuthorizationResource(r) {
133
+ return formatEntity(r);
134
+ }
135
+ export function formatRoleAssignment(ra) {
136
+ return formatEntity(ra);
137
+ }
138
+ export function formatDeviceAuthorization(d) {
139
+ return {
140
+ device_code: d.device_code,
141
+ user_code: d.user_code,
142
+ verification_uri: 'http://localhost:0/user_management/authorize/device/verify',
143
+ expires_in: Math.max(0, Math.floor((new Date(d.expires_at).getTime() - Date.now()) / 1000)),
144
+ interval: d.interval,
145
+ };
146
+ }
147
+ export function formatDirectory(d) {
148
+ return formatEntity(d);
149
+ }
150
+ export function formatDirectoryUser(u) {
151
+ return formatEntity(u);
152
+ }
153
+ export function formatDirectoryGroup(g) {
154
+ return formatEntity(g);
155
+ }
156
+ export function formatAuditLogAction(a) {
157
+ return formatEntity(a);
158
+ }
159
+ export function formatAuditLogEvent(e) {
160
+ return formatEntity(e);
161
+ }
162
+ export function formatAuditLogExport(ex) {
163
+ return formatEntity(ex);
164
+ }
165
+ export function formatFeatureFlag(f) {
166
+ return formatEntity(f);
167
+ }
168
+ export function formatFlagTarget(t) {
169
+ return formatEntity(t);
170
+ }
171
+ export function formatConnectApplication(a) {
172
+ return formatEntity(a);
173
+ }
174
+ const CLIENT_SECRET_EXCLUDE = new Set([...INTERNAL_FIELDS, 'value']);
175
+ export function formatClientSecret(s) {
176
+ return formatEntity(s, { exclude: CLIENT_SECRET_EXCLUDE });
177
+ }
178
+ export function formatRadarAttempt(a) {
179
+ return formatEntity(a);
180
+ }
181
+ const API_KEY_EXCLUDE = new Set([...INTERNAL_FIELDS, 'key', 'environment']);
182
+ export function formatApiKeyRecord(k) {
183
+ return formatEntity(k, { exclude: API_KEY_EXCLUDE });
184
+ }
185
+ const EVENT_EXCLUDE = new Set([...INTERNAL_FIELDS, 'updated_at']);
186
+ export function formatEvent(e) {
187
+ return formatEntity(e, { exclude: EVENT_EXCLUDE });
188
+ }
189
+ export function formatWebhookEndpoint(ep, opts) {
190
+ return {
191
+ object: 'webhook_endpoint',
192
+ id: ep.id,
193
+ url: ep.url,
194
+ secret: opts?.includeSecret ? ep.secret : `${ep.secret.slice(0, 8)}****`,
195
+ enabled: ep.enabled,
196
+ events: ep.events,
197
+ description: ep.description,
198
+ created_at: ep.created_at,
199
+ updated_at: ep.updated_at,
200
+ };
201
+ }
202
+ export function sealSession(data, apiKey) {
203
+ const key = createHash('sha256').update(apiKey).digest();
204
+ const iv = randomBytes(12);
205
+ const cipher = createCipheriv('aes-256-gcm', key, iv);
206
+ const plaintext = JSON.stringify(data);
207
+ const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
208
+ const tag = cipher.getAuthTag();
209
+ return Buffer.concat([iv, tag, encrypted]).toString('base64');
210
+ }
211
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/emulate/workos/helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomBytes, createHash, createCipheriv } from 'node:crypto';\nimport { WorkOSApiError, type CursorPaginatedResult, type Entity } from '../core/index.js';\nimport type { WorkOSStore } from './store.js';\nimport type {\n WorkOSOrganization,\n WorkOSOrganizationDomain,\n WorkOSOrganizationMembership,\n WorkOSUser,\n WorkOSSession,\n WorkOSEmailVerification,\n WorkOSPasswordReset,\n WorkOSMagicAuth,\n WorkOSAuthenticationFactor,\n WorkOSIdentity,\n WorkOSConnection,\n WorkOSSSOProfile,\n WorkOSPipeConnection,\n WorkOSInvitation,\n WorkOSRedirectUri,\n WorkOSCorsOrigin,\n WorkOSAuthorizedApplication,\n WorkOSConnectedAccount,\n WorkOSAuthenticationChallenge,\n WorkOSDeviceAuthorization,\n WorkOSRole,\n WorkOSPermission,\n WorkOSAuthorizationResource,\n WorkOSRoleAssignment,\n WorkOSDirectory,\n WorkOSDirectoryUser,\n WorkOSDirectoryGroup,\n WorkOSAuditLogAction,\n WorkOSAuditLogEvent,\n WorkOSAuditLogExport,\n WorkOSFeatureFlag,\n WorkOSFlagTarget,\n WorkOSConnectApplication,\n WorkOSClientSecret,\n WorkOSRadarAttempt,\n WorkOSApiKey,\n WorkOSEvent,\n WorkOSWebhookEndpoint,\n} from './entities.js';\n\nconst INTERNAL_FIELDS = new Set<string>(['password_hash', 'code_challenge', 'code_challenge_method']);\n\nexport function formatEntity<T extends Entity>(entity: T, opts?: { exclude?: Set<string> }): Record<string, unknown> {\n const exclude = opts?.exclude ?? INTERNAL_FIELDS;\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(entity)) {\n if (!exclude.has(key)) result[key] = value;\n }\n return result;\n}\n\nexport function formatListResponse<T>(\n result: CursorPaginatedResult<T>,\n formatter: (item: T) => Record<string, unknown>,\n): { object: 'list'; data: Record<string, unknown>[]; list_metadata: { before: string | null; after: string | null } } {\n return {\n object: 'list',\n data: result.data.map(formatter),\n list_metadata: result.list_metadata,\n };\n}\n\nexport function formatOrganization(\n org: WorkOSOrganization,\n ws: WorkOSStore,\n opts?: { domains?: WorkOSOrganizationDomain[] },\n): Record<string, unknown> {\n const domains = (opts?.domains ?? ws.organizationDomains.findBy('organization_id', org.id)).map(formatDomain);\n\n return {\n object: 'organization',\n id: org.id,\n name: org.name,\n external_id: org.external_id,\n metadata: org.metadata,\n domains,\n stripe_customer_id: org.stripe_customer_id,\n created_at: org.created_at,\n updated_at: org.updated_at,\n };\n}\n\nexport function formatDomain(domain: WorkOSOrganizationDomain): Record<string, unknown> {\n return formatEntity(domain);\n}\n\nexport function formatMembership(m: WorkOSOrganizationMembership): Record<string, unknown> {\n return formatEntity(m);\n}\n\nconst USER_EXCLUDE = new Set([...INTERNAL_FIELDS, 'impersonator']);\n\nexport function formatUser(user: WorkOSUser): Record<string, unknown> {\n return formatEntity(user, { exclude: USER_EXCLUDE });\n}\n\nexport function formatSession(s: WorkOSSession): Record<string, unknown> {\n return formatEntity(s);\n}\n\nexport function formatEmailVerification(ev: WorkOSEmailVerification): Record<string, unknown> {\n return formatEntity(ev);\n}\n\nexport function formatPasswordReset(pr: WorkOSPasswordReset): Record<string, unknown> {\n return formatEntity(pr);\n}\n\nexport function formatMagicAuth(ma: WorkOSMagicAuth): Record<string, unknown> {\n return formatEntity(ma);\n}\n\nexport function formatAuthFactor(f: WorkOSAuthenticationFactor): Record<string, unknown> {\n return formatEntity(f);\n}\n\nexport function formatIdentity(i: WorkOSIdentity): Record<string, unknown> {\n return formatEntity(i);\n}\n\nexport function generateVerificationToken(): string {\n return randomBytes(16).toString('hex');\n}\n\nexport function generateCode(): string {\n return String(Math.floor(100000 + Math.random() * 900000));\n}\n\nexport function hashPassword(password: string): string {\n return createHash('sha256').update(password).digest('hex');\n}\n\nexport function verifyPassword(password: string, hash: string): boolean {\n return hashPassword(password) === hash;\n}\n\nexport function expiresIn(minutes: number): string {\n return new Date(Date.now() + minutes * 60 * 1000).toISOString();\n}\n\nexport function isExpired(expiresAt: string): boolean {\n return new Date(expiresAt).getTime() < Date.now();\n}\n\nexport function formatConnection(conn: WorkOSConnection): Record<string, unknown> {\n return formatEntity(conn);\n}\n\nexport function formatSSOProfile(p: WorkOSSSOProfile): Record<string, unknown> {\n return formatEntity(p);\n}\n\nexport function formatPipeConnection(pc: WorkOSPipeConnection): Record<string, unknown> {\n return formatEntity(pc);\n}\n\nexport function formatInvitation(inv: WorkOSInvitation): Record<string, unknown> {\n return formatEntity(inv);\n}\n\nexport function formatRedirectUri(r: WorkOSRedirectUri): Record<string, unknown> {\n return formatEntity(r);\n}\n\nexport function formatCorsOrigin(o: WorkOSCorsOrigin): Record<string, unknown> {\n return formatEntity(o);\n}\n\nexport function formatAuthorizedApplication(a: WorkOSAuthorizedApplication): Record<string, unknown> {\n return formatEntity(a);\n}\n\nexport function formatConnectedAccount(a: WorkOSConnectedAccount): Record<string, unknown> {\n return formatEntity(a);\n}\n\n/** Allowed redirect URI hosts for the emulator's authorize endpoints. */\nconst ALLOWED_REDIRECT_HOSTS = new Set(['localhost', '127.0.0.1', '[::1]']);\n\n/**\n * Validate that a redirect_uri points to a localhost origin.\n * Prevents the emulator from being used as an open redirect.\n */\nexport function assertLocalRedirectUri(uri: string): void {\n let parsed: URL;\n try {\n parsed = new URL(uri);\n } catch {\n throw new WorkOSApiError(400, 'Invalid redirect_uri', 'invalid_redirect_uri');\n }\n if (!ALLOWED_REDIRECT_HOSTS.has(parsed.hostname)) {\n throw new WorkOSApiError(\n 400,\n `redirect_uri must point to localhost, got ${parsed.hostname}`,\n 'invalid_redirect_uri',\n );\n }\n}\n\nconst AUTH_CHALLENGE_EXCLUDE = new Set([...INTERNAL_FIELDS, 'code']);\n\nexport function formatAuthChallenge(c: WorkOSAuthenticationChallenge): Record<string, unknown> {\n return formatEntity(c, { exclude: AUTH_CHALLENGE_EXCLUDE });\n}\n\nexport function formatRole(role: WorkOSRole): Record<string, unknown> {\n return formatEntity(role);\n}\n\nexport function formatPermission(p: WorkOSPermission): Record<string, unknown> {\n return formatEntity(p);\n}\n\nexport function formatAuthorizationResource(r: WorkOSAuthorizationResource): Record<string, unknown> {\n return formatEntity(r);\n}\n\nexport function formatRoleAssignment(ra: WorkOSRoleAssignment): Record<string, unknown> {\n return formatEntity(ra);\n}\n\nexport function formatDeviceAuthorization(d: WorkOSDeviceAuthorization): Record<string, unknown> {\n return {\n device_code: d.device_code,\n user_code: d.user_code,\n verification_uri: 'http://localhost:0/user_management/authorize/device/verify',\n expires_in: Math.max(0, Math.floor((new Date(d.expires_at).getTime() - Date.now()) / 1000)),\n interval: d.interval,\n };\n}\n\nexport function formatDirectory(d: WorkOSDirectory): Record<string, unknown> {\n return formatEntity(d);\n}\n\nexport function formatDirectoryUser(u: WorkOSDirectoryUser): Record<string, unknown> {\n return formatEntity(u);\n}\n\nexport function formatDirectoryGroup(g: WorkOSDirectoryGroup): Record<string, unknown> {\n return formatEntity(g);\n}\n\nexport function formatAuditLogAction(a: WorkOSAuditLogAction): Record<string, unknown> {\n return formatEntity(a);\n}\n\nexport function formatAuditLogEvent(e: WorkOSAuditLogEvent): Record<string, unknown> {\n return formatEntity(e);\n}\n\nexport function formatAuditLogExport(ex: WorkOSAuditLogExport): Record<string, unknown> {\n return formatEntity(ex);\n}\n\nexport function formatFeatureFlag(f: WorkOSFeatureFlag): Record<string, unknown> {\n return formatEntity(f);\n}\n\nexport function formatFlagTarget(t: WorkOSFlagTarget): Record<string, unknown> {\n return formatEntity(t);\n}\n\nexport function formatConnectApplication(a: WorkOSConnectApplication): Record<string, unknown> {\n return formatEntity(a);\n}\n\nconst CLIENT_SECRET_EXCLUDE = new Set([...INTERNAL_FIELDS, 'value']);\n\nexport function formatClientSecret(s: WorkOSClientSecret): Record<string, unknown> {\n return formatEntity(s, { exclude: CLIENT_SECRET_EXCLUDE });\n}\n\nexport function formatRadarAttempt(a: WorkOSRadarAttempt): Record<string, unknown> {\n return formatEntity(a);\n}\n\nconst API_KEY_EXCLUDE = new Set([...INTERNAL_FIELDS, 'key', 'environment']);\n\nexport function formatApiKeyRecord(k: WorkOSApiKey): Record<string, unknown> {\n return formatEntity(k, { exclude: API_KEY_EXCLUDE });\n}\n\nconst EVENT_EXCLUDE = new Set([...INTERNAL_FIELDS, 'updated_at']);\n\nexport function formatEvent(e: WorkOSEvent): Record<string, unknown> {\n return formatEntity(e, { exclude: EVENT_EXCLUDE });\n}\n\nexport function formatWebhookEndpoint(\n ep: WorkOSWebhookEndpoint,\n opts?: { includeSecret?: boolean },\n): Record<string, unknown> {\n return {\n object: 'webhook_endpoint',\n id: ep.id,\n url: ep.url,\n secret: opts?.includeSecret ? ep.secret : `${ep.secret.slice(0, 8)}****`,\n enabled: ep.enabled,\n events: ep.events,\n description: ep.description,\n created_at: ep.created_at,\n updated_at: ep.updated_at,\n };\n}\n\nexport function sealSession(\n data: { access_token: string; refresh_token: string; session_id: string },\n apiKey: string,\n): string {\n const key = createHash('sha256').update(apiKey).digest();\n const iv = randomBytes(12);\n const cipher = createCipheriv('aes-256-gcm', key, iv);\n const plaintext = JSON.stringify(data);\n const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);\n const tag = cipher.getAuthTag();\n return Buffer.concat([iv, tag, encrypted]).toString('base64');\n}\n"]}
@@ -0,0 +1,91 @@
1
+ import type { ServicePlugin, Store } from '../core/index.js';
2
+ import type { WorkOSConnectionType, PipeProvider, PipeConnectionStatus } from './entities.js';
3
+ export { getWorkOSStore, type WorkOSStore } from './store.js';
4
+ export * from './entities.js';
5
+ export interface WorkOSSeedOrganization {
6
+ name: string;
7
+ external_id?: string;
8
+ metadata?: Record<string, string>;
9
+ domains?: Array<{
10
+ domain: string;
11
+ state?: 'verified' | 'pending';
12
+ }>;
13
+ memberships?: Array<{
14
+ user_id: string;
15
+ role?: string;
16
+ status?: 'active' | 'inactive' | 'pending';
17
+ }>;
18
+ }
19
+ export interface WorkOSSeedUser {
20
+ email: string;
21
+ first_name?: string;
22
+ last_name?: string;
23
+ password?: string;
24
+ email_verified?: boolean;
25
+ external_id?: string;
26
+ metadata?: Record<string, string>;
27
+ impersonator?: {
28
+ email: string;
29
+ reason: string;
30
+ };
31
+ }
32
+ export interface WorkOSSeedConnection {
33
+ name: string;
34
+ connection_type?: WorkOSConnectionType;
35
+ organization: string;
36
+ state?: 'active' | 'inactive' | 'validating';
37
+ domains?: string[];
38
+ profiles?: Array<{
39
+ email: string;
40
+ first_name?: string;
41
+ last_name?: string;
42
+ idp_id?: string;
43
+ groups?: string[];
44
+ }>;
45
+ }
46
+ export interface WorkOSSeedPipeConnection {
47
+ user_id: string;
48
+ provider: PipeProvider;
49
+ scopes: string[];
50
+ status?: PipeConnectionStatus;
51
+ external_account_id?: string;
52
+ }
53
+ export interface WorkOSSeedInvitation {
54
+ email: string;
55
+ organization_id?: string;
56
+ inviter_user_id?: string;
57
+ role_slug?: string;
58
+ }
59
+ export interface WorkOSSeedRole {
60
+ slug: string;
61
+ name: string;
62
+ description?: string;
63
+ type?: 'EnvironmentRole' | 'OrganizationRole';
64
+ organization_id?: string;
65
+ is_default_role?: boolean;
66
+ priority?: number;
67
+ permissions?: string[];
68
+ }
69
+ export interface WorkOSSeedPermission {
70
+ slug: string;
71
+ name: string;
72
+ description?: string;
73
+ }
74
+ export interface WorkOSSeedWebhookEndpoint {
75
+ url: string;
76
+ events?: string[];
77
+ enabled?: boolean;
78
+ }
79
+ export interface WorkOSSeedConfig {
80
+ organizations?: WorkOSSeedOrganization[];
81
+ users?: WorkOSSeedUser[];
82
+ connections?: WorkOSSeedConnection[];
83
+ pipeConnections?: WorkOSSeedPipeConnection[];
84
+ invitations?: WorkOSSeedInvitation[];
85
+ roles?: WorkOSSeedRole[];
86
+ permissions?: WorkOSSeedPermission[];
87
+ webhookEndpoints?: WorkOSSeedWebhookEndpoint[];
88
+ }
89
+ export declare function seedFromConfig(store: Store, _baseUrl: string, config: WorkOSSeedConfig): void;
90
+ export declare const workosPlugin: ServicePlugin;
91
+ export default workosPlugin;
@@ -0,0 +1,322 @@
1
+ import { randomBytes } from 'node:crypto';
2
+ import { generateId } from '../core/index.js';
3
+ import { getWorkOSStore } from './store.js';
4
+ import { organizationRoutes } from './routes/organizations.js';
5
+ import { organizationDomainRoutes } from './routes/organization-domains.js';
6
+ import { membershipRoutes } from './routes/memberships.js';
7
+ import { userRoutes } from './routes/users.js';
8
+ import { emailVerificationRoutes } from './routes/email-verification.js';
9
+ import { passwordResetRoutes } from './routes/password-reset.js';
10
+ import { magicAuthRoutes } from './routes/magic-auth.js';
11
+ import { authFactorRoutes } from './routes/auth-factors.js';
12
+ import { sessionRoutes } from './routes/sessions.js';
13
+ import { authRoutes } from './routes/auth.js';
14
+ import { connectionRoutes } from './routes/connections.js';
15
+ import { ssoRoutes } from './routes/sso.js';
16
+ import { pipeRoutes } from './routes/pipes.js';
17
+ import { authChallengeRoutes } from './routes/auth-challenges.js';
18
+ import { invitationRoutes } from './routes/invitations.js';
19
+ import { configRoutes } from './routes/config.js';
20
+ import { userFeatureRoutes } from './routes/user-features.js';
21
+ import { widgetRoutes } from './routes/widgets.js';
22
+ import { authorizationRoleRoutes } from './routes/authorization-roles.js';
23
+ import { authorizationPermissionRoutes } from './routes/authorization-permissions.js';
24
+ import { authorizationOrgRoleRoutes } from './routes/authorization-org-roles.js';
25
+ import { authorizationResourceRoutes } from './routes/authorization-resources.js';
26
+ import { authorizationCheckRoutes } from './routes/authorization-checks.js';
27
+ import { portalRoutes } from './routes/portal.js';
28
+ import { legacyMfaRoutes } from './routes/legacy-mfa.js';
29
+ import { apiKeyRoutes } from './routes/api-keys.js';
30
+ import { radarRoutes } from './routes/radar.js';
31
+ import { connectRoutes } from './routes/connect.js';
32
+ import { directoryRoutes } from './routes/directories.js';
33
+ import { auditLogRoutes } from './routes/audit-logs.js';
34
+ import { featureFlagRoutes } from './routes/feature-flags.js';
35
+ import { dataIntegrationRoutes } from './routes/data-integrations.js';
36
+ import { webhookEndpointRoutes } from './routes/webhook-endpoints.js';
37
+ import { eventRoutes } from './routes/events.js';
38
+ import { EventBus } from './event-bus.js';
39
+ import { STORE_KEYS, EVENTS } from './constants.js';
40
+ import { generateVerificationToken, hashPassword, expiresIn, formatUser, formatOrganization, formatMembership, formatConnection, formatSession, formatInvitation, formatRole, formatPermission, formatDirectory, formatDirectoryUser, formatDirectoryGroup, formatDomain, } from './helpers.js';
41
+ export { getWorkOSStore } from './store.js';
42
+ export * from './entities.js';
43
+ export function seedFromConfig(store, _baseUrl, config) {
44
+ const ws = getWorkOSStore(store);
45
+ if (config.users) {
46
+ for (const userConfig of config.users) {
47
+ ws.users.insert({
48
+ object: 'user',
49
+ email: userConfig.email,
50
+ first_name: userConfig.first_name ?? null,
51
+ last_name: userConfig.last_name ?? null,
52
+ email_verified: userConfig.email_verified ?? false,
53
+ profile_picture_url: null,
54
+ last_sign_in_at: null,
55
+ external_id: userConfig.external_id ?? null,
56
+ metadata: userConfig.metadata ?? {},
57
+ locale: null,
58
+ password_hash: userConfig.password ? hashPassword(userConfig.password) : null,
59
+ impersonator: userConfig.impersonator ?? null,
60
+ });
61
+ }
62
+ }
63
+ if (config.organizations) {
64
+ for (const orgConfig of config.organizations) {
65
+ const org = ws.organizations.insert({
66
+ object: 'organization',
67
+ name: orgConfig.name,
68
+ external_id: orgConfig.external_id ?? null,
69
+ metadata: orgConfig.metadata ?? {},
70
+ stripe_customer_id: null,
71
+ });
72
+ if (orgConfig.domains) {
73
+ for (const dd of orgConfig.domains) {
74
+ ws.organizationDomains.insert({
75
+ object: 'organization_domain',
76
+ organization_id: org.id,
77
+ domain: dd.domain,
78
+ state: dd.state ?? 'pending',
79
+ verification_strategy: 'manual',
80
+ verification_token: generateVerificationToken(),
81
+ verification_prefix: 'workos-verify',
82
+ });
83
+ }
84
+ }
85
+ if (orgConfig.memberships) {
86
+ for (const mm of orgConfig.memberships) {
87
+ ws.organizationMemberships.insert({
88
+ object: 'organization_membership',
89
+ organization_id: org.id,
90
+ user_id: mm.user_id,
91
+ role: { slug: mm.role ?? 'member' },
92
+ status: mm.status ?? 'active',
93
+ external_id: null,
94
+ metadata: {},
95
+ });
96
+ }
97
+ }
98
+ }
99
+ }
100
+ if (config.connections) {
101
+ for (const connConfig of config.connections) {
102
+ const org = ws.organizations.findOneBy('name', connConfig.organization);
103
+ if (!org)
104
+ continue;
105
+ const domains = (connConfig.domains ?? []).map((d) => ({
106
+ object: 'connection_domain',
107
+ id: generateId('conn_domain'),
108
+ domain: d,
109
+ }));
110
+ const conn = ws.connections.insert({
111
+ object: 'connection',
112
+ organization_id: org.id,
113
+ connection_type: connConfig.connection_type ?? 'GenericSAML',
114
+ name: connConfig.name,
115
+ state: connConfig.state ?? 'active',
116
+ domains,
117
+ });
118
+ if (connConfig.profiles) {
119
+ for (const p of connConfig.profiles) {
120
+ ws.ssoProfiles.insert({
121
+ object: 'profile',
122
+ connection_id: conn.id,
123
+ connection_type: conn.connection_type,
124
+ organization_id: org.id,
125
+ idp_id: p.idp_id ?? `idp_${generateId('usr')}`,
126
+ email: p.email,
127
+ first_name: p.first_name ?? null,
128
+ last_name: p.last_name ?? null,
129
+ groups: p.groups ?? [],
130
+ raw_attributes: { email: p.email },
131
+ });
132
+ }
133
+ }
134
+ }
135
+ }
136
+ if (config.pipeConnections) {
137
+ for (const pc of config.pipeConnections) {
138
+ ws.pipeConnections.insert({
139
+ object: 'pipe_connection',
140
+ user_id: pc.user_id,
141
+ provider: pc.provider,
142
+ scopes: pc.scopes,
143
+ status: pc.status ?? 'connected',
144
+ external_account_id: pc.external_account_id ?? null,
145
+ });
146
+ }
147
+ }
148
+ if (config.permissions) {
149
+ for (const permConfig of config.permissions) {
150
+ ws.permissions.insert({
151
+ object: 'permission',
152
+ slug: permConfig.slug,
153
+ name: permConfig.name,
154
+ description: permConfig.description ?? null,
155
+ });
156
+ }
157
+ }
158
+ if (config.roles) {
159
+ for (const roleConfig of config.roles) {
160
+ const role = ws.roles.insert({
161
+ object: 'role',
162
+ slug: roleConfig.slug,
163
+ name: roleConfig.name,
164
+ description: roleConfig.description ?? null,
165
+ type: roleConfig.type ?? 'EnvironmentRole',
166
+ organization_id: roleConfig.organization_id ?? null,
167
+ is_default_role: roleConfig.is_default_role ?? false,
168
+ priority: roleConfig.priority ?? 0,
169
+ });
170
+ if (roleConfig.permissions) {
171
+ for (const permSlug of roleConfig.permissions) {
172
+ const perm = ws.permissions.findOneBy('slug', permSlug);
173
+ if (perm) {
174
+ ws.rolePermissions.insert({ role_id: role.id, permission_id: perm.id });
175
+ }
176
+ }
177
+ }
178
+ }
179
+ }
180
+ if (config.invitations) {
181
+ for (const invConfig of config.invitations) {
182
+ const token = generateVerificationToken();
183
+ ws.invitations.insert({
184
+ object: 'invitation',
185
+ email: invConfig.email,
186
+ state: 'pending',
187
+ token,
188
+ accept_invitation_url: `${_baseUrl}/user_management/invitations/accept?token=${token}`,
189
+ organization_id: invConfig.organization_id ?? null,
190
+ inviter_user_id: invConfig.inviter_user_id ?? null,
191
+ role_slug: invConfig.role_slug ?? null,
192
+ expires_at: expiresIn(72 * 60),
193
+ });
194
+ }
195
+ }
196
+ if (config.webhookEndpoints) {
197
+ for (const whConfig of config.webhookEndpoints) {
198
+ ws.webhookEndpoints.insert({
199
+ object: 'webhook_endpoint',
200
+ url: whConfig.url,
201
+ secret: randomBytes(32).toString('hex'),
202
+ enabled: whConfig.enabled !== false,
203
+ events: whConfig.events ?? [],
204
+ description: null,
205
+ });
206
+ }
207
+ }
208
+ }
209
+ export const workosPlugin = {
210
+ name: 'workos',
211
+ register(ctx) {
212
+ organizationRoutes(ctx);
213
+ organizationDomainRoutes(ctx);
214
+ membershipRoutes(ctx);
215
+ userRoutes(ctx);
216
+ emailVerificationRoutes(ctx);
217
+ passwordResetRoutes(ctx);
218
+ magicAuthRoutes(ctx);
219
+ authFactorRoutes(ctx);
220
+ authChallengeRoutes(ctx);
221
+ sessionRoutes(ctx);
222
+ authRoutes(ctx);
223
+ connectionRoutes(ctx);
224
+ ssoRoutes(ctx);
225
+ pipeRoutes(ctx);
226
+ invitationRoutes(ctx);
227
+ configRoutes(ctx);
228
+ userFeatureRoutes(ctx);
229
+ widgetRoutes(ctx);
230
+ authorizationRoleRoutes(ctx);
231
+ authorizationPermissionRoutes(ctx);
232
+ authorizationOrgRoleRoutes(ctx);
233
+ authorizationResourceRoutes(ctx);
234
+ authorizationCheckRoutes(ctx);
235
+ portalRoutes(ctx);
236
+ legacyMfaRoutes(ctx);
237
+ apiKeyRoutes(ctx);
238
+ radarRoutes(ctx);
239
+ connectRoutes(ctx);
240
+ directoryRoutes(ctx);
241
+ auditLogRoutes(ctx);
242
+ featureFlagRoutes(ctx);
243
+ dataIntegrationRoutes(ctx);
244
+ webhookEndpointRoutes(ctx);
245
+ eventRoutes(ctx);
246
+ // Set up event bus with collection hooks (Option A from spec)
247
+ // Store on ctx.store for route-level access (hybrid Option A+B for action events)
248
+ const eventBus = new EventBus(ctx.store);
249
+ ctx.store.setData(STORE_KEYS.eventBus, eventBus);
250
+ const ws = getWorkOSStore(ctx.store);
251
+ ws.users.setHooks({
252
+ onInsert: (u) => eventBus.emit({ event: EVENTS.userCreated, data: formatUser(u) }),
253
+ onUpdate: (u) => eventBus.emit({ event: EVENTS.userUpdated, data: formatUser(u) }),
254
+ onDelete: (u) => eventBus.emit({ event: EVENTS.userDeleted, data: formatUser(u) }),
255
+ });
256
+ ws.organizations.setHooks({
257
+ onInsert: (o) => eventBus.emit({ event: EVENTS.organizationCreated, data: formatOrganization(o, ws) }),
258
+ onUpdate: (o) => eventBus.emit({ event: EVENTS.organizationUpdated, data: formatOrganization(o, ws) }),
259
+ onDelete: (o) => eventBus.emit({ event: EVENTS.organizationDeleted, data: formatOrganization(o, ws) }),
260
+ });
261
+ ws.organizationDomains.setHooks({
262
+ onInsert: (d) => eventBus.emit({ event: EVENTS.organizationDomainCreated, data: formatDomain(d) }),
263
+ onUpdate: (d) => eventBus.emit({
264
+ event: d.state === 'verified' ? EVENTS.organizationDomainVerified : EVENTS.organizationDomainUpdated,
265
+ data: formatDomain(d),
266
+ }),
267
+ onDelete: (d) => eventBus.emit({ event: EVENTS.organizationDomainDeleted, data: formatDomain(d) }),
268
+ });
269
+ ws.organizationMemberships.setHooks({
270
+ onInsert: (m) => eventBus.emit({ event: EVENTS.organizationMembershipCreated, data: formatMembership(m) }),
271
+ onUpdate: (m) => eventBus.emit({ event: EVENTS.organizationMembershipUpdated, data: formatMembership(m) }),
272
+ onDelete: (m) => eventBus.emit({ event: EVENTS.organizationMembershipDeleted, data: formatMembership(m) }),
273
+ });
274
+ ws.connections.setHooks({
275
+ onInsert: (c) => eventBus.emit({ event: EVENTS.connectionCreated, data: formatConnection(c) }),
276
+ onUpdate: (c) => eventBus.emit({ event: EVENTS.connectionUpdated, data: formatConnection(c) }),
277
+ onDelete: (c) => eventBus.emit({ event: EVENTS.connectionDeleted, data: formatConnection(c) }),
278
+ });
279
+ ws.sessions.setHooks({
280
+ onInsert: (s) => eventBus.emit({ event: EVENTS.sessionCreated, data: formatSession(s) }),
281
+ onDelete: (s) => eventBus.emit({ event: EVENTS.sessionRevoked, data: formatSession(s) }),
282
+ });
283
+ ws.invitations.setHooks({
284
+ onInsert: (i) => eventBus.emit({ event: EVENTS.invitationCreated, data: formatInvitation(i) }),
285
+ });
286
+ ws.roles.setHooks({
287
+ onInsert: (r) => eventBus.emit({ event: EVENTS.roleCreated, data: formatRole(r) }),
288
+ onUpdate: (r) => eventBus.emit({ event: EVENTS.roleUpdated, data: formatRole(r) }),
289
+ onDelete: (r) => eventBus.emit({ event: EVENTS.roleDeleted, data: formatRole(r) }),
290
+ });
291
+ ws.permissions.setHooks({
292
+ onInsert: (p) => eventBus.emit({ event: EVENTS.permissionCreated, data: formatPermission(p) }),
293
+ onUpdate: (p) => eventBus.emit({ event: EVENTS.permissionUpdated, data: formatPermission(p) }),
294
+ onDelete: (p) => eventBus.emit({ event: EVENTS.permissionDeleted, data: formatPermission(p) }),
295
+ });
296
+ ws.directories.setHooks({
297
+ onInsert: (d) => eventBus.emit({ event: EVENTS.directoryCreated, data: formatDirectory(d) }),
298
+ onUpdate: (d) => eventBus.emit({ event: EVENTS.directoryUpdated, data: formatDirectory(d) }),
299
+ onDelete: (d) => eventBus.emit({ event: EVENTS.directoryDeleted, data: formatDirectory(d) }),
300
+ });
301
+ ws.directoryUsers.setHooks({
302
+ onInsert: (u) => eventBus.emit({ event: EVENTS.directoryUserCreated, data: formatDirectoryUser(u) }),
303
+ onUpdate: (u) => eventBus.emit({ event: EVENTS.directoryUserUpdated, data: formatDirectoryUser(u) }),
304
+ onDelete: (u) => eventBus.emit({ event: EVENTS.directoryUserDeleted, data: formatDirectoryUser(u) }),
305
+ });
306
+ ws.directoryGroups.setHooks({
307
+ onInsert: (g) => eventBus.emit({ event: EVENTS.directoryGroupCreated, data: formatDirectoryGroup(g) }),
308
+ onUpdate: (g) => eventBus.emit({ event: EVENTS.directoryGroupUpdated, data: formatDirectoryGroup(g) }),
309
+ onDelete: (g) => eventBus.emit({ event: EVENTS.directoryGroupDeleted, data: formatDirectoryGroup(g) }),
310
+ });
311
+ ws.webhookEndpoints.setHooks({
312
+ onInsert: () => eventBus.rebuildIndex(),
313
+ onUpdate: () => eventBus.rebuildIndex(),
314
+ onDelete: () => eventBus.rebuildIndex(),
315
+ });
316
+ },
317
+ seed(_store, _baseUrl) {
318
+ // No default seed data — users provide their own via seedFromConfig
319
+ },
320
+ };
321
+ export default workosPlugin;
322
+ //# sourceMappingURL=index.js.map