@alistigo/list-document 0.4.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.
Files changed (64) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +151 -0
  3. package/dist/__tests__/projection.test.d.ts +2 -0
  4. package/dist/__tests__/projection.test.d.ts.map +1 -0
  5. package/dist/__tests__/projection.test.js +318 -0
  6. package/dist/__tests__/projection.test.js.map +1 -0
  7. package/dist/application/__tests__/list-application-service.test.d.ts +2 -0
  8. package/dist/application/__tests__/list-application-service.test.d.ts.map +1 -0
  9. package/dist/application/__tests__/list-application-service.test.js +281 -0
  10. package/dist/application/__tests__/list-application-service.test.js.map +1 -0
  11. package/dist/application/list-application-service.d.ts +59 -0
  12. package/dist/application/list-application-service.d.ts.map +1 -0
  13. package/dist/application/list-application-service.js +138 -0
  14. package/dist/application/list-application-service.js.map +1 -0
  15. package/dist/index.d.ts +135 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +11 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/markdown/__tests__/list-markdown.test.d.ts +2 -0
  20. package/dist/markdown/__tests__/list-markdown.test.d.ts.map +1 -0
  21. package/dist/markdown/__tests__/list-markdown.test.js +133 -0
  22. package/dist/markdown/__tests__/list-markdown.test.js.map +1 -0
  23. package/dist/markdown/list-markdown.d.ts +13 -0
  24. package/dist/markdown/list-markdown.d.ts.map +1 -0
  25. package/dist/markdown/list-markdown.js +50 -0
  26. package/dist/markdown/list-markdown.js.map +1 -0
  27. package/dist/package.json +58 -0
  28. package/dist/projection.d.ts +32 -0
  29. package/dist/projection.d.ts.map +1 -0
  30. package/dist/projection.js +59 -0
  31. package/dist/projection.js.map +1 -0
  32. package/dist/projector/list-projector.d.ts +27 -0
  33. package/dist/projector/list-projector.d.ts.map +1 -0
  34. package/dist/projector/list-projector.js +36 -0
  35. package/dist/projector/list-projector.js.map +1 -0
  36. package/dist/result.d.ts +10 -0
  37. package/dist/result.d.ts.map +1 -0
  38. package/dist/result.js +7 -0
  39. package/dist/result.js.map +1 -0
  40. package/dist/schemas/alistigo-document.json +117 -0
  41. package/dist/schemas/document.json +83 -0
  42. package/dist/serializer/__tests__/list-document-serializer.test.d.ts +2 -0
  43. package/dist/serializer/__tests__/list-document-serializer.test.d.ts.map +1 -0
  44. package/dist/serializer/__tests__/list-document-serializer.test.js +282 -0
  45. package/dist/serializer/__tests__/list-document-serializer.test.js.map +1 -0
  46. package/dist/serializer/list-document-serializer.d.ts +11 -0
  47. package/dist/serializer/list-document-serializer.d.ts.map +1 -0
  48. package/dist/serializer/list-document-serializer.js +160 -0
  49. package/dist/serializer/list-document-serializer.js.map +1 -0
  50. package/dist/types/list.d.ts +53 -0
  51. package/dist/types/list.d.ts.map +1 -0
  52. package/dist/types/list.js +2 -0
  53. package/dist/types/list.js.map +1 -0
  54. package/dist/types.d.ts +3 -0
  55. package/dist/types.d.ts.map +1 -0
  56. package/dist/types.js +3 -0
  57. package/dist/types.js.map +1 -0
  58. package/dist/validate.d.ts +12 -0
  59. package/dist/validate.d.ts.map +1 -0
  60. package/dist/validate.js +39 -0
  61. package/dist/validate.js.map +1 -0
  62. package/package.json +57 -0
  63. package/src/schemas/alistigo-document.json +117 -0
  64. package/src/schemas/document.json +83 -0
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ export { buildListDocumentFromMarkdown, isValidListMarkdown, parseListMarkdown, } from "./markdown/list-markdown.js";
2
+ export { buildAttributionMap, buildProjection, } from "./projection.js";
3
+ export { ListDocumentSerializer } from "./serializer/list-document-serializer.js";
4
+ export * from "./types.js";
5
+ export { validateDocument } from "./validate.js";
6
+ import documentSchemaJson from "./schemas/document.json" with { type: "json" };
7
+ export const documentSchema = documentSchemaJson;
8
+ export { ListApplicationService, } from "./application/list-application-service.js";
9
+ export { ListProjector, projectList, } from "./projector/list-projector.js";
10
+ export { err, ok } from "./result.js";
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,6BAA6B,EAC7B,mBAAmB,EAEnB,iBAAiB,GAClB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAIL,mBAAmB,EACnB,eAAe,GAChB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,sBAAsB,EAAE,MAAM,0CAA0C,CAAC;AAClF,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,kBAAkB,MAAM,yBAAyB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAC/E,MAAM,CAAC,MAAM,cAAc,GAAG,kBAAkB,CAAC;AAEjD,OAAO,EAEL,sBAAsB,GACvB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAEL,aAAa,EACb,WAAW,GACZ,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,GAAG,EAAE,EAAE,EAAe,MAAM,aAAa,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=list-markdown.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-markdown.test.d.ts","sourceRoot":"","sources":["../../../src/markdown/__tests__/list-markdown.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,133 @@
1
+ import { describe, expect, it } from "bun:test";
2
+ import { generateActorId, generateListId } from "@alistigo/list-domain";
3
+ import { buildListDocumentFromMarkdown, isValidListMarkdown, parseListMarkdown, } from "../list-markdown.js";
4
+ const actorId = generateActorId();
5
+ describe("parseListMarkdown", () => {
6
+ it("parses a title-and-items block (dash markers)", () => {
7
+ const md = "Groceries:\n- Buy bread\n- Buy milk\n- Buy eggs";
8
+ const { title, items } = parseListMarkdown(md);
9
+ expect(title).toBe("Groceries");
10
+ expect(items).toEqual(["Buy bread", "Buy milk", "Buy eggs"]);
11
+ });
12
+ it("parses items with asterisk markers", () => {
13
+ const md = "Shopping:\n* Apples\n* Bananas";
14
+ const { title, items } = parseListMarkdown(md);
15
+ expect(title).toBe("Shopping");
16
+ expect(items).toEqual(["Apples", "Bananas"]);
17
+ });
18
+ it("parses an ordered list", () => {
19
+ const md = "Steps:\n1. First step\n2. Second step\n3. Third step";
20
+ const { title, items } = parseListMarkdown(md);
21
+ expect(title).toBe("Steps");
22
+ expect(items).toEqual(["First step", "Second step", "Third step"]);
23
+ });
24
+ it("parses items with no title line", () => {
25
+ const md = "- Item one\n- Item two";
26
+ const { title, items } = parseListMarkdown(md);
27
+ expect(title).toBeUndefined();
28
+ expect(items).toEqual(["Item one", "Item two"]);
29
+ });
30
+ it("parses a title-only block (empty list)", () => {
31
+ const md = "Empty list:";
32
+ const { title, items } = parseListMarkdown(md);
33
+ expect(title).toBe("Empty list");
34
+ expect(items).toHaveLength(0);
35
+ });
36
+ it("trims leading/trailing whitespace from items", () => {
37
+ const md = "List:\n- Padded item \n- Another ";
38
+ const { items } = parseListMarkdown(md);
39
+ expect(items).toEqual(["Padded item", "Another"]);
40
+ });
41
+ it("skips blank lines and non-list prose lines", () => {
42
+ const md = "My list:\n\nSome prose.\n- Real item\n\n- Another real item";
43
+ const { title, items } = parseListMarkdown(md);
44
+ expect(title).toBe("My list");
45
+ expect(items).toEqual(["Real item", "Another real item"]);
46
+ });
47
+ it("allows duplicate items", () => {
48
+ const md = "Duplicates allowed:\n- Buy bread\n- Buy bread\n- Buy milk";
49
+ const { items } = parseListMarkdown(md);
50
+ expect(items).toEqual(["Buy bread", "Buy bread", "Buy milk"]);
51
+ });
52
+ it("returns empty title and no items for blank markdown", () => {
53
+ const { title, items } = parseListMarkdown(" ");
54
+ expect(title).toBeUndefined();
55
+ expect(items).toHaveLength(0);
56
+ });
57
+ });
58
+ describe("isValidListMarkdown", () => {
59
+ it("returns true for markdown with a title", () => {
60
+ expect(isValidListMarkdown("My list:")).toBe(true);
61
+ });
62
+ it("returns true for markdown with items but no title", () => {
63
+ expect(isValidListMarkdown("- Item one\n- Item two")).toBe(true);
64
+ });
65
+ it("returns true for markdown with both title and items", () => {
66
+ expect(isValidListMarkdown("Groceries:\n- Milk")).toBe(true);
67
+ });
68
+ it("returns false for blank markdown", () => {
69
+ expect(isValidListMarkdown("")).toBe(false);
70
+ expect(isValidListMarkdown(" \n ")).toBe(false);
71
+ });
72
+ it("returns false for plain prose with no list markers or title colon", () => {
73
+ expect(isValidListMarkdown("Just some plain text without list markers")).toBe(false);
74
+ });
75
+ });
76
+ describe("buildListDocumentFromMarkdown", () => {
77
+ // fallow-ignore-next-line complexity
78
+ it("builds a document with title and items from a typical grocery list", () => {
79
+ const md = "Groceries:\n- Buy bread\n- Buy milk\n- Buy eggs";
80
+ const doc = buildListDocumentFromMarkdown(md, actorId);
81
+ expect(doc["@type"]).toBe("ItemList");
82
+ expect(doc.name).toBe("Groceries");
83
+ expect(doc.itemListElement).toHaveLength(3);
84
+ expect(doc.itemListElement[0]?.name).toBe("Buy bread");
85
+ expect(doc.itemListElement[1]?.name).toBe("Buy milk");
86
+ expect(doc.itemListElement[2]?.name).toBe("Buy eggs");
87
+ expect(doc.itemListElement[0]?.position).toBe(1);
88
+ expect(doc.itemListElement[2]?.position).toBe(3);
89
+ });
90
+ it("builds a document without a name when title is absent", () => {
91
+ const md = "- Only items\n- No title";
92
+ const doc = buildListDocumentFromMarkdown(md, actorId);
93
+ expect(doc.name).toBeUndefined();
94
+ expect(doc.itemListElement).toHaveLength(2);
95
+ expect(doc.itemListElement[0]?.name).toBe("Only items");
96
+ });
97
+ it("builds an empty-element document when markdown has only a title", () => {
98
+ const md = "Empty list:";
99
+ const doc = buildListDocumentFromMarkdown(md, actorId);
100
+ expect(doc.name).toBe("Empty list");
101
+ expect(doc.itemListElement).toHaveLength(0);
102
+ });
103
+ it("preserves duplicates", () => {
104
+ const md = "Duplicates allowed:\n- Buy bread\n- Buy bread\n- Buy milk";
105
+ const doc = buildListDocumentFromMarkdown(md, actorId);
106
+ expect(doc.itemListElement).toHaveLength(3);
107
+ expect(doc.itemListElement[0]?.name).toBe("Buy bread");
108
+ expect(doc.itemListElement[1]?.name).toBe("Buy bread");
109
+ });
110
+ it("handles an ordered list", () => {
111
+ const md = "Steps:\n1. First\n2. Second\n3. Third";
112
+ const doc = buildListDocumentFromMarkdown(md, actorId);
113
+ expect(doc.name).toBe("Steps");
114
+ expect(doc.itemListElement.map((i) => i.name)).toEqual(["First", "Second", "Third"]);
115
+ });
116
+ it("uses the provided listId", () => {
117
+ const listId = generateListId();
118
+ const doc = buildListDocumentFromMarkdown("List:\n- Item", actorId, listId);
119
+ expect(doc["@id"]).toBe(listId.toString());
120
+ });
121
+ it("generates a listId starting with lst_ when none is given", () => {
122
+ const doc = buildListDocumentFromMarkdown("List:\n- Item", actorId);
123
+ expect(doc["@id"]).toMatch(/^lst_/);
124
+ });
125
+ it("event log contains ListCreated plus one ListElementAdded per item", () => {
126
+ const md = "List:\n- A\n- B\n- C";
127
+ const doc = buildListDocumentFromMarkdown(md, actorId);
128
+ expect(doc["alistigo:eventLog"]).toHaveLength(4); // 1 created + 3 added
129
+ expect(doc["alistigo:eventLog"][0]?.["alistigo:eventType"]).toBe("ListCreated");
130
+ expect(doc["alistigo:eventLog"][1]?.["alistigo:eventType"]).toBe("ListElementAdded");
131
+ });
132
+ });
133
+ //# sourceMappingURL=list-markdown.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-markdown.test.js","sourceRoot":"","sources":["../../../src/markdown/__tests__/list-markdown.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { type ActorId, type ListId } from "@alistigo/list-domain";
2
+ import type { AlistigoDocument } from "../types.js";
3
+ export interface MarkdownParseResult {
4
+ title: string | undefined;
5
+ items: string[];
6
+ }
7
+ /** Parses markdown into a title and ordered list of item strings. */
8
+ export declare function parseListMarkdown(markdown: string): MarkdownParseResult;
9
+ /** Returns true if the markdown contains a recognisable title or at least one item. */
10
+ export declare function isValidListMarkdown(markdown: string): boolean;
11
+ /** Converts markdown to an AlistigoDocument. Caller supplies actorId; listId is generated when omitted. */
12
+ export declare function buildListDocumentFromMarkdown(markdown: string, actorId: ActorId, listId?: ListId): AlistigoDocument;
13
+ //# sourceMappingURL=list-markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-markdown.d.ts","sourceRoot":"","sources":["../../src/markdown/list-markdown.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EAIZ,KAAK,MAAM,EACZ,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AA+BD,qEAAqE;AACrE,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,mBAAmB,CAEvE;AAED,uFAAuF;AACvF,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAG7D;AAED,2GAA2G;AAC3G,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,OAAO,EAChB,MAAM,CAAC,EAAE,MAAM,GACd,gBAAgB,CAgBlB"}
@@ -0,0 +1,50 @@
1
+ import { createListElementContent, generateListId, List, } from "@alistigo/list-domain";
2
+ import { ListDocumentSerializer } from "../serializer/list-document-serializer.js";
3
+ // fallow-ignore-next-line complexity
4
+ function parseLines(lines) {
5
+ let title;
6
+ const items = [];
7
+ for (let i = 0; i < lines.length; i++) {
8
+ const line = lines[i] ?? "";
9
+ const trimmed = line.trim();
10
+ if (i === 0 && trimmed.endsWith(":")) {
11
+ title = trimmed.slice(0, -1).trim();
12
+ continue;
13
+ }
14
+ const unordered = trimmed.match(/^[-*]\s+(.+)/);
15
+ if (unordered !== null) {
16
+ items.push(unordered[1]?.trim() ?? "");
17
+ continue;
18
+ }
19
+ const ordered = trimmed.match(/^\d+\.\s+(.+)/);
20
+ if (ordered !== null) {
21
+ items.push(ordered[1]?.trim() ?? "");
22
+ }
23
+ }
24
+ return { title, items };
25
+ }
26
+ /** Parses markdown into a title and ordered list of item strings. */
27
+ export function parseListMarkdown(markdown) {
28
+ return parseLines(markdown.split("\n"));
29
+ }
30
+ /** Returns true if the markdown contains a recognisable title or at least one item. */
31
+ export function isValidListMarkdown(markdown) {
32
+ const { title, items } = parseListMarkdown(markdown.trim());
33
+ return title !== undefined || items.length > 0;
34
+ }
35
+ /** Converts markdown to an AlistigoDocument. Caller supplies actorId; listId is generated when omitted. */
36
+ export function buildListDocumentFromMarkdown(markdown, actorId, listId) {
37
+ const { title, items } = parseListMarkdown(markdown);
38
+ const resolvedListId = listId ?? generateListId();
39
+ const { list } = List.create({
40
+ actorId,
41
+ listId: resolvedListId,
42
+ ...(title !== undefined ? { title } : {}),
43
+ });
44
+ for (const item of items) {
45
+ const content = createListElementContent(item);
46
+ list.addListElement({ actorId, listId: resolvedListId, content });
47
+ }
48
+ return ListDocumentSerializer.serialize(list, undefined);
49
+ }
50
+ //# sourceMappingURL=list-markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-markdown.js","sourceRoot":"","sources":["../../src/markdown/list-markdown.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,wBAAwB,EACxB,cAAc,EACd,IAAI,GAEL,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AAQnF,qCAAqC;AACrC,SAAS,UAAU,CAAC,KAAe;IACjC,IAAI,KAAyB,CAAC;IAC9B,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAE5B,IAAI,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACrC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACpC,SAAS;QACX,CAAC;QAED,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAChD,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YACvC,SAAS;QACX,CAAC;QAED,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QAC/C,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAC1B,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,OAAO,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,mBAAmB,CAAC,QAAgB;IAClD,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,iBAAiB,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5D,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;AACjD,CAAC;AAED,2GAA2G;AAC3G,MAAM,UAAU,6BAA6B,CAC3C,QAAgB,EAChB,OAAgB,EAChB,MAAe;IAEf,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACrD,MAAM,cAAc,GAAG,MAAM,IAAI,cAAc,EAAE,CAAC;IAElD,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,OAAO;QACP,MAAM,EAAE,cAAc;QACtB,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1C,CAAC,CAAC;IAEH,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,wBAAwB,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAI,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,OAAO,sBAAsB,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@alistigo/list-document",
3
+ "version": "0.4.0",
4
+ "license": "MIT",
5
+ "author": {
6
+ "name": "Mikael Labrut",
7
+ "email": "contact@alistigo.com"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/alistigo/holos.git",
12
+ "directory": "packages/list-document"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/alistigo/holos/issues"
16
+ },
17
+ "homepage": "https://github.com/alistigo/holos/tree/main/packages/list-document#readme",
18
+ "alistigo": {
19
+ "type": "document"
20
+ },
21
+ "keywords": [
22
+ "alistigo",
23
+ "list",
24
+ "document",
25
+ "json-schema",
26
+ "json-ld",
27
+ "typescript"
28
+ ],
29
+ "private": false,
30
+ "type": "module",
31
+ "description": "Specification, JSON schemas, and TypeScript types for the Alistigo list document format.",
32
+ "exports": {
33
+ ".": {
34
+ "import": "./dist/index.js",
35
+ "types": "./dist/index.d.ts"
36
+ },
37
+ "./schemas/document.json": "./src/schemas/document.json"
38
+ },
39
+ "main": "./dist/index.js",
40
+ "types": "./dist/index.d.ts",
41
+ "files": [
42
+ "dist",
43
+ "src/schemas",
44
+ "docs"
45
+ ],
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "dependencies": {
50
+ "@alistigo/core-document": "workspace:*",
51
+ "@alistigo/list-domain": "workspace:*",
52
+ "@alistigo/logger": "workspace:*",
53
+ "ajv": "^8.17.0",
54
+ "ajv-formats": "^3.0.1",
55
+ "schema-dts": "^2.0.0"
56
+ },
57
+ "module": "./index.js"
58
+ }
@@ -0,0 +1,32 @@
1
+ import type { AlistigoDocument } from "./types.js";
2
+ export interface AlistigoItemAttribution {
3
+ actorId: string;
4
+ pseudo: string;
5
+ avatar: string;
6
+ addedAt: string;
7
+ }
8
+ export interface AlistigoProjectionItem {
9
+ "@type": "ListItem";
10
+ position: number;
11
+ item: {
12
+ "@type": "Thing";
13
+ "@id": string;
14
+ name: string;
15
+ };
16
+ "alistigo:attribution"?: AlistigoItemAttribution;
17
+ }
18
+ export interface AlistigoProjection {
19
+ "@type": "ItemList";
20
+ numberOfItems: number;
21
+ itemListElement: AlistigoProjectionItem[];
22
+ }
23
+ export declare function buildAttributionMap(doc: AlistigoDocument): Map<string, AlistigoItemAttribution>;
24
+ /**
25
+ * Derives a view-model projection from an `AlistigoDocument`.
26
+ *
27
+ * Attribution (`"alistigo:attribution"`) is populated on each item only when
28
+ * the document contains **2 or more** agent records — a list with a single
29
+ * agent has no meaningful attribution context to display.
30
+ */
31
+ export declare function buildProjection(doc: AlistigoDocument): AlistigoProjection;
32
+ //# sourceMappingURL=projection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projection.d.ts","sourceRoot":"","sources":["../src/projection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAMnD,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,UAAU,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE;QACJ,OAAO,EAAE,OAAO,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,sBAAsB,CAAC,EAAE,uBAAuB,CAAC;CAClD;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,UAAU,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,sBAAsB,EAAE,CAAC;CAC3C;AAOD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,gBAAgB,GAAG,GAAG,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAsB/F;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,gBAAgB,GAAG,kBAAkB,CA+BzE"}
@@ -0,0 +1,59 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Projection builder
3
+ // ---------------------------------------------------------------------------
4
+ // fallow-ignore-next-line complexity
5
+ export function buildAttributionMap(doc) {
6
+ const agentsById = new Map((doc["alistigo:agents"] ?? []).map((a) => [a["@id"], a]));
7
+ const result = new Map();
8
+ for (const event of doc["alistigo:eventLog"]) {
9
+ if (event["alistigo:eventType"] === "ListElementAdded") {
10
+ const elementId = event["listItem"]["@id"];
11
+ if (!result.has(elementId)) {
12
+ const agent = agentsById.get(event.agent["@id"]);
13
+ if (agent) {
14
+ result.set(elementId, {
15
+ actorId: agent["@id"],
16
+ pseudo: agent.name,
17
+ avatar: typeof agent.image === "string" ? agent.image : "",
18
+ addedAt: event.startTime,
19
+ });
20
+ }
21
+ }
22
+ }
23
+ }
24
+ return result;
25
+ }
26
+ /**
27
+ * Derives a view-model projection from an `AlistigoDocument`.
28
+ *
29
+ * Attribution (`"alistigo:attribution"`) is populated on each item only when
30
+ * the document contains **2 or more** agent records — a list with a single
31
+ * agent has no meaningful attribution context to display.
32
+ */
33
+ export function buildProjection(doc) {
34
+ const agents = doc["alistigo:agents"] ?? [];
35
+ const attributionMap = agents.length >= 2 ? buildAttributionMap(doc) : new Map();
36
+ const itemListElement = doc.itemListElement.map((item, index) => {
37
+ const elementId = item["alistigo:listElementId"];
38
+ const attribution = attributionMap.get(elementId);
39
+ const projectionItem = {
40
+ "@type": "ListItem",
41
+ position: index + 1,
42
+ item: {
43
+ "@type": "Thing",
44
+ "@id": elementId,
45
+ name: item.name,
46
+ },
47
+ };
48
+ if (attribution !== undefined) {
49
+ projectionItem["alistigo:attribution"] = attribution;
50
+ }
51
+ return projectionItem;
52
+ });
53
+ return {
54
+ "@type": "ItemList",
55
+ numberOfItems: itemListElement.length,
56
+ itemListElement,
57
+ };
58
+ }
59
+ //# sourceMappingURL=projection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projection.js","sourceRoot":"","sources":["../src/projection.ts"],"names":[],"mappings":"AA8BA,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E,qCAAqC;AACrC,MAAM,UAAU,mBAAmB,CAAC,GAAqB;IACvD,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACrF,MAAM,MAAM,GAAG,IAAI,GAAG,EAAmC,CAAC;IAE1D,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC7C,IAAI,KAAK,CAAC,oBAAoB,CAAC,KAAK,kBAAkB,EAAE,CAAC;YACvD,MAAM,SAAS,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC;YAC3C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC3B,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;gBACjD,IAAI,KAAK,EAAE,CAAC;oBACV,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE;wBACpB,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC;wBACrB,MAAM,EAAE,KAAK,CAAC,IAAI;wBAClB,MAAM,EAAE,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;wBAC1D,OAAO,EAAE,KAAK,CAAC,SAAS;qBACzB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,GAAqB;IACnD,MAAM,MAAM,GAAG,GAAG,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC;IAC5C,MAAM,cAAc,GAClB,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,EAAmC,CAAC;IAE7F,MAAM,eAAe,GAA6B,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QACxF,MAAM,SAAS,GAAG,IAAI,CAAC,wBAAwB,CAAC,CAAC;QACjD,MAAM,WAAW,GAAG,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAElD,MAAM,cAAc,GAA2B;YAC7C,OAAO,EAAE,UAAU;YACnB,QAAQ,EAAE,KAAK,GAAG,CAAC;YACnB,IAAI,EAAE;gBACJ,OAAO,EAAE,OAAO;gBAChB,KAAK,EAAE,SAAS;gBAChB,IAAI,EAAE,IAAI,CAAC,IAAI;aAChB;SACF,CAAC;QAEF,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,cAAc,CAAC,sBAAsB,CAAC,GAAG,WAAW,CAAC;QACvD,CAAC;QAED,OAAO,cAAc,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,OAAO,EAAE,UAAU;QACnB,aAAa,EAAE,eAAe,CAAC,MAAM;QACrC,eAAe;KAChB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { ListElementContent, ListElementId, ListEvent, ListId } from "@alistigo/list-domain";
2
+ /**
3
+ * Projection of a List's current visible state, derived from its event log.
4
+ * Contains only elements that are currently present (deletes are applied).
5
+ */
6
+ export interface ListProjection {
7
+ listId: ListId;
8
+ elements: ReadonlyArray<{
9
+ id: ListElementId;
10
+ content: ListElementContent;
11
+ }>;
12
+ }
13
+ /**
14
+ * Replays a list of events to produce the current visible projection.
15
+ * Deterministic: same events → same projection.
16
+ *
17
+ * - ListCreated → no element change
18
+ * - ListElementAdded → append element
19
+ * - ListElementDeleted → remove element by id
20
+ * - ListExported → ignored (audit-only)
21
+ */
22
+ export declare function projectList(listId: ListId, events: readonly ListEvent[]): ListProjection;
23
+ /** Namespace object kept for callers that use `ListProjector.project(...)`. */
24
+ export declare const ListProjector: {
25
+ project: typeof projectList;
26
+ };
27
+ //# sourceMappingURL=list-projector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-projector.d.ts","sourceRoot":"","sources":["../../src/projector/list-projector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAElG;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,aAAa,CAAC;QAAE,EAAE,EAAE,aAAa,CAAC;QAAC,OAAO,EAAE,kBAAkB,CAAA;KAAE,CAAC,CAAC;CAC7E;AAED;;;;;;;;GAQG;AAEH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,cAAc,CA2BxF;AAED,+EAA+E;AAC/E,eAAO,MAAM,aAAa;;CAA2B,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Replays a list of events to produce the current visible projection.
3
+ * Deterministic: same events → same projection.
4
+ *
5
+ * - ListCreated → no element change
6
+ * - ListElementAdded → append element
7
+ * - ListElementDeleted → remove element by id
8
+ * - ListExported → ignored (audit-only)
9
+ */
10
+ // fallow-ignore-next-line complexity
11
+ export function projectList(listId, events) {
12
+ const elements = [];
13
+ for (const event of events) {
14
+ switch (event.type) {
15
+ case "ListCreated":
16
+ break;
17
+ case "ListElementAdded":
18
+ elements.push({ id: event.listElementId, content: event.content });
19
+ break;
20
+ case "ListElementDeleted": {
21
+ const idStr = event.listElementId.toString();
22
+ const idx = elements.findIndex((el) => el.id.toString() === idStr);
23
+ if (idx !== -1) {
24
+ elements.splice(idx, 1);
25
+ }
26
+ break;
27
+ }
28
+ case "ListExported":
29
+ break;
30
+ }
31
+ }
32
+ return { listId, elements };
33
+ }
34
+ /** Namespace object kept for callers that use `ListProjector.project(...)`. */
35
+ export const ListProjector = { project: projectList };
36
+ //# sourceMappingURL=list-projector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-projector.js","sourceRoot":"","sources":["../../src/projector/list-projector.ts"],"names":[],"mappings":"AAWA;;;;;;;;GAQG;AACH,qCAAqC;AACrC,MAAM,UAAU,WAAW,CAAC,MAAc,EAAE,MAA4B;IACtE,MAAM,QAAQ,GAA8D,EAAE,CAAC;IAE/E,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,aAAa;gBAChB,MAAM;YAER,KAAK,kBAAkB;gBACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,aAAa,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;gBACnE,MAAM;YAER,KAAK,oBAAoB,CAAC,CAAC,CAAC;gBAC1B,MAAM,KAAK,GAAG,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC;gBAC7C,MAAM,GAAG,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,KAAK,CAAC,CAAC;gBACnE,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;oBACf,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;gBAC1B,CAAC;gBACD,MAAM;YACR,CAAC;YAED,KAAK,cAAc;gBACjB,MAAM;QACV,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AAC9B,CAAC;AAED,+EAA+E;AAC/E,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC"}
@@ -0,0 +1,10 @@
1
+ export type Result<T, E> = {
2
+ readonly ok: true;
3
+ readonly value: T;
4
+ } | {
5
+ readonly ok: false;
6
+ readonly error: E;
7
+ };
8
+ export declare function ok<T>(value: T): Result<T, never>;
9
+ export declare function err<E>(error: E): Result<never, E>;
10
+ //# sourceMappingURL=result.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../src/result.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,CAAC,CAAC,EAAE,CAAC,IACnB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GACxC;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;CAAE,CAAC;AAE9C,wBAAgB,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAEhD;AAED,wBAAgB,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAEjD"}
package/dist/result.js ADDED
@@ -0,0 +1,7 @@
1
+ export function ok(value) {
2
+ return { ok: true, value };
3
+ }
4
+ export function err(error) {
5
+ return { ok: false, error };
6
+ }
7
+ //# sourceMappingURL=result.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result.js","sourceRoot":"","sources":["../src/result.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,EAAE,CAAI,KAAQ;IAC5B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,GAAG,CAAI,KAAQ;IAC7B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,117 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.alistigo.com/v1/documents/alistigo-document.json",
4
+ "title": "Alistigo Document",
5
+ "description": "Common properties shared by all Alistigo artifact documents",
6
+ "type": "object",
7
+ "allOf": [
8
+ {
9
+ "$ref": "schema:Thing"
10
+ }
11
+ ],
12
+ "required": ["alistigo:eventLog", "@type", "@id"],
13
+ "properties": {
14
+ "alistigo:eventLog": {
15
+ "type": "array",
16
+ "items": {
17
+ "$ref": "#/$defs/Event"
18
+ }
19
+ },
20
+ "alistigo:agents": {
21
+ "type": "array",
22
+ "items": {
23
+ "$ref": "#/$defs/Agent"
24
+ }
25
+ },
26
+ "alistigo:plugins": {
27
+ "type": "array",
28
+ "items": {
29
+ "$ref": "#/$defs/Plugin"
30
+ }
31
+ }
32
+ },
33
+ "$defs": {
34
+ "Reference": {
35
+ "type": "object",
36
+ "required": ["@id"],
37
+ "properties": {
38
+ "@id": { "type": "string" }
39
+ }
40
+ },
41
+ "Event": {
42
+ "allOf": [
43
+ {
44
+ "$ref": "schema:Action"
45
+ },
46
+ {
47
+ "type": "object",
48
+ "required": ["@id", "alistigo:eventType", "agent", "startTime"],
49
+ "properties": {
50
+ "@id": {
51
+ "type": "string"
52
+ },
53
+ "alistigo:eventType": {
54
+ "type": "string"
55
+ },
56
+ "agent": {
57
+ "$ref": "#/$defs/Reference"
58
+ },
59
+ "startTime": {
60
+ "type": "string",
61
+ "format": "date-time"
62
+ }
63
+ }
64
+ }
65
+ ]
66
+ },
67
+ "Agent": {
68
+ "oneOf": [
69
+ {
70
+ "$ref": "#/$defs/Person"
71
+ },
72
+ {
73
+ "$ref": "#/$defs/SoftwareApplication"
74
+ }
75
+ ]
76
+ },
77
+ "Person": {
78
+ "type": "object",
79
+ "required": ["@type", "@id", "name"],
80
+ "properties": {
81
+ "@type": { "const": "Person" }
82
+ },
83
+ "allOf": [
84
+ {
85
+ "$ref": "schema:Person"
86
+ }
87
+ ]
88
+ },
89
+ "SoftwareApplication": {
90
+ "type": "object",
91
+ "required": ["@type", "@id", "name"],
92
+ "properties": {
93
+ "@type": { "const": "SoftwareApplication" }
94
+ },
95
+ "allOf": [
96
+ {
97
+ "$ref": "schema:SoftwareApplication"
98
+ }
99
+ ]
100
+ },
101
+ "Plugin": {
102
+ "type": "object",
103
+ "required": ["name"],
104
+ "properties": {
105
+ "name": {
106
+ "type": "string"
107
+ },
108
+ "version": {
109
+ "type": "string"
110
+ },
111
+ "config": {
112
+ "type": "object"
113
+ }
114
+ }
115
+ }
116
+ }
117
+ }