@ekanos/cli 0.22.1 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -4
- package/dist/commands/add.js +21 -10
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/contract.js +12 -2
- package/dist/commands/contract.js.map +1 -1
- package/dist/commands/dev.js +33 -2
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/publish.d.ts +6 -0
- package/dist/commands/publish.js +80 -4
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/status.d.ts +44 -0
- package/dist/commands/status.js +79 -18
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/upgrade.js +287 -144
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/docs-links.js +5 -1
- package/dist/docs-links.js.map +1 -1
- package/dist/errors.d.ts +2 -0
- package/dist/errors.js +9 -0
- package/dist/errors.js.map +1 -1
- package/dist/exit-codes.d.ts +3 -0
- package/dist/exit-codes.js +3 -0
- package/dist/exit-codes.js.map +1 -1
- package/dist/experience/checks.js +2 -1
- package/dist/experience/checks.js.map +1 -1
- package/dist/experience/definition-checks.d.ts +7 -0
- package/dist/experience/definition-checks.js +36 -4
- package/dist/experience/definition-checks.js.map +1 -1
- package/dist/experience/init.js +10 -0
- package/dist/experience/init.js.map +1 -1
- package/dist/experience/load-experience.js +33 -2
- package/dist/experience/load-experience.js.map +1 -1
- package/dist/experience/pins.d.ts +10 -0
- package/dist/experience/pins.js +19 -1
- package/dist/experience/pins.js.map +1 -1
- package/dist/generated/phosphor-names.d.ts +3 -0
- package/dist/generated/phosphor-names.js +1541 -0
- package/dist/generated/phosphor-names.js.map +1 -0
- package/dist/harness-scaffold.d.ts +13 -0
- package/dist/harness-scaffold.js +19 -3
- package/dist/harness-scaffold.js.map +1 -1
- package/dist/icon-findings.d.ts +12 -17
- package/dist/icon-findings.js +49 -74
- package/dist/icon-findings.js.map +1 -1
- package/dist/index.js +28 -5
- package/dist/index.js.map +1 -1
- package/dist/lockfile-instances.d.ts +60 -0
- package/dist/lockfile-instances.js +177 -0
- package/dist/lockfile-instances.js.map +1 -0
- package/dist/pack-hygiene.d.ts +8 -0
- package/dist/pack-hygiene.js +57 -0
- package/dist/pack-hygiene.js.map +1 -0
- package/dist/package-manager.d.ts +34 -6
- package/dist/package-manager.js +130 -20
- package/dist/package-manager.js.map +1 -1
- package/dist/project.js +11 -0
- package/dist/project.js.map +1 -1
- package/dist/repo/scaffold.js +4 -0
- package/dist/repo/scaffold.js.map +1 -1
- package/dist/validate-findings.js +10 -1
- package/dist/validate-findings.js.map +1 -1
- package/dist/workspace-root.d.ts +16 -0
- package/dist/workspace-root.js +50 -0
- package/dist/workspace-root.js.map +1 -0
- package/package.json +4 -4
- package/templates/AGENTS.md.tmpl +11 -15
- package/templates/experience/package.json.tmpl +8 -6
- package/templates/experience/src/widgets/hello-widget.test.tsx.tmpl +49 -0
- package/templates/experience/vitest.config.ts.tmpl +21 -0
- package/templates/harness/next.config.mjs.tmpl +7 -4
- package/templates/package.json.tmpl +5 -5
- package/templates/skills/build-integration/references/widget-design.md +2 -3
- package/templates/skills/polish-widgets/references/patterns.md +5 -5
- package/dist/generated/fa-free-names.d.ts +0 -9
- package/dist/generated/fa-free-names.js +0 -2599
- package/dist/generated/fa-free-names.js.map +0 -1
package/dist/commands/dev.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"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","sourcesContent":["import { type SourceCatalog } from '@ekanos/integration-schema';\nimport {\n type RepoDiscovery,\n discoverRepo,\n isRepoRoot,\n} from '@ekanos/integration-schema/repo';\nimport { spawn } from 'node:child_process';\nimport * as path from 'node:path';\n\nimport {\n requireSession,\n resolveAuthEnvironment,\n refreshStoredSession,\n} from '../auth/session';\nimport { fetchSourceCatalog } from '../catalog-api';\nimport { assertHarnessCompatible } from '../compatibility';\nimport type { CliContext } from '../context';\nimport {\n type HarnessResolver,\n detectKind,\n loadHarnessResolver,\n readExperienceProject,\n writeSessionCatalog,\n} from '../dev-experience';\nimport { preconditionError, usageError } from '../errors';\nimport {\n BUILD_CACHE_DIR,\n HARNESS_DIR,\n HARNESS_PACKAGE,\n SHELL_REGISTRY_FILENAME,\n assertShellDirIsOurs,\n bootstrapHarnessConfig,\n ensureGitignoreEntry,\n missingDependencies,\n readInstalledHarness,\n scaffoldShell,\n} from '../harness-scaffold';\nimport {\n detectPackageManager,\n execArgs,\n formatCommand,\n installCommand,\n} from '../package-manager';\nimport {\n createOutputTail,\n findIgnoredBuilds,\n ignoredBuildsHint,\n} from '../pnpm-builds';\nimport { loadProject } from '../project';\nimport { resolveSourceTarget } from '../source-target';\nimport { displayPath } from '../ui';\nimport { announceUpdate, checkForUpdate } from '../update-notice';\n\nexport interface DevArgs {\n /** Project directory (contains ekanos.json). Defaults to cwd. */\n dir: string;\n /** Port for the dev server. */\n port?: string;\n /**\n * Interface to bind. Defaults to loopback — see `resolveHost`. Anything\n * else is an explicit, warned-about decision to expose the harness.\n *\n * NOTE: unrelated to the Ekanos HOST the update notice checks against —\n * this is the local bind address for `next dev`, never an Ekanos origin.\n */\n host?: string;\n /** Rewrite every generated file even when its bytes already match. */\n force: boolean;\n /**\n * Explicit `--start` / `--no-start`. Undefined means \"decide from the\n * output mode\": a JSON caller is an agent or a pipe and must not be handed\n * a process that never exits.\n */\n start?: boolean;\n env?: Record<string, string | undefined>;\n /** Experience projects: an offline directory of contracts (`--contracts-dir`). */\n contractsDir?: string;\n /** Test seams. */\n loadResolver?: (projectDir: string) => Promise<HarnessResolver>;\n fetchCatalog?: () => Promise<SourceCatalog | null>;\n}\n\nconst DEFAULT_PORT = 3100;\n\n/**\n * Loopback, NOT Next's default.\n *\n * `next dev` binds 0.0.0.0 unless told otherwise, so the harness would be\n * reachable by anyone on the same network — a coffee-shop Wi-Fi, a shared\n * office VLAN — while we printed \"http://localhost:3100\" and implied\n * otherwise. It renders a partner's integration with their fixtures and, in\n * live mode, whatever their vendor API returns; there is no auth in front of\n * any of it. Binding loopback by default costs a partner nothing and makes\n * exposure a thing they ask for.\n */\nconst DEFAULT_HOST = '127.0.0.1';\n\n/** Addresses that are only reachable from this machine. */\nconst LOOPBACK_HOSTS = new Set(['127.0.0.1', '::1', 'localhost']);\n\n/**\n * Set for the dev server when `--host` binds beyond loopback. The shell's\n * API routes (`@ekanos/harness/api`) refuse non-loopback `Host` headers\n * unless this is `1`: they hold the partner's local OAuth credentials and\n * run handlers on request, so exposing them has to be a decision — this one,\n * made after the warning below — rather than a side effect of the bind.\n */\nconst EXPOSED_ENV = 'EKANOS_HARNESS_EXPOSED';\n\n/** Where the harness generates, and reads, local dev credentials. */\nconst LOCAL_SECRETS_PATH = path.join('.ekanos', 'local-secrets.json');\n\n/**\n * `dev` — scaffold the local harness shell into the partner's project, then\n * run it with their own Next.\n *\n * The shape of this verb follows from one rule: we must be able to ship a\n * harness bugfix as an `@ekanos/harness` version bump that a partner picks up\n * with `pnpm up`, with zero edits to any file they own. So everything under\n * `.ekanos/` is generated, gitignored and rewritten freely, `harness.config.ts`\n * at the project root is written once and never touched again, and all actual\n * harness behaviour lives in the installed package.\n *\n * Two idempotency properties matter and are both tested: a second run produces\n * byte-identical files and rewrites nothing (so Next's watcher stays quiet),\n * and `.gitignore` never grows a duplicate line.\n */\nexport async function runDev(ctx: CliContext, args: DevArgs): Promise<number> {\n // At a repo root one harness serves every package; anywhere else the\n // project is a single integration or experience, exactly as before.\n const repo = isRepoRoot(path.resolve(args.dir))\n ? discoverRepo(path.resolve(args.dir))\n : null;\n const experience =\n repo === null && detectKind(path.resolve(args.dir)) === 'experience';\n const loaded: DevProject = repo\n ? repoProject(repo)\n : experience\n ? experienceProject(path.resolve(args.dir))\n : loadProject(args.dir);\n const port = parsePort(args.port);\n const host = parseHost(args.host);\n const exposed = !LOOPBACK_HOSTS.has(host);\n const pm = detectPackageManager(loaded.projectDir);\n\n const notice = await checkForUpdate({ env: args.env ?? process.env });\n announceUpdate(ctx, notice);\n\n // Fail before writing anything: the shell declares no dependencies of its\n // own, so a missing one would otherwise surface as an opaque Next\n // resolution error minutes later.\n const missing = missingDependencies(loaded.projectDir);\n if (missing.length > 0) {\n throw preconditionError(\n `${missing.length} package${missing.length === 1 ? '' : 's'} the ` +\n `harness needs ${missing.length === 1 ? 'is' : 'are'} not installed ` +\n `in ${loaded.projectDir}: ${missing.join(', ')}.`,\n `Run \"${installCommand(pm, missing)}\" in ${loaded.projectDir}, then ` +\n 're-run \"ekanos dev\".',\n );\n }\n\n const harness = readInstalledHarness(loaded.projectDir);\n const harnessVersion = harness?.version;\n if (!harnessVersion) {\n throw preconditionError(\n `${HARNESS_PACKAGE} is installed but declares no version.`,\n `Reinstall it with \"${installCommand(pm, [HARNESS_PACKAGE])}\" in ` +\n `${loaded.projectDir}, then re-run \"ekanos dev\".`,\n );\n }\n\n // The templates ship with the CLI and the code they import ships with the\n // harness, so a partner can upgrade one without the other. Name that\n // mismatch here rather than letting it surface later as a module-resolution\n // error inside a shell we cheerfully certified as current.\n assertHarnessCompatible({\n harnessVersion,\n harnessManifest: harness?.manifest,\n installHint: (spec) => installCommand(pm, [spec]),\n });\n\n // Validate the shell target BEFORE writing anything at all. Bootstrapping\n // harness.config.ts first and only then discovering that .ekanos/harness is\n // a file or someone else's tree would leave the project half-scaffolded.\n assertShellDirIsOurs(path.join(loaded.projectDir, HARNESS_DIR), args.force);\n\n // An experience has no integration to register, so it gets no\n // project-root registry: the shell carries its own empty one.\n if (repo) {\n for (const problem of repo.problems) {\n ctx.warn(`${problem.where}: ${problem.message}`);\n }\n }\n\n // A repo's integration packages each keep their own harness.config.ts; the\n // repo shell's registry imports them.\n const repoConfigs = repo\n ? repo.packages\n .filter((pkg) => pkg.kind === 'integration')\n .map((pkg) =>\n bootstrapHarnessConfig(pkg.dir, loadProject(pkg.dir).integrations),\n )\n : [];\n const config = repo\n ? {\n bootstrapped: repoConfigs.some((result) => result.bootstrapped),\n configPath: path.join(\n loaded.projectDir,\n HARNESS_DIR,\n SHELL_REGISTRY_FILENAME,\n ),\n }\n : experience\n ? {\n bootstrapped: false,\n configPath: path.join(\n loaded.projectDir,\n HARNESS_DIR,\n SHELL_REGISTRY_FILENAME,\n ),\n }\n : bootstrapHarnessConfig(loaded.projectDir, loaded.integrations);\n const shell = scaffoldShell({\n projectDir: loaded.projectDir,\n slug: loaded.primary.slug,\n harnessVersion,\n force: args.force,\n sourceGlobs: loaded.project.sourceGlobs,\n ...(experience\n ? { experienceEntry: readExperienceProject(loaded.projectDir).entry }\n : {}),\n ...(repo\n ? {\n repo: {\n integrations: repo.packages\n .filter((pkg) => pkg.kind === 'integration')\n .map((pkg) => ({ name: pkg.name, dir: pkg.relDir })),\n experiences: repo.packages\n .filter((pkg) => pkg.kind === 'experience')\n .map((pkg) => ({\n name: pkg.name,\n dir: pkg.relDir,\n entry: readExperienceProject(pkg.dir).entry,\n })),\n },\n }\n : {}),\n });\n const gitignoreUpdated = ensureGitignoreEntry(loaded.projectDir);\n\n if (shell.stale) {\n ctx.log(\n `Regenerating ${HARNESS_DIR} — ${shell.staleReasons.join('; ')}. ` +\n `Nothing you own changed; ${config.configPath} is untouched.`,\n );\n }\n if (shell.buildCacheCleared) {\n ctx.log(\n ` removed ${HARNESS_DIR}/${BUILD_CACHE_DIR} (Next's cache from the previous shell)`,\n );\n }\n\n if (config.bootstrapped) {\n ctx.log(` created harness.config.ts (yours — edit it, we never will)`);\n }\n for (const file of shell.created) ctx.log(` created ${HARNESS_DIR}/${file}`);\n for (const file of shell.updated) ctx.log(` updated ${HARNESS_DIR}/${file}`);\n if (gitignoreUpdated) ctx.log(' updated .gitignore (.ekanos/)');\n ctx.log(\n ` live-mode OAuth: the harness generates ${LOCAL_SECRETS_PATH} on first ` +\n 'use — fill it in and follow \"Local OAuth\" on the Activation surface.',\n );\n\n let integrations: ExperienceStartup | null = null;\n if (repo) {\n // Each experience package resolves its own integrations through the repo\n // server; the session catalog is shared from the repo root.\n writeSessionCatalog(\n loaded.projectDir,\n await tryFetchCatalog(ctx, args, loaded.projectDir),\n );\n for (const pkg of repo.packages) {\n ctx.log(` ${pkg.kind} ${pkg.name} v${pkg.version} (${pkg.relDir})`);\n }\n } else if (experience) {\n integrations = await resolveExperienceIntegrations(\n ctx,\n args,\n loaded.projectDir,\n );\n }\n\n // `--hostname` is passed ALWAYS, never left to Next's default, so the URL\n // we print is the URL that is actually served.\n const serverArgs = ['dev', '--port', String(port), '--hostname', host];\n const serverEnv: Record<string, string> = exposed\n ? { [EXPOSED_ENV]: '1' }\n : {};\n const command =\n (exposed ? `${EXPOSED_ENV}=1 ` : '') +\n formatCommand(pm.bin, execArgs(pm, 'next', serverArgs));\n const url = `http://${displayHost(host)}:${port}`;\n\n const scaffold = {\n kind: repo ? 'repo' : experience ? 'experience' : 'integration',\n ...(repo\n ? {\n packages: repo.packages.map((pkg) => ({\n name: pkg.name,\n kind: pkg.kind,\n dir: pkg.relDir,\n })),\n }\n : {}),\n ...(integrations\n ? {\n overrides: integrations.overrides,\n publishBlocked: integrations.overrides.length > 0,\n }\n : {}),\n slug: loaded.primary.slug,\n // An experience lists the integrations it depends on (provenance lines);\n // an integration project lists its own slugs.\n integrations: integrations\n ? integrations.lines\n : repo\n ? repo.packages\n .filter((p) => p.kind === 'integration')\n .map((p) => p.name)\n : loaded.integrations.map((i) => i.slug),\n projectDir: loaded.projectDir,\n harnessDir: shell.harnessDir,\n harnessVersion,\n previousVersion: shell.previousVersion,\n previousMarker: shell.previousMarker,\n stale: shell.stale,\n staleReasons: shell.staleReasons,\n buildCacheCleared: shell.buildCacheCleared,\n sourceGlobs: loaded.project.sourceGlobs ?? [],\n created: shell.created,\n updated: shell.updated,\n unchanged: shell.unchanged,\n configBootstrapped: config.bootstrapped,\n configPath: config.configPath,\n gitignoreUpdated,\n ...(notice ? { toolchain: notice } : {}),\n };\n\n if (exposed) {\n ctx.warn(\n `WARNING: --host ${host} exposes the harness beyond this machine. It ` +\n 'has no authentication, and it renders your fixtures and — in live ' +\n 'mode — real responses from your vendor API. Its API routes hold the ' +\n `client secret from ${LOCAL_SECRETS_PATH}, the tokens onTokens stored, ` +\n 'and run your handlers on request; they refuse non-loopback callers ' +\n `unless ${EXPOSED_ENV}=1, which this sets. Anyone who can reach ` +\n `${url} can read and run all of it. Omit --host to bind ${DEFAULT_HOST}.`,\n );\n }\n\n // A JSON caller is an agent or a pipe. Handing it a dev server that never\n // exits would hang its tool call forever and it would never see the\n // envelope, so JSON mode scaffolds and reports the command instead of\n // running it. `--start` overrides; `--no-start` opts out in a terminal.\n const shouldStart = args.start ?? !ctx.jsonMode;\n if (!shouldStart) {\n const reason = args.start === false ? 'no-start' : 'non-interactive';\n const note =\n reason === 'non-interactive'\n ? `Scaffolded only: the server was NOT started because this run is non-interactive (JSON output, a pipe, or an agent). Pass --start to run it, or run: ${command}`\n : `Scaffolded only (--no-start). Run: ${command}`;\n ctx.log(note);\n return ctx.succeed(\n {\n ...scaffold,\n server: {\n started: false,\n reason,\n note,\n command,\n url,\n port,\n host,\n exposed,\n },\n },\n ctx.ui.result({\n title: 'Harness ready',\n rows: [\n ['Directory', displayPath(shell.harnessDir, process.cwd())],\n ['URL', url],\n ['Started', 'no (scaffold only)'],\n ['Start', command],\n ],\n }),\n );\n }\n\n ctx.log(ctx.ui.dim(`Starting the harness on ${url} (${command})…`));\n const tail = createOutputTail();\n const exitCode = await spawnServer({\n ctx,\n tail,\n bin: pm.bin,\n argv: execArgs(pm, 'next', serverArgs),\n cwd: shell.harnessDir,\n env: serverEnv,\n });\n\n const data = {\n ...scaffold,\n server: { started: true, command, url, port, host, exposed, exitCode },\n };\n\n if (exitCode === 0) {\n return ctx.succeed(\n data,\n ctx.ui.result({ title: 'Harness stopped', rows: [['URL', url]] }),\n );\n }\n\n const ignoredBuilds = findIgnoredBuilds(tail.text());\n\n return ctx.failWith({\n code: 'dev_server_failed',\n message: `\"${command}\" exited with code ${exitCode}.`,\n hint:\n ignoredBuilds.length > 0\n ? ignoredBuildsHint(ignoredBuilds)\n : 'Read the Next output on stderr. If it cannot resolve @ekanos/harness ' +\n `or next, reinstall dependencies in ${loaded.projectDir}; if a route ` +\n `fails to compile, delete ${shell.harnessDir} and re-run \"ekanos dev\".`,\n // Transparent passthrough of Next's own exit code.\n exitCode,\n data,\n });\n}\n\nfunction spawnServer(params: {\n ctx: CliContext;\n tail: ReturnType<typeof createOutputTail>;\n bin: string;\n argv: string[];\n cwd: string;\n env: Record<string, string>;\n}): Promise<number> {\n return new Promise<number>((resolve, reject) => {\n const child = spawn(params.bin, params.argv, {\n cwd: params.cwd,\n env: { ...process.env, ...params.env },\n // stdin inherited so Next's own key handling works; stdout/stderr piped\n // so we can route them and keep OUR stdout reserved for the envelope.\n stdio: ['inherit', 'pipe', 'pipe'],\n });\n\n child.stdout?.on('data', (chunk: Buffer) => {\n params.tail.push(chunk);\n (params.ctx.jsonMode ? process.stderr : process.stdout).write(chunk);\n });\n child.stderr?.on('data', (chunk: Buffer) => {\n params.tail.push(chunk);\n process.stderr.write(chunk);\n });\n\n child.on('error', (error) => reject(error));\n child.on('close', (code) => resolve(code ?? 1));\n });\n}\n\n/**\n * The hostname to show a human. `127.0.0.1` is spelled `localhost` because\n * that is what people type; a wildcard bind is spelled `localhost` too, but\n * only after `exposed` has already been warned about — printing `0.0.0.0` as\n * a URL is not useful.\n */\nfunction displayHost(host: string): string {\n if (host === '127.0.0.1' || host === '0.0.0.0' || host === '::') {\n return 'localhost';\n }\n if (host === '::1') return '[::1]';\n return host;\n}\n\nfunction parseHost(raw: string | undefined): string {\n if (raw === undefined) return DEFAULT_HOST;\n\n const host = raw.trim();\n if (host.length === 0) {\n throw usageError(\n 'Invalid --host \"\".',\n `Pass an interface to bind, e.g. \"--host 0.0.0.0\" to expose the ` +\n `harness on your network, or omit it to bind ${DEFAULT_HOST}.`,\n );\n }\n return host;\n}\n\nfunction parsePort(raw: string | undefined): number {\n if (raw === undefined) return DEFAULT_PORT;\n\n const port = Number(raw);\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw usageError(\n `Invalid --port \"${raw}\".`,\n 'Pass an integer between 1 and 65535, e.g. \"--port 3100\".',\n );\n }\n return port;\n}\n\ninterface DevProject {\n projectDir: string;\n integrations: Array<{ slug: string; entry: string }>;\n primary: { slug: string };\n project: { sourceGlobs?: string[] | undefined };\n}\n\nfunction experienceProject(projectDir: string): DevProject {\n const { slug } = readExperienceProject(projectDir);\n return {\n projectDir,\n // An experience registers no integration of its own with the harness; its\n // integrations come from ekanos.json through /__ekanos/api.\n integrations: [],\n primary: { slug },\n project: {},\n };\n}\n\nfunction repoProject(repo: RepoDiscovery): DevProject {\n return {\n projectDir: repo.root,\n integrations: [],\n primary: { slug: path.basename(repo.root) },\n // The shell's stylesheet scans integrations/ already; experiences/ is the\n // other half of a repo.\n project: { sourceGlobs: ['experiences/**/*.{ts,tsx}'] },\n };\n}\n\ninterface ExperienceStartup {\n lines: string[];\n overrides: Array<{ integration: string; path: string; via: 'file' | 'env' }>;\n}\n\n/**\n * Resolve every integration with the harness the project installed, print where each\n * came from, and refuse to start when an integration cannot be served (a pin the\n * resolver cannot satisfy is a startup failure, not a blank widget later).\n */\nasync function resolveExperienceIntegrations(\n ctx: CliContext,\n args: DevArgs,\n projectDir: string,\n): Promise<ExperienceStartup> {\n const env = args.env ?? process.env;\n const resolver = await (args.loadResolver ?? loadHarnessResolver)(projectDir);\n\n const catalog = await (\n args.fetchCatalog ?? (() => tryFetchCatalog(ctx, args, projectDir))\n )();\n writeSessionCatalog(projectDir, catalog);\n\n const contractsDir = args.contractsDir ?? env.EKANOS_CONTRACTS_DIR;\n const resolution = await resolver.resolveIntegrations({\n projectRoot: projectDir,\n env,\n ...(contractsDir ? { contractsDir: path.resolve(contractsDir) } : {}),\n catalog,\n });\n const lines = resolver.formatProvenanceLines(resolution as never);\n for (const line of lines) ctx.log(line);\n for (const notice of resolution.notices) ctx.warn(notice);\n\n if (resolution.errors.length > 0) {\n throw preconditionError(\n `${resolution.errors.length} integration${resolution.errors.length === 1 ? '' : 's'} could not be resolved: ${resolution.errors\n .map((e) => e.message)\n .join(' | ')}`,\n 'Fix the pin in ekanos.json (or run \"ekanos sync\"), or remove the bad override in ekanos.local.json, then re-run \"ekanos dev\".',\n );\n }\n return { lines, overrides: resolution.overrides };\n}\n\n/** The dev's Source catalog when a session exists; null (offline) otherwise. Never throws. */\nasync function tryFetchCatalog(\n ctx: CliContext,\n args: DevArgs,\n projectDir: string,\n): Promise<SourceCatalog | null> {\n try {\n const env = resolveAuthEnvironment(\n ctx,\n undefined,\n args.env ?? process.env,\n {\n projectDir,\n },\n );\n let session = requireSession(env);\n const resolved = await resolveSourceTarget(env, session, {\n source: undefined,\n dir: projectDir,\n });\n session = resolved.session;\n let result = await fetchSourceCatalog(env.host, session.accessToken, {\n source: resolved.source,\n });\n if (result.status === 'unauthorized') {\n session = await refreshStoredSession(env, session);\n result = await fetchSourceCatalog(env.host, session.accessToken, {\n source: resolved.source,\n });\n }\n return result.status === 'ok' ? result.catalog : null;\n } catch {\n ctx.log(\n ctx.ui.dim(\n 'No CLI session: integrations resolve offline (registry integrations fixtures-only, overrides unverified). Run \"ekanos login\" to enable develop-aware live mode.',\n ),\n );\n return null;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"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","sourcesContent":["import { type SourceCatalog } from '@ekanos/integration-schema';\nimport {\n type RepoDiscovery,\n discoverRepo,\n isRepoRoot,\n} from '@ekanos/integration-schema/repo';\nimport { spawn } from 'node:child_process';\nimport * as path from 'node:path';\n\nimport {\n requireSession,\n resolveAuthEnvironment,\n refreshStoredSession,\n} from '../auth/session';\nimport { fetchSourceCatalog } from '../catalog-api';\nimport { assertHarnessCompatible } from '../compatibility';\nimport type { CliContext } from '../context';\nimport {\n type HarnessResolver,\n detectKind,\n loadHarnessResolver,\n readExperienceProject,\n writeSessionCatalog,\n} from '../dev-experience';\nimport { preconditionError, usageError } from '../errors';\nimport {\n BUILD_CACHE_DIR,\n HARNESS_DIR,\n HARNESS_PACKAGE,\n SHELL_REGISTRY_FILENAME,\n assertShellDirIsOurs,\n bootstrapHarnessConfig,\n ensureGitignoreEntry,\n missingDependencies,\n readInstalledHarness,\n scaffoldShell,\n} from '../harness-scaffold';\nimport {\n DUPLICATE_INSTANCE_HINT,\n describeDuplicates,\n scanLockfileInstances,\n} from '../lockfile-instances';\nimport {\n detectPackageManager,\n execArgs,\n formatCommand,\n installCommand,\n} from '../package-manager';\nimport {\n createOutputTail,\n findIgnoredBuilds,\n ignoredBuildsHint,\n} from '../pnpm-builds';\nimport { loadProject } from '../project';\nimport { resolveSourceTarget } from '../source-target';\nimport { displayPath } from '../ui';\nimport { announceUpdate, checkForUpdate } from '../update-notice';\nimport { findWorkspaceRoot } from '../workspace-root';\n\nexport interface DevArgs {\n /** Project directory (contains ekanos.json). Defaults to cwd. */\n dir: string;\n /** Port for the dev server. */\n port?: string;\n /**\n * Interface to bind. Defaults to loopback — see `resolveHost`. Anything\n * else is an explicit, warned-about decision to expose the harness.\n *\n * NOTE: unrelated to the Ekanos HOST the update notice checks against —\n * this is the local bind address for `next dev`, never an Ekanos origin.\n */\n host?: string;\n /** Rewrite every generated file even when its bytes already match. */\n force: boolean;\n /**\n * Explicit `--start` / `--no-start`. Undefined means \"decide from the\n * output mode\": a JSON caller is an agent or a pipe and must not be handed\n * a process that never exits.\n */\n start?: boolean;\n env?: Record<string, string | undefined>;\n /** Experience projects: an offline directory of contracts (`--contracts-dir`). */\n contractsDir?: string;\n /** Test seams. */\n loadResolver?: (projectDir: string) => Promise<HarnessResolver>;\n fetchCatalog?: () => Promise<SourceCatalog | null>;\n}\n\nconst DEFAULT_PORT = 3100;\n\n/**\n * Loopback, NOT Next's default.\n *\n * `next dev` binds 0.0.0.0 unless told otherwise, so the harness would be\n * reachable by anyone on the same network — a coffee-shop Wi-Fi, a shared\n * office VLAN — while we printed \"http://localhost:3100\" and implied\n * otherwise. It renders a partner's integration with their fixtures and, in\n * live mode, whatever their vendor API returns; there is no auth in front of\n * any of it. Binding loopback by default costs a partner nothing and makes\n * exposure a thing they ask for.\n */\nconst DEFAULT_HOST = '127.0.0.1';\n\n/** Addresses that are only reachable from this machine. */\nconst LOOPBACK_HOSTS = new Set(['127.0.0.1', '::1', 'localhost']);\n\n/**\n * Set for the dev server when `--host` binds beyond loopback. The shell's\n * API routes (`@ekanos/harness/api`) refuse non-loopback `Host` headers\n * unless this is `1`: they hold the partner's local OAuth credentials and\n * run handlers on request, so exposing them has to be a decision — this one,\n * made after the warning below — rather than a side effect of the bind.\n */\nconst EXPOSED_ENV = 'EKANOS_HARNESS_EXPOSED';\n\n/** Where the harness generates, and reads, local dev credentials. */\nconst LOCAL_SECRETS_PATH = path.join('.ekanos', 'local-secrets.json');\n\n/**\n * `dev` — scaffold the local harness shell into the partner's project, then\n * run it with their own Next.\n *\n * The shape of this verb follows from one rule: we must be able to ship a\n * harness bugfix as an `@ekanos/harness` version bump that a partner picks up\n * with `pnpm up`, with zero edits to any file they own. So everything under\n * `.ekanos/` is generated, gitignored and rewritten freely, `harness.config.ts`\n * at the project root is written once and never touched again, and all actual\n * harness behaviour lives in the installed package.\n *\n * Two idempotency properties matter and are both tested: a second run produces\n * byte-identical files and rewrites nothing (so Next's watcher stays quiet),\n * and `.gitignore` never grows a duplicate line.\n */\nexport async function runDev(ctx: CliContext, args: DevArgs): Promise<number> {\n // At a repo root one harness serves every package; anywhere else the\n // project is a single integration or experience, exactly as before.\n const repo = isRepoRoot(path.resolve(args.dir))\n ? discoverRepo(path.resolve(args.dir))\n : null;\n const experience =\n repo === null && detectKind(path.resolve(args.dir)) === 'experience';\n const loaded: DevProject = repo\n ? repoProject(repo)\n : experience\n ? experienceProject(path.resolve(args.dir))\n : loadProject(args.dir);\n const port = parsePort(args.port);\n const host = parseHost(args.host);\n const exposed = !LOOPBACK_HOSTS.has(host);\n const pm = detectPackageManager(loaded.projectDir);\n\n const notice = await checkForUpdate({ env: args.env ?? process.env });\n announceUpdate(ctx, notice);\n\n // Fail before writing anything: the shell declares no dependencies of its\n // own, so a missing one would otherwise surface as an opaque Next\n // resolution error minutes later.\n const missing = missingDependencies(loaded.projectDir);\n if (missing.length > 0) {\n throw preconditionError(\n `${missing.length} package${missing.length === 1 ? '' : 's'} the ` +\n `harness needs ${missing.length === 1 ? 'is' : 'are'} not installed ` +\n `in ${loaded.projectDir}: ${missing.join(', ')}.`,\n `Run \"${installCommand(pm, missing)}\" in ${loaded.projectDir}, then ` +\n 're-run \"ekanos dev\".',\n );\n }\n\n warnOnDuplicateInstances(ctx, loaded.projectDir);\n\n const harness = readInstalledHarness(loaded.projectDir);\n const harnessVersion = harness?.version;\n if (!harnessVersion) {\n throw preconditionError(\n `${HARNESS_PACKAGE} is installed but declares no version.`,\n `Reinstall it with \"${installCommand(pm, [HARNESS_PACKAGE])}\" in ` +\n `${loaded.projectDir}, then re-run \"ekanos dev\".`,\n );\n }\n\n // The templates ship with the CLI and the code they import ships with the\n // harness, so a partner can upgrade one without the other. Name that\n // mismatch here rather than letting it surface later as a module-resolution\n // error inside a shell we cheerfully certified as current.\n assertHarnessCompatible({\n harnessVersion,\n harnessManifest: harness?.manifest,\n installHint: (spec) => installCommand(pm, [spec]),\n });\n\n // Validate the shell target BEFORE writing anything at all. Bootstrapping\n // harness.config.ts first and only then discovering that .ekanos/harness is\n // a file or someone else's tree would leave the project half-scaffolded.\n assertShellDirIsOurs(path.join(loaded.projectDir, HARNESS_DIR), args.force);\n\n // An experience has no integration to register, so it gets no\n // project-root registry: the shell carries its own empty one.\n if (repo) {\n for (const problem of repo.problems) {\n ctx.warn(`${problem.where}: ${problem.message}`);\n }\n }\n\n // A repo's integration packages each keep their own harness.config.ts; the\n // repo shell's registry imports them.\n const repoConfigs = repo\n ? repo.packages\n .filter((pkg) => pkg.kind === 'integration')\n .map((pkg) =>\n bootstrapHarnessConfig(pkg.dir, loadProject(pkg.dir).integrations),\n )\n : [];\n const config = repo\n ? {\n bootstrapped: repoConfigs.some((result) => result.bootstrapped),\n configPath: path.join(\n loaded.projectDir,\n HARNESS_DIR,\n SHELL_REGISTRY_FILENAME,\n ),\n }\n : experience\n ? {\n bootstrapped: false,\n configPath: path.join(\n loaded.projectDir,\n HARNESS_DIR,\n SHELL_REGISTRY_FILENAME,\n ),\n }\n : bootstrapHarnessConfig(loaded.projectDir, loaded.integrations);\n // A package inside a workspace resolves `next` and the harness from the\n // workspace root's node_modules (pnpm symlinks them there), so Turbopack's\n // root has to be that root, not the package.\n const turbopackRoot = findWorkspaceRoot(loaded.projectDir);\n if (turbopackRoot !== loaded.projectDir) {\n ctx.log(\n ctx.ui.dim(\n `Workspace package: Turbopack uses the workspace root ${displayPath(turbopackRoot, process.cwd())}.`,\n ),\n );\n }\n const shell = scaffoldShell({\n projectDir: loaded.projectDir,\n turbopackRoot,\n slug: loaded.primary.slug,\n harnessVersion,\n force: args.force,\n sourceGlobs: loaded.project.sourceGlobs,\n ...(experience\n ? { experienceEntry: readExperienceProject(loaded.projectDir).entry }\n : {}),\n ...(repo\n ? {\n repo: {\n integrations: repo.packages\n .filter((pkg) => pkg.kind === 'integration')\n .map((pkg) => ({ name: pkg.name, dir: pkg.relDir })),\n experiences: repo.packages\n .filter((pkg) => pkg.kind === 'experience')\n .map((pkg) => ({\n name: pkg.name,\n dir: pkg.relDir,\n entry: readExperienceProject(pkg.dir).entry,\n })),\n },\n }\n : {}),\n });\n const gitignoreUpdated = ensureGitignoreEntry(loaded.projectDir);\n\n if (shell.stale) {\n ctx.log(\n `Regenerating ${HARNESS_DIR} — ${shell.staleReasons.join('; ')}. ` +\n `Nothing you own changed; ${config.configPath} is untouched.`,\n );\n }\n if (shell.buildCacheCleared) {\n ctx.log(\n ` removed ${HARNESS_DIR}/${BUILD_CACHE_DIR} (Next's cache from the previous shell)`,\n );\n }\n\n if (config.bootstrapped) {\n ctx.log(` created harness.config.ts (yours — edit it, we never will)`);\n }\n for (const file of shell.created) ctx.log(` created ${HARNESS_DIR}/${file}`);\n for (const file of shell.updated) ctx.log(` updated ${HARNESS_DIR}/${file}`);\n if (gitignoreUpdated) ctx.log(' updated .gitignore (.ekanos/)');\n ctx.log(\n ` live-mode OAuth: the harness generates ${LOCAL_SECRETS_PATH} on first ` +\n 'use — fill it in and follow \"Local OAuth\" on the Activation surface.',\n );\n\n let integrations: ExperienceStartup | null = null;\n if (repo) {\n // Each experience package resolves its own integrations through the repo\n // server; the session catalog is shared from the repo root.\n writeSessionCatalog(\n loaded.projectDir,\n await tryFetchCatalog(ctx, args, loaded.projectDir),\n );\n for (const pkg of repo.packages) {\n ctx.log(` ${pkg.kind} ${pkg.name} v${pkg.version} (${pkg.relDir})`);\n }\n } else if (experience) {\n integrations = await resolveExperienceIntegrations(\n ctx,\n args,\n loaded.projectDir,\n );\n }\n\n // `--hostname` is passed ALWAYS, never left to Next's default, so the URL\n // we print is the URL that is actually served.\n const serverArgs = ['dev', '--port', String(port), '--hostname', host];\n const serverEnv: Record<string, string> = exposed\n ? { [EXPOSED_ENV]: '1' }\n : {};\n const command =\n (exposed ? `${EXPOSED_ENV}=1 ` : '') +\n formatCommand(pm.bin, execArgs(pm, 'next', serverArgs));\n const url = `http://${displayHost(host)}:${port}`;\n\n const scaffold = {\n kind: repo ? 'repo' : experience ? 'experience' : 'integration',\n ...(repo\n ? {\n packages: repo.packages.map((pkg) => ({\n name: pkg.name,\n kind: pkg.kind,\n dir: pkg.relDir,\n })),\n }\n : {}),\n ...(integrations\n ? {\n overrides: integrations.overrides,\n publishBlocked: integrations.overrides.length > 0,\n }\n : {}),\n slug: loaded.primary.slug,\n // An experience lists the integrations it depends on (provenance lines);\n // an integration project lists its own slugs.\n integrations: integrations\n ? integrations.lines\n : repo\n ? repo.packages\n .filter((p) => p.kind === 'integration')\n .map((p) => p.name)\n : loaded.integrations.map((i) => i.slug),\n projectDir: loaded.projectDir,\n turbopackRoot,\n harnessDir: shell.harnessDir,\n harnessVersion,\n previousVersion: shell.previousVersion,\n previousMarker: shell.previousMarker,\n stale: shell.stale,\n staleReasons: shell.staleReasons,\n buildCacheCleared: shell.buildCacheCleared,\n sourceGlobs: loaded.project.sourceGlobs ?? [],\n created: shell.created,\n updated: shell.updated,\n unchanged: shell.unchanged,\n configBootstrapped: config.bootstrapped,\n configPath: config.configPath,\n gitignoreUpdated,\n ...(notice ? { toolchain: notice } : {}),\n };\n\n if (exposed) {\n ctx.warn(\n `WARNING: --host ${host} exposes the harness beyond this machine. It ` +\n 'has no authentication, and it renders your fixtures and — in live ' +\n 'mode — real responses from your vendor API. Its API routes hold the ' +\n `client secret from ${LOCAL_SECRETS_PATH}, the tokens onTokens stored, ` +\n 'and run your handlers on request; they refuse non-loopback callers ' +\n `unless ${EXPOSED_ENV}=1, which this sets. Anyone who can reach ` +\n `${url} can read and run all of it. Omit --host to bind ${DEFAULT_HOST}.`,\n );\n }\n\n // A JSON caller is an agent or a pipe. Handing it a dev server that never\n // exits would hang its tool call forever and it would never see the\n // envelope, so JSON mode scaffolds and reports the command instead of\n // running it. `--start` overrides; `--no-start` opts out in a terminal.\n const shouldStart = args.start ?? !ctx.jsonMode;\n if (!shouldStart) {\n const reason = args.start === false ? 'no-start' : 'non-interactive';\n const note =\n reason === 'non-interactive'\n ? `Scaffolded only: the server was NOT started because this run is non-interactive (JSON output, a pipe, or an agent). Pass --start to run it, or run: ${command}`\n : `Scaffolded only (--no-start). Run: ${command}`;\n ctx.log(note);\n return ctx.succeed(\n {\n ...scaffold,\n server: {\n started: false,\n reason,\n note,\n command,\n url,\n port,\n host,\n exposed,\n },\n },\n ctx.ui.result({\n title: 'Harness ready',\n rows: [\n ['Directory', displayPath(shell.harnessDir, process.cwd())],\n ['URL', url],\n ['Started', 'no (scaffold only)'],\n ['Start', command],\n ],\n }),\n );\n }\n\n ctx.log(ctx.ui.dim(`Starting the harness on ${url} (${command})…`));\n const tail = createOutputTail();\n const exitCode = await spawnServer({\n ctx,\n tail,\n bin: pm.bin,\n argv: execArgs(pm, 'next', serverArgs),\n cwd: shell.harnessDir,\n env: serverEnv,\n });\n\n const data = {\n ...scaffold,\n server: { started: true, command, url, port, host, exposed, exitCode },\n };\n\n if (exitCode === 0) {\n return ctx.succeed(\n data,\n ctx.ui.result({ title: 'Harness stopped', rows: [['URL', url]] }),\n );\n }\n\n const ignoredBuilds = findIgnoredBuilds(tail.text());\n\n return ctx.failWith({\n code: 'dev_server_failed',\n message: `\"${command}\" exited with code ${exitCode}.`,\n hint:\n ignoredBuilds.length > 0\n ? ignoredBuildsHint(ignoredBuilds)\n : 'Read the Next output on stderr. If it cannot resolve @ekanos/harness ' +\n `or next, reinstall dependencies in ${loaded.projectDir}; if a route ` +\n `fails to compile, delete ${shell.harnessDir} and re-run \"ekanos dev\".`,\n // Transparent passthrough of Next's own exit code.\n exitCode,\n data,\n });\n}\n\n/**\n * Warn — never fail — when the lockfile resolves `@ekanos/sdk` or `@ekanos/ui`\n * more than once: the harness would mount its providers from one copy and the\n * project's hooks would read the other's, which throws at render time with a\n * message that points nowhere near the lockfile.\n */\nfunction warnOnDuplicateInstances(ctx: CliContext, projectDir: string): void {\n const scan = scanLockfileInstances(projectDir);\n if (scan.status === 'unreadable') {\n ctx.log(\n ctx.ui.dim(\n `Could not check ${scan.lockfile} for duplicate @ekanos/sdk copies: ${scan.reason}`,\n ),\n );\n return;\n }\n if (scan.status !== 'ok') return;\n const lines = describeDuplicates(scan.duplicates);\n if (lines.length === 0) return;\n\n ctx.warn(\n `WARNING: ${lines.join('; ')} (${scan.lockfile}). The harness and your ` +\n 'code may load different copies, and a provider from one is invisible ' +\n `to hooks from the other. ${DUPLICATE_INSTANCE_HINT}`,\n );\n}\n\nfunction spawnServer(params: {\n ctx: CliContext;\n tail: ReturnType<typeof createOutputTail>;\n bin: string;\n argv: string[];\n cwd: string;\n env: Record<string, string>;\n}): Promise<number> {\n return new Promise<number>((resolve, reject) => {\n const child = spawn(params.bin, params.argv, {\n cwd: params.cwd,\n env: { ...process.env, ...params.env },\n // stdin inherited so Next's own key handling works; stdout/stderr piped\n // so we can route them and keep OUR stdout reserved for the envelope.\n stdio: ['inherit', 'pipe', 'pipe'],\n });\n\n child.stdout?.on('data', (chunk: Buffer) => {\n params.tail.push(chunk);\n (params.ctx.jsonMode ? process.stderr : process.stdout).write(chunk);\n });\n child.stderr?.on('data', (chunk: Buffer) => {\n params.tail.push(chunk);\n process.stderr.write(chunk);\n });\n\n child.on('error', (error) => reject(error));\n child.on('close', (code) => resolve(code ?? 1));\n });\n}\n\n/**\n * The hostname to show a human. `127.0.0.1` is spelled `localhost` because\n * that is what people type; a wildcard bind is spelled `localhost` too, but\n * only after `exposed` has already been warned about — printing `0.0.0.0` as\n * a URL is not useful.\n */\nfunction displayHost(host: string): string {\n if (host === '127.0.0.1' || host === '0.0.0.0' || host === '::') {\n return 'localhost';\n }\n if (host === '::1') return '[::1]';\n return host;\n}\n\nfunction parseHost(raw: string | undefined): string {\n if (raw === undefined) return DEFAULT_HOST;\n\n const host = raw.trim();\n if (host.length === 0) {\n throw usageError(\n 'Invalid --host \"\".',\n `Pass an interface to bind, e.g. \"--host 0.0.0.0\" to expose the ` +\n `harness on your network, or omit it to bind ${DEFAULT_HOST}.`,\n );\n }\n return host;\n}\n\nfunction parsePort(raw: string | undefined): number {\n if (raw === undefined) return DEFAULT_PORT;\n\n const port = Number(raw);\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw usageError(\n `Invalid --port \"${raw}\".`,\n 'Pass an integer between 1 and 65535, e.g. \"--port 3100\".',\n );\n }\n return port;\n}\n\ninterface DevProject {\n projectDir: string;\n integrations: Array<{ slug: string; entry: string }>;\n primary: { slug: string };\n project: { sourceGlobs?: string[] | undefined };\n}\n\nfunction experienceProject(projectDir: string): DevProject {\n const { slug } = readExperienceProject(projectDir);\n return {\n projectDir,\n // An experience registers no integration of its own with the harness; its\n // integrations come from ekanos.json through /__ekanos/api.\n integrations: [],\n primary: { slug },\n project: {},\n };\n}\n\nfunction repoProject(repo: RepoDiscovery): DevProject {\n return {\n projectDir: repo.root,\n integrations: [],\n primary: { slug: path.basename(repo.root) },\n // The shell's stylesheet scans integrations/ already; experiences/ is the\n // other half of a repo.\n project: { sourceGlobs: ['experiences/**/*.{ts,tsx}'] },\n };\n}\n\ninterface ExperienceStartup {\n lines: string[];\n overrides: Array<{ integration: string; path: string; via: 'file' | 'env' }>;\n}\n\n/**\n * Resolve every integration with the harness the project installed, print where each\n * came from, and refuse to start when an integration cannot be served (a pin the\n * resolver cannot satisfy is a startup failure, not a blank widget later).\n */\nasync function resolveExperienceIntegrations(\n ctx: CliContext,\n args: DevArgs,\n projectDir: string,\n): Promise<ExperienceStartup> {\n const env = args.env ?? process.env;\n const resolver = await (args.loadResolver ?? loadHarnessResolver)(projectDir);\n\n const catalog = await (\n args.fetchCatalog ?? (() => tryFetchCatalog(ctx, args, projectDir))\n )();\n writeSessionCatalog(projectDir, catalog);\n\n const contractsDir = args.contractsDir ?? env.EKANOS_CONTRACTS_DIR;\n const resolution = await resolver.resolveIntegrations({\n projectRoot: projectDir,\n env,\n ...(contractsDir ? { contractsDir: path.resolve(contractsDir) } : {}),\n catalog,\n });\n const lines = resolver.formatProvenanceLines(resolution as never);\n for (const line of lines) ctx.log(line);\n for (const notice of resolution.notices) ctx.warn(notice);\n\n if (resolution.errors.length > 0) {\n throw preconditionError(\n `${resolution.errors.length} integration${resolution.errors.length === 1 ? '' : 's'} could not be resolved: ${resolution.errors\n .map((e) => e.message)\n .join(' | ')}`,\n 'Fix the pin in ekanos.json (or run \"ekanos sync\"), or remove the bad override in ekanos.local.json, then re-run \"ekanos dev\".',\n );\n }\n return { lines, overrides: resolution.overrides };\n}\n\n/** The dev's Source catalog when a session exists; null (offline) otherwise. Never throws. */\nasync function tryFetchCatalog(\n ctx: CliContext,\n args: DevArgs,\n projectDir: string,\n): Promise<SourceCatalog | null> {\n try {\n const env = resolveAuthEnvironment(\n ctx,\n undefined,\n args.env ?? process.env,\n {\n projectDir,\n },\n );\n let session = requireSession(env);\n const resolved = await resolveSourceTarget(env, session, {\n source: undefined,\n dir: projectDir,\n });\n session = resolved.session;\n let result = await fetchSourceCatalog(env.host, session.accessToken, {\n source: resolved.source,\n });\n if (result.status === 'unauthorized') {\n session = await refreshStoredSession(env, session);\n result = await fetchSourceCatalog(env.host, session.accessToken, {\n source: resolved.source,\n });\n }\n return result.status === 'ok' ? result.catalog : null;\n } catch {\n ctx.log(\n ctx.ui.dim(\n 'No CLI session: integrations resolve offline (registry integrations fixtures-only, overrides unverified). Run \"ekanos login\" to enable develop-aware live mode.',\n ),\n );\n return null;\n }\n}\n"]}
|
|
@@ -48,6 +48,12 @@ export interface PublishArgs {
|
|
|
48
48
|
packages?: readonly string[];
|
|
49
49
|
/** Repo only: publish every package. */
|
|
50
50
|
all?: boolean;
|
|
51
|
+
/** Integration only: after submitting, wait for the gate verdict. */
|
|
52
|
+
wait?: boolean;
|
|
53
|
+
/** `--wait`: minutes to wait for the verdict (default 30). */
|
|
54
|
+
timeoutMinutes?: number;
|
|
55
|
+
/** Injectable for tests: the wait between polls. */
|
|
56
|
+
sleep?: (ms: number) => Promise<void>;
|
|
51
57
|
}
|
|
52
58
|
/** Where the resolved source slug came from — governs the confirmation rules below. */
|
|
53
59
|
export interface SourceResolution {
|
package/dist/commands/publish.js
CHANGED
|
@@ -17,6 +17,7 @@ import { stillUnauthorizedSourceSeats } from '../sources-api.js';
|
|
|
17
17
|
import { shortHost } from '../ui.js';
|
|
18
18
|
import { announceUpdate, checkForUpdate } from '../update-notice.js';
|
|
19
19
|
import { collectAllFindings } from '../validate-findings.js';
|
|
20
|
+
import { DEFAULT_WAIT_MINUTES, failWatchTimeout, waitForGate, watchOutcomeData, } from './status.js';
|
|
20
21
|
/**
|
|
21
22
|
* Checks that are WARN in plain `ekanos validate` but must refuse a
|
|
22
23
|
* `publish` outright: a project that will fail the gate is not allowed to
|
|
@@ -57,7 +58,7 @@ export function escalateForPublish(findings) {
|
|
|
57
58
|
*/
|
|
58
59
|
export async function runPublish(ctx, args) {
|
|
59
60
|
var _a;
|
|
60
|
-
var _b, _c;
|
|
61
|
+
var _b, _c, _d, _e, _f;
|
|
61
62
|
// Inside a repo, `publish` plans the packages: a same-repo integration is
|
|
62
63
|
// ordered first rather than refused as an override.
|
|
63
64
|
const repoRoot = findRepoRoot(path.resolve(args.dir));
|
|
@@ -87,8 +88,42 @@ export async function runPublish(ctx, args) {
|
|
|
87
88
|
confirm: args.confirm,
|
|
88
89
|
});
|
|
89
90
|
}
|
|
91
|
+
if (args.dryRun)
|
|
92
|
+
return runIntegrationDryRun(ctx, args);
|
|
90
93
|
const prepared = await prepareIntegrationSubmission(ctx, args);
|
|
91
94
|
const { loaded, version, slug } = prepared;
|
|
95
|
+
const gate = await refuseOnFindings(ctx, loaded, slug, version);
|
|
96
|
+
if (gate.exitCode !== null)
|
|
97
|
+
return gate.exitCode;
|
|
98
|
+
const submitted = await submitPrepared(ctx, args, prepared);
|
|
99
|
+
if (!args.wait)
|
|
100
|
+
return ctx.succeed(submitted.data, submitted.human);
|
|
101
|
+
const submittedSource = submitted.data.source.slug;
|
|
102
|
+
const waited = await waitForGate(ctx, prepared.env, {
|
|
103
|
+
slug,
|
|
104
|
+
source: submittedSource,
|
|
105
|
+
version,
|
|
106
|
+
timeoutMinutes: (_d = args.timeoutMinutes) !== null && _d !== void 0 ? _d : DEFAULT_WAIT_MINUTES,
|
|
107
|
+
sleep: (_e = args.sleep) !== null && _e !== void 0 ? _e : ((ms) => new Promise((resolve) => {
|
|
108
|
+
setTimeout(resolve, ms);
|
|
109
|
+
})),
|
|
110
|
+
});
|
|
111
|
+
if (waited.timedOut)
|
|
112
|
+
return failWatchTimeout(ctx, slug, version, waited);
|
|
113
|
+
const gateData = watchOutcomeData(slug, waited.version);
|
|
114
|
+
if (waited.version.state === 'rejected') {
|
|
115
|
+
return ctx.fail(gateFailedError(`${slug}@${version} was submitted but rejected by the gate ` +
|
|
116
|
+
`(${(_f = gateData.errorCount) !== null && _f !== void 0 ? _f : 0} error${gateData.errorCount === 1 ? '' : 's'}).`, 'Resolve the error-severity findings in data.gate.findings, bump the ' +
|
|
117
|
+
'version (a submitted version cannot be changed), and re-run "ekanos publish".'), Object.assign(Object.assign({}, submitted.data), { gate: gateData }));
|
|
118
|
+
}
|
|
119
|
+
return ctx.succeed(Object.assign(Object.assign({}, submitted.data), { state: waited.version.state, gate: gateData }), `${submitted.human}\n${ctx.ui.ok(`${ctx.ui.glyphs.ok} gate verdict: ${waited.version.state}`)}`);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* The local gate every publish shares: the full findings pass, refusing with
|
|
123
|
+
* GATE_FAILED when any finding is an error. Returns the exit code when it
|
|
124
|
+
* refused, `null` when the project may go on.
|
|
125
|
+
*/
|
|
126
|
+
async function refuseOnFindings(ctx, loaded, slug, version) {
|
|
92
127
|
ctx.log(`Validating ${slug} before publishing…`);
|
|
93
128
|
const findings = escalateForPublish(await collectAllFindings(loaded));
|
|
94
129
|
const errorCount = findings.filter((f) => f.severity === 'error').length;
|
|
@@ -112,13 +147,54 @@ export async function runPublish(ctx, args) {
|
|
|
112
147
|
if (!ctx.jsonMode) {
|
|
113
148
|
ctx.log(ctx.ui.nextAction('ekanos validate', 'fix the error-severity findings above, then re-run "ekanos publish"'));
|
|
114
149
|
}
|
|
115
|
-
return exitCode;
|
|
150
|
+
return { exitCode, packWarnings: [] };
|
|
116
151
|
}
|
|
117
152
|
if (!ctx.jsonMode) {
|
|
118
153
|
ctx.log(ctx.ui.ok(`${ctx.ui.glyphs.ok} validated ${slug} — no error-severity findings.`));
|
|
119
154
|
}
|
|
120
|
-
|
|
121
|
-
|
|
155
|
+
// What is about to be packed is the one thing a version cannot take back.
|
|
156
|
+
const packWarnings = findings.filter((f) => f.check.startsWith('pack.'));
|
|
157
|
+
if (packWarnings.length > 0 && !ctx.jsonMode) {
|
|
158
|
+
renderFindings(ctx, packWarnings, { cwd: loaded.projectDir });
|
|
159
|
+
}
|
|
160
|
+
return { exitCode: null, packWarnings };
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* `publish --dry-run` for one integration: the same findings gate and the same
|
|
164
|
+
* pack a real publish runs, with nothing sent. It needs no login and no
|
|
165
|
+
* source, so it is what a CI job or a first look runs before the real one.
|
|
166
|
+
*/
|
|
167
|
+
async function runIntegrationDryRun(ctx, args) {
|
|
168
|
+
const loaded = loadProject(args.dir);
|
|
169
|
+
const skew = assertSchemaNotSkewed(ctx, loaded.projectDir);
|
|
170
|
+
const version = readProjectVersion(loaded.projectDir);
|
|
171
|
+
const slug = loaded.primary.slug;
|
|
172
|
+
const gate = await refuseOnFindings(ctx, loaded, slug, version);
|
|
173
|
+
if (gate.exitCode !== null)
|
|
174
|
+
return gate.exitCode;
|
|
175
|
+
ctx.log(`Packing ${slug}@${version}…`);
|
|
176
|
+
const packed = packProject(loaded.projectDir);
|
|
177
|
+
buildManifest(loaded, packed.files);
|
|
178
|
+
return ctx.succeed(Object.assign({ dryRun: true, slug,
|
|
179
|
+
version, files: packed.files, archiveBytes: packed.archive.length, warnings: gate.packWarnings }, (skew.status === 'project-older'
|
|
180
|
+
? {
|
|
181
|
+
schemaSkew: {
|
|
182
|
+
status: skew.status,
|
|
183
|
+
cliSchemaVersion: skew.cliSchemaVersion,
|
|
184
|
+
projectSchemaVersion: skew.projectSchemaVersion,
|
|
185
|
+
},
|
|
186
|
+
}
|
|
187
|
+
: {})), ctx.ui.result({
|
|
188
|
+
title: 'Dry run: nothing submitted',
|
|
189
|
+
rows: [
|
|
190
|
+
['Integration', `${slug}@${version}`],
|
|
191
|
+
['Files', String(packed.files.length)],
|
|
192
|
+
['Archive', `${packed.archive.length} bytes`],
|
|
193
|
+
],
|
|
194
|
+
notes: [
|
|
195
|
+
'A submitted version is immutable: a mistake means a version bump. Run "ekanos publish" to submit.',
|
|
196
|
+
],
|
|
197
|
+
}));
|
|
122
198
|
}
|
|
123
199
|
/**
|
|
124
200
|
* Confirm the target, pack and submit one gated integration. The caller has
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../../src/commands/publish.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAGlC,OAAO,EAEL,oBAAoB,EACpB,cAAc,EACd,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,QAAQ,EACR,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,UAAU,EACV,eAAe,GAChB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAmB,UAAU,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAsB,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,iBAAiB,EACjB,aAAa,GACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,EAAmB,4BAA4B,EAAE,MAAM,gBAAgB,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D;;;;;;;;;;;GAWG;AACH,MAAM,yBAAyB,GAAsB;IACnD,6BAA6B;CAC9B,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAmB;IACpD,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAC9B,OAAO,CAAC,QAAQ,KAAK,MAAM;QAC3B,yBAAyB,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC;QAC/C,CAAC,iCAAM,OAAO,KAAE,QAAQ,EAAE,OAAO,IACjC,CAAC,CAAC,OAAO,CACZ,CAAC;AACJ,CAAC;AA6CD;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,GAAe,EACf,IAAiB;;;IAEjB,0EAA0E;IAC1E,oDAAoD;IACpD,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACtD,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,cAAc,CAAC,GAAG,EAAE;YACzB,QAAQ;YACR,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC;YAC3B,KAAK,QAAE,IAAI,CAAC,QAAQ,mCAAI,EAAE;YAC1B,GAAG,EAAE,IAAI,CAAC,GAAG,KAAK,IAAI;YACtB,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;IACL,CAAC;IACD,IAAI,OAAC,MAAA,IAAI,CAAC,QAAQ,0CAAE,MAAM,mCAAI,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QACjD,MAAM,UAAU,CACd,yCAAyC,EACzC,kGAAkG,CACnG,CAAC;IACJ,CAAC;IAED,0EAA0E;IAC1E,4DAA4D;IAC5D,IAAI,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,YAAY,EAAE,CAAC;QAC7D,OAAO,oBAAoB,CAAC,GAAG,EAAE;YAC/B,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,MAAM,EAAE,IAAI,CAAC,MAAM,KAAK,IAAI;YAC5B,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,4BAA4B,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC/D,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC;IAE3C,GAAG,CAAC,GAAG,CAAC,cAAc,IAAI,qBAAqB,CAAC,CAAC;IAEjD,MAAM,QAAQ,GAAG,kBAAkB,CAAC,MAAM,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC;IACtE,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,MAAM,CAAC;IAEzE,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QACnB,sEAAsE;QACtE,sEAAsE;QACtE,sEAAsE;QACtE,qEAAqE;QACrE,4CAA4C;QAC5C,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;YAClB,GAAG,CAAC,GAAG,CACL,GAAG,CAAC,EAAE,CAAC,GAAG,CACR,GAAG,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,yBAAyB,UAAU,UAAU;gBAC/D,GAAG,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CACpC,CACF,CAAC;YACF,cAAc,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,CACvB,eAAe,CACb,wBAAwB,UAAU,qBAAqB;YACrD,GAAG,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,EACnC,iEAAiE;YAC/D,uDAAuD;YACvD,mBAAmB,CACtB,EACD,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,EAC3B,CAAC,GAAG,CAAC,QAAQ;YACX,CAAC,CAAC,EAAE,eAAe,EAAE,EAAE,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,EAAE;YAChE,CAAC,CAAC,SAAS,CACd,CAAC;QAEF,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;YAClB,GAAG,CAAC,GAAG,CACL,GAAG,CAAC,EAAE,CAAC,UAAU,CACf,iBAAiB,EACjB,qEAAqE,CACtE,CACF,CAAC;QACJ,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAClB,GAAG,CAAC,GAAG,CACL,GAAG,CAAC,EAAE,CAAC,EAAE,CACP,GAAG,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,cAAc,IAAI,gCAAgC,CACtE,CACF,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IAE5D,OAAO,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC;AACtD,CAAC;AAOD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,GAAe,EACf,IAAiB,EACjB,QAA4B;;;IAE5B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,QAAQ,CAAC;IAE1E,uEAAuE;IACvE,yEAAyE;IACzE,wEAAwE;IACxE,2EAA2E;IAC3E,yBAAyB;IACzB,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,CAAC,OAAO,EAAE;QACvE,MAAM,EAAE,UAAU,CAAC,MAAM;QACzB,QAAQ,EAAE,UAAU,CAAC,QAAQ;QAC7B,IAAI;QACJ,OAAO;QACP,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,UAAU,QAAE,IAAI,CAAC,UAAU,mCAAI,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI;QAC3D,OAAO,QAAE,IAAI,CAAC,OAAO,mCAAI,WAAW;KACrC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC;IACxC,MAAM,YAAY,GAAG,MAAA,MAAM,CAAC,OAAO,CAAC,YAAY,0CAAE,IAAI,CAAC;IAEvD,uEAAuE;IACvE,mCAAmC;IACnC,MAAM,MAAM,GAAG,MAAM,aAAa,CAChC,GAAG,EACH,GAAG,EACH,QAAQ,CAAC,OAAO,EAChB,MAAM,EACN,IAAI,EACJ,YAAY,CACb,CAAC;IAEF,GAAG,CAAC,GAAG,CAAC,WAAW,IAAI,IAAI,OAAO,GAAG,CAAC,CAAC;IAEvC,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAErD,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAClB,GAAG,CAAC,GAAG,CACL,GAAG,CAAC,EAAE,CAAC,EAAE,CACP,GAAG,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,IAAI,IAAI,OAAO,KAAK,MAAM,CAAC,KAAK,CAAC,MAAM,UAAU,CAChF,CACF,CAAC;IACJ,CAAC;IAED,GAAG,CAAC,GAAG,CAAC,iBAAiB,GAAG,CAAC,IAAI,aAAa,MAAM,KAAK,CAAC,CAAC;IAE3D,MAAM,OAAO,GAAG,MAAM,oBAAoB,CAAC,GAAG,EAAE,QAAQ,CAAC,OAAO,kBAC9D,MAAM;QACN,IAAI;QACJ,OAAO;QACP,QAAQ,EACR,OAAO,EAAE,MAAM,CAAC,OAAO,IACpB,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EACzC,CAAC;IAEH,MAAM,WAAW,eACf,OAAO,CAAC,WAAW,mCAAI,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,WAAW,mCAAI,OAAO,CAAC,IAAI,CAAC;IAE7D,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAClB,GAAG,CAAC,GAAG,CACL,GAAG,CAAC,EAAE,CAAC,EAAE,CACP,GAAG,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,cAAc,WAAW,IAAI,OAAO,CAAC,OAAO,GAAG;YAChE,WAAW,OAAO,CAAC,KAAK,KAAK,CAChC,CACF,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IAEjE,MAAM,aAAa,GAAG;QACpB,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,cAAc,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACtD,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;KACrD,CAAC;IAEF,OAAO;QACL,IAAI,gCACF,IAAI,EAAE,GAAG,CAAC,IAAI,EACd,MAAM,EAAE;gBACN,EAAE,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE;gBAC1B,IAAI,EAAE,QAAQ,CAAC,UAAU,CAAC,IAAI;gBAC9B,IAAI,EAAE,QAAQ,CAAC,UAAU,CAAC,IAAI;aAC/B,EACD,IAAI,EAAE,OAAO,CAAC,IAAI,EAClB,SAAS,cAAE,OAAO,CAAC,SAAS,mCAAI,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,SAAS,mCAAI,IAAI,EACzD,WAAW,EACX,OAAO,EAAE,OAAO,CAAC,OAAO,EACxB,YAAY,EAAE,OAAO,CAAC,YAAY,EAClC,KAAK,EAAE,OAAO,CAAC,KAAK,EACpB,aAAa,EAAE,OAAO,CAAC,aAAa,EACpC,KAAK,EAAE,MAAM,CAAC,KAAK,EACnB,eAAe,EAAE,SAAS,CAAC,MAAM,EACjC,aAAa,EAAE,SAAS,CAAC,IAAI,EAC7B,YAAY,EAAE,SAAS,CAAC,YAAY,IACjC,CAAC,IAAI,CAAC,MAAM,KAAK,eAAe;YACjC,CAAC,CAAC;gBACE,UAAU,EAAE;oBACV,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;oBACvC,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;iBAChD;aACF;YACH,CAAC,CAAC,EAAE,CAAC,GACJ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CACzC;QACD,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC;YACnB,KAAK,EAAE,WAAW;YAClB,IAAI,EAAE;gBACJ,CAAC,aAAa,EAAE,GAAG,WAAW,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBACpD,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC;gBACxB,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAClB,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAC7B,GAAG,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC;oBAC1B,CAAC,CAAC;wBACE;4BACE,OAAO;4BACP,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,iBAAiB;yBACvC;qBACX;oBACH,CAAC,CAAC,EAAE,CAAC;aACR;YACD,KAAK,EAAE,SAAS,CAAC,YAAY;gBAC3B,CAAC,CAAC;oBACE,wBAAwB,GAAG,CAAC,IAAI,kCAAkC;wBAChE,IAAI,SAAS,CAAC,YAAY,wCAAwC;wBAClE,gDAAgD;iBACnD;gBACH,CAAC,CAAC,EAAE;SACP,CAAC;KACH,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,aAAa,CAC1B,GAAe,EACf,GAAoB,EACpB,OAAsB,EACtB,MAAc,EACd,IAAY,EACZ,YAAiD;IAEjD,IAAI,MAAM,GAAsB,IAAI,CAAC;IAErC,IAAI,CAAC;QACH,IAAI,MAAM,GAAG,MAAM,UAAU,CAC3B,GAAG,CAAC,IAAI,EACR,OAAO,CAAC,WAAW,EACnB,MAAM,EACN,IAAI,EACJ,YAAY,CACb,CAAC;QACF,IAAI,MAAM,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;YACrC,MAAM,SAAS,GAAG,MAAM,oBAAoB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YAC3D,MAAM,GAAG,MAAM,UAAU,CACvB,GAAG,CAAC,IAAI,EACR,SAAS,CAAC,WAAW,EACrB,MAAM,EACN,IAAI,EACJ,YAAY,CACb,CAAC;QACJ,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI;YAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IACrD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,CAAC,KAAK,YAAY,QAAQ,CAAC;YAAE,MAAM,KAAK,CAAC;QAC9C,GAAG,CAAC,GAAG,CACL,mCAAmC,IAAI,KAAK,KAAK,CAAC,OAAO,gBAAgB,CAC1E,CAAC;IACJ,CAAC;IAED,IAAI,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,MAAM,MAAK,mBAAmB,EAAE,CAAC;QAC3C,MAAM,yBAAyB,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;IAED,IAAI,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,WAAW,KAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QACzC,GAAG,CAAC,GAAG,CAAC,iBAAiB,MAAM,CAAC,WAAW,GAAG,CAAC,CAAC;IAClD,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAaD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,GAAe,EACf,IAAiB;IAEjB,MAAM,GAAG,GAAG,sBAAsB,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE;QAC3D,UAAU,EAAE,IAAI,CAAC,GAAG;KACrB,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IAEpC,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAErC,wEAAwE;IACxE,0EAA0E;IAC1E,uEAAuE;IACvE,2EAA2E;IAC3E,MAAM,IAAI,GAAG,qBAAqB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IAE3D,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC;QAClC,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,OAAO;KACR,CAAC,CAAC;IACH,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAE5B,uEAAuE;IACvE,4EAA4E;IAC5E,2EAA2E;IAC3E,0DAA0D;IAC1D,IAAI,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,MAAM,MAAK,aAAa,EAAE,CAAC;QACrC,MAAM,iBAAiB,CACrB,eAAe,MAAM,CAAC,OAAO,CAAC,GAAG,aAAa,GAAG,CAAC,IAAI,aAAa;YACjE,qCAAqC,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI,EAC5D,qEAAqE;YACnE,gDAAgD,CACnD,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9E,MAAM,OAAO,GAAG,kBAAkB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACtD,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;IAEjC,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3E,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,GAAe,EACf,GAAoB,EACpB,OAAsB,EACtB,IAOC;;IAED,MAAM,MAAM,GAAG,MAAM,wBAAwB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAE5D,IAAI,MAAM,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;QACrC,4BAA4B,CAAC,GAAG,CAAC,CAAC;IACpC,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC;IAEhE,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,cAAc,CAClB,gDAAgD,IAAI,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAI,GAAG,EAC9E,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,CACpC,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;IACvD,CAAC;IAED,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,GAAG,CAAC,GAAG,CACL,iBAAiB,MAAA,IAAI,CAAC,IAAI,mCAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,gBAAgB;YACnE,iBAAiB,CACpB,CAAC;QACF,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;IACvD,CAAC;IAED,uDAAuD;IACvD,EAAE;IACF,sEAAsE;IACtE,qEAAqE;IACrE,0EAA0E;IAC1E,uEAAuE;IACvE,0EAA0E;IAC1E,yEAAyE;IACzE,uEAAuE;IACvE,2EAA2E;IAC3E,0EAA0E;IAC1E,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC;IAEnD,IAAI,SAAS,EAAE,CAAC;QACd,GAAG,CAAC,GAAG,CACL,cAAc,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,cAAc,MAAA,IAAI,CAAC,IAAI,mCAAI,IAAI,CAAC,IAAI,GAAG;YAC5E,IAAI,IAAI,CAAC,IAAI,QAAQ,GAAG,CAAC,IAAI,EAAE,CAClC,CAAC;QAEF,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACd,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;YAEvD,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,eAAe,CACnB,eAAe,IAAI,CAAC,IAAI,sBAAsB,EAC9C,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAC9B,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;IACvD,CAAC;IAED,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;IACvD,CAAC;IAED,MAAM,eAAe,CACnB,gDAAgD,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG;QACtE,oEAAoE;QACpE,mBAAmB,EACrB,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAC9B,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,OAAqB,EAAE,IAAY;IACpD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CACL,sCAAsC,IAAI,eAAe;YACzD,kEAAkE,CACnE,CAAC;IACJ,CAAC;IAED,OAAO,CACL,uBAAuB,aAAa,CAAC,OAAO,CAAC,2BAA2B;QACxE,uEAAuE;QACvE,UAAU,CACX,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,OAAqB;IAC1C,OAAO,CACL,sBAAsB,aAAa,CAAC,OAAO,CAAC,2BAA2B;QACvE,mEAAmE;QACnE,uEAAuE;QACvE,kCAAkC,CACnC,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,OAAqB;IAC1C,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC5E,CAAC;AAED;;;;;;GAMG;AACH;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAgB;IAChD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC;IACxD,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;QAClC,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,GAAG,QAAQ,GAAG,CAAC,CAAC;QACjD,OAAO,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,GAA8C,EAC9C,OAAsB,EACtB,OAA4C;IAE5C,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAE1E,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC,OAAO,CAAC;IAEhD,uEAAuE;IACvE,gEAAgE;IAChE,MAAM,SAAS,GAAG,MAAM,oBAAoB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAE7E,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC,OAAO,CAAC;IAElD,OAAO,iBAAiB,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,GAAoB,EACpB,OAAsB,EACtB,IAAwB;AACxB,iHAAiH;AACjH,MAAwC;IAExC,MAAM,QAAQ,GAAG,IAAI,KAAK,SAAS,CAAC;IACpC,MAAM,GAAG,GAAG,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;IAE1C,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpC,OAAO,aAAa,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AACnD,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,aAAa,CAC1B,GAAoB,EACpB,OAAsB;IAEtB,IAAI,SAAS,GAAG,EAAE,CAAC;IAEnB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,wBAAwB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAE5D,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YAC3B,SAAS;gBACP,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;oBACvB,CAAC,CAAC,wBAAwB,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG;oBAC1D,CAAC,CAAC,oDAAoD,CAAC;QAC7D,CAAC;IACH,CAAC;eAAO,CAAC;QACP,2DAA2D;IAC7D,CAAC;IAED,MAAM,eAAe,CACnB,4CAA4C,EAC5C,kEAAkE;QAChE,mEAAmE;QACnE,iBAAiB,SAAS,EAAE,CAC/B,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,oBAAoB,CAClC,MAAqB,EACrB,MAAc,EACd,IAAY;IAEZ,MAAM,KAAK,GAAG;QACZ,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,MAAM;QACxC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS;KACxC,CAAC;IAEF,MAAM,YAAY,GAChB,MAAM,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,KAAK,IAAI;QAC/D,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI;QACrB,CAAC,CAAC,IAAI,CAAC;IAEX,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACjC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;IACtD,CAAC;IAED,IAAI,CAAC;QACH,EAAE,CAAC,aAAa,CACd,MAAM,CAAC,UAAU,EACjB,gBAAgB,iCACX,MAAM,CAAC,OAAO,KACjB,MAAM,EACN,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAC7C,CACH,CAAC;QAEF,uCAAY,KAAK,KAAE,YAAY,IAAG;IACpC,CAAC;eAAO,CAAC;QACP,wEAAwE;QACxE,gDAAgD;QAChD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;IACtD,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,sBAAsB,GAAG,GAAG,CAAC;AAEnC;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,MAAqB,EAAE,KAAe;IAClE,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,iBAC7B,OAAO,EAAE,MAAM,CAAC,OAAO,EACvB,YAAY,EAAE,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC5C,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,KAAK,EAAE,CAAC,CAAC,KAAK;SACf,CAAC,CAAC,EACH,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,sBAAsB,CAAC,IAC1C,CAAC,KAAK,CAAC,MAAM,GAAG,sBAAsB;QACvC,CAAC,CAAC,EAAE,cAAc,EAAE,KAAK,CAAC,MAAM,EAAE;QAClC,CAAC,CAAC,EAAE,CAAC,EACP,CAAC;IAEH,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAElD,IAAI,KAAK,GAAG,kBAAkB,EAAE,CAAC;QAC/B,MAAM,eAAe,CACnB,8BAA8B,KAAK,mBAAmB;YACpD,GAAG,kBAAkB,mBAAmB,EAC1C,qEAAqE;YACnE,mEAAmE,CACtE,CAAC;IACJ,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,cAAc,GAClB,gGAAgG,CAAC;AAEnG;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,UAAkB;IACnD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;IAE3D,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,iBAAiB,CACrB,kBAAkB,YAAY,KAC5B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,EAAE,EACF,uEAAuE;YACrE,sBAAsB,CACzB,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GACX,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;QAC3C,CAAC,CAAE,MAAgC,CAAC,OAAO;QAC3C,CAAC,CAAC,SAAS,CAAC;IAEhB,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACjE,MAAM,eAAe,CACnB,6BACE,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC,SACjD,kCAAkC,EAClC,oBAAoB,YAAY,oCAAoC;YAClE,+BAA+B,CAClC,CAAC;IACJ,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC","sourcesContent":["import type { Finding } from '@ekanos/integration-schema';\nimport { findRepoRoot } from '@ekanos/integration-schema/repo';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport type { StoredSession } from '../auth/credential-store';\nimport {\n type AuthEnvironment,\n refreshStoredSession,\n requireSession,\n resolveAuthEnvironment,\n} from '../auth/session';\nimport type { CliContext } from '../context';\nimport {\n CliError,\n forbiddenError,\n gateFailedError,\n preconditionError,\n usageError,\n validationError,\n} from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport { readProjectKind } from '../experience/project';\nimport { runExperiencePublish } from '../experience/publish';\nimport { renderFindings } from '../findings-renderer';\nimport { type SlugLookup, lookupSlug } from '../names-api';\nimport { packProject } from '../pack';\nimport { type LoadedProject, loadProject, serializeProject } from '../project';\nimport {\n MAX_MANIFEST_BYTES,\n globalNameUnapprovedError,\n stillUnauthorized,\n submitArchive,\n} from '../publish-api';\nimport { runRepoPublish } from '../repo/publish';\nimport { assertSchemaNotSkewed } from '../schema-skew';\nimport { fetchSeatsWithOneRefresh } from '../seats';\nimport { type SourceSeat, stillUnauthorizedSourceSeats } from '../sources-api';\nimport { shortHost } from '../ui';\nimport { announceUpdate, checkForUpdate } from '../update-notice';\nimport { collectAllFindings } from '../validate-findings';\n\n/**\n * Checks that are WARN in plain `ekanos validate` but must refuse a\n * `publish` outright: a project that will fail the gate is not allowed to\n * upload and find that out from the gate instead of from itself.\n * `project.host-compiler-rules` (see `project-checks.ts`) is WARN-severity\n * everywhere else on purpose — it reads a partner's local tsconfig, not the\n * gate's own verdict, so it must not block plain validate on a false\n * positive — but at the publish gate, \"this WILL fail the gate\" is exactly\n * the thing a submission preflight exists to refuse. A list, not a second\n * check, so the underlying rule and its message/hint stay defined in exactly\n * one place.\n */\nconst PUBLISH_ERROR_ESCALATIONS: readonly string[] = [\n 'project.host-compiler-rules',\n];\n\n/**\n * Escalate the checks in `PUBLISH_ERROR_ESCALATIONS` from `warn` to `error`\n * for THIS publish run only — `validate`'s own output (and the underlying\n * finding objects elsewhere) is never touched.\n */\nexport function escalateForPublish(findings: Finding[]): Finding[] {\n return findings.map((finding) =>\n finding.severity === 'warn' &&\n PUBLISH_ERROR_ESCALATIONS.includes(finding.check)\n ? { ...finding, severity: 'error' }\n : finding,\n );\n}\n\nexport interface PublishArgs {\n host?: string;\n /** Ekanos source slug. Falls back to ekanos.json's \"source\" field. */\n source?: string;\n /** Project directory (contains ekanos.json). Defaults to cwd. */\n dir: string;\n /**\n * Skips the interactive confirm when the source resolved IMPLICITLY (from\n * ekanos.json) and the caller holds more than one developer seat. Has no\n * effect when `--source` was passed this invocation (explicit is already\n * consent) or when the caller holds exactly one seat (nothing to\n * disambiguate).\n */\n yes: boolean;\n env: Record<string, string | undefined>;\n /**\n * Whether stdin is a real interactive terminal — the SECOND condition (with\n * human/non-JSON mode) required before publish will ever prompt. Defaults\n * to `process.stdin.isTTY === true`. Injectable so tests can exercise the\n * confirm branch without a real TTY.\n */\n stdinIsTTY?: boolean;\n /**\n * Injectable y/N prompt, for tests. Defaults to a real readline prompt over\n * stdin/stderr. Never invoked unless BOTH human mode and a real stdin TTY\n * are in play — see `canPrompt` in `verifyPublishTarget`.\n */\n confirm?: (question: string) => Promise<boolean>;\n /** Experiences only: build and pack, publish nothing. In a repo: every package. */\n dryRun?: boolean;\n /** Repo only: the packages to publish, by name. */\n packages?: readonly string[];\n /** Repo only: publish every package. */\n all?: boolean;\n}\n\n/** Where the resolved source slug came from — governs the confirmation rules below. */\nexport interface SourceResolution {\n source: string;\n /** True iff `--source` was passed THIS invocation. */\n explicit: boolean;\n}\n\n/**\n * `publish` — pack the project and submit it to an Ekanos deployment.\n *\n * The submission gate is the SAME findings pass `validate` runs (one\n * implementation, `validate-findings.ts`): any error-severity finding refuses\n * the publish with GATE_FAILED (exit 10) and the findings in `data`, so an\n * agent can branch on the code and fix-then-retry without re-running validate.\n *\n * Authorization is server-side — the dev seat on the target source — and the\n * stored session is refreshed once on a 401, mirroring `whoami`. On the first\n * successful publish the chosen source slug is persisted into `ekanos.json`\n * so later publishes need no `--source`.\n */\nexport async function runPublish(\n ctx: CliContext,\n args: PublishArgs,\n): Promise<ExitCode> {\n // Inside a repo, `publish` plans the packages: a same-repo integration is\n // ordered first rather than refused as an override.\n const repoRoot = findRepoRoot(path.resolve(args.dir));\n if (repoRoot) {\n return runRepoPublish(ctx, {\n repoRoot,\n cwd: path.resolve(args.dir),\n names: args.packages ?? [],\n all: args.all === true,\n publish: args,\n });\n }\n if ((args.packages?.length ?? 0) > 0 || args.all) {\n throw usageError(\n 'Package names and --all are for a repo.',\n 'Run this from a repo (see \"ekanos init --kind repo\"), or drop the names to publish this project.',\n );\n }\n\n // An experience is published (dry-run only, for now) by its own pipeline,\n // before any login: overrides and the gate refuse it first.\n if (readProjectKind(path.resolve(args.dir)) === 'experience') {\n return runExperiencePublish(ctx, {\n dir: args.dir,\n dryRun: args.dryRun === true,\n env: args.env,\n host: args.host,\n source: args.source,\n yes: args.yes,\n stdinIsTTY: args.stdinIsTTY,\n confirm: args.confirm,\n });\n }\n\n const prepared = await prepareIntegrationSubmission(ctx, args);\n const { loaded, version, slug } = prepared;\n\n ctx.log(`Validating ${slug} before publishing…`);\n\n const findings = escalateForPublish(await collectAllFindings(loaded));\n const errorCount = findings.filter((f) => f.severity === 'error').length;\n\n if (errorCount > 0) {\n // Same rule as `validate`: render the shared findings block to stderr\n // BEFORE the envelope settles, human mode only. JSON mode carries the\n // identical findings in `data.findings` and must stay byte-identical.\n // Closing order is findings block -> short summary (via `ctx.fail`'s\n // `findingsSummary` option) -> next action.\n if (!ctx.jsonMode) {\n ctx.log(\n ctx.ui.err(\n `${ctx.ui.glyphs.err} Refusing to publish: ${errorCount} finding` +\n `${errorCount === 1 ? '' : 's'}.`,\n ),\n );\n renderFindings(ctx, findings, { cwd: loaded.projectDir });\n }\n\n const exitCode = ctx.fail(\n gateFailedError(\n `Refusing to publish: ${errorCount} validation finding` +\n `${errorCount === 1 ? '' : 's'}.`,\n 'Resolve the error-severity findings in data.findings (they are ' +\n 'exactly what \"ekanos validate\" reports), then re-run ' +\n '\"ekanos publish\".',\n ),\n { slug, version, findings },\n !ctx.jsonMode\n ? { findingsSummary: { command: 'ekanos publish', errorCount } }\n : undefined,\n );\n\n if (!ctx.jsonMode) {\n ctx.log(\n ctx.ui.nextAction(\n 'ekanos validate',\n 'fix the error-severity findings above, then re-run \"ekanos publish\"',\n ),\n );\n }\n\n return exitCode;\n }\n\n if (!ctx.jsonMode) {\n ctx.log(\n ctx.ui.ok(\n `${ctx.ui.glyphs.ok} validated ${slug} — no error-severity findings.`,\n ),\n );\n }\n\n const submitted = await submitPrepared(ctx, args, prepared);\n\n return ctx.succeed(submitted.data, submitted.human);\n}\n\nexport interface SubmittedIntegration {\n data: Record<string, unknown>;\n human: string;\n}\n\n/**\n * Confirm the target, pack and submit one gated integration. The caller has\n * already passed the gate; this is the only part of `publish` that talks to\n * the host.\n */\nexport async function submitPrepared(\n ctx: CliContext,\n args: PublishArgs,\n prepared: PreparedSubmission,\n): Promise<SubmittedIntegration> {\n const { loaded, skew, notice, env, version, slug, resolution } = prepared;\n\n // The 100%-certainty mechanism: confirm the resolved source is one the\n // caller actually holds a seat on — and, when it was resolved IMPLICITLY\n // from ekanos.json with more than one seat in play, that a human (or an\n // explicit --yes) actually intends this target — BEFORE anything is packed\n // or sent over the wire.\n const verified = await verifyPublishTarget(ctx, env, resolution.session, {\n source: resolution.source,\n explicit: resolution.explicit,\n slug,\n version,\n yes: args.yes,\n stdinIsTTY: args.stdinIsTTY ?? process.stdin.isTTY === true,\n confirm: args.confirm ?? promptYesNo,\n });\n\n const source = verified.sourceSeat.slug;\n const availability = loaded.project.availability?.mode;\n\n // Say the full name the host will use, and refuse an unapproved global\n // name, before anything is packed.\n const lookup = await preflightName(\n ctx,\n env,\n verified.session,\n source,\n slug,\n availability,\n );\n\n ctx.log(`Packing ${slug}@${version}…`);\n\n const packed = packProject(loaded.projectDir);\n const manifest = buildManifest(loaded, packed.files);\n\n if (!ctx.jsonMode) {\n ctx.log(\n ctx.ui.ok(\n `${ctx.ui.glyphs.ok} packed ${slug}@${version} (${packed.files.length} files).`,\n ),\n );\n }\n\n ctx.log(`Submitting to ${env.host} (source \"${source}\")…`);\n\n const receipt = await submitWithOneRefresh(env, verified.session, {\n source,\n slug,\n version,\n manifest,\n archive: packed.archive,\n ...(availability ? { availability } : {}),\n });\n\n const displayName =\n receipt.displayName ?? lookup?.displayName ?? receipt.slug;\n\n if (!ctx.jsonMode) {\n ctx.log(\n ctx.ui.ok(\n `${ctx.ui.glyphs.ok} submitted ${displayName}@${receipt.version} ` +\n `(state \"${receipt.state}\").`,\n ),\n );\n }\n\n const persisted = persistProjectFields(loaded, source, env.host);\n\n const persistedNote = [\n ...(persisted.source ? [`\"source\": \"${source}\"`] : []),\n ...(persisted.host ? [`\"host\": \"${env.host}\"`] : []),\n ];\n\n return {\n data: {\n host: env.host,\n source: {\n id: verified.sourceSeat.id,\n slug: verified.sourceSeat.slug,\n name: verified.sourceSeat.name,\n },\n slug: receipt.slug,\n namespace: receipt.namespace ?? lookup?.namespace ?? null,\n displayName,\n version: receipt.version,\n submissionId: receipt.submissionId,\n state: receipt.state,\n archiveSha256: receipt.archiveSha256,\n files: packed.files,\n sourcePersisted: persisted.source,\n hostPersisted: persisted.host,\n hostOverride: persisted.hostOverride,\n ...(skew.status === 'project-older'\n ? {\n schemaSkew: {\n status: skew.status,\n cliSchemaVersion: skew.cliSchemaVersion,\n projectSchemaVersion: skew.projectSchemaVersion,\n },\n }\n : {}),\n ...(notice ? { toolchain: notice } : {}),\n },\n human: ctx.ui.result({\n title: 'Submitted',\n rows: [\n ['Integration', `${displayName}@${receipt.version}`],\n ['State', receipt.state],\n ['Source', source],\n ['Host', shortHost(env.host)],\n ...(persistedNote.length > 0\n ? [\n [\n 'Saved',\n `${persistedNote.join(' and ')} to ekanos.json`,\n ] as const,\n ]\n : []),\n ],\n notes: persisted.hostOverride\n ? [\n `This publish went to ${env.host}, but ekanos.json keeps \"host\": ` +\n `\"${persisted.hostOverride}\" — a one-off override never replaces ` +\n 'the saved host; edit ekanos.json to change it.',\n ]\n : [],\n }),\n };\n}\n\n/**\n * Ask the host what it will call this slug for the Source, before packing.\n * An unapproved global name stops the publish here. Any other answer - an\n * older host without the route, a server error, a shape this CLI does not\n * read - is not a reason to stop: the submission itself is authoritative, and\n * the bare slug stands in for the name.\n */\nasync function preflightName(\n ctx: CliContext,\n env: AuthEnvironment,\n session: StoredSession,\n source: string,\n slug: string,\n availability: 'global' | 'restricted' | undefined,\n): Promise<SlugLookup | null> {\n let lookup: SlugLookup | null = null;\n\n try {\n let result = await lookupSlug(\n env.host,\n session.accessToken,\n source,\n slug,\n availability,\n );\n if (result.status === 'unauthorized') {\n const refreshed = await refreshStoredSession(env, session);\n result = await lookupSlug(\n env.host,\n refreshed.accessToken,\n source,\n slug,\n availability,\n );\n }\n if (result.status === 'ok') lookup = result.lookup;\n } catch (error) {\n if (!(error instanceof CliError)) throw error;\n ctx.log(\n `Could not pre-check the name of ${slug} (${error.message}); continuing.`,\n );\n }\n\n if (lookup?.status === 'global_unapproved') {\n throw globalNameUnapprovedError(slug);\n }\n\n if (lookup?.displayName && !ctx.jsonMode) {\n ctx.log(`Publishing as ${lookup.displayName}.`);\n }\n\n return lookup;\n}\n\nexport interface PreparedSubmission {\n env: AuthEnvironment;\n session: StoredSession;\n loaded: LoadedProject;\n skew: ReturnType<typeof assertSchemaNotSkewed>;\n notice: Awaited<ReturnType<typeof checkForUpdate>>;\n resolution: SourceResolution & { session: StoredSession };\n version: string;\n slug: string;\n}\n\n/**\n * Everything `publish` does before it gates a project: sign-in, load, schema\n * skew, toolchain check, source resolution. Shared by the single-project verb\n * and the repo verb (which gates every package before submitting any).\n */\nexport async function prepareIntegrationSubmission(\n ctx: CliContext,\n args: PublishArgs,\n): Promise<PreparedSubmission> {\n const env = resolveAuthEnvironment(ctx, args.host, args.env, {\n projectDir: args.dir,\n });\n const session = requireSession(env);\n\n const loaded = loadProject(args.dir);\n\n // Fail fast, before anything else: a project whose schema is newer than\n // this CLI bundles cannot be trusted to validate correctly, so publishing\n // it — the one verb whose findings gate is meant to be authoritative —\n // must refuse before packing or submitting anything. See `schema-skew.ts`.\n const skew = assertSchemaNotSkewed(ctx, loaded.projectDir);\n\n const notice = await checkForUpdate({\n env: args.env,\n host: env.host,\n session,\n });\n announceUpdate(ctx, notice);\n\n // The host would reject a build from a CLI it has declared unsupported\n // anyway (see the wire contract in `toolchain-api.ts`) — refuse here with a\n // hint naming the fix, rather than let the submission round-trip fail with\n // whatever generic error the host happens to answer with.\n if (notice?.status === 'unsupported') {\n throw preconditionError(\n `@ekanos/cli ${notice.current.cli} is below ${env.host}'s minimum ` +\n `supported version (needs at least ${notice.target.cli}).`,\n 'Run \"ekanos upgrade\" before publishing — the host will refuse this ' +\n 'submission from an unsupported CLI regardless.',\n );\n }\n\n const resolution = await resolveSourceSlug(env, session, args.source, loaded);\n const version = readProjectVersion(loaded.projectDir);\n const slug = loaded.primary.slug;\n\n return { env, session, loaded, skew, notice, resolution, version, slug };\n}\n\n/**\n * The publish-target verification gate.\n *\n * FORBIDDEN (exit 5) whenever the resolved source is not among the caller's\n * seats — regardless of whether it came from `--source` or ekanos.json.\n * Beyond that, the confirmation rules branch on how the source was resolved:\n *\n * - `--source` THIS invocation: explicit is consent. Proceed.\n * - ekanos.json, exactly one seat held (which must be the match, or the\n * FORBIDDEN check above would have already fired): proceed, but say so —\n * there is nothing to disambiguate, but the target should never be silent.\n * - ekanos.json, multiple seats held: the ambiguous case this mechanism\n * exists for. Only when BOTH human (non-JSON) mode AND stdin is a real\n * TTY does it print the target and require an explicit y/N confirm\n * (`--yes` skips it) — see `canPrompt` below for why stdin matters, not\n * just stdout. Every other combination (JSON mode, or human mode with a\n * closed/non-interactive stdin) NEVER prompts — it proceeds only with\n * `--yes`, otherwise VALIDATION (exit 3) with the seat list, naming\n * `--source`, `--yes` and `ekanos use`.\n */\nexport async function verifyPublishTarget(\n ctx: CliContext,\n env: AuthEnvironment,\n session: StoredSession,\n args: SourceResolution & {\n slug: string;\n version: string;\n yes: boolean;\n /** Real interactivity signal for stdin — see `canPrompt` below. */\n stdinIsTTY: boolean;\n confirm: (question: string) => Promise<boolean>;\n },\n): Promise<{ sourceSeat: SourceSeat; session: StoredSession }> {\n const result = await fetchSeatsWithOneRefresh(env, session);\n\n if (result.status === 'unauthorized') {\n stillUnauthorizedSourceSeats(env);\n }\n\n const seat = result.sources.find((s) => s.slug === args.source);\n\n if (!seat) {\n throw forbiddenError(\n `This account does not hold a seat on source \"${args.source}\" on ${env.host}.`,\n seatsHint(result.sources, env.host),\n );\n }\n\n if (args.explicit) {\n return { sourceSeat: seat, session: result.session };\n }\n\n if (result.sources.length === 1) {\n ctx.log(\n `Publishing to ${seat.name ?? seat.slug} (${seat.slug}) — your only ` +\n `developer seat.`,\n );\n return { sourceSeat: seat, session: result.session };\n }\n\n // Implicit source, multiple seats: the ambiguous case.\n //\n // `ctx.jsonMode` alone is NOT enough to decide whether an interactive\n // confirm is safe: `--no-json` forces human mode even when stdout is\n // piped, and neither `--no-json` nor a bare human run says anything about\n // stdin. Prompting `readline`'s `.question()` against a closed/non-TTY\n // stdin (a cron job, a wrapper script piping stdout but not attached to a\n // terminal) never resolves — the process hangs instead of exiting with a\n // clean code. So an actual prompt requires BOTH: human mode AND a real\n // stdin TTY. Anything else — JSON mode, or human mode with non-interactive\n // stdin — falls through to the same non-prompting `--yes`-or-refuse rule.\n const canPrompt = !ctx.jsonMode && args.stdinIsTTY;\n\n if (canPrompt) {\n ctx.log(\n `Publishing ${args.slug}@${args.version} to SOURCE ${seat.name ?? seat.slug} ` +\n `(${seat.slug}) on ${env.host}`,\n );\n\n if (!args.yes) {\n const confirmed = await args.confirm('Proceed? [y/N]');\n\n if (!confirmed) {\n throw validationError(\n `Publish to \"${seat.slug}\" was not confirmed.`,\n multiSeatHint(result.sources),\n );\n }\n }\n\n return { sourceSeat: seat, session: result.session };\n }\n\n if (args.yes) {\n return { sourceSeat: seat, session: result.session };\n }\n\n throw validationError(\n `Ambiguous publish target: this account holds ${result.sources.length} ` +\n `developer seats and the source was resolved from ekanos.json, not ` +\n `an explicit flag.`,\n multiSeatHint(result.sources),\n );\n}\n\nfunction seatsHint(sources: SourceSeat[], host: string): string {\n if (sources.length === 0) {\n return (\n `You hold no seats on any source on ${host}. Ask Ekanos ` +\n `to grant your account the developer seat on the intended source.`\n );\n }\n\n return (\n `You hold a seat on: ${describeSeats(sources)}. Pass \"--source <slug>\" ` +\n `naming one of these, or run \"ekanos use <slug>\" to set the project's ` +\n `default.`\n );\n}\n\nfunction multiSeatHint(sources: SourceSeat[]): string {\n return (\n `You hold seats on: ${describeSeats(sources)}. Pass \"--source <slug>\" ` +\n `to name the target explicitly, add \"--yes\" to confirm the target ` +\n `already in ekanos.json non-interactively, or run \"ekanos use <slug>\" ` +\n `to change the project's default.`\n );\n}\n\nfunction describeSeats(sources: SourceSeat[]): string {\n return sources.map((s) => `${s.slug} (${s.roles.join(', ')})`).join(', ');\n}\n\n/**\n * The real, non-test y/N prompt. Reads a line from stdin and writes the\n * question to stderr, so it never touches stdout — the one stream the JSON\n * envelope invariant depends on. Only reachable when `verifyPublishTarget`'s\n * `canPrompt` is true — human mode AND a real stdin TTY — so this never\n * blocks on a closed or non-interactive stdin.\n */\n/**\n * Exported so `upgrade` can reuse the exact same y/N prompt rather than\n * writing a second one — see `canPrompt` above for the stdin-TTY gating this\n * is only ever invoked behind.\n */\nexport async function promptYesNo(question: string): Promise<boolean> {\n const readline = await import('node:readline/promises');\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stderr,\n });\n\n try {\n const answer = await rl.question(`${question} `);\n return /^y(es)?$/i.test(answer.trim());\n } finally {\n rl.close();\n }\n}\n\nexport async function submitWithOneRefresh(\n env: ReturnType<typeof resolveAuthEnvironment>,\n session: StoredSession,\n payload: Parameters<typeof submitArchive>[2],\n) {\n const first = await submitArchive(env.host, session.accessToken, payload);\n\n if (first.status === 'ok') return first.receipt;\n\n // The access token no longer authenticates — an ordinary event, not an\n // error. One refresh, one retry; a second 401 is authoritative.\n const refreshed = await refreshStoredSession(env, session);\n const second = await submitArchive(env.host, refreshed.accessToken, payload);\n\n if (second.status === 'ok') return second.receipt;\n\n return stillUnauthorized(env);\n}\n\n/**\n * Resolve the source slug (flag → ekanos.json) and whether it was given\n * EXPLICITLY this invocation — the fact `verifyPublishTarget` uses to decide\n * whether a confirmation is even in play. `flag !== undefined` (rather than\n * \"non-empty after trim\") is deliberate: an explicit `--source` that is\n * effectively empty is still a caller who typed the flag, not one who\n * fell through to ekanos.json.\n */\nexport async function resolveSourceSlug(\n env: AuthEnvironment,\n session: StoredSession,\n flag: string | undefined,\n /** Anything that carries the project's saved `source`: an integration project or an experience's ekanos.json. */\n loaded: { project: { source?: string } },\n): Promise<SourceResolution & { session: StoredSession }> {\n const explicit = flag !== undefined;\n const raw = flag ?? loaded.project.source;\n\n if (!raw || raw.trim().length === 0) {\n return noSourceError(env, session);\n }\n\n return { source: raw.trim(), explicit, session };\n}\n\n/**\n * The no-source validation error, enriched with the caller's seat list when\n * it can be fetched — best-effort, since a session is guaranteed to exist\n * here (publish already called `requireSession`) but the fetch itself can\n * still fail (network, MFA, a down deployment). A failure to enrich must\n * never mask or replace the primary \"no source given\" error.\n */\nasync function noSourceError(\n env: AuthEnvironment,\n session: StoredSession,\n): Promise<never> {\n let seatsNote = '';\n\n try {\n const result = await fetchSeatsWithOneRefresh(env, session);\n\n if (result.status === 'ok') {\n seatsNote =\n result.sources.length > 0\n ? ` You hold a seat on: ${describeSeats(result.sources)}.`\n : ' You hold no seats on any source on this host yet.';\n }\n } catch {\n // Best-effort — the primary error below stands on its own.\n }\n\n throw validationError(\n 'No Ekanos source given for the submission.',\n 'Pass \"--source <slug>\" (your operator names the source), or set ' +\n '\"source\": \"<slug>\" in ekanos.json. A successful publish saves it ' +\n `there for you.${seatsNote}`,\n );\n}\n\n/**\n * Persist the chosen source AND host into ekanos.json after a SUCCESSFUL\n * publish, so the next publish — and every other host-taking verb — needs no\n * flag. Returns what was written. A write failure is reported but never fails\n * the command — the submission already landed.\n *\n * `publish` is the only verb that writes ekanos.json: it is the one verb that\n * proves the (host, source) pair actually works, and it always runs inside a\n * project. `login` deliberately never writes — it is routinely run outside\n * one, and the credential store's sole-host fallback covers it.\n *\n * `host` persists on FIRST WRITE ONLY. It decides where every future verb\n * sends the bearer token and the source archive, so a one-off `--host`\n * override (a staging test, say) must not silently become the project's\n * sticky default; when the override differs from the stored host, the stored\n * value is kept and the difference is called out in the result instead.\n * Changing it is an explicit edit of ekanos.json. `source` keeps the simpler\n * always-update semantics — it is scoped BY the host, and updating it is the\n * documented way to repoint a project.\n */\nexport function persistProjectFields(\n loaded: LoadedProject,\n source: string,\n host: string,\n): { source: boolean; host: boolean; hostOverride: string | null } {\n const wants = {\n source: loaded.project.source !== source,\n host: loaded.project.host === undefined,\n };\n\n const hostOverride =\n loaded.project.host !== undefined && loaded.project.host !== host\n ? loaded.project.host\n : null;\n\n if (!wants.source && !wants.host) {\n return { source: false, host: false, hostOverride };\n }\n\n try {\n fs.writeFileSync(\n loaded.configPath,\n serializeProject({\n ...loaded.project,\n source,\n host: wants.host ? host : loaded.project.host,\n }),\n );\n\n return { ...wants, hostOverride };\n } catch {\n // Diagnostics-only: the publish succeeded; a read-only ekanos.json just\n // means the next publish needs the flags again.\n return { source: false, host: false, hostOverride };\n }\n}\n\n/**\n * How many packed paths the manifest embeds before switching to a truncated\n * list plus a `filesTruncated` total. The manifest is metadata — the archive\n * itself is the payload — and the server caps it at MAX_MANIFEST_BYTES, so a\n * many-small-files project must not be able to blow the cap with its file\n * list alone.\n */\nconst MANIFEST_FILE_LIST_CAP = 200;\n\n/**\n * The submission manifest: the parsed ekanos.json, the integration entries,\n * and (a bounded prefix of) the packed file list. Refuses to build one over\n * the server's byte cap — a clear VALIDATION error here beats the server's\n * generic 400 after a 4 MiB upload.\n */\nexport function buildManifest(loaded: LoadedProject, files: string[]): string {\n const manifest = JSON.stringify({\n project: loaded.project,\n integrations: loaded.integrations.map((i) => ({\n slug: i.slug,\n entry: i.entry,\n })),\n files: files.slice(0, MANIFEST_FILE_LIST_CAP),\n ...(files.length > MANIFEST_FILE_LIST_CAP\n ? { filesTruncated: files.length }\n : {}),\n });\n\n const bytes = Buffer.byteLength(manifest, 'utf8');\n\n if (bytes > MAX_MANIFEST_BYTES) {\n throw validationError(\n `The submission manifest is ${bytes} bytes, over the ` +\n `${MAX_MANIFEST_BYTES}-byte server cap.`,\n 'The manifest embeds your ekanos.json — trim oversized fields there ' +\n '(sourceGlobs is the usual culprit), then re-run \"ekanos publish\".',\n );\n }\n\n return manifest;\n}\n\nconst SEMVER_PATTERN =\n /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$/;\n\n/**\n * The submitted version is the project's own `package.json#version` — one\n * source of truth, the same field npm would publish.\n */\nexport function readProjectVersion(projectDir: string): string {\n const manifestPath = path.join(projectDir, 'package.json');\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));\n } catch (error) {\n throw preconditionError(\n `Could not read ${manifestPath}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n `Ensure the project has a valid package.json — its \"version\" field is ` +\n `what gets submitted.`,\n );\n }\n\n const version =\n typeof parsed === 'object' && parsed !== null\n ? (parsed as { version?: unknown }).version\n : undefined;\n\n if (typeof version !== 'string' || !SEMVER_PATTERN.test(version)) {\n throw validationError(\n `package.json \"version\" is ${\n typeof version === 'string' ? `\"${version}\"` : 'missing'\n }, which is not a semver version.`,\n `Set \"version\" in ${manifestPath} to a semver string like \"0.1.0\", ` +\n `then re-run \"ekanos publish\".`,\n );\n }\n\n return version;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../../src/commands/publish.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Finding } from '@ekanos/integration-schema';\nimport { findRepoRoot } from '@ekanos/integration-schema/repo';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport type { StoredSession } from '../auth/credential-store';\nimport {\n type AuthEnvironment,\n refreshStoredSession,\n requireSession,\n resolveAuthEnvironment,\n} from '../auth/session';\nimport type { CliContext } from '../context';\nimport {\n CliError,\n forbiddenError,\n gateFailedError,\n preconditionError,\n usageError,\n validationError,\n} from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport { readProjectKind } from '../experience/project';\nimport { runExperiencePublish } from '../experience/publish';\nimport { renderFindings } from '../findings-renderer';\nimport { type SlugLookup, lookupSlug } from '../names-api';\nimport { packProject } from '../pack';\nimport { type LoadedProject, loadProject, serializeProject } from '../project';\nimport {\n MAX_MANIFEST_BYTES,\n globalNameUnapprovedError,\n stillUnauthorized,\n submitArchive,\n} from '../publish-api';\nimport { runRepoPublish } from '../repo/publish';\nimport { assertSchemaNotSkewed } from '../schema-skew';\nimport { fetchSeatsWithOneRefresh } from '../seats';\nimport { type SourceSeat, stillUnauthorizedSourceSeats } from '../sources-api';\nimport { shortHost } from '../ui';\nimport { announceUpdate, checkForUpdate } from '../update-notice';\nimport { collectAllFindings } from '../validate-findings';\nimport {\n DEFAULT_WAIT_MINUTES,\n failWatchTimeout,\n waitForGate,\n watchOutcomeData,\n} from './status';\n\n/**\n * Checks that are WARN in plain `ekanos validate` but must refuse a\n * `publish` outright: a project that will fail the gate is not allowed to\n * upload and find that out from the gate instead of from itself.\n * `project.host-compiler-rules` (see `project-checks.ts`) is WARN-severity\n * everywhere else on purpose — it reads a partner's local tsconfig, not the\n * gate's own verdict, so it must not block plain validate on a false\n * positive — but at the publish gate, \"this WILL fail the gate\" is exactly\n * the thing a submission preflight exists to refuse. A list, not a second\n * check, so the underlying rule and its message/hint stay defined in exactly\n * one place.\n */\nconst PUBLISH_ERROR_ESCALATIONS: readonly string[] = [\n 'project.host-compiler-rules',\n];\n\n/**\n * Escalate the checks in `PUBLISH_ERROR_ESCALATIONS` from `warn` to `error`\n * for THIS publish run only — `validate`'s own output (and the underlying\n * finding objects elsewhere) is never touched.\n */\nexport function escalateForPublish(findings: Finding[]): Finding[] {\n return findings.map((finding) =>\n finding.severity === 'warn' &&\n PUBLISH_ERROR_ESCALATIONS.includes(finding.check)\n ? { ...finding, severity: 'error' }\n : finding,\n );\n}\n\nexport interface PublishArgs {\n host?: string;\n /** Ekanos source slug. Falls back to ekanos.json's \"source\" field. */\n source?: string;\n /** Project directory (contains ekanos.json). Defaults to cwd. */\n dir: string;\n /**\n * Skips the interactive confirm when the source resolved IMPLICITLY (from\n * ekanos.json) and the caller holds more than one developer seat. Has no\n * effect when `--source` was passed this invocation (explicit is already\n * consent) or when the caller holds exactly one seat (nothing to\n * disambiguate).\n */\n yes: boolean;\n env: Record<string, string | undefined>;\n /**\n * Whether stdin is a real interactive terminal — the SECOND condition (with\n * human/non-JSON mode) required before publish will ever prompt. Defaults\n * to `process.stdin.isTTY === true`. Injectable so tests can exercise the\n * confirm branch without a real TTY.\n */\n stdinIsTTY?: boolean;\n /**\n * Injectable y/N prompt, for tests. Defaults to a real readline prompt over\n * stdin/stderr. Never invoked unless BOTH human mode and a real stdin TTY\n * are in play — see `canPrompt` in `verifyPublishTarget`.\n */\n confirm?: (question: string) => Promise<boolean>;\n /** Experiences only: build and pack, publish nothing. In a repo: every package. */\n dryRun?: boolean;\n /** Repo only: the packages to publish, by name. */\n packages?: readonly string[];\n /** Repo only: publish every package. */\n all?: boolean;\n /** Integration only: after submitting, wait for the gate verdict. */\n wait?: boolean;\n /** `--wait`: minutes to wait for the verdict (default 30). */\n timeoutMinutes?: number;\n /** Injectable for tests: the wait between polls. */\n sleep?: (ms: number) => Promise<void>;\n}\n\n/** Where the resolved source slug came from — governs the confirmation rules below. */\nexport interface SourceResolution {\n source: string;\n /** True iff `--source` was passed THIS invocation. */\n explicit: boolean;\n}\n\n/**\n * `publish` — pack the project and submit it to an Ekanos deployment.\n *\n * The submission gate is the SAME findings pass `validate` runs (one\n * implementation, `validate-findings.ts`): any error-severity finding refuses\n * the publish with GATE_FAILED (exit 10) and the findings in `data`, so an\n * agent can branch on the code and fix-then-retry without re-running validate.\n *\n * Authorization is server-side — the dev seat on the target source — and the\n * stored session is refreshed once on a 401, mirroring `whoami`. On the first\n * successful publish the chosen source slug is persisted into `ekanos.json`\n * so later publishes need no `--source`.\n */\nexport async function runPublish(\n ctx: CliContext,\n args: PublishArgs,\n): Promise<ExitCode> {\n // Inside a repo, `publish` plans the packages: a same-repo integration is\n // ordered first rather than refused as an override.\n const repoRoot = findRepoRoot(path.resolve(args.dir));\n if (repoRoot) {\n return runRepoPublish(ctx, {\n repoRoot,\n cwd: path.resolve(args.dir),\n names: args.packages ?? [],\n all: args.all === true,\n publish: args,\n });\n }\n if ((args.packages?.length ?? 0) > 0 || args.all) {\n throw usageError(\n 'Package names and --all are for a repo.',\n 'Run this from a repo (see \"ekanos init --kind repo\"), or drop the names to publish this project.',\n );\n }\n\n // An experience is published (dry-run only, for now) by its own pipeline,\n // before any login: overrides and the gate refuse it first.\n if (readProjectKind(path.resolve(args.dir)) === 'experience') {\n return runExperiencePublish(ctx, {\n dir: args.dir,\n dryRun: args.dryRun === true,\n env: args.env,\n host: args.host,\n source: args.source,\n yes: args.yes,\n stdinIsTTY: args.stdinIsTTY,\n confirm: args.confirm,\n });\n }\n\n if (args.dryRun) return runIntegrationDryRun(ctx, args);\n\n const prepared = await prepareIntegrationSubmission(ctx, args);\n const { loaded, version, slug } = prepared;\n\n const gate = await refuseOnFindings(ctx, loaded, slug, version);\n if (gate.exitCode !== null) return gate.exitCode;\n\n const submitted = await submitPrepared(ctx, args, prepared);\n\n if (!args.wait) return ctx.succeed(submitted.data, submitted.human);\n\n const submittedSource = (submitted.data.source as { slug: string }).slug;\n const waited = await waitForGate(ctx, prepared.env, {\n slug,\n source: submittedSource,\n version,\n timeoutMinutes: args.timeoutMinutes ?? DEFAULT_WAIT_MINUTES,\n sleep:\n args.sleep ??\n ((ms) =>\n new Promise((resolve) => {\n setTimeout(resolve, ms);\n })),\n });\n if (waited.timedOut) return failWatchTimeout(ctx, slug, version, waited);\n\n const gateData = watchOutcomeData(slug, waited.version);\n if (waited.version.state === 'rejected') {\n return ctx.fail(\n gateFailedError(\n `${slug}@${version} was submitted but rejected by the gate ` +\n `(${gateData.errorCount ?? 0} error${gateData.errorCount === 1 ? '' : 's'}).`,\n 'Resolve the error-severity findings in data.gate.findings, bump the ' +\n 'version (a submitted version cannot be changed), and re-run \"ekanos publish\".',\n ),\n { ...submitted.data, gate: gateData },\n );\n }\n\n return ctx.succeed(\n { ...submitted.data, state: waited.version.state, gate: gateData },\n `${submitted.human}\\n${ctx.ui.ok(`${ctx.ui.glyphs.ok} gate verdict: ${waited.version.state}`)}`,\n );\n}\n\n/**\n * The local gate every publish shares: the full findings pass, refusing with\n * GATE_FAILED when any finding is an error. Returns the exit code when it\n * refused, `null` when the project may go on.\n */\nasync function refuseOnFindings(\n ctx: CliContext,\n loaded: LoadedProject,\n slug: string,\n version: string,\n): Promise<{ exitCode: ExitCode | null; packWarnings: Finding[] }> {\n ctx.log(`Validating ${slug} before publishing…`);\n\n const findings = escalateForPublish(await collectAllFindings(loaded));\n const errorCount = findings.filter((f) => f.severity === 'error').length;\n\n if (errorCount > 0) {\n // Same rule as `validate`: render the shared findings block to stderr\n // BEFORE the envelope settles, human mode only. JSON mode carries the\n // identical findings in `data.findings` and must stay byte-identical.\n // Closing order is findings block -> short summary (via `ctx.fail`'s\n // `findingsSummary` option) -> next action.\n if (!ctx.jsonMode) {\n ctx.log(\n ctx.ui.err(\n `${ctx.ui.glyphs.err} Refusing to publish: ${errorCount} finding` +\n `${errorCount === 1 ? '' : 's'}.`,\n ),\n );\n renderFindings(ctx, findings, { cwd: loaded.projectDir });\n }\n\n const exitCode = ctx.fail(\n gateFailedError(\n `Refusing to publish: ${errorCount} validation finding` +\n `${errorCount === 1 ? '' : 's'}.`,\n 'Resolve the error-severity findings in data.findings (they are ' +\n 'exactly what \"ekanos validate\" reports), then re-run ' +\n '\"ekanos publish\".',\n ),\n { slug, version, findings },\n !ctx.jsonMode\n ? { findingsSummary: { command: 'ekanos publish', errorCount } }\n : undefined,\n );\n\n if (!ctx.jsonMode) {\n ctx.log(\n ctx.ui.nextAction(\n 'ekanos validate',\n 'fix the error-severity findings above, then re-run \"ekanos publish\"',\n ),\n );\n }\n\n return { exitCode, packWarnings: [] };\n }\n\n if (!ctx.jsonMode) {\n ctx.log(\n ctx.ui.ok(\n `${ctx.ui.glyphs.ok} validated ${slug} — no error-severity findings.`,\n ),\n );\n }\n\n // What is about to be packed is the one thing a version cannot take back.\n const packWarnings = findings.filter((f) => f.check.startsWith('pack.'));\n if (packWarnings.length > 0 && !ctx.jsonMode) {\n renderFindings(ctx, packWarnings, { cwd: loaded.projectDir });\n }\n\n return { exitCode: null, packWarnings };\n}\n\n/**\n * `publish --dry-run` for one integration: the same findings gate and the same\n * pack a real publish runs, with nothing sent. It needs no login and no\n * source, so it is what a CI job or a first look runs before the real one.\n */\nasync function runIntegrationDryRun(\n ctx: CliContext,\n args: PublishArgs,\n): Promise<ExitCode> {\n const loaded = loadProject(args.dir);\n const skew = assertSchemaNotSkewed(ctx, loaded.projectDir);\n const version = readProjectVersion(loaded.projectDir);\n const slug = loaded.primary.slug;\n\n const gate = await refuseOnFindings(ctx, loaded, slug, version);\n if (gate.exitCode !== null) return gate.exitCode;\n\n ctx.log(`Packing ${slug}@${version}…`);\n const packed = packProject(loaded.projectDir);\n buildManifest(loaded, packed.files);\n\n return ctx.succeed(\n {\n dryRun: true,\n slug,\n version,\n files: packed.files,\n archiveBytes: packed.archive.length,\n warnings: gate.packWarnings,\n ...(skew.status === 'project-older'\n ? {\n schemaSkew: {\n status: skew.status,\n cliSchemaVersion: skew.cliSchemaVersion,\n projectSchemaVersion: skew.projectSchemaVersion,\n },\n }\n : {}),\n },\n ctx.ui.result({\n title: 'Dry run: nothing submitted',\n rows: [\n ['Integration', `${slug}@${version}`],\n ['Files', String(packed.files.length)],\n ['Archive', `${packed.archive.length} bytes`],\n ],\n notes: [\n 'A submitted version is immutable: a mistake means a version bump. Run \"ekanos publish\" to submit.',\n ],\n }),\n );\n}\n\nexport interface SubmittedIntegration {\n data: Record<string, unknown>;\n human: string;\n}\n\n/**\n * Confirm the target, pack and submit one gated integration. The caller has\n * already passed the gate; this is the only part of `publish` that talks to\n * the host.\n */\nexport async function submitPrepared(\n ctx: CliContext,\n args: PublishArgs,\n prepared: PreparedSubmission,\n): Promise<SubmittedIntegration> {\n const { loaded, skew, notice, env, version, slug, resolution } = prepared;\n\n // The 100%-certainty mechanism: confirm the resolved source is one the\n // caller actually holds a seat on — and, when it was resolved IMPLICITLY\n // from ekanos.json with more than one seat in play, that a human (or an\n // explicit --yes) actually intends this target — BEFORE anything is packed\n // or sent over the wire.\n const verified = await verifyPublishTarget(ctx, env, resolution.session, {\n source: resolution.source,\n explicit: resolution.explicit,\n slug,\n version,\n yes: args.yes,\n stdinIsTTY: args.stdinIsTTY ?? process.stdin.isTTY === true,\n confirm: args.confirm ?? promptYesNo,\n });\n\n const source = verified.sourceSeat.slug;\n const availability = loaded.project.availability?.mode;\n\n // Say the full name the host will use, and refuse an unapproved global\n // name, before anything is packed.\n const lookup = await preflightName(\n ctx,\n env,\n verified.session,\n source,\n slug,\n availability,\n );\n\n ctx.log(`Packing ${slug}@${version}…`);\n\n const packed = packProject(loaded.projectDir);\n const manifest = buildManifest(loaded, packed.files);\n\n if (!ctx.jsonMode) {\n ctx.log(\n ctx.ui.ok(\n `${ctx.ui.glyphs.ok} packed ${slug}@${version} (${packed.files.length} files).`,\n ),\n );\n }\n\n ctx.log(`Submitting to ${env.host} (source \"${source}\")…`);\n\n const receipt = await submitWithOneRefresh(env, verified.session, {\n source,\n slug,\n version,\n manifest,\n archive: packed.archive,\n ...(availability ? { availability } : {}),\n });\n\n const displayName =\n receipt.displayName ?? lookup?.displayName ?? receipt.slug;\n\n if (!ctx.jsonMode) {\n ctx.log(\n ctx.ui.ok(\n `${ctx.ui.glyphs.ok} submitted ${displayName}@${receipt.version} ` +\n `(state \"${receipt.state}\").`,\n ),\n );\n }\n\n const persisted = persistProjectFields(loaded, source, env.host);\n\n const persistedNote = [\n ...(persisted.source ? [`\"source\": \"${source}\"`] : []),\n ...(persisted.host ? [`\"host\": \"${env.host}\"`] : []),\n ];\n\n return {\n data: {\n host: env.host,\n source: {\n id: verified.sourceSeat.id,\n slug: verified.sourceSeat.slug,\n name: verified.sourceSeat.name,\n },\n slug: receipt.slug,\n namespace: receipt.namespace ?? lookup?.namespace ?? null,\n displayName,\n version: receipt.version,\n submissionId: receipt.submissionId,\n state: receipt.state,\n archiveSha256: receipt.archiveSha256,\n files: packed.files,\n sourcePersisted: persisted.source,\n hostPersisted: persisted.host,\n hostOverride: persisted.hostOverride,\n ...(skew.status === 'project-older'\n ? {\n schemaSkew: {\n status: skew.status,\n cliSchemaVersion: skew.cliSchemaVersion,\n projectSchemaVersion: skew.projectSchemaVersion,\n },\n }\n : {}),\n ...(notice ? { toolchain: notice } : {}),\n },\n human: ctx.ui.result({\n title: 'Submitted',\n rows: [\n ['Integration', `${displayName}@${receipt.version}`],\n ['State', receipt.state],\n ['Source', source],\n ['Host', shortHost(env.host)],\n ...(persistedNote.length > 0\n ? [\n [\n 'Saved',\n `${persistedNote.join(' and ')} to ekanos.json`,\n ] as const,\n ]\n : []),\n ],\n notes: persisted.hostOverride\n ? [\n `This publish went to ${env.host}, but ekanos.json keeps \"host\": ` +\n `\"${persisted.hostOverride}\" — a one-off override never replaces ` +\n 'the saved host; edit ekanos.json to change it.',\n ]\n : [],\n }),\n };\n}\n\n/**\n * Ask the host what it will call this slug for the Source, before packing.\n * An unapproved global name stops the publish here. Any other answer - an\n * older host without the route, a server error, a shape this CLI does not\n * read - is not a reason to stop: the submission itself is authoritative, and\n * the bare slug stands in for the name.\n */\nasync function preflightName(\n ctx: CliContext,\n env: AuthEnvironment,\n session: StoredSession,\n source: string,\n slug: string,\n availability: 'global' | 'restricted' | undefined,\n): Promise<SlugLookup | null> {\n let lookup: SlugLookup | null = null;\n\n try {\n let result = await lookupSlug(\n env.host,\n session.accessToken,\n source,\n slug,\n availability,\n );\n if (result.status === 'unauthorized') {\n const refreshed = await refreshStoredSession(env, session);\n result = await lookupSlug(\n env.host,\n refreshed.accessToken,\n source,\n slug,\n availability,\n );\n }\n if (result.status === 'ok') lookup = result.lookup;\n } catch (error) {\n if (!(error instanceof CliError)) throw error;\n ctx.log(\n `Could not pre-check the name of ${slug} (${error.message}); continuing.`,\n );\n }\n\n if (lookup?.status === 'global_unapproved') {\n throw globalNameUnapprovedError(slug);\n }\n\n if (lookup?.displayName && !ctx.jsonMode) {\n ctx.log(`Publishing as ${lookup.displayName}.`);\n }\n\n return lookup;\n}\n\nexport interface PreparedSubmission {\n env: AuthEnvironment;\n session: StoredSession;\n loaded: LoadedProject;\n skew: ReturnType<typeof assertSchemaNotSkewed>;\n notice: Awaited<ReturnType<typeof checkForUpdate>>;\n resolution: SourceResolution & { session: StoredSession };\n version: string;\n slug: string;\n}\n\n/**\n * Everything `publish` does before it gates a project: sign-in, load, schema\n * skew, toolchain check, source resolution. Shared by the single-project verb\n * and the repo verb (which gates every package before submitting any).\n */\nexport async function prepareIntegrationSubmission(\n ctx: CliContext,\n args: PublishArgs,\n): Promise<PreparedSubmission> {\n const env = resolveAuthEnvironment(ctx, args.host, args.env, {\n projectDir: args.dir,\n });\n const session = requireSession(env);\n\n const loaded = loadProject(args.dir);\n\n // Fail fast, before anything else: a project whose schema is newer than\n // this CLI bundles cannot be trusted to validate correctly, so publishing\n // it — the one verb whose findings gate is meant to be authoritative —\n // must refuse before packing or submitting anything. See `schema-skew.ts`.\n const skew = assertSchemaNotSkewed(ctx, loaded.projectDir);\n\n const notice = await checkForUpdate({\n env: args.env,\n host: env.host,\n session,\n });\n announceUpdate(ctx, notice);\n\n // The host would reject a build from a CLI it has declared unsupported\n // anyway (see the wire contract in `toolchain-api.ts`) — refuse here with a\n // hint naming the fix, rather than let the submission round-trip fail with\n // whatever generic error the host happens to answer with.\n if (notice?.status === 'unsupported') {\n throw preconditionError(\n `@ekanos/cli ${notice.current.cli} is below ${env.host}'s minimum ` +\n `supported version (needs at least ${notice.target.cli}).`,\n 'Run \"ekanos upgrade\" before publishing — the host will refuse this ' +\n 'submission from an unsupported CLI regardless.',\n );\n }\n\n const resolution = await resolveSourceSlug(env, session, args.source, loaded);\n const version = readProjectVersion(loaded.projectDir);\n const slug = loaded.primary.slug;\n\n return { env, session, loaded, skew, notice, resolution, version, slug };\n}\n\n/**\n * The publish-target verification gate.\n *\n * FORBIDDEN (exit 5) whenever the resolved source is not among the caller's\n * seats — regardless of whether it came from `--source` or ekanos.json.\n * Beyond that, the confirmation rules branch on how the source was resolved:\n *\n * - `--source` THIS invocation: explicit is consent. Proceed.\n * - ekanos.json, exactly one seat held (which must be the match, or the\n * FORBIDDEN check above would have already fired): proceed, but say so —\n * there is nothing to disambiguate, but the target should never be silent.\n * - ekanos.json, multiple seats held: the ambiguous case this mechanism\n * exists for. Only when BOTH human (non-JSON) mode AND stdin is a real\n * TTY does it print the target and require an explicit y/N confirm\n * (`--yes` skips it) — see `canPrompt` below for why stdin matters, not\n * just stdout. Every other combination (JSON mode, or human mode with a\n * closed/non-interactive stdin) NEVER prompts — it proceeds only with\n * `--yes`, otherwise VALIDATION (exit 3) with the seat list, naming\n * `--source`, `--yes` and `ekanos use`.\n */\nexport async function verifyPublishTarget(\n ctx: CliContext,\n env: AuthEnvironment,\n session: StoredSession,\n args: SourceResolution & {\n slug: string;\n version: string;\n yes: boolean;\n /** Real interactivity signal for stdin — see `canPrompt` below. */\n stdinIsTTY: boolean;\n confirm: (question: string) => Promise<boolean>;\n },\n): Promise<{ sourceSeat: SourceSeat; session: StoredSession }> {\n const result = await fetchSeatsWithOneRefresh(env, session);\n\n if (result.status === 'unauthorized') {\n stillUnauthorizedSourceSeats(env);\n }\n\n const seat = result.sources.find((s) => s.slug === args.source);\n\n if (!seat) {\n throw forbiddenError(\n `This account does not hold a seat on source \"${args.source}\" on ${env.host}.`,\n seatsHint(result.sources, env.host),\n );\n }\n\n if (args.explicit) {\n return { sourceSeat: seat, session: result.session };\n }\n\n if (result.sources.length === 1) {\n ctx.log(\n `Publishing to ${seat.name ?? seat.slug} (${seat.slug}) — your only ` +\n `developer seat.`,\n );\n return { sourceSeat: seat, session: result.session };\n }\n\n // Implicit source, multiple seats: the ambiguous case.\n //\n // `ctx.jsonMode` alone is NOT enough to decide whether an interactive\n // confirm is safe: `--no-json` forces human mode even when stdout is\n // piped, and neither `--no-json` nor a bare human run says anything about\n // stdin. Prompting `readline`'s `.question()` against a closed/non-TTY\n // stdin (a cron job, a wrapper script piping stdout but not attached to a\n // terminal) never resolves — the process hangs instead of exiting with a\n // clean code. So an actual prompt requires BOTH: human mode AND a real\n // stdin TTY. Anything else — JSON mode, or human mode with non-interactive\n // stdin — falls through to the same non-prompting `--yes`-or-refuse rule.\n const canPrompt = !ctx.jsonMode && args.stdinIsTTY;\n\n if (canPrompt) {\n ctx.log(\n `Publishing ${args.slug}@${args.version} to SOURCE ${seat.name ?? seat.slug} ` +\n `(${seat.slug}) on ${env.host}`,\n );\n\n if (!args.yes) {\n const confirmed = await args.confirm('Proceed? [y/N]');\n\n if (!confirmed) {\n throw validationError(\n `Publish to \"${seat.slug}\" was not confirmed.`,\n multiSeatHint(result.sources),\n );\n }\n }\n\n return { sourceSeat: seat, session: result.session };\n }\n\n if (args.yes) {\n return { sourceSeat: seat, session: result.session };\n }\n\n throw validationError(\n `Ambiguous publish target: this account holds ${result.sources.length} ` +\n `developer seats and the source was resolved from ekanos.json, not ` +\n `an explicit flag.`,\n multiSeatHint(result.sources),\n );\n}\n\nfunction seatsHint(sources: SourceSeat[], host: string): string {\n if (sources.length === 0) {\n return (\n `You hold no seats on any source on ${host}. Ask Ekanos ` +\n `to grant your account the developer seat on the intended source.`\n );\n }\n\n return (\n `You hold a seat on: ${describeSeats(sources)}. Pass \"--source <slug>\" ` +\n `naming one of these, or run \"ekanos use <slug>\" to set the project's ` +\n `default.`\n );\n}\n\nfunction multiSeatHint(sources: SourceSeat[]): string {\n return (\n `You hold seats on: ${describeSeats(sources)}. Pass \"--source <slug>\" ` +\n `to name the target explicitly, add \"--yes\" to confirm the target ` +\n `already in ekanos.json non-interactively, or run \"ekanos use <slug>\" ` +\n `to change the project's default.`\n );\n}\n\nfunction describeSeats(sources: SourceSeat[]): string {\n return sources.map((s) => `${s.slug} (${s.roles.join(', ')})`).join(', ');\n}\n\n/**\n * The real, non-test y/N prompt. Reads a line from stdin and writes the\n * question to stderr, so it never touches stdout — the one stream the JSON\n * envelope invariant depends on. Only reachable when `verifyPublishTarget`'s\n * `canPrompt` is true — human mode AND a real stdin TTY — so this never\n * blocks on a closed or non-interactive stdin.\n */\n/**\n * Exported so `upgrade` can reuse the exact same y/N prompt rather than\n * writing a second one — see `canPrompt` above for the stdin-TTY gating this\n * is only ever invoked behind.\n */\nexport async function promptYesNo(question: string): Promise<boolean> {\n const readline = await import('node:readline/promises');\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stderr,\n });\n\n try {\n const answer = await rl.question(`${question} `);\n return /^y(es)?$/i.test(answer.trim());\n } finally {\n rl.close();\n }\n}\n\nexport async function submitWithOneRefresh(\n env: ReturnType<typeof resolveAuthEnvironment>,\n session: StoredSession,\n payload: Parameters<typeof submitArchive>[2],\n) {\n const first = await submitArchive(env.host, session.accessToken, payload);\n\n if (first.status === 'ok') return first.receipt;\n\n // The access token no longer authenticates — an ordinary event, not an\n // error. One refresh, one retry; a second 401 is authoritative.\n const refreshed = await refreshStoredSession(env, session);\n const second = await submitArchive(env.host, refreshed.accessToken, payload);\n\n if (second.status === 'ok') return second.receipt;\n\n return stillUnauthorized(env);\n}\n\n/**\n * Resolve the source slug (flag → ekanos.json) and whether it was given\n * EXPLICITLY this invocation — the fact `verifyPublishTarget` uses to decide\n * whether a confirmation is even in play. `flag !== undefined` (rather than\n * \"non-empty after trim\") is deliberate: an explicit `--source` that is\n * effectively empty is still a caller who typed the flag, not one who\n * fell through to ekanos.json.\n */\nexport async function resolveSourceSlug(\n env: AuthEnvironment,\n session: StoredSession,\n flag: string | undefined,\n /** Anything that carries the project's saved `source`: an integration project or an experience's ekanos.json. */\n loaded: { project: { source?: string } },\n): Promise<SourceResolution & { session: StoredSession }> {\n const explicit = flag !== undefined;\n const raw = flag ?? loaded.project.source;\n\n if (!raw || raw.trim().length === 0) {\n return noSourceError(env, session);\n }\n\n return { source: raw.trim(), explicit, session };\n}\n\n/**\n * The no-source validation error, enriched with the caller's seat list when\n * it can be fetched — best-effort, since a session is guaranteed to exist\n * here (publish already called `requireSession`) but the fetch itself can\n * still fail (network, MFA, a down deployment). A failure to enrich must\n * never mask or replace the primary \"no source given\" error.\n */\nasync function noSourceError(\n env: AuthEnvironment,\n session: StoredSession,\n): Promise<never> {\n let seatsNote = '';\n\n try {\n const result = await fetchSeatsWithOneRefresh(env, session);\n\n if (result.status === 'ok') {\n seatsNote =\n result.sources.length > 0\n ? ` You hold a seat on: ${describeSeats(result.sources)}.`\n : ' You hold no seats on any source on this host yet.';\n }\n } catch {\n // Best-effort — the primary error below stands on its own.\n }\n\n throw validationError(\n 'No Ekanos source given for the submission.',\n 'Pass \"--source <slug>\" (your operator names the source), or set ' +\n '\"source\": \"<slug>\" in ekanos.json. A successful publish saves it ' +\n `there for you.${seatsNote}`,\n );\n}\n\n/**\n * Persist the chosen source AND host into ekanos.json after a SUCCESSFUL\n * publish, so the next publish — and every other host-taking verb — needs no\n * flag. Returns what was written. A write failure is reported but never fails\n * the command — the submission already landed.\n *\n * `publish` is the only verb that writes ekanos.json: it is the one verb that\n * proves the (host, source) pair actually works, and it always runs inside a\n * project. `login` deliberately never writes — it is routinely run outside\n * one, and the credential store's sole-host fallback covers it.\n *\n * `host` persists on FIRST WRITE ONLY. It decides where every future verb\n * sends the bearer token and the source archive, so a one-off `--host`\n * override (a staging test, say) must not silently become the project's\n * sticky default; when the override differs from the stored host, the stored\n * value is kept and the difference is called out in the result instead.\n * Changing it is an explicit edit of ekanos.json. `source` keeps the simpler\n * always-update semantics — it is scoped BY the host, and updating it is the\n * documented way to repoint a project.\n */\nexport function persistProjectFields(\n loaded: LoadedProject,\n source: string,\n host: string,\n): { source: boolean; host: boolean; hostOverride: string | null } {\n const wants = {\n source: loaded.project.source !== source,\n host: loaded.project.host === undefined,\n };\n\n const hostOverride =\n loaded.project.host !== undefined && loaded.project.host !== host\n ? loaded.project.host\n : null;\n\n if (!wants.source && !wants.host) {\n return { source: false, host: false, hostOverride };\n }\n\n try {\n fs.writeFileSync(\n loaded.configPath,\n serializeProject({\n ...loaded.project,\n source,\n host: wants.host ? host : loaded.project.host,\n }),\n );\n\n return { ...wants, hostOverride };\n } catch {\n // Diagnostics-only: the publish succeeded; a read-only ekanos.json just\n // means the next publish needs the flags again.\n return { source: false, host: false, hostOverride };\n }\n}\n\n/**\n * How many packed paths the manifest embeds before switching to a truncated\n * list plus a `filesTruncated` total. The manifest is metadata — the archive\n * itself is the payload — and the server caps it at MAX_MANIFEST_BYTES, so a\n * many-small-files project must not be able to blow the cap with its file\n * list alone.\n */\nconst MANIFEST_FILE_LIST_CAP = 200;\n\n/**\n * The submission manifest: the parsed ekanos.json, the integration entries,\n * and (a bounded prefix of) the packed file list. Refuses to build one over\n * the server's byte cap — a clear VALIDATION error here beats the server's\n * generic 400 after a 4 MiB upload.\n */\nexport function buildManifest(loaded: LoadedProject, files: string[]): string {\n const manifest = JSON.stringify({\n project: loaded.project,\n integrations: loaded.integrations.map((i) => ({\n slug: i.slug,\n entry: i.entry,\n })),\n files: files.slice(0, MANIFEST_FILE_LIST_CAP),\n ...(files.length > MANIFEST_FILE_LIST_CAP\n ? { filesTruncated: files.length }\n : {}),\n });\n\n const bytes = Buffer.byteLength(manifest, 'utf8');\n\n if (bytes > MAX_MANIFEST_BYTES) {\n throw validationError(\n `The submission manifest is ${bytes} bytes, over the ` +\n `${MAX_MANIFEST_BYTES}-byte server cap.`,\n 'The manifest embeds your ekanos.json — trim oversized fields there ' +\n '(sourceGlobs is the usual culprit), then re-run \"ekanos publish\".',\n );\n }\n\n return manifest;\n}\n\nconst SEMVER_PATTERN =\n /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$/;\n\n/**\n * The submitted version is the project's own `package.json#version` — one\n * source of truth, the same field npm would publish.\n */\nexport function readProjectVersion(projectDir: string): string {\n const manifestPath = path.join(projectDir, 'package.json');\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));\n } catch (error) {\n throw preconditionError(\n `Could not read ${manifestPath}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n `Ensure the project has a valid package.json — its \"version\" field is ` +\n `what gets submitted.`,\n );\n }\n\n const version =\n typeof parsed === 'object' && parsed !== null\n ? (parsed as { version?: unknown }).version\n : undefined;\n\n if (typeof version !== 'string' || !SEMVER_PATTERN.test(version)) {\n throw validationError(\n `package.json \"version\" is ${\n typeof version === 'string' ? `\"${version}\"` : 'missing'\n }, which is not a semver version.`,\n `Set \"version\" in ${manifestPath} to a semver string like \"0.1.0\", ` +\n `then re-run \"ekanos publish\".`,\n );\n }\n\n return version;\n}\n"]}
|