diff --git a/examples/prisma-next-cloudflare-worker/src/prisma/contract.d.ts b/examples/prisma-next-cloudflare-worker/src/prisma/contract.d.ts index 72de230104..894f9e5ecd 100644 --- a/examples/prisma-next-cloudflare-worker/src/prisma/contract.d.ts +++ b/examples/prisma-next-cloudflare-worker/src/prisma/contract.d.ts @@ -34,7 +34,6 @@ export type ProfileHash = ProfileHashBase<'sha256:1a8dbe044289f30a1de958fe800cc5a8378b285d2e126a8c44b58864bac2c18e'>; export type CodecTypes = PgTypes; -export type OperationTypes = Record; export type LaneCodecTypes = CodecTypes; export type QueryOperationTypes = PgAdapterQueryOps; type DefaultLiteralValue = CodecId extends keyof CodecTypes @@ -120,7 +119,6 @@ export type FieldInputTypes = { }; export type TypeMaps = TypeMapsType< CodecTypes, - OperationTypes, QueryOperationTypes, FieldOutputTypes, FieldInputTypes diff --git a/examples/prisma-next-demo/src/prisma/contract.d.ts b/examples/prisma-next-demo/src/prisma/contract.d.ts index 7d1eb3aa07..e0aa3a97ed 100644 --- a/examples/prisma-next-demo/src/prisma/contract.d.ts +++ b/examples/prisma-next-demo/src/prisma/contract.d.ts @@ -15,7 +15,6 @@ import type { Timetz } from '@prisma-next/target-postgres/codec-types'; import type { Interval } from '@prisma-next/target-postgres/codec-types'; import type { CodecTypes as PgVectorTypes } from '@prisma-next/extension-pgvector/codec-types'; import type { Vector } from '@prisma-next/extension-pgvector/codec-types'; -import type { OperationTypes as PgVectorOperationTypes } from '@prisma-next/extension-pgvector/operation-types'; import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma-next/adapter-postgres/operation-types'; import type { QueryOperationTypes as PgVectorQueryOperationTypes } from '@prisma-next/extension-pgvector/operation-types'; @@ -38,7 +37,6 @@ export type ProfileHash = ProfileHashBase<'sha256:1a8dbe044289f30a1de958fe800cc5a8378b285d2e126a8c44b58864bac2c18e'>; export type CodecTypes = PgTypes & PgVectorTypes; -export type OperationTypes = PgVectorOperationTypes; export type LaneCodecTypes = CodecTypes; export type QueryOperationTypes = PgAdapterQueryOps & PgVectorQueryOperationTypes; @@ -127,7 +125,6 @@ export type FieldInputTypes = { }; export type TypeMaps = TypeMapsType< CodecTypes, - OperationTypes, QueryOperationTypes, FieldOutputTypes, FieldInputTypes @@ -582,13 +579,6 @@ type ContractBase = ContractType< }, ]; }; - readonly operationTypes: { - readonly import: { - readonly alias: 'PgVectorOperationTypes'; - readonly named: 'OperationTypes'; - readonly package: '@prisma-next/extension-pgvector/operation-types'; - }; - }; readonly queryOperationTypes: { readonly import: { readonly alias: 'PgVectorQueryOperationTypes'; diff --git a/examples/prisma-next-demo/src/prisma/contract.json b/examples/prisma-next-demo/src/prisma/contract.json index f06c625258..2ad4196c63 100644 --- a/examples/prisma-next-demo/src/prisma/contract.json +++ b/examples/prisma-next-demo/src/prisma/contract.json @@ -704,13 +704,6 @@ } ] }, - "operationTypes": { - "import": { - "alias": "PgVectorOperationTypes", - "named": "OperationTypes", - "package": "@prisma-next/extension-pgvector/operation-types" - } - }, "queryOperationTypes": { "import": { "alias": "PgVectorQueryOperationTypes", diff --git a/examples/prisma-next-demo/test/demo-dx.types.test.ts b/examples/prisma-next-demo/test/demo-dx.types.test.ts index bff0dcf087..9811a10e0f 100644 --- a/examples/prisma-next-demo/test/demo-dx.types.test.ts +++ b/examples/prisma-next-demo/test/demo-dx.types.test.ts @@ -16,7 +16,7 @@ import contractJson from '../src/prisma/contract.json' with { type: 'json' }; test('contract.d.ts exports Contract and TypeMaps separately', () => { expectTypeOf().toHaveProperty('models'); expectTypeOf().toHaveProperty('codecTypes'); - expectTypeOf().toHaveProperty('operationTypes'); + expectTypeOf().toHaveProperty('queryOperationTypes'); }); test('validateContract output is assignable to visualization shape', () => { diff --git a/packages/1-framework/1-core/framework-components/src/control/control-stack.ts b/packages/1-framework/1-core/framework-components/src/control/control-stack.ts index 62a8fa36d6..a0aaa298bd 100644 --- a/packages/1-framework/1-core/framework-components/src/control/control-stack.ts +++ b/packages/1-framework/1-core/framework-components/src/control/control-stack.ts @@ -37,7 +37,6 @@ export interface ControlStack< readonly extensionPacks: readonly ControlExtensionDescriptor[]; readonly codecTypeImports: ReadonlyArray; - readonly operationTypeImports: ReadonlyArray; readonly queryOperationTypeImports: ReadonlyArray; readonly extensionIds: ReadonlyArray; readonly codecLookup: CodecLookup; @@ -101,21 +100,6 @@ export function extractCodecTypeImports( return imports; } -export function extractOperationTypeImports( - descriptors: ReadonlyArray>, -): ReadonlyArray { - const imports: TypesImportSpec[] = []; - - for (const descriptor of descriptors) { - const operationTypes = descriptor.types?.operationTypes; - if (operationTypes?.import) { - imports.push(operationTypes.import); - } - } - - return imports; -} - export function extractQueryOperationTypeImports( descriptors: ReadonlyArray>, ): ReadonlyArray { @@ -382,7 +366,6 @@ export function createControlStack[], codecTypeImports: extractCodecTypeImports(allDescriptors), - operationTypeImports: extractOperationTypeImports(allDescriptors), queryOperationTypeImports: extractQueryOperationTypeImports(allDescriptors), extensionIds: extractComponentIds(family, target, adapter, extensionPacks), codecLookup, diff --git a/packages/1-framework/1-core/framework-components/src/control/emission-types.ts b/packages/1-framework/1-core/framework-components/src/control/emission-types.ts index 0dce88b2c2..a7c3f573a0 100644 --- a/packages/1-framework/1-core/framework-components/src/control/emission-types.ts +++ b/packages/1-framework/1-core/framework-components/src/control/emission-types.ts @@ -7,7 +7,6 @@ export interface GenerateContractTypesOptions { export interface ValidationContext { readonly codecTypeImports?: ReadonlyArray; - readonly operationTypeImports?: ReadonlyArray; readonly extensionIds?: ReadonlyArray; } diff --git a/packages/1-framework/1-core/framework-components/src/exports/control.ts b/packages/1-framework/1-core/framework-components/src/exports/control.ts index a12e9dcaf3..36092b1ea2 100644 --- a/packages/1-framework/1-core/framework-components/src/exports/control.ts +++ b/packages/1-framework/1-core/framework-components/src/exports/control.ts @@ -88,7 +88,6 @@ export { extractCodecLookup, extractCodecTypeImports, extractComponentIds, - extractOperationTypeImports, extractQueryOperationTypeImports, } from '../control/control-stack'; export type { diff --git a/packages/1-framework/1-core/framework-components/src/shared/framework-components.ts b/packages/1-framework/1-core/framework-components/src/shared/framework-components.ts index 2be70985d5..3f99768ba8 100644 --- a/packages/1-framework/1-core/framework-components/src/shared/framework-components.ts +++ b/packages/1-framework/1-core/framework-components/src/shared/framework-components.ts @@ -48,7 +48,6 @@ export interface ComponentMetadata { */ readonly codecInstances?: ReadonlyArray; }; - readonly operationTypes?: { readonly import: TypesImportSpec }; readonly queryOperationTypes?: { readonly import: TypesImportSpec }; readonly storage?: ReadonlyArray<{ readonly typeId: string; diff --git a/packages/1-framework/1-core/framework-components/test/control-stack.test.ts b/packages/1-framework/1-core/framework-components/test/control-stack.test.ts index 51eb28f7af..69e7b27523 100644 --- a/packages/1-framework/1-core/framework-components/test/control-stack.test.ts +++ b/packages/1-framework/1-core/framework-components/test/control-stack.test.ts @@ -9,7 +9,6 @@ import { extractCodecLookup, extractCodecTypeImports, extractComponentIds, - extractOperationTypeImports, extractQueryOperationTypeImports, validateScalarTypeCodecIds, } from '../src/control/control-stack'; @@ -78,26 +77,6 @@ describe('extractCodecTypeImports', () => { }); }); -describe('extractOperationTypeImports', () => { - it('returns empty array for descriptors without operation types', () => { - const result = extractOperationTypeImports([createDescriptor()]); - expect(result).toEqual([]); - }); - - it('extracts operation type import', () => { - const result = extractOperationTypeImports([ - createDescriptor({ - types: { - operationTypes: { - import: { package: '@test/ops', named: 'Ops', alias: 'O' }, - }, - }, - }), - ]); - expect(result).toEqual([{ package: '@test/ops', named: 'Ops', alias: 'O' }]); - }); -}); - describe('extractQueryOperationTypeImports', () => { it('returns empty array for descriptors without query operation types', () => { const result = extractQueryOperationTypeImports([createDescriptor()]); @@ -371,9 +350,6 @@ describe('createControlStack', () => { codecTypes: { typeImports: [{ package: '@test/param', named: 'P', alias: 'TP' }], }, - operationTypes: { - import: { package: '@test/ops', named: 'O', alias: 'TO' }, - }, queryOperationTypes: { import: { package: '@test/qops', named: 'Q', alias: 'TQ' }, }, @@ -392,7 +368,6 @@ describe('createControlStack', () => { ); expect(state.codecTypeImports).toHaveLength(2); - expect(state.operationTypeImports).toHaveLength(1); expect(state.queryOperationTypeImports).toHaveLength(1); expect(state.extensionIds).toEqual(['sql', 'target', 'adapter']); expect(Object.keys(state.authoringContributions.type)).toEqual(['myType']); @@ -435,7 +410,6 @@ describe('createControlStack', () => { expect(state.codecTypeImports).toHaveLength(1); expect(state.extensionIds).toEqual(['mongo']); - expect(state.operationTypeImports).toEqual([]); }); it('returns empty state when descriptors have no types', () => { @@ -446,7 +420,6 @@ describe('createControlStack', () => { }), ); expect(state.codecTypeImports).toEqual([]); - expect(state.operationTypeImports).toEqual([]); expect(state.queryOperationTypeImports).toEqual([]); expect(state.extensionIds).toEqual(['fam', 'tgt']); expect(state.authoringContributions).toEqual({ field: {}, type: {} }); diff --git a/packages/1-framework/1-core/operations/README.md b/packages/1-framework/1-core/operations/README.md index 6f331cccdb..47f07e8fe5 100644 --- a/packages/1-framework/1-core/operations/README.md +++ b/packages/1-framework/1-core/operations/README.md @@ -9,10 +9,11 @@ This package provides a generic, target-neutral operation registry. It's part of ## Responsibilities - **Operation Registry**: Generic operation registry interface and implementation - - `OperationRegistry`: Generic interface for registering and iterating operations, parameterized by entry type + - `OperationRegistry`: Generic interface for registering and iterating operations, parameterized by entry type. `register(name, descriptor)` keys each entry by an explicit method name supplied at the call site. - `createOperationRegistry()`: Factory function to create operation registries - - `OperationEntry`: Base entry type with `args` and `returns` - - `OperationDescriptor`: Entry plus a `method` name, used for registration + - `OperationEntry`: Base entry type with `self` and `impl` + - `OperationDescriptor`: Alias for the entry shape used at registration sites + - `OperationDescriptors`: `Readonly>>` — the natural shape contributors return, where the record key IS the method name - `ParamSpec`: Describes an operation parameter (`codecId`, `nullable`), used for both arguments and return values ## Dependencies @@ -59,19 +60,18 @@ import { createOperationRegistry, type OperationDescriptor } from '@prisma-next/ const registry = createOperationRegistry(); const descriptor: OperationDescriptor = { - method: 'cosineDistance', - args: [{ codecId: 'pg/vector@1', nullable: false }], - returns: { codecId: 'pg/float8@1', nullable: false }, + self: { codecId: 'pg/vector@1' }, + impl: () => ({ returnType: { codecId: 'pg/float8@1', nullable: false } }), }; -registry.register(descriptor); +registry.register('cosineDistance', descriptor); const entries = registry.entries(); // Record ``` ### Using a Custom Entry Type ```typescript -import { createOperationRegistry, type OperationEntry, type OperationDescriptor } from '@prisma-next/operations'; +import { createOperationRegistry, type OperationEntry } from '@prisma-next/operations'; interface MyEntry extends OperationEntry { readonly extra: string; @@ -79,10 +79,9 @@ interface MyEntry extends OperationEntry { const registry = createOperationRegistry(); -registry.register({ - method: 'myMethod', - args: [], - returns: { codecId: 'pg/int4@1', nullable: false }, +registry.register('myMethod', { + self: { codecId: 'pg/int4@1' }, + impl: () => undefined as never, extra: 'custom data', }); ``` diff --git a/packages/1-framework/1-core/operations/src/index.ts b/packages/1-framework/1-core/operations/src/index.ts index fa4e23764b..d3f9eb269a 100644 --- a/packages/1-framework/1-core/operations/src/index.ts +++ b/packages/1-framework/1-core/operations/src/index.ts @@ -18,12 +18,14 @@ export interface OperationEntry { readonly impl: (...args: never[]) => unknown; } -export type OperationDescriptor = T & { - readonly method: string; -}; +export type OperationDescriptor = T; + +export type OperationDescriptors = Readonly< + Record> +>; export interface OperationRegistry { - register(descriptor: OperationDescriptor): void; + register(name: string, descriptor: OperationDescriptor): void; entries(): Readonly>; } @@ -33,24 +35,21 @@ export function createOperationRegistry< const operations: Record = Object.create(null); return { - register(descriptor: OperationDescriptor) { - if (descriptor.method in operations) { - throw new Error(`Operation "${descriptor.method}" is already registered`); + register(name: string, descriptor: OperationDescriptor) { + if (name in operations) { + throw new Error(`Operation "${name}" is already registered`); } if (descriptor.self) { const hasCodecId = descriptor.self.codecId !== undefined; const hasTraits = descriptor.self.traits !== undefined && descriptor.self.traits.length > 0; if (!hasCodecId && !hasTraits) { - throw new Error(`Operation "${descriptor.method}" self has neither codecId nor traits`); + throw new Error(`Operation "${name}" self has neither codecId nor traits`); } if (hasCodecId && hasTraits) { - throw new Error(`Operation "${descriptor.method}" self has both codecId and traits`); + throw new Error(`Operation "${name}" self has both codecId and traits`); } } - const { method: _method, ...entry } = descriptor; - // OperationDescriptor = T & { method }, so stripping method yields T. - // TypeScript can't prove Omit = T for generic T. - operations[descriptor.method] = entry as unknown as T; + operations[name] = descriptor; }, entries() { return Object.freeze({ ...operations }); diff --git a/packages/1-framework/1-core/operations/test/operations-registry.test.ts b/packages/1-framework/1-core/operations/test/operations-registry.test.ts index 4782e46309..c3ad0bcab6 100644 --- a/packages/1-framework/1-core/operations/test/operations-registry.test.ts +++ b/packages/1-framework/1-core/operations/test/operations-registry.test.ts @@ -8,11 +8,7 @@ import { describe('OperationRegistry', () => { const noopImpl = () => undefined; - const descriptor = ( - method: string, - overrides?: Partial, - ): OperationDescriptor => ({ - method, + const descriptor = (overrides?: Partial): OperationDescriptor => ({ self: { codecId: 'pg/vector@1' }, impl: noopImpl, ...overrides, @@ -25,7 +21,7 @@ describe('OperationRegistry', () => { it('registers and retrieves an operation', () => { const registry = createOperationRegistry(); - registry.register(descriptor('cosineDistance')); + registry.register('cosineDistance', descriptor()); const entries = registry.entries(); expect(entries['cosineDistance']).toEqual({ @@ -36,8 +32,8 @@ describe('OperationRegistry', () => { it('registers multiple operations', () => { const registry = createOperationRegistry(); - registry.register(descriptor('cosineDistance')); - registry.register(descriptor('l2Distance')); + registry.register('cosineDistance', descriptor()); + registry.register('l2Distance', descriptor()); const entries = registry.entries(); expect(Object.keys(entries)).toEqual(['cosineDistance', 'l2Distance']); @@ -45,9 +41,9 @@ describe('OperationRegistry', () => { it('throws on duplicate method name', () => { const registry = createOperationRegistry(); - registry.register(descriptor('cosineDistance')); + registry.register('cosineDistance', descriptor()); - expect(() => registry.register(descriptor('cosineDistance'))).toThrow( + expect(() => registry.register('cosineDistance', descriptor())).toThrow( 'Operation "cosineDistance" is already registered', ); }); @@ -56,8 +52,7 @@ describe('OperationRegistry', () => { const registry = createOperationRegistry(); expect(() => - registry.register({ - method: 'bad', + registry.register('bad', { // @ts-expect-error — SelfSpec requires codecId or traits self: {}, impl: noopImpl, @@ -69,8 +64,7 @@ describe('OperationRegistry', () => { const registry = createOperationRegistry(); expect(() => - registry.register({ - method: 'bad', + registry.register('bad', { self: { traits: [] }, impl: noopImpl, }), @@ -81,8 +75,7 @@ describe('OperationRegistry', () => { const registry = createOperationRegistry(); expect(() => - registry.register({ - method: 'bad', + registry.register('bad', { // @ts-expect-error — SelfSpec disallows both codecId and traits self: { codecId: 'pg/text@1', traits: ['textual'] }, impl: noopImpl, @@ -95,7 +88,8 @@ describe('OperationRegistry', () => { expect(() => registry.register( - descriptor('fine', { + 'fine', + descriptor({ self: { traits: ['textual'] }, }), ), @@ -106,24 +100,15 @@ describe('OperationRegistry', () => { const registry = createOperationRegistry(); expect(() => - registry.register({ - method: 'builtin', + registry.register('builtin', { impl: noopImpl, }), ).not.toThrow(); }); - it('strips method from stored entry', () => { - const registry = createOperationRegistry(); - registry.register(descriptor('cosineDistance')); - - const entry = registry.entries()['cosineDistance']; - expect(entry).not.toHaveProperty('method'); - }); - it('returns frozen entries', () => { const registry = createOperationRegistry(); - registry.register(descriptor('cosineDistance')); + registry.register('cosineDistance', descriptor()); const entries = registry.entries(); expect(Object.isFrozen(entries)).toBe(true); @@ -135,8 +120,7 @@ describe('OperationRegistry', () => { } const registry = createOperationRegistry(); - registry.register({ - method: 'custom', + registry.register('custom', { self: { codecId: 'core/int4' }, impl: noopImpl, extra: 'metadata', diff --git a/packages/1-framework/3-tooling/cli/README.md b/packages/1-framework/3-tooling/cli/README.md index acc1120014..4fef2376a3 100644 --- a/packages/1-framework/3-tooling/cli/README.md +++ b/packages/1-framework/3-tooling/cli/README.md @@ -1245,7 +1245,7 @@ See `.cursor/rules/config-validation-and-normalization.mdc` for detailed pattern - **`capabilities`**: Feature flags the component contributes (e.g., adapter/runtime lowering requirements). Typically namespaced by target (e.g., `{ postgres: { returning: true } }`) so contracts can be validated against the active target. - **`types`**: Type import specs and type IDs contributed by the component. Common examples: - `types.codecTypes.import`: Where to import codec type mappings for `contract.d.ts`. - - `types.operationTypes.import`: Where to import operation type mappings for `contract.d.ts` (extensions). + - `types.queryOperationTypes.import`: Where to import flat query-builder operation type signatures for `contract.d.ts` (adapters/extensions). - `types.storage`: Storage type bindings (`typeId`, `nativeType`, etc.) used in authoring/emission. - **`operations`**: Operation signatures the component contributes (extensions), used for type generation and (optionally) validation/lowering. - **Component-specific metadata**: @@ -1268,11 +1268,11 @@ const exampleExtension: SqlControlExtensionDescriptor<'postgres'> = { targetId: 'postgres', capabilities: { postgres: { 'example/feature': true } }, types: { - operationTypes: { + queryOperationTypes: { import: { package: '@prisma-next/extension-example/operation-types', - named: 'OperationTypes', - alias: 'ExampleOperationTypes', + named: 'QueryOperationTypes', + alias: 'ExampleQueryOperationTypes', }, }, }, diff --git a/packages/1-framework/3-tooling/emitter/README.md b/packages/1-framework/3-tooling/emitter/README.md index 641f1cbe1d..bec8796f47 100644 --- a/packages/1-framework/3-tooling/emitter/README.md +++ b/packages/1-framework/3-tooling/emitter/README.md @@ -25,7 +25,7 @@ Provide a deterministic, verifiable representation of the application's data con - **Validate**: Core structure validation (family-specific validation is the caller's responsibility) - **Canonicalize**: Compute `storageHash` (schema meaning), `executionHash` (execution defaults), and `profileHash` (capabilities/pins) from canonical JSON - **Emit**: Generate `contract.json` and `contract.d.ts` with family-specific type generation -- **Descriptor-Agnostic**: The emitter is completely agnostic to how descriptors are produced. It receives pre-assembled `OperationRegistry`, `codecTypeImports`, `operationTypeImports`, and `extensionIds` from the CLI or family helpers—no pack manifest parsing happens inside the emitter. +- **Descriptor-Agnostic**: The emitter is completely agnostic to how descriptors are produced. It receives pre-assembled `OperationRegistry`, `codecTypeImports`, and `extensionIds` from the CLI or family helpers—no pack manifest parsing happens inside the emitter. **Note**: The emitter does NOT normalize contracts. Normalization must happen in the contract builder when the contract is created. The emitter assumes contracts are already normalized (all required fields present, including `schemaVersion`, `models`, `relations`, `storage`, `extensions`, `capabilities`, `meta`, and `sources`). All fields can be empty objects/arrays, but they must be present. @@ -162,7 +162,6 @@ const result = await emit(contract, { outputDir: './dist', operationRegistry: createOperationRegistry(), // Pre-assembled from packs codecTypeImports: [], // Extracted from packs (codec types) - operationTypeImports: [], // Extracted from packs (operation types) extensionIds: ['postgres', 'pg'], // Extracted from packs }, sqlEmission); diff --git a/packages/1-framework/3-tooling/emitter/src/emit-types.ts b/packages/1-framework/3-tooling/emitter/src/emit-types.ts index 39411d12dd..51cbcc0a8e 100644 --- a/packages/1-framework/3-tooling/emitter/src/emit-types.ts +++ b/packages/1-framework/3-tooling/emitter/src/emit-types.ts @@ -8,7 +8,6 @@ import type { TypesImportSpec } from '@prisma-next/framework-components/emission */ export interface EmitStackInput { readonly codecTypeImports?: ReadonlyArray; - readonly operationTypeImports?: ReadonlyArray; readonly queryOperationTypeImports?: ReadonlyArray; readonly extensionIds?: ReadonlyArray; readonly codecLookup?: CodecLookup; diff --git a/packages/1-framework/3-tooling/emitter/src/emit.ts b/packages/1-framework/3-tooling/emitter/src/emit.ts index 48406feee9..3d65c95c96 100644 --- a/packages/1-framework/3-tooling/emitter/src/emit.ts +++ b/packages/1-framework/3-tooling/emitter/src/emit.ts @@ -19,7 +19,7 @@ export async function emit( getEmittedArtifactPaths(options.outputJsonPath); } - const { codecTypeImports, operationTypeImports, queryOperationTypeImports } = stack; + const { codecTypeImports, queryOperationTypeImports } = stack; const { storageHash } = contract.storage; const executionHash = contract.execution?.executionHash; @@ -52,7 +52,6 @@ export async function emit( contract, targetFamily, codecTypeImports ?? [], - operationTypeImports ?? [], contractTypeHashes, generateOptions, stack.codecLookup, diff --git a/packages/1-framework/3-tooling/emitter/src/generate-contract-dts.ts b/packages/1-framework/3-tooling/emitter/src/generate-contract-dts.ts index debd817d36..f5e89c749c 100644 --- a/packages/1-framework/3-tooling/emitter/src/generate-contract-dts.ts +++ b/packages/1-framework/3-tooling/emitter/src/generate-contract-dts.ts @@ -23,7 +23,6 @@ export function generateContractDts( contract: Contract, emitter: EmissionSpi, codecTypeImports: ReadonlyArray, - operationTypeImports: ReadonlyArray, hashes: { readonly storageHash: string; readonly executionHash?: string; @@ -32,7 +31,7 @@ export function generateContractDts( options?: GenerateContractTypesOptions, codecLookup?: CodecLookup, ): string { - const allImports: TypesImportSpec[] = [...codecTypeImports, ...operationTypeImports]; + const allImports: TypesImportSpec[] = [...codecTypeImports]; if (options?.queryOperationTypeImports) { allImports.push(...options.queryOperationTypeImports); } @@ -44,7 +43,6 @@ export function generateContractDts( const hashAliases = generateHashTypeAliases(hashes); const codecTypes = generateCodecTypeIntersection(codecTypeImports, 'CodecTypes'); - const operationTypes = generateCodecTypeIntersection(operationTypeImports, 'OperationTypes'); const familyTypeAliases = emitter.getFamilyTypeAliases(options); @@ -100,7 +98,6 @@ import type { ${hashAliases} export type CodecTypes = ${codecTypes}; -export type OperationTypes = ${operationTypes}; ${familyTypeAliases} ${valueObjectTypeAliases} export type FieldOutputTypes = ${fieldTypesMaps.output}; diff --git a/packages/1-framework/3-tooling/emitter/test/emitter.integration.test.ts b/packages/1-framework/3-tooling/emitter/test/emitter.integration.test.ts index fd67e0e47b..acf704f113 100644 --- a/packages/1-framework/3-tooling/emitter/test/emitter.integration.test.ts +++ b/packages/1-framework/3-tooling/emitter/test/emitter.integration.test.ts @@ -52,11 +52,9 @@ describe('emitter integration', () => { }); const codecTypeImports: TypesImportSpec[] = []; - const operationTypeImports: TypesImportSpec[] = []; const extensionIds = ['postgres', 'pg']; const options: EmitStackInput = { codecTypeImports, - operationTypeImports, extensionIds, }; @@ -125,11 +123,9 @@ describe('emitter integration', () => { }); const codecTypeImports: TypesImportSpec[] = []; - const operationTypeImports: TypesImportSpec[] = []; const extensionIds = ['postgres', 'pg']; const options: EmitStackInput = { codecTypeImports, - operationTypeImports, extensionIds, }; @@ -186,11 +182,9 @@ describe('emitter integration', () => { }); const codecTypeImports: TypesImportSpec[] = []; - const operationTypeImports: TypesImportSpec[] = []; const extensionIds = ['postgres', 'pg']; const options: EmitStackInput = { codecTypeImports, - operationTypeImports, extensionIds, }; diff --git a/packages/1-framework/3-tooling/emitter/test/emitter.roundtrip.test.ts b/packages/1-framework/3-tooling/emitter/test/emitter.roundtrip.test.ts index 30ee6fdad1..e433b21dda 100644 --- a/packages/1-framework/3-tooling/emitter/test/emitter.roundtrip.test.ts +++ b/packages/1-framework/3-tooling/emitter/test/emitter.roundtrip.test.ts @@ -33,11 +33,9 @@ describe('emitter round-trip', () => { }); const codecTypeImports: TypesImportSpec[] = []; - const operationTypeImports: TypesImportSpec[] = []; const extensionIds = ['postgres', 'pg']; const options: EmitStackInput = { codecTypeImports, - operationTypeImports, extensionIds, }; @@ -140,11 +138,9 @@ describe('emitter round-trip', () => { }); const codecTypeImports: TypesImportSpec[] = []; - const operationTypeImports: TypesImportSpec[] = []; const extensionIds = ['postgres']; const options: EmitStackInput = { codecTypeImports, - operationTypeImports, extensionIds, }; @@ -195,11 +191,9 @@ describe('emitter round-trip', () => { }); const codecTypeImports: TypesImportSpec[] = []; - const operationTypeImports: TypesImportSpec[] = []; const extensionIds = ['postgres', 'pg']; const options: EmitStackInput = { codecTypeImports, - operationTypeImports, extensionIds, }; @@ -264,11 +258,9 @@ describe('emitter round-trip', () => { }); const codecTypeImports: TypesImportSpec[] = []; - const operationTypeImports: TypesImportSpec[] = []; const extensionIds = ['postgres', 'pg']; const options: EmitStackInput = { codecTypeImports, - operationTypeImports, extensionIds, }; diff --git a/packages/1-framework/3-tooling/emitter/test/emitter.test.ts b/packages/1-framework/3-tooling/emitter/test/emitter.test.ts index 437a6b453d..9cdc5ad701 100644 --- a/packages/1-framework/3-tooling/emitter/test/emitter.test.ts +++ b/packages/1-framework/3-tooling/emitter/test/emitter.test.ts @@ -28,7 +28,6 @@ describe('emitter', () => { const ir = createTestContract(); const options: EmitStackInput = { codecTypeImports: [], - operationTypeImports: [], }; await expect( @@ -83,11 +82,9 @@ describe('emitter', () => { }); const codecTypeImports: TypesImportSpec[] = []; - const operationTypeImports: TypesImportSpec[] = []; const extensionIds = ['postgres', 'pg']; const options: EmitStackInput = { codecTypeImports, - operationTypeImports, extensionIds, }; @@ -122,7 +119,6 @@ describe('emitter', () => { const options: EmitStackInput = { codecTypeImports: [], - operationTypeImports: [], extensionIds: [], }; @@ -150,7 +146,6 @@ describe('emitter', () => { const options: EmitStackInput = { codecTypeImports: [], - operationTypeImports: [], extensionIds: ['some-other-extension'], }; @@ -177,7 +172,6 @@ describe('emitter', () => { const options: EmitStackInput = { codecTypeImports: [], - operationTypeImports: [], extensionIds: [], }; @@ -204,7 +198,6 @@ describe('emitter', () => { const options: EmitStackInput = { codecTypeImports: [], - operationTypeImports: [], extensionIds: [], }; @@ -224,7 +217,6 @@ describe('emitter', () => { const options: EmitStackInput = { codecTypeImports: [], - operationTypeImports: [], extensionIds: [], }; @@ -246,7 +238,6 @@ describe('emitter', () => { const options: EmitStackInput = { codecTypeImports: [], - operationTypeImports: [], extensionIds: [], }; @@ -280,7 +271,6 @@ describe('emitter', () => { const options: EmitStackInput = { codecTypeImports: [], - operationTypeImports: [], extensionIds: [], }; @@ -301,7 +291,6 @@ describe('emitter', () => { const options: EmitStackInput = { codecTypeImports: [], - operationTypeImports: [], extensionIds: ['postgres'], }; @@ -310,7 +299,7 @@ describe('emitter', () => { expect(result.contractDts).toBeDefined(); }); - it('defaults codecTypeImports and operationTypeImports to empty arrays when omitted', async () => { + it('defaults codecTypeImports to empty array when omitted', async () => { const ir = createTestContract({ storage: { tables: {} }, }); @@ -321,7 +310,6 @@ describe('emitter', () => { const result = await emit(ir, options, mockSqlHook); expect(result.contractDts).toContain('export type CodecTypes'); - expect(result.contractDts).toContain('export type OperationTypes'); }); it('passes parameterizedTypeImports and queryOperationTypeImports to generateContractDts', async () => { @@ -335,7 +323,6 @@ describe('emitter', () => { const options: EmitStackInput = { codecTypeImports: [], - operationTypeImports: [], extensionIds: [], queryOperationTypeImports, }; @@ -389,7 +376,6 @@ describe('emitter', () => { const options: EmitStackInput = { codecTypeImports: [], - operationTypeImports: [], extensionIds: [], }; @@ -424,7 +410,6 @@ describe('emitter', () => { const options: EmitStackInput = { codecTypeImports: [], - operationTypeImports: [], extensionIds: [], }; @@ -455,7 +440,6 @@ describe('emitter', () => { const options: EmitStackInput = { codecTypeImports: [], - operationTypeImports: [], extensionIds: [], }; @@ -474,7 +458,6 @@ describe('emitter', () => { const options: EmitStackInput = { codecTypeImports: [], - operationTypeImports: [], extensionIds: [], }; diff --git a/packages/1-framework/3-tooling/emitter/test/mock-spi.ts b/packages/1-framework/3-tooling/emitter/test/mock-spi.ts index 52121f07f9..0d4f550fac 100644 --- a/packages/1-framework/3-tooling/emitter/test/mock-spi.ts +++ b/packages/1-framework/3-tooling/emitter/test/mock-spi.ts @@ -10,7 +10,7 @@ export function createMockSpi(overrides: Partial = {}): EmissionSpi "import type { ContractWithTypeMaps, TypeMaps as TypeMapsType } from '@prisma-next/sql-contract/types';", ], getFamilyTypeAliases: () => 'export type LaneCodecTypes = CodecTypes;', - getTypeMapsExpression: () => 'TypeMapsType', + getTypeMapsExpression: () => 'TypeMapsType', getContractWrapper: (base, tm) => `export type Contract = ContractWithTypeMaps<${base}, ${tm}>;`, ...overrides, diff --git a/packages/2-mongo-family/1-foundation/mongo-contract/src/contract-types.ts b/packages/2-mongo-family/1-foundation/mongo-contract/src/contract-types.ts index 8a54a4db9d..79a4cda058 100644 --- a/packages/2-mongo-family/1-foundation/mongo-contract/src/contract-types.ts +++ b/packages/2-mongo-family/1-foundation/mongo-contract/src/contract-types.ts @@ -166,7 +166,6 @@ export type MongoContract< export type MongoTypeMaps< TCodecTypes extends Record = Record, - TOperationTypes extends Record = Record, TFieldOutputTypes extends Record> = Record< string, Record @@ -177,7 +176,6 @@ export type MongoTypeMaps< >, > = { readonly codecTypes: TCodecTypes; - readonly operationTypes: TOperationTypes; readonly fieldOutputTypes: TFieldOutputTypes; readonly fieldInputTypes: TFieldInputTypes; }; diff --git a/packages/2-mongo-family/1-foundation/mongo-contract/test/contract-types.test-d.ts b/packages/2-mongo-family/1-foundation/mongo-contract/test/contract-types.test-d.ts index 8055e50aeb..c9978834f0 100644 --- a/packages/2-mongo-family/1-foundation/mongo-contract/test/contract-types.test-d.ts +++ b/packages/2-mongo-family/1-foundation/mongo-contract/test/contract-types.test-d.ts @@ -113,7 +113,7 @@ test('InferModelRow still handles scalar fields alongside value objects', () => }); test('MongoTypeMaps accepts a fieldOutputTypes parameter', () => { - type TM = MongoTypeMaps, TestFieldOutputTypes>; + type TM = MongoTypeMaps; expectTypeOf().toEqualTypeOf(); }); @@ -123,7 +123,7 @@ test('MongoTypeMaps defaults fieldOutputTypes to Record { - type TM = MongoTypeMaps, TestFieldOutputTypes>; + type TM = MongoTypeMaps; type C = MongoContractWithTypeMaps< { readonly target: 'mongo'; @@ -145,13 +145,8 @@ test('ExtractMongoFieldOutputTypes extracts fieldOutputTypes from contract', () expectTypeOf>().toEqualTypeOf(); }); -test('MongoTypeMaps accepts a 4th fieldInputTypes parameter', () => { - type TM = MongoTypeMaps< - TestCodecTypes, - Record, - TestFieldOutputTypes, - TestFieldInputTypes - >; +test('MongoTypeMaps accepts a 3rd fieldInputTypes parameter', () => { + type TM = MongoTypeMaps; expectTypeOf().toEqualTypeOf(); }); @@ -161,12 +156,7 @@ test('MongoTypeMaps defaults fieldInputTypes to Record { - type TM = MongoTypeMaps< - TestCodecTypes, - Record, - TestFieldOutputTypes, - TestFieldInputTypes - >; + type TM = MongoTypeMaps; type C = MongoContractWithTypeMaps< { readonly target: 'mongo'; @@ -188,8 +178,8 @@ test('ExtractMongoFieldInputTypes extracts fieldInputTypes from contract', () => expectTypeOf>().toEqualTypeOf(); }); -test('backward compat: MongoTypeMaps with 2 params still compiles', () => { - type TM = MongoTypeMaps>; +test('MongoTypeMaps with single param compiles', () => { + type TM = MongoTypeMaps; expectTypeOf().toEqualTypeOf(); expectTypeOf().toEqualTypeOf>>(); expectTypeOf().toEqualTypeOf>>(); diff --git a/packages/2-mongo-family/3-tooling/emitter/src/index.ts b/packages/2-mongo-family/3-tooling/emitter/src/index.ts index 65a2ba6d8d..2f9cacd573 100644 --- a/packages/2-mongo-family/3-tooling/emitter/src/index.ts +++ b/packages/2-mongo-family/3-tooling/emitter/src/index.ts @@ -194,7 +194,7 @@ export const mongoEmission = { }, getTypeMapsExpression(): string { - return 'MongoTypeMaps'; + return 'MongoTypeMaps'; }, getContractWrapper(contractBaseName: string, typeMapsName: string): string { diff --git a/packages/2-mongo-family/3-tooling/emitter/test/emitter-hook.e2e.test.ts b/packages/2-mongo-family/3-tooling/emitter/test/emitter-hook.e2e.test.ts index fe96521060..7d99e8286b 100644 --- a/packages/2-mongo-family/3-tooling/emitter/test/emitter-hook.e2e.test.ts +++ b/packages/2-mongo-family/3-tooling/emitter/test/emitter-hook.e2e.test.ts @@ -21,19 +21,13 @@ describe('Mongo emitter hook end-to-end (blog fixture)', () => { }); it('generates complete contract.d.ts from blog contract', () => { - const types = generateContractDts( - blogContract, - mongoEmission, - mongoCodecImports, - [], - testHashes, - ); + const types = generateContractDts(blogContract, mongoEmission, mongoCodecImports, testHashes); expect(types).toContain( 'export type Contract = MongoContractWithTypeMaps', ); expect(types).toContain( - 'export type TypeMaps = MongoTypeMaps', + 'export type TypeMaps = MongoTypeMaps', ); expect(types).toContain('export type CodecTypes = MongoCodecTypes'); @@ -72,7 +66,7 @@ describe('Mongo emitter hook end-to-end (blog fixture)', () => { }); it('generates storage section with collections', () => { - const types = generateContractDts(blogContract, mongoEmission, [], [], testHashes); + const types = generateContractDts(blogContract, mongoEmission, [], testHashes); expect(types).toContain('readonly collections:'); expect(types).toContain('readonly users: Record'); @@ -80,7 +74,7 @@ describe('Mongo emitter hook end-to-end (blog fixture)', () => { }); it('generates Comment model with owner and empty storage', () => { - const types = generateContractDts(blogContract, mongoEmission, [], [], testHashes); + const types = generateContractDts(blogContract, mongoEmission, [], testHashes); expect(types).toContain( "readonly text: { readonly nullable: false; readonly type: { readonly kind: 'scalar'; readonly codecId: 'mongo/string@1' } }", diff --git a/packages/2-mongo-family/3-tooling/emitter/test/emitter-hook.generation.test.ts b/packages/2-mongo-family/3-tooling/emitter/test/emitter-hook.generation.test.ts index 6c53a6ff3a..622e2d3f1e 100644 --- a/packages/2-mongo-family/3-tooling/emitter/test/emitter-hook.generation.test.ts +++ b/packages/2-mongo-family/3-tooling/emitter/test/emitter-hook.generation.test.ts @@ -9,25 +9,25 @@ const testHashes = { storageHash: 'test-storage-hash', profileHash: 'test-profil describe('mongoEmission.generateContractTypes', () => { it('generates Contract and TypeMaps exports', () => { const contract = createMongoContract(); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain( 'export type Contract = MongoContractWithTypeMaps', ); expect(types).toContain( - 'export type TypeMaps = MongoTypeMaps', + 'export type TypeMaps = MongoTypeMaps', ); }); it('generates hash type aliases', () => { const contract = createMongoContract(); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain("StorageHashBase<'test-storage-hash'>"); expect(types).toContain("ProfileHashBase<'test-profile-hash'>"); }); it('generates concrete execution hash when provided', () => { const contract = createMongoContract(); - const types = generateContractDts(contract, mongoEmission, [], [], { + const types = generateContractDts(contract, mongoEmission, [], { ...testHashes, executionHash: 'test-exec-hash', }); @@ -36,13 +36,13 @@ describe('mongoEmission.generateContractTypes', () => { it('generates generic execution hash when not provided', () => { const contract = createMongoContract(); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain('ExecutionHashBase'); }); it('includes framework imports', () => { const contract = createMongoContract(); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain("from '@prisma-next/mongo-contract'"); expect(types).toContain("from '@prisma-next/contract/types'"); expect(types).toContain('MongoContractWithTypeMaps'); @@ -61,7 +61,7 @@ describe('mongoEmission.generateContractTypes', () => { alias: 'MongoCodecTypes', }, ]; - const types = generateContractDts(contract, mongoEmission, codecImports, [], testHashes); + const types = generateContractDts(contract, mongoEmission, codecImports, testHashes); expect(types).toContain( "import type { CodecTypes as MongoCodecTypes } from '@prisma-next/adapter-mongo/codec-types'", ); @@ -70,13 +70,13 @@ describe('mongoEmission.generateContractTypes', () => { it('generates empty CodecTypes when no codec imports', () => { const contract = createMongoContract(); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain('export type CodecTypes = Record'); }); it('generates contract header fields', () => { const contract = createMongoContract(); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain("readonly target: 'mongo'"); expect(types).not.toContain('schemaVersion'); expect(types).toContain('readonly profileHash: ProfileHash'); @@ -86,7 +86,7 @@ describe('mongoEmission.generateContractTypes', () => { const contract = createMongoContract({ roots: { users: 'User', posts: 'Post' }, }); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain("readonly users: 'User'"); expect(types).toContain("readonly posts: 'Post'"); }); @@ -107,7 +107,7 @@ describe('mongoEmission.generateContractTypes', () => { }, storage: { collections: { users: {} } }, }); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain( "readonly _id: { readonly nullable: false; readonly type: { readonly kind: 'scalar'; readonly codecId: 'mongo/objectId@1' } }", ); @@ -152,7 +152,7 @@ describe('mongoEmission.generateContractTypes', () => { }, storage: { collections: { users: {}, posts: {} } }, }); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain("readonly to: 'Post'"); expect(types).toContain("readonly cardinality: '1:N'"); expect(types).toContain("readonly localFields: readonly ['_id']"); @@ -173,7 +173,7 @@ describe('mongoEmission.generateContractTypes', () => { }, storage: { collections: { users: {} } }, }); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain("readonly collection: 'users'"); }); @@ -201,7 +201,7 @@ describe('mongoEmission.generateContractTypes', () => { }, storage: { collections: { users: {} } }, }); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain('readonly Address: { readonly fields:'); expect(types).toContain("readonly owner: 'User'"); }); @@ -227,7 +227,7 @@ describe('mongoEmission.generateContractTypes', () => { }, storage: { collections: { posts: {} } }, }); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain("readonly owner: 'Post'"); }); @@ -263,7 +263,7 @@ describe('mongoEmission.generateContractTypes', () => { }, storage: { collections: { tasks: {} } }, }); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain("discriminator: { readonly field: 'type' }"); expect(types).toContain("readonly Bug: { readonly value: 'bug' }"); expect(types).toContain("readonly Feature: { readonly value: 'feature' }"); @@ -294,7 +294,7 @@ describe('mongoEmission.generateContractTypes', () => { }, storage: { collections: { users: {} } }, }); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain( "readonly relations: { readonly addresses: { readonly field: 'addresses' } }", ); @@ -306,7 +306,7 @@ describe('mongoEmission.generateContractTypes', () => { const contract = createMongoContract({ storage: { collections: { users: {}, posts: {} } }, }); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain('readonly collections:'); expect(types).toContain('readonly users: Record'); expect(types).toContain('readonly posts: Record'); @@ -325,7 +325,7 @@ describe('mongoEmission.generateContractTypes', () => { }, }, }); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain('readonly users: { readonly indexes:'); expect(types).toContain('readonly fields: { readonly email: 1 }'); expect(types).toContain('readonly options: { readonly unique: true }'); @@ -336,7 +336,7 @@ describe('mongoEmission.generateContractTypes', () => { it('generates empty collections', () => { const contract = createMongoContract({ storage: { collections: {} } }); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain('readonly collections: Record'); }); }); @@ -363,7 +363,7 @@ describe('mongoEmission.generateContractTypes', () => { }, storage: { collections: { users: {} } }, }); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain('export type AddressOutput ='); expect(types).toContain('export type AddressInput ='); expect(types).not.toMatch(/export type Address =/); @@ -379,7 +379,7 @@ describe('mongoEmission.generateContractTypes', () => { }, }, }); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain('readonly valueObjects:'); expect(types).toContain('readonly Address: { readonly fields:'); }); @@ -408,7 +408,7 @@ describe('mongoEmission.generateContractTypes', () => { }, storage: { collections: { users: {} } }, }); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain( "readonly homeAddress: { readonly nullable: true; readonly type: { readonly kind: 'valueObject'; readonly name: 'Address' } }", ); @@ -439,7 +439,7 @@ describe('mongoEmission.generateContractTypes', () => { }, storage: { collections: { users: {} } }, }); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain( "readonly previousAddresses: { readonly nullable: false; readonly type: { readonly kind: 'valueObject'; readonly name: 'Address' }; readonly many: true }", ); @@ -460,7 +460,7 @@ describe('mongoEmission.generateContractTypes', () => { }, }, }); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain('export type NavItemOutput ='); expect(types).toContain('export type NavItemInput ='); expect(types).toContain('readonly children: ReadonlyArray'); @@ -469,7 +469,7 @@ describe('mongoEmission.generateContractTypes', () => { it('omits valueObjects when none exist', () => { const contract = createMongoContract(); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).not.toContain('valueObjects'); }); @@ -483,7 +483,7 @@ describe('mongoEmission.generateContractTypes', () => { }, }, }); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain("readonly zip: CodecTypes['mongo/string@1']['output'] | null"); }); @@ -501,7 +501,7 @@ describe('mongoEmission.generateContractTypes', () => { }, storage: { collections: { users: {} } }, }); - const types = generateContractDts(contract, mongoEmission, [], [], testHashes); + const types = generateContractDts(contract, mongoEmission, [], testHashes); expect(types).toContain('export type FieldOutputTypes ='); expect(types).toContain('export type FieldInputTypes ='); expect(types).toContain("CodecTypes['mongo/objectId@1']['input']"); diff --git a/packages/2-mongo-family/5-query-builders/orm/test/value-object-inputs.test-d.ts b/packages/2-mongo-family/5-query-builders/orm/test/value-object-inputs.test-d.ts index 2f920958d8..abd716da7e 100644 --- a/packages/2-mongo-family/5-query-builders/orm/test/value-object-inputs.test-d.ts +++ b/packages/2-mongo-family/5-query-builders/orm/test/value-object-inputs.test-d.ts @@ -145,7 +145,6 @@ type FieldInputTypesForUser = { type TypeMapsWithFieldTypes = MongoTypeMaps< TestCodecTypes, - Record, FieldOutputTypesForUser, FieldInputTypesForUser >; @@ -259,12 +258,7 @@ type ExtFieldInputTypes = { readonly Comment: { readonly _id: string; readonly text: string }; }; -type ExtTypeMaps = MongoTypeMaps< - ExtCodecTypes, - Record, - ExtFieldOutputTypes, - ExtFieldInputTypes ->; +type ExtTypeMaps = MongoTypeMaps; type ExtContract = MongoContractWithTypeMaps< { diff --git a/packages/2-sql/1-core/contract/src/exports/types.ts b/packages/2-sql/1-core/contract/src/exports/types.ts index 578ddf1e48..d4d918ef69 100644 --- a/packages/2-sql/1-core/contract/src/exports/types.ts +++ b/packages/2-sql/1-core/contract/src/exports/types.ts @@ -12,7 +12,6 @@ export type { ForeignKeyOptions, ForeignKeyReferences, Index, - OperationTypesOf, PrimaryKey, QueryOperationReturn, QueryOperationSelfSpec, @@ -21,7 +20,6 @@ export type { QueryOperationTypesOf, ReferentialAction, ResolveCodecTypes, - ResolveOperationTypes, SqlModelFieldStorage, SqlModelStorage, SqlQueryOperationTypes, diff --git a/packages/2-sql/1-core/contract/src/types.ts b/packages/2-sql/1-core/contract/src/types.ts index 27d80bcc6a..1bd21271da 100644 --- a/packages/2-sql/1-core/contract/src/types.ts +++ b/packages/2-sql/1-core/contract/src/types.ts @@ -139,13 +139,11 @@ export function applyFkDefaults( export type TypeMaps< TCodecTypes extends Record = Record, - TOperationTypes extends Record = Record, TQueryOperationTypes extends Record = Record, TFieldOutputTypes extends Record> = Record, TFieldInputTypes extends Record> = Record, > = { readonly codecTypes: TCodecTypes; - readonly operationTypes: TOperationTypes; readonly queryOperationTypes: TQueryOperationTypes; readonly fieldOutputTypes: TFieldOutputTypes; readonly fieldInputTypes: TFieldInputTypes; @@ -159,14 +157,6 @@ export type CodecTypesOf = [T] extends [never] : Record : Record; -export type OperationTypesOf = [T] extends [never] - ? Record - : T extends { readonly operationTypes: infer O } - ? O extends Record - ? O - : Record - : Record; - /** * Dispatch hint identifying the first-argument target of an operation. * @@ -244,5 +234,3 @@ export type ExtractFieldInputTypes = FieldInputTypesOf = [TTypeMaps] extends [never] ? ExtractCodecTypes : CodecTypesOf; - -export type ResolveOperationTypes<_TContract, TTypeMaps> = OperationTypesOf; diff --git a/packages/2-sql/1-core/contract/test/contract-typemaps-shape.test.ts b/packages/2-sql/1-core/contract/test/contract-typemaps-shape.test.ts index bf01c7651c..b81685a60b 100644 --- a/packages/2-sql/1-core/contract/test/contract-typemaps-shape.test.ts +++ b/packages/2-sql/1-core/contract/test/contract-typemaps-shape.test.ts @@ -1,40 +1,25 @@ import { describe, it } from 'vitest'; -import type { - CodecTypesOf, - FieldInputTypesOf, - FieldOutputTypesOf, - OperationTypesOf, - TypeMaps, -} from '../src/types'; +import type { CodecTypesOf, FieldInputTypesOf, FieldOutputTypesOf, TypeMaps } from '../src/types'; describe('Contract and TypeMaps shape', () => { describe('TypeMaps shape', () => { - it('TypeMaps has locked shape with codecTypes and operationTypes', () => { - type TM = TypeMaps<{ 'pg/text@1': { output: string } }, Record>; + it('TypeMaps has locked shape with codecTypes', () => { + type TM = TypeMaps<{ 'pg/text@1': { output: string } }>; type HasCodecTypes = TM extends { readonly codecTypes: unknown } ? true : false; - type HasOperationTypes = TM extends { readonly operationTypes: unknown } ? true : false; const _codec: HasCodecTypes = true; - const _op: HasOperationTypes = true; }); it('CodecTypesOf extracts codecTypes from TypeMaps', () => { - type TM = TypeMaps<{ foo: { output: number } }, Record>; + type TM = TypeMaps<{ foo: { output: number } }>; type CT = CodecTypesOf; const _ct: CT = { foo: { output: 0 } }; }); - it('OperationTypesOf extracts operationTypes from TypeMaps', () => { - type TM = TypeMaps, { bar: Record }>; - type OT = OperationTypesOf; - const _ot: OT = { bar: {} }; - }); - - it('TypeMaps accepts 5th TFieldInputTypes parameter', () => { + it('TypeMaps accepts 4th TFieldInputTypes parameter', () => { type TM = TypeMaps< Record, Record, Record, - Record, { User: { name: string } } >; type HasFieldInputTypes = TM extends { readonly fieldInputTypes: unknown } ? true : false; @@ -48,12 +33,7 @@ describe('Contract and TypeMaps shape', () => { }); it('FieldOutputTypesOf extracts fieldOutputTypes from TypeMaps', () => { - type TM = TypeMaps< - Record, - Record, - Record, - { User: { name: string } } - >; + type TM = TypeMaps, Record, { User: { name: string } }>; type FOT = FieldOutputTypesOf; const _fot: FOT = { User: { name: 'test' } }; }); @@ -63,17 +43,10 @@ describe('Contract and TypeMaps shape', () => { Record, Record, Record, - Record, { User: { name: string } } >; type FIT = FieldInputTypesOf; const _fit: FIT = { User: { name: 'test' } }; }); - - it('backward compat: 2-param TypeMaps compiles', () => { - type TM = TypeMaps<{ 'pg/text@1': { output: string } }, Record>; - type CT = CodecTypesOf; - const _ct: CT = { 'pg/text@1': { output: '' } }; - }); }); }); diff --git a/packages/2-sql/1-core/operations/README.md b/packages/2-sql/1-core/operations/README.md index a389b2831b..d5b2bbc69c 100644 --- a/packages/2-sql/1-core/operations/README.md +++ b/packages/2-sql/1-core/operations/README.md @@ -16,7 +16,8 @@ This package provides SQL-specific operation types that extend the generic `Oper - **SQL Operation Types**: SQL-specific operation entry and descriptor types - `SqlOperationEntry`: Extends `OperationEntry` with a `lowering` field (`SqlLoweringSpec`) - - `SqlOperationDescriptor`: Extends `OperationDescriptor` (entry plus `method` name) + - `SqlOperationDescriptor`: Alias for `SqlOperationEntry` used at registration sites + - `SqlOperationDescriptors`: `Readonly>` — the keyed-record shape adapter/extension `queryOperations()` factories return - `SqlLoweringSpec`: SQL-specific lowering specification (`targetFamily`, `strategy`, `template`) - `SqlOperationRegistry`: Typed registry alias (`OperationRegistry`) @@ -72,17 +73,11 @@ import { const registry = createSqlOperationRegistry(); const descriptor: SqlOperationDescriptor = { - method: 'cosineDistance', - args: [{ codecId: 'pg/vector@1', nullable: false }], - returns: { codecId: 'pg/float8@1', nullable: false }, - lowering: { - targetFamily: 'sql', - strategy: 'infix', - template: '{{self}} <=> {{arg0}}', - }, + self: { codecId: 'pg/vector@1' }, + impl: () => ({ returnType: { codecId: 'pg/float8@1', nullable: false } }), }; -registry.register(descriptor); +registry.register('cosineDistance', descriptor); const entries = registry.entries(); // Record ``` diff --git a/packages/2-sql/1-core/operations/src/index.ts b/packages/2-sql/1-core/operations/src/index.ts index 5e51963a8a..b4ae1280ee 100644 --- a/packages/2-sql/1-core/operations/src/index.ts +++ b/packages/2-sql/1-core/operations/src/index.ts @@ -1,4 +1,8 @@ -import type { OperationDescriptor, OperationRegistry } from '@prisma-next/operations'; +import type { + OperationDescriptor, + OperationDescriptors, + OperationRegistry, +} from '@prisma-next/operations'; import { createOperationRegistry } from '@prisma-next/operations'; import type { QueryOperationTypeEntry } from '@prisma-next/sql-contract/types'; @@ -19,6 +23,8 @@ export type SqlOperationEntry = QueryOperationTypeEntry; export type SqlOperationDescriptor = OperationDescriptor; +export type SqlOperationDescriptors = OperationDescriptors; + export type SqlOperationRegistry = OperationRegistry; export function createSqlOperationRegistry(): SqlOperationRegistry { diff --git a/packages/2-sql/1-core/operations/test/operations-registry.test.ts b/packages/2-sql/1-core/operations/test/operations-registry.test.ts index ac04e81227..c0521b77f8 100644 --- a/packages/2-sql/1-core/operations/test/operations-registry.test.ts +++ b/packages/2-sql/1-core/operations/test/operations-registry.test.ts @@ -4,11 +4,7 @@ import { createSqlOperationRegistry, type SqlOperationDescriptor } from '../src/ describe('SqlOperationRegistry', () => { const noopImpl = () => ({ returnType: { codecId: 'pg/bool@1', nullable: false } }); - const descriptor = ( - method: string, - overrides?: Partial, - ): SqlOperationDescriptor => ({ - method, + const descriptor = (overrides?: Partial): SqlOperationDescriptor => ({ self: { codecId: 'pg/vector@1' }, impl: noopImpl, ...overrides, @@ -16,7 +12,7 @@ describe('SqlOperationRegistry', () => { it('registers and retrieves an operation', () => { const registry = createSqlOperationRegistry(); - registry.register(descriptor('cosineDistance')); + registry.register('cosineDistance', descriptor()); const entry = registry.entries()['cosineDistance']; expect(entry).toEqual({ @@ -27,8 +23,8 @@ describe('SqlOperationRegistry', () => { it('registers multiple operations', () => { const registry = createSqlOperationRegistry(); - registry.register(descriptor('cosineDistance')); - registry.register(descriptor('l2Distance', { self: { traits: ['order'] } })); + registry.register('cosineDistance', descriptor()); + registry.register('l2Distance', descriptor({ self: { traits: ['order'] } })); const entries = registry.entries(); expect(Object.keys(entries)).toEqual(['cosineDistance', 'l2Distance']); @@ -36,9 +32,9 @@ describe('SqlOperationRegistry', () => { it('throws on duplicate method', () => { const registry = createSqlOperationRegistry(); - registry.register(descriptor('cosineDistance')); + registry.register('cosineDistance', descriptor()); - expect(() => registry.register(descriptor('cosineDistance'))).toThrow( + expect(() => registry.register('cosineDistance', descriptor())).toThrow( 'Operation "cosineDistance" is already registered', ); }); diff --git a/packages/2-sql/3-tooling/emitter/README.md b/packages/2-sql/3-tooling/emitter/README.md index fdb18fec93..baa805ccac 100644 --- a/packages/2-sql/3-tooling/emitter/README.md +++ b/packages/2-sql/3-tooling/emitter/README.md @@ -13,7 +13,7 @@ This package provides the SQL-specific emitter hook implementation for the Prism - `validateStructure()`: Validates SQL-specific logical consistency (foreign key references, model-to-table mappings, constraint consistency). **Note**: Structural properties (required fields, types) are validated by Arktype schema validation - this function focuses on logical validation that schema validators can't perform. - **Type Generation**: Generates TypeScript type definitions for SQL contracts - - `generateContractTypes()`: Generates `contract.d.ts` file content (receives separate `codecTypeImports` and `operationTypeImports` arrays) + - `generateContractTypes()`: Generates `contract.d.ts` file content (receives a `codecTypeImports` array) ## Dependencies diff --git a/packages/2-sql/3-tooling/emitter/src/index.ts b/packages/2-sql/3-tooling/emitter/src/index.ts index d0db6a81d1..23edfbc759 100644 --- a/packages/2-sql/3-tooling/emitter/src/index.ts +++ b/packages/2-sql/3-tooling/emitter/src/index.ts @@ -351,7 +351,7 @@ export const sqlEmission = { }, getTypeMapsExpression(): string { - return 'TypeMapsType'; + return 'TypeMapsType'; }, getContractWrapper(contractBaseName: string, typeMapsName: string): string { diff --git a/packages/2-sql/3-tooling/emitter/test/emitter-hook.generation.advanced.test.ts b/packages/2-sql/3-tooling/emitter/test/emitter-hook.generation.advanced.test.ts index 59921e2a52..ef1667c8d1 100644 --- a/packages/2-sql/3-tooling/emitter/test/emitter-hook.generation.advanced.test.ts +++ b/packages/2-sql/3-tooling/emitter/test/emitter-hook.generation.advanced.test.ts @@ -5,10 +5,7 @@ import type { ControlExtensionDescriptor, ControlTargetDescriptor, } from '@prisma-next/framework-components/control'; -import { - extractCodecTypeImports, - extractOperationTypeImports, -} from '@prisma-next/framework-components/control'; +import { extractCodecTypeImports } from '@prisma-next/framework-components/control'; import { describe, expect, it } from 'vitest'; import { sqlEmission } from '../src/index'; @@ -100,7 +97,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain('relations: {'); expect(types).toContain( "readonly posts: { readonly to: 'Post'; readonly cardinality: '1:N'; readonly on: { readonly localFields: readonly ['id']; readonly targetFields: readonly ['userId'] } }", @@ -125,7 +122,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).not.toContain('SqlMappings'); expect(types).toContain('export type TypeMaps'); expect(types).not.toContain("'__@prisma-next/sql-contract/codecTypes@__'"); @@ -170,14 +167,7 @@ describe('sql-target-family-hook', () => { }); const codecTypeImports = extractCodecTypeImports(descriptors); - const operationTypeImports = extractOperationTypeImports(descriptors); - const types = generateContractDts( - ir, - sqlEmission, - codecTypeImports, - operationTypeImports, - testHashes, - ); + const types = generateContractDts(ir, sqlEmission, codecTypeImports, testHashes); expect(types).not.toContain('SqlMappings'); expect(types).toContain('CodecTypes'); expect(types).toContain('export type TypeMaps'); @@ -220,14 +210,7 @@ describe('sql-target-family-hook', () => { ]; const codecTypeImports = extractCodecTypeImports(descriptors); - const operationTypeImports = extractOperationTypeImports(descriptors); - const types = generateContractDts( - ir, - sqlEmission, - codecTypeImports, - operationTypeImports, - testHashes, - ); + const types = generateContractDts(ir, sqlEmission, codecTypeImports, testHashes); expect(types).not.toContain('SqlMappings'); expect(types).toContain('CodecTypes'); expect(types).toContain('export type TypeMaps'); @@ -305,7 +288,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).not.toContain('export type Relations'); expect(types).toContain( "readonly posts: { readonly to: 'Post'; readonly cardinality: '1:N'; readonly on: { readonly localFields: readonly ['id']; readonly targetFields: readonly ['userId'] } }", @@ -346,7 +329,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain('Record'); }); @@ -387,7 +370,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain('export type Contract'); expect(types).toContain('readonly User: {'); expect(types).toContain("storage: { readonly table: 'user'"); @@ -459,7 +442,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain('readonly User: {'); expect(types).toContain('readonly Post: {'); expect(types).toContain("readonly table: 'user'"); @@ -487,7 +470,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).not.toContain('SqlMappings'); expect(types).toContain('storageHash: StorageHash'); }); @@ -518,7 +501,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain("readonly partialRel: { readonly to: 'Post' }"); }); @@ -549,7 +532,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain('readonly User: {'); expect(types).toContain("storage: { readonly table: 'user'"); expect(types).toContain('readonly fields: Record'); @@ -594,11 +577,9 @@ describe('sql-target-family-hook', () => { ]; const codecImports = extractCodecTypeImports(descriptors); - const operationImports = extractOperationTypeImports(descriptors); expect(codecImports.length).toBe(2); expect(codecImports[0]?.package).toBe('@test/adapter/codec-types'); expect(codecImports[1]?.package).toBe('@test/extension/codec-types'); - expect(operationImports.length).toBe(0); }); it('gets types imports with descriptors without codecTypes', () => { @@ -613,12 +594,10 @@ describe('sql-target-family-hook', () => { ]; const codecImports = extractCodecTypeImports(descriptors); - const operationImports = extractOperationTypeImports(descriptors); expect(codecImports.length).toBe(0); - expect(operationImports.length).toBe(0); }); - it('gets types imports using extractCodecTypeImports and extractOperationTypeImports', () => { + it('gets types imports using extractCodecTypeImports', () => { const descriptors: TestDescriptor[] = [ { kind: 'adapter', @@ -634,25 +613,14 @@ describe('sql-target-family-hook', () => { alias: 'TestTypes', }, }, - operationTypes: { - import: { - package: '@test/adapter/operation-types', - named: 'OperationTypes', - alias: 'TestOps', - }, - }, }, }, ]; const codecImports = extractCodecTypeImports(descriptors); - const operationImports = extractOperationTypeImports(descriptors); expect(codecImports).toEqual([ { package: '@test/adapter/codec-types', named: 'CodecTypes', alias: 'TestTypes' }, ]); - expect(operationImports).toEqual([ - { package: '@test/adapter/operation-types', named: 'OperationTypes', alias: 'TestOps' }, - ]); }); it('generates model storage type via generateModelStorageType', () => { @@ -704,7 +672,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain("owner: { readonly kind: 'system' }"); }); }); diff --git a/packages/2-sql/3-tooling/emitter/test/emitter-hook.generation.basic.test.ts b/packages/2-sql/3-tooling/emitter/test/emitter-hook.generation.basic.test.ts index 7c729723f3..360b7caca5 100644 --- a/packages/2-sql/3-tooling/emitter/test/emitter-hook.generation.basic.test.ts +++ b/packages/2-sql/3-tooling/emitter/test/emitter-hook.generation.basic.test.ts @@ -5,10 +5,7 @@ import type { ControlExtensionDescriptor, ControlTargetDescriptor, } from '@prisma-next/framework-components/control'; -import { - extractCodecTypeImports, - extractOperationTypeImports, -} from '@prisma-next/framework-components/control'; +import { extractCodecTypeImports } from '@prisma-next/framework-components/control'; import { describe, expect, it } from 'vitest'; import { sqlEmission } from '../src/index'; @@ -67,7 +64,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain('export type Contract'); expect(types).toContain('CodecTypes'); expect(types).toContain('readonly roots:'); @@ -99,24 +96,24 @@ describe('sql-target-family-hook', () => { }, }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain( - 'export type TypeMaps = TypeMapsType', + 'export type TypeMaps = TypeMapsType', ); }); - it('TypeMaps delegates to TypeMapsType with CodecTypes and OperationTypes', () => { + it('TypeMaps delegates to TypeMapsType with CodecTypes', () => { const ir = createContract({ models: {}, storage: { tables: {} }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain( - 'TypeMapsType', + 'TypeMapsType', ); }); - it('Contract does not include phantom codecTypes or operationTypes keys', () => { + it('Contract does not include phantom codecTypes keys', () => { const ir = createContract({ models: { User: { @@ -141,7 +138,7 @@ describe('sql-target-family-hook', () => { }, }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).not.toContain("'__@prisma-next/sql-contract/codecTypes@__'"); expect(types).not.toContain("'__@prisma-next/sql-contract/operationTypes@__'"); expect(types).not.toContain("'__@prisma-next/sql-contract/typeMaps@__'"); @@ -179,7 +176,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain('Contract as ContractType,'); expect(types).toContain('ContractWithTypeMaps,'); expect(types).toContain('TypeMaps as TypeMapsType,'); @@ -214,7 +211,6 @@ describe('sql-target-family-hook', () => { ]; const codecImports = extractCodecTypeImports(descriptors); - const operationImports = extractOperationTypeImports(descriptors); expect(codecImports).toEqual([ { package: '@test/adapter/codec-types', @@ -222,7 +218,6 @@ describe('sql-target-family-hook', () => { alias: 'TestTypes', }, ]); - expect(operationImports).toEqual([]); }); it('generates contract types with multiple extensions', () => { @@ -289,7 +284,6 @@ describe('sql-target-family-hook', () => { ]; const codecTypeImports = extractCodecTypeImports(descriptors); - const operationTypeImports = extractOperationTypeImports(descriptors); expect(codecTypeImports).toEqual([ { package: '@prisma-next/target-postgres/codec-types', @@ -298,14 +292,7 @@ describe('sql-target-family-hook', () => { }, { package: '@prisma-next/pgvector/codec-types', named: 'CodecTypes', alias: 'VectorTypes' }, ]); - expect(operationTypeImports).toEqual([]); - const types = generateContractDts( - ir, - sqlEmission, - codecTypeImports, - operationTypeImports, - testHashes, - ); + const types = generateContractDts(ir, sqlEmission, codecTypeImports, testHashes); expect(types).toContain('PgTypes'); expect(types).toContain('VectorTypes'); }); @@ -330,7 +317,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain('uniques: readonly'); expect(types).toContain("readonly columns: readonly ['email']"); }); @@ -355,7 +342,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain('uniques: readonly'); expect(types).toContain("readonly name: 'unique_email'"); }); @@ -381,7 +368,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain('uniques: readonly'); expect(types).toContain("readonly columns: readonly ['first_name', 'last_name']"); }); @@ -406,7 +393,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain('indexes: readonly'); expect(types).toContain("readonly columns: readonly ['email']"); }); @@ -431,7 +418,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain('indexes: readonly'); expect(types).toContain("readonly name: 'idx_email'"); }); @@ -470,7 +457,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain('foreignKeys: readonly'); expect(types).toContain("readonly columns: readonly ['userId']"); expect(types).toContain("readonly table: 'user'"); @@ -512,7 +499,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain('foreignKeys: readonly'); expect(types).toContain("readonly name: 'fk_post_user'"); }); @@ -536,7 +523,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain("readonly name: 'pk_user'"); }); @@ -577,7 +564,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain( "readonly name: { readonly nullable: true; readonly type: { readonly kind: 'scalar'; readonly codecId: 'pg/text@1' } }", ); @@ -620,7 +607,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain( "readonly email: { readonly nullable: false; readonly type: { readonly kind: 'scalar'; readonly codecId: 'pg/text@1' } }", ); @@ -657,7 +644,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain( "readonly id: { readonly nullable: false; readonly type: { readonly kind: 'scalar'; readonly codecId: 'pg/int4@1' } }", ); @@ -681,7 +668,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain('Record'); expect(types).not.toContain('SqlMappings'); }); @@ -721,7 +708,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain( "readonly id: { readonly nullable: false; readonly type: { readonly kind: 'scalar'; readonly codecId: 'pg/int4@1' } }", ); @@ -768,7 +755,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain( "readonly vector: { readonly nullable: false; readonly type: { readonly kind: 'scalar'; readonly codecId: 'pg/vector@1'; readonly typeParams: { readonly length: 1536 } } }", @@ -776,58 +763,6 @@ describe('sql-target-family-hook', () => { expect(types).not.toContain('Vector<1536>'); }); - it('generates contract types with no operation type imports', () => { - const ir = createContract({ - storage: { - tables: { - user: { - columns: { - id: { nativeType: 'int4', codecId: 'pg/int4@1', nullable: false }, - }, - primaryKey: { columns: ['id'] }, - uniques: [], - indexes: [], - foreignKeys: [], - }, - }, - }, - }); - - // Pass empty operationTypeImports array to test filter/map on lines 278-279 - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); - expect(types).toContain('export type OperationTypes = Record'); - }); - - it('filters operation type imports to only OperationTypes', () => { - const ir = createContract({ - storage: { - tables: { - user: { - columns: { - id: { nativeType: 'int4', codecId: 'pg/int4@1', nullable: false }, - }, - primaryKey: { columns: ['id'] }, - uniques: [], - indexes: [], - foreignKeys: [], - }, - }, - }, - }); - - // Include operation type imports with different named values to test filter on line 278 - const operationTypeImports = [ - { package: '@test/ops', named: 'OperationTypes', alias: 'TestOps' }, - { package: '@test/other', named: 'OtherTypes', alias: 'Other' }, - ]; - - const types = generateContractDts(ir, sqlEmission, [], operationTypeImports, testHashes); - // Only OperationTypes should be included in the intersection, not OtherTypes - // (OtherTypes will still be imported but not used in the OperationTypes type) - expect(types).toContain('export type OperationTypes = TestOps'); - expect(types).not.toContain('export type OperationTypes = TestOps & Other'); - }); - it('generates contract types with query operation type imports', () => { const ir = createContract({ storage: { @@ -850,7 +785,7 @@ describe('sql-target-family-hook', () => { { package: '@test/other', named: 'OtherTypes', alias: 'Other' }, ]; - const types = generateContractDts(ir, sqlEmission, [], [], testHashes, { + const types = generateContractDts(ir, sqlEmission, [], testHashes, { queryOperationTypeImports, }); expect(types).toContain('export type QueryOperationTypes = TestQueryOps'); @@ -893,7 +828,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain("readonly using: 'bm25'"); expect(types).toContain("readonly config: { readonly keyField: 'id'"); expect(types).toContain("readonly name: 'search_idx'"); @@ -937,7 +872,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain("readonly expression: 'description || \\' \\' || category'"); expect(types).toContain("readonly alias: 'concat'"); }); @@ -972,7 +907,7 @@ describe('sql-target-family-hook', () => { }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain("readonly 'min-token-size': 2"); expect(types).toContain("readonly 'max-ngram': 5"); }); @@ -1032,7 +967,7 @@ describe('sql-target-family-hook', () => { storage: { tables: {} }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).not.toContain('readonly execution'); }); @@ -1068,7 +1003,7 @@ describe('sql-target-family-hook', () => { }, }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain('export type AddressOutput ='); expect(types).toContain('export type AddressInput ='); expect(types).not.toMatch(/export type Address =/); @@ -1087,7 +1022,7 @@ describe('sql-target-family-hook', () => { }, storage: { tables: {} }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain('readonly valueObjects:'); expect(types).toContain('readonly Address: { readonly fields:'); }); @@ -1135,7 +1070,7 @@ describe('sql-target-family-hook', () => { }, }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain( "readonly homeAddress: { readonly nullable: true; readonly type: { readonly kind: 'valueObject'; readonly name: 'Address' } }", ); @@ -1185,7 +1120,7 @@ describe('sql-target-family-hook', () => { }, }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain( "readonly addresses: { readonly nullable: false; readonly type: { readonly kind: 'valueObject'; readonly name: 'Address' }; readonly many: true }", ); @@ -1207,7 +1142,7 @@ describe('sql-target-family-hook', () => { }, storage: { tables: {} }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain('export type NavItemOutput ='); expect(types).toContain('export type NavItemInput ='); expect(types).toContain('readonly children: ReadonlyArray'); @@ -1217,7 +1152,7 @@ describe('sql-target-family-hook', () => { const ir = createContract({ storage: { tables: {} }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).not.toContain('valueObjects'); }); @@ -1232,7 +1167,7 @@ describe('sql-target-family-hook', () => { }, storage: { tables: {} }, }); - const types = generateContractDts(ir, sqlEmission, [], [], testHashes); + const types = generateContractDts(ir, sqlEmission, [], testHashes); expect(types).toContain("readonly zip: CodecTypes['pg/text@1']['output'] | null"); }); }); diff --git a/packages/2-sql/3-tooling/emitter/test/emitter-hook.typeref-resolver.test.ts b/packages/2-sql/3-tooling/emitter/test/emitter-hook.typeref-resolver.test.ts index 579c17b55a..a2bbce2222 100644 --- a/packages/2-sql/3-tooling/emitter/test/emitter-hook.typeref-resolver.test.ts +++ b/packages/2-sql/3-tooling/emitter/test/emitter-hook.typeref-resolver.test.ts @@ -106,7 +106,6 @@ describe('sqlEmission.resolveFieldTypeParams (integration via generateContractDt contract, sqlEmission, [], - [], testHashes, undefined, vectorCodecLookup(), @@ -170,7 +169,6 @@ describe('sqlEmission.resolveFieldTypeParams (integration via generateContractDt contract, sqlEmission, [], - [], testHashes, undefined, vectorCodecLookup(), diff --git a/packages/2-sql/4-lanes/sql-builder/test/fixtures/generated/contract.d.ts b/packages/2-sql/4-lanes/sql-builder/test/fixtures/generated/contract.d.ts index cf3dc10a45..c63e465718 100644 --- a/packages/2-sql/4-lanes/sql-builder/test/fixtures/generated/contract.d.ts +++ b/packages/2-sql/4-lanes/sql-builder/test/fixtures/generated/contract.d.ts @@ -15,7 +15,6 @@ import type { Timetz } from '@prisma-next/target-postgres/codec-types'; import type { Interval } from '@prisma-next/target-postgres/codec-types'; import type { CodecTypes as PgVectorTypes } from '@prisma-next/extension-pgvector/codec-types'; import type { Vector } from '@prisma-next/extension-pgvector/codec-types'; -import type { OperationTypes as PgVectorOperationTypes } from '@prisma-next/extension-pgvector/operation-types'; import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma-next/adapter-postgres/operation-types'; import type { QueryOperationTypes as PgVectorQueryOperationTypes } from '@prisma-next/extension-pgvector/operation-types'; @@ -38,7 +37,6 @@ export type ProfileHash = ProfileHashBase<'sha256:03c90a412dcfe182a475d25eae8cbf5c56fba67009defe8713eaf0b7fbd66b13'>; export type CodecTypes = PgTypes & PgVectorTypes; -export type OperationTypes = PgVectorOperationTypes; export type LaneCodecTypes = CodecTypes; export type QueryOperationTypes = PgAdapterQueryOps & PgVectorQueryOperationTypes; @@ -103,7 +101,6 @@ export type FieldInputTypes = { }; export type TypeMaps = TypeMapsType< CodecTypes, - OperationTypes, QueryOperationTypes, FieldOutputTypes, FieldInputTypes @@ -490,13 +487,6 @@ type ContractBase = ContractType< }, ]; }; - readonly operationTypes: { - readonly import: { - readonly alias: 'PgVectorOperationTypes'; - readonly named: 'OperationTypes'; - readonly package: '@prisma-next/extension-pgvector/operation-types'; - }; - }; readonly queryOperationTypes: { readonly import: { readonly alias: 'PgVectorQueryOperationTypes'; diff --git a/packages/2-sql/4-lanes/sql-builder/test/fixtures/generated/contract.json b/packages/2-sql/4-lanes/sql-builder/test/fixtures/generated/contract.json index 44fdcea5c7..efe5415ac1 100644 --- a/packages/2-sql/4-lanes/sql-builder/test/fixtures/generated/contract.json +++ b/packages/2-sql/4-lanes/sql-builder/test/fixtures/generated/contract.json @@ -533,13 +533,6 @@ } ] }, - "operationTypes": { - "import": { - "alias": "PgVectorOperationTypes", - "named": "OperationTypes", - "package": "@prisma-next/extension-pgvector/operation-types" - } - }, "queryOperationTypes": { "import": { "alias": "PgVectorQueryOperationTypes", diff --git a/packages/2-sql/5-runtime/src/sql-context.ts b/packages/2-sql/5-runtime/src/sql-context.ts index bac980874a..e29446fc98 100644 --- a/packages/2-sql/5-runtime/src/sql-context.ts +++ b/packages/2-sql/5-runtime/src/sql-context.ts @@ -19,7 +19,7 @@ import { runtimeError } from '@prisma-next/framework-components/runtime'; import type { SqlStorage } from '@prisma-next/sql-contract/types'; import { createSqlOperationRegistry, - type SqlOperationDescriptor, + type SqlOperationDescriptors, } from '@prisma-next/sql-operations'; import type { Adapter, @@ -59,7 +59,7 @@ export interface SqlStaticContributions { readonly codecs: () => CodecRegistry; // biome-ignore lint/suspicious/noExplicitAny: needed for covariance with concrete descriptor types readonly parameterizedCodecs: () => ReadonlyArray>; - readonly queryOperations?: () => ReadonlyArray; + readonly queryOperations?: () => SqlOperationDescriptors; readonly mutationDefaultGenerators?: () => ReadonlyArray; } @@ -715,8 +715,9 @@ export function createExecutionContext< const queryOperationRegistry = createSqlOperationRegistry(); for (const contributor of contributors) { - for (const op of contributor.queryOperations?.() ?? []) { - queryOperationRegistry.register(op); + const ops = contributor.queryOperations?.() ?? {}; + for (const [name, op] of Object.entries(ops)) { + queryOperationRegistry.register(name, op); } } diff --git a/packages/2-sql/5-runtime/test/execution-stack.test.ts b/packages/2-sql/5-runtime/test/execution-stack.test.ts index b41c392315..2f324a589a 100644 --- a/packages/2-sql/5-runtime/test/execution-stack.test.ts +++ b/packages/2-sql/5-runtime/test/execution-stack.test.ts @@ -78,12 +78,11 @@ function createStubExtensionDescriptor(): SqlRuntimeExtensionDescriptor<'postgre }), ); - const operations = [ - { - method: 'example', + const operations = { + example: { impl: () => undefined as never, }, - ]; + }; return { kind: 'extension', diff --git a/packages/2-sql/5-runtime/test/sql-context.test.ts b/packages/2-sql/5-runtime/test/sql-context.test.ts index 72948f00cd..f63e1f1337 100644 --- a/packages/2-sql/5-runtime/test/sql-context.test.ts +++ b/packages/2-sql/5-runtime/test/sql-context.test.ts @@ -1,6 +1,6 @@ import { type Contract, coreHash, executionHash, profileHash } from '@prisma-next/contract/types'; import type { SqlStorage } from '@prisma-next/sql-contract/types'; -import type { SqlOperationDescriptor } from '@prisma-next/sql-operations'; +import type { SqlOperationDescriptors } from '@prisma-next/sql-operations'; import { codec, createCodecRegistry } from '@prisma-next/sql-relational-core/ast'; import { describe, expect, it } from 'vitest'; import { @@ -48,15 +48,14 @@ function createTestExtensionDescriptor(options?: { })() : createCodecRegistry(); - const operationsArray: ReadonlyArray = hasOperations - ? [ - { - method: 'testOp', + const operations: SqlOperationDescriptors = hasOperations + ? { + testOp: { self: { codecId: 'test/ext@1' }, impl: () => undefined as never, }, - ] - : []; + } + : {}; return { kind: 'extension' as const, @@ -65,7 +64,7 @@ function createTestExtensionDescriptor(options?: { familyId: 'sql' as const, targetId: 'postgres' as const, codecs: () => codecRegistry, - queryOperations: () => operationsArray, + queryOperations: () => operations, parameterizedCodecs: () => [], create() { return { @@ -157,13 +156,12 @@ describe('comprehensive descriptor-based derivation', () => { }), ); - const targetOps: SqlOperationDescriptor[] = [ - { - method: 'targetOp', + const targetOps: SqlOperationDescriptors = { + targetOp: { self: { codecId: 'target/special@1' }, impl: () => undefined as never, }, - ]; + }; const target: SqlRuntimeTargetDescriptor<'postgres'> = { kind: 'target' as const, diff --git a/packages/2-sql/9-family/src/core/control-instance.ts b/packages/2-sql/9-family/src/core/control-instance.ts index e682af2b86..e2af316a62 100644 --- a/packages/2-sql/9-family/src/core/control-instance.ts +++ b/packages/2-sql/9-family/src/core/control-instance.ts @@ -169,7 +169,6 @@ type SqlTypeMetadataRegistry = Map; interface SqlFamilyInstanceState { readonly codecTypeImports: ReadonlyArray; - readonly operationTypeImports: ReadonlyArray; readonly extensionIds: ReadonlyArray; readonly typeMetadataRegistry: SqlTypeMetadataRegistry; } @@ -300,7 +299,7 @@ export function createSqlFamilyInstance( stack.extensionPacks as unknown as readonly (SqlControlExtensionDescriptor & DescriptorWithStorageTypes)[]; - const { codecTypeImports, operationTypeImports, extensionIds } = stack; + const { codecTypeImports, extensionIds } = stack; const typeMetadataRegistry = buildSqlTypeMetadataRegistry({ target, @@ -325,7 +324,6 @@ export function createSqlFamilyInstance( return { familyId: 'sql', codecTypeImports, - operationTypeImports, extensionIds, typeMetadataRegistry, diff --git a/packages/2-sql/9-family/src/core/migrations/types.ts b/packages/2-sql/9-family/src/core/migrations/types.ts index 37589d35dd..11ef0c4e7c 100644 --- a/packages/2-sql/9-family/src/core/migrations/types.ts +++ b/packages/2-sql/9-family/src/core/migrations/types.ts @@ -18,7 +18,7 @@ import type { SchemaIssue, } from '@prisma-next/framework-components/control'; import type { SqlStorage, StorageTypeInstance } from '@prisma-next/sql-contract/types'; -import type { SqlOperationDescriptor } from '@prisma-next/sql-operations'; +import type { SqlOperationDescriptors } from '@prisma-next/sql-operations'; import type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types'; import type { Result } from '@prisma-next/utils/result'; import type { SqlControlFamilyInstance } from '../control-instance'; @@ -127,12 +127,12 @@ export interface CodecControlHooks { export interface SqlControlExtensionDescriptor extends ControlExtensionDescriptor<'sql', TTargetId> { readonly databaseDependencies?: ComponentDatabaseDependencies; - readonly queryOperations?: () => ReadonlyArray; + readonly queryOperations?: () => SqlOperationDescriptors; } export interface SqlControlAdapterDescriptor extends ControlAdapterDescriptor<'sql', TTargetId> { - readonly queryOperations?: () => ReadonlyArray; + readonly queryOperations?: () => SqlOperationDescriptors; } export interface SqlMigrationPlanOperationStep { @@ -339,7 +339,7 @@ export interface SqlMigrationRunner { export interface SqlControlTargetDescriptor extends MigratableTargetDescriptor<'sql', TTargetId, SqlControlFamilyInstance> { - readonly queryOperations?: () => ReadonlyArray; + readonly queryOperations?: () => SqlOperationDescriptors; createPlanner(family: SqlControlFamilyInstance): SqlMigrationPlanner; createRunner(family: SqlControlFamilyInstance): SqlMigrationRunner; } diff --git a/packages/2-sql/9-family/src/exports/test-utils.ts b/packages/2-sql/9-family/src/exports/test-utils.ts index bbec5fd6f5..a2dd195616 100644 --- a/packages/2-sql/9-family/src/exports/test-utils.ts +++ b/packages/2-sql/9-family/src/exports/test-utils.ts @@ -5,6 +5,5 @@ export { extractCodecTypeImports, extractComponentIds, - extractOperationTypeImports, extractQueryOperationTypeImports, } from '@prisma-next/framework-components/control'; diff --git a/packages/2-sql/9-family/test/compute-column-js-type.test-d.ts b/packages/2-sql/9-family/test/compute-column-js-type.test-d.ts index 6c1fb68846..1b9a54b92f 100644 --- a/packages/2-sql/9-family/test/compute-column-js-type.test-d.ts +++ b/packages/2-sql/9-family/test/compute-column-js-type.test-d.ts @@ -93,12 +93,7 @@ type TestModels = { readonly Vectors: VectorsModel; }; -type TestTypeMaps = TypeMaps< - TestCodecTypes, - Record, - Record, - TestFieldOutputTypes ->; +type TestTypeMaps = TypeMaps, TestFieldOutputTypes>; type ContractInlineTypeParams = Contract & { readonly target: 'postgres'; @@ -200,7 +195,6 @@ type ContractNullable = Contract< readonly [K in TypeMapsPhantomKey]?: TypeMaps< TestCodecTypes, Record, - Record, NullableFieldOutputTypes >; }; diff --git a/packages/2-sql/9-family/test/operation-preview.test.ts b/packages/2-sql/9-family/test/operation-preview.test.ts index 97c5df24f8..1dc474aec9 100644 --- a/packages/2-sql/9-family/test/operation-preview.test.ts +++ b/packages/2-sql/9-family/test/operation-preview.test.ts @@ -110,7 +110,6 @@ describe('SqlControlFamilyInstance OperationPreviewCapable', () => { }, extensionPacks: [], codecTypeImports: [], - operationTypeImports: [], extensionIds: [], // biome-ignore lint/suspicious/noExplicitAny: minimal stub } as any; diff --git a/packages/3-extensions/pgvector/src/core/descriptor-meta.ts b/packages/3-extensions/pgvector/src/core/descriptor-meta.ts index bc98b7ec65..e709659412 100644 --- a/packages/3-extensions/pgvector/src/core/descriptor-meta.ts +++ b/packages/3-extensions/pgvector/src/core/descriptor-meta.ts @@ -1,11 +1,6 @@ -import type { SqlOperationDescriptor } from '@prisma-next/sql-operations'; -import { - buildOperation, - type CodecExpression, - type Expression, - toExpr, -} from '@prisma-next/sql-relational-core/expression'; +import { buildOperation, toExpr } from '@prisma-next/sql-relational-core/expression'; import type { CodecTypes } from '../types/codec-types'; +import type { QueryOperationTypes } from '../types/operation-types'; import { pgvectorAuthoringTypes } from './authoring'; import { codecDefinitions } from './codecs'; @@ -13,17 +8,11 @@ const pgvectorTypeId = 'pg/vector@1' as const; type CodecTypesBase = Record; -export function pgvectorQueryOperations< - CT extends CodecTypesBase, ->(): readonly SqlOperationDescriptor[] { - return [ - { - method: 'cosineDistance', +export function pgvectorQueryOperations(): QueryOperationTypes { + return { + cosineDistance: { self: { codecId: pgvectorTypeId }, - impl: ( - self: CodecExpression<'pg/vector@1', boolean, CT>, - other: CodecExpression<'pg/vector@1', boolean, CT>, - ): Expression<{ codecId: 'pg/float8@1'; nullable: false }> => + impl: (self, other) => buildOperation({ method: 'cosineDistance', args: [toExpr(self, pgvectorTypeId), toExpr(other, pgvectorTypeId)], @@ -35,13 +24,9 @@ export function pgvectorQueryOperations< }, }), }, - { - method: 'cosineSimilarity', + cosineSimilarity: { self: { codecId: pgvectorTypeId }, - impl: ( - self: CodecExpression<'pg/vector@1', boolean, CT>, - other: CodecExpression<'pg/vector@1', boolean, CT>, - ): Expression<{ codecId: 'pg/float8@1'; nullable: false }> => + impl: (self, other) => buildOperation({ method: 'cosineSimilarity', args: [toExpr(self, pgvectorTypeId), toExpr(other, pgvectorTypeId)], @@ -53,7 +38,7 @@ export function pgvectorQueryOperations< }, }), }, - ]; + }; } const pgvectorPackMetaBase = { @@ -86,13 +71,6 @@ const pgvectorPackMetaBase = { }, ], }, - operationTypes: { - import: { - package: '@prisma-next/extension-pgvector/operation-types', - named: 'OperationTypes', - alias: 'PgVectorOperationTypes', - }, - }, queryOperationTypes: { import: { package: '@prisma-next/extension-pgvector/operation-types', diff --git a/packages/3-extensions/pgvector/src/exports/operation-types.ts b/packages/3-extensions/pgvector/src/exports/operation-types.ts index b8c3baac1b..33232eca71 100644 --- a/packages/3-extensions/pgvector/src/exports/operation-types.ts +++ b/packages/3-extensions/pgvector/src/exports/operation-types.ts @@ -4,4 +4,4 @@ * Re-export from types module for public API. */ -export type { OperationTypes, QueryOperationTypes } from '../types/operation-types'; +export type { QueryOperationTypes } from '../types/operation-types'; diff --git a/packages/3-extensions/pgvector/src/types/operation-types.ts b/packages/3-extensions/pgvector/src/types/operation-types.ts index 9306b303a1..38a514f1c2 100644 --- a/packages/3-extensions/pgvector/src/types/operation-types.ts +++ b/packages/3-extensions/pgvector/src/types/operation-types.ts @@ -10,17 +10,6 @@ type CodecTypesBase = Record = SqlQueryOperationTypes< CT, diff --git a/packages/3-extensions/pgvector/test/manifest.test.ts b/packages/3-extensions/pgvector/test/manifest.test.ts index caf71e6413..3528a8f9c5 100644 --- a/packages/3-extensions/pgvector/test/manifest.test.ts +++ b/packages/3-extensions/pgvector/test/manifest.test.ts @@ -22,14 +22,6 @@ describe('pgvector descriptor', () => { }); }); - it('has operation types import', () => { - expect(pgvectorExtensionDescriptor.types?.operationTypes?.import).toEqual({ - package: '@prisma-next/extension-pgvector/operation-types', - named: 'OperationTypes', - alias: 'PgVectorOperationTypes', - }); - }); - it( 'codec types are importable', async () => { diff --git a/packages/3-extensions/pgvector/test/operations.test.ts b/packages/3-extensions/pgvector/test/operations.test.ts index e03ff2a905..7317cf0b8e 100644 --- a/packages/3-extensions/pgvector/test/operations.test.ts +++ b/packages/3-extensions/pgvector/test/operations.test.ts @@ -24,9 +24,9 @@ describe('pgvector operations', () => { it('descriptor provides query operations whose impls build AST with lowering', () => { const operations = pgvectorDescriptor.queryOperations!(); expect(operations).toBeDefined(); - expect(operations.length).toBe(2); + expect(Object.keys(operations).sort()).toEqual(['cosineDistance', 'cosineSimilarity']); - const cosineDistanceOp = operations.find((op) => op.method === 'cosineDistance'); + const cosineDistanceOp = operations['cosineDistance']; expect(cosineDistanceOp).toBeDefined(); const distExpr = cosineDistanceOp?.impl( ParamRef.of([1, 2], { codecId: 'pg/vector@1' }) as never, @@ -40,7 +40,7 @@ describe('pgvector operations', () => { template: '{{self}} <=> {{arg0}}', }); - const cosineSimilarityOp = operations.find((op) => op.method === 'cosineSimilarity'); + const cosineSimilarityOp = operations['cosineSimilarity']; expect(cosineSimilarityOp).toBeDefined(); const simExpr = cosineSimilarityOp?.impl( ParamRef.of([1, 2], { codecId: 'pg/vector@1' }) as never, @@ -59,8 +59,8 @@ describe('pgvector operations', () => { const operations = pgvectorDescriptor.queryOperations!(); const registry = createSqlOperationRegistry(); - for (const op of operations) { - registry.register(op); + for (const [name, op] of Object.entries(operations)) { + registry.register(name, op); } const entries = registry.entries(); diff --git a/packages/3-extensions/sql-orm-client/test/fixtures/generated/contract.d.ts b/packages/3-extensions/sql-orm-client/test/fixtures/generated/contract.d.ts index 778d7aa33f..67c2cd7c59 100644 --- a/packages/3-extensions/sql-orm-client/test/fixtures/generated/contract.d.ts +++ b/packages/3-extensions/sql-orm-client/test/fixtures/generated/contract.d.ts @@ -15,7 +15,6 @@ import type { Timetz } from '@prisma-next/target-postgres/codec-types'; import type { Interval } from '@prisma-next/target-postgres/codec-types'; import type { CodecTypes as PgVectorTypes } from '@prisma-next/extension-pgvector/codec-types'; import type { Vector } from '@prisma-next/extension-pgvector/codec-types'; -import type { OperationTypes as PgVectorOperationTypes } from '@prisma-next/extension-pgvector/operation-types'; import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma-next/adapter-postgres/operation-types'; import type { QueryOperationTypes as PgVectorQueryOperationTypes } from '@prisma-next/extension-pgvector/operation-types'; @@ -38,7 +37,6 @@ export type ProfileHash = ProfileHashBase<'sha256:1a8dbe044289f30a1de958fe800cc5a8378b285d2e126a8c44b58864bac2c18e'>; export type CodecTypes = PgTypes & PgVectorTypes; -export type OperationTypes = PgVectorOperationTypes; export type LaneCodecTypes = CodecTypes; export type QueryOperationTypes = PgAdapterQueryOps & PgVectorQueryOperationTypes; @@ -124,7 +122,6 @@ export type FieldInputTypes = { }; export type TypeMaps = TypeMapsType< CodecTypes, - OperationTypes, QueryOperationTypes, FieldOutputTypes, FieldInputTypes @@ -606,13 +603,6 @@ type ContractBase = ContractType< }, ]; }; - readonly operationTypes: { - readonly import: { - readonly alias: 'PgVectorOperationTypes'; - readonly named: 'OperationTypes'; - readonly package: '@prisma-next/extension-pgvector/operation-types'; - }; - }; readonly queryOperationTypes: { readonly import: { readonly alias: 'PgVectorQueryOperationTypes'; diff --git a/packages/3-extensions/sql-orm-client/test/fixtures/generated/contract.json b/packages/3-extensions/sql-orm-client/test/fixtures/generated/contract.json index 9a92513632..fbdb7712da 100644 --- a/packages/3-extensions/sql-orm-client/test/fixtures/generated/contract.json +++ b/packages/3-extensions/sql-orm-client/test/fixtures/generated/contract.json @@ -730,13 +730,6 @@ } ] }, - "operationTypes": { - "import": { - "alias": "PgVectorOperationTypes", - "named": "OperationTypes", - "package": "@prisma-next/extension-pgvector/operation-types" - } - }, "queryOperationTypes": { "import": { "alias": "PgVectorQueryOperationTypes", diff --git a/packages/3-extensions/sql-orm-client/test/generated-contract-types.test-d.ts b/packages/3-extensions/sql-orm-client/test/generated-contract-types.test-d.ts index 7840c1c3e6..5fda87af2a 100644 --- a/packages/3-extensions/sql-orm-client/test/generated-contract-types.test-d.ts +++ b/packages/3-extensions/sql-orm-client/test/generated-contract-types.test-d.ts @@ -38,7 +38,6 @@ type GeneratedLikeFieldOutputTypes = { type GeneratedLikeTypeMaps = TypeMaps< GeneratedLikeCodecTypes, Record, - Record, GeneratedLikeFieldOutputTypes >; @@ -389,12 +388,7 @@ type VOFieldOutputTypes = { }; }; -type VOTypeMaps = TypeMaps< - VOCodecTypes, - Record, - Record, - VOFieldOutputTypes ->; +type VOTypeMaps = TypeMaps, VOFieldOutputTypes>; type VOContractBase = Contract< { diff --git a/packages/3-extensions/sql-orm-client/test/model-accessor.test.ts b/packages/3-extensions/sql-orm-client/test/model-accessor.test.ts index 5965a5d733..9e3ce24431 100644 --- a/packages/3-extensions/sql-orm-client/test/model-accessor.test.ts +++ b/packages/3-extensions/sql-orm-client/test/model-accessor.test.ts @@ -617,8 +617,7 @@ describe('createModelAccessor', () => { it('attaches trait-targeted op only when codec traits are a superset of required traits', () => { const queryOperations = createSqlOperationRegistry(); - queryOperations.register({ - method: 'synthetic', + queryOperations.register('synthetic', { self: { traits: ['equality', 'textual'] }, impl: () => undefined as never, }); diff --git a/packages/3-mongo-target/2-mongo-adapter/src/core/operations.ts b/packages/3-mongo-target/2-mongo-adapter/src/core/operations.ts index 145c9e74ef..845cce583d 100644 --- a/packages/3-mongo-target/2-mongo-adapter/src/core/operations.ts +++ b/packages/3-mongo-target/2-mongo-adapter/src/core/operations.ts @@ -1,12 +1,11 @@ -import type { OperationDescriptor } from '@prisma-next/operations'; +import type { OperationDescriptor, OperationDescriptors } from '@prisma-next/operations'; import { MONGO_VECTOR_CODEC_ID } from './codec-ids'; -export const mongoVectorNearOperation = Object.freeze({ - method: 'near', +export const mongoVectorNearOperation: OperationDescriptor = Object.freeze({ self: { codecId: MONGO_VECTOR_CODEC_ID }, impl: () => undefined as never, -}) satisfies OperationDescriptor; +}); -export const mongoVectorOperationDescriptors: readonly OperationDescriptor[] = [ - mongoVectorNearOperation, -]; +export const mongoVectorOperationDescriptors: OperationDescriptors = { + near: mongoVectorNearOperation, +}; diff --git a/packages/3-mongo-target/2-mongo-adapter/test/codecs.test.ts b/packages/3-mongo-target/2-mongo-adapter/test/codecs.test.ts index 0df250cafd..61772600e7 100644 --- a/packages/3-mongo-target/2-mongo-adapter/test/codecs.test.ts +++ b/packages/3-mongo-target/2-mongo-adapter/test/codecs.test.ts @@ -170,8 +170,7 @@ describe('mongoVectorCodec.renderOutputType', () => { }); describe('vector operation descriptors (production-defined)', () => { - it('mongoVectorNearOperation has method near', () => { - expect(mongoVectorNearOperation.method).toBe('near'); + it('mongoVectorNearOperation targets the vector codec', () => { expect(mongoVectorNearOperation.self?.codecId).toBe(MONGO_VECTOR_CODEC_ID); }); @@ -182,14 +181,14 @@ describe('vector operation descriptors (production-defined)', () => { }); it('mongoVectorOperationDescriptors includes near', () => { - expect(mongoVectorOperationDescriptors).toHaveLength(1); - expect(mongoVectorOperationDescriptors[0]).toBe(mongoVectorNearOperation); + expect(Object.keys(mongoVectorOperationDescriptors)).toEqual(['near']); + expect(mongoVectorOperationDescriptors['near']).toBe(mongoVectorNearOperation); }); it('registers production-defined operations in registry', () => { const registry = createOperationRegistry(); - for (const op of mongoVectorOperationDescriptors) { - registry.register(op); + for (const [name, op] of Object.entries(mongoVectorOperationDescriptors)) { + registry.register(name, op); } const entries = registry.entries(); diff --git a/packages/3-targets/6-adapters/postgres/src/core/descriptor-meta.ts b/packages/3-targets/6-adapters/postgres/src/core/descriptor-meta.ts index e3a40ffbda..dabbcd7612 100644 --- a/packages/3-targets/6-adapters/postgres/src/core/descriptor-meta.ts +++ b/packages/3-targets/6-adapters/postgres/src/core/descriptor-meta.ts @@ -1,12 +1,5 @@ import type { CodecControlHooks, ExpandNativeTypeInput } from '@prisma-next/family-sql/control'; -import type { SqlOperationDescriptor } from '@prisma-next/sql-operations'; -import { - buildOperation, - type CodecExpression, - type Expression, - type TraitExpression, - toExpr, -} from '@prisma-next/sql-relational-core/expression'; +import { buildOperation, toExpr } from '@prisma-next/sql-relational-core/expression'; import { PG_BIT_CODEC_ID, PG_BOOL_CODEC_ID, @@ -39,6 +32,7 @@ import { SQL_VARCHAR_CODEC_ID, } from '@prisma-next/target-postgres/codec-ids'; import { codecDefinitions } from '@prisma-next/target-postgres/codecs'; +import type { QueryOperationTypes } from '../types/operation-types'; import { pgEnumControlHooks } from './enum-control-hooks'; // ============================================================================ @@ -138,17 +132,11 @@ const identityHooks: CodecControlHooks = { expandNativeType: ({ nativeType }) => type CodecTypesBase = Record; -export function postgresQueryOperations< - CT extends CodecTypesBase, ->(): readonly SqlOperationDescriptor[] { - return [ - { - method: 'ilike', +export function postgresQueryOperations(): QueryOperationTypes { + return { + ilike: { self: { traits: ['textual'] }, - impl: ( - self: TraitExpression, - pattern: CodecExpression<'pg/text@1', false, CT>, - ): Expression<{ codecId: 'pg/bool@1'; nullable: false }> => + impl: (self, pattern) => buildOperation({ method: 'ilike', args: [toExpr(self), toExpr(pattern, PG_TEXT_CODEC_ID)], @@ -156,7 +144,7 @@ export function postgresQueryOperations< lowering: { targetFamily: 'sql', strategy: 'infix', template: '{{self}} ILIKE {{arg0}}' }, }), }, - ]; + }; } export const postgresAdapterDescriptorMeta = { diff --git a/test/e2e/framework/test/fixtures/generated/contract.d.ts b/test/e2e/framework/test/fixtures/generated/contract.d.ts index 7546018d82..8a98c47fdd 100644 --- a/test/e2e/framework/test/fixtures/generated/contract.d.ts +++ b/test/e2e/framework/test/fixtures/generated/contract.d.ts @@ -16,7 +16,6 @@ import type { Interval } from '@prisma-next/target-postgres/codec-types'; import type { CodecTypes as PgVectorTypes } from '@prisma-next/extension-pgvector/codec-types'; import type { Vector } from '@prisma-next/extension-pgvector/codec-types'; import type { CodecTypes as ArktypeJsonTypes } from '@prisma-next/extension-arktype-json/codec-types'; -import type { OperationTypes as PgVectorOperationTypes } from '@prisma-next/extension-pgvector/operation-types'; import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma-next/adapter-postgres/operation-types'; import type { QueryOperationTypes as PgVectorQueryOperationTypes } from '@prisma-next/extension-pgvector/operation-types'; @@ -39,7 +38,6 @@ export type ProfileHash = ProfileHashBase<'sha256:29a17a141f69a59f39e6e5ce56adda9719ab0899a8af17bc6e4db2c4e866a182'>; export type CodecTypes = PgTypes & PgVectorTypes & ArktypeJsonTypes; -export type OperationTypes = PgVectorOperationTypes; export type LaneCodecTypes = CodecTypes; export type QueryOperationTypes = PgAdapterQueryOps & PgVectorQueryOperationTypes; @@ -165,7 +163,6 @@ export type FieldInputTypes = { }; export type TypeMaps = TypeMapsType< CodecTypes, - OperationTypes, QueryOperationTypes, FieldOutputTypes, FieldInputTypes @@ -964,13 +961,6 @@ type ContractBase = ContractType< }, ]; }; - readonly operationTypes: { - readonly import: { - readonly alias: 'PgVectorOperationTypes'; - readonly named: 'OperationTypes'; - readonly package: '@prisma-next/extension-pgvector/operation-types'; - }; - }; readonly queryOperationTypes: { readonly import: { readonly alias: 'PgVectorQueryOperationTypes'; diff --git a/test/e2e/framework/test/fixtures/generated/contract.json b/test/e2e/framework/test/fixtures/generated/contract.json index fbb994a39f..303d1c217e 100644 --- a/test/e2e/framework/test/fixtures/generated/contract.json +++ b/test/e2e/framework/test/fixtures/generated/contract.json @@ -1128,13 +1128,6 @@ } ] }, - "operationTypes": { - "import": { - "alias": "PgVectorOperationTypes", - "named": "OperationTypes", - "package": "@prisma-next/extension-pgvector/operation-types" - } - }, "queryOperationTypes": { "import": { "alias": "PgVectorQueryOperationTypes", diff --git a/test/e2e/framework/test/sqlite/fixtures/generated/contract.d.ts b/test/e2e/framework/test/sqlite/fixtures/generated/contract.d.ts index c495391df4..56b0e39b29 100644 --- a/test/e2e/framework/test/sqlite/fixtures/generated/contract.d.ts +++ b/test/e2e/framework/test/sqlite/fixtures/generated/contract.d.ts @@ -21,7 +21,6 @@ export type ProfileHash = ProfileHashBase<'sha256:213031a5ce861b455f22bc065769080ea0357fabcb999de0190524ecd32531f7'>; export type CodecTypes = SqliteTypes; -export type OperationTypes = Record; export type LaneCodecTypes = CodecTypes; export type QueryOperationTypes = Record; type DefaultLiteralValue = CodecId extends keyof CodecTypes @@ -102,7 +101,6 @@ export type FieldInputTypes = { }; export type TypeMaps = TypeMapsType< CodecTypes, - OperationTypes, QueryOperationTypes, FieldOutputTypes, FieldInputTypes diff --git a/test/integration/test/authoring/parity/callback-mode-scalars/expected.contract.json b/test/integration/test/authoring/parity/callback-mode-scalars/expected.contract.json index 3113ab7fb0..6448dd3268 100644 --- a/test/integration/test/authoring/parity/callback-mode-scalars/expected.contract.json +++ b/test/integration/test/authoring/parity/callback-mode-scalars/expected.contract.json @@ -326,13 +326,6 @@ } ] }, - "operationTypes": { - "import": { - "alias": "PgVectorOperationTypes", - "named": "OperationTypes", - "package": "@prisma-next/extension-pgvector/operation-types" - } - }, "queryOperationTypes": { "import": { "alias": "PgVectorQueryOperationTypes", diff --git a/test/integration/test/authoring/parity/pgvector-named-type/expected.contract.json b/test/integration/test/authoring/parity/pgvector-named-type/expected.contract.json index 2a6a50cf63..0a1c895d62 100644 --- a/test/integration/test/authoring/parity/pgvector-named-type/expected.contract.json +++ b/test/integration/test/authoring/parity/pgvector-named-type/expected.contract.json @@ -118,13 +118,6 @@ } ] }, - "operationTypes": { - "import": { - "alias": "PgVectorOperationTypes", - "named": "OperationTypes", - "package": "@prisma-next/extension-pgvector/operation-types" - } - }, "queryOperationTypes": { "import": { "alias": "PgVectorQueryOperationTypes", diff --git a/test/integration/test/cli.emit.test.ts b/test/integration/test/cli.emit.test.ts index ef71d2601d..c93eba8d1c 100644 --- a/test/integration/test/cli.emit.test.ts +++ b/test/integration/test/cli.emit.test.ts @@ -4,11 +4,7 @@ import { dirname, join, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; import { loadContractFromTs } from '@prisma-next/cli'; import { emit } from '@prisma-next/emitter'; -import { - extractCodecTypeImports, - extractComponentIds, - extractOperationTypeImports, -} from '@prisma-next/family-sql/test-utils'; +import { extractCodecTypeImports, extractComponentIds } from '@prisma-next/family-sql/test-utils'; import { sqlEmission } from '@prisma-next/sql-contract-emitter'; import { timeouts } from '@prisma-next/test-utils'; import { afterEach, beforeEach, describe, expect, it } from 'vitest'; @@ -39,7 +35,6 @@ describe('emit command functionality', () => { const descriptors = [target, adapter, ...extensions]; return { codecTypeImports: extractCodecTypeImports(descriptors), - operationTypeImports: extractOperationTypeImports(descriptors), extensionIds: extractComponentIds({ id: 'sql' }, target, adapter, extensions), }; }; @@ -49,13 +44,12 @@ describe('emit command functionality', () => { async () => { const contractPath = join(fixturesDir, 'valid-contract.ts'); const contract = await loadContractFromTs(contractPath); - const { codecTypeImports, operationTypeImports, extensionIds } = buildEmitterArtifacts(); + const { codecTypeImports, extensionIds } = buildEmitterArtifacts(); const result = await emit( contract, { codecTypeImports, - operationTypeImports, extensionIds, }, sqlEmission, @@ -93,13 +87,12 @@ describe('emit command functionality', () => { async () => { const contractPath = join(fixturesDir, 'valid-contract.ts'); const contract = await loadContractFromTs(contractPath); - const { codecTypeImports, operationTypeImports, extensionIds } = buildEmitterArtifacts(); + const { codecTypeImports, extensionIds } = buildEmitterArtifacts(); const result = await emit( contract, { codecTypeImports, - operationTypeImports, extensionIds, }, sqlEmission, @@ -116,13 +109,12 @@ describe('emit command functionality', () => { const newOutputDir = join(tmpdir(), `prisma-next-test-new-${Date.now()}`); const contractPath = join(fixturesDir, 'valid-contract.ts'); const contract = await loadContractFromTs(contractPath); - const { codecTypeImports, operationTypeImports, extensionIds } = buildEmitterArtifacts(); + const { codecTypeImports, extensionIds } = buildEmitterArtifacts(); const result = await emit( contract, { codecTypeImports, - operationTypeImports, extensionIds, }, sqlEmission, diff --git a/test/integration/test/contract-imports.test.ts b/test/integration/test/contract-imports.test.ts index c5574335c4..f6b4b97941 100644 --- a/test/integration/test/contract-imports.test.ts +++ b/test/integration/test/contract-imports.test.ts @@ -7,11 +7,7 @@ import { promisify } from 'node:util'; import type { EmitStackInput } from '@prisma-next/emitter'; import { emit } from '@prisma-next/emitter'; import { createTestContract } from '@prisma-next/emitter/test/utils'; -import { - extractCodecTypeImports, - extractComponentIds, - extractOperationTypeImports, -} from '@prisma-next/family-sql/test-utils'; +import { extractCodecTypeImports, extractComponentIds } from '@prisma-next/family-sql/test-utils'; import { sqlEmission } from '@prisma-next/sql-contract-emitter'; import { timeouts } from '@prisma-next/test-utils'; import { afterEach, beforeEach, describe, expect, it } from 'vitest'; @@ -149,11 +145,9 @@ describe('contract.d.ts imports resolution', () => { const { adapter, target, extensions } = getSqlDescriptorBundle(); const allDescriptors = [target, adapter, ...extensions]; const codecTypeImports = extractCodecTypeImports(allDescriptors); - const operationTypeImports = extractOperationTypeImports(allDescriptors); const extensionIds = extractComponentIds({ id: 'sql' }, target, adapter, extensions); const options: EmitStackInput = { codecTypeImports, - operationTypeImports, extensionIds, }; @@ -284,11 +278,9 @@ type UserIdColumn = UserColumns['id']; const { adapter, target, extensions } = getSqlDescriptorBundle(); const allDescriptors = [target, adapter, ...extensions]; const codecTypeImports = extractCodecTypeImports(allDescriptors); - const operationTypeImports = extractOperationTypeImports(allDescriptors); const extensionIds = extractComponentIds({ id: 'sql' }, target, adapter, extensions); const options: EmitStackInput = { codecTypeImports, - operationTypeImports, extensionIds, }; diff --git a/test/integration/test/emitter.adapter-query-operation-types.test.ts b/test/integration/test/emitter.adapter-query-operation-types.test.ts index d9900c669e..cbdf7d5ff2 100644 --- a/test/integration/test/emitter.adapter-query-operation-types.test.ts +++ b/test/integration/test/emitter.adapter-query-operation-types.test.ts @@ -25,7 +25,6 @@ describe('emitter + postgres adapter descriptor', () => { ir, sqlEmission, [], - [], { storageHash: 'h', profileHash: 'p' }, { queryOperationTypeImports }, ); diff --git a/test/integration/test/fixtures/contract.d.ts b/test/integration/test/fixtures/contract.d.ts index 9866d738a4..3c3a34a19d 100644 --- a/test/integration/test/fixtures/contract.d.ts +++ b/test/integration/test/fixtures/contract.d.ts @@ -33,7 +33,6 @@ export type ProfileHash = ProfileHashBase<'sha256:1a8dbe044289f30a1de958fe800cc5a8378b285d2e126a8c44b58864bac2c18e'>; export type CodecTypes = PgTypes; -export type OperationTypes = Record; export type LaneCodecTypes = CodecTypes; export type QueryOperationTypes = PgAdapterQueryOps; type DefaultLiteralValue = CodecId extends keyof CodecTypes @@ -56,7 +55,6 @@ export type FieldInputTypes = { }; export type TypeMaps = TypeMapsType< CodecTypes, - OperationTypes, QueryOperationTypes, FieldOutputTypes, FieldInputTypes diff --git a/test/integration/test/mongo/fixtures/generated/contract.d.ts b/test/integration/test/mongo/fixtures/generated/contract.d.ts index e7ccb8eaed..b1594b18d8 100644 --- a/test/integration/test/mongo/fixtures/generated/contract.d.ts +++ b/test/integration/test/mongo/fixtures/generated/contract.d.ts @@ -19,7 +19,6 @@ export type ProfileHash = ProfileHashBase<'sha256:840de65fba7eb950a31487f74ee420b9c21205f38bce58579026747e0264e840'>; export type CodecTypes = MongoCodecTypes; -export type OperationTypes = Record; export type FieldOutputTypes = { readonly Address: { @@ -77,7 +76,7 @@ export type FieldInputTypes = { readonly email: CodecTypes['mongo/string@1']['input']; }; }; -export type TypeMaps = MongoTypeMaps; +export type TypeMaps = MongoTypeMaps; type ContractBase = ContractType< { diff --git a/test/integration/test/pgvector.test.ts b/test/integration/test/pgvector.test.ts index 672d221533..9bf4d49532 100644 --- a/test/integration/test/pgvector.test.ts +++ b/test/integration/test/pgvector.test.ts @@ -1,8 +1,5 @@ import pgvector from '@prisma-next/extension-pgvector/runtime'; -import { - extractCodecTypeImports, - extractOperationTypeImports, -} from '@prisma-next/family-sql/test-utils'; +import { extractCodecTypeImports } from '@prisma-next/family-sql/test-utils'; import { createCodecRegistry } from '@prisma-next/sql-relational-core/ast'; import { describe, expect, it } from 'vitest'; import { getSqlDescriptorBundle, pgvectorExtensionDescriptor } from '../utils/framework-components'; @@ -38,20 +35,6 @@ describe('pgvector extension pack integration', () => { }); }); - it('extracts operation type imports from descriptors', () => { - const { target, adapter, extensions } = getSqlDescriptorBundle({ - extensions: [pgvectorExtensionDescriptor], - }); - - const operationTypeImports = extractOperationTypeImports([target, adapter, ...extensions]); - expect(operationTypeImports.length).toBe(1); - expect(operationTypeImports[0]).toEqual({ - package: '@prisma-next/extension-pgvector/operation-types', - named: 'OperationTypes', - alias: 'PgVectorOperationTypes', - }); - }); - it('descriptor provides codecs', () => { const codecs = pgvector.codecs(); expect(codecs).toBeDefined(); @@ -65,13 +48,9 @@ describe('pgvector extension pack integration', () => { it('descriptor provides query operations', () => { const operations = pgvector.queryOperations!(); expect(operations).toBeDefined(); - expect(operations.length).toBe(2); - - const cosineDistanceOp = operations.find((op) => op.method === 'cosineDistance'); - expect(cosineDistanceOp).toBeDefined(); - - const cosineSimilarityOp = operations.find((op) => op.method === 'cosineSimilarity'); - expect(cosineSimilarityOp).toBeDefined(); + expect(Object.keys(operations).sort()).toEqual(['cosineDistance', 'cosineSimilarity']); + expect(operations['cosineDistance']).toBeDefined(); + expect(operations['cosineSimilarity']).toBeDefined(); }); it('codecs can be registered in registry', { timeout: 1_000 }, () => { diff --git a/test/integration/test/sql-builder/fixtures/generated/contract.d.ts b/test/integration/test/sql-builder/fixtures/generated/contract.d.ts index cf3dc10a45..c63e465718 100644 --- a/test/integration/test/sql-builder/fixtures/generated/contract.d.ts +++ b/test/integration/test/sql-builder/fixtures/generated/contract.d.ts @@ -15,7 +15,6 @@ import type { Timetz } from '@prisma-next/target-postgres/codec-types'; import type { Interval } from '@prisma-next/target-postgres/codec-types'; import type { CodecTypes as PgVectorTypes } from '@prisma-next/extension-pgvector/codec-types'; import type { Vector } from '@prisma-next/extension-pgvector/codec-types'; -import type { OperationTypes as PgVectorOperationTypes } from '@prisma-next/extension-pgvector/operation-types'; import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma-next/adapter-postgres/operation-types'; import type { QueryOperationTypes as PgVectorQueryOperationTypes } from '@prisma-next/extension-pgvector/operation-types'; @@ -38,7 +37,6 @@ export type ProfileHash = ProfileHashBase<'sha256:03c90a412dcfe182a475d25eae8cbf5c56fba67009defe8713eaf0b7fbd66b13'>; export type CodecTypes = PgTypes & PgVectorTypes; -export type OperationTypes = PgVectorOperationTypes; export type LaneCodecTypes = CodecTypes; export type QueryOperationTypes = PgAdapterQueryOps & PgVectorQueryOperationTypes; @@ -103,7 +101,6 @@ export type FieldInputTypes = { }; export type TypeMaps = TypeMapsType< CodecTypes, - OperationTypes, QueryOperationTypes, FieldOutputTypes, FieldInputTypes @@ -490,13 +487,6 @@ type ContractBase = ContractType< }, ]; }; - readonly operationTypes: { - readonly import: { - readonly alias: 'PgVectorOperationTypes'; - readonly named: 'OperationTypes'; - readonly package: '@prisma-next/extension-pgvector/operation-types'; - }; - }; readonly queryOperationTypes: { readonly import: { readonly alias: 'PgVectorQueryOperationTypes'; diff --git a/test/integration/test/sql-builder/fixtures/generated/contract.json b/test/integration/test/sql-builder/fixtures/generated/contract.json index 44fdcea5c7..efe5415ac1 100644 --- a/test/integration/test/sql-builder/fixtures/generated/contract.json +++ b/test/integration/test/sql-builder/fixtures/generated/contract.json @@ -533,13 +533,6 @@ } ] }, - "operationTypes": { - "import": { - "alias": "PgVectorOperationTypes", - "named": "OperationTypes", - "package": "@prisma-next/extension-pgvector/operation-types" - } - }, "queryOperationTypes": { "import": { "alias": "PgVectorQueryOperationTypes",