workos 0.11.2 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +165 -6
- package/dist/bin.js +22 -1
- package/dist/bin.js.map +1 -1
- package/dist/check-coverage.ts +237 -0
- package/dist/commands/debug.js +0 -1
- package/dist/commands/debug.js.map +1 -1
- package/dist/commands/dev.d.ts +23 -0
- package/dist/commands/dev.js +139 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/emulate.d.ts +6 -0
- package/dist/commands/emulate.js +64 -0
- package/dist/commands/emulate.js.map +1 -0
- package/dist/commands/login.js +0 -4
- package/dist/commands/login.js.map +1 -1
- package/dist/emulate/core/id.d.ts +48 -0
- package/dist/emulate/core/id.js +73 -0
- package/dist/emulate/core/id.js.map +1 -0
- package/dist/emulate/core/index.d.ts +8 -0
- package/dist/emulate/core/index.js +8 -0
- package/dist/emulate/core/index.js.map +1 -0
- package/dist/emulate/core/jwt.d.ts +28 -0
- package/dist/emulate/core/jwt.js +78 -0
- package/dist/emulate/core/jwt.js.map +1 -0
- package/dist/emulate/core/middleware/auth.d.ts +15 -0
- package/dist/emulate/core/middleware/auth.js +17 -0
- package/dist/emulate/core/middleware/auth.js.map +1 -0
- package/dist/emulate/core/middleware/error-handler.d.ts +22 -0
- package/dist/emulate/core/middleware/error-handler.js +72 -0
- package/dist/emulate/core/middleware/error-handler.js.map +1 -0
- package/dist/emulate/core/pagination.d.ts +27 -0
- package/dist/emulate/core/pagination.js +43 -0
- package/dist/emulate/core/pagination.js.map +1 -0
- package/dist/emulate/core/plugin.d.ts +15 -0
- package/dist/emulate/core/plugin.js +2 -0
- package/dist/emulate/core/plugin.js.map +1 -0
- package/dist/emulate/core/server.d.ts +17 -0
- package/dist/emulate/core/server.js +90 -0
- package/dist/emulate/core/server.js.map +1 -0
- package/dist/emulate/core/store.d.ts +44 -0
- package/dist/emulate/core/store.js +169 -0
- package/dist/emulate/core/store.js.map +1 -0
- package/dist/emulate/index.d.ts +25 -0
- package/dist/emulate/index.js +47 -0
- package/dist/emulate/index.js.map +1 -0
- package/dist/emulate/workos/constants.d.ts +56 -0
- package/dist/emulate/workos/constants.js +56 -0
- package/dist/emulate/workos/constants.js.map +1 -0
- package/dist/emulate/workos/entities.d.ts +360 -0
- package/dist/emulate/workos/entities.js +2 -0
- package/dist/emulate/workos/entities.js.map +1 -0
- package/dist/emulate/workos/event-bus.d.ts +17 -0
- package/dist/emulate/workos/event-bus.js +70 -0
- package/dist/emulate/workos/event-bus.js.map +1 -0
- package/dist/emulate/workos/helpers.d.ts +72 -0
- package/dist/emulate/workos/helpers.js +211 -0
- package/dist/emulate/workos/helpers.js.map +1 -0
- package/dist/emulate/workos/index.d.ts +91 -0
- package/dist/emulate/workos/index.js +322 -0
- package/dist/emulate/workos/index.js.map +1 -0
- package/dist/emulate/workos/role-helpers.d.ts +21 -0
- package/dist/emulate/workos/role-helpers.js +130 -0
- package/dist/emulate/workos/role-helpers.js.map +1 -0
- package/dist/emulate/workos/routes/api-keys.d.ts +2 -0
- package/dist/emulate/workos/routes/api-keys.js +32 -0
- package/dist/emulate/workos/routes/api-keys.js.map +1 -0
- package/dist/emulate/workos/routes/audit-logs.d.ts +2 -0
- package/dist/emulate/workos/routes/audit-logs.js +104 -0
- package/dist/emulate/workos/routes/audit-logs.js.map +1 -0
- package/dist/emulate/workos/routes/auth-challenges.d.ts +2 -0
- package/dist/emulate/workos/routes/auth-challenges.js +51 -0
- package/dist/emulate/workos/routes/auth-challenges.js.map +1 -0
- package/dist/emulate/workos/routes/auth-factors.d.ts +2 -0
- package/dist/emulate/workos/routes/auth-factors.js +51 -0
- package/dist/emulate/workos/routes/auth-factors.js.map +1 -0
- package/dist/emulate/workos/routes/auth.d.ts +2 -0
- package/dist/emulate/workos/routes/auth.js +350 -0
- package/dist/emulate/workos/routes/auth.js.map +1 -0
- package/dist/emulate/workos/routes/authorization-checks.d.ts +10 -0
- package/dist/emulate/workos/routes/authorization-checks.js +123 -0
- package/dist/emulate/workos/routes/authorization-checks.js.map +1 -0
- package/dist/emulate/workos/routes/authorization-org-roles.d.ts +2 -0
- package/dist/emulate/workos/routes/authorization-org-roles.js +64 -0
- package/dist/emulate/workos/routes/authorization-org-roles.js.map +1 -0
- package/dist/emulate/workos/routes/authorization-permissions.d.ts +2 -0
- package/dist/emulate/workos/routes/authorization-permissions.js +67 -0
- package/dist/emulate/workos/routes/authorization-permissions.js.map +1 -0
- package/dist/emulate/workos/routes/authorization-resources.d.ts +2 -0
- package/dist/emulate/workos/routes/authorization-resources.js +117 -0
- package/dist/emulate/workos/routes/authorization-resources.js.map +1 -0
- package/dist/emulate/workos/routes/authorization-roles.d.ts +2 -0
- package/dist/emulate/workos/routes/authorization-roles.js +13 -0
- package/dist/emulate/workos/routes/authorization-roles.js.map +1 -0
- package/dist/emulate/workos/routes/config.d.ts +2 -0
- package/dist/emulate/workos/routes/config.js +57 -0
- package/dist/emulate/workos/routes/config.js.map +1 -0
- package/dist/emulate/workos/routes/connect.d.ts +2 -0
- package/dist/emulate/workos/routes/connect.js +65 -0
- package/dist/emulate/workos/routes/connect.js.map +1 -0
- package/dist/emulate/workos/routes/connections.d.ts +2 -0
- package/dist/emulate/workos/routes/connections.js +73 -0
- package/dist/emulate/workos/routes/connections.js.map +1 -0
- package/dist/emulate/workos/routes/data-integrations.d.ts +2 -0
- package/dist/emulate/workos/routes/data-integrations.js +55 -0
- package/dist/emulate/workos/routes/data-integrations.js.map +1 -0
- package/dist/emulate/workos/routes/directories.d.ts +2 -0
- package/dist/emulate/workos/routes/directories.js +90 -0
- package/dist/emulate/workos/routes/directories.js.map +1 -0
- package/dist/emulate/workos/routes/email-verification.d.ts +2 -0
- package/dist/emulate/workos/routes/email-verification.js +49 -0
- package/dist/emulate/workos/routes/email-verification.js.map +1 -0
- package/dist/emulate/workos/routes/events.d.ts +2 -0
- package/dist/emulate/workos/routes/events.js +18 -0
- package/dist/emulate/workos/routes/events.js.map +1 -0
- package/dist/emulate/workos/routes/feature-flags.d.ts +2 -0
- package/dist/emulate/workos/routes/feature-flags.js +103 -0
- package/dist/emulate/workos/routes/feature-flags.js.map +1 -0
- package/dist/emulate/workos/routes/invitations.d.ts +2 -0
- package/dist/emulate/workos/routes/invitations.js +122 -0
- package/dist/emulate/workos/routes/invitations.js.map +1 -0
- package/dist/emulate/workos/routes/legacy-mfa.d.ts +2 -0
- package/dist/emulate/workos/routes/legacy-mfa.js +75 -0
- package/dist/emulate/workos/routes/legacy-mfa.js.map +1 -0
- package/dist/emulate/workos/routes/magic-auth.d.ts +2 -0
- package/dist/emulate/workos/routes/magic-auth.js +32 -0
- package/dist/emulate/workos/routes/magic-auth.js.map +1 -0
- package/dist/emulate/workos/routes/memberships.d.ts +2 -0
- package/dist/emulate/workos/routes/memberships.js +114 -0
- package/dist/emulate/workos/routes/memberships.js.map +1 -0
- package/dist/emulate/workos/routes/organization-domains.d.ts +2 -0
- package/dist/emulate/workos/routes/organization-domains.js +58 -0
- package/dist/emulate/workos/routes/organization-domains.js.map +1 -0
- package/dist/emulate/workos/routes/organizations.d.ts +2 -0
- package/dist/emulate/workos/routes/organizations.js +131 -0
- package/dist/emulate/workos/routes/organizations.js.map +1 -0
- package/dist/emulate/workos/routes/password-reset.d.ts +2 -0
- package/dist/emulate/workos/routes/password-reset.js +61 -0
- package/dist/emulate/workos/routes/password-reset.js.map +1 -0
- package/dist/emulate/workos/routes/pipes.d.ts +2 -0
- package/dist/emulate/workos/routes/pipes.js +82 -0
- package/dist/emulate/workos/routes/pipes.js.map +1 -0
- package/dist/emulate/workos/routes/portal.d.ts +2 -0
- package/dist/emulate/workos/routes/portal.js +18 -0
- package/dist/emulate/workos/routes/portal.js.map +1 -0
- package/dist/emulate/workos/routes/radar.d.ts +2 -0
- package/dist/emulate/workos/routes/radar.js +41 -0
- package/dist/emulate/workos/routes/radar.js.map +1 -0
- package/dist/emulate/workos/routes/sessions.d.ts +2 -0
- package/dist/emulate/workos/routes/sessions.js +51 -0
- package/dist/emulate/workos/routes/sessions.js.map +1 -0
- package/dist/emulate/workos/routes/sso.d.ts +2 -0
- package/dist/emulate/workos/routes/sso.js +161 -0
- package/dist/emulate/workos/routes/sso.js.map +1 -0
- package/dist/emulate/workos/routes/user-features.d.ts +2 -0
- package/dist/emulate/workos/routes/user-features.js +50 -0
- package/dist/emulate/workos/routes/user-features.js.map +1 -0
- package/dist/emulate/workos/routes/users.d.ts +2 -0
- package/dist/emulate/workos/routes/users.js +129 -0
- package/dist/emulate/workos/routes/users.js.map +1 -0
- package/dist/emulate/workos/routes/webhook-endpoints.d.ts +2 -0
- package/dist/emulate/workos/routes/webhook-endpoints.js +66 -0
- package/dist/emulate/workos/routes/webhook-endpoints.js.map +1 -0
- package/dist/emulate/workos/routes/widgets.d.ts +2 -0
- package/dist/emulate/workos/routes/widgets.js +27 -0
- package/dist/emulate/workos/routes/widgets.js.map +1 -0
- package/dist/emulate/workos/store.d.ts +48 -0
- package/dist/emulate/workos/store.js +102 -0
- package/dist/emulate/workos/store.js.map +1 -0
- package/dist/emulate/workos/webhook-signer.d.ts +1 -0
- package/dist/emulate/workos/webhook-signer.js +8 -0
- package/dist/emulate/workos/webhook-signer.js.map +1 -0
- package/dist/gen-routes-lib.spec.ts +659 -0
- package/dist/gen-routes-lib.ts +647 -0
- package/dist/gen-routes.ts +96 -0
- package/dist/lib/dev-command.d.ts +26 -0
- package/dist/lib/dev-command.js +122 -0
- package/dist/lib/dev-command.js.map +1 -0
- package/dist/lib/run-with-core.js +0 -3
- package/dist/lib/run-with-core.js.map +1 -1
- package/dist/lib/settings.js +1 -1
- package/dist/lib/settings.js.map +1 -1
- package/dist/utils/help-json.js +1 -0
- package/dist/utils/help-json.js.map +1 -1
- package/dist/utils/register-subcommand.d.ts +5 -2
- package/dist/utils/register-subcommand.js +16 -19
- package/dist/utils/register-subcommand.js.map +1 -1
- package/package.json +21 -8
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import { Store } from './store.js';
|
|
3
|
+
import { JWTManager } from './jwt.js';
|
|
4
|
+
import { type ApiKeyMap, type WorkOSAppEnv } from './middleware/auth.js';
|
|
5
|
+
import type { ServicePlugin } from './plugin.js';
|
|
6
|
+
export interface ServerOptions {
|
|
7
|
+
port?: number;
|
|
8
|
+
baseUrl?: string;
|
|
9
|
+
apiKeys?: ApiKeyMap;
|
|
10
|
+
}
|
|
11
|
+
export declare function createServer(plugin: ServicePlugin, options?: ServerOptions): {
|
|
12
|
+
app: Hono<WorkOSAppEnv, import("hono/types").BlankSchema, "/">;
|
|
13
|
+
store: Store;
|
|
14
|
+
jwt: JWTManager;
|
|
15
|
+
port: number;
|
|
16
|
+
baseUrl: string;
|
|
17
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import { cors } from 'hono/cors';
|
|
3
|
+
import { Store } from './store.js';
|
|
4
|
+
import { JWTManager } from './jwt.js';
|
|
5
|
+
import { createApiErrorHandler, requestIdMiddleware } from './middleware/error-handler.js';
|
|
6
|
+
import { authMiddleware } from './middleware/auth.js';
|
|
7
|
+
export function createServer(plugin, options = {}) {
|
|
8
|
+
const port = options.port ?? 4100;
|
|
9
|
+
const baseUrl = options.baseUrl ?? `http://localhost:${port}`;
|
|
10
|
+
const app = new Hono();
|
|
11
|
+
const store = new Store();
|
|
12
|
+
const jwt = new JWTManager(baseUrl);
|
|
13
|
+
const apiKeys = options.apiKeys ?? {
|
|
14
|
+
sk_test_default: { environment: 'test' },
|
|
15
|
+
};
|
|
16
|
+
app.onError(createApiErrorHandler());
|
|
17
|
+
app.use('*', cors());
|
|
18
|
+
app.use('*', requestIdMiddleware());
|
|
19
|
+
// JWKS endpoint (public, no auth)
|
|
20
|
+
app.get('/sso/jwks/:client_id', (c) => {
|
|
21
|
+
return c.json(jwt.getJWKS());
|
|
22
|
+
});
|
|
23
|
+
// Auth middleware — single catch-all instance
|
|
24
|
+
const auth = authMiddleware(apiKeys);
|
|
25
|
+
const PUBLIC_PATHS = new Set([
|
|
26
|
+
'/health',
|
|
27
|
+
'/user_management/authorize',
|
|
28
|
+
'/user_management/authenticate',
|
|
29
|
+
'/user_management/sessions/logout',
|
|
30
|
+
]);
|
|
31
|
+
const PUBLIC_PATH_PREFIXES = ['/sso/', '/user_management/sessions/jwks/', '/data-integrations/'];
|
|
32
|
+
app.use('*', async (c, next) => {
|
|
33
|
+
const path = new URL(c.req.url).pathname;
|
|
34
|
+
// Skip auth for public paths
|
|
35
|
+
if (PUBLIC_PATHS.has(path))
|
|
36
|
+
return next();
|
|
37
|
+
for (const prefix of PUBLIC_PATH_PREFIXES) {
|
|
38
|
+
if (path.startsWith(prefix)) {
|
|
39
|
+
// data-integrations: only /authorize subpath is public
|
|
40
|
+
if (prefix === '/data-integrations/' && !path.endsWith('/authorize'))
|
|
41
|
+
break;
|
|
42
|
+
return next();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return auth(c, next);
|
|
46
|
+
});
|
|
47
|
+
// Rate limiting
|
|
48
|
+
const rateLimitCounters = new Map();
|
|
49
|
+
let lastPruneAt = Math.floor(Date.now() / 1000);
|
|
50
|
+
app.use('*', async (c, next) => {
|
|
51
|
+
const auth = c.get('auth');
|
|
52
|
+
const key = auth?.apiKey ?? '__anonymous__';
|
|
53
|
+
const now = Math.floor(Date.now() / 1000);
|
|
54
|
+
if (now - lastPruneAt > 3600) {
|
|
55
|
+
for (const [k, val] of rateLimitCounters) {
|
|
56
|
+
if (val.resetAt <= now)
|
|
57
|
+
rateLimitCounters.delete(k);
|
|
58
|
+
}
|
|
59
|
+
lastPruneAt = now;
|
|
60
|
+
}
|
|
61
|
+
let counter = rateLimitCounters.get(key);
|
|
62
|
+
if (!counter || counter.resetAt <= now) {
|
|
63
|
+
counter = { remaining: 1000, resetAt: now + 60 };
|
|
64
|
+
rateLimitCounters.set(key, counter);
|
|
65
|
+
}
|
|
66
|
+
counter.remaining = Math.max(0, counter.remaining - 1);
|
|
67
|
+
c.header('X-RateLimit-Limit', '1000');
|
|
68
|
+
c.header('X-RateLimit-Remaining', String(counter.remaining));
|
|
69
|
+
c.header('X-RateLimit-Reset', String(counter.resetAt));
|
|
70
|
+
if (counter.remaining === 0) {
|
|
71
|
+
c.header('Retry-After', String(counter.resetAt - now));
|
|
72
|
+
return c.json({
|
|
73
|
+
message: 'Too Many Requests',
|
|
74
|
+
code: 'rate_limit_exceeded',
|
|
75
|
+
}, 429);
|
|
76
|
+
}
|
|
77
|
+
await next();
|
|
78
|
+
});
|
|
79
|
+
// Store API key map for route access
|
|
80
|
+
store.setData('apiKeyMap', apiKeys);
|
|
81
|
+
// Register plugin routes
|
|
82
|
+
plugin.register({ app, store, jwt, baseUrl });
|
|
83
|
+
// Not found handler
|
|
84
|
+
app.notFound((c) => c.json({
|
|
85
|
+
message: 'Not Found',
|
|
86
|
+
code: 'not_found',
|
|
87
|
+
}, 404));
|
|
88
|
+
return { app, store, jwt, port, baseUrl };
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/emulate/core/server.ts"],"names":[],"mappings":"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","sourcesContent":["import { Hono } from 'hono';\nimport { cors } from 'hono/cors';\nimport { Store } from './store.js';\nimport { JWTManager } from './jwt.js';\nimport { createApiErrorHandler, requestIdMiddleware } from './middleware/error-handler.js';\nimport { authMiddleware, type ApiKeyMap, type WorkOSAppEnv } from './middleware/auth.js';\nimport type { ServicePlugin } from './plugin.js';\n\nexport interface ServerOptions {\n port?: number;\n baseUrl?: string;\n apiKeys?: ApiKeyMap;\n}\n\nexport function createServer(plugin: ServicePlugin, options: ServerOptions = {}) {\n const port = options.port ?? 4100;\n const baseUrl = options.baseUrl ?? `http://localhost:${port}`;\n\n const app = new Hono<WorkOSAppEnv>();\n const store = new Store();\n const jwt = new JWTManager(baseUrl);\n\n const apiKeys: ApiKeyMap = options.apiKeys ?? {\n sk_test_default: { environment: 'test' },\n };\n\n app.onError(createApiErrorHandler());\n app.use('*', cors());\n app.use('*', requestIdMiddleware());\n\n // JWKS endpoint (public, no auth)\n app.get('/sso/jwks/:client_id', (c) => {\n return c.json(jwt.getJWKS());\n });\n\n // Auth middleware — single catch-all instance\n const auth = authMiddleware(apiKeys);\n\n const PUBLIC_PATHS = new Set([\n '/health',\n '/user_management/authorize',\n '/user_management/authenticate',\n '/user_management/sessions/logout',\n ]);\n\n const PUBLIC_PATH_PREFIXES = ['/sso/', '/user_management/sessions/jwks/', '/data-integrations/'];\n\n app.use('*', async (c, next) => {\n const path = new URL(c.req.url).pathname;\n\n // Skip auth for public paths\n if (PUBLIC_PATHS.has(path)) return next();\n for (const prefix of PUBLIC_PATH_PREFIXES) {\n if (path.startsWith(prefix)) {\n // data-integrations: only /authorize subpath is public\n if (prefix === '/data-integrations/' && !path.endsWith('/authorize')) break;\n return next();\n }\n }\n\n return auth(c, next);\n });\n\n // Rate limiting\n const rateLimitCounters = new Map<string, { remaining: number; resetAt: number }>();\n let lastPruneAt = Math.floor(Date.now() / 1000);\n\n app.use('*', async (c, next) => {\n const auth = c.get('auth');\n const key = auth?.apiKey ?? '__anonymous__';\n const now = Math.floor(Date.now() / 1000);\n\n if (now - lastPruneAt > 3600) {\n for (const [k, val] of rateLimitCounters) {\n if (val.resetAt <= now) rateLimitCounters.delete(k);\n }\n lastPruneAt = now;\n }\n\n let counter = rateLimitCounters.get(key);\n if (!counter || counter.resetAt <= now) {\n counter = { remaining: 1000, resetAt: now + 60 };\n rateLimitCounters.set(key, counter);\n }\n\n counter.remaining = Math.max(0, counter.remaining - 1);\n\n c.header('X-RateLimit-Limit', '1000');\n c.header('X-RateLimit-Remaining', String(counter.remaining));\n c.header('X-RateLimit-Reset', String(counter.resetAt));\n\n if (counter.remaining === 0) {\n c.header('Retry-After', String(counter.resetAt - now));\n return c.json(\n {\n message: 'Too Many Requests',\n code: 'rate_limit_exceeded',\n },\n 429,\n );\n }\n\n await next();\n });\n\n // Store API key map for route access\n store.setData('apiKeyMap', apiKeys);\n\n // Register plugin routes\n plugin.register({ app, store, jwt, baseUrl });\n\n // Not found handler\n app.notFound((c) =>\n c.json(\n {\n message: 'Not Found',\n code: 'not_found',\n },\n 404,\n ),\n );\n\n return { app, store, jwt, port, baseUrl };\n}\n"]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type Entity, type CursorPaginationOptions, type CursorPaginatedResult } from './pagination.js';
|
|
2
|
+
export type { Entity };
|
|
3
|
+
export type InsertInput<T extends Entity> = Omit<T, 'id' | 'created_at' | 'updated_at'> & {
|
|
4
|
+
id?: string;
|
|
5
|
+
};
|
|
6
|
+
export type FilterFn<T> = (item: T) => boolean;
|
|
7
|
+
export type SortFn<T> = (a: T, b: T) => number;
|
|
8
|
+
export interface CollectionHooks<T extends Entity> {
|
|
9
|
+
onInsert?: (item: T) => void;
|
|
10
|
+
onUpdate?: (item: T) => void;
|
|
11
|
+
onDelete?: (item: T) => void;
|
|
12
|
+
}
|
|
13
|
+
export declare class Collection<T extends Entity> {
|
|
14
|
+
private prefix;
|
|
15
|
+
private indexFields;
|
|
16
|
+
private items;
|
|
17
|
+
private indexes;
|
|
18
|
+
private hooks;
|
|
19
|
+
readonly fieldNames: string[];
|
|
20
|
+
constructor(prefix: string, indexFields?: (keyof T)[]);
|
|
21
|
+
private addToIndex;
|
|
22
|
+
private removeFromIndex;
|
|
23
|
+
insert(data: InsertInput<T>): T;
|
|
24
|
+
get(id: string): T | undefined;
|
|
25
|
+
findBy(field: keyof T, value: string | number): T[];
|
|
26
|
+
findOneBy(field: keyof T, value: string | number): T | undefined;
|
|
27
|
+
update(id: string, data: Partial<T>): T | undefined;
|
|
28
|
+
delete(id: string): boolean;
|
|
29
|
+
deleteBy(field: keyof T, value: string | number): number;
|
|
30
|
+
setHooks(hooks: CollectionHooks<T>): void;
|
|
31
|
+
all(): T[];
|
|
32
|
+
list(options?: CursorPaginationOptions<T>): CursorPaginatedResult<T>;
|
|
33
|
+
count(filter?: FilterFn<T>): number;
|
|
34
|
+
clear(): void;
|
|
35
|
+
}
|
|
36
|
+
export declare class Store {
|
|
37
|
+
private collections;
|
|
38
|
+
private _data;
|
|
39
|
+
collection<T extends Entity>(name: string, prefix: string, indexFields?: (keyof T)[]): Collection<T>;
|
|
40
|
+
getData<V>(key: string): V | undefined;
|
|
41
|
+
setData<V>(key: string, value: V): void;
|
|
42
|
+
deleteDataByPrefix(prefix: string): number;
|
|
43
|
+
reset(): void;
|
|
44
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { generateId } from './id.js';
|
|
2
|
+
import { cursorPaginate } from './pagination.js';
|
|
3
|
+
export class Collection {
|
|
4
|
+
prefix;
|
|
5
|
+
indexFields;
|
|
6
|
+
items = new Map();
|
|
7
|
+
indexes = new Map();
|
|
8
|
+
hooks = {};
|
|
9
|
+
fieldNames;
|
|
10
|
+
constructor(prefix, indexFields = []) {
|
|
11
|
+
this.prefix = prefix;
|
|
12
|
+
this.indexFields = indexFields;
|
|
13
|
+
this.fieldNames = indexFields.map(String).sort();
|
|
14
|
+
for (const field of indexFields) {
|
|
15
|
+
this.indexes.set(String(field), new Map());
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
addToIndex(item) {
|
|
19
|
+
for (const field of this.indexFields) {
|
|
20
|
+
const value = item[field];
|
|
21
|
+
if (value === undefined || value === null)
|
|
22
|
+
continue;
|
|
23
|
+
const indexMap = this.indexes.get(String(field));
|
|
24
|
+
const key = String(value);
|
|
25
|
+
if (!indexMap.has(key)) {
|
|
26
|
+
indexMap.set(key, new Set());
|
|
27
|
+
}
|
|
28
|
+
indexMap.get(key).add(item.id);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
removeFromIndex(item) {
|
|
32
|
+
for (const field of this.indexFields) {
|
|
33
|
+
const value = item[field];
|
|
34
|
+
if (value === undefined || value === null)
|
|
35
|
+
continue;
|
|
36
|
+
const indexMap = this.indexes.get(String(field));
|
|
37
|
+
const key = String(value);
|
|
38
|
+
indexMap.get(key)?.delete(item.id);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
insert(data) {
|
|
42
|
+
const now = new Date().toISOString();
|
|
43
|
+
const id = data.id ?? generateId(this.prefix);
|
|
44
|
+
const item = {
|
|
45
|
+
...data,
|
|
46
|
+
id,
|
|
47
|
+
created_at: now,
|
|
48
|
+
updated_at: now,
|
|
49
|
+
};
|
|
50
|
+
this.items.set(id, item);
|
|
51
|
+
this.addToIndex(item);
|
|
52
|
+
this.hooks.onInsert?.(item);
|
|
53
|
+
return item;
|
|
54
|
+
}
|
|
55
|
+
get(id) {
|
|
56
|
+
return this.items.get(id);
|
|
57
|
+
}
|
|
58
|
+
findBy(field, value) {
|
|
59
|
+
if (this.indexes.has(String(field))) {
|
|
60
|
+
const ids = this.indexes.get(String(field)).get(String(value));
|
|
61
|
+
if (!ids)
|
|
62
|
+
return [];
|
|
63
|
+
return Array.from(ids)
|
|
64
|
+
.map((id) => this.items.get(id))
|
|
65
|
+
.filter(Boolean);
|
|
66
|
+
}
|
|
67
|
+
return this.all().filter((item) => item[field] === value);
|
|
68
|
+
}
|
|
69
|
+
findOneBy(field, value) {
|
|
70
|
+
return this.findBy(field, value)[0];
|
|
71
|
+
}
|
|
72
|
+
update(id, data) {
|
|
73
|
+
const existing = this.items.get(id);
|
|
74
|
+
if (!existing)
|
|
75
|
+
return undefined;
|
|
76
|
+
this.removeFromIndex(existing);
|
|
77
|
+
const updated = {
|
|
78
|
+
...existing,
|
|
79
|
+
...data,
|
|
80
|
+
id,
|
|
81
|
+
updated_at: new Date().toISOString(),
|
|
82
|
+
};
|
|
83
|
+
this.items.set(id, updated);
|
|
84
|
+
this.addToIndex(updated);
|
|
85
|
+
this.hooks.onUpdate?.(updated);
|
|
86
|
+
return updated;
|
|
87
|
+
}
|
|
88
|
+
delete(id) {
|
|
89
|
+
const existing = this.items.get(id);
|
|
90
|
+
if (!existing)
|
|
91
|
+
return false;
|
|
92
|
+
this.hooks.onDelete?.(existing);
|
|
93
|
+
this.removeFromIndex(existing);
|
|
94
|
+
return this.items.delete(id);
|
|
95
|
+
}
|
|
96
|
+
deleteBy(field, value) {
|
|
97
|
+
const items = this.findBy(field, value);
|
|
98
|
+
for (const item of items)
|
|
99
|
+
this.delete(item.id);
|
|
100
|
+
return items.length;
|
|
101
|
+
}
|
|
102
|
+
setHooks(hooks) {
|
|
103
|
+
this.hooks = hooks;
|
|
104
|
+
}
|
|
105
|
+
all() {
|
|
106
|
+
return Array.from(this.items.values());
|
|
107
|
+
}
|
|
108
|
+
list(options = {}) {
|
|
109
|
+
return cursorPaginate(this.all(), options);
|
|
110
|
+
}
|
|
111
|
+
count(filter) {
|
|
112
|
+
if (!filter)
|
|
113
|
+
return this.items.size;
|
|
114
|
+
let n = 0;
|
|
115
|
+
for (const item of this.items.values()) {
|
|
116
|
+
if (filter(item))
|
|
117
|
+
n++;
|
|
118
|
+
}
|
|
119
|
+
return n;
|
|
120
|
+
}
|
|
121
|
+
clear() {
|
|
122
|
+
this.items.clear();
|
|
123
|
+
for (const indexMap of this.indexes.values()) {
|
|
124
|
+
indexMap.clear();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
export class Store {
|
|
129
|
+
collections = new Map();
|
|
130
|
+
_data = new Map();
|
|
131
|
+
collection(name, prefix, indexFields = []) {
|
|
132
|
+
const existing = this.collections.get(name);
|
|
133
|
+
if (existing) {
|
|
134
|
+
if (indexFields.length > 0) {
|
|
135
|
+
const requested = indexFields.map(String).sort();
|
|
136
|
+
if (existing.fieldNames.length !== requested.length || existing.fieldNames.some((f, i) => f !== requested[i])) {
|
|
137
|
+
throw new Error(`Collection "${name}" already exists with indexes [${existing.fieldNames}] but was requested with [${requested}]`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return existing;
|
|
141
|
+
}
|
|
142
|
+
const col = new Collection(prefix, indexFields);
|
|
143
|
+
this.collections.set(name, col);
|
|
144
|
+
return col;
|
|
145
|
+
}
|
|
146
|
+
getData(key) {
|
|
147
|
+
return this._data.get(key);
|
|
148
|
+
}
|
|
149
|
+
setData(key, value) {
|
|
150
|
+
this._data.set(key, value);
|
|
151
|
+
}
|
|
152
|
+
deleteDataByPrefix(prefix) {
|
|
153
|
+
let count = 0;
|
|
154
|
+
for (const key of this._data.keys()) {
|
|
155
|
+
if (key.startsWith(prefix)) {
|
|
156
|
+
this._data.delete(key);
|
|
157
|
+
count++;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return count;
|
|
161
|
+
}
|
|
162
|
+
reset() {
|
|
163
|
+
for (const collection of this.collections.values()) {
|
|
164
|
+
collection.clear();
|
|
165
|
+
}
|
|
166
|
+
this._data.clear();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/emulate/core/store.ts"],"names":[],"mappings":"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","sourcesContent":["import { generateId } from './id.js';\nimport { cursorPaginate, type Entity, type CursorPaginationOptions, type CursorPaginatedResult } from './pagination.js';\n\nexport type { Entity };\n\nexport type InsertInput<T extends Entity> = Omit<T, 'id' | 'created_at' | 'updated_at'> & {\n id?: string;\n};\n\nexport type FilterFn<T> = (item: T) => boolean;\nexport type SortFn<T> = (a: T, b: T) => number;\n\nexport interface CollectionHooks<T extends Entity> {\n onInsert?: (item: T) => void;\n onUpdate?: (item: T) => void;\n onDelete?: (item: T) => void;\n}\n\nexport class Collection<T extends Entity> {\n private items = new Map<string, T>();\n private indexes = new Map<string, Map<string, Set<string>>>();\n private hooks: CollectionHooks<T> = {};\n readonly fieldNames: string[];\n\n constructor(\n private prefix: string,\n private indexFields: (keyof T)[] = [],\n ) {\n this.fieldNames = indexFields.map(String).sort();\n for (const field of indexFields) {\n this.indexes.set(String(field), new Map());\n }\n }\n\n private addToIndex(item: T): void {\n for (const field of this.indexFields) {\n const value = item[field];\n if (value === undefined || value === null) continue;\n const indexMap = this.indexes.get(String(field))!;\n const key = String(value);\n if (!indexMap.has(key)) {\n indexMap.set(key, new Set());\n }\n indexMap.get(key)!.add(item.id);\n }\n }\n\n private removeFromIndex(item: T): void {\n for (const field of this.indexFields) {\n const value = item[field];\n if (value === undefined || value === null) continue;\n const indexMap = this.indexes.get(String(field))!;\n const key = String(value);\n indexMap.get(key)?.delete(item.id);\n }\n }\n\n insert(data: InsertInput<T>): T {\n const now = new Date().toISOString();\n const id = data.id ?? generateId(this.prefix);\n const item = {\n ...data,\n id,\n created_at: now,\n updated_at: now,\n } as unknown as T;\n this.items.set(id, item);\n this.addToIndex(item);\n this.hooks.onInsert?.(item);\n return item;\n }\n\n get(id: string): T | undefined {\n return this.items.get(id);\n }\n\n findBy(field: keyof T, value: string | number): T[] {\n if (this.indexes.has(String(field))) {\n const ids = this.indexes.get(String(field))!.get(String(value));\n if (!ids) return [];\n return Array.from(ids)\n .map((id) => this.items.get(id)!)\n .filter(Boolean);\n }\n return this.all().filter((item) => item[field] === value);\n }\n\n findOneBy(field: keyof T, value: string | number): T | undefined {\n return this.findBy(field, value)[0];\n }\n\n update(id: string, data: Partial<T>): T | undefined {\n const existing = this.items.get(id);\n if (!existing) return undefined;\n this.removeFromIndex(existing);\n const updated = {\n ...existing,\n ...data,\n id,\n updated_at: new Date().toISOString(),\n } as T;\n this.items.set(id, updated);\n this.addToIndex(updated);\n this.hooks.onUpdate?.(updated);\n return updated;\n }\n\n delete(id: string): boolean {\n const existing = this.items.get(id);\n if (!existing) return false;\n this.hooks.onDelete?.(existing);\n this.removeFromIndex(existing);\n return this.items.delete(id);\n }\n\n deleteBy(field: keyof T, value: string | number): number {\n const items = this.findBy(field, value);\n for (const item of items) this.delete(item.id);\n return items.length;\n }\n\n setHooks(hooks: CollectionHooks<T>): void {\n this.hooks = hooks;\n }\n\n all(): T[] {\n return Array.from(this.items.values());\n }\n\n list(options: CursorPaginationOptions<T> = {}): CursorPaginatedResult<T> {\n return cursorPaginate(this.all(), options);\n }\n\n count(filter?: FilterFn<T>): number {\n if (!filter) return this.items.size;\n let n = 0;\n for (const item of this.items.values()) {\n if (filter(item)) n++;\n }\n return n;\n }\n\n clear(): void {\n this.items.clear();\n for (const indexMap of this.indexes.values()) {\n indexMap.clear();\n }\n }\n}\n\nexport class Store {\n private collections = new Map<string, Collection<any>>();\n private _data = new Map<string, unknown>();\n\n collection<T extends Entity>(name: string, prefix: string, indexFields: (keyof T)[] = []): Collection<T> {\n const existing = this.collections.get(name);\n if (existing) {\n if (indexFields.length > 0) {\n const requested = indexFields.map(String).sort();\n if (existing.fieldNames.length !== requested.length || existing.fieldNames.some((f, i) => f !== requested[i])) {\n throw new Error(\n `Collection \"${name}\" already exists with indexes [${existing.fieldNames}] but was requested with [${requested}]`,\n );\n }\n }\n return existing as Collection<T>;\n }\n const col = new Collection<T>(prefix, indexFields);\n this.collections.set(name, col);\n return col;\n }\n\n getData<V>(key: string): V | undefined {\n return this._data.get(key) as V | undefined;\n }\n\n setData<V>(key: string, value: V): void {\n this._data.set(key, value);\n }\n\n deleteDataByPrefix(prefix: string): number {\n let count = 0;\n for (const key of this._data.keys()) {\n if (key.startsWith(prefix)) {\n this._data.delete(key);\n count++;\n }\n }\n return count;\n }\n\n reset(): void {\n for (const collection of this.collections.values()) {\n collection.clear();\n }\n this._data.clear();\n }\n}\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type WorkOSSeedConfig } from './workos/index.js';
|
|
2
|
+
export interface EmulatorSeedConfig {
|
|
3
|
+
apiKeys?: Record<string, {
|
|
4
|
+
environment: string;
|
|
5
|
+
}>;
|
|
6
|
+
organizations?: WorkOSSeedConfig['organizations'];
|
|
7
|
+
users?: WorkOSSeedConfig['users'];
|
|
8
|
+
connections?: WorkOSSeedConfig['connections'];
|
|
9
|
+
invitations?: WorkOSSeedConfig['invitations'];
|
|
10
|
+
roles?: WorkOSSeedConfig['roles'];
|
|
11
|
+
permissions?: WorkOSSeedConfig['permissions'];
|
|
12
|
+
webhookEndpoints?: WorkOSSeedConfig['webhookEndpoints'];
|
|
13
|
+
}
|
|
14
|
+
export interface EmulatorOptions {
|
|
15
|
+
port?: number;
|
|
16
|
+
seed?: EmulatorSeedConfig;
|
|
17
|
+
}
|
|
18
|
+
export interface Emulator {
|
|
19
|
+
url: string;
|
|
20
|
+
port: number;
|
|
21
|
+
apiKey: string;
|
|
22
|
+
close(): Promise<void>;
|
|
23
|
+
reset(): void;
|
|
24
|
+
}
|
|
25
|
+
export declare function createEmulator(options?: EmulatorOptions): Promise<Emulator>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { createServer } from './core/index.js';
|
|
2
|
+
import { workosPlugin, seedFromConfig } from './workos/index.js';
|
|
3
|
+
import { serve } from '@hono/node-server';
|
|
4
|
+
export async function createEmulator(options = {}) {
|
|
5
|
+
const port = options.port ?? 4100;
|
|
6
|
+
const baseUrl = `http://localhost:${port}`;
|
|
7
|
+
const apiKeys = options.seed?.apiKeys ?? {
|
|
8
|
+
sk_test_default: { environment: 'test' },
|
|
9
|
+
};
|
|
10
|
+
const { app, store, jwt } = createServer(workosPlugin, {
|
|
11
|
+
port,
|
|
12
|
+
baseUrl,
|
|
13
|
+
apiKeys,
|
|
14
|
+
});
|
|
15
|
+
// Health check endpoint
|
|
16
|
+
app.get('/health', (c) => c.json({ status: 'ok' }));
|
|
17
|
+
const seedFn = () => {
|
|
18
|
+
workosPlugin.seed?.(store, baseUrl);
|
|
19
|
+
if (options.seed) {
|
|
20
|
+
seedFromConfig(store, baseUrl, options.seed);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
seedFn();
|
|
24
|
+
const httpServer = serve({ fetch: app.fetch, port });
|
|
25
|
+
// Resolve actual port (important for port: 0)
|
|
26
|
+
const addr = httpServer.address();
|
|
27
|
+
const actualPort = typeof addr === 'object' && addr ? addr.port : port;
|
|
28
|
+
const url = `http://localhost:${actualPort}`;
|
|
29
|
+
// Update JWT issuer to reflect the actual bound URL (matters when port: 0)
|
|
30
|
+
jwt.issuer = url;
|
|
31
|
+
const primaryApiKey = Object.keys(apiKeys)[0];
|
|
32
|
+
return {
|
|
33
|
+
url,
|
|
34
|
+
port: actualPort,
|
|
35
|
+
apiKey: primaryApiKey,
|
|
36
|
+
reset() {
|
|
37
|
+
store.reset();
|
|
38
|
+
seedFn();
|
|
39
|
+
},
|
|
40
|
+
close() {
|
|
41
|
+
return new Promise((resolve, reject) => {
|
|
42
|
+
httpServer.close((err) => (err ? reject(err) : resolve()));
|
|
43
|
+
});
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/emulate/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAkB,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,cAAc,EAAyB,MAAM,mBAAmB,CAAC;AACxF,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AA0B1C,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,UAA2B,EAAE;IAChE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC;IAClC,MAAM,OAAO,GAAG,oBAAoB,IAAI,EAAE,CAAC;IAE3C,MAAM,OAAO,GAAc,OAAO,CAAC,IAAI,EAAE,OAAO,IAAI;QAClD,eAAe,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE;KACzC,CAAC;IAEF,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,YAAY,CAAC,YAAY,EAAE;QACrD,IAAI;QACJ,OAAO;QACP,OAAO;KACR,CAAC,CAAC;IAEH,wBAAwB;IACxB,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAEpD,MAAM,MAAM,GAAG,GAAG,EAAE;QAClB,YAAY,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACpC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC,CAAC;IACF,MAAM,EAAE,CAAC;IAET,MAAM,UAAU,GAAG,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAErD,8CAA8C;IAC9C,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC;IAClC,MAAM,UAAU,GAAG,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IACvE,MAAM,GAAG,GAAG,oBAAoB,UAAU,EAAE,CAAC;IAE7C,2EAA2E;IAC3E,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;IAEjB,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAE9C,OAAO;QACL,GAAG;QACH,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE,aAAa;QACrB,KAAK;YACH,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,MAAM,EAAE,CAAC;QACX,CAAC;QACD,KAAK;YACH,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACrC,UAAU,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAC7D,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { createServer, type ApiKeyMap } from './core/index.js';\nimport { workosPlugin, seedFromConfig, type WorkOSSeedConfig } from './workos/index.js';\nimport { serve } from '@hono/node-server';\n\nexport interface EmulatorSeedConfig {\n apiKeys?: Record<string, { environment: string }>;\n organizations?: WorkOSSeedConfig['organizations'];\n users?: WorkOSSeedConfig['users'];\n connections?: WorkOSSeedConfig['connections'];\n invitations?: WorkOSSeedConfig['invitations'];\n roles?: WorkOSSeedConfig['roles'];\n permissions?: WorkOSSeedConfig['permissions'];\n webhookEndpoints?: WorkOSSeedConfig['webhookEndpoints'];\n}\n\nexport interface EmulatorOptions {\n port?: number;\n seed?: EmulatorSeedConfig;\n}\n\nexport interface Emulator {\n url: string;\n port: number;\n apiKey: string;\n close(): Promise<void>;\n reset(): void;\n}\n\nexport async function createEmulator(options: EmulatorOptions = {}): Promise<Emulator> {\n const port = options.port ?? 4100;\n const baseUrl = `http://localhost:${port}`;\n\n const apiKeys: ApiKeyMap = options.seed?.apiKeys ?? {\n sk_test_default: { environment: 'test' },\n };\n\n const { app, store, jwt } = createServer(workosPlugin, {\n port,\n baseUrl,\n apiKeys,\n });\n\n // Health check endpoint\n app.get('/health', (c) => c.json({ status: 'ok' }));\n\n const seedFn = () => {\n workosPlugin.seed?.(store, baseUrl);\n if (options.seed) {\n seedFromConfig(store, baseUrl, options.seed);\n }\n };\n seedFn();\n\n const httpServer = serve({ fetch: app.fetch, port });\n\n // Resolve actual port (important for port: 0)\n const addr = httpServer.address();\n const actualPort = typeof addr === 'object' && addr ? addr.port : port;\n const url = `http://localhost:${actualPort}`;\n\n // Update JWT issuer to reflect the actual bound URL (matters when port: 0)\n jwt.issuer = url;\n\n const primaryApiKey = Object.keys(apiKeys)[0];\n\n return {\n url,\n port: actualPort,\n apiKey: primaryApiKey,\n reset() {\n store.reset();\n seedFn();\n },\n close(): Promise<void> {\n return new Promise((resolve, reject) => {\n httpServer.close((err) => (err ? reject(err) : resolve()));\n });\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/** Typed keys for Store.getData/setData */
|
|
2
|
+
export declare const STORE_KEYS: {
|
|
3
|
+
readonly workosStore: "_workos_store";
|
|
4
|
+
readonly eventBus: "eventBus";
|
|
5
|
+
readonly apiKeyMap: "apiKeyMap";
|
|
6
|
+
readonly jwtTemplate: "jwt_template";
|
|
7
|
+
};
|
|
8
|
+
/** Prefix for dynamic store keys */
|
|
9
|
+
export declare const STORE_KEY_PREFIXES: {
|
|
10
|
+
readonly pendingAuth: "pending_auth:";
|
|
11
|
+
readonly ssoToken: "sso_token:";
|
|
12
|
+
readonly ssoLogout: "sso_logout:";
|
|
13
|
+
readonly auditSchema: "audit_schema_";
|
|
14
|
+
readonly radarIpList: "radar_ip_list";
|
|
15
|
+
};
|
|
16
|
+
/** All WorkOS webhook event names */
|
|
17
|
+
export declare const EVENTS: {
|
|
18
|
+
readonly userCreated: "user.created";
|
|
19
|
+
readonly userUpdated: "user.updated";
|
|
20
|
+
readonly userDeleted: "user.deleted";
|
|
21
|
+
readonly organizationCreated: "organization.created";
|
|
22
|
+
readonly organizationUpdated: "organization.updated";
|
|
23
|
+
readonly organizationDeleted: "organization.deleted";
|
|
24
|
+
readonly organizationDomainCreated: "organization_domain.created";
|
|
25
|
+
readonly organizationDomainVerified: "organization_domain.verified";
|
|
26
|
+
readonly organizationDomainUpdated: "organization_domain.updated";
|
|
27
|
+
readonly organizationDomainDeleted: "organization_domain.deleted";
|
|
28
|
+
readonly organizationMembershipCreated: "organization_membership.created";
|
|
29
|
+
readonly organizationMembershipUpdated: "organization_membership.updated";
|
|
30
|
+
readonly organizationMembershipDeleted: "organization_membership.deleted";
|
|
31
|
+
readonly connectionCreated: "connection.created";
|
|
32
|
+
readonly connectionUpdated: "connection.updated";
|
|
33
|
+
readonly connectionDeleted: "connection.deleted";
|
|
34
|
+
readonly sessionCreated: "session.created";
|
|
35
|
+
readonly sessionRevoked: "session.revoked";
|
|
36
|
+
readonly invitationCreated: "invitation.created";
|
|
37
|
+
readonly invitationAccepted: "invitation.accepted";
|
|
38
|
+
readonly invitationRevoked: "invitation.revoked";
|
|
39
|
+
readonly invitationResent: "invitation.resent";
|
|
40
|
+
readonly roleCreated: "role.created";
|
|
41
|
+
readonly roleUpdated: "role.updated";
|
|
42
|
+
readonly roleDeleted: "role.deleted";
|
|
43
|
+
readonly permissionCreated: "permission.created";
|
|
44
|
+
readonly permissionUpdated: "permission.updated";
|
|
45
|
+
readonly permissionDeleted: "permission.deleted";
|
|
46
|
+
readonly directoryCreated: "directory.created";
|
|
47
|
+
readonly directoryUpdated: "directory.updated";
|
|
48
|
+
readonly directoryDeleted: "directory.deleted";
|
|
49
|
+
readonly directoryUserCreated: "directory_user.created";
|
|
50
|
+
readonly directoryUserUpdated: "directory_user.updated";
|
|
51
|
+
readonly directoryUserDeleted: "directory_user.deleted";
|
|
52
|
+
readonly directoryGroupCreated: "directory_group.created";
|
|
53
|
+
readonly directoryGroupUpdated: "directory_group.updated";
|
|
54
|
+
readonly directoryGroupDeleted: "directory_group.deleted";
|
|
55
|
+
};
|
|
56
|
+
export type WorkOSEventName = (typeof EVENTS)[keyof typeof EVENTS];
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/** Typed keys for Store.getData/setData */
|
|
2
|
+
export const STORE_KEYS = {
|
|
3
|
+
workosStore: '_workos_store',
|
|
4
|
+
eventBus: 'eventBus',
|
|
5
|
+
apiKeyMap: 'apiKeyMap',
|
|
6
|
+
jwtTemplate: 'jwt_template',
|
|
7
|
+
};
|
|
8
|
+
/** Prefix for dynamic store keys */
|
|
9
|
+
export const STORE_KEY_PREFIXES = {
|
|
10
|
+
pendingAuth: 'pending_auth:',
|
|
11
|
+
ssoToken: 'sso_token:',
|
|
12
|
+
ssoLogout: 'sso_logout:',
|
|
13
|
+
auditSchema: 'audit_schema_',
|
|
14
|
+
radarIpList: 'radar_ip_list',
|
|
15
|
+
};
|
|
16
|
+
/** All WorkOS webhook event names */
|
|
17
|
+
export const EVENTS = {
|
|
18
|
+
userCreated: 'user.created',
|
|
19
|
+
userUpdated: 'user.updated',
|
|
20
|
+
userDeleted: 'user.deleted',
|
|
21
|
+
organizationCreated: 'organization.created',
|
|
22
|
+
organizationUpdated: 'organization.updated',
|
|
23
|
+
organizationDeleted: 'organization.deleted',
|
|
24
|
+
organizationDomainCreated: 'organization_domain.created',
|
|
25
|
+
organizationDomainVerified: 'organization_domain.verified',
|
|
26
|
+
organizationDomainUpdated: 'organization_domain.updated',
|
|
27
|
+
organizationDomainDeleted: 'organization_domain.deleted',
|
|
28
|
+
organizationMembershipCreated: 'organization_membership.created',
|
|
29
|
+
organizationMembershipUpdated: 'organization_membership.updated',
|
|
30
|
+
organizationMembershipDeleted: 'organization_membership.deleted',
|
|
31
|
+
connectionCreated: 'connection.created',
|
|
32
|
+
connectionUpdated: 'connection.updated',
|
|
33
|
+
connectionDeleted: 'connection.deleted',
|
|
34
|
+
sessionCreated: 'session.created',
|
|
35
|
+
sessionRevoked: 'session.revoked',
|
|
36
|
+
invitationCreated: 'invitation.created',
|
|
37
|
+
invitationAccepted: 'invitation.accepted',
|
|
38
|
+
invitationRevoked: 'invitation.revoked',
|
|
39
|
+
invitationResent: 'invitation.resent',
|
|
40
|
+
roleCreated: 'role.created',
|
|
41
|
+
roleUpdated: 'role.updated',
|
|
42
|
+
roleDeleted: 'role.deleted',
|
|
43
|
+
permissionCreated: 'permission.created',
|
|
44
|
+
permissionUpdated: 'permission.updated',
|
|
45
|
+
permissionDeleted: 'permission.deleted',
|
|
46
|
+
directoryCreated: 'directory.created',
|
|
47
|
+
directoryUpdated: 'directory.updated',
|
|
48
|
+
directoryDeleted: 'directory.deleted',
|
|
49
|
+
directoryUserCreated: 'directory_user.created',
|
|
50
|
+
directoryUserUpdated: 'directory_user.updated',
|
|
51
|
+
directoryUserDeleted: 'directory_user.deleted',
|
|
52
|
+
directoryGroupCreated: 'directory_group.created',
|
|
53
|
+
directoryGroupUpdated: 'directory_group.updated',
|
|
54
|
+
directoryGroupDeleted: 'directory_group.deleted',
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/emulate/workos/constants.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,WAAW,EAAE,eAAe;IAC5B,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,WAAW;IACtB,WAAW,EAAE,cAAc;CACnB,CAAC;AAEX,oCAAoC;AACpC,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,WAAW,EAAE,eAAe;IAC5B,QAAQ,EAAE,YAAY;IACtB,SAAS,EAAE,aAAa;IACxB,WAAW,EAAE,eAAe;IAC5B,WAAW,EAAE,eAAe;CACpB,CAAC;AAEX,qCAAqC;AACrC,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,WAAW,EAAE,cAAc;IAC3B,WAAW,EAAE,cAAc;IAC3B,WAAW,EAAE,cAAc;IAC3B,mBAAmB,EAAE,sBAAsB;IAC3C,mBAAmB,EAAE,sBAAsB;IAC3C,mBAAmB,EAAE,sBAAsB;IAC3C,yBAAyB,EAAE,6BAA6B;IACxD,0BAA0B,EAAE,8BAA8B;IAC1D,yBAAyB,EAAE,6BAA6B;IACxD,yBAAyB,EAAE,6BAA6B;IACxD,6BAA6B,EAAE,iCAAiC;IAChE,6BAA6B,EAAE,iCAAiC;IAChE,6BAA6B,EAAE,iCAAiC;IAChE,iBAAiB,EAAE,oBAAoB;IACvC,iBAAiB,EAAE,oBAAoB;IACvC,iBAAiB,EAAE,oBAAoB;IACvC,cAAc,EAAE,iBAAiB;IACjC,cAAc,EAAE,iBAAiB;IACjC,iBAAiB,EAAE,oBAAoB;IACvC,kBAAkB,EAAE,qBAAqB;IACzC,iBAAiB,EAAE,oBAAoB;IACvC,gBAAgB,EAAE,mBAAmB;IACrC,WAAW,EAAE,cAAc;IAC3B,WAAW,EAAE,cAAc;IAC3B,WAAW,EAAE,cAAc;IAC3B,iBAAiB,EAAE,oBAAoB;IACvC,iBAAiB,EAAE,oBAAoB;IACvC,iBAAiB,EAAE,oBAAoB;IACvC,gBAAgB,EAAE,mBAAmB;IACrC,gBAAgB,EAAE,mBAAmB;IACrC,gBAAgB,EAAE,mBAAmB;IACrC,oBAAoB,EAAE,wBAAwB;IAC9C,oBAAoB,EAAE,wBAAwB;IAC9C,oBAAoB,EAAE,wBAAwB;IAC9C,qBAAqB,EAAE,yBAAyB;IAChD,qBAAqB,EAAE,yBAAyB;IAChD,qBAAqB,EAAE,yBAAyB;CACxC,CAAC","sourcesContent":["/** Typed keys for Store.getData/setData */\nexport const STORE_KEYS = {\n workosStore: '_workos_store',\n eventBus: 'eventBus',\n apiKeyMap: 'apiKeyMap',\n jwtTemplate: 'jwt_template',\n} as const;\n\n/** Prefix for dynamic store keys */\nexport const STORE_KEY_PREFIXES = {\n pendingAuth: 'pending_auth:',\n ssoToken: 'sso_token:',\n ssoLogout: 'sso_logout:',\n auditSchema: 'audit_schema_',\n radarIpList: 'radar_ip_list',\n} as const;\n\n/** All WorkOS webhook event names */\nexport const EVENTS = {\n userCreated: 'user.created',\n userUpdated: 'user.updated',\n userDeleted: 'user.deleted',\n organizationCreated: 'organization.created',\n organizationUpdated: 'organization.updated',\n organizationDeleted: 'organization.deleted',\n organizationDomainCreated: 'organization_domain.created',\n organizationDomainVerified: 'organization_domain.verified',\n organizationDomainUpdated: 'organization_domain.updated',\n organizationDomainDeleted: 'organization_domain.deleted',\n organizationMembershipCreated: 'organization_membership.created',\n organizationMembershipUpdated: 'organization_membership.updated',\n organizationMembershipDeleted: 'organization_membership.deleted',\n connectionCreated: 'connection.created',\n connectionUpdated: 'connection.updated',\n connectionDeleted: 'connection.deleted',\n sessionCreated: 'session.created',\n sessionRevoked: 'session.revoked',\n invitationCreated: 'invitation.created',\n invitationAccepted: 'invitation.accepted',\n invitationRevoked: 'invitation.revoked',\n invitationResent: 'invitation.resent',\n roleCreated: 'role.created',\n roleUpdated: 'role.updated',\n roleDeleted: 'role.deleted',\n permissionCreated: 'permission.created',\n permissionUpdated: 'permission.updated',\n permissionDeleted: 'permission.deleted',\n directoryCreated: 'directory.created',\n directoryUpdated: 'directory.updated',\n directoryDeleted: 'directory.deleted',\n directoryUserCreated: 'directory_user.created',\n directoryUserUpdated: 'directory_user.updated',\n directoryUserDeleted: 'directory_user.deleted',\n directoryGroupCreated: 'directory_group.created',\n directoryGroupUpdated: 'directory_group.updated',\n directoryGroupDeleted: 'directory_group.deleted',\n} as const;\n\nexport type WorkOSEventName = (typeof EVENTS)[keyof typeof EVENTS];\n"]}
|