@prisma-next/mongo-codec 0.5.0-dev.60 → 0.5.0-dev.62

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,10 +4,10 @@ Codec interface and registry for MongoDB value serialization.
4
4
 
5
5
  ## Responsibilities
6
6
 
7
- - **Codec interface**: `MongoCodec<Id, TTraits, TWire, TInput>` — declares how a JS value translates to and from the BSON-shaped wire format the Mongo driver exchanges, plus the JSON-safe form stored in contract artifacts. Carries trait annotations (`equality`, `order`, `boolean`, `numeric`, `textual`, `vector`) for operator gating. Same four generics as the framework `Codec` base.
7
+ - **Codec interface**: `MongoCodec<Id, TTraits, TWire, TInput>` — declares how a JS value translates to and from the BSON-shaped wire format the Mongo driver exchanges, plus the JSON-safe form stored in contract artifacts. Same four generics as the framework `Codec` base; the codec instance carries only `id` plus the four conversion methods. Trait annotations (`equality`, `order`, `boolean`, `numeric`, `textual`, `vector`) for operator gating live on the unified `CodecDescriptor` (see [ADR 208](../../../../docs/architecture%20docs/adrs/ADR%20208%20-%20Higher-order%20codecs%20for%20parameterized%20types.md)).
8
8
  - **Codec factory**: `mongoCodec()` — creates frozen codec instances from a config object. Both `encode` and `decode` are required so `TInput` and `TWire` are always covered by an explicit author function — the factory installs no identity fallback. `encode` and `decode` may be authored as sync or async functions and are lifted to Promise-returning query-time methods automatically. Build-time methods (`encodeJson`, `decodeJson`) are synchronous and default to identity when omitted.
9
- - **Codec registry**: `MongoCodecRegistry` and `createMongoCodecRegistry()` — a map-based container that stores and retrieves codecs by ID, with duplicate-ID protection
10
- - **Type-level helpers**: `MongoCodecInput<T>` and `MongoCodecTraits<T>` for extracting the input JS type and traits from codec types
9
+ - **Codec registry**: `MongoCodecRegistry` and `newMongoCodecRegistry()` — a map-based container that stores and retrieves codecs by ID, with duplicate-ID protection
10
+ - **Type-level helper**: `MongoCodecInput<T>` for extracting the JS application type from a codec type. Trait metadata lives on the unified `CodecDescriptor` (see [ADR 208](../../../../docs/architecture%20docs/adrs/ADR%20208%20-%20Higher-order%20codecs%20for%20parameterized%20types.md)).
11
11
 
12
12
  ## Examples
13
13
 
@@ -15,7 +15,6 @@ Codec interface and registry for MongoDB value serialization.
15
15
  // Sync authoring:
16
16
  const intCodec = mongoCodec({
17
17
  typeId: 'mongo/int@1',
18
- targetTypes: ['int'],
19
18
  encode: (v: number) => v,
20
19
  decode: (w: number) => w,
21
20
  encodeJson: (v: number) => v,
@@ -25,7 +24,6 @@ const intCodec = mongoCodec({
25
24
  // Async authoring (e.g. KMS-backed encryption): same factory, same shape.
26
25
  const secretCodec = mongoCodec({
27
26
  typeId: 'mongo/secret@1',
28
- targetTypes: ['string'],
29
27
  encode: async (v: string) => encrypt(v, await getKey()),
30
28
  decode: async (w: string) => decrypt(w, await getKey()),
31
29
  encodeJson: (v: string) => v,
@@ -41,7 +39,6 @@ Codecs receive a second `ctx` options argument; you may ignore it. The Mongo run
41
39
  // Forward ctx.signal to a network SDK so aborted queries stop the round-trip.
42
40
  const kmsSecretCodec = mongoCodec({
43
41
  typeId: 'mongo/kms-secret@1',
44
- targetTypes: ['string'],
45
42
  encode: async (v: string, ctx) =>
46
43
  kms.encrypt({ plaintext: v }, { signal: ctx?.signal }),
47
44
  decode: async (w: string, ctx) =>
package/dist/index.d.mts CHANGED
@@ -4,22 +4,13 @@ import { Codec, CodecCallContext, CodecTrait } from "@prisma-next/framework-comp
4
4
  //#region src/codecs.d.ts
5
5
  type MongoCodecTrait = CodecTrait;
6
6
  /**
7
- * A codec for the Mongo target. Translates between an application value
8
- * and the BSON-shaped wire form the Mongo driver exchanges, and between
9
- * an application value and the JSON form stored in contract artifacts.
7
+ * A codec for the Mongo target. Translates between an application value and the BSON-shaped wire form the Mongo driver exchanges, and between an application value and the JSON form stored in contract artifacts.
10
8
  *
11
- * Same shape as the framework codec base — see `Codec` in
12
- * `@prisma-next/framework-components/codec` for the contract. The alias
13
- * exists so Mongo-specific metadata can be added here in future without
14
- * touching the framework base.
9
+ * Same shape as the framework codec base — see `Codec` in `@prisma-next/framework-components/codec` for the contract. Codec-id-keyed static metadata (`traits`, `targetTypes`, `renderOutputType`) lives on the unified {@link import('@prisma-next/framework-components/codec').CodecDescriptor}; Mongo's full migration to descriptor-side registration is tracked under TML-2324.
15
10
  */
16
- type MongoCodec<Id extends string = string, TTraits$1 extends readonly MongoCodecTrait[] = readonly MongoCodecTrait[], TWire = unknown, TInput = unknown> = Codec<Id, TTraits$1, TWire, TInput>;
11
+ interface MongoCodec<Id extends string = string, TTraits extends readonly MongoCodecTrait[] = readonly MongoCodecTrait[], TWire = unknown, TInput = unknown> extends Codec<Id, TTraits, TWire, TInput> {}
17
12
  /**
18
- * Conditional bundle for `encodeJson`/`decodeJson`: when `TInput` is
19
- * structurally assignable to `JsonValue` the identity defaults are
20
- * sound and both fields are optional; otherwise both fields are
21
- * required so an author cannot silently produce a non-JSON-safe
22
- * contract artifact.
13
+ * Conditional bundle for `encodeJson`/`decodeJson`: when `TInput` is structurally assignable to `JsonValue` the identity defaults are sound and both fields are optional; otherwise both fields are required so an author cannot silently produce a non-JSON-safe contract artifact.
23
14
  */
24
15
  type JsonRoundTripConfig<TInput> = [TInput] extends [JsonValue] ? {
25
16
  encodeJson?: (value: TInput) => JsonValue;
@@ -31,29 +22,19 @@ type JsonRoundTripConfig<TInput> = [TInput] extends [JsonValue] ? {
31
22
  /**
32
23
  * Construct a Mongo codec from author functions.
33
24
  *
34
- * Author `encode` and `decode` as sync or async functions; the factory
35
- * produces a {@link MongoCodec} whose query-time methods follow the
36
- * boundary contract documented on the framework {@link BaseCodec}.
37
- * Authors receive a second `ctx` options argument carrying the per-call
38
- * context; ignore it if you don't need it.
25
+ * Author `encode` and `decode` as sync or async functions; the factory produces a {@link MongoCodec} whose query-time methods follow the boundary contract documented on the framework {@link BaseCodec}. Authors receive a second `ctx` options argument carrying the per-call context; ignore it if you don't need it.
39
26
  *
40
- * Both `encode` and `decode` are required so `TInput` and `TWire` are
41
- * always covered by an explicit author function — the factory installs
42
- * no identity fallback. `encodeJson` and `decodeJson` default to identity
43
- * **only when `TInput` is assignable to `JsonValue`**; otherwise both are
44
- * required so the contract artifact stays JSON-safe.
27
+ * Both `encode` and `decode` are required so `TInput` and `TWire` are always covered by an explicit author function — the factory installs no identity fallback. `encodeJson` and `decodeJson` default to identity **only when `TInput` is assignable to `JsonValue`**; otherwise both are required so the contract artifact stays JSON-safe.
28
+ *
29
+ * Codec-id-keyed static metadata (`traits`, `targetTypes`, `renderOutputType`) lives on the unified `CodecDescriptor` rather than on the codec instance itself (TML-2357).
45
30
  */
46
- declare function mongoCodec<Id extends string, const TTraits$1 extends readonly MongoCodecTrait[] = readonly [], TWire = unknown, TInput = unknown>(config: {
31
+ declare function mongoCodec<Id extends string, const TTraits extends readonly MongoCodecTrait[] = readonly [], TWire = unknown, TInput = unknown>(config: {
47
32
  typeId: Id;
48
- targetTypes: readonly string[];
49
- traits?: TTraits$1;
50
33
  encode: (value: TInput, ctx: CodecCallContext) => TWire | Promise<TWire>;
51
34
  decode: (wire: TWire, ctx: CodecCallContext) => TInput | Promise<TInput>;
52
- renderOutputType?: (typeParams: Record<string, unknown>) => string | undefined;
53
- } & JsonRoundTripConfig<TInput>): MongoCodec<Id, TTraits$1, TWire, TInput>;
35
+ } & JsonRoundTripConfig<TInput>): MongoCodec<Id, TTraits, TWire, TInput>;
54
36
  /** Extract the JS application type carried by a Mongo codec — used both as `encode` input and as `decode` output. */
55
37
  type MongoCodecInput<T> = T extends MongoCodec<string, readonly MongoCodecTrait[], unknown, infer TInput> ? TInput : never;
56
- type MongoCodecTraits<T> = T extends MongoCodec<string, infer TTraits> ? TTraits[number] & MongoCodecTrait : never;
57
38
  //#endregion
58
39
  //#region src/codec-registry.d.ts
59
40
  interface MongoCodecRegistry {
@@ -63,7 +44,10 @@ interface MongoCodecRegistry {
63
44
  [Symbol.iterator](): Iterator<MongoCodec<string>>;
64
45
  values(): IterableIterator<MongoCodec<string>>;
65
46
  }
66
- declare function createMongoCodecRegistry(): MongoCodecRegistry;
47
+ /**
48
+ * Create a new Mongo codec registry. Inline object literal — no class implementation; the registry is just a private `Map` with the documented surface methods.
49
+ */
50
+ declare function newMongoCodecRegistry(): MongoCodecRegistry;
67
51
  //#endregion
68
- export { type MongoCodec, type MongoCodecInput, type MongoCodecRegistry, type MongoCodecTrait, type MongoCodecTraits, createMongoCodecRegistry, mongoCodec };
52
+ export { type MongoCodec, type MongoCodecInput, type MongoCodecRegistry, type MongoCodecTrait, mongoCodec, newMongoCodecRegistry };
69
53
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/codecs.ts","../src/codec-registry.ts"],"sourcesContent":[],"mappings":";;;;KAQY,eAAA,GAAkB;;AAA9B;AAYA;;;;;;;;AAKa,KALD,UAKC,CAAA,WAAA,MAAA,GAAA,MAAA,EAAA,kBAAA,SAHc,eAGd,EAAA,GAAA,SAH2C,eAG3C,EAAA,EAAA,QAAA,OAAA,EAAA,SAAA,OAAA,CAAA,GAAT,KAAS,CAAC,EAAD,EAAK,SAAL,EAAc,KAAd,EAAqB,MAArB,CAAA;AAA6B;;;;;;;KASrC,mBAMqB,CAAA,MAAA,CAAA,GAAA,CANU,MAMV,CAAA,SAAA,CAN2B,SAM3B,CAAA,GAAA;EAAW,UAAA,CAAA,EAAA,CAAA,KAAA,EAJV,MAIU,EAAA,GAJC,SAID;EACZ,UAAA,CAAA,EAAA,CAAA,IAAA,EAJC,SAID,EAAA,GAJe,MAIf;CAAc,GAAA;EAAM,UAAA,EAAA,CAAA,KAAA,EADnB,MACmB,EAAA,GADR,SACQ;EAkB7B,UAAA,EAAA,CAAU,IAAA,EAlBD,SAkBC,EAAA,GAlBa,MAkBb;CAEO;;;;;;;;;;;;;;;;AAYnB,iBAdE,UAcF,CAAA,WAAA,MAAA,EAAA,wBAAA,SAZmB,eAYnB,EAAA,GAAA,SAAA,EAAA,EAAA,QAAA,OAAA,EAAA,SAAA,OAAA,CAAA,CAAA,MAAA,EAAA;EAAI,MAAA,EAPN,EAOM;EAAS,WAAA,EAAA,SAAA,MAAA,EAAA;EAAO,MAAA,CAAA,EALrB,SAKqB;EAA/B,MAAA,EAAA,CAAA,KAAA,EAJiB,MAIjB,EAAA,GAAA,EAJ8B,gBAI9B,EAAA,GAJmD,KAInD,GAJ2D,OAI3D,CAJmE,KAInE,CAAA;EAAU,MAAA,EAAA,CAAA,IAAA,EAHM,KAGN,EAAA,GAAA,EAHkB,gBAGlB,EAAA,GAHuC,MAGvC,GAHgD,OAGhD,CAHwD,MAGxD,CAAA;EA0CD,gBAAA,CAAA,EAAe,CAAA,UAAA,EA5CS,MA4CT,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,GAAA,MAAA,GAAA,SAAA;CACzB,GA5CI,mBA4CJ,CA5CwB,MA4CxB,CAAA,CAAA,EA3CC,UA2CD,CA3CY,EA2CZ,EA3CgB,SA2ChB,EA3CyB,KA2CzB,EA3CgC,MA2ChC,CAAA;;AAAU,KADA,eACA,CAAA,CAAA,CAAA,GAAV,CAAU,SAAA,UAAA,CAAA,MAAA,EAAA,SAA4B,eAA5B,EAAA,EAAA,OAAA,EAAA,KAAA,OAAA,CAAA,GAAA,MAAA,GAAA,KAAA;AAAU,KAEV,gBAFU,CAAA,CAAA,CAAA,GAGpB,CAHoB,SAGV,UAHU,CAAA,MAAA,EAAA,KAAA,QAAA,CAAA,GAG0B,OAH1B,CAAA,MAAA,CAAA,GAG4C,eAH5C,GAAA,KAAA;;;UClHL,kBAAA;mBACE;;EDKP,QAAA,CAAA,KAAA,ECHM,UDGS,CAAA,MAAG,CAAA,CAAA,EAAA,IAAU;EAY5B,CAAA,MAAA,CAAA,QAAU,GAAA,ECdC,QDcD,CCdU,UDcV,CAAA,MAAA,CAAA,CAAA;EAEK,MAAA,EAAA,ECff,gBDee,CCfE,UDeF,CAAA,MAAA,CAAA,CAAA;;AAGb,iBCYE,wBAAA,CAAA,CDZF,ECY8B,kBDZ9B"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/codecs.ts","../src/codec-registry.ts"],"sourcesContent":[],"mappings":";;;;KAOY,eAAA,GAAkB;;AAA9B;AAOA;;;AAKoB,UALH,UAKG,CAAA,WAAA,MAAA,GAAA,MAAA,EAAA,gBAAA,SAHO,eAGP,EAAA,GAAA,SAHoC,eAGpC,EAAA,EAAA,QAAA,OAAA,EAAA,SAAA,OAAA,CAAA,SAAV,KAAU,CAAA,EAAA,EAAI,OAAJ,EAAa,KAAb,EAAoB,MAApB,CAAA,CAAA;;;;KAKf,mBALc,CAAA,MAAA,CAAA,GAAA,CAKiB,MALjB,CAAA,SAAA,CAKkC,SALlC,CAAA,GAAA;EAKd,UAAA,CAAA,EAAA,CAAA,KAAA,EAEsB,MAFH,EAAA,GAEc,SAFd;EAAY,UAAA,CAAA,EAAA,CAAA,IAAA,EAGV,SAHU,EAAA,GAGI,MAHJ;CAAiB,GAAA;EAE1B,UAAA,EAAA,CAAA,KAAA,EAID,MAJC,EAAA,GAIU,SAJV;EAAW,UAAA,EAAA,CAAA,IAAA,EAKb,SALa,EAAA,GAKC,MALD;CACZ;;;;;;;AAgB1B;;;AAQoB,iBARJ,UAQI,CAAA,WAAA,MAAA,EAAA,sBAAA,SANa,eAMb,EAAA,GAAA,SAAA,EAAA,EAAA,QAAA,OAAA,EAAA,SAAA,OAAA,CAAA,CAAA,MAAA,EAAA;EAAa,MAAA,EADrB,EACqB;EAAqB,MAAA,EAAA,CAAA,KAAA,EAAlC,MAAkC,EAAA,GAAA,EAArB,gBAAqB,EAAA,GAAA,KAAA,GAAQ,OAAR,CAAgB,KAAhB,CAAA;EAAgB,MAAA,EAAA,CAAA,IAAA,EACnD,KADmD,EAAA,GAAA,EACvC,gBADuC,EAAA,GAClB,MADkB,GACT,OADS,CACD,MADC,CAAA;CAAR,GAExD,mBAFwD,CAEpC,MAFoC,CAAA,CAAA,EAG3D,UAH2D,CAGhD,EAHgD,EAG5C,OAH4C,EAGnC,KAHmC,EAG5B,MAH4B,CAAA;;AAC/B,KAiCnB,eAjCmB,CAAA,CAAA,CAAA,GAkC7B,CAlC6B,SAkCnB,UAlCmB,CAAA,MAAA,EAAA,SAkCS,eAlCT,EAAA,EAAA,OAAA,EAAA,KAAA,OAAA,CAAA,GAAA,MAAA,GAAA,KAAA;;;UClDd,kBAAA;mBACE;;EDIP,QAAA,CAAA,KAAA,ECFM,UDES,CAAA,MAAG,CAAA,CAAA,EAAA,IAAU;EAOvB,CAAA,MAAA,CAAA,QAAU,GAAA,ECRJ,QDQI,CCRK,UDQL,CAAA,MAAA,CAAA,CAAA;EAEA,MAAA,EAAA,ECTf,gBDSe,CCTE,UDSF,CAAA,MAAA,CAAA,CAAA;;;;;AAGa,iBCNxB,qBAAA,CAAA,CDMwB,ECNC,kBDMD"}
package/dist/index.mjs CHANGED
@@ -1,27 +1,21 @@
1
- import { ifDefined } from "@prisma-next/utils/defined";
2
-
3
1
  //#region src/codec-registry.ts
4
- var MongoCodecRegistryImpl = class {
5
- #byId = /* @__PURE__ */ new Map();
6
- get(id) {
7
- return this.#byId.get(id);
8
- }
9
- has(id) {
10
- return this.#byId.has(id);
11
- }
12
- register(codec) {
13
- if (this.#byId.has(codec.id)) throw new Error(`Codec with ID '${codec.id}' is already registered`);
14
- this.#byId.set(codec.id, codec);
15
- }
16
- *[Symbol.iterator]() {
17
- yield* this.#byId.values();
18
- }
19
- values() {
20
- return this.#byId.values();
21
- }
22
- };
23
- function createMongoCodecRegistry() {
24
- return new MongoCodecRegistryImpl();
2
+ /**
3
+ * Create a new Mongo codec registry. Inline object literal — no class implementation; the registry is just a private `Map` with the documented surface methods.
4
+ */
5
+ function newMongoCodecRegistry() {
6
+ const byId = /* @__PURE__ */ new Map();
7
+ return {
8
+ get: (id) => byId.get(id),
9
+ has: (id) => byId.has(id),
10
+ register: (codec) => {
11
+ if (byId.has(codec.id)) throw new Error(`Codec with ID '${codec.id}' is already registered`);
12
+ byId.set(codec.id, codec);
13
+ },
14
+ values: () => byId.values(),
15
+ [Symbol.iterator]: function* () {
16
+ yield* byId.values();
17
+ }
18
+ };
25
19
  }
26
20
 
27
21
  //#endregion
@@ -29,17 +23,11 @@ function createMongoCodecRegistry() {
29
23
  /**
30
24
  * Construct a Mongo codec from author functions.
31
25
  *
32
- * Author `encode` and `decode` as sync or async functions; the factory
33
- * produces a {@link MongoCodec} whose query-time methods follow the
34
- * boundary contract documented on the framework {@link BaseCodec}.
35
- * Authors receive a second `ctx` options argument carrying the per-call
36
- * context; ignore it if you don't need it.
26
+ * Author `encode` and `decode` as sync or async functions; the factory produces a {@link MongoCodec} whose query-time methods follow the boundary contract documented on the framework {@link BaseCodec}. Authors receive a second `ctx` options argument carrying the per-call context; ignore it if you don't need it.
27
+ *
28
+ * Both `encode` and `decode` are required so `TInput` and `TWire` are always covered by an explicit author function — the factory installs no identity fallback. `encodeJson` and `decodeJson` default to identity **only when `TInput` is assignable to `JsonValue`**; otherwise both are required so the contract artifact stays JSON-safe.
37
29
  *
38
- * Both `encode` and `decode` are required so `TInput` and `TWire` are
39
- * always covered by an explicit author function — the factory installs
40
- * no identity fallback. `encodeJson` and `decodeJson` default to identity
41
- * **only when `TInput` is assignable to `JsonValue`**; otherwise both are
42
- * required so the contract artifact stays JSON-safe.
30
+ * Codec-id-keyed static metadata (`traits`, `targetTypes`, `renderOutputType`) lives on the unified `CodecDescriptor` rather than on the codec instance itself (TML-2357).
43
31
  */
44
32
  function mongoCodec(config) {
45
33
  const identity = (v) => v;
@@ -48,9 +36,6 @@ function mongoCodec(config) {
48
36
  const widenedConfig = config;
49
37
  return {
50
38
  id: config.typeId,
51
- targetTypes: config.targetTypes,
52
- ...ifDefined("traits", config.traits ? Object.freeze([...config.traits]) : void 0),
53
- ...ifDefined("renderOutputType", config.renderOutputType),
54
39
  encode: (value, ctx) => {
55
40
  try {
56
41
  return Promise.resolve(userEncode(value, ctx));
@@ -71,5 +56,5 @@ function mongoCodec(config) {
71
56
  }
72
57
 
73
58
  //#endregion
74
- export { createMongoCodecRegistry, mongoCodec };
59
+ export { mongoCodec, newMongoCodecRegistry };
75
60
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["#byId"],"sources":["../src/codec-registry.ts","../src/codecs.ts"],"sourcesContent":["import type { MongoCodec } from './codecs';\n\nexport interface MongoCodecRegistry {\n get(id: string): MongoCodec<string> | undefined;\n has(id: string): boolean;\n register(codec: MongoCodec<string>): void;\n [Symbol.iterator](): Iterator<MongoCodec<string>>;\n values(): IterableIterator<MongoCodec<string>>;\n}\n\nclass MongoCodecRegistryImpl implements MongoCodecRegistry {\n readonly #byId = new Map<string, MongoCodec<string>>();\n\n get(id: string): MongoCodec<string> | undefined {\n return this.#byId.get(id);\n }\n\n has(id: string): boolean {\n return this.#byId.has(id);\n }\n\n register(codec: MongoCodec<string>): void {\n if (this.#byId.has(codec.id)) {\n throw new Error(`Codec with ID '${codec.id}' is already registered`);\n }\n this.#byId.set(codec.id, codec);\n }\n\n *[Symbol.iterator](): Iterator<MongoCodec<string>> {\n yield* this.#byId.values();\n }\n\n values(): IterableIterator<MongoCodec<string>> {\n return this.#byId.values();\n }\n}\n\nexport function createMongoCodecRegistry(): MongoCodecRegistry {\n return new MongoCodecRegistryImpl();\n}\n","import type { JsonValue } from '@prisma-next/contract/types';\nimport type {\n Codec as BaseCodec,\n CodecCallContext,\n CodecTrait,\n} from '@prisma-next/framework-components/codec';\nimport { ifDefined } from '@prisma-next/utils/defined';\n\nexport type MongoCodecTrait = CodecTrait;\n\n/**\n * A codec for the Mongo target. Translates between an application value\n * and the BSON-shaped wire form the Mongo driver exchanges, and between\n * an application value and the JSON form stored in contract artifacts.\n *\n * Same shape as the framework codec base — see `Codec` in\n * `@prisma-next/framework-components/codec` for the contract. The alias\n * exists so Mongo-specific metadata can be added here in future without\n * touching the framework base.\n */\nexport type MongoCodec<\n Id extends string = string,\n TTraits extends readonly MongoCodecTrait[] = readonly MongoCodecTrait[],\n TWire = unknown,\n TInput = unknown,\n> = BaseCodec<Id, TTraits, TWire, TInput>;\n\n/**\n * Conditional bundle for `encodeJson`/`decodeJson`: when `TInput` is\n * structurally assignable to `JsonValue` the identity defaults are\n * sound and both fields are optional; otherwise both fields are\n * required so an author cannot silently produce a non-JSON-safe\n * contract artifact.\n */\ntype JsonRoundTripConfig<TInput> = [TInput] extends [JsonValue]\n ? {\n encodeJson?: (value: TInput) => JsonValue;\n decodeJson?: (json: JsonValue) => TInput;\n }\n : {\n encodeJson: (value: TInput) => JsonValue;\n decodeJson: (json: JsonValue) => TInput;\n };\n\n/**\n * Construct a Mongo codec from author functions.\n *\n * Author `encode` and `decode` as sync or async functions; the factory\n * produces a {@link MongoCodec} whose query-time methods follow the\n * boundary contract documented on the framework {@link BaseCodec}.\n * Authors receive a second `ctx` options argument carrying the per-call\n * context; ignore it if you don't need it.\n *\n * Both `encode` and `decode` are required so `TInput` and `TWire` are\n * always covered by an explicit author function — the factory installs\n * no identity fallback. `encodeJson` and `decodeJson` default to identity\n * **only when `TInput` is assignable to `JsonValue`**; otherwise both are\n * required so the contract artifact stays JSON-safe.\n */\nexport function mongoCodec<\n Id extends string,\n const TTraits extends readonly MongoCodecTrait[] = readonly [],\n TWire = unknown,\n TInput = unknown,\n>(\n config: {\n typeId: Id;\n targetTypes: readonly string[];\n traits?: TTraits;\n encode: (value: TInput, ctx: CodecCallContext) => TWire | Promise<TWire>;\n decode: (wire: TWire, ctx: CodecCallContext) => TInput | Promise<TInput>;\n renderOutputType?: (typeParams: Record<string, unknown>) => string | undefined;\n } & JsonRoundTripConfig<TInput>,\n): MongoCodec<Id, TTraits, TWire, TInput> {\n const identity = (v: unknown) => v;\n // The runtime allocates one `CodecCallContext` per `runtime.execute()`\n // call (no caller-supplied `signal` produces `{}` instead of `undefined`)\n // and threads it as a non-optional reference to every codec call. The\n // author surface keeps the second parameter optional so single-arg\n // `(value) => …` authors continue to satisfy the signature via\n // TypeScript's bivariance for trailing parameters.\n const userEncode = config.encode;\n const userDecode = config.decode;\n const widenedConfig = config as {\n encodeJson?: (value: TInput) => JsonValue;\n decodeJson?: (json: JsonValue) => TInput;\n };\n return {\n id: config.typeId,\n targetTypes: config.targetTypes,\n ...ifDefined(\n 'traits',\n config.traits ? (Object.freeze([...config.traits]) as TTraits) : undefined,\n ),\n ...ifDefined('renderOutputType', config.renderOutputType),\n encode: (value, ctx) => {\n try {\n return Promise.resolve(userEncode(value, ctx));\n } catch (error) {\n return Promise.reject(error);\n }\n },\n decode: (wire, ctx) => {\n try {\n return Promise.resolve(userDecode(wire, ctx));\n } catch (error) {\n return Promise.reject(error);\n }\n },\n encodeJson: (widenedConfig.encodeJson ?? identity) as (value: TInput) => JsonValue,\n decodeJson: (widenedConfig.decodeJson ?? identity) as (json: JsonValue) => TInput,\n };\n}\n\n/** Extract the JS application type carried by a Mongo codec — used both as `encode` input and as `decode` output. */\nexport type MongoCodecInput<T> =\n T extends MongoCodec<string, readonly MongoCodecTrait[], unknown, infer TInput> ? TInput : never;\n\nexport type MongoCodecTraits<T> =\n T extends MongoCodec<string, infer TTraits> ? TTraits[number] & MongoCodecTrait : never;\n"],"mappings":";;;AAUA,IAAM,yBAAN,MAA2D;CACzD,CAASA,uBAAQ,IAAI,KAAiC;CAEtD,IAAI,IAA4C;AAC9C,SAAO,MAAKA,KAAM,IAAI,GAAG;;CAG3B,IAAI,IAAqB;AACvB,SAAO,MAAKA,KAAM,IAAI,GAAG;;CAG3B,SAAS,OAAiC;AACxC,MAAI,MAAKA,KAAM,IAAI,MAAM,GAAG,CAC1B,OAAM,IAAI,MAAM,kBAAkB,MAAM,GAAG,yBAAyB;AAEtE,QAAKA,KAAM,IAAI,MAAM,IAAI,MAAM;;CAGjC,EAAE,OAAO,YAA0C;AACjD,SAAO,MAAKA,KAAM,QAAQ;;CAG5B,SAA+C;AAC7C,SAAO,MAAKA,KAAM,QAAQ;;;AAI9B,SAAgB,2BAA+C;AAC7D,QAAO,IAAI,wBAAwB;;;;;;;;;;;;;;;;;;;;ACqBrC,SAAgB,WAMd,QAQwC;CACxC,MAAM,YAAY,MAAe;CAOjC,MAAM,aAAa,OAAO;CAC1B,MAAM,aAAa,OAAO;CAC1B,MAAM,gBAAgB;AAItB,QAAO;EACL,IAAI,OAAO;EACX,aAAa,OAAO;EACpB,GAAG,UACD,UACA,OAAO,SAAU,OAAO,OAAO,CAAC,GAAG,OAAO,OAAO,CAAC,GAAe,OAClE;EACD,GAAG,UAAU,oBAAoB,OAAO,iBAAiB;EACzD,SAAS,OAAO,QAAQ;AACtB,OAAI;AACF,WAAO,QAAQ,QAAQ,WAAW,OAAO,IAAI,CAAC;YACvC,OAAO;AACd,WAAO,QAAQ,OAAO,MAAM;;;EAGhC,SAAS,MAAM,QAAQ;AACrB,OAAI;AACF,WAAO,QAAQ,QAAQ,WAAW,MAAM,IAAI,CAAC;YACtC,OAAO;AACd,WAAO,QAAQ,OAAO,MAAM;;;EAGhC,YAAa,cAAc,cAAc;EACzC,YAAa,cAAc,cAAc;EAC1C"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/codec-registry.ts","../src/codecs.ts"],"sourcesContent":["import type { MongoCodec } from './codecs';\n\nexport interface MongoCodecRegistry {\n get(id: string): MongoCodec<string> | undefined;\n has(id: string): boolean;\n register(codec: MongoCodec<string>): void;\n [Symbol.iterator](): Iterator<MongoCodec<string>>;\n values(): IterableIterator<MongoCodec<string>>;\n}\n\n/**\n * Create a new Mongo codec registry. Inline object literal — no class implementation; the registry is just a private `Map` with the documented surface methods.\n */\nexport function newMongoCodecRegistry(): MongoCodecRegistry {\n const byId = new Map<string, MongoCodec<string>>();\n return {\n get: (id) => byId.get(id),\n has: (id) => byId.has(id),\n register: (codec) => {\n if (byId.has(codec.id)) {\n throw new Error(`Codec with ID '${codec.id}' is already registered`);\n }\n byId.set(codec.id, codec);\n },\n values: () => byId.values(),\n [Symbol.iterator]: function* () {\n yield* byId.values();\n },\n };\n}\n","import type { JsonValue } from '@prisma-next/contract/types';\nimport type {\n Codec as BaseCodec,\n CodecCallContext,\n CodecTrait,\n} from '@prisma-next/framework-components/codec';\n\nexport type MongoCodecTrait = CodecTrait;\n\n/**\n * A codec for the Mongo target. Translates between an application value and the BSON-shaped wire form the Mongo driver exchanges, and between an application value and the JSON form stored in contract artifacts.\n *\n * Same shape as the framework codec base — see `Codec` in `@prisma-next/framework-components/codec` for the contract. Codec-id-keyed static metadata (`traits`, `targetTypes`, `renderOutputType`) lives on the unified {@link import('@prisma-next/framework-components/codec').CodecDescriptor}; Mongo's full migration to descriptor-side registration is tracked under TML-2324.\n */\nexport interface MongoCodec<\n Id extends string = string,\n TTraits extends readonly MongoCodecTrait[] = readonly MongoCodecTrait[],\n TWire = unknown,\n TInput = unknown,\n> extends BaseCodec<Id, TTraits, TWire, TInput> {}\n\n/**\n * Conditional bundle for `encodeJson`/`decodeJson`: when `TInput` is structurally assignable to `JsonValue` the identity defaults are sound and both fields are optional; otherwise both fields are required so an author cannot silently produce a non-JSON-safe contract artifact.\n */\ntype JsonRoundTripConfig<TInput> = [TInput] extends [JsonValue]\n ? {\n encodeJson?: (value: TInput) => JsonValue;\n decodeJson?: (json: JsonValue) => TInput;\n }\n : {\n encodeJson: (value: TInput) => JsonValue;\n decodeJson: (json: JsonValue) => TInput;\n };\n\n/**\n * Construct a Mongo codec from author functions.\n *\n * Author `encode` and `decode` as sync or async functions; the factory produces a {@link MongoCodec} whose query-time methods follow the boundary contract documented on the framework {@link BaseCodec}. Authors receive a second `ctx` options argument carrying the per-call context; ignore it if you don't need it.\n *\n * Both `encode` and `decode` are required so `TInput` and `TWire` are always covered by an explicit author function — the factory installs no identity fallback. `encodeJson` and `decodeJson` default to identity **only when `TInput` is assignable to `JsonValue`**; otherwise both are required so the contract artifact stays JSON-safe.\n *\n * Codec-id-keyed static metadata (`traits`, `targetTypes`, `renderOutputType`) lives on the unified `CodecDescriptor` rather than on the codec instance itself (TML-2357).\n */\nexport function mongoCodec<\n Id extends string,\n const TTraits extends readonly MongoCodecTrait[] = readonly [],\n TWire = unknown,\n TInput = unknown,\n>(\n config: {\n typeId: Id;\n encode: (value: TInput, ctx: CodecCallContext) => TWire | Promise<TWire>;\n decode: (wire: TWire, ctx: CodecCallContext) => TInput | Promise<TInput>;\n } & JsonRoundTripConfig<TInput>,\n): MongoCodec<Id, TTraits, TWire, TInput> {\n const identity = (v: unknown) => v;\n // The runtime allocates one `CodecCallContext` per `runtime.execute()` call (no caller-supplied `signal` produces `{}` instead of `undefined`) and threads it as a non-optional reference to every codec call. The author surface keeps the second parameter optional so single-arg `(value) => …` authors continue to satisfy the signature via TypeScript's bivariance for trailing parameters.\n const userEncode = config.encode;\n const userDecode = config.decode;\n const widenedConfig = config as {\n encodeJson?: (value: TInput) => JsonValue;\n decodeJson?: (json: JsonValue) => TInput;\n };\n return {\n id: config.typeId,\n encode: (value, ctx) => {\n try {\n return Promise.resolve(userEncode(value, ctx));\n } catch (error) {\n return Promise.reject(error);\n }\n },\n decode: (wire, ctx) => {\n try {\n return Promise.resolve(userDecode(wire, ctx));\n } catch (error) {\n return Promise.reject(error);\n }\n },\n encodeJson: (widenedConfig.encodeJson ?? identity) as (value: TInput) => JsonValue,\n decodeJson: (widenedConfig.decodeJson ?? identity) as (json: JsonValue) => TInput,\n };\n}\n\n/** Extract the JS application type carried by a Mongo codec — used both as `encode` input and as `decode` output. */\nexport type MongoCodecInput<T> =\n T extends MongoCodec<string, readonly MongoCodecTrait[], unknown, infer TInput> ? TInput : never;\n"],"mappings":";;;;AAaA,SAAgB,wBAA4C;CAC1D,MAAM,uBAAO,IAAI,KAAiC;AAClD,QAAO;EACL,MAAM,OAAO,KAAK,IAAI,GAAG;EACzB,MAAM,OAAO,KAAK,IAAI,GAAG;EACzB,WAAW,UAAU;AACnB,OAAI,KAAK,IAAI,MAAM,GAAG,CACpB,OAAM,IAAI,MAAM,kBAAkB,MAAM,GAAG,yBAAyB;AAEtE,QAAK,IAAI,MAAM,IAAI,MAAM;;EAE3B,cAAc,KAAK,QAAQ;EAC3B,CAAC,OAAO,WAAW,aAAa;AAC9B,UAAO,KAAK,QAAQ;;EAEvB;;;;;;;;;;;;;;ACeH,SAAgB,WAMd,QAKwC;CACxC,MAAM,YAAY,MAAe;CAEjC,MAAM,aAAa,OAAO;CAC1B,MAAM,aAAa,OAAO;CAC1B,MAAM,gBAAgB;AAItB,QAAO;EACL,IAAI,OAAO;EACX,SAAS,OAAO,QAAQ;AACtB,OAAI;AACF,WAAO,QAAQ,QAAQ,WAAW,OAAO,IAAI,CAAC;YACvC,OAAO;AACd,WAAO,QAAQ,OAAO,MAAM;;;EAGhC,SAAS,MAAM,QAAQ;AACrB,OAAI;AACF,WAAO,QAAQ,QAAQ,WAAW,MAAM,IAAI,CAAC;YACtC,OAAO;AACd,WAAO,QAAQ,OAAO,MAAM;;;EAGhC,YAAa,cAAc,cAAc;EACzC,YAAa,cAAc,cAAc;EAC1C"}
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@prisma-next/mongo-codec",
3
- "version": "0.5.0-dev.60",
3
+ "version": "0.5.0-dev.62",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "description": "Codec interface and registry for Prisma Next MongoDB support",
8
8
  "dependencies": {
9
- "@prisma-next/contract": "0.5.0-dev.60",
10
- "@prisma-next/framework-components": "0.5.0-dev.60",
11
- "@prisma-next/utils": "0.5.0-dev.60"
9
+ "@prisma-next/contract": "0.5.0-dev.62",
10
+ "@prisma-next/framework-components": "0.5.0-dev.62",
11
+ "@prisma-next/utils": "0.5.0-dev.62"
12
12
  },
13
13
  "devDependencies": {
14
14
  "tsdown": "0.18.4",
@@ -8,33 +8,23 @@ export interface MongoCodecRegistry {
8
8
  values(): IterableIterator<MongoCodec<string>>;
9
9
  }
10
10
 
11
- class MongoCodecRegistryImpl implements MongoCodecRegistry {
12
- readonly #byId = new Map<string, MongoCodec<string>>();
13
-
14
- get(id: string): MongoCodec<string> | undefined {
15
- return this.#byId.get(id);
16
- }
17
-
18
- has(id: string): boolean {
19
- return this.#byId.has(id);
20
- }
21
-
22
- register(codec: MongoCodec<string>): void {
23
- if (this.#byId.has(codec.id)) {
24
- throw new Error(`Codec with ID '${codec.id}' is already registered`);
25
- }
26
- this.#byId.set(codec.id, codec);
27
- }
28
-
29
- *[Symbol.iterator](): Iterator<MongoCodec<string>> {
30
- yield* this.#byId.values();
31
- }
32
-
33
- values(): IterableIterator<MongoCodec<string>> {
34
- return this.#byId.values();
35
- }
36
- }
37
-
38
- export function createMongoCodecRegistry(): MongoCodecRegistry {
39
- return new MongoCodecRegistryImpl();
11
+ /**
12
+ * Create a new Mongo codec registry. Inline object literal — no class implementation; the registry is just a private `Map` with the documented surface methods.
13
+ */
14
+ export function newMongoCodecRegistry(): MongoCodecRegistry {
15
+ const byId = new Map<string, MongoCodec<string>>();
16
+ return {
17
+ get: (id) => byId.get(id),
18
+ has: (id) => byId.has(id),
19
+ register: (codec) => {
20
+ if (byId.has(codec.id)) {
21
+ throw new Error(`Codec with ID '${codec.id}' is already registered`);
22
+ }
23
+ byId.set(codec.id, codec);
24
+ },
25
+ values: () => byId.values(),
26
+ [Symbol.iterator]: function* () {
27
+ yield* byId.values();
28
+ },
29
+ };
40
30
  }
package/src/codecs.ts CHANGED
@@ -4,33 +4,23 @@ import type {
4
4
  CodecCallContext,
5
5
  CodecTrait,
6
6
  } from '@prisma-next/framework-components/codec';
7
- import { ifDefined } from '@prisma-next/utils/defined';
8
7
 
9
8
  export type MongoCodecTrait = CodecTrait;
10
9
 
11
10
  /**
12
- * A codec for the Mongo target. Translates between an application value
13
- * and the BSON-shaped wire form the Mongo driver exchanges, and between
14
- * an application value and the JSON form stored in contract artifacts.
11
+ * A codec for the Mongo target. Translates between an application value and the BSON-shaped wire form the Mongo driver exchanges, and between an application value and the JSON form stored in contract artifacts.
15
12
  *
16
- * Same shape as the framework codec base — see `Codec` in
17
- * `@prisma-next/framework-components/codec` for the contract. The alias
18
- * exists so Mongo-specific metadata can be added here in future without
19
- * touching the framework base.
13
+ * Same shape as the framework codec base — see `Codec` in `@prisma-next/framework-components/codec` for the contract. Codec-id-keyed static metadata (`traits`, `targetTypes`, `renderOutputType`) lives on the unified {@link import('@prisma-next/framework-components/codec').CodecDescriptor}; Mongo's full migration to descriptor-side registration is tracked under TML-2324.
20
14
  */
21
- export type MongoCodec<
15
+ export interface MongoCodec<
22
16
  Id extends string = string,
23
17
  TTraits extends readonly MongoCodecTrait[] = readonly MongoCodecTrait[],
24
18
  TWire = unknown,
25
19
  TInput = unknown,
26
- > = BaseCodec<Id, TTraits, TWire, TInput>;
20
+ > extends BaseCodec<Id, TTraits, TWire, TInput> {}
27
21
 
28
22
  /**
29
- * Conditional bundle for `encodeJson`/`decodeJson`: when `TInput` is
30
- * structurally assignable to `JsonValue` the identity defaults are
31
- * sound and both fields are optional; otherwise both fields are
32
- * required so an author cannot silently produce a non-JSON-safe
33
- * contract artifact.
23
+ * Conditional bundle for `encodeJson`/`decodeJson`: when `TInput` is structurally assignable to `JsonValue` the identity defaults are sound and both fields are optional; otherwise both fields are required so an author cannot silently produce a non-JSON-safe contract artifact.
34
24
  */
35
25
  type JsonRoundTripConfig<TInput> = [TInput] extends [JsonValue]
36
26
  ? {
@@ -45,17 +35,11 @@ type JsonRoundTripConfig<TInput> = [TInput] extends [JsonValue]
45
35
  /**
46
36
  * Construct a Mongo codec from author functions.
47
37
  *
48
- * Author `encode` and `decode` as sync or async functions; the factory
49
- * produces a {@link MongoCodec} whose query-time methods follow the
50
- * boundary contract documented on the framework {@link BaseCodec}.
51
- * Authors receive a second `ctx` options argument carrying the per-call
52
- * context; ignore it if you don't need it.
38
+ * Author `encode` and `decode` as sync or async functions; the factory produces a {@link MongoCodec} whose query-time methods follow the boundary contract documented on the framework {@link BaseCodec}. Authors receive a second `ctx` options argument carrying the per-call context; ignore it if you don't need it.
53
39
  *
54
- * Both `encode` and `decode` are required so `TInput` and `TWire` are
55
- * always covered by an explicit author function — the factory installs
56
- * no identity fallback. `encodeJson` and `decodeJson` default to identity
57
- * **only when `TInput` is assignable to `JsonValue`**; otherwise both are
58
- * required so the contract artifact stays JSON-safe.
40
+ * Both `encode` and `decode` are required so `TInput` and `TWire` are always covered by an explicit author function — the factory installs no identity fallback. `encodeJson` and `decodeJson` default to identity **only when `TInput` is assignable to `JsonValue`**; otherwise both are required so the contract artifact stays JSON-safe.
41
+ *
42
+ * Codec-id-keyed static metadata (`traits`, `targetTypes`, `renderOutputType`) lives on the unified `CodecDescriptor` rather than on the codec instance itself (TML-2357).
59
43
  */
60
44
  export function mongoCodec<
61
45
  Id extends string,
@@ -65,20 +49,12 @@ export function mongoCodec<
65
49
  >(
66
50
  config: {
67
51
  typeId: Id;
68
- targetTypes: readonly string[];
69
- traits?: TTraits;
70
52
  encode: (value: TInput, ctx: CodecCallContext) => TWire | Promise<TWire>;
71
53
  decode: (wire: TWire, ctx: CodecCallContext) => TInput | Promise<TInput>;
72
- renderOutputType?: (typeParams: Record<string, unknown>) => string | undefined;
73
54
  } & JsonRoundTripConfig<TInput>,
74
55
  ): MongoCodec<Id, TTraits, TWire, TInput> {
75
56
  const identity = (v: unknown) => v;
76
- // The runtime allocates one `CodecCallContext` per `runtime.execute()`
77
- // call (no caller-supplied `signal` produces `{}` instead of `undefined`)
78
- // and threads it as a non-optional reference to every codec call. The
79
- // author surface keeps the second parameter optional so single-arg
80
- // `(value) => …` authors continue to satisfy the signature via
81
- // TypeScript's bivariance for trailing parameters.
57
+ // The runtime allocates one `CodecCallContext` per `runtime.execute()` call (no caller-supplied `signal` produces `{}` instead of `undefined`) and threads it as a non-optional reference to every codec call. The author surface keeps the second parameter optional so single-arg `(value) => …` authors continue to satisfy the signature via TypeScript's bivariance for trailing parameters.
82
58
  const userEncode = config.encode;
83
59
  const userDecode = config.decode;
84
60
  const widenedConfig = config as {
@@ -87,12 +63,6 @@ export function mongoCodec<
87
63
  };
88
64
  return {
89
65
  id: config.typeId,
90
- targetTypes: config.targetTypes,
91
- ...ifDefined(
92
- 'traits',
93
- config.traits ? (Object.freeze([...config.traits]) as TTraits) : undefined,
94
- ),
95
- ...ifDefined('renderOutputType', config.renderOutputType),
96
66
  encode: (value, ctx) => {
97
67
  try {
98
68
  return Promise.resolve(userEncode(value, ctx));
@@ -115,6 +85,3 @@ export function mongoCodec<
115
85
  /** Extract the JS application type carried by a Mongo codec — used both as `encode` input and as `decode` output. */
116
86
  export type MongoCodecInput<T> =
117
87
  T extends MongoCodec<string, readonly MongoCodecTrait[], unknown, infer TInput> ? TInput : never;
118
-
119
- export type MongoCodecTraits<T> =
120
- T extends MongoCodec<string, infer TTraits> ? TTraits[number] & MongoCodecTrait : never;
@@ -1,9 +1,4 @@
1
1
  export type { MongoCodecRegistry } from '../codec-registry';
2
- export { createMongoCodecRegistry } from '../codec-registry';
3
- export type {
4
- MongoCodec,
5
- MongoCodecInput,
6
- MongoCodecTrait,
7
- MongoCodecTraits,
8
- } from '../codecs';
2
+ export { newMongoCodecRegistry } from '../codec-registry';
3
+ export type { MongoCodec, MongoCodecInput, MongoCodecTrait } from '../codecs';
9
4
  export { mongoCodec } from '../codecs';