velocious 1.0.514 → 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.
- package/README.md +4 -3
- package/build/background-jobs/cron-expression.js +9 -9
- package/build/background-jobs/forked-runner-child.js +1 -1
- package/build/background-jobs/job-runner.js +21 -15
- package/build/background-jobs/json-socket.js +4 -0
- package/build/background-jobs/main.js +180 -18
- package/build/background-jobs/status-reporter.js +12 -5
- package/build/background-jobs/store.js +132 -50
- package/build/background-jobs/types.js +11 -3
- package/build/background-jobs/worker.js +9 -5
- package/build/beacon/client.js +13 -6
- package/build/configuration.js +54 -29
- package/build/controller.js +9 -3
- package/build/database/drivers/sqlite/base.js +1 -1
- package/build/database/drivers/sqlite/index.js +15 -14
- package/build/database/migrations-ledger.js +16 -16
- package/build/database/pool/async-tracked-multi-connection.js +16 -0
- package/build/database/pool/base.js +26 -0
- package/build/database/query/where-model-class-hash.js +2 -0
- package/build/database/query/with-count.js +1 -1
- package/build/database/record/acts-as-list.js +2 -2
- package/build/database/record/auditing.js +23 -6
- package/build/database/record/index.js +7 -7
- package/build/database/record/validators/uniqueness.js +3 -3
- package/build/database/tenants/data-copier.js +23 -23
- package/build/database/tenants/schema-cloner.js +27 -27
- package/build/environment-handlers/browser.js +0 -1
- package/build/environment-handlers/node/cli/commands/background-jobs-runner.js +2 -1
- package/build/environment-handlers/node/cli/commands/lint/relationships.js +2 -2
- package/build/environment-handlers/node.js +1 -1
- package/build/frontend-model-controller.js +26 -18
- package/build/frontend-model-resource/base-resource.js +4 -4
- package/build/frontend-models/base.js +5 -5
- package/build/frontend-models/query.js +12 -12
- package/build/http-server/client/index.js +61 -15
- package/build/http-server/client/request-runner.js +7 -1
- package/build/http-server/client/response.js +17 -1
- package/build/http-server/client/websocket-session.js +13 -13
- package/build/http-server/server-client.js +96 -0
- package/build/http-server/websocket-channel.js +12 -11
- package/build/http-server/websocket-connection.js +12 -11
- package/build/http-server/websocket-events-host.js +1 -1
- package/build/http-server/worker-handler/in-process.js +48 -9
- package/build/http-server/worker-handler/index.js +67 -7
- package/build/http-server/worker-handler/worker-thread.js +68 -0
- package/build/src/background-jobs/cron-expression.d.ts +2 -2
- package/build/src/background-jobs/cron-expression.js +10 -10
- package/build/src/background-jobs/forked-runner-child.js +2 -2
- package/build/src/background-jobs/job-runner.d.ts +5 -1
- package/build/src/background-jobs/job-runner.d.ts.map +1 -1
- package/build/src/background-jobs/job-runner.js +22 -16
- package/build/src/background-jobs/json-socket.d.ts +4 -0
- package/build/src/background-jobs/json-socket.d.ts.map +1 -1
- package/build/src/background-jobs/json-socket.js +5 -1
- package/build/src/background-jobs/main.d.ts +62 -10
- package/build/src/background-jobs/main.d.ts.map +1 -1
- package/build/src/background-jobs/main.js +171 -19
- package/build/src/background-jobs/status-reporter.d.ts +6 -2
- package/build/src/background-jobs/status-reporter.d.ts.map +1 -1
- package/build/src/background-jobs/status-reporter.js +13 -6
- package/build/src/background-jobs/store.d.ts +48 -25
- package/build/src/background-jobs/store.d.ts.map +1 -1
- package/build/src/background-jobs/store.js +123 -50
- package/build/src/background-jobs/types.d.ts +36 -3
- package/build/src/background-jobs/types.d.ts.map +1 -1
- package/build/src/background-jobs/types.js +12 -4
- package/build/src/background-jobs/worker.d.ts +7 -5
- package/build/src/background-jobs/worker.d.ts.map +1 -1
- package/build/src/background-jobs/worker.js +10 -6
- package/build/src/beacon/client.d.ts +6 -3
- package/build/src/beacon/client.d.ts.map +1 -1
- package/build/src/beacon/client.js +14 -7
- package/build/src/configuration-types.d.ts +1 -1
- package/build/src/configuration.d.ts +42 -29
- package/build/src/configuration.d.ts.map +1 -1
- package/build/src/configuration.js +52 -30
- package/build/src/controller.d.ts +3 -0
- package/build/src/controller.d.ts.map +1 -1
- package/build/src/controller.js +9 -4
- package/build/src/database/drivers/sqlite/base.js +2 -2
- package/build/src/database/drivers/sqlite/index.d.ts +7 -6
- package/build/src/database/drivers/sqlite/index.d.ts.map +1 -1
- package/build/src/database/drivers/sqlite/index.js +16 -15
- package/build/src/database/migrations-ledger.d.ts +16 -16
- package/build/src/database/migrations-ledger.js +17 -17
- package/build/src/database/pool/async-tracked-multi-connection.d.ts +0 -11
- package/build/src/database/pool/async-tracked-multi-connection.d.ts.map +1 -1
- package/build/src/database/pool/async-tracked-multi-connection.js +16 -1
- package/build/src/database/pool/base.d.ts +21 -0
- package/build/src/database/pool/base.d.ts.map +1 -1
- package/build/src/database/pool/base.js +24 -1
- package/build/src/database/query/where-model-class-hash.d.ts.map +1 -1
- package/build/src/database/query/where-model-class-hash.js +3 -1
- package/build/src/database/query/with-count.js +2 -2
- package/build/src/database/record/acts-as-list.js +3 -3
- package/build/src/database/record/auditing.d.ts +1 -1
- package/build/src/database/record/auditing.d.ts.map +1 -1
- package/build/src/database/record/auditing.js +24 -7
- package/build/src/database/record/index.d.ts +7 -7
- package/build/src/database/record/index.js +8 -8
- package/build/src/database/record/validators/uniqueness.d.ts +3 -3
- package/build/src/database/record/validators/uniqueness.js +4 -4
- package/build/src/database/tenants/data-copier.d.ts +18 -18
- package/build/src/database/tenants/data-copier.js +24 -24
- package/build/src/database/tenants/schema-cloner.d.ts +27 -27
- package/build/src/database/tenants/schema-cloner.js +28 -28
- package/build/src/environment-handlers/browser.d.ts +9 -0
- package/build/src/environment-handlers/browser.d.ts.map +1 -1
- package/build/src/environment-handlers/browser.js +1 -2
- package/build/src/environment-handlers/node/cli/commands/background-jobs-runner.d.ts.map +1 -1
- package/build/src/environment-handlers/node/cli/commands/background-jobs-runner.js +3 -2
- package/build/src/environment-handlers/node/cli/commands/lint/relationships.js +3 -3
- package/build/src/environment-handlers/node.js +2 -2
- package/build/src/frontend-model-controller.d.ts +9 -8
- package/build/src/frontend-model-controller.d.ts.map +1 -1
- package/build/src/frontend-model-controller.js +26 -19
- package/build/src/frontend-model-resource/base-resource.js +5 -5
- package/build/src/frontend-models/base.d.ts +4 -4
- package/build/src/frontend-models/base.d.ts.map +1 -1
- package/build/src/frontend-models/base.js +6 -6
- package/build/src/frontend-models/query.d.ts +7 -7
- package/build/src/frontend-models/query.js +13 -13
- package/build/src/http-server/client/index.d.ts +23 -1
- package/build/src/http-server/client/index.d.ts.map +1 -1
- package/build/src/http-server/client/index.js +55 -17
- package/build/src/http-server/client/request-runner.d.ts.map +1 -1
- package/build/src/http-server/client/request-runner.js +8 -2
- package/build/src/http-server/client/response.d.ts +11 -1
- package/build/src/http-server/client/response.d.ts.map +1 -1
- package/build/src/http-server/client/response.js +16 -2
- package/build/src/http-server/client/websocket-session.d.ts +13 -13
- package/build/src/http-server/client/websocket-session.js +14 -14
- package/build/src/http-server/server-client.d.ts +13 -0
- package/build/src/http-server/server-client.d.ts.map +1 -1
- package/build/src/http-server/server-client.js +94 -1
- package/build/src/http-server/websocket-channel.d.ts +12 -11
- package/build/src/http-server/websocket-channel.d.ts.map +1 -1
- package/build/src/http-server/websocket-channel.js +13 -12
- package/build/src/http-server/websocket-connection.d.ts +12 -11
- package/build/src/http-server/websocket-connection.d.ts.map +1 -1
- package/build/src/http-server/websocket-connection.js +13 -12
- package/build/src/http-server/websocket-events-host.d.ts +1 -1
- package/build/src/http-server/websocket-events-host.js +2 -2
- package/build/src/http-server/worker-handler/in-process.d.ts +2 -0
- package/build/src/http-server/worker-handler/in-process.d.ts.map +1 -1
- package/build/src/http-server/worker-handler/in-process.js +42 -11
- package/build/src/http-server/worker-handler/index.d.ts +21 -0
- package/build/src/http-server/worker-handler/index.d.ts.map +1 -1
- package/build/src/http-server/worker-handler/index.js +61 -7
- package/build/src/http-server/worker-handler/worker-thread.d.ts +30 -0
- package/build/src/http-server/worker-handler/worker-thread.d.ts.map +1 -1
- package/build/src/http-server/worker-handler/worker-thread.js +61 -1
- package/build/src/sync/device-identity.d.ts +2 -2
- package/build/src/sync/device-identity.d.ts.map +1 -1
- package/build/src/sync/device-identity.js +4 -4
- package/build/src/sync/local-mutation-log.d.ts +0 -1
- package/build/src/sync/local-mutation-log.d.ts.map +1 -1
- package/build/src/sync/local-mutation-log.js +1 -2
- package/build/src/sync/query-scope.d.ts +5 -0
- package/build/src/sync/query-scope.d.ts.map +1 -1
- package/build/src/sync/query-scope.js +7 -2
- package/build/src/sync/sync-client-types.d.ts +2 -2
- package/build/src/sync/sync-client-types.d.ts.map +1 -1
- package/build/src/sync/sync-client-types.js +1 -1
- package/build/src/sync/sync-client.d.ts +17 -2
- package/build/src/sync/sync-client.d.ts.map +1 -1
- package/build/src/sync/sync-client.js +28 -14
- package/build/src/sync/sync-realtime-bridge.d.ts +6 -2
- package/build/src/sync/sync-realtime-bridge.d.ts.map +1 -1
- package/build/src/sync/sync-realtime-bridge.js +14 -3
- package/build/src/sync/sync-resource-base.d.ts +14 -3
- package/build/src/sync/sync-resource-base.d.ts.map +1 -1
- package/build/src/sync/sync-resource-base.js +20 -4
- package/build/src/sync/sync-scope-store.d.ts +3 -3
- package/build/src/sync/sync-scope-store.d.ts.map +1 -1
- package/build/src/sync/sync-scope-store.js +7 -5
- package/build/src/sync/sync-websocket-channel.d.ts +10 -0
- package/build/src/sync/sync-websocket-channel.d.ts.map +1 -1
- package/build/src/sync/sync-websocket-channel.js +20 -3
- package/build/src/tenants/tenant-iterator.d.ts +8 -8
- package/build/src/tenants/tenant-iterator.js +9 -9
- package/build/src/tenants/tenant.d.ts +6 -6
- package/build/src/tenants/tenant.js +7 -7
- package/build/src/testing/test-runner.d.ts +16 -0
- package/build/src/testing/test-runner.d.ts.map +1 -1
- package/build/src/testing/test-runner.js +79 -19
- package/build/sync/device-identity.js +3 -3
- package/build/sync/local-mutation-log.js +0 -1
- package/build/sync/query-scope.js +6 -1
- package/build/sync/sync-client-types.js +1 -1
- package/build/sync/sync-client.js +28 -15
- package/build/sync/sync-realtime-bridge.js +13 -2
- package/build/sync/sync-resource-base.js +20 -3
- package/build/sync/sync-scope-store.js +6 -4
- package/build/sync/sync-websocket-channel.js +18 -2
- package/build/tenants/tenant-iterator.js +8 -8
- package/build/tenants/tenant.js +6 -6
- package/build/testing/test-runner.js +86 -20
- package/package.json +2 -2
- package/src/background-jobs/cron-expression.js +9 -9
- package/src/background-jobs/forked-runner-child.js +1 -1
- package/src/background-jobs/job-runner.js +21 -15
- package/src/background-jobs/json-socket.js +4 -0
- package/src/background-jobs/main.js +180 -18
- package/src/background-jobs/status-reporter.js +12 -5
- package/src/background-jobs/store.js +132 -50
- package/src/background-jobs/types.js +11 -3
- package/src/background-jobs/worker.js +9 -5
- package/src/beacon/client.js +13 -6
- package/src/configuration.js +54 -29
- package/src/controller.js +9 -3
- package/src/database/drivers/sqlite/base.js +1 -1
- package/src/database/drivers/sqlite/index.js +15 -14
- package/src/database/migrations-ledger.js +16 -16
- package/src/database/pool/async-tracked-multi-connection.js +16 -0
- package/src/database/pool/base.js +26 -0
- package/src/database/query/where-model-class-hash.js +2 -0
- package/src/database/query/with-count.js +1 -1
- package/src/database/record/acts-as-list.js +2 -2
- package/src/database/record/auditing.js +23 -6
- package/src/database/record/index.js +7 -7
- package/src/database/record/validators/uniqueness.js +3 -3
- package/src/database/tenants/data-copier.js +23 -23
- package/src/database/tenants/schema-cloner.js +27 -27
- package/src/environment-handlers/browser.js +0 -1
- package/src/environment-handlers/node/cli/commands/background-jobs-runner.js +2 -1
- package/src/environment-handlers/node/cli/commands/lint/relationships.js +2 -2
- package/src/environment-handlers/node.js +1 -1
- package/src/frontend-model-controller.js +26 -18
- package/src/frontend-model-resource/base-resource.js +4 -4
- package/src/frontend-models/base.js +5 -5
- package/src/frontend-models/query.js +12 -12
- package/src/http-server/client/index.js +61 -15
- package/src/http-server/client/request-runner.js +7 -1
- package/src/http-server/client/response.js +17 -1
- package/src/http-server/client/websocket-session.js +13 -13
- package/src/http-server/server-client.js +96 -0
- package/src/http-server/websocket-channel.js +12 -11
- package/src/http-server/websocket-connection.js +12 -11
- package/src/http-server/websocket-events-host.js +1 -1
- package/src/http-server/worker-handler/in-process.js +48 -9
- package/src/http-server/worker-handler/index.js +67 -7
- package/src/http-server/worker-handler/worker-thread.js +68 -0
- package/src/sync/device-identity.js +3 -3
- package/src/sync/local-mutation-log.js +0 -1
- package/src/sync/query-scope.js +6 -1
- package/src/sync/sync-client-types.js +1 -1
- package/src/sync/sync-client.js +28 -15
- package/src/sync/sync-realtime-bridge.js +13 -2
- package/src/sync/sync-resource-base.js +20 -3
- package/src/sync/sync-scope-store.js +6 -4
- package/src/sync/sync-websocket-channel.js +18 -2
- package/src/tenants/tenant-iterator.js +8 -8
- package/src/tenants/tenant.js +6 -6
- package/src/testing/test-runner.js +86 -20
|
@@ -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 {
|
|
195
|
+
* @returns {FrontendModelQueryMetadata} - Query metadata access helper.
|
|
194
196
|
*/
|
|
195
197
|
function frontendModelQueryMetadata(query) {
|
|
196
|
-
return /** @type {
|
|
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))
|
|
@@ -1128,10 +1128,10 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
1128
1128
|
}
|
|
1129
1129
|
|
|
1130
1130
|
if (notPermittedAttachments.length > 0) {
|
|
1131
|
-
throw
|
|
1131
|
+
throw VelociousError.safe(`Frontend model attachment names not permitted by permittedParams(): ${notPermittedAttachments.join(", ")}`, {code: "frontend-model-attribute-error"})
|
|
1132
1132
|
}
|
|
1133
1133
|
if (invalidAttachments.length > 0) {
|
|
1134
|
-
throw
|
|
1134
|
+
throw VelociousError.safe(`Invalid frontend model attachment names: ${invalidAttachments.join(", ")}`, {code: "frontend-model-attribute-error"})
|
|
1135
1135
|
}
|
|
1136
1136
|
}
|
|
1137
1137
|
|
|
@@ -1978,11 +1978,11 @@ function filterWritableFrontendModelAttributes(
|
|
|
1978
1978
|
}
|
|
1979
1979
|
|
|
1980
1980
|
if (notPermittedAttributes.length > 0) {
|
|
1981
|
-
throw
|
|
1981
|
+
throw VelociousError.safe(`Frontend model write attributes not permitted by permittedParams(): ${notPermittedAttributes.join(", ")}`, {code: "frontend-model-attribute-error"})
|
|
1982
1982
|
}
|
|
1983
1983
|
|
|
1984
1984
|
if (invalidAttributes.length > 0) {
|
|
1985
|
-
throw
|
|
1985
|
+
throw VelociousError.safe(`Invalid frontend model write attributes: ${invalidAttributes.join(", ")}`, {code: "frontend-model-attribute-error"})
|
|
1986
1986
|
}
|
|
1987
1987
|
|
|
1988
1988
|
return writableAttributes
|
|
@@ -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
|
|
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
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import crypto from "crypto"
|
|
4
4
|
import fs from "node:fs/promises"
|
|
5
|
-
import {createReadStream} from "node:fs"
|
|
6
5
|
import {digg} from "diggerize"
|
|
7
6
|
import {ensureError} from "typanic"
|
|
8
7
|
import EventEmitter from "../../utils/event-emitter.js"
|
|
@@ -58,6 +57,9 @@ export default class VeoliciousHttpServerClient {
|
|
|
58
57
|
* Narrows the runtime value to the documented type.
|
|
59
58
|
* @type {RequestRunner[]} */
|
|
60
59
|
this.requestRunners = []
|
|
60
|
+
|
|
61
|
+
/** @type {Set<(result: "completed" | "aborted") => Promise<void>>} */
|
|
62
|
+
this.pendingFileResponses = new Set()
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
/**
|
|
@@ -355,6 +357,7 @@ export default class VeoliciousHttpServerClient {
|
|
|
355
357
|
const response = digg(requestRunner, "response")
|
|
356
358
|
const request = requestRunner.getRequest()
|
|
357
359
|
const filePath = response.getFilePath()
|
|
360
|
+
const fileOnFinished = response.getFileOnFinished()
|
|
358
361
|
const date = new Date()
|
|
359
362
|
const connectionHeader = request.header("connection")?.toLowerCase()?.trim()
|
|
360
363
|
const httpVersion = request.httpVersion()
|
|
@@ -423,8 +426,9 @@ export default class VeoliciousHttpServerClient {
|
|
|
423
426
|
|
|
424
427
|
if (isBodylessStatus) {
|
|
425
428
|
this.logger.debug(() => ["sendResponse body suppressed for no-body status", {clientCount: this.clientCount, statusCode: response.getStatusCode()}])
|
|
429
|
+
if (hasFilePath) await this.sendFileOutput(filePath, false, fileOnFinished)
|
|
426
430
|
} else if (hasFilePath) {
|
|
427
|
-
await this.sendFileOutput(filePath)
|
|
431
|
+
await this.sendFileOutput(filePath, true, fileOnFinished)
|
|
428
432
|
} else {
|
|
429
433
|
this.events.emit("output", body)
|
|
430
434
|
this.logger.debug(() => ["sendResponse body emitted", {clientCount: this.clientCount, bodyLength: bodyIsString ? body.length : body.byteLength}])
|
|
@@ -441,27 +445,69 @@ export default class VeoliciousHttpServerClient {
|
|
|
441
445
|
/**
|
|
442
446
|
* Runs send file output.
|
|
443
447
|
* @param {string} filePath - File path.
|
|
448
|
+
* @param {boolean} sendBody - Whether the file body should be sent.
|
|
449
|
+
* @param {((result: "completed" | "aborted") => void | Promise<void>) | null} onFinished - Completion callback.
|
|
444
450
|
* @returns {Promise<void>} - Resolves when complete.
|
|
445
451
|
*/
|
|
446
|
-
async sendFileOutput(filePath) {
|
|
452
|
+
async sendFileOutput(filePath, sendBody, onFinished) {
|
|
447
453
|
this.logger.debug(() => ["sendFileOutput start", {clientCount: this.clientCount, filePath}])
|
|
448
|
-
|
|
449
|
-
|
|
454
|
+
|
|
455
|
+
const result = await new Promise((resolve) => {
|
|
456
|
+
/** @type {Promise<void> | null} */
|
|
457
|
+
let settlement = null
|
|
458
|
+
const settle = (/** @type {"completed" | "aborted"} */ transferResult) => {
|
|
459
|
+
if (settlement) return settlement
|
|
460
|
+
|
|
461
|
+
this.pendingFileResponses.delete(settle)
|
|
462
|
+
settlement = this.runFileOnFinished({filePath, onFinished, result: transferResult})
|
|
463
|
+
.finally(() => resolve(transferResult))
|
|
464
|
+
|
|
465
|
+
return settlement
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
this.pendingFileResponses.add(settle)
|
|
469
|
+
this.events.emit("file", {filePath, sendBody, settle})
|
|
470
|
+
})
|
|
471
|
+
|
|
472
|
+
this.logger.debug(() => ["sendFileOutput done", {clientCount: this.clientCount, filePath, result}])
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Runs a file completion callback without allowing cleanup failures to replace the committed response.
|
|
477
|
+
* @param {object} args - Completion details.
|
|
478
|
+
* @param {string} args.filePath - File path.
|
|
479
|
+
* @param {((result: "completed" | "aborted") => void | Promise<void>) | null} args.onFinished - Completion callback.
|
|
480
|
+
* @param {"completed" | "aborted"} args.result - Transfer result.
|
|
481
|
+
* @returns {Promise<void>} - Resolves after callback cleanup and error reporting finish.
|
|
482
|
+
*/
|
|
483
|
+
async runFileOnFinished({filePath, onFinished, result}) {
|
|
484
|
+
if (!onFinished) return
|
|
450
485
|
|
|
451
486
|
try {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
487
|
+
await onFinished(result)
|
|
488
|
+
} catch (caughtError) {
|
|
489
|
+
const error = ensureError(caughtError)
|
|
490
|
+
|
|
491
|
+
await this.logger.error(() => ["File response onFinished callback failed", {clientCount: this.clientCount, filePath, result}, error])
|
|
492
|
+
|
|
493
|
+
const errorPayload = {
|
|
494
|
+
context: {clientCount: this.clientCount, filePath, result, stage: "send-file-on-finished"},
|
|
495
|
+
error
|
|
457
496
|
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
this.
|
|
461
|
-
throw error
|
|
497
|
+
|
|
498
|
+
this.configuration.getErrorEvents().emit("framework-error", errorPayload)
|
|
499
|
+
this.configuration.getErrorEvents().emit("all-error", {...errorPayload, errorType: "framework-error"})
|
|
462
500
|
}
|
|
463
501
|
}
|
|
464
502
|
|
|
503
|
+
/**
|
|
504
|
+
* Aborts all file responses awaiting transport acknowledgement.
|
|
505
|
+
* @returns {Promise<void>} - Resolves after pending callbacks settle.
|
|
506
|
+
*/
|
|
507
|
+
async abortPendingFileResponses() {
|
|
508
|
+
await Promise.all([...this.pendingFileResponses].map((settle) => settle("aborted")))
|
|
509
|
+
}
|
|
510
|
+
|
|
465
511
|
/**
|
|
466
512
|
* Runs should close connection.
|
|
467
513
|
* @param {import("./request.js").default | import("./websocket-request.js").default} request - Request object.
|
|
@@ -488,7 +534,7 @@ export default class VeoliciousHttpServerClient {
|
|
|
488
534
|
* cannot carry a message body: every 1xx informational, 204 No
|
|
489
535
|
* Content, and 304 Not Modified.
|
|
490
536
|
* @param {number} statusCode - HTTP status code.
|
|
491
|
-
* @returns {boolean}
|
|
537
|
+
* @returns {boolean} - Whether the status code forbids a response body.
|
|
492
538
|
*/
|
|
493
539
|
function isNoBodyStatusCode(statusCode) {
|
|
494
540
|
return (statusCode >= 100 && statusCode < 200) || statusCode === 204 || statusCode === 304
|
|
@@ -135,7 +135,13 @@ export default class VelociousHttpServerClientRequestRunner {
|
|
|
135
135
|
this.requestTiming.startedAtMs = Date.now()
|
|
136
136
|
|
|
137
137
|
return await this.configuration.runWithRequestTiming(this.requestTiming, async () => {
|
|
138
|
-
|
|
138
|
+
// Run the whole request inside any per-test shared connection context so an
|
|
139
|
+
// in-process handler executes on the test's connection (and open transaction).
|
|
140
|
+
// No shared connection is set outside tests / in worker threads, so this is a
|
|
141
|
+
// no-op there.
|
|
142
|
+
await this.configuration.runWithTestSharedConnectionContexts(async () => {
|
|
143
|
+
await this._run()
|
|
144
|
+
})
|
|
139
145
|
})
|
|
140
146
|
}
|
|
141
147
|
|
|
@@ -88,6 +88,11 @@ export default class VelociousHttpServerClientResponse {
|
|
|
88
88
|
* @type {string | null} */
|
|
89
89
|
filePath = null
|
|
90
90
|
|
|
91
|
+
/**
|
|
92
|
+
* File response completion callback.
|
|
93
|
+
* @type {((result: "completed" | "aborted") => void | Promise<void>) | null} */
|
|
94
|
+
fileOnFinished = null
|
|
95
|
+
|
|
91
96
|
/**
|
|
92
97
|
* Headers.
|
|
93
98
|
* @type {Record<string, string[]>} */
|
|
@@ -163,6 +168,7 @@ export default class VelociousHttpServerClientResponse {
|
|
|
163
168
|
*/
|
|
164
169
|
setBody(value) {
|
|
165
170
|
this.filePath = null
|
|
171
|
+
this.fileOnFinished = null
|
|
166
172
|
this.body = value
|
|
167
173
|
}
|
|
168
174
|
|
|
@@ -174,13 +180,23 @@ export default class VelociousHttpServerClientResponse {
|
|
|
174
180
|
return this.filePath
|
|
175
181
|
}
|
|
176
182
|
|
|
183
|
+
/**
|
|
184
|
+
* Gets the file response completion callback.
|
|
185
|
+
* @returns {((result: "completed" | "aborted") => void | Promise<void>) | null} - File response completion callback.
|
|
186
|
+
*/
|
|
187
|
+
getFileOnFinished() {
|
|
188
|
+
return this.fileOnFinished
|
|
189
|
+
}
|
|
190
|
+
|
|
177
191
|
/**
|
|
178
192
|
* Runs set file path.
|
|
179
193
|
* @param {string} path - File path.
|
|
194
|
+
* @param {((result: "completed" | "aborted") => void | Promise<void>) | null} [onFinished] - Completion callback.
|
|
180
195
|
* @returns {void} - No return value.
|
|
181
196
|
*/
|
|
182
|
-
setFilePath(path) {
|
|
197
|
+
setFilePath(path, onFinished = null) {
|
|
183
198
|
this.filePath = path
|
|
199
|
+
this.fileOnFinished = onFinished
|
|
184
200
|
this.body = null
|
|
185
201
|
}
|
|
186
202
|
|
|
@@ -239,7 +239,7 @@ export default class VelociousHttpServerClientWebsocketSession {
|
|
|
239
239
|
* Removes a closed connection from the session registry. Called by
|
|
240
240
|
* `VelociousWebsocketConnection.close()` after it sends the final
|
|
241
241
|
* `connection-closed` frame.
|
|
242
|
-
* @param {string} connectionId
|
|
242
|
+
* @param {string} connectionId - Closed connection identifier to remove.
|
|
243
243
|
* @returns {void}
|
|
244
244
|
*/
|
|
245
245
|
_removeConnection(connectionId) {
|
|
@@ -450,7 +450,7 @@ export default class VelociousHttpServerClientWebsocketSession {
|
|
|
450
450
|
* The actual message dispatch, extracted so
|
|
451
451
|
* `configuration.getWebsocketAroundRequest()` can wrap it in any
|
|
452
452
|
* per-request context (AsyncLocalStorage, tracing, etc.).
|
|
453
|
-
* @param {WebsocketSessionMessage} message
|
|
453
|
+
* @param {WebsocketSessionMessage} message - Decoded client frame to dispatch by message type.
|
|
454
454
|
* @returns {Promise<void>}
|
|
455
455
|
*/
|
|
456
456
|
async _handleMessageInner(message) {
|
|
@@ -731,8 +731,8 @@ export default class VelociousHttpServerClientWebsocketSession {
|
|
|
731
731
|
* fragmented message. Returns true when the fragment was accepted
|
|
732
732
|
* and false when the per-message cap was hit and the socket has
|
|
733
733
|
* been closed.
|
|
734
|
-
* @param {Buffer} payload
|
|
735
|
-
* @returns {boolean}
|
|
734
|
+
* @param {Buffer} payload - Continuation-frame bytes to append.
|
|
735
|
+
* @returns {boolean} - Whether the fragment was accepted.
|
|
736
736
|
*/
|
|
737
737
|
_appendFragment(payload) {
|
|
738
738
|
// Guard pushing first so `_enforceFragmentLimits` sees the final
|
|
@@ -750,7 +750,7 @@ export default class VelociousHttpServerClientWebsocketSession {
|
|
|
750
750
|
* close frame, and tears the session down. Returns true when the
|
|
751
751
|
* caller can continue processing, false when the session is being
|
|
752
752
|
* closed.
|
|
753
|
-
* @returns {boolean}
|
|
753
|
+
* @returns {boolean} - Whether fragment processing may continue.
|
|
754
754
|
*/
|
|
755
755
|
_enforceFragmentLimits() {
|
|
756
756
|
if (this._fragmentedPayloads === null) return true
|
|
@@ -1024,7 +1024,7 @@ export default class VelociousHttpServerClientWebsocketSession {
|
|
|
1024
1024
|
* The returned promise is stored at pause time and awaited at
|
|
1025
1025
|
* resume time so we can reject resume attempts from a different
|
|
1026
1026
|
* authenticated caller (signed out, swapped user, expired cookie).
|
|
1027
|
-
* @returns {Promise<?>}
|
|
1027
|
+
* @returns {Promise<?>} - Captured authenticated identity for resume validation.
|
|
1028
1028
|
*/
|
|
1029
1029
|
async _captureResumeIdentity() {
|
|
1030
1030
|
const resolver = this.configuration.getWebsocketSessionIdentityResolver?.()
|
|
@@ -1087,7 +1087,7 @@ export default class VelociousHttpServerClientWebsocketSession {
|
|
|
1087
1087
|
* created one whose socket just connected) transfers state from
|
|
1088
1088
|
* the paused session and instructs the client via
|
|
1089
1089
|
* `session-resumed` or `session-gone`.
|
|
1090
|
-
* @param {Record<string, ?>} message
|
|
1090
|
+
* @param {Record<string, ?>} message - Session-resume frame containing the paused session identifier.
|
|
1091
1091
|
* @returns {Promise<void>}
|
|
1092
1092
|
*/
|
|
1093
1093
|
async _handleSessionResume(message) {
|
|
@@ -1168,7 +1168,7 @@ export default class VelociousHttpServerClientWebsocketSession {
|
|
|
1168
1168
|
* Fires `onClose(reason)` on every live app-defined connection, then
|
|
1169
1169
|
* drops them from the registry. No network frame is sent — the
|
|
1170
1170
|
* socket is already going away.
|
|
1171
|
-
* @param {"session_destroyed" | "grace_expired" | "error"} reason
|
|
1171
|
+
* @param {"session_destroyed" | "grace_expired" | "error"} reason - Permanent teardown reason passed to each connection.
|
|
1172
1172
|
* @returns {Promise<void>}
|
|
1173
1173
|
*/
|
|
1174
1174
|
async _teardownConnections(reason) {
|
|
@@ -1194,7 +1194,7 @@ export default class VelociousHttpServerClientWebsocketSession {
|
|
|
1194
1194
|
* registered connection class, stores it on `_connections`, and
|
|
1195
1195
|
* fires `onConnect()`. Sends `connection-opened` on success or
|
|
1196
1196
|
* `connection-error` on failure.
|
|
1197
|
-
* @param {Record<string, ?>} message
|
|
1197
|
+
* @param {Record<string, ?>} message - Connection-open frame naming the connection type and identifier.
|
|
1198
1198
|
* @returns {Promise<void>}
|
|
1199
1199
|
*/
|
|
1200
1200
|
async _handleConnectionOpen(message) {
|
|
@@ -1242,7 +1242,7 @@ export default class VelociousHttpServerClientWebsocketSession {
|
|
|
1242
1242
|
|
|
1243
1243
|
/**
|
|
1244
1244
|
* Handles a `{type: "connection-message"}` from the client.
|
|
1245
|
-
* @param {Record<string, ?>} message
|
|
1245
|
+
* @param {Record<string, ?>} message - Connection-message frame containing the target identifier and body.
|
|
1246
1246
|
* @returns {Promise<void>}
|
|
1247
1247
|
*/
|
|
1248
1248
|
async _handleConnectionMessage(message) {
|
|
@@ -1267,7 +1267,7 @@ export default class VelociousHttpServerClientWebsocketSession {
|
|
|
1267
1267
|
/**
|
|
1268
1268
|
* Handles a `{type: "connection-close"}` from the client — fires
|
|
1269
1269
|
* `onClose("client_close")` and confirms with `connection-closed`.
|
|
1270
|
-
* @param {Record<string, ?>} message
|
|
1270
|
+
* @param {Record<string, ?>} message - Connection-close frame containing the target identifier.
|
|
1271
1271
|
* @returns {Promise<void>}
|
|
1272
1272
|
*/
|
|
1273
1273
|
async _handleConnectionClose(message) {
|
|
@@ -1296,7 +1296,7 @@ export default class VelociousHttpServerClientWebsocketSession {
|
|
|
1296
1296
|
* Handles `{type: "channel-subscribe"}` — runs `canSubscribe()`,
|
|
1297
1297
|
* registers with the Configuration's global routing registry on
|
|
1298
1298
|
* success, and sends `channel-subscribed` or `channel-error`.
|
|
1299
|
-
* @param {Record<string, ?>} message
|
|
1299
|
+
* @param {Record<string, ?>} message - Channel-subscribe frame describing the requested subscription.
|
|
1300
1300
|
* @returns {Promise<void>}
|
|
1301
1301
|
*/
|
|
1302
1302
|
async _handleChannelSubscribe(message) {
|
|
@@ -1421,7 +1421,7 @@ export default class VelociousHttpServerClientWebsocketSession {
|
|
|
1421
1421
|
/**
|
|
1422
1422
|
* Handles `{type: "channel-unsubscribe"}` from the client — calls
|
|
1423
1423
|
* `unsubscribed()` and sends `channel-unsubscribed`.
|
|
1424
|
-
* @param {Record<string, ?>} message
|
|
1424
|
+
* @param {Record<string, ?>} message - Channel-unsubscribe frame containing the subscription identifier.
|
|
1425
1425
|
* @returns {Promise<void>}
|
|
1426
1426
|
*/
|
|
1427
1427
|
async _handleChannelUnsubscribe(message) {
|