@zenith-open/zenithcms-db-mongodb 0.1.0

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 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA"}
@@ -0,0 +1,3 @@
1
+ import { Model } from 'mongoose';
2
+ import { CollectionConfig } from '@zenith-open/zenithcms-types';
3
+ export declare function getModelForCollection(config: CollectionConfig): Model<unknown>;
@@ -0,0 +1,162 @@
1
+ import mongoose, { Schema } from 'mongoose';
2
+ const models = {};
3
+ function mapFieldToMongoose(field) {
4
+ let type;
5
+ switch (field.type) {
6
+ case 'text':
7
+ case 'email':
8
+ case 'textarea':
9
+ case 'select':
10
+ type = String;
11
+ break;
12
+ case 'richtext':
13
+ type = field.format === 'json' ? Schema.Types.Mixed : String;
14
+ break;
15
+ case 'number':
16
+ type = Number;
17
+ break;
18
+ case 'boolean':
19
+ case 'checkbox':
20
+ type = Boolean;
21
+ break;
22
+ case 'date':
23
+ type = Date;
24
+ break;
25
+ case 'json':
26
+ type = Schema.Types.Mixed;
27
+ break;
28
+ case 'media':
29
+ type = new Schema({
30
+ url: String,
31
+ id: String,
32
+ alt: String,
33
+ width: Number,
34
+ height: Number,
35
+ }, { _id: false });
36
+ break;
37
+ case 'relation':
38
+ // Use String instead of ObjectId to support database-agnostic string IDs and UUIDs
39
+ type = String;
40
+ break;
41
+ case 'array':
42
+ if (field.fields) {
43
+ type = [new Schema(generateSchemaFields(field.fields), { _id: false })];
44
+ }
45
+ else {
46
+ type = [Schema.Types.Mixed];
47
+ }
48
+ break;
49
+ case 'group':
50
+ if (field.fields) {
51
+ type = new Schema(generateSchemaFields(field.fields), { _id: false });
52
+ }
53
+ else {
54
+ type = Schema.Types.Mixed;
55
+ }
56
+ break;
57
+ case 'blocks':
58
+ if (field.blocks && field.blocks.length > 0) {
59
+ // Blocks are stored as objects with a blockType discriminator
60
+ type = [
61
+ new Schema({
62
+ blockType: { type: String, index: true },
63
+ }, { strict: false, _id: false }),
64
+ ];
65
+ }
66
+ else {
67
+ type = [Schema.Types.Mixed];
68
+ }
69
+ break;
70
+ case 'code':
71
+ case 'radio':
72
+ type = String;
73
+ break;
74
+ case 'collapsible':
75
+ if (field.fields) {
76
+ type = new Schema(generateSchemaFields(field.fields), { _id: false });
77
+ }
78
+ else {
79
+ type = Schema.Types.Mixed;
80
+ }
81
+ break;
82
+ case 'join':
83
+ // Virtual read-only field — stored as array of Mixed
84
+ type = [Schema.Types.Mixed];
85
+ break;
86
+ case 'point':
87
+ // Stored as [lng, lat] tuple
88
+ type = [Number];
89
+ break;
90
+ case 'row':
91
+ case 'ui':
92
+ // Layout/presentational fields — no data stored
93
+ return undefined;
94
+ default:
95
+ type = Schema.Types.Mixed;
96
+ }
97
+ if (field.hasMany && field.type !== 'array') {
98
+ type = [type];
99
+ }
100
+ // Handle i18n
101
+ if (field.localized) {
102
+ type = new Schema({
103
+ // We use a Mixed object to store any locale keys (en, es, fr, etc.)
104
+ }, { strict: false, _id: false });
105
+ }
106
+ const mongooseField = {
107
+ type,
108
+ required: field.required || false,
109
+ default: field.defaultValue,
110
+ };
111
+ if (field.unique !== undefined)
112
+ mongooseField.unique = field.unique;
113
+ if (field.index !== undefined)
114
+ mongooseField.index = field.index;
115
+ return mongooseField;
116
+ }
117
+ function generateSchemaFields(fields) {
118
+ const schemaFields = {};
119
+ fields.forEach((field) => {
120
+ // Skip layout/presentational fields that produce no schema mapping
121
+ if (field.type === 'row' || field.type === 'ui')
122
+ return;
123
+ schemaFields[field.name] = mapFieldToMongoose(field);
124
+ });
125
+ return schemaFields;
126
+ }
127
+ export function getModelForCollection(config) {
128
+ if (models[config.slug])
129
+ return models[config.slug];
130
+ const schemaFields = generateSchemaFields(config.fields);
131
+ const schema = new Schema(schemaFields, {
132
+ timestamps: config.timestamps !== false,
133
+ collection: config.slug,
134
+ strict: false, // Allow extra dynamic fields
135
+ });
136
+ // Global meta fields
137
+ schema.add({
138
+ siteId: { type: String, index: true },
139
+ isFocused: { type: Boolean, default: false },
140
+ _status: {
141
+ type: String,
142
+ enum: ['draft', 'published'],
143
+ default: config.drafts ? 'draft' : 'published',
144
+ },
145
+ });
146
+ // Scheduling support
147
+ if (config.scheduling) {
148
+ schema.add({
149
+ scheduledAt: { type: Date, index: true },
150
+ });
151
+ }
152
+ // Soft Delete support
153
+ if (config.softDelete) {
154
+ schema.add({
155
+ deletedAt: { type: Date, default: null, index: true },
156
+ });
157
+ }
158
+ const model = mongoose.models[config.slug] || mongoose.model(config.slug, schema);
159
+ models[config.slug] = model;
160
+ return model;
161
+ }
162
+ //# sourceMappingURL=model-factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-factory.js","sourceRoot":"","sources":["../src/model-factory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import js from '@eslint/js'
2
+ import tseslint from 'typescript-eslint'
3
+
4
+ export default tseslint.config(
5
+ js.configs.recommended,
6
+ ...tseslint.configs.recommended,
7
+ {
8
+ languageOptions: {
9
+ globals: {
10
+ node: true,
11
+ es2022: true,
12
+ },
13
+ parserOptions: {
14
+ project: ['./tsconfig.eslint.json'],
15
+ tsconfigRootDir: import.meta.dirname,
16
+ },
17
+ },
18
+ rules: {
19
+ '@typescript-eslint/no-unused-vars': 'off',
20
+ '@typescript-eslint/no-explicit-any': 'off',
21
+ },
22
+ },
23
+ {
24
+ ignores: ['scripts/**/*.ts', 'test_sync.js', 'test_path.ts', 'test_seed.ts', 'test_sync.ts', 'dist', 'node_modules', 'uploads', 'src/sandbox/worker-runner.js', '.zenith'],
25
+ }
26
+ )
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@zenith-open/zenithcms-db-mongodb",
3
+ "version": "0.1.0",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "lint": "eslint src/**/*.ts"
12
+ },
13
+ "dependencies": {
14
+ "mongoose": "^8.4.0",
15
+ "node-cache": "^5.1.2",
16
+ "pino": "^9.0.0",
17
+ "ioredis": "^5.4.1",
18
+ "@zenith-open/zenithcms-types": "workspace:*"
19
+ },
20
+ "devDependencies": {
21
+ "typescript": "^5.4.0"
22
+ }
23
+ }