@prisma-next/migration-tools 0.11.0-dev.3 → 0.11.0-dev.30
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/{errors-DGYwcwXs.mjs → errors-CoEN114u.mjs} +14 -2
- package/dist/errors-CoEN114u.mjs.map +1 -0
- package/dist/exports/aggregate.d.mts +4 -4
- package/dist/exports/aggregate.d.mts.map +1 -1
- package/dist/exports/aggregate.mjs +5 -4
- package/dist/exports/aggregate.mjs.map +1 -1
- package/dist/exports/enumerate-migration-spaces.d.mts +53 -0
- package/dist/exports/enumerate-migration-spaces.d.mts.map +1 -0
- package/dist/exports/enumerate-migration-spaces.mjs +107 -0
- package/dist/exports/enumerate-migration-spaces.mjs.map +1 -0
- package/dist/exports/errors.d.mts.map +1 -1
- package/dist/exports/errors.mjs +1 -1
- package/dist/exports/graph.d.mts +1 -1
- package/dist/exports/hash.d.mts +2 -2
- package/dist/exports/hash.d.mts.map +1 -1
- package/dist/exports/invariants.d.mts +1 -1
- package/dist/exports/invariants.d.mts.map +1 -1
- package/dist/exports/invariants.mjs +1 -1
- package/dist/exports/io.d.mts +1 -1
- package/dist/exports/io.d.mts.map +1 -1
- package/dist/exports/io.mjs +1 -1
- package/dist/exports/metadata.d.mts +1 -1
- package/dist/exports/migration-graph.d.mts +9 -2
- package/dist/exports/migration-graph.d.mts.map +1 -0
- package/dist/exports/migration-graph.mjs +16 -2
- package/dist/exports/migration-graph.mjs.map +1 -0
- package/dist/exports/migration-list-types.d.mts +2 -0
- package/dist/exports/migration-list-types.mjs +1 -0
- package/dist/exports/migration-ts.d.mts.map +1 -1
- package/dist/exports/migration-ts.mjs.map +1 -1
- package/dist/exports/migration.d.mts +1 -1
- package/dist/exports/migration.d.mts.map +1 -1
- package/dist/exports/migration.mjs +2 -2
- package/dist/exports/migration.mjs.map +1 -1
- package/dist/exports/package.d.mts +1 -1
- package/dist/exports/ref-resolution.d.mts +2 -2
- package/dist/exports/ref-resolution.d.mts.map +1 -1
- package/dist/exports/ref-resolution.mjs +1 -1
- package/dist/exports/ref-resolution.mjs.map +1 -1
- package/dist/exports/refs.d.mts +15 -2
- package/dist/exports/refs.d.mts.map +1 -0
- package/dist/exports/refs.mjs +137 -2
- package/dist/exports/refs.mjs.map +1 -0
- package/dist/exports/spaces.d.mts +27 -2
- package/dist/exports/spaces.d.mts.map +1 -1
- package/dist/exports/spaces.mjs +9 -7
- package/dist/exports/spaces.mjs.map +1 -1
- package/dist/{graph-BrLXqoUc.d.mts → graph-C7AJPGV5.d.mts} +1 -1
- package/dist/graph-C7AJPGV5.d.mts.map +1 -0
- package/dist/hash-Cr4WIr4Z.mjs.map +1 -1
- package/dist/{invariants-0daYEzyo.mjs → invariants-lbJddL-S.mjs} +2 -2
- package/dist/{invariants-0daYEzyo.mjs.map → invariants-lbJddL-S.mjs.map} +1 -1
- package/dist/{io-BPLfzvZe.mjs → io-gHmDrSjQ.mjs} +3 -3
- package/dist/{io-BPLfzvZe.mjs.map → io-gHmDrSjQ.mjs.map} +1 -1
- package/dist/{migration-graph-De0dUZoC.d.mts → migration-graph-ABYqVsmv.d.mts} +3 -3
- package/dist/migration-graph-ABYqVsmv.d.mts.map +1 -0
- package/dist/{migration-graph-nlS4TRpn.mjs → migration-graph-C2iNX8dk.mjs} +2 -2
- package/dist/{migration-graph-nlS4TRpn.mjs.map → migration-graph-C2iNX8dk.mjs.map} +1 -1
- package/dist/migration-list-types-B-qimPet.d.mts +23 -0
- package/dist/migration-list-types-B-qimPet.d.mts.map +1 -0
- package/dist/op-schema-D5qkXfEf.mjs.map +1 -1
- package/dist/{package-DZj8YvD0.d.mts → package-DIttKL7X.d.mts} +1 -1
- package/dist/package-DIttKL7X.d.mts.map +1 -0
- package/dist/read-contract-space-contract-CwwlqKl_.mjs +82 -0
- package/dist/read-contract-space-contract-CwwlqKl_.mjs.map +1 -0
- package/dist/{refs-CDaNerhT.d.mts → refs-BaygQaFD.d.mts} +1 -1
- package/dist/refs-BaygQaFD.d.mts.map +1 -0
- package/dist/{refs-BDHo5l_g.mjs → refs-HhOkD8BT.mjs} +3 -3
- package/dist/refs-HhOkD8BT.mjs.map +1 -0
- package/dist/{read-contract-space-contract-DRueB4Aa.mjs → verify-contract-spaces-DxXWxGR0.mjs} +32 -80
- package/dist/verify-contract-spaces-DxXWxGR0.mjs.map +1 -0
- package/package.json +14 -6
- package/src/emit-contract-space-artefacts.ts +4 -3
- package/src/enumerate-migration-spaces.ts +127 -0
- package/src/errors.ts +15 -0
- package/src/exports/enumerate-migration-spaces.ts +4 -0
- package/src/exports/migration-graph.ts +1 -0
- package/src/exports/migration-list-types.ts +5 -0
- package/src/exports/refs.ts +8 -0
- package/src/exports/spaces.ts +3 -0
- package/src/graph-membership.ts +17 -0
- package/src/migration-list-types.ts +21 -0
- package/src/read-contract-space-head-ref.ts +5 -2
- package/src/refs/snapshot.ts +197 -0
- package/src/refs.ts +3 -1
- package/src/space-layout.ts +30 -0
- package/dist/errors-DGYwcwXs.mjs.map +0 -1
- package/dist/graph-BrLXqoUc.d.mts.map +0 -1
- package/dist/migration-graph-De0dUZoC.d.mts.map +0 -1
- package/dist/package-DZj8YvD0.d.mts.map +0 -1
- package/dist/read-contract-space-contract-DRueB4Aa.mjs.map +0 -1
- package/dist/refs-BDHo5l_g.mjs.map +0 -1
- package/dist/refs-CDaNerhT.d.mts.map +0 -1
- /package/dist/{metadata-BFX0xdz8.d.mts → metadata-B4Wy6zor.d.mts} +0 -0
package/src/exports/refs.ts
CHANGED
|
@@ -8,3 +8,11 @@ export {
|
|
|
8
8
|
validateRefValue,
|
|
9
9
|
writeRef,
|
|
10
10
|
} from '../refs';
|
|
11
|
+
export type { ContractIR } from '../refs/snapshot';
|
|
12
|
+
export {
|
|
13
|
+
deleteRefPaired,
|
|
14
|
+
deleteRefSnapshot,
|
|
15
|
+
readRefSnapshot,
|
|
16
|
+
writeRefPaired,
|
|
17
|
+
writeRefSnapshot,
|
|
18
|
+
} from '../refs/snapshot';
|
package/src/exports/spaces.ts
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { EMPTY_CONTRACT_HASH } from './constants';
|
|
2
|
+
import { errorHashNotInGraph } from './errors';
|
|
3
|
+
import type { MigrationGraph } from './graph';
|
|
4
|
+
|
|
5
|
+
export function isGraphNode(hash: string, graph: MigrationGraph): boolean {
|
|
6
|
+
if (hash === EMPTY_CONTRACT_HASH) {
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
return graph.nodes.has(hash);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function assertHashIsGraphNode(hash: string, graph: MigrationGraph): asserts hash is string {
|
|
13
|
+
if (isGraphNode(hash, graph)) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
throw errorHashNotInGraph(hash, graph);
|
|
17
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface MigrationListEntry {
|
|
2
|
+
readonly dirName: string;
|
|
3
|
+
readonly from: string | null;
|
|
4
|
+
readonly to: string;
|
|
5
|
+
readonly migrationHash: string;
|
|
6
|
+
readonly operationCount: number;
|
|
7
|
+
readonly createdAt: string;
|
|
8
|
+
readonly refs: readonly string[];
|
|
9
|
+
readonly providedInvariants: readonly string[];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface MigrationSpaceListEntry {
|
|
13
|
+
readonly spaceId: string;
|
|
14
|
+
readonly migrations: readonly MigrationListEntry[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface MigrationListResult {
|
|
18
|
+
readonly ok: true;
|
|
19
|
+
readonly spaces: readonly MigrationSpaceListEntry[];
|
|
20
|
+
readonly summary: string;
|
|
21
|
+
}
|
|
@@ -2,7 +2,7 @@ import { readFile } from 'node:fs/promises';
|
|
|
2
2
|
import type { ContractSpaceHeadRef } from '@prisma-next/framework-components/control';
|
|
3
3
|
import { join } from 'pathe';
|
|
4
4
|
import { errorInvalidJson, errorInvalidRefFile } from './errors';
|
|
5
|
-
import { assertValidSpaceId } from './space-layout';
|
|
5
|
+
import { assertValidSpaceId, spaceMigrationDirectory, spaceRefsDirectory } from './space-layout';
|
|
6
6
|
|
|
7
7
|
export type { ContractSpaceHeadRef };
|
|
8
8
|
|
|
@@ -29,7 +29,10 @@ export async function readContractSpaceHeadRef(
|
|
|
29
29
|
): Promise<ContractSpaceHeadRef | null> {
|
|
30
30
|
assertValidSpaceId(spaceId);
|
|
31
31
|
|
|
32
|
-
const filePath = join(
|
|
32
|
+
const filePath = join(
|
|
33
|
+
spaceRefsDirectory(spaceMigrationDirectory(projectMigrationsDir, spaceId)),
|
|
34
|
+
'head.json',
|
|
35
|
+
);
|
|
33
36
|
|
|
34
37
|
let raw: string;
|
|
35
38
|
try {
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
import { access, mkdir, readFile, rename, unlink, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { canonicalizeJson } from '@prisma-next/framework-components/utils';
|
|
4
|
+
import { type } from 'arktype';
|
|
5
|
+
import { basename, dirname, join } from 'pathe';
|
|
6
|
+
import { errorInvalidRefFile, errorInvalidRefName, MigrationToolsError } from '../errors';
|
|
7
|
+
import { deleteRef, type RefEntry, validateRefName, writeRef } from '../refs';
|
|
8
|
+
|
|
9
|
+
export interface ContractIR {
|
|
10
|
+
readonly contract: unknown;
|
|
11
|
+
readonly contractDts: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const ContractIrSchema = type({
|
|
15
|
+
targetFamily: 'string',
|
|
16
|
+
target: 'string',
|
|
17
|
+
profileHash: 'string',
|
|
18
|
+
storage: type({
|
|
19
|
+
storageHash: 'string',
|
|
20
|
+
}),
|
|
21
|
+
models: 'object',
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
function hasErrnoCode(error: unknown, code: string): boolean {
|
|
25
|
+
return error instanceof Error && (error as { code?: string }).code === code;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function snapshotJsonPath(refsDir: string, name: string): string {
|
|
29
|
+
return join(refsDir, `${name}.contract.json`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function snapshotDtsPath(refsDir: string, name: string): string {
|
|
33
|
+
return join(refsDir, `${name}.contract.d.ts`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function tmpPathFor(finalPath: string): string {
|
|
37
|
+
const dir = dirname(finalPath);
|
|
38
|
+
const fileName = basename(finalPath);
|
|
39
|
+
return join(dir, `.${fileName}.${Date.now()}-${randomBytes(4).toString('hex')}.tmp`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function atomicWriteFile(finalPath: string, content: string): Promise<void> {
|
|
43
|
+
const dir = dirname(finalPath);
|
|
44
|
+
await mkdir(dir, { recursive: true });
|
|
45
|
+
const tmpPath = tmpPathFor(finalPath);
|
|
46
|
+
await writeFile(tmpPath, content);
|
|
47
|
+
await rename(tmpPath, finalPath);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function unlinkIfExists(filePath: string): Promise<void> {
|
|
51
|
+
try {
|
|
52
|
+
await unlink(filePath);
|
|
53
|
+
} catch (error) {
|
|
54
|
+
if (hasErrnoCode(error, 'ENOENT')) return;
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function parseContractSnapshotJson(filePath: string, raw: string): unknown {
|
|
60
|
+
let parsed: unknown;
|
|
61
|
+
try {
|
|
62
|
+
parsed = JSON.parse(raw);
|
|
63
|
+
} catch {
|
|
64
|
+
throw errorInvalidRefFile(filePath, 'Failed to parse as JSON');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const result = ContractIrSchema(parsed);
|
|
68
|
+
if (result instanceof type.errors) {
|
|
69
|
+
throw errorInvalidRefFile(filePath, result.summary);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export async function writeRefSnapshot(
|
|
76
|
+
refsDir: string,
|
|
77
|
+
name: string,
|
|
78
|
+
snapshot: ContractIR,
|
|
79
|
+
): Promise<void> {
|
|
80
|
+
if (!validateRefName(name)) {
|
|
81
|
+
throw errorInvalidRefName(name);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const jsonPath = snapshotJsonPath(refsDir, name);
|
|
85
|
+
const dtsPath = snapshotDtsPath(refsDir, name);
|
|
86
|
+
const jsonContent = `${canonicalizeJson(snapshot.contract)}\n`;
|
|
87
|
+
const dtsContent = snapshot.contractDts.endsWith('\n')
|
|
88
|
+
? snapshot.contractDts
|
|
89
|
+
: `${snapshot.contractDts}\n`;
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
await atomicWriteFile(jsonPath, jsonContent);
|
|
93
|
+
} catch (error) {
|
|
94
|
+
await unlinkIfExists(jsonPath);
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
await atomicWriteFile(dtsPath, dtsContent);
|
|
100
|
+
} catch (error) {
|
|
101
|
+
await unlinkIfExists(jsonPath);
|
|
102
|
+
await unlinkIfExists(dtsPath);
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export async function readRefSnapshot(refsDir: string, name: string): Promise<ContractIR | null> {
|
|
108
|
+
if (!validateRefName(name)) {
|
|
109
|
+
throw errorInvalidRefName(name);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const jsonPath = snapshotJsonPath(refsDir, name);
|
|
113
|
+
const dtsPath = snapshotDtsPath(refsDir, name);
|
|
114
|
+
|
|
115
|
+
let raw: string;
|
|
116
|
+
try {
|
|
117
|
+
raw = await readFile(jsonPath, 'utf-8');
|
|
118
|
+
} catch (error) {
|
|
119
|
+
if (hasErrnoCode(error, 'ENOENT')) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const contract = parseContractSnapshotJson(jsonPath, raw);
|
|
126
|
+
|
|
127
|
+
let contractDts: string;
|
|
128
|
+
try {
|
|
129
|
+
contractDts = await readFile(dtsPath, 'utf-8');
|
|
130
|
+
} catch (error) {
|
|
131
|
+
if (hasErrnoCode(error, 'ENOENT')) {
|
|
132
|
+
throw errorInvalidRefFile(dtsPath, 'Missing paired contract.d.ts snapshot file');
|
|
133
|
+
}
|
|
134
|
+
throw error;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return { contract, contractDts };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export async function deleteRefSnapshot(refsDir: string, name: string): Promise<void> {
|
|
141
|
+
if (!validateRefName(name)) {
|
|
142
|
+
throw errorInvalidRefName(name);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
await unlinkIfExists(snapshotJsonPath(refsDir, name));
|
|
146
|
+
await unlinkIfExists(snapshotDtsPath(refsDir, name));
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export async function writeRefPaired(
|
|
150
|
+
refsDir: string,
|
|
151
|
+
name: string,
|
|
152
|
+
entry: RefEntry,
|
|
153
|
+
snapshot: ContractIR,
|
|
154
|
+
): Promise<void> {
|
|
155
|
+
await writeRefSnapshot(refsDir, name, snapshot);
|
|
156
|
+
try {
|
|
157
|
+
await writeRef(refsDir, name, entry);
|
|
158
|
+
} catch (writeError) {
|
|
159
|
+
try {
|
|
160
|
+
await deleteRefSnapshot(refsDir, name);
|
|
161
|
+
} catch {
|
|
162
|
+
// Rollback failure is secondary; preserve the original writeRef error.
|
|
163
|
+
}
|
|
164
|
+
throw writeError;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function isUnknownRefError(error: unknown): boolean {
|
|
169
|
+
return MigrationToolsError.is(error) && error.code === 'MIGRATION.UNKNOWN_REF';
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async function snapshotFilesExist(refsDir: string, name: string): Promise<boolean> {
|
|
173
|
+
if (!validateRefName(name)) {
|
|
174
|
+
throw errorInvalidRefName(name);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const paths = [snapshotJsonPath(refsDir, name), snapshotDtsPath(refsDir, name)];
|
|
178
|
+
const checks = await Promise.allSettled(paths.map((filePath) => access(filePath)));
|
|
179
|
+
return checks.some((result) => result.status === 'fulfilled');
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export async function deleteRefPaired(refsDir: string, name: string): Promise<void> {
|
|
183
|
+
if (await snapshotFilesExist(refsDir, name)) {
|
|
184
|
+
try {
|
|
185
|
+
await deleteRef(refsDir, name);
|
|
186
|
+
} catch (error) {
|
|
187
|
+
if (!isUnknownRefError(error)) {
|
|
188
|
+
throw error;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
await deleteRefSnapshot(refsDir, name);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
await deleteRef(refsDir, name);
|
|
196
|
+
await deleteRefSnapshot(refsDir, name);
|
|
197
|
+
}
|
package/src/refs.ts
CHANGED
|
@@ -94,7 +94,9 @@ export async function readRefs(refsDir: string): Promise<Refs> {
|
|
|
94
94
|
throw error;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
const jsonFiles = entries.filter(
|
|
97
|
+
const jsonFiles = entries.filter(
|
|
98
|
+
(entry) => entry.endsWith('.json') && !entry.endsWith('.contract.json'),
|
|
99
|
+
);
|
|
98
100
|
const refs: Record<string, RefEntry> = {};
|
|
99
101
|
|
|
100
102
|
for (const jsonFile of jsonFiles) {
|
package/src/space-layout.ts
CHANGED
|
@@ -46,3 +46,33 @@ export function spaceMigrationDirectory(projectMigrationsDir: string, spaceId: s
|
|
|
46
46
|
assertValidSpaceId(spaceId);
|
|
47
47
|
return join(projectMigrationsDir, spaceId);
|
|
48
48
|
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Per-space subdirectory name reserved for the ref store
|
|
52
|
+
* (`migrations/<space>/<SPACE_REFS_DIRNAME>/*.json`). Single source of
|
|
53
|
+
* truth: every helper that composes a per-space refs path imports this
|
|
54
|
+
* constant, and the enumerator uses it (via
|
|
55
|
+
* {@link RESERVED_SPACE_SUBDIR_NAMES}) to exclude reserved names from
|
|
56
|
+
* the contract-space candidate list.
|
|
57
|
+
*/
|
|
58
|
+
export const SPACE_REFS_DIRNAME = 'refs';
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Names reserved as per-space subdirectories of `migrations/<space>/`.
|
|
62
|
+
* Used by the enumerator to filter contract-space candidates so a
|
|
63
|
+
* reserved name (e.g. a top-level `migrations/refs/` left in the wrong
|
|
64
|
+
* place) is never enumerated as a phantom contract space. Currently
|
|
65
|
+
* holds `SPACE_REFS_DIRNAME`; extend if future per-space layouts add
|
|
66
|
+
* more reserved subdirectories.
|
|
67
|
+
*/
|
|
68
|
+
export const RESERVED_SPACE_SUBDIR_NAMES: ReadonlySet<string> = new Set([SPACE_REFS_DIRNAME]);
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Resolve the per-space refs directory for `spaceMigrationsDir`
|
|
72
|
+
* (typically the value returned by {@link spaceMigrationDirectory}).
|
|
73
|
+
* Composes the canonical {@link SPACE_REFS_DIRNAME} so callers do not
|
|
74
|
+
* hard-code the literal.
|
|
75
|
+
*/
|
|
76
|
+
export function spaceRefsDirectory(spaceMigrationsDir: string): string {
|
|
77
|
+
return join(spaceMigrationsDir, SPACE_REFS_DIRNAME);
|
|
78
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"errors-DGYwcwXs.mjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["import { ifDefined } from '@prisma-next/utils/defined';\nimport { basename, dirname, relative } from 'pathe';\n\n/**\n * Build the canonical \"re-emit this package\" remediation hint.\n *\n * Every on-disk migration package ships its own `migration.ts` author-time\n * file. Running it regenerates `migration.json` and `ops.json` with the\n * correct hash + metadata, so it is the right primitive whenever a single\n * package's on-disk artifacts are missing, malformed, or otherwise corrupt.\n * Pointing users at `migration plan` would emit a *new* package rather than\n * heal the broken one.\n */\nfunction reemitHint(dir: string, fallback?: string): string {\n const relativeDir = relative(process.cwd(), dir);\n const reemit = `Re-emit the package by running \\`node \"${relativeDir}/migration.ts\"\\``;\n return fallback ? `${reemit}, ${fallback}` : `${reemit}.`;\n}\n\n/**\n * Structured error for migration tooling operations.\n *\n * Follows the NAMESPACE.SUBCODE convention from ADR 027. All codes live under\n * the MIGRATION namespace. These are tooling-time errors (file I/O, hash\n * verification, migration history reconstruction), distinct from the runtime\n * MIGRATION.* codes for apply-time failures (PRECHECK_FAILED, POSTCHECK_FAILED,\n * etc.).\n *\n * Fields:\n * - code: Stable machine-readable code (MIGRATION.SUBCODE)\n * - category: Always 'MIGRATION'\n * - why: Explains the cause in plain language\n * - fix: Actionable remediation step\n * - details: Machine-readable structured data for agents\n */\nexport class MigrationToolsError extends Error {\n readonly code: string;\n readonly category = 'MIGRATION' as const;\n readonly why: string;\n readonly fix: string;\n readonly details: Record<string, unknown> | undefined;\n\n constructor(\n code: string,\n summary: string,\n options: {\n readonly why: string;\n readonly fix: string;\n readonly details?: Record<string, unknown>;\n },\n ) {\n super(summary);\n this.name = 'MigrationToolsError';\n this.code = code;\n this.why = options.why;\n this.fix = options.fix;\n this.details = options.details;\n }\n\n static is(error: unknown): error is MigrationToolsError {\n if (!(error instanceof Error)) return false;\n const candidate = error as MigrationToolsError;\n return candidate.name === 'MigrationToolsError' && typeof candidate.code === 'string';\n }\n}\n\nexport function errorDirectoryExists(dir: string): MigrationToolsError {\n return new MigrationToolsError('MIGRATION.DIR_EXISTS', 'Migration directory already exists', {\n why: `The directory \"${dir}\" already exists. Each migration must have a unique directory.`,\n fix: 'Use --name to pick a different name, or delete the existing directory and re-run.',\n details: { dir },\n });\n}\n\nexport function errorMissingFile(file: string, dir: string): MigrationToolsError {\n return new MigrationToolsError('MIGRATION.FILE_MISSING', `Missing ${file}`, {\n why: `Expected \"${file}\" in \"${dir}\" but the file does not exist.`,\n fix: reemitHint(\n dir,\n 'or delete the directory if the migration is unwanted and the source TypeScript is gone.',\n ),\n details: { file, dir },\n });\n}\n\nexport function errorInvalidJson(filePath: string, parseError: string): MigrationToolsError {\n return new MigrationToolsError('MIGRATION.INVALID_JSON', 'Invalid JSON in migration file', {\n why: `Failed to parse \"${filePath}\": ${parseError}`,\n fix: reemitHint(dirname(filePath), 'or restore the directory from version control.'),\n details: { filePath, parseError },\n });\n}\n\nexport function errorInvalidManifest(filePath: string, reason: string): MigrationToolsError {\n return new MigrationToolsError('MIGRATION.INVALID_MANIFEST', 'Invalid migration manifest', {\n why: `Migration manifest at \"${filePath}\" is invalid: ${reason}`,\n fix: reemitHint(dirname(filePath), 'or restore the directory from version control.'),\n details: { filePath, reason },\n });\n}\n\nexport function errorInvalidOperationEntry(index: number, reason: string): MigrationToolsError {\n return new MigrationToolsError(\n 'MIGRATION.INVALID_OPERATION_ENTRY',\n 'Migration operation entry is malformed',\n {\n why: `Operation at index ${index} returned by the migration class failed schema validation: ${reason}.`,\n fix: \"Update the migration class so each entry of `operations` carries `id` (string), `label` (string), and `operationClass` (one of 'additive' | 'widening' | 'destructive' | 'data').\",\n details: { index, reason },\n },\n );\n}\n\nexport function errorInvalidSlug(slug: string): MigrationToolsError {\n return new MigrationToolsError('MIGRATION.INVALID_NAME', 'Invalid migration name', {\n why: `The slug \"${slug}\" contains no valid characters after sanitization (only a-z, 0-9 are kept).`,\n fix: 'Provide a name with at least one alphanumeric character, e.g. --name add_users.',\n details: { slug },\n });\n}\n\nexport function errorInvalidDestName(destName: string): MigrationToolsError {\n return new MigrationToolsError('MIGRATION.INVALID_DEST_NAME', 'Invalid copy destination name', {\n why: `The destination name \"${destName}\" must be a single path segment (no \"..\" or directory separators).`,\n fix: 'Use a simple file name such as \"contract.json\" for each destination in the copy list.',\n details: { destName },\n });\n}\n\nexport function errorInvalidSpaceId(spaceId: string): MigrationToolsError {\n return new MigrationToolsError(\n 'MIGRATION.INVALID_SPACE_ID',\n 'Invalid contract space identifier',\n {\n why: `The space id \"${spaceId}\" does not match the required pattern /^[a-z][a-z0-9_-]{0,63}$/. Space ids are used as filesystem directory names under \\`migrations/\\`, so the pattern is conservative on purpose.`,\n fix: 'Pick a lowercase identifier that begins with a letter and contains only lowercase letters, digits, hyphens, or underscores; max 64 characters total.',\n details: { spaceId },\n },\n );\n}\n\nexport function errorDescriptorHeadHashMismatch(args: {\n readonly extensionId: string;\n readonly recomputedHash: string;\n readonly headRefHash: string;\n}): MigrationToolsError {\n const { extensionId, recomputedHash, headRefHash } = args;\n return new MigrationToolsError(\n 'MIGRATION.DESCRIPTOR_HEAD_HASH_MISMATCH',\n \"Extension descriptor's headRef.hash does not match its contractJson\",\n {\n why: `Extension \"${extensionId}\" publishes a \\`contractSpace\\` whose \\`headRef.hash\\` (${headRefHash}) does not match the canonical hash recomputed from \\`contractSpace.contractJson\\` (${recomputedHash}). This means the extension descriptor was published with stale \\`headRef.hash\\` — typically because the contract was bumped without rerunning the extension's emit pipeline.`,\n fix: 'Re-run the extension authoring pipeline so `contractJson.storage.storageHash` and `headRef.hash` agree, then republish the extension. If you are the extension author and you intentionally bumped `contractJson`, recompute and update `headRef.hash` (and refresh any on-disk migration metadata that derives from it).',\n details: { extensionId, recomputedHash, headRefHash },\n },\n );\n}\n\nexport function errorDuplicateSpaceId(spaceId: string): MigrationToolsError {\n return new MigrationToolsError(\n 'MIGRATION.DUPLICATE_SPACE_ID',\n 'Duplicate contract space identifier',\n {\n why: `The space id \"${spaceId}\" appears more than once in the per-space planner input. Each space id must be unique across the inputs (the per-space planner emits one output entry per id).`,\n fix: 'Deduplicate the inputs before passing them to `planAllSpaces` — typically by checking your `extensionPacks` declaration for repeated entries.',\n details: { spaceId },\n },\n );\n}\n\nexport function errorSameSourceAndTarget(dir: string, hash: string): MigrationToolsError {\n const dirName = basename(dir);\n return new MigrationToolsError(\n 'MIGRATION.SAME_SOURCE_AND_TARGET',\n 'Migration without data-transform operations has same source and target',\n {\n why: `Migration \"${dirName}\" has from === to === \"${hash}\" and declares no data-transform operations. Self-edges are only allowed when the migration runs at least one dataTransform — otherwise the migration is a no-op.`,\n fix: reemitHint(\n dir,\n 'and either change the contract so from ≠ to, add a dataTransform op, or delete the directory if the migration is unwanted.',\n ),\n details: { dirName, hash },\n },\n );\n}\n\nexport function errorAmbiguousTarget(\n branchTips: readonly string[],\n context?: {\n divergencePoint: string;\n branches: readonly {\n tip: string;\n edges: readonly { dirName: string; from: string; to: string }[];\n }[];\n },\n): MigrationToolsError {\n const divergenceInfo = context\n ? `\\nDivergence point: ${context.divergencePoint}\\nBranches:\\n${context.branches.map((b) => ` → ${b.tip} (${b.edges.length} edge(s): ${b.edges.map((e) => e.dirName).join(' → ') || 'direct'})`).join('\\n')}`\n : '';\n return new MigrationToolsError('MIGRATION.AMBIGUOUS_TARGET', 'Ambiguous migration target', {\n why: `The migration history has diverged into multiple branches: ${branchTips.join(', ')}. This typically happens when two developers plan migrations from the same starting point.${divergenceInfo}`,\n fix: 'Use `ref set <name> <hash>` to target a specific branch, delete one of the conflicting migration directories and re-run `migration plan`, or use --from <hash> to explicitly select a starting point.',\n details: {\n branchTips,\n ...(context ? { divergencePoint: context.divergencePoint, branches: context.branches } : {}),\n },\n });\n}\n\nexport function errorNoInitialMigration(nodes: readonly string[]): MigrationToolsError {\n return new MigrationToolsError('MIGRATION.NO_INITIAL_MIGRATION', 'No initial migration found', {\n why: `No migration starts from the empty contract state (known hashes: ${nodes.join(', ')}). At least one migration must originate from the empty state.`,\n fix: 'Inspect the migrations directory for corrupted migration.json files. At least one migration must start from the empty contract hash.',\n details: { nodes },\n });\n}\n\nexport function errorInvalidRefs(refsPath: string, reason: string): MigrationToolsError {\n return new MigrationToolsError('MIGRATION.INVALID_REFS', 'Invalid refs.json', {\n why: `refs.json at \"${refsPath}\" is invalid: ${reason}`,\n fix: 'Ensure refs.json is a flat object mapping valid ref names to contract hash strings.',\n details: { path: refsPath, reason },\n });\n}\n\nexport function errorInvalidRefFile(filePath: string, reason: string): MigrationToolsError {\n return new MigrationToolsError('MIGRATION.INVALID_REF_FILE', 'Invalid ref file', {\n why: `Ref file at \"${filePath}\" is invalid: ${reason}`,\n fix: 'Ensure the ref file contains valid JSON with { \"hash\": \"sha256:<64 hex chars>\", \"invariants\": [\"...\"] }.',\n details: { path: filePath, reason },\n });\n}\n\nexport function errorInvalidRefName(refName: string): MigrationToolsError {\n return new MigrationToolsError('MIGRATION.INVALID_REF_NAME', 'Invalid ref name', {\n why: `Ref name \"${refName}\" is invalid. Names must be lowercase alphanumeric with hyphens or forward slashes (no \".\" or \"..\" segments).`,\n fix: `Use a valid ref name (e.g., \"staging\", \"envs/production\").`,\n details: { refName },\n });\n}\n\nexport function errorNoTarget(reachableHashes: readonly string[]): MigrationToolsError {\n return new MigrationToolsError('MIGRATION.NO_TARGET', 'No migration target could be resolved', {\n why: `The migration history contains cycles and no target can be resolved automatically (reachable hashes: ${reachableHashes.join(', ')}). This typically happens after rollback migrations (e.g., C1→C2→C1).`,\n fix: 'Use --from <hash> to specify the planning origin explicitly.',\n details: { reachableHashes },\n });\n}\n\nexport function errorInvalidRefValue(value: string): MigrationToolsError {\n return new MigrationToolsError('MIGRATION.INVALID_REF_VALUE', 'Invalid ref value', {\n why: `Ref value \"${value}\" is not a valid contract hash. Values must be in the format \"sha256:<64 hex chars>\" or \"sha256:empty\".`,\n fix: 'Use a valid storage hash from `prisma-next contract emit` output or an existing migration.',\n details: { value },\n });\n}\n\nexport function errorDuplicateMigrationHash(migrationHash: string): MigrationToolsError {\n return new MigrationToolsError(\n 'MIGRATION.DUPLICATE_MIGRATION_HASH',\n 'Duplicate migrationHash in migration graph',\n {\n why: `Multiple migrations share migrationHash \"${migrationHash}\". Each migration must have a unique content-addressed identity.`,\n fix: 'Regenerate one of the conflicting migrations so each migrationHash is unique, then re-run migration commands.',\n details: { migrationHash },\n },\n );\n}\n\nexport function errorInvalidInvariantId(invariantId: string): MigrationToolsError {\n return new MigrationToolsError('MIGRATION.INVALID_INVARIANT_ID', 'Invalid invariantId', {\n why: `invariantId ${JSON.stringify(invariantId)} is invalid. Ids must be non-empty and contain no whitespace or control characters (including Unicode whitespace like NBSP); other content (kebab-case, camelCase, namespaced, Unicode letters) is allowed.`,\n fix: 'Pick an invariantId without spaces, tabs, newlines, or control characters — e.g. \"backfill-user-phone\", \"users/backfill-phone\", or \"BackfillUserPhone\".',\n details: { invariantId },\n });\n}\n\nexport function errorDuplicateInvariantInEdge(invariantId: string): MigrationToolsError {\n return new MigrationToolsError(\n 'MIGRATION.DUPLICATE_INVARIANT_IN_EDGE',\n 'Duplicate invariantId on a single migration',\n {\n why: `invariantId \"${invariantId}\" is declared by more than one dataTransform on the same migration. The marker stores invariants as a set and the routing layer treats them as edge-level, so two ops cannot share a routing identity.`,\n fix: 'Rename one of the conflicting dataTransform invariantIds, or drop invariantId on the op that does not need to be routing-visible.',\n details: { invariantId },\n },\n );\n}\n\nexport function errorProvidedInvariantsMismatch(\n filePath: string,\n stored: readonly string[],\n derived: readonly string[],\n): MigrationToolsError {\n const storedSet = new Set(stored);\n const derivedSet = new Set(derived);\n const missing = [...derivedSet].filter((id) => !storedSet.has(id));\n const extra = [...storedSet].filter((id) => !derivedSet.has(id));\n // When sets agree but arrays don't, the only difference is ordering — call\n // it out so the reader doesn't stare at two visually-identical arrays.\n // Canonical providedInvariants is sorted ascending; a manifest with the\n // same ids in a different order is still a mismatch (the hash check would\n // also fail), but the human-readable diagnostic is otherwise unhelpful.\n const orderingOnly = missing.length === 0 && extra.length === 0;\n const why = orderingOnly\n ? `migration.json at \"${filePath}\" stores providedInvariants ${JSON.stringify(stored)}, but the canonical value derived from ops.json is ${JSON.stringify(derived)} — same ids, different order. Canonical providedInvariants is sorted ascending.`\n : `migration.json at \"${filePath}\" stores providedInvariants ${JSON.stringify(stored)}, but the value derived from ops.json is ${JSON.stringify(derived)}. The manifest copy was likely hand-edited without re-emitting.`;\n return new MigrationToolsError(\n 'MIGRATION.PROVIDED_INVARIANTS_MISMATCH',\n 'providedInvariants on migration.json disagrees with ops.json',\n {\n why,\n fix: reemitHint(dirname(filePath), 'or restore the directory from version control.'),\n details: { filePath, stored, derived, difference: { missing, extra } },\n },\n );\n}\n\n/**\n * Wire-shape edge surfaced through the JSON envelope's\n * `meta.structuralPath` of `MIGRATION.NO_INVARIANT_PATH`. Slim by design —\n * authoring metadata (`createdAt`, `labels`) lives on `MigrationEdge` but\n * is intentionally dropped here so the envelope stays stable across\n * graph-internal refactors.\n *\n * Stability: any field added here is part of the public CLI JSON contract.\n * Callers (CLI consumers, agents) must be able to treat\n * `(dirName, migrationHash, from, to, invariants)` as the canonical shape.\n */\nexport interface NoInvariantPathStructuralEdge {\n readonly dirName: string;\n readonly migrationHash: string;\n readonly from: string;\n readonly to: string;\n readonly invariants: readonly string[];\n}\n\nexport function errorNoInvariantPath(args: {\n readonly refName?: string;\n readonly required: readonly string[];\n readonly missing: readonly string[];\n readonly structuralPath: readonly NoInvariantPathStructuralEdge[];\n}): MigrationToolsError {\n const { refName, required, missing, structuralPath } = args;\n const refClause = refName ? `Ref \"${refName}\"` : 'Target';\n const missingList = missing.map((id) => JSON.stringify(id)).join(', ');\n const requiredList = required.map((id) => JSON.stringify(id)).join(', ');\n return new MigrationToolsError(\n 'MIGRATION.NO_INVARIANT_PATH',\n 'No path covers the required invariants',\n {\n why: `${refClause} requires invariants the reachable path doesn't cover. required=[${requiredList}], missing=[${missingList}].`,\n fix: 'Add a migration on the path that runs `dataTransform({ invariantId: \"<id>\", … })` for each missing invariant, or retarget the ref to a hash whose path already provides them.',\n details: {\n required,\n missing,\n structuralPath,\n ...ifDefined('refName', refName),\n },\n },\n );\n}\n\nexport function errorUnknownInvariant(args: {\n readonly refName?: string;\n readonly unknown: readonly string[];\n readonly declared: readonly string[];\n}): MigrationToolsError {\n const { refName, unknown, declared } = args;\n const refClause = refName ? `Ref \"${refName}\" declares` : 'Declares';\n const unknownList = unknown.map((id) => JSON.stringify(id)).join(', ');\n return new MigrationToolsError(\n 'MIGRATION.UNKNOWN_INVARIANT',\n 'Ref declares invariants no migration in the graph provides',\n {\n why: `${refClause} invariants no migration in the graph provides. unknown=[${unknownList}].`,\n fix: 'Either the ref has a typo, or the declaring migration has not been authored/attested yet. Re-check the ref file and the migrations directory.',\n details: {\n unknown,\n declared,\n ...ifDefined('refName', refName),\n },\n },\n );\n}\n\nexport function errorMigrationHashMismatch(\n dir: string,\n storedHash: string,\n computedHash: string,\n): MigrationToolsError {\n // Render a cwd-relative path in the human-readable diagnostic so users\n // running CLI commands from the project root see a familiar short path.\n // Keep the absolute path in `details.dir` for machine consumers.\n const relativeDir = relative(process.cwd(), dir);\n return new MigrationToolsError('MIGRATION.HASH_MISMATCH', 'Migration package is corrupt', {\n why: `Stored migrationHash \"${storedHash}\" does not match the recomputed hash \"${computedHash}\" for \"${relativeDir}\". The migration.json or ops.json has been edited or partially written since emit.`,\n fix: reemitHint(dir, 'or restore the directory from version control.'),\n details: { dir, storedHash, computedHash },\n });\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"graph-BrLXqoUc.d.mts","names":[],"sources":["../src/graph.ts"],"mappings":";;AAIA;;;UAAiB,aAAA;EAAA,SACN,IAAA;EAAA,SACA,EAAA;EAAA,SACA,aAAA;EAAA,SACA,OAAA;EAAA,SACA,SAAA;EAAA,SACA,MAAA;EAMA;;;AAGX;;EAHW,SAAA,UAAA;AAAA;AAAA,UAGM,cAAA;EAAA,SACN,KAAA,EAAO,WAAA;EAAA,SACP,YAAA,EAAc,WAAA,kBAA6B,aAAA;EAAA,SAC3C,YAAA,EAAc,WAAA,kBAA6B,aAAA;EAAA,SAC3C,eAAA,EAAiB,WAAA,SAAoB,aAAA;AAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"migration-graph-De0dUZoC.d.mts","names":[],"sources":["../src/migration-graph.ts"],"mappings":";;;;iBAsCgB,gBAAA,CAAiB,QAAA,WAAmB,sBAAA,KAA2B,cAAA;;AAA/E;;;;;;;iBAqFgB,QAAA,CACd,KAAA,EAAO,cAAA,EACP,QAAA,UACA,MAAA,oBACU,aAAA;;AAJZ;;;;;;;;;;;AAgDA;;;;;;;iBAAgB,sBAAA,CACd,KAAA,EAAO,cAAA,EACP,QAAA,UACA,MAAA,UACA,QAAA,EAAU,WAAA,oBACA,aAAA;AAAA,UAsFK,YAAA;EAAA,SACN,YAAA,WAAuB,aAAA;EAAA,SACvB,QAAA;EAAA,SACA,MAAA;EAAA,SACA,gBAAA;EAAA,SACA,eAAA;EAAA,SACA,OAAA;EA5Fc;EAAA,SA8Fd,kBAAA;EARM;;;;;EAAA,SAcN,mBAAA;AAAA;;;;;;;;;AAoBX;;;;;;;;;KAAY,eAAA;EAAA,SACG,IAAA;EAAA,SAAqB,QAAA,EAAU,YAAA;AAAA;EAAA,SAC/B,IAAA;AAAA;EAAA,SAEA,IAAA;EAAA,SACA,cAAA,WAAyB,aAAA;EAAA,SACzB,OAAA;AAAA;;;;;AAyBf;;;UAfiB,2BAAA;EAAA,SACN,OAAA;EAAA,SACA,QAAA,GAAW,WAAA;AAAA;;;;;;;;;;;iBAaN,oBAAA,CACd,KAAA,EAAO,cAAA,EACP,QAAA,UACA,MAAA,UACA,OAAA,GAAS,2BAAA,GACR,eAAA;;;;;iBAqLa,mBAAA,CAAoB,KAAA,EAAO,cAAA,EAAgB,QAAA;;;;AAkB3D;;;;;iBAAgB,QAAA,CAAS,KAAA,EAAO,cAAA;;;;;;iBAwChB,mBAAA,CAAoB,KAAA,EAAO,cAAA,GAAiB,aAAA;AAAA,iBAQ5C,YAAA,CAAa,KAAA,EAAO,cAAA;AAAA,iBA8DpB,aAAA,CAAc,KAAA,EAAO,cAAA,YAA0B,aAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"package-DZj8YvD0.d.mts","names":[],"sources":["../src/package.ts"],"mappings":";;;KAKY,YAAA,YAAwB,sBAAA;;AAApC;;;;;AAaA;;;;;UAAiB,sBAAA,SAA+B,gBAAA;EAAA,SACrC,OAAA;AAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"read-contract-space-contract-DRueB4Aa.mjs","names":["hasErrnoCode","hasErrnoCode"],"sources":["../src/space-layout.ts","../src/read-contract-space-head-ref.ts","../src/verify-contract-spaces.ts","../src/read-contract-space-contract.ts"],"sourcesContent":["import { APP_SPACE_ID } from '@prisma-next/framework-components/control';\nimport { join } from 'pathe';\nimport { errorInvalidSpaceId } from './errors';\n\nexport { APP_SPACE_ID };\n\n/**\n * Branded string carrying a compile-time guarantee that the value has\n * been validated by {@link assertValidSpaceId}. Downstream filesystem\n * helpers (e.g. {@link spaceMigrationDirectory}) accept this type to\n * make \"validated\" tracking visible at the type level rather than\n * relying purely on a runtime check.\n */\nexport type ValidSpaceId = string & { readonly __brand: 'ValidSpaceId' };\n\n/**\n * Pattern a contract-space identifier must match. The constraint is\n * filesystem-friendly: lowercase letters / digits / hyphen / underscore,\n * starts with a letter, max 64 characters.\n */\nconst SPACE_ID_PATTERN = /^[a-z][a-z0-9_-]{0,63}$/;\n\nexport function isValidSpaceId(spaceId: string): spaceId is ValidSpaceId {\n return SPACE_ID_PATTERN.test(spaceId);\n}\n\nexport function assertValidSpaceId(spaceId: string): asserts spaceId is ValidSpaceId {\n if (!isValidSpaceId(spaceId)) {\n throw errorInvalidSpaceId(spaceId);\n }\n}\n\n/**\n * Resolve the migrations subdirectory for a given contract space.\n *\n * Every contract space — including the app space (default `'app'`) —\n * lands under `<projectMigrationsDir>/<spaceId>/`. The space id is\n * validated against {@link SPACE_ID_PATTERN} because it becomes a\n * filesystem directory name verbatim.\n *\n * `projectMigrationsDir` is the project's top-level `migrations/`\n * directory; the helper does not assume anything about its absolute /\n * relative shape and is symmetric with `pathe.join`.\n */\nexport function spaceMigrationDirectory(projectMigrationsDir: string, spaceId: string): string {\n assertValidSpaceId(spaceId);\n return join(projectMigrationsDir, spaceId);\n}\n","import { readFile } from 'node:fs/promises';\nimport type { ContractSpaceHeadRef } from '@prisma-next/framework-components/control';\nimport { join } from 'pathe';\nimport { errorInvalidJson, errorInvalidRefFile } from './errors';\nimport { assertValidSpaceId } from './space-layout';\n\nexport type { ContractSpaceHeadRef };\n\nfunction hasErrnoCode(error: unknown, code: string): boolean {\n return error instanceof Error && (error as { code?: string }).code === code;\n}\n\n/**\n * Read the head ref (`hash` + `invariants`) for a contract space from\n * `<projectMigrationsDir>/<spaceId>/refs/head.json`.\n *\n * Returns `null` when the file does not exist (first emit). Surfaces\n * `MIGRATION.INVALID_JSON` / `MIGRATION.INVALID_REF_FILE` on a corrupt\n * `refs/head.json` so callers can distinguish \"no head ref on disk\"\n * (returns `null`) from \"head ref present but unreadable\" (throws).\n *\n * Validates the space id against `[a-z][a-z0-9_-]{0,63}` for the same\n * filesystem-safety reasons as the rest of the per-space helpers. The\n * helper is uniform across the app and extension spaces.\n */\nexport async function readContractSpaceHeadRef(\n projectMigrationsDir: string,\n spaceId: string,\n): Promise<ContractSpaceHeadRef | null> {\n assertValidSpaceId(spaceId);\n\n const filePath = join(projectMigrationsDir, spaceId, 'refs', 'head.json');\n\n let raw: string;\n try {\n raw = await readFile(filePath, 'utf-8');\n } catch (error) {\n if (hasErrnoCode(error, 'ENOENT')) {\n return null;\n }\n throw error;\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (e) {\n throw errorInvalidJson(filePath, e instanceof Error ? e.message : String(e));\n }\n\n if (typeof parsed !== 'object' || parsed === null) {\n throw errorInvalidRefFile(filePath, 'expected an object');\n }\n const obj = parsed as { hash?: unknown; invariants?: unknown };\n if (typeof obj.hash !== 'string') {\n throw errorInvalidRefFile(filePath, 'expected an object with a string `hash` field');\n }\n if (!Array.isArray(obj.invariants) || obj.invariants.some((value) => typeof value !== 'string')) {\n throw errorInvalidRefFile(filePath, 'expected an object with an `invariants` array of strings');\n }\n\n return { hash: obj.hash, invariants: obj.invariants as readonly string[] };\n}\n","import { readdir, stat } from 'node:fs/promises';\nimport { join } from 'pathe';\nimport { MANIFEST_FILE } from './io';\nimport { APP_SPACE_ID } from './space-layout';\n\nfunction hasErrnoCode(error: unknown, code: string): boolean {\n return error instanceof Error && (error as { code?: string }).code === code;\n}\n\n/**\n * List the per-space subdirectories under\n * `<projectRoot>/migrations/`. Returns space-id directory names (sorted\n * alphabetically) — i.e. any non-dot-prefixed subdirectory whose root\n * does **not** contain a `migration.json` manifest. The manifest is the\n * structural marker of a user-authored migration directory (see\n * `readMigrationsDir` in `./io`); directory names themselves belong to\n * the user and are not part of the contract.\n *\n * Returns `[]` if the migrations directory does not exist (greenfield\n * project).\n *\n * Reads only the user's repo. **No descriptor import.** The caller\n * (verifier) feeds the result into {@link verifyContractSpaces} alongside\n * the loaded-space set and the marker rows.\n */\nexport async function listContractSpaceDirectories(\n projectMigrationsDir: string,\n): Promise<readonly string[]> {\n let entries: { readonly name: string; readonly isDirectory: boolean }[];\n try {\n const dirents = await readdir(projectMigrationsDir, { withFileTypes: true });\n entries = dirents.map((d) => ({ name: d.name, isDirectory: d.isDirectory() }));\n } catch (error) {\n if (hasErrnoCode(error, 'ENOENT')) {\n return [];\n }\n throw error;\n }\n\n const namedCandidates = entries\n .filter((e) => e.isDirectory)\n .map((e) => e.name)\n .filter((name) => !name.startsWith('.'))\n .sort();\n\n const manifestChecks = await Promise.all(\n namedCandidates.map(async (name) => {\n try {\n await stat(join(projectMigrationsDir, name, MANIFEST_FILE));\n return { name, isMigrationDir: true };\n } catch (error) {\n if (hasErrnoCode(error, 'ENOENT')) {\n return { name, isMigrationDir: false };\n }\n throw error;\n }\n }),\n );\n\n return manifestChecks.filter((c) => !c.isMigrationDir).map((c) => c.name);\n}\n\n/**\n * On-disk head value (`(hash, invariants)`) for one contract space.\n * The verifier compares this against the marker row for the same space\n * to detect drift between the user-emitted artefacts and the live DB\n * marker.\n */\nexport interface ContractSpaceHeadRecord {\n readonly hash: string;\n readonly invariants: readonly string[];\n}\n\n/**\n * Marker row read from `prisma_contract.marker` (one per `space`).\n * Caller resolves these via the family runtime's marker reader before\n * invoking {@link verifyContractSpaces}.\n */\nexport interface SpaceMarkerRecord {\n readonly hash: string;\n readonly invariants: readonly string[];\n}\n\nexport interface VerifyContractSpacesInputs {\n /**\n * Set of contract spaces the project declares: `'app'` plus each\n * extension space in `extensionPacks`. The caller's discovery path\n * never reads the extension descriptor module — it walks the\n * `extensionPacks` configuration in `prisma-next.config.ts` for the\n * space ids.\n */\n readonly loadedSpaces: ReadonlySet<string>;\n\n /**\n * Per-space subdirectories observed under\n * `<projectRoot>/migrations/`. Resolved via\n * {@link listContractSpaceDirectories}.\n */\n readonly spaceDirsOnDisk: readonly string[];\n\n /**\n * Head ref per space, keyed by space id. Caller reads\n * `<projectRoot>/migrations/<space-id>/contract.json` and\n * `<projectRoot>/migrations/<space-id>/refs/head.json` to construct\n * this map. Spaces with no contract-space dir on disk simply omit a\n * map entry.\n */\n readonly headRefsBySpace: ReadonlyMap<string, ContractSpaceHeadRecord>;\n\n /**\n * Marker rows keyed by `space`. Caller reads them from the\n * `prisma_contract.marker` table.\n */\n readonly markerRowsBySpace: ReadonlyMap<string, SpaceMarkerRecord>;\n}\n\nexport type SpaceVerifierViolation =\n | {\n readonly kind: 'declaredButUnmigrated';\n readonly spaceId: string;\n readonly remediation: string;\n }\n | {\n readonly kind: 'orphanMarker';\n readonly spaceId: string;\n readonly remediation: string;\n }\n | {\n readonly kind: 'orphanSpaceDir';\n readonly spaceId: string;\n readonly remediation: string;\n }\n | {\n readonly kind: 'hashMismatch';\n readonly spaceId: string;\n readonly priorHeadHash: string;\n readonly markerHash: string;\n readonly remediation: string;\n }\n | {\n readonly kind: 'invariantsMismatch';\n readonly spaceId: string;\n readonly onDiskInvariants: readonly string[];\n readonly markerInvariants: readonly string[];\n readonly remediation: string;\n };\n\nexport type VerifyContractSpacesResult =\n | { readonly ok: true }\n | { readonly ok: false; readonly violations: readonly SpaceVerifierViolation[] };\n\n/**\n * Pure structural verifier for the per-space mechanism. Aggregates the\n * three orphan / missing checks plus per-space hash and invariant\n * comparison.\n *\n * Algorithm:\n *\n * - For every extension space declared in `loadedSpaces` (`'app'`\n * excluded — the per-space verifier is scoped to extension members;\n * the app is verified through the aggregate path):\n * - If no contract-space dir on disk → `declaredButUnmigrated`.\n * - Else if `markerRowsBySpace` lacks an entry → no violation here;\n * the live-DB compare done outside this helper is where the\n * absence shows up.\n * - Else compare marker hash / invariants vs. on-disk head hash /\n * invariants → `hashMismatch` / `invariantsMismatch` on drift.\n * - For every contract-space dir on disk that is not in `loadedSpaces` →\n * `orphanSpaceDir`.\n * - For every marker row whose `space` is not in `loadedSpaces` →\n * `orphanMarker`. The app-space marker is always loaded (`'app'` is\n * in `loadedSpaces` by definition).\n *\n * Output is deterministic: violations are sorted first by `kind`\n * (`declaredButUnmigrated` → `orphanMarker` → `orphanSpaceDir` →\n * `hashMismatch` → `invariantsMismatch`) then by `spaceId`. Two callers\n * passing equivalent inputs see byte-identical violation lists.\n *\n * Synchronous, pure, no I/O. **Does not import the extension descriptor**\n * (the inputs are pre-resolved by the caller); the verifier reads only\n * the user repo, not `node_modules`.\n */\nexport function verifyContractSpaces(\n inputs: VerifyContractSpacesInputs,\n): VerifyContractSpacesResult {\n const violations: SpaceVerifierViolation[] = [];\n\n for (const spaceId of [...inputs.loadedSpaces].sort()) {\n if (spaceId === APP_SPACE_ID) continue;\n\n if (!inputs.spaceDirsOnDisk.includes(spaceId)) {\n violations.push({\n kind: 'declaredButUnmigrated',\n spaceId,\n remediation: `Extension '${spaceId}' is declared in extensionPacks but has not been emitted; run \\`prisma-next migrate\\`.`,\n });\n continue;\n }\n\n const head = inputs.headRefsBySpace.get(spaceId);\n const marker = inputs.markerRowsBySpace.get(spaceId);\n if (!head || !marker) {\n continue;\n }\n\n if (head.hash !== marker.hash) {\n violations.push({\n kind: 'hashMismatch',\n spaceId,\n priorHeadHash: head.hash,\n markerHash: marker.hash,\n remediation: `Marker row for space '${spaceId}' is keyed at ${marker.hash}, but the on-disk ${join('migrations', spaceId, 'contract.json')} resolves to ${head.hash}. Run \\`prisma-next db update\\` to advance the database, or \\`prisma-next migrate\\` if the descriptor was bumped without re-emitting.`,\n });\n continue;\n }\n\n const onDiskInvariants = [...head.invariants].sort();\n const markerInvariants = new Set(marker.invariants);\n const missing = onDiskInvariants.filter((id) => !markerInvariants.has(id));\n if (missing.length > 0) {\n violations.push({\n kind: 'invariantsMismatch',\n spaceId,\n onDiskInvariants,\n markerInvariants: [...marker.invariants].sort(),\n remediation: `Marker row for space '${spaceId}' is missing invariants [${missing.map((s) => JSON.stringify(s)).join(', ')}]. Run \\`prisma-next db update\\` to apply the corresponding data-transform migrations.`,\n });\n }\n }\n\n for (const dir of [...inputs.spaceDirsOnDisk].sort()) {\n if (!inputs.loadedSpaces.has(dir)) {\n violations.push({\n kind: 'orphanSpaceDir',\n spaceId: dir,\n remediation: `Orphan contract-space directory \\`${join('migrations', dir)}/\\` for an extension not in extensionPacks; remove the directory or re-add the extension.`,\n });\n }\n }\n\n for (const space of [...inputs.markerRowsBySpace.keys()].sort()) {\n if (!inputs.loadedSpaces.has(space)) {\n violations.push({\n kind: 'orphanMarker',\n spaceId: space,\n remediation: `Orphan marker row for space '${space}' (no longer in extensionPacks); remediation: manually delete the row from \\`prisma_contract.marker\\`.`,\n });\n }\n }\n\n if (violations.length === 0) {\n return { ok: true };\n }\n\n const kindOrder: Record<SpaceVerifierViolation['kind'], number> = {\n declaredButUnmigrated: 0,\n orphanMarker: 1,\n orphanSpaceDir: 2,\n hashMismatch: 3,\n invariantsMismatch: 4,\n };\n\n violations.sort((a, b) => {\n const k = kindOrder[a.kind] - kindOrder[b.kind];\n if (k !== 0) return k;\n if (a.spaceId < b.spaceId) return -1;\n if (a.spaceId > b.spaceId) return 1;\n return 0;\n });\n\n return { ok: false, violations };\n}\n","import { readFile } from 'node:fs/promises';\nimport { join } from 'pathe';\nimport { errorInvalidJson, errorMissingFile } from './errors';\nimport { assertValidSpaceId } from './space-layout';\n\nfunction hasErrnoCode(error: unknown, code: string): boolean {\n return error instanceof Error && (error as { code?: string }).code === code;\n}\n\n/**\n * Read the on-disk contract value for a contract space\n * (`<projectMigrationsDir>/<spaceId>/contract.json`). Returns the parsed\n * JSON value as `unknown` — callers that need a typed contract validate\n * via their family's `deserializeContract` to surface schema issues.\n *\n * Companion to {@link import('./read-contract-space-head-ref').readContractSpaceHeadRef}\n * — same ENOENT-throws / corrupt-file-error semantics. Returns the\n * canonical-JSON value the framework wrote during emit, so re-running\n * this helper across machines / runs yields a byte-identical value.\n */\nexport async function readContractSpaceContract(\n projectMigrationsDir: string,\n spaceId: string,\n): Promise<unknown> {\n assertValidSpaceId(spaceId);\n\n const filePath = join(projectMigrationsDir, spaceId, 'contract.json');\n\n let raw: string;\n try {\n raw = await readFile(filePath, 'utf-8');\n } catch (error) {\n if (hasErrnoCode(error, 'ENOENT')) {\n throw errorMissingFile('contract.json', join(projectMigrationsDir, spaceId));\n }\n throw error;\n }\n\n try {\n return JSON.parse(raw);\n } catch (e) {\n throw errorInvalidJson(filePath, e instanceof Error ? e.message : String(e));\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"refs-BDHo5l_g.mjs","names":[],"sources":["../src/refs.ts"],"sourcesContent":["import { mkdir, readdir, readFile, rename, rmdir, unlink, writeFile } from 'node:fs/promises';\nimport { type } from 'arktype';\nimport { dirname, join, relative } from 'pathe';\nimport {\n errorInvalidRefFile,\n errorInvalidRefName,\n errorInvalidRefValue,\n MigrationToolsError,\n} from './errors';\n\nexport interface RefEntry {\n readonly hash: string;\n readonly invariants: readonly string[];\n}\n\nexport type Refs = Readonly<Record<string, RefEntry>>;\n\nconst REF_NAME_PATTERN = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\/[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/;\nconst REF_VALUE_PATTERN = /^sha256:(empty|[0-9a-f]{64})$/;\n\nexport function validateRefName(name: string): boolean {\n if (name.length === 0) return false;\n if (name.includes('..')) return false;\n if (name.includes('//')) return false;\n if (name.startsWith('.')) return false;\n return REF_NAME_PATTERN.test(name);\n}\n\nexport function validateRefValue(value: string): boolean {\n return REF_VALUE_PATTERN.test(value);\n}\n\nconst RefEntrySchema = type({\n hash: 'string',\n invariants: 'string[]',\n}).narrow((entry, ctx) => {\n if (!validateRefValue(entry.hash))\n return ctx.mustBe(`a valid contract hash (got \"${entry.hash}\")`);\n return true;\n});\n\nfunction refFilePath(refsDir: string, name: string): string {\n return join(refsDir, `${name}.json`);\n}\n\nfunction refNameFromPath(refsDir: string, filePath: string): string {\n const rel = relative(refsDir, filePath);\n return rel.replace(/\\.json$/, '');\n}\n\nexport async function readRef(refsDir: string, name: string): Promise<RefEntry> {\n if (!validateRefName(name)) {\n throw errorInvalidRefName(name);\n }\n\n const filePath = refFilePath(refsDir, name);\n let raw: string;\n try {\n raw = await readFile(filePath, 'utf-8');\n } catch (error) {\n if (error instanceof Error && (error as { code?: string }).code === 'ENOENT') {\n throw new MigrationToolsError('MIGRATION.UNKNOWN_REF', `Unknown ref \"${name}\"`, {\n why: `No ref file found at \"${filePath}\".`,\n fix: `Create the ref with: prisma-next ref set ${name} <hash>`,\n details: { refName: name, filePath },\n });\n }\n throw error;\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw errorInvalidRefFile(filePath, 'Failed to parse as JSON');\n }\n\n const result = RefEntrySchema(parsed);\n if (result instanceof type.errors) {\n throw errorInvalidRefFile(filePath, result.summary);\n }\n\n return result;\n}\n\nexport async function readRefs(refsDir: string): Promise<Refs> {\n let entries: string[];\n try {\n entries = await readdir(refsDir, { recursive: true, encoding: 'utf-8' });\n } catch (error) {\n if (error instanceof Error && (error as { code?: string }).code === 'ENOENT') {\n return {};\n }\n throw error;\n }\n\n const jsonFiles = entries.filter((entry) => entry.endsWith('.json'));\n const refs: Record<string, RefEntry> = {};\n\n for (const jsonFile of jsonFiles) {\n const filePath = join(refsDir, jsonFile);\n const name = refNameFromPath(refsDir, filePath);\n\n let raw: string;\n try {\n raw = await readFile(filePath, 'utf-8');\n } catch (error) {\n // Tolerate the TOCTOU race between `readdir` and `readFile` (ENOENT) and\n // benign EISDIR if a directory happens to end in `.json`. Anything else\n // (EACCES, EIO, EMFILE, …) is a real failure and propagates so the CLI\n // surfaces it rather than silently dropping the ref.\n const code = error instanceof Error ? (error as { code?: string }).code : undefined;\n if (code === 'ENOENT' || code === 'EISDIR') {\n continue;\n }\n throw error;\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw errorInvalidRefFile(filePath, 'Failed to parse as JSON');\n }\n\n const result = RefEntrySchema(parsed);\n if (result instanceof type.errors) {\n throw errorInvalidRefFile(filePath, result.summary);\n }\n\n refs[name] = result;\n }\n\n return refs;\n}\n\nexport async function writeRef(refsDir: string, name: string, entry: RefEntry): Promise<void> {\n if (!validateRefName(name)) {\n throw errorInvalidRefName(name);\n }\n if (!validateRefValue(entry.hash)) {\n throw errorInvalidRefValue(entry.hash);\n }\n\n const filePath = refFilePath(refsDir, name);\n const dir = dirname(filePath);\n await mkdir(dir, { recursive: true });\n\n const tmpPath = join(dir, `.${name.split('/').pop()}.json.${Date.now()}.tmp`);\n await writeFile(\n tmpPath,\n `${JSON.stringify({ hash: entry.hash, invariants: [...entry.invariants] }, null, 2)}\\n`,\n );\n await rename(tmpPath, filePath);\n}\n\nexport async function deleteRef(refsDir: string, name: string): Promise<void> {\n if (!validateRefName(name)) {\n throw errorInvalidRefName(name);\n }\n\n const filePath = refFilePath(refsDir, name);\n try {\n await unlink(filePath);\n } catch (error) {\n if (error instanceof Error && (error as { code?: string }).code === 'ENOENT') {\n throw new MigrationToolsError('MIGRATION.UNKNOWN_REF', `Unknown ref \"${name}\"`, {\n why: `No ref file found at \"${filePath}\".`,\n fix: 'Run `prisma-next ref list` to see available refs.',\n details: { refName: name, filePath },\n });\n }\n throw error;\n }\n\n // Clean empty parent directories up to refsDir. Stop walking on the expected\n // \"directory has siblings\" signal (ENOTEMPTY on Linux, EEXIST on some BSDs)\n // and on ENOENT (concurrent removal). Anything else (EACCES, EIO, …) is a\n // real failure and propagates.\n let dir = dirname(filePath);\n while (dir !== refsDir && dir.startsWith(refsDir)) {\n try {\n await rmdir(dir);\n dir = dirname(dir);\n } catch (error) {\n const code = error instanceof Error ? (error as { code?: string }).code : undefined;\n if (code === 'ENOTEMPTY' || code === 'EEXIST' || code === 'ENOENT') {\n break;\n }\n throw error;\n }\n }\n}\n\nexport function resolveRef(refs: Refs, name: string): RefEntry {\n if (!validateRefName(name)) {\n throw errorInvalidRefName(name);\n }\n\n // Object.hasOwn gate: plain-object `refs` would otherwise let\n // `refs['constructor']` return Object.prototype.constructor and bypass the\n // UNKNOWN_REF throw. validateRefName accepts `\"constructor\"` as a name shape.\n if (!Object.hasOwn(refs, name)) {\n throw new MigrationToolsError('MIGRATION.UNKNOWN_REF', `Unknown ref \"${name}\"`, {\n why: `No ref named \"${name}\" exists.`,\n fix: `Available refs: ${Object.keys(refs).join(', ') || '(none)'}. Create a ref with: prisma-next ref set ${name} <hash>`,\n details: { refName: name, availableRefs: Object.keys(refs) },\n });\n }\n\n // biome-ignore lint/style/noNonNullAssertion: Object.hasOwn gate above guarantees this is defined\n return refs[name]!;\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"refs-CDaNerhT.d.mts","names":[],"sources":["../src/refs.ts"],"mappings":";UAUiB,QAAA;EAAA,SACN,IAAA;EAAA,SACA,UAAA;AAAA;AAAA,KAGC,IAAA,GAAO,QAAA,CAAS,MAAA,SAAe,QAAA;AAAA,iBAK3B,eAAA,CAAgB,IAAA;AAAA,iBAQhB,gBAAA,CAAiB,KAAA;AAAA,iBAsBX,OAAA,CAAQ,OAAA,UAAiB,IAAA,WAAe,OAAA,CAAQ,QAAA;AAAA,iBAmChD,QAAA,CAAS,OAAA,WAAkB,OAAA,CAAQ,IAAA;AAAA,iBAmDnC,QAAA,CAAS,OAAA,UAAiB,IAAA,UAAc,KAAA,EAAO,QAAA,GAAW,OAAA;AAAA,iBAoB1D,SAAA,CAAU,OAAA,UAAiB,IAAA,WAAe,OAAA;AAAA,iBAsChD,UAAA,CAAW,IAAA,EAAM,IAAA,EAAM,IAAA,WAAe,QAAA"}
|
|
File without changes
|