@fjall/util 8.0.0 → 9.0.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/dist/.build-source-hash
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"package.json",
|
|
10
10
|
"tsconfig.json"
|
|
11
11
|
],
|
|
12
|
-
"hash": "
|
|
12
|
+
"hash": "45c0c260a70c536ef2d05997781c8ccc49866ce559e8d6940f58f9f092c5f250",
|
|
13
13
|
"files": {
|
|
14
14
|
"src/async/concurrency.ts": "3c7ebe0222a720f9",
|
|
15
15
|
"src/async/singleton.ts": "7bcc21b0fb920561",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"src/migration/index.ts": "de586c9d775b3174",
|
|
82
82
|
"src/migration/pickLatestClickHouseMigration.ts": "a5b4a00ba63522cb",
|
|
83
83
|
"src/migration/pickLatestPrismaMigration.ts": "cbddc2950f4d4c85",
|
|
84
|
-
"src/migration/verifyExpectedSchemaVersion.ts": "
|
|
84
|
+
"src/migration/verifyExpectedSchemaVersion.ts": "cd583329d771a047",
|
|
85
85
|
"src/naming/accountNameCollision.ts": "2dc8b278ff039220",
|
|
86
86
|
"src/naming/caseConversion.ts": "8b8984f2b58b8ab7",
|
|
87
87
|
"src/naming/connectedAccountName.ts": "3cd3bc7dba0a2f0b",
|
|
@@ -103,9 +103,9 @@
|
|
|
103
103
|
"src/securityHelpers.ts": "ee2ab9ffd53119fb",
|
|
104
104
|
"src/targets.ts": "126280f0a5762e21",
|
|
105
105
|
"../scripts/minify-dist.mjs": "6b2e4b0df8aec601",
|
|
106
|
-
"package.json": "
|
|
106
|
+
"package.json": "de20bfd9ecd3a130",
|
|
107
107
|
"tsconfig.json": "db759831ad95f396"
|
|
108
108
|
},
|
|
109
|
-
"outputHash": "
|
|
109
|
+
"outputHash": "d92d1ce1a95c7c760cdd03cefa7cd594c041bb5c0768c96a6806c9d703b6456b",
|
|
110
110
|
"outputFileCount": 189
|
|
111
111
|
}
|
package/dist/.minified
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
94 files minified at 2026-08-
|
|
1
|
+
94 files minified at 2026-08-09T10:16:53.310Z
|
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Tool-discriminated boot-time gate: verify a relational database's
|
|
3
|
-
*
|
|
4
|
-
* deployed image. Companion to {@link pickLatestPrismaMigration} (which
|
|
2
|
+
* Tool-discriminated boot-time gate: verify a relational database's
|
|
3
|
+
* latest-by-name applied migration matches the expected version baked into
|
|
4
|
+
* the deployed image. Companion to {@link pickLatestPrismaMigration} (which
|
|
5
5
|
* resolves the expected version FROM disk at synth/runner time); this
|
|
6
6
|
* helper closes the loop by reading what the DB actually has APPLIED.
|
|
7
7
|
*
|
|
8
|
+
* "Latest" MUST mean lexicographic max of migration_name, mirroring
|
|
9
|
+
* pickLatestPrismaMigration — NOT most recently finished. Prisma's
|
|
10
|
+
* `migrate deploy` applies a pending migration even when it name-sorts
|
|
11
|
+
* before already-applied ones (parallel branches landing interleaved
|
|
12
|
+
* timestamps), so latest-by-finished_at can be an OLDER name than what the
|
|
13
|
+
* schema actually satisfies, false-failing the gate against a complete DB.
|
|
14
|
+
*
|
|
8
15
|
* Consumer supplies the driver via the {@link MigrationsSqlClient} shim so
|
|
9
16
|
* the package stays driver-agnostic (pg, mysql2, postgres.js, Drizzle
|
|
10
17
|
* session, raw Prisma `$queryRawUnsafe`, …). The shim's single `query(sql)`
|
|
11
18
|
* surface is intentionally narrower than any real driver — callers wrap.
|
|
12
19
|
*
|
|
13
20
|
* Two tool branches today:
|
|
14
|
-
* - `tool: "prisma"` reads `_prisma_migrations.migration_name` (
|
|
15
|
-
* `finished_at IS NOT NULL`). Stable across all Prisma DB engines.
|
|
21
|
+
* - `tool: "prisma"` reads `_prisma_migrations.migration_name` (max name
|
|
22
|
+
* among `finished_at IS NOT NULL`). Stable across all Prisma DB engines.
|
|
16
23
|
* - `tool: "custom"` lets a caller pass a `{ sql, column }` pair when the
|
|
17
24
|
* migration tool's metadata table doesn't match the Prisma shape (e.g.
|
|
18
25
|
* Drizzle's `__drizzle_migrations.hash`, Knex's `knex_migrations.name`).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var a=Object.defineProperty;var c=(e,r)=>a(e,"name",{value:r,configurable:!0});import{isSchemaVersionSatisfied as s}from"./compareSchemaVersion.js";const u="SELECT migration_name FROM _prisma_migrations WHERE finished_at IS NOT NULL ORDER BY migration_name DESC LIMIT 1",m="migration_name";async function E(e){if(e.signal?.aborted)throw new Error("verifyExpectedSchemaVersion: aborted by signal before query");let r,n;if(e.tool==="prisma")r=u,n=m;else if(e.tool==="custom"){if(e.customQuery===void 0)throw new Error('verifyExpectedSchemaVersion: tool="custom" requires customQuery');r=e.customQuery.sql,n=e.customQuery.column}else throw new Error(`verifyExpectedSchemaVersion: unknown tool ${String(e.tool)}`);const i=(await e.client.query(r)).rows[0],o=i!==void 0?i[n]:void 0,t=typeof o=="string"?o:null;return{matches:t!==null&&s(e.expected,t),expected:e.expected,actual:t}}c(E,"verifyExpectedSchemaVersion");export{E as verifyExpectedSchemaVersion};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var d=Object.defineProperty;var
|
|
1
|
+
var d=Object.defineProperty;var c=(e,t)=>d(e,"name",{value:t,configurable:!0});import{describe as r,expect as a,it as o,vi as u}from"vitest";import{verifyExpectedSchemaVersion as n}from"./verifyExpectedSchemaVersion.js";function i(e){const t=[];return{client:{query:u.fn(async l=>(t.push(l),{rows:e}))},queries:t}}c(i,"makeMockClient"),r("verifyExpectedSchemaVersion",()=>{r('tool: "prisma"',()=>{o("returns matches=true when actual === expected",async()=>{const{client:e,queries:t}=i([{migration_name:"20260520000000_add_widgets"}]),s=await n({tool:"prisma",expected:"20260520000000_add_widgets",client:e});a(s).toEqual({matches:!0,expected:"20260520000000_add_widgets",actual:"20260520000000_add_widgets"}),a(t).toHaveLength(1),a(t[0]).toContain("_prisma_migrations"),a(t[0]).toContain("finished_at IS NOT NULL"),a(t[0]).toContain("ORDER BY migration_name DESC LIMIT 1")}),o("orders by migration_name, not finished_at (out-of-order application)",async()=>{const{client:e,queries:t}=i([{migration_name:"20260809140000_drop_admin_plugin_columns"}]),s=await n({tool:"prisma",expected:"20260809140000_drop_admin_plugin_columns",client:e});a(s.matches).toBe(!0),a(t[0]).not.toContain("ORDER BY finished_at"),a(t[0]).toContain("ORDER BY migration_name DESC LIMIT 1")}),o("returns matches=false with actual when DB trails image",async()=>{const{client:e}=i([{migration_name:"20260519000000_old"}]),t=await n({tool:"prisma",expected:"20260520000000_add_widgets",client:e});a(t).toEqual({matches:!1,expected:"20260520000000_add_widgets",actual:"20260519000000_old"})}),o("returns matches=true when DB is AHEAD (expand-only rollback)",async()=>{const{client:e}=i([{migration_name:"20260521000000_add_more_widgets"}]),t=await n({tool:"prisma",expected:"20260520000000_add_widgets",client:e});a(t).toEqual({matches:!0,expected:"20260520000000_add_widgets",actual:"20260521000000_add_more_widgets"})}),o("returns actual=null on empty result set",async()=>{const{client:e}=i([]),t=await n({tool:"prisma",expected:"20260520000000_add_widgets",client:e});a(t).toEqual({matches:!1,expected:"20260520000000_add_widgets",actual:null})}),o("returns actual=null when row's migration_name is not a string",async()=>{const{client:e}=i([{migration_name:12345}]),t=await n({tool:"prisma",expected:"x",client:e});a(t.actual).toBeNull(),a(t.matches).toBe(!1)})}),r('tool: "custom"',()=>{o("uses customQuery sql and column",async()=>{const{client:e,queries:t}=i([{hash:"deadbeef"}]),s=await n({tool:"custom",expected:"deadbeef",client:e,customQuery:{sql:"SELECT hash FROM __drizzle_migrations ORDER BY created_at DESC LIMIT 1",column:"hash"}});a(s.matches).toBe(!0),a(s.actual).toBe("deadbeef"),a(t[0]).toBe("SELECT hash FROM __drizzle_migrations ORDER BY created_at DESC LIMIT 1")}),o("stays strict for non-orderable versions even when actual sorts later",async()=>{const{client:e}=i([{hash:"ffffffff"}]),t=await n({tool:"custom",expected:"00000000",client:e,customQuery:{sql:"SELECT hash FROM __drizzle_migrations ORDER BY created_at DESC LIMIT 1",column:"hash"}});a(t.matches).toBe(!1),a(t.actual).toBe("ffffffff")}),o("throws when customQuery is omitted",async()=>{const{client:e}=i([]);await a(n({tool:"custom",expected:"x",client:e})).rejects.toThrow(/tool="custom" requires customQuery/)})}),r("abort signal",()=>{o("short-circuits before query when signal is already aborted",async()=>{const{client:e,queries:t}=i([{migration_name:"irrelevant"}]),s=new AbortController;s.abort(),await a(n({tool:"prisma",expected:"x",client:e,signal:s.signal})).rejects.toThrow(/aborted by signal before query/),a(t).toEqual([])})})});
|