velocious 1.0.563 → 1.0.565
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 +3 -1
- package/build/background-jobs/cron-expression.js +12 -13
- package/build/background-jobs/main.js +6 -6
- package/build/background-jobs/runner-graceful-shutdown.js +2 -3
- package/build/background-jobs/scheduler.js +3 -3
- package/build/background-jobs/worker.js +8 -9
- package/build/beacon/client.js +3 -4
- package/build/database/drivers/sqlite/web-persistence.js +2 -5
- package/build/database/pool/async-tracked-multi-connection.js +65 -15
- package/build/database/pool/base.js +23 -7
- package/build/database/query/index.js +21 -22
- package/build/database/query/model-class-query.js +5 -6
- package/build/database/record/acts-as-list.js +37 -10
- package/build/database/record/attachments/normalize-input.js +9 -10
- package/build/database/record/attachments/store.js +2 -2
- package/build/database/record/auditing.js +7 -8
- package/build/database/record/index.js +4 -5
- package/build/environment-handlers/node/cli/commands/generate/base-models.js +4 -12
- package/build/environment-handlers/node/cli/commands/generate/frontend-models.js +1 -2
- package/build/frontend-model-controller.js +49 -56
- package/build/frontend-models/base.js +17 -19
- package/build/frontend-models/outgoing-event-buffer.js +3 -4
- package/build/frontend-models/query.js +40 -44
- package/build/frontend-models/resource-definition.js +7 -8
- package/build/frontend-models/transport-serialization.js +10 -12
- package/build/frontend-models/websocket-channel.js +12 -13
- package/build/http-server/client/websocket-session.js +4 -5
- package/build/http-server/client-delivery-queue.js +7 -8
- package/build/http-server/websocket-event-log-store.js +4 -6
- package/build/plugins/sqljs-wasm-route.js +3 -5
- package/build/src/background-jobs/cron-expression.d.ts +0 -12
- package/build/src/background-jobs/cron-expression.d.ts.map +1 -1
- package/build/src/background-jobs/cron-expression.js +13 -13
- package/build/src/background-jobs/main.d.ts.map +1 -1
- package/build/src/background-jobs/main.js +7 -7
- package/build/src/background-jobs/runner-graceful-shutdown.d.ts +0 -6
- package/build/src/background-jobs/runner-graceful-shutdown.d.ts.map +1 -1
- package/build/src/background-jobs/runner-graceful-shutdown.js +3 -3
- package/build/src/background-jobs/scheduler.d.ts +0 -3
- package/build/src/background-jobs/scheduler.d.ts.map +1 -1
- package/build/src/background-jobs/scheduler.js +4 -4
- package/build/src/background-jobs/worker.d.ts +0 -8
- package/build/src/background-jobs/worker.d.ts.map +1 -1
- package/build/src/background-jobs/worker.js +9 -9
- package/build/src/beacon/client.d.ts +0 -4
- package/build/src/beacon/client.d.ts.map +1 -1
- package/build/src/beacon/client.js +4 -4
- package/build/src/database/drivers/sqlite/web-persistence.d.ts +0 -14
- package/build/src/database/drivers/sqlite/web-persistence.d.ts.map +1 -1
- package/build/src/database/drivers/sqlite/web-persistence.js +3 -3
- package/build/src/database/pool/async-tracked-multi-connection.d.ts +29 -1
- package/build/src/database/pool/async-tracked-multi-connection.d.ts.map +1 -1
- package/build/src/database/pool/async-tracked-multi-connection.js +57 -15
- package/build/src/database/pool/base.d.ts +53 -4
- package/build/src/database/pool/base.d.ts.map +1 -1
- package/build/src/database/pool/base.js +23 -6
- package/build/src/database/query/index.d.ts +18 -39
- package/build/src/database/query/index.d.ts.map +1 -1
- package/build/src/database/query/index.js +22 -22
- package/build/src/database/query/model-class-query.d.ts +0 -5
- package/build/src/database/query/model-class-query.d.ts.map +1 -1
- package/build/src/database/query/model-class-query.js +6 -6
- package/build/src/database/record/acts-as-list.d.ts.map +1 -1
- package/build/src/database/record/acts-as-list.js +34 -12
- package/build/src/database/record/attachments/normalize-input.d.ts +0 -9
- package/build/src/database/record/attachments/normalize-input.d.ts.map +1 -1
- package/build/src/database/record/attachments/normalize-input.js +10 -10
- package/build/src/database/record/attachments/store.d.ts.map +1 -1
- package/build/src/database/record/attachments/store.js +2 -2
- package/build/src/database/record/auditing.d.ts +17 -24
- package/build/src/database/record/auditing.d.ts.map +1 -1
- package/build/src/database/record/auditing.js +8 -8
- package/build/src/database/record/index.d.ts +4 -4
- package/build/src/database/record/index.d.ts.map +1 -1
- package/build/src/database/record/index.js +5 -5
- package/build/src/environment-handlers/node/cli/commands/generate/base-models.d.ts.map +1 -1
- package/build/src/environment-handlers/node/cli/commands/generate/base-models.js +5 -13
- package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts +0 -39
- package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts.map +1 -1
- package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.js +2 -2
- package/build/src/frontend-model-controller.d.ts +1 -1
- package/build/src/frontend-model-controller.d.ts.map +1 -1
- package/build/src/frontend-model-controller.js +50 -50
- package/build/src/frontend-models/base.d.ts.map +1 -1
- package/build/src/frontend-models/base.js +18 -18
- package/build/src/frontend-models/outgoing-event-buffer.d.ts.map +1 -1
- package/build/src/frontend-models/outgoing-event-buffer.js +3 -3
- package/build/src/frontend-models/query.d.ts +56 -37
- package/build/src/frontend-models/query.d.ts.map +1 -1
- package/build/src/frontend-models/query.js +39 -39
- package/build/src/frontend-models/resource-definition.d.ts +0 -7
- package/build/src/frontend-models/resource-definition.d.ts.map +1 -1
- package/build/src/frontend-models/resource-definition.js +8 -8
- package/build/src/frontend-models/transport-serialization.d.ts +0 -10
- package/build/src/frontend-models/transport-serialization.d.ts.map +1 -1
- package/build/src/frontend-models/transport-serialization.js +11 -11
- package/build/src/frontend-models/websocket-channel.d.ts +0 -12
- package/build/src/frontend-models/websocket-channel.d.ts.map +1 -1
- package/build/src/frontend-models/websocket-channel.js +13 -13
- package/build/src/http-server/client/websocket-session.d.ts.map +1 -1
- package/build/src/http-server/client/websocket-session.js +5 -5
- package/build/src/http-server/client-delivery-queue.d.ts +7 -7
- package/build/src/http-server/client-delivery-queue.d.ts.map +1 -1
- package/build/src/http-server/client-delivery-queue.js +8 -8
- package/build/src/http-server/websocket-event-log-store.d.ts +0 -14
- package/build/src/http-server/websocket-event-log-store.d.ts.map +1 -1
- package/build/src/http-server/websocket-event-log-store.js +5 -5
- package/build/src/plugins/sqljs-wasm-route.d.ts.map +1 -1
- package/build/src/plugins/sqljs-wasm-route.js +4 -4
- package/build/src/sync/conflict-strategy.d.ts +0 -15
- package/build/src/sync/conflict-strategy.d.ts.map +1 -1
- package/build/src/sync/conflict-strategy.js +3 -3
- package/build/src/sync/device-identity.d.ts +0 -45
- 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 -41
- package/build/src/sync/local-mutation-log.d.ts.map +1 -1
- package/build/src/sync/local-mutation-log.js +9 -9
- package/build/src/sync/offline-grant.d.ts +0 -26
- package/build/src/sync/offline-grant.d.ts.map +1 -1
- package/build/src/sync/offline-grant.js +4 -4
- package/build/src/sync/peer-mutation-bundle.d.ts +0 -14
- package/build/src/sync/peer-mutation-bundle.d.ts.map +1 -1
- package/build/src/sync/peer-mutation-bundle.js +3 -3
- package/build/src/sync/server-change-feed.d.ts.map +1 -1
- package/build/src/sync/server-change-feed.js +33 -33
- package/build/src/sync/sync-api-client.d.ts +0 -9
- package/build/src/sync/sync-api-client.d.ts.map +1 -1
- package/build/src/sync/sync-api-client.js +2 -2
- package/build/src/sync/sync-envelope-replay-service.d.ts +38 -21
- package/build/src/sync/sync-envelope-replay-service.d.ts.map +1 -1
- package/build/src/sync/sync-envelope-replay-service.js +18 -18
- package/build/src/sync/sync-resource-base.d.ts +0 -7
- package/build/src/sync/sync-resource-base.d.ts.map +1 -1
- package/build/src/sync/sync-resource-base.js +2 -2
- package/build/src/sync/sync-scope-store.d.ts +0 -9
- package/build/src/sync/sync-scope-store.d.ts.map +1 -1
- package/build/src/sync/sync-scope-store.js +10 -10
- package/build/src/testing/test-filter-parser.d.ts +0 -10
- package/build/src/testing/test-filter-parser.d.ts.map +1 -1
- package/build/src/testing/test-filter-parser.js +11 -11
- package/build/src/testing/test-runner.d.ts +25 -91
- package/build/src/testing/test-runner.d.ts.map +1 -1
- package/build/src/testing/test-runner.js +113 -98
- package/build/src/testing/test.d.ts +8 -0
- package/build/src/testing/test.d.ts.map +1 -1
- package/build/src/testing/test.js +9 -9
- package/build/src/utils/backtrace-cleaner.d.ts.map +1 -1
- package/build/src/utils/backtrace-cleaner.js +9 -9
- package/build/src/utils/model-scope.d.ts +0 -8
- package/build/src/utils/model-scope.d.ts.map +1 -1
- package/build/src/utils/model-scope.js +3 -3
- package/build/src/utils/ransack.d.ts +52 -19
- package/build/src/utils/ransack.d.ts.map +1 -1
- package/build/src/utils/ransack.js +26 -26
- package/build/sync/conflict-strategy.js +3 -6
- package/build/sync/device-identity.js +4 -9
- package/build/sync/local-mutation-log.js +9 -14
- package/build/sync/offline-grant.js +4 -7
- package/build/sync/peer-mutation-bundle.js +2 -4
- package/build/sync/server-change-feed.js +32 -34
- package/build/sync/sync-api-client.js +1 -2
- package/build/sync/sync-envelope-replay-service.js +17 -19
- package/build/sync/sync-resource-base.js +1 -2
- package/build/sync/sync-scope-store.js +9 -10
- package/build/testing/test-filter-parser.js +10 -11
- package/build/testing/test-runner.js +116 -108
- package/build/testing/test.js +8 -9
- package/build/utils/backtrace-cleaner.js +8 -9
- package/build/utils/model-scope.js +3 -4
- package/build/utils/ransack.js +27 -34
- package/package.json +2 -1
- package/scripts/eslint-rules/typedefs-first.js +67 -0
- package/scripts/prewarm-chromedriver.js +26 -0
- package/src/background-jobs/cron-expression.js +12 -13
- package/src/background-jobs/main.js +6 -6
- package/src/background-jobs/runner-graceful-shutdown.js +2 -3
- package/src/background-jobs/scheduler.js +3 -3
- package/src/background-jobs/worker.js +8 -9
- package/src/beacon/client.js +3 -4
- package/src/database/drivers/sqlite/web-persistence.js +2 -5
- package/src/database/pool/async-tracked-multi-connection.js +65 -15
- package/src/database/pool/base.js +23 -7
- package/src/database/query/index.js +21 -22
- package/src/database/query/model-class-query.js +5 -6
- package/src/database/record/acts-as-list.js +37 -10
- package/src/database/record/attachments/normalize-input.js +9 -10
- package/src/database/record/attachments/store.js +2 -2
- package/src/database/record/auditing.js +7 -8
- package/src/database/record/index.js +4 -5
- package/src/environment-handlers/node/cli/commands/generate/base-models.js +4 -12
- package/src/environment-handlers/node/cli/commands/generate/frontend-models.js +1 -2
- package/src/frontend-model-controller.js +49 -56
- package/src/frontend-models/base.js +17 -19
- package/src/frontend-models/outgoing-event-buffer.js +3 -4
- package/src/frontend-models/query.js +40 -44
- package/src/frontend-models/resource-definition.js +7 -8
- package/src/frontend-models/transport-serialization.js +10 -12
- package/src/frontend-models/websocket-channel.js +12 -13
- package/src/http-server/client/websocket-session.js +4 -5
- package/src/http-server/client-delivery-queue.js +7 -8
- package/src/http-server/websocket-event-log-store.js +4 -6
- package/src/plugins/sqljs-wasm-route.js +3 -5
- package/src/sync/conflict-strategy.js +3 -6
- package/src/sync/device-identity.js +4 -9
- package/src/sync/local-mutation-log.js +9 -14
- package/src/sync/offline-grant.js +4 -7
- package/src/sync/peer-mutation-bundle.js +2 -4
- package/src/sync/server-change-feed.js +32 -34
- package/src/sync/sync-api-client.js +1 -2
- package/src/sync/sync-envelope-replay-service.js +17 -19
- package/src/sync/sync-resource-base.js +1 -2
- package/src/sync/sync-scope-store.js +9 -10
- package/src/testing/test-filter-parser.js +10 -11
- package/src/testing/test-runner.js +116 -108
- package/src/testing/test.js +8 -9
- package/src/utils/backtrace-cleaner.js +8 -9
- package/src/utils/model-scope.js +3 -4
- package/src/utils/ransack.js +27 -34
|
@@ -4,6 +4,18 @@ import VelociousWebsocketChannel from "../http-server/websocket-channel.js"
|
|
|
4
4
|
import Response from "../http-server/client/response.js"
|
|
5
5
|
import {serializeFrontendModelTransportValue} from "./transport-serialization.js"
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Defines this typedef.
|
|
9
|
+
* @typedef {{action?: string, id?: string | number, matchedEventFilterKeys?: string[], record?: import("./query.js").FrontendModelTransportValue, [key: string]: import("./query.js").FrontendModelTransportValue | string[] | undefined}} FrontendModelLifecycleBroadcastBody
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Defines this typedef.
|
|
13
|
+
* @typedef {{headers?: () => Record<string, string | string[] | undefined>, remoteAddress?: () => string | undefined}} FrontendModelWebsocketUpgradeRequest
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Defines this typedef.
|
|
17
|
+
* @typedef {{headers: () => Record<string, string | string[] | undefined>, header: (name: string) => string | string[] | undefined, metadata: (key?: string) => Record<string, import("./query.js").FrontendModelTransportValue> | import("./query.js").FrontendModelTransportValue | undefined, path: () => string, httpMethod: () => string, remoteAddress: () => string | undefined, origin: () => string | string[] | undefined}} FrontendModelWebsocketSyntheticRequest
|
|
18
|
+
*/
|
|
7
19
|
const EVENT_FILTER_KEYS = new Set(["joins", "key", "searches", "where"])
|
|
8
20
|
|
|
9
21
|
// Mirrors FRONTEND_MODELS_CHANNEL_NAME in ./websocket-publishers.js, duplicated here
|
|
@@ -21,19 +33,6 @@ function transportSerializationOptionsForConfiguration(configuration) {
|
|
|
21
33
|
}
|
|
22
34
|
}
|
|
23
35
|
|
|
24
|
-
/**
|
|
25
|
-
* Defines this typedef.
|
|
26
|
-
* @typedef {{action?: string, id?: string | number, matchedEventFilterKeys?: string[], record?: import("./query.js").FrontendModelTransportValue, [key: string]: import("./query.js").FrontendModelTransportValue | string[] | undefined}} FrontendModelLifecycleBroadcastBody
|
|
27
|
-
*/
|
|
28
|
-
/**
|
|
29
|
-
* Defines this typedef.
|
|
30
|
-
* @typedef {{headers?: () => Record<string, string | string[] | undefined>, remoteAddress?: () => string | undefined}} FrontendModelWebsocketUpgradeRequest
|
|
31
|
-
*/
|
|
32
|
-
/**
|
|
33
|
-
* Defines this typedef.
|
|
34
|
-
* @typedef {{headers: () => Record<string, string | string[] | undefined>, header: (name: string) => string | string[] | undefined, metadata: (key?: string) => Record<string, import("./query.js").FrontendModelTransportValue> | import("./query.js").FrontendModelTransportValue | undefined, path: () => string, httpMethod: () => string, remoteAddress: () => string | undefined, origin: () => string | string[] | undefined}} FrontendModelWebsocketSyntheticRequest
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
36
|
/**
|
|
38
37
|
* Per-session channel subscription for frontend-model lifecycle events.
|
|
39
38
|
* Replaces the legacy `FrontendModelWebsocketChannel` (Phase 3).
|
|
@@ -9,6 +9,10 @@ import WebsocketRequest from "./websocket-request.js"
|
|
|
9
9
|
import WebsocketChannel from "../websocket-channel.js"
|
|
10
10
|
import {websocketEventLogStoreForConfiguration} from "../websocket-event-log-store.js"
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Defines this typedef.
|
|
14
|
+
* @typedef {{type: "subscribe", channel: string, lastEventId?: string, params?: Record<string, ?>} | {type: "metadata", data?: Record<string, ?>} | {type?: "request", body?: ?, headers?: Record<string, ?>, id?: string | number | null, method: string, path: string} | Record<string, ?>} WebsocketSessionMessage
|
|
15
|
+
*/
|
|
12
16
|
const WEBSOCKET_FINAL_FRAME = 0x80
|
|
13
17
|
const WEBSOCKET_OPCODE_CONTINUATION = 0x0
|
|
14
18
|
const WEBSOCKET_OPCODE_TEXT = 0x1
|
|
@@ -31,11 +35,6 @@ const WEBSOCKET_MAX_INBOUND_FRAME_BYTES_BIGINT = BigInt(WEBSOCKET_MAX_FINAL_FRAM
|
|
|
31
35
|
/** Cap on fragment count for a single fragmented message. */
|
|
32
36
|
const WEBSOCKET_MAX_FRAGMENTED_MESSAGE_FRAGMENTS = 1024
|
|
33
37
|
|
|
34
|
-
/**
|
|
35
|
-
* Defines this typedef.
|
|
36
|
-
* @typedef {{type: "subscribe", channel: string, lastEventId?: string, params?: Record<string, ?>} | {type: "metadata", data?: Record<string, ?>} | {type?: "request", body?: ?, headers?: Record<string, ?>, id?: string | number | null, method: string, path: string} | Record<string, ?>} WebsocketSessionMessage
|
|
37
|
-
*/
|
|
38
|
-
|
|
39
38
|
/**
|
|
40
39
|
* Runs subscribe message.
|
|
41
40
|
* @param {WebsocketSessionMessage} message - Raw websocket message.
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {object} DeliveryTask
|
|
3
|
+
* @property {number} byteLength - Retained complete-buffer bytes.
|
|
4
|
+
* @property {boolean} countedFrame - Whether this task is an outbound frame.
|
|
5
|
+
* @property {() => Promise<void>} delivery - Delivery operation.
|
|
6
|
+
* @property {(error?: Error) => void} settle - Settles the enqueue promise.
|
|
7
|
+
*/
|
|
1
8
|
// @ts-check
|
|
2
9
|
|
|
3
10
|
export class ClientDeliveryQueueOverflowError extends Error {
|
|
@@ -17,14 +24,6 @@ export class ClientDeliveryQueueOverflowError extends Error {
|
|
|
17
24
|
}
|
|
18
25
|
}
|
|
19
26
|
|
|
20
|
-
/**
|
|
21
|
-
* @typedef {object} DeliveryTask
|
|
22
|
-
* @property {number} byteLength - Retained complete-buffer bytes.
|
|
23
|
-
* @property {boolean} countedFrame - Whether this task is an outbound frame.
|
|
24
|
-
* @property {() => Promise<void>} delivery - Delivery operation.
|
|
25
|
-
* @property {(error?: Error) => void} settle - Settles the enqueue promise.
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
27
|
export default class ClientDeliveryQueue {
|
|
29
28
|
/**
|
|
30
29
|
* Builds a per-client delivery queue.
|
|
@@ -4,11 +4,6 @@ import {randomUUID} from "crypto"
|
|
|
4
4
|
import TableData from "../database/table-data/index.js"
|
|
5
5
|
import Logger from "../logger.js"
|
|
6
6
|
|
|
7
|
-
const EVENTS_TABLE = "websocket_channel_events"
|
|
8
|
-
const REPLAY_CHANNELS_TABLE = "websocket_replay_channels"
|
|
9
|
-
const DEFAULT_RETENTION_MS = 10 * 60 * 1000
|
|
10
|
-
const stores = new WeakMap()
|
|
11
|
-
|
|
12
7
|
/**
|
|
13
8
|
* WebsocketEventRow type.
|
|
14
9
|
* @typedef {object} WebsocketEventRow
|
|
@@ -18,12 +13,15 @@ const stores = new WeakMap()
|
|
|
18
13
|
* @property {string} payload_json - Serialized payload.
|
|
19
14
|
* @property {number | string} sequence - Sequence number.
|
|
20
15
|
*/
|
|
21
|
-
|
|
22
16
|
/**
|
|
23
17
|
* WebsocketReplayChannelRow type.
|
|
24
18
|
* @typedef {object} WebsocketReplayChannelRow
|
|
25
19
|
* @property {string} channel - Channel name.
|
|
26
20
|
*/
|
|
21
|
+
const EVENTS_TABLE = "websocket_channel_events"
|
|
22
|
+
const REPLAY_CHANNELS_TABLE = "websocket_replay_channels"
|
|
23
|
+
const DEFAULT_RETENTION_MS = 10 * 60 * 1000
|
|
24
|
+
const stores = new WeakMap()
|
|
27
25
|
|
|
28
26
|
/**
|
|
29
27
|
* Runs the websocketEventLogStoreForConfiguration helper.
|
|
@@ -2,23 +2,21 @@ import {createRequire} from "node:module"
|
|
|
2
2
|
import path from "node:path"
|
|
3
3
|
import SqlJsWasmRouteController from "./sqljs-wasm-route-controller.js"
|
|
4
4
|
|
|
5
|
-
const require = createRequire(import.meta.url)
|
|
6
|
-
const sqlJsEntryPath = require.resolve("sql.js")
|
|
7
|
-
const sqlJsDistDirectory = path.dirname(sqlJsEntryPath)
|
|
8
|
-
|
|
9
5
|
/**
|
|
10
6
|
* InstallSqlJsWasmRouteArgs type.
|
|
11
7
|
* @typedef {object} InstallSqlJsWasmRouteArgs
|
|
12
8
|
* @property {import("../configuration.js").default} configuration - Velocious configuration instance.
|
|
13
9
|
* @property {string} [routePrefix] - Route prefix used for sql.js asset serving.
|
|
14
10
|
*/
|
|
15
|
-
|
|
16
11
|
/**
|
|
17
12
|
* SqlJsLocateFileFromBackendArgs type.
|
|
18
13
|
* @typedef {object} SqlJsLocateFileFromBackendArgs
|
|
19
14
|
* @property {string} backendBaseUrl - Backend base URL (for example `https://api.example.com`).
|
|
20
15
|
* @property {string} [routePrefix] - Route prefix used for sql.js asset serving.
|
|
21
16
|
*/
|
|
17
|
+
const require = createRequire(import.meta.url)
|
|
18
|
+
const sqlJsEntryPath = require.resolve("sql.js")
|
|
19
|
+
const sqlJsDistDirectory = path.dirname(sqlJsEntryPath)
|
|
22
20
|
|
|
23
21
|
/**
|
|
24
22
|
* Runs normalize route prefix.
|
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
const CONFLICT_STRATEGIES = new Set(["optimisticVersion", "serverWins", "lastWriterWins", "fieldThreeWay", "appendOnly"])
|
|
4
|
-
|
|
5
1
|
/**
|
|
6
2
|
* @typedef {null | string | number | boolean | unknown[] | Record<string, unknown>} SyncJsonValue
|
|
7
3
|
*/
|
|
8
|
-
|
|
9
4
|
/**
|
|
10
5
|
* @typedef {object} SyncConflictRecord
|
|
11
6
|
* @property {Record<string, SyncJsonValue>} attributes - Record attributes.
|
|
12
7
|
* @property {string | number | boolean | null} [version] - Record version value.
|
|
13
8
|
*/
|
|
14
|
-
|
|
15
9
|
/**
|
|
16
10
|
* @typedef {object} SyncConflictResult
|
|
17
11
|
* @property {Record<string, SyncJsonValue>} [attributes] - Attributes to apply when replay may continue.
|
|
@@ -19,6 +13,9 @@ const CONFLICT_STRATEGIES = new Set(["optimisticVersion", "serverWins", "lastWri
|
|
|
19
13
|
* @property {"applied" | "conflict" | "rejected"} status - Conflict decision.
|
|
20
14
|
* @property {string} strategy - Strategy that produced the decision.
|
|
21
15
|
*/
|
|
16
|
+
// @ts-check
|
|
17
|
+
|
|
18
|
+
const CONFLICT_STRATEGIES = new Set(["optimisticVersion", "serverWins", "lastWriterWins", "fieldThreeWay", "appendOnly"])
|
|
22
19
|
|
|
23
20
|
/**
|
|
24
21
|
* Evaluates a replay mutation against server/base state using a sync conflict strategy.
|
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
const ECDSA_P256_SHA256_ALGORITHM = "ECDSA-P256-SHA256"
|
|
4
|
-
const ECDSA_P256_SHA256_SIGNATURE_PREFIX = "ecdsa-p256-sha256-"
|
|
5
|
-
|
|
6
1
|
/**
|
|
7
2
|
* JSON Web Key used by the sync signing helpers.
|
|
8
3
|
* @typedef {import("node:crypto").webcrypto.JsonWebKey} SyncJsonWebKey
|
|
9
4
|
*/
|
|
10
|
-
|
|
11
5
|
/**
|
|
12
6
|
* Backend-signed device certificate payload.
|
|
13
7
|
* @typedef {object} DeviceCertificatePayload
|
|
@@ -18,7 +12,6 @@ const ECDSA_P256_SHA256_SIGNATURE_PREFIX = "ecdsa-p256-sha256-"
|
|
|
18
12
|
* @property {string} expiresAt - ISO timestamp after which the certificate is invalid.
|
|
19
13
|
* @property {string} issuedAt - ISO timestamp when the backend issued the certificate.
|
|
20
14
|
*/
|
|
21
|
-
|
|
22
15
|
/**
|
|
23
16
|
* Backend-signed device certificate envelope.
|
|
24
17
|
* @typedef {object} DeviceCertificate
|
|
@@ -26,7 +19,6 @@ const ECDSA_P256_SHA256_SIGNATURE_PREFIX = "ecdsa-p256-sha256-"
|
|
|
26
19
|
* @property {DeviceCertificatePayload} certificate - Certificate payload.
|
|
27
20
|
* @property {string} signature - Backend signature over the certificate payload.
|
|
28
21
|
*/
|
|
29
|
-
|
|
30
22
|
/**
|
|
31
23
|
* Sync mutation payload signed by a device.
|
|
32
24
|
* @typedef {object} SyncMutation
|
|
@@ -43,7 +35,6 @@ const ECDSA_P256_SHA256_SIGNATURE_PREFIX = "ecdsa-p256-sha256-"
|
|
|
43
35
|
* @property {Record<string, import("../configuration-types.js").FrontendModelSyncJsonValue>} [payload] - Domain command payload.
|
|
44
36
|
* @property {string} policyHash - Sync policy hash the mutation was checked against.
|
|
45
37
|
*/
|
|
46
|
-
|
|
47
38
|
/**
|
|
48
39
|
* Device-signed mutation envelope.
|
|
49
40
|
* @typedef {object} SignedSyncMutation
|
|
@@ -52,6 +43,10 @@ const ECDSA_P256_SHA256_SIGNATURE_PREFIX = "ecdsa-p256-sha256-"
|
|
|
52
43
|
* @property {SyncMutation} mutation - Mutation payload.
|
|
53
44
|
* @property {string} signature - Device signature over the mutation envelope.
|
|
54
45
|
*/
|
|
46
|
+
// @ts-check
|
|
47
|
+
|
|
48
|
+
const ECDSA_P256_SHA256_ALGORITHM = "ECDSA-P256-SHA256"
|
|
49
|
+
const ECDSA_P256_SHA256_SIGNATURE_PREFIX = "ecdsa-p256-sha256-"
|
|
55
50
|
|
|
56
51
|
/**
|
|
57
52
|
* Generates an ECDSA P-256 keypair exported as JWKs.
|
|
@@ -1,19 +1,8 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
const DEFAULT_STORAGE_KEY = "velocious.sync.localMutationLog"
|
|
4
|
-
const PENDING_STATUS_VALUES = /** @type {LocalMutationStatus[]} */ (["pending", "applied-locally", "peer-applied"])
|
|
5
|
-
const PENDING_STATUSES = new Set(PENDING_STATUS_VALUES)
|
|
6
|
-
const MUTATION_STATUSES = new Set([...PENDING_STATUSES, "conflict", "rejected", "synced"])
|
|
7
|
-
const TERMINAL_STATUSES = new Set(["rejected", "synced"])
|
|
8
|
-
/** @type {Map<string, Promise<unknown>>} */
|
|
9
|
-
const STORAGE_KEY_LOCKS = new Map()
|
|
10
|
-
|
|
11
1
|
/**
|
|
12
2
|
* Local mutation log record query options.
|
|
13
3
|
* @typedef {object} LocalMutationLogRecordsOptions
|
|
14
4
|
* @property {LocalMutationStatus[]} [statuses] - Optional status filter.
|
|
15
5
|
*/
|
|
16
|
-
|
|
17
6
|
/**
|
|
18
7
|
* Local mutation log row-oriented storage adapter.
|
|
19
8
|
*
|
|
@@ -28,19 +17,16 @@ const STORAGE_KEY_LOCKS = new Map()
|
|
|
28
17
|
* @property {(storageKey: string, options?: LocalMutationLogRecordsOptions) => Promise<LocalMutationLogRecord[]> | LocalMutationLogRecord[]} records - Reads log records.
|
|
29
18
|
* @property {(storageKey: string, record: LocalMutationLogRecord) => Promise<void> | void} updateRecord - Replaces one log record.
|
|
30
19
|
*/
|
|
31
|
-
|
|
32
20
|
/**
|
|
33
21
|
* Local sync mutation dependency metadata.
|
|
34
22
|
* @typedef {object} LocalMutationDependency
|
|
35
23
|
* @property {string} clientMutationId - Client mutation id this mutation depends on.
|
|
36
24
|
* @property {string} model - Dependent model/resource name.
|
|
37
25
|
*/
|
|
38
|
-
|
|
39
26
|
/**
|
|
40
27
|
* Local mutation log status.
|
|
41
28
|
* @typedef {"pending" | "applied-locally" | "peer-applied" | "conflict" | "rejected" | "synced"} LocalMutationStatus
|
|
42
29
|
* */
|
|
43
|
-
|
|
44
30
|
/**
|
|
45
31
|
* Local mutation log record.
|
|
46
32
|
* @typedef {object} LocalMutationLogRecord
|
|
@@ -53,6 +39,15 @@ const STORAGE_KEY_LOCKS = new Map()
|
|
|
53
39
|
* @property {Record<string, import("../configuration-types.js").FrontendModelSyncJsonValue>} [syncResult] - Backend replay/result metadata.
|
|
54
40
|
* @property {string} updatedAt - ISO timestamp when the record was last changed.
|
|
55
41
|
*/
|
|
42
|
+
// @ts-check
|
|
43
|
+
|
|
44
|
+
const DEFAULT_STORAGE_KEY = "velocious.sync.localMutationLog"
|
|
45
|
+
const PENDING_STATUS_VALUES = /** @type {LocalMutationStatus[]} */ (["pending", "applied-locally", "peer-applied"])
|
|
46
|
+
const PENDING_STATUSES = new Set(PENDING_STATUS_VALUES)
|
|
47
|
+
const MUTATION_STATUSES = new Set([...PENDING_STATUSES, "conflict", "rejected", "synced"])
|
|
48
|
+
const TERMINAL_STATUSES = new Set(["rejected", "synced"])
|
|
49
|
+
/** @type {Map<string, Promise<unknown>>} */
|
|
50
|
+
const STORAGE_KEY_LOCKS = new Map()
|
|
56
51
|
|
|
57
52
|
/** Client-side append-only sync mutation log with pluggable persistent storage. */
|
|
58
53
|
export default class LocalMutationLog {
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
const OFFLINE_GRANT_SIGNATURE_ALGORITHM = "HS256"
|
|
4
|
-
const OFFLINE_GRANT_SIGNATURE_PREFIX = "hmac-sha256-"
|
|
5
|
-
|
|
6
1
|
/**
|
|
7
2
|
* Signed offline grant envelope.
|
|
8
3
|
* @typedef {object} SignedOfflineGrant
|
|
@@ -11,7 +6,6 @@ const OFFLINE_GRANT_SIGNATURE_PREFIX = "hmac-sha256-"
|
|
|
11
6
|
* @property {string} keyId - Signing key id.
|
|
12
7
|
* @property {string} signature - Hex HMAC signature with a hmac-sha256 prefix.
|
|
13
8
|
*/
|
|
14
|
-
|
|
15
9
|
/**
|
|
16
10
|
* Backend-issued offline grant payload.
|
|
17
11
|
* @typedef {object} OfflineGrant
|
|
@@ -23,7 +17,6 @@ const OFFLINE_GRANT_SIGNATURE_PREFIX = "hmac-sha256-"
|
|
|
23
17
|
* @property {Record<string, import("../configuration-types.js").FrontendModelSyncJsonValue>} scopes - Materialized grant scopes.
|
|
24
18
|
* @property {string} userId - Actor user id allowed to use the grant.
|
|
25
19
|
*/
|
|
26
|
-
|
|
27
20
|
/**
|
|
28
21
|
* Offline grant signing key.
|
|
29
22
|
* @typedef {object} OfflineGrantSigningKey
|
|
@@ -31,6 +24,10 @@ const OFFLINE_GRANT_SIGNATURE_PREFIX = "hmac-sha256-"
|
|
|
31
24
|
* @property {string} id - Public key id included in signed grant envelopes.
|
|
32
25
|
* @property {string} secret - Private HMAC secret. Never expose this to clients.
|
|
33
26
|
*/
|
|
27
|
+
// @ts-check
|
|
28
|
+
|
|
29
|
+
const OFFLINE_GRANT_SIGNATURE_ALGORITHM = "HS256"
|
|
30
|
+
const OFFLINE_GRANT_SIGNATURE_PREFIX = "hmac-sha256-"
|
|
34
31
|
|
|
35
32
|
/**
|
|
36
33
|
* Creates a signed offline grant envelope.
|
|
@@ -2,9 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import {createSignedMutation, mutationIdempotencyKey, verifySignedMutation} from "./device-identity.js"
|
|
4
4
|
|
|
5
|
-
const PEER_MUTATION_BUNDLE_FORMAT = "velocious.sync.peer-mutation-bundle.v1"
|
|
6
|
-
const EXPORTABLE_STATUSES = new Set(["pending", "applied-locally", "conflict"])
|
|
7
|
-
|
|
8
5
|
/**
|
|
9
6
|
* Peer mutation bundle exported by a device for offline/P2P transfer.
|
|
10
7
|
* @typedef {object} PeerMutationBundle
|
|
@@ -12,7 +9,6 @@ const EXPORTABLE_STATUSES = new Set(["pending", "applied-locally", "conflict"])
|
|
|
12
9
|
* @property {"velocious.sync.peer-mutation-bundle.v1"} format - Bundle format identifier.
|
|
13
10
|
* @property {PeerMutationBundleEntry[]} mutations - Signed mutations in local sequence order.
|
|
14
11
|
*/
|
|
15
|
-
|
|
16
12
|
/**
|
|
17
13
|
* One peer mutation bundle entry.
|
|
18
14
|
* @typedef {object} PeerMutationBundleEntry
|
|
@@ -20,6 +16,8 @@ const EXPORTABLE_STATUSES = new Set(["pending", "applied-locally", "conflict"])
|
|
|
20
16
|
* @property {number} [localSequence] - Exporting device's local mutation sequence.
|
|
21
17
|
* @property {import("./device-identity.js").SignedSyncMutation} signedMutation - Device-signed mutation envelope.
|
|
22
18
|
*/
|
|
19
|
+
const PEER_MUTATION_BUNDLE_FORMAT = "velocious.sync.peer-mutation-bundle.v1"
|
|
20
|
+
const EXPORTABLE_STATUSES = new Set(["pending", "applied-locally", "conflict"])
|
|
23
21
|
|
|
24
22
|
/**
|
|
25
23
|
* Exports local non-terminal mutations as a signed peer-transfer bundle.
|
|
@@ -4,6 +4,38 @@ import {randomUUID} from "crypto"
|
|
|
4
4
|
import TableData from "../database/table-data/index.js"
|
|
5
5
|
import stableJsonStringify from "./stable-json.js"
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {object} ServerChangeFeedEntry
|
|
9
|
+
* @property {string | null} actorDeviceId - Signed mutation actor device id when available.
|
|
10
|
+
* @property {string | null} actorUserId - Signed mutation actor user id when available.
|
|
11
|
+
* @property {Record<string, ?> | null} attributes - Serialized mutation attributes.
|
|
12
|
+
* @property {string} createdAt - Server change creation timestamp.
|
|
13
|
+
* @property {string} id - Server change id.
|
|
14
|
+
* @property {string | null} idempotencyKey - Mutation idempotency key when available.
|
|
15
|
+
* @property {string} model - Frontend model name.
|
|
16
|
+
* @property {string} operation - Mutation operation.
|
|
17
|
+
* @property {Record<string, ?> | null} payload - Serialized mutation payload.
|
|
18
|
+
* @property {string | null} recordId - Changed record id when known.
|
|
19
|
+
* @property {Record<string, ?> | null} response - Command response payload.
|
|
20
|
+
* @property {Record<string, ?> | null} scope - Offline grant scope.
|
|
21
|
+
* @property {number} serverSequence - Monotonic server sequence.
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* @typedef {object} ServerChangeFeedRow
|
|
25
|
+
* @property {string | null} actor_device_id - Actor device id.
|
|
26
|
+
* @property {string | null} actor_user_id - Actor user id.
|
|
27
|
+
* @property {string | null} attributes_json - Attributes JSON.
|
|
28
|
+
* @property {Date | string} created_at - Creation time.
|
|
29
|
+
* @property {string} id - Entry id.
|
|
30
|
+
* @property {string | null} idempotency_key - Mutation idempotency key.
|
|
31
|
+
* @property {string} model - Frontend model name.
|
|
32
|
+
* @property {string} operation - Mutation operation.
|
|
33
|
+
* @property {string | null} payload_json - Mutation payload JSON.
|
|
34
|
+
* @property {string | null} record_id - Record id.
|
|
35
|
+
* @property {string | null} response_json - Response JSON.
|
|
36
|
+
* @property {string | null} scope_json - Scope JSON.
|
|
37
|
+
* @property {number | string} server_sequence - Server sequence.
|
|
38
|
+
*/
|
|
7
39
|
const DEFAULT_RETENTION_SIZE = 10000
|
|
8
40
|
const DEFAULT_PAGE_SIZE = 100
|
|
9
41
|
const MAX_PAGE_SIZE = 1000
|
|
@@ -464,37 +496,3 @@ function scopesEqual(changeScope, requestedScope) {
|
|
|
464
496
|
|
|
465
497
|
return stableJsonStringify(changeScope || null) === stableJsonStringify(requestedScope)
|
|
466
498
|
}
|
|
467
|
-
|
|
468
|
-
/**
|
|
469
|
-
* @typedef {object} ServerChangeFeedEntry
|
|
470
|
-
* @property {string | null} actorDeviceId - Signed mutation actor device id when available.
|
|
471
|
-
* @property {string | null} actorUserId - Signed mutation actor user id when available.
|
|
472
|
-
* @property {Record<string, ?> | null} attributes - Serialized mutation attributes.
|
|
473
|
-
* @property {string} createdAt - Server change creation timestamp.
|
|
474
|
-
* @property {string} id - Server change id.
|
|
475
|
-
* @property {string | null} idempotencyKey - Mutation idempotency key when available.
|
|
476
|
-
* @property {string} model - Frontend model name.
|
|
477
|
-
* @property {string} operation - Mutation operation.
|
|
478
|
-
* @property {Record<string, ?> | null} payload - Serialized mutation payload.
|
|
479
|
-
* @property {string | null} recordId - Changed record id when known.
|
|
480
|
-
* @property {Record<string, ?> | null} response - Command response payload.
|
|
481
|
-
* @property {Record<string, ?> | null} scope - Offline grant scope.
|
|
482
|
-
* @property {number} serverSequence - Monotonic server sequence.
|
|
483
|
-
*/
|
|
484
|
-
|
|
485
|
-
/**
|
|
486
|
-
* @typedef {object} ServerChangeFeedRow
|
|
487
|
-
* @property {string | null} actor_device_id - Actor device id.
|
|
488
|
-
* @property {string | null} actor_user_id - Actor user id.
|
|
489
|
-
* @property {string | null} attributes_json - Attributes JSON.
|
|
490
|
-
* @property {Date | string} created_at - Creation time.
|
|
491
|
-
* @property {string} id - Entry id.
|
|
492
|
-
* @property {string | null} idempotency_key - Mutation idempotency key.
|
|
493
|
-
* @property {string} model - Frontend model name.
|
|
494
|
-
* @property {string} operation - Mutation operation.
|
|
495
|
-
* @property {string | null} payload_json - Mutation payload JSON.
|
|
496
|
-
* @property {string | null} record_id - Record id.
|
|
497
|
-
* @property {string | null} response_json - Response JSON.
|
|
498
|
-
* @property {string | null} scope_json - Scope JSON.
|
|
499
|
-
* @property {number | string} server_sequence - Server sequence.
|
|
500
|
-
*/
|
|
@@ -4,8 +4,6 @@ import {optionalBoolean, optionalInteger} from "typanic"
|
|
|
4
4
|
|
|
5
5
|
import recordChanges from "../database/record-changes.js"
|
|
6
6
|
|
|
7
|
-
const syncTaskPromises = new Map()
|
|
8
|
-
|
|
9
7
|
/** @typedef {import("./sync-api-client-types.js").SyncChangeApplyResult} SyncChangeApplyResult */
|
|
10
8
|
/** @typedef {import("./sync-api-client-types.js").SyncChangeEnvelope} SyncChangeEnvelope */
|
|
11
9
|
/** @typedef {import("./sync-api-client-types.js").SyncChangesRequest} SyncChangesRequest */
|
|
@@ -15,6 +13,7 @@ const syncTaskPromises = new Map()
|
|
|
15
13
|
/** @typedef {import("./sync-api-client-types.js").SyncReplayItem} SyncReplayItem */
|
|
16
14
|
/** @typedef {import("./sync-api-client-types.js").SyncReplayResponse} SyncReplayResponse */
|
|
17
15
|
/** @typedef {import("./sync-api-client-types.js").SyncResourceConfig} SyncResourceConfig */
|
|
16
|
+
const syncTaskPromises = new Map()
|
|
18
17
|
|
|
19
18
|
/**
|
|
20
19
|
* Generic client-side helper for replaying pending sync envelopes through the
|
|
@@ -7,6 +7,23 @@ import SyncReplayUpsertApplier from "./sync-replay-upsert-applier.js"
|
|
|
7
7
|
import {ValidationError} from "../database/record/index.js"
|
|
8
8
|
import VelociousError from "../velocious-error.js"
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Resolved routed-resource registration for one replay resource type.
|
|
12
|
+
* @typedef {object} SyncReplayResourceRegistration
|
|
13
|
+
* @property {string} modelName - Effective frontend model name.
|
|
14
|
+
* @property {import("../configuration-types.js").FrontendModelResourceClassType} resourceClass - Routed resource class.
|
|
15
|
+
* @property {import("../configuration-types.js").NormalizedFrontendModelResourceConfiguration | null} resourceConfiguration - Normalized resource configuration when registry-resolved.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* @typedef {object} SyncReplayMutation
|
|
19
|
+
* @property {Date} clientUpdatedAt - Client-side mutation timestamp.
|
|
20
|
+
* @property {Record<string, ?>} data - Parsed mutation payload.
|
|
21
|
+
* @property {?} id - Client sync row id for per-sync responses.
|
|
22
|
+
* @property {string} resourceId - Resource id as a string.
|
|
23
|
+
* @property {string} resourceType - Resource/model name.
|
|
24
|
+
* @property {string} serializedData - JSON serialized mutation payload.
|
|
25
|
+
* @property {string} syncType - Sync operation type.
|
|
26
|
+
*/
|
|
10
27
|
/**
|
|
11
28
|
* One declarative broadcast fanned out after a mutation applies.
|
|
12
29
|
* @typedef {object} SyncReplayBroadcast
|
|
@@ -778,22 +795,3 @@ export default class SyncEnvelopeReplayService {
|
|
|
778
795
|
await deliverDeclaredBroadcasts({args, broadcaster: this.broadcaster, broadcasts: this.broadcasts})
|
|
779
796
|
}
|
|
780
797
|
}
|
|
781
|
-
|
|
782
|
-
/**
|
|
783
|
-
* Resolved routed-resource registration for one replay resource type.
|
|
784
|
-
* @typedef {object} SyncReplayResourceRegistration
|
|
785
|
-
* @property {string} modelName - Effective frontend model name.
|
|
786
|
-
* @property {import("../configuration-types.js").FrontendModelResourceClassType} resourceClass - Routed resource class.
|
|
787
|
-
* @property {import("../configuration-types.js").NormalizedFrontendModelResourceConfiguration | null} resourceConfiguration - Normalized resource configuration when registry-resolved.
|
|
788
|
-
*/
|
|
789
|
-
|
|
790
|
-
/**
|
|
791
|
-
* @typedef {object} SyncReplayMutation
|
|
792
|
-
* @property {Date} clientUpdatedAt - Client-side mutation timestamp.
|
|
793
|
-
* @property {Record<string, ?>} data - Parsed mutation payload.
|
|
794
|
-
* @property {?} id - Client sync row id for per-sync responses.
|
|
795
|
-
* @property {string} resourceId - Resource id as a string.
|
|
796
|
-
* @property {string} resourceType - Resource/model name.
|
|
797
|
-
* @property {string} serializedData - JSON serialized mutation payload.
|
|
798
|
-
* @property {string} syncType - Sync operation type.
|
|
799
|
-
*/
|
|
@@ -7,8 +7,6 @@ import SyncEnvelopeReplayService from "./sync-envelope-replay-service.js"
|
|
|
7
7
|
import SyncModelChangeFeedService from "./sync-model-change-feed-service.js"
|
|
8
8
|
import VelociousError from "../velocious-error.js"
|
|
9
9
|
|
|
10
|
-
const QUICK_SEARCH_COLUMN = "quickSearch"
|
|
11
|
-
|
|
12
10
|
/**
|
|
13
11
|
* Optional client-declared sync scope carried on a changes request.
|
|
14
12
|
* @typedef {object} SerializedChangesScope
|
|
@@ -16,6 +14,7 @@ const QUICK_SEARCH_COLUMN = "quickSearch"
|
|
|
16
14
|
* @property {string | null} resourceType - Client resource/model name the scope was declared for, or null for the all-types (user) scope: one scope covering every resource type this resource authorizes for the caller, so a sync authorizes once however many types it serves.
|
|
17
15
|
* @property {string[] | null} resourceTypes - For the all-types scope, the resource types the client can apply. A cheap delivery/type filter only - it narrows, never widens, what the app's authorization already allows. Null for a type-declared scope.
|
|
18
16
|
*/
|
|
17
|
+
const QUICK_SEARCH_COLUMN = "quickSearch"
|
|
19
18
|
|
|
20
19
|
/**
|
|
21
20
|
* Base resource for Velocious sync endpoints.
|
|
@@ -6,6 +6,15 @@ import UUID from "pure-uuid"
|
|
|
6
6
|
import {scopeKey} from "./query-scope.js"
|
|
7
7
|
import stableJsonStringify from "./stable-json.js"
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {object} SyncScopeRow
|
|
11
|
+
* @property {Record<string, ?>} conditions - Scope attribute conditions.
|
|
12
|
+
* @property {string | null} cursorPayload - Persisted cursor JSON payload.
|
|
13
|
+
* @property {string} id - Scope row id.
|
|
14
|
+
* @property {string | null} resourceType - Scope resource/model name, or null for the all-types (user) scope.
|
|
15
|
+
* @property {string} scopeDigest - Fixed-size deterministic digest of the canonical scope key.
|
|
16
|
+
* @property {string} state - Scope state ("active" or "removed").
|
|
17
|
+
*/
|
|
9
18
|
const TABLE_NAME = "velocious_sync_scopes"
|
|
10
19
|
const SCOPE_DIGEST_PREFIX = "velocious-sync-scope:"
|
|
11
20
|
|
|
@@ -19,16 +28,6 @@ function scopeDigestForScope(scope) {
|
|
|
19
28
|
return new UUID(5, "ns:URL", `${SCOPE_DIGEST_PREFIX}${scopeKey(scope)}`).format()
|
|
20
29
|
}
|
|
21
30
|
|
|
22
|
-
/**
|
|
23
|
-
* @typedef {object} SyncScopeRow
|
|
24
|
-
* @property {Record<string, ?>} conditions - Scope attribute conditions.
|
|
25
|
-
* @property {string | null} cursorPayload - Persisted cursor JSON payload.
|
|
26
|
-
* @property {string} id - Scope row id.
|
|
27
|
-
* @property {string | null} resourceType - Scope resource/model name, or null for the all-types (user) scope.
|
|
28
|
-
* @property {string} scopeDigest - Fixed-size deterministic digest of the canonical scope key.
|
|
29
|
-
* @property {string} state - Scope state ("active" or "removed").
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
31
|
/**
|
|
33
32
|
* Framework-owned local persistence for declared sync scopes and their cursors.
|
|
34
33
|
*
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ParseFiltersResult type.
|
|
3
|
+
* @typedef {object} ParseFiltersResult
|
|
4
|
+
* @property {string[]} includeTags - Tags to include.
|
|
5
|
+
* @property {string[]} excludeTags - Tags to exclude.
|
|
6
|
+
* @property {string[]} examplePatterns - Example name patterns.
|
|
7
|
+
* @property {string[]} filteredProcessArgs - Remaining process args with filter flags removed.
|
|
8
|
+
* @property {number | undefined} groups - Total number of groups for test splitting.
|
|
9
|
+
* @property {number | undefined} groupNumber - Which group to run (1-indexed).
|
|
10
|
+
*/
|
|
1
11
|
// @ts-check
|
|
2
12
|
|
|
3
13
|
const INCLUDE_TAG_FLAGS = new Set(["--tag", "--include-tag", "-t"])
|
|
@@ -50,17 +60,6 @@ export function normalizeExamplePatterns(patterns) {
|
|
|
50
60
|
return normalized
|
|
51
61
|
}
|
|
52
62
|
|
|
53
|
-
/**
|
|
54
|
-
* ParseFiltersResult type.
|
|
55
|
-
* @typedef {object} ParseFiltersResult
|
|
56
|
-
* @property {string[]} includeTags - Tags to include.
|
|
57
|
-
* @property {string[]} excludeTags - Tags to exclude.
|
|
58
|
-
* @property {string[]} examplePatterns - Example name patterns.
|
|
59
|
-
* @property {string[]} filteredProcessArgs - Remaining process args with filter flags removed.
|
|
60
|
-
* @property {number | undefined} groups - Total number of groups for test splitting.
|
|
61
|
-
* @property {number | undefined} groupNumber - Which group to run (1-indexed).
|
|
62
|
-
*/
|
|
63
|
-
|
|
64
63
|
/**
|
|
65
64
|
* Runs the parseFilters helper.
|
|
66
65
|
* @param {string[]} processArgs - Process args.
|