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