workos 0.13.1 → 0.13.3

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 (34) hide show
  1. package/README.md +1 -1
  2. package/dist/commands/env.js +9 -1
  3. package/dist/commands/env.js.map +1 -1
  4. package/dist/commands/login.js +44 -117
  5. package/dist/commands/login.js.map +1 -1
  6. package/dist/commands/webhook.js +20 -1
  7. package/dist/commands/webhook.js.map +1 -1
  8. package/dist/emulate/workos/entities.d.ts +1 -1
  9. package/dist/emulate/workos/entities.js.map +1 -1
  10. package/dist/emulate/workos/event-bus.js +1 -1
  11. package/dist/emulate/workos/event-bus.js.map +1 -1
  12. package/dist/emulate/workos/helpers.js +1 -1
  13. package/dist/emulate/workos/helpers.js.map +1 -1
  14. package/dist/emulate/workos/index.d.ts +3 -1
  15. package/dist/emulate/workos/index.js +5 -1
  16. package/dist/emulate/workos/index.js.map +1 -1
  17. package/dist/emulate/workos/routes/authorization-org-roles.js.map +1 -1
  18. package/dist/emulate/workos/routes/authorization-roles.js.map +1 -1
  19. package/dist/emulate/workos/routes/webhook-endpoints.js +9 -8
  20. package/dist/emulate/workos/routes/webhook-endpoints.js.map +1 -1
  21. package/dist/emulate/workos/store.js +1 -1
  22. package/dist/emulate/workos/store.js.map +1 -1
  23. package/dist/lib/api-key.d.ts +2 -2
  24. package/dist/lib/api-key.js +4 -4
  25. package/dist/lib/api-key.js.map +1 -1
  26. package/dist/lib/device-auth.d.ts +3 -0
  27. package/dist/lib/device-auth.js +31 -9
  28. package/dist/lib/device-auth.js.map +1 -1
  29. package/dist/lib/workos-client.d.ts +1 -1
  30. package/dist/lib/workos-client.js.map +1 -1
  31. package/dist/utils/output.d.ts +6 -1
  32. package/dist/utils/output.js +12 -2
  33. package/dist/utils/output.js.map +1 -1
  34. package/package.json +1 -1
package/README.md CHANGED
@@ -367,7 +367,7 @@ API keys are stored in the system keychain via `@napi-rs/keyring`, with a JSON f
367
367
 
368
368
  ### Resource Management
369
369
 
370
- All resource commands follow the same pattern: `workos <resource> <action> [args] [--options]`. API keys resolve via: `WORKOS_API_KEY` env var → `--api-key` flag → active environment's stored key.
370
+ All resource commands follow the same pattern: `workos <resource> <action> [args] [--options]`. API keys resolve via: `--api-key` flag → `WORKOS_API_KEY` env var → active environment's stored key.
371
371
 
372
372
  #### organization
373
373
 
@@ -151,7 +151,15 @@ export async function runEnvSwitch(name) {
151
151
  config.activeEnvironment = name;
152
152
  saveConfig(config);
153
153
  const env = config.environments[name];
154
- outputSuccess('Switched environment', { name, type: env.type });
154
+ const warnings = process.env.WORKOS_API_KEY
155
+ ? [
156
+ {
157
+ code: 'env_var_override',
158
+ message: "WORKOS_API_KEY is set in your shell. It will override this environment's stored key unless you pass --api-key.",
159
+ },
160
+ ]
161
+ : undefined;
162
+ outputSuccess('Switched environment', { name, type: env.type }, { warnings });
155
163
  }
156
164
  export async function runEnvList() {
157
165
  const config = getConfig();
@@ -1 +1 @@
1
- {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/commands/env.ts"],"names":[],"mappings":"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","sourcesContent":["import chalk from 'chalk';\nimport clack from '../utils/clack.js';\nimport { getConfig, saveConfig, isUnclaimedEnvironment } from '../lib/config-store.js';\nimport type { CliConfig } from '../lib/config-store.js';\nimport { outputSuccess, outputJson, exitWithError, isJsonMode } from '../utils/output.js';\nimport { isNonInteractiveEnvironment } from '../utils/environment.js';\n\nconst ENV_NAME_REGEX = /^[a-z0-9\\-_]+$/;\n\nfunction validateEnvName(name: string | undefined): string | undefined {\n if (!name || !ENV_NAME_REGEX.test(name)) {\n return 'Name must contain only lowercase letters, numbers, hyphens, and underscores';\n }\n return undefined;\n}\n\nfunction getOrCreateConfig(): CliConfig {\n return getConfig() ?? { environments: {} };\n}\n\nexport async function runEnvAdd(options: {\n name?: string;\n apiKey?: string;\n clientId?: string;\n endpoint?: string;\n}): Promise<void> {\n let { name, apiKey, endpoint } = options;\n const { clientId } = options;\n\n if (name && apiKey) {\n // Non-interactive mode\n const nameError = validateEnvName(name);\n if (nameError) {\n exitWithError({ code: 'invalid_args', message: nameError });\n }\n } else if (isNonInteractiveEnvironment()) {\n exitWithError({ code: 'missing_args', message: 'Name and API key required in non-interactive mode' });\n } else {\n // Interactive mode\n const nameResult = await clack.text({\n message: 'Enter a name for the environment (e.g., production, sandbox, local)',\n validate: (value) => validateEnvName(value),\n });\n if (clack.isCancel(nameResult)) process.exit(0);\n name = nameResult;\n\n const typeResult = await clack.select({\n message: 'Select the environment type',\n options: [\n { value: 'production', label: 'Production' },\n { value: 'sandbox', label: 'Sandbox' },\n ],\n });\n if (clack.isCancel(typeResult)) process.exit(0);\n\n const apiKeyResult = await clack.password({\n message: 'Enter the API key for this environment',\n validate: (value) => {\n if (!value) return 'API key is required';\n return undefined;\n },\n });\n if (clack.isCancel(apiKeyResult)) process.exit(0);\n apiKey = apiKeyResult;\n\n const config = getOrCreateConfig();\n const isFirst = Object.keys(config.environments).length === 0;\n\n config.environments[name] = {\n name,\n type: typeResult as 'production' | 'sandbox',\n apiKey,\n ...(clientId && { clientId }),\n ...(endpoint && { endpoint }),\n };\n\n if (isFirst) {\n config.activeEnvironment = name;\n }\n\n saveConfig(config);\n clack.log.success(`Environment ${chalk.bold(name)} added`);\n if (isFirst) {\n clack.log.info(`Set as active environment`);\n }\n return;\n }\n\n // Non-interactive path\n const config = getOrCreateConfig();\n const isFirst = Object.keys(config.environments).length === 0;\n\n const type: 'production' | 'sandbox' = apiKey.startsWith('sk_test_') ? 'sandbox' : 'production';\n\n config.environments[name!] = {\n name: name!,\n type,\n apiKey,\n ...(clientId && { clientId }),\n ...(endpoint && { endpoint }),\n };\n\n if (isFirst) {\n config.activeEnvironment = name;\n }\n\n saveConfig(config);\n outputSuccess('Environment added', { name: name!, type, active: isFirst });\n}\n\nexport async function runEnvRemove(name: string): Promise<void> {\n const config = getConfig();\n if (!config || Object.keys(config.environments).length === 0) {\n exitWithError({\n code: 'no_environments',\n message: 'No environments configured. Run `workos env add` to get started.',\n });\n }\n\n if (!config.environments[name]) {\n const available = Object.keys(config.environments).join(', ');\n exitWithError({ code: 'not_found', message: `Environment \"${name}\" not found. Available: ${available}` });\n }\n\n delete config.environments[name];\n\n if (config.activeEnvironment === name) {\n const remaining = Object.keys(config.environments);\n config.activeEnvironment = remaining.length > 0 ? remaining[0] : undefined;\n if (config.activeEnvironment && !isJsonMode()) {\n clack.log.info(`Active environment switched to ${chalk.bold(config.activeEnvironment)}`);\n }\n }\n\n saveConfig(config);\n outputSuccess('Environment removed', { name, newActive: config.activeEnvironment ?? null });\n}\n\nexport async function runEnvSwitch(name?: string): Promise<void> {\n const config = getConfig();\n if (!config || Object.keys(config.environments).length === 0) {\n exitWithError({\n code: 'no_environments',\n message: 'No environments configured. Run `workos env add` to get started.',\n });\n }\n\n if (name) {\n if (!config.environments[name]) {\n const available = Object.keys(config.environments).join(', ');\n exitWithError({ code: 'not_found', message: `Environment \"${name}\" not found. Available: ${available}` });\n }\n } else {\n // Interactive selection (TTY only — non-TTY guard is in bin.ts)\n const options = Object.entries(config.environments).map(([key, env]) => {\n let label = key;\n if (env.type === 'sandbox') label += ` [Sandbox]`;\n if (env.endpoint) label += ` [${env.endpoint}]`;\n if (key === config.activeEnvironment) label += chalk.green(' (active)');\n return { value: key, label };\n });\n\n const selected = await clack.select({\n message: 'Select an environment',\n options,\n });\n if (clack.isCancel(selected)) process.exit(0);\n name = selected as string;\n }\n\n config.activeEnvironment = name;\n saveConfig(config);\n\n const env = config.environments[name];\n outputSuccess('Switched environment', { name, type: env.type });\n}\n\nexport async function runEnvList(): Promise<void> {\n const config = getConfig();\n if (!config || Object.keys(config.environments).length === 0) {\n if (isJsonMode()) {\n outputJson({ data: [] });\n } else {\n clack.log.info('No environments configured. Run `workos env add` to get started.');\n }\n return;\n }\n\n const entries = Object.entries(config.environments);\n\n if (isJsonMode()) {\n const data = entries.map(([key, env]) => ({\n name: key,\n type: env.type,\n active: key === config.activeEnvironment,\n endpoint: env.endpoint ?? null,\n hasApiKey: !!env.apiKey,\n hasClientId: !!env.clientId,\n }));\n outputJson({ data });\n return;\n }\n\n // Human-mode table\n const hasUnclaimed = entries.some(([, env]) => isUnclaimedEnvironment(env));\n const nameW =\n Math.max(6, ...entries.map(([k, env]) => k.length + (isUnclaimedEnvironment(env) ? ' (unclaimed)'.length : 0))) + 2;\n const typeW = 12;\n\n const header = [\n chalk.yellow(' '),\n chalk.yellow('Name'.padEnd(nameW)),\n chalk.yellow('Type'.padEnd(typeW)),\n chalk.yellow('Endpoint'),\n ].join(' ');\n\n const separator = chalk.dim('─'.repeat(header.length));\n\n console.log(header);\n console.log(separator);\n\n for (const [key, env] of entries) {\n const isActive = key === config.activeEnvironment;\n const marker = isActive ? chalk.green('▸ ') : ' ';\n const unclaimed = isUnclaimedEnvironment(env);\n const displayName = unclaimed ? `${key} ${chalk.yellow('(unclaimed)')}` : key;\n const name = isActive ? chalk.green(displayName.padEnd(nameW)) : displayName.padEnd(nameW);\n const type = unclaimed ? 'Unclaimed' : env.type === 'sandbox' ? 'Sandbox' : 'Production';\n const endpoint = env.endpoint || chalk.dim('default');\n\n console.log([marker, name, type.padEnd(typeW), endpoint].join(' '));\n }\n\n if (hasUnclaimed) {\n console.log('');\n console.log(chalk.dim(' Run `workos env claim` to keep this environment.'));\n }\n}\n"]}
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/commands/env.ts"],"names":[],"mappings":"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","sourcesContent":["import chalk from 'chalk';\nimport clack from '../utils/clack.js';\nimport { getConfig, saveConfig, isUnclaimedEnvironment } from '../lib/config-store.js';\nimport type { CliConfig } from '../lib/config-store.js';\nimport { outputSuccess, outputJson, exitWithError, isJsonMode } from '../utils/output.js';\nimport { isNonInteractiveEnvironment } from '../utils/environment.js';\n\nconst ENV_NAME_REGEX = /^[a-z0-9\\-_]+$/;\n\nfunction validateEnvName(name: string | undefined): string | undefined {\n if (!name || !ENV_NAME_REGEX.test(name)) {\n return 'Name must contain only lowercase letters, numbers, hyphens, and underscores';\n }\n return undefined;\n}\n\nfunction getOrCreateConfig(): CliConfig {\n return getConfig() ?? { environments: {} };\n}\n\nexport async function runEnvAdd(options: {\n name?: string;\n apiKey?: string;\n clientId?: string;\n endpoint?: string;\n}): Promise<void> {\n let { name, apiKey, endpoint } = options;\n const { clientId } = options;\n\n if (name && apiKey) {\n // Non-interactive mode\n const nameError = validateEnvName(name);\n if (nameError) {\n exitWithError({ code: 'invalid_args', message: nameError });\n }\n } else if (isNonInteractiveEnvironment()) {\n exitWithError({ code: 'missing_args', message: 'Name and API key required in non-interactive mode' });\n } else {\n // Interactive mode\n const nameResult = await clack.text({\n message: 'Enter a name for the environment (e.g., production, sandbox, local)',\n validate: (value) => validateEnvName(value),\n });\n if (clack.isCancel(nameResult)) process.exit(0);\n name = nameResult;\n\n const typeResult = await clack.select({\n message: 'Select the environment type',\n options: [\n { value: 'production', label: 'Production' },\n { value: 'sandbox', label: 'Sandbox' },\n ],\n });\n if (clack.isCancel(typeResult)) process.exit(0);\n\n const apiKeyResult = await clack.password({\n message: 'Enter the API key for this environment',\n validate: (value) => {\n if (!value) return 'API key is required';\n return undefined;\n },\n });\n if (clack.isCancel(apiKeyResult)) process.exit(0);\n apiKey = apiKeyResult;\n\n const config = getOrCreateConfig();\n const isFirst = Object.keys(config.environments).length === 0;\n\n config.environments[name] = {\n name,\n type: typeResult as 'production' | 'sandbox',\n apiKey,\n ...(clientId && { clientId }),\n ...(endpoint && { endpoint }),\n };\n\n if (isFirst) {\n config.activeEnvironment = name;\n }\n\n saveConfig(config);\n clack.log.success(`Environment ${chalk.bold(name)} added`);\n if (isFirst) {\n clack.log.info(`Set as active environment`);\n }\n return;\n }\n\n // Non-interactive path\n const config = getOrCreateConfig();\n const isFirst = Object.keys(config.environments).length === 0;\n\n const type: 'production' | 'sandbox' = apiKey.startsWith('sk_test_') ? 'sandbox' : 'production';\n\n config.environments[name!] = {\n name: name!,\n type,\n apiKey,\n ...(clientId && { clientId }),\n ...(endpoint && { endpoint }),\n };\n\n if (isFirst) {\n config.activeEnvironment = name;\n }\n\n saveConfig(config);\n outputSuccess('Environment added', { name: name!, type, active: isFirst });\n}\n\nexport async function runEnvRemove(name: string): Promise<void> {\n const config = getConfig();\n if (!config || Object.keys(config.environments).length === 0) {\n exitWithError({\n code: 'no_environments',\n message: 'No environments configured. Run `workos env add` to get started.',\n });\n }\n\n if (!config.environments[name]) {\n const available = Object.keys(config.environments).join(', ');\n exitWithError({ code: 'not_found', message: `Environment \"${name}\" not found. Available: ${available}` });\n }\n\n delete config.environments[name];\n\n if (config.activeEnvironment === name) {\n const remaining = Object.keys(config.environments);\n config.activeEnvironment = remaining.length > 0 ? remaining[0] : undefined;\n if (config.activeEnvironment && !isJsonMode()) {\n clack.log.info(`Active environment switched to ${chalk.bold(config.activeEnvironment)}`);\n }\n }\n\n saveConfig(config);\n outputSuccess('Environment removed', { name, newActive: config.activeEnvironment ?? null });\n}\n\nexport async function runEnvSwitch(name?: string): Promise<void> {\n const config = getConfig();\n if (!config || Object.keys(config.environments).length === 0) {\n exitWithError({\n code: 'no_environments',\n message: 'No environments configured. Run `workos env add` to get started.',\n });\n }\n\n if (name) {\n if (!config.environments[name]) {\n const available = Object.keys(config.environments).join(', ');\n exitWithError({ code: 'not_found', message: `Environment \"${name}\" not found. Available: ${available}` });\n }\n } else {\n // Interactive selection (TTY only — non-TTY guard is in bin.ts)\n const options = Object.entries(config.environments).map(([key, env]) => {\n let label = key;\n if (env.type === 'sandbox') label += ` [Sandbox]`;\n if (env.endpoint) label += ` [${env.endpoint}]`;\n if (key === config.activeEnvironment) label += chalk.green(' (active)');\n return { value: key, label };\n });\n\n const selected = await clack.select({\n message: 'Select an environment',\n options,\n });\n if (clack.isCancel(selected)) process.exit(0);\n name = selected as string;\n }\n\n config.activeEnvironment = name;\n saveConfig(config);\n\n const env = config.environments[name];\n const warnings = process.env.WORKOS_API_KEY\n ? [\n {\n code: 'env_var_override',\n message:\n \"WORKOS_API_KEY is set in your shell. It will override this environment's stored key unless you pass --api-key.\",\n },\n ]\n : undefined;\n outputSuccess('Switched environment', { name, type: env.type }, { warnings });\n}\n\nexport async function runEnvList(): Promise<void> {\n const config = getConfig();\n if (!config || Object.keys(config.environments).length === 0) {\n if (isJsonMode()) {\n outputJson({ data: [] });\n } else {\n clack.log.info('No environments configured. Run `workos env add` to get started.');\n }\n return;\n }\n\n const entries = Object.entries(config.environments);\n\n if (isJsonMode()) {\n const data = entries.map(([key, env]) => ({\n name: key,\n type: env.type,\n active: key === config.activeEnvironment,\n endpoint: env.endpoint ?? null,\n hasApiKey: !!env.apiKey,\n hasClientId: !!env.clientId,\n }));\n outputJson({ data });\n return;\n }\n\n // Human-mode table\n const hasUnclaimed = entries.some(([, env]) => isUnclaimedEnvironment(env));\n const nameW =\n Math.max(6, ...entries.map(([k, env]) => k.length + (isUnclaimedEnvironment(env) ? ' (unclaimed)'.length : 0))) + 2;\n const typeW = 12;\n\n const header = [\n chalk.yellow(' '),\n chalk.yellow('Name'.padEnd(nameW)),\n chalk.yellow('Type'.padEnd(typeW)),\n chalk.yellow('Endpoint'),\n ].join(' ');\n\n const separator = chalk.dim('─'.repeat(header.length));\n\n console.log(header);\n console.log(separator);\n\n for (const [key, env] of entries) {\n const isActive = key === config.activeEnvironment;\n const marker = isActive ? chalk.green('▸ ') : ' ';\n const unclaimed = isUnclaimedEnvironment(env);\n const displayName = unclaimed ? `${key} ${chalk.yellow('(unclaimed)')}` : key;\n const name = isActive ? chalk.green(displayName.padEnd(nameW)) : displayName.padEnd(nameW);\n const type = unclaimed ? 'Unclaimed' : env.type === 'sandbox' ? 'Sandbox' : 'Production';\n const endpoint = env.endpoint || chalk.dim('default');\n\n console.log([marker, name, type.padEnd(typeW), endpoint].join(' '));\n }\n\n if (hasUnclaimed) {\n console.log('');\n console.log(chalk.dim(' Run `workos env claim` to keep this environment.'));\n }\n}\n"]}
@@ -10,43 +10,7 @@ import { getConfig, saveConfig } from '../lib/config-store.js';
10
10
  import { formatWorkOSCommand } from '../utils/command-invocation.js';
11
11
  import { autoInstallSkills } from './install-skill.js';
12
12
  import { isJsonMode } from '../utils/output.js';
13
- /**
14
- * Parse JWT payload
15
- */
16
- function parseJwt(token) {
17
- try {
18
- const parts = token.split('.');
19
- if (parts.length !== 3)
20
- return null;
21
- return JSON.parse(Buffer.from(parts[1], 'base64url').toString('utf-8'));
22
- }
23
- catch {
24
- return null;
25
- }
26
- }
27
- /**
28
- * Extract expiry time from JWT token
29
- */
30
- function getJwtExpiry(token) {
31
- const payload = parseJwt(token);
32
- if (!payload || typeof payload.exp !== 'number')
33
- return null;
34
- return payload.exp * 1000;
35
- }
36
- const POLL_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
37
- /**
38
- * Get Connect OAuth endpoints from AuthKit domain
39
- */
40
- function getConnectEndpoints() {
41
- const domain = getAuthkitDomain();
42
- return {
43
- deviceAuthorization: `${domain}/oauth2/device_authorization`,
44
- token: `${domain}/oauth2/token`,
45
- };
46
- }
47
- function sleep(ms) {
48
- return new Promise((resolve) => setTimeout(resolve, ms));
49
- }
13
+ import { requestDeviceCode, pollForToken, DeviceAuthTimeoutError } from '../lib/device-auth.js';
50
14
  /**
51
15
  * Best-effort skill install after a successful auth-login.
52
16
  *
@@ -139,24 +103,17 @@ export async function runLogin() {
139
103
  // Refresh failed, proceed with fresh login
140
104
  }
141
105
  }
106
+ const authkitDomain = getAuthkitDomain();
142
107
  clack.log.step('Starting authentication...');
143
- const endpoints = getConnectEndpoints();
144
- const authResponse = await fetch(endpoints.deviceAuthorization, {
145
- method: 'POST',
146
- headers: {
147
- 'Content-Type': 'application/x-www-form-urlencoded',
148
- },
149
- body: new URLSearchParams({
150
- client_id: clientId,
151
- scope: 'openid email staging-environment:credentials:read offline_access',
152
- }),
153
- });
154
- if (!authResponse.ok) {
155
- clack.log.error(`Failed to start authentication: ${authResponse.status}`);
108
+ let deviceAuth;
109
+ try {
110
+ deviceAuth = await requestDeviceCode({ clientId, authkitDomain });
111
+ }
112
+ catch (error) {
113
+ const msg = error instanceof Error ? error.message : String(error);
114
+ clack.log.error(`Failed to start authentication: ${msg}`);
156
115
  process.exit(1);
157
116
  }
158
- const deviceAuth = (await authResponse.json());
159
- const pollIntervalMs = (deviceAuth.interval || 5) * 1000;
160
117
  clack.log.info(`\nOpen this URL in your browser:\n`);
161
118
  console.log(` ${deviceAuth.verification_uri}`);
162
119
  console.log(`\nEnter code: ${deviceAuth.user_code}\n`);
@@ -169,73 +126,43 @@ export async function runLogin() {
169
126
  }
170
127
  const spinner = clack.spinner();
171
128
  spinner.start('Waiting for authentication...');
172
- const startTime = Date.now();
173
- let currentInterval = pollIntervalMs;
174
- while (Date.now() - startTime < POLL_TIMEOUT_MS) {
175
- await sleep(currentInterval);
176
- try {
177
- const tokenResponse = await fetch(endpoints.token, {
178
- method: 'POST',
179
- headers: {
180
- 'Content-Type': 'application/x-www-form-urlencoded',
181
- },
182
- body: new URLSearchParams({
183
- grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
184
- device_code: deviceAuth.device_code,
185
- client_id: clientId,
186
- }),
187
- });
188
- const data = await tokenResponse.json();
189
- if (tokenResponse.ok) {
190
- const result = data;
191
- // Parse user info from id_token JWT
192
- const idTokenPayload = parseJwt(result.id_token);
193
- const userId = idTokenPayload?.sub || 'unknown';
194
- const email = idTokenPayload?.email || undefined;
195
- // Extract actual expiry from access token JWT, fallback to response or 15 min
196
- const jwtExpiry = getJwtExpiry(result.access_token);
197
- const expiresAt = jwtExpiry ?? (result.expires_in ? Date.now() + result.expires_in * 1000 : Date.now() + 15 * 60 * 1000);
198
- const expiresInSec = Math.round((expiresAt - Date.now()) / 1000);
199
- saveCredentials({
200
- accessToken: result.access_token,
201
- expiresAt,
202
- userId,
203
- email,
204
- refreshToken: result.refresh_token,
205
- });
206
- spinner.stop('Authentication successful!');
207
- clack.log.success(`Logged in as ${email || userId}`);
208
- clack.log.info(`Token expires in ${expiresInSec} seconds`);
209
- // Auto-provision staging environment
210
- const provisioned = await provisionStagingEnvironment(result.access_token);
211
- if (provisioned) {
212
- clack.log.success('Staging environment configured automatically');
213
- }
214
- else {
215
- clack.log.info(chalk.dim('Run `workos env add` to configure an environment manually'));
216
- }
217
- // Best-effort skill install. Wrapped helper guarantees login never
218
- // fails on skill errors.
219
- await installSkillsAfterLogin();
220
- return;
221
- }
222
- const errorData = data;
223
- if (errorData.error === 'authorization_pending')
224
- continue;
225
- if (errorData.error === 'slow_down') {
226
- currentInterval += 5000;
227
- continue;
228
- }
229
- spinner.stop('Authentication failed');
230
- clack.log.error(`Authentication error: ${errorData.error}`);
231
- process.exit(1);
129
+ try {
130
+ const result = await pollForToken(deviceAuth.device_code, {
131
+ clientId,
132
+ authkitDomain,
133
+ interval: deviceAuth.interval,
134
+ });
135
+ const expiresInSec = Math.round((result.expiresAt - Date.now()) / 1000);
136
+ saveCredentials({
137
+ accessToken: result.accessToken,
138
+ expiresAt: result.expiresAt,
139
+ userId: result.userId,
140
+ email: result.email,
141
+ refreshToken: result.refreshToken,
142
+ });
143
+ spinner.stop('Authentication successful!');
144
+ clack.log.success(`Logged in as ${result.email || result.userId}`);
145
+ clack.log.info(`Token expires in ${expiresInSec} seconds`);
146
+ const provisioned = await provisionStagingEnvironment(result.accessToken);
147
+ if (provisioned) {
148
+ clack.log.success('Staging environment configured automatically');
232
149
  }
233
- catch {
234
- continue;
150
+ else {
151
+ clack.log.info(chalk.dim('Run `workos env add` to configure an environment manually'));
152
+ }
153
+ await installSkillsAfterLogin();
154
+ }
155
+ catch (error) {
156
+ if (error instanceof DeviceAuthTimeoutError) {
157
+ spinner.stop('Authentication timed out');
158
+ clack.log.error('Authentication timed out. Please try again.');
159
+ }
160
+ else {
161
+ spinner.stop('Authentication failed');
162
+ const msg = error instanceof Error ? error.message : String(error);
163
+ clack.log.error(`Authentication error: ${msg}`);
235
164
  }
165
+ process.exit(1);
236
166
  }
237
- spinner.stop('Authentication timed out');
238
- clack.log.error('Authentication timed out. Please try again.');
239
- process.exit(1);
240
167
  }
241
168
  //# sourceMappingURL=login.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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","sourcesContent":["import open from 'opn';\nimport chalk from 'chalk';\nimport clack from '../utils/clack.js';\nimport { saveCredentials, getCredentials, getAccessToken, isTokenExpired, updateTokens } from '../lib/credentials.js';\nimport { getCliAuthClientId, getAuthkitDomain } from '../lib/settings.js';\nimport { refreshAccessToken } from '../lib/token-refresh-client.js';\nimport { logInfo, logError } from '../utils/debug.js';\nimport { fetchStagingCredentials } from '../lib/staging-api.js';\nimport { getConfig, saveConfig } from '../lib/config-store.js';\nimport type { CliConfig } from '../lib/config-store.js';\nimport { formatWorkOSCommand } from '../utils/command-invocation.js';\nimport { autoInstallSkills } from './install-skill.js';\nimport { isJsonMode } from '../utils/output.js';\n\n/**\n * Parse JWT payload\n */\nfunction parseJwt(token: string): Record<string, unknown> | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) return null;\n return JSON.parse(Buffer.from(parts[1], 'base64url').toString('utf-8'));\n } catch {\n return null;\n }\n}\n\n/**\n * Extract expiry time from JWT token\n */\nfunction getJwtExpiry(token: string): number | null {\n const payload = parseJwt(token);\n if (!payload || typeof payload.exp !== 'number') return null;\n return payload.exp * 1000;\n}\n\nconst POLL_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes\n\n/**\n * Get Connect OAuth endpoints from AuthKit domain\n */\nfunction getConnectEndpoints() {\n const domain = getAuthkitDomain();\n return {\n deviceAuthorization: `${domain}/oauth2/device_authorization`,\n token: `${domain}/oauth2/token`,\n };\n}\n\ninterface DeviceAuthResponse {\n device_code: string;\n user_code: string;\n verification_uri: string;\n verification_uri_complete: string;\n expires_in: number;\n interval: number;\n}\n\ninterface ConnectTokenResponse {\n access_token: string;\n id_token: string;\n token_type: string;\n expires_in: number;\n refresh_token?: string;\n}\n\ninterface AuthErrorResponse {\n error: string;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Best-effort skill install after a successful auth-login.\n *\n * Mirrors the install.ts hook copy, but wraps `autoInstallSkills` in its own\n * try/catch AND a 30s timeout so a skill install hang (e.g. blocked filesystem\n * call) never blocks login completion. Login already succeeded by the time\n * this runs — the user having a working session is the contract that must hold.\n *\n * Extracted from runLogin so it can be unit-tested without standing up the\n * device-auth polling loop.\n */\nexport const SKILL_INSTALL_TIMEOUT_MS = 30 * 1000;\n\nexport async function installSkillsAfterLogin(): Promise<void> {\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined;\n try {\n const timeout = new Promise<null>((resolve) => {\n timeoutHandle = setTimeout(() => resolve(null), SKILL_INSTALL_TIMEOUT_MS);\n // Don't keep the event loop alive on this timer — process should exit\n // immediately if everything else has resolved.\n timeoutHandle.unref?.();\n });\n const result = await Promise.race([autoInstallSkills(), timeout]);\n if (result && !isJsonMode()) {\n const skillWord = result.skills.length === 1 ? 'skill' : 'skills';\n clack.log.info(`Installed ${result.skills.length} WorkOS ${skillWord} for ${result.agents.join(', ')}.`);\n }\n } catch {\n // Skill install must never fail login.\n } finally {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n }\n}\n\n/**\n * Auto-provision a staging environment after login.\n *\n * Fetches staging credentials using the access token, then saves them\n * as a \"staging\" environment in the config store. Non-fatal — logs a\n * hint on failure instead of throwing.\n */\nexport async function provisionStagingEnvironment(accessToken: string): Promise<boolean> {\n try {\n const staging = await fetchStagingCredentials(accessToken);\n\n const config: CliConfig = getConfig() ?? { environments: {} };\n const isFirst = Object.keys(config.environments).length === 0;\n\n config.environments['staging'] = {\n name: 'staging',\n type: 'sandbox',\n apiKey: staging.apiKey,\n clientId: staging.clientId,\n };\n\n if (isFirst || !config.activeEnvironment) {\n config.activeEnvironment = 'staging';\n }\n\n saveConfig(config);\n logInfo('[login] Staging environment auto-provisioned');\n return true;\n } catch (error) {\n logError('[login] Failed to auto-provision staging environment:', error instanceof Error ? error.message : error);\n return false;\n }\n}\n\nexport async function runLogin(): Promise<void> {\n const clientId = getCliAuthClientId();\n\n // Check if already logged in with valid token\n if (getAccessToken()) {\n const creds = getCredentials();\n console.log(chalk.green(`Already logged in as ${creds?.email ?? 'unknown'}`));\n console.log(chalk.dim(`Run \\`${formatWorkOSCommand('auth logout')}\\` to log out`));\n return;\n }\n\n // Try to refresh if we have expired credentials with a refresh token\n const existingCreds = getCredentials();\n if (existingCreds?.refreshToken && isTokenExpired(existingCreds)) {\n try {\n const authkitDomain = getAuthkitDomain();\n const result = await refreshAccessToken(authkitDomain, clientId);\n if (result.accessToken && result.expiresAt) {\n updateTokens(result.accessToken, result.expiresAt, result.refreshToken);\n logInfo('[login] Session refreshed via refresh token');\n console.log(chalk.green(`Already logged in as ${existingCreds.email ?? 'unknown'}`));\n console.log(chalk.dim(`Run \\`${formatWorkOSCommand('auth logout')}\\` to log out`));\n return;\n }\n } catch {\n // Refresh failed, proceed with fresh login\n }\n }\n\n clack.log.step('Starting authentication...');\n\n const endpoints = getConnectEndpoints();\n\n const authResponse = await fetch(endpoints.deviceAuthorization, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n client_id: clientId,\n scope: 'openid email staging-environment:credentials:read offline_access',\n }),\n });\n\n if (!authResponse.ok) {\n clack.log.error(`Failed to start authentication: ${authResponse.status}`);\n process.exit(1);\n }\n\n const deviceAuth = (await authResponse.json()) as DeviceAuthResponse;\n const pollIntervalMs = (deviceAuth.interval || 5) * 1000;\n\n clack.log.info(`\\nOpen this URL in your browser:\\n`);\n console.log(` ${deviceAuth.verification_uri}`);\n console.log(`\\nEnter code: ${deviceAuth.user_code}\\n`);\n\n try {\n open(deviceAuth.verification_uri_complete);\n clack.log.info('Browser opened automatically');\n } catch {\n // User can open manually\n }\n\n const spinner = clack.spinner();\n spinner.start('Waiting for authentication...');\n\n const startTime = Date.now();\n let currentInterval = pollIntervalMs;\n\n while (Date.now() - startTime < POLL_TIMEOUT_MS) {\n await sleep(currentInterval);\n\n try {\n const tokenResponse = await fetch(endpoints.token, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'urn:ietf:params:oauth:grant-type:device_code',\n device_code: deviceAuth.device_code,\n client_id: clientId,\n }),\n });\n\n const data = await tokenResponse.json();\n\n if (tokenResponse.ok) {\n const result = data as ConnectTokenResponse;\n\n // Parse user info from id_token JWT\n const idTokenPayload = parseJwt(result.id_token);\n const userId = (idTokenPayload?.sub as string) || 'unknown';\n const email = (idTokenPayload?.email as string) || undefined;\n\n // Extract actual expiry from access token JWT, fallback to response or 15 min\n const jwtExpiry = getJwtExpiry(result.access_token);\n const expiresAt =\n jwtExpiry ?? (result.expires_in ? Date.now() + result.expires_in * 1000 : Date.now() + 15 * 60 * 1000);\n\n const expiresInSec = Math.round((expiresAt - Date.now()) / 1000);\n\n saveCredentials({\n accessToken: result.access_token,\n expiresAt,\n userId,\n email,\n refreshToken: result.refresh_token,\n });\n\n spinner.stop('Authentication successful!');\n clack.log.success(`Logged in as ${email || userId}`);\n clack.log.info(`Token expires in ${expiresInSec} seconds`);\n\n // Auto-provision staging environment\n const provisioned = await provisionStagingEnvironment(result.access_token);\n if (provisioned) {\n clack.log.success('Staging environment configured automatically');\n } else {\n clack.log.info(chalk.dim('Run `workos env add` to configure an environment manually'));\n }\n\n // Best-effort skill install. Wrapped helper guarantees login never\n // fails on skill errors.\n await installSkillsAfterLogin();\n return;\n }\n\n const errorData = data as AuthErrorResponse;\n if (errorData.error === 'authorization_pending') continue;\n if (errorData.error === 'slow_down') {\n currentInterval += 5000;\n continue;\n }\n\n spinner.stop('Authentication failed');\n clack.log.error(`Authentication error: ${errorData.error}`);\n process.exit(1);\n } catch {\n continue;\n }\n }\n\n spinner.stop('Authentication timed out');\n clack.log.error('Authentication timed out. Please try again.');\n process.exit(1);\n}\n"]}
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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","sourcesContent":["import open from 'opn';\nimport chalk from 'chalk';\nimport clack from '../utils/clack.js';\nimport { saveCredentials, getCredentials, getAccessToken, isTokenExpired, updateTokens } from '../lib/credentials.js';\nimport { getCliAuthClientId, getAuthkitDomain } from '../lib/settings.js';\nimport { refreshAccessToken } from '../lib/token-refresh-client.js';\nimport { logInfo, logError } from '../utils/debug.js';\nimport { fetchStagingCredentials } from '../lib/staging-api.js';\nimport { getConfig, saveConfig } from '../lib/config-store.js';\nimport type { CliConfig } from '../lib/config-store.js';\nimport { formatWorkOSCommand } from '../utils/command-invocation.js';\nimport { autoInstallSkills } from './install-skill.js';\nimport { isJsonMode } from '../utils/output.js';\nimport { requestDeviceCode, pollForToken, DeviceAuthTimeoutError } from '../lib/device-auth.js';\n\n/**\n * Best-effort skill install after a successful auth-login.\n *\n * Mirrors the install.ts hook copy, but wraps `autoInstallSkills` in its own\n * try/catch AND a 30s timeout so a skill install hang (e.g. blocked filesystem\n * call) never blocks login completion. Login already succeeded by the time\n * this runs — the user having a working session is the contract that must hold.\n *\n * Extracted from runLogin so it can be unit-tested without standing up the\n * device-auth polling loop.\n */\nexport const SKILL_INSTALL_TIMEOUT_MS = 30 * 1000;\n\nexport async function installSkillsAfterLogin(): Promise<void> {\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined;\n try {\n const timeout = new Promise<null>((resolve) => {\n timeoutHandle = setTimeout(() => resolve(null), SKILL_INSTALL_TIMEOUT_MS);\n // Don't keep the event loop alive on this timer — process should exit\n // immediately if everything else has resolved.\n timeoutHandle.unref?.();\n });\n const result = await Promise.race([autoInstallSkills(), timeout]);\n if (result && !isJsonMode()) {\n const skillWord = result.skills.length === 1 ? 'skill' : 'skills';\n clack.log.info(`Installed ${result.skills.length} WorkOS ${skillWord} for ${result.agents.join(', ')}.`);\n }\n } catch {\n // Skill install must never fail login.\n } finally {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n }\n}\n\n/**\n * Auto-provision a staging environment after login.\n *\n * Fetches staging credentials using the access token, then saves them\n * as a \"staging\" environment in the config store. Non-fatal — logs a\n * hint on failure instead of throwing.\n */\nexport async function provisionStagingEnvironment(accessToken: string): Promise<boolean> {\n try {\n const staging = await fetchStagingCredentials(accessToken);\n\n const config: CliConfig = getConfig() ?? { environments: {} };\n const isFirst = Object.keys(config.environments).length === 0;\n\n config.environments['staging'] = {\n name: 'staging',\n type: 'sandbox',\n apiKey: staging.apiKey,\n clientId: staging.clientId,\n };\n\n if (isFirst || !config.activeEnvironment) {\n config.activeEnvironment = 'staging';\n }\n\n saveConfig(config);\n logInfo('[login] Staging environment auto-provisioned');\n return true;\n } catch (error) {\n logError('[login] Failed to auto-provision staging environment:', error instanceof Error ? error.message : error);\n return false;\n }\n}\n\nexport async function runLogin(): Promise<void> {\n const clientId = getCliAuthClientId();\n\n // Check if already logged in with valid token\n if (getAccessToken()) {\n const creds = getCredentials();\n console.log(chalk.green(`Already logged in as ${creds?.email ?? 'unknown'}`));\n console.log(chalk.dim(`Run \\`${formatWorkOSCommand('auth logout')}\\` to log out`));\n return;\n }\n\n // Try to refresh if we have expired credentials with a refresh token\n const existingCreds = getCredentials();\n if (existingCreds?.refreshToken && isTokenExpired(existingCreds)) {\n try {\n const authkitDomain = getAuthkitDomain();\n const result = await refreshAccessToken(authkitDomain, clientId);\n if (result.accessToken && result.expiresAt) {\n updateTokens(result.accessToken, result.expiresAt, result.refreshToken);\n logInfo('[login] Session refreshed via refresh token');\n console.log(chalk.green(`Already logged in as ${existingCreds.email ?? 'unknown'}`));\n console.log(chalk.dim(`Run \\`${formatWorkOSCommand('auth logout')}\\` to log out`));\n return;\n }\n } catch {\n // Refresh failed, proceed with fresh login\n }\n }\n\n const authkitDomain = getAuthkitDomain();\n\n clack.log.step('Starting authentication...');\n\n let deviceAuth;\n try {\n deviceAuth = await requestDeviceCode({ clientId, authkitDomain });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n clack.log.error(`Failed to start authentication: ${msg}`);\n process.exit(1);\n }\n\n clack.log.info(`\\nOpen this URL in your browser:\\n`);\n console.log(` ${deviceAuth.verification_uri}`);\n console.log(`\\nEnter code: ${deviceAuth.user_code}\\n`);\n\n try {\n open(deviceAuth.verification_uri_complete);\n clack.log.info('Browser opened automatically');\n } catch {\n // User can open manually\n }\n\n const spinner = clack.spinner();\n spinner.start('Waiting for authentication...');\n\n try {\n const result = await pollForToken(deviceAuth.device_code, {\n clientId,\n authkitDomain,\n interval: deviceAuth.interval,\n });\n\n const expiresInSec = Math.round((result.expiresAt - Date.now()) / 1000);\n\n saveCredentials({\n accessToken: result.accessToken,\n expiresAt: result.expiresAt,\n userId: result.userId,\n email: result.email,\n refreshToken: result.refreshToken,\n });\n\n spinner.stop('Authentication successful!');\n clack.log.success(`Logged in as ${result.email || result.userId}`);\n clack.log.info(`Token expires in ${expiresInSec} seconds`);\n\n const provisioned = await provisionStagingEnvironment(result.accessToken);\n if (provisioned) {\n clack.log.success('Staging environment configured automatically');\n } else {\n clack.log.info(chalk.dim('Run `workos env add` to configure an environment manually'));\n }\n\n await installSkillsAfterLogin();\n } catch (error) {\n if (error instanceof DeviceAuthTimeoutError) {\n spinner.stop('Authentication timed out');\n clack.log.error('Authentication timed out. Please try again.');\n } else {\n spinner.stop('Authentication failed');\n const msg = error instanceof Error ? error.message : String(error);\n clack.log.error(`Authentication error: ${msg}`);\n }\n process.exit(1);\n }\n}\n"]}
@@ -23,7 +23,26 @@ export async function runWebhookList(apiKey, baseUrl) {
23
23
  console.log('No webhook endpoints found.');
24
24
  return;
25
25
  }
26
- const rows = result.data.map((ep) => [ep.id, ep.url, ep.events.join(', '), ep.created_at]);
26
+ const maxEventsChars = 60;
27
+ const rows = result.data.map((ep) => {
28
+ const joined = ep.events.join(', ');
29
+ if (joined.length <= maxEventsChars) {
30
+ return [ep.id, ep.endpoint_url, joined, ep.created_at];
31
+ }
32
+ // Always include the first event so the cell isn't content-free when a single event name exceeds the budget.
33
+ const visible = [ep.events[0]];
34
+ let len = ep.events[0].length;
35
+ for (let i = 1; i < ep.events.length; i++) {
36
+ const next = len + 2 + ep.events[i].length;
37
+ if (next > maxEventsChars)
38
+ break;
39
+ visible.push(ep.events[i]);
40
+ len = next;
41
+ }
42
+ const hidden = ep.events.length - visible.length;
43
+ const suffix = hidden > 0 ? `, … (+${hidden} more)` : '';
44
+ return [ep.id, ep.endpoint_url, `${visible.join(', ')}${suffix}`, ep.created_at];
45
+ });
27
46
  console.log(formatTable([{ header: 'ID' }, { header: 'URL' }, { header: 'Events' }, { header: 'Created' }], rows));
28
47
  const { before, after } = result.list_metadata;
29
48
  if (before && after) {
@@ -1 +1 @@
1
- {"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/commands/webhook.ts"],"names":[],"mappings":"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","sourcesContent":["import chalk from 'chalk';\nimport { createWorkOSClient } from '../lib/workos-client.js';\nimport { formatTable } from '../utils/table.js';\nimport { outputJson, outputSuccess, isJsonMode } from '../utils/output.js';\nimport { createApiErrorHandler } from '../lib/api-error-handler.js';\n\nconst handleApiError = createApiErrorHandler('Webhook');\n\nexport async function runWebhookList(apiKey: string, baseUrl?: string): Promise<void> {\n const client = createWorkOSClient(apiKey, baseUrl);\n\n try {\n const result = await client.webhooks.list();\n\n if (isJsonMode()) {\n // Normalize snake_case list_metadata to camelCase for consistent CLI output\n outputJson({\n data: result.data,\n listMetadata: {\n before: result.list_metadata.before,\n after: result.list_metadata.after,\n },\n });\n return;\n }\n\n if (result.data.length === 0) {\n console.log('No webhook endpoints found.');\n return;\n }\n\n const rows = result.data.map((ep) => [ep.id, ep.url, ep.events.join(', '), ep.created_at]);\n\n console.log(formatTable([{ header: 'ID' }, { header: 'URL' }, { header: 'Events' }, { header: 'Created' }], rows));\n\n const { before, after } = result.list_metadata;\n if (before && after) {\n console.log(chalk.dim(`Before: ${before} After: ${after}`));\n } else if (before) {\n console.log(chalk.dim(`Before: ${before}`));\n } else if (after) {\n console.log(chalk.dim(`After: ${after}`));\n }\n } catch (error) {\n handleApiError(error);\n }\n}\n\nexport async function runWebhookCreate(url: string, events: string[], apiKey: string, baseUrl?: string): Promise<void> {\n const client = createWorkOSClient(apiKey, baseUrl);\n\n try {\n const endpoint = await client.webhooks.create(url, events);\n\n if (isJsonMode()) {\n outputJson({ status: 'ok', message: 'Created webhook endpoint', data: endpoint });\n return;\n }\n\n console.log(chalk.green('Created webhook endpoint'));\n console.log(JSON.stringify(endpoint, null, 2));\n if (endpoint.secret) {\n console.log('');\n console.log(chalk.yellow('Signing secret: ') + endpoint.secret);\n console.log(chalk.yellow('Save this secret now — it will not be shown again.'));\n }\n } catch (error) {\n handleApiError(error);\n }\n}\n\nexport async function runWebhookDelete(id: string, apiKey: string, baseUrl?: string): Promise<void> {\n const client = createWorkOSClient(apiKey, baseUrl);\n\n try {\n await client.webhooks.delete(id);\n outputSuccess('Deleted webhook endpoint', { id });\n } catch (error) {\n handleApiError(error);\n }\n}\n"]}
1
+ {"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/commands/webhook.ts"],"names":[],"mappings":"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","sourcesContent":["import chalk from 'chalk';\nimport { createWorkOSClient } from '../lib/workos-client.js';\nimport { formatTable } from '../utils/table.js';\nimport { outputJson, outputSuccess, isJsonMode } from '../utils/output.js';\nimport { createApiErrorHandler } from '../lib/api-error-handler.js';\n\nconst handleApiError = createApiErrorHandler('Webhook');\n\nexport async function runWebhookList(apiKey: string, baseUrl?: string): Promise<void> {\n const client = createWorkOSClient(apiKey, baseUrl);\n\n try {\n const result = await client.webhooks.list();\n\n if (isJsonMode()) {\n // Normalize snake_case list_metadata to camelCase for consistent CLI output\n outputJson({\n data: result.data,\n listMetadata: {\n before: result.list_metadata.before,\n after: result.list_metadata.after,\n },\n });\n return;\n }\n\n if (result.data.length === 0) {\n console.log('No webhook endpoints found.');\n return;\n }\n\n const maxEventsChars = 60;\n const rows = result.data.map((ep) => {\n const joined = ep.events.join(', ');\n if (joined.length <= maxEventsChars) {\n return [ep.id, ep.endpoint_url, joined, ep.created_at];\n }\n // Always include the first event so the cell isn't content-free when a single event name exceeds the budget.\n const visible: string[] = [ep.events[0]];\n let len = ep.events[0].length;\n for (let i = 1; i < ep.events.length; i++) {\n const next = len + 2 + ep.events[i].length;\n if (next > maxEventsChars) break;\n visible.push(ep.events[i]);\n len = next;\n }\n const hidden = ep.events.length - visible.length;\n const suffix = hidden > 0 ? `, … (+${hidden} more)` : '';\n return [ep.id, ep.endpoint_url, `${visible.join(', ')}${suffix}`, ep.created_at];\n });\n\n console.log(formatTable([{ header: 'ID' }, { header: 'URL' }, { header: 'Events' }, { header: 'Created' }], rows));\n\n const { before, after } = result.list_metadata;\n if (before && after) {\n console.log(chalk.dim(`Before: ${before} After: ${after}`));\n } else if (before) {\n console.log(chalk.dim(`Before: ${before}`));\n } else if (after) {\n console.log(chalk.dim(`After: ${after}`));\n }\n } catch (error) {\n handleApiError(error);\n }\n}\n\nexport async function runWebhookCreate(url: string, events: string[], apiKey: string, baseUrl?: string): Promise<void> {\n const client = createWorkOSClient(apiKey, baseUrl);\n\n try {\n const endpoint = await client.webhooks.create(url, events);\n\n if (isJsonMode()) {\n outputJson({ status: 'ok', message: 'Created webhook endpoint', data: endpoint });\n return;\n }\n\n console.log(chalk.green('Created webhook endpoint'));\n console.log(JSON.stringify(endpoint, null, 2));\n if (endpoint.secret) {\n console.log('');\n console.log(chalk.yellow('Signing secret: ') + endpoint.secret);\n console.log(chalk.yellow('Save this secret now — it will not be shown again.'));\n }\n } catch (error) {\n handleApiError(error);\n }\n}\n\nexport async function runWebhookDelete(id: string, apiKey: string, baseUrl?: string): Promise<void> {\n const client = createWorkOSClient(apiKey, baseUrl);\n\n try {\n await client.webhooks.delete(id);\n outputSuccess('Deleted webhook endpoint', { id });\n } catch (error) {\n handleApiError(error);\n }\n}\n"]}
@@ -352,7 +352,7 @@ export interface WorkOSEvent extends Entity {
352
352
  }
353
353
  export interface WorkOSWebhookEndpoint extends Entity {
354
354
  object: 'webhook_endpoint';
355
- url: string;
355
+ endpoint_url: string;
356
356
  secret: string;
357
357
  enabled: boolean;
358
358
  events: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"entities.js","sourceRoot":"","sources":["../../../src/emulate/workos/entities.ts"],"names":[],"mappings":"","sourcesContent":["import type { Entity } from '../core/index.js';\n\nexport interface WorkOSOrganization extends Entity {\n object: 'organization';\n name: string;\n external_id: string | null;\n metadata: Record<string, string>;\n stripe_customer_id: string | null;\n}\n\nexport interface WorkOSOrganizationDomain extends Entity {\n object: 'organization_domain';\n organization_id: string;\n domain: string;\n state: 'verified' | 'pending';\n verification_strategy: 'manual' | 'dns';\n verification_token: string;\n verification_prefix: string;\n}\n\nexport interface WorkOSOrganizationMembership extends Entity {\n object: 'organization_membership';\n organization_id: string;\n user_id: string;\n role: { slug: string };\n status: 'active' | 'inactive' | 'pending';\n external_id: string | null;\n metadata: Record<string, string>;\n}\n\nexport interface WorkOSUser extends Entity {\n object: 'user';\n email: string;\n first_name: string | null;\n last_name: string | null;\n email_verified: boolean;\n profile_picture_url: string | null;\n last_sign_in_at: string | null;\n external_id: string | null;\n metadata: Record<string, string>;\n locale: string | null;\n password_hash: string | null;\n impersonator: { email: string; reason: string } | null;\n}\n\nexport interface WorkOSSession extends Entity {\n object: 'session';\n user_id: string;\n organization_id: string | null;\n ip_address: string | null;\n user_agent: string | null;\n}\n\nexport interface WorkOSEmailVerification extends Entity {\n object: 'email_verification';\n user_id: string;\n email: string;\n code: string;\n expires_at: string;\n}\n\nexport interface WorkOSPasswordReset extends Entity {\n object: 'password_reset';\n user_id: string;\n email: string;\n token: string;\n expires_at: string;\n}\n\nexport interface WorkOSMagicAuth extends Entity {\n object: 'magic_auth';\n user_id: string;\n email: string;\n code: string;\n expires_at: string;\n}\n\nexport interface WorkOSAuthenticationFactor extends Entity {\n object: 'authentication_factor';\n user_id: string;\n type: 'totp';\n totp: {\n issuer: string;\n user: string;\n uri: string;\n };\n}\n\nexport interface WorkOSAuthorizationCode extends Entity {\n user_id: string;\n organization_id: string | null;\n code: string;\n redirect_uri: string;\n expires_at: string;\n code_challenge: string | null;\n code_challenge_method: string | null;\n}\n\nexport interface WorkOSIdentity extends Entity {\n object: 'identity';\n user_id: string;\n provider: string;\n provider_id: string;\n type: 'OAuth';\n}\n\nexport type WorkOSConnectionType =\n | 'ADFSSAML'\n | 'AzureSAML'\n | 'GenericOIDC'\n | 'GenericSAML'\n | 'GoogleOAuth'\n | 'GoogleSAML'\n | 'OktaSAML'\n | 'OneLoginSAML'\n | 'PingFederateSAML'\n | 'PingOneSAML'\n | 'GitHubOAuth'\n | 'MicrosoftOAuth'\n | 'AppleOAuth';\n\nexport interface WorkOSConnectionDomain {\n object: 'connection_domain';\n id: string;\n domain: string;\n}\n\nexport interface WorkOSConnection extends Entity {\n object: 'connection';\n organization_id: string;\n connection_type: WorkOSConnectionType;\n name: string;\n state: 'active' | 'inactive' | 'validating';\n domains: WorkOSConnectionDomain[];\n}\n\nexport interface WorkOSSSOProfile extends Entity {\n object: 'profile';\n connection_id: string;\n connection_type: WorkOSConnectionType;\n organization_id: string;\n idp_id: string;\n email: string;\n first_name: string | null;\n last_name: string | null;\n groups: string[];\n raw_attributes: Record<string, unknown>;\n}\n\nexport interface WorkOSSSOAuthorization extends Entity {\n code: string;\n connection_id: string;\n organization_id: string;\n profile_id: string;\n redirect_uri: string;\n state: string | null;\n expires_at: string;\n}\n\nexport interface WorkOSInvitation extends Entity {\n object: 'invitation';\n email: string;\n state: 'pending' | 'accepted' | 'expired' | 'revoked';\n token: string;\n accept_invitation_url: string;\n organization_id: string | null;\n inviter_user_id: string | null;\n role_slug: string | null;\n expires_at: string;\n}\n\nexport interface WorkOSRedirectUri extends Entity {\n object: 'redirect_uri';\n uri: string;\n}\n\nexport interface WorkOSCorsOrigin extends Entity {\n object: 'cors_origin';\n origin: string;\n}\n\nexport interface WorkOSAuthorizedApplication extends Entity {\n object: 'authorized_application';\n user_id: string;\n name: string;\n redirect_uri: string;\n}\n\nexport interface WorkOSConnectedAccount extends Entity {\n object: 'connected_account';\n user_id: string;\n provider: string;\n provider_id: string;\n}\n\nexport type PipeProvider = 'github' | 'slack' | 'google' | 'salesforce';\nexport type PipeConnectionStatus = 'connected' | 'disconnected' | 'requires_reauth';\n\nexport interface WorkOSPipeConnection extends Entity {\n object: 'pipe_connection';\n user_id: string;\n provider: PipeProvider;\n scopes: string[];\n status: PipeConnectionStatus;\n external_account_id: string | null;\n}\n\nexport interface WorkOSRefreshToken extends Entity {\n token: string;\n user_id: string;\n organization_id: string | null;\n session_id: string;\n expires_at: string;\n}\n\nexport interface WorkOSAuthenticationChallenge extends Entity {\n object: 'authentication_challenge';\n user_id: string;\n factor_id: string;\n expires_at: string;\n code: string | null;\n}\n\nexport interface WorkOSDeviceAuthorization extends Entity {\n device_code: string;\n user_code: string;\n user_id: string | null;\n client_id: string;\n expires_at: string;\n interval: number;\n}\n\nexport interface WorkOSRole extends Entity {\n object: 'role';\n slug: string;\n name: string;\n description: string | null;\n type: 'EnvironmentRole' | 'OrganizationRole';\n organization_id: string | null;\n is_default_role: boolean;\n priority: number;\n}\n\nexport interface WorkOSPermission extends Entity {\n object: 'permission';\n slug: string;\n name: string;\n description: string | null;\n}\n\nexport interface WorkOSRolePermission extends Entity {\n role_id: string;\n permission_id: string;\n}\n\nexport interface WorkOSAuthorizationResource extends Entity {\n object: 'authorization_resource';\n resource_type_slug: string;\n external_id: string;\n organization_id: string;\n metadata: Record<string, string>;\n}\n\nexport interface WorkOSRoleAssignment extends Entity {\n object: 'role_assignment';\n organization_membership_id: string;\n role_id: string;\n}\n\nexport interface WorkOSDirectory extends Entity {\n object: 'directory';\n name: string;\n organization_id: string | null;\n domain: string | null;\n type: string;\n state: 'linked' | 'unlinked' | 'deleting' | 'invalid_credentials';\n external_key: string | null;\n}\n\nexport interface WorkOSDirectoryUser extends Entity {\n object: 'directory_user';\n directory_id: string;\n organization_id: string | null;\n idp_id: string;\n first_name: string | null;\n last_name: string | null;\n email: string | null;\n username: string | null;\n state: 'active' | 'inactive';\n role: { slug: string } | null;\n custom_attributes: Record<string, unknown>;\n raw_attributes: Record<string, unknown>;\n groups: Array<{ object: 'directory_group'; id: string; name: string }>;\n}\n\nexport interface WorkOSDirectoryGroup extends Entity {\n object: 'directory_group';\n directory_id: string;\n organization_id: string | null;\n idp_id: string;\n name: string;\n raw_attributes: Record<string, unknown>;\n}\n\nexport interface WorkOSAuditLogAction extends Entity {\n object: 'audit_log_action';\n name: string;\n description: string | null;\n condition: string | null;\n}\n\nexport interface WorkOSAuditLogEvent extends Entity {\n object: 'audit_log_event';\n organization_id: string;\n action: { name: string; type: string; id: string };\n actor: Record<string, unknown>;\n targets: Array<Record<string, unknown>>;\n metadata: Record<string, unknown> | null;\n occurred_at: string;\n}\n\nexport interface WorkOSAuditLogExport extends Entity {\n object: 'audit_log_export';\n organization_id: string;\n state: 'pending' | 'ready' | 'error';\n url: string | null;\n filters: Record<string, unknown>;\n}\n\nexport interface WorkOSFeatureFlag extends Entity {\n object: 'feature_flag';\n slug: string;\n name: string;\n description: string | null;\n type: 'boolean' | 'string' | 'number';\n default_value: unknown;\n enabled: boolean;\n}\n\nexport interface WorkOSFlagTarget extends Entity {\n object: 'flag_target';\n flag_slug: string;\n resource_id: string;\n resource_type: string;\n value: unknown;\n}\n\nexport interface WorkOSConnectApplication extends Entity {\n object: 'connect_application';\n name: string;\n redirect_uris: string[];\n client_id: string;\n logo_url: string | null;\n}\n\nexport interface WorkOSClientSecret extends Entity {\n object: 'client_secret';\n application_id: string;\n value: string;\n last_four: string;\n}\n\nexport interface WorkOSDataIntegrationAuth extends Entity {\n slug: string;\n code: string;\n redirect_uri: string;\n state: string | null;\n expires_at: string;\n}\n\nexport interface WorkOSRadarAttempt extends Entity {\n object: 'radar_attempt';\n user_id: string | null;\n ip_address: string;\n user_agent: string | null;\n verdict: 'allow' | 'deny' | 'challenge';\n signals: Array<{ type: string; confidence: number }>;\n}\n\nexport interface WorkOSApiKey extends Entity {\n object: 'api_key';\n name: string;\n key: string;\n environment: string;\n}\n\nexport interface WorkOSEvent extends Entity {\n object: 'event';\n event: string;\n data: Record<string, unknown>;\n environment_id: string | null;\n}\n\nexport interface WorkOSWebhookEndpoint extends Entity {\n object: 'webhook_endpoint';\n url: string;\n secret: string;\n enabled: boolean;\n events: string[];\n description: string | null;\n}\n"]}
1
+ {"version":3,"file":"entities.js","sourceRoot":"","sources":["../../../src/emulate/workos/entities.ts"],"names":[],"mappings":"","sourcesContent":["import type { Entity } from '../core/index.js';\n\nexport interface WorkOSOrganization extends Entity {\n object: 'organization';\n name: string;\n external_id: string | null;\n metadata: Record<string, string>;\n stripe_customer_id: string | null;\n}\n\nexport interface WorkOSOrganizationDomain extends Entity {\n object: 'organization_domain';\n organization_id: string;\n domain: string;\n state: 'verified' | 'pending';\n verification_strategy: 'manual' | 'dns';\n verification_token: string;\n verification_prefix: string;\n}\n\nexport interface WorkOSOrganizationMembership extends Entity {\n object: 'organization_membership';\n organization_id: string;\n user_id: string;\n role: { slug: string };\n status: 'active' | 'inactive' | 'pending';\n external_id: string | null;\n metadata: Record<string, string>;\n}\n\nexport interface WorkOSUser extends Entity {\n object: 'user';\n email: string;\n first_name: string | null;\n last_name: string | null;\n email_verified: boolean;\n profile_picture_url: string | null;\n last_sign_in_at: string | null;\n external_id: string | null;\n metadata: Record<string, string>;\n locale: string | null;\n password_hash: string | null;\n impersonator: { email: string; reason: string } | null;\n}\n\nexport interface WorkOSSession extends Entity {\n object: 'session';\n user_id: string;\n organization_id: string | null;\n ip_address: string | null;\n user_agent: string | null;\n}\n\nexport interface WorkOSEmailVerification extends Entity {\n object: 'email_verification';\n user_id: string;\n email: string;\n code: string;\n expires_at: string;\n}\n\nexport interface WorkOSPasswordReset extends Entity {\n object: 'password_reset';\n user_id: string;\n email: string;\n token: string;\n expires_at: string;\n}\n\nexport interface WorkOSMagicAuth extends Entity {\n object: 'magic_auth';\n user_id: string;\n email: string;\n code: string;\n expires_at: string;\n}\n\nexport interface WorkOSAuthenticationFactor extends Entity {\n object: 'authentication_factor';\n user_id: string;\n type: 'totp';\n totp: {\n issuer: string;\n user: string;\n uri: string;\n };\n}\n\nexport interface WorkOSAuthorizationCode extends Entity {\n user_id: string;\n organization_id: string | null;\n code: string;\n redirect_uri: string;\n expires_at: string;\n code_challenge: string | null;\n code_challenge_method: string | null;\n}\n\nexport interface WorkOSIdentity extends Entity {\n object: 'identity';\n user_id: string;\n provider: string;\n provider_id: string;\n type: 'OAuth';\n}\n\nexport type WorkOSConnectionType =\n | 'ADFSSAML'\n | 'AzureSAML'\n | 'GenericOIDC'\n | 'GenericSAML'\n | 'GoogleOAuth'\n | 'GoogleSAML'\n | 'OktaSAML'\n | 'OneLoginSAML'\n | 'PingFederateSAML'\n | 'PingOneSAML'\n | 'GitHubOAuth'\n | 'MicrosoftOAuth'\n | 'AppleOAuth';\n\nexport interface WorkOSConnectionDomain {\n object: 'connection_domain';\n id: string;\n domain: string;\n}\n\nexport interface WorkOSConnection extends Entity {\n object: 'connection';\n organization_id: string;\n connection_type: WorkOSConnectionType;\n name: string;\n state: 'active' | 'inactive' | 'validating';\n domains: WorkOSConnectionDomain[];\n}\n\nexport interface WorkOSSSOProfile extends Entity {\n object: 'profile';\n connection_id: string;\n connection_type: WorkOSConnectionType;\n organization_id: string;\n idp_id: string;\n email: string;\n first_name: string | null;\n last_name: string | null;\n groups: string[];\n raw_attributes: Record<string, unknown>;\n}\n\nexport interface WorkOSSSOAuthorization extends Entity {\n code: string;\n connection_id: string;\n organization_id: string;\n profile_id: string;\n redirect_uri: string;\n state: string | null;\n expires_at: string;\n}\n\nexport interface WorkOSInvitation extends Entity {\n object: 'invitation';\n email: string;\n state: 'pending' | 'accepted' | 'expired' | 'revoked';\n token: string;\n accept_invitation_url: string;\n organization_id: string | null;\n inviter_user_id: string | null;\n role_slug: string | null;\n expires_at: string;\n}\n\nexport interface WorkOSRedirectUri extends Entity {\n object: 'redirect_uri';\n uri: string;\n}\n\nexport interface WorkOSCorsOrigin extends Entity {\n object: 'cors_origin';\n origin: string;\n}\n\nexport interface WorkOSAuthorizedApplication extends Entity {\n object: 'authorized_application';\n user_id: string;\n name: string;\n redirect_uri: string;\n}\n\nexport interface WorkOSConnectedAccount extends Entity {\n object: 'connected_account';\n user_id: string;\n provider: string;\n provider_id: string;\n}\n\nexport type PipeProvider = 'github' | 'slack' | 'google' | 'salesforce';\nexport type PipeConnectionStatus = 'connected' | 'disconnected' | 'requires_reauth';\n\nexport interface WorkOSPipeConnection extends Entity {\n object: 'pipe_connection';\n user_id: string;\n provider: PipeProvider;\n scopes: string[];\n status: PipeConnectionStatus;\n external_account_id: string | null;\n}\n\nexport interface WorkOSRefreshToken extends Entity {\n token: string;\n user_id: string;\n organization_id: string | null;\n session_id: string;\n expires_at: string;\n}\n\nexport interface WorkOSAuthenticationChallenge extends Entity {\n object: 'authentication_challenge';\n user_id: string;\n factor_id: string;\n expires_at: string;\n code: string | null;\n}\n\nexport interface WorkOSDeviceAuthorization extends Entity {\n device_code: string;\n user_code: string;\n user_id: string | null;\n client_id: string;\n expires_at: string;\n interval: number;\n}\n\nexport interface WorkOSRole extends Entity {\n object: 'role';\n slug: string;\n name: string;\n description: string | null;\n type: 'EnvironmentRole' | 'OrganizationRole';\n organization_id: string | null;\n is_default_role: boolean;\n priority: number;\n}\n\nexport interface WorkOSPermission extends Entity {\n object: 'permission';\n slug: string;\n name: string;\n description: string | null;\n}\n\nexport interface WorkOSRolePermission extends Entity {\n role_id: string;\n permission_id: string;\n}\n\nexport interface WorkOSAuthorizationResource extends Entity {\n object: 'authorization_resource';\n resource_type_slug: string;\n external_id: string;\n organization_id: string;\n metadata: Record<string, string>;\n}\n\nexport interface WorkOSRoleAssignment extends Entity {\n object: 'role_assignment';\n organization_membership_id: string;\n role_id: string;\n}\n\nexport interface WorkOSDirectory extends Entity {\n object: 'directory';\n name: string;\n organization_id: string | null;\n domain: string | null;\n type: string;\n state: 'linked' | 'unlinked' | 'deleting' | 'invalid_credentials';\n external_key: string | null;\n}\n\nexport interface WorkOSDirectoryUser extends Entity {\n object: 'directory_user';\n directory_id: string;\n organization_id: string | null;\n idp_id: string;\n first_name: string | null;\n last_name: string | null;\n email: string | null;\n username: string | null;\n state: 'active' | 'inactive';\n role: { slug: string } | null;\n custom_attributes: Record<string, unknown>;\n raw_attributes: Record<string, unknown>;\n groups: Array<{ object: 'directory_group'; id: string; name: string }>;\n}\n\nexport interface WorkOSDirectoryGroup extends Entity {\n object: 'directory_group';\n directory_id: string;\n organization_id: string | null;\n idp_id: string;\n name: string;\n raw_attributes: Record<string, unknown>;\n}\n\nexport interface WorkOSAuditLogAction extends Entity {\n object: 'audit_log_action';\n name: string;\n description: string | null;\n condition: string | null;\n}\n\nexport interface WorkOSAuditLogEvent extends Entity {\n object: 'audit_log_event';\n organization_id: string;\n action: { name: string; type: string; id: string };\n actor: Record<string, unknown>;\n targets: Array<Record<string, unknown>>;\n metadata: Record<string, unknown> | null;\n occurred_at: string;\n}\n\nexport interface WorkOSAuditLogExport extends Entity {\n object: 'audit_log_export';\n organization_id: string;\n state: 'pending' | 'ready' | 'error';\n url: string | null;\n filters: Record<string, unknown>;\n}\n\nexport interface WorkOSFeatureFlag extends Entity {\n object: 'feature_flag';\n slug: string;\n name: string;\n description: string | null;\n type: 'boolean' | 'string' | 'number';\n default_value: unknown;\n enabled: boolean;\n}\n\nexport interface WorkOSFlagTarget extends Entity {\n object: 'flag_target';\n flag_slug: string;\n resource_id: string;\n resource_type: string;\n value: unknown;\n}\n\nexport interface WorkOSConnectApplication extends Entity {\n object: 'connect_application';\n name: string;\n redirect_uris: string[];\n client_id: string;\n logo_url: string | null;\n}\n\nexport interface WorkOSClientSecret extends Entity {\n object: 'client_secret';\n application_id: string;\n value: string;\n last_four: string;\n}\n\nexport interface WorkOSDataIntegrationAuth extends Entity {\n slug: string;\n code: string;\n redirect_uri: string;\n state: string | null;\n expires_at: string;\n}\n\nexport interface WorkOSRadarAttempt extends Entity {\n object: 'radar_attempt';\n user_id: string | null;\n ip_address: string;\n user_agent: string | null;\n verdict: 'allow' | 'deny' | 'challenge';\n signals: Array<{ type: string; confidence: number }>;\n}\n\nexport interface WorkOSApiKey extends Entity {\n object: 'api_key';\n name: string;\n key: string;\n environment: string;\n}\n\nexport interface WorkOSEvent extends Entity {\n object: 'event';\n event: string;\n data: Record<string, unknown>;\n environment_id: string | null;\n}\n\nexport interface WorkOSWebhookEndpoint extends Entity {\n object: 'webhook_endpoint';\n endpoint_url: string;\n secret: string;\n enabled: boolean;\n events: string[];\n description: string | null;\n}\n"]}
@@ -56,7 +56,7 @@ export class EventBus {
56
56
  created_at: event.created_at,
57
57
  });
58
58
  const signature = signWebhookPayload(body, endpoint.secret);
59
- await fetch(endpoint.url, {
59
+ await fetch(endpoint.endpoint_url, {
60
60
  method: 'POST',
61
61
  headers: {
62
62
  'Content-Type': 'application/json',
@@ -1 +1 @@
1
- {"version":3,"file":"event-bus.js","sourceRoot":"","sources":["../../../src/emulate/workos/event-bus.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Store } from '../core/index.js';\nimport { getWorkOSStore } from './store.js';\nimport type { WorkOSWebhookEndpoint, WorkOSEvent } from './entities.js';\nimport { signWebhookPayload } from './webhook-signer.js';\nimport type { WorkOSEventName } from './constants.js';\n\nexport interface EventPayload {\n event: WorkOSEventName | string;\n data: Record<string, unknown>;\n environment_id?: string;\n}\n\nexport class EventBus {\n private endpointsByEvent = new Map<string, Set<string>>();\n private catchAllEndpoints = new Set<string>();\n\n constructor(private store: Store) {}\n\n /** Rebuild the event-type index. Auto-called via collection hooks; call manually only in tests. */\n rebuildIndex(): void {\n this.endpointsByEvent.clear();\n this.catchAllEndpoints.clear();\n const ws = getWorkOSStore(this.store);\n for (const ep of ws.webhookEndpoints.all()) {\n if (!ep.enabled) continue;\n if (ep.events.length === 0) {\n this.catchAllEndpoints.add(ep.id);\n } else {\n for (const evt of ep.events) {\n const set = this.endpointsByEvent.get(evt) ?? new Set();\n set.add(ep.id);\n this.endpointsByEvent.set(evt, set);\n }\n }\n }\n }\n\n emit(payload: EventPayload): void {\n const ws = getWorkOSStore(this.store);\n\n const event = ws.events.insert({\n object: 'event',\n event: payload.event,\n data: payload.data,\n environment_id: payload.environment_id ?? null,\n });\n\n // Pre-filtered: only endpoints that care about this event\n const targetIds = new Set(this.catchAllEndpoints);\n const eventSpecific = this.endpointsByEvent.get(payload.event);\n if (eventSpecific) {\n for (const id of eventSpecific) targetIds.add(id);\n }\n\n for (const id of targetIds) {\n const endpoint = ws.webhookEndpoints.get(id);\n if (endpoint) this.deliver(endpoint, event).catch(() => {});\n }\n }\n\n private async deliver(endpoint: WorkOSWebhookEndpoint, event: WorkOSEvent): Promise<void> {\n const body = JSON.stringify({\n id: event.id,\n event: event.event,\n data: event.data,\n created_at: event.created_at,\n });\n\n const signature = signWebhookPayload(body, endpoint.secret);\n\n await fetch(endpoint.url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'WorkOS-Signature': signature,\n },\n body,\n signal: AbortSignal.timeout(5000),\n });\n }\n}\n"]}
1
+ {"version":3,"file":"event-bus.js","sourceRoot":"","sources":["../../../src/emulate/workos/event-bus.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Store } from '../core/index.js';\nimport { getWorkOSStore } from './store.js';\nimport type { WorkOSWebhookEndpoint, WorkOSEvent } from './entities.js';\nimport { signWebhookPayload } from './webhook-signer.js';\nimport type { WorkOSEventName } from './constants.js';\n\nexport interface EventPayload {\n event: WorkOSEventName | string;\n data: Record<string, unknown>;\n environment_id?: string;\n}\n\nexport class EventBus {\n private endpointsByEvent = new Map<string, Set<string>>();\n private catchAllEndpoints = new Set<string>();\n\n constructor(private store: Store) {}\n\n /** Rebuild the event-type index. Auto-called via collection hooks; call manually only in tests. */\n rebuildIndex(): void {\n this.endpointsByEvent.clear();\n this.catchAllEndpoints.clear();\n const ws = getWorkOSStore(this.store);\n for (const ep of ws.webhookEndpoints.all()) {\n if (!ep.enabled) continue;\n if (ep.events.length === 0) {\n this.catchAllEndpoints.add(ep.id);\n } else {\n for (const evt of ep.events) {\n const set = this.endpointsByEvent.get(evt) ?? new Set();\n set.add(ep.id);\n this.endpointsByEvent.set(evt, set);\n }\n }\n }\n }\n\n emit(payload: EventPayload): void {\n const ws = getWorkOSStore(this.store);\n\n const event = ws.events.insert({\n object: 'event',\n event: payload.event,\n data: payload.data,\n environment_id: payload.environment_id ?? null,\n });\n\n // Pre-filtered: only endpoints that care about this event\n const targetIds = new Set(this.catchAllEndpoints);\n const eventSpecific = this.endpointsByEvent.get(payload.event);\n if (eventSpecific) {\n for (const id of eventSpecific) targetIds.add(id);\n }\n\n for (const id of targetIds) {\n const endpoint = ws.webhookEndpoints.get(id);\n if (endpoint) this.deliver(endpoint, event).catch(() => {});\n }\n }\n\n private async deliver(endpoint: WorkOSWebhookEndpoint, event: WorkOSEvent): Promise<void> {\n const body = JSON.stringify({\n id: event.id,\n event: event.event,\n data: event.data,\n created_at: event.created_at,\n });\n\n const signature = signWebhookPayload(body, endpoint.secret);\n\n await fetch(endpoint.endpoint_url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'WorkOS-Signature': signature,\n },\n body,\n signal: AbortSignal.timeout(5000),\n });\n }\n}\n"]}
@@ -190,7 +190,7 @@ export function formatWebhookEndpoint(ep, opts) {
190
190
  return {
191
191
  object: 'webhook_endpoint',
192
192
  id: ep.id,
193
- url: ep.url,
193
+ endpoint_url: ep.endpoint_url,
194
194
  secret: opts?.includeSecret ? ep.secret : `${ep.secret.slice(0, 8)}****`,
195
195
  enabled: ep.enabled,
196
196
  events: ep.events,