@prisma-next-idb/target-idb 0.1.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/LICENSE +21 -0
- package/dist/apply-ddl-op-DZAoihY0.d.mts +129 -0
- package/dist/apply-ddl-op-DZAoihY0.d.mts.map +1 -0
- package/dist/apply-ddl-op-LP-l0o4O.mjs +232 -0
- package/dist/apply-ddl-op-LP-l0o4O.mjs.map +1 -0
- package/dist/control.d.mts +33 -0
- package/dist/control.d.mts.map +1 -0
- package/dist/control.mjs +44 -0
- package/dist/control.mjs.map +1 -0
- package/dist/descriptor-meta-CKLekROR.mjs +237 -0
- package/dist/descriptor-meta-CKLekROR.mjs.map +1 -0
- package/dist/idb-contract-types-DndrdtW0.d.mts +111 -0
- package/dist/idb-contract-types-DndrdtW0.d.mts.map +1 -0
- package/dist/migration-B43yOFXO.d.mts +227 -0
- package/dist/migration-B43yOFXO.d.mts.map +1 -0
- package/dist/migration-driver-4T8Hk1vu.mjs +334 -0
- package/dist/migration-driver-4T8Hk1vu.mjs.map +1 -0
- package/dist/migration.d.mts +3 -0
- package/dist/migration.mjs +89 -0
- package/dist/migration.mjs.map +1 -0
- package/dist/pack.d.mts +104 -0
- package/dist/pack.d.mts.map +1 -0
- package/dist/pack.mjs +7 -0
- package/dist/pack.mjs.map +1 -0
- package/dist/runtime.d.mts +20 -0
- package/dist/runtime.d.mts.map +1 -0
- package/dist/runtime.mjs +16 -0
- package/dist/runtime.mjs.map +1 -0
- package/package.json +57 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Prisma IDB
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { a as IdbIndexDefinition, u as IdbStoreDefinition } from "./idb-contract-types-DndrdtW0.mjs";
|
|
2
|
+
import { MigrationPlanOperation } from "@prisma-next/framework-components/control";
|
|
3
|
+
import { ContractMarkerRecord } from "@prisma-next/contract/types";
|
|
4
|
+
|
|
5
|
+
//#region src/core/migration-factories.d.ts
|
|
6
|
+
/** DDL operation that creates a new object store. Always `additive`. */
|
|
7
|
+
type CreateObjectStoreOp = MigrationPlanOperation & {
|
|
8
|
+
readonly kind: "createObjectStore";
|
|
9
|
+
readonly storeName: string;
|
|
10
|
+
readonly def: IdbStoreDefinition;
|
|
11
|
+
};
|
|
12
|
+
/** DDL operation that drops an existing object store and all its indexes. Always `destructive`. */
|
|
13
|
+
type DropObjectStoreOp = MigrationPlanOperation & {
|
|
14
|
+
readonly kind: "dropObjectStore";
|
|
15
|
+
readonly storeName: string;
|
|
16
|
+
};
|
|
17
|
+
/** DDL operation that creates a secondary index on an object store. Always `additive`. */
|
|
18
|
+
type CreateIndexOp = MigrationPlanOperation & {
|
|
19
|
+
readonly kind: "createIndex";
|
|
20
|
+
readonly storeName: string;
|
|
21
|
+
readonly indexName: string;
|
|
22
|
+
readonly def: IdbIndexDefinition;
|
|
23
|
+
};
|
|
24
|
+
/** DDL operation that drops a secondary index from an object store. Always `destructive`. */
|
|
25
|
+
type DropIndexOp = MigrationPlanOperation & {
|
|
26
|
+
readonly kind: "dropIndex";
|
|
27
|
+
readonly storeName: string;
|
|
28
|
+
readonly indexName: string;
|
|
29
|
+
};
|
|
30
|
+
/** Union of all IDB DDL plan operations. */
|
|
31
|
+
type IdbDdlOp = CreateObjectStoreOp | DropObjectStoreOp | CreateIndexOp | DropIndexOp;
|
|
32
|
+
/** Returns `true` if `op` is one of the four IDB DDL op kinds. */
|
|
33
|
+
declare function isIdbDdlOp(op: MigrationPlanOperation): op is IdbDdlOp;
|
|
34
|
+
declare function createObjectStoreOp(storeName: string, def: IdbStoreDefinition): CreateObjectStoreOp;
|
|
35
|
+
declare function dropObjectStoreOp(storeName: string): DropObjectStoreOp;
|
|
36
|
+
declare function createIndexOp(storeName: string, indexName: string, def: IdbIndexDefinition): CreateIndexOp;
|
|
37
|
+
declare function dropIndexOp(storeName: string, indexName: string): DropIndexOp;
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/core/apply-ddl-op.d.ts
|
|
40
|
+
/**
|
|
41
|
+
* Execute a single DDL operation against an open `upgradeneeded` transaction.
|
|
42
|
+
*
|
|
43
|
+
* All IndexedDB DDL (createObjectStore, deleteObjectStore, createIndex,
|
|
44
|
+
* deleteIndex) MUST happen inside the version-change transaction that fires
|
|
45
|
+
* in `upgradeneeded`. The `db` and `tx` references are valid only for the
|
|
46
|
+
* duration of that callback.
|
|
47
|
+
*
|
|
48
|
+
* Shared by the runner (target-idb), the browser auto-migrate path
|
|
49
|
+
* (client-idb), and the preflight CLI (family-idb) so all three apply paths
|
|
50
|
+
* use a single, byte-identical implementation.
|
|
51
|
+
*
|
|
52
|
+
* **Idempotency.** Each op is guarded by an existence check so re-applying an
|
|
53
|
+
* already-applied op is a no-op rather than a throw. This is the load-bearing
|
|
54
|
+
* guarantee behind the two-phase marker write (ADR 002): if a tab is killed in
|
|
55
|
+
* the window between the version-change transaction committing and the marker
|
|
56
|
+
* `put` landing, the schema is advanced but the marker still points at the old
|
|
57
|
+
* hash. On the next open, the chain walk re-collects the already-applied ops
|
|
58
|
+
* and replays them here. Without the guards, `createObjectStore` /
|
|
59
|
+
* `createIndex` throw `ConstraintError` on the existing store/index, the
|
|
60
|
+
* version-change transaction aborts, and the database is permanently wedged
|
|
61
|
+
* (every subsequent open repeats the failed upgrade). Contrary to a common
|
|
62
|
+
* assumption, IndexedDB itself offers **no** "already exists" tolerance — these
|
|
63
|
+
* guards are what make replay safe. (Was PLAN Issue #25.)
|
|
64
|
+
*/
|
|
65
|
+
declare function applyOneDdlOp(db: IDBDatabase, tx: IDBTransaction, op: IdbDdlOp): void;
|
|
66
|
+
/**
|
|
67
|
+
* Marker write input. The `space` field is the contract-space identifier
|
|
68
|
+
* (`"app"` for the single app space; per-extension callers pass their own
|
|
69
|
+
* space id when extensions land on IDB). All other fields mirror
|
|
70
|
+
* {@link ContractMarkerRecord} exactly so the in-DB record has full parity
|
|
71
|
+
* with the framework's canonical marker shape.
|
|
72
|
+
*/
|
|
73
|
+
interface MarkerWriteInput {
|
|
74
|
+
readonly space: string;
|
|
75
|
+
readonly storageHash: string;
|
|
76
|
+
readonly profileHash?: string;
|
|
77
|
+
readonly invariants?: readonly string[];
|
|
78
|
+
readonly contractJson?: unknown;
|
|
79
|
+
readonly canonicalVersion?: number | null;
|
|
80
|
+
readonly appTag?: string | null;
|
|
81
|
+
readonly meta?: Record<string, unknown>;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* In-DB marker record shape stored in `_prisma_next_marker`.
|
|
85
|
+
*
|
|
86
|
+
* Identical to {@link ContractMarkerRecord} plus the keying `space` field;
|
|
87
|
+
* `updatedAt` is a `Date` (not an ISO string) because IndexedDB serialises
|
|
88
|
+
* Dates natively via structured-clone.
|
|
89
|
+
*/
|
|
90
|
+
type IdbMarkerRecord = ContractMarkerRecord & {
|
|
91
|
+
readonly space: string;
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* Write the contract marker into the `_prisma_next_marker` store using a
|
|
95
|
+
* separate `readwrite` transaction. The marker store is created inside the
|
|
96
|
+
* version-change transaction during the migration's first run (see
|
|
97
|
+
* `createMarkerStoreOp`); subsequent runs reuse it.
|
|
98
|
+
*
|
|
99
|
+
* Keyed by `space` (defaulting to `"app"` at the caller layer) so the
|
|
100
|
+
* storage layout doesn't have to be migrated when IDB eventually grows
|
|
101
|
+
* extension support (see ADR 021 + feedback issue #5).
|
|
102
|
+
*/
|
|
103
|
+
declare function writeMarker(db: IDBDatabase, input: MarkerWriteInput): Promise<void>;
|
|
104
|
+
/**
|
|
105
|
+
* Read the marker record for a given space from the `_prisma_next_marker`
|
|
106
|
+
* store. Returns `null` when the store doesn't exist (fresh DB) or the
|
|
107
|
+
* record is absent.
|
|
108
|
+
*/
|
|
109
|
+
declare function readMarker(db: IDBDatabase, space: string): Promise<IdbMarkerRecord | null>;
|
|
110
|
+
/**
|
|
111
|
+
* Open `dbName` at `targetVersion`, apply `ops` inside the `upgradeneeded`
|
|
112
|
+
* callback, optionally write the contract marker (in a separate readwrite
|
|
113
|
+
* tx after `onsuccess`), then close the connection.
|
|
114
|
+
*
|
|
115
|
+
* Returns the number of ops applied. Throws on open-request error or DDL
|
|
116
|
+
* application error.
|
|
117
|
+
*/
|
|
118
|
+
declare function openAndUpgrade(input: {
|
|
119
|
+
readonly factory: IDBFactory;
|
|
120
|
+
readonly dbName: string;
|
|
121
|
+
readonly targetVersion: number;
|
|
122
|
+
readonly ops: readonly IdbDdlOp[];
|
|
123
|
+
readonly marker?: MarkerWriteInput;
|
|
124
|
+
readonly onOperationStart?: (op: IdbDdlOp) => void;
|
|
125
|
+
readonly onOperationComplete?: (op: IdbDdlOp) => void;
|
|
126
|
+
}): Promise<number>;
|
|
127
|
+
//#endregion
|
|
128
|
+
export { readMarker as a, CreateObjectStoreOp as c, IdbDdlOp as d, createIndexOp as f, isIdbDdlOp as g, dropObjectStoreOp as h, openAndUpgrade as i, DropIndexOp as l, dropIndexOp as m, MarkerWriteInput as n, writeMarker as o, createObjectStoreOp as p, applyOneDdlOp as r, CreateIndexOp as s, IdbMarkerRecord as t, DropObjectStoreOp as u };
|
|
129
|
+
//# sourceMappingURL=apply-ddl-op-DZAoihY0.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply-ddl-op-DZAoihY0.d.mts","names":[],"sources":["../src/core/migration-factories.ts","../src/core/apply-ddl-op.ts"],"mappings":";;;;;;KAqBY,mBAAA,GAAsB,sBAAA;EAAA,SACvB,IAAA;EAAA,SACA,SAAA;EAAA,SACA,GAAA,EAAK,kBAAkB;AAAA;;KAItB,iBAAA,GAAoB,sBAAsB;EAAA,SAC3C,IAAA;EAAA,SACA,SAAA;AAAA;AANuB;AAAA,KAUtB,aAAA,GAAgB,sBAAA;EAAA,SACjB,IAAA;EAAA,SACA,SAAA;EAAA,SACA,SAAA;EAAA,SACA,GAAA,EAAK,kBAAkB;AAAA;;KAItB,WAAA,GAAc,sBAAsB;EAAA,SACrC,IAAA;EAAA,SACA,SAAA;EAAA,SACA,SAAA;AAAA;;KAIC,QAAA,GAAW,mBAAA,GAAsB,iBAAA,GAAoB,aAAA,GAAgB,WAAA;;iBAKjE,UAAA,CAAW,EAAA,EAAI,sBAAA,GAAyB,EAAA,IAAM,QAAQ;AAAA,iBAYtD,mBAAA,CAAoB,SAAA,UAAmB,GAAA,EAAK,kBAAA,GAAqB,mBAAmB;AAAA,iBAWpF,iBAAA,CAAkB,SAAA,WAAoB,iBAAiB;AAAA,iBAUvD,aAAA,CAAc,SAAA,UAAmB,SAAA,UAAmB,GAAA,EAAK,kBAAA,GAAqB,aAAa;AAAA,iBAY3F,WAAA,CAAY,SAAA,UAAmB,SAAA,WAAoB,WAAW;;;;;;AA9E9E;;;;;;;;;;AAGkC;AAIlC;;;;;;;;AAEoB;AAIpB;;iBCNgB,aAAA,CAAc,EAAA,EAAI,WAAA,EAAa,EAAA,EAAI,cAAA,EAAgB,EAAA,EAAI,QAAA;;;;;;;;UAwCtD,gBAAA;EAAA,SACN,KAAA;EAAA,SACA,WAAA;EAAA,SACA,WAAA;EAAA,SACA,UAAA;EAAA,SACA,YAAA;EAAA,SACA,gBAAA;EAAA,SACA,MAAA;EAAA,SACA,IAAA,GAAO,MAAM;AAAA;;AD/BJ;AAIpB;;;;;KCqCY,eAAA,GAAkB,oBAAoB;EAAA,SAAc,KAAK;AAAA;;;;;;;ADrCuB;AAK5F;;;iBC4CgB,WAAA,CAAY,EAAA,EAAI,WAAA,EAAa,KAAA,EAAO,gBAAA,GAAmB,OAAA;;;;;;iBAqCvD,UAAA,CAAW,EAAA,EAAI,WAAA,EAAa,KAAA,WAAgB,OAAA,CAAQ,eAAA;ADrEpE;;;;;;;;AAAA,iBC8FgB,cAAA,CAAe,KAAA;EAAA,SACpB,OAAA,EAAS,UAAA;EAAA,SACT,MAAA;EAAA,SACA,aAAA;EAAA,SACA,GAAA,WAAc,QAAA;EAAA,SACd,MAAA,GAAS,gBAAA;EAAA,SACT,gBAAA,IAAoB,EAAA,EAAI,QAAA;EAAA,SACxB,mBAAA,IAAuB,EAAA,EAAI,QAAA;AAAA,IAClC,OAAA"}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
//#region src/core/migration-factories.ts
|
|
2
|
+
/** Name of the internal marker store. Must match {@link MARKER_STORE_NAME} in driver-idb. */
|
|
3
|
+
const IDB_MARKER_STORE = "_prisma_next_marker";
|
|
4
|
+
/**
|
|
5
|
+
* Default keyPath for the marker store.
|
|
6
|
+
*
|
|
7
|
+
* Keyed by `space` (per-contract-space, defaulting to `"app"`) rather than
|
|
8
|
+
* the legacy `"id"`/`"default"` shape so the storage layout doesn't need to
|
|
9
|
+
* be migrated later if IDB grows extension support. See ADR 021 +
|
|
10
|
+
* feedback issue #5.
|
|
11
|
+
*/
|
|
12
|
+
const MARKER_KEYPATH = "space";
|
|
13
|
+
/** Returns `true` if `op` is one of the four IDB DDL op kinds. */
|
|
14
|
+
function isIdbDdlOp(op) {
|
|
15
|
+
return "kind" in op && (op.kind === "createObjectStore" || op.kind === "dropObjectStore" || op.kind === "createIndex" || op.kind === "dropIndex");
|
|
16
|
+
}
|
|
17
|
+
function createObjectStoreOp(storeName, def) {
|
|
18
|
+
return {
|
|
19
|
+
kind: "createObjectStore",
|
|
20
|
+
id: `object-store.${storeName}.create`,
|
|
21
|
+
label: `Create object store "${storeName}"`,
|
|
22
|
+
operationClass: "additive",
|
|
23
|
+
storeName,
|
|
24
|
+
def
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function dropObjectStoreOp(storeName) {
|
|
28
|
+
return {
|
|
29
|
+
kind: "dropObjectStore",
|
|
30
|
+
id: `object-store.${storeName}.drop`,
|
|
31
|
+
label: `Drop object store "${storeName}"`,
|
|
32
|
+
operationClass: "destructive",
|
|
33
|
+
storeName
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function createIndexOp(storeName, indexName, def) {
|
|
37
|
+
return {
|
|
38
|
+
kind: "createIndex",
|
|
39
|
+
id: `index.${storeName}.${indexName}.create`,
|
|
40
|
+
label: `Create index "${indexName}" on "${storeName}"`,
|
|
41
|
+
operationClass: "additive",
|
|
42
|
+
storeName,
|
|
43
|
+
indexName,
|
|
44
|
+
def
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function dropIndexOp(storeName, indexName) {
|
|
48
|
+
return {
|
|
49
|
+
kind: "dropIndex",
|
|
50
|
+
id: `index.${storeName}.${indexName}.drop`,
|
|
51
|
+
label: `Drop index "${indexName}" on "${storeName}"`,
|
|
52
|
+
operationClass: "destructive",
|
|
53
|
+
storeName,
|
|
54
|
+
indexName
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Create the internal `_prisma_next_marker` object store.
|
|
59
|
+
*
|
|
60
|
+
* This store holds the contract marker (`storageHash` + `profileHash`) that
|
|
61
|
+
* the runtime verifies before executing queries. It is always additive and
|
|
62
|
+
* should be the first op in any migration plan.
|
|
63
|
+
*/
|
|
64
|
+
function createMarkerStoreOp() {
|
|
65
|
+
return {
|
|
66
|
+
kind: "createObjectStore",
|
|
67
|
+
id: `object-store.${IDB_MARKER_STORE}.create`,
|
|
68
|
+
label: `Create internal marker store "${IDB_MARKER_STORE}"`,
|
|
69
|
+
operationClass: "additive",
|
|
70
|
+
storeName: IDB_MARKER_STORE,
|
|
71
|
+
def: { keyPath: MARKER_KEYPATH }
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
75
|
+
//#region src/core/apply-ddl-op.ts
|
|
76
|
+
/**
|
|
77
|
+
* Execute a single DDL operation against an open `upgradeneeded` transaction.
|
|
78
|
+
*
|
|
79
|
+
* All IndexedDB DDL (createObjectStore, deleteObjectStore, createIndex,
|
|
80
|
+
* deleteIndex) MUST happen inside the version-change transaction that fires
|
|
81
|
+
* in `upgradeneeded`. The `db` and `tx` references are valid only for the
|
|
82
|
+
* duration of that callback.
|
|
83
|
+
*
|
|
84
|
+
* Shared by the runner (target-idb), the browser auto-migrate path
|
|
85
|
+
* (client-idb), and the preflight CLI (family-idb) so all three apply paths
|
|
86
|
+
* use a single, byte-identical implementation.
|
|
87
|
+
*
|
|
88
|
+
* **Idempotency.** Each op is guarded by an existence check so re-applying an
|
|
89
|
+
* already-applied op is a no-op rather than a throw. This is the load-bearing
|
|
90
|
+
* guarantee behind the two-phase marker write (ADR 002): if a tab is killed in
|
|
91
|
+
* the window between the version-change transaction committing and the marker
|
|
92
|
+
* `put` landing, the schema is advanced but the marker still points at the old
|
|
93
|
+
* hash. On the next open, the chain walk re-collects the already-applied ops
|
|
94
|
+
* and replays them here. Without the guards, `createObjectStore` /
|
|
95
|
+
* `createIndex` throw `ConstraintError` on the existing store/index, the
|
|
96
|
+
* version-change transaction aborts, and the database is permanently wedged
|
|
97
|
+
* (every subsequent open repeats the failed upgrade). Contrary to a common
|
|
98
|
+
* assumption, IndexedDB itself offers **no** "already exists" tolerance — these
|
|
99
|
+
* guards are what make replay safe. (Was PLAN Issue #25.)
|
|
100
|
+
*/
|
|
101
|
+
function applyOneDdlOp(db, tx, op) {
|
|
102
|
+
switch (op.kind) {
|
|
103
|
+
case "createObjectStore":
|
|
104
|
+
if (db.objectStoreNames.contains(op.storeName)) return;
|
|
105
|
+
db.createObjectStore(op.storeName, {
|
|
106
|
+
keyPath: op.def.keyPath,
|
|
107
|
+
...op.def.autoIncrement !== void 0 && { autoIncrement: op.def.autoIncrement }
|
|
108
|
+
});
|
|
109
|
+
return;
|
|
110
|
+
case "dropObjectStore":
|
|
111
|
+
if (!db.objectStoreNames.contains(op.storeName)) return;
|
|
112
|
+
db.deleteObjectStore(op.storeName);
|
|
113
|
+
return;
|
|
114
|
+
case "createIndex": {
|
|
115
|
+
const store = tx.objectStore(op.storeName);
|
|
116
|
+
if (store.indexNames.contains(op.indexName)) return;
|
|
117
|
+
store.createIndex(op.indexName, op.def.keyPath, {
|
|
118
|
+
unique: op.def.unique,
|
|
119
|
+
...op.def.multiEntry !== void 0 && { multiEntry: op.def.multiEntry }
|
|
120
|
+
});
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
case "dropIndex": {
|
|
124
|
+
const store = tx.objectStore(op.storeName);
|
|
125
|
+
if (!store.indexNames.contains(op.indexName)) return;
|
|
126
|
+
store.deleteIndex(op.indexName);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Write the contract marker into the `_prisma_next_marker` store using a
|
|
133
|
+
* separate `readwrite` transaction. The marker store is created inside the
|
|
134
|
+
* version-change transaction during the migration's first run (see
|
|
135
|
+
* `createMarkerStoreOp`); subsequent runs reuse it.
|
|
136
|
+
*
|
|
137
|
+
* Keyed by `space` (defaulting to `"app"` at the caller layer) so the
|
|
138
|
+
* storage layout doesn't have to be migrated when IDB eventually grows
|
|
139
|
+
* extension support (see ADR 021 + feedback issue #5).
|
|
140
|
+
*/
|
|
141
|
+
function writeMarker(db, input) {
|
|
142
|
+
return new Promise((resolve, reject) => {
|
|
143
|
+
if (!db.objectStoreNames.contains("_prisma_next_marker")) {
|
|
144
|
+
console.warn("[prisma-next] _prisma_next_marker store not found after DDL — this indicates a bug in the migration planner.");
|
|
145
|
+
resolve();
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const tx = db.transaction(IDB_MARKER_STORE, "readwrite");
|
|
149
|
+
const store = tx.objectStore(IDB_MARKER_STORE);
|
|
150
|
+
const record = {
|
|
151
|
+
space: input.space,
|
|
152
|
+
storageHash: input.storageHash,
|
|
153
|
+
profileHash: input.profileHash ?? "",
|
|
154
|
+
updatedAt: /* @__PURE__ */ new Date(),
|
|
155
|
+
invariants: input.invariants ?? [],
|
|
156
|
+
contractJson: input.contractJson ?? null,
|
|
157
|
+
canonicalVersion: input.canonicalVersion ?? null,
|
|
158
|
+
appTag: input.appTag ?? null,
|
|
159
|
+
meta: input.meta ?? {}
|
|
160
|
+
};
|
|
161
|
+
const putReq = store.put(record);
|
|
162
|
+
putReq.onerror = () => reject(putReq.error);
|
|
163
|
+
tx.oncomplete = () => resolve();
|
|
164
|
+
tx.onerror = () => reject(tx.error);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Read the marker record for a given space from the `_prisma_next_marker`
|
|
169
|
+
* store. Returns `null` when the store doesn't exist (fresh DB) or the
|
|
170
|
+
* record is absent.
|
|
171
|
+
*/
|
|
172
|
+
function readMarker(db, space) {
|
|
173
|
+
return new Promise((resolve, reject) => {
|
|
174
|
+
if (!db.objectStoreNames.contains("_prisma_next_marker")) {
|
|
175
|
+
resolve(null);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
const req = db.transaction(IDB_MARKER_STORE, "readonly").objectStore(IDB_MARKER_STORE).get(space);
|
|
179
|
+
req.onsuccess = () => {
|
|
180
|
+
const result = req.result;
|
|
181
|
+
resolve(result ?? null);
|
|
182
|
+
};
|
|
183
|
+
req.onerror = () => reject(req.error);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Open `dbName` at `targetVersion`, apply `ops` inside the `upgradeneeded`
|
|
188
|
+
* callback, optionally write the contract marker (in a separate readwrite
|
|
189
|
+
* tx after `onsuccess`), then close the connection.
|
|
190
|
+
*
|
|
191
|
+
* Returns the number of ops applied. Throws on open-request error or DDL
|
|
192
|
+
* application error.
|
|
193
|
+
*/
|
|
194
|
+
function openAndUpgrade(input) {
|
|
195
|
+
return new Promise((resolve, reject) => {
|
|
196
|
+
const request = input.factory.open(input.dbName, input.targetVersion);
|
|
197
|
+
request.onupgradeneeded = (event) => {
|
|
198
|
+
const target = event.target;
|
|
199
|
+
const db = target.result;
|
|
200
|
+
const tx = target.transaction;
|
|
201
|
+
if (tx === null) {
|
|
202
|
+
reject(/* @__PURE__ */ new Error("IDB: upgradeneeded fired with null version-change transaction"));
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
for (const op of input.ops) {
|
|
206
|
+
input.onOperationStart?.(op);
|
|
207
|
+
applyOneDdlOp(db, tx, op);
|
|
208
|
+
input.onOperationComplete?.(op);
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
request.onsuccess = async (event) => {
|
|
212
|
+
const db = event.target.result;
|
|
213
|
+
try {
|
|
214
|
+
if (input.marker !== void 0) await writeMarker(db, input.marker);
|
|
215
|
+
} finally {
|
|
216
|
+
db.close();
|
|
217
|
+
}
|
|
218
|
+
resolve(input.ops.length);
|
|
219
|
+
};
|
|
220
|
+
request.onerror = (event) => {
|
|
221
|
+
const err = event.target.error;
|
|
222
|
+
reject(err ?? /* @__PURE__ */ new Error("IDB: migration open request failed without an error object"));
|
|
223
|
+
};
|
|
224
|
+
request.onblocked = () => {
|
|
225
|
+
reject(/* @__PURE__ */ new Error(`IDB: migration of "${input.dbName}" is blocked — another connection is open at an older version and did not close. Close other tabs/connections to this database and retry.`));
|
|
226
|
+
};
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
//#endregion
|
|
230
|
+
export { createIndexOp as a, dropIndexOp as c, writeMarker as i, dropObjectStoreOp as l, openAndUpgrade as n, createMarkerStoreOp as o, readMarker as r, createObjectStoreOp as s, applyOneDdlOp as t, isIdbDdlOp as u };
|
|
231
|
+
|
|
232
|
+
//# sourceMappingURL=apply-ddl-op-LP-l0o4O.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply-ddl-op-LP-l0o4O.mjs","names":[],"sources":["../src/core/migration-factories.ts","../src/core/apply-ddl-op.ts"],"sourcesContent":["import type { MigrationOperationClass, MigrationPlanOperation } from \"@prisma-next/framework-components/control\";\nimport type { IdbIndexDefinition, IdbStoreDefinition } from \"./idb-contract-types\";\n\n// ── Marker store ─────────────────────────────────────────────────────────────\n\n/** Name of the internal marker store. Must match {@link MARKER_STORE_NAME} in driver-idb. */\nexport const IDB_MARKER_STORE = \"_prisma_next_marker\";\n\n/**\n * Default keyPath for the marker store.\n *\n * Keyed by `space` (per-contract-space, defaulting to `\"app\"`) rather than\n * the legacy `\"id\"`/`\"default\"` shape so the storage layout doesn't need to\n * be migrated later if IDB grows extension support. See ADR 021 +\n * feedback issue #5.\n */\nconst MARKER_KEYPATH = \"space\";\n\n// ── Op kinds ──────────────────────────────────────────────────────────────────\n\n/** DDL operation that creates a new object store. Always `additive`. */\nexport type CreateObjectStoreOp = MigrationPlanOperation & {\n readonly kind: \"createObjectStore\";\n readonly storeName: string;\n readonly def: IdbStoreDefinition;\n};\n\n/** DDL operation that drops an existing object store and all its indexes. Always `destructive`. */\nexport type DropObjectStoreOp = MigrationPlanOperation & {\n readonly kind: \"dropObjectStore\";\n readonly storeName: string;\n};\n\n/** DDL operation that creates a secondary index on an object store. Always `additive`. */\nexport type CreateIndexOp = MigrationPlanOperation & {\n readonly kind: \"createIndex\";\n readonly storeName: string;\n readonly indexName: string;\n readonly def: IdbIndexDefinition;\n};\n\n/** DDL operation that drops a secondary index from an object store. Always `destructive`. */\nexport type DropIndexOp = MigrationPlanOperation & {\n readonly kind: \"dropIndex\";\n readonly storeName: string;\n readonly indexName: string;\n};\n\n/** Union of all IDB DDL plan operations. */\nexport type IdbDdlOp = CreateObjectStoreOp | DropObjectStoreOp | CreateIndexOp | DropIndexOp;\n\n// ── Type guard ────────────────────────────────────────────────────────────────\n\n/** Returns `true` if `op` is one of the four IDB DDL op kinds. */\nexport function isIdbDdlOp(op: MigrationPlanOperation): op is IdbDdlOp {\n return (\n \"kind\" in op &&\n (op.kind === \"createObjectStore\" ||\n op.kind === \"dropObjectStore\" ||\n op.kind === \"createIndex\" ||\n op.kind === \"dropIndex\")\n );\n}\n\n// ── Factories ─────────────────────────────────────────────────────────────────\n\nexport function createObjectStoreOp(storeName: string, def: IdbStoreDefinition): CreateObjectStoreOp {\n return {\n kind: \"createObjectStore\",\n id: `object-store.${storeName}.create`,\n label: `Create object store \"${storeName}\"`,\n operationClass: \"additive\" as MigrationOperationClass,\n storeName,\n def,\n };\n}\n\nexport function dropObjectStoreOp(storeName: string): DropObjectStoreOp {\n return {\n kind: \"dropObjectStore\",\n id: `object-store.${storeName}.drop`,\n label: `Drop object store \"${storeName}\"`,\n operationClass: \"destructive\" as MigrationOperationClass,\n storeName,\n };\n}\n\nexport function createIndexOp(storeName: string, indexName: string, def: IdbIndexDefinition): CreateIndexOp {\n return {\n kind: \"createIndex\",\n id: `index.${storeName}.${indexName}.create`,\n label: `Create index \"${indexName}\" on \"${storeName}\"`,\n operationClass: \"additive\" as MigrationOperationClass,\n storeName,\n indexName,\n def,\n };\n}\n\nexport function dropIndexOp(storeName: string, indexName: string): DropIndexOp {\n return {\n kind: \"dropIndex\",\n id: `index.${storeName}.${indexName}.drop`,\n label: `Drop index \"${indexName}\" on \"${storeName}\"`,\n operationClass: \"destructive\" as MigrationOperationClass,\n storeName,\n indexName,\n };\n}\n\n/**\n * Create the internal `_prisma_next_marker` object store.\n *\n * This store holds the contract marker (`storageHash` + `profileHash`) that\n * the runtime verifies before executing queries. It is always additive and\n * should be the first op in any migration plan.\n */\nexport function createMarkerStoreOp(): CreateObjectStoreOp {\n return {\n kind: \"createObjectStore\",\n id: `object-store.${IDB_MARKER_STORE}.create`,\n label: `Create internal marker store \"${IDB_MARKER_STORE}\"`,\n operationClass: \"additive\" as MigrationOperationClass,\n storeName: IDB_MARKER_STORE,\n def: { keyPath: MARKER_KEYPATH },\n };\n}\n","import type { ContractMarkerRecord } from \"@prisma-next/contract/types\";\nimport { IDB_MARKER_STORE, type IdbDdlOp } from \"./migration-factories\";\n\n/**\n * Execute a single DDL operation against an open `upgradeneeded` transaction.\n *\n * All IndexedDB DDL (createObjectStore, deleteObjectStore, createIndex,\n * deleteIndex) MUST happen inside the version-change transaction that fires\n * in `upgradeneeded`. The `db` and `tx` references are valid only for the\n * duration of that callback.\n *\n * Shared by the runner (target-idb), the browser auto-migrate path\n * (client-idb), and the preflight CLI (family-idb) so all three apply paths\n * use a single, byte-identical implementation.\n *\n * **Idempotency.** Each op is guarded by an existence check so re-applying an\n * already-applied op is a no-op rather than a throw. This is the load-bearing\n * guarantee behind the two-phase marker write (ADR 002): if a tab is killed in\n * the window between the version-change transaction committing and the marker\n * `put` landing, the schema is advanced but the marker still points at the old\n * hash. On the next open, the chain walk re-collects the already-applied ops\n * and replays them here. Without the guards, `createObjectStore` /\n * `createIndex` throw `ConstraintError` on the existing store/index, the\n * version-change transaction aborts, and the database is permanently wedged\n * (every subsequent open repeats the failed upgrade). Contrary to a common\n * assumption, IndexedDB itself offers **no** \"already exists\" tolerance — these\n * guards are what make replay safe. (Was PLAN Issue #25.)\n */\nexport function applyOneDdlOp(db: IDBDatabase, tx: IDBTransaction, op: IdbDdlOp): void {\n switch (op.kind) {\n case \"createObjectStore\": {\n if (db.objectStoreNames.contains(op.storeName)) return;\n db.createObjectStore(op.storeName, {\n keyPath: op.def.keyPath,\n ...(op.def.autoIncrement !== undefined && { autoIncrement: op.def.autoIncrement }),\n });\n return;\n }\n case \"dropObjectStore\": {\n if (!db.objectStoreNames.contains(op.storeName)) return;\n db.deleteObjectStore(op.storeName);\n return;\n }\n case \"createIndex\": {\n const store = tx.objectStore(op.storeName);\n if (store.indexNames.contains(op.indexName)) return;\n store.createIndex(op.indexName, op.def.keyPath, {\n unique: op.def.unique,\n ...(op.def.multiEntry !== undefined && { multiEntry: op.def.multiEntry }),\n });\n return;\n }\n case \"dropIndex\": {\n const store = tx.objectStore(op.storeName);\n if (!store.indexNames.contains(op.indexName)) return;\n store.deleteIndex(op.indexName);\n return;\n }\n }\n}\n\n/**\n * Marker write input. The `space` field is the contract-space identifier\n * (`\"app\"` for the single app space; per-extension callers pass their own\n * space id when extensions land on IDB). All other fields mirror\n * {@link ContractMarkerRecord} exactly so the in-DB record has full parity\n * with the framework's canonical marker shape.\n */\nexport interface MarkerWriteInput {\n readonly space: string;\n readonly storageHash: string;\n readonly profileHash?: string;\n readonly invariants?: readonly string[];\n readonly contractJson?: unknown;\n readonly canonicalVersion?: number | null;\n readonly appTag?: string | null;\n readonly meta?: Record<string, unknown>;\n}\n\n/**\n * In-DB marker record shape stored in `_prisma_next_marker`.\n *\n * Identical to {@link ContractMarkerRecord} plus the keying `space` field;\n * `updatedAt` is a `Date` (not an ISO string) because IndexedDB serialises\n * Dates natively via structured-clone.\n */\nexport type IdbMarkerRecord = ContractMarkerRecord & { readonly space: string };\n\n/**\n * Write the contract marker into the `_prisma_next_marker` store using a\n * separate `readwrite` transaction. The marker store is created inside the\n * version-change transaction during the migration's first run (see\n * `createMarkerStoreOp`); subsequent runs reuse it.\n *\n * Keyed by `space` (defaulting to `\"app\"` at the caller layer) so the\n * storage layout doesn't have to be migrated when IDB eventually grows\n * extension support (see ADR 021 + feedback issue #5).\n */\nexport function writeMarker(db: IDBDatabase, input: MarkerWriteInput): Promise<void> {\n return new Promise((resolve, reject) => {\n if (!db.objectStoreNames.contains(IDB_MARKER_STORE)) {\n // Marker store missing — should never happen because the planner emits\n // its creation as the first op. Non-fatal so the runner can still\n // report DDL success, but worth surfacing as a planner invariant bug.\n console.warn(\n \"[prisma-next] _prisma_next_marker store not found after DDL — this indicates a bug in the migration planner.\"\n );\n resolve();\n return;\n }\n const tx = db.transaction(IDB_MARKER_STORE, \"readwrite\");\n const store = tx.objectStore(IDB_MARKER_STORE);\n const record: IdbMarkerRecord = {\n space: input.space,\n storageHash: input.storageHash,\n profileHash: input.profileHash ?? \"\",\n updatedAt: new Date(),\n invariants: input.invariants ?? [],\n contractJson: input.contractJson ?? null,\n canonicalVersion: input.canonicalVersion ?? null,\n appTag: input.appTag ?? null,\n meta: input.meta ?? {},\n };\n const putReq = store.put(record);\n putReq.onerror = () => reject(putReq.error);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n}\n\n/**\n * Read the marker record for a given space from the `_prisma_next_marker`\n * store. Returns `null` when the store doesn't exist (fresh DB) or the\n * record is absent.\n */\nexport function readMarker(db: IDBDatabase, space: string): Promise<IdbMarkerRecord | null> {\n return new Promise((resolve, reject) => {\n if (!db.objectStoreNames.contains(IDB_MARKER_STORE)) {\n resolve(null);\n return;\n }\n const tx = db.transaction(IDB_MARKER_STORE, \"readonly\");\n const store = tx.objectStore(IDB_MARKER_STORE);\n const req = store.get(space);\n req.onsuccess = () => {\n const result = req.result as IdbMarkerRecord | undefined;\n resolve(result ?? null);\n };\n req.onerror = () => reject(req.error);\n });\n}\n\n/**\n * Open `dbName` at `targetVersion`, apply `ops` inside the `upgradeneeded`\n * callback, optionally write the contract marker (in a separate readwrite\n * tx after `onsuccess`), then close the connection.\n *\n * Returns the number of ops applied. Throws on open-request error or DDL\n * application error.\n */\nexport function openAndUpgrade(input: {\n readonly factory: IDBFactory;\n readonly dbName: string;\n readonly targetVersion: number;\n readonly ops: readonly IdbDdlOp[];\n readonly marker?: MarkerWriteInput;\n readonly onOperationStart?: (op: IdbDdlOp) => void;\n readonly onOperationComplete?: (op: IdbDdlOp) => void;\n}): Promise<number> {\n return new Promise((resolve, reject) => {\n const request = input.factory.open(input.dbName, input.targetVersion);\n\n request.onupgradeneeded = (event) => {\n const target = event.target as IDBOpenDBRequest;\n const db = target.result;\n const tx = target.transaction;\n if (tx === null) {\n reject(new Error(\"IDB: upgradeneeded fired with null version-change transaction\"));\n return;\n }\n for (const op of input.ops) {\n input.onOperationStart?.(op);\n applyOneDdlOp(db, tx, op);\n input.onOperationComplete?.(op);\n }\n };\n\n request.onsuccess = async (event) => {\n const db = (event.target as IDBOpenDBRequest).result;\n try {\n if (input.marker !== undefined) {\n await writeMarker(db, input.marker);\n }\n } finally {\n db.close();\n }\n resolve(input.ops.length);\n };\n\n request.onerror = (event) => {\n const err = (event.target as IDBOpenDBRequest).error;\n reject(err ?? new Error(\"IDB: migration open request failed without an error object\"));\n };\n\n // Another open connection at an older version is holding the upgrade back.\n // Runtime connections self-close on `versionchange` (see driver-idb), so\n // this should be unreachable in normal operation — but a stray third-party\n // connection on the same database name would otherwise hang the upgrade\n // forever. Fail fast with an actionable message instead.\n request.onblocked = () => {\n reject(\n new Error(\n `IDB: migration of \"${input.dbName}\" is blocked — another connection is open at an older ` +\n \"version and did not close. Close other tabs/connections to this database and retry.\"\n )\n );\n };\n });\n}\n"],"mappings":";;AAMA,MAAa,mBAAmB;;;;;;;;;AAUhC,MAAM,iBAAiB;;AAsCvB,SAAgB,WAAW,IAA4C;CACrE,OACE,UAAU,OACT,GAAG,SAAS,uBACX,GAAG,SAAS,qBACZ,GAAG,SAAS,iBACZ,GAAG,SAAS;AAElB;AAIA,SAAgB,oBAAoB,WAAmB,KAA8C;CACnG,OAAO;EACL,MAAM;EACN,IAAI,gBAAgB,UAAU;EAC9B,OAAO,wBAAwB,UAAU;EACzC,gBAAgB;EAChB;EACA;CACF;AACF;AAEA,SAAgB,kBAAkB,WAAsC;CACtE,OAAO;EACL,MAAM;EACN,IAAI,gBAAgB,UAAU;EAC9B,OAAO,sBAAsB,UAAU;EACvC,gBAAgB;EAChB;CACF;AACF;AAEA,SAAgB,cAAc,WAAmB,WAAmB,KAAwC;CAC1G,OAAO;EACL,MAAM;EACN,IAAI,SAAS,UAAU,GAAG,UAAU;EACpC,OAAO,iBAAiB,UAAU,QAAQ,UAAU;EACpD,gBAAgB;EAChB;EACA;EACA;CACF;AACF;AAEA,SAAgB,YAAY,WAAmB,WAAgC;CAC7E,OAAO;EACL,MAAM;EACN,IAAI,SAAS,UAAU,GAAG,UAAU;EACpC,OAAO,eAAe,UAAU,QAAQ,UAAU;EAClD,gBAAgB;EAChB;EACA;CACF;AACF;;;;;;;;AASA,SAAgB,sBAA2C;CACzD,OAAO;EACL,MAAM;EACN,IAAI,gBAAgB,iBAAiB;EACrC,OAAO,iCAAiC,iBAAiB;EACzD,gBAAgB;EAChB,WAAW;EACX,KAAK,EAAE,SAAS,eAAe;CACjC;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;AClGA,SAAgB,cAAc,IAAiB,IAAoB,IAAoB;CACrF,QAAQ,GAAG,MAAX;EACE,KAAK;GACH,IAAI,GAAG,iBAAiB,SAAS,GAAG,SAAS,GAAG;GAChD,GAAG,kBAAkB,GAAG,WAAW;IACjC,SAAS,GAAG,IAAI;IAChB,GAAI,GAAG,IAAI,kBAAkB,KAAA,KAAa,EAAE,eAAe,GAAG,IAAI,cAAc;GAClF,CAAC;GACD;EAEF,KAAK;GACH,IAAI,CAAC,GAAG,iBAAiB,SAAS,GAAG,SAAS,GAAG;GACjD,GAAG,kBAAkB,GAAG,SAAS;GACjC;EAEF,KAAK,eAAe;GAClB,MAAM,QAAQ,GAAG,YAAY,GAAG,SAAS;GACzC,IAAI,MAAM,WAAW,SAAS,GAAG,SAAS,GAAG;GAC7C,MAAM,YAAY,GAAG,WAAW,GAAG,IAAI,SAAS;IAC9C,QAAQ,GAAG,IAAI;IACf,GAAI,GAAG,IAAI,eAAe,KAAA,KAAa,EAAE,YAAY,GAAG,IAAI,WAAW;GACzE,CAAC;GACD;EACF;EACA,KAAK,aAAa;GAChB,MAAM,QAAQ,GAAG,YAAY,GAAG,SAAS;GACzC,IAAI,CAAC,MAAM,WAAW,SAAS,GAAG,SAAS,GAAG;GAC9C,MAAM,YAAY,GAAG,SAAS;GAC9B;EACF;CACF;AACF;;;;;;;;;;;AAuCA,SAAgB,YAAY,IAAiB,OAAwC;CACnF,OAAO,IAAI,SAAS,SAAS,WAAW;EACtC,IAAI,CAAC,GAAG,iBAAiB,SAAA,qBAAyB,GAAG;GAInD,QAAQ,KACN,8GACF;GACA,QAAQ;GACR;EACF;EACA,MAAM,KAAK,GAAG,YAAY,kBAAkB,WAAW;EACvD,MAAM,QAAQ,GAAG,YAAY,gBAAgB;EAC7C,MAAM,SAA0B;GAC9B,OAAO,MAAM;GACb,aAAa,MAAM;GACnB,aAAa,MAAM,eAAe;GAClC,2BAAW,IAAI,KAAK;GACpB,YAAY,MAAM,cAAc,CAAC;GACjC,cAAc,MAAM,gBAAgB;GACpC,kBAAkB,MAAM,oBAAoB;GAC5C,QAAQ,MAAM,UAAU;GACxB,MAAM,MAAM,QAAQ,CAAC;EACvB;EACA,MAAM,SAAS,MAAM,IAAI,MAAM;EAC/B,OAAO,gBAAgB,OAAO,OAAO,KAAK;EAC1C,GAAG,mBAAmB,QAAQ;EAC9B,GAAG,gBAAgB,OAAO,GAAG,KAAK;CACpC,CAAC;AACH;;;;;;AAOA,SAAgB,WAAW,IAAiB,OAAgD;CAC1F,OAAO,IAAI,SAAS,SAAS,WAAW;EACtC,IAAI,CAAC,GAAG,iBAAiB,SAAA,qBAAyB,GAAG;GACnD,QAAQ,IAAI;GACZ;EACF;EAGA,MAAM,MAFK,GAAG,YAAY,kBAAkB,UAC7B,CAAC,CAAC,YAAY,gBACb,CAAC,CAAC,IAAI,KAAK;EAC3B,IAAI,kBAAkB;GACpB,MAAM,SAAS,IAAI;GACnB,QAAQ,UAAU,IAAI;EACxB;EACA,IAAI,gBAAgB,OAAO,IAAI,KAAK;CACtC,CAAC;AACH;;;;;;;;;AAUA,SAAgB,eAAe,OAQX;CAClB,OAAO,IAAI,SAAS,SAAS,WAAW;EACtC,MAAM,UAAU,MAAM,QAAQ,KAAK,MAAM,QAAQ,MAAM,aAAa;EAEpE,QAAQ,mBAAmB,UAAU;GACnC,MAAM,SAAS,MAAM;GACrB,MAAM,KAAK,OAAO;GAClB,MAAM,KAAK,OAAO;GAClB,IAAI,OAAO,MAAM;IACf,uBAAO,IAAI,MAAM,+DAA+D,CAAC;IACjF;GACF;GACA,KAAK,MAAM,MAAM,MAAM,KAAK;IAC1B,MAAM,mBAAmB,EAAE;IAC3B,cAAc,IAAI,IAAI,EAAE;IACxB,MAAM,sBAAsB,EAAE;GAChC;EACF;EAEA,QAAQ,YAAY,OAAO,UAAU;GACnC,MAAM,KAAM,MAAM,OAA4B;GAC9C,IAAI;IACF,IAAI,MAAM,WAAW,KAAA,GACnB,MAAM,YAAY,IAAI,MAAM,MAAM;GAEtC,UAAU;IACR,GAAG,MAAM;GACX;GACA,QAAQ,MAAM,IAAI,MAAM;EAC1B;EAEA,QAAQ,WAAW,UAAU;GAC3B,MAAM,MAAO,MAAM,OAA4B;GAC/C,OAAO,uBAAO,IAAI,MAAM,4DAA4D,CAAC;EACvF;EAOA,QAAQ,kBAAkB;GACxB,uBACE,IAAI,MACF,sBAAsB,MAAM,OAAO,0IAErC,CACF;EACF;CACF,CAAC;AACH"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { c as IdbMigrationControlDriverDescriptor, i as IdbMigrationPlanner, l as extractMigrationDriver, o as IdbMigrationRunner, s as IdbMigrationControlDriver, u as IdbSchemaDiffInput } from "./migration-B43yOFXO.mjs";
|
|
2
|
+
import { ContractSerializer, ControlAdapterInstance, ControlFamilyInstance, ControlTargetInstance } from "@prisma-next/framework-components/control";
|
|
3
|
+
import { Contract } from "@prisma-next/contract/types";
|
|
4
|
+
import { TargetBoundComponentDescriptor } from "@prisma-next/framework-components/components";
|
|
5
|
+
|
|
6
|
+
//#region src/exports/control.d.ts
|
|
7
|
+
declare const idbControlTargetDescription: {
|
|
8
|
+
contractSerializer: ContractSerializer<Contract<import("@prisma-next/contract/types").StorageBase<string>>>;
|
|
9
|
+
migrations: {
|
|
10
|
+
createPlanner(_adapter: ControlAdapterInstance<"idb", "idb">): IdbMigrationPlanner;
|
|
11
|
+
createRunner(_family: ControlFamilyInstance<"idb", unknown>): IdbMigrationRunner;
|
|
12
|
+
contractToSchema(contract: Contract | null, _frameworkComponents?: ReadonlyArray<TargetBoundComponentDescriptor<"idb", "idb">>): IdbSchemaDiffInput | null;
|
|
13
|
+
};
|
|
14
|
+
create(): ControlTargetInstance<"idb", "idb">;
|
|
15
|
+
kind: "target";
|
|
16
|
+
familyId: "idb";
|
|
17
|
+
targetId: "idb";
|
|
18
|
+
id: "idb";
|
|
19
|
+
version: "0.0.1";
|
|
20
|
+
types: {
|
|
21
|
+
readonly codecTypes: {
|
|
22
|
+
readonly import: {
|
|
23
|
+
readonly package: "@prisma-next-idb/target-idb/pack";
|
|
24
|
+
readonly named: "CodecTypes";
|
|
25
|
+
readonly alias: "IdbCodecTypes";
|
|
26
|
+
};
|
|
27
|
+
readonly codecDescriptors: readonly import("@prisma-next/framework-components/codec").AnyCodecDescriptor[];
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
//#endregion
|
|
32
|
+
export { type IdbMigrationControlDriver, IdbMigrationControlDriverDescriptor, idbControlTargetDescription as default, extractMigrationDriver };
|
|
33
|
+
//# sourceMappingURL=control.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"control.d.mts","names":[],"sources":["../src/exports/control.ts"],"mappings":";;;;;;cA+CM,2BAAA;;;4BAdoB,sBAAA,iBAAoC,mBAAA;0BAGtC,qBAAA,mBAAqC,kBAAA;+BAI/C,QAAA,SAAe,oBAAA,GACF,aAAA,CAAc,8BAAA,kBAAD,kBAAA;EAAA;YAU5B,qBAAA"}
|
package/dist/control.mjs
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { t as idbTargetDescriptorMeta } from "./descriptor-meta-CKLekROR.mjs";
|
|
2
|
+
import { a as contractToIdbSchema, i as IdbMigrationPlanner, n as extractMigrationDriver, r as IdbMigrationRunner, t as IdbMigrationControlDriverDescriptor } from "./migration-driver-4T8Hk1vu.mjs";
|
|
3
|
+
//#region src/exports/control.ts
|
|
4
|
+
/**
|
|
5
|
+
* IDB contract serializer — validates on input, passes through on output.
|
|
6
|
+
*
|
|
7
|
+
* IDB contracts are TypeScript-first (`defineContract`), so they are
|
|
8
|
+
* already plain objects with no class instances. Serialization is identity;
|
|
9
|
+
* deserialization runs validation.
|
|
10
|
+
*/
|
|
11
|
+
const idbContractSerializer = {
|
|
12
|
+
deserializeContract(json) {
|
|
13
|
+
return json;
|
|
14
|
+
},
|
|
15
|
+
serializeContract(_contract) {
|
|
16
|
+
return _contract;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
const idbMigrationsCapability = {
|
|
20
|
+
createPlanner(_adapter) {
|
|
21
|
+
return new IdbMigrationPlanner();
|
|
22
|
+
},
|
|
23
|
+
createRunner(_family) {
|
|
24
|
+
return new IdbMigrationRunner();
|
|
25
|
+
},
|
|
26
|
+
contractToSchema(contract, _frameworkComponents) {
|
|
27
|
+
return contractToIdbSchema(contract);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const idbControlTargetDescription = {
|
|
31
|
+
...idbTargetDescriptorMeta,
|
|
32
|
+
contractSerializer: idbContractSerializer,
|
|
33
|
+
migrations: idbMigrationsCapability,
|
|
34
|
+
create() {
|
|
35
|
+
return {
|
|
36
|
+
familyId: "idb",
|
|
37
|
+
targetId: "idb"
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
//#endregion
|
|
42
|
+
export { IdbMigrationControlDriverDescriptor, idbControlTargetDescription as default, extractMigrationDriver };
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=control.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"control.mjs","names":[],"sources":["../src/exports/control.ts"],"sourcesContent":["import type { Contract } from \"@prisma-next/contract/types\";\nimport type { TargetBoundComponentDescriptor } from \"@prisma-next/framework-components/components\";\nimport type {\n ContractSerializer,\n ControlAdapterInstance,\n ControlFamilyInstance,\n ControlTargetInstance,\n MigratableTargetDescriptor,\n TargetMigrationsCapability,\n} from \"@prisma-next/framework-components/control\";\nimport { idbTargetDescriptorMeta } from \"../core/descriptor-meta\";\nimport { IdbMigrationPlanner, contractToIdbSchema } from \"../core/migration-planner\";\nimport { IdbMigrationRunner } from \"../core/migration-runner\";\n\n/**\n * IDB contract serializer — validates on input, passes through on output.\n *\n * IDB contracts are TypeScript-first (`defineContract`), so they are\n * already plain objects with no class instances. Serialization is identity;\n * deserialization runs validation.\n */\nconst idbContractSerializer: ContractSerializer<Contract> = {\n deserializeContract<T extends Contract = Contract>(json: unknown): T {\n return json as T;\n },\n serializeContract(_contract: Contract) {\n // IDB contracts are plain JSON-safe objects. Serialization is identity.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return _contract as any;\n },\n};\n\nconst idbMigrationsCapability = {\n createPlanner(_adapter: ControlAdapterInstance<\"idb\", \"idb\">) {\n return new IdbMigrationPlanner();\n },\n createRunner(_family: ControlFamilyInstance<\"idb\", unknown>) {\n return new IdbMigrationRunner();\n },\n contractToSchema(\n contract: Contract | null,\n _frameworkComponents?: ReadonlyArray<TargetBoundComponentDescriptor<\"idb\", \"idb\">>\n ) {\n return contractToIdbSchema(contract);\n },\n} satisfies TargetMigrationsCapability<\"idb\", \"idb\">;\n\nconst idbControlTargetDescription = {\n ...idbTargetDescriptorMeta,\n contractSerializer: idbContractSerializer,\n migrations: idbMigrationsCapability,\n create(): ControlTargetInstance<\"idb\", \"idb\"> {\n return { familyId: \"idb\", targetId: \"idb\" };\n },\n} satisfies MigratableTargetDescriptor<\"idb\", \"idb\">;\n\nexport default idbControlTargetDescription;\nexport { IdbMigrationControlDriverDescriptor, extractMigrationDriver } from \"../core/migration-driver\";\nexport type { IdbMigrationControlDriver } from \"../core/migration-driver\";\n"],"mappings":";;;;;;;;;;AAqBA,MAAM,wBAAsD;CAC1D,oBAAmD,MAAkB;EACnE,OAAO;CACT;CACA,kBAAkB,WAAqB;EAGrC,OAAO;CACT;AACF;AAEA,MAAM,0BAA0B;CAC9B,cAAc,UAAgD;EAC5D,OAAO,IAAI,oBAAoB;CACjC;CACA,aAAa,SAAgD;EAC3D,OAAO,IAAI,mBAAmB;CAChC;CACA,iBACE,UACA,sBACA;EACA,OAAO,oBAAoB,QAAQ;CACrC;AACF;AAEA,MAAM,8BAA8B;CAClC,GAAG;CACH,oBAAoB;CACpB,YAAY;CACZ,SAA8C;EAC5C,OAAO;GAAE,UAAU;GAAO,UAAU;EAAM;CAC5C;AACF"}
|