@prisma-next/sql-contract 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +154 -0
- package/dist/exports/factories.d.ts +33 -0
- package/dist/exports/factories.js +82 -0
- package/dist/exports/factories.js.map +1 -0
- package/dist/exports/types.d.ts +69 -0
- package/dist/exports/types.js +1 -0
- package/dist/exports/types.js.map +1 -0
- package/dist/exports/validators.d.ts +38 -0
- package/dist/exports/validators.js +95 -0
- package/dist/exports/validators.js.map +1 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# @prisma-next/sql-contract
|
|
2
|
+
|
|
3
|
+
SQL contract types, validators, and IR factories for Prisma Next.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This package provides TypeScript type definitions, Arktype validators, and factory functions for constructing SQL contract structures. It is located in the **shared plane**, making it available to both migration-plane (authoring, emitter) and runtime-plane (lanes, runtime) packages.
|
|
8
|
+
|
|
9
|
+
## Responsibilities
|
|
10
|
+
|
|
11
|
+
- **SQL Contract Types**: Defines SQL-specific contract types (`SqlContract`, `SqlStorage`, `StorageTable`, `ModelDefinition`, `SqlMappings`) that extend framework-level contract types
|
|
12
|
+
- **Contract Validation**: Provides Arktype-based validators for structural validation of SQL contracts, storage, and models
|
|
13
|
+
- **IR Factories**: Provides pure factory functions for constructing contract IR structures in tests and authoring
|
|
14
|
+
- **Shared Plane Access**: Enables both migration-plane and runtime-plane packages to import SQL contract types without violating plane boundaries
|
|
15
|
+
|
|
16
|
+
## Package Contents
|
|
17
|
+
|
|
18
|
+
- **TypeScript Types**: Type definitions for `SqlContract`, `SqlStorage`, `StorageTable`, `ModelDefinition`, and related types
|
|
19
|
+
- **Validators**: Arktype-based validators for structural validation of contracts, storage, and models
|
|
20
|
+
- **Factories**: Pure factory functions for constructing contract IR structures in tests and authoring
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
### TypeScript Types
|
|
25
|
+
|
|
26
|
+
Import SQL contract types:
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import type {
|
|
30
|
+
SqlContract,
|
|
31
|
+
SqlStorage,
|
|
32
|
+
StorageTable,
|
|
33
|
+
ModelDefinition,
|
|
34
|
+
} from '@prisma-next/sql-contract/exports/types';
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Validators
|
|
38
|
+
|
|
39
|
+
Validate contract structures using Arktype validators:
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { validateSqlContract, validateStorage, validateModel } from '@prisma-next/sql-contract/exports/validators';
|
|
43
|
+
|
|
44
|
+
// Validate a complete contract
|
|
45
|
+
const contract = validateSqlContract<Contract>(contractJson);
|
|
46
|
+
|
|
47
|
+
// Validate storage structure
|
|
48
|
+
const storage = validateStorage(storageJson);
|
|
49
|
+
|
|
50
|
+
// Validate model structure
|
|
51
|
+
const model = validateModel(modelJson);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Factories
|
|
55
|
+
|
|
56
|
+
Use factory functions to construct contract IR structures in tests:
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import { col, table, storage, model, contract, pk, unique, index, fk } from '@prisma-next/sql-contract/exports/factories';
|
|
60
|
+
|
|
61
|
+
// Create a column
|
|
62
|
+
const idColumn = col('pg/int4@1', false);
|
|
63
|
+
|
|
64
|
+
// Create a table
|
|
65
|
+
const userTable = table(
|
|
66
|
+
{
|
|
67
|
+
id: col('pg/int4@1'),
|
|
68
|
+
email: col('pg/text@1'),
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
pk: pk('id'),
|
|
72
|
+
uniques: [unique('email')],
|
|
73
|
+
indexes: [index('email')],
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// Create storage
|
|
78
|
+
const s = storage({ user: userTable });
|
|
79
|
+
|
|
80
|
+
// Create a model
|
|
81
|
+
const userModel = model('user', {
|
|
82
|
+
id: { column: 'id' },
|
|
83
|
+
email: { column: 'email' },
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Create a complete contract
|
|
87
|
+
const c = contract({
|
|
88
|
+
target: 'postgres',
|
|
89
|
+
coreHash: 'sha256:abc123',
|
|
90
|
+
storage: s,
|
|
91
|
+
models: { User: userModel },
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Exports
|
|
96
|
+
|
|
97
|
+
- `./exports/types`: TypeScript type definitions
|
|
98
|
+
- `./exports/validators`: Arktype validators for structural validation
|
|
99
|
+
- `./exports/factories`: Factory functions for constructing contract IR
|
|
100
|
+
|
|
101
|
+
## Architecture
|
|
102
|
+
|
|
103
|
+
```mermaid
|
|
104
|
+
flowchart TD
|
|
105
|
+
subgraph "SQL Contract Package (Shared Plane)"
|
|
106
|
+
TYPES[Type Definitions]
|
|
107
|
+
VALIDATORS[Validators]
|
|
108
|
+
FACTORIES[IR Factories]
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
subgraph "Migration Plane"
|
|
112
|
+
AUTHORING[Authoring]
|
|
113
|
+
EMITTER[Emitter]
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
subgraph "Runtime Plane"
|
|
117
|
+
LANES[Lanes]
|
|
118
|
+
RUNTIME[Runtime]
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
TYPES --> AUTHORING
|
|
122
|
+
TYPES --> EMITTER
|
|
123
|
+
TYPES --> LANES
|
|
124
|
+
TYPES --> RUNTIME
|
|
125
|
+
VALIDATORS --> AUTHORING
|
|
126
|
+
VALIDATORS --> EMITTER
|
|
127
|
+
VALIDATORS --> RUNTIME
|
|
128
|
+
FACTORIES --> AUTHORING
|
|
129
|
+
FACTORIES --> EMITTER
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Dependencies
|
|
133
|
+
|
|
134
|
+
- **`@prisma-next/contract`**: Framework-level contract types (`ContractBase`)
|
|
135
|
+
- **`arktype`**: Runtime validation library
|
|
136
|
+
|
|
137
|
+
**Dependents:**
|
|
138
|
+
- **`@prisma-next/sql-contract-ts`**: Uses SQL contract types and validators for authoring
|
|
139
|
+
- **`@prisma-next/sql-contract-emitter`**: Uses SQL contract types for emission
|
|
140
|
+
- **`@prisma-next/sql-query`**: Uses SQL contract types for query building
|
|
141
|
+
- **`@prisma-next/sql-runtime`**: Uses SQL contract types for runtime execution
|
|
142
|
+
- **`@prisma-next/sql-lane`**: Uses SQL contract types for lane operations
|
|
143
|
+
|
|
144
|
+
## Related Packages
|
|
145
|
+
|
|
146
|
+
- `@prisma-next/contract`: Framework-level contract types (`ContractBase`)
|
|
147
|
+
- `@prisma-next/sql-contract-ts`: SQL contract authoring surface (uses this package)
|
|
148
|
+
- `@prisma-next/emitter`: Contract emission engine (uses validators)
|
|
149
|
+
|
|
150
|
+
## Related Subsystems
|
|
151
|
+
|
|
152
|
+
- **[Data Contract](../../../docs/architecture%20docs/subsystems/1.%20Data%20Contract.md)**: Detailed subsystem specification
|
|
153
|
+
- **[Contract Emitter & Types](../../../docs/architecture%20docs/subsystems/2.%20Contract%20Emitter%20&%20Types.md)**: Contract emission
|
|
154
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { StorageColumn, SqlStorage, ModelDefinition, SqlMappings, SqlContract, ForeignKey, Index, ModelField, PrimaryKey, StorageTable, UniqueConstraint } from './types.js';
|
|
2
|
+
import '@prisma-next/contract/types';
|
|
3
|
+
|
|
4
|
+
declare function col(typeId: string, nullable?: boolean): StorageColumn;
|
|
5
|
+
declare function pk(...columns: readonly string[]): PrimaryKey;
|
|
6
|
+
declare function unique(...columns: readonly string[]): UniqueConstraint;
|
|
7
|
+
declare function index(...columns: readonly string[]): Index;
|
|
8
|
+
declare function fk(columns: readonly string[], refTable: string, refColumns: readonly string[], name?: string): ForeignKey;
|
|
9
|
+
declare function table(columns: Record<string, StorageColumn>, opts?: {
|
|
10
|
+
pk?: PrimaryKey;
|
|
11
|
+
uniques?: readonly UniqueConstraint[];
|
|
12
|
+
indexes?: readonly Index[];
|
|
13
|
+
fks?: readonly ForeignKey[];
|
|
14
|
+
}): StorageTable;
|
|
15
|
+
declare function model(table: string, fields: Record<string, ModelField>, relations?: Record<string, unknown>): ModelDefinition;
|
|
16
|
+
declare function storage(tables: Record<string, StorageTable>): SqlStorage;
|
|
17
|
+
declare function contract(opts: {
|
|
18
|
+
target: string;
|
|
19
|
+
coreHash: string;
|
|
20
|
+
storage: SqlStorage;
|
|
21
|
+
models?: Record<string, ModelDefinition>;
|
|
22
|
+
relations?: Record<string, unknown>;
|
|
23
|
+
mappings?: Partial<SqlMappings>;
|
|
24
|
+
schemaVersion?: '1';
|
|
25
|
+
targetFamily?: 'sql';
|
|
26
|
+
profileHash?: string;
|
|
27
|
+
capabilities?: Record<string, Record<string, boolean>>;
|
|
28
|
+
extensions?: Record<string, unknown>;
|
|
29
|
+
meta?: Record<string, unknown>;
|
|
30
|
+
sources?: Record<string, unknown>;
|
|
31
|
+
}): SqlContract;
|
|
32
|
+
|
|
33
|
+
export { col, contract, fk, index, model, pk, storage, table, unique };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// src/factories.ts
|
|
2
|
+
function col(typeId, nullable = false) {
|
|
3
|
+
return {
|
|
4
|
+
type: typeId,
|
|
5
|
+
nullable
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
function pk(...columns) {
|
|
9
|
+
return {
|
|
10
|
+
columns
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function unique(...columns) {
|
|
14
|
+
return {
|
|
15
|
+
columns
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function index(...columns) {
|
|
19
|
+
return {
|
|
20
|
+
columns
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function fk(columns, refTable, refColumns, name) {
|
|
24
|
+
const references = {
|
|
25
|
+
table: refTable,
|
|
26
|
+
columns: refColumns
|
|
27
|
+
};
|
|
28
|
+
return {
|
|
29
|
+
columns,
|
|
30
|
+
references,
|
|
31
|
+
...name !== void 0 && { name }
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function table(columns, opts) {
|
|
35
|
+
return {
|
|
36
|
+
columns,
|
|
37
|
+
...opts?.pk !== void 0 && { primaryKey: opts.pk },
|
|
38
|
+
uniques: opts?.uniques ?? [],
|
|
39
|
+
indexes: opts?.indexes ?? [],
|
|
40
|
+
foreignKeys: opts?.fks ?? []
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function model(table2, fields, relations = {}) {
|
|
44
|
+
const storage2 = { table: table2 };
|
|
45
|
+
return {
|
|
46
|
+
storage: storage2,
|
|
47
|
+
fields,
|
|
48
|
+
relations
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function storage(tables) {
|
|
52
|
+
return { tables };
|
|
53
|
+
}
|
|
54
|
+
function contract(opts) {
|
|
55
|
+
return {
|
|
56
|
+
schemaVersion: opts.schemaVersion ?? "1",
|
|
57
|
+
target: opts.target,
|
|
58
|
+
targetFamily: opts.targetFamily ?? "sql",
|
|
59
|
+
coreHash: opts.coreHash,
|
|
60
|
+
storage: opts.storage,
|
|
61
|
+
models: opts.models ?? {},
|
|
62
|
+
relations: opts.relations ?? {},
|
|
63
|
+
mappings: opts.mappings ?? {},
|
|
64
|
+
...opts.profileHash !== void 0 && { profileHash: opts.profileHash },
|
|
65
|
+
...opts.capabilities !== void 0 && { capabilities: opts.capabilities },
|
|
66
|
+
...opts.extensions !== void 0 && { extensions: opts.extensions },
|
|
67
|
+
...opts.meta !== void 0 && { meta: opts.meta },
|
|
68
|
+
...opts.sources !== void 0 && { sources: opts.sources }
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export {
|
|
72
|
+
col,
|
|
73
|
+
contract,
|
|
74
|
+
fk,
|
|
75
|
+
index,
|
|
76
|
+
model,
|
|
77
|
+
pk,
|
|
78
|
+
storage,
|
|
79
|
+
table,
|
|
80
|
+
unique
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=factories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/factories.ts"],"sourcesContent":["import type {\n ForeignKey,\n ForeignKeyReferences,\n Index,\n ModelDefinition,\n ModelField,\n ModelStorage,\n PrimaryKey,\n SqlContract,\n SqlMappings,\n SqlStorage,\n StorageColumn,\n StorageTable,\n UniqueConstraint,\n} from './types';\n\nexport function col(typeId: string, nullable = false): StorageColumn {\n return {\n type: typeId,\n nullable,\n };\n}\n\nexport function pk(...columns: readonly string[]): PrimaryKey {\n return {\n columns,\n };\n}\n\nexport function unique(...columns: readonly string[]): UniqueConstraint {\n return {\n columns,\n };\n}\n\nexport function index(...columns: readonly string[]): Index {\n return {\n columns,\n };\n}\n\nexport function fk(\n columns: readonly string[],\n refTable: string,\n refColumns: readonly string[],\n name?: string,\n): ForeignKey {\n const references: ForeignKeyReferences = {\n table: refTable,\n columns: refColumns,\n };\n return {\n columns,\n references,\n ...(name !== undefined && { name }),\n };\n}\n\nexport function table(\n columns: Record<string, StorageColumn>,\n opts?: {\n pk?: PrimaryKey;\n uniques?: readonly UniqueConstraint[];\n indexes?: readonly Index[];\n fks?: readonly ForeignKey[];\n },\n): StorageTable {\n return {\n columns,\n ...(opts?.pk !== undefined && { primaryKey: opts.pk }),\n uniques: opts?.uniques ?? [],\n indexes: opts?.indexes ?? [],\n foreignKeys: opts?.fks ?? [],\n };\n}\n\nexport function model(\n table: string,\n fields: Record<string, ModelField>,\n relations: Record<string, unknown> = {},\n): ModelDefinition {\n const storage: ModelStorage = { table };\n return {\n storage,\n fields,\n relations,\n };\n}\n\nexport function storage(tables: Record<string, StorageTable>): SqlStorage {\n return { tables };\n}\n\nexport function contract(opts: {\n target: string;\n coreHash: string;\n storage: SqlStorage;\n models?: Record<string, ModelDefinition>;\n relations?: Record<string, unknown>;\n mappings?: Partial<SqlMappings>;\n schemaVersion?: '1';\n targetFamily?: 'sql';\n profileHash?: string;\n capabilities?: Record<string, Record<string, boolean>>;\n extensions?: Record<string, unknown>;\n meta?: Record<string, unknown>;\n sources?: Record<string, unknown>;\n}): SqlContract {\n return {\n schemaVersion: opts.schemaVersion ?? '1',\n target: opts.target,\n targetFamily: opts.targetFamily ?? 'sql',\n coreHash: opts.coreHash,\n storage: opts.storage,\n models: opts.models ?? {},\n relations: opts.relations ?? {},\n mappings: (opts.mappings ?? {}) as SqlMappings,\n ...(opts.profileHash !== undefined && { profileHash: opts.profileHash }),\n ...(opts.capabilities !== undefined && { capabilities: opts.capabilities }),\n ...(opts.extensions !== undefined && { extensions: opts.extensions }),\n ...(opts.meta !== undefined && { meta: opts.meta }),\n ...(opts.sources !== undefined && { sources: opts.sources as Record<string, unknown> }),\n } as SqlContract;\n}\n"],"mappings":";AAgBO,SAAS,IAAI,QAAgB,WAAW,OAAsB;AACnE,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,EACF;AACF;AAEO,SAAS,MAAM,SAAwC;AAC5D,SAAO;AAAA,IACL;AAAA,EACF;AACF;AAEO,SAAS,UAAU,SAA8C;AACtE,SAAO;AAAA,IACL;AAAA,EACF;AACF;AAEO,SAAS,SAAS,SAAmC;AAC1D,SAAO;AAAA,IACL;AAAA,EACF;AACF;AAEO,SAAS,GACd,SACA,UACA,YACA,MACY;AACZ,QAAM,aAAmC;AAAA,IACvC,OAAO;AAAA,IACP,SAAS;AAAA,EACX;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,GAAI,SAAS,UAAa,EAAE,KAAK;AAAA,EACnC;AACF;AAEO,SAAS,MACd,SACA,MAMc;AACd,SAAO;AAAA,IACL;AAAA,IACA,GAAI,MAAM,OAAO,UAAa,EAAE,YAAY,KAAK,GAAG;AAAA,IACpD,SAAS,MAAM,WAAW,CAAC;AAAA,IAC3B,SAAS,MAAM,WAAW,CAAC;AAAA,IAC3B,aAAa,MAAM,OAAO,CAAC;AAAA,EAC7B;AACF;AAEO,SAAS,MACdA,QACA,QACA,YAAqC,CAAC,GACrB;AACjB,QAAMC,WAAwB,EAAE,OAAAD,OAAM;AACtC,SAAO;AAAA,IACL,SAAAC;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,QAAQ,QAAkD;AACxE,SAAO,EAAE,OAAO;AAClB;AAEO,SAAS,SAAS,MAcT;AACd,SAAO;AAAA,IACL,eAAe,KAAK,iBAAiB;AAAA,IACrC,QAAQ,KAAK;AAAA,IACb,cAAc,KAAK,gBAAgB;AAAA,IACnC,UAAU,KAAK;AAAA,IACf,SAAS,KAAK;AAAA,IACd,QAAQ,KAAK,UAAU,CAAC;AAAA,IACxB,WAAW,KAAK,aAAa,CAAC;AAAA,IAC9B,UAAW,KAAK,YAAY,CAAC;AAAA,IAC7B,GAAI,KAAK,gBAAgB,UAAa,EAAE,aAAa,KAAK,YAAY;AAAA,IACtE,GAAI,KAAK,iBAAiB,UAAa,EAAE,cAAc,KAAK,aAAa;AAAA,IACzE,GAAI,KAAK,eAAe,UAAa,EAAE,YAAY,KAAK,WAAW;AAAA,IACnE,GAAI,KAAK,SAAS,UAAa,EAAE,MAAM,KAAK,KAAK;AAAA,IACjD,GAAI,KAAK,YAAY,UAAa,EAAE,SAAS,KAAK,QAAmC;AAAA,EACvF;AACF;","names":["table","storage"]}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { ContractBase } from '@prisma-next/contract/types';
|
|
2
|
+
|
|
3
|
+
type StorageColumn = {
|
|
4
|
+
readonly type: string;
|
|
5
|
+
readonly nullable: boolean;
|
|
6
|
+
};
|
|
7
|
+
type PrimaryKey = {
|
|
8
|
+
readonly columns: readonly string[];
|
|
9
|
+
readonly name?: string;
|
|
10
|
+
};
|
|
11
|
+
type UniqueConstraint = {
|
|
12
|
+
readonly columns: readonly string[];
|
|
13
|
+
readonly name?: string;
|
|
14
|
+
};
|
|
15
|
+
type Index = {
|
|
16
|
+
readonly columns: readonly string[];
|
|
17
|
+
readonly name?: string;
|
|
18
|
+
};
|
|
19
|
+
type ForeignKeyReferences = {
|
|
20
|
+
readonly table: string;
|
|
21
|
+
readonly columns: readonly string[];
|
|
22
|
+
};
|
|
23
|
+
type ForeignKey = {
|
|
24
|
+
readonly columns: readonly string[];
|
|
25
|
+
readonly references: ForeignKeyReferences;
|
|
26
|
+
readonly name?: string;
|
|
27
|
+
};
|
|
28
|
+
type StorageTable = {
|
|
29
|
+
readonly columns: Record<string, StorageColumn>;
|
|
30
|
+
readonly primaryKey?: PrimaryKey;
|
|
31
|
+
readonly uniques: ReadonlyArray<UniqueConstraint>;
|
|
32
|
+
readonly indexes: ReadonlyArray<Index>;
|
|
33
|
+
readonly foreignKeys: ReadonlyArray<ForeignKey>;
|
|
34
|
+
};
|
|
35
|
+
type SqlStorage = {
|
|
36
|
+
readonly tables: Record<string, StorageTable>;
|
|
37
|
+
};
|
|
38
|
+
type ModelField = {
|
|
39
|
+
readonly column: string;
|
|
40
|
+
};
|
|
41
|
+
type ModelStorage = {
|
|
42
|
+
readonly table: string;
|
|
43
|
+
};
|
|
44
|
+
type ModelDefinition = {
|
|
45
|
+
readonly storage: ModelStorage;
|
|
46
|
+
readonly fields: Record<string, ModelField>;
|
|
47
|
+
readonly relations: Record<string, unknown>;
|
|
48
|
+
};
|
|
49
|
+
type SqlMappings = {
|
|
50
|
+
readonly modelToTable?: Record<string, string>;
|
|
51
|
+
readonly tableToModel?: Record<string, string>;
|
|
52
|
+
readonly fieldToColumn?: Record<string, Record<string, string>>;
|
|
53
|
+
readonly columnToField?: Record<string, Record<string, string>>;
|
|
54
|
+
readonly codecTypes: Record<string, {
|
|
55
|
+
readonly output: unknown;
|
|
56
|
+
}>;
|
|
57
|
+
readonly operationTypes: Record<string, Record<string, unknown>>;
|
|
58
|
+
};
|
|
59
|
+
type SqlContract<S extends SqlStorage = SqlStorage, M extends Record<string, unknown> = Record<string, unknown>, R extends Record<string, unknown> = Record<string, unknown>, Map extends SqlMappings = SqlMappings> = ContractBase & {
|
|
60
|
+
readonly targetFamily: string;
|
|
61
|
+
readonly storage: S;
|
|
62
|
+
readonly models: M;
|
|
63
|
+
readonly relations: R;
|
|
64
|
+
readonly mappings: Map;
|
|
65
|
+
};
|
|
66
|
+
type ExtractCodecTypes<TContract extends SqlContract<SqlStorage>> = TContract['mappings']['codecTypes'];
|
|
67
|
+
type ExtractOperationTypes<TContract extends SqlContract<SqlStorage>> = TContract['mappings']['operationTypes'];
|
|
68
|
+
|
|
69
|
+
export type { ExtractCodecTypes, ExtractOperationTypes, ForeignKey, ForeignKeyReferences, Index, ModelDefinition, ModelField, ModelStorage, PrimaryKey, SqlContract, SqlMappings, SqlStorage, StorageColumn, StorageTable, UniqueConstraint };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { ModelDefinition, SqlContract, SqlStorage } from './types.js';
|
|
2
|
+
import '@prisma-next/contract/types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Validates the structural shape of SqlStorage using Arktype.
|
|
6
|
+
*
|
|
7
|
+
* @param value - The storage value to validate
|
|
8
|
+
* @returns The validated storage if structure is valid
|
|
9
|
+
* @throws Error if the storage structure is invalid
|
|
10
|
+
*/
|
|
11
|
+
declare function validateStorage(value: unknown): SqlStorage;
|
|
12
|
+
/**
|
|
13
|
+
* Validates the structural shape of ModelDefinition using Arktype.
|
|
14
|
+
*
|
|
15
|
+
* @param value - The model value to validate
|
|
16
|
+
* @returns The validated model if structure is valid
|
|
17
|
+
* @throws Error if the model structure is invalid
|
|
18
|
+
*/
|
|
19
|
+
declare function validateModel(value: unknown): ModelDefinition;
|
|
20
|
+
/**
|
|
21
|
+
* Validates the structural shape of a SqlContract using Arktype.
|
|
22
|
+
*
|
|
23
|
+
* **Responsibility: Validation Only**
|
|
24
|
+
* This function validates that the contract has the correct structure and types.
|
|
25
|
+
* It does NOT normalize the contract - normalization must happen in the contract builder.
|
|
26
|
+
*
|
|
27
|
+
* The contract passed to this function must already be normalized (all required fields present).
|
|
28
|
+
* If normalization is needed, it should be done by the contract builder before calling this function.
|
|
29
|
+
*
|
|
30
|
+
* This ensures all required fields are present and have the correct types.
|
|
31
|
+
*
|
|
32
|
+
* @param value - The contract value to validate (typically from a JSON import)
|
|
33
|
+
* @returns The validated contract if structure is valid
|
|
34
|
+
* @throws Error if the contract structure is invalid
|
|
35
|
+
*/
|
|
36
|
+
declare function validateSqlContract<T extends SqlContract<SqlStorage>>(value: unknown): T;
|
|
37
|
+
|
|
38
|
+
export { validateModel, validateSqlContract, validateStorage };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// src/validators.ts
|
|
2
|
+
import { type } from "arktype";
|
|
3
|
+
var StorageColumnSchema = type.declare().type({
|
|
4
|
+
type: "string",
|
|
5
|
+
nullable: "boolean"
|
|
6
|
+
});
|
|
7
|
+
var PrimaryKeySchema = type.declare().type({
|
|
8
|
+
columns: type.string.array().readonly(),
|
|
9
|
+
"name?": "string"
|
|
10
|
+
});
|
|
11
|
+
var UniqueConstraintSchema = type.declare().type({
|
|
12
|
+
columns: type.string.array().readonly(),
|
|
13
|
+
"name?": "string"
|
|
14
|
+
});
|
|
15
|
+
var IndexSchema = type.declare().type({
|
|
16
|
+
columns: type.string.array().readonly(),
|
|
17
|
+
"name?": "string"
|
|
18
|
+
});
|
|
19
|
+
var ForeignKeyReferencesSchema = type.declare().type({
|
|
20
|
+
table: "string",
|
|
21
|
+
columns: type.string.array().readonly()
|
|
22
|
+
});
|
|
23
|
+
var ForeignKeySchema = type.declare().type({
|
|
24
|
+
columns: type.string.array().readonly(),
|
|
25
|
+
references: ForeignKeyReferencesSchema,
|
|
26
|
+
"name?": "string"
|
|
27
|
+
});
|
|
28
|
+
var StorageTableSchema = type.declare().type({
|
|
29
|
+
columns: type({ "[string]": StorageColumnSchema }),
|
|
30
|
+
"primaryKey?": PrimaryKeySchema,
|
|
31
|
+
uniques: UniqueConstraintSchema.array().readonly(),
|
|
32
|
+
indexes: IndexSchema.array().readonly(),
|
|
33
|
+
foreignKeys: ForeignKeySchema.array().readonly()
|
|
34
|
+
});
|
|
35
|
+
var StorageSchema = type.declare().type({
|
|
36
|
+
tables: type({ "[string]": StorageTableSchema })
|
|
37
|
+
});
|
|
38
|
+
var ModelFieldSchema = type.declare().type({
|
|
39
|
+
column: "string"
|
|
40
|
+
});
|
|
41
|
+
var ModelStorageSchema = type.declare().type({
|
|
42
|
+
table: "string"
|
|
43
|
+
});
|
|
44
|
+
var ModelSchema = type.declare().type({
|
|
45
|
+
storage: ModelStorageSchema,
|
|
46
|
+
fields: type({ "[string]": ModelFieldSchema }),
|
|
47
|
+
relations: type({ "[string]": "unknown" })
|
|
48
|
+
});
|
|
49
|
+
var SqlContractSchema = type({
|
|
50
|
+
"schemaVersion?": "'1'",
|
|
51
|
+
target: "string",
|
|
52
|
+
targetFamily: "'sql'",
|
|
53
|
+
coreHash: "string",
|
|
54
|
+
"profileHash?": "string",
|
|
55
|
+
"capabilities?": "Record<string, Record<string, boolean>>",
|
|
56
|
+
"extensions?": "Record<string, unknown>",
|
|
57
|
+
"meta?": "Record<string, unknown>",
|
|
58
|
+
"sources?": "Record<string, unknown>",
|
|
59
|
+
models: type({ "[string]": ModelSchema }),
|
|
60
|
+
storage: StorageSchema
|
|
61
|
+
});
|
|
62
|
+
function validateStorage(value) {
|
|
63
|
+
const result = StorageSchema(value);
|
|
64
|
+
if (result instanceof type.errors) {
|
|
65
|
+
const messages = result.map((p) => p.message).join("; ");
|
|
66
|
+
throw new Error(`Storage validation failed: ${messages}`);
|
|
67
|
+
}
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
function validateModel(value) {
|
|
71
|
+
const result = ModelSchema(value);
|
|
72
|
+
if (result instanceof type.errors) {
|
|
73
|
+
const messages = result.map((p) => p.message).join("; ");
|
|
74
|
+
throw new Error(`Model validation failed: ${messages}`);
|
|
75
|
+
}
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
function validateSqlContract(value) {
|
|
79
|
+
const rawValue = value;
|
|
80
|
+
if (rawValue.targetFamily !== void 0 && rawValue.targetFamily !== "sql") {
|
|
81
|
+
throw new Error(`Unsupported target family: ${rawValue.targetFamily}`);
|
|
82
|
+
}
|
|
83
|
+
const contractResult = SqlContractSchema(value);
|
|
84
|
+
if (contractResult instanceof type.errors) {
|
|
85
|
+
const messages = contractResult.map((p) => p.message).join("; ");
|
|
86
|
+
throw new Error(`Contract structural validation failed: ${messages}`);
|
|
87
|
+
}
|
|
88
|
+
return contractResult;
|
|
89
|
+
}
|
|
90
|
+
export {
|
|
91
|
+
validateModel,
|
|
92
|
+
validateSqlContract,
|
|
93
|
+
validateStorage
|
|
94
|
+
};
|
|
95
|
+
//# sourceMappingURL=validators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/validators.ts"],"sourcesContent":["import { type } from 'arktype';\nimport type {\n ForeignKey,\n ForeignKeyReferences,\n Index,\n ModelDefinition,\n ModelField,\n ModelStorage,\n PrimaryKey,\n SqlContract,\n SqlStorage,\n StorageColumn,\n StorageTable,\n UniqueConstraint,\n} from './types';\n\nconst StorageColumnSchema = type.declare<StorageColumn>().type({\n type: 'string',\n nullable: 'boolean',\n});\n\nconst PrimaryKeySchema = type.declare<PrimaryKey>().type({\n columns: type.string.array().readonly(),\n 'name?': 'string',\n});\n\nconst UniqueConstraintSchema = type.declare<UniqueConstraint>().type({\n columns: type.string.array().readonly(),\n 'name?': 'string',\n});\n\nconst IndexSchema = type.declare<Index>().type({\n columns: type.string.array().readonly(),\n 'name?': 'string',\n});\n\nconst ForeignKeyReferencesSchema = type.declare<ForeignKeyReferences>().type({\n table: 'string',\n columns: type.string.array().readonly(),\n});\n\nconst ForeignKeySchema = type.declare<ForeignKey>().type({\n columns: type.string.array().readonly(),\n references: ForeignKeyReferencesSchema,\n 'name?': 'string',\n});\n\nconst StorageTableSchema = type.declare<StorageTable>().type({\n columns: type({ '[string]': StorageColumnSchema }),\n 'primaryKey?': PrimaryKeySchema,\n uniques: UniqueConstraintSchema.array().readonly(),\n indexes: IndexSchema.array().readonly(),\n foreignKeys: ForeignKeySchema.array().readonly(),\n});\n\nconst StorageSchema = type.declare<SqlStorage>().type({\n tables: type({ '[string]': StorageTableSchema }),\n});\n\nconst ModelFieldSchema = type.declare<ModelField>().type({\n column: 'string',\n});\n\nconst ModelStorageSchema = type.declare<ModelStorage>().type({\n table: 'string',\n});\n\nconst ModelSchema = type.declare<ModelDefinition>().type({\n storage: ModelStorageSchema,\n fields: type({ '[string]': ModelFieldSchema }),\n relations: type({ '[string]': 'unknown' }),\n});\n\nconst SqlContractSchema = type({\n 'schemaVersion?': \"'1'\",\n target: 'string',\n targetFamily: \"'sql'\",\n coreHash: 'string',\n 'profileHash?': 'string',\n 'capabilities?': 'Record<string, Record<string, boolean>>',\n 'extensions?': 'Record<string, unknown>',\n 'meta?': 'Record<string, unknown>',\n 'sources?': 'Record<string, unknown>',\n models: type({ '[string]': ModelSchema }),\n storage: StorageSchema,\n});\n\n/**\n * Validates the structural shape of SqlStorage using Arktype.\n *\n * @param value - The storage value to validate\n * @returns The validated storage if structure is valid\n * @throws Error if the storage structure is invalid\n */\nexport function validateStorage(value: unknown): SqlStorage {\n const result = StorageSchema(value);\n if (result instanceof type.errors) {\n const messages = result.map((p: { message: string }) => p.message).join('; ');\n throw new Error(`Storage validation failed: ${messages}`);\n }\n return result;\n}\n\n/**\n * Validates the structural shape of ModelDefinition using Arktype.\n *\n * @param value - The model value to validate\n * @returns The validated model if structure is valid\n * @throws Error if the model structure is invalid\n */\nexport function validateModel(value: unknown): ModelDefinition {\n const result = ModelSchema(value);\n if (result instanceof type.errors) {\n const messages = result.map((p: { message: string }) => p.message).join('; ');\n throw new Error(`Model validation failed: ${messages}`);\n }\n return result;\n}\n\n/**\n * Validates the structural shape of a SqlContract using Arktype.\n *\n * **Responsibility: Validation Only**\n * This function validates that the contract has the correct structure and types.\n * It does NOT normalize the contract - normalization must happen in the contract builder.\n *\n * The contract passed to this function must already be normalized (all required fields present).\n * If normalization is needed, it should be done by the contract builder before calling this function.\n *\n * This ensures all required fields are present and have the correct types.\n *\n * @param value - The contract value to validate (typically from a JSON import)\n * @returns The validated contract if structure is valid\n * @throws Error if the contract structure is invalid\n */\nexport function validateSqlContract<T extends SqlContract<SqlStorage>>(value: unknown): T {\n // Check targetFamily first to provide a clear error message for unsupported target families\n const rawValue = value as { targetFamily?: string };\n if (rawValue.targetFamily !== undefined && rawValue.targetFamily !== 'sql') {\n throw new Error(`Unsupported target family: ${rawValue.targetFamily}`);\n }\n\n const contractResult = SqlContractSchema(value);\n\n if (contractResult instanceof type.errors) {\n const messages = contractResult.map((p: { message: string }) => p.message).join('; ');\n throw new Error(`Contract structural validation failed: ${messages}`);\n }\n\n // After validation, contractResult matches the schema and preserves the input structure\n // TypeScript needs an assertion here due to exactOptionalPropertyTypes differences\n // between Arktype's inferred type and the generic T, but runtime-wise they're compatible\n return contractResult as T;\n}\n"],"mappings":";AAAA,SAAS,YAAY;AAgBrB,IAAM,sBAAsB,KAAK,QAAuB,EAAE,KAAK;AAAA,EAC7D,MAAM;AAAA,EACN,UAAU;AACZ,CAAC;AAED,IAAM,mBAAmB,KAAK,QAAoB,EAAE,KAAK;AAAA,EACvD,SAAS,KAAK,OAAO,MAAM,EAAE,SAAS;AAAA,EACtC,SAAS;AACX,CAAC;AAED,IAAM,yBAAyB,KAAK,QAA0B,EAAE,KAAK;AAAA,EACnE,SAAS,KAAK,OAAO,MAAM,EAAE,SAAS;AAAA,EACtC,SAAS;AACX,CAAC;AAED,IAAM,cAAc,KAAK,QAAe,EAAE,KAAK;AAAA,EAC7C,SAAS,KAAK,OAAO,MAAM,EAAE,SAAS;AAAA,EACtC,SAAS;AACX,CAAC;AAED,IAAM,6BAA6B,KAAK,QAA8B,EAAE,KAAK;AAAA,EAC3E,OAAO;AAAA,EACP,SAAS,KAAK,OAAO,MAAM,EAAE,SAAS;AACxC,CAAC;AAED,IAAM,mBAAmB,KAAK,QAAoB,EAAE,KAAK;AAAA,EACvD,SAAS,KAAK,OAAO,MAAM,EAAE,SAAS;AAAA,EACtC,YAAY;AAAA,EACZ,SAAS;AACX,CAAC;AAED,IAAM,qBAAqB,KAAK,QAAsB,EAAE,KAAK;AAAA,EAC3D,SAAS,KAAK,EAAE,YAAY,oBAAoB,CAAC;AAAA,EACjD,eAAe;AAAA,EACf,SAAS,uBAAuB,MAAM,EAAE,SAAS;AAAA,EACjD,SAAS,YAAY,MAAM,EAAE,SAAS;AAAA,EACtC,aAAa,iBAAiB,MAAM,EAAE,SAAS;AACjD,CAAC;AAED,IAAM,gBAAgB,KAAK,QAAoB,EAAE,KAAK;AAAA,EACpD,QAAQ,KAAK,EAAE,YAAY,mBAAmB,CAAC;AACjD,CAAC;AAED,IAAM,mBAAmB,KAAK,QAAoB,EAAE,KAAK;AAAA,EACvD,QAAQ;AACV,CAAC;AAED,IAAM,qBAAqB,KAAK,QAAsB,EAAE,KAAK;AAAA,EAC3D,OAAO;AACT,CAAC;AAED,IAAM,cAAc,KAAK,QAAyB,EAAE,KAAK;AAAA,EACvD,SAAS;AAAA,EACT,QAAQ,KAAK,EAAE,YAAY,iBAAiB,CAAC;AAAA,EAC7C,WAAW,KAAK,EAAE,YAAY,UAAU,CAAC;AAC3C,CAAC;AAED,IAAM,oBAAoB,KAAK;AAAA,EAC7B,kBAAkB;AAAA,EAClB,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,UAAU;AAAA,EACV,gBAAgB;AAAA,EAChB,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,QAAQ,KAAK,EAAE,YAAY,YAAY,CAAC;AAAA,EACxC,SAAS;AACX,CAAC;AASM,SAAS,gBAAgB,OAA4B;AAC1D,QAAM,SAAS,cAAc,KAAK;AAClC,MAAI,kBAAkB,KAAK,QAAQ;AACjC,UAAM,WAAW,OAAO,IAAI,CAAC,MAA2B,EAAE,OAAO,EAAE,KAAK,IAAI;AAC5E,UAAM,IAAI,MAAM,8BAA8B,QAAQ,EAAE;AAAA,EAC1D;AACA,SAAO;AACT;AASO,SAAS,cAAc,OAAiC;AAC7D,QAAM,SAAS,YAAY,KAAK;AAChC,MAAI,kBAAkB,KAAK,QAAQ;AACjC,UAAM,WAAW,OAAO,IAAI,CAAC,MAA2B,EAAE,OAAO,EAAE,KAAK,IAAI;AAC5E,UAAM,IAAI,MAAM,4BAA4B,QAAQ,EAAE;AAAA,EACxD;AACA,SAAO;AACT;AAkBO,SAAS,oBAAuD,OAAmB;AAExF,QAAM,WAAW;AACjB,MAAI,SAAS,iBAAiB,UAAa,SAAS,iBAAiB,OAAO;AAC1E,UAAM,IAAI,MAAM,8BAA8B,SAAS,YAAY,EAAE;AAAA,EACvE;AAEA,QAAM,iBAAiB,kBAAkB,KAAK;AAE9C,MAAI,0BAA0B,KAAK,QAAQ;AACzC,UAAM,WAAW,eAAe,IAAI,CAAC,MAA2B,EAAE,OAAO,EAAE,KAAK,IAAI;AACpF,UAAM,IAAI,MAAM,0CAA0C,QAAQ,EAAE;AAAA,EACtE;AAKA,SAAO;AACT;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@prisma-next/sql-contract",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"sideEffects": false,
|
|
6
|
+
"description": "SQL contract types, validators, and IR factories for Prisma Next",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"arktype": "^2.1.25",
|
|
9
|
+
"@prisma-next/contract": "0.0.1"
|
|
10
|
+
},
|
|
11
|
+
"devDependencies": {
|
|
12
|
+
"@vitest/coverage-v8": "^2.1.1",
|
|
13
|
+
"tsup": "^8.3.0",
|
|
14
|
+
"typescript": "^5.9.3",
|
|
15
|
+
"vitest": "^2.1.1",
|
|
16
|
+
"@prisma-next/test-utils": "0.0.1"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"exports": {
|
|
22
|
+
"./types": {
|
|
23
|
+
"types": "./dist/exports/types.d.ts",
|
|
24
|
+
"import": "./dist/exports/types.js"
|
|
25
|
+
},
|
|
26
|
+
"./validators": {
|
|
27
|
+
"types": "./dist/exports/validators.d.ts",
|
|
28
|
+
"import": "./dist/exports/validators.js"
|
|
29
|
+
},
|
|
30
|
+
"./factories": {
|
|
31
|
+
"types": "./dist/exports/factories.d.ts",
|
|
32
|
+
"import": "./dist/exports/factories.js"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsup --config tsup.config.ts",
|
|
37
|
+
"test": "vitest run",
|
|
38
|
+
"test:coverage": "vitest run --coverage",
|
|
39
|
+
"typecheck": "tsc --project tsconfig.json --noEmit",
|
|
40
|
+
"lint": "biome check . --config-path ../../../biome.json --error-on-warnings",
|
|
41
|
+
"clean": "node ../../../../scripts/clean.mjs"
|
|
42
|
+
}
|
|
43
|
+
}
|