api-emulator 0.5.1 → 0.5.2

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/dist/api.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/external-plugin-adapter.ts","../src/default-plugin-catalog.ts","../src/registry.ts","../src/base-url.ts","../src/service-runtime.ts","../src/api.ts"],"sourcesContent":["import type { ServicePlugin, Store, AuthFallback, WebhookDispatcher } from \"@emulators/core\";\nimport { isAbsolute, resolve } from \"path\";\nimport type { PluginModule } from \"./plugin-types.js\";\n\nexport interface ExternalPluginModule {\n plugin?: ServicePlugin;\n default?: ServicePlugin;\n seedFromConfig?(store: Store, baseUrl: string, config: unknown, webhooks?: WebhookDispatcher): void;\n label?: string;\n endpoints?: string;\n defaultFallback?(svcSeedConfig?: Record<string, unknown>): AuthFallback;\n initConfig?: Record<string, unknown>;\n}\n\nexport async function loadExternalPluginModule(specifier: string): Promise<PluginModule> {\n const modulePath = specifier.startsWith(\".\") || isAbsolute(specifier) ? resolve(specifier) : specifier;\n\n const mod = (await import(modulePath)) as ExternalPluginModule;\n const plugin = mod.plugin ?? mod.default;\n if (!plugin || typeof plugin.register !== \"function\" || typeof plugin.name !== \"string\") {\n throw new Error(`Plugin \"${specifier}\" must export a ServicePlugin (as \"plugin\" or default export)`);\n }\n\n const name = plugin.name;\n return {\n name,\n label: mod.label ?? `${name} (external plugin)`,\n endpoints: mod.endpoints ?? \"\",\n async load() {\n return {\n plugin,\n seedFromConfig: mod.seedFromConfig,\n };\n },\n defaultFallback: mod.defaultFallback ?? (() => ({ login: \"admin\", id: 1, scopes: [] })),\n initConfig: mod.initConfig ?? {},\n };\n}\n\nexport async function loadExternalPlugin(specifier: string): Promise<{ name: string; entry: PluginModule }> {\n const pluginModule = await loadExternalPluginModule(specifier);\n return { name: pluginModule.name, entry: pluginModule };\n}\n","import type { Store, AppKeyResolver } from \"@emulators/core\";\nimport type { PluginModule } from \"./plugin-types.js\";\n\nconst DEFAULT_PLUGIN_NAME_LIST = [\n \"vercel\",\n \"github\",\n \"google\",\n \"slack\",\n \"apple\",\n \"microsoft\",\n \"okta\",\n \"aws\",\n \"resend\",\n \"stripe\",\n \"mongoatlas\",\n \"clerk\",\n] as const;\nexport type ServiceName = (typeof DEFAULT_PLUGIN_NAME_LIST)[number];\nexport const DEFAULT_PLUGIN_NAMES: readonly ServiceName[] = DEFAULT_PLUGIN_NAME_LIST;\nexport const SERVICE_NAMES: readonly ServiceName[] = DEFAULT_PLUGIN_NAMES;\n\nexport const DEFAULT_PLUGIN_REGISTRY: Record<ServiceName, PluginModule> = {\n vercel: {\n name: \"vercel\",\n label: \"Vercel REST API emulator\",\n endpoints: \"projects, deployments, domains, env vars, users, teams, file uploads, protection bypass\",\n async load() {\n const mod = await import(\"@emulators/vercel\");\n return { plugin: mod.vercelPlugin, seedFromConfig: mod.seedFromConfig };\n },\n defaultFallback(cfg) {\n const firstLogin = (cfg?.users as Array<{ username?: string }> | undefined)?.[0]?.username ?? \"admin\";\n return { login: firstLogin, id: 1, scopes: [] };\n },\n initConfig: {\n vercel: {\n users: [{ username: \"developer\", name: \"Developer\", email: \"dev@example.com\" }],\n teams: [{ slug: \"my-team\", name: \"My Team\" }],\n projects: [{ name: \"my-app\", team: \"my-team\", framework: \"nextjs\" }],\n integrations: [\n {\n client_id: \"oac_example_client_id\",\n client_secret: \"example_client_secret\",\n name: \"My Vercel App\",\n redirect_uris: [\"http://localhost:3000/api/auth/callback/vercel\"],\n },\n ],\n },\n },\n },\n\n github: {\n name: \"github\",\n label: \"GitHub REST API emulator\",\n endpoints:\n \"users, repos, issues, PRs, comments, reviews, labels, milestones, branches, git data, orgs, teams, releases, webhooks, search, actions, checks, rate limit\",\n async load() {\n const mod = await import(\"@emulators/github\");\n return {\n plugin: mod.githubPlugin,\n seedFromConfig: mod.seedFromConfig,\n createAppKeyResolver(store: Store): AppKeyResolver {\n return (appId: number) => {\n try {\n const gh = mod.getGitHubStore(store);\n const ghApp = gh.apps.all().find((a) => a.app_id === appId);\n if (!ghApp) return null;\n return { privateKey: ghApp.private_key, slug: ghApp.slug, name: ghApp.name };\n } catch {\n return null;\n }\n };\n },\n };\n },\n defaultFallback(cfg) {\n const firstLogin = (cfg?.users as Array<{ login?: string }> | undefined)?.[0]?.login ?? \"admin\";\n return { login: firstLogin, id: 1, scopes: [\"repo\", \"user\", \"admin:org\", \"admin:repo_hook\"] };\n },\n initConfig: {\n github: {\n users: [\n {\n login: \"octocat\",\n name: \"The Octocat\",\n email: \"octocat@github.com\",\n bio: \"I am the Octocat\",\n company: \"GitHub\",\n location: \"San Francisco\",\n },\n ],\n orgs: [{ login: \"my-org\", name: \"My Organization\", description: \"A test organization\" }],\n repos: [\n {\n owner: \"octocat\",\n name: \"hello-world\",\n description: \"My first repository\",\n language: \"JavaScript\",\n topics: [\"hello\", \"world\"],\n auto_init: true,\n },\n {\n owner: \"my-org\",\n name: \"org-repo\",\n description: \"An organization repository\",\n language: \"TypeScript\",\n auto_init: true,\n },\n ],\n oauth_apps: [\n {\n client_id: \"Iv1.example_client_id\",\n client_secret: \"example_client_secret\",\n name: \"My App\",\n redirect_uris: [\"http://localhost:3000/api/auth/callback/github\"],\n },\n ],\n },\n },\n },\n\n google: {\n name: \"google\",\n label: \"Google OAuth 2.0 / OpenID Connect + Gmail, Calendar, and Drive emulator\",\n endpoints:\n \"OAuth authorize, token exchange, userinfo, OIDC discovery, token revocation, Gmail messages/drafts/threads/labels/history/settings, Calendar lists/events/freebusy, Drive files/uploads\",\n async load() {\n const mod = await import(\"@emulators/google\");\n return { plugin: mod.googlePlugin, seedFromConfig: mod.seedFromConfig };\n },\n defaultFallback(cfg) {\n const firstEmail = (cfg?.users as Array<{ email?: string }> | undefined)?.[0]?.email ?? \"testuser@gmail.com\";\n return { login: firstEmail, id: 1, scopes: [\"openid\", \"email\", \"profile\"] };\n },\n initConfig: {\n google: {\n users: [\n {\n email: \"testuser@example.com\",\n name: \"Test User\",\n picture: \"https://lh3.googleusercontent.com/a/default-user\",\n email_verified: true,\n },\n ],\n oauth_clients: [\n {\n client_id: \"example-client-id.apps.googleusercontent.com\",\n client_secret: \"GOCSPX-example_secret\",\n name: \"Code App (Google)\",\n redirect_uris: [\"http://localhost:3000/api/auth/callback/google\"],\n },\n ],\n labels: [\n {\n id: \"Label_ops\",\n user_email: \"testuser@example.com\",\n name: \"Ops/Review\",\n color_background: \"#DDEEFF\",\n color_text: \"#111111\",\n },\n ],\n messages: [\n {\n id: \"msg_welcome\",\n user_email: \"testuser@example.com\",\n from: \"welcome@example.com\",\n to: \"testuser@example.com\",\n subject: \"Welcome to the Gmail emulator\",\n body_text: \"You can now test Gmail, Calendar, and Drive flows locally.\",\n label_ids: [\"INBOX\", \"UNREAD\", \"CATEGORY_UPDATES\"],\n date: \"2025-01-04T10:00:00.000Z\",\n },\n ],\n calendars: [\n {\n id: \"primary\",\n user_email: \"testuser@example.com\",\n summary: \"testuser@example.com\",\n primary: true,\n selected: true,\n time_zone: \"UTC\",\n },\n ],\n calendar_events: [\n {\n id: \"evt_kickoff\",\n user_email: \"testuser@example.com\",\n calendar_id: \"primary\",\n summary: \"Project Kickoff\",\n start_date_time: \"2025-01-10T09:00:00.000Z\",\n end_date_time: \"2025-01-10T09:30:00.000Z\",\n },\n ],\n drive_items: [\n {\n id: \"drv_docs\",\n user_email: \"testuser@example.com\",\n name: \"Docs\",\n mime_type: \"application/vnd.google-apps.folder\",\n parent_ids: [\"root\"],\n },\n ],\n },\n },\n },\n\n slack: {\n name: \"slack\",\n label: \"Slack API emulator\",\n endpoints: \"auth, chat, conversations, users, reactions, team, OAuth, incoming webhooks\",\n async load() {\n const mod = await import(\"@emulators/slack\");\n return { plugin: mod.slackPlugin, seedFromConfig: mod.seedFromConfig };\n },\n defaultFallback() {\n return { login: \"U000000001\", id: 1, scopes: [\"chat:write\", \"channels:read\", \"users:read\", \"reactions:write\"] };\n },\n initConfig: {\n slack: {\n team: { name: \"My Workspace\", domain: \"my-workspace\" },\n users: [{ name: \"developer\", real_name: \"Developer\", email: \"dev@example.com\" }],\n channels: [\n { name: \"general\", topic: \"General discussion\" },\n { name: \"random\", topic: \"Random stuff\" },\n ],\n bots: [{ name: \"my-bot\" }],\n oauth_apps: [\n {\n client_id: \"12345.67890\",\n client_secret: \"example_client_secret\",\n name: \"My Slack App\",\n redirect_uris: [\"http://localhost:3000/api/auth/callback/slack\"],\n },\n ],\n },\n },\n },\n\n apple: {\n name: \"apple\",\n label: \"Apple Sign In / OAuth emulator\",\n endpoints: \"OAuth authorize, token exchange, JWKS\",\n async load() {\n const mod = await import(\"@emulators/apple\");\n return { plugin: mod.applePlugin, seedFromConfig: mod.seedFromConfig };\n },\n defaultFallback(cfg) {\n const firstEmail = (cfg?.users as Array<{ email?: string }> | undefined)?.[0]?.email ?? \"testuser@icloud.com\";\n return { login: firstEmail, id: 1, scopes: [\"openid\", \"email\", \"name\"] };\n },\n initConfig: {\n apple: {\n users: [{ email: \"testuser@icloud.com\", name: \"Test User\" }],\n oauth_clients: [\n {\n client_id: \"com.example.app\",\n team_id: \"TEAM001\",\n name: \"My Apple App\",\n redirect_uris: [\"http://localhost:3000/api/auth/callback/apple\"],\n },\n ],\n },\n },\n },\n\n microsoft: {\n name: \"microsoft\",\n label: \"Microsoft Entra ID OAuth 2.0 / OpenID Connect emulator\",\n endpoints: \"OAuth authorize, token exchange, userinfo, OIDC discovery, Graph /me, logout, token revocation\",\n async load() {\n const mod = await import(\"@emulators/microsoft\");\n return { plugin: mod.microsoftPlugin, seedFromConfig: mod.seedFromConfig };\n },\n defaultFallback(cfg) {\n const firstEmail = (cfg?.users as Array<{ email?: string }> | undefined)?.[0]?.email ?? \"testuser@outlook.com\";\n return { login: firstEmail, id: 1, scopes: [\"openid\", \"email\", \"profile\", \"User.Read\"] };\n },\n initConfig: {\n microsoft: {\n users: [{ email: \"testuser@outlook.com\", name: \"Test User\" }],\n oauth_clients: [\n {\n client_id: \"example-client-id\",\n client_secret: \"example-client-secret\",\n name: \"My Microsoft App\",\n redirect_uris: [\"http://localhost:3000/api/auth/callback/microsoft-entra-id\"],\n },\n ],\n },\n },\n },\n\n okta: {\n name: \"okta\",\n label: \"Okta OAuth 2.0 / OpenID Connect + management API emulator\",\n endpoints:\n \"OIDC discovery, JWKS, OAuth authorize/token/userinfo/introspect/revoke/logout, users, groups, apps, authorization servers\",\n async load() {\n const mod = await import(\"@emulators/okta\");\n return { plugin: mod.oktaPlugin, seedFromConfig: mod.seedFromConfig };\n },\n defaultFallback(cfg) {\n const firstLogin =\n (cfg?.users as Array<{ login?: string; email?: string }> | undefined)?.[0]?.login ??\n (cfg?.users as Array<{ login?: string; email?: string }> | undefined)?.[0]?.email ??\n \"testuser@okta.local\";\n return { login: firstLogin, id: 1, scopes: [\"openid\", \"profile\", \"email\", \"groups\"] };\n },\n initConfig: {\n okta: {\n users: [{ login: \"testuser@okta.local\", email: \"testuser@okta.local\", first_name: \"Test\", last_name: \"User\" }],\n groups: [{ name: \"Everyone\", description: \"All users\", type: \"BUILT_IN\", okta_id: \"00g_everyone\" }],\n authorization_servers: [{ id: \"default\", name: \"default\", audiences: [\"api://default\"] }],\n oauth_clients: [\n {\n client_id: \"okta-test-client\",\n client_secret: \"okta-test-secret\",\n name: \"Sample OIDC Client\",\n redirect_uris: [\"http://localhost:3000/callback\"],\n auth_server_id: \"default\",\n },\n ],\n },\n },\n },\n\n aws: {\n name: \"aws\",\n label: \"AWS cloud service emulator\",\n endpoints:\n \"S3 (buckets, objects), SQS (queues, messages), IAM (users, roles, access keys), STS (assume role, caller identity)\",\n async load() {\n const mod = await import(\"@emulators/aws\");\n return { plugin: mod.awsPlugin, seedFromConfig: mod.seedFromConfig };\n },\n defaultFallback() {\n return { login: \"admin\", id: 1, scopes: [\"s3:*\", \"sqs:*\", \"iam:*\", \"sts:*\"] };\n },\n initConfig: {\n aws: {\n region: \"us-east-1\",\n s3: { buckets: [{ name: \"my-app-bucket\" }, { name: \"my-app-uploads\" }] },\n sqs: { queues: [{ name: \"my-app-events\" }, { name: \"my-app-dlq\" }] },\n iam: {\n users: [{ user_name: \"developer\", create_access_key: true }],\n roles: [{ role_name: \"lambda-execution-role\", description: \"Role for Lambda function execution\" }],\n },\n },\n },\n },\n resend: {\n name: \"resend\",\n label: \"Resend email API emulator\",\n endpoints: \"emails, domains, contacts, API keys, inbox UI\",\n async load() {\n const mod = await import(\"@emulators/resend\");\n return { plugin: mod.resendPlugin, seedFromConfig: mod.seedFromConfig };\n },\n defaultFallback() {\n return { login: \"re_test_admin\", id: 1, scopes: [] };\n },\n initConfig: {\n resend: {\n domains: [{ name: \"example.com\", region: \"us-east-1\" }],\n contacts: [{ email: \"test@example.com\", first_name: \"Test\", last_name: \"User\" }],\n },\n },\n },\n stripe: {\n name: \"stripe\",\n label: \"Stripe payments emulator\",\n endpoints:\n \"customers, payment methods, customer sessions, payment intents, charges, products, prices, checkout sessions, webhooks\",\n async load() {\n const mod = await import(\"@emulators/stripe\");\n return { plugin: mod.stripePlugin, seedFromConfig: mod.seedFromConfig };\n },\n defaultFallback() {\n return { login: \"sk_test_admin\", id: 1, scopes: [] };\n },\n initConfig: {\n stripe: {\n customers: [{ email: \"test@example.com\", name: \"Test Customer\" }],\n products: [{ name: \"Pro Plan\", description: \"Monthly pro subscription\" }],\n prices: [{ product_name: \"Pro Plan\", currency: \"usd\", unit_amount: 2000 }],\n },\n },\n },\n mongoatlas: {\n name: \"mongoatlas\",\n label: \"MongoDB Atlas service emulator\",\n endpoints:\n \"Atlas Admin API v2 (projects, clusters, database users, databases, collections), Atlas Data API v1 (findOne, find, insertOne, insertMany, updateOne, updateMany, deleteOne, deleteMany, aggregate)\",\n async load() {\n const mod = await import(\"@emulators/mongoatlas\");\n return { plugin: mod.mongoatlasPlugin, seedFromConfig: mod.seedFromConfig };\n },\n defaultFallback() {\n return { login: \"admin\", id: 1, scopes: [] };\n },\n initConfig: {\n mongoatlas: {\n projects: [{ name: \"Project0\" }],\n clusters: [{ name: \"Cluster0\", project: \"Project0\" }],\n database_users: [{ username: \"admin\", project: \"Project0\" }],\n databases: [{ cluster: \"Cluster0\", name: \"test\", collections: [\"items\"] }],\n },\n },\n },\n clerk: {\n name: \"clerk\",\n label: \"Clerk authentication and user management emulator\",\n endpoints:\n \"OIDC discovery, JWKS, OAuth authorize/token/userinfo, users, email addresses, organizations, memberships, invitations, sessions\",\n async load() {\n const mod = await import(\"@emulators/clerk\");\n return { plugin: mod.clerkPlugin, seedFromConfig: mod.seedFromConfig };\n },\n defaultFallback(cfg) {\n const firstEmail =\n (cfg?.users as Array<{ email_addresses?: string[] }> | undefined)?.[0]?.email_addresses?.[0] ??\n \"test@example.com\";\n return { login: firstEmail, id: 1, scopes: [] };\n },\n initConfig: {\n clerk: {\n users: [\n {\n first_name: \"Test\",\n last_name: \"User\",\n email_addresses: [\"test@example.com\"],\n password: \"clerk_test_password\",\n },\n ],\n organizations: [\n {\n name: \"My Company\",\n slug: \"my-company\",\n members: [{ email: \"test@example.com\", role: \"admin\" }],\n },\n ],\n oauth_applications: [\n {\n client_id: \"clerk_emulate_client\",\n client_secret: \"clerk_emulate_secret\",\n name: \"api-emulator App\",\n redirect_uris: [\"http://localhost:3000/api/auth/callback/clerk\"],\n },\n ],\n },\n },\n },\n};\n","import { loadExternalPluginModule } from \"./external-plugin-adapter.js\";\nimport {\n DEFAULT_PLUGIN_REGISTRY,\n DEFAULT_PLUGIN_NAMES,\n SERVICE_NAMES,\n type ServiceName,\n} from \"./default-plugin-catalog.js\";\nimport type { PluginModule } from \"./plugin-types.js\";\nexport { DEFAULT_PLUGIN_REGISTRY, DEFAULT_PLUGIN_NAMES, SERVICE_NAMES, type ServiceName };\nexport type { LoadedPlugin, LoadedService, PluginModule, ServiceEntry } from \"./plugin-types.js\";\n\nexport const DEFAULT_TOKENS = {\n tokens: {\n test_token_admin: {\n login: \"admin\",\n scopes: [\"repo\", \"user\", \"admin:org\", \"admin:repo_hook\"],\n },\n test_token_user1: {\n login: \"octocat\",\n scopes: [\"repo\", \"user\"],\n },\n },\n};\n\nexport async function resolvePluginModules(pluginSpecifiers: string[] = []): Promise<Record<string, PluginModule>> {\n const results = await Promise.all(pluginSpecifiers.map(loadExternalPluginModule));\n\n const externalEntries: Record<string, PluginModule> = {};\n for (const pluginModule of results) {\n if (pluginModule.name in DEFAULT_PLUGIN_REGISTRY) {\n throw new Error(`Plugin \"${pluginModule.name}\" conflicts with default plugin \"${pluginModule.name}\"`);\n }\n if (pluginModule.name in externalEntries) {\n throw new Error(`Duplicate plugin name \"${pluginModule.name}\"`);\n }\n externalEntries[pluginModule.name] = pluginModule;\n }\n\n return { ...DEFAULT_PLUGIN_REGISTRY, ...externalEntries };\n}\n\nexport const resolveServiceEntries = resolvePluginModules;\n\nexport function getDefaultPluginNames(): string[] {\n return [...DEFAULT_PLUGIN_NAMES];\n}\n","export interface ResolveBaseUrlOptions {\n service: string;\n port: number;\n baseUrl?: string;\n seedBaseUrl?: string;\n}\n\n/**\n * Fallback chain:\n * 1. Per-service baseUrl from seed config\n * 2. Explicit baseUrl (CLI flag or programmatic option)\n * 3. API_EMULATOR_BASE_URL env var (with {service} interpolation)\n * 4. EMULATE_BASE_URL env var for backward compatibility (with {service} interpolation)\n * 5. PORTLESS_URL env var (with {service} interpolation)\n * 6. http://localhost:<port>\n */\nexport function resolveBaseUrl(opts: ResolveBaseUrlOptions): string {\n if (opts.seedBaseUrl) {\n return opts.seedBaseUrl.replace(/\\{service\\}/g, opts.service);\n }\n if (opts.baseUrl) {\n return opts.baseUrl.replace(/\\{service\\}/g, opts.service);\n }\n const envBaseUrl = process.env.API_EMULATOR_BASE_URL ?? process.env.EMULATE_BASE_URL;\n if (envBaseUrl) {\n return envBaseUrl.replace(/\\{service\\}/g, opts.service);\n }\n const portlessUrl = process.env.PORTLESS_URL;\n if (portlessUrl) {\n return portlessUrl.replace(/\\{service\\}/g, opts.service);\n }\n return `http://localhost:${opts.port}`;\n}\n","import { createServer, type AppKeyResolver, type Store } from \"@emulators/core\";\nimport { serve } from \"@hono/node-server\";\nimport type { LoadedPlugin, PluginModule } from \"./registry.js\";\n\nexport interface SeedConfig {\n tokens?: Record<string, { login: string; scopes?: string[] }>;\n [service: string]: unknown;\n}\n\nexport type TokenMap = Record<string, { login: string; id: number; scopes?: string[] }>;\n\nexport interface ServiceRuntimeOptions {\n service: string;\n pluginModule: PluginModule;\n loadedPlugin: LoadedPlugin;\n port: number;\n baseUrl: string;\n tokens: TokenMap;\n seedConfig?: Record<string, unknown>;\n}\n\nexport interface RunningService {\n service: string;\n url: string;\n store: Store;\n reset(): void;\n close(): Promise<void>;\n}\n\nexport function createAuthTokens(seedConfig?: SeedConfig | null): TokenMap {\n const tokens: TokenMap = {};\n if (seedConfig?.tokens) {\n let tokenId = 100;\n for (const [token, user] of Object.entries(seedConfig.tokens)) {\n tokens[token] = { login: user.login, id: tokenId++, scopes: user.scopes };\n }\n } else {\n tokens[\"test_token_admin\"] = { login: \"admin\", id: 2, scopes: [\"repo\", \"user\", \"admin:org\", \"admin:repo_hook\"] };\n }\n return tokens;\n}\n\nexport function createServiceRuntime(options: ServiceRuntimeOptions): RunningService {\n const { service, pluginModule, loadedPlugin, port, baseUrl, tokens, seedConfig } = options;\n\n const resolverRef: { current?: AppKeyResolver } = {};\n const appKeyResolver: AppKeyResolver | undefined = loadedPlugin.createAppKeyResolver\n ? (appId) => resolverRef.current!(appId)\n : undefined;\n const fallbackUser = pluginModule.defaultFallback(seedConfig);\n\n const { app, store, webhooks } = createServer(loadedPlugin.plugin, {\n port,\n baseUrl,\n tokens,\n appKeyResolver,\n fallbackUser,\n });\n resolverRef.current = loadedPlugin.createAppKeyResolver?.(store);\n\n const seed = () => {\n loadedPlugin.plugin.seed?.(store, baseUrl);\n if (seedConfig && loadedPlugin.seedFromConfig) {\n loadedPlugin.seedFromConfig(store, baseUrl, seedConfig, webhooks);\n }\n };\n seed();\n\n const httpServer = serve({ fetch: app.fetch, port });\n\n return {\n service,\n url: baseUrl,\n store,\n reset() {\n store.reset();\n seed();\n },\n close(): Promise<void> {\n return new Promise((resolve, reject) => {\n httpServer.close((err) => {\n if (err) reject(err);\n else resolve();\n });\n });\n },\n };\n}\n","import { resolvePluginModules } from \"./registry.js\";\nexport type { ServiceName } from \"./registry.js\";\nimport type { ServiceName } from \"./registry.js\";\nimport { resolveBaseUrl } from \"./base-url.js\";\nimport { createAuthTokens, createServiceRuntime, type SeedConfig } from \"./service-runtime.js\";\n\nexport type { SeedConfig };\n\nexport interface EmulatorOptions {\n service: ServiceName | (string & {});\n port?: number;\n seed?: SeedConfig;\n baseUrl?: string;\n plugins?: string[];\n}\n\nexport interface Emulator {\n url: string;\n reset(): void;\n close(): Promise<void>;\n}\n\nexport async function createEmulator(options: EmulatorOptions): Promise<Emulator> {\n const { service, port = 4000, seed: seedConfig, plugins = [] } = options;\n\n const registry = await resolvePluginModules(plugins);\n const pluginModule = registry[service];\n if (!pluginModule) {\n throw new Error(`Unknown service: ${service}`);\n }\n\n const loadedPlugin = await pluginModule.load();\n\n const svcSeedConfig = seedConfig?.[service] as Record<string, unknown> | undefined;\n const seedBaseUrl =\n typeof svcSeedConfig?.baseUrl === \"string\" && svcSeedConfig.baseUrl.length > 0 ? svcSeedConfig.baseUrl : undefined;\n const baseUrl = resolveBaseUrl({ service, port, baseUrl: options.baseUrl, seedBaseUrl });\n const running = createServiceRuntime({\n service,\n pluginModule,\n loadedPlugin,\n port,\n baseUrl,\n tokens: createAuthTokens(seedConfig),\n seedConfig: svcSeedConfig,\n });\n\n return {\n url: running.url,\n reset: running.reset,\n close: running.close,\n };\n}\n"],"mappings":"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","names":["resolve"]}
1
+ {"version":3,"sources":["../src/external-plugin-adapter.ts","../src/plugin-manifest.ts","../src/plugin-lock.ts","../src/default-plugin-catalog.ts","../src/registry.ts","../src/base-url.ts","../src/service-runtime.ts","../src/api.ts"],"sourcesContent":["import type { ServicePlugin, Store, AuthFallback, WebhookDispatcher } from \"@api-emulator/core\";\nimport { isAbsolute, resolve } from \"path\";\nimport { readPluginManifest, validatePluginManifest, type PluginManifest } from \"./plugin-manifest.js\";\nimport type { PluginModule } from \"./plugin-types.js\";\n\nexport interface ExternalPluginModule {\n plugin?: ServicePlugin;\n default?: ServicePlugin;\n seedFromConfig?(store: Store, baseUrl: string, config: unknown, webhooks?: WebhookDispatcher): void;\n label?: string;\n endpoints?: string;\n manifest?: PluginManifest;\n contract?: unknown;\n defaultFallback?(svcSeedConfig?: Record<string, unknown>): AuthFallback;\n initConfig?: Record<string, unknown>;\n}\n\nexport async function loadExternalPluginModule(specifier: string): Promise<PluginModule> {\n const modulePath = specifier.startsWith(\".\") || isAbsolute(specifier) ? resolve(specifier) : specifier;\n\n const mod = (await import(modulePath)) as ExternalPluginModule;\n const plugin = mod.plugin ?? mod.default;\n if (!plugin || typeof plugin.register !== \"function\" || typeof plugin.name !== \"string\") {\n throw new Error(`Plugin \"${specifier}\" must export a ServicePlugin (as \"plugin\" or default export)`);\n }\n\n const name = plugin.name;\n const manifest = validatePluginManifest(readPluginManifest(mod), name);\n return {\n name,\n label: manifest.label,\n endpoints: manifest.endpoints,\n manifest,\n async load() {\n return {\n plugin,\n seedFromConfig: mod.seedFromConfig,\n };\n },\n defaultFallback: mod.defaultFallback ?? (() => ({ login: \"admin\", id: 1, scopes: [] })),\n initConfig: manifest.initConfig,\n };\n}\n\nexport async function loadExternalPlugin(specifier: string): Promise<{ name: string; entry: PluginModule }> {\n const pluginModule = await loadExternalPluginModule(specifier);\n return { name: pluginModule.name, entry: pluginModule };\n}\n","import type { AuthFallback } from \"@api-emulator/core\";\n\nexport interface PluginManifest {\n name?: string;\n label?: string;\n endpoints?: string;\n initConfig?: Record<string, unknown>;\n contract?: unknown;\n compatibility?: {\n apiEmulator?: string;\n };\n}\n\ninterface LegacyManifestFields {\n label?: string;\n endpoints?: string;\n initConfig?: Record<string, unknown>;\n contract?: unknown;\n defaultFallback?(svcSeedConfig?: Record<string, unknown>): AuthFallback;\n}\n\nexport function readPluginManifest(mod: { manifest?: PluginManifest } & LegacyManifestFields): PluginManifest {\n return {\n label: mod.label,\n endpoints: mod.endpoints,\n initConfig: mod.initConfig,\n contract: mod.contract,\n ...mod.manifest,\n };\n}\n\nexport function validatePluginManifest(\n manifest: PluginManifest,\n pluginName: string,\n): Required<Pick<PluginManifest, \"label\" | \"endpoints\" | \"initConfig\">> &\n Omit<PluginManifest, \"label\" | \"endpoints\" | \"initConfig\"> {\n if (manifest.name && manifest.name !== pluginName) {\n throw new Error(`Plugin manifest name \"${manifest.name}\" does not match plugin name \"${pluginName}\"`);\n }\n\n return {\n ...manifest,\n label: manifest.label ?? `${pluginName} (external plugin)`,\n endpoints: manifest.endpoints ?? \"\",\n initConfig: manifest.initConfig ?? {},\n };\n}\n","import { existsSync, readFileSync, writeFileSync } from \"fs\";\nimport { resolve } from \"path\";\n\nexport const PLUGIN_LOCK_FILE = \"api-emulator.lock\";\n\nexport interface PluginLockEntry {\n name: string;\n source: \"registry\" | \"specifier\";\n specifier: string;\n sourceId?: string;\n packageName?: string;\n version?: string;\n}\n\nexport interface PluginLock {\n version: 1;\n plugins: Record<string, PluginLockEntry>;\n}\n\nexport function createEmptyPluginLock(): PluginLock {\n return { version: 1, plugins: {} };\n}\n\nexport function readPluginLock(cwd = process.cwd()): PluginLock {\n const path = resolve(cwd, PLUGIN_LOCK_FILE);\n if (!existsSync(path)) return createEmptyPluginLock();\n\n const parsed = JSON.parse(readFileSync(path, \"utf-8\")) as PluginLock;\n if (parsed.version !== 1 || typeof parsed.plugins !== \"object\" || parsed.plugins === null) {\n throw new Error(`Invalid ${PLUGIN_LOCK_FILE}`);\n }\n return parsed;\n}\n\nexport function writePluginLock(lock: PluginLock, cwd = process.cwd()): void {\n const sortedPlugins = Object.fromEntries(Object.entries(lock.plugins).sort(([a], [b]) => a.localeCompare(b)));\n const content = `${JSON.stringify({ version: 1, plugins: sortedPlugins }, null, 2)}\\n`;\n writeFileSync(resolve(cwd, PLUGIN_LOCK_FILE), content, \"utf-8\");\n}\n\nexport function getLockedPluginSpecifiers(cwd = process.cwd()): string[] {\n return Object.values(readPluginLock(cwd).plugins).map((entry) => entry.specifier);\n}\n","import type { PluginModule } from \"./plugin-types.js\";\n\nexport type ServiceName = string;\nexport const DEFAULT_PLUGIN_NAMES: readonly ServiceName[] = [];\nexport const SERVICE_NAMES: readonly ServiceName[] = DEFAULT_PLUGIN_NAMES;\nexport const DEFAULT_PLUGIN_REGISTRY: Record<ServiceName, PluginModule> = {};\n","import { loadExternalPluginModule } from \"./external-plugin-adapter.js\";\nimport { getLockedPluginSpecifiers } from \"./plugin-lock.js\";\nimport {\n DEFAULT_PLUGIN_REGISTRY,\n DEFAULT_PLUGIN_NAMES,\n SERVICE_NAMES,\n type ServiceName,\n} from \"./default-plugin-catalog.js\";\nimport type { PluginModule } from \"./plugin-types.js\";\nexport { DEFAULT_PLUGIN_REGISTRY, DEFAULT_PLUGIN_NAMES, SERVICE_NAMES, type ServiceName };\nexport type { LoadedPlugin, LoadedService, PluginModule, ServiceEntry } from \"./plugin-types.js\";\n\nexport interface ResolvePluginModulesOptions {\n includeInstalled?: boolean;\n}\n\nexport const DEFAULT_TOKENS = {\n tokens: {\n test_token_admin: {\n login: \"admin\",\n scopes: [\"repo\", \"user\", \"admin:org\", \"admin:repo_hook\"],\n },\n test_token_user1: {\n login: \"octocat\",\n scopes: [\"repo\", \"user\"],\n },\n },\n};\n\nexport async function resolvePluginModules(\n pluginSpecifiers: string[] = [],\n options: ResolvePluginModulesOptions = {},\n): Promise<Record<string, PluginModule>> {\n const installedSpecifiers = options.includeInstalled ? getLockedPluginSpecifiers() : [];\n const allSpecifiers = [...installedSpecifiers, ...pluginSpecifiers];\n const results = await Promise.all(allSpecifiers.map(loadExternalPluginModule));\n\n const externalEntries: Record<string, PluginModule> = {};\n for (const pluginModule of results) {\n if (pluginModule.name in DEFAULT_PLUGIN_REGISTRY) {\n throw new Error(`Plugin \"${pluginModule.name}\" conflicts with default plugin \"${pluginModule.name}\"`);\n }\n if (pluginModule.name in externalEntries) {\n throw new Error(`Duplicate plugin name \"${pluginModule.name}\"`);\n }\n externalEntries[pluginModule.name] = pluginModule;\n }\n\n return { ...DEFAULT_PLUGIN_REGISTRY, ...externalEntries };\n}\n\nexport const resolveServiceEntries = resolvePluginModules;\n\nexport function getDefaultPluginNames(): string[] {\n return [...DEFAULT_PLUGIN_NAMES];\n}\n","export interface ResolveBaseUrlOptions {\n service: string;\n port: number;\n baseUrl?: string;\n seedBaseUrl?: string;\n}\n\n/**\n * Fallback chain:\n * 1. Per-service baseUrl from seed config\n * 2. Explicit baseUrl (CLI flag or programmatic option)\n * 3. API_EMULATOR_BASE_URL env var (with {service} interpolation)\n * 4. EMULATE_BASE_URL env var for backward compatibility (with {service} interpolation)\n * 5. PORTLESS_URL env var (with {service} interpolation)\n * 6. http://localhost:<port>\n */\nexport function resolveBaseUrl(opts: ResolveBaseUrlOptions): string {\n if (opts.seedBaseUrl) {\n return opts.seedBaseUrl.replace(/\\{service\\}/g, opts.service);\n }\n if (opts.baseUrl) {\n return opts.baseUrl.replace(/\\{service\\}/g, opts.service);\n }\n const envBaseUrl = process.env.API_EMULATOR_BASE_URL ?? process.env.EMULATE_BASE_URL;\n if (envBaseUrl) {\n return envBaseUrl.replace(/\\{service\\}/g, opts.service);\n }\n const portlessUrl = process.env.PORTLESS_URL;\n if (portlessUrl) {\n return portlessUrl.replace(/\\{service\\}/g, opts.service);\n }\n return `http://localhost:${opts.port}`;\n}\n","import {\n createServer,\n createStoreFixture,\n fixtureStoreSnapshot,\n type AppKeyResolver,\n type FixtureInteraction,\n type FixtureSource,\n type Store,\n type StoreFixture,\n type StoreFixtureOptions,\n type StoreSnapshot,\n} from \"@api-emulator/core\";\nimport { serve } from \"@hono/node-server\";\nimport type { LoadedPlugin, PluginModule } from \"./registry.js\";\n\nexport interface SeedConfig {\n tokens?: Record<string, { login: string; scopes?: string[] }>;\n [service: string]: unknown;\n}\n\nexport type TokenMap = Record<string, { login: string; id: number; scopes?: string[] }>;\n\nexport interface ServiceRuntimeOptions {\n service: string;\n pluginModule: PluginModule;\n loadedPlugin: LoadedPlugin;\n port: number;\n baseUrl: string;\n tokens: TokenMap;\n seedConfig?: Record<string, unknown>;\n}\n\nexport interface RunningService {\n service: string;\n url: string;\n store: Store;\n snapshot(): StoreSnapshot;\n restore(fixture: FixtureSource): void;\n exportFixture(options?: StoreFixtureOptions): StoreFixture;\n resetToFixture(fixture: FixtureSource): void;\n reset(): void;\n close(): Promise<void>;\n}\n\nexport function createAuthTokens(seedConfig?: SeedConfig | null): TokenMap {\n const tokens: TokenMap = {};\n if (seedConfig?.tokens) {\n let tokenId = 100;\n for (const [token, user] of Object.entries(seedConfig.tokens)) {\n tokens[token] = { login: user.login, id: tokenId++, scopes: user.scopes };\n }\n } else {\n tokens[\"test_token_admin\"] = { login: \"admin\", id: 2, scopes: [\"repo\", \"user\", \"admin:org\", \"admin:repo_hook\"] };\n }\n return tokens;\n}\n\nexport function createServiceRuntime(options: ServiceRuntimeOptions): RunningService {\n const { service, pluginModule, loadedPlugin, port, baseUrl, tokens, seedConfig } = options;\n\n const resolverRef: { current?: AppKeyResolver } = {};\n const appKeyResolver: AppKeyResolver | undefined = loadedPlugin.createAppKeyResolver\n ? (appId) => resolverRef.current!(appId)\n : undefined;\n const fallbackUser = pluginModule.defaultFallback(seedConfig);\n\n const { app, store, webhooks } = createServer(loadedPlugin.plugin, {\n port,\n baseUrl,\n tokens,\n appKeyResolver,\n fallbackUser,\n });\n resolverRef.current = loadedPlugin.createAppKeyResolver?.(store);\n\n const seed = () => {\n loadedPlugin.plugin.seed?.(store, baseUrl);\n if (seedConfig && loadedPlugin.seedFromConfig) {\n loadedPlugin.seedFromConfig(store, baseUrl, seedConfig, webhooks);\n }\n };\n seed();\n\n const httpServer = serve({ fetch: app.fetch, port });\n\n return {\n service,\n url: baseUrl,\n store,\n snapshot() {\n return store.snapshot();\n },\n restore(fixture) {\n store.restore(fixtureStoreSnapshot(fixture));\n },\n exportFixture(options = {}) {\n const interactions = store.getData<FixtureInteraction[]>(\"api-emulator:interactions\");\n return createStoreFixture(service, store.snapshot(), {\n ...options,\n interactions: options.interactions ?? interactions,\n });\n },\n resetToFixture(fixture) {\n store.reset();\n store.restore(fixtureStoreSnapshot(fixture));\n },\n reset() {\n store.reset();\n seed();\n },\n close(): Promise<void> {\n return new Promise((resolve, reject) => {\n httpServer.close((err) => {\n if (err) reject(err);\n else resolve();\n });\n });\n },\n };\n}\n","import { resolvePluginModules } from \"./registry.js\";\nexport type { ServiceName } from \"./registry.js\";\nimport type { ServiceName } from \"./registry.js\";\nimport type { FixtureSource, StoreFixture, StoreFixtureOptions, StoreSnapshot } from \"@api-emulator/core\";\nimport { resolveBaseUrl } from \"./base-url.js\";\nimport { createAuthTokens, createServiceRuntime, type SeedConfig } from \"./service-runtime.js\";\n\nexport type { SeedConfig };\nexport type {\n FixtureInteraction,\n FixtureSource,\n StoreFixture,\n StoreFixtureOptions,\n StoreSnapshot,\n} from \"@api-emulator/core\";\n\nexport interface EmulatorOptions {\n service: ServiceName | (string & {});\n port?: number;\n seed?: SeedConfig;\n baseUrl?: string;\n plugins?: string[];\n}\n\nexport interface Emulator {\n url: string;\n snapshot(): StoreSnapshot;\n restore(fixture: FixtureSource): void;\n exportFixture(options?: StoreFixtureOptions): StoreFixture;\n resetToFixture(fixture: FixtureSource): void;\n reset(): void;\n close(): Promise<void>;\n}\n\nexport async function createEmulator(options: EmulatorOptions): Promise<Emulator> {\n const { service, port = 4000, seed: seedConfig, plugins = [] } = options;\n\n const registry = await resolvePluginModules(plugins);\n const pluginModule = registry[service];\n if (!pluginModule) {\n throw new Error(`Unknown service: ${service}`);\n }\n\n const loadedPlugin = await pluginModule.load();\n\n const svcSeedConfig = seedConfig?.[service] as Record<string, unknown> | undefined;\n const seedBaseUrl =\n typeof svcSeedConfig?.baseUrl === \"string\" && svcSeedConfig.baseUrl.length > 0 ? svcSeedConfig.baseUrl : undefined;\n const baseUrl = resolveBaseUrl({ service, port, baseUrl: options.baseUrl, seedBaseUrl });\n const running = createServiceRuntime({\n service,\n pluginModule,\n loadedPlugin,\n port,\n baseUrl,\n tokens: createAuthTokens(seedConfig),\n seedConfig: svcSeedConfig,\n });\n\n return {\n url: running.url,\n snapshot: running.snapshot,\n restore: running.restore,\n exportFixture: running.exportFixture,\n resetToFixture: running.resetToFixture,\n reset: running.reset,\n close: running.close,\n };\n}\n"],"mappings":"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","names":["resolve","options","resolve"]}