nymbal 0.2.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -217,6 +217,45 @@ function resolveAdminRoot() {
217
217
  }
218
218
  }
219
219
 
220
+ // src/utils/shutdown.ts
221
+ var SHUTDOWN_BOUND_MS = 3e3;
222
+ var running = false;
223
+ async function runShutdown(steps, opts) {
224
+ if (running) {
225
+ opts.logger.error({}, "Shutdown already running; exiting now");
226
+ return opts.exit(1);
227
+ }
228
+ running = true;
229
+ let pending;
230
+ let failed = false;
231
+ const work = (async () => {
232
+ for (const step of steps) {
233
+ pending = step.name;
234
+ try {
235
+ await step.run();
236
+ } catch (err) {
237
+ failed = true;
238
+ opts.logger.error({ err, step: step.name }, `Shutdown step "${step.name}" failed`);
239
+ }
240
+ }
241
+ pending = void 0;
242
+ })();
243
+ let timer;
244
+ const bound = new Promise((resolve4) => {
245
+ timer = setTimeout(() => resolve4("bound"), opts.boundMs);
246
+ });
247
+ const outcome = await Promise.race([work.then(() => "done"), bound]);
248
+ clearTimeout(timer);
249
+ if (outcome === "bound") {
250
+ opts.logger.error(
251
+ { step: pending, boundMs: opts.boundMs },
252
+ `Shutdown step "${pending}" did not finish within ${opts.boundMs} ms; exiting`
253
+ );
254
+ return opts.exit(1);
255
+ }
256
+ return opts.exit(failed ? 1 : 0);
257
+ }
258
+
220
259
  // src/commands/dev.ts
221
260
  function defaultStorefrontPort(template) {
222
261
  return template === "astro" ? 4321 : 3e3;
@@ -250,6 +289,14 @@ function storefrontEnv(config, apiUrl, storefrontPort, baseEnv = process.env) {
250
289
  ...stubPayments
251
290
  };
252
291
  }
292
+ function apiPort(config, flagPort) {
293
+ if (flagPort === void 0 || flagPort.trim() === "") return config.http.port;
294
+ const port = Number(flagPort);
295
+ if (!Number.isInteger(port) || port < 1 || port > 65535) {
296
+ throw new Error(`--port must be an integer from 1 to 65535, got "${flagPort}"`);
297
+ }
298
+ return port;
299
+ }
253
300
  var devCommand = defineCommand2({
254
301
  meta: {
255
302
  name: "dev",
@@ -273,6 +320,10 @@ var devCommand = defineCommand2({
273
320
  description: "Start only the API server (skip template dev server)",
274
321
  default: false
275
322
  },
323
+ port: {
324
+ type: "string",
325
+ description: "Port for the API server (default: the config's http.port)"
326
+ },
276
327
  storefrontPort: {
277
328
  type: "string",
278
329
  alias: "storefront-port",
@@ -280,7 +331,10 @@ var devCommand = defineCommand2({
280
331
  }
281
332
  },
282
333
  async run({ args }) {
283
- const { config, projectRoot } = await loadProject();
334
+ const loaded = await loadProject();
335
+ const { projectRoot } = loaded;
336
+ const port = apiPort(loaded.config, args.port);
337
+ const config = { ...loaded.config, http: { ...loaded.config.http, port } };
284
338
  const version = getCliVersion();
285
339
  await migrateProject(config, projectRoot);
286
340
  const app = await createApp(config, { version });
@@ -318,14 +372,19 @@ var devCommand = defineCommand2({
318
372
  }
319
373
  await app.attachHttp(http.adapter, { adminRoot });
320
374
  await http.start();
375
+ const stopApi = [
376
+ { name: "http.stop", run: () => http.stop() },
377
+ { name: "app.stop", run: () => app.stop() }
378
+ ];
379
+ const shutdownWith = (steps) => runShutdown(steps, {
380
+ boundMs: SHUTDOWN_BOUND_MS,
381
+ logger: platform.logger,
382
+ exit: (code) => process.exit(code)
383
+ });
321
384
  if (args.apiOnly) {
322
- const shutdown2 = async (signal) => {
385
+ const shutdown2 = (signal) => {
323
386
  platform.logger.info({ signal }, "Shutting down API");
324
- await http.stop().catch(() => {
325
- });
326
- await app.stop().catch(() => {
327
- });
328
- process.exit(0);
387
+ return shutdownWith(stopApi);
329
388
  };
330
389
  process.on("SIGINT", () => void shutdown2("SIGINT"));
331
390
  process.on("SIGTERM", () => void shutdown2("SIGTERM"));
@@ -355,22 +414,25 @@ var devCommand = defineCommand2({
355
414
  cwd: launch.cwd,
356
415
  env: storefrontEnv(config, apiUrl, storefrontPort)
357
416
  });
358
- const shutdown = async (signal) => {
417
+ let shuttingDown = false;
418
+ const shutdown = (signal) => {
419
+ shuttingDown = true;
359
420
  platform.logger.info({ signal }, "Shutting down");
360
- try {
361
- templateProc.child.kill("SIGINT");
362
- } catch {
363
- }
364
- await http.stop().catch(() => {
365
- });
366
- await app.stop().catch(() => {
367
- });
368
- process.exit(0);
421
+ return shutdownWith([
422
+ {
423
+ name: "storefront.kill",
424
+ run: async () => {
425
+ templateProc.child.kill("SIGINT");
426
+ }
427
+ },
428
+ ...stopApi
429
+ ]);
369
430
  };
370
431
  process.on("SIGINT", () => void shutdown("SIGINT"));
371
432
  process.on("SIGTERM", () => void shutdown("SIGTERM"));
372
433
  const templateExit = await templateProc.done;
373
434
  platform.logger.info({ code: templateExit }, "Template process exited");
435
+ if (shuttingDown) return;
374
436
  await shutdown("template-exit");
375
437
  }
376
438
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/utils/version.ts","../src/commands/dev.ts","../src/utils/project.ts","../src/utils/spawn.ts","../src/utils/port.ts","../src/utils/template-runner.ts","../src/commands/migrate.ts","../src/admin.ts","../src/commands/build.ts","../src/commands/seed.ts","../src/commands/import.ts","../src/commands/config-validate.ts","../src/commands/test.ts"],"sourcesContent":["import { defineCommand, runMain } from 'citty'\nimport { getCliVersion } from './utils/version.js'\nimport { devCommand } from './commands/dev.js'\nimport { buildCommand } from './commands/build.js'\nimport { migrateCommand } from './commands/migrate.js'\nimport { seedCommand } from './commands/seed.js'\nimport { importCommand } from './commands/import.js'\nimport { configValidateCommand } from './commands/config-validate.js'\nimport {\n testAllCommand,\n testCommand,\n testContractsCommand,\n testE2eCommand,\n testPerformanceCommand,\n testVisualCommand,\n} from './commands/test.js'\n\nexport { resolveAdminRoot } from './admin.js'\n\nconst main = defineCommand({\n meta: {\n name: 'nymbal',\n version: getCliVersion(),\n description: 'Nymbal developer CLI',\n },\n subCommands: {\n dev: devCommand,\n build: buildCommand,\n migrate: migrateCommand,\n seed: seedCommand,\n import: importCommand,\n 'config:validate': configValidateCommand,\n test: testCommand,\n 'test:e2e': testE2eCommand,\n 'test:visual': testVisualCommand,\n 'test:contracts': testContractsCommand,\n 'test:performance': testPerformanceCommand,\n 'test:all': testAllCommand,\n },\n})\n\n// citty prints --version through consola, which prefixes `[log]` when CI is set; scripts need the bare version.\nconst [flag, ...rest] = process.argv.slice(2)\nif (rest.length === 0 && (flag === '--version' || flag === '-v')) {\n process.stdout.write(`${getCliVersion()}\\n`)\n} else {\n runMain(main)\n}\n","import { readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst CLI_PACKAGE_NAME = 'nymbal'\n\nlet cached: string | null = null\n\n/**\n * Walks up from this module to the CLI's own package.json (found by name, so a nested or unrelated package.json\n * never answers). That is `dist/` in the workspace and in `node_modules/nymbal`, and `src/utils/` under Vitest.\n */\nfunction readOwnVersion(): string | undefined {\n let dir = dirname(fileURLToPath(import.meta.url))\n for (;;) {\n try {\n const pkg = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')) as {\n name?: string\n version?: string\n }\n if (pkg.name === CLI_PACKAGE_NAME) return pkg.version\n } catch {\n // No readable package.json in this directory: keep walking.\n }\n const parent = dirname(dir)\n if (parent === dir) return undefined\n dir = parent\n }\n}\n\nexport function getCliVersion(): string {\n cached ??= readOwnVersion() ?? '0.0.0'\n return cached\n}\n","import { defineCommand } from 'citty'\nimport pc from 'picocolors'\nimport type { NymbalConfig } from '@nymbalhq/config'\nimport { loadProject } from '../utils/project.js'\nimport { createApp, runSeed } from '@nymbalhq/platform'\nimport { createHttpServer } from '@nymbalhq/http'\nimport { run } from '../utils/spawn.js'\nimport { getCliVersion } from '../utils/version.js'\nimport { findFreePort } from '../utils/port.js'\nimport { planTemplateLaunch } from '../utils/template-runner.js'\nimport { migrateProject } from './migrate.js'\nimport { resolveAdminRoot } from '../admin.js'\n\n/** Default storefront dev-server port per template (matches the scaffold scripts). */\nexport function defaultStorefrontPort(template: 'astro' | 'nextjs'): number {\n return template === 'astro' ? 4321 : 3000\n}\n\n/**\n * Resolve the *preferred* storefront port from (in priority order):\n * 1. --storefront-port flag\n * 2. NYMBAL_STOREFRONT_PORT env var\n * 3. the template default (Astro 4321 / Next.js 3000)\n * The value returned here is only the starting point; the dev command then\n * probes upward for a genuinely free port so a busy default never hard-fails.\n */\nexport function preferredStorefrontPort(\n template: 'astro' | 'nextjs',\n flagPort: number | undefined,\n env: NodeJS.ProcessEnv,\n): number {\n if (typeof flagPort === 'number' && Number.isFinite(flagPort)) return flagPort\n const fromEnv = env['NYMBAL_STOREFRONT_PORT']\n if (fromEnv && fromEnv.trim() !== '') {\n const parsed = Number(fromEnv)\n if (Number.isInteger(parsed) && parsed > 0) return parsed\n }\n return defaultStorefrontPort(template)\n}\n\n/**\n * The environment the storefront dev server starts with. The client-side variables must be set before it starts, and\n * both templates skip Stripe when the payments provider variable says `native-stub`, which is every provider but\n * `stripe`.\n */\nexport function storefrontEnv(\n config: NymbalConfig,\n apiUrl: string,\n storefrontPort: number,\n baseEnv: NodeJS.ProcessEnv = process.env,\n): NodeJS.ProcessEnv {\n const stubPayments =\n config.commerce.payments.provider === 'stripe'\n ? {}\n : {\n PUBLIC_NYMBAL_PAYMENTS_PROVIDER: 'native-stub', // Astro\n NEXT_PUBLIC_NYMBAL_PAYMENTS_PROVIDER: 'native-stub', // Next.js\n }\n return {\n ...baseEnv,\n NYMBAL_API_URL: apiUrl,\n PUBLIC_NYMBAL_API_URL: apiUrl, // Astro\n NEXT_PUBLIC_NYMBAL_API_URL: apiUrl, // Next.js\n // The framework also reads the port flag; the env var keeps the scaffold\n // config (astro.config.mjs) in sync when it honours NYMBAL_STOREFRONT_PORT.\n NYMBAL_STOREFRONT_PORT: String(storefrontPort),\n ...stubPayments,\n }\n}\n\nexport const devCommand = defineCommand({\n meta: {\n name: 'dev',\n description: 'Start the API server and the configured storefront template with HMR',\n },\n args: {\n seed: {\n type: 'boolean',\n description: 'Run seed before starting (default: true if empty)',\n default: true,\n },\n apiOnly: {\n type: 'boolean',\n // `alias` is required: citty 0.1.6 registers the camelCase key `apiOnly`\n // with mri and applies `default: false`. Without this alias a kebab\n // `--api-only` flag lands on `args['api-only']`, but `args.apiOnly`\n // resolves to the `false` default first (`??` does not fall through on\n // `false`), so the flag is silently ignored. The alias makes mri map\n // `--api-only` straight to `apiOnly`. Both forms now work.\n alias: 'api-only',\n description: 'Start only the API server (skip template dev server)',\n default: false,\n },\n storefrontPort: {\n type: 'string',\n alias: 'storefront-port',\n description:\n 'Port for the storefront dev server (default: 4321 Astro / 3000 Next.js). ' +\n 'If busy, the next free port is used. Also settable via NYMBAL_STOREFRONT_PORT.',\n },\n },\n async run({ args }) {\n const { config, projectRoot } = await loadProject()\n const version = getCliVersion()\n\n // Auto-migrate on startup so a fresh clone works without running `nymbal migrate` first\n await migrateProject(config, projectRoot)\n\n const app = await createApp(config, { version })\n const { platform } = app\n\n if (args.seed) {\n const existing = await platform.documentStore.query('products', {\n partitionKey: { field: 'storeId', value: config.store.name },\n limit: 1,\n })\n if (existing.items.length === 0) {\n platform.logger.info({}, 'Seeding demo content (first run)')\n await runSeed({\n config,\n commandStore: platform.commandStore,\n documentStore: platform.documentStore,\n eventBus: platform.eventBus,\n logger: platform.logger,\n version,\n })\n }\n }\n\n const http = createHttpServer({\n config,\n logger: platform.logger,\n documentStore: platform.documentStore,\n version,\n })\n const adminRoot = resolveAdminRoot()\n if (adminRoot === null) {\n // eslint-disable-next-line no-console\n console.log(\n pc.yellow(\n '→ The admin is not built, so /admin/ answers 404: run `pnpm --filter @nymbalhq/admin build`.',\n ),\n )\n }\n await app.attachHttp(http.adapter, { adminRoot })\n await http.start()\n\n if (args.apiOnly) {\n const shutdown = async (signal: string) => {\n platform.logger.info({ signal }, 'Shutting down API')\n await http.stop().catch(() => {})\n await app.stop().catch(() => {})\n process.exit(0)\n }\n process.on('SIGINT', () => void shutdown('SIGINT'))\n process.on('SIGTERM', () => void shutdown('SIGTERM'))\n // Keep process alive — Playwright webServer will kill it when done\n return\n }\n\n // Resolve a free storefront port. The preferred port is configurable but may\n // be taken (a developer commonly has another project on 4321/3000), so we\n // probe upward for a free one instead of hard-failing.\n const flagPortRaw = args.storefrontPort\n const flagPort =\n typeof flagPortRaw === 'string' && flagPortRaw.trim() !== '' ? Number(flagPortRaw) : undefined\n const preferred = preferredStorefrontPort(config.template, flagPort, process.env)\n const storefrontPort = await findFreePort(preferred)\n if (storefrontPort !== preferred) {\n // eslint-disable-next-line no-console\n console.log(\n pc.yellow(\n `→ Storefront port ${preferred} is busy; using free port ${pc.bold(String(storefrontPort))} instead.`,\n ),\n )\n }\n\n // Plan how to launch the storefront. A flat scaffold (create-nymbal-app\n // output) runs the framework dev server directly in the project root; a\n // monorepo layout falls back to a pnpm --filter on the template package.\n const launch = planTemplateLaunch(projectRoot, config.template, storefrontPort)\n\n const apiUrl = `http://localhost:${config.http.port}`\n const storefrontUrl = `http://localhost:${storefrontPort}`\n // eslint-disable-next-line no-console\n console.log(\n pc.cyan(\n `→ Starting storefront (${pc.bold(config.template)}, ${launch.mode}) on ${pc.bold(storefrontUrl)}`,\n ),\n )\n // eslint-disable-next-line no-console\n console.log(pc.dim(` API: ${apiUrl}`))\n\n const templateProc = run(launch.command, launch.args, {\n cwd: launch.cwd,\n env: storefrontEnv(config, apiUrl, storefrontPort),\n })\n\n const shutdown = async (signal: string) => {\n platform.logger.info({ signal }, 'Shutting down')\n try {\n templateProc.child.kill('SIGINT')\n } catch {\n // ignore\n }\n await http.stop().catch(() => {})\n await app.stop().catch(() => {})\n process.exit(0)\n }\n process.on('SIGINT', () => void shutdown('SIGINT'))\n process.on('SIGTERM', () => void shutdown('SIGTERM'))\n\n const templateExit = await templateProc.done\n platform.logger.info({ code: templateExit }, 'Template process exited')\n await shutdown('template-exit')\n },\n})\n","import { existsSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\nimport { findConfigFile, loadConfig, type LoadedConfig } from '@nymbalhq/config'\n\n/**\n * Loads `<projectRoot>/.env` into the process environment, then the project's config, so `env()` calls in\n * `nymbal.config.ts` see it. A variable already set in the environment is kept: `process.loadEnvFile` never overrides.\n */\nexport async function loadProject(startDir: string = process.cwd()): Promise<LoadedConfig> {\n const configPath = findConfigFile(startDir)\n if (configPath) {\n const envFile = resolve(dirname(configPath), '.env')\n if (existsSync(envFile)) process.loadEnvFile(envFile)\n }\n return loadConfig(startDir)\n}\n","import { spawn, type ChildProcess, type SpawnOptions } from 'node:child_process'\n\nexport interface RunOptions extends SpawnOptions {\n name?: string\n}\n\nexport function run(\n command: string,\n args: string[],\n options: RunOptions = {},\n): { child: ChildProcess; done: Promise<number> } {\n const child = spawn(command, args, {\n stdio: 'inherit',\n shell: false,\n ...options,\n })\n const done = new Promise<number>((resolve, reject) => {\n child.on('error', reject)\n child.on('exit', (code) => resolve(code ?? 0))\n })\n return { child, done }\n}\n\nexport async function runOrFail(\n command: string,\n args: string[],\n options: RunOptions = {},\n): Promise<void> {\n const { done } = run(command, args, options)\n const code = await done\n if (code !== 0) {\n throw new Error(`${command} ${args.join(' ')} exited with code ${code}`)\n }\n}\n","import { createServer } from 'node:net'\n\n/**\n * Resolve a usable storefront port.\n *\n * The headline `nymbal dev` flow must not hard-fail when the preferred port is\n * already taken (a developer commonly has another project on 4321/3000). We\n * probe the preferred port first and, if it is busy, increment until we find a\n * free one — exactly how the underlying dev servers (Astro, Next.js) behave on\n * their own, but here we resolve the port *before* spawning so we can tell the\n * storefront which port to bind and tell the user where to open the browser.\n */\nexport async function isPortFree(port: number, host?: string): Promise<boolean> {\n return new Promise<boolean>((resolve) => {\n const server = createServer()\n server.once('error', (err: NodeJS.ErrnoException) => {\n // EADDRINUSE / EACCES → not usable. Any other error → treat as not free\n // rather than silently swallowing it; the caller will skip this port.\n if (err.code !== 'EADDRINUSE' && err.code !== 'EACCES') {\n // eslint-disable-next-line no-console\n console.error(`[dev] unexpected error probing port ${port}:`, err.message)\n }\n resolve(false)\n })\n server.once('listening', () => {\n server.close(() => resolve(true))\n })\n // Bind across all interfaces (no explicit host) so a port already held on\n // IPv6 (e.g. another dev server on [::1]) is correctly seen as busy. A\n // 127.0.0.1-only probe would miss an IPv6 listener and wrongly report free,\n // then the framework — which binds dual-stack — would fail on that port.\n if (host) {\n server.listen(port, host)\n } else {\n server.listen(port)\n }\n })\n}\n\n/**\n * Find a free port starting at `preferred`, scanning upward up to `maxAttempts`\n * times. Throws an actionable error if no port in the range is free.\n */\nexport async function findFreePort(\n preferred: number,\n maxAttempts = 20,\n host?: string,\n): Promise<number> {\n if (!Number.isInteger(preferred) || preferred < 1 || preferred > 65535) {\n throw new Error(\n `Invalid storefront port \"${preferred}\". Set a valid port (1–65535) via --storefront-port or NYMBAL_STOREFRONT_PORT.`,\n )\n }\n for (let i = 0; i < maxAttempts; i++) {\n const candidate = preferred + i\n if (candidate > 65535) break\n if (await isPortFree(candidate, host)) {\n return candidate\n }\n }\n throw new Error(\n `No free storefront port found in range ${preferred}–${Math.min(preferred + maxAttempts - 1, 65535)}. ` +\n `Free a port in that range or pass an explicit free port via --storefront-port.`,\n )\n}\n","import { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport type { NymbalConfig } from '@nymbalhq/config'\n\nexport type TemplateName = 'astro' | 'nextjs'\n\nexport interface TemplateLaunch {\n /** Working directory the storefront dev server runs in. */\n cwd: string\n /** Command + args to start the storefront dev server. */\n command: string\n args: string[]\n /**\n * How the storefront was located. `flat` = the project root IS the storefront\n * (create-nymbal-app output). `filter` = a sub-package in a monorepo layout.\n */\n mode: 'flat' | 'filter'\n}\n\nexport function templateFilterFor(template: NymbalConfig['template']): string {\n return template === 'astro' ? '@nymbalhq/template-astro' : '@nymbalhq/template-nextjs'\n}\n\n/**\n * A flat scaffold (create-nymbal-app output) places the storefront AT the\n * project root: the framework config and a `dev` script live in projectRoot.\n * In that layout we must run the dev server in projectRoot directly — NOT via\n * `pnpm --filter @nymbalhq/template-astro`, which would match the workspace\n * template package (the wrong directory) inside a monorepo, or match nothing at\n * all outside one.\n */\nexport function isFlatScaffold(projectRoot: string, template: TemplateName): boolean {\n const marker = template === 'astro' ? 'astro.config.mjs' : 'next.config.mjs'\n const altMarker = template === 'astro' ? 'astro.config.ts' : 'next.config.ts'\n return existsSync(resolve(projectRoot, marker)) || existsSync(resolve(projectRoot, altMarker))\n}\n\n/**\n * Resolve the framework's local CLI bin inside the project's node_modules.\n * We spawn the local bin directly (rather than the package-manager `run dev`\n * script) so we can inject the resolved free port via `--port`, overriding the\n * hardcoded port baked into the scaffold's `dev` script. Returns null when the\n * bin is not present (deps not installed) so the caller can produce an\n * actionable error.\n */\nexport function resolveLocalBin(projectRoot: string, bin: string): string | null {\n const binPath = resolve(projectRoot, 'node_modules', '.bin', bin)\n return existsSync(binPath) ? binPath : null\n}\n\n/**\n * Build the storefront dev launch plan.\n *\n * @param storefrontPort - the resolved (free) port the storefront must bind to.\n * Passed to the framework via flag so we control where it listens, instead of\n * relying on the framework's hardcoded default which may already be taken.\n */\nexport function planTemplateLaunch(\n projectRoot: string,\n template: TemplateName,\n storefrontPort: number,\n): TemplateLaunch {\n if (isFlatScaffold(projectRoot, template)) {\n // Run the framework dev server directly in the project root. We pass the\n // port explicitly so the framework binds where we resolved a free port,\n // overriding any hardcoded port in the scaffold's package.json script.\n const binName = template === 'astro' ? 'astro' : 'next'\n const localBin = resolveLocalBin(projectRoot, binName)\n if (!localBin) {\n throw new Error(\n `Cannot find the ${binName} dev server in ${projectRoot}/node_modules/.bin. ` +\n `Install dependencies first (e.g. \\`pnpm install\\`), then re-run \\`nymbal dev\\`.`,\n )\n }\n return {\n cwd: projectRoot,\n command: localBin,\n args: ['dev', '--port', String(storefrontPort), ...foregroundArgs(template)],\n mode: 'flat',\n }\n }\n\n // Monorepo layout fallback: the storefront lives in a workspace sub-package.\n const filter = templateFilterFor(template)\n return {\n cwd: projectRoot,\n command: 'pnpm',\n args: ['--filter', filter, 'dev', ...foregroundArgs(template)],\n mode: 'filter',\n }\n}\n\n/**\n * Astro 7 backgrounds `astro dev` when it detects an AI agent, so the launcher would see its child exit while the\n * server lives on detached; --ignore-lock keeps it in the foreground. `next dev` rejects unknown options.\n */\nfunction foregroundArgs(template: TemplateName): string[] {\n return template === 'astro' ? ['--ignore-lock'] : []\n}\n","import { defineCommand } from 'citty'\nimport type { NymbalConfig } from '@nymbalhq/config'\nimport { loadProject } from '../utils/project.js'\nimport { createCommandStore, runMigrations } from '@nymbalhq/platform'\nimport { dirname, resolve } from 'node:path'\nimport { existsSync } from 'node:fs'\n\nexport const migrateCommand = defineCommand({\n meta: { name: 'migrate', description: 'Run database migrations (Drizzle)' },\n async run() {\n const { config, projectRoot } = await loadProject()\n const kind = await migrateProject(config, projectRoot)\n // eslint-disable-next-line no-console\n console.log(`✓ migrations applied (${kind})`)\n },\n})\n\n/** Applies the project's migrations to its command store; the store is closed again before returning. */\nexport async function migrateProject(config: NymbalConfig, projectRoot: string): Promise<string> {\n const store = createCommandStore(config)\n try {\n await runMigrations(store, { migrationsRoot: resolveMigrations(projectRoot) })\n return store.kind\n } finally {\n await store.close()\n }\n}\n\nexport function resolveMigrations(projectRoot: string): string {\n // 1. Project-local override (scaffolded projects or custom migrations)\n const local = resolve(projectRoot, 'migrations')\n if (existsSync(local)) return local\n\n // 2. Monorepo workspace: packages/platform/migrations (for CI and fresh clones)\n const monorepoDev = resolve(projectRoot, 'packages/platform/migrations')\n if (existsSync(monorepoDev)) return monorepoDev\n\n // 3. Published package: node_modules/@nymbalhq/platform/migrations\n //\n // We must NOT use `require.resolve('@nymbalhq/platform/package.json')` nor\n // `require.resolve('@nymbalhq/platform')`: the package's `exports` map is\n // ESM-only and does not expose `./package.json`, so CJS resolution throws\n // (ERR_PACKAGE_PATH_NOT_EXPORTED / \"No exports main defined\"). Instead we\n // locate the installed package directory directly under node_modules, which\n // is independent of the exports map and works for symlinked (pnpm workspace)\n // and flat installs alike.\n const pkgDir = resolvePackageDir(projectRoot, '@nymbalhq/platform')\n if (pkgDir) {\n const pkgMigrations = resolve(pkgDir, 'migrations')\n if (existsSync(pkgMigrations)) return pkgMigrations\n }\n\n return local\n}\n\n/**\n * Resolve the on-disk root directory of an installed package from `fromRoot`,\n * by walking up the directory tree looking for `node_modules/<pkgName>`. This\n * does not depend on the package's `exports` map (which may be ESM-only and not\n * expose `./package.json`), and resolves correctly for pnpm symlinked workspace\n * installs as well as flat node_modules. Returns null when not found.\n */\nexport function resolvePackageDir(fromRoot: string, pkgName: string): string | null {\n let dir = resolve(fromRoot)\n for (let i = 0; i < 24; i++) {\n const candidate = resolve(dir, 'node_modules', pkgName)\n if (existsSync(resolve(candidate, 'package.json'))) {\n return candidate\n }\n const parent = dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n return null\n}\n","import { existsSync } from 'node:fs'\nimport { createRequire } from 'node:module'\nimport { dirname, join } from 'node:path'\n\nfunction hasIndex(dir: string): boolean {\n return existsSync(join(dir, 'index.html'))\n}\n\n/**\n * The admin dist to serve: `NYMBAL_ADMIN_DIST` when it holds `index.html` (read per call), else the installed\n * `@nymbalhq/admin` dist when built, else null.\n */\nexport function resolveAdminRoot(): string | null {\n const override = process.env['NYMBAL_ADMIN_DIST']\n if (override && hasIndex(override)) return override\n try {\n const manifest = createRequire(import.meta.url).resolve('@nymbalhq/admin/package.json')\n const dist = join(dirname(manifest), 'dist')\n return hasIndex(dist) ? dist : null\n } catch {\n return null\n }\n}\n","import { defineCommand } from 'citty'\nimport { loadProject } from '../utils/project.js'\nimport { runOrFail } from '../utils/spawn.js'\nimport { isFlatScaffold, resolveLocalBin, templateFilterFor } from '../utils/template-runner.js'\n\nexport const buildCommand = defineCommand({\n meta: { name: 'build', description: 'Production build of the configured template' },\n async run() {\n const { config, projectRoot } = await loadProject()\n if (!isFlatScaffold(projectRoot, config.template)) {\n // Inside this monorepo the storefront is a workspace package.\n await runOrFail('pnpm', ['--filter', templateFilterFor(config.template), 'build'], {\n cwd: projectRoot,\n })\n return\n }\n const binName = config.template === 'astro' ? 'astro' : 'next'\n const bin = resolveLocalBin(projectRoot, binName)\n if (!bin) {\n throw new Error(\n `Cannot find the ${binName} binary in ${projectRoot}/node_modules/.bin. ` +\n 'Install dependencies first, then re-run `nymbal build`.',\n )\n }\n await runOrFail(bin, ['build'], { cwd: projectRoot })\n },\n})\n","import { defineCommand } from 'citty'\nimport { loadProject } from '../utils/project.js'\nimport { createPlatform, runSeed } from '@nymbalhq/platform'\nimport { getCliVersion } from '../utils/version.js'\nimport { migrateProject } from './migrate.js'\n\nexport const seedCommand = defineCommand({\n meta: { name: 'seed', description: 'Re-seed demo content (products, categories)' },\n async run() {\n const { config, projectRoot } = await loadProject()\n // A fresh project has no tables yet; `nymbal dev` migrates before it seeds, and so does this.\n await migrateProject(config, projectRoot)\n const platform = createPlatform(config)\n try {\n const result = await runSeed({\n config,\n commandStore: platform.commandStore,\n documentStore: platform.documentStore,\n eventBus: platform.eventBus,\n logger: platform.logger,\n version: getCliVersion(),\n })\n // eslint-disable-next-line no-console\n console.log(\n result.alreadySeeded\n ? '✓ demo content already present, nothing to seed'\n : `✓ seeded ${result.products} products across ${result.categories} categories`,\n )\n } finally {\n await platform.close()\n }\n },\n})\n","import { defineCommand } from 'citty'\nimport { intro, outro, text, select, spinner, isCancel, cancel } from '@clack/prompts'\nimport * as p from 'picocolors'\nimport { loadProject } from '../utils/project.js'\nimport { createApp } from '@nymbalhq/platform'\nimport { runWooCommerceImport, writeReport, type ImportEntity, type ProgressEvent } from '@nymbalhq/importers'\nimport { join } from 'node:path'\nimport { getCliVersion } from '../utils/version.js'\n\nexport const importCommand = defineCommand({\n meta: {\n name: 'import',\n description: 'Migrate content from WooCommerce (or other sources) into Nymbal',\n },\n args: {\n source: {\n type: 'string',\n description: 'Import source (woocommerce)',\n },\n url: {\n type: 'string',\n description: 'Store URL (e.g. https://mystore.com)',\n },\n key: {\n type: 'string',\n description: 'WooCommerce Consumer Key (or set WOOCOMMERCE_KEY env var)',\n },\n secret: {\n type: 'string',\n description: 'WooCommerce Consumer Secret (or set WOOCOMMERCE_SECRET env var)',\n },\n entities: {\n type: 'string',\n description: 'Comma-separated list: products,customers,orders,reviews (default: products,customers,orders)',\n },\n ai: {\n type: 'boolean',\n description: 'Enable AI enrichment (default: true)',\n default: true,\n },\n gdpr: {\n type: 'boolean',\n description: 'Anonymise customer PII (default: true)',\n default: true,\n },\n fresh: {\n type: 'boolean',\n description: 'Ignore previous progress and re-import',\n default: false,\n },\n concurrency: {\n type: 'string',\n description: 'Parallel import workers (default: 4)',\n },\n },\n async run({ args }) {\n const { config } = await loadProject()\n const projectRoot = process.cwd()\n const statePath = join(projectRoot, '.nymbal-migration.json')\n const isTTY = process.stdin.isTTY ?? false\n\n intro(p.bold('Nymbal Import'))\n\n // ── Resolve source ────────────────────────────────────────────────────────\n let source = args.source\n if (!source) {\n if (!isTTY) {\n console.error('--source is required (woocommerce)')\n process.exit(1)\n }\n const picked = await select({\n message: 'Source platform?',\n options: [{ value: 'woocommerce', label: 'WooCommerce' }],\n })\n if (isCancel(picked)) { cancel('Import cancelled'); process.exit(0) }\n source = String(picked)\n }\n if (source !== 'woocommerce') {\n console.error(`Unsupported source: ${source}. Only 'woocommerce' is supported.`)\n process.exit(1)\n }\n\n // ── Resolve credentials ───────────────────────────────────────────────────\n let storeUrl = args.url\n if (!storeUrl) {\n if (!isTTY) { console.error('--url is required'); process.exit(1) }\n const val = await text({ message: 'Store URL?', placeholder: 'https://mystore.com', validate: (v) => v.startsWith('http') ? undefined : 'Must be a URL' })\n if (isCancel(val)) { cancel('Import cancelled'); process.exit(0) }\n storeUrl = String(val)\n }\n\n let consumerKey = args.key ?? process.env['WOOCOMMERCE_KEY'] ?? ''\n if (!consumerKey) {\n if (!isTTY) { console.error('--key or WOOCOMMERCE_KEY is required'); process.exit(1) }\n const val = await text({ message: 'Consumer Key?', placeholder: 'ck_...' })\n if (isCancel(val)) { cancel('Import cancelled'); process.exit(0) }\n consumerKey = String(val)\n }\n\n let consumerSecret = args.secret ?? process.env['WOOCOMMERCE_SECRET'] ?? ''\n if (!consumerSecret) {\n if (!isTTY) { console.error('--secret or WOOCOMMERCE_SECRET is required'); process.exit(1) }\n const val = await text({ message: 'Consumer Secret?', placeholder: 'cs_...' })\n if (isCancel(val)) { cancel('Import cancelled'); process.exit(0) }\n consumerSecret = String(val)\n }\n\n // ── Resolve entity list ───────────────────────────────────────────────────\n let entityList: ImportEntity[]\n if (args.entities) {\n entityList = args.entities.split(',').map((e) => e.trim()) as ImportEntity[]\n } else {\n entityList = ['categories', 'products', 'customers', 'orders']\n }\n\n const concurrency = parseInt(String(args.concurrency ?? '4'), 10)\n const aiEnabled = args.ai !== false\n const gdprEnabled = args.gdpr !== false\n\n // ── Bootstrap app ─────────────────────────────────────────────────────────\n const loadSpin = spinner()\n loadSpin.start('Starting platform…')\n const app = await createApp(config, { version: getCliVersion() })\n loadSpin.stop('Platform ready')\n\n try {\n const report = await runWooCommerceImport(\n {\n credentials: { url: storeUrl, consumerKey, consumerSecret },\n entities: entityList,\n ai: aiEnabled,\n gdpr: gdprEnabled,\n fresh: args.fresh,\n concurrency,\n projectRoot,\n currency: config.store.currency,\n statePath,\n },\n {\n services: app.services,\n repos: app.repos,\n adapters: { ai: app.adapters.ai, reviews: app.adapters.reviews },\n onProgress(event: ProgressEvent) {\n if (event.kind === 'phase') {\n console.log(p.cyan(` → ${event.phase}`))\n } else if (event.kind === 'progress') {\n const pct = Math.round((event.done / event.total) * 100)\n process.stdout.write(`\\r ${event.entity}: ${event.done}/${event.total} (${pct}%) `)\n if (event.done === event.total) process.stdout.write('\\n')\n } else if (event.kind === 'error') {\n console.log(p.red(` ✗ ${event.phase} [${event.id}]: ${event.message}`))\n }\n },\n },\n )\n\n const reportPath = await writeReport(report, projectRoot, config.store.name)\n\n outro(\n [\n p.green('✓ Import complete'),\n ` Products: ${report.imported.products}`,\n ` Customers: ${report.imported.customers}`,\n ` Orders: ${report.imported.orders}`,\n ` Categories: ${report.imported.categories}`,\n ...(aiEnabled ? [` AI enriched: ${report.enriched.enriched} products`] : []),\n ...(report.errors.length > 0 ? [p.yellow(` ⚠ ${report.errors.length} errors — see report`)] : []),\n ``,\n ` Report: ${reportPath}`,\n ` Next: ${p.bold('nymbal dev')}`,\n ].join('\\n'),\n )\n } finally {\n await app.stop()\n }\n },\n})\n","import { defineCommand } from 'citty'\nimport pc from 'picocolors'\nimport { loadProject } from '../utils/project.js'\nimport { NymbalError } from '@nymbalhq/types'\n\nexport const configValidateCommand = defineCommand({\n meta: { name: 'config:validate', description: 'Validate nymbal.config.ts' },\n async run() {\n try {\n const { config, path } = await loadProject()\n // eslint-disable-next-line no-console\n console.log(pc.green(`✓ config valid`) + ` (${path})`)\n // eslint-disable-next-line no-console\n console.log(\n ` template: ${config.template}, cloud: ${config.infrastructure.cloud}, commandStore: ${config.infrastructure.commandStore}`,\n )\n process.exit(0)\n } catch (err) {\n if (err instanceof NymbalError) {\n // eslint-disable-next-line no-console\n console.error(pc.red('✗ config invalid'))\n // eslint-disable-next-line no-console\n console.error(err.message)\n } else {\n // eslint-disable-next-line no-console\n console.error(err)\n }\n process.exit(1)\n }\n },\n})\n","import { defineCommand } from 'citty'\nimport { loadConfig } from '@nymbalhq/config'\nimport { run, runOrFail } from '../utils/spawn.js'\n\nexport const testCommand = defineCommand({\n meta: { name: 'test', description: 'Run unit + integration tests (vitest)' },\n async run() {\n await runOrFail('pnpm', ['vitest', 'run'])\n },\n})\n\nexport const testE2eCommand = defineCommand({\n meta: { name: 'test:e2e', description: 'Run Playwright E2E against the configured template' },\n async run() {\n const { config } = await loadConfig()\n await runOrFail('pnpm', [\n '--filter', '@nymbalhq/e2e', 'exec',\n 'playwright', 'test', '--project', config.template, '--grep-invert', '@visual|@a11y',\n ])\n },\n})\n\nexport const testVisualCommand = defineCommand({\n meta: { name: 'test:visual', description: 'Run visual regression tests (Playwright toHaveScreenshot)' },\n args: {\n 'update-baselines': {\n type: 'boolean',\n description: 'Regenerate screenshot baselines',\n default: false,\n },\n },\n async run({ args }) {\n const { config } = await loadConfig()\n const isCI = !!process.env.CI\n const updateBaselines = args['update-baselines']\n\n if (updateBaselines && !isCI) {\n // Run in Docker for Linux-consistent baselines\n const dockerImage = 'mcr.microsoft.com/playwright:v1.50-jammy'\n const cwd = process.cwd()\n await runOrFail('docker', [\n 'run', '--rm', '-v', `${cwd}:${cwd}`, '-w', cwd,\n dockerImage, 'sh', '-c',\n `pnpm --filter @nymbalhq/e2e exec playwright test --project ${config.template} --grep \"@visual\" --update-snapshots`,\n ])\n } else {\n const pwArgs = [\n '--filter', '@nymbalhq/e2e', 'exec',\n 'playwright', 'test', '--project', config.template, '--grep', '@visual',\n ]\n if (updateBaselines) pwArgs.push('--update-snapshots')\n await runOrFail('pnpm', pwArgs)\n }\n },\n})\n\nexport const testContractsCommand = defineCommand({\n meta: { name: 'test:contracts', description: 'Run adapter contract tests' },\n args: {\n adapter: { type: 'string', description: 'Run only contracts for a specific adapter (e.g. payments, email)' },\n },\n async run({ args }) {\n const vArgs = [\n 'vitest', 'run',\n '--project', 'contracts-native',\n ]\n if (args.adapter) {\n // Pass the specific file path as additional argument\n vArgs.push(`tests/contracts/${String(args.adapter)}.test.ts`)\n }\n await runOrFail('pnpm', vArgs)\n },\n})\n\nexport const testPerformanceCommand = defineCommand({\n meta: { name: 'test:performance', description: 'Run Lighthouse CI against the configured template' },\n async run() {\n const { config } = await loadConfig()\n const port = config.template === 'nextjs' ? 3000 : 4321\n await runOrFail('pnpm', ['lhci', 'autorun'], {\n env: {\n ...process.env,\n NYMBAL_TEMPLATE: config.template,\n NYMBAL_TEMPLATE_PORT: String(port),\n },\n })\n },\n})\n\nexport const testAllCommand = defineCommand({\n meta: { name: 'test:all', description: 'Run unit, contract, e2e, visual, and performance tests' },\n async run() {\n const steps: Array<{ name: string; args: string[] }> = [\n { name: 'unit', args: ['vitest', 'run'] },\n { name: 'contracts', args: ['vitest', 'run', '--project', 'contracts-native'] },\n ]\n\n for (const step of steps) {\n const { done } = run('pnpm', step.args)\n const code = await done\n if (code !== 0) {\n // eslint-disable-next-line no-console\n console.error(`✗ ${step.name} failed`)\n process.exit(code)\n }\n }\n\n const { config } = await loadConfig()\n await runOrFail('pnpm', [\n '--filter', '@nymbalhq/e2e', 'exec',\n 'playwright', 'test', '--project', config.template, '--grep-invert', '@visual|@a11y',\n ])\n await runOrFail('pnpm', [\n '--filter', '@nymbalhq/e2e', 'exec',\n 'playwright', 'test', '--project', config.template, '--grep', '@visual',\n ])\n await runOrFail('pnpm', ['lhci', 'autorun'], {\n env: { ...process.env, NYMBAL_TEMPLATE: config.template },\n })\n },\n})\n"],"mappings":"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","names":["defineCommand","defineCommand","dirname","resolve","resolve","existsSync","resolve","dirname","resolve","existsSync","existsSync","dirname","join","defineCommand","shutdown","defineCommand","defineCommand","defineCommand","runSeed","defineCommand","runSeed","defineCommand","createApp","join","defineCommand","join","createApp","defineCommand","pc","defineCommand","pc","defineCommand","loadConfig","defineCommand","loadConfig","defineCommand"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/utils/version.ts","../src/commands/dev.ts","../src/utils/project.ts","../src/utils/spawn.ts","../src/utils/port.ts","../src/utils/template-runner.ts","../src/commands/migrate.ts","../src/admin.ts","../src/utils/shutdown.ts","../src/commands/build.ts","../src/commands/seed.ts","../src/commands/import.ts","../src/commands/config-validate.ts","../src/commands/test.ts"],"sourcesContent":["import { defineCommand, runMain } from 'citty'\nimport { getCliVersion } from './utils/version.js'\nimport { devCommand } from './commands/dev.js'\nimport { buildCommand } from './commands/build.js'\nimport { migrateCommand } from './commands/migrate.js'\nimport { seedCommand } from './commands/seed.js'\nimport { importCommand } from './commands/import.js'\nimport { configValidateCommand } from './commands/config-validate.js'\nimport {\n testAllCommand,\n testCommand,\n testContractsCommand,\n testE2eCommand,\n testPerformanceCommand,\n testVisualCommand,\n} from './commands/test.js'\n\nexport { resolveAdminRoot } from './admin.js'\n\nconst main = defineCommand({\n meta: {\n name: 'nymbal',\n version: getCliVersion(),\n description: 'Nymbal developer CLI',\n },\n subCommands: {\n dev: devCommand,\n build: buildCommand,\n migrate: migrateCommand,\n seed: seedCommand,\n import: importCommand,\n 'config:validate': configValidateCommand,\n test: testCommand,\n 'test:e2e': testE2eCommand,\n 'test:visual': testVisualCommand,\n 'test:contracts': testContractsCommand,\n 'test:performance': testPerformanceCommand,\n 'test:all': testAllCommand,\n },\n})\n\n// citty prints --version through consola, which prefixes `[log]` when CI is set; scripts need the bare version.\nconst [flag, ...rest] = process.argv.slice(2)\nif (rest.length === 0 && (flag === '--version' || flag === '-v')) {\n process.stdout.write(`${getCliVersion()}\\n`)\n} else {\n runMain(main)\n}\n","import { readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst CLI_PACKAGE_NAME = 'nymbal'\n\nlet cached: string | null = null\n\n/**\n * Walks up from this module to the CLI's own package.json (found by name, so a nested or unrelated package.json\n * never answers). That is `dist/` in the workspace and in `node_modules/nymbal`, and `src/utils/` under Vitest.\n */\nfunction readOwnVersion(): string | undefined {\n let dir = dirname(fileURLToPath(import.meta.url))\n for (;;) {\n try {\n const pkg = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')) as {\n name?: string\n version?: string\n }\n if (pkg.name === CLI_PACKAGE_NAME) return pkg.version\n } catch {\n // No readable package.json in this directory: keep walking.\n }\n const parent = dirname(dir)\n if (parent === dir) return undefined\n dir = parent\n }\n}\n\nexport function getCliVersion(): string {\n cached ??= readOwnVersion() ?? '0.0.0'\n return cached\n}\n","import { defineCommand } from 'citty'\nimport pc from 'picocolors'\nimport type { NymbalConfig } from '@nymbalhq/config'\nimport { loadProject } from '../utils/project.js'\nimport { createApp, runSeed } from '@nymbalhq/platform'\nimport { createHttpServer } from '@nymbalhq/http'\nimport { run } from '../utils/spawn.js'\nimport { getCliVersion } from '../utils/version.js'\nimport { findFreePort } from '../utils/port.js'\nimport { planTemplateLaunch } from '../utils/template-runner.js'\nimport { migrateProject } from './migrate.js'\nimport { resolveAdminRoot } from '../admin.js'\nimport { runShutdown, SHUTDOWN_BOUND_MS, type ShutdownStep } from '../utils/shutdown.js'\n\n/** Default storefront dev-server port per template (matches the scaffold scripts). */\nexport function defaultStorefrontPort(template: 'astro' | 'nextjs'): number {\n return template === 'astro' ? 4321 : 3000\n}\n\n/**\n * Resolve the *preferred* storefront port from (in priority order):\n * 1. --storefront-port flag\n * 2. NYMBAL_STOREFRONT_PORT env var\n * 3. the template default (Astro 4321 / Next.js 3000)\n * The value returned here is only the starting point; the dev command then\n * probes upward for a genuinely free port so a busy default never hard-fails.\n */\nexport function preferredStorefrontPort(\n template: 'astro' | 'nextjs',\n flagPort: number | undefined,\n env: NodeJS.ProcessEnv,\n): number {\n if (typeof flagPort === 'number' && Number.isFinite(flagPort)) return flagPort\n const fromEnv = env['NYMBAL_STOREFRONT_PORT']\n if (fromEnv && fromEnv.trim() !== '') {\n const parsed = Number(fromEnv)\n if (Number.isInteger(parsed) && parsed > 0) return parsed\n }\n return defaultStorefrontPort(template)\n}\n\n/**\n * The environment the storefront dev server starts with. The client-side variables must be set before it starts, and\n * both templates skip Stripe when the payments provider variable says `native-stub`, which is every provider but\n * `stripe`.\n */\nexport function storefrontEnv(\n config: NymbalConfig,\n apiUrl: string,\n storefrontPort: number,\n baseEnv: NodeJS.ProcessEnv = process.env,\n): NodeJS.ProcessEnv {\n const stubPayments =\n config.commerce.payments.provider === 'stripe'\n ? {}\n : {\n PUBLIC_NYMBAL_PAYMENTS_PROVIDER: 'native-stub', // Astro\n NEXT_PUBLIC_NYMBAL_PAYMENTS_PROVIDER: 'native-stub', // Next.js\n }\n return {\n ...baseEnv,\n NYMBAL_API_URL: apiUrl,\n PUBLIC_NYMBAL_API_URL: apiUrl, // Astro\n NEXT_PUBLIC_NYMBAL_API_URL: apiUrl, // Next.js\n // The framework also reads the port flag; the env var keeps the scaffold\n // config (astro.config.mjs) in sync when it honours NYMBAL_STOREFRONT_PORT.\n NYMBAL_STOREFRONT_PORT: String(storefrontPort),\n ...stubPayments,\n }\n}\n\n/** The API port: `--port` when given, else the config's `http.port`. */\nfunction apiPort(config: NymbalConfig, flagPort: string | undefined): number {\n if (flagPort === undefined || flagPort.trim() === '') return config.http.port\n const port = Number(flagPort)\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new Error(`--port must be an integer from 1 to 65535, got \"${flagPort}\"`)\n }\n return port\n}\n\nexport const devCommand = defineCommand({\n meta: {\n name: 'dev',\n description: 'Start the API server and the configured storefront template with HMR',\n },\n args: {\n seed: {\n type: 'boolean',\n description: 'Run seed before starting (default: true if empty)',\n default: true,\n },\n apiOnly: {\n type: 'boolean',\n // `alias` is required: citty 0.1.6 registers the camelCase key `apiOnly`\n // with mri and applies `default: false`. Without this alias a kebab\n // `--api-only` flag lands on `args['api-only']`, but `args.apiOnly`\n // resolves to the `false` default first (`??` does not fall through on\n // `false`), so the flag is silently ignored. The alias makes mri map\n // `--api-only` straight to `apiOnly`. Both forms now work.\n alias: 'api-only',\n description: 'Start only the API server (skip template dev server)',\n default: false,\n },\n port: {\n type: 'string',\n description: \"Port for the API server (default: the config's http.port)\",\n },\n storefrontPort: {\n type: 'string',\n alias: 'storefront-port',\n description:\n 'Port for the storefront dev server (default: 4321 Astro / 3000 Next.js). ' +\n 'If busy, the next free port is used. Also settable via NYMBAL_STOREFRONT_PORT.',\n },\n },\n async run({ args }) {\n const loaded = await loadProject()\n const { projectRoot } = loaded\n const port = apiPort(loaded.config, args.port)\n const config: NymbalConfig = { ...loaded.config, http: { ...loaded.config.http, port } }\n const version = getCliVersion()\n\n // Auto-migrate on startup so a fresh clone works without running `nymbal migrate` first\n await migrateProject(config, projectRoot)\n\n const app = await createApp(config, { version })\n const { platform } = app\n\n if (args.seed) {\n const existing = await platform.documentStore.query('products', {\n partitionKey: { field: 'storeId', value: config.store.name },\n limit: 1,\n })\n if (existing.items.length === 0) {\n platform.logger.info({}, 'Seeding demo content (first run)')\n await runSeed({\n config,\n commandStore: platform.commandStore,\n documentStore: platform.documentStore,\n eventBus: platform.eventBus,\n logger: platform.logger,\n version,\n })\n }\n }\n\n const http = createHttpServer({\n config,\n logger: platform.logger,\n documentStore: platform.documentStore,\n version,\n })\n const adminRoot = resolveAdminRoot()\n if (adminRoot === null) {\n // eslint-disable-next-line no-console\n console.log(\n pc.yellow(\n '→ The admin is not built, so /admin/ answers 404: run `pnpm --filter @nymbalhq/admin build`.',\n ),\n )\n }\n await app.attachHttp(http.adapter, { adminRoot })\n await http.start()\n\n const stopApi: ShutdownStep[] = [\n { name: 'http.stop', run: () => http.stop() },\n { name: 'app.stop', run: () => app.stop() },\n ]\n const shutdownWith = (steps: ShutdownStep[]): Promise<never> =>\n runShutdown(steps, {\n boundMs: SHUTDOWN_BOUND_MS,\n logger: platform.logger,\n exit: (code) => process.exit(code),\n })\n\n if (args.apiOnly) {\n const shutdown = (signal: string) => {\n platform.logger.info({ signal }, 'Shutting down API')\n return shutdownWith(stopApi)\n }\n process.on('SIGINT', () => void shutdown('SIGINT'))\n process.on('SIGTERM', () => void shutdown('SIGTERM'))\n // Keep process alive — Playwright webServer will kill it when done\n return\n }\n\n // Resolve a free storefront port. The preferred port is configurable but may\n // be taken (a developer commonly has another project on 4321/3000), so we\n // probe upward for a free one instead of hard-failing.\n const flagPortRaw = args.storefrontPort\n const flagPort =\n typeof flagPortRaw === 'string' && flagPortRaw.trim() !== '' ? Number(flagPortRaw) : undefined\n const preferred = preferredStorefrontPort(config.template, flagPort, process.env)\n const storefrontPort = await findFreePort(preferred)\n if (storefrontPort !== preferred) {\n // eslint-disable-next-line no-console\n console.log(\n pc.yellow(\n `→ Storefront port ${preferred} is busy; using free port ${pc.bold(String(storefrontPort))} instead.`,\n ),\n )\n }\n\n // Plan how to launch the storefront. A flat scaffold (create-nymbal-app\n // output) runs the framework dev server directly in the project root; a\n // monorepo layout falls back to a pnpm --filter on the template package.\n const launch = planTemplateLaunch(projectRoot, config.template, storefrontPort)\n\n const apiUrl = `http://localhost:${config.http.port}`\n const storefrontUrl = `http://localhost:${storefrontPort}`\n // eslint-disable-next-line no-console\n console.log(\n pc.cyan(\n `→ Starting storefront (${pc.bold(config.template)}, ${launch.mode}) on ${pc.bold(storefrontUrl)}`,\n ),\n )\n // eslint-disable-next-line no-console\n console.log(pc.dim(` API: ${apiUrl}`))\n\n const templateProc = run(launch.command, launch.args, {\n cwd: launch.cwd,\n env: storefrontEnv(config, apiUrl, storefrontPort),\n })\n\n let shuttingDown = false\n const shutdown = (signal: string) => {\n shuttingDown = true\n platform.logger.info({ signal }, 'Shutting down')\n return shutdownWith([\n {\n name: 'storefront.kill',\n run: async () => {\n templateProc.child.kill('SIGINT')\n },\n },\n ...stopApi,\n ])\n }\n process.on('SIGINT', () => void shutdown('SIGINT'))\n process.on('SIGTERM', () => void shutdown('SIGTERM'))\n\n const templateExit = await templateProc.done\n platform.logger.info({ code: templateExit }, 'Template process exited')\n // A Ctrl-C reaches the storefront too, so it exits during the signal's own shutdown, which ends the process.\n // Calling `runShutdown` again would count as a repeat signal and exit 1 at once.\n if (shuttingDown) return\n await shutdown('template-exit')\n },\n})\n","import { existsSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\nimport { findConfigFile, loadConfig, type LoadedConfig } from '@nymbalhq/config'\n\n/**\n * Loads `<projectRoot>/.env` into the process environment, then the project's config, so `env()` calls in\n * `nymbal.config.ts` see it. A variable already set in the environment is kept: `process.loadEnvFile` never overrides.\n */\nexport async function loadProject(startDir: string = process.cwd()): Promise<LoadedConfig> {\n const configPath = findConfigFile(startDir)\n if (configPath) {\n const envFile = resolve(dirname(configPath), '.env')\n if (existsSync(envFile)) process.loadEnvFile(envFile)\n }\n return loadConfig(startDir)\n}\n","import { spawn, type ChildProcess, type SpawnOptions } from 'node:child_process'\n\nexport interface RunOptions extends SpawnOptions {\n name?: string\n}\n\nexport function run(\n command: string,\n args: string[],\n options: RunOptions = {},\n): { child: ChildProcess; done: Promise<number> } {\n const child = spawn(command, args, {\n stdio: 'inherit',\n shell: false,\n ...options,\n })\n const done = new Promise<number>((resolve, reject) => {\n child.on('error', reject)\n child.on('exit', (code) => resolve(code ?? 0))\n })\n return { child, done }\n}\n\nexport async function runOrFail(\n command: string,\n args: string[],\n options: RunOptions = {},\n): Promise<void> {\n const { done } = run(command, args, options)\n const code = await done\n if (code !== 0) {\n throw new Error(`${command} ${args.join(' ')} exited with code ${code}`)\n }\n}\n","import { createServer } from 'node:net'\n\n/**\n * Resolve a usable storefront port.\n *\n * The headline `nymbal dev` flow must not hard-fail when the preferred port is\n * already taken (a developer commonly has another project on 4321/3000). We\n * probe the preferred port first and, if it is busy, increment until we find a\n * free one — exactly how the underlying dev servers (Astro, Next.js) behave on\n * their own, but here we resolve the port *before* spawning so we can tell the\n * storefront which port to bind and tell the user where to open the browser.\n */\nexport async function isPortFree(port: number, host?: string): Promise<boolean> {\n return new Promise<boolean>((resolve) => {\n const server = createServer()\n server.once('error', (err: NodeJS.ErrnoException) => {\n // EADDRINUSE / EACCES → not usable. Any other error → treat as not free\n // rather than silently swallowing it; the caller will skip this port.\n if (err.code !== 'EADDRINUSE' && err.code !== 'EACCES') {\n // eslint-disable-next-line no-console\n console.error(`[dev] unexpected error probing port ${port}:`, err.message)\n }\n resolve(false)\n })\n server.once('listening', () => {\n server.close(() => resolve(true))\n })\n // Bind across all interfaces (no explicit host) so a port already held on\n // IPv6 (e.g. another dev server on [::1]) is correctly seen as busy. A\n // 127.0.0.1-only probe would miss an IPv6 listener and wrongly report free,\n // then the framework — which binds dual-stack — would fail on that port.\n if (host) {\n server.listen(port, host)\n } else {\n server.listen(port)\n }\n })\n}\n\n/**\n * Find a free port starting at `preferred`, scanning upward up to `maxAttempts`\n * times. Throws an actionable error if no port in the range is free.\n */\nexport async function findFreePort(\n preferred: number,\n maxAttempts = 20,\n host?: string,\n): Promise<number> {\n if (!Number.isInteger(preferred) || preferred < 1 || preferred > 65535) {\n throw new Error(\n `Invalid storefront port \"${preferred}\". Set a valid port (1–65535) via --storefront-port or NYMBAL_STOREFRONT_PORT.`,\n )\n }\n for (let i = 0; i < maxAttempts; i++) {\n const candidate = preferred + i\n if (candidate > 65535) break\n if (await isPortFree(candidate, host)) {\n return candidate\n }\n }\n throw new Error(\n `No free storefront port found in range ${preferred}–${Math.min(preferred + maxAttempts - 1, 65535)}. ` +\n `Free a port in that range or pass an explicit free port via --storefront-port.`,\n )\n}\n","import { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport type { NymbalConfig } from '@nymbalhq/config'\n\nexport type TemplateName = 'astro' | 'nextjs'\n\nexport interface TemplateLaunch {\n /** Working directory the storefront dev server runs in. */\n cwd: string\n /** Command + args to start the storefront dev server. */\n command: string\n args: string[]\n /**\n * How the storefront was located. `flat` = the project root IS the storefront\n * (create-nymbal-app output). `filter` = a sub-package in a monorepo layout.\n */\n mode: 'flat' | 'filter'\n}\n\nexport function templateFilterFor(template: NymbalConfig['template']): string {\n return template === 'astro' ? '@nymbalhq/template-astro' : '@nymbalhq/template-nextjs'\n}\n\n/**\n * A flat scaffold (create-nymbal-app output) places the storefront AT the\n * project root: the framework config and a `dev` script live in projectRoot.\n * In that layout we must run the dev server in projectRoot directly — NOT via\n * `pnpm --filter @nymbalhq/template-astro`, which would match the workspace\n * template package (the wrong directory) inside a monorepo, or match nothing at\n * all outside one.\n */\nexport function isFlatScaffold(projectRoot: string, template: TemplateName): boolean {\n const marker = template === 'astro' ? 'astro.config.mjs' : 'next.config.mjs'\n const altMarker = template === 'astro' ? 'astro.config.ts' : 'next.config.ts'\n return existsSync(resolve(projectRoot, marker)) || existsSync(resolve(projectRoot, altMarker))\n}\n\n/**\n * Resolve the framework's local CLI bin inside the project's node_modules.\n * We spawn the local bin directly (rather than the package-manager `run dev`\n * script) so we can inject the resolved free port via `--port`, overriding the\n * hardcoded port baked into the scaffold's `dev` script. Returns null when the\n * bin is not present (deps not installed) so the caller can produce an\n * actionable error.\n */\nexport function resolveLocalBin(projectRoot: string, bin: string): string | null {\n const binPath = resolve(projectRoot, 'node_modules', '.bin', bin)\n return existsSync(binPath) ? binPath : null\n}\n\n/**\n * Build the storefront dev launch plan.\n *\n * @param storefrontPort - the resolved (free) port the storefront must bind to.\n * Passed to the framework via flag so we control where it listens, instead of\n * relying on the framework's hardcoded default which may already be taken.\n */\nexport function planTemplateLaunch(\n projectRoot: string,\n template: TemplateName,\n storefrontPort: number,\n): TemplateLaunch {\n if (isFlatScaffold(projectRoot, template)) {\n // Run the framework dev server directly in the project root. We pass the\n // port explicitly so the framework binds where we resolved a free port,\n // overriding any hardcoded port in the scaffold's package.json script.\n const binName = template === 'astro' ? 'astro' : 'next'\n const localBin = resolveLocalBin(projectRoot, binName)\n if (!localBin) {\n throw new Error(\n `Cannot find the ${binName} dev server in ${projectRoot}/node_modules/.bin. ` +\n `Install dependencies first (e.g. \\`pnpm install\\`), then re-run \\`nymbal dev\\`.`,\n )\n }\n return {\n cwd: projectRoot,\n command: localBin,\n args: ['dev', '--port', String(storefrontPort), ...foregroundArgs(template)],\n mode: 'flat',\n }\n }\n\n // Monorepo layout fallback: the storefront lives in a workspace sub-package.\n const filter = templateFilterFor(template)\n return {\n cwd: projectRoot,\n command: 'pnpm',\n args: ['--filter', filter, 'dev', ...foregroundArgs(template)],\n mode: 'filter',\n }\n}\n\n/**\n * Astro 7 backgrounds `astro dev` when it detects an AI agent, so the launcher would see its child exit while the\n * server lives on detached; --ignore-lock keeps it in the foreground. `next dev` rejects unknown options.\n */\nfunction foregroundArgs(template: TemplateName): string[] {\n return template === 'astro' ? ['--ignore-lock'] : []\n}\n","import { defineCommand } from 'citty'\nimport type { NymbalConfig } from '@nymbalhq/config'\nimport { loadProject } from '../utils/project.js'\nimport { createCommandStore, runMigrations } from '@nymbalhq/platform'\nimport { dirname, resolve } from 'node:path'\nimport { existsSync } from 'node:fs'\n\nexport const migrateCommand = defineCommand({\n meta: { name: 'migrate', description: 'Run database migrations (Drizzle)' },\n async run() {\n const { config, projectRoot } = await loadProject()\n const kind = await migrateProject(config, projectRoot)\n // eslint-disable-next-line no-console\n console.log(`✓ migrations applied (${kind})`)\n },\n})\n\n/** Applies the project's migrations to its command store; the store is closed again before returning. */\nexport async function migrateProject(config: NymbalConfig, projectRoot: string): Promise<string> {\n const store = createCommandStore(config)\n try {\n await runMigrations(store, { migrationsRoot: resolveMigrations(projectRoot) })\n return store.kind\n } finally {\n await store.close()\n }\n}\n\nexport function resolveMigrations(projectRoot: string): string {\n // 1. Project-local override (scaffolded projects or custom migrations)\n const local = resolve(projectRoot, 'migrations')\n if (existsSync(local)) return local\n\n // 2. Monorepo workspace: packages/platform/migrations (for CI and fresh clones)\n const monorepoDev = resolve(projectRoot, 'packages/platform/migrations')\n if (existsSync(monorepoDev)) return monorepoDev\n\n // 3. Published package: node_modules/@nymbalhq/platform/migrations\n //\n // We must NOT use `require.resolve('@nymbalhq/platform/package.json')` nor\n // `require.resolve('@nymbalhq/platform')`: the package's `exports` map is\n // ESM-only and does not expose `./package.json`, so CJS resolution throws\n // (ERR_PACKAGE_PATH_NOT_EXPORTED / \"No exports main defined\"). Instead we\n // locate the installed package directory directly under node_modules, which\n // is independent of the exports map and works for symlinked (pnpm workspace)\n // and flat installs alike.\n const pkgDir = resolvePackageDir(projectRoot, '@nymbalhq/platform')\n if (pkgDir) {\n const pkgMigrations = resolve(pkgDir, 'migrations')\n if (existsSync(pkgMigrations)) return pkgMigrations\n }\n\n return local\n}\n\n/**\n * Resolve the on-disk root directory of an installed package from `fromRoot`,\n * by walking up the directory tree looking for `node_modules/<pkgName>`. This\n * does not depend on the package's `exports` map (which may be ESM-only and not\n * expose `./package.json`), and resolves correctly for pnpm symlinked workspace\n * installs as well as flat node_modules. Returns null when not found.\n */\nexport function resolvePackageDir(fromRoot: string, pkgName: string): string | null {\n let dir = resolve(fromRoot)\n for (let i = 0; i < 24; i++) {\n const candidate = resolve(dir, 'node_modules', pkgName)\n if (existsSync(resolve(candidate, 'package.json'))) {\n return candidate\n }\n const parent = dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n return null\n}\n","import { existsSync } from 'node:fs'\nimport { createRequire } from 'node:module'\nimport { dirname, join } from 'node:path'\n\nfunction hasIndex(dir: string): boolean {\n return existsSync(join(dir, 'index.html'))\n}\n\n/**\n * The admin dist to serve: `NYMBAL_ADMIN_DIST` when it holds `index.html` (read per call), else the installed\n * `@nymbalhq/admin` dist when built, else null.\n */\nexport function resolveAdminRoot(): string | null {\n const override = process.env['NYMBAL_ADMIN_DIST']\n if (override && hasIndex(override)) return override\n try {\n const manifest = createRequire(import.meta.url).resolve('@nymbalhq/admin/package.json')\n const dist = join(dirname(manifest), 'dist')\n return hasIndex(dist) ? dist : null\n } catch {\n return null\n }\n}\n","/**\n * The CLI's own bound on a signal shutdown. Below the E2E wrapper's `DEFAULT_SHUTDOWN_MS` (`scripts/e2e-server.mjs`),\n * so the pending step is logged before the wrapper's SIGKILL lands.\n */\nexport const SHUTDOWN_BOUND_MS = 3000\n\nexport interface ShutdownStep {\n name: string\n run: () => Promise<void>\n}\n\nexport interface ShutdownOptions {\n boundMs: number\n logger: { info: (obj: unknown, msg?: string) => void; error: (obj: unknown, msg?: string) => void }\n exit: (code: number) => never\n}\n\nlet running = false\n\n/**\n * Runs the steps in order, then exits 0. A step that throws is logged and the rest still run, then it exits 1. A step\n * still pending at `boundMs` is named in the log and it exits 1, so no client can hold the process open. A second call\n * while one runs (a repeat signal) exits 1 at once.\n */\nexport async function runShutdown(steps: ShutdownStep[], opts: ShutdownOptions): Promise<never> {\n if (running) {\n opts.logger.error({}, 'Shutdown already running; exiting now')\n return opts.exit(1)\n }\n running = true\n\n let pending: string | undefined\n let failed = false\n const work = (async () => {\n for (const step of steps) {\n pending = step.name\n try {\n await step.run()\n } catch (err) {\n failed = true\n opts.logger.error({ err, step: step.name }, `Shutdown step \"${step.name}\" failed`)\n }\n }\n pending = undefined\n })()\n\n let timer: ReturnType<typeof setTimeout> | undefined\n const bound = new Promise<'bound'>((resolve) => {\n timer = setTimeout(() => resolve('bound'), opts.boundMs)\n })\n const outcome = await Promise.race([work.then(() => 'done' as const), bound])\n clearTimeout(timer)\n\n if (outcome === 'bound') {\n opts.logger.error(\n { step: pending, boundMs: opts.boundMs },\n `Shutdown step \"${pending}\" did not finish within ${opts.boundMs} ms; exiting`,\n )\n return opts.exit(1)\n }\n return opts.exit(failed ? 1 : 0)\n}\n","import { defineCommand } from 'citty'\nimport { loadProject } from '../utils/project.js'\nimport { runOrFail } from '../utils/spawn.js'\nimport { isFlatScaffold, resolveLocalBin, templateFilterFor } from '../utils/template-runner.js'\n\nexport const buildCommand = defineCommand({\n meta: { name: 'build', description: 'Production build of the configured template' },\n async run() {\n const { config, projectRoot } = await loadProject()\n if (!isFlatScaffold(projectRoot, config.template)) {\n // Inside this monorepo the storefront is a workspace package.\n await runOrFail('pnpm', ['--filter', templateFilterFor(config.template), 'build'], {\n cwd: projectRoot,\n })\n return\n }\n const binName = config.template === 'astro' ? 'astro' : 'next'\n const bin = resolveLocalBin(projectRoot, binName)\n if (!bin) {\n throw new Error(\n `Cannot find the ${binName} binary in ${projectRoot}/node_modules/.bin. ` +\n 'Install dependencies first, then re-run `nymbal build`.',\n )\n }\n await runOrFail(bin, ['build'], { cwd: projectRoot })\n },\n})\n","import { defineCommand } from 'citty'\nimport { loadProject } from '../utils/project.js'\nimport { createPlatform, runSeed } from '@nymbalhq/platform'\nimport { getCliVersion } from '../utils/version.js'\nimport { migrateProject } from './migrate.js'\n\nexport const seedCommand = defineCommand({\n meta: { name: 'seed', description: 'Re-seed demo content (products, categories)' },\n async run() {\n const { config, projectRoot } = await loadProject()\n // A fresh project has no tables yet; `nymbal dev` migrates before it seeds, and so does this.\n await migrateProject(config, projectRoot)\n const platform = createPlatform(config)\n try {\n const result = await runSeed({\n config,\n commandStore: platform.commandStore,\n documentStore: platform.documentStore,\n eventBus: platform.eventBus,\n logger: platform.logger,\n version: getCliVersion(),\n })\n // eslint-disable-next-line no-console\n console.log(\n result.alreadySeeded\n ? '✓ demo content already present, nothing to seed'\n : `✓ seeded ${result.products} products across ${result.categories} categories`,\n )\n } finally {\n await platform.close()\n }\n },\n})\n","import { defineCommand } from 'citty'\nimport { intro, outro, text, select, spinner, isCancel, cancel } from '@clack/prompts'\nimport * as p from 'picocolors'\nimport { loadProject } from '../utils/project.js'\nimport { createApp } from '@nymbalhq/platform'\nimport { runWooCommerceImport, writeReport, type ImportEntity, type ProgressEvent } from '@nymbalhq/importers'\nimport { join } from 'node:path'\nimport { getCliVersion } from '../utils/version.js'\n\nexport const importCommand = defineCommand({\n meta: {\n name: 'import',\n description: 'Migrate content from WooCommerce (or other sources) into Nymbal',\n },\n args: {\n source: {\n type: 'string',\n description: 'Import source (woocommerce)',\n },\n url: {\n type: 'string',\n description: 'Store URL (e.g. https://mystore.com)',\n },\n key: {\n type: 'string',\n description: 'WooCommerce Consumer Key (or set WOOCOMMERCE_KEY env var)',\n },\n secret: {\n type: 'string',\n description: 'WooCommerce Consumer Secret (or set WOOCOMMERCE_SECRET env var)',\n },\n entities: {\n type: 'string',\n description: 'Comma-separated list: products,customers,orders,reviews (default: products,customers,orders)',\n },\n ai: {\n type: 'boolean',\n description: 'Enable AI enrichment (default: true)',\n default: true,\n },\n gdpr: {\n type: 'boolean',\n description: 'Anonymise customer PII (default: true)',\n default: true,\n },\n fresh: {\n type: 'boolean',\n description: 'Ignore previous progress and re-import',\n default: false,\n },\n concurrency: {\n type: 'string',\n description: 'Parallel import workers (default: 4)',\n },\n },\n async run({ args }) {\n const { config } = await loadProject()\n const projectRoot = process.cwd()\n const statePath = join(projectRoot, '.nymbal-migration.json')\n const isTTY = process.stdin.isTTY ?? false\n\n intro(p.bold('Nymbal Import'))\n\n // ── Resolve source ────────────────────────────────────────────────────────\n let source = args.source\n if (!source) {\n if (!isTTY) {\n console.error('--source is required (woocommerce)')\n process.exit(1)\n }\n const picked = await select({\n message: 'Source platform?',\n options: [{ value: 'woocommerce', label: 'WooCommerce' }],\n })\n if (isCancel(picked)) { cancel('Import cancelled'); process.exit(0) }\n source = String(picked)\n }\n if (source !== 'woocommerce') {\n console.error(`Unsupported source: ${source}. Only 'woocommerce' is supported.`)\n process.exit(1)\n }\n\n // ── Resolve credentials ───────────────────────────────────────────────────\n let storeUrl = args.url\n if (!storeUrl) {\n if (!isTTY) { console.error('--url is required'); process.exit(1) }\n const val = await text({ message: 'Store URL?', placeholder: 'https://mystore.com', validate: (v) => v.startsWith('http') ? undefined : 'Must be a URL' })\n if (isCancel(val)) { cancel('Import cancelled'); process.exit(0) }\n storeUrl = String(val)\n }\n\n let consumerKey = args.key ?? process.env['WOOCOMMERCE_KEY'] ?? ''\n if (!consumerKey) {\n if (!isTTY) { console.error('--key or WOOCOMMERCE_KEY is required'); process.exit(1) }\n const val = await text({ message: 'Consumer Key?', placeholder: 'ck_...' })\n if (isCancel(val)) { cancel('Import cancelled'); process.exit(0) }\n consumerKey = String(val)\n }\n\n let consumerSecret = args.secret ?? process.env['WOOCOMMERCE_SECRET'] ?? ''\n if (!consumerSecret) {\n if (!isTTY) { console.error('--secret or WOOCOMMERCE_SECRET is required'); process.exit(1) }\n const val = await text({ message: 'Consumer Secret?', placeholder: 'cs_...' })\n if (isCancel(val)) { cancel('Import cancelled'); process.exit(0) }\n consumerSecret = String(val)\n }\n\n // ── Resolve entity list ───────────────────────────────────────────────────\n let entityList: ImportEntity[]\n if (args.entities) {\n entityList = args.entities.split(',').map((e) => e.trim()) as ImportEntity[]\n } else {\n entityList = ['categories', 'products', 'customers', 'orders']\n }\n\n const concurrency = parseInt(String(args.concurrency ?? '4'), 10)\n const aiEnabled = args.ai !== false\n const gdprEnabled = args.gdpr !== false\n\n // ── Bootstrap app ─────────────────────────────────────────────────────────\n const loadSpin = spinner()\n loadSpin.start('Starting platform…')\n const app = await createApp(config, { version: getCliVersion() })\n loadSpin.stop('Platform ready')\n\n try {\n const report = await runWooCommerceImport(\n {\n credentials: { url: storeUrl, consumerKey, consumerSecret },\n entities: entityList,\n ai: aiEnabled,\n gdpr: gdprEnabled,\n fresh: args.fresh,\n concurrency,\n projectRoot,\n currency: config.store.currency,\n statePath,\n },\n {\n services: app.services,\n repos: app.repos,\n adapters: { ai: app.adapters.ai, reviews: app.adapters.reviews },\n onProgress(event: ProgressEvent) {\n if (event.kind === 'phase') {\n console.log(p.cyan(` → ${event.phase}`))\n } else if (event.kind === 'progress') {\n const pct = Math.round((event.done / event.total) * 100)\n process.stdout.write(`\\r ${event.entity}: ${event.done}/${event.total} (${pct}%) `)\n if (event.done === event.total) process.stdout.write('\\n')\n } else if (event.kind === 'error') {\n console.log(p.red(` ✗ ${event.phase} [${event.id}]: ${event.message}`))\n }\n },\n },\n )\n\n const reportPath = await writeReport(report, projectRoot, config.store.name)\n\n outro(\n [\n p.green('✓ Import complete'),\n ` Products: ${report.imported.products}`,\n ` Customers: ${report.imported.customers}`,\n ` Orders: ${report.imported.orders}`,\n ` Categories: ${report.imported.categories}`,\n ...(aiEnabled ? [` AI enriched: ${report.enriched.enriched} products`] : []),\n ...(report.errors.length > 0 ? [p.yellow(` ⚠ ${report.errors.length} errors — see report`)] : []),\n ``,\n ` Report: ${reportPath}`,\n ` Next: ${p.bold('nymbal dev')}`,\n ].join('\\n'),\n )\n } finally {\n await app.stop()\n }\n },\n})\n","import { defineCommand } from 'citty'\nimport pc from 'picocolors'\nimport { loadProject } from '../utils/project.js'\nimport { NymbalError } from '@nymbalhq/types'\n\nexport const configValidateCommand = defineCommand({\n meta: { name: 'config:validate', description: 'Validate nymbal.config.ts' },\n async run() {\n try {\n const { config, path } = await loadProject()\n // eslint-disable-next-line no-console\n console.log(pc.green(`✓ config valid`) + ` (${path})`)\n // eslint-disable-next-line no-console\n console.log(\n ` template: ${config.template}, cloud: ${config.infrastructure.cloud}, commandStore: ${config.infrastructure.commandStore}`,\n )\n process.exit(0)\n } catch (err) {\n if (err instanceof NymbalError) {\n // eslint-disable-next-line no-console\n console.error(pc.red('✗ config invalid'))\n // eslint-disable-next-line no-console\n console.error(err.message)\n } else {\n // eslint-disable-next-line no-console\n console.error(err)\n }\n process.exit(1)\n }\n },\n})\n","import { defineCommand } from 'citty'\nimport { loadConfig } from '@nymbalhq/config'\nimport { run, runOrFail } from '../utils/spawn.js'\n\nexport const testCommand = defineCommand({\n meta: { name: 'test', description: 'Run unit + integration tests (vitest)' },\n async run() {\n await runOrFail('pnpm', ['vitest', 'run'])\n },\n})\n\nexport const testE2eCommand = defineCommand({\n meta: { name: 'test:e2e', description: 'Run Playwright E2E against the configured template' },\n async run() {\n const { config } = await loadConfig()\n await runOrFail('pnpm', [\n '--filter', '@nymbalhq/e2e', 'exec',\n 'playwright', 'test', '--project', config.template, '--grep-invert', '@visual|@a11y',\n ])\n },\n})\n\nexport const testVisualCommand = defineCommand({\n meta: { name: 'test:visual', description: 'Run visual regression tests (Playwright toHaveScreenshot)' },\n args: {\n 'update-baselines': {\n type: 'boolean',\n description: 'Regenerate screenshot baselines',\n default: false,\n },\n },\n async run({ args }) {\n const { config } = await loadConfig()\n const isCI = !!process.env.CI\n const updateBaselines = args['update-baselines']\n\n if (updateBaselines && !isCI) {\n // Run in Docker for Linux-consistent baselines\n const dockerImage = 'mcr.microsoft.com/playwright:v1.50-jammy'\n const cwd = process.cwd()\n await runOrFail('docker', [\n 'run', '--rm', '-v', `${cwd}:${cwd}`, '-w', cwd,\n dockerImage, 'sh', '-c',\n `pnpm --filter @nymbalhq/e2e exec playwright test --project ${config.template} --grep \"@visual\" --update-snapshots`,\n ])\n } else {\n const pwArgs = [\n '--filter', '@nymbalhq/e2e', 'exec',\n 'playwright', 'test', '--project', config.template, '--grep', '@visual',\n ]\n if (updateBaselines) pwArgs.push('--update-snapshots')\n await runOrFail('pnpm', pwArgs)\n }\n },\n})\n\nexport const testContractsCommand = defineCommand({\n meta: { name: 'test:contracts', description: 'Run adapter contract tests' },\n args: {\n adapter: { type: 'string', description: 'Run only contracts for a specific adapter (e.g. payments, email)' },\n },\n async run({ args }) {\n const vArgs = [\n 'vitest', 'run',\n '--project', 'contracts-native',\n ]\n if (args.adapter) {\n // Pass the specific file path as additional argument\n vArgs.push(`tests/contracts/${String(args.adapter)}.test.ts`)\n }\n await runOrFail('pnpm', vArgs)\n },\n})\n\nexport const testPerformanceCommand = defineCommand({\n meta: { name: 'test:performance', description: 'Run Lighthouse CI against the configured template' },\n async run() {\n const { config } = await loadConfig()\n const port = config.template === 'nextjs' ? 3000 : 4321\n await runOrFail('pnpm', ['lhci', 'autorun'], {\n env: {\n ...process.env,\n NYMBAL_TEMPLATE: config.template,\n NYMBAL_TEMPLATE_PORT: String(port),\n },\n })\n },\n})\n\nexport const testAllCommand = defineCommand({\n meta: { name: 'test:all', description: 'Run unit, contract, e2e, visual, and performance tests' },\n async run() {\n const steps: Array<{ name: string; args: string[] }> = [\n { name: 'unit', args: ['vitest', 'run'] },\n { name: 'contracts', args: ['vitest', 'run', '--project', 'contracts-native'] },\n ]\n\n for (const step of steps) {\n const { done } = run('pnpm', step.args)\n const code = await done\n if (code !== 0) {\n // eslint-disable-next-line no-console\n console.error(`✗ ${step.name} failed`)\n process.exit(code)\n }\n }\n\n const { config } = await loadConfig()\n await runOrFail('pnpm', [\n '--filter', '@nymbalhq/e2e', 'exec',\n 'playwright', 'test', '--project', config.template, '--grep-invert', '@visual|@a11y',\n ])\n await runOrFail('pnpm', [\n '--filter', '@nymbalhq/e2e', 'exec',\n 'playwright', 'test', '--project', config.template, '--grep', '@visual',\n ])\n await runOrFail('pnpm', ['lhci', 'autorun'], {\n env: { ...process.env, NYMBAL_TEMPLATE: config.template },\n })\n },\n})\n"],"mappings":"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","names":["defineCommand","defineCommand","dirname","resolve","resolve","existsSync","resolve","dirname","resolve","existsSync","existsSync","dirname","join","resolve","defineCommand","shutdown","defineCommand","defineCommand","defineCommand","runSeed","defineCommand","runSeed","defineCommand","createApp","join","defineCommand","join","createApp","defineCommand","pc","defineCommand","pc","defineCommand","loadConfig","defineCommand","loadConfig","defineCommand"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nymbal",
3
- "version": "0.2.0",
3
+ "version": "1.0.0",
4
4
  "description": "nymbal — developer CLI for the Nymbal platform",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -34,12 +34,12 @@
34
34
  "@clack/prompts": "^0.7.0",
35
35
  "citty": "^0.1.6",
36
36
  "picocolors": "^1.1.1",
37
- "@nymbalhq/admin": "0.2.0",
38
- "@nymbalhq/config": "0.2.0",
39
- "@nymbalhq/http": "0.2.0",
40
- "@nymbalhq/importers": "0.2.0",
41
- "@nymbalhq/platform": "0.2.0",
42
- "@nymbalhq/types": "0.2.0"
37
+ "@nymbalhq/admin": "1.0.0",
38
+ "@nymbalhq/config": "1.0.0",
39
+ "@nymbalhq/importers": "0.2.1",
40
+ "@nymbalhq/http": "1.0.0",
41
+ "@nymbalhq/platform": "1.0.0",
42
+ "@nymbalhq/types": "1.0.0"
43
43
  },
44
44
  "devDependencies": {
45
45
  "tsup": "^8.3.5",