iterate 0.2.4 → 0.2.5

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/bin/iterate.js CHANGED
@@ -1,9 +1,6 @@
1
1
  #!/usr/bin/env node
2
- // @ts-check
3
2
 
4
- import { execFileSync } from "node:child_process";
5
- import { existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from "node:fs";
6
- import { homedir } from "node:os";
3
+ import { existsSync, realpathSync } from "node:fs";
7
4
  import { dirname, join, resolve } from "node:path";
8
5
  import process from "node:process";
9
6
  import { fileURLToPath } from "node:url";
@@ -28,23 +25,28 @@ const findUp = (relativePath, startDir = process.cwd()) => {
28
25
  };
29
26
 
30
27
  const __filename = fileURLToPath(import.meta.url);
28
+ const __dirname = dirname(__filename);
29
+ const pkgRoot = dirname(__dirname);
31
30
 
32
31
  /**
33
- * If we're already running from a local version, skip delegation to avoid loops.
34
- * Otherwise, find the closest local iterate CLI and re-exec into it.
32
+ * Find a local version of the iterate CLI that differs from the currently
33
+ * running script. Returns an importable module path, or null.
34
+ * @returns {string | null}
35
35
  */
36
- const delegateToLocal = () => {
37
- if (process.env.__ITERATE_CLI_DELEGATED) return;
38
-
36
+ const findLocalModule = () => {
39
37
  const selfReal = realpathSync(__filename);
40
38
 
41
39
  // 1. Check if we're inside the iterate repo (has pnpm-workspace.yaml at root)
42
40
  const repoRoot = findUp("pnpm-workspace.yaml");
43
41
  if (repoRoot) {
44
- const repoScript = join(repoRoot, "packages/iterate/bin/iterate.js");
45
- if (existsSync(repoScript) && realpathSync(repoScript) !== selfReal) {
46
- reExec(repoScript);
47
- return;
42
+ const repoPkg = join(repoRoot, "packages/iterate");
43
+ const repoBin = join(repoPkg, "bin/iterate.js");
44
+ if (existsSync(repoBin) && realpathSync(repoBin) !== selfReal) {
45
+ // Prefer TS source in monorepo dev, fall back to dist
46
+ const repoSrc = join(repoPkg, "src/index.ts");
47
+ if (existsSync(repoSrc)) return repoSrc;
48
+ const repoDist = join(repoPkg, "dist/index.js");
49
+ if (existsSync(repoDist)) return repoDist;
48
50
  }
49
51
  }
50
52
 
@@ -53,580 +55,25 @@ const delegateToLocal = () => {
53
55
  if (nmRoot) {
54
56
  const nmScript = join(nmRoot, "node_modules/.bin/iterate");
55
57
  if (existsSync(nmScript) && realpathSync(nmScript) !== selfReal) {
56
- reExec(nmScript);
57
- return;
58
- }
59
- }
60
- };
61
-
62
- /**
63
- * Re-exec into `scriptPath` with the same argv, never returning.
64
- * @param {string} scriptPath
65
- */
66
- const reExec = (scriptPath) => {
67
- try {
68
- execFileSync(process.execPath, [scriptPath, ...process.argv.slice(2)], {
69
- stdio: "inherit",
70
- env: { ...process.env, __ITERATE_CLI_DELEGATED: "1" },
71
- });
72
- } catch (e) {
73
- process.exit(e && typeof e === "object" && "status" in e ? Number(e.status) || 1 : 1);
74
- }
75
- process.exit(0);
76
- };
77
-
78
- delegateToLocal();
79
-
80
- // --- Normal CLI startup (dynamic imports so delegation can short-circuit first) ---
81
-
82
- const prompts = await import("@clack/prompts");
83
- const { createTRPCClient, httpLink } = await import("@trpc/client");
84
- const { initTRPC } = await import("@trpc/server");
85
- const { createAuthClient } = await import("better-auth/client");
86
- const { adminClient } = await import("better-auth/client/plugins");
87
- const { default: superjson } = await import("superjson");
88
- const { createCli } = await import("trpc-cli");
89
- const { proxify } = await import("trpc-cli/dist/proxify.js");
90
- const { z } = await import("zod/v4");
91
-
92
- const XDG_CONFIG_PARENT = join(
93
- process.env.XDG_CONFIG_HOME ? process.env.XDG_CONFIG_HOME : join(homedir(), ".config"),
94
- "iterate",
95
- );
96
-
97
- const XDG_CONFIG_PATH = join(XDG_CONFIG_PARENT, "config.json");
98
- const CONFIG_PATH = XDG_CONFIG_PATH;
99
- // todo write json schema to file too - need to make everything zod first
100
- // const CONFIG_SCHEMA_PATH = join(XDG_CONFIG_PARENT, "config-schema.json");
101
-
102
- const SetupInput = z.object({
103
- osBaseUrl: z
104
- .string()
105
- .describe(`Base URL for OS API (for example https://dev-yourname-os.dev.iterate.com)`),
106
- daemonBaseUrl: z.string().describe(`Base URL for daemon API (for example http://localhost:3001)`),
107
- adminPasswordEnvVarName: z.string().describe("Env var name containing admin password"),
108
- userEmail: z.string().describe("User email to impersonate for OS calls"),
109
- scope: z.enum(["workspace", "global"]).describe("Where to store launcher config"),
110
- });
111
-
112
- const AuthConfig = z.object({
113
- osBaseUrl: z.string(),
114
- daemonBaseUrl: z.string(),
115
- adminPasswordEnvVarName: z.string(),
116
- userEmail: z.string(),
117
- });
118
-
119
- const ConfigFile = z.object({
120
- global: AuthConfig.partial().optional(),
121
- workspaces: z.record(z.string(), AuthConfig).optional(),
122
- /** a place where I put old/invalid configs I can't quite let go of */
123
- rubbish: z.unknown().optional(),
124
- });
125
-
126
- /** @typedef {import('zod').infer<typeof AuthConfig>} AuthConfig */
127
- /** @typedef {import('zod').infer<typeof ConfigFile>} ConfigFile */
128
-
129
- /**
130
- * @typedef {{
131
- * command: string;
132
- * args: string[];
133
- * cwd?: string;
134
- * env?: Record<string, string | undefined>;
135
- * }} SpawnOptions
136
- */
137
-
138
- const isAgent =
139
- process.env.AGENT === "1" ||
140
- process.env.OPENCODE === "1" ||
141
- Boolean(process.env.OPENCODE_SESSION) ||
142
- Boolean(process.env.CLAUDE_CODE);
143
-
144
- const t = initTRPC.meta().create();
145
-
146
- /**
147
- * @param {unknown} value
148
- * @returns {value is Record<string, unknown>}
149
- */
150
- const isObject = (value) => {
151
- return Boolean(value && typeof value === "object" && !Array.isArray(value));
152
- };
153
-
154
- /** @returns {ConfigFile} */
155
- const readConfigFile = () => {
156
- if (!existsSync(CONFIG_PATH)) {
157
- return {};
158
- }
159
- const rawText = readFileSync(CONFIG_PATH, "utf8");
160
- let parsed;
161
- try {
162
- parsed = JSON.parse(rawText);
163
- } catch (error) {
164
- const detail = error instanceof Error ? error.message : String(error);
165
- throw new Error(`Invalid JSON in ${CONFIG_PATH}: ${detail}`);
166
- }
167
-
168
- return parsed;
169
- };
170
-
171
- /**
172
- * @param {ConfigFile} configFile
173
- * @param {string} workspacePath
174
- */
175
- const getWorkspaceConfig = (configFile, workspacePath) => {
176
- const workspaces = isObject(configFile.workspaces) ? configFile.workspaces : {};
177
- const rawWorkspaceConfig = workspaces[workspacePath];
178
- return isObject(rawWorkspaceConfig) ? rawWorkspaceConfig : {};
179
- };
180
-
181
- /**
182
- * @param {ConfigFile} configFile
183
- * @param {string} workspacePath
184
- */
185
- const getMergedWorkspaceConfig = (configFile, workspacePath) => {
186
- const configs = [];
187
- while (workspacePath && workspacePath !== "/") {
188
- if (workspacePath in (configFile.workspaces || {})) {
189
- configs.push(configFile.workspaces?.[workspacePath]);
58
+ // Published package — use dist
59
+ const nmDist = join(nmRoot, "node_modules/iterate/dist/index.js");
60
+ if (existsSync(nmDist)) return nmDist;
190
61
  }
191
- workspacePath = dirname(workspacePath);
192
62
  }
193
- configs.push(configFile.global);
194
- /** @type {AuthConfig} */
195
- return configs.reverse().reduce((acc, config) => {
196
- return { ...acc, ...config };
197
- }, {});
198
- };
199
-
200
- /**
201
- * @param {{ patch?: Partial<AuthConfig>; scope: "workspace" | "global"; workspacePath: string; }} options
202
- * @returns {ConfigFile}
203
- */
204
- const writeNewConfig = ({ patch, scope, workspacePath }) => {
205
- patch = Object.fromEntries(
206
- Object.entries(patch || {}).filter(([_key, value]) => value !== undefined),
207
- );
208
- const configFile = readConfigFile();
209
- const cloned = structuredClone(configFile);
210
63
 
211
- if (scope === "global") {
212
- cloned.global = { ...configFile.global, ...patch };
213
- }
214
- if (scope === "workspace" && workspacePath) {
215
- cloned.workspaces ||= {};
216
- // @ts-expect-error - we know it's a string
217
- cloned.workspaces[workspacePath] = {
218
- ...configFile.workspaces?.[workspacePath],
219
- ...patch,
220
- };
221
- }
222
-
223
- const parsed = ConfigFile.safeParse(cloned);
224
- if (!parsed.success) {
225
- throw new Error(`Invalid config file: ${z.prettifyError(parsed.error)}`);
226
- }
227
-
228
- mkdirSync(dirname(CONFIG_PATH), { recursive: true });
229
- writeFileSync(CONFIG_PATH, `${JSON.stringify(parsed.data, null, 2)}\n`);
230
- return cloned;
231
- };
232
-
233
- /** @param {string} workspacePath */
234
- const readAuthConfig = (workspacePath) => {
235
- const configFile = readConfigFile();
236
- const mergedConfig = getMergedWorkspaceConfig(configFile, workspacePath);
237
- const parsed = AuthConfig.safeParse(mergedConfig);
238
- if (!parsed.success) {
239
- return new Error(
240
- `Invalid auth config for ${workspacePath} (in config file ${CONFIG_PATH}). Have you run \`iterate setup\`?\n${z.prettifyError(parsed.error)}`,
241
- );
242
- }
243
- return parsed.data;
244
- };
245
-
246
- /** @param {string[] | undefined} setCookies */
247
- const setCookiesToCookieHeader = (setCookies) => {
248
- const byName = new Map();
249
- for (const c of setCookies ?? []) {
250
- const pair = c.split(";")[0]?.trim();
251
- if (!pair) continue;
252
- const eq = pair.indexOf("=");
253
- if (eq === -1) continue;
254
- byName.set(pair.slice(0, eq), pair.slice(eq + 1));
255
- }
256
- return [...byName.entries()].map(([k, v]) => `${k}=${v}`).join("; ");
64
+ return null;
257
65
  };
258
66
 
259
- const impersonationUserIdCache = new Map();
260
-
261
- /**
262
- * @param {{
263
- * superadminAuthClient: any;
264
- * userEmail: string;
265
- * baseUrl: string;
266
- * }} options
267
- */
268
- const resolveImpersonationUserId = async ({ superadminAuthClient, userEmail, baseUrl }) => {
269
- const normalizedEmail = userEmail.trim().toLowerCase();
270
- const cacheKey = `${baseUrl}::${normalizedEmail}`;
271
- const cachedUserId = impersonationUserIdCache.get(cacheKey);
272
- if (cachedUserId) {
273
- return cachedUserId;
274
- }
275
-
276
- /** @type {any[]} */
277
- let users = [];
278
-
279
- try {
280
- const result = await superadminAuthClient.admin.listUsers({
281
- query: {
282
- filterField: "email",
283
- filterOperator: "eq",
284
- filterValue: normalizedEmail,
285
- limit: 10,
286
- },
287
- fetchOptions: {
288
- throw: true,
289
- },
290
- });
291
- users = Array.isArray(result?.users) ? result.users : [];
292
- } catch {
293
- const result = await superadminAuthClient.admin.listUsers({
294
- query: {
295
- searchField: "email",
296
- searchOperator: "contains",
297
- searchValue: normalizedEmail,
298
- limit: 100,
299
- },
300
- fetchOptions: {
301
- throw: true,
302
- },
303
- });
304
- users = Array.isArray(result?.users) ? result.users : [];
305
- }
306
-
307
- const exactMatches = users.filter(
308
- (user) =>
309
- user &&
310
- typeof user === "object" &&
311
- "email" in user &&
312
- typeof user.email === "string" &&
313
- user.email.toLowerCase() === normalizedEmail &&
314
- "id" in user &&
315
- typeof user.id === "string",
316
- );
317
-
318
- if (exactMatches.length === 0) {
319
- throw new Error(`No user found with email ${userEmail}`);
320
- }
321
- if (exactMatches.length > 1) {
322
- throw new Error(`Multiple users found with email ${userEmail}`);
323
- }
324
-
325
- const resolvedUserId = exactMatches[0].id;
326
- impersonationUserIdCache.set(cacheKey, resolvedUserId);
327
- return resolvedUserId;
328
- };
329
-
330
- /** @param {import('zod').infer<typeof AuthConfig>} authConfig */
331
- const osAuthDance = async (authConfig) => {
332
- /** @type {string[] | undefined} */
333
- let superadminSetCookie;
334
- const authClient = createAuthClient({
335
- baseURL: authConfig.osBaseUrl,
336
- fetchOptions: {
337
- throw: true,
338
- },
339
- });
340
- const password = process.env[authConfig.adminPasswordEnvVarName];
341
- if (!password) {
342
- throw new Error(`Password not found in env var ${authConfig.adminPasswordEnvVarName}`);
343
- }
344
-
345
- await authClient.signIn.email({
346
- email: "superadmin@nustom.com",
347
- password,
348
- fetchOptions: {
349
- throw: true,
350
- onResponse: (ctx) => {
351
- superadminSetCookie = ctx.response.headers.getSetCookie();
352
- },
353
- },
354
- });
355
-
356
- const superadminAuthClient = createAuthClient({
357
- baseURL: authConfig.osBaseUrl,
358
- fetchOptions: {
359
- throw: true,
360
- onRequest: (ctx) => {
361
- ctx.headers.set("origin", authConfig.osBaseUrl);
362
- ctx.headers.set("cookie", setCookiesToCookieHeader(superadminSetCookie));
363
- },
364
- },
365
- plugins: [adminClient()],
366
- });
367
-
368
- const userId = await resolveImpersonationUserId({
369
- superadminAuthClient,
370
- userEmail: authConfig.userEmail,
371
- baseUrl: authConfig.osBaseUrl,
372
- });
373
-
374
- let impersonateSetCookie;
375
- await superadminAuthClient.admin.impersonateUser({
376
- userId,
377
- fetchOptions: {
378
- throw: true,
379
- onResponse: (ctx) => {
380
- impersonateSetCookie = ctx.response.headers.getSetCookie();
381
- },
382
- },
383
- });
384
-
385
- const userCookies = setCookiesToCookieHeader(impersonateSetCookie);
386
-
387
- const userClient = createAuthClient({
388
- baseURL: authConfig.osBaseUrl,
389
- fetchOptions: {
390
- throw: true,
391
- onRequest: (ctx) => {
392
- ctx.headers.set("origin", authConfig.osBaseUrl);
393
- ctx.headers.set("cookie", userCookies);
394
- },
395
- },
396
- });
397
-
398
- return { userCookies, userClient };
399
- };
400
-
401
- /** @param {{baseUrl: string}} params */
402
- const loadAppRouter = async (params) => {
403
- const url = `${params.baseUrl}/api/trpc-cli-procedures`;
404
- const response = await fetch(url);
405
- if (!response.ok) {
406
- throw new Error(`${url} got ${response.status}: ${await response.text()}`);
407
- }
408
-
409
- const router = await response.json().catch((e) => {
410
- throw new Error(`${url} returned invalid router: ${e.message}`);
411
- });
412
- if (!Array.isArray(router?.procedures)) {
413
- throw new Error(`${url} returned invalid router: ${JSON.stringify(router)}`);
414
- }
415
- /** @type {{procedures: any[]}} */
416
- return router;
417
- };
418
-
419
- /** @param {{ baseUrl: string }} params */
420
- const getOsProcedures = async (params) => {
421
- const appRouter = await loadAppRouter(params);
422
- /** @type {{}} */
423
- const proxiedRouter = proxify(appRouter.procedures, async () => {
424
- return createTRPCClient({
425
- links: [
426
- httpLink({
427
- url: `${params.baseUrl}/api/trpc/`,
428
- transformer: superjson,
429
- fetch: async (request, init) => {
430
- const authConfig = readAuthConfig(process.cwd());
431
- if (authConfig instanceof Error) throw authConfig;
432
- const { userCookies } = await osAuthDance(authConfig);
433
- const headers = new Headers(init?.headers);
434
- headers.set("cookie", userCookies);
435
- return fetch(request, { ...init, headers });
436
- },
437
- }),
438
- ],
439
- });
440
- });
441
-
442
- return proxiedRouter;
443
- };
444
-
445
- /**
446
- * Creates a fetch wrapper that calls /api/trpc-stream/* instead of /api/trpc/*.
447
- * The streaming endpoint returns SSE: log lines as `event: log` and the final
448
- * tRPC response as `event: response`, which we reassemble into a normal Response.
449
- * @param {string} daemonBaseUrl
450
- * @returns {typeof globalThis.fetch}
451
- */
452
- const streamingFetch = (daemonBaseUrl) => {
453
- return async (/** @type {any} */ input, /** @type {any} */ init) => {
454
- // Rewrite URL from /api/trpc/X to /api/trpc-stream/X
455
- const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
456
- const rewritten = url.replace(
457
- `${daemonBaseUrl}/api/trpc/`,
458
- `${daemonBaseUrl}/api/trpc-stream/`,
459
- );
460
- const res = await fetch(rewritten, init);
461
- if (rewritten === url) return res;
462
-
463
- const contentType = res.headers.get("content-type") || "";
464
- // If the daemon didn't respond with SSE, pass through as-is (non-streaming endpoint)
465
- if (!contentType.includes("text/event-stream")) return res;
466
- // Parse SSE stream: print log events to stderr, collect the final response
467
- const reader = res.body?.getReader();
468
- if (!reader) return res;
469
- const decoder = new TextDecoder();
470
- let buffer = "";
471
- /** @type {string | null} */
472
- let responseBody = null;
473
- while (true) {
474
- const { done, value } = await reader.read();
475
- if (done) break;
476
- buffer += decoder.decode(value, { stream: true });
477
- // Process complete SSE messages (double newline delimited)
478
- const parts = buffer.split("\n\n");
479
- buffer = parts.pop() || "";
480
- for (const part of parts) {
481
- const lines = part.split("\n");
482
- const event = lines[0].split(": ")[1];
483
- const data = lines[1].split(": ").slice(1).join(": ");
484
- if (event === "log") {
485
- /** @type {{level: "debug" | "info" | "warn" | "error"; args: unknown[]}} */
486
- const detail = JSON.parse(data);
487
- console[detail.level](...detail.args);
488
- } else if (event === "response") {
489
- responseBody = data;
490
- }
491
- }
492
- }
493
- // Reconstruct a normal Response from the final payload so tRPC client is happy
494
- return new Response(responseBody, {
495
- status: res.status,
496
- headers: { "content-type": "application/json" },
497
- });
498
- };
499
- };
500
-
501
- /** @param {{ daemonBaseUrl: string }} params */
502
- const getDaemonProcedures = async (params) => {
503
- const daemonRouter = await loadAppRouter({ baseUrl: params.daemonBaseUrl });
504
- const proxiedRouter = proxify(daemonRouter.procedures, async () => {
505
- return createTRPCClient({
506
- links: [
507
- httpLink({
508
- url: `${params.daemonBaseUrl}/api/trpc/`,
509
- fetch: streamingFetch(params.daemonBaseUrl),
510
- }),
511
- ],
512
- });
513
- });
514
-
515
- return proxiedRouter;
516
- };
517
-
518
- const launcherProcedures = {
519
- doctor: t.procedure
520
- .meta({ description: "Show launcher config and resolved runtime options" })
521
- .mutation(async () => {
522
- const configFile = readConfigFile();
523
- const parsed = ConfigFile.safeParse(configFile);
524
- if (!parsed.success) {
525
- throw new Error(`Invalid config file ${CONFIG_PATH}: ${z.prettifyError(parsed.error)}`);
526
- }
527
- const current = readAuthConfig(process.cwd());
528
- if (current instanceof Error) throw current;
529
- return { configPath: CONFIG_PATH, current };
530
- }),
531
- setup: t.procedure
532
- .input(SetupInput.partial())
533
- .meta({ prompt: true, description: "Configure auth + launcher defaults for current workspace" })
534
- .mutation(async ({ input }) => {
535
- writeNewConfig({
536
- scope: input.scope || "workspace",
537
- patch: {
538
- osBaseUrl: input.osBaseUrl,
539
- daemonBaseUrl: input.daemonBaseUrl,
540
- adminPasswordEnvVarName: input.adminPasswordEnvVarName,
541
- userEmail: input.userEmail,
542
- },
543
- workspacePath: process.cwd(),
544
- });
545
-
546
- const current = readAuthConfig(process.cwd());
547
- if (current instanceof Error) throw current;
548
- return { configPath: CONFIG_PATH, current };
549
- }),
550
-
551
- whoami: t.procedure.mutation(async () => {
552
- const authConfig = readAuthConfig(process.cwd());
553
- if (authConfig instanceof Error) throw authConfig;
554
- const { userClient } = await osAuthDance(authConfig);
555
- return await userClient.getSession();
556
- }),
557
- };
558
-
559
- const runCli = async () => {
560
- const authConfig = readAuthConfig(process.cwd());
561
-
562
- /** @type {(problem: string) => (e: Error) => {}} */
563
- const errorProcedure = (problem) => (e) => {
564
- const message = `${problem}: ${e.message}`;
565
- return t.procedure.meta({ description: message }).mutation(() => {
566
- throw new Error(problem, { cause: e });
567
- });
568
- };
569
-
570
- /** @type {import("@trpc/server").AnyRouter[]} */
571
- const routers = [t.router(launcherProcedures)];
572
-
573
- if (authConfig instanceof Error) {
574
- routers.push(
575
- t.router({
576
- os: errorProcedure(`Invalid auth config`)(authConfig),
577
- daemon: errorProcedure(`Invalid auth config`)(authConfig),
578
- }),
579
- );
580
- } else {
581
- const [osProcedures, daemonProcedures] = await Promise.allSettled([
582
- getOsProcedures({ baseUrl: authConfig.osBaseUrl }),
583
- getDaemonProcedures({ daemonBaseUrl: authConfig.daemonBaseUrl }),
584
- ]);
585
-
586
- if (osProcedures.status === "fulfilled") {
587
- routers.push(t.router({ os: osProcedures.value }));
588
- } else {
589
- routers.push(
590
- t.router({
591
- os: errorProcedure(`Couldn't connect to os at ${authConfig.osBaseUrl}`)(
592
- osProcedures.reason,
593
- ),
594
- }),
595
- );
596
- }
597
- if (daemonProcedures.status === "fulfilled") {
598
- // don't nest daemon procedures under "daemon"
599
- routers.push(daemonProcedures.value);
600
- } else {
601
- routers.push(
602
- t.router({
603
- daemon: errorProcedure(`Couldn't connect to daemon at ${authConfig.daemonBaseUrl}`)(
604
- daemonProcedures.reason,
605
- ),
606
- }),
607
- );
608
- }
609
- }
610
-
611
- const router = t.mergeRouters(...routers);
612
-
613
- const cli = createCli({
614
- router,
615
- name: "iterate",
616
- version: "0.0.1",
617
- description: "Iterate CLI",
618
- });
619
-
620
- await cli.run({
621
- prompts: isAgent ? undefined : prompts,
622
- });
623
- };
624
-
625
- const main = async () => {
67
+ const localModule = findLocalModule();
68
+ if (localModule) {
69
+ const { runCli } = await import(localModule);
626
70
  await runCli();
627
- };
628
-
629
- main().catch((error) => {
630
- console.error(error);
631
- process.exit(1);
632
- });
71
+ } else {
72
+ // No delegation — run our own copy.
73
+ // In monorepo dev: src/index.ts exists. Published: dist/index.js exists.
74
+ const srcPath = join(pkgRoot, "src/index.ts");
75
+ const distPath = join(pkgRoot, "dist/index.js");
76
+ const modulePath = existsSync(srcPath) ? srcPath : distPath;
77
+ const { runCli } = await import(modulePath);
78
+ await runCli();
79
+ }
package/dist/cli.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import * as prompts from "@clack/prompts";
2
+ export declare const getCli: () => Promise<{
3
+ cli: import("trpc-cli").TrpcCli;
4
+ prompts: typeof prompts | undefined;
5
+ }>;
6
+ export declare const runCli: () => Promise<void>;
7
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AA4b1C,eAAO,MAAM,MAAM;;;EA4DlB,CAAC;AAEF,eAAO,MAAM,MAAM,qBAGlB,CAAC"}
package/dist/cli.js ADDED
@@ -0,0 +1,430 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { dirname, join } from "node:path";
4
+ import process from "node:process";
5
+ import * as prompts from "@clack/prompts";
6
+ import { createTRPCClient, httpLink } from "@trpc/client";
7
+ import { initTRPC } from "@trpc/server";
8
+ import { createAuthClient } from "better-auth/client";
9
+ import { adminClient } from "better-auth/client/plugins";
10
+ import superjson from "superjson";
11
+ import { createCli } from "trpc-cli";
12
+ import { proxify } from "trpc-cli/dist/proxify.js";
13
+ import { z } from "zod/v4";
14
+ const XDG_CONFIG_PARENT = join(process.env.XDG_CONFIG_HOME ? process.env.XDG_CONFIG_HOME : join(homedir(), ".config"), "iterate");
15
+ const XDG_CONFIG_PATH = join(XDG_CONFIG_PARENT, "config.json");
16
+ const CONFIG_PATH = XDG_CONFIG_PATH;
17
+ const SetupInput = z.object({
18
+ osBaseUrl: z
19
+ .string()
20
+ .describe(`Base URL for OS API (for example https://dev-yourname-os.dev.iterate.com)`),
21
+ daemonBaseUrl: z.string().describe(`Base URL for daemon API (for example http://localhost:3001)`),
22
+ adminPasswordEnvVarName: z.string().describe("Env var name containing admin password"),
23
+ userEmail: z.string().describe("User email to impersonate for OS calls"),
24
+ scope: z.enum(["workspace", "global"]).describe("Where to store launcher config"),
25
+ });
26
+ const AuthConfig = z.object({
27
+ osBaseUrl: z.string(),
28
+ daemonBaseUrl: z.string(),
29
+ adminPasswordEnvVarName: z.string(),
30
+ userEmail: z.string(),
31
+ });
32
+ const ConfigFile = z.object({
33
+ global: AuthConfig.partial().optional(),
34
+ workspaces: z.record(z.string(), AuthConfig).optional(),
35
+ /** a place where I put old/invalid configs I can't quite let go of */
36
+ rubbish: z.unknown().optional(),
37
+ });
38
+ const isAgent = process.env.AGENT === "1" ||
39
+ process.env.OPENCODE === "1" ||
40
+ Boolean(process.env.OPENCODE_SESSION) ||
41
+ Boolean(process.env.CLAUDE_CODE);
42
+ const t = initTRPC.meta().create();
43
+ const readConfigFile = () => {
44
+ if (!existsSync(CONFIG_PATH)) {
45
+ return {};
46
+ }
47
+ const rawText = readFileSync(CONFIG_PATH, "utf8");
48
+ let parsed;
49
+ try {
50
+ parsed = JSON.parse(rawText);
51
+ }
52
+ catch (error) {
53
+ const detail = error instanceof Error ? error.message : String(error);
54
+ throw new Error(`Invalid JSON in ${CONFIG_PATH}: ${detail}`);
55
+ }
56
+ return parsed;
57
+ };
58
+ const getMergedWorkspaceConfig = (configFile, workspacePath) => {
59
+ const configs = [];
60
+ while (workspacePath && workspacePath !== "/") {
61
+ if (workspacePath in (configFile.workspaces || {})) {
62
+ configs.push(configFile.workspaces?.[workspacePath]);
63
+ }
64
+ workspacePath = dirname(workspacePath);
65
+ }
66
+ configs.push(configFile.global);
67
+ return configs.reverse().reduce((acc, config) => {
68
+ return { ...acc, ...config };
69
+ }, {});
70
+ };
71
+ const writeNewConfig = ({ patch, scope, workspacePath, }) => {
72
+ patch = Object.fromEntries(Object.entries(patch || {}).filter(([_key, value]) => value !== undefined));
73
+ const configFile = readConfigFile();
74
+ const cloned = structuredClone(configFile);
75
+ if (scope === "global") {
76
+ cloned.global = { ...configFile.global, ...patch };
77
+ }
78
+ if (scope === "workspace" && workspacePath) {
79
+ cloned.workspaces ||= {};
80
+ cloned.workspaces[workspacePath] = {
81
+ ...configFile.workspaces?.[workspacePath],
82
+ ...patch,
83
+ };
84
+ }
85
+ const parsed = ConfigFile.safeParse(cloned);
86
+ if (!parsed.success) {
87
+ throw new Error(`Invalid config file: ${z.prettifyError(parsed.error)}`);
88
+ }
89
+ mkdirSync(dirname(CONFIG_PATH), { recursive: true });
90
+ writeFileSync(CONFIG_PATH, `${JSON.stringify(parsed.data, null, 2)}\n`);
91
+ return cloned;
92
+ };
93
+ const readAuthConfig = (workspacePath) => {
94
+ const configFile = readConfigFile();
95
+ const mergedConfig = getMergedWorkspaceConfig(configFile, workspacePath);
96
+ const parsed = AuthConfig.safeParse(mergedConfig);
97
+ if (!parsed.success) {
98
+ return new Error(`Invalid auth config for ${workspacePath} (in config file ${CONFIG_PATH}). Have you run \`iterate setup\`?\n${z.prettifyError(parsed.error)}`);
99
+ }
100
+ return parsed.data;
101
+ };
102
+ const setCookiesToCookieHeader = (setCookies) => {
103
+ const byName = new Map();
104
+ for (const c of setCookies ?? []) {
105
+ const pair = c.split(";")[0]?.trim();
106
+ if (!pair)
107
+ continue;
108
+ const eq = pair.indexOf("=");
109
+ if (eq === -1)
110
+ continue;
111
+ byName.set(pair.slice(0, eq), pair.slice(eq + 1));
112
+ }
113
+ return [...byName.entries()].map(([k, v]) => `${k}=${v}`).join("; ");
114
+ };
115
+ const impersonationUserIdCache = new Map();
116
+ const resolveImpersonationUserId = async ({ superadminAuthClient, userEmail, baseUrl, }) => {
117
+ const normalizedEmail = userEmail.trim().toLowerCase();
118
+ const cacheKey = `${baseUrl}::${normalizedEmail}`;
119
+ const cachedUserId = impersonationUserIdCache.get(cacheKey);
120
+ if (cachedUserId) {
121
+ return cachedUserId;
122
+ }
123
+ let users = [];
124
+ try {
125
+ const result = await superadminAuthClient.admin.listUsers({
126
+ query: {
127
+ filterField: "email",
128
+ filterOperator: "eq",
129
+ filterValue: normalizedEmail,
130
+ limit: 10,
131
+ },
132
+ fetchOptions: {
133
+ throw: true,
134
+ },
135
+ });
136
+ users = Array.isArray(result?.users) ? result.users : [];
137
+ }
138
+ catch {
139
+ const result = await superadminAuthClient.admin.listUsers({
140
+ query: {
141
+ searchField: "email",
142
+ searchOperator: "contains",
143
+ searchValue: normalizedEmail,
144
+ limit: 100,
145
+ },
146
+ fetchOptions: {
147
+ throw: true,
148
+ },
149
+ });
150
+ users = Array.isArray(result?.users) ? result.users : [];
151
+ }
152
+ const exactMatches = users.filter((user) => user &&
153
+ typeof user === "object" &&
154
+ "email" in user &&
155
+ typeof user.email === "string" &&
156
+ user.email.toLowerCase() === normalizedEmail &&
157
+ "id" in user &&
158
+ typeof user.id === "string");
159
+ if (exactMatches.length === 0) {
160
+ throw new Error(`No user found with email ${userEmail}`);
161
+ }
162
+ if (exactMatches.length > 1) {
163
+ throw new Error(`Multiple users found with email ${userEmail}`);
164
+ }
165
+ const resolvedUserId = exactMatches[0].id;
166
+ impersonationUserIdCache.set(cacheKey, resolvedUserId);
167
+ return resolvedUserId;
168
+ };
169
+ const osAuthDance = async (authConfig) => {
170
+ let superadminSetCookie;
171
+ const authClient = createAuthClient({
172
+ baseURL: authConfig.osBaseUrl,
173
+ fetchOptions: {
174
+ throw: true,
175
+ },
176
+ });
177
+ const password = process.env[authConfig.adminPasswordEnvVarName];
178
+ if (!password) {
179
+ throw new Error(`Password not found in env var ${authConfig.adminPasswordEnvVarName}`);
180
+ }
181
+ await authClient.signIn.email({
182
+ email: "superadmin@nustom.com",
183
+ password,
184
+ fetchOptions: {
185
+ throw: true,
186
+ onResponse: (ctx) => {
187
+ superadminSetCookie = ctx.response.headers.getSetCookie();
188
+ },
189
+ },
190
+ });
191
+ const superadminAuthClient = createAuthClient({
192
+ baseURL: authConfig.osBaseUrl,
193
+ fetchOptions: {
194
+ throw: true,
195
+ onRequest: (ctx) => {
196
+ ctx.headers.set("origin", authConfig.osBaseUrl);
197
+ ctx.headers.set("cookie", setCookiesToCookieHeader(superadminSetCookie));
198
+ },
199
+ },
200
+ plugins: [adminClient()],
201
+ });
202
+ const userId = await resolveImpersonationUserId({
203
+ superadminAuthClient,
204
+ userEmail: authConfig.userEmail,
205
+ baseUrl: authConfig.osBaseUrl,
206
+ });
207
+ let impersonateSetCookie;
208
+ await superadminAuthClient.admin.impersonateUser({
209
+ userId,
210
+ fetchOptions: {
211
+ throw: true,
212
+ onResponse: (ctx) => {
213
+ impersonateSetCookie = ctx.response.headers.getSetCookie();
214
+ },
215
+ },
216
+ });
217
+ const userCookies = setCookiesToCookieHeader(impersonateSetCookie);
218
+ const userClient = createAuthClient({
219
+ baseURL: authConfig.osBaseUrl,
220
+ fetchOptions: {
221
+ throw: true,
222
+ onRequest: (ctx) => {
223
+ ctx.headers.set("origin", authConfig.osBaseUrl);
224
+ ctx.headers.set("cookie", userCookies);
225
+ },
226
+ },
227
+ });
228
+ return { userCookies, userClient };
229
+ };
230
+ const loadAppRouter = async (params) => {
231
+ const url = `${params.baseUrl}/api/trpc-cli-procedures`;
232
+ const response = await fetch(url);
233
+ if (!response.ok) {
234
+ throw new Error(`${url} got ${response.status}: ${await response.text()}`);
235
+ }
236
+ let router;
237
+ try {
238
+ router = await response.json();
239
+ }
240
+ catch (e) {
241
+ const message = e instanceof Error ? e.message : String(e);
242
+ throw new Error(`${url} returned invalid router: ${message}`);
243
+ }
244
+ if (!Array.isArray(router?.procedures)) {
245
+ throw new Error(`${url} returned invalid router: ${JSON.stringify(router)}`);
246
+ }
247
+ return router;
248
+ };
249
+ const getOsProcedures = async (params) => {
250
+ const appRouter = await loadAppRouter(params);
251
+ const proxiedRouter = proxify(appRouter.procedures, async () => {
252
+ return createTRPCClient({
253
+ links: [
254
+ httpLink({
255
+ url: `${params.baseUrl}/api/trpc/`,
256
+ transformer: superjson,
257
+ fetch: async (request, init) => {
258
+ const authConfig = readAuthConfig(process.cwd());
259
+ if (authConfig instanceof Error)
260
+ throw authConfig;
261
+ const { userCookies } = await osAuthDance(authConfig);
262
+ const headers = new Headers(init?.headers);
263
+ headers.set("cookie", userCookies);
264
+ return fetch(request, { ...init, headers });
265
+ },
266
+ }),
267
+ ],
268
+ });
269
+ });
270
+ return proxiedRouter;
271
+ };
272
+ /**
273
+ * Creates a fetch wrapper that calls /api/trpc-stream/* instead of /api/trpc/*.
274
+ * The streaming endpoint returns SSE: log lines as `event: log` and the final
275
+ * tRPC response as `event: response`, which we reassemble into a normal Response.
276
+ */
277
+ const streamingFetch = (daemonBaseUrl) => {
278
+ return async (input, init) => {
279
+ // Rewrite URL from /api/trpc/X to /api/trpc-stream/X
280
+ const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
281
+ const rewritten = url.replace(`${daemonBaseUrl}/api/trpc/`, `${daemonBaseUrl}/api/trpc-stream/`);
282
+ const res = await fetch(rewritten, init);
283
+ if (rewritten === url)
284
+ return res;
285
+ const contentType = res.headers.get("content-type") || "";
286
+ // If the daemon didn't respond with SSE, pass through as-is (non-streaming endpoint)
287
+ if (!contentType.includes("text/event-stream"))
288
+ return res;
289
+ // Parse SSE stream: print log events to stderr, collect the final response
290
+ const reader = res.body?.getReader();
291
+ if (!reader)
292
+ return res;
293
+ const decoder = new TextDecoder();
294
+ let buffer = "";
295
+ let responseBody = null;
296
+ while (true) {
297
+ const { done, value } = await reader.read();
298
+ if (done)
299
+ break;
300
+ buffer += decoder.decode(value, { stream: true });
301
+ // Process complete SSE messages (double newline delimited)
302
+ const parts = buffer.split("\n\n");
303
+ buffer = parts.pop() || "";
304
+ for (const part of parts) {
305
+ const lines = part.split("\n");
306
+ const event = lines[0].split(": ")[1];
307
+ const data = lines[1].split(": ").slice(1).join(": ");
308
+ if (event === "log") {
309
+ const detail = JSON.parse(data);
310
+ console[detail.level](...detail.args);
311
+ }
312
+ else if (event === "response") {
313
+ responseBody = data;
314
+ }
315
+ }
316
+ }
317
+ // Reconstruct a normal Response from the final payload so tRPC client is happy
318
+ return new Response(responseBody, {
319
+ status: res.status,
320
+ headers: { "content-type": "application/json" },
321
+ });
322
+ };
323
+ };
324
+ const getDaemonProcedures = async (params) => {
325
+ const daemonRouter = await loadAppRouter({ baseUrl: params.daemonBaseUrl });
326
+ const proxiedRouter = proxify(daemonRouter.procedures, async () => {
327
+ return createTRPCClient({
328
+ links: [
329
+ httpLink({
330
+ url: `${params.daemonBaseUrl}/api/trpc/`,
331
+ fetch: streamingFetch(params.daemonBaseUrl),
332
+ }),
333
+ ],
334
+ });
335
+ });
336
+ return proxiedRouter;
337
+ };
338
+ const launcherProcedures = {
339
+ doctor: t.procedure
340
+ .meta({ description: "Show launcher config and resolved runtime options" })
341
+ .mutation(async () => {
342
+ const configFile = readConfigFile();
343
+ const parsed = ConfigFile.safeParse(configFile);
344
+ if (!parsed.success) {
345
+ throw new Error(`Invalid config file ${CONFIG_PATH}: ${z.prettifyError(parsed.error)}`);
346
+ }
347
+ const current = readAuthConfig(process.cwd());
348
+ if (current instanceof Error)
349
+ throw current;
350
+ return { configPath: CONFIG_PATH, current };
351
+ }),
352
+ setup: t.procedure
353
+ .input(SetupInput.partial())
354
+ .meta({ prompt: true, description: "Configure auth + launcher defaults for current workspace" })
355
+ .mutation(async ({ input }) => {
356
+ writeNewConfig({
357
+ scope: input.scope || "workspace",
358
+ patch: {
359
+ osBaseUrl: input.osBaseUrl,
360
+ daemonBaseUrl: input.daemonBaseUrl,
361
+ adminPasswordEnvVarName: input.adminPasswordEnvVarName,
362
+ userEmail: input.userEmail,
363
+ },
364
+ workspacePath: process.cwd(),
365
+ });
366
+ const current = readAuthConfig(process.cwd());
367
+ if (current instanceof Error)
368
+ throw current;
369
+ return { configPath: CONFIG_PATH, current };
370
+ }),
371
+ whoami: t.procedure.mutation(async () => {
372
+ const authConfig = readAuthConfig(process.cwd());
373
+ if (authConfig instanceof Error)
374
+ throw authConfig;
375
+ const { userClient } = await osAuthDance(authConfig);
376
+ return await userClient.getSession();
377
+ }),
378
+ };
379
+ export const getCli = async () => {
380
+ const authConfig = readAuthConfig(process.cwd());
381
+ const errorProcedure = (problem) => (e) => {
382
+ const message = `${problem}: ${e.message}`;
383
+ return t.procedure.meta({ description: message }).mutation(() => {
384
+ throw new Error(problem, { cause: e });
385
+ });
386
+ };
387
+ const routers = [t.router(launcherProcedures)];
388
+ if (authConfig instanceof Error) {
389
+ routers.push(t.router({
390
+ os: errorProcedure(`Invalid auth config`)(authConfig),
391
+ daemon: errorProcedure(`Invalid auth config`)(authConfig),
392
+ }));
393
+ }
394
+ else {
395
+ const [osProcedures, daemonProcedures] = await Promise.allSettled([
396
+ getOsProcedures({ baseUrl: authConfig.osBaseUrl }),
397
+ getDaemonProcedures({ daemonBaseUrl: authConfig.daemonBaseUrl }),
398
+ ]);
399
+ if (osProcedures.status === "fulfilled") {
400
+ routers.push(t.router({ os: osProcedures.value }));
401
+ }
402
+ else {
403
+ routers.push(t.router({
404
+ os: errorProcedure(`Couldn't connect to os at ${authConfig.osBaseUrl}`)(osProcedures.reason),
405
+ }));
406
+ }
407
+ if (daemonProcedures.status === "fulfilled") {
408
+ // don't nest daemon procedures under "daemon"
409
+ routers.push(daemonProcedures.value);
410
+ }
411
+ else {
412
+ routers.push(t.router({
413
+ daemon: errorProcedure(`Couldn't connect to daemon at ${authConfig.daemonBaseUrl}`)(daemonProcedures.reason),
414
+ }));
415
+ }
416
+ }
417
+ const router = t.mergeRouters(...routers);
418
+ const cli = createCli({
419
+ router,
420
+ name: "iterate",
421
+ version: "0.0.1",
422
+ description: "Iterate CLI",
423
+ });
424
+ return { cli, prompts: isAgent ? undefined : prompts };
425
+ };
426
+ export const runCli = async () => {
427
+ const { cli, prompts: cliPrompts } = await getCli();
428
+ await cli.run({ prompts: cliPrompts });
429
+ };
430
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { getCli, runCli } from "./cli.ts";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { getCli, runCli } from "./cli.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iterate",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "CLI for iterate",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -21,18 +21,30 @@
21
21
  "engines": {
22
22
  "node": ">=22"
23
23
  },
24
- "publishConfig": {
25
- "access": "public"
26
- },
27
24
  "bin": {
28
25
  "iterate": "./bin/iterate.js"
29
26
  },
27
+ "exports": {
28
+ ".": "./src/index.ts"
29
+ },
30
+ "publishConfig": {
31
+ "access": "public",
32
+ "exports": {
33
+ ".": {
34
+ "import": "./dist/index.js",
35
+ "types": "./dist/index.d.ts"
36
+ }
37
+ }
38
+ },
30
39
  "files": [
31
40
  "bin",
41
+ "dist",
32
42
  "README.md"
33
43
  ],
34
44
  "scripts": {
35
- "typecheck": "node --check ./bin/iterate.js"
45
+ "build": "tsgo",
46
+ "typecheck": "tsgo --noEmit",
47
+ "prepack": "pnpm build"
36
48
  },
37
49
  "dependencies": {
38
50
  "@clack/prompts": "^1.0.0",
@@ -42,5 +54,8 @@
42
54
  "superjson": "^2.2.2",
43
55
  "trpc-cli": "0.12.4",
44
56
  "zod": "4.1.12"
57
+ },
58
+ "devDependencies": {
59
+ "@types/node": "^22.0.0"
45
60
  }
46
61
  }