@ekanos/cli 0.17.1 → 0.19.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 +1 -0
- package/dist/commands/add.js +1 -1
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/catalog.js +11 -7
- package/dist/commands/catalog.js.map +1 -1
- package/dist/commands/names.d.ts +19 -0
- package/dist/commands/names.js +122 -0
- package/dist/commands/names.js.map +1 -0
- package/dist/commands/publish.d.ts +53 -3
- package/dist/commands/publish.js +58 -16
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/sources.js +15 -5
- package/dist/commands/sources.js.map +1 -1
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.js +12 -12
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/sync.js +2 -2
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/teams-connect.js +1 -1
- package/dist/commands/teams-connect.js.map +1 -1
- package/dist/experience/boundary.d.ts +2 -2
- package/dist/experience/boundary.js +2 -11
- package/dist/experience/boundary.js.map +1 -1
- package/dist/experience/build.d.ts +3 -1
- package/dist/experience/build.js +15 -26
- package/dist/experience/build.js.map +1 -1
- package/dist/experience/clean-room.d.ts +40 -0
- package/dist/experience/clean-room.js +150 -0
- package/dist/experience/clean-room.js.map +1 -0
- package/dist/experience/contract-sources.d.ts +7 -2
- package/dist/experience/contract-sources.js +15 -8
- package/dist/experience/contract-sources.js.map +1 -1
- package/dist/experience/definition-checks.d.ts +12 -1
- package/dist/experience/definition-checks.js +34 -11
- package/dist/experience/definition-checks.js.map +1 -1
- package/dist/experience/definition-shape.d.ts +20 -2
- package/dist/experience/definition-shape.js.map +1 -1
- package/dist/experience/project.js +8 -2
- package/dist/experience/project.js.map +1 -1
- package/dist/experience/publish.d.ts +42 -5
- package/dist/experience/publish.js +195 -11
- package/dist/experience/publish.js.map +1 -1
- package/dist/harness-scaffold.js +3 -1
- package/dist/harness-scaffold.js.map +1 -1
- package/dist/index.js +25 -2
- package/dist/index.js.map +1 -1
- package/dist/names-api.d.ts +90 -0
- package/dist/names-api.js +123 -0
- package/dist/names-api.js.map +1 -0
- package/dist/product-kinds.d.ts +13 -0
- package/dist/product-kinds.js +17 -0
- package/dist/product-kinds.js.map +1 -0
- package/dist/publish-api.d.ts +38 -5
- package/dist/publish-api.js +59 -16
- package/dist/publish-api.js.map +1 -1
- package/dist/repo/publish.d.ts +6 -3
- package/dist/repo/publish.js +48 -14
- package/dist/repo/publish.js.map +1 -1
- package/dist/source-products-api.d.ts +3 -2
- package/dist/source-products-api.js +1 -1
- package/dist/source-products-api.js.map +1 -1
- package/dist/team-connect-api.d.ts +4 -0
- package/dist/team-connect-api.js +1 -1
- package/dist/team-connect-api.js.map +1 -1
- package/dist/toolchain-api.d.ts +15 -0
- package/dist/toolchain-api.js +12 -1
- package/dist/toolchain-api.js.map +1 -1
- package/package.json +2 -2
- package/templates/experience/package.json.tmpl +7 -4
- package/templates/harness/app/experience/layout/page.tsx.tmpl +1 -0
- package/templates/harness/app/experience/layout.tsx.tmpl +3 -0
- package/templates/harness/app/experience/pages/[id]/[...path]/page.tsx.tmpl +1 -0
- package/templates/package.json.tmpl +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"teams-connect.js","sourceRoot":"","sources":["../../src/commands/teams-connect.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n TeamAgentListSchema,\n type TeamIntegrationStatus,\n} from '@ekanos/integration-schema';\n\nimport { fieldPrompt, parseFieldValue } from '../connect-fields';\nimport type { CliContext } from '../context';\nimport { invalidStateError, usageError, validationError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport { cli } from '../invocation';\nimport { assertBrowserSafeUrl, openInBrowser } from '../open-url';\nimport {\n FIELD_SECRET_FORMS,\n collectSecrets,\n parsePlainValues,\n readSecretFlags,\n secretInputGiven,\n} from '../secret-input';\nimport {\n type FieldValue,\n type TeamConnectPlan,\n showTeamConnect,\n startTeamConnect,\n} from '../team-connect-api';\nimport { call, showTeamIntegration } from '../teams-api';\nimport type { ResultRow } from '../ui';\nimport { promptHidden, promptLine } from './apps';\nimport { scopeHiddenLines } from './scope-notice';\nimport {\n type TeamsArgs,\n type TeamsClient,\n canPrompt,\n checklist,\n promptAndSaveTeamApp,\n teamsSecretIO,\n} from './teams';\nimport { isTeamChannel, runTeamChannelInstall } from './teams-channel-install';\n\n/**\n * `teams connect <team> <product>` — connect a product for one team, doing\n * whichever the integration needs (the host's plan decides, never the CLI):\n *\n * - works as shipped → says so; not self-serve or not enabled → refuses\n * with the reason (and points at `sources products` for the latter);\n * - form fields → asks them here (secrets hidden, never as arguments) and\n * activates exactly as the app's form does;\n * - OAuth → runs `teams app set` inline when the team's own app is needed\n * first (Zendesk), then a one-time sign-in link for the member who\n * consents: the caller when a member, else `--as <email>`. Opens it for\n * the caller (unless `--no-open`), always prints it, and waits until the\n * team is connected (unless `--no-wait`);\n * - a form only the browser can fill → prints the team's page.\n *\n * `--connection <id>` connects one of the integration's named connections\n * instead of the main one — Linear's `agent`, the team's own Linear app\n * installed as a workspace member, which is what makes Linear send the\n * @mention and assignment webhooks an agent's triggers listen for. It runs\n * the same way: the team app's fields when missing, then the sign-in, then\n * the wait until it is installed.\n *\n * Without `--connection`, once the main connection is made (or already\n * was), a named connection the team's agents' triggers wait on is offered\n * next — at a terminal it asks and installs it, otherwise it names the\n * command. \"Connected\" is not the goal; an agent that can be reached is.\n *\n * `--reconnect` connects it again even though it reads as connected — for\n * a revoked or expired sign-in, or new form values. An OAuth reconnect\n * prints the link and returns: the team already reads as connected, so\n * there is nothing to wait for.\n *\n * `--link-only` keeps the old behaviour: the team's page and its status.\n *\n * `slack` and `linear-app` install the channels agent triggers answer\n * through — Slack, and Ekanos's own Linear Agents app — by the same\n * link-and-wait (`teams-channel-install.ts`).\n */\nexport async function runTeamConnect(\n ctx: CliContext,\n args: TeamsArgs,\n client: TeamsClient,\n host: string,\n source: string,\n input: { team: string; product: string; as?: string; connection?: string },\n): Promise<ExitCode> {\n const target = {\n source,\n team: input.team,\n product: input.product,\n ...(input.connection ? { connection: input.connection } : {}),\n };\n\n // Slack and Ekanos's Linear Agents app: the channels a `slack` or `linear`\n // agent trigger answers through, installed by their own flows.\n if (!input.connection && !args.linkOnly && isTeamChannel(input.product)) {\n return runTeamChannelInstall(ctx, args, client, host, source, {\n team: input.team,\n channel: input.product,\n ...(input.as ? { as: input.as } : {}),\n open: args.openUrl ?? openInBrowser,\n });\n }\n\n if (args.linkOnly) return printLink(ctx, client, host, target);\n\n const { plan } = await client.call((token) =>\n showTeamConnect(host, token, target, input.as),\n );\n const named = isNamed(plan);\n const name = named\n ? await connectionLabel(client, host, target, plan)\n : plan.product.name;\n await warnOtherRunsAs(ctx, client, host, source, plan);\n for (const line of scopeHiddenLines(plan.productScope, {\n team: plan.team.slug,\n product: plan.product.slug,\n source: plan.source.slug,\n })) {\n ctx.warn(line);\n }\n\n switch (plan.mode) {\n case 'not-entitled':\n throw invalidStateError(\n plan.reason ??\n `\"${input.product}\" is not enabled on ${plan.source.slug}.`,\n `Enable it for the Source first: \"ekanos sources products enable ${input.product}\" as a Source admin if ${plan.source.slug} built it, otherwise a super-admin (/admin in the browser). \"ekanos sources products\" shows what ${plan.source.slug} has.`,\n );\n case 'not-self-serve':\n throw invalidStateError(\n plan.reason ?? `${name} is not connected by a team.`,\n plan.product.kind === 'experience'\n ? `\"ekanos sources products --source ${plan.source.slug}\" shows whether it is on for the Source.`\n : 'It is turned on for the Source by Ekanos; there is nothing for the team to do.',\n );\n case 'unsupported':\n throw invalidStateError(\n plan.reason ?? `${name} cannot be connected from here.`,\n `Open the team's page instead: ${plan.connectUrl}`,\n );\n case 'works-as-shipped':\n return ctx.succeed(\n { host, plan, connected: true },\n ctx.ui.result({\n title: `${name} works as shipped for ${plan.team.slug}`,\n rows: [['Status', 'nothing to connect']],\n }),\n );\n case 'browser':\n return ctx.succeed(\n { host, plan, connected: plan.connected },\n ctx.ui.result({\n title: plan.connected\n ? `${plan.team.slug} has connected ${name}`\n : `${name} connects in the app for ${plan.team.slug}`,\n tone: plan.connected ? 'ok' : 'warn',\n rows: [\n ['Open', plan.connectUrl],\n ['Status', statusOf(plan)],\n ],\n notes: plan.connected\n ? []\n : [\n plan.reason ??\n `${name} connects through its own form in the app.`,\n 'A team admin signs in there and clicks Connect.',\n ],\n }),\n );\n default:\n break;\n }\n\n if (plan.connected && !args.reconnect) {\n const summary = ctx.ui.result({\n title: `${plan.team.slug} has already ${named ? 'installed' : 'connected'} ${name}`,\n rows: [\n ['Status', statusOf(plan, named)],\n ['Team page', plan.connectUrl],\n ],\n notes: [\n `\"ekanos teams show ${plan.team.slug} ${plan.product.slug}\" shows the full setup.`,\n `Broken (revoked or expired)? Connect it again: ekanos teams connect ${plan.team.slug} ${plan.product.slug}${named ? ` --connection ${plan.connectionId}` : ''} --reconnect`,\n ],\n });\n return named\n ? ctx.succeed({ host, plan, connected: true }, summary)\n : offerChannels(ctx, args, client, host, source, input, {\n data: { host, plan, connected: true },\n summary,\n });\n }\n\n if (plan.mode === 'fields' || plan.mode === 'no-fields') {\n return activate(ctx, args, client, host, target, plan);\n }\n return connectOAuth(ctx, args, client, host, target, plan, input.as, {\n name,\n then: named\n ? undefined\n : (done) => offerChannels(ctx, args, client, host, source, input, done),\n });\n}\n\n/**\n * A personal connection belongs to whoever makes it, but a provided agent\n * uses the personal connection of the person it runs as — so connecting\n * your own leaves the agent missing it (CLI audit P0-5). Name each agent\n * that runs as someone else and the command that connects it for them.\n */\nasync function warnOtherRunsAs(\n ctx: CliContext,\n client: TeamsClient,\n host: string,\n source: string,\n plan: TeamConnectPlan,\n): Promise<void> {\n const email = plan.member?.email?.toLowerCase();\n if (plan.scope !== 'user' || !email) return;\n let list;\n try {\n list = await client.call((token) =>\n call(host, token, TeamAgentListSchema, {\n method: 'GET',\n path: `/api/partner/teams/${encodeURIComponent(plan.team.slug)}/agents`,\n source,\n }),\n );\n } catch (error) {\n ctx.log(\n `Could not check who ${plan.team.slug}'s agents run as: ${error instanceof Error ? error.message : String(error)}`,\n );\n return;\n }\n for (const entry of list.agents) {\n const runsAs = entry.agent?.requirements.find(\n (item) =>\n item.key === plan.product.slug &&\n item.via === 'person' &&\n item.viaDetail &&\n item.viaDetail.toLowerCase() !== email,\n )?.viaDetail;\n if (!runsAs) continue;\n ctx.warn(\n `Note: ${entry.key} runs as ${runsAs} and uses ${runsAs}'s ${plan.product.name} connection, not ${email}'s. For the agent, run: ${cli()} teams connect ${plan.team.slug} ${plan.product.slug} --as ${runsAs} --source ${source}`,\n );\n }\n}\n\n/**\n * After the main connection: the named connections the team's agents'\n * triggers wait on and the team has not installed (Linear's agent). At a\n * terminal, ask and install each; otherwise name the command, in the\n * result and its JSON (`channelsToInstall`).\n */\nasync function offerChannels(\n ctx: CliContext,\n args: TeamsArgs,\n client: TeamsClient,\n host: string,\n source: string,\n input: { team: string; product: string; as?: string },\n done: { data: Record<string, unknown>; summary: string },\n): Promise<ExitCode> {\n const status = await client.call((token) =>\n showTeamIntegration(host, token, {\n source,\n team: input.team,\n product: input.product,\n }),\n );\n const waiting = channelsToInstall(status);\n if (waiting.length === 0) return ctx.succeed(done.data, done.summary);\n\n const command = (connectionId: string) =>\n `ekanos teams connect ${input.team} ${input.product} --connection ${connectionId} --source ${status.source.slug}`;\n const why = (entry: (typeof waiting)[number]) =>\n `${entry.label} is not installed for ${input.team}, and ${entry.neededBy.map((need) => `${need.agent} (${need.triggers.join(', ')})`).join(', ')} only start${entry.neededBy.length === 1 ? 's' : ''} through it.`;\n\n if (!canPrompt(ctx, args)) {\n return ctx.succeed(\n {\n ...done.data,\n channelsToInstall: waiting.map((entry) => ({\n connectionId: entry.connectionId,\n label: entry.label,\n neededBy: entry.neededBy,\n command: command(entry.connectionId),\n })),\n },\n [\n done.summary,\n ...waiting.flatMap((entry) => [\n `Next: ${why(entry)}`,\n ` Install it in your terminal: ${cli()} ${command(entry.connectionId)}`,\n ]),\n ].join('\\n'),\n );\n }\n\n ctx.log(done.summary);\n let code: ExitCode = 0;\n for (const entry of waiting) {\n ctx.log(why(entry));\n const answer = (\n await (args.ask ?? promptLine)(`Install ${entry.label} now? [Y/n] `)\n )\n .trim()\n .toLowerCase();\n if (answer !== '' && answer !== 'y' && answer !== 'yes') {\n ctx.log(`Skipped. Later: ${command(entry.connectionId)}`);\n continue;\n }\n code = await runTeamConnect(ctx, args, client, host, source, {\n ...input,\n connection: entry.connectionId,\n });\n }\n return code;\n}\n\n/** Named connections the team's agents wait on and the team has not installed. */\nexport function channelsToInstall(status: TeamIntegrationStatus) {\n return (status.connections ?? []).filter(\n (entry) =>\n entry.connectionId !== 'default' &&\n !entry.connected &&\n entry.neededBy.length > 0,\n );\n}\n\nfunction isNamed(plan: TeamConnectPlan): boolean {\n return Boolean(plan.connectionId && plan.connectionId !== 'default');\n}\n\nasync function connectionLabel(\n client: TeamsClient,\n host: string,\n target: { source: string; team: string; product: string },\n plan: TeamConnectPlan,\n): Promise<string> {\n const status = await client.call((token) =>\n showTeamIntegration(host, token, target),\n );\n return (\n status.connections?.find(\n (entry) => entry.connectionId === plan.connectionId,\n )?.label ??\n status.teamApps.find((entry) => entry.connectionId === plan.connectionId)\n ?.label ??\n `${plan.product.name} (${plan.connectionId})`\n );\n}\n\nasync function activate(\n ctx: CliContext,\n args: TeamsArgs,\n client: TeamsClient,\n host: string,\n target: { source: string; team: string; product: string },\n plan: TeamConnectPlan,\n): Promise<ExitCode> {\n if (plan.scope === 'user' && !plan.member) {\n throw invalidStateError(\n plan.memberProblem ??\n `${plan.product.name} is a personal connection: each member connects their own.`,\n joinHint(plan, target),\n );\n }\n\n const entered =\n plan.mode === 'fields'\n ? await enterFields(ctx, args, plan, connectAgain(target, plan))\n : { fields: {}, set: [] };\n const started = await client.call((token) =>\n startTeamConnect(host, token, target, {\n fields: entered.fields,\n ...(entered.set.length > 0 ? { set: entered.set } : {}),\n }),\n );\n return ctx.succeed(\n { host, ...started, connected: started.plan.connected },\n ctx.ui.result({\n title: `Connected ${started.plan.product.name} for ${started.plan.team.slug}`,\n rows: [\n ['Status', statusOf(started.plan)],\n [\n 'For',\n started.plan.scope === 'user'\n ? `you (${started.plan.member?.email ?? 'your account'}) — a personal connection`\n : 'the whole team',\n ],\n ['Team page', started.plan.connectUrl],\n ],\n }),\n );\n}\n\nasync function connectOAuth(\n ctx: CliContext,\n args: TeamsArgs,\n client: TeamsClient,\n host: string,\n target: {\n source: string;\n team: string;\n product: string;\n connection?: string;\n },\n plan: TeamConnectPlan,\n asEmail: string | undefined,\n options: {\n /** What is being connected: the product, or a named connection's label. */\n name: string;\n /** On success, instead of finishing: the main connection's follow-ups. */\n then?: (done: {\n data: Record<string, unknown>;\n summary: string;\n }) => Promise<ExitCode>;\n },\n): Promise<ExitCode> {\n const named = isNamed(plan);\n const name = options.name;\n const again = `ekanos teams connect ${target.team} ${target.product}${named ? ` --connection ${plan.connectionId}` : ''}`;\n if (!plan.member) {\n throw invalidStateError(\n plan.memberProblem ?? 'No member of the team can sign in yet.',\n plan.scope === 'user'\n ? joinHint(plan, target)\n : `Name a member of ${plan.team.slug} who signs in: ${again} --as <email>. Or join it and sign in yourself: ekanos teams members add ${plan.team.slug} --self --role admin`,\n );\n }\n\n if (plan.teamApp) {\n const status = await client.call((token) =>\n showTeamIntegration(host, token, target),\n );\n const connectionId = plan.connectionId ?? 'default';\n const app =\n status.teamApps.find((entry) => entry.connectionId === connectionId) ??\n (named ? undefined : status.teamApps[0]);\n if (app && app.fields.some((field) => !field.set)) {\n if (\n !canPrompt(ctx, args) &&\n !secretInputGiven(readSecretFlags(args.flags))\n ) {\n throw usageError(\n `${name} needs ${plan.team.slug}'s own app first (${app.fields\n .filter((field) => !field.set)\n .map((field) => field.secretName)\n .join(', ')}), and there is no terminal to ask at.`,\n `Without a terminal, pass --set <field>=<value> for the plain fields and ${FIELD_SECRET_FORMS}. Or run it yourself in your terminal: ${cli()} ${again} --source ${plan.source.slug}`,\n );\n }\n ctx.log(\n `${name} signs ${plan.team.slug} in through the team's own app. Set it up first:`,\n );\n await promptAndSaveTeamApp(ctx, args, client, host, target, status, app);\n }\n }\n\n // An app sign-in (GitHub, ROAM) activates on return with what the app's\n // form would add after the sign-in: asked now, applied then.\n const entered =\n plan.signIn === 'app' && plan.fields.length > 0\n ? await enterFields(\n ctx,\n args,\n plan,\n `${again} --source ${plan.source.slug}`,\n )\n : undefined;\n const started = await client.call((token) =>\n startTeamConnect(host, token, target, {\n ...(asEmail ? { as: asEmail } : {}),\n ...(entered ? { fields: entered.fields } : {}),\n ...(entered && entered.set.length > 0 ? { set: entered.set } : {}),\n }),\n );\n if (started.result !== 'consent') {\n throw invalidStateError(\n `The host answered \"${started.result}\" where a sign-in link was expected.`,\n 'Run \"ekanos upgrade\" — the CLI and the host disagree on the connect contract.',\n );\n }\n assertBrowserSafeUrl(started.authorizeUrl, 'sign-in link');\n\n const member = started.plan.member ?? plan.member;\n const forCaller = member.isCaller;\n const expires = started.expiresAt.replace('T', ' ').slice(0, 16);\n ctx.log(\n forCaller\n ? [\n named\n ? `Install ${name} for ${plan.team.slug} — sign in as an admin of the workspace it goes into, and approve it:`\n : `Sign in to ${plan.product.name} as the account ${plan.team.slug} should use${plan.scope === 'user' ? ' (a personal connection: yours)' : ''}:`,\n ` ${started.authorizeUrl}`,\n ` (one-time link, valid until ${expires} UTC)`,\n ...(plan.signIn === 'app'\n ? [\n ` It opens ${plan.product.name}'s sign-in through ${plan.source.slug}'s app: if the browser asks you to sign in to the app first, do, then open the link again.`,\n ]\n : []),\n ].join('\\n')\n : [\n `Send this link to ${member.email ?? 'the member'} — they ${named ? `install ${name}` : `sign in to ${plan.product.name}`} for ${plan.team.slug}${plan.scope === 'user' ? ' (a personal connection: theirs)' : ''}:`,\n ` ${started.authorizeUrl}`,\n ` (one-time, for them only, valid until ${expires} UTC)`,\n ...(plan.signIn === 'app'\n ? [\n ` They open it signed in to ${plan.source.slug}'s app as themselves.`,\n ]\n : []),\n ].join('\\n'),\n );\n\n // Only ever the caller's own browser: opening a link meant for another\n // member would sign the caller's provider account in for them.\n if (forCaller && !args.noOpen && !ctx.jsonMode) {\n (args.openUrl ?? openInBrowser)(started.authorizeUrl);\n }\n\n // A reconnect can't be waited on: the team already reads as connected, so\n // nothing the host reports changes when the new sign-in lands.\n const reconnecting = args.reconnect === true && plan.connected;\n if (args.noWait || ctx.jsonMode || reconnecting) {\n return ctx.succeed(\n {\n host,\n plan: started.plan,\n authorizeUrl: started.authorizeUrl,\n expiresAt: started.expiresAt,\n connected: false,\n },\n ctx.ui.hint(\n reconnecting\n ? `The current connection keeps working until the sign-in finishes; then its tokens are replaced. Check with \"ekanos teams show ${target.team} ${target.product}\".`\n : `Then check with \"ekanos teams show ${target.team} ${target.product}\".`,\n ),\n );\n }\n\n ctx.log(\n 'Waiting for the sign-in to finish (Ctrl-C stops waiting; the link stays valid)…',\n );\n const deadline = Date.parse(started.expiresAt) || Date.now() + 10 * 60 * 1000;\n while (Date.now() < deadline) {\n await new Promise((resolve) =>\n setTimeout(resolve, args.pollDelayMs ?? 3000),\n );\n const polled = await client.call((token) =>\n showTeamConnect(host, token, target, asEmail),\n );\n if (polled.plan.connected) {\n const status = await client.call((token) =>\n showTeamIntegration(host, token, target),\n );\n const done = {\n data: { host, plan: polled.plan, status, connected: true },\n summary: [\n ctx.ui.result({\n title: `${named ? 'Installed' : 'Connected'} ${name} for ${plan.team.slug}`,\n rows: [\n ['Signed in by', member.email ?? member.userId],\n ['Status', statusOf(polled.plan, named)],\n ],\n notes: named\n ? [\n `Prove it end to end: @mention the agent in ${plan.product.name}, then \"ekanos runs list --team ${plan.team.slug}\" shows the run it started.`,\n ]\n : [],\n }),\n checklist(status).join('\\n'),\n ].join('\\n'),\n };\n return options.then\n ? options.then(done)\n : ctx.succeed(done.data, done.summary);\n }\n }\n throw validationError(\n 'The sign-in did not finish before the link expired.',\n `Run \"${again}${asEmail ? ` --as ${asEmail}` : ''}\" again for a fresh link.`,\n );\n}\n\n/** The command that connects it again, for a hint. */\nfunction connectAgain(\n target: { team: string; product: string },\n plan: TeamConnectPlan,\n): string {\n return `ekanos teams connect ${target.team} ${target.product} --source ${plan.source.slug}`;\n}\n\n/**\n * A personal connection is the member's own: whoever runs connect makes\n * theirs, so a caller who is not on the team joins it first.\n */\nfunction joinHint(\n plan: TeamConnectPlan,\n target: { team: string; product: string },\n): string {\n return `It is yours to connect once you are a member: ekanos teams members add ${plan.team.slug} --self, then ${connectAgain(target, plan)}. For someone else's, send them a link: ${connectAgain(target, plan)} --as <their-email>.`;\n}\n\n/**\n * The activation fields, through the shared secret input (`secret-input.ts`)\n * that every command taking a secret uses: `--set <field>=<value>` for a\n * plain field; for a secret (which includes a JSON value, which can carry\n * one) `--set-secret <field>=env:…|file:…|stdin`, `--secret-env|file|stdin`\n * for a single one, or `--browser`; otherwise a prompt at a terminal, hidden\n * for a secret. Each value is then typed by its field (`connect-fields.ts`).\n *\n * In a script or an agent run with no secret flags, an optional field\n * nobody gave is skipped rather than refused, so a product whose fields are\n * all optional (GitHub) goes straight to its sign-in.\n *\n * `set` names the fields given by `--set`: the host refuses a secret among\n * them (`SECRET_AS_ARGUMENT`), as `--set` here already does.\n */\nasync function enterFields(\n ctx: CliContext,\n args: TeamsArgs,\n plan: TeamConnectPlan,\n again: string,\n): Promise<{ fields: Record<string, FieldValue>; set: string[] }> {\n const plain = parsePlainValues(args.flags?.set, 'default_labels=bug,triage');\n const secret = readSecretFlags(args.flags);\n const interactive = canPrompt(ctx, args);\n const asking = interactive || secretInputGiven(secret);\n // Without a terminal, a secret flag or any --set, only the required fields\n // are asked for (and refused); an optional one is skipped.\n const fields =\n asking || Object.keys(plain).length > 0\n ? plan.fields\n : plan.fields.filter((field) => field.required);\n if (\n interactive &&\n !secretInputGiven(secret) &&\n fields.some((field) => !(field.name in plain))\n ) {\n ctx.log(\n `${plan.product.name} for ${plan.scope === 'user' ? 'you, in' : 'team'} ${plan.team.slug}: enter what the app's form asks${plan.signIn === 'app' ? ' after the sign-in' : ''}. Secrets are hidden and never shown again.`,\n );\n }\n\n const byName = new Map(plan.fields.map((field) => [field.name, field]));\n const raw =\n fields.length === 0 && Object.keys(plain).length === 0\n ? {}\n : await collectSecrets(ctx, {\n fields: fields.map((field) => ({\n name: field.name,\n label: field.label,\n sensitive: field.sensitive,\n required: field.required,\n ...(field.description ? { description: field.description } : {}),\n })),\n plain,\n flags: secret,\n io: teamsSecretIO(args),\n interactive,\n title: `${plan.product.name} for ${plan.team.slug}`,\n refusal: `${plan.product.name} needs its form's fields (${fields\n .filter((field) => field.required)\n .map((field) => `${field.label} [${field.name}]`)\n .join(', ')}), and there is no terminal to ask at.`,\n again: again.replace(/^ekanos /, ''),\n prompt: (spec) => {\n const field = byName.get(spec.name)!;\n if (field.description) ctx.log(` ${field.description}`);\n return (\n field.sensitive\n ? (args.askSecret ?? promptHidden)\n : (args.ask ?? promptLine)\n )(fieldPrompt(field));\n },\n });\n\n const values: Record<string, FieldValue> = {};\n for (const [name, text] of Object.entries(raw)) {\n const field = byName.get(name);\n if (!field) continue;\n const value = parseFieldValue(field, text);\n if (value !== undefined) values[name] = value;\n }\n const missing = plan.fields.filter(\n (field) => field.required && values[field.name] === undefined,\n );\n if (missing.length > 0) {\n throw validationError(\n `${missing.map((field) => `${field.label} (${field.name})`).join(', ')} ${missing.length === 1 ? 'is' : 'are'} needed.`,\n `Run \"${again}\" again.`,\n );\n }\n return {\n fields: values,\n set: Object.keys(plain).filter((name) => plain[name] !== ''),\n };\n}\n\n/** `--link-only`: the team's page and whether it is connected. */\nasync function printLink(\n ctx: CliContext,\n client: TeamsClient,\n host: string,\n target: { source: string; team: string; product: string },\n): Promise<ExitCode> {\n const status = await client.call((token) =>\n showTeamIntegration(host, token, target),\n );\n if (!status.enabled) {\n throw invalidStateError(\n `\"${target.product}\" is not enabled on ${status.source.slug}.`,\n `\"ekanos sources products --source ${status.source.slug}\" shows what this Source has; a super-admin enables a product for a Source.`,\n );\n }\n const connected = status.activation !== null;\n const rows: ResultRow[] = [\n ['Open', status.connectUrl],\n [\n 'Status',\n connected\n ? `connected${status.activation?.activatedAt ? ` ${status.activation.activatedAt.slice(0, 10)}` : ''}`\n : 'not connected',\n ],\n ];\n return ctx.succeed(\n { host, ...status },\n ctx.ui.result({\n title: connected\n ? `${status.team.slug} has connected ${status.product.name}`\n : `Connect link for ${status.team.slug} · ${status.product.name}`,\n tone: connected ? 'ok' : 'warn',\n rows,\n notes: [\n 'A team member signs in there and clicks Connect.',\n `\"ekanos teams connect ${status.team.slug} ${status.product.slug}\" (without --link-only) connects it from here.`,\n ],\n }),\n );\n}\n\nfunction statusOf(plan: TeamConnectPlan, named = false): string {\n if (!plan.connected) return named ? 'not installed' : 'not connected';\n return `${named ? 'installed' : 'connected'}${plan.connectedAt ? ` ${plan.connectedAt.slice(0, 10)}` : ''}`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"teams-connect.js","sourceRoot":"","sources":["../../src/commands/teams-connect.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n TeamAgentListSchema,\n type TeamIntegrationStatus,\n} from '@ekanos/integration-schema';\n\nimport { fieldPrompt, parseFieldValue } from '../connect-fields';\nimport type { CliContext } from '../context';\nimport { invalidStateError, usageError, validationError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport { cli } from '../invocation';\nimport { assertBrowserSafeUrl, openInBrowser } from '../open-url';\nimport {\n FIELD_SECRET_FORMS,\n collectSecrets,\n parsePlainValues,\n readSecretFlags,\n secretInputGiven,\n} from '../secret-input';\nimport {\n type FieldValue,\n type TeamConnectPlan,\n showTeamConnect,\n startTeamConnect,\n} from '../team-connect-api';\nimport { call, showTeamIntegration } from '../teams-api';\nimport type { ResultRow } from '../ui';\nimport { promptHidden, promptLine } from './apps';\nimport { scopeHiddenLines } from './scope-notice';\nimport {\n type TeamsArgs,\n type TeamsClient,\n canPrompt,\n checklist,\n promptAndSaveTeamApp,\n teamsSecretIO,\n} from './teams';\nimport { isTeamChannel, runTeamChannelInstall } from './teams-channel-install';\n\n/**\n * `teams connect <team> <product>` — connect a product for one team, doing\n * whichever the integration needs (the host's plan decides, never the CLI):\n *\n * - works as shipped → says so; not self-serve or not enabled → refuses\n * with the reason (and points at `sources products` for the latter);\n * - form fields → asks them here (secrets hidden, never as arguments) and\n * activates exactly as the app's form does;\n * - OAuth → runs `teams app set` inline when the team's own app is needed\n * first (Zendesk), then a one-time sign-in link for the member who\n * consents: the caller when a member, else `--as <email>`. Opens it for\n * the caller (unless `--no-open`), always prints it, and waits until the\n * team is connected (unless `--no-wait`);\n * - a form only the browser can fill → prints the team's page.\n *\n * `--connection <id>` connects one of the integration's named connections\n * instead of the main one — Linear's `agent`, the team's own Linear app\n * installed as a workspace member, which is what makes Linear send the\n * @mention and assignment webhooks an agent's triggers listen for. It runs\n * the same way: the team app's fields when missing, then the sign-in, then\n * the wait until it is installed.\n *\n * Without `--connection`, once the main connection is made (or already\n * was), a named connection the team's agents' triggers wait on is offered\n * next — at a terminal it asks and installs it, otherwise it names the\n * command. \"Connected\" is not the goal; an agent that can be reached is.\n *\n * `--reconnect` connects it again even though it reads as connected — for\n * a revoked or expired sign-in, or new form values. An OAuth reconnect\n * prints the link and returns: the team already reads as connected, so\n * there is nothing to wait for.\n *\n * `--link-only` keeps the old behaviour: the team's page and its status.\n *\n * `slack` and `linear-app` install the channels agent triggers answer\n * through — Slack, and Ekanos's own Linear Agents app — by the same\n * link-and-wait (`teams-channel-install.ts`).\n */\nexport async function runTeamConnect(\n ctx: CliContext,\n args: TeamsArgs,\n client: TeamsClient,\n host: string,\n source: string,\n input: { team: string; product: string; as?: string; connection?: string },\n): Promise<ExitCode> {\n const target = {\n source,\n team: input.team,\n product: input.product,\n ...(input.connection ? { connection: input.connection } : {}),\n };\n\n // Slack and Ekanos's Linear Agents app: the channels a `slack` or `linear`\n // agent trigger answers through, installed by their own flows.\n if (!input.connection && !args.linkOnly && isTeamChannel(input.product)) {\n return runTeamChannelInstall(ctx, args, client, host, source, {\n team: input.team,\n channel: input.product,\n ...(input.as ? { as: input.as } : {}),\n open: args.openUrl ?? openInBrowser,\n });\n }\n\n if (args.linkOnly) return printLink(ctx, client, host, target);\n\n const { plan } = await client.call((token) =>\n showTeamConnect(host, token, target, input.as),\n );\n const named = isNamed(plan);\n const name = named\n ? await connectionLabel(client, host, target, plan)\n : plan.product.name;\n await warnOtherRunsAs(ctx, client, host, source, plan);\n for (const line of scopeHiddenLines(plan.productScope, {\n team: plan.team.slug,\n product: plan.product.slug,\n source: plan.source.slug,\n })) {\n ctx.warn(line);\n }\n\n switch (plan.mode) {\n case 'not-entitled':\n throw invalidStateError(\n plan.reason ??\n `\"${input.product}\" is not enabled on ${plan.source.slug}.`,\n `Enable it for the Source first: \"ekanos sources products enable ${input.product}\" as a Source admin if ${plan.source.slug} built it, otherwise a super-admin (/admin in the browser). \"ekanos sources products\" shows what ${plan.source.slug} has.`,\n );\n case 'not-self-serve':\n throw invalidStateError(\n plan.reason ?? `${name} is not connected by a team.`,\n plan.product.kind === 'feature' || plan.product.kind === 'experience'\n ? `\"ekanos sources products --source ${plan.source.slug}\" shows whether it is on for the Source.`\n : 'It is turned on for the Source by Ekanos; there is nothing for the team to do.',\n );\n case 'unsupported':\n throw invalidStateError(\n plan.reason ?? `${name} cannot be connected from here.`,\n `Open the team's page instead: ${plan.connectUrl}`,\n );\n case 'works-as-shipped':\n return ctx.succeed(\n { host, plan, connected: true },\n ctx.ui.result({\n title: `${name} works as shipped for ${plan.team.slug}`,\n rows: [['Status', 'nothing to connect']],\n }),\n );\n case 'browser':\n return ctx.succeed(\n { host, plan, connected: plan.connected },\n ctx.ui.result({\n title: plan.connected\n ? `${plan.team.slug} has connected ${name}`\n : `${name} connects in the app for ${plan.team.slug}`,\n tone: plan.connected ? 'ok' : 'warn',\n rows: [\n ['Open', plan.connectUrl],\n ['Status', statusOf(plan)],\n ],\n notes: plan.connected\n ? []\n : [\n plan.reason ??\n `${name} connects through its own form in the app.`,\n 'A team admin signs in there and clicks Connect.',\n ],\n }),\n );\n default:\n break;\n }\n\n if (plan.connected && !args.reconnect) {\n const summary = ctx.ui.result({\n title: `${plan.team.slug} has already ${named ? 'installed' : 'connected'} ${name}`,\n rows: [\n ['Status', statusOf(plan, named)],\n ['Team page', plan.connectUrl],\n ],\n notes: [\n `\"ekanos teams show ${plan.team.slug} ${plan.product.slug}\" shows the full setup.`,\n `Broken (revoked or expired)? Connect it again: ekanos teams connect ${plan.team.slug} ${plan.product.slug}${named ? ` --connection ${plan.connectionId}` : ''} --reconnect`,\n ],\n });\n return named\n ? ctx.succeed({ host, plan, connected: true }, summary)\n : offerChannels(ctx, args, client, host, source, input, {\n data: { host, plan, connected: true },\n summary,\n });\n }\n\n if (plan.mode === 'fields' || plan.mode === 'no-fields') {\n return activate(ctx, args, client, host, target, plan);\n }\n return connectOAuth(ctx, args, client, host, target, plan, input.as, {\n name,\n then: named\n ? undefined\n : (done) => offerChannels(ctx, args, client, host, source, input, done),\n });\n}\n\n/**\n * A personal connection belongs to whoever makes it, but a provided agent\n * uses the personal connection of the person it runs as — so connecting\n * your own leaves the agent missing it (CLI audit P0-5). Name each agent\n * that runs as someone else and the command that connects it for them.\n */\nasync function warnOtherRunsAs(\n ctx: CliContext,\n client: TeamsClient,\n host: string,\n source: string,\n plan: TeamConnectPlan,\n): Promise<void> {\n const email = plan.member?.email?.toLowerCase();\n if (plan.scope !== 'user' || !email) return;\n let list;\n try {\n list = await client.call((token) =>\n call(host, token, TeamAgentListSchema, {\n method: 'GET',\n path: `/api/partner/teams/${encodeURIComponent(plan.team.slug)}/agents`,\n source,\n }),\n );\n } catch (error) {\n ctx.log(\n `Could not check who ${plan.team.slug}'s agents run as: ${error instanceof Error ? error.message : String(error)}`,\n );\n return;\n }\n for (const entry of list.agents) {\n const runsAs = entry.agent?.requirements.find(\n (item) =>\n item.key === plan.product.slug &&\n item.via === 'person' &&\n item.viaDetail &&\n item.viaDetail.toLowerCase() !== email,\n )?.viaDetail;\n if (!runsAs) continue;\n ctx.warn(\n `Note: ${entry.key} runs as ${runsAs} and uses ${runsAs}'s ${plan.product.name} connection, not ${email}'s. For the agent, run: ${cli()} teams connect ${plan.team.slug} ${plan.product.slug} --as ${runsAs} --source ${source}`,\n );\n }\n}\n\n/**\n * After the main connection: the named connections the team's agents'\n * triggers wait on and the team has not installed (Linear's agent). At a\n * terminal, ask and install each; otherwise name the command, in the\n * result and its JSON (`channelsToInstall`).\n */\nasync function offerChannels(\n ctx: CliContext,\n args: TeamsArgs,\n client: TeamsClient,\n host: string,\n source: string,\n input: { team: string; product: string; as?: string },\n done: { data: Record<string, unknown>; summary: string },\n): Promise<ExitCode> {\n const status = await client.call((token) =>\n showTeamIntegration(host, token, {\n source,\n team: input.team,\n product: input.product,\n }),\n );\n const waiting = channelsToInstall(status);\n if (waiting.length === 0) return ctx.succeed(done.data, done.summary);\n\n const command = (connectionId: string) =>\n `ekanos teams connect ${input.team} ${input.product} --connection ${connectionId} --source ${status.source.slug}`;\n const why = (entry: (typeof waiting)[number]) =>\n `${entry.label} is not installed for ${input.team}, and ${entry.neededBy.map((need) => `${need.agent} (${need.triggers.join(', ')})`).join(', ')} only start${entry.neededBy.length === 1 ? 's' : ''} through it.`;\n\n if (!canPrompt(ctx, args)) {\n return ctx.succeed(\n {\n ...done.data,\n channelsToInstall: waiting.map((entry) => ({\n connectionId: entry.connectionId,\n label: entry.label,\n neededBy: entry.neededBy,\n command: command(entry.connectionId),\n })),\n },\n [\n done.summary,\n ...waiting.flatMap((entry) => [\n `Next: ${why(entry)}`,\n ` Install it in your terminal: ${cli()} ${command(entry.connectionId)}`,\n ]),\n ].join('\\n'),\n );\n }\n\n ctx.log(done.summary);\n let code: ExitCode = 0;\n for (const entry of waiting) {\n ctx.log(why(entry));\n const answer = (\n await (args.ask ?? promptLine)(`Install ${entry.label} now? [Y/n] `)\n )\n .trim()\n .toLowerCase();\n if (answer !== '' && answer !== 'y' && answer !== 'yes') {\n ctx.log(`Skipped. Later: ${command(entry.connectionId)}`);\n continue;\n }\n code = await runTeamConnect(ctx, args, client, host, source, {\n ...input,\n connection: entry.connectionId,\n });\n }\n return code;\n}\n\n/** Named connections the team's agents wait on and the team has not installed. */\nexport function channelsToInstall(status: TeamIntegrationStatus) {\n return (status.connections ?? []).filter(\n (entry) =>\n entry.connectionId !== 'default' &&\n !entry.connected &&\n entry.neededBy.length > 0,\n );\n}\n\nfunction isNamed(plan: TeamConnectPlan): boolean {\n return Boolean(plan.connectionId && plan.connectionId !== 'default');\n}\n\nasync function connectionLabel(\n client: TeamsClient,\n host: string,\n target: { source: string; team: string; product: string },\n plan: TeamConnectPlan,\n): Promise<string> {\n const status = await client.call((token) =>\n showTeamIntegration(host, token, target),\n );\n return (\n status.connections?.find(\n (entry) => entry.connectionId === plan.connectionId,\n )?.label ??\n status.teamApps.find((entry) => entry.connectionId === plan.connectionId)\n ?.label ??\n `${plan.product.name} (${plan.connectionId})`\n );\n}\n\nasync function activate(\n ctx: CliContext,\n args: TeamsArgs,\n client: TeamsClient,\n host: string,\n target: { source: string; team: string; product: string },\n plan: TeamConnectPlan,\n): Promise<ExitCode> {\n if (plan.scope === 'user' && !plan.member) {\n throw invalidStateError(\n plan.memberProblem ??\n `${plan.product.name} is a personal connection: each member connects their own.`,\n joinHint(plan, target),\n );\n }\n\n const entered =\n plan.mode === 'fields'\n ? await enterFields(ctx, args, plan, connectAgain(target, plan))\n : { fields: {}, set: [] };\n const started = await client.call((token) =>\n startTeamConnect(host, token, target, {\n fields: entered.fields,\n ...(entered.set.length > 0 ? { set: entered.set } : {}),\n }),\n );\n return ctx.succeed(\n { host, ...started, connected: started.plan.connected },\n ctx.ui.result({\n title: `Connected ${started.plan.product.name} for ${started.plan.team.slug}`,\n rows: [\n ['Status', statusOf(started.plan)],\n [\n 'For',\n started.plan.scope === 'user'\n ? `you (${started.plan.member?.email ?? 'your account'}) — a personal connection`\n : 'the whole team',\n ],\n ['Team page', started.plan.connectUrl],\n ],\n }),\n );\n}\n\nasync function connectOAuth(\n ctx: CliContext,\n args: TeamsArgs,\n client: TeamsClient,\n host: string,\n target: {\n source: string;\n team: string;\n product: string;\n connection?: string;\n },\n plan: TeamConnectPlan,\n asEmail: string | undefined,\n options: {\n /** What is being connected: the product, or a named connection's label. */\n name: string;\n /** On success, instead of finishing: the main connection's follow-ups. */\n then?: (done: {\n data: Record<string, unknown>;\n summary: string;\n }) => Promise<ExitCode>;\n },\n): Promise<ExitCode> {\n const named = isNamed(plan);\n const name = options.name;\n const again = `ekanos teams connect ${target.team} ${target.product}${named ? ` --connection ${plan.connectionId}` : ''}`;\n if (!plan.member) {\n throw invalidStateError(\n plan.memberProblem ?? 'No member of the team can sign in yet.',\n plan.scope === 'user'\n ? joinHint(plan, target)\n : `Name a member of ${plan.team.slug} who signs in: ${again} --as <email>. Or join it and sign in yourself: ekanos teams members add ${plan.team.slug} --self --role admin`,\n );\n }\n\n if (plan.teamApp) {\n const status = await client.call((token) =>\n showTeamIntegration(host, token, target),\n );\n const connectionId = plan.connectionId ?? 'default';\n const app =\n status.teamApps.find((entry) => entry.connectionId === connectionId) ??\n (named ? undefined : status.teamApps[0]);\n if (app && app.fields.some((field) => !field.set)) {\n if (\n !canPrompt(ctx, args) &&\n !secretInputGiven(readSecretFlags(args.flags))\n ) {\n throw usageError(\n `${name} needs ${plan.team.slug}'s own app first (${app.fields\n .filter((field) => !field.set)\n .map((field) => field.secretName)\n .join(', ')}), and there is no terminal to ask at.`,\n `Without a terminal, pass --set <field>=<value> for the plain fields and ${FIELD_SECRET_FORMS}. Or run it yourself in your terminal: ${cli()} ${again} --source ${plan.source.slug}`,\n );\n }\n ctx.log(\n `${name} signs ${plan.team.slug} in through the team's own app. Set it up first:`,\n );\n await promptAndSaveTeamApp(ctx, args, client, host, target, status, app);\n }\n }\n\n // An app sign-in (GitHub, ROAM) activates on return with what the app's\n // form would add after the sign-in: asked now, applied then.\n const entered =\n plan.signIn === 'app' && plan.fields.length > 0\n ? await enterFields(\n ctx,\n args,\n plan,\n `${again} --source ${plan.source.slug}`,\n )\n : undefined;\n const started = await client.call((token) =>\n startTeamConnect(host, token, target, {\n ...(asEmail ? { as: asEmail } : {}),\n ...(entered ? { fields: entered.fields } : {}),\n ...(entered && entered.set.length > 0 ? { set: entered.set } : {}),\n }),\n );\n if (started.result !== 'consent') {\n throw invalidStateError(\n `The host answered \"${started.result}\" where a sign-in link was expected.`,\n 'Run \"ekanos upgrade\" — the CLI and the host disagree on the connect contract.',\n );\n }\n assertBrowserSafeUrl(started.authorizeUrl, 'sign-in link');\n\n const member = started.plan.member ?? plan.member;\n const forCaller = member.isCaller;\n const expires = started.expiresAt.replace('T', ' ').slice(0, 16);\n ctx.log(\n forCaller\n ? [\n named\n ? `Install ${name} for ${plan.team.slug} — sign in as an admin of the workspace it goes into, and approve it:`\n : `Sign in to ${plan.product.name} as the account ${plan.team.slug} should use${plan.scope === 'user' ? ' (a personal connection: yours)' : ''}:`,\n ` ${started.authorizeUrl}`,\n ` (one-time link, valid until ${expires} UTC)`,\n ...(plan.signIn === 'app'\n ? [\n ` It opens ${plan.product.name}'s sign-in through ${plan.source.slug}'s app: if the browser asks you to sign in to the app first, do, then open the link again.`,\n ]\n : []),\n ].join('\\n')\n : [\n `Send this link to ${member.email ?? 'the member'} — they ${named ? `install ${name}` : `sign in to ${plan.product.name}`} for ${plan.team.slug}${plan.scope === 'user' ? ' (a personal connection: theirs)' : ''}:`,\n ` ${started.authorizeUrl}`,\n ` (one-time, for them only, valid until ${expires} UTC)`,\n ...(plan.signIn === 'app'\n ? [\n ` They open it signed in to ${plan.source.slug}'s app as themselves.`,\n ]\n : []),\n ].join('\\n'),\n );\n\n // Only ever the caller's own browser: opening a link meant for another\n // member would sign the caller's provider account in for them.\n if (forCaller && !args.noOpen && !ctx.jsonMode) {\n (args.openUrl ?? openInBrowser)(started.authorizeUrl);\n }\n\n // A reconnect can't be waited on: the team already reads as connected, so\n // nothing the host reports changes when the new sign-in lands.\n const reconnecting = args.reconnect === true && plan.connected;\n if (args.noWait || ctx.jsonMode || reconnecting) {\n return ctx.succeed(\n {\n host,\n plan: started.plan,\n authorizeUrl: started.authorizeUrl,\n expiresAt: started.expiresAt,\n connected: false,\n },\n ctx.ui.hint(\n reconnecting\n ? `The current connection keeps working until the sign-in finishes; then its tokens are replaced. Check with \"ekanos teams show ${target.team} ${target.product}\".`\n : `Then check with \"ekanos teams show ${target.team} ${target.product}\".`,\n ),\n );\n }\n\n ctx.log(\n 'Waiting for the sign-in to finish (Ctrl-C stops waiting; the link stays valid)…',\n );\n const deadline = Date.parse(started.expiresAt) || Date.now() + 10 * 60 * 1000;\n while (Date.now() < deadline) {\n await new Promise((resolve) =>\n setTimeout(resolve, args.pollDelayMs ?? 3000),\n );\n const polled = await client.call((token) =>\n showTeamConnect(host, token, target, asEmail),\n );\n if (polled.plan.connected) {\n const status = await client.call((token) =>\n showTeamIntegration(host, token, target),\n );\n const done = {\n data: { host, plan: polled.plan, status, connected: true },\n summary: [\n ctx.ui.result({\n title: `${named ? 'Installed' : 'Connected'} ${name} for ${plan.team.slug}`,\n rows: [\n ['Signed in by', member.email ?? member.userId],\n ['Status', statusOf(polled.plan, named)],\n ],\n notes: named\n ? [\n `Prove it end to end: @mention the agent in ${plan.product.name}, then \"ekanos runs list --team ${plan.team.slug}\" shows the run it started.`,\n ]\n : [],\n }),\n checklist(status).join('\\n'),\n ].join('\\n'),\n };\n return options.then\n ? options.then(done)\n : ctx.succeed(done.data, done.summary);\n }\n }\n throw validationError(\n 'The sign-in did not finish before the link expired.',\n `Run \"${again}${asEmail ? ` --as ${asEmail}` : ''}\" again for a fresh link.`,\n );\n}\n\n/** The command that connects it again, for a hint. */\nfunction connectAgain(\n target: { team: string; product: string },\n plan: TeamConnectPlan,\n): string {\n return `ekanos teams connect ${target.team} ${target.product} --source ${plan.source.slug}`;\n}\n\n/**\n * A personal connection is the member's own: whoever runs connect makes\n * theirs, so a caller who is not on the team joins it first.\n */\nfunction joinHint(\n plan: TeamConnectPlan,\n target: { team: string; product: string },\n): string {\n return `It is yours to connect once you are a member: ekanos teams members add ${plan.team.slug} --self, then ${connectAgain(target, plan)}. For someone else's, send them a link: ${connectAgain(target, plan)} --as <their-email>.`;\n}\n\n/**\n * The activation fields, through the shared secret input (`secret-input.ts`)\n * that every command taking a secret uses: `--set <field>=<value>` for a\n * plain field; for a secret (which includes a JSON value, which can carry\n * one) `--set-secret <field>=env:…|file:…|stdin`, `--secret-env|file|stdin`\n * for a single one, or `--browser`; otherwise a prompt at a terminal, hidden\n * for a secret. Each value is then typed by its field (`connect-fields.ts`).\n *\n * In a script or an agent run with no secret flags, an optional field\n * nobody gave is skipped rather than refused, so a product whose fields are\n * all optional (GitHub) goes straight to its sign-in.\n *\n * `set` names the fields given by `--set`: the host refuses a secret among\n * them (`SECRET_AS_ARGUMENT`), as `--set` here already does.\n */\nasync function enterFields(\n ctx: CliContext,\n args: TeamsArgs,\n plan: TeamConnectPlan,\n again: string,\n): Promise<{ fields: Record<string, FieldValue>; set: string[] }> {\n const plain = parsePlainValues(args.flags?.set, 'default_labels=bug,triage');\n const secret = readSecretFlags(args.flags);\n const interactive = canPrompt(ctx, args);\n const asking = interactive || secretInputGiven(secret);\n // Without a terminal, a secret flag or any --set, only the required fields\n // are asked for (and refused); an optional one is skipped.\n const fields =\n asking || Object.keys(plain).length > 0\n ? plan.fields\n : plan.fields.filter((field) => field.required);\n if (\n interactive &&\n !secretInputGiven(secret) &&\n fields.some((field) => !(field.name in plain))\n ) {\n ctx.log(\n `${plan.product.name} for ${plan.scope === 'user' ? 'you, in' : 'team'} ${plan.team.slug}: enter what the app's form asks${plan.signIn === 'app' ? ' after the sign-in' : ''}. Secrets are hidden and never shown again.`,\n );\n }\n\n const byName = new Map(plan.fields.map((field) => [field.name, field]));\n const raw =\n fields.length === 0 && Object.keys(plain).length === 0\n ? {}\n : await collectSecrets(ctx, {\n fields: fields.map((field) => ({\n name: field.name,\n label: field.label,\n sensitive: field.sensitive,\n required: field.required,\n ...(field.description ? { description: field.description } : {}),\n })),\n plain,\n flags: secret,\n io: teamsSecretIO(args),\n interactive,\n title: `${plan.product.name} for ${plan.team.slug}`,\n refusal: `${plan.product.name} needs its form's fields (${fields\n .filter((field) => field.required)\n .map((field) => `${field.label} [${field.name}]`)\n .join(', ')}), and there is no terminal to ask at.`,\n again: again.replace(/^ekanos /, ''),\n prompt: (spec) => {\n const field = byName.get(spec.name)!;\n if (field.description) ctx.log(` ${field.description}`);\n return (\n field.sensitive\n ? (args.askSecret ?? promptHidden)\n : (args.ask ?? promptLine)\n )(fieldPrompt(field));\n },\n });\n\n const values: Record<string, FieldValue> = {};\n for (const [name, text] of Object.entries(raw)) {\n const field = byName.get(name);\n if (!field) continue;\n const value = parseFieldValue(field, text);\n if (value !== undefined) values[name] = value;\n }\n const missing = plan.fields.filter(\n (field) => field.required && values[field.name] === undefined,\n );\n if (missing.length > 0) {\n throw validationError(\n `${missing.map((field) => `${field.label} (${field.name})`).join(', ')} ${missing.length === 1 ? 'is' : 'are'} needed.`,\n `Run \"${again}\" again.`,\n );\n }\n return {\n fields: values,\n set: Object.keys(plain).filter((name) => plain[name] !== ''),\n };\n}\n\n/** `--link-only`: the team's page and whether it is connected. */\nasync function printLink(\n ctx: CliContext,\n client: TeamsClient,\n host: string,\n target: { source: string; team: string; product: string },\n): Promise<ExitCode> {\n const status = await client.call((token) =>\n showTeamIntegration(host, token, target),\n );\n if (!status.enabled) {\n throw invalidStateError(\n `\"${target.product}\" is not enabled on ${status.source.slug}.`,\n `\"ekanos sources products --source ${status.source.slug}\" shows what this Source has; a super-admin enables a product for a Source.`,\n );\n }\n const connected = status.activation !== null;\n const rows: ResultRow[] = [\n ['Open', status.connectUrl],\n [\n 'Status',\n connected\n ? `connected${status.activation?.activatedAt ? ` ${status.activation.activatedAt.slice(0, 10)}` : ''}`\n : 'not connected',\n ],\n ];\n return ctx.succeed(\n { host, ...status },\n ctx.ui.result({\n title: connected\n ? `${status.team.slug} has connected ${status.product.name}`\n : `Connect link for ${status.team.slug} · ${status.product.name}`,\n tone: connected ? 'ok' : 'warn',\n rows,\n notes: [\n 'A team member signs in there and clicks Connect.',\n `\"ekanos teams connect ${status.team.slug} ${status.product.slug}\" (without --link-only) connects it from here.`,\n ],\n }),\n );\n}\n\nfunction statusOf(plan: TeamConnectPlan, named = false): string {\n if (!plan.connected) return named ? 'not installed' : 'not connected';\n return `${named ? 'installed' : 'connected'}${plan.connectedAt ? ` ${plan.connectedAt.slice(0, 10)}` : ''}`;\n}\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Finding } from '@ekanos/integration-schema';
|
|
2
2
|
import type { ExperienceProject } from './project.js';
|
|
3
3
|
export declare const BOUNDARY_CHECK = "checks/experience-boundary";
|
|
4
4
|
/** Packages that may stay external at runtime (the host provides them). */
|
|
5
|
-
export declare const ALLOWED_EXTERNALS: readonly [
|
|
5
|
+
export declare const ALLOWED_EXTERNALS: readonly ["react", "react-dom", "@ekanos/sdk", "@ekanos/ui", "zod", "@tanstack/react-query", "next-intl", "react-hook-form", "@hookform/resolvers"];
|
|
6
6
|
/** Nearest `ekanos.json` at or above `start`, with its kind, or null. */
|
|
7
7
|
export declare function nearestEkanosKind(start: string): {
|
|
8
8
|
dir: string;
|
|
@@ -1,20 +1,11 @@
|
|
|
1
|
+
import { EXPERIENCE_HOST_EXTERNALS, } from '@ekanos/integration-schema';
|
|
1
2
|
import { build } from 'esbuild';
|
|
2
3
|
import * as fs from 'node:fs';
|
|
3
4
|
import * as path from 'node:path';
|
|
4
5
|
import { isContained } from '../safe-fs.js';
|
|
5
6
|
export const BOUNDARY_CHECK = 'checks/experience-boundary';
|
|
6
7
|
/** Packages that may stay external at runtime (the host provides them). */
|
|
7
|
-
export const ALLOWED_EXTERNALS =
|
|
8
|
-
'react',
|
|
9
|
-
'react-dom',
|
|
10
|
-
'@ekanos/sdk',
|
|
11
|
-
'@ekanos/ui',
|
|
12
|
-
'zod',
|
|
13
|
-
'@tanstack/react-query',
|
|
14
|
-
'next-intl',
|
|
15
|
-
'react-hook-form',
|
|
16
|
-
'@hookform/resolvers',
|
|
17
|
-
];
|
|
8
|
+
export const ALLOWED_EXTERNALS = EXPERIENCE_HOST_EXTERNALS;
|
|
18
9
|
const INTEGRATION_PACKAGE = /^@companydotcom\/integration-[a-z0-9-]+/;
|
|
19
10
|
/** A pnpm-store or plain node_modules path of an integration package. */
|
|
20
11
|
const INTEGRATION_IN_PATH = /@companydotcom[/+]integration-[a-z0-9-]+/;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boundary.js","sourceRoot":"","sources":["../../src/experience/boundary.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Finding } from '@ekanos/integration-schema';\nimport { build } from 'esbuild';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport { isContained } from '../safe-fs';\nimport type { ExperienceProject } from './project';\n\nexport const BOUNDARY_CHECK = 'checks/experience-boundary';\n\n/** Packages that may stay external at runtime (the host provides them). */\nexport const ALLOWED_EXTERNALS = [\n 'react',\n 'react-dom',\n '@ekanos/sdk',\n '@ekanos/ui',\n 'zod',\n '@tanstack/react-query',\n 'next-intl',\n 'react-hook-form',\n '@hookform/resolvers',\n] as const;\n\nconst INTEGRATION_PACKAGE = /^@companydotcom\\/integration-[a-z0-9-]+/;\n/** A pnpm-store or plain node_modules path of an integration package. */\nconst INTEGRATION_IN_PATH = /@companydotcom[/+]integration-[a-z0-9-]+/;\nconst HOST_INTERNAL = /^@kit\\//;\n\nconst SOURCE_EXT = /\\.(?:[cm]?[jt]sx?)$/;\nconst SKIP_DIRS = new Set(['node_modules', 'dist', '.ekanos', '.git']);\n\nconst finding = (\n message: string,\n hint: string,\n file?: string,\n line?: number,\n): Finding => ({\n check: BOUNDARY_CHECK,\n severity: 'error',\n message,\n hint,\n ...(file ? { file } : {}),\n ...(line ? { line } : {}),\n});\n\nconst INTEGRATION_HINT =\n 'An experience reaches an integration only through its pinned contract: useOperation / operation() / step.tool. Add the integration with \"ekanos add <integration>@<version>\".';\n\n/** Nearest `ekanos.json` at or above `start`, with its kind, or null. */\nexport function nearestEkanosKind(\n start: string,\n): { dir: string; kind: string } | null {\n let current =\n fs.existsSync(start) && fs.statSync(start).isDirectory()\n ? start\n : path.dirname(start);\n for (;;) {\n const file = path.join(current, 'ekanos.json');\n if (fs.existsSync(file)) {\n try {\n const parsed = JSON.parse(fs.readFileSync(file, 'utf8')) as {\n kind?: string;\n };\n\n return { dir: current, kind: parsed.kind ?? 'integration' };\n } catch {\n return { dir: current, kind: 'integration' };\n }\n }\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\n\n// ─── 1. package.json ────────────────────────────────────────────────────────\n\nconst DEP_FIELDS = [\n 'dependencies',\n 'devDependencies',\n 'peerDependencies',\n 'optionalDependencies',\n] as const;\n\nfunction checkPackageJson(project: ExperienceProject): Finding[] {\n const file = path.join(project.dir, 'package.json');\n if (!fs.existsSync(file)) return [];\n const findings: Finding[] = [];\n const pkg = JSON.parse(fs.readFileSync(file, 'utf8')) as Record<\n string,\n unknown\n >;\n\n const specs: Array<[string, string]> = [];\n for (const field of DEP_FIELDS) {\n const block = pkg[field];\n if (block && typeof block === 'object') {\n specs.push(...Object.entries(block as Record<string, string>));\n }\n }\n const pnpm = pkg.pnpm as { overrides?: Record<string, string> } | undefined;\n for (const block of [\n pnpm?.overrides,\n pkg.overrides as Record<string, string> | undefined,\n ]) {\n if (block && typeof block === 'object')\n specs.push(...Object.entries(block));\n }\n\n for (const [name, spec] of specs) {\n if (INTEGRATION_PACKAGE.test(name)) {\n findings.push(\n finding(\n `package.json depends on the integration package ${name}.`,\n INTEGRATION_HINT,\n 'package.json',\n ),\n );\n continue;\n }\n const linked = /^(?:file|link|workspace):(.*)$/.exec(String(spec));\n if (linked?.[1] !== undefined && linked[1] !== '*' && linked[1] !== '^') {\n const target = path.resolve(project.dir, linked[1]);\n const kind = nearestEkanosKind(target);\n if (\n kind &&\n kind.kind === 'integration' &&\n path.resolve(kind.dir) !== project.dir\n ) {\n findings.push(\n finding(\n `package.json links ${name} to ${linked[1]}, an integration project.`,\n INTEGRATION_HINT,\n 'package.json',\n ),\n );\n }\n }\n // A resolved dependency that is itself an integration, whatever its name.\n const installed = path.join(\n project.dir,\n 'node_modules',\n name,\n 'ekanos.json',\n );\n if (fs.existsSync(installed)) {\n try {\n const kind = (\n JSON.parse(fs.readFileSync(installed, 'utf8')) as { kind?: string }\n ).kind;\n if ((kind ?? 'integration') === 'integration') {\n findings.push(\n finding(\n `package.json depends on ${name}, which is an integration (its ekanos.json is kind \"integration\").`,\n INTEGRATION_HINT,\n 'package.json',\n ),\n );\n }\n } catch {\n // unreadable ekanos.json in a dependency: the bundle scan still applies\n }\n }\n }\n\n return findings;\n}\n\n// ─── 2. source scan ─────────────────────────────────────────────────────────\n\nconst IMPORT_PATTERN =\n /(?:\\bfrom\\s*|\\bimport\\s*\\(\\s*|\\bimport\\s+|\\brequire\\s*\\(\\s*)(['\"`])([^'\"`\\n]+)\\1/g;\nconst COMPUTED_IMPORT = /\\bimport\\s*\\(\\s*(?!['\"`])/g;\n\nfunction* walkSources(\n dir: string,\n ignore: readonly string[],\n root: string,\n): Generator<string> {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n if (entry.isSymbolicLink()) continue;\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (SKIP_DIRS.has(entry.name)) continue;\n const rel = path.relative(root, full).split(path.sep).join('/');\n if (ignore.includes(rel)) continue;\n yield* walkSources(full, ignore, root);\n } else if (SOURCE_EXT.test(entry.name)) {\n yield full;\n }\n }\n}\n\nconst lineOf = (text: string, index: number) =>\n text.slice(0, index).split('\\n').length;\n\nfunction checkSources(project: ExperienceProject): Finding[] {\n const findings: Finding[] = [];\n const srcDir = path.join(project.dir, 'src');\n if (!fs.existsSync(srcDir)) return findings;\n const ignore = project.ekanos.ignore ?? [];\n\n for (const file of walkSources(srcDir, ignore, project.dir)) {\n const text = fs.readFileSync(file, 'utf8');\n const rel = path.relative(project.dir, file).split(path.sep).join('/');\n\n for (const match of text.matchAll(IMPORT_PATTERN)) {\n const spec = match[2] as string;\n const line = lineOf(text, match.index ?? 0);\n\n if (INTEGRATION_PACKAGE.test(spec) || INTEGRATION_IN_PATH.test(spec)) {\n findings.push(\n finding(\n `${rel}:${line} imports the integration \"${spec}\".`,\n INTEGRATION_HINT,\n rel,\n line,\n ),\n );\n } else if (HOST_INTERNAL.test(spec)) {\n findings.push(\n finding(\n `${rel}:${line} imports \"${spec}\", which is host-internal.`,\n 'Build with @ekanos/ui and @ekanos/sdk; @kit/* does not exist for a partner.',\n rel,\n line,\n ),\n );\n } else if (spec.startsWith('.')) {\n const target = path.resolve(path.dirname(file), spec);\n if (!isContained(project.dir, target)) {\n findings.push(\n finding(\n `${rel}:${line} imports \"${spec}\", a path outside the project.`,\n `${INTEGRATION_HINT} Code outside this project is not part of the experience.`,\n rel,\n line,\n ),\n );\n } else {\n const owner = nearestEkanosKind(target);\n if (owner && owner.kind === 'integration') {\n findings.push(\n finding(\n `${rel}:${line} imports \"${spec}\", inside an integration project.`,\n INTEGRATION_HINT,\n rel,\n line,\n ),\n );\n }\n }\n }\n }\n\n for (const match of text.matchAll(COMPUTED_IMPORT)) {\n const line = lineOf(text, match.index ?? 0);\n findings.push(\n finding(\n `${rel}:${line} uses a computed dynamic import(), which cannot be checked.`,\n 'Import a static specifier.',\n rel,\n line,\n ),\n );\n }\n }\n\n return findings;\n}\n\n// ─── 3. bundle scan ─────────────────────────────────────────────────────────\n\nfunction externalsFor(project: ExperienceProject): string[] {\n const names = [...ALLOWED_EXTERNALS, ...(project.ekanos.allowImports ?? [])];\n\n return names.flatMap((name) => [name, `${name}/*`]);\n}\n\n/** Bundle the entry and fail on any input that is integration code. */\nasync function checkBundle(project: ExperienceProject): Promise<Finding[]> {\n const entry = path.join(project.dir, project.entry);\n if (!fs.existsSync(entry)) {\n return [\n finding(\n `entry ${project.entry} does not exist.`,\n 'Fix \"entry\" in ekanos.json.',\n 'ekanos.json',\n ),\n ];\n }\n\n let result;\n try {\n result = await build({\n entryPoints: [entry],\n bundle: true,\n write: false,\n metafile: true,\n platform: 'browser',\n format: 'esm',\n jsx: 'automatic',\n logLevel: 'silent',\n absWorkingDir: project.dir,\n external: externalsFor(project),\n loader: { '.css': 'empty', '.svg': 'dataurl', '.png': 'dataurl' },\n });\n } catch (error) {\n const errors =\n (\n error as {\n errors?: Array<{\n text: string;\n location?: { file: string; line: number } | null;\n }>;\n }\n ).errors ?? [];\n if (errors.length === 0) {\n return [\n finding(\n `the entry could not be bundled: ${error instanceof Error ? error.message : String(error)}`,\n 'Fix the error and re-run.',\n ),\n ];\n }\n\n return errors.map((e) =>\n finding(\n `bundle: ${e.text}`,\n 'Install the dependency, fix the import, or add a reviewed specifier to ekanos.json \"allowImports\".',\n e.location?.file,\n e.location?.line,\n ),\n );\n }\n\n const findings: Finding[] = [];\n const reported = new Set<string>();\n for (const input of Object.keys(result.metafile.inputs)) {\n const absolute = path.resolve(project.dir, input);\n let problem: string | null = null;\n\n if (INTEGRATION_IN_PATH.test(absolute)) {\n problem = 'is integration package code';\n } else if (\n !isContained(project.dir, absolute) &&\n !absolute.includes(`${path.sep}node_modules${path.sep}`)\n ) {\n problem = 'is outside the project';\n } else if (absolute.includes(`${path.sep}node_modules${path.sep}`)) {\n const owner = packageRootOf(absolute);\n const kind = owner ? nearestEkanosKind(owner) : null;\n if (kind && kind.dir === owner && kind.kind === 'integration') {\n problem = 'is code of an integration package';\n }\n } else {\n const owner = nearestEkanosKind(absolute);\n if (owner && owner.kind === 'integration')\n problem = 'is inside an integration project';\n }\n\n if (problem && !reported.has(input)) {\n reported.add(input);\n findings.push(\n finding(\n `the bundle contains ${input}, which ${problem}.`,\n `${INTEGRATION_HINT} It reached the bundle through an import chain; the source scan cannot always see this.`,\n input,\n ),\n );\n }\n }\n\n return findings;\n}\n\nfunction packageRootOf(file: string): string | null {\n let current = path.dirname(file);\n for (;;) {\n if (fs.existsSync(path.join(current, 'package.json'))) return current;\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\n\n/** The authoritative boundary: package.json, source scan, bundle scan. */\nexport async function checkExperienceBoundary(\n project: ExperienceProject,\n): Promise<Finding[]> {\n return [\n ...checkPackageJson(project),\n ...checkSources(project),\n ...(await checkBundle(project)),\n ];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"boundary.js","sourceRoot":"","sources":["../../src/experience/boundary.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n EXPERIENCE_HOST_EXTERNALS,\n type Finding,\n} from '@ekanos/integration-schema';\nimport { build } from 'esbuild';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport { isContained } from '../safe-fs';\nimport type { ExperienceProject } from './project';\n\nexport const BOUNDARY_CHECK = 'checks/experience-boundary';\n\n/** Packages that may stay external at runtime (the host provides them). */\nexport const ALLOWED_EXTERNALS = EXPERIENCE_HOST_EXTERNALS;\n\nconst INTEGRATION_PACKAGE = /^@companydotcom\\/integration-[a-z0-9-]+/;\n/** A pnpm-store or plain node_modules path of an integration package. */\nconst INTEGRATION_IN_PATH = /@companydotcom[/+]integration-[a-z0-9-]+/;\nconst HOST_INTERNAL = /^@kit\\//;\n\nconst SOURCE_EXT = /\\.(?:[cm]?[jt]sx?)$/;\nconst SKIP_DIRS = new Set(['node_modules', 'dist', '.ekanos', '.git']);\n\nconst finding = (\n message: string,\n hint: string,\n file?: string,\n line?: number,\n): Finding => ({\n check: BOUNDARY_CHECK,\n severity: 'error',\n message,\n hint,\n ...(file ? { file } : {}),\n ...(line ? { line } : {}),\n});\n\nconst INTEGRATION_HINT =\n 'An experience reaches an integration only through its pinned contract: useOperation / operation() / step.tool. Add the integration with \"ekanos add <integration>@<version>\".';\n\n/** Nearest `ekanos.json` at or above `start`, with its kind, or null. */\nexport function nearestEkanosKind(\n start: string,\n): { dir: string; kind: string } | null {\n let current =\n fs.existsSync(start) && fs.statSync(start).isDirectory()\n ? start\n : path.dirname(start);\n for (;;) {\n const file = path.join(current, 'ekanos.json');\n if (fs.existsSync(file)) {\n try {\n const parsed = JSON.parse(fs.readFileSync(file, 'utf8')) as {\n kind?: string;\n };\n\n return { dir: current, kind: parsed.kind ?? 'integration' };\n } catch {\n return { dir: current, kind: 'integration' };\n }\n }\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\n\n// ─── 1. package.json ────────────────────────────────────────────────────────\n\nconst DEP_FIELDS = [\n 'dependencies',\n 'devDependencies',\n 'peerDependencies',\n 'optionalDependencies',\n] as const;\n\nfunction checkPackageJson(project: ExperienceProject): Finding[] {\n const file = path.join(project.dir, 'package.json');\n if (!fs.existsSync(file)) return [];\n const findings: Finding[] = [];\n const pkg = JSON.parse(fs.readFileSync(file, 'utf8')) as Record<\n string,\n unknown\n >;\n\n const specs: Array<[string, string]> = [];\n for (const field of DEP_FIELDS) {\n const block = pkg[field];\n if (block && typeof block === 'object') {\n specs.push(...Object.entries(block as Record<string, string>));\n }\n }\n const pnpm = pkg.pnpm as { overrides?: Record<string, string> } | undefined;\n for (const block of [\n pnpm?.overrides,\n pkg.overrides as Record<string, string> | undefined,\n ]) {\n if (block && typeof block === 'object')\n specs.push(...Object.entries(block));\n }\n\n for (const [name, spec] of specs) {\n if (INTEGRATION_PACKAGE.test(name)) {\n findings.push(\n finding(\n `package.json depends on the integration package ${name}.`,\n INTEGRATION_HINT,\n 'package.json',\n ),\n );\n continue;\n }\n const linked = /^(?:file|link|workspace):(.*)$/.exec(String(spec));\n if (linked?.[1] !== undefined && linked[1] !== '*' && linked[1] !== '^') {\n const target = path.resolve(project.dir, linked[1]);\n const kind = nearestEkanosKind(target);\n if (\n kind &&\n kind.kind === 'integration' &&\n path.resolve(kind.dir) !== project.dir\n ) {\n findings.push(\n finding(\n `package.json links ${name} to ${linked[1]}, an integration project.`,\n INTEGRATION_HINT,\n 'package.json',\n ),\n );\n }\n }\n // A resolved dependency that is itself an integration, whatever its name.\n const installed = path.join(\n project.dir,\n 'node_modules',\n name,\n 'ekanos.json',\n );\n if (fs.existsSync(installed)) {\n try {\n const kind = (\n JSON.parse(fs.readFileSync(installed, 'utf8')) as { kind?: string }\n ).kind;\n if ((kind ?? 'integration') === 'integration') {\n findings.push(\n finding(\n `package.json depends on ${name}, which is an integration (its ekanos.json is kind \"integration\").`,\n INTEGRATION_HINT,\n 'package.json',\n ),\n );\n }\n } catch {\n // unreadable ekanos.json in a dependency: the bundle scan still applies\n }\n }\n }\n\n return findings;\n}\n\n// ─── 2. source scan ─────────────────────────────────────────────────────────\n\nconst IMPORT_PATTERN =\n /(?:\\bfrom\\s*|\\bimport\\s*\\(\\s*|\\bimport\\s+|\\brequire\\s*\\(\\s*)(['\"`])([^'\"`\\n]+)\\1/g;\nconst COMPUTED_IMPORT = /\\bimport\\s*\\(\\s*(?!['\"`])/g;\n\nfunction* walkSources(\n dir: string,\n ignore: readonly string[],\n root: string,\n): Generator<string> {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n if (entry.isSymbolicLink()) continue;\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (SKIP_DIRS.has(entry.name)) continue;\n const rel = path.relative(root, full).split(path.sep).join('/');\n if (ignore.includes(rel)) continue;\n yield* walkSources(full, ignore, root);\n } else if (SOURCE_EXT.test(entry.name)) {\n yield full;\n }\n }\n}\n\nconst lineOf = (text: string, index: number) =>\n text.slice(0, index).split('\\n').length;\n\nfunction checkSources(project: ExperienceProject): Finding[] {\n const findings: Finding[] = [];\n const srcDir = path.join(project.dir, 'src');\n if (!fs.existsSync(srcDir)) return findings;\n const ignore = project.ekanos.ignore ?? [];\n\n for (const file of walkSources(srcDir, ignore, project.dir)) {\n const text = fs.readFileSync(file, 'utf8');\n const rel = path.relative(project.dir, file).split(path.sep).join('/');\n\n for (const match of text.matchAll(IMPORT_PATTERN)) {\n const spec = match[2] as string;\n const line = lineOf(text, match.index ?? 0);\n\n if (INTEGRATION_PACKAGE.test(spec) || INTEGRATION_IN_PATH.test(spec)) {\n findings.push(\n finding(\n `${rel}:${line} imports the integration \"${spec}\".`,\n INTEGRATION_HINT,\n rel,\n line,\n ),\n );\n } else if (HOST_INTERNAL.test(spec)) {\n findings.push(\n finding(\n `${rel}:${line} imports \"${spec}\", which is host-internal.`,\n 'Build with @ekanos/ui and @ekanos/sdk; @kit/* does not exist for a partner.',\n rel,\n line,\n ),\n );\n } else if (spec.startsWith('.')) {\n const target = path.resolve(path.dirname(file), spec);\n if (!isContained(project.dir, target)) {\n findings.push(\n finding(\n `${rel}:${line} imports \"${spec}\", a path outside the project.`,\n `${INTEGRATION_HINT} Code outside this project is not part of the experience.`,\n rel,\n line,\n ),\n );\n } else {\n const owner = nearestEkanosKind(target);\n if (owner && owner.kind === 'integration') {\n findings.push(\n finding(\n `${rel}:${line} imports \"${spec}\", inside an integration project.`,\n INTEGRATION_HINT,\n rel,\n line,\n ),\n );\n }\n }\n }\n }\n\n for (const match of text.matchAll(COMPUTED_IMPORT)) {\n const line = lineOf(text, match.index ?? 0);\n findings.push(\n finding(\n `${rel}:${line} uses a computed dynamic import(), which cannot be checked.`,\n 'Import a static specifier.',\n rel,\n line,\n ),\n );\n }\n }\n\n return findings;\n}\n\n// ─── 3. bundle scan ─────────────────────────────────────────────────────────\n\nfunction externalsFor(project: ExperienceProject): string[] {\n const names = [...ALLOWED_EXTERNALS, ...(project.ekanos.allowImports ?? [])];\n\n return names.flatMap((name) => [name, `${name}/*`]);\n}\n\n/** Bundle the entry and fail on any input that is integration code. */\nasync function checkBundle(project: ExperienceProject): Promise<Finding[]> {\n const entry = path.join(project.dir, project.entry);\n if (!fs.existsSync(entry)) {\n return [\n finding(\n `entry ${project.entry} does not exist.`,\n 'Fix \"entry\" in ekanos.json.',\n 'ekanos.json',\n ),\n ];\n }\n\n let result;\n try {\n result = await build({\n entryPoints: [entry],\n bundle: true,\n write: false,\n metafile: true,\n platform: 'browser',\n format: 'esm',\n jsx: 'automatic',\n logLevel: 'silent',\n absWorkingDir: project.dir,\n external: externalsFor(project),\n loader: { '.css': 'empty', '.svg': 'dataurl', '.png': 'dataurl' },\n });\n } catch (error) {\n const errors =\n (\n error as {\n errors?: Array<{\n text: string;\n location?: { file: string; line: number } | null;\n }>;\n }\n ).errors ?? [];\n if (errors.length === 0) {\n return [\n finding(\n `the entry could not be bundled: ${error instanceof Error ? error.message : String(error)}`,\n 'Fix the error and re-run.',\n ),\n ];\n }\n\n return errors.map((e) =>\n finding(\n `bundle: ${e.text}`,\n 'Install the dependency, fix the import, or add a reviewed specifier to ekanos.json \"allowImports\".',\n e.location?.file,\n e.location?.line,\n ),\n );\n }\n\n const findings: Finding[] = [];\n const reported = new Set<string>();\n for (const input of Object.keys(result.metafile.inputs)) {\n const absolute = path.resolve(project.dir, input);\n let problem: string | null = null;\n\n if (INTEGRATION_IN_PATH.test(absolute)) {\n problem = 'is integration package code';\n } else if (\n !isContained(project.dir, absolute) &&\n !absolute.includes(`${path.sep}node_modules${path.sep}`)\n ) {\n problem = 'is outside the project';\n } else if (absolute.includes(`${path.sep}node_modules${path.sep}`)) {\n const owner = packageRootOf(absolute);\n const kind = owner ? nearestEkanosKind(owner) : null;\n if (kind && kind.dir === owner && kind.kind === 'integration') {\n problem = 'is code of an integration package';\n }\n } else {\n const owner = nearestEkanosKind(absolute);\n if (owner && owner.kind === 'integration')\n problem = 'is inside an integration project';\n }\n\n if (problem && !reported.has(input)) {\n reported.add(input);\n findings.push(\n finding(\n `the bundle contains ${input}, which ${problem}.`,\n `${INTEGRATION_HINT} It reached the bundle through an import chain; the source scan cannot always see this.`,\n input,\n ),\n );\n }\n }\n\n return findings;\n}\n\nfunction packageRootOf(file: string): string | null {\n let current = path.dirname(file);\n for (;;) {\n if (fs.existsSync(path.join(current, 'package.json'))) return current;\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\n\n/** The authoritative boundary: package.json, source scan, bundle scan. */\nexport async function checkExperienceBoundary(\n project: ExperienceProject,\n): Promise<Finding[]> {\n return [\n ...checkPackageJson(project),\n ...checkSources(project),\n ...(await checkBundle(project)),\n ];\n}\n"]}
|
|
@@ -3,6 +3,7 @@ import type { ExperienceCheckResult } from './checks.js';
|
|
|
3
3
|
import { type ExperienceProject } from './project.js';
|
|
4
4
|
export declare const DIST_ENTRY = "dist/experience.js";
|
|
5
5
|
export declare const DIST_TYPES = "dist/experience.d.ts";
|
|
6
|
+
export declare const DIST_SURFACES = "dist/surfaces.json";
|
|
6
7
|
export declare const MANIFEST_FILE = "manifest.json";
|
|
7
8
|
export interface BuildOutput {
|
|
8
9
|
manifest: ExperienceManifest;
|
|
@@ -11,6 +12,7 @@ export interface BuildOutput {
|
|
|
11
12
|
}
|
|
12
13
|
/**
|
|
13
14
|
* Emit `dist/experience.js` (browser ESM, runtime packages left external),
|
|
14
|
-
* `dist/experience.d.ts
|
|
15
|
+
* `dist/experience.d.ts`, `dist/surfaces.json` (the surfaces and suggested
|
|
16
|
+
* layout as data, so admission reads them without running code) and `manifest.json`. Assumes the checks passed.
|
|
15
17
|
*/
|
|
16
18
|
export declare function emitExperience(project: ExperienceProject, result: ExperienceCheckResult): Promise<BuildOutput>;
|
package/dist/experience/build.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { ExperienceManifestSchema, } from '@ekanos/integration-schema';
|
|
1
|
+
import { EXPERIENCE_BUNDLE_OPTIONS, EXPERIENCE_DTS, ExperienceManifestSchema, experienceExternals, } from '@ekanos/integration-schema';
|
|
2
2
|
import { build as esbuild } from 'esbuild';
|
|
3
3
|
import * as fs from 'node:fs';
|
|
4
4
|
import * as path from 'node:path';
|
|
5
5
|
import { preconditionError } from '../errors.js';
|
|
6
|
-
import {
|
|
7
|
-
import { buildManifest } from './definition-checks.js';
|
|
6
|
+
import { buildManifest, buildSurfaces } from './definition-checks.js';
|
|
8
7
|
import { formatJson, writeIfChanged } from './project.js';
|
|
9
8
|
export const DIST_ENTRY = 'dist/experience.js';
|
|
10
9
|
export const DIST_TYPES = 'dist/experience.d.ts';
|
|
10
|
+
export const DIST_SURFACES = 'dist/surfaces.json';
|
|
11
11
|
export const MANIFEST_FILE = 'manifest.json';
|
|
12
12
|
function readPackageJson(project) {
|
|
13
13
|
try {
|
|
@@ -31,11 +31,12 @@ function sdkVersion(project, declared) {
|
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
33
|
* Emit `dist/experience.js` (browser ESM, runtime packages left external),
|
|
34
|
-
* `dist/experience.d.ts
|
|
34
|
+
* `dist/experience.d.ts`, `dist/surfaces.json` (the surfaces and suggested
|
|
35
|
+
* layout as data, so admission reads them without running code) and `manifest.json`. Assumes the checks passed.
|
|
35
36
|
*/
|
|
36
37
|
export async function emitExperience(project, result) {
|
|
37
38
|
var _a;
|
|
38
|
-
var _b, _c
|
|
39
|
+
var _b, _c;
|
|
39
40
|
const loaded = result.loaded;
|
|
40
41
|
if (!loaded) {
|
|
41
42
|
throw preconditionError('The experience definition was not loaded.', 'Run "ekanos check" to see why.');
|
|
@@ -45,7 +46,9 @@ export async function emitExperience(project, result) {
|
|
|
45
46
|
if (!/^\d+\.\d+\.\d+/.test(version)) {
|
|
46
47
|
throw preconditionError(`package.json "version" is "${version}", not semver.`, 'Set a version such as 0.1.0.');
|
|
47
48
|
}
|
|
49
|
+
const surfaces = buildSurfaces(project, loaded.definition);
|
|
48
50
|
const manifest = buildManifest({
|
|
51
|
+
surfaces,
|
|
49
52
|
project,
|
|
50
53
|
definition: loaded.definition,
|
|
51
54
|
pinned: result.pinned,
|
|
@@ -57,33 +60,19 @@ export async function emitExperience(project, result) {
|
|
|
57
60
|
if (!parsed.success) {
|
|
58
61
|
throw preconditionError(`The generated manifest is invalid: ${parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ')}`, 'This is a bug in @ekanos/cli or an unsupported definition; report it.');
|
|
59
62
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
format: 'esm',
|
|
65
|
-
platform: 'browser',
|
|
66
|
-
jsx: 'automatic',
|
|
67
|
-
logLevel: 'silent',
|
|
68
|
-
absWorkingDir: project.dir,
|
|
69
|
-
external: [
|
|
70
|
-
...ALLOWED_EXTERNALS,
|
|
71
|
-
...((_c = project.ekanos.allowImports) !== null && _c !== void 0 ? _c : []),
|
|
72
|
-
].flatMap((n) => [n, `${n}/*`]),
|
|
73
|
-
loader: { '.css': 'empty', '.svg': 'dataurl', '.png': 'dataurl' },
|
|
74
|
-
});
|
|
75
|
-
const js = (_d = (_a = bundle.outputFiles[0]) === null || _a === void 0 ? void 0 : _a.text) !== null && _d !== void 0 ? _d : '';
|
|
76
|
-
const dts = "import type { ExperienceDefinition } from '@ekanos/sdk/experience';\n" +
|
|
77
|
-
'declare const experience: ExperienceDefinition;\n' +
|
|
78
|
-
'export default experience;\n';
|
|
63
|
+
// The options are shared with the host's rebuild stage, which must produce
|
|
64
|
+
// these exact bytes from the shipped source.
|
|
65
|
+
const bundle = await esbuild(Object.assign(Object.assign({}, EXPERIENCE_BUNDLE_OPTIONS), { entryPoints: [path.join(project.dir, project.entry)], absWorkingDir: project.dir, external: experienceExternals(project.ekanos.allowImports) }));
|
|
66
|
+
const js = (_c = (_a = bundle.outputFiles[0]) === null || _a === void 0 ? void 0 : _a.text) !== null && _c !== void 0 ? _c : '';
|
|
79
67
|
const changed = [
|
|
80
68
|
writeIfChanged(path.join(project.dir, DIST_ENTRY), js),
|
|
81
|
-
writeIfChanged(path.join(project.dir, DIST_TYPES),
|
|
69
|
+
writeIfChanged(path.join(project.dir, DIST_TYPES), EXPERIENCE_DTS),
|
|
70
|
+
writeIfChanged(path.join(project.dir, DIST_SURFACES), formatJson(surfaces)),
|
|
82
71
|
writeIfChanged(path.join(project.dir, MANIFEST_FILE), formatJson(manifest)),
|
|
83
72
|
].some(Boolean);
|
|
84
73
|
return {
|
|
85
74
|
manifest,
|
|
86
|
-
files: [DIST_ENTRY, DIST_TYPES, MANIFEST_FILE],
|
|
75
|
+
files: [DIST_ENTRY, DIST_TYPES, DIST_SURFACES, MANIFEST_FILE],
|
|
87
76
|
changed,
|
|
88
77
|
};
|
|
89
78
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/experience/build.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/experience/build.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n EXPERIENCE_BUNDLE_OPTIONS,\n EXPERIENCE_DTS,\n type ExperienceManifest,\n ExperienceManifestSchema,\n experienceExternals,\n} from '@ekanos/integration-schema';\nimport { build as esbuild } from 'esbuild';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport { preconditionError } from '../errors';\nimport type { ExperienceCheckResult } from './checks';\nimport { buildManifest, buildSurfaces } from './definition-checks';\nimport { type ExperienceProject, formatJson, writeIfChanged } from './project';\n\nexport const DIST_ENTRY = 'dist/experience.js';\nexport const DIST_TYPES = 'dist/experience.d.ts';\nexport const DIST_SURFACES = 'dist/surfaces.json';\nexport const MANIFEST_FILE = 'manifest.json';\n\nfunction readPackageJson(project: ExperienceProject): {\n version?: string;\n dependencies?: Record<string, string>;\n} {\n try {\n return JSON.parse(\n fs.readFileSync(path.join(project.dir, 'package.json'), 'utf8'),\n ) as { version?: string; dependencies?: Record<string, string> };\n } catch {\n throw preconditionError(\n 'package.json is missing or unreadable.',\n 'An experience is an npm package; run \"ekanos init --kind experience\" or add a package.json.',\n );\n }\n}\n\nfunction sdkVersion(\n project: ExperienceProject,\n declared: Record<string, string> | undefined,\n): string {\n try {\n const installed = JSON.parse(\n fs.readFileSync(\n path.join(\n project.dir,\n 'node_modules',\n '@ekanos',\n 'sdk',\n 'package.json',\n ),\n 'utf8',\n ),\n ) as { version?: string };\n if (installed.version) return installed.version;\n } catch {\n // not installed: fall back to the declared range\n }\n\n return (declared?.['@ekanos/sdk'] ?? 'unknown').replace(/^[\\^~]/, '');\n}\n\nexport interface BuildOutput {\n manifest: ExperienceManifest;\n files: string[];\n changed: boolean;\n}\n\n/**\n * Emit `dist/experience.js` (browser ESM, runtime packages left external),\n * `dist/experience.d.ts`, `dist/surfaces.json` (the surfaces and suggested\n * layout as data, so admission reads them without running code) and `manifest.json`. Assumes the checks passed.\n */\nexport async function emitExperience(\n project: ExperienceProject,\n result: ExperienceCheckResult,\n): Promise<BuildOutput> {\n const loaded = result.loaded;\n if (!loaded) {\n throw preconditionError(\n 'The experience definition was not loaded.',\n 'Run \"ekanos check\" to see why.',\n );\n }\n const pkg = readPackageJson(project);\n const version = pkg.version ?? '';\n if (!/^\\d+\\.\\d+\\.\\d+/.test(version)) {\n throw preconditionError(\n `package.json \"version\" is \"${version}\", not semver.`,\n 'Set a version such as 0.1.0.',\n );\n }\n\n const surfaces = buildSurfaces(project, loaded.definition);\n const manifest = buildManifest({\n surfaces,\n project,\n definition: loaded.definition,\n pinned: result.pinned,\n workflows: result.workflows,\n version,\n sdk: sdkVersion(project, pkg.dependencies),\n });\n const parsed = ExperienceManifestSchema.safeParse(manifest);\n if (!parsed.success) {\n throw preconditionError(\n `The generated manifest is invalid: ${parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ')}`,\n 'This is a bug in @ekanos/cli or an unsupported definition; report it.',\n );\n }\n\n // The options are shared with the host's rebuild stage, which must produce\n // these exact bytes from the shipped source.\n const bundle = await esbuild({\n ...EXPERIENCE_BUNDLE_OPTIONS,\n entryPoints: [path.join(project.dir, project.entry)],\n absWorkingDir: project.dir,\n external: experienceExternals(project.ekanos.allowImports),\n });\n const js = bundle.outputFiles[0]?.text ?? '';\n\n const changed = [\n writeIfChanged(path.join(project.dir, DIST_ENTRY), js),\n writeIfChanged(path.join(project.dir, DIST_TYPES), EXPERIENCE_DTS),\n writeIfChanged(path.join(project.dir, DIST_SURFACES), formatJson(surfaces)),\n writeIfChanged(path.join(project.dir, MANIFEST_FILE), formatJson(manifest)),\n ].some(Boolean);\n\n return {\n manifest,\n files: [DIST_ENTRY, DIST_TYPES, DIST_SURFACES, MANIFEST_FILE],\n changed,\n };\n}\n"]}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type ExperienceSurfaces } from '@ekanos/integration-schema';
|
|
2
|
+
import type { ExperienceProject } from './project.js';
|
|
3
|
+
/** Set to `off` to skip the clean-room build (offline work, tests); the host's gate still rebuilds. */
|
|
4
|
+
export declare const CLEAN_ROOM_ENV = "EKANOS_PUBLISH_CLEAN_ROOM";
|
|
5
|
+
/** The npm binary the clean room runs. Defaults to `npm`; overridden by tests. */
|
|
6
|
+
export declare const NPM_BIN_ENV = "EKANOS_NPM_BIN";
|
|
7
|
+
export type LockfileSource = 'package-lock' | 'npm-shrinkwrap' | 'generated-from-pnpm';
|
|
8
|
+
export interface CleanRoomBuild {
|
|
9
|
+
/** `dist/experience.js` exactly as the host's gate will rebuild it. */
|
|
10
|
+
bundle: string;
|
|
11
|
+
/** The standalone lockfile the bundle was built against; ships as npm-shrinkwrap.json. */
|
|
12
|
+
lockfile: string;
|
|
13
|
+
lockfileSource: LockfileSource;
|
|
14
|
+
/** `dist/surfaces.json` as the rebuilt bundle's own definition declares it. */
|
|
15
|
+
surfaces: ExperienceSurfaces;
|
|
16
|
+
}
|
|
17
|
+
/** A `pnpm-lock.yaml` at or above the project: it lives in a pnpm workspace. */
|
|
18
|
+
export declare function findPnpmLockfile(dir: string): string | null;
|
|
19
|
+
/** Whether the project has a lockfile of either kind to build from. */
|
|
20
|
+
export declare function hasBuildableLockfile(dir: string): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Builds the experience bundle the way the host's gate will, so the bytes match
|
|
23
|
+
* by construction: in a temp directory holding only what ships (package.json,
|
|
24
|
+
* tsconfig, `src/`), with dependencies installed by `npm ci --ignore-scripts`
|
|
25
|
+
* from a standalone lockfile, and the shared bundle options.
|
|
26
|
+
*
|
|
27
|
+
* The lockfile is the project's own `package-lock.json`/`npm-shrinkwrap.json`
|
|
28
|
+
* when it has one. A project inside a pnpm workspace (a `pnpm-lock.yaml` at the
|
|
29
|
+
* repo root, no per-package npm lockfile) gets one generated for just its
|
|
30
|
+
* `package.json` (`npm install`), and that generated file
|
|
31
|
+
* is what ships, so the host resolves the dependencies the bundle was built
|
|
32
|
+
* with. It resolves the declared ranges from the registry, which can differ from
|
|
33
|
+
* the versions the workspace's pnpm lockfile pins; the bundle you ship is the
|
|
34
|
+
* one built from the shipped lockfile, not from your workspace's tree.
|
|
35
|
+
*
|
|
36
|
+
* The surfaces are recomputed from the rebuilt bundle's own definition (the host
|
|
37
|
+
* does the same), so a project whose local tree declares something else is
|
|
38
|
+
* caught here instead of at the gate.
|
|
39
|
+
*/
|
|
40
|
+
export declare function buildInCleanRoom(project: ExperienceProject, env?: Record<string, string | undefined>): Promise<CleanRoomBuild>;
|