@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,5 +1,5 @@
|
|
|
1
1
|
import { invalidStateError, usageError } from '../errors.js';
|
|
2
|
-
import { createTeam, disconnectTeamIntegration, inviteTeamMember, listTeamMembers, listTeamRoles, removeTeamMember, renameTeam, setTeamMemberRole, } from '../teams-api.js';
|
|
2
|
+
import { addTeamMember, createTeam, disconnectTeamIntegration, inviteTeamMember, listTeamMembers, listTeamRoles, removeTeamMember, renameTeam, setTeamMemberRole, } from '../teams-api.js';
|
|
3
3
|
import { runTeamConnect } from './teams-connect.js';
|
|
4
4
|
/**
|
|
5
5
|
* Onboarding a team from the terminal, for the Source admin: `teams create`,
|
|
@@ -16,7 +16,7 @@ export const ONBOARDING_SUBCOMMANDS = [
|
|
|
16
16
|
'connect',
|
|
17
17
|
'disconnect',
|
|
18
18
|
];
|
|
19
|
-
const MEMBERS_VERBS = ['list', 'invite', 'role', 'remove'];
|
|
19
|
+
const MEMBERS_VERBS = ['list', 'add', 'invite', 'role', 'remove'];
|
|
20
20
|
export function isOnboardingSubcommand(value) {
|
|
21
21
|
return ONBOARDING_SUBCOMMANDS.includes(value);
|
|
22
22
|
}
|
|
@@ -54,10 +54,13 @@ export function parseOnboarding(subcommand, rest, flags) {
|
|
|
54
54
|
noExtra(extra);
|
|
55
55
|
const teamSlug = slugOf(team, 'team');
|
|
56
56
|
const productSlug = slugOf(product, 'product');
|
|
57
|
+
const mine = flags.mine === true;
|
|
57
58
|
if (!flags.yes) {
|
|
58
|
-
throw invalidStateError(
|
|
59
|
+
throw invalidStateError(mine
|
|
60
|
+
? `Disconnecting your own ${productSlug} connection removes its tokens: anything of ${teamSlug} that acts with your connection — your personal agents, an agent that runs as you — stops until you connect it again.`
|
|
61
|
+
: `Disconnecting ${productSlug} from ${teamSlug} removes the team's connection and its tokens: every widget, workflow and agent of the team that uses it stops until someone connects it again. The team's own app (its saved fields) stays.`, `Re-run with --yes: ekanos teams disconnect ${teamSlug} ${productSlug}${mine ? ' --mine' : ''} --yes`);
|
|
59
62
|
}
|
|
60
|
-
return { kind: 'disconnect', team: teamSlug, product: productSlug };
|
|
63
|
+
return { kind: 'disconnect', team: teamSlug, product: productSlug, mine };
|
|
61
64
|
}
|
|
62
65
|
if (subcommand === 'roles') {
|
|
63
66
|
const [verb, team, ...extra] = rest;
|
|
@@ -74,7 +77,7 @@ export function parseOnboarding(subcommand, rest, flags) {
|
|
|
74
77
|
if (!match) {
|
|
75
78
|
throw usageError(verb
|
|
76
79
|
? `Unknown teams members subcommand "${verb}".`
|
|
77
|
-
: 'teams members needs a subcommand.', 'Run one of: ekanos teams members list <team>, ekanos teams members invite <team> <email> --role <role>, ekanos teams members role <team> <email> <role>, ekanos teams members remove <team> <email> --yes
|
|
80
|
+
: 'teams members needs a subcommand.', 'Run one of: ekanos teams members list <team>, ekanos teams members add <team> --self | <email> [--role <role>], ekanos teams members invite <team> <email> --role <role>, ekanos teams members role <team> <email> <role>, ekanos teams members remove <team> <email> --yes, ekanos teams members resend <team> <email>.');
|
|
78
81
|
}
|
|
79
82
|
noExtra(extra);
|
|
80
83
|
if (match === 'list') {
|
|
@@ -83,6 +86,17 @@ export function parseOnboarding(subcommand, rest, flags) {
|
|
|
83
86
|
return { kind: 'members-list', team: slugOf(team, 'team') };
|
|
84
87
|
}
|
|
85
88
|
const teamSlug = slugOf(team, 'team');
|
|
89
|
+
if (match === 'add') {
|
|
90
|
+
if (role !== undefined)
|
|
91
|
+
noExtra([role]);
|
|
92
|
+
if (flags.self === true && email !== undefined) {
|
|
93
|
+
throw usageError('Name one person: --self, or an email.', `Run "ekanos teams members add ${teamSlug} --self" to join it yourself, or "ekanos teams members add ${teamSlug} <email>" for someone who already has an Ekanos account on this Source.`);
|
|
94
|
+
}
|
|
95
|
+
if (flags.self !== true && email === undefined) {
|
|
96
|
+
throw usageError('Name who joins: --self, or an email.', `Run "ekanos teams members add ${teamSlug} --self" to join it yourself.`);
|
|
97
|
+
}
|
|
98
|
+
return Object.assign({ kind: 'members-add', team: teamSlug, target: flags.self === true ? { self: true } : { email: emailOf(email) } }, (flags.role === undefined ? {} : { role: roleOf(flags.role) }));
|
|
99
|
+
}
|
|
86
100
|
const address = emailOf(email);
|
|
87
101
|
if (match === 'invite') {
|
|
88
102
|
if (role !== undefined)
|
|
@@ -114,7 +128,7 @@ export function parseOnboarding(subcommand, rest, flags) {
|
|
|
114
128
|
return { kind: 'members-remove', team: teamSlug, email: address };
|
|
115
129
|
}
|
|
116
130
|
export async function runOnboarding(ctx, args, client, host, source, plan) {
|
|
117
|
-
var _a, _b;
|
|
131
|
+
var _a, _b, _c, _d;
|
|
118
132
|
switch (plan.kind) {
|
|
119
133
|
case 'create': {
|
|
120
134
|
const created = await client.call((token) => createTeam(host, token, source, {
|
|
@@ -178,7 +192,37 @@ export async function runOnboarding(ctx, args, client, host, source, plan) {
|
|
|
178
192
|
tone: rows.length === 0 ? 'warn' : 'ok',
|
|
179
193
|
rows,
|
|
180
194
|
notes: [
|
|
181
|
-
`"ekanos teams members invite ${list.team.slug} <email> --role <role>"
|
|
195
|
+
`"ekanos teams members add ${list.team.slug} --self" joins it yourself, now; "ekanos teams members add ${list.team.slug} <email>" adds someone already on the Source; "ekanos teams members invite ${list.team.slug} <email> --role <role>" emails anyone else an invitation.`,
|
|
196
|
+
],
|
|
197
|
+
}));
|
|
198
|
+
}
|
|
199
|
+
case 'members-add': {
|
|
200
|
+
const added = await client.call((token) => addTeamMember(host, token, { source, team: plan.team }, Object.assign(Object.assign({}, plan.target), (plan.role ? { role: plan.role } : {}))));
|
|
201
|
+
const who = added.self
|
|
202
|
+
? `you${added.member.email ? ` (${added.member.email})` : ''}`
|
|
203
|
+
: ((_a = added.member.email) !== null && _a !== void 0 ? _a : added.member.userId);
|
|
204
|
+
const already = added.outcome === 'already';
|
|
205
|
+
return ctx.succeed(Object.assign({ host }, added), ctx.ui.result({
|
|
206
|
+
title: already
|
|
207
|
+
? `${added.self ? 'You are' : `${who} is`} already a member of ${added.team.slug}`
|
|
208
|
+
: `Added ${who} to ${added.team.slug}`,
|
|
209
|
+
rows: [
|
|
210
|
+
['Role', added.member.role],
|
|
211
|
+
['Status', added.member.status],
|
|
212
|
+
],
|
|
213
|
+
notes: [
|
|
214
|
+
...(already && plan.role && plan.role !== added.member.role
|
|
215
|
+
? [
|
|
216
|
+
`The role was left as ${added.member.role}. Change it: ekanos teams members role ${added.team.slug} ${(_b = added.member.email) !== null && _b !== void 0 ? _b : '<email>'} ${plan.role}`,
|
|
217
|
+
]
|
|
218
|
+
: []),
|
|
219
|
+
...(added.withdrawnInvitation
|
|
220
|
+
? [
|
|
221
|
+
`Their pending invitation${added.withdrawnInvitationRole ? ` (as ${added.withdrawnInvitationRole})` : ''} was withdrawn: the membership replaces it.`,
|
|
222
|
+
]
|
|
223
|
+
: []),
|
|
224
|
+
...(already ? [] : ['No email was sent: it takes effect now.']),
|
|
225
|
+
`Connect a product for ${added.self ? 'yourself' : 'the team'}: ekanos teams connect ${added.team.slug} <product>`,
|
|
182
226
|
],
|
|
183
227
|
}));
|
|
184
228
|
}
|
|
@@ -202,7 +246,7 @@ export async function runOnboarding(ctx, args, client, host, source, plan) {
|
|
|
202
246
|
? `${changed.email} is already ${changed.after} on ${changed.team.slug}`
|
|
203
247
|
: `${changed.email} is now ${changed.after} on ${changed.team.slug}`,
|
|
204
248
|
rows: [
|
|
205
|
-
['Was', (
|
|
249
|
+
['Was', (_c = changed.before) !== null && _c !== void 0 ? _c : '—'],
|
|
206
250
|
[
|
|
207
251
|
'Applies to',
|
|
208
252
|
changed.kind === 'member'
|
|
@@ -222,7 +266,7 @@ export async function runOnboarding(ctx, args, client, host, source, plan) {
|
|
|
222
266
|
title: removed.kind === 'member'
|
|
223
267
|
? `Removed ${removed.email} from ${removed.team.slug}`
|
|
224
268
|
: `Withdrew ${removed.email}'s invitation to ${removed.team.slug}`,
|
|
225
|
-
rows: [['Role was', (
|
|
269
|
+
rows: [['Role was', (_d = removed.before) !== null && _d !== void 0 ? _d : '—']],
|
|
226
270
|
}));
|
|
227
271
|
}
|
|
228
272
|
case 'roles-list': {
|
|
@@ -243,11 +287,16 @@ export async function runOnboarding(ctx, args, client, host, source, plan) {
|
|
|
243
287
|
source,
|
|
244
288
|
team: plan.team,
|
|
245
289
|
product: plan.product,
|
|
290
|
+
mine: plan.mine,
|
|
246
291
|
}));
|
|
247
|
-
return ctx.succeed(Object.assign({ host }, done), ctx.ui.result({
|
|
248
|
-
title:
|
|
249
|
-
?
|
|
250
|
-
|
|
292
|
+
return ctx.succeed(Object.assign(Object.assign({ host }, done), (plan.mine ? { mine: true } : {})), ctx.ui.result({
|
|
293
|
+
title: plan.mine
|
|
294
|
+
? done.wasConnected
|
|
295
|
+
? `Disconnected your own ${done.product.name} connection`
|
|
296
|
+
: `You had no ${done.product.name} connection; cleared what was left`
|
|
297
|
+
: done.wasConnected
|
|
298
|
+
? `Disconnected ${done.product.name} from ${done.team.slug}`
|
|
299
|
+
: `${done.team.slug} had no ${done.product.name} connection; cleared what was left`,
|
|
251
300
|
tone: 'warn',
|
|
252
301
|
notes: [
|
|
253
302
|
`Connect it again with "ekanos teams connect ${done.team.slug} ${done.product.slug}".`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"teams-onboard.js","sourceRoot":"","sources":["../../src/commands/teams-onboard.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CliContext } from '../context';\nimport { invalidStateError, usageError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport {\n createTeam,\n disconnectTeamIntegration,\n inviteTeamMember,\n listTeamMembers,\n listTeamRoles,\n removeTeamMember,\n renameTeam,\n setTeamMemberRole,\n} from '../teams-api';\nimport type { TeamsArgs, TeamsClient } from './teams';\nimport { runTeamConnect } from './teams-connect';\n\n/**\n * Onboarding a team from the terminal, for the Source admin: `teams create`,\n * `teams members list|invite|role|remove`, `teams roles list`,\n * `teams connect` and `teams disconnect`. Parsed before any session is touched (`parseOnboarding`)\n * so a usage error never costs a network round-trip, then run against the\n * session `runTeams` resolved.\n */\n\nexport const ONBOARDING_SUBCOMMANDS = [\n 'create',\n 'rename',\n 'members',\n 'roles',\n 'connect',\n 'disconnect',\n] as const;\nexport type OnboardingSubcommand = (typeof ONBOARDING_SUBCOMMANDS)[number];\n\nexport interface OnboardingFlags {\n slug?: string;\n owner?: string;\n role?: string;\n /** `connect --as <member-email>`: the member who signs in. */\n as?: string;\n yes: boolean;\n}\n\nexport type OnboardingPlan =\n | { kind: 'create'; name: string; slug?: string; ownerEmail?: string }\n | { kind: 'rename'; team: string; name: string }\n | { kind: 'members-list'; team: string }\n | { kind: 'members-invite'; team: string; email: string; role: string }\n | { kind: 'members-role'; team: string; email: string; role: string }\n | { kind: 'members-remove'; team: string; email: string }\n | { kind: 'roles-list'; team: string }\n | { kind: 'connect'; team: string; product: string; as?: string }\n | { kind: 'disconnect'; team: string; product: string };\n\nconst MEMBERS_VERBS = ['list', 'invite', 'role', 'remove'] as const;\n\nexport function isOnboardingSubcommand(\n value: string,\n): value is OnboardingSubcommand {\n return (ONBOARDING_SUBCOMMANDS as readonly string[]).includes(value);\n}\n\nexport function parseOnboarding(\n subcommand: OnboardingSubcommand,\n rest: readonly string[],\n flags: OnboardingFlags,\n): OnboardingPlan {\n if (subcommand === 'create') {\n const [name, ...extra] = rest;\n if (!name?.trim()) {\n throw usageError(\n 'Name the team.',\n 'Run \"ekanos teams create \\\\\"Bank A\\\\\" [--slug bank-a] [--owner <email>]\".',\n );\n }\n noExtra(extra);\n return {\n kind: 'create',\n name: name.trim(),\n slug: flags.slug === undefined ? undefined : slugOf(flags.slug, 'team'),\n ownerEmail: flags.owner === undefined ? undefined : emailOf(flags.owner),\n };\n }\n\n if (subcommand === 'rename') {\n const [team, name, ...extra] = rest;\n const teamSlug = slugOf(team, 'team');\n if (!name?.trim()) {\n throw usageError(\n 'Name the team’s new name.',\n `Run \"ekanos teams rename ${teamSlug} \\\\\"Bank A Support\\\\\"\".`,\n );\n }\n noExtra(extra);\n return { kind: 'rename', team: teamSlug, name: name.trim() };\n }\n\n if (subcommand === 'connect') {\n const [team, product, ...extra] = rest;\n noExtra(extra);\n return {\n kind: 'connect',\n team: slugOf(team, 'team'),\n product: slugOf(product, 'product'),\n ...(flags.as === undefined ? {} : { as: emailOf(flags.as) }),\n };\n }\n\n if (subcommand === 'disconnect') {\n const [team, product, ...extra] = rest;\n noExtra(extra);\n const teamSlug = slugOf(team, 'team');\n const productSlug = slugOf(product, 'product');\n if (!flags.yes) {\n throw invalidStateError(\n `Disconnecting ${productSlug} from ${teamSlug} removes the team's connection and its tokens: every widget, workflow and agent of the team that uses it stops until someone connects it again. The team's own app (its saved fields) stays.`,\n `Re-run with --yes: ekanos teams disconnect ${teamSlug} ${productSlug} --yes`,\n );\n }\n return { kind: 'disconnect', team: teamSlug, product: productSlug };\n }\n\n if (subcommand === 'roles') {\n const [verb, team, ...extra] = rest;\n if (verb !== 'list') {\n throw usageError(\n verb\n ? `Unknown teams roles subcommand \"${verb}\".`\n : 'teams roles needs a subcommand.',\n 'Run \"ekanos teams roles list <team>\".',\n );\n }\n noExtra(extra);\n return { kind: 'roles-list', team: slugOf(team, 'team') };\n }\n\n const [verb, team, email, role, ...extra] = rest;\n const match = MEMBERS_VERBS.find((name) => name === verb);\n if (!match) {\n throw usageError(\n verb\n ? `Unknown teams members subcommand \"${verb}\".`\n : 'teams members needs a subcommand.',\n 'Run one of: ekanos teams members list <team>, ekanos teams members invite <team> <email> --role <role>, ekanos teams members role <team> <email> <role>, ekanos teams members remove <team> <email> --yes.',\n );\n }\n noExtra(extra);\n\n if (match === 'list') {\n if (email !== undefined) noExtra([email]);\n return { kind: 'members-list', team: slugOf(team, 'team') };\n }\n\n const teamSlug = slugOf(team, 'team');\n const address = emailOf(email);\n\n if (match === 'invite') {\n if (role !== undefined) noExtra([role]);\n return {\n kind: 'members-invite',\n team: teamSlug,\n email: address,\n role: roleOf(flags.role ?? 'member'),\n };\n }\n\n if (match === 'role') {\n const named = role ?? flags.role;\n if (!named) {\n throw usageError(\n 'Name the new role.',\n `Run \"ekanos teams members role ${teamSlug} ${address} <role>\"; \"ekanos teams roles list ${teamSlug}\" lists them.`,\n );\n }\n return {\n kind: 'members-role',\n team: teamSlug,\n email: address,\n role: roleOf(named),\n };\n }\n\n if (role !== undefined) noExtra([role]);\n if (!flags.yes) {\n throw invalidStateError(\n `Removing ${address} from ${teamSlug} ends their access to the team (a pending invitation is withdrawn instead).`,\n `Re-run with --yes: ekanos teams members remove ${teamSlug} ${address} --yes`,\n );\n }\n return { kind: 'members-remove', team: teamSlug, email: address };\n}\n\nexport async function runOnboarding(\n ctx: CliContext,\n args: TeamsArgs,\n client: TeamsClient,\n host: string,\n source: string,\n plan: OnboardingPlan,\n): Promise<ExitCode> {\n switch (plan.kind) {\n case 'create': {\n const created = await client.call((token) =>\n createTeam(host, token, source, {\n name: plan.name,\n slug: plan.slug,\n ownerEmail: plan.ownerEmail,\n }),\n );\n return ctx.succeed(\n { host, ...created },\n ctx.ui.result({\n title: `Created team ${created.team.slug}`,\n rows: [\n ['Name', created.team.name],\n ['Source', created.source.slug],\n [\n 'Owner',\n created.owner.kind === 'caller'\n ? `you${created.owner.email ? ` (${created.owner.email})` : ''}`\n : `${created.owner.email} — invited; ownership moves to them on accept`,\n ],\n ['Team home', created.teamUrl],\n ],\n notes: [\n `Next: \"ekanos teams members invite ${created.team.slug} <email> --role <role>\" (\"ekanos teams roles list ${created.team.slug}\" lists the roles).`,\n `Then \"ekanos teams connect ${created.team.slug} <product>\" connects an integration for the team.`,\n ],\n }),\n );\n }\n\n case 'rename': {\n const renamed = await client.call((token) =>\n renameTeam(host, token, { source, team: plan.team }, plan.name),\n );\n const moved = renamed.team.slug !== renamed.previous.slug;\n return ctx.succeed(\n { host, ...renamed },\n ctx.ui.result({\n title:\n renamed.team.name === renamed.previous.name\n ? `${renamed.team.slug} is already named ${renamed.team.name}`\n : `Renamed ${renamed.previous.slug} to ${renamed.team.name}`,\n rows: [\n ['Name', renamed.team.name],\n ['Slug', renamed.team.slug],\n ['Team home', renamed.teamUrl],\n ],\n notes: moved\n ? [\n `The slug followed the name: use \"${renamed.team.slug}\" from now on. Links and scripts naming \"${renamed.previous.slug}\" no longer reach the team.`,\n ]\n : [],\n tone: moved ? 'warn' : 'ok',\n }),\n );\n }\n\n case 'members-list': {\n const list = await client.call((token) =>\n listTeamMembers(host, token, { source, team: plan.team }),\n );\n const rows: [string, string][] = list.members.map((member) => [\n member.email ?? member.userId,\n `${member.role}${member.primaryOwner ? ' · primary owner' : ''}${member.status === 'active' ? '' : ` · ${member.status}`}${member.name ? ` · ${member.name}` : ''}`,\n ]);\n for (const invitation of list.invitations) {\n rows.push([\n invitation.email,\n `${invitation.role} · invited, expires ${invitation.expiresAt.slice(0, 10)}`,\n ]);\n }\n return ctx.succeed(\n { host, ...list },\n ctx.ui.result({\n title: `Members of ${list.team.slug} (${list.team.name})`,\n tone: rows.length === 0 ? 'warn' : 'ok',\n rows,\n notes: [\n `\"ekanos teams members invite ${list.team.slug} <email> --role <role>\" adds one.`,\n ],\n }),\n );\n }\n\n case 'members-invite': {\n const invited = await client.call((token) =>\n inviteTeamMember(\n host,\n token,\n { source, team: plan.team },\n { email: plan.email, role: plan.role },\n ),\n );\n return ctx.succeed(\n { host, ...invited },\n ctx.ui.result({\n title: `Invited ${invited.invitation.email} to ${invited.team.slug}`,\n rows: [\n ['Role', invited.invitation.role],\n ['Expires', invited.invitation.expiresAt.slice(0, 10)],\n ],\n notes: [\n 'The invitation email is on its way; they join when they accept it.',\n ],\n }),\n );\n }\n\n case 'members-role': {\n const changed = await client.call((token) =>\n setTeamMemberRole(\n host,\n token,\n { source, team: plan.team, email: plan.email },\n plan.role,\n ),\n );\n return ctx.succeed(\n { host, ...changed },\n ctx.ui.result({\n title:\n changed.before === changed.after\n ? `${changed.email} is already ${changed.after} on ${changed.team.slug}`\n : `${changed.email} is now ${changed.after} on ${changed.team.slug}`,\n rows: [\n ['Was', changed.before ?? '—'],\n [\n 'Applies to',\n changed.kind === 'member'\n ? 'their membership'\n : 'their pending invitation',\n ],\n ],\n }),\n );\n }\n\n case 'members-remove': {\n const removed = await client.call((token) =>\n removeTeamMember(host, token, {\n source,\n team: plan.team,\n email: plan.email,\n }),\n );\n return ctx.succeed(\n { host, ...removed },\n ctx.ui.result({\n title:\n removed.kind === 'member'\n ? `Removed ${removed.email} from ${removed.team.slug}`\n : `Withdrew ${removed.email}'s invitation to ${removed.team.slug}`,\n rows: [['Role was', removed.before ?? '—']],\n }),\n );\n }\n\n case 'roles-list': {\n const roles = await client.call((token) =>\n listTeamRoles(host, token, { source, team: plan.team }),\n );\n return ctx.succeed(\n { host, ...roles },\n ctx.ui.result({\n title: `Roles on ${roles.team.slug}`,\n rows: roles.roles.map((role) => [\n `${role.name} (${role.displayName})`,\n role.permissions.length > 0 ? role.permissions : ['no permissions'],\n ]),\n notes: [\n 'Lower roles are listed last. Give one with \"ekanos teams members role <team> <email> <role>\".',\n ],\n }),\n );\n }\n\n case 'disconnect': {\n const done = await client.call((token) =>\n disconnectTeamIntegration(host, token, {\n source,\n team: plan.team,\n product: plan.product,\n }),\n );\n return ctx.succeed(\n { host, ...done },\n ctx.ui.result({\n title: done.wasConnected\n ? `Disconnected ${done.product.name} from ${done.team.slug}`\n : `${done.team.slug} had no ${done.product.name} connection; cleared what was left`,\n tone: 'warn',\n notes: [\n `Connect it again with \"ekanos teams connect ${done.team.slug} ${done.product.slug}\".`,\n ],\n }),\n );\n }\n\n case 'connect':\n return runTeamConnect(ctx, args, client, host, source, {\n team: plan.team,\n product: plan.product,\n as: plan.as,\n ...(args.connection ? { connection: args.connection } : {}),\n });\n }\n}\n\nfunction noExtra(extra: readonly string[]) {\n if (extra.length > 0) {\n throw usageError(\n `Unexpected argument \"${extra[0]}\".`,\n 'See \"ekanos teams --help\".',\n );\n }\n}\n\nfunction slugOf(value: string | undefined, what: 'team' | 'product'): 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 ? `\"${value}\" is not a ${what} slug.` : `Name the ${what}.`,\n what === 'team'\n ? '\"ekanos teams list\" lists the teams, e.g. \"ekanos teams members list bank-a\".'\n : '\"ekanos catalog\" lists the products, e.g. \"ekanos teams connect bank-a zendesk\".',\n );\n}\n\nfunction emailOf(value: string | undefined): string {\n const email = value?.trim().toLowerCase();\n if (email && /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email)) return email;\n throw usageError(\n value ? `\"${value}\" is not an email address.` : 'Name the person by email.',\n 'e.g. \"ekanos teams members invite bank-a ana@bank-a.com --role member\".',\n );\n}\n\nfunction roleOf(value: string): string {\n const role = value.trim().toLowerCase();\n if (/^[a-z][a-z0-9_-]{0,49}$/.test(role)) return role;\n throw usageError(\n `\"${value}\" is not a role name.`,\n '\"ekanos teams roles list <team>\" lists the roles this Source uses.',\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"teams-onboard.js","sourceRoot":"","sources":["../../src/commands/teams-onboard.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CliContext } from '../context';\nimport { invalidStateError, usageError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport {\n addTeamMember,\n createTeam,\n disconnectTeamIntegration,\n inviteTeamMember,\n listTeamMembers,\n listTeamRoles,\n removeTeamMember,\n renameTeam,\n setTeamMemberRole,\n} from '../teams-api';\nimport type { TeamsArgs, TeamsClient } from './teams';\nimport { runTeamConnect } from './teams-connect';\n\n/**\n * Onboarding a team from the terminal, for the Source admin: `teams create`,\n * `teams members list|invite|role|remove`, `teams roles list`,\n * `teams connect` and `teams disconnect`. Parsed before any session is touched (`parseOnboarding`)\n * so a usage error never costs a network round-trip, then run against the\n * session `runTeams` resolved.\n */\n\nexport const ONBOARDING_SUBCOMMANDS = [\n 'create',\n 'rename',\n 'members',\n 'roles',\n 'connect',\n 'disconnect',\n] as const;\nexport type OnboardingSubcommand = (typeof ONBOARDING_SUBCOMMANDS)[number];\n\nexport interface OnboardingFlags {\n slug?: string;\n owner?: string;\n role?: string;\n /** `connect --as <member-email>`: the member who signs in. */\n as?: string;\n /** `members add --self`: the caller joins. */\n self?: boolean;\n /** `disconnect --mine`: the caller's own personal connection. */\n mine?: boolean;\n yes: boolean;\n}\n\nexport type OnboardingPlan =\n | { kind: 'create'; name: string; slug?: string; ownerEmail?: string }\n | { kind: 'rename'; team: string; name: string }\n | { kind: 'members-list'; team: string }\n | { kind: 'members-invite'; team: string; email: string; role: string }\n | {\n kind: 'members-add';\n team: string;\n target: { self: true } | { email: string };\n role?: string;\n }\n | { kind: 'members-role'; team: string; email: string; role: string }\n | { kind: 'members-remove'; team: string; email: string }\n | { kind: 'roles-list'; team: string }\n | { kind: 'connect'; team: string; product: string; as?: string }\n | { kind: 'disconnect'; team: string; product: string; mine: boolean };\n\nconst MEMBERS_VERBS = ['list', 'add', 'invite', 'role', 'remove'] as const;\n\nexport function isOnboardingSubcommand(\n value: string,\n): value is OnboardingSubcommand {\n return (ONBOARDING_SUBCOMMANDS as readonly string[]).includes(value);\n}\n\nexport function parseOnboarding(\n subcommand: OnboardingSubcommand,\n rest: readonly string[],\n flags: OnboardingFlags,\n): OnboardingPlan {\n if (subcommand === 'create') {\n const [name, ...extra] = rest;\n if (!name?.trim()) {\n throw usageError(\n 'Name the team.',\n 'Run \"ekanos teams create \\\\\"Bank A\\\\\" [--slug bank-a] [--owner <email>]\".',\n );\n }\n noExtra(extra);\n return {\n kind: 'create',\n name: name.trim(),\n slug: flags.slug === undefined ? undefined : slugOf(flags.slug, 'team'),\n ownerEmail: flags.owner === undefined ? undefined : emailOf(flags.owner),\n };\n }\n\n if (subcommand === 'rename') {\n const [team, name, ...extra] = rest;\n const teamSlug = slugOf(team, 'team');\n if (!name?.trim()) {\n throw usageError(\n 'Name the team’s new name.',\n `Run \"ekanos teams rename ${teamSlug} \\\\\"Bank A Support\\\\\"\".`,\n );\n }\n noExtra(extra);\n return { kind: 'rename', team: teamSlug, name: name.trim() };\n }\n\n if (subcommand === 'connect') {\n const [team, product, ...extra] = rest;\n noExtra(extra);\n return {\n kind: 'connect',\n team: slugOf(team, 'team'),\n product: slugOf(product, 'product'),\n ...(flags.as === undefined ? {} : { as: emailOf(flags.as) }),\n };\n }\n\n if (subcommand === 'disconnect') {\n const [team, product, ...extra] = rest;\n noExtra(extra);\n const teamSlug = slugOf(team, 'team');\n const productSlug = slugOf(product, 'product');\n const mine = flags.mine === true;\n if (!flags.yes) {\n throw invalidStateError(\n mine\n ? `Disconnecting your own ${productSlug} connection removes its tokens: anything of ${teamSlug} that acts with your connection — your personal agents, an agent that runs as you — stops until you connect it again.`\n : `Disconnecting ${productSlug} from ${teamSlug} removes the team's connection and its tokens: every widget, workflow and agent of the team that uses it stops until someone connects it again. The team's own app (its saved fields) stays.`,\n `Re-run with --yes: ekanos teams disconnect ${teamSlug} ${productSlug}${mine ? ' --mine' : ''} --yes`,\n );\n }\n return { kind: 'disconnect', team: teamSlug, product: productSlug, mine };\n }\n\n if (subcommand === 'roles') {\n const [verb, team, ...extra] = rest;\n if (verb !== 'list') {\n throw usageError(\n verb\n ? `Unknown teams roles subcommand \"${verb}\".`\n : 'teams roles needs a subcommand.',\n 'Run \"ekanos teams roles list <team>\".',\n );\n }\n noExtra(extra);\n return { kind: 'roles-list', team: slugOf(team, 'team') };\n }\n\n const [verb, team, email, role, ...extra] = rest;\n const match = MEMBERS_VERBS.find((name) => name === verb);\n if (!match) {\n throw usageError(\n verb\n ? `Unknown teams members subcommand \"${verb}\".`\n : 'teams members needs a subcommand.',\n 'Run one of: ekanos teams members list <team>, ekanos teams members add <team> --self | <email> [--role <role>], ekanos teams members invite <team> <email> --role <role>, ekanos teams members role <team> <email> <role>, ekanos teams members remove <team> <email> --yes, ekanos teams members resend <team> <email>.',\n );\n }\n noExtra(extra);\n\n if (match === 'list') {\n if (email !== undefined) noExtra([email]);\n return { kind: 'members-list', team: slugOf(team, 'team') };\n }\n\n const teamSlug = slugOf(team, 'team');\n\n if (match === 'add') {\n if (role !== undefined) noExtra([role]);\n if (flags.self === true && email !== undefined) {\n throw usageError(\n 'Name one person: --self, or an email.',\n `Run \"ekanos teams members add ${teamSlug} --self\" to join it yourself, or \"ekanos teams members add ${teamSlug} <email>\" for someone who already has an Ekanos account on this Source.`,\n );\n }\n if (flags.self !== true && email === undefined) {\n throw usageError(\n 'Name who joins: --self, or an email.',\n `Run \"ekanos teams members add ${teamSlug} --self\" to join it yourself.`,\n );\n }\n return {\n kind: 'members-add',\n team: teamSlug,\n target: flags.self === true ? { self: true } : { email: emailOf(email) },\n ...(flags.role === undefined ? {} : { role: roleOf(flags.role) }),\n };\n }\n\n const address = emailOf(email);\n\n if (match === 'invite') {\n if (role !== undefined) noExtra([role]);\n return {\n kind: 'members-invite',\n team: teamSlug,\n email: address,\n role: roleOf(flags.role ?? 'member'),\n };\n }\n\n if (match === 'role') {\n const named = role ?? flags.role;\n if (!named) {\n throw usageError(\n 'Name the new role.',\n `Run \"ekanos teams members role ${teamSlug} ${address} <role>\"; \"ekanos teams roles list ${teamSlug}\" lists them.`,\n );\n }\n return {\n kind: 'members-role',\n team: teamSlug,\n email: address,\n role: roleOf(named),\n };\n }\n\n if (role !== undefined) noExtra([role]);\n if (!flags.yes) {\n throw invalidStateError(\n `Removing ${address} from ${teamSlug} ends their access to the team (a pending invitation is withdrawn instead).`,\n `Re-run with --yes: ekanos teams members remove ${teamSlug} ${address} --yes`,\n );\n }\n return { kind: 'members-remove', team: teamSlug, email: address };\n}\n\nexport async function runOnboarding(\n ctx: CliContext,\n args: TeamsArgs,\n client: TeamsClient,\n host: string,\n source: string,\n plan: OnboardingPlan,\n): Promise<ExitCode> {\n switch (plan.kind) {\n case 'create': {\n const created = await client.call((token) =>\n createTeam(host, token, source, {\n name: plan.name,\n slug: plan.slug,\n ownerEmail: plan.ownerEmail,\n }),\n );\n return ctx.succeed(\n { host, ...created },\n ctx.ui.result({\n title: `Created team ${created.team.slug}`,\n rows: [\n ['Name', created.team.name],\n ['Source', created.source.slug],\n [\n 'Owner',\n created.owner.kind === 'caller'\n ? `you${created.owner.email ? ` (${created.owner.email})` : ''}`\n : `${created.owner.email} — invited; ownership moves to them on accept`,\n ],\n ['Team home', created.teamUrl],\n ],\n notes: [\n `Next: \"ekanos teams members invite ${created.team.slug} <email> --role <role>\" (\"ekanos teams roles list ${created.team.slug}\" lists the roles).`,\n `Then \"ekanos teams connect ${created.team.slug} <product>\" connects an integration for the team.`,\n ],\n }),\n );\n }\n\n case 'rename': {\n const renamed = await client.call((token) =>\n renameTeam(host, token, { source, team: plan.team }, plan.name),\n );\n const moved = renamed.team.slug !== renamed.previous.slug;\n return ctx.succeed(\n { host, ...renamed },\n ctx.ui.result({\n title:\n renamed.team.name === renamed.previous.name\n ? `${renamed.team.slug} is already named ${renamed.team.name}`\n : `Renamed ${renamed.previous.slug} to ${renamed.team.name}`,\n rows: [\n ['Name', renamed.team.name],\n ['Slug', renamed.team.slug],\n ['Team home', renamed.teamUrl],\n ],\n notes: moved\n ? [\n `The slug followed the name: use \"${renamed.team.slug}\" from now on. Links and scripts naming \"${renamed.previous.slug}\" no longer reach the team.`,\n ]\n : [],\n tone: moved ? 'warn' : 'ok',\n }),\n );\n }\n\n case 'members-list': {\n const list = await client.call((token) =>\n listTeamMembers(host, token, { source, team: plan.team }),\n );\n const rows: [string, string][] = list.members.map((member) => [\n member.email ?? member.userId,\n `${member.role}${member.primaryOwner ? ' · primary owner' : ''}${member.status === 'active' ? '' : ` · ${member.status}`}${member.name ? ` · ${member.name}` : ''}`,\n ]);\n for (const invitation of list.invitations) {\n rows.push([\n invitation.email,\n `${invitation.role} · invited, expires ${invitation.expiresAt.slice(0, 10)}`,\n ]);\n }\n return ctx.succeed(\n { host, ...list },\n ctx.ui.result({\n title: `Members of ${list.team.slug} (${list.team.name})`,\n tone: rows.length === 0 ? 'warn' : 'ok',\n rows,\n notes: [\n `\"ekanos teams members add ${list.team.slug} --self\" joins it yourself, now; \"ekanos teams members add ${list.team.slug} <email>\" adds someone already on the Source; \"ekanos teams members invite ${list.team.slug} <email> --role <role>\" emails anyone else an invitation.`,\n ],\n }),\n );\n }\n\n case 'members-add': {\n const added = await client.call((token) =>\n addTeamMember(\n host,\n token,\n { source, team: plan.team },\n { ...plan.target, ...(plan.role ? { role: plan.role } : {}) },\n ),\n );\n const who = added.self\n ? `you${added.member.email ? ` (${added.member.email})` : ''}`\n : (added.member.email ?? added.member.userId);\n const already = added.outcome === 'already';\n return ctx.succeed(\n { host, ...added },\n ctx.ui.result({\n title: already\n ? `${added.self ? 'You are' : `${who} is`} already a member of ${added.team.slug}`\n : `Added ${who} to ${added.team.slug}`,\n rows: [\n ['Role', added.member.role],\n ['Status', added.member.status],\n ],\n notes: [\n ...(already && plan.role && plan.role !== added.member.role\n ? [\n `The role was left as ${added.member.role}. Change it: ekanos teams members role ${added.team.slug} ${added.member.email ?? '<email>'} ${plan.role}`,\n ]\n : []),\n ...(added.withdrawnInvitation\n ? [\n `Their pending invitation${added.withdrawnInvitationRole ? ` (as ${added.withdrawnInvitationRole})` : ''} was withdrawn: the membership replaces it.`,\n ]\n : []),\n ...(already ? [] : ['No email was sent: it takes effect now.']),\n `Connect a product for ${added.self ? 'yourself' : 'the team'}: ekanos teams connect ${added.team.slug} <product>`,\n ],\n }),\n );\n }\n\n case 'members-invite': {\n const invited = await client.call((token) =>\n inviteTeamMember(\n host,\n token,\n { source, team: plan.team },\n { email: plan.email, role: plan.role },\n ),\n );\n return ctx.succeed(\n { host, ...invited },\n ctx.ui.result({\n title: `Invited ${invited.invitation.email} to ${invited.team.slug}`,\n rows: [\n ['Role', invited.invitation.role],\n ['Expires', invited.invitation.expiresAt.slice(0, 10)],\n ],\n notes: [\n 'The invitation email is on its way; they join when they accept it.',\n ],\n }),\n );\n }\n\n case 'members-role': {\n const changed = await client.call((token) =>\n setTeamMemberRole(\n host,\n token,\n { source, team: plan.team, email: plan.email },\n plan.role,\n ),\n );\n return ctx.succeed(\n { host, ...changed },\n ctx.ui.result({\n title:\n changed.before === changed.after\n ? `${changed.email} is already ${changed.after} on ${changed.team.slug}`\n : `${changed.email} is now ${changed.after} on ${changed.team.slug}`,\n rows: [\n ['Was', changed.before ?? '—'],\n [\n 'Applies to',\n changed.kind === 'member'\n ? 'their membership'\n : 'their pending invitation',\n ],\n ],\n }),\n );\n }\n\n case 'members-remove': {\n const removed = await client.call((token) =>\n removeTeamMember(host, token, {\n source,\n team: plan.team,\n email: plan.email,\n }),\n );\n return ctx.succeed(\n { host, ...removed },\n ctx.ui.result({\n title:\n removed.kind === 'member'\n ? `Removed ${removed.email} from ${removed.team.slug}`\n : `Withdrew ${removed.email}'s invitation to ${removed.team.slug}`,\n rows: [['Role was', removed.before ?? '—']],\n }),\n );\n }\n\n case 'roles-list': {\n const roles = await client.call((token) =>\n listTeamRoles(host, token, { source, team: plan.team }),\n );\n return ctx.succeed(\n { host, ...roles },\n ctx.ui.result({\n title: `Roles on ${roles.team.slug}`,\n rows: roles.roles.map((role) => [\n `${role.name} (${role.displayName})`,\n role.permissions.length > 0 ? role.permissions : ['no permissions'],\n ]),\n notes: [\n 'Lower roles are listed last. Give one with \"ekanos teams members role <team> <email> <role>\".',\n ],\n }),\n );\n }\n\n case 'disconnect': {\n const done = await client.call((token) =>\n disconnectTeamIntegration(host, token, {\n source,\n team: plan.team,\n product: plan.product,\n mine: plan.mine,\n }),\n );\n return ctx.succeed(\n { host, ...done, ...(plan.mine ? { mine: true } : {}) },\n ctx.ui.result({\n title: plan.mine\n ? done.wasConnected\n ? `Disconnected your own ${done.product.name} connection`\n : `You had no ${done.product.name} connection; cleared what was left`\n : done.wasConnected\n ? `Disconnected ${done.product.name} from ${done.team.slug}`\n : `${done.team.slug} had no ${done.product.name} connection; cleared what was left`,\n tone: 'warn',\n notes: [\n `Connect it again with \"ekanos teams connect ${done.team.slug} ${done.product.slug}\".`,\n ],\n }),\n );\n }\n\n case 'connect':\n return runTeamConnect(ctx, args, client, host, source, {\n team: plan.team,\n product: plan.product,\n as: plan.as,\n ...(args.connection ? { connection: args.connection } : {}),\n });\n }\n}\n\nfunction noExtra(extra: readonly string[]) {\n if (extra.length > 0) {\n throw usageError(\n `Unexpected argument \"${extra[0]}\".`,\n 'See \"ekanos teams --help\".',\n );\n }\n}\n\nfunction slugOf(value: string | undefined, what: 'team' | 'product'): 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 ? `\"${value}\" is not a ${what} slug.` : `Name the ${what}.`,\n what === 'team'\n ? '\"ekanos teams list\" lists the teams, e.g. \"ekanos teams members list bank-a\".'\n : '\"ekanos catalog\" lists the products, e.g. \"ekanos teams connect bank-a zendesk\".',\n );\n}\n\nfunction emailOf(value: string | undefined): string {\n const email = value?.trim().toLowerCase();\n if (email && /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email)) return email;\n throw usageError(\n value ? `\"${value}\" is not an email address.` : 'Name the person by email.',\n 'e.g. \"ekanos teams members invite bank-a ana@bank-a.com --role member\".',\n );\n}\n\nfunction roleOf(value: string): string {\n const role = value.trim().toLowerCase();\n if (/^[a-z][a-z0-9_-]{0,49}$/.test(role)) return role;\n throw usageError(\n `\"${value}\" is not a role name.`,\n '\"ekanos teams roles list <team>\" lists the roles this Source uses.',\n );\n}\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SourceCatalogSchema, TeamAgentListSchema, } from '@ekanos/integration-schema';
|
|
2
2
|
import { notFoundError } from '../errors.js';
|
|
3
|
+
import { cli } from '../invocation.js';
|
|
3
4
|
import { call, listTeams, showTeamIntegration } from '../teams-api.js';
|
|
4
5
|
import { scopeFix, scopeHiddenWords } from './scope-notice.js';
|
|
5
6
|
import { REASON_WORDS, agentReadiness, liveLine, requirementFix, } from './team-agent-readiness.js';
|
|
@@ -30,7 +31,10 @@ export async function runTeamOverview(ctx, client, host, source, team) {
|
|
|
30
31
|
if (!ref) {
|
|
31
32
|
throw notFoundError(`No team "${team}" on ${teams.source.slug}.`, 'Run "ekanos teams list" to see the teams on this Source.');
|
|
32
33
|
}
|
|
33
|
-
const integrations = catalog.products.filter((product) => product.kind === 'integration' &&
|
|
34
|
+
const integrations = catalog.products.filter((product) => product.kind === 'integration' &&
|
|
35
|
+
product.availability === 'enabled' &&
|
|
36
|
+
// A catalog row with no package on this host has no team status to read.
|
|
37
|
+
product.registered !== false);
|
|
34
38
|
const statuses = await inBatches(integrations, 4, (product) => client.call((token) => showTeamIntegration(host, token, {
|
|
35
39
|
source,
|
|
36
40
|
team,
|
|
@@ -135,7 +139,7 @@ function integrationLine(product, status, need, target) {
|
|
|
135
139
|
}
|
|
136
140
|
return {
|
|
137
141
|
state: `✗ not connected${webhookNote}`,
|
|
138
|
-
fix:
|
|
142
|
+
fix: `${cli()} teams connect ${target.team} ${product.slug} --source ${target.source}`,
|
|
139
143
|
};
|
|
140
144
|
}
|
|
141
145
|
/** A product the team's scopes hide from it in the app says so, whatever else is true. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"teams-overview.js","sourceRoot":"","sources":["../../src/commands/teams-overview.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type CatalogProduct,\n type Requirement,\n SourceCatalogSchema,\n TeamAgentListSchema,\n type TeamIntegrationStatus,\n} from '@ekanos/integration-schema';\n\nimport type { CliContext } from '../context';\nimport { notFoundError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport { call, listTeams, showTeamIntegration } from '../teams-api';\nimport { scopeFix, scopeHiddenWords } from './scope-notice';\nimport {\n REASON_WORDS,\n agentReadiness,\n liveLine,\n requirementFix,\n} from './team-agent-readiness';\nimport type { TeamsClient } from './teams';\n\n/**\n * `ekanos teams show <team>` with no product: one screen per team (CLI audit\n * P1-7) — its members, one line per Integration the Source has enabled (whose\n * connection, or the step to make it), and one line per provided agent with\n * the same verdict as `teams agents show`. Reads the team list, the Source\n * catalog, the team's agents, and each enabled Integration's status.\n */\nexport async function runTeamOverview(\n ctx: CliContext,\n client: TeamsClient,\n host: string,\n source: string,\n team: string,\n): Promise<ExitCode> {\n const [teams, catalog, agents] = await Promise.all([\n client.call((token) => listTeams(host, token, source)),\n client.call((token) =>\n call(host, token, SourceCatalogSchema, {\n method: 'GET',\n path: '/api/partner/catalog',\n source,\n }),\n ),\n client.call((token) =>\n call(host, token, TeamAgentListSchema, {\n method: 'GET',\n path: `/api/partner/teams/${encodeURIComponent(team)}/agents`,\n source,\n }),\n ),\n ]);\n const ref = teams.teams.find((entry) => entry.slug === team);\n if (!ref) {\n throw notFoundError(\n `No team \"${team}\" on ${teams.source.slug}.`,\n 'Run \"ekanos teams list\" to see the teams on this Source.',\n );\n }\n\n const integrations = catalog.products.filter(\n (product) =>\n product.kind === 'integration' && product.availability === 'enabled',\n );\n const statuses = await inBatches(integrations, 4, (product) =>\n client.call((token) =>\n showTeamIntegration(host, token, {\n source,\n team,\n product: product.slug,\n }),\n ),\n );\n\n // What the team's agents need of each product, and whose connection it is.\n const needs = new Map<string, Requirement>();\n for (const entry of agents.agents) {\n for (const item of entry.agent?.requirements ?? []) {\n if (item.kind === 'product' && !needs.has(item.key)) {\n needs.set(item.key, item);\n }\n }\n }\n\n const target = { team, source };\n const agentRows = agents.agents.map((entry) => ({\n key: entry.key,\n name: entry.name,\n on: entry.agent?.status === 'active',\n readiness: agentReadiness(entry, target),\n }));\n const integrationRows = integrations.map((product, index) => ({\n slug: product.slug,\n name: product.name,\n line: withScope(\n integrationLine(\n product,\n statuses[index]!,\n needs.get(product.slug),\n target,\n ),\n statuses[index]!,\n { ...target, product: product.slug },\n ),\n }));\n\n const width = Math.max(\n 8,\n ...integrations.map((product) => product.slug.length),\n ...agents.agents.map((entry) => entry.key.length),\n );\n const pad = (label: string) => label.padEnd(width);\n const live = agentRows.filter((row) => row.readiness.live).length;\n\n return ctx.succeed(\n {\n host,\n team: { slug: ref.slug, name: ref.name, memberCount: ref.memberCount },\n integrations: integrationRows.map((row, index) => ({\n slug: row.slug,\n name: row.name,\n status: statuses[index],\n agentsNeed: needs.get(row.slug) ?? null,\n })),\n agents: agentRows,\n },\n [\n `${ref.name} (${ref.slug}) · ${ref.memberCount} member${ref.memberCount === 1 ? '' : 's'} · ${agentRows.filter((row) => row.on).length} agent${agentRows.filter((row) => row.on).length === 1 ? '' : 's'} on, ${live} live`,\n '',\n 'Integrations',\n ...(integrationRows.length === 0\n ? [' none enabled for the Source']\n : integrationRows.flatMap((row) => [\n ` ${pad(row.slug)} ${row.line.state}`,\n ...(row.line.fix ? [` ${pad('')} → ${row.line.fix}`] : []),\n ])),\n '',\n 'Agents',\n ...(agentRows.length === 0\n ? [' none provided']\n : agentRows.map(\n (row) =>\n ` ${pad(row.key)} ${liveLine(row.readiness)}${row.readiness.next ? ` · Next: ${row.readiness.next}` : ''}`,\n )),\n '',\n `\"ekanos teams agents show ${team} <key>\" explains one agent; \"ekanos teams show ${team} <product>\" one integration.`,\n ].join('\\n'),\n );\n}\n\nfunction integrationLine(\n product: CatalogProduct,\n status: TeamIntegrationStatus,\n need: Requirement | undefined,\n target: { team: string; source: string },\n): { state: string; fix: string | null } {\n if (need?.owner === 'source' || need?.via === 'source') {\n const problem =\n need.reason && need.reason !== 'not_connected'\n ? REASON_WORDS[need.reason]\n : null;\n const state = !need.connected\n ? `✗ via Source connection — ${problem ?? REASON_WORDS.not_connected}`\n : need.via === 'source'\n ? `✓ via Source connection${need.viaDetail ? ` · routes: ${need.viaDetail}` : ''}`\n : `! via team connection (${problem ?? 'the Source connection is not used'})`;\n return {\n state,\n fix:\n need.connected && need.via === 'source'\n ? null\n : requirementFix(need, target.team, target.source),\n };\n }\n if (!product.requiresActivation) {\n return { state: '✓ works as shipped', fix: null };\n }\n if (product.scope === 'user') {\n const person =\n need?.via === 'person' && need.viaDetail\n ? need.connected\n ? ` · ✓ ${need.viaDetail} connected (an agent runs as them)`\n : ` · ✗ ${need.viaDetail} not connected (an agent runs as them)`\n : '';\n return {\n state: `personal: each person connects their own${person}`,\n fix:\n need && !need.connected\n ? requirementFix(need, target.team, target.source)\n : null,\n };\n }\n const webhooks = status.teamApps.flatMap((app) => app.webhooks);\n const made = webhooks.filter((webhook) => webhook.endpoint).length;\n const webhookNote =\n webhooks.length > 0 ? ` · webhook URL ${made}/${webhooks.length} made` : '';\n if (status.activation) {\n const by = status.activation.activatedBy?.email;\n return {\n state: `✓ connected${status.activation.activatedAt ? ` ${status.activation.activatedAt.slice(0, 10)}` : ''}${by ? ` by ${by}` : ''}${webhookNote}`,\n fix: null,\n };\n }\n return {\n state: `✗ not connected${webhookNote}`,\n fix: `npx @ekanos/cli teams connect ${target.team} ${product.slug} --source ${target.source}`,\n };\n}\n\n/** A product the team's scopes hide from it in the app says so, whatever else is true. */\nfunction withScope(\n line: { state: string; fix: string | null },\n status: TeamIntegrationStatus,\n target: { team: string; source: string; product: string },\n): { state: string; fix: string | null } {\n if (!status.scope?.hidden) return line;\n return {\n state: `${line.state} · ! ${scopeHiddenWords(status.scope)}`,\n fix: line.fix ?? scopeFix(status.scope, target),\n };\n}\n\n/** Each item through `read`, at most `size` at a time, in order. */\nasync function inBatches<T, R>(\n items: T[],\n size: number,\n read: (item: T) => Promise<R>,\n): Promise<R[]> {\n const results: R[] = [];\n for (let start = 0; start < items.length; start += size) {\n results.push(\n ...(await Promise.all(items.slice(start, start + size).map(read))),\n );\n }\n return results;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"teams-overview.js","sourceRoot":"","sources":["../../src/commands/teams-overview.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type CatalogProduct,\n type Requirement,\n SourceCatalogSchema,\n TeamAgentListSchema,\n type TeamIntegrationStatus,\n} from '@ekanos/integration-schema';\n\nimport type { CliContext } from '../context';\nimport { notFoundError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport { cli } from '../invocation';\nimport { call, listTeams, showTeamIntegration } from '../teams-api';\nimport { scopeFix, scopeHiddenWords } from './scope-notice';\nimport {\n REASON_WORDS,\n agentReadiness,\n liveLine,\n requirementFix,\n} from './team-agent-readiness';\nimport type { TeamsClient } from './teams';\n\n/**\n * `ekanos teams show <team>` with no product: one screen per team (CLI audit\n * P1-7) — its members, one line per Integration the Source has enabled (whose\n * connection, or the step to make it), and one line per provided agent with\n * the same verdict as `teams agents show`. Reads the team list, the Source\n * catalog, the team's agents, and each enabled Integration's status.\n */\nexport async function runTeamOverview(\n ctx: CliContext,\n client: TeamsClient,\n host: string,\n source: string,\n team: string,\n): Promise<ExitCode> {\n const [teams, catalog, agents] = await Promise.all([\n client.call((token) => listTeams(host, token, source)),\n client.call((token) =>\n call(host, token, SourceCatalogSchema, {\n method: 'GET',\n path: '/api/partner/catalog',\n source,\n }),\n ),\n client.call((token) =>\n call(host, token, TeamAgentListSchema, {\n method: 'GET',\n path: `/api/partner/teams/${encodeURIComponent(team)}/agents`,\n source,\n }),\n ),\n ]);\n const ref = teams.teams.find((entry) => entry.slug === team);\n if (!ref) {\n throw notFoundError(\n `No team \"${team}\" on ${teams.source.slug}.`,\n 'Run \"ekanos teams list\" to see the teams on this Source.',\n );\n }\n\n const integrations = catalog.products.filter(\n (product) =>\n product.kind === 'integration' &&\n product.availability === 'enabled' &&\n // A catalog row with no package on this host has no team status to read.\n product.registered !== false,\n );\n const statuses = await inBatches(integrations, 4, (product) =>\n client.call((token) =>\n showTeamIntegration(host, token, {\n source,\n team,\n product: product.slug,\n }),\n ),\n );\n\n // What the team's agents need of each product, and whose connection it is.\n const needs = new Map<string, Requirement>();\n for (const entry of agents.agents) {\n for (const item of entry.agent?.requirements ?? []) {\n if (item.kind === 'product' && !needs.has(item.key)) {\n needs.set(item.key, item);\n }\n }\n }\n\n const target = { team, source };\n const agentRows = agents.agents.map((entry) => ({\n key: entry.key,\n name: entry.name,\n on: entry.agent?.status === 'active',\n readiness: agentReadiness(entry, target),\n }));\n const integrationRows = integrations.map((product, index) => ({\n slug: product.slug,\n name: product.name,\n line: withScope(\n integrationLine(\n product,\n statuses[index]!,\n needs.get(product.slug),\n target,\n ),\n statuses[index]!,\n { ...target, product: product.slug },\n ),\n }));\n\n const width = Math.max(\n 8,\n ...integrations.map((product) => product.slug.length),\n ...agents.agents.map((entry) => entry.key.length),\n );\n const pad = (label: string) => label.padEnd(width);\n const live = agentRows.filter((row) => row.readiness.live).length;\n\n return ctx.succeed(\n {\n host,\n team: { slug: ref.slug, name: ref.name, memberCount: ref.memberCount },\n integrations: integrationRows.map((row, index) => ({\n slug: row.slug,\n name: row.name,\n status: statuses[index],\n agentsNeed: needs.get(row.slug) ?? null,\n })),\n agents: agentRows,\n },\n [\n `${ref.name} (${ref.slug}) · ${ref.memberCount} member${ref.memberCount === 1 ? '' : 's'} · ${agentRows.filter((row) => row.on).length} agent${agentRows.filter((row) => row.on).length === 1 ? '' : 's'} on, ${live} live`,\n '',\n 'Integrations',\n ...(integrationRows.length === 0\n ? [' none enabled for the Source']\n : integrationRows.flatMap((row) => [\n ` ${pad(row.slug)} ${row.line.state}`,\n ...(row.line.fix ? [` ${pad('')} → ${row.line.fix}`] : []),\n ])),\n '',\n 'Agents',\n ...(agentRows.length === 0\n ? [' none provided']\n : agentRows.map(\n (row) =>\n ` ${pad(row.key)} ${liveLine(row.readiness)}${row.readiness.next ? ` · Next: ${row.readiness.next}` : ''}`,\n )),\n '',\n `\"ekanos teams agents show ${team} <key>\" explains one agent; \"ekanos teams show ${team} <product>\" one integration.`,\n ].join('\\n'),\n );\n}\n\nfunction integrationLine(\n product: CatalogProduct,\n status: TeamIntegrationStatus,\n need: Requirement | undefined,\n target: { team: string; source: string },\n): { state: string; fix: string | null } {\n if (need?.owner === 'source' || need?.via === 'source') {\n const problem =\n need.reason && need.reason !== 'not_connected'\n ? REASON_WORDS[need.reason]\n : null;\n const state = !need.connected\n ? `✗ via Source connection — ${problem ?? REASON_WORDS.not_connected}`\n : need.via === 'source'\n ? `✓ via Source connection${need.viaDetail ? ` · routes: ${need.viaDetail}` : ''}`\n : `! via team connection (${problem ?? 'the Source connection is not used'})`;\n return {\n state,\n fix:\n need.connected && need.via === 'source'\n ? null\n : requirementFix(need, target.team, target.source),\n };\n }\n if (!product.requiresActivation) {\n return { state: '✓ works as shipped', fix: null };\n }\n if (product.scope === 'user') {\n const person =\n need?.via === 'person' && need.viaDetail\n ? need.connected\n ? ` · ✓ ${need.viaDetail} connected (an agent runs as them)`\n : ` · ✗ ${need.viaDetail} not connected (an agent runs as them)`\n : '';\n return {\n state: `personal: each person connects their own${person}`,\n fix:\n need && !need.connected\n ? requirementFix(need, target.team, target.source)\n : null,\n };\n }\n const webhooks = status.teamApps.flatMap((app) => app.webhooks);\n const made = webhooks.filter((webhook) => webhook.endpoint).length;\n const webhookNote =\n webhooks.length > 0 ? ` · webhook URL ${made}/${webhooks.length} made` : '';\n if (status.activation) {\n const by = status.activation.activatedBy?.email;\n return {\n state: `✓ connected${status.activation.activatedAt ? ` ${status.activation.activatedAt.slice(0, 10)}` : ''}${by ? ` by ${by}` : ''}${webhookNote}`,\n fix: null,\n };\n }\n return {\n state: `✗ not connected${webhookNote}`,\n fix: `${cli()} teams connect ${target.team} ${product.slug} --source ${target.source}`,\n };\n}\n\n/** A product the team's scopes hide from it in the app says so, whatever else is true. */\nfunction withScope(\n line: { state: string; fix: string | null },\n status: TeamIntegrationStatus,\n target: { team: string; source: string; product: string },\n): { state: string; fix: string | null } {\n if (!status.scope?.hidden) return line;\n return {\n state: `${line.state} · ! ${scopeHiddenWords(status.scope)}`,\n fix: line.fix ?? scopeFix(status.scope, target),\n };\n}\n\n/** Each item through `read`, at most `size` at a time, in order. */\nasync function inBatches<T, R>(\n items: T[],\n size: number,\n read: (item: T) => Promise<R>,\n): Promise<R[]> {\n const results: R[] = [];\n for (let start = 0; start < items.length; start += size) {\n results.push(\n ...(await Promise.all(items.slice(start, start + size).map(read))),\n );\n }\n return results;\n}\n"]}
|
|
@@ -2,6 +2,7 @@ import { requireSession, resolveAuthEnvironment } from '../auth/session.js';
|
|
|
2
2
|
import { invalidStateError, usageError } from '../errors.js';
|
|
3
3
|
import { resolveSourceTarget } from '../source-target.js';
|
|
4
4
|
import { setTeamScopes, showTeamScopes } from '../teams-api.js';
|
|
5
|
+
import { scopeDeprecationNotice } from './scope-notice.js';
|
|
5
6
|
import { TeamsClient } from './teams.js';
|
|
6
7
|
const USAGE = 'Run "ekanos teams scope show <team>" or "ekanos teams scope set <team> <scope> [<scope>…] [--yes]".';
|
|
7
8
|
/**
|
|
@@ -29,6 +30,9 @@ export async function runTeamScope(ctx, args, rest) {
|
|
|
29
30
|
if (verb === 'set' && scopes.length === 0) {
|
|
30
31
|
throw usageError('Name the scope (or scopes) the team should hold.', `"ekanos sources scopes" lists them, e.g. "ekanos teams scope set ${team} Gold".`);
|
|
31
32
|
}
|
|
33
|
+
ctx.warn(scopeDeprecationNotice(verb === 'set'
|
|
34
|
+
? `teams audience ${team} <audience>`
|
|
35
|
+
: `teams audience ${team}`));
|
|
32
36
|
const env = resolveAuthEnvironment(ctx, args.host, args.env, {
|
|
33
37
|
projectDir: args.dir,
|
|
34
38
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"teams-scope.js","sourceRoot":"","sources":["../../src/commands/teams-scope.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TeamScopes } 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 { setTeamScopes, showTeamScopes } from '../teams-api';\nimport type { Ui } from '../ui';\nimport { TeamsClient, type TeamsArgs } from './teams';\n\nconst USAGE =\n 'Run \"ekanos teams scope show <team>\" or \"ekanos teams scope set <team> <scope> [<scope>…] [--yes]\".';\n\n/**\n * `teams scope show|set <team>` — which of the Source's product scopes a team\n * holds, and so which products it sees in the app. `set` replaces them\n * (names or ids); taking one away can hide products the team uses, so that\n * needs `--yes`. The Source's scopes and their products: `sources scopes`.\n */\nexport async function runTeamScope(\n ctx: CliContext,\n args: TeamsArgs,\n rest: readonly string[],\n): Promise<ExitCode> {\n const [verb, rawTeam, ...scopes] = rest;\n if (verb !== 'show' && verb !== 'set') {\n throw usageError(\n verb\n ? `Unknown teams scope subcommand \"${verb}\".`\n : 'teams scope needs a subcommand.',\n USAGE,\n );\n }\n const team = rawTeam?.trim().toLowerCase();\n if (!team || !/^[a-z0-9][a-z0-9-]*$/.test(team)) {\n throw usageError(\n rawTeam\n ? `\"${rawTeam}\" is not a team slug.`\n : `teams scope ${verb} needs a team.`,\n USAGE,\n );\n }\n if (verb === 'show' && scopes.length > 0) {\n throw usageError(`Unexpected argument \"${scopes[0]}\".`, USAGE);\n }\n if (verb === 'set' && scopes.length === 0) {\n throw usageError(\n 'Name the scope (or scopes) the team should hold.',\n `\"ekanos sources scopes\" lists them, e.g. \"ekanos teams scope set ${team} Gold\".`,\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 TeamsClient(env, resolved.session);\n const target = { source: resolved.source, team };\n\n const current = await client.call((token) =>\n showTeamScopes(env.host, token, target),\n );\n if (verb === 'show') {\n return ctx.succeed(\n { host: env.host, ...current },\n describe(ctx.ui, current, resolved.source),\n );\n }\n\n const wanted = scopes.map((scope) => scope.trim().toLowerCase());\n const dropped = current.scopes.filter(\n (scope) =>\n !wanted.includes(scope.name.toLowerCase()) && !wanted.includes(scope.id),\n );\n if (dropped.length > 0 && !args.yes) {\n throw invalidStateError(\n `${team} would no longer hold ${dropped.map((scope) => scope.name).join(', ')}: any product only ${dropped.length === 1 ? 'it shows' : 'they show'} disappears from the team in the app.`,\n `Re-run with --yes: ekanos teams scope set ${team} ${scopes.map(quote).join(' ')} --source ${resolved.source} --yes`,\n );\n }\n\n const result = await client.call((token) =>\n setTeamScopes(env.host, token, target, scopes),\n );\n return ctx.succeed(\n { host: env.host, ...result },\n [\n ctx.ui.result({\n title: `${result.team.slug} holds ${names(result.scopes)}`,\n tone: result.hidden.length > 0 ? 'warn' : 'ok',\n rows: [\n ['Before', names(result.before)],\n ...(result.hidden.length > 0\n ? ([\n [\n 'No longer sees',\n result.hidden.map((product) => product.slug),\n ],\n ] as Array<[string, string[]]>)\n : []),\n ],\n }),\n describe(ctx.ui, result, resolved.source),\n ].join('\\n\\n'),\n );\n}\n\nfunction describe(ui: Ui, scopes: TeamScopes, source: string): string {\n if (scopes.state === 'unscoped') {\n return ui.result({\n title: `${scopes.team.slug} sees every product ${scopes.source.slug} has`,\n rows: [['Scopes', `none: ${scopes.source.slug} has no product scopes`]],\n });\n }\n if (scopes.state === 'locked_out') {\n return ui.result({\n title: `${scopes.team.slug} sees no product in the app`,\n tone: 'warn',\n rows: [['Scopes', `none of ${scopes.source.slug}'s`]],\n notes: [\n `Give it one: ekanos teams scope set ${scopes.team.slug} <scope> --source ${source} (\"ekanos sources scopes\" lists them).`,\n ],\n });\n }\n return ui.result({\n title: `What ${scopes.team.slug} sees in the app`,\n rows: [\n ['Scopes', names(scopes.scopes)],\n [\n 'Products',\n (scopes.products ?? []).length > 0\n ? (scopes.products ?? []).map((product) => product.slug)\n : 'none',\n ],\n ],\n notes: [\n `\"ekanos sources scopes add <scope> <product>\" shows a product to every team on a scope.`,\n ],\n });\n}\n\nfunction names(scopes: Array<{ name: string }>): string {\n return scopes.length > 0\n ? scopes.map((scope) => scope.name).join(', ')\n : 'no scope';\n}\n\nfunction quote(name: string): string {\n return /^[A-Za-z0-9._-]+$/.test(name) ? name : `\"${name}\"`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"teams-scope.js","sourceRoot":"","sources":["../../src/commands/teams-scope.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TeamScopes } 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 { setTeamScopes, showTeamScopes } from '../teams-api';\nimport type { Ui } from '../ui';\nimport { scopeDeprecationNotice } from './scope-notice';\nimport { TeamsClient, type TeamsArgs } from './teams';\n\nconst USAGE =\n 'Run \"ekanos teams scope show <team>\" or \"ekanos teams scope set <team> <scope> [<scope>…] [--yes]\".';\n\n/**\n * `teams scope show|set <team>` — which of the Source's product scopes a team\n * holds, and so which products it sees in the app. `set` replaces them\n * (names or ids); taking one away can hide products the team uses, so that\n * needs `--yes`. The Source's scopes and their products: `sources scopes`.\n */\nexport async function runTeamScope(\n ctx: CliContext,\n args: TeamsArgs,\n rest: readonly string[],\n): Promise<ExitCode> {\n const [verb, rawTeam, ...scopes] = rest;\n if (verb !== 'show' && verb !== 'set') {\n throw usageError(\n verb\n ? `Unknown teams scope subcommand \"${verb}\".`\n : 'teams scope needs a subcommand.',\n USAGE,\n );\n }\n const team = rawTeam?.trim().toLowerCase();\n if (!team || !/^[a-z0-9][a-z0-9-]*$/.test(team)) {\n throw usageError(\n rawTeam\n ? `\"${rawTeam}\" is not a team slug.`\n : `teams scope ${verb} needs a team.`,\n USAGE,\n );\n }\n if (verb === 'show' && scopes.length > 0) {\n throw usageError(`Unexpected argument \"${scopes[0]}\".`, USAGE);\n }\n if (verb === 'set' && scopes.length === 0) {\n throw usageError(\n 'Name the scope (or scopes) the team should hold.',\n `\"ekanos sources scopes\" lists them, e.g. \"ekanos teams scope set ${team} Gold\".`,\n );\n }\n\n ctx.warn(\n scopeDeprecationNotice(\n verb === 'set'\n ? `teams audience ${team} <audience>`\n : `teams audience ${team}`,\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 TeamsClient(env, resolved.session);\n const target = { source: resolved.source, team };\n\n const current = await client.call((token) =>\n showTeamScopes(env.host, token, target),\n );\n if (verb === 'show') {\n return ctx.succeed(\n { host: env.host, ...current },\n describe(ctx.ui, current, resolved.source),\n );\n }\n\n const wanted = scopes.map((scope) => scope.trim().toLowerCase());\n const dropped = current.scopes.filter(\n (scope) =>\n !wanted.includes(scope.name.toLowerCase()) && !wanted.includes(scope.id),\n );\n if (dropped.length > 0 && !args.yes) {\n throw invalidStateError(\n `${team} would no longer hold ${dropped.map((scope) => scope.name).join(', ')}: any product only ${dropped.length === 1 ? 'it shows' : 'they show'} disappears from the team in the app.`,\n `Re-run with --yes: ekanos teams scope set ${team} ${scopes.map(quote).join(' ')} --source ${resolved.source} --yes`,\n );\n }\n\n const result = await client.call((token) =>\n setTeamScopes(env.host, token, target, scopes),\n );\n return ctx.succeed(\n { host: env.host, ...result },\n [\n ctx.ui.result({\n title: `${result.team.slug} holds ${names(result.scopes)}`,\n tone: result.hidden.length > 0 ? 'warn' : 'ok',\n rows: [\n ['Before', names(result.before)],\n ...(result.hidden.length > 0\n ? ([\n [\n 'No longer sees',\n result.hidden.map((product) => product.slug),\n ],\n ] as Array<[string, string[]]>)\n : []),\n ],\n }),\n describe(ctx.ui, result, resolved.source),\n ].join('\\n\\n'),\n );\n}\n\nfunction describe(ui: Ui, scopes: TeamScopes, source: string): string {\n if (scopes.state === 'unscoped') {\n return ui.result({\n title: `${scopes.team.slug} sees every product ${scopes.source.slug} has`,\n rows: [['Scopes', `none: ${scopes.source.slug} has no product scopes`]],\n });\n }\n if (scopes.state === 'locked_out') {\n return ui.result({\n title: `${scopes.team.slug} sees no product in the app`,\n tone: 'warn',\n rows: [['Scopes', `none of ${scopes.source.slug}'s`]],\n notes: [\n `Give it one: ekanos teams scope set ${scopes.team.slug} <scope> --source ${source} (\"ekanos sources scopes\" lists them).`,\n ],\n });\n }\n return ui.result({\n title: `What ${scopes.team.slug} sees in the app`,\n rows: [\n ['Scopes', names(scopes.scopes)],\n [\n 'Products',\n (scopes.products ?? []).length > 0\n ? (scopes.products ?? []).map((product) => product.slug)\n : 'none',\n ],\n ],\n notes: [\n `\"ekanos sources scopes add <scope> <product>\" shows a product to every team on a scope.`,\n ],\n });\n}\n\nfunction names(scopes: Array<{ name: string }>): string {\n return scopes.length > 0\n ? scopes.map((scope) => scope.name).join(', ')\n : 'no scope';\n}\n\nfunction quote(name: string): string {\n return /^[A-Za-z0-9._-]+$/.test(name) ? name : `\"${name}\"`;\n}\n"]}
|
package/dist/commands/teams.d.ts
CHANGED
|
@@ -3,8 +3,9 @@ import type { StoredSession } from '../auth/credential-store.js';
|
|
|
3
3
|
import { type AuthEnvironment } from '../auth/session.js';
|
|
4
4
|
import type { CliContext } from '../context.js';
|
|
5
5
|
import type { ExitCode } from '../exit-codes.js';
|
|
6
|
+
import { type SecretFlags, type SecretIO } from '../secret-input.js';
|
|
6
7
|
import { type TeamsApiResult } from '../teams-api.js';
|
|
7
|
-
export declare const TEAMS_SUBCOMMANDS: readonly ["list", "show", "app", "webhook", "events", "scope", "create", "rename", "members", "roles", "connect", "disconnect"];
|
|
8
|
+
export declare const TEAMS_SUBCOMMANDS: readonly ["list", "show", "app", "webhook", "events", "scope", "audience", "create", "rename", "members", "roles", "connect", "disconnect", "leave", "groups", "health", "workspace"];
|
|
8
9
|
export interface TeamsArgs {
|
|
9
10
|
host?: string;
|
|
10
11
|
source?: string;
|
|
@@ -35,6 +36,9 @@ export interface TeamsArgs {
|
|
|
35
36
|
/** Test seams for the questions `app set` asks. */
|
|
36
37
|
ask?: (question: string) => Promise<string>;
|
|
37
38
|
askSecret?: (question: string) => Promise<string>;
|
|
39
|
+
/** Test seams for the secret-input flags (`secret-input.ts`). */
|
|
40
|
+
readStdin?: () => Promise<string>;
|
|
41
|
+
secretFormTimeoutMs?: number;
|
|
38
42
|
}
|
|
39
43
|
export interface Target {
|
|
40
44
|
source: string;
|
|
@@ -47,9 +51,10 @@ export interface Target {
|
|
|
47
51
|
* team's setup of one product as a checklist; `app set` enters or updates
|
|
48
52
|
* any of a team's own app fields (Zendesk's subdomain, client and signing
|
|
49
53
|
* secret), one at a time if need be — a field left alone keeps its saved
|
|
50
|
-
* value.
|
|
51
|
-
*
|
|
52
|
-
*
|
|
54
|
+
* value. A secret is typed at the admin's terminal with hidden input or,
|
|
55
|
+
* without one, read from the environment, a private file, stdin or a form
|
|
56
|
+
* in the browser (`secret-input.ts`) — never a value in argv; a non-secret
|
|
57
|
+
* field may be passed as `--set name=value`; `webhook` mints the URL the
|
|
53
58
|
* team's provider sends to, shown once.
|
|
54
59
|
*/
|
|
55
60
|
export declare function runTeams(ctx: CliContext, args: TeamsArgs): Promise<ExitCode>;
|
|
@@ -61,7 +66,9 @@ interface AppEdits {
|
|
|
61
66
|
values: Record<string, string>;
|
|
62
67
|
/** `--clear name`: remove a saved value. */
|
|
63
68
|
clear: string[];
|
|
64
|
-
/**
|
|
69
|
+
/** `--secret-*`, `--set-secret`, `--browser`: where secrets come from without a terminal. */
|
|
70
|
+
secret: SecretFlags;
|
|
71
|
+
/** Whether any field is collected (asked, or read from the secret-input flags). */
|
|
65
72
|
prompts: boolean;
|
|
66
73
|
}
|
|
67
74
|
/**
|
|
@@ -91,6 +98,17 @@ export declare function promptAndSaveTeamApp(ctx: CliContext, args: TeamsArgs, c
|
|
|
91
98
|
}>;
|
|
92
99
|
/** `teams show`, read top to bottom like a setup checklist. */
|
|
93
100
|
export declare function checklist(status: TeamIntegrationStatus): string[];
|
|
101
|
+
/**
|
|
102
|
+
* One team in `teams list`: its members, and whether the caller is one. A
|
|
103
|
+
* team nobody has joined says so with the command that joins it, rather than
|
|
104
|
+
* reading as a count of zero.
|
|
105
|
+
*/
|
|
106
|
+
export declare function teamLine(entry: {
|
|
107
|
+
slug: string;
|
|
108
|
+
name: string;
|
|
109
|
+
memberCount: number;
|
|
110
|
+
callerIsMember?: boolean;
|
|
111
|
+
}): string;
|
|
94
112
|
export declare function chooseApp(status: TeamIntegrationStatus, connection: string | undefined): TeamAppState;
|
|
95
113
|
export declare class TeamsClient {
|
|
96
114
|
private readonly env;
|
|
@@ -99,4 +117,6 @@ export declare class TeamsClient {
|
|
|
99
117
|
call<T>(send: (accessToken: string) => Promise<TeamsApiResult<T>>): Promise<T>;
|
|
100
118
|
}
|
|
101
119
|
export declare function canPrompt(ctx: CliContext, args: TeamsArgs): boolean;
|
|
120
|
+
/** What the secret-input flags read from, with this run's test seams. */
|
|
121
|
+
export declare function teamsSecretIO(args: TeamsArgs): SecretIO;
|
|
102
122
|
export {};
|