@zenith-open/zenithcms-types 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.
package/src/index.d.ts ADDED
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Zenith CMS — Core Type System
3
+ * ─────────────────────────────
4
+ * Strictly typed configuration schema for collections, fields, and plugins.
5
+ * Uses Discriminated Unions for robust field-level validation and IntelliSense.
6
+ */
7
+ export type FieldType = 'text' | 'number' | 'email' | 'textarea' | 'checkbox' | 'date' | 'select' | 'media' | 'richtext' | 'json' | 'group' | 'tabs' | 'array' | 'relation' | 'blocks' | 'boolean';
8
+ export interface BlockDefinition {
9
+ slug: string;
10
+ labels?: {
11
+ singular: string;
12
+ plural: string;
13
+ };
14
+ fields: FieldConfig[];
15
+ admin?: {
16
+ description?: string;
17
+ icon?: string;
18
+ };
19
+ }
20
+ export interface FieldAdminConfig {
21
+ placeholder?: string;
22
+ description?: string;
23
+ hidden?: boolean;
24
+ readOnly?: boolean;
25
+ width?: string;
26
+ condition?: (data: any, siblingData: any) => boolean;
27
+ }
28
+ export interface BaseFieldConfig {
29
+ name: string;
30
+ label?: string;
31
+ required?: boolean;
32
+ unique?: boolean;
33
+ localized?: boolean;
34
+ virtual?: boolean;
35
+ defaultValue?: any;
36
+ admin?: FieldAdminConfig;
37
+ hooks?: {
38
+ beforeChange?: (value: any) => any | Promise<any>;
39
+ afterRead?: (value: any) => any | Promise<any>;
40
+ validate?: (value: any, data: any) => boolean | string | Promise<boolean | string>;
41
+ };
42
+ access?: {
43
+ read?: (user: any) => boolean;
44
+ update?: (user: any) => boolean;
45
+ create?: (user: any) => boolean;
46
+ };
47
+ }
48
+ export interface TextFieldConfig extends BaseFieldConfig {
49
+ type: 'text' | 'email' | 'textarea';
50
+ minLength?: number;
51
+ maxLength?: number;
52
+ }
53
+ export interface NumberFieldConfig extends BaseFieldConfig {
54
+ type: 'number';
55
+ min?: number;
56
+ max?: number;
57
+ }
58
+ export interface CheckboxFieldConfig extends BaseFieldConfig {
59
+ type: 'checkbox' | 'boolean';
60
+ }
61
+ export interface SelectFieldConfig extends BaseFieldConfig {
62
+ type: 'select';
63
+ options: (string | {
64
+ label: string;
65
+ value: string;
66
+ })[];
67
+ hasMany?: boolean;
68
+ }
69
+ export interface MediaFieldConfig extends BaseFieldConfig {
70
+ type: 'media';
71
+ hasMany?: boolean;
72
+ }
73
+ export interface RelationFieldConfig extends BaseFieldConfig {
74
+ type: 'relation';
75
+ relationTo: string;
76
+ hasMany?: boolean;
77
+ }
78
+ export interface ArrayFieldConfig extends BaseFieldConfig {
79
+ type: 'array';
80
+ fields: FieldConfig[];
81
+ minRows?: number;
82
+ maxRows?: number;
83
+ }
84
+ export interface GroupFieldConfig extends BaseFieldConfig {
85
+ type: 'group';
86
+ fields: FieldConfig[];
87
+ }
88
+ export interface BlocksFieldConfig extends BaseFieldConfig {
89
+ type: 'blocks';
90
+ blocks: BlockDefinition[];
91
+ }
92
+ export interface BasicFieldConfig extends BaseFieldConfig {
93
+ type: 'date' | 'richtext' | 'json';
94
+ }
95
+ export type FieldConfig = TextFieldConfig | NumberFieldConfig | CheckboxFieldConfig | SelectFieldConfig | MediaFieldConfig | RelationFieldConfig | ArrayFieldConfig | GroupFieldConfig | BlocksFieldConfig | BasicFieldConfig;
96
+ export interface CollectionConfig {
97
+ name: string;
98
+ slug: string;
99
+ labels?: {
100
+ singular: string;
101
+ plural: string;
102
+ };
103
+ fields: FieldConfig[];
104
+ drafts?: boolean;
105
+ seo?: boolean;
106
+ timestamps?: boolean;
107
+ singleton?: boolean;
108
+ versions?: boolean;
109
+ scheduling?: boolean;
110
+ publicRead?: boolean;
111
+ hooks?: {
112
+ beforeValidate?: (data: any, user: any, context: {
113
+ hookType: string;
114
+ }) => any | Promise<any>;
115
+ beforeCreate?: (data: any, user: any, context: {
116
+ hookType: string;
117
+ }) => any | Promise<any>;
118
+ afterCreate?: (doc: any, user: any, context: {
119
+ hookType: string;
120
+ }) => void | Promise<void>;
121
+ beforeUpdate?: (data: any, user: any, context: {
122
+ hookType: string;
123
+ }) => any | Promise<any>;
124
+ afterUpdate?: (doc: any, user: any, context: {
125
+ hookType: string;
126
+ }) => void | Promise<void>;
127
+ beforeDelete?: (id: string, user: any, context: {
128
+ hookType: string;
129
+ }) => void | Promise<void>;
130
+ afterDelete?: (id: string, user: any, context: {
131
+ hookType: string;
132
+ }) => void | Promise<void>;
133
+ afterRead?: (doc: any, user: any, context: {
134
+ hookType: string;
135
+ }) => any | Promise<any>;
136
+ afterError?: (error: Error, data: any, user: any) => void | Promise<void>;
137
+ };
138
+ access?: {
139
+ read?: (user: any) => boolean | object;
140
+ create?: (user: any) => boolean;
141
+ update?: (user: any) => boolean;
142
+ delete?: (user: any) => boolean;
143
+ };
144
+ admin?: {
145
+ group?: string;
146
+ hidden?: boolean;
147
+ useAsTitle?: string;
148
+ displayTemplate?: string;
149
+ defaultColumns?: string[];
150
+ icon?: string;
151
+ previewUrl?: string | ((doc: any) => string);
152
+ };
153
+ endpoints?: {
154
+ path: string;
155
+ method: 'get' | 'post' | 'put' | 'delete' | 'patch';
156
+ handler: (req: any, res: any) => void | Promise<void>;
157
+ }[];
158
+ }
159
+ export type GlobalConfig = CollectionConfig;
160
+ export interface ZenithPlugin {
161
+ name: string;
162
+ version?: string;
163
+ description?: string;
164
+ author?: string;
165
+ downloads?: number;
166
+ apply: (config: CMSConfig) => CMSConfig | void;
167
+ onInit?: (app: any) => void | Promise<void>;
168
+ onReady?: (app: any) => void | Promise<void>;
169
+ }
170
+ export type DeploymentProvider = 'cloudflare' | 'netlify' | 'vercel' | 'custom';
171
+ export interface DeploymentConfig {
172
+ provider: DeploymentProvider;
173
+ hookUrl: string;
174
+ triggerOn?: string[];
175
+ autoTrigger?: boolean;
176
+ }
177
+ export interface WebhookTarget {
178
+ url: string;
179
+ events: string[];
180
+ secret?: string;
181
+ }
182
+ export interface CMSConfig {
183
+ collections: CollectionConfig[];
184
+ globals?: GlobalConfig[];
185
+ plugins?: ZenithPlugin[];
186
+ webhooks?: WebhookTarget[];
187
+ deployment?: DeploymentConfig;
188
+ cors?: {
189
+ origins: string[];
190
+ };
191
+ }
192
+ export * from './generated';
193
+ export * from './database';
package/src/index.js ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Zenith CMS — Core Type System
3
+ * ─────────────────────────────
4
+ * Strictly typed configuration schema for collections, fields, and plugins.
5
+ * Uses Discriminated Unions for robust field-level validation and IntelliSense.
6
+ */
7
+ export * from './generated';
8
+ export * from './database';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA+MH,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA"}
package/src/index.ts ADDED
@@ -0,0 +1,378 @@
1
+ /**
2
+ * Zenith CMS — Core Type System
3
+ * ─────────────────────────────
4
+ * Strictly typed configuration schema for collections, fields, and plugins.
5
+ * Uses Discriminated Unions for robust field-level validation and IntelliSense.
6
+ */
7
+
8
+ import type React from 'react'
9
+
10
+ export interface ZenithDocument {
11
+ _id?: string
12
+ id?: string
13
+ siteId?: string | null
14
+ _status?: 'draft' | 'published' | string
15
+ _version?: number
16
+ workflowStatus?: string
17
+ deletedAt?: Date | null
18
+ [key: string]: unknown
19
+ }
20
+
21
+ export type FieldType =
22
+ | 'text'
23
+ | 'number'
24
+ | 'email'
25
+ | 'textarea'
26
+ | 'checkbox'
27
+ | 'date'
28
+ | 'select'
29
+ | 'media'
30
+ | 'richtext'
31
+ | 'json'
32
+ | 'group'
33
+ | 'tabs'
34
+ | 'array'
35
+ | 'relation'
36
+ | 'blocks'
37
+ | 'boolean'
38
+ | 'code'
39
+ | 'collapsible'
40
+ | 'join'
41
+ | 'point'
42
+ | 'radio'
43
+ | 'row'
44
+ | 'ui'
45
+ | 'dz'
46
+
47
+ export interface BlockDefinition {
48
+ slug: string
49
+ labels?: { singular: string; plural: string }
50
+ fields: FieldConfig[]
51
+ admin?: {
52
+ description?: string
53
+ icon?: string
54
+ imageURL?: string
55
+ category?: string
56
+ }
57
+ }
58
+
59
+ export interface FieldAdminConfig {
60
+ placeholder?: string
61
+ description?: string
62
+ hidden?: boolean
63
+ readOnly?: boolean
64
+ width?: string
65
+ condition?: (data: unknown, siblingData: unknown) => boolean
66
+ readAccess?: string[]
67
+ writeAccess?: string[]
68
+ }
69
+
70
+ export interface BaseFieldConfig {
71
+ name: string
72
+ label?: string
73
+ required?: boolean
74
+ unique?: boolean
75
+ localized?: boolean
76
+ virtual?: boolean
77
+ defaultValue?: unknown
78
+ admin?: FieldAdminConfig
79
+ hooks?: {
80
+ beforeChange?: (value: unknown) => unknown | Promise<unknown>
81
+ afterRead?: (value: unknown) => unknown | Promise<unknown>
82
+ validate?: (value: unknown, data: unknown) => boolean | string | Promise<boolean | string>
83
+ }
84
+ access?: {
85
+ read?: (user: unknown) => boolean
86
+ update?: (user: unknown) => boolean
87
+ create?: (user: unknown) => boolean
88
+ }
89
+ }
90
+
91
+ // ── Specific Field Interfaces ────────────────────────────────────────────────
92
+
93
+ export interface TextFieldConfig extends BaseFieldConfig {
94
+ type: 'text' | 'email' | 'textarea' | 'password' | 'uid' | 'color'
95
+ minLength?: number
96
+ maxLength?: number
97
+ }
98
+ export interface NumberFieldConfig extends BaseFieldConfig {
99
+ type: 'number'
100
+ min?: number
101
+ max?: number
102
+ }
103
+ export interface CheckboxFieldConfig extends BaseFieldConfig {
104
+ type: 'checkbox' | 'boolean'
105
+ }
106
+ export interface SelectFieldConfig extends BaseFieldConfig {
107
+ type: 'select'
108
+ options: (string | { label: string; value: string })[]
109
+ hasMany?: boolean
110
+ }
111
+ export interface MediaFieldConfig extends BaseFieldConfig {
112
+ type: 'media'
113
+ hasMany?: boolean
114
+ options?: {
115
+ focalPoint?: boolean
116
+ blurhash?: boolean
117
+ responsive?: boolean
118
+ }
119
+ }
120
+ export type OnDeletePolicy = 'SET_NULL' | 'CASCADE' | 'RESTRICT' | 'NO_ACTION'
121
+
122
+ export interface RelationFieldConfig extends BaseFieldConfig {
123
+ type: 'relation'
124
+ relationTo: string | string[]
125
+ hasMany?: boolean
126
+ junctionTable?: string
127
+ pivotFields?: FieldConfig[]
128
+ onDelete?: OnDeletePolicy
129
+ }
130
+ export interface ArrayFieldConfig extends BaseFieldConfig {
131
+ type: 'array'
132
+ fields: FieldConfig[]
133
+ minRows?: number
134
+ maxRows?: number
135
+ }
136
+ export interface GroupFieldConfig extends BaseFieldConfig {
137
+ type: 'group'
138
+ fields: FieldConfig[]
139
+ }
140
+ export interface BlocksFieldConfig extends BaseFieldConfig {
141
+ type: 'blocks'
142
+ blocks: BlockDefinition[]
143
+ }
144
+ export interface RichTextFieldConfig extends BaseFieldConfig {
145
+ type: 'richtext'
146
+ format?: 'html' | 'json'
147
+ }
148
+ export interface BasicFieldConfig extends BaseFieldConfig {
149
+ type: 'date' | 'json'
150
+ }
151
+ export interface CodeFieldConfig extends BaseFieldConfig {
152
+ type: 'code'
153
+ language?: string
154
+ minLength?: number
155
+ maxLength?: number
156
+ }
157
+ export interface CollapsibleFieldConfig extends BaseFieldConfig {
158
+ type: 'collapsible'
159
+ fields: FieldConfig[]
160
+ initCollapsed?: boolean
161
+ }
162
+ export interface JoinFieldConfig extends Omit<BaseFieldConfig, 'required'> {
163
+ type: 'join'
164
+ collection: string | string[]
165
+ on: string
166
+ maxDepth?: number
167
+ where?: Record<string, unknown>
168
+ defaultLimit?: number
169
+ defaultSort?: string
170
+ }
171
+ export interface PointFieldConfig extends BaseFieldConfig {
172
+ type: 'point'
173
+ }
174
+ export interface RadioFieldConfig extends BaseFieldConfig {
175
+ type: 'radio'
176
+ options: (string | { label: string; value: string })[]
177
+ layout?: 'horizontal' | 'vertical'
178
+ }
179
+ export interface RowFieldConfig extends Omit<BaseFieldConfig, 'required' | 'unique' | 'localized' | 'virtual' | 'defaultValue' | 'admin' | 'hooks' | 'access'> {
180
+ type: 'row'
181
+ fields: FieldConfig[]
182
+ admin?: {
183
+ className?: string
184
+ }
185
+ }
186
+ export interface UIFieldConfig extends Omit<BaseFieldConfig, 'required' | 'unique' | 'localized' | 'virtual' | 'defaultValue' | 'hooks' | 'access'> {
187
+ type: 'ui'
188
+ admin?: {
189
+ components?: {
190
+ Field?: React.ComponentType<unknown>
191
+ }
192
+ condition?: (data: unknown, siblingData: unknown) => boolean
193
+ }
194
+ }
195
+
196
+ export interface DZFieldConfig extends BaseFieldConfig {
197
+ type: 'dz'
198
+ /** List of available component types (block slugs) for this dynamic zone */
199
+ components?: string[]
200
+ }
201
+
202
+ export type FieldConfig =
203
+ | TextFieldConfig
204
+ | NumberFieldConfig
205
+ | CheckboxFieldConfig
206
+ | SelectFieldConfig
207
+ | MediaFieldConfig
208
+ | RelationFieldConfig
209
+ | ArrayFieldConfig
210
+ | GroupFieldConfig
211
+ | BlocksFieldConfig
212
+ | RichTextFieldConfig
213
+ | BasicFieldConfig
214
+ | CodeFieldConfig
215
+ | CollapsibleFieldConfig
216
+ | JoinFieldConfig
217
+ | PointFieldConfig
218
+ | RadioFieldConfig
219
+ | RowFieldConfig
220
+ | UIFieldConfig
221
+ | DZFieldConfig
222
+
223
+ // ── Collection & Global Config ───────────────────────────────────────────────
224
+
225
+ export interface CollectionConfig {
226
+ name: string
227
+ slug: string
228
+ labels?: { singular: string; plural: string }
229
+ fields: FieldConfig[]
230
+ drafts?: boolean
231
+ seo?: boolean
232
+ timestamps?: boolean
233
+ singleton?: boolean
234
+ versions?: boolean
235
+ maxVersions?: number
236
+ scheduling?: boolean
237
+ publicRead?: boolean
238
+ softDelete?: boolean
239
+ hooks?: {
240
+ beforeValidate?: (data: unknown, user: unknown, context: { hookType: string }) => unknown | Promise<unknown>
241
+ beforeCreate?: (data: unknown, user: unknown, context: { hookType: string }) => unknown | Promise<unknown>
242
+ afterCreate?: (doc: unknown, user: unknown, context: { hookType: string }) => void | Promise<void>
243
+ beforeUpdate?: (data: unknown, user: unknown, context: { hookType: string }) => unknown | Promise<unknown>
244
+ afterUpdate?: (doc: unknown, user: unknown, context: { hookType: string }) => void | Promise<void>
245
+ beforeDelete?: (id: string, user: unknown, context: { hookType: string }) => void | Promise<void>
246
+ afterDelete?: (id: string, user: unknown, context: { hookType: string }) => void | Promise<void>
247
+ afterRead?: (doc: unknown, user: unknown, context: { hookType: string }) => unknown | Promise<unknown>
248
+ afterError?: (error: Error, data: unknown, user: unknown) => void | Promise<void>
249
+ }
250
+ access?: {
251
+ /** Return false to deny, or an object to merge as query constraints (Row-Level Security). */
252
+ read?: (user: unknown, context?: { req?: unknown }) => boolean | object
253
+ /** Return false to deny, or an object to constrain which documents the user may create. */
254
+ create?: (user: unknown, context?: { req?: unknown }) => boolean
255
+ /** Return false to deny, or an object to constrain which documents the user may update. */
256
+ update?: (user: unknown, context?: { req?: unknown }) => boolean | object
257
+ /** Return false to deny, or an object to constrain which documents the user may delete. */
258
+ delete?: (user: unknown, context?: { req?: unknown }) => boolean | object
259
+ }
260
+ admin?: {
261
+ group?: string
262
+ hidden?: boolean
263
+ useAsTitle?: string
264
+ displayTemplate?: string
265
+ defaultColumns?: string[]
266
+ icon?: string
267
+ previewUrl?: string | ((doc: unknown) => string)
268
+ }
269
+ endpoints?: {
270
+ path: string
271
+ method: 'get' | 'post' | 'put' | 'delete' | 'patch'
272
+ handler: (req: unknown, res: unknown) => void | Promise<void>
273
+ }[]
274
+ }
275
+
276
+ export type GlobalConfig = CollectionConfig // Globals are singletons
277
+
278
+ // ── Plugin & System Config ───────────────────────────────────────────────────
279
+
280
+ export interface ZenithPlugin {
281
+ /** Unique identifier (slug). Use reverse-domain notation: `zenith-seo`, `acme-analytics` */
282
+ id: string
283
+ /** Display name shown in admin UI */
284
+ name: string
285
+ version?: string
286
+ description?: string
287
+ author?: string
288
+ /** Plugin home page / documentation URL */
289
+ homepage?: string
290
+ /** NPM package name if installable via package manager */
291
+ packageName?: string
292
+ downloads?: number
293
+ /** Minimum Zenith engine version required */
294
+ minEngineVersion?: string
295
+ /** Other plugin IDs this plugin depends on */
296
+ dependencies?: string[]
297
+ /** Whether the plugin is active. Disabled plugins are not applied. */
298
+ enabled?: boolean
299
+ /**
300
+ * JSON Schema for plugin configuration options.
301
+ * Used by the admin UI to render a settings form.
302
+ */
303
+ configSchema?: Record<string, {
304
+ type: 'string' | 'number' | 'boolean' | 'select' | 'multiselect' | 'url' | 'secret'
305
+ label: string
306
+ description?: string
307
+ default?: unknown
308
+ options?: Array<{ label: string; value: string }>
309
+ required?: boolean
310
+ }>
311
+ /** Runtime config values (set by admin UI) */
312
+ config?: Record<string, unknown>
313
+ /**
314
+ * Transform the CMS config (add collections, fields, hooks, etc.).
315
+ * Called at engine bootstrap for each enabled plugin.
316
+ */
317
+ apply: (config: CMSConfig, pluginConfig?: Record<string, unknown>) => CMSConfig | void
318
+ /** Called after all plugins are applied, before routes are mounted */
319
+ onInit?: (ctx: PluginContext) => void | Promise<void>
320
+ /** Called after the engine is fully started and listening */
321
+ onReady?: (ctx: PluginContext) => void | Promise<void>
322
+ /** Called when the engine is shutting down */
323
+ onDestroy?: (ctx: PluginContext) => void | Promise<void>
324
+ }
325
+
326
+ export interface PluginContext {
327
+ /** Express application instance */
328
+ app: unknown
329
+ /** Active database adapter */
330
+ adapter: unknown
331
+ /** Current CMS config (after all plugins applied) */
332
+ config: CMSConfig
333
+ /** Hook registry — use to register lifecycle hooks */
334
+ hooks: {
335
+ on: <T = unknown>(hook: string, handler: (payload: T) => T | Promise<T> | void, priority?: number) => () => void
336
+ emit: (hook: string, payload: unknown) => Promise<void>
337
+ }
338
+ /** Register admin UI components */
339
+ admin: {
340
+ registerComponent: (slot: string, component: { id: string; label: string; icon?: string }) => void
341
+ }
342
+ /** Logger instance */
343
+ logger: {
344
+ info: (msg: string, meta?: Record<string, unknown>) => void
345
+ warn: (msg: string, meta?: Record<string, unknown>) => void
346
+ error: (msg: string, meta?: Record<string, unknown>) => void
347
+ debug: (msg: string, meta?: Record<string, unknown>) => void
348
+ }
349
+ }
350
+
351
+ export type DeploymentProvider = 'cloudflare' | 'netlify' | 'vercel' | 'custom'
352
+
353
+ export interface DeploymentConfig {
354
+ provider: DeploymentProvider
355
+ hookUrl: string
356
+ triggerOn?: string[]
357
+ autoTrigger?: boolean
358
+ }
359
+
360
+ export interface WebhookTarget {
361
+ url: string
362
+ events: string[]
363
+ secret?: string
364
+ }
365
+
366
+ export interface CMSConfig {
367
+ collections: CollectionConfig[]
368
+ globals?: GlobalConfig[]
369
+ plugins?: ZenithPlugin[]
370
+ webhooks?: WebhookTarget[]
371
+ deployment?: DeploymentConfig
372
+ cors?: {
373
+ origins: string[]
374
+ }
375
+ }
376
+
377
+ export * from './generated'
378
+ export * from './database'
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src",
6
+ "strict": true
7
+ },
8
+ "include": [
9
+ "src/**/*"
10
+ ],
11
+ "exclude": [
12
+ "node_modules",
13
+ "dist"
14
+ ]
15
+ }