@c9up/atlas 0.1.19 → 0.2.1

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 (250) hide show
  1. package/README.md +63 -14
  2. package/db.darwin-arm64.node +0 -0
  3. package/db.darwin-x64.node +0 -0
  4. package/db.linux-arm64-gnu.node +0 -0
  5. package/db.linux-x64-gnu.node +0 -0
  6. package/db.win32-x64-msvc.node +0 -0
  7. package/dist/AtlasProvider.d.ts +66 -7
  8. package/dist/AtlasProvider.d.ts.map +1 -1
  9. package/dist/AtlasProvider.js +205 -39
  10. package/dist/AtlasProvider.js.map +1 -1
  11. package/dist/BaseEntity.d.ts +181 -5
  12. package/dist/BaseEntity.d.ts.map +1 -1
  13. package/dist/BaseEntity.js +339 -33
  14. package/dist/BaseEntity.js.map +1 -1
  15. package/dist/BaseModel.d.ts +127 -0
  16. package/dist/BaseModel.d.ts.map +1 -0
  17. package/dist/BaseModel.js +250 -0
  18. package/dist/BaseModel.js.map +1 -0
  19. package/dist/BaseRepository.d.ts +81 -15
  20. package/dist/BaseRepository.d.ts.map +1 -1
  21. package/dist/BaseRepository.js +1433 -387
  22. package/dist/BaseRepository.js.map +1 -1
  23. package/dist/ConnectionManager.d.ts +106 -0
  24. package/dist/ConnectionManager.d.ts.map +1 -0
  25. package/dist/ConnectionManager.js +228 -0
  26. package/dist/ConnectionManager.js.map +1 -0
  27. package/dist/ModelQuery.d.ts +577 -41
  28. package/dist/ModelQuery.d.ts.map +1 -1
  29. package/dist/ModelQuery.js +2188 -291
  30. package/dist/ModelQuery.js.map +1 -1
  31. package/dist/Transaction.d.ts +71 -1
  32. package/dist/Transaction.d.ts.map +1 -1
  33. package/dist/Transaction.js +138 -24
  34. package/dist/Transaction.js.map +1 -1
  35. package/dist/adapters/NapiDbAdapter.d.ts +44 -4
  36. package/dist/adapters/NapiDbAdapter.d.ts.map +1 -1
  37. package/dist/adapters/NapiDbAdapter.js +131 -13
  38. package/dist/adapters/NapiDbAdapter.js.map +1 -1
  39. package/dist/console/contract.d.ts +62 -0
  40. package/dist/console/contract.d.ts.map +1 -0
  41. package/dist/console/contract.js +38 -0
  42. package/dist/console/contract.js.map +1 -0
  43. package/dist/console/factoryCommands.d.ts +23 -0
  44. package/dist/console/factoryCommands.d.ts.map +1 -0
  45. package/dist/console/factoryCommands.js +62 -0
  46. package/dist/console/factoryCommands.js.map +1 -0
  47. package/dist/console/migrationCommands.d.ts +78 -0
  48. package/dist/console/migrationCommands.d.ts.map +1 -0
  49. package/dist/console/migrationCommands.js +327 -0
  50. package/dist/console/migrationCommands.js.map +1 -0
  51. package/dist/console/schemaCheckCommand.d.ts +11 -17
  52. package/dist/console/schemaCheckCommand.d.ts.map +1 -1
  53. package/dist/console/schemaCheckCommand.js +21 -15
  54. package/dist/console/schemaCheckCommand.js.map +1 -1
  55. package/dist/console/schemaDumpCommand.d.ts +30 -0
  56. package/dist/console/schemaDumpCommand.d.ts.map +1 -0
  57. package/dist/console/schemaDumpCommand.js +69 -0
  58. package/dist/console/schemaDumpCommand.js.map +1 -0
  59. package/dist/console/schemaGenerateCommand.d.ts +100 -0
  60. package/dist/console/schemaGenerateCommand.d.ts.map +1 -0
  61. package/dist/console/schemaGenerateCommand.js +246 -0
  62. package/dist/console/schemaGenerateCommand.js.map +1 -0
  63. package/dist/console/seederCommands.d.ts +46 -0
  64. package/dist/console/seederCommands.d.ts.map +1 -0
  65. package/dist/console/seederCommands.js +136 -0
  66. package/dist/console/seederCommands.js.map +1 -0
  67. package/dist/decorators/entity.d.ts +50 -8
  68. package/dist/decorators/entity.d.ts.map +1 -1
  69. package/dist/decorators/entity.js +42 -2
  70. package/dist/decorators/entity.js.map +1 -1
  71. package/dist/decorators/hooks.d.ts +3 -3
  72. package/dist/decorators/hooks.d.ts.map +1 -1
  73. package/dist/decorators/hooks.js.map +1 -1
  74. package/dist/events.d.ts +69 -0
  75. package/dist/events.d.ts.map +1 -0
  76. package/dist/events.js +82 -0
  77. package/dist/events.js.map +1 -0
  78. package/dist/factories.d.ts +8 -0
  79. package/dist/factories.d.ts.map +1 -0
  80. package/dist/factories.js +8 -0
  81. package/dist/factories.js.map +1 -0
  82. package/dist/index.d.ts +15 -5
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +14 -3
  85. package/dist/index.js.map +1 -1
  86. package/dist/lucid-schema.d.ts +15 -0
  87. package/dist/lucid-schema.d.ts.map +1 -0
  88. package/dist/lucid-schema.js +16 -0
  89. package/dist/lucid-schema.js.map +1 -0
  90. package/dist/metadata-keys.d.ts +3 -2
  91. package/dist/metadata-keys.d.ts.map +1 -1
  92. package/dist/naming/NamingStrategy.d.ts +7 -0
  93. package/dist/naming/NamingStrategy.d.ts.map +1 -1
  94. package/dist/naming/NamingStrategy.js +16 -0
  95. package/dist/naming/NamingStrategy.js.map +1 -1
  96. package/dist/orm.d.ts +14 -0
  97. package/dist/orm.d.ts.map +1 -0
  98. package/dist/orm.js +14 -0
  99. package/dist/orm.js.map +1 -0
  100. package/dist/query/DatabaseQueryBuilder.d.ts +557 -0
  101. package/dist/query/DatabaseQueryBuilder.d.ts.map +1 -0
  102. package/dist/query/DatabaseQueryBuilder.js +1798 -0
  103. package/dist/query/DatabaseQueryBuilder.js.map +1 -0
  104. package/dist/query/DmlBuilder.d.ts +62 -0
  105. package/dist/query/DmlBuilder.d.ts.map +1 -0
  106. package/dist/query/DmlBuilder.js +84 -0
  107. package/dist/query/DmlBuilder.js.map +1 -0
  108. package/dist/query/QueryBuilder.d.ts +5 -0
  109. package/dist/query/QueryBuilder.d.ts.map +1 -1
  110. package/dist/query/QueryBuilder.js +7 -0
  111. package/dist/query/QueryBuilder.js.map +1 -1
  112. package/dist/query/RawQueryBuilder.d.ts +47 -0
  113. package/dist/query/RawQueryBuilder.d.ts.map +1 -0
  114. package/dist/query/RawQueryBuilder.js +138 -0
  115. package/dist/query/RawQueryBuilder.js.map +1 -0
  116. package/dist/query/interpolate.d.ts +45 -0
  117. package/dist/query/interpolate.d.ts.map +1 -0
  118. package/dist/query/interpolate.js +51 -0
  119. package/dist/query/interpolate.js.map +1 -0
  120. package/dist/query/native.d.ts +8 -0
  121. package/dist/query/native.d.ts.map +1 -1
  122. package/dist/query/native.js +14 -0
  123. package/dist/query/native.js.map +1 -1
  124. package/dist/query/operators.d.ts +4 -0
  125. package/dist/query/operators.d.ts.map +1 -0
  126. package/dist/query/operators.js +27 -0
  127. package/dist/query/operators.js.map +1 -0
  128. package/dist/schema/Migration.d.ts +50 -3
  129. package/dist/schema/Migration.d.ts.map +1 -1
  130. package/dist/schema/Migration.js +60 -24
  131. package/dist/schema/Migration.js.map +1 -1
  132. package/dist/schema/MigrationRunner.d.ts +95 -34
  133. package/dist/schema/MigrationRunner.d.ts.map +1 -1
  134. package/dist/schema/MigrationRunner.js +523 -68
  135. package/dist/schema/MigrationRunner.js.map +1 -1
  136. package/dist/schema/Schema.d.ts +114 -0
  137. package/dist/schema/Schema.d.ts.map +1 -1
  138. package/dist/schema/Schema.js +272 -3
  139. package/dist/schema/Schema.js.map +1 -1
  140. package/dist/schema/SchemaDumper.d.ts +121 -0
  141. package/dist/schema/SchemaDumper.d.ts.map +1 -0
  142. package/dist/schema/SchemaDumper.js +365 -0
  143. package/dist/schema/SchemaDumper.js.map +1 -0
  144. package/dist/schema/Seeder.d.ts +13 -0
  145. package/dist/schema/Seeder.d.ts.map +1 -1
  146. package/dist/schema/Seeder.js +28 -5
  147. package/dist/schema/Seeder.js.map +1 -1
  148. package/dist/schema/TableBuilder.d.ts +274 -16
  149. package/dist/schema/TableBuilder.d.ts.map +1 -1
  150. package/dist/schema/TableBuilder.js +656 -52
  151. package/dist/schema/TableBuilder.js.map +1 -1
  152. package/dist/schema/catalog.d.ts +71 -0
  153. package/dist/schema/catalog.d.ts.map +1 -0
  154. package/dist/schema/catalog.js +158 -0
  155. package/dist/schema/catalog.js.map +1 -0
  156. package/dist/schema/introspect.d.ts +1 -1
  157. package/dist/schema/introspect.d.ts.map +1 -1
  158. package/dist/schema/introspect.js +26 -11
  159. package/dist/schema/introspect.js.map +1 -1
  160. package/dist/schema/types.d.ts +150 -1
  161. package/dist/schema/types.d.ts.map +1 -1
  162. package/dist/schema/types.js +11 -0
  163. package/dist/schema/types.js.map +1 -1
  164. package/dist/seeders.d.ts +7 -0
  165. package/dist/seeders.d.ts.map +1 -0
  166. package/dist/seeders.js +7 -0
  167. package/dist/seeders.js.map +1 -0
  168. package/dist/services/db.d.ts +122 -5
  169. package/dist/services/db.d.ts.map +1 -1
  170. package/dist/services/db.js +187 -14
  171. package/dist/services/db.js.map +1 -1
  172. package/dist/testing/DatabaseCleanup.d.ts +33 -7
  173. package/dist/testing/DatabaseCleanup.d.ts.map +1 -1
  174. package/dist/testing/DatabaseCleanup.js +54 -24
  175. package/dist/testing/DatabaseCleanup.js.map +1 -1
  176. package/dist/testing/DbAssertions.d.ts +48 -0
  177. package/dist/testing/DbAssertions.d.ts.map +1 -0
  178. package/dist/testing/DbAssertions.js +80 -0
  179. package/dist/testing/DbAssertions.js.map +1 -0
  180. package/dist/testing/Factory.d.ts +166 -15
  181. package/dist/testing/Factory.d.ts.map +1 -1
  182. package/dist/testing/Factory.js +497 -23
  183. package/dist/testing/Factory.js.map +1 -1
  184. package/dist/testing/TestUtils.d.ts +49 -0
  185. package/dist/testing/TestUtils.d.ts.map +1 -0
  186. package/dist/testing/TestUtils.js +79 -0
  187. package/dist/testing/TestUtils.js.map +1 -0
  188. package/dist/testing/index.d.ts +3 -1
  189. package/dist/testing/index.d.ts.map +1 -1
  190. package/dist/testing/index.js +3 -1
  191. package/dist/testing/index.js.map +1 -1
  192. package/dist/types/relations.d.ts +31 -0
  193. package/dist/types/relations.d.ts.map +1 -0
  194. package/dist/types/relations.js +20 -0
  195. package/dist/types/relations.js.map +1 -0
  196. package/index.darwin-arm64.node +0 -0
  197. package/index.darwin-x64.node +0 -0
  198. package/index.linux-arm64-gnu.node +0 -0
  199. package/index.linux-x64-gnu.node +0 -0
  200. package/index.win32-x64-msvc.node +0 -0
  201. package/package.json +32 -2
  202. package/scripts/guard-publish.mjs +15 -0
  203. package/src/AtlasProvider.ts +305 -52
  204. package/src/BaseEntity.ts +460 -41
  205. package/src/BaseModel.ts +461 -0
  206. package/src/BaseRepository.ts +1710 -421
  207. package/src/ConnectionManager.ts +298 -0
  208. package/src/ModelQuery.ts +2998 -335
  209. package/src/Transaction.ts +227 -30
  210. package/src/adapters/NapiDbAdapter.ts +224 -17
  211. package/src/console/contract.ts +96 -0
  212. package/src/console/factoryCommands.ts +73 -0
  213. package/src/console/migrationCommands.ts +448 -0
  214. package/src/console/schemaCheckCommand.ts +26 -22
  215. package/src/console/schemaDumpCommand.ts +96 -0
  216. package/src/console/schemaGenerateCommand.ts +380 -0
  217. package/src/console/seederCommands.ts +174 -0
  218. package/src/decorators/entity.ts +71 -8
  219. package/src/decorators/hooks.ts +5 -3
  220. package/src/events.ts +117 -0
  221. package/src/factories.ts +10 -0
  222. package/src/index.ts +69 -3
  223. package/src/lucid-schema.ts +22 -0
  224. package/src/metadata-keys.ts +3 -2
  225. package/src/naming/NamingStrategy.ts +23 -0
  226. package/src/orm.ts +13 -0
  227. package/src/query/DatabaseQueryBuilder.ts +2724 -0
  228. package/src/query/DmlBuilder.ts +131 -0
  229. package/src/query/QueryBuilder.ts +8 -0
  230. package/src/query/RawQueryBuilder.ts +173 -0
  231. package/src/query/interpolate.ts +73 -0
  232. package/src/query/native.ts +29 -0
  233. package/src/query/operators.ts +27 -0
  234. package/src/schema/Migration.ts +71 -3
  235. package/src/schema/MigrationRunner.ts +676 -69
  236. package/src/schema/Schema.ts +359 -3
  237. package/src/schema/SchemaDumper.ts +518 -0
  238. package/src/schema/Seeder.ts +47 -10
  239. package/src/schema/TableBuilder.ts +783 -52
  240. package/src/schema/catalog.ts +236 -0
  241. package/src/schema/introspect.ts +26 -9
  242. package/src/schema/types.ts +137 -2
  243. package/src/seeders.ts +16 -0
  244. package/src/services/db.ts +361 -21
  245. package/src/testing/DatabaseCleanup.ts +78 -25
  246. package/src/testing/DbAssertions.ts +127 -0
  247. package/src/testing/Factory.ts +837 -40
  248. package/src/testing/TestUtils.ts +123 -0
  249. package/src/testing/index.ts +12 -1
  250. package/src/types/relations.ts +43 -0
@@ -6,27 +6,82 @@
6
6
  *
7
7
  * Builds SQL fluently and executes against the database connection.
8
8
  */
9
- import type { BaseEntity } from "./BaseEntity.js";
10
- import type { DatabaseConnection } from "./BaseRepository.js";
11
- import { type AtlasDialect } from "./query/native.js";
9
+ import { type BaseEntity, type DomainEvent } from "./BaseEntity.js";
10
+ import { type DatabaseConnection } from "./BaseRepository.js";
11
+ import { DmlBuilder } from "./query/DmlBuilder.js";
12
+ import { type CompiledStatement } from "./query/interpolate.js";
13
+ import { type AtlasDialect, type DialectName } from "./query/native.js";
14
+ import { RawSql } from "./query/QueryBuilder.js";
12
15
  type PreloadCallback = (query: ModelQuery<BaseEntity>) => void;
13
16
  type ColumnResolver = (column: string) => string;
17
+ /**
18
+ * Lower a value bound for a given property to its DB form — mirrors
19
+ * `BaseRepository.#applyPrepare` (a `@column.dateTime` DateTime → ISO string, a
20
+ * `@Column({ prepare })` adapter runs). Threaded into ModelQuery so the fluent
21
+ * `update()` / WHERE paths don't bypass prepare the way direct repo writes don't.
22
+ */
23
+ type ValuePreparer = (column: string, value: unknown) => unknown;
14
24
  type WhereCallback = (q: ModelQuery<BaseEntity>) => void;
15
- /** Enable or disable Atlas strict mode. When enabled, whereRaw/joinRaw throw in user code. */
25
+ /** A compound-query (union/intersect/except) arg a query OR a callback building one. */
26
+ type UnionArg = ModelQuery<BaseEntity> | ((q: ModelQuery<BaseEntity>) => void);
27
+ /** Enable or disable Atlas strict mode. When enabled, whereRaw/joinRaw/havingRaw throw in user code. */
16
28
  export declare function setAtlasStrictMode(enabled: boolean): void;
17
29
  /** Current strict mode state — lazy env var read on first access. */
18
30
  export declare function isAtlasStrictMode(): boolean;
19
31
  export declare function runWithAtlasInternalBypass<T>(fn: () => T): T;
20
- /** Multi-condition join builder passed to innerJoin/leftJoin/rightJoin callbacks. */
32
+ /**
33
+ * Multi-condition join builder passed to innerJoin/leftJoin/rightJoin callbacks.
34
+ * `on`/`andOn`/`orOn` join two COLUMNS; `onVal`/`andOnVal`/`orOnVal` join a column
35
+ * to a bound VALUE (AdonisJS/Knex parity) — the value flows through the join-params
36
+ * channel into the compiled parameter list.
37
+ */
38
+ interface JoinPartMQ {
39
+ kind: "and" | "or";
40
+ left?: string;
41
+ operator?: string;
42
+ right?: string;
43
+ value?: {
44
+ v: unknown;
45
+ };
46
+ values?: unknown[];
47
+ notIn?: boolean;
48
+ between?: [unknown, unknown];
49
+ notBetween?: boolean;
50
+ nullOp?: "IS NULL" | "IS NOT NULL";
51
+ exists?: {
52
+ sql: string;
53
+ params: unknown[];
54
+ not: boolean;
55
+ };
56
+ }
21
57
  interface JoinBuilder {
22
- parts: Array<{
23
- kind: "and" | "or";
24
- left: string;
25
- right: string;
26
- }>;
58
+ /** Accumulated `ON` parts — column-to-column, column-to-value, IN, BETWEEN, NULL, EXISTS. */
59
+ parts: JoinPartMQ[];
27
60
  on(left: string, right: string): JoinBuilder;
61
+ on(left: string, operator: string, right: string): JoinBuilder;
28
62
  andOn(left: string, right: string): JoinBuilder;
63
+ andOn(left: string, operator: string, right: string): JoinBuilder;
64
+ orOn(left: string, right: string): JoinBuilder;
65
+ orOn(left: string, operator: string, right: string): JoinBuilder;
66
+ onVal(left: string, value: unknown): JoinBuilder;
29
67
  andOnVal(left: string, value: unknown): JoinBuilder;
68
+ orOnVal(left: string, value: unknown): JoinBuilder;
69
+ /** `ON col IN (?, ?)` (Lucid/Knex `onIn`). */
70
+ onIn(left: string, values: unknown[]): JoinBuilder;
71
+ /** `ON col NOT IN (?, ?)` (Lucid/Knex `onNotIn`). */
72
+ onNotIn(left: string, values: unknown[]): JoinBuilder;
73
+ /** `ON col IS NULL` (Lucid/Knex `onNull`). */
74
+ onNull(left: string): JoinBuilder;
75
+ /** `ON col IS NOT NULL` (Lucid/Knex `onNotNull`). */
76
+ onNotNull(left: string): JoinBuilder;
77
+ /** `ON col BETWEEN ? AND ?` — inclusive (Lucid/Knex `onBetween`). */
78
+ onBetween(left: string, range: readonly [unknown, unknown]): JoinBuilder;
79
+ /** `ON col NOT BETWEEN ? AND ?` (Lucid/Knex `onNotBetween`). */
80
+ onNotBetween(left: string, range: readonly [unknown, unknown]): JoinBuilder;
81
+ /** `ON EXISTS (subquery)` — a builder or a callback (Lucid/Knex `onExists`). */
82
+ onExists(subquery: UnionArg): JoinBuilder;
83
+ /** `ON NOT EXISTS (subquery)` (Lucid/Knex `onNotExists`). */
84
+ onNotExists(subquery: UnionArg): JoinBuilder;
30
85
  }
31
86
  /** Offset-based paginator (Story 29.10). */
32
87
  export declare class Paginator<T> {
@@ -43,8 +98,18 @@ export declare class Paginator<T> {
43
98
  total: number;
44
99
  perPage: number;
45
100
  currentPage: number;
46
- });
101
+ }, metaKeys?: Record<string, string>);
47
102
  all(): T[];
103
+ /** Total row count across all pages. */
104
+ get total(): number;
105
+ /** Rows per page. */
106
+ get perPage(): number;
107
+ /** The current page number. */
108
+ get currentPage(): number;
109
+ /** The last page number. */
110
+ get lastPage(): number;
111
+ /** The first page number (always 1). */
112
+ get firstPage(): number;
48
113
  /** True when there is more than one page of results (AdonisJS `hasPages`). */
49
114
  get hasPages(): boolean;
50
115
  /** True when there is at least one more page after the current one (AdonisJS `hasMorePages`). */
@@ -53,22 +118,42 @@ export declare class Paginator<T> {
53
118
  fields?: string[];
54
119
  }): {
55
120
  data: unknown[];
56
- meta: Paginator<T>["meta"];
121
+ meta: Record<string, unknown>;
57
122
  };
58
123
  baseUrl(url: string): this;
59
124
  queryString(qs: Record<string, unknown>): this;
125
+ /**
126
+ * Build the URL for a page number, honouring `baseUrl` + `queryString`.
127
+ * Returns `''` when no `baseUrl` was set (AdonisJS `getUrl`).
128
+ */
129
+ getUrl(page: number): string;
130
+ /** URL of the next page, or `null` when on the last page (AdonisJS `getNextPageUrl`). */
131
+ getNextPageUrl(): string | null;
132
+ /** URL of the previous page, or `null` when on the first page (AdonisJS `getPreviousPageUrl`). */
133
+ getPreviousPageUrl(): string | null;
134
+ /** URLs for an inclusive page range, clamped to `[1, lastPage]` (AdonisJS `getUrlsForRange`). */
135
+ getUrlsForRange(start: number, end: number): Array<{
136
+ page: number;
137
+ url: string;
138
+ isActive: boolean;
139
+ }>;
60
140
  toJSON(): {
61
141
  data: unknown[];
62
- meta: Paginator<T>["meta"] & Record<string, unknown>;
142
+ meta: Record<string, unknown>;
63
143
  };
64
144
  }
65
145
  export declare class ModelQuery<T extends BaseEntity> {
66
146
  #private;
67
- constructor(tableName: string, db: DatabaseConnection, hydrateFn: (row: Record<string, unknown>) => T, entityClass: new () => T, resolveColumn?: ColumnResolver, softDeletes?: boolean, dialect?: AtlasDialect);
147
+ constructor(tableName: string, db: DatabaseConnection, hydrateFn: (row: Record<string, unknown>) => T, entityClass: new () => T, resolveColumn?: ColumnResolver, softDeletes?: boolean, dialect?: AtlasDialect, prepareValue?: ValuePreparer, onDomainEvents?: (events: DomainEvent[]) => Promise<void>);
68
148
  /** Include soft-deleted rows in the result (default behavior excludes them). */
69
149
  withTrashed(): this;
70
150
  /** Return ONLY soft-deleted rows (deleted_at IS NOT NULL). */
71
151
  onlyTrashed(): this;
152
+ /**
153
+ * Apply the first `[guard, callback]` whose guard is truthy (Adonis Lucid
154
+ * `match`); a trailing bare callback is the default, run when none matched.
155
+ */
156
+ match(...blocks: Array<[unknown, (query: this) => void] | ((query: this) => void)>): this;
72
157
  /**
73
158
  * Eager-load a relation (AdonisJS-style).
74
159
  * Relations are never loaded automatically — you must call .preload() explicitly.
@@ -78,8 +163,29 @@ export declare class ModelQuery<T extends BaseEntity> {
78
163
  * repo.query().preload('posts', q => q.where('published', true)).exec()
79
164
  */
80
165
  preload(relationName: string, callback?: PreloadCallback): this;
81
- /** Select specific columns (default: `*`). Accepts a comma-separated string or an array. */
82
- select(columns: string | string[]): this;
166
+ /**
167
+ * Eager-load a relation only if it hasn't been registered yet (Adonis Lucid
168
+ * `preloadOnce`) — a later `preload`/`preloadOnce` for the same relation is
169
+ * ignored, so a shared scope can safely add a preload without clobbering one
170
+ * the caller already set.
171
+ */
172
+ preloadOnce(relationName: string, callback?: PreloadCallback): this;
173
+ /**
174
+ * Register a callback run for every hydrated instance after loading (preloads
175
+ * included) but before the query resolves (Adonis Lucid `rowTransformer`). The
176
+ * callback mutates the instance in place — decorate rows with per-query
177
+ * computed values without a model hook/accessor. Multiple transformers run in
178
+ * registration order.
179
+ */
180
+ rowTransformer(callback: (row: T) => void): this;
181
+ /**
182
+ * Select columns (default: `*`). The model query builder extends the database
183
+ * query builder's `select` surface (Lucid parity): bare names, multiple args,
184
+ * a comma-separated string, an array, an `{ alias: 'column' }` object map, a
185
+ * `db.raw(...)` fragment, and a named subquery — `select(subquery.as('x'))`.
186
+ * Plain columns are resolved to their DB column (honouring `@Column`).
187
+ */
188
+ select(...columns: Array<string | string[] | Record<string, string> | RawSql | ModelQuery<BaseEntity>>): this;
83
189
  where(callback: WhereCallback): this;
84
190
  where(column: string, value: unknown): this;
85
191
  where(column: string, operator: string, value: unknown): this;
@@ -88,9 +194,40 @@ export declare class ModelQuery<T extends BaseEntity> {
88
194
  orWhere(column: string, operator: string, value: unknown): this;
89
195
  whereNull(column: string): this;
90
196
  whereNotNull(column: string): this;
91
- /** `WHERE col != ?` — negation of `where`. */
197
+ andWhere(callback: WhereCallback): this;
198
+ andWhere(column: string, value: unknown): this;
199
+ andWhere(column: string, operator: string, value: unknown): this;
200
+ /** Alias of {@link whereNot} (Lucid parity). */
201
+ andWhereNot(column: string, value: unknown): this;
202
+ /** Alias of {@link whereIn} (Lucid parity). */
203
+ andWhereIn(column: string, values: readonly unknown[]): this;
204
+ /** Alias of {@link whereNotIn} (Lucid parity). */
205
+ andWhereNotIn(column: string, values: readonly unknown[]): this;
206
+ /** Alias of {@link whereNull} (Lucid parity). */
207
+ andWhereNull(column: string): this;
208
+ /** Alias of {@link whereNotNull} (Lucid parity). */
209
+ andWhereNotNull(column: string): this;
210
+ /** Alias of {@link whereBetween} (Lucid parity). */
211
+ andWhereBetween(column: string, range: readonly [unknown, unknown]): this;
212
+ /** Alias of {@link whereNotBetween} (Lucid parity). */
213
+ andWhereNotBetween(column: string, range: readonly [unknown, unknown]): this;
214
+ /** Alias of {@link whereLike} (Lucid parity). */
215
+ andWhereLike(column: string, pattern: string): this;
216
+ /** Alias of {@link whereILike} (Lucid parity). */
217
+ andWhereILike(column: string, pattern: string): this;
218
+ /** Alias of {@link whereColumn} (Lucid parity). */
219
+ andWhereColumn(left: string, operator: string, right: string): this;
220
+ /**
221
+ * Negated WHERE (Lucid/Knex `whereNot`) — the same forms as {@link where}: a
222
+ * `(column, [operator,] value)` comparison, an object (`whereNot({ a: 1 })` →
223
+ * `a != 1`), or a callback group (`whereNot((q) => …)` → `NOT (…)`).
224
+ */
225
+ whereNot(callback: WhereCallback): this;
226
+ whereNot(conditions: Record<string, unknown>): this;
92
227
  whereNot(column: string, value: unknown): this;
228
+ whereNot(column: string, operator: string, value: unknown): this;
93
229
  /** `WHERE col IN (...)` — accepts an array of values OR a `ModelQuery` subquery source. */
230
+ whereIn(columns: string[], rows: unknown[][]): this;
94
231
  whereIn(column: string, source: readonly unknown[] | ModelQuery<BaseEntity>): this;
95
232
  /** `WHERE col NOT IN (...)` — accepts an array of values OR a `ModelQuery` subquery source. */
96
233
  whereNotIn(column: string, source: readonly unknown[] | ModelQuery<BaseEntity>): this;
@@ -147,6 +284,29 @@ export declare class ModelQuery<T extends BaseEntity> {
147
284
  * @unsafe Raw SQL fragment — never concatenate user input into `sql`.
148
285
  */
149
286
  whereRaw(sql: string, bindings?: readonly unknown[]): this;
287
+ /** Alias of {@link whereRaw} (Lucid parity). Subject to the same strict-mode gate. */
288
+ andWhereRaw(sql: string, bindings?: readonly unknown[]): this;
289
+ /**
290
+ * `OR <raw fragment>` (Lucid parity).
291
+ *
292
+ * @unsafe Raw SQL fragment — never concatenate user input into `sql`.
293
+ * Subject to the same strict-mode gate as {@link whereRaw}.
294
+ */
295
+ orWhereRaw(sql: string, bindings?: readonly unknown[]): this;
296
+ /**
297
+ * Framework-internal: register the deferred m2m EXISTS predicate for a lazy
298
+ * `related().query()`. The builder is re-invoked on every `#buildSpec()` with
299
+ * the pivot constraints known at that moment, so `.wherePivot()` added after
300
+ * the proxy returned still applies. Not exported from the barrel.
301
+ */
302
+ setPivotExistsBuilder(builder: (pivotWheres: ReadonlyArray<{
303
+ column: string;
304
+ operator: string;
305
+ value: unknown;
306
+ }>) => {
307
+ sql: string;
308
+ bindings: unknown[];
309
+ }): this;
150
310
  /**
151
311
  * **SAFE** alternative to `whereRaw` for the common case of a single
152
312
  * SQL expression built from a validated column + operator + bound value.
@@ -171,9 +331,105 @@ export declare class ModelQuery<T extends BaseEntity> {
171
331
  * operator is allow-listed; nothing is bound (it's a column reference, not a
172
332
  * value), which the standard `where`/`whereExpr` value-binding path can't do.
173
333
  */
334
+ /** `WHERE EXISTS (subquery)` (Lucid parity). */
335
+ whereExists(subquery: ModelQuery<BaseEntity>): this;
336
+ /** Alias of {@link whereExists} (Lucid parity). */
337
+ andWhereExists(subquery: ModelQuery<BaseEntity>): this;
338
+ /** `OR EXISTS (subquery)` (Lucid parity). */
339
+ orWhereExists(subquery: ModelQuery<BaseEntity>): this;
340
+ /** `WHERE NOT EXISTS (subquery)` (Lucid parity). */
341
+ whereNotExists(subquery: ModelQuery<BaseEntity>): this;
342
+ /** Alias of {@link whereNotExists} (Lucid parity). */
343
+ andWhereNotExists(subquery: ModelQuery<BaseEntity>): this;
344
+ /** `OR NOT EXISTS (subquery)` (Lucid parity). */
345
+ orWhereNotExists(subquery: ModelQuery<BaseEntity>): this;
346
+ /**
347
+ * `WHERE <col at path> <op> ?` — compare a value inside a JSON column
348
+ * (Lucid/Knex `whereJsonPath`). `path` is a JSONPath (`$.a.b`, `$.items[0]`).
349
+ *
350
+ * query.whereJsonPath('data', '$.address.city', '=', 'Paris')
351
+ */
352
+ whereJsonPath(column: string, path: string, value: unknown): this;
353
+ whereJsonPath(column: string, path: string, operator: string, value: unknown): this;
354
+ /** Alias of {@link whereJsonPath} (Lucid parity). Operator defaults to `=`. */
355
+ andWhereJsonPath(column: string, path: string, value: unknown): this;
356
+ andWhereJsonPath(column: string, path: string, operator: string, value: unknown): this;
357
+ /** `OR <col at path> <op> ?` (Lucid parity). Operator defaults to `=`. */
358
+ orWhereJsonPath(column: string, path: string, value: unknown): this;
359
+ orWhereJsonPath(column: string, path: string, operator: string, value: unknown): this;
360
+ /**
361
+ * Structural JSON match (Lucid `whereJson`) — the column's JSON must equal
362
+ * `value` (canonical comparison on Postgres/MySQL). AND is the default.
363
+ */
364
+ whereJson(column: string, value: unknown): this;
365
+ /** Alias of {@link whereJson} (Lucid `andWhereJson`). */
366
+ andWhereJson(column: string, value: unknown): this;
367
+ /** OR form of {@link whereJson} (Lucid `orWhereJson`). */
368
+ orWhereJson(column: string, value: unknown): this;
369
+ /** WHERE NOT structural JSON match (Lucid `whereNotJson`). */
370
+ whereNotJson(column: string, value: unknown): this;
371
+ /** Alias of {@link whereNotJson} (Lucid `andWhereNotJson`). */
372
+ andWhereNotJson(column: string, value: unknown): this;
373
+ /** OR NOT structural JSON match (Lucid `orWhereNotJson`). */
374
+ orWhereNotJson(column: string, value: unknown): this;
375
+ /**
376
+ * `WHERE <col> @> ?` — the JSON column contains `value` (Lucid/Knex
377
+ * `whereJsonSupersetOf`). `value` is any JSON-serialisable value.
378
+ *
379
+ * Postgres and MySQL only — SQLite has no JSON containment operator and the
380
+ * compiler raises `E_UNSUPPORTED` there.
381
+ */
382
+ whereJsonSupersetOf(column: string, value: unknown): this;
383
+ /** Alias of {@link whereJsonSupersetOf} (Lucid parity). */
384
+ andWhereJsonSupersetOf(column: string, value: unknown): this;
385
+ /** `OR <col> @> ?` (Lucid parity). See {@link whereJsonSupersetOf}. */
386
+ orWhereJsonSupersetOf(column: string, value: unknown): this;
387
+ /** `WHERE NOT (<col> @> ?)` (Lucid parity). */
388
+ whereNotJsonSupersetOf(column: string, value: unknown): this;
389
+ /** `OR NOT (<col> @> ?)` (Lucid parity). */
390
+ orWhereNotJsonSupersetOf(column: string, value: unknown): this;
391
+ /**
392
+ * `WHERE <col> <@ ?` — the JSON column is contained in `value` (Lucid/Knex
393
+ * `whereJsonSubsetOf`). Postgres/MySQL only; see {@link whereJsonSupersetOf}.
394
+ */
395
+ whereJsonSubsetOf(column: string, value: unknown): this;
396
+ /** Alias of {@link whereJsonSubsetOf} (Lucid parity). */
397
+ andWhereJsonSubsetOf(column: string, value: unknown): this;
398
+ /** `OR <col> <@ ?` (Lucid parity). See {@link whereJsonSubsetOf}. */
399
+ orWhereJsonSubsetOf(column: string, value: unknown): this;
400
+ /** `WHERE NOT (<col> <@ ?)` (Lucid parity). */
401
+ whereNotJsonSubsetOf(column: string, value: unknown): this;
402
+ /** `OR NOT (<col> <@ ?)` (Lucid parity). */
403
+ orWhereNotJsonSubsetOf(column: string, value: unknown): this;
404
+ /** Lucid `whereJsonSuperset` (alias of {@link whereJsonSupersetOf}). */
405
+ whereJsonSuperset(column: string, value: unknown): this;
406
+ /** Lucid `andWhereJsonSuperset`. */
407
+ andWhereJsonSuperset(column: string, value: unknown): this;
408
+ /** Lucid `orWhereJsonSuperset`. */
409
+ orWhereJsonSuperset(column: string, value: unknown): this;
410
+ /** Lucid `whereNotJsonSuperset`. */
411
+ whereNotJsonSuperset(column: string, value: unknown): this;
412
+ /** Lucid `orWhereNotJsonSuperset`. */
413
+ orWhereNotJsonSuperset(column: string, value: unknown): this;
414
+ /** Lucid `whereJsonSubset` (alias of {@link whereJsonSubsetOf}). */
415
+ whereJsonSubset(column: string, value: unknown): this;
416
+ /** Lucid `andWhereJsonSubset`. */
417
+ andWhereJsonSubset(column: string, value: unknown): this;
418
+ /** Lucid `orWhereJsonSubset`. */
419
+ orWhereJsonSubset(column: string, value: unknown): this;
420
+ /** Lucid `whereNotJsonSubset`. */
421
+ whereNotJsonSubset(column: string, value: unknown): this;
422
+ /** Lucid `orWhereNotJsonSubset`. */
423
+ orWhereNotJsonSubset(column: string, value: unknown): this;
174
424
  whereColumn(left: string, operator: string, right: string): this;
175
425
  /** `OR`-combined {@link whereColumn}. */
176
426
  orWhereColumn(left: string, operator: string, right: string): this;
427
+ /** `WHERE NOT (left <op> right)` — negation of {@link whereColumn} (Lucid parity). */
428
+ whereNotColumn(left: string, operator: string, right: string): this;
429
+ /** Alias of {@link whereNotColumn} (Lucid parity). */
430
+ andWhereNotColumn(left: string, operator: string, right: string): this;
431
+ /** `OR NOT (left <op> right)` (Lucid parity). */
432
+ orWhereNotColumn(left: string, operator: string, right: string): this;
177
433
  /**
178
434
  * `WHERE EXISTS (SELECT * FROM related WHERE <join> AND <cb>)` — filter parent rows
179
435
  * by the existence of related rows, optionally constrained by a callback.
@@ -186,6 +442,10 @@ export declare class ModelQuery<T extends BaseEntity> {
186
442
  /** `WHERE NOT EXISTS (...)` — negation of whereHas. */
187
443
  whereDoesntHave(relationName: string, callback?: (query: ModelQuery<BaseEntity>) => void): this;
188
444
  orWhereDoesntHave(relationName: string, callback?: (query: ModelQuery<BaseEntity>) => void): this;
445
+ /** Alias of {@link whereHas} (Lucid parity) — `whereHas` is already AND. */
446
+ andWhereHas(relationName: string, callback?: (query: ModelQuery<BaseEntity>) => void): this;
447
+ /** Alias of {@link whereDoesntHave} (Lucid parity). */
448
+ andWhereDoesntHave(relationName: string, callback?: (query: ModelQuery<BaseEntity>) => void): this;
189
449
  /**
190
450
  * Short form of `whereHas`. With an operator + count, emits a count threshold:
191
451
  * has('comments') → EXISTS (SELECT * FROM comments WHERE <join>)
@@ -195,6 +455,12 @@ export declare class ModelQuery<T extends BaseEntity> {
195
455
  orHas(relationName: string, countOp?: string, countThreshold?: number): this;
196
456
  /** `WHERE NOT EXISTS (...)` — short form. */
197
457
  doesntHave(relationName: string): this;
458
+ /** `OR NOT EXISTS (...)` — the OR form of {@link doesntHave} (Lucid parity). */
459
+ orDoesntHave(relationName: string): this;
460
+ /** Alias of {@link has} (Lucid parity) — `has` is already AND. */
461
+ andHas(relationName: string, countOp?: string, countThreshold?: number): this;
462
+ /** Alias of {@link doesntHave} (Lucid parity). */
463
+ andDoesntHave(relationName: string): this;
198
464
  /**
199
465
  * Set this query's projection alias — only meaningful when this ModelQuery
200
466
  * is used as the sub-builder callback argument of `withCount` / `withAggregate`.
@@ -234,22 +500,65 @@ export declare class ModelQuery<T extends BaseEntity> {
234
500
  * userRepo.query().withAggregate('posts', q => q.sum('views').as('total_views'))
235
501
  */
236
502
  withAggregate(relationName: string, callback: (query: ModelQuery<BaseEntity>) => void): this;
237
- orderBy(column: string, direction?: "asc" | "desc"): this;
503
+ /** ORDER BY a column, a `db.ref()` fragment, or an array of terms (Lucid/Knex `orderBy`). */
504
+ orderBy(column: string | RawSql, direction?: "asc" | "desc"): this;
505
+ orderBy(terms: Array<string | {
506
+ column: string;
507
+ order?: "asc" | "desc";
508
+ }>): this;
509
+ /**
510
+ * `ORDER BY <raw fragment>` (Lucid/Knex `orderByRaw`) — for orderings with
511
+ * no typed form: `NULLS LAST`, `RANDOM()`, a CASE expression, a computed
512
+ * alias.
513
+ *
514
+ * query.orderBy('rank').orderByRaw('created_at DESC NULLS LAST')
515
+ *
516
+ * The fragment keeps its position among the plain `orderBy` terms.
517
+ *
518
+ * **Strict mode**: like {@link whereRaw}, this throws when
519
+ * `setAtlasStrictMode(true)` (or `ATLAS_STRICT`) is on.
520
+ *
521
+ * @unsafe Raw SQL fragment — never concatenate user input into `sql`.
522
+ */
523
+ orderByRaw(sql: string): this;
238
524
  /**
239
525
  * `GROUP BY col1, col2, …` (AdonisJS/Lucid `groupBy`). Columns are resolved
240
526
  * through the entity's column map (camelCase → snake_case) like `orderBy`.
241
- * For a raw grouping expression, use a `whereRaw`-style construct via the
242
- * fluent {@link QueryBuilder}.
527
+ * For a grouping expression with no typed form, see {@link groupByRaw}.
243
528
  */
244
529
  groupBy(...columns: string[]): this;
530
+ /**
531
+ * `GROUP BY <raw fragment>` (Lucid/Knex `groupByRaw`) — for groupings with
532
+ * no typed form, e.g. `DATE_TRUNC('day', created_at)`.
533
+ *
534
+ * The fragment keeps its position among the plain `groupBy` terms.
535
+ *
536
+ * **Strict mode**: like {@link whereRaw}, this throws when
537
+ * `setAtlasStrictMode(true)` (or `ATLAS_STRICT`) is on.
538
+ *
539
+ * @unsafe Raw SQL fragment — never concatenate user input into `sql`.
540
+ */
541
+ groupByRaw(sql: string): this;
245
542
  /**
246
543
  * `HAVING <col> <op> ?` — applied after `groupBy` (AdonisJS/Lucid `having`).
247
- * The column is passed verbatim to the Rust HAVING compiler, which quotes a
248
- * plain identifier or accepts an allow-listed aggregate expression
249
- * (`COUNT(*)`, `SUM(col)`, …) it is NOT run through the entity column map,
250
- * so aggregate expressions and result aliases both work.
544
+ * A bare model property is resolved through the entity column map (honouring
545
+ * `@Column({ columnName })`) via {@link #resolveHavingCol}; an aggregate
546
+ * expression (`COUNT(*)`, `SUM(col)`, …) or a result alias is left verbatim so
547
+ * `having` can still reference `withCount`/`withAggregate` aliases.
251
548
  */
252
549
  having(column: string, operator: string, value: unknown): this;
550
+ /** HAVING col IS NULL (Lucid/Knex `havingNull`). */
551
+ havingNull(column: string): this;
552
+ /** HAVING col IS NOT NULL (Lucid/Knex `havingNotNull`). */
553
+ havingNotNull(column: string): this;
554
+ /** HAVING col IN (...) (Lucid/Knex `havingIn`). */
555
+ havingIn(column: string, values: unknown[]): this;
556
+ /** HAVING col NOT IN (...) (Lucid/Knex `havingNotIn`). */
557
+ havingNotIn(column: string, values: unknown[]): this;
558
+ /** HAVING col BETWEEN ? AND ? (Lucid/Knex `havingBetween`). */
559
+ havingBetween(column: string, range: readonly [unknown, unknown]): this;
560
+ /** HAVING col NOT BETWEEN ? AND ? (Lucid/Knex `havingNotBetween`). */
561
+ havingNotBetween(column: string, range: readonly [unknown, unknown]): this;
253
562
  /** `OR HAVING <col> <op> ?` — OR-combined {@link having}. */
254
563
  orHaving(column: string, operator: string, value: unknown): this;
255
564
  /**
@@ -266,15 +575,59 @@ export declare class ModelQuery<T extends BaseEntity> {
266
575
  * appended as a parenthesised UNION branch; its bindings are re-indexed into
267
576
  * the outer parameter list.
268
577
  */
269
- union(query: ModelQuery<BaseEntity>): this;
578
+ union(query: UnionArg): this;
270
579
  /** `UNION ALL (<query>)` — duplicate-preserving {@link union}. */
271
- unionAll(query: ModelQuery<BaseEntity>): this;
580
+ unionAll(query: UnionArg): this;
581
+ /** `INTERSECT (<query>)` — rows present in both (Lucid/Knex `intersect`). */
582
+ intersect(query: UnionArg): this;
583
+ /**
584
+ * `INTERSECT ALL (<query>)` — duplicate-preserving {@link intersect}.
585
+ *
586
+ * Postgres and MySQL only: SQLite's compound operators are UNION, UNION ALL,
587
+ * INTERSECT and EXCEPT — there is no INTERSECT ALL — so the compiler raises
588
+ * `E_UNSUPPORTED` there rather than emitting a syntax error.
589
+ */
590
+ intersectAll(query: UnionArg): this;
591
+ /** `EXCEPT (<query>)` — rows in this query but not the other (Lucid/Knex `except`). */
592
+ except(query: UnionArg): this;
593
+ /** `EXCEPT ALL (<query>)` — duplicate-preserving {@link except}. Not on SQLite; see {@link intersectAll}. */
594
+ exceptAll(query: UnionArg): this;
272
595
  /**
273
596
  * `WITH <name> AS (<query>)` — register a Common Table Expression
274
597
  * (AdonisJS/Lucid `with`). The CTE name is validated as an identifier; the
275
598
  * sub-query is compiled and its bindings are re-indexed into the outer list.
276
599
  */
277
- with(name: string, query: ModelQuery<BaseEntity>): this;
600
+ with(name: string, query: UnionArg): this;
601
+ /**
602
+ * `WITH RECURSIVE <name> AS (<query>)` — a self-referencing CTE
603
+ * (Lucid/Knex `withRecursive`), for trees and graph walks.
604
+ *
605
+ * RECURSIVE is a property of the WITH clause rather than of one CTE, so a
606
+ * single recursive entry makes the whole clause recursive — which is what
607
+ * all three dialects require. Mixing `with()` and `withRecursive()` is fine.
608
+ *
609
+ * The recursive term itself is a `UNION`/`UNION ALL` inside `query`, e.g.
610
+ * an anchor `SELECT` unioned with a select that references `<name>`.
611
+ */
612
+ withRecursive(name: string, query: UnionArg, columns?: string[]): this;
613
+ /**
614
+ * `WITH <name> AS MATERIALIZED (<query>)` — force the CTE to be evaluated
615
+ * once and stashed (Lucid/Knex `withMaterialized`).
616
+ *
617
+ * Postgres 12+ and SQLite 3.35+ only; MySQL has no such hint and the
618
+ * compiler raises `E_UNSUPPORTED` rather than emitting a syntax error.
619
+ */
620
+ withMaterialized(name: string, query: UnionArg): this;
621
+ /** `WITH <name> AS NOT MATERIALIZED (<query>)` — let it be inlined (Lucid/Knex `withNotMaterialized`). See {@link withMaterialized}. */
622
+ withNotMaterialized(name: string, query: UnionArg): this;
623
+ /**
624
+ * `@ManyToMany` only — project EXTRA pivot columns at query time (AdonisJS/Lucid
625
+ * `pivotColumns([...])`), on top of any declared in the relation decorator. Read
626
+ * off each loaded relation as `$extras.pivot_<col>`. Inert on non-m2m relations.
627
+ *
628
+ * userRepo.query().preload('skills', q => q.pivotColumns(['notes']))
629
+ */
630
+ pivotColumns(columns: string[]): this;
278
631
  /**
279
632
  * `@ManyToMany` only — filter loaded relations by a PIVOT-table column
280
633
  * (AdonisJS/Lucid `wherePivot`). Recorded separately from the related-table
@@ -285,15 +638,76 @@ export declare class ModelQuery<T extends BaseEntity> {
285
638
  */
286
639
  wherePivot(column: string, value: unknown): this;
287
640
  wherePivot(column: string, operator: string, value: unknown): this;
288
- /** `@ManyToMany` only `WHERE <pivotCol> IN (...)` on the pivot table (Lucid `wherePivotIn`). */
641
+ /** Alias of {@link wherePivot} (Lucid parity) pivot filters already AND together. */
642
+ andWherePivot(column: string, value: unknown): this;
643
+ andWherePivot(column: string, operator: string, value: unknown): this;
644
+ /**
645
+ * `@ManyToMany` only — OR form of {@link wherePivot} (Lucid parity).
646
+ *
647
+ * The pivot filters are compiled as a parenthesised group, so an OR joins
648
+ * the other pivot filters and cannot escape the `pivot_fk IN (parents)`
649
+ * scoping that makes the preload correct.
650
+ */
651
+ orWherePivot(column: string, value: unknown): this;
652
+ orWherePivot(column: string, operator: string, value: unknown): this;
653
+ /** `@ManyToMany` only — `WHERE <pivotCol> IN (...)` on the pivot table (AdonisJS Lucid `whereInPivot`). */
654
+ whereInPivot(column: string, values: readonly unknown[]): this;
655
+ /** Alias of {@link whereInPivot} (Lucid parity). */
656
+ andWhereInPivot(column: string, values: readonly unknown[]): this;
657
+ /** `@ManyToMany` only — OR form of {@link whereInPivot} (Lucid parity). */
658
+ orWhereInPivot(column: string, values: readonly unknown[]): this;
659
+ /** Alias of {@link whereInPivot} kept for the earlier atlas name. */
289
660
  wherePivotIn(column: string, values: readonly unknown[]): this;
661
+ /**
662
+ * `@ManyToMany` only — negated pivot filter (AdonisJS Lucid `whereNotPivot`).
663
+ * `whereNotPivot(col, value)` → `col != value`; `whereNotPivot(col, op, value)`
664
+ * → the negated comparison (`whereNotPivot('proficiency', '>=', 4)` → `< 4`).
665
+ */
666
+ whereNotPivot(column: string, value: unknown): this;
667
+ whereNotPivot(column: string, operator: string, value: unknown): this;
668
+ /** Alias of {@link whereNotPivot} (Lucid parity). Operator form supported too. */
669
+ andWhereNotPivot(column: string, value: unknown): this;
670
+ andWhereNotPivot(column: string, operator: string, value: unknown): this;
671
+ /** `@ManyToMany` only — OR form of {@link whereNotPivot} (Lucid parity). */
672
+ orWhereNotPivot(column: string, value: unknown): this;
673
+ orWhereNotPivot(column: string, operator: string, value: unknown): this;
674
+ /** `@ManyToMany` only — `WHERE <pivotCol> NOT IN (...)` on the pivot table (AdonisJS Lucid `whereNotInPivot`). */
675
+ whereNotInPivot(column: string, values: readonly unknown[]): this;
676
+ /** Alias of {@link whereNotInPivot} (Lucid parity). */
677
+ andWhereNotInPivot(column: string, values: readonly unknown[]): this;
678
+ /** `@ManyToMany` only — OR form of {@link whereNotInPivot} (Lucid parity). */
679
+ orWhereNotInPivot(column: string, values: readonly unknown[]): this;
680
+ /** `@ManyToMany` only — `WHERE <pivotCol> IS NULL` on the pivot table (Lucid `whereNullPivot`). */
681
+ whereNullPivot(column: string): this;
682
+ /** Alias of {@link whereNullPivot} (Lucid parity). */
683
+ andWhereNullPivot(column: string): this;
684
+ /** `@ManyToMany` only — OR form of {@link whereNullPivot} (Lucid parity). */
685
+ orWhereNullPivot(column: string): this;
686
+ /** `@ManyToMany` only — `WHERE <pivotCol> IS NOT NULL` on the pivot table (Lucid `whereNotNullPivot`). */
687
+ whereNotNullPivot(column: string): this;
688
+ /** Alias of {@link whereNotNullPivot} (Lucid parity). */
689
+ andWhereNotNullPivot(column: string): this;
690
+ /** `@ManyToMany` only — OR form of {@link whereNotNullPivot} (Lucid parity). */
691
+ orWhereNotNullPivot(column: string): this;
290
692
  /** Read-only accessor for pivot constraints — consumed by the m2m preload resolver. */
291
693
  get pivotConstraints(): ReadonlyArray<{
292
694
  column: string;
293
695
  operator: string;
294
696
  value: unknown;
697
+ type: "and" | "or";
295
698
  }>;
699
+ /** Read-only accessor for query-time pivot columns — consumed by the m2m preload resolver. */
700
+ get pivotColumnRequests(): readonly string[];
296
701
  limit(n: number): this;
702
+ /**
703
+ * In a has-many preload callback, cap the related rows PER PARENT (Lucid
704
+ * `groupLimit`) — a plain `.limit()` caps the whole result set across parents.
705
+ * Compiled with a `ROW_NUMBER() OVER (PARTITION BY <fk> …)` window. Pair with
706
+ * {@link groupOrderBy} to pick which N per parent.
707
+ */
708
+ groupLimit(n: number): this;
709
+ /** ORDER BY for the {@link groupLimit} per-parent window (Lucid `groupOrderBy`). */
710
+ groupOrderBy(column: string, direction?: "asc" | "desc"): this;
297
711
  offset(n: number): this;
298
712
  /** Execute and return the first matching entity or null. Fires beforeFind/afterFind. */
299
713
  first(): Promise<T | null>;
@@ -317,13 +731,53 @@ export declare class ModelQuery<T extends BaseEntity> {
317
731
  * get a fresh builder that re-executes.
318
732
  */
319
733
  then<TResult1 = T[], TResult2 = never>(onfulfilled?: ((value: T[]) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null | undefined): Promise<TResult1 | TResult2>;
320
- /** Build SQL + params via the Rust query compiler. */
321
- toSQL(): {
734
+ /**
735
+ * Build SQL via the Rust query compiler (Lucid `toSQL`). `.sql` uses `?`
736
+ * placeholders (Knex-normalized, like Lucid); `.toNative()` yields the native
737
+ * form. Returns `bindings` (Lucid's name) and `params` (atlas's) — same array.
738
+ */
739
+ toSQL(): CompiledStatement;
740
+ /** `{ sql, bindings }` — the compiled native query (Lucid/Knex `toNative`). */
741
+ toNative(): {
322
742
  sql: string;
323
- params: unknown[];
743
+ bindings: unknown[];
324
744
  };
745
+ /** The model class this query targets (Adonis Lucid `query.model`). */
746
+ get model(): new () => T;
747
+ /** Apply `cb` only on the given dialect(s) (Lucid `ifDialect`; Lucid names accepted). */
748
+ ifDialect(dialect: DialectName | DialectName[], cb: (query: this) => void): this;
749
+ /** Apply `cb` on every dialect EXCEPT the given one(s) (Lucid `unlessDialect`). */
750
+ unlessDialect(dialect: DialectName | DialectName[], cb: (query: this) => void): this;
751
+ /** Prepend a `/* … *​/` SQL comment to the compiled query (Lucid/Knex `comment`). */
752
+ comment(text: string): this;
753
+ /**
754
+ * Set a caller-facing statement timeout in milliseconds (Lucid `timeout(ms)`).
755
+ * The awaiting promise rejects after `ms` on the primary result fetch. With
756
+ * `{ cancel: true }` a SERVER-side statement timeout is also applied — Postgres
757
+ * `statement_timeout`, MySQL `MAX_EXECUTION_TIME` (SELECT) — so the server
758
+ * aborts the query, not just the client. (SQLite has no server timeout; the
759
+ * client race applies.) Called with no argument it clears the timeout.
760
+ */
761
+ timeout(ms?: number, options?: {
762
+ cancel?: boolean;
763
+ }): this;
325
764
  /** Execute and return all matching entities, with preloaded relations. Fires beforeFetch/afterFetch. */
326
765
  exec(): Promise<T[]>;
766
+ /**
767
+ * Execute and return PLAIN row objects (raw snake_case DB columns), skipping
768
+ * model hydration, `@column({ consume })`, dirty-tracking and preloads —
769
+ * AdonisJS Lucid `pojo()`. Fast read path for reports/exports where model
770
+ * instances aren't needed.
771
+ */
772
+ pojo<R = Record<string, unknown>>(): Promise<R[]>;
773
+ /**
774
+ * Thread arbitrary context onto every instance this query hydrates, exposed as
775
+ * `entity.$sideloaded` (AdonisJS Lucid `sideload`) — e.g. the current tenant or
776
+ * user, so hooks/computed can read it. REPLACES the current sideloaded data by
777
+ * default (Lucid); pass `merge = true` to merge instead. The data also
778
+ * propagates to preloaded relation queries. Chainable.
779
+ */
780
+ sideload(values: Record<string, unknown>, merge?: boolean): this;
327
781
  /**
328
782
  * Resolve a relation to its table + correlated join predicate and return an
329
783
  * `ExistsWhere` clause. Used by whereHas / has / doesntHave / whereDoesntHave.
@@ -336,13 +790,32 @@ export declare class ModelQuery<T extends BaseEntity> {
336
790
  * without GROUP BY — SQL treats the whole sub-result as one group, so
337
791
  * COUNT(*) against the correlated rows returns the right number.
338
792
  */
339
- /** `INNER JOIN <table> ON <left> = <right>`. */
793
+ /** `INNER JOIN` alias of {@link innerJoin} (Lucid/Knex `join`). */
794
+ join(table: string, left: string, right: string): this;
795
+ join(table: string, left: string, operator: string, right: string): this;
796
+ join(table: string, build: (j: JoinBuilder) => void): this;
797
+ /** `INNER JOIN <table> ON <left> [op] <right>` or a callback `ON` builder. */
340
798
  innerJoin(table: string, left: string, right: string): this;
799
+ innerJoin(table: string, left: string, operator: string, right: string): this;
341
800
  innerJoin(table: string, build: (j: JoinBuilder) => void): this;
342
801
  leftJoin(table: string, left: string, right: string): this;
802
+ leftJoin(table: string, left: string, operator: string, right: string): this;
343
803
  leftJoin(table: string, build: (j: JoinBuilder) => void): this;
804
+ /** `LEFT OUTER JOIN` — alias of {@link leftJoin} (Lucid/Knex `leftOuterJoin`). */
805
+ leftOuterJoin(table: string, left: string, right: string): this;
806
+ leftOuterJoin(table: string, left: string, operator: string, right: string): this;
807
+ leftOuterJoin(table: string, build: (j: JoinBuilder) => void): this;
344
808
  rightJoin(table: string, left: string, right: string): this;
809
+ rightJoin(table: string, left: string, operator: string, right: string): this;
345
810
  rightJoin(table: string, build: (j: JoinBuilder) => void): this;
811
+ /** `RIGHT OUTER JOIN` — alias of {@link rightJoin} (Lucid/Knex `rightOuterJoin`). */
812
+ rightOuterJoin(table: string, left: string, right: string): this;
813
+ rightOuterJoin(table: string, left: string, operator: string, right: string): this;
814
+ rightOuterJoin(table: string, build: (j: JoinBuilder) => void): this;
815
+ /** `FULL OUTER JOIN` (Lucid/Knex `fullOuterJoin`; Postgres — MySQL/SQLite lack it). */
816
+ fullOuterJoin(table: string, left: string, right: string): this;
817
+ fullOuterJoin(table: string, left: string, operator: string, right: string): this;
818
+ fullOuterJoin(table: string, build: (j: JoinBuilder) => void): this;
346
819
  crossJoin(table: string): this;
347
820
  /**
348
821
  * **⚠ UNSAFE** — append a raw JOIN fragment verbatim. No identifier quoting,
@@ -360,7 +833,7 @@ export declare class ModelQuery<T extends BaseEntity> {
360
833
  *
361
834
  * @unsafe Raw SQL fragment — never concatenate user input into `fragment`.
362
835
  */
363
- joinRaw(fragment: string): this;
836
+ joinRaw(fragment: string, bindings?: readonly unknown[]): this;
364
837
  /**
365
838
  * **SAFE** helper that builds an `INNER JOIN <table> ON <left> = <right>`
366
839
  * with dialect-correct identifier quoting on both sides. Thin sugar over
@@ -373,9 +846,31 @@ export declare class ModelQuery<T extends BaseEntity> {
373
846
  * you need multiple join conditions.
374
847
  */
375
848
  joinOn(table: string, left: string, right: string): this;
376
- distinct(): this;
849
+ /**
850
+ * SELECT DISTINCT (Lucid/Knex `distinct`). With columns, those replace the
851
+ * projection too — `distinct('a', 'b')` ≈ `SELECT DISTINCT a, b`.
852
+ */
853
+ distinct(...columns: string[]): this;
854
+ /**
855
+ * `SELECT DISTINCT ON (cols) …` — keep the first row per distinct set of
856
+ * `columns` (Lucid/Knex `distinctOn`). Takes precedence over
857
+ * {@link distinct}.
858
+ *
859
+ * Postgres-only, and the compiler refuses it elsewhere: MySQL and SQLite
860
+ * would parse `DISTINCT (a, b)` as a plain DISTINCT over a row value and
861
+ * return a *different* result set rather than fail — a silent wrong answer
862
+ * is worse than an error.
863
+ *
864
+ * Postgres also requires the leading `ORDER BY` terms to match `columns`;
865
+ * that is left to the database to enforce.
866
+ */
867
+ distinctOn(...columns: string[]): this;
377
868
  /** `SELECT COUNT(DISTINCT col)`. */
378
869
  countDistinct(column: string): Promise<number>;
870
+ /** `SUM(DISTINCT col)` (Lucid parity). */
871
+ sumDistinct(column: string): Promise<number | null>;
872
+ /** `AVG(DISTINCT col)` (Lucid parity). */
873
+ avgDistinct(column: string): Promise<number | null>;
379
874
  /** `SELECT 1 FROM ... LIMIT 1` — returns boolean. */
380
875
  exists(): Promise<boolean>;
381
876
  doesntExist(): Promise<boolean>;
@@ -386,7 +881,7 @@ export declare class ModelQuery<T extends BaseEntity> {
386
881
  /** Alias for `apply` — Lucid compatibility. */
387
882
  withScopes(callback: (scopes: Record<string, (...args: unknown[]) => ModelQuery<T>>) => void): this;
388
883
  if<V>(condition: V | undefined | null | false, ifFn: (q: this, value: V) => void, elseFn?: (q: this) => void): this;
389
- unless<V>(condition: V | undefined | null | false, fn: (q: this) => void): this;
884
+ unless<V>(condition: V | undefined | null | false, fn: (q: this) => void, elseFn?: (q: this) => void): this;
390
885
  /** Offset-based paginator. */
391
886
  paginate(page: number, perPage: number): Promise<Paginator<T>>;
392
887
  /**
@@ -414,20 +909,61 @@ export declare class ModelQuery<T extends BaseEntity> {
414
909
  /** Thin alias for `offset((page-1)*perPage).limit(perPage)`. */
415
910
  forPage(page: number, perPage: number): this;
416
911
  debug(flag?: boolean): this;
912
+ /**
913
+ * Attach arbitrary metadata to the `db:query` event this query emits (Adonis
914
+ * Lucid `reporterData`) — request id, user id, feature flag, … A listener
915
+ * reads it off `event.reporterData`. Repeated calls merge. Setting it also
916
+ * forces emission (like {@link debug}), so the data actually reaches a listener.
917
+ */
918
+ reporterData(data: Record<string, unknown>): this;
417
919
  /** Returns the compiled SQL with bindings interpolated as dialect-safe literals. */
418
920
  toQuery(): string;
419
921
  /** Deep clone of this query — mutations on the clone never affect the original. */
420
922
  clone(): ModelQuery<T>;
421
- /** Execute a fluent UPDATE. Returns affected rows (or rows when `returning` is set). */
422
- update(patch: Record<string, unknown>, returning?: string[]): Promise<number | Record<string, unknown>[]>;
423
- /** Execute a fluent DELETE. Returns affected rows (or rows when `returning` is set). */
424
- delete(returning?: string[]): Promise<number | Record<string, unknown>[]>;
425
- increment(column: string, amount: number): Promise<number>;
923
+ /**
924
+ * Execute a fluent UPDATE (Lucid/Knex `update`). Accepts a `{ col: value }` map
925
+ * OR a single `(column, value)` pair; a value may be a `db.raw(...)` expression.
926
+ * Returns affected rows (or the RETURNING rows when `returning` is set).
927
+ */
928
+ update(column: string, value: unknown): DmlBuilder<number | Record<string, unknown>[]>;
929
+ update(patch: Record<string, unknown>, returning?: string[]): DmlBuilder<number | Record<string, unknown>[]>;
930
+ /**
931
+ * Execute a fluent DELETE. For a `@SoftDeletes` model this SOFT-deletes the
932
+ * scoped rows (stamps `deleted_at`) — consistent with the entity-level
933
+ * `delete()`; use {@link forceDelete} for a hard `DELETE`. For a non-soft-delete
934
+ * model it issues a hard `DELETE`. Returns affected rows (or rows when
935
+ * `returning` is set).
936
+ */
937
+ delete(returning?: string[]): DmlBuilder<number | Record<string, unknown>[]>;
938
+ /** Hard `DELETE` of the scoped rows, bypassing `@SoftDeletes` (AdonisJS/Lucid `forceDelete`). */
939
+ forceDelete(returning?: string[]): DmlBuilder<number | Record<string, unknown>[]>;
940
+ /**
941
+ * Bulk restore: clear `deleted_at` on the trashed rows matching the user's
942
+ * predicates (the soft-delete counterpart of {@link delete}). No-op count `0`
943
+ * on a non-soft-delete model. Independent of the current soft-scope — it always
944
+ * targets trashed rows (`deleted_at IS NOT NULL`).
945
+ */
946
+ restore(returning?: string[]): DmlBuilder<number | Record<string, unknown>[]>;
947
+ increment(column: string, amount?: number): Promise<number>;
426
948
  increment(patch: Record<string, number>): Promise<number>;
427
- decrement(column: string, amount: number): Promise<number>;
949
+ decrement(column: string, amount?: number): Promise<number>;
428
950
  decrement(patch: Record<string, number>): Promise<number>;
429
951
  forUpdate(): this;
430
952
  forShare(): this;
953
+ /** Postgres `FOR NO KEY UPDATE` — a weaker lock that doesn't block FK checks (AdonisJS/Knex). */
954
+ forNoKeyUpdate(): this;
955
+ /** Postgres `FOR KEY SHARE` — the weakest share lock (AdonisJS/Knex). */
956
+ forKeyShare(): this;
957
+ /**
958
+ * Append `SKIP LOCKED` to the lock clause — locked rows are skipped instead of
959
+ * waited on (AdonisJS/Knex). Requires a base lock (`forUpdate`/`forShare`/…).
960
+ */
961
+ skipLocked(): this;
962
+ /**
963
+ * Append `NOWAIT` to the lock clause — error immediately instead of waiting on
964
+ * a locked row (AdonisJS/Knex). Requires a base lock (`forUpdate`/`forShare`/…).
965
+ */
966
+ noWait(): this;
431
967
  }
432
968
  export {};
433
969
  //# sourceMappingURL=ModelQuery.d.ts.map