hikoutei 0.5.17 → 0.5.18

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 CHANGED
@@ -125,15 +125,18 @@ an operation for each write. The sync runtime uses one Google Sheets API
125
125
  provider (the internal `googleSheetsApi` bootstrap option) with a service
126
126
  account — no Apps Script deployment.
127
127
 
128
- **Fastest path:** install the gcloud CLI and log in once with Drive access
129
- (`gcloud auth login --enable-gdrive-access`), then `npx hikoutei setup` it
130
- creates the project, service account, and key, creates a spreadsheet owned
131
- by your account, shares it with the service account as an Editor, verifies
132
- service-account access, and writes `GOOGLE_APPLICATION_CREDENTIALS` plus
133
- `HIKOUTEI_SYNC_SPREADSHEET_URL` into your `.env`. The human access token is
134
- used in memory only and never stored. Automatic setup runs on macOS and
135
- Linux; on Windows a non-dry-run is refused before any mutation and manual
136
- setup is available. Interrupted runs resume from a local checkpoint
128
+ **Fastest path:** install the gcloud CLI, then run `npx hikoutei setup` from your
129
+ project directory. On an interactive terminal it offers (press Enter) to
130
+ start `gcloud auth login --enable-gdrive-access --force` for you when the
131
+ active account is missing or lacks Drive access you only complete the
132
+ browser approval yourself. (In `--yes`, CI, or non-TTY sessions, run that
133
+ login command yourself first.) Setup then creates the project, service
134
+ account, and key, creates a spreadsheet owned by your account, shares it
135
+ with the service account as an Editor, verifies service-account access, and
136
+ writes `GOOGLE_APPLICATION_CREDENTIALS` plus `HIKOUTEI_SYNC_SPREADSHEET_URL`
137
+ into your `.env`. The human access token is used in memory only and never
138
+ stored. Automatic setup runs on macOS and Linux; on Windows a non-dry-run
139
+ is refused before any mutation and manual setup is available. Interrupted runs resume from a local checkpoint
137
140
  (`.hikoutei-setup-state.json`); a spreadsheet create whose outcome is
138
141
  unknown is reconciled by its creation marker on the next run and setup
139
142
  never creates a second spreadsheet (inspect Drive and rerun if setup
@@ -1 +1 @@
1
- {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAmC,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAEjF,kEAAkE;AAClE,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAE7C,iFAAiF;AACjF,eAAO,MAAM,wBAAwB,SAAS,CAAC;AAE/C,mEAAmE;AACnE,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,+CAA+C;IAC/C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,iFAAiF;IACjF,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,4DAA4D;IAC5D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,qCAAqC;IACrC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,qEAAqE;IACrE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED,gDAAgD;AAChD,MAAM,MAAM,oBAAoB,GAC5B;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GAC5D;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAA;CAAE,CAAC;AAanE,eAAO,MAAM,eAAe,QAkEhB,CAAC;AAUb;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,oBAAoB,CAyG5E"}
1
+ {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAmC,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAEjF,kEAAkE;AAClE,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAE7C,iFAAiF;AACjF,eAAO,MAAM,wBAAwB,SAAS,CAAC;AAE/C,mEAAmE;AACnE,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,+CAA+C;IAC/C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,iFAAiF;IACjF,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,4DAA4D;IAC5D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,qCAAqC;IACrC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,qEAAqE;IACrE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED,gDAAgD;AAChD,MAAM,MAAM,oBAAoB,GAC5B;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GAC5D;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAA;CAAE,CAAC;AAanE,eAAO,MAAM,eAAe,QAyEhB,CAAC;AAUb;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,oBAAoB,CAyG5E"}
package/dist/cli/args.js CHANGED
@@ -25,10 +25,14 @@ export const SETUP_HELP_TEXT = [
25
25
  "hikoutei setup - bootstrap a Google Cloud project, service account, key, and",
26
26
  "a human-owned spreadsheet for Hikoutei sync, then write a ready-to-use .env file.",
27
27
  "",
28
- "Prerequisites: the gcloud CLI is installed and `gcloud auth login",
29
- "--enable-gdrive-access` has been run once. Setup creates the spreadsheet as",
30
- "the logged-in user and shares it with the service account as a writer, so the",
31
- "active account must grant Drive access.",
28
+ "Prerequisites: the gcloud CLI is installed. On an interactive terminal,",
29
+ "`npx hikoutei setup` offers to start `gcloud auth login",
30
+ "--enable-gdrive-access --force` for you (press Enter) when the active",
31
+ "account is missing or lacks Drive access; you complete the browser",
32
+ "approval. In --yes / CI / non-TTY sessions, run that login command",
33
+ "yourself first. Setup creates the spreadsheet as the logged-in user",
34
+ "and shares it with the service account as a writer, so the active",
35
+ "account must grant Drive access.",
32
36
  "",
33
37
  "Usage:",
34
38
  " hikoutei setup [options]",
@@ -43,13 +47,16 @@ export const SETUP_HELP_TEXT = [
43
47
  " --output <path> .env file to write or update (default: .env in",
44
48
  " the current directory).",
45
49
  " --yes Skip interactive confirmation (non-interactive",
46
- " mode).",
50
+ " mode). Also disables the Enter-to-login",
51
+ " handoff: log in with `gcloud auth login",
52
+ " --enable-gdrive-access --force` first.",
47
53
  " --dry-run Print the exact command sequence and",
48
54
  " simulated outcomes without executing anything",
49
55
  " (read-only local path-safety checks only;",
50
56
  " no subprocess, network, cloud, or file",
51
- " mutations; the gcloud key create shows the",
52
- " private staging placeholder",
57
+ " mutations; never runs the interactive",
58
+ " gcloud login handoff; the gcloud key create",
59
+ " shows the private staging placeholder",
53
60
  " <private-key-staging-dir>/key.json — never the",
54
61
  " final key path).",
55
62
  " -h, --help Show this help and exit.",
@@ -1 +1 @@
1
- {"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,12 @@
5
5
  * y/N confirmation before running unless `--yes` (non-interactive mode) or
6
6
  * `--dry-run` is given. The input and output sinks are injected so tests can
7
7
  * exercise the prompt without a TTY.
8
+ *
9
+ * The separate {@link promptLoginHandoff} prompt offers an Enter-to-start
10
+ * handoff into `gcloud auth login`: when the preflight detects a missing or
11
+ * Drive-less account on a real terminal, Enter launches the browser login in
12
+ * the inherited terminal, while any other input or end-of-input cancels and
13
+ * leaves setup for a later run.
8
14
  */
9
15
  export interface ConfirmSetupOptions {
10
16
  readonly yes: boolean;
@@ -20,6 +26,31 @@ export type ConfirmSetupResult = {
20
26
  } | {
21
27
  readonly status: "declined";
22
28
  };
29
+ /** Input and output sinks for the Enter-to-login handoff prompt. */
30
+ export interface PromptLoginHandoffOptions {
31
+ /** Line/chunk source; `process.stdin` in the real CLI. */
32
+ readonly input: AsyncIterable<string>;
33
+ readonly output: {
34
+ readonly write: (text: string) => void;
35
+ };
36
+ }
37
+ /** Result of the Enter-to-login handoff prompt. */
38
+ export type PromptLoginHandoffResult = {
39
+ readonly status: "proceed";
40
+ } | {
41
+ readonly status: "cancel";
42
+ };
43
+ /**
44
+ * Prompts once for the Enter-to-login handoff.
45
+ *
46
+ * Reads a single input chunk: an empty line (Enter) or whitespace-only input
47
+ * proceeds with the gcloud login; any other input or end-of-input cancels.
48
+ * Buffers are decoded as UTF-8 so the function works with both string and
49
+ * Buffer stdin streams. This prompt is intentionally separate from the
50
+ * resource-creation {@link confirmSetup} prompt and never runs for `--yes`,
51
+ * `--dry-run`, or non-TTY sessions.
52
+ */
53
+ export declare function promptLoginHandoff(options: PromptLoginHandoffOptions): Promise<PromptLoginHandoffResult>;
23
54
  /**
24
55
  * Asks for confirmation unless `--yes` or `--dry-run` was given.
25
56
  *
@@ -1 +1 @@
1
- {"version":3,"file":"confirm.d.ts","sourceRoot":"","sources":["../../src/cli/confirm.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,0DAA0D;IAC1D,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;CAC7D;AAED,MAAM,MAAM,kBAAkB,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAA;CAAE,CAAC;AAKpG;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAW5F"}
1
+ {"version":3,"file":"confirm.d.ts","sourceRoot":"","sources":["../../src/cli/confirm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,0DAA0D;IAC1D,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;CAC7D;AAED,MAAM,MAAM,kBAAkB,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAA;CAAE,CAAC;AAEpG,oEAAoE;AACpE,MAAM,WAAW,yBAAyB;IACxC,0DAA0D;IAC1D,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;CAC7D;AAED,mDAAmD;AACnD,MAAM,MAAM,wBAAwB,GAChC;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAA;CAAE,GAC9B;IAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAA;CAAE,CAAC;AAkClC;;;;;;;;;GASG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,wBAAwB,CAAC,CAOnC;AAKD;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAW5F"}
@@ -5,7 +5,60 @@
5
5
  * y/N confirmation before running unless `--yes` (non-interactive mode) or
6
6
  * `--dry-run` is given. The input and output sinks are injected so tests can
7
7
  * exercise the prompt without a TTY.
8
+ *
9
+ * The separate {@link promptLoginHandoff} prompt offers an Enter-to-start
10
+ * handoff into `gcloud auth login`: when the preflight detects a missing or
11
+ * Drive-less account on a real terminal, Enter launches the browser login in
12
+ * the inherited terminal, while any other input or end-of-input cancels and
13
+ * leaves setup for a later run.
14
+ */
15
+ /**
16
+ * Reads exactly one input chunk from a shared async iterable WITHOUT closing
17
+ * or aborting it.
18
+ *
19
+ * A `for await (... of input) { ... return; }` loop calls the iterator's
20
+ * `return()` on early completion. For a Node Readable such as `process.stdin`,
21
+ * `return()` destroys the stream, so the very next read raises `ABORT_ERR`.
22
+ * Setup asks two sequential prompts (the y/N confirmation, then the
23
+ * Enter-to-login handoff) over the SAME shared stdin, so each prompt must
24
+ * consume exactly one chunk and leave the stream open for the next one.
25
+ *
26
+ * This helper acquires the shared iterator — `process.stdin` is its own
27
+ * self-iterator, so re-acquiring it on the next prompt continues right after
28
+ * the last read — and calls `next()` once. It deliberately never calls
29
+ * `return()`, which is the one difference that keeps a later prompt working.
30
+ */
31
+ async function readOneInputChunk(input) {
32
+ const iterator = input[Symbol.asyncIterator]();
33
+ const result = await iterator.next();
34
+ if (result.done === true || result.value === undefined) {
35
+ return null;
36
+ }
37
+ const value = result.value;
38
+ return typeof value === "string" ? value : String(value);
39
+ }
40
+ const LOGIN_HANDOFF_PROMPT = "The active gcloud account is missing or lacks Drive access. Press Enter to " +
41
+ "start `gcloud auth login --enable-gdrive-access --force` in this terminal (a " +
42
+ "browser window opens for you to approve); press any other key or Ctrl-D to " +
43
+ "cancel and finish setup later. ";
44
+ /**
45
+ * Prompts once for the Enter-to-login handoff.
46
+ *
47
+ * Reads a single input chunk: an empty line (Enter) or whitespace-only input
48
+ * proceeds with the gcloud login; any other input or end-of-input cancels.
49
+ * Buffers are decoded as UTF-8 so the function works with both string and
50
+ * Buffer stdin streams. This prompt is intentionally separate from the
51
+ * resource-creation {@link confirmSetup} prompt and never runs for `--yes`,
52
+ * `--dry-run`, or non-TTY sessions.
8
53
  */
54
+ export async function promptLoginHandoff(options) {
55
+ options.output.write(LOGIN_HANDOFF_PROMPT);
56
+ const chunk = await readOneInputChunk(options.input);
57
+ if (chunk === null) {
58
+ return { status: "cancel" };
59
+ }
60
+ return chunk.trim() === "" ? { status: "proceed" } : { status: "cancel" };
61
+ }
9
62
  const CONFIRMATION_PROMPT = "This will create Google Cloud resources (project, service account, key, spreadsheet). Continue? [y/N] ";
10
63
  /**
11
64
  * Asks for confirmation unless `--yes` or `--dry-run` was given.
@@ -19,11 +72,11 @@ export async function confirmSetup(options) {
19
72
  return { status: "confirmed" };
20
73
  }
21
74
  options.output.write(CONFIRMATION_PROMPT);
22
- for await (const chunk of options.input) {
23
- const text = typeof chunk === "string" ? chunk : String(chunk);
24
- const answer = text.trim().toLowerCase();
25
- return answer === "y" || answer === "yes" ? { status: "confirmed" } : { status: "declined" };
75
+ const chunk = await readOneInputChunk(options.input);
76
+ if (chunk === null) {
77
+ return { status: "declined" };
26
78
  }
27
- return { status: "declined" };
79
+ const answer = chunk.trim().toLowerCase();
80
+ return answer === "y" || answer === "yes" ? { status: "confirmed" } : { status: "declined" };
28
81
  }
29
82
  //# sourceMappingURL=confirm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"confirm.js","sourceRoot":"","sources":["../../src/cli/confirm.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAYH,MAAM,mBAAmB,GACvB,wGAAwG,CAAC;AAE3G;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAA4B;IAC7D,IAAI,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QAClC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACjC,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;IAC1C,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACxC,MAAM,IAAI,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC/D,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACzC,OAAO,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAC/F,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAChC,CAAC"}
1
+ {"version":3,"file":"confirm.js","sourceRoot":"","sources":["../../src/cli/confirm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAwBH;;;;;;;;;;;;;;;GAeG;AACH,KAAK,UAAU,iBAAiB,CAAC,KAA4B;IAC3D,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;IAC/C,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACrC,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QACvD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IAC3B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,oBAAoB,GACxB,6EAA6E;IAC7E,+EAA+E;IAC/E,6EAA6E;IAC7E,iCAAiC,CAAC;AAEpC;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,OAAkC;IAElC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACrD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IAC9B,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AAC5E,CAAC;AAED,MAAM,mBAAmB,GACvB,wGAAwG,CAAC;AAE3G;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAA4B;IAC7D,IAAI,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QAClC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACjC,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACrD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAChC,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC1C,OAAO,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAC/F,CAAC"}
@@ -14,6 +14,8 @@ export declare const SETUP_ERROR_CODES: {
14
14
  readonly GCLOUD_NOT_LOGGED_IN: "gcloud_not_logged_in";
15
15
  /** The active gcloud account lacks the Drive scope needed to create and own the spreadsheet. */
16
16
  readonly GCLOUD_DRIVE_ACCESS_REQUIRED: "gcloud_drive_access_required";
17
+ /** The interactive `gcloud auth login --enable-gdrive-access --force` handoff did not complete successfully. */
18
+ readonly GCLOUD_LOGIN_FAILED: "gcloud_login_failed";
17
19
  /** The user access token could not be retrieved or validated through tokeninfo. */
18
20
  readonly USER_TOKEN_FAILED: "user_token_failed";
19
21
  /** `gcloud projects create` failed for a reason other than "already exists". */
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/cli/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,iBAAiB;IAC5B,+DAA+D;;IAE/D,6DAA6D;;IAE7D,gGAAgG;;IAEhG,mFAAmF;;IAEnF,gFAAgF;;IAEhF,iGAAiG;;IAEjG,0CAA0C;;IAE1C,6DAA6D;;IAE7D,kDAAkD;;IAElD,mEAAmE;;IAEnE,yXAAyX;;IAEzX,mGAAmG;;IAEnG,iGAAiG;;IAEjG,0HAA0H;;IAE1H,oHAAoH;;IAEpH,sGAAsG;;IAEtG,wFAAwF;;IAExF,qFAAqF;;IAErF,0FAA0F;;IAE1F,yFAAyF;;IAEzF,kEAAkE;;IAElE,oDAAoD;;IAEpD,+EAA+E;;CAEvE,CAAC;AAEX,wDAAwD;AACxD,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAC;AAExF,2CAA2C;AAC3C,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C,sCAAsC;AACtC,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAE/C,6EAA6E;AAC7E,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,yCAAyC;AACzC,wBAAgB,YAAY,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,YAAY,CAEhF"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/cli/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,iBAAiB;IAC5B,+DAA+D;;IAE/D,6DAA6D;;IAE7D,gGAAgG;;IAEhG,gHAAgH;;IAEhH,mFAAmF;;IAEnF,gFAAgF;;IAEhF,iGAAiG;;IAEjG,0CAA0C;;IAE1C,6DAA6D;;IAE7D,kDAAkD;;IAElD,mEAAmE;;IAEnE,yXAAyX;;IAEzX,mGAAmG;;IAEnG,iGAAiG;;IAEjG,0HAA0H;;IAE1H,oHAAoH;;IAEpH,sGAAsG;;IAEtG,wFAAwF;;IAExF,qFAAqF;;IAErF,0FAA0F;;IAE1F,yFAAyF;;IAEzF,kEAAkE;;IAElE,oDAAoD;;IAEpD,+EAA+E;;CAEvE,CAAC;AAEX,wDAAwD;AACxD,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAC;AAExF,2CAA2C;AAC3C,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C,sCAAsC;AACtC,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAE/C,6EAA6E;AAC7E,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,yCAAyC;AACzC,wBAAgB,YAAY,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,YAAY,CAEhF"}
@@ -14,6 +14,8 @@ export const SETUP_ERROR_CODES = {
14
14
  GCLOUD_NOT_LOGGED_IN: "gcloud_not_logged_in",
15
15
  /** The active gcloud account lacks the Drive scope needed to create and own the spreadsheet. */
16
16
  GCLOUD_DRIVE_ACCESS_REQUIRED: "gcloud_drive_access_required",
17
+ /** The interactive `gcloud auth login --enable-gdrive-access --force` handoff did not complete successfully. */
18
+ GCLOUD_LOGIN_FAILED: "gcloud_login_failed",
17
19
  /** The user access token could not be retrieved or validated through tokeninfo. */
18
20
  USER_TOKEN_FAILED: "user_token_failed",
19
21
  /** `gcloud projects create` failed for a reason other than "already exists". */
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/cli/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,+DAA+D;IAC/D,cAAc,EAAE,gBAAgB;IAChC,6DAA6D;IAC7D,oBAAoB,EAAE,sBAAsB;IAC5C,gGAAgG;IAChG,4BAA4B,EAAE,8BAA8B;IAC5D,mFAAmF;IACnF,iBAAiB,EAAE,mBAAmB;IACtC,gFAAgF;IAChF,qBAAqB,EAAE,uBAAuB;IAC9C,iGAAiG;IACjG,iBAAiB,EAAE,mBAAmB;IACtC,0CAA0C;IAC1C,qBAAqB,EAAE,uBAAuB;IAC9C,6DAA6D;IAC7D,iBAAiB,EAAE,mBAAmB;IACtC,kDAAkD;IAClD,gBAAgB,EAAE,kBAAkB;IACpC,mEAAmE;IACnE,iBAAiB,EAAE,mBAAmB;IACtC,yXAAyX;IACzX,oBAAoB,EAAE,sBAAsB;IAC5C,mGAAmG;IACnG,oBAAoB,EAAE,sBAAsB;IAC5C,iGAAiG;IACjG,mBAAmB,EAAE,qBAAqB;IAC1C,0HAA0H;IAC1H,sBAAsB,EAAE,wBAAwB;IAChD,oHAAoH;IACpH,iBAAiB,EAAE,mBAAmB;IACtC,sGAAsG;IACtG,iBAAiB,EAAE,mBAAmB;IACtC,wFAAwF;IACxF,kBAAkB,EAAE,oBAAoB;IACxC,qFAAqF;IACrF,uBAAuB,EAAE,yBAAyB;IAClD,0FAA0F;IAC1F,mBAAmB,EAAE,qBAAqB;IAC1C,yFAAyF;IACzF,oBAAoB,EAAE,sBAAsB;IAC5C,kEAAkE;IAClE,wBAAwB,EAAE,0BAA0B;IACpD,oDAAoD;IACpD,mBAAmB,EAAE,qBAAqB;IAC1C,+EAA+E;IAC/E,YAAY,EAAE,cAAc;CACpB,CAAC;AAKX,2CAA2C;AAC3C,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC;AAE3C,sCAAsC;AACtC,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC;AAQ/C,yCAAyC;AACzC,MAAM,UAAU,YAAY,CAAC,IAAoB,EAAE,OAAe;IAChE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC3B,CAAC"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/cli/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,+DAA+D;IAC/D,cAAc,EAAE,gBAAgB;IAChC,6DAA6D;IAC7D,oBAAoB,EAAE,sBAAsB;IAC5C,gGAAgG;IAChG,4BAA4B,EAAE,8BAA8B;IAC5D,gHAAgH;IAChH,mBAAmB,EAAE,qBAAqB;IAC1C,mFAAmF;IACnF,iBAAiB,EAAE,mBAAmB;IACtC,gFAAgF;IAChF,qBAAqB,EAAE,uBAAuB;IAC9C,iGAAiG;IACjG,iBAAiB,EAAE,mBAAmB;IACtC,0CAA0C;IAC1C,qBAAqB,EAAE,uBAAuB;IAC9C,6DAA6D;IAC7D,iBAAiB,EAAE,mBAAmB;IACtC,kDAAkD;IAClD,gBAAgB,EAAE,kBAAkB;IACpC,mEAAmE;IACnE,iBAAiB,EAAE,mBAAmB;IACtC,yXAAyX;IACzX,oBAAoB,EAAE,sBAAsB;IAC5C,mGAAmG;IACnG,oBAAoB,EAAE,sBAAsB;IAC5C,iGAAiG;IACjG,mBAAmB,EAAE,qBAAqB;IAC1C,0HAA0H;IAC1H,sBAAsB,EAAE,wBAAwB;IAChD,oHAAoH;IACpH,iBAAiB,EAAE,mBAAmB;IACtC,sGAAsG;IACtG,iBAAiB,EAAE,mBAAmB;IACtC,wFAAwF;IACxF,kBAAkB,EAAE,oBAAoB;IACxC,qFAAqF;IACrF,uBAAuB,EAAE,yBAAyB;IAClD,0FAA0F;IAC1F,mBAAmB,EAAE,qBAAqB;IAC1C,yFAAyF;IACzF,oBAAoB,EAAE,sBAAsB;IAC5C,kEAAkE;IAClE,wBAAwB,EAAE,0BAA0B;IACpD,oDAAoD;IACpD,mBAAmB,EAAE,qBAAqB;IAC1C,+EAA+E;IAC/E,YAAY,EAAE,cAAc;CACpB,CAAC;AAKX,2CAA2C;AAC3C,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC;AAE3C,sCAAsC;AACtC,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC;AAQ/C,yCAAyC;AACzC,MAAM,UAAU,YAAY,CAAC,IAAoB,EAAE,OAAe;IAChE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC3B,CAAC"}
@@ -49,6 +49,68 @@ export interface GcloudRunner {
49
49
  * non-thrown results pass through unchanged.
50
50
  */
51
51
  export declare function createSafeRunner(runner: GcloudRunner): GcloudRunner;
52
+ /**
53
+ * Exact `gcloud auth login` arguments used for the interactive handoff.
54
+ *
55
+ * These mirror {@link DRIVE_ACCESS_COMMAND} in `humanAuth.ts`; the constant
56
+ * is duplicated here so `gcloudRunner` (which `humanAuth` imports) stays free
57
+ * of a runtime import cycle. `--enable-gdrive-access` grants the Drive scope
58
+ * needed to create and own the spreadsheet; `--force` refreshes the cached
59
+ * credentials of an already-logged-in account that lacks the scope.
60
+ */
61
+ export declare const LOGIN_ARGS: readonly ["auth", "login", "--enable-gdrive-access", "--force"];
62
+ /**
63
+ * Sanitized outcome of the interactive `gcloud auth login` handoff.
64
+ *
65
+ * Only the process exit result is exposed: stdout, stderr, and any access
66
+ * token stay in the user's own gcloud credential store and are never
67
+ * captured, stored, checkpointed, or forwarded by Hikoutei.
68
+ */
69
+ export type GcloudLoginResult = {
70
+ readonly status: "ok";
71
+ } | {
72
+ readonly status: "not_found";
73
+ } | {
74
+ readonly status: "spawn_error";
75
+ } | {
76
+ readonly status: "failed";
77
+ readonly code: number | null;
78
+ };
79
+ /**
80
+ * Minimal child-process surface the login runner observes.
81
+ *
82
+ * The real `spawn` returns a `ChildProcess`; tests inject a fake that emits
83
+ * `error`/`exit`. Only the two lifecycle events the runner maps to a sanitized
84
+ * result are required.
85
+ */
86
+ export interface LoginChildProcess {
87
+ on(event: "error", listener: (error: NodeJS.ErrnoException) => void): unknown;
88
+ on(event: "exit", listener: (code: number | null, signal: NodeJS.Signals | null) => void): unknown;
89
+ }
90
+ /** Spawns the login subprocess; injectable so tests assert the exact command and stdio. */
91
+ export type LoginSpawner = (command: string, args: readonly string[], options: {
92
+ readonly stdio: "inherit";
93
+ }) => LoginChildProcess;
94
+ /** Runs the interactive `gcloud auth login` handoff attached to the terminal. */
95
+ export interface GcloudLoginRunner {
96
+ runInteractiveLogin(): Promise<GcloudLoginResult>;
97
+ }
98
+ /**
99
+ * Production interactive login runner.
100
+ *
101
+ * Spawns `gcloud auth login --enable-gdrive-access --force` with the terminal
102
+ * streams inherited (`stdio: "inherit"`) so the user completes the browser
103
+ * OAuth flow in their own gcloud session and Hikoutei never touches the
104
+ * resulting token. Only the exit outcome is reduced to a sanitized result:
105
+ * `ENOENT` (gcloud not installed) is `not_found`, any other spawn failure is
106
+ * `spawn_error`, a non-zero exit is `failed` with the exit code, and a clean
107
+ * exit is `ok`. The runner resolves exactly once even if both `error` and
108
+ * `exit` arrive.
109
+ *
110
+ * @param spawner Process spawner; defaults to Node's `spawn`. Injectable so
111
+ * tests assert the exact command and the inherited stdio without spawning.
112
+ */
113
+ export declare function createInteractiveLoginRunner(spawner?: LoginSpawner): GcloudLoginRunner;
52
114
  /**
53
115
  * Production runner: executes `gcloud <args>` with `execFile`.
54
116
  *
@@ -1 +1 @@
1
- {"version":3,"file":"gcloudRunner.d.ts","sourceRoot":"","sources":["../../src/cli/gcloudRunner.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,wCAAwC;AACxC,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC3E;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GAChC;IACA,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,CAAC;AAEJ,+CAA+C;AAC/C,MAAM,WAAW,gBAAgB;IAC/B;;;;;;OAMG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,4EAA4E;AAC5E,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CACpF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAYnE;AAKD;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,YAAY,CA6BjD"}
1
+ {"version":3,"file":"gcloudRunner.d.ts","sourceRoot":"","sources":["../../src/cli/gcloudRunner.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,wCAAwC;AACxC,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC3E;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GAChC;IACA,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,CAAC;AAEJ,+CAA+C;AAC/C,MAAM,WAAW,gBAAgB;IAC/B;;;;;;OAMG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,4EAA4E;AAC5E,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CACpF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAYnE;AAKD;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,iEAAkE,CAAC;AAE1F;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GACzB;IAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAA;CAAE,GACzB;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GAChC;IAAE,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;CAAE,GAClC;IAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAEhE;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC;IAC9E,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC;CACpG;AAED,2FAA2F;AAC3F,MAAM,MAAM,YAAY,GAAG,CACzB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;CAAE,KACnC,iBAAiB,CAAC;AAEvB,iFAAiF;AACjF,MAAM,WAAW,iBAAiB;IAChC,mBAAmB,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACnD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,4BAA4B,CAAC,OAAO,GAAE,YAAkC,GAAG,iBAAiB,CAyB3G;AAWD;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,YAAY,CA6BjD"}
@@ -7,7 +7,7 @@
7
7
  * implementation shells out with `node:child_process` `execFile`; a missing
8
8
  * binary is reported distinctly (`not_found`) from a failed invocation.
9
9
  */
10
- import { execFile } from "node:child_process";
10
+ import { execFile, spawn } from "node:child_process";
11
11
  /**
12
12
  * Wraps a runner so a throwing invocation becomes a sanitized failed result.
13
13
  *
@@ -36,6 +36,61 @@ export function createSafeRunner(runner) {
36
36
  }
37
37
  const GCLOUD_BINARY = "gcloud";
38
38
  const MAX_BUFFER_BYTES = 1024 * 1024;
39
+ /**
40
+ * Exact `gcloud auth login` arguments used for the interactive handoff.
41
+ *
42
+ * These mirror {@link DRIVE_ACCESS_COMMAND} in `humanAuth.ts`; the constant
43
+ * is duplicated here so `gcloudRunner` (which `humanAuth` imports) stays free
44
+ * of a runtime import cycle. `--enable-gdrive-access` grants the Drive scope
45
+ * needed to create and own the spreadsheet; `--force` refreshes the cached
46
+ * credentials of an already-logged-in account that lacks the scope.
47
+ */
48
+ export const LOGIN_ARGS = ["auth", "login", "--enable-gdrive-access", "--force"];
49
+ /**
50
+ * Production interactive login runner.
51
+ *
52
+ * Spawns `gcloud auth login --enable-gdrive-access --force` with the terminal
53
+ * streams inherited (`stdio: "inherit"`) so the user completes the browser
54
+ * OAuth flow in their own gcloud session and Hikoutei never touches the
55
+ * resulting token. Only the exit outcome is reduced to a sanitized result:
56
+ * `ENOENT` (gcloud not installed) is `not_found`, any other spawn failure is
57
+ * `spawn_error`, a non-zero exit is `failed` with the exit code, and a clean
58
+ * exit is `ok`. The runner resolves exactly once even if both `error` and
59
+ * `exit` arrive.
60
+ *
61
+ * @param spawner Process spawner; defaults to Node's `spawn`. Injectable so
62
+ * tests assert the exact command and the inherited stdio without spawning.
63
+ */
64
+ export function createInteractiveLoginRunner(spawner = spawnAsLoginSpawner) {
65
+ return {
66
+ runInteractiveLogin() {
67
+ return new Promise((resolve) => {
68
+ let settled = false;
69
+ const finish = (result) => {
70
+ if (settled) {
71
+ return;
72
+ }
73
+ settled = true;
74
+ resolve(result);
75
+ };
76
+ const child = spawner(GCLOUD_BINARY, LOGIN_ARGS, { stdio: "inherit" });
77
+ child.on("error", (error) => {
78
+ // The subprocess could not be started. `ENOENT` means gcloud is
79
+ // absent from PATH; anything else is an opaque spawn failure.
80
+ // The error text may carry transport detail and is never forwarded.
81
+ finish(error.code === "ENOENT" ? { status: "not_found" } : { status: "spawn_error" });
82
+ });
83
+ child.on("exit", (code) => {
84
+ finish(code === 0 ? { status: "ok" } : { status: "failed", code });
85
+ });
86
+ });
87
+ },
88
+ };
89
+ }
90
+ /** Default spawner backed by Node's `child_process.spawn`. */
91
+ function spawnAsLoginSpawner(command, args, options) {
92
+ return spawn(command, [...args], options);
93
+ }
39
94
  /**
40
95
  * Production runner: executes `gcloud <args>` with `execFile`.
41
96
  *
@@ -1 +1 @@
1
- {"version":3,"file":"gcloudRunner.js","sourceRoot":"","sources":["../../src/cli/gcloudRunner.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AA+B9C;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAoB;IACnD,OAAO;QACL,KAAK,CAAC,GAAG,CAAC,IAAuB,EAAE,OAA0B;YAC3D,IAAI,CAAC;gBACH,OAAO,MAAM,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACzC,CAAC;YAAC,MAAM,CAAC;gBACP,iEAAiE;gBACjE,mDAAmD;gBACnD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;YAClE,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,aAAa,GAAG,QAAQ,CAAC;AAC/B,MAAM,gBAAgB,GAAG,IAAI,GAAG,IAAI,CAAC;AAErC;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO;QACL,GAAG,CAAC,IAAuB,EAAE,OAA0B;YACrD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC7B,QAAQ,CACN,aAAa,EACb,CAAC,GAAG,IAAI,CAAC,EACT;oBACE,QAAQ,EAAE,MAAM;oBAChB,SAAS,EAAE,gBAAgB;oBAC3B,GAAG,CAAC,OAAO,EAAE,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;iBAC5D,EACD,CAAC,KAAc,EAAE,MAAc,EAAE,MAAc,EAAE,EAAE;oBACjD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;wBACnB,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;wBAC1C,OAAO;oBACT,CAAC;oBACD,MAAM,KAAK,GAAG,KAA8B,CAAC;oBAC7C,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;wBAC5B,OAAO,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;wBACjC,OAAO;oBACT,CAAC;oBACD,MAAM,IAAI,GAAG,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;oBAChE,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;gBACtD,CAAC,CACF,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"gcloudRunner.js","sourceRoot":"","sources":["../../src/cli/gcloudRunner.ts"],"names":[],"mappings":"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"}
@@ -2,12 +2,110 @@
2
2
  /**
3
3
  * `hikoutei setup` CLI entry.
4
4
  *
5
- * Thin main: parse flags, resolve path defaults against the current
6
- * directory, ask for confirmation (unless `--yes`/`--dry-run`), run the
7
- * injected-runner setup flow, and print the summary or the dry-run plan.
8
- * Exit codes: 0 success, 2 argument errors, 1 runtime failures. Errors are
9
- * printed as `hikoutei-setup:<code>: <message>` for machine consumption, and
10
- * key material and the user access token are never printed.
11
- */
12
- export {};
5
+ * The orchestration is split into a thin `main()` that wires production
6
+ * dependencies (gcloud runner, token validator, sheet factory, SA verifier,
7
+ * interactive login runner) and a testable {@link runSetupCli} that owns the
8
+ * sequence: resolve paths, reject canonical path collisions, ask for the
9
+ * one-time y/N confirmation (skipped by `--yes`/`--dry-run`), run setup, and
10
+ * on an auth preflight failure offer a single interactive Enter-to-login
11
+ * handoff into `gcloud auth login` before retrying exactly once. Exit codes:
12
+ * 0 success, 2 argument errors, 1 runtime failures. Errors are printed as
13
+ * `hikoutei-setup:<code>: <message>` for machine consumption, and key
14
+ * material and the user access token are never printed.
15
+ */
16
+ import { type SetupOptions } from "./args.js";
17
+ import { type GcloudLoginRunner } from "./gcloudRunner.js";
18
+ import { type SetupResult } from "./setupFlow.js";
19
+ /** Pure parameters for one setup attempt (no injected infrastructure). */
20
+ export interface RunSetupParams {
21
+ readonly projectId: string | undefined;
22
+ readonly saName: string;
23
+ readonly spreadsheetTitle: string | undefined;
24
+ readonly keyPath: string;
25
+ readonly outputPath: string;
26
+ readonly statePath: string;
27
+ readonly dryRun: boolean;
28
+ }
29
+ /**
30
+ * Runs one setup attempt.
31
+ *
32
+ * Infrastructure (gcloud runner, token validator, sheet factory, SA verifier)
33
+ * is closed over by the caller, so {@link runSetupCli} can be tested with a
34
+ * scripted callable that returns auth preflight failures and successes
35
+ * without wiring up the full harness.
36
+ */
37
+ export type RunSetupCallable = (params: RunSetupParams) => Promise<SetupResult>;
38
+ /** Terminal line source for the CLI; `process.stdin` in production. */
39
+ export interface CliStdin extends AsyncIterable<string> {
40
+ /** True when stdin is attached to a terminal (gates the login handoff). */
41
+ readonly isTTY?: boolean;
42
+ }
43
+ /** Terminal output sink; `process.stdout` in production. */
44
+ export interface CliStdout {
45
+ /** True when stdout is attached to a terminal (gates the login handoff). */
46
+ readonly isTTY?: boolean;
47
+ readonly write: (text: string) => void;
48
+ }
49
+ /** Diagnostic output sink; `process.stderr` in production. */
50
+ export interface CliStderr {
51
+ readonly write: (text: string) => void;
52
+ }
53
+ /** Context injected into {@link runSetupCli}; production values come from `main()`. */
54
+ export interface RunSetupCliContext {
55
+ readonly options: SetupOptions;
56
+ readonly cwd: string;
57
+ /** Runs one setup attempt with all real/fake infrastructure closed over. */
58
+ readonly runSetup: RunSetupCallable;
59
+ /** Runs the interactive `gcloud auth login` handoff attached to the terminal. */
60
+ readonly loginRunner: GcloudLoginRunner;
61
+ readonly stdin: CliStdin;
62
+ readonly stdout: CliStdout;
63
+ readonly stderr: CliStderr;
64
+ /**
65
+ * Releases the shared stdin after every prompt and the inherited gcloud
66
+ * login have finished; called exactly once on every setup outcome
67
+ * (collision, declined confirmation, success, dry run, errors, login
68
+ * cancel/failure, and retries). Optional so tests that do not exercise
69
+ * the lifecycle run unchanged.
70
+ *
71
+ * The confirmation and login-handoff prompts read `process.stdin` through
72
+ * its async iterator WITHOUT calling the iterator's `return()` so the two
73
+ * sequential prompts share one stream; that open iterator keeps an internal
74
+ * listener on the Readable and would hold the process alive after setup
75
+ * finishes. The production finalizer destroys `process.stdin` to release
76
+ * it. It is invoked from a `finally` AFTER the inherited login subprocess
77
+ * (which needs the live terminal) resolves, never before it.
78
+ */
79
+ readonly finalizeStdin?: () => void;
80
+ }
81
+ /**
82
+ * Orchestrates the setup CLI: path resolution, collision guard, one-time
83
+ * confirmation, the setup run, and the optional interactive login handoff.
84
+ *
85
+ * The handoff runs ONLY when the first attempt fails with an auth preflight
86
+ * error (`gcloud_not_logged_in` or `gcloud_drive_access_required`) AND the
87
+ * session is a real interactive terminal (`stdin.isTTY && stdout.isTTY`) AND
88
+ * neither `--yes` nor `--dry-run` was given. The preflight runs before any
89
+ * lock, checkpoint, cloud, or file mutation, so retrying after a successful
90
+ * login cannot create duplicate resources. The login is attempted at most
91
+ * once and the setup retried at most once; if the retry still lacks the
92
+ * scope, the original sanitized error is reported with no further login.
93
+ *
94
+ * @returns the process exit code (0 success, 2 argument collision, 1 failure).
95
+ */
96
+ export declare function runSetupCli(context: RunSetupCliContext): Promise<number>;
97
+ /**
98
+ * Pure ESM entrypoint guard: true only when `entryArg` resolves (following
99
+ * symlinks) to the same file as `moduleUrl`.
100
+ *
101
+ * In CommonJS the bin would use `require.main === module`; in this package's
102
+ * pure-ESM layout (`"type": "module"`) this realpath comparison is the robust
103
+ * equivalent. `npx hikoutei` runs the published bin through a symlink, so the
104
+ * realpath step resolves `.bin/hikoutei` to `dist/cli/setup.js` and matches
105
+ * `import.meta.url`. When this module is imported — for example by the unit
106
+ * tests importing `runSetupCli` — the entry argument is the test runner binary
107
+ * and never matches, so `main()` is not executed and nothing parses argv,
108
+ * writes CLI errors, or mutates `process.exitCode` on import.
109
+ */
110
+ export declare function isModuleMainEntry(entryArg: string | undefined, moduleUrl: string): boolean;
13
111
  //# sourceMappingURL=setup.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/cli/setup.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG"}
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/cli/setup.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;GAaG;AAKH,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AAS9D,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,mBAAmB,CAAC;AAS3B,OAAO,EAOL,KAAK,WAAW,EACjB,MAAM,gBAAgB,CAAC;AAExB,0EAA0E;AAC1E,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,cAAc,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;AAEhF,uEAAuE;AACvE,MAAM,WAAW,QAAS,SAAQ,aAAa,CAAC,MAAM,CAAC;IACrD,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,4DAA4D;AAC5D,MAAM,WAAW,SAAS;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAED,8DAA8D;AAC9D,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAED,uFAAuF;AACvF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,iFAAiF;IACjF,QAAQ,CAAC,WAAW,EAAE,iBAAiB,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CACrC;AAQD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiG9E;AAsCD;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAW1F"}