@agent-native/core 0.12.24 → 0.12.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/dist/agent/production-agent.d.ts +9 -2
  2. package/dist/agent/production-agent.d.ts.map +1 -1
  3. package/dist/agent/production-agent.js +56 -37
  4. package/dist/agent/production-agent.js.map +1 -1
  5. package/dist/agent/thread-data-builder.d.ts +16 -1
  6. package/dist/agent/thread-data-builder.d.ts.map +1 -1
  7. package/dist/agent/thread-data-builder.js +132 -0
  8. package/dist/agent/thread-data-builder.js.map +1 -1
  9. package/dist/client/AgentTaskCard.d.ts.map +1 -1
  10. package/dist/client/AgentTaskCard.js +16 -3
  11. package/dist/client/AgentTaskCard.js.map +1 -1
  12. package/dist/client/AssistantChat.d.ts.map +1 -1
  13. package/dist/client/AssistantChat.js +22 -12
  14. package/dist/client/AssistantChat.js.map +1 -1
  15. package/dist/client/IframeEmbed.d.ts.map +1 -1
  16. package/dist/client/IframeEmbed.js +2 -2
  17. package/dist/client/IframeEmbed.js.map +1 -1
  18. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  19. package/dist/client/agent-chat-adapter.js +77 -12
  20. package/dist/client/agent-chat-adapter.js.map +1 -1
  21. package/dist/client/composer/ComposerPlusMenu.d.ts.map +1 -1
  22. package/dist/client/composer/ComposerPlusMenu.js +1 -1
  23. package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
  24. package/dist/client/composer/PromptComposer.d.ts.map +1 -1
  25. package/dist/client/composer/PromptComposer.js +8 -7
  26. package/dist/client/composer/PromptComposer.js.map +1 -1
  27. package/dist/client/composer/attachment-accept.d.ts +7 -0
  28. package/dist/client/composer/attachment-accept.d.ts.map +1 -0
  29. package/dist/client/composer/attachment-accept.js +36 -0
  30. package/dist/client/composer/attachment-accept.js.map +1 -0
  31. package/dist/client/progress/RunsTray.d.ts.map +1 -1
  32. package/dist/client/progress/RunsTray.js +3 -1
  33. package/dist/client/progress/RunsTray.js.map +1 -1
  34. package/dist/client/sse-event-processor.d.ts.map +1 -1
  35. package/dist/client/sse-event-processor.js +12 -1
  36. package/dist/client/sse-event-processor.js.map +1 -1
  37. package/dist/db/client.d.ts +3 -0
  38. package/dist/db/client.d.ts.map +1 -1
  39. package/dist/db/client.js +70 -34
  40. package/dist/db/client.js.map +1 -1
  41. package/dist/db/create-get-db.d.ts.map +1 -1
  42. package/dist/db/create-get-db.js +30 -7
  43. package/dist/db/create-get-db.js.map +1 -1
  44. package/dist/deploy/build.js +64 -0
  45. package/dist/deploy/build.js.map +1 -1
  46. package/dist/onboarding/default-steps.d.ts.map +1 -1
  47. package/dist/onboarding/default-steps.js +8 -1
  48. package/dist/onboarding/default-steps.js.map +1 -1
  49. package/dist/scripts/db/exec.d.ts.map +1 -1
  50. package/dist/scripts/db/exec.js +3 -6
  51. package/dist/scripts/db/exec.js.map +1 -1
  52. package/dist/scripts/db/patch.d.ts.map +1 -1
  53. package/dist/scripts/db/patch.js +3 -6
  54. package/dist/scripts/db/patch.js.map +1 -1
  55. package/dist/scripts/db/query.d.ts.map +1 -1
  56. package/dist/scripts/db/query.js +3 -6
  57. package/dist/scripts/db/query.js.map +1 -1
  58. package/dist/scripts/db/schema.d.ts.map +1 -1
  59. package/dist/scripts/db/schema.js +3 -6
  60. package/dist/scripts/db/schema.js.map +1 -1
  61. package/dist/scripts/db/sqlite-client.d.ts +15 -0
  62. package/dist/scripts/db/sqlite-client.d.ts.map +1 -0
  63. package/dist/scripts/db/sqlite-client.js +51 -0
  64. package/dist/scripts/db/sqlite-client.js.map +1 -0
  65. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  66. package/dist/server/agent-chat-plugin.js +53 -2
  67. package/dist/server/agent-chat-plugin.js.map +1 -1
  68. package/dist/server/better-auth-instance.js +4 -3
  69. package/dist/server/better-auth-instance.js.map +1 -1
  70. package/dist/server/credential-provider.d.ts +2 -2
  71. package/dist/server/credential-provider.d.ts.map +1 -1
  72. package/dist/server/credential-provider.js +22 -1
  73. package/dist/server/credential-provider.js.map +1 -1
  74. package/dist/server/google-oauth.js +1 -1
  75. package/dist/server/google-oauth.js.map +1 -1
  76. package/package.json +1 -1
@@ -14,11 +14,11 @@
14
14
  * pnpm action db-exec --statements '[{"sql":"INSERT INTO notes (id,title) VALUES (?,?)","args":["n1","One"]},{"sql":"UPDATE counters SET value=value+1 WHERE key=?","args":["notes"]}]'
15
15
  */
16
16
  import path from "path";
17
- import { createClient } from "@libsql/client";
18
- import { getDatabaseUrl, getDatabaseAuthToken } from "../../db/client.js";
17
+ import { getDatabaseUrl } from "../../db/client.js";
19
18
  import { parseArgs, fail } from "../utils.js";
20
19
  import { buildScopingPostgres, buildScopingSqlite, } from "./scoping.js";
21
20
  import { assertNoSensitiveFrameworkTables } from "./safety.js";
21
+ import { createSqliteScriptClient } from "./sqlite-client.js";
22
22
  function isPostgresUrl(url) {
23
23
  return url.startsWith("postgres://") || url.startsWith("postgresql://");
24
24
  }
@@ -558,10 +558,7 @@ Options:
558
558
  return;
559
559
  }
560
560
  // libsql / SQLite path
561
- const client = createClient({
562
- url,
563
- authToken: getDatabaseAuthToken(),
564
- });
561
+ const client = await createSqliteScriptClient(url);
565
562
  try {
566
563
  // Set up user-scoped temp views in production
567
564
  const scoping = await buildScopingSqlite(client);
@@ -1 +1 @@
1
- {"version":3,"file":"exec.js","sourceRoot":"","sources":["../../../src/scripts/db/exec.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Core script: db-exec\n *\n * Execute write SQL statements (INSERT, UPDATE, DELETE, REPLACE)\n * against a SQLite or Postgres database.\n *\n * In production mode, temporary views scope UPDATE/DELETE to the current\n * user's data (AGENT_USER_EMAIL / AGENT_ORG_ID). For INSERT, the\n * `owner_email` and `org_id` columns are auto-injected if the target\n * table uses the ownership convention.\n *\n * Usage:\n * pnpm action db-exec --sql \"UPDATE forms SET status=? WHERE id=?\" [--args '[\"published\",\"abc\"]'] [--db path]\n * pnpm action db-exec --statements '[{\"sql\":\"INSERT INTO notes (id,title) VALUES (?,?)\",\"args\":[\"n1\",\"One\"]},{\"sql\":\"UPDATE counters SET value=value+1 WHERE key=?\",\"args\":[\"notes\"]}]'\n */\n\nimport path from \"path\";\nimport { createClient } from \"@libsql/client\";\nimport { getDatabaseUrl, getDatabaseAuthToken } from \"../../db/client.js\";\nimport { parseArgs, fail } from \"../utils.js\";\nimport {\n buildScopingPostgres,\n buildScopingSqlite,\n type ScopingContext,\n} from \"./scoping.js\";\nimport { assertNoSensitiveFrameworkTables } from \"./safety.js\";\n\nfunction isPostgresUrl(url: string): boolean {\n return url.startsWith(\"postgres://\") || url.startsWith(\"postgresql://\");\n}\n\ninterface DbExecStatement {\n sql: string;\n args: unknown[];\n}\n\ninterface DbExecResult {\n index: number;\n sql: string;\n changes?: number;\n lastInsertRowid?: bigint | number;\n rows?: Record<string, unknown>[];\n}\n\nfunction parseSqlArgs(raw: string | undefined, label = \"--args\"): unknown[] {\n if (!raw) return [];\n try {\n const parsed = JSON.parse(raw);\n if (Array.isArray(parsed)) return parsed;\n } catch {\n // Fall through to the shared error below.\n }\n fail(`${label} must be a JSON array`);\n}\n\nfunction parseStatements(parsed: Record<string, string>): DbExecStatement[] {\n if (parsed.statements) {\n if (parsed.sql) {\n fail(\"Pass either --sql or --statements, not both.\");\n }\n let raw: unknown;\n try {\n raw = JSON.parse(parsed.statements);\n } catch {\n fail(\n '--statements must be a JSON array of {\"sql\": string, \"args\"?: unknown[]} objects',\n );\n }\n if (!Array.isArray(raw) || raw.length === 0) {\n fail(\"--statements must be a non-empty JSON array\");\n }\n return raw.map((entry, index) => {\n if (\n !entry ||\n typeof entry !== \"object\" ||\n typeof (entry as any).sql !== \"string\" ||\n !(entry as any).sql.trim()\n ) {\n fail(`Statement ${index + 1} must include a non-empty sql string`);\n }\n const args = (entry as any).args;\n if (args != null && !Array.isArray(args)) {\n fail(`Statement ${index + 1} args must be a JSON array`);\n }\n return { sql: (entry as any).sql, args: args ?? [] };\n });\n }\n\n if (!parsed.sql) {\n fail(\n '--sql is required unless --statements is provided. Example: --sql \"UPDATE forms SET status=? WHERE id=?\" --args \\'[\"published\",\"abc\"]\\'',\n );\n }\n return [{ sql: parsed.sql, args: parseSqlArgs(parsed.args) }];\n}\n\nfunction stripLeadingSqlComments(sql: string): string {\n return sql\n .replace(/^\\s*--[^\\n]*\\n/gm, \"\")\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\")\n .trim();\n}\n\nfunction hasAdditionalStatement(sql: string): boolean {\n let state: \"normal\" | \"single\" | \"double\" | \"line-comment\" | \"block-comment\" =\n \"normal\";\n\n for (let i = 0; i < sql.length; i++) {\n const ch = sql[i];\n const next = sql[i + 1];\n\n if (state === \"line-comment\") {\n if (ch === \"\\n\") state = \"normal\";\n continue;\n }\n if (state === \"block-comment\") {\n if (ch === \"*\" && next === \"/\") {\n i++;\n state = \"normal\";\n }\n continue;\n }\n if (state === \"single\") {\n if (ch === \"'\" && next === \"'\") {\n i++;\n } else if (ch === \"'\") {\n state = \"normal\";\n }\n continue;\n }\n if (state === \"double\") {\n if (ch === '\"' && next === '\"') {\n i++;\n } else if (ch === '\"') {\n state = \"normal\";\n }\n continue;\n }\n\n if (ch === \"-\" && next === \"-\") {\n i++;\n state = \"line-comment\";\n continue;\n }\n if (ch === \"/\" && next === \"*\") {\n i++;\n state = \"block-comment\";\n continue;\n }\n if (ch === \"'\") {\n state = \"single\";\n continue;\n }\n if (ch === '\"') {\n state = \"double\";\n continue;\n }\n if (ch === \";\") {\n return sql.slice(i + 1).trim().length > 0;\n }\n }\n return false;\n}\n\nfunction normalizeUserSql(sql: string, index: number): string {\n const stripped = stripLeadingSqlComments(sql);\n if (!stripped) {\n fail(`Statement ${index} is empty`);\n }\n if (hasAdditionalStatement(stripped)) {\n fail(\n `Statement ${index} contains multiple SQL statements. Use --statements for batches so each write can be validated and run transactionally.`,\n );\n }\n return stripped.replace(/;\\s*$/, \"\");\n}\n\nfunction validateWriteSql(sql: string, index: number): string {\n const normalized = normalizeUserSql(sql, index);\n const upper = normalized.toUpperCase();\n const allowed = [\"INSERT\", \"UPDATE\", \"DELETE\", \"REPLACE\"];\n const blocked = [\"SELECT\", \"WITH\", \"EXPLAIN\", \"PRAGMA\"];\n\n if (blocked.some((kw) => upper.startsWith(kw))) {\n fail(\n `Statement ${index}: use db-query for SELECT/read statements. db-exec is for writes only.`,\n );\n }\n if (upper.startsWith(\"CREATE\") || upper.startsWith(\"ALTER\")) {\n fail(\n `Statement ${index}: schema changes are not allowed through db-exec. Additive schema changes must go through reviewed migrations/startup code, not ad-hoc agent SQL.`,\n );\n }\n if (!allowed.some((kw) => upper.startsWith(kw))) {\n fail(\n `Statement ${index}: only ${allowed.join(\", \")} statements are allowed. ` +\n `Dangerous operations like DROP, ATTACH, VACUUM, DETACH, CREATE, and ALTER are blocked.`,\n );\n }\n assertNoSensitiveFrameworkTables(normalized, \"write\");\n return normalized;\n}\n\nfunction convertQuestionMarksToPostgresParams(sql: string): string {\n let index = 0;\n let out = \"\";\n let state: \"normal\" | \"single\" | \"double\" | \"line-comment\" | \"block-comment\" =\n \"normal\";\n\n for (let i = 0; i < sql.length; i++) {\n const ch = sql[i];\n const next = sql[i + 1];\n\n if (state === \"line-comment\") {\n out += ch;\n if (ch === \"\\n\") state = \"normal\";\n continue;\n }\n\n if (state === \"block-comment\") {\n out += ch;\n if (ch === \"*\" && next === \"/\") {\n out += next;\n i++;\n state = \"normal\";\n }\n continue;\n }\n\n if (state === \"single\") {\n out += ch;\n if (ch === \"'\" && next === \"'\") {\n out += next;\n i++;\n } else if (ch === \"'\") {\n state = \"normal\";\n }\n continue;\n }\n\n if (state === \"double\") {\n out += ch;\n if (ch === '\"' && next === '\"') {\n out += next;\n i++;\n } else if (ch === '\"') {\n state = \"normal\";\n }\n continue;\n }\n\n if (ch === \"-\" && next === \"-\") {\n out += ch + next;\n i++;\n state = \"line-comment\";\n continue;\n }\n if (ch === \"/\" && next === \"*\") {\n out += ch + next;\n i++;\n state = \"block-comment\";\n continue;\n }\n if (ch === \"'\") {\n out += ch;\n state = \"single\";\n continue;\n }\n if (ch === '\"') {\n out += ch;\n state = \"double\";\n continue;\n }\n if (ch === \"?\") {\n index++;\n out += `$${index}`;\n continue;\n }\n out += ch;\n }\n\n return out;\n}\n\nfunction normalizePostgresSql(sql: string, args: unknown[]): string {\n if (args.length === 0 || /\\$\\d+\\b/.test(sql)) return sql;\n return convertQuestionMarksToPostgresParams(sql);\n}\n\n/**\n * For INSERT statements targeting a table with owner_email / org_id columns,\n * auto-inject the current user's email and org ID if not already present.\n *\n * Handles the explicit column list form:\n * INSERT INTO table (col1, col2) VALUES (val1, val2)\n */\nfunction injectOwnership(sql: string, scoping: ScopingContext): string {\n if (!scoping.active) return sql;\n\n const upper = sql\n .replace(/^\\s*--[^\\n]*\\n/gm, \"\")\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\")\n .trim()\n .toUpperCase();\n if (!upper.startsWith(\"INSERT\")) return sql;\n\n // Extract table name: INSERT INTO <table> ...\n const match = sql.match(/INSERT\\s+INTO\\s+[\"']?(\\w+)[\"']?/i);\n if (!match) return sql;\n\n const tableName = match[1];\n\n // Determine which columns to inject\n const injections: { col: string; value: string }[] = [];\n\n if (\n scoping.userEmail &&\n scoping.ownerEmailTables.has(tableName) &&\n !/owner_email/i.test(sql)\n ) {\n injections.push({\n col: \"owner_email\",\n value: `'${scoping.userEmail.replace(/'/g, \"''\")}'`,\n });\n }\n\n if (\n scoping.orgId &&\n scoping.orgIdTables.has(tableName) &&\n !/org_id/i.test(sql)\n ) {\n injections.push({\n col: \"org_id\",\n value: `'${scoping.orgId.replace(/'/g, \"''\")}'`,\n });\n }\n\n if (injections.length === 0) return sql;\n\n // Try to inject into explicit column list: INSERT INTO t (cols) VALUES (vals)\n const colListMatch = sql.match(\n /(INSERT\\s+INTO\\s+[\"']?\\w+[\"']?\\s*)\\(([^)]+)\\)(\\s*VALUES\\s*)\\(([^)]+)\\)/i,\n );\n if (colListMatch) {\n const [, prefix, cols, valueKeyword, vals] = colListMatch;\n const extraCols = injections.map((i) => i.col).join(\", \");\n const extraVals = injections.map((i) => i.value).join(\", \");\n return `${prefix}(${cols}, ${extraCols})${valueKeyword}(${vals}, ${extraVals})`;\n }\n\n return sql;\n}\n\nfunction escapeSqlString(value: string): string {\n return value.replace(/'/g, \"''\");\n}\n\nfunction sqliteScopePredicate(\n tableName: string,\n scoping: ScopingContext,\n): string | null {\n if (tableName === \"tool_data\" && scoping.userEmail) {\n const userClause = `(scope = 'user' AND owner_email = '${escapeSqlString(scoping.userEmail)}')`;\n const orgClause = scoping.orgId\n ? ` OR (scope = 'org' AND org_id = '${escapeSqlString(scoping.orgId)}')`\n : \"\";\n return `(${userClause}${orgClause})`;\n }\n\n const clauses: string[] = [];\n const hasOwner = scoping.ownerEmailTables.has(tableName);\n const hasOrg = scoping.orgIdTables.has(tableName);\n if (scoping.userEmail && hasOwner) {\n const ownerClause = `owner_email = '${escapeSqlString(scoping.userEmail)}'`;\n if (scoping.orgId && hasOrg) {\n clauses.push(\n `${ownerClause} AND (org_id = '${escapeSqlString(scoping.orgId)}' OR org_id IS NULL)`,\n );\n } else {\n clauses.push(ownerClause);\n }\n } else if (scoping.orgId && hasOrg) {\n clauses.push(`org_id = '${escapeSqlString(scoping.orgId)}'`);\n }\n return clauses.length > 0 ? clauses.join(\" AND \") : null;\n}\n\nfunction splitReturning(sql: string): { body: string; returning: string } {\n const match = /\\bRETURNING\\b/i.exec(sql);\n if (!match) return { body: sql, returning: \"\" };\n return {\n body: sql.slice(0, match.index).trimEnd(),\n returning: sql.slice(match.index),\n };\n}\n\nfunction addSqliteScopeToWhere(sql: string, predicate: string): string {\n const { body, returning } = splitReturning(sql);\n const whereMatch = /\\bWHERE\\b/i.exec(body);\n const scoped = whereMatch\n ? `${body.slice(0, whereMatch.index)}WHERE ${predicate} AND (${body.slice(whereMatch.index + whereMatch[0].length).trim()})`\n : `${body} WHERE ${predicate}`;\n return returning ? `${scoped} ${returning}` : scoped;\n}\n\nfunction qualifySqliteWrite(sql: string, scoping: ScopingContext): string {\n if (!scoping.active) return sql;\n\n const updateMatch = sql.match(/^\\s*UPDATE\\s+(?:\"([^\"]+)\"|'([^']+)'|(\\w+))/i);\n if (updateMatch) {\n const tableName = updateMatch[1] ?? updateMatch[2] ?? updateMatch[3];\n const predicate = sqliteScopePredicate(tableName, scoping);\n if (!predicate) return sql;\n const qualified = sql.replace(\n /^\\s*UPDATE\\s+(?:\"[^\"]+\"|'[^']+'|\\w+)/i,\n `UPDATE main.\"${tableName.replace(/\"/g, '\"\"')}\"`,\n );\n return addSqliteScopeToWhere(qualified, predicate);\n }\n\n const deleteMatch = sql.match(\n /^\\s*DELETE\\s+FROM\\s+(?:\"([^\"]+)\"|'([^']+)'|(\\w+))/i,\n );\n if (deleteMatch) {\n const tableName = deleteMatch[1] ?? deleteMatch[2] ?? deleteMatch[3];\n const predicate = sqliteScopePredicate(tableName, scoping);\n if (!predicate) return sql;\n const qualified = sql.replace(\n /^\\s*DELETE\\s+FROM\\s+(?:\"[^\"]+\"|'[^']+'|\\w+)/i,\n `DELETE FROM main.\"${tableName.replace(/\"/g, '\"\"')}\"`,\n );\n return addSqliteScopeToWhere(qualified, predicate);\n }\n\n return sql.replace(\n /^\\s*(INSERT\\s+INTO|REPLACE\\s+INTO)\\s+(?:\"([^\"]+)\"|'([^']+)'|(\\w+))/i,\n (match, keyword, quotedDouble, quotedSingle, bare) => {\n const tableName = quotedDouble ?? quotedSingle ?? bare;\n if (\n !scoping.ownerEmailTables.has(tableName) &&\n !scoping.orgIdTables.has(tableName)\n ) {\n return match;\n }\n return `${keyword} main.\"${tableName.replace(/\"/g, '\"\"')}\"`;\n },\n );\n}\n\nfunction printResult(\n sql: string,\n result: {\n count?: number;\n rowsAffected?: number;\n lastInsertRowid?: bigint | number;\n rows?: Record<string, unknown>[];\n },\n hasReturning: boolean,\n format?: string,\n) {\n if (hasReturning && result.rows && result.rows.length > 0) {\n if (format === \"json\") {\n console.log(\n JSON.stringify(\n { sql, rows: result.rows, count: result.rows.length },\n null,\n 2,\n ),\n );\n return;\n }\n console.log(`Executed: ${sql}`);\n console.log(`Returned ${result.rows.length} row(s):`);\n console.log(JSON.stringify(result.rows, null, 2));\n } else {\n const changes = result.count ?? result.rowsAffected ?? 0;\n if (format === \"json\") {\n console.log(\n JSON.stringify(\n {\n sql,\n changes,\n ...(result.lastInsertRowid && changes > 0\n ? { lastInsertRowid: Number(result.lastInsertRowid) }\n : {}),\n },\n null,\n 2,\n ),\n );\n return;\n }\n console.log(`Executed: ${sql}`);\n console.log(`Changes: ${changes}`);\n if (result.lastInsertRowid && changes > 0) {\n console.log(`Last Insert Row ID: ${result.lastInsertRowid}`);\n }\n if (changes === 0) {\n console.log(zeroChangesHint(sql));\n }\n }\n}\n\n/**\n * Hint emitted when an UPDATE/DELETE/REPLACE matches zero rows. Matches the\n * wording used by db-patch's \"no rows matched\" error so the agent gets the\n * same scoping nudge from both tools — without this hint, the agent reports\n * \"Changes: 0\" as success and the user sees no UI update because the row\n * either didn't exist or wasn't visible to the current user under per-user\n * scoping.\n */\nfunction zeroChangesHint(sql: string): string {\n const upper = sql.toUpperCase(); // leading whitespace already stripped by normalizeUserSql\n if (upper.startsWith(\"INSERT\")) {\n // INSERT changes=0 means INSERT OR IGNORE skipped a duplicate — different\n // failure mode, not a scoping issue.\n return \"Hint: 0 rows inserted. The row likely violated a UNIQUE / PRIMARY KEY constraint and was skipped (INSERT OR IGNORE).\";\n }\n return (\n \"Hint: 0 rows changed. The WHERE clause matched no rows — either the row \" +\n \"doesn't exist, or it exists but is owned by a different user (per-user \" +\n \"and per-org scoping is automatic for db-exec).\"\n );\n}\n\nfunction printBatchResult(results: DbExecResult[], format?: string): void {\n if (results.length === 1) {\n const result = results[0];\n printResult(\n result.sql,\n {\n count: result.changes,\n rowsAffected: result.changes,\n lastInsertRowid: result.lastInsertRowid,\n rows: result.rows,\n },\n Boolean(result.rows?.length),\n format,\n );\n return;\n }\n\n const totalChanges = results.reduce(\n (sum, result) => sum + Number(result.changes ?? 0),\n 0,\n );\n\n if (format === \"json\") {\n console.log(\n JSON.stringify(\n {\n statements: results.map((result) => ({\n index: result.index,\n sql: result.sql,\n changes: result.changes ?? 0,\n ...(result.lastInsertRowid && Number(result.changes ?? 0) > 0\n ? { lastInsertRowid: Number(result.lastInsertRowid) }\n : {}),\n ...(result.rows?.length\n ? { rows: result.rows, count: result.rows.length }\n : {}),\n })),\n changes: totalChanges,\n },\n null,\n 2,\n ),\n );\n return;\n }\n\n console.log(`Executed ${results.length} statements in one transaction.`);\n for (const result of results) {\n if (result.rows?.length) {\n console.log(`[${result.index}] Returned ${result.rows.length} row(s):`);\n console.log(JSON.stringify(result.rows, null, 2));\n } else {\n const changes = Number(result.changes ?? 0);\n console.log(`[${result.index}] Changes: ${changes}`);\n if (changes === 0) {\n console.log(`[${result.index}] ${zeroChangesHint(result.sql)}`);\n }\n }\n }\n console.log(`Total changes: ${totalChanges}`);\n}\n\nfunction sqliteRowsToObjects(\n rows: any[],\n columns: string[],\n): Record<string, unknown>[] {\n return rows.map((row) => {\n if (!Array.isArray(row) && row && typeof row === \"object\") {\n return { ...row };\n }\n const obj: Record<string, unknown> = {};\n for (let i = 0; i < columns.length; i++) {\n obj[columns[i]] = row[i];\n }\n return obj;\n });\n}\n\nexport default async function dbExec(args: string[]): Promise<void> {\n const parsed = parseArgs(args);\n\n if (parsed.help === \"true\") {\n console.log(`Usage: pnpm action db-exec --sql \"<statement>\" [options]\n pnpm action db-exec --statements '[{\"sql\":\"UPDATE ...\",\"args\":[...]}]' [options]\n\nOptions:\n --sql <stmt> Single INSERT / UPDATE / DELETE / REPLACE statement\n --args <json> JSON array of positional SQL bind parameters for --sql\n --statements <json> JSON array of {sql, args?}; runs in one transaction\n --db <path> Path to SQLite database (default: data/app.db)\n --format json Output as JSON\n --help Show this help message`);\n return;\n }\n\n const statements = parseStatements(parsed).map((statement, index) => ({\n sql: validateWriteSql(statement.sql, index + 1),\n args: statement.args,\n }));\n\n // Resolve database URL: --db flag → DATABASE_URL env → default file path\n let url: string;\n if (parsed.db) {\n url = \"file:\" + path.resolve(parsed.db);\n } else if (getDatabaseUrl()) {\n url = getDatabaseUrl();\n } else {\n url = \"file:\" + path.resolve(process.cwd(), \"data\", \"app.db\");\n }\n\n // Postgres path\n if (isPostgresUrl(url)) {\n const { default: pg } = await import(\"postgres\");\n const pgSql = pg(url);\n try {\n // Set up user-scoped temp views in production\n const scoping = await buildScopingPostgres(pgSql);\n\n const results: DbExecResult[] = [];\n await pgSql.begin(async (tx: any) => {\n try {\n // For UPDATE/DELETE: temp views scope to current user's rows.\n // Creating and dropping them inside the same transaction keeps\n // pooled Postgres backends from retaining session-local views.\n for (const stmt of scoping.setup) {\n await tx.unsafe(stmt);\n }\n\n for (let i = 0; i < statements.length; i++) {\n const statement = statements[i];\n const hasReturning = /\\bRETURNING\\b/i.test(statement.sql);\n const finalSql = normalizePostgresSql(\n injectOwnership(statement.sql, scoping),\n statement.args,\n );\n try {\n const result =\n statement.args.length > 0\n ? await tx.unsafe(finalSql, statement.args as any[])\n : await tx.unsafe(finalSql);\n const rows: Record<string, unknown>[] =\n hasReturning && result.length > 0 ? Array.from(result) : [];\n results.push({\n index: i + 1,\n sql: finalSql,\n changes: result.count ?? 0,\n rows,\n });\n } catch (err: any) {\n throw new Error(\n `Statement ${i + 1} failed: ${err?.message ?? String(err)}`,\n );\n }\n }\n } finally {\n for (const stmt of scoping.teardown) {\n await tx.unsafe(stmt).catch(() => {});\n }\n }\n });\n\n printBatchResult(results, parsed.format);\n } finally {\n await pgSql.end();\n }\n return;\n }\n\n // libsql / SQLite path\n const client = createClient({\n url,\n authToken: getDatabaseAuthToken(),\n });\n\n try {\n // Set up user-scoped temp views in production\n const scoping = await buildScopingSqlite(client);\n for (const stmt of scoping.setup) {\n await client.execute(stmt);\n }\n\n const results: DbExecResult[] = [];\n const shouldTransact = statements.length > 1;\n if (shouldTransact) await client.execute(\"BEGIN\");\n try {\n for (let i = 0; i < statements.length; i++) {\n const statement = statements[i];\n const hasReturning = /\\bRETURNING\\b/i.test(statement.sql);\n const finalSql = qualifySqliteWrite(\n injectOwnership(statement.sql, scoping),\n scoping,\n );\n try {\n const result =\n statement.args.length > 0\n ? await client.execute({\n sql: finalSql,\n args: statement.args as any[],\n })\n : await client.execute(finalSql);\n\n const rows: Record<string, unknown>[] =\n hasReturning && result.rows.length > 0\n ? sqliteRowsToObjects(result.rows, result.columns)\n : [];\n results.push({\n index: i + 1,\n sql: finalSql,\n changes: result.rowsAffected,\n lastInsertRowid: result.lastInsertRowid,\n rows,\n });\n } catch (err: any) {\n throw new Error(\n `Statement ${i + 1} failed: ${err?.message ?? String(err)}`,\n );\n }\n }\n if (shouldTransact) await client.execute(\"COMMIT\");\n } catch (err) {\n if (shouldTransact) {\n await client.execute(\"ROLLBACK\").catch(() => {});\n }\n throw err;\n }\n\n printBatchResult(results, parsed.format);\n\n for (const stmt of scoping.teardown) {\n await client.execute(stmt).catch(() => {});\n }\n } finally {\n client.close();\n }\n}\n"]}
1
+ {"version":3,"file":"exec.js","sourceRoot":"","sources":["../../../src/scripts/db/exec.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Core script: db-exec\n *\n * Execute write SQL statements (INSERT, UPDATE, DELETE, REPLACE)\n * against a SQLite or Postgres database.\n *\n * In production mode, temporary views scope UPDATE/DELETE to the current\n * user's data (AGENT_USER_EMAIL / AGENT_ORG_ID). For INSERT, the\n * `owner_email` and `org_id` columns are auto-injected if the target\n * table uses the ownership convention.\n *\n * Usage:\n * pnpm action db-exec --sql \"UPDATE forms SET status=? WHERE id=?\" [--args '[\"published\",\"abc\"]'] [--db path]\n * pnpm action db-exec --statements '[{\"sql\":\"INSERT INTO notes (id,title) VALUES (?,?)\",\"args\":[\"n1\",\"One\"]},{\"sql\":\"UPDATE counters SET value=value+1 WHERE key=?\",\"args\":[\"notes\"]}]'\n */\n\nimport path from \"path\";\nimport { getDatabaseUrl } from \"../../db/client.js\";\nimport { parseArgs, fail } from \"../utils.js\";\nimport {\n buildScopingPostgres,\n buildScopingSqlite,\n type ScopingContext,\n} from \"./scoping.js\";\nimport { assertNoSensitiveFrameworkTables } from \"./safety.js\";\nimport { createSqliteScriptClient } from \"./sqlite-client.js\";\n\nfunction isPostgresUrl(url: string): boolean {\n return url.startsWith(\"postgres://\") || url.startsWith(\"postgresql://\");\n}\n\ninterface DbExecStatement {\n sql: string;\n args: unknown[];\n}\n\ninterface DbExecResult {\n index: number;\n sql: string;\n changes?: number;\n lastInsertRowid?: bigint | number;\n rows?: Record<string, unknown>[];\n}\n\nfunction parseSqlArgs(raw: string | undefined, label = \"--args\"): unknown[] {\n if (!raw) return [];\n try {\n const parsed = JSON.parse(raw);\n if (Array.isArray(parsed)) return parsed;\n } catch {\n // Fall through to the shared error below.\n }\n fail(`${label} must be a JSON array`);\n}\n\nfunction parseStatements(parsed: Record<string, string>): DbExecStatement[] {\n if (parsed.statements) {\n if (parsed.sql) {\n fail(\"Pass either --sql or --statements, not both.\");\n }\n let raw: unknown;\n try {\n raw = JSON.parse(parsed.statements);\n } catch {\n fail(\n '--statements must be a JSON array of {\"sql\": string, \"args\"?: unknown[]} objects',\n );\n }\n if (!Array.isArray(raw) || raw.length === 0) {\n fail(\"--statements must be a non-empty JSON array\");\n }\n return raw.map((entry, index) => {\n if (\n !entry ||\n typeof entry !== \"object\" ||\n typeof (entry as any).sql !== \"string\" ||\n !(entry as any).sql.trim()\n ) {\n fail(`Statement ${index + 1} must include a non-empty sql string`);\n }\n const args = (entry as any).args;\n if (args != null && !Array.isArray(args)) {\n fail(`Statement ${index + 1} args must be a JSON array`);\n }\n return { sql: (entry as any).sql, args: args ?? [] };\n });\n }\n\n if (!parsed.sql) {\n fail(\n '--sql is required unless --statements is provided. Example: --sql \"UPDATE forms SET status=? WHERE id=?\" --args \\'[\"published\",\"abc\"]\\'',\n );\n }\n return [{ sql: parsed.sql, args: parseSqlArgs(parsed.args) }];\n}\n\nfunction stripLeadingSqlComments(sql: string): string {\n return sql\n .replace(/^\\s*--[^\\n]*\\n/gm, \"\")\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\")\n .trim();\n}\n\nfunction hasAdditionalStatement(sql: string): boolean {\n let state: \"normal\" | \"single\" | \"double\" | \"line-comment\" | \"block-comment\" =\n \"normal\";\n\n for (let i = 0; i < sql.length; i++) {\n const ch = sql[i];\n const next = sql[i + 1];\n\n if (state === \"line-comment\") {\n if (ch === \"\\n\") state = \"normal\";\n continue;\n }\n if (state === \"block-comment\") {\n if (ch === \"*\" && next === \"/\") {\n i++;\n state = \"normal\";\n }\n continue;\n }\n if (state === \"single\") {\n if (ch === \"'\" && next === \"'\") {\n i++;\n } else if (ch === \"'\") {\n state = \"normal\";\n }\n continue;\n }\n if (state === \"double\") {\n if (ch === '\"' && next === '\"') {\n i++;\n } else if (ch === '\"') {\n state = \"normal\";\n }\n continue;\n }\n\n if (ch === \"-\" && next === \"-\") {\n i++;\n state = \"line-comment\";\n continue;\n }\n if (ch === \"/\" && next === \"*\") {\n i++;\n state = \"block-comment\";\n continue;\n }\n if (ch === \"'\") {\n state = \"single\";\n continue;\n }\n if (ch === '\"') {\n state = \"double\";\n continue;\n }\n if (ch === \";\") {\n return sql.slice(i + 1).trim().length > 0;\n }\n }\n return false;\n}\n\nfunction normalizeUserSql(sql: string, index: number): string {\n const stripped = stripLeadingSqlComments(sql);\n if (!stripped) {\n fail(`Statement ${index} is empty`);\n }\n if (hasAdditionalStatement(stripped)) {\n fail(\n `Statement ${index} contains multiple SQL statements. Use --statements for batches so each write can be validated and run transactionally.`,\n );\n }\n return stripped.replace(/;\\s*$/, \"\");\n}\n\nfunction validateWriteSql(sql: string, index: number): string {\n const normalized = normalizeUserSql(sql, index);\n const upper = normalized.toUpperCase();\n const allowed = [\"INSERT\", \"UPDATE\", \"DELETE\", \"REPLACE\"];\n const blocked = [\"SELECT\", \"WITH\", \"EXPLAIN\", \"PRAGMA\"];\n\n if (blocked.some((kw) => upper.startsWith(kw))) {\n fail(\n `Statement ${index}: use db-query for SELECT/read statements. db-exec is for writes only.`,\n );\n }\n if (upper.startsWith(\"CREATE\") || upper.startsWith(\"ALTER\")) {\n fail(\n `Statement ${index}: schema changes are not allowed through db-exec. Additive schema changes must go through reviewed migrations/startup code, not ad-hoc agent SQL.`,\n );\n }\n if (!allowed.some((kw) => upper.startsWith(kw))) {\n fail(\n `Statement ${index}: only ${allowed.join(\", \")} statements are allowed. ` +\n `Dangerous operations like DROP, ATTACH, VACUUM, DETACH, CREATE, and ALTER are blocked.`,\n );\n }\n assertNoSensitiveFrameworkTables(normalized, \"write\");\n return normalized;\n}\n\nfunction convertQuestionMarksToPostgresParams(sql: string): string {\n let index = 0;\n let out = \"\";\n let state: \"normal\" | \"single\" | \"double\" | \"line-comment\" | \"block-comment\" =\n \"normal\";\n\n for (let i = 0; i < sql.length; i++) {\n const ch = sql[i];\n const next = sql[i + 1];\n\n if (state === \"line-comment\") {\n out += ch;\n if (ch === \"\\n\") state = \"normal\";\n continue;\n }\n\n if (state === \"block-comment\") {\n out += ch;\n if (ch === \"*\" && next === \"/\") {\n out += next;\n i++;\n state = \"normal\";\n }\n continue;\n }\n\n if (state === \"single\") {\n out += ch;\n if (ch === \"'\" && next === \"'\") {\n out += next;\n i++;\n } else if (ch === \"'\") {\n state = \"normal\";\n }\n continue;\n }\n\n if (state === \"double\") {\n out += ch;\n if (ch === '\"' && next === '\"') {\n out += next;\n i++;\n } else if (ch === '\"') {\n state = \"normal\";\n }\n continue;\n }\n\n if (ch === \"-\" && next === \"-\") {\n out += ch + next;\n i++;\n state = \"line-comment\";\n continue;\n }\n if (ch === \"/\" && next === \"*\") {\n out += ch + next;\n i++;\n state = \"block-comment\";\n continue;\n }\n if (ch === \"'\") {\n out += ch;\n state = \"single\";\n continue;\n }\n if (ch === '\"') {\n out += ch;\n state = \"double\";\n continue;\n }\n if (ch === \"?\") {\n index++;\n out += `$${index}`;\n continue;\n }\n out += ch;\n }\n\n return out;\n}\n\nfunction normalizePostgresSql(sql: string, args: unknown[]): string {\n if (args.length === 0 || /\\$\\d+\\b/.test(sql)) return sql;\n return convertQuestionMarksToPostgresParams(sql);\n}\n\n/**\n * For INSERT statements targeting a table with owner_email / org_id columns,\n * auto-inject the current user's email and org ID if not already present.\n *\n * Handles the explicit column list form:\n * INSERT INTO table (col1, col2) VALUES (val1, val2)\n */\nfunction injectOwnership(sql: string, scoping: ScopingContext): string {\n if (!scoping.active) return sql;\n\n const upper = sql\n .replace(/^\\s*--[^\\n]*\\n/gm, \"\")\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\")\n .trim()\n .toUpperCase();\n if (!upper.startsWith(\"INSERT\")) return sql;\n\n // Extract table name: INSERT INTO <table> ...\n const match = sql.match(/INSERT\\s+INTO\\s+[\"']?(\\w+)[\"']?/i);\n if (!match) return sql;\n\n const tableName = match[1];\n\n // Determine which columns to inject\n const injections: { col: string; value: string }[] = [];\n\n if (\n scoping.userEmail &&\n scoping.ownerEmailTables.has(tableName) &&\n !/owner_email/i.test(sql)\n ) {\n injections.push({\n col: \"owner_email\",\n value: `'${scoping.userEmail.replace(/'/g, \"''\")}'`,\n });\n }\n\n if (\n scoping.orgId &&\n scoping.orgIdTables.has(tableName) &&\n !/org_id/i.test(sql)\n ) {\n injections.push({\n col: \"org_id\",\n value: `'${scoping.orgId.replace(/'/g, \"''\")}'`,\n });\n }\n\n if (injections.length === 0) return sql;\n\n // Try to inject into explicit column list: INSERT INTO t (cols) VALUES (vals)\n const colListMatch = sql.match(\n /(INSERT\\s+INTO\\s+[\"']?\\w+[\"']?\\s*)\\(([^)]+)\\)(\\s*VALUES\\s*)\\(([^)]+)\\)/i,\n );\n if (colListMatch) {\n const [, prefix, cols, valueKeyword, vals] = colListMatch;\n const extraCols = injections.map((i) => i.col).join(\", \");\n const extraVals = injections.map((i) => i.value).join(\", \");\n return `${prefix}(${cols}, ${extraCols})${valueKeyword}(${vals}, ${extraVals})`;\n }\n\n return sql;\n}\n\nfunction escapeSqlString(value: string): string {\n return value.replace(/'/g, \"''\");\n}\n\nfunction sqliteScopePredicate(\n tableName: string,\n scoping: ScopingContext,\n): string | null {\n if (tableName === \"tool_data\" && scoping.userEmail) {\n const userClause = `(scope = 'user' AND owner_email = '${escapeSqlString(scoping.userEmail)}')`;\n const orgClause = scoping.orgId\n ? ` OR (scope = 'org' AND org_id = '${escapeSqlString(scoping.orgId)}')`\n : \"\";\n return `(${userClause}${orgClause})`;\n }\n\n const clauses: string[] = [];\n const hasOwner = scoping.ownerEmailTables.has(tableName);\n const hasOrg = scoping.orgIdTables.has(tableName);\n if (scoping.userEmail && hasOwner) {\n const ownerClause = `owner_email = '${escapeSqlString(scoping.userEmail)}'`;\n if (scoping.orgId && hasOrg) {\n clauses.push(\n `${ownerClause} AND (org_id = '${escapeSqlString(scoping.orgId)}' OR org_id IS NULL)`,\n );\n } else {\n clauses.push(ownerClause);\n }\n } else if (scoping.orgId && hasOrg) {\n clauses.push(`org_id = '${escapeSqlString(scoping.orgId)}'`);\n }\n return clauses.length > 0 ? clauses.join(\" AND \") : null;\n}\n\nfunction splitReturning(sql: string): { body: string; returning: string } {\n const match = /\\bRETURNING\\b/i.exec(sql);\n if (!match) return { body: sql, returning: \"\" };\n return {\n body: sql.slice(0, match.index).trimEnd(),\n returning: sql.slice(match.index),\n };\n}\n\nfunction addSqliteScopeToWhere(sql: string, predicate: string): string {\n const { body, returning } = splitReturning(sql);\n const whereMatch = /\\bWHERE\\b/i.exec(body);\n const scoped = whereMatch\n ? `${body.slice(0, whereMatch.index)}WHERE ${predicate} AND (${body.slice(whereMatch.index + whereMatch[0].length).trim()})`\n : `${body} WHERE ${predicate}`;\n return returning ? `${scoped} ${returning}` : scoped;\n}\n\nfunction qualifySqliteWrite(sql: string, scoping: ScopingContext): string {\n if (!scoping.active) return sql;\n\n const updateMatch = sql.match(/^\\s*UPDATE\\s+(?:\"([^\"]+)\"|'([^']+)'|(\\w+))/i);\n if (updateMatch) {\n const tableName = updateMatch[1] ?? updateMatch[2] ?? updateMatch[3];\n const predicate = sqliteScopePredicate(tableName, scoping);\n if (!predicate) return sql;\n const qualified = sql.replace(\n /^\\s*UPDATE\\s+(?:\"[^\"]+\"|'[^']+'|\\w+)/i,\n `UPDATE main.\"${tableName.replace(/\"/g, '\"\"')}\"`,\n );\n return addSqliteScopeToWhere(qualified, predicate);\n }\n\n const deleteMatch = sql.match(\n /^\\s*DELETE\\s+FROM\\s+(?:\"([^\"]+)\"|'([^']+)'|(\\w+))/i,\n );\n if (deleteMatch) {\n const tableName = deleteMatch[1] ?? deleteMatch[2] ?? deleteMatch[3];\n const predicate = sqliteScopePredicate(tableName, scoping);\n if (!predicate) return sql;\n const qualified = sql.replace(\n /^\\s*DELETE\\s+FROM\\s+(?:\"[^\"]+\"|'[^']+'|\\w+)/i,\n `DELETE FROM main.\"${tableName.replace(/\"/g, '\"\"')}\"`,\n );\n return addSqliteScopeToWhere(qualified, predicate);\n }\n\n return sql.replace(\n /^\\s*(INSERT\\s+INTO|REPLACE\\s+INTO)\\s+(?:\"([^\"]+)\"|'([^']+)'|(\\w+))/i,\n (match, keyword, quotedDouble, quotedSingle, bare) => {\n const tableName = quotedDouble ?? quotedSingle ?? bare;\n if (\n !scoping.ownerEmailTables.has(tableName) &&\n !scoping.orgIdTables.has(tableName)\n ) {\n return match;\n }\n return `${keyword} main.\"${tableName.replace(/\"/g, '\"\"')}\"`;\n },\n );\n}\n\nfunction printResult(\n sql: string,\n result: {\n count?: number;\n rowsAffected?: number;\n lastInsertRowid?: bigint | number;\n rows?: Record<string, unknown>[];\n },\n hasReturning: boolean,\n format?: string,\n) {\n if (hasReturning && result.rows && result.rows.length > 0) {\n if (format === \"json\") {\n console.log(\n JSON.stringify(\n { sql, rows: result.rows, count: result.rows.length },\n null,\n 2,\n ),\n );\n return;\n }\n console.log(`Executed: ${sql}`);\n console.log(`Returned ${result.rows.length} row(s):`);\n console.log(JSON.stringify(result.rows, null, 2));\n } else {\n const changes = result.count ?? result.rowsAffected ?? 0;\n if (format === \"json\") {\n console.log(\n JSON.stringify(\n {\n sql,\n changes,\n ...(result.lastInsertRowid && changes > 0\n ? { lastInsertRowid: Number(result.lastInsertRowid) }\n : {}),\n },\n null,\n 2,\n ),\n );\n return;\n }\n console.log(`Executed: ${sql}`);\n console.log(`Changes: ${changes}`);\n if (result.lastInsertRowid && changes > 0) {\n console.log(`Last Insert Row ID: ${result.lastInsertRowid}`);\n }\n if (changes === 0) {\n console.log(zeroChangesHint(sql));\n }\n }\n}\n\n/**\n * Hint emitted when an UPDATE/DELETE/REPLACE matches zero rows. Matches the\n * wording used by db-patch's \"no rows matched\" error so the agent gets the\n * same scoping nudge from both tools — without this hint, the agent reports\n * \"Changes: 0\" as success and the user sees no UI update because the row\n * either didn't exist or wasn't visible to the current user under per-user\n * scoping.\n */\nfunction zeroChangesHint(sql: string): string {\n const upper = sql.toUpperCase(); // leading whitespace already stripped by normalizeUserSql\n if (upper.startsWith(\"INSERT\")) {\n // INSERT changes=0 means INSERT OR IGNORE skipped a duplicate — different\n // failure mode, not a scoping issue.\n return \"Hint: 0 rows inserted. The row likely violated a UNIQUE / PRIMARY KEY constraint and was skipped (INSERT OR IGNORE).\";\n }\n return (\n \"Hint: 0 rows changed. The WHERE clause matched no rows — either the row \" +\n \"doesn't exist, or it exists but is owned by a different user (per-user \" +\n \"and per-org scoping is automatic for db-exec).\"\n );\n}\n\nfunction printBatchResult(results: DbExecResult[], format?: string): void {\n if (results.length === 1) {\n const result = results[0];\n printResult(\n result.sql,\n {\n count: result.changes,\n rowsAffected: result.changes,\n lastInsertRowid: result.lastInsertRowid,\n rows: result.rows,\n },\n Boolean(result.rows?.length),\n format,\n );\n return;\n }\n\n const totalChanges = results.reduce(\n (sum, result) => sum + Number(result.changes ?? 0),\n 0,\n );\n\n if (format === \"json\") {\n console.log(\n JSON.stringify(\n {\n statements: results.map((result) => ({\n index: result.index,\n sql: result.sql,\n changes: result.changes ?? 0,\n ...(result.lastInsertRowid && Number(result.changes ?? 0) > 0\n ? { lastInsertRowid: Number(result.lastInsertRowid) }\n : {}),\n ...(result.rows?.length\n ? { rows: result.rows, count: result.rows.length }\n : {}),\n })),\n changes: totalChanges,\n },\n null,\n 2,\n ),\n );\n return;\n }\n\n console.log(`Executed ${results.length} statements in one transaction.`);\n for (const result of results) {\n if (result.rows?.length) {\n console.log(`[${result.index}] Returned ${result.rows.length} row(s):`);\n console.log(JSON.stringify(result.rows, null, 2));\n } else {\n const changes = Number(result.changes ?? 0);\n console.log(`[${result.index}] Changes: ${changes}`);\n if (changes === 0) {\n console.log(`[${result.index}] ${zeroChangesHint(result.sql)}`);\n }\n }\n }\n console.log(`Total changes: ${totalChanges}`);\n}\n\nfunction sqliteRowsToObjects(\n rows: any[],\n columns: string[],\n): Record<string, unknown>[] {\n return rows.map((row) => {\n if (!Array.isArray(row) && row && typeof row === \"object\") {\n return { ...row };\n }\n const obj: Record<string, unknown> = {};\n for (let i = 0; i < columns.length; i++) {\n obj[columns[i]] = row[i];\n }\n return obj;\n });\n}\n\nexport default async function dbExec(args: string[]): Promise<void> {\n const parsed = parseArgs(args);\n\n if (parsed.help === \"true\") {\n console.log(`Usage: pnpm action db-exec --sql \"<statement>\" [options]\n pnpm action db-exec --statements '[{\"sql\":\"UPDATE ...\",\"args\":[...]}]' [options]\n\nOptions:\n --sql <stmt> Single INSERT / UPDATE / DELETE / REPLACE statement\n --args <json> JSON array of positional SQL bind parameters for --sql\n --statements <json> JSON array of {sql, args?}; runs in one transaction\n --db <path> Path to SQLite database (default: data/app.db)\n --format json Output as JSON\n --help Show this help message`);\n return;\n }\n\n const statements = parseStatements(parsed).map((statement, index) => ({\n sql: validateWriteSql(statement.sql, index + 1),\n args: statement.args,\n }));\n\n // Resolve database URL: --db flag → DATABASE_URL env → default file path\n let url: string;\n if (parsed.db) {\n url = \"file:\" + path.resolve(parsed.db);\n } else if (getDatabaseUrl()) {\n url = getDatabaseUrl();\n } else {\n url = \"file:\" + path.resolve(process.cwd(), \"data\", \"app.db\");\n }\n\n // Postgres path\n if (isPostgresUrl(url)) {\n const { default: pg } = await import(\"postgres\");\n const pgSql = pg(url);\n try {\n // Set up user-scoped temp views in production\n const scoping = await buildScopingPostgres(pgSql);\n\n const results: DbExecResult[] = [];\n await pgSql.begin(async (tx: any) => {\n try {\n // For UPDATE/DELETE: temp views scope to current user's rows.\n // Creating and dropping them inside the same transaction keeps\n // pooled Postgres backends from retaining session-local views.\n for (const stmt of scoping.setup) {\n await tx.unsafe(stmt);\n }\n\n for (let i = 0; i < statements.length; i++) {\n const statement = statements[i];\n const hasReturning = /\\bRETURNING\\b/i.test(statement.sql);\n const finalSql = normalizePostgresSql(\n injectOwnership(statement.sql, scoping),\n statement.args,\n );\n try {\n const result =\n statement.args.length > 0\n ? await tx.unsafe(finalSql, statement.args as any[])\n : await tx.unsafe(finalSql);\n const rows: Record<string, unknown>[] =\n hasReturning && result.length > 0 ? Array.from(result) : [];\n results.push({\n index: i + 1,\n sql: finalSql,\n changes: result.count ?? 0,\n rows,\n });\n } catch (err: any) {\n throw new Error(\n `Statement ${i + 1} failed: ${err?.message ?? String(err)}`,\n );\n }\n }\n } finally {\n for (const stmt of scoping.teardown) {\n await tx.unsafe(stmt).catch(() => {});\n }\n }\n });\n\n printBatchResult(results, parsed.format);\n } finally {\n await pgSql.end();\n }\n return;\n }\n\n // libsql / SQLite path\n const client = await createSqliteScriptClient(url);\n\n try {\n // Set up user-scoped temp views in production\n const scoping = await buildScopingSqlite(client);\n for (const stmt of scoping.setup) {\n await client.execute(stmt);\n }\n\n const results: DbExecResult[] = [];\n const shouldTransact = statements.length > 1;\n if (shouldTransact) await client.execute(\"BEGIN\");\n try {\n for (let i = 0; i < statements.length; i++) {\n const statement = statements[i];\n const hasReturning = /\\bRETURNING\\b/i.test(statement.sql);\n const finalSql = qualifySqliteWrite(\n injectOwnership(statement.sql, scoping),\n scoping,\n );\n try {\n const result =\n statement.args.length > 0\n ? await client.execute({\n sql: finalSql,\n args: statement.args as any[],\n })\n : await client.execute(finalSql);\n\n const rows: Record<string, unknown>[] =\n hasReturning && result.rows.length > 0\n ? sqliteRowsToObjects(result.rows, result.columns)\n : [];\n results.push({\n index: i + 1,\n sql: finalSql,\n changes: result.rowsAffected,\n lastInsertRowid: result.lastInsertRowid,\n rows,\n });\n } catch (err: any) {\n throw new Error(\n `Statement ${i + 1} failed: ${err?.message ?? String(err)}`,\n );\n }\n }\n if (shouldTransact) await client.execute(\"COMMIT\");\n } catch (err) {\n if (shouldTransact) {\n await client.execute(\"ROLLBACK\").catch(() => {});\n }\n throw err;\n }\n\n printBatchResult(results, parsed.format);\n\n for (const stmt of scoping.teardown) {\n await client.execute(stmt).catch(() => {});\n }\n } finally {\n client.close();\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"patch.d.ts","sourceRoot":"","sources":["../../../src/scripts/db/patch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AAsoBH,wBAA8B,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA6GnE"}
1
+ {"version":3,"file":"patch.d.ts","sourceRoot":"","sources":["../../../src/scripts/db/patch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AAmoBH,wBAA8B,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA6GnE"}
@@ -47,11 +47,11 @@
47
47
  * --edits '[{"find":"Q3","replace":"Q4"},{"find":"$1M","replace":"$1.2M"}]'
48
48
  */
49
49
  import path from "path";
50
- import { createClient } from "@libsql/client";
51
- import { getDatabaseUrl, getDatabaseAuthToken } from "../../db/client.js";
50
+ import { getDatabaseUrl } from "../../db/client.js";
52
51
  import { parseArgs, fail } from "../utils.js";
53
52
  import { assertNoSensitiveFrameworkTables } from "./safety.js";
54
53
  import { buildScopingPostgres, buildScopingSqlite } from "./scoping.js";
54
+ import { createSqliteScriptClient } from "./sqlite-client.js";
55
55
  function isPostgresUrl(url) {
56
56
  return url.startsWith("postgres://") || url.startsWith("postgresql://");
57
57
  }
@@ -510,10 +510,7 @@ async function runPostgres(opts) {
510
510
  }
511
511
  // ─── SQLite / libSQL path ───────────────────────────────────────────────────
512
512
  async function runSqlite(opts) {
513
- const client = createClient({
514
- url: opts.url,
515
- authToken: getDatabaseAuthToken(),
516
- });
513
+ const client = await createSqliteScriptClient(opts.url);
517
514
  try {
518
515
  const scoping = await buildScopingSqlite(client);
519
516
  for (const stmt of scoping.setup) {
@@ -1 +1 @@
1
- {"version":3,"file":"patch.js","sourceRoot":"","sources":["../../../src/scripts/db/patch.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Core script: db-patch\n *\n * Surgical search-and-replace on a text column in any SQL table. Instead of\n * re-sending the full column value (as `db-exec UPDATE` would require), the\n * agent sends one or more `{find, replace}` pairs. The script reads the row,\n * applies the edits in memory, and writes the result back in a single UPDATE.\n *\n * ## When to use which tool\n *\n * Large text field, small slice to change → db-patch (this)\n * e.g. fix one paragraph in a 50KB document, tweak one key in a dashboard\n * JSON blob, rename a label in a slide HTML string.\n *\n * Short field, set outright → db-exec UPDATE\n * e.g. `UPDATE forms SET status = 'published' WHERE id = '...'`.\n *\n * Multiple columns / computed values → db-exec UPDATE\n * e.g. `UPDATE meals SET calories = calories + 50, ...`.\n *\n * Domain-specific action exists → use that action\n * e.g. `edit-document` or `update-slide` — they also push live Yjs\n * updates to any open collaborative editor. db-patch is the generic\n * fallback for tables without a bespoke action.\n *\n * ## Why it's faster\n *\n * The agent only has to transmit the diff (the `find` + `replace`\n * strings), not the full new value. For large text fields — multi-kilobyte\n * markdown documents, slide HTML, dashboard/form JSON — this dramatically\n * reduces tokens per edit and keeps concurrent edits composable.\n *\n * ## Security\n *\n * In production mode, the same per-user / per-org temp view scoping that\n * `db-exec` uses applies here: the SELECT and UPDATE both go through the\n * scoped view, so you can never read or write rows outside the current\n * user's data. The WHERE clause is validated against a keyword denylist\n * (no ;, no chained statements, no DDL).\n *\n * ## Usage\n *\n * pnpm action db-patch --table <t> --column <c> --where \"<clause>\" \\\n * --find \"old\" --replace \"new\"\n *\n * pnpm action db-patch --table decks --column data --where \"id='d1'\" \\\n * --edits '[{\"find\":\"Q3\",\"replace\":\"Q4\"},{\"find\":\"$1M\",\"replace\":\"$1.2M\"}]'\n */\n\nimport path from \"path\";\nimport { createClient } from \"@libsql/client\";\nimport { getDatabaseUrl, getDatabaseAuthToken } from \"../../db/client.js\";\nimport { parseArgs, fail } from \"../utils.js\";\nimport { assertNoSensitiveFrameworkTables } from \"./safety.js\";\nimport { buildScopingPostgres, buildScopingSqlite } from \"./scoping.js\";\n\ninterface TextEdit {\n find: string;\n replace: string;\n}\n\n/**\n * JSON patch operation — a subset of RFC 6902 plus a convenience `move-before`\n * that's rare in the spec but common for list reordering. The agent ends up\n * needing this all the time (reordering dashboard panels, form fields, slide\n * layers) and without it has to do multi-step string surgery.\n */\ninterface JsonOp {\n op: \"set\" | \"replace\" | \"remove\" | \"move\" | \"move-before\" | \"insert\";\n /** JSON Pointer-style path, e.g. \"/panels/3/title\". \"\" = root. */\n path?: string;\n /** For move / move-before: source path. */\n from?: string;\n /** For set / replace / insert: value to write. */\n value?: unknown;\n}\n\ninterface EditResult {\n index: number;\n status: \"replaced\" | \"deleted\" | \"not-found\";\n detail: string;\n occurrences: number;\n}\n\ninterface PatchOutput {\n table: string;\n column: string;\n applied: number;\n total: number;\n bytesBefore: number;\n bytesAfter: number;\n results: EditResult[];\n}\n\nfunction isPostgresUrl(url: string): boolean {\n return url.startsWith(\"postgres://\") || url.startsWith(\"postgresql://\");\n}\n\n/** Only unquoted [A-Za-z_][A-Za-z0-9_]* identifiers are allowed — no spaces,\n * no quoting, no dotted names. This is deliberately strict: it stops the\n * agent from sneaking SQL into the table/column slots. */\nfunction isValidIdentifier(s: string): boolean {\n return /^[A-Za-z_][A-Za-z0-9_]*$/.test(s);\n}\n\n/** Reject WHERE clauses that could chain statements or hide DDL. This isn't\n * a full SQL parser — just a keyword/character denylist to keep the surface\n * area equivalent to what db-exec already allows. */\nfunction validateWhere(where: string): void {\n if (where.includes(\";\")) {\n fail(\"--where must not contain ';' (no statement chaining)\");\n }\n // Strip inline strings before keyword scanning so \"WHERE name = 'DROP TABLE'\"\n // doesn't trip the denylist.\n const stripped = where\n .replace(/'(?:''|[^'])*'/g, \"''\")\n .replace(/\"(?:\"\"|[^\"])*\"/g, '\"\"')\n .toUpperCase();\n\n const blocked = [\n \" INSERT \",\n \" UPDATE \",\n \" DELETE \",\n \" DROP \",\n \" ALTER \",\n \" CREATE \",\n \" ATTACH \",\n \" DETACH \",\n \" PRAGMA \",\n \" VACUUM \",\n \"--\",\n \"/*\",\n ];\n const padded = \" \" + stripped + \" \";\n for (const kw of blocked) {\n if (padded.includes(kw)) {\n fail(`--where must not contain \"${kw.trim()}\"`);\n }\n }\n}\n\nfunction parseEdits(parsed: Record<string, string>): TextEdit[] {\n let edits: TextEdit[];\n\n if (parsed.edits) {\n let parsedJson: unknown;\n try {\n parsedJson = JSON.parse(parsed.edits);\n } catch (e: any) {\n fail(`Invalid --edits JSON: ${e.message}`);\n }\n if (!Array.isArray(parsedJson) || parsedJson.length === 0) {\n fail(\"--edits must be a non-empty JSON array of {find, replace} objects\");\n }\n edits = parsedJson as TextEdit[];\n } else if (parsed.find !== undefined) {\n if (parsed.find === \"\") fail(\"--find cannot be empty\");\n edits = [{ find: parsed.find, replace: parsed.replace ?? \"\" }];\n } else {\n fail(\"Either --find/--replace or --edits is required\");\n }\n\n for (const edit of edits!) {\n if (typeof edit.find !== \"string\" || edit.find === \"\") {\n fail(\"Each edit must have a non-empty 'find' string\");\n }\n if (edit.replace === undefined || edit.replace === null) {\n edit.replace = \"\";\n }\n if (typeof edit.replace !== \"string\") {\n fail(\"Each edit's 'replace' field must be a string\");\n }\n }\n\n return edits!;\n}\n\nfunction preview(s: string): string {\n const max = 60;\n const trimmed = s.replace(/\\s+/g, \" \");\n return trimmed.length > max ? trimmed.slice(0, max) + \"...\" : trimmed;\n}\n\n// ─── JSON patch helpers ─────────────────────────────────────────────────────\n\n/** Parse a JSON Pointer (\"/panels/3/title\") into path segments. \"\" = root. */\nfunction parsePointer(pointer: string): string[] {\n if (pointer === \"\" || pointer === \"/\") return [];\n if (!pointer.startsWith(\"/\")) {\n fail(`JSON path must start with '/' (got: ${pointer})`);\n }\n return pointer\n .slice(1)\n .split(\"/\")\n .map((s) => s.replace(/~1/g, \"/\").replace(/~0/g, \"~\"));\n}\n\n/** Walk to the parent container of the given path. Returns [parent, lastKey]. */\nfunction resolveParent(\n root: unknown,\n segments: string[],\n): [any, string | number] {\n if (segments.length === 0) {\n fail(\"Root path is not supported for this operation\");\n }\n let node: any = root;\n for (let i = 0; i < segments.length - 1; i++) {\n const seg = segments[i];\n if (Array.isArray(node)) {\n const idx = parseInt(seg, 10);\n if (isNaN(idx) || idx < 0 || idx >= node.length) {\n fail(\n `Path segment \"${seg}\" is out of bounds for array of length ${node.length}`,\n );\n }\n node = node[idx];\n } else if (node && typeof node === \"object\") {\n if (!(seg in node)) {\n fail(`Path segment \"${seg}\" not found in object`);\n }\n node = node[seg];\n } else {\n fail(`Cannot descend into ${typeof node} at segment \"${seg}\"`);\n }\n }\n const last = segments[segments.length - 1];\n if (Array.isArray(node)) {\n const idx = last === \"-\" ? node.length : parseInt(last, 10);\n if (isNaN(idx)) fail(`Expected numeric index, got \"${last}\"`);\n return [node, idx];\n }\n return [node, last];\n}\n\n/** Apply one JSON op, mutating `root` in place. Returns a short detail string. */\nfunction applyJsonOp(root: any, op: JsonOp): string {\n switch (op.op) {\n case \"set\":\n case \"replace\": {\n if (op.path === undefined) fail(`${op.op} requires 'path'`);\n const [parent, key] = resolveParent(root, parsePointer(op.path));\n parent[key as any] = op.value;\n return `${op.op} ${op.path}`;\n }\n case \"remove\": {\n if (op.path === undefined) fail(\"remove requires 'path'\");\n const [parent, key] = resolveParent(root, parsePointer(op.path));\n if (Array.isArray(parent)) {\n parent.splice(key as number, 1);\n } else {\n delete parent[key as string];\n }\n return `remove ${op.path}`;\n }\n case \"insert\": {\n if (op.path === undefined) fail(\"insert requires 'path'\");\n const [parent, key] = resolveParent(root, parsePointer(op.path));\n if (!Array.isArray(parent)) fail(`insert target must be an array`);\n parent.splice(key as number, 0, op.value);\n return `insert at ${op.path}`;\n }\n case \"move\":\n case \"move-before\": {\n if (!op.from || op.path === undefined) {\n fail(`${op.op} requires 'from' and 'path'`);\n }\n const fromSeg = parsePointer(op.from);\n const toSeg = parsePointer(op.path);\n const [fromParent, fromKey] = resolveParent(root, fromSeg);\n // Extract the value\n let value: unknown;\n if (Array.isArray(fromParent)) {\n value = fromParent[fromKey as number];\n fromParent.splice(fromKey as number, 1);\n } else {\n value = fromParent[fromKey as string];\n delete fromParent[fromKey as string];\n }\n // For array moves where the destination is in the same array and\n // after the removed index, shift the target index down by one so\n // \"move /panels/7 to /panels/3\" lands exactly at index 3 even after\n // the earlier splice shifted indices.\n let [toParent, toKey] = resolveParent(root, toSeg);\n if (\n Array.isArray(toParent) &&\n Array.isArray(fromParent) &&\n toParent === fromParent\n ) {\n const fromIdx = fromKey as number;\n const toIdx = toKey as number;\n if (toIdx > fromIdx) {\n toKey = toIdx - 1;\n }\n }\n if (Array.isArray(toParent)) {\n toParent.splice(toKey as number, 0, value);\n } else {\n toParent[toKey as string] = value;\n }\n return `${op.op} ${op.from} → ${op.path}`;\n }\n default:\n fail(`Unknown JSON op: ${(op as any).op}`);\n }\n return \"\";\n}\n\nfunction parseJsonOps(parsed: Record<string, string>): JsonOp[] | null {\n if (!parsed.jsonOps && !parsed[\"json-ops\"]) return null;\n const raw = parsed.jsonOps ?? parsed[\"json-ops\"];\n let parsedJson: unknown;\n try {\n parsedJson = JSON.parse(raw);\n } catch (e: any) {\n fail(`Invalid --json-ops JSON: ${e.message}`);\n }\n if (!Array.isArray(parsedJson) || parsedJson.length === 0) {\n fail(\"--json-ops must be a non-empty JSON array\");\n }\n for (const op of parsedJson as any[]) {\n if (!op || typeof op !== \"object\" || typeof op.op !== \"string\") {\n fail(\"Each op must be an object with an 'op' field\");\n }\n }\n return parsedJson as JsonOp[];\n}\n\nfunction countOccurrences(haystack: string, needle: string): number {\n if (!needle) return 0;\n let count = 0;\n let idx = 0;\n while ((idx = haystack.indexOf(needle, idx)) !== -1) {\n count++;\n idx += needle.length;\n }\n return count;\n}\n\n/** Find all match positions (up to a cap so we don't explode memory). */\nfunction findAll(haystack: string, needle: string, cap = 10): number[] {\n const out: number[] = [];\n if (!needle) return out;\n let idx = 0;\n while ((idx = haystack.indexOf(needle, idx)) !== -1 && out.length < cap) {\n out.push(idx);\n idx += needle.length;\n }\n return out;\n}\n\n/** Format a single match with ~40 chars of surrounding context so the agent\n * can widen its `find` string to disambiguate ambiguous matches. */\nfunction formatContext(\n content: string,\n matchIdx: number,\n matchLen: number,\n radius = 40,\n): string {\n const start = Math.max(0, matchIdx - radius);\n const end = Math.min(content.length, matchIdx + matchLen + radius);\n const before = content.slice(start, matchIdx).replace(/\\s+/g, \" \");\n const middle = content\n .slice(matchIdx, matchIdx + matchLen)\n .replace(/\\s+/g, \" \");\n const after = content.slice(matchIdx + matchLen, end).replace(/\\s+/g, \" \");\n const prefix = start > 0 ? \"…\" : \"\";\n const suffix = end < content.length ? \"…\" : \"\";\n return `${prefix}${before}⟨${middle}⟩${after}${suffix}`;\n}\n\n/** Build a \"string not unique\" error message showing each match in\n * context — matches Claude Code's Edit-tool UX so the agent can\n * widen the find string and retry. */\nfunction buildAmbiguousMessage(\n findStr: string,\n content: string,\n count: number,\n): string {\n const positions = findAll(content, findStr, 6);\n const lines = [\n `Found ${count} occurrences of the 'find' string — db-patch requires exactly one match by default.`,\n `Widen 'find' with unique surrounding context, or pass --all to replace every occurrence.`,\n `'find' preview: \"${preview(findStr)}\"`,\n \"Matches:\",\n ];\n for (let i = 0; i < positions.length; i++) {\n lines.push(\n ` [${i + 1}] ${formatContext(content, positions[i], findStr.length)}`,\n );\n }\n if (count > positions.length) {\n lines.push(` … and ${count - positions.length} more`);\n }\n return lines.join(\"\\n\");\n}\n\n/**\n * Apply edits sequentially.\n *\n * Default behavior matches Claude Code's Edit tool: the `find` string must\n * match exactly one occurrence. If 0 → \"not found\". If >1 → error with\n * surrounding context for each match so the agent can widen `find` and\n * retry. Pass `replaceAll` (`--all`) to allow replacing every occurrence.\n *\n * This strict-uniqueness default is a deliberate reliability upgrade — 9×\n * fewer silent wrong-match bugs at the cost of slightly more verbose finds.\n */\nfunction applyEdits(\n content: string,\n edits: TextEdit[],\n replaceAll: boolean,\n): { content: string; results: EditResult[]; applied: number } {\n let out = content;\n const results: EditResult[] = [];\n let applied = 0;\n\n for (let i = 0; i < edits.length; i++) {\n const edit = edits[i];\n const occurrences = countOccurrences(out, edit.find);\n\n if (occurrences === 0) {\n results.push({\n index: i,\n status: \"not-found\",\n detail: `NOT FOUND: \"${preview(edit.find)}\"`,\n occurrences: 0,\n });\n continue;\n }\n\n if (replaceAll) {\n // Literal replaceAll via split/join — no regex, no special chars.\n out = out.split(edit.find).join(edit.replace);\n applied++;\n results.push({\n index: i,\n status: edit.replace === \"\" ? \"deleted\" : \"replaced\",\n detail: `${edit.replace === \"\" ? \"deleted\" : \"replaced\"} ${occurrences}×: \"${preview(edit.find)}\"`,\n occurrences,\n });\n } else if (occurrences > 1) {\n results.push({\n index: i,\n status: \"not-found\",\n detail: buildAmbiguousMessage(edit.find, out, occurrences),\n occurrences,\n });\n } else {\n const idx = out.indexOf(edit.find);\n out =\n out.slice(0, idx) + edit.replace + out.slice(idx + edit.find.length);\n applied++;\n results.push({\n index: i,\n status: edit.replace === \"\" ? \"deleted\" : \"replaced\",\n detail: `${edit.replace === \"\" ? \"deleted\" : \"replaced\"}: \"${preview(edit.find)}\"`,\n occurrences: 1,\n });\n }\n }\n\n return { content: out, results, applied };\n}\n\nfunction printResult(out: PatchOutput, format?: string): void {\n if (format === \"json\") {\n console.log(JSON.stringify(out, null, 2));\n return;\n }\n console.log(`db-patch: ${out.table}.${out.column}`);\n console.log(` Applied: ${out.applied}/${out.total}`);\n console.log(` Bytes: ${out.bytesBefore} → ${out.bytesAfter}`);\n for (const r of out.results) {\n console.log(` - ${r.detail}`);\n }\n}\n\ninterface RunOpts {\n url: string;\n table: string;\n column: string;\n where: string;\n edits: TextEdit[];\n jsonOps?: JsonOp[];\n replaceAll: boolean;\n format?: string;\n}\n\nfunction applyEither(\n original: string,\n opts: RunOpts,\n): {\n content: string;\n results: EditResult[];\n applied: number;\n total: number;\n} {\n if (opts.jsonOps && opts.jsonOps.length > 0) {\n let root: unknown;\n try {\n root = JSON.parse(original);\n } catch (e: any) {\n fail(\n `--json-ops requires the column value to be valid JSON. Parse failed: ${e.message}`,\n );\n }\n const results: EditResult[] = [];\n let applied = 0;\n for (let i = 0; i < opts.jsonOps.length; i++) {\n const op = opts.jsonOps[i];\n try {\n const detail = applyJsonOp(root, op);\n results.push({\n index: i,\n status: \"replaced\",\n detail,\n occurrences: 1,\n });\n applied++;\n } catch (e: any) {\n results.push({\n index: i,\n status: \"not-found\",\n detail: `FAILED: ${e?.message ?? String(e)}`,\n occurrences: 0,\n });\n }\n }\n return {\n content: JSON.stringify(root),\n results,\n applied,\n total: opts.jsonOps.length,\n };\n }\n const out = applyEdits(original, opts.edits, opts.replaceAll);\n return { ...out, total: opts.edits.length };\n}\n\n// ─── Postgres path ──────────────────────────────────────────────────────────\n\nasync function runPostgres(opts: RunOpts): Promise<void> {\n const { default: pg } = await import(\"postgres\");\n const pgSql = pg(opts.url);\n try {\n let result:\n | {\n table: string;\n column: string;\n applied: number;\n total: number;\n bytesBefore: number;\n bytesAfter: number;\n results: EditResult[];\n }\n | undefined;\n\n await pgSql.begin(async (tx: any) => {\n // Same temp-view scoping db-exec uses — SELECT and UPDATE both go\n // through the scoped view. Keep setup and teardown transaction-local\n // so pooled Postgres backends never retain the temp views.\n const scoping = await buildScopingPostgres(tx);\n try {\n for (const stmt of scoping.setup) {\n await tx.unsafe(stmt);\n }\n\n const selectSql = `SELECT \"${opts.column}\" AS __val FROM \"${opts.table}\" WHERE ${opts.where}`;\n const selected: any[] = Array.from(await tx.unsafe(selectSql));\n\n if (selected.length === 0) {\n fail(\n `No rows matched: ${opts.table} WHERE ${opts.where}. ` +\n `(In production, data scoping filters results to the current user — the row may exist but be owned by someone else.)`,\n );\n }\n if (selected.length > 1) {\n fail(\n `WHERE matched ${selected.length} rows in ${opts.table}. db-patch expects exactly one row — narrow the WHERE clause (usually by primary key).`,\n );\n }\n\n const original = (selected[0].__val ?? \"\") as string;\n if (typeof original !== \"string\") {\n fail(\n `Column ${opts.table}.${opts.column} is not a text column (got ${typeof original}).`,\n );\n }\n\n const { content, results, applied, total } = applyEither(\n original,\n opts,\n );\n\n if (applied > 0) {\n await tx.unsafe(\n `UPDATE \"${opts.table}\" SET \"${opts.column}\" = $1 WHERE ${opts.where}`,\n [content],\n );\n }\n\n result = {\n table: opts.table,\n column: opts.column,\n applied,\n total,\n bytesBefore: original.length,\n bytesAfter: content.length,\n results,\n };\n } finally {\n for (const stmt of scoping.teardown) {\n await tx.unsafe(stmt).catch(() => {});\n }\n }\n });\n\n if (result) {\n printResult(result, opts.format);\n }\n } finally {\n await pgSql.end();\n }\n}\n\n// ─── SQLite / libSQL path ───────────────────────────────────────────────────\n\nasync function runSqlite(opts: RunOpts): Promise<void> {\n const client = createClient({\n url: opts.url,\n authToken: getDatabaseAuthToken(),\n });\n try {\n const scoping = await buildScopingSqlite(client);\n for (const stmt of scoping.setup) {\n await client.execute(stmt);\n }\n\n const selectSql = `SELECT \"${opts.column}\" AS __val FROM \"${opts.table}\" WHERE ${opts.where}`;\n const selectRes = await client.execute(selectSql);\n\n if (selectRes.rows.length === 0) {\n fail(\n `No rows matched: ${opts.table} WHERE ${opts.where}. ` +\n `(In production, data scoping filters results to the current user — the row may exist but be owned by someone else.)`,\n );\n }\n if (selectRes.rows.length > 1) {\n fail(\n `WHERE matched ${selectRes.rows.length} rows in ${opts.table}. db-patch expects exactly one row — narrow the WHERE clause (usually by primary key).`,\n );\n }\n\n const row = selectRes.rows[0] as any;\n const original = (row.__val ?? row[0] ?? \"\") as string;\n if (typeof original !== \"string\") {\n fail(\n `Column ${opts.table}.${opts.column} is not a text column (got ${typeof original}).`,\n );\n }\n\n const { content, results, applied, total } = applyEither(original, opts);\n\n if (applied > 0) {\n await client.execute({\n sql: `UPDATE \"${opts.table}\" SET \"${opts.column}\" = ? WHERE ${opts.where}`,\n args: [content],\n });\n }\n\n printResult(\n {\n table: opts.table,\n column: opts.column,\n applied,\n total,\n bytesBefore: original.length,\n bytesAfter: content.length,\n results,\n },\n opts.format,\n );\n\n for (const stmt of scoping.teardown) {\n await client.execute(stmt).catch(() => {});\n }\n } finally {\n client.close();\n }\n}\n\n// ─── Entry point ────────────────────────────────────────────────────────────\n\nexport default async function dbPatch(args: string[]): Promise<void> {\n const parsed = parseArgs(args);\n\n if (parsed.help === \"true\") {\n console.log(`Usage: pnpm action db-patch --table <t> --column <c> --where \"<clause>\" [edit flags]\n\nSurgical search-and-replace on a text column. Avoids re-sending the full\ncolumn value — ideal for large strings (documents, slides, dashboards, JSON).\n\nRequired:\n --table <name> Target table (identifier; no quoting)\n --column <name> Target text column (identifier; no quoting)\n --where \"<clause>\" SQL WHERE clause that matches exactly one row\n\nEdit mode (pick one):\n --find <text> Text to find (single edit; default replace = \"\")\n --replace <text> Replacement text (used with --find)\n --edits <json> Batch: JSON array of {find, replace} objects\n --json-ops <json> Structural JSON edits on a JSON column — array of ops:\n { op: \"set\", path, value } → set/replace at path\n { op: \"remove\", path } → delete at path\n { op: \"insert\", path, value } → insert into array\n { op: \"move\", from, path } → move node\n { op: \"move-before\", from, path } → move, stable indexing\n Paths use JSON Pointer (\"/panels/3/title\").\n Much safer than string patches for JSON columns\n (dashboards, forms, slide decks).\n\nOptions:\n --all Replace every occurrence of each 'find' (default: first only)\n --format json Output as JSON\n --help Show this help\n\nExamples:\n # Fix a typo in one document\n pnpm action db-patch --table documents --column content \\\\\n --where \"id='abc'\" --find \"teh\" --replace \"the\"\n\n # Batch edits on a deck's JSON blob\n pnpm action db-patch --table decks --column data --where \"id='d1'\" \\\\\n --edits '[{\"find\":\"\\\\\"Q3\\\\\"\",\"replace\":\"\\\\\"Q4\\\\\"\"},{\"find\":\"$1M\",\"replace\":\"$1.2M\"}]'\n\nWhen to use db-patch vs other tools:\n Large text field, small edit → db-patch (this)\n Short field or multi-column set → db-exec UPDATE\n Domain action exists (edit-document, ...) → use that action (syncs live\n to open collaborative editors)\n`);\n return;\n }\n\n const table = parsed.table;\n const column = parsed.column;\n const where = parsed.where;\n\n if (!table) fail(\"--table is required\");\n if (!column) fail(\"--column is required\");\n if (!where) fail(\"--where is required\");\n if (!isValidIdentifier(table))\n fail(\n `Invalid --table: \"${table}\". Must be a plain identifier (letters, digits, underscore).`,\n );\n if (!isValidIdentifier(column))\n fail(\n `Invalid --column: \"${column}\". Must be a plain identifier (letters, digits, underscore).`,\n );\n assertNoSensitiveFrameworkTables(table, \"patch\");\n assertNoSensitiveFrameworkTables(where, \"read\");\n validateWhere(where);\n\n const jsonOps = parseJsonOps(parsed);\n // Edit parsing only runs when json-ops isn't provided — otherwise the\n // find/replace args are irrelevant and would error if missing.\n const edits = jsonOps ? [] : parseEdits(parsed);\n const replaceAll = parsed.all === \"true\";\n\n // Resolve database URL: --db flag → DATABASE_URL env → default file path\n let url: string;\n if (parsed.db) {\n url = \"file:\" + path.resolve(parsed.db);\n } else if (getDatabaseUrl()) {\n url = getDatabaseUrl();\n } else {\n url = \"file:\" + path.resolve(process.cwd(), \"data\", \"app.db\");\n }\n\n if (isPostgresUrl(url)) {\n await runPostgres({\n url,\n table,\n column,\n where,\n edits,\n jsonOps: jsonOps ?? undefined,\n replaceAll,\n format: parsed.format,\n });\n } else {\n await runSqlite({\n url,\n table,\n column,\n where,\n edits,\n jsonOps: jsonOps ?? undefined,\n replaceAll,\n format: parsed.format,\n });\n }\n}\n"]}
1
+ {"version":3,"file":"patch.js","sourceRoot":"","sources":["../../../src/scripts/db/patch.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Core script: db-patch\n *\n * Surgical search-and-replace on a text column in any SQL table. Instead of\n * re-sending the full column value (as `db-exec UPDATE` would require), the\n * agent sends one or more `{find, replace}` pairs. The script reads the row,\n * applies the edits in memory, and writes the result back in a single UPDATE.\n *\n * ## When to use which tool\n *\n * Large text field, small slice to change → db-patch (this)\n * e.g. fix one paragraph in a 50KB document, tweak one key in a dashboard\n * JSON blob, rename a label in a slide HTML string.\n *\n * Short field, set outright → db-exec UPDATE\n * e.g. `UPDATE forms SET status = 'published' WHERE id = '...'`.\n *\n * Multiple columns / computed values → db-exec UPDATE\n * e.g. `UPDATE meals SET calories = calories + 50, ...`.\n *\n * Domain-specific action exists → use that action\n * e.g. `edit-document` or `update-slide` — they also push live Yjs\n * updates to any open collaborative editor. db-patch is the generic\n * fallback for tables without a bespoke action.\n *\n * ## Why it's faster\n *\n * The agent only has to transmit the diff (the `find` + `replace`\n * strings), not the full new value. For large text fields — multi-kilobyte\n * markdown documents, slide HTML, dashboard/form JSON — this dramatically\n * reduces tokens per edit and keeps concurrent edits composable.\n *\n * ## Security\n *\n * In production mode, the same per-user / per-org temp view scoping that\n * `db-exec` uses applies here: the SELECT and UPDATE both go through the\n * scoped view, so you can never read or write rows outside the current\n * user's data. The WHERE clause is validated against a keyword denylist\n * (no ;, no chained statements, no DDL).\n *\n * ## Usage\n *\n * pnpm action db-patch --table <t> --column <c> --where \"<clause>\" \\\n * --find \"old\" --replace \"new\"\n *\n * pnpm action db-patch --table decks --column data --where \"id='d1'\" \\\n * --edits '[{\"find\":\"Q3\",\"replace\":\"Q4\"},{\"find\":\"$1M\",\"replace\":\"$1.2M\"}]'\n */\n\nimport path from \"path\";\nimport { getDatabaseUrl } from \"../../db/client.js\";\nimport { parseArgs, fail } from \"../utils.js\";\nimport { assertNoSensitiveFrameworkTables } from \"./safety.js\";\nimport { buildScopingPostgres, buildScopingSqlite } from \"./scoping.js\";\nimport { createSqliteScriptClient } from \"./sqlite-client.js\";\n\ninterface TextEdit {\n find: string;\n replace: string;\n}\n\n/**\n * JSON patch operation — a subset of RFC 6902 plus a convenience `move-before`\n * that's rare in the spec but common for list reordering. The agent ends up\n * needing this all the time (reordering dashboard panels, form fields, slide\n * layers) and without it has to do multi-step string surgery.\n */\ninterface JsonOp {\n op: \"set\" | \"replace\" | \"remove\" | \"move\" | \"move-before\" | \"insert\";\n /** JSON Pointer-style path, e.g. \"/panels/3/title\". \"\" = root. */\n path?: string;\n /** For move / move-before: source path. */\n from?: string;\n /** For set / replace / insert: value to write. */\n value?: unknown;\n}\n\ninterface EditResult {\n index: number;\n status: \"replaced\" | \"deleted\" | \"not-found\";\n detail: string;\n occurrences: number;\n}\n\ninterface PatchOutput {\n table: string;\n column: string;\n applied: number;\n total: number;\n bytesBefore: number;\n bytesAfter: number;\n results: EditResult[];\n}\n\nfunction isPostgresUrl(url: string): boolean {\n return url.startsWith(\"postgres://\") || url.startsWith(\"postgresql://\");\n}\n\n/** Only unquoted [A-Za-z_][A-Za-z0-9_]* identifiers are allowed — no spaces,\n * no quoting, no dotted names. This is deliberately strict: it stops the\n * agent from sneaking SQL into the table/column slots. */\nfunction isValidIdentifier(s: string): boolean {\n return /^[A-Za-z_][A-Za-z0-9_]*$/.test(s);\n}\n\n/** Reject WHERE clauses that could chain statements or hide DDL. This isn't\n * a full SQL parser — just a keyword/character denylist to keep the surface\n * area equivalent to what db-exec already allows. */\nfunction validateWhere(where: string): void {\n if (where.includes(\";\")) {\n fail(\"--where must not contain ';' (no statement chaining)\");\n }\n // Strip inline strings before keyword scanning so \"WHERE name = 'DROP TABLE'\"\n // doesn't trip the denylist.\n const stripped = where\n .replace(/'(?:''|[^'])*'/g, \"''\")\n .replace(/\"(?:\"\"|[^\"])*\"/g, '\"\"')\n .toUpperCase();\n\n const blocked = [\n \" INSERT \",\n \" UPDATE \",\n \" DELETE \",\n \" DROP \",\n \" ALTER \",\n \" CREATE \",\n \" ATTACH \",\n \" DETACH \",\n \" PRAGMA \",\n \" VACUUM \",\n \"--\",\n \"/*\",\n ];\n const padded = \" \" + stripped + \" \";\n for (const kw of blocked) {\n if (padded.includes(kw)) {\n fail(`--where must not contain \"${kw.trim()}\"`);\n }\n }\n}\n\nfunction parseEdits(parsed: Record<string, string>): TextEdit[] {\n let edits: TextEdit[];\n\n if (parsed.edits) {\n let parsedJson: unknown;\n try {\n parsedJson = JSON.parse(parsed.edits);\n } catch (e: any) {\n fail(`Invalid --edits JSON: ${e.message}`);\n }\n if (!Array.isArray(parsedJson) || parsedJson.length === 0) {\n fail(\"--edits must be a non-empty JSON array of {find, replace} objects\");\n }\n edits = parsedJson as TextEdit[];\n } else if (parsed.find !== undefined) {\n if (parsed.find === \"\") fail(\"--find cannot be empty\");\n edits = [{ find: parsed.find, replace: parsed.replace ?? \"\" }];\n } else {\n fail(\"Either --find/--replace or --edits is required\");\n }\n\n for (const edit of edits!) {\n if (typeof edit.find !== \"string\" || edit.find === \"\") {\n fail(\"Each edit must have a non-empty 'find' string\");\n }\n if (edit.replace === undefined || edit.replace === null) {\n edit.replace = \"\";\n }\n if (typeof edit.replace !== \"string\") {\n fail(\"Each edit's 'replace' field must be a string\");\n }\n }\n\n return edits!;\n}\n\nfunction preview(s: string): string {\n const max = 60;\n const trimmed = s.replace(/\\s+/g, \" \");\n return trimmed.length > max ? trimmed.slice(0, max) + \"...\" : trimmed;\n}\n\n// ─── JSON patch helpers ─────────────────────────────────────────────────────\n\n/** Parse a JSON Pointer (\"/panels/3/title\") into path segments. \"\" = root. */\nfunction parsePointer(pointer: string): string[] {\n if (pointer === \"\" || pointer === \"/\") return [];\n if (!pointer.startsWith(\"/\")) {\n fail(`JSON path must start with '/' (got: ${pointer})`);\n }\n return pointer\n .slice(1)\n .split(\"/\")\n .map((s) => s.replace(/~1/g, \"/\").replace(/~0/g, \"~\"));\n}\n\n/** Walk to the parent container of the given path. Returns [parent, lastKey]. */\nfunction resolveParent(\n root: unknown,\n segments: string[],\n): [any, string | number] {\n if (segments.length === 0) {\n fail(\"Root path is not supported for this operation\");\n }\n let node: any = root;\n for (let i = 0; i < segments.length - 1; i++) {\n const seg = segments[i];\n if (Array.isArray(node)) {\n const idx = parseInt(seg, 10);\n if (isNaN(idx) || idx < 0 || idx >= node.length) {\n fail(\n `Path segment \"${seg}\" is out of bounds for array of length ${node.length}`,\n );\n }\n node = node[idx];\n } else if (node && typeof node === \"object\") {\n if (!(seg in node)) {\n fail(`Path segment \"${seg}\" not found in object`);\n }\n node = node[seg];\n } else {\n fail(`Cannot descend into ${typeof node} at segment \"${seg}\"`);\n }\n }\n const last = segments[segments.length - 1];\n if (Array.isArray(node)) {\n const idx = last === \"-\" ? node.length : parseInt(last, 10);\n if (isNaN(idx)) fail(`Expected numeric index, got \"${last}\"`);\n return [node, idx];\n }\n return [node, last];\n}\n\n/** Apply one JSON op, mutating `root` in place. Returns a short detail string. */\nfunction applyJsonOp(root: any, op: JsonOp): string {\n switch (op.op) {\n case \"set\":\n case \"replace\": {\n if (op.path === undefined) fail(`${op.op} requires 'path'`);\n const [parent, key] = resolveParent(root, parsePointer(op.path));\n parent[key as any] = op.value;\n return `${op.op} ${op.path}`;\n }\n case \"remove\": {\n if (op.path === undefined) fail(\"remove requires 'path'\");\n const [parent, key] = resolveParent(root, parsePointer(op.path));\n if (Array.isArray(parent)) {\n parent.splice(key as number, 1);\n } else {\n delete parent[key as string];\n }\n return `remove ${op.path}`;\n }\n case \"insert\": {\n if (op.path === undefined) fail(\"insert requires 'path'\");\n const [parent, key] = resolveParent(root, parsePointer(op.path));\n if (!Array.isArray(parent)) fail(`insert target must be an array`);\n parent.splice(key as number, 0, op.value);\n return `insert at ${op.path}`;\n }\n case \"move\":\n case \"move-before\": {\n if (!op.from || op.path === undefined) {\n fail(`${op.op} requires 'from' and 'path'`);\n }\n const fromSeg = parsePointer(op.from);\n const toSeg = parsePointer(op.path);\n const [fromParent, fromKey] = resolveParent(root, fromSeg);\n // Extract the value\n let value: unknown;\n if (Array.isArray(fromParent)) {\n value = fromParent[fromKey as number];\n fromParent.splice(fromKey as number, 1);\n } else {\n value = fromParent[fromKey as string];\n delete fromParent[fromKey as string];\n }\n // For array moves where the destination is in the same array and\n // after the removed index, shift the target index down by one so\n // \"move /panels/7 to /panels/3\" lands exactly at index 3 even after\n // the earlier splice shifted indices.\n let [toParent, toKey] = resolveParent(root, toSeg);\n if (\n Array.isArray(toParent) &&\n Array.isArray(fromParent) &&\n toParent === fromParent\n ) {\n const fromIdx = fromKey as number;\n const toIdx = toKey as number;\n if (toIdx > fromIdx) {\n toKey = toIdx - 1;\n }\n }\n if (Array.isArray(toParent)) {\n toParent.splice(toKey as number, 0, value);\n } else {\n toParent[toKey as string] = value;\n }\n return `${op.op} ${op.from} → ${op.path}`;\n }\n default:\n fail(`Unknown JSON op: ${(op as any).op}`);\n }\n return \"\";\n}\n\nfunction parseJsonOps(parsed: Record<string, string>): JsonOp[] | null {\n if (!parsed.jsonOps && !parsed[\"json-ops\"]) return null;\n const raw = parsed.jsonOps ?? parsed[\"json-ops\"];\n let parsedJson: unknown;\n try {\n parsedJson = JSON.parse(raw);\n } catch (e: any) {\n fail(`Invalid --json-ops JSON: ${e.message}`);\n }\n if (!Array.isArray(parsedJson) || parsedJson.length === 0) {\n fail(\"--json-ops must be a non-empty JSON array\");\n }\n for (const op of parsedJson as any[]) {\n if (!op || typeof op !== \"object\" || typeof op.op !== \"string\") {\n fail(\"Each op must be an object with an 'op' field\");\n }\n }\n return parsedJson as JsonOp[];\n}\n\nfunction countOccurrences(haystack: string, needle: string): number {\n if (!needle) return 0;\n let count = 0;\n let idx = 0;\n while ((idx = haystack.indexOf(needle, idx)) !== -1) {\n count++;\n idx += needle.length;\n }\n return count;\n}\n\n/** Find all match positions (up to a cap so we don't explode memory). */\nfunction findAll(haystack: string, needle: string, cap = 10): number[] {\n const out: number[] = [];\n if (!needle) return out;\n let idx = 0;\n while ((idx = haystack.indexOf(needle, idx)) !== -1 && out.length < cap) {\n out.push(idx);\n idx += needle.length;\n }\n return out;\n}\n\n/** Format a single match with ~40 chars of surrounding context so the agent\n * can widen its `find` string to disambiguate ambiguous matches. */\nfunction formatContext(\n content: string,\n matchIdx: number,\n matchLen: number,\n radius = 40,\n): string {\n const start = Math.max(0, matchIdx - radius);\n const end = Math.min(content.length, matchIdx + matchLen + radius);\n const before = content.slice(start, matchIdx).replace(/\\s+/g, \" \");\n const middle = content\n .slice(matchIdx, matchIdx + matchLen)\n .replace(/\\s+/g, \" \");\n const after = content.slice(matchIdx + matchLen, end).replace(/\\s+/g, \" \");\n const prefix = start > 0 ? \"…\" : \"\";\n const suffix = end < content.length ? \"…\" : \"\";\n return `${prefix}${before}⟨${middle}⟩${after}${suffix}`;\n}\n\n/** Build a \"string not unique\" error message showing each match in\n * context — matches Claude Code's Edit-tool UX so the agent can\n * widen the find string and retry. */\nfunction buildAmbiguousMessage(\n findStr: string,\n content: string,\n count: number,\n): string {\n const positions = findAll(content, findStr, 6);\n const lines = [\n `Found ${count} occurrences of the 'find' string — db-patch requires exactly one match by default.`,\n `Widen 'find' with unique surrounding context, or pass --all to replace every occurrence.`,\n `'find' preview: \"${preview(findStr)}\"`,\n \"Matches:\",\n ];\n for (let i = 0; i < positions.length; i++) {\n lines.push(\n ` [${i + 1}] ${formatContext(content, positions[i], findStr.length)}`,\n );\n }\n if (count > positions.length) {\n lines.push(` … and ${count - positions.length} more`);\n }\n return lines.join(\"\\n\");\n}\n\n/**\n * Apply edits sequentially.\n *\n * Default behavior matches Claude Code's Edit tool: the `find` string must\n * match exactly one occurrence. If 0 → \"not found\". If >1 → error with\n * surrounding context for each match so the agent can widen `find` and\n * retry. Pass `replaceAll` (`--all`) to allow replacing every occurrence.\n *\n * This strict-uniqueness default is a deliberate reliability upgrade — 9×\n * fewer silent wrong-match bugs at the cost of slightly more verbose finds.\n */\nfunction applyEdits(\n content: string,\n edits: TextEdit[],\n replaceAll: boolean,\n): { content: string; results: EditResult[]; applied: number } {\n let out = content;\n const results: EditResult[] = [];\n let applied = 0;\n\n for (let i = 0; i < edits.length; i++) {\n const edit = edits[i];\n const occurrences = countOccurrences(out, edit.find);\n\n if (occurrences === 0) {\n results.push({\n index: i,\n status: \"not-found\",\n detail: `NOT FOUND: \"${preview(edit.find)}\"`,\n occurrences: 0,\n });\n continue;\n }\n\n if (replaceAll) {\n // Literal replaceAll via split/join — no regex, no special chars.\n out = out.split(edit.find).join(edit.replace);\n applied++;\n results.push({\n index: i,\n status: edit.replace === \"\" ? \"deleted\" : \"replaced\",\n detail: `${edit.replace === \"\" ? \"deleted\" : \"replaced\"} ${occurrences}×: \"${preview(edit.find)}\"`,\n occurrences,\n });\n } else if (occurrences > 1) {\n results.push({\n index: i,\n status: \"not-found\",\n detail: buildAmbiguousMessage(edit.find, out, occurrences),\n occurrences,\n });\n } else {\n const idx = out.indexOf(edit.find);\n out =\n out.slice(0, idx) + edit.replace + out.slice(idx + edit.find.length);\n applied++;\n results.push({\n index: i,\n status: edit.replace === \"\" ? \"deleted\" : \"replaced\",\n detail: `${edit.replace === \"\" ? \"deleted\" : \"replaced\"}: \"${preview(edit.find)}\"`,\n occurrences: 1,\n });\n }\n }\n\n return { content: out, results, applied };\n}\n\nfunction printResult(out: PatchOutput, format?: string): void {\n if (format === \"json\") {\n console.log(JSON.stringify(out, null, 2));\n return;\n }\n console.log(`db-patch: ${out.table}.${out.column}`);\n console.log(` Applied: ${out.applied}/${out.total}`);\n console.log(` Bytes: ${out.bytesBefore} → ${out.bytesAfter}`);\n for (const r of out.results) {\n console.log(` - ${r.detail}`);\n }\n}\n\ninterface RunOpts {\n url: string;\n table: string;\n column: string;\n where: string;\n edits: TextEdit[];\n jsonOps?: JsonOp[];\n replaceAll: boolean;\n format?: string;\n}\n\nfunction applyEither(\n original: string,\n opts: RunOpts,\n): {\n content: string;\n results: EditResult[];\n applied: number;\n total: number;\n} {\n if (opts.jsonOps && opts.jsonOps.length > 0) {\n let root: unknown;\n try {\n root = JSON.parse(original);\n } catch (e: any) {\n fail(\n `--json-ops requires the column value to be valid JSON. Parse failed: ${e.message}`,\n );\n }\n const results: EditResult[] = [];\n let applied = 0;\n for (let i = 0; i < opts.jsonOps.length; i++) {\n const op = opts.jsonOps[i];\n try {\n const detail = applyJsonOp(root, op);\n results.push({\n index: i,\n status: \"replaced\",\n detail,\n occurrences: 1,\n });\n applied++;\n } catch (e: any) {\n results.push({\n index: i,\n status: \"not-found\",\n detail: `FAILED: ${e?.message ?? String(e)}`,\n occurrences: 0,\n });\n }\n }\n return {\n content: JSON.stringify(root),\n results,\n applied,\n total: opts.jsonOps.length,\n };\n }\n const out = applyEdits(original, opts.edits, opts.replaceAll);\n return { ...out, total: opts.edits.length };\n}\n\n// ─── Postgres path ──────────────────────────────────────────────────────────\n\nasync function runPostgres(opts: RunOpts): Promise<void> {\n const { default: pg } = await import(\"postgres\");\n const pgSql = pg(opts.url);\n try {\n let result:\n | {\n table: string;\n column: string;\n applied: number;\n total: number;\n bytesBefore: number;\n bytesAfter: number;\n results: EditResult[];\n }\n | undefined;\n\n await pgSql.begin(async (tx: any) => {\n // Same temp-view scoping db-exec uses — SELECT and UPDATE both go\n // through the scoped view. Keep setup and teardown transaction-local\n // so pooled Postgres backends never retain the temp views.\n const scoping = await buildScopingPostgres(tx);\n try {\n for (const stmt of scoping.setup) {\n await tx.unsafe(stmt);\n }\n\n const selectSql = `SELECT \"${opts.column}\" AS __val FROM \"${opts.table}\" WHERE ${opts.where}`;\n const selected: any[] = Array.from(await tx.unsafe(selectSql));\n\n if (selected.length === 0) {\n fail(\n `No rows matched: ${opts.table} WHERE ${opts.where}. ` +\n `(In production, data scoping filters results to the current user — the row may exist but be owned by someone else.)`,\n );\n }\n if (selected.length > 1) {\n fail(\n `WHERE matched ${selected.length} rows in ${opts.table}. db-patch expects exactly one row — narrow the WHERE clause (usually by primary key).`,\n );\n }\n\n const original = (selected[0].__val ?? \"\") as string;\n if (typeof original !== \"string\") {\n fail(\n `Column ${opts.table}.${opts.column} is not a text column (got ${typeof original}).`,\n );\n }\n\n const { content, results, applied, total } = applyEither(\n original,\n opts,\n );\n\n if (applied > 0) {\n await tx.unsafe(\n `UPDATE \"${opts.table}\" SET \"${opts.column}\" = $1 WHERE ${opts.where}`,\n [content],\n );\n }\n\n result = {\n table: opts.table,\n column: opts.column,\n applied,\n total,\n bytesBefore: original.length,\n bytesAfter: content.length,\n results,\n };\n } finally {\n for (const stmt of scoping.teardown) {\n await tx.unsafe(stmt).catch(() => {});\n }\n }\n });\n\n if (result) {\n printResult(result, opts.format);\n }\n } finally {\n await pgSql.end();\n }\n}\n\n// ─── SQLite / libSQL path ───────────────────────────────────────────────────\n\nasync function runSqlite(opts: RunOpts): Promise<void> {\n const client = await createSqliteScriptClient(opts.url);\n try {\n const scoping = await buildScopingSqlite(client);\n for (const stmt of scoping.setup) {\n await client.execute(stmt);\n }\n\n const selectSql = `SELECT \"${opts.column}\" AS __val FROM \"${opts.table}\" WHERE ${opts.where}`;\n const selectRes = await client.execute(selectSql);\n\n if (selectRes.rows.length === 0) {\n fail(\n `No rows matched: ${opts.table} WHERE ${opts.where}. ` +\n `(In production, data scoping filters results to the current user — the row may exist but be owned by someone else.)`,\n );\n }\n if (selectRes.rows.length > 1) {\n fail(\n `WHERE matched ${selectRes.rows.length} rows in ${opts.table}. db-patch expects exactly one row — narrow the WHERE clause (usually by primary key).`,\n );\n }\n\n const row = selectRes.rows[0] as any;\n const original = (row.__val ?? row[0] ?? \"\") as string;\n if (typeof original !== \"string\") {\n fail(\n `Column ${opts.table}.${opts.column} is not a text column (got ${typeof original}).`,\n );\n }\n\n const { content, results, applied, total } = applyEither(original, opts);\n\n if (applied > 0) {\n await client.execute({\n sql: `UPDATE \"${opts.table}\" SET \"${opts.column}\" = ? WHERE ${opts.where}`,\n args: [content],\n });\n }\n\n printResult(\n {\n table: opts.table,\n column: opts.column,\n applied,\n total,\n bytesBefore: original.length,\n bytesAfter: content.length,\n results,\n },\n opts.format,\n );\n\n for (const stmt of scoping.teardown) {\n await client.execute(stmt).catch(() => {});\n }\n } finally {\n client.close();\n }\n}\n\n// ─── Entry point ────────────────────────────────────────────────────────────\n\nexport default async function dbPatch(args: string[]): Promise<void> {\n const parsed = parseArgs(args);\n\n if (parsed.help === \"true\") {\n console.log(`Usage: pnpm action db-patch --table <t> --column <c> --where \"<clause>\" [edit flags]\n\nSurgical search-and-replace on a text column. Avoids re-sending the full\ncolumn value — ideal for large strings (documents, slides, dashboards, JSON).\n\nRequired:\n --table <name> Target table (identifier; no quoting)\n --column <name> Target text column (identifier; no quoting)\n --where \"<clause>\" SQL WHERE clause that matches exactly one row\n\nEdit mode (pick one):\n --find <text> Text to find (single edit; default replace = \"\")\n --replace <text> Replacement text (used with --find)\n --edits <json> Batch: JSON array of {find, replace} objects\n --json-ops <json> Structural JSON edits on a JSON column — array of ops:\n { op: \"set\", path, value } → set/replace at path\n { op: \"remove\", path } → delete at path\n { op: \"insert\", path, value } → insert into array\n { op: \"move\", from, path } → move node\n { op: \"move-before\", from, path } → move, stable indexing\n Paths use JSON Pointer (\"/panels/3/title\").\n Much safer than string patches for JSON columns\n (dashboards, forms, slide decks).\n\nOptions:\n --all Replace every occurrence of each 'find' (default: first only)\n --format json Output as JSON\n --help Show this help\n\nExamples:\n # Fix a typo in one document\n pnpm action db-patch --table documents --column content \\\\\n --where \"id='abc'\" --find \"teh\" --replace \"the\"\n\n # Batch edits on a deck's JSON blob\n pnpm action db-patch --table decks --column data --where \"id='d1'\" \\\\\n --edits '[{\"find\":\"\\\\\"Q3\\\\\"\",\"replace\":\"\\\\\"Q4\\\\\"\"},{\"find\":\"$1M\",\"replace\":\"$1.2M\"}]'\n\nWhen to use db-patch vs other tools:\n Large text field, small edit → db-patch (this)\n Short field or multi-column set → db-exec UPDATE\n Domain action exists (edit-document, ...) → use that action (syncs live\n to open collaborative editors)\n`);\n return;\n }\n\n const table = parsed.table;\n const column = parsed.column;\n const where = parsed.where;\n\n if (!table) fail(\"--table is required\");\n if (!column) fail(\"--column is required\");\n if (!where) fail(\"--where is required\");\n if (!isValidIdentifier(table))\n fail(\n `Invalid --table: \"${table}\". Must be a plain identifier (letters, digits, underscore).`,\n );\n if (!isValidIdentifier(column))\n fail(\n `Invalid --column: \"${column}\". Must be a plain identifier (letters, digits, underscore).`,\n );\n assertNoSensitiveFrameworkTables(table, \"patch\");\n assertNoSensitiveFrameworkTables(where, \"read\");\n validateWhere(where);\n\n const jsonOps = parseJsonOps(parsed);\n // Edit parsing only runs when json-ops isn't provided — otherwise the\n // find/replace args are irrelevant and would error if missing.\n const edits = jsonOps ? [] : parseEdits(parsed);\n const replaceAll = parsed.all === \"true\";\n\n // Resolve database URL: --db flag → DATABASE_URL env → default file path\n let url: string;\n if (parsed.db) {\n url = \"file:\" + path.resolve(parsed.db);\n } else if (getDatabaseUrl()) {\n url = getDatabaseUrl();\n } else {\n url = \"file:\" + path.resolve(process.cwd(), \"data\", \"app.db\");\n }\n\n if (isPostgresUrl(url)) {\n await runPostgres({\n url,\n table,\n column,\n where,\n edits,\n jsonOps: jsonOps ?? undefined,\n replaceAll,\n format: parsed.format,\n });\n } else {\n await runSqlite({\n url,\n table,\n column,\n where,\n edits,\n jsonOps: jsonOps ?? undefined,\n replaceAll,\n format: parsed.format,\n });\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../src/scripts/db/query.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAyJH,wBAA8B,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAyInE"}
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../src/scripts/db/query.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAyJH,wBAA8B,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsInE"}
@@ -12,11 +12,11 @@
12
12
  * pnpm action db-query --sql "SELECT * FROM forms WHERE id = ?" [--args '["abc"]'] [--db path] [--format json] [--limit N]
13
13
  */
14
14
  import path from "path";
15
- import { createClient } from "@libsql/client";
16
- import { getDatabaseUrl, getDatabaseAuthToken } from "../../db/client.js";
15
+ import { getDatabaseUrl } from "../../db/client.js";
17
16
  import { parseArgs, fail } from "../utils.js";
18
17
  import { assertNoSensitiveFrameworkTables } from "./safety.js";
19
18
  import { buildScopingPostgres, buildScopingSqlite } from "./scoping.js";
19
+ import { createSqliteScriptClient } from "./sqlite-client.js";
20
20
  function isPostgresUrl(url) {
21
21
  return url.startsWith("postgres://") || url.startsWith("postgresql://");
22
22
  }
@@ -232,10 +232,7 @@ Options:
232
232
  return;
233
233
  }
234
234
  // libsql / SQLite path
235
- const client = createClient({
236
- url,
237
- authToken: getDatabaseAuthToken(),
238
- });
235
+ const client = await createSqliteScriptClient(url);
239
236
  try {
240
237
  // Set up user-scoped temp views in production
241
238
  const scoping = await buildScopingSqlite(client);