trellis 3.1.1 → 3.1.3
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/CHANGELOG.md +20 -0
- package/README.md +37 -0
- package/dist/cms/client.d.ts +21 -3
- package/dist/cms/client.d.ts.map +1 -1
- package/dist/cms/index.d.ts +1 -1
- package/dist/cms/index.d.ts.map +1 -1
- package/dist/cms/index.js +134 -55
- package/dist/cms/internal.d.ts +7 -1
- package/dist/cms/internal.d.ts.map +1 -1
- package/dist/cms/scaffold.d.ts +5 -0
- package/dist/cms/scaffold.d.ts.map +1 -1
- package/dist/cms/types.d.ts +12 -0
- package/dist/cms/types.d.ts.map +1 -1
- package/package.json +3 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 3.1.2
|
|
4
|
+
|
|
5
|
+
- Fixed `trellis/cms` collection reads for inferred collections whose normalized key differs from the stored entity type casing, such as `blogpost` reading `BlogPost` entities.
|
|
6
|
+
- Added graph-link awareness to CMS entries so reference links such as `post --author--> author` appear in `fields` and can be expanded.
|
|
7
|
+
- Added `status` fact fallback when `cms_status` is absent, preserving content created by agents or lower-level store tools.
|
|
8
|
+
- Added shared polling for CMS subscriptions so duplicate subscribers to the same collection or entry reuse one poll stream.
|
|
9
|
+
- Added `onError` and custom `equals` subscription options.
|
|
10
|
+
- Fixed CMS entity pagination to respect the opencode store route's 1000-entity page limit.
|
|
11
|
+
- Added CMS client/scaffold tests and included them in the default test script.
|
|
12
|
+
- Added `directory` support to CMS consumer scaffolds for multi-instance opencode routing.
|
|
13
|
+
|
|
14
|
+
## 3.1.1
|
|
15
|
+
|
|
16
|
+
- Published the first `trellis/cms` SDK package update after adding scaffold helpers.
|
|
17
|
+
|
|
18
|
+
## 3.1.0
|
|
19
|
+
|
|
20
|
+
- Added the `trellis/cms` subpath with `createCmsClient`, collection reads, entry reads, polling subscriptions, reference expansion, collection discovery, and consumer scaffold helpers for vanilla, React, Solid, and Vue.
|
package/README.md
CHANGED
|
@@ -50,6 +50,43 @@ See the [CLI guide](https://trellis.computer/docs/cli) for complete documentatio
|
|
|
50
50
|
|
|
51
51
|
---
|
|
52
52
|
|
|
53
|
+
## CMS Client SDK
|
|
54
|
+
|
|
55
|
+
Use `trellis/cms` from browser apps to read content from a Trellis-compatible HTTP server such as opencode at `http://localhost:4096`.
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
import { createCmsClient } from 'trellis/cms';
|
|
59
|
+
|
|
60
|
+
const cms = createCmsClient({
|
|
61
|
+
url: 'http://localhost:4096',
|
|
62
|
+
directory: '/path/to/project',
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const posts = await cms.collection('blogpost').list({
|
|
66
|
+
status: 'all',
|
|
67
|
+
expand: ['author'],
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const off = cms.collection('blogpost').subscribe(
|
|
71
|
+
(entries) => {
|
|
72
|
+
console.log(entries);
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
status: 'published',
|
|
76
|
+
onError: console.error,
|
|
77
|
+
},
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
off();
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
- **Collections**: `cms.collections()` returns explicit `TypeSchema` collections and inferred collections from existing entity types.
|
|
84
|
+
- **Normalized keys**: `cms.collection('blogpost')` matches stored entity types like `BlogPost`.
|
|
85
|
+
- **References**: `expand` resolves reference ids from facts and graph links into nested entries.
|
|
86
|
+
- **Scaffolds**: `scaffoldConsumer({ collection, framework, directory })` generates starter consumer code for vanilla, React, Solid, or Vue.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
53
90
|
## What is Trellis?
|
|
54
91
|
|
|
55
92
|
Trellis is an **event-sourced causal graph engine** that unifies version control, knowledge management, and semantic analysis. Every action is an immutable operation in a causal stream:
|
package/dist/cms/client.d.ts
CHANGED
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
*
|
|
24
24
|
* @module trellis/cms
|
|
25
25
|
*/
|
|
26
|
-
import type { CmsClientOptions, Collection, Entry, EntrySubscriber, GetOptions, ListOptions, ListSubscriber, Unsubscribe } from './types.js';
|
|
26
|
+
import type { CmsClientOptions, Collection, Entry, EntrySubscribeOptions, EntrySubscriber, GetOptions, ListOptions, ListSubscribeOptions, ListSubscriber, Unsubscribe } from './types.js';
|
|
27
|
+
import { type RawEntity } from './internal.js';
|
|
27
28
|
export declare class CmsClient {
|
|
28
29
|
private readonly url;
|
|
29
30
|
private readonly basePath;
|
|
@@ -31,15 +32,29 @@ export declare class CmsClient {
|
|
|
31
32
|
readonly pollIntervalMs: number;
|
|
32
33
|
private readonly fetchFn;
|
|
33
34
|
private readonly apiKey?;
|
|
35
|
+
private readonly subscriptions;
|
|
34
36
|
constructor(opts: CmsClientOptions);
|
|
35
37
|
collection<T extends Record<string, unknown> = Record<string, unknown>>(key: string): CollectionRef<T>;
|
|
36
38
|
entry<T extends Record<string, unknown> = Record<string, unknown>>(id: string): EntryRef<T>;
|
|
37
39
|
/** List all CMS collections (explicit + inferred). */
|
|
38
40
|
collections(): Promise<Collection[]>;
|
|
39
41
|
close(): void;
|
|
42
|
+
/**
|
|
43
|
+
* Shared polling subscription. Multiple subscribers to the same key share a
|
|
44
|
+
* single timer and one HTTP request per poll cycle. New subscribers receive
|
|
45
|
+
* the most recently fetched value immediately if one is cached.
|
|
46
|
+
*
|
|
47
|
+
* @internal
|
|
48
|
+
*/
|
|
49
|
+
_share<T>(key: string, fetcher: () => Promise<T>, callback: (value: T) => void, extras?: {
|
|
50
|
+
equals?: (prev: unknown, next: unknown) => boolean;
|
|
51
|
+
onError?: (err: unknown) => void;
|
|
52
|
+
}): Unsubscribe;
|
|
40
53
|
/** @internal */
|
|
41
54
|
_get<T>(path: string): Promise<T | undefined>;
|
|
42
55
|
/** @internal */
|
|
56
|
+
_entities(): Promise<RawEntity[]>;
|
|
57
|
+
/** @internal */
|
|
43
58
|
_entryById(id: string): Promise<Entry | null>;
|
|
44
59
|
}
|
|
45
60
|
export declare class CollectionRef<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
@@ -51,15 +66,18 @@ export declare class CollectionRef<T extends Record<string, unknown> = Record<st
|
|
|
51
66
|
/**
|
|
52
67
|
* Subscribe to changes. Currently implemented as polling; a future SSE-backed
|
|
53
68
|
* upgrade will replace the transport without changing this API.
|
|
69
|
+
*
|
|
70
|
+
* Multiple subscribers to the same collection + opts share one polling timer
|
|
71
|
+
* and one HTTP request per cycle.
|
|
54
72
|
*/
|
|
55
|
-
subscribe(callback: ListSubscriber<T>, opts?:
|
|
73
|
+
subscribe(callback: ListSubscriber<T>, opts?: ListSubscribeOptions): Unsubscribe;
|
|
56
74
|
}
|
|
57
75
|
export declare class EntryRef<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
58
76
|
private readonly client;
|
|
59
77
|
readonly id: string;
|
|
60
78
|
constructor(client: CmsClient, id: string);
|
|
61
79
|
get(opts?: GetOptions): Promise<Entry<T> | null>;
|
|
62
|
-
subscribe(callback: EntrySubscriber<T>, opts?:
|
|
80
|
+
subscribe(callback: EntrySubscriber<T>, opts?: EntrySubscribeOptions): Unsubscribe;
|
|
63
81
|
}
|
|
64
82
|
export declare function createCmsClient(opts: CmsClientOptions): CmsClient;
|
|
65
83
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/cms/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/cms/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,UAAU,EACV,KAAK,EACL,eAAe,EACf,UAAU,EACV,WAAW,EACX,cAAc,EACd,WAAW,EACZ,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/cms/client.ts"],"names":[],"mappings":"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"}
|
package/dist/cms/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @module trellis/cms
|
|
5
5
|
*/
|
|
6
6
|
export { CmsClient, CollectionRef, EntryRef, createCmsClient } from './client.js';
|
|
7
|
-
export type { CmsClientOptions, Collection, Entry, EntryStatus, EntrySubscriber, Framework, GetOptions, ListOptions, ListSubscriber, Unsubscribe, } from './types.js';
|
|
7
|
+
export type { CmsClientOptions, Collection, Entry, EntryStatus, EntrySubscribeOptions, EntrySubscriber, Framework, GetOptions, ListOptions, ListSubscribeOptions, ListSubscriber, SubscribeExtras, Unsubscribe, } from './types.js';
|
|
8
8
|
export { scaffoldConsumer, scaffoldFilename } from './scaffold.js';
|
|
9
9
|
export type { ScaffoldOptions } from './scaffold.js';
|
|
10
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/cms/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cms/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAElF,YAAY,EACV,gBAAgB,EAChB,UAAU,EACV,KAAK,EACL,WAAW,EACX,eAAe,EACf,SAAS,EACT,UAAU,EACV,WAAW,EACX,cAAc,EACd,WAAW,GACZ,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACnE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cms/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAElF,YAAY,EACV,gBAAgB,EAChB,UAAU,EACV,KAAK,EACL,WAAW,EACX,qBAAqB,EACrB,eAAe,EACf,SAAS,EACT,UAAU,EACV,WAAW,EACX,oBAAoB,EACpB,cAAc,EACd,eAAe,EACf,WAAW,GACZ,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACnE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/cms/index.js
CHANGED
|
@@ -29,18 +29,34 @@ function isSystemType(type) {
|
|
|
29
29
|
function typeKey(type) {
|
|
30
30
|
return type.trim().toLowerCase();
|
|
31
31
|
}
|
|
32
|
-
function entryFromFacts(entity, facts) {
|
|
32
|
+
function entryFromFacts(entity, facts, links) {
|
|
33
33
|
const fields = {};
|
|
34
34
|
let status = "draft";
|
|
35
|
+
let cmsStatusSeen = false;
|
|
35
36
|
for (const f of facts) {
|
|
36
37
|
if (f.a === "type")
|
|
37
38
|
continue;
|
|
38
39
|
if (f.a === "cms_status") {
|
|
39
40
|
status = f.v === "published" ? "published" : "draft";
|
|
41
|
+
cmsStatusSeen = true;
|
|
40
42
|
continue;
|
|
41
43
|
}
|
|
42
44
|
fields[f.a] = f.v;
|
|
43
45
|
}
|
|
46
|
+
if (!cmsStatusSeen) {
|
|
47
|
+
if (fields.status === "published")
|
|
48
|
+
status = "published";
|
|
49
|
+
else if (fields.status === "draft")
|
|
50
|
+
status = "draft";
|
|
51
|
+
}
|
|
52
|
+
if (links) {
|
|
53
|
+
for (const link of links) {
|
|
54
|
+
if (link.e1 !== entity.id)
|
|
55
|
+
continue;
|
|
56
|
+
if (!(link.a in fields))
|
|
57
|
+
fields[link.a] = link.e2;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
44
60
|
return { id: entity.id, type: entity.type, status, fields };
|
|
45
61
|
}
|
|
46
62
|
function groupFactsByEntity(facts) {
|
|
@@ -54,6 +70,17 @@ function groupFactsByEntity(facts) {
|
|
|
54
70
|
}
|
|
55
71
|
return map;
|
|
56
72
|
}
|
|
73
|
+
function groupLinksBySource(links) {
|
|
74
|
+
const map = new Map;
|
|
75
|
+
for (const l of links) {
|
|
76
|
+
const list = map.get(l.e1);
|
|
77
|
+
if (list)
|
|
78
|
+
list.push(l);
|
|
79
|
+
else
|
|
80
|
+
map.set(l.e1, [l]);
|
|
81
|
+
}
|
|
82
|
+
return map;
|
|
83
|
+
}
|
|
57
84
|
async function expandReferences(entries, expandKeys, fetchEntity) {
|
|
58
85
|
const ids = new Set;
|
|
59
86
|
for (const entry of entries) {
|
|
@@ -93,6 +120,8 @@ var DEFAULT_BASE_PATH = "/trellis/store";
|
|
|
93
120
|
var DEFAULT_POLL_MS = 2000;
|
|
94
121
|
var MIN_POLL_MS = 500;
|
|
95
122
|
var MAX_FACTS_PER_FETCH = 5000;
|
|
123
|
+
var MAX_ENTITIES_PER_FETCH = 1000;
|
|
124
|
+
var defaultEquals = (prev, next) => fingerprint(prev) === fingerprint(next);
|
|
96
125
|
|
|
97
126
|
class CmsClient {
|
|
98
127
|
url;
|
|
@@ -101,6 +130,7 @@ class CmsClient {
|
|
|
101
130
|
pollIntervalMs;
|
|
102
131
|
fetchFn;
|
|
103
132
|
apiKey;
|
|
133
|
+
subscriptions = new Map;
|
|
104
134
|
constructor(opts) {
|
|
105
135
|
this.url = opts.url.replace(/\/+$/, "");
|
|
106
136
|
this.basePath = (opts.basePath ?? DEFAULT_BASE_PATH).replace(/\/+$/, "");
|
|
@@ -117,7 +147,7 @@ class CmsClient {
|
|
|
117
147
|
}
|
|
118
148
|
async collections() {
|
|
119
149
|
const [entities, facts] = await Promise.all([
|
|
120
|
-
this.
|
|
150
|
+
this._entities(),
|
|
121
151
|
this._get(`/facts?limit=${MAX_FACTS_PER_FETCH}`)
|
|
122
152
|
]);
|
|
123
153
|
const factsByEntity = groupFactsByEntity(facts ?? []);
|
|
@@ -160,7 +190,64 @@ class CmsClient {
|
|
|
160
190
|
}
|
|
161
191
|
return [...out.values()].sort((a, b) => a.label.localeCompare(b.label));
|
|
162
192
|
}
|
|
163
|
-
close() {
|
|
193
|
+
close() {
|
|
194
|
+
for (const sub of this.subscriptions.values()) {
|
|
195
|
+
clearInterval(sub.interval);
|
|
196
|
+
sub.subscribers.clear();
|
|
197
|
+
}
|
|
198
|
+
this.subscriptions.clear();
|
|
199
|
+
}
|
|
200
|
+
_share(key, fetcher, callback, extras = {}) {
|
|
201
|
+
let sub = this.subscriptions.get(key);
|
|
202
|
+
if (!sub) {
|
|
203
|
+
const fresh = {
|
|
204
|
+
subscribers: new Set,
|
|
205
|
+
interval: undefined,
|
|
206
|
+
hasLast: false,
|
|
207
|
+
fetcher
|
|
208
|
+
};
|
|
209
|
+
const tick = async () => {
|
|
210
|
+
try {
|
|
211
|
+
const next = await fresh.fetcher();
|
|
212
|
+
fresh.last = next;
|
|
213
|
+
fresh.hasLast = true;
|
|
214
|
+
for (const item2 of fresh.subscribers) {
|
|
215
|
+
if (!item2.hasLast || !item2.equals(item2.last, next)) {
|
|
216
|
+
item2.last = next;
|
|
217
|
+
item2.hasLast = true;
|
|
218
|
+
item2.callback(next);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
} catch (err) {
|
|
222
|
+
for (const item2 of fresh.subscribers)
|
|
223
|
+
item2.onError?.(err);
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
fresh.interval = setInterval(tick, this.pollIntervalMs);
|
|
227
|
+
this.subscriptions.set(key, fresh);
|
|
228
|
+
sub = fresh;
|
|
229
|
+
tick();
|
|
230
|
+
}
|
|
231
|
+
const item = {
|
|
232
|
+
callback,
|
|
233
|
+
equals: extras.equals ?? defaultEquals,
|
|
234
|
+
onError: extras.onError,
|
|
235
|
+
hasLast: false
|
|
236
|
+
};
|
|
237
|
+
sub.subscribers.add(item);
|
|
238
|
+
if (sub.hasLast) {
|
|
239
|
+
item.last = sub.last;
|
|
240
|
+
item.hasLast = true;
|
|
241
|
+
callback(sub.last);
|
|
242
|
+
}
|
|
243
|
+
return () => {
|
|
244
|
+
sub.subscribers.delete(item);
|
|
245
|
+
if (sub.subscribers.size === 0) {
|
|
246
|
+
clearInterval(sub.interval);
|
|
247
|
+
this.subscriptions.delete(key);
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
}
|
|
164
251
|
async _get(path) {
|
|
165
252
|
const u = new URL(`${this.basePath}${path}`, this.url);
|
|
166
253
|
if (this.directory && !u.searchParams.has("directory")) {
|
|
@@ -169,17 +256,30 @@ class CmsClient {
|
|
|
169
256
|
const res = await this.fetchFn(u.toString(), {
|
|
170
257
|
headers: this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}
|
|
171
258
|
});
|
|
172
|
-
if (
|
|
259
|
+
if (res.status === 404)
|
|
173
260
|
return;
|
|
261
|
+
if (!res.ok)
|
|
262
|
+
throw new Error(`Trellis CMS request failed (${res.status}) ${u.pathname}`);
|
|
174
263
|
return await res.json();
|
|
175
264
|
}
|
|
265
|
+
async _entities() {
|
|
266
|
+
const out = [];
|
|
267
|
+
let offset = 0;
|
|
268
|
+
while (true) {
|
|
269
|
+
const page = await this._get(`/entities?limit=${MAX_ENTITIES_PER_FETCH}&offset=${offset}`) ?? [];
|
|
270
|
+
out.push(...page);
|
|
271
|
+
if (page.length < MAX_ENTITIES_PER_FETCH)
|
|
272
|
+
return out;
|
|
273
|
+
offset += MAX_ENTITIES_PER_FETCH;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
176
276
|
async _entryById(id) {
|
|
177
277
|
const detail = await this._get(`/entity/${encodeURIComponent(id)}`);
|
|
178
278
|
if (!detail)
|
|
179
279
|
return null;
|
|
180
280
|
const typeFact = detail.facts.find((f) => f.a === "type");
|
|
181
281
|
const type = typeof typeFact?.v === "string" ? typeFact.v : "unknown";
|
|
182
|
-
return entryFromFacts({ id: detail.id, type }, detail.facts);
|
|
282
|
+
return entryFromFacts({ id: detail.id, type }, detail.facts, detail.links);
|
|
183
283
|
}
|
|
184
284
|
}
|
|
185
285
|
|
|
@@ -193,18 +293,26 @@ class CollectionRef {
|
|
|
193
293
|
async list(opts = {}) {
|
|
194
294
|
const status = opts.status ?? "published";
|
|
195
295
|
const limit = opts.limit ?? 100;
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
this.client.
|
|
296
|
+
const wantsExpand = opts.expand && opts.expand.length > 0;
|
|
297
|
+
const [allEntities, facts, links] = await Promise.all([
|
|
298
|
+
this.client._entities(),
|
|
299
|
+
this.client._get(`/facts?limit=${MAX_FACTS_PER_FETCH}`),
|
|
300
|
+
this.client._get(`/links`)
|
|
199
301
|
]);
|
|
200
|
-
if (!
|
|
302
|
+
if (!allEntities)
|
|
303
|
+
return [];
|
|
304
|
+
const wantedKey = typeKey(this.key);
|
|
305
|
+
const matching = allEntities.filter((e) => typeKey(e.type) === wantedKey);
|
|
306
|
+
if (matching.length === 0)
|
|
201
307
|
return [];
|
|
202
308
|
const factsByEntity = groupFactsByEntity(facts ?? []);
|
|
203
|
-
|
|
309
|
+
const linksBySource = groupLinksBySource(links ?? []);
|
|
310
|
+
let entries = matching.map((e) => entryFromFacts(e, factsByEntity.get(e.id) ?? [], linksBySource.get(e.id) ?? []));
|
|
204
311
|
if (status !== "all") {
|
|
205
312
|
entries = entries.filter((e) => e.status === status);
|
|
206
313
|
}
|
|
207
|
-
|
|
314
|
+
entries = entries.slice(0, limit);
|
|
315
|
+
if (wantsExpand) {
|
|
208
316
|
entries = await expandReferences(entries, opts.expand, (id) => this.client._entryById(id));
|
|
209
317
|
}
|
|
210
318
|
return entries;
|
|
@@ -220,26 +328,9 @@ class CollectionRef {
|
|
|
220
328
|
return entry;
|
|
221
329
|
}
|
|
222
330
|
subscribe(callback, opts = {}) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
if (stopped)
|
|
227
|
-
return;
|
|
228
|
-
try {
|
|
229
|
-
const entries = await this.list(opts);
|
|
230
|
-
const sig = fingerprint(entries);
|
|
231
|
-
if (sig !== last) {
|
|
232
|
-
last = sig;
|
|
233
|
-
callback(entries);
|
|
234
|
-
}
|
|
235
|
-
} catch {}
|
|
236
|
-
};
|
|
237
|
-
tick();
|
|
238
|
-
const interval = setInterval(tick, this.client.pollIntervalMs);
|
|
239
|
-
return () => {
|
|
240
|
-
stopped = true;
|
|
241
|
-
clearInterval(interval);
|
|
242
|
-
};
|
|
331
|
+
const { onError, equals, ...listOpts } = opts;
|
|
332
|
+
const key = `coll:${typeKey(this.key)}:${JSON.stringify(listOpts)}`;
|
|
333
|
+
return this.client._share(key, () => this.list(listOpts), callback, { onError, equals });
|
|
243
334
|
}
|
|
244
335
|
}
|
|
245
336
|
|
|
@@ -261,26 +352,9 @@ class EntryRef {
|
|
|
261
352
|
return entry;
|
|
262
353
|
}
|
|
263
354
|
subscribe(callback, opts = {}) {
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
if (stopped)
|
|
268
|
-
return;
|
|
269
|
-
try {
|
|
270
|
-
const entry = await this.get(opts);
|
|
271
|
-
const sig = fingerprint(entry);
|
|
272
|
-
if (sig !== last) {
|
|
273
|
-
last = sig;
|
|
274
|
-
callback(entry);
|
|
275
|
-
}
|
|
276
|
-
} catch {}
|
|
277
|
-
};
|
|
278
|
-
tick();
|
|
279
|
-
const interval = setInterval(tick, this.client.pollIntervalMs);
|
|
280
|
-
return () => {
|
|
281
|
-
stopped = true;
|
|
282
|
-
clearInterval(interval);
|
|
283
|
-
};
|
|
355
|
+
const { onError, equals, ...getOpts } = opts;
|
|
356
|
+
const key = `entry:${this.id}:${JSON.stringify(getOpts)}`;
|
|
357
|
+
return this.client._share(key, () => this.get(getOpts), callback, { onError, equals });
|
|
284
358
|
}
|
|
285
359
|
}
|
|
286
360
|
function createCmsClient(opts) {
|
|
@@ -293,12 +367,17 @@ function expandLiteral(expand) {
|
|
|
293
367
|
return "";
|
|
294
368
|
return ` expand: ${JSON.stringify(expand)},`;
|
|
295
369
|
}
|
|
370
|
+
function clientLiteral(url, directory) {
|
|
371
|
+
if (!directory)
|
|
372
|
+
return `createCmsClient({ url: "${url}" })`;
|
|
373
|
+
return `createCmsClient({ url: "${url}", directory: ${JSON.stringify(directory)} })`;
|
|
374
|
+
}
|
|
296
375
|
function vanilla(opts) {
|
|
297
376
|
const url = opts.url ?? DEFAULT_URL;
|
|
298
377
|
const exp = expandLiteral(opts.expand);
|
|
299
378
|
return `import { createCmsClient } from "trellis/cms";
|
|
300
379
|
|
|
301
|
-
const cms =
|
|
380
|
+
const cms = ${clientLiteral(url, opts.directory)};
|
|
302
381
|
|
|
303
382
|
const collection = cms.collection("${opts.collection}");
|
|
304
383
|
|
|
@@ -322,7 +401,7 @@ function react(opts) {
|
|
|
322
401
|
return `import { useEffect, useState } from "react";
|
|
323
402
|
import { createCmsClient, type Entry } from "trellis/cms";
|
|
324
403
|
|
|
325
|
-
const cms =
|
|
404
|
+
const cms = ${clientLiteral(url, opts.directory)};
|
|
326
405
|
|
|
327
406
|
export function use${pascal(opts.collection)}() {
|
|
328
407
|
const [entries, setEntries] = useState<Entry[]>([]);
|
|
@@ -344,7 +423,7 @@ function solid(opts) {
|
|
|
344
423
|
return `import { createSignal, onCleanup } from "solid-js";
|
|
345
424
|
import { createCmsClient, type Entry } from "trellis/cms";
|
|
346
425
|
|
|
347
|
-
const cms =
|
|
426
|
+
const cms = ${clientLiteral(url, opts.directory)};
|
|
348
427
|
|
|
349
428
|
export function create${pascal(opts.collection)}() {
|
|
350
429
|
const [entries, setEntries] = createSignal<Entry[]>([]);
|
|
@@ -364,7 +443,7 @@ function vue(opts) {
|
|
|
364
443
|
return `import { ref, onUnmounted } from "vue";
|
|
365
444
|
import { createCmsClient, type Entry } from "trellis/cms";
|
|
366
445
|
|
|
367
|
-
const cms =
|
|
446
|
+
const cms = ${clientLiteral(url, opts.directory)};
|
|
368
447
|
|
|
369
448
|
export function use${pascal(opts.collection)}() {
|
|
370
449
|
const entries = ref<Entry[]>([]);
|
package/dist/cms/internal.d.ts
CHANGED
|
@@ -11,10 +11,16 @@ export type RawEntity = {
|
|
|
11
11
|
id: string;
|
|
12
12
|
type: string;
|
|
13
13
|
};
|
|
14
|
+
export type RawLink = {
|
|
15
|
+
e1: string;
|
|
16
|
+
a: string;
|
|
17
|
+
e2: string;
|
|
18
|
+
};
|
|
14
19
|
export declare function isSystemType(type: string): boolean;
|
|
15
20
|
export declare function typeKey(type: string): string;
|
|
16
|
-
export declare function entryFromFacts(entity: RawEntity, facts: RawFact[]): Entry;
|
|
21
|
+
export declare function entryFromFacts(entity: RawEntity, facts: RawFact[], links?: RawLink[]): Entry;
|
|
17
22
|
export declare function groupFactsByEntity(facts: RawFact[]): Map<string, RawFact[]>;
|
|
23
|
+
export declare function groupLinksBySource(links: RawLink[]): Map<string, RawLink[]>;
|
|
18
24
|
/**
|
|
19
25
|
* For each entry, replace string ids in `expand` field keys with the resolved Entry.
|
|
20
26
|
* Lookups are batched in parallel.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../src/cms/internal.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAe,MAAM,YAAY,CAAC;AAErD,MAAM,MAAM,OAAO,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC;AAC7E,MAAM,MAAM,SAAS,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../src/cms/internal.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAe,MAAM,YAAY,CAAC;AAErD,MAAM,MAAM,OAAO,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC;AAC7E,MAAM,MAAM,SAAS,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AACrD,MAAM,MAAM,OAAO,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAwB5D,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElD;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,GAAG,KAAK,CA+B5F;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAQ3E;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAQ3E;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,KAAK,EAAE,EAChB,UAAU,EAAE,MAAM,EAAE,EACpB,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,GACjD,OAAO,CAAC,KAAK,EAAE,CAAC,CA+BlB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAElD"}
|
package/dist/cms/scaffold.d.ts
CHANGED
|
@@ -12,6 +12,11 @@ export type ScaffoldOptions = {
|
|
|
12
12
|
expand?: string[];
|
|
13
13
|
/** Override the CMS server URL. Default: http://localhost:4096 */
|
|
14
14
|
url?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Project directory for multi-instance backends (e.g. opencode requires this).
|
|
17
|
+
* Baked into the generated client literal so requests route to the correct project.
|
|
18
|
+
*/
|
|
19
|
+
directory?: string;
|
|
15
20
|
};
|
|
16
21
|
export declare function scaffoldConsumer(opts: ScaffoldOptions): string;
|
|
17
22
|
export declare function scaffoldFilename(opts: ScaffoldOptions): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/cms/scaffold.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,MAAM,eAAe,GAAG;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,kEAAkE;IAClE,GAAG,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/cms/scaffold.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,MAAM,eAAe,GAAG;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,kEAAkE;IAClE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AA6GF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAW9D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAW9D"}
|
package/dist/cms/types.d.ts
CHANGED
|
@@ -25,6 +25,18 @@ export type ListOptions = {
|
|
|
25
25
|
export type GetOptions = {
|
|
26
26
|
expand?: string[];
|
|
27
27
|
};
|
|
28
|
+
export type SubscribeExtras = {
|
|
29
|
+
/** Called when a poll fails. If absent, errors are silently swallowed. */
|
|
30
|
+
onError?: (err: unknown) => void;
|
|
31
|
+
/**
|
|
32
|
+
* Custom equality check between consecutive results. Default: deep JSON
|
|
33
|
+
* comparison. Override with a faster check (e.g. id/version-based) for
|
|
34
|
+
* very large payloads.
|
|
35
|
+
*/
|
|
36
|
+
equals?: (prev: unknown, next: unknown) => boolean;
|
|
37
|
+
};
|
|
38
|
+
export type ListSubscribeOptions = ListOptions & SubscribeExtras;
|
|
39
|
+
export type EntrySubscribeOptions = GetOptions & SubscribeExtras;
|
|
28
40
|
export type Unsubscribe = () => void;
|
|
29
41
|
export type ListSubscriber<T extends Record<string, unknown> = Record<string, unknown>> = (entries: Entry<T>[]) => void;
|
|
30
42
|
export type EntrySubscriber<T extends Record<string, unknown> = Record<string, unknown>> = (entry: Entry<T> | null) => void;
|
package/dist/cms/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/cms/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,WAAW,CAAC;AAEhD,MAAM,MAAM,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IAC/E,oEAAoE;IACpE,EAAE,EAAE,MAAM,CAAC;IACX,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,MAAM,EAAE,WAAW,CAAC;IACpB,4FAA4F;IAC5F,MAAM,EAAE,CAAC,CAAC;CACX,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,KAAK,GAAG,WAAW,CAAC;IAC7B,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AACrC,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CACxF,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAChB,IAAI,CAAC;AACV,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CACzF,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,KACnB,IAAI,CAAC;AAEV,MAAM,MAAM,UAAU,GAAG;IACvB,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;IACZ,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,wFAAwF;IACxF,QAAQ,EAAE,OAAO,CAAC;IAClB,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,iGAAiG;IACjG,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sFAAsF;IACtF,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/cms/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,WAAW,CAAC;AAEhD,MAAM,MAAM,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IAC/E,oEAAoE;IACpE,EAAE,EAAE,MAAM,CAAC;IACX,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,MAAM,EAAE,WAAW,CAAC;IACpB,4FAA4F;IAC5F,MAAM,EAAE,CAAC,CAAC;CACX,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,KAAK,GAAG,WAAW,CAAC;IAC7B,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,0EAA0E;IAC1E,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IACjC;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC;CACpD,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,WAAW,GAAG,eAAe,CAAC;AACjE,MAAM,MAAM,qBAAqB,GAAG,UAAU,GAAG,eAAe,CAAC;AAEjE,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AACrC,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CACxF,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAChB,IAAI,CAAC;AACV,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CACzF,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,KACnB,IAAI,CAAC;AAEV,MAAM,MAAM,UAAU,GAAG;IACvB,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;IACZ,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,wFAAwF;IACxF,QAAQ,EAAE,OAAO,CAAC;IAClB,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,iGAAiG;IACjG,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sFAAsF;IACtF,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trellis",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.3",
|
|
4
4
|
"description": "Agentic State Engine — event-sourced causal graph with branching, decision traces, and realtime sync for AI-native applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -99,6 +99,7 @@
|
|
|
99
99
|
"logo.png",
|
|
100
100
|
"logo.svg",
|
|
101
101
|
"LICENSE",
|
|
102
|
+
"CHANGELOG.md",
|
|
102
103
|
"README.md"
|
|
103
104
|
],
|
|
104
105
|
"scripts": {
|
|
@@ -108,7 +109,7 @@
|
|
|
108
109
|
"mcp:docs": "bun run src/mcp/docs.ts",
|
|
109
110
|
"build": "bun build src/index.ts src/core/index.ts src/vcs/index.ts src/embeddings/index.ts src/links/index.ts src/decisions/index.ts src/server/index.ts src/client/index.ts src/react/index.ts src/db/index.ts src/cli/index.ts src/cms/index.ts --outdir dist --target bun --splitting --format esm --root src --external @xenova/transformers --external @huggingface/transformers --external react && mkdir -p dist/ui && cp src/ui/client.html dist/ui/client.html && tsc -p tsconfig.build.json --emitDeclarationOnly --noEmit false --noEmitOnError false && bun run build:inspector",
|
|
110
111
|
"build:inspector": "vite build --config vite.inspector.config.ts",
|
|
111
|
-
"test": "bun test test/core test/vcs test/git test/p2 test/p3 test/p4 test/p5 test/p6 test/p7 test/engine.test.ts",
|
|
112
|
+
"test": "bun test test/core test/cms test/vcs test/git test/p2 test/p3 test/p4 test/p5 test/p6 test/p7 test/engine.test.ts",
|
|
112
113
|
"test:all": "bun test",
|
|
113
114
|
"prepublishOnly": "npm run test && npm run build"
|
|
114
115
|
},
|