@atscript/mongo 0.1.26 → 0.1.28

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
@@ -43,15 +43,10 @@ const analyzers = [
43
43
  "lucene.russian",
44
44
  "lucene.arabic"
45
45
  ];
46
- const annotations = { mongo: {
46
+ const annotations = {
47
47
  collection: new __atscript_core.AnnotationSpec({
48
- description: "Defines a **MongoDB collection**. This annotation is required to mark an interface as a collection.\n\n- Automatically enforces a **non-optional** `_id` field.\n- `_id` must be of type **`string`**, **`number`**, or **`mongo.objectId`**.\n- Ensures that `_id` is included if not explicitly defined.\n\n**Example:**\n```atscript\n@mongo.collection \"users\"\nexport interface User {\n _id: mongo.objectId\n email: string.email\n}\n```\n",
48
+ description: "Marks an interface as a **MongoDB collection**.\n\n- Use together with `@db.table \"name\"` which provides the collection name.\n- Automatically injects a **non-optional** `_id` field if not explicitly defined.\n- `_id` must be of type **`string`**, **`number`**, or **`mongo.objectId`**.\n\n**Example:**\n```atscript\n@db.table \"users\"\n@db.mongo.collection\nexport interface User {\n _id: mongo.objectId\n email: string.email\n}\n```\n",
49
49
  nodeType: ["interface"],
50
- argument: {
51
- name: "name",
52
- type: "string",
53
- description: "The **name of the MongoDB collection**."
54
- },
55
50
  validate(token, args, doc) {
56
51
  const parent = token.parentNode;
57
52
  const struc = parent?.getDefinition();
@@ -60,7 +55,7 @@ const annotations = { mongo: {
60
55
  const _id = parent.props.get("_id");
61
56
  const isOptional = !!_id.token("optional");
62
57
  if (isOptional) errors.push({
63
- message: `[mongo] _id can't be optional in Mongo Collection`,
58
+ message: `[db.mongo] _id can't be optional in Mongo Collection`,
64
59
  severity: 1,
65
60
  range: _id.token("identifier").range
66
61
  });
@@ -72,7 +67,7 @@ const annotations = { mongo: {
72
67
  if ((0, __atscript_core.isPrimitive)(def) && !["string", "number"].includes(def.config.type)) wrongType = true;
73
68
  } else wrongType = true;
74
69
  if (wrongType) errors.push({
75
- message: `[mongo] _id must be of type string, number or mongo.objectId`,
70
+ message: `[db.mongo] _id must be of type string, number or mongo.objectId`,
76
71
  severity: 1,
77
72
  range: _id.token("identifier").range
78
73
  });
@@ -98,43 +93,19 @@ const annotations = { mongo: {
98
93
  description: "On/Off the automatic index creation"
99
94
  }
100
95
  }),
101
- index: {
102
- plain: new __atscript_core.AnnotationSpec({
103
- description: "Defines a **standard MongoDB index** on a field.\n\n- Improves query performance on indexed fields.\n- Can be used for **single-field** or **compound** indexes.\n\n**Example:**\n```atscript\n@mongo.index.plain \"departmentIndex\"\ndepartment: string\n```\n",
104
- multiple: true,
105
- nodeType: ["prop"],
106
- argument: {
107
- optional: true,
108
- name: "indexName",
109
- type: "string",
110
- description: "The **name of the index** (optional). If omitted, property name is used."
111
- }
112
- }),
113
- unique: new __atscript_core.AnnotationSpec({
114
- description: "Creates a **unique index** on a field to ensure no duplicate values exist.\n\n- Enforces uniqueness at the database level.\n- Automatically prevents duplicate entries.\n- Typically used for **emails, usernames, and IDs**.\n\n**Example:**\n```atscript\n@mongo.index.unique \"uniqueEmailIndex\"\nemail: string.email\n```\n",
115
- multiple: true,
116
- nodeType: ["prop"],
117
- argument: {
118
- optional: true,
119
- name: "indexName",
120
- type: "string",
121
- description: "The **name of the unique index** (optional). If omitted, property name is used."
122
- }
123
- }),
124
- text: new __atscript_core.AnnotationSpec({
125
- description: "Creates a **legacy MongoDB text index** for full-text search.\n\n**⚠ WARNING:** *Text indexes slow down database operations. Use `@mongo.defineTextSearch` instead for better performance.*\n\n- Allows **basic full-text search** on a field.\n- Does **not support fuzzy matching or ranking**.\n- **Replaced by MongoDB Atlas Search Indexes (`@mongo.searchIndex.text`).**\n\n**Example:**\n```atscript\n@mongo.index.text 5\nbio: string\n```\n",
126
- nodeType: ["prop"],
127
- argument: {
128
- optional: true,
129
- name: "weight",
130
- type: "number",
131
- description: "Field importance in search results (higher = more relevant). Defaults to `1`."
132
- }
133
- })
134
- },
96
+ index: { text: new __atscript_core.AnnotationSpec({
97
+ description: "Creates a **legacy MongoDB text index** for full-text search with optional **weight** specification.\n\nUse this when you need per-field weight control. For simple full-text indexing without weights, use the generic `@db.index.fulltext` instead.\n\n**Example:**\n```atscript\n@db.mongo.index.text 5\nbio: string\n```\n",
98
+ nodeType: ["prop"],
99
+ argument: {
100
+ optional: true,
101
+ name: "weight",
102
+ type: "number",
103
+ description: "Field importance in search results (higher = more relevant). Defaults to `1`."
104
+ }
105
+ }) },
135
106
  search: {
136
107
  dynamic: new __atscript_core.AnnotationSpec({
137
- description: "Creates a **dynamic MongoDB Search Index** that applies to the entire collection.\n\n- **Indexes all text fields automatically** (no need to specify fields).\n- Supports **language analyzers** for text tokenization.\n- Enables **fuzzy search** (typo tolerance) if needed.\n\n**Example:**\n```atscript\n@mongo.search.dynamic \"lucene.english\", 1\nexport interface MongoCollection {}\n```\n",
108
+ description: "Creates a **dynamic MongoDB Search Index** that applies to the entire collection.\n\n- **Indexes all text fields automatically** (no need to specify fields).\n- Supports **language analyzers** for text tokenization.\n- Enables **fuzzy search** (typo tolerance) if needed.\n\n**Example:**\n```atscript\n@db.mongo.search.dynamic \"lucene.english\", 1\nexport interface MongoCollection {}\n```\n",
138
109
  nodeType: ["interface"],
139
110
  multiple: false,
140
111
  argument: [{
@@ -151,7 +122,7 @@ const annotations = { mongo: {
151
122
  }]
152
123
  }),
153
124
  static: new __atscript_core.AnnotationSpec({
154
- description: "Defines a **MongoDB Atlas Search Index** for the collection. The props can refer to this index using `@mongo.search.text` annotation.\n\n- **Creates a named search index** for full-text search.\n- **Specify analyzers and fuzzy search** behavior at the index level.\n- **Fields must explicitly use `@mongo.useTextSearch`** to be included in this search index.\n\n**Example:**\n```atscript\n@mongo.search.static \"lucene.english\", 1, \"mySearchIndex\"\nexport interface MongoCollection {}\n```\n",
125
+ description: "Defines a **MongoDB Atlas Search Index** for the collection. The props can refer to this index using `@db.mongo.search.text` annotation.\n\n- **Creates a named search index** for full-text search.\n- **Specify analyzers and fuzzy search** behavior at the index level.\n- **Fields must explicitly use `@db.mongo.search.text`** to be included in this search index.\n\n**Example:**\n```atscript\n@db.mongo.search.static \"lucene.english\", 1, \"mySearchIndex\"\nexport interface MongoCollection {}\n```\n",
155
126
  nodeType: ["interface"],
156
127
  multiple: true,
157
128
  argument: [
@@ -172,12 +143,12 @@ const annotations = { mongo: {
172
143
  optional: true,
173
144
  name: "indexName",
174
145
  type: "string",
175
- description: "The name of the search index. Fields must reference this name using `@mongo.search.text`. If not set, defaults to `\"DEFAULT\"`."
146
+ description: "The name of the search index. Fields must reference this name using `@db.mongo.search.text`. If not set, defaults to `\"DEFAULT\"`."
176
147
  }
177
148
  ]
178
149
  }),
179
150
  text: new __atscript_core.AnnotationSpec({
180
- description: "Marks a field to be **included in a MongoDB Atlas Search Index** defined by `@mongo.search.static`.\n\n- **The field has to reference an existing search index name**.\n- If index name is not defined, a new search index with default attributes will be created.\n\n**Example:**\n```atscript\n@mongo.search.text \"lucene.english\", \"mySearchIndex\"\nfirstName: string\n```\n",
151
+ description: "Marks a field to be **included in a MongoDB Atlas Search Index** defined by `@db.mongo.search.static`.\n\n- **The field has to reference an existing search index name**.\n- If index name is not defined, a new search index with default attributes will be created.\n\n**Example:**\n```atscript\n@db.mongo.search.text \"lucene.english\", \"mySearchIndex\"\nfirstName: string\n```\n",
181
152
  nodeType: ["prop"],
182
153
  multiple: true,
183
154
  argument: [{
@@ -190,11 +161,11 @@ const annotations = { mongo: {
190
161
  optional: true,
191
162
  name: "indexName",
192
163
  type: "string",
193
- description: "The **name of the search index** defined in `@mongo.defineTextSearch`. This links the field to the correct index. If not set, defaults to `\"DEFAULT\"`."
164
+ description: "The **name of the search index** defined in `@db.mongo.search.static`. This links the field to the correct index. If not set, defaults to `\"DEFAULT\"`."
194
165
  }]
195
166
  }),
196
167
  vector: new __atscript_core.AnnotationSpec({
197
- description: "Creates a **MongoDB Vector Search Index** for **semantic search, embeddings, and AI-powered search**.\n\n- Each field that stores vector embeddings **must define its own vector index**.\n- Supports **cosine similarity, Euclidean distance, and dot product similarity**.\n- Vector fields must be an **array of numbers**.\n\n**Example:**\n```atscript\n@mongo.search.vector 512, \"cosine\"\nembedding: mongo.vector\n```\n",
168
+ description: "Creates a **MongoDB Vector Search Index** for **semantic search, embeddings, and AI-powered search**.\n\n- Each field that stores vector embeddings **must define its own vector index**.\n- Supports **cosine similarity, Euclidean distance, and dot product similarity**.\n- Vector fields must be an **array of numbers**.\n\n**Example:**\n```atscript\n@db.mongo.search.vector 512, \"cosine\"\nembedding: mongo.vector\n```\n",
198
169
  nodeType: ["prop"],
199
170
  multiple: false,
200
171
  argument: [
@@ -232,7 +203,7 @@ const annotations = { mongo: {
232
203
  ]
233
204
  }),
234
205
  filter: new __atscript_core.AnnotationSpec({
235
- description: "Assigns a field as a **filter field** for a **MongoDB Vector Search Index**.\n\n- The assigned field **must be indexed** for efficient filtering.\n- Filters allow vector search queries to return results **only within a specific category, user group, or tag**.\n- The vector index must be defined using `@mongo.search.vector`.\n\n**Example:**\n```atscript\n@mongo.search.vector 512, \"cosine\"\nembedding: number[]\n\n@mongo.search.filter \"embedding\"\ncategory: string\n```\n",
206
+ description: "Assigns a field as a **filter field** for a **MongoDB Vector Search Index**.\n\n- The assigned field **must be indexed** for efficient filtering.\n- Filters allow vector search queries to return results **only within a specific category, user group, or tag**.\n- The vector index must be defined using `@db.mongo.search.vector`.\n\n**Example:**\n```atscript\n@db.mongo.search.vector 512, \"cosine\"\nembedding: number[]\n\n@db.mongo.search.filter \"embedding\"\ncategory: string\n```\n",
236
207
  nodeType: ["prop"],
237
208
  multiple: true,
238
209
  argument: [{
@@ -244,7 +215,7 @@ const annotations = { mongo: {
244
215
  })
245
216
  },
246
217
  patch: { strategy: new __atscript_core.AnnotationSpec({
247
- description: "Defines the **patching strategy** for updating MongoDB documents.\n\n- **\"replace\"** → The field or object will be **fully replaced**.\n- **\"merge\"** → The field or object will be **merged recursively** (applies only to objects, not arrays).\n\n**Example:**\n```atscript\n@mongo.patch.strategy \"merge\"\nsettings: {\n notifications: boolean\n preferences: {\n theme: string\n }\n}\n```\n",
218
+ description: "Defines the **patching strategy** for updating MongoDB documents.\n\n- **\"replace\"** → The field or object will be **fully replaced**.\n- **\"merge\"** → The field or object will be **merged recursively** (applies only to objects, not arrays).\n\n**Example:**\n```atscript\n@db.mongo.patch.strategy \"merge\"\nsettings: {\n notifications: boolean\n preferences: {\n theme: string\n }\n}\n```\n",
248
219
  nodeType: ["prop"],
249
220
  multiple: false,
250
221
  argument: {
@@ -264,7 +235,7 @@ const annotations = { mongo: {
264
235
  if (!(0, __atscript_core.isStructure)(def) && !(0, __atscript_core.isInterface)(def) && !(0, __atscript_core.isArray)(def)) wrongType = true;
265
236
  } else if (!(0, __atscript_core.isStructure)(definition) && !(0, __atscript_core.isInterface)(definition) && !(0, __atscript_core.isArray)(definition)) wrongType = true;
266
237
  if (wrongType) errors.push({
267
- message: `[mongo] type of object or array expected when using @mongo.patch.strategy`,
238
+ message: `[db.mongo] type of object or array expected when using @db.mongo.patch.strategy`,
268
239
  severity: 1,
269
240
  range: token.range
270
241
  });
@@ -272,7 +243,7 @@ const annotations = { mongo: {
272
243
  }
273
244
  }) },
274
245
  array: { uniqueItems: new __atscript_core.AnnotationSpec({
275
- description: "Marks an **array field** as containing *globally unique items* when handling **patch `$insert` operations**.\n\n- Forces the patcher to use **set-semantics** (`$setUnion`) instead of a plain append, so duplicates are silently skipped.\n- Has **no effect** on `$replace`, `$update`, or `$remove`.\n- If the arrays element type already defines one or more `@meta.isKey` properties, *uniqueness is implied* and this annotation is unnecessary (but harmless).\n\n**Example:**\n```atscript\n@mongo.array.uniqueItems\ntags: string[]\n\n// Later in a patch payload …\n{\n $insert: {\n tags: [\"mongo\", \"mongo\"] // second \"mongo\" is ignored\n }\n}\n```\n",
246
+ description: "Marks an **array field** as containing *globally unique items* when handling **patch `$insert` operations**.\n\n- Forces the patcher to use **set-semantics** (`$setUnion`) instead of a plain append, so duplicates are silently skipped.\n- Has **no effect** on `$replace`, `$update`, or `$remove`.\n- If the array's element type already defines one or more `@expect.array.key` properties, *uniqueness is implied* and this annotation is unnecessary (but harmless).\n\n**Example:**\n```atscript\n@db.mongo.array.uniqueItems\ntags: string[]\n\n// Later in a patch payload …\n{\n $insert: {\n tags: [\"mongo\", \"mongo\"] // second \"mongo\" is ignored\n }\n}\n```\n",
276
247
  nodeType: ["prop"],
277
248
  multiple: false,
278
249
  validate(token, args, doc) {
@@ -286,14 +257,14 @@ const annotations = { mongo: {
286
257
  if (!(0, __atscript_core.isArray)(def)) wrongType = true;
287
258
  } else if (!(0, __atscript_core.isArray)(definition)) wrongType = true;
288
259
  if (wrongType) errors.push({
289
- message: `[mongo] type of array expected when using @mongo.array.uniqueItems`,
260
+ message: `[db.mongo] type of array expected when using @db.mongo.array.uniqueItems`,
290
261
  severity: 1,
291
262
  range: token.range
292
263
  });
293
264
  return errors;
294
265
  }
295
266
  }) }
296
- } };
267
+ };
297
268
 
298
269
  //#endregion
299
270
  //#region packages/mongo/src/plugin/primitives.ts
@@ -301,7 +272,7 @@ const primitives = { mongo: { extensions: {
301
272
  objectId: {
302
273
  type: "string",
303
274
  documentation: "Represents a **MongoDB ObjectId**.\n\n- Stored as a **string** but can be converted to an ObjectId at runtime.\n- Useful for handling `_id` fields and queries that require ObjectId conversion.\n- Automatically converts string `_id` values into **MongoDB ObjectId** when needed.\n\n**Example:**\n```atscript\nuserId: mongo.objectId\n```\n",
304
- expect: { pattern: /^[a-fA-F0-9]{24}$/ }
275
+ annotations: { "expect.pattern": { pattern: "^[a-fA-F0-9]{24}$" } }
305
276
  },
306
277
  vector: {
307
278
  type: {
@@ -319,7 +290,7 @@ const MongoPlugin = () => ({
319
290
  config() {
320
291
  return {
321
292
  primitives,
322
- annotations
293
+ annotations: { db: { mongo: annotations } }
323
294
  };
324
295
  }
325
296
  });
@@ -330,7 +301,7 @@ const validateMongoIdPlugin = (ctx, def, value) => {
330
301
  if (ctx.path === "_id" && def.type.tags.has("objectId")) return ctx.validateAnnotatedType(def, value instanceof mongodb.ObjectId ? value.toString() : value);
331
302
  };
332
303
  const validateMongoUniqueArrayItemsPlugin = (ctx, def, value) => {
333
- if (def.metadata.has("mongo.array.uniqueItems") && def.type.kind === "array") {
304
+ if (def.metadata.has("db.mongo.array.uniqueItems") && def.type.kind === "array") {
334
305
  if (Array.isArray(value)) {
335
306
  const separator = "▼↩";
336
307
  const seen = new Set();
@@ -364,7 +335,7 @@ else obj[key] = value;
364
335
  }
365
336
  var CollectionPatcher = class CollectionPatcher {
366
337
  /**
367
- * Extract a set of *key properties* (annotated with `@meta.isKey`) from an
338
+ * Extract a set of *key properties* (annotated with `@expect.array.key`) from an
368
339
  * array‐of‐objects type definition. These keys uniquely identify an element
369
340
  * inside the array and are later used for `$update`, `$remove` and `$upsert`.
370
341
  *
@@ -374,7 +345,7 @@ var CollectionPatcher = class CollectionPatcher {
374
345
  if (def.type.of.type.kind === "object") {
375
346
  const objType = def.type.of.type;
376
347
  const keyProps = new Set();
377
- for (const [key, val] of objType.props.entries()) if (val.metadata.get("meta.isKey")) keyProps.add(key);
348
+ for (const [key, val] of objType.props.entries()) if (val.metadata.get("expect.array.key")) keyProps.add(key);
378
349
  return keyProps;
379
350
  }
380
351
  return new Set();
@@ -383,7 +354,7 @@ var CollectionPatcher = class CollectionPatcher {
383
354
  * Build a runtime *Validator* that understands the extended patch payload.
384
355
  *
385
356
  * * Adds per‑array *patch* wrappers (the `$replace`, `$insert`, … fields).
386
- * * Honors `mongo.patch.strategy === "merge"` metadata.
357
+ * * Honors `db.mongo.patch.strategy === "merge"` metadata.
387
358
  *
388
359
  * @param collection Target collection wrapper
389
360
  * @returns Atscript Validator
@@ -396,12 +367,12 @@ var CollectionPatcher = class CollectionPatcher {
396
367
  for (const [prop, type] of def.type.props.entries()) obj.prop(prop, (0, __atscript_typescript_utils.defineAnnotatedType)().refTo(type).copyMetadata(type.metadata).optional(prop !== "_id").$type);
397
368
  return obj.$type;
398
369
  }
399
- if (def.type.kind === "array" && collection.flatMap.get(path)?.metadata.get("mongo.__topLevelArray") && !def.metadata.has("mongo.__patchArrayValue")) {
370
+ if (def.type.kind === "array" && collection.flatMap.get(path)?.metadata.get("db.mongo.__topLevelArray") && !def.metadata.has("db.mongo.__patchArrayValue")) {
400
371
  const defArray = def;
401
- const mergeStrategy = defArray.metadata.get("mongo.patch.strategy") === "merge";
372
+ const mergeStrategy = defArray.metadata.get("db.mongo.patch.strategy") === "merge";
402
373
  function getPatchType() {
403
374
  const isPrimitive$1 = (0, __atscript_typescript_utils.isAnnotatedTypeOfPrimitive)(defArray.type.of);
404
- if (isPrimitive$1) return (0, __atscript_typescript_utils.defineAnnotatedType)().refTo(def).copyMetadata(def.metadata).annotate("mongo.__patchArrayValue").optional().$type;
375
+ if (isPrimitive$1) return (0, __atscript_typescript_utils.defineAnnotatedType)().refTo(def).copyMetadata(def.metadata).annotate("db.mongo.__patchArrayValue").optional().$type;
405
376
  if (defArray.type.of.type.kind === "object") {
406
377
  const objType = defArray.type.of.type;
407
378
  const t = (0, __atscript_typescript_utils.defineAnnotatedType)("object").copyMetadata(defArray.type.of.metadata);
@@ -409,17 +380,17 @@ var CollectionPatcher = class CollectionPatcher {
409
380
  for (const [key, val] of objType.props.entries()) if (keyProps.size > 0) if (keyProps.has(key)) t.prop(key, (0, __atscript_typescript_utils.defineAnnotatedType)().refTo(val).copyMetadata(def.metadata).$type);
410
381
  else t.prop(key, (0, __atscript_typescript_utils.defineAnnotatedType)().refTo(val).copyMetadata(def.metadata).optional().$type);
411
382
  else t.prop(key, (0, __atscript_typescript_utils.defineAnnotatedType)().refTo(val).copyMetadata(def.metadata).optional(!!val.optional).$type);
412
- return (0, __atscript_typescript_utils.defineAnnotatedType)("array").of(t.$type).copyMetadata(def.metadata).annotate("mongo.__patchArrayValue").optional().$type;
383
+ return (0, __atscript_typescript_utils.defineAnnotatedType)("array").of(t.$type).copyMetadata(def.metadata).annotate("db.mongo.__patchArrayValue").optional().$type;
413
384
  }
414
385
  return undefined;
415
386
  }
416
- const fullType = (0, __atscript_typescript_utils.defineAnnotatedType)().refTo(def).copyMetadata(def.metadata).annotate("mongo.__patchArrayValue").optional().$type;
387
+ const fullType = (0, __atscript_typescript_utils.defineAnnotatedType)().refTo(def).copyMetadata(def.metadata).annotate("db.mongo.__patchArrayValue").optional().$type;
417
388
  const patchType = getPatchType();
418
389
  return patchType ? (0, __atscript_typescript_utils.defineAnnotatedType)("object").prop("$replace", fullType).prop("$insert", fullType).prop("$upsert", fullType).prop("$update", mergeStrategy ? patchType : fullType).prop("$remove", patchType).optional().$type : (0, __atscript_typescript_utils.defineAnnotatedType)("object").prop("$replace", fullType).prop("$insert", fullType).optional().$type;
419
390
  }
420
391
  return def;
421
392
  },
422
- partial: (def, path) => path !== "" && def.metadata.get("mongo.patch.strategy") === "merge"
393
+ partial: (def, path) => path !== "" && def.metadata.get("db.mongo.patch.strategy") === "merge"
423
394
  });
424
395
  }
425
396
  /**
@@ -470,9 +441,9 @@ else t.prop(key, (0, __atscript_typescript_utils.defineAnnotatedType)().refTo(va
470
441
  for (const [_key, value] of Object.entries(payload)) {
471
442
  const key = evalKey(_key);
472
443
  const flatType = this.collection.flatMap.get(key);
473
- const topLevelArray = flatType?.metadata?.get("mongo.__topLevelArray");
444
+ const topLevelArray = flatType?.metadata?.get("db.mongo.__topLevelArray");
474
445
  if (typeof value === "object" && topLevelArray) this.parseArrayPatch(key, value);
475
- else if (typeof value === "object" && this.collection.flatMap.get(key)?.metadata?.get("mongo.patch.strategy") === "merge") this.flattenPayload(value, key);
446
+ else if (typeof value === "object" && this.collection.flatMap.get(key)?.metadata?.get("db.mongo.patch.strategy") === "merge") this.flattenPayload(value, key);
476
447
  else if (key !== "_id") this._set(key, value);
477
448
  }
478
449
  return this.updatePipeline;
@@ -526,7 +497,7 @@ else if (key !== "_id") this._set(key, value);
526
497
  * - unique / keyed → delegate to _upsert (insert-or-update)
527
498
  */ _insert(key, input, keyProps) {
528
499
  if (!input?.length) return;
529
- const uniqueItems = this.collection.flatMap.get(key)?.metadata?.has("mongo.array.uniqueItems");
500
+ const uniqueItems = this.collection.flatMap.get(key)?.metadata?.has("db.mongo.array.uniqueItems");
530
501
  if (uniqueItems || keyProps.size > 0) this._upsert(key, input, keyProps);
531
502
  else this._set(key, { $concatArrays: [{ $ifNull: [`$${key}`, []] }, input] });
532
503
  }
@@ -564,7 +535,7 @@ else this._set(key, { $concatArrays: [{ $ifNull: [`$${key}`, []] }, input] });
564
535
  */ _update(key, input, keyProps) {
565
536
  if (!input?.length) return;
566
537
  if (keyProps.size > 0) {
567
- const mergeStrategy = this.collection.flatMap.get(key)?.metadata?.get("mongo.patch.strategy") === "merge";
538
+ const mergeStrategy = this.collection.flatMap.get(key)?.metadata?.get("db.mongo.patch.strategy") === "merge";
568
539
  const keys = [...keyProps];
569
540
  this._set(key, { $reduce: {
570
541
  input,
@@ -773,13 +744,13 @@ else {
773
744
  }
774
745
  _prepareIndexesForCollection() {
775
746
  const typeMeta = this.type.metadata;
776
- const dynamicText = typeMeta.get("mongo.search.dynamic");
747
+ const dynamicText = typeMeta.get("db.mongo.search.dynamic");
777
748
  if (dynamicText) this._setSearchIndex("dynamic_text", "_", {
778
749
  mappings: { dynamic: true },
779
750
  analyzer: dynamicText.analyzer,
780
751
  text: { fuzzy: { maxEdits: dynamicText.fuzzy || 0 } }
781
752
  });
782
- for (const textSearch of typeMeta.get("mongo.search.static") || []) this._setSearchIndex("search_text", textSearch.indexName, {
753
+ for (const textSearch of typeMeta.get("db.mongo.search.static") || []) this._setSearchIndex("search_text", textSearch.indexName, {
783
754
  mappings: { fields: {} },
784
755
  analyzer: textSearch.analyzer,
785
756
  text: { fuzzy: { maxEdits: textSearch.fuzzy || 0 } }
@@ -802,25 +773,35 @@ else {
802
773
  }
803
774
  }
804
775
  _prepareIndexesForField(fieldName, metadata) {
805
- for (const index of metadata.get("mongo.index.plain") || []) this._addIndexField("plain", index === true ? fieldName : index, fieldName);
806
- for (const index of metadata.get("mongo.index.unique") || []) this._addIndexField("unique", index === true ? fieldName : index, fieldName);
807
- const textWeight = metadata.get("mongo.index.text");
776
+ for (const index of metadata.get("db.index.plain") || []) {
777
+ const name = index === true ? fieldName : index.name || fieldName;
778
+ this._addIndexField("plain", name, fieldName);
779
+ }
780
+ for (const index of metadata.get("db.index.unique") || []) {
781
+ const name = index === true ? fieldName : index.name || fieldName;
782
+ this._addIndexField("unique", name, fieldName);
783
+ }
784
+ for (const index of metadata.get("db.index.fulltext") || []) {
785
+ const name = index === true ? "" : index.name || "";
786
+ this._addIndexField("text", name, fieldName, 1);
787
+ }
788
+ const textWeight = metadata.get("db.mongo.index.text");
808
789
  if (textWeight) this._addIndexField("text", "", fieldName, textWeight === true ? 1 : textWeight);
809
- for (const index of metadata.get("mongo.search.text") || []) this._addFieldToSearchIndex("search_text", index.indexName, fieldName, index.analyzer);
810
- const vectorIndex = metadata.get("mongo.search.vector");
790
+ for (const index of metadata.get("db.mongo.search.text") || []) this._addFieldToSearchIndex("search_text", index.indexName, fieldName, index.analyzer);
791
+ const vectorIndex = metadata.get("db.mongo.search.vector");
811
792
  if (vectorIndex) this._setSearchIndex("vector", vectorIndex.indexName || fieldName, { fields: [{
812
793
  type: "vector",
813
794
  path: fieldName,
814
795
  similarity: vectorIndex.similarity || "dotProduct",
815
796
  numDimensions: vectorIndex.dimensions
816
797
  }] });
817
- for (const index of metadata.get("mongo.search.filter") || []) this._vectorFilters.set(indexKey("vector", index.indexName), fieldName);
798
+ for (const index of metadata.get("db.mongo.search.filter") || []) this._vectorFilters.set(indexKey("vector", index.indexName), fieldName);
818
799
  }
819
800
  _flatten() {
820
801
  if (!this._flatMap) {
821
802
  this._prepareIndexesForCollection();
822
803
  this._flatMap = (0, __atscript_typescript_utils.flattenAnnotatedType)(this.type, {
823
- topLevelArrayTag: "mongo.__topLevelArray",
804
+ topLevelArrayTag: "db.mongo.__topLevelArray",
824
805
  excludePhantomTypes: true,
825
806
  onField: (path, _type, metadata) => this._prepareIndexesForField(path, metadata)
826
807
  });
@@ -1032,8 +1013,8 @@ else if (this.idType !== "objectId") throw new Error("Missing \"_id\" field");
1032
1013
  this._vectorFilters = new Map();
1033
1014
  this._uniqueProps = new Set();
1034
1015
  if (!(0, __atscript_typescript_utils.isAnnotatedType)(_type)) throw new Error("Atscript Annotated Type expected");
1035
- const name = _type.metadata.get("mongo.collection");
1036
- if (!name) throw new Error("@mongo.collection annotation expected with collection name");
1016
+ const name = _type.metadata.get("db.table");
1017
+ if (!name) throw new Error("@db.table annotation expected with collection name");
1037
1018
  if (_type.type.kind !== "object") throw new Error("Mongo collection must be an object type");
1038
1019
  this.name = name;
1039
1020
  this.collection = asMongo.db.collection(name);