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