From d19ed6cec3076e23d472454ee2dbb0d68bb09dbb Mon Sep 17 00:00:00 2001 From: Patrick Taylor <1963845+pstaylor-patrick@users.noreply.github.com> Date: Mon, 9 Feb 2026 08:08:38 -0600 Subject: [PATCH 1/2] Add support for single-quoted multiline values in env loader --- scripts/firebase-env.sh | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/scripts/firebase-env.sh b/scripts/firebase-env.sh index 50ad885..51afca0 100644 --- a/scripts/firebase-env.sh +++ b/scripts/firebase-env.sh @@ -192,6 +192,16 @@ load_environment_variables() { current_value="$value_part" in_multiline=true fi + elif [[ "$value_part" =~ ^\' ]]; then + value_part="${value_part#\'}" + + if [[ "$value_part" =~ \'$ ]]; then + current_value="${value_part%\'}" + export "$current_var=$current_value" + else + current_value="$value_part" + in_multiline=true + fi else export "$current_var=$value_part" fi @@ -202,6 +212,11 @@ load_environment_variables() { ${line%\"}" export "$current_var=$current_value" in_multiline=false + elif [[ "$line" =~ \'$ ]]; then + current_value="$current_value +${line%\'}" + export "$current_var=$current_value" + in_multiline=false else current_value="$current_value $line" From 4c5b16d511ba1d92ef2908a871454a8fba441a1d Mon Sep 17 00:00:00 2001 From: Patrick Taylor <1963845+pstaylor-patrick@users.noreply.github.com> Date: Mon, 9 Feb 2026 08:11:52 -0600 Subject: [PATCH 2/2] Remove unused writeFileSync import and schema generation code --- scripts/db-pull-dump.ts | 131 +--------------------------------------- 1 file changed, 1 insertion(+), 130 deletions(-) diff --git a/scripts/db-pull-dump.ts b/scripts/db-pull-dump.ts index 8330645..218528f 100644 --- a/scripts/db-pull-dump.ts +++ b/scripts/db-pull-dump.ts @@ -1,5 +1,5 @@ import { Pool } from "pg"; -import { writeFileSync, mkdirSync, createWriteStream } from "fs"; +import { mkdirSync, createWriteStream } from "fs"; import { resolve } from "path"; import { config } from "dotenv"; @@ -30,135 +30,6 @@ async function main() { } } -async function generateSchemaSql(pool: Pool): Promise { - const schemas = await pool.query(` - SELECT schema_name FROM information_schema.schemata - WHERE schema_name NOT IN ('information_schema', 'pg_catalog', 'pg_toast', 'drizzle', 'auth', 'temp') - ORDER BY schema_name - `); - - const lines: string[] = [ - "-- Schema dump from GCP", - `-- Generated at ${new Date().toISOString()}`, - "", - ]; - - for (const s of schemas.rows) { - if (s.schema_name !== "public") { - lines.push(`CREATE SCHEMA IF NOT EXISTS ${s.schema_name};`); - } - } - lines.push(""); - - const tables = await pool.query(` - SELECT table_schema, table_name - FROM information_schema.tables - WHERE table_schema NOT IN ('information_schema', 'pg_catalog', 'pg_toast', 'drizzle', 'auth', 'temp') - AND table_type = 'BASE TABLE' - ORDER BY table_schema, table_name - `); - - for (const table of tables.rows) { - const fullName = `"${table.table_schema}"."${table.table_name}"`; - const cols = await pool.query( - ` - SELECT column_name, data_type, udt_name, is_nullable, column_default, - character_maximum_length, numeric_precision, numeric_scale, - is_identity, identity_generation - FROM information_schema.columns - WHERE table_schema = $1 AND table_name = $2 - ORDER BY ordinal_position - `, - [table.table_schema, table.table_name], - ); - - lines.push(`CREATE TABLE IF NOT EXISTS ${fullName} (`); - const colDefs: string[] = []; - for (const col of cols.rows) { - const typeName = getColumnType(col); - let def = ` "${col.column_name}" ${typeName}`; - if (col.column_default && col.is_identity !== "YES") { - def += ` DEFAULT ${col.column_default}`; - } - if (col.is_identity === "YES") { - def += ` GENERATED ${col.identity_generation === "ALWAYS" ? "ALWAYS" : "BY DEFAULT"} AS IDENTITY`; - } - if (col.is_nullable === "NO") { - def += " NOT NULL"; - } - colDefs.push(def); - } - - const pk = await pool.query( - ` - SELECT kcu.column_name - FROM information_schema.table_constraints tc - JOIN information_schema.key_column_usage kcu - ON tc.constraint_name = kcu.constraint_name - AND tc.table_schema = kcu.table_schema - WHERE tc.table_schema = $1 AND tc.table_name = $2 - AND tc.constraint_type = 'PRIMARY KEY' - ORDER BY kcu.ordinal_position - `, - [table.table_schema, table.table_name], - ); - - if (pk.rows.length > 0) { - const pkCols = pk.rows.map((r) => `"${r.column_name}"`).join(", "); - colDefs.push(` PRIMARY KEY (${pkCols})`); - } - - lines.push(colDefs.join(",\n")); - lines.push(");"); - lines.push(""); - } - - const indexes = await pool.query(` - SELECT schemaname, tablename, indexname, indexdef - FROM pg_indexes - WHERE schemaname NOT IN ('information_schema', 'pg_catalog', 'pg_toast', 'drizzle', 'auth', 'temp') - AND indexdef NOT LIKE '%PRIMARY%' - AND indexname NOT LIKE '%_pkey' - ORDER BY schemaname, tablename, indexname - `); - - if (indexes.rows.length > 0) { - lines.push("-- Indexes"); - for (const idx of indexes.rows) { - lines.push(`${idx.indexdef};`); - } - lines.push(""); - } - - return lines.join("\n"); -} - -function getColumnType(col: Record): string { - const udtName = col.udt_name as string; - const dataType = col.data_type as string; - const maxLen = col.character_maximum_length as number | null; - const numPrecision = col.numeric_precision as number | null; - const numScale = col.numeric_scale as number | null; - - switch (dataType) { - case "character varying": - return maxLen ? `VARCHAR(${maxLen})` : "VARCHAR"; - case "character": - return maxLen ? `CHAR(${maxLen})` : "CHAR"; - case "numeric": - if (numPrecision && numScale) - return `NUMERIC(${numPrecision}, ${numScale})`; - if (numPrecision) return `NUMERIC(${numPrecision})`; - return "NUMERIC"; - case "ARRAY": - return `${udtName.replace(/^_/, "")}[]`; - case "USER-DEFINED": - return udtName; - default: - return dataType; - } -} - // Escape a value for COPY tab-delimited format function escapeCopyValue(val: unknown): string { if (val === null || val === undefined) return "\\N";