You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

@prisma/param-graph

Package Overview
Dependencies
Maintainers
7
Versions
88
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@prisma/param-graph - npm Package Compare versions

Comparing version
7.3.0-integration-parameterization.15
to
7.4.0-dev.22
+113
dist/serialization.d.ts
/**
* 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 { ParamGraphData } 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 declare function serializeParamGraph(data: ParamGraphData): SerializedParamGraph;
/**
* Deserializes a binary-encoded ParamGraph.
*/
export declare function deserializeParamGraph(serialized: SerializedParamGraph): ParamGraphData;
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var serialization_exports = {};
__export(serialization_exports, {
deserializeParamGraph: () => deserializeParamGraph,
serializeParamGraph: () => serializeParamGraph
});
module.exports = __toCommonJS(serialization_exports);
function serializeParamGraph(data) {
return new Serializer(data).serialize();
}
function deserializeParamGraph(serialized) {
return new Deserializer(serialized).deserialize();
}
function encodeBase64url(bytes) {
return Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString("base64url");
}
function decodeBase64url(str) {
return Buffer.from(str, "base64url");
}
function varuintSize(value) {
let size = 1;
while (value >= 128) {
size++;
value >>>= 7;
}
return size;
}
class Serializer {
#data;
#buffer;
#view;
#offset = 0;
#rootKeys;
constructor(data) {
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() {
this.#writeHeader();
this.#writeInputNodes();
this.#writeOutputNodes();
this.#writeRoots();
return {
strings: this.#data.strings,
graph: encodeBase64url(new Uint8Array(this.#buffer, 0, this.#offset))
};
}
#writeVaruint(value) {
while (value >= 128) {
this.#view.setUint8(this.#offset++, value & 127 | 128);
value >>>= 7;
}
this.#view.setUint8(this.#offset++, value);
}
#writeOptionalVaruint(value) {
this.#writeVaruint(value === void 0 ? 0 : value + 1);
}
#writeByte(value) {
this.#view.setUint8(this.#offset, value);
this.#offset += 1;
}
#writeU16(value) {
this.#view.setUint16(this.#offset, value, true);
this.#offset += 2;
}
#calculateBufferSize() {
let size = 0;
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;
size += varuintSize(edge.childNodeId === void 0 ? 0 : edge.childNodeId + 1);
size += varuintSize(edge.enumNameIndex === void 0 ? 0 : edge.enumNameIndex + 1);
size += 1;
}
}
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 === void 0 ? 0 : edge.argsNodeId + 1);
size += varuintSize(edge.outputNodeId === void 0 ? 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 === void 0 ? 0 : root.argsNodeId + 1);
size += varuintSize(root.outputNodeId === void 0 ? 0 : root.outputNodeId + 1);
}
return size;
}
#writeHeader() {
this.#writeVaruint(this.#data.inputNodes.length);
this.#writeVaruint(this.#data.outputNodes.length);
this.#writeVaruint(this.#rootKeys.length);
}
#writeInputNodes() {
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() {
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() {
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;
#view;
#offset = 0;
constructor(serialized) {
this.#serialized = serialized;
const bytes = decodeBase64url(serialized.graph);
this.#view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
}
deserialize() {
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() {
let value = 0;
let shift = 0;
let byte;
do {
byte = this.#view.getUint8(this.#offset++);
value |= (byte & 127) << shift;
shift += 7;
} while (byte >= 128);
return value;
}
#readOptionalVaruint() {
const value = this.#readVaruint();
return value === 0 ? void 0 : value - 1;
}
#readByte() {
const value = this.#view.getUint8(this.#offset);
this.#offset += 1;
return value;
}
#readU16() {
const value = this.#view.getUint16(this.#offset, true);
this.#offset += 2;
return value;
}
#readHeader() {
const inputNodeCount = this.#readVaruint();
const outputNodeCount = this.#readVaruint();
const rootCount = this.#readVaruint();
return { inputNodeCount, outputNodeCount, rootCount };
}
#readInputNodes(count) {
const inputNodes = [];
for (let i = 0; i < count; i++) {
const edgeCount = this.#readVaruint();
const edges = {};
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 = { flags };
if (scalarMask !== 0) edge.scalarMask = scalarMask;
if (childNodeId !== void 0) edge.childNodeId = childNodeId;
if (enumNameIndex !== void 0) edge.enumNameIndex = enumNameIndex;
edges[fieldIndex] = edge;
}
inputNodes.push({ edges });
}
return inputNodes;
}
#readOutputNodes(count) {
const outputNodes = [];
for (let i = 0; i < count; i++) {
const edgeCount = this.#readVaruint();
const edges = {};
for (let j = 0; j < edgeCount; j++) {
const fieldIndex = this.#readVaruint();
const argsNodeId = this.#readOptionalVaruint();
const outputNodeId = this.#readOptionalVaruint();
const edge = {};
if (argsNodeId !== void 0) edge.argsNodeId = argsNodeId;
if (outputNodeId !== void 0) edge.outputNodeId = outputNodeId;
edges[fieldIndex] = edge;
}
outputNodes.push({ edges });
}
return outputNodes;
}
#readRoots(count) {
const roots = {};
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 = {};
if (argsNodeId !== void 0) root.argsNodeId = argsNodeId;
if (outputNodeId !== void 0) root.outputNodeId = outputNodeId;
roots[key] = root;
}
return roots;
}
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
deserializeParamGraph,
serializeParamGraph
});
function serializeParamGraph(data) {
return new Serializer(data).serialize();
}
function deserializeParamGraph(serialized) {
return new Deserializer(serialized).deserialize();
}
function encodeBase64url(bytes) {
return Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString("base64url");
}
function decodeBase64url(str) {
return Buffer.from(str, "base64url");
}
function varuintSize(value) {
let size = 1;
while (value >= 128) {
size++;
value >>>= 7;
}
return size;
}
class Serializer {
#data;
#buffer;
#view;
#offset = 0;
#rootKeys;
constructor(data) {
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() {
this.#writeHeader();
this.#writeInputNodes();
this.#writeOutputNodes();
this.#writeRoots();
return {
strings: this.#data.strings,
graph: encodeBase64url(new Uint8Array(this.#buffer, 0, this.#offset))
};
}
#writeVaruint(value) {
while (value >= 128) {
this.#view.setUint8(this.#offset++, value & 127 | 128);
value >>>= 7;
}
this.#view.setUint8(this.#offset++, value);
}
#writeOptionalVaruint(value) {
this.#writeVaruint(value === void 0 ? 0 : value + 1);
}
#writeByte(value) {
this.#view.setUint8(this.#offset, value);
this.#offset += 1;
}
#writeU16(value) {
this.#view.setUint16(this.#offset, value, true);
this.#offset += 2;
}
#calculateBufferSize() {
let size = 0;
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;
size += varuintSize(edge.childNodeId === void 0 ? 0 : edge.childNodeId + 1);
size += varuintSize(edge.enumNameIndex === void 0 ? 0 : edge.enumNameIndex + 1);
size += 1;
}
}
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 === void 0 ? 0 : edge.argsNodeId + 1);
size += varuintSize(edge.outputNodeId === void 0 ? 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 === void 0 ? 0 : root.argsNodeId + 1);
size += varuintSize(root.outputNodeId === void 0 ? 0 : root.outputNodeId + 1);
}
return size;
}
#writeHeader() {
this.#writeVaruint(this.#data.inputNodes.length);
this.#writeVaruint(this.#data.outputNodes.length);
this.#writeVaruint(this.#rootKeys.length);
}
#writeInputNodes() {
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() {
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() {
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;
#view;
#offset = 0;
constructor(serialized) {
this.#serialized = serialized;
const bytes = decodeBase64url(serialized.graph);
this.#view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
}
deserialize() {
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() {
let value = 0;
let shift = 0;
let byte;
do {
byte = this.#view.getUint8(this.#offset++);
value |= (byte & 127) << shift;
shift += 7;
} while (byte >= 128);
return value;
}
#readOptionalVaruint() {
const value = this.#readVaruint();
return value === 0 ? void 0 : value - 1;
}
#readByte() {
const value = this.#view.getUint8(this.#offset);
this.#offset += 1;
return value;
}
#readU16() {
const value = this.#view.getUint16(this.#offset, true);
this.#offset += 2;
return value;
}
#readHeader() {
const inputNodeCount = this.#readVaruint();
const outputNodeCount = this.#readVaruint();
const rootCount = this.#readVaruint();
return { inputNodeCount, outputNodeCount, rootCount };
}
#readInputNodes(count) {
const inputNodes = [];
for (let i = 0; i < count; i++) {
const edgeCount = this.#readVaruint();
const edges = {};
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 = { flags };
if (scalarMask !== 0) edge.scalarMask = scalarMask;
if (childNodeId !== void 0) edge.childNodeId = childNodeId;
if (enumNameIndex !== void 0) edge.enumNameIndex = enumNameIndex;
edges[fieldIndex] = edge;
}
inputNodes.push({ edges });
}
return inputNodes;
}
#readOutputNodes(count) {
const outputNodes = [];
for (let i = 0; i < count; i++) {
const edgeCount = this.#readVaruint();
const edges = {};
for (let j = 0; j < edgeCount; j++) {
const fieldIndex = this.#readVaruint();
const argsNodeId = this.#readOptionalVaruint();
const outputNodeId = this.#readOptionalVaruint();
const edge = {};
if (argsNodeId !== void 0) edge.argsNodeId = argsNodeId;
if (outputNodeId !== void 0) edge.outputNodeId = outputNodeId;
edges[fieldIndex] = edge;
}
outputNodes.push({ edges });
}
return outputNodes;
}
#readRoots(count) {
const roots = {};
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 = {};
if (argsNodeId !== void 0) root.argsNodeId = argsNodeId;
if (outputNodeId !== void 0) root.outputNodeId = outputNodeId;
roots[key] = root;
}
return roots;
}
}
export {
deserializeParamGraph,
serializeParamGraph
};
"use strict";
var import_vitest = require("vitest");
var import_serialization = require("./serialization");
(0, import_vitest.describe)("param-graph serialization", () => {
(0, import_vitest.test)("roundtrip with empty data", () => {
const data = {
strings: ["root1"],
inputNodes: [],
outputNodes: [],
roots: { root1: {} }
};
const serialized = (0, import_serialization.serializeParamGraph)(data);
const deserialized = (0, import_serialization.deserializeParamGraph)(serialized);
(0, import_vitest.expect)(deserialized.strings).toEqual(data.strings);
(0, import_vitest.expect)(deserialized.inputNodes).toEqual(data.inputNodes);
(0, import_vitest.expect)(deserialized.outputNodes).toEqual(data.outputNodes);
(0, import_vitest.expect)(deserialized.roots).toEqual(data.roots);
});
(0, import_vitest.test)("roundtrip with small data", () => {
const data = {
strings: ["findMany", "where", "id"],
inputNodes: [{ edges: { 1: { flags: 0, scalarMask: 1 } } }],
outputNodes: [{ edges: { 2: { argsNodeId: 0 } } }],
roots: { findMany: { argsNodeId: 0, outputNodeId: 0 } }
};
const serialized = (0, import_serialization.serializeParamGraph)(data);
const deserialized = (0, import_serialization.deserializeParamGraph)(serialized);
(0, import_vitest.expect)(deserialized.strings).toEqual(data.strings);
(0, import_vitest.expect)(deserialized.inputNodes.length).toBe(data.inputNodes.length);
(0, import_vitest.expect)(deserialized.outputNodes.length).toBe(data.outputNodes.length);
(0, import_vitest.expect)(Object.keys(deserialized.roots)).toEqual(Object.keys(data.roots));
});
(0, import_vitest.test)("roundtrip with multiple nodes and edges", () => {
const data = {
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 = (0, import_serialization.serializeParamGraph)(data);
const deserialized = (0, import_serialization.deserializeParamGraph)(serialized);
(0, import_vitest.expect)(deserialized.inputNodes.length).toBe(2);
(0, import_vitest.expect)(deserialized.outputNodes.length).toBe(2);
(0, import_vitest.expect)(Object.keys(deserialized.roots).length).toBe(3);
const inputEdge = deserialized.inputNodes[0].edges[3];
(0, import_vitest.expect)(inputEdge.flags).toBe(1);
(0, import_vitest.expect)(inputEdge.scalarMask).toBe(1);
(0, import_vitest.expect)(inputEdge.childNodeId).toBe(1);
const enumEdge = deserialized.inputNodes[1].edges[5];
(0, import_vitest.expect)(enumEdge.flags).toBe(2);
(0, import_vitest.expect)(enumEdge.enumNameIndex).toBe(7);
});
(0, import_vitest.test)("handles undefined values correctly", () => {
const data = {
strings: ["root"],
inputNodes: [{ edges: { 0: { flags: 0 } } }],
outputNodes: [{ edges: { 0: {} } }],
roots: { root: { argsNodeId: 0 } }
};
const serialized = (0, import_serialization.serializeParamGraph)(data);
const deserialized = (0, import_serialization.deserializeParamGraph)(serialized);
(0, import_vitest.expect)(deserialized.inputNodes[0].edges[0].childNodeId).toBeUndefined();
(0, import_vitest.expect)(deserialized.inputNodes[0].edges[0].scalarMask).toBeUndefined();
(0, import_vitest.expect)(deserialized.inputNodes[0].edges[0].enumNameIndex).toBeUndefined();
(0, import_vitest.expect)(deserialized.outputNodes[0].edges[0].argsNodeId).toBeUndefined();
(0, import_vitest.expect)(deserialized.outputNodes[0].edges[0].outputNodeId).toBeUndefined();
(0, import_vitest.expect)(deserialized.roots["root"].outputNodeId).toBeUndefined();
});
(0, import_vitest.test)("base64url encoding produces URL-safe output", () => {
const data = {
strings: ["test"],
inputNodes: [{ edges: { 255: { flags: 255, scalarMask: 65535, childNodeId: 0, enumNameIndex: 0 } } }],
outputNodes: [],
roots: { test: { argsNodeId: 0 } }
};
const serialized = (0, import_serialization.serializeParamGraph)(data);
(0, import_vitest.expect)(serialized.graph).toMatch(/^[A-Za-z0-9_-]+$/);
});
(0, import_vitest.test)("handles large indices requiring multi-byte varints (128-16383)", () => {
const strings = Array.from({ length: 200 }, (_, i) => `field${i}`);
const data = {
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 = (0, import_serialization.serializeParamGraph)(data);
const deserialized = (0, import_serialization.deserializeParamGraph)(serialized);
(0, import_vitest.expect)(deserialized.inputNodes[0].edges[128].flags).toBe(1);
(0, import_vitest.expect)(deserialized.inputNodes[0].edges[128].childNodeId).toBe(150);
(0, import_vitest.expect)(deserialized.inputNodes[0].edges[150].flags).toBe(2);
(0, import_vitest.expect)(deserialized.inputNodes[0].edges[150].enumNameIndex).toBe(180);
(0, import_vitest.expect)(deserialized.outputNodes[0].edges[199].argsNodeId).toBe(0);
(0, import_vitest.expect)(deserialized.outputNodes[0].edges[199].outputNodeId).toBe(0);
});
(0, import_vitest.test)("handles very large indices requiring 3-byte varints (16384+)", () => {
const strings = Array.from({ length: 17e3 }, (_, i) => `f${i}`);
const data = {
strings,
inputNodes: [
{
edges: {
16384: { flags: 1, childNodeId: 16500 }
}
}
],
outputNodes: [{ edges: { 16999: { argsNodeId: 0, outputNodeId: 0 } } }],
roots: { f0: { argsNodeId: 0, outputNodeId: 0 } }
};
const serialized = (0, import_serialization.serializeParamGraph)(data);
const deserialized = (0, import_serialization.deserializeParamGraph)(serialized);
(0, import_vitest.expect)(deserialized.inputNodes[0].edges[16384].flags).toBe(1);
(0, import_vitest.expect)(deserialized.inputNodes[0].edges[16384].childNodeId).toBe(16500);
(0, import_vitest.expect)(deserialized.outputNodes[0].edges[16999].argsNodeId).toBe(0);
});
(0, import_vitest.test)("varint boundary values encode and decode correctly", () => {
const boundaryValues = [0, 1, 127, 128, 16383, 16384];
for (const value of boundaryValues) {
const strings = Array.from({ length: Math.max(value + 1, 2) }, (_, i) => `s${i}`);
const data = {
strings,
inputNodes: [{ edges: { [value]: { flags: 0 } } }],
outputNodes: [],
roots: { s0: {} }
};
const serialized = (0, import_serialization.serializeParamGraph)(data);
const deserialized = (0, import_serialization.deserializeParamGraph)(serialized);
(0, import_vitest.expect)(deserialized.inputNodes[0].edges[value]).toBeDefined();
(0, import_vitest.expect)(deserialized.inputNodes[0].edges[value].flags).toBe(0);
}
});
(0, import_vitest.test)("optional value 0 is correctly distinguished from undefined", () => {
const data = {
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 = (0, import_serialization.serializeParamGraph)(data);
const deserialized = (0, import_serialization.deserializeParamGraph)(serialized);
(0, import_vitest.expect)(deserialized.inputNodes[0].edges[1].childNodeId).toBe(0);
(0, import_vitest.expect)(deserialized.outputNodes[0].edges[1].argsNodeId).toBe(0);
(0, import_vitest.expect)(deserialized.outputNodes[0].edges[1].outputNodeId).toBe(0);
(0, import_vitest.expect)(deserialized.roots["root"].argsNodeId).toBe(0);
(0, import_vitest.expect)(deserialized.roots["root"].outputNodeId).toBe(0);
});
});
import { describe, expect, test } from "vitest";
import { deserializeParamGraph, serializeParamGraph } from "./serialization";
describe("param-graph serialization", () => {
test("roundtrip with empty data", () => {
const data = {
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 = {
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 = {
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);
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 = {
strings: ["root"],
inputNodes: [{ edges: { 0: { flags: 0 } } }],
outputNodes: [{ edges: { 0: {} } }],
roots: { root: { argsNodeId: 0 } }
};
const serialized = serializeParamGraph(data);
const deserialized = deserializeParamGraph(serialized);
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 = {
strings: ["test"],
inputNodes: [{ edges: { 255: { flags: 255, scalarMask: 65535, childNodeId: 0, enumNameIndex: 0 } } }],
outputNodes: [],
roots: { test: { argsNodeId: 0 } }
};
const serialized = serializeParamGraph(data);
expect(serialized.graph).toMatch(/^[A-Za-z0-9_-]+$/);
});
test("handles large indices requiring multi-byte varints (128-16383)", () => {
const strings = Array.from({ length: 200 }, (_, i) => `field${i}`);
const data = {
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+)", () => {
const strings = Array.from({ length: 17e3 }, (_, i) => `f${i}`);
const data = {
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", () => {
const boundaryValues = [0, 1, 127, 128, 16383, 16384];
for (const value of boundaryValues) {
const strings = Array.from({ length: Math.max(value + 1, 2) }, (_, i) => `s${i}`);
const data = {
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 = {
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);
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);
});
});
/**
* 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<string, RootEntryData>;
}
/**
* Input node data: describes parameterizable fields in an input object.
*/
export interface InputNodeData {
/** Map from string-table index to edge descriptor */
edges: Record<number, InputEdgeData>;
}
/**
* Output node data: describes fields in a selection set.
*/
export interface OutputNodeData {
/** Map from string-table index to edge descriptor */
edges: Record<number, OutputEdgeData>;
}
/**
* 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;
}
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var types_exports = {};
module.exports = __toCommonJS(types_exports);
+6
-1

@@ -1,2 +0,7 @@

export type { EdgeFlagValue, InputEdge, InputNode, NodeId, OutputEdge, OutputNode, ParamGraph, RootEntry, ScalarMaskValue, } from './param-graph';
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';
+14
-6

@@ -21,17 +21,25 @@ "use strict";

__export(index_exports, {
EdgeFlag: () => import_param_graph.EdgeFlag,
ScalarMask: () => import_param_graph.ScalarMask,
getScalarMask: () => import_param_graph.getScalarMask,
hasFlag: () => import_param_graph.hasFlag,
scalarTypeToMask: () => import_param_graph.scalarTypeToMask
EdgeFlag: () => import_param_graph2.EdgeFlag,
ParamGraph: () => import_param_graph.ParamGraph,
ScalarMask: () => import_param_graph2.ScalarMask,
deserializeParamGraph: () => import_serialization.deserializeParamGraph,
getScalarMask: () => import_param_graph2.getScalarMask,
hasFlag: () => import_param_graph2.hasFlag,
scalarTypeToMask: () => import_param_graph2.scalarTypeToMask,
serializeParamGraph: () => import_serialization.serializeParamGraph
});
module.exports = __toCommonJS(index_exports);
var import_param_graph = require("./param-graph");
var import_param_graph2 = require("./param-graph");
var import_serialization = require("./serialization");
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
EdgeFlag,
ParamGraph,
ScalarMask,
deserializeParamGraph,
getScalarMask,
hasFlag,
scalarTypeToMask
scalarTypeToMask,
serializeParamGraph
});

@@ -0,8 +1,13 @@

import { ParamGraph } from "./param-graph";
import { EdgeFlag, getScalarMask, hasFlag, ScalarMask, scalarTypeToMask } from "./param-graph";
import { deserializeParamGraph, serializeParamGraph } from "./serialization";
export {
EdgeFlag,
ParamGraph,
ScalarMask,
deserializeParamGraph,
getScalarMask,
hasFlag,
scalarTypeToMask
scalarTypeToMask,
serializeParamGraph
};
/**
* ParamGraph: Compact schema for runtime parameterization.
* ParamGraph: Runtime class for schema-aware parameterization.
*
* This data structure is generated from DMMF at client generation time
* and embedded in the generated client. It enables schema-aware
* parameterization where values are only parameterized when both schema
* rules and runtime value types agree.
* 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 type { InputEdgeData, InputNodeData, OutputEdgeData, OutputNodeData, ParamGraphData, RootEntryData } from './types';
/**
* Compact schema embedded in the generated client.
* Function type for looking up enum values by name.
* This allows ParamGraph to remain decoupled from RuntimeDataModel.
*/
export type ParamGraph = {
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 declare class ParamGraph {
#private;
private constructor();
/**
* String table to avoid repeating field names.
* Field names are referenced by index throughout the graph.
* Creates a ParamGraph from serialized format.
* This is the primary factory method for runtime use.
*/
s: string[];
static deserialize(serialized: SerializedParamGraph, enumLookup: EnumLookup): ParamGraph;
/**
* User enum names for runtime membership checks.
* Values are looked up via `runtimeDataModel.enums[enumName].values`.
* Creates a ParamGraph from builder data.
* Used by the builder for testing and direct construction.
*/
e: string[];
static fromData(data: ParamGraphData, enumLookup: EnumLookup): ParamGraph;
/**
* Input nodes used for argument objects and input types.
* Each node describes which fields are parameterizable or lead to
* parameterizable descendants.
* Look up a root entry by "Model.action" or "action".
*/
i: InputNode[];
root(key: string): RootEntry | undefined;
/**
* Output nodes used for selection traversal.
* Each node describes which fields have arguments or lead to
* nested selections with arguments.
* Get an input node by ID.
*/
o: OutputNode[];
inputNode(id: number | undefined): InputNode | undefined;
/**
* Root mapping: "Model.action" or "action" (for non-model ops).
* Points to the args node (input) and root output node.
* Get an output node by ID.
*/
r: Record<string, RootEntry>;
};
/**
* Entry point for a root operation.
*/
export type RootEntry = {
/** Args node id (into `i` array) */
a?: NodeId;
/** Output node id (into `o` array) */
o?: NodeId;
};
/**
* Node ID is an index into `i` or `o` array.
*/
export type NodeId = number;
/**
* Input node: describes parameterizable fields in an input object.
* Only fields that are parameterizable or lead to parameterizable
* descendants are present.
*/
export type InputNode = {
outputNode(id: number | undefined): OutputNode | undefined;
/**
* Map from string-table index to edge descriptor.
* Omitted if the node has no fields (shouldn't happen in practice).
* Get an input edge for a field name within a node.
*/
f?: Record<number, InputEdge>;
};
/**
* Output node: describes fields in a selection set that have args
* or nested selections that may contain parameterizable args.
*/
export type OutputNode = {
inputEdge(node: InputNode | undefined, fieldName: string): InputEdge | undefined;
/**
* Map from string-table index to edge descriptor.
* Get an output edge for a field name within a node.
*/
f?: Record<number, OutputEdge>;
};
/**
* Edge descriptor for input fields.
* Encodes what kinds of values the field accepts and how to handle them.
*/
export type InputEdge = {
outputEdge(node: OutputNode | undefined, fieldName: string): OutputEdge | undefined;
/**
* Bit flags describing field capabilities.
* See EdgeFlag enum below.
* Get enum values for an edge that references a user enum.
* Returns undefined if the edge doesn't reference an enum.
*/
k: number;
enumValues(edge: InputEdge | undefined): readonly string[] | undefined;
/**
* Child input node id (for object values or list of objects).
* Present when the field accepts input object types.
* Get a string from the string table by index.
*/
c?: NodeId;
/**
* Scalar type mask for allowed scalar categories.
* Present when field accepts scalar values.
* See ScalarMask enum below.
*/
m?: number;
/**
* Enum name id (index into `en` array).
* Present when field accepts a user enum without a plain String scalar.
* Used for runtime membership validation.
*/
e?: number;
};
getString(index: number): string | undefined;
}
/**
* Edge descriptor for output fields.
* Bit flags for InputEdge.flags describing what the field accepts.
*/
export type OutputEdge = {
/** Args node for this field (if it accepts arguments) */
a?: NodeId;
/** Next output node for nested selection traversal */
o?: NodeId;
};
/**
* Bit flags for InputEdge.k describing what the field accepts.
*/
export declare const EdgeFlag: {

@@ -151,3 +135,3 @@ /**

* Bit mask for scalar type categories.
* Used in InputEdge.m to validate runtime value types.
* Used in InputEdge.scalarMask to validate runtime value types.
*/

@@ -178,1 +162,2 @@ export declare const ScalarMask: {

export declare function scalarTypeToMask(typeName: string): number;
export type { InputEdgeData, InputNodeData, OutputEdgeData, OutputNodeData, ParamGraphData, RootEntryData };

@@ -22,2 +22,3 @@ "use strict";

EdgeFlag: () => EdgeFlag,
ParamGraph: () => ParamGraph,
ScalarMask: () => ScalarMask,

@@ -29,2 +30,132 @@ getScalarMask: () => getScalarMask,

module.exports = __toCommonJS(param_graph_exports);
var import_serialization = require("./serialization");
class ParamGraph {
#data;
#stringIndex;
#enumLookup;
constructor(data, enumLookup) {
this.#data = data;
this.#enumLookup = enumLookup;
this.#stringIndex = /* @__PURE__ */ 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, enumLookup) {
const data = (0, import_serialization.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, enumLookup) {
return new ParamGraph(data, enumLookup);
}
/**
* Look up a root entry by "Model.action" or "action".
*/
root(key) {
const entry = this.#data.roots[key];
if (!entry) {
return void 0;
}
return {
argsNodeId: entry.argsNodeId,
outputNodeId: entry.outputNodeId
};
}
/**
* Get an input node by ID.
*/
inputNode(id) {
if (id === void 0 || id < 0 || id >= this.#data.inputNodes.length) {
return void 0;
}
return { id };
}
/**
* Get an output node by ID.
*/
outputNode(id) {
if (id === void 0 || id < 0 || id >= this.#data.outputNodes.length) {
return void 0;
}
return { id };
}
/**
* Get an input edge for a field name within a node.
*/
inputEdge(node, fieldName) {
if (!node) {
return void 0;
}
const nodeData = this.#data.inputNodes[node.id];
if (!nodeData) {
return void 0;
}
const fieldIndex = this.#stringIndex.get(fieldName);
if (fieldIndex === void 0) {
return void 0;
}
const edge = nodeData.edges[fieldIndex];
if (!edge) {
return void 0;
}
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, fieldName) {
if (!node) {
return void 0;
}
const nodeData = this.#data.outputNodes[node.id];
if (!nodeData) {
return void 0;
}
const fieldIndex = this.#stringIndex.get(fieldName);
if (fieldIndex === void 0) {
return void 0;
}
const edge = nodeData.edges[fieldIndex];
if (!edge) {
return void 0;
}
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) {
if (edge?.enumNameIndex === void 0) {
return void 0;
}
const enumName = this.#data.strings[edge.enumNameIndex];
if (!enumName) {
return void 0;
}
return this.#enumLookup(enumName);
}
/**
* Get a string from the string table by index.
*/
getString(index) {
return this.#data.strings[index];
}
}
const EdgeFlag = {

@@ -74,6 +205,6 @@ /**

function hasFlag(edge, flag) {
return (edge.k & flag) !== 0;
return (edge.flags & flag) !== 0;
}
function getScalarMask(edge) {
return edge.m ?? 0;
return edge.scalarMask;
}

@@ -108,2 +239,3 @@ function scalarTypeToMask(typeName) {

EdgeFlag,
ParamGraph,
ScalarMask,

@@ -110,0 +242,0 @@ getScalarMask,

@@ -0,1 +1,131 @@

import { deserializeParamGraph } from "./serialization";
class ParamGraph {
#data;
#stringIndex;
#enumLookup;
constructor(data, enumLookup) {
this.#data = data;
this.#enumLookup = enumLookup;
this.#stringIndex = /* @__PURE__ */ 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, enumLookup) {
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, enumLookup) {
return new ParamGraph(data, enumLookup);
}
/**
* Look up a root entry by "Model.action" or "action".
*/
root(key) {
const entry = this.#data.roots[key];
if (!entry) {
return void 0;
}
return {
argsNodeId: entry.argsNodeId,
outputNodeId: entry.outputNodeId
};
}
/**
* Get an input node by ID.
*/
inputNode(id) {
if (id === void 0 || id < 0 || id >= this.#data.inputNodes.length) {
return void 0;
}
return { id };
}
/**
* Get an output node by ID.
*/
outputNode(id) {
if (id === void 0 || id < 0 || id >= this.#data.outputNodes.length) {
return void 0;
}
return { id };
}
/**
* Get an input edge for a field name within a node.
*/
inputEdge(node, fieldName) {
if (!node) {
return void 0;
}
const nodeData = this.#data.inputNodes[node.id];
if (!nodeData) {
return void 0;
}
const fieldIndex = this.#stringIndex.get(fieldName);
if (fieldIndex === void 0) {
return void 0;
}
const edge = nodeData.edges[fieldIndex];
if (!edge) {
return void 0;
}
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, fieldName) {
if (!node) {
return void 0;
}
const nodeData = this.#data.outputNodes[node.id];
if (!nodeData) {
return void 0;
}
const fieldIndex = this.#stringIndex.get(fieldName);
if (fieldIndex === void 0) {
return void 0;
}
const edge = nodeData.edges[fieldIndex];
if (!edge) {
return void 0;
}
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) {
if (edge?.enumNameIndex === void 0) {
return void 0;
}
const enumName = this.#data.strings[edge.enumNameIndex];
if (!enumName) {
return void 0;
}
return this.#enumLookup(enumName);
}
/**
* Get a string from the string table by index.
*/
getString(index) {
return this.#data.strings[index];
}
}
const EdgeFlag = {

@@ -45,6 +175,6 @@ /**

function hasFlag(edge, flag) {
return (edge.k & flag) !== 0;
return (edge.flags & flag) !== 0;
}
function getScalarMask(edge) {
return edge.m ?? 0;
return edge.scalarMask;
}

@@ -78,2 +208,3 @@ function scalarTypeToMask(typeName) {

EdgeFlag,
ParamGraph,
ScalarMask,

@@ -80,0 +211,0 @@ getScalarMask,

{
"name": "@prisma/param-graph",
"version": "7.3.0-integration-parameterization.15",
"version": "7.4.0-dev.22",
"description": "This package is intended for Prisma's internal use",

@@ -32,4 +32,5 @@ "main": "dist/index.js",

"dev": "DEV=true tsx helpers/build.ts",
"build": "tsx helpers/build.ts"
"build": "tsx helpers/build.ts",
"test": "vitest run"
}
}