@atscript/db 0.1.38 → 0.1.40

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.
Files changed (64) hide show
  1. package/README.md +42 -303
  2. package/dist/agg.cjs +8 -3
  3. package/dist/agg.d.cts +7 -0
  4. package/dist/agg.d.mts +7 -0
  5. package/dist/agg.mjs +7 -3
  6. package/dist/control-DRgryKeg.cjs +14 -0
  7. package/dist/{control_as-bjmwe24C.mjs → control-IANbnfjG.mjs} +6 -18
  8. package/dist/db-readable-BQQzfguJ.d.cts +1249 -0
  9. package/dist/db-readable-Bbr4CjMb.d.mts +1249 -0
  10. package/dist/db-space-BUrQ5BFm.d.mts +309 -0
  11. package/dist/db-space-Vxpcnyt5.d.cts +309 -0
  12. package/dist/db-validator-plugin-07kDiis2.d.cts +22 -0
  13. package/dist/db-validator-plugin-CiqsHTI_.d.mts +22 -0
  14. package/dist/db-view-BntnAmXO.cjs +3071 -0
  15. package/dist/db-view-ZsoN91-q.mjs +2970 -0
  16. package/dist/index.cjs +95 -2801
  17. package/dist/index.d.cts +137 -0
  18. package/dist/index.d.mts +137 -0
  19. package/dist/index.mjs +55 -2761
  20. package/dist/{nested-writer-BkqL7cp3.cjs → nested-writer-BDXsDMPP.cjs} +196 -150
  21. package/dist/{nested-writer-NEN51mnR.mjs → nested-writer-Dmm1gbZV.mjs} +118 -70
  22. package/dist/ops-BdRAFLKY.d.mts +67 -0
  23. package/dist/ops-DXJ4Zw0P.d.cts +67 -0
  24. package/dist/ops.cjs +123 -0
  25. package/dist/ops.d.cts +2 -0
  26. package/dist/ops.d.mts +2 -0
  27. package/dist/ops.mjs +112 -0
  28. package/dist/plugin.cjs +90 -109
  29. package/dist/plugin.d.cts +6 -0
  30. package/dist/plugin.d.mts +6 -0
  31. package/dist/plugin.mjs +29 -49
  32. package/dist/rel.cjs +20 -20
  33. package/dist/rel.d.cts +119 -0
  34. package/dist/rel.d.mts +119 -0
  35. package/dist/rel.mjs +4 -5
  36. package/dist/{relation-helpers-guFL_oRf.cjs → relation-helpers-BYvsE1tR.cjs} +26 -22
  37. package/dist/{relation-helpers-DyBIlQnB.mjs → relation-helpers-CLasawQq.mjs} +11 -6
  38. package/dist/{relation-loader-Dv7qXYq7.mjs → relation-loader-BEOTXNcq.mjs} +63 -43
  39. package/dist/{relation-loader-CpnDRf9k.cjs → relation-loader-CRC5LcqM.cjs} +74 -49
  40. package/dist/shared.cjs +13 -13
  41. package/dist/{shared.d.ts → shared.d.cts} +14 -13
  42. package/dist/shared.d.mts +71 -0
  43. package/dist/shared.mjs +2 -3
  44. package/dist/sync.cjs +300 -252
  45. package/dist/sync.d.cts +369 -0
  46. package/dist/sync.d.mts +369 -0
  47. package/dist/sync.mjs +284 -233
  48. package/dist/{validation-utils-DEoCMmEb.cjs → validation-utils-DVJDijnB.cjs} +141 -109
  49. package/dist/{validation-utils-DhR_mtKa.mjs → validation-utils-DhjIjP1-.mjs} +71 -37
  50. package/package.json +31 -30
  51. package/LICENSE +0 -21
  52. package/dist/agg-BJFJ3dFQ.mjs +0 -8
  53. package/dist/agg-DnUWAOK8.cjs +0 -14
  54. package/dist/agg.d.ts +0 -13
  55. package/dist/chunk-CrpGerW8.cjs +0 -31
  56. package/dist/control_as-BFPERAF_.cjs +0 -28
  57. package/dist/index.d.ts +0 -1706
  58. package/dist/logger-B7oxCfLQ.mjs +0 -12
  59. package/dist/logger-Dt2v_-wb.cjs +0 -18
  60. package/dist/plugin.d.ts +0 -5
  61. package/dist/rel.d.ts +0 -1305
  62. package/dist/relation-loader-D4mTw6yH.cjs +0 -4
  63. package/dist/relation-loader-Ggy1ujwR.mjs +0 -4
  64. package/dist/sync.d.ts +0 -1878
package/dist/plugin.cjs CHANGED
@@ -1,12 +1,12 @@
1
- "use strict";
2
- Object.defineProperty(exports, '__esModule', { value: true });
3
- const require_chunk = require('./chunk-CrpGerW8.cjs');
4
- const require_validation_utils = require('./validation-utils-DEoCMmEb.cjs');
5
- const __atscript_core = require_chunk.__toESM(require("@atscript/core"));
6
-
7
- //#region packages/db/src/plugin/annotations/agg.ts
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ const require_validation_utils = require("./validation-utils-DVJDijnB.cjs");
6
+ let _atscript_core = require("@atscript/core");
7
+ //#region src/plugin/annotations/agg.ts
8
8
  const dbAggAnnotations = { agg: {
9
- sum: new __atscript_core.AnnotationSpec({
9
+ sum: new _atscript_core.AnnotationSpec({
10
10
  description: "Declares a view field as SUM of a source column.",
11
11
  nodeType: ["prop"],
12
12
  argument: {
@@ -18,7 +18,7 @@ const dbAggAnnotations = { agg: {
18
18
  return require_validation_utils.validateFieldBaseType(token, doc, "@db.agg.sum", ["number", "decimal"]);
19
19
  }
20
20
  }),
21
- avg: new __atscript_core.AnnotationSpec({
21
+ avg: new _atscript_core.AnnotationSpec({
22
22
  description: "Declares a view field as AVG of a source column.",
23
23
  nodeType: ["prop"],
24
24
  argument: {
@@ -30,7 +30,7 @@ const dbAggAnnotations = { agg: {
30
30
  return require_validation_utils.validateFieldBaseType(token, doc, "@db.agg.avg", ["number", "decimal"]);
31
31
  }
32
32
  }),
33
- count: new __atscript_core.AnnotationSpec({
33
+ count: new _atscript_core.AnnotationSpec({
34
34
  description: "Declares a view field as COUNT. Without argument: COUNT(*). With field name argument: COUNT(field) (non-null count).",
35
35
  nodeType: ["prop"],
36
36
  argument: {
@@ -43,7 +43,7 @@ const dbAggAnnotations = { agg: {
43
43
  return require_validation_utils.validateFieldBaseType(token, doc, "@db.agg.count", ["number"]);
44
44
  }
45
45
  }),
46
- min: new __atscript_core.AnnotationSpec({
46
+ min: new _atscript_core.AnnotationSpec({
47
47
  description: "Declares a view field as MIN of a source column.",
48
48
  nodeType: ["prop"],
49
49
  argument: {
@@ -52,7 +52,7 @@ const dbAggAnnotations = { agg: {
52
52
  description: "Source column name."
53
53
  }
54
54
  }),
55
- max: new __atscript_core.AnnotationSpec({
55
+ max: new _atscript_core.AnnotationSpec({
56
56
  description: "Declares a view field as MAX of a source column.",
57
57
  nodeType: ["prop"],
58
58
  argument: {
@@ -62,11 +62,10 @@ const dbAggAnnotations = { agg: {
62
62
  }
63
63
  })
64
64
  } };
65
-
66
65
  //#endregion
67
- //#region packages/db/src/plugin/annotations/column.ts
66
+ //#region src/plugin/annotations/column.ts
68
67
  const dbColumnAnnotations = {
69
- patch: { strategy: new __atscript_core.AnnotationSpec({
68
+ patch: { strategy: new _atscript_core.AnnotationSpec({
70
69
  description: "Defines the **patching strategy** for updating nested objects.\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.patch.strategy \"merge\"\nsettings: {\n notifications: boolean\n preferences: {\n theme: string\n }\n}\n```\n",
71
70
  nodeType: ["prop"],
72
71
  multiple: false,
@@ -82,10 +81,10 @@ const dbColumnAnnotations = {
82
81
  const definition = field.getDefinition();
83
82
  if (!definition) return errors;
84
83
  let wrongType = false;
85
- if ((0, __atscript_core.isRef)(definition)) {
84
+ if ((0, _atscript_core.isRef)(definition)) {
86
85
  const def = doc.unwindType(definition.id, definition.chain)?.def;
87
- if (!(0, __atscript_core.isStructure)(def) && !(0, __atscript_core.isInterface)(def) && !(0, __atscript_core.isArray)(def)) wrongType = true;
88
- } else if (!(0, __atscript_core.isStructure)(definition) && !(0, __atscript_core.isInterface)(definition) && !(0, __atscript_core.isArray)(definition)) wrongType = true;
86
+ if (!(0, _atscript_core.isStructure)(def) && !(0, _atscript_core.isInterface)(def) && !(0, _atscript_core.isArray)(def)) wrongType = true;
87
+ } else if (!(0, _atscript_core.isStructure)(definition) && !(0, _atscript_core.isInterface)(definition) && !(0, _atscript_core.isArray)(definition)) wrongType = true;
89
88
  if (wrongType) errors.push({
90
89
  message: `@db.patch.strategy requires a field of type object or array`,
91
90
  severity: 1,
@@ -95,7 +94,7 @@ const dbColumnAnnotations = {
95
94
  }
96
95
  }) },
97
96
  column: {
98
- $self: new __atscript_core.AnnotationSpec({
97
+ $self: new _atscript_core.AnnotationSpec({
99
98
  description: "Overrides the physical column name in the database. For nested (flattened) fields, the parent prefix is still prepended automatically.\n\n**Example:**\n```atscript\n@db.column \"first_name\"\nfirstName: string\n// → physical column: first_name\n\n// Nested:\naddress: {\n @db.column \"zip_code\"\n zip: string\n}\n// → physical column: address__zip_code\n```\n",
100
99
  nodeType: ["prop"],
101
100
  argument: {
@@ -104,7 +103,7 @@ const dbColumnAnnotations = {
104
103
  description: "The column/field name (without parent prefix for nested fields)."
105
104
  }
106
105
  }),
107
- renamed: new __atscript_core.AnnotationSpec({
106
+ renamed: new _atscript_core.AnnotationSpec({
108
107
  description: "Specifies the previous local field name for column rename migration. The sync engine generates ALTER TABLE RENAME COLUMN instead of drop+add.\n\n**Example:**\n```atscript\n@db.column.renamed \"zip\"\npostalCode: string\n// Renames address__zip → address__postalCode\n```\n",
109
108
  nodeType: ["prop"],
110
109
  argument: {
@@ -113,7 +112,7 @@ const dbColumnAnnotations = {
113
112
  description: "The old local field name (parent prefix is reconstructed automatically)."
114
113
  }
115
114
  }),
116
- collate: new __atscript_core.AnnotationSpec({
115
+ collate: new _atscript_core.AnnotationSpec({
117
116
  description: "Portable collation for string comparison and sorting. Adapters map the generic value to their native collation.\n\n- **\"binary\"** — exact byte comparison (case-sensitive)\n- **\"nocase\"** — case-insensitive comparison\n- **\"unicode\"** — full Unicode-aware sorting\n\nFor adapter-specific collations, use `@db.<engine>.collate` instead.\n\n**Example:**\n```atscript\n@db.column.collate \"nocase\"\nusername: string\n```\n",
118
117
  nodeType: ["prop"],
119
118
  argument: {
@@ -130,7 +129,7 @@ const dbColumnAnnotations = {
130
129
  return require_validation_utils.validateFieldBaseType(token, doc, "@db.column.collate", "string");
131
130
  }
132
131
  }),
133
- precision: new __atscript_core.AnnotationSpec({
132
+ precision: new _atscript_core.AnnotationSpec({
134
133
  description: "Sets decimal precision and scale for database storage. Adapters map this to their native decimal type (e.g., `DECIMAL(10,2)` in SQL, ignored in MongoDB).\n\nFor `decimal` fields the runtime value is a string; for `number` fields this is a DB storage hint only.\n\n**Example:**\n```atscript\n@db.column.precision 10, 2\nprice: decimal\n```\n",
135
134
  nodeType: ["prop"],
136
135
  argument: [{
@@ -146,11 +145,11 @@ const dbColumnAnnotations = {
146
145
  return require_validation_utils.validateFieldBaseType(token, doc, "@db.column.precision", ["number", "decimal"]);
147
146
  }
148
147
  }),
149
- dimension: new __atscript_core.AnnotationSpec({
148
+ dimension: new _atscript_core.AnnotationSpec({
150
149
  description: "Marks a field as a dimension — groupable in aggregate queries ($groupBy). Dimension fields automatically receive a database index during schema sync.",
151
150
  nodeType: ["prop"]
152
151
  }),
153
- measure: new __atscript_core.AnnotationSpec({
152
+ measure: new _atscript_core.AnnotationSpec({
154
153
  description: "Marks a field as a measure — aggregatable in aggregate queries (sum, avg, count, min, max). Only valid on numeric or decimal fields.",
155
154
  nodeType: ["prop"],
156
155
  validate(token, _args, doc) {
@@ -159,7 +158,7 @@ const dbColumnAnnotations = {
159
158
  })
160
159
  },
161
160
  default: {
162
- $self: new __atscript_core.AnnotationSpec({
161
+ $self: new _atscript_core.AnnotationSpec({
163
162
  description: "Sets a static DB-level default value (used in DDL DEFAULT clause). For string fields the value is used as-is; for other types it is parsed as JSON.\n\n**Example:**\n```atscript\n@db.default \"active\"\nstatus: string\n```\n",
164
163
  nodeType: ["prop"],
165
164
  argument: {
@@ -168,7 +167,7 @@ const dbColumnAnnotations = {
168
167
  description: "Static default value. Strings used as-is; other types parsed via JSON.parse()."
169
168
  }
170
169
  }),
171
- increment: new __atscript_core.AnnotationSpec({
170
+ increment: new _atscript_core.AnnotationSpec({
172
171
  description: "Auto-incrementing integer default. Each adapter maps this to its native mechanism (e.g., `AUTO_INCREMENT` in MySQL, `INTEGER PRIMARY KEY` in SQLite, counter collection in MongoDB).\n\n**Example:**\n```atscript\n@db.default.increment\nid: number.int\n\n// With optional start value:\n@db.default.increment 1000\nid: number.int\n```\n",
173
172
  nodeType: ["prop"],
174
173
  argument: {
@@ -181,14 +180,14 @@ const dbColumnAnnotations = {
181
180
  return require_validation_utils.validateFieldBaseType(token, doc, "db.default.increment", "number");
182
181
  }
183
182
  }),
184
- uuid: new __atscript_core.AnnotationSpec({
183
+ uuid: new _atscript_core.AnnotationSpec({
185
184
  description: "UUID generation default. Each adapter maps this to its native mechanism (e.g., `DEFAULT (UUID())` in MySQL, `gen_random_uuid()` in PostgreSQL, app-level in SQLite).\n\n**Example:**\n```atscript\n@db.default.uuid\nid: string.uuid\n```\n",
186
185
  nodeType: ["prop"],
187
186
  validate(token, args, doc) {
188
187
  return require_validation_utils.validateFieldBaseType(token, doc, "db.default.uuid", "string");
189
188
  }
190
189
  }),
191
- now: new __atscript_core.AnnotationSpec({
190
+ now: new _atscript_core.AnnotationSpec({
192
191
  description: "Current timestamp default. Each adapter maps this to its native mechanism (e.g., `DEFAULT CURRENT_TIMESTAMP` in MySQL, `DEFAULT now()` in PostgreSQL).\n\n**Example:**\n```atscript\n@db.default.now\ncreatedAt: number.timestamp\n```\n",
193
192
  nodeType: ["prop"],
194
193
  validate(token, args, doc) {
@@ -196,16 +195,15 @@ const dbColumnAnnotations = {
196
195
  }
197
196
  })
198
197
  },
199
- json: new __atscript_core.AnnotationSpec({
198
+ json: new _atscript_core.AnnotationSpec({
200
199
  description: "Forces a field to be stored as a single JSON column instead of being flattened into separate columns. Use on nested object fields that should remain as JSON in the database.\n\n**Example:**\n```atscript\n@db.json\nmetadata: { key: string, value: string }\n```\n",
201
200
  nodeType: ["prop"],
202
201
  validate(token, _args, doc) {
203
202
  const errors = [];
204
- const field = token.parentNode;
205
- const definition = field.getDefinition();
206
- if (definition && (0, __atscript_core.isRef)(definition)) {
203
+ const definition = token.parentNode.getDefinition();
204
+ if (definition && (0, _atscript_core.isRef)(definition)) {
207
205
  const unwound = doc.unwindType(definition.id, definition.chain);
208
- if (unwound && (0, __atscript_core.isPrimitive)(unwound.def)) errors.push({
206
+ if (unwound && (0, _atscript_core.isPrimitive)(unwound.def)) errors.push({
209
207
  message: "@db.json on a primitive field has no effect — primitive fields are already stored as scalar columns",
210
208
  severity: 2,
211
209
  range: token.range
@@ -214,13 +212,12 @@ const dbColumnAnnotations = {
214
212
  return errors;
215
213
  }
216
214
  }),
217
- ignore: new __atscript_core.AnnotationSpec({
215
+ ignore: new _atscript_core.AnnotationSpec({
218
216
  description: "Excludes a field from the database schema. The field exists in the Atscript type but has no column in the DB.\n\n**Example:**\n```atscript\n@db.ignore\ndisplayName: string\n```\n",
219
217
  nodeType: ["prop"],
220
- validate(token, args, doc) {
218
+ validate(token, _args, _doc) {
221
219
  const errors = [];
222
- const field = token.parentNode;
223
- if (field.countAnnotations("meta.id") > 0) errors.push({
220
+ if (token.parentNode.countAnnotations("meta.id") > 0) errors.push({
224
221
  message: `@db.ignore cannot coexist with @meta.id — a field cannot be both a primary key and excluded from the database`,
225
222
  severity: 1,
226
223
  range: token.range
@@ -229,11 +226,10 @@ const dbColumnAnnotations = {
229
226
  }
230
227
  })
231
228
  };
232
-
233
229
  //#endregion
234
- //#region packages/db/src/plugin/annotations/index-ann.ts
230
+ //#region src/plugin/annotations/index-ann.ts
235
231
  const dbIndexAnnotations = { index: {
236
- plain: new __atscript_core.AnnotationSpec({
232
+ plain: new _atscript_core.AnnotationSpec({
237
233
  description: "Standard (non-unique) index for query performance. Fields sharing the same index name form a composite index.\n\n**Example:**\n```atscript\n@db.index.plain \"idx_timeline\", \"desc\"\ncreatedAt: number.timestamp\n```\n",
238
234
  nodeType: ["prop"],
239
235
  multiple: true,
@@ -251,7 +247,7 @@ const dbIndexAnnotations = { index: {
251
247
  description: "Sort direction. Defaults to \"asc\"."
252
248
  }]
253
249
  }),
254
- unique: new __atscript_core.AnnotationSpec({
250
+ unique: new _atscript_core.AnnotationSpec({
255
251
  description: "Unique index — ensures no two rows/documents have the same value(s). Fields sharing the same index name form a composite unique constraint.\n\n**Example:**\n```atscript\n@db.index.unique \"tenant_email\"\nemail: string.email\n```\n",
256
252
  nodeType: ["prop"],
257
253
  multiple: true,
@@ -263,7 +259,7 @@ const dbIndexAnnotations = { index: {
263
259
  description: "Index name / composite group name."
264
260
  }
265
261
  }),
266
- fulltext: new __atscript_core.AnnotationSpec({
262
+ fulltext: new _atscript_core.AnnotationSpec({
267
263
  description: "Full-text search index. Fields sharing the same index name form a composite full-text index.\n\n**Example:**\n```atscript\n@db.index.fulltext \"ft_content\"\ntitle: string\n\n@db.index.fulltext \"ft_content\", 5\nbio: string\n```\n",
268
264
  nodeType: ["prop"],
269
265
  multiple: true,
@@ -281,11 +277,10 @@ const dbIndexAnnotations = { index: {
281
277
  }]
282
278
  })
283
279
  } };
284
-
285
280
  //#endregion
286
- //#region packages/db/src/plugin/annotations/rel.ts
281
+ //#region src/plugin/annotations/rel.ts
287
282
  const dbRelAnnotations = { rel: {
288
- FK: new __atscript_core.AnnotationSpec({
283
+ FK: new _atscript_core.AnnotationSpec({
289
284
  description: "Declares a foreign key constraint on this field. The field must use a chain reference type (e.g., `User.id`) to specify the FK target.\n\n**Example:**\n```atscript\n@db.rel.FK\nauthorId: User.id\n\n// With alias (required when multiple FKs point to the same type)\n@db.rel.FK \"author\"\nauthorId: User.id\n```\n",
290
285
  nodeType: ["prop"],
291
286
  argument: {
@@ -310,7 +305,7 @@ const dbRelAnnotations = { rel: {
310
305
  range: token.range
311
306
  });
312
307
  const definition = field.getDefinition();
313
- if (!definition || !(0, __atscript_core.isRef)(definition) || !definition.hasChain) {
308
+ if (!definition || !(0, _atscript_core.isRef)(definition) || !definition.hasChain) {
314
309
  errors.push({
315
310
  message: `@db.rel.FK requires a chain reference type (e.g. User.id), got scalar type`,
316
311
  severity: 1,
@@ -324,9 +319,9 @@ const dbRelAnnotations = { rel: {
324
319
  const targetUnwound = doc.unwindType(refTypeName);
325
320
  if (targetUnwound) {
326
321
  const targetDef = targetUnwound.def;
327
- if ((0, __atscript_core.isInterface)(targetDef) || (0, __atscript_core.isStructure)(targetDef)) {
328
- const struct = (0, __atscript_core.isInterface)(targetDef) ? targetDef.getDefinition() : targetDef;
329
- if (struct && (0, __atscript_core.isStructure)(struct) && chainFields.length > 0) {
322
+ if ((0, _atscript_core.isInterface)(targetDef) || (0, _atscript_core.isStructure)(targetDef)) {
323
+ const struct = (0, _atscript_core.isInterface)(targetDef) ? targetDef.getDefinition() : targetDef;
324
+ if (struct && (0, _atscript_core.isStructure)(struct) && chainFields.length > 0) {
330
325
  const targetProp = struct.props.get(chainFields[0]);
331
326
  if (targetProp) {
332
327
  if (targetProp.countAnnotations("meta.id") === 0 && targetProp.countAnnotations("db.index.unique") === 0) errors.push({
@@ -335,14 +330,14 @@ const dbRelAnnotations = { rel: {
335
330
  range: token.range
336
331
  });
337
332
  const propDef = targetProp.getDefinition();
338
- if (propDef && (0, __atscript_core.isRef)(propDef)) {
333
+ if (propDef && (0, _atscript_core.isRef)(propDef)) {
339
334
  const propUnwound = targetUnwound.doc.unwindType(propDef.id, propDef.chain);
340
- if (propUnwound && !(0, __atscript_core.isPrimitive)(propUnwound.def)) errors.push({
335
+ if (propUnwound && !(0, _atscript_core.isPrimitive)(propUnwound.def)) errors.push({
341
336
  message: `Foreign key field must resolve to a scalar type (number, string, etc.), got '${propDef.id}'`,
342
337
  severity: 1,
343
338
  range: token.range
344
339
  });
345
- } else if (propDef && !(0, __atscript_core.isPrimitive)(propDef)) errors.push({
340
+ } else if (propDef && !(0, _atscript_core.isPrimitive)(propDef)) errors.push({
346
341
  message: `Foreign key field must resolve to a scalar type (number, string, etc.)`,
347
342
  severity: 1,
348
343
  range: token.range
@@ -358,7 +353,7 @@ const dbRelAnnotations = { rel: {
358
353
  for (const [, prop] of struct.props) {
359
354
  if (prop.countAnnotations("db.rel.FK") === 0) continue;
360
355
  const def = prop.getDefinition();
361
- if (!def || !(0, __atscript_core.isRef)(def)) continue;
356
+ if (!def || !(0, _atscript_core.isRef)(def)) continue;
362
357
  const r = def;
363
358
  if (!r.hasChain) continue;
364
359
  if (r.id === refTypeName) {
@@ -375,7 +370,7 @@ const dbRelAnnotations = { rel: {
375
370
  return errors;
376
371
  }
377
372
  }),
378
- to: new __atscript_core.AnnotationSpec({
373
+ to: new _atscript_core.AnnotationSpec({
379
374
  description: "Forward navigational property — the FK is on **this** interface. The compiler resolves the matching @db.rel.FK by target type or alias.\n\n**Example:**\n```atscript\n@db.rel.to\nauthor?: User\n\n// With alias\n@db.rel.to \"author\"\nauthor?: User\n```\n",
380
375
  nodeType: ["prop"],
381
376
  argument: {
@@ -404,7 +399,7 @@ const dbRelAnnotations = { rel: {
404
399
  const unwound = doc.unwindType(targetTypeName);
405
400
  if (unwound) {
406
401
  const targetDef = unwound.def;
407
- const targetNode = (0, __atscript_core.isInterface)(targetDef) ? targetDef : undefined;
402
+ const targetNode = (0, _atscript_core.isInterface)(targetDef) ? targetDef : void 0;
408
403
  if (!targetNode || targetNode.countAnnotations("db.table") === 0) errors.push({
409
404
  message: `@db.rel.to target '${targetTypeName}' is not a @db.table entity`,
410
405
  severity: 1,
@@ -424,9 +419,8 @@ const dbRelAnnotations = { rel: {
424
419
  if (name === fieldName) continue;
425
420
  if (prop.countAnnotations("db.rel.to") === 0) continue;
426
421
  const propAlias = require_validation_utils.getAnnotationAlias(prop, "db.rel.to");
427
- if ((alias || undefined) === (propAlias || undefined)) {
428
- const otherTarget = require_validation_utils.getNavTargetTypeName(prop);
429
- if (otherTarget === targetTypeName) {
422
+ if ((alias || void 0) === (propAlias || void 0)) {
423
+ if (require_validation_utils.getNavTargetTypeName(prop) === targetTypeName) {
430
424
  errors.push({
431
425
  message: `Duplicate @db.rel.to '${alias || targetTypeName}' — only one forward navigational property per alias`,
432
426
  severity: 1,
@@ -437,8 +431,7 @@ const dbRelAnnotations = { rel: {
437
431
  }
438
432
  }
439
433
  if (alias) {
440
- const matches = require_validation_utils.findFKFieldsPointingTo(doc, struct, targetTypeName, alias);
441
- if (matches.length === 0) errors.push({
434
+ if (require_validation_utils.findFKFieldsPointingTo(doc, struct, targetTypeName, alias).length === 0) errors.push({
442
435
  message: `No @db.rel.FK '${alias}' found on this interface`,
443
436
  severity: 1,
444
437
  range: token.range
@@ -450,7 +443,7 @@ const dbRelAnnotations = { rel: {
450
443
  severity: 1,
451
444
  range: token.range
452
445
  });
453
- else if (matches.length > 1) errors.push({
446
+ else if (matches.length > 1) errors.push({
454
447
  message: `Multiple @db.rel.FK fields point to '${targetTypeName}' — add alias to disambiguate`,
455
448
  severity: 1,
456
449
  range: token.range
@@ -460,7 +453,7 @@ else if (matches.length > 1) errors.push({
460
453
  return errors;
461
454
  }
462
455
  }),
463
- from: new __atscript_core.AnnotationSpec({
456
+ from: new _atscript_core.AnnotationSpec({
464
457
  description: "Inverse navigational property — the FK is on the **target** interface, pointing back to this one.\n\n**Example:**\n```atscript\n@db.rel.from\nposts: Post[]\n\n// With alias\n@db.rel.from \"original\"\ncomments: Comment[]\n```\n",
465
458
  nodeType: ["prop"],
466
459
  argument: {
@@ -490,7 +483,7 @@ else if (matches.length > 1) errors.push({
490
483
  if (!unwound) return errors;
491
484
  const targetDef = unwound.def;
492
485
  const targetDoc = unwound.doc;
493
- if (!(0, __atscript_core.isInterface)(targetDef) || targetDef.countAnnotations("db.table") === 0) {
486
+ if (!(0, _atscript_core.isInterface)(targetDef) || targetDef.countAnnotations("db.table") === 0) {
494
487
  errors.push({
495
488
  message: `@db.rel.from target '${targetTypeName}' is not a @db.table entity`,
496
489
  severity: 1,
@@ -505,9 +498,8 @@ else if (matches.length > 1) errors.push({
505
498
  if (name === fieldName) continue;
506
499
  if (prop.countAnnotations("db.rel.from") === 0) continue;
507
500
  const propAlias = require_validation_utils.getAnnotationAlias(prop, "db.rel.from");
508
- if ((alias || undefined) === (propAlias || undefined)) {
509
- const otherTarget = require_validation_utils.getNavTargetTypeName(prop);
510
- if (otherTarget === targetTypeName) {
501
+ if ((alias || void 0) === (propAlias || void 0)) {
502
+ if (require_validation_utils.getNavTargetTypeName(prop) === targetTypeName) {
511
503
  errors.push({
512
504
  message: `Duplicate @db.rel.from '${alias || targetTypeName}' — only one inverse navigational property per alias`,
513
505
  severity: 1,
@@ -532,15 +524,13 @@ else if (matches.length > 1) errors.push({
532
524
  severity: 1,
533
525
  range: token.range
534
526
  });
535
- else if (matches.length > 1) errors.push({
527
+ else if (matches.length > 1) errors.push({
536
528
  message: `'${targetTypeName}' has multiple @db.rel.FK fields pointing to '${thisTypeName}' — add alias`,
537
529
  severity: 1,
538
530
  range: token.range
539
531
  });
540
- const fieldDef = field.getDefinition();
541
- if (!(0, __atscript_core.isArray)(fieldDef) && matches.length === 1) {
542
- const fkProp = matches[0].prop;
543
- if (fkProp.countAnnotations("db.index.unique") === 0) errors.push({
532
+ if (!(0, _atscript_core.isArray)(field.getDefinition()) && matches.length === 1) {
533
+ if (matches[0].prop.countAnnotations("db.index.unique") === 0) errors.push({
544
534
  message: `@db.rel.from '${field.id}' has singular type '${targetTypeName}' (1:1) but the FK on '${targetTypeName}' is not @db.index.unique — did you mean '${targetTypeName}[]' (1:N)?`,
545
535
  severity: 2,
546
536
  range: token.range
@@ -551,7 +541,7 @@ else if (matches.length > 1) errors.push({
551
541
  }),
552
542
  onDelete: require_validation_utils.refActionAnnotation("onDelete"),
553
543
  onUpdate: require_validation_utils.refActionAnnotation("onUpdate"),
554
- via: new __atscript_core.AnnotationSpec({
544
+ via: new _atscript_core.AnnotationSpec({
555
545
  description: "Declares a many-to-many navigational property through an explicit junction table. `@db.rel.via` is self-sufficient — no `@db.rel.from` pairing is needed.\n\n**Example:**\n```atscript\n@db.rel.via PostTag\ntags: Tag[]\n```\n",
556
546
  nodeType: ["prop"],
557
547
  argument: {
@@ -567,8 +557,7 @@ else if (matches.length > 1) errors.push({
567
557
  severity: 1,
568
558
  range: token.range
569
559
  });
570
- const definition = field.getDefinition();
571
- if (!(0, __atscript_core.isArray)(definition)) errors.push({
560
+ if (!(0, _atscript_core.isArray)(field.getDefinition())) errors.push({
572
561
  message: "@db.rel.via requires an array type (e.g. Tag[])",
573
562
  severity: 1,
574
563
  range: token.range
@@ -580,7 +569,7 @@ else if (matches.length > 1) errors.push({
580
569
  const junctionUnwound = doc.unwindType(junctionName);
581
570
  if (!junctionUnwound) return errors;
582
571
  const junctionDef = junctionUnwound.def;
583
- if (!(0, __atscript_core.isInterface)(junctionDef)) return errors;
572
+ if (!(0, _atscript_core.isInterface)(junctionDef)) return errors;
584
573
  const thisTypeName = require_validation_utils.getParentTypeName(token);
585
574
  const targetTypeName = require_validation_utils.getNavTargetTypeName(field);
586
575
  if (!thisTypeName || !targetTypeName) return errors;
@@ -590,7 +579,7 @@ else if (matches.length > 1) errors.push({
590
579
  severity: 1,
591
580
  range: args[0].range
592
581
  });
593
- else if (fksToThis.length > 1) errors.push({
582
+ else if (fksToThis.length > 1) errors.push({
594
583
  message: `Junction '${junctionName}' has multiple @db.rel.FK pointing to '${thisTypeName}' — not supported`,
595
584
  severity: 1,
596
585
  range: args[0].range
@@ -602,7 +591,7 @@ else if (fksToThis.length > 1) errors.push({
602
591
  severity: 1,
603
592
  range: args[0].range
604
593
  });
605
- else if (fksToTarget.length > 1) errors.push({
594
+ else if (fksToTarget.length > 1) errors.push({
606
595
  message: `Junction '${junctionName}' has multiple @db.rel.FK pointing to '${targetTypeName}' — not supported`,
607
596
  severity: 1,
608
597
  range: args[0].range
@@ -611,7 +600,7 @@ else if (fksToTarget.length > 1) errors.push({
611
600
  return errors;
612
601
  }
613
602
  }),
614
- filter: new __atscript_core.AnnotationSpec({
603
+ filter: new _atscript_core.AnnotationSpec({
615
604
  description: "Applies a filter to a navigational property, restricting which related records are loaded.\n\n**Example:**\n```atscript\n@db.rel.from\n@db.rel.filter `Post.published = true`\npublishedPosts: Post[]\n```\n",
616
605
  nodeType: ["prop"],
617
606
  argument: {
@@ -646,12 +635,11 @@ else if (fksToTarget.length > 1) errors.push({
646
635
  }
647
636
  })
648
637
  } };
649
-
650
638
  //#endregion
651
- //#region packages/db/src/plugin/annotations/search.ts
639
+ //#region src/plugin/annotations/search.ts
652
640
  const dbSearchAnnotations = { search: {
653
641
  vector: {
654
- $self: new __atscript_core.AnnotationSpec({
642
+ $self: new _atscript_core.AnnotationSpec({
655
643
  description: "Marks a field as a **vector embedding** for **similarity search**.\n\n- Each adapter maps this to its native vector type and index:\n - **MongoDB** → Atlas `$vectorSearch` index\n - **MySQL 9+** → `VECTOR(N)` column + `VEC_DISTANCE_*` functions\n - **PostgreSQL** → pgvector `vector(N)` column + distance operators\n - **SQLite** → JSON storage (no native vector support)\n\n**Example:**\n```atscript\n@db.search.vector 1536, \"cosine\"\nembedding: db.vector\n```\n",
656
644
  nodeType: ["prop"],
657
645
  multiple: false,
@@ -689,7 +677,7 @@ const dbSearchAnnotations = { search: {
689
677
  }
690
678
  ]
691
679
  }),
692
- threshold: new __atscript_core.AnnotationSpec({
680
+ threshold: new _atscript_core.AnnotationSpec({
693
681
  description: "Sets a **default minimum similarity threshold** for vector search queries on this field.\n\n- Results with a similarity score below this threshold are excluded.\n- Query-time `$threshold` control overrides this default.\n- Value range: `0` to `1` (where `1` means exact match).\n\n**Example:**\n```atscript\n@db.search.vector 1536, \"cosine\"\n@db.search.vector.threshold 0.7\nembedding: db.vector\n```\n",
694
682
  nodeType: ["prop"],
695
683
  multiple: false,
@@ -701,7 +689,7 @@ const dbSearchAnnotations = { search: {
701
689
  }
702
690
  })
703
691
  },
704
- filter: new __atscript_core.AnnotationSpec({
692
+ filter: new _atscript_core.AnnotationSpec({
705
693
  description: "Assigns a field as a **pre-filter** for a **vector search index**.\n\n- Filters allow vector search queries to return results only within a specific subset.\n- The referenced index must be defined using `@db.search.vector`.\n\n**Example:**\n```atscript\n@db.search.vector 1536, \"cosine\"\nembedding: db.vector\n\n@db.search.filter \"embedding\"\ncategory: string\n```\n",
706
694
  nodeType: ["prop"],
707
695
  multiple: true,
@@ -713,12 +701,11 @@ const dbSearchAnnotations = { search: {
713
701
  }
714
702
  })
715
703
  } };
716
-
717
704
  //#endregion
718
- //#region packages/db/src/plugin/annotations/table.ts
705
+ //#region src/plugin/annotations/table.ts
719
706
  const dbTableAnnotations = {
720
707
  table: {
721
- $self: new __atscript_core.AnnotationSpec({
708
+ $self: new _atscript_core.AnnotationSpec({
722
709
  description: "Marks an interface as a database-persisted entity (table in SQL, collection in MongoDB). If the name argument is omitted, the adapter derives the table name from the interface name.\n\n**Example:**\n```atscript\n@db.table \"users\"\nexport interface User { ... }\n```\n",
723
710
  nodeType: ["interface"],
724
711
  argument: {
@@ -738,7 +725,7 @@ const dbTableAnnotations = {
738
725
  return errors;
739
726
  }
740
727
  }),
741
- renamed: new __atscript_core.AnnotationSpec({
728
+ renamed: new _atscript_core.AnnotationSpec({
742
729
  description: "Specifies the previous table name for table rename migration. The sync engine generates ALTER TABLE RENAME instead of drop+create.\n\n**Example:**\n```atscript\n@db.table \"app_users\"\n@db.table.renamed \"users\"\nexport interface User { ... }\n```\n",
743
730
  nodeType: ["interface"],
744
731
  argument: {
@@ -748,8 +735,7 @@ const dbTableAnnotations = {
748
735
  },
749
736
  validate(token, _args, _doc) {
750
737
  const errors = [];
751
- const owner = token.parentNode;
752
- if (owner.countAnnotations("db.table") === 0) errors.push({
738
+ if (token.parentNode.countAnnotations("db.table") === 0) errors.push({
753
739
  message: "@db.table.renamed requires @db.table on the same interface",
754
740
  severity: 1,
755
741
  range: token.range
@@ -758,7 +744,7 @@ const dbTableAnnotations = {
758
744
  }
759
745
  })
760
746
  },
761
- schema: new __atscript_core.AnnotationSpec({
747
+ schema: new _atscript_core.AnnotationSpec({
762
748
  description: "Assigns the entity to a database schema/namespace.\n\n**Example:**\n```atscript\n@db.table \"users\"\n@db.schema \"auth\"\nexport interface User { ... }\n```\n",
763
749
  nodeType: ["interface"],
764
750
  argument: {
@@ -767,7 +753,7 @@ const dbTableAnnotations = {
767
753
  description: "Schema/namespace name."
768
754
  }
769
755
  }),
770
- sync: { method: new __atscript_core.AnnotationSpec({
756
+ sync: { method: new _atscript_core.AnnotationSpec({
771
757
  description: "Controls how the sync engine handles structural changes that cannot be applied via ALTER TABLE.\n\n- `\"recreate\"` — lossless: create temp table, copy data, drop old, rename.\n- `\"drop\"` — lossy: drop table entirely and create from scratch.\n\nWithout this annotation, structural changes fail with an error requiring manual intervention.\n\n**Example:**\n```atscript\n@db.sync.method \"drop\"\ninterface Logs { ... }\n```\n",
772
758
  nodeType: ["interface"],
773
759
  argument: {
@@ -778,11 +764,10 @@ const dbTableAnnotations = {
778
764
  }
779
765
  }) }
780
766
  };
781
-
782
767
  //#endregion
783
- //#region packages/db/src/plugin/annotations/view.ts
768
+ //#region src/plugin/annotations/view.ts
784
769
  const dbViewAnnotations = { view: {
785
- $self: new __atscript_core.AnnotationSpec({
770
+ $self: new _atscript_core.AnnotationSpec({
786
771
  description: "Marks an interface as a **database view**. Optionally takes a view name argument.\n\n**Example:**\n```atscript\n@db.view \"active_premium_users\"\n@db.view.for User\nexport interface ActivePremiumUser { ... }\n```\n",
787
772
  nodeType: ["interface"],
788
773
  argument: {
@@ -793,8 +778,7 @@ const dbViewAnnotations = { view: {
793
778
  },
794
779
  validate(token, _args, _doc) {
795
780
  const errors = [];
796
- const owner = token.parentNode;
797
- if (owner.countAnnotations("db.table") > 0) errors.push({
781
+ if (token.parentNode.countAnnotations("db.table") > 0) errors.push({
798
782
  message: "An interface cannot be both a @db.table and a @db.view",
799
783
  severity: 1,
800
784
  range: token.range
@@ -802,7 +786,7 @@ const dbViewAnnotations = { view: {
802
786
  return errors;
803
787
  }
804
788
  }),
805
- for: new __atscript_core.AnnotationSpec({
789
+ for: new _atscript_core.AnnotationSpec({
806
790
  description: "Specifies the entry/primary table for a computed view. Required for views that map fields via chain refs.\n\n**Example:**\n```atscript\n@db.view.for Order\n@db.view.filter `Order.status = 'active'`\nexport interface ActiveOrderDetails { ... }\n```\n",
807
791
  nodeType: ["interface"],
808
792
  argument: {
@@ -812,8 +796,7 @@ const dbViewAnnotations = { view: {
812
796
  },
813
797
  validate(token, args, doc) {
814
798
  const errors = [];
815
- const owner = token.parentNode;
816
- if (owner.countAnnotations("db.table") > 0) errors.push({
799
+ if (token.parentNode.countAnnotations("db.table") > 0) errors.push({
817
800
  message: "An interface cannot be both a @db.table and a @db.view",
818
801
  severity: 1,
819
802
  range: token.range
@@ -822,7 +805,7 @@ const dbViewAnnotations = { view: {
822
805
  return errors;
823
806
  }
824
807
  }),
825
- joins: new __atscript_core.AnnotationSpec({
808
+ joins: new _atscript_core.AnnotationSpec({
826
809
  description: "Declares an explicit join for a view. Use when no `@db.rel.*` path exists between the entry table and the target.\n\n**Example:**\n```atscript\n@db.view.for Order\n@db.view.joins Warehouse, `Warehouse.regionId = Order.regionId`\nexport interface OrderWarehouse { ... }\n```\n",
827
810
  nodeType: ["interface"],
828
811
  multiple: true,
@@ -864,7 +847,7 @@ const dbViewAnnotations = { view: {
864
847
  return errors;
865
848
  }
866
849
  }),
867
- filter: new __atscript_core.AnnotationSpec({
850
+ filter: new _atscript_core.AnnotationSpec({
868
851
  description: "WHERE clause for a view, filtering which rows are included.\n\n**Example:**\n```atscript\n@db.view.for User\n@db.view.filter `User.status = 'active' and User.age >= 18`\nexport interface ActiveUser { ... }\n```\n",
869
852
  nodeType: ["interface"],
870
853
  argument: {
@@ -902,7 +885,7 @@ const dbViewAnnotations = { view: {
902
885
  return errors;
903
886
  }
904
887
  }),
905
- materialized: new __atscript_core.AnnotationSpec({
888
+ materialized: new _atscript_core.AnnotationSpec({
906
889
  description: "Marks a view as materialized (precomputed, stored on disk). Supported by PostgreSQL, CockroachDB, Oracle, SQL Server (indexed views), Snowflake. MongoDB supports on-demand materialized views via $merge/$out. Not applicable to MySQL or SQLite.\n\n**Example:**\n```atscript\n@db.view.materialized\n@db.view.for User\n@db.view.filter `User.status = 'active'`\nexport interface ActiveUsers { ... }\n```\n",
907
890
  nodeType: ["interface"],
908
891
  validate(token, _args, _doc) {
@@ -916,7 +899,7 @@ const dbViewAnnotations = { view: {
916
899
  return errors;
917
900
  }
918
901
  }),
919
- renamed: new __atscript_core.AnnotationSpec({
902
+ renamed: new _atscript_core.AnnotationSpec({
920
903
  description: "Specifies the previous view name for view rename migration. The sync engine drops the old view and creates the new one.\n\n**Example:**\n```atscript\n@db.view \"active_premium_users\"\n@db.view.renamed \"active_users\"\n@db.view.for User\nexport interface ActivePremiumUser { ... }\n```\n",
921
904
  nodeType: ["interface"],
922
905
  argument: {
@@ -935,7 +918,7 @@ const dbViewAnnotations = { view: {
935
918
  return errors;
936
919
  }
937
920
  }),
938
- having: new __atscript_core.AnnotationSpec({
921
+ having: new _atscript_core.AnnotationSpec({
939
922
  description: "Post-aggregation filter (HAVING clause) for analytical views. References view field aliases with applied aggregate functions.\n\n**Example:**\n```atscript\n@db.view\n@db.view.for Order\n@db.view.having `totalRevenue > 100`\nexport interface TopCategories { ... }\n```\n",
940
923
  nodeType: ["interface"],
941
924
  argument: {
@@ -955,9 +938,8 @@ const dbViewAnnotations = { view: {
955
938
  }
956
939
  })
957
940
  } };
958
-
959
941
  //#endregion
960
- //#region packages/db/src/plugin/index.ts
942
+ //#region src/plugin/index.ts
961
943
  const dbPlugin = () => ({
962
944
  name: "db",
963
945
  config() {
@@ -987,7 +969,6 @@ const dbPlugin = () => ({
987
969
  };
988
970
  }
989
971
  });
990
-
991
972
  //#endregion
992
- exports.dbPlugin = dbPlugin
993
- exports.default = dbPlugin
973
+ exports.dbPlugin = dbPlugin;
974
+ exports.default = dbPlugin;
@@ -0,0 +1,6 @@
1
+ import { TAtscriptPlugin } from "@atscript/core";
2
+
3
+ //#region src/plugin/index.d.ts
4
+ declare const dbPlugin: () => TAtscriptPlugin;
5
+ //#endregion
6
+ export { dbPlugin, dbPlugin as default };
@@ -0,0 +1,6 @@
1
+ import { TAtscriptPlugin } from "@atscript/core";
2
+
3
+ //#region src/plugin/index.d.ts
4
+ declare const dbPlugin: () => TAtscriptPlugin;
5
+ //#endregion
6
+ export { dbPlugin, dbPlugin as default };