@ekanos/cli 0.15.0 → 0.17.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 +103 -8
- package/dist/auth/ekanos-api.d.ts +23 -0
- package/dist/auth/ekanos-api.js +33 -6
- package/dist/auth/ekanos-api.js.map +1 -1
- package/dist/commands/add.d.ts +2 -0
- package/dist/commands/add.js +118 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/agents.js +3 -2
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/apps.d.ts +11 -3
- package/dist/commands/apps.js +86 -28
- package/dist/commands/apps.js.map +1 -1
- package/dist/commands/audiences.d.ts +31 -0
- package/dist/commands/audiences.js +239 -0
- package/dist/commands/audiences.js.map +1 -0
- package/dist/commands/build.d.ts +2 -0
- package/dist/commands/build.js +41 -0
- package/dist/commands/build.js.map +1 -0
- package/dist/commands/catalog.d.ts +4 -2
- package/dist/commands/catalog.js +166 -35
- package/dist/commands/catalog.js.map +1 -1
- package/dist/commands/check.d.ts +2 -0
- package/dist/commands/check.js +43 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/codegen.d.ts +2 -0
- package/dist/commands/codegen.js +49 -0
- package/dist/commands/codegen.js.map +1 -0
- package/dist/commands/contract.d.ts +52 -0
- package/dist/commands/contract.js +300 -0
- package/dist/commands/contract.js.map +1 -0
- package/dist/commands/dev.d.ts +7 -0
- package/dist/commands/dev.js +186 -12
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/index-experience.d.ts +31 -0
- package/dist/commands/index-experience.js +21 -0
- package/dist/commands/index-experience.js.map +1 -0
- package/dist/commands/init.d.ts +7 -0
- package/dist/commands/init.js +12 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.js +17 -0
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/new.d.ts +2 -0
- package/dist/commands/new.js +39 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/publish.d.ts +59 -0
- package/dist/commands/publish.js +118 -65
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/runs.d.ts +7 -3
- package/dist/commands/runs.js +21 -5
- package/dist/commands/runs.js.map +1 -1
- package/dist/commands/scope-notice.d.ts +13 -0
- package/dist/commands/scope-notice.js +12 -4
- package/dist/commands/scope-notice.js.map +1 -1
- package/dist/commands/sources-roles.d.ts +5 -0
- package/dist/commands/sources-roles.js +235 -0
- package/dist/commands/sources-roles.js.map +1 -0
- package/dist/commands/sources.d.ts +5 -0
- package/dist/commands/sources.js +8 -1
- package/dist/commands/sources.js.map +1 -1
- package/dist/commands/sync.d.ts +2 -0
- package/dist/commands/sync.js +150 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/team-agent-readiness.d.ts +18 -2
- package/dist/commands/team-agent-readiness.js +39 -39
- package/dist/commands/team-agent-readiness.js.map +1 -1
- package/dist/commands/team-agents-agents.d.ts +5 -2
- package/dist/commands/team-agents-agents.js +152 -15
- package/dist/commands/team-agents-agents.js.map +1 -1
- package/dist/commands/team-agents-define.d.ts +31 -0
- package/dist/commands/team-agents-define.js +176 -0
- package/dist/commands/team-agents-define.js.map +1 -0
- package/dist/commands/team-agents-mcp.js +112 -10
- package/dist/commands/team-agents-mcp.js.map +1 -1
- package/dist/commands/team-agents-triggers.d.ts +1 -1
- package/dist/commands/team-agents-triggers.js +137 -5
- package/dist/commands/team-agents-triggers.js.map +1 -1
- package/dist/commands/team-agents.d.ts +4 -1
- package/dist/commands/team-agents.js +17 -4
- package/dist/commands/team-agents.js.map +1 -1
- package/dist/commands/team-llm-key.d.ts +14 -0
- package/dist/commands/team-llm-key.js +122 -0
- package/dist/commands/team-llm-key.js.map +1 -0
- package/dist/commands/teams-audience.d.ts +12 -0
- package/dist/commands/teams-audience.js +144 -0
- package/dist/commands/teams-audience.js.map +1 -0
- package/dist/commands/teams-connect.js +123 -31
- package/dist/commands/teams-connect.js.map +1 -1
- package/dist/commands/teams-lifecycle.d.ts +90 -0
- package/dist/commands/teams-lifecycle.js +457 -0
- package/dist/commands/teams-lifecycle.js.map +1 -0
- package/dist/commands/teams-onboard.d.ts +14 -0
- package/dist/commands/teams-onboard.js +62 -13
- package/dist/commands/teams-onboard.js.map +1 -1
- package/dist/commands/teams-overview.js +6 -2
- package/dist/commands/teams-overview.js.map +1 -1
- package/dist/commands/teams-scope.js +4 -0
- package/dist/commands/teams-scope.js.map +1 -1
- package/dist/commands/teams.d.ts +25 -5
- package/dist/commands/teams.js +106 -39
- package/dist/commands/teams.js.map +1 -1
- package/dist/commands/workflows.d.ts +37 -0
- package/dist/commands/workflows.js +589 -0
- package/dist/commands/workflows.js.map +1 -0
- package/dist/compatibility.d.ts +10 -1
- package/dist/compatibility.js +10 -1
- package/dist/compatibility.js.map +1 -1
- package/dist/connect-fields.d.ts +22 -0
- package/dist/connect-fields.js +115 -0
- package/dist/connect-fields.js.map +1 -0
- package/dist/context.d.ts +12 -0
- package/dist/context.js +32 -9
- package/dist/context.js.map +1 -1
- package/dist/dev-experience.d.ts +125 -0
- package/dist/dev-experience.js +128 -0
- package/dist/dev-experience.js.map +1 -0
- package/dist/experience/boundary.d.ts +12 -0
- package/dist/experience/boundary.js +260 -0
- package/dist/experience/boundary.js.map +1 -0
- package/dist/experience/build.d.ts +16 -0
- package/dist/experience/build.js +90 -0
- package/dist/experience/build.js.map +1 -0
- package/dist/experience/checks.d.ts +29 -0
- package/dist/experience/checks.js +133 -0
- package/dist/experience/checks.js.map +1 -0
- package/dist/experience/contract-sources.d.ts +36 -0
- package/dist/experience/contract-sources.js +111 -0
- package/dist/experience/contract-sources.js.map +1 -0
- package/dist/experience/definition-checks.d.ts +26 -0
- package/dist/experience/definition-checks.js +201 -0
- package/dist/experience/definition-checks.js.map +1 -0
- package/dist/experience/definition-shape.d.ts +60 -0
- package/dist/experience/definition-shape.js +2 -0
- package/dist/experience/definition-shape.js.map +1 -0
- package/dist/experience/init.d.ts +10 -0
- package/dist/experience/init.js +64 -0
- package/dist/experience/init.js.map +1 -0
- package/dist/experience/integrations-codegen.d.ts +17 -0
- package/dist/experience/integrations-codegen.js +51 -0
- package/dist/experience/integrations-codegen.js.map +1 -0
- package/dist/experience/json-schema-to-ts.d.ts +1 -0
- package/dist/experience/json-schema-to-ts.js +90 -0
- package/dist/experience/json-schema-to-ts.js.map +1 -0
- package/dist/experience/load-experience.d.ts +23 -0
- package/dist/experience/load-experience.js +115 -0
- package/dist/experience/load-experience.js.map +1 -0
- package/dist/experience/overrides.d.ts +8 -0
- package/dist/experience/overrides.js +21 -0
- package/dist/experience/overrides.js.map +1 -0
- package/dist/experience/pin-integration.d.ts +8 -0
- package/dist/experience/pin-integration.js +17 -0
- package/dist/experience/pin-integration.js.map +1 -0
- package/dist/experience/pin-ops.d.ts +12 -0
- package/dist/experience/pin-ops.js +36 -0
- package/dist/experience/pin-ops.js.map +1 -0
- package/dist/experience/pins.d.ts +35 -0
- package/dist/experience/pins.js +91 -0
- package/dist/experience/pins.js.map +1 -0
- package/dist/experience/project.d.ts +52 -0
- package/dist/experience/project.js +149 -0
- package/dist/experience/project.js.map +1 -0
- package/dist/experience/publish.d.ts +51 -0
- package/dist/experience/publish.js +144 -0
- package/dist/experience/publish.js.map +1 -0
- package/dist/experience/regenerate.d.ts +10 -0
- package/dist/experience/regenerate.js +33 -0
- package/dist/experience/regenerate.js.map +1 -0
- package/dist/experience/report.d.ts +9 -0
- package/dist/experience/report.js +23 -0
- package/dist/experience/report.js.map +1 -0
- package/dist/harness-scaffold.d.ts +52 -18
- package/dist/harness-scaffold.js +189 -9
- package/dist/harness-scaffold.js.map +1 -1
- package/dist/index.d.ts +13 -0
- package/dist/index.js +494 -127
- package/dist/index.js.map +1 -1
- package/dist/invocation.d.ts +31 -0
- package/dist/invocation.js +58 -0
- package/dist/invocation.js.map +1 -0
- package/dist/project-checks.d.ts +12 -0
- package/dist/project-checks.js +46 -0
- package/dist/project-checks.js.map +1 -1
- package/dist/project.d.ts +14 -0
- package/dist/project.js +10 -0
- package/dist/project.js.map +1 -1
- package/dist/repo/publish.d.ts +42 -0
- package/dist/repo/publish.js +225 -0
- package/dist/repo/publish.js.map +1 -0
- package/dist/repo/scaffold.d.ts +30 -0
- package/dist/repo/scaffold.js +165 -0
- package/dist/repo/scaffold.js.map +1 -0
- package/dist/runs-api.js +8 -3
- package/dist/runs-api.js.map +1 -1
- package/dist/safe-fs.d.ts +18 -0
- package/dist/safe-fs.js +57 -0
- package/dist/safe-fs.js.map +1 -1
- package/dist/secret-form.d.ts +48 -0
- package/dist/secret-form.js +212 -0
- package/dist/secret-form.js.map +1 -0
- package/dist/secret-input.d.ts +96 -0
- package/dist/secret-input.js +299 -0
- package/dist/secret-input.js.map +1 -0
- package/dist/team-connect-api.d.ts +78 -3
- package/dist/team-connect-api.js +17 -2
- package/dist/team-connect-api.js.map +1 -1
- package/dist/team-lifecycle-api.d.ts +435 -0
- package/dist/team-lifecycle-api.js +301 -0
- package/dist/team-lifecycle-api.js.map +1 -0
- package/dist/teams-api.d.ts +49 -1
- package/dist/teams-api.js +149 -27
- package/dist/teams-api.js.map +1 -1
- package/dist/unknown-command.d.ts +18 -0
- package/dist/unknown-command.js +50 -0
- package/dist/unknown-command.js.map +1 -0
- package/dist/validate-findings.js +2 -1
- package/dist/validate-findings.js.map +1 -1
- package/dist/workflows-api.d.ts +69 -0
- package/dist/workflows-api.js +182 -0
- package/dist/workflows-api.js.map +1 -0
- package/package.json +3 -3
- package/templates/AGENTS.md.tmpl +6 -4
- package/templates/claude-skill.md.tmpl +4 -1
- package/templates/ekanos.json.tmpl +1 -0
- package/templates/experience/AGENTS.md.tmpl +22 -0
- package/templates/experience/ekanos.json.tmpl +7 -0
- package/templates/experience/ekanos.lock.json.tmpl +4 -0
- package/templates/experience/eslint.config.mjs.tmpl +25 -0
- package/templates/experience/gitignore.tmpl +17 -0
- package/templates/experience/package.json.tmpl +41 -0
- package/templates/experience/src/.ekanos/integrations.d.ts.tmpl +3 -0
- package/templates/experience/src/experience.ts.tmpl +30 -0
- package/templates/experience/src/widgets/hello-widget.tsx.tmpl +40 -0
- package/templates/experience/tsconfig.json.tmpl +20 -0
- package/templates/harness/app/%5F%5Fekanos/api/[...path]/route.ts.tmpl +9 -0
- package/templates/harness/app/[slug]/activation/page.tsx.tmpl +1 -1
- package/templates/harness/app/[slug]/page.tsx.tmpl +1 -1
- package/templates/harness/app/[slug]/tile/page.tsx.tmpl +1 -1
- package/templates/harness/app/[slug]/triggers/page.tsx.tmpl +1 -1
- package/templates/harness/app/[slug]/widgets/[widgetId]/page.tsx.tmpl +1 -1
- package/templates/harness/app/[slug]/widgets/page.tsx.tmpl +1 -1
- package/templates/harness/app/experience/layout.tsx.tmpl +17 -0
- package/templates/harness/app/experience/page.tsx.tmpl +1 -0
- package/templates/harness/app/experience/pages/[id]/page.tsx.tmpl +1 -0
- package/templates/harness/app/experience/review-queue/page.tsx.tmpl +1 -0
- package/templates/harness/app/experience/runs/page.tsx.tmpl +1 -0
- package/templates/harness/app/experience/widgets/[id]/page.tsx.tmpl +1 -0
- package/templates/harness/app/experience/widgets/page.tsx.tmpl +1 -0
- package/templates/harness/app/experience/workflows/[id]/page.tsx.tmpl +1 -0
- package/templates/harness/app/experience/workflows/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/connect/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/events/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/health/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/operations/[kind]/[name]/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/operations/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/preview/activation/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/preview/layout.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/preview/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/preview/tile/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/preview/triggers/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/preview/widgets/[widgetId]/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/preview/widgets/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/runs/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/layout.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/page.tsx.tmpl +1 -0
- package/templates/harness/app/page.experience.tsx.tmpl +5 -0
- package/templates/harness/repo/app/%5F%5Fekanos/api/[...path]/route.ts.tmpl +11 -0
- package/templates/harness/repo/app/(repo)/connections/page.tsx.tmpl +1 -0
- package/templates/harness/repo/app/(repo)/layout.tsx.tmpl +1 -0
- package/templates/harness/repo/app/(repo)/page.tsx.tmpl +1 -0
- package/templates/harness/repo/app/experiences/[name]/connect/page.tsx.tmpl +1 -0
- package/templates/harness/repo/app/experiences/[name]/layout.tsx.tmpl +9 -0
- package/templates/harness/repo/app/experiences/page.tsx.tmpl +5 -0
- package/templates/harness/repo/app/harness-shell.tsx.tmpl +9 -0
- package/templates/harness/repo/app/integrations/[slug]/layout.tsx.tmpl +1 -0
- package/templates/harness/repo/app/integrations/page.tsx.tmpl +5 -0
- package/templates/harness/repo/app/repo-experiences.ts.tmpl +5 -0
- package/templates/harness/styles/globals.css.tmpl +15 -1
- package/templates/package.json.tmpl +4 -4
- package/templates/skills/build-agent/SKILL.md +43 -10
- package/templates/skills/build-agent/references/agent-json.md +4 -1
- package/templates/skills/build-agent/references/app-setup.md +14 -7
- package/templates/skills/build-agent/references/rollout.md +26 -2
- package/templates/skills/build-agent/references/set-up-an-integration.md +46 -29
- package/templates/skills/build-integration/references/widget-design.md +1 -1
- package/templates/skills/ekanos-platform/SKILL.md +66 -14
- package/templates/skills/polish-widgets/references/patterns.md +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apps.js","sourceRoot":"","sources":["../../src/commands/apps.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ProviderAppStatus } from '@ekanos/integration-schema';\n\nimport {\n type AppsApiResult,\n setProviderApp,\n showProviderApp,\n} from '../apps-api';\nimport type { StoredSession } from '../auth/credential-store';\nimport { loginHint } from '../auth/host-trust';\nimport {\n type AuthEnvironment,\n refreshStoredSession,\n requireSession,\n resolveAuthEnvironment,\n} from '../auth/session';\nimport {\n type ConnectionsApiResult,\n type SourceConnection,\n deleteConnection,\n listConnections,\n showConnection,\n startConnection,\n} from '../connections-api';\nimport type { CliContext } from '../context';\nimport {\n authRequiredError,\n invalidStateError,\n usageError,\n validationError,\n} from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport { resolveSourceTarget } from '../source-target';\nimport type { ResultRow } from '../ui';\nimport { promptYesNo } from './publish';\n\nexport const APPS_SUBCOMMANDS = [\n 'show',\n 'set',\n 'list',\n 'connect',\n 'disconnect',\n] as const;\ntype AppsSubcommand = (typeof APPS_SUBCOMMANDS)[number];\n\nexport interface AppsArgs {\n host?: string;\n source?: string;\n subcommand?: string;\n product?: string;\n dir: string;\n env: Record<string, string | undefined>;\n stdinIsTTY?: boolean;\n /** Test seams for the questions `set` and `connect` ask. */\n ask?: (question: string) => Promise<string>;\n askSecret?: (question: string) => Promise<string>;\n confirm?: (question: string) => Promise<boolean>;\n /** Test seam: `connect`'s wait between status polls. */\n pollDelayMs?: number;\n /** `connect --no-wait`: print the URL and return without polling. */\n noWait?: boolean;\n /** `disconnect --yes`: confirm without the question (a script, an agent run). */\n yes?: boolean;\n}\n\n/**\n * `apps` — a Source's provider apps: the OAuth client an integration signs\n * every team in through (Linear's, say). `show` says whether the Source has\n * one and which callback URL to register; `set` takes the client id and\n * secret from the Source admin at the terminal — either on its own, Enter\n * keeping the saved one — never from a flag, a file or a non-interactive\n * run, so an agent driving the CLI never handles the secret.\n */\nexport async function runApps(\n ctx: CliContext,\n args: AppsArgs,\n): Promise<ExitCode> {\n const subcommand = parseSubcommand(args.subcommand);\n if (subcommand === 'list') return runList(ctx, args);\n const product = requireProduct(args.product, subcommand);\n if (subcommand === 'connect' || subcommand === 'disconnect') {\n return runConnection(ctx, args, subcommand, product);\n }\n\n if (subcommand === 'set' && !canPrompt(ctx, args)) {\n throw usageError(\n 'apps set takes the client secret at a terminal, never in a script or an agent run.',\n `Run it yourself in your terminal: npx @ekanos/cli apps set ${product}${args.source ? ` --source ${args.source}` : ''}`,\n );\n }\n\n const env = resolveAuthEnvironment(ctx, args.host, args.env, {\n projectDir: args.dir,\n });\n const resolved = await resolveSourceTarget(env, requireSession(env), args);\n const client = new AppsClient(env, resolved.session);\n const source = resolved.source;\n\n if (subcommand === 'show') {\n return showApp(ctx, env.host, client, source, product);\n }\n\n const status = await client.call((token) =>\n showProviderApp(env.host, token, source, product),\n );\n\n ctx.log(walkthrough(status).join('\\n'));\n\n // Either credential on its own: Enter keeps what is saved. An older host\n // sends no `fields`; then `configured` says whether both are saved.\n const saved = (name: 'clientId' | 'clientSecret') =>\n status.fields?.find((field) => field.name === name) ?? {\n set: status.configured,\n value: null,\n };\n const savedId = saved('clientId');\n const savedSecret = saved('clientSecret');\n const clientId = (\n await (args.ask ?? promptLine)(\n savedId.set\n ? `Client ID (current: ${savedId.value ?? 'saved'} — Enter to keep): `\n : 'Client ID: ',\n )\n ).trim();\n const clientSecret = (\n await (args.askSecret ?? promptHidden)(\n savedSecret.set\n ? 'Client secret (saved — Enter to keep, hidden): '\n : 'Client secret (hidden): ',\n )\n ).trim();\n if (!clientId && !clientSecret) {\n throw validationError(\n 'Nothing was changed.',\n `Run \"ekanos apps show ${product}\" to see the current state.`,\n );\n }\n\n const result = await client.call((token) =>\n setProviderApp(env.host, token, {\n source,\n product,\n ...(clientId ? { clientId } : {}),\n ...(clientSecret ? { clientSecret } : {}),\n }),\n );\n return ctx.succeed(\n { host: env.host, ...result },\n ctx.ui.result({\n title: result.replaced\n ? `Updated the ${result.product.name} app`\n : `Set up the ${result.product.name} app`,\n rows: [\n ['Source', result.source.slug],\n ...providerFieldRows(result),\n ['Teams can connect', result.configured ? 'yes' : 'not yet'],\n ['Callback URLs', callbackUrls(result)],\n ],\n }),\n );\n}\n\n/**\n * How to create the app: the integration's own steps (`oauth.setup`, with the\n * callback URL filled in) when it declares them, else the generic three.\n */\nexport function walkthrough(status: ProviderAppStatus): string[] {\n const name = status.product.name;\n const lines = [`${name} app for ${status.source.slug}`];\n if (status.setup?.consoleUrl) {\n lines.push(` Open: ${status.setup.consoleUrl}`);\n }\n const steps = status.setup?.steps.length\n ? [\n ...status.setup.steps,\n `Check the app lists exactly: ${callbackUrls(status).join(', ')}`,\n ]\n : [\n `In ${name}, create an OAuth app (or open the one you use).`,\n `Register exactly these callback URLs: ${callbackUrls(status).join(', ')}`,\n ];\n steps.push(\n \"Enter its client ID and secret below. The secret is stored in Ekanos's vault and never shown again.\",\n );\n lines.push(...steps.map((step, index) => ` ${index + 1}. ${step}`));\n if (status.setup?.guideUrl) lines.push(` Guide: ${status.setup.guideUrl}`);\n return lines;\n}\n\nfunction summary(ctx: CliContext, status: ProviderAppStatus): string {\n const rows: ResultRow[] = [\n ['Source', status.source.slug],\n ...(status.setup\n ? ([\n [\n 'How to create it',\n [\n ...(status.setup.consoleUrl\n ? [`Open ${status.setup.consoleUrl}`]\n : []),\n ...status.setup.steps.map(\n (step, index) => `${index + 1}. ${step}`,\n ),\n ],\n ],\n ] as const)\n : []),\n ...providerFieldRows(status),\n [\n 'App ready',\n status.configured\n ? 'yes — teams can connect'\n : 'no — no team can connect yet',\n ],\n ['Callback URLs', callbackUrls(status)],\n ];\n return [\n ctx.ui.result({ title: `${status.product.name} app`, rows }),\n ...(status.configured\n ? []\n : [\n ctx.ui.hint(\n `Run \"ekanos apps set ${status.product.slug}\" in your terminal to enter its credentials.`,\n ),\n ]),\n ].join('\\n');\n}\n\n/**\n * `apps show <product>`: the Source provider app, and — for an integration\n * that supports one — the Source connection (plan 241). A `teamApp`\n * integration (Zendesk) has no provider app but can have a Source\n * connection, so either half may be absent.\n */\nasync function showApp(\n ctx: CliContext,\n host: string,\n client: AppsClient,\n source: string,\n product: string,\n): Promise<ExitCode> {\n const [app, connection] = await Promise.all([\n client\n .call((token) => showProviderApp(host, token, source, product))\n .then(\n (status) => ({ ok: true as const, status }),\n (error: unknown) => ({ ok: false as const, error }),\n ),\n // A host without the connections routes (before plan 241), or one that\n // refuses, leaves `show` exactly as it was: the provider app alone.\n client\n .connection((token) => showConnection(host, token, source, product))\n .catch(() => ({ status: 'unavailable' as const })),\n ]);\n\n if (!app.ok && connection.status !== 'ok') throw app.error;\n\n const parts: string[] = [];\n if (app.ok) parts.push(summary(ctx, app.status));\n if (connection.status === 'ok') {\n parts.push(\n connectionSummary(ctx, connection.data.connection, {\n sourceSlug: connection.data.source.slug,\n callbackUrls: connection.data.callbackUrls,\n }),\n );\n }\n\n return ctx.succeed(\n {\n host,\n ...(app.ok ? app.status : {}),\n ...(connection.status === 'ok'\n ? {\n sourceConnection: connection.data.connection,\n sourceConnectionCallbackUrls: connection.data.callbackUrls,\n }\n : {}),\n },\n parts.join('\\n'),\n );\n}\n\n/** `apps list`: every integration the Source can connect once, with status. */\nasync function runList(ctx: CliContext, args: AppsArgs): Promise<ExitCode> {\n const { env, client, source } = await openClient(ctx, args);\n const result = await client.connection((token) =>\n listConnections(env.host, token, source),\n );\n if (result.status !== 'ok') {\n throw invalidStateError(\n 'The host could not list the connections.',\n 'Retry shortly.',\n );\n }\n const { connections } = result.data;\n const rows: ResultRow[] = connections.map((connection) => [\n `${connection.name} (${connection.slug})`,\n connectionState(connection),\n ]);\n return ctx.succeed(\n { host: env.host, ...result.data },\n connections.length === 0\n ? ctx.ui.hint(\n `No integration on ${result.data.source.slug} supports one connection for the whole Source yet.`,\n )\n : ctx.ui.result({\n title: `Source connections on ${result.data.source.slug}`,\n rows,\n }),\n );\n}\n\nfunction connectionState(connection: SourceConnection): string {\n if (connection.connected) {\n return [\n 'connected',\n connection.connectedAt ? ` ${connection.connectedAt}` : '',\n connection.connectedBy ? ` by ${connection.connectedBy}` : '',\n ].join('');\n }\n return connection.missing.length > 0\n ? `not connected — app fields missing: ${connection.missing.join(', ')}`\n : 'not connected';\n}\n\n/**\n * `apps connect <product>`: connect the integration ONCE for the whole Source,\n * for the Source's provided agents whose template says `owner: \"source\"`.\n * Asks for any missing app fields at the terminal (secrets hidden, never from\n * a flag), prints the provider's consent URL, then waits until the browser\n * finishes. `apps disconnect <product>` removes it.\n */\nasync function runConnection(\n ctx: CliContext,\n args: AppsArgs,\n subcommand: 'connect' | 'disconnect',\n product: string,\n): Promise<ExitCode> {\n const { env, client, source } = await openClient(ctx, args);\n\n if (subcommand === 'disconnect') {\n return disconnect(ctx, args, client, env.host, source, product);\n }\n\n const shown = await client.connection((token) =>\n showConnection(env.host, token, source, product),\n );\n if (shown.status === 'unsupported') {\n throw invalidStateError(\n shown.message,\n `Each team connects ${product} itself: \"ekanos teams connect <team> ${product}\".`,\n );\n }\n if (shown.status !== 'ok') {\n throw invalidStateError(\n 'The host could not read the connection.',\n 'Retry shortly.',\n );\n }\n const current = shown.data.connection;\n\n if (current.app === 'fields') {\n ctx.log(\n [\n `${current.name} app for ${shown.data.source.slug} (one for the whole Source)`,\n ` Register this redirect URL in the app: ${shown.data.callbackUrls.join(', ')}`,\n ].join('\\n'),\n );\n }\n\n const fields = await askFields(ctx, args, current, product);\n\n const started = await client.connection((token) =>\n startConnection(env.host, token, {\n source,\n product,\n ...(Object.keys(fields).length > 0 ? { fields } : {}),\n }),\n );\n if (started.status === 'not-configured') {\n throw validationError(\n `${current.name} is not set up for the Source yet — missing: ${started.missing.join(', ')}.`,\n current.app === 'source-app'\n ? `Run \"ekanos apps set ${product}\" to enter the Source's app first.`\n : `Run \"ekanos apps connect ${product}\" again and fill every field.`,\n );\n }\n if (started.status !== 'ok') {\n throw invalidStateError(\n 'The host could not start the connection.',\n 'Retry shortly.',\n );\n }\n\n ctx.log(\n [\n `Open this link and approve ${current.name} as the account the Source's agents should act as:`,\n ` ${started.data.authorizeUrl}`,\n ].join('\\n'),\n );\n\n if (args.noWait || ctx.jsonMode) {\n return ctx.succeed(\n {\n host: env.host,\n product,\n authorizeUrl: started.data.authorizeUrl,\n callbackUrl: started.data.callbackUrl,\n connected: false,\n },\n ctx.ui.hint(`Then check with \"ekanos apps show ${product}\".`),\n );\n }\n\n const deadline = Date.now() + 10 * 60 * 1000;\n const before = current.connectedAt;\n while (Date.now() < deadline) {\n await new Promise((resolve) =>\n setTimeout(resolve, args.pollDelayMs ?? 3000),\n );\n const polled = await client.connection((token) =>\n showConnection(env.host, token, source, product),\n );\n if (\n polled.status === 'ok' &&\n polled.data.connection.connected &&\n polled.data.connection.connectedAt !== before\n ) {\n return ctx.succeed(\n { host: env.host, product, connection: polled.data.connection },\n connectionSummary(ctx, polled.data.connection, {\n sourceSlug: polled.data.source.slug,\n callbackUrls: polled.data.callbackUrls,\n }),\n );\n }\n }\n throw validationError(\n 'The connection did not finish within ten minutes.',\n `Run \"ekanos apps connect ${product}\" again for a fresh link.`,\n );\n}\n\nasync function askFields(\n ctx: CliContext,\n args: AppsArgs,\n current: SourceConnection,\n product: string,\n): Promise<Record<string, string>> {\n const toAsk = current.fields.filter(\n (field) => !field.set || current.missing.includes(field.name),\n );\n if (toAsk.length === 0) return {};\n if (!canPrompt(ctx, args)) {\n throw usageError(\n `${current.name} needs its app fields entered for the Source: ${toAsk.map((field) => field.label).join(', ')}.`,\n `Run it yourself in your terminal: npx @ekanos/cli apps connect ${product}${args.source ? ` --source ${args.source}` : ''}`,\n );\n }\n const fields: Record<string, string> = {};\n for (const field of toAsk) {\n const question = field.sensitive\n ? `${field.label} (hidden): `\n : `${field.label}: `;\n const value = (\n await (\n field.sensitive\n ? (args.askSecret ?? promptHidden)\n : (args.ask ?? promptLine)\n )(question)\n ).trim();\n if (value) fields[field.name] = value;\n }\n return fields;\n}\n\nasync function disconnect(\n ctx: CliContext,\n args: AppsArgs,\n client: AppsClient,\n host: string,\n source: string,\n product: string,\n): Promise<ExitCode> {\n if (!args.yes && !canPrompt(ctx, args)) {\n throw invalidStateError(\n `Disconnecting ${product} on ${source} stops it for every team's provided agents that use the Source connection, until someone connects it again.`,\n `Re-run with --yes: ekanos apps disconnect ${product} --source ${source} --yes`,\n );\n }\n if (!args.yes) {\n const sure = await (args.confirm ?? promptYesNo)(\n `Disconnect ${product} for every team's provided agents on ${source}? [y/N]`,\n );\n if (!sure) {\n throw validationError(\n 'Nothing was changed.',\n `Run \"ekanos apps show ${product}\" to see the current state.`,\n );\n }\n }\n const result = await client.connection((token) =>\n deleteConnection(host, token, source, product),\n );\n if (result.status === 'unsupported') {\n throw invalidStateError(\n result.message,\n `Each team connects ${product} itself: \"ekanos teams connect <team> ${product}\".`,\n );\n }\n if (result.status !== 'ok') {\n throw invalidStateError('The host could not disconnect.', 'Retry shortly.');\n }\n return ctx.succeed(\n { host, product, ...result.data },\n ctx.ui.result({\n title: result.data.removed\n ? `Disconnected the ${product} Source connection on ${source}`\n : `${product} had no Source connection on ${source}`,\n rows: [\n [\n 'Provided agents',\n 'their tools for this product stop until you connect again',\n ],\n ],\n }),\n );\n}\n\nfunction connectionSummary(\n ctx: CliContext,\n connection: SourceConnection,\n meta: { sourceSlug: string; callbackUrls: string[] },\n): string {\n const rows: ResultRow[] = [\n ['Source', meta.sourceSlug],\n ['Connected', connectionState(connection)],\n ...(connection.scope ? ([['Scope', connection.scope]] as ResultRow[]) : []),\n ...(connection.fields.length > 0\n ? ([\n [\n 'App fields',\n connection.fields.map(\n (field) =>\n `${field.label}: ${field.set ? (field.value ?? 'set') : 'missing'}`,\n ),\n ],\n ] as ResultRow[])\n : []),\n ['Redirect URL', meta.callbackUrls],\n [\n 'Used by',\n `provided agents whose template says connections.${connection.slug}.owner: \"source\", in every team`,\n ],\n ];\n return [\n ctx.ui.result({\n title: `${connection.name} — Source connection (one for every team's provided agents)`,\n rows,\n }),\n ...(connection.connected\n ? []\n : [\n ctx.ui.hint(\n `Run \"ekanos apps connect ${connection.slug}\" in your terminal to connect it.`,\n ),\n ]),\n ].join('\\n');\n}\n\nasync function openClient(ctx: CliContext, args: AppsArgs) {\n const env = resolveAuthEnvironment(ctx, args.host, args.env, {\n projectDir: args.dir,\n });\n const resolved = await resolveSourceTarget(env, requireSession(env), args);\n return {\n env,\n client: new AppsClient(env, resolved.session),\n source: resolved.source,\n };\n}\n\nclass AppsClient {\n constructor(\n private readonly env: AuthEnvironment,\n private session: StoredSession,\n ) {}\n\n async call<T>(\n send: (accessToken: string) => Promise<AppsApiResult<T>>,\n ): Promise<T> {\n let result = await send(this.session.accessToken);\n if (result.status === 'unauthorized') {\n this.session = await refreshStoredSession(this.env, this.session);\n result = await send(this.session.accessToken);\n }\n if (result.status === 'ok') return result.data;\n throw authRequiredError(\n `The session for ${this.env.host} could not authorize the apps call.`,\n loginHint(this.env),\n );\n }\n\n /** As `call`, for the connections client, whose 409s are answers. */\n async connection<T>(\n send: (accessToken: string) => Promise<ConnectionsApiResult<T>>,\n ): Promise<Exclude<ConnectionsApiResult<T>, { status: 'unauthorized' }>> {\n let result = await send(this.session.accessToken);\n if (result.status === 'unauthorized') {\n this.session = await refreshStoredSession(this.env, this.session);\n result = await send(this.session.accessToken);\n }\n if (result.status !== 'unauthorized') return result;\n throw authRequiredError(\n `The session for ${this.env.host} could not authorize the connections call.`,\n loginHint(this.env),\n );\n }\n}\n\nfunction canPrompt(ctx: CliContext, args: AppsArgs): boolean {\n return !ctx.jsonMode && (args.stdinIsTTY ?? process.stdin.isTTY === true);\n}\n\nfunction parseSubcommand(value: string | undefined): AppsSubcommand {\n const match = APPS_SUBCOMMANDS.find((name) => name === value);\n if (match) return match;\n throw usageError(\n value ? `Unknown apps subcommand \"${value}\".` : 'apps needs a subcommand.',\n `Run one of: ${APPS_SUBCOMMANDS.map((name) => `ekanos apps ${name} <product>`).join(', ')}.`,\n );\n}\n\nfunction requireProduct(value: string | undefined, verb: string): string {\n const slug = value?.trim().toLowerCase();\n if (slug && /^[a-z0-9][a-z0-9-]*$/.test(slug)) return slug;\n throw usageError(\n value\n ? `\"${value}\" is not a product slug.`\n : `apps ${verb} needs a product.`,\n `Pass the product's slug, e.g. \"ekanos apps ${verb} linear\". \"ekanos catalog\" lists them.`,\n );\n}\n\nexport async function promptLine(question: string): Promise<string> {\n const readline = await import('node:readline/promises');\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stderr,\n });\n try {\n return await rl.question(question);\n } finally {\n rl.close();\n }\n}\n\n/**\n * Read a line without echoing it: the secret never appears on screen or in\n * scrollback. The question is always printed; only the typed characters are\n * hidden (each shows as `*`, so a paste visibly landed).\n *\n * Raw mode by hand rather than readline: a terminal readline redraws its\n * line on `question()` — cursor to column 0, clear to the end of the screen —\n * which erased the question written before it, so the terminal sat on an\n * empty line and a hidden field looked skipped.\n */\nexport async function promptHidden(question: string): Promise<string> {\n const stdin = process.stdin;\n const stderr = process.stderr;\n stderr.write(question);\n\n if (!stdin.isTTY) {\n // Piped stdin echoes nothing: read one line as is.\n const readline = await import('node:readline/promises');\n const rl = readline.createInterface({ input: stdin, terminal: false });\n try {\n return await rl.question('');\n } finally {\n rl.close();\n stderr.write('\\n');\n }\n }\n\n return new Promise<string>((resolve) => {\n let value = '';\n let inEscape = false;\n const wasRaw = stdin.isRaw;\n const finish = () => {\n stdin.off('data', onData);\n stdin.setRawMode(wasRaw);\n stdin.pause();\n stderr.write('\\n');\n };\n const onData = (chunk: Buffer | string) => {\n for (const char of typeof chunk === 'string'\n ? chunk\n : chunk.toString('utf8')) {\n if (inEscape) {\n // An escape sequence (an arrow key) ends at its final letter.\n if (/[A-Za-z~]/.test(char)) inEscape = false;\n continue;\n }\n if (char === '\\u001b') {\n inEscape = true;\n continue;\n }\n if (char === '\\r' || char === '\\n' || char === '\\u0004') {\n finish();\n resolve(value);\n return;\n }\n if (char === '\\u0003') {\n // Ctrl-C: raw mode swallowed the signal, so leave as SIGINT would.\n finish();\n process.exit(130);\n }\n if (char === '\\u007f' || char === '\\b') {\n if (value.length > 0) {\n value = value.slice(0, -1);\n stderr.write('\\b \\b');\n }\n continue;\n }\n if (char === '\\u0015') {\n // Ctrl-U: clear what was typed.\n stderr.write('\\b \\b'.repeat(value.length));\n value = '';\n continue;\n }\n if (char < ' ') continue;\n value += char;\n stderr.write('*');\n }\n };\n stdin.setRawMode(true);\n stdin.resume();\n stdin.on('data', onData);\n });\n}\n\n/** Each credential's state: the client id's value, the secret as saved or not. */\nfunction providerFieldRows(status: ProviderAppStatus): ResultRow[] {\n return (status.fields ?? []).map((field) => [\n field.label,\n !field.set\n ? 'not set'\n : field.sensitive\n ? 'saved'\n : (field.value ?? 'saved'),\n ]);\n}\n\n/** Every redirect URI to register; an older host sends only the one. */\nfunction callbackUrls(status: ProviderAppStatus): string[] {\n return status.callbackUrls?.length\n ? status.callbackUrls\n : [status.callbackUrl];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"apps.js","sourceRoot":"","sources":["../../src/commands/apps.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ProviderAppStatus } from '@ekanos/integration-schema';\n\nimport {\n type AppsApiResult,\n setProviderApp,\n showProviderApp,\n} from '../apps-api';\nimport type { StoredSession } from '../auth/credential-store';\nimport { loginHint } from '../auth/host-trust';\nimport {\n type AuthEnvironment,\n refreshStoredSession,\n requireSession,\n resolveAuthEnvironment,\n} from '../auth/session';\nimport {\n type ConnectionsApiResult,\n type SourceConnection,\n deleteConnection,\n listConnections,\n showConnection,\n startConnection,\n} from '../connections-api';\nimport type { CliContext } from '../context';\nimport {\n authRequiredError,\n invalidStateError,\n usageError,\n validationError,\n} from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport { cli } from '../invocation';\nimport {\n type SecretIO,\n collectSecrets,\n parsePlainValues,\n readSecretFlags,\n secretInputGiven,\n} from '../secret-input';\nimport { resolveSourceTarget } from '../source-target';\nimport type { ResultRow } from '../ui';\nimport { promptYesNo } from './publish';\n\nexport const APPS_SUBCOMMANDS = [\n 'show',\n 'set',\n 'list',\n 'connect',\n 'disconnect',\n] as const;\ntype AppsSubcommand = (typeof APPS_SUBCOMMANDS)[number];\n\nexport interface AppsArgs {\n host?: string;\n source?: string;\n subcommand?: string;\n product?: string;\n dir: string;\n env: Record<string, string | undefined>;\n stdinIsTTY?: boolean;\n /** Test seams for the questions `set` and `connect` ask. */\n ask?: (question: string) => Promise<string>;\n askSecret?: (question: string) => Promise<string>;\n confirm?: (question: string) => Promise<boolean>;\n /** Test seam: `connect`'s wait between status polls. */\n pollDelayMs?: number;\n /** `connect --no-wait`: print the URL and return without polling. */\n noWait?: boolean;\n /** `disconnect --yes`: confirm without the question (a script, an agent run). */\n yes?: boolean;\n /** Every parsed flag: the secret-input flags and `set --set clientId=…`. */\n flags?: Record<string, string | boolean | string[]>;\n /** Test seams for the secret-input flags (`secret-input.ts`). */\n readStdin?: () => Promise<string>;\n openUrl?: (url: string) => void;\n secretFormTimeoutMs?: number;\n}\n\n/**\n * `apps` — a Source's provider apps: the OAuth client an integration signs\n * every team in through (Linear's, say). `show` says whether the Source has\n * one and which callback URL to register; `set` takes the client id and\n * secret — either on its own, the other keeping its saved value — at the\n * terminal with hidden input, or, with no terminal, from `--set clientId=…`\n * and the secret-input flags (`--secret-env`, `--secret-file`,\n * `--secret-stdin`, `--browser`; see `secret-input.ts`). Never as a value in\n * argv, so it lands in no shell history and no agent's context.\n */\nexport async function runApps(\n ctx: CliContext,\n args: AppsArgs,\n): Promise<ExitCode> {\n const subcommand = parseSubcommand(args.subcommand);\n if (subcommand === 'list') return runList(ctx, args);\n const product = requireProduct(args.product, subcommand);\n if (subcommand === 'connect' || subcommand === 'disconnect') {\n return runConnection(ctx, args, subcommand, product);\n }\n\n const secret = readSecretFlags(args.flags);\n const plain =\n subcommand === 'set'\n ? parsePlainValues(args.flags?.set, 'clientId=abc123')\n : {};\n for (const name of Object.keys(plain)) {\n if (name === 'clientId') continue;\n throw usageError(\n name === 'clientSecret'\n ? 'clientSecret is a secret: it is never passed as an argument.'\n : '--set takes clientId=<id> here; the client secret has flags of its own.',\n 'Pass the secret with --secret-env <NAME>, --secret-file <path>, --secret-stdin or --browser.',\n );\n }\n const again = `apps set ${product}${args.source ? ` --source ${args.source}` : ''}`;\n const interactive = canPrompt(ctx, args);\n if (\n subcommand === 'set' &&\n !interactive &&\n !secretInputGiven(secret) &&\n Object.keys(plain).length === 0\n ) {\n throw usageError(\n SET_REFUSAL,\n `Without a terminal, pass --set clientId=<id> and the secret as --secret-env <NAME>, --secret-file <path>, --secret-stdin, or --browser (a form in your browser on this computer). Or run it yourself in your terminal: ${cli()} ${again}`,\n );\n }\n\n const env = resolveAuthEnvironment(ctx, args.host, args.env, {\n projectDir: args.dir,\n });\n const resolved = await resolveSourceTarget(env, requireSession(env), args);\n const client = new AppsClient(env, resolved.session);\n const source = resolved.source;\n\n if (subcommand === 'show') {\n return showApp(ctx, env.host, client, source, product);\n }\n\n const status = await client.call((token) =>\n showProviderApp(env.host, token, source, product),\n );\n\n ctx.log(walkthrough(status).join('\\n'));\n\n // Either credential on its own: Enter keeps what is saved. An older host\n // sends no `fields`; then `configured` says whether both are saved.\n const saved = (name: 'clientId' | 'clientSecret') =>\n status.fields?.find((field) => field.name === name) ?? {\n set: status.configured,\n value: null,\n };\n const savedId = saved('clientId');\n const savedSecret = saved('clientSecret');\n const fields = [\n {\n name: 'clientId',\n label: 'Client ID',\n sensitive: false,\n set: savedId.set,\n value: savedId.value ?? null,\n },\n {\n name: 'clientSecret',\n label: 'Client secret',\n sensitive: true,\n set: savedSecret.set,\n },\n ];\n const collected = await collectSecrets(ctx, {\n fields,\n plain,\n flags: secret,\n io: secretIO(args),\n interactive,\n title: `the ${status.product.name} app on ${status.source.slug}`,\n refusal: SET_REFUSAL,\n again,\n prompt: (field) =>\n field.sensitive\n ? (args.askSecret ?? promptHidden)(\n savedSecret.set\n ? 'Client secret (saved — Enter to keep, hidden): '\n : 'Client secret (hidden): ',\n )\n : (args.ask ?? promptLine)(\n savedId.set\n ? `Client ID (current: ${savedId.value ?? 'saved'} — Enter to keep): `\n : 'Client ID: ',\n ),\n });\n const clientId = collected.clientId ?? '';\n const clientSecret = collected.clientSecret ?? '';\n if (!clientId && !clientSecret) {\n throw validationError(\n 'Nothing was changed.',\n `Run \"ekanos apps show ${product}\" to see the current state.`,\n );\n }\n\n const result = await client.call((token) =>\n setProviderApp(env.host, token, {\n source,\n product,\n ...(clientId ? { clientId } : {}),\n ...(clientSecret ? { clientSecret } : {}),\n }),\n );\n return ctx.succeed(\n { host: env.host, ...result },\n ctx.ui.result({\n title: result.replaced\n ? `Updated the ${result.product.name} app`\n : `Set up the ${result.product.name} app`,\n rows: [\n ['Source', result.source.slug],\n ...providerFieldRows(result),\n ['Teams can connect', result.configured ? 'yes' : 'not yet'],\n ['Callback URLs', callbackUrls(result)],\n ],\n }),\n );\n}\n\n/**\n * How to create the app: the integration's own steps (`oauth.setup`, with the\n * callback URL filled in) when it declares them, else the generic three.\n */\nexport function walkthrough(status: ProviderAppStatus): string[] {\n const name = status.product.name;\n const lines = [`${name} app for ${status.source.slug}`];\n if (status.setup?.consoleUrl) {\n lines.push(` Open: ${status.setup.consoleUrl}`);\n }\n const steps = status.setup?.steps.length\n ? [\n ...status.setup.steps,\n `Check the app lists exactly: ${callbackUrls(status).join(', ')}`,\n ]\n : [\n `In ${name}, create an OAuth app (or open the one you use).`,\n `Register exactly these callback URLs: ${callbackUrls(status).join(', ')}`,\n ];\n steps.push(\n \"Enter its client ID and secret below. The secret is stored in Ekanos's vault and never shown again.\",\n );\n lines.push(...steps.map((step, index) => ` ${index + 1}. ${step}`));\n if (status.setup?.guideUrl) lines.push(` Guide: ${status.setup.guideUrl}`);\n return lines;\n}\n\nfunction summary(ctx: CliContext, status: ProviderAppStatus): string {\n const rows: ResultRow[] = [\n ['Source', status.source.slug],\n ...(status.setup\n ? ([\n [\n 'How to create it',\n [\n ...(status.setup.consoleUrl\n ? [`Open ${status.setup.consoleUrl}`]\n : []),\n ...status.setup.steps.map(\n (step, index) => `${index + 1}. ${step}`,\n ),\n ],\n ],\n ] as const)\n : []),\n ...providerFieldRows(status),\n [\n 'App ready',\n status.configured\n ? 'yes — teams can connect'\n : 'no — no team can connect yet',\n ],\n ['Callback URLs', callbackUrls(status)],\n ];\n return [\n ctx.ui.result({ title: `${status.product.name} app`, rows }),\n ...(status.configured\n ? []\n : [\n ctx.ui.hint(\n `Run \"ekanos apps set ${status.product.slug}\" in your terminal to enter its credentials.`,\n ),\n ]),\n ].join('\\n');\n}\n\n/**\n * `apps show <product>`: the Source provider app, and — for an integration\n * that supports one — the Source connection (plan 241). A `teamApp`\n * integration (Zendesk) has no provider app but can have a Source\n * connection, so either half may be absent.\n */\nasync function showApp(\n ctx: CliContext,\n host: string,\n client: AppsClient,\n source: string,\n product: string,\n): Promise<ExitCode> {\n const [app, connection] = await Promise.all([\n client\n .call((token) => showProviderApp(host, token, source, product))\n .then(\n (status) => ({ ok: true as const, status }),\n (error: unknown) => ({ ok: false as const, error }),\n ),\n // A host without the connections routes (before plan 241), or one that\n // refuses, leaves `show` exactly as it was: the provider app alone.\n client\n .connection((token) => showConnection(host, token, source, product))\n .catch(() => ({ status: 'unavailable' as const })),\n ]);\n\n if (!app.ok && connection.status !== 'ok') throw app.error;\n\n const parts: string[] = [];\n if (app.ok) parts.push(summary(ctx, app.status));\n if (connection.status === 'ok') {\n parts.push(\n connectionSummary(ctx, connection.data.connection, {\n sourceSlug: connection.data.source.slug,\n callbackUrls: connection.data.callbackUrls,\n }),\n );\n }\n\n return ctx.succeed(\n {\n host,\n ...(app.ok ? app.status : {}),\n ...(connection.status === 'ok'\n ? {\n sourceConnection: connection.data.connection,\n sourceConnectionCallbackUrls: connection.data.callbackUrls,\n }\n : {}),\n },\n parts.join('\\n'),\n );\n}\n\n/** `apps list`: every integration the Source can connect once, with status. */\nasync function runList(ctx: CliContext, args: AppsArgs): Promise<ExitCode> {\n const { env, client, source } = await openClient(ctx, args);\n const result = await client.connection((token) =>\n listConnections(env.host, token, source),\n );\n if (result.status !== 'ok') {\n throw invalidStateError(\n 'The host could not list the connections.',\n 'Retry shortly.',\n );\n }\n const { connections } = result.data;\n const rows: ResultRow[] = connections.map((connection) => [\n `${connection.name} (${connection.slug})`,\n connectionState(connection),\n ]);\n return ctx.succeed(\n { host: env.host, ...result.data },\n connections.length === 0\n ? ctx.ui.hint(\n `No integration on ${result.data.source.slug} supports one connection for the whole Source yet.`,\n )\n : ctx.ui.result({\n title: `Source connections on ${result.data.source.slug}`,\n rows,\n }),\n );\n}\n\nfunction connectionState(connection: SourceConnection): string {\n if (connection.connected) {\n return [\n 'connected',\n connection.connectedAt ? ` ${connection.connectedAt}` : '',\n connection.connectedBy ? ` by ${connection.connectedBy}` : '',\n ].join('');\n }\n return connection.missing.length > 0\n ? `not connected — app fields missing: ${connection.missing.join(', ')}`\n : 'not connected';\n}\n\n/**\n * `apps connect <product>`: connect the integration ONCE for the whole Source,\n * for the Source's provided agents whose template says `owner: \"source\"`.\n * Asks for any missing app fields at the terminal (secrets hidden, never from\n * a flag), prints the provider's consent URL, then waits until the browser\n * finishes. `apps disconnect <product>` removes it.\n */\nasync function runConnection(\n ctx: CliContext,\n args: AppsArgs,\n subcommand: 'connect' | 'disconnect',\n product: string,\n): Promise<ExitCode> {\n const { env, client, source } = await openClient(ctx, args);\n\n if (subcommand === 'disconnect') {\n return disconnect(ctx, args, client, env.host, source, product);\n }\n\n const shown = await client.connection((token) =>\n showConnection(env.host, token, source, product),\n );\n if (shown.status === 'unsupported') {\n throw invalidStateError(\n shown.message,\n `Each team connects ${product} itself: \"ekanos teams connect <team> ${product}\".`,\n );\n }\n if (shown.status !== 'ok') {\n throw invalidStateError(\n 'The host could not read the connection.',\n 'Retry shortly.',\n );\n }\n const current = shown.data.connection;\n\n if (current.app === 'fields') {\n ctx.log(\n [\n `${current.name} app for ${shown.data.source.slug} (one for the whole Source)`,\n ` Register this redirect URL in the app: ${shown.data.callbackUrls.join(', ')}`,\n ].join('\\n'),\n );\n }\n\n const fields = await askFields(ctx, args, current, product);\n\n const started = await client.connection((token) =>\n startConnection(env.host, token, {\n source,\n product,\n ...(Object.keys(fields).length > 0 ? { fields } : {}),\n }),\n );\n if (started.status === 'not-configured') {\n throw validationError(\n `${current.name} is not set up for the Source yet — missing: ${started.missing.join(', ')}.`,\n current.app === 'source-app'\n ? `Run \"ekanos apps set ${product}\" to enter the Source's app first.`\n : `Run \"ekanos apps connect ${product}\" again and fill every field.`,\n );\n }\n if (started.status !== 'ok') {\n throw invalidStateError(\n 'The host could not start the connection.',\n 'Retry shortly.',\n );\n }\n\n ctx.log(\n [\n `Open this link and approve ${current.name} as the account the Source's agents should act as:`,\n ` ${started.data.authorizeUrl}`,\n ].join('\\n'),\n );\n\n if (args.noWait || ctx.jsonMode) {\n return ctx.succeed(\n {\n host: env.host,\n product,\n authorizeUrl: started.data.authorizeUrl,\n callbackUrl: started.data.callbackUrl,\n connected: false,\n },\n ctx.ui.hint(`Then check with \"ekanos apps show ${product}\".`),\n );\n }\n\n const deadline = Date.now() + 10 * 60 * 1000;\n const before = current.connectedAt;\n while (Date.now() < deadline) {\n await new Promise((resolve) =>\n setTimeout(resolve, args.pollDelayMs ?? 3000),\n );\n const polled = await client.connection((token) =>\n showConnection(env.host, token, source, product),\n );\n if (\n polled.status === 'ok' &&\n polled.data.connection.connected &&\n polled.data.connection.connectedAt !== before\n ) {\n return ctx.succeed(\n { host: env.host, product, connection: polled.data.connection },\n connectionSummary(ctx, polled.data.connection, {\n sourceSlug: polled.data.source.slug,\n callbackUrls: polled.data.callbackUrls,\n }),\n );\n }\n }\n throw validationError(\n 'The connection did not finish within ten minutes.',\n `Run \"ekanos apps connect ${product}\" again for a fresh link.`,\n );\n}\n\nasync function askFields(\n ctx: CliContext,\n args: AppsArgs,\n current: SourceConnection,\n product: string,\n): Promise<Record<string, string>> {\n const toAsk = current.fields.filter(\n (field) => !field.set || current.missing.includes(field.name),\n );\n if (toAsk.length === 0) return {};\n return collectSecrets(ctx, {\n fields: toAsk.map((field) => ({\n name: field.name,\n label: field.label,\n sensitive: field.sensitive,\n ...(field.description ? { description: field.description } : {}),\n set: false,\n required: current.missing.includes(field.name),\n })),\n plain: parsePlainValues(args.flags?.set),\n flags: readSecretFlags(args.flags),\n io: secretIO(args),\n interactive: canPrompt(ctx, args),\n title: `${current.name}'s app for the whole Source`,\n refusal: `${current.name} needs its app fields entered for the Source (${toAsk.map((field) => `${field.label} [${field.name}]`).join(', ')}), and there is no terminal to ask at.`,\n again: `apps connect ${product}${args.source ? ` --source ${args.source}` : ''}`,\n prompt: (field) =>\n field.sensitive\n ? (args.askSecret ?? promptHidden)(`${field.label} (hidden): `)\n : (args.ask ?? promptLine)(`${field.label}: `),\n });\n}\n\nasync function disconnect(\n ctx: CliContext,\n args: AppsArgs,\n client: AppsClient,\n host: string,\n source: string,\n product: string,\n): Promise<ExitCode> {\n if (!args.yes && !canPrompt(ctx, args)) {\n throw invalidStateError(\n `Disconnecting ${product} on ${source} stops it for every team's provided agents that use the Source connection, until someone connects it again.`,\n `Re-run with --yes: ekanos apps disconnect ${product} --source ${source} --yes`,\n );\n }\n if (!args.yes) {\n const sure = await (args.confirm ?? promptYesNo)(\n `Disconnect ${product} for every team's provided agents on ${source}? [y/N]`,\n );\n if (!sure) {\n throw validationError(\n 'Nothing was changed.',\n `Run \"ekanos apps show ${product}\" to see the current state.`,\n );\n }\n }\n const result = await client.connection((token) =>\n deleteConnection(host, token, source, product),\n );\n if (result.status === 'unsupported') {\n throw invalidStateError(\n result.message,\n `Each team connects ${product} itself: \"ekanos teams connect <team> ${product}\".`,\n );\n }\n if (result.status !== 'ok') {\n throw invalidStateError('The host could not disconnect.', 'Retry shortly.');\n }\n return ctx.succeed(\n { host, product, ...result.data },\n ctx.ui.result({\n title: result.data.removed\n ? `Disconnected the ${product} Source connection on ${source}`\n : `${product} had no Source connection on ${source}`,\n rows: [\n [\n 'Provided agents',\n 'their tools for this product stop until you connect again',\n ],\n ],\n }),\n );\n}\n\nfunction connectionSummary(\n ctx: CliContext,\n connection: SourceConnection,\n meta: { sourceSlug: string; callbackUrls: string[] },\n): string {\n const rows: ResultRow[] = [\n ['Source', meta.sourceSlug],\n ['Connected', connectionState(connection)],\n ...(connection.scope ? ([['Scope', connection.scope]] as ResultRow[]) : []),\n ...(connection.fields.length > 0\n ? ([\n [\n 'App fields',\n connection.fields.map(\n (field) =>\n `${field.label}: ${field.set ? (field.value ?? 'set') : 'missing'}`,\n ),\n ],\n ] as ResultRow[])\n : []),\n ['Redirect URL', meta.callbackUrls],\n [\n 'Used by',\n `provided agents whose template says connections.${connection.slug}.owner: \"source\", in every team`,\n ],\n ];\n return [\n ctx.ui.result({\n title: `${connection.name} — Source connection (one for every team's provided agents)`,\n rows,\n }),\n ...(connection.connected\n ? []\n : [\n ctx.ui.hint(\n `Run \"ekanos apps connect ${connection.slug}\" in your terminal to connect it.`,\n ),\n ]),\n ].join('\\n');\n}\n\nasync function openClient(ctx: CliContext, args: AppsArgs) {\n const env = resolveAuthEnvironment(ctx, args.host, args.env, {\n projectDir: args.dir,\n });\n const resolved = await resolveSourceTarget(env, requireSession(env), args);\n return {\n env,\n client: new AppsClient(env, resolved.session),\n source: resolved.source,\n };\n}\n\nclass AppsClient {\n constructor(\n private readonly env: AuthEnvironment,\n private session: StoredSession,\n ) {}\n\n async call<T>(\n send: (accessToken: string) => Promise<AppsApiResult<T>>,\n ): Promise<T> {\n let result = await send(this.session.accessToken);\n if (result.status === 'unauthorized') {\n this.session = await refreshStoredSession(this.env, this.session);\n result = await send(this.session.accessToken);\n }\n if (result.status === 'ok') return result.data;\n throw authRequiredError(\n `The session for ${this.env.host} could not authorize the apps call.`,\n loginHint(this.env),\n );\n }\n\n /** As `call`, for the connections client, whose 409s are answers. */\n async connection<T>(\n send: (accessToken: string) => Promise<ConnectionsApiResult<T>>,\n ): Promise<Exclude<ConnectionsApiResult<T>, { status: 'unauthorized' }>> {\n let result = await send(this.session.accessToken);\n if (result.status === 'unauthorized') {\n this.session = await refreshStoredSession(this.env, this.session);\n result = await send(this.session.accessToken);\n }\n if (result.status !== 'unauthorized') return result;\n throw authRequiredError(\n `The session for ${this.env.host} could not authorize the connections call.`,\n loginHint(this.env),\n );\n }\n}\n\nfunction canPrompt(ctx: CliContext, args: AppsArgs): boolean {\n return !ctx.jsonMode && (args.stdinIsTTY ?? process.stdin.isTTY === true);\n}\n\nconst SET_REFUSAL =\n 'apps set needs the client secret, and there is no terminal to ask at.';\n\nfunction secretIO(args: AppsArgs): SecretIO {\n return {\n env: args.env,\n stdinIsTTY: args.stdinIsTTY ?? process.stdin.isTTY === true,\n readStdin: args.readStdin,\n openUrl: args.openUrl,\n formTimeoutMs: args.secretFormTimeoutMs,\n };\n}\n\nfunction parseSubcommand(value: string | undefined): AppsSubcommand {\n const match = APPS_SUBCOMMANDS.find((name) => name === value);\n if (match) return match;\n throw usageError(\n value ? `Unknown apps subcommand \"${value}\".` : 'apps needs a subcommand.',\n `Run one of: ${APPS_SUBCOMMANDS.map((name) => `ekanos apps ${name} <product>`).join(', ')}.`,\n );\n}\n\nfunction requireProduct(value: string | undefined, verb: string): string {\n const slug = value?.trim().toLowerCase();\n if (slug && /^[a-z0-9][a-z0-9-]*$/.test(slug)) return slug;\n throw usageError(\n value\n ? `\"${value}\" is not a product slug.`\n : `apps ${verb} needs a product.`,\n `Pass the product's slug, e.g. \"ekanos apps ${verb} linear\". \"ekanos catalog\" lists them.`,\n );\n}\n\nexport async function promptLine(question: string): Promise<string> {\n const readline = await import('node:readline/promises');\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stderr,\n });\n try {\n return await rl.question(question);\n } finally {\n rl.close();\n }\n}\n\n/**\n * Read a line without echoing it: the secret never appears on screen or in\n * scrollback. The question is always printed; only the typed characters are\n * hidden (each shows as `*`, so a paste visibly landed).\n *\n * Raw mode by hand rather than readline: a terminal readline redraws its\n * line on `question()` — cursor to column 0, clear to the end of the screen —\n * which erased the question written before it, so the terminal sat on an\n * empty line and a hidden field looked skipped.\n */\nexport async function promptHidden(question: string): Promise<string> {\n const stdin = process.stdin;\n const stderr = process.stderr;\n stderr.write(question);\n\n if (!stdin.isTTY) {\n // Piped stdin echoes nothing: read one line as is.\n const readline = await import('node:readline/promises');\n const rl = readline.createInterface({ input: stdin, terminal: false });\n try {\n return await rl.question('');\n } finally {\n rl.close();\n stderr.write('\\n');\n }\n }\n\n return new Promise<string>((resolve) => {\n let value = '';\n let inEscape = false;\n const wasRaw = stdin.isRaw;\n const finish = () => {\n stdin.off('data', onData);\n stdin.setRawMode(wasRaw);\n stdin.pause();\n stderr.write('\\n');\n };\n const onData = (chunk: Buffer | string) => {\n for (const char of typeof chunk === 'string'\n ? chunk\n : chunk.toString('utf8')) {\n if (inEscape) {\n // An escape sequence (an arrow key) ends at its final letter.\n if (/[A-Za-z~]/.test(char)) inEscape = false;\n continue;\n }\n if (char === '\\u001b') {\n inEscape = true;\n continue;\n }\n if (char === '\\r' || char === '\\n' || char === '\\u0004') {\n finish();\n resolve(value);\n return;\n }\n if (char === '\\u0003') {\n // Ctrl-C: raw mode swallowed the signal, so leave as SIGINT would.\n finish();\n process.exit(130);\n }\n if (char === '\\u007f' || char === '\\b') {\n if (value.length > 0) {\n value = value.slice(0, -1);\n stderr.write('\\b \\b');\n }\n continue;\n }\n if (char === '\\u0015') {\n // Ctrl-U: clear what was typed.\n stderr.write('\\b \\b'.repeat(value.length));\n value = '';\n continue;\n }\n if (char < ' ') continue;\n value += char;\n stderr.write('*');\n }\n };\n stdin.setRawMode(true);\n stdin.resume();\n stdin.on('data', onData);\n });\n}\n\n/** Each credential's state: the client id's value, the secret as saved or not. */\nfunction providerFieldRows(status: ProviderAppStatus): ResultRow[] {\n return (status.fields ?? []).map((field) => [\n field.label,\n !field.set\n ? 'not set'\n : field.sensitive\n ? 'saved'\n : (field.value ?? 'saved'),\n ]);\n}\n\n/** Every redirect URI to register; an older host sends only the one. */\nfunction callbackUrls(status: ProviderAppStatus): string[] {\n return status.callbackUrls?.length\n ? status.callbackUrls\n : [status.callbackUrl];\n}\n"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { CliContext } from '../context.js';
|
|
2
|
+
import type { ExitCode } from '../exit-codes.js';
|
|
3
|
+
export interface AudiencesArgs {
|
|
4
|
+
host?: string;
|
|
5
|
+
source?: string;
|
|
6
|
+
/** `list`, `show <audience>`, `create <name>`, `set <audience>`. */
|
|
7
|
+
positionals: readonly string[];
|
|
8
|
+
yes: boolean;
|
|
9
|
+
/** `--products`, `--widgets`, `--tools`, `--name`, `--description` … */
|
|
10
|
+
flags?: Record<string, string | boolean | string[]>;
|
|
11
|
+
dir: string;
|
|
12
|
+
env: Record<string, string | undefined>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* `audiences` — a Source's audiences, for its Source admin. An audience is a
|
|
16
|
+
* named set of the Source's products (with optional per-product widget and
|
|
17
|
+
* tool rules) that people see in the app: each team member holds one, their
|
|
18
|
+
* own else their team's default (`ekanos teams audience`). It replaces a
|
|
19
|
+
* product scope; `sources scopes` and `teams scope` keep working until 0.20.
|
|
20
|
+
*
|
|
21
|
+
* list every audience, its products and rules
|
|
22
|
+
* show <audience> one, in full
|
|
23
|
+
* create <name> … --products a,b | --all-entitled, --description,
|
|
24
|
+
* --default, --widgets <product>=<id>,…,
|
|
25
|
+
* --tools <product>=<name>,…
|
|
26
|
+
* set <audience> … the same flags, plus --name; --products
|
|
27
|
+
* replaces the product set (rules of kept
|
|
28
|
+
* products stay unless re-stated). Dropping a
|
|
29
|
+
* product needs --yes.
|
|
30
|
+
*/
|
|
31
|
+
export declare function runAudiences(ctx: CliContext, args: AudiencesArgs): Promise<ExitCode>;
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { requireSession, resolveAuthEnvironment } from '../auth/session.js';
|
|
2
|
+
import { invalidStateError, usageError } from '../errors.js';
|
|
3
|
+
import { resolveSourceTarget } from '../source-target.js';
|
|
4
|
+
import { createAudience, listAudiences, showAudience, updateAudience, } from '../teams-api.js';
|
|
5
|
+
import { pluralize } from '../ui.js';
|
|
6
|
+
import { TeamsClient } from './teams.js';
|
|
7
|
+
const USAGE = 'Run "ekanos audiences list", "ekanos audiences show <audience>", "ekanos audiences create <name> [--products a,b | --all-entitled]" or "ekanos audiences set <audience> [--products a,b] [--widgets <product>=<id>,…] [--tools <product>=<name>,…]".';
|
|
8
|
+
/**
|
|
9
|
+
* `audiences` — a Source's audiences, for its Source admin. An audience is a
|
|
10
|
+
* named set of the Source's products (with optional per-product widget and
|
|
11
|
+
* tool rules) that people see in the app: each team member holds one, their
|
|
12
|
+
* own else their team's default (`ekanos teams audience`). It replaces a
|
|
13
|
+
* product scope; `sources scopes` and `teams scope` keep working until 0.20.
|
|
14
|
+
*
|
|
15
|
+
* list every audience, its products and rules
|
|
16
|
+
* show <audience> one, in full
|
|
17
|
+
* create <name> … --products a,b | --all-entitled, --description,
|
|
18
|
+
* --default, --widgets <product>=<id>,…,
|
|
19
|
+
* --tools <product>=<name>,…
|
|
20
|
+
* set <audience> … the same flags, plus --name; --products
|
|
21
|
+
* replaces the product set (rules of kept
|
|
22
|
+
* products stay unless re-stated). Dropping a
|
|
23
|
+
* product needs --yes.
|
|
24
|
+
*/
|
|
25
|
+
export async function runAudiences(ctx, args) {
|
|
26
|
+
var _a, _b;
|
|
27
|
+
const [verb = 'list', rawName, ...extra] = args.positionals;
|
|
28
|
+
if (!['list', 'show', 'create', 'set'].includes(verb)) {
|
|
29
|
+
throw usageError(`Unknown audiences subcommand "${verb}".`, USAGE);
|
|
30
|
+
}
|
|
31
|
+
if (extra.length > 0) {
|
|
32
|
+
throw usageError(`Unexpected argument "${extra[0]}".`, USAGE);
|
|
33
|
+
}
|
|
34
|
+
if (verb === 'list' && rawName) {
|
|
35
|
+
throw usageError(`Unexpected argument "${rawName}".`, USAGE);
|
|
36
|
+
}
|
|
37
|
+
const name = rawName === null || rawName === void 0 ? void 0 : rawName.trim();
|
|
38
|
+
if (verb !== 'list' && !name) {
|
|
39
|
+
throw usageError(verb === 'create'
|
|
40
|
+
? 'audiences create needs a name.'
|
|
41
|
+
: `audiences ${verb} needs an audience (its name or id).`, USAGE);
|
|
42
|
+
}
|
|
43
|
+
const flags = readFlags((_a = args.flags) !== null && _a !== void 0 ? _a : {});
|
|
44
|
+
const env = resolveAuthEnvironment(ctx, args.host, args.env, {
|
|
45
|
+
projectDir: args.dir,
|
|
46
|
+
});
|
|
47
|
+
const resolved = await resolveSourceTarget(env, requireSession(env), args);
|
|
48
|
+
const client = new TeamsClient(env, resolved.session);
|
|
49
|
+
const source = resolved.source;
|
|
50
|
+
if (verb === 'list') {
|
|
51
|
+
const list = await client.call((token) => listAudiences(env.host, token, source));
|
|
52
|
+
if (list.audiences.length === 0) {
|
|
53
|
+
return ctx.succeed(Object.assign({ host: env.host }, list), ctx.ui.result({
|
|
54
|
+
title: `No audiences on ${list.source.slug}`,
|
|
55
|
+
notes: [`"ekanos audiences create <name> --products a,b" makes one.`],
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
58
|
+
return ctx.succeed(Object.assign({ host: env.host }, list), ctx.ui.result({
|
|
59
|
+
title: `Audiences on ${list.source.slug}`,
|
|
60
|
+
rows: list.audiences.map((audience) => [
|
|
61
|
+
audience.name,
|
|
62
|
+
describeLines(audience),
|
|
63
|
+
]),
|
|
64
|
+
notes: [
|
|
65
|
+
'A person sees the products of their own audience, else their team’s ("ekanos teams audience <team>").',
|
|
66
|
+
],
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
if (verb === 'show') {
|
|
70
|
+
const shown = await client.call((token) => showAudience(env.host, token, { source, audience: name }));
|
|
71
|
+
return ctx.succeed(Object.assign({ host: env.host }, shown), renderAudience(ctx.ui, shown.audience, `${shown.audience.name}`));
|
|
72
|
+
}
|
|
73
|
+
if (verb === 'create') {
|
|
74
|
+
const body = Object.assign(Object.assign(Object.assign(Object.assign({ name: name }, (flags.description !== undefined
|
|
75
|
+
? { description: flags.description }
|
|
76
|
+
: {})), (flags.isDefault ? { isDefault: true } : {})), (flags.allEntitled !== undefined
|
|
77
|
+
? { includesAllEntitled: flags.allEntitled }
|
|
78
|
+
: {})), (flags.products || flags.widgets.size > 0 || flags.tools.size > 0
|
|
79
|
+
? { products: applyRules([], flags) }
|
|
80
|
+
: {}));
|
|
81
|
+
const created = await client.call((token) => createAudience(env.host, token, source, body));
|
|
82
|
+
return ctx.succeed(Object.assign({ host: env.host }, created), renderAudience(ctx.ui, created.audience, `Created ${created.audience.name}`));
|
|
83
|
+
}
|
|
84
|
+
const current = await client.call((token) => showAudience(env.host, token, { source, audience: name }));
|
|
85
|
+
const before = current.audience;
|
|
86
|
+
const body = Object.assign(Object.assign(Object.assign(Object.assign({}, (flags.name !== undefined ? { name: flags.name } : {})), (flags.description !== undefined
|
|
87
|
+
? { description: flags.description }
|
|
88
|
+
: {})), (flags.isDefault ? { isDefault: true } : {})), (flags.allEntitled !== undefined
|
|
89
|
+
? { includesAllEntitled: flags.allEntitled }
|
|
90
|
+
: {}));
|
|
91
|
+
if (flags.products || flags.widgets.size > 0 || flags.tools.size > 0) {
|
|
92
|
+
body.products = applyRules(before.products.map((product) => (Object.assign(Object.assign({ slug: product.slug }, (product.widgetIds ? { widgetIds: product.widgetIds } : {})), (product.toolNames ? { toolNames: product.toolNames } : {})))), flags);
|
|
93
|
+
}
|
|
94
|
+
if (Object.keys(body).length === 0) {
|
|
95
|
+
throw usageError('Nothing to change.', 'Pass --products, --widgets, --tools, --name, --description, --default or --all-entitled.');
|
|
96
|
+
}
|
|
97
|
+
const kept = new Set(((_b = body.products) !== null && _b !== void 0 ? _b : []).map((product) => product.slug));
|
|
98
|
+
const dropped = body.products
|
|
99
|
+
? before.products.filter((product) => !kept.has(product.slug))
|
|
100
|
+
: [];
|
|
101
|
+
if (dropped.length > 0 && !args.yes) {
|
|
102
|
+
throw invalidStateError(`${before.name} would no longer show ${dropped.map((product) => product.slug).join(', ')}: everyone on it stops seeing ${dropped.length === 1 ? 'it' : 'them'} in the app.`, `Re-run with --yes: ekanos audiences set ${quote(before.name)} … --source ${source} --yes`);
|
|
103
|
+
}
|
|
104
|
+
const updated = await client.call((token) => updateAudience(env.host, token, { source, audience: name }, body));
|
|
105
|
+
return ctx.succeed(Object.assign({ host: env.host }, updated), renderAudience(ctx.ui, updated.audience, `Updated ${updated.audience.name}`, {
|
|
106
|
+
tone: dropped.length > 0 ? 'warn' : 'ok',
|
|
107
|
+
}));
|
|
108
|
+
}
|
|
109
|
+
function readFlags(flags) {
|
|
110
|
+
const text = (key) => typeof flags[key] === 'string' ? flags[key] : undefined;
|
|
111
|
+
const list = (key) => {
|
|
112
|
+
const value = flags[key];
|
|
113
|
+
return Array.isArray(value)
|
|
114
|
+
? value
|
|
115
|
+
: typeof value === 'string'
|
|
116
|
+
? [value]
|
|
117
|
+
: [];
|
|
118
|
+
};
|
|
119
|
+
const products = text('products');
|
|
120
|
+
return {
|
|
121
|
+
name: text('name'),
|
|
122
|
+
description: text('description'),
|
|
123
|
+
isDefault: flags.default === true,
|
|
124
|
+
allEntitled: typeof flags['all-entitled'] === 'boolean'
|
|
125
|
+
? flags['all-entitled']
|
|
126
|
+
: undefined,
|
|
127
|
+
products: products === undefined
|
|
128
|
+
? undefined
|
|
129
|
+
: products === 'none'
|
|
130
|
+
? []
|
|
131
|
+
: products
|
|
132
|
+
.split(',')
|
|
133
|
+
.map((slug) => slug.trim().toLowerCase())
|
|
134
|
+
.filter(Boolean),
|
|
135
|
+
widgets: ruleMap('widgets', list('widgets')),
|
|
136
|
+
tools: ruleMap('tools', list('tools')),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
/** `linear=w1,w2` per product; `linear=` clears the rule (all of them). */
|
|
140
|
+
function ruleMap(flag, values) {
|
|
141
|
+
const rules = new Map();
|
|
142
|
+
for (const value of values) {
|
|
143
|
+
const at = value.indexOf('=');
|
|
144
|
+
const slug = (at < 0 ? value : value.slice(0, at)).trim().toLowerCase();
|
|
145
|
+
if (!slug || at < 0) {
|
|
146
|
+
throw usageError(`--${flag} takes <product>=<name>,<name>… (got "${value}").`, `e.g. --${flag} linear=${flag === 'widgets' ? 'linear-issues' : 'create_issue'}; "<product>=" lifts the rule.`);
|
|
147
|
+
}
|
|
148
|
+
rules.set(slug, value
|
|
149
|
+
.slice(at + 1)
|
|
150
|
+
.split(',')
|
|
151
|
+
.map((item) => item.trim())
|
|
152
|
+
.filter(Boolean));
|
|
153
|
+
}
|
|
154
|
+
return rules;
|
|
155
|
+
}
|
|
156
|
+
/** The product set after `--products` and the widget and tool rules. */
|
|
157
|
+
function applyRules(base, flags) {
|
|
158
|
+
var _a;
|
|
159
|
+
const known = new Map(base.map((product) => [product.slug, product]));
|
|
160
|
+
const slugs = (_a = flags.products) !== null && _a !== void 0 ? _a : base.map((product) => product.slug);
|
|
161
|
+
const products = slugs.map((slug) => {
|
|
162
|
+
const existing = known.get(slug);
|
|
163
|
+
return Object.assign(Object.assign({ slug }, ((existing === null || existing === void 0 ? void 0 : existing.widgetIds) ? { widgetIds: existing.widgetIds } : {})), ((existing === null || existing === void 0 ? void 0 : existing.toolNames) ? { toolNames: existing.toolNames } : {}));
|
|
164
|
+
});
|
|
165
|
+
for (const [kind, rules] of [
|
|
166
|
+
['widgetIds', flags.widgets],
|
|
167
|
+
['toolNames', flags.tools],
|
|
168
|
+
]) {
|
|
169
|
+
for (const [slug, names] of rules) {
|
|
170
|
+
const product = products.find((entry) => entry.slug === slug);
|
|
171
|
+
if (!product) {
|
|
172
|
+
throw usageError(`--${kind === 'widgetIds' ? 'widgets' : 'tools'} names ${slug}, which the audience would not show.`, 'Add it with --products, or name a product that is in the audience.');
|
|
173
|
+
}
|
|
174
|
+
if (names.length > 0)
|
|
175
|
+
product[kind] = names;
|
|
176
|
+
else
|
|
177
|
+
delete product[kind];
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return products;
|
|
181
|
+
}
|
|
182
|
+
function describeLines(audience) {
|
|
183
|
+
const lines = [
|
|
184
|
+
[
|
|
185
|
+
audience.includesAllEntitled
|
|
186
|
+
? 'every product the Source has'
|
|
187
|
+
: pluralize(audience.products.length, 'product'),
|
|
188
|
+
audience.isDefault ? 'given to every new team' : null,
|
|
189
|
+
]
|
|
190
|
+
.filter(Boolean)
|
|
191
|
+
.join(' · '),
|
|
192
|
+
];
|
|
193
|
+
if (!audience.includesAllEntitled) {
|
|
194
|
+
lines.push(audience.products.length > 0
|
|
195
|
+
? audience.products.map(productWords).join(', ')
|
|
196
|
+
: 'no products');
|
|
197
|
+
}
|
|
198
|
+
return lines;
|
|
199
|
+
}
|
|
200
|
+
function productWords(product) {
|
|
201
|
+
const rules = [
|
|
202
|
+
product.widgetIds
|
|
203
|
+
? `${pluralize(product.widgetIds.length, 'widget')}`
|
|
204
|
+
: null,
|
|
205
|
+
product.toolNames ? `${pluralize(product.toolNames.length, 'tool')}` : null,
|
|
206
|
+
].filter(Boolean);
|
|
207
|
+
return rules.length > 0
|
|
208
|
+
? `${product.slug} (only ${rules.join(', ')})`
|
|
209
|
+
: product.slug;
|
|
210
|
+
}
|
|
211
|
+
function renderAudience(ui, audience, title, options = {}) {
|
|
212
|
+
var _a;
|
|
213
|
+
return ui.result({
|
|
214
|
+
title,
|
|
215
|
+
tone: (_a = options.tone) !== null && _a !== void 0 ? _a : 'ok',
|
|
216
|
+
rows: [
|
|
217
|
+
['Audience', audience.name],
|
|
218
|
+
...(audience.description
|
|
219
|
+
? [['About', audience.description]]
|
|
220
|
+
: []),
|
|
221
|
+
['Default', audience.isDefault ? 'yes, new teams start on it' : 'no'],
|
|
222
|
+
[
|
|
223
|
+
'Products',
|
|
224
|
+
audience.includesAllEntitled
|
|
225
|
+
? 'every product the Source has, now and later'
|
|
226
|
+
: audience.products.length > 0
|
|
227
|
+
? audience.products.map(productWords)
|
|
228
|
+
: 'none',
|
|
229
|
+
],
|
|
230
|
+
],
|
|
231
|
+
notes: [
|
|
232
|
+
'Teams and members are put on an audience with "ekanos teams audience <team> [<audience>]".',
|
|
233
|
+
],
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
function quote(name) {
|
|
237
|
+
return /^[A-Za-z0-9._-]+$/.test(name) ? name : `"${name}"`;
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=audiences.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audiences.js","sourceRoot":"","sources":["../../src/commands/audiences.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n Audience,\n AudienceCreateRequest,\n AudienceUpdateRequest,\n} from '@ekanos/integration-schema';\n\nimport { requireSession, resolveAuthEnvironment } from '../auth/session';\nimport type { CliContext } from '../context';\nimport { invalidStateError, usageError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport { resolveSourceTarget } from '../source-target';\nimport {\n createAudience,\n listAudiences,\n showAudience,\n updateAudience,\n} from '../teams-api';\nimport { type Ui, pluralize } from '../ui';\nimport { TeamsClient } from './teams';\n\nexport interface AudiencesArgs {\n host?: string;\n source?: string;\n /** `list`, `show <audience>`, `create <name>`, `set <audience>`. */\n positionals: readonly string[];\n yes: boolean;\n /** `--products`, `--widgets`, `--tools`, `--name`, `--description` … */\n flags?: Record<string, string | boolean | string[]>;\n dir: string;\n env: Record<string, string | undefined>;\n}\n\nconst USAGE =\n 'Run \"ekanos audiences list\", \"ekanos audiences show <audience>\", \"ekanos audiences create <name> [--products a,b | --all-entitled]\" or \"ekanos audiences set <audience> [--products a,b] [--widgets <product>=<id>,…] [--tools <product>=<name>,…]\".';\n\ntype ProductRule = { slug: string; widgetIds?: string[]; toolNames?: string[] };\n\n/**\n * `audiences` — a Source's audiences, for its Source admin. An audience is a\n * named set of the Source's products (with optional per-product widget and\n * tool rules) that people see in the app: each team member holds one, their\n * own else their team's default (`ekanos teams audience`). It replaces a\n * product scope; `sources scopes` and `teams scope` keep working until 0.20.\n *\n * list every audience, its products and rules\n * show <audience> one, in full\n * create <name> … --products a,b | --all-entitled, --description,\n * --default, --widgets <product>=<id>,…,\n * --tools <product>=<name>,…\n * set <audience> … the same flags, plus --name; --products\n * replaces the product set (rules of kept\n * products stay unless re-stated). Dropping a\n * product needs --yes.\n */\nexport async function runAudiences(\n ctx: CliContext,\n args: AudiencesArgs,\n): Promise<ExitCode> {\n const [verb = 'list', rawName, ...extra] = args.positionals;\n if (!['list', 'show', 'create', 'set'].includes(verb)) {\n throw usageError(`Unknown audiences subcommand \"${verb}\".`, USAGE);\n }\n if (extra.length > 0) {\n throw usageError(`Unexpected argument \"${extra[0]}\".`, USAGE);\n }\n if (verb === 'list' && rawName) {\n throw usageError(`Unexpected argument \"${rawName}\".`, USAGE);\n }\n const name = rawName?.trim();\n if (verb !== 'list' && !name) {\n throw usageError(\n verb === 'create'\n ? 'audiences create needs a name.'\n : `audiences ${verb} needs an audience (its name or id).`,\n USAGE,\n );\n }\n const flags = readFlags(args.flags ?? {});\n\n const env = resolveAuthEnvironment(ctx, args.host, args.env, {\n projectDir: args.dir,\n });\n const resolved = await resolveSourceTarget(env, requireSession(env), args);\n const client = new TeamsClient(env, resolved.session);\n const source = resolved.source;\n\n if (verb === 'list') {\n const list = await client.call((token) =>\n listAudiences(env.host, token, source),\n );\n if (list.audiences.length === 0) {\n return ctx.succeed(\n { host: env.host, ...list },\n ctx.ui.result({\n title: `No audiences on ${list.source.slug}`,\n notes: [`\"ekanos audiences create <name> --products a,b\" makes one.`],\n }),\n );\n }\n return ctx.succeed(\n { host: env.host, ...list },\n ctx.ui.result({\n title: `Audiences on ${list.source.slug}`,\n rows: list.audiences.map((audience): [string, string[]] => [\n audience.name,\n describeLines(audience),\n ]),\n notes: [\n 'A person sees the products of their own audience, else their team’s (\"ekanos teams audience <team>\").',\n ],\n }),\n );\n }\n\n if (verb === 'show') {\n const shown = await client.call((token) =>\n showAudience(env.host, token, { source, audience: name! }),\n );\n return ctx.succeed(\n { host: env.host, ...shown },\n renderAudience(ctx.ui, shown.audience, `${shown.audience.name}`),\n );\n }\n\n if (verb === 'create') {\n const body: AudienceCreateRequest = {\n name: name!,\n ...(flags.description !== undefined\n ? { description: flags.description }\n : {}),\n ...(flags.isDefault ? { isDefault: true } : {}),\n ...(flags.allEntitled !== undefined\n ? { includesAllEntitled: flags.allEntitled }\n : {}),\n ...(flags.products || flags.widgets.size > 0 || flags.tools.size > 0\n ? { products: applyRules([], flags) }\n : {}),\n };\n const created = await client.call((token) =>\n createAudience(env.host, token, source, body),\n );\n return ctx.succeed(\n { host: env.host, ...created },\n renderAudience(\n ctx.ui,\n created.audience,\n `Created ${created.audience.name}`,\n ),\n );\n }\n\n const current = await client.call((token) =>\n showAudience(env.host, token, { source, audience: name! }),\n );\n const before = current.audience;\n const body: AudienceUpdateRequest = {\n ...(flags.name !== undefined ? { name: flags.name } : {}),\n ...(flags.description !== undefined\n ? { description: flags.description }\n : {}),\n ...(flags.isDefault ? { isDefault: true } : {}),\n ...(flags.allEntitled !== undefined\n ? { includesAllEntitled: flags.allEntitled }\n : {}),\n };\n if (flags.products || flags.widgets.size > 0 || flags.tools.size > 0) {\n body.products = applyRules(\n before.products.map((product) => ({\n slug: product.slug,\n ...(product.widgetIds ? { widgetIds: product.widgetIds } : {}),\n ...(product.toolNames ? { toolNames: product.toolNames } : {}),\n })),\n flags,\n );\n }\n if (Object.keys(body).length === 0) {\n throw usageError(\n 'Nothing to change.',\n 'Pass --products, --widgets, --tools, --name, --description, --default or --all-entitled.',\n );\n }\n\n const kept = new Set((body.products ?? []).map((product) => product.slug));\n const dropped = body.products\n ? before.products.filter((product) => !kept.has(product.slug))\n : [];\n if (dropped.length > 0 && !args.yes) {\n throw invalidStateError(\n `${before.name} would no longer show ${dropped.map((product) => product.slug).join(', ')}: everyone on it stops seeing ${dropped.length === 1 ? 'it' : 'them'} in the app.`,\n `Re-run with --yes: ekanos audiences set ${quote(before.name)} … --source ${source} --yes`,\n );\n }\n\n const updated = await client.call((token) =>\n updateAudience(env.host, token, { source, audience: name! }, body),\n );\n return ctx.succeed(\n { host: env.host, ...updated },\n renderAudience(\n ctx.ui,\n updated.audience,\n `Updated ${updated.audience.name}`,\n {\n tone: dropped.length > 0 ? 'warn' : 'ok',\n },\n ),\n );\n}\n\ninterface AudienceFlags {\n name?: string;\n description?: string;\n isDefault: boolean;\n allEntitled?: boolean;\n /** Slugs, in the order given; absent when the flag was not passed. */\n products?: string[];\n widgets: Map<string, string[]>;\n tools: Map<string, string[]>;\n}\n\nfunction readFlags(\n flags: Record<string, string | boolean | string[]>,\n): AudienceFlags {\n const text = (key: string) =>\n typeof flags[key] === 'string' ? (flags[key] as string) : undefined;\n const list = (key: string) => {\n const value = flags[key];\n return Array.isArray(value)\n ? value\n : typeof value === 'string'\n ? [value]\n : [];\n };\n\n const products = text('products');\n return {\n name: text('name'),\n description: text('description'),\n isDefault: flags.default === true,\n allEntitled:\n typeof flags['all-entitled'] === 'boolean'\n ? (flags['all-entitled'] as boolean)\n : undefined,\n products:\n products === undefined\n ? undefined\n : products === 'none'\n ? []\n : products\n .split(',')\n .map((slug) => slug.trim().toLowerCase())\n .filter(Boolean),\n widgets: ruleMap('widgets', list('widgets')),\n tools: ruleMap('tools', list('tools')),\n };\n}\n\n/** `linear=w1,w2` per product; `linear=` clears the rule (all of them). */\nfunction ruleMap(flag: string, values: string[]): Map<string, string[]> {\n const rules = new Map<string, string[]>();\n for (const value of values) {\n const at = value.indexOf('=');\n const slug = (at < 0 ? value : value.slice(0, at)).trim().toLowerCase();\n if (!slug || at < 0) {\n throw usageError(\n `--${flag} takes <product>=<name>,<name>… (got \"${value}\").`,\n `e.g. --${flag} linear=${flag === 'widgets' ? 'linear-issues' : 'create_issue'}; \"<product>=\" lifts the rule.`,\n );\n }\n rules.set(\n slug,\n value\n .slice(at + 1)\n .split(',')\n .map((item) => item.trim())\n .filter(Boolean),\n );\n }\n return rules;\n}\n\n/** The product set after `--products` and the widget and tool rules. */\nfunction applyRules(base: ProductRule[], flags: AudienceFlags): ProductRule[] {\n const known = new Map(base.map((product) => [product.slug, product]));\n const slugs = flags.products ?? base.map((product) => product.slug);\n\n const products = slugs.map((slug): ProductRule => {\n const existing = known.get(slug);\n return {\n slug,\n ...(existing?.widgetIds ? { widgetIds: existing.widgetIds } : {}),\n ...(existing?.toolNames ? { toolNames: existing.toolNames } : {}),\n };\n });\n for (const [kind, rules] of [\n ['widgetIds', flags.widgets],\n ['toolNames', flags.tools],\n ] as const) {\n for (const [slug, names] of rules) {\n const product = products.find((entry) => entry.slug === slug);\n if (!product) {\n throw usageError(\n `--${kind === 'widgetIds' ? 'widgets' : 'tools'} names ${slug}, which the audience would not show.`,\n 'Add it with --products, or name a product that is in the audience.',\n );\n }\n if (names.length > 0) product[kind] = names;\n else delete product[kind];\n }\n }\n return products;\n}\n\nfunction describeLines(audience: Audience): string[] {\n const lines = [\n [\n audience.includesAllEntitled\n ? 'every product the Source has'\n : pluralize(audience.products.length, 'product'),\n audience.isDefault ? 'given to every new team' : null,\n ]\n .filter(Boolean)\n .join(' · '),\n ];\n if (!audience.includesAllEntitled) {\n lines.push(\n audience.products.length > 0\n ? audience.products.map(productWords).join(', ')\n : 'no products',\n );\n }\n return lines;\n}\n\nfunction productWords(product: Audience['products'][number]): string {\n const rules = [\n product.widgetIds\n ? `${pluralize(product.widgetIds.length, 'widget')}`\n : null,\n product.toolNames ? `${pluralize(product.toolNames.length, 'tool')}` : null,\n ].filter(Boolean);\n return rules.length > 0\n ? `${product.slug} (only ${rules.join(', ')})`\n : product.slug;\n}\n\nfunction renderAudience(\n ui: Ui,\n audience: Audience,\n title: string,\n options: { tone?: 'ok' | 'warn' } = {},\n): string {\n return ui.result({\n title,\n tone: options.tone ?? 'ok',\n rows: [\n ['Audience', audience.name],\n ...(audience.description\n ? ([['About', audience.description]] as Array<[string, string]>)\n : []),\n ['Default', audience.isDefault ? 'yes, new teams start on it' : 'no'],\n [\n 'Products',\n audience.includesAllEntitled\n ? 'every product the Source has, now and later'\n : audience.products.length > 0\n ? audience.products.map(productWords)\n : 'none',\n ],\n ],\n notes: [\n 'Teams and members are put on an audience with \"ekanos teams audience <team> [<audience>]\".',\n ],\n });\n}\n\nfunction quote(name: string): string {\n return /^[A-Za-z0-9._-]+$/.test(name) ? name : `\"${name}\"`;\n}\n"]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { emitExperience } from '../experience/build.js';
|
|
2
|
+
import { runExperienceChecks } from '../experience/checks.js';
|
|
3
|
+
import { readExperienceProject } from '../experience/project.js';
|
|
4
|
+
import { failOnErrors } from '../experience/report.js';
|
|
5
|
+
export const buildCommand = {
|
|
6
|
+
name: 'build',
|
|
7
|
+
usage: [
|
|
8
|
+
' build Build an experience: gate (pins, boundary, definition), then emit',
|
|
9
|
+
' dist/ and manifest.json',
|
|
10
|
+
],
|
|
11
|
+
specs: {
|
|
12
|
+
dir: {
|
|
13
|
+
type: 'string',
|
|
14
|
+
description: 'Project directory (default: the current one)',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
async run(ctx, args) {
|
|
18
|
+
const project = readExperienceProject(args.dir);
|
|
19
|
+
const result = await runExperienceChecks(project, {
|
|
20
|
+
typecheck: false,
|
|
21
|
+
loadDefinition: true,
|
|
22
|
+
inlineSdk: args.env.EKANOS_INLINE_SDK,
|
|
23
|
+
});
|
|
24
|
+
const failed = failOnErrors(ctx, 'build', result.findings, { slug: project.slug }, project.dir);
|
|
25
|
+
if (failed !== null)
|
|
26
|
+
return failed;
|
|
27
|
+
const output = await emitExperience(project, result);
|
|
28
|
+
return ctx.succeed({
|
|
29
|
+
slug: project.slug,
|
|
30
|
+
version: output.manifest.version,
|
|
31
|
+
digest: output.manifest.digest,
|
|
32
|
+
files: output.files,
|
|
33
|
+
widgets: output.manifest.widgets.length,
|
|
34
|
+
pages: output.manifest.pages.length,
|
|
35
|
+
workflowTemplates: output.manifest.workflowTemplates.length,
|
|
36
|
+
findings: result.findings,
|
|
37
|
+
changed: output.changed,
|
|
38
|
+
}, `Built ${project.slug}@${output.manifest.version} (${output.manifest.digest.slice(0, 18)}…): ${output.files.join(', ')}.`);
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGpD,MAAM,CAAC,MAAM,YAAY,GAAsB;IAC7C,IAAI,EAAE,OAAO;IACb,KAAK,EAAE;QACL,gFAAgF;QAChF,sCAAsC;KACvC;IACD,KAAK,EAAE;QACL,GAAG,EAAE;YACH,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,8CAA8C;SAC5D;KACF;IACD,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI;QACjB,MAAM,OAAO,GAAG,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,OAAO,EAAE;YAChD,SAAS,EAAE,KAAK;YAChB,cAAc,EAAE,IAAI;YACpB,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,iBAAiB;SACtC,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,YAAY,CACzB,GAAG,EACH,OAAO,EACP,MAAM,CAAC,QAAQ,EACf,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,EACtB,OAAO,CAAC,GAAG,CACZ,CAAC;QACF,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,MAAM,CAAC;QAEnC,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAErD,OAAO,GAAG,CAAC,OAAO,CAChB;YACE,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO;YAChC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM;YAC9B,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM;YACvC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM;YACnC,iBAAiB,EAAE,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAC,MAAM;YAC3D,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,OAAO,EAAE,MAAM,CAAC,OAAO;SACxB,EACD,SAAS,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,KAAK,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC1H,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { emitExperience } from '../experience/build';\nimport { runExperienceChecks } from '../experience/checks';\nimport { readExperienceProject } from '../experience/project';\nimport { failOnErrors } from '../experience/report';\nimport type { ExperienceCommand } from './index-experience';\n\nexport const buildCommand: ExperienceCommand = {\n name: 'build',\n usage: [\n ' build Build an experience: gate (pins, boundary, definition), then emit',\n ' dist/ and manifest.json',\n ],\n specs: {\n dir: {\n type: 'string',\n description: 'Project directory (default: the current one)',\n },\n },\n async run(ctx, args) {\n const project = readExperienceProject(args.dir);\n const result = await runExperienceChecks(project, {\n typecheck: false,\n loadDefinition: true,\n inlineSdk: args.env.EKANOS_INLINE_SDK,\n });\n\n const failed = failOnErrors(\n ctx,\n 'build',\n result.findings,\n { slug: project.slug },\n project.dir,\n );\n if (failed !== null) return failed;\n\n const output = await emitExperience(project, result);\n\n return ctx.succeed(\n {\n slug: project.slug,\n version: output.manifest.version,\n digest: output.manifest.digest,\n files: output.files,\n widgets: output.manifest.widgets.length,\n pages: output.manifest.pages.length,\n workflowTemplates: output.manifest.workflowTemplates.length,\n findings: result.findings,\n changed: output.changed,\n },\n `Built ${project.slug}@${output.manifest.version} (${output.manifest.digest.slice(0, 18)}…): ${output.files.join(', ')}.`,\n );\n },\n};\n"]}
|