UNPKG

everything-dev

Version:

A consolidated product package for building Module Federation apps with oRPC APIs.

1 lines • 11.5 kB
{"version":3,"file":"core.mjs","names":[],"sources":["../../src/db/core.ts"],"sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\nexport interface MigrationStorage {\n schema: string;\n table: string;\n slug: string;\n}\n\nconst DEFAULT_MIGRATION_JOURNAL = {\n schema: \"drizzle\",\n table: \"__drizzle_migrations\",\n} as const;\n\nconst PER_PLUGIN_ISOLATION = false;\n\nexport function normalizeSlug(name: string): string {\n const basename = name.split(\"/\").pop() ?? name;\n return basename\n .replace(/^@/, \"\")\n .replace(/[^a-zA-Z0-9_-]/g, \"_\")\n .replace(/-plugin$/i, \"\")\n .replace(/-/g, \"_\")\n .toLowerCase();\n}\n\nexport function getMigrationSlug(dir?: string): string {\n if (!dir) return normalizeSlug(process.env.npm_package_name ?? \"unknown\");\n let current = dir;\n for (let i = 0; i < 10; i++) {\n const pkgPath = join(current, \"package.json\");\n if (existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\")) as { name?: string };\n return normalizeSlug(pkg.name ?? current);\n } catch {\n return normalizeSlug(current);\n }\n }\n const parent = dirname(current);\n if (parent === current) break;\n current = parent;\n }\n return normalizeSlug(dir);\n}\n\nexport function getMigrationStorage(\n slug?: string,\n options?: { isolated?: boolean },\n): MigrationStorage {\n const s = normalizeSlug(slug ?? getMigrationSlug());\n const isolated = options?.isolated ?? PER_PLUGIN_ISOLATION;\n if (isolated) {\n return {\n schema: DEFAULT_MIGRATION_JOURNAL.schema,\n table: `__drizzle_migrations_${s}`,\n slug: s,\n };\n }\n return {\n schema: DEFAULT_MIGRATION_JOURNAL.schema,\n table: DEFAULT_MIGRATION_JOURNAL.table,\n slug: s,\n };\n}\n\n/**\n * Format a JavaScript string array as a PostgreSQL text array literal for use\n * with Drizzle's `sql` tag. Example return:\n * `'{\"h1\",\"h2\"}'::text[]`\n *\n * Usage: sql`WHERE col = ANY(${toSqlArray(values)})`\n *\n * Drizzle's default parameter binding does not handle array types correctly\n * with the pg driver (it emits `ANY(($1))` with a single string, which\n * Postgres rejects as a malformed array literal).\n */\nexport function toSqlArray(arr: string[]): string {\n if (arr.length === 0) return `'{}'::text[]`;\n const escaped = arr.map((v) => v.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"'));\n return `'{${escaped.map((v) => `\"${v}\"`).join(\",\")}}'::text[]`;\n}\n\nexport function pluginMigrationSlug(key: string): string {\n return normalizeSlug(key);\n}\n\nexport function getDatabaseUrlSecretName(slug: string): string {\n return `${slug.toUpperCase().replace(/-/g, \"_\")}_DATABASE_URL`;\n}\n\nexport const DUPLICATE_OBJECT_SQLSTATES: readonly string[] = [\"42710\", \"42701\", \"42P07\"];\n\n/**\n * Walk `error` and its `cause` chain (bounded), invoking `visit` on each link.\n * Postgres driver errors arrive wrapped by drizzle/Effect at varying depths,\n * so every error-shape predicate below shares this traversal.\n */\nexport function visitCauses(\n error: unknown,\n depth: number,\n visit: (link: object) => boolean,\n): boolean {\n let current: unknown = error;\n for (let i = 0; i < depth && current; i++) {\n if (typeof current === \"object\" && current !== null && visit(current)) return true;\n current = (current as { cause?: unknown })?.cause;\n }\n return false;\n}\n\n/**\n * pg_catalog unique indexes that can surface a concurrent-DDL race as SQLSTATE\n * 23505 instead of a duplicate-object class. When two connections run\n * `CREATE TABLE <name>` at the same time, the loser fails its insert into\n * `pg_type` (\"duplicate key value violates unique constraint\n * `pg_type_typname_nsp_index`\") rather than seeing 42P07, because the winner's\n * table is not yet committed. The same shape exists for schemas and other\n * relations.\n */\nconst CONCURRENT_DDL_CONSTRAINTS: ReadonlySet<string> = new Set([\n \"pg_type_typname_nsp_index\",\n \"pg_namespace_nspname_index\",\n \"pg_class_relname_nsp_index\",\n]);\n\n/**\n * Whether a SQLSTATE 23505 unique violation is the concurrent-DDL catalog\n * collision signature rather than a data-level constraint on a user table.\n * Data-level violations must keep failing loudly; only the pg_catalog indexes\n * above are treated as duplicate-DDL tolerance candidates.\n */\nexport function isConcurrentDdlUniqueViolation(error: unknown): boolean {\n return visitCauses(error, 6, (link) => {\n const { code, constraint, message } = link as {\n code?: unknown;\n constraint?: unknown;\n message?: unknown;\n };\n if (code !== \"23505\") return false;\n if (typeof constraint === \"string\" && CONCURRENT_DDL_CONSTRAINTS.has(constraint)) return true;\n if (typeof message !== \"string\") return false;\n for (const name of CONCURRENT_DDL_CONSTRAINTS) {\n if (message.includes(name)) return true;\n }\n return false;\n });\n}\n\nconst RETRYABLE_SQLSTATES: ReadonlySet<string> = new Set([\n \"42P06\",\n \"42710\",\n \"42701\",\n \"42P07\",\n \"23505\",\n \"40001\",\n \"40P01\",\n \"55P03\",\n]);\n\nconst RETRYABLE_DRIVER_CODES: ReadonlySet<string> = new Set([\n \"ECONNREFUSED\",\n \"ECONNRESET\",\n \"EPIPE\",\n \"ETIMEDOUT\",\n \"ENOTFOUND\",\n \"EAI_AGAIN\",\n]);\n\nfunction matchesRetryableStates(error: unknown, states: ReadonlySet<string>): boolean {\n return visitCauses(error, 6, (link) => {\n const code = (link as { code?: unknown }).code;\n if (typeof code !== \"string\") return false;\n return states.has(code) || code.startsWith(\"08\") || RETRYABLE_DRIVER_CODES.has(code);\n });\n}\n\n/**\n * Decide whether a failed migration-init statement (schema/journal creation)\n * is worth retrying. Covers the concurrent `CREATE SCHEMA IF NOT EXISTS`\n * race (unique violation on `pg_namespace`, duplicate-object errors),\n * serialization/deadlock errors, and transient connection failures.\n */\nexport function isRetryableMigrationError(error: unknown): boolean {\n return matchesRetryableStates(error, RETRYABLE_SQLSTATES);\n}\n\nconst RETRYABLE_STATEMENT_SQLSTATES: ReadonlySet<string> = new Set([\n \"40001\", // serialization_failure\n \"40P01\", // deadlock_detected\n \"55P03\", // lock_not_available\n]);\n\n/**\n * Decide whether a failed migration *statement* (inside its transaction) is\n * worth retrying. Deliberately narrower than `isRetryableMigrationError`:\n * duplicate-object classes are tolerated at the SAVEPOINT level, and a 23505\n * is either the concurrent-DDL catalog collision (also tolerated) or a\n * deterministic data-level violation (retrying is pointless) — so only\n * lock/serialization/transient-connection states justify re-running the\n * transaction.\n */\nexport function isRetryableMigrationExecutionError(error: unknown): boolean {\n return matchesRetryableStates(error, RETRYABLE_STATEMENT_SQLSTATES);\n}\n\nconst PG_QUERY_QUEUE_DEPRECATION = \"client.query() when the client is already executing a query\";\n\nlet pgWarningFilterInstalled = false;\n\n/**\n * Silence pg's query-queue deprecation warning (fires once per process from\n * pg-pool's internal dispatch under concurrent boot load — node-postgres#3612,\n * #3617). Node's default warning handler prints even when user listeners are\n * attached, so it is removed first; every other warning is re-printed here.\n */\nexport function suppressPgQueryQueueDeprecation(): void {\n if (pgWarningFilterInstalled) return;\n if (typeof process === \"undefined\" || typeof process.on !== \"function\") return;\n pgWarningFilterInstalled = true;\n process.removeAllListeners(\"warning\");\n process.on(\"warning\", (warning) => {\n if (\n warning.name === \"DeprecationWarning\" &&\n warning.message.includes(PG_QUERY_QUEUE_DEPRECATION)\n ) {\n return;\n }\n console.error(warning.stack || `${warning.name}: ${warning.message}`);\n });\n}\n\nexport function extractExpectedTables(migrations: { sql: string[] }[]): string[] {\n const tables = new Set<string>();\n const re = /CREATE\\s+TABLE\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(?:\"([^\"]+)\"\\.)?\"([^\"]+)\"/gi;\n for (const migration of migrations) {\n for (const stmt of migration.sql) {\n for (const match of stmt.matchAll(re)) {\n const tableName = match[2];\n if (tableName) {\n tables.add(tableName);\n }\n }\n }\n }\n return [...tables];\n}\n"],"mappings":"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"}