@iqlabs-official/iq-git-cli 0.1.1 → 0.1.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.
package/README.md CHANGED
@@ -52,15 +52,18 @@ public repo without setting up a wallet first.
52
52
  ### Changing the RPC URL later
53
53
 
54
54
  ```bash
55
- iqgit config rpcUrl # show current value
56
- iqgit config rpcUrl https://my-rpc.example # set a new one
57
- iqgit config --unset rpcUrl # reset (will re-prompt)
55
+ iqgit config rpcUrl # show current value
56
+ iqgit config rpcUrl 'https://my-rpc.example' # set a new one
57
+ iqgit config --unset rpcUrl # reset (will re-prompt)
58
58
  ```
59
59
 
60
+ Quote the URL — if it contains `?` (e.g. an API-key query string), an
61
+ unquoted URL makes zsh try to glob it and fail with `no matches found:`.
62
+
60
63
  You can also override per-command via environment variable:
61
64
 
62
65
  ```bash
63
- SOLANA_RPC_ENDPOINT=https://my-rpc.example iqgit log
66
+ SOLANA_RPC_ENDPOINT='https://my-rpc.example' iqgit log
64
67
  ```
65
68
 
66
69
  ## Gateway
package/dist/cli.js CHANGED
@@ -914,7 +914,7 @@ function register12(program2) {
914
914
  Examples:
915
915
  iqgit config list all
916
916
  iqgit config rpcUrl print current RPC URL
917
- iqgit config rpcUrl https://my-rpc.example change RPC URL
917
+ iqgit config rpcUrl "https://my-rpc.example" change RPC URL
918
918
  iqgit config --unset rpcUrl reset (re-prompts next run)`).option("--unset <key>").action((key, value, opts) => {
919
919
  const cfg = readGlobalConfig();
920
920
  if (opts.unset) {
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/commands/init.ts","../src/core/repo.ts","../src/ui.ts","../src/commands/create.ts","../src/setup.ts","../src/commands/add.ts","../src/core/scan.ts","../src/commands/reset.ts","../src/commands/commit.ts","../src/core/tree.ts","../src/core/gateway.ts","../src/commands/push.ts","../src/commands/clone.ts","../src/commands/restore.ts","../src/commands/log.ts","../src/commands/status.ts","../src/commands/registry.ts","../src/commands/config.ts","../src/commands/wallet.ts"],"sourcesContent":["// Entry point. Wires commander, registers every command in `commands/`,\n// and dispatches to them. The only file that touches process.argv directly.\n//\n// SDK dependency: \"@iqlabs-official/git-sdk\" >= 0.1.4\n// 0.1.4 is the first version that re-exports the write-side layer fns\n// (uploadBlob, uploadTree, writeCommit) which push.ts depends on.\n\nimport { Command } from \"commander\";\nimport { register as initCmd } from \"./commands/init\";\nimport { register as createCmd } from \"./commands/create\";\nimport { register as addCmd } from \"./commands/add\";\nimport { register as resetCmd } from \"./commands/reset\";\nimport { register as commitCmd } from \"./commands/commit\";\nimport { register as pushCmd } from \"./commands/push\";\nimport { register as cloneCmd } from \"./commands/clone\";\nimport { register as restoreCmd } from \"./commands/restore\";\nimport { register as logCmd } from \"./commands/log\";\nimport { register as statusCmd } from \"./commands/status\";\nimport { register as registryCmd } from \"./commands/registry\";\nimport { register as configCmd } from \"./commands/config\";\nimport { register as walletCmd } from \"./commands/wallet\";\n\nconst program = new Command(\"iqgit\")\n .description(\"On-chain Git for Solana\")\n .version(\"0.1.0\");\n\ninitCmd(program);\ncreateCmd(program);\naddCmd(program);\nresetCmd(program);\ncommitCmd(program);\npushCmd(program);\ncloneCmd(program);\nrestoreCmd(program);\nlogCmd(program);\nstatusCmd(program);\nregistryCmd(program);\nconfigCmd(program);\nwalletCmd(program);\n\nprogram.parseAsync(process.argv);\n","// `iqgit init` — local-only. Creates .iqgit/ skeleton. Does NOT touch\n// chain. Mirror of `git init`.\n//\n// in: optionally `--name <repo>` `--public|--private`\n// sdk: (none)\n// out: prints next-step hint about `iqgit create`\n//\n// Why no auto-create on init: chain writes cost SOL. We want users to\n// explicitly opt in via `iqgit create` so the first transaction is\n// never a surprise.\n//\n// Stub config: we write .iqgit/config.json with empty `owner` so that\n// `iqgit add`, `iqgit commit`, `iqgit status` work against the local\n// pending state without an ENOENT crash. The empty owner is the gate\n// commit.ts already checks — it triggers the friendly \"run iqgit create\n// first\" message at the right time.\n\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { Command } from \"commander\";\nimport * as repo from \"../core/repo\";\nimport * as ui from \"../ui\";\n\nexport function register(program: Command): void {\n program\n .command(\"init\")\n .option(\"--name <name>\", \"repository name\")\n .option(\"--public\", \"default visibility\")\n .option(\"--private\")\n .action((opts: { name?: string; public?: boolean; private?: boolean }) => {\n const cwd = process.cwd();\n if (existsSync(join(cwd, \".iqgit\"))) ui.fail(\"already an iqgit repo\");\n repo.initRepo(cwd);\n repo.writeConfig(cwd, {\n owner: \"\",\n repo: opts.name ?? \"\",\n isPublic: !opts.private,\n });\n ui.log.success(\"Initialized empty iqgit repo in .iqgit/\");\n ui.log.dim(\"Next: iqgit create <name> [--public|--private]\");\n });\n}\n","// All .iqgit/ disk I/O lives here. One file, function-prefixed by concern,\n// because all four pieces (config / HEAD / pending / cache) are tiny JSON\n// reads/writes that share the same root path resolution. Splitting them\n// would be premature (CODE-RULES §1).\n//\n// Layout this file owns (per repo):\n//\n// <repoRoot>/.iqgit/\n// ├── config.json { owner, repo, isPublic }\n// ├── HEAD last successfully-pushed commitId (utf8)\n// ├── index.json string[] — paths staged for the next commit\n// ├── pending/\n// │ └── NNN-<commitId>/\n// │ ├── meta.json { id, message, parentCommitId, timestamp,\n// │ │ author, treeTxId|null, committedSig|null }\n// │ ├── tree.json { [path]: { hash, size } } ← size for stats\n// │ └── blobs/<hash> raw base64 content (push reads from here)\n// └── upload-cache.json { [hash]: { txId, uploadedAt } }\n//\n// CRITICAL: every cache mutation flushes synchronously. Process kill\n// during push must leave a recoverable state. Don't batch writes here.\n\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n readdirSync,\n renameSync,\n rmSync,\n writeFileSync,\n} from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\nconst DIR = \".iqgit\";\n\nexport interface RepoConfig {\n owner: string;\n repo: string;\n isPublic: boolean;\n}\n\nexport interface PendingMeta {\n id: string;\n message: string;\n parentCommitId: string | null;\n timestamp: number;\n author: string;\n treeTxId: string | null;\n committedSig: string | null;\n}\n\nexport interface PendingCommit {\n dir: string;\n seq: number;\n meta: PendingMeta;\n}\n\nexport interface CacheEntry {\n txId: string;\n uploadedAt: number;\n}\n\n// === bootstrap / discovery ===\n\nexport function findRepoRoot(cwd = process.cwd()): string {\n let dir = cwd;\n while (true) {\n if (existsSync(join(dir, DIR))) return dir;\n const parent = dirname(dir);\n if (parent === dir) {\n throw new Error(\"not an iqgit repo (or any parent)\");\n }\n dir = parent;\n }\n}\n\nexport function initRepo(cwd: string): void {\n mkdirSync(join(cwd, DIR, \"pending\"), { recursive: true });\n}\n\n// === config.json ===\n\nexport function readConfig(repoRoot: string): RepoConfig {\n // Defensive: pre-fix repos may lack config.json. Return defaults so\n // `add` / `status` / `commit` give the friendly \"run iqgit create first\"\n // message via commit.ts:41 instead of an ENOENT stack trace.\n try {\n return JSON.parse(readFileSync(join(repoRoot, DIR, \"config.json\"), \"utf8\")) as RepoConfig;\n } catch {\n return { owner: \"\", repo: \"\", isPublic: true };\n }\n}\n\nexport function writeConfig(repoRoot: string, cfg: RepoConfig): void {\n writeFileSync(join(repoRoot, DIR, \"config.json\"), JSON.stringify(cfg, null, 2));\n}\n\n// === HEAD ===\n\nexport function readHead(repoRoot: string): string | null {\n try {\n return readFileSync(join(repoRoot, DIR, \"HEAD\"), \"utf8\").trim() || null;\n } catch {\n return null;\n }\n}\n\nexport function writeHead(repoRoot: string, commitId: string): void {\n writeFileSync(join(repoRoot, DIR, \"HEAD\"), commitId);\n}\n\n// === index.json ===\n//\n// Set of staged paths for the next commit. Stored as a plain string[] —\n// order doesn't matter, and a Set serialized as sorted array keeps diffs\n// readable for anyone who peeks at the file.\n\nexport function readIndex(repoRoot: string): string[] {\n try {\n return JSON.parse(readFileSync(join(repoRoot, DIR, \"index.json\"), \"utf8\")) as string[];\n } catch {\n return [];\n }\n}\n\nexport function writeIndex(repoRoot: string, paths: string[]): void {\n const sorted = Array.from(new Set(paths)).sort();\n writeFileSync(join(repoRoot, DIR, \"index.json\"), JSON.stringify(sorted, null, 2));\n}\n\n// === pending ===\n\nexport function listPending(repoRoot: string): PendingCommit[] {\n const dir = join(repoRoot, DIR, \"pending\");\n if (!existsSync(dir)) return [];\n return readdirSync(dir, { withFileTypes: true })\n .filter((e) => e.isDirectory())\n .map((e) => {\n const seqStr = e.name.split(\"-\")[0];\n if (!seqStr) throw new Error(`malformed pending dir: ${e.name}`);\n const dirPath = join(dir, e.name);\n return {\n dir: dirPath,\n seq: Number(seqStr),\n meta: JSON.parse(readFileSync(join(dirPath, \"meta.json\"), \"utf8\")) as PendingMeta,\n };\n })\n .sort((a, b) => a.seq - b.seq);\n}\n\n// blobs is hash → base64. Caller (commit.ts) builds it from a ScanFile[]\n// where Map deduplication already collapsed identical-content files.\nexport function appendPending(\n repoRoot: string,\n meta: PendingMeta,\n tree: Record<string, { hash: string; size: number }>,\n blobs: Map<string, string>,\n): PendingCommit {\n const existing = listPending(repoRoot);\n const seq = (existing[existing.length - 1]?.seq ?? 0) + 1;\n const seqStr = String(seq).padStart(3, \"0\");\n const dir = join(repoRoot, DIR, \"pending\", `${seqStr}-${meta.id}`);\n mkdirSync(join(dir, \"blobs\"), { recursive: true });\n writeFileSync(join(dir, \"meta.json\"), JSON.stringify(meta, null, 2));\n writeFileSync(join(dir, \"tree.json\"), JSON.stringify(tree, null, 2));\n for (const [hash, base64] of blobs) {\n writeFileSync(join(dir, \"blobs\", hash), base64);\n }\n return { dir, seq, meta };\n}\n\n// Atomic-ish meta update. Write to .tmp then rename — survives process kill\n// mid-update. Used to checkpoint treeTxId / committedSig during push.\nexport function updatePendingMeta(p: PendingCommit, patch: Partial<PendingMeta>): void {\n const next = { ...p.meta, ...patch };\n const target = join(p.dir, \"meta.json\");\n const tmp = `${target}.tmp`;\n writeFileSync(tmp, JSON.stringify(next, null, 2));\n renameSync(tmp, target);\n p.meta = next;\n}\n\nexport function readPendingTree(p: PendingCommit): Record<string, { hash: string; size: number }> {\n return JSON.parse(readFileSync(join(p.dir, \"tree.json\"), \"utf8\")) as Record<\n string,\n { hash: string; size: number }\n >;\n}\n\nexport function readPendingBlob(p: PendingCommit, hash: string): string {\n return readFileSync(join(p.dir, \"blobs\", hash), \"utf8\");\n}\n\nexport function discardPending(p: PendingCommit): void {\n rmSync(p.dir, { recursive: true, force: true });\n}\n\n// === upload-cache.json ===\n//\n// Per-repo (under .iqgit/), not global — keeps repos self-contained,\n// simpler to reason about, and cross-repo dedup wasn't a stated need.\n// In-memory cache loaded lazily; every set() rewrites the whole file\n// synchronously so a process kill leaves the latest entry on disk.\n\nconst cacheMem = new Map<string, Record<string, CacheEntry>>();\n\nexport function cacheGet(repoRoot: string, hash: string): CacheEntry | null {\n return loadCache(repoRoot)[hash] ?? null;\n}\n\nexport function cacheSet(repoRoot: string, hash: string, entry: CacheEntry): void {\n const c = loadCache(repoRoot);\n c[hash] = entry;\n writeFileSync(cachePath(repoRoot), JSON.stringify(c, null, 2));\n}\n\nfunction cachePath(repoRoot: string): string {\n return join(repoRoot, DIR, \"upload-cache.json\");\n}\n\nfunction loadCache(repoRoot: string): Record<string, CacheEntry> {\n const cached = cacheMem.get(repoRoot);\n if (cached) return cached;\n let parsed: Record<string, CacheEntry> = {};\n try {\n parsed = JSON.parse(readFileSync(cachePath(repoRoot), \"utf8\")) as Record<string, CacheEntry>;\n } catch {\n // absent — start empty\n }\n cacheMem.set(repoRoot, parsed);\n return parsed;\n}\n\n","// Thin display layer. chalk + ora + @inquirer/prompts wrapped behind\n// named functions so commands don't import them directly. Keeps colors\n// and prompt styles consistent across commands.\n//\n// Functions are intentionally minimal — if a command needs a one-off\n// formatter, do it inline in the command file (CODE-RULES §1: no\n// meaningless wrapper). This file only holds things used by ≥2 commands.\n\nimport { confirm as inqConfirm, input as inqInput, select as inqSelect } from \"@inquirer/prompts\";\nimport chalk from \"chalk\";\nimport ora, { type Ora } from \"ora\";\n\n// Free function (not a method) so TS narrows callers' control flow on\n// `never` return — see https://github.com/microsoft/TypeScript/issues/12825.\nexport function fail(msg: string): never {\n console.error(chalk.red(\"✗\"), msg);\n process.exit(1);\n}\n\nexport const log = {\n info(msg: string): void {\n console.log(msg);\n },\n success(msg: string): void {\n console.log(chalk.green(\"✓\"), msg);\n },\n warn(msg: string): void {\n console.log(chalk.yellow(\"⚠\"), msg);\n },\n dim(msg: string): void {\n console.log(chalk.gray(msg));\n },\n};\n\nexport function spinner(label: string): Ora {\n return ora(label);\n}\n\nexport const confirm = inqConfirm;\nexport const input = inqInput;\nexport const select = inqSelect;\n\nexport function formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / 1024 / 1024).toFixed(1)} MB`;\n}\n\n// Format: \"a3f5b2 fix login bug (2h ago)\". Caller passes a Commit-shaped\n// object; we only read the three fields we need to keep this loosely coupled.\nexport function formatCommit(c: { id: string; message: string; timestamp: number }): string {\n return `${chalk.yellow(c.id.slice(0, 7))} ${c.message} ${chalk.gray(timeAgo(c.timestamp))}`;\n}\n\nfunction timeAgo(ts: number): string {\n const s = Math.floor((Date.now() - ts) / 1000);\n if (s < 60) return `${s}s ago`;\n if (s < 3600) return `${Math.floor(s / 60)}m ago`;\n if (s < 86400) return `${Math.floor(s / 3600)}h ago`;\n return `${Math.floor(s / 86400)}d ago`;\n}\n","// `iqgit create <name> [--public|--private]` — registers the repo\n// on-chain. First chain-touching command in a repo's life.\n//\n// in: <name>, --public (default) | --private, --description\n// sdk: GitClient.createRepo({ name, description, isPublic, timestamp })\n// ↑ also pre-creates the per-repo commit table (SDK does this\n// inside createRepo so the first commit() is cheaper)\n// out: writes .iqgit/config.json with { owner, repo, isPublic }\n\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { Command } from \"commander\";\nimport * as repo from \"../core/repo\";\nimport { setup } from \"../setup\";\nimport * as ui from \"../ui\";\n\nexport function register(program: Command): void {\n program\n .command(\"create <name>\")\n .option(\"--public\", \"default visibility\")\n .option(\"--private\")\n .option(\"--description <text>\", \"\", \"\")\n .action(async (\n name: string,\n opts: { public?: boolean; private?: boolean; description: string },\n ) => {\n const cwd = process.cwd();\n if (!existsSync(join(cwd, \".iqgit\"))) repo.initRepo(cwd);\n\n const { client, signer } = await setup();\n const isPublic = !opts.private;\n\n const sp = ui.spinner(`Creating on-chain repo ${name}...`).start();\n try {\n await client.createRepo({\n name,\n description: opts.description,\n isPublic,\n timestamp: Date.now(),\n });\n sp.succeed(`Created ${signer.publicKey.toBase58()}/${name}`);\n } catch (e) {\n sp.fail((e as Error).message);\n process.exit(1);\n }\n\n repo.writeConfig(cwd, {\n owner: signer.publicKey.toBase58(),\n repo: name,\n isPublic,\n });\n\n ui.log.dim(`Next: edit files, then iqgit commit -m \"...\" && iqgit push`);\n });\n}\n","// Pre-flight gate for every write command. Read-only commands skip it\n// (clone, log, registry, restore-against-someone-else's-repo).\n//\n// Returns a ready-to-use GitClient. Centralized here so commands don't\n// duplicate wallet/RPC validation. (CODE-RULES §2 — single source of truth.)\n//\n// sdk: new GitClient({ connection, signer })\n// ↑ imported from \"@iqlabs-official/git-sdk/node\" so the\n// node:crypto SHA-256 backend is wired (required before any\n// commit/status/etc that hashes content).\n//\n// Side effects:\n// • creates ~/.iq-git/ on first run\n// • may write to ~/.iq-git/config.json (rpcUrl) and wallets/default.json\n// • may write SOLANA_RPC_ENDPOINT into ~/.iq-git/.env\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { Connection, Keypair, LAMPORTS_PER_SOL } from \"@solana/web3.js\";\nimport iqlabs from \"@iqlabs-official/solana-sdk\";\nimport { GitClient } from \"@iqlabs-official/git-sdk/node\";\nimport { config as loadEnv } from \"dotenv\";\nimport * as ui from \"./ui\";\n\nconst HOME_DIR = join(homedir(), \".iq-git\");\nconst ENV_PATH = join(HOME_DIR, \".env\");\nconst CONFIG_PATH = join(HOME_DIR, \"config.json\");\nexport const DEFAULT_WALLET = join(HOME_DIR, \"wallets\", \"default.json\");\nconst HELIUS_URL = \"https://www.helius.dev/\";\n\ninterface GlobalConfig {\n walletPath?: string;\n rpcUrl?: string;\n}\n\nexport interface SetupResult {\n client: GitClient;\n signer: Keypair;\n connection: Connection;\n}\n\nexport async function setup(): Promise<SetupResult> {\n mkdirSync(HOME_DIR, { recursive: true });\n loadEnv({ path: ENV_PATH });\n\n const signer = await loadOrCreateWallet();\n const rpcUrl = await loadOrPromptRpc();\n iqlabs.setRpcUrl(rpcUrl);\n const connection = new Connection(rpcUrl, \"confirmed\");\n await healthCheck(connection);\n await maybeWarnBalance(connection, signer);\n\n return { client: new GitClient({ connection, signer }), signer, connection };\n}\n\n// Read-only path for commands that only need to fetch from chain\n// (e.g. commit's base tree, log, registry). Skips wallet prompts AND\n// the RPC health check — when gateway is set, we may never hit the RPC,\n// so a bogus RPC URL shouldn't fail-fast. The actual RPC call (via SDK\n// fallback) will surface its own error if it ever runs.\nexport async function setupReadOnly(): Promise<Connection> {\n mkdirSync(HOME_DIR, { recursive: true });\n loadEnv({ path: ENV_PATH });\n const rpcUrl = await loadOrPromptRpc();\n iqlabs.setRpcUrl(rpcUrl);\n return new Connection(rpcUrl, \"confirmed\");\n}\n\nasync function loadOrCreateWallet(): Promise<Keypair> {\n const cfg = readGlobalConfig();\n let path = cfg.walletPath;\n\n if (!path || !existsSync(path)) {\n const choice = await ui.select({\n message: \"No Solana keypair configured. What would you like to do?\",\n choices: [\n { name: \"Generate a new keypair\", value: \"new\" as const },\n { name: \"Use an existing keypair file\", value: \"existing\" as const },\n ],\n });\n if (choice === \"new\") {\n mkdirSync(dirname(DEFAULT_WALLET), { recursive: true });\n const kp = Keypair.generate();\n writeFileSync(DEFAULT_WALLET, JSON.stringify(Array.from(kp.secretKey)));\n ui.log.success(`Created ${DEFAULT_WALLET}`);\n ui.log.info(`pubkey: ${kp.publicKey.toBase58()}`);\n writeGlobalConfig({ ...cfg, walletPath: DEFAULT_WALLET });\n return kp;\n }\n path = await ui.input({ message: \"Path to keypair JSON file:\" });\n writeGlobalConfig({ ...cfg, walletPath: path });\n }\n\n return loadKeypairFromFile(path);\n}\n\n// Single source of truth for parsing a Solana keypair JSON file. Used by\n// setup() above and wallet.ts:walletShow (CODE-RULES §2).\nexport function loadKeypairFromFile(path: string): Keypair {\n try {\n const secret = JSON.parse(readFileSync(path, \"utf8\")) as number[];\n return Keypair.fromSecretKey(Uint8Array.from(secret));\n } catch (e) {\n ui.fail(`Invalid keypair at ${path}: ${(e as Error).message}`);\n }\n}\n\nasync function loadOrPromptRpc(): Promise<string> {\n const cfg = readGlobalConfig();\n const url = process.env.SOLANA_RPC_ENDPOINT ?? cfg.rpcUrl;\n if (url) return url;\n\n ui.log.warn(\"No Solana RPC endpoint configured.\");\n ui.log.info(`Get a free RPC URL from Helius: ${HELIUS_URL}`);\n const entered = await ui.input({ message: \"Paste your RPC URL:\" });\n appendEnv(\"SOLANA_RPC_ENDPOINT\", entered);\n writeGlobalConfig({ ...cfg, rpcUrl: entered });\n return entered;\n}\n\nasync function healthCheck(connection: Connection): Promise<void> {\n try {\n await connection.getLatestBlockhash();\n } catch (e) {\n ui.fail(`RPC health check failed: ${(e as Error).message}`);\n }\n}\n\nasync function maybeWarnBalance(connection: Connection, signer: Keypair): Promise<void> {\n const lamports = await connection.getBalance(signer.publicKey);\n if (lamports >= 0.01 * LAMPORTS_PER_SOL) return;\n ui.log.warn(\n `Low balance: ${lamports / LAMPORTS_PER_SOL} SOL on ${signer.publicKey.toBase58()}`,\n );\n ui.log.dim(\"On-chain writes need SOL — fund the address before pushing.\");\n}\n\n// Exported because commands/config.ts edits the same file. Single source\n// of truth for shape + path (CODE-RULES §2).\nexport function readGlobalConfig(): GlobalConfig {\n try {\n return JSON.parse(readFileSync(CONFIG_PATH, \"utf8\")) as GlobalConfig;\n } catch {\n return {};\n }\n}\n\nexport function writeGlobalConfig(cfg: GlobalConfig): void {\n mkdirSync(HOME_DIR, { recursive: true });\n writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2));\n}\n\nfunction appendEnv(key: string, value: string): void {\n const line = `${key}=${value}\\n`;\n let existing = \"\";\n try {\n existing = readFileSync(ENV_PATH, \"utf8\");\n } catch {\n // first write\n }\n const stripped = existing\n .split(\"\\n\")\n .filter((l) => !l.startsWith(`${key}=`))\n .join(\"\\n\");\n writeFileSync(ENV_PATH, stripped.endsWith(\"\\n\") || !stripped ? stripped + line : `${stripped}\\n${line}`);\n process.env[key] = value;\n}\n","// `iqgit add <pathspec...>` — stage paths for the next commit.\n//\n// in: one or more pathspecs. \".\" stages every non-ignored file in the repo.\n// Directory args expand to every non-ignored file under them.\n// Single-file args are staged unless ignored (with a notice).\n// sdk: (none)\n// out: writes .iqgit/index.json with merged path set.\n//\n// Mirrors `git add`. The repo-wide file list comes from scan() so the same\n// ignore rules apply here as in commit/status (CODE-RULES §2).\n\nimport { existsSync, statSync } from \"node:fs\";\nimport { isAbsolute, relative, resolve, sep } from \"node:path\";\nimport type { Command } from \"commander\";\nimport * as repo from \"../core/repo\";\nimport { loadIgnore, scan } from \"../core/scan\";\nimport * as ui from \"../ui\";\n\nexport function register(program: Command): void {\n program\n .command(\"add <pathspec...>\")\n .description(\"stage paths for the next commit\")\n .action((pathspecs: string[]) => {\n const cwd = repo.findRepoRoot();\n const allPaths = scan(cwd).map((f) => f.path);\n const ig = loadIgnore(cwd);\n const collected = new Set(repo.readIndex(cwd));\n\n for (const spec of pathspecs) {\n const abs = isAbsolute(spec) ? spec : resolve(process.cwd(), spec);\n if (!existsSync(abs)) ui.fail(`path does not exist: ${spec}`);\n\n if (statSync(abs).isDirectory()) {\n const prefix = relative(cwd, abs).split(sep).join(\"/\");\n const matches = prefix === \"\"\n ? allPaths\n : allPaths.filter((p) => p === prefix || p.startsWith(`${prefix}/`));\n for (const p of matches) collected.add(p);\n } else {\n const rel = relative(cwd, abs).split(sep).join(\"/\");\n if (ig.ignores(rel)) {\n ui.log.dim(`ignored: ${rel}`);\n continue;\n }\n collected.add(rel);\n }\n }\n\n repo.writeIndex(cwd, [...collected]);\n ui.log.success(`staged ${collected.size} path(s)`);\n });\n}\n","// fs walker — the only thing the SDK can't do for us, because the SDK\n// also runs in browsers without `fs`. Produces the `Record<string, string>`\n// shape (path → base64 content) that GitClient.commit() / .status() expect.\n//\n// Reads .gitignore AND .iqgitignore (both optional, both merged via the\n// `ignore` package) plus always-ignore [\".git/\", \".iqgit/\"].\n//\n// Returns enough info that the caller (commit.ts) can warn about >1MB files\n// without re-walking. Hash is sha256(base64) — same convention as SDK\n// (storage.ts:33), so cache lookups match SDK's internal dedup.\n\nimport { createHash } from \"node:crypto\";\nimport { readdirSync, readFileSync } from \"node:fs\";\nimport { join, relative, sep } from \"node:path\";\nimport ignore, { type Ignore } from \"ignore\";\n\nexport interface ScanFile {\n path: string;\n base64: string;\n hash: string;\n size: number;\n}\n\n// Build a ScanFile from a single working-tree path. Used by `add`-driven\n// flows (commit) where the caller already knows which paths to read; the\n// full repo walk in `scan` would over-fetch.\nexport function readScanFile(repoRoot: string, repoRel: string): ScanFile {\n const buf = readFileSync(join(repoRoot, repoRel));\n const base64 = buf.toString(\"base64\");\n return {\n path: repoRel,\n base64,\n hash: createHash(\"sha256\").update(base64).digest(\"hex\"),\n size: buf.byteLength,\n };\n}\n\nexport function loadIgnore(repoRoot: string): Ignore {\n const ig = ignore().add([\".git/\", \".iqgit/\"]);\n for (const name of [\".gitignore\", \".iqgitignore\"]) {\n try {\n ig.add(readFileSync(join(repoRoot, name), \"utf8\"));\n } catch {\n // file absent — fine\n }\n }\n return ig;\n}\n\nexport function scan(repoRoot: string): ScanFile[] {\n const out: ScanFile[] = [];\n walk(repoRoot, repoRoot, loadIgnore(repoRoot), out);\n return out;\n}\n\n// Convert ScanFile[] → Record<string,string> for SDK calls. Inlined as a\n// helper because both commit.ts and status.ts need this exact shape; not\n// worth a generic utility (CODE-RULES §1).\nexport function toScanMap(files: ScanFile[]): Record<string, string> {\n return Object.fromEntries(files.map((f) => [f.path, f.base64]));\n}\n\nfunction walk(root: string, dir: string, ig: Ignore, out: ScanFile[]): void {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const abs = join(dir, entry.name);\n const rel = relative(root, abs).split(sep).join(\"/\");\n const relForIgnore = entry.isDirectory() ? `${rel}/` : rel;\n if (ig.ignores(relForIgnore)) continue;\n\n if (entry.isDirectory()) {\n walk(root, abs, ig, out);\n continue;\n }\n if (entry.isFile()) {\n out.push(readScanFile(root, rel));\n }\n }\n}\n","// `iqgit reset [pathspec...]` — unstage paths.\n//\n// in: zero or more pathspecs. No args = clear the entire index.\n// Directory args remove every staged path under them.\n// sdk: (none)\n// out: rewrites .iqgit/index.json.\n//\n// Mirrors `git reset` (the unstaging half — we don't have HEAD-moving\n// semantics in v1).\n\nimport { isAbsolute, relative, resolve, sep } from \"node:path\";\nimport type { Command } from \"commander\";\nimport * as repo from \"../core/repo\";\nimport * as ui from \"../ui\";\n\nexport function register(program: Command): void {\n program\n .command(\"reset [pathspec...]\")\n .description(\"unstage paths (no args clears the index)\")\n .action((pathspecs: string[]) => {\n const cwd = repo.findRepoRoot();\n\n if (pathspecs.length === 0) {\n repo.writeIndex(cwd, []);\n ui.log.success(\"index cleared\");\n return;\n }\n\n const removeRels = pathspecs.map((spec) => {\n const abs = isAbsolute(spec) ? spec : resolve(process.cwd(), spec);\n return relative(cwd, abs).split(sep).join(\"/\");\n });\n\n const next = repo.readIndex(cwd).filter((p) =>\n !removeRels.some((r) => p === r || p.startsWith(`${r}/`)),\n );\n repo.writeIndex(cwd, next);\n ui.log.success(`index now has ${next.length} path(s)`);\n });\n}\n","// `iqgit commit -m \"msg\"` — LOCAL build of a snapshot, no chain WRITES.\n// Stages a pending commit under .iqgit/pending/ that push.ts will upload.\n//\n// in: -m <message> (required), --no-warn-large\n// reads (gateway-first, SDK fallback): commit history + tree blob\n// when there's a HEAD but no local pending commits — both via\n// core/tree.ts:resolveBaseTree.\n// out: appends pending/NNN-<commitId>/ with meta.json + tree.json + blobs/\n//\n// Snapshot semantics (matches git):\n// final tree = base tree, with index entries overlaid.\n// • base = last pending's tree.json (if any pending exist), else\n// loadTree(HEAD.treeTxId) (if HEAD exists), else\n// {} (first ever commit)\n// • for each indexed path:\n// file exists on disk → set tree[path] from working tree\n// file missing → delete tree[path] (= staged removal)\n//\n// Empty index = nothing to do. We do NOT auto-stage everything; the user\n// runs `iqgit add .` to opt in (matches `git commit` without -a).\n\nimport { randomUUID } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { Command } from \"commander\";\nimport * as repo from \"../core/repo\";\nimport { readScanFile } from \"../core/scan\";\nimport { resolveBaseTree, type Tree } from \"../core/tree\";\nimport { setupReadOnly } from \"../setup\";\nimport * as ui from \"../ui\";\n\nconst LARGE_FILE_THRESHOLD = 1024 * 1024;\n\nexport function register(program: Command): void {\n program\n .command(\"commit\")\n .requiredOption(\"-m, --message <msg>\", \"commit message\")\n .option(\"--no-warn-large\", \"skip 1MB confirmation prompt\")\n .action(async (opts: { message: string; warnLarge: boolean }) => {\n const cwd = repo.findRepoRoot();\n const cfg = repo.readConfig(cwd);\n if (!cfg.owner) ui.fail(\"repo not yet created on-chain — run iqgit create first\");\n\n const indexPaths = repo.readIndex(cwd);\n if (indexPaths.length === 0) {\n ui.fail(\"nothing staged — use `iqgit add <path>` first\");\n }\n\n const stagedFiles = [];\n const stagedDeletes: string[] = [];\n for (const p of indexPaths) {\n if (existsSync(join(cwd, p))) {\n stagedFiles.push(readScanFile(cwd, p));\n } else {\n stagedDeletes.push(p);\n }\n }\n\n const big = stagedFiles.filter((f) => f.size > LARGE_FILE_THRESHOLD);\n if (big.length > 0 && opts.warnLarge) {\n ui.log.warn(\"Large files (>1MB) — on-chain upload will be costly:\");\n for (const b of big) ui.log.info(` ${b.path} ${ui.formatSize(b.size)}`);\n const ok = await ui.confirm({ message: \"Include them?\" });\n if (!ok) {\n ui.log.dim(\"Tip: add to .iqgitignore to skip on-chain upload only.\");\n return;\n }\n }\n\n // Ensure SDK has an RPC configured for the gwFetchRows fallback path.\n await setupReadOnly();\n const sp = ui.spinner(\"fetching base tree from chain...\").start();\n let baseTree: Tree;\n try {\n baseTree = await resolveBaseTree(cwd, cfg.owner, cfg.repo);\n sp.succeed(\"fetched base tree\");\n } catch (e) {\n sp.fail((e as Error).message);\n throw e;\n }\n const tree: Tree = { ...baseTree };\n const blobs = new Map<string, string>();\n for (const f of stagedFiles) {\n tree[f.path] = { hash: f.hash, size: f.size };\n blobs.set(f.hash, f.base64);\n }\n for (const p of stagedDeletes) {\n delete tree[p];\n }\n\n const last = repo.listPending(cwd).at(-1);\n const meta: repo.PendingMeta = {\n id: randomUUID(),\n message: opts.message,\n parentCommitId: last?.meta.id ?? repo.readHead(cwd),\n timestamp: Date.now(),\n author: cfg.owner,\n treeTxId: null,\n committedSig: null,\n };\n repo.appendPending(cwd, meta, tree, blobs);\n repo.writeIndex(cwd, []);\n\n const totalSize = stagedFiles.reduce((sum, f) => sum + f.size, 0);\n ui.log.success(`commit ${meta.id.slice(0, 7)} saved locally`);\n ui.log.info(\n ` ${stagedFiles.length} file(s) added/modified, ` +\n `${stagedDeletes.length} removed, ` +\n `${ui.formatSize(totalSize)}`,\n );\n ui.log.dim(\"Run: iqgit push to upload on-chain\");\n });\n}\n","// Tree resolution shared by commit / status. Pure logic over local pending\n// state and chain reads — no commands here, no UI.\n//\n// `Tree` is the shape stored in pending/<id>/tree.json: {hash, size}.\n// SDK's FileTree adds txId; we strip it on the way in (size=0 placeholder\n// since tree.json sizes are display-only — the real size comes from the\n// working tree when a path is restaged).\n\nimport {\n IQGIT_ROOT_ID,\n commitTableHint,\n} from \"@iqlabs-official/git-sdk/node\";\nimport { getDbRootPda, getTablePda } from \"@iqlabs-official/solana-sdk/contract\";\nimport { toSeedBytes } from \"@iqlabs-official/solana-sdk/utils\";\nimport { gwFetchAllRows, gwLoadTreeJson } from \"./gateway\";\nimport * as repo from \"./repo\";\n\nexport type Tree = Record<string, { hash: string; size: number }>;\n\n// Resolve the base tree against which a new commit (or status diff) layers:\n// 1. last pending's tree.json (purely local), else\n// 2. on-chain tree at HEAD (gwFetchRows + gwLoadTreeJson), else\n// 3. {} for a brand-new repo.\n//\n// Both chain reads route through gateway when GATEWAY_URL is set, falling\n// back to RPC transparently. The SDK's RPC connection must be initialized\n// (via iqlabs.setRpcUrl) before this is called — setup.ts handles that.\nexport async function resolveBaseTree(\n cwd: string,\n owner: string,\n repoName: string,\n): Promise<Tree> {\n const last = repo.listPending(cwd).at(-1);\n if (last) return repo.readPendingTree(last);\n\n const head = repo.readHead(cwd);\n if (head === null) return {};\n\n const dbRoot = getDbRootPda(toSeedBytes(IQGIT_ROOT_ID));\n const commitTable = getTablePda(dbRoot, toSeedBytes(commitTableHint(owner, repoName)));\n const history = (await gwFetchAllRows(commitTable.toBase58(), 200)) as Array<{\n id: string;\n treeTxId: string;\n }>;\n\n const headCommit = history.find((c) => c.id === head);\n if (!headCommit) {\n throw new Error(`HEAD ${head.slice(0, 7)} not found in on-chain history`);\n }\n const onChain = await gwLoadTreeJson<Record<string, { txId: string; hash: string }>>(headCommit.treeTxId);\n const out: Tree = {};\n for (const [p, entry] of Object.entries(onChain)) {\n out[p] = { hash: entry.hash, size: 0 };\n }\n return out;\n}\n","// Optional gateway-aware reads. Pattern + URL list mirror\n// iq-chan/src/lib/config.ts: try the primary gateway, then the Akash\n// direct ingress, then the backup gateway, then fall back to direct RPC.\n//\n// Why route reads through gateway:\n// - free RPCs (Helius free tier) rate-limit getTransaction; the SDK's\n// readTableRows fans out to N getTransaction calls per table. Gateway\n// has its own RPC + 3-tier cache so its reads don't burn the user's\n// RPC quota.\n// - decentralized: anyone can run a gateway. iqgit isn't tied to one.\n//\n// Configuration:\n// (no env) default 3-gateway chain (recommended)\n// GATEWAY_URL=https://my.example single override, then RPC fallback\n// GATEWAY_URL=url1,url2,url3 comma-separated list, tried in order\n// GATEWAY_URL=off disable gateway, all reads via RPC\n\nimport iqlabs from \"@iqlabs-official/solana-sdk\";\nimport { loadBlob, loadTree } from \"@iqlabs-official/git-sdk/node\";\n\n// Defaults match iq-chan/src/lib/config.ts so iqgit, blockchan and any\n// other consumer hit the same 3 read endpoints.\nconst DEFAULT_GATEWAYS = [\n \"https://gateway.solanainternet.com\",\n \"https://gateway.iqlabs.dev\",\n \"https://fem4pe7sthdm5f9fkhc1fnmpos.ingress.akashprovid.com\",\n \"https://fem4pe7sthdm5f9fkhc1fnmpos.ingress.cpu.aesservices.net\",\n];\n\nfunction getGatewayUrls(): string[] {\n const raw = process.env.GATEWAY_URL?.trim();\n if (raw === undefined || raw === \"\") return DEFAULT_GATEWAYS;\n if (raw.toLowerCase() === \"off\") return [];\n return raw.split(\",\").map((s) => s.trim()).filter(Boolean);\n}\n\n// Try each gateway in order with a per-request timeout. Returns the first\n// 2xx Response, or null if all gateways failed (network error or non-2xx).\nasync function gwFetch(path: string, timeoutMs = 8000): Promise<Response | null> {\n for (const base of getGatewayUrls()) {\n try {\n const res = await fetch(`${base}${path}`, { signal: AbortSignal.timeout(timeoutMs) });\n if (res.ok) return res;\n } catch {\n // try next gateway\n }\n }\n return null;\n}\n\n// Fetch rows for a table PDA. Always returns rows[] — gateway chain first,\n// SDK readTableRows (which uses the global RPC) on full gateway failure.\n// The SDK's RPC URL must be initialized via iqlabs.setRpcUrl before this\n// is called; setup.ts handles that.\nexport async function gwFetchRows(\n tablePda: string,\n limit = 50,\n before?: string,\n): Promise<Record<string, unknown>[]> {\n const path = `/table/${tablePda}/rows?limit=${limit}` + (before ? `&before=${before}` : \"\");\n const res = await gwFetch(path);\n if (res !== null) {\n try {\n const data = (await res.json()) as { rows?: Record<string, unknown>[] };\n return data.rows ?? [];\n } catch {\n // fall through to SDK\n }\n }\n return iqlabs.reader.readTableRows(tablePda, { limit, before });\n}\n\n// Page through gwFetchRows until at least maxRows or the gateway returns\n// fewer than asked (signals end of table).\nexport async function gwFetchAllRows(\n tablePda: string,\n maxRows = 200,\n): Promise<Record<string, unknown>[]> {\n const all: Record<string, unknown>[] = [];\n let before: string | undefined;\n while (all.length < maxRows) {\n const limit = Math.min(50, maxRows - all.length);\n const rows = await gwFetchRows(tablePda, limit, before);\n all.push(...rows);\n if (rows.length < limit) break;\n const last = rows[rows.length - 1] as { __txSignature?: string };\n if (!last.__txSignature) break;\n before = last.__txSignature;\n }\n return all;\n}\n\n// Load a JSON blob by tx signature. Gateway-first via /data/{sig}, falls\n// back to SDK's loadTree (RPC) on full chain failure.\nexport async function gwLoadTreeJson<T>(txSignature: string): Promise<T> {\n const res = await gwFetch(`/data/${txSignature}`);\n if (res !== null) {\n try {\n const env = (await res.json()) as { data?: string };\n if (typeof env.data === \"string\") return JSON.parse(env.data) as T;\n } catch {\n // fall through\n }\n }\n return (await loadTree(txSignature)) as T;\n}\n\n// Load a base64 blob by tx signature, gateway-first. Falls back to SDK's\n// loadBlob (RPC) on any gateway failure. Used for clone's per-file blob\n// fetches; gateway's /data/{sig} handles inline/linked-list/session\n// reassembly internally so callers don't need three code paths.\nexport async function gwLoadBlobBase64(txSignature: string): Promise<string> {\n const res = await gwFetch(`/data/${txSignature}`);\n if (res !== null) {\n try {\n const env = (await res.json()) as { data?: string };\n if (typeof env.data === \"string\") return env.data;\n } catch {\n // fall through\n }\n }\n return await loadBlob(txSignature);\n}\n\n// Fire-and-forget cache-warm hint after a write. Tries each gateway until\n// one ack-2xxs. Failures swallowed — the row is on chain, gateways will\n// pick it up on their next poll regardless.\nexport async function gwNotify(\n tablePda: string,\n txSignature: string,\n row?: Record<string, unknown>,\n signer?: string,\n): Promise<void> {\n const body = JSON.stringify({ txSignature, row, signer });\n for (const base of getGatewayUrls()) {\n try {\n const res = await fetch(`${base}/table/${tablePda}/notify`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body,\n signal: AbortSignal.timeout(3000),\n });\n if (res.ok) return;\n } catch {\n // try next gateway\n }\n }\n}\n","// `iqgit push` — drains .iqgit/pending/ to chain. The single most\n// involved command; everything else is short. Resume-safe by design.\n//\n// in: (no flags in v1; --dry-run could be added later)\n// sdk: NOT GitClient.commit() directly — we re-implement the workflow\n// because we need granular cache between blob/tree/row steps.\n// Per pending commit, we call the SDK's layer-level fns\n// (re-exported from the SDK root entry as of 2026-05-05):\n// • uploadBlob(connection, signer, relativePath, base64, reuse, onProgress?)\n// — per blob. We pass `reuse={}` because our upload-cache\n// already filtered hits before the call.\n// • uploadTree(connection, signer, tree)\n// — once per pending commit, after all blobs done.\n// • writeCommit(connection, signer, repoName, commit)\n// — once per pending commit, last step.\n//\n// Resume invariants:\n// • A blob's cache entry is written ONLY after uploadBlob returns.\n// • Tree's txId is persisted into pending/NNN/meta.json BEFORE writing\n// the commit row. If row write fails, next push reuses the tree.\n// • Commit row's signature is persisted into meta.json BEFORE deleting\n// the pending dir. If we crash between those two, next push sees\n// committedSig present and just cleans up + advances HEAD.\n\nimport type { Connection, Keypair } from \"@solana/web3.js\";\nimport type { Command } from \"commander\";\nimport { IQGIT_ROOT_ID,\n commitTableHint,\n uploadBlob,\n uploadTree,\n writeCommit,\n type Commit,\n type FileTree,\n} from \"@iqlabs-official/git-sdk/node\";\nimport { getDbRootPda, getTablePda } from \"@iqlabs-official/solana-sdk/contract\";\nimport { toSeedBytes } from \"@iqlabs-official/solana-sdk/utils\";\nimport { gwNotify } from \"../core/gateway\";\n\nimport * as repo from \"../core/repo\";\nimport { setup } from \"../setup\";\nimport * as ui from \"../ui\";\n\nexport function register(program: Command): void {\n program.command(\"push\").action(async () => {\n const cwd = repo.findRepoRoot();\n const cfg = repo.readConfig(cwd);\n const queue = repo.listPending(cwd);\n if (queue.length === 0) {\n ui.log.info(\"nothing to push\");\n return;\n }\n const { signer, connection } = await setup();\n\n for (const p of queue) {\n ui.log.info(`pushing ${p.meta.id.slice(0, 7)} \"${p.meta.message}\"`);\n try {\n await pushOne(connection, signer, cwd, cfg.repo, p);\n } catch (e) {\n ui.fail(\n `failed at ${p.meta.id.slice(0, 7)}: ${(e as Error).message}\\n` +\n `re-run \"iqgit push\" to resume.`,\n );\n }\n repo.writeHead(cwd, p.meta.id);\n repo.discardPending(p);\n ui.log.success(` pushed ${p.meta.id.slice(0, 7)}`);\n }\n });\n}\n\nasync function pushOne(\n connection: Connection,\n signer: Keypair,\n cwd: string,\n repoName: string,\n p: repo.PendingCommit,\n): Promise<void> {\n const tree = repo.readPendingTree(p);\n const newTree: FileTree = {};\n\n // ---- 1. blobs ----\n const total = Object.keys(tree).length;\n const sp = ui.spinner(` blobs 0/${total}`).start();\n let done = 0;\n let reused = 0;\n\n for (const [path, { hash }] of Object.entries(tree)) {\n const cached = repo.cacheGet(cwd, hash);\n if (cached) {\n newTree[path] = { txId: cached.txId, hash };\n reused++;\n } else {\n const base64 = repo.readPendingBlob(p, hash);\n const { txId } = await uploadBlob(connection, signer, path, base64, {});\n repo.cacheSet(cwd, hash, { txId, uploadedAt: Date.now() });\n newTree[path] = { txId, hash };\n }\n done++;\n sp.text = ` blobs ${done}/${total} (${reused} reused)`;\n }\n sp.succeed(` blobs ${done}/${total} (${reused} reused)`);\n\n // ---- 2. tree ----\n let treeTxId = p.meta.treeTxId;\n if (!treeTxId) {\n treeTxId = await uploadTree(connection, signer, newTree);\n repo.updatePendingMeta(p, { treeTxId });\n }\n\n // ---- 3. commit row ----\n if (!p.meta.committedSig) {\n const commit: Commit = {\n id: p.meta.id,\n message: p.meta.message,\n treeTxId,\n parentCommitId: p.meta.parentCommitId ?? undefined,\n timestamp: p.meta.timestamp,\n author: p.meta.author,\n };\n const sig = await writeCommit(connection, signer, repoName, commit);\n repo.updatePendingMeta(p, { committedSig: sig });\n // Cache warm hint to gateway — fire-and-forget, gateway will pull tx\n // on its own anyway.\n const dbRoot = getDbRootPda(toSeedBytes(IQGIT_ROOT_ID));\n const tablePda = getTablePda(dbRoot, toSeedBytes(commitTableHint(commit.author, repoName)));\n void gwNotify(tablePda.toBase58(), sig, undefined, signer.publicKey.toBase58());\n }\n}\n","// `iqgit clone <owner>/<repo> [dir]` — pulls latest snapshot to disk.\n// Read-only and anonymous: no wallet required. Cloning a public repo\n// only needs an RPC (for SDK fallback) and optionally a gateway.\n//\n// in: <owner>/<repo>, optional [dir] (default = repo name)\n// reads (gateway-first, RPC fallback):\n// gwFetchAllRows on git_commits:<owner>:<repo> → newest commit row\n// gwLoadTreeJson on commit.treeTxId → tree.json\n// gwLoadBlobBase64 per file txId → file bytes\n// gwFetchAllRows on git_repos_v2_<owner> → isPublic for config\n// out: directory tree on disk + initialized .iqgit/ with HEAD set so\n// future `status` / `commit` work without re-resolving.\n\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { Buffer } from \"node:buffer\";\nimport type { Command } from \"commander\";\nimport {\n IQGIT_ROOT_ID,\n commitTableHint,\n repoListHint,\n} from \"@iqlabs-official/git-sdk/node\";\nimport { getDbRootPda, getTablePda } from \"@iqlabs-official/solana-sdk/contract\";\nimport { toSeedBytes } from \"@iqlabs-official/solana-sdk/utils\";\nimport * as repo from \"../core/repo\";\nimport { gwFetchAllRows, gwLoadBlobBase64, gwLoadTreeJson } from \"../core/gateway\";\nimport { setupReadOnly } from \"../setup\";\nimport * as ui from \"../ui\";\n\nexport function register(program: Command): void {\n program\n .command(\"clone <slug> [dir]\")\n .action(async (slug: string, dir: string | undefined) => {\n const [owner, repoName] = slug.split(\"/\");\n if (!owner || !repoName) ui.fail(\"expected <owner>/<repo>\");\n const target = dir ?? repoName;\n if (existsSync(target)) ui.fail(`${target} already exists`);\n mkdirSync(target, { recursive: true });\n\n // Initialize SDK RPC for the gateway functions' fallback paths.\n // No wallet prompt — clone is read-only.\n await setupReadOnly();\n\n const dbRoot = getDbRootPda(toSeedBytes(IQGIT_ROOT_ID));\n\n const sp = ui.spinner(`cloning ${slug}...`).start();\n\n // 1. latest commit\n const commitTable = getTablePda(dbRoot, toSeedBytes(commitTableHint(owner, repoName)));\n const commits = await gwFetchAllRows(commitTable.toBase58(), 200);\n if (commits.length === 0) {\n sp.fail(`no commits in ${slug}`);\n process.exit(1);\n }\n const latest = [...commits].sort(\n (a, b) => ((b as { timestamp?: number }).timestamp ?? 0) - ((a as { timestamp?: number }).timestamp ?? 0),\n )[0] as { id: string; treeTxId: string };\n\n // 2. tree\n const tree = await gwLoadTreeJson<Record<string, { txId: string; hash: string }>>(latest.treeTxId);\n const paths = Object.entries(tree);\n\n // 3. blobs — one per file\n let i = 0;\n for (const [path, entry] of paths) {\n i++;\n sp.text = `cloning ${slug}... (${i}/${paths.length}) ${path}`;\n const base64 = await gwLoadBlobBase64(entry.txId);\n const abs = join(target, path);\n mkdirSync(dirname(abs), { recursive: true });\n writeFileSync(abs, Buffer.from(base64, \"base64\"));\n }\n sp.succeed(`cloned ${paths.length} file(s) to ${target}/`);\n\n // 4. local config — read on-chain isPublic so cloned config is accurate\n const ownerListPda = getTablePda(dbRoot, toSeedBytes(repoListHint(owner)));\n const repos = await gwFetchAllRows(ownerListPda.toBase58(), 200);\n const meta = repos.find((r) => (r as { name?: string }).name === repoName) as\n | { isPublic?: boolean }\n | undefined;\n const isPublic = meta?.isPublic ?? true;\n\n repo.initRepo(target);\n repo.writeConfig(target, { owner, repo: repoName, isPublic });\n repo.writeHead(target, latest.id);\n });\n}\n","// `iqgit restore [commitId]` — restore working tree to a commit's\n// snapshot. Defaults to \"latest\" (functionally a re-pull).\n//\n// NAMING NOTE: in git this would be `checkout`, but git's `checkout` is\n// overloaded with branch-switching, which we don't have in v1. Calling\n// it `restore` matches `git restore --source=<commit>` and is unambiguous.\n// FUTURE: when branches land, a real `checkout` command may be added for\n// branch-switching, and this `restore` may be folded into it.\n//\n// in: optional <commitId> (full or short prefix); default = \"latest\"\n// sdk: GitClient.checkout(repoName, commitId | \"latest\", sink)\n// out: overwrites/creates files in cwd from the target tree;\n// updates .iqgit/HEAD only when restore(\"latest\").\n//\n// SAFETY: this destroys uncommitted local changes. We bail unless\n// `iqgit status` shows clean OR --force is passed.\n\nimport { mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport type { Command } from \"commander\";\nimport * as repo from \"../core/repo\";\nimport { scan, toScanMap } from \"../core/scan\";\nimport { setup } from \"../setup\";\nimport * as ui from \"../ui\";\n\nexport function register(program: Command): void {\n program\n .command(\"restore [commitId]\")\n .option(\"--force\", \"discard uncommitted changes\")\n .action(async (commitId: string | undefined, opts: { force?: boolean }) => {\n const cwd = repo.findRepoRoot();\n const cfg = repo.readConfig(cwd);\n const { client } = await setup();\n\n if (!opts.force) {\n const { added, modified } = await client.status(\n cfg.owner,\n cfg.repo,\n toScanMap(scan(cwd)),\n );\n if (added.length || modified.length) {\n ui.fail(\"uncommitted changes — commit them or pass --force\");\n }\n }\n\n const target = commitId ?? \"latest\";\n const sp = ui.spinner(`restoring ${target}...`).start();\n const c = await client.checkout(cfg.repo, target, async (path, base64) => {\n const abs = join(cwd, path);\n mkdirSync(dirname(abs), { recursive: true });\n writeFileSync(abs, Buffer.from(base64, \"base64\"));\n });\n sp.succeed(`restored ${c.id.slice(0, 7)} \"${c.message}\"`);\n\n if (target === \"latest\") repo.writeHead(cwd, c.id);\n });\n}\n","// `iqgit log [--limit N]` — print commit history newest-first.\n// Read-only. Uses gwFetchRows which transparently routes through the\n// gateway when GATEWAY_URL is set, falls back to direct RPC otherwise.\n//\n// in: optional --limit <n>, --owner <pubkey>, --repo <name>\n//\n// Owner/repo default from .iqgit/config.json so users can `cd` into a\n// cloned repo and just run `iqgit log`. Override flags exist for peeking\n// at someone else's repo without cloning.\n\nimport type { Command } from \"commander\";\nimport {\n IQGIT_ROOT_ID,\n commitTableHint,\n type Commit,\n} from \"@iqlabs-official/git-sdk/node\";\nimport { getDbRootPda, getTablePda } from \"@iqlabs-official/solana-sdk/contract\";\nimport { toSeedBytes } from \"@iqlabs-official/solana-sdk/utils\";\nimport * as repo from \"../core/repo\";\nimport { gwFetchAllRows } from \"../core/gateway\";\nimport { setupReadOnly } from \"../setup\";\nimport * as ui from \"../ui\";\n\nexport function register(program: Command): void {\n program\n .command(\"log\")\n .option(\"--limit <n>\", \"max entries\", \"20\")\n .option(\"--owner <pubkey>\")\n .option(\"--repo <name>\")\n .action(async (opts: { limit: string; owner?: string; repo?: string }) => {\n let owner = opts.owner;\n let repoName = opts.repo;\n if (!owner || !repoName) {\n const cfg = repo.readConfig(repo.findRepoRoot());\n owner ??= cfg.owner;\n repoName ??= cfg.repo;\n }\n // Ensure SDK has an RPC configured for the gwFetchRows fallback path.\n await setupReadOnly();\n\n const dbRoot = getDbRootPda(toSeedBytes(IQGIT_ROOT_ID));\n const tablePda = getTablePda(dbRoot, toSeedBytes(commitTableHint(owner, repoName)));\n const commits = (await gwFetchAllRows(tablePda.toBase58(), Number(opts.limit))) as unknown as Commit[];\n\n // Gateway returns rows in chain order; SDK returns newest-first. Sort\n // here unconditionally so output is stable regardless of source.\n const sorted = [...commits].sort((a, b) => b.timestamp - a.timestamp);\n for (const c of sorted) {\n ui.log.info(ui.formatCommit(c));\n ui.log.dim(` author: ${c.author}`);\n ui.log.dim(` tree: ${c.treeTxId}`);\n ui.log.info(\"\");\n }\n });\n}\n","// `iqgit status` — four-tier view, mirrors git plus our pending layer:\n//\n// remote (HEAD on chain) ── what was last pushed\n// │\n// ▼\n// pending (.iqgit/pending/) ── committed locally, not yet on chain\n// │\n// ▼\n// index (.iqgit/index.json) ── staged for the next commit\n// │\n// ▼\n// working tree (cwd files) ── on disk\n//\n// We diff working tree vs base tree (last pending → on-chain HEAD → empty)\n// to label each path: staged / unstaged-modified / unstaged-added /\n// unstaged-deleted. The base resolution reuses core/tree.ts so commit and\n// status agree on what \"current state\" means (CODE-RULES §2).\n\nimport type { Command } from \"commander\";\nimport * as repo from \"../core/repo\";\nimport { scan } from \"../core/scan\";\nimport { resolveBaseTree } from \"../core/tree\";\nimport { setupReadOnly } from \"../setup\";\nimport * as ui from \"../ui\";\n\nexport function register(program: Command): void {\n program.command(\"status\").action(async () => {\n const cwd = repo.findRepoRoot();\n const cfg = repo.readConfig(cwd);\n const head = repo.readHead(cwd);\n const pending = repo.listPending(cwd);\n const index = new Set(repo.readIndex(cwd));\n const files = scan(cwd);\n const filesByPath = new Map(files.map((f) => [f.path, f]));\n\n // Initialize SDK RPC for the gwFetchRows fallback path; resolveBaseTree\n // skips chain reads entirely when local pending exists or HEAD is null.\n if (pending.length === 0 && head !== null) await setupReadOnly();\n const base = await resolveBaseTree(cwd, cfg.owner, cfg.repo);\n\n const stagedAddedOrModified: string[] = [];\n const stagedDeleted: string[] = [];\n const unstagedAdded: string[] = [];\n const unstagedModified: string[] = [];\n const unstagedDeleted: string[] = [];\n\n // Paths present in base, working tree, or both.\n const allPaths = new Set([...Object.keys(base), ...files.map((f) => f.path)]);\n for (const p of allPaths) {\n const inBase = base[p];\n const inWorking = filesByPath.get(p);\n const isStaged = index.has(p);\n\n if (inWorking && !inBase) {\n (isStaged ? stagedAddedOrModified : unstagedAdded).push(p);\n } else if (!inWorking && inBase) {\n (isStaged ? stagedDeleted : unstagedDeleted).push(p);\n } else if (inWorking && inBase && inWorking.hash !== inBase.hash) {\n (isStaged ? stagedAddedOrModified : unstagedModified).push(p);\n }\n }\n\n ui.log.info(`On HEAD: ${head ? head.slice(0, 7) : \"(no commits yet)\"}`);\n\n if (pending.length) {\n ui.log.info(\"\");\n ui.log.info(`Pending commits (not yet pushed): ${pending.length}`);\n for (const p of pending) {\n ui.log.info(` ${p.meta.id.slice(0, 7)} \"${p.meta.message}\"`);\n }\n }\n\n if (stagedAddedOrModified.length || stagedDeleted.length) {\n ui.log.info(\"\");\n ui.log.info(\"Staged for next commit:\");\n for (const f of stagedAddedOrModified) ui.log.info(` ${f}`);\n for (const f of stagedDeleted) ui.log.info(` deleted: ${f}`);\n }\n\n if (unstagedAdded.length || unstagedModified.length || unstagedDeleted.length) {\n ui.log.info(\"\");\n ui.log.info(\"Unstaged changes:\");\n for (const f of unstagedAdded) ui.log.info(` added: ${f}`);\n for (const f of unstagedModified) ui.log.info(` modified: ${f}`);\n for (const f of unstagedDeleted) ui.log.info(` deleted: ${f}`);\n }\n\n const clean =\n pending.length === 0 &&\n stagedAddedOrModified.length === 0 &&\n stagedDeleted.length === 0 &&\n unstagedAdded.length === 0 &&\n unstagedModified.length === 0 &&\n unstagedDeleted.length === 0;\n if (clean) ui.log.info(\"clean\");\n });\n}\n","// `iqgit registry` — browse the public gallery (git_repos:all). Read-only.\n\nimport type { Command } from \"commander\";\nimport {\n IQGIT_ROOT_ID,\n REGISTRY_HINT,\n type RegistryEntry,\n} from \"@iqlabs-official/git-sdk/node\";\nimport { getDbRootPda, getTablePda } from \"@iqlabs-official/solana-sdk/contract\";\nimport { toSeedBytes } from \"@iqlabs-official/solana-sdk/utils\";\nimport { gwFetchAllRows } from \"../core/gateway\";\nimport { setupReadOnly } from \"../setup\";\nimport * as ui from \"../ui\";\n\nexport function register(program: Command): void {\n program\n .command(\"registry\")\n .description(\"browse the public on-chain repo gallery\")\n .option(\"--limit <n>\", \"max entries\", \"20\")\n .action(async (opts: { limit: string }) => {\n await setupReadOnly();\n const dbRoot = getDbRootPda(toSeedBytes(IQGIT_ROOT_ID));\n const tablePda = getTablePda(dbRoot, toSeedBytes(REGISTRY_HINT));\n const entries = (await gwFetchAllRows(tablePda.toBase58(), Number(opts.limit))) as unknown as RegistryEntry[];\n if (entries.length === 0) {\n ui.log.dim(\"registry empty\");\n return;\n }\n for (const e of entries) {\n ui.log.info(`${e.owner.slice(0, 8)}…/${e.repo} ${e.description ?? \"\"}`);\n }\n });\n}\n","// `iqgit config`: get/set values in ~/.iq-git/config.json.\n// Mirrors `git config` ergonomics but for the global CLI config only\n// (not per-repo). Per-repo config is just .iqgit/config.json which\n// commands edit directly.\n//\n// in: no args → list all\n// <key> → print value\n// <key> <value> → set + persist\n// --unset <key> → remove key\n// sdk: (none)\n// out: stdout\n\nimport type { Command } from \"commander\";\nimport { readGlobalConfig, writeGlobalConfig } from \"../setup\";\nimport * as ui from \"../ui\";\n\nconst KNOWN_KEYS = [\"walletPath\", \"rpcUrl\"] as const;\n\nexport function register(program: Command): void {\n program\n .command(\"config [key] [value]\")\n .description(\"get or set global config (keys: walletPath, rpcUrl)\")\n .addHelpText(\"after\", `\nExamples:\n iqgit config list all\n iqgit config rpcUrl print current RPC URL\n iqgit config rpcUrl https://my-rpc.example change RPC URL\n iqgit config --unset rpcUrl reset (re-prompts next run)`)\n .option(\"--unset <key>\")\n .action((key: string | undefined, value: string | undefined, opts: { unset?: string }) => {\n const cfg = readGlobalConfig() as Record<string, string | undefined>;\n\n if (opts.unset) {\n ensureKnown(opts.unset);\n delete cfg[opts.unset];\n writeGlobalConfig(cfg);\n ui.log.success(`unset ${opts.unset}`);\n return;\n }\n if (!key) {\n for (const [k, v] of Object.entries(cfg)) {\n if (v !== undefined) ui.log.info(`${k}=${v}`);\n }\n return;\n }\n ensureKnown(key);\n if (value === undefined) {\n ui.log.info(cfg[key] ?? \"\");\n return;\n }\n cfg[key] = value;\n writeGlobalConfig(cfg);\n ui.log.success(`set ${key}=${value}`);\n });\n}\n\nfunction ensureKnown(key: string): void {\n if (!(KNOWN_KEYS as readonly string[]).includes(key)) {\n ui.fail(`unknown config key: ${key}\\nknown: ${KNOWN_KEYS.join(\", \")}`);\n }\n}\n","// `iqgit wallet <action>` — manage keypair. Multiple actions in one file\n// (CODE-RULES §1: don't fan out into wallet/new.ts, wallet/show.ts ...\n// when each is 10 lines).\n//\n// in: iqgit wallet new → generate Keypair, save to ~/.iq-git/wallets/default.json\n// iqgit wallet show → print pubkey + path\n// iqgit wallet balance → print SOL balance\n// iqgit wallet repos → list repos owned by current pubkey\n// reads: gwFetchAllRows on git_repos_v2_<owner> (for `repos` action)\n// out: stdout\n\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { Command } from \"commander\";\nimport { Keypair, LAMPORTS_PER_SOL } from \"@solana/web3.js\";\nimport { IQGIT_ROOT_ID, repoListHint } from \"@iqlabs-official/git-sdk/node\";\nimport { getDbRootPda, getTablePda } from \"@iqlabs-official/solana-sdk/contract\";\nimport { toSeedBytes } from \"@iqlabs-official/solana-sdk/utils\";\nimport { gwFetchAllRows } from \"../core/gateway\";\nimport { DEFAULT_WALLET, loadKeypairFromFile, readGlobalConfig, setup } from \"../setup\";\n\nimport * as ui from \"../ui\";\n\nexport function register(program: Command): void {\n program\n .command(\"wallet <action>\")\n .description(\"new | show | balance | repos\")\n .action(async (action: string) => {\n switch (action) {\n case \"new\":\n return walletNew();\n case \"show\":\n return walletShow();\n case \"balance\":\n return walletBalance();\n case \"repos\":\n return walletRepos();\n default:\n ui.fail(`unknown action: ${action}`);\n }\n });\n}\n\nfunction walletNew(): void {\n if (existsSync(DEFAULT_WALLET)) {\n ui.fail(`default wallet exists at ${DEFAULT_WALLET}; remove it first`);\n }\n mkdirSync(dirname(DEFAULT_WALLET), { recursive: true });\n const kp = Keypair.generate();\n writeFileSync(DEFAULT_WALLET, JSON.stringify(Array.from(kp.secretKey)));\n ui.log.success(`created ${DEFAULT_WALLET}`);\n ui.log.info(`pubkey: ${kp.publicKey.toBase58()}`);\n}\n\nfunction walletShow(): void {\n const path = readGlobalConfig().walletPath ?? DEFAULT_WALLET;\n const kp = loadKeypairFromFile(path);\n ui.log.info(`path: ${path}`);\n ui.log.info(`pubkey: ${kp.publicKey.toBase58()}`);\n}\n\nasync function walletBalance(): Promise<void> {\n const { signer, connection } = await setup();\n const lamports = await connection.getBalance(signer.publicKey);\n ui.log.info(signer.publicKey.toBase58());\n ui.log.info(`${lamports / LAMPORTS_PER_SOL} SOL`);\n}\n\nasync function walletRepos(): Promise<void> {\n const { signer } = await setup();\n // Gateway-first read of git_repos_v2_<owner>; falls through to RPC.\n const owner = signer.publicKey.toBase58();\n const dbRoot = getDbRootPda(toSeedBytes(IQGIT_ROOT_ID));\n const tablePda = getTablePda(dbRoot, toSeedBytes(repoListHint(owner)));\n const repos = (await gwFetchAllRows(tablePda.toBase58(), 200)) as Array<{\n name: string; description: string; isPublic: boolean;\n }>;\n if (repos.length === 0) {\n ui.log.dim(\"no repos yet\");\n return;\n }\n for (const r of repos) {\n const visibility = r.isPublic ? \"public \" : \"private\";\n ui.log.info(`${visibility} ${r.name} ${r.description}`);\n }\n}\n"],"mappings":"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","names":["existsSync","join","program","existsSync","join","existsSync","join","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","join","join","mkdirSync","existsSync","dirname","writeFileSync","readFileSync","register","program","existsSync","join","existsSync","relative","sep","readdirSync","readFileSync","join","register","program","existsSync","relative","sep","isAbsolute","relative","resolve","sep","register","program","isAbsolute","resolve","relative","sep","existsSync","join","iqlabs","register","program","existsSync","join","IQGIT_ROOT_ID","commitTableHint","getDbRootPda","getTablePda","toSeedBytes","register","program","getDbRootPda","toSeedBytes","IQGIT_ROOT_ID","getTablePda","commitTableHint","existsSync","mkdirSync","writeFileSync","dirname","join","Buffer","IQGIT_ROOT_ID","commitTableHint","getDbRootPda","getTablePda","toSeedBytes","register","program","existsSync","mkdirSync","getDbRootPda","toSeedBytes","IQGIT_ROOT_ID","getTablePda","commitTableHint","join","dirname","writeFileSync","Buffer","mkdirSync","writeFileSync","dirname","join","register","program","join","mkdirSync","dirname","writeFileSync","IQGIT_ROOT_ID","commitTableHint","getDbRootPda","getTablePda","toSeedBytes","register","program","getDbRootPda","toSeedBytes","IQGIT_ROOT_ID","getTablePda","commitTableHint","register","program","IQGIT_ROOT_ID","getDbRootPda","getTablePda","toSeedBytes","register","program","getDbRootPda","toSeedBytes","IQGIT_ROOT_ID","getTablePda","register","program","existsSync","mkdirSync","writeFileSync","dirname","Keypair","LAMPORTS_PER_SOL","IQGIT_ROOT_ID","repoListHint","getDbRootPda","getTablePda","toSeedBytes","register","program","existsSync","mkdirSync","dirname","Keypair","writeFileSync","LAMPORTS_PER_SOL","getDbRootPda","toSeedBytes","IQGIT_ROOT_ID","getTablePda","repoListHint","register"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/commands/init.ts","../src/core/repo.ts","../src/ui.ts","../src/commands/create.ts","../src/setup.ts","../src/commands/add.ts","../src/core/scan.ts","../src/commands/reset.ts","../src/commands/commit.ts","../src/core/tree.ts","../src/core/gateway.ts","../src/commands/push.ts","../src/commands/clone.ts","../src/commands/restore.ts","../src/commands/log.ts","../src/commands/status.ts","../src/commands/registry.ts","../src/commands/config.ts","../src/commands/wallet.ts"],"sourcesContent":["// Entry point. Wires commander, registers every command in `commands/`,\n// and dispatches to them. The only file that touches process.argv directly.\n//\n// SDK dependency: \"@iqlabs-official/git-sdk\" >= 0.1.4\n// 0.1.4 is the first version that re-exports the write-side layer fns\n// (uploadBlob, uploadTree, writeCommit) which push.ts depends on.\n\nimport { Command } from \"commander\";\nimport { register as initCmd } from \"./commands/init\";\nimport { register as createCmd } from \"./commands/create\";\nimport { register as addCmd } from \"./commands/add\";\nimport { register as resetCmd } from \"./commands/reset\";\nimport { register as commitCmd } from \"./commands/commit\";\nimport { register as pushCmd } from \"./commands/push\";\nimport { register as cloneCmd } from \"./commands/clone\";\nimport { register as restoreCmd } from \"./commands/restore\";\nimport { register as logCmd } from \"./commands/log\";\nimport { register as statusCmd } from \"./commands/status\";\nimport { register as registryCmd } from \"./commands/registry\";\nimport { register as configCmd } from \"./commands/config\";\nimport { register as walletCmd } from \"./commands/wallet\";\n\nconst program = new Command(\"iqgit\")\n .description(\"On-chain Git for Solana\")\n .version(\"0.1.0\");\n\ninitCmd(program);\ncreateCmd(program);\naddCmd(program);\nresetCmd(program);\ncommitCmd(program);\npushCmd(program);\ncloneCmd(program);\nrestoreCmd(program);\nlogCmd(program);\nstatusCmd(program);\nregistryCmd(program);\nconfigCmd(program);\nwalletCmd(program);\n\nprogram.parseAsync(process.argv);\n","// `iqgit init` — local-only. Creates .iqgit/ skeleton. Does NOT touch\n// chain. Mirror of `git init`.\n//\n// in: optionally `--name <repo>` `--public|--private`\n// sdk: (none)\n// out: prints next-step hint about `iqgit create`\n//\n// Why no auto-create on init: chain writes cost SOL. We want users to\n// explicitly opt in via `iqgit create` so the first transaction is\n// never a surprise.\n//\n// Stub config: we write .iqgit/config.json with empty `owner` so that\n// `iqgit add`, `iqgit commit`, `iqgit status` work against the local\n// pending state without an ENOENT crash. The empty owner is the gate\n// commit.ts already checks — it triggers the friendly \"run iqgit create\n// first\" message at the right time.\n\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { Command } from \"commander\";\nimport * as repo from \"../core/repo\";\nimport * as ui from \"../ui\";\n\nexport function register(program: Command): void {\n program\n .command(\"init\")\n .option(\"--name <name>\", \"repository name\")\n .option(\"--public\", \"default visibility\")\n .option(\"--private\")\n .action((opts: { name?: string; public?: boolean; private?: boolean }) => {\n const cwd = process.cwd();\n if (existsSync(join(cwd, \".iqgit\"))) ui.fail(\"already an iqgit repo\");\n repo.initRepo(cwd);\n repo.writeConfig(cwd, {\n owner: \"\",\n repo: opts.name ?? \"\",\n isPublic: !opts.private,\n });\n ui.log.success(\"Initialized empty iqgit repo in .iqgit/\");\n ui.log.dim(\"Next: iqgit create <name> [--public|--private]\");\n });\n}\n","// All .iqgit/ disk I/O lives here. One file, function-prefixed by concern,\n// because all four pieces (config / HEAD / pending / cache) are tiny JSON\n// reads/writes that share the same root path resolution. Splitting them\n// would be premature (CODE-RULES §1).\n//\n// Layout this file owns (per repo):\n//\n// <repoRoot>/.iqgit/\n// ├── config.json { owner, repo, isPublic }\n// ├── HEAD last successfully-pushed commitId (utf8)\n// ├── index.json string[] — paths staged for the next commit\n// ├── pending/\n// │ └── NNN-<commitId>/\n// │ ├── meta.json { id, message, parentCommitId, timestamp,\n// │ │ author, treeTxId|null, committedSig|null }\n// │ ├── tree.json { [path]: { hash, size } } ← size for stats\n// │ └── blobs/<hash> raw base64 content (push reads from here)\n// └── upload-cache.json { [hash]: { txId, uploadedAt } }\n//\n// CRITICAL: every cache mutation flushes synchronously. Process kill\n// during push must leave a recoverable state. Don't batch writes here.\n\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n readdirSync,\n renameSync,\n rmSync,\n writeFileSync,\n} from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\nconst DIR = \".iqgit\";\n\nexport interface RepoConfig {\n owner: string;\n repo: string;\n isPublic: boolean;\n}\n\nexport interface PendingMeta {\n id: string;\n message: string;\n parentCommitId: string | null;\n timestamp: number;\n author: string;\n treeTxId: string | null;\n committedSig: string | null;\n}\n\nexport interface PendingCommit {\n dir: string;\n seq: number;\n meta: PendingMeta;\n}\n\nexport interface CacheEntry {\n txId: string;\n uploadedAt: number;\n}\n\n// === bootstrap / discovery ===\n\nexport function findRepoRoot(cwd = process.cwd()): string {\n let dir = cwd;\n while (true) {\n if (existsSync(join(dir, DIR))) return dir;\n const parent = dirname(dir);\n if (parent === dir) {\n throw new Error(\"not an iqgit repo (or any parent)\");\n }\n dir = parent;\n }\n}\n\nexport function initRepo(cwd: string): void {\n mkdirSync(join(cwd, DIR, \"pending\"), { recursive: true });\n}\n\n// === config.json ===\n\nexport function readConfig(repoRoot: string): RepoConfig {\n // Defensive: pre-fix repos may lack config.json. Return defaults so\n // `add` / `status` / `commit` give the friendly \"run iqgit create first\"\n // message via commit.ts:41 instead of an ENOENT stack trace.\n try {\n return JSON.parse(readFileSync(join(repoRoot, DIR, \"config.json\"), \"utf8\")) as RepoConfig;\n } catch {\n return { owner: \"\", repo: \"\", isPublic: true };\n }\n}\n\nexport function writeConfig(repoRoot: string, cfg: RepoConfig): void {\n writeFileSync(join(repoRoot, DIR, \"config.json\"), JSON.stringify(cfg, null, 2));\n}\n\n// === HEAD ===\n\nexport function readHead(repoRoot: string): string | null {\n try {\n return readFileSync(join(repoRoot, DIR, \"HEAD\"), \"utf8\").trim() || null;\n } catch {\n return null;\n }\n}\n\nexport function writeHead(repoRoot: string, commitId: string): void {\n writeFileSync(join(repoRoot, DIR, \"HEAD\"), commitId);\n}\n\n// === index.json ===\n//\n// Set of staged paths for the next commit. Stored as a plain string[] —\n// order doesn't matter, and a Set serialized as sorted array keeps diffs\n// readable for anyone who peeks at the file.\n\nexport function readIndex(repoRoot: string): string[] {\n try {\n return JSON.parse(readFileSync(join(repoRoot, DIR, \"index.json\"), \"utf8\")) as string[];\n } catch {\n return [];\n }\n}\n\nexport function writeIndex(repoRoot: string, paths: string[]): void {\n const sorted = Array.from(new Set(paths)).sort();\n writeFileSync(join(repoRoot, DIR, \"index.json\"), JSON.stringify(sorted, null, 2));\n}\n\n// === pending ===\n\nexport function listPending(repoRoot: string): PendingCommit[] {\n const dir = join(repoRoot, DIR, \"pending\");\n if (!existsSync(dir)) return [];\n return readdirSync(dir, { withFileTypes: true })\n .filter((e) => e.isDirectory())\n .map((e) => {\n const seqStr = e.name.split(\"-\")[0];\n if (!seqStr) throw new Error(`malformed pending dir: ${e.name}`);\n const dirPath = join(dir, e.name);\n return {\n dir: dirPath,\n seq: Number(seqStr),\n meta: JSON.parse(readFileSync(join(dirPath, \"meta.json\"), \"utf8\")) as PendingMeta,\n };\n })\n .sort((a, b) => a.seq - b.seq);\n}\n\n// blobs is hash → base64. Caller (commit.ts) builds it from a ScanFile[]\n// where Map deduplication already collapsed identical-content files.\nexport function appendPending(\n repoRoot: string,\n meta: PendingMeta,\n tree: Record<string, { hash: string; size: number }>,\n blobs: Map<string, string>,\n): PendingCommit {\n const existing = listPending(repoRoot);\n const seq = (existing[existing.length - 1]?.seq ?? 0) + 1;\n const seqStr = String(seq).padStart(3, \"0\");\n const dir = join(repoRoot, DIR, \"pending\", `${seqStr}-${meta.id}`);\n mkdirSync(join(dir, \"blobs\"), { recursive: true });\n writeFileSync(join(dir, \"meta.json\"), JSON.stringify(meta, null, 2));\n writeFileSync(join(dir, \"tree.json\"), JSON.stringify(tree, null, 2));\n for (const [hash, base64] of blobs) {\n writeFileSync(join(dir, \"blobs\", hash), base64);\n }\n return { dir, seq, meta };\n}\n\n// Atomic-ish meta update. Write to .tmp then rename — survives process kill\n// mid-update. Used to checkpoint treeTxId / committedSig during push.\nexport function updatePendingMeta(p: PendingCommit, patch: Partial<PendingMeta>): void {\n const next = { ...p.meta, ...patch };\n const target = join(p.dir, \"meta.json\");\n const tmp = `${target}.tmp`;\n writeFileSync(tmp, JSON.stringify(next, null, 2));\n renameSync(tmp, target);\n p.meta = next;\n}\n\nexport function readPendingTree(p: PendingCommit): Record<string, { hash: string; size: number }> {\n return JSON.parse(readFileSync(join(p.dir, \"tree.json\"), \"utf8\")) as Record<\n string,\n { hash: string; size: number }\n >;\n}\n\nexport function readPendingBlob(p: PendingCommit, hash: string): string {\n return readFileSync(join(p.dir, \"blobs\", hash), \"utf8\");\n}\n\nexport function discardPending(p: PendingCommit): void {\n rmSync(p.dir, { recursive: true, force: true });\n}\n\n// === upload-cache.json ===\n//\n// Per-repo (under .iqgit/), not global — keeps repos self-contained,\n// simpler to reason about, and cross-repo dedup wasn't a stated need.\n// In-memory cache loaded lazily; every set() rewrites the whole file\n// synchronously so a process kill leaves the latest entry on disk.\n\nconst cacheMem = new Map<string, Record<string, CacheEntry>>();\n\nexport function cacheGet(repoRoot: string, hash: string): CacheEntry | null {\n return loadCache(repoRoot)[hash] ?? null;\n}\n\nexport function cacheSet(repoRoot: string, hash: string, entry: CacheEntry): void {\n const c = loadCache(repoRoot);\n c[hash] = entry;\n writeFileSync(cachePath(repoRoot), JSON.stringify(c, null, 2));\n}\n\nfunction cachePath(repoRoot: string): string {\n return join(repoRoot, DIR, \"upload-cache.json\");\n}\n\nfunction loadCache(repoRoot: string): Record<string, CacheEntry> {\n const cached = cacheMem.get(repoRoot);\n if (cached) return cached;\n let parsed: Record<string, CacheEntry> = {};\n try {\n parsed = JSON.parse(readFileSync(cachePath(repoRoot), \"utf8\")) as Record<string, CacheEntry>;\n } catch {\n // absent — start empty\n }\n cacheMem.set(repoRoot, parsed);\n return parsed;\n}\n\n","// Thin display layer. chalk + ora + @inquirer/prompts wrapped behind\n// named functions so commands don't import them directly. Keeps colors\n// and prompt styles consistent across commands.\n//\n// Functions are intentionally minimal — if a command needs a one-off\n// formatter, do it inline in the command file (CODE-RULES §1: no\n// meaningless wrapper). This file only holds things used by ≥2 commands.\n\nimport { confirm as inqConfirm, input as inqInput, select as inqSelect } from \"@inquirer/prompts\";\nimport chalk from \"chalk\";\nimport ora, { type Ora } from \"ora\";\n\n// Free function (not a method) so TS narrows callers' control flow on\n// `never` return — see https://github.com/microsoft/TypeScript/issues/12825.\nexport function fail(msg: string): never {\n console.error(chalk.red(\"✗\"), msg);\n process.exit(1);\n}\n\nexport const log = {\n info(msg: string): void {\n console.log(msg);\n },\n success(msg: string): void {\n console.log(chalk.green(\"✓\"), msg);\n },\n warn(msg: string): void {\n console.log(chalk.yellow(\"⚠\"), msg);\n },\n dim(msg: string): void {\n console.log(chalk.gray(msg));\n },\n};\n\nexport function spinner(label: string): Ora {\n return ora(label);\n}\n\nexport const confirm = inqConfirm;\nexport const input = inqInput;\nexport const select = inqSelect;\n\nexport function formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / 1024 / 1024).toFixed(1)} MB`;\n}\n\n// Format: \"a3f5b2 fix login bug (2h ago)\". Caller passes a Commit-shaped\n// object; we only read the three fields we need to keep this loosely coupled.\nexport function formatCommit(c: { id: string; message: string; timestamp: number }): string {\n return `${chalk.yellow(c.id.slice(0, 7))} ${c.message} ${chalk.gray(timeAgo(c.timestamp))}`;\n}\n\nfunction timeAgo(ts: number): string {\n const s = Math.floor((Date.now() - ts) / 1000);\n if (s < 60) return `${s}s ago`;\n if (s < 3600) return `${Math.floor(s / 60)}m ago`;\n if (s < 86400) return `${Math.floor(s / 3600)}h ago`;\n return `${Math.floor(s / 86400)}d ago`;\n}\n","// `iqgit create <name> [--public|--private]` — registers the repo\n// on-chain. First chain-touching command in a repo's life.\n//\n// in: <name>, --public (default) | --private, --description\n// sdk: GitClient.createRepo({ name, description, isPublic, timestamp })\n// ↑ also pre-creates the per-repo commit table (SDK does this\n// inside createRepo so the first commit() is cheaper)\n// out: writes .iqgit/config.json with { owner, repo, isPublic }\n\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { Command } from \"commander\";\nimport * as repo from \"../core/repo\";\nimport { setup } from \"../setup\";\nimport * as ui from \"../ui\";\n\nexport function register(program: Command): void {\n program\n .command(\"create <name>\")\n .option(\"--public\", \"default visibility\")\n .option(\"--private\")\n .option(\"--description <text>\", \"\", \"\")\n .action(async (\n name: string,\n opts: { public?: boolean; private?: boolean; description: string },\n ) => {\n const cwd = process.cwd();\n if (!existsSync(join(cwd, \".iqgit\"))) repo.initRepo(cwd);\n\n const { client, signer } = await setup();\n const isPublic = !opts.private;\n\n const sp = ui.spinner(`Creating on-chain repo ${name}...`).start();\n try {\n await client.createRepo({\n name,\n description: opts.description,\n isPublic,\n timestamp: Date.now(),\n });\n sp.succeed(`Created ${signer.publicKey.toBase58()}/${name}`);\n } catch (e) {\n sp.fail((e as Error).message);\n process.exit(1);\n }\n\n repo.writeConfig(cwd, {\n owner: signer.publicKey.toBase58(),\n repo: name,\n isPublic,\n });\n\n ui.log.dim(`Next: edit files, then iqgit commit -m \"...\" && iqgit push`);\n });\n}\n","// Pre-flight gate for every write command. Read-only commands skip it\n// (clone, log, registry, restore-against-someone-else's-repo).\n//\n// Returns a ready-to-use GitClient. Centralized here so commands don't\n// duplicate wallet/RPC validation. (CODE-RULES §2 — single source of truth.)\n//\n// sdk: new GitClient({ connection, signer })\n// ↑ imported from \"@iqlabs-official/git-sdk/node\" so the\n// node:crypto SHA-256 backend is wired (required before any\n// commit/status/etc that hashes content).\n//\n// Side effects:\n// • creates ~/.iq-git/ on first run\n// • may write to ~/.iq-git/config.json (rpcUrl) and wallets/default.json\n// • may write SOLANA_RPC_ENDPOINT into ~/.iq-git/.env\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { Connection, Keypair, LAMPORTS_PER_SOL } from \"@solana/web3.js\";\nimport iqlabs from \"@iqlabs-official/solana-sdk\";\nimport { GitClient } from \"@iqlabs-official/git-sdk/node\";\nimport { config as loadEnv } from \"dotenv\";\nimport * as ui from \"./ui\";\n\nconst HOME_DIR = join(homedir(), \".iq-git\");\nconst ENV_PATH = join(HOME_DIR, \".env\");\nconst CONFIG_PATH = join(HOME_DIR, \"config.json\");\nexport const DEFAULT_WALLET = join(HOME_DIR, \"wallets\", \"default.json\");\nconst HELIUS_URL = \"https://www.helius.dev/\";\n\ninterface GlobalConfig {\n walletPath?: string;\n rpcUrl?: string;\n}\n\nexport interface SetupResult {\n client: GitClient;\n signer: Keypair;\n connection: Connection;\n}\n\nexport async function setup(): Promise<SetupResult> {\n mkdirSync(HOME_DIR, { recursive: true });\n loadEnv({ path: ENV_PATH });\n\n const signer = await loadOrCreateWallet();\n const rpcUrl = await loadOrPromptRpc();\n iqlabs.setRpcUrl(rpcUrl);\n const connection = new Connection(rpcUrl, \"confirmed\");\n await healthCheck(connection);\n await maybeWarnBalance(connection, signer);\n\n return { client: new GitClient({ connection, signer }), signer, connection };\n}\n\n// Read-only path for commands that only need to fetch from chain\n// (e.g. commit's base tree, log, registry). Skips wallet prompts AND\n// the RPC health check — when gateway is set, we may never hit the RPC,\n// so a bogus RPC URL shouldn't fail-fast. The actual RPC call (via SDK\n// fallback) will surface its own error if it ever runs.\nexport async function setupReadOnly(): Promise<Connection> {\n mkdirSync(HOME_DIR, { recursive: true });\n loadEnv({ path: ENV_PATH });\n const rpcUrl = await loadOrPromptRpc();\n iqlabs.setRpcUrl(rpcUrl);\n return new Connection(rpcUrl, \"confirmed\");\n}\n\nasync function loadOrCreateWallet(): Promise<Keypair> {\n const cfg = readGlobalConfig();\n let path = cfg.walletPath;\n\n if (!path || !existsSync(path)) {\n const choice = await ui.select({\n message: \"No Solana keypair configured. What would you like to do?\",\n choices: [\n { name: \"Generate a new keypair\", value: \"new\" as const },\n { name: \"Use an existing keypair file\", value: \"existing\" as const },\n ],\n });\n if (choice === \"new\") {\n mkdirSync(dirname(DEFAULT_WALLET), { recursive: true });\n const kp = Keypair.generate();\n writeFileSync(DEFAULT_WALLET, JSON.stringify(Array.from(kp.secretKey)));\n ui.log.success(`Created ${DEFAULT_WALLET}`);\n ui.log.info(`pubkey: ${kp.publicKey.toBase58()}`);\n writeGlobalConfig({ ...cfg, walletPath: DEFAULT_WALLET });\n return kp;\n }\n path = await ui.input({ message: \"Path to keypair JSON file:\" });\n writeGlobalConfig({ ...cfg, walletPath: path });\n }\n\n return loadKeypairFromFile(path);\n}\n\n// Single source of truth for parsing a Solana keypair JSON file. Used by\n// setup() above and wallet.ts:walletShow (CODE-RULES §2).\nexport function loadKeypairFromFile(path: string): Keypair {\n try {\n const secret = JSON.parse(readFileSync(path, \"utf8\")) as number[];\n return Keypair.fromSecretKey(Uint8Array.from(secret));\n } catch (e) {\n ui.fail(`Invalid keypair at ${path}: ${(e as Error).message}`);\n }\n}\n\nasync function loadOrPromptRpc(): Promise<string> {\n const cfg = readGlobalConfig();\n const url = process.env.SOLANA_RPC_ENDPOINT ?? cfg.rpcUrl;\n if (url) return url;\n\n ui.log.warn(\"No Solana RPC endpoint configured.\");\n ui.log.info(`Get a free RPC URL from Helius: ${HELIUS_URL}`);\n const entered = await ui.input({ message: \"Paste your RPC URL:\" });\n appendEnv(\"SOLANA_RPC_ENDPOINT\", entered);\n writeGlobalConfig({ ...cfg, rpcUrl: entered });\n return entered;\n}\n\nasync function healthCheck(connection: Connection): Promise<void> {\n try {\n await connection.getLatestBlockhash();\n } catch (e) {\n ui.fail(`RPC health check failed: ${(e as Error).message}`);\n }\n}\n\nasync function maybeWarnBalance(connection: Connection, signer: Keypair): Promise<void> {\n const lamports = await connection.getBalance(signer.publicKey);\n if (lamports >= 0.01 * LAMPORTS_PER_SOL) return;\n ui.log.warn(\n `Low balance: ${lamports / LAMPORTS_PER_SOL} SOL on ${signer.publicKey.toBase58()}`,\n );\n ui.log.dim(\"On-chain writes need SOL — fund the address before pushing.\");\n}\n\n// Exported because commands/config.ts edits the same file. Single source\n// of truth for shape + path (CODE-RULES §2).\nexport function readGlobalConfig(): GlobalConfig {\n try {\n return JSON.parse(readFileSync(CONFIG_PATH, \"utf8\")) as GlobalConfig;\n } catch {\n return {};\n }\n}\n\nexport function writeGlobalConfig(cfg: GlobalConfig): void {\n mkdirSync(HOME_DIR, { recursive: true });\n writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2));\n}\n\nfunction appendEnv(key: string, value: string): void {\n const line = `${key}=${value}\\n`;\n let existing = \"\";\n try {\n existing = readFileSync(ENV_PATH, \"utf8\");\n } catch {\n // first write\n }\n const stripped = existing\n .split(\"\\n\")\n .filter((l) => !l.startsWith(`${key}=`))\n .join(\"\\n\");\n writeFileSync(ENV_PATH, stripped.endsWith(\"\\n\") || !stripped ? stripped + line : `${stripped}\\n${line}`);\n process.env[key] = value;\n}\n","// `iqgit add <pathspec...>` — stage paths for the next commit.\n//\n// in: one or more pathspecs. \".\" stages every non-ignored file in the repo.\n// Directory args expand to every non-ignored file under them.\n// Single-file args are staged unless ignored (with a notice).\n// sdk: (none)\n// out: writes .iqgit/index.json with merged path set.\n//\n// Mirrors `git add`. The repo-wide file list comes from scan() so the same\n// ignore rules apply here as in commit/status (CODE-RULES §2).\n\nimport { existsSync, statSync } from \"node:fs\";\nimport { isAbsolute, relative, resolve, sep } from \"node:path\";\nimport type { Command } from \"commander\";\nimport * as repo from \"../core/repo\";\nimport { loadIgnore, scan } from \"../core/scan\";\nimport * as ui from \"../ui\";\n\nexport function register(program: Command): void {\n program\n .command(\"add <pathspec...>\")\n .description(\"stage paths for the next commit\")\n .action((pathspecs: string[]) => {\n const cwd = repo.findRepoRoot();\n const allPaths = scan(cwd).map((f) => f.path);\n const ig = loadIgnore(cwd);\n const collected = new Set(repo.readIndex(cwd));\n\n for (const spec of pathspecs) {\n const abs = isAbsolute(spec) ? spec : resolve(process.cwd(), spec);\n if (!existsSync(abs)) ui.fail(`path does not exist: ${spec}`);\n\n if (statSync(abs).isDirectory()) {\n const prefix = relative(cwd, abs).split(sep).join(\"/\");\n const matches = prefix === \"\"\n ? allPaths\n : allPaths.filter((p) => p === prefix || p.startsWith(`${prefix}/`));\n for (const p of matches) collected.add(p);\n } else {\n const rel = relative(cwd, abs).split(sep).join(\"/\");\n if (ig.ignores(rel)) {\n ui.log.dim(`ignored: ${rel}`);\n continue;\n }\n collected.add(rel);\n }\n }\n\n repo.writeIndex(cwd, [...collected]);\n ui.log.success(`staged ${collected.size} path(s)`);\n });\n}\n","// fs walker — the only thing the SDK can't do for us, because the SDK\n// also runs in browsers without `fs`. Produces the `Record<string, string>`\n// shape (path → base64 content) that GitClient.commit() / .status() expect.\n//\n// Reads .gitignore AND .iqgitignore (both optional, both merged via the\n// `ignore` package) plus always-ignore [\".git/\", \".iqgit/\"].\n//\n// Returns enough info that the caller (commit.ts) can warn about >1MB files\n// without re-walking. Hash is sha256(base64) — same convention as SDK\n// (storage.ts:33), so cache lookups match SDK's internal dedup.\n\nimport { createHash } from \"node:crypto\";\nimport { readdirSync, readFileSync } from \"node:fs\";\nimport { join, relative, sep } from \"node:path\";\nimport ignore, { type Ignore } from \"ignore\";\n\nexport interface ScanFile {\n path: string;\n base64: string;\n hash: string;\n size: number;\n}\n\n// Build a ScanFile from a single working-tree path. Used by `add`-driven\n// flows (commit) where the caller already knows which paths to read; the\n// full repo walk in `scan` would over-fetch.\nexport function readScanFile(repoRoot: string, repoRel: string): ScanFile {\n const buf = readFileSync(join(repoRoot, repoRel));\n const base64 = buf.toString(\"base64\");\n return {\n path: repoRel,\n base64,\n hash: createHash(\"sha256\").update(base64).digest(\"hex\"),\n size: buf.byteLength,\n };\n}\n\nexport function loadIgnore(repoRoot: string): Ignore {\n const ig = ignore().add([\".git/\", \".iqgit/\"]);\n for (const name of [\".gitignore\", \".iqgitignore\"]) {\n try {\n ig.add(readFileSync(join(repoRoot, name), \"utf8\"));\n } catch {\n // file absent — fine\n }\n }\n return ig;\n}\n\nexport function scan(repoRoot: string): ScanFile[] {\n const out: ScanFile[] = [];\n walk(repoRoot, repoRoot, loadIgnore(repoRoot), out);\n return out;\n}\n\n// Convert ScanFile[] → Record<string,string> for SDK calls. Inlined as a\n// helper because both commit.ts and status.ts need this exact shape; not\n// worth a generic utility (CODE-RULES §1).\nexport function toScanMap(files: ScanFile[]): Record<string, string> {\n return Object.fromEntries(files.map((f) => [f.path, f.base64]));\n}\n\nfunction walk(root: string, dir: string, ig: Ignore, out: ScanFile[]): void {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const abs = join(dir, entry.name);\n const rel = relative(root, abs).split(sep).join(\"/\");\n const relForIgnore = entry.isDirectory() ? `${rel}/` : rel;\n if (ig.ignores(relForIgnore)) continue;\n\n if (entry.isDirectory()) {\n walk(root, abs, ig, out);\n continue;\n }\n if (entry.isFile()) {\n out.push(readScanFile(root, rel));\n }\n }\n}\n","// `iqgit reset [pathspec...]` — unstage paths.\n//\n// in: zero or more pathspecs. No args = clear the entire index.\n// Directory args remove every staged path under them.\n// sdk: (none)\n// out: rewrites .iqgit/index.json.\n//\n// Mirrors `git reset` (the unstaging half — we don't have HEAD-moving\n// semantics in v1).\n\nimport { isAbsolute, relative, resolve, sep } from \"node:path\";\nimport type { Command } from \"commander\";\nimport * as repo from \"../core/repo\";\nimport * as ui from \"../ui\";\n\nexport function register(program: Command): void {\n program\n .command(\"reset [pathspec...]\")\n .description(\"unstage paths (no args clears the index)\")\n .action((pathspecs: string[]) => {\n const cwd = repo.findRepoRoot();\n\n if (pathspecs.length === 0) {\n repo.writeIndex(cwd, []);\n ui.log.success(\"index cleared\");\n return;\n }\n\n const removeRels = pathspecs.map((spec) => {\n const abs = isAbsolute(spec) ? spec : resolve(process.cwd(), spec);\n return relative(cwd, abs).split(sep).join(\"/\");\n });\n\n const next = repo.readIndex(cwd).filter((p) =>\n !removeRels.some((r) => p === r || p.startsWith(`${r}/`)),\n );\n repo.writeIndex(cwd, next);\n ui.log.success(`index now has ${next.length} path(s)`);\n });\n}\n","// `iqgit commit -m \"msg\"` — LOCAL build of a snapshot, no chain WRITES.\n// Stages a pending commit under .iqgit/pending/ that push.ts will upload.\n//\n// in: -m <message> (required), --no-warn-large\n// reads (gateway-first, SDK fallback): commit history + tree blob\n// when there's a HEAD but no local pending commits — both via\n// core/tree.ts:resolveBaseTree.\n// out: appends pending/NNN-<commitId>/ with meta.json + tree.json + blobs/\n//\n// Snapshot semantics (matches git):\n// final tree = base tree, with index entries overlaid.\n// • base = last pending's tree.json (if any pending exist), else\n// loadTree(HEAD.treeTxId) (if HEAD exists), else\n// {} (first ever commit)\n// • for each indexed path:\n// file exists on disk → set tree[path] from working tree\n// file missing → delete tree[path] (= staged removal)\n//\n// Empty index = nothing to do. We do NOT auto-stage everything; the user\n// runs `iqgit add .` to opt in (matches `git commit` without -a).\n\nimport { randomUUID } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { Command } from \"commander\";\nimport * as repo from \"../core/repo\";\nimport { readScanFile } from \"../core/scan\";\nimport { resolveBaseTree, type Tree } from \"../core/tree\";\nimport { setupReadOnly } from \"../setup\";\nimport * as ui from \"../ui\";\n\nconst LARGE_FILE_THRESHOLD = 1024 * 1024;\n\nexport function register(program: Command): void {\n program\n .command(\"commit\")\n .requiredOption(\"-m, --message <msg>\", \"commit message\")\n .option(\"--no-warn-large\", \"skip 1MB confirmation prompt\")\n .action(async (opts: { message: string; warnLarge: boolean }) => {\n const cwd = repo.findRepoRoot();\n const cfg = repo.readConfig(cwd);\n if (!cfg.owner) ui.fail(\"repo not yet created on-chain — run iqgit create first\");\n\n const indexPaths = repo.readIndex(cwd);\n if (indexPaths.length === 0) {\n ui.fail(\"nothing staged — use `iqgit add <path>` first\");\n }\n\n const stagedFiles = [];\n const stagedDeletes: string[] = [];\n for (const p of indexPaths) {\n if (existsSync(join(cwd, p))) {\n stagedFiles.push(readScanFile(cwd, p));\n } else {\n stagedDeletes.push(p);\n }\n }\n\n const big = stagedFiles.filter((f) => f.size > LARGE_FILE_THRESHOLD);\n if (big.length > 0 && opts.warnLarge) {\n ui.log.warn(\"Large files (>1MB) — on-chain upload will be costly:\");\n for (const b of big) ui.log.info(` ${b.path} ${ui.formatSize(b.size)}`);\n const ok = await ui.confirm({ message: \"Include them?\" });\n if (!ok) {\n ui.log.dim(\"Tip: add to .iqgitignore to skip on-chain upload only.\");\n return;\n }\n }\n\n // Ensure SDK has an RPC configured for the gwFetchRows fallback path.\n await setupReadOnly();\n const sp = ui.spinner(\"fetching base tree from chain...\").start();\n let baseTree: Tree;\n try {\n baseTree = await resolveBaseTree(cwd, cfg.owner, cfg.repo);\n sp.succeed(\"fetched base tree\");\n } catch (e) {\n sp.fail((e as Error).message);\n throw e;\n }\n const tree: Tree = { ...baseTree };\n const blobs = new Map<string, string>();\n for (const f of stagedFiles) {\n tree[f.path] = { hash: f.hash, size: f.size };\n blobs.set(f.hash, f.base64);\n }\n for (const p of stagedDeletes) {\n delete tree[p];\n }\n\n const last = repo.listPending(cwd).at(-1);\n const meta: repo.PendingMeta = {\n id: randomUUID(),\n message: opts.message,\n parentCommitId: last?.meta.id ?? repo.readHead(cwd),\n timestamp: Date.now(),\n author: cfg.owner,\n treeTxId: null,\n committedSig: null,\n };\n repo.appendPending(cwd, meta, tree, blobs);\n repo.writeIndex(cwd, []);\n\n const totalSize = stagedFiles.reduce((sum, f) => sum + f.size, 0);\n ui.log.success(`commit ${meta.id.slice(0, 7)} saved locally`);\n ui.log.info(\n ` ${stagedFiles.length} file(s) added/modified, ` +\n `${stagedDeletes.length} removed, ` +\n `${ui.formatSize(totalSize)}`,\n );\n ui.log.dim(\"Run: iqgit push to upload on-chain\");\n });\n}\n","// Tree resolution shared by commit / status. Pure logic over local pending\n// state and chain reads — no commands here, no UI.\n//\n// `Tree` is the shape stored in pending/<id>/tree.json: {hash, size}.\n// SDK's FileTree adds txId; we strip it on the way in (size=0 placeholder\n// since tree.json sizes are display-only — the real size comes from the\n// working tree when a path is restaged).\n\nimport {\n IQGIT_ROOT_ID,\n commitTableHint,\n} from \"@iqlabs-official/git-sdk/node\";\nimport { getDbRootPda, getTablePda } from \"@iqlabs-official/solana-sdk/contract\";\nimport { toSeedBytes } from \"@iqlabs-official/solana-sdk/utils\";\nimport { gwFetchAllRows, gwLoadTreeJson } from \"./gateway\";\nimport * as repo from \"./repo\";\n\nexport type Tree = Record<string, { hash: string; size: number }>;\n\n// Resolve the base tree against which a new commit (or status diff) layers:\n// 1. last pending's tree.json (purely local), else\n// 2. on-chain tree at HEAD (gwFetchRows + gwLoadTreeJson), else\n// 3. {} for a brand-new repo.\n//\n// Both chain reads route through gateway when GATEWAY_URL is set, falling\n// back to RPC transparently. The SDK's RPC connection must be initialized\n// (via iqlabs.setRpcUrl) before this is called — setup.ts handles that.\nexport async function resolveBaseTree(\n cwd: string,\n owner: string,\n repoName: string,\n): Promise<Tree> {\n const last = repo.listPending(cwd).at(-1);\n if (last) return repo.readPendingTree(last);\n\n const head = repo.readHead(cwd);\n if (head === null) return {};\n\n const dbRoot = getDbRootPda(toSeedBytes(IQGIT_ROOT_ID));\n const commitTable = getTablePda(dbRoot, toSeedBytes(commitTableHint(owner, repoName)));\n const history = (await gwFetchAllRows(commitTable.toBase58(), 200)) as Array<{\n id: string;\n treeTxId: string;\n }>;\n\n const headCommit = history.find((c) => c.id === head);\n if (!headCommit) {\n throw new Error(`HEAD ${head.slice(0, 7)} not found in on-chain history`);\n }\n const onChain = await gwLoadTreeJson<Record<string, { txId: string; hash: string }>>(headCommit.treeTxId);\n const out: Tree = {};\n for (const [p, entry] of Object.entries(onChain)) {\n out[p] = { hash: entry.hash, size: 0 };\n }\n return out;\n}\n","// Optional gateway-aware reads. Pattern + URL list mirror\n// iq-chan/src/lib/config.ts: try the primary gateway, then the Akash\n// direct ingress, then the backup gateway, then fall back to direct RPC.\n//\n// Why route reads through gateway:\n// - free RPCs (Helius free tier) rate-limit getTransaction; the SDK's\n// readTableRows fans out to N getTransaction calls per table. Gateway\n// has its own RPC + 3-tier cache so its reads don't burn the user's\n// RPC quota.\n// - decentralized: anyone can run a gateway. iqgit isn't tied to one.\n//\n// Configuration:\n// (no env) default 3-gateway chain (recommended)\n// GATEWAY_URL=https://my.example single override, then RPC fallback\n// GATEWAY_URL=url1,url2,url3 comma-separated list, tried in order\n// GATEWAY_URL=off disable gateway, all reads via RPC\n\nimport iqlabs from \"@iqlabs-official/solana-sdk\";\nimport { loadBlob, loadTree } from \"@iqlabs-official/git-sdk/node\";\n\n// Defaults match iq-chan/src/lib/config.ts so iqgit, blockchan and any\n// other consumer hit the same 3 read endpoints.\nconst DEFAULT_GATEWAYS = [\n \"https://gateway.solanainternet.com\",\n \"https://gateway.iqlabs.dev\",\n \"https://fem4pe7sthdm5f9fkhc1fnmpos.ingress.akashprovid.com\",\n \"https://fem4pe7sthdm5f9fkhc1fnmpos.ingress.cpu.aesservices.net\",\n];\n\nfunction getGatewayUrls(): string[] {\n const raw = process.env.GATEWAY_URL?.trim();\n if (raw === undefined || raw === \"\") return DEFAULT_GATEWAYS;\n if (raw.toLowerCase() === \"off\") return [];\n return raw.split(\",\").map((s) => s.trim()).filter(Boolean);\n}\n\n// Try each gateway in order with a per-request timeout. Returns the first\n// 2xx Response, or null if all gateways failed (network error or non-2xx).\nasync function gwFetch(path: string, timeoutMs = 8000): Promise<Response | null> {\n for (const base of getGatewayUrls()) {\n try {\n const res = await fetch(`${base}${path}`, { signal: AbortSignal.timeout(timeoutMs) });\n if (res.ok) return res;\n } catch {\n // try next gateway\n }\n }\n return null;\n}\n\n// Fetch rows for a table PDA. Always returns rows[] — gateway chain first,\n// SDK readTableRows (which uses the global RPC) on full gateway failure.\n// The SDK's RPC URL must be initialized via iqlabs.setRpcUrl before this\n// is called; setup.ts handles that.\nexport async function gwFetchRows(\n tablePda: string,\n limit = 50,\n before?: string,\n): Promise<Record<string, unknown>[]> {\n const path = `/table/${tablePda}/rows?limit=${limit}` + (before ? `&before=${before}` : \"\");\n const res = await gwFetch(path);\n if (res !== null) {\n try {\n const data = (await res.json()) as { rows?: Record<string, unknown>[] };\n return data.rows ?? [];\n } catch {\n // fall through to SDK\n }\n }\n return iqlabs.reader.readTableRows(tablePda, { limit, before });\n}\n\n// Page through gwFetchRows until at least maxRows or the gateway returns\n// fewer than asked (signals end of table).\nexport async function gwFetchAllRows(\n tablePda: string,\n maxRows = 200,\n): Promise<Record<string, unknown>[]> {\n const all: Record<string, unknown>[] = [];\n let before: string | undefined;\n while (all.length < maxRows) {\n const limit = Math.min(50, maxRows - all.length);\n const rows = await gwFetchRows(tablePda, limit, before);\n all.push(...rows);\n if (rows.length < limit) break;\n const last = rows[rows.length - 1] as { __txSignature?: string };\n if (!last.__txSignature) break;\n before = last.__txSignature;\n }\n return all;\n}\n\n// Load a JSON blob by tx signature. Gateway-first via /data/{sig}, falls\n// back to SDK's loadTree (RPC) on full chain failure.\nexport async function gwLoadTreeJson<T>(txSignature: string): Promise<T> {\n const res = await gwFetch(`/data/${txSignature}`);\n if (res !== null) {\n try {\n const env = (await res.json()) as { data?: string };\n if (typeof env.data === \"string\") return JSON.parse(env.data) as T;\n } catch {\n // fall through\n }\n }\n return (await loadTree(txSignature)) as T;\n}\n\n// Load a base64 blob by tx signature, gateway-first. Falls back to SDK's\n// loadBlob (RPC) on any gateway failure. Used for clone's per-file blob\n// fetches; gateway's /data/{sig} handles inline/linked-list/session\n// reassembly internally so callers don't need three code paths.\nexport async function gwLoadBlobBase64(txSignature: string): Promise<string> {\n const res = await gwFetch(`/data/${txSignature}`);\n if (res !== null) {\n try {\n const env = (await res.json()) as { data?: string };\n if (typeof env.data === \"string\") return env.data;\n } catch {\n // fall through\n }\n }\n return await loadBlob(txSignature);\n}\n\n// Fire-and-forget cache-warm hint after a write. Tries each gateway until\n// one ack-2xxs. Failures swallowed — the row is on chain, gateways will\n// pick it up on their next poll regardless.\nexport async function gwNotify(\n tablePda: string,\n txSignature: string,\n row?: Record<string, unknown>,\n signer?: string,\n): Promise<void> {\n const body = JSON.stringify({ txSignature, row, signer });\n for (const base of getGatewayUrls()) {\n try {\n const res = await fetch(`${base}/table/${tablePda}/notify`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body,\n signal: AbortSignal.timeout(3000),\n });\n if (res.ok) return;\n } catch {\n // try next gateway\n }\n }\n}\n","// `iqgit push` — drains .iqgit/pending/ to chain. The single most\n// involved command; everything else is short. Resume-safe by design.\n//\n// in: (no flags in v1; --dry-run could be added later)\n// sdk: NOT GitClient.commit() directly — we re-implement the workflow\n// because we need granular cache between blob/tree/row steps.\n// Per pending commit, we call the SDK's layer-level fns\n// (re-exported from the SDK root entry as of 2026-05-05):\n// • uploadBlob(connection, signer, relativePath, base64, reuse, onProgress?)\n// — per blob. We pass `reuse={}` because our upload-cache\n// already filtered hits before the call.\n// • uploadTree(connection, signer, tree)\n// — once per pending commit, after all blobs done.\n// • writeCommit(connection, signer, repoName, commit)\n// — once per pending commit, last step.\n//\n// Resume invariants:\n// • A blob's cache entry is written ONLY after uploadBlob returns.\n// • Tree's txId is persisted into pending/NNN/meta.json BEFORE writing\n// the commit row. If row write fails, next push reuses the tree.\n// • Commit row's signature is persisted into meta.json BEFORE deleting\n// the pending dir. If we crash between those two, next push sees\n// committedSig present and just cleans up + advances HEAD.\n\nimport type { Connection, Keypair } from \"@solana/web3.js\";\nimport type { Command } from \"commander\";\nimport { IQGIT_ROOT_ID,\n commitTableHint,\n uploadBlob,\n uploadTree,\n writeCommit,\n type Commit,\n type FileTree,\n} from \"@iqlabs-official/git-sdk/node\";\nimport { getDbRootPda, getTablePda } from \"@iqlabs-official/solana-sdk/contract\";\nimport { toSeedBytes } from \"@iqlabs-official/solana-sdk/utils\";\nimport { gwNotify } from \"../core/gateway\";\n\nimport * as repo from \"../core/repo\";\nimport { setup } from \"../setup\";\nimport * as ui from \"../ui\";\n\nexport function register(program: Command): void {\n program.command(\"push\").action(async () => {\n const cwd = repo.findRepoRoot();\n const cfg = repo.readConfig(cwd);\n const queue = repo.listPending(cwd);\n if (queue.length === 0) {\n ui.log.info(\"nothing to push\");\n return;\n }\n const { signer, connection } = await setup();\n\n for (const p of queue) {\n ui.log.info(`pushing ${p.meta.id.slice(0, 7)} \"${p.meta.message}\"`);\n try {\n await pushOne(connection, signer, cwd, cfg.repo, p);\n } catch (e) {\n ui.fail(\n `failed at ${p.meta.id.slice(0, 7)}: ${(e as Error).message}\\n` +\n `re-run \"iqgit push\" to resume.`,\n );\n }\n repo.writeHead(cwd, p.meta.id);\n repo.discardPending(p);\n ui.log.success(` pushed ${p.meta.id.slice(0, 7)}`);\n }\n });\n}\n\nasync function pushOne(\n connection: Connection,\n signer: Keypair,\n cwd: string,\n repoName: string,\n p: repo.PendingCommit,\n): Promise<void> {\n const tree = repo.readPendingTree(p);\n const newTree: FileTree = {};\n\n // ---- 1. blobs ----\n const total = Object.keys(tree).length;\n const sp = ui.spinner(` blobs 0/${total}`).start();\n let done = 0;\n let reused = 0;\n\n for (const [path, { hash }] of Object.entries(tree)) {\n const cached = repo.cacheGet(cwd, hash);\n if (cached) {\n newTree[path] = { txId: cached.txId, hash };\n reused++;\n } else {\n const base64 = repo.readPendingBlob(p, hash);\n const { txId } = await uploadBlob(connection, signer, path, base64, {});\n repo.cacheSet(cwd, hash, { txId, uploadedAt: Date.now() });\n newTree[path] = { txId, hash };\n }\n done++;\n sp.text = ` blobs ${done}/${total} (${reused} reused)`;\n }\n sp.succeed(` blobs ${done}/${total} (${reused} reused)`);\n\n // ---- 2. tree ----\n let treeTxId = p.meta.treeTxId;\n if (!treeTxId) {\n treeTxId = await uploadTree(connection, signer, newTree);\n repo.updatePendingMeta(p, { treeTxId });\n }\n\n // ---- 3. commit row ----\n if (!p.meta.committedSig) {\n const commit: Commit = {\n id: p.meta.id,\n message: p.meta.message,\n treeTxId,\n parentCommitId: p.meta.parentCommitId ?? undefined,\n timestamp: p.meta.timestamp,\n author: p.meta.author,\n };\n const sig = await writeCommit(connection, signer, repoName, commit);\n repo.updatePendingMeta(p, { committedSig: sig });\n // Cache warm hint to gateway — fire-and-forget, gateway will pull tx\n // on its own anyway.\n const dbRoot = getDbRootPda(toSeedBytes(IQGIT_ROOT_ID));\n const tablePda = getTablePda(dbRoot, toSeedBytes(commitTableHint(commit.author, repoName)));\n void gwNotify(tablePda.toBase58(), sig, undefined, signer.publicKey.toBase58());\n }\n}\n","// `iqgit clone <owner>/<repo> [dir]` — pulls latest snapshot to disk.\n// Read-only and anonymous: no wallet required. Cloning a public repo\n// only needs an RPC (for SDK fallback) and optionally a gateway.\n//\n// in: <owner>/<repo>, optional [dir] (default = repo name)\n// reads (gateway-first, RPC fallback):\n// gwFetchAllRows on git_commits:<owner>:<repo> → newest commit row\n// gwLoadTreeJson on commit.treeTxId → tree.json\n// gwLoadBlobBase64 per file txId → file bytes\n// gwFetchAllRows on git_repos_v2_<owner> → isPublic for config\n// out: directory tree on disk + initialized .iqgit/ with HEAD set so\n// future `status` / `commit` work without re-resolving.\n\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { Buffer } from \"node:buffer\";\nimport type { Command } from \"commander\";\nimport {\n IQGIT_ROOT_ID,\n commitTableHint,\n repoListHint,\n} from \"@iqlabs-official/git-sdk/node\";\nimport { getDbRootPda, getTablePda } from \"@iqlabs-official/solana-sdk/contract\";\nimport { toSeedBytes } from \"@iqlabs-official/solana-sdk/utils\";\nimport * as repo from \"../core/repo\";\nimport { gwFetchAllRows, gwLoadBlobBase64, gwLoadTreeJson } from \"../core/gateway\";\nimport { setupReadOnly } from \"../setup\";\nimport * as ui from \"../ui\";\n\nexport function register(program: Command): void {\n program\n .command(\"clone <slug> [dir]\")\n .action(async (slug: string, dir: string | undefined) => {\n const [owner, repoName] = slug.split(\"/\");\n if (!owner || !repoName) ui.fail(\"expected <owner>/<repo>\");\n const target = dir ?? repoName;\n if (existsSync(target)) ui.fail(`${target} already exists`);\n mkdirSync(target, { recursive: true });\n\n // Initialize SDK RPC for the gateway functions' fallback paths.\n // No wallet prompt — clone is read-only.\n await setupReadOnly();\n\n const dbRoot = getDbRootPda(toSeedBytes(IQGIT_ROOT_ID));\n\n const sp = ui.spinner(`cloning ${slug}...`).start();\n\n // 1. latest commit\n const commitTable = getTablePda(dbRoot, toSeedBytes(commitTableHint(owner, repoName)));\n const commits = await gwFetchAllRows(commitTable.toBase58(), 200);\n if (commits.length === 0) {\n sp.fail(`no commits in ${slug}`);\n process.exit(1);\n }\n const latest = [...commits].sort(\n (a, b) => ((b as { timestamp?: number }).timestamp ?? 0) - ((a as { timestamp?: number }).timestamp ?? 0),\n )[0] as { id: string; treeTxId: string };\n\n // 2. tree\n const tree = await gwLoadTreeJson<Record<string, { txId: string; hash: string }>>(latest.treeTxId);\n const paths = Object.entries(tree);\n\n // 3. blobs — one per file\n let i = 0;\n for (const [path, entry] of paths) {\n i++;\n sp.text = `cloning ${slug}... (${i}/${paths.length}) ${path}`;\n const base64 = await gwLoadBlobBase64(entry.txId);\n const abs = join(target, path);\n mkdirSync(dirname(abs), { recursive: true });\n writeFileSync(abs, Buffer.from(base64, \"base64\"));\n }\n sp.succeed(`cloned ${paths.length} file(s) to ${target}/`);\n\n // 4. local config — read on-chain isPublic so cloned config is accurate\n const ownerListPda = getTablePda(dbRoot, toSeedBytes(repoListHint(owner)));\n const repos = await gwFetchAllRows(ownerListPda.toBase58(), 200);\n const meta = repos.find((r) => (r as { name?: string }).name === repoName) as\n | { isPublic?: boolean }\n | undefined;\n const isPublic = meta?.isPublic ?? true;\n\n repo.initRepo(target);\n repo.writeConfig(target, { owner, repo: repoName, isPublic });\n repo.writeHead(target, latest.id);\n });\n}\n","// `iqgit restore [commitId]` — restore working tree to a commit's\n// snapshot. Defaults to \"latest\" (functionally a re-pull).\n//\n// NAMING NOTE: in git this would be `checkout`, but git's `checkout` is\n// overloaded with branch-switching, which we don't have in v1. Calling\n// it `restore` matches `git restore --source=<commit>` and is unambiguous.\n// FUTURE: when branches land, a real `checkout` command may be added for\n// branch-switching, and this `restore` may be folded into it.\n//\n// in: optional <commitId> (full or short prefix); default = \"latest\"\n// sdk: GitClient.checkout(repoName, commitId | \"latest\", sink)\n// out: overwrites/creates files in cwd from the target tree;\n// updates .iqgit/HEAD only when restore(\"latest\").\n//\n// SAFETY: this destroys uncommitted local changes. We bail unless\n// `iqgit status` shows clean OR --force is passed.\n\nimport { mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport type { Command } from \"commander\";\nimport * as repo from \"../core/repo\";\nimport { scan, toScanMap } from \"../core/scan\";\nimport { setup } from \"../setup\";\nimport * as ui from \"../ui\";\n\nexport function register(program: Command): void {\n program\n .command(\"restore [commitId]\")\n .option(\"--force\", \"discard uncommitted changes\")\n .action(async (commitId: string | undefined, opts: { force?: boolean }) => {\n const cwd = repo.findRepoRoot();\n const cfg = repo.readConfig(cwd);\n const { client } = await setup();\n\n if (!opts.force) {\n const { added, modified } = await client.status(\n cfg.owner,\n cfg.repo,\n toScanMap(scan(cwd)),\n );\n if (added.length || modified.length) {\n ui.fail(\"uncommitted changes — commit them or pass --force\");\n }\n }\n\n const target = commitId ?? \"latest\";\n const sp = ui.spinner(`restoring ${target}...`).start();\n const c = await client.checkout(cfg.repo, target, async (path, base64) => {\n const abs = join(cwd, path);\n mkdirSync(dirname(abs), { recursive: true });\n writeFileSync(abs, Buffer.from(base64, \"base64\"));\n });\n sp.succeed(`restored ${c.id.slice(0, 7)} \"${c.message}\"`);\n\n if (target === \"latest\") repo.writeHead(cwd, c.id);\n });\n}\n","// `iqgit log [--limit N]` — print commit history newest-first.\n// Read-only. Uses gwFetchRows which transparently routes through the\n// gateway when GATEWAY_URL is set, falls back to direct RPC otherwise.\n//\n// in: optional --limit <n>, --owner <pubkey>, --repo <name>\n//\n// Owner/repo default from .iqgit/config.json so users can `cd` into a\n// cloned repo and just run `iqgit log`. Override flags exist for peeking\n// at someone else's repo without cloning.\n\nimport type { Command } from \"commander\";\nimport {\n IQGIT_ROOT_ID,\n commitTableHint,\n type Commit,\n} from \"@iqlabs-official/git-sdk/node\";\nimport { getDbRootPda, getTablePda } from \"@iqlabs-official/solana-sdk/contract\";\nimport { toSeedBytes } from \"@iqlabs-official/solana-sdk/utils\";\nimport * as repo from \"../core/repo\";\nimport { gwFetchAllRows } from \"../core/gateway\";\nimport { setupReadOnly } from \"../setup\";\nimport * as ui from \"../ui\";\n\nexport function register(program: Command): void {\n program\n .command(\"log\")\n .option(\"--limit <n>\", \"max entries\", \"20\")\n .option(\"--owner <pubkey>\")\n .option(\"--repo <name>\")\n .action(async (opts: { limit: string; owner?: string; repo?: string }) => {\n let owner = opts.owner;\n let repoName = opts.repo;\n if (!owner || !repoName) {\n const cfg = repo.readConfig(repo.findRepoRoot());\n owner ??= cfg.owner;\n repoName ??= cfg.repo;\n }\n // Ensure SDK has an RPC configured for the gwFetchRows fallback path.\n await setupReadOnly();\n\n const dbRoot = getDbRootPda(toSeedBytes(IQGIT_ROOT_ID));\n const tablePda = getTablePda(dbRoot, toSeedBytes(commitTableHint(owner, repoName)));\n const commits = (await gwFetchAllRows(tablePda.toBase58(), Number(opts.limit))) as unknown as Commit[];\n\n // Gateway returns rows in chain order; SDK returns newest-first. Sort\n // here unconditionally so output is stable regardless of source.\n const sorted = [...commits].sort((a, b) => b.timestamp - a.timestamp);\n for (const c of sorted) {\n ui.log.info(ui.formatCommit(c));\n ui.log.dim(` author: ${c.author}`);\n ui.log.dim(` tree: ${c.treeTxId}`);\n ui.log.info(\"\");\n }\n });\n}\n","// `iqgit status` — four-tier view, mirrors git plus our pending layer:\n//\n// remote (HEAD on chain) ── what was last pushed\n// │\n// ▼\n// pending (.iqgit/pending/) ── committed locally, not yet on chain\n// │\n// ▼\n// index (.iqgit/index.json) ── staged for the next commit\n// │\n// ▼\n// working tree (cwd files) ── on disk\n//\n// We diff working tree vs base tree (last pending → on-chain HEAD → empty)\n// to label each path: staged / unstaged-modified / unstaged-added /\n// unstaged-deleted. The base resolution reuses core/tree.ts so commit and\n// status agree on what \"current state\" means (CODE-RULES §2).\n\nimport type { Command } from \"commander\";\nimport * as repo from \"../core/repo\";\nimport { scan } from \"../core/scan\";\nimport { resolveBaseTree } from \"../core/tree\";\nimport { setupReadOnly } from \"../setup\";\nimport * as ui from \"../ui\";\n\nexport function register(program: Command): void {\n program.command(\"status\").action(async () => {\n const cwd = repo.findRepoRoot();\n const cfg = repo.readConfig(cwd);\n const head = repo.readHead(cwd);\n const pending = repo.listPending(cwd);\n const index = new Set(repo.readIndex(cwd));\n const files = scan(cwd);\n const filesByPath = new Map(files.map((f) => [f.path, f]));\n\n // Initialize SDK RPC for the gwFetchRows fallback path; resolveBaseTree\n // skips chain reads entirely when local pending exists or HEAD is null.\n if (pending.length === 0 && head !== null) await setupReadOnly();\n const base = await resolveBaseTree(cwd, cfg.owner, cfg.repo);\n\n const stagedAddedOrModified: string[] = [];\n const stagedDeleted: string[] = [];\n const unstagedAdded: string[] = [];\n const unstagedModified: string[] = [];\n const unstagedDeleted: string[] = [];\n\n // Paths present in base, working tree, or both.\n const allPaths = new Set([...Object.keys(base), ...files.map((f) => f.path)]);\n for (const p of allPaths) {\n const inBase = base[p];\n const inWorking = filesByPath.get(p);\n const isStaged = index.has(p);\n\n if (inWorking && !inBase) {\n (isStaged ? stagedAddedOrModified : unstagedAdded).push(p);\n } else if (!inWorking && inBase) {\n (isStaged ? stagedDeleted : unstagedDeleted).push(p);\n } else if (inWorking && inBase && inWorking.hash !== inBase.hash) {\n (isStaged ? stagedAddedOrModified : unstagedModified).push(p);\n }\n }\n\n ui.log.info(`On HEAD: ${head ? head.slice(0, 7) : \"(no commits yet)\"}`);\n\n if (pending.length) {\n ui.log.info(\"\");\n ui.log.info(`Pending commits (not yet pushed): ${pending.length}`);\n for (const p of pending) {\n ui.log.info(` ${p.meta.id.slice(0, 7)} \"${p.meta.message}\"`);\n }\n }\n\n if (stagedAddedOrModified.length || stagedDeleted.length) {\n ui.log.info(\"\");\n ui.log.info(\"Staged for next commit:\");\n for (const f of stagedAddedOrModified) ui.log.info(` ${f}`);\n for (const f of stagedDeleted) ui.log.info(` deleted: ${f}`);\n }\n\n if (unstagedAdded.length || unstagedModified.length || unstagedDeleted.length) {\n ui.log.info(\"\");\n ui.log.info(\"Unstaged changes:\");\n for (const f of unstagedAdded) ui.log.info(` added: ${f}`);\n for (const f of unstagedModified) ui.log.info(` modified: ${f}`);\n for (const f of unstagedDeleted) ui.log.info(` deleted: ${f}`);\n }\n\n const clean =\n pending.length === 0 &&\n stagedAddedOrModified.length === 0 &&\n stagedDeleted.length === 0 &&\n unstagedAdded.length === 0 &&\n unstagedModified.length === 0 &&\n unstagedDeleted.length === 0;\n if (clean) ui.log.info(\"clean\");\n });\n}\n","// `iqgit registry` — browse the public gallery (git_repos:all). Read-only.\n\nimport type { Command } from \"commander\";\nimport {\n IQGIT_ROOT_ID,\n REGISTRY_HINT,\n type RegistryEntry,\n} from \"@iqlabs-official/git-sdk/node\";\nimport { getDbRootPda, getTablePda } from \"@iqlabs-official/solana-sdk/contract\";\nimport { toSeedBytes } from \"@iqlabs-official/solana-sdk/utils\";\nimport { gwFetchAllRows } from \"../core/gateway\";\nimport { setupReadOnly } from \"../setup\";\nimport * as ui from \"../ui\";\n\nexport function register(program: Command): void {\n program\n .command(\"registry\")\n .description(\"browse the public on-chain repo gallery\")\n .option(\"--limit <n>\", \"max entries\", \"20\")\n .action(async (opts: { limit: string }) => {\n await setupReadOnly();\n const dbRoot = getDbRootPda(toSeedBytes(IQGIT_ROOT_ID));\n const tablePda = getTablePda(dbRoot, toSeedBytes(REGISTRY_HINT));\n const entries = (await gwFetchAllRows(tablePda.toBase58(), Number(opts.limit))) as unknown as RegistryEntry[];\n if (entries.length === 0) {\n ui.log.dim(\"registry empty\");\n return;\n }\n for (const e of entries) {\n ui.log.info(`${e.owner.slice(0, 8)}…/${e.repo} ${e.description ?? \"\"}`);\n }\n });\n}\n","// `iqgit config`: get/set values in ~/.iq-git/config.json.\n// Mirrors `git config` ergonomics but for the global CLI config only\n// (not per-repo). Per-repo config is just .iqgit/config.json which\n// commands edit directly.\n//\n// in: no args → list all\n// <key> → print value\n// <key> <value> → set + persist\n// --unset <key> → remove key\n// sdk: (none)\n// out: stdout\n\nimport type { Command } from \"commander\";\nimport { readGlobalConfig, writeGlobalConfig } from \"../setup\";\nimport * as ui from \"../ui\";\n\nconst KNOWN_KEYS = [\"walletPath\", \"rpcUrl\"] as const;\n\nexport function register(program: Command): void {\n program\n .command(\"config [key] [value]\")\n .description(\"get or set global config (keys: walletPath, rpcUrl)\")\n .addHelpText(\"after\", `\nExamples:\n iqgit config list all\n iqgit config rpcUrl print current RPC URL\n iqgit config rpcUrl \"https://my-rpc.example\" change RPC URL\n iqgit config --unset rpcUrl reset (re-prompts next run)`)\n .option(\"--unset <key>\")\n .action((key: string | undefined, value: string | undefined, opts: { unset?: string }) => {\n const cfg = readGlobalConfig() as Record<string, string | undefined>;\n\n if (opts.unset) {\n ensureKnown(opts.unset);\n delete cfg[opts.unset];\n writeGlobalConfig(cfg);\n ui.log.success(`unset ${opts.unset}`);\n return;\n }\n if (!key) {\n for (const [k, v] of Object.entries(cfg)) {\n if (v !== undefined) ui.log.info(`${k}=${v}`);\n }\n return;\n }\n ensureKnown(key);\n if (value === undefined) {\n ui.log.info(cfg[key] ?? \"\");\n return;\n }\n cfg[key] = value;\n writeGlobalConfig(cfg);\n ui.log.success(`set ${key}=${value}`);\n });\n}\n\nfunction ensureKnown(key: string): void {\n if (!(KNOWN_KEYS as readonly string[]).includes(key)) {\n ui.fail(`unknown config key: ${key}\\nknown: ${KNOWN_KEYS.join(\", \")}`);\n }\n}\n","// `iqgit wallet <action>` — manage keypair. Multiple actions in one file\n// (CODE-RULES §1: don't fan out into wallet/new.ts, wallet/show.ts ...\n// when each is 10 lines).\n//\n// in: iqgit wallet new → generate Keypair, save to ~/.iq-git/wallets/default.json\n// iqgit wallet show → print pubkey + path\n// iqgit wallet balance → print SOL balance\n// iqgit wallet repos → list repos owned by current pubkey\n// reads: gwFetchAllRows on git_repos_v2_<owner> (for `repos` action)\n// out: stdout\n\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { Command } from \"commander\";\nimport { Keypair, LAMPORTS_PER_SOL } from \"@solana/web3.js\";\nimport { IQGIT_ROOT_ID, repoListHint } from \"@iqlabs-official/git-sdk/node\";\nimport { getDbRootPda, getTablePda } from \"@iqlabs-official/solana-sdk/contract\";\nimport { toSeedBytes } from \"@iqlabs-official/solana-sdk/utils\";\nimport { gwFetchAllRows } from \"../core/gateway\";\nimport { DEFAULT_WALLET, loadKeypairFromFile, readGlobalConfig, setup } from \"../setup\";\n\nimport * as ui from \"../ui\";\n\nexport function register(program: Command): void {\n program\n .command(\"wallet <action>\")\n .description(\"new | show | balance | repos\")\n .action(async (action: string) => {\n switch (action) {\n case \"new\":\n return walletNew();\n case \"show\":\n return walletShow();\n case \"balance\":\n return walletBalance();\n case \"repos\":\n return walletRepos();\n default:\n ui.fail(`unknown action: ${action}`);\n }\n });\n}\n\nfunction walletNew(): void {\n if (existsSync(DEFAULT_WALLET)) {\n ui.fail(`default wallet exists at ${DEFAULT_WALLET}; remove it first`);\n }\n mkdirSync(dirname(DEFAULT_WALLET), { recursive: true });\n const kp = Keypair.generate();\n writeFileSync(DEFAULT_WALLET, JSON.stringify(Array.from(kp.secretKey)));\n ui.log.success(`created ${DEFAULT_WALLET}`);\n ui.log.info(`pubkey: ${kp.publicKey.toBase58()}`);\n}\n\nfunction walletShow(): void {\n const path = readGlobalConfig().walletPath ?? DEFAULT_WALLET;\n const kp = loadKeypairFromFile(path);\n ui.log.info(`path: ${path}`);\n ui.log.info(`pubkey: ${kp.publicKey.toBase58()}`);\n}\n\nasync function walletBalance(): Promise<void> {\n const { signer, connection } = await setup();\n const lamports = await connection.getBalance(signer.publicKey);\n ui.log.info(signer.publicKey.toBase58());\n ui.log.info(`${lamports / LAMPORTS_PER_SOL} SOL`);\n}\n\nasync function walletRepos(): Promise<void> {\n const { signer } = await setup();\n // Gateway-first read of git_repos_v2_<owner>; falls through to RPC.\n const owner = signer.publicKey.toBase58();\n const dbRoot = getDbRootPda(toSeedBytes(IQGIT_ROOT_ID));\n const tablePda = getTablePda(dbRoot, toSeedBytes(repoListHint(owner)));\n const repos = (await gwFetchAllRows(tablePda.toBase58(), 200)) as Array<{\n name: string; description: string; isPublic: boolean;\n }>;\n if (repos.length === 0) {\n ui.log.dim(\"no repos yet\");\n return;\n }\n for (const r of repos) {\n const visibility = r.isPublic ? \"public \" : \"private\";\n ui.log.info(`${visibility} ${r.name} ${r.description}`);\n }\n}\n"],"mappings":"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","names":["existsSync","join","program","existsSync","join","existsSync","join","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","join","join","mkdirSync","existsSync","dirname","writeFileSync","readFileSync","register","program","existsSync","join","existsSync","relative","sep","readdirSync","readFileSync","join","register","program","existsSync","relative","sep","isAbsolute","relative","resolve","sep","register","program","isAbsolute","resolve","relative","sep","existsSync","join","iqlabs","register","program","existsSync","join","IQGIT_ROOT_ID","commitTableHint","getDbRootPda","getTablePda","toSeedBytes","register","program","getDbRootPda","toSeedBytes","IQGIT_ROOT_ID","getTablePda","commitTableHint","existsSync","mkdirSync","writeFileSync","dirname","join","Buffer","IQGIT_ROOT_ID","commitTableHint","getDbRootPda","getTablePda","toSeedBytes","register","program","existsSync","mkdirSync","getDbRootPda","toSeedBytes","IQGIT_ROOT_ID","getTablePda","commitTableHint","join","dirname","writeFileSync","Buffer","mkdirSync","writeFileSync","dirname","join","register","program","join","mkdirSync","dirname","writeFileSync","IQGIT_ROOT_ID","commitTableHint","getDbRootPda","getTablePda","toSeedBytes","register","program","getDbRootPda","toSeedBytes","IQGIT_ROOT_ID","getTablePda","commitTableHint","register","program","IQGIT_ROOT_ID","getDbRootPda","getTablePda","toSeedBytes","register","program","getDbRootPda","toSeedBytes","IQGIT_ROOT_ID","getTablePda","register","program","existsSync","mkdirSync","writeFileSync","dirname","Keypair","LAMPORTS_PER_SOL","IQGIT_ROOT_ID","repoListHint","getDbRootPda","getTablePda","toSeedBytes","register","program","existsSync","mkdirSync","dirname","Keypair","writeFileSync","LAMPORTS_PER_SOL","getDbRootPda","toSeedBytes","IQGIT_ROOT_ID","getTablePda","repoListHint","register"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iqlabs-official/iq-git-cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Command-line client for on-chain Git on Solana. Talks to @iqlabs-official/git-sdk to commit, push, clone, and browse repos stored entirely on chain.",
5
5
  "keywords": [
6
6
  "solana",
@@ -32,10 +32,10 @@
32
32
  "test:e2e": "bun tests/e2e/full-cycle.test.ts"
33
33
  },
34
34
  "dependencies": {
35
- "@iqlabs-official/git-sdk": "^0.1.4",
35
+ "@inquirer/prompts": "^5.0.0",
36
+ "@iqlabs-official/git-sdk": "^0.1.5",
36
37
  "@iqlabs-official/solana-sdk": "^0.1.21",
37
38
  "@solana/web3.js": "^1.98.0",
38
- "@inquirer/prompts": "^5.0.0",
39
39
  "chalk": "^5.3.0",
40
40
  "commander": "^12.0.0",
41
41
  "dotenv": "^16.4.0",