@anchrd/intel-contract 0.25.0 → 0.26.0
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/dist/contract/feed.d.ts +70 -0
- package/dist/contract/feed.js +84 -0
- package/package.json +5 -1
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const FeedAction: z.ZodEnum<{
|
|
3
|
+
"node.create": "node.create";
|
|
4
|
+
"node.save": "node.save";
|
|
5
|
+
"node.update": "node.update";
|
|
6
|
+
"node.append": "node.append";
|
|
7
|
+
"node.archive": "node.archive";
|
|
8
|
+
"node.share": "node.share";
|
|
9
|
+
"node.revoke": "node.revoke";
|
|
10
|
+
}>;
|
|
11
|
+
export type FeedAction = z.infer<typeof FeedAction>;
|
|
12
|
+
export declare const FeedPathSegment: z.ZodObject<{
|
|
13
|
+
id: z.ZodString;
|
|
14
|
+
title: z.ZodString;
|
|
15
|
+
}, z.core.$strict>;
|
|
16
|
+
export type FeedPathSegment = z.infer<typeof FeedPathSegment>;
|
|
17
|
+
export declare const FeedEvent: z.ZodObject<{
|
|
18
|
+
id: z.ZodString;
|
|
19
|
+
actorId: z.ZodString;
|
|
20
|
+
action: z.ZodEnum<{
|
|
21
|
+
"node.create": "node.create";
|
|
22
|
+
"node.save": "node.save";
|
|
23
|
+
"node.update": "node.update";
|
|
24
|
+
"node.append": "node.append";
|
|
25
|
+
"node.archive": "node.archive";
|
|
26
|
+
"node.share": "node.share";
|
|
27
|
+
"node.revoke": "node.revoke";
|
|
28
|
+
}>;
|
|
29
|
+
nodeId: z.ZodString;
|
|
30
|
+
nodeTitle: z.ZodString;
|
|
31
|
+
path: z.ZodArray<z.ZodObject<{
|
|
32
|
+
id: z.ZodString;
|
|
33
|
+
title: z.ZodString;
|
|
34
|
+
}, z.core.$strict>>;
|
|
35
|
+
metadata: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
36
|
+
occurredAt: z.ZodISODateTime;
|
|
37
|
+
}, z.core.$strict>;
|
|
38
|
+
export type FeedEvent = z.infer<typeof FeedEvent>;
|
|
39
|
+
export declare const FeedCursor: z.ZodString;
|
|
40
|
+
export declare const FeedListRequest: z.ZodObject<{
|
|
41
|
+
actor: z.ZodOptional<z.ZodString>;
|
|
42
|
+
before: z.ZodOptional<z.ZodString>;
|
|
43
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
44
|
+
}, z.core.$strict>;
|
|
45
|
+
export type FeedListRequest = z.infer<typeof FeedListRequest>;
|
|
46
|
+
export declare const FeedListResponse: z.ZodObject<{
|
|
47
|
+
events: z.ZodArray<z.ZodObject<{
|
|
48
|
+
id: z.ZodString;
|
|
49
|
+
actorId: z.ZodString;
|
|
50
|
+
action: z.ZodEnum<{
|
|
51
|
+
"node.create": "node.create";
|
|
52
|
+
"node.save": "node.save";
|
|
53
|
+
"node.update": "node.update";
|
|
54
|
+
"node.append": "node.append";
|
|
55
|
+
"node.archive": "node.archive";
|
|
56
|
+
"node.share": "node.share";
|
|
57
|
+
"node.revoke": "node.revoke";
|
|
58
|
+
}>;
|
|
59
|
+
nodeId: z.ZodString;
|
|
60
|
+
nodeTitle: z.ZodString;
|
|
61
|
+
path: z.ZodArray<z.ZodObject<{
|
|
62
|
+
id: z.ZodString;
|
|
63
|
+
title: z.ZodString;
|
|
64
|
+
}, z.core.$strict>>;
|
|
65
|
+
metadata: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
66
|
+
occurredAt: z.ZodISODateTime;
|
|
67
|
+
}, z.core.$strict>>;
|
|
68
|
+
nextCursor: z.ZodNullable<z.ZodString>;
|
|
69
|
+
}, z.core.$strict>;
|
|
70
|
+
export type FeedListResponse = z.infer<typeof FeedListResponse>;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { IntelId, IsoDateTime } from "./contract.js";
|
|
3
|
+
// What a person did, in the words a person would use. This is a POSITIVE LIST and not the set of
|
|
4
|
+
// actions the journal carries (#740).
|
|
5
|
+
//
|
|
6
|
+
// ⚠️ Two omissions are the point of the list, not an oversight. `node.version` is written by the
|
|
7
|
+
// same batch as `node.save`, so admitting both would show every edit twice — and because this feed
|
|
8
|
+
// does not group anything yet, twice means two cards. `node.link` and `node.import` are machine
|
|
9
|
+
// traces of a save rather than something anybody did.
|
|
10
|
+
//
|
|
11
|
+
// ⚠️ And it stays a positive list. "Everything except" would silently admit whatever the next
|
|
12
|
+
// migration starts writing, on a surface whose whole job is to be readable.
|
|
13
|
+
export const FeedAction = z.enum([
|
|
14
|
+
"node.create",
|
|
15
|
+
"node.save",
|
|
16
|
+
"node.update",
|
|
17
|
+
"node.append",
|
|
18
|
+
"node.archive",
|
|
19
|
+
"node.share",
|
|
20
|
+
"node.revoke",
|
|
21
|
+
]);
|
|
22
|
+
// One step on the way down to the node, from the root. It carries the id as well as the title
|
|
23
|
+
// because the surface links each step, and two folders may share a name.
|
|
24
|
+
export const FeedPathSegment = z.strictObject({
|
|
25
|
+
id: IntelId,
|
|
26
|
+
title: z.string().min(1),
|
|
27
|
+
});
|
|
28
|
+
// One card's worth of journal.
|
|
29
|
+
//
|
|
30
|
+
// ⚠️ `nodeTitle` and `path` are read from `nodes` at query time, so they are TODAY's title and
|
|
31
|
+
// today's place — not the ones the node had when the event happened. That is the right answer for a
|
|
32
|
+
// feed (the reader wants to find the thing now) and the wrong one for an audit trail, which is one
|
|
33
|
+
// more reason these are two doors and not one.
|
|
34
|
+
//
|
|
35
|
+
// `metadata` is whatever the write site recorded, untyped on purpose: a schema per action would
|
|
36
|
+
// have to be kept in step with eleven write sites and would go stale in silence. What the surface
|
|
37
|
+
// needs from it today is `sequence` on a `node.save`, which is the version number behind the card's
|
|
38
|
+
// button.
|
|
39
|
+
export const FeedEvent = z.strictObject({
|
|
40
|
+
id: IntelId,
|
|
41
|
+
actorId: z.string().min(1),
|
|
42
|
+
action: FeedAction,
|
|
43
|
+
nodeId: IntelId,
|
|
44
|
+
nodeTitle: z.string().min(1),
|
|
45
|
+
path: z.array(FeedPathSegment),
|
|
46
|
+
metadata: z.record(z.string(), z.unknown()),
|
|
47
|
+
occurredAt: IsoDateTime,
|
|
48
|
+
});
|
|
49
|
+
// ⚠️ Opaque BY CONTRACT, like the audit cursor and for the same reason: it is a PAIR
|
|
50
|
+
// (`occurredAt`, `id`), and a timestamp alone cannot separate two events written in the same
|
|
51
|
+
// millisecond — the normal case inside one batch. A reader continuing on the timestamp alone skips
|
|
52
|
+
// the second one with no error and no log.
|
|
53
|
+
//
|
|
54
|
+
// ⚠️ It is deliberately NOT interchangeable with an audit cursor, although both encode the same
|
|
55
|
+
// pair. The two doors walk the journal in opposite directions, so handing one's position to the
|
|
56
|
+
// other reads on from the wrong end — and would look like a feed that suddenly starts at the
|
|
57
|
+
// beginning of time rather than like a mistake. The encoding therefore carries its own marker and
|
|
58
|
+
// the other door's cursor is refused.
|
|
59
|
+
export const FeedCursor = z.string().min(1).max(400);
|
|
60
|
+
export const FeedListRequest = z.strictObject({
|
|
61
|
+
actor: z
|
|
62
|
+
.string()
|
|
63
|
+
.min(1)
|
|
64
|
+
.optional()
|
|
65
|
+
.describe("Show only what this person or agent did. Omit it for everybody whose work you may see anyway."),
|
|
66
|
+
before: FeedCursor.optional().describe("Where to continue: the `nextCursor` of a previous answer, passed back unchanged. Omit it to start at the most recent event. Do not build one — it is opaque on purpose, and a cursor from `audit_list` is refused rather than followed backwards."),
|
|
67
|
+
limit: z
|
|
68
|
+
.number()
|
|
69
|
+
.int()
|
|
70
|
+
.min(1)
|
|
71
|
+
.max(100)
|
|
72
|
+
.default(30)
|
|
73
|
+
.describe("How many events to return at most. The answer may be shorter."),
|
|
74
|
+
});
|
|
75
|
+
// `nextCursor` is present exactly when another page may exist, and it is the cursor of the LAST
|
|
76
|
+
// returned row.
|
|
77
|
+
//
|
|
78
|
+
// ⚠️ Present does not promise the next page is non-empty: the rows a reader may see can shrink
|
|
79
|
+
// between calls. Treating "cursor present" as "there is more" is fair; treating an empty answer as
|
|
80
|
+
// "you have reached the beginning of the journal" is not.
|
|
81
|
+
export const FeedListResponse = z.strictObject({
|
|
82
|
+
events: z.array(FeedEvent),
|
|
83
|
+
nextCursor: FeedCursor.nullable(),
|
|
84
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anchrd/intel-contract",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"repository": {
|
|
@@ -28,6 +28,10 @@
|
|
|
28
28
|
"types": "./dist/contract/bundle.d.ts",
|
|
29
29
|
"default": "./dist/contract/bundle.js"
|
|
30
30
|
},
|
|
31
|
+
"./feed": {
|
|
32
|
+
"types": "./dist/contract/feed.d.ts",
|
|
33
|
+
"default": "./dist/contract/feed.js"
|
|
34
|
+
},
|
|
31
35
|
"./flow": {
|
|
32
36
|
"types": "./dist/contract/flow.d.ts",
|
|
33
37
|
"default": "./dist/contract/flow.js"
|