create-egregore 0.14.0 → 0.14.2

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 (3) hide show
  1. package/lib/auth.js +5 -14
  2. package/lib/local.js +29 -10
  3. package/package.json +1 -1
package/lib/auth.js CHANGED
@@ -5,9 +5,7 @@
5
5
 
6
6
  const https = require("node:https");
7
7
 
8
- const GITHUB_APP_CLIENT_ID = "Iv23li2obNsAjakoK2RE"; // GitHub App — for founder flow
9
- const OAUTH_APP_CLIENT_ID = "Ov23liYZjJbbbNgnJ9vH"; // OAuth App — for join flow
10
- const OAUTH_JOIN_SCOPE = "repo"; // Minimal scope for cross-account access
8
+ const CLIENT_ID = "Iv23li2obNsAjakoK2RE"; // GitHub App — clean consent, permissions via installation
11
9
 
12
10
  function post(url, body) {
13
11
  return new Promise((resolve, reject) => {
@@ -74,19 +72,12 @@ function copyToClipboard(text) {
74
72
  /**
75
73
  * Run GitHub Device Flow.
76
74
  * Returns the access token string, or throws on failure.
77
- * @param {object} ui - UI module for output
78
- * @param {object} [opts] - Options
79
- * @param {string} [opts.mode] - "join" uses OAuth App with repo scope; default uses GitHub App
80
75
  */
81
- async function deviceFlow(ui, opts = {}) {
82
- const isJoin = opts.mode === "join";
83
- const clientId = isJoin ? OAUTH_APP_CLIENT_ID : GITHUB_APP_CLIENT_ID;
84
- const scope = isJoin ? OAUTH_JOIN_SCOPE : "";
85
-
76
+ async function deviceFlow(ui) {
86
77
  // 1. Request device code
87
78
  const codeResp = await post("https://github.com/login/device/code", {
88
- client_id: clientId,
89
- scope,
79
+ client_id: CLIENT_ID,
80
+ scope: "",
90
81
  });
91
82
 
92
83
  if (!codeResp.device_code) {
@@ -120,7 +111,7 @@ async function deviceFlow(ui, opts = {}) {
120
111
  await sleep(interval);
121
112
 
122
113
  const tokenResp = await post("https://github.com/login/oauth/access_token", {
123
- client_id: clientId,
114
+ client_id: CLIENT_ID,
124
115
  device_code,
125
116
  grant_type: "urn:ietf:params:oauth:grant-type:device_code",
126
117
  });
package/lib/local.js CHANGED
@@ -568,11 +568,18 @@ async function localJoinFlow(orgArg, ui) {
568
568
  explicitRepo = null;
569
569
  }
570
570
 
571
- // 1. GitHub auth — OAuth App with repo scope for cross-account access
571
+ // 1. Install GitHub App — needed for the token to access repository resources
572
572
  ui.info(`Joining ${ui.bold(orgLogin)}. First, sign in with GitHub.\n`);
573
+ ui.info("Install the Egregore app on your GitHub account.");
574
+ ui.info("This lets Egregore access the repos you've been invited to.\n");
575
+ openBrowser(APP_INSTALL_URL);
576
+ await ui.prompt("Press Enter when done...");
577
+
578
+ // 2. GitHub auth (auto-approved after App install)
579
+ ui.info("");
573
580
  let githubToken;
574
581
  try {
575
- githubToken = await deviceFlow(ui, { mode: "join" });
582
+ githubToken = await deviceFlow(ui);
576
583
  ui.success("Authenticated with GitHub");
577
584
  } catch (err) {
578
585
  ui.error(`GitHub auth failed: ${err.message}`);
@@ -637,17 +644,29 @@ async function localJoinFlow(orgArg, ui) {
637
644
  : `${orgLogin}-memory`;
638
645
  const managedRepos = config.repos || [];
639
646
 
640
- // 5b. Check access to memory repo (required) — may need invitation acceptance
641
- if (!(await repoExists(githubToken, orgLogin, memoryRepoName))) {
647
+ // 5b. Check access to ALL repos — open browser for any that need invitation acceptance
648
+ const allRepos = [repoName, memoryRepoName, ...managedRepos];
649
+ const inaccessible = [];
650
+ for (const repo of allRepos) {
651
+ if (!(await repoExists(githubToken, orgLogin, repo))) {
652
+ inaccessible.push(repo);
653
+ }
654
+ }
655
+ if (inaccessible.length > 0) {
642
656
  console.log("");
643
- ui.info("Accept the memory repo invitation in your browser.");
644
- openBrowser(`https://github.com/${orgLogin}/${memoryRepoName}`);
657
+ ui.info(`Accept ${inaccessible.length === 1 ? "the invitation" : `${inaccessible.length} invitations`} in your browser.`);
658
+ for (const repo of inaccessible) {
659
+ openBrowser(`https://github.com/${orgLogin}/${repo}`);
660
+ }
645
661
  await ui.prompt("Press Enter after accepting...");
646
662
 
647
- if (!(await repoExists(githubToken, orgLogin, memoryRepoName))) {
648
- ui.error(`Still can't access ${orgLogin}/${memoryRepoName}`);
649
- ui.error("Make sure the org admin has invited you to the memory repo.");
650
- process.exit(1);
663
+ // Retry — only block on main + memory, managed repos are best-effort
664
+ for (const repo of [repoName, memoryRepoName]) {
665
+ if (inaccessible.includes(repo) && !(await repoExists(githubToken, orgLogin, repo))) {
666
+ ui.error(`Still can't access ${orgLogin}/${repo}`);
667
+ ui.error("Make sure the org admin has set up Egregore and invited you.");
668
+ process.exit(1);
669
+ }
651
670
  }
652
671
  ui.success("Access confirmed");
653
672
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-egregore",
3
- "version": "0.14.0",
3
+ "version": "0.14.2",
4
4
  "description": "Set up Egregore for your team in one command",
5
5
  "license": "MIT",
6
6
  "bin": {