easy-ping 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +174 -82
- package/dist/adapter-B7R4rXtJ.d.cts +17 -0
- package/dist/adapter-B7R4rXtJ.d.ts +17 -0
- package/dist/{adapter-BfLe2J0t.d.cts → adapter-D3lTy-4E.d.cts} +6 -32
- package/dist/{adapter-BfLe2J0t.d.ts → adapter-D3lTy-4E.d.ts} +6 -32
- package/dist/adapters/drizzle.cjs +4 -4
- package/dist/adapters/drizzle.cjs.map +1 -1
- package/dist/adapters/drizzle.d.cts +35 -1
- package/dist/adapters/drizzle.d.ts +35 -1
- package/dist/adapters/drizzle.js +5 -5
- package/dist/adapters/drizzle.js.map +1 -1
- package/dist/adapters/mongodb.cjs +8 -7
- package/dist/adapters/mongodb.cjs.map +1 -1
- package/dist/adapters/mongodb.d.cts +4 -17
- package/dist/adapters/mongodb.d.ts +4 -17
- package/dist/adapters/mongodb.js +7 -7
- package/dist/adapters/mongodb.js.map +1 -1
- package/dist/adapters/mysql.cjs +605 -0
- package/dist/adapters/mysql.cjs.map +1 -0
- package/dist/adapters/mysql.d.cts +38 -0
- package/dist/adapters/mysql.d.ts +38 -0
- package/dist/adapters/mysql.js +51 -0
- package/dist/adapters/mysql.js.map +1 -0
- package/dist/adapters/postgres.cjs +19 -11
- package/dist/adapters/postgres.cjs.map +1 -1
- package/dist/adapters/postgres.d.cts +9 -54
- package/dist/adapters/postgres.d.ts +9 -54
- package/dist/adapters/postgres.js +6 -41
- package/dist/adapters/postgres.js.map +1 -1
- package/dist/adapters/sqlite.cjs +593 -0
- package/dist/adapters/sqlite.cjs.map +1 -0
- package/dist/adapters/sqlite.d.cts +37 -0
- package/dist/adapters/sqlite.d.ts +37 -0
- package/dist/adapters/sqlite.js +53 -0
- package/dist/adapters/sqlite.js.map +1 -0
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +2 -14
- package/dist/browser.d.ts +2 -14
- package/dist/browser.js.map +1 -1
- package/dist/chunk-2EYKPF5A.js +393 -0
- package/dist/chunk-2EYKPF5A.js.map +1 -0
- package/dist/{chunk-OZSOIX23.js → chunk-3VOQOGDR.js} +54 -12
- package/dist/chunk-3VOQOGDR.js.map +1 -0
- package/dist/{chunk-NYDVNMKG.js → chunk-AEYYTE5I.js} +4 -3
- package/dist/chunk-AEYYTE5I.js.map +1 -0
- package/dist/chunk-BECMTNK7.js +315 -0
- package/dist/chunk-BECMTNK7.js.map +1 -0
- package/dist/chunk-CK5UPVYP.js +48 -0
- package/dist/chunk-CK5UPVYP.js.map +1 -0
- package/dist/{chunk-BV3U542P.js → chunk-E4IZ2CQC.js} +2 -2
- package/dist/chunk-E4IZ2CQC.js.map +1 -0
- package/dist/chunk-GJNLOQJS.js +226 -0
- package/dist/chunk-GJNLOQJS.js.map +1 -0
- package/dist/chunk-HY47TQMY.js +52 -0
- package/dist/chunk-HY47TQMY.js.map +1 -0
- package/dist/chunk-M4R77BJD.js +64 -0
- package/dist/chunk-M4R77BJD.js.map +1 -0
- package/dist/{chunk-RBDW4S6F.js → chunk-XIDVLYNQ.js} +14 -4
- package/dist/chunk-XIDVLYNQ.js.map +1 -0
- package/dist/client.cjs.map +1 -1
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +362 -64
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +56 -37
- package/dist/index.d.ts +56 -37
- package/dist/index.js +120 -359
- package/dist/index.js.map +1 -1
- package/dist/node.cjs +27 -6
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +8 -2
- package/dist/node.d.ts +8 -2
- package/dist/node.js +26 -6
- package/dist/node.js.map +1 -1
- package/dist/{plugin-CmPOFVmn.d.ts → plugin-CHd2ZiGC.d.cts} +37 -25
- package/dist/{plugin-f5KaFWSN.d.cts → plugin-Cg9usuUi.d.ts} +37 -25
- package/dist/plugins/digests.cjs +1 -4
- package/dist/plugins/digests.cjs.map +1 -1
- package/dist/plugins/digests.d.cts +6 -31
- package/dist/plugins/digests.d.ts +6 -31
- package/dist/plugins/digests.js +1 -4
- package/dist/plugins/digests.js.map +1 -1
- package/dist/plugins/preferences-client.cjs.map +1 -1
- package/dist/plugins/preferences-client.d.cts +2 -2
- package/dist/plugins/preferences-client.d.ts +2 -2
- package/dist/plugins/preferences-client.js +1 -1
- package/dist/plugins/preferences-react.cjs.map +1 -1
- package/dist/plugins/preferences-react.js.map +1 -1
- package/dist/plugins/preferences.cjs +101 -17
- package/dist/plugins/preferences.cjs.map +1 -1
- package/dist/plugins/preferences.d.cts +4 -2
- package/dist/plugins/preferences.d.ts +4 -2
- package/dist/plugins/preferences.js +36 -9
- package/dist/plugins/preferences.js.map +1 -1
- package/dist/plugins/push.cjs +198 -40
- package/dist/plugins/push.cjs.map +1 -1
- package/dist/plugins/push.d.cts +20 -18
- package/dist/plugins/push.d.ts +20 -18
- package/dist/plugins/push.js +141 -41
- package/dist/plugins/push.js.map +1 -1
- package/dist/providers/web-push.cjs +37 -11
- package/dist/providers/web-push.cjs.map +1 -1
- package/dist/providers/web-push.d.cts +10 -11
- package/dist/providers/web-push.d.ts +10 -11
- package/dist/providers/web-push.js +37 -12
- package/dist/providers/web-push.js.map +1 -1
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -4
- package/dist/react.d.ts +1 -4
- package/dist/react.js.map +1 -1
- package/dist/schema.cjs +121 -2
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +25 -14
- package/dist/schema.d.ts +25 -14
- package/dist/schema.js +4 -2
- package/dist/testing.cjs +3 -19
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +4 -22
- package/dist/testing.d.ts +4 -22
- package/dist/testing.js +3 -19
- package/dist/testing.js.map +1 -1
- package/package.json +12 -1
- package/dist/chunk-BV3U542P.js.map +0 -1
- package/dist/chunk-NYDVNMKG.js.map +0 -1
- package/dist/chunk-OZSOIX23.js.map +0 -1
- package/dist/chunk-RBDW4S6F.js.map +0 -1
- package/dist/chunk-W3BMEPPQ.js +0 -50
- package/dist/chunk-W3BMEPPQ.js.map +0 -1
package/dist/schema.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/schema/declaration.ts","../src/schema/render-sql.ts","../src/schema/migrate-sql.ts","../src/schema/render-drizzle.ts"],"names":["indexName","columns","SQL_TYPE","quote","defaultClause"],"mappings":"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","file":"schema.cjs","sourcesContent":["import type { SchemaDeclaration } from \"../core/plugin\";\n\nexport const toSnakeCase = (value: string) => value.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);\n\n/**\n * Core tables in the format plugins use. Less expressive than the hand-written\n * Drizzle schema (no partial indexes, ordering or cascade) — a drift test\n * asserts the two agree on the fields they share.\n */\nexport const coreSchema = {\n notification: {\n tableName: \"notification\",\n fields: {\n id: { type: \"string\", required: true },\n userId: { type: \"string\", required: true },\n type: { type: \"string\", required: true },\n payload: { type: \"json\", required: true },\n actorId: { type: \"string\" },\n groupKey: { type: \"string\" },\n dedupeKey: { type: \"string\" },\n seenAt: { type: \"date\" },\n readAt: { type: \"date\" },\n archivedAt: { type: \"date\" },\n createdAt: { type: \"date\", required: true, defaultNow: true },\n },\n primaryKey: [\"id\"],\n indexes: [\n { on: [\"userId\", \"createdAt\"], name: \"notification_feed_idx\" },\n { on: [\"userId\", \"groupKey\"], name: \"notification_group_idx\" },\n { on: [\"userId\", \"dedupeKey\"], unique: true, name: \"notification_dedupe_idx\" },\n ],\n },\n\n notificationDelivery: {\n tableName: \"notification_delivery\",\n fields: {\n id: { type: \"string\", required: true },\n notificationId: { type: \"string\", required: true },\n channel: { type: \"string\", required: true },\n status: { type: \"string\", required: true, default: \"pending\" },\n attempts: { type: \"number\", required: true, default: 0 },\n maxAttempts: { type: \"number\", required: true, default: 5 },\n notBefore: { type: \"date\", required: true, defaultNow: true },\n claimedAt: { type: \"date\" },\n claimedBy: { type: \"string\" },\n lastError: { type: \"string\" },\n updatedAt: { type: \"date\", required: true, defaultNow: true },\n },\n primaryKey: [\"id\"],\n indexes: [\n { on: [\"status\", \"notBefore\"], name: \"delivery_claim_idx\" },\n { on: [\"notificationId\"], name: \"delivery_notification_idx\" },\n ],\n },\n\n notificationPreference: {\n tableName: \"notification_preference\",\n fields: {\n userId: { type: \"string\", required: true },\n type: { type: \"string\", required: true },\n channel: { type: \"string\", required: true },\n enabled: { type: \"boolean\", required: true, default: true },\n frequency: { type: \"string\", required: true, default: \"instant\" },\n },\n primaryKey: [\"userId\", \"type\", \"channel\"],\n },\n} satisfies SchemaDeclaration;\n","import type { FieldDeclaration, SchemaDeclaration } from \"../core/plugin\";\nimport { toSnakeCase } from \"./declaration\";\n\nconst SQL_TYPE: Record<FieldDeclaration[\"type\"], string> = {\n string: \"text\",\n number: \"integer\",\n boolean: \"boolean\",\n date: \"timestamptz\",\n json: \"jsonb\",\n};\n\nconst quote = (value: string) => `\"${value.replace(/\"/g, '\"\"')}\"`;\n\nconst defaultClause = (field: FieldDeclaration): string => {\n if (field.defaultNow) return \" DEFAULT now()\";\n if (field.default === undefined) return \"\";\n if (typeof field.default === \"string\") return ` DEFAULT '${field.default.replace(/'/g, \"''\")}'`;\n return ` DEFAULT ${field.default}`;\n};\n\n/** SchemaDeclaration to Postgres DDL, from the same source as the Drizzle renderer. */\nexport function renderPostgresDdl(schema: SchemaDeclaration, prefix = \"\"): string[] {\n const statements: string[] = [];\n\n for (const table of Object.values(schema)) {\n const name = quote(prefix + table.tableName);\n\n const columns = Object.entries(table.fields).map(([field, spec]) => {\n const nullability = spec.required ? \" NOT NULL\" : \"\";\n return ` ${quote(toSnakeCase(field))} ${SQL_TYPE[spec.type]}${nullability}${defaultClause(spec)}`;\n });\n\n if (table.primaryKey?.length) {\n const key = table.primaryKey.map((field) => quote(toSnakeCase(field))).join(\", \");\n columns.push(` PRIMARY KEY (${key})`);\n }\n\n statements.push(`CREATE TABLE IF NOT EXISTS ${name} (\\n${columns.join(\",\\n\")}\\n)`);\n\n for (const declaration of table.indexes ?? []) {\n const indexName = quote(\n prefix + (declaration.name ?? `${table.tableName}_${declaration.on.join(\"_\")}_idx`),\n );\n const columns = declaration.on.map((field) => quote(toSnakeCase(field))).join(\", \");\n const unique = declaration.unique ? \"UNIQUE \" : \"\";\n statements.push(`CREATE ${unique}INDEX IF NOT EXISTS ${indexName} ON ${name} (${columns})`);\n }\n }\n\n return statements;\n}\n","import type { FieldDeclaration, SchemaDeclaration, TableDeclaration } from \"../core/plugin\";\nimport { toSnakeCase } from \"./declaration\";\nimport { renderPostgresDdl } from \"./render-sql\";\n\n/**\n * Introspects a live Postgres schema and emits only what is missing.\n *\n * renderPostgresDdl emits CREATE TABLE IF NOT EXISTS, which is correct exactly\n * once. On an existing database it is a silent no-op, so an adopter who\n * bootstrapped with raw SQL had no way to pick up a column a later version\n * added — their app broke at runtime with \"column does not exist\" instead.\n *\n * Additive only, on purpose. Dropping a column or changing a type is\n * destructive and context-dependent, so those are reported in `unsupported`\n * rather than guessed at.\n */\n\nconst SQL_TYPE: Record<FieldDeclaration[\"type\"], string> = {\n string: \"text\",\n number: \"integer\",\n boolean: \"boolean\",\n date: \"timestamptz\",\n json: \"jsonb\",\n};\n\n/** What information_schema reports for each of our declared types. */\nconst LIVE_TYPE: Record<FieldDeclaration[\"type\"], readonly string[]> = {\n string: [\"text\", \"character varying\", \"character\"],\n number: [\"integer\", \"bigint\", \"smallint\"],\n boolean: [\"boolean\"],\n date: [\"timestamp with time zone\", \"timestamp without time zone\"],\n json: [\"jsonb\", \"json\"],\n};\n\nconst quote = (value: string) => `\"${value.replace(/\"/g, '\"\"')}\"`;\n\nconst defaultClause = (field: FieldDeclaration): string => {\n if (field.defaultNow) return \" DEFAULT now()\";\n if (field.default === undefined) return \"\";\n if (typeof field.default === \"string\") return ` DEFAULT '${field.default.replace(/'/g, \"''\")}'`;\n return ` DEFAULT ${field.default}`;\n};\n\nconst indexName = (\n table: TableDeclaration,\n declaration: { on: readonly string[]; name?: string },\n) => declaration.name ?? `${table.tableName}_${declaration.on.join(\"_\")}_idx`;\n\nexport type LiveColumn = { table: string; column: string; type: string; nullable: boolean };\n\nexport type MigrationPlan = {\n /** Run in order. Empty means the live schema already matches. */\n statements: readonly string[];\n /** Differences this cannot express safely. Read them; they need a human. */\n unsupported: readonly string[];\n /** Tables that do not exist yet — these get a full CREATE TABLE. */\n createdTables: readonly string[];\n};\n\n/**\n * Reads the live column list. Pass a function that runs the query — this\n * module stays driver-agnostic, as the rest of the schema tooling does.\n */\nexport type Introspector = () => Promise<readonly LiveColumn[]>;\n\n/** The query an Introspector should run. Exported so callers need not retype it. */\nexport const INTROSPECT_SQL = `\n SELECT table_name, column_name, data_type, is_nullable\n FROM information_schema.columns\n WHERE table_schema = current_schema()\n`;\n\nexport async function planPostgresMigration(\n introspect: Introspector,\n schema: SchemaDeclaration,\n prefix = \"\",\n): Promise<MigrationPlan> {\n const live = await introspect();\n\n const byTable = new Map<string, Map<string, LiveColumn>>();\n for (const column of live) {\n const columns = byTable.get(column.table) ?? new Map<string, LiveColumn>();\n columns.set(column.column, column);\n byTable.set(column.table, columns);\n }\n\n const statements: string[] = [];\n const unsupported: string[] = [];\n const createdTables: string[] = [];\n\n for (const table of Object.values(schema)) {\n const qualified = prefix + table.tableName;\n const existing = byTable.get(qualified);\n\n // Absent entirely: the ordinary bootstrap path still applies.\n if (!existing || existing.size === 0) {\n createdTables.push(qualified);\n statements.push(...renderPostgresDdl({ [table.tableName]: table }, prefix));\n continue;\n }\n\n for (const [field, spec] of Object.entries(table.fields)) {\n const column = toSnakeCase(field);\n const found = existing.get(column);\n\n if (!found) {\n // NOT NULL on a populated table fails without a default, so a required\n // column that cannot fill itself is added nullable and flagged.\n const canFill = spec.defaultNow || spec.default !== undefined;\n const nullability = spec.required && canFill ? \" NOT NULL\" : \"\";\n\n statements.push(\n `ALTER TABLE ${quote(qualified)} ADD COLUMN IF NOT EXISTS ` +\n `${quote(column)} ${SQL_TYPE[spec.type]}${nullability}${defaultClause(spec)}`,\n );\n\n if (spec.required && !canFill) {\n unsupported.push(\n `${qualified}.${column} is declared required but has no default; ` +\n \"it was added nullable. Backfill it, then ALTER ... SET NOT NULL yourself.\",\n );\n }\n continue;\n }\n\n if (!LIVE_TYPE[spec.type].includes(found.type)) {\n unsupported.push(\n `${qualified}.${column} is ${found.type} but ${spec.type} is declared ` +\n `(${SQL_TYPE[spec.type]}). Changing a column type can lose data — do it yourself.`,\n );\n }\n }\n\n // Indexes are cheap and idempotent, so they are re-issued unconditionally.\n for (const declaration of table.indexes ?? []) {\n const name = quote(prefix + indexName(table, declaration));\n const columns = declaration.on.map((field) => quote(toSnakeCase(field))).join(\", \");\n statements.push(\n `CREATE ${declaration.unique ? \"UNIQUE \" : \"\"}INDEX IF NOT EXISTS ${name} ` +\n `ON ${quote(qualified)} (${columns})`,\n );\n }\n\n for (const column of existing.keys()) {\n const declared = Object.keys(table.fields).some((field) => toSnakeCase(field) === column);\n if (!declared) {\n unsupported.push(\n `${qualified}.${column} exists but is not declared. Left alone — ` +\n \"drop it yourself if it is ours and no longer needed.\",\n );\n }\n }\n }\n\n return { statements, unsupported, createdTables };\n}\n","import type { FieldDeclaration, SchemaDeclaration, TableDeclaration } from \"../core/plugin\";\nimport { toSnakeCase } from \"./declaration\";\n\nconst COLUMN_BUILDER: Record<FieldDeclaration[\"type\"], string> = {\n string: \"text\",\n number: \"integer\",\n boolean: \"boolean\",\n date: \"timestamp\",\n json: \"jsonb\",\n};\n\nconst literal = (value: string | number | boolean) =>\n typeof value === \"string\" ? JSON.stringify(value) : String(value);\n\nfunction renderColumn(name: string, field: FieldDeclaration, isSinglePk: boolean): string {\n const builder = COLUMN_BUILDER[field.type];\n const column = toSnakeCase(name);\n\n let expression =\n field.type === \"date\"\n ? `${builder}(${JSON.stringify(column)}, { withTimezone: true })`\n : `${builder}(${JSON.stringify(column)})`;\n\n if (isSinglePk) return ` ${name}: ${expression}.primaryKey(),`;\n\n if (field.required) expression += \".notNull()\";\n if (field.defaultNow) expression += \".defaultNow()\";\n else if (field.default !== undefined) expression += `.default(${literal(field.default)})`;\n\n return ` ${name}: ${expression},`;\n}\n\nfunction renderTable(key: string, table: TableDeclaration, prefix: string): string {\n const compositePk = (table.primaryKey?.length ?? 0) > 1;\n const singlePk = !compositePk ? table.primaryKey?.[0] : undefined;\n\n const columns = Object.entries(table.fields)\n .map(([name, field]) => renderColumn(name, field, name === singlePk))\n .join(\"\\n\");\n\n const extras: string[] = [];\n\n for (const declaration of table.indexes ?? []) {\n const builder = declaration.unique ? \"uniqueIndex\" : \"index\";\n const name = declaration.name ?? `${table.tableName}_${declaration.on.join(\"_\")}_idx`;\n const columns = declaration.on.map((field) => `table.${field}`).join(\", \");\n extras.push(` ${builder}(${JSON.stringify(prefix + name)}).on(${columns}),`);\n }\n\n if (compositePk) {\n const columns = (table.primaryKey ?? []).map((field) => `table.${field}`).join(\", \");\n extras.push(` primaryKey({ columns: [${columns}] }),`);\n }\n\n const third = extras.length ? `,\\n (table) => [\\n${extras.join(\"\\n\")}\\n ]` : \"\";\n\n return `export const ${key} = pgTable(\\n ${JSON.stringify(prefix + table.tableName)},\\n {\\n${columns}\\n }${third},\\n);`;\n}\n\n/** Renders a SchemaDeclaration to Drizzle pg-core source. */\nexport function renderDrizzleSchema(schema: SchemaDeclaration, prefix = \"\"): string {\n const tables = Object.entries(schema);\n\n const used = new Set<string>([\"pgTable\"]);\n for (const [, table] of tables) {\n for (const field of Object.values(table.fields)) used.add(COLUMN_BUILDER[field.type]);\n for (const declaration of table.indexes ?? []) {\n used.add(declaration.unique ? \"uniqueIndex\" : \"index\");\n }\n if ((table.primaryKey?.length ?? 0) > 1) used.add(\"primaryKey\");\n }\n\n const imports = [...used].sort().join(\", \");\n const body = tables.map(([key, table]) => renderTable(key, table, prefix)).join(\"\\n\\n\");\n\n return `// Generated by easy-ping. Do not edit by hand.\\nimport { ${imports} } from \"drizzle-orm/pg-core\";\\n\\n${body}\\n`;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/schema/declaration.ts","../src/schema/render-sql.ts","../src/schema/migrate-sql.ts","../src/schema/render-drizzle.ts","../src/schema/render-mysql.ts","../src/schema/render-sqlite.ts"],"names":["indexName","columns","SQL_TYPE","quote","defaultClause"],"mappings":"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","file":"schema.cjs","sourcesContent":["import type { SchemaDeclaration } from \"../core/plugin\";\n\nexport const toSnakeCase = (value: string) => value.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);\n\n/** Core tables in the plugin format. A drift test asserts it agrees with the Drizzle schema. */\nexport const coreSchema = {\n notification: {\n tableName: \"notification\",\n fields: {\n id: { type: \"string\", required: true },\n userId: { type: \"string\", required: true },\n type: { type: \"string\", required: true },\n payload: { type: \"json\", required: true },\n actorId: { type: \"string\" },\n groupKey: { type: \"string\" },\n dedupeKey: { type: \"string\" },\n seenAt: { type: \"date\" },\n readAt: { type: \"date\" },\n archivedAt: { type: \"date\" },\n createdAt: { type: \"date\", required: true, defaultNow: true },\n },\n primaryKey: [\"id\"],\n indexes: [\n { on: [\"userId\", \"createdAt\"], name: \"notification_feed_idx\" },\n { on: [\"userId\", \"groupKey\"], name: \"notification_group_idx\" },\n { on: [\"userId\", \"dedupeKey\"], unique: true, name: \"notification_dedupe_idx\" },\n ],\n },\n\n notificationDelivery: {\n tableName: \"notification_delivery\",\n fields: {\n id: { type: \"string\", required: true },\n notificationId: { type: \"string\", required: true },\n channel: { type: \"string\", required: true },\n status: { type: \"string\", required: true, default: \"pending\" },\n attempts: { type: \"number\", required: true, default: 0 },\n maxAttempts: { type: \"number\", required: true, default: 5 },\n notBefore: { type: \"date\", required: true, defaultNow: true },\n claimedAt: { type: \"date\" },\n claimedBy: { type: \"string\" },\n lastError: { type: \"string\" },\n updatedAt: { type: \"date\", required: true, defaultNow: true },\n },\n primaryKey: [\"id\"],\n indexes: [\n { on: [\"status\", \"notBefore\"], name: \"delivery_claim_idx\" },\n { on: [\"notificationId\"], name: \"delivery_notification_idx\" },\n ],\n },\n\n notificationPreference: {\n tableName: \"notification_preference\",\n fields: {\n userId: { type: \"string\", required: true },\n type: { type: \"string\", required: true },\n channel: { type: \"string\", required: true },\n enabled: { type: \"boolean\", required: true, default: true },\n frequency: { type: \"string\", required: true, default: \"instant\" },\n updatedAt: { type: \"date\", required: true, defaultNow: true },\n },\n primaryKey: [\"userId\", \"type\", \"channel\"],\n },\n} satisfies SchemaDeclaration;\n","import type { FieldDeclaration, SchemaDeclaration } from \"../core/plugin\";\nimport { toSnakeCase } from \"./declaration\";\n\nconst SQL_TYPE: Record<FieldDeclaration[\"type\"], string> = {\n string: \"text\",\n number: \"integer\",\n boolean: \"boolean\",\n date: \"timestamptz\",\n json: \"jsonb\",\n};\n\nconst quote = (value: string) => `\"${value.replace(/\"/g, '\"\"')}\"`;\n\nconst defaultClause = (field: FieldDeclaration): string => {\n if (field.defaultNow) return \" DEFAULT now()\";\n if (field.default === undefined) return \"\";\n if (typeof field.default === \"string\") return ` DEFAULT '${field.default.replace(/'/g, \"''\")}'`;\n return ` DEFAULT ${field.default}`;\n};\n\n/** SchemaDeclaration to Postgres DDL, from the same source as the Drizzle renderer. */\nexport function renderPostgresDdl(schema: SchemaDeclaration, prefix = \"\"): string[] {\n const statements: string[] = [];\n\n for (const table of Object.values(schema)) {\n const name = quote(prefix + table.tableName);\n\n const columns = Object.entries(table.fields).map(([field, spec]) => {\n const nullability = spec.required ? \" NOT NULL\" : \"\";\n return ` ${quote(toSnakeCase(field))} ${SQL_TYPE[spec.type]}${nullability}${defaultClause(spec)}`;\n });\n\n if (table.primaryKey?.length) {\n const key = table.primaryKey.map((field) => quote(toSnakeCase(field))).join(\", \");\n columns.push(` PRIMARY KEY (${key})`);\n }\n\n statements.push(`CREATE TABLE IF NOT EXISTS ${name} (\\n${columns.join(\",\\n\")}\\n)`);\n\n for (const declaration of table.indexes ?? []) {\n const indexName = quote(\n prefix + (declaration.name ?? `${table.tableName}_${declaration.on.join(\"_\")}_idx`),\n );\n const columns = declaration.on.map((field) => quote(toSnakeCase(field))).join(\", \");\n const unique = declaration.unique ? \"UNIQUE \" : \"\";\n statements.push(`CREATE ${unique}INDEX IF NOT EXISTS ${indexName} ON ${name} (${columns})`);\n }\n }\n\n return statements;\n}\n","import type { FieldDeclaration, SchemaDeclaration, TableDeclaration } from \"../core/plugin\";\nimport { toSnakeCase } from \"./declaration\";\nimport { renderPostgresDdl } from \"./render-sql\";\n\n/** Introspects a live Postgres schema and emits only what is missing. Additive only: drops and type changes land in `unsupported`. */\n\nconst SQL_TYPE: Record<FieldDeclaration[\"type\"], string> = {\n string: \"text\",\n number: \"integer\",\n boolean: \"boolean\",\n date: \"timestamptz\",\n json: \"jsonb\",\n};\n\n/** What information_schema reports for each of our declared types. */\nconst LIVE_TYPE: Record<FieldDeclaration[\"type\"], readonly string[]> = {\n string: [\"text\", \"character varying\", \"character\"],\n number: [\"integer\", \"bigint\", \"smallint\"],\n boolean: [\"boolean\"],\n date: [\"timestamp with time zone\", \"timestamp without time zone\"],\n json: [\"jsonb\", \"json\"],\n};\n\nconst quote = (value: string) => `\"${value.replace(/\"/g, '\"\"')}\"`;\n\nconst defaultClause = (field: FieldDeclaration): string => {\n if (field.defaultNow) return \" DEFAULT now()\";\n if (field.default === undefined) return \"\";\n if (typeof field.default === \"string\") return ` DEFAULT '${field.default.replace(/'/g, \"''\")}'`;\n return ` DEFAULT ${field.default}`;\n};\n\nconst indexName = (\n table: TableDeclaration,\n declaration: { on: readonly string[]; name?: string },\n) => declaration.name ?? `${table.tableName}_${declaration.on.join(\"_\")}_idx`;\n\nexport type LiveColumn = { table: string; column: string; type: string; nullable: boolean };\n\n/** A row as INTROSPECT_SQL returns it; `LiveColumn` uses the short forms and both are accepted. */\nexport type LiveColumnRow =\n | LiveColumn\n | {\n table_name: string;\n column_name: string;\n data_type: string;\n is_nullable: string | boolean;\n };\n\n/** Accepts either shape, so raw rows and hand-mapped rows both work. */\nfunction normaliseColumn(row: LiveColumnRow): LiveColumn {\n if (\"table\" in row) return row;\n return {\n table: String(row.table_name),\n column: String(row.column_name),\n type: String(row.data_type),\n nullable: typeof row.is_nullable === \"boolean\" ? row.is_nullable : row.is_nullable === \"YES\",\n };\n}\n\nexport type MigrationPlan = {\n /** Run in order. Empty means the live schema already matches. */\n statements: readonly string[];\n /** Differences this cannot express safely. Read them; they need a human. */\n unsupported: readonly string[];\n /** Tables that do not exist yet — these get a full CREATE TABLE. */\n createdTables: readonly string[];\n};\n\n/** Reads the live column list; a function, so this module stays driver-agnostic. */\nexport type Introspector = () => Promise<readonly LiveColumnRow[]>;\n\n/** The query an Introspector should run; raw rows are accepted as they come back. */\nexport const INTROSPECT_SQL = `\n SELECT table_name, column_name, data_type, is_nullable\n FROM information_schema.columns\n WHERE table_schema = current_schema()\n`;\n\nexport async function planPostgresMigration(\n introspect: Introspector,\n schema: SchemaDeclaration,\n prefix = \"\",\n): Promise<MigrationPlan> {\n const live = await introspect();\n\n const byTable = new Map<string, Map<string, LiveColumn>>();\n for (const row of live) {\n const column = normaliseColumn(row);\n const columns = byTable.get(column.table) ?? new Map<string, LiveColumn>();\n columns.set(column.column, column);\n byTable.set(column.table, columns);\n }\n\n const statements: string[] = [];\n const unsupported: string[] = [];\n const createdTables: string[] = [];\n\n for (const table of Object.values(schema)) {\n const qualified = prefix + table.tableName;\n const existing = byTable.get(qualified);\n\n // Absent entirely: the ordinary bootstrap path still applies.\n if (!existing || existing.size === 0) {\n createdTables.push(qualified);\n statements.push(...renderPostgresDdl({ [table.tableName]: table }, prefix));\n continue;\n }\n\n for (const [field, spec] of Object.entries(table.fields)) {\n const column = toSnakeCase(field);\n const found = existing.get(column);\n\n if (!found) {\n // NOT NULL fails on a populated table without a default: added nullable and flagged.\n const canFill = spec.defaultNow || spec.default !== undefined;\n const nullability = spec.required && canFill ? \" NOT NULL\" : \"\";\n\n statements.push(\n `ALTER TABLE ${quote(qualified)} ADD COLUMN IF NOT EXISTS ` +\n `${quote(column)} ${SQL_TYPE[spec.type]}${nullability}${defaultClause(spec)}`,\n );\n\n if (spec.required && !canFill) {\n unsupported.push(\n `${qualified}.${column} is declared required but has no default; ` +\n \"it was added nullable. Backfill it, then ALTER ... SET NOT NULL yourself.\",\n );\n }\n continue;\n }\n\n if (!LIVE_TYPE[spec.type].includes(found.type)) {\n unsupported.push(\n `${qualified}.${column} is ${found.type} but ${spec.type} is declared ` +\n `(${SQL_TYPE[spec.type]}). Changing a column type can lose data — do it yourself.`,\n );\n }\n }\n\n // Indexes are cheap and idempotent, so they are re-issued unconditionally.\n for (const declaration of table.indexes ?? []) {\n const name = quote(prefix + indexName(table, declaration));\n const columns = declaration.on.map((field) => quote(toSnakeCase(field))).join(\", \");\n statements.push(\n `CREATE ${declaration.unique ? \"UNIQUE \" : \"\"}INDEX IF NOT EXISTS ${name} ` +\n `ON ${quote(qualified)} (${columns})`,\n );\n }\n\n for (const column of existing.keys()) {\n const declared = Object.keys(table.fields).some((field) => toSnakeCase(field) === column);\n if (!declared) {\n unsupported.push(\n `${qualified}.${column} exists but is not declared. Left alone — ` +\n \"drop it yourself if it is ours and no longer needed.\",\n );\n }\n }\n }\n\n return { statements, unsupported, createdTables };\n}\n","import type { FieldDeclaration, SchemaDeclaration, TableDeclaration } from \"../core/plugin\";\nimport { toSnakeCase } from \"./declaration\";\n\nconst COLUMN_BUILDER: Record<FieldDeclaration[\"type\"], string> = {\n string: \"text\",\n number: \"integer\",\n boolean: \"boolean\",\n date: \"timestamp\",\n json: \"jsonb\",\n};\n\nconst literal = (value: string | number | boolean) =>\n typeof value === \"string\" ? JSON.stringify(value) : String(value);\n\nfunction renderColumn(name: string, field: FieldDeclaration, isSinglePk: boolean): string {\n const builder = COLUMN_BUILDER[field.type];\n const column = toSnakeCase(name);\n\n let expression =\n field.type === \"date\"\n ? `${builder}(${JSON.stringify(column)}, { withTimezone: true })`\n : `${builder}(${JSON.stringify(column)})`;\n\n if (isSinglePk) return ` ${name}: ${expression}.primaryKey(),`;\n\n if (field.required) expression += \".notNull()\";\n if (field.defaultNow) expression += \".defaultNow()\";\n else if (field.default !== undefined) expression += `.default(${literal(field.default)})`;\n\n return ` ${name}: ${expression},`;\n}\n\nfunction renderTable(key: string, table: TableDeclaration, prefix: string): string {\n const compositePk = (table.primaryKey?.length ?? 0) > 1;\n const singlePk = !compositePk ? table.primaryKey?.[0] : undefined;\n\n const columns = Object.entries(table.fields)\n .map(([name, field]) => renderColumn(name, field, name === singlePk))\n .join(\"\\n\");\n\n const extras: string[] = [];\n\n for (const declaration of table.indexes ?? []) {\n const builder = declaration.unique ? \"uniqueIndex\" : \"index\";\n const name = declaration.name ?? `${table.tableName}_${declaration.on.join(\"_\")}_idx`;\n const columns = declaration.on.map((field) => `table.${field}`).join(\", \");\n extras.push(` ${builder}(${JSON.stringify(prefix + name)}).on(${columns}),`);\n }\n\n if (compositePk) {\n const columns = (table.primaryKey ?? []).map((field) => `table.${field}`).join(\", \");\n extras.push(` primaryKey({ columns: [${columns}] }),`);\n }\n\n const third = extras.length ? `,\\n (table) => [\\n${extras.join(\"\\n\")}\\n ]` : \"\";\n\n return `export const ${key} = pgTable(\\n ${JSON.stringify(prefix + table.tableName)},\\n {\\n${columns}\\n }${third},\\n);`;\n}\n\n/** Renders a SchemaDeclaration to Drizzle pg-core source. */\nexport function renderDrizzleSchema(schema: SchemaDeclaration, prefix = \"\"): string {\n const tables = Object.entries(schema);\n\n const used = new Set<string>([\"pgTable\"]);\n for (const [, table] of tables) {\n for (const field of Object.values(table.fields)) used.add(COLUMN_BUILDER[field.type]);\n for (const declaration of table.indexes ?? []) {\n used.add(declaration.unique ? \"uniqueIndex\" : \"index\");\n }\n if ((table.primaryKey?.length ?? 0) > 1) used.add(\"primaryKey\");\n }\n\n const imports = [...used].sort().join(\", \");\n const body = tables.map(([key, table]) => renderTable(key, table, prefix)).join(\"\\n\\n\");\n\n return `// Generated by easy-ping. Do not edit by hand.\\nimport { ${imports} } from \"drizzle-orm/pg-core\";\\n\\n${body}\\n`;\n}\n","import type { FieldDeclaration, SchemaDeclaration, TableDeclaration } from \"../core/plugin\";\nimport { toSnakeCase } from \"./declaration\";\n\nconst quote = (value: string) => `\\`${value.split(\"`\").join(\"``\")}\\``;\n\n/** InnoDB caps a key at 3072 bytes: 768 utf8mb4 chars for one column, 255 each for three. TEXT cannot be a key or carry a default. */\nfunction stringType(field: string, table: TableDeclaration, spec: FieldDeclaration): string {\n const keys = [\n ...(table.primaryKey ? [table.primaryKey] : []),\n ...(table.indexes ?? []).map((index) => index.on),\n ].filter((columns) => columns.includes(field));\n\n if (keys.some((columns) => columns.length > 1)) return \"VARCHAR(255)\";\n if (keys.length > 0) return \"VARCHAR(768)\";\n if (spec.default !== undefined) return \"VARCHAR(255)\";\n return \"TEXT\";\n}\n\nfunction columnType(field: string, table: TableDeclaration, spec: FieldDeclaration): string {\n switch (spec.type) {\n case \"string\":\n return stringType(field, table, spec);\n case \"number\":\n return \"INT\";\n case \"boolean\":\n return \"TINYINT(1)\";\n case \"date\":\n return \"DATETIME(3)\";\n case \"json\":\n return \"JSON\";\n }\n}\n\nconst defaultClause = (spec: FieldDeclaration): string => {\n if (spec.defaultNow) return \" DEFAULT CURRENT_TIMESTAMP(3)\";\n if (spec.default === undefined) return \"\";\n if (typeof spec.default === \"string\") return ` DEFAULT '${spec.default.replace(/'/g, \"''\")}'`;\n if (typeof spec.default === \"boolean\") return ` DEFAULT ${spec.default ? 1 : 0}`;\n return ` DEFAULT ${spec.default}`;\n};\n\n/** MySQL DDL, one CREATE TABLE IF NOT EXISTS per table with indexes inline (no CREATE INDEX IF NOT EXISTS). */\nexport function renderMysqlDdl(schema: SchemaDeclaration, prefix = \"\"): string[] {\n const statements: string[] = [];\n\n for (const table of Object.values(schema)) {\n const lines = Object.entries(table.fields).map(([field, spec]) => {\n const nullability = spec.required ? \" NOT NULL\" : \"\";\n return ` ${quote(toSnakeCase(field))} ${columnType(field, table, spec)}${nullability}${defaultClause(spec)}`;\n });\n\n if (table.primaryKey?.length) {\n lines.push(\n ` PRIMARY KEY (${table.primaryKey.map((f) => quote(toSnakeCase(f))).join(\", \")})`,\n );\n }\n\n for (const index of table.indexes ?? []) {\n const name = quote(prefix + (index.name ?? `${table.tableName}_${index.on.join(\"_\")}_idx`));\n const columns = index.on.map((f) => quote(toSnakeCase(f))).join(\", \");\n lines.push(` ${index.unique ? \"UNIQUE \" : \"\"}INDEX ${name} (${columns})`);\n }\n\n statements.push(\n `CREATE TABLE IF NOT EXISTS ${quote(prefix + table.tableName)} (\\n${lines.join(\",\\n\")}\\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4`,\n );\n }\n\n return statements;\n}\n","import type { FieldDeclaration, SchemaDeclaration } from \"../core/plugin\";\nimport { toSnakeCase } from \"./declaration\";\n\nconst SQL_TYPE: Record<FieldDeclaration[\"type\"], string> = {\n string: \"TEXT\",\n number: \"INTEGER\",\n boolean: \"INTEGER\",\n // ISO-8601 with milliseconds and a trailing Z, the same 24 characters\n // `Date#toISOString` writes, so `<=` on the text is `<=` on the instant.\n date: \"TEXT\",\n json: \"TEXT\",\n};\n\nconst quote = (value: string) => `\"${value.split('\"').join('\"\"')}\"`;\n\nconst defaultClause = (spec: FieldDeclaration): string => {\n if (spec.defaultNow) return \" DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))\";\n if (spec.default === undefined) return \"\";\n if (typeof spec.default === \"string\") return ` DEFAULT '${spec.default.replace(/'/g, \"''\")}'`;\n if (typeof spec.default === \"boolean\") return ` DEFAULT ${spec.default ? 1 : 0}`;\n return ` DEFAULT ${spec.default}`;\n};\n\n/** SchemaDeclaration to SQLite DDL. Every statement is `IF NOT EXISTS`. */\nexport function renderSqliteDdl(schema: SchemaDeclaration, prefix = \"\"): string[] {\n const statements: string[] = [];\n\n for (const table of Object.values(schema)) {\n const name = quote(prefix + table.tableName);\n\n const columns = Object.entries(table.fields).map(([field, spec]) => {\n const nullability = spec.required ? \" NOT NULL\" : \"\";\n return ` ${quote(toSnakeCase(field))} ${SQL_TYPE[spec.type]}${nullability}${defaultClause(spec)}`;\n });\n\n if (table.primaryKey?.length) {\n columns.push(\n ` PRIMARY KEY (${table.primaryKey.map((f) => quote(toSnakeCase(f))).join(\", \")})`,\n );\n }\n\n statements.push(`CREATE TABLE IF NOT EXISTS ${name} (\\n${columns.join(\",\\n\")}\\n)`);\n\n for (const index of table.indexes ?? []) {\n const indexName = quote(\n prefix + (index.name ?? `${table.tableName}_${index.on.join(\"_\")}_idx`),\n );\n const cols = index.on.map((f) => quote(toSnakeCase(f))).join(\", \");\n statements.push(\n `CREATE ${index.unique ? \"UNIQUE \" : \"\"}INDEX IF NOT EXISTS ${indexName} ON ${name} (${cols})`,\n );\n }\n }\n\n return statements;\n}\n"]}
|
package/dist/schema.d.cts
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
import { S as SchemaDeclaration } from './plugin-
|
|
2
|
-
import './adapter-
|
|
1
|
+
import { S as SchemaDeclaration } from './plugin-CHd2ZiGC.cjs';
|
|
2
|
+
import './adapter-D3lTy-4E.cjs';
|
|
3
3
|
|
|
4
4
|
declare const toSnakeCase: (value: string) => string;
|
|
5
|
-
/**
|
|
6
|
-
* Core tables in the format plugins use. Less expressive than the hand-written
|
|
7
|
-
* Drizzle schema (no partial indexes, ordering or cascade) — a drift test
|
|
8
|
-
* asserts the two agree on the fields they share.
|
|
9
|
-
*/
|
|
5
|
+
/** Core tables in the plugin format. A drift test asserts it agrees with the Drizzle schema. */
|
|
10
6
|
declare const coreSchema: {
|
|
11
7
|
notification: {
|
|
12
8
|
tableName: string;
|
|
@@ -143,6 +139,11 @@ declare const coreSchema: {
|
|
|
143
139
|
required: true;
|
|
144
140
|
default: string;
|
|
145
141
|
};
|
|
142
|
+
updatedAt: {
|
|
143
|
+
type: "date";
|
|
144
|
+
required: true;
|
|
145
|
+
defaultNow: true;
|
|
146
|
+
};
|
|
146
147
|
};
|
|
147
148
|
primaryKey: string[];
|
|
148
149
|
};
|
|
@@ -154,6 +155,13 @@ type LiveColumn = {
|
|
|
154
155
|
type: string;
|
|
155
156
|
nullable: boolean;
|
|
156
157
|
};
|
|
158
|
+
/** A row as INTROSPECT_SQL returns it; `LiveColumn` uses the short forms and both are accepted. */
|
|
159
|
+
type LiveColumnRow = LiveColumn | {
|
|
160
|
+
table_name: string;
|
|
161
|
+
column_name: string;
|
|
162
|
+
data_type: string;
|
|
163
|
+
is_nullable: string | boolean;
|
|
164
|
+
};
|
|
157
165
|
type MigrationPlan = {
|
|
158
166
|
/** Run in order. Empty means the live schema already matches. */
|
|
159
167
|
statements: readonly string[];
|
|
@@ -162,19 +170,22 @@ type MigrationPlan = {
|
|
|
162
170
|
/** Tables that do not exist yet — these get a full CREATE TABLE. */
|
|
163
171
|
createdTables: readonly string[];
|
|
164
172
|
};
|
|
165
|
-
/**
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
*/
|
|
169
|
-
type Introspector = () => Promise<readonly LiveColumn[]>;
|
|
170
|
-
/** The query an Introspector should run. Exported so callers need not retype it. */
|
|
173
|
+
/** Reads the live column list; a function, so this module stays driver-agnostic. */
|
|
174
|
+
type Introspector = () => Promise<readonly LiveColumnRow[]>;
|
|
175
|
+
/** The query an Introspector should run; raw rows are accepted as they come back. */
|
|
171
176
|
declare const INTROSPECT_SQL = "\n SELECT table_name, column_name, data_type, is_nullable\n FROM information_schema.columns\n WHERE table_schema = current_schema()\n";
|
|
172
177
|
declare function planPostgresMigration(introspect: Introspector, schema: SchemaDeclaration, prefix?: string): Promise<MigrationPlan>;
|
|
173
178
|
|
|
174
179
|
/** Renders a SchemaDeclaration to Drizzle pg-core source. */
|
|
175
180
|
declare function renderDrizzleSchema(schema: SchemaDeclaration, prefix?: string): string;
|
|
176
181
|
|
|
182
|
+
/** MySQL DDL, one CREATE TABLE IF NOT EXISTS per table with indexes inline (no CREATE INDEX IF NOT EXISTS). */
|
|
183
|
+
declare function renderMysqlDdl(schema: SchemaDeclaration, prefix?: string): string[];
|
|
184
|
+
|
|
177
185
|
/** SchemaDeclaration to Postgres DDL, from the same source as the Drizzle renderer. */
|
|
178
186
|
declare function renderPostgresDdl(schema: SchemaDeclaration, prefix?: string): string[];
|
|
179
187
|
|
|
180
|
-
|
|
188
|
+
/** SchemaDeclaration to SQLite DDL. Every statement is `IF NOT EXISTS`. */
|
|
189
|
+
declare function renderSqliteDdl(schema: SchemaDeclaration, prefix?: string): string[];
|
|
190
|
+
|
|
191
|
+
export { INTROSPECT_SQL, type Introspector, type LiveColumn, type MigrationPlan, coreSchema, planPostgresMigration, renderDrizzleSchema, renderMysqlDdl, renderPostgresDdl, renderSqliteDdl, toSnakeCase };
|
package/dist/schema.d.ts
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
import { S as SchemaDeclaration } from './plugin-
|
|
2
|
-
import './adapter-
|
|
1
|
+
import { S as SchemaDeclaration } from './plugin-Cg9usuUi.js';
|
|
2
|
+
import './adapter-D3lTy-4E.js';
|
|
3
3
|
|
|
4
4
|
declare const toSnakeCase: (value: string) => string;
|
|
5
|
-
/**
|
|
6
|
-
* Core tables in the format plugins use. Less expressive than the hand-written
|
|
7
|
-
* Drizzle schema (no partial indexes, ordering or cascade) — a drift test
|
|
8
|
-
* asserts the two agree on the fields they share.
|
|
9
|
-
*/
|
|
5
|
+
/** Core tables in the plugin format. A drift test asserts it agrees with the Drizzle schema. */
|
|
10
6
|
declare const coreSchema: {
|
|
11
7
|
notification: {
|
|
12
8
|
tableName: string;
|
|
@@ -143,6 +139,11 @@ declare const coreSchema: {
|
|
|
143
139
|
required: true;
|
|
144
140
|
default: string;
|
|
145
141
|
};
|
|
142
|
+
updatedAt: {
|
|
143
|
+
type: "date";
|
|
144
|
+
required: true;
|
|
145
|
+
defaultNow: true;
|
|
146
|
+
};
|
|
146
147
|
};
|
|
147
148
|
primaryKey: string[];
|
|
148
149
|
};
|
|
@@ -154,6 +155,13 @@ type LiveColumn = {
|
|
|
154
155
|
type: string;
|
|
155
156
|
nullable: boolean;
|
|
156
157
|
};
|
|
158
|
+
/** A row as INTROSPECT_SQL returns it; `LiveColumn` uses the short forms and both are accepted. */
|
|
159
|
+
type LiveColumnRow = LiveColumn | {
|
|
160
|
+
table_name: string;
|
|
161
|
+
column_name: string;
|
|
162
|
+
data_type: string;
|
|
163
|
+
is_nullable: string | boolean;
|
|
164
|
+
};
|
|
157
165
|
type MigrationPlan = {
|
|
158
166
|
/** Run in order. Empty means the live schema already matches. */
|
|
159
167
|
statements: readonly string[];
|
|
@@ -162,19 +170,22 @@ type MigrationPlan = {
|
|
|
162
170
|
/** Tables that do not exist yet — these get a full CREATE TABLE. */
|
|
163
171
|
createdTables: readonly string[];
|
|
164
172
|
};
|
|
165
|
-
/**
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
*/
|
|
169
|
-
type Introspector = () => Promise<readonly LiveColumn[]>;
|
|
170
|
-
/** The query an Introspector should run. Exported so callers need not retype it. */
|
|
173
|
+
/** Reads the live column list; a function, so this module stays driver-agnostic. */
|
|
174
|
+
type Introspector = () => Promise<readonly LiveColumnRow[]>;
|
|
175
|
+
/** The query an Introspector should run; raw rows are accepted as they come back. */
|
|
171
176
|
declare const INTROSPECT_SQL = "\n SELECT table_name, column_name, data_type, is_nullable\n FROM information_schema.columns\n WHERE table_schema = current_schema()\n";
|
|
172
177
|
declare function planPostgresMigration(introspect: Introspector, schema: SchemaDeclaration, prefix?: string): Promise<MigrationPlan>;
|
|
173
178
|
|
|
174
179
|
/** Renders a SchemaDeclaration to Drizzle pg-core source. */
|
|
175
180
|
declare function renderDrizzleSchema(schema: SchemaDeclaration, prefix?: string): string;
|
|
176
181
|
|
|
182
|
+
/** MySQL DDL, one CREATE TABLE IF NOT EXISTS per table with indexes inline (no CREATE INDEX IF NOT EXISTS). */
|
|
183
|
+
declare function renderMysqlDdl(schema: SchemaDeclaration, prefix?: string): string[];
|
|
184
|
+
|
|
177
185
|
/** SchemaDeclaration to Postgres DDL, from the same source as the Drizzle renderer. */
|
|
178
186
|
declare function renderPostgresDdl(schema: SchemaDeclaration, prefix?: string): string[];
|
|
179
187
|
|
|
180
|
-
|
|
188
|
+
/** SchemaDeclaration to SQLite DDL. Every statement is `IF NOT EXISTS`. */
|
|
189
|
+
declare function renderSqliteDdl(schema: SchemaDeclaration, prefix?: string): string[];
|
|
190
|
+
|
|
191
|
+
export { INTROSPECT_SQL, type Introspector, type LiveColumn, type MigrationPlan, coreSchema, planPostgresMigration, renderDrizzleSchema, renderMysqlDdl, renderPostgresDdl, renderSqliteDdl, toSnakeCase };
|
package/dist/schema.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export { INTROSPECT_SQL, planPostgresMigration, renderDrizzleSchema, renderPostgresDdl } from './chunk-
|
|
2
|
-
export {
|
|
1
|
+
export { INTROSPECT_SQL, planPostgresMigration, renderDrizzleSchema, renderPostgresDdl } from './chunk-XIDVLYNQ.js';
|
|
2
|
+
export { renderSqliteDdl } from './chunk-HY47TQMY.js';
|
|
3
|
+
export { renderMysqlDdl } from './chunk-M4R77BJD.js';
|
|
4
|
+
export { coreSchema, toSnakeCase } from './chunk-AEYYTE5I.js';
|
|
3
5
|
//# sourceMappingURL=schema.js.map
|
|
4
6
|
//# sourceMappingURL=schema.js.map
|
package/dist/testing.cjs
CHANGED
|
@@ -39,13 +39,7 @@ async function seed(ctx, options = {}) {
|
|
|
39
39
|
var CLAIM = { limit: 10, leaseMs: 6e4 };
|
|
40
40
|
var adapterConformanceCases = [
|
|
41
41
|
{
|
|
42
|
-
/**
|
|
43
|
-
* The case that actually distinguishes a correct adapter.
|
|
44
|
-
*
|
|
45
|
-
* A row locked by another transaction must be *skipped*, not waited on.
|
|
46
|
-
* Without SKIP LOCKED the claim blocks until the holder commits, which on
|
|
47
|
-
* a busy table serialises every worker behind the slowest one.
|
|
48
|
-
*/
|
|
42
|
+
/** A row locked by another transaction must be skipped, not waited on. */
|
|
49
43
|
name: "a row locked by another transaction is skipped, not waited on",
|
|
50
44
|
requires: "rowLock",
|
|
51
45
|
run: async (ctx) => {
|
|
@@ -263,8 +257,7 @@ var adapterConformanceCases = [
|
|
|
263
257
|
}
|
|
264
258
|
},
|
|
265
259
|
{
|
|
266
|
-
//
|
|
267
|
-
// show up in the view an operator reads to find real breakage.
|
|
260
|
+
// A delivery with nothing to do must stay out of the failure view.
|
|
268
261
|
name: "a skipped delivery is terminal and stays out of getFailedDeliveries",
|
|
269
262
|
run: async (ctx) => {
|
|
270
263
|
const seeded = await seed(ctx, { maxAttempts: 5 });
|
|
@@ -335,16 +328,7 @@ var adapterConformanceCases = [
|
|
|
335
328
|
}
|
|
336
329
|
},
|
|
337
330
|
{
|
|
338
|
-
|
|
339
|
-
* createdAt must come from the same clock as the cutoff it is compared to.
|
|
340
|
-
*
|
|
341
|
-
* An adapter that leaves createdAt to a database DEFAULT now() is comparing
|
|
342
|
-
* the database clock against the application clock. On one machine they
|
|
343
|
-
* agree and this never fails; in production they are different hosts, and a
|
|
344
|
-
* database a second ahead means markSeen(now) silently misses the newest
|
|
345
|
-
* notifications and the unseen badge never clears. Found when a laptop
|
|
346
|
-
* resumed from sleep with its Docker VM 6s ahead.
|
|
347
|
-
*/
|
|
331
|
+
// createdAt must come from the same clock as the cutoffs it is compared to; a database DEFAULT now() breaks markSeen under NTP skew.
|
|
348
332
|
name: "createdAt comes from the caller clock, not the database clock",
|
|
349
333
|
run: async (ctx) => {
|
|
350
334
|
const userId = uid("user");
|
package/dist/testing.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/testing/conformance.ts"],"names":[],"mappings":";;;AAsCA,IAAM,gBAAA,GAAN,cAA+B,KAAA,CAAM;AAAC,CAAA;AAEtC,SAAS,MAAA,CAAO,WAAoB,OAAA,EAAoC;AACtE,EAAA,IAAI,CAAC,SAAA,EAAW,MAAM,IAAI,iBAAiB,OAAO,CAAA;AACpD;AAEA,IAAM,QAAQ,CAAC,MAAA,EAAiB,UAAmB,OAAA,KACjD,MAAA,CAAO,WAAW,QAAA,EAAU,CAAA,EAAG,OAAO,CAAA,MAAA,EAAS,OAAO,MAAM,CAAC,cAAc,MAAA,CAAO,QAAQ,CAAC,CAAA,CAAA,CAAG,CAAA;AAEhG,IAAI,OAAA,GAAU,CAAA;AACd,SAAS,IAAI,KAAA,EAAuB;AAClC,EAAA,OAAA,IAAW,CAAA;AACX,EAAA,OAAO,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,IAAA,CAAK,GAAA,GAAM,QAAA,CAAS,EAAE,CAAC,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA;AACvD;AAWA,eAAe,IAAA,CAAK,GAAA,EAAyB,OAAA,GAAuB,EAAC,EAAG;AACtE,EAAA,MAAM,KAAA,GAAQ,QAAQ,KAAA,IAAS,CAAA;AAC/B,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,IAAU,GAAA,CAAI,MAAM,CAAA;AAE3C,EAAA,MAAM,OAA6B,KAAA,CAAM,IAAA,CAAK,EAAE,MAAA,EAAQ,KAAA,IAAS,MAAM;AACrE,IAAA,MAAM,EAAA,GAAK,IAAI,OAAO,CAAA;AACtB,IAAA,OAAO;AAAA,MACL,EAAA;AAAA,MACA,MAAA;AAAA,MACA,IAAA,EAAM,cAAA;AAAA,MACN,OAAA,EAAS,EAAE,UAAA,EAAY,MAAA,EAAO;AAAA,MAC9B,GAAI,QAAQ,SAAA,GAAY,EAAE,WAAW,OAAA,CAAQ,SAAA,KAAc,EAAC;AAAA,MAC5D,UAAA,EAAY;AAAA,QACV;AAAA,UACE,EAAA,EAAI,IAAI,UAAU,CAAA;AAAA,UAClB,OAAA,EAAS,QAAQ,OAAA,IAAW,OAAA;AAAA,UAC5B,WAAA,EAAa,QAAQ,WAAA,IAAe,CAAA;AAAA,UACpC,SAAA,EAAW,QAAQ,SAAA,IAAa,IAAI,KAAK,IAAA,CAAK,GAAA,KAAQ,GAAI;AAAA;AAC5D;AACF,KACF;AAAA,EACF,CAAC,CAAA;AAED,EAAA,MAAM,MAAA,GAAS,MAAM,GAAA,CAAI,OAAA,CAAQ,oBAAoB,IAAI,CAAA;AACzD,EAAA,OAAO,EAAE,MAAA,EAAQ,IAAA,EAAM,MAAA,EAAO;AAChC;AAEA,IAAM,KAAA,GAAQ,EAAE,KAAA,EAAO,EAAA,EAAI,SAAS,GAAA,EAAO;AAEpC,IAAM,uBAAA,GAAsD;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQE,IAAA,EAAM,+DAAA;AAAA,IACN,QAAA,EAAU,SAAA;AAAA,IACV,GAAA,EAAK,OAAO,GAAA,KAAQ;AAClB,MAAA,MAAM,EAAE,SAAQ,GAAI,GAAA;AACpB,MAAA,MAAA,CAAO,SAAS,uBAAuB,CAAA;AAEvC,MAAA,MAAM,EAAE,MAAK,GAAI,MAAM,KAAK,GAAA,EAAK,EAAE,KAAA,EAAO,CAAA,EAAG,CAAA;AAC7C,MAAA,MAAM,SAAS,IAAA,CAAK,CAAC,CAAA,EAAG,UAAA,CAAW,CAAC,CAAA,EAAG,EAAA;AACvC,MAAA,MAAM,OAAO,IAAA,CAAK,CAAC,CAAA,EAAG,UAAA,CAAW,CAAC,CAAA,EAAG,EAAA;AACrC,MAAA,MAAA,CAAO,MAAA,IAAU,MAAM,kCAAkC,CAAA;AAEzD,MAAA,MAAM,OAAA,CAAQ,QAAQ,YAAY;AAChC,QAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,IAAA,CAAK;AAAA,UACjC,GAAA,CAAI,OAAA,CAAQ,sBAAA,CAAuB,EAAE,GAAG,OAAO,UAAA,EAAY,GAAA,CAAI,OAAO,CAAA,EAAG,CAAA;AAAA,UACzE,IAAI,OAAA;AAAA,YAAe,CAAC,GAAG,MAAA,KACrB,UAAA;AAAA,cACE,MACE,MAAA;AAAA,gBACE,IAAI,gBAAA;AAAA,kBACF;AAAA;AACF,eACF;AAAA,cACF;AAAA;AACF;AACF,SACD,CAAA;AAED,QAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,OAAA,CAAQ,IAAI,CAAC,GAAA,KAAQ,GAAA,CAAI,EAAE,CAAC,CAAA;AAChD,QAAA,MAAA,CAAO,CAAC,GAAA,CAAI,GAAA,CAAI,MAAM,GAAG,6CAA6C,CAAA;AACtE,QAAA,MAAA,CAAO,GAAA,CAAI,GAAA,CAAI,IAAI,CAAA,EAAG,kDAAkD,CAAA;AAAA,MAC1E,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AAAA,EAEA;AAAA,IACE,IAAA,EAAM,wCAAA;AAAA,IACN,GAAA,EAAK,OAAO,GAAA,KAAQ;AAClB,MAAA,MAAM,IAAA,CAAK,GAAA,EAAK,EAAE,KAAA,EAAO,IAAI,CAAA;AAI7B,MAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,GAAA;AAAA,QAC5B,KAAA,CAAM,IAAA;AAAA,UAAK,EAAE,QAAQ,CAAA,EAAE;AAAA,UAAG,MACxB,GAAA,CAAI,OAAA,CAAQ,sBAAA,CAAuB,EAAE,KAAA,EAAO,CAAA,EAAG,OAAA,EAAS,GAAA,EAAQ,UAAA,EAAY,GAAA,CAAI,GAAG,GAAG;AAAA;AACxF,OACF;AAEA,MAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,OAAA,CAAQ,CAAC,KAAA,KAAU,KAAA,CAAM,GAAA,CAAI,CAAC,GAAA,KAAQ,GAAA,CAAI,EAAE,CAAC,CAAA;AACjE,MAAA,KAAA,CAAM,IAAI,GAAA,CAAI,GAAG,EAAE,IAAA,EAAM,GAAA,CAAI,QAAQ,8CAA8C,CAAA;AACnF,MAAA,MAAA,CAAO,GAAA,CAAI,MAAA,IAAU,EAAA,EAAI,8BAA8B,CAAA;AAAA,IACzD;AAAA,GACF;AAAA,EAEA;AAAA,IACE,IAAA,EAAM,qDAAA;AAAA,IACN,GAAA,EAAK,OAAO,GAAA,KAAQ;AAClB,MAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,KAAK,GAAG,CAAA;AAC/B,MAAA,MAAM,SAAS,IAAA,CAAK,CAAC,CAAA,EAAG,UAAA,CAAW,CAAC,CAAA,EAAG,EAAA;AAEvC,MAAA,MAAM,KAAA,GAAQ,MAAM,GAAA,CAAI,OAAA,CAAQ,sBAAA,CAAuB,EAAE,GAAG,KAAA,EAAO,UAAA,EAAY,GAAA,CAAI,GAAG,CAAA,EAAG,CAAA;AACzF,MAAA,MAAA;AAAA,QACE,MAAM,IAAA,CAAK,CAAC,GAAA,KAAQ,GAAA,CAAI,OAAO,MAAM,CAAA;AAAA,QACrC;AAAA,OACF;AAEA,MAAA,MAAM,MAAA,GAAS,MAAM,GAAA,CAAI,OAAA,CAAQ,sBAAA,CAAuB,EAAE,GAAG,KAAA,EAAO,UAAA,EAAY,GAAA,CAAI,GAAG,CAAA,EAAG,CAAA;AAC1F,MAAA,MAAA,CAAO,CAAC,OAAO,IAAA,CAAK,CAAC,QAAQ,GAAA,CAAI,EAAA,KAAO,MAAM,CAAA,EAAG,8BAA8B,CAAA;AAAA,IACjF;AAAA,GACF;AAAA,EAEA;AAAA,IACE,IAAA,EAAM,uDAAA;AAAA,IACN,GAAA,EAAK,OAAO,GAAA,KAAQ;AAClB,MAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,KAAK,GAAG,CAAA;AAC/B,MAAA,MAAM,SAAS,IAAA,CAAK,CAAC,CAAA,EAAG,UAAA,CAAW,CAAC,CAAA,EAAG,EAAA;AAEvC,MAAA,MAAM,GAAA,CAAI,OAAA,CAAQ,sBAAA,CAAuB,EAAE,GAAG,OAAO,UAAA,EAAY,GAAA,CAAI,GAAG,CAAA,EAAG,CAAA;AAE3E,MAAA,MAAM,KAAA,GAAQ,IAAI,IAAA,CAAK,IAAA,CAAK,KAAI,GAAI,KAAA,CAAM,UAAU,GAAK,CAAA;AACzD,MAAA,MAAM,SAAA,GAAY,MAAM,GAAA,CAAI,OAAA,CAAQ,sBAAA,CAAuB;AAAA,QACzD,GAAG,KAAA;AAAA,QACH,UAAA,EAAY,IAAI,GAAG,CAAA;AAAA,QACnB,GAAA,EAAK;AAAA,OACN,CAAA;AAED,MAAA,MAAA;AAAA,QACE,UAAU,IAAA,CAAK,CAAC,GAAA,KAAQ,GAAA,CAAI,OAAO,MAAM,CAAA;AAAA,QACzC;AAAA,OACF;AAAA,IACF;AAAA,GACF;AAAA,EAEA;AAAA,IACE,IAAA,EAAM,2CAAA;AAAA,IACN,GAAA,EAAK,OAAO,GAAA,KAAQ;AAClB,MAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,KAAK,GAAA,EAAK,EAAE,SAAA,EAAW,IAAI,KAAK,IAAA,CAAK,GAAA,EAAI,GAAI,IAAS,GAAG,CAAA;AAChF,MAAA,MAAM,SAAS,IAAA,CAAK,CAAC,CAAA,EAAG,UAAA,CAAW,CAAC,CAAA,EAAG,EAAA;AAEvC,MAAA,MAAM,OAAA,GAAU,MAAM,GAAA,CAAI,OAAA,CAAQ,sBAAA,CAAuB,EAAE,GAAG,KAAA,EAAO,UAAA,EAAY,GAAA,CAAI,GAAG,CAAA,EAAG,CAAA;AAC3F,MAAA,MAAA,CAAO,CAAC,QAAQ,IAAA,CAAK,CAAC,QAAQ,GAAA,CAAI,EAAA,KAAO,MAAM,CAAA,EAAG,0CAA0C,CAAA;AAAA,IAC9F;AAAA,GACF;AAAA,EAEA;AAAA,IACE,IAAA,EAAM,qDAAA;AAAA,IACN,GAAA,EAAK,OAAO,GAAA,KAAQ;AAClB,MAAA,MAAM,EAAE,MAAK,GAAI,MAAM,KAAK,GAAA,EAAK,EAAE,WAAA,EAAa,CAAA,EAAG,CAAA;AACnD,MAAA,MAAM,SAAS,IAAA,CAAK,CAAC,CAAA,EAAG,UAAA,CAAW,CAAC,CAAA,EAAG,EAAA;AACvC,MAAA,MAAA,CAAO,QAAQ,2BAA2B,CAAA;AAE1C,MAAA,MAAM,GAAA,CAAI,WAAA,CAAY,MAAA,EAAQ,CAAC,CAAA;AAE/B,MAAA,MAAM,OAAA,GAAU,MAAM,GAAA,CAAI,OAAA,CAAQ,sBAAA,CAAuB,EAAE,GAAG,KAAA,EAAO,UAAA,EAAY,GAAA,CAAI,GAAG,CAAA,EAAG,CAAA;AAC3F,MAAA,MAAA,CAAO,CAAC,QAAQ,IAAA,CAAK,CAAC,QAAQ,GAAA,CAAI,EAAA,KAAO,MAAM,CAAA,EAAG,+BAA+B,CAAA;AAAA,IACnF;AAAA,GACF;AAAA,EAEA;AAAA,IACE,IAAA,EAAM,4CAAA;AAAA,IACN,GAAA,EAAK,OAAO,GAAA,KAAQ;AAClB,MAAA,MAAM,MAAA,GAAS,IAAI,MAAM,CAAA;AACzB,MAAA,MAAM,KAAA,GAAQ,IAAI,UAAU,CAAA;AAC5B,MAAA,MAAM,KAAA,GAAQ,IAAI,UAAU,CAAA;AAE5B,MAAA,MAAM,GAAA,CAAI,QAAQ,mBAAA,CAAoB;AAAA,QACpC;AAAA,UACE,EAAA,EAAI,IAAI,OAAO,CAAA;AAAA,UACf,MAAA;AAAA,UACA,IAAA,EAAM,GAAA;AAAA,UACN,SAAS,EAAC;AAAA,UACV,UAAA,EAAY;AAAA,YACV;AAAA,cACE,EAAA,EAAI,KAAA;AAAA,cACJ,OAAA,EAAS,OAAA;AAAA,cACT,WAAA,EAAa,CAAA;AAAA,cACb,WAAW,IAAI,IAAA,CAAK,IAAA,CAAK,GAAA,KAAQ,GAAK;AAAA;AACxC;AACF,SACF;AAAA,QACA;AAAA,UACE,EAAA,EAAI,IAAI,OAAO,CAAA;AAAA,UACf,MAAA;AAAA,UACA,IAAA,EAAM,GAAA;AAAA,UACN,SAAS,EAAC;AAAA,UACV,UAAA,EAAY;AAAA,YACV;AAAA,cACE,EAAA,EAAI,KAAA;AAAA,cACJ,OAAA,EAAS,OAAA;AAAA,cACT,WAAA,EAAa,CAAA;AAAA,cACb,WAAW,IAAI,IAAA,CAAK,IAAA,CAAK,GAAA,KAAQ,GAAO;AAAA;AAC1C;AACF;AACF,OACD,CAAA;AAED,MAAA,MAAM,OAAA,GAAU,MAAM,GAAA,CAAI,OAAA,CAAQ,sBAAA,CAAuB;AAAA,QACvD,KAAA,EAAO,CAAA;AAAA,QACP,OAAA,EAAS,GAAA;AAAA,QACT,UAAA,EAAY,IAAI,GAAG;AAAA,OACpB,CAAA;AAED,MAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA,EAAG,EAAA,EAAI,OAAO,gDAAgD,CAAA;AAAA,IAC/E;AAAA,GACF;AAAA,EAEA;AAAA,IACE,IAAA,EAAM,4DAAA;AAAA,IACN,GAAA,EAAK,OAAO,GAAA,KAAQ;AAClB,MAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,KAAK,GAAG,CAAA;AAC/B,MAAA,MAAM,SAAS,IAAA,CAAK,CAAC,CAAA,EAAG,UAAA,CAAW,CAAC,CAAA,EAAG,EAAA;AACvC,MAAA,MAAA,CAAO,QAAQ,2BAA2B,CAAA;AAE1C,MAAA,MAAM,GAAA,CAAI,OAAA,CAAQ,sBAAA,CAAuB,EAAE,GAAG,OAAO,UAAA,EAAY,GAAA,CAAI,MAAM,CAAA,EAAG,CAAA;AAE9E,MAAA,MAAM,GAAA,CAAI,QAAQ,iBAAA,CAAkB;AAAA,QAClC;AAAA,UACE,EAAA,EAAI,MAAA;AAAA,UACJ,UAAA,EAAY,oCAAA;AAAA,UACZ,OAAA,EAAS,EAAE,MAAA,EAAQ,MAAA;AAAO;AAC5B,OACD,CAAA;AAED,MAAA,MAAM,cAAA,GAAiB,MAAM,GAAA,CAAI,OAAA,CAAQ,sBAAA,CAAuB;AAAA,QAC9D,GAAG,KAAA;AAAA,QACH,UAAA,EAAY,IAAI,GAAG,CAAA;AAAA,QACnB,GAAA,EAAK,IAAI,IAAA,CAAK,IAAA,CAAK,KAAI,GAAI,KAAA,CAAM,UAAU,GAAK;AAAA,OACjD,CAAA;AAED,MAAA,MAAA;AAAA,QACE,CAAC,cAAA,CAAe,IAAA,CAAK,CAAC,GAAA,KAAQ,GAAA,CAAI,OAAO,MAAM,CAAA;AAAA,QAC/C;AAAA,OACF;AAAA,IACF;AAAA,GACF;AAAA,EAEA;AAAA,IACE,IAAA,EAAM,4DAAA;AAAA,IACN,GAAA,EAAK,OAAO,GAAA,KAAQ;AAClB,MAAA,MAAM,QAAQ,MAAM,IAAA,CAAK,KAAK,EAAE,WAAA,EAAa,GAAG,CAAA;AAChD,MAAA,MAAM,UAAU,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,EAAG,UAAA,CAAW,CAAC,CAAA,EAAG,EAAA;AAC9C,MAAA,MAAA,CAAO,SAAS,2BAA2B,CAAA;AAE3C,MAAA,MAAM,GAAA,CAAI,OAAA,CAAQ,sBAAA,CAAuB,EAAE,GAAG,OAAO,UAAA,EAAY,GAAA,CAAI,GAAG,CAAA,EAAG,CAAA;AAE3E,MAAA,MAAM,OAAO,IAAI,IAAA,CAAK,IAAA,CAAK,GAAA,KAAQ,GAAM,CAAA;AACzC,MAAA,MAAM,GAAA,CAAI,QAAQ,iBAAA,CAAkB;AAAA,QAClC;AAAA,UACE,EAAA,EAAI,OAAA;AAAA,UACJ,UAAA,EAAY,GAAA;AAAA,UACZ,SAAS,EAAE,MAAA,EAAQ,UAAU,KAAA,EAAO,cAAA,EAAgB,WAAW,IAAA,EAAK;AAAA,UACpE,aAAA,EAAe;AAAA;AACjB,OACD,CAAA;AAED,MAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CAAI,OAAA,CAAQ,sBAAA,CAAuB,EAAE,GAAG,KAAA,EAAO,UAAA,EAAY,GAAA,CAAI,GAAG,CAAA,EAAG,CAAA;AAC5F,MAAA,MAAA;AAAA,QACE,CAAC,QAAA,CAAS,IAAA,CAAK,CAAC,GAAA,KAAQ,GAAA,CAAI,OAAO,OAAO,CAAA;AAAA,QAC1C;AAAA,OACF;AAEA,MAAA,MAAM,YAAA,GAAe,MAAM,GAAA,CAAI,OAAA,CAAQ,sBAAA,CAAuB;AAAA,QAC5D,GAAG,KAAA;AAAA,QACH,UAAA,EAAY,IAAI,GAAG,CAAA;AAAA,QACnB,KAAK,IAAI,IAAA,CAAK,IAAA,CAAK,OAAA,KAAY,GAAK;AAAA,OACrC,CAAA;AACD,MAAA,MAAA;AAAA,QACE,aAAa,IAAA,CAAK,CAAC,GAAA,KAAQ,GAAA,CAAI,OAAO,OAAO,CAAA;AAAA,QAC7C;AAAA,OACF;AAEA,MAAA,MAAM,WAAW,MAAM,IAAA,CAAK,KAAK,EAAE,WAAA,EAAa,GAAG,CAAA;AACnD,MAAA,MAAM,aAAa,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,EAAG,UAAA,CAAW,CAAC,CAAA,EAAG,EAAA;AACpD,MAAA,MAAA,CAAO,YAAY,2BAA2B,CAAA;AAE9C,MAAA,MAAM,GAAA,CAAI,OAAA,CAAQ,sBAAA,CAAuB,EAAE,GAAG,OAAO,UAAA,EAAY,GAAA,CAAI,GAAG,CAAA,EAAG,CAAA;AAC3E,MAAA,MAAM,GAAA,CAAI,QAAQ,iBAAA,CAAkB;AAAA,QAClC;AAAA,UACE,EAAA,EAAI,UAAA;AAAA,UACJ,UAAA,EAAY,GAAA;AAAA,UACZ,SAAS,EAAE,MAAA,EAAQ,UAAU,KAAA,EAAO,iBAAA,EAAmB,WAAW,KAAA;AAAM;AAC1E,OACD,CAAA;AAED,MAAA,MAAM,MAAA,GAAS,MAAM,GAAA,CAAI,OAAA,CAAQ,mBAAA,CAAoB;AAAA,QACnD,OAAO,IAAI,IAAA,CAAK,IAAA,CAAK,GAAA,KAAQ,GAAM,CAAA;AAAA,QACnC,KAAA,EAAO;AAAA,OACR,CAAA;AACD,MAAA,MAAA;AAAA,QACE,OAAO,IAAA,CAAK,CAAC,GAAA,KAAQ,GAAA,CAAI,OAAO,UAAU,CAAA;AAAA,QAC1C;AAAA,OACF;AAAA,IACF;AAAA,GACF;AAAA,EAEA;AAAA;AAAA;AAAA,IAGE,IAAA,EAAM,qEAAA;AAAA,IACN,GAAA,EAAK,OAAO,GAAA,KAAQ;AAClB,MAAA,MAAM,SAAS,MAAM,IAAA,CAAK,KAAK,EAAE,WAAA,EAAa,GAAG,CAAA;AACjD,MAAA,MAAM,KAAK,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,EAAG,UAAA,CAAW,CAAC,CAAA,EAAG,EAAA;AAC1C,MAAA,MAAA,CAAO,IAAI,2BAA2B,CAAA;AAEtC,MAAA,MAAM,GAAA,CAAI,OAAA,CAAQ,sBAAA,CAAuB,EAAE,GAAG,OAAO,UAAA,EAAY,GAAA,CAAI,GAAG,CAAA,EAAG,CAAA;AAC3E,MAAA,MAAM,GAAA,CAAI,QAAQ,iBAAA,CAAkB;AAAA,QAClC;AAAA,UACE,EAAA;AAAA,UACA,UAAA,EAAY,GAAA;AAAA,UACZ,OAAA,EAAS,EAAE,MAAA,EAAQ,SAAA,EAAW,QAAQ,uBAAA;AAAwB;AAChE,OACD,CAAA;AAED,MAAA,MAAM,MAAA,GAAS,MAAM,GAAA,CAAI,OAAA,CAAQ,mBAAA,CAAoB;AAAA,QACnD,OAAO,IAAI,IAAA,CAAK,IAAA,CAAK,GAAA,KAAQ,GAAM,CAAA;AAAA,QACnC,KAAA,EAAO;AAAA,OACR,CAAA;AACD,MAAA,MAAA,CAAO,CAAC,OAAO,IAAA,CAAK,CAAC,QAAQ,GAAA,CAAI,EAAA,KAAO,EAAE,CAAA,EAAG,2CAA2C,CAAA;AAIxF,MAAA,MAAM,SAAA,GAAY,MAAM,GAAA,CAAI,OAAA,CAAQ,sBAAA,CAAuB;AAAA,QACzD,GAAG,KAAA;AAAA,QACH,UAAA,EAAY,IAAI,GAAG,CAAA;AAAA,QACnB,KAAK,IAAI,IAAA,CAAK,IAAA,CAAK,GAAA,KAAQ,IAAS;AAAA,OACrC,CAAA;AACD,MAAA,MAAA,CAAO,CAAC,UAAU,IAAA,CAAK,CAAC,QAAQ,GAAA,CAAI,EAAA,KAAO,EAAE,CAAA,EAAG,sCAAsC,CAAA;AAAA,IACxF;AAAA,GACF;AAAA,EAEA;AAAA,IACE,IAAA,EAAM,4CAAA;AAAA,IACN,GAAA,EAAK,OAAO,GAAA,KAAQ;AAClB,MAAA,MAAM,MAAA,GAAS,IAAI,MAAM,CAAA;AACzB,MAAA,MAAM,GAAA,GAAM,IAAI,QAAQ,CAAA;AAExB,MAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,KAAK,CAAA;AACxD,MAAA,KAAA,CAAM,KAAA,CAAM,MAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ,GAAG,8BAA8B,CAAA;AAEpE,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,KAAK,CAAA;AACzD,MAAA,KAAA,CAAM,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ,GAAG,uBAAuB,CAAA;AAC9D,MAAA,KAAA,CAAM,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ,GAAG,uCAAuC,CAAA;AAAA,IAChF;AAAA,GACF;AAAA,EAEA;AAAA,IACE,IAAA,EAAM,+CAAA;AAAA,IACN,GAAA,EAAK,OAAO,GAAA,KAAQ;AAClB,MAAA,MAAM,MAAA,GAAS,IAAI,MAAM,CAAA;AACzB,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,GAAA,EAAK,EAAE,MAAA,EAAQ,KAAA,EAAO,GAAG,CAAA;AACnD,MAAA,KAAA,CAAM,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ,GAAG,kCAAkC,CAAA;AAAA,IAC3E;AAAA,GACF;AAAA,EAEA;AAAA,IACE,IAAA,EAAM,uCAAA;AAAA,IACN,GAAA,EAAK,OAAO,GAAA,KAAQ;AAClB,MAAA,MAAM,KAAA,GAAQ,IAAI,MAAM,CAAA;AACxB,MAAA,MAAM,EAAE,MAAK,GAAI,MAAM,KAAK,GAAA,EAAK,EAAE,MAAA,EAAQ,KAAA,EAAO,CAAA;AAClD,MAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,CAAC,CAAA,EAAG,EAAA;AAChC,MAAA,MAAA,CAAO,gBAAgB,+BAA+B,CAAA;AAEtD,MAAA,MAAM,MAAA,GAAS,MAAM,GAAA,CAAI,OAAA,CAAQ,QAAA,CAAS,IAAI,UAAU,CAAA,EAAG,CAAC,cAAc,CAAC,CAAA;AAC3E,MAAA,KAAA,CAAM,MAAA,EAAQ,GAAG,yCAAyC,CAAA;AAE1D,MAAA,MAAM,GAAA,GAAM,MAAM,GAAA,CAAI,OAAA,CAAQ,SAAS,KAAA,EAAO,CAAC,cAAc,CAAC,CAAA;AAC9D,MAAA,KAAA,CAAM,GAAA,EAAK,GAAG,kDAAkD,CAAA;AAAA,IAClE;AAAA,GACF;AAAA,EAEA;AAAA,IACE,IAAA,EAAM,iCAAA;AAAA,IACN,GAAA,EAAK,OAAO,GAAA,KAAQ;AAClB,MAAA,MAAM,MAAA,GAAS,IAAI,MAAM,CAAA;AACzB,MAAA,MAAM,KAAK,GAAA,EAAK,EAAE,MAAA,EAAQ,KAAA,EAAO,GAAG,CAAA;AAEpC,MAAA,KAAA,CAAM,MAAM,GAAA,CAAI,OAAA,CAAQ,YAAY,MAAM,CAAA,EAAG,GAAG,oCAAoC,CAAA;AAEpF,MAAA,MAAM,IAAI,OAAA,CAAQ,QAAA,CAAS,MAAA,kBAAQ,IAAI,MAAM,CAAA;AAC7C,MAAA,KAAA,CAAM,MAAM,GAAA,CAAI,OAAA,CAAQ,YAAY,MAAM,CAAA,EAAG,GAAG,mCAAmC,CAAA;AAAA,IACrF;AAAA,GACF;AAAA,EAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAWE,IAAA,EAAM,+DAAA;AAAA,IACN,GAAA,EAAK,OAAO,GAAA,KAAQ;AAClB,MAAA,MAAM,MAAA,GAAS,IAAI,MAAM,CAAA;AACzB,MAAA,MAAM,MAAA,uBAAa,IAAA,EAAK;AACxB,MAAA,MAAM,KAAK,GAAA,EAAK,EAAE,MAAA,EAAQ,KAAA,EAAO,GAAG,CAAA;AACpC,MAAA,MAAM,KAAA,uBAAY,IAAA,EAAK;AAEvB,MAAA,MAAM,EAAE,aAAA,EAAc,GAAI,MAAM,GAAA,CAAI,OAAA,CAAQ,iBAAA,CAAkB,EAAE,MAAA,EAAQ,KAAA,EAAO,EAAA,EAAI,CAAA;AACnF,MAAA,MAAM,SAAA,GAAY,aAAA,CAAc,CAAC,CAAA,EAAG,SAAA;AACpC,MAAA,MAAA,CAAO,WAAW,+BAA+B,CAAA;AAIjD,MAAA,MAAM,SAAS,IAAA,CAAK,GAAA;AAAA,QAClB,MAAA,CAAO,OAAA,EAAQ,GAAI,SAAA,CAAU,OAAA,EAAQ;AAAA,QACrC,SAAA,CAAU,OAAA,EAAQ,GAAI,KAAA,CAAM,OAAA;AAAQ,OACtC;AACA,MAAA,MAAA;AAAA,QACE,MAAA,IAAU,GAAA;AAAA,QACV,gBAAgB,MAAM,CAAA,gFAAA;AAAA,OACxB;AAAA,IACF;AAAA;AAEJ","file":"testing.cjs","sourcesContent":["import type { DatabaseAdapter, InsertNotification } from \"../core/adapter\";\nimport type { Channel } from \"../core/types\";\n\nexport type ConformanceContext = {\n adapter: DatabaseAdapter;\n /**\n * Forces a delivery's attempt count. Not reachable through the public API —\n * the adapter would have marked the row failed on the way there — so each\n * backend writes it directly.\n */\n setAttempts: (deliveryId: string, attempts: number) => Promise<void>;\n /**\n * Empties the tables. Cases must run against a clean table: claims are\n * ordered by not_before ASC and bounded by limit, so leftover rows from an\n * earlier case can push the row under test out of the claim window.\n */\n reset: () => Promise<void>;\n /**\n * Holds a row lock on a separate connection for the duration of `fn`.\n *\n * Required to test SKIP LOCKED deterministically. Two Promise.all'd claims\n * do not reliably overlap — they complete in single-digit milliseconds and\n * simply queue — so a race-based test passes even with no locking at all.\n *\n * Only meaningful where a claim can block on someone else's lock. A document\n * store whose claim is a single atomic update has nothing to skip, so cases\n * tagged `rowLock` do not apply to it.\n */\n lockRow?: (deliveryId: string, fn: () => Promise<void>) => Promise<void>;\n};\n\nexport type ConformanceCase = {\n name: string;\n /** Capability the case needs; a backend without it must filter the case out. */\n requires?: \"rowLock\";\n run: (ctx: ConformanceContext) => Promise<void>;\n};\n\nclass ConformanceError extends Error {}\n\nfunction assert(condition: unknown, message: string): asserts condition {\n if (!condition) throw new ConformanceError(message);\n}\n\nconst equal = (actual: unknown, expected: unknown, message: string) =>\n assert(actual === expected, `${message} (got ${String(actual)}, expected ${String(expected)})`);\n\nlet counter = 0;\nfunction uid(label: string): string {\n counter += 1;\n return `${label}_${Date.now().toString(36)}_${counter}`;\n}\n\ntype SeedOptions = {\n count?: number;\n notBefore?: Date;\n maxAttempts?: number;\n channel?: Channel;\n dedupeKey?: string;\n userId?: string;\n};\n\nasync function seed(ctx: ConformanceContext, options: SeedOptions = {}) {\n const count = options.count ?? 1;\n const userId = options.userId ?? uid(\"user\");\n\n const rows: InsertNotification[] = Array.from({ length: count }, () => {\n const id = uid(\"notif\");\n return {\n id,\n userId,\n type: \"commentReply\",\n payload: { authorName: \"Dana\" },\n ...(options.dedupeKey ? { dedupeKey: options.dedupeKey } : {}),\n deliveries: [\n {\n id: uid(\"delivery\"),\n channel: options.channel ?? \"email\",\n maxAttempts: options.maxAttempts ?? 5,\n notBefore: options.notBefore ?? new Date(Date.now() - 1000),\n },\n ],\n };\n });\n\n const result = await ctx.adapter.createNotifications(rows);\n return { userId, rows, result };\n}\n\nconst CLAIM = { limit: 10, leaseMs: 60_000 };\n\nexport const adapterConformanceCases: readonly ConformanceCase[] = [\n {\n /**\n * The case that actually distinguishes a correct adapter.\n *\n * A row locked by another transaction must be *skipped*, not waited on.\n * Without SKIP LOCKED the claim blocks until the holder commits, which on\n * a busy table serialises every worker behind the slowest one.\n */\n name: \"a row locked by another transaction is skipped, not waited on\",\n requires: \"rowLock\",\n run: async (ctx) => {\n const { lockRow } = ctx;\n assert(lockRow, \"case requires lockRow\");\n\n const { rows } = await seed(ctx, { count: 2 });\n const locked = rows[0]?.deliveries[0]?.id;\n const free = rows[1]?.deliveries[0]?.id;\n assert(locked && free, \"seed produced too few deliveries\");\n\n await lockRow(locked, async () => {\n const claimed = await Promise.race([\n ctx.adapter.claimPendingDeliveries({ ...CLAIM, claimToken: uid(\"token\") }),\n new Promise<never>((_, reject) =>\n setTimeout(\n () =>\n reject(\n new ConformanceError(\n \"claim blocked on a row locked by another transaction — SKIP LOCKED is missing\",\n ),\n ),\n 2_000,\n ),\n ),\n ]);\n\n const ids = new Set(claimed.map((row) => row.id));\n assert(!ids.has(locked), \"claimed a row locked by another transaction\");\n assert(ids.has(free), \"skipped an unlocked row alongside the locked one\");\n });\n },\n },\n\n {\n name: \"concurrent claims return disjoint sets\",\n run: async (ctx) => {\n await seed(ctx, { count: 40 });\n\n // Eight callers over 40 rows, repeated — a single Promise.all pair is\n // too fast to overlap and proves nothing on its own.\n const claimed = await Promise.all(\n Array.from({ length: 8 }, () =>\n ctx.adapter.claimPendingDeliveries({ limit: 5, leaseMs: 60_000, claimToken: uid(\"t\") }),\n ),\n );\n\n const all = claimed.flatMap((batch) => batch.map((row) => row.id));\n equal(new Set(all).size, all.length, \"the same delivery was claimed by two callers\");\n assert(all.length <= 40, \"claimed more rows than exist\");\n },\n },\n\n {\n name: \"a claimed row is invisible before its lease expires\",\n run: async (ctx) => {\n const { rows } = await seed(ctx);\n const target = rows[0]?.deliveries[0]?.id;\n\n const first = await ctx.adapter.claimPendingDeliveries({ ...CLAIM, claimToken: uid(\"t\") });\n assert(\n first.some((row) => row.id === target),\n \"seeded delivery was not claimed\",\n );\n\n const second = await ctx.adapter.claimPendingDeliveries({ ...CLAIM, claimToken: uid(\"t\") });\n assert(!second.some((row) => row.id === target), \"leased row was claimed twice\");\n },\n },\n\n {\n name: \"a claimed row is re-claimable after its lease expires\",\n run: async (ctx) => {\n const { rows } = await seed(ctx);\n const target = rows[0]?.deliveries[0]?.id;\n\n await ctx.adapter.claimPendingDeliveries({ ...CLAIM, claimToken: uid(\"t\") });\n\n const later = new Date(Date.now() + CLAIM.leaseMs + 5_000);\n const reclaimed = await ctx.adapter.claimPendingDeliveries({\n ...CLAIM,\n claimToken: uid(\"t\"),\n now: later,\n });\n\n assert(\n reclaimed.some((row) => row.id === target),\n \"expired lease was not reclaimed\",\n );\n },\n },\n\n {\n name: \"not_before in the future is never claimed\",\n run: async (ctx) => {\n const { rows } = await seed(ctx, { notBefore: new Date(Date.now() + 3_600_000) });\n const target = rows[0]?.deliveries[0]?.id;\n\n const claimed = await ctx.adapter.claimPendingDeliveries({ ...CLAIM, claimToken: uid(\"t\") });\n assert(!claimed.some((row) => row.id === target), \"claimed a delivery before its not_before\");\n },\n },\n\n {\n name: \"attempts at or beyond max_attempts is never claimed\",\n run: async (ctx) => {\n const { rows } = await seed(ctx, { maxAttempts: 3 });\n const target = rows[0]?.deliveries[0]?.id;\n assert(target, \"seed produced no delivery\");\n\n await ctx.setAttempts(target, 3);\n\n const claimed = await ctx.adapter.claimPendingDeliveries({ ...CLAIM, claimToken: uid(\"t\") });\n assert(!claimed.some((row) => row.id === target), \"claimed an exhausted delivery\");\n },\n },\n\n {\n name: \"claims are ordered by not_before ascending\",\n run: async (ctx) => {\n const userId = uid(\"user\");\n const older = uid(\"delivery\");\n const newer = uid(\"delivery\");\n\n await ctx.adapter.createNotifications([\n {\n id: uid(\"notif\"),\n userId,\n type: \"t\",\n payload: {},\n deliveries: [\n {\n id: newer,\n channel: \"email\",\n maxAttempts: 5,\n notBefore: new Date(Date.now() - 1_000),\n },\n ],\n },\n {\n id: uid(\"notif\"),\n userId,\n type: \"t\",\n payload: {},\n deliveries: [\n {\n id: older,\n channel: \"email\",\n maxAttempts: 5,\n notBefore: new Date(Date.now() - 600_000),\n },\n ],\n },\n ]);\n\n const claimed = await ctx.adapter.claimPendingDeliveries({\n limit: 1,\n leaseMs: 60_000,\n claimToken: uid(\"t\"),\n });\n\n equal(claimed[0]?.id, older, \"oldest eligible delivery was not claimed first\");\n },\n },\n\n {\n name: \"release with a stale token still writes the terminal state\",\n run: async (ctx) => {\n const { rows } = await seed(ctx);\n const target = rows[0]?.deliveries[0]?.id;\n assert(target, \"seed produced no delivery\");\n\n await ctx.adapter.claimPendingDeliveries({ ...CLAIM, claimToken: uid(\"real\") });\n\n await ctx.adapter.releaseDeliveries([\n {\n id: target,\n claimToken: \"a-token-that-never-held-this-lease\",\n outcome: { result: \"sent\" },\n },\n ]);\n\n const stillClaimable = await ctx.adapter.claimPendingDeliveries({\n ...CLAIM,\n claimToken: uid(\"t\"),\n now: new Date(Date.now() + CLAIM.leaseMs + 5_000),\n });\n\n assert(\n !stillClaimable.some((row) => row.id === target),\n \"row stayed claimable after being marked sent\",\n );\n },\n },\n\n {\n name: \"retryable failure re-arms; non-retryable fails immediately\",\n run: async (ctx) => {\n const retry = await seed(ctx, { maxAttempts: 5 });\n const retryId = retry.rows[0]?.deliveries[0]?.id;\n assert(retryId, \"seed produced no delivery\");\n\n await ctx.adapter.claimPendingDeliveries({ ...CLAIM, claimToken: uid(\"t\") });\n\n const soon = new Date(Date.now() + 30_000);\n await ctx.adapter.releaseDeliveries([\n {\n id: retryId,\n claimToken: \"t\",\n outcome: { result: \"failed\", error: \"smtp timeout\", retryable: true },\n nextAttemptAt: soon,\n },\n ]);\n\n const tooEarly = await ctx.adapter.claimPendingDeliveries({ ...CLAIM, claimToken: uid(\"t\") });\n assert(\n !tooEarly.some((row) => row.id === retryId),\n \"re-armed delivery was claimable before its backoff elapsed\",\n );\n\n const afterBackoff = await ctx.adapter.claimPendingDeliveries({\n ...CLAIM,\n claimToken: uid(\"t\"),\n now: new Date(soon.getTime() + 1_000),\n });\n assert(\n afterBackoff.some((row) => row.id === retryId),\n \"re-armed delivery never became claimable\",\n );\n\n const terminal = await seed(ctx, { maxAttempts: 5 });\n const terminalId = terminal.rows[0]?.deliveries[0]?.id;\n assert(terminalId, \"seed produced no delivery\");\n\n await ctx.adapter.claimPendingDeliveries({ ...CLAIM, claimToken: uid(\"t\") });\n await ctx.adapter.releaseDeliveries([\n {\n id: terminalId,\n claimToken: \"t\",\n outcome: { result: \"failed\", error: \"invalid api key\", retryable: false },\n },\n ]);\n\n const failed = await ctx.adapter.getFailedDeliveries({\n since: new Date(Date.now() - 60_000),\n limit: 50,\n });\n assert(\n failed.some((row) => row.id === terminalId),\n \"non-retryable failure did not land in failed\",\n );\n },\n },\n\n {\n // The whole point of the status: a delivery with nothing to do must not\n // show up in the view an operator reads to find real breakage.\n name: \"a skipped delivery is terminal and stays out of getFailedDeliveries\",\n run: async (ctx) => {\n const seeded = await seed(ctx, { maxAttempts: 5 });\n const id = seeded.rows[0]?.deliveries[0]?.id;\n assert(id, \"seed produced no delivery\");\n\n await ctx.adapter.claimPendingDeliveries({ ...CLAIM, claimToken: uid(\"t\") });\n await ctx.adapter.releaseDeliveries([\n {\n id,\n claimToken: \"t\",\n outcome: { result: \"skipped\", reason: \"no registered devices\" },\n },\n ]);\n\n const failed = await ctx.adapter.getFailedDeliveries({\n since: new Date(Date.now() - 60_000),\n limit: 50,\n });\n assert(!failed.some((row) => row.id === id), \"a skipped delivery was reported as failed\");\n\n // Terminal: it must never be handed out again, or a user with no devices\n // is retried on every sweep forever.\n const reclaimed = await ctx.adapter.claimPendingDeliveries({\n ...CLAIM,\n claimToken: uid(\"t\"),\n now: new Date(Date.now() + 3_600_000),\n });\n assert(!reclaimed.some((row) => row.id === id), \"a skipped delivery was claimed again\");\n },\n },\n\n {\n name: \"duplicate dedupeKey is skipped, not thrown\",\n run: async (ctx) => {\n const userId = uid(\"user\");\n const key = uid(\"dedupe\");\n\n const first = await seed(ctx, { userId, dedupeKey: key });\n equal(first.result.created.length, 1, \"first insert was not created\");\n\n const second = await seed(ctx, { userId, dedupeKey: key });\n equal(second.result.created.length, 0, \"duplicate was created\");\n equal(second.result.deduped.length, 1, \"duplicate was not reported as deduped\");\n },\n },\n\n {\n name: \"notifications with no dedupeKey never collide\",\n run: async (ctx) => {\n const userId = uid(\"user\");\n const result = await seed(ctx, { userId, count: 3 });\n equal(result.result.created.length, 3, \"undeduped notifications collided\");\n },\n },\n\n {\n name: \"markRead is scoped to the owning user\",\n run: async (ctx) => {\n const owner = uid(\"user\");\n const { rows } = await seed(ctx, { userId: owner });\n const notificationId = rows[0]?.id;\n assert(notificationId, \"seed produced no notification\");\n\n const stolen = await ctx.adapter.markRead(uid(\"attacker\"), [notificationId]);\n equal(stolen, 0, \"another user marked a notification read\");\n\n const own = await ctx.adapter.markRead(owner, [notificationId]);\n equal(own, 1, \"owner could not mark their own notification read\");\n },\n },\n\n {\n name: \"unseen count and markSeen agree\",\n run: async (ctx) => {\n const userId = uid(\"user\");\n await seed(ctx, { userId, count: 3 });\n\n equal(await ctx.adapter.countUnseen(userId), 3, \"unseen count wrong before markSeen\");\n\n await ctx.adapter.markSeen(userId, new Date());\n equal(await ctx.adapter.countUnseen(userId), 0, \"unseen count wrong after markSeen\");\n },\n },\n\n {\n /**\n * createdAt must come from the same clock as the cutoff it is compared to.\n *\n * An adapter that leaves createdAt to a database DEFAULT now() is comparing\n * the database clock against the application clock. On one machine they\n * agree and this never fails; in production they are different hosts, and a\n * database a second ahead means markSeen(now) silently misses the newest\n * notifications and the unseen badge never clears. Found when a laptop\n * resumed from sleep with its Docker VM 6s ahead.\n */\n name: \"createdAt comes from the caller clock, not the database clock\",\n run: async (ctx) => {\n const userId = uid(\"user\");\n const before = new Date();\n await seed(ctx, { userId, count: 1 });\n const after = new Date();\n\n const { notifications } = await ctx.adapter.listNotifications({ userId, limit: 10 });\n const createdAt = notifications[0]?.createdAt;\n assert(createdAt, \"seed produced no notification\");\n\n // A second of slack for a slow round trip, far under the skew that breaks\n // markSeen but tight enough to catch a foreign clock.\n const skewMs = Math.max(\n before.getTime() - createdAt.getTime(),\n createdAt.getTime() - after.getTime(),\n );\n assert(\n skewMs <= 1_000,\n `createdAt is ${skewMs}ms outside the window the caller observed — it is coming from another clock`,\n );\n },\n },\n];\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/testing/conformance.ts"],"names":[],"mappings":"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","file":"testing.cjs","sourcesContent":["import type { DatabaseAdapter, InsertNotification } from \"../core/adapter\";\nimport type { Channel } from \"../core/types\";\n\nexport type ConformanceContext = {\n adapter: DatabaseAdapter;\n /** Forces a delivery's attempt count; not reachable through the public API. */\n setAttempts: (deliveryId: string, attempts: number) => Promise<void>;\n /** Empties the tables. Leftover rows can push the row under test out of the claim window. */\n reset: () => Promise<void>;\n /** Holds a row lock on a separate connection for the duration of `fn`, to test SKIP LOCKED deterministically. Only where a claim can block. */\n lockRow?: (deliveryId: string, fn: () => Promise<void>) => Promise<void>;\n};\n\nexport type ConformanceCase = {\n name: string;\n /** Capability the case needs; a backend without it must filter the case out. */\n requires?: \"rowLock\";\n run: (ctx: ConformanceContext) => Promise<void>;\n};\n\nclass ConformanceError extends Error {}\n\nfunction assert(condition: unknown, message: string): asserts condition {\n if (!condition) throw new ConformanceError(message);\n}\n\nconst equal = (actual: unknown, expected: unknown, message: string) =>\n assert(actual === expected, `${message} (got ${String(actual)}, expected ${String(expected)})`);\n\nlet counter = 0;\nfunction uid(label: string): string {\n counter += 1;\n return `${label}_${Date.now().toString(36)}_${counter}`;\n}\n\ntype SeedOptions = {\n count?: number;\n notBefore?: Date;\n maxAttempts?: number;\n channel?: Channel;\n dedupeKey?: string;\n userId?: string;\n};\n\nasync function seed(ctx: ConformanceContext, options: SeedOptions = {}) {\n const count = options.count ?? 1;\n const userId = options.userId ?? uid(\"user\");\n\n const rows: InsertNotification[] = Array.from({ length: count }, () => {\n const id = uid(\"notif\");\n return {\n id,\n userId,\n type: \"commentReply\",\n payload: { authorName: \"Dana\" },\n ...(options.dedupeKey ? { dedupeKey: options.dedupeKey } : {}),\n deliveries: [\n {\n id: uid(\"delivery\"),\n channel: options.channel ?? \"email\",\n maxAttempts: options.maxAttempts ?? 5,\n notBefore: options.notBefore ?? new Date(Date.now() - 1000),\n },\n ],\n };\n });\n\n const result = await ctx.adapter.createNotifications(rows);\n return { userId, rows, result };\n}\n\nconst CLAIM = { limit: 10, leaseMs: 60_000 };\n\nexport const adapterConformanceCases: readonly ConformanceCase[] = [\n {\n /** A row locked by another transaction must be skipped, not waited on. */\n name: \"a row locked by another transaction is skipped, not waited on\",\n requires: \"rowLock\",\n run: async (ctx) => {\n const { lockRow } = ctx;\n assert(lockRow, \"case requires lockRow\");\n\n const { rows } = await seed(ctx, { count: 2 });\n const locked = rows[0]?.deliveries[0]?.id;\n const free = rows[1]?.deliveries[0]?.id;\n assert(locked && free, \"seed produced too few deliveries\");\n\n await lockRow(locked, async () => {\n const claimed = await Promise.race([\n ctx.adapter.claimPendingDeliveries({ ...CLAIM, claimToken: uid(\"token\") }),\n new Promise<never>((_, reject) =>\n setTimeout(\n () =>\n reject(\n new ConformanceError(\n \"claim blocked on a row locked by another transaction — SKIP LOCKED is missing\",\n ),\n ),\n 2_000,\n ),\n ),\n ]);\n\n const ids = new Set(claimed.map((row) => row.id));\n assert(!ids.has(locked), \"claimed a row locked by another transaction\");\n assert(ids.has(free), \"skipped an unlocked row alongside the locked one\");\n });\n },\n },\n\n {\n name: \"concurrent claims return disjoint sets\",\n run: async (ctx) => {\n await seed(ctx, { count: 40 });\n\n // Eight callers over 40 rows; a single pair is too fast to overlap.\n const claimed = await Promise.all(\n Array.from({ length: 8 }, () =>\n ctx.adapter.claimPendingDeliveries({ limit: 5, leaseMs: 60_000, claimToken: uid(\"t\") }),\n ),\n );\n\n const all = claimed.flatMap((batch) => batch.map((row) => row.id));\n equal(new Set(all).size, all.length, \"the same delivery was claimed by two callers\");\n assert(all.length <= 40, \"claimed more rows than exist\");\n },\n },\n\n {\n name: \"a claimed row is invisible before its lease expires\",\n run: async (ctx) => {\n const { rows } = await seed(ctx);\n const target = rows[0]?.deliveries[0]?.id;\n\n const first = await ctx.adapter.claimPendingDeliveries({ ...CLAIM, claimToken: uid(\"t\") });\n assert(\n first.some((row) => row.id === target),\n \"seeded delivery was not claimed\",\n );\n\n const second = await ctx.adapter.claimPendingDeliveries({ ...CLAIM, claimToken: uid(\"t\") });\n assert(!second.some((row) => row.id === target), \"leased row was claimed twice\");\n },\n },\n\n {\n name: \"a claimed row is re-claimable after its lease expires\",\n run: async (ctx) => {\n const { rows } = await seed(ctx);\n const target = rows[0]?.deliveries[0]?.id;\n\n await ctx.adapter.claimPendingDeliveries({ ...CLAIM, claimToken: uid(\"t\") });\n\n const later = new Date(Date.now() + CLAIM.leaseMs + 5_000);\n const reclaimed = await ctx.adapter.claimPendingDeliveries({\n ...CLAIM,\n claimToken: uid(\"t\"),\n now: later,\n });\n\n assert(\n reclaimed.some((row) => row.id === target),\n \"expired lease was not reclaimed\",\n );\n },\n },\n\n {\n name: \"not_before in the future is never claimed\",\n run: async (ctx) => {\n const { rows } = await seed(ctx, { notBefore: new Date(Date.now() + 3_600_000) });\n const target = rows[0]?.deliveries[0]?.id;\n\n const claimed = await ctx.adapter.claimPendingDeliveries({ ...CLAIM, claimToken: uid(\"t\") });\n assert(!claimed.some((row) => row.id === target), \"claimed a delivery before its not_before\");\n },\n },\n\n {\n name: \"attempts at or beyond max_attempts is never claimed\",\n run: async (ctx) => {\n const { rows } = await seed(ctx, { maxAttempts: 3 });\n const target = rows[0]?.deliveries[0]?.id;\n assert(target, \"seed produced no delivery\");\n\n await ctx.setAttempts(target, 3);\n\n const claimed = await ctx.adapter.claimPendingDeliveries({ ...CLAIM, claimToken: uid(\"t\") });\n assert(!claimed.some((row) => row.id === target), \"claimed an exhausted delivery\");\n },\n },\n\n {\n name: \"claims are ordered by not_before ascending\",\n run: async (ctx) => {\n const userId = uid(\"user\");\n const older = uid(\"delivery\");\n const newer = uid(\"delivery\");\n\n await ctx.adapter.createNotifications([\n {\n id: uid(\"notif\"),\n userId,\n type: \"t\",\n payload: {},\n deliveries: [\n {\n id: newer,\n channel: \"email\",\n maxAttempts: 5,\n notBefore: new Date(Date.now() - 1_000),\n },\n ],\n },\n {\n id: uid(\"notif\"),\n userId,\n type: \"t\",\n payload: {},\n deliveries: [\n {\n id: older,\n channel: \"email\",\n maxAttempts: 5,\n notBefore: new Date(Date.now() - 600_000),\n },\n ],\n },\n ]);\n\n const claimed = await ctx.adapter.claimPendingDeliveries({\n limit: 1,\n leaseMs: 60_000,\n claimToken: uid(\"t\"),\n });\n\n equal(claimed[0]?.id, older, \"oldest eligible delivery was not claimed first\");\n },\n },\n\n {\n name: \"release with a stale token still writes the terminal state\",\n run: async (ctx) => {\n const { rows } = await seed(ctx);\n const target = rows[0]?.deliveries[0]?.id;\n assert(target, \"seed produced no delivery\");\n\n await ctx.adapter.claimPendingDeliveries({ ...CLAIM, claimToken: uid(\"real\") });\n\n await ctx.adapter.releaseDeliveries([\n {\n id: target,\n claimToken: \"a-token-that-never-held-this-lease\",\n outcome: { result: \"sent\" },\n },\n ]);\n\n const stillClaimable = await ctx.adapter.claimPendingDeliveries({\n ...CLAIM,\n claimToken: uid(\"t\"),\n now: new Date(Date.now() + CLAIM.leaseMs + 5_000),\n });\n\n assert(\n !stillClaimable.some((row) => row.id === target),\n \"row stayed claimable after being marked sent\",\n );\n },\n },\n\n {\n name: \"retryable failure re-arms; non-retryable fails immediately\",\n run: async (ctx) => {\n const retry = await seed(ctx, { maxAttempts: 5 });\n const retryId = retry.rows[0]?.deliveries[0]?.id;\n assert(retryId, \"seed produced no delivery\");\n\n await ctx.adapter.claimPendingDeliveries({ ...CLAIM, claimToken: uid(\"t\") });\n\n const soon = new Date(Date.now() + 30_000);\n await ctx.adapter.releaseDeliveries([\n {\n id: retryId,\n claimToken: \"t\",\n outcome: { result: \"failed\", error: \"smtp timeout\", retryable: true },\n nextAttemptAt: soon,\n },\n ]);\n\n const tooEarly = await ctx.adapter.claimPendingDeliveries({ ...CLAIM, claimToken: uid(\"t\") });\n assert(\n !tooEarly.some((row) => row.id === retryId),\n \"re-armed delivery was claimable before its backoff elapsed\",\n );\n\n const afterBackoff = await ctx.adapter.claimPendingDeliveries({\n ...CLAIM,\n claimToken: uid(\"t\"),\n now: new Date(soon.getTime() + 1_000),\n });\n assert(\n afterBackoff.some((row) => row.id === retryId),\n \"re-armed delivery never became claimable\",\n );\n\n const terminal = await seed(ctx, { maxAttempts: 5 });\n const terminalId = terminal.rows[0]?.deliveries[0]?.id;\n assert(terminalId, \"seed produced no delivery\");\n\n await ctx.adapter.claimPendingDeliveries({ ...CLAIM, claimToken: uid(\"t\") });\n await ctx.adapter.releaseDeliveries([\n {\n id: terminalId,\n claimToken: \"t\",\n outcome: { result: \"failed\", error: \"invalid api key\", retryable: false },\n },\n ]);\n\n const failed = await ctx.adapter.getFailedDeliveries({\n since: new Date(Date.now() - 60_000),\n limit: 50,\n });\n assert(\n failed.some((row) => row.id === terminalId),\n \"non-retryable failure did not land in failed\",\n );\n },\n },\n\n {\n // A delivery with nothing to do must stay out of the failure view.\n name: \"a skipped delivery is terminal and stays out of getFailedDeliveries\",\n run: async (ctx) => {\n const seeded = await seed(ctx, { maxAttempts: 5 });\n const id = seeded.rows[0]?.deliveries[0]?.id;\n assert(id, \"seed produced no delivery\");\n\n await ctx.adapter.claimPendingDeliveries({ ...CLAIM, claimToken: uid(\"t\") });\n await ctx.adapter.releaseDeliveries([\n {\n id,\n claimToken: \"t\",\n outcome: { result: \"skipped\", reason: \"no registered devices\" },\n },\n ]);\n\n const failed = await ctx.adapter.getFailedDeliveries({\n since: new Date(Date.now() - 60_000),\n limit: 50,\n });\n assert(!failed.some((row) => row.id === id), \"a skipped delivery was reported as failed\");\n\n // Terminal: never handed out again.\n const reclaimed = await ctx.adapter.claimPendingDeliveries({\n ...CLAIM,\n claimToken: uid(\"t\"),\n now: new Date(Date.now() + 3_600_000),\n });\n assert(!reclaimed.some((row) => row.id === id), \"a skipped delivery was claimed again\");\n },\n },\n\n {\n name: \"duplicate dedupeKey is skipped, not thrown\",\n run: async (ctx) => {\n const userId = uid(\"user\");\n const key = uid(\"dedupe\");\n\n const first = await seed(ctx, { userId, dedupeKey: key });\n equal(first.result.created.length, 1, \"first insert was not created\");\n\n const second = await seed(ctx, { userId, dedupeKey: key });\n equal(second.result.created.length, 0, \"duplicate was created\");\n equal(second.result.deduped.length, 1, \"duplicate was not reported as deduped\");\n },\n },\n\n {\n name: \"notifications with no dedupeKey never collide\",\n run: async (ctx) => {\n const userId = uid(\"user\");\n const result = await seed(ctx, { userId, count: 3 });\n equal(result.result.created.length, 3, \"undeduped notifications collided\");\n },\n },\n\n {\n name: \"markRead is scoped to the owning user\",\n run: async (ctx) => {\n const owner = uid(\"user\");\n const { rows } = await seed(ctx, { userId: owner });\n const notificationId = rows[0]?.id;\n assert(notificationId, \"seed produced no notification\");\n\n const stolen = await ctx.adapter.markRead(uid(\"attacker\"), [notificationId]);\n equal(stolen, 0, \"another user marked a notification read\");\n\n const own = await ctx.adapter.markRead(owner, [notificationId]);\n equal(own, 1, \"owner could not mark their own notification read\");\n },\n },\n\n {\n name: \"unseen count and markSeen agree\",\n run: async (ctx) => {\n const userId = uid(\"user\");\n await seed(ctx, { userId, count: 3 });\n\n equal(await ctx.adapter.countUnseen(userId), 3, \"unseen count wrong before markSeen\");\n\n await ctx.adapter.markSeen(userId, new Date());\n equal(await ctx.adapter.countUnseen(userId), 0, \"unseen count wrong after markSeen\");\n },\n },\n\n {\n // createdAt must come from the same clock as the cutoffs it is compared to; a database DEFAULT now() breaks markSeen under NTP skew.\n name: \"createdAt comes from the caller clock, not the database clock\",\n run: async (ctx) => {\n const userId = uid(\"user\");\n const before = new Date();\n await seed(ctx, { userId, count: 1 });\n const after = new Date();\n\n const { notifications } = await ctx.adapter.listNotifications({ userId, limit: 10 });\n const createdAt = notifications[0]?.createdAt;\n assert(createdAt, \"seed produced no notification\");\n\n // A second of slack for a slow round trip.\n const skewMs = Math.max(\n before.getTime() - createdAt.getTime(),\n createdAt.getTime() - after.getTime(),\n );\n assert(\n skewMs <= 1_000,\n `createdAt is ${skewMs}ms outside the window the caller observed — it is coming from another clock`,\n );\n },\n },\n];\n"]}
|
package/dist/testing.d.cts
CHANGED
|
@@ -1,30 +1,12 @@
|
|
|
1
|
-
import { D as DatabaseAdapter } from './adapter-
|
|
1
|
+
import { D as DatabaseAdapter } from './adapter-D3lTy-4E.cjs';
|
|
2
2
|
|
|
3
3
|
type ConformanceContext = {
|
|
4
4
|
adapter: DatabaseAdapter;
|
|
5
|
-
/**
|
|
6
|
-
* Forces a delivery's attempt count. Not reachable through the public API —
|
|
7
|
-
* the adapter would have marked the row failed on the way there — so each
|
|
8
|
-
* backend writes it directly.
|
|
9
|
-
*/
|
|
5
|
+
/** Forces a delivery's attempt count; not reachable through the public API. */
|
|
10
6
|
setAttempts: (deliveryId: string, attempts: number) => Promise<void>;
|
|
11
|
-
/**
|
|
12
|
-
* Empties the tables. Cases must run against a clean table: claims are
|
|
13
|
-
* ordered by not_before ASC and bounded by limit, so leftover rows from an
|
|
14
|
-
* earlier case can push the row under test out of the claim window.
|
|
15
|
-
*/
|
|
7
|
+
/** Empties the tables. Leftover rows can push the row under test out of the claim window. */
|
|
16
8
|
reset: () => Promise<void>;
|
|
17
|
-
/**
|
|
18
|
-
* Holds a row lock on a separate connection for the duration of `fn`.
|
|
19
|
-
*
|
|
20
|
-
* Required to test SKIP LOCKED deterministically. Two Promise.all'd claims
|
|
21
|
-
* do not reliably overlap — they complete in single-digit milliseconds and
|
|
22
|
-
* simply queue — so a race-based test passes even with no locking at all.
|
|
23
|
-
*
|
|
24
|
-
* Only meaningful where a claim can block on someone else's lock. A document
|
|
25
|
-
* store whose claim is a single atomic update has nothing to skip, so cases
|
|
26
|
-
* tagged `rowLock` do not apply to it.
|
|
27
|
-
*/
|
|
9
|
+
/** Holds a row lock on a separate connection for the duration of `fn`, to test SKIP LOCKED deterministically. Only where a claim can block. */
|
|
28
10
|
lockRow?: (deliveryId: string, fn: () => Promise<void>) => Promise<void>;
|
|
29
11
|
};
|
|
30
12
|
type ConformanceCase = {
|
package/dist/testing.d.ts
CHANGED
|
@@ -1,30 +1,12 @@
|
|
|
1
|
-
import { D as DatabaseAdapter } from './adapter-
|
|
1
|
+
import { D as DatabaseAdapter } from './adapter-D3lTy-4E.js';
|
|
2
2
|
|
|
3
3
|
type ConformanceContext = {
|
|
4
4
|
adapter: DatabaseAdapter;
|
|
5
|
-
/**
|
|
6
|
-
* Forces a delivery's attempt count. Not reachable through the public API —
|
|
7
|
-
* the adapter would have marked the row failed on the way there — so each
|
|
8
|
-
* backend writes it directly.
|
|
9
|
-
*/
|
|
5
|
+
/** Forces a delivery's attempt count; not reachable through the public API. */
|
|
10
6
|
setAttempts: (deliveryId: string, attempts: number) => Promise<void>;
|
|
11
|
-
/**
|
|
12
|
-
* Empties the tables. Cases must run against a clean table: claims are
|
|
13
|
-
* ordered by not_before ASC and bounded by limit, so leftover rows from an
|
|
14
|
-
* earlier case can push the row under test out of the claim window.
|
|
15
|
-
*/
|
|
7
|
+
/** Empties the tables. Leftover rows can push the row under test out of the claim window. */
|
|
16
8
|
reset: () => Promise<void>;
|
|
17
|
-
/**
|
|
18
|
-
* Holds a row lock on a separate connection for the duration of `fn`.
|
|
19
|
-
*
|
|
20
|
-
* Required to test SKIP LOCKED deterministically. Two Promise.all'd claims
|
|
21
|
-
* do not reliably overlap — they complete in single-digit milliseconds and
|
|
22
|
-
* simply queue — so a race-based test passes even with no locking at all.
|
|
23
|
-
*
|
|
24
|
-
* Only meaningful where a claim can block on someone else's lock. A document
|
|
25
|
-
* store whose claim is a single atomic update has nothing to skip, so cases
|
|
26
|
-
* tagged `rowLock` do not apply to it.
|
|
27
|
-
*/
|
|
9
|
+
/** Holds a row lock on a separate connection for the duration of `fn`, to test SKIP LOCKED deterministically. Only where a claim can block. */
|
|
28
10
|
lockRow?: (deliveryId: string, fn: () => Promise<void>) => Promise<void>;
|
|
29
11
|
};
|
|
30
12
|
type ConformanceCase = {
|
package/dist/testing.js
CHANGED
|
@@ -37,13 +37,7 @@ async function seed(ctx, options = {}) {
|
|
|
37
37
|
var CLAIM = { limit: 10, leaseMs: 6e4 };
|
|
38
38
|
var adapterConformanceCases = [
|
|
39
39
|
{
|
|
40
|
-
/**
|
|
41
|
-
* The case that actually distinguishes a correct adapter.
|
|
42
|
-
*
|
|
43
|
-
* A row locked by another transaction must be *skipped*, not waited on.
|
|
44
|
-
* Without SKIP LOCKED the claim blocks until the holder commits, which on
|
|
45
|
-
* a busy table serialises every worker behind the slowest one.
|
|
46
|
-
*/
|
|
40
|
+
/** A row locked by another transaction must be skipped, not waited on. */
|
|
47
41
|
name: "a row locked by another transaction is skipped, not waited on",
|
|
48
42
|
requires: "rowLock",
|
|
49
43
|
run: async (ctx) => {
|
|
@@ -261,8 +255,7 @@ var adapterConformanceCases = [
|
|
|
261
255
|
}
|
|
262
256
|
},
|
|
263
257
|
{
|
|
264
|
-
//
|
|
265
|
-
// show up in the view an operator reads to find real breakage.
|
|
258
|
+
// A delivery with nothing to do must stay out of the failure view.
|
|
266
259
|
name: "a skipped delivery is terminal and stays out of getFailedDeliveries",
|
|
267
260
|
run: async (ctx) => {
|
|
268
261
|
const seeded = await seed(ctx, { maxAttempts: 5 });
|
|
@@ -333,16 +326,7 @@ var adapterConformanceCases = [
|
|
|
333
326
|
}
|
|
334
327
|
},
|
|
335
328
|
{
|
|
336
|
-
|
|
337
|
-
* createdAt must come from the same clock as the cutoff it is compared to.
|
|
338
|
-
*
|
|
339
|
-
* An adapter that leaves createdAt to a database DEFAULT now() is comparing
|
|
340
|
-
* the database clock against the application clock. On one machine they
|
|
341
|
-
* agree and this never fails; in production they are different hosts, and a
|
|
342
|
-
* database a second ahead means markSeen(now) silently misses the newest
|
|
343
|
-
* notifications and the unseen badge never clears. Found when a laptop
|
|
344
|
-
* resumed from sleep with its Docker VM 6s ahead.
|
|
345
|
-
*/
|
|
329
|
+
// createdAt must come from the same clock as the cutoffs it is compared to; a database DEFAULT now() breaks markSeen under NTP skew.
|
|
346
330
|
name: "createdAt comes from the caller clock, not the database clock",
|
|
347
331
|
run: async (ctx) => {
|
|
348
332
|
const userId = uid("user");
|