api-emulator 0.5.0 → 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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/external-plugin-adapter.ts","../src/default-plugin-catalog.ts","../src/registry.ts","../src/commands/start.ts","../src/portless.ts","../src/base-url.ts","../src/service-runtime.ts","../src/commands/init.ts","../src/commands/list.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { startCommand } from \"./commands/start.js\";\nimport { initCommand } from \"./commands/init.js\";\nimport { listCommand } from \"./commands/list.js\";\n\ndeclare const PKG_VERSION: string;\nconst pkg = { version: PKG_VERSION };\n\nconst defaultPort = process.env.API_EMULATOR_PORT ?? process.env.EMULATE_PORT ?? process.env.PORT ?? \"4000\";\n\nconst program = new Command();\n\nprogram\n .name(\"api-emulator\")\n .description(\"Local API emulators you can run, share, and extend with plugins\")\n .version(pkg.version);\n\nprogram\n .command(\"start\", { isDefault: true })\n .description(\"Start the emulator server\")\n .option(\"-p, --port <port>\", \"Base port\", defaultPort)\n .option(\"-s, --service <services>\", \"Comma-separated services to enable\")\n .option(\"--seed <file>\", \"Path to seed config file\")\n .option(\"--base-url <url>\", \"Override advertised base URL (supports {service} template)\")\n .option(\"--portless\", \"Serve over HTTPS via portless (auto-registers aliases)\")\n .option(\"--plugin <plugins>\", \"Comma-separated external plugin paths or package names\")\n .action(async (opts) => {\n const port = parseInt(opts.port, 10);\n if (Number.isNaN(port) || port < 1 || port > 65535) {\n console.error(`Invalid port: ${opts.port}`);\n process.exit(1);\n }\n await startCommand({\n port,\n service: opts.service,\n seed: opts.seed,\n baseUrl: opts.baseUrl,\n portless: opts.portless,\n plugin: opts.plugin,\n });\n });\n\nprogram\n .command(\"init\")\n .description(\"Generate a starter config file\")\n .option(\"-s, --service <service>\", \"Service to generate config for\", \"all\")\n .option(\"--plugin <plugins>\", \"Comma-separated external plugin paths or package names\")\n .action(async (opts) => {\n await initCommand({ service: opts.service, plugin: opts.plugin });\n });\n\nprogram\n .command(\"list\")\n .alias(\"list-services\")\n .description(\"List available services\")\n .option(\"--plugin <plugins>\", \"Comma-separated external plugin paths or package names\")\n .action(async (opts) => {\n await listCommand({ plugin: opts.plugin });\n });\n\nprogram.parse();\n","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","import { resolvePluginModules, getDefaultPluginNames, type LoadedPlugin, type PluginModule } from \"../registry.js\";\nimport { readFileSync, existsSync } from \"fs\";\nimport { resolve } from \"path\";\nimport { parse as parseYaml } from \"yaml\";\nimport pc from \"picocolors\";\nimport { ensurePortless, registerAliases, removeAliases, portlessBaseUrl, type PortlessAlias } from \"../portless.js\";\nimport { resolveBaseUrl } from \"../base-url.js\";\nimport { createAuthTokens, createServiceRuntime, type RunningService, type SeedConfig } from \"../service-runtime.js\";\n\ndeclare const PKG_VERSION: string;\nconst pkg = { version: PKG_VERSION };\n\nexport interface StartOptions {\n port: number;\n service?: string;\n seed?: string;\n baseUrl?: string;\n portless?: boolean;\n plugin?: string;\n}\n\ninterface LoadResult {\n config: SeedConfig;\n source: string;\n}\n\nfunction loadSeedConfig(seedPath?: string): LoadResult | null {\n if (seedPath) {\n const fullPath = resolve(seedPath);\n if (!existsSync(fullPath)) {\n console.error(`Seed file not found: ${fullPath}`);\n process.exit(1);\n }\n const content = readFileSync(fullPath, \"utf-8\");\n try {\n const config = fullPath.endsWith(\".json\") ? JSON.parse(content) : parseYaml(content);\n return { config, source: seedPath };\n } catch (err) {\n console.error(`Failed to parse ${seedPath}: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n }\n\n const autoFiles = [\n \"api-emulator.config.yaml\",\n \"api-emulator.config.yml\",\n \"api-emulator.config.json\",\n \"emulate.config.yaml\",\n \"emulate.config.yml\",\n \"emulate.config.json\",\n \"service-emulator.config.yaml\",\n \"service-emulator.config.yml\",\n \"service-emulator.config.json\",\n ];\n\n for (const file of autoFiles) {\n const fullPath = resolve(file);\n if (existsSync(fullPath)) {\n const content = readFileSync(fullPath, \"utf-8\");\n try {\n const config = fullPath.endsWith(\".json\") ? JSON.parse(content) : parseYaml(content);\n return { config, source: file };\n } catch (err) {\n console.error(`Failed to parse ${file}: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n }\n }\n\n return null;\n}\n\nfunction inferServicesFromConfig(config: SeedConfig, availableServices: string[]): string[] | null {\n const found = availableServices.filter((k) => k in config);\n return found.length > 0 ? [...found] : null;\n}\n\nexport async function startCommand(options: StartOptions): Promise<void> {\n const { port: basePort } = options;\n\n if (options.portless && options.baseUrl) {\n console.error(\"--portless and --base-url are mutually exclusive.\");\n process.exit(1);\n }\n\n const loaded = loadSeedConfig(options.seed);\n const seedConfig = loaded?.config ?? null;\n const configSource = loaded?.source ?? null;\n\n const pluginSpecifiers =\n options.plugin\n ?.split(\",\")\n .map((s) => s.trim())\n .filter(Boolean) ?? [];\n let allPluginModules: Record<string, PluginModule>;\n try {\n allPluginModules = await resolvePluginModules(pluginSpecifiers);\n } catch (err) {\n console.error(`Failed to load plugins: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n\n const defaultPlugins = getDefaultPluginNames();\n const externalServices = Object.keys(allPluginModules).filter((name) => !defaultPlugins.includes(name));\n\n let services: string[];\n if (options.service) {\n services = options.service.split(\",\").map((s) => s.trim());\n } else if (seedConfig) {\n services = inferServicesFromConfig(seedConfig, Object.keys(allPluginModules)) ?? [\n ...defaultPlugins,\n ...externalServices,\n ];\n } else {\n services = [...defaultPlugins, ...externalServices];\n }\n\n for (const svc of services) {\n if (!allPluginModules[svc]) {\n console.error(`Unknown service: ${svc}`);\n process.exit(1);\n }\n }\n\n const tokens = createAuthTokens(seedConfig);\n\n if (options.portless) {\n await ensurePortless();\n }\n\n interface PreparedService {\n svc: string;\n pluginModule: PluginModule;\n loadedPlugin: LoadedPlugin;\n svcSeedConfig: Record<string, unknown> | undefined;\n port: number;\n baseUrl: string;\n }\n\n const portlessAliases: PortlessAlias[] = [];\n const prepared: PreparedService[] = [];\n\n for (let i = 0; i < services.length; i++) {\n const svc = services[i];\n const pluginModule = allPluginModules[svc];\n const loadedPlugin = await pluginModule.load();\n\n const svcSeedConfig = seedConfig?.[svc] as Record<string, unknown> | undefined;\n const port = (svcSeedConfig?.port as number | undefined) ?? basePort + i;\n\n if (options.portless) {\n portlessAliases.push({ name: `${svc}.api-emulator`, port });\n }\n\n const seedBaseUrl =\n typeof svcSeedConfig?.baseUrl === \"string\" && svcSeedConfig.baseUrl.length > 0\n ? svcSeedConfig.baseUrl\n : undefined;\n const effectiveBaseUrl = options.portless ? portlessBaseUrl(svc) : options.baseUrl;\n const baseUrl = resolveBaseUrl({ service: svc, port, baseUrl: effectiveBaseUrl, seedBaseUrl });\n\n prepared.push({ svc, pluginModule, loadedPlugin, svcSeedConfig, port, baseUrl });\n }\n\n if (portlessAliases.length > 0) {\n registerAliases(portlessAliases);\n }\n\n const serviceUrls: Array<{ name: string; url: string }> = [];\n const runningServices: RunningService[] = [];\n\n for (const { svc, pluginModule, loadedPlugin, svcSeedConfig, port, baseUrl } of prepared) {\n serviceUrls.push({ name: svc, url: baseUrl });\n\n const running = createServiceRuntime({\n service: svc,\n pluginModule,\n loadedPlugin,\n port,\n baseUrl,\n tokens,\n seedConfig: svcSeedConfig,\n });\n runningServices.push(running);\n }\n\n printBanner(serviceUrls, tokens, configSource);\n\n const shutdown = () => {\n console.log(`\\n${pc.dim(\"Shutting down...\")}`);\n if (portlessAliases.length > 0) {\n removeAliases(portlessAliases);\n }\n for (const running of runningServices) {\n void running.close();\n }\n process.exit(0);\n };\n process.once(\"SIGINT\", shutdown);\n process.once(\"SIGTERM\", shutdown);\n}\n\nfunction printBanner(\n services: Array<{ name: string; url: string }>,\n tokens: Record<string, { login: string; id: number; scopes?: string[] }>,\n configSource: string | null,\n): void {\n const lines: string[] = [];\n lines.push(\"\");\n lines.push(` ${pc.bold(\"api-emulator\")} ${pc.dim(`v${pkg.version}`)}`);\n lines.push(\"\");\n\n const maxNameLen = Math.max(...services.map((s) => s.name.length));\n for (const { name, url } of services) {\n lines.push(` ${pc.cyan(name.padEnd(maxNameLen + 2))}${pc.bold(url)}`);\n }\n lines.push(\"\");\n\n const tokenEntries = Object.entries(tokens);\n if (tokenEntries.length > 0) {\n lines.push(` ${pc.dim(\"Tokens\")}`);\n for (const [token, user] of tokenEntries) {\n lines.push(` ${pc.dim(token)} ${pc.dim(\"->\")} ${user.login}`);\n }\n lines.push(\"\");\n }\n\n if (configSource) {\n lines.push(` ${pc.dim(\"Config:\")} ${configSource}`);\n } else {\n lines.push(` ${pc.dim(\"Config:\")} defaults ${pc.dim(\"(run\")} npx api-emulator init ${pc.dim(\"to customize)\")}`);\n }\n lines.push(\"\");\n\n console.log(lines.join(\"\\n\"));\n}\n","import { execSync, spawnSync } from \"child_process\";\nimport { createInterface } from \"readline\";\n\nfunction isInteractive(): boolean {\n return Boolean(process.stdin.isTTY) && !process.env.CI;\n}\n\nfunction hasPortless(): boolean {\n const result = spawnSync(\"portless\", [\"--version\"], { stdio: \"ignore\" });\n return result.status === 0;\n}\n\nfunction promptYesNo(question: string): Promise<boolean> {\n return new Promise((resolve) => {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n rl.question(question, (answer) => {\n rl.close();\n const normalized = answer.trim().toLowerCase();\n resolve(normalized === \"\" || normalized === \"y\" || normalized === \"yes\");\n });\n });\n}\n\nfunction isProxyRunning(): boolean {\n const result = spawnSync(\"portless\", [\"list\"], { stdio: \"ignore\" });\n return result.status === 0;\n}\n\nexport async function ensurePortless(): Promise<void> {\n if (!hasPortless()) {\n if (!isInteractive()) {\n console.error(\"portless is required but not installed. Run: npm i -g portless\");\n process.exit(1);\n }\n\n const yes = await promptYesNo(\"portless is not installed. Install it now? (npm i -g portless) [Y/n] \");\n if (!yes) {\n console.error(\"Cannot continue without portless.\");\n process.exit(1);\n }\n\n try {\n execSync(\"npm i -g portless\", { stdio: \"inherit\" });\n } catch {\n console.error(\"Failed to install portless.\");\n process.exit(1);\n }\n\n if (!hasPortless()) {\n console.error(\"portless was installed but could not be found on PATH.\");\n process.exit(1);\n }\n }\n\n if (!isProxyRunning()) {\n console.error(\"portless proxy is not running. Start it with: portless proxy start\");\n process.exit(1);\n }\n}\n\nexport interface PortlessAlias {\n name: string;\n port: number;\n}\n\nexport function registerAliases(aliases: PortlessAlias[]): void {\n const registered: PortlessAlias[] = [];\n for (const { name, port } of aliases) {\n const result = spawnSync(\"portless\", [\"alias\", name, String(port), \"--force\"], {\n stdio: \"inherit\",\n });\n if (result.status !== 0) {\n if (registered.length > 0) {\n removeAliases(registered);\n }\n throw new Error(`Failed to register portless alias: ${name} -> ${port}`);\n }\n registered.push({ name, port });\n }\n}\n\nexport function removeAliases(aliases: PortlessAlias[]): void {\n for (const { name } of aliases) {\n const result = spawnSync(\"portless\", [\"alias\", \"--remove\", name], { stdio: \"ignore\" });\n if (result.status !== 0) {\n console.error(`Warning: failed to remove portless alias: ${name}`);\n }\n }\n}\n\nexport function portlessBaseUrl(serviceName: string): string {\n return `https://${serviceName}.api-emulator.localhost`;\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 { writeFileSync, existsSync } from \"fs\";\nimport { resolve } from \"path\";\nimport { stringify as yamlStringify } from \"yaml\";\nimport { DEFAULT_TOKENS, resolvePluginModules } from \"../registry.js\";\n\ninterface InitOptions {\n service: string;\n plugin?: string;\n}\n\nexport async function initCommand(options: InitOptions): Promise<void> {\n const filename = \"api-emulator.config.yaml\";\n const fullPath = resolve(filename);\n\n if (existsSync(fullPath)) {\n console.error(`Config file already exists: ${filename}`);\n process.exit(1);\n }\n\n const pluginSpecifiers =\n options.plugin\n ?.split(\",\")\n .map((s) => s.trim())\n .filter(Boolean) ?? [];\n const pluginModules = await resolvePluginModules(pluginSpecifiers);\n const availableServices = Object.keys(pluginModules);\n\n let config: Record<string, unknown>;\n if (options.service === \"all\") {\n config = { ...DEFAULT_TOKENS };\n for (const name of availableServices) {\n Object.assign(config, pluginModules[name].initConfig);\n }\n } else {\n const pluginModule = pluginModules[options.service];\n if (!pluginModule) {\n console.error(`Unknown service: ${options.service}. Available: ${availableServices.join(\", \")}, all`);\n process.exit(1);\n }\n config = { ...DEFAULT_TOKENS, ...pluginModule.initConfig };\n }\n\n const content = yamlStringify(config);\n writeFileSync(fullPath, content, \"utf-8\");\n\n console.log(`Created ${filename}`);\n console.log(`\\nRun 'npx api-emulator' to start the emulator.`);\n}\n","import { resolvePluginModules } from \"../registry.js\";\n\ninterface ListOptions {\n plugin?: string;\n}\n\nexport async function listCommand(options: ListOptions = {}): Promise<void> {\n const pluginSpecifiers =\n options.plugin\n ?.split(\",\")\n .map((s) => s.trim())\n .filter(Boolean) ?? [];\n const pluginModules = await resolvePluginModules(pluginSpecifiers);\n\n console.log(\"\\nAvailable services:\\n\");\n for (const pluginModule of Object.values(pluginModules)) {\n console.log(` ${pluginModule.name.padEnd(10)}${pluginModule.label}`);\n console.log(` Endpoints: ${pluginModule.endpoints}`);\n console.log();\n }\n}\n"],"mappings":"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","names":["resolve","resolve","resolve","resolve","existsSync","resolve","resolve","existsSync","pkg"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/external-plugin-adapter.ts","../src/plugin-manifest.ts","../src/plugin-lock.ts","../src/default-plugin-catalog.ts","../src/registry.ts","../src/commands/start.ts","../src/portless.ts","../src/base-url.ts","../src/service-runtime.ts","../src/commands/init.ts","../src/commands/list.ts","../src/commands/install.ts","../src/plugin-source-registry.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { startCommand } from \"./commands/start.js\";\nimport { initCommand } from \"./commands/init.js\";\nimport { listCommand } from \"./commands/list.js\";\nimport { installCommand } from \"./commands/install.js\";\n\ndeclare const PKG_VERSION: string;\nconst pkg = { version: PKG_VERSION };\n\nconst defaultPort = process.env.API_EMULATOR_PORT ?? process.env.EMULATE_PORT ?? process.env.PORT ?? \"4000\";\n\nconst program = new Command();\n\nprogram.name(\"api\").description(\"Local API emulators you can run, share, and extend with plugins\").version(pkg.version);\n\nprogram\n .command(\"start\", { isDefault: true })\n .description(\"Start the emulator server\")\n .option(\"-p, --port <port>\", \"Base port\", defaultPort)\n .option(\"-s, --service <services>\", \"Comma-separated services to enable\")\n .option(\"--seed <file>\", \"Path to seed config file\")\n .option(\"--base-url <url>\", \"Override advertised base URL (supports {service} template)\")\n .option(\"--portless\", \"Serve over HTTPS via portless (auto-registers aliases)\")\n .option(\"--plugin <plugins>\", \"Comma-separated external plugin paths or package names\")\n .action(async (opts) => {\n const port = parseInt(opts.port, 10);\n if (Number.isNaN(port) || port < 1 || port > 65535) {\n console.error(`Invalid port: ${opts.port}`);\n process.exit(1);\n }\n await startCommand({\n port,\n service: opts.service,\n seed: opts.seed,\n baseUrl: opts.baseUrl,\n portless: opts.portless,\n plugin: opts.plugin,\n });\n });\n\nprogram\n .command(\"init\")\n .description(\"Generate a starter config file\")\n .option(\"-s, --service <service>\", \"Service to generate config for\", \"all\")\n .option(\"--plugin <plugins>\", \"Comma-separated external plugin paths or package names\")\n .action(async (opts) => {\n await initCommand({ service: opts.service, plugin: opts.plugin });\n });\n\nprogram\n .command(\"list\")\n .alias(\"list-services\")\n .description(\"List available services\")\n .option(\"--plugin <plugins>\", \"Comma-separated external plugin paths or package names\")\n .action(async (opts) => {\n await listCommand({ plugin: opts.plugin });\n });\n\nprogram\n .command(\"install <plugin>\")\n .description(\"Install a provider plugin by name\")\n .option(\"--package-manager <name>\", \"Package manager to use\")\n .option(\"--no-package-manager\", \"Only record the plugin in api-emulator.lock\")\n .action(async (plugin, opts) => {\n try {\n await installCommand(plugin, {\n packageManager: opts.packageManager === false ? false : opts.packageManager,\n });\n } catch (err) {\n console.error(err instanceof Error ? err.message : err);\n process.exit(1);\n }\n });\n\nprogram.parse();\n","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","import { resolvePluginModules, getDefaultPluginNames, type LoadedPlugin, type PluginModule } from \"../registry.js\";\nimport { readFileSync, existsSync } from \"fs\";\nimport { resolve } from \"path\";\nimport { parse as parseYaml } from \"yaml\";\nimport pc from \"picocolors\";\nimport { ensurePortless, registerAliases, removeAliases, portlessBaseUrl, type PortlessAlias } from \"../portless.js\";\nimport { resolveBaseUrl } from \"../base-url.js\";\nimport { createAuthTokens, createServiceRuntime, type RunningService, type SeedConfig } from \"../service-runtime.js\";\n\ndeclare const PKG_VERSION: string;\nconst pkg = { version: PKG_VERSION };\n\nexport interface StartOptions {\n port: number;\n service?: string;\n seed?: string;\n baseUrl?: string;\n portless?: boolean;\n plugin?: string;\n}\n\ninterface LoadResult {\n config: SeedConfig;\n source: string;\n}\n\nfunction loadSeedConfig(seedPath?: string): LoadResult | null {\n if (seedPath) {\n const fullPath = resolve(seedPath);\n if (!existsSync(fullPath)) {\n console.error(`Seed file not found: ${fullPath}`);\n process.exit(1);\n }\n const content = readFileSync(fullPath, \"utf-8\");\n try {\n const config = fullPath.endsWith(\".json\") ? JSON.parse(content) : parseYaml(content);\n return { config, source: seedPath };\n } catch (err) {\n console.error(`Failed to parse ${seedPath}: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n }\n\n const autoFiles = [\n \"api-emulator.config.yaml\",\n \"api-emulator.config.yml\",\n \"api-emulator.config.json\",\n \"emulate.config.yaml\",\n \"emulate.config.yml\",\n \"emulate.config.json\",\n \"service-emulator.config.yaml\",\n \"service-emulator.config.yml\",\n \"service-emulator.config.json\",\n ];\n\n for (const file of autoFiles) {\n const fullPath = resolve(file);\n if (existsSync(fullPath)) {\n const content = readFileSync(fullPath, \"utf-8\");\n try {\n const config = fullPath.endsWith(\".json\") ? JSON.parse(content) : parseYaml(content);\n return { config, source: file };\n } catch (err) {\n console.error(`Failed to parse ${file}: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n }\n }\n\n return null;\n}\n\nfunction inferServicesFromConfig(config: SeedConfig, availableServices: string[]): string[] | null {\n const found = availableServices.filter((k) => k in config);\n return found.length > 0 ? [...found] : null;\n}\n\nexport async function startCommand(options: StartOptions): Promise<void> {\n const { port: basePort } = options;\n\n if (options.portless && options.baseUrl) {\n console.error(\"--portless and --base-url are mutually exclusive.\");\n process.exit(1);\n }\n\n const loaded = loadSeedConfig(options.seed);\n const seedConfig = loaded?.config ?? null;\n const configSource = loaded?.source ?? null;\n\n const pluginSpecifiers =\n options.plugin\n ?.split(\",\")\n .map((s) => s.trim())\n .filter(Boolean) ?? [];\n let allPluginModules: Record<string, PluginModule>;\n try {\n allPluginModules = await resolvePluginModules(pluginSpecifiers, { includeInstalled: true });\n } catch (err) {\n console.error(`Failed to load plugins: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n\n const defaultPlugins = getDefaultPluginNames();\n const externalServices = Object.keys(allPluginModules).filter((name) => !defaultPlugins.includes(name));\n\n let services: string[];\n if (options.service) {\n services = options.service.split(\",\").map((s) => s.trim());\n } else if (seedConfig) {\n services = inferServicesFromConfig(seedConfig, Object.keys(allPluginModules)) ?? [\n ...defaultPlugins,\n ...externalServices,\n ];\n } else {\n services = [...defaultPlugins, ...externalServices];\n }\n\n for (const svc of services) {\n if (!allPluginModules[svc]) {\n console.error(`Unknown service: ${svc}`);\n process.exit(1);\n }\n }\n\n const tokens = createAuthTokens(seedConfig);\n\n if (options.portless) {\n await ensurePortless();\n }\n\n interface PreparedService {\n svc: string;\n pluginModule: PluginModule;\n loadedPlugin: LoadedPlugin;\n svcSeedConfig: Record<string, unknown> | undefined;\n port: number;\n baseUrl: string;\n }\n\n const portlessAliases: PortlessAlias[] = [];\n const prepared: PreparedService[] = [];\n\n for (let i = 0; i < services.length; i++) {\n const svc = services[i];\n const pluginModule = allPluginModules[svc];\n const loadedPlugin = await pluginModule.load();\n\n const svcSeedConfig = seedConfig?.[svc] as Record<string, unknown> | undefined;\n const port = (svcSeedConfig?.port as number | undefined) ?? basePort + i;\n\n if (options.portless) {\n portlessAliases.push({ name: `${svc}.api-emulator`, port });\n }\n\n const seedBaseUrl =\n typeof svcSeedConfig?.baseUrl === \"string\" && svcSeedConfig.baseUrl.length > 0\n ? svcSeedConfig.baseUrl\n : undefined;\n const effectiveBaseUrl = options.portless ? portlessBaseUrl(svc) : options.baseUrl;\n const baseUrl = resolveBaseUrl({ service: svc, port, baseUrl: effectiveBaseUrl, seedBaseUrl });\n\n prepared.push({ svc, pluginModule, loadedPlugin, svcSeedConfig, port, baseUrl });\n }\n\n if (portlessAliases.length > 0) {\n registerAliases(portlessAliases);\n }\n\n const serviceUrls: Array<{ name: string; url: string }> = [];\n const runningServices: RunningService[] = [];\n\n for (const { svc, pluginModule, loadedPlugin, svcSeedConfig, port, baseUrl } of prepared) {\n serviceUrls.push({ name: svc, url: baseUrl });\n\n const running = createServiceRuntime({\n service: svc,\n pluginModule,\n loadedPlugin,\n port,\n baseUrl,\n tokens,\n seedConfig: svcSeedConfig,\n });\n runningServices.push(running);\n }\n\n printBanner(serviceUrls, tokens, configSource);\n\n const shutdown = () => {\n console.log(`\\n${pc.dim(\"Shutting down...\")}`);\n if (portlessAliases.length > 0) {\n removeAliases(portlessAliases);\n }\n for (const running of runningServices) {\n void running.close();\n }\n process.exit(0);\n };\n process.once(\"SIGINT\", shutdown);\n process.once(\"SIGTERM\", shutdown);\n}\n\nfunction printBanner(\n services: Array<{ name: string; url: string }>,\n tokens: Record<string, { login: string; id: number; scopes?: string[] }>,\n configSource: string | null,\n): void {\n const lines: string[] = [];\n lines.push(\"\");\n lines.push(` ${pc.bold(\"api-emulator\")} ${pc.dim(`v${pkg.version}`)}`);\n lines.push(\"\");\n\n const maxNameLen = Math.max(...services.map((s) => s.name.length));\n for (const { name, url } of services) {\n lines.push(` ${pc.cyan(name.padEnd(maxNameLen + 2))}${pc.bold(url)}`);\n }\n lines.push(\"\");\n\n const tokenEntries = Object.entries(tokens);\n if (tokenEntries.length > 0) {\n lines.push(` ${pc.dim(\"Tokens\")}`);\n for (const [token, user] of tokenEntries) {\n lines.push(` ${pc.dim(token)} ${pc.dim(\"->\")} ${user.login}`);\n }\n lines.push(\"\");\n }\n\n if (configSource) {\n lines.push(` ${pc.dim(\"Config:\")} ${configSource}`);\n } else {\n lines.push(\n ` ${pc.dim(\"Config:\")} defaults ${pc.dim(\"(run\")} npx -p api-emulator api init ${pc.dim(\"to customize)\")}`,\n );\n }\n lines.push(\"\");\n\n console.log(lines.join(\"\\n\"));\n}\n","import { execSync, spawnSync } from \"child_process\";\nimport { createInterface } from \"readline\";\n\nfunction isInteractive(): boolean {\n return Boolean(process.stdin.isTTY) && !process.env.CI;\n}\n\nfunction hasPortless(): boolean {\n const result = spawnSync(\"portless\", [\"--version\"], { stdio: \"ignore\" });\n return result.status === 0;\n}\n\nfunction promptYesNo(question: string): Promise<boolean> {\n return new Promise((resolve) => {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n rl.question(question, (answer) => {\n rl.close();\n const normalized = answer.trim().toLowerCase();\n resolve(normalized === \"\" || normalized === \"y\" || normalized === \"yes\");\n });\n });\n}\n\nfunction isProxyRunning(): boolean {\n const result = spawnSync(\"portless\", [\"list\"], { stdio: \"ignore\" });\n return result.status === 0;\n}\n\nexport async function ensurePortless(): Promise<void> {\n if (!hasPortless()) {\n if (!isInteractive()) {\n console.error(\"portless is required but not installed. Run: npm i -g portless\");\n process.exit(1);\n }\n\n const yes = await promptYesNo(\"portless is not installed. Install it now? (npm i -g portless) [Y/n] \");\n if (!yes) {\n console.error(\"Cannot continue without portless.\");\n process.exit(1);\n }\n\n try {\n execSync(\"npm i -g portless\", { stdio: \"inherit\" });\n } catch {\n console.error(\"Failed to install portless.\");\n process.exit(1);\n }\n\n if (!hasPortless()) {\n console.error(\"portless was installed but could not be found on PATH.\");\n process.exit(1);\n }\n }\n\n if (!isProxyRunning()) {\n console.error(\"portless proxy is not running. Start it with: portless proxy start\");\n process.exit(1);\n }\n}\n\nexport interface PortlessAlias {\n name: string;\n port: number;\n}\n\nexport function registerAliases(aliases: PortlessAlias[]): void {\n const registered: PortlessAlias[] = [];\n for (const { name, port } of aliases) {\n const result = spawnSync(\"portless\", [\"alias\", name, String(port), \"--force\"], {\n stdio: \"inherit\",\n });\n if (result.status !== 0) {\n if (registered.length > 0) {\n removeAliases(registered);\n }\n throw new Error(`Failed to register portless alias: ${name} -> ${port}`);\n }\n registered.push({ name, port });\n }\n}\n\nexport function removeAliases(aliases: PortlessAlias[]): void {\n for (const { name } of aliases) {\n const result = spawnSync(\"portless\", [\"alias\", \"--remove\", name], { stdio: \"ignore\" });\n if (result.status !== 0) {\n console.error(`Warning: failed to remove portless alias: ${name}`);\n }\n }\n}\n\nexport function portlessBaseUrl(serviceName: string): string {\n return `https://${serviceName}.api-emulator.localhost`;\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 { writeFileSync, existsSync } from \"fs\";\nimport { resolve } from \"path\";\nimport { stringify as yamlStringify } from \"yaml\";\nimport { DEFAULT_TOKENS, resolvePluginModules } from \"../registry.js\";\n\ninterface InitOptions {\n service: string;\n plugin?: string;\n}\n\nexport async function initCommand(options: InitOptions): Promise<void> {\n const filename = \"api-emulator.config.yaml\";\n const fullPath = resolve(filename);\n\n if (existsSync(fullPath)) {\n console.error(`Config file already exists: ${filename}`);\n process.exit(1);\n }\n\n const pluginSpecifiers =\n options.plugin\n ?.split(\",\")\n .map((s) => s.trim())\n .filter(Boolean) ?? [];\n const pluginModules = await resolvePluginModules(pluginSpecifiers, { includeInstalled: true });\n const availableServices = Object.keys(pluginModules);\n\n let config: Record<string, unknown>;\n if (options.service === \"all\") {\n config = { ...DEFAULT_TOKENS };\n for (const name of availableServices) {\n Object.assign(config, pluginModules[name].initConfig);\n }\n } else {\n const pluginModule = pluginModules[options.service];\n if (!pluginModule) {\n console.error(`Unknown service: ${options.service}. Available: ${availableServices.join(\", \")}, all`);\n process.exit(1);\n }\n config = { ...DEFAULT_TOKENS, ...pluginModule.initConfig };\n }\n\n const content = yamlStringify(config);\n writeFileSync(fullPath, content, \"utf-8\");\n\n console.log(`Created ${filename}`);\n console.log(`\\nRun 'npx -p api-emulator api' to start the emulator.`);\n}\n","import { resolvePluginModules } from \"../registry.js\";\n\ninterface ListOptions {\n plugin?: string;\n}\n\nexport async function listCommand(options: ListOptions = {}): Promise<void> {\n const pluginSpecifiers =\n options.plugin\n ?.split(\",\")\n .map((s) => s.trim())\n .filter(Boolean) ?? [];\n const pluginModules = await resolvePluginModules(pluginSpecifiers, { includeInstalled: true });\n\n console.log(\"\\nAvailable services:\\n\");\n for (const pluginModule of Object.values(pluginModules)) {\n console.log(` ${pluginModule.name.padEnd(10)}${pluginModule.label}`);\n console.log(` Endpoints: ${pluginModule.endpoints}`);\n console.log();\n }\n}\n","import { spawnSync } from \"child_process\";\nimport { existsSync } from \"fs\";\nimport { resolve } from \"path\";\nimport { PLUGIN_LOCK_FILE, readPluginLock, writePluginLock } from \"../plugin-lock.js\";\nimport { resolvePluginSource } from \"../plugin-source-registry.js\";\n\nexport interface InstallOptions {\n packageManager?: string | false;\n}\n\nfunction detectPackageManager(): string {\n if (existsSync(resolve(\"bun.lock\")) || existsSync(resolve(\"bun.lockb\"))) return \"bun\";\n if (existsSync(resolve(\"pnpm-lock.yaml\"))) return \"pnpm\";\n if (existsSync(resolve(\"yarn.lock\"))) return \"yarn\";\n return \"npm\";\n}\n\nfunction installPackage(packageManager: string, packageName: string): void {\n const args =\n packageManager === \"bun\"\n ? [\"add\", \"-D\", packageName]\n : packageManager === \"pnpm\"\n ? [\"add\", \"-D\", packageName]\n : packageManager === \"yarn\"\n ? [\"add\", \"-D\", packageName]\n : [\"install\", \"-D\", packageName];\n\n const result = spawnSync(packageManager, args, { stdio: \"inherit\" });\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw new Error(`${packageManager} ${args.join(\" \")} failed`);\n }\n}\n\nexport async function installCommand(name: string, options: InstallOptions = {}): Promise<void> {\n const source = resolvePluginSource(name);\n if (!source) {\n throw new Error(`Unknown plugin source: ${name}`);\n }\n\n const packageManager = options.packageManager === undefined ? detectPackageManager() : options.packageManager;\n if (packageManager && source.packageName) {\n installPackage(packageManager, source.packageName);\n } else if (packageManager && source.kind === \"package\" && !source.packageName) {\n throw new Error(`Plugin source \"${name}\" is a local package without a package name`);\n }\n\n const lock = readPluginLock();\n lock.plugins[source.name] = {\n name: source.name,\n source: source.kind === \"file\" ? \"specifier\" : \"registry\",\n sourceId: source.sourceId,\n packageName: source.packageName,\n specifier: packageManager && source.packageName ? source.packageName : source.specifier,\n version: \"latest\",\n };\n writePluginLock(lock);\n\n console.log(`Installed ${source.name} from ${source.sourceId}`);\n console.log(`Recorded plugin in ${PLUGIN_LOCK_FILE}`);\n}\n","import { existsSync, readdirSync, readFileSync, statSync } from \"fs\";\nimport { dirname, join, resolve } from \"path\";\n\nexport type PluginSourceKind = \"package\" | \"file\";\n\nexport interface PluginSource {\n name: string;\n sourceId: string;\n kind: PluginSourceKind;\n specifier: string;\n description: string;\n packageName?: string;\n packageRoot?: string;\n}\n\nconst PLUGIN_SOURCES: Record<string, PluginSource> = {\n cloudflare: {\n name: \"cloudflare\",\n sourceId: \"public\",\n kind: \"package\",\n packageName: \"@api-emulator/cloudflare\",\n specifier: \"@api-emulator/cloudflare\",\n description: \"Workers-style bindings, D1, KV, R2, queues, durable objects, and service bindings\",\n },\n};\n\nconst DEFAULT_CATALOG_DIRS = [\"api-emulator-plugins\", \"api-emulator-internal\"];\nconst CATALOG_MANIFEST_FILES = [\"api-emulator.catalog.json\"];\nconst PLUGIN_ENTRY_FILES = [\"api-emulator.mjs\", \"api-emulator/index.mjs\"];\nconst PACKAGE_ENTRY_DIRS = [\"api-emulator\", \"trading-emulator\"];\n\nfunction candidateCatalogRoots(cwd = process.cwd()): string[] {\n const envRoots =\n process.env.API_EMULATOR_PLUGIN_CATALOGS?.split(\",\")\n .map((value) => value.trim())\n .filter(Boolean) ?? [];\n const roots = [...envRoots];\n let current = resolve(cwd);\n for (;;) {\n for (const dir of DEFAULT_CATALOG_DIRS) {\n roots.push(join(current, dir));\n roots.push(join(dirname(current), dir));\n }\n const parent = dirname(current);\n if (parent === current) break;\n current = parent;\n }\n return [...new Set(roots.map((root) => resolve(root)))];\n}\n\nfunction sourceIdForRoot(root: string): string {\n const base = root.split(/[\\\\/]/).pop() ?? \"local\";\n if (base === \"api-emulator-plugins\") return \"public\";\n if (base === \"api-emulator-internal\") return \"internal\";\n return base;\n}\n\nfunction packageEntrySpecifier(packageRoot: string, pkg: { exports?: unknown; main?: string }): string {\n if (typeof pkg.exports === \"string\") return resolve(packageRoot, pkg.exports);\n if (\n typeof pkg.exports === \"object\" &&\n pkg.exports !== null &&\n \".\" in pkg.exports &&\n typeof pkg.exports[\".\"] === \"string\"\n ) {\n return resolve(packageRoot, pkg.exports[\".\"]);\n }\n if (\n typeof pkg.exports === \"object\" &&\n pkg.exports !== null &&\n \".\" in pkg.exports &&\n typeof pkg.exports[\".\"] === \"object\" &&\n pkg.exports[\".\"] !== null &&\n \"import\" in pkg.exports[\".\"] &&\n typeof pkg.exports[\".\"].import === \"string\"\n ) {\n return resolve(packageRoot, pkg.exports[\".\"].import);\n }\n if (typeof pkg.main === \"string\") return resolve(packageRoot, pkg.main);\n return packageRoot;\n}\n\ninterface CatalogManifest {\n plugins?: Record<\n string,\n {\n kind?: PluginSourceKind;\n specifier: string;\n description?: string;\n packageName?: string;\n }\n >;\n}\n\nfunction discoverManifest(root: string, sourceId: string): PluginSource[] {\n const sources: PluginSource[] = [];\n for (const manifestFile of CATALOG_MANIFEST_FILES) {\n const manifestPath = join(root, manifestFile);\n if (!existsSync(manifestPath)) continue;\n const manifest = JSON.parse(readFileSync(manifestPath, \"utf-8\")) as CatalogManifest;\n for (const [name, entry] of Object.entries(manifest.plugins ?? {})) {\n sources.push({\n name,\n sourceId,\n kind: entry.kind ?? (entry.packageName ? \"package\" : \"file\"),\n packageName: entry.packageName,\n specifier: entry.specifier.startsWith(\".\") ? resolve(root, entry.specifier) : entry.specifier,\n description: entry.description ?? `${name} plugin from ${sourceId} catalog`,\n });\n }\n }\n return sources;\n}\n\nfunction discoverCatalog(root: string): PluginSource[] {\n if (!existsSync(root) || !statSync(root).isDirectory()) return [];\n\n const sourceId = sourceIdForRoot(root);\n const sources: PluginSource[] = discoverManifest(root, sourceId);\n for (const entry of readdirSync(root, { withFileTypes: true })) {\n if (!entry.isDirectory() || !entry.name.startsWith(\"@\")) continue;\n const name = entry.name.slice(1);\n const pluginRoot = join(root, entry.name);\n\n for (const entryFile of PLUGIN_ENTRY_FILES) {\n const specifier = join(pluginRoot, entryFile);\n if (existsSync(specifier)) {\n sources.push({\n name,\n sourceId,\n kind: \"file\",\n specifier,\n description: `${name} plugin from ${sourceId} catalog`,\n });\n break;\n }\n }\n\n for (const entryDir of PACKAGE_ENTRY_DIRS) {\n const packageRoot = join(pluginRoot, entryDir);\n const packageJsonPath = join(packageRoot, \"package.json\");\n if (!existsSync(packageJsonPath)) continue;\n const pkg = JSON.parse(readFileSync(packageJsonPath, \"utf-8\")) as {\n name?: string;\n description?: string;\n main?: string;\n };\n sources.push({\n name,\n sourceId,\n kind: \"package\",\n packageName: pkg.name,\n packageRoot,\n specifier: packageEntrySpecifier(packageRoot, pkg),\n description: pkg.description ?? `${name} package from ${sourceId} catalog`,\n });\n break;\n }\n }\n return sources;\n}\n\nfunction pluginSources(): Record<string, PluginSource> {\n const sources = { ...PLUGIN_SOURCES };\n for (const root of candidateCatalogRoots()) {\n for (const source of discoverCatalog(root)) {\n sources[source.name] ??= source;\n }\n }\n return sources;\n}\n\nexport function listPluginSources(): PluginSource[] {\n return Object.values(pluginSources());\n}\n\nexport function resolvePluginSource(name: string): PluginSource | null {\n return pluginSources()[name] ?? null;\n}\n"],"mappings":"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","names":["resolve","readFileSync","existsSync","resolve","resolve","options","resolve","resolve","existsSync","readFileSync","writeFileSync","existsSync","resolve","resolve","existsSync","writeFileSync","spawnSync","existsSync","resolve","existsSync","readFileSync","resolve","pkg","existsSync","resolve","spawnSync","pkg"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "api-emulator",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Local API emulators you can run, share, and extend with plugins",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -19,11 +19,14 @@
19
19
  "repository": {
20
20
  "type": "git",
21
21
  "url": "https://github.com/jsj/api-emulator.git",
22
- "directory": "packages/emulate"
22
+ "directory": "packages/api-emulator"
23
23
  },
24
24
  "bugs": {
25
25
  "url": "https://github.com/jsj/api-emulator/issues"
26
26
  },
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
27
30
  "keywords": [
28
31
  "emulator",
29
32
  "mock",
@@ -40,10 +43,9 @@
40
43
  "dist"
41
44
  ],
42
45
  "bin": {
43
- "api-emulator": "./dist/index.js"
46
+ "api": "./dist/index.js"
44
47
  },
45
48
  "scripts": {
46
- "prepack": "cp ../../README.md .",
47
49
  "build": "tsup",
48
50
  "dev": "tsup --watch",
49
51
  "test": "vitest run",
@@ -53,22 +55,10 @@
53
55
  },
54
56
  "dependencies": {
55
57
  "@hono/node-server": "^1",
58
+ "@api-emulator/core": "0.5.2",
56
59
  "commander": "^14",
57
60
  "picocolors": "^1.1.1",
58
- "yaml": "^2",
59
- "@emulators/core": "workspace:*",
60
- "@emulators/github": "workspace:*",
61
- "@emulators/apple": "workspace:*",
62
- "@emulators/microsoft": "workspace:*",
63
- "@emulators/okta": "workspace:*",
64
- "@emulators/aws": "workspace:*",
65
- "@emulators/google": "workspace:*",
66
- "@emulators/mongoatlas": "workspace:*",
67
- "@emulators/slack": "workspace:*",
68
- "@emulators/vercel": "workspace:*",
69
- "@emulators/resend": "workspace:*",
70
- "@emulators/stripe": "workspace:*",
71
- "@emulators/clerk": "workspace:*"
61
+ "yaml": "^2"
72
62
  },
73
63
  "devDependencies": {
74
64
  "tsup": "^8",