Prisma Migrate
Declarative data modeling & schema migrations
-
Quickstart
+
Quickstart
•
Website
•
diff --git a/packages/migrate/package.json b/packages/migrate/package.json
index a96d7423388d..7191b5e3cb49 100644
--- a/packages/migrate/package.json
+++ b/packages/migrate/package.json
@@ -54,7 +54,7 @@
"@prisma/config": "workspace:*",
"@prisma/debug": "workspace:*",
"@prisma/driver-adapter-utils": "workspace:*",
- "@prisma/engines-version": "7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735",
+ "@prisma/engines-version": "7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57",
"@prisma/generator": "workspace:*",
"@prisma/get-platform": "workspace:*",
"@prisma/internals": "workspace:*",
diff --git a/packages/param-graph-builder/README.md b/packages/param-graph-builder/README.md
new file mode 100644
index 000000000000..58a6231cc1f2
--- /dev/null
+++ b/packages/param-graph-builder/README.md
@@ -0,0 +1,9 @@
+# @prisma/param-graph-builder
+
+This package is intended for Prisma's internal use.
+
+Builds a ParamGraph from DMMF (Data Model Metadata Format) at client generation time.
+
+The ParamGraph is a compact data structure that enables schema-aware parameterization at runtime. It stores only parameterizable paths and uses a string table to de-duplicate field names.
+
+This package is used by both `@prisma/client-generator-js` and `@prisma/client-generator-ts` to generate the parameterization schema that is embedded in the generated Prisma Client.
diff --git a/packages/param-graph-builder/helpers/build.ts b/packages/param-graph-builder/helpers/build.ts
new file mode 100644
index 000000000000..5350df5ceb8e
--- /dev/null
+++ b/packages/param-graph-builder/helpers/build.ts
@@ -0,0 +1,4 @@
+import { build } from '../../../helpers/compile/build'
+import { unbundledConfig } from '../../../helpers/compile/configs'
+
+void build(unbundledConfig)
diff --git a/packages/param-graph-builder/package.json b/packages/param-graph-builder/package.json
new file mode 100644
index 000000000000..9659179ad7c2
--- /dev/null
+++ b/packages/param-graph-builder/package.json
@@ -0,0 +1,39 @@
+{
+ "name": "@prisma/param-graph-builder",
+ "version": "0.0.0",
+ "description": "This package is intended for Prisma's internal use",
+ "main": "dist/index.js",
+ "module": "dist/index.mjs",
+ "types": "dist/index.d.ts",
+ "exports": {
+ ".": {
+ "require": {
+ "types": "./dist/index.d.ts",
+ "default": "./dist/index.js"
+ },
+ "import": {
+ "types": "./dist/index.d.ts",
+ "default": "./dist/index.mjs"
+ }
+ }
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/prisma/prisma.git",
+ "directory": "packages/param-graph-builder"
+ },
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@prisma/dmmf": "workspace:*",
+ "@prisma/param-graph": "workspace:*"
+ },
+ "scripts": {
+ "dev": "DEV=true tsx helpers/build.ts",
+ "build": "tsx helpers/build.ts",
+ "prepublishOnly": "pnpm run build"
+ },
+ "files": [
+ "dist"
+ ],
+ "sideEffects": false
+}
diff --git a/packages/param-graph-builder/src/build-param-graph.ts b/packages/param-graph-builder/src/build-param-graph.ts
new file mode 100644
index 000000000000..2a7359c43368
--- /dev/null
+++ b/packages/param-graph-builder/src/build-param-graph.ts
@@ -0,0 +1,41 @@
+/**
+ * Entry point for building ParamGraph from DMMF.
+ *
+ * This module provides the main API for client generators to build
+ * parameterization schemas from DMMF at generation time.
+ */
+
+import type * as DMMF from '@prisma/dmmf'
+import type { ParamGraphData, SerializedParamGraph } from '@prisma/param-graph'
+
+import { DMMFTraverser } from './dmmf-traverser'
+import { ParamGraphBuilder } from './param-graph-builder'
+
+/**
+ * Builds a ParamGraphData from DMMF schema.
+ *
+ * @param dmmf - The DMMF document from the schema
+ * @returns The param graph data structure
+ */
+export function buildParamGraph(dmmf: DMMF.Document): ParamGraphData {
+ const builder = new ParamGraphBuilder()
+ const traverser = new DMMFTraverser(builder, dmmf)
+ traverser.processRoots(dmmf.mappings.modelOperations)
+ return builder.build()
+}
+
+/**
+ * Builds and serializes a ParamGraph from DMMF schema.
+ *
+ * This is the primary API for generators - it returns the compact
+ * serialized format ready to be embedded in generated clients.
+ *
+ * @param dmmf - The DMMF document from the schema
+ * @returns The serialized param graph
+ */
+export function buildAndSerializeParamGraph(dmmf: DMMF.Document): SerializedParamGraph {
+ const builder = new ParamGraphBuilder()
+ const traverser = new DMMFTraverser(builder, dmmf)
+ traverser.processRoots(dmmf.mappings.modelOperations)
+ return builder.buildAndSerialize()
+}
diff --git a/packages/param-graph-builder/src/dmmf-traverser.ts b/packages/param-graph-builder/src/dmmf-traverser.ts
new file mode 100644
index 000000000000..01392db517e7
--- /dev/null
+++ b/packages/param-graph-builder/src/dmmf-traverser.ts
@@ -0,0 +1,453 @@
+/**
+ * DMMFTraverser: DMMF traversal logic for building ParamGraph.
+ *
+ * This class contains the traversal algorithms that walk DMMF structures
+ * and build the param graph. It uses ParamGraphBuilder for allocation
+ * and caching.
+ */
+
+import type * as DMMF from '@prisma/dmmf'
+import { ModelAction } from '@prisma/dmmf'
+import type { InputEdgeData, OutputEdgeData } from '@prisma/param-graph'
+import { EdgeFlag, scalarTypeToMask } from '@prisma/param-graph'
+
+import type { NodeId, ParamGraphBuilder } from './param-graph-builder'
+
+interface PendingInputNode {
+ nodeId: NodeId
+ fields: readonly DMMF.SchemaArg[]
+}
+
+interface PendingUnionNode {
+ nodeId: NodeId
+ typeNames: string[]
+}
+
+/**
+ * Traverses DMMF and populates a ParamGraphBuilder.
+ */
+export class DMMFTraverser {
+ readonly #builder: ParamGraphBuilder
+ readonly #inputTypeMap: Map
+ readonly #outputTypeMap: Map
+
+ readonly #pendingInputNodes: PendingInputNode[] = []
+ readonly #pendingUnionNodes: PendingUnionNode[] = []
+
+ constructor(builder: ParamGraphBuilder, dmmf: DMMF.Document) {
+ this.#builder = builder
+ this.#inputTypeMap = new Map()
+ this.#outputTypeMap = new Map()
+
+ // Collect all input types
+ for (const inputType of dmmf.schema.inputObjectTypes.prisma ?? []) {
+ this.#inputTypeMap.set(getTypeName(inputType.name, 'prisma'), inputType)
+ }
+ for (const inputType of dmmf.schema.inputObjectTypes.model ?? []) {
+ this.#inputTypeMap.set(getTypeName(inputType.name, 'model'), inputType)
+ }
+
+ // Collect all output types
+ for (const outputType of dmmf.schema.outputObjectTypes.prisma ?? []) {
+ this.#outputTypeMap.set(getTypeName(outputType.name, 'prisma'), outputType)
+ }
+ for (const outputType of dmmf.schema.outputObjectTypes.model ?? []) {
+ this.#outputTypeMap.set(getTypeName(outputType.name, 'model'), outputType)
+ }
+ }
+
+ /**
+ * Process all root operations from model mappings.
+ */
+ processRoots(mappings: readonly DMMF.ModelMapping[]): void {
+ for (const mapping of mappings) {
+ const modelName = mapping.model
+ const actions = Object.keys(ModelAction) as `${ModelAction}`[]
+
+ for (const action of actions) {
+ const fieldName = mapping[action]
+ if (!fieldName) continue
+
+ const rootField = this.#findRootField(fieldName)
+ if (!rootField) continue
+
+ const argsNodeId = this.buildInputNodeFromArgs(rootField.args)
+
+ let outputNodeId: NodeId | undefined
+ if (rootField.outputType.location === 'outputObjectTypes') {
+ outputNodeId = this.buildOutputTypeNode(
+ getTypeName(rootField.outputType.type, rootField.outputType.namespace),
+ )
+ }
+
+ const dmmfActionToJsonAction: Partial> = {
+ create: 'createOne',
+ update: 'updateOne',
+ delete: 'deleteOne',
+ upsert: 'upsertOne',
+ }
+
+ const jsonAction = dmmfActionToJsonAction[action] ?? action
+ const rootKey = `${modelName}.${jsonAction}`
+
+ this.#builder.setRoot(rootKey, {
+ argsNodeId,
+ outputNodeId,
+ })
+ }
+ }
+
+ // Process all queued work iteratively to avoid stack overflow
+ this.#drainPendingWork()
+ }
+
+ /**
+ * Iteratively processes all pending input and union nodes.
+ * This avoids deep recursion that can cause stack overflow on complex schemas.
+ */
+ #drainPendingWork(): void {
+ while (this.#pendingInputNodes.length > 0 || this.#pendingUnionNodes.length > 0) {
+ // Process pending input nodes
+ while (this.#pendingInputNodes.length > 0) {
+ const pending = this.#pendingInputNodes.pop()!
+ this.#processInputNodeFields(pending.nodeId, pending.fields)
+ }
+
+ // Process pending union nodes
+ while (this.#pendingUnionNodes.length > 0) {
+ const pending = this.#pendingUnionNodes.pop()!
+ this.#processUnionNodeFields(pending.nodeId, pending.typeNames)
+ }
+ }
+ }
+
+ #findRootField(fieldName: string): DMMF.SchemaField | undefined {
+ const queryType = this.#outputTypeMap.get('prisma.Query')
+ if (queryType) {
+ const field = queryType.fields.find((f) => f.name === fieldName)
+ if (field) return field
+ }
+
+ const mutationType = this.#outputTypeMap.get('prisma.Mutation')
+ if (mutationType) {
+ const field = mutationType.fields.find((f) => f.name === fieldName)
+ if (field) return field
+ }
+
+ return undefined
+ }
+
+ /**
+ * Builds an input node from schema arguments.
+ */
+ buildInputNodeFromArgs(args: readonly DMMF.SchemaArg[]): NodeId | undefined {
+ const edges: Record = {}
+ let hasAnyEdge = false
+
+ for (const arg of args) {
+ const edge = this.#mergeFieldVariants([arg])
+ if (edge) {
+ const stringIndex = this.#builder.internString(arg.name)
+ edges[stringIndex] = edge
+ hasAnyEdge = true
+ }
+ }
+
+ if (!hasAnyEdge) {
+ return undefined
+ }
+
+ const nodeId = this.#builder.allocateInputNode()
+ this.#builder.setInputNodeEdges(nodeId, edges)
+ return nodeId
+ }
+
+ /**
+ * Builds an input node for a named input type.
+ * Node allocation happens immediately, but field processing is deferred
+ * to avoid deep recursion.
+ */
+ buildInputTypeNode(typeName: string): NodeId | undefined {
+ if (this.#builder.hasInputTypeNode(typeName)) {
+ return this.#builder.getInputTypeNode(typeName)
+ }
+
+ const inputType = this.#inputTypeMap.get(typeName)
+ if (!inputType) {
+ this.#builder.setInputTypeNode(typeName, undefined)
+ return undefined
+ }
+
+ // Pre-allocate node to handle cycles
+ const nodeId = this.#builder.allocateInputNode()
+ this.#builder.setInputTypeNode(typeName, nodeId)
+
+ // Queue field processing for later to avoid deep recursion
+ this.#pendingInputNodes.push({ nodeId, fields: inputType.fields })
+
+ return nodeId
+ }
+
+ /**
+ * Process fields for an input node (called from drainPendingWork).
+ */
+ #processInputNodeFields(nodeId: NodeId, fields: readonly DMMF.SchemaArg[]): void {
+ const edges: Record = {}
+ let hasAnyEdge = false
+
+ for (const field of fields) {
+ const edge = this.#mergeFieldVariants([field])
+ if (edge) {
+ const stringIndex = this.#builder.internString(field.name)
+ edges[stringIndex] = edge
+ hasAnyEdge = true
+ }
+ }
+
+ if (hasAnyEdge) {
+ this.#builder.setInputNodeEdges(nodeId, edges)
+ }
+ }
+
+ /**
+ * Builds a union node for multiple input types.
+ * Node allocation happens immediately, but field processing is deferred
+ * to avoid deep recursion.
+ */
+ buildUnionNode(typeNames: string[]): NodeId | undefined {
+ // Sort type names for stable cache key
+ const sortedNames = [...typeNames].sort()
+ const cacheKey = sortedNames.join('|')
+
+ if (this.#builder.hasUnionNode(cacheKey)) {
+ return this.#builder.getUnionNode(cacheKey)
+ }
+
+ // Pre-allocate node
+ const nodeId = this.#builder.allocateInputNode()
+ this.#builder.setUnionNode(cacheKey, nodeId)
+
+ // Queue field processing for later to avoid deep recursion
+ this.#pendingUnionNodes.push({ nodeId, typeNames })
+
+ return nodeId
+ }
+
+ /**
+ * Process fields for a union node (called from drainPendingWork).
+ */
+ #processUnionNodeFields(nodeId: NodeId, typeNames: string[]): void {
+ // Collect all fields from all variants
+ const fieldsByName = new Map()
+
+ for (const typeName of typeNames) {
+ const inputType = this.#inputTypeMap.get(typeName)
+ if (!inputType) continue
+
+ for (const field of inputType.fields) {
+ let fieldsForName = fieldsByName.get(field.name)
+ if (!fieldsForName) {
+ fieldsForName = []
+ fieldsByName.set(field.name, fieldsForName)
+ }
+ fieldsForName.push(field)
+ }
+ }
+
+ // Merge fields conservatively
+ const mergedEdges: Record = {}
+ let hasAnyEdge = false
+
+ for (const [fieldName, variantFields] of fieldsByName) {
+ const mergedEdge = this.#mergeFieldVariants(variantFields)
+ if (mergedEdge) {
+ const stringIndex = this.#builder.internString(fieldName)
+ mergedEdges[stringIndex] = mergedEdge
+ hasAnyEdge = true
+ }
+ }
+
+ if (hasAnyEdge) {
+ this.#builder.setInputNodeEdges(nodeId, mergedEdges)
+ }
+ }
+
+ /**
+ * Merges field variants to produce a single edge descriptor.
+ * This is the most complex part of the traversal - it handles
+ * union types and determines what kinds of values a field accepts.
+ */
+ #mergeFieldVariants(variants: readonly DMMF.SchemaArg[]): InputEdgeData | undefined {
+ let flags = 0
+ let scalarMask = 0
+ let childNodeId: NodeId | undefined
+ let enumNameIndex: number | undefined
+
+ const scalarTypes: DMMF.InputTypeRef[] = []
+ const enumTypes: DMMF.InputTypeRef[] = []
+ const inputObjectTypes: DMMF.InputTypeRef[] = []
+
+ for (const variant of variants) {
+ for (const inputType of variant.inputTypes) {
+ switch (inputType.location) {
+ case 'scalar':
+ if (variant.isParameterizable) {
+ scalarTypes.push(inputType)
+ }
+ break
+ case 'enumTypes':
+ if (variant.isParameterizable) {
+ enumTypes.push(inputType)
+ }
+ break
+ case 'inputObjectTypes':
+ if (
+ !inputObjectTypes.some(
+ (ot) =>
+ ot.type === inputType.type && ot.namespace === inputType.namespace && ot.isList === inputType.isList,
+ )
+ ) {
+ inputObjectTypes.push(inputType)
+ }
+ break
+ case 'fieldRefTypes':
+ break
+ default:
+ throw new Error(`Invalid location ${inputType.location satisfies never}`)
+ }
+ }
+ }
+
+ // Process scalar types
+ for (const st of scalarTypes) {
+ scalarMask |= scalarTypeToMask(st.type)
+ if (st.isList) {
+ flags |= EdgeFlag.ParamListScalar
+ } else {
+ flags |= EdgeFlag.ParamScalar
+ }
+ }
+
+ // Process enum types
+ for (const et of enumTypes) {
+ if (et.namespace === 'model') {
+ // Enum names are now stored in the main string table
+ enumNameIndex = this.#builder.internString(et.type)
+ if (et.isList) {
+ flags |= EdgeFlag.ParamListEnum
+ } else {
+ flags |= EdgeFlag.ParamEnum
+ }
+ break
+ }
+ }
+
+ // Process input object types
+ if (inputObjectTypes.length > 0) {
+ const hasObjectList = inputObjectTypes.some((iot) => iot.isList)
+ const hasSingleObject = inputObjectTypes.some((iot) => !iot.isList)
+
+ if (hasObjectList) {
+ flags |= EdgeFlag.ListObject
+ }
+ if (hasSingleObject) {
+ flags |= EdgeFlag.Object
+ }
+
+ if (inputObjectTypes.length === 1) {
+ childNodeId = this.buildInputTypeNode(getTypeName(inputObjectTypes[0].type, inputObjectTypes[0].namespace))
+ } else {
+ childNodeId = this.buildUnionNode(inputObjectTypes.map((iot) => getTypeName(iot.type, iot.namespace)))
+ }
+ }
+
+ // If no flags are set, this field is not parameterizable
+ if (flags === 0) {
+ return undefined
+ }
+
+ const edge: InputEdgeData = { flags }
+ if (childNodeId !== undefined) {
+ edge.childNodeId = childNodeId
+ }
+ if (scalarMask !== 0) {
+ edge.scalarMask = scalarMask
+ }
+ if (enumNameIndex !== undefined) {
+ edge.enumNameIndex = enumNameIndex
+ }
+
+ return edge
+ }
+
+ /**
+ * Builds an output node for a named output type.
+ */
+ buildOutputTypeNode(typeName: string): NodeId | undefined {
+ if (this.#builder.hasOutputTypeNode(typeName)) {
+ return this.#builder.getOutputTypeNode(typeName)
+ }
+
+ const outputType = this.#outputTypeMap.get(typeName)
+ if (!outputType) {
+ this.#builder.setOutputTypeNode(typeName, undefined)
+ return undefined
+ }
+
+ // Pre-allocate to handle cycles
+ const nodeId = this.#builder.allocateOutputNode()
+ this.#builder.setOutputTypeNode(typeName, nodeId)
+
+ const edges: Record = {}
+ let hasAnyEdge = false
+
+ for (const field of outputType.fields) {
+ const edge = this.#buildOutputEdge(field)
+ if (edge) {
+ const stringIndex = this.#builder.internString(field.name)
+ edges[stringIndex] = edge
+ hasAnyEdge = true
+ }
+ }
+
+ if (hasAnyEdge) {
+ this.#builder.setOutputNodeEdges(nodeId, edges)
+ }
+
+ return nodeId
+ }
+
+ #buildOutputEdge(field: DMMF.SchemaField): OutputEdgeData | undefined {
+ let argsNodeId: NodeId | undefined
+ let outputNodeId: NodeId | undefined
+
+ if (field.args.length > 0) {
+ argsNodeId = this.buildInputNodeFromArgs(field.args)
+ }
+
+ if (field.outputType.location === 'outputObjectTypes') {
+ outputNodeId = this.buildOutputTypeNode(getTypeName(field.outputType.type, field.outputType.namespace))
+ }
+
+ if (argsNodeId === undefined && outputNodeId === undefined) {
+ return undefined
+ }
+
+ const edge: OutputEdgeData = {}
+ if (argsNodeId !== undefined) {
+ edge.argsNodeId = argsNodeId
+ }
+ if (outputNodeId !== undefined) {
+ edge.outputNodeId = outputNodeId
+ }
+
+ return edge
+ }
+}
+
+function getTypeName(name: string, namespace: string | undefined): string {
+ if (namespace === undefined) {
+ return name
+ }
+ return `${namespace}.${name}`
+}
diff --git a/packages/param-graph-builder/src/index.ts b/packages/param-graph-builder/src/index.ts
new file mode 100644
index 000000000000..a056a8ca57d9
--- /dev/null
+++ b/packages/param-graph-builder/src/index.ts
@@ -0,0 +1,4 @@
+export { buildAndSerializeParamGraph, buildParamGraph } from './build-param-graph'
+export { DMMFTraverser } from './dmmf-traverser'
+export type { NodeId } from './param-graph-builder'
+export { ParamGraphBuilder } from './param-graph-builder'
diff --git a/packages/param-graph-builder/src/param-graph-builder.ts b/packages/param-graph-builder/src/param-graph-builder.ts
new file mode 100644
index 000000000000..eb319f82c9d2
--- /dev/null
+++ b/packages/param-graph-builder/src/param-graph-builder.ts
@@ -0,0 +1,156 @@
+/**
+ * ParamGraphBuilder: Data holder for building ParamGraph.
+ *
+ * This class manages allocation and caching during graph construction.
+ * The actual traversal logic is in DMMFTraverser.
+ */
+
+import type {
+ InputEdgeData,
+ InputNodeData,
+ OutputEdgeData,
+ OutputNodeData,
+ ParamGraphData,
+ RootEntryData,
+ SerializedParamGraph,
+} from '@prisma/param-graph'
+import { serializeParamGraph } from '@prisma/param-graph'
+
+export type NodeId = number
+
+/**
+ * Builder class that accumulates graph data during construction.
+ */
+export class ParamGraphBuilder {
+ readonly #stringTable: string[] = []
+ readonly #stringToIndex = new Map()
+ readonly #inputNodes: InputNodeData[] = []
+ readonly #outputNodes: OutputNodeData[] = []
+ readonly #roots: Record = {}
+
+ readonly #inputTypeNodeCache = new Map()
+ readonly #unionNodeCache = new Map()
+ readonly #outputTypeNodeCache = new Map()
+
+ /**
+ * Interns a string into the string table, returning its index.
+ * Both field names and enum names go through this method.
+ */
+ internString(str: string): number {
+ let index = this.#stringToIndex.get(str)
+ if (index === undefined) {
+ index = this.#stringTable.length
+ this.#stringTable.push(str)
+ this.#stringToIndex.set(str, index)
+ }
+ return index
+ }
+
+ /**
+ * Allocates a new input node and returns its ID.
+ */
+ allocateInputNode(): NodeId {
+ const id = this.#inputNodes.length
+ this.#inputNodes.push({ edges: {} })
+ return id
+ }
+
+ /**
+ * Sets edges on an input node.
+ */
+ setInputNodeEdges(nodeId: NodeId, edges: Record): void {
+ if (Object.keys(edges).length > 0) {
+ this.#inputNodes[nodeId].edges = edges
+ }
+ }
+
+ /**
+ * Allocates a new output node and returns its ID.
+ */
+ allocateOutputNode(): NodeId {
+ const id = this.#outputNodes.length
+ this.#outputNodes.push({ edges: {} })
+ return id
+ }
+
+ /**
+ * Sets edges on an output node.
+ */
+ setOutputNodeEdges(nodeId: NodeId, edges: Record): void {
+ if (Object.keys(edges).length > 0) {
+ this.#outputNodes[nodeId].edges = edges
+ }
+ }
+
+ /**
+ * Records a root entry for an operation.
+ */
+ setRoot(key: string, entry: RootEntryData): void {
+ if (entry.argsNodeId !== undefined || entry.outputNodeId !== undefined) {
+ // Intern the root key into the string table for binary serialization
+ this.internString(key)
+ this.#roots[key] = entry
+ }
+ }
+
+ // Cache methods for input type nodes
+
+ getInputTypeNode(typeName: string): NodeId | undefined {
+ return this.#inputTypeNodeCache.get(typeName)
+ }
+
+ setInputTypeNode(typeName: string, nodeId: NodeId | undefined): void {
+ this.#inputTypeNodeCache.set(typeName, nodeId)
+ }
+
+ hasInputTypeNode(typeName: string): boolean {
+ return this.#inputTypeNodeCache.has(typeName)
+ }
+
+ // Cache methods for union nodes
+
+ getUnionNode(key: string): NodeId | undefined {
+ return this.#unionNodeCache.get(key)
+ }
+
+ setUnionNode(key: string, nodeId: NodeId | undefined): void {
+ this.#unionNodeCache.set(key, nodeId)
+ }
+
+ hasUnionNode(key: string): boolean {
+ return this.#unionNodeCache.has(key)
+ }
+
+ // Cache methods for output type nodes
+
+ getOutputTypeNode(typeName: string): NodeId | undefined {
+ return this.#outputTypeNodeCache.get(typeName)
+ }
+
+ setOutputTypeNode(typeName: string, nodeId: NodeId | undefined): void {
+ this.#outputTypeNodeCache.set(typeName, nodeId)
+ }
+
+ hasOutputTypeNode(typeName: string): boolean {
+ return this.#outputTypeNodeCache.has(typeName)
+ }
+
+ /**
+ * Builds the final ParamGraphData structure.
+ */
+ build(): ParamGraphData {
+ return {
+ strings: this.#stringTable,
+ inputNodes: this.#inputNodes,
+ outputNodes: this.#outputNodes,
+ roots: this.#roots,
+ }
+ }
+
+ /**
+ * Builds and serializes to the compact binary format.
+ */
+ buildAndSerialize(): SerializedParamGraph {
+ return serializeParamGraph(this.build())
+ }
+}
diff --git a/packages/param-graph-builder/tsconfig.build.json b/packages/param-graph-builder/tsconfig.build.json
new file mode 100644
index 000000000000..1eae4ca25256
--- /dev/null
+++ b/packages/param-graph-builder/tsconfig.build.json
@@ -0,0 +1,7 @@
+{
+ "extends": "../../tsconfig.build.regular.json",
+ "compilerOptions": {
+ "outDir": "dist"
+ },
+ "include": ["src"]
+}
diff --git a/packages/param-graph-builder/tsconfig.json b/packages/param-graph-builder/tsconfig.json
new file mode 100644
index 000000000000..63e20a2cf0b8
--- /dev/null
+++ b/packages/param-graph-builder/tsconfig.json
@@ -0,0 +1,4 @@
+{
+ "extends": "../../tsconfig.json",
+ "include": ["./**/*"]
+}
diff --git a/packages/param-graph/README.md b/packages/param-graph/README.md
new file mode 100644
index 000000000000..49c5f169b5b5
--- /dev/null
+++ b/packages/param-graph/README.md
@@ -0,0 +1,17 @@
+# @prisma/param-graph
+
+This package is intended for Prisma's internal use.
+
+Contains the ParamGraph types and utilities for schema-aware query parameterization in Prisma Client.
+
+ParamGraph is a compact data structure generated from DMMF (Data Model Metadata Format) at client generation time. It enables precise, schema-driven parameterization of query values at runtime.
+
+## Contents
+
+- `ParamGraph` - The main type representing the compact schema
+- `InputNode` / `OutputNode` - Node types for input arguments and output selections
+- `InputEdge` / `OutputEdge` - Edge types describing field capabilities
+- `EdgeFlag` - Bit flags for input field capabilities
+- `ScalarMask` - Bit mask for scalar type categories
+- `scalarTypeToMask` - Maps DMMF scalar type names to mask values
+- `hasFlag` / `getScalarMask` - Helper functions for edge inspection
diff --git a/packages/param-graph/helpers/build.ts b/packages/param-graph/helpers/build.ts
new file mode 100644
index 000000000000..5350df5ceb8e
--- /dev/null
+++ b/packages/param-graph/helpers/build.ts
@@ -0,0 +1,4 @@
+import { build } from '../../../helpers/compile/build'
+import { unbundledConfig } from '../../../helpers/compile/configs'
+
+void build(unbundledConfig)
diff --git a/packages/param-graph/package.json b/packages/param-graph/package.json
new file mode 100644
index 000000000000..c4892602f273
--- /dev/null
+++ b/packages/param-graph/package.json
@@ -0,0 +1,36 @@
+{
+ "name": "@prisma/param-graph",
+ "version": "0.0.0",
+ "description": "This package is intended for Prisma's internal use",
+ "main": "dist/index.js",
+ "module": "dist/index.mjs",
+ "types": "dist/index.d.ts",
+ "exports": {
+ ".": {
+ "require": {
+ "types": "./dist/index.d.ts",
+ "default": "./dist/index.js"
+ },
+ "import": {
+ "types": "./dist/index.d.ts",
+ "default": "./dist/index.mjs"
+ }
+ }
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/prisma/prisma.git",
+ "directory": "packages/param-graph"
+ },
+ "license": "Apache-2.0",
+ "scripts": {
+ "dev": "DEV=true tsx helpers/build.ts",
+ "build": "tsx helpers/build.ts",
+ "prepublishOnly": "pnpm run build",
+ "test": "vitest run"
+ },
+ "files": [
+ "dist"
+ ],
+ "sideEffects": false
+}
diff --git a/packages/param-graph/src/index.ts b/packages/param-graph/src/index.ts
new file mode 100644
index 000000000000..3914da22abc3
--- /dev/null
+++ b/packages/param-graph/src/index.ts
@@ -0,0 +1,14 @@
+export type { EnumLookup, InputEdge, InputNode, OutputEdge, OutputNode, RootEntry } from './param-graph'
+export type {
+ InputEdgeData,
+ InputNodeData,
+ OutputEdgeData,
+ OutputNodeData,
+ ParamGraphData,
+ RootEntryData,
+} from './param-graph'
+export type { EdgeFlagValue, ScalarMaskValue } from './param-graph'
+export { ParamGraph } from './param-graph'
+export { EdgeFlag, getScalarMask, hasFlag, ScalarMask, scalarTypeToMask } from './param-graph'
+export type { SerializedParamGraph } from './serialization'
+export { deserializeParamGraph, serializeParamGraph } from './serialization'
diff --git a/packages/param-graph/src/param-graph.ts b/packages/param-graph/src/param-graph.ts
new file mode 100644
index 000000000000..61617a37674a
--- /dev/null
+++ b/packages/param-graph/src/param-graph.ts
@@ -0,0 +1,327 @@
+/**
+ * ParamGraph: Runtime class for schema-aware parameterization.
+ *
+ * This class provides a readable API for navigating the param graph structure
+ * at runtime. It's created once per PrismaClient instance from the serialized
+ * format embedded in the generated client.
+ */
+
+import type { SerializedParamGraph } from './serialization'
+import { deserializeParamGraph } from './serialization'
+import type {
+ InputEdgeData,
+ InputNodeData,
+ OutputEdgeData,
+ OutputNodeData,
+ ParamGraphData,
+ RootEntryData,
+} from './types'
+
+/**
+ * Function type for looking up enum values by name.
+ * This allows ParamGraph to remain decoupled from RuntimeDataModel.
+ */
+export type EnumLookup = (enumName: string) => readonly string[] | undefined
+
+/**
+ * Readable view of root entry.
+ */
+export interface RootEntry {
+ readonly argsNodeId: number | undefined
+ readonly outputNodeId: number | undefined
+}
+
+/**
+ * Readable view of input node.
+ */
+export interface InputNode {
+ readonly id: number
+}
+
+/**
+ * Readable view of output node.
+ */
+export interface OutputNode {
+ readonly id: number
+}
+
+/**
+ * Readable view of input edge.
+ */
+export interface InputEdge {
+ readonly flags: number
+ readonly childNodeId: number | undefined
+ readonly scalarMask: number
+ readonly enumNameIndex: number | undefined
+}
+
+/**
+ * Readable view of output edge.
+ */
+export interface OutputEdge {
+ readonly argsNodeId: number | undefined
+ readonly outputNodeId: number | undefined
+}
+
+/**
+ * ParamGraph provides runtime access to the schema information
+ * needed for parameterization decisions.
+ */
+export class ParamGraph {
+ readonly #data: ParamGraphData
+ readonly #stringIndex: Map
+ readonly #enumLookup: EnumLookup
+
+ private constructor(data: ParamGraphData, enumLookup: EnumLookup) {
+ this.#data = data
+ this.#enumLookup = enumLookup
+
+ // Build string-to-index map for O(1) lookups
+ this.#stringIndex = new Map()
+ for (let i = 0; i < data.strings.length; i++) {
+ this.#stringIndex.set(data.strings[i], i)
+ }
+ }
+
+ /**
+ * Creates a ParamGraph from serialized format.
+ * This is the primary factory method for runtime use.
+ */
+ static deserialize(serialized: SerializedParamGraph, enumLookup: EnumLookup): ParamGraph {
+ const data = deserializeParamGraph(serialized)
+ return new ParamGraph(data, enumLookup)
+ }
+
+ /**
+ * Creates a ParamGraph from builder data.
+ * Used by the builder for testing and direct construction.
+ */
+ static fromData(data: ParamGraphData, enumLookup: EnumLookup): ParamGraph {
+ return new ParamGraph(data, enumLookup)
+ }
+
+ /**
+ * Look up a root entry by "Model.action" or "action".
+ */
+ root(key: string): RootEntry | undefined {
+ const entry = this.#data.roots[key]
+ if (!entry) {
+ return undefined
+ }
+ return {
+ argsNodeId: entry.argsNodeId,
+ outputNodeId: entry.outputNodeId,
+ }
+ }
+
+ /**
+ * Get an input node by ID.
+ */
+ inputNode(id: number | undefined): InputNode | undefined {
+ if (id === undefined || id < 0 || id >= this.#data.inputNodes.length) {
+ return undefined
+ }
+ return { id }
+ }
+
+ /**
+ * Get an output node by ID.
+ */
+ outputNode(id: number | undefined): OutputNode | undefined {
+ if (id === undefined || id < 0 || id >= this.#data.outputNodes.length) {
+ return undefined
+ }
+ return { id }
+ }
+
+ /**
+ * Get an input edge for a field name within a node.
+ */
+ inputEdge(node: InputNode | undefined, fieldName: string): InputEdge | undefined {
+ if (!node) {
+ return undefined
+ }
+
+ const nodeData = this.#data.inputNodes[node.id]
+ if (!nodeData) {
+ return undefined
+ }
+
+ const fieldIndex = this.#stringIndex.get(fieldName)
+ if (fieldIndex === undefined) {
+ return undefined
+ }
+
+ const edge = nodeData.edges[fieldIndex]
+ if (!edge) {
+ return undefined
+ }
+
+ return {
+ flags: edge.flags,
+ childNodeId: edge.childNodeId,
+ scalarMask: edge.scalarMask ?? 0,
+ enumNameIndex: edge.enumNameIndex,
+ }
+ }
+
+ /**
+ * Get an output edge for a field name within a node.
+ */
+ outputEdge(node: OutputNode | undefined, fieldName: string): OutputEdge | undefined {
+ if (!node) {
+ return undefined
+ }
+
+ const nodeData = this.#data.outputNodes[node.id]
+ if (!nodeData) {
+ return undefined
+ }
+
+ const fieldIndex = this.#stringIndex.get(fieldName)
+ if (fieldIndex === undefined) {
+ return undefined
+ }
+
+ const edge = nodeData.edges[fieldIndex]
+ if (!edge) {
+ return undefined
+ }
+
+ return {
+ argsNodeId: edge.argsNodeId,
+ outputNodeId: edge.outputNodeId,
+ }
+ }
+
+ /**
+ * Get enum values for an edge that references a user enum.
+ * Returns undefined if the edge doesn't reference an enum.
+ */
+ enumValues(edge: InputEdge | undefined): readonly string[] | undefined {
+ if (edge?.enumNameIndex === undefined) {
+ return undefined
+ }
+
+ const enumName = this.#data.strings[edge.enumNameIndex]
+ if (!enumName) {
+ return undefined
+ }
+
+ return this.#enumLookup(enumName)
+ }
+
+ /**
+ * Get a string from the string table by index.
+ */
+ getString(index: number): string | undefined {
+ return this.#data.strings[index]
+ }
+}
+
+/**
+ * Bit flags for InputEdge.flags describing what the field accepts.
+ */
+export const EdgeFlag = {
+ /**
+ * Field may be parameterized as a scalar value.
+ * Check ScalarMask to validate the value type.
+ */
+ ParamScalar: 1,
+
+ /**
+ * Field may be parameterized as an enum.
+ * Check enum ID to validate the value type.
+ */
+ ParamEnum: 2,
+
+ /**
+ * Field accepts list-of-scalar values.
+ * Parameterize the whole list if all elements match ScalarMask.
+ */
+ ParamListScalar: 4,
+
+ /**
+ * Field accepts list-of-enum values.
+ * Parameterize the whole list if all elements match enum ID.
+ */
+ ParamListEnum: 8,
+
+ /**
+ * Field accepts list-of-object values.
+ * Recurse into each element using the child node.
+ */
+ ListObject: 16,
+
+ /**
+ * Field accepts object values.
+ * Recurse into child input node.
+ */
+ Object: 32,
+} as const
+
+export type EdgeFlagValue = (typeof EdgeFlag)[keyof typeof EdgeFlag]
+
+/**
+ * Bit mask for scalar type categories.
+ * Used in InputEdge.scalarMask to validate runtime value types.
+ */
+export const ScalarMask = {
+ String: 1,
+ Int: 2,
+ BigInt: 4,
+ Float: 8,
+ Decimal: 16,
+ Boolean: 32,
+ DateTime: 64,
+ Json: 128,
+ Bytes: 256,
+} as const
+
+export type ScalarMaskValue = (typeof ScalarMask)[keyof typeof ScalarMask]
+
+/**
+ * Helper function to check if an edge has a specific flag.
+ */
+export function hasFlag(edge: InputEdge, flag: number): boolean {
+ return (edge.flags & flag) !== 0
+}
+
+/**
+ * Helper function to get the scalar mask from an edge.
+ */
+export function getScalarMask(edge: InputEdge): number {
+ return edge.scalarMask
+}
+
+/**
+ * Maps DMMF scalar type names to ScalarMask values.
+ */
+export function scalarTypeToMask(typeName: string): number {
+ switch (typeName) {
+ case 'String':
+ case 'UUID':
+ return ScalarMask.String
+ case 'Int':
+ return ScalarMask.Int
+ case 'BigInt':
+ return ScalarMask.BigInt
+ case 'Float':
+ return ScalarMask.Float
+ case 'Decimal':
+ return ScalarMask.Decimal
+ case 'Boolean':
+ return ScalarMask.Boolean
+ case 'DateTime':
+ return ScalarMask.DateTime
+ case 'Json':
+ return ScalarMask.Json
+ case 'Bytes':
+ return ScalarMask.Bytes
+ default:
+ return 0
+ }
+}
+
+// Re-export data types for builder use
+export type { InputEdgeData, InputNodeData, OutputEdgeData, OutputNodeData, ParamGraphData, RootEntryData }
diff --git a/packages/param-graph/src/serialization.test.ts b/packages/param-graph/src/serialization.test.ts
new file mode 100644
index 000000000000..66585fa44c33
--- /dev/null
+++ b/packages/param-graph/src/serialization.test.ts
@@ -0,0 +1,206 @@
+import { describe, expect, test } from 'vitest'
+
+import { deserializeParamGraph, serializeParamGraph } from './serialization'
+import type { ParamGraphData } from './types'
+
+describe('param-graph serialization', () => {
+ test('roundtrip with empty data', () => {
+ const data: ParamGraphData = {
+ strings: ['root1'],
+ inputNodes: [],
+ outputNodes: [],
+ roots: { root1: {} },
+ }
+
+ const serialized = serializeParamGraph(data)
+ const deserialized = deserializeParamGraph(serialized)
+
+ expect(deserialized.strings).toEqual(data.strings)
+ expect(deserialized.inputNodes).toEqual(data.inputNodes)
+ expect(deserialized.outputNodes).toEqual(data.outputNodes)
+ expect(deserialized.roots).toEqual(data.roots)
+ })
+
+ test('roundtrip with small data', () => {
+ const data: ParamGraphData = {
+ strings: ['findMany', 'where', 'id'],
+ inputNodes: [{ edges: { 1: { flags: 0, scalarMask: 1 } } }],
+ outputNodes: [{ edges: { 2: { argsNodeId: 0 } } }],
+ roots: { findMany: { argsNodeId: 0, outputNodeId: 0 } },
+ }
+
+ const serialized = serializeParamGraph(data)
+ const deserialized = deserializeParamGraph(serialized)
+
+ expect(deserialized.strings).toEqual(data.strings)
+ expect(deserialized.inputNodes.length).toBe(data.inputNodes.length)
+ expect(deserialized.outputNodes.length).toBe(data.outputNodes.length)
+ expect(Object.keys(deserialized.roots)).toEqual(Object.keys(data.roots))
+ })
+
+ test('roundtrip with multiple nodes and edges', () => {
+ const data: ParamGraphData = {
+ strings: ['findMany', 'create', 'update', 'where', 'data', 'id', 'name', 'Status'],
+ inputNodes: [
+ { edges: { 3: { flags: 1, scalarMask: 1, childNodeId: 1 }, 4: { flags: 0, scalarMask: 2 } } },
+ { edges: { 5: { flags: 2, enumNameIndex: 7 } } },
+ ],
+ outputNodes: [{ edges: { 6: { argsNodeId: 0, outputNodeId: 1 } } }, { edges: {} }],
+ roots: {
+ findMany: { argsNodeId: 0, outputNodeId: 0 },
+ create: { argsNodeId: 1, outputNodeId: 1 },
+ update: { argsNodeId: 0 },
+ },
+ }
+
+ const serialized = serializeParamGraph(data)
+ const deserialized = deserializeParamGraph(serialized)
+
+ expect(deserialized.inputNodes.length).toBe(2)
+ expect(deserialized.outputNodes.length).toBe(2)
+ expect(Object.keys(deserialized.roots).length).toBe(3)
+
+ // Verify edge data is preserved
+ const inputEdge = deserialized.inputNodes[0].edges[3]
+ expect(inputEdge.flags).toBe(1)
+ expect(inputEdge.scalarMask).toBe(1)
+ expect(inputEdge.childNodeId).toBe(1)
+
+ const enumEdge = deserialized.inputNodes[1].edges[5]
+ expect(enumEdge.flags).toBe(2)
+ expect(enumEdge.enumNameIndex).toBe(7)
+ })
+
+ test('handles undefined values correctly', () => {
+ const data: ParamGraphData = {
+ strings: ['root'],
+ inputNodes: [{ edges: { 0: { flags: 0 } } }],
+ outputNodes: [{ edges: { 0: {} } }],
+ roots: { root: { argsNodeId: 0 } },
+ }
+
+ const serialized = serializeParamGraph(data)
+ const deserialized = deserializeParamGraph(serialized)
+
+ // Undefined values should not be present in deserialized data
+ expect(deserialized.inputNodes[0].edges[0].childNodeId).toBeUndefined()
+ expect(deserialized.inputNodes[0].edges[0].scalarMask).toBeUndefined()
+ expect(deserialized.inputNodes[0].edges[0].enumNameIndex).toBeUndefined()
+ expect(deserialized.outputNodes[0].edges[0].argsNodeId).toBeUndefined()
+ expect(deserialized.outputNodes[0].edges[0].outputNodeId).toBeUndefined()
+ expect(deserialized.roots['root'].outputNodeId).toBeUndefined()
+ })
+
+ test('base64url encoding produces URL-safe output', () => {
+ const data: ParamGraphData = {
+ strings: ['test'],
+ inputNodes: [{ edges: { 255: { flags: 255, scalarMask: 65535, childNodeId: 0, enumNameIndex: 0 } } }],
+ outputNodes: [],
+ roots: { test: { argsNodeId: 0 } },
+ }
+
+ const serialized = serializeParamGraph(data)
+
+ // Should only contain URL-safe characters
+ expect(serialized.graph).toMatch(/^[A-Za-z0-9_-]+$/)
+ })
+
+ test('handles large indices requiring multi-byte varints (128-16383)', () => {
+ // Generate enough strings to require 2-byte varints (>127)
+ const strings = Array.from({ length: 200 }, (_, i) => `field${i}`)
+ const data: ParamGraphData = {
+ strings,
+ inputNodes: [
+ {
+ edges: {
+ // Use indices that require 2-byte encoding (128+)
+ 128: { flags: 1, childNodeId: 150 },
+ 150: { flags: 2, enumNameIndex: 180 },
+ },
+ },
+ ],
+ outputNodes: [{ edges: { 199: { argsNodeId: 0, outputNodeId: 0 } } }],
+ roots: { field0: { argsNodeId: 0, outputNodeId: 0 } },
+ }
+
+ const serialized = serializeParamGraph(data)
+ const deserialized = deserializeParamGraph(serialized)
+
+ expect(deserialized.inputNodes[0].edges[128].flags).toBe(1)
+ expect(deserialized.inputNodes[0].edges[128].childNodeId).toBe(150)
+ expect(deserialized.inputNodes[0].edges[150].flags).toBe(2)
+ expect(deserialized.inputNodes[0].edges[150].enumNameIndex).toBe(180)
+ expect(deserialized.outputNodes[0].edges[199].argsNodeId).toBe(0)
+ expect(deserialized.outputNodes[0].edges[199].outputNodeId).toBe(0)
+ })
+
+ test('handles very large indices requiring 3-byte varints (16384+)', () => {
+ // Generate enough strings to require 3-byte varints (>16383)
+ const strings = Array.from({ length: 17000 }, (_, i) => `f${i}`)
+ const data: ParamGraphData = {
+ strings,
+ inputNodes: [
+ {
+ edges: {
+ 16384: { flags: 1, childNodeId: 16500 },
+ },
+ },
+ ],
+ outputNodes: [{ edges: { 16999: { argsNodeId: 0, outputNodeId: 0 } } }],
+ roots: { f0: { argsNodeId: 0, outputNodeId: 0 } },
+ }
+
+ const serialized = serializeParamGraph(data)
+ const deserialized = deserializeParamGraph(serialized)
+
+ expect(deserialized.inputNodes[0].edges[16384].flags).toBe(1)
+ expect(deserialized.inputNodes[0].edges[16384].childNodeId).toBe(16500)
+ expect(deserialized.outputNodes[0].edges[16999].argsNodeId).toBe(0)
+ })
+
+ test('varint boundary values encode and decode correctly', () => {
+ // Test values at varint encoding boundaries
+ const boundaryValues = [0, 1, 127, 128, 16383, 16384]
+
+ for (const value of boundaryValues) {
+ // Create strings to make the index value valid
+ const strings = Array.from({ length: Math.max(value + 1, 2) }, (_, i) => `s${i}`)
+
+ const data: ParamGraphData = {
+ strings,
+ inputNodes: [{ edges: { [value]: { flags: 0 } } }],
+ outputNodes: [],
+ roots: { s0: {} },
+ }
+
+ const serialized = serializeParamGraph(data)
+ const deserialized = deserializeParamGraph(serialized)
+
+ expect(deserialized.inputNodes[0].edges[value]).toBeDefined()
+ expect(deserialized.inputNodes[0].edges[value].flags).toBe(0)
+ }
+ })
+
+ test('optional value 0 is correctly distinguished from undefined', () => {
+ const data: ParamGraphData = {
+ strings: ['root', 'field'],
+ inputNodes: [
+ { edges: { 1: { flags: 0, childNodeId: 0 } } }, // childNodeId = 0 (not undefined)
+ ],
+ outputNodes: [
+ { edges: { 1: { argsNodeId: 0, outputNodeId: 0 } } }, // both are 0 (not undefined)
+ ],
+ roots: { root: { argsNodeId: 0, outputNodeId: 0 } }, // both are 0 (not undefined)
+ }
+
+ const serialized = serializeParamGraph(data)
+ const deserialized = deserializeParamGraph(serialized)
+
+ // Value 0 should be preserved, not converted to undefined
+ expect(deserialized.inputNodes[0].edges[1].childNodeId).toBe(0)
+ expect(deserialized.outputNodes[0].edges[1].argsNodeId).toBe(0)
+ expect(deserialized.outputNodes[0].edges[1].outputNodeId).toBe(0)
+ expect(deserialized.roots['root'].argsNodeId).toBe(0)
+ expect(deserialized.roots['root'].outputNodeId).toBe(0)
+ })
+})
diff --git a/packages/param-graph/src/serialization.ts b/packages/param-graph/src/serialization.ts
new file mode 100644
index 000000000000..dd9a94d1d1a1
--- /dev/null
+++ b/packages/param-graph/src/serialization.ts
@@ -0,0 +1,431 @@
+/**
+ * Binary serialization for ParamGraph.
+ *
+ * This module handles compact binary encoding/decoding of the param graph structure.
+ * The format uses a hybrid approach: JSON string array for field names + binary blob
+ * for structural data (nodes, edges, roots).
+ *
+ * ## Serialized Representation
+ *
+ * ```
+ * SerializedParamGraph {
+ * strings: string[] // String table (field names, enum names, root keys)
+ * graph: string // Base64url-encoded binary blob
+ * }
+ * ```
+ *
+ * ## Why Hybrid?
+ *
+ * - **Strings stay as JSON**: V8's JSON.parse is highly optimized for string arrays
+ * - **Structure goes binary**: Indices, flags, masks benefit from compact encoding
+ * - **Best of both**: Fast parsing + compact size where it matters
+ *
+ * ## Variable-Length Encoding
+ *
+ * All integer values (except fixed-size fields like `scalarMask` and `flags`) use
+ * unsigned LEB128 (Little Endian Base 128) variable-length encoding:
+ *
+ * - Values 0-127: 1 byte
+ * - Values 128-16383: 2 bytes
+ * - Values 16384-2097151: 3 bytes
+ * - And so on...
+ *
+ * Optional values use value+1 encoding: 0 means "none/undefined", N+1 means actual value N.
+ *
+ * ## Binary Blob Layout
+ *
+ * ```
+ * ┌───────────────────────────────────────────────────────────────────┐
+ * │ HEADER │
+ * ├───────────────────────────────────────────────────────────────────┤
+ * │ inputNodeCount: varuint │
+ * │ outputNodeCount: varuint │
+ * │ rootCount: varuint │
+ * └───────────────────────────────────────────────────────────────────┘
+ *
+ * ┌───────────────────────────────────────────────────────────────────┐
+ * │ INPUT NODES (repeated inputNodeCount times) │
+ * ├───────────────────────────────────────────────────────────────────┤
+ * │ edgeCount: varuint │
+ * │ edges[] │
+ * └───────────────────────────────────────────────────────────────────┘
+ *
+ * ┌───────────────────────────────────────────────────────────────────┐
+ * │ INPUT EDGE │
+ * ├───────────────────────────────────────────────────────────────────┤
+ * │ fieldIndex: varuint │
+ * │ scalarMask: u16 │
+ * │ childNodeId: varuint (0=none, N+1=actual) │
+ * │ enumNameIndex: varuint (0=none, N+1=actual) │
+ * │ flags: u8 │
+ * └───────────────────────────────────────────────────────────────────┘
+ *
+ * ┌───────────────────────────────────────────────────────────────────┐
+ * │ OUTPUT NODES (repeated outputNodeCount times) │
+ * ├───────────────────────────────────────────────────────────────────┤
+ * │ edgeCount: varuint │
+ * │ edges[] │
+ * └───────────────────────────────────────────────────────────────────┘
+ *
+ * ┌───────────────────────────────────────────────────────────────────┐
+ * │ OUTPUT EDGE │
+ * ├───────────────────────────────────────────────────────────────────┤
+ * │ fieldIndex: varuint │
+ * │ argsNodeId: varuint (0=none, N+1=actual) │
+ * │ outputNodeId: varuint (0=none, N+1=actual) │
+ * └───────────────────────────────────────────────────────────────────┘
+ *
+ * ┌───────────────────────────────────────────────────────────────────┐
+ * │ ROOTS (repeated rootCount times) │
+ * ├───────────────────────────────────────────────────────────────────┤
+ * │ keyIndex: varuint │
+ * │ argsNodeId: varuint (0=none, N+1=actual) │
+ * │ outputNodeId: varuint (0=none, N+1=actual) │
+ * └───────────────────────────────────────────────────────────────────┘
+ * ```
+ *
+ * ## Embedding in Generated Client
+ *
+ * ```js
+ * config.parameterizationSchema = {
+ * strings: JSON.parse('["where","id","email",...]'),
+ * graph: "base64url_encoded_binary_blob..."
+ * }
+ * ```
+ */
+
+import type {
+ InputEdgeData,
+ InputNodeData,
+ OutputEdgeData,
+ OutputNodeData,
+ ParamGraphData,
+ RootEntryData,
+} from './types'
+
+/**
+ * Serialized format stored in the generated client.
+ */
+export interface SerializedParamGraph {
+ /** String table (field names, enum names, root keys) */
+ strings: string[]
+ /** Base64url-encoded binary blob for structural data */
+ graph: string
+}
+
+/**
+ * Serializes a ParamGraphData to the compact binary format.
+ */
+export function serializeParamGraph(data: ParamGraphData): SerializedParamGraph {
+ return new Serializer(data).serialize()
+}
+
+/**
+ * Deserializes a binary-encoded ParamGraph.
+ */
+export function deserializeParamGraph(serialized: SerializedParamGraph): ParamGraphData {
+ return new Deserializer(serialized).deserialize()
+}
+
+function encodeBase64url(bytes: Uint8Array): string {
+ return Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString('base64url')
+}
+
+function decodeBase64url(str: string): Uint8Array {
+ return Buffer.from(str, 'base64url')
+}
+
+/**
+ * Calculates the number of bytes needed to encode a value as an unsigned LEB128 varint.
+ */
+function varuintSize(value: number): number {
+ let size = 1
+ while (value >= 0x80) {
+ size++
+ value >>>= 7
+ }
+ return size
+}
+
+class Serializer {
+ #data: ParamGraphData
+ #buffer: ArrayBuffer
+ #view: DataView
+ #offset: number = 0
+ #rootKeys: string[]
+
+ constructor(data: ParamGraphData) {
+ this.#data = data
+ this.#rootKeys = Object.keys(data.roots)
+
+ const size = this.#calculateBufferSize()
+ this.#buffer = new ArrayBuffer(size)
+ this.#view = new DataView(this.#buffer)
+ }
+
+ serialize(): SerializedParamGraph {
+ this.#writeHeader()
+ this.#writeInputNodes()
+ this.#writeOutputNodes()
+ this.#writeRoots()
+
+ return {
+ strings: this.#data.strings,
+ graph: encodeBase64url(new Uint8Array(this.#buffer, 0, this.#offset)),
+ }
+ }
+
+ #writeVaruint(value: number): void {
+ while (value >= 0x80) {
+ this.#view.setUint8(this.#offset++, (value & 0x7f) | 0x80)
+ value >>>= 7
+ }
+ this.#view.setUint8(this.#offset++, value)
+ }
+
+ #writeOptionalVaruint(value: number | undefined): void {
+ this.#writeVaruint(value === undefined ? 0 : value + 1)
+ }
+
+ #writeByte(value: number): void {
+ this.#view.setUint8(this.#offset, value)
+ this.#offset += 1
+ }
+
+ #writeU16(value: number): void {
+ this.#view.setUint16(this.#offset, value, true)
+ this.#offset += 2
+ }
+
+ #calculateBufferSize(): number {
+ let size = 0
+
+ // Header: 3 varints
+ size += varuintSize(this.#data.inputNodes.length)
+ size += varuintSize(this.#data.outputNodes.length)
+ size += varuintSize(this.#rootKeys.length)
+
+ for (const node of this.#data.inputNodes) {
+ const fieldIndices = Object.keys(node.edges).map(Number)
+ size += varuintSize(fieldIndices.length)
+
+ for (const fieldIndex of fieldIndices) {
+ const edge = node.edges[fieldIndex]
+ size += varuintSize(fieldIndex)
+ size += 2 // scalarMask: u16
+ size += varuintSize(edge.childNodeId === undefined ? 0 : edge.childNodeId + 1)
+ size += varuintSize(edge.enumNameIndex === undefined ? 0 : edge.enumNameIndex + 1)
+ size += 1 // flags: u8
+ }
+ }
+
+ for (const node of this.#data.outputNodes) {
+ const fieldIndices = Object.keys(node.edges).map(Number)
+ size += varuintSize(fieldIndices.length)
+
+ for (const fieldIndex of fieldIndices) {
+ const edge = node.edges[fieldIndex]
+ size += varuintSize(fieldIndex)
+ size += varuintSize(edge.argsNodeId === undefined ? 0 : edge.argsNodeId + 1)
+ size += varuintSize(edge.outputNodeId === undefined ? 0 : edge.outputNodeId + 1)
+ }
+ }
+
+ for (const key of this.#rootKeys) {
+ const root = this.#data.roots[key]
+ const keyIndex = this.#data.strings.indexOf(key)
+ size += varuintSize(keyIndex)
+ size += varuintSize(root.argsNodeId === undefined ? 0 : root.argsNodeId + 1)
+ size += varuintSize(root.outputNodeId === undefined ? 0 : root.outputNodeId + 1)
+ }
+
+ return size
+ }
+
+ #writeHeader(): void {
+ this.#writeVaruint(this.#data.inputNodes.length)
+ this.#writeVaruint(this.#data.outputNodes.length)
+ this.#writeVaruint(this.#rootKeys.length)
+ }
+
+ #writeInputNodes(): void {
+ for (const node of this.#data.inputNodes) {
+ const fieldIndices = Object.keys(node.edges).map(Number)
+ this.#writeVaruint(fieldIndices.length)
+
+ for (const fieldIndex of fieldIndices) {
+ const edge = node.edges[fieldIndex]
+
+ this.#writeVaruint(fieldIndex)
+ this.#writeU16(edge.scalarMask ?? 0)
+ this.#writeOptionalVaruint(edge.childNodeId)
+ this.#writeOptionalVaruint(edge.enumNameIndex)
+ this.#writeByte(edge.flags)
+ }
+ }
+ }
+
+ #writeOutputNodes(): void {
+ for (const node of this.#data.outputNodes) {
+ const fieldIndices = Object.keys(node.edges).map(Number)
+ this.#writeVaruint(fieldIndices.length)
+
+ for (const fieldIndex of fieldIndices) {
+ const edge = node.edges[fieldIndex]
+
+ this.#writeVaruint(fieldIndex)
+ this.#writeOptionalVaruint(edge.argsNodeId)
+ this.#writeOptionalVaruint(edge.outputNodeId)
+ }
+ }
+ }
+
+ #writeRoots(): void {
+ for (const key of this.#rootKeys) {
+ const root = this.#data.roots[key]
+ const keyIndex = this.#data.strings.indexOf(key)
+ if (keyIndex === -1) {
+ throw new Error(`Root key "${key}" not found in strings table`)
+ }
+
+ this.#writeVaruint(keyIndex)
+ this.#writeOptionalVaruint(root.argsNodeId)
+ this.#writeOptionalVaruint(root.outputNodeId)
+ }
+ }
+}
+
+class Deserializer {
+ #serialized: SerializedParamGraph
+ #view: DataView
+ #offset: number = 0
+
+ constructor(serialized: SerializedParamGraph) {
+ this.#serialized = serialized
+ const bytes = decodeBase64url(serialized.graph)
+ this.#view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)
+ }
+
+ deserialize(): ParamGraphData {
+ const { inputNodeCount, outputNodeCount, rootCount } = this.#readHeader()
+ const inputNodes = this.#readInputNodes(inputNodeCount)
+ const outputNodes = this.#readOutputNodes(outputNodeCount)
+ const roots = this.#readRoots(rootCount)
+
+ return {
+ strings: this.#serialized.strings,
+ inputNodes,
+ outputNodes,
+ roots,
+ }
+ }
+
+ #readVaruint(): number {
+ let value = 0
+ let shift = 0
+ let byte: number
+ do {
+ byte = this.#view.getUint8(this.#offset++)
+ value |= (byte & 0x7f) << shift
+ shift += 7
+ } while (byte >= 0x80)
+ return value
+ }
+
+ #readOptionalVaruint(): number | undefined {
+ const value = this.#readVaruint()
+ return value === 0 ? undefined : value - 1
+ }
+
+ #readByte(): number {
+ const value = this.#view.getUint8(this.#offset)
+ this.#offset += 1
+ return value
+ }
+
+ #readU16(): number {
+ const value = this.#view.getUint16(this.#offset, true)
+ this.#offset += 2
+ return value
+ }
+
+ #readHeader(): { inputNodeCount: number; outputNodeCount: number; rootCount: number } {
+ const inputNodeCount = this.#readVaruint()
+ const outputNodeCount = this.#readVaruint()
+ const rootCount = this.#readVaruint()
+
+ return { inputNodeCount, outputNodeCount, rootCount }
+ }
+
+ #readInputNodes(count: number): InputNodeData[] {
+ const inputNodes: InputNodeData[] = []
+
+ for (let i = 0; i < count; i++) {
+ const edgeCount = this.#readVaruint()
+ const edges: Record = {}
+
+ for (let j = 0; j < edgeCount; j++) {
+ const fieldIndex = this.#readVaruint()
+ const scalarMask = this.#readU16()
+ const childNodeId = this.#readOptionalVaruint()
+ const enumNameIndex = this.#readOptionalVaruint()
+ const flags = this.#readByte()
+
+ const edge: InputEdgeData = { flags }
+ if (scalarMask !== 0) edge.scalarMask = scalarMask
+ if (childNodeId !== undefined) edge.childNodeId = childNodeId
+ if (enumNameIndex !== undefined) edge.enumNameIndex = enumNameIndex
+
+ edges[fieldIndex] = edge
+ }
+
+ inputNodes.push({ edges })
+ }
+
+ return inputNodes
+ }
+
+ #readOutputNodes(count: number): OutputNodeData[] {
+ const outputNodes: OutputNodeData[] = []
+
+ for (let i = 0; i < count; i++) {
+ const edgeCount = this.#readVaruint()
+ const edges: Record = {}
+
+ for (let j = 0; j < edgeCount; j++) {
+ const fieldIndex = this.#readVaruint()
+ const argsNodeId = this.#readOptionalVaruint()
+ const outputNodeId = this.#readOptionalVaruint()
+
+ const edge: OutputEdgeData = {}
+ if (argsNodeId !== undefined) edge.argsNodeId = argsNodeId
+ if (outputNodeId !== undefined) edge.outputNodeId = outputNodeId
+
+ edges[fieldIndex] = edge
+ }
+
+ outputNodes.push({ edges })
+ }
+
+ return outputNodes
+ }
+
+ #readRoots(count: number): Record {
+ const roots: Record = {}
+
+ for (let i = 0; i < count; i++) {
+ const keyIndex = this.#readVaruint()
+ const argsNodeId = this.#readOptionalVaruint()
+ const outputNodeId = this.#readOptionalVaruint()
+
+ const key = this.#serialized.strings[keyIndex]
+ const root: RootEntryData = {}
+ if (argsNodeId !== undefined) root.argsNodeId = argsNodeId
+ if (outputNodeId !== undefined) root.outputNodeId = outputNodeId
+
+ roots[key] = root
+ }
+
+ return roots
+ }
+}
diff --git a/packages/param-graph/src/types.ts b/packages/param-graph/src/types.ts
new file mode 100644
index 000000000000..d3a991d9386a
--- /dev/null
+++ b/packages/param-graph/src/types.ts
@@ -0,0 +1,79 @@
+/**
+ * Internal data types for ParamGraph.
+ *
+ * These types represent the in-memory structure of the param graph,
+ * used both during building and after deserialization.
+ */
+
+/**
+ * Complete param graph data structure.
+ * This is the internal representation, not the serialized format.
+ */
+export interface ParamGraphData {
+ /** String table containing field names and enum names */
+ strings: string[]
+
+ /** Input nodes for argument objects and input types */
+ inputNodes: InputNodeData[]
+
+ /** Output nodes for selection traversal */
+ outputNodes: OutputNodeData[]
+
+ /** Root mapping: "Model.action" -> entry */
+ roots: Record
+}
+
+/**
+ * Input node data: describes parameterizable fields in an input object.
+ */
+export interface InputNodeData {
+ /** Map from string-table index to edge descriptor */
+ edges: Record
+}
+
+/**
+ * Output node data: describes fields in a selection set.
+ */
+export interface OutputNodeData {
+ /** Map from string-table index to edge descriptor */
+ edges: Record
+}
+
+/**
+ * Input edge data: describes what a field accepts.
+ */
+export interface InputEdgeData {
+ /** Bit flags describing field capabilities (see EdgeFlag) */
+ flags: number
+
+ /** Child input node id (for object values) */
+ childNodeId?: number
+
+ /** Scalar type mask (see ScalarMask) */
+ scalarMask?: number
+
+ /** Enum name index into string table */
+ enumNameIndex?: number
+}
+
+/**
+ * Output edge data: describes a field in a selection set.
+ */
+export interface OutputEdgeData {
+ /** Args node id for this field */
+ argsNodeId?: number
+
+ /** Next output node id for nested selection */
+ outputNodeId?: number
+}
+
+/**
+ * Root entry data: entry point for an operation.
+ */
+export interface RootEntryData {
+ /** Args node id */
+ argsNodeId?: number
+
+ /** Output node id */
+ outputNodeId?: number
+}
diff --git a/packages/param-graph/tsconfig.build.json b/packages/param-graph/tsconfig.build.json
new file mode 100644
index 000000000000..1eae4ca25256
--- /dev/null
+++ b/packages/param-graph/tsconfig.build.json
@@ -0,0 +1,7 @@
+{
+ "extends": "../../tsconfig.build.regular.json",
+ "compilerOptions": {
+ "outDir": "dist"
+ },
+ "include": ["src"]
+}
diff --git a/packages/param-graph/tsconfig.json b/packages/param-graph/tsconfig.json
new file mode 100644
index 000000000000..63e20a2cf0b8
--- /dev/null
+++ b/packages/param-graph/tsconfig.json
@@ -0,0 +1,4 @@
+{
+ "extends": "../../tsconfig.json",
+ "include": ["./**/*"]
+}
diff --git a/packages/query-plan-executor/package.json b/packages/query-plan-executor/package.json
index 8340de572ce8..2ad7cd5cd157 100644
--- a/packages/query-plan-executor/package.json
+++ b/packages/query-plan-executor/package.json
@@ -21,7 +21,7 @@
"@prisma/adapter-mssql": "workspace:*",
"@prisma/client-engine-runtime": "workspace:*",
"@prisma/driver-adapter-utils": "workspace:*",
- "hono": "4.10.6",
+ "hono": "4.11.7",
"temporal-polyfill": "0.3.0",
"vitest": "3.2.4",
"zod": "4.1.3"
diff --git a/packages/schema-files-loader/package.json b/packages/schema-files-loader/package.json
index e8d0f94dfb09..19197587c7b0 100644
--- a/packages/schema-files-loader/package.json
+++ b/packages/schema-files-loader/package.json
@@ -22,7 +22,7 @@
],
"sideEffects": false,
"dependencies": {
- "@prisma/prisma-schema-wasm": "7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735",
+ "@prisma/prisma-schema-wasm": "7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57",
"fs-extra": "11.3.0"
}
}
diff --git a/packages/sqlcommenter-query-insights/src/parameterize/parameterize.ts b/packages/sqlcommenter-query-insights/src/parameterize/parameterize.ts
index 908fb70bbba4..c68059b69a7b 100644
--- a/packages/sqlcommenter-query-insights/src/parameterize/parameterize.ts
+++ b/packages/sqlcommenter-query-insights/src/parameterize/parameterize.ts
@@ -100,7 +100,8 @@ function parameterize(value: unknown, context: Context, key?: string): unknown {
}
if (isTaggedValue(value)) {
- return value.$type === 'FieldRef' ? value : PARAM_PLACEHOLDER
+ // Preserve structural tagged values: FieldRef (field comparisons) and Param (already parameterized)
+ return value.$type === 'FieldRef' || value.$type === 'Param' ? value : PARAM_PLACEHOLDER
}
if (Array.isArray(value)) {
diff --git a/packages/sqlcommenter-query-insights/src/parameterize/tests/tagged-values.test.ts b/packages/sqlcommenter-query-insights/src/parameterize/tests/tagged-values.test.ts
index d4989ba95ad3..026e9ab3d019 100644
--- a/packages/sqlcommenter-query-insights/src/parameterize/tests/tagged-values.test.ts
+++ b/packages/sqlcommenter-query-insights/src/parameterize/tests/tagged-values.test.ts
@@ -164,6 +164,70 @@ describe('parameterizeQuery - tagged values', () => {
})
})
+ it('preserves pre-existing Param tagged values', () => {
+ const query = {
+ arguments: {
+ where: {
+ email: { contains: PARAM_PLACEHOLDER },
+ age: { gte: PARAM_PLACEHOLDER },
+ },
+ },
+ selection: { $scalars: true },
+ }
+
+ expect(parameterizeQuery(query)).toEqual({
+ arguments: {
+ where: {
+ email: { contains: PARAM_PLACEHOLDER },
+ age: { gte: PARAM_PLACEHOLDER },
+ },
+ },
+ selection: { $scalars: true },
+ })
+ })
+
+ it('preserves pre-existing Param tagged values in data context', () => {
+ const query = {
+ arguments: {
+ data: {
+ name: PARAM_PLACEHOLDER,
+ email: PARAM_PLACEHOLDER,
+ },
+ },
+ selection: { $scalars: true },
+ }
+
+ expect(parameterizeQuery(query)).toEqual({
+ arguments: {
+ data: {
+ name: PARAM_PLACEHOLDER,
+ email: PARAM_PLACEHOLDER,
+ },
+ },
+ selection: { $scalars: true },
+ })
+ })
+
+ it('preserves pre-existing Param tagged values in arrays', () => {
+ const query = {
+ arguments: {
+ where: {
+ id: { in: [PARAM_PLACEHOLDER, PARAM_PLACEHOLDER] },
+ },
+ },
+ selection: { $scalars: true },
+ }
+
+ expect(parameterizeQuery(query)).toEqual({
+ arguments: {
+ where: {
+ id: { in: [PARAM_PLACEHOLDER, PARAM_PLACEHOLDER] },
+ },
+ },
+ selection: { $scalars: true },
+ })
+ })
+
it('parameterizes tagged values in data context', () => {
const query = {
arguments: {
diff --git a/packages/type-benchmark-tests/test.ts b/packages/type-benchmark-tests/test.ts
index 0d6e7e36f2ce..1499a6f2a24b 100644
--- a/packages/type-benchmark-tests/test.ts
+++ b/packages/type-benchmark-tests/test.ts
@@ -111,7 +111,10 @@ function getBenchmarkFiles(dir: string) {
async function runGenerate(dir: string, cwd: string) {
console.log(`Running generate command in ${dir}...`)
- await execa('tsx', ['../../cli/src/bin.ts', 'generate', '--no-hints'], { cwd, stdio: 'inherit' })
+ // tsx sometimes crashes with stack overflow with the default stack size when
+ // using `pnpm dev` instead of `pnpm build` in the workspace, which skips type
+ // bundling and re-exports the types in `.d.ts` files from the raw TypeScript sources.
+ await execa('tsx', ['--stack-size=2048', '../../cli/src/bin.ts', 'generate', '--no-hints'], { cwd, stdio: 'inherit' })
}
async function runBenchmark({
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 36a56a9321f3..1420f26c6b4a 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -6,9 +6,10 @@ settings:
overrides:
form-data: '>=4.0.4'
- hono: '>=4.10.3'
+ hono: '>=4.11.7'
jws: '>=4.0.1'
tar-fs: '>=2.1.4'
+ lodash: '>=4.17.23'
importers:
@@ -247,8 +248,8 @@ importers:
packages/adapter-libsql:
dependencies:
'@libsql/client':
- specifier: ^0.8.1
- version: 0.8.1
+ specifier: ^0.17.0
+ version: 0.17.0(encoding@0.1.13)
'@prisma/driver-adapter-utils':
specifier: workspace:*
version: link:../driver-adapter-utils
@@ -441,7 +442,7 @@ importers:
devDependencies:
'@hono/node-server':
specifier: 1.19.9
- version: 1.19.9(hono@4.11.4)
+ version: 1.19.9(hono@4.11.7)
'@inquirer/prompts':
specifier: 7.3.3
version: 7.3.3(@types/node@20.19.25)
@@ -551,8 +552,8 @@ importers:
specifier: 4.10.0
version: 4.10.0
hono:
- specifier: '>=4.10.3'
- version: 4.11.4
+ specifier: '>=4.11.7'
+ version: 4.11.7
jest:
specifier: 29.7.0
version: 29.7.0(@types/node@20.19.25)(ts-node@10.9.2(@swc/core@1.11.5)(@types/node@20.19.25)(typescript@5.4.5))
@@ -637,7 +638,7 @@ importers:
version: 2.0.3(@jest/expect@29.7.0)(@jest/globals@29.7.0)
'@hono/node-server':
specifier: 1.19.0
- version: 1.19.0(hono@4.11.4)
+ version: 1.19.0(hono@4.11.7)
'@inquirer/prompts':
specifier: 7.3.3
version: 7.3.3(@types/node@20.19.25)
@@ -729,8 +730,8 @@ importers:
specifier: workspace:*
version: link:../engines
'@prisma/engines-version':
- specifier: 7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735
- version: 7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735
+ specifier: 7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57
+ version: 7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57
'@prisma/fetch-engine':
specifier: workspace:*
version: link:../fetch-engine
@@ -758,9 +759,15 @@ importers:
'@prisma/migrate':
specifier: workspace:*
version: link:../migrate
+ '@prisma/param-graph':
+ specifier: workspace:*
+ version: link:../param-graph
+ '@prisma/param-graph-builder':
+ specifier: workspace:*
+ version: link:../param-graph-builder
'@prisma/query-compiler-wasm':
- specifier: 7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735
- version: 7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735
+ specifier: 7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57
+ version: 7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57
'@prisma/query-plan-executor':
specifier: workspace:*
version: link:../query-plan-executor
@@ -935,6 +942,9 @@ importers:
'@prisma/internals':
specifier: workspace:*
version: link:../internals
+ '@prisma/param-graph':
+ specifier: workspace:*
+ version: link:../param-graph
packages/client-engine-runtime:
dependencies:
@@ -1009,8 +1019,8 @@ importers:
specifier: workspace:*
version: link:../dmmf
'@prisma/engines-version':
- specifier: 7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735
- version: 7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735
+ specifier: 7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57
+ version: 7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57
'@prisma/fetch-engine':
specifier: workspace:*
version: link:../fetch-engine
@@ -1023,6 +1033,9 @@ importers:
'@prisma/internals':
specifier: workspace:*
version: link:../internals
+ '@prisma/param-graph-builder':
+ specifier: workspace:*
+ version: link:../param-graph-builder
'@prisma/ts-builders':
specifier: workspace:*
version: link:../ts-builders
@@ -1086,8 +1099,8 @@ importers:
specifier: workspace:*
version: link:../dmmf
'@prisma/engines-version':
- specifier: 7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735
- version: 7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735
+ specifier: 7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57
+ version: 7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57
'@prisma/fetch-engine':
specifier: workspace:*
version: link:../fetch-engine
@@ -1100,6 +1113,9 @@ importers:
'@prisma/internals':
specifier: workspace:*
version: link:../internals
+ '@prisma/param-graph-builder':
+ specifier: workspace:*
+ version: link:../param-graph-builder
'@prisma/ts-builders':
specifier: workspace:*
version: link:../ts-builders
@@ -1221,8 +1237,8 @@ importers:
specifier: workspace:*
version: link:../debug
'@prisma/engines-version':
- specifier: 7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735
- version: 7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735
+ specifier: 7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57
+ version: 7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57
'@prisma/fetch-engine':
specifier: workspace:*
version: link:../fetch-engine
@@ -1258,8 +1274,8 @@ importers:
specifier: workspace:*
version: link:../debug
'@prisma/engines-version':
- specifier: 7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735
- version: 7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735
+ specifier: 7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57
+ version: 7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57
'@prisma/get-platform':
specifier: workspace:*
version: link:../get-platform
@@ -1547,11 +1563,11 @@ importers:
specifier: workspace:*
version: link:../get-platform
'@prisma/prisma-schema-wasm':
- specifier: 7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735
- version: 7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735
+ specifier: 7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57
+ version: 7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57
'@prisma/schema-engine-wasm':
- specifier: 7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735
- version: 7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735
+ specifier: 7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57
+ version: 7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57
'@prisma/schema-files-loader':
specifier: workspace:*
version: link:../schema-files-loader
@@ -1712,8 +1728,8 @@ importers:
specifier: workspace:*
version: link:../driver-adapter-utils
'@prisma/engines-version':
- specifier: 7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735
- version: 7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735
+ specifier: 7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57
+ version: 7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57
'@prisma/generator':
specifier: workspace:*
version: link:../generator
@@ -1818,14 +1834,25 @@ importers:
specifier: 5.92.1
version: 5.92.1(@swc/core@1.11.5)(esbuild@0.25.5)
+ packages/param-graph: {}
+
+ packages/param-graph-builder:
+ dependencies:
+ '@prisma/dmmf':
+ specifier: workspace:*
+ version: link:../dmmf
+ '@prisma/param-graph':
+ specifier: workspace:*
+ version: link:../param-graph
+
packages/query-plan-executor:
devDependencies:
'@hono/node-server':
specifier: 1.19.0
- version: 1.19.0(hono@4.10.6)
+ version: 1.19.0(hono@4.11.7)
'@hono/zod-validator':
specifier: 0.7.2
- version: 0.7.2(hono@4.10.6)(zod@4.1.3)
+ version: 0.7.2(hono@4.11.7)(zod@4.1.3)
'@opentelemetry/api':
specifier: 1.9.0
version: 1.9.0
@@ -1851,8 +1878,8 @@ importers:
specifier: workspace:*
version: link:../driver-adapter-utils
hono:
- specifier: '>=4.10.3'
- version: 4.10.6
+ specifier: '>=4.11.7'
+ version: 4.11.7
temporal-polyfill:
specifier: 0.3.0
version: 0.3.0
@@ -1866,8 +1893,8 @@ importers:
packages/schema-files-loader:
dependencies:
'@prisma/prisma-schema-wasm':
- specifier: 7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735
- version: 7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735
+ specifier: 7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57
+ version: 7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57
fs-extra:
specifier: 11.3.0
version: 11.3.0
@@ -2868,18 +2895,18 @@ packages:
resolution: {integrity: sha512-1k8/8OHf5VIymJEcJyVksFpT+AQ5euY0VA5hUkCnlKpD4mr8FSbvXaHblxeTTEr90OaqWzAkQaqD80qHZQKxBA==}
engines: {node: '>=18.14.1'}
peerDependencies:
- hono: '>=4.10.3'
+ hono: '>=4.11.7'
'@hono/node-server@1.19.9':
resolution: {integrity: sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==}
engines: {node: '>=18.14.1'}
peerDependencies:
- hono: '>=4.10.3'
+ hono: '>=4.11.7'
'@hono/zod-validator@0.7.2':
resolution: {integrity: sha512-ub5eL/NeZ4eLZawu78JpW/J+dugDAYhwqUIdp9KYScI6PZECij4Hx4UsrthlEUutqDDhPwRI0MscUfNkvn/mqQ==}
peerDependencies:
- hono: '>=4.10.3'
+ hono: '>=4.11.7'
zod: ^3.25.0 || ^4.0.0
'@humanfs/core@0.19.1':
@@ -3285,9 +3312,15 @@ packages:
peerDependencies:
tslib: '2'
+ '@libsql/client@0.17.0':
+ resolution: {integrity: sha512-TLjSU9Otdpq0SpKHl1tD1Nc9MKhrsZbCFGot3EbCxRa8m1E5R1mMwoOjKMMM31IyF7fr+hPNHLpYfwbMKNusmg==}
+
'@libsql/client@0.8.1':
resolution: {integrity: sha512-xGg0F4iTDFpeBZ0r4pA6icGsYa5rG6RAG+i/iLDnpCAnSuTqEWMDdPlVseiq4Z/91lWI9jvvKKiKpovqJ1kZWA==}
+ '@libsql/core@0.17.0':
+ resolution: {integrity: sha512-hnZRnJHiS+nrhHKLGYPoJbc78FE903MSDrFJTbftxo+e52X+E0Y0fHOCVYsKWcg6XgB7BbJYUrz/xEkVTSaipw==}
+
'@libsql/core@0.8.1':
resolution: {integrity: sha512-u6nrj6HZMTPsgJ9EBhLzO2uhqhlHQJQmVHV+0yFLvfGf3oSP8w7TjZCNUgu1G8jHISx6KFi7bmcrdXW9lRt++A==}
@@ -3296,45 +3329,93 @@ packages:
cpu: [arm64]
os: [darwin]
+ '@libsql/darwin-arm64@0.5.22':
+ resolution: {integrity: sha512-4B8ZlX3nIDPndfct7GNe0nI3Yw6ibocEicWdC4fvQbSs/jdq/RC2oCsoJxJ4NzXkvktX70C1J4FcmmoBy069UA==}
+ cpu: [arm64]
+ os: [darwin]
+
'@libsql/darwin-x64@0.3.10':
resolution: {integrity: sha512-SNVN6n4qNUdMW1fJMFmx4qn4n5RnXsxjFbczpkzG/V7m/5VeTFt1chhGcrahTHCr3+K6eRJWJUEQHRGqjBwPkw==}
cpu: [x64]
os: [darwin]
+ '@libsql/darwin-x64@0.5.22':
+ resolution: {integrity: sha512-ny2HYWt6lFSIdNFzUFIJ04uiW6finXfMNJ7wypkAD8Pqdm6nAByO+Fdqu8t7sD0sqJGeUCiOg480icjyQ2/8VA==}
+ cpu: [x64]
+ os: [darwin]
+
'@libsql/hrana-client@0.6.2':
resolution: {integrity: sha512-MWxgD7mXLNf9FXXiM0bc90wCjZSpErWKr5mGza7ERy2FJNNMXd7JIOv+DepBA1FQTIfI8TFO4/QDYgaQC0goNw==}
+ '@libsql/hrana-client@0.9.0':
+ resolution: {integrity: sha512-pxQ1986AuWfPX4oXzBvLwBnfgKDE5OMhAdR/5cZmRaB4Ygz5MecQybvwZupnRz341r2CtFmbk/BhSu7k2Lm+Jw==}
+
'@libsql/isomorphic-fetch@0.2.1':
resolution: {integrity: sha512-Sv07QP1Aw8A5OOrmKgRUBKe2fFhF2hpGJhtHe3d1aRnTESZCGkn//0zDycMKTGamVWb3oLYRroOsCV8Ukes9GA==}
'@libsql/isomorphic-ws@0.1.5':
resolution: {integrity: sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg==}
+ '@libsql/linux-arm-gnueabihf@0.5.22':
+ resolution: {integrity: sha512-3Uo3SoDPJe/zBnyZKosziRGtszXaEtv57raWrZIahtQDsjxBVjuzYQinCm9LRCJCUT5t2r5Z5nLDPJi2CwZVoA==}
+ cpu: [arm]
+ os: [linux]
+
+ '@libsql/linux-arm-musleabihf@0.5.22':
+ resolution: {integrity: sha512-LCsXh07jvSojTNJptT9CowOzwITznD+YFGGW+1XxUr7fS+7/ydUrpDfsMX7UqTqjm7xG17eq86VkWJgHJfvpNg==}
+ cpu: [arm]
+ os: [linux]
+
'@libsql/linux-arm64-gnu@0.3.10':
resolution: {integrity: sha512-2uXpi9d8qtyIOr7pyG4a88j6YXgemyIHEs2Wbp+PPletlCIPsFS+E7IQHbz8VwTohchOzcokGUm1Bc5QC+A7wg==}
cpu: [arm64]
os: [linux]
+ '@libsql/linux-arm64-gnu@0.5.22':
+ resolution: {integrity: sha512-KSdnOMy88c9mpOFKUEzPskSaF3VLflfSUCBwas/pn1/sV3pEhtMF6H8VUCd2rsedwoukeeCSEONqX7LLnQwRMA==}
+ cpu: [arm64]
+ os: [linux]
+
'@libsql/linux-arm64-musl@0.3.10':
resolution: {integrity: sha512-72SN1FUavLvzHddCS861ynSpQndcW5oLGKA3U8CyMfgIZIwJAPc7+48Uj1plW00htXBx4GBpcntFp68KKIx3YQ==}
cpu: [arm64]
os: [linux]
+ '@libsql/linux-arm64-musl@0.5.22':
+ resolution: {integrity: sha512-mCHSMAsDTLK5YH//lcV3eFEgiR23Ym0U9oEvgZA0667gqRZg/2px+7LshDvErEKv2XZ8ixzw3p1IrBzLQHGSsw==}
+ cpu: [arm64]
+ os: [linux]
+
'@libsql/linux-x64-gnu@0.3.10':
resolution: {integrity: sha512-hXyNqVRi7ONuyWZ1SX6setxL0QaQ7InyS3bHLupsi9s7NpOGD5vcpTaYicJOqmIIm+6kt8vJfmo7ZxlarIHy7Q==}
cpu: [x64]
os: [linux]
+ '@libsql/linux-x64-gnu@0.5.22':
+ resolution: {integrity: sha512-kNBHaIkSg78Y4BqAdgjcR2mBilZXs4HYkAmi58J+4GRwDQZh5fIUWbnQvB9f95DkWUIGVeenqLRFY2pcTmlsew==}
+ cpu: [x64]
+ os: [linux]
+
'@libsql/linux-x64-musl@0.3.10':
resolution: {integrity: sha512-kNmIRxomVwt9S+cLyYS497F/3gXFF4r8wW12YSBQgxG75JYft07AHVd8J7HINg+oqRkLzT0s+mVX5dM6nk68EQ==}
cpu: [x64]
os: [linux]
+ '@libsql/linux-x64-musl@0.5.22':
+ resolution: {integrity: sha512-UZ4Xdxm4pu3pQXjvfJiyCzZop/9j/eA2JjmhMaAhe3EVLH2g11Fy4fwyUp9sT1QJYR1kpc2JLuybPM0kuXv/Tg==}
+ cpu: [x64]
+ os: [linux]
+
'@libsql/win32-x64-msvc@0.3.10':
resolution: {integrity: sha512-c/6rjdtGULKrJkLgfLobFefObfOtxjXGmCfPxv6pr0epPCeUEssfDbDIeEH9fQUgzogIMWEHwT8so52UJ/iT1Q==}
cpu: [x64]
os: [win32]
+ '@libsql/win32-x64-msvc@0.5.22':
+ resolution: {integrity: sha512-Fj0j8RnBpo43tVZUVoNK6BV/9AtDUM5S7DF3LB4qTYg1LMSZqi3yeCneUTLJD6XomQJlZzbI4mst89yspVSAnA==}
+ cpu: [x64]
+ os: [win32]
+
'@microsoft/api-extractor-model@7.30.7':
resolution: {integrity: sha512-TBbmSI2/BHpfR9YhQA7nH0nqVmGgJ0xH0Ex4D99/qBDAUpnhA2oikGmdXanbw9AWWY/ExBYIpkmY8dBHdla3YQ==}
@@ -3586,8 +3667,8 @@ packages:
'@prisma/dev@0.20.0':
resolution: {integrity: sha512-ovlBYwWor0OzG+yH4J3Ot+AneD818BttLA+Ii7wjbcLHUrnC4tbUPVGyNd3c/+71KETPKZfjhkTSpdS15dmXNQ==}
- '@prisma/engines-version@7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735':
- resolution: {integrity: sha512-IH2va2ouUHihyiTTRW889LjKAl1CusZOvFfZxCDNpjSENt7g2ndFsK0vdIw/72v7+jCN6YgkHmdAP/BI7SDgyg==}
+ '@prisma/engines-version@7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57':
+ resolution: {integrity: sha512-5o3/bubIYdUeg38cyNf+VDq+LVtxvvi2393Fd1Uru52LPfkGJnmVbCaX1wBOAncgKR3BCloMJFD+Koog9LtYqQ==}
'@prisma/get-platform@7.2.0':
resolution: {integrity: sha512-k1V0l0Td1732EHpAfi2eySTezyllok9dXb6UQanajkJQzPUGi3vO2z7jdkz67SypFTdmbnyGYxvEvYZdZsMAVA==}
@@ -3598,17 +3679,17 @@ packages:
'@prisma/ppg@1.0.1':
resolution: {integrity: sha512-rRRXuPPerXwNWjSA3OE0e/bqXSTfsE82EsMvoiluc0fN0DizQSe3937/Tnl5+DPbxY5rdAOlYjWXG0A2wwTbKA==}
- '@prisma/prisma-schema-wasm@7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735':
- resolution: {integrity: sha512-pL9W918JLoK9fdAccH07ryjN9D4TZU1H3zBrLtYZbd+YhsAYQVvyM8hhyxzv8UrXVDKwsiYWoMdTb2PC+cjy3A==}
+ '@prisma/prisma-schema-wasm@7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57':
+ resolution: {integrity: sha512-c4l8sQorhTZGIRx2IcJZUoFBaST0jVhbKb7yC68FF065T11K5BNAQt8mgcsdsC2UA1AsRK1LFpMZjvfiYg1tNA==}
- '@prisma/query-compiler-wasm@7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735':
- resolution: {integrity: sha512-RsqWxibTq1vXlCpns2NuZ8VJQuxPKtf0CK+786jsxHEBJ2utuSlMpcyl8bFazu2hMPCNE8EjaKRcJrROk3fmwQ==}
+ '@prisma/query-compiler-wasm@7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57':
+ resolution: {integrity: sha512-UfjxUfReGmDFGz7OaQ+C5X28b6GojCysgv3c1gmD6wyx8Z8dNQNJpn/5XmsF3Gyq+/dPlI8G/FB+yBHqlgjOqg==}
'@prisma/query-plan-executor@7.2.0':
resolution: {integrity: sha512-EOZmNzcV8uJ0mae3DhTsiHgoNCuu1J9mULQpGCh62zN3PxPTd+qI9tJvk5jOst8WHKQNwJWR3b39t0XvfBB0WQ==}
- '@prisma/schema-engine-wasm@7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735':
- resolution: {integrity: sha512-C1Ahpv7VAfrSKhooPWBJlxIrljwfQsm7LaXTxgk7zxooHWyiRI7uK3HVBHYL4fC8PM4kCT5Q6FXvuMWR5eq6vg==}
+ '@prisma/schema-engine-wasm@7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57':
+ resolution: {integrity: sha512-iYJdHsejfsqMq4pufb8yDESDdgvah9BX8e2io+pPcKHGDEtEq6s1+6yIih9zLLKoRammgeScA6V6MFngNa/xHA==}
'@prisma/studio-core@0.13.1':
resolution: {integrity: sha512-agdqaPEePRHcQ7CexEfkX1RvSH9uWDb6pXrZnhCRykhDFAV0/0P3d07WtfiY8hZWb7oRU4v+NkT4cGFHkQJIPg==}
@@ -4872,6 +4953,9 @@ packages:
create-require@1.1.1:
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
+ cross-fetch@4.1.0:
+ resolution: {integrity: sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==}
+
cross-spawn@7.0.6:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'}
@@ -5707,12 +5791,8 @@ packages:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
- hono@4.10.6:
- resolution: {integrity: sha512-BIdolzGpDO9MQ4nu3AUuDwHZZ+KViNm+EZ75Ae55eMXMqLVhDFqEMXxtUe9Qh8hjL+pIna/frs2j6Y2yD5Ua/g==}
- engines: {node: '>=16.9.0'}
-
- hono@4.11.4:
- resolution: {integrity: sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA==}
+ hono@4.11.7:
+ resolution: {integrity: sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw==}
engines: {node: '>=16.9.0'}
hosted-git-info@2.8.9:
@@ -6308,6 +6388,11 @@ packages:
cpu: [x64, arm64, wasm32]
os: [darwin, linux, win32]
+ libsql@0.5.22:
+ resolution: {integrity: sha512-NscWthMQt7fpU8lqd7LXMvT9pi+KhhmTHAJWUB/Lj6MWa0MKFv0F2V4C6WKKpjCVZl0VwcDz4nOI3CyaT1DDiA==}
+ cpu: [x64, arm64, wasm32, arm]
+ os: [darwin, linux, win32]
+
lilconfig@2.1.0:
resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==}
engines: {node: '>=10'}
@@ -6372,8 +6457,8 @@ packages:
lodash.once@4.1.1:
resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==}
- lodash@4.17.21:
- resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+ lodash@4.17.23:
+ resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==}
log-symbols@4.1.0:
resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
@@ -7808,6 +7893,7 @@ packages:
tar@6.1.14:
resolution: {integrity: sha512-piERznXu0U7/pW7cdSn7hjqySIVTYT6F76icmFk7ptU7dDYlXTm5r9A6K04R2vU3olYgoKeo1Cg3eeu5nhftAw==}
engines: {node: '>=10'}
+ deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exhorbitant rates) by contacting i@izs.me
tarn@3.0.2:
resolution: {integrity: sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==}
@@ -8920,12 +9006,12 @@ snapshots:
dependencies:
'@chevrotain/gast': 10.5.0
'@chevrotain/types': 10.5.0
- lodash: 4.17.21
+ lodash: 4.17.23
'@chevrotain/gast@10.5.0':
dependencies:
'@chevrotain/types': 10.5.0
- lodash: 4.17.21
+ lodash: 4.17.23
'@chevrotain/types@10.5.0': {}
@@ -8987,7 +9073,7 @@ snapshots:
dependencies:
'@codspeed/core': 4.0.0
benchmark: 2.1.4
- lodash: 4.17.21
+ lodash: 4.17.23
stack-trace: 1.0.0-pre2
transitivePeerDependencies:
- debug
@@ -9332,21 +9418,17 @@ snapshots:
'@gar/promisify@1.1.3':
optional: true
- '@hono/node-server@1.19.0(hono@4.10.6)':
+ '@hono/node-server@1.19.0(hono@4.11.7)':
dependencies:
- hono: 4.10.6
+ hono: 4.11.7
- '@hono/node-server@1.19.0(hono@4.11.4)':
+ '@hono/node-server@1.19.9(hono@4.11.7)':
dependencies:
- hono: 4.11.4
+ hono: 4.11.7
- '@hono/node-server@1.19.9(hono@4.11.4)':
+ '@hono/zod-validator@0.7.2(hono@4.11.7)(zod@4.1.3)':
dependencies:
- hono: 4.11.4
-
- '@hono/zod-validator@0.7.2(hono@4.10.6)(zod@4.1.3)':
- dependencies:
- hono: 4.10.6
+ hono: 4.11.7
zod: 4.1.3
'@humanfs/core@0.19.1': {}
@@ -9846,6 +9928,18 @@ snapshots:
dependencies:
tslib: 2.8.1
+ '@libsql/client@0.17.0(encoding@0.1.13)':
+ dependencies:
+ '@libsql/core': 0.17.0
+ '@libsql/hrana-client': 0.9.0(encoding@0.1.13)
+ js-base64: 3.7.5
+ libsql: 0.5.22
+ promise-limit: 2.7.0
+ transitivePeerDependencies:
+ - bufferutil
+ - encoding
+ - utf-8-validate
+
'@libsql/client@0.8.1':
dependencies:
'@libsql/core': 0.8.1
@@ -9857,6 +9951,10 @@ snapshots:
- bufferutil
- utf-8-validate
+ '@libsql/core@0.17.0':
+ dependencies:
+ js-base64: 3.7.5
+
'@libsql/core@0.8.1':
dependencies:
js-base64: 3.7.5
@@ -9864,9 +9962,15 @@ snapshots:
'@libsql/darwin-arm64@0.3.10':
optional: true
+ '@libsql/darwin-arm64@0.5.22':
+ optional: true
+
'@libsql/darwin-x64@0.3.10':
optional: true
+ '@libsql/darwin-x64@0.5.22':
+ optional: true
+
'@libsql/hrana-client@0.6.2':
dependencies:
'@libsql/isomorphic-fetch': 0.2.1
@@ -9877,6 +9981,17 @@ snapshots:
- bufferutil
- utf-8-validate
+ '@libsql/hrana-client@0.9.0(encoding@0.1.13)':
+ dependencies:
+ '@libsql/isomorphic-ws': 0.1.5
+ cross-fetch: 4.1.0(encoding@0.1.13)
+ js-base64: 3.7.5
+ node-fetch: 3.3.2
+ transitivePeerDependencies:
+ - bufferutil
+ - encoding
+ - utf-8-validate
+
'@libsql/isomorphic-fetch@0.2.1': {}
'@libsql/isomorphic-ws@0.1.5':
@@ -9887,21 +10002,42 @@ snapshots:
- bufferutil
- utf-8-validate
+ '@libsql/linux-arm-gnueabihf@0.5.22':
+ optional: true
+
+ '@libsql/linux-arm-musleabihf@0.5.22':
+ optional: true
+
'@libsql/linux-arm64-gnu@0.3.10':
optional: true
+ '@libsql/linux-arm64-gnu@0.5.22':
+ optional: true
+
'@libsql/linux-arm64-musl@0.3.10':
optional: true
+ '@libsql/linux-arm64-musl@0.5.22':
+ optional: true
+
'@libsql/linux-x64-gnu@0.3.10':
optional: true
+ '@libsql/linux-x64-gnu@0.5.22':
+ optional: true
+
'@libsql/linux-x64-musl@0.3.10':
optional: true
+ '@libsql/linux-x64-musl@0.5.22':
+ optional: true
+
'@libsql/win32-x64-msvc@0.3.10':
optional: true
+ '@libsql/win32-x64-msvc@0.5.22':
+ optional: true
+
'@microsoft/api-extractor-model@7.30.7(@types/node@20.19.25)':
dependencies:
'@microsoft/tsdoc': 0.15.1
@@ -9919,7 +10055,7 @@ snapshots:
'@rushstack/rig-package': 0.5.3
'@rushstack/terminal': 0.15.4(@types/node@20.19.25)
'@rushstack/ts-command-line': 5.0.2(@types/node@20.19.25)
- lodash: 4.17.21
+ lodash: 4.17.23
minimatch: 10.0.3
resolve: 1.22.10
semver: 7.5.4
@@ -10185,13 +10321,13 @@ snapshots:
'@electric-sql/pglite': 0.3.15
'@electric-sql/pglite-socket': 0.0.20(@electric-sql/pglite@0.3.15)
'@electric-sql/pglite-tools': 0.2.20(@electric-sql/pglite@0.3.15)
- '@hono/node-server': 1.19.9(hono@4.11.4)
+ '@hono/node-server': 1.19.9(hono@4.11.7)
'@mrleebo/prisma-ast': 0.13.1
'@prisma/get-platform': 7.2.0
'@prisma/query-plan-executor': 7.2.0
foreground-child: 3.3.1
get-port-please: 3.2.0
- hono: 4.11.4
+ hono: 4.11.7
http-status-codes: 2.3.0
pathe: 2.0.3
proper-lockfile: 4.1.2
@@ -10202,7 +10338,7 @@ snapshots:
transitivePeerDependencies:
- typescript
- '@prisma/engines-version@7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735': {}
+ '@prisma/engines-version@7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57': {}
'@prisma/get-platform@7.2.0':
dependencies:
@@ -10219,13 +10355,13 @@ snapshots:
- bufferutil
- utf-8-validate
- '@prisma/prisma-schema-wasm@7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735': {}
+ '@prisma/prisma-schema-wasm@7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57': {}
- '@prisma/query-compiler-wasm@7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735': {}
+ '@prisma/query-compiler-wasm@7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57': {}
'@prisma/query-plan-executor@7.2.0': {}
- '@prisma/schema-engine-wasm@7.3.0-16.9d6ad21cbbceab97458517b147a6a09ff43aa735': {}
+ '@prisma/schema-engine-wasm@7.4.0-20.ab56fe763f921d033a6c195e7ddeb3e255bdbb57': {}
'@prisma/studio-core@0.13.1': {}
@@ -10816,7 +10952,7 @@ snapshots:
'@typescript/vfs@1.6.1(typescript@5.8.2)':
dependencies:
- debug: 4.4.0(supports-color@10.2.2)
+ debug: 4.4.1
typescript: 5.8.2
transitivePeerDependencies:
- supports-color
@@ -11102,7 +11238,7 @@ snapshots:
glob: 8.1.0
graceful-fs: 4.2.11
lazystream: 1.0.1
- lodash: 4.17.21
+ lodash: 4.17.23
normalize-path: 3.0.0
readable-stream: 3.6.2
@@ -11283,7 +11419,7 @@ snapshots:
benchmark@2.1.4:
dependencies:
- lodash: 4.17.21
+ lodash: 4.17.23
platform: 1.3.6
better-sqlite3@11.10.0:
@@ -11494,7 +11630,7 @@ snapshots:
'@chevrotain/gast': 10.5.0
'@chevrotain/types': 10.5.0
'@chevrotain/utils': 10.5.0
- lodash: 4.17.21
+ lodash: 4.17.23
regexp-to-ast: 0.5.0
chokidar@4.0.3:
@@ -11671,6 +11807,12 @@ snapshots:
create-require@1.1.1: {}
+ cross-fetch@4.1.0(encoding@0.1.13):
+ dependencies:
+ node-fetch: 2.7.0(encoding@0.1.13)
+ transitivePeerDependencies:
+ - encoding
+
cross-spawn@7.0.6:
dependencies:
path-key: 3.1.1
@@ -12570,9 +12712,7 @@ snapshots:
dependencies:
function-bind: 1.1.2
- hono@4.10.6: {}
-
- hono@4.11.4: {}
+ hono@4.11.7: {}
hosted-git-info@2.8.9: {}
@@ -13376,6 +13516,21 @@ snapshots:
'@libsql/linux-x64-musl': 0.3.10
'@libsql/win32-x64-msvc': 0.3.10
+ libsql@0.5.22:
+ dependencies:
+ '@neon-rs/load': 0.0.4
+ detect-libc: 2.0.2
+ optionalDependencies:
+ '@libsql/darwin-arm64': 0.5.22
+ '@libsql/darwin-x64': 0.5.22
+ '@libsql/linux-arm-gnueabihf': 0.5.22
+ '@libsql/linux-arm-musleabihf': 0.5.22
+ '@libsql/linux-arm64-gnu': 0.5.22
+ '@libsql/linux-arm64-musl': 0.5.22
+ '@libsql/linux-x64-gnu': 0.5.22
+ '@libsql/linux-x64-musl': 0.5.22
+ '@libsql/win32-x64-msvc': 0.5.22
+
lilconfig@2.1.0: {}
lilconfig@3.1.3: {}
@@ -13438,7 +13593,7 @@ snapshots:
lodash.once@4.1.1: {}
- lodash@4.17.21: {}
+ lodash@4.17.23: {}
log-symbols@4.1.0:
dependencies:
diff --git a/tsconfig.build.bundle.json b/tsconfig.build.bundle.json
index 0cd48129c7fd..fc3173eea217 100644
--- a/tsconfig.build.bundle.json
+++ b/tsconfig.build.bundle.json
@@ -32,6 +32,8 @@
"@prisma/adapter-neon": ["./packages/adapter-neon/src"],
"@prisma/adapter-pg": ["./packages/adapter-pg/src"],
"@prisma/adapter-planetscale": ["./packages/adapter-planetscale/src"],
+ "@prisma/param-graph": ["./packages/param-graph/src"],
+ "@prisma/param-graph-builder": ["./packages/param-graph-builder/src"],
"@prisma/query-plan-executor": ["./packages/query-plan-executor/src"],
"@prisma/sqlcommenter": ["./packages/sqlcommenter/src"],
"@prisma/sqlcommenter-query-insights": ["./packages/sqlcommenter-query-insights/src"],