@magnet-cms/common 0.1.1 → 0.3.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/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import 'reflect-metadata';
2
+ import { SetMetadata, applyDecorators } from '@nestjs/common';
2
3
  import { existsSync } from 'node:fs';
3
4
  import { join } from 'node:path';
4
- import { applyDecorators } from '@nestjs/common';
5
5
 
6
6
  var __defProp = Object.defineProperty;
7
7
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
@@ -11,6 +11,21 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
11
11
  if (typeof require !== "undefined") return require.apply(this, arguments);
12
12
  throw Error('Dynamic require of "' + x + '" is not supported');
13
13
  });
14
+ var EVENT_HANDLER_METADATA = "magnet:event_handler";
15
+ function OnEvent(event, options = {}) {
16
+ return (target, propertyKey, descriptor) => {
17
+ const metadata = {
18
+ event,
19
+ options
20
+ };
21
+ SetMetadata(EVENT_HANDLER_METADATA, metadata)(target, propertyKey, descriptor);
22
+ return descriptor;
23
+ };
24
+ }
25
+ __name(OnEvent, "OnEvent");
26
+ var Validators = /* @__PURE__ */ __name((...validators) => {
27
+ return applyDecorators(...validators);
28
+ }, "Validators");
14
29
 
15
30
  // src/constants.ts
16
31
  var RESOLVER_METADATA_KEY = "magnet:resolver";
@@ -20,13 +35,936 @@ var SCHEMA_OPTIONS_METADATA_KEY = "magnet:schema:options";
20
35
  var BASE_SCHEMA_METADATA_KEY = "magnet:schema:base";
21
36
  var PROP_METADATA_KEY = "magnet:schema:prop";
22
37
  var UI_METADATA_KEY = "magnet:schema:ui";
38
+ var FIELD_METADATA_KEY = "magnet:schema:field";
23
39
  var SETTING_METADATA_KEY = "magnet:setting";
40
+ var SETTINGS_OPTIONS_METADATA_KEY = "magnet:settings:options";
41
+ var SETTING_FIELD_METADATA_KEY = "magnet:settings:field";
42
+ var EXTEND_USER_METADATA_KEY = "magnet:extend:user";
43
+ var PERMISSION_METADATA_KEY = "magnet:permission";
44
+ var PERMISSION_OPTIONS_METADATA_KEY = "magnet:permission:options";
45
+ var RESOLVED_PERMISSION_KEY = "magnet:permission:resolved";
24
46
  var INJECT_MODEL = "magnet:inject:model";
25
47
  var DESIGN_TYPE = "design:type";
26
48
  var DESIGN_META = "design:metadata";
27
49
  var DESIGN_PARAM_TYPES = "design:paramtypes";
28
50
  var DESIGN_RETURN_TYPE = "design:returntype";
29
51
 
52
+ // src/utils/database-adapter-singleton-for-feature.util.ts
53
+ var GETTER_KEY = Symbol.for("@magnet-cms/common/database-adapter-singleton-for-feature");
54
+ function getGetterSlot() {
55
+ const g = globalThis;
56
+ return g[GETTER_KEY] ?? null;
57
+ }
58
+ __name(getGetterSlot, "getGetterSlot");
59
+ function setGetterSlot(getter) {
60
+ const g = globalThis;
61
+ g[GETTER_KEY] = getter;
62
+ }
63
+ __name(setGetterSlot, "setGetterSlot");
64
+ function registerDatabaseAdapterSingletonForFeature(getter) {
65
+ setGetterSlot(getter);
66
+ }
67
+ __name(registerDatabaseAdapterSingletonForFeature, "registerDatabaseAdapterSingletonForFeature");
68
+ function getDatabaseAdapterSingletonForFeature() {
69
+ const databaseAdapterSingletonGetter = getGetterSlot();
70
+ if (!databaseAdapterSingletonGetter) return null;
71
+ try {
72
+ return databaseAdapterSingletonGetter();
73
+ } catch {
74
+ return null;
75
+ }
76
+ }
77
+ __name(getDatabaseAdapterSingletonForFeature, "getDatabaseAdapterSingletonForFeature");
78
+ function clearDatabaseAdapterSingletonForFeature() {
79
+ setGetterSlot(null);
80
+ }
81
+ __name(clearDatabaseAdapterSingletonForFeature, "clearDatabaseAdapterSingletonForFeature");
82
+ var cachedAdapter = null;
83
+ function isPackageInstalled(packageName) {
84
+ try {
85
+ return existsSync(join(__require.resolve(packageName), "../../"));
86
+ } catch {
87
+ return false;
88
+ }
89
+ }
90
+ __name(isPackageInstalled, "isPackageInstalled");
91
+ function detectDatabaseAdapter(dbConfig) {
92
+ if (dbConfig) {
93
+ if ("connectionString" in dbConfig || "dialect" in dbConfig) {
94
+ cachedAdapter = "drizzle";
95
+ return cachedAdapter;
96
+ }
97
+ if ("uri" in dbConfig) {
98
+ cachedAdapter = "mongoose";
99
+ return cachedAdapter;
100
+ }
101
+ }
102
+ if (cachedAdapter) return cachedAdapter;
103
+ if (isPackageInstalled("@magnet-cms/adapter-db-mongoose")) {
104
+ cachedAdapter = "mongoose";
105
+ } else if (isPackageInstalled("@magnet-cms/adapter-db-drizzle")) {
106
+ cachedAdapter = "drizzle";
107
+ } else {
108
+ throw new Error("\u274C No supported database adapter found. Install @magnet-cms/adapter-db-mongoose or @magnet-cms/adapter-db-drizzle.");
109
+ }
110
+ return cachedAdapter;
111
+ }
112
+ __name(detectDatabaseAdapter, "detectDatabaseAdapter");
113
+ function setDatabaseAdapter(adapter) {
114
+ cachedAdapter = adapter;
115
+ }
116
+ __name(setDatabaseAdapter, "setDatabaseAdapter");
117
+ function clearAdapterCache() {
118
+ cachedAdapter = null;
119
+ }
120
+ __name(clearAdapterCache, "clearAdapterCache");
121
+
122
+ // src/utils/get-model-token.util.ts
123
+ function getModelToken(schema) {
124
+ const name = typeof schema === "string" ? schema : schema.name;
125
+ return `MAGNET_MODEL_${name.toUpperCase()}`;
126
+ }
127
+ __name(getModelToken, "getModelToken");
128
+ function getAdapterToken() {
129
+ return "MAGNET_DATABASE_ADAPTER";
130
+ }
131
+ __name(getAdapterToken, "getAdapterToken");
132
+ var globalModelRegistry = /* @__PURE__ */ new Map();
133
+ function registerModel(token, model) {
134
+ globalModelRegistry.set(token, model);
135
+ }
136
+ __name(registerModel, "registerModel");
137
+ function getRegisteredModel(token) {
138
+ return globalModelRegistry.get(token);
139
+ }
140
+ __name(getRegisteredModel, "getRegisteredModel");
141
+
142
+ // src/utils/get-schema-token.util.ts
143
+ var getSchemaToken = /* @__PURE__ */ __name((schema) => {
144
+ return `${schema.name}Schema`;
145
+ }, "getSchemaToken");
146
+ var getSettingToken = /* @__PURE__ */ __name((setting) => {
147
+ return `${setting.name}Setting`;
148
+ }, "getSettingToken");
149
+
150
+ // src/utils/type-guards.ts
151
+ function isObject(value) {
152
+ return typeof value === "object" && value !== null && !Array.isArray(value);
153
+ }
154
+ __name(isObject, "isObject");
155
+ function hasProperty(value, key) {
156
+ return isObject(value) && key in value;
157
+ }
158
+ __name(hasProperty, "hasProperty");
159
+ function hasProperties(value, keys) {
160
+ return isObject(value) && keys.every((key) => key in value);
161
+ }
162
+ __name(hasProperties, "hasProperties");
163
+ function isString(value) {
164
+ return typeof value === "string";
165
+ }
166
+ __name(isString, "isString");
167
+ function isNumber(value) {
168
+ return typeof value === "number" && !Number.isNaN(value);
169
+ }
170
+ __name(isNumber, "isNumber");
171
+ function isBoolean(value) {
172
+ return typeof value === "boolean";
173
+ }
174
+ __name(isBoolean, "isBoolean");
175
+ function isArray(value) {
176
+ return Array.isArray(value);
177
+ }
178
+ __name(isArray, "isArray");
179
+ function isStringArray(value) {
180
+ return Array.isArray(value) && value.every((item) => typeof item === "string");
181
+ }
182
+ __name(isStringArray, "isStringArray");
183
+ function isFunction(value) {
184
+ return typeof value === "function";
185
+ }
186
+ __name(isFunction, "isFunction");
187
+ function isDocument(value) {
188
+ return isObject(value) && hasProperty(value, "id") && typeof value.id === "string";
189
+ }
190
+ __name(isDocument, "isDocument");
191
+ function isCastError(error) {
192
+ return isObject(error) && hasProperty(error, "name") && error.name === "CastError" && hasProperty(error, "path") && typeof error.path === "string";
193
+ }
194
+ __name(isCastError, "isCastError");
195
+ function isDuplicateKeyError(error) {
196
+ return isObject(error) && hasProperty(error, "code") && error.code === 11e3;
197
+ }
198
+ __name(isDuplicateKeyError, "isDuplicateKeyError");
199
+ function isValidationError(error) {
200
+ return isObject(error) && hasProperty(error, "name") && error.name === "ValidationError" && hasProperty(error, "errors");
201
+ }
202
+ __name(isValidationError, "isValidationError");
203
+ function isPostgresUniqueError(error) {
204
+ return isObject(error) && hasProperty(error, "code") && error.code === "23505";
205
+ }
206
+ __name(isPostgresUniqueError, "isPostgresUniqueError");
207
+ function hasMethod(value, methodName) {
208
+ return isObject(value) && hasProperty(value, methodName) && typeof value[methodName] === "function";
209
+ }
210
+ __name(hasMethod, "hasMethod");
211
+ function hasSetLocale(value) {
212
+ return isObject(value) && hasMethod(value, "setLocale");
213
+ }
214
+ __name(hasSetLocale, "hasSetLocale");
215
+ function hasToString(value) {
216
+ return isObject(value) && hasMethod(value, "toString");
217
+ }
218
+ __name(hasToString, "hasToString");
219
+ function assertDefined(value, message) {
220
+ if (value === null || value === void 0) {
221
+ throw new Error(message ?? "Value is null or undefined");
222
+ }
223
+ }
224
+ __name(assertDefined, "assertDefined");
225
+ function assert(condition, message) {
226
+ if (!condition) {
227
+ throw new Error(message ?? "Assertion failed");
228
+ }
229
+ }
230
+ __name(assert, "assert");
231
+ function getDocumentId(doc) {
232
+ if (!isObject(doc)) return void 0;
233
+ if (hasProperty(doc, "id") && typeof doc.id === "string") {
234
+ return doc.id;
235
+ }
236
+ if (hasProperty(doc, "_id")) {
237
+ if (typeof doc._id === "string") {
238
+ return doc._id;
239
+ }
240
+ if (hasToString(doc._id)) {
241
+ return doc._id.toString();
242
+ }
243
+ }
244
+ return void 0;
245
+ }
246
+ __name(getDocumentId, "getDocumentId");
247
+ function isStringRecord(value) {
248
+ if (!isObject(value)) return false;
249
+ return Object.values(value).every((v) => typeof v === "string");
250
+ }
251
+ __name(isStringRecord, "isStringRecord");
252
+ function isVersionDocument(value) {
253
+ return isObject(value) && hasProperty(value, "documentId") && typeof value.documentId === "string" && hasProperty(value, "versionId") && typeof value.versionId === "string" && hasProperty(value, "schemaName") && typeof value.schemaName === "string" && hasProperty(value, "status") && hasProperty(value, "data") && isObject(value.data);
254
+ }
255
+ __name(isVersionDocument, "isVersionDocument");
256
+
257
+ // src/decorators/field/field.prop-mapper.ts
258
+ function isPropDefaultValue(value) {
259
+ if (value === null) return true;
260
+ if (typeof value === "string") return true;
261
+ if (typeof value === "number") return true;
262
+ if (typeof value === "boolean") return true;
263
+ if (typeof value === "function") return true;
264
+ if (Array.isArray(value)) return true;
265
+ if (typeof value === "object") return true;
266
+ return false;
267
+ }
268
+ __name(isPropDefaultValue, "isPropDefaultValue");
269
+ function mapFieldTypeToProp(type, options) {
270
+ const propOptions = {
271
+ required: options.required,
272
+ unique: options.unique,
273
+ default: isPropDefaultValue(options.default) ? options.default : void 0,
274
+ hidden: options.hidden,
275
+ readonly: options.readonly,
276
+ description: options.description
277
+ };
278
+ switch (type) {
279
+ case "text":
280
+ case "email":
281
+ case "url":
282
+ case "phone":
283
+ case "address":
284
+ case "color":
285
+ case "slug":
286
+ case "textarea":
287
+ case "markdown":
288
+ case "code":
289
+ propOptions.type = String;
290
+ break;
291
+ case "number":
292
+ propOptions.type = Number;
293
+ break;
294
+ case "boolean":
295
+ propOptions.type = Boolean;
296
+ break;
297
+ case "date":
298
+ case "datetime":
299
+ propOptions.type = Date;
300
+ break;
301
+ case "richtext":
302
+ propOptions.type = String;
303
+ break;
304
+ case "json":
305
+ case "object":
306
+ propOptions.type = Object;
307
+ break;
308
+ case "select":
309
+ case "enum":
310
+ propOptions.type = String;
311
+ break;
312
+ case "tags":
313
+ propOptions.type = [
314
+ String
315
+ ];
316
+ break;
317
+ case "image":
318
+ case "file":
319
+ propOptions.type = String;
320
+ break;
321
+ case "gallery":
322
+ propOptions.type = [
323
+ String
324
+ ];
325
+ break;
326
+ case "array":
327
+ propOptions.type = Array;
328
+ break;
329
+ case "blocks":
330
+ propOptions.type = Array;
331
+ break;
332
+ case "relationship": {
333
+ const relOptions = options;
334
+ propOptions.ref = relOptions.ref;
335
+ if (relOptions.multiple) {
336
+ propOptions.type = [
337
+ String
338
+ ];
339
+ } else {
340
+ propOptions.type = String;
341
+ }
342
+ break;
343
+ }
344
+ default: {
345
+ const _exhaustiveCheck = type;
346
+ throw new Error(`Unknown field type: ${_exhaustiveCheck}`);
347
+ }
348
+ }
349
+ return Object.fromEntries(Object.entries(propOptions).filter(([, value]) => value !== void 0));
350
+ }
351
+ __name(mapFieldTypeToProp, "mapFieldTypeToProp");
352
+
353
+ // src/decorators/field/field.ui-mapper.ts
354
+ function mapFieldTypeToUIType(type) {
355
+ const typeMap = {
356
+ text: "text",
357
+ number: "number",
358
+ boolean: "switch",
359
+ date: "date",
360
+ datetime: "date",
361
+ richtext: "richText",
362
+ markdown: "textarea",
363
+ code: "code",
364
+ json: "json",
365
+ select: "select",
366
+ enum: "select",
367
+ tags: "multiSelect",
368
+ image: "upload",
369
+ file: "fileUpload",
370
+ gallery: "upload",
371
+ slug: "text",
372
+ email: "email",
373
+ url: "text",
374
+ phone: "phone",
375
+ address: "text",
376
+ color: "text",
377
+ object: "json",
378
+ array: "array",
379
+ blocks: "blocks",
380
+ relationship: "relationship",
381
+ textarea: "textarea"
382
+ };
383
+ return typeMap[type];
384
+ }
385
+ __name(mapFieldTypeToUIType, "mapFieldTypeToUIType");
386
+ function convertToUISelectItems(options) {
387
+ return options.map((opt) => {
388
+ if (typeof opt === "object" && opt !== null && "label" in opt && "value" in opt) {
389
+ return {
390
+ key: String(opt.value),
391
+ value: opt.label
392
+ };
393
+ }
394
+ return {
395
+ key: String(opt),
396
+ value: String(opt)
397
+ };
398
+ });
399
+ }
400
+ __name(convertToUISelectItems, "convertToUISelectItems");
401
+ function convertEnumToUISelectItems(enumObj) {
402
+ return Object.entries(enumObj).filter(([key]) => Number.isNaN(Number(key))).map(([key, value]) => ({
403
+ key: String(value),
404
+ value: key
405
+ }));
406
+ }
407
+ __name(convertEnumToUISelectItems, "convertEnumToUISelectItems");
408
+ function toUIDecoratorOptions(internal) {
409
+ if (internal.side) {
410
+ return {
411
+ type: internal.type,
412
+ label: internal.label,
413
+ description: internal.description,
414
+ side: true,
415
+ options: internal.options
416
+ };
417
+ }
418
+ const result = {
419
+ type: internal.type,
420
+ label: internal.label,
421
+ description: internal.description,
422
+ tab: internal.tab ?? "General"
423
+ };
424
+ if (internal.options) {
425
+ result.options = internal.options;
426
+ }
427
+ return result;
428
+ }
429
+ __name(toUIDecoratorOptions, "toUIDecoratorOptions");
430
+ function mapFieldTypeToUI(type, options) {
431
+ const uiType = mapFieldTypeToUIType(type);
432
+ const internal = {
433
+ type: uiType,
434
+ label: options.label,
435
+ description: options.description,
436
+ tab: options.tab,
437
+ side: options.side ? true : void 0
438
+ };
439
+ switch (type) {
440
+ case "select": {
441
+ const selectOpts = options;
442
+ return toUIDecoratorOptions({
443
+ ...internal,
444
+ type: selectOpts.multiple ? "multiSelect" : "select",
445
+ options: convertToUISelectItems(selectOpts.options)
446
+ });
447
+ }
448
+ case "enum": {
449
+ const enumOpts = options;
450
+ return toUIDecoratorOptions({
451
+ ...internal,
452
+ type: enumOpts.multiple ? "multiSelect" : "select",
453
+ options: convertEnumToUISelectItems(enumOpts.enum)
454
+ });
455
+ }
456
+ case "boolean": {
457
+ const boolOpts = options;
458
+ return toUIDecoratorOptions({
459
+ ...internal,
460
+ type: boolOpts.style === "checkbox" ? "checkbox" : "switch"
461
+ });
462
+ }
463
+ case "richtext": {
464
+ return toUIDecoratorOptions({
465
+ ...internal,
466
+ type: "richText"
467
+ });
468
+ }
469
+ case "code": {
470
+ return toUIDecoratorOptions({
471
+ ...internal,
472
+ type: "code"
473
+ });
474
+ }
475
+ case "tags": {
476
+ const tagsOpts = options;
477
+ return toUIDecoratorOptions({
478
+ ...internal,
479
+ type: "multiSelect",
480
+ options: tagsOpts.suggestions?.map((s) => ({
481
+ key: s,
482
+ value: s
483
+ })) ?? []
484
+ });
485
+ }
486
+ default:
487
+ return toUIDecoratorOptions(internal);
488
+ }
489
+ }
490
+ __name(mapFieldTypeToUI, "mapFieldTypeToUI");
491
+
492
+ // src/decorators/field/field.factory.ts
493
+ function createFieldDecorator(type, defaultOptions = {}) {
494
+ return (options) => {
495
+ const mergedOptions = {
496
+ ...defaultOptions,
497
+ ...options
498
+ };
499
+ return (target, propertyKey) => {
500
+ const designType = Reflect.getMetadata(DESIGN_TYPE, target, propertyKey);
501
+ const metadata = {
502
+ type,
503
+ options: mergedOptions,
504
+ propertyKey,
505
+ target: target.constructor,
506
+ designType
507
+ };
508
+ const existingFields = Reflect.getMetadata(FIELD_METADATA_KEY, target.constructor) ?? [];
509
+ const filteredFields = existingFields.filter((f) => f.propertyKey !== propertyKey);
510
+ Reflect.defineMetadata(FIELD_METADATA_KEY, [
511
+ ...filteredFields,
512
+ metadata
513
+ ], target.constructor);
514
+ emitLegacyPropMetadata(target, propertyKey, type, mergedOptions);
515
+ emitLegacyUIMetadata(target, propertyKey, type, mergedOptions, designType);
516
+ applyAdapterProp(target, propertyKey, type, mergedOptions);
517
+ };
518
+ };
519
+ }
520
+ __name(createFieldDecorator, "createFieldDecorator");
521
+ function emitLegacyPropMetadata(target, propertyKey, type, options) {
522
+ const propOptions = mapFieldTypeToProp(type, options);
523
+ const existingProps = Reflect.getMetadata(PROP_METADATA_KEY, target) ?? [];
524
+ const filteredProps = existingProps.filter((p) => p.propertyKey !== propertyKey);
525
+ Reflect.defineMetadata(PROP_METADATA_KEY, [
526
+ ...filteredProps,
527
+ {
528
+ propertyKey,
529
+ options: propOptions
530
+ }
531
+ ], target);
532
+ }
533
+ __name(emitLegacyPropMetadata, "emitLegacyPropMetadata");
534
+ function emitLegacyUIMetadata(target, propertyKey, type, options, designType) {
535
+ const uiOptions = mapFieldTypeToUI(type, options);
536
+ const existingUI = Reflect.getMetadata(UI_METADATA_KEY, target) ?? [];
537
+ const filteredUI = existingUI.filter((u) => u.propertyKey !== propertyKey);
538
+ Reflect.defineMetadata(UI_METADATA_KEY, [
539
+ ...filteredUI,
540
+ {
541
+ propertyKey,
542
+ options: {
543
+ ...uiOptions,
544
+ designType
545
+ }
546
+ }
547
+ ], target);
548
+ }
549
+ __name(emitLegacyUIMetadata, "emitLegacyUIMetadata");
550
+ function applyAdapterProp(target, propertyKey, type, options) {
551
+ try {
552
+ const adapter = detectDatabaseAdapter();
553
+ const propOptions = mapFieldTypeToProp(type, options);
554
+ const { Prop: Prop2 } = __require(`@magnet-cms/adapter-db-${adapter}`);
555
+ Prop2(propOptions)(target, propertyKey);
556
+ } catch {
557
+ }
558
+ }
559
+ __name(applyAdapterProp, "applyAdapterProp");
560
+ function getFieldMetadata(target) {
561
+ return Reflect.getMetadata(FIELD_METADATA_KEY, target) ?? [];
562
+ }
563
+ __name(getFieldMetadata, "getFieldMetadata");
564
+ function getFieldMetadataForProperty(target, propertyKey) {
565
+ const fields = getFieldMetadata(target);
566
+ return fields.find((f) => f.propertyKey === propertyKey);
567
+ }
568
+ __name(getFieldMetadataForProperty, "getFieldMetadataForProperty");
569
+
570
+ // src/types/field.types.ts
571
+ function isFieldMetadata(value) {
572
+ if (typeof value !== "object" || value === null) {
573
+ return false;
574
+ }
575
+ const metadata = value;
576
+ return typeof metadata.type === "string" && typeof metadata.options === "object" && metadata.options !== null && "propertyKey" in metadata;
577
+ }
578
+ __name(isFieldMetadata, "isFieldMetadata");
579
+ function isValidFieldType(type) {
580
+ const validTypes = [
581
+ "text",
582
+ "number",
583
+ "boolean",
584
+ "date",
585
+ "datetime",
586
+ "richtext",
587
+ "markdown",
588
+ "code",
589
+ "json",
590
+ "select",
591
+ "enum",
592
+ "tags",
593
+ "image",
594
+ "file",
595
+ "gallery",
596
+ "slug",
597
+ "email",
598
+ "url",
599
+ "phone",
600
+ "address",
601
+ "color",
602
+ "object",
603
+ "array",
604
+ "blocks",
605
+ "relationship",
606
+ "textarea"
607
+ ];
608
+ return typeof type === "string" && validTypes.includes(type);
609
+ }
610
+ __name(isValidFieldType, "isValidFieldType");
611
+
612
+ // src/decorators/field/index.ts
613
+ var Field = {
614
+ // ============================================
615
+ // PRIMITIVES
616
+ // ============================================
617
+ /**
618
+ * Text field - single line text input
619
+ *
620
+ * @example
621
+ * ```typescript
622
+ * @Field.Text({ required: true, maxLength: 200 })
623
+ * title: string
624
+ * ```
625
+ */
626
+ Text: createFieldDecorator("text"),
627
+ /**
628
+ * Number field - numeric input
629
+ *
630
+ * @example
631
+ * ```typescript
632
+ * @Field.Number({ min: 0, max: 100, integer: true })
633
+ * quantity: number
634
+ * ```
635
+ */
636
+ Number: createFieldDecorator("number"),
637
+ /**
638
+ * Boolean field - true/false toggle
639
+ *
640
+ * @example
641
+ * ```typescript
642
+ * @Field.Boolean({ default: false, style: 'switch' })
643
+ * isPublished: boolean
644
+ * ```
645
+ */
646
+ Boolean: createFieldDecorator("boolean", {
647
+ style: "switch"
648
+ }),
649
+ /**
650
+ * Date field - date picker (without time)
651
+ *
652
+ * @example
653
+ * ```typescript
654
+ * @Field.Date({ min: '2024-01-01' })
655
+ * publishDate: Date
656
+ * ```
657
+ */
658
+ Date: createFieldDecorator("date"),
659
+ /**
660
+ * DateTime field - date and time picker
661
+ *
662
+ * @example
663
+ * ```typescript
664
+ * @Field.DateTime({ timezone: 'UTC' })
665
+ * scheduledAt: Date
666
+ * ```
667
+ */
668
+ DateTime: createFieldDecorator("datetime"),
669
+ // ============================================
670
+ // RICH CONTENT
671
+ // ============================================
672
+ /**
673
+ * RichText field - WYSIWYG editor
674
+ *
675
+ * @example
676
+ * ```typescript
677
+ * @Field.RichText({ toolbar: 'full' })
678
+ * content: string
679
+ * ```
680
+ */
681
+ RichText: createFieldDecorator("richtext", {
682
+ toolbar: "standard"
683
+ }),
684
+ /**
685
+ * Markdown field - markdown editor with preview
686
+ *
687
+ * @example
688
+ * ```typescript
689
+ * @Field.Markdown({ preview: true })
690
+ * description: string
691
+ * ```
692
+ */
693
+ Markdown: createFieldDecorator("markdown", {
694
+ preview: true
695
+ }),
696
+ /**
697
+ * Code field - code editor with syntax highlighting
698
+ *
699
+ * @example
700
+ * ```typescript
701
+ * @Field.Code({ language: 'typescript' })
702
+ * snippet: string
703
+ * ```
704
+ */
705
+ Code: createFieldDecorator("code"),
706
+ /**
707
+ * JSON field - JSON editor
708
+ *
709
+ * @example
710
+ * ```typescript
711
+ * @Field.JSON()
712
+ * metadata: Record<string, unknown>
713
+ * ```
714
+ */
715
+ JSON: createFieldDecorator("json"),
716
+ /**
717
+ * Textarea field - multi-line text input
718
+ *
719
+ * @example
720
+ * ```typescript
721
+ * @Field.Textarea({ rows: 5 })
722
+ * summary: string
723
+ * ```
724
+ */
725
+ Textarea: createFieldDecorator("textarea"),
726
+ // ============================================
727
+ // SELECTION
728
+ // ============================================
729
+ /**
730
+ * Select field - dropdown selection
731
+ *
732
+ * @example
733
+ * ```typescript
734
+ * @Field.Select({
735
+ * options: [
736
+ * { label: 'Draft', value: 'draft' },
737
+ * { label: 'Published', value: 'published' }
738
+ * ],
739
+ * default: 'draft'
740
+ * })
741
+ * status: string
742
+ * ```
743
+ */
744
+ Select: /* @__PURE__ */ __name((options) => createFieldDecorator("select")(options), "Select"),
745
+ /**
746
+ * Enum field - dropdown from TypeScript enum
747
+ *
748
+ * @example
749
+ * ```typescript
750
+ * enum Status { Draft = 'draft', Published = 'published' }
751
+ *
752
+ * @Field.Enum({ enum: Status, default: Status.Draft })
753
+ * status: Status
754
+ * ```
755
+ */
756
+ Enum: /* @__PURE__ */ __name((options) => createFieldDecorator("enum")(options), "Enum"),
757
+ /**
758
+ * Tags field - multi-value tag input
759
+ *
760
+ * @example
761
+ * ```typescript
762
+ * @Field.Tags({ suggestions: ['tech', 'news'], maxTags: 5 })
763
+ * tags: string[]
764
+ * ```
765
+ */
766
+ Tags: createFieldDecorator("tags"),
767
+ // ============================================
768
+ // MEDIA
769
+ // ============================================
770
+ /**
771
+ * Image field - single image upload
772
+ *
773
+ * @example
774
+ * ```typescript
775
+ * @Field.Image({ folder: 'covers', formats: ['jpg', 'png', 'webp'] })
776
+ * coverImage: string
777
+ * ```
778
+ */
779
+ Image: createFieldDecorator("image"),
780
+ /**
781
+ * File field - single file upload
782
+ *
783
+ * @example
784
+ * ```typescript
785
+ * @Field.File({ folder: 'documents', accept: ['application/pdf'] })
786
+ * attachment: string
787
+ * ```
788
+ */
789
+ File: createFieldDecorator("file"),
790
+ /**
791
+ * Gallery field - multiple image upload
792
+ *
793
+ * @example
794
+ * ```typescript
795
+ * @Field.Gallery({ maxItems: 10 })
796
+ * images: string[]
797
+ * ```
798
+ */
799
+ Gallery: createFieldDecorator("gallery"),
800
+ // ============================================
801
+ // SPECIAL
802
+ // ============================================
803
+ /**
804
+ * Slug field - auto-generated URL-friendly string
805
+ *
806
+ * @example
807
+ * ```typescript
808
+ * @Field.Slug({ from: 'title', unique: true })
809
+ * slug: string
810
+ * ```
811
+ */
812
+ Slug: createFieldDecorator("slug"),
813
+ /**
814
+ * Email field - email input with validation pattern
815
+ *
816
+ * @example
817
+ * ```typescript
818
+ * @Field.Email({ required: true })
819
+ * @Field.Validators(IsEmail())
820
+ * email: string
821
+ * ```
822
+ */
823
+ Email: createFieldDecorator("email", {
824
+ pattern: "^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$"
825
+ }),
826
+ /**
827
+ * URL field - URL input
828
+ *
829
+ * @example
830
+ * ```typescript
831
+ * @Field.URL({ protocols: ['https'] })
832
+ * @Field.Validators(IsUrl())
833
+ * website: string
834
+ * ```
835
+ */
836
+ URL: createFieldDecorator("url"),
837
+ /**
838
+ * Phone field - phone number input
839
+ *
840
+ * @example
841
+ * ```typescript
842
+ * @Field.Phone({ defaultCountry: 'US' })
843
+ * phone: string
844
+ * ```
845
+ */
846
+ Phone: createFieldDecorator("phone"),
847
+ /**
848
+ * Address field - address input with optional geocoding
849
+ *
850
+ * @example
851
+ * ```typescript
852
+ * @Field.Address({ provider: 'google' })
853
+ * address: string
854
+ * ```
855
+ */
856
+ Address: createFieldDecorator("address"),
857
+ /**
858
+ * Color field - color picker
859
+ *
860
+ * @example
861
+ * ```typescript
862
+ * @Field.Color({ format: 'hex', presets: ['#ff0000', '#00ff00'] })
863
+ * brandColor: string
864
+ * ```
865
+ */
866
+ Color: createFieldDecorator("color", {
867
+ format: "hex"
868
+ }),
869
+ // ============================================
870
+ // COMPOSITION
871
+ // ============================================
872
+ /**
873
+ * Object field - nested object structure
874
+ *
875
+ * @example
876
+ * ```typescript
877
+ * @Field.Object()
878
+ * metadata: { key: string; value: string }
879
+ * ```
880
+ */
881
+ Object: createFieldDecorator("object"),
882
+ /**
883
+ * Array field - array of items
884
+ *
885
+ * @example
886
+ * ```typescript
887
+ * @Field.Array({ of: { type: 'text' }, maxItems: 10 })
888
+ * items: string[]
889
+ * ```
890
+ */
891
+ Array: /* @__PURE__ */ __name((options) => createFieldDecorator("array")(options), "Array"),
892
+ /**
893
+ * Blocks field - flexible content blocks
894
+ *
895
+ * @example
896
+ * ```typescript
897
+ * @Field.Blocks({ types: ['paragraph', 'image', 'quote'] })
898
+ * content: Block[]
899
+ * ```
900
+ */
901
+ Blocks: createFieldDecorator("blocks"),
902
+ /**
903
+ * Relationship field - reference to another schema
904
+ *
905
+ * @example
906
+ * ```typescript
907
+ * @Field.Relationship({ ref: 'users', multiple: false })
908
+ * author: string
909
+ *
910
+ * @Field.Relationship({ ref: 'categories', multiple: true })
911
+ * categories: string[]
912
+ * ```
913
+ */
914
+ Relationship: createFieldDecorator("relationship"),
915
+ // ============================================
916
+ // VALIDATION
917
+ // ============================================
918
+ /**
919
+ * Validators - apply class-validator decorators
920
+ *
921
+ * This is an alias for the existing @Validators decorator,
922
+ * keeping validation explicit and using familiar class-validator syntax.
923
+ *
924
+ * @example
925
+ * ```typescript
926
+ * @Field.Text({ required: true })
927
+ * @Field.Validators(IsString(), Length(1, 200), IsNotEmpty())
928
+ * title: string
929
+ * ```
930
+ */
931
+ Validators
932
+ };
933
+ function RequirePermission(options) {
934
+ return (target, propertyKey, descriptor) => {
935
+ SetMetadata(PERMISSION_METADATA_KEY, options)(target, propertyKey, descriptor);
936
+ return descriptor;
937
+ };
938
+ }
939
+ __name(RequirePermission, "RequirePermission");
940
+ function HasPermission(permission) {
941
+ return (target, propertyKey, descriptor) => {
942
+ const options = {
943
+ id: permission,
944
+ name: permission.split(".").pop() ?? permission,
945
+ description: `Requires ${permission} permission`
946
+ };
947
+ SetMetadata(PERMISSION_METADATA_KEY, options)(target, propertyKey, descriptor);
948
+ return descriptor;
949
+ };
950
+ }
951
+ __name(HasPermission, "HasPermission");
952
+ function PermissionMeta(options) {
953
+ return (target, propertyKey, descriptor) => {
954
+ SetMetadata(PERMISSION_OPTIONS_METADATA_KEY, options)(target, propertyKey, descriptor);
955
+ return descriptor;
956
+ };
957
+ }
958
+ __name(PermissionMeta, "PermissionMeta");
959
+ function getPermissionMetadata(target, propertyKey) {
960
+ return Reflect.getMetadata(PERMISSION_METADATA_KEY, target, propertyKey);
961
+ }
962
+ __name(getPermissionMetadata, "getPermissionMetadata");
963
+ function hasPermissionDecorator(target, propertyKey) {
964
+ return Reflect.hasMetadata(PERMISSION_METADATA_KEY, target, propertyKey);
965
+ }
966
+ __name(hasPermissionDecorator, "hasPermissionDecorator");
967
+
30
968
  // src/decorators/resolver/resolver.decorator.ts
31
969
  function Resolver(optionsOrFn) {
32
970
  return (target) => {
@@ -81,59 +1019,36 @@ function Resolve(optionsOrFn) {
81
1019
  };
82
1020
  }
83
1021
  __name(Resolve, "Resolve");
84
- var cachedAdapter = null;
85
- function isPackageInstalled(packageName) {
86
- try {
87
- return existsSync(join(__require.resolve(packageName), "../../"));
88
- } catch {
89
- return false;
90
- }
91
- }
92
- __name(isPackageInstalled, "isPackageInstalled");
93
- function detectDatabaseAdapter(dbConfig) {
94
- if (dbConfig) {
95
- if ("connectionString" in dbConfig || "dialect" in dbConfig) {
96
- cachedAdapter = "drizzle";
97
- return cachedAdapter;
98
- }
99
- if ("uri" in dbConfig) {
100
- cachedAdapter = "mongoose";
101
- return cachedAdapter;
1022
+
1023
+ // src/decorators/schema/extend-user.decorator.ts
1024
+ function ExtendUser(options = {}) {
1025
+ const mergedOptions = {
1026
+ timestamps: true,
1027
+ ...options
1028
+ };
1029
+ return (target) => {
1030
+ Reflect.defineMetadata(EXTEND_USER_METADATA_KEY, mergedOptions, target);
1031
+ Reflect.defineMetadata(SCHEMA_METADATA_KEY, true, target);
1032
+ try {
1033
+ const adapter = detectDatabaseAdapter();
1034
+ const { Schema: Schema2 } = __require(`@magnet-cms/adapter-db-${adapter}`);
1035
+ Schema2({
1036
+ collection: "users",
1037
+ timestamps: mergedOptions.timestamps
1038
+ })(target);
1039
+ } catch {
102
1040
  }
103
- }
104
- if (cachedAdapter) return cachedAdapter;
105
- if (isPackageInstalled("@magnet-cms/adapter-mongoose")) {
106
- cachedAdapter = "mongoose";
107
- } else if (isPackageInstalled("@magnet-cms/adapter-drizzle")) {
108
- cachedAdapter = "drizzle";
109
- } else {
110
- throw new Error("\u274C No supported database adapter found. Install @magnet-cms/adapter-mongoose or @magnet-cms/adapter-drizzle.");
111
- }
112
- return cachedAdapter;
1041
+ };
113
1042
  }
114
- __name(detectDatabaseAdapter, "detectDatabaseAdapter");
115
- function setDatabaseAdapter(adapter) {
116
- cachedAdapter = adapter;
1043
+ __name(ExtendUser, "ExtendUser");
1044
+ function isUserExtension(target) {
1045
+ return Reflect.hasMetadata(EXTEND_USER_METADATA_KEY, target);
117
1046
  }
118
- __name(setDatabaseAdapter, "setDatabaseAdapter");
119
- function clearAdapterCache() {
120
- cachedAdapter = null;
1047
+ __name(isUserExtension, "isUserExtension");
1048
+ function getExtendUserOptions(target) {
1049
+ return Reflect.getMetadata(EXTEND_USER_METADATA_KEY, target);
121
1050
  }
122
- __name(clearAdapterCache, "clearAdapterCache");
123
-
124
- // src/utils/get-model-token.util.ts
125
- function getModelToken(schema) {
126
- return `Magnet${schema.name}Model`;
127
- }
128
- __name(getModelToken, "getModelToken");
129
-
130
- // src/utils/get-schema-token.util.ts
131
- var getSchemaToken = /* @__PURE__ */ __name((schema) => {
132
- return `${schema.name}Schema`;
133
- }, "getSchemaToken");
134
- var getSettingToken = /* @__PURE__ */ __name((setting) => {
135
- return `${setting.name}Setting`;
136
- }, "getSettingToken");
1051
+ __name(getExtendUserOptions, "getExtendUserOptions");
137
1052
 
138
1053
  // src/decorators/schema/prop.decorator.ts
139
1054
  function Prop(options) {
@@ -147,7 +1062,7 @@ function Prop(options) {
147
1062
  options
148
1063
  }
149
1064
  ], target);
150
- const { Prop: Prop2 } = __require(`@magnet-cms/adapter-${adapter}`);
1065
+ const { Prop: Prop2 } = __require(`@magnet-cms/adapter-db-${adapter}`);
151
1066
  return Prop2(options)(target, propertyKey);
152
1067
  };
153
1068
  }
@@ -156,7 +1071,8 @@ __name(Prop, "Prop");
156
1071
  // src/decorators/schema/schema.decorator.ts
157
1072
  var defaultSchemaOptions = {
158
1073
  versioning: true,
159
- i18n: true
1074
+ i18n: true,
1075
+ visible: true
160
1076
  };
161
1077
  function Schema(options = {}) {
162
1078
  return (target) => {
@@ -167,7 +1083,7 @@ function Schema(options = {}) {
167
1083
  };
168
1084
  Reflect.defineMetadata(SCHEMA_METADATA_KEY, true, target);
169
1085
  Reflect.defineMetadata(SCHEMA_OPTIONS_METADATA_KEY, mergedOptions, target);
170
- const { Schema: Schema2 } = __require(`@magnet-cms/adapter-${adapter}`);
1086
+ const { Schema: Schema2 } = __require(`@magnet-cms/adapter-db-${adapter}`);
171
1087
  return Schema2()(target);
172
1088
  };
173
1089
  }
@@ -185,6 +1101,81 @@ function Setting() {
185
1101
  }
186
1102
  __name(Setting, "Setting");
187
1103
 
1104
+ // src/decorators/schema/settings.decorator.ts
1105
+ function Settings(options) {
1106
+ return (target) => {
1107
+ Reflect.defineMetadata(SETTING_METADATA_KEY, true, target);
1108
+ Reflect.defineMetadata(SETTINGS_OPTIONS_METADATA_KEY, options, target);
1109
+ };
1110
+ }
1111
+ __name(Settings, "Settings");
1112
+ function getSettingsOptions(target) {
1113
+ return Reflect.getMetadata(SETTINGS_OPTIONS_METADATA_KEY, target);
1114
+ }
1115
+ __name(getSettingsOptions, "getSettingsOptions");
1116
+ function getSettingFields(target) {
1117
+ return Reflect.getMetadata(SETTING_FIELD_METADATA_KEY, target) ?? [];
1118
+ }
1119
+ __name(getSettingFields, "getSettingFields");
1120
+ function createSettingFieldDecorator(type, defaultOptions = {}) {
1121
+ return (options) => {
1122
+ const mergedOptions = {
1123
+ ...defaultOptions,
1124
+ ...options
1125
+ };
1126
+ return (target, propertyKey) => {
1127
+ const metadata = {
1128
+ type,
1129
+ options: mergedOptions,
1130
+ propertyKey
1131
+ };
1132
+ const existingFields = Reflect.getMetadata(SETTING_FIELD_METADATA_KEY, target.constructor) ?? [];
1133
+ const filteredFields = existingFields.filter((f) => f.propertyKey !== propertyKey);
1134
+ Reflect.defineMetadata(SETTING_FIELD_METADATA_KEY, [
1135
+ ...filteredFields,
1136
+ metadata
1137
+ ], target.constructor);
1138
+ };
1139
+ };
1140
+ }
1141
+ __name(createSettingFieldDecorator, "createSettingFieldDecorator");
1142
+ var SettingField = {
1143
+ /**
1144
+ * Text setting field
1145
+ */
1146
+ Text: createSettingFieldDecorator("text"),
1147
+ /**
1148
+ * Number setting field
1149
+ */
1150
+ Number: createSettingFieldDecorator("number"),
1151
+ /**
1152
+ * Boolean setting field (toggle/switch)
1153
+ */
1154
+ Boolean: createSettingFieldDecorator("boolean"),
1155
+ /**
1156
+ * Select setting field (dropdown)
1157
+ */
1158
+ Select: createSettingFieldDecorator("select"),
1159
+ /**
1160
+ * Secret setting field (encrypted, masked in UI)
1161
+ */
1162
+ Secret: createSettingFieldDecorator("secret", {
1163
+ masked: true
1164
+ }),
1165
+ /**
1166
+ * Image setting field
1167
+ */
1168
+ Image: createSettingFieldDecorator("image"),
1169
+ /**
1170
+ * JSON setting field
1171
+ */
1172
+ JSON: createSettingFieldDecorator("json"),
1173
+ /**
1174
+ * Textarea setting field (multi-line text)
1175
+ */
1176
+ Textarea: createSettingFieldDecorator("textarea")
1177
+ };
1178
+
188
1179
  // src/decorators/schema/ui.decorator.ts
189
1180
  function UI(options) {
190
1181
  return (target, propertyKey) => {
@@ -203,9 +1194,6 @@ function UI(options) {
203
1194
  };
204
1195
  }
205
1196
  __name(UI, "UI");
206
- var Validators = /* @__PURE__ */ __name((...validators) => {
207
- return applyDecorators(...validators);
208
- }, "Validators");
209
1197
 
210
1198
  // src/decorators/schema/version.decorator.ts
211
1199
  var VERSION_METADATA_KEY = "version:metadata";
@@ -223,12 +1211,643 @@ function InjectModel(model) {
223
1211
  if (propertyKey !== void 0) {
224
1212
  Reflect.defineMetadata(INJECT_MODEL, model, target, propertyKey);
225
1213
  }
226
- const { InjectModel: InjectModel2 } = __require(`@magnet-cms/adapter-${adapter}`);
1214
+ const { InjectModel: InjectModel2 } = __require(`@magnet-cms/adapter-db-${adapter}`);
227
1215
  return InjectModel2(model)(target, propertyKey, parameterIndex);
228
1216
  };
229
1217
  }
230
1218
  __name(InjectModel, "InjectModel");
231
1219
 
1220
+ // src/errors/base.error.ts
1221
+ var ErrorCode = /* @__PURE__ */ function(ErrorCode2) {
1222
+ ErrorCode2[ErrorCode2["VALIDATION_FAILED"] = 1e3] = "VALIDATION_FAILED";
1223
+ ErrorCode2[ErrorCode2["REQUIRED_FIELD_MISSING"] = 1001] = "REQUIRED_FIELD_MISSING";
1224
+ ErrorCode2[ErrorCode2["INVALID_FORMAT"] = 1002] = "INVALID_FORMAT";
1225
+ ErrorCode2[ErrorCode2["VALUE_OUT_OF_RANGE"] = 1003] = "VALUE_OUT_OF_RANGE";
1226
+ ErrorCode2[ErrorCode2["UNIQUE_CONSTRAINT_VIOLATION"] = 1004] = "UNIQUE_CONSTRAINT_VIOLATION";
1227
+ ErrorCode2[ErrorCode2["AUTHENTICATION_REQUIRED"] = 2e3] = "AUTHENTICATION_REQUIRED";
1228
+ ErrorCode2[ErrorCode2["INVALID_CREDENTIALS"] = 2001] = "INVALID_CREDENTIALS";
1229
+ ErrorCode2[ErrorCode2["TOKEN_EXPIRED"] = 2002] = "TOKEN_EXPIRED";
1230
+ ErrorCode2[ErrorCode2["TOKEN_INVALID"] = 2003] = "TOKEN_INVALID";
1231
+ ErrorCode2[ErrorCode2["ACCOUNT_LOCKED"] = 2004] = "ACCOUNT_LOCKED";
1232
+ ErrorCode2[ErrorCode2["EMAIL_NOT_VERIFIED"] = 2005] = "EMAIL_NOT_VERIFIED";
1233
+ ErrorCode2[ErrorCode2["PERMISSION_DENIED"] = 3e3] = "PERMISSION_DENIED";
1234
+ ErrorCode2[ErrorCode2["INSUFFICIENT_PERMISSIONS"] = 3001] = "INSUFFICIENT_PERMISSIONS";
1235
+ ErrorCode2[ErrorCode2["ROLE_NOT_FOUND"] = 3002] = "ROLE_NOT_FOUND";
1236
+ ErrorCode2[ErrorCode2["PERMISSION_NOT_FOUND"] = 3003] = "PERMISSION_NOT_FOUND";
1237
+ ErrorCode2[ErrorCode2["RESOURCE_NOT_FOUND"] = 4e3] = "RESOURCE_NOT_FOUND";
1238
+ ErrorCode2[ErrorCode2["SCHEMA_NOT_FOUND"] = 4001] = "SCHEMA_NOT_FOUND";
1239
+ ErrorCode2[ErrorCode2["DOCUMENT_NOT_FOUND"] = 4002] = "DOCUMENT_NOT_FOUND";
1240
+ ErrorCode2[ErrorCode2["USER_NOT_FOUND"] = 4003] = "USER_NOT_FOUND";
1241
+ ErrorCode2[ErrorCode2["FILE_NOT_FOUND"] = 4004] = "FILE_NOT_FOUND";
1242
+ ErrorCode2[ErrorCode2["VERSION_NOT_FOUND"] = 4005] = "VERSION_NOT_FOUND";
1243
+ ErrorCode2[ErrorCode2["DATABASE_ERROR"] = 5e3] = "DATABASE_ERROR";
1244
+ ErrorCode2[ErrorCode2["CONNECTION_FAILED"] = 5001] = "CONNECTION_FAILED";
1245
+ ErrorCode2[ErrorCode2["QUERY_FAILED"] = 5002] = "QUERY_FAILED";
1246
+ ErrorCode2[ErrorCode2["TRANSACTION_FAILED"] = 5003] = "TRANSACTION_FAILED";
1247
+ ErrorCode2[ErrorCode2["DUPLICATE_KEY"] = 5004] = "DUPLICATE_KEY";
1248
+ ErrorCode2[ErrorCode2["PLUGIN_ERROR"] = 6e3] = "PLUGIN_ERROR";
1249
+ ErrorCode2[ErrorCode2["PLUGIN_NOT_FOUND"] = 6001] = "PLUGIN_NOT_FOUND";
1250
+ ErrorCode2[ErrorCode2["PLUGIN_INITIALIZATION_FAILED"] = 6002] = "PLUGIN_INITIALIZATION_FAILED";
1251
+ ErrorCode2[ErrorCode2["HOOK_EXECUTION_FAILED"] = 6003] = "HOOK_EXECUTION_FAILED";
1252
+ ErrorCode2[ErrorCode2["EXTERNAL_SERVICE_ERROR"] = 7e3] = "EXTERNAL_SERVICE_ERROR";
1253
+ ErrorCode2[ErrorCode2["STORAGE_ERROR"] = 7001] = "STORAGE_ERROR";
1254
+ ErrorCode2[ErrorCode2["EMAIL_SERVICE_ERROR"] = 7002] = "EMAIL_SERVICE_ERROR";
1255
+ ErrorCode2[ErrorCode2["WEBHOOK_DELIVERY_FAILED"] = 7003] = "WEBHOOK_DELIVERY_FAILED";
1256
+ ErrorCode2[ErrorCode2["INTERNAL_ERROR"] = 9e3] = "INTERNAL_ERROR";
1257
+ ErrorCode2[ErrorCode2["CONFIGURATION_ERROR"] = 9001] = "CONFIGURATION_ERROR";
1258
+ ErrorCode2[ErrorCode2["UNEXPECTED_ERROR"] = 9999] = "UNEXPECTED_ERROR";
1259
+ return ErrorCode2;
1260
+ }({});
1261
+ var MagnetError = class extends Error {
1262
+ static {
1263
+ __name(this, "MagnetError");
1264
+ }
1265
+ timestamp;
1266
+ metadata;
1267
+ constructor(message, metadata = {}) {
1268
+ super(message);
1269
+ this.name = this.constructor.name;
1270
+ this.timestamp = /* @__PURE__ */ new Date();
1271
+ this.metadata = metadata;
1272
+ if (Error.captureStackTrace) {
1273
+ Error.captureStackTrace(this, this.constructor);
1274
+ }
1275
+ }
1276
+ /**
1277
+ * Convert to API response format
1278
+ */
1279
+ toResponse() {
1280
+ return {
1281
+ error: {
1282
+ code: this.code,
1283
+ message: this.message,
1284
+ name: this.name,
1285
+ timestamp: this.timestamp.toISOString(),
1286
+ metadata: this.metadata
1287
+ }
1288
+ };
1289
+ }
1290
+ /**
1291
+ * Convert to JSON for logging
1292
+ */
1293
+ toJSON() {
1294
+ return {
1295
+ name: this.name,
1296
+ code: this.code,
1297
+ message: this.message,
1298
+ httpStatus: this.httpStatus,
1299
+ timestamp: this.timestamp.toISOString(),
1300
+ metadata: this.metadata,
1301
+ stack: this.stack
1302
+ };
1303
+ }
1304
+ };
1305
+
1306
+ // src/errors/validation.error.ts
1307
+ var ValidationError = class _ValidationError extends MagnetError {
1308
+ static {
1309
+ __name(this, "ValidationError");
1310
+ }
1311
+ code = ErrorCode.VALIDATION_FAILED;
1312
+ httpStatus = 400;
1313
+ details;
1314
+ constructor(message, details, metadata) {
1315
+ super(message, metadata);
1316
+ this.details = details;
1317
+ }
1318
+ /**
1319
+ * Create ValidationError from class-validator errors
1320
+ */
1321
+ static fromClassValidator(errors) {
1322
+ const details = errors.flatMap((error) => Object.entries(error.constraints ?? {}).map(([constraint, message]) => ({
1323
+ field: error.property,
1324
+ message,
1325
+ constraint,
1326
+ value: error.value
1327
+ })));
1328
+ return new _ValidationError(`Validation failed for ${details.length} field(s)`, details);
1329
+ }
1330
+ toResponse() {
1331
+ return {
1332
+ error: {
1333
+ ...super.toResponse().error,
1334
+ details: this.details
1335
+ }
1336
+ };
1337
+ }
1338
+ };
1339
+ var RequiredFieldError = class extends MagnetError {
1340
+ static {
1341
+ __name(this, "RequiredFieldError");
1342
+ }
1343
+ code = ErrorCode.REQUIRED_FIELD_MISSING;
1344
+ httpStatus = 400;
1345
+ constructor(field, metadata) {
1346
+ super(`Required field '${field}' is missing`, {
1347
+ ...metadata,
1348
+ field
1349
+ });
1350
+ }
1351
+ };
1352
+ var InvalidFormatError = class extends MagnetError {
1353
+ static {
1354
+ __name(this, "InvalidFormatError");
1355
+ }
1356
+ code = ErrorCode.INVALID_FORMAT;
1357
+ httpStatus = 400;
1358
+ constructor(field, expectedFormat, metadata) {
1359
+ super(`Field '${field}' has invalid format. Expected: ${expectedFormat}`, {
1360
+ ...metadata,
1361
+ field
1362
+ });
1363
+ }
1364
+ };
1365
+ var ValueOutOfRangeError = class extends MagnetError {
1366
+ static {
1367
+ __name(this, "ValueOutOfRangeError");
1368
+ }
1369
+ code = ErrorCode.VALUE_OUT_OF_RANGE;
1370
+ httpStatus = 400;
1371
+ constructor(field, min, max, metadata) {
1372
+ const rangeMsg = min !== void 0 && max !== void 0 ? `between ${min} and ${max}` : min !== void 0 ? `at least ${min}` : max !== void 0 ? `at most ${max}` : "within valid range";
1373
+ super(`Field '${field}' must be ${rangeMsg}`, {
1374
+ ...metadata,
1375
+ field
1376
+ });
1377
+ }
1378
+ };
1379
+
1380
+ // src/errors/auth.error.ts
1381
+ var AuthenticationRequiredError = class extends MagnetError {
1382
+ static {
1383
+ __name(this, "AuthenticationRequiredError");
1384
+ }
1385
+ code = ErrorCode.AUTHENTICATION_REQUIRED;
1386
+ httpStatus = 401;
1387
+ constructor(message = "Authentication required", metadata) {
1388
+ super(message, metadata);
1389
+ }
1390
+ };
1391
+ var InvalidCredentialsError = class extends MagnetError {
1392
+ static {
1393
+ __name(this, "InvalidCredentialsError");
1394
+ }
1395
+ code = ErrorCode.INVALID_CREDENTIALS;
1396
+ httpStatus = 401;
1397
+ constructor(message = "Invalid email or password", metadata) {
1398
+ super(message, metadata);
1399
+ }
1400
+ };
1401
+ var TokenExpiredError = class extends MagnetError {
1402
+ static {
1403
+ __name(this, "TokenExpiredError");
1404
+ }
1405
+ code = ErrorCode.TOKEN_EXPIRED;
1406
+ httpStatus = 401;
1407
+ constructor(message = "Token has expired", metadata) {
1408
+ super(message, metadata);
1409
+ }
1410
+ };
1411
+ var TokenInvalidError = class extends MagnetError {
1412
+ static {
1413
+ __name(this, "TokenInvalidError");
1414
+ }
1415
+ code = ErrorCode.TOKEN_INVALID;
1416
+ httpStatus = 401;
1417
+ constructor(message = "Token is invalid", metadata) {
1418
+ super(message, metadata);
1419
+ }
1420
+ };
1421
+ var AccountLockedError = class extends MagnetError {
1422
+ static {
1423
+ __name(this, "AccountLockedError");
1424
+ }
1425
+ code = ErrorCode.ACCOUNT_LOCKED;
1426
+ httpStatus = 423;
1427
+ unlockAt;
1428
+ constructor(message = "Account is temporarily locked", unlockAt, metadata) {
1429
+ super(message, metadata);
1430
+ this.unlockAt = unlockAt;
1431
+ }
1432
+ };
1433
+ var EmailNotVerifiedError = class extends MagnetError {
1434
+ static {
1435
+ __name(this, "EmailNotVerifiedError");
1436
+ }
1437
+ code = ErrorCode.EMAIL_NOT_VERIFIED;
1438
+ httpStatus = 403;
1439
+ constructor(message = "Email address not verified", metadata) {
1440
+ super(message, metadata);
1441
+ }
1442
+ };
1443
+ var PermissionDeniedError = class extends MagnetError {
1444
+ static {
1445
+ __name(this, "PermissionDeniedError");
1446
+ }
1447
+ code = ErrorCode.PERMISSION_DENIED;
1448
+ httpStatus = 403;
1449
+ requiredPermission;
1450
+ constructor(message = "You do not have permission to perform this action", requiredPermission, metadata) {
1451
+ super(message, metadata);
1452
+ this.requiredPermission = requiredPermission;
1453
+ }
1454
+ };
1455
+ var InsufficientPermissionsError = class extends MagnetError {
1456
+ static {
1457
+ __name(this, "InsufficientPermissionsError");
1458
+ }
1459
+ code = ErrorCode.INSUFFICIENT_PERMISSIONS;
1460
+ httpStatus = 403;
1461
+ requiredPermissions;
1462
+ constructor(requiredPermissions, metadata) {
1463
+ super(`Insufficient permissions. Required: ${requiredPermissions.join(", ")}`, metadata);
1464
+ this.requiredPermissions = requiredPermissions;
1465
+ }
1466
+ };
1467
+ var RoleNotFoundError = class extends MagnetError {
1468
+ static {
1469
+ __name(this, "RoleNotFoundError");
1470
+ }
1471
+ code = ErrorCode.ROLE_NOT_FOUND;
1472
+ httpStatus = 404;
1473
+ constructor(roleName, metadata) {
1474
+ super(`Role '${roleName}' not found`, metadata);
1475
+ }
1476
+ };
1477
+ var PermissionNotFoundError = class extends MagnetError {
1478
+ static {
1479
+ __name(this, "PermissionNotFoundError");
1480
+ }
1481
+ code = ErrorCode.PERMISSION_NOT_FOUND;
1482
+ httpStatus = 400;
1483
+ invalidPermissionIds;
1484
+ constructor(invalidPermissionIds, metadata) {
1485
+ super(`Invalid permission(s): ${invalidPermissionIds.join(", ")}. These permissions are not registered in the system.`, {
1486
+ ...metadata,
1487
+ context: {
1488
+ ...metadata?.context,
1489
+ invalidPermissionIds
1490
+ }
1491
+ });
1492
+ this.invalidPermissionIds = invalidPermissionIds;
1493
+ }
1494
+ };
1495
+
1496
+ // src/errors/resource.error.ts
1497
+ var ResourceNotFoundError = class extends MagnetError {
1498
+ static {
1499
+ __name(this, "ResourceNotFoundError");
1500
+ }
1501
+ code = ErrorCode.RESOURCE_NOT_FOUND;
1502
+ httpStatus = 404;
1503
+ constructor(resourceType, identifier, metadata) {
1504
+ super(`${resourceType} with identifier '${identifier}' not found`, {
1505
+ ...metadata,
1506
+ resourceId: identifier
1507
+ });
1508
+ }
1509
+ };
1510
+ var SchemaNotFoundError = class extends MagnetError {
1511
+ static {
1512
+ __name(this, "SchemaNotFoundError");
1513
+ }
1514
+ code = ErrorCode.SCHEMA_NOT_FOUND;
1515
+ httpStatus = 404;
1516
+ constructor(schemaName, metadata) {
1517
+ super(`Schema '${schemaName}' not found`, {
1518
+ ...metadata,
1519
+ schema: schemaName
1520
+ });
1521
+ }
1522
+ };
1523
+ var DocumentNotFoundError = class extends MagnetError {
1524
+ static {
1525
+ __name(this, "DocumentNotFoundError");
1526
+ }
1527
+ code = ErrorCode.DOCUMENT_NOT_FOUND;
1528
+ httpStatus = 404;
1529
+ constructor(schema, id, metadata) {
1530
+ super(`Document '${id}' not found in ${schema}`, {
1531
+ ...metadata,
1532
+ schema,
1533
+ resourceId: id
1534
+ });
1535
+ }
1536
+ };
1537
+ var UserNotFoundError = class extends MagnetError {
1538
+ static {
1539
+ __name(this, "UserNotFoundError");
1540
+ }
1541
+ code = ErrorCode.USER_NOT_FOUND;
1542
+ httpStatus = 404;
1543
+ constructor(identifier, metadata) {
1544
+ super(`User '${identifier}' not found`, {
1545
+ ...metadata,
1546
+ resourceId: identifier
1547
+ });
1548
+ }
1549
+ };
1550
+ var FileNotFoundError = class extends MagnetError {
1551
+ static {
1552
+ __name(this, "FileNotFoundError");
1553
+ }
1554
+ code = ErrorCode.FILE_NOT_FOUND;
1555
+ httpStatus = 404;
1556
+ constructor(path, metadata) {
1557
+ super(`File '${path}' not found`, {
1558
+ ...metadata,
1559
+ resourceId: path
1560
+ });
1561
+ }
1562
+ };
1563
+ var VersionNotFoundError = class extends MagnetError {
1564
+ static {
1565
+ __name(this, "VersionNotFoundError");
1566
+ }
1567
+ code = ErrorCode.VERSION_NOT_FOUND;
1568
+ httpStatus = 404;
1569
+ constructor(schema, documentId, versionId, metadata) {
1570
+ super(`Version '${versionId}' not found for document '${documentId}' in ${schema}`, {
1571
+ ...metadata,
1572
+ schema,
1573
+ resourceId: documentId,
1574
+ context: {
1575
+ versionId
1576
+ }
1577
+ });
1578
+ }
1579
+ };
1580
+
1581
+ // src/errors/database.error.ts
1582
+ var DatabaseError = class extends MagnetError {
1583
+ static {
1584
+ __name(this, "DatabaseError");
1585
+ }
1586
+ code = ErrorCode.DATABASE_ERROR;
1587
+ httpStatus = 500;
1588
+ originalError;
1589
+ constructor(message, originalError, metadata) {
1590
+ super(message, metadata);
1591
+ this.originalError = originalError;
1592
+ }
1593
+ };
1594
+ var ConnectionFailedError = class extends MagnetError {
1595
+ static {
1596
+ __name(this, "ConnectionFailedError");
1597
+ }
1598
+ code = ErrorCode.CONNECTION_FAILED;
1599
+ httpStatus = 503;
1600
+ constructor(message = "Database connection failed", metadata) {
1601
+ super(message, metadata);
1602
+ }
1603
+ };
1604
+ var QueryFailedError = class extends MagnetError {
1605
+ static {
1606
+ __name(this, "QueryFailedError");
1607
+ }
1608
+ code = ErrorCode.QUERY_FAILED;
1609
+ httpStatus = 500;
1610
+ query;
1611
+ constructor(message, query, metadata) {
1612
+ super(message, metadata);
1613
+ this.query = query;
1614
+ }
1615
+ };
1616
+ var TransactionFailedError = class extends MagnetError {
1617
+ static {
1618
+ __name(this, "TransactionFailedError");
1619
+ }
1620
+ code = ErrorCode.TRANSACTION_FAILED;
1621
+ httpStatus = 500;
1622
+ constructor(message = "Transaction failed", metadata) {
1623
+ super(message, metadata);
1624
+ }
1625
+ };
1626
+ var DuplicateKeyError = class extends MagnetError {
1627
+ static {
1628
+ __name(this, "DuplicateKeyError");
1629
+ }
1630
+ code = ErrorCode.DUPLICATE_KEY;
1631
+ httpStatus = 409;
1632
+ constructor(field, value, metadata) {
1633
+ super(`A record with ${field} '${String(value)}' already exists`, {
1634
+ ...metadata,
1635
+ field
1636
+ });
1637
+ }
1638
+ };
1639
+
1640
+ // src/errors/plugin.error.ts
1641
+ var PluginError = class extends MagnetError {
1642
+ static {
1643
+ __name(this, "PluginError");
1644
+ }
1645
+ code = ErrorCode.PLUGIN_ERROR;
1646
+ httpStatus = 500;
1647
+ constructor(pluginName, message, metadata) {
1648
+ super(`Plugin '${pluginName}': ${message}`, metadata);
1649
+ }
1650
+ };
1651
+ var PluginNotFoundError = class extends MagnetError {
1652
+ static {
1653
+ __name(this, "PluginNotFoundError");
1654
+ }
1655
+ code = ErrorCode.PLUGIN_NOT_FOUND;
1656
+ httpStatus = 404;
1657
+ constructor(pluginName, metadata) {
1658
+ super(`Plugin '${pluginName}' not found`, metadata);
1659
+ }
1660
+ };
1661
+ var PluginInitializationError = class extends MagnetError {
1662
+ static {
1663
+ __name(this, "PluginInitializationError");
1664
+ }
1665
+ code = ErrorCode.PLUGIN_INITIALIZATION_FAILED;
1666
+ httpStatus = 500;
1667
+ constructor(pluginName, reason, metadata) {
1668
+ super(`Failed to initialize plugin '${pluginName}': ${reason}`, metadata);
1669
+ }
1670
+ };
1671
+ var HookExecutionError = class extends MagnetError {
1672
+ static {
1673
+ __name(this, "HookExecutionError");
1674
+ }
1675
+ code = ErrorCode.HOOK_EXECUTION_FAILED;
1676
+ httpStatus = 500;
1677
+ constructor(hookName, pluginName, reason, metadata) {
1678
+ super(`Hook '${hookName}' in plugin '${pluginName}' failed: ${reason}`, metadata);
1679
+ }
1680
+ };
1681
+
1682
+ // src/errors/external.error.ts
1683
+ var ExternalServiceError = class extends MagnetError {
1684
+ static {
1685
+ __name(this, "ExternalServiceError");
1686
+ }
1687
+ code = ErrorCode.EXTERNAL_SERVICE_ERROR;
1688
+ httpStatus = 502;
1689
+ constructor(serviceName, message, metadata) {
1690
+ super(`External service '${serviceName}' error: ${message}`, metadata);
1691
+ }
1692
+ };
1693
+ var StorageError = class extends MagnetError {
1694
+ static {
1695
+ __name(this, "StorageError");
1696
+ }
1697
+ code = ErrorCode.STORAGE_ERROR;
1698
+ httpStatus = 502;
1699
+ constructor(message, metadata) {
1700
+ super(`Storage error: ${message}`, metadata);
1701
+ }
1702
+ };
1703
+ var EmailServiceError = class extends MagnetError {
1704
+ static {
1705
+ __name(this, "EmailServiceError");
1706
+ }
1707
+ code = ErrorCode.EMAIL_SERVICE_ERROR;
1708
+ httpStatus = 502;
1709
+ constructor(message, metadata) {
1710
+ super(`Email service error: ${message}`, metadata);
1711
+ }
1712
+ };
1713
+ var WebhookDeliveryError = class extends MagnetError {
1714
+ static {
1715
+ __name(this, "WebhookDeliveryError");
1716
+ }
1717
+ code = ErrorCode.WEBHOOK_DELIVERY_FAILED;
1718
+ httpStatus = 502;
1719
+ webhookUrl;
1720
+ statusCode;
1721
+ constructor(webhookUrl, reason, statusCode, metadata) {
1722
+ super(`Webhook delivery to '${webhookUrl}' failed: ${reason}`, metadata);
1723
+ this.webhookUrl = webhookUrl;
1724
+ this.statusCode = statusCode;
1725
+ }
1726
+ };
1727
+
1728
+ // src/errors/internal.error.ts
1729
+ var InternalError = class extends MagnetError {
1730
+ static {
1731
+ __name(this, "InternalError");
1732
+ }
1733
+ code = ErrorCode.INTERNAL_ERROR;
1734
+ httpStatus = 500;
1735
+ constructor(message = "An internal error occurred", metadata) {
1736
+ super(message, metadata);
1737
+ }
1738
+ };
1739
+ var ConfigurationError = class extends MagnetError {
1740
+ static {
1741
+ __name(this, "ConfigurationError");
1742
+ }
1743
+ code = ErrorCode.CONFIGURATION_ERROR;
1744
+ httpStatus = 500;
1745
+ constructor(message, metadata) {
1746
+ super(`Configuration error: ${message}`, metadata);
1747
+ }
1748
+ };
1749
+ var UnexpectedError = class extends MagnetError {
1750
+ static {
1751
+ __name(this, "UnexpectedError");
1752
+ }
1753
+ code = ErrorCode.UNEXPECTED_ERROR;
1754
+ httpStatus = 500;
1755
+ originalError;
1756
+ constructor(message = "An unexpected error occurred", originalError, metadata) {
1757
+ super(message, metadata);
1758
+ this.originalError = originalError;
1759
+ }
1760
+ };
1761
+
1762
+ // src/errors/factory.ts
1763
+ function fromMongooseError(error, context) {
1764
+ if (isCastError(error) && error.path === "_id") {
1765
+ return new DocumentNotFoundError(context?.schema ?? "document", String(error.value), {
1766
+ operation: context?.operation
1767
+ });
1768
+ }
1769
+ if (isDuplicateKeyError(error)) {
1770
+ const keyValue = error.keyValue;
1771
+ const field = Object.keys(keyValue)[0] ?? "field";
1772
+ const value = keyValue[field];
1773
+ return new DuplicateKeyError(field, value, {
1774
+ schema: context?.schema
1775
+ });
1776
+ }
1777
+ if (isValidationError(error)) {
1778
+ const details = Object.entries(error.errors).map(([field, err]) => {
1779
+ const errorObj = err;
1780
+ return {
1781
+ field,
1782
+ message: String(errorObj.message ?? "Validation failed")
1783
+ };
1784
+ });
1785
+ return new ValidationError("Validation failed", details, {
1786
+ schema: context?.schema
1787
+ });
1788
+ }
1789
+ return new DatabaseError(error instanceof Error ? error.message : "Database operation failed", error, {
1790
+ schema: context?.schema
1791
+ });
1792
+ }
1793
+ __name(fromMongooseError, "fromMongooseError");
1794
+ function extractPostgresUniqueInfo(error) {
1795
+ if (!error.detail) {
1796
+ return null;
1797
+ }
1798
+ const match = error.detail.match(/Key \((\w+)\)=\(([^)]+)\)/);
1799
+ const field = match?.[1];
1800
+ const value = match?.[2];
1801
+ if (field && value) {
1802
+ return {
1803
+ field,
1804
+ value
1805
+ };
1806
+ }
1807
+ return null;
1808
+ }
1809
+ __name(extractPostgresUniqueInfo, "extractPostgresUniqueInfo");
1810
+ function fromDrizzleError(error, context) {
1811
+ if (isPostgresUniqueError(error)) {
1812
+ const info = extractPostgresUniqueInfo(error);
1813
+ if (info) {
1814
+ return new DuplicateKeyError(info.field, info.value, {
1815
+ schema: context?.schema
1816
+ });
1817
+ }
1818
+ }
1819
+ if (error instanceof Error && error.message.includes("unique constraint")) {
1820
+ const match = error.message.match(/Key \((\w+)\)=\(([^)]+)\)/);
1821
+ const field = match?.[1];
1822
+ const value = match?.[2];
1823
+ if (field && value) {
1824
+ return new DuplicateKeyError(field, value, {
1825
+ schema: context?.schema
1826
+ });
1827
+ }
1828
+ }
1829
+ if (error instanceof Error && error.message.includes("no result")) {
1830
+ return new DocumentNotFoundError(context?.schema ?? "document", "unknown", {
1831
+ operation: "read"
1832
+ });
1833
+ }
1834
+ return new DatabaseError(error instanceof Error ? error.message : "Database operation failed", error, {
1835
+ schema: context?.schema
1836
+ });
1837
+ }
1838
+ __name(fromDrizzleError, "fromDrizzleError");
1839
+ function isMagnetError(error) {
1840
+ return error instanceof MagnetError;
1841
+ }
1842
+ __name(isMagnetError, "isMagnetError");
1843
+ function wrapError(error, fallbackMessage = "An error occurred") {
1844
+ if (isMagnetError(error)) {
1845
+ return error;
1846
+ }
1847
+ return new DatabaseError(error instanceof Error ? error.message : fallbackMessage, error);
1848
+ }
1849
+ __name(wrapError, "wrapError");
1850
+
232
1851
  // src/exceptions/validation.exception.ts
233
1852
  var ValidationException = class extends Error {
234
1853
  static {
@@ -246,13 +1865,35 @@ var Model = class {
246
1865
  __name(this, "Model");
247
1866
  }
248
1867
  /**
1868
+ * Get current locale
1869
+ */
1870
+ getLocale() {
1871
+ return "en";
1872
+ }
1873
+ /**
249
1874
  * Set the version for subsequent operations
250
1875
  * @param versionId The version ID or status ('draft', 'published', 'archived')
1876
+ * @returns Same instance (chainable)
251
1877
  */
252
1878
  version(versionId) {
253
1879
  return this;
254
1880
  }
255
1881
  /**
1882
+ * Check if versioning is enabled for this model
1883
+ */
1884
+ isVersioningEnabled() {
1885
+ return false;
1886
+ }
1887
+ /**
1888
+ * Create a version snapshot of a document
1889
+ * @param documentId The document ID
1890
+ * @param data The data to version
1891
+ * @returns Version record or null if versioning disabled
1892
+ */
1893
+ createVersion(documentId, data) {
1894
+ return Promise.resolve(null);
1895
+ }
1896
+ /**
256
1897
  * Find all versions of a document
257
1898
  * @param documentId The document ID
258
1899
  */
@@ -267,12 +1908,13 @@ var Model = class {
267
1908
  return Promise.resolve(null);
268
1909
  }
269
1910
  /**
270
- * Restore a version
1911
+ * Restore a document to a specific version
271
1912
  * @param versionId The version ID to restore
272
1913
  */
273
1914
  restoreVersion(versionId) {
274
1915
  return Promise.resolve(null);
275
1916
  }
1917
+ // ============= Query Builder =============
276
1918
  /**
277
1919
  * Create a query builder for advanced queries with sorting, pagination, and operators.
278
1920
  * The query builder inherits the current locale/version context.
@@ -289,15 +1931,29 @@ var Model = class {
289
1931
  query() {
290
1932
  throw new Error("QueryBuilder not implemented by this adapter");
291
1933
  }
1934
+ // ============= Native Access =============
292
1935
  /**
293
1936
  * Get access to the native database model/collection.
294
1937
  * Use with caution - bypasses Magnet abstractions like locale and versioning.
295
1938
  *
296
- * @returns The underlying database model (e.g., Mongoose Model)
1939
+ * @returns Typed native access object
297
1940
  */
298
1941
  native() {
299
1942
  throw new Error("Native access not implemented by this adapter");
300
1943
  }
1944
+ // ============= Metadata =============
1945
+ /**
1946
+ * Get schema name
1947
+ */
1948
+ getSchemaName() {
1949
+ throw new Error("getSchemaName not implemented by this adapter");
1950
+ }
1951
+ /**
1952
+ * Get schema metadata
1953
+ */
1954
+ getMetadata() {
1955
+ throw new Error("getMetadata not implemented by this adapter");
1956
+ }
301
1957
  };
302
1958
 
303
1959
  // src/model/mixed.model.ts
@@ -314,6 +1970,17 @@ var QueryBuilder = class {
314
1970
  static {
315
1971
  __name(this, "QueryBuilder");
316
1972
  }
1973
+ /**
1974
+ * Exclude specific fields from results
1975
+ * @param fields Array of field names to exclude
1976
+ */
1977
+ exclude(fields) {
1978
+ const projection = {};
1979
+ for (const field of fields) {
1980
+ projection[field] = 0;
1981
+ }
1982
+ return this.select(projection);
1983
+ }
317
1984
  };
318
1985
 
319
1986
  // src/types/auth.types.ts
@@ -330,6 +1997,13 @@ var AuthStrategy = class {
330
1997
  }
331
1998
  };
332
1999
 
2000
+ // src/types/email.types.ts
2001
+ var EmailAdapter = class {
2002
+ static {
2003
+ __name(this, "EmailAdapter");
2004
+ }
2005
+ };
2006
+
333
2007
  // src/types/config.types.ts
334
2008
  var MagnetModuleOptions = class {
335
2009
  static {
@@ -345,17 +2019,54 @@ var MagnetModuleOptions = class {
345
2019
  playground;
346
2020
  storage;
347
2021
  /**
2022
+ * Email adapter configuration
2023
+ * @example
2024
+ * email: { adapter: 'nodemailer', nodemailer: { host: 'smtp.example.com', port: 587, auth: { user: 'user', pass: 'pass' } } }
2025
+ */
2026
+ email;
2027
+ /**
348
2028
  * Plugins to load with the Magnet module
349
2029
  */
350
2030
  plugins;
351
- constructor({ db, jwt, auth, internationalization, playground, storage, plugins }) {
2031
+ /**
2032
+ * Admin panel configuration (enabled by default when omitted).
2033
+ * @example
2034
+ * // Explicit enable (same as omitting `admin`)
2035
+ * admin: true
2036
+ *
2037
+ * // Custom path
2038
+ * admin: { enabled: true, path: '/dashboard' }
2039
+ *
2040
+ * // Disable (for API-only mode)
2041
+ * admin: false
2042
+ */
2043
+ admin;
2044
+ /**
2045
+ * RBAC (Role-Based Access Control) configuration
2046
+ * @example
2047
+ * rbac: { enabled: true, defaultRole: 'authenticated' }
2048
+ */
2049
+ rbac;
2050
+ /**
2051
+ * Vault configuration for encrypted secrets management.
2052
+ * Uses the built-in DB adapter by default (requires VAULT_MASTER_KEY env var).
2053
+ * @example
2054
+ * vault: { adapter: 'db' }
2055
+ * vault: { adapter: 'hashicorp', hashicorp: { url: 'https://vault.example.com:8200' } }
2056
+ */
2057
+ vault;
2058
+ constructor({ db, jwt, auth, internationalization, playground, storage, email, plugins, admin, rbac, vault }) {
352
2059
  this.db = db;
353
2060
  this.jwt = jwt;
354
2061
  this.auth = auth;
355
2062
  this.internationalization = internationalization;
356
2063
  this.playground = playground;
357
2064
  this.storage = storage;
2065
+ this.email = email;
358
2066
  this.plugins = plugins;
2067
+ this.admin = admin;
2068
+ this.rbac = rbac;
2069
+ this.vault = vault;
359
2070
  }
360
2071
  };
361
2072
 
@@ -366,6 +2077,16 @@ var DatabaseAdapter = class {
366
2077
  }
367
2078
  };
368
2079
 
2080
+ // src/types/settings.types.ts
2081
+ function isSettingFieldMetadata(value) {
2082
+ if (typeof value !== "object" || value === null) {
2083
+ return false;
2084
+ }
2085
+ const metadata = value;
2086
+ return typeof metadata.type === "string" && typeof metadata.options === "object" && metadata.options !== null && "propertyKey" in metadata;
2087
+ }
2088
+ __name(isSettingFieldMetadata, "isSettingFieldMetadata");
2089
+
369
2090
  // src/types/storage.types.ts
370
2091
  var StorageAdapter = class {
371
2092
  static {
@@ -373,4 +2094,18 @@ var StorageAdapter = class {
373
2094
  }
374
2095
  };
375
2096
 
376
- export { AuthStrategy, BASE_SCHEMA_METADATA_KEY, DESIGN_META, DESIGN_PARAM_TYPES, DESIGN_RETURN_TYPE, DESIGN_TYPE, DatabaseAdapter, INJECT_MODEL, InjectModel, MagnetModuleOptions, Mixed, Model, PROP_METADATA_KEY, Prop, QueryBuilder, RESOLVER_METADATA_KEY, RESOLVE_METADATA_KEY, Resolve, Resolver, SCHEMA_METADATA_KEY, SCHEMA_OPTIONS_METADATA_KEY, SETTING_METADATA_KEY, Schema, Setting, StorageAdapter, UI, UI_METADATA_KEY, VERSION_METADATA_KEY, ValidationException, Validators, Version, clearAdapterCache, detectDatabaseAdapter, getModelToken, getSchemaOptions, getSchemaToken, getSettingToken, setDatabaseAdapter };
2097
+ // src/types/vault.types.ts
2098
+ var VaultAdapter = class {
2099
+ static {
2100
+ __name(this, "VaultAdapter");
2101
+ }
2102
+ };
2103
+
2104
+ // src/types/cache.types.ts
2105
+ var CacheAdapter = class {
2106
+ static {
2107
+ __name(this, "CacheAdapter");
2108
+ }
2109
+ };
2110
+
2111
+ export { AccountLockedError, AuthStrategy, AuthenticationRequiredError, BASE_SCHEMA_METADATA_KEY, CacheAdapter, ConfigurationError, ConnectionFailedError, DESIGN_META, DESIGN_PARAM_TYPES, DESIGN_RETURN_TYPE, DESIGN_TYPE, DatabaseAdapter, DatabaseError, DocumentNotFoundError, DuplicateKeyError, EVENT_HANDLER_METADATA, EXTEND_USER_METADATA_KEY, EmailAdapter, EmailNotVerifiedError, EmailServiceError, ErrorCode, ExtendUser, ExternalServiceError, FIELD_METADATA_KEY, Field, FileNotFoundError, HasPermission, HookExecutionError, INJECT_MODEL, InjectModel, InsufficientPermissionsError, InternalError, InvalidCredentialsError, InvalidFormatError, MagnetError, MagnetModuleOptions, Mixed, Model, OnEvent, PERMISSION_METADATA_KEY, PERMISSION_OPTIONS_METADATA_KEY, PROP_METADATA_KEY, PermissionDeniedError, PermissionMeta, PermissionNotFoundError, PluginError, PluginInitializationError, PluginNotFoundError, Prop, QueryBuilder, QueryFailedError, RESOLVED_PERMISSION_KEY, RESOLVER_METADATA_KEY, RESOLVE_METADATA_KEY, RequirePermission, RequiredFieldError, Resolve, Resolver, ResourceNotFoundError, RoleNotFoundError, SCHEMA_METADATA_KEY, SCHEMA_OPTIONS_METADATA_KEY, SETTINGS_OPTIONS_METADATA_KEY, SETTING_FIELD_METADATA_KEY, SETTING_METADATA_KEY, Schema, SchemaNotFoundError, Setting, SettingField, Settings, StorageAdapter, StorageError, TokenExpiredError, TokenInvalidError, TransactionFailedError, UI, UI_METADATA_KEY, UnexpectedError, UserNotFoundError, VERSION_METADATA_KEY, ValidationError, ValidationException, Validators, ValueOutOfRangeError, VaultAdapter, Version, VersionNotFoundError, WebhookDeliveryError, assert, assertDefined, clearAdapterCache, clearDatabaseAdapterSingletonForFeature, createFieldDecorator, detectDatabaseAdapter, fromDrizzleError, fromMongooseError, getAdapterToken, getDatabaseAdapterSingletonForFeature, getDocumentId, getExtendUserOptions, getFieldMetadata, getFieldMetadataForProperty, getModelToken, getPermissionMetadata, getRegisteredModel, getSchemaOptions, getSchemaToken, getSettingFields, getSettingToken, getSettingsOptions, hasMethod, hasPermissionDecorator, hasProperties, hasProperty, hasSetLocale, hasToString, isArray, isBoolean, isCastError, isDocument, isDuplicateKeyError, isFieldMetadata, isFunction, isMagnetError, isNumber, isObject, isPostgresUniqueError, isSettingFieldMetadata, isString, isStringArray, isStringRecord, isUserExtension, isValidFieldType, isValidationError, isVersionDocument, mapFieldTypeToProp, mapFieldTypeToUI, registerDatabaseAdapterSingletonForFeature, registerModel, setDatabaseAdapter, wrapError };