{"version":3,"file":"mongo-contract-serializer-C9yUH1Ze.mjs","names":["arktypeType"],"sources":["../src/core/ir/mongo-contract-serializer-base.ts","../src/core/ir/mongo-contract-serializer.ts"],"sourcesContent":["import { validateContractDomain } from '@prisma-next/contract/validate-domain';\nimport type { ContractSerializer } from '@prisma-next/framework-components/control';\nimport {\n  type AnyEntityKindDescriptor,\n  hydrateNamespaceEntities,\n} from '@prisma-next/framework-components/ir';\nimport {\n  createMongoContractSchema,\n  type MongoContract,\n  MongoContractSchema,\n  type MongoNamespaceEntries,\n  validateMongoStorage,\n} from '@prisma-next/mongo-contract';\nimport { mongoContractCanonicalizationHooks } from '@prisma-next/mongo-contract/canonicalization-hooks';\nimport { composeMongoEntityKinds } from '@prisma-next/mongo-contract/entity-kinds';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport type { JsonObject } from '@prisma-next/utils/json';\nimport { type as arktypeType, type Type } from 'arktype';\n\n/**\n * Mongo family `ContractSerializer` abstract base. Owns the family-shared\n * deserialization pipeline:\n *\n * 1. Structural validation against the Mongo contract arktype schema\n *    (`MongoContractSchema`).\n * 2. Framework-shared domain validation (`validateContractDomain`).\n * 3. Family-shared storage validation (`validateMongoStorage`).\n *\n * The validated value is handed to the target via the\n * `constructTargetContract` hook, which wraps the plain-JSON shape in\n * the family-layer `MongoStorage` class instance (carrying the\n * target-supplied `namespaces` map). Targets that need to add\n * structural checks beyond the family default can override\n * `parseMongoContractStructure`.\n *\n * Default `serializeContract` is identity over the contract — Mongo\n * target classes carry JSON-clean fields by construction, so the value\n * can be `JSON.stringify`'d directly. Targets that need on-the-way-out\n * canonicalization override `serializeContract`.\n */\nexport abstract class MongoContractSerializerBase<TContract>\n  implements ContractSerializer<TContract>\n{\n  private readonly contractSchema: Type<unknown> | undefined;\n  private readonly entryKinds: ReadonlyMap<string, AnyEntityKindDescriptor>;\n\n  constructor(\n    validatorFragments?: ReadonlyMap<string, Type<unknown>>,\n    packEntityKinds: readonly AnyEntityKindDescriptor[] = [],\n  ) {\n    this.entryKinds = composeMongoEntityKinds(packEntityKinds);\n    this.contractSchema =\n      validatorFragments !== undefined && validatorFragments.size > 0\n        ? createMongoContractSchema(validatorFragments)\n        : undefined;\n  }\n\n  deserializeContract<T extends TContract = TContract>(json: unknown): T {\n    const validated = this.parseMongoContractStructure(json);\n    return this.constructTargetContract(validated) as T;\n  }\n\n  serializeContract(contract: TContract): JsonObject {\n    // Mongo contract class fields are JSON-clean by construction; the\n    // cast asserts that. Targets that need to canonicalize on the way\n    // out override this method.\n    return contract as unknown as JsonObject;\n  }\n\n  /**\n   * Preserve empty `collections` maps and per-collection payloads. Mongo\n   * collections legitimately serialize empty (a declared collection with no\n   * schema is valid); SQL tables never do — that asymmetry lives here rather\n   * than in the family-agnostic canonicalizer.\n   */\n  shouldPreserveEmpty = mongoContractCanonicalizationHooks.shouldPreserveEmpty;\n\n  /**\n   * Family-shared structural validation: parse against the Mongo\n   * contract arktype schema, then run framework-shared domain + Mongo\n   * family storage checks, then hydrate the validated tree into Mongo\n   * Contract IR class instances. Targets can override to add\n   * target-specific structural checks; most targets accept the family\n   * default.\n   *\n   * The returned `MongoContract` carries class instances under\n   * `storage.namespaces[namespaceId].entries.collection[collectionName]` (each value is a\n   * `MongoCollection`, with nested `MongoIndex` / `MongoValidator` /\n   * `MongoCollectionOptions` constructed by the `MongoCollection` constructor).\n   * The rest of the contract envelope (models, valueObjects, capabilities, …)\n   * remains in plain-JSON form; those IR layers are handled by sibling\n   * subsystems and don't sit behind this SPI.\n   */\n  protected parseMongoContractStructure(json: unknown): MongoContract {\n    const schema = this.contractSchema ?? MongoContractSchema;\n    const parsed = schema(json);\n    if (parsed instanceof arktypeType.errors) {\n      throw new Error(`Contract structural validation failed: ${parsed.summary}`);\n    }\n\n    // arktype's `infer`d type for `MongoContractSchema` is structurally\n    // equivalent to `MongoContract` (both describe the same on-disk JSON\n    // envelope) but not nominally so: the arktype DSL produces a type whose\n    // optional/readonly profile, narrowed string-literal positions, and\n    // utility-type wrappings (`Type.infer`, `Out`, …) differ from the\n    // hand-authored `MongoContract<S>` generic surface. The schema and\n    // the type are kept in lockstep by the round-trip fixtures under\n    // `test/validate.test.ts`. The hydration walk below additionally\n    // re-shapes `storage.namespaces.*.collections` from plain data into IR-class\n    // instances, so the `MongoContract` returned here carries class identity\n    // under those collections maps (and transitively under `indexes` / `validator`\n    // / `options`).\n    const validatedShape = parsed as unknown as MongoContract;\n\n    const hydratedContract = this.hydrateMongoContract(validatedShape);\n\n    validateContractDomain(hydratedContract);\n    validateMongoStorage(hydratedContract);\n\n    return hydratedContract;\n  }\n\n  /**\n   * Walk a structurally-validated Mongo contract and hydrate each namespace's\n   * entries via the registered entity-kind descriptors. Unknown kinds throw (fail-closed),\n   * preserving the existing Mongo serializer semantics.\n   */\n  protected hydrateMongoContract(contract: MongoContract): MongoContract {\n    const rawNamespaces = contract.storage.namespaces;\n    const hydratedNamespaces = Object.fromEntries(\n      Object.entries(rawNamespaces).map(([nsId, nsEnvelope]) => {\n        const hydratedEntries = hydrateNamespaceEntities(\n          blindCast<\n            Readonly<Record<string, Readonly<Record<string, unknown>>>>,\n            'nsEnvelope.entries has been validated by the Mongo contract schema before hydration'\n          >(nsEnvelope.entries),\n          this.entryKinds,\n          'fail',\n          nsId,\n        );\n        return [\n          nsId,\n          {\n            ...nsEnvelope,\n            id: nsEnvelope.id,\n            entries: blindCast<\n              MongoNamespaceEntries,\n              'this.entryKinds (composeMongoEntityKinds plus any pack kinds) supplies the collection→MongoCollection descriptor, so this open-dict result holds the typed collection member MongoNamespaceEntries declares; the descriptor Map erases that per-kind Node type from the return.'\n            >(hydratedEntries),\n          },\n        ];\n      }),\n    );\n    return {\n      ...contract,\n      storage: {\n        ...contract.storage,\n        namespaces: hydratedNamespaces,\n      },\n    };\n  }\n\n  /**\n   * Target-specific class construction from the validated structural\n   * data. The target wraps the contract envelope in the family-layer\n   * `MongoStorage` class instance, supplying the `namespaces` map\n   * (target concretions like `MongoTargetUnboundDatabase`). The\n   * leaf collection / index shapes are already family-layer IR-class\n   * instances after the hydration walk above.\n   */\n  protected abstract constructTargetContract(validated: MongoContract): TContract;\n}\n","import type { MongoContract } from '@prisma-next/mongo-contract';\nimport { MongoContractSerializerBase } from './mongo-contract-serializer-base';\n\n/**\n * Default Mongo family `ContractSerializer` concretion. Inherits the\n * Mongo-shared deserialization pipeline (structural validation +\n * collection-level hydration) and falls through `constructTargetContract`\n * with the validated `MongoContract` shape. Family-level call sites\n * (family-instance methods, family-layer tests that don't reach into\n * a target descriptor) instantiate this directly; targets with their\n * own storage concretion (`target-mongo`'s `MongoTargetContractSerializer`)\n * override `constructTargetContract` to wrap the storage shape.\n */\nexport class MongoContractSerializer extends MongoContractSerializerBase<MongoContract> {\n  protected constructTargetContract(validated: MongoContract): MongoContract {\n    return validated;\n  }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,IAAsB,8BAAtB,MAEA;CACE;CACA;CAEA,YACE,oBACA,kBAAsD,CAAC,GACvD;EACA,KAAK,aAAa,wBAAwB,eAAe;EACzD,KAAK,iBACH,uBAAuB,KAAA,KAAa,mBAAmB,OAAO,IAC1D,0BAA0B,kBAAkB,IAC5C,KAAA;CACR;CAEA,oBAAqD,MAAkB;EACrE,MAAM,YAAY,KAAK,4BAA4B,IAAI;EACvD,OAAO,KAAK,wBAAwB,SAAS;CAC/C;CAEA,kBAAkB,UAAiC;EAIjD,OAAO;CACT;;;;;;;CAQA,sBAAsB,mCAAmC;;;;;;;;;;;;;;;;;CAkBzD,4BAAsC,MAA8B;EAElE,MAAM,UADS,KAAK,kBAAkB,oBAAA,CAChB,IAAI;EAC1B,IAAI,kBAAkBA,KAAY,QAChC,MAAM,IAAI,MAAM,0CAA0C,OAAO,SAAS;EAe5E,MAAM,iBAAiB;EAEvB,MAAM,mBAAmB,KAAK,qBAAqB,cAAc;EAEjE,uBAAuB,gBAAgB;EACvC,qBAAqB,gBAAgB;EAErC,OAAO;CACT;;;;;;CAOA,qBAA+B,UAAwC;EACrE,MAAM,gBAAgB,SAAS,QAAQ;EACvC,MAAM,qBAAqB,OAAO,YAChC,OAAO,QAAQ,aAAa,CAAC,CAAC,KAAK,CAAC,MAAM,gBAAgB;GACxD,MAAM,kBAAkB,yBACtB,UAGE,WAAW,OAAO,GACpB,KAAK,YACL,QACA,IACF;GACA,OAAO,CACL,MACA;IACE,GAAG;IACH,IAAI,WAAW;IACf,SAAS,UAGP,eAAe;GACnB,CACF;EACF,CAAC,CACH;EACA,OAAO;GACL,GAAG;GACH,SAAS;IACP,GAAG,SAAS;IACZ,YAAY;GACd;EACF;CACF;AAWF;;;;;;;;;;;;;AC9JA,IAAa,0BAAb,cAA6C,4BAA2C;CACtF,wBAAkC,WAAyC;EACzE,OAAO;CACT;AACF"}