@prisma-next/sql-relational-core 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 +123 -0
- package/dist/chunk-2F7DSEOU.js +8 -0
- package/dist/chunk-2F7DSEOU.js.map +1 -0
- package/dist/chunk-7FMQVMSM.js +128 -0
- package/dist/chunk-7FMQVMSM.js.map +1 -0
- package/dist/chunk-7I3EMQID.js +16 -0
- package/dist/chunk-7I3EMQID.js.map +1 -0
- package/dist/chunk-ENOLRQZS.js +320 -0
- package/dist/chunk-ENOLRQZS.js.map +1 -0
- package/dist/chunk-FMVAOBWJ.js +151 -0
- package/dist/chunk-FMVAOBWJ.js.map +1 -0
- package/dist/chunk-G52ENULI.js +1 -0
- package/dist/chunk-G52ENULI.js.map +1 -0
- package/dist/chunk-ILC64YWE.js +9 -0
- package/dist/chunk-ILC64YWE.js.map +1 -0
- package/dist/chunk-U7AXAUJA.js +1 -0
- package/dist/chunk-U7AXAUJA.js.map +1 -0
- package/dist/chunk-UVFWELV2.js +1 -0
- package/dist/chunk-UVFWELV2.js.map +1 -0
- package/dist/exports/ast.d.ts +119 -0
- package/dist/exports/ast.js +46 -0
- package/dist/exports/ast.js.map +1 -0
- package/dist/exports/errors.d.ts +1 -0
- package/dist/exports/errors.js +9 -0
- package/dist/exports/errors.js.map +1 -0
- package/dist/exports/operations-registry.d.ts +13 -0
- package/dist/exports/operations-registry.js +8 -0
- package/dist/exports/operations-registry.js.map +1 -0
- package/dist/exports/param.d.ts +14 -0
- package/dist/exports/param.js +7 -0
- package/dist/exports/param.js.map +1 -0
- package/dist/exports/plan.d.ts +4 -0
- package/dist/exports/plan.js +2 -0
- package/dist/exports/plan.js.map +1 -0
- package/dist/exports/query-lane-context.d.ts +4 -0
- package/dist/exports/query-lane-context.js +2 -0
- package/dist/exports/query-lane-context.js.map +1 -0
- package/dist/exports/schema.d.ts +63 -0
- package/dist/exports/schema.js +12 -0
- package/dist/exports/schema.js.map +1 -0
- package/dist/exports/types.d.ts +306 -0
- package/dist/exports/types.js +7 -0
- package/dist/exports/types.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +74 -0
- package/dist/index.js.map +1 -0
- package/dist/plan-D6dOf1wQ.d.ts +135 -0
- package/dist/query-lane-context-BhOMmb_K.d.ts +158 -0
- package/package.json +72 -0
package/README.md
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# @prisma-next/sql-relational-core
|
|
2
|
+
|
|
3
|
+
Schema and column builders, operation attachment, and AST types for Prisma Next.
|
|
4
|
+
|
|
5
|
+
## Package Classification
|
|
6
|
+
|
|
7
|
+
- **Domain**: sql
|
|
8
|
+
- **Layer**: lanes
|
|
9
|
+
- **Plane**: runtime
|
|
10
|
+
|
|
11
|
+
## Overview
|
|
12
|
+
|
|
13
|
+
The relational core package provides the foundational primitives for building relational SQL queries. It includes table/column builders, parameter helpers, operation attachment logic, and type definitions that are shared across SQL query lanes (DSL, ORM, Raw).
|
|
14
|
+
|
|
15
|
+
This package is part of the SQL lanes layer and provides the relational primitives that both the SQL DSL and ORM builder depend on.
|
|
16
|
+
|
|
17
|
+
## Purpose
|
|
18
|
+
|
|
19
|
+
Provide shared relational primitives (schema builders, column builders, parameter helpers, operations registry) that can be consumed by multiple SQL query lanes without code duplication.
|
|
20
|
+
|
|
21
|
+
## Responsibilities
|
|
22
|
+
|
|
23
|
+
- **Schema Builder**: Creates typed table and column builders from contracts
|
|
24
|
+
- **Column Builders**: Provides column accessors with operation methods attached based on column typeId
|
|
25
|
+
- **Parameter Helpers**: Creates parameter placeholders for query building
|
|
26
|
+
- **Operations Registry**: Attaches registered operations as methods on column builders
|
|
27
|
+
- **Type Definitions**: Defines TypeScript types for column builders, operations, and projections
|
|
28
|
+
|
|
29
|
+
**Non-goals:**
|
|
30
|
+
- Query DSL construction (sql-lane)
|
|
31
|
+
- ORM lowering (orm-lane)
|
|
32
|
+
- Raw SQL handling (sql-lane)
|
|
33
|
+
- Execution or runtime behavior (runtime)
|
|
34
|
+
|
|
35
|
+
## Architecture
|
|
36
|
+
|
|
37
|
+
```mermaid
|
|
38
|
+
flowchart TD
|
|
39
|
+
subgraph "Relational Core"
|
|
40
|
+
SCHEMA[Schema Builder]
|
|
41
|
+
COL[Column Builders]
|
|
42
|
+
PARAM[Parameter Helpers]
|
|
43
|
+
OPS[Operations Registry]
|
|
44
|
+
TYPES[Type Definitions]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
subgraph "Consumers"
|
|
48
|
+
SQL[SQL Lane]
|
|
49
|
+
ORM[ORM Lane]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
SCHEMA --> SQL
|
|
53
|
+
SCHEMA --> ORM
|
|
54
|
+
COL --> SQL
|
|
55
|
+
COL --> ORM
|
|
56
|
+
PARAM --> SQL
|
|
57
|
+
PARAM --> ORM
|
|
58
|
+
OPS --> SQL
|
|
59
|
+
OPS --> ORM
|
|
60
|
+
TYPES --> SQL
|
|
61
|
+
TYPES --> ORM
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Components
|
|
65
|
+
|
|
66
|
+
### Schema Builder (`schema.ts`)
|
|
67
|
+
- Creates a schema handle with typed table builders
|
|
68
|
+
- Builds column builders with operation methods attached
|
|
69
|
+
- Provides proxy access for convenience (e.g., `tables.user.id` in addition to `tables.user.columns.id`)
|
|
70
|
+
|
|
71
|
+
### Column Builders (`types.ts`)
|
|
72
|
+
- Defines `ColumnBuilder` type with operation methods based on column typeId
|
|
73
|
+
- Provides type inference for JavaScript types from codec types
|
|
74
|
+
- Supports operation chaining when operations return typeIds
|
|
75
|
+
|
|
76
|
+
### Parameter Helpers (`param.ts`)
|
|
77
|
+
- Creates parameter placeholders for query building
|
|
78
|
+
- Validates parameter names
|
|
79
|
+
|
|
80
|
+
### Operations Registry (`operations-registry.ts`)
|
|
81
|
+
- Attaches registered operations as methods on `ColumnBuilder` instances
|
|
82
|
+
- Dynamically exposes operations based on column `typeId` and contract capabilities
|
|
83
|
+
- Handles operation chaining when operations return typeIds
|
|
84
|
+
|
|
85
|
+
### Type Definitions (`types.ts`)
|
|
86
|
+
- Defines TypeScript types for column builders, operations, projections
|
|
87
|
+
- Provides type inference utilities for extracting JavaScript types from codec types (e.g., `ExtractJsTypeFromColumnBuilder`)
|
|
88
|
+
- Defines projection row inference types
|
|
89
|
+
- Defines `AnyColumnBuilder` helper type for accepting column builders with any operation types
|
|
90
|
+
|
|
91
|
+
## Dependencies
|
|
92
|
+
|
|
93
|
+
- **`@prisma-next/contract`**: Core contract types
|
|
94
|
+
- **`@prisma-next/plan`**: Plan error helpers (`planInvalid`, `planUnsupported`) and `RuntimeError` type
|
|
95
|
+
- **`@prisma-next/runtime`**: Runtime context types (TODO: Slice 6 will clean this up)
|
|
96
|
+
- **`@prisma-next/sql-target`**: SQL contract types, adapter interfaces
|
|
97
|
+
|
|
98
|
+
**Note**: This package does not depend on specific adapters (e.g., `@prisma-next/adapter-postgres`). Test fixtures define `CodecTypes` inline to remain adapter-agnostic and avoid cyclic dependencies.
|
|
99
|
+
|
|
100
|
+
**Note**: Error helpers (`planInvalid`, `planUnsupported`) and the `RuntimeError` type are imported from `@prisma-next/plan` (core ring) rather than being defined locally. This ensures target-agnostic error handling.
|
|
101
|
+
|
|
102
|
+
## Package Structure
|
|
103
|
+
|
|
104
|
+
This package follows the standard `exports/` directory pattern:
|
|
105
|
+
|
|
106
|
+
- `src/exports/schema.ts` - Re-exports schema builder
|
|
107
|
+
- `src/exports/param.ts` - Re-exports parameter helpers
|
|
108
|
+
- `src/exports/types.ts` - Re-exports type definitions
|
|
109
|
+
- `src/exports/operations-registry.ts` - Re-exports operations registry
|
|
110
|
+
- `src/exports/errors.ts` - Re-exports error helpers (from `@prisma-next/plan`)
|
|
111
|
+
- `src/index.ts` - Main entry point that re-exports from `exports/`
|
|
112
|
+
|
|
113
|
+
This enables subpath imports like `@prisma-next/sql-relational-core/schema`, `@prisma-next/sql-relational-core/param`, etc.
|
|
114
|
+
|
|
115
|
+
## Related Subsystems
|
|
116
|
+
|
|
117
|
+
- **[Query Lanes](../../../../docs/architecture%20docs/subsystems/3.%20Query%20Lanes.md)**: Detailed subsystem specification
|
|
118
|
+
- **[Runtime & Plugin Framework](../../../../docs/architecture%20docs/subsystems/4.%20Runtime%20&%20Plugin%20Framework.md)**: Plan execution
|
|
119
|
+
|
|
120
|
+
## Related ADRs
|
|
121
|
+
|
|
122
|
+
- [ADR 140 - Package Layering & Target-Family Namespacing](../../../../docs/architecture%20docs/adrs/ADR%20140%20-%20Package%20Layering%20&%20Target-Family%20Namespacing.md)
|
|
123
|
+
- [ADR 005 - Thin Core, Fat Targets](../../../../docs/architecture%20docs/adrs/ADR%20005%20-%20Thin%20Core,%20Fat%20Targets.md)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts"],"sourcesContent":["export { planInvalid, planUnsupported } from '@prisma-next/plan';\n"],"mappings":";AAAA,SAAS,aAAa,uBAAuB;","names":[]}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import {
|
|
2
|
+
attachOperationsToColumnBuilder
|
|
3
|
+
} from "./chunk-FMVAOBWJ.js";
|
|
4
|
+
|
|
5
|
+
// src/schema.ts
|
|
6
|
+
import { planInvalid } from "@prisma-next/plan";
|
|
7
|
+
var ColumnBuilderImpl = class {
|
|
8
|
+
constructor(table, column, storageColumn) {
|
|
9
|
+
this.table = table;
|
|
10
|
+
this.column = column;
|
|
11
|
+
this.storageColumn = storageColumn;
|
|
12
|
+
}
|
|
13
|
+
kind = "column";
|
|
14
|
+
get columnMeta() {
|
|
15
|
+
return this.storageColumn;
|
|
16
|
+
}
|
|
17
|
+
// Type-level helper property (not used at runtime)
|
|
18
|
+
get __jsType() {
|
|
19
|
+
return void 0;
|
|
20
|
+
}
|
|
21
|
+
eq(value) {
|
|
22
|
+
if (value.kind !== "param-placeholder") {
|
|
23
|
+
throw planInvalid("Parameter placeholder required for column comparison");
|
|
24
|
+
}
|
|
25
|
+
return Object.freeze({
|
|
26
|
+
kind: "binary",
|
|
27
|
+
op: "eq",
|
|
28
|
+
left: this,
|
|
29
|
+
right: value
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
asc() {
|
|
33
|
+
return Object.freeze({
|
|
34
|
+
kind: "order",
|
|
35
|
+
expr: this,
|
|
36
|
+
dir: "asc"
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
desc() {
|
|
40
|
+
return Object.freeze({
|
|
41
|
+
kind: "order",
|
|
42
|
+
expr: this,
|
|
43
|
+
dir: "desc"
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
var TableBuilderImpl = class {
|
|
48
|
+
kind = "table";
|
|
49
|
+
columns;
|
|
50
|
+
_name;
|
|
51
|
+
constructor(name, columns) {
|
|
52
|
+
this._name = name;
|
|
53
|
+
this.columns = columns;
|
|
54
|
+
}
|
|
55
|
+
get name() {
|
|
56
|
+
return this._name;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
function buildColumns(tableName, storage, _contract, operationRegistry, contractCapabilities) {
|
|
60
|
+
const table = storage.tables[tableName];
|
|
61
|
+
if (!table) {
|
|
62
|
+
throw planInvalid(`Unknown table ${tableName}`);
|
|
63
|
+
}
|
|
64
|
+
const tableColumns = table.columns;
|
|
65
|
+
const result = {};
|
|
66
|
+
const assignColumn = (columnName, columnDef) => {
|
|
67
|
+
const columnBuilder = new ColumnBuilderImpl(
|
|
68
|
+
tableName,
|
|
69
|
+
columnName,
|
|
70
|
+
columnDef
|
|
71
|
+
);
|
|
72
|
+
const builderWithOps = attachOperationsToColumnBuilder(
|
|
73
|
+
columnBuilder,
|
|
74
|
+
columnDef,
|
|
75
|
+
operationRegistry,
|
|
76
|
+
contractCapabilities
|
|
77
|
+
);
|
|
78
|
+
result[columnName] = builderWithOps;
|
|
79
|
+
};
|
|
80
|
+
for (const columnName of Object.keys(tableColumns)) {
|
|
81
|
+
const columnDef = tableColumns[columnName];
|
|
82
|
+
if (!columnDef) continue;
|
|
83
|
+
assignColumn(columnName, columnDef);
|
|
84
|
+
}
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
function createTableProxy(table) {
|
|
88
|
+
return new Proxy(table, {
|
|
89
|
+
get(target, prop) {
|
|
90
|
+
if (prop === "name" || prop === "kind" || prop === "columns") {
|
|
91
|
+
return Reflect.get(target, prop);
|
|
92
|
+
}
|
|
93
|
+
if (typeof prop === "string" && prop in target.columns) {
|
|
94
|
+
return target.columns[prop];
|
|
95
|
+
}
|
|
96
|
+
return void 0;
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
function schema(context) {
|
|
101
|
+
const contract = context.contract;
|
|
102
|
+
const storage = contract.storage;
|
|
103
|
+
const tables = {};
|
|
104
|
+
const contractCapabilities = contract.capabilities;
|
|
105
|
+
const operationRegistry = context.operations;
|
|
106
|
+
for (const tableName of Object.keys(storage.tables)) {
|
|
107
|
+
const columns = buildColumns(
|
|
108
|
+
tableName,
|
|
109
|
+
storage,
|
|
110
|
+
contract,
|
|
111
|
+
operationRegistry,
|
|
112
|
+
contractCapabilities
|
|
113
|
+
);
|
|
114
|
+
const table = new TableBuilderImpl(tableName, columns);
|
|
115
|
+
const proxiedTable = createTableProxy(table);
|
|
116
|
+
tables[tableName] = Object.freeze(
|
|
117
|
+
proxiedTable
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
return Object.freeze({ tables });
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export {
|
|
124
|
+
ColumnBuilderImpl,
|
|
125
|
+
TableBuilderImpl,
|
|
126
|
+
schema
|
|
127
|
+
};
|
|
128
|
+
//# sourceMappingURL=chunk-7FMQVMSM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/schema.ts"],"sourcesContent":["import type { OperationRegistry } from '@prisma-next/operations';\nimport { planInvalid } from '@prisma-next/plan';\nimport type {\n ExtractCodecTypes,\n ExtractOperationTypes,\n SqlContract,\n SqlStorage,\n StorageColumn,\n} from '@prisma-next/sql-contract/types';\nimport type { TableRef } from './ast/types';\nimport { attachOperationsToColumnBuilder } from './operations-registry';\nimport type { QueryLaneContext } from './query-lane-context';\nimport type {\n BinaryBuilder,\n CodecTypes as CodecTypesType,\n ColumnBuilder,\n ComputeColumnJsType,\n OperationTypeSignature,\n OperationTypes,\n OrderBuilder,\n ParamPlaceholder,\n} from './types';\n\ntype TableColumns<Table extends { columns: Record<string, StorageColumn> }> = Table['columns'];\n\ntype ColumnBuilders<\n Contract extends SqlContract<SqlStorage>,\n TableName extends string,\n Columns extends Record<string, StorageColumn>,\n CodecTypes extends CodecTypesType,\n Operations extends OperationTypes,\n> = {\n readonly [K in keyof Columns]: ColumnBuilder<\n K & string,\n Columns[K],\n ComputeColumnJsType<Contract, TableName, K & string, Columns[K], CodecTypes>,\n Operations\n >;\n};\n\nexport class ColumnBuilderImpl<\n ColumnName extends string,\n ColumnMeta extends StorageColumn,\n JsType = unknown,\n> {\n readonly kind = 'column' as const;\n\n constructor(\n readonly table: string,\n readonly column: ColumnName,\n private readonly storageColumn: ColumnMeta,\n ) {}\n\n get columnMeta(): ColumnMeta {\n return this.storageColumn;\n }\n\n // Type-level helper property (not used at runtime)\n get __jsType(): JsType {\n return undefined as unknown as JsType;\n }\n\n eq(\n this: ColumnBuilderImpl<ColumnName, ColumnMeta, JsType>,\n value: ParamPlaceholder,\n ): BinaryBuilder<ColumnName, ColumnMeta, JsType> {\n if (value.kind !== 'param-placeholder') {\n throw planInvalid('Parameter placeholder required for column comparison');\n }\n\n return Object.freeze({\n kind: 'binary' as const,\n op: 'eq' as const,\n left: this as unknown as ColumnBuilder<ColumnName, ColumnMeta, JsType>,\n right: value,\n }) as BinaryBuilder<ColumnName, ColumnMeta, JsType>;\n }\n\n asc(\n this: ColumnBuilderImpl<ColumnName, ColumnMeta, JsType>,\n ): OrderBuilder<ColumnName, ColumnMeta, JsType> {\n return Object.freeze({\n kind: 'order' as const,\n expr: this as unknown as ColumnBuilder<ColumnName, ColumnMeta, JsType>,\n dir: 'asc' as const,\n }) as OrderBuilder<ColumnName, ColumnMeta, JsType>;\n }\n\n desc(\n this: ColumnBuilderImpl<ColumnName, ColumnMeta, JsType>,\n ): OrderBuilder<ColumnName, ColumnMeta, JsType> {\n return Object.freeze({\n kind: 'order' as const,\n expr: this as unknown as ColumnBuilder<ColumnName, ColumnMeta, JsType>,\n dir: 'desc' as const,\n }) as OrderBuilder<ColumnName, ColumnMeta, JsType>;\n }\n}\n\nexport class TableBuilderImpl<\n Contract extends SqlContract<SqlStorage>,\n TableName extends string,\n Columns extends Record<string, StorageColumn>,\n CodecTypes extends CodecTypesType,\n Operations extends OperationTypes,\n> implements TableRef\n{\n readonly kind = 'table' as const;\n readonly columns: ColumnBuilders<Contract, TableName, Columns, CodecTypes, Operations>;\n private readonly _name: TableName;\n\n constructor(\n name: TableName,\n columns: ColumnBuilders<Contract, TableName, Columns, CodecTypes, Operations>,\n ) {\n this._name = name;\n this.columns = columns;\n }\n\n get name(): string {\n return this._name;\n }\n}\n\nfunction buildColumns<\n Contract extends SqlContract<SqlStorage>,\n TableName extends keyof Contract['storage']['tables'] & string,\n CodecTypes extends CodecTypesType,\n Operations extends OperationTypes,\n>(\n tableName: TableName,\n storage: SqlStorage,\n _contract: Contract,\n operationRegistry?: OperationRegistry,\n contractCapabilities?: Record<string, Record<string, boolean>>,\n): ColumnBuilders<\n Contract,\n TableName,\n Contract['storage']['tables'][TableName]['columns'],\n CodecTypes,\n Operations\n> {\n const table = storage.tables[tableName];\n\n if (!table) {\n throw planInvalid(`Unknown table ${tableName}`);\n }\n\n type Columns = Contract['storage']['tables'][TableName]['columns'];\n const tableColumns = table.columns as Columns;\n\n const result = {} as {\n [K in keyof Columns]: ColumnBuilder<\n K & string,\n Columns[K],\n ComputeColumnJsType<Contract, TableName, K & string, Columns[K], CodecTypes>,\n Operations\n >;\n };\n\n const assignColumn = <ColumnKey extends keyof Columns & string>(\n columnName: ColumnKey,\n columnDef: Columns[ColumnKey],\n ) => {\n type JsType = ComputeColumnJsType<\n Contract,\n TableName,\n ColumnKey,\n Columns[ColumnKey],\n CodecTypes\n >;\n\n const columnBuilder = new ColumnBuilderImpl<ColumnKey, Columns[ColumnKey], JsType>(\n tableName,\n columnName,\n columnDef,\n );\n\n const builderWithOps = attachOperationsToColumnBuilder<\n ColumnKey,\n Columns[ColumnKey],\n JsType,\n Operations\n >(\n columnBuilder as unknown as ColumnBuilder<\n ColumnKey,\n Columns[ColumnKey],\n JsType,\n Record<string, never>\n >,\n columnDef,\n operationRegistry,\n contractCapabilities,\n );\n\n (result as Record<string, unknown>)[columnName] = builderWithOps;\n };\n\n for (const columnName of Object.keys(tableColumns) as Array<keyof Columns & string>) {\n const columnDef = tableColumns[columnName];\n if (!columnDef) continue;\n assignColumn(columnName, columnDef);\n }\n\n return result as ColumnBuilders<Contract, TableName, Columns, CodecTypes, Operations>;\n}\n\n/**\n * Creates a Proxy that enables accessing table columns directly on the table object,\n * in addition to the standard `table.columns.columnName` syntax.\n *\n * This allows both access patterns:\n * - `tables.user.columns.id` (standard access)\n * - `tables.user.id` (convenience access via proxy)\n *\n * The proxy intercepts property access and routes column name lookups to\n * `table.columns[prop]`, while preserving direct access to table properties\n * like `name`, `kind`, and `columns`.\n */\nfunction createTableProxy<\n Contract extends SqlContract<SqlStorage>,\n TableName extends string,\n Columns extends Record<string, StorageColumn>,\n CodecTypes extends CodecTypesType,\n Operations extends OperationTypes,\n>(\n table: TableBuilderImpl<Contract, TableName, Columns, CodecTypes, Operations>,\n): TableBuilderImpl<Contract, TableName, Columns, CodecTypes, Operations> {\n return new Proxy(table, {\n get(target, prop) {\n if (prop === 'name' || prop === 'kind' || prop === 'columns') {\n return Reflect.get(target, prop);\n }\n if (typeof prop === 'string' && prop in target.columns) {\n return target.columns[prop as keyof typeof target.columns];\n }\n return undefined;\n },\n });\n}\n\ntype ExtractSchemaTables<\n Contract extends SqlContract<SqlStorage>,\n CodecTypes extends CodecTypesType,\n Operations extends OperationTypes,\n> = {\n readonly [TableName in keyof Contract['storage']['tables']]: TableBuilderImpl<\n Contract,\n TableName & string,\n TableColumns<Contract['storage']['tables'][TableName]>,\n CodecTypes,\n Operations\n > &\n TableRef;\n};\n\nexport type SchemaHandle<\n Contract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>,\n CodecTypes extends CodecTypesType = CodecTypesType,\n Operations extends OperationTypes = Record<string, never>,\n> = {\n readonly tables: ExtractSchemaTables<Contract, CodecTypes, Operations>;\n};\n\ntype SchemaReturnType<Contract extends SqlContract<SqlStorage>> = SchemaHandle<\n Contract,\n ExtractCodecTypes<Contract>,\n ToOperationTypes<ExtractOperationTypes<Contract>>\n>;\n\ntype NormalizeOperationTypes<T> = {\n [TypeId in keyof T]: {\n [Method in keyof T[TypeId]]: T[TypeId][Method] extends OperationTypeSignature\n ? T[TypeId][Method]\n : OperationTypeSignature;\n };\n};\n\ntype ToOperationTypes<T> = T extends OperationTypes ? T : NormalizeOperationTypes<T>;\n\n/**\n * Creates a schema handle for building SQL queries.\n *\n * @param context - Query lane context containing contract, codec and operation registries\n * @returns A schema handle with typed table builders\n *\n * @example\n * ```typescript\n * const schemaHandle = schema<Contract>(context);\n * const userTable = schemaHandle.tables.user;\n * ```\n */\nexport function schema<Contract extends SqlContract<SqlStorage>>(\n context: QueryLaneContext<Contract>,\n): SchemaReturnType<Contract> {\n const contract = context.contract;\n const storage = contract.storage;\n type CodecTypes = ExtractCodecTypes<Contract>;\n type Operations = ToOperationTypes<ExtractOperationTypes<Contract>>;\n const tables = {} as ExtractSchemaTables<Contract, CodecTypes, Operations>;\n const contractCapabilities = contract.capabilities;\n\n const operationRegistry = context.operations;\n\n for (const tableName of Object.keys(storage.tables) as Array<\n keyof Contract['storage']['tables'] & string\n >) {\n const columns = buildColumns<Contract, typeof tableName, CodecTypes, Operations>(\n tableName,\n storage,\n contract,\n operationRegistry,\n contractCapabilities,\n );\n const table = new TableBuilderImpl<\n Contract,\n typeof tableName & string,\n Contract['storage']['tables'][typeof tableName]['columns'],\n CodecTypes,\n Operations\n >(tableName, columns);\n const proxiedTable = createTableProxy<\n Contract,\n typeof tableName & string,\n Contract['storage']['tables'][typeof tableName]['columns'],\n CodecTypes,\n Operations\n >(table);\n (tables as Record<string, unknown>)[tableName] = Object.freeze(\n proxiedTable,\n ) as ExtractSchemaTables<Contract, CodecTypes, Operations>[typeof tableName];\n }\n\n return Object.freeze({ tables }) as SchemaReturnType<Contract>;\n}\n\nexport type { ColumnBuilderImpl as Column, TableBuilderImpl as Table };\n"],"mappings":";;;;;AACA,SAAS,mBAAmB;AAuCrB,IAAM,oBAAN,MAIL;AAAA,EAGA,YACW,OACA,QACQ,eACjB;AAHS;AACA;AACQ;AAAA,EAChB;AAAA,EANM,OAAO;AAAA,EAQhB,IAAI,aAAyB;AAC3B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,WAAmB;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,GAEE,OAC+C;AAC/C,QAAI,MAAM,SAAS,qBAAqB;AACtC,YAAM,YAAY,sDAAsD;AAAA,IAC1E;AAEA,WAAO,OAAO,OAAO;AAAA,MACnB,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA,EAEA,MAEgD;AAC9C,WAAO,OAAO,OAAO;AAAA,MACnB,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP,CAAC;AAAA,EACH;AAAA,EAEA,OAEgD;AAC9C,WAAO,OAAO,OAAO;AAAA,MACnB,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP,CAAC;AAAA,EACH;AACF;AAEO,IAAM,mBAAN,MAOP;AAAA,EACW,OAAO;AAAA,EACP;AAAA,EACQ;AAAA,EAEjB,YACE,MACA,SACA;AACA,SAAK,QAAQ;AACb,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,IAAI,OAAe;AACjB,WAAO,KAAK;AAAA,EACd;AACF;AAEA,SAAS,aAMP,WACA,SACA,WACA,mBACA,sBAOA;AACA,QAAM,QAAQ,QAAQ,OAAO,SAAS;AAEtC,MAAI,CAAC,OAAO;AACV,UAAM,YAAY,iBAAiB,SAAS,EAAE;AAAA,EAChD;AAGA,QAAM,eAAe,MAAM;AAE3B,QAAM,SAAS,CAAC;AAShB,QAAM,eAAe,CACnB,YACA,cACG;AASH,UAAM,gBAAgB,IAAI;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,UAAM,iBAAiB;AAAA,MAMrB;AAAA,MAMA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,IAAC,OAAmC,UAAU,IAAI;AAAA,EACpD;AAEA,aAAW,cAAc,OAAO,KAAK,YAAY,GAAoC;AACnF,UAAM,YAAY,aAAa,UAAU;AACzC,QAAI,CAAC,UAAW;AAChB,iBAAa,YAAY,SAAS;AAAA,EACpC;AAEA,SAAO;AACT;AAcA,SAAS,iBAOP,OACwE;AACxE,SAAO,IAAI,MAAM,OAAO;AAAA,IACtB,IAAI,QAAQ,MAAM;AAChB,UAAI,SAAS,UAAU,SAAS,UAAU,SAAS,WAAW;AAC5D,eAAO,QAAQ,IAAI,QAAQ,IAAI;AAAA,MACjC;AACA,UAAI,OAAO,SAAS,YAAY,QAAQ,OAAO,SAAS;AACtD,eAAO,OAAO,QAAQ,IAAmC;AAAA,MAC3D;AACA,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACH;AAqDO,SAAS,OACd,SAC4B;AAC5B,QAAM,WAAW,QAAQ;AACzB,QAAM,UAAU,SAAS;AAGzB,QAAM,SAAS,CAAC;AAChB,QAAM,uBAAuB,SAAS;AAEtC,QAAM,oBAAoB,QAAQ;AAElC,aAAW,aAAa,OAAO,KAAK,QAAQ,MAAM,GAE/C;AACD,UAAM,UAAU;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,QAAQ,IAAI,iBAMhB,WAAW,OAAO;AACpB,UAAM,eAAe,iBAMnB,KAAK;AACP,IAAC,OAAmC,SAAS,IAAI,OAAO;AAAA,MACtD;AAAA,IACF;AAAA,EACF;AAEA,SAAO,OAAO,OAAO,EAAE,OAAO,CAAC;AACjC;","names":[]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// src/param.ts
|
|
2
|
+
import { planInvalid } from "@prisma-next/plan";
|
|
3
|
+
function param(name) {
|
|
4
|
+
if (typeof name !== "string" || name.length === 0) {
|
|
5
|
+
throw planInvalid("Parameter name must be a non-empty string");
|
|
6
|
+
}
|
|
7
|
+
return Object.freeze({
|
|
8
|
+
kind: "param-placeholder",
|
|
9
|
+
name
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export {
|
|
14
|
+
param
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=chunk-7I3EMQID.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/param.ts"],"sourcesContent":["import { planInvalid } from '@prisma-next/plan';\nimport type { ParamPlaceholder } from './types';\n\nexport type Parameter = ParamPlaceholder;\n\nexport function param(name: string): Parameter {\n if (typeof name !== 'string' || name.length === 0) {\n throw planInvalid('Parameter name must be a non-empty string');\n }\n\n return Object.freeze({\n kind: 'param-placeholder' as const,\n name,\n }) satisfies Parameter;\n}\n"],"mappings":";AAAA,SAAS,mBAAmB;AAKrB,SAAS,MAAM,MAAyB;AAC7C,MAAI,OAAO,SAAS,YAAY,KAAK,WAAW,GAAG;AACjD,UAAM,YAAY,2CAA2C;AAAA,EAC/D;AAEA,SAAO,OAAO,OAAO;AAAA,IACnB,MAAM;AAAA,IACN;AAAA,EACF,CAAC;AACH;","names":[]}
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isColumnBuilder
|
|
3
|
+
} from "./chunk-ILC64YWE.js";
|
|
4
|
+
|
|
5
|
+
// src/ast/codec-types.ts
|
|
6
|
+
var CodecRegistryImpl = class {
|
|
7
|
+
_byId = /* @__PURE__ */ new Map();
|
|
8
|
+
_byScalar = /* @__PURE__ */ new Map();
|
|
9
|
+
/**
|
|
10
|
+
* Map-like interface for codec lookup by ID.
|
|
11
|
+
* Example: registry.get('pg/text@1')
|
|
12
|
+
*/
|
|
13
|
+
get(id) {
|
|
14
|
+
return this._byId.get(id);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Check if a codec with the given ID is registered.
|
|
18
|
+
*/
|
|
19
|
+
has(id) {
|
|
20
|
+
return this._byId.has(id);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get all codecs that handle a given scalar type.
|
|
24
|
+
* Returns an empty frozen array if no codecs are found.
|
|
25
|
+
* Example: registry.getByScalar('text') → [codec1, codec2, ...]
|
|
26
|
+
*/
|
|
27
|
+
getByScalar(scalar) {
|
|
28
|
+
return this._byScalar.get(scalar) ?? Object.freeze([]);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get the default codec for a scalar type (first registered codec).
|
|
32
|
+
* Returns undefined if no codec handles this scalar type.
|
|
33
|
+
*/
|
|
34
|
+
getDefaultCodec(scalar) {
|
|
35
|
+
const _codecs = this._byScalar.get(scalar);
|
|
36
|
+
return _codecs?.[0];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Register a codec in the registry.
|
|
40
|
+
* Throws an error if a codec with the same ID is already registered.
|
|
41
|
+
*
|
|
42
|
+
* @param codec - The codec to register
|
|
43
|
+
* @throws Error if a codec with the same ID already exists
|
|
44
|
+
*/
|
|
45
|
+
register(codec2) {
|
|
46
|
+
if (this._byId.has(codec2.id)) {
|
|
47
|
+
throw new Error(`Codec with ID '${codec2.id}' is already registered`);
|
|
48
|
+
}
|
|
49
|
+
this._byId.set(codec2.id, codec2);
|
|
50
|
+
for (const scalarType of codec2.targetTypes) {
|
|
51
|
+
const existing = this._byScalar.get(scalarType);
|
|
52
|
+
if (existing) {
|
|
53
|
+
existing.push(codec2);
|
|
54
|
+
} else {
|
|
55
|
+
this._byScalar.set(scalarType, [codec2]);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Returns an iterator over all registered codecs.
|
|
61
|
+
* Useful for iterating through codecs from another registry.
|
|
62
|
+
*/
|
|
63
|
+
*[Symbol.iterator]() {
|
|
64
|
+
for (const codec2 of this._byId.values()) {
|
|
65
|
+
yield codec2;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Returns an iterable of all registered codecs.
|
|
70
|
+
*/
|
|
71
|
+
values() {
|
|
72
|
+
return this._byId.values();
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
function codec(config) {
|
|
76
|
+
return {
|
|
77
|
+
id: config.typeId,
|
|
78
|
+
targetTypes: config.targetTypes,
|
|
79
|
+
...config.meta ? { meta: config.meta } : {},
|
|
80
|
+
encode: config.encode,
|
|
81
|
+
decode: config.decode
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
var CodecDefBuilderImpl = class _CodecDefBuilderImpl {
|
|
85
|
+
_codecs;
|
|
86
|
+
CodecTypes;
|
|
87
|
+
dataTypes;
|
|
88
|
+
constructor(codecs) {
|
|
89
|
+
this._codecs = codecs;
|
|
90
|
+
const codecTypes = {};
|
|
91
|
+
for (const [, codecImpl] of Object.entries(this._codecs)) {
|
|
92
|
+
const codecImplTyped = codecImpl;
|
|
93
|
+
codecTypes[codecImplTyped.id] = {
|
|
94
|
+
input: void 0,
|
|
95
|
+
output: void 0
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
this.CodecTypes = codecTypes;
|
|
99
|
+
const dataTypes = {};
|
|
100
|
+
for (const key in this._codecs) {
|
|
101
|
+
if (Object.hasOwn(this._codecs, key)) {
|
|
102
|
+
const codec2 = this._codecs[key];
|
|
103
|
+
dataTypes[key] = codec2.id;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
this.dataTypes = dataTypes;
|
|
107
|
+
}
|
|
108
|
+
add(scalarName, codecImpl) {
|
|
109
|
+
return new _CodecDefBuilderImpl({
|
|
110
|
+
...this._codecs,
|
|
111
|
+
[scalarName]: codecImpl
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Derive codecDefinitions structure.
|
|
116
|
+
*/
|
|
117
|
+
get codecDefinitions() {
|
|
118
|
+
const result = {};
|
|
119
|
+
for (const [scalarName, codecImpl] of Object.entries(this._codecs)) {
|
|
120
|
+
const codec2 = codecImpl;
|
|
121
|
+
result[scalarName] = {
|
|
122
|
+
typeId: codec2.id,
|
|
123
|
+
scalar: scalarName,
|
|
124
|
+
codec: codec2,
|
|
125
|
+
input: void 0,
|
|
126
|
+
output: void 0,
|
|
127
|
+
jsType: void 0
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
return result;
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
function createCodecRegistry() {
|
|
134
|
+
return new CodecRegistryImpl();
|
|
135
|
+
}
|
|
136
|
+
function defineCodecs() {
|
|
137
|
+
return new CodecDefBuilderImpl({});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// src/ast/util.ts
|
|
141
|
+
function compact(o) {
|
|
142
|
+
const out = {};
|
|
143
|
+
for (const [k, v] of Object.entries(o)) {
|
|
144
|
+
if (v === void 0 || v === null) continue;
|
|
145
|
+
if (Array.isArray(v) && v.length === 0) continue;
|
|
146
|
+
out[k] = v;
|
|
147
|
+
}
|
|
148
|
+
return out;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// src/ast/common.ts
|
|
152
|
+
function createTableRef(name) {
|
|
153
|
+
return {
|
|
154
|
+
kind: "table",
|
|
155
|
+
name
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function createColumnRef(table, column) {
|
|
159
|
+
return {
|
|
160
|
+
kind: "col",
|
|
161
|
+
table,
|
|
162
|
+
column
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function createParamRef(index, name) {
|
|
166
|
+
return compact({
|
|
167
|
+
kind: "param",
|
|
168
|
+
index,
|
|
169
|
+
name
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
function createOperationExpr(operation) {
|
|
173
|
+
return operation;
|
|
174
|
+
}
|
|
175
|
+
function createLiteralExpr(value) {
|
|
176
|
+
return {
|
|
177
|
+
kind: "literal",
|
|
178
|
+
value
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// src/ast/delete.ts
|
|
183
|
+
function createDeleteAst(options) {
|
|
184
|
+
return compact({
|
|
185
|
+
kind: "delete",
|
|
186
|
+
table: options.table,
|
|
187
|
+
where: options.where,
|
|
188
|
+
returning: options.returning
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// src/ast/insert.ts
|
|
193
|
+
function createInsertAst(options) {
|
|
194
|
+
return compact({
|
|
195
|
+
kind: "insert",
|
|
196
|
+
table: options.table,
|
|
197
|
+
values: options.values,
|
|
198
|
+
returning: options.returning
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// src/ast/join.ts
|
|
203
|
+
import { planInvalid } from "@prisma-next/plan";
|
|
204
|
+
function createJoin(joinType, table, on) {
|
|
205
|
+
return {
|
|
206
|
+
kind: "join",
|
|
207
|
+
joinType,
|
|
208
|
+
table,
|
|
209
|
+
on
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
function createJoinOnExpr(left, right) {
|
|
213
|
+
return {
|
|
214
|
+
kind: "eqCol",
|
|
215
|
+
left,
|
|
216
|
+
right
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
var JoinOnBuilderImpl = class {
|
|
220
|
+
eqCol(left, right) {
|
|
221
|
+
if (!left || !isColumnBuilder(left)) {
|
|
222
|
+
throw planInvalid("Join ON left operand must be a column");
|
|
223
|
+
}
|
|
224
|
+
if (!right || !isColumnBuilder(right)) {
|
|
225
|
+
throw planInvalid("Join ON right operand must be a column");
|
|
226
|
+
}
|
|
227
|
+
const leftCol = left;
|
|
228
|
+
const rightCol = right;
|
|
229
|
+
if (leftCol.table === rightCol.table) {
|
|
230
|
+
throw planInvalid("Self-joins are not supported in MVP");
|
|
231
|
+
}
|
|
232
|
+
return {
|
|
233
|
+
kind: "join-on",
|
|
234
|
+
left,
|
|
235
|
+
right
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
function createJoinOnBuilder() {
|
|
240
|
+
return new JoinOnBuilderImpl();
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// src/ast/order.ts
|
|
244
|
+
function createOrderByItem(expr, dir) {
|
|
245
|
+
return {
|
|
246
|
+
expr,
|
|
247
|
+
dir
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// src/ast/predicate.ts
|
|
252
|
+
function createBinaryExpr(op, left, right) {
|
|
253
|
+
return {
|
|
254
|
+
kind: "bin",
|
|
255
|
+
op,
|
|
256
|
+
left,
|
|
257
|
+
right
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
function createExistsExpr(not, subquery) {
|
|
261
|
+
return {
|
|
262
|
+
kind: "exists",
|
|
263
|
+
not,
|
|
264
|
+
subquery
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// src/ast/select.ts
|
|
269
|
+
function createSelectAst(options) {
|
|
270
|
+
return compact({
|
|
271
|
+
kind: "select",
|
|
272
|
+
from: options.from,
|
|
273
|
+
joins: options.joins,
|
|
274
|
+
includes: options.includes,
|
|
275
|
+
project: options.project,
|
|
276
|
+
where: options.where,
|
|
277
|
+
orderBy: options.orderBy,
|
|
278
|
+
limit: options.limit
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// src/ast/types.ts
|
|
283
|
+
function isOperationExpr(expr) {
|
|
284
|
+
return expr.kind === "operation";
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// src/ast/update.ts
|
|
288
|
+
function createUpdateAst(options) {
|
|
289
|
+
return compact({
|
|
290
|
+
kind: "update",
|
|
291
|
+
table: options.table,
|
|
292
|
+
set: options.set,
|
|
293
|
+
where: options.where,
|
|
294
|
+
returning: options.returning
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
export {
|
|
299
|
+
codec,
|
|
300
|
+
createCodecRegistry,
|
|
301
|
+
defineCodecs,
|
|
302
|
+
compact,
|
|
303
|
+
createTableRef,
|
|
304
|
+
createColumnRef,
|
|
305
|
+
createParamRef,
|
|
306
|
+
createOperationExpr,
|
|
307
|
+
createLiteralExpr,
|
|
308
|
+
createDeleteAst,
|
|
309
|
+
createInsertAst,
|
|
310
|
+
createJoin,
|
|
311
|
+
createJoinOnExpr,
|
|
312
|
+
createJoinOnBuilder,
|
|
313
|
+
createOrderByItem,
|
|
314
|
+
createBinaryExpr,
|
|
315
|
+
createExistsExpr,
|
|
316
|
+
createSelectAst,
|
|
317
|
+
isOperationExpr,
|
|
318
|
+
createUpdateAst
|
|
319
|
+
};
|
|
320
|
+
//# sourceMappingURL=chunk-ENOLRQZS.js.map
|