create-egregore 0.7.0 → 0.8.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/lib/local.js CHANGED
@@ -197,7 +197,7 @@ async function localFounderFlow(ui) {
197
197
  for (const o of orgs) {
198
198
  orgChoices.push({ label: o.login, description: "Organization" });
199
199
  }
200
- const orgChoice = await ui.choose("Where do you want to set up Egregore?", orgChoices);
200
+ const orgChoice = await ui.choose("Where do you want to set up Egregore?", orgChoices, "Don't see your org? Grant access on the GitHub authorization page and re-run.");
201
201
  githubOrg = orgChoice.label;
202
202
  isOrg = githubOrg !== user.login;
203
203
  }
@@ -346,6 +346,7 @@ async function localFounderFlow(ui) {
346
346
 
347
347
  // 8. Write egregore.json to remote repo (so joiners can read it)
348
348
  const egreConfig = {
349
+ mode: "local",
349
350
  org_name: orgName,
350
351
  github_org: githubOrg,
351
352
  memory_repo: `https://github.com/${githubOrg}/${memoryRepoName}.git`,
@@ -491,46 +492,43 @@ async function localFounderFlow(ui) {
491
492
 
492
493
  // 19. Optional invite
493
494
  console.log("");
494
- const inviteAnswer = await ui.prompt("Know someone who'd find this useful? [y/N]:");
495
- if (inviteAnswer && inviteAnswer.toLowerCase() === "y") {
496
- const invUsername = await ui.prompt("GitHub username:");
497
- if (invUsername) {
498
- const invSpin = ui.spinner(`Inviting ${invUsername}...`);
499
- try {
500
- // Add as collaborator to all repos
501
- await addCollaborator(githubToken, githubOrg, repoName, invUsername);
502
- await addCollaborator(githubToken, githubOrg, memoryRepoName, invUsername);
503
- for (const mr of selectedRepos) {
504
- await addCollaborator(githubToken, githubOrg, mr, invUsername).catch(() => {});
505
- }
506
-
507
- // Create person file
508
- const invPersonContent = [
509
- "---",
510
- `name: ${invUsername}`,
511
- `github: ${invUsername}`,
512
- `invited_by: ${user.login}`,
513
- `joined: ${today}`,
514
- "---",
515
- "",
516
- ].join("\n");
517
- const invPersonFile = path.join(memoryDir, "people", `${invUsername}.md`);
518
- if (!fs.existsSync(invPersonFile)) {
519
- fs.writeFileSync(invPersonFile, invPersonContent);
520
- try {
521
- run("git add -A", { cwd: memoryDir });
522
- run(`git commit -m "Invite ${invUsername}"`, { cwd: memoryDir });
523
- run("git push", { cwd: memoryDir });
524
- } catch {}
525
- }
495
+ const invUsername = await ui.prompt("Invite a teammate? Enter their GitHub username (or press Enter to skip):");
496
+ if (invUsername) {
497
+ const invSpin = ui.spinner(`Inviting ${invUsername}...`);
498
+ try {
499
+ // Add as collaborator to all repos
500
+ await addCollaborator(githubToken, githubOrg, repoName, invUsername);
501
+ await addCollaborator(githubToken, githubOrg, memoryRepoName, invUsername);
502
+ for (const mr of selectedRepos) {
503
+ await addCollaborator(githubToken, githubOrg, mr, invUsername).catch(() => {});
504
+ }
526
505
 
527
- invSpin.stop(`Invited ${invUsername}`);
528
- console.log("");
529
- ui.info(`Tell them to run:`);
530
- ui.info(` ${ui.bold(`npx create-egregore join ${githubOrg}/${repoName}`)}`);
531
- } catch (err) {
532
- invSpin.fail(`Could not invite ${invUsername}: ${err.message}`);
506
+ // Create person file
507
+ const invPersonContent = [
508
+ "---",
509
+ `name: ${invUsername}`,
510
+ `github: ${invUsername}`,
511
+ `invited_by: ${user.login}`,
512
+ `joined: ${today}`,
513
+ "---",
514
+ "",
515
+ ].join("\n");
516
+ const invPersonFile = path.join(memoryDir, "people", `${invUsername}.md`);
517
+ if (!fs.existsSync(invPersonFile)) {
518
+ fs.writeFileSync(invPersonFile, invPersonContent);
519
+ try {
520
+ run("git add -A", { cwd: memoryDir });
521
+ run(`git commit -m "Invite ${invUsername}"`, { cwd: memoryDir });
522
+ run("git push", { cwd: memoryDir });
523
+ } catch {}
533
524
  }
525
+
526
+ invSpin.stop(`Invited ${invUsername}`);
527
+ console.log("");
528
+ ui.info(`Tell them to run:`);
529
+ ui.commandBox("command", `npx create-egregore@latest join ${githubOrg}/${repoName}`);
530
+ } catch (err) {
531
+ invSpin.fail(`Could not invite ${invUsername}: ${err.message}`);
534
532
  }
535
533
  }
536
534
 
package/lib/setup.js CHANGED
@@ -212,6 +212,18 @@ async function install(data, ui, targetDir) {
212
212
  }
213
213
  fs.writeFileSync(statePath, JSON.stringify(state, null, 2) + "\n");
214
214
 
215
+ // 4c. Ensure mode is set in egregore.json (connected mode for API-based setup)
216
+ const configPath = path.join(egregoreDir, "egregore.json");
217
+ if (fs.existsSync(configPath)) {
218
+ try {
219
+ const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
220
+ if (!config.mode) {
221
+ config.mode = "connected";
222
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
223
+ }
224
+ } catch {}
225
+ }
226
+
215
227
  // 5. Register instance + shell alias
216
228
  ui.step(5, totalSteps, "Registering instance...");
217
229
  registerInstance(forkDirName, org_name, egregoreDir);
@@ -357,7 +369,7 @@ async function installShellAlias(egregoreDir, ui) {
357
369
  if (fs.existsSync(configPath)) {
358
370
  try { slug = JSON.parse(fs.readFileSync(configPath, "utf-8")).slug || ""; } catch {}
359
371
  }
360
- defaultName = slug ? `egregore-${slug}` : "egregore-2";
372
+ defaultName = slug || "egregore-2";
361
373
  }
362
374
 
363
375
  // Ask user (skip prompt in non-interactive mode)
package/lib/ui.js CHANGED
@@ -69,11 +69,11 @@ function spinner(msg) {
69
69
  return {
70
70
  stop(result) {
71
71
  clearInterval(interval);
72
- process.stdout.write(`\r ${GREEN}✓${RESET} ${result || msg}\n`);
72
+ process.stdout.write(`\r\x1b[2K ${GREEN}✓${RESET} ${result || msg}\n`);
73
73
  },
74
74
  fail(result) {
75
75
  clearInterval(interval);
76
- process.stdout.write(`\r ${RED}✗${RESET} ${result || msg}\n`);
76
+ process.stdout.write(`\r\x1b[2K ${RED}✗${RESET} ${result || msg}\n`);
77
77
  },
78
78
  };
79
79
  }
@@ -93,12 +93,13 @@ function prompt(question) {
93
93
  }
94
94
 
95
95
  // Prompt with numbered choices
96
- async function choose(question, options) {
96
+ async function choose(question, options, hint) {
97
97
  console.log(`\n ${question}\n`);
98
98
  for (let i = 0; i < options.length; i++) {
99
99
  const { label, description } = options[i];
100
100
  console.log(` ${BOLD}${i + 1}.${RESET} ${label}${description ? ` ${DIM}— ${description}${RESET}` : ""}`);
101
101
  }
102
+ if (hint) console.log(`\n ${DIM}${hint}${RESET}`);
102
103
  console.log();
103
104
 
104
105
  while (true) {
@@ -137,7 +138,21 @@ async function multiSelect(question, options) {
137
138
  return selected;
138
139
  }
139
140
 
141
+ function commandBox(label, cmd) {
142
+ const inner = ` ${cmd} `;
143
+ const width = Math.max(inner.length, label.length + 5);
144
+ const pad = (s) => s + " ".repeat(Math.max(0, width - s.length));
145
+ const top = `┌─ ${label} ${"─".repeat(Math.max(0, width - label.length - 4))}┐`;
146
+ const blank = `│${" ".repeat(width)}│`;
147
+ const bot = `└${"─".repeat(width)}┘`;
148
+ console.log(`\n ${DIM}${top}${RESET}`);
149
+ console.log(` ${DIM}${blank}${RESET}`);
150
+ console.log(` ${DIM}│${RESET}${BOLD}${pad(inner)}${RESET}${DIM}│${RESET}`);
151
+ console.log(` ${DIM}${blank}${RESET}`);
152
+ console.log(` ${DIM}${bot}${RESET}\n`);
153
+ }
154
+
140
155
  module.exports = {
141
156
  banner, info, success, warn, error, step, dim, bold, cyan,
142
- spinner, prompt, choose, multiSelect,
157
+ spinner, prompt, choose, multiSelect, commandBox,
143
158
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-egregore",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Set up Egregore for your team in one command",
5
5
  "license": "MIT",
6
6
  "bin": {