@ixo/topic-protocol 0.1.1 → 0.3.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/README.md +11 -2
- package/dist/schemas/topic-capsule.schema.json +2 -1
- package/dist/schemas/topic-file-attachment.schema.json +23 -0
- package/dist/schemas/topic-operation.schema.json +1 -1
- package/dist/schemas/topic-record-message.schema.json +23 -0
- package/dist/schemas/topic-root.schema.json +31 -1
- package/dist/schemas/topic-source-message.schema.json +54 -0
- package/dist/schemas/topic-state.schema.json +22 -1
- package/dist/src/contracts/schemas.d.ts +302 -1
- package/dist/src/contracts/schemas.js +6 -0
- package/dist/src/contracts/schemas.js.map +1 -1
- package/dist/src/contracts/validator.d.ts +1 -0
- package/dist/src/contracts/validator.js +10 -1
- package/dist/src/contracts/validator.js.map +1 -1
- package/dist/src/errors.d.ts +1 -1
- package/dist/src/errors.js.map +1 -1
- package/dist/src/index.d.ts +5 -3
- package/dist/src/index.js +4 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/matrix/cards.d.ts +59 -0
- package/dist/src/matrix/cards.js +86 -0
- package/dist/src/matrix/cards.js.map +1 -0
- package/dist/src/matrix/content.d.ts +2 -1
- package/dist/src/matrix/content.js +11 -0
- package/dist/src/matrix/content.js.map +1 -1
- package/dist/src/matrix/events.js +0 -2
- package/dist/src/matrix/events.js.map +1 -1
- package/dist/src/matrix/runtime.js +12 -4
- package/dist/src/matrix/runtime.js.map +1 -1
- package/dist/src/matrix/types.d.ts +2 -1
- package/dist/src/projector/payload.d.ts +11 -1
- package/dist/src/projector/payload.js +131 -2
- package/dist/src/projector/payload.js.map +1 -1
- package/dist/src/projector/prepare.d.ts +2 -1
- package/dist/src/projector/prepare.js +5 -6
- package/dist/src/projector/prepare.js.map +1 -1
- package/dist/src/projector/project.js +5 -4
- package/dist/src/projector/project.js.map +1 -1
- package/dist/src/projector/state.js +57 -0
- package/dist/src/projector/state.js.map +1 -1
- package/dist/src/projector/types.d.ts +48 -1
- package/dist/src/projector/types.js +18 -0
- package/dist/src/projector/types.js.map +1 -1
- package/dist/src/records/types.d.ts +12 -0
- package/dist/src/records/types.js +12 -0
- package/dist/src/records/types.js.map +1 -0
- package/package.json +1 -1
|
@@ -6,6 +6,9 @@ const ajv = new Ajv2020({ allErrors: true, strict: true });
|
|
|
6
6
|
const validators = new Map();
|
|
7
7
|
const addFormats = formatsModule.default;
|
|
8
8
|
addFormats(ajv);
|
|
9
|
+
for (const schema of Object.values(SCHEMA_REGISTRY))
|
|
10
|
+
ajv.addSchema(schema);
|
|
11
|
+
const dateTimeValidator = ajv.compile({ type: "string", format: "date-time" });
|
|
9
12
|
function isContractName(value) {
|
|
10
13
|
return Object.hasOwn(SCHEMA_REGISTRY, value);
|
|
11
14
|
}
|
|
@@ -13,10 +16,16 @@ function validatorFor(name) {
|
|
|
13
16
|
const existing = validators.get(name);
|
|
14
17
|
if (existing !== undefined)
|
|
15
18
|
return existing;
|
|
16
|
-
const
|
|
19
|
+
const schema = SCHEMA_REGISTRY[name];
|
|
20
|
+
const validator = ajv.getSchema(schema.$id);
|
|
21
|
+
if (validator === undefined)
|
|
22
|
+
throw new Error(`Schema is not registered: ${schema.$id}`);
|
|
17
23
|
validators.set(name, validator);
|
|
18
24
|
return validator;
|
|
19
25
|
}
|
|
26
|
+
export function isJsonDateTime(value) {
|
|
27
|
+
return dateTimeValidator(value);
|
|
28
|
+
}
|
|
20
29
|
function normaliseError(error) {
|
|
21
30
|
const path = error.instancePath.length === 0 ? "/" : error.instancePath;
|
|
22
31
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../../src/contracts/validator.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,GAGR,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,aAAa,MAAM,aAAa,CAAC;AAG7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EACL,eAAe,GAEhB,MAAM,cAAc,CAAC;AAYtB,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AAC3D,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkC,CAAC;AAC7D,MAAM,UAAU,GAAG,aAAa,CAAC,OAAmC,CAAC;AACrE,UAAU,CAAC,GAAG,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../../src/contracts/validator.ts"],"names":[],"mappings":"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"}
|
package/dist/src/errors.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type TopicProtocolErrorCode = "ANCHOR_CONFLICT" | "ANCHOR_CYCLE" | "AUTHORIZATION_FAILED" | "CONTRACT_VALIDATION_FAILED" | "DUPLICATE_OPERATION" | "FIRST_MESSAGE_FAILED" | "INVALID_ANCHOR" | "INVALID_MATRIX_EVENT" | "INVALID_OPERATION_PAYLOAD" | "INVALID_SERVER_EVENT_ID" | "NON_CANONICAL_CONFLICT_SELECTION" | "PENDING_ROOT_UNRESOLVED" | "ROOT_CREATION_FAILED" | "ROOT_DISCOVERY_FAILED" | "STORAGE_FAILED" | "TOPIC_ROOT_NOT_FOUND" | "TOPIC_MISMATCH" | "UNKNOWN_CONFLICT" | "UNKNOWN_CONTRACT";
|
|
1
|
+
export type TopicProtocolErrorCode = "ANCHOR_CONFLICT" | "ANCHOR_CYCLE" | "AUTHORIZATION_FAILED" | "CONTRACT_VALIDATION_FAILED" | "DUPLICATE_OPERATION" | "FIRST_MESSAGE_FAILED" | "INVALID_ANCHOR" | "INVALID_CONTEXT_TYPE" | "INVALID_MATRIX_EVENT" | "INVALID_OPERATION_PAYLOAD" | "INVALID_SERVER_EVENT_ID" | "NON_CANONICAL_CONFLICT_SELECTION" | "PENDING_ROOT_UNRESOLVED" | "ROOT_CREATION_FAILED" | "ROOT_DISCOVERY_FAILED" | "STORAGE_FAILED" | "TOPIC_ROOT_NOT_FOUND" | "TOPIC_MISMATCH" | "UNKNOWN_CONFLICT" | "UNKNOWN_CONTRACT";
|
|
2
2
|
export declare class TopicProtocolError extends Error {
|
|
3
3
|
readonly code: TopicProtocolErrorCode;
|
|
4
4
|
readonly details: Readonly<Record<string, unknown>>;
|
package/dist/src/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAsBA,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAClC,IAAI,CAAyB;IAC7B,OAAO,CAAoC;IAEpD,YACE,IAA4B,EAC5B,OAAe,EACf,UAA6C,EAAE,EAC/C,OAAsB;QAEtB,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -3,9 +3,11 @@ export { assertContract, validateContract, type ContractValidationError, type Co
|
|
|
3
3
|
export { TopicProtocolError, type TopicProtocolErrorCode, } from "./errors.js";
|
|
4
4
|
export { projectTopic } from "./projector/project.js";
|
|
5
5
|
export { selectCanonicalTopicAnchor } from "./matrix/anchors.js";
|
|
6
|
-
export { assertMatrixAnchor, assertMatrixRoomId, assertServerEventId, assertTopicMessageContent, buildTopicMessageContent, buildTopicOperationContent, buildTopicRootContent, createTopicId, } from "./matrix/content.js";
|
|
6
|
+
export { assertMatrixAnchor, assertMatrixRoomId, assertServerEventId, assertTopicMessageContent, buildTopicMessageContent, buildTopicOperationContent, buildTopicRootContent, createTopicId, createTopicOperationId, } from "./matrix/content.js";
|
|
7
|
+
export { TOPIC_RECORD_KEY, TOPIC_RECORD_MSGTYPE, TOPIC_SOURCE_KEY, TOPIC_SOURCE_KINDS, TOPIC_SOURCE_MSGTYPE, createTopicRecordMessageContent, createTopicSourceMessageContent, parseTopicRecordMessageContent, parseTopicSourceMessageContent, type CreateTopicRecordMessageInput, type CreateTopicSourceMessageInput, type TopicCardContext, type TopicRecordMessageContent, type TopicSourceDisclosure, type TopicSourceKind, type TopicSourceMessageContent, type TopicSourceReference, } from "./matrix/cards.js";
|
|
7
8
|
export { isTopicInfrastructureEvent, parseTopicRootEvent, projectMatrixTopic, } from "./matrix/events.js";
|
|
8
9
|
export { JsonPendingTopicStore, MemoryPendingTopicStore, type TopicKeyValueStore, } from "./matrix/pending.js";
|
|
9
10
|
export { TopicRuntime, type TopicRuntimeOptions } from "./matrix/runtime.js";
|
|
10
|
-
export { MATRIX_ROOM_MESSAGE, TOPIC_ANCHOR_KEY, TOPIC_METADATA_KEY, TOPIC_OPERATION_EVENT_TYPE, type CanonicalTopicAnchor, type MatrixEventContent, type MatrixSendRequest, type MatrixTopicProjection, type MatrixTopicProjectionInput, type ParsedTopicRoot, type PendingTopicCreation, type PendingTopicStore, type RejectedTopicEvent, type RejectedTopicEventReason, type TopicAnchorConflict, type TopicCreationInput, type TopicCreationResult, type TopicMatrixEvent, type TopicMatrixTransport, type TopicRootContentOptions, } from "./matrix/types.js";
|
|
11
|
-
export { TOPIC_KINDS, TOPIC_STATUSES, type IgnoredOperation, type IgnoredOperationReason, type MatrixAnchor, type ProjectedTopicRelation, type ProjectionInput, type TopicContext, type TopicDecision, type TopicKind, type TopicOperation, type TopicOperationType, type TopicProjection, type TopicProjectionConflict, type TopicRelationType, type TopicRoot, type TopicStatus, } from "./projector/types.js";
|
|
11
|
+
export { MATRIX_ROOM_MESSAGE, TOPIC_ANCHOR_KEY, TOPIC_METADATA_KEY, TOPIC_OPERATION_EVENT_TYPE, type CanonicalTopicAnchor, type MatrixEventContent, type MatrixSendRequest, type MatrixTopicProjection, type MatrixTopicProjectionInput, type ParsedTopicRoot, type PendingTopicCreation, type PendingTopicStore, type RejectedTopicEvent, type RejectedTopicEventReason, type TopicAnchorConflict, type TopicCreationInput, type TopicCreationResult, type TopicFirstMessageFactory, type TopicMatrixEvent, type TopicMatrixTransport, type TopicRootContentOptions, } from "./matrix/types.js";
|
|
12
|
+
export { TOPIC_KINDS, TOPIC_CONTEXT_TYPES, TOPIC_STATUSES, TOPIC_VFS_FILE_PROVIDER, type IgnoredOperation, type IgnoredOperationReason, type MatrixAnchor, type ProjectedTopicRelation, type ProjectionInput, type TopicContext, type TopicContextType, type TopicFileAttachmentIdentity, type TopicDecision, type TopicKind, type TopicNextStep, type TopicOperation, type TopicOperationType, type TopicProjection, type ProjectedTopicAttachment, type ProjectedTopicOverview, type TopicOverview, type TopicProjectionConflict, type TopicRelationType, type TopicRoot, type TopicStatus, type TopicVfsFileReference, isCanonicalTopicContextType, } from "./projector/types.js";
|
|
13
|
+
export { TOPIC_RECORD_KINDS, type TopicRecord, type TopicRecordKind, } from "./records/types.js";
|
package/dist/src/index.js
CHANGED
|
@@ -3,10 +3,12 @@ export { assertContract, validateContract, } from "./contracts/validator.js";
|
|
|
3
3
|
export { TopicProtocolError, } from "./errors.js";
|
|
4
4
|
export { projectTopic } from "./projector/project.js";
|
|
5
5
|
export { selectCanonicalTopicAnchor } from "./matrix/anchors.js";
|
|
6
|
-
export { assertMatrixAnchor, assertMatrixRoomId, assertServerEventId, assertTopicMessageContent, buildTopicMessageContent, buildTopicOperationContent, buildTopicRootContent, createTopicId, } from "./matrix/content.js";
|
|
6
|
+
export { assertMatrixAnchor, assertMatrixRoomId, assertServerEventId, assertTopicMessageContent, buildTopicMessageContent, buildTopicOperationContent, buildTopicRootContent, createTopicId, createTopicOperationId, } from "./matrix/content.js";
|
|
7
|
+
export { TOPIC_RECORD_KEY, TOPIC_RECORD_MSGTYPE, TOPIC_SOURCE_KEY, TOPIC_SOURCE_KINDS, TOPIC_SOURCE_MSGTYPE, createTopicRecordMessageContent, createTopicSourceMessageContent, parseTopicRecordMessageContent, parseTopicSourceMessageContent, } from "./matrix/cards.js";
|
|
7
8
|
export { isTopicInfrastructureEvent, parseTopicRootEvent, projectMatrixTopic, } from "./matrix/events.js";
|
|
8
9
|
export { JsonPendingTopicStore, MemoryPendingTopicStore, } from "./matrix/pending.js";
|
|
9
10
|
export { TopicRuntime } from "./matrix/runtime.js";
|
|
10
11
|
export { MATRIX_ROOM_MESSAGE, TOPIC_ANCHOR_KEY, TOPIC_METADATA_KEY, TOPIC_OPERATION_EVENT_TYPE, } from "./matrix/types.js";
|
|
11
|
-
export { TOPIC_KINDS, TOPIC_STATUSES, } from "./projector/types.js";
|
|
12
|
+
export { TOPIC_KINDS, TOPIC_CONTEXT_TYPES, TOPIC_STATUSES, TOPIC_VFS_FILE_PROVIDER, isCanonicalTopicContextType, } from "./projector/types.js";
|
|
13
|
+
export { TOPIC_RECORD_KINDS, } from "./records/types.js";
|
|
12
14
|
//# sourceMappingURL=index.js.map
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,GAEf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,cAAc,EACd,gBAAgB,GAGjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,kBAAkB,GAEnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,yBAAyB,EACzB,wBAAwB,EACxB,0BAA0B,EAC1B,qBAAqB,EACrB,aAAa,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,GAEf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,cAAc,EACd,gBAAgB,GAGjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,kBAAkB,GAEnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,yBAAyB,EACzB,wBAAwB,EACxB,0BAA0B,EAC1B,qBAAqB,EACrB,aAAa,EACb,sBAAsB,GACvB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EACpB,+BAA+B,EAC/B,+BAA+B,EAC/B,8BAA8B,EAC9B,8BAA8B,GAS/B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,0BAA0B,EAC1B,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,qBAAqB,EACrB,uBAAuB,GAExB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAA4B,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,0BAA0B,GAkB3B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,uBAAuB,EAuBvB,2BAA2B,GAC5B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,kBAAkB,GAGnB,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { MatrixAnchor } from "../projector/types.js";
|
|
2
|
+
import type { TopicRecord } from "../records/types.js";
|
|
3
|
+
export declare const TOPIC_RECORD_MSGTYPE = "ixo.topic.record";
|
|
4
|
+
export declare const TOPIC_SOURCE_MSGTYPE = "ixo.topic.source";
|
|
5
|
+
export declare const TOPIC_RECORD_KEY = "ixo.topic.record";
|
|
6
|
+
export declare const TOPIC_SOURCE_KEY = "ixo.topic.source";
|
|
7
|
+
export declare const TOPIC_SOURCE_KINDS: readonly ["message", "flow", "decision", "artifact", "notification", "other"];
|
|
8
|
+
export type TopicSourceKind = (typeof TOPIC_SOURCE_KINDS)[number];
|
|
9
|
+
export type TopicSourceDisclosure = "reference-only" | "summary";
|
|
10
|
+
export interface TopicSourceReference {
|
|
11
|
+
readonly roomId: string;
|
|
12
|
+
readonly eventId: string;
|
|
13
|
+
readonly kind: TopicSourceKind;
|
|
14
|
+
readonly occurredAt: string;
|
|
15
|
+
readonly disclosure: TopicSourceDisclosure;
|
|
16
|
+
readonly label?: string;
|
|
17
|
+
readonly summary?: string;
|
|
18
|
+
}
|
|
19
|
+
interface ThreadRelation {
|
|
20
|
+
readonly rel_type: "m.thread";
|
|
21
|
+
readonly event_id: string;
|
|
22
|
+
readonly is_falling_back: true;
|
|
23
|
+
}
|
|
24
|
+
export interface TopicRecordMessageContent {
|
|
25
|
+
readonly [key: string]: unknown;
|
|
26
|
+
readonly msgtype: typeof TOPIC_RECORD_MSGTYPE;
|
|
27
|
+
readonly body: string;
|
|
28
|
+
readonly "ixo.topic.record": TopicRecord;
|
|
29
|
+
readonly "m.relates_to": ThreadRelation;
|
|
30
|
+
}
|
|
31
|
+
export interface TopicSourceMessageContent {
|
|
32
|
+
readonly [key: string]: unknown;
|
|
33
|
+
readonly msgtype: typeof TOPIC_SOURCE_MSGTYPE;
|
|
34
|
+
readonly body: string;
|
|
35
|
+
readonly topicId: string;
|
|
36
|
+
readonly "ixo.topic.source": TopicSourceReference;
|
|
37
|
+
readonly "m.relates_to": ThreadRelation;
|
|
38
|
+
}
|
|
39
|
+
export interface TopicCardContext {
|
|
40
|
+
readonly topicId?: string;
|
|
41
|
+
readonly anchor?: MatrixAnchor;
|
|
42
|
+
}
|
|
43
|
+
export interface CreateTopicRecordMessageInput {
|
|
44
|
+
readonly topicId: string;
|
|
45
|
+
readonly anchor: MatrixAnchor;
|
|
46
|
+
readonly body: string;
|
|
47
|
+
readonly record: TopicRecord;
|
|
48
|
+
}
|
|
49
|
+
export interface CreateTopicSourceMessageInput {
|
|
50
|
+
readonly topicId: string;
|
|
51
|
+
readonly anchor: MatrixAnchor;
|
|
52
|
+
readonly body: string;
|
|
53
|
+
readonly source: TopicSourceReference;
|
|
54
|
+
}
|
|
55
|
+
export declare function createTopicRecordMessageContent(input: CreateTopicRecordMessageInput): TopicRecordMessageContent;
|
|
56
|
+
export declare function createTopicSourceMessageContent(input: CreateTopicSourceMessageInput): TopicSourceMessageContent;
|
|
57
|
+
export declare function parseTopicRecordMessageContent(content: unknown, context?: TopicCardContext): TopicRecordMessageContent | null;
|
|
58
|
+
export declare function parseTopicSourceMessageContent(content: unknown, context?: TopicCardContext): TopicSourceMessageContent | null;
|
|
59
|
+
export {};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { assertContract, validateContract } from "../contracts/validator.js";
|
|
2
|
+
import { TopicProtocolError } from "../errors.js";
|
|
3
|
+
import { buildTopicMessageContent } from "./content.js";
|
|
4
|
+
export const TOPIC_RECORD_MSGTYPE = "ixo.topic.record";
|
|
5
|
+
export const TOPIC_SOURCE_MSGTYPE = "ixo.topic.source";
|
|
6
|
+
export const TOPIC_RECORD_KEY = "ixo.topic.record";
|
|
7
|
+
export const TOPIC_SOURCE_KEY = "ixo.topic.source";
|
|
8
|
+
export const TOPIC_SOURCE_KINDS = [
|
|
9
|
+
"message",
|
|
10
|
+
"flow",
|
|
11
|
+
"decision",
|
|
12
|
+
"artifact",
|
|
13
|
+
"notification",
|
|
14
|
+
"other",
|
|
15
|
+
];
|
|
16
|
+
function invalid(message) {
|
|
17
|
+
throw new TopicProtocolError("INVALID_MATRIX_EVENT", message);
|
|
18
|
+
}
|
|
19
|
+
function assertMatchingTopic(expected, actual) {
|
|
20
|
+
if (actual === expected)
|
|
21
|
+
return;
|
|
22
|
+
invalid("Topic card payload does not match the selected Topic");
|
|
23
|
+
}
|
|
24
|
+
function assertSourceDisclosure(source) {
|
|
25
|
+
const copiesDetails = source.label !== undefined || source.summary !== undefined;
|
|
26
|
+
if (source.disclosure === "reference-only" && copiesDetails) {
|
|
27
|
+
invalid("Reference-only Topic source cards cannot copy labels or summaries");
|
|
28
|
+
}
|
|
29
|
+
if (source.disclosure === "summary" && source.summary === undefined) {
|
|
30
|
+
invalid("Summary Topic source cards require an explicitly disclosed summary");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function matchesAnchor(content, anchor) {
|
|
34
|
+
if (anchor === undefined)
|
|
35
|
+
return true;
|
|
36
|
+
const relation = content["m.relates_to"];
|
|
37
|
+
if (typeof relation !== "object" || relation === null)
|
|
38
|
+
return false;
|
|
39
|
+
return relation.event_id === anchor.rootEventId;
|
|
40
|
+
}
|
|
41
|
+
export function createTopicRecordMessageContent(input) {
|
|
42
|
+
assertMatchingTopic(input.topicId, input.record.topicId);
|
|
43
|
+
assertContract("topic-record", input.record);
|
|
44
|
+
const content = buildTopicMessageContent(input.anchor, {
|
|
45
|
+
msgtype: TOPIC_RECORD_MSGTYPE,
|
|
46
|
+
body: input.body,
|
|
47
|
+
[TOPIC_RECORD_KEY]: input.record,
|
|
48
|
+
});
|
|
49
|
+
assertContract("topic-record-message", content);
|
|
50
|
+
return content;
|
|
51
|
+
}
|
|
52
|
+
export function createTopicSourceMessageContent(input) {
|
|
53
|
+
assertSourceDisclosure(input.source);
|
|
54
|
+
const content = buildTopicMessageContent(input.anchor, {
|
|
55
|
+
msgtype: TOPIC_SOURCE_MSGTYPE,
|
|
56
|
+
body: input.body,
|
|
57
|
+
topicId: input.topicId,
|
|
58
|
+
[TOPIC_SOURCE_KEY]: input.source,
|
|
59
|
+
});
|
|
60
|
+
assertContract("topic-source-message", content);
|
|
61
|
+
return content;
|
|
62
|
+
}
|
|
63
|
+
export function parseTopicRecordMessageContent(content, context = {}) {
|
|
64
|
+
if (!validateContract("topic-record-message", content).ok)
|
|
65
|
+
return null;
|
|
66
|
+
const matrixContent = content;
|
|
67
|
+
const record = matrixContent[TOPIC_RECORD_KEY];
|
|
68
|
+
if (!validateContract("topic-record", record).ok)
|
|
69
|
+
return null;
|
|
70
|
+
if (context.topicId !== undefined && record.topicId !== context.topicId)
|
|
71
|
+
return null;
|
|
72
|
+
if (!matchesAnchor(matrixContent, context.anchor))
|
|
73
|
+
return null;
|
|
74
|
+
return content;
|
|
75
|
+
}
|
|
76
|
+
export function parseTopicSourceMessageContent(content, context = {}) {
|
|
77
|
+
if (!validateContract("topic-source-message", content).ok)
|
|
78
|
+
return null;
|
|
79
|
+
const matrixContent = content;
|
|
80
|
+
if (context.topicId !== undefined && matrixContent.topicId !== context.topicId)
|
|
81
|
+
return null;
|
|
82
|
+
if (!matchesAnchor(matrixContent, context.anchor))
|
|
83
|
+
return null;
|
|
84
|
+
return content;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=cards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cards.js","sourceRoot":"","sources":["../../../src/matrix/cards.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type MatrixAnchor, type TopicOperation, type TopicRoot } from "../projector/types.js";
|
|
2
2
|
import { MATRIX_ROOM_MESSAGE, TOPIC_OPERATION_EVENT_TYPE, type MatrixEventContent, type TopicRootContentOptions } from "./types.js";
|
|
3
3
|
export declare function createTopicId(): string;
|
|
4
|
+
export declare function createTopicOperationId(): string;
|
|
4
5
|
export declare function assertServerEventId(eventId: string): void;
|
|
5
6
|
export declare function assertMatrixRoomId(roomId: string): void;
|
|
6
7
|
export declare function assertMatrixAnchor(anchor: MatrixAnchor): void;
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { v7 as uuidv7 } from "uuid";
|
|
2
2
|
import { assertContract } from "../contracts/validator.js";
|
|
3
3
|
import { TopicProtocolError } from "../errors.js";
|
|
4
|
+
import { parsePayload } from "../projector/payload.js";
|
|
5
|
+
import { isCanonicalTopicContextType, } from "../projector/types.js";
|
|
4
6
|
import { MATRIX_ROOM_MESSAGE, TOPIC_ANCHOR_KEY, TOPIC_METADATA_KEY, TOPIC_OPERATION_EVENT_TYPE, } from "./types.js";
|
|
5
7
|
export function createTopicId() {
|
|
6
8
|
return `ixo:topic:${uuidv7()}`;
|
|
7
9
|
}
|
|
10
|
+
export function createTopicOperationId() {
|
|
11
|
+
return `ixo:topic-operation:${uuidv7()}`;
|
|
12
|
+
}
|
|
8
13
|
export function assertServerEventId(eventId) {
|
|
9
14
|
if (eventId.startsWith("$") && eventId.length > 1)
|
|
10
15
|
return;
|
|
@@ -26,6 +31,11 @@ export function assertTopicMessageContent(message) {
|
|
|
26
31
|
}
|
|
27
32
|
export function buildTopicRootContent(root, options = {}) {
|
|
28
33
|
assertContract("topic-root", root);
|
|
34
|
+
for (const context of root.context ?? []) {
|
|
35
|
+
if (isCanonicalTopicContextType(context.type))
|
|
36
|
+
continue;
|
|
37
|
+
throw new TopicProtocolError("INVALID_CONTEXT_TYPE", "New Topic roots require core or dotted vendor context types", { type: context.type });
|
|
38
|
+
}
|
|
29
39
|
if (options.replaces !== undefined)
|
|
30
40
|
assertMatrixAnchor(options.replaces);
|
|
31
41
|
return {
|
|
@@ -52,6 +62,7 @@ export function buildTopicMessageContent(anchor, message) {
|
|
|
52
62
|
export function buildTopicOperationContent(anchor, operation) {
|
|
53
63
|
assertMatrixAnchor(anchor);
|
|
54
64
|
assertContract("topic-operation", operation);
|
|
65
|
+
parsePayload(operation);
|
|
55
66
|
return {
|
|
56
67
|
operation,
|
|
57
68
|
"m.relates_to": {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content.js","sourceRoot":"","sources":["../../../src/matrix/content.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,CAAC;AAEpC,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"content.js","sourceRoot":"","sources":["../../../src/matrix/content.ts"],"names":[],"mappings":"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"}
|
|
@@ -69,8 +69,6 @@ function parseOperationEvent(event, rootEventId, authenticateActor) {
|
|
|
69
69
|
if (!validateContract("topic-operation", operation).ok)
|
|
70
70
|
return rejected(event.eventId, "invalid-content");
|
|
71
71
|
const typed = operation;
|
|
72
|
-
if (typed.operationId !== event.eventId)
|
|
73
|
-
return rejected(event.eventId, "invalid-content");
|
|
74
72
|
if (!authenticateActor(typed, event))
|
|
75
73
|
return rejected(event.eventId, "actor-mismatch");
|
|
76
74
|
return { operation: typed };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../../src/matrix/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,0BAA0B,GAO3B,MAAM,YAAY,CAAC;AAEpB,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IACjC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAC;IACpE,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;IACrC,MAAM,WAAW,GAAG,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC;IAC/C,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAC5E,IAAI,OAAO,WAAW,KAAK,QAAQ,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IACtF,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;AACjC,CAAC;AAED,SAAS,eAAe,CAAC,KAAuB;IAC9C,OAAO,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;WACzD,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAuB;IACzD,IAAI,KAAK,CAAC,IAAI,KAAK,mBAAmB,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/E,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACzC,IAAI,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC7D,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC/C,IAAI,CAAC,gBAAgB,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IAC1D,MAAM,cAAc,GAAG,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAG,WAAW,CAAC,cAAc,CAAC,CAAC;IAC7C,IAAI,cAAc,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACxE,MAAM,MAAM,GAAG;QACb,KAAK;QACL,IAAI,EAAE,IAAiB;QACvB,MAAM,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,OAAO,EAAE;KAC7D,CAAC;IACF,OAAO,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,KAAuB;IAChE,IAAI,KAAK,CAAC,IAAI,KAAK,0BAA0B;QAAE,OAAO,IAAI,CAAC;IAC3D,OAAO,mBAAmB,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;AAC7C,CAAC;AAOD,SAAS,QAAQ,CAAC,OAAe,EAAE,MAAgC;IACjE,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC;AAC5C,CAAC;AAED,SAAS,YAAY,CAAC,OAA0C;IAC9D,MAAM,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACzC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,QAAQ,KAAK,aAAa;QAAE,OAAO,SAAS,CAAC;IACjF,OAAO,OAAO,QAAQ,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/E,CAAC;AAED,SAAS,mBAAmB,CAC1B,KAAuB,EACvB,WAAmB,EACnB,iBAAkE;IAElE,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI;QAAE,OAAO,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACxE,IAAI,KAAK,CAAC,IAAI,KAAK,0BAA0B;QAAE,OAAO,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;IACjG,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7C,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;IAC/E,IAAI,QAAQ,KAAK,WAAW;QAAE,OAAO,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IAC3E,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;IAC1C,IAAI,CAAC,gBAAgB,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC,EAAE;QAAE,OAAO,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;IAC1G,MAAM,KAAK,GAAG,SAA2B,CAAC;IAC1C,IAAI,
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../../src/matrix/events.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,16 @@ import { TopicProtocolError } from "../errors.js";
|
|
|
2
2
|
import { assertMatrixRoomId, assertServerEventId, assertTopicMessageContent, buildTopicMessageContent, buildTopicRootContent, } from "./content.js";
|
|
3
3
|
import { parseTopicRootEvent } from "./events.js";
|
|
4
4
|
import { MATRIX_ROOM_MESSAGE, } from "./types.js";
|
|
5
|
+
function firstMessageContent(input, anchor) {
|
|
6
|
+
const message = typeof input.firstMessage === "function" ? input.firstMessage(anchor) : input.firstMessage;
|
|
7
|
+
assertTopicMessageContent(message);
|
|
8
|
+
return buildTopicMessageContent(anchor, message);
|
|
9
|
+
}
|
|
10
|
+
function validateCreationInput(input) {
|
|
11
|
+
assertMatrixRoomId(input.roomId);
|
|
12
|
+
buildTopicRootContent(input.root);
|
|
13
|
+
firstMessageContent(input, { roomId: input.roomId, rootEventId: "$validation" });
|
|
14
|
+
}
|
|
5
15
|
export class TopicRuntime {
|
|
6
16
|
#inflight = new Map();
|
|
7
17
|
#transport;
|
|
@@ -24,14 +34,12 @@ export class TopicRuntime {
|
|
|
24
34
|
await this.removePending(roomId, topicId);
|
|
25
35
|
}
|
|
26
36
|
async create(input) {
|
|
27
|
-
|
|
28
|
-
buildTopicRootContent(input.root);
|
|
29
|
-
assertTopicMessageContent(input.firstMessage);
|
|
37
|
+
validateCreationInput(input);
|
|
30
38
|
const anchor = await this.resolveAnchor(input);
|
|
31
39
|
const messageRequest = {
|
|
32
40
|
roomId: input.roomId,
|
|
33
41
|
type: MATRIX_ROOM_MESSAGE,
|
|
34
|
-
content:
|
|
42
|
+
content: firstMessageContent(input, anchor),
|
|
35
43
|
};
|
|
36
44
|
let firstMessageEventId;
|
|
37
45
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/matrix/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,yBAAyB,EACzB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EACL,mBAAmB,GAOpB,MAAM,YAAY,CAAC;AAOpB,MAAM,OAAO,YAAY;IACd,SAAS,GAAG,IAAI,GAAG,EAAwC,CAAC;IAC5D,UAAU,CAAuB;IACjC,MAAM,CAAoB;IAEnC,YAAY,OAA4B;QACtC,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC;QACpC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IACrC,CAAC;IAED,WAAW,CAAC,KAAyB;QACnC,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,MAAM,SAAS,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAO,QAAQ,CAAC;QAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAClC,KAAK,QAAQ,CAAC,IAAI,CAChB,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,EAChC,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CACjC,CAAC;QACF,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,MAAc,EAAE,OAAe;QAClD,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;IAEO,KAAK,CAAC,MAAM,CAAC,KAAyB;QAC5C,
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/matrix/runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -35,10 +35,11 @@ export interface PendingTopicStore {
|
|
|
35
35
|
save(pending: PendingTopicCreation): Promise<void>;
|
|
36
36
|
remove(roomId: string, topicId: string): Promise<void>;
|
|
37
37
|
}
|
|
38
|
+
export type TopicFirstMessageFactory = (anchor: MatrixAnchor) => MatrixEventContent;
|
|
38
39
|
export interface TopicCreationInput {
|
|
39
40
|
readonly roomId: string;
|
|
40
41
|
readonly root: TopicRoot;
|
|
41
|
-
readonly firstMessage: MatrixEventContent;
|
|
42
|
+
readonly firstMessage: MatrixEventContent | TopicFirstMessageFactory;
|
|
42
43
|
}
|
|
43
44
|
export interface TopicCreationResult {
|
|
44
45
|
readonly root: TopicRoot;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type TopicContext, type TopicOperation, type TopicStatus } from "./types.js";
|
|
1
|
+
import { type TopicContext, type TopicFileAttachmentIdentity, type TopicOperation, type TopicOverview, type TopicStatus, type TopicVfsFileReference } from "./types.js";
|
|
2
2
|
interface DecisionPayload {
|
|
3
3
|
readonly id: string;
|
|
4
4
|
readonly summary: string;
|
|
@@ -9,9 +9,19 @@ export type ParsedPayload = {
|
|
|
9
9
|
} | {
|
|
10
10
|
readonly kind: "change-status";
|
|
11
11
|
readonly status: TopicStatus;
|
|
12
|
+
} | {
|
|
13
|
+
readonly kind: "update-overview";
|
|
14
|
+
readonly overview: TopicOverview;
|
|
15
|
+
readonly status?: TopicStatus;
|
|
12
16
|
} | {
|
|
13
17
|
readonly kind: "link-context" | "unlink-context";
|
|
14
18
|
readonly context: TopicContext;
|
|
19
|
+
} | {
|
|
20
|
+
readonly kind: "attach-files";
|
|
21
|
+
readonly files: readonly TopicVfsFileReference[];
|
|
22
|
+
} | {
|
|
23
|
+
readonly kind: "detach-files";
|
|
24
|
+
readonly files: readonly TopicFileAttachmentIdentity[];
|
|
15
25
|
} | {
|
|
16
26
|
readonly kind: "record-decision";
|
|
17
27
|
readonly decision: DecisionPayload;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { TopicProtocolError } from "../errors.js";
|
|
2
|
-
import {
|
|
2
|
+
import { isJsonDateTime } from "../contracts/validator.js";
|
|
3
|
+
import { isCanonicalTopicContextType, TOPIC_STATUSES, TOPIC_VFS_FILE_PROVIDER, } from "./types.js";
|
|
3
4
|
function invalid(operation, message) {
|
|
4
5
|
throw new TopicProtocolError("INVALID_OPERATION_PAYLOAD", `${operation.type} ${operation.operationId}: ${message}`, { operationId: operation.operationId, operationType: operation.type });
|
|
5
6
|
}
|
|
@@ -10,6 +11,13 @@ function recordValue(operation, key) {
|
|
|
10
11
|
}
|
|
11
12
|
return value;
|
|
12
13
|
}
|
|
14
|
+
function arrayValue(operation, key) {
|
|
15
|
+
const value = operation.payload[key];
|
|
16
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
17
|
+
return invalid(operation, `${key} must be a non-empty array`);
|
|
18
|
+
}
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
13
21
|
function stringValue(operation, source, key) {
|
|
14
22
|
const value = source[key];
|
|
15
23
|
if (typeof value !== "string" || value.trim().length === 0) {
|
|
@@ -17,6 +25,11 @@ function stringValue(operation, source, key) {
|
|
|
17
25
|
}
|
|
18
26
|
return value;
|
|
19
27
|
}
|
|
28
|
+
function optionalString(operation, source, key) {
|
|
29
|
+
if (source[key] === undefined)
|
|
30
|
+
return undefined;
|
|
31
|
+
return stringValue(operation, source, key);
|
|
32
|
+
}
|
|
20
33
|
function topicIdValue(operation, key) {
|
|
21
34
|
const value = stringValue(operation, operation.payload, key);
|
|
22
35
|
if (!/^ixo:topic:[0-9a-f-]{36}$/u.test(value)) {
|
|
@@ -26,11 +39,84 @@ function topicIdValue(operation, key) {
|
|
|
26
39
|
}
|
|
27
40
|
function contextValue(operation) {
|
|
28
41
|
const context = recordValue(operation, "context");
|
|
42
|
+
const type = stringValue(operation, context, "type");
|
|
43
|
+
if (!isCanonicalTopicContextType(type)) {
|
|
44
|
+
return invalid(operation, "context.type must be a core or dotted vendor namespace");
|
|
45
|
+
}
|
|
29
46
|
return {
|
|
30
|
-
type
|
|
47
|
+
type,
|
|
31
48
|
id: stringValue(operation, context, "id"),
|
|
32
49
|
};
|
|
33
50
|
}
|
|
51
|
+
function positiveIntegerValue(operation, source, key) {
|
|
52
|
+
const value = source[key];
|
|
53
|
+
if (!Number.isSafeInteger(value) || value < 1) {
|
|
54
|
+
return invalid(operation, `${key} must be a positive integer`);
|
|
55
|
+
}
|
|
56
|
+
return value;
|
|
57
|
+
}
|
|
58
|
+
function nonNegativeIntegerValue(operation, source, key) {
|
|
59
|
+
const value = source[key];
|
|
60
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
61
|
+
return invalid(operation, `${key} must be a non-negative integer`);
|
|
62
|
+
}
|
|
63
|
+
return value;
|
|
64
|
+
}
|
|
65
|
+
function attachmentIdentityValue(operation, value) {
|
|
66
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
67
|
+
return invalid(operation, "files entries must be objects");
|
|
68
|
+
}
|
|
69
|
+
const source = value;
|
|
70
|
+
const provider = stringValue(operation, source, "provider");
|
|
71
|
+
if (provider !== TOPIC_VFS_FILE_PROVIDER)
|
|
72
|
+
return invalid(operation, "provider must be ixo.vfs");
|
|
73
|
+
return {
|
|
74
|
+
provider: TOPIC_VFS_FILE_PROVIDER,
|
|
75
|
+
resource: stringValue(operation, source, "resource"),
|
|
76
|
+
fileId: stringValue(operation, source, "fileId"),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function attachmentValue(operation, value) {
|
|
80
|
+
const identity = attachmentIdentityValue(operation, value);
|
|
81
|
+
const source = value;
|
|
82
|
+
const contentHash = stringValue(operation, source, "contentHash");
|
|
83
|
+
if (!/^[0-9a-f]{64}$/u.test(contentHash)) {
|
|
84
|
+
return invalid(operation, "contentHash must be a lowercase SHA-256 digest");
|
|
85
|
+
}
|
|
86
|
+
const path = stringValue(operation, source, "path");
|
|
87
|
+
if (!path.startsWith("/") || path.split("/").includes("..")) {
|
|
88
|
+
return invalid(operation, "path must be an absolute VFS path without traversal");
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
...identity,
|
|
92
|
+
version: positiveIntegerValue(operation, source, "version"),
|
|
93
|
+
cid: stringValue(operation, source, "cid"),
|
|
94
|
+
contentHash,
|
|
95
|
+
path,
|
|
96
|
+
name: stringValue(operation, source, "name"),
|
|
97
|
+
mimeType: stringValue(operation, source, "mimeType"),
|
|
98
|
+
size: nonNegativeIntegerValue(operation, source, "size"),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function attachmentKey(identity) {
|
|
102
|
+
return `${identity.provider}\u0000${identity.resource}\u0000${identity.fileId}`;
|
|
103
|
+
}
|
|
104
|
+
function uniqueFiles(operation, files) {
|
|
105
|
+
const keys = new Set();
|
|
106
|
+
for (const file of files) {
|
|
107
|
+
const key = attachmentKey(file);
|
|
108
|
+
if (keys.has(key))
|
|
109
|
+
return invalid(operation, "files must not contain duplicate VFS identities");
|
|
110
|
+
keys.add(key);
|
|
111
|
+
}
|
|
112
|
+
return files;
|
|
113
|
+
}
|
|
114
|
+
function attachmentsValue(operation) {
|
|
115
|
+
return uniqueFiles(operation, arrayValue(operation, "files").map((value) => attachmentValue(operation, value)));
|
|
116
|
+
}
|
|
117
|
+
function attachmentIdentitiesValue(operation) {
|
|
118
|
+
return uniqueFiles(operation, arrayValue(operation, "files").map((value) => attachmentIdentityValue(operation, value)));
|
|
119
|
+
}
|
|
34
120
|
function decisionValue(operation) {
|
|
35
121
|
const decision = recordValue(operation, "decision");
|
|
36
122
|
return {
|
|
@@ -45,6 +131,43 @@ function statusValue(operation) {
|
|
|
45
131
|
}
|
|
46
132
|
return status;
|
|
47
133
|
}
|
|
134
|
+
function statusFrom(value, operation) {
|
|
135
|
+
if (!TOPIC_STATUSES.includes(value)) {
|
|
136
|
+
return invalid(operation, `status is not supported: ${value}`);
|
|
137
|
+
}
|
|
138
|
+
return value;
|
|
139
|
+
}
|
|
140
|
+
function nextStepValue(operation, source) {
|
|
141
|
+
const summary = stringValue(operation, source, "summary");
|
|
142
|
+
if (summary.length > 280)
|
|
143
|
+
return invalid(operation, "next step summary must be at most 280 characters");
|
|
144
|
+
const assignee = optionalString(operation, source, "assignee");
|
|
145
|
+
const dueAt = optionalString(operation, source, "dueAt");
|
|
146
|
+
if (dueAt !== undefined && !isJsonDateTime(dueAt))
|
|
147
|
+
return invalid(operation, "dueAt must be an ISO date-time");
|
|
148
|
+
return { summary, ...(assignee === undefined ? {} : { assignee }), ...(dueAt === undefined ? {} : { dueAt }) };
|
|
149
|
+
}
|
|
150
|
+
function overviewValue(operation) {
|
|
151
|
+
const overview = recordValue(operation, "overview");
|
|
152
|
+
const summary = stringValue(operation, overview, "summary");
|
|
153
|
+
if (summary.length > 280)
|
|
154
|
+
return invalid(operation, "overview summary must be at most 280 characters");
|
|
155
|
+
const rawNextStep = overview.nextStep;
|
|
156
|
+
if (rawNextStep === undefined)
|
|
157
|
+
return { summary };
|
|
158
|
+
if (typeof rawNextStep !== "object" || rawNextStep === null || Array.isArray(rawNextStep)) {
|
|
159
|
+
return invalid(operation, "nextStep must be an object");
|
|
160
|
+
}
|
|
161
|
+
return { summary, nextStep: nextStepValue(operation, rawNextStep) };
|
|
162
|
+
}
|
|
163
|
+
function updateOverviewValue(operation) {
|
|
164
|
+
const status = optionalString(operation, operation.payload, "status");
|
|
165
|
+
return {
|
|
166
|
+
kind: "update-overview",
|
|
167
|
+
overview: overviewValue(operation),
|
|
168
|
+
...(status === undefined ? {} : { status: statusFrom(status, operation) }),
|
|
169
|
+
};
|
|
170
|
+
}
|
|
48
171
|
function titleValue(operation) {
|
|
49
172
|
const title = stringValue(operation, operation.payload, "title");
|
|
50
173
|
if (title.length > 280)
|
|
@@ -64,9 +187,15 @@ export function parsePayload(operation) {
|
|
|
64
187
|
return { kind: operation.type, title: titleValue(operation) };
|
|
65
188
|
case "change-status":
|
|
66
189
|
return { kind: operation.type, status: statusValue(operation) };
|
|
190
|
+
case "update-overview":
|
|
191
|
+
return updateOverviewValue(operation);
|
|
67
192
|
case "link-context":
|
|
68
193
|
case "unlink-context":
|
|
69
194
|
return { kind: operation.type, context: contextValue(operation) };
|
|
195
|
+
case "attach-files":
|
|
196
|
+
return { kind: operation.type, files: attachmentsValue(operation) };
|
|
197
|
+
case "detach-files":
|
|
198
|
+
return { kind: operation.type, files: attachmentIdentitiesValue(operation) };
|
|
70
199
|
case "record-decision":
|
|
71
200
|
return { kind: operation.type, decision: decisionValue(operation) };
|
|
72
201
|
case "redirect":
|