
Product
Socket Firewall Now Blocks Malicious VS Code and Open VSX Extensions
Socket Firewall blocks malicious VS Code and Open VSX extensions before install, protecting developers from compromised editor marketplaces.
@prisma-next/sql-contract-ts
Advanced tools
SQL-specific TypeScript contract authoring surface for Prisma Next
Status: Current SQL TypeScript contract authoring surface
This package owns the SQL TypeScript authoring API for Prisma Next.
This package is part of the SQL family namespace (packages/2-sql/2-authoring/contract-ts) and provides:
defineContract(...)./contract-builder: field.column(...), field.generated(...), field.namedType(...), plus model(...) and rel.*field.id.uuidv7String(), field.text(), field.temporal.createdAt(), field.temporal.updatedAt(), plus pack-contributed entity-type helpers at top level alongside the built-in model / rel (e.g. enum({ name, values }))ContracttypescriptContract(...) for prisma-next.config.tsdescriptor.contractSerializer.deserializeContract(json))This is the current SQL TypeScript authoring implementation. Shared descriptor types live in @prisma-next/contract-authoring. Contract validation flows through the per-target descriptor's contractSerializer SPI (e.g. postgresTarget.contractSerializer.deserializeContract), or via the canonical façade (postgres<Contract>(...)).
./contract-builder exports the stable structural DSL (defineContract, field, model, rel)defineContract(config, (helpers) => ...) synthesizes helpers.field.* and helpers.type.* from the selected family, target, and extension packs@prisma-next/contract-authoring provides the target-neutral descriptor types used by the DSL and by authoring-adjacent packsContributor-facing lowering notes and detailed warning semantics live in DEVELOPING.md.
flowchart LR
builderInput[TypeScript contract input] --> sqlContractTs[@prisma-next/sql-contract-ts]
sqlContractTs --> authoringCore[@prisma-next/contract-authoring]
sqlContractTs --> sqlTypes[@prisma-next/sql-contract/types]
sqlContractTs --> contract[SQL Contract]
./contract-builder - SQL contract DSL (defineContract, field, model, rel)./config-types - typescriptContract(...) config helperDirect imports expose the base structural helpers. Use this surface when you want to author with explicit column descriptors, explicit generators, or named storage types.
Built-in ID helpers from @prisma-next/ids already return the generated-field spec accepted by field.generated(...), so field.generated(uuidv4()) is a valid structural DSL call.
import { textColumn, timestamptzColumn } from '@prisma-next/adapter-postgres/column-types';
import sqlFamily from '@prisma-next/family-sql/pack';
import { uuidv4 } from '@prisma-next/ids';
import { defineContract, field, model, rel } from '@prisma-next/sql-contract-ts/contract-builder';
import postgresPack from '@prisma-next/target-postgres/pack';
const User = model('User', {
fields: {
id: field.generated(uuidv4()).id(),
email: field.column(textColumn).unique(),
createdAt: field.column(timestamptzColumn).defaultSql('now()'),
},
})
.relations({
posts: rel.hasMany('Post', { by: 'userId' }),
})
.sql({
table: 'app_user',
});
const Post = model('Post', {
fields: {
id: field.generated(uuidv4()).id(),
userId: field.column(textColumn),
title: field.column(textColumn),
},
})
.relations({
user: rel.belongsTo(User, { from: 'userId', to: 'id' }),
})
.sql({
table: 'blog_post',
});
export const contract = defineContract({
family: sqlFamily,
target: postgresPack,
naming: { tables: 'snake_case', columns: 'snake_case' },
models: {
User,
Post,
},
});
Pack-provided helper presets are available through the callback overload. This is the surface that exposes field.id.*, field.text(), field.temporal.createdAt(), field.temporal.updatedAt(), type.sql.String(...), and extension helpers such as type.pgvector.Vector(...).
import pgvector from '@prisma-next/extension-pgvector/pack';
import sqlFamily from '@prisma-next/family-sql/pack';
import { defineContract, enumType, member } from '@prisma-next/sql-contract-ts/contract-builder';
import postgresPack from '@prisma-next/target-postgres/pack';
const pgText = { codecId: 'pg/text@1', nativeType: 'text' } as const;
const Role = enumType('role', pgText, member('USER', 'user'), member('ADMIN', 'admin'));
export const contract = defineContract(
{
family: sqlFamily,
target: postgresPack,
extensionPacks: { pgvector },
},
({ type, field, model, rel }) => {
const types = {
ShortName: type.sql.String(35),
Embedding1536: type.pgvector.Vector(1536),
} as const;
const User = model('User', {
fields: {
id: field.id.uuidv7String().sql({ id: { name: 'user_pkey' } }),
shortName: field.namedType(types.ShortName),
role: field.namedType(Role),
embedding: field.namedType(types.Embedding1536).optional(),
createdAt: field.temporal.createdAt(),
updatedAt: field.temporal.updatedAt(),
},
});
const Post = model('Post', {
fields: {
id: field.id.uuidv7String(),
authorId: field.uuidString(),
title: field.text(),
},
});
return {
enums: { role: Role },
types,
models: {
User: User.relations({
posts: rel.hasMany(Post, { by: 'authorId' }),
}).sql({
table: 'user',
}),
Post: Post.relations({
author: rel.belongsTo(User, { from: 'authorId', to: 'id' }),
}).sql({
table: 'post',
}),
},
};
},
);
Single-field constraints are usually most readable inline on the field, while compound constraints live in .attributes(...) or model-level .sql(...).
const Membership = model('Membership', {
fields: {
orgId: field.column(textColumn).column('org_id'),
userId: field.column(textColumn).column('user_id'),
role: field.column(textColumn),
},
})
.attributes(({ fields, constraints }) => ({
id: constraints.id([fields.orgId, fields.userId], { name: 'membership_pkey' }),
uniques: [
constraints.unique([fields.orgId, fields.role], {
name: 'membership_org_role_key',
}),
],
}))
.sql({ table: 'membership' });
field.column(...), field.generated(...), field.namedType(...), plus model(...) and rel.*field.id.uuidv4String(), field.id.uuidv7String(), field.id.nanoid({ size }), field.uuidString(), field.text(), field.timestamp(), field.temporal.createdAt(), field.temporal.updatedAt(), and type.* (Postgres also adds field.uuidNative(), field.id.uuidv4Native(), field.id.uuidv7Native() — these emit pg/uuid@1)field.temporal.createdAt() lowers to a target storage now() default, while field.temporal.updatedAt() lowers to the target-owned timestampNow execution default for create and non-empty update mutations.field.sql(...) and rel.belongsTo(...).sql({ fk })field.namedType(types.Role), User.refs.id, and User.ref('id') when those tokens are availableUse the root-level foreignKeyDefaults option when a contract wants non-default FK materialization:
const contract = defineContract({
family: sqlFamily,
target: postgresPack,
foreignKeyDefaults: { constraint: true, index: false },
models: {
// ...
},
});
Per-FK overrides still live next to the FK authoring site, either via constraints.foreignKey(...) inside model .sql(...) or via rel.belongsTo(...).sql({ fk: ... }). See ADR 161.
Contract JSON validation flows through the per-target descriptor's
contractSerializer SPI; this package focuses on authoring and lowering.
End-user app code typically goes through the canonical façade
(postgres<Contract>(...)), which threads the descriptor SPI internally.
import postgres from '@prisma-next/postgres/runtime';
import contractJson from './contract.json' with { type: 'json' };
import type { Contract, TypeMaps } from './contract.d';
const db = postgres<Contract, TypeMaps>({
contractJson,
url: process.env['DATABASE_URL']!,
});
For advanced consumers that need direct access to the SPI:
import postgresTarget from '@prisma-next/target-postgres/control';
import type { Contract } from './contract.d';
const contract = postgresTarget.contractSerializer.deserializeContract(
contractJson,
) as Contract;
Use typescriptContract from this package when wiring TS-authored contracts in prisma-next.config.ts.
import { defineConfig } from '@prisma-next/cli/config-types';
import { typescriptContract } from '@prisma-next/sql-contract-ts/config-types';
import { contract } from './src/prisma/contract';
export default defineConfig({
contract: typescriptContract(contract, 'src/prisma/contract.json'),
});
Optional third argument (options bag) for typescriptContract / typescriptContractFromPath, and defaultControlPolicy on emptyContract:
typescriptContract(contract, 'src/prisma/contract.json', { defaultControlPolicy: 'external' });
The specifier value applies only when the loaded contract omits defaultControlPolicy (a value authored on the contract module wins).
@prisma-next/config - ContractConfig types used by typescriptContract(...)@prisma-next/contract-authoring - Shared descriptor types@prisma-next/framework-components - Pack refs, authoring contributions, and codec lookup types@prisma-next/sql-contract - SQL contract types and validation targetUnit tests for the authoring DSL live in this package. Broader integration tests that span authoring, emission, CLI, and runtime packages live in @prisma-next/integration-tests.
@prisma-next/sql-contract-tscontractSerializer.deserializeContract(...) (or via the canonical façade)@prisma-next/contract-authoring - Shared target-neutral authoring descriptor types@prisma-next/sql-contract-psl - PSL parser-output to SQL contract interpreter@prisma-next/sql-contract-psl/provider - SQL PSL-first prismaContract() helperFAQs
SQL-specific TypeScript contract authoring surface for Prisma Next
The npm package @prisma-next/sql-contract-ts receives a total of 10,001 weekly downloads. As such, @prisma-next/sql-contract-ts popularity was classified as popular.
We found that @prisma-next/sql-contract-ts demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Socket Firewall blocks malicious VS Code and Open VSX extensions before install, protecting developers from compromised editor marketplaces.

Research
More than 140 Mastra npm packages were compromised in a supply chain attack that used a typosquatted dependency to deliver a cross-platform infostealer during installation.

Research
/Security News
A new npm package tests AI malware scanners with prompt injection, safety-triggering comments, context flooding, and obfuscated JavaScript.