What problem are you trying to solve?
prismaContract(schemaPath, options) (@prisma/orm-family-sql, packages/2-sql/2-authoring/contract-psl/src/provider.ts:65-113) and mongoContract() (@prisma/orm-family-mongo) always readFile() their first argument — there's no way to hand them schema text directly:
|
export function prismaContract(schemaPath: string, options: PrismaContractOptions): ContractConfig { |
|
const source: PslInterpretCapable = { |
|
format: 'psl', |
|
inputs: [schemaPath], |
|
interpret(input, context) { |
|
const scalarColumnDescriptors: ReadonlyMap<string, ColumnDescriptor> = |
|
collectScalarTypeConstructors(context.authoringContributions.type); |
|
return interpretPslDocumentToSqlContract({ |
|
symbolTable: input.symbolTable, |
|
sourceFile: input.sourceFile, |
|
sourceId: input.sourceId, |
|
seedDiagnostics: [], |
|
target: options.target, |
|
authoringContributions: context.authoringContributions, |
|
scalarColumnDescriptors, |
|
...ifDefined( |
|
'composedExtensions', |
|
context.composedExtensions.length > 0 ? [...context.composedExtensions] : undefined, |
|
), |
|
composedExtensionContracts: context.composedExtensionContracts, |
|
...ifDefined( |
|
'composedExtensionPackRefs', |
|
options.composedExtensionPackRefs?.length ? options.composedExtensionPackRefs : undefined, |
|
), |
|
controlMutationDefaults: context.controlMutationDefaults, |
|
createNamespace: options.createNamespace, |
|
capabilities: context.capabilities, |
|
codecLookup: context.codecLookup, |
|
...ifDefined('enumInferenceCodecs', options.enumInferenceCodecs), |
|
}); |
|
}, |
|
async load(context) { |
|
const [absoluteSchemaPath] = context.resolvedInputs; |
|
if (absoluteSchemaPath === undefined) { |
|
throw new InternalError( |
|
'prismaContract: context.resolvedInputs is empty. The CLI config loader should populate it positional-matched with source.inputs.', |
|
); |
|
} |
|
let schema: string; |
|
try { |
|
schema = await readFile(absoluteSchemaPath, 'utf-8'); |
|
} catch (error) { |
|
const message = String(error); |
|
return notOk({ |
|
summary: `Failed to read Prisma schema at "${schemaPath}"`, |
|
diagnostics: [ |
|
{ |
|
code: 'PSL_SCHEMA_READ_FAILED', |
|
message, |
I maintain prisma-next-idb's sync layer, which needs to strip an IDB-only attribute (@idb.exclude) and append a synthetic Changelog model to a consumer's schema before handing it to defineConfig. Since prismaContract can't take that composed text directly, I have to write it to a generated file on disk just so there's something to readFile():
export default defineConfig({
contract: writeSqlSchemaWithSync('src/schema.prisma', 'src/schema.postgres.generated.prisma'),
// ...
});
Proposed solution
Accept schema text directly, e.g.:
prismaContract({ path } | { text }, options)
// or
prismaContract(schemaPath, { ...options, injectSchemaText?: (schema: string) => string })
Prior art: I already ship the injectSchemaText shape in my own IDB-family provider (prismaIdbContract()), where it runs on the raw text right before parse():
readonly injectSchemaText?: (schema: string) => string;
It's in production use today and the injected text flows through the normal parse → interpret → hash pipeline, so storageHash correctness isn't a new concern — it's the SQL/Mongo providers that are missing this, not a novel design. Happy to port it over as a PR.
Alternatives considered
Before filing, I checked whether the public builder DSL (typescriptContract/defineContract) could replace this — it can, but only for a schema authored entirely in TS. My case needs to keep an arbitrary, PSL-authored consumer schema untouched and splice in one extra model; there's no supported way to merge a builder-built Contract into a separately-parsed one, and prismaContract's extension-pack options (composedExtensionPackRefs) are for registering new PSL vocabulary, not injecting a plain model — using them here would be more machinery than the temp-file workaround it'd replace. The temp-file approach (above) is the only thing that currently works.
Scope and impact
- Touches
contract-psl in both the SQL and Mongo family packages (near-identical implementations).
- Additive only — no breaking change to the existing signature.
- No target-specific (Postgres/SQLite/Mongo) implications.
Happy to open a PR if this is worth landing.
What problem are you trying to solve?
prismaContract(schemaPath, options)(@prisma/orm-family-sql,packages/2-sql/2-authoring/contract-psl/src/provider.ts:65-113) andmongoContract()(@prisma/orm-family-mongo) alwaysreadFile()their first argument — there's no way to hand them schema text directly:prisma/packages/2-sql/2-authoring/contract-psl/src/provider.ts
Lines 65 to 113 in 9b75b95
I maintain
prisma-next-idb's sync layer, which needs to strip an IDB-only attribute (@idb.exclude) and append a syntheticChangelogmodel to a consumer's schema before handing it todefineConfig. SinceprismaContractcan't take that composed text directly, I have to write it to a generated file on disk just so there's something toreadFile():Proposed solution
Accept schema text directly, e.g.:
Prior art: I already ship the
injectSchemaTextshape in my own IDB-family provider (prismaIdbContract()), where it runs on the raw text right beforeparse():It's in production use today and the injected text flows through the normal parse → interpret → hash pipeline, so
storageHashcorrectness isn't a new concern — it's the SQL/Mongo providers that are missing this, not a novel design. Happy to port it over as a PR.Alternatives considered
Before filing, I checked whether the public builder DSL (
typescriptContract/defineContract) could replace this — it can, but only for a schema authored entirely in TS. My case needs to keep an arbitrary, PSL-authored consumer schema untouched and splice in one extra model; there's no supported way to merge a builder-builtContractinto a separately-parsed one, andprismaContract's extension-pack options (composedExtensionPackRefs) are for registering new PSL vocabulary, not injecting a plain model — using them here would be more machinery than the temp-file workaround it'd replace. The temp-file approach (above) is the only thing that currently works.Scope and impact
contract-pslin both the SQL and Mongo family packages (near-identical implementations).Happy to open a PR if this is worth landing.