create-hq 10.1.0 → 10.7.1

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.
Files changed (70) hide show
  1. package/dist/admin-onboarding.d.ts +42 -0
  2. package/dist/admin-onboarding.d.ts.map +1 -0
  3. package/dist/admin-onboarding.js +460 -0
  4. package/dist/admin-onboarding.js.map +1 -0
  5. package/dist/art.d.ts +17 -0
  6. package/dist/art.d.ts.map +1 -0
  7. package/dist/art.js +171 -0
  8. package/dist/art.js.map +1 -0
  9. package/dist/auth.d.ts +60 -23
  10. package/dist/auth.d.ts.map +1 -1
  11. package/dist/auth.js +219 -116
  12. package/dist/auth.js.map +1 -1
  13. package/dist/cloud.d.ts +26 -0
  14. package/dist/cloud.d.ts.map +1 -0
  15. package/dist/cloud.js +126 -0
  16. package/dist/cloud.js.map +1 -0
  17. package/dist/company-template.d.ts +34 -0
  18. package/dist/company-template.d.ts.map +1 -0
  19. package/dist/company-template.js +142 -0
  20. package/dist/company-template.js.map +1 -0
  21. package/dist/deps.d.ts +2 -0
  22. package/dist/deps.d.ts.map +1 -1
  23. package/dist/deps.js +42 -30
  24. package/dist/deps.js.map +1 -1
  25. package/dist/fetch-template.d.ts +2 -2
  26. package/dist/fetch-template.d.ts.map +1 -1
  27. package/dist/fetch-template.js +54 -38
  28. package/dist/fetch-template.js.map +1 -1
  29. package/dist/git.d.ts.map +1 -1
  30. package/dist/git.js +28 -4
  31. package/dist/git.js.map +1 -1
  32. package/dist/index.js +18 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/invite-command.d.ts +10 -0
  35. package/dist/invite-command.d.ts.map +1 -0
  36. package/dist/invite-command.js +110 -0
  37. package/dist/invite-command.js.map +1 -0
  38. package/dist/invite.d.ts +91 -0
  39. package/dist/invite.d.ts.map +1 -0
  40. package/dist/invite.js +230 -0
  41. package/dist/invite.js.map +1 -0
  42. package/dist/join-flow.d.ts +32 -0
  43. package/dist/join-flow.d.ts.map +1 -0
  44. package/dist/join-flow.js +194 -0
  45. package/dist/join-flow.js.map +1 -0
  46. package/dist/platform.d.ts +2 -2
  47. package/dist/platform.d.ts.map +1 -1
  48. package/dist/platform.js +14 -1
  49. package/dist/platform.js.map +1 -1
  50. package/dist/scaffold.d.ts +4 -1
  51. package/dist/scaffold.d.ts.map +1 -1
  52. package/dist/scaffold.js +152 -41
  53. package/dist/scaffold.js.map +1 -1
  54. package/dist/team-setup.d.ts +58 -0
  55. package/dist/team-setup.d.ts.map +1 -0
  56. package/dist/team-setup.js +237 -0
  57. package/dist/team-setup.js.map +1 -0
  58. package/dist/teams-flow.d.ts +36 -0
  59. package/dist/teams-flow.d.ts.map +1 -0
  60. package/dist/teams-flow.js +134 -0
  61. package/dist/teams-flow.js.map +1 -0
  62. package/dist/tui.d.ts +8 -0
  63. package/dist/tui.d.ts.map +1 -0
  64. package/dist/tui.js +86 -0
  65. package/dist/tui.js.map +1 -0
  66. package/dist/ui.d.ts +17 -0
  67. package/dist/ui.d.ts.map +1 -1
  68. package/dist/ui.js +45 -0
  69. package/dist/ui.js.map +1 -1
  70. package/package.json +1 -1
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Admin onboarding flow — for users creating a brand new HQ team.
3
+ *
4
+ * Steps:
5
+ * 1. List user's GitHub orgs (only those where they can create repos)
6
+ * 2. Let user pick an existing org or create a new one (browser hand-off)
7
+ * 3. Verify the HQ App is installed on the chosen org (browser hand-off if not)
8
+ * 4. Prompt for team name (default = org display name)
9
+ * 5. Create the {org}/hq private repo
10
+ * 6. Seed the repo locally with the company template + push
11
+ * 7. Clone the repo into companies/{slug}/ as a nested git
12
+ * 8. Return team metadata for the orientation summary
13
+ */
14
+ import { type GitHubAuth } from "./auth.js";
15
+ import { type TeamMetadata } from "./company-template.js";
16
+ export interface AdminOnboardingResult {
17
+ team: TeamMetadata;
18
+ /** Local path where the team repo was cloned. */
19
+ companyDir: string;
20
+ /** GitHub HTML URL for the new team repo. */
21
+ repoHtmlUrl: string;
22
+ }
23
+ export declare function slugify(input: string): string;
24
+ /**
25
+ * Run the admin onboarding flow.
26
+ *
27
+ * @param auth - Authenticated GitHub user
28
+ * @param hqRoot - Local HQ root directory (where companies/ lives)
29
+ * @param hqVersion - HQ template version (for team metadata)
30
+ */
31
+ export declare function runAdminOnboarding(auth: GitHubAuth, hqRoot: string, hqVersion: string): Promise<AdminOnboardingResult | null>;
32
+ /**
33
+ * Interactive invite generation for a single member. Prompts for email,
34
+ * sends org invite, generates token, and prints instructions.
35
+ */
36
+ export declare function generateInviteInteractive(auth: GitHubAuth, meta: TeamMetadata, cloneUrl: string): Promise<void>;
37
+ /**
38
+ * Invite loop — asks "Invite a team member?" and repeats until the admin
39
+ * says no. Used after team creation and from the standalone invite command.
40
+ */
41
+ export declare function inviteLoop(auth: GitHubAuth, meta: TeamMetadata, cloneUrl: string): Promise<void>;
42
+ //# sourceMappingURL=admin-onboarding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-onboarding.d.ts","sourceRoot":"","sources":["../src/admin-onboarding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AASH,OAAO,EACL,KAAK,UAAU,EAIhB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAwB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAiDhF,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,YAAY,CAAC;IACnB,iDAAiD;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,WAAW,EAAE,MAAM,CAAC;CACrB;AA+KD,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM7C;AAID;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CA+PvC;AAID;;;GAGG;AACH,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAqDf;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAaf"}
@@ -0,0 +1,460 @@
1
+ /**
2
+ * Admin onboarding flow — for users creating a brand new HQ team.
3
+ *
4
+ * Steps:
5
+ * 1. List user's GitHub orgs (only those where they can create repos)
6
+ * 2. Let user pick an existing org or create a new one (browser hand-off)
7
+ * 3. Verify the HQ App is installed on the chosen org (browser hand-off if not)
8
+ * 4. Prompt for team name (default = org display name)
9
+ * 5. Create the {org}/hq private repo
10
+ * 6. Seed the repo locally with the company template + push
11
+ * 7. Clone the repo into companies/{slug}/ as a nested git
12
+ * 8. Return team metadata for the orientation summary
13
+ */
14
+ import * as fs from "fs";
15
+ import * as path from "path";
16
+ import * as os from "os";
17
+ import * as crypto from "crypto";
18
+ import { execSync } from "child_process";
19
+ import { createInterface } from "readline";
20
+ import chalk from "chalk";
21
+ import { HQ_GITHUB_APP_SLUG, githubApi, openBrowser, } from "./auth.js";
22
+ import { writeCompanyTemplate } from "./company-template.js";
23
+ import { stepStatus, success, warn, info } from "./ui.js";
24
+ import { encodeInviteToken, printInviteSummary, openInviteEmail, formatInviteMessage, copyToClipboard, sendOrgInviteByEmail, } from "./invite.js";
25
+ // ─── Prompt helpers ─────────────────────────────────────────────────────────
26
+ function prompt(question, defaultVal) {
27
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
28
+ const suffix = defaultVal ? ` (${defaultVal})` : "";
29
+ return new Promise((resolve) => {
30
+ rl.question(` ? ${question}${suffix} `, (answer) => {
31
+ rl.close();
32
+ resolve(answer.trim() || defaultVal || "");
33
+ });
34
+ });
35
+ }
36
+ function pause(message) {
37
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
38
+ return new Promise((resolve) => {
39
+ rl.question(` ${message} `, () => {
40
+ rl.close();
41
+ resolve();
42
+ });
43
+ });
44
+ }
45
+ // ─── GitHub helpers ─────────────────────────────────────────────────────────
46
+ /**
47
+ * Fetch the orgs the user is an active admin of. Uses
48
+ * /user/memberships/orgs which (unlike /user/orgs) tells us our role.
49
+ *
50
+ * Requires the App's "Organization > Members: Read" permission. If the App
51
+ * isn't permitted, this returns an empty array (and we tell the user to
52
+ * check their App permissions).
53
+ */
54
+ async function fetchAdminOrgs(auth) {
55
+ try {
56
+ const memberships = await githubApi("/user/memberships/orgs?state=active&per_page=100", auth);
57
+ return memberships
58
+ .filter((m) => m.role === "admin")
59
+ .map((m) => ({
60
+ login: m.organization.login,
61
+ id: m.organization.id,
62
+ }));
63
+ }
64
+ catch (err) {
65
+ // Permission errors come back as 403/404 — surface as empty list, the
66
+ // caller will guide the user to fix App permissions or create an org.
67
+ return [];
68
+ }
69
+ }
70
+ async function fetchInstallations(auth) {
71
+ const data = await githubApi("/user/installations?per_page=100", auth);
72
+ return data.installations ?? [];
73
+ }
74
+ function findHqInstallation(installations, orgLogin) {
75
+ return (installations.find((i) => i.app_slug === HQ_GITHUB_APP_SLUG &&
76
+ i.account?.login?.toLowerCase() === orgLogin.toLowerCase()) ?? null);
77
+ }
78
+ async function createOrgRepo(auth, orgLogin, repoName, description) {
79
+ return githubApi(`/orgs/${orgLogin}/repos`, auth, {
80
+ method: "POST",
81
+ body: JSON.stringify({
82
+ name: repoName,
83
+ private: true,
84
+ description,
85
+ auto_init: false,
86
+ has_issues: true,
87
+ has_projects: false,
88
+ has_wiki: false,
89
+ }),
90
+ });
91
+ }
92
+ async function getExistingRepo(auth, orgLogin, repoName) {
93
+ try {
94
+ return await githubApi(`/repos/${orgLogin}/${repoName}`, auth);
95
+ }
96
+ catch {
97
+ return null;
98
+ }
99
+ }
100
+ // ─── Git helpers ────────────────────────────────────────────────────────────
101
+ /**
102
+ * Run a git command, embedding the user's GitHub token via a one-shot
103
+ * credential helper so the token never appears in argv or remote URLs.
104
+ *
105
+ * The token is passed via an environment variable to a tiny inline askpass
106
+ * script written to a temp file, which git invokes via GIT_ASKPASS.
107
+ */
108
+ function runGitWithToken(args, cwd, auth, inputEnv = {}) {
109
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "create-hq-git-"));
110
+ const isWindows = process.platform === "win32";
111
+ const askpassPath = path.join(tmpDir, isWindows ? "askpass.cmd" : "askpass.sh");
112
+ try {
113
+ if (isWindows) {
114
+ // Windows batch script: stdout the token (for Password) or username
115
+ fs.writeFileSync(askpassPath, `@echo off\nif "%~1"=="" (echo %GIT_TOKEN%) else (echo %GIT_TOKEN%)\n`, "utf-8");
116
+ }
117
+ else {
118
+ fs.writeFileSync(askpassPath, `#!/bin/sh\necho "$GIT_TOKEN"\n`, "utf-8");
119
+ fs.chmodSync(askpassPath, 0o700);
120
+ }
121
+ execSync(`git -c credential.helper= ${args.join(" ")}`, {
122
+ cwd,
123
+ stdio: "pipe",
124
+ env: {
125
+ ...process.env,
126
+ ...inputEnv,
127
+ GIT_TOKEN: auth.access_token,
128
+ GIT_ASKPASS: askpassPath,
129
+ GIT_TERMINAL_PROMPT: "0",
130
+ // Prevent any system credential helper from caching the token
131
+ GCM_INTERACTIVE: "never",
132
+ },
133
+ });
134
+ }
135
+ finally {
136
+ try {
137
+ fs.rmSync(tmpDir, { recursive: true, force: true });
138
+ }
139
+ catch {
140
+ // ignore
141
+ }
142
+ }
143
+ }
144
+ /**
145
+ * Build an HTTPS URL with the username embedded so git's askpass only
146
+ * needs to provide the password (the token). We use "x-access-token" as
147
+ * the username — GitHub's recommended convention for token auth.
148
+ */
149
+ function tokenAuthUrl(cloneUrl) {
150
+ const u = new URL(cloneUrl);
151
+ u.username = "x-access-token";
152
+ // Don't put the token in the URL — askpass handles it
153
+ return u.toString();
154
+ }
155
+ // ─── Slug helper ────────────────────────────────────────────────────────────
156
+ export function slugify(input) {
157
+ return input
158
+ .toLowerCase()
159
+ .replace(/[^a-z0-9-]+/g, "-")
160
+ .replace(/^-+|-+$/g, "")
161
+ .slice(0, 50) || "team";
162
+ }
163
+ // ─── Main flow ──────────────────────────────────────────────────────────────
164
+ /**
165
+ * Run the admin onboarding flow.
166
+ *
167
+ * @param auth - Authenticated GitHub user
168
+ * @param hqRoot - Local HQ root directory (where companies/ lives)
169
+ * @param hqVersion - HQ template version (for team metadata)
170
+ */
171
+ export async function runAdminOnboarding(auth, hqRoot, hqVersion) {
172
+ console.log();
173
+ console.log(chalk.bold(" Create a new HQ team"));
174
+ console.log();
175
+ // 1. Fetch admin orgs
176
+ const orgsLabel = "Looking up your GitHub organizations";
177
+ stepStatus(orgsLabel, "running");
178
+ let orgs = await fetchAdminOrgs(auth);
179
+ stepStatus(orgsLabel, "done");
180
+ // 2. Pick or create org
181
+ let chosenOrg = null;
182
+ while (!chosenOrg) {
183
+ if (orgs.length === 0) {
184
+ console.log();
185
+ info("You aren't an admin of any GitHub organization yet.");
186
+ info("HQ Teams need a GitHub org to host the shared workspace repo.");
187
+ console.log();
188
+ const create = await prompt("Open browser to create one now? (Y/n)", "y");
189
+ if (!create.toLowerCase().startsWith("y")) {
190
+ warn("Skipping team creation — you can run create-hq again after creating an org.");
191
+ return null;
192
+ }
193
+ openBrowser("https://github.com/organizations/new");
194
+ await pause("Press Enter when you have finished creating the org...");
195
+ stepStatus("Re-checking organizations", "running");
196
+ orgs = await fetchAdminOrgs(auth);
197
+ stepStatus("Re-checking organizations", "done");
198
+ continue;
199
+ }
200
+ console.log();
201
+ console.log(chalk.bold(" Choose an organization:"));
202
+ for (let i = 0; i < orgs.length; i++) {
203
+ console.log(chalk.cyan(` [${i + 1}] `) + chalk.white(orgs[i].login));
204
+ }
205
+ console.log(chalk.cyan(` [${orgs.length + 1}] `) + chalk.dim("Create a new GitHub organization"));
206
+ console.log();
207
+ const answer = await prompt(`Select (1-${orgs.length + 1})`, "1");
208
+ const idx = parseInt(answer, 10) - 1;
209
+ if (idx === orgs.length) {
210
+ // Create new org
211
+ openBrowser("https://github.com/organizations/new");
212
+ await pause("Press Enter when you have finished creating the org...");
213
+ stepStatus("Re-checking organizations", "running");
214
+ orgs = await fetchAdminOrgs(auth);
215
+ stepStatus("Re-checking organizations", "done");
216
+ continue;
217
+ }
218
+ if (idx < 0 || idx >= orgs.length) {
219
+ warn("Invalid selection. Try again.");
220
+ continue;
221
+ }
222
+ chosenOrg = orgs[idx];
223
+ }
224
+ // 3. Verify HQ App is installed on the org
225
+ let installation = null;
226
+ while (!installation) {
227
+ const installLabel = `Checking HQ App on ${chosenOrg.login}`;
228
+ stepStatus(installLabel, "running");
229
+ const installations = await fetchInstallations(auth);
230
+ installation = findHqInstallation(installations, chosenOrg.login);
231
+ if (installation) {
232
+ stepStatus(installLabel, "done");
233
+ break;
234
+ }
235
+ stepStatus(installLabel, "failed");
236
+ console.log();
237
+ info(`The HQ GitHub App isn't installed on ${chalk.cyan(chosenOrg.login)} yet.`);
238
+ info("Installing it gives HQ permission to manage the team workspace repo.");
239
+ console.log();
240
+ const installUrl = `https://github.com/apps/${HQ_GITHUB_APP_SLUG}/installations/new/permissions?target_id=${chosenOrg.id}`;
241
+ const proceed = await prompt("Open the install page in your browser? (Y/n)", "y");
242
+ if (!proceed.toLowerCase().startsWith("y")) {
243
+ warn("HQ App is required to create a team. Aborting team creation.");
244
+ return null;
245
+ }
246
+ openBrowser(installUrl);
247
+ await pause("Press Enter when the App has been installed...");
248
+ }
249
+ // 4. Prompt for team name
250
+ console.log();
251
+ const defaultName = chosenOrg.login;
252
+ const teamName = (await prompt("Team name", defaultName)) || defaultName;
253
+ const teamSlug = slugify(teamName);
254
+ const teamId = crypto.randomUUID();
255
+ const meta = {
256
+ team_id: teamId,
257
+ team_name: teamName,
258
+ team_slug: teamSlug,
259
+ org_login: chosenOrg.login,
260
+ org_id: chosenOrg.id,
261
+ created_by: auth.login,
262
+ created_at: new Date().toISOString(),
263
+ hq_version: hqVersion,
264
+ };
265
+ // 5. Create the {org}/hq-{teamSlug} repo
266
+ const repoName = `hq-${teamSlug}`;
267
+ const repoLabel = `Creating ${chosenOrg.login}/${repoName} private repo`;
268
+ stepStatus(repoLabel, "running");
269
+ let repo = null;
270
+ try {
271
+ repo = await createOrgRepo(auth, chosenOrg.login, repoName, `HQ Teams workspace for ${teamName}`);
272
+ stepStatus(repoLabel, "done");
273
+ }
274
+ catch (err) {
275
+ const message = err instanceof Error ? err.message : String(err);
276
+ if (message.includes("422") && /already exists/i.test(message)) {
277
+ // Repo already exists — could be from a prior run. Confirm before reusing.
278
+ stepStatus(repoLabel, "done");
279
+ console.log();
280
+ info(`${chosenOrg.login}/${repoName} already exists.`);
281
+ const reuse = await prompt("Reuse this repo? (Y/n)", "y");
282
+ if (!reuse.toLowerCase().startsWith("y")) {
283
+ warn("Aborting — choose a different team name next time to avoid the conflict.");
284
+ return null;
285
+ }
286
+ repo = await getExistingRepo(auth, chosenOrg.login, repoName);
287
+ if (!repo) {
288
+ stepStatus(repoLabel, "failed");
289
+ warn(`Could not load existing ${chosenOrg.login}/${repoName}: ${message}`);
290
+ return null;
291
+ }
292
+ }
293
+ else {
294
+ stepStatus(repoLabel, "failed");
295
+ warn(`Could not create repo: ${message}`);
296
+ return null;
297
+ }
298
+ }
299
+ // 6. Seed locally and push
300
+ const seedLabel = "Seeding team workspace";
301
+ stepStatus(seedLabel, "running");
302
+ const seedDir = fs.mkdtempSync(path.join(os.tmpdir(), "create-hq-seed-"));
303
+ try {
304
+ // git init in seed dir
305
+ execSync(`git init -b main`, { cwd: seedDir, stdio: "pipe" });
306
+ execSync(`git config user.email "${auth.email || `${auth.login}@users.noreply.github.com`}"`, {
307
+ cwd: seedDir,
308
+ stdio: "pipe",
309
+ });
310
+ execSync(`git config user.name "${auth.name || auth.login}"`, {
311
+ cwd: seedDir,
312
+ stdio: "pipe",
313
+ });
314
+ writeCompanyTemplate(seedDir, meta);
315
+ execSync(`git add -A`, { cwd: seedDir, stdio: "pipe" });
316
+ execSync(`git commit -m "chore: bootstrap HQ team workspace"`, { cwd: seedDir, stdio: "pipe" });
317
+ const remoteUrl = tokenAuthUrl(repo.clone_url);
318
+ execSync(`git remote add origin "${remoteUrl}"`, { cwd: seedDir, stdio: "pipe" });
319
+ runGitWithToken(["push", "-u", "origin", "main"], seedDir, auth);
320
+ stepStatus(seedLabel, "done");
321
+ }
322
+ catch (err) {
323
+ stepStatus(seedLabel, "failed");
324
+ const message = err instanceof Error ? err.message : String(err);
325
+ warn(`Failed to seed team repo: ${message}`);
326
+ return null;
327
+ }
328
+ finally {
329
+ try {
330
+ fs.rmSync(seedDir, { recursive: true, force: true });
331
+ }
332
+ catch {
333
+ // ignore
334
+ }
335
+ }
336
+ // 7. Clone into companies/{slug}/
337
+ const companiesDir = path.join(hqRoot, "companies");
338
+ if (!fs.existsSync(companiesDir)) {
339
+ fs.mkdirSync(companiesDir, { recursive: true });
340
+ }
341
+ const companyDir = path.join(companiesDir, teamSlug);
342
+ if (fs.existsSync(companyDir) && fs.readdirSync(companyDir).length > 0) {
343
+ warn(`companies/${teamSlug}/ already exists and is not empty — skipping clone.`);
344
+ }
345
+ else {
346
+ const cloneLabel = `Cloning into companies/${teamSlug}`;
347
+ stepStatus(cloneLabel, "running");
348
+ try {
349
+ const remoteUrl = tokenAuthUrl(repo.clone_url);
350
+ runGitWithToken(["clone", `"${remoteUrl}"`, `"${companyDir}"`], companiesDir, auth);
351
+ // Strip token from the stored remote URL
352
+ execSync(`git remote set-url origin "${repo.clone_url}"`, {
353
+ cwd: companyDir,
354
+ stdio: "pipe",
355
+ });
356
+ stepStatus(cloneLabel, "done");
357
+ }
358
+ catch (err) {
359
+ stepStatus(cloneLabel, "failed");
360
+ const message = err instanceof Error ? err.message : String(err);
361
+ warn(`Could not clone into companies/${teamSlug}/: ${message}`);
362
+ // Team repo was created on GitHub — still return success so the user
363
+ // gets the admin orientation (with repo URL) instead of generic next steps.
364
+ // They can clone manually later.
365
+ console.log();
366
+ success(`Team "${teamName}" created at ${repo.html_url}`);
367
+ info("Local clone failed — clone manually with:");
368
+ info(` git clone ${repo.clone_url} companies/${teamSlug}`);
369
+ // Still offer invite generation
370
+ await inviteLoop(auth, meta, repo.clone_url);
371
+ return {
372
+ team: meta,
373
+ companyDir,
374
+ repoHtmlUrl: repo.html_url,
375
+ };
376
+ }
377
+ }
378
+ console.log();
379
+ success(`Team "${teamName}" created — ${repo.html_url}`);
380
+ // 8. Offer to generate member invites
381
+ await inviteLoop(auth, meta, repo.clone_url);
382
+ return {
383
+ team: meta,
384
+ companyDir,
385
+ repoHtmlUrl: repo.html_url,
386
+ };
387
+ }
388
+ // ─── Invite generation (used by admin onboarding + standalone) ──────────────
389
+ /**
390
+ * Interactive invite generation for a single member. Prompts for email,
391
+ * sends org invite, generates token, and prints instructions.
392
+ */
393
+ export async function generateInviteInteractive(auth, meta, cloneUrl) {
394
+ const payload = {
395
+ org: meta.org_login,
396
+ repo: `hq-${meta.team_slug}`,
397
+ slug: meta.team_slug,
398
+ teamName: meta.team_name,
399
+ cloneUrl,
400
+ invitedBy: auth.login,
401
+ };
402
+ const token = encodeInviteToken(payload);
403
+ // Ask for email — used for the mailto invite, not for API calls
404
+ const email = await prompt("New member's email (or press Enter to skip)");
405
+ printInviteSummary(payload, token, false, email || undefined);
406
+ // Copy invite message to clipboard
407
+ const msg = formatInviteMessage(payload, token, email || undefined);
408
+ const copied = copyToClipboard(msg);
409
+ // Try to open mailto: with pre-populated email (works well on macOS/first use)
410
+ if (email) {
411
+ openInviteEmail(payload, token, email);
412
+ }
413
+ // Always show clipboard status — mailto: is unreliable on Windows after first use
414
+ if (copied) {
415
+ success("Invite message copied to clipboard — if your email client didn't open, just paste into a new email and send.");
416
+ }
417
+ else if (!email) {
418
+ info("No email provided — share the invite message above via email, Slack, or text.");
419
+ }
420
+ // Send the GitHub org invite via API (required for the member to accept)
421
+ if (email) {
422
+ const result = await sendOrgInviteByEmail(auth, meta.org_login, email);
423
+ if (result.ok) {
424
+ success(`GitHub org invite sent to ${email}`);
425
+ }
426
+ else {
427
+ warn(`Could not send org invite automatically: ${result.error}`);
428
+ console.log();
429
+ info(`Send the invite manually (required for access):`);
430
+ info(` https://github.com/orgs/${meta.org_login}/people`);
431
+ info(` Click "Invite member" and enter: ${email}`);
432
+ }
433
+ }
434
+ else {
435
+ console.log();
436
+ info(`Send them a GitHub org invite (required for access):`);
437
+ info(` https://github.com/orgs/${meta.org_login}/people`);
438
+ info(` Click "Invite member" and enter their email or GitHub username`);
439
+ }
440
+ }
441
+ /**
442
+ * Invite loop — asks "Invite a team member?" and repeats until the admin
443
+ * says no. Used after team creation and from the standalone invite command.
444
+ */
445
+ export async function inviteLoop(auth, meta, cloneUrl) {
446
+ let first = true;
447
+ while (true) {
448
+ console.log();
449
+ const question = first
450
+ ? "Invite a team member now? (Y/n)"
451
+ : "Invite another team member? (y/N)";
452
+ const defaultAnswer = first ? "y" : "n";
453
+ const answer = await prompt(question, defaultAnswer);
454
+ if (!answer.toLowerCase().startsWith("y"))
455
+ break;
456
+ await generateInviteInteractive(auth, meta, cloneUrl);
457
+ first = false;
458
+ }
459
+ }
460
+ //# sourceMappingURL=admin-onboarding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-onboarding.js","sourceRoot":"","sources":["../src/admin-onboarding.ts"],"names":[],"mappings":"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"}
package/dist/art.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Raw banner lines without ANSI codes — testable.
3
+ */
4
+ export declare function bannerLines(): string[];
5
+ /**
6
+ * Raw compact banner lines without ANSI codes — testable.
7
+ */
8
+ export declare function compactBannerLines(): string[];
9
+ /**
10
+ * Full-width ASCII art banner (80 cols) — retro office building + INDIGO HQ
11
+ */
12
+ export declare function banner(): void;
13
+ /**
14
+ * Compact banner for narrow terminals (< 80 cols)
15
+ */
16
+ export declare function compactBanner(): void;
17
+ //# sourceMappingURL=art.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"art.d.ts","sourceRoot":"","sources":["../src/art.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,EAAE,CAuCtC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CA4B7C;AAED;;GAEG;AACH,wBAAgB,MAAM,IAAI,IAAI,CAkD7B;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAuCpC"}