velocious 1.0.515 → 1.0.516

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 (198) hide show
  1. package/README.md +3 -3
  2. package/build/background-jobs/cron-expression.js +9 -9
  3. package/build/background-jobs/forked-runner-child.js +1 -1
  4. package/build/background-jobs/job-runner.js +21 -15
  5. package/build/background-jobs/json-socket.js +4 -0
  6. package/build/background-jobs/main.js +180 -18
  7. package/build/background-jobs/status-reporter.js +12 -5
  8. package/build/background-jobs/store.js +132 -50
  9. package/build/background-jobs/types.js +11 -3
  10. package/build/background-jobs/worker.js +9 -5
  11. package/build/beacon/client.js +13 -6
  12. package/build/configuration.js +31 -29
  13. package/build/controller.js +9 -3
  14. package/build/database/drivers/sqlite/base.js +1 -1
  15. package/build/database/drivers/sqlite/index.js +15 -14
  16. package/build/database/migrations-ledger.js +16 -16
  17. package/build/database/query/where-model-class-hash.js +2 -0
  18. package/build/database/query/with-count.js +1 -1
  19. package/build/database/record/acts-as-list.js +2 -2
  20. package/build/database/record/auditing.js +23 -6
  21. package/build/database/record/index.js +7 -7
  22. package/build/database/record/validators/uniqueness.js +3 -3
  23. package/build/database/tenants/data-copier.js +23 -23
  24. package/build/database/tenants/schema-cloner.js +27 -27
  25. package/build/environment-handlers/browser.js +0 -1
  26. package/build/environment-handlers/node/cli/commands/background-jobs-runner.js +2 -1
  27. package/build/environment-handlers/node/cli/commands/lint/relationships.js +2 -2
  28. package/build/environment-handlers/node.js +1 -1
  29. package/build/frontend-model-controller.js +26 -18
  30. package/build/frontend-models/base.js +5 -5
  31. package/build/frontend-models/query.js +12 -12
  32. package/build/http-server/client/index.js +61 -15
  33. package/build/http-server/client/response.js +17 -1
  34. package/build/http-server/client/websocket-session.js +13 -13
  35. package/build/http-server/server-client.js +96 -0
  36. package/build/http-server/websocket-channel.js +12 -11
  37. package/build/http-server/websocket-connection.js +12 -11
  38. package/build/http-server/websocket-events-host.js +1 -1
  39. package/build/http-server/worker-handler/in-process.js +48 -9
  40. package/build/http-server/worker-handler/index.js +67 -7
  41. package/build/http-server/worker-handler/worker-thread.js +68 -0
  42. package/build/src/background-jobs/cron-expression.d.ts +2 -2
  43. package/build/src/background-jobs/cron-expression.js +10 -10
  44. package/build/src/background-jobs/forked-runner-child.js +2 -2
  45. package/build/src/background-jobs/job-runner.d.ts +5 -1
  46. package/build/src/background-jobs/job-runner.d.ts.map +1 -1
  47. package/build/src/background-jobs/job-runner.js +22 -16
  48. package/build/src/background-jobs/json-socket.d.ts +4 -0
  49. package/build/src/background-jobs/json-socket.d.ts.map +1 -1
  50. package/build/src/background-jobs/json-socket.js +5 -1
  51. package/build/src/background-jobs/main.d.ts +62 -10
  52. package/build/src/background-jobs/main.d.ts.map +1 -1
  53. package/build/src/background-jobs/main.js +171 -19
  54. package/build/src/background-jobs/status-reporter.d.ts +6 -2
  55. package/build/src/background-jobs/status-reporter.d.ts.map +1 -1
  56. package/build/src/background-jobs/status-reporter.js +13 -6
  57. package/build/src/background-jobs/store.d.ts +48 -25
  58. package/build/src/background-jobs/store.d.ts.map +1 -1
  59. package/build/src/background-jobs/store.js +123 -50
  60. package/build/src/background-jobs/types.d.ts +36 -3
  61. package/build/src/background-jobs/types.d.ts.map +1 -1
  62. package/build/src/background-jobs/types.js +12 -4
  63. package/build/src/background-jobs/worker.d.ts +7 -5
  64. package/build/src/background-jobs/worker.d.ts.map +1 -1
  65. package/build/src/background-jobs/worker.js +10 -6
  66. package/build/src/beacon/client.d.ts +6 -3
  67. package/build/src/beacon/client.d.ts.map +1 -1
  68. package/build/src/beacon/client.js +14 -7
  69. package/build/src/configuration-types.d.ts +1 -1
  70. package/build/src/configuration.d.ts +31 -29
  71. package/build/src/configuration.d.ts.map +1 -1
  72. package/build/src/configuration.js +32 -30
  73. package/build/src/controller.d.ts +3 -0
  74. package/build/src/controller.d.ts.map +1 -1
  75. package/build/src/controller.js +9 -4
  76. package/build/src/database/drivers/sqlite/base.js +2 -2
  77. package/build/src/database/drivers/sqlite/index.d.ts +7 -6
  78. package/build/src/database/drivers/sqlite/index.d.ts.map +1 -1
  79. package/build/src/database/drivers/sqlite/index.js +16 -15
  80. package/build/src/database/migrations-ledger.d.ts +16 -16
  81. package/build/src/database/migrations-ledger.js +17 -17
  82. package/build/src/database/query/where-model-class-hash.d.ts.map +1 -1
  83. package/build/src/database/query/where-model-class-hash.js +3 -1
  84. package/build/src/database/query/with-count.js +2 -2
  85. package/build/src/database/record/acts-as-list.js +3 -3
  86. package/build/src/database/record/auditing.d.ts +1 -1
  87. package/build/src/database/record/auditing.d.ts.map +1 -1
  88. package/build/src/database/record/auditing.js +24 -7
  89. package/build/src/database/record/index.d.ts +7 -7
  90. package/build/src/database/record/index.js +8 -8
  91. package/build/src/database/record/validators/uniqueness.d.ts +3 -3
  92. package/build/src/database/record/validators/uniqueness.js +4 -4
  93. package/build/src/database/tenants/data-copier.d.ts +18 -18
  94. package/build/src/database/tenants/data-copier.js +24 -24
  95. package/build/src/database/tenants/schema-cloner.d.ts +27 -27
  96. package/build/src/database/tenants/schema-cloner.js +28 -28
  97. package/build/src/environment-handlers/browser.d.ts +9 -0
  98. package/build/src/environment-handlers/browser.d.ts.map +1 -1
  99. package/build/src/environment-handlers/browser.js +1 -2
  100. package/build/src/environment-handlers/node/cli/commands/background-jobs-runner.d.ts.map +1 -1
  101. package/build/src/environment-handlers/node/cli/commands/background-jobs-runner.js +3 -2
  102. package/build/src/environment-handlers/node/cli/commands/lint/relationships.js +3 -3
  103. package/build/src/environment-handlers/node.js +2 -2
  104. package/build/src/frontend-model-controller.d.ts +9 -8
  105. package/build/src/frontend-model-controller.d.ts.map +1 -1
  106. package/build/src/frontend-model-controller.js +26 -19
  107. package/build/src/frontend-models/base.d.ts +4 -4
  108. package/build/src/frontend-models/base.d.ts.map +1 -1
  109. package/build/src/frontend-models/base.js +6 -6
  110. package/build/src/frontend-models/query.d.ts +7 -7
  111. package/build/src/frontend-models/query.js +13 -13
  112. package/build/src/http-server/client/index.d.ts +23 -1
  113. package/build/src/http-server/client/index.d.ts.map +1 -1
  114. package/build/src/http-server/client/index.js +55 -17
  115. package/build/src/http-server/client/response.d.ts +11 -1
  116. package/build/src/http-server/client/response.d.ts.map +1 -1
  117. package/build/src/http-server/client/response.js +16 -2
  118. package/build/src/http-server/client/websocket-session.d.ts +13 -13
  119. package/build/src/http-server/client/websocket-session.js +14 -14
  120. package/build/src/http-server/server-client.d.ts +13 -0
  121. package/build/src/http-server/server-client.d.ts.map +1 -1
  122. package/build/src/http-server/server-client.js +94 -1
  123. package/build/src/http-server/websocket-channel.d.ts +12 -11
  124. package/build/src/http-server/websocket-channel.d.ts.map +1 -1
  125. package/build/src/http-server/websocket-channel.js +13 -12
  126. package/build/src/http-server/websocket-connection.d.ts +12 -11
  127. package/build/src/http-server/websocket-connection.d.ts.map +1 -1
  128. package/build/src/http-server/websocket-connection.js +13 -12
  129. package/build/src/http-server/websocket-events-host.d.ts +1 -1
  130. package/build/src/http-server/websocket-events-host.js +2 -2
  131. package/build/src/http-server/worker-handler/in-process.d.ts +2 -0
  132. package/build/src/http-server/worker-handler/in-process.d.ts.map +1 -1
  133. package/build/src/http-server/worker-handler/in-process.js +42 -11
  134. package/build/src/http-server/worker-handler/index.d.ts +21 -0
  135. package/build/src/http-server/worker-handler/index.d.ts.map +1 -1
  136. package/build/src/http-server/worker-handler/index.js +61 -7
  137. package/build/src/http-server/worker-handler/worker-thread.d.ts +30 -0
  138. package/build/src/http-server/worker-handler/worker-thread.d.ts.map +1 -1
  139. package/build/src/http-server/worker-handler/worker-thread.js +61 -1
  140. package/build/src/sync/device-identity.d.ts +2 -2
  141. package/build/src/sync/device-identity.d.ts.map +1 -1
  142. package/build/src/sync/device-identity.js +4 -4
  143. package/build/src/sync/local-mutation-log.d.ts +0 -1
  144. package/build/src/sync/local-mutation-log.d.ts.map +1 -1
  145. package/build/src/sync/local-mutation-log.js +1 -2
  146. package/build/src/tenants/tenant-iterator.d.ts +8 -8
  147. package/build/src/tenants/tenant-iterator.js +9 -9
  148. package/build/src/tenants/tenant.d.ts +6 -6
  149. package/build/src/tenants/tenant.js +7 -7
  150. package/build/sync/device-identity.js +3 -3
  151. package/build/sync/local-mutation-log.js +0 -1
  152. package/build/tenants/tenant-iterator.js +8 -8
  153. package/build/tenants/tenant.js +6 -6
  154. package/package.json +2 -2
  155. package/src/background-jobs/cron-expression.js +9 -9
  156. package/src/background-jobs/forked-runner-child.js +1 -1
  157. package/src/background-jobs/job-runner.js +21 -15
  158. package/src/background-jobs/json-socket.js +4 -0
  159. package/src/background-jobs/main.js +180 -18
  160. package/src/background-jobs/status-reporter.js +12 -5
  161. package/src/background-jobs/store.js +132 -50
  162. package/src/background-jobs/types.js +11 -3
  163. package/src/background-jobs/worker.js +9 -5
  164. package/src/beacon/client.js +13 -6
  165. package/src/configuration.js +31 -29
  166. package/src/controller.js +9 -3
  167. package/src/database/drivers/sqlite/base.js +1 -1
  168. package/src/database/drivers/sqlite/index.js +15 -14
  169. package/src/database/migrations-ledger.js +16 -16
  170. package/src/database/query/where-model-class-hash.js +2 -0
  171. package/src/database/query/with-count.js +1 -1
  172. package/src/database/record/acts-as-list.js +2 -2
  173. package/src/database/record/auditing.js +23 -6
  174. package/src/database/record/index.js +7 -7
  175. package/src/database/record/validators/uniqueness.js +3 -3
  176. package/src/database/tenants/data-copier.js +23 -23
  177. package/src/database/tenants/schema-cloner.js +27 -27
  178. package/src/environment-handlers/browser.js +0 -1
  179. package/src/environment-handlers/node/cli/commands/background-jobs-runner.js +2 -1
  180. package/src/environment-handlers/node/cli/commands/lint/relationships.js +2 -2
  181. package/src/environment-handlers/node.js +1 -1
  182. package/src/frontend-model-controller.js +26 -18
  183. package/src/frontend-models/base.js +5 -5
  184. package/src/frontend-models/query.js +12 -12
  185. package/src/http-server/client/index.js +61 -15
  186. package/src/http-server/client/response.js +17 -1
  187. package/src/http-server/client/websocket-session.js +13 -13
  188. package/src/http-server/server-client.js +96 -0
  189. package/src/http-server/websocket-channel.js +12 -11
  190. package/src/http-server/websocket-connection.js +12 -11
  191. package/src/http-server/websocket-events-host.js +1 -1
  192. package/src/http-server/worker-handler/in-process.js +48 -9
  193. package/src/http-server/worker-handler/index.js +67 -7
  194. package/src/http-server/worker-handler/worker-thread.js +68 -0
  195. package/src/sync/device-identity.js +3 -3
  196. package/src/sync/local-mutation-log.js +0 -1
  197. package/src/tenants/tenant-iterator.js +8 -8
  198. package/src/tenants/tenant.js +6 -6
@@ -74,9 +74,9 @@ export default class VelociousDatabaseRecordValidatorsUniqueness extends Base {
74
74
  * `new Task({project})`, the FK (`projectId`) is only flushed onto
75
75
  * the attribute store during save — but the relationship object is
76
76
  * already loaded and carries the id we need for the WHERE clause.
77
- * @param {import("../index.js").default} model
77
+ * @param {import("../index.js").default} model - Record whose loaded relationship may supply the scope value.
78
78
  * @param {string} scopeColumn - camelCase attribute name (e.g. `"projectId"`).
79
- * @returns {string | number | null}
79
+ * @returns {string | number | null} - Value normalized for comparison.
80
80
  */
81
81
  _resolveScopeValueFromRelationship(model, scopeColumn) {
82
82
  const modelClass = /** @type {typeof import("../index.js").default} */ (model.constructor)
@@ -106,7 +106,7 @@ export default class VelociousDatabaseRecordValidatorsUniqueness extends Base {
106
106
  * Normalize the `scope` option into an array of attribute names.
107
107
  * Supports string (`"userId"`), array of strings (`["userId", "projectId"]`),
108
108
  * or absent (empty array — no scope, original single-column behavior).
109
- * @returns {string[]}
109
+ * @returns {string[]} - Columns participating in the uniqueness check.
110
110
  */
111
111
  _normalizeScopeColumns() {
112
112
  const scope = this.args?.scope
@@ -6,9 +6,9 @@ const DEFAULT_QUERY_CHUNK_SIZE = 500
6
6
  /**
7
7
  * Splits an array into chunks of at most `chunkSize` items.
8
8
  * @template T
9
- * @param {T[]} values
10
- * @param {number} chunkSize
11
- * @returns {T[][]}
9
+ * @param {T[]} values - Ordered items to partition.
10
+ * @param {number} chunkSize - Maximum items per chunk.
11
+ * @returns {T[][]} - Consecutive chunks preserving input order.
12
12
  */
13
13
  function chunks(values, chunkSize) {
14
14
  const chunkedValues = []
@@ -22,8 +22,8 @@ function chunks(values, chunkSize) {
22
22
 
23
23
  /**
24
24
  * Stringifies values and returns the distinct, non-blank ones, preserving first-seen order.
25
- * @param {unknown[]} values
26
- * @returns {string[]}
25
+ * @param {unknown[]} values - Candidate database identifiers to stringify and deduplicate.
26
+ * @returns {string[]} - Distinct non-blank identifiers in first-seen order.
27
27
  */
28
28
  function uniqueStrings(values) {
29
29
  return Array.from(new Set(values.map((value) => String(value)).filter((value) => value.trim())))
@@ -60,7 +60,7 @@ export default class DataCopier {
60
60
  * insertChunkSize?: number,
61
61
  * queryChunkSize?: number,
62
62
  * onProgress?: (message: string) => void
63
- * }} args
63
+ * }} args - Source, target, traversal plan, chunk limits, and progress handler.
64
64
  */
65
65
  constructor({sourceDb, targetDb, tablePlan, idColumn = "id", insertChunkSize = DEFAULT_INSERT_CHUNK_SIZE, queryChunkSize = DEFAULT_QUERY_CHUNK_SIZE, onProgress}) {
66
66
  this.sourceDb = sourceDb
@@ -77,8 +77,8 @@ export default class DataCopier {
77
77
  * returns the copied source rows keyed by table name. The target's current tenant rows
78
78
  * are deleted (children first) and the source rows inserted (parents first) in a single
79
79
  * target transaction with foreign keys disabled.
80
- * @param {string} keyValue
81
- * @returns {Promise<Map<string, Record<string, unknown>[]>>}
80
+ * @param {string} keyValue - Tenant key selecting the rows to copy.
81
+ * @returns {Promise<Map<string, Record<string, unknown>[]>>} - Copied source rows grouped by table name.
82
82
  */
83
83
  async copy(keyValue) {
84
84
  const sourceRowsByTableName = await this.loadRows(this.sourceDb, keyValue)
@@ -125,9 +125,9 @@ export default class DataCopier {
125
125
  * Loads the rows for `keyValue` for every table in the plan from `db`, resolving
126
126
  * parent-scoped tables from the ids already selected for their parent table. Used for
127
127
  * both the source rows to copy and the target's current tenant rows to delete.
128
- * @param {import("../drivers/base.js").default} db
129
- * @param {string} keyValue
130
- * @returns {Promise<Map<string, Record<string, unknown>[]>>}
128
+ * @param {import("../drivers/base.js").default} db - Source or target database to traverse.
129
+ * @param {string} keyValue - Tenant key selecting the root plan rows.
130
+ * @returns {Promise<Map<string, Record<string, unknown>[]>>} - Loaded rows grouped by table name.
131
131
  */
132
132
  async loadRows(db, keyValue) {
133
133
  /** @type {Map<string, string[]>} */
@@ -175,8 +175,8 @@ export default class DataCopier {
175
175
 
176
176
  /**
177
177
  * Selects all rows of `tableName` in `db` whose `columnName` is in `values`, chunked.
178
- * @param {{columnName: string, db: import("../drivers/base.js").default, tableName: string, values: string[]}} args
179
- * @returns {Promise<Record<string, unknown>[]>}
178
+ * @param {{columnName: string, db: import("../drivers/base.js").default, tableName: string, values: string[]}} args - Table, column, database, and values for the chunked lookup.
179
+ * @returns {Promise<Record<string, unknown>[]>} - Rows matching the supplied column values.
180
180
  */
181
181
  async queryRowsByColumn({columnName, db, tableName, values}) {
182
182
  const normalizedValues = uniqueStrings(values)
@@ -201,7 +201,7 @@ export default class DataCopier {
201
201
  /**
202
202
  * Deletes the matching target rows for every plan table, children before parents, so the
203
203
  * reinsert that follows starts from a clean slate without violating foreign keys.
204
- * @param {Map<string, Record<string, unknown>[]>} rowsByTableName
204
+ * @param {Map<string, Record<string, unknown>[]>} rowsByTableName - Rows grouped by table name.
205
205
  * @returns {Promise<void>}
206
206
  */
207
207
  async deleteTargetRows(rowsByTableName) {
@@ -227,7 +227,7 @@ export default class DataCopier {
227
227
  /**
228
228
  * Inserts the loaded source rows into the target for every plan table, parents before
229
229
  * children, chunked to bound statement size.
230
- * @param {Map<string, Record<string, unknown>[]>} rowsByTableName
230
+ * @param {Map<string, Record<string, unknown>[]>} rowsByTableName - Rows grouped by table name.
231
231
  * @returns {Promise<void>}
232
232
  */
233
233
  async insertTargetRows(rowsByTableName) {
@@ -256,9 +256,9 @@ export default class DataCopier {
256
256
 
257
257
  /**
258
258
  * Quotes and comma-joins values for an SQL `IN (...)` list against the given database.
259
- * @param {import("../drivers/base.js").default} db
260
- * @param {string[]} values
261
- * @returns {string}
259
+ * @param {import("../drivers/base.js").default} db - Database whose quoting rules format the values.
260
+ * @param {string[]} values - Values to quote for the `IN` list.
261
+ * @returns {string} - Quoted SQL value list.
262
262
  */
263
263
  quotedValuesSql(db, values) {
264
264
  return values.map((value) => db.quote(value)).join(", ")
@@ -266,9 +266,9 @@ export default class DataCopier {
266
266
 
267
267
  /**
268
268
  * Runs a query without per-query logging, used for the high-volume copy statements.
269
- * @param {import("../drivers/base.js").default} db
270
- * @param {string} sql
271
- * @returns {Promise<Record<string, unknown>[]>}
269
+ * @param {import("../drivers/base.js").default} db - Database on which to execute the copy query.
270
+ * @param {string} sql - Copy-related SQL statement to execute quietly.
271
+ * @returns {Promise<Record<string, unknown>[]>} - Query result rows.
272
272
  */
273
273
  async executeQuietQuery(db, sql) {
274
274
  return await db.query(sql, {logQuery: false})
@@ -276,7 +276,7 @@ export default class DataCopier {
276
276
 
277
277
  /**
278
278
  * Inserts column-aligned row tuples into a table without per-query logging.
279
- * @param {{columns: string[], db: import("../drivers/base.js").default, rows: Array<Array<unknown>>, tableName: string}} args
279
+ * @param {{columns: string[], db: import("../drivers/base.js").default, rows: Array<Array<unknown>>, tableName: string}} args - Destination table and column-aligned row values to insert.
280
280
  * @returns {Promise<void>}
281
281
  */
282
282
  async insertRowsQuietly({columns, db, rows, tableName}) {
@@ -285,7 +285,7 @@ export default class DataCopier {
285
285
 
286
286
  /**
287
287
  * Forwards a progress message to the optional `onProgress` callback when one was given.
288
- * @param {string} message
288
+ * @param {string} message - Copy progress message to forward when reporting is enabled.
289
289
  * @returns {void}
290
290
  */
291
291
  reportProgress(message) {
@@ -31,7 +31,7 @@ const TEXT_TYPE_RANKS = {
31
31
  export default class SchemaCloner {
32
32
  /**
33
33
  * Creates a cloner that copies table structure from `sourceDb` into `targetDb`.
34
- * @param {{sourceDb: import("../drivers/base.js").default, targetDb: import("../drivers/base.js").default}} args
34
+ * @param {{sourceDb: import("../drivers/base.js").default, targetDb: import("../drivers/base.js").default}} args - Databases to clone structure from and into.
35
35
  */
36
36
  constructor({sourceDb, targetDb}) {
37
37
  this.sourceDb = sourceDb
@@ -41,7 +41,7 @@ export default class SchemaCloner {
41
41
  /**
42
42
  * Clones every given table from the source into the target, then baselines the
43
43
  * target's ledger so the cloned schema is recorded as already-migrated.
44
- * @param {string[]} tableNames
44
+ * @param {string[]} tableNames - Source tables whose structure should be cloned.
45
45
  * @returns {Promise<void>}
46
46
  */
47
47
  async syncTables(tableNames) {
@@ -55,7 +55,7 @@ export default class SchemaCloner {
55
55
  /**
56
56
  * Clones a single table from the source into the target, creating it or adding and
57
57
  * widening columns and indexes as needed.
58
- * @param {string} tableName
58
+ * @param {string} tableName - Source table to synchronize with the target.
59
59
  * @returns {Promise<void>}
60
60
  */
61
61
  async syncTable(tableName) {
@@ -82,7 +82,7 @@ export default class SchemaCloner {
82
82
  /**
83
83
  * Creates the table in the target from the source table's columns and its
84
84
  * non-primary-key indexes.
85
- * @param {{sourceTable: import("../drivers/base-table.js").default, tableName: string}} args
85
+ * @param {{sourceTable: import("../drivers/base-table.js").default, tableName: string}} args - Source table metadata and target table name.
86
86
  * @returns {Promise<void>}
87
87
  */
88
88
  async createTargetTable({sourceTable, tableName}) {
@@ -105,7 +105,7 @@ export default class SchemaCloner {
105
105
  /**
106
106
  * Adds columns present on the source but missing from the target, and widens
107
107
  * too-narrow target text columns.
108
- * @param {{sourceTable: import("../drivers/base-table.js").default, tableName: string}} args
108
+ * @param {{sourceTable: import("../drivers/base-table.js").default, tableName: string}} args - Source table metadata and target table name.
109
109
  * @returns {Promise<boolean>} Whether any column was added or widened.
110
110
  */
111
111
  async ensureTargetColumns({sourceTable, tableName}) {
@@ -154,7 +154,7 @@ export default class SchemaCloner {
154
154
  * Creates non-primary-key indexes present on the source but missing from the target,
155
155
  * and replaces target indexes whose definition (columns or uniqueness) drifted from
156
156
  * the source.
157
- * @param {{sourceTable: import("../drivers/base-table.js").default, tableName: string}} args
157
+ * @param {{sourceTable: import("../drivers/base-table.js").default, tableName: string}} args - Source table metadata and target table name.
158
158
  * @returns {Promise<void>}
159
159
  */
160
160
  async ensureTargetIndexes({sourceTable, tableName}) {
@@ -230,7 +230,7 @@ export default class SchemaCloner {
230
230
 
231
231
  /**
232
232
  * Drops an index on the target database.
233
- * @param {{tableName: string, targetIndex: import("../drivers/base-columns-index.js").default}} args
233
+ * @param {{tableName: string, targetIndex: import("../drivers/base-columns-index.js").default}} args - Target table and index to remove.
234
234
  * @returns {Promise<void>}
235
235
  */
236
236
  async dropTargetIndex({tableName, targetIndex}) {
@@ -252,7 +252,7 @@ export default class SchemaCloner {
252
252
  /**
253
253
  * Whether the target ledger is missing any version applied on the source — i.e. the
254
254
  * target schema may have been advanced out of band without recording it.
255
- * @returns {Promise<boolean>}
255
+ * @returns {Promise<boolean>} - Whether the target ledger differs from the source.
256
256
  */
257
257
  async ledgerDriftsFromSource() {
258
258
  if (!await MigrationsLedger.tableExists(this.targetDb)) {
@@ -268,8 +268,8 @@ export default class SchemaCloner {
268
268
  /**
269
269
  * Maps a source index into a TableData index for table creation (SQLite omits the
270
270
  * index name so the driver can generate a unique one).
271
- * @param {import("../drivers/base-columns-index.js").default} sourceIndex
272
- * @returns {TableIndex}
271
+ * @param {import("../drivers/base-columns-index.js").default} sourceIndex - Source index definition.
272
+ * @returns {TableIndex} - Framework-independent index definition.
273
273
  */
274
274
  tableDataIndexFromSourceIndex(sourceIndex) {
275
275
  /** @type {{name?: string, unique: boolean}} */
@@ -289,8 +289,8 @@ export default class SchemaCloner {
289
289
  /**
290
290
  * Builds driver create-index args from a source index (the index name is omitted on
291
291
  * SQLite, where index names are unique per-database rather than per-table).
292
- * @param {{sourceIndex: import("../drivers/base-columns-index.js").default, tableName: string}} args
293
- * @returns {{columns: string[], name?: string, tableName: string, unique: boolean}}
292
+ * @param {{sourceIndex: import("../drivers/base-columns-index.js").default, tableName: string}} args - Source index and target table receiving it.
293
+ * @returns {{columns: string[], name?: string, tableName: string, unique: boolean}} - Arguments for creating the target index.
294
294
  */
295
295
  createIndexArgsFromSourceIndex({sourceIndex, tableName}) {
296
296
  /** @type {{columns: string[], name?: string, tableName: string, unique: boolean}} */
@@ -309,9 +309,9 @@ export default class SchemaCloner {
309
309
 
310
310
  /**
311
311
  * Whether two indexes have the same uniqueness and ordered column list.
312
- * @param {import("../drivers/base-columns-index.js").default} sourceIndex
313
- * @param {import("../drivers/base-columns-index.js").default} targetIndex
314
- * @returns {boolean}
312
+ * @param {import("../drivers/base-columns-index.js").default} sourceIndex - Source index definition.
313
+ * @param {import("../drivers/base-columns-index.js").default} targetIndex - Target index definition.
314
+ * @returns {boolean} - Whether both indexes have the same shape.
315
315
  */
316
316
  indexesMatch(sourceIndex, targetIndex) {
317
317
  const sourceColumnNames = sourceIndex.getColumnNames()
@@ -336,8 +336,8 @@ export default class SchemaCloner {
336
336
 
337
337
  /**
338
338
  * A stable signature for an index, used to match cloned indexes by shape.
339
- * @param {import("../drivers/base-columns-index.js").default} index
340
- * @returns {string}
339
+ * @param {import("../drivers/base-columns-index.js").default} index - Index definition.
340
+ * @returns {string} - Stable index-shape signature.
341
341
  */
342
342
  indexSignature(index) {
343
343
  return `${index.isUnique() ? "unique" : "index"}:${index.getColumnNames().join(",")}`
@@ -345,8 +345,8 @@ export default class SchemaCloner {
345
345
 
346
346
  /**
347
347
  * Normalizes a column type to its canonical lowercase form (`int` becomes `integer`).
348
- * @param {string} columnType
349
- * @returns {string}
348
+ * @param {string} columnType - Database column type.
349
+ * @returns {string} - Canonical lowercase column type.
350
350
  */
351
351
  normalizedColumnType(columnType) {
352
352
  const normalizedType = columnType.toLowerCase()
@@ -360,8 +360,8 @@ export default class SchemaCloner {
360
360
 
361
361
  /**
362
362
  * The widening rank of a text column type (0 when not a text type).
363
- * @param {string} columnType
364
- * @returns {number}
363
+ * @param {string} columnType - Database column type.
364
+ * @returns {number} - Text-type widening rank.
365
365
  */
366
366
  textTypeRank(columnType) {
367
367
  return TEXT_TYPE_RANKS[this.normalizedColumnType(columnType)] || 0
@@ -369,9 +369,9 @@ export default class SchemaCloner {
369
369
 
370
370
  /**
371
371
  * Whether the target's text column is narrower than the source's and must be widened.
372
- * @param {import("../drivers/base-column.js").default} sourceColumn
373
- * @param {import("../drivers/base-column.js").default} targetColumn
374
- * @returns {boolean}
372
+ * @param {import("../drivers/base-column.js").default} sourceColumn - Source column definition.
373
+ * @param {import("../drivers/base-column.js").default} targetColumn - Target column definition.
374
+ * @returns {boolean} - Whether the target text column must be widened.
375
375
  */
376
376
  columnNeedsWidening(sourceColumn, targetColumn) {
377
377
  const sourceRank = this.textTypeRank(sourceColumn.getType())
@@ -383,9 +383,9 @@ export default class SchemaCloner {
383
383
  /**
384
384
  * Builds TableData column args from a source column, copying type, nullability,
385
385
  * length, notes, simple defaults and (for full clones) primary-key flag.
386
- * @param {import("../drivers/base-column.js").default} sourceColumn
387
- * @param {{isNewColumn: boolean}} args
388
- * @returns {Record<string, unknown>}
386
+ * @param {import("../drivers/base-column.js").default} sourceColumn - Source column definition.
387
+ * @param {{isNewColumn: boolean}} args - Whether the column is being added instead of cloned with its table.
388
+ * @returns {Record<string, unknown>} - Arguments for altering the target column.
389
389
  */
390
390
  columnArgsFromSourceColumn(sourceColumn, {isNewColumn}) {
391
391
  /** @type {{autoIncrement?: boolean, default?: unknown, isNewColumn: boolean, maxLength?: number, notes?: string, null: boolean, primaryKey?: boolean, type: string}} */
@@ -290,7 +290,6 @@ export default class VelociousEnvironmentsHandlerBrowser extends Base {
290
290
  * Runs after migrations.
291
291
  * @param {object} args - Options object.
292
292
  * @param {Record<string, import("../database/drivers/base.js").default>} args.dbs - Dbs.
293
- * @param {"migration" | "schemaDump"} [args.reason] - Why the structure hook is running.
294
293
  * @returns {Promise<void>} - Resolves when complete.
295
294
  */
296
295
  async afterMigrations({dbs}) {
@@ -19,6 +19,7 @@ export default class BackgroundJobsRunnerCommand extends BaseCommand {
19
19
  const decoded = Buffer.from(payload, "base64").toString("utf8")
20
20
  const jobPayload = JSON.parse(decoded)
21
21
 
22
- await runJobPayload(jobPayload)
22
+ await runJobPayload(jobPayload, {closeConnections: false})
23
+ process.exit(0)
23
24
  }
24
25
  }
@@ -124,7 +124,7 @@ export default class VelociousCliCommandsLintRelationships extends BaseCommand {
124
124
 
125
125
  if (!stats.isDirectory()) return false
126
126
  } catch (error) {
127
- if (/** @type {NodeJS.ErrnoException} */ (error).code == "ENOENT") return false
127
+ if (/** @type {Error & {code?: string}} */ (error).code == "ENOENT") return false
128
128
 
129
129
  throw error
130
130
  }
@@ -213,7 +213,7 @@ export default class VelociousCliCommandsLintRelationships extends BaseCommand {
213
213
  try {
214
214
  configContent = await fs.readFile(configPath, "utf8")
215
215
  } catch (error) {
216
- if (!explicitConfigPath && /** @type {NodeJS.ErrnoException} */ (error).code == "ENOENT") {
216
+ if (!explicitConfigPath && /** @type {Error & {code?: string}} */ (error).code == "ENOENT") {
217
217
  return new Set()
218
218
  }
219
219
 
@@ -860,7 +860,7 @@ export default class VelociousEnvironmentHandlerNode extends Base{
860
860
  files.push({file, fullPath, date, migrationClassName})
861
861
  }
862
862
  } catch (error) {
863
- if (/** @type {NodeJS.ErrnoException} */ (error)?.code !== "ENOENT") {
863
+ if (/** @type {Error & {code?: string}} */ (error)?.code !== "ENOENT") {
864
864
  throw error
865
865
  }
866
866
  }
@@ -20,6 +20,8 @@ import isDate from "./utils/is-date.js"
20
20
  import isPlainObject from "./utils/plain-object.js"
21
21
  import {RansackQueryError, normalizeRansackGroup, parseRansackSort} from "./utils/ransack.js"
22
22
 
23
+ /** @typedef {import("./database/query/model-class-query.js").default & Record<symbol, Set<string> | undefined>} FrontendModelQueryMetadata */
24
+
23
25
  /**
24
26
  * Runs normalize frontend model preload.
25
27
  * @param {import("./database/query/index.js").NestedPreloadRecord | string | string[] | boolean | undefined | null} preload - Preload shorthand.
@@ -31,7 +33,7 @@ function normalizeFrontendModelPreload(preload) {
31
33
  try {
32
34
  return normalizeQueryPreload(preload)
33
35
  } catch (error) {
34
- throwFrontendModelQueryErrorForParserError(error)
36
+ return throwFrontendModelQueryErrorForParserError(error)
35
37
  }
36
38
  }
37
39
 
@@ -46,7 +48,7 @@ function normalizeFrontendModelJoins(joins) {
46
48
  try {
47
49
  return normalizeQueryJoins(joins)
48
50
  } catch (error) {
49
- throwFrontendModelQueryErrorForParserError(error)
51
+ return throwFrontendModelQueryErrorForParserError(error)
50
52
  }
51
53
  }
52
54
 
@@ -190,10 +192,10 @@ function frontendSyncReplaySafeError(message, cause) {
190
192
  /**
191
193
  * Runs frontend model query metadata.
192
194
  * @param {import("./database/query/model-class-query.js").default} query - Query instance.
193
- * @returns {import("./database/query/model-class-query.js").default & {[frontendModelJoinedPathsSymbol]?: Set<string>, [frontendModelGroupedColumnsSymbol]?: Set<string>}} - Query metadata access helper.
195
+ * @returns {FrontendModelQueryMetadata} - Query metadata access helper.
194
196
  */
195
197
  function frontendModelQueryMetadata(query) {
196
- return /** @type {import("./database/query/model-class-query.js").default & {[frontendModelJoinedPathsSymbol]?: Set<string>, [frontendModelGroupedColumnsSymbol]?: Set<string>}} */ (query)
198
+ return /** @type {FrontendModelQueryMetadata} */ (query)
197
199
  }
198
200
 
199
201
  /**
@@ -1253,7 +1255,7 @@ export default class FrontendModelController extends Controller {
1253
1255
  try {
1254
1256
  return normalizeQuerySort(this.frontendModelParams().sort)
1255
1257
  } catch (error) {
1256
- throwFrontendModelQueryErrorForParserError(error)
1258
+ return throwFrontendModelQueryErrorForParserError(error)
1257
1259
  }
1258
1260
  }
1259
1261
 
@@ -1265,7 +1267,7 @@ export default class FrontendModelController extends Controller {
1265
1267
  try {
1266
1268
  return normalizeQueryGroup(this.frontendModelParams().group)
1267
1269
  } catch (error) {
1268
- throwFrontendModelQueryErrorForParserError(error)
1270
+ return throwFrontendModelQueryErrorForParserError(error)
1269
1271
  }
1270
1272
  }
1271
1273
 
@@ -1304,7 +1306,7 @@ export default class FrontendModelController extends Controller {
1304
1306
 
1305
1307
  return pluck
1306
1308
  } catch (error) {
1307
- throwFrontendModelQueryErrorForParserError(error)
1309
+ return throwFrontendModelQueryErrorForParserError(error)
1308
1310
  }
1309
1311
  }
1310
1312
 
@@ -1351,8 +1353,8 @@ export default class FrontendModelController extends Controller {
1351
1353
  * its backend model class by looking up the resource by modelName
1352
1354
  * across all configured backend projects. Returns null when no
1353
1355
  * resource matches the user-provided ability entry.
1354
- * @param {string} modelName
1355
- * @returns {typeof import("./database/record/index.js").default | null}
1356
+ * @param {string} modelName - Frontend model name from an ability request.
1357
+ * @returns {typeof import("./database/record/index.js").default | null} - Backend model class exposed under that frontend name, if present.
1356
1358
  */
1357
1359
  _frontendModelClassForAbilities(modelName) {
1358
1360
  if (typeof modelName !== "string" || modelName.length === 0) return null
@@ -1383,9 +1385,9 @@ export default class FrontendModelController extends Controller {
1383
1385
  * preloaded relationships at any depth. Used to evaluate per-record
1384
1386
  * abilities against nested preloaded children with a single batched
1385
1387
  * query per (modelClass, action) pair.
1386
- * @param {import("./database/record/index.js").default[]} rootModels
1387
- * @param {string} modelName
1388
- * @returns {import("./database/record/index.js").default[]}
1388
+ * @param {import("./database/record/index.js").default[]} rootModels - Loaded roots whose relationship graphs should be traversed.
1389
+ * @param {string} modelName - Model name records must match.
1390
+ * @returns {import("./database/record/index.js").default[]} - Matching records reachable from the loaded roots.
1389
1391
  */
1390
1392
  _frontendModelCollectRecordsForName(rootModels, modelName) {
1391
1393
  /**
@@ -1399,7 +1401,8 @@ export default class FrontendModelController extends Controller {
1399
1401
 
1400
1402
  /**
1401
1403
  * Walk.
1402
- * @param {import("./database/record/index.js").default | null | undefined} record */
1404
+ * @param {import("./database/record/index.js").default | null | undefined} record - Loaded record whose relationship graph should be visited.
1405
+ */
1403
1406
  const walk = (record) => {
1404
1407
  if (!record || typeof record !== "object") return
1405
1408
  if (seen.has(record)) return
@@ -1437,7 +1440,7 @@ export default class FrontendModelController extends Controller {
1437
1440
  * `_setComputedAbility`. Runs one batched `authorized query + pluck`
1438
1441
  * per (modelClass, action) pair, regardless of how many records
1439
1442
  * were loaded.
1440
- * @param {import("./database/record/index.js").default[]} rootModels
1443
+ * @param {import("./database/record/index.js").default[]} rootModels - Loaded roots that receive computed ability results.
1441
1444
  * @returns {Promise<void>}
1442
1445
  */
1443
1446
  async frontendModelComputeAbilities(rootModels) {
@@ -1491,7 +1494,7 @@ export default class FrontendModelController extends Controller {
1491
1494
  * Unknown entries are silently skipped — downstream code resolves
1492
1495
  * model names to classes when applying the check, so unresolved
1493
1496
  * names naturally become no-ops.
1494
- * @returns {Array<{modelName: string, actions: string[]}>}
1497
+ * @returns {Array<{modelName: string, actions: string[]}>} - Normalized model ability requests.
1495
1498
  */
1496
1499
  frontendModelAbilities() {
1497
1500
  const raw = this.frontendModelParams().abilities
@@ -1529,7 +1532,7 @@ export default class FrontendModelController extends Controller {
1529
1532
  *
1530
1533
  * Returns the raw nested-record spec (shape validated by the
1531
1534
  * normalizer inside `Query.queryData`) or `null` when not requested.
1532
- * @returns {import("./database/query/query-data.js").QueryDataSpec | null}
1535
+ * @returns {import("./database/query/query-data.js").QueryDataSpec | null} - Normalized query-data specification.
1533
1536
  */
1534
1537
  frontendModelQueryData() {
1535
1538
  const raw = this.frontendModelParams().queryData
@@ -1853,7 +1856,7 @@ export default class FrontendModelController extends Controller {
1853
1856
  try {
1854
1857
  return normalizeRansackGroup(this.frontendModelClass(), filterParams)
1855
1858
  } catch (error) {
1856
- throwFrontendModelQueryErrorForParserError(error)
1859
+ return throwFrontendModelQueryErrorForParserError(error)
1857
1860
  }
1858
1861
  }
1859
1862
 
@@ -1866,7 +1869,7 @@ export default class FrontendModelController extends Controller {
1866
1869
  try {
1867
1870
  return parseRansackSort(this.frontendModelClass(), sortString)
1868
1871
  } catch (error) {
1869
- throwFrontendModelQueryErrorForParserError(error)
1872
+ return throwFrontendModelQueryErrorForParserError(error)
1870
1873
  }
1871
1874
  }
1872
1875
 
@@ -2698,12 +2701,14 @@ export default class FrontendModelController extends Controller {
2698
2701
  /**
2699
2702
  * Resource attribute method name.
2700
2703
  * @param {string} attributeName - Attribute name.
2704
+ * @returns {string} - Resource attribute method name.
2701
2705
  */
2702
2706
  const resourceAttributeMethodName = (attributeName) => `${attributeName}Attribute`
2703
2707
 
2704
2708
  /**
2705
2709
  * Resource has attribute.
2706
2710
  * @param {string} attributeName - Attribute name.
2711
+ * @returns {ReturnType<FrontendModelBaseResource["resourceMethod"]>} - Resource attribute method details.
2707
2712
  */
2708
2713
  const resourceAttributeMethod = (attributeName) => {
2709
2714
  const methodName = resourceAttributeMethodName(attributeName)
@@ -2714,6 +2719,7 @@ export default class FrontendModelController extends Controller {
2714
2719
  /**
2715
2720
  * Prototype attribute method.
2716
2721
  * @param {string} attributeName - Attribute name.
2722
+ * @returns {{method: (...args: Array<?>) => ?, ownerName: string} | undefined} - Prototype method details when present.
2717
2723
  */
2718
2724
  const prototypeAttributeMethod = (attributeName) => {
2719
2725
  let currentPrototype = Object.getPrototypeOf(model)
@@ -2735,6 +2741,7 @@ export default class FrontendModelController extends Controller {
2735
2741
  /**
2736
2742
  * Serialized attribute value.
2737
2743
  * @param {string} attributeName - Attribute name.
2744
+ * @returns {Promise<?>} - Serialized attribute value.
2738
2745
  */
2739
2746
  const serializedAttributeValue = async (attributeName) => {
2740
2747
  // Check resource instance first (virtual/computed attributes via ${name}Attribute convention)
@@ -2758,6 +2765,7 @@ export default class FrontendModelController extends Controller {
2758
2765
  /**
2759
2766
  * Attribute exists.
2760
2767
  * @param {string} attributeName - Attribute name.
2768
+ * @returns {boolean} - Whether the attribute exists.
2761
2769
  */
2762
2770
  const attributeExists = (attributeName) => {
2763
2771
  return (attributeName in modelAttributes) || (attributeName in /** @type {Record<string, ?>} */ (model)) || Boolean(resourceAttributeMethod(attributeName))
@@ -104,7 +104,7 @@ import {readPayloadAssociationCount, readPayloadComputedAbility, readPayloadQuer
104
104
  * frontend models passed model classes into relationship helpers, while newer
105
105
  * generated models pass instance types.
106
106
  * @template {FrontendModelBase<any, any, any> | typeof FrontendModelBase} T
107
- * @typedef {T extends new (...args: any[]) => infer Instance ? Instance : T} FrontendModelRelationshipModel
107
+ * @typedef {T extends typeof FrontendModelBase ? InstanceType<T> : T} FrontendModelRelationshipModel
108
108
  */
109
109
  /**
110
110
  * FrontendModelTransportConfig type.
@@ -1799,7 +1799,7 @@ async function performSharedFrontendModelApiRequest(requestPayload) {
1799
1799
  /**
1800
1800
  * Throws a frontend-model HTTP error with backend-provided envelope details when available.
1801
1801
  * @param {{commandLabel: string, response: Response, responseText: string}} args - Error response details.
1802
- * @returns {never}
1802
+ * @returns {never} - Always throws an unknown-attribute error.
1803
1803
  */
1804
1804
  function throwFrontendModelHttpError({commandLabel, response, responseText}) {
1805
1805
  // Surface the backend's friendly errorMessage envelope (the
@@ -2612,7 +2612,7 @@ export default class FrontendModelBase {
2612
2612
  * column of the same name. Returns the attached value, or 0 when
2613
2613
  * `.withCount(...)` wasn't requested for this attribute.
2614
2614
  * @param {string} attributeName - Attribute name, e.g. `"tasksCount"` or a custom name from `.withCount({customName: {...}})`.
2615
- * @returns {number}
2615
+ * @returns {number} - Attached association count, or zero when absent.
2616
2616
  */
2617
2617
  readCount(attributeName) {
2618
2618
  return readPayloadAssociationCount(/** @type {import("../record-payload-values.js").RecordPayloadValuesTarget} */ (/** @type {?} */ (this)), attributeName)
@@ -2638,7 +2638,7 @@ export default class FrontendModelBase {
2638
2638
  * on `record.can("update")` without first checking whether the
2639
2639
  * ability was loaded.
2640
2640
  * @param {string} action - Ability action name, e.g. `"update"`.
2641
- * @returns {boolean}
2641
+ * @returns {boolean} - Whether the requested ability is allowed.
2642
2642
  */
2643
2643
  can(action) {
2644
2644
  return readPayloadComputedAbility(/** @type {import("../record-payload-values.js").RecordPayloadValuesTarget} */ (/** @type {?} */ (this)), action)
@@ -2663,7 +2663,7 @@ export default class FrontendModelBase {
2663
2663
  * name. Returns `null` when no registered fn produced that alias for
2664
2664
  * this record (e.g. no child rows matched the aggregate).
2665
2665
  * @param {string} name - queryData alias name.
2666
- * @returns {?}
2666
+ * @returns {?} - Attached query-data value.
2667
2667
  */
2668
2668
  queryData(name) {
2669
2669
  return readPayloadQueryData(/** @type {import("../record-payload-values.js").RecordPayloadValuesTarget} */ (/** @type {?} */ (this)), name)
@@ -166,8 +166,8 @@ export function normalizePreload(preload) {
166
166
  * query API into the strict internal entries used in the transport
167
167
  * payload. Shares the shape semantics with the backend normalizer in
168
168
  * `database/query/with-count.js`.
169
- * @param {string | string[] | Record<string, boolean | {relationship?: string, where?: Record<string, ?>}>} spec
170
- * @returns {Array<{attributeName: string, relationshipName: string, where?: Record<string, ?>}>}
169
+ * @param {string | string[] | Record<string, boolean | {relationship?: string, where?: Record<string, ?>}>} spec - Association-count shorthand to normalize.
170
+ * @returns {Array<{attributeName: string, relationshipName: string, where?: Record<string, ?>}>} - Normalized association-count requests.
171
171
  */
172
172
  function normalizeWithCountFrontend(spec) {
173
173
  if (spec == null) return []
@@ -222,9 +222,9 @@ function normalizeWithCountFrontend(spec) {
222
222
  * shorthand (applies to the query's own model class) and the keyed
223
223
  * `{ModelName: [action, ...]}` form (applies to records of that model
224
224
  * class, useful for preloaded children).
225
- * @param {string[] | Record<string, string[]>} spec
226
- * @param {{getModelName: () => string}} rootModelClass
227
- * @returns {Array<{modelName: string, actions: string[]}>}
225
+ * @param {string[] | Record<string, string[]>} spec - Ability actions grouped by model, or root-model action shorthand.
226
+ * @param {{getModelName: () => string}} rootModelClass - Query root used by the flat action shorthand.
227
+ * @returns {Array<{modelName: string, actions: string[]}>} - Normalized model ability requests.
228
228
  */
229
229
  function normalizeAbilitiesSpec(spec, rootModelClass) {
230
230
  if (spec == null) return []
@@ -1181,8 +1181,8 @@ export default class FrontendModelQuery {
1181
1181
  * strings — typically `"update"` / `"destroy"` / `"create"` /
1182
1182
  * `"read"`, but any custom action registered on the resource's
1183
1183
  * authorization ability is accepted.
1184
- * @param {string[] | Record<string, string[]>} spec
1185
- * @returns {this}
1184
+ * @param {string[] | Record<string, string[]>} spec - Ability actions to request for root or named models.
1185
+ * @returns {this} - This query for chaining.
1186
1186
  */
1187
1187
  abilities(spec) {
1188
1188
  for (const entry of normalizeAbilitiesSpec(spec, this.modelClass)) {
@@ -1194,7 +1194,7 @@ export default class FrontendModelQuery {
1194
1194
 
1195
1195
  /**
1196
1196
  * Runs merge ability entry.
1197
- * @param {{modelName: string, actions: string[]}} entry
1197
+ * @param {{modelName: string, actions: string[]}} entry - Normalized model ability request to append.
1198
1198
  * @returns {void}
1199
1199
  */
1200
1200
  _mergeAbilityEntry(entry) {
@@ -1215,8 +1215,8 @@ export default class FrontendModelQuery {
1215
1215
  * counts to each returned record. Parses the same shapes as the
1216
1216
  * backend `ModelClassQuery#withCount`, then ships the normalized
1217
1217
  * entries as part of the `index` command payload.
1218
- * @param {string | string[] | Record<string, boolean | {relationship?: string, where?: Record<string, ?>}>} spec
1219
- * @returns {this}
1218
+ * @param {string | string[] | Record<string, boolean | {relationship?: string, where?: Record<string, ?>}>} spec - Relationships whose counts should be serialized.
1219
+ * @returns {this} - This query for chaining.
1220
1220
  */
1221
1221
  withCount(spec) {
1222
1222
  for (const entry of normalizeWithCountFrontend(spec)) {
@@ -1233,8 +1233,8 @@ export default class FrontendModelQuery {
1233
1233
  * frontend ships only these names; the SQL fragments stay server-
1234
1234
  * side. All resulting aliases are attached to the root record and
1235
1235
  * read back with `record.queryData(aliasName)`.
1236
- * @param {string | Array<string | Record<string, ?>> | Record<string, ?>} spec
1237
- * @returns {this}
1236
+ * @param {string | Array<string | Record<string, ?>> | Record<string, ?>} spec - Backend query-data names and arguments to serialize.
1237
+ * @returns {this} - This query for chaining.
1238
1238
  */
1239
1239
  queryData(spec) {
1240
1240
  if (spec == null) return this