@onlyne/lib 3.1.0 → 3.2.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 (121) hide show
  1. package/README.md +4 -3
  2. package/dist/awaited.d.ts +43 -0
  3. package/dist/awaited.d.ts.map +1 -0
  4. package/dist/awaited.js +82 -0
  5. package/dist/awaited.js.map +1 -0
  6. package/dist/client.d.ts +140 -0
  7. package/dist/client.d.ts.map +1 -0
  8. package/dist/client.js +1772 -0
  9. package/dist/client.js.map +1 -0
  10. package/dist/core.d.ts +36 -0
  11. package/dist/core.d.ts.map +1 -0
  12. package/dist/core.js +122 -0
  13. package/dist/core.js.map +1 -0
  14. package/dist/delivery.d.ts +120 -0
  15. package/dist/delivery.d.ts.map +1 -0
  16. package/dist/delivery.js +117 -0
  17. package/dist/delivery.js.map +1 -0
  18. package/dist/discovery.d.ts +35 -0
  19. package/dist/discovery.d.ts.map +1 -0
  20. package/dist/discovery.js +306 -0
  21. package/dist/discovery.js.map +1 -0
  22. package/dist/domains.d.ts +29 -0
  23. package/dist/domains.d.ts.map +1 -0
  24. package/dist/domains.js +267 -0
  25. package/dist/domains.js.map +1 -0
  26. package/dist/history.d.ts +13 -0
  27. package/dist/history.d.ts.map +1 -0
  28. package/dist/history.js +143 -0
  29. package/dist/history.js.map +1 -0
  30. package/dist/http.d.ts +20 -0
  31. package/dist/http.d.ts.map +1 -0
  32. package/dist/http.js +88 -0
  33. package/dist/http.js.map +1 -0
  34. package/{src/index.ts → dist/index.d.ts} +2 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +15 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/keys.d.ts +97 -0
  39. package/dist/keys.d.ts.map +1 -0
  40. package/dist/keys.js +679 -0
  41. package/dist/keys.js.map +1 -0
  42. package/dist/memory.d.ts +9 -0
  43. package/dist/memory.d.ts.map +1 -0
  44. package/dist/memory.js +35 -0
  45. package/dist/memory.js.map +1 -0
  46. package/dist/messages.d.ts +64 -0
  47. package/dist/messages.d.ts.map +1 -0
  48. package/dist/messages.js +480 -0
  49. package/dist/messages.js.map +1 -0
  50. package/dist/node.d.ts +26 -0
  51. package/dist/node.d.ts.map +1 -0
  52. package/dist/node.js +59 -0
  53. package/dist/node.js.map +1 -0
  54. package/dist/resolve.d.ts +18 -0
  55. package/dist/resolve.d.ts.map +1 -0
  56. package/dist/resolve.js +37 -0
  57. package/dist/resolve.js.map +1 -0
  58. package/dist/resources.d.ts +25 -0
  59. package/dist/resources.d.ts.map +1 -0
  60. package/dist/resources.js +782 -0
  61. package/dist/resources.js.map +1 -0
  62. package/dist/routes/domains.d.ts +4 -0
  63. package/dist/routes/domains.d.ts.map +1 -0
  64. package/dist/routes/domains.js +42 -0
  65. package/dist/routes/domains.js.map +1 -0
  66. package/dist/routes/grants.d.ts +8 -0
  67. package/dist/routes/grants.d.ts.map +1 -0
  68. package/dist/routes/grants.js +32 -0
  69. package/dist/routes/grants.js.map +1 -0
  70. package/dist/routes/public.d.ts +4 -0
  71. package/dist/routes/public.d.ts.map +1 -0
  72. package/dist/routes/public.js +62 -0
  73. package/dist/routes/public.js.map +1 -0
  74. package/dist/routes/resources.d.ts +8 -0
  75. package/dist/routes/resources.d.ts.map +1 -0
  76. package/dist/routes/resources.js +87 -0
  77. package/dist/routes/resources.js.map +1 -0
  78. package/dist/routes/shared.d.ts +77 -0
  79. package/dist/routes/shared.d.ts.map +1 -0
  80. package/dist/routes/shared.js +349 -0
  81. package/dist/routes/shared.js.map +1 -0
  82. package/dist/routes/threads.d.ts +8 -0
  83. package/dist/routes/threads.d.ts.map +1 -0
  84. package/dist/routes/threads.js +113 -0
  85. package/dist/routes/threads.js.map +1 -0
  86. package/dist/routes/trust.d.ts +4 -0
  87. package/dist/routes/trust.d.ts.map +1 -0
  88. package/dist/routes/trust.js +36 -0
  89. package/dist/routes/trust.js.map +1 -0
  90. package/dist/stream.d.ts +20 -0
  91. package/dist/stream.d.ts.map +1 -0
  92. package/dist/stream.js +141 -0
  93. package/dist/stream.js.map +1 -0
  94. package/dist/threads.d.ts +79 -0
  95. package/dist/threads.d.ts.map +1 -0
  96. package/dist/threads.js +480 -0
  97. package/dist/threads.js.map +1 -0
  98. package/dist/transport.d.ts +45 -0
  99. package/dist/transport.d.ts.map +1 -0
  100. package/dist/transport.js +175 -0
  101. package/dist/transport.js.map +1 -0
  102. package/dist/types.d.ts +809 -0
  103. package/dist/types.d.ts.map +1 -0
  104. package/dist/types.js +9 -0
  105. package/dist/types.js.map +1 -0
  106. package/package.json +16 -8
  107. package/src/client.ts +0 -1745
  108. package/src/core.ts +0 -114
  109. package/src/discovery.ts +0 -275
  110. package/src/domains.ts +0 -213
  111. package/src/history.ts +0 -139
  112. package/src/http.ts +0 -852
  113. package/src/keys.ts +0 -642
  114. package/src/memory.ts +0 -34
  115. package/src/messages.ts +0 -409
  116. package/src/node.ts +0 -63
  117. package/src/resolve.ts +0 -39
  118. package/src/resources.ts +0 -745
  119. package/src/threads.ts +0 -409
  120. package/src/transport.ts +0 -211
  121. package/src/types.ts +0 -428
package/src/history.ts DELETED
@@ -1,139 +0,0 @@
1
- import type { AttentionSettlement, Auth, Conversation, Entry, HistoryMessage, HistoryQuery, LocalAttention, MessageRef, Outbound, Page, ThreadRef, Transaction } from './types.ts';
2
- import { fail, key, page, same, type Context } from './core.ts';
3
-
4
- const identity = (ref: MessageRef): string => key(ref.sender, ref.id);
5
- const threadIdentity = (ref: ThreadRef): string => key(ref.owner, ref.id);
6
-
7
- /** A read-only projection of the records this node already holds. It performs no remote reads. */
8
- export class HistoryService {
9
- readonly #ctx: Context;
10
-
11
- constructor(ctx: Context) {
12
- this.#ctx = ctx;
13
- }
14
-
15
- async list(auth: Auth, query: HistoryQuery = {}): Promise<Page<Conversation>> {
16
- this.authorize(auth);
17
- return this.#ctx.storage.transaction(async tx => {
18
- const conversations = await this.collect(tx);
19
- const selected = conversations.filter(conversation =>
20
- (query.thread === undefined || conversation.thread_refs.some(ref => same(ref, query.thread)))
21
- && (query.message === undefined || conversation.messages.some(row => same(row.message_ref, query.message)) || same(conversation.id, query.message)));
22
- selected.sort((left, right) => identity(left.id).localeCompare(identity(right.id)));
23
- return page(selected, query, { kind: 'history', actor: auth.actor, thread: query.thread, message: query.message }, row => identity(row.id));
24
- });
25
- }
26
-
27
- async conversation(auth: Auth, message: MessageRef): Promise<Conversation> {
28
- this.authorize(auth);
29
- return this.#ctx.storage.transaction(async tx => {
30
- const found = (await this.collect(tx)).find(row => same(row.id, message) || row.messages.some(item => same(item.message_ref, message)));
31
- if (found === undefined) fail('not_found', 'This node holds no conversation for that message.');
32
- return found;
33
- });
34
- }
35
-
36
- async message(auth: Auth, message: MessageRef): Promise<HistoryMessage> {
37
- const conversation = await this.conversation(auth, message);
38
- const found = conversation.messages.find(row => same(row.message_ref, message));
39
- if (found === undefined) fail('not_found', 'This node holds the reply reference, but no body for that message.');
40
- return found;
41
- }
42
-
43
- private authorize(auth: Auth): void {
44
- if (auth.actor !== this.#ctx.node) fail('forbidden', 'Conversation history belongs to this node.');
45
- }
46
-
47
- private async collect(tx: Transaction): Promise<Conversation[]> {
48
- const messages = new Map<string, HistoryMessage>();
49
- const addEntry = (entry: Entry, injected?: boolean, settlement?: AttentionSettlement): void => {
50
- const message_ref = { sender: entry.message.sender, id: entry.message.id };
51
- const id = identity(message_ref);
52
- const previous = messages.get(id);
53
- const closed = previous?.settlement ?? settlement;
54
- messages.set(id, {
55
- message_ref, message: entry.message, direction: entry.message.sender === this.#ctx.node ? 'out' : 'in',
56
- thread_ref: entry.thread_ref, seq: entry.seq, at: entry.at, delivery: previous?.delivery ?? 'received',
57
- ...(previous?.guarantee === undefined ? {} : { guarantee: previous.guarantee }),
58
- // A settlement closes the row without asserting a read, so it carries no consumption.
59
- ...(closed !== undefined ? { settlement: closed }
60
- : injected === undefined ? previous?.consumption === undefined ? {} : { consumption: previous.consumption }
61
- : { consumption: injected || previous?.consumption === 'consumed' ? 'consumed' : 'pending' }),
62
- });
63
- };
64
- for (const { value } of await tx.scan<Entry>('entry-ref/')) addEntry(value);
65
- for (const { value } of await tx.scan<LocalAttention>('inbox/')) {
66
- if (value.attention.entry !== undefined && value.attention.disposition !== 'expired') {
67
- addEntry(value.attention.entry, value.injected, value.settlement);
68
- }
69
- }
70
- const confirmed = new Set<string>();
71
- for (const { value } of await tx.scan<{ thread_ref: ThreadRef; seq: string; confirmed: boolean }>('consumed/')) {
72
- if (value.confirmed) confirmed.add(key(value.thread_ref.owner, value.thread_ref.id, value.seq));
73
- }
74
- for (const { value } of await tx.scan<Outbound>('outbound/')) {
75
- const message = value.request.message;
76
- const message_ref = { sender: message.sender, id: message.id };
77
- const previous = messages.get(identity(message_ref));
78
- messages.set(identity(message_ref), {
79
- message_ref, message, direction: 'out', at: value.created_at ?? previous?.at ?? null,
80
- delivery: value.state,
81
- ...(value.receipt === undefined ? {} : { thread_ref: value.receipt.thread_ref, seq: value.receipt.seq, guarantee: value.receipt.guarantee }),
82
- ...(value.error === undefined ? {} : { error: value.error }),
83
- ...(previous?.settlement === undefined ? {} : { settlement: previous.settlement }),
84
- });
85
- }
86
- for (const row of messages.values()) {
87
- if (row.direction === 'in' && row.thread_ref !== undefined && row.seq !== undefined
88
- && confirmed.has(key(row.thread_ref.owner, row.thread_ref.id, row.seq))) row.consumption = 'consumed';
89
- }
90
- const parents = new Map<string, string>();
91
- const refs = new Map<string, MessageRef>();
92
- const root = (id: string): string => {
93
- const parent = parents.get(id);
94
- if (parent === undefined || parent === id) return id;
95
- const found = root(parent);
96
- parents.set(id, found);
97
- return found;
98
- };
99
- for (const row of messages.values()) {
100
- const id = identity(row.message_ref);
101
- refs.set(id, row.message_ref);
102
- const original = row.message.meta?.in_reply_to;
103
- if (original === undefined) continue;
104
- const source = identity(original);
105
- refs.set(source, original);
106
- const left = root(id);
107
- const right = root(source);
108
- if (left !== right) parents.set(left, right);
109
- }
110
- const grouped = new Map<string, HistoryMessage[]>();
111
- for (const [id, message] of messages) {
112
- const group = root(id);
113
- const rows = grouped.get(group) ?? [];
114
- rows.push(message);
115
- grouped.set(group, rows);
116
- }
117
- return [...grouped].map(([id, rows]) => {
118
- // Parent-before-child ordering also works when one legacy outbound has no timestamp.
119
- const ordered: HistoryMessage[] = [];
120
- const seen = new Set<string>();
121
- const byId = new Map(rows.map(row => [identity(row.message_ref), row]));
122
- const visit = (row: HistoryMessage): void => {
123
- const key = identity(row.message_ref);
124
- if (seen.has(key)) return;
125
- seen.add(key);
126
- const source = row.message.meta?.in_reply_to;
127
- const parent = source === undefined ? undefined : byId.get(identity(source));
128
- if (parent !== undefined) visit(parent);
129
- ordered.push(row);
130
- };
131
- rows.sort((a, b) => (a.at ?? '').localeCompare(b.at ?? '') || identity(a.message_ref).localeCompare(identity(b.message_ref)));
132
- rows.forEach(visit);
133
- const threads = new Map<string, ThreadRef>();
134
- for (const row of ordered) if (row.thread_ref !== undefined) threads.set(threadIdentity(row.thread_ref), row.thread_ref);
135
- const subject = ordered[0]!.message.delivery_kind.replace(/\s+/g, ' ').trim();
136
- return { id: refs.get(id)!, title: subject || ordered[0]!.message.msg.split(/\r?\n/, 1)[0]!, thread_refs: [...threads.values()], messages: ordered, last_at: rows.filter(row => row.at !== null).at(-1)?.at ?? null };
137
- });
138
- }
139
- }