@prisma-next/mongo-contract 0.0.1 → 0.3.0-dev.146

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.
@@ -0,0 +1,75 @@
1
+ import { Contract, ContractField, ContractModel, ContractValueObject, StorageBase } from "@prisma-next/contract/types";
2
+
3
+ //#region src/contract-types.d.ts
4
+ type MongoStorageCollection = Record<string, never>;
5
+ type MongoStorage<THash extends string = string> = StorageBase<THash> & {
6
+ readonly collections: Record<string, MongoStorageCollection>;
7
+ };
8
+ type MongoModelStorage = {
9
+ readonly collection?: string;
10
+ readonly relations?: Record<string, {
11
+ readonly field: string;
12
+ }>;
13
+ };
14
+ type MongoModelDefinition = ContractModel<MongoModelStorage>;
15
+ type MongoContract<S extends MongoStorage = MongoStorage, M extends Record<string, MongoModelDefinition> = Record<string, MongoModelDefinition>> = Contract<S, M>;
16
+ type MongoTypeMaps<TCodecTypes extends Record<string, {
17
+ output: unknown;
18
+ }> = Record<string, {
19
+ output: unknown;
20
+ }>, TOperationTypes extends Record<string, unknown> = Record<string, never>, TFieldOutputTypes extends Record<string, Record<string, unknown>> = Record<string, Record<string, unknown>>> = {
21
+ readonly codecTypes: TCodecTypes;
22
+ readonly operationTypes: TOperationTypes;
23
+ readonly fieldOutputTypes: TFieldOutputTypes;
24
+ };
25
+ type MongoTypeMapsPhantomKey = '__@prisma-next/mongo-core/typeMaps@__';
26
+ type MongoContractWithTypeMaps<TContract, TTypeMaps> = TContract & { readonly [K in MongoTypeMapsPhantomKey]?: TTypeMaps };
27
+ type ExtractMongoTypeMaps<T> = MongoTypeMapsPhantomKey extends keyof T ? NonNullable<T[MongoTypeMapsPhantomKey & keyof T]> : never;
28
+ type ExtractMongoCodecTypes<T> = ExtractMongoTypeMaps<T> extends {
29
+ codecTypes: infer C;
30
+ } ? C extends Record<string, {
31
+ output: unknown;
32
+ }> ? C : Record<string, never> : Record<string, never>;
33
+ type ExtractMongoFieldOutputTypes<T> = ExtractMongoTypeMaps<T> extends {
34
+ fieldOutputTypes: infer F;
35
+ } ? F extends Record<string, Record<string, unknown>> ? F : Record<string, never> : Record<string, never>;
36
+ type ExtractValueObjects<TContract> = TContract extends {
37
+ valueObjects: infer VO extends Record<string, ContractValueObject>;
38
+ } ? VO : Record<never, never>;
39
+ type InferFieldBaseType<TFieldType, TValueObjects extends Record<string, ContractValueObject>, TCodecTypes extends Record<string, {
40
+ output: unknown;
41
+ }>> = TFieldType extends {
42
+ kind: 'scalar';
43
+ codecId: infer CId extends string & keyof TCodecTypes;
44
+ } ? TCodecTypes[CId]['output'] : TFieldType extends {
45
+ kind: 'valueObject';
46
+ name: infer VOName extends string;
47
+ } ? VOName extends keyof TValueObjects ? { -readonly [K in keyof TValueObjects[VOName]['fields']]: InferFieldType<TValueObjects[VOName]['fields'][K], TValueObjects, TCodecTypes> } : unknown : TFieldType extends {
48
+ kind: 'union';
49
+ members: infer TMembers extends ReadonlyArray<unknown>;
50
+ } ? TMembers[number] extends infer TMember ? InferFieldBaseType<TMember, TValueObjects, TCodecTypes> : unknown : unknown;
51
+ type InferFieldType<TField extends ContractField, TValueObjects extends Record<string, ContractValueObject>, TCodecTypes extends Record<string, {
52
+ output: unknown;
53
+ }>> = TField extends {
54
+ many: true;
55
+ } ? TField['nullable'] extends true ? InferFieldBaseType<TField['type'], TValueObjects, TCodecTypes>[] | null : InferFieldBaseType<TField['type'], TValueObjects, TCodecTypes>[] : TField['nullable'] extends true ? InferFieldBaseType<TField['type'], TValueObjects, TCodecTypes> | null : InferFieldBaseType<TField['type'], TValueObjects, TCodecTypes>;
56
+ type InferModelRow<TContract extends MongoContractWithTypeMaps<MongoContract, MongoTypeMaps>, ModelName extends string & keyof TContract['models'], TFields extends Record<string, ContractField> = TContract['models'][ModelName]['fields'], TCodecTypes extends Record<string, {
57
+ output: unknown;
58
+ }> = ExtractMongoCodecTypes<TContract>, TValueObjects extends Record<string, ContractValueObject> = ExtractValueObjects<TContract>> = { -readonly [FieldName in keyof TFields]: InferFieldType<TFields[FieldName], TValueObjects, TCodecTypes> };
59
+ //#endregion
60
+ //#region src/validate-mongo-contract.d.ts
61
+ interface MongoContractIndices {
62
+ readonly variantToBase: Record<string, string>;
63
+ readonly modelToVariants: Record<string, string[]>;
64
+ }
65
+ interface ValidatedMongoContract<TContract extends MongoContract> {
66
+ readonly contract: TContract;
67
+ readonly indices: MongoContractIndices;
68
+ }
69
+ declare function validateMongoContract<TContract extends MongoContract>(value: unknown): ValidatedMongoContract<TContract>;
70
+ //#endregion
71
+ //#region src/validate-storage.d.ts
72
+ declare function validateMongoStorage(contract: MongoContract): void;
73
+ //#endregion
74
+ export { type ExtractMongoCodecTypes, type ExtractMongoFieldOutputTypes, type ExtractMongoTypeMaps, type InferModelRow, type MongoContract, type MongoContractIndices, type MongoContractWithTypeMaps, type MongoModelDefinition, type MongoModelStorage, type MongoStorage, type MongoStorageCollection, type MongoTypeMaps, type MongoTypeMapsPhantomKey, type ValidatedMongoContract, validateMongoContract, validateMongoStorage };
75
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/contract-types.ts","../src/validate-mongo-contract.ts","../src/validate-storage.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/index.mjs ADDED
@@ -0,0 +1,154 @@
1
+ import { validateContractDomain } from "@prisma-next/contract/validate-domain";
2
+ import { type } from "arktype";
3
+
4
+ //#region src/contract-schema.ts
5
+ const ScalarFieldTypeSchema = type({
6
+ "+": "reject",
7
+ kind: "'scalar'",
8
+ codecId: "string",
9
+ "typeParams?": "Record<string, unknown>"
10
+ });
11
+ const ValueObjectFieldTypeSchema = type({
12
+ "+": "reject",
13
+ kind: "'valueObject'",
14
+ name: "string"
15
+ });
16
+ const UnionFieldTypeSchema = type({
17
+ "+": "reject",
18
+ kind: "'union'",
19
+ members: ScalarFieldTypeSchema.or(ValueObjectFieldTypeSchema).array()
20
+ });
21
+ const FieldTypeSchema = ScalarFieldTypeSchema.or(ValueObjectFieldTypeSchema).or(UnionFieldTypeSchema);
22
+ const FieldSchema = type({
23
+ "+": "reject",
24
+ type: FieldTypeSchema,
25
+ "nullable?": "boolean",
26
+ "many?": "boolean",
27
+ "dict?": "boolean"
28
+ }).pipe((field) => ({
29
+ ...field,
30
+ nullable: field.nullable ?? false
31
+ }));
32
+ const RelationOnSchema = type({
33
+ "+": "reject",
34
+ localFields: "string[]",
35
+ targetFields: "string[]"
36
+ });
37
+ const RelationSchema = type({
38
+ "+": "reject",
39
+ to: "string",
40
+ cardinality: "'1:1' | '1:N' | 'N:1'",
41
+ "on?": RelationOnSchema
42
+ });
43
+ const StorageRelationEntrySchema = type({
44
+ "+": "reject",
45
+ field: "string"
46
+ });
47
+ const ModelStorageSchema = type({
48
+ "+": "reject",
49
+ "collection?": "string",
50
+ "relations?": type({ "[string]": StorageRelationEntrySchema })
51
+ });
52
+ const DiscriminatorSchema = type({
53
+ "+": "reject",
54
+ field: "string"
55
+ });
56
+ const VariantEntrySchema = type({
57
+ "+": "reject",
58
+ value: "string"
59
+ });
60
+ const ModelDefinitionSchema = type({
61
+ "+": "reject",
62
+ fields: type({ "[string]": FieldSchema }),
63
+ storage: ModelStorageSchema,
64
+ "relations?": type({ "[string]": RelationSchema }),
65
+ "discriminator?": DiscriminatorSchema,
66
+ "variants?": type({ "[string]": VariantEntrySchema }),
67
+ "base?": "string",
68
+ "owner?": "string"
69
+ });
70
+ const StorageCollectionSchema = type({ "+": "reject" });
71
+ const MongoContractSchema = type({
72
+ "+": "reject",
73
+ targetFamily: "'mongo'",
74
+ "schemaVersion?": "string",
75
+ "target?": "string",
76
+ "storageHash?": "string",
77
+ "profileHash?": "string",
78
+ roots: "Record<string, string>",
79
+ "capabilities?": "Record<string, unknown>",
80
+ "extensionPacks?": "Record<string, unknown>",
81
+ "meta?": "Record<string, unknown>",
82
+ "sources?": "Record<string, unknown>",
83
+ "_generated?": "Record<string, unknown>",
84
+ storage: type({
85
+ "+": "reject",
86
+ collections: type({ "[string]": StorageCollectionSchema }),
87
+ "storageHash?": "string"
88
+ }),
89
+ models: type({ "[string]": ModelDefinitionSchema }),
90
+ "valueObjects?": type({ "[string]": type({
91
+ "+": "reject",
92
+ fields: type({ "[string]": FieldSchema })
93
+ }) })
94
+ });
95
+
96
+ //#endregion
97
+ //#region src/validate-storage.ts
98
+ function validateMongoStorage(contract) {
99
+ const errors = [];
100
+ for (const [modelName, model] of Object.entries(contract.models)) {
101
+ if (model.storage.collection && !(model.storage.collection in contract.storage.collections)) errors.push(`Model "${modelName}" references collection "${model.storage.collection}" which is not in storage.collections`);
102
+ if (model.base) {
103
+ const baseModel = contract.models[model.base];
104
+ if (baseModel) {
105
+ const variantCollection = model.storage.collection;
106
+ const baseCollection = baseModel.storage.collection;
107
+ if (variantCollection !== baseCollection) errors.push(`Mongo does not support multi-table inheritance; variant "${modelName}" must share its base's collection ("${baseCollection ?? "(none)"}"), but has "${variantCollection ?? "(none)"}"`);
108
+ }
109
+ }
110
+ for (const [relName, relation] of Object.entries(model.relations ?? {})) {
111
+ const targetModel = contract.models[relation.to];
112
+ if (targetModel?.owner) {
113
+ if (targetModel.owner !== modelName) errors.push(`Embed relation "${relName}" targets "${relation.to}" which is owned by "${targetModel.owner}", not "${modelName}"`);
114
+ if (targetModel.storage.collection) errors.push(`Embed relation "${relName}" targets "${relation.to}" which must not have a collection`);
115
+ } else if ("on" in relation && relation.on) {
116
+ for (const localField of relation.on.localFields) if (!(localField in model.fields)) errors.push(`Reference relation "${relName}": localField "${localField}" is not a field on model "${modelName}"`);
117
+ if (targetModel) {
118
+ for (const targetField of relation.on.targetFields) if (!(targetField in targetModel.fields)) errors.push(`Reference relation "${relName}": targetField "${targetField}" is not a field on model "${relation.to}"`);
119
+ }
120
+ }
121
+ }
122
+ }
123
+ if (errors.length > 0) throw new Error(`Contract storage validation failed:\n- ${errors.join("\n- ")}`);
124
+ }
125
+
126
+ //#endregion
127
+ //#region src/validate-mongo-contract.ts
128
+ function validateMongoContract(value) {
129
+ const parsed = MongoContractSchema(value);
130
+ if (parsed instanceof type.errors) throw new Error(`Contract structural validation failed: ${parsed.summary}`);
131
+ const contract = parsed;
132
+ validateContractDomain(contract);
133
+ validateMongoStorage(contract);
134
+ return {
135
+ contract,
136
+ indices: buildIndices(contract)
137
+ };
138
+ }
139
+ function buildIndices(contract) {
140
+ const variantToBase = {};
141
+ const modelToVariants = {};
142
+ for (const [modelName, model] of Object.entries(contract.models)) {
143
+ if (model.base) variantToBase[modelName] = model.base;
144
+ if (model.variants) modelToVariants[modelName] = Object.keys(model.variants);
145
+ }
146
+ return {
147
+ variantToBase,
148
+ modelToVariants
149
+ };
150
+ }
151
+
152
+ //#endregion
153
+ export { validateMongoContract, validateMongoStorage };
154
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["errors: string[]","arktypeType","variantToBase: Record<string, string>","modelToVariants: Record<string, string[]>"],"sources":["../src/contract-schema.ts","../src/validate-storage.ts","../src/validate-mongo-contract.ts"],"sourcesContent":["import { type } from 'arktype';\n\nconst ScalarFieldTypeSchema = type({\n '+': 'reject',\n kind: \"'scalar'\",\n codecId: 'string',\n 'typeParams?': 'Record<string, unknown>',\n});\n\nconst ValueObjectFieldTypeSchema = type({\n '+': 'reject',\n kind: \"'valueObject'\",\n name: 'string',\n});\n\nconst UnionFieldTypeSchema = type({\n '+': 'reject',\n kind: \"'union'\",\n members: ScalarFieldTypeSchema.or(ValueObjectFieldTypeSchema).array(),\n});\n\nconst FieldTypeSchema = ScalarFieldTypeSchema.or(ValueObjectFieldTypeSchema).or(\n UnionFieldTypeSchema,\n);\n\nconst RawFieldSchema = type({\n '+': 'reject',\n type: FieldTypeSchema,\n 'nullable?': 'boolean',\n 'many?': 'boolean',\n 'dict?': 'boolean',\n});\n\nconst FieldSchema = RawFieldSchema.pipe((field) => ({\n ...field,\n nullable: field.nullable ?? false,\n}));\n\nconst RelationOnSchema = type({\n '+': 'reject',\n localFields: 'string[]',\n targetFields: 'string[]',\n});\n\nconst RelationSchema = type({\n '+': 'reject',\n to: 'string',\n cardinality: \"'1:1' | '1:N' | 'N:1'\",\n 'on?': RelationOnSchema,\n});\n\nconst StorageRelationEntrySchema = type({\n '+': 'reject',\n field: 'string',\n});\n\nconst ModelStorageSchema = type({\n '+': 'reject',\n 'collection?': 'string',\n 'relations?': type({ '[string]': StorageRelationEntrySchema }),\n});\n\nconst DiscriminatorSchema = type({\n '+': 'reject',\n field: 'string',\n});\n\nconst VariantEntrySchema = type({\n '+': 'reject',\n value: 'string',\n});\n\nconst ModelDefinitionSchema = type({\n '+': 'reject',\n fields: type({ '[string]': FieldSchema }),\n storage: ModelStorageSchema,\n 'relations?': type({ '[string]': RelationSchema }),\n 'discriminator?': DiscriminatorSchema,\n 'variants?': type({ '[string]': VariantEntrySchema }),\n 'base?': 'string',\n 'owner?': 'string',\n});\n\nconst StorageCollectionSchema = type({ '+': 'reject' });\n\nexport const MongoContractSchema = type({\n '+': 'reject',\n targetFamily: \"'mongo'\",\n 'schemaVersion?': 'string',\n 'target?': 'string',\n 'storageHash?': 'string',\n 'profileHash?': 'string',\n roots: 'Record<string, string>',\n 'capabilities?': 'Record<string, unknown>',\n 'extensionPacks?': 'Record<string, unknown>',\n 'meta?': 'Record<string, unknown>',\n 'sources?': 'Record<string, unknown>',\n '_generated?': 'Record<string, unknown>',\n storage: type({\n '+': 'reject',\n collections: type({ '[string]': StorageCollectionSchema }),\n 'storageHash?': 'string',\n }),\n models: type({ '[string]': ModelDefinitionSchema }),\n 'valueObjects?': type({\n '[string]': type({ '+': 'reject', fields: type({ '[string]': FieldSchema }) }),\n }),\n});\n","import type { MongoContract } from './contract-types';\n\nexport function validateMongoStorage(contract: MongoContract): void {\n const errors: string[] = [];\n\n for (const [modelName, model] of Object.entries(contract.models)) {\n if (model.storage.collection && !(model.storage.collection in contract.storage.collections)) {\n errors.push(\n `Model \"${modelName}\" references collection \"${model.storage.collection}\" which is not in storage.collections`,\n );\n }\n\n // Mongo does not support multi-table inheritance (ADR 2): all variants of a base\n // must share the same collection (single-table inheritance only).\n if (model.base) {\n const baseModel = contract.models[model.base];\n if (baseModel) {\n const variantCollection = model.storage.collection;\n const baseCollection = baseModel.storage.collection;\n if (variantCollection !== baseCollection) {\n errors.push(\n `Mongo does not support multi-table inheritance; variant \"${modelName}\" must share its base's collection (\"${baseCollection ?? '(none)'}\"), but has \"${variantCollection ?? '(none)'}\"`,\n );\n }\n }\n }\n\n for (const [relName, relation] of Object.entries(model.relations ?? {})) {\n const targetModel = contract.models[relation.to];\n\n if (targetModel?.owner) {\n if (targetModel.owner !== modelName) {\n errors.push(\n `Embed relation \"${relName}\" targets \"${relation.to}\" which is owned by \"${targetModel.owner}\", not \"${modelName}\"`,\n );\n }\n if (targetModel.storage.collection) {\n errors.push(\n `Embed relation \"${relName}\" targets \"${relation.to}\" which must not have a collection`,\n );\n }\n } else if ('on' in relation && relation.on) {\n for (const localField of relation.on.localFields) {\n if (!(localField in model.fields)) {\n errors.push(\n `Reference relation \"${relName}\": localField \"${localField}\" is not a field on model \"${modelName}\"`,\n );\n }\n }\n\n if (targetModel) {\n for (const targetField of relation.on.targetFields) {\n if (!(targetField in targetModel.fields)) {\n errors.push(\n `Reference relation \"${relName}\": targetField \"${targetField}\" is not a field on model \"${relation.to}\"`,\n );\n }\n }\n }\n }\n }\n }\n\n if (errors.length > 0) {\n throw new Error(`Contract storage validation failed:\\n- ${errors.join('\\n- ')}`);\n }\n}\n","import { validateContractDomain } from '@prisma-next/contract/validate-domain';\nimport { type as arktypeType } from 'arktype';\nimport { MongoContractSchema } from './contract-schema';\nimport type { MongoContract } from './contract-types';\nimport { validateMongoStorage } from './validate-storage';\n\nexport interface MongoContractIndices {\n readonly variantToBase: Record<string, string>;\n readonly modelToVariants: Record<string, string[]>;\n}\n\nexport interface ValidatedMongoContract<TContract extends MongoContract> {\n readonly contract: TContract;\n readonly indices: MongoContractIndices;\n}\n\nexport function validateMongoContract<TContract extends MongoContract>(\n value: unknown,\n): ValidatedMongoContract<TContract> {\n const parsed = MongoContractSchema(value);\n if (parsed instanceof arktypeType.errors) {\n throw new Error(`Contract structural validation failed: ${parsed.summary}`);\n }\n\n const contract = parsed as unknown as TContract;\n\n validateContractDomain(contract);\n validateMongoStorage(contract);\n\n const indices = buildIndices(contract);\n\n return { contract, indices };\n}\n\nfunction buildIndices(contract: MongoContract): MongoContractIndices {\n const variantToBase: Record<string, string> = {};\n const modelToVariants: Record<string, string[]> = {};\n\n for (const [modelName, model] of Object.entries(contract.models)) {\n if (model.base) {\n variantToBase[modelName] = model.base;\n }\n if (model.variants) {\n modelToVariants[modelName] = Object.keys(model.variants);\n }\n }\n\n return { variantToBase, modelToVariants };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "name": "@prisma-next/mongo-contract",
3
- "version": "0.0.1",
3
+ "version": "0.3.0-dev.146",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "description": "Contract types and validation for Prisma Next MongoDB support",
7
7
  "dependencies": {
8
8
  "arktype": "^2.1.29",
9
- "@prisma-next/contract": "0.0.1"
9
+ "@prisma-next/contract": "0.3.0-dev.146"
10
10
  },
11
11
  "devDependencies": {
12
12
  "tsdown": "0.18.4",
13
13
  "typescript": "5.9.3",
14
14
  "vitest": "4.0.17",
15
+ "@prisma-next/adapter-mongo": "0.3.0-dev.146",
15
16
  "@prisma-next/test-utils": "0.0.1",
16
- "@prisma-next/tsconfig": "0.0.0",
17
- "@prisma-next/adapter-mongo": "0.0.1",
18
- "@prisma-next/tsdown": "0.0.0"
17
+ "@prisma-next/tsdown": "0.0.0",
18
+ "@prisma-next/tsconfig": "0.0.0"
19
19
  },
20
20
  "files": [
21
21
  "dist",