velocious 1.0.558 → 1.0.559

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/README.md +1 -1
  2. package/build/background-jobs/store.js +262 -16
  3. package/build/background-jobs/web/authorization.js +5 -4
  4. package/build/background-jobs/web/controller.js +13 -16
  5. package/build/background-jobs/web/counts-channel.js +79 -0
  6. package/build/background-jobs/web/index.js +2 -0
  7. package/build/background-jobs/web/registry.js +1 -1
  8. package/build/src/background-jobs/store.d.ts +79 -0
  9. package/build/src/background-jobs/store.d.ts.map +1 -1
  10. package/build/src/background-jobs/store.js +235 -17
  11. package/build/src/background-jobs/web/authorization.d.ts +5 -3
  12. package/build/src/background-jobs/web/authorization.d.ts.map +1 -1
  13. package/build/src/background-jobs/web/authorization.js +6 -5
  14. package/build/src/background-jobs/web/controller.d.ts.map +1 -1
  15. package/build/src/background-jobs/web/controller.js +14 -15
  16. package/build/src/background-jobs/web/counts-channel.d.ts +31 -0
  17. package/build/src/background-jobs/web/counts-channel.d.ts.map +1 -0
  18. package/build/src/background-jobs/web/counts-channel.js +71 -0
  19. package/build/src/background-jobs/web/index.d.ts.map +1 -1
  20. package/build/src/background-jobs/web/index.js +3 -1
  21. package/build/src/background-jobs/web/registry.d.ts +1 -1
  22. package/build/src/background-jobs/web/registry.d.ts.map +1 -1
  23. package/build/src/background-jobs/web/registry.js +2 -2
  24. package/build/tsconfig.tsbuildinfo +1 -1
  25. package/package.json +1 -1
  26. package/src/background-jobs/store.js +262 -16
  27. package/src/background-jobs/web/authorization.js +5 -4
  28. package/src/background-jobs/web/controller.js +13 -16
  29. package/src/background-jobs/web/counts-channel.js +79 -0
  30. package/src/background-jobs/web/index.js +2 -0
  31. package/src/background-jobs/web/registry.js +1 -1
@@ -99,7 +99,11 @@ export default class VelociousBackgroundJobsWebController extends Controller {
99
99
  */
100
100
  async health() {
101
101
  await this._respond(async () => {
102
- await this.render({json: {ok: true, service: "velocious-background-jobs"}})
102
+ await this.render({json: {
103
+ capabilities: {backgroundJobCountDeltas: 1},
104
+ ok: true,
105
+ service: "velocious-background-jobs"
106
+ }})
103
107
  })
104
108
  }
105
109
 
@@ -109,22 +113,15 @@ export default class VelociousBackgroundJobsWebController extends Controller {
109
113
  */
110
114
  async stats() {
111
115
  await this._respond(async () => {
112
- const counts = await this._store().countsByStatus()
113
- /**
114
- * By status.
115
- * @type {Record<string, number>} */
116
- const byStatus = {}
117
- let total = 0
118
-
119
- for (const status of DASHBOARD_STATUSES) {
120
- byStatus[status] = counts[status] || 0
121
- }
116
+ const snapshot = await this._store().countSnapshot()
122
117
 
123
- for (const value of Object.values(counts)) {
124
- total += value
125
- }
126
-
127
- await this.render({json: {counts: byStatus, generatedAtMs: Date.now(), total}})
118
+ await this.render({json: {
119
+ capabilities: {backgroundJobCountDeltas: 1},
120
+ counts: snapshot.counts,
121
+ generatedAtMs: Date.now(),
122
+ revision: snapshot.revision,
123
+ total: snapshot.total
124
+ }})
128
125
  })
129
126
  }
130
127
 
@@ -0,0 +1,79 @@
1
+ // @ts-check
2
+
3
+ import {BACKGROUND_JOB_COUNTS_CHANNEL} from "../store.js"
4
+ import VelociousWebsocketChannel from "../../http-server/websocket-channel.js"
5
+ import {authorizeJobsRequest} from "./authorization.js"
6
+ import {getJobsMount} from "./registry.js"
7
+ import {normalizeMountPrefix} from "./path-matcher.js"
8
+
9
+ /**
10
+ * Authorized dashboard count-delta channel. Clients subscribe with the mount
11
+ * path and their normal bearer token as `authenticationToken`.
12
+ */
13
+ export default class BackgroundJobCountsChannel extends VelociousWebsocketChannel {
14
+ /**
15
+ * Authorizes the subscription.
16
+ * @returns {Promise<boolean>} Whether the mount's normal dashboard authorization allows the subscription.
17
+ */
18
+ async canSubscribe() {
19
+ if (typeof this.params.mountAt !== "string") return false
20
+
21
+ const mountAt = normalizeMountPrefix(this.params.mountAt)
22
+ const options = getJobsMount(this.session.configuration, mountAt)
23
+
24
+ if (!options || !this.session.upgradeRequest) return false
25
+
26
+ const token = typeof this.params.authenticationToken === "string"
27
+ ? this.params.authenticationToken
28
+ : null
29
+ const ability = await this.session.configuration.resolveAbility({
30
+ params: this.params,
31
+ request: this.session.upgradeRequest
32
+ })
33
+ const authorized = await authorizeJobsRequest({
34
+ ability,
35
+ configuration: this.session.configuration,
36
+ options,
37
+ request: this.session.upgradeRequest,
38
+ token
39
+ })
40
+
41
+ if (!authorized) return false
42
+
43
+ this.databaseIdentifier = options.databaseIdentifier
44
+ || this.session.configuration.getBackgroundJobsConfig().databaseIdentifier
45
+ || "default"
46
+
47
+ return true
48
+ }
49
+
50
+ /**
51
+ * Matches only events from the database selected by the authorized mount.
52
+ * @param {import("../../http-server/websocket-channel.js").WebsocketJsonValue} broadcastParams - Publisher scope.
53
+ * @returns {boolean} Whether this subscription should receive the event.
54
+ */
55
+ matches(broadcastParams) {
56
+ if (!broadcastParams || typeof broadcastParams !== "object" || Array.isArray(broadcastParams)) return false
57
+
58
+ return String(/** @type {Record<string, ?>} */ (broadcastParams).databaseIdentifier) === this.databaseIdentifier
59
+ }
60
+
61
+ /**
62
+ * Builds diagnostics.
63
+ * @returns {Record<string, string>} Non-sensitive diagnostics.
64
+ */
65
+ debugSnapshot() {
66
+ return {databaseIdentifier: this.databaseIdentifier}
67
+ }
68
+
69
+ /** @type {string} */
70
+ databaseIdentifier = ""
71
+
72
+ /**
73
+ * Registers the framework channel used by mounted jobs dashboards.
74
+ * @param {import("../../configuration.js").default} configuration - Configuration.
75
+ */
76
+ static register(configuration) {
77
+ configuration.registerWebsocketChannel(BACKGROUND_JOB_COUNTS_CHANNEL, this)
78
+ }
79
+ }
@@ -1,6 +1,7 @@
1
1
  // @ts-check
2
2
 
3
3
  import VelociousBackgroundJobsWebController from "./controller.js"
4
+ import BackgroundJobCountsChannel from "./counts-channel.js"
4
5
  import {matchJobsApiPath, normalizeMountPrefix} from "./path-matcher.js"
5
6
  import {registerJobsMount} from "./registry.js"
6
7
 
@@ -40,6 +41,7 @@ export default class VelociousBackgroundJobsApi {
40
41
  const prefix = normalizeMountPrefix(at)
41
42
 
42
43
  registerJobsMount(configuration, prefix, {accessTokens, allowedOrigins, authorize, databaseIdentifier, redactArgs})
44
+ BackgroundJobCountsChannel.register(configuration)
43
45
 
44
46
  configuration.addRouteResolverHook(({currentPath, request}) => {
45
47
  const match = matchJobsApiPath({method: request.httpMethod(), path: currentPath, prefix})
@@ -3,7 +3,7 @@
3
3
  /**
4
4
  * JobsMountOptions type.
5
5
  * @typedef {object} JobsMountOptions
6
- * @property {(args: {request: import("../../http-server/client/request.js").default, ability: (import("../../authorization/ability.js").default | undefined), token: (string | null), configuration: import("../../configuration.js").default}) => (boolean | void | Promise<boolean | void>)} [authorize] - Authorization callback. Return true to allow the request.
6
+ * @property {(args: {request: import("../../http-server/client/request.js").default | import("../../http-server/client/websocket-request.js").default, ability: (import("../../authorization/ability.js").default | undefined), token: (string | null), configuration: import("../../configuration.js").default}) => (boolean | void | Promise<boolean | void>)} [authorize] - Authorization callback. Return true to allow the request.
7
7
  * @property {string[]} [accessTokens] - Bearer tokens accepted for cross-origin/native access.
8
8
  * @property {string[]} [allowedOrigins] - Origins allowed for cross-origin browser access.
9
9
  * @property {boolean} [redactArgs] - When true, job arguments are omitted from API responses.