@owlmeans/server-job 0.1.18-rc.2 → 0.1.18-rc.21
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 +36 -86
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/server-job/SKILL.md +60 -107
- package/build/actions/cancel.d.ts +3 -4
- package/build/actions/cancel.d.ts.map +1 -1
- package/build/actions/cancel.js +11 -6
- package/build/actions/cancel.js.map +1 -1
- package/build/actions/get.d.ts +3 -4
- package/build/actions/get.d.ts.map +1 -1
- package/build/actions/get.js +6 -4
- package/build/actions/get.js.map +1 -1
- package/build/actions/list.d.ts +3 -4
- package/build/actions/list.d.ts.map +1 -1
- package/build/actions/list.js +10 -12
- package/build/actions/list.js.map +1 -1
- package/build/actions/watch.d.ts +5 -6
- package/build/actions/watch.d.ts.map +1 -1
- package/build/actions/watch.js +21 -20
- package/build/actions/watch.js.map +1 -1
- package/build/entrypoints.d.ts +3 -4
- package/build/entrypoints.d.ts.map +1 -1
- package/build/entrypoints.js +10 -10
- package/build/entrypoints.js.map +1 -1
- package/build/helper.d.ts +3 -5
- package/build/helper.d.ts.map +1 -1
- package/build/helper.js +9 -11
- package/build/helper.js.map +1 -1
- package/build/index.d.ts +0 -3
- package/build/index.d.ts.map +1 -1
- package/build/index.js +0 -3
- package/build/index.js.map +1 -1
- package/build/types.d.ts +18 -46
- package/build/types.d.ts.map +1 -1
- package/build/utils/index.d.ts +2 -2
- package/build/utils/index.d.ts.map +1 -1
- package/build/utils/index.js +2 -2
- package/build/utils/index.js.map +1 -1
- package/build/utils/policy.d.ts +7 -0
- package/build/utils/policy.d.ts.map +1 -0
- package/build/utils/policy.js +10 -0
- package/build/utils/policy.js.map +1 -0
- package/build/utils/view.d.ts +18 -0
- package/build/utils/view.d.ts.map +1 -0
- package/build/utils/view.js +94 -0
- package/build/utils/view.js.map +1 -0
- package/package.json +17 -14
- package/src/actions/cancel.ts +15 -12
- package/src/actions/get.ts +10 -10
- package/src/actions/list.ts +15 -21
- package/src/actions/watch.ts +24 -25
- package/src/helper.ts +10 -18
- package/src/index.ts +0 -3
- package/src/types.ts +21 -48
- package/src/utils/index.ts +2 -2
- package/src/utils/policy.ts +20 -0
- package/src/utils/view.ts +102 -0
- package/tests/view.spec.ts +55 -0
- package/src/consts.ts +0 -28
- package/src/entrypoints.ts +0 -56
- package/src/schemas.ts +0 -19
- package/src/utils/owner.ts +0 -60
- package/src/utils/resource.ts +0 -40
package/build/actions/watch.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { connection } from '@owlmeans/server-socket';
|
|
2
2
|
import { MessageType } from '@owlmeans/socket';
|
|
3
|
-
import { JOB_EVENT } from '
|
|
4
|
-
import {
|
|
3
|
+
import { JOB_EVENT } from '@owlmeans/job';
|
|
4
|
+
import { jobsOf } from '../utils/index.js';
|
|
5
5
|
/**
|
|
6
6
|
* Push this caller's job lifecycle events down a socket.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* Broker events are resolved inside the caller's audience and mapped to {@link JobViewEvent}; raw
|
|
9
|
+
* queue ids, payloads, failures and ownership fields never cross the socket boundary.
|
|
10
10
|
*
|
|
11
11
|
* **A `JobEvent` carries no owner**, so each one is attributed by reading its job back, and the
|
|
12
12
|
* ids that answered are remembered for the life of the connection. A queue configured with
|
|
@@ -14,26 +14,27 @@ import { jobViewer, jobsOf, owns } from '../utils/index.js';
|
|
|
14
14
|
* attributed by is gone by the time the event arrives, and an unattributable event is dropped
|
|
15
15
|
* rather than fanned out to everyone. Leave completed jobs in place on any queue that is watched.
|
|
16
16
|
*/
|
|
17
|
-
export const watchJobs = (opts) =>
|
|
17
|
+
export const watchJobs = (protocol, opts) => connection(protocol, async (conn, ctx, req) => {
|
|
18
18
|
const resource = jobsOf(ctx, opts);
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
const audience = await opts.policy.audience(req, ctx);
|
|
20
|
+
const publicIds = new Map();
|
|
21
|
+
const project = async (event) => {
|
|
22
|
+
const record = await resource.load({
|
|
23
|
+
$and: [{ id: event.id }, opts.policy.where(audience, {})],
|
|
24
|
+
});
|
|
25
|
+
if (record != null) {
|
|
26
|
+
const job = await opts.policy.map(record, audience);
|
|
27
|
+
publicIds.set(event.id, job.id);
|
|
28
|
+
return { type: 'upsert', job };
|
|
24
29
|
}
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
|
-
mine.add(event.id);
|
|
30
|
-
return true;
|
|
30
|
+
const id = publicIds.get(event.id);
|
|
31
|
+
return id == null ? null : { type: 'remove', id };
|
|
31
32
|
};
|
|
32
33
|
const unsubscribe = await resource.subscribe(async (event) => {
|
|
33
34
|
try {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
const projected = await project(event);
|
|
36
|
+
if (projected != null)
|
|
37
|
+
await conn.notify(JOB_EVENT, projected);
|
|
37
38
|
}
|
|
38
39
|
catch (e) {
|
|
39
40
|
console.error('Job watch notify error:', e);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/actions/watch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/actions/watch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AAEpD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAIzC,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAE1C;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,QAAiC,EACjC,IAAuB,EACQ,EAAE,CAAC,UAAU,CAA2B,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IAC1G,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IAClC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;IACrD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAA;IAE3C,MAAM,OAAO,GAAG,KAAK,EAAE,KAAe,EAAgC,EAAE;QACtE,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC;YACjC,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;SAC1D,CAAC,CAAA;QACF,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;YACnD,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAA;YAC/B,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAA;QAChC,CAAC;QACD,MAAM,EAAE,GAAG,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QAClC,OAAO,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;IACnD,CAAC,CAAA;IAED,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,SAAS,CAAC,KAAK,EAAC,KAAK,EAAC,EAAE;QACzD,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,CAAA;YACtC,IAAI,SAAS,IAAI,IAAI;gBAAE,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;QAChE,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,CAAC,CAAC,CAAA;QAC7C,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,MAAM,CAAC,KAAK,EAAC,OAAO,EAAC,EAAE;QAC1B,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChC,OAAM;QACR,CAAC;QACD,MAAM,GAAG,GAAG,OAA6B,CAAA;QACzC,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,CAAC,MAAM,IAAI,GAAG,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;YAC7D,IAAI,CAAC;gBACH,MAAM,WAAW,EAAE,CAAA;YACrB,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,CAAC,CAAC,CAAA;YAClD,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
package/build/entrypoints.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { JobEntrypointAliases, JobEntrypointOptions } from './types.js';
|
|
1
|
+
import type { JobEntrypointAliases, JobEntrypoints, JobEntrypointOptions } from './types.js';
|
|
3
2
|
/**
|
|
4
3
|
* The aliases one job group answers under.
|
|
5
4
|
*
|
|
@@ -11,11 +10,11 @@ export declare const jobEntrypointAliases: (root: string) => JobEntrypointAliase
|
|
|
11
10
|
* Declare the list/get/cancel/watch entrypoints of one job group.
|
|
12
11
|
*
|
|
13
12
|
* It belongs in the SHARED package of a target app — the one both the API and the browser import —
|
|
14
|
-
* so that the server
|
|
13
|
+
* so that the server binds and the client calls the very declarations, and neither side ever
|
|
15
14
|
* writes a path. Declaring a second group is the same call with another root.
|
|
16
15
|
*
|
|
17
16
|
* The guard rides on the base alone: guards are inherited, so stating it once is what keeps the
|
|
18
17
|
* four from drifting apart.
|
|
19
18
|
*/
|
|
20
|
-
export declare const declareJobEntrypoints: (root: string, opts?: JobEntrypointOptions) =>
|
|
19
|
+
export declare const declareJobEntrypoints: (root: string, opts?: JobEntrypointOptions) => JobEntrypoints;
|
|
21
20
|
//# sourceMappingURL=entrypoints.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entrypoints.d.ts","sourceRoot":"","sources":["../src/entrypoints.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"entrypoints.d.ts","sourceRoot":"","sources":["../src/entrypoints.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,oBAAoB,EAAE,cAAc,EAAE,oBAAoB,EAAgB,MAAM,YAAY,CAAA;AAE1G;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,SAAU,MAAM,KAAG,oBAMlD,CAAA;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,SAC1B,MAAM,SAAS,oBAAoB,KACxC,cA0BF,CAAA"}
|
package/build/entrypoints.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { contract, openProtocol, protocol, typed } from '@owlmeans/entrypoint';
|
|
2
2
|
import { backend, route, RouteMethod, socket } from '@owlmeans/route';
|
|
3
3
|
import { DEFAULT_GUARD } from '@owlmeans/auth-common';
|
|
4
4
|
import { DEFAULT_JOB_PATH } from './consts.js';
|
|
@@ -20,7 +20,7 @@ export const jobEntrypointAliases = (root) => ({
|
|
|
20
20
|
* Declare the list/get/cancel/watch entrypoints of one job group.
|
|
21
21
|
*
|
|
22
22
|
* It belongs in the SHARED package of a target app — the one both the API and the browser import —
|
|
23
|
-
* so that the server
|
|
23
|
+
* so that the server binds and the client calls the very declarations, and neither side ever
|
|
24
24
|
* writes a path. Declaring a second group is the same call with another root.
|
|
25
25
|
*
|
|
26
26
|
* The guard rides on the base alone: guards are inherited, so stating it once is what keeps the
|
|
@@ -32,15 +32,15 @@ export const declareJobEntrypoints = (root, opts) => {
|
|
|
32
32
|
...(opts?.parent != null ? { parent: opts.parent } : {}),
|
|
33
33
|
...(opts?.service != null ? { service: opts.service } : {}),
|
|
34
34
|
};
|
|
35
|
-
const guarded = opts?.guard === null ? undefined :
|
|
36
|
-
return
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
const guarded = opts?.guard === null ? undefined : { guards: opts?.guard ?? DEFAULT_GUARD };
|
|
36
|
+
return {
|
|
37
|
+
base: openProtocol(route(aliases.base, opts?.path ?? DEFAULT_JOB_PATH, backend(base)), guarded),
|
|
38
|
+
list: protocol(route(aliases.list, '/', backend(aliases.base)), contract.request({ query: typed(JobListQuerySchema) }, typed())),
|
|
39
39
|
// Static before parametric, so `/watch` is not swallowed by `/:id`. The router picks the
|
|
40
40
|
// static branch on its own; the order here is for whoever reads the declaration.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
watch: protocol(route(aliases.watch, '/watch', socket(aliases.base)), contract(typed())),
|
|
42
|
+
get: protocol(route(aliases.get, '/:id', backend(aliases.base)), contract.request({ params: typed() }, typed())),
|
|
43
|
+
cancel: protocol(route(aliases.cancel, '/:id', backend(aliases.base, RouteMethod.DELETE)), contract.request({ params: typed() }, typed())),
|
|
44
|
+
};
|
|
45
45
|
};
|
|
46
46
|
//# sourceMappingURL=entrypoints.js.map
|
package/build/entrypoints.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entrypoints.js","sourceRoot":"","sources":["../src/entrypoints.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"entrypoints.js","sourceRoot":"","sources":["../src/entrypoints.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAC9E,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAErE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAGjD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,IAAY,EAAwB,EAAE,CAAC,CAAC;IAC3E,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,GAAG,IAAI,OAAO;IACpB,GAAG,EAAE,GAAG,IAAI,MAAM;IAClB,MAAM,EAAE,GAAG,IAAI,SAAS;IACxB,KAAK,EAAE,GAAG,IAAI,QAAQ;CACvB,CAAC,CAAA;AAEF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,IAAY,EAAE,IAA2B,EACzB,EAAE;IAClB,MAAM,OAAO,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAA;IAC1C,MAAM,IAAI,GAA0B;QAClC,GAAG,CAAC,IAAI,EAAE,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,GAAG,CAAC,IAAI,EAAE,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5D,CAAA;IACD,MAAM,OAAO,GAAG,IAAI,EAAE,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI,aAAa,EAAE,CAAA;IAE3F,OAAO;QACL,IAAI,EAAE,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,IAAI,gBAAgB,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC;QAC/F,IAAI,EAAE,QAAQ,CACZ,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAC/C,QAAQ,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,CAAe,kBAAkB,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAC9E;QACD,yFAAyF;QACzF,iFAAiF;QACjF,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,KAAK,EAAQ,CAAC,CAAC;QAC9F,GAAG,EAAE,QAAQ,CACX,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EACjD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAkB,EAAE,EAAE,KAAK,EAAE,CAAC,CAC/D;QACD,MAAM,EAAE,QAAQ,CACd,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,EACxE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAkB,EAAE,EAAE,KAAK,EAAE,CAAC,CAC/D;KACF,CAAA;AACH,CAAC,CAAA"}
|
package/build/helper.d.ts
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { CommonEntrypoint } from '@owlmeans/entrypoint';
|
|
3
|
-
import type { JobHandlerOptions } from './types.js';
|
|
1
|
+
import type { JobEntrypoints, JobHandlerOptions } from './types.js';
|
|
4
2
|
/**
|
|
5
3
|
* Attach this package's handlers to a group declared by {@link declareJobEntrypoints}.
|
|
6
4
|
*
|
|
7
5
|
* The whole server half of "a long job reports progress to the user's screen" is this call plus
|
|
8
6
|
* the queue driver an app already wires — nothing is subclassed, and an app that wants one
|
|
9
|
-
* handler of its own
|
|
7
|
+
* handler of its own binds that alias itself afterwards.
|
|
10
8
|
*
|
|
11
9
|
* @throws {SyntaxError} when the array carries no group under that root.
|
|
12
10
|
*/
|
|
13
|
-
export declare const serveJobEntrypoints:
|
|
11
|
+
export declare const serveJobEntrypoints: (entrypoints: JobEntrypoints, opts: JobHandlerOptions) => import("@owlmeans/server-entrypoint").ServerProtocolEntrypoint<import("@owlmeans/entrypoint").EntrypointProtocolDeclaration>[];
|
|
14
12
|
//# sourceMappingURL=helper.d.ts.map
|
package/build/helper.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEnE;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,gBAAiB,cAAc,QAAQ,iBAAiB,mIAMvF,CAAA"}
|
package/build/helper.js
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { jobEntrypointAliases } from './entrypoints.js';
|
|
1
|
+
import { bind } from '@owlmeans/server-entrypoint';
|
|
3
2
|
import { cancelJob, getJob, listJobs, watchJobs } from './actions/index.js';
|
|
4
3
|
/**
|
|
5
4
|
* Attach this package's handlers to a group declared by {@link declareJobEntrypoints}.
|
|
6
5
|
*
|
|
7
6
|
* The whole server half of "a long job reports progress to the user's screen" is this call plus
|
|
8
7
|
* the queue driver an app already wires — nothing is subclassed, and an app that wants one
|
|
9
|
-
* handler of its own
|
|
8
|
+
* handler of its own binds that alias itself afterwards.
|
|
10
9
|
*
|
|
11
10
|
* @throws {SyntaxError} when the array carries no group under that root.
|
|
12
11
|
*/
|
|
13
|
-
export const serveJobEntrypoints = (entrypoints,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
};
|
|
12
|
+
export const serveJobEntrypoints = (entrypoints, opts) => [
|
|
13
|
+
bind(entrypoints.base),
|
|
14
|
+
bind(entrypoints.list, listJobs(entrypoints.list, opts)),
|
|
15
|
+
bind(entrypoints.watch, watchJobs(entrypoints.watch, opts)),
|
|
16
|
+
bind(entrypoints.get, getJob(entrypoints.get, opts)),
|
|
17
|
+
bind(entrypoints.cancel, cancelJob(entrypoints.cancel, opts)),
|
|
18
|
+
];
|
|
21
19
|
//# sourceMappingURL=helper.js.map
|
package/build/helper.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helper.js","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"helper.js","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,6BAA6B,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAG3E;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,WAA2B,EAAE,IAAuB,EAAE,EAAE,CAAC;IAC3F,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;IACtB,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACxD,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC3D,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACpD,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;CAC9D,CAAA"}
|
package/build/index.d.ts
CHANGED
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mBAAmB,YAAY,CAAA;AAE/B,cAAc,aAAa,CAAA;AAC3B,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mBAAmB,YAAY,CAAA;AAE/B,cAAc,aAAa,CAAA;AAC3B,cAAc,oBAAoB,CAAA;AAClC,cAAc,kBAAkB,CAAA"}
|
package/build/index.js
CHANGED
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,aAAa,CAAA;AAC3B,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,aAAa,CAAA;AAC3B,cAAc,oBAAoB,CAAA;AAClC,cAAc,kBAAkB,CAAA"}
|
package/build/types.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { BasicConfig, BasicContext } from '@owlmeans/context';
|
|
2
2
|
import type { AbstractRequest } from '@owlmeans/entrypoint';
|
|
3
|
-
import type {
|
|
3
|
+
import type { JobEntrypoints, JobListQuery, JobView } from '@owlmeans/job';
|
|
4
|
+
import type { JobRecord, QueueAppend, QueueConfig, QueueResource } from '@owlmeans/queue';
|
|
5
|
+
import type { Criteria } from '@owlmeans/resource';
|
|
4
6
|
import type { ApiServerAppend } from '@owlmeans/server-api';
|
|
5
7
|
import type { ServerConfig, ServerContext } from '@owlmeans/server-context';
|
|
6
8
|
export interface Config extends ServerConfig {
|
|
@@ -8,53 +10,23 @@ export interface Config extends ServerConfig {
|
|
|
8
10
|
}
|
|
9
11
|
export interface Context<C extends Config = Config> extends ServerContext<C>, ApiServerAppend, QueueAppend {
|
|
10
12
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
export type JobAudience = Record<string, unknown>;
|
|
14
|
+
/** Required application policy at the raw-broker to public-domain boundary. */
|
|
15
|
+
export interface JobExposurePolicy<A extends JobAudience = JobAudience> {
|
|
16
|
+
audience: (req: AbstractRequest, ctx: BasicContext<BasicConfig>) => A | Promise<A>;
|
|
17
|
+
/** Translate public filters and authenticated scope into broker criteria. */
|
|
18
|
+
where: (audience: A, query: JobListQuery) => Criteria<JobRecord>;
|
|
19
|
+
/** Resolve an opaque public id within the authenticated scope. */
|
|
20
|
+
lookup: (id: string, audience: A, resource: QueueResource) => Promise<JobRecord | null>;
|
|
21
|
+
/** Allowlist and map a scoped broker record into its public representation. */
|
|
22
|
+
map: (record: JobRecord, audience: A) => JobView | Promise<JobView>;
|
|
23
|
+
/** Cancellation is unavailable unless this callback is present and approves the record. */
|
|
24
|
+
cancel?: (record: JobRecord, audience: A) => boolean | Promise<boolean>;
|
|
18
25
|
}
|
|
19
|
-
export interface
|
|
20
|
-
/** The path segment the group answers under. Defaults to `/jobs`. */
|
|
21
|
-
path?: string;
|
|
22
|
-
/** The entrypoint the group hangs under — an app's API base. Top level when omitted. */
|
|
23
|
-
parent?: string;
|
|
24
|
-
/** The service route the group answers on, when it is not this app's own. */
|
|
25
|
-
service?: string;
|
|
26
|
-
/**
|
|
27
|
-
* The guard the group's base carries, and every entrypoint under it inherits.
|
|
28
|
-
*
|
|
29
|
-
* `DEFAULT_GUARD` unless told otherwise, because ownership is derived from the authenticated
|
|
30
|
-
* subject and an unguarded declaration has no subject to derive it from. Pass `null` only for a
|
|
31
|
-
* group that is scoped some other way — its handlers then answer `AuthorizationError`.
|
|
32
|
-
*/
|
|
33
|
-
guard?: string | null;
|
|
34
|
-
}
|
|
35
|
-
/** The list entrypoint's query, as it travels on the wire. */
|
|
36
|
-
export interface JobListQuery {
|
|
37
|
-
state?: string;
|
|
38
|
-
name?: string;
|
|
39
|
-
page?: number;
|
|
40
|
-
size?: number;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* A request that may read the queue unscoped.
|
|
44
|
-
*
|
|
45
|
-
* A predicate rather than a permission name: which permission, gate or role means "operator" is
|
|
46
|
-
* the application's decision, and hardcoding one here would make every deployment that names it
|
|
47
|
-
* differently patch this package.
|
|
48
|
-
*/
|
|
49
|
-
export interface JobAdminCheck {
|
|
50
|
-
(req: AbstractRequest, ctx: BasicContext<BasicConfig>): boolean | Promise<boolean>;
|
|
51
|
-
}
|
|
52
|
-
export interface JobHandlerOptions {
|
|
26
|
+
export interface JobHandlerOptions<A extends JobAudience = JobAudience> {
|
|
53
27
|
/** Which declared queue these handlers read. The context's sole queue when omitted. */
|
|
54
28
|
queue?: string;
|
|
55
|
-
|
|
56
|
-
ownerField?: string;
|
|
57
|
-
/** The escape hatch — see {@link JobAdminCheck}. Nothing is unscoped without one. */
|
|
58
|
-
admin?: JobAdminCheck;
|
|
29
|
+
policy: JobExposurePolicy<A>;
|
|
59
30
|
}
|
|
31
|
+
export type { JobEntrypoints, JobListQuery };
|
|
60
32
|
//# sourceMappingURL=types.d.ts.map
|
package/build/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAC1E,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AACzF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAE3E,MAAM,WAAW,MAAO,SAAQ,YAAY;IAC1C,KAAK,CAAC,EAAE,WAAW,CAAA;CACpB;AAED,MAAM,WAAW,OAAO,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,aAAa,CAAC,CAAC,CAAC,EAC1E,eAAe,EAAE,WAAW;CAAI;AAElC,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAEjD,+EAA+E;AAC/E,MAAM,WAAW,iBAAiB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW;IACpE,QAAQ,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,YAAY,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IAClF,6EAA6E;IAC7E,KAAK,EAAE,CAAC,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,YAAY,KAAK,QAAQ,CAAC,SAAS,CAAC,CAAA;IAChE,kEAAkE;IAClE,MAAM,EAAE,CACN,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,aAAa,KAC7C,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAA;IAC9B,+EAA+E;IAC/E,GAAG,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACnE,2FAA2F;IAC3F,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CACxE;AAED,MAAM,WAAW,iBAAiB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW;IACpE,uFAAuF;IACvF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAA;CAC7B;AAED,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,CAAA"}
|
package/build/utils/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './
|
|
1
|
+
export * from './policy.js';
|
|
2
|
+
export * from './view.js';
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA"}
|
package/build/utils/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './
|
|
1
|
+
export * from './policy.js';
|
|
2
|
+
export * from './view.js';
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
package/build/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { BasicConfig, BasicContext } from '@owlmeans/context';
|
|
2
|
+
import type { JobRecord, QueueResource } from '@owlmeans/queue';
|
|
3
|
+
import type { JobAudience, JobHandlerOptions } from '../types.js';
|
|
4
|
+
export declare const jobsOf: <D = unknown, R = unknown>(ctx: BasicContext<BasicConfig>, opts: JobHandlerOptions) => QueueResource<D, R>;
|
|
5
|
+
/** Resolve an opaque id without revealing whether it exists outside the current audience. */
|
|
6
|
+
export declare const readExposedJob: <A extends JobAudience>(resource: QueueResource, id: string, audience: A, opts: JobHandlerOptions<A>) => Promise<JobRecord>;
|
|
7
|
+
//# sourceMappingURL=policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../src/utils/policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAE/D,OAAO,KAAK,EAAW,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAE1E,eAAO,MAAM,MAAM,GAAI,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,OACxC,YAAY,CAAC,WAAW,CAAC,QAAQ,iBAAiB,KACtD,aAAa,CAAC,CAAC,EAAE,CAAC,CAAuD,CAAA;AAE5E,6FAA6F;AAC7F,eAAO,MAAM,cAAc,GAAU,CAAC,SAAS,WAAW,YAC9C,aAAa,MACnB,MAAM,YACA,CAAC,QACL,iBAAiB,CAAC,CAAC,CAAC,KACzB,OAAO,CAAC,SAAS,CAInB,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { UnknownJob } from '@owlmeans/queue';
|
|
2
|
+
export const jobsOf = (ctx, opts) => ctx.jobs(opts.queue);
|
|
3
|
+
/** Resolve an opaque id without revealing whether it exists outside the current audience. */
|
|
4
|
+
export const readExposedJob = async (resource, id, audience, opts) => {
|
|
5
|
+
const record = await opts.policy.lookup(id, audience, resource);
|
|
6
|
+
if (record == null)
|
|
7
|
+
throw new UnknownJob('job');
|
|
8
|
+
return record;
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/utils/policy.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAG5C,MAAM,CAAC,MAAM,MAAM,GAAG,CACpB,GAA8B,EAAE,IAAuB,EAClC,EAAE,CAAE,GAA0B,CAAC,IAAI,CAAO,IAAI,CAAC,KAAK,CAAC,CAAA;AAE5E,6FAA6F;AAC7F,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EACjC,QAAuB,EACvB,EAAU,EACV,QAAW,EACX,IAA0B,EACN,EAAE;IACtB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAA;IAC/D,IAAI,MAAM,IAAI,IAAI;QAAE,MAAM,IAAI,UAAU,CAAC,KAAK,CAAC,CAAA;IAC/C,OAAO,MAAM,CAAA;AACf,CAAC,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { JobJson, JobView, PublicJobError } from '@owlmeans/job';
|
|
2
|
+
import type { JobRecord } from '@owlmeans/queue';
|
|
3
|
+
export interface JobViewFields {
|
|
4
|
+
id: string;
|
|
5
|
+
kind: string;
|
|
6
|
+
summary?: string;
|
|
7
|
+
metadata?: Record<string, JobJson>;
|
|
8
|
+
result?: JobJson;
|
|
9
|
+
error?: PublicJobError;
|
|
10
|
+
cancellable?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/** Copy JSON through bounded, prototype-free containers and discard every non-JSON value. */
|
|
13
|
+
export declare const sanitizeJobJson: (value: unknown, depth?: number) => JobJson | undefined;
|
|
14
|
+
/** Build a public view from fields an application explicitly allowlisted. */
|
|
15
|
+
export declare const jobViewOf: (record: JobRecord, fields: JobViewFields) => JobView;
|
|
16
|
+
/** Safe default for a broker failure; raw reasons and stacks never cross the boundary. */
|
|
17
|
+
export declare const publicJobError: (type?: string) => PublicJobError;
|
|
18
|
+
//# sourceMappingURL=view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../src/utils/view.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAmB,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAEtF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAEhD,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAClC,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE,cAAc,CAAA;IACtB,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAOD,6FAA6F;AAC7F,eAAO,MAAM,eAAe,UAAW,OAAO,UAAS,MAAM,KAAO,OAAO,GAAG,SAoB7E,CAAA;AA8BD,6EAA6E;AAC7E,eAAO,MAAM,SAAS,WAAY,SAAS,UAAU,aAAa,KAAG,OAuBpE,CAAA;AAED,0FAA0F;AAC1F,eAAO,MAAM,cAAc,UAAU,MAAM,KAAkB,cAG3D,CAAA"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { JobViewStatus } from '@owlmeans/job';
|
|
2
|
+
import { JobState } from '@owlmeans/queue';
|
|
3
|
+
const MAX_JSON_DEPTH = 8;
|
|
4
|
+
const MAX_JSON_ITEMS = 100;
|
|
5
|
+
const MAX_JSON_STRING = 16_384;
|
|
6
|
+
const FORBIDDEN_KEYS = new Set(['__proto__', 'prototype', 'constructor']);
|
|
7
|
+
/** Copy JSON through bounded, prototype-free containers and discard every non-JSON value. */
|
|
8
|
+
export const sanitizeJobJson = (value, depth = 0) => {
|
|
9
|
+
if (depth > MAX_JSON_DEPTH)
|
|
10
|
+
return undefined;
|
|
11
|
+
if (value == null || typeof value === 'boolean' || typeof value === 'string') {
|
|
12
|
+
return typeof value === 'string' ? value.slice(0, MAX_JSON_STRING) : value;
|
|
13
|
+
}
|
|
14
|
+
if (typeof value === 'number')
|
|
15
|
+
return Number.isFinite(value) ? value : undefined;
|
|
16
|
+
if (Array.isArray(value)) {
|
|
17
|
+
return value.slice(0, MAX_JSON_ITEMS)
|
|
18
|
+
.map(item => sanitizeJobJson(item, depth + 1))
|
|
19
|
+
.filter((item) => item !== undefined);
|
|
20
|
+
}
|
|
21
|
+
if (typeof value !== 'object')
|
|
22
|
+
return undefined;
|
|
23
|
+
const result = Object.create(null);
|
|
24
|
+
for (const [key, item] of Object.entries(value).slice(0, MAX_JSON_ITEMS)) {
|
|
25
|
+
if (FORBIDDEN_KEYS.has(key))
|
|
26
|
+
continue;
|
|
27
|
+
const safe = sanitizeJobJson(item, depth + 1);
|
|
28
|
+
if (safe !== undefined)
|
|
29
|
+
result[key] = safe;
|
|
30
|
+
}
|
|
31
|
+
return result;
|
|
32
|
+
};
|
|
33
|
+
const sanitizeError = (error) => error == null
|
|
34
|
+
? undefined
|
|
35
|
+
: {
|
|
36
|
+
type: error.type.slice(0, 128),
|
|
37
|
+
message: error.message.slice(0, 2048),
|
|
38
|
+
};
|
|
39
|
+
const statusOf = (state) => {
|
|
40
|
+
switch (state) {
|
|
41
|
+
case JobState.Active: return JobViewStatus.Running;
|
|
42
|
+
case JobState.Completed: return JobViewStatus.Succeeded;
|
|
43
|
+
case JobState.Failed: return JobViewStatus.Failed;
|
|
44
|
+
default: return JobViewStatus.Queued;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const progressOf = (value) => {
|
|
48
|
+
if (typeof value === 'number' && Number.isFinite(value))
|
|
49
|
+
return { percent: value };
|
|
50
|
+
if (value == null || typeof value !== 'object' || Array.isArray(value))
|
|
51
|
+
return undefined;
|
|
52
|
+
const raw = value;
|
|
53
|
+
const progress = {};
|
|
54
|
+
if (typeof raw.percent === 'number' && Number.isFinite(raw.percent))
|
|
55
|
+
progress.percent = raw.percent;
|
|
56
|
+
if (typeof raw.done === 'number' && Number.isFinite(raw.done))
|
|
57
|
+
progress.done = raw.done;
|
|
58
|
+
if (typeof raw.total === 'number' && Number.isFinite(raw.total))
|
|
59
|
+
progress.total = raw.total;
|
|
60
|
+
if (typeof raw.message === 'string')
|
|
61
|
+
progress.message = raw.message.slice(0, 512);
|
|
62
|
+
return Object.keys(progress).length === 0 ? undefined : progress;
|
|
63
|
+
};
|
|
64
|
+
/** Build a public view from fields an application explicitly allowlisted. */
|
|
65
|
+
export const jobViewOf = (record, fields) => {
|
|
66
|
+
const createdAt = record.createdAt ?? new Date(0).toISOString();
|
|
67
|
+
const updatedAt = record.finishedAt ?? record.startedAt ?? createdAt;
|
|
68
|
+
const progress = progressOf(record.progress);
|
|
69
|
+
const metadata = sanitizeJobJson(fields.metadata);
|
|
70
|
+
const result = sanitizeJobJson(fields.result);
|
|
71
|
+
const error = sanitizeError(fields.error);
|
|
72
|
+
return {
|
|
73
|
+
id: fields.id,
|
|
74
|
+
kind: fields.kind.slice(0, 128),
|
|
75
|
+
status: statusOf(record.state),
|
|
76
|
+
...(progress == null ? {} : { progress }),
|
|
77
|
+
...(fields.summary == null ? {} : { summary: fields.summary.slice(0, 2048) }),
|
|
78
|
+
...(metadata == null || Array.isArray(metadata) || typeof metadata !== 'object'
|
|
79
|
+
? {} : { metadata }),
|
|
80
|
+
...(result === undefined ? {} : { result }),
|
|
81
|
+
...(error == null ? {} : { error }),
|
|
82
|
+
cancellable: fields.cancellable ?? false,
|
|
83
|
+
createdAt,
|
|
84
|
+
updatedAt,
|
|
85
|
+
...(record.startedAt == null ? {} : { startedAt: record.startedAt }),
|
|
86
|
+
...(record.finishedAt == null ? {} : { finishedAt: record.finishedAt }),
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
/** Safe default for a broker failure; raw reasons and stacks never cross the boundary. */
|
|
90
|
+
export const publicJobError = (type = 'job-failed') => ({
|
|
91
|
+
type,
|
|
92
|
+
message: 'The background operation failed.',
|
|
93
|
+
});
|
|
94
|
+
//# sourceMappingURL=view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view.js","sourceRoot":"","sources":["../../src/utils/view.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owlmeans/server-job",
|
|
3
|
-
"version": "0.1.18-rc.
|
|
3
|
+
"version": "0.1.18-rc.21",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"build": "tsc -b",
|
|
8
8
|
"dev": "sleep 354 && nodemon -e ts,tsx,json --watch src --exec \"tsc -p ./tsconfig.json\"",
|
|
9
|
-
"watch": "tsc -b -w --preserveWatchOutput --pretty"
|
|
9
|
+
"watch": "tsc -b -w --preserveWatchOutput --pretty",
|
|
10
|
+
"test": "bun test ./tests"
|
|
10
11
|
},
|
|
11
12
|
"main": "build/index.js",
|
|
12
13
|
"module": "build/index.js",
|
|
@@ -22,6 +23,7 @@
|
|
|
22
23
|
},
|
|
23
24
|
"devDependencies": {
|
|
24
25
|
"@owlmeans/dep-config": "workspace:*",
|
|
26
|
+
"@types/bun": "^1.4.0",
|
|
25
27
|
"@types/node": "^26.1.0",
|
|
26
28
|
"nodemon": "^3.1.14",
|
|
27
29
|
"typescript": "^7.0.2"
|
|
@@ -30,17 +32,18 @@
|
|
|
30
32
|
"access": "public"
|
|
31
33
|
},
|
|
32
34
|
"dependencies": {
|
|
33
|
-
"@owlmeans/auth": "^0.1.18-rc.
|
|
34
|
-
"@owlmeans/auth-common": "^0.1.18-rc.
|
|
35
|
-
"@owlmeans/context": "^0.1.18-rc.
|
|
36
|
-
"@owlmeans/entrypoint": "^0.1.18-rc.
|
|
37
|
-
"@owlmeans/
|
|
38
|
-
"@owlmeans/
|
|
39
|
-
"@owlmeans/
|
|
40
|
-
"@owlmeans/
|
|
41
|
-
"@owlmeans/server-
|
|
42
|
-
"@owlmeans/server-
|
|
43
|
-
"@owlmeans/server-
|
|
44
|
-
"@owlmeans/socket": "^0.1.18-rc.
|
|
35
|
+
"@owlmeans/auth": "^0.1.18-rc.32",
|
|
36
|
+
"@owlmeans/auth-common": "^0.1.18-rc.34",
|
|
37
|
+
"@owlmeans/context": "^0.1.18-rc.30",
|
|
38
|
+
"@owlmeans/entrypoint": "^0.1.18-rc.33",
|
|
39
|
+
"@owlmeans/job": "^0.1.18-rc.4",
|
|
40
|
+
"@owlmeans/queue": "^0.1.18-rc.28",
|
|
41
|
+
"@owlmeans/resource": "^0.1.18-rc.32",
|
|
42
|
+
"@owlmeans/route": "^0.1.18-rc.31",
|
|
43
|
+
"@owlmeans/server-api": "^0.1.18-rc.38",
|
|
44
|
+
"@owlmeans/server-context": "^0.1.18-rc.33",
|
|
45
|
+
"@owlmeans/server-entrypoint": "^0.1.18-rc.32",
|
|
46
|
+
"@owlmeans/server-socket": "^0.1.18-rc.41",
|
|
47
|
+
"@owlmeans/socket": "^0.1.18-rc.30"
|
|
45
48
|
}
|
|
46
49
|
}
|