workos 0.11.2 → 0.12.0-beta.1

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 (169) hide show
  1. package/README.md +163 -6
  2. package/dist/bin.js +20 -1
  3. package/dist/bin.js.map +1 -1
  4. package/dist/check-coverage.ts +237 -0
  5. package/dist/commands/dev.d.ts +23 -0
  6. package/dist/commands/dev.js +139 -0
  7. package/dist/commands/dev.js.map +1 -0
  8. package/dist/commands/emulate.d.ts +6 -0
  9. package/dist/commands/emulate.js +64 -0
  10. package/dist/commands/emulate.js.map +1 -0
  11. package/dist/emulate/core/id.d.ts +33 -0
  12. package/dist/emulate/core/id.js +58 -0
  13. package/dist/emulate/core/id.js.map +1 -0
  14. package/dist/emulate/core/index.d.ts +8 -0
  15. package/dist/emulate/core/index.js +8 -0
  16. package/dist/emulate/core/index.js.map +1 -0
  17. package/dist/emulate/core/jwt.d.ts +28 -0
  18. package/dist/emulate/core/jwt.js +78 -0
  19. package/dist/emulate/core/jwt.js.map +1 -0
  20. package/dist/emulate/core/middleware/auth.d.ts +18 -0
  21. package/dist/emulate/core/middleware/auth.js +28 -0
  22. package/dist/emulate/core/middleware/auth.js.map +1 -0
  23. package/dist/emulate/core/middleware/error-handler.d.ts +22 -0
  24. package/dist/emulate/core/middleware/error-handler.js +72 -0
  25. package/dist/emulate/core/middleware/error-handler.js.map +1 -0
  26. package/dist/emulate/core/pagination.d.ts +21 -0
  27. package/dist/emulate/core/pagination.js +35 -0
  28. package/dist/emulate/core/pagination.js.map +1 -0
  29. package/dist/emulate/core/plugin.d.ts +15 -0
  30. package/dist/emulate/core/plugin.js +2 -0
  31. package/dist/emulate/core/plugin.js.map +1 -0
  32. package/dist/emulate/core/server.d.ts +17 -0
  33. package/dist/emulate/core/server.js +116 -0
  34. package/dist/emulate/core/server.js.map +1 -0
  35. package/dist/emulate/core/store.d.ts +42 -0
  36. package/dist/emulate/core/store.js +148 -0
  37. package/dist/emulate/core/store.js.map +1 -0
  38. package/dist/emulate/index.d.ts +25 -0
  39. package/dist/emulate/index.js +47 -0
  40. package/dist/emulate/index.js.map +1 -0
  41. package/dist/emulate/workos/entities.d.ts +360 -0
  42. package/dist/emulate/workos/entities.js +2 -0
  43. package/dist/emulate/workos/entities.js.map +1 -0
  44. package/dist/emulate/workos/event-bus.d.ts +12 -0
  45. package/dist/emulate/workos/event-bus.js +45 -0
  46. package/dist/emulate/workos/event-bus.js.map +1 -0
  47. package/dist/emulate/workos/helpers.d.ts +63 -0
  48. package/dist/emulate/workos/helpers.js +518 -0
  49. package/dist/emulate/workos/helpers.js.map +1 -0
  50. package/dist/emulate/workos/index.d.ts +91 -0
  51. package/dist/emulate/workos/index.js +319 -0
  52. package/dist/emulate/workos/index.js.map +1 -0
  53. package/dist/emulate/workos/routes/api-keys.d.ts +2 -0
  54. package/dist/emulate/workos/routes/api-keys.js +35 -0
  55. package/dist/emulate/workos/routes/api-keys.js.map +1 -0
  56. package/dist/emulate/workos/routes/audit-logs.d.ts +2 -0
  57. package/dist/emulate/workos/routes/audit-logs.js +107 -0
  58. package/dist/emulate/workos/routes/audit-logs.js.map +1 -0
  59. package/dist/emulate/workos/routes/auth-challenges.d.ts +2 -0
  60. package/dist/emulate/workos/routes/auth-challenges.js +51 -0
  61. package/dist/emulate/workos/routes/auth-challenges.js.map +1 -0
  62. package/dist/emulate/workos/routes/auth-factors.d.ts +2 -0
  63. package/dist/emulate/workos/routes/auth-factors.js +51 -0
  64. package/dist/emulate/workos/routes/auth-factors.js.map +1 -0
  65. package/dist/emulate/workos/routes/auth.d.ts +2 -0
  66. package/dist/emulate/workos/routes/auth.js +349 -0
  67. package/dist/emulate/workos/routes/auth.js.map +1 -0
  68. package/dist/emulate/workos/routes/authorization-checks.d.ts +10 -0
  69. package/dist/emulate/workos/routes/authorization-checks.js +135 -0
  70. package/dist/emulate/workos/routes/authorization-checks.js.map +1 -0
  71. package/dist/emulate/workos/routes/authorization-org-roles.d.ts +2 -0
  72. package/dist/emulate/workos/routes/authorization-org-roles.js +206 -0
  73. package/dist/emulate/workos/routes/authorization-org-roles.js.map +1 -0
  74. package/dist/emulate/workos/routes/authorization-permissions.d.ts +2 -0
  75. package/dist/emulate/workos/routes/authorization-permissions.js +78 -0
  76. package/dist/emulate/workos/routes/authorization-permissions.js.map +1 -0
  77. package/dist/emulate/workos/routes/authorization-resources.d.ts +2 -0
  78. package/dist/emulate/workos/routes/authorization-resources.js +128 -0
  79. package/dist/emulate/workos/routes/authorization-resources.js.map +1 -0
  80. package/dist/emulate/workos/routes/authorization-roles.d.ts +2 -0
  81. package/dist/emulate/workos/routes/authorization-roles.js +136 -0
  82. package/dist/emulate/workos/routes/authorization-roles.js.map +1 -0
  83. package/dist/emulate/workos/routes/config.d.ts +2 -0
  84. package/dist/emulate/workos/routes/config.js +56 -0
  85. package/dist/emulate/workos/routes/config.js.map +1 -0
  86. package/dist/emulate/workos/routes/connect.d.ts +2 -0
  87. package/dist/emulate/workos/routes/connect.js +69 -0
  88. package/dist/emulate/workos/routes/connect.js.map +1 -0
  89. package/dist/emulate/workos/routes/connections.d.ts +2 -0
  90. package/dist/emulate/workos/routes/connections.js +77 -0
  91. package/dist/emulate/workos/routes/connections.js.map +1 -0
  92. package/dist/emulate/workos/routes/data-integrations.d.ts +2 -0
  93. package/dist/emulate/workos/routes/data-integrations.js +55 -0
  94. package/dist/emulate/workos/routes/data-integrations.js.map +1 -0
  95. package/dist/emulate/workos/routes/directories.d.ts +2 -0
  96. package/dist/emulate/workos/routes/directories.js +106 -0
  97. package/dist/emulate/workos/routes/directories.js.map +1 -0
  98. package/dist/emulate/workos/routes/email-verification.d.ts +2 -0
  99. package/dist/emulate/workos/routes/email-verification.js +49 -0
  100. package/dist/emulate/workos/routes/email-verification.js.map +1 -0
  101. package/dist/emulate/workos/routes/events.d.ts +2 -0
  102. package/dist/emulate/workos/routes/events.js +21 -0
  103. package/dist/emulate/workos/routes/events.js.map +1 -0
  104. package/dist/emulate/workos/routes/feature-flags.d.ts +2 -0
  105. package/dist/emulate/workos/routes/feature-flags.js +131 -0
  106. package/dist/emulate/workos/routes/feature-flags.js.map +1 -0
  107. package/dist/emulate/workos/routes/invitations.d.ts +2 -0
  108. package/dist/emulate/workos/routes/invitations.js +125 -0
  109. package/dist/emulate/workos/routes/invitations.js.map +1 -0
  110. package/dist/emulate/workos/routes/legacy-mfa.d.ts +2 -0
  111. package/dist/emulate/workos/routes/legacy-mfa.js +75 -0
  112. package/dist/emulate/workos/routes/legacy-mfa.js.map +1 -0
  113. package/dist/emulate/workos/routes/magic-auth.d.ts +2 -0
  114. package/dist/emulate/workos/routes/magic-auth.js +32 -0
  115. package/dist/emulate/workos/routes/magic-auth.js.map +1 -0
  116. package/dist/emulate/workos/routes/memberships.d.ts +2 -0
  117. package/dist/emulate/workos/routes/memberships.js +118 -0
  118. package/dist/emulate/workos/routes/memberships.js.map +1 -0
  119. package/dist/emulate/workos/routes/organization-domains.d.ts +2 -0
  120. package/dist/emulate/workos/routes/organization-domains.js +58 -0
  121. package/dist/emulate/workos/routes/organization-domains.js.map +1 -0
  122. package/dist/emulate/workos/routes/organizations.d.ts +2 -0
  123. package/dist/emulate/workos/routes/organizations.js +133 -0
  124. package/dist/emulate/workos/routes/organizations.js.map +1 -0
  125. package/dist/emulate/workos/routes/password-reset.d.ts +2 -0
  126. package/dist/emulate/workos/routes/password-reset.js +61 -0
  127. package/dist/emulate/workos/routes/password-reset.js.map +1 -0
  128. package/dist/emulate/workos/routes/pipes.d.ts +2 -0
  129. package/dist/emulate/workos/routes/pipes.js +86 -0
  130. package/dist/emulate/workos/routes/pipes.js.map +1 -0
  131. package/dist/emulate/workos/routes/portal.d.ts +2 -0
  132. package/dist/emulate/workos/routes/portal.js +18 -0
  133. package/dist/emulate/workos/routes/portal.js.map +1 -0
  134. package/dist/emulate/workos/routes/radar.d.ts +2 -0
  135. package/dist/emulate/workos/routes/radar.js +45 -0
  136. package/dist/emulate/workos/routes/radar.js.map +1 -0
  137. package/dist/emulate/workos/routes/sessions.d.ts +2 -0
  138. package/dist/emulate/workos/routes/sessions.js +51 -0
  139. package/dist/emulate/workos/routes/sessions.js.map +1 -0
  140. package/dist/emulate/workos/routes/sso.d.ts +2 -0
  141. package/dist/emulate/workos/routes/sso.js +160 -0
  142. package/dist/emulate/workos/routes/sso.js.map +1 -0
  143. package/dist/emulate/workos/routes/user-features.d.ts +2 -0
  144. package/dist/emulate/workos/routes/user-features.js +50 -0
  145. package/dist/emulate/workos/routes/user-features.js.map +1 -0
  146. package/dist/emulate/workos/routes/users.d.ts +2 -0
  147. package/dist/emulate/workos/routes/users.js +133 -0
  148. package/dist/emulate/workos/routes/users.js.map +1 -0
  149. package/dist/emulate/workos/routes/webhook-endpoints.d.ts +2 -0
  150. package/dist/emulate/workos/routes/webhook-endpoints.js +70 -0
  151. package/dist/emulate/workos/routes/webhook-endpoints.js.map +1 -0
  152. package/dist/emulate/workos/routes/widgets.d.ts +2 -0
  153. package/dist/emulate/workos/routes/widgets.js +27 -0
  154. package/dist/emulate/workos/routes/widgets.js.map +1 -0
  155. package/dist/emulate/workos/store.d.ts +48 -0
  156. package/dist/emulate/workos/store.js +93 -0
  157. package/dist/emulate/workos/store.js.map +1 -0
  158. package/dist/emulate/workos/webhook-signer.d.ts +1 -0
  159. package/dist/emulate/workos/webhook-signer.js +8 -0
  160. package/dist/emulate/workos/webhook-signer.js.map +1 -0
  161. package/dist/gen-routes-lib.spec.ts +659 -0
  162. package/dist/gen-routes-lib.ts +647 -0
  163. package/dist/gen-routes.ts +96 -0
  164. package/dist/lib/dev-command.d.ts +26 -0
  165. package/dist/lib/dev-command.js +122 -0
  166. package/dist/lib/dev-command.js.map +1 -0
  167. package/dist/utils/help-json.js +23 -0
  168. package/dist/utils/help-json.js.map +1 -1
  169. package/package.json +20 -7
@@ -0,0 +1,75 @@
1
+ import { notFound, parseJsonBody, WorkOSApiError } from '../../core/index.js';
2
+ import { getWorkOSStore } from '../store.js';
3
+ import { formatAuthFactor, formatAuthChallenge, expiresIn, isExpired, generateCode } from '../helpers.js';
4
+ import { randomBytes } from 'node:crypto';
5
+ export function legacyMfaRoutes(ctx) {
6
+ const { app, store } = ctx;
7
+ const ws = getWorkOSStore(store);
8
+ // Enroll factor (legacy path — not tied to user management users)
9
+ app.post('/auth/factors/enroll', async (c) => {
10
+ const body = await parseJsonBody(c);
11
+ const type = body.type ?? 'totp';
12
+ const issuer = body.totp_issuer ?? 'WorkOS Emulator';
13
+ const totpUser = body.totp_user ?? 'legacy@emulator';
14
+ const secret = randomBytes(20).toString('hex').slice(0, 32).toUpperCase();
15
+ const uri = `otpauth://totp/${encodeURIComponent(issuer)}:${encodeURIComponent(totpUser)}?secret=${secret}&issuer=${encodeURIComponent(issuer)}`;
16
+ const factor = ws.authFactors.insert({
17
+ object: 'authentication_factor',
18
+ user_id: 'legacy',
19
+ type: type,
20
+ totp: { issuer, user: totpUser, uri },
21
+ });
22
+ return c.json(formatAuthFactor(factor), 201);
23
+ });
24
+ // Get factor
25
+ app.get('/auth/factors/:id', (c) => {
26
+ const factor = ws.authFactors.get(c.req.param('id'));
27
+ if (!factor)
28
+ throw notFound('AuthenticationFactor');
29
+ return c.json(formatAuthFactor(factor));
30
+ });
31
+ // Delete factor
32
+ app.delete('/auth/factors/:id', (c) => {
33
+ const factor = ws.authFactors.get(c.req.param('id'));
34
+ if (!factor)
35
+ throw notFound('AuthenticationFactor');
36
+ ws.authFactors.delete(factor.id);
37
+ return c.body(null, 204);
38
+ });
39
+ // Create challenge
40
+ app.post('/auth/factors/:id/challenge', async (c) => {
41
+ const factor = ws.authFactors.get(c.req.param('id'));
42
+ if (!factor)
43
+ throw notFound('AuthenticationFactor');
44
+ const code = generateCode();
45
+ const challenge = ws.authChallenges.insert({
46
+ object: 'authentication_challenge',
47
+ user_id: factor.user_id,
48
+ factor_id: factor.id,
49
+ expires_at: expiresIn(10),
50
+ code,
51
+ });
52
+ return c.json(formatAuthChallenge(challenge), 201);
53
+ });
54
+ // Verify challenge
55
+ app.post('/auth/challenges/:id/verify', async (c) => {
56
+ const challenge = ws.authChallenges.get(c.req.param('id'));
57
+ if (!challenge)
58
+ throw notFound('AuthenticationChallenge');
59
+ if (isExpired(challenge.expires_at)) {
60
+ ws.authChallenges.delete(challenge.id);
61
+ throw new WorkOSApiError(400, 'Challenge has expired', 'expired_challenge');
62
+ }
63
+ const body = await parseJsonBody(c);
64
+ const code = body.code;
65
+ if (!code) {
66
+ throw new WorkOSApiError(400, 'code is required', 'invalid_request');
67
+ }
68
+ if (challenge.code && code !== challenge.code) {
69
+ throw new WorkOSApiError(400, 'Invalid one-time code', 'invalid_one_time_code');
70
+ }
71
+ ws.authChallenges.delete(challenge.id);
72
+ return c.json({ challenge: formatAuthChallenge(challenge), valid: true });
73
+ });
74
+ }
75
+ //# sourceMappingURL=legacy-mfa.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"legacy-mfa.js","sourceRoot":"","sources":["../../../../src/emulate/workos/routes/legacy-mfa.ts"],"names":[],"mappings":"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","sourcesContent":["import { type RouteContext, notFound, parseJsonBody, WorkOSApiError } from '../../core/index.js';\nimport { getWorkOSStore } from '../store.js';\nimport { formatAuthFactor, formatAuthChallenge, expiresIn, isExpired, generateCode } from '../helpers.js';\nimport { randomBytes } from 'node:crypto';\n\nexport function legacyMfaRoutes(ctx: RouteContext): void {\n const { app, store } = ctx;\n const ws = getWorkOSStore(store);\n\n // Enroll factor (legacy path — not tied to user management users)\n app.post('/auth/factors/enroll', async (c) => {\n const body = await parseJsonBody(c);\n const type = (body.type as string) ?? 'totp';\n const issuer = (body.totp_issuer as string) ?? 'WorkOS Emulator';\n const totpUser = (body.totp_user as string) ?? 'legacy@emulator';\n const secret = randomBytes(20).toString('hex').slice(0, 32).toUpperCase();\n const uri = `otpauth://totp/${encodeURIComponent(issuer)}:${encodeURIComponent(totpUser)}?secret=${secret}&issuer=${encodeURIComponent(issuer)}`;\n\n const factor = ws.authFactors.insert({\n object: 'authentication_factor',\n user_id: 'legacy',\n type: type as 'totp',\n totp: { issuer, user: totpUser, uri },\n });\n\n return c.json(formatAuthFactor(factor), 201);\n });\n\n // Get factor\n app.get('/auth/factors/:id', (c) => {\n const factor = ws.authFactors.get(c.req.param('id'));\n if (!factor) throw notFound('AuthenticationFactor');\n return c.json(formatAuthFactor(factor));\n });\n\n // Delete factor\n app.delete('/auth/factors/:id', (c) => {\n const factor = ws.authFactors.get(c.req.param('id'));\n if (!factor) throw notFound('AuthenticationFactor');\n ws.authFactors.delete(factor.id);\n return c.body(null, 204);\n });\n\n // Create challenge\n app.post('/auth/factors/:id/challenge', async (c) => {\n const factor = ws.authFactors.get(c.req.param('id'));\n if (!factor) throw notFound('AuthenticationFactor');\n\n const code = generateCode();\n const challenge = ws.authChallenges.insert({\n object: 'authentication_challenge',\n user_id: factor.user_id,\n factor_id: factor.id,\n expires_at: expiresIn(10),\n code,\n });\n\n return c.json(formatAuthChallenge(challenge), 201);\n });\n\n // Verify challenge\n app.post('/auth/challenges/:id/verify', async (c) => {\n const challenge = ws.authChallenges.get(c.req.param('id'));\n if (!challenge) throw notFound('AuthenticationChallenge');\n\n if (isExpired(challenge.expires_at)) {\n ws.authChallenges.delete(challenge.id);\n throw new WorkOSApiError(400, 'Challenge has expired', 'expired_challenge');\n }\n\n const body = await parseJsonBody(c);\n const code = body.code as string;\n if (!code) {\n throw new WorkOSApiError(400, 'code is required', 'invalid_request');\n }\n if (challenge.code && code !== challenge.code) {\n throw new WorkOSApiError(400, 'Invalid one-time code', 'invalid_one_time_code');\n }\n\n ws.authChallenges.delete(challenge.id);\n return c.json({ challenge: formatAuthChallenge(challenge), valid: true });\n });\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import { type RouteContext } from '../../core/index.js';
2
+ export declare function magicAuthRoutes(ctx: RouteContext): void;
@@ -0,0 +1,32 @@
1
+ import { notFound, parseJsonBody, WorkOSApiError } from '../../core/index.js';
2
+ import { getWorkOSStore } from '../store.js';
3
+ import { formatMagicAuth, generateCode, expiresIn } from '../helpers.js';
4
+ export function magicAuthRoutes(ctx) {
5
+ const { app, store } = ctx;
6
+ const ws = getWorkOSStore(store);
7
+ app.get('/user_management/magic_auth/:id', (c) => {
8
+ const ma = ws.magicAuths.get(c.req.param('id'));
9
+ if (!ma)
10
+ throw notFound('Magic Auth');
11
+ return c.json(formatMagicAuth(ma));
12
+ });
13
+ app.post('/user_management/magic_auth', async (c) => {
14
+ const body = await parseJsonBody(c);
15
+ const email = body.email;
16
+ if (!email) {
17
+ throw new WorkOSApiError(400, 'email is required', 'invalid_request');
18
+ }
19
+ const user = ws.users.findOneBy('email', email);
20
+ if (!user)
21
+ throw notFound('User');
22
+ const ma = ws.magicAuths.insert({
23
+ object: 'magic_auth',
24
+ user_id: user.id,
25
+ email: user.email,
26
+ code: generateCode(),
27
+ expires_at: expiresIn(10),
28
+ });
29
+ return c.json(formatMagicAuth(ma), 201);
30
+ });
31
+ }
32
+ //# sourceMappingURL=magic-auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"magic-auth.js","sourceRoot":"","sources":["../../../../src/emulate/workos/routes/magic-auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,QAAQ,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACjG,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAEzE,MAAM,UAAU,eAAe,CAAC,GAAiB;IAC/C,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC;IAC3B,MAAM,EAAE,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IAEjC,GAAG,CAAC,GAAG,CAAC,iCAAiC,EAAE,CAAC,CAAC,EAAE,EAAE;QAC/C,MAAM,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAChD,IAAI,CAAC,EAAE;YAAE,MAAM,QAAQ,CAAC,YAAY,CAAC,CAAC;QACtC,OAAO,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,6BAA6B,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAClD,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,CAAC,CAAC,CAAC;QACpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAA2B,CAAC;QAC/C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,cAAc,CAAC,GAAG,EAAE,mBAAmB,EAAE,iBAAiB,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAChD,IAAI,CAAC,IAAI;YAAE,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC;QAElC,MAAM,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC;YAC9B,MAAM,EAAE,YAAY;YACpB,OAAO,EAAE,IAAI,CAAC,EAAE;YAChB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,IAAI,EAAE,YAAY,EAAE;YACpB,UAAU,EAAE,SAAS,CAAC,EAAE,CAAC;SAC1B,CAAC,CAAC;QAEH,OAAO,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { type RouteContext, notFound, parseJsonBody, WorkOSApiError } from '../../core/index.js';\nimport { getWorkOSStore } from '../store.js';\nimport { formatMagicAuth, generateCode, expiresIn } from '../helpers.js';\n\nexport function magicAuthRoutes(ctx: RouteContext): void {\n const { app, store } = ctx;\n const ws = getWorkOSStore(store);\n\n app.get('/user_management/magic_auth/:id', (c) => {\n const ma = ws.magicAuths.get(c.req.param('id'));\n if (!ma) throw notFound('Magic Auth');\n return c.json(formatMagicAuth(ma));\n });\n\n app.post('/user_management/magic_auth', async (c) => {\n const body = await parseJsonBody(c);\n const email = body.email as string | undefined;\n if (!email) {\n throw new WorkOSApiError(400, 'email is required', 'invalid_request');\n }\n\n const user = ws.users.findOneBy('email', email);\n if (!user) throw notFound('User');\n\n const ma = ws.magicAuths.insert({\n object: 'magic_auth',\n user_id: user.id,\n email: user.email,\n code: generateCode(),\n expires_at: expiresIn(10),\n });\n\n return c.json(formatMagicAuth(ma), 201);\n });\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import { type RouteContext } from '../../core/index.js';
2
+ export declare function membershipRoutes(ctx: RouteContext): void;
@@ -0,0 +1,118 @@
1
+ import { notFound, validationError, parseJsonBody, WorkOSApiError } from '../../core/index.js';
2
+ import { getWorkOSStore } from '../store.js';
3
+ import { formatMembership, parseListParams } from '../helpers.js';
4
+ export function membershipRoutes(ctx) {
5
+ const { app, store } = ctx;
6
+ const ws = getWorkOSStore(store);
7
+ app.post('/user_management/organization_memberships', async (c) => {
8
+ const body = await parseJsonBody(c);
9
+ const organizationId = body.organization_id;
10
+ const userId = body.user_id;
11
+ if (!organizationId) {
12
+ throw validationError('organization_id is required', [{ field: 'organization_id', code: 'required' }]);
13
+ }
14
+ if (!userId) {
15
+ throw validationError('user_id is required', [{ field: 'user_id', code: 'required' }]);
16
+ }
17
+ const org = ws.organizations.get(organizationId);
18
+ if (!org)
19
+ throw notFound('Organization');
20
+ const existing = ws.organizationMemberships
21
+ .findBy('organization_id', organizationId)
22
+ .find((m) => m.user_id === userId && m.status !== 'inactive');
23
+ if (existing) {
24
+ throw new WorkOSApiError(409, 'Membership already exists', 'conflict');
25
+ }
26
+ const roleSlug = body.role_slug ?? 'member';
27
+ const membership = ws.organizationMemberships.insert({
28
+ object: 'organization_membership',
29
+ organization_id: organizationId,
30
+ user_id: userId,
31
+ role: { slug: roleSlug },
32
+ status: 'active',
33
+ external_id: body.external_id ?? null,
34
+ metadata: body.metadata ?? {},
35
+ });
36
+ return c.json(formatMembership(membership), 201);
37
+ });
38
+ app.get('/user_management/organization_memberships', (c) => {
39
+ const url = new URL(c.req.url);
40
+ const params = parseListParams(url);
41
+ const orgFilter = url.searchParams.get('organization_id') ?? undefined;
42
+ const userFilter = url.searchParams.get('user_id') ?? undefined;
43
+ const statusesParam = url.searchParams.getAll('statuses[]');
44
+ const result = ws.organizationMemberships.list({
45
+ ...params,
46
+ filter: (m) => {
47
+ if (orgFilter && m.organization_id !== orgFilter)
48
+ return false;
49
+ if (userFilter && m.user_id !== userFilter)
50
+ return false;
51
+ if (statusesParam.length > 0 && !statusesParam.includes(m.status))
52
+ return false;
53
+ return true;
54
+ },
55
+ });
56
+ return c.json({
57
+ object: 'list',
58
+ data: result.data.map(formatMembership),
59
+ list_metadata: result.list_metadata,
60
+ });
61
+ });
62
+ app.get('/user_management/organization_memberships/:id', (c) => {
63
+ const m = ws.organizationMemberships.get(c.req.param('id'));
64
+ if (!m)
65
+ throw notFound('Organization Membership');
66
+ return c.json(formatMembership(m));
67
+ });
68
+ app.put('/user_management/organization_memberships/:id', async (c) => {
69
+ const m = ws.organizationMemberships.get(c.req.param('id'));
70
+ if (!m)
71
+ throw notFound('Organization Membership');
72
+ const body = await parseJsonBody(c);
73
+ const updates = {};
74
+ if ('role_slug' in body) {
75
+ updates.role = { slug: body.role_slug };
76
+ }
77
+ if ('external_id' in body) {
78
+ updates.external_id = body.external_id ?? null;
79
+ }
80
+ if ('metadata' in body) {
81
+ updates.metadata = body.metadata ?? {};
82
+ }
83
+ const updated = ws.organizationMemberships.update(m.id, updates);
84
+ return c.json(formatMembership(updated));
85
+ });
86
+ app.delete('/user_management/organization_memberships/:id', (c) => {
87
+ const m = ws.organizationMemberships.get(c.req.param('id'));
88
+ if (!m)
89
+ throw notFound('Organization Membership');
90
+ ws.organizationMemberships.delete(m.id);
91
+ return c.body(null, 204);
92
+ });
93
+ app.put('/user_management/organization_memberships/:id/deactivate', (c) => {
94
+ const m = ws.organizationMemberships.get(c.req.param('id'));
95
+ if (!m)
96
+ throw notFound('Organization Membership');
97
+ if (m.status === 'inactive') {
98
+ throw validationError('Membership is already inactive');
99
+ }
100
+ const updated = ws.organizationMemberships.update(m.id, {
101
+ status: 'inactive',
102
+ });
103
+ return c.json(formatMembership(updated));
104
+ });
105
+ app.put('/user_management/organization_memberships/:id/reactivate', (c) => {
106
+ const m = ws.organizationMemberships.get(c.req.param('id'));
107
+ if (!m)
108
+ throw notFound('Organization Membership');
109
+ if (m.status === 'active') {
110
+ throw validationError('Membership is already active');
111
+ }
112
+ const updated = ws.organizationMemberships.update(m.id, {
113
+ status: 'active',
114
+ });
115
+ return c.json(formatMembership(updated));
116
+ });
117
+ }
118
+ //# sourceMappingURL=memberships.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memberships.js","sourceRoot":"","sources":["../../../../src/emulate/workos/routes/memberships.ts"],"names":[],"mappings":"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","sourcesContent":["import { type RouteContext, notFound, validationError, parseJsonBody, WorkOSApiError } from '../../core/index.js';\nimport { getWorkOSStore } from '../store.js';\nimport { formatMembership, parseListParams } from '../helpers.js';\n\nexport function membershipRoutes(ctx: RouteContext): void {\n const { app, store } = ctx;\n const ws = getWorkOSStore(store);\n\n app.post('/user_management/organization_memberships', async (c) => {\n const body = await parseJsonBody(c);\n const organizationId = body.organization_id as string | undefined;\n const userId = body.user_id as string | undefined;\n\n if (!organizationId) {\n throw validationError('organization_id is required', [{ field: 'organization_id', code: 'required' }]);\n }\n if (!userId) {\n throw validationError('user_id is required', [{ field: 'user_id', code: 'required' }]);\n }\n\n const org = ws.organizations.get(organizationId);\n if (!org) throw notFound('Organization');\n\n const existing = ws.organizationMemberships\n .findBy('organization_id', organizationId)\n .find((m) => m.user_id === userId && m.status !== 'inactive');\n if (existing) {\n throw new WorkOSApiError(409, 'Membership already exists', 'conflict');\n }\n\n const roleSlug = (body.role_slug as string) ?? 'member';\n\n const membership = ws.organizationMemberships.insert({\n object: 'organization_membership',\n organization_id: organizationId,\n user_id: userId,\n role: { slug: roleSlug },\n status: 'active',\n external_id: (body.external_id as string) ?? null,\n metadata: (body.metadata as Record<string, string>) ?? {},\n });\n\n return c.json(formatMembership(membership), 201);\n });\n\n app.get('/user_management/organization_memberships', (c) => {\n const url = new URL(c.req.url);\n const params = parseListParams(url);\n const orgFilter = url.searchParams.get('organization_id') ?? undefined;\n const userFilter = url.searchParams.get('user_id') ?? undefined;\n const statusesParam = url.searchParams.getAll('statuses[]');\n\n const result = ws.organizationMemberships.list({\n ...params,\n filter: (m) => {\n if (orgFilter && m.organization_id !== orgFilter) return false;\n if (userFilter && m.user_id !== userFilter) return false;\n if (statusesParam.length > 0 && !statusesParam.includes(m.status)) return false;\n return true;\n },\n });\n\n return c.json({\n object: 'list',\n data: result.data.map(formatMembership),\n list_metadata: result.list_metadata,\n });\n });\n\n app.get('/user_management/organization_memberships/:id', (c) => {\n const m = ws.organizationMemberships.get(c.req.param('id'));\n if (!m) throw notFound('Organization Membership');\n return c.json(formatMembership(m));\n });\n\n app.put('/user_management/organization_memberships/:id', async (c) => {\n const m = ws.organizationMemberships.get(c.req.param('id'));\n if (!m) throw notFound('Organization Membership');\n\n const body = await parseJsonBody(c);\n const updates: Record<string, unknown> = {};\n\n if ('role_slug' in body) {\n updates.role = { slug: body.role_slug as string };\n }\n if ('external_id' in body) {\n updates.external_id = body.external_id ?? null;\n }\n if ('metadata' in body) {\n updates.metadata = body.metadata ?? {};\n }\n\n const updated = ws.organizationMemberships.update(m.id, updates);\n return c.json(formatMembership(updated!));\n });\n\n app.delete('/user_management/organization_memberships/:id', (c) => {\n const m = ws.organizationMemberships.get(c.req.param('id'));\n if (!m) throw notFound('Organization Membership');\n ws.organizationMemberships.delete(m.id);\n return c.body(null, 204);\n });\n\n app.put('/user_management/organization_memberships/:id/deactivate', (c) => {\n const m = ws.organizationMemberships.get(c.req.param('id'));\n if (!m) throw notFound('Organization Membership');\n if (m.status === 'inactive') {\n throw validationError('Membership is already inactive');\n }\n const updated = ws.organizationMemberships.update(m.id, {\n status: 'inactive',\n });\n return c.json(formatMembership(updated!));\n });\n\n app.put('/user_management/organization_memberships/:id/reactivate', (c) => {\n const m = ws.organizationMemberships.get(c.req.param('id'));\n if (!m) throw notFound('Organization Membership');\n if (m.status === 'active') {\n throw validationError('Membership is already active');\n }\n const updated = ws.organizationMemberships.update(m.id, {\n status: 'active',\n });\n return c.json(formatMembership(updated!));\n });\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import { type RouteContext } from '../../core/index.js';
2
+ export declare function organizationDomainRoutes(ctx: RouteContext): void;
@@ -0,0 +1,58 @@
1
+ import { notFound, validationError, parseJsonBody, WorkOSApiError } from '../../core/index.js';
2
+ import { getWorkOSStore } from '../store.js';
3
+ import { formatDomain, generateVerificationToken } from '../helpers.js';
4
+ export function organizationDomainRoutes(ctx) {
5
+ const { app, store } = ctx;
6
+ const ws = getWorkOSStore(store);
7
+ app.post('/organization_domains', async (c) => {
8
+ const body = await parseJsonBody(c);
9
+ const organizationId = body.organization_id;
10
+ const domain = body.domain;
11
+ if (!organizationId) {
12
+ throw validationError('organization_id is required', [{ field: 'organization_id', code: 'required' }]);
13
+ }
14
+ if (!domain) {
15
+ throw validationError('domain is required', [{ field: 'domain', code: 'required' }]);
16
+ }
17
+ const org = ws.organizations.get(organizationId);
18
+ if (!org)
19
+ throw notFound('Organization');
20
+ const existing = ws.organizationDomains.findBy('organization_id', organizationId).find((d) => d.domain === domain);
21
+ if (existing) {
22
+ throw new WorkOSApiError(409, 'Domain already exists for this organization', 'conflict');
23
+ }
24
+ const domainEntity = ws.organizationDomains.insert({
25
+ object: 'organization_domain',
26
+ organization_id: organizationId,
27
+ domain,
28
+ state: 'pending',
29
+ verification_strategy: body.verification_strategy ?? 'manual',
30
+ verification_token: generateVerificationToken(),
31
+ verification_prefix: 'workos-verify',
32
+ });
33
+ return c.json(formatDomain(domainEntity), 201);
34
+ });
35
+ app.get('/organization_domains/:id', (c) => {
36
+ const domain = ws.organizationDomains.get(c.req.param('id'));
37
+ if (!domain)
38
+ throw notFound('Organization Domain');
39
+ return c.json(formatDomain(domain));
40
+ });
41
+ app.delete('/organization_domains/:id', (c) => {
42
+ const domain = ws.organizationDomains.get(c.req.param('id'));
43
+ if (!domain)
44
+ throw notFound('Organization Domain');
45
+ ws.organizationDomains.delete(domain.id);
46
+ return c.body(null, 204);
47
+ });
48
+ app.post('/organization_domains/:id/verify', (c) => {
49
+ const domain = ws.organizationDomains.get(c.req.param('id'));
50
+ if (!domain)
51
+ throw notFound('Organization Domain');
52
+ const updated = ws.organizationDomains.update(domain.id, {
53
+ state: 'verified',
54
+ });
55
+ return c.json(formatDomain(updated));
56
+ });
57
+ }
58
+ //# sourceMappingURL=organization-domains.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"organization-domains.js","sourceRoot":"","sources":["../../../../src/emulate/workos/routes/organization-domains.ts"],"names":[],"mappings":"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","sourcesContent":["import { type RouteContext, notFound, validationError, parseJsonBody, WorkOSApiError } from '../../core/index.js';\nimport { getWorkOSStore } from '../store.js';\nimport { formatDomain, generateVerificationToken } from '../helpers.js';\n\nexport function organizationDomainRoutes(ctx: RouteContext): void {\n const { app, store } = ctx;\n const ws = getWorkOSStore(store);\n\n app.post('/organization_domains', async (c) => {\n const body = await parseJsonBody(c);\n const organizationId = body.organization_id as string | undefined;\n const domain = body.domain as string | undefined;\n\n if (!organizationId) {\n throw validationError('organization_id is required', [{ field: 'organization_id', code: 'required' }]);\n }\n if (!domain) {\n throw validationError('domain is required', [{ field: 'domain', code: 'required' }]);\n }\n\n const org = ws.organizations.get(organizationId);\n if (!org) throw notFound('Organization');\n\n const existing = ws.organizationDomains.findBy('organization_id', organizationId).find((d) => d.domain === domain);\n if (existing) {\n throw new WorkOSApiError(409, 'Domain already exists for this organization', 'conflict');\n }\n\n const domainEntity = ws.organizationDomains.insert({\n object: 'organization_domain',\n organization_id: organizationId,\n domain,\n state: 'pending',\n verification_strategy: (body.verification_strategy as 'manual' | 'dns') ?? 'manual',\n verification_token: generateVerificationToken(),\n verification_prefix: 'workos-verify',\n });\n\n return c.json(formatDomain(domainEntity), 201);\n });\n\n app.get('/organization_domains/:id', (c) => {\n const domain = ws.organizationDomains.get(c.req.param('id'));\n if (!domain) throw notFound('Organization Domain');\n return c.json(formatDomain(domain));\n });\n\n app.delete('/organization_domains/:id', (c) => {\n const domain = ws.organizationDomains.get(c.req.param('id'));\n if (!domain) throw notFound('Organization Domain');\n ws.organizationDomains.delete(domain.id);\n return c.body(null, 204);\n });\n\n app.post('/organization_domains/:id/verify', (c) => {\n const domain = ws.organizationDomains.get(c.req.param('id'));\n if (!domain) throw notFound('Organization Domain');\n\n const updated = ws.organizationDomains.update(domain.id, {\n state: 'verified',\n });\n return c.json(formatDomain(updated!));\n });\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import { type RouteContext } from '../../core/index.js';
2
+ export declare function organizationRoutes(ctx: RouteContext): void;
@@ -0,0 +1,133 @@
1
+ import { notFound, validationError, parseJsonBody } from '../../core/index.js';
2
+ import { getWorkOSStore } from '../store.js';
3
+ import { formatOrganization, generateVerificationToken, parseListParams } from '../helpers.js';
4
+ export function organizationRoutes(ctx) {
5
+ const { app, store } = ctx;
6
+ const ws = getWorkOSStore(store);
7
+ app.post('/organizations', async (c) => {
8
+ const body = await parseJsonBody(c);
9
+ const name = body.name;
10
+ if (!name || typeof name !== 'string' || name.trim().length === 0) {
11
+ throw validationError('Name is required', [{ field: 'name', code: 'required' }]);
12
+ }
13
+ const org = ws.organizations.insert({
14
+ object: 'organization',
15
+ name: name.trim(),
16
+ external_id: body.external_id ?? null,
17
+ metadata: body.metadata ?? {},
18
+ stripe_customer_id: null,
19
+ });
20
+ const domainData = body.domain_data;
21
+ if (domainData && Array.isArray(domainData)) {
22
+ for (const dd of domainData) {
23
+ ws.organizationDomains.insert({
24
+ object: 'organization_domain',
25
+ organization_id: org.id,
26
+ domain: dd.domain,
27
+ state: dd.state === 'verified' ? 'verified' : 'pending',
28
+ verification_strategy: 'manual',
29
+ verification_token: generateVerificationToken(),
30
+ verification_prefix: 'workos-verify',
31
+ });
32
+ }
33
+ }
34
+ return c.json(formatOrganization(org, ws), 201);
35
+ });
36
+ app.get('/organizations', (c) => {
37
+ const url = new URL(c.req.url);
38
+ const params = parseListParams(url);
39
+ const nameFilter = url.searchParams.get('name') ?? undefined;
40
+ const domainsFilter = url.searchParams.get('domains') ?? undefined;
41
+ const result = ws.organizations.list({
42
+ ...params,
43
+ filter: (org) => {
44
+ if (nameFilter && !org.name.toLowerCase().includes(nameFilter.toLowerCase())) {
45
+ return false;
46
+ }
47
+ if (domainsFilter) {
48
+ const orgDomains = ws.organizationDomains.findBy('organization_id', org.id);
49
+ if (!orgDomains.some((d) => d.domain === domainsFilter)) {
50
+ return false;
51
+ }
52
+ }
53
+ return true;
54
+ },
55
+ });
56
+ return c.json({
57
+ object: 'list',
58
+ data: result.data.map((org) => formatOrganization(org, ws)),
59
+ list_metadata: result.list_metadata,
60
+ });
61
+ });
62
+ app.get('/organizations/:id', (c) => {
63
+ const org = ws.organizations.get(c.req.param('id'));
64
+ if (!org)
65
+ throw notFound('Organization');
66
+ return c.json(formatOrganization(org, ws));
67
+ });
68
+ app.get('/organizations/external_id/:external_id', (c) => {
69
+ const org = ws.organizations.findOneBy('external_id', c.req.param('external_id'));
70
+ if (!org)
71
+ throw notFound('Organization');
72
+ return c.json(formatOrganization(org, ws));
73
+ });
74
+ app.put('/organizations/:id', async (c) => {
75
+ const org = ws.organizations.get(c.req.param('id'));
76
+ if (!org)
77
+ throw notFound('Organization');
78
+ const body = await parseJsonBody(c);
79
+ const updates = {};
80
+ if ('name' in body) {
81
+ if (!body.name || typeof body.name !== 'string' || body.name.trim().length === 0) {
82
+ throw validationError('Name is required', [{ field: 'name', code: 'required' }]);
83
+ }
84
+ updates.name = body.name.trim();
85
+ }
86
+ if ('external_id' in body)
87
+ updates.external_id = body.external_id ?? null;
88
+ if ('metadata' in body)
89
+ updates.metadata = body.metadata ?? {};
90
+ if ('domain_data' in body && Array.isArray(body.domain_data)) {
91
+ const existing = ws.organizationDomains.findBy('organization_id', org.id);
92
+ const incoming = body.domain_data;
93
+ const incomingDomains = new Set(incoming.map((d) => d.domain));
94
+ for (const d of existing) {
95
+ if (!incomingDomains.has(d.domain)) {
96
+ ws.organizationDomains.delete(d.id);
97
+ }
98
+ }
99
+ const existingDomains = new Set(existing.map((d) => d.domain));
100
+ for (const dd of incoming) {
101
+ if (!existingDomains.has(dd.domain)) {
102
+ ws.organizationDomains.insert({
103
+ object: 'organization_domain',
104
+ organization_id: org.id,
105
+ domain: dd.domain,
106
+ state: dd.state === 'verified' ? 'verified' : 'pending',
107
+ verification_strategy: 'manual',
108
+ verification_token: generateVerificationToken(),
109
+ verification_prefix: 'workos-verify',
110
+ });
111
+ }
112
+ }
113
+ }
114
+ const updated = ws.organizations.update(org.id, updates);
115
+ return c.json(formatOrganization(updated, ws));
116
+ });
117
+ app.delete('/organizations/:id', (c) => {
118
+ const org = ws.organizations.get(c.req.param('id'));
119
+ if (!org)
120
+ throw notFound('Organization');
121
+ const domains = ws.organizationDomains.findBy('organization_id', org.id);
122
+ for (const d of domains) {
123
+ ws.organizationDomains.delete(d.id);
124
+ }
125
+ const memberships = ws.organizationMemberships.findBy('organization_id', org.id);
126
+ for (const m of memberships) {
127
+ ws.organizationMemberships.delete(m.id);
128
+ }
129
+ ws.organizations.delete(org.id);
130
+ return c.body(null, 204);
131
+ });
132
+ }
133
+ //# sourceMappingURL=organizations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"organizations.js","sourceRoot":"","sources":["../../../../src/emulate/workos/routes/organizations.ts"],"names":[],"mappings":"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","sourcesContent":["import { type RouteContext, notFound, validationError, parseJsonBody } from '../../core/index.js';\nimport { getWorkOSStore } from '../store.js';\nimport { formatOrganization, generateVerificationToken, parseListParams } from '../helpers.js';\n\nexport function organizationRoutes(ctx: RouteContext): void {\n const { app, store } = ctx;\n const ws = getWorkOSStore(store);\n\n app.post('/organizations', async (c) => {\n const body = await parseJsonBody(c);\n const name = body.name as string | undefined;\n if (!name || typeof name !== 'string' || name.trim().length === 0) {\n throw validationError('Name is required', [{ field: 'name', code: 'required' }]);\n }\n\n const org = ws.organizations.insert({\n object: 'organization',\n name: name.trim(),\n external_id: (body.external_id as string) ?? null,\n metadata: (body.metadata as Record<string, string>) ?? {},\n stripe_customer_id: null,\n });\n\n const domainData = body.domain_data as Array<{ domain: string; state?: string }> | undefined;\n if (domainData && Array.isArray(domainData)) {\n for (const dd of domainData) {\n ws.organizationDomains.insert({\n object: 'organization_domain',\n organization_id: org.id,\n domain: dd.domain,\n state: dd.state === 'verified' ? 'verified' : 'pending',\n verification_strategy: 'manual',\n verification_token: generateVerificationToken(),\n verification_prefix: 'workos-verify',\n });\n }\n }\n\n return c.json(formatOrganization(org, ws), 201);\n });\n\n app.get('/organizations', (c) => {\n const url = new URL(c.req.url);\n const params = parseListParams(url);\n const nameFilter = url.searchParams.get('name') ?? undefined;\n const domainsFilter = url.searchParams.get('domains') ?? undefined;\n\n const result = ws.organizations.list({\n ...params,\n filter: (org) => {\n if (nameFilter && !org.name.toLowerCase().includes(nameFilter.toLowerCase())) {\n return false;\n }\n if (domainsFilter) {\n const orgDomains = ws.organizationDomains.findBy('organization_id', org.id);\n if (!orgDomains.some((d) => d.domain === domainsFilter)) {\n return false;\n }\n }\n return true;\n },\n });\n\n return c.json({\n object: 'list',\n data: result.data.map((org) => formatOrganization(org, ws)),\n list_metadata: result.list_metadata,\n });\n });\n\n app.get('/organizations/:id', (c) => {\n const org = ws.organizations.get(c.req.param('id'));\n if (!org) throw notFound('Organization');\n return c.json(formatOrganization(org, ws));\n });\n\n app.get('/organizations/external_id/:external_id', (c) => {\n const org = ws.organizations.findOneBy('external_id', c.req.param('external_id'));\n if (!org) throw notFound('Organization');\n return c.json(formatOrganization(org, ws));\n });\n\n app.put('/organizations/:id', async (c) => {\n const org = ws.organizations.get(c.req.param('id'));\n if (!org) throw notFound('Organization');\n\n const body = await parseJsonBody(c);\n const updates: Record<string, unknown> = {};\n\n if ('name' in body) {\n if (!body.name || typeof body.name !== 'string' || (body.name as string).trim().length === 0) {\n throw validationError('Name is required', [{ field: 'name', code: 'required' }]);\n }\n updates.name = (body.name as string).trim();\n }\n if ('external_id' in body) updates.external_id = body.external_id ?? null;\n if ('metadata' in body) updates.metadata = body.metadata ?? {};\n\n if ('domain_data' in body && Array.isArray(body.domain_data)) {\n const existing = ws.organizationDomains.findBy('organization_id', org.id);\n const incoming = body.domain_data as Array<{ domain: string; state?: string }>;\n const incomingDomains = new Set(incoming.map((d) => d.domain));\n\n for (const d of existing) {\n if (!incomingDomains.has(d.domain)) {\n ws.organizationDomains.delete(d.id);\n }\n }\n\n const existingDomains = new Set(existing.map((d) => d.domain));\n for (const dd of incoming) {\n if (!existingDomains.has(dd.domain)) {\n ws.organizationDomains.insert({\n object: 'organization_domain',\n organization_id: org.id,\n domain: dd.domain,\n state: dd.state === 'verified' ? 'verified' : 'pending',\n verification_strategy: 'manual',\n verification_token: generateVerificationToken(),\n verification_prefix: 'workos-verify',\n });\n }\n }\n }\n\n const updated = ws.organizations.update(org.id, updates);\n return c.json(formatOrganization(updated!, ws));\n });\n\n app.delete('/organizations/:id', (c) => {\n const org = ws.organizations.get(c.req.param('id'));\n if (!org) throw notFound('Organization');\n\n const domains = ws.organizationDomains.findBy('organization_id', org.id);\n for (const d of domains) {\n ws.organizationDomains.delete(d.id);\n }\n\n const memberships = ws.organizationMemberships.findBy('organization_id', org.id);\n for (const m of memberships) {\n ws.organizationMemberships.delete(m.id);\n }\n\n ws.organizations.delete(org.id);\n return c.body(null, 204);\n });\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import { type RouteContext } from '../../core/index.js';
2
+ export declare function passwordResetRoutes(ctx: RouteContext): void;
@@ -0,0 +1,61 @@
1
+ import { notFound, parseJsonBody, WorkOSApiError } from '../../core/index.js';
2
+ import { getWorkOSStore } from '../store.js';
3
+ import { formatPasswordReset, generateVerificationToken, hashPassword, expiresIn, isExpired } from '../helpers.js';
4
+ export function passwordResetRoutes(ctx) {
5
+ const { app, store } = ctx;
6
+ const ws = getWorkOSStore(store);
7
+ app.get('/user_management/password_reset/:id', (c) => {
8
+ const pr = ws.passwordResets.get(c.req.param('id'));
9
+ if (!pr)
10
+ throw notFound('Password Reset');
11
+ return c.json(formatPasswordReset(pr));
12
+ });
13
+ app.post('/user_management/password_reset', async (c) => {
14
+ const body = await parseJsonBody(c);
15
+ const email = body.email;
16
+ if (!email) {
17
+ throw new WorkOSApiError(400, 'email is required', 'invalid_request');
18
+ }
19
+ const user = ws.users.findOneBy('email', email);
20
+ if (!user)
21
+ throw notFound('User');
22
+ const pr = ws.passwordResets.insert({
23
+ object: 'password_reset',
24
+ user_id: user.id,
25
+ email: user.email,
26
+ token: generateVerificationToken(),
27
+ expires_at: expiresIn(60),
28
+ });
29
+ return c.json(formatPasswordReset(pr), 201);
30
+ });
31
+ app.post('/user_management/password_reset/confirm', async (c) => {
32
+ const body = await parseJsonBody(c);
33
+ const token = body.token;
34
+ const newPassword = body.new_password;
35
+ if (!token) {
36
+ throw new WorkOSApiError(400, 'token is required', 'invalid_request');
37
+ }
38
+ if (!newPassword) {
39
+ throw new WorkOSApiError(400, 'new_password is required', 'invalid_request');
40
+ }
41
+ const resets = ws.passwordResets.all();
42
+ const pr = resets.find((r) => r.token === token);
43
+ if (!pr) {
44
+ throw new WorkOSApiError(400, 'Invalid token', 'invalid_token');
45
+ }
46
+ if (isExpired(pr.expires_at)) {
47
+ throw new WorkOSApiError(400, 'Token has expired', 'expired_token');
48
+ }
49
+ const user = ws.users.get(pr.user_id);
50
+ if (!user) {
51
+ ws.passwordResets.delete(pr.id);
52
+ throw notFound('User');
53
+ }
54
+ ws.users.update(pr.user_id, {
55
+ password_hash: hashPassword(newPassword),
56
+ });
57
+ ws.passwordResets.delete(pr.id);
58
+ return c.json({ user: { object: 'user', id: user.id, email: user.email } });
59
+ });
60
+ }
61
+ //# sourceMappingURL=password-reset.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"password-reset.js","sourceRoot":"","sources":["../../../../src/emulate/workos/routes/password-reset.ts"],"names":[],"mappings":"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","sourcesContent":["import { type RouteContext, notFound, parseJsonBody, WorkOSApiError } from '../../core/index.js';\nimport { getWorkOSStore } from '../store.js';\nimport { formatPasswordReset, generateVerificationToken, hashPassword, expiresIn, isExpired } from '../helpers.js';\n\nexport function passwordResetRoutes(ctx: RouteContext): void {\n const { app, store } = ctx;\n const ws = getWorkOSStore(store);\n\n app.get('/user_management/password_reset/:id', (c) => {\n const pr = ws.passwordResets.get(c.req.param('id'));\n if (!pr) throw notFound('Password Reset');\n return c.json(formatPasswordReset(pr));\n });\n\n app.post('/user_management/password_reset', async (c) => {\n const body = await parseJsonBody(c);\n const email = body.email as string | undefined;\n if (!email) {\n throw new WorkOSApiError(400, 'email is required', 'invalid_request');\n }\n\n const user = ws.users.findOneBy('email', email);\n if (!user) throw notFound('User');\n\n const pr = ws.passwordResets.insert({\n object: 'password_reset',\n user_id: user.id,\n email: user.email,\n token: generateVerificationToken(),\n expires_at: expiresIn(60),\n });\n\n return c.json(formatPasswordReset(pr), 201);\n });\n\n app.post('/user_management/password_reset/confirm', async (c) => {\n const body = await parseJsonBody(c);\n const token = body.token as string | undefined;\n const newPassword = body.new_password as string | undefined;\n\n if (!token) {\n throw new WorkOSApiError(400, 'token is required', 'invalid_request');\n }\n if (!newPassword) {\n throw new WorkOSApiError(400, 'new_password is required', 'invalid_request');\n }\n\n const resets = ws.passwordResets.all();\n const pr = resets.find((r) => r.token === token);\n if (!pr) {\n throw new WorkOSApiError(400, 'Invalid token', 'invalid_token');\n }\n if (isExpired(pr.expires_at)) {\n throw new WorkOSApiError(400, 'Token has expired', 'expired_token');\n }\n\n const user = ws.users.get(pr.user_id);\n if (!user) {\n ws.passwordResets.delete(pr.id);\n throw notFound('User');\n }\n\n ws.users.update(pr.user_id, {\n password_hash: hashPassword(newPassword),\n });\n ws.passwordResets.delete(pr.id);\n\n return c.json({ user: { object: 'user', id: user.id, email: user.email } });\n });\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import { type RouteContext } from '../../core/index.js';
2
+ export declare function pipeRoutes(ctx: RouteContext): void;