@rolexjs/local-platform 0.12.0-dev-20260223120451 → 0.12.0-dev-20260228032306

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -2,21 +2,15 @@ import { Platform } from '@rolexjs/core';
2
2
  import { State } from '@rolexjs/system';
3
3
 
4
4
  /**
5
- * localPlatform — create a Platform backed by local filesystem.
5
+ * localPlatform — create a Platform backed by SQLite + local filesystem.
6
6
  *
7
- * Storage layout:
8
- * {dataDir}/
9
- * role/<id>/
10
- * individual.json manifest (tree structure + links)
11
- * <id>.<type>.feature — node information (Gherkin)
12
- * organization/<id>/
13
- * organization.json — manifest (tree structure + links)
14
- * <id>.<type>.feature — node information (Gherkin)
7
+ * Storage:
8
+ * {dataDir}/rolex.db — SQLite database (single source of truth for runtime graph)
9
+ * {dataDir}/prototype.json — prototype registry
10
+ * {dataDir}/context/<id>.json role context persistence
15
11
  *
16
- * In-memory: Map-based tree (same model as @rolexjs/system createRuntime).
17
- * Persistence: loaded before every operation, saved after every mutation.
18
- * Refs are stored in manifests to ensure stability across reload cycles.
19
- * When dataDir is null, runs purely in-memory (useful for tests).
12
+ * Runtime: SQLite-backed via Drizzle ORM (no in-memory Map, no load/save cycle).
13
+ * When dataDir is null, runs with in-memory SQLite (useful for tests).
20
14
  */
21
15
 
22
16
  interface LocalPlatformConfig {
@@ -24,8 +18,10 @@ interface LocalPlatformConfig {
24
18
  dataDir?: string | null;
25
19
  /** Directory for ResourceX storage. Defaults to ~/.deepractice/resourcex. Set to null to disable. */
26
20
  resourceDir?: string | null;
21
+ /** Prototype sources to settle on genesis. */
22
+ bootstrap?: string[];
27
23
  }
28
- /** Create a local Platform. Persistent by default (~/.deepractice/rolex), in-memory if dataDir is null. */
24
+ /** Create a local Platform. Persistent by default ($DEEPRACTICE_HOME/rolex), in-memory if dataDir is null. */
29
25
  declare function localPlatform(config?: LocalPlatformConfig): Platform;
30
26
 
31
27
  /**
@@ -51,7 +47,9 @@ declare function localPlatform(config?: LocalPlatformConfig): Platform;
51
47
  interface ManifestNode {
52
48
  readonly type: string;
53
49
  readonly ref?: string;
50
+ readonly tag?: string;
54
51
  readonly children?: Record<string, ManifestNode>;
52
+ readonly links?: Record<string, string[]>;
55
53
  }
56
54
  /** Root manifest for an entity (individual or organization). */
57
55
  interface Manifest {
package/dist/index.js CHANGED
@@ -1,11 +1,303 @@
1
1
  // src/LocalPlatform.ts
2
- import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from "fs";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
3
3
  import { homedir } from "os";
4
4
  import { join } from "path";
5
+ import { drizzle } from "@deepracticex/drizzle";
6
+ import { openDatabase } from "@deepracticex/sqlite";
5
7
  import { NodeProvider } from "@resourcexjs/node-provider";
6
- import { organizationType, roleType } from "@rolexjs/resourcex-types";
8
+ import { sql } from "drizzle-orm";
7
9
  import { createResourceX, setProvider } from "resourcexjs";
8
10
 
11
+ // src/sqliteRuntime.ts
12
+ import { and, eq, isNull } from "drizzle-orm";
13
+
14
+ // src/schema.ts
15
+ import { index, primaryKey, sqliteTable, text } from "drizzle-orm/sqlite-core";
16
+ var nodes = sqliteTable(
17
+ "nodes",
18
+ {
19
+ ref: text("ref").primaryKey(),
20
+ id: text("id"),
21
+ alias: text("alias"),
22
+ // JSON array: '["Sean","姜山"]'
23
+ name: text("name").notNull(),
24
+ description: text("description").default(""),
25
+ parentRef: text("parent_ref").references(() => nodes.ref),
26
+ information: text("information"),
27
+ tag: text("tag")
28
+ },
29
+ (table) => [
30
+ index("idx_nodes_id").on(table.id),
31
+ index("idx_nodes_name").on(table.name),
32
+ index("idx_nodes_parent_ref").on(table.parentRef)
33
+ ]
34
+ );
35
+ var links = sqliteTable(
36
+ "links",
37
+ {
38
+ fromRef: text("from_ref").notNull().references(() => nodes.ref),
39
+ toRef: text("to_ref").notNull().references(() => nodes.ref),
40
+ relation: text("relation").notNull()
41
+ },
42
+ (table) => [
43
+ primaryKey({ columns: [table.fromRef, table.toRef, table.relation] }),
44
+ index("idx_links_from").on(table.fromRef),
45
+ index("idx_links_to").on(table.toRef)
46
+ ]
47
+ );
48
+
49
+ // src/sqliteRuntime.ts
50
+ function nextRef(db) {
51
+ const max = db.select({ ref: nodes.ref }).from(nodes).all().reduce((max2, r) => {
52
+ const n = parseInt(r.ref.slice(1), 10);
53
+ return Number.isNaN(n) ? max2 : Math.max(max2, n);
54
+ }, 0);
55
+ return `n${max + 1}`;
56
+ }
57
+ function toStructure(row) {
58
+ return {
59
+ ref: row.ref,
60
+ ...row.id ? { id: row.id } : {},
61
+ ...row.alias ? { alias: JSON.parse(row.alias) } : {},
62
+ name: row.name,
63
+ description: row.description ?? "",
64
+ parent: null,
65
+ // Runtime doesn't use parent as Structure; tree is via parentRef
66
+ ...row.information ? { information: row.information } : {},
67
+ ...row.tag ? { tag: row.tag } : {}
68
+ };
69
+ }
70
+ function projectNode(db, ref) {
71
+ const row = db.select().from(nodes).where(eq(nodes.ref, ref)).get();
72
+ if (!row) throw new Error(`Node not found: ${ref}`);
73
+ const children = db.select().from(nodes).where(eq(nodes.parentRef, ref)).all();
74
+ const nodeLinks = db.select().from(links).where(eq(links.fromRef, ref)).all();
75
+ return {
76
+ ...toStructure(row),
77
+ children: children.map((c) => projectNode(db, c.ref)),
78
+ ...nodeLinks.length > 0 ? {
79
+ links: nodeLinks.map((l) => ({
80
+ relation: l.relation,
81
+ target: projectRef(db, l.toRef)
82
+ }))
83
+ } : {}
84
+ };
85
+ }
86
+ function projectRef(db, ref) {
87
+ const row = db.select().from(nodes).where(eq(nodes.ref, ref)).get();
88
+ if (!row) throw new Error(`Node not found: ${ref}`);
89
+ return { ...toStructure(row), children: [] };
90
+ }
91
+ function removeSubtree(db, ref) {
92
+ const children = db.select({ ref: nodes.ref }).from(nodes).where(eq(nodes.parentRef, ref)).all();
93
+ for (const child of children) {
94
+ removeSubtree(db, child.ref);
95
+ }
96
+ db.delete(links).where(eq(links.fromRef, ref)).run();
97
+ db.delete(links).where(eq(links.toRef, ref)).run();
98
+ db.delete(nodes).where(eq(nodes.ref, ref)).run();
99
+ }
100
+ function createSqliteRuntime(db) {
101
+ return {
102
+ create(parent, type, information, id, alias) {
103
+ if (id && parent?.ref) {
104
+ const existing = db.select().from(nodes).where(and(eq(nodes.parentRef, parent.ref), eq(nodes.id, id))).get();
105
+ if (existing) return toStructure(existing);
106
+ }
107
+ const ref = nextRef(db);
108
+ db.insert(nodes).values({
109
+ ref,
110
+ id: id ?? null,
111
+ alias: alias && alias.length > 0 ? JSON.stringify(alias) : null,
112
+ name: type.name,
113
+ description: type.description,
114
+ parentRef: parent?.ref ?? null,
115
+ information: information ?? null,
116
+ tag: null
117
+ }).run();
118
+ return toStructure(db.select().from(nodes).where(eq(nodes.ref, ref)).get());
119
+ },
120
+ remove(node) {
121
+ if (!node.ref) return;
122
+ const row = db.select().from(nodes).where(eq(nodes.ref, node.ref)).get();
123
+ if (!row) return;
124
+ removeSubtree(db, node.ref);
125
+ },
126
+ transform(source, target, information) {
127
+ if (!source.ref) throw new Error("Source node has no ref");
128
+ const row = db.select().from(nodes).where(eq(nodes.ref, source.ref)).get();
129
+ if (!row) throw new Error(`Source node not found: ${source.ref}`);
130
+ const targetParent = target.parent;
131
+ if (!targetParent) {
132
+ throw new Error(`Cannot transform to root structure: ${target.name}`);
133
+ }
134
+ const parentRow = db.select().from(nodes).where(eq(nodes.name, targetParent.name)).get();
135
+ if (!parentRow) {
136
+ throw new Error(`No node found for structure: ${targetParent.name}`);
137
+ }
138
+ db.update(nodes).set({
139
+ parentRef: parentRow.ref,
140
+ name: target.name,
141
+ description: target.description,
142
+ ...information !== void 0 ? { information } : {}
143
+ }).where(eq(nodes.ref, source.ref)).run();
144
+ return toStructure(db.select().from(nodes).where(eq(nodes.ref, source.ref)).get());
145
+ },
146
+ link(from, to, relationName, reverseName) {
147
+ if (!from.ref) throw new Error("Source node has no ref");
148
+ if (!to.ref) throw new Error("Target node has no ref");
149
+ const existsForward = db.select().from(links).where(
150
+ and(
151
+ eq(links.fromRef, from.ref),
152
+ eq(links.toRef, to.ref),
153
+ eq(links.relation, relationName)
154
+ )
155
+ ).get();
156
+ if (!existsForward) {
157
+ db.insert(links).values({ fromRef: from.ref, toRef: to.ref, relation: relationName }).run();
158
+ }
159
+ const existsReverse = db.select().from(links).where(
160
+ and(eq(links.fromRef, to.ref), eq(links.toRef, from.ref), eq(links.relation, reverseName))
161
+ ).get();
162
+ if (!existsReverse) {
163
+ db.insert(links).values({ fromRef: to.ref, toRef: from.ref, relation: reverseName }).run();
164
+ }
165
+ },
166
+ unlink(from, to, relationName, reverseName) {
167
+ if (!from.ref || !to.ref) return;
168
+ db.delete(links).where(
169
+ and(
170
+ eq(links.fromRef, from.ref),
171
+ eq(links.toRef, to.ref),
172
+ eq(links.relation, relationName)
173
+ )
174
+ ).run();
175
+ db.delete(links).where(
176
+ and(eq(links.fromRef, to.ref), eq(links.toRef, from.ref), eq(links.relation, reverseName))
177
+ ).run();
178
+ },
179
+ tag(node, tagValue) {
180
+ if (!node.ref) throw new Error("Node has no ref");
181
+ const row = db.select().from(nodes).where(eq(nodes.ref, node.ref)).get();
182
+ if (!row) throw new Error(`Node not found: ${node.ref}`);
183
+ db.update(nodes).set({ tag: tagValue }).where(eq(nodes.ref, node.ref)).run();
184
+ },
185
+ project(node) {
186
+ if (!node.ref) throw new Error(`Node has no ref`);
187
+ return projectNode(db, node.ref);
188
+ },
189
+ roots() {
190
+ const rows = db.select().from(nodes).where(isNull(nodes.parentRef)).all();
191
+ return rows.map(toStructure);
192
+ }
193
+ };
194
+ }
195
+
196
+ // src/LocalPlatform.ts
197
+ var CREATE_NODES = sql`CREATE TABLE IF NOT EXISTS nodes (
198
+ ref TEXT PRIMARY KEY,
199
+ id TEXT,
200
+ alias TEXT,
201
+ name TEXT NOT NULL,
202
+ description TEXT DEFAULT '',
203
+ parent_ref TEXT REFERENCES nodes(ref),
204
+ information TEXT,
205
+ tag TEXT
206
+ )`;
207
+ var CREATE_LINKS = sql`CREATE TABLE IF NOT EXISTS links (
208
+ from_ref TEXT NOT NULL REFERENCES nodes(ref),
209
+ to_ref TEXT NOT NULL REFERENCES nodes(ref),
210
+ relation TEXT NOT NULL,
211
+ PRIMARY KEY (from_ref, to_ref, relation)
212
+ )`;
213
+ var CREATE_INDEXES = [
214
+ sql`CREATE INDEX IF NOT EXISTS idx_nodes_id ON nodes(id)`,
215
+ sql`CREATE INDEX IF NOT EXISTS idx_nodes_name ON nodes(name)`,
216
+ sql`CREATE INDEX IF NOT EXISTS idx_nodes_parent_ref ON nodes(parent_ref)`,
217
+ sql`CREATE INDEX IF NOT EXISTS idx_links_from ON links(from_ref)`,
218
+ sql`CREATE INDEX IF NOT EXISTS idx_links_to ON links(to_ref)`
219
+ ];
220
+ function deepracticeHome() {
221
+ return process.env.DEEPRACTICE_HOME ?? join(homedir(), ".deepractice");
222
+ }
223
+ function localPlatform(config = {}) {
224
+ const dataDir = config.dataDir === null ? void 0 : config.dataDir ?? join(deepracticeHome(), "rolex");
225
+ let dbPath;
226
+ if (dataDir) {
227
+ mkdirSync(dataDir, { recursive: true });
228
+ dbPath = join(dataDir, "rolex.db");
229
+ } else {
230
+ dbPath = ":memory:";
231
+ }
232
+ const rawDb = openDatabase(dbPath);
233
+ const db = drizzle(rawDb);
234
+ db.run(CREATE_NODES);
235
+ db.run(CREATE_LINKS);
236
+ for (const idx of CREATE_INDEXES) {
237
+ db.run(idx);
238
+ }
239
+ const runtime = createSqliteRuntime(db);
240
+ let resourcex;
241
+ if (config.resourceDir !== null) {
242
+ setProvider(new NodeProvider());
243
+ resourcex = createResourceX({
244
+ path: config.resourceDir ?? join(deepracticeHome(), "resourcex")
245
+ });
246
+ }
247
+ const registryPath = dataDir ? join(dataDir, "prototype.json") : void 0;
248
+ const readRegistry = () => {
249
+ if (registryPath && existsSync(registryPath)) {
250
+ return JSON.parse(readFileSync(registryPath, "utf-8"));
251
+ }
252
+ return {};
253
+ };
254
+ const writeRegistry = (registry) => {
255
+ if (!registryPath) return;
256
+ mkdirSync(dataDir, { recursive: true });
257
+ writeFileSync(registryPath, JSON.stringify(registry, null, 2), "utf-8");
258
+ };
259
+ const prototype = {
260
+ settle(id, source) {
261
+ const registry = readRegistry();
262
+ registry[id] = source;
263
+ writeRegistry(registry);
264
+ },
265
+ evict(id) {
266
+ const registry = readRegistry();
267
+ delete registry[id];
268
+ writeRegistry(registry);
269
+ },
270
+ list() {
271
+ return readRegistry();
272
+ }
273
+ };
274
+ const initializer = {
275
+ async bootstrap() {
276
+ }
277
+ };
278
+ const saveContext = (roleId, data) => {
279
+ if (!dataDir) return;
280
+ const contextDir = join(dataDir, "context");
281
+ mkdirSync(contextDir, { recursive: true });
282
+ writeFileSync(join(contextDir, `${roleId}.json`), JSON.stringify(data, null, 2), "utf-8");
283
+ };
284
+ const loadContext = (roleId) => {
285
+ if (!dataDir) return null;
286
+ const contextPath = join(dataDir, "context", `${roleId}.json`);
287
+ if (!existsSync(contextPath)) return null;
288
+ return JSON.parse(readFileSync(contextPath, "utf-8"));
289
+ };
290
+ return {
291
+ runtime,
292
+ prototype,
293
+ resourcex,
294
+ initializer,
295
+ bootstrap: config.bootstrap,
296
+ saveContext,
297
+ loadContext
298
+ };
299
+ }
300
+
9
301
  // src/manifest.ts
10
302
  function stateToFiles(state) {
11
303
  const files = [];
@@ -28,7 +320,9 @@ function stateToFiles(state) {
28
320
  const buildManifestNode = (node) => {
29
321
  const entry = {
30
322
  type: node.name,
31
- ...node.ref ? { ref: node.ref } : {}
323
+ ...node.ref ? { ref: node.ref } : {},
324
+ ...node.tag ? { tag: node.tag } : {},
325
+ ...node.links && node.links.length > 0 ? { links: buildManifestLinks(node.links) } : {}
32
326
  };
33
327
  if (node.children && node.children.length > 0) {
34
328
  const children = {};
@@ -53,9 +347,9 @@ function stateToFiles(state) {
53
347
  };
54
348
  return { manifest, files };
55
349
  }
56
- function buildManifestLinks(links) {
350
+ function buildManifestLinks(links2) {
57
351
  const result = {};
58
- for (const link of links) {
352
+ for (const link of links2) {
59
353
  const targetId = link.target.id ?? link.target.name;
60
354
  if (!result[link.relation]) {
61
355
  result[link.relation] = [];
@@ -74,14 +368,27 @@ function filesToState(manifest, fileContents) {
74
368
  children2.push(buildState(childId, childNode));
75
369
  }
76
370
  }
371
+ const nodeLinks = [];
372
+ if (node.links) {
373
+ for (const [relation, targetIds] of Object.entries(node.links)) {
374
+ for (const targetId of targetIds) {
375
+ nodeLinks.push({
376
+ relation,
377
+ target: { id: targetId, name: "", description: "", parent: null }
378
+ });
379
+ }
380
+ }
381
+ }
77
382
  return {
78
383
  ...node.ref ? { ref: node.ref } : {},
79
384
  id,
80
385
  name: node.type,
81
386
  description: "",
82
387
  parent: null,
388
+ ...node.tag ? { tag: node.tag } : {},
83
389
  ...information ? { information } : {},
84
- ...children2.length > 0 ? { children: children2 } : {}
390
+ ...children2.length > 0 ? { children: children2 } : {},
391
+ ...nodeLinks.length > 0 ? { links: nodeLinks } : {}
85
392
  };
86
393
  };
87
394
  const rootFilename = `${manifest.id}.${manifest.type}.feature`;
@@ -92,11 +399,11 @@ function filesToState(manifest, fileContents) {
92
399
  children.push(buildState(childId, childNode));
93
400
  }
94
401
  }
95
- const links = [];
402
+ const links2 = [];
96
403
  if (manifest.links) {
97
404
  for (const [relation, targetIds] of Object.entries(manifest.links)) {
98
405
  for (const targetId of targetIds) {
99
- links.push({
406
+ links2.push({
100
407
  relation,
101
408
  target: {
102
409
  id: targetId,
@@ -117,328 +424,8 @@ function filesToState(manifest, fileContents) {
117
424
  parent: null,
118
425
  ...rootInformation ? { information: rootInformation } : {},
119
426
  ...children.length > 0 ? { children } : {},
120
- ...links.length > 0 ? { links } : {}
121
- };
122
- }
123
-
124
- // src/LocalPlatform.ts
125
- function localPlatform(config = {}) {
126
- const dataDir = config.dataDir === null ? void 0 : config.dataDir ?? join(homedir(), ".deepractice", "rolex");
127
- const nodes = /* @__PURE__ */ new Map();
128
- const links = /* @__PURE__ */ new Map();
129
- let counter = 0;
130
- const nextRef = () => `n${++counter}`;
131
- const findByStructure = (s) => {
132
- for (const treeNode of nodes.values()) {
133
- if (treeNode.node.name === s.name) return treeNode;
134
- }
135
- return void 0;
136
- };
137
- const removeSubtree = (ref) => {
138
- const treeNode = nodes.get(ref);
139
- if (!treeNode) return;
140
- for (const childRef of [...treeNode.children]) {
141
- removeSubtree(childRef);
142
- }
143
- links.delete(ref);
144
- for (const [fromRef, fromLinks] of links.entries()) {
145
- const filtered = fromLinks.filter((l) => l.toId !== ref);
146
- if (filtered.length === 0) {
147
- links.delete(fromRef);
148
- } else {
149
- links.set(fromRef, filtered);
150
- }
151
- }
152
- nodes.delete(ref);
153
- };
154
- const projectRef = (ref) => {
155
- const treeNode = nodes.get(ref);
156
- return { ...treeNode.node, children: [] };
157
- };
158
- const projectNode = (ref) => {
159
- const treeNode = nodes.get(ref);
160
- const nodeLinks = links.get(ref);
161
- return {
162
- ...treeNode.node,
163
- children: treeNode.children.map(projectNode),
164
- ...nodeLinks && nodeLinks.length > 0 ? {
165
- links: nodeLinks.map((l) => ({
166
- relation: l.relation,
167
- target: projectRef(l.toId)
168
- }))
169
- } : {}
170
- };
171
- };
172
- const createNode = (parentRef, type, information, id, alias) => {
173
- const ref = nextRef();
174
- const node = {
175
- ref,
176
- ...id ? { id } : {},
177
- ...alias && alias.length > 0 ? { alias } : {},
178
- name: type.name,
179
- description: type.description,
180
- parent: type.parent,
181
- information
182
- };
183
- const treeNode = { node, parent: parentRef, children: [] };
184
- nodes.set(ref, treeNode);
185
- if (parentRef) {
186
- const parentTreeNode = nodes.get(parentRef);
187
- if (!parentTreeNode) throw new Error(`Parent not found: ${parentRef}`);
188
- parentTreeNode.children.push(ref);
189
- }
190
- return node;
191
- };
192
- const useRef = (storedRef) => {
193
- const n = parseInt(storedRef.slice(1), 10);
194
- if (!Number.isNaN(n) && n > counter) counter = n;
195
- return storedRef;
196
- };
197
- const replayState = (state, parentRef) => {
198
- const ref = state.ref ? useRef(state.ref) : nextRef();
199
- const node = {
200
- ref,
201
- ...state.id ? { id: state.id } : {},
202
- ...state.alias ? { alias: state.alias } : {},
203
- name: state.name,
204
- description: state.description ?? "",
205
- parent: null,
206
- ...state.information ? { information: state.information } : {}
207
- };
208
- const treeNode = { node, parent: parentRef, children: [] };
209
- nodes.set(ref, treeNode);
210
- if (parentRef) {
211
- nodes.get(parentRef).children.push(ref);
212
- }
213
- if (state.children) {
214
- for (const child of state.children) {
215
- replayState(child, ref);
216
- }
217
- }
218
- return ref;
219
- };
220
- const loadEntitiesFrom = (dir, manifestName, parentRef) => {
221
- const results = [];
222
- if (!existsSync(dir)) return results;
223
- for (const entry of readdirSync(dir, { withFileTypes: true })) {
224
- if (!entry.isDirectory()) continue;
225
- const entityDir = join(dir, entry.name);
226
- const manifestPath = join(entityDir, manifestName);
227
- if (!existsSync(manifestPath)) continue;
228
- const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
229
- const featureFiles = {};
230
- for (const file of readdirSync(entityDir)) {
231
- if (file.endsWith(".feature")) {
232
- featureFiles[file] = readFileSync(join(entityDir, file), "utf-8");
233
- }
234
- }
235
- const state = filesToState(manifest, featureFiles);
236
- const entityRef = replayState(state, parentRef);
237
- results.push({ ref: entityRef, manifest });
238
- }
239
- return results;
240
- };
241
- const load = () => {
242
- if (!dataDir) return;
243
- nodes.clear();
244
- links.clear();
245
- counter = 0;
246
- const societyRef = nextRef();
247
- nodes.set(societyRef, {
248
- node: {
249
- ref: societyRef,
250
- name: "society",
251
- description: "",
252
- parent: null
253
- },
254
- parent: null,
255
- children: []
256
- });
257
- const entityRefs = [
258
- ...loadEntitiesFrom(join(dataDir, "role"), "individual.json", societyRef),
259
- ...loadEntitiesFrom(join(dataDir, "organization"), "organization.json", societyRef)
260
- ];
261
- const idToRef = /* @__PURE__ */ new Map();
262
- for (const [ref, treeNode] of nodes) {
263
- if (treeNode.node.id) {
264
- idToRef.set(treeNode.node.id, ref);
265
- }
266
- }
267
- for (const { ref, manifest } of entityRefs) {
268
- if (!manifest.links) continue;
269
- const entityLinks = [];
270
- for (const [relation, targetIds] of Object.entries(manifest.links)) {
271
- for (const targetId of targetIds) {
272
- const targetRef = idToRef.get(targetId);
273
- if (targetRef) {
274
- entityLinks.push({ toId: targetRef, relation });
275
- }
276
- }
277
- }
278
- if (entityLinks.length > 0) {
279
- links.set(ref, entityLinks);
280
- }
281
- }
282
- };
283
- const saveEntity = (baseDir, entityId, manifestName, state) => {
284
- const entityDir = join(baseDir, entityId);
285
- mkdirSync(entityDir, { recursive: true });
286
- const { manifest, files } = stateToFiles(state);
287
- writeFileSync(join(entityDir, manifestName), JSON.stringify(manifest, null, 2), "utf-8");
288
- for (const file of files) {
289
- writeFileSync(join(entityDir, file.path), file.content, "utf-8");
290
- }
291
- };
292
- const save = () => {
293
- if (!dataDir) return;
294
- mkdirSync(dataDir, { recursive: true });
295
- let societyTreeNode;
296
- for (const treeNode of nodes.values()) {
297
- if (treeNode.parent === null && treeNode.node.name === "society") {
298
- societyTreeNode = treeNode;
299
- break;
300
- }
301
- }
302
- if (!societyTreeNode) return;
303
- const roleDir = join(dataDir, "role");
304
- const orgDir = join(dataDir, "organization");
305
- if (existsSync(roleDir)) rmSync(roleDir, { recursive: true });
306
- if (existsSync(orgDir)) rmSync(orgDir, { recursive: true });
307
- for (const childRef of societyTreeNode.children) {
308
- if (!nodes.has(childRef)) continue;
309
- const state = projectNode(childRef);
310
- const entityId = state.id ?? state.name;
311
- if (state.name === "individual") {
312
- saveEntity(roleDir, entityId, "individual.json", state);
313
- } else if (state.name === "organization") {
314
- saveEntity(orgDir, entityId, "organization.json", state);
315
- }
316
- }
317
- };
318
- const runtime = {
319
- create(parent, type, information, id, alias) {
320
- load();
321
- const node = createNode(parent?.ref ?? null, type, information, id, alias);
322
- save();
323
- return node;
324
- },
325
- remove(node) {
326
- load();
327
- if (!node.ref) return;
328
- const treeNode = nodes.get(node.ref);
329
- if (!treeNode) return;
330
- if (treeNode.parent) {
331
- const parentTreeNode = nodes.get(treeNode.parent);
332
- if (parentTreeNode) {
333
- parentTreeNode.children = parentTreeNode.children.filter((r) => r !== node.ref);
334
- }
335
- }
336
- removeSubtree(node.ref);
337
- save();
338
- },
339
- transform(_source, target, information) {
340
- load();
341
- const targetParent = target.parent;
342
- if (!targetParent) {
343
- throw new Error(`Cannot transform to root structure: ${target.name}`);
344
- }
345
- const parentTreeNode = findByStructure(targetParent);
346
- if (!parentTreeNode) {
347
- throw new Error(`No node found for structure: ${targetParent.name}`);
348
- }
349
- const node = createNode(parentTreeNode.node.ref, target, information);
350
- save();
351
- return node;
352
- },
353
- link(from, to, relationName, reverseName) {
354
- load();
355
- if (!from.ref) throw new Error("Source node has no ref");
356
- if (!to.ref) throw new Error("Target node has no ref");
357
- const fromLinks = links.get(from.ref) ?? [];
358
- if (!fromLinks.some((l) => l.toId === to.ref && l.relation === relationName)) {
359
- fromLinks.push({ toId: to.ref, relation: relationName });
360
- links.set(from.ref, fromLinks);
361
- }
362
- const toLinks = links.get(to.ref) ?? [];
363
- if (!toLinks.some((l) => l.toId === from.ref && l.relation === reverseName)) {
364
- toLinks.push({ toId: from.ref, relation: reverseName });
365
- links.set(to.ref, toLinks);
366
- }
367
- save();
368
- },
369
- unlink(from, to, relationName, reverseName) {
370
- load();
371
- if (!from.ref || !to.ref) return;
372
- const fromLinks = links.get(from.ref);
373
- if (fromLinks) {
374
- const filtered = fromLinks.filter(
375
- (l) => !(l.toId === to.ref && l.relation === relationName)
376
- );
377
- if (filtered.length === 0) links.delete(from.ref);
378
- else links.set(from.ref, filtered);
379
- }
380
- const toLinks = links.get(to.ref);
381
- if (toLinks) {
382
- const filtered = toLinks.filter(
383
- (l) => !(l.toId === from.ref && l.relation === reverseName)
384
- );
385
- if (filtered.length === 0) links.delete(to.ref);
386
- else links.set(to.ref, filtered);
387
- }
388
- save();
389
- },
390
- project(node) {
391
- load();
392
- if (!node.ref || !nodes.has(node.ref)) {
393
- throw new Error(`Node not found: ${node.ref}`);
394
- }
395
- return projectNode(node.ref);
396
- },
397
- roots() {
398
- load();
399
- const result = [];
400
- for (const treeNode of nodes.values()) {
401
- if (treeNode.parent === null) {
402
- result.push(treeNode.node);
403
- }
404
- }
405
- return result;
406
- }
407
- };
408
- let resourcex;
409
- if (config.resourceDir !== null) {
410
- setProvider(new NodeProvider());
411
- resourcex = createResourceX({
412
- path: config.resourceDir ?? join(homedir(), ".deepractice", "resourcex"),
413
- types: [roleType, organizationType]
414
- });
415
- }
416
- const registryPath = dataDir ? join(dataDir, "prototype.json") : void 0;
417
- const readRegistry = () => {
418
- if (!registryPath || !existsSync(registryPath)) return {};
419
- return JSON.parse(readFileSync(registryPath, "utf-8"));
420
- };
421
- const registerPrototype = (id, source) => {
422
- if (!registryPath) return;
423
- const registry = readRegistry();
424
- registry[id] = source;
425
- mkdirSync(dataDir, { recursive: true });
426
- writeFileSync(registryPath, JSON.stringify(registry, null, 2), "utf-8");
427
- };
428
- const prototype = {
429
- async resolve(id) {
430
- if (!resourcex) return void 0;
431
- const registry = readRegistry();
432
- const source = registry[id];
433
- if (!source) return void 0;
434
- try {
435
- return await resourcex.ingest(source);
436
- } catch {
437
- return void 0;
438
- }
439
- }
427
+ ...links2.length > 0 ? { links: links2 } : {}
440
428
  };
441
- return { runtime, prototype, resourcex, registerPrototype };
442
429
  }
443
430
  export {
444
431
  filesToState,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/LocalPlatform.ts","../src/manifest.ts"],"sourcesContent":["/**\n * localPlatform — create a Platform backed by local filesystem.\n *\n * Storage layout:\n * {dataDir}/\n * role/<id>/\n * individual.json — manifest (tree structure + links)\n * <id>.<type>.feature — node information (Gherkin)\n * organization/<id>/\n * organization.json — manifest (tree structure + links)\n * <id>.<type>.feature — node information (Gherkin)\n *\n * In-memory: Map-based tree (same model as @rolexjs/system createRuntime).\n * Persistence: loaded before every operation, saved after every mutation.\n * Refs are stored in manifests to ensure stability across reload cycles.\n * When dataDir is null, runs purely in-memory (useful for tests).\n */\n\nimport { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { NodeProvider } from \"@resourcexjs/node-provider\";\nimport type { Platform } from \"@rolexjs/core\";\nimport { organizationType, roleType } from \"@rolexjs/resourcex-types\";\nimport type { Prototype, Runtime, State, Structure } from \"@rolexjs/system\";\nimport { createResourceX, setProvider } from \"resourcexjs\";\nimport { filesToState, type Manifest, stateToFiles } from \"./manifest.js\";\n\n// ===== Internal types =====\n\ninterface TreeNode {\n node: Structure;\n parent: string | null;\n children: string[];\n}\n\ninterface LinkEntry {\n toId: string;\n relation: string;\n}\n\n// ===== Config =====\n\nexport interface LocalPlatformConfig {\n /** Directory for persistent storage. Defaults to ~/.deepractice/rolex. Set to null for in-memory only. */\n dataDir?: string | null;\n /** Directory for ResourceX storage. Defaults to ~/.deepractice/resourcex. Set to null to disable. */\n resourceDir?: string | null;\n}\n\n/** Create a local Platform. Persistent by default (~/.deepractice/rolex), in-memory if dataDir is null. */\nexport function localPlatform(config: LocalPlatformConfig = {}): Platform {\n const dataDir =\n config.dataDir === null\n ? undefined\n : (config.dataDir ?? join(homedir(), \".deepractice\", \"rolex\"));\n\n const nodes = new Map<string, TreeNode>();\n const links = new Map<string, LinkEntry[]>();\n let counter = 0;\n\n // ===== Internal helpers =====\n\n const nextRef = () => `n${++counter}`;\n\n const findByStructure = (s: Structure): TreeNode | undefined => {\n for (const treeNode of nodes.values()) {\n if (treeNode.node.name === s.name) return treeNode;\n }\n return undefined;\n };\n\n const removeSubtree = (ref: string): void => {\n const treeNode = nodes.get(ref);\n if (!treeNode) return;\n for (const childRef of [...treeNode.children]) {\n removeSubtree(childRef);\n }\n links.delete(ref);\n for (const [fromRef, fromLinks] of links.entries()) {\n const filtered = fromLinks.filter((l) => l.toId !== ref);\n if (filtered.length === 0) {\n links.delete(fromRef);\n } else {\n links.set(fromRef, filtered);\n }\n }\n nodes.delete(ref);\n };\n\n const projectRef = (ref: string): State => {\n const treeNode = nodes.get(ref)!;\n return { ...treeNode.node, children: [] };\n };\n\n const projectNode = (ref: string): State => {\n const treeNode = nodes.get(ref)!;\n const nodeLinks = links.get(ref);\n return {\n ...treeNode.node,\n children: treeNode.children.map(projectNode),\n ...(nodeLinks && nodeLinks.length > 0\n ? {\n links: nodeLinks.map((l) => ({\n relation: l.relation,\n target: projectRef(l.toId),\n })),\n }\n : {}),\n };\n };\n\n const createNode = (\n parentRef: string | null,\n type: Structure,\n information?: string,\n id?: string,\n alias?: readonly string[]\n ): Structure => {\n const ref = nextRef();\n const node: Structure = {\n ref,\n ...(id ? { id } : {}),\n ...(alias && alias.length > 0 ? { alias } : {}),\n name: type.name,\n description: type.description,\n parent: type.parent,\n information,\n };\n const treeNode: TreeNode = { node, parent: parentRef, children: [] };\n nodes.set(ref, treeNode);\n\n if (parentRef) {\n const parentTreeNode = nodes.get(parentRef);\n if (!parentTreeNode) throw new Error(`Parent not found: ${parentRef}`);\n parentTreeNode.children.push(ref);\n }\n\n return node;\n };\n\n // ===== Persistence =====\n\n /** Use a stored ref, updating counter to avoid future collisions. */\n const useRef = (storedRef: string): string => {\n const n = parseInt(storedRef.slice(1), 10);\n if (!Number.isNaN(n) && n > counter) counter = n;\n return storedRef;\n };\n\n /** Replay a State tree into the in-memory Maps. Returns the root ref. */\n const replayState = (state: State, parentRef: string | null): string => {\n const ref = state.ref ? useRef(state.ref) : nextRef();\n const node: Structure = {\n ref,\n ...(state.id ? { id: state.id } : {}),\n ...(state.alias ? { alias: state.alias } : {}),\n name: state.name,\n description: state.description ?? \"\",\n parent: null,\n ...(state.information ? { information: state.information } : {}),\n };\n const treeNode: TreeNode = { node, parent: parentRef, children: [] };\n nodes.set(ref, treeNode);\n\n if (parentRef) {\n nodes.get(parentRef)!.children.push(ref);\n }\n\n if (state.children) {\n for (const child of state.children) {\n replayState(child, ref);\n }\n }\n\n return ref;\n };\n\n const loadEntitiesFrom = (\n dir: string,\n manifestName: string,\n parentRef: string\n ): { ref: string; manifest: Manifest }[] => {\n const results: { ref: string; manifest: Manifest }[] = [];\n if (!existsSync(dir)) return results;\n\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n const entityDir = join(dir, entry.name);\n const manifestPath = join(entityDir, manifestName);\n if (!existsSync(manifestPath)) continue;\n\n const manifest: Manifest = JSON.parse(readFileSync(manifestPath, \"utf-8\"));\n const featureFiles: Record<string, string> = {};\n for (const file of readdirSync(entityDir)) {\n if (file.endsWith(\".feature\")) {\n featureFiles[file] = readFileSync(join(entityDir, file), \"utf-8\");\n }\n }\n const state = filesToState(manifest, featureFiles);\n const entityRef = replayState(state, parentRef);\n results.push({ ref: entityRef, manifest });\n }\n\n return results;\n };\n\n const load = () => {\n if (!dataDir) return;\n\n // Clear and rebuild from disk\n nodes.clear();\n links.clear();\n counter = 0;\n\n // Create implicit society root\n const societyRef = nextRef();\n nodes.set(societyRef, {\n node: {\n ref: societyRef,\n name: \"society\",\n description: \"\",\n parent: null,\n },\n parent: null,\n children: [],\n });\n\n // Load entities\n const entityRefs = [\n ...loadEntitiesFrom(join(dataDir, \"role\"), \"individual.json\", societyRef),\n ...loadEntitiesFrom(join(dataDir, \"organization\"), \"organization.json\", societyRef),\n ];\n\n // Build id → ref index for link resolution\n const idToRef = new Map<string, string>();\n for (const [ref, treeNode] of nodes) {\n if (treeNode.node.id) {\n idToRef.set(treeNode.node.id, ref);\n }\n }\n\n // Resolve links from manifests\n for (const { ref, manifest } of entityRefs) {\n if (!manifest.links) continue;\n const entityLinks: LinkEntry[] = [];\n for (const [relation, targetIds] of Object.entries(manifest.links)) {\n for (const targetId of targetIds) {\n const targetRef = idToRef.get(targetId);\n if (targetRef) {\n entityLinks.push({ toId: targetRef, relation });\n }\n }\n }\n if (entityLinks.length > 0) {\n links.set(ref, entityLinks);\n }\n }\n };\n\n const saveEntity = (baseDir: string, entityId: string, manifestName: string, state: State) => {\n const entityDir = join(baseDir, entityId);\n mkdirSync(entityDir, { recursive: true });\n const { manifest, files } = stateToFiles(state);\n writeFileSync(join(entityDir, manifestName), JSON.stringify(manifest, null, 2), \"utf-8\");\n for (const file of files) {\n writeFileSync(join(entityDir, file.path), file.content, \"utf-8\");\n }\n };\n\n const save = () => {\n if (!dataDir) return;\n mkdirSync(dataDir, { recursive: true });\n\n // Find society root\n let societyTreeNode: TreeNode | undefined;\n for (const treeNode of nodes.values()) {\n if (treeNode.parent === null && treeNode.node.name === \"society\") {\n societyTreeNode = treeNode;\n break;\n }\n }\n if (!societyTreeNode) return;\n\n // Clean up existing entity directories\n const roleDir = join(dataDir, \"role\");\n const orgDir = join(dataDir, \"organization\");\n if (existsSync(roleDir)) rmSync(roleDir, { recursive: true });\n if (existsSync(orgDir)) rmSync(orgDir, { recursive: true });\n\n // Save each entity child of society\n for (const childRef of societyTreeNode.children) {\n if (!nodes.has(childRef)) continue;\n const state = projectNode(childRef);\n const entityId = state.id ?? state.name;\n\n if (state.name === \"individual\") {\n saveEntity(roleDir, entityId, \"individual.json\", state);\n } else if (state.name === \"organization\") {\n saveEntity(orgDir, entityId, \"organization.json\", state);\n }\n // Other types (past, etc.) are not persisted yet\n }\n };\n\n // ===== Runtime =====\n\n const runtime: Runtime = {\n create(parent, type, information, id, alias) {\n load();\n const node = createNode(parent?.ref ?? null, type, information, id, alias);\n save();\n return node;\n },\n\n remove(node) {\n load();\n if (!node.ref) return;\n const treeNode = nodes.get(node.ref);\n if (!treeNode) return;\n\n if (treeNode.parent) {\n const parentTreeNode = nodes.get(treeNode.parent);\n if (parentTreeNode) {\n parentTreeNode.children = parentTreeNode.children.filter((r) => r !== node.ref);\n }\n }\n\n removeSubtree(node.ref);\n save();\n },\n\n transform(_source, target, information) {\n load();\n const targetParent = target.parent;\n if (!targetParent) {\n throw new Error(`Cannot transform to root structure: ${target.name}`);\n }\n\n const parentTreeNode = findByStructure(targetParent);\n if (!parentTreeNode) {\n throw new Error(`No node found for structure: ${targetParent.name}`);\n }\n\n const node = createNode(parentTreeNode.node.ref!, target, information);\n save();\n return node;\n },\n\n link(from, to, relationName, reverseName) {\n load();\n if (!from.ref) throw new Error(\"Source node has no ref\");\n if (!to.ref) throw new Error(\"Target node has no ref\");\n\n const fromLinks = links.get(from.ref) ?? [];\n if (!fromLinks.some((l) => l.toId === to.ref && l.relation === relationName)) {\n fromLinks.push({ toId: to.ref, relation: relationName });\n links.set(from.ref, fromLinks);\n }\n\n const toLinks = links.get(to.ref) ?? [];\n if (!toLinks.some((l) => l.toId === from.ref && l.relation === reverseName)) {\n toLinks.push({ toId: from.ref, relation: reverseName });\n links.set(to.ref, toLinks);\n }\n\n save();\n },\n\n unlink(from, to, relationName, reverseName) {\n load();\n if (!from.ref || !to.ref) return;\n\n const fromLinks = links.get(from.ref);\n if (fromLinks) {\n const filtered = fromLinks.filter(\n (l) => !(l.toId === to.ref && l.relation === relationName)\n );\n if (filtered.length === 0) links.delete(from.ref);\n else links.set(from.ref, filtered);\n }\n\n const toLinks = links.get(to.ref);\n if (toLinks) {\n const filtered = toLinks.filter(\n (l) => !(l.toId === from.ref && l.relation === reverseName)\n );\n if (filtered.length === 0) links.delete(to.ref);\n else links.set(to.ref, filtered);\n }\n\n save();\n },\n\n project(node) {\n load();\n if (!node.ref || !nodes.has(node.ref)) {\n throw new Error(`Node not found: ${node.ref}`);\n }\n return projectNode(node.ref);\n },\n\n roots() {\n load();\n const result: Structure[] = [];\n for (const treeNode of nodes.values()) {\n if (treeNode.parent === null) {\n result.push(treeNode.node);\n }\n }\n return result;\n },\n };\n\n // ===== ResourceX =====\n\n let resourcex: ReturnType<typeof createResourceX> | undefined;\n if (config.resourceDir !== null) {\n setProvider(new NodeProvider());\n resourcex = createResourceX({\n path: config.resourceDir ?? join(homedir(), \".deepractice\", \"resourcex\"),\n types: [roleType, organizationType],\n });\n }\n\n // ===== Prototype registry =====\n\n const registryPath = dataDir ? join(dataDir, \"prototype.json\") : undefined;\n\n const readRegistry = (): Record<string, string> => {\n if (!registryPath || !existsSync(registryPath)) return {};\n return JSON.parse(readFileSync(registryPath, \"utf-8\"));\n };\n\n const registerPrototype = (id: string, source: string): void => {\n if (!registryPath) return;\n const registry = readRegistry();\n registry[id] = source;\n mkdirSync(dataDir!, { recursive: true });\n writeFileSync(registryPath, JSON.stringify(registry, null, 2), \"utf-8\");\n };\n\n const prototype: Prototype = {\n async resolve(id) {\n if (!resourcex) return undefined;\n const registry = readRegistry();\n const source = registry[id];\n if (!source) return undefined;\n try {\n return await resourcex.ingest<State>(source);\n } catch {\n return undefined;\n }\n },\n };\n\n return { runtime, prototype, resourcex, registerPrototype };\n}\n","/**\n * Manifest — file-based storage format for RoleX entities.\n *\n * Storage layout:\n * role/<id>/\n * individual.json — manifest (tree structure + links)\n * <id>.<type>.feature — node information (Gherkin)\n *\n * organization/<id>/\n * organization.json — manifest (tree structure + links)\n * <id>.<type>.feature — node information (Gherkin)\n *\n * Rules:\n * - Directories: only role/ and organization/ at top level\n * - Files: all [id].[type].feature, flat within the entity directory\n * - Manifest: tree structure in JSON, content in .feature files\n * - Nodes without explicit id default to their type name\n */\n\nimport type { State } from \"@rolexjs/system\";\n\n// ===== Manifest types =====\n\n/** A node in the manifest tree. */\nexport interface ManifestNode {\n readonly type: string;\n readonly ref?: string;\n readonly children?: Record<string, ManifestNode>;\n}\n\n/** Root manifest for an entity (individual or organization). */\nexport interface Manifest {\n readonly id: string;\n readonly type: string;\n readonly ref?: string;\n readonly alias?: readonly string[];\n readonly children?: Record<string, ManifestNode>;\n readonly links?: Record<string, string[]>;\n}\n\n// ===== State → files =====\n\nexport interface FileEntry {\n readonly path: string;\n readonly content: string;\n}\n\n/**\n * Convert a State tree to a manifest + feature files.\n * Returns the manifest and a list of file entries (path → content).\n */\nexport function stateToFiles(state: State): { manifest: Manifest; files: FileEntry[] } {\n const files: FileEntry[] = [];\n\n const collectFiles = (node: State, nodeId: string) => {\n if (node.information) {\n files.push({\n path: `${nodeId}.${node.name}.feature`,\n content: node.information,\n });\n }\n if (node.children) {\n for (const child of node.children) {\n const childId = child.id ?? child.name;\n collectFiles(child, childId);\n }\n }\n };\n\n const rootId = state.id ?? state.name;\n collectFiles(state, rootId);\n\n const buildManifestNode = (node: State): ManifestNode => {\n const entry: ManifestNode = {\n type: node.name,\n ...(node.ref ? { ref: node.ref } : {}),\n };\n if (node.children && node.children.length > 0) {\n const children: Record<string, ManifestNode> = {};\n for (const child of node.children) {\n const childId = child.id ?? child.name;\n children[childId] = buildManifestNode(child);\n }\n return { ...entry, children };\n }\n return entry;\n };\n\n const manifestNode = buildManifestNode(state);\n\n const manifest: Manifest = {\n id: rootId,\n type: state.name,\n ...(state.ref ? { ref: state.ref } : {}),\n ...(state.alias ? { alias: state.alias } : {}),\n ...(manifestNode.children ? { children: manifestNode.children } : {}),\n ...(state.links && state.links.length > 0\n ? {\n links: buildManifestLinks(state.links),\n }\n : {}),\n };\n\n return { manifest, files };\n}\n\nfunction buildManifestLinks(\n links: readonly { readonly relation: string; readonly target: State }[]\n): Record<string, string[]> {\n const result: Record<string, string[]> = {};\n for (const link of links) {\n const targetId = link.target.id ?? link.target.name;\n if (!result[link.relation]) {\n result[link.relation] = [];\n }\n result[link.relation].push(targetId);\n }\n return result;\n}\n\n// ===== Files → State =====\n\n/**\n * Convert a manifest + feature file contents to a State tree.\n * fileContents maps filename (e.g. \"role-creation.principle.feature\") to Gherkin text.\n */\nexport function filesToState(manifest: Manifest, fileContents: Record<string, string>): State {\n const buildState = (id: string, node: ManifestNode): State => {\n const filename = `${id}.${node.type}.feature`;\n const information = fileContents[filename];\n\n const children: State[] = [];\n if (node.children) {\n for (const [childId, childNode] of Object.entries(node.children)) {\n children.push(buildState(childId, childNode));\n }\n }\n\n return {\n ...(node.ref ? { ref: node.ref } : {}),\n id,\n name: node.type,\n description: \"\",\n parent: null,\n ...(information ? { information } : {}),\n ...(children.length > 0 ? { children } : {}),\n };\n };\n\n const rootFilename = `${manifest.id}.${manifest.type}.feature`;\n const rootInformation = fileContents[rootFilename];\n\n const children: State[] = [];\n if (manifest.children) {\n for (const [childId, childNode] of Object.entries(manifest.children)) {\n children.push(buildState(childId, childNode));\n }\n }\n\n const links: { relation: string; target: State }[] = [];\n if (manifest.links) {\n for (const [relation, targetIds] of Object.entries(manifest.links)) {\n for (const targetId of targetIds) {\n links.push({\n relation,\n target: {\n id: targetId,\n name: \"\",\n description: \"\",\n parent: null,\n },\n });\n }\n }\n }\n\n return {\n ...(manifest.ref ? { ref: manifest.ref } : {}),\n id: manifest.id,\n ...(manifest.alias ? { alias: manifest.alias } : {}),\n name: manifest.type,\n description: \"\",\n parent: null,\n ...(rootInformation ? { information: rootInformation } : {}),\n ...(children.length > 0 ? { children } : {}),\n ...(links.length > 0 ? { links } : {}),\n };\n}\n"],"mappings":"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","names":["children"]}
1
+ {"version":3,"sources":["../src/LocalPlatform.ts","../src/sqliteRuntime.ts","../src/schema.ts","../src/manifest.ts"],"sourcesContent":["/**\n * localPlatform — create a Platform backed by SQLite + local filesystem.\n *\n * Storage:\n * {dataDir}/rolex.db — SQLite database (single source of truth for runtime graph)\n * {dataDir}/prototype.json — prototype registry\n * {dataDir}/context/<id>.json — role context persistence\n *\n * Runtime: SQLite-backed via Drizzle ORM (no in-memory Map, no load/save cycle).\n * When dataDir is null, runs with in-memory SQLite (useful for tests).\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { drizzle } from \"@deepracticex/drizzle\";\nimport { openDatabase } from \"@deepracticex/sqlite\";\nimport { NodeProvider } from \"@resourcexjs/node-provider\";\nimport type { ContextData, Platform } from \"@rolexjs/core\";\nimport type { Initializer } from \"@rolexjs/system\";\nimport { sql } from \"drizzle-orm\";\nimport { createResourceX, setProvider } from \"resourcexjs\";\nimport { createSqliteRuntime } from \"./sqliteRuntime.js\";\n\n// ===== Config =====\n\nexport interface LocalPlatformConfig {\n /** Directory for persistent storage. Defaults to ~/.deepractice/rolex. Set to null for in-memory only. */\n dataDir?: string | null;\n /** Directory for ResourceX storage. Defaults to ~/.deepractice/resourcex. Set to null to disable. */\n resourceDir?: string | null;\n /** Prototype sources to settle on genesis. */\n bootstrap?: string[];\n}\n\n// ===== DDL =====\n\nconst CREATE_NODES = sql`CREATE TABLE IF NOT EXISTS nodes (\n ref TEXT PRIMARY KEY,\n id TEXT,\n alias TEXT,\n name TEXT NOT NULL,\n description TEXT DEFAULT '',\n parent_ref TEXT REFERENCES nodes(ref),\n information TEXT,\n tag TEXT\n)`;\n\nconst CREATE_LINKS = sql`CREATE TABLE IF NOT EXISTS links (\n from_ref TEXT NOT NULL REFERENCES nodes(ref),\n to_ref TEXT NOT NULL REFERENCES nodes(ref),\n relation TEXT NOT NULL,\n PRIMARY KEY (from_ref, to_ref, relation)\n)`;\n\nconst CREATE_INDEXES = [\n sql`CREATE INDEX IF NOT EXISTS idx_nodes_id ON nodes(id)`,\n sql`CREATE INDEX IF NOT EXISTS idx_nodes_name ON nodes(name)`,\n sql`CREATE INDEX IF NOT EXISTS idx_nodes_parent_ref ON nodes(parent_ref)`,\n sql`CREATE INDEX IF NOT EXISTS idx_links_from ON links(from_ref)`,\n sql`CREATE INDEX IF NOT EXISTS idx_links_to ON links(to_ref)`,\n];\n\n// ===== Factory =====\n\n/** Resolve the DEEPRACTICE_HOME base directory. Env > default (~/.deepractice). */\nfunction deepracticeHome(): string {\n return process.env.DEEPRACTICE_HOME ?? join(homedir(), \".deepractice\");\n}\n\n/** Create a local Platform. Persistent by default ($DEEPRACTICE_HOME/rolex), in-memory if dataDir is null. */\nexport function localPlatform(config: LocalPlatformConfig = {}): Platform {\n const dataDir =\n config.dataDir === null ? undefined : (config.dataDir ?? join(deepracticeHome(), \"rolex\"));\n\n // ===== SQLite database =====\n\n let dbPath: string;\n if (dataDir) {\n mkdirSync(dataDir, { recursive: true });\n dbPath = join(dataDir, \"rolex.db\");\n } else {\n dbPath = \":memory:\";\n }\n\n const rawDb = openDatabase(dbPath);\n const db = drizzle(rawDb);\n\n // Ensure tables exist\n db.run(CREATE_NODES);\n db.run(CREATE_LINKS);\n for (const idx of CREATE_INDEXES) {\n db.run(idx);\n }\n\n // ===== Runtime =====\n\n const runtime = createSqliteRuntime(db);\n\n // ===== ResourceX =====\n\n let resourcex: ReturnType<typeof createResourceX> | undefined;\n if (config.resourceDir !== null) {\n setProvider(new NodeProvider());\n resourcex = createResourceX({\n path: config.resourceDir ?? join(deepracticeHome(), \"resourcex\"),\n });\n }\n\n // ===== Prototype registry =====\n\n const registryPath = dataDir ? join(dataDir, \"prototype.json\") : undefined;\n\n const readRegistry = (): Record<string, string> => {\n if (registryPath && existsSync(registryPath)) {\n return JSON.parse(readFileSync(registryPath, \"utf-8\"));\n }\n return {};\n };\n\n const writeRegistry = (registry: Record<string, string>): void => {\n if (!registryPath) return;\n mkdirSync(dataDir!, { recursive: true });\n writeFileSync(registryPath, JSON.stringify(registry, null, 2), \"utf-8\");\n };\n\n const prototype = {\n settle(id: string, source: string) {\n const registry = readRegistry();\n registry[id] = source;\n writeRegistry(registry);\n },\n\n evict(id: string) {\n const registry = readRegistry();\n delete registry[id];\n writeRegistry(registry);\n },\n\n list(): Record<string, string> {\n return readRegistry();\n },\n };\n\n // ===== Initializer =====\n\n const initializer: Initializer = {\n async bootstrap() {},\n };\n\n // ===== Context persistence =====\n\n const saveContext = (roleId: string, data: ContextData): void => {\n if (!dataDir) return;\n const contextDir = join(dataDir, \"context\");\n mkdirSync(contextDir, { recursive: true });\n writeFileSync(join(contextDir, `${roleId}.json`), JSON.stringify(data, null, 2), \"utf-8\");\n };\n\n const loadContext = (roleId: string): ContextData | null => {\n if (!dataDir) return null;\n const contextPath = join(dataDir, \"context\", `${roleId}.json`);\n if (!existsSync(contextPath)) return null;\n return JSON.parse(readFileSync(contextPath, \"utf-8\"));\n };\n\n return {\n runtime,\n prototype,\n resourcex,\n initializer,\n bootstrap: config.bootstrap,\n saveContext,\n loadContext,\n };\n}\n","/**\n * SQLite-backed Runtime — single source of truth.\n *\n * Every operation reads/writes directly to SQLite.\n * No in-memory Map, no load/save cycle, no stale refs.\n */\n\nimport type { CommonXDatabase } from \"@deepracticex/drizzle\";\nimport type { Runtime, State, Structure } from \"@rolexjs/system\";\nimport { and, eq, isNull } from \"drizzle-orm\";\nimport { links, nodes } from \"./schema.js\";\n\ntype DB = CommonXDatabase;\n\n// ===== Helpers =====\n\nfunction nextRef(db: DB): string {\n const max = db\n .select({ ref: nodes.ref })\n .from(nodes)\n .all()\n .reduce((max, r) => {\n const n = parseInt(r.ref.slice(1), 10);\n return Number.isNaN(n) ? max : Math.max(max, n);\n }, 0);\n return `n${max + 1}`;\n}\n\nfunction toStructure(row: typeof nodes.$inferSelect): Structure {\n return {\n ref: row.ref,\n ...(row.id ? { id: row.id } : {}),\n ...(row.alias ? { alias: JSON.parse(row.alias) } : {}),\n name: row.name,\n description: row.description ?? \"\",\n parent: null, // Runtime doesn't use parent as Structure; tree is via parentRef\n ...(row.information ? { information: row.information } : {}),\n ...(row.tag ? { tag: row.tag } : {}),\n };\n}\n\n// ===== Projection =====\n\nfunction projectNode(db: DB, ref: string): State {\n const row = db.select().from(nodes).where(eq(nodes.ref, ref)).get();\n if (!row) throw new Error(`Node not found: ${ref}`);\n\n const children = db.select().from(nodes).where(eq(nodes.parentRef, ref)).all();\n\n const nodeLinks = db.select().from(links).where(eq(links.fromRef, ref)).all();\n\n return {\n ...toStructure(row),\n children: children.map((c) => projectNode(db, c.ref)),\n ...(nodeLinks.length > 0\n ? {\n links: nodeLinks.map((l) => ({\n relation: l.relation,\n target: projectRef(db, l.toRef),\n })),\n }\n : {}),\n };\n}\n\nfunction projectRef(db: DB, ref: string): State {\n const row = db.select().from(nodes).where(eq(nodes.ref, ref)).get();\n if (!row) throw new Error(`Node not found: ${ref}`);\n return { ...toStructure(row), children: [] };\n}\n\n// ===== Subtree removal =====\n\nfunction removeSubtree(db: DB, ref: string): void {\n // Remove children first (depth-first)\n const children = db.select({ ref: nodes.ref }).from(nodes).where(eq(nodes.parentRef, ref)).all();\n for (const child of children) {\n removeSubtree(db, child.ref);\n }\n\n // Remove links from/to this node\n db.delete(links).where(eq(links.fromRef, ref)).run();\n db.delete(links).where(eq(links.toRef, ref)).run();\n\n // Remove the node itself\n db.delete(nodes).where(eq(nodes.ref, ref)).run();\n}\n\n// ===== Runtime factory =====\n\nexport function createSqliteRuntime(db: DB): Runtime {\n return {\n create(parent, type, information, id, alias) {\n // Idempotent: if parent has a child with the same id, return existing node.\n if (id && parent?.ref) {\n const existing = db\n .select()\n .from(nodes)\n .where(and(eq(nodes.parentRef, parent.ref), eq(nodes.id, id)))\n .get();\n if (existing) return toStructure(existing);\n }\n const ref = nextRef(db);\n db.insert(nodes)\n .values({\n ref,\n id: id ?? null,\n alias: alias && alias.length > 0 ? JSON.stringify(alias) : null,\n name: type.name,\n description: type.description,\n parentRef: parent?.ref ?? null,\n information: information ?? null,\n tag: null,\n })\n .run();\n return toStructure(db.select().from(nodes).where(eq(nodes.ref, ref)).get()!);\n },\n\n remove(node) {\n if (!node.ref) return;\n const row = db.select().from(nodes).where(eq(nodes.ref, node.ref)).get();\n if (!row) return;\n\n // Detach from parent's children (implicit via parentRef)\n removeSubtree(db, node.ref);\n },\n\n transform(source, target, information) {\n if (!source.ref) throw new Error(\"Source node has no ref\");\n const row = db.select().from(nodes).where(eq(nodes.ref, source.ref)).get();\n if (!row) throw new Error(`Source node not found: ${source.ref}`);\n\n const targetParent = target.parent;\n if (!targetParent) {\n throw new Error(`Cannot transform to root structure: ${target.name}`);\n }\n\n const parentRow = db.select().from(nodes).where(eq(nodes.name, targetParent.name)).get();\n if (!parentRow) {\n throw new Error(`No node found for structure: ${targetParent.name}`);\n }\n\n // Reparent + update type in place — subtree preserved\n db.update(nodes)\n .set({\n parentRef: parentRow.ref,\n name: target.name,\n description: target.description,\n ...(information !== undefined ? { information } : {}),\n })\n .where(eq(nodes.ref, source.ref))\n .run();\n\n return toStructure(db.select().from(nodes).where(eq(nodes.ref, source.ref)).get()!);\n },\n\n link(from, to, relationName, reverseName) {\n if (!from.ref) throw new Error(\"Source node has no ref\");\n if (!to.ref) throw new Error(\"Target node has no ref\");\n\n // Forward: from → to\n const existsForward = db\n .select()\n .from(links)\n .where(\n and(\n eq(links.fromRef, from.ref),\n eq(links.toRef, to.ref),\n eq(links.relation, relationName)\n )\n )\n .get();\n if (!existsForward) {\n db.insert(links).values({ fromRef: from.ref, toRef: to.ref, relation: relationName }).run();\n }\n\n // Reverse: to → from\n const existsReverse = db\n .select()\n .from(links)\n .where(\n and(eq(links.fromRef, to.ref), eq(links.toRef, from.ref), eq(links.relation, reverseName))\n )\n .get();\n if (!existsReverse) {\n db.insert(links).values({ fromRef: to.ref, toRef: from.ref, relation: reverseName }).run();\n }\n },\n\n unlink(from, to, relationName, reverseName) {\n if (!from.ref || !to.ref) return;\n\n db.delete(links)\n .where(\n and(\n eq(links.fromRef, from.ref),\n eq(links.toRef, to.ref),\n eq(links.relation, relationName)\n )\n )\n .run();\n\n db.delete(links)\n .where(\n and(eq(links.fromRef, to.ref), eq(links.toRef, from.ref), eq(links.relation, reverseName))\n )\n .run();\n },\n\n tag(node, tagValue) {\n if (!node.ref) throw new Error(\"Node has no ref\");\n const row = db.select().from(nodes).where(eq(nodes.ref, node.ref)).get();\n if (!row) throw new Error(`Node not found: ${node.ref}`);\n db.update(nodes).set({ tag: tagValue }).where(eq(nodes.ref, node.ref)).run();\n },\n\n project(node) {\n if (!node.ref) throw new Error(`Node has no ref`);\n return projectNode(db, node.ref);\n },\n\n roots() {\n const rows = db.select().from(nodes).where(isNull(nodes.parentRef)).all();\n return rows.map(toStructure);\n },\n };\n}\n","/**\n * Drizzle schema — SQLite tables for the RoleX runtime graph.\n *\n * Two tables:\n * nodes — tree backbone (Structure instances)\n * links — cross-branch relations (bidirectional)\n */\n\nimport { index, primaryKey, sqliteTable, text } from \"drizzle-orm/sqlite-core\";\n\n/**\n * nodes — every node in the society graph.\n *\n * Maps 1:1 to the Structure interface:\n * ref → graph-internal reference (primary key)\n * id → user-facing kebab-case identifier\n * alias → JSON array of alternative names\n * name → structure type (\"individual\", \"goal\", \"task\", etc.)\n * description → what this structure is\n * parent_ref → tree parent (self-referencing foreign key)\n * information → Gherkin Feature source text\n * tag → generic label (\"done\", \"abandoned\")\n */\nexport const nodes = sqliteTable(\n \"nodes\",\n {\n ref: text(\"ref\").primaryKey(),\n id: text(\"id\"),\n alias: text(\"alias\"), // JSON array: '[\"Sean\",\"姜山\"]'\n name: text(\"name\").notNull(),\n description: text(\"description\").default(\"\"),\n parentRef: text(\"parent_ref\").references((): any => nodes.ref),\n information: text(\"information\"),\n tag: text(\"tag\"),\n },\n (table) => [\n index(\"idx_nodes_id\").on(table.id),\n index(\"idx_nodes_name\").on(table.name),\n index(\"idx_nodes_parent_ref\").on(table.parentRef),\n ]\n);\n\n/**\n * links — cross-branch relations between nodes.\n *\n * Bidirectional: if A→B is \"membership\", B→A is \"belong\".\n * Both directions stored as separate rows.\n */\nexport const links = sqliteTable(\n \"links\",\n {\n fromRef: text(\"from_ref\")\n .notNull()\n .references(() => nodes.ref),\n toRef: text(\"to_ref\")\n .notNull()\n .references(() => nodes.ref),\n relation: text(\"relation\").notNull(),\n },\n (table) => [\n primaryKey({ columns: [table.fromRef, table.toRef, table.relation] }),\n index(\"idx_links_from\").on(table.fromRef),\n index(\"idx_links_to\").on(table.toRef),\n ]\n);\n","/**\n * Manifest — file-based storage format for RoleX entities.\n *\n * Storage layout:\n * role/<id>/\n * individual.json — manifest (tree structure + links)\n * <id>.<type>.feature — node information (Gherkin)\n *\n * organization/<id>/\n * organization.json — manifest (tree structure + links)\n * <id>.<type>.feature — node information (Gherkin)\n *\n * Rules:\n * - Directories: only role/ and organization/ at top level\n * - Files: all [id].[type].feature, flat within the entity directory\n * - Manifest: tree structure in JSON, content in .feature files\n * - Nodes without explicit id default to their type name\n */\n\nimport type { State } from \"@rolexjs/system\";\n\n// ===== Manifest types =====\n\n/** A node in the manifest tree. */\nexport interface ManifestNode {\n readonly type: string;\n readonly ref?: string;\n readonly tag?: string;\n readonly children?: Record<string, ManifestNode>;\n readonly links?: Record<string, string[]>;\n}\n\n/** Root manifest for an entity (individual or organization). */\nexport interface Manifest {\n readonly id: string;\n readonly type: string;\n readonly ref?: string;\n readonly alias?: readonly string[];\n readonly children?: Record<string, ManifestNode>;\n readonly links?: Record<string, string[]>;\n}\n\n// ===== State → files =====\n\nexport interface FileEntry {\n readonly path: string;\n readonly content: string;\n}\n\n/**\n * Convert a State tree to a manifest + feature files.\n * Returns the manifest and a list of file entries (path → content).\n */\nexport function stateToFiles(state: State): { manifest: Manifest; files: FileEntry[] } {\n const files: FileEntry[] = [];\n\n const collectFiles = (node: State, nodeId: string) => {\n if (node.information) {\n files.push({\n path: `${nodeId}.${node.name}.feature`,\n content: node.information,\n });\n }\n if (node.children) {\n for (const child of node.children) {\n const childId = child.id ?? child.name;\n collectFiles(child, childId);\n }\n }\n };\n\n const rootId = state.id ?? state.name;\n collectFiles(state, rootId);\n\n const buildManifestNode = (node: State): ManifestNode => {\n const entry: ManifestNode = {\n type: node.name,\n ...(node.ref ? { ref: node.ref } : {}),\n ...(node.tag ? { tag: node.tag } : {}),\n ...(node.links && node.links.length > 0 ? { links: buildManifestLinks(node.links) } : {}),\n };\n if (node.children && node.children.length > 0) {\n const children: Record<string, ManifestNode> = {};\n for (const child of node.children) {\n const childId = child.id ?? child.name;\n children[childId] = buildManifestNode(child);\n }\n return { ...entry, children };\n }\n return entry;\n };\n\n const manifestNode = buildManifestNode(state);\n\n const manifest: Manifest = {\n id: rootId,\n type: state.name,\n ...(state.ref ? { ref: state.ref } : {}),\n ...(state.alias ? { alias: state.alias } : {}),\n ...(manifestNode.children ? { children: manifestNode.children } : {}),\n ...(state.links && state.links.length > 0\n ? {\n links: buildManifestLinks(state.links),\n }\n : {}),\n };\n\n return { manifest, files };\n}\n\nfunction buildManifestLinks(\n links: readonly { readonly relation: string; readonly target: State }[]\n): Record<string, string[]> {\n const result: Record<string, string[]> = {};\n for (const link of links) {\n const targetId = link.target.id ?? link.target.name;\n if (!result[link.relation]) {\n result[link.relation] = [];\n }\n result[link.relation].push(targetId);\n }\n return result;\n}\n\n// ===== Files → State =====\n\n/**\n * Convert a manifest + feature file contents to a State tree.\n * fileContents maps filename (e.g. \"role-creation.principle.feature\") to Gherkin text.\n */\nexport function filesToState(manifest: Manifest, fileContents: Record<string, string>): State {\n const buildState = (id: string, node: ManifestNode): State => {\n const filename = `${id}.${node.type}.feature`;\n const information = fileContents[filename];\n\n const children: State[] = [];\n if (node.children) {\n for (const [childId, childNode] of Object.entries(node.children)) {\n children.push(buildState(childId, childNode));\n }\n }\n\n const nodeLinks: { relation: string; target: State }[] = [];\n if (node.links) {\n for (const [relation, targetIds] of Object.entries(node.links)) {\n for (const targetId of targetIds) {\n nodeLinks.push({\n relation,\n target: { id: targetId, name: \"\", description: \"\", parent: null },\n });\n }\n }\n }\n\n return {\n ...(node.ref ? { ref: node.ref } : {}),\n id,\n name: node.type,\n description: \"\",\n parent: null,\n ...(node.tag ? { tag: node.tag } : {}),\n ...(information ? { information } : {}),\n ...(children.length > 0 ? { children } : {}),\n ...(nodeLinks.length > 0 ? { links: nodeLinks } : {}),\n };\n };\n\n const rootFilename = `${manifest.id}.${manifest.type}.feature`;\n const rootInformation = fileContents[rootFilename];\n\n const children: State[] = [];\n if (manifest.children) {\n for (const [childId, childNode] of Object.entries(manifest.children)) {\n children.push(buildState(childId, childNode));\n }\n }\n\n const links: { relation: string; target: State }[] = [];\n if (manifest.links) {\n for (const [relation, targetIds] of Object.entries(manifest.links)) {\n for (const targetId of targetIds) {\n links.push({\n relation,\n target: {\n id: targetId,\n name: \"\",\n description: \"\",\n parent: null,\n },\n });\n }\n }\n }\n\n return {\n ...(manifest.ref ? { ref: manifest.ref } : {}),\n id: manifest.id,\n ...(manifest.alias ? { alias: manifest.alias } : {}),\n name: manifest.type,\n description: \"\",\n parent: null,\n ...(rootInformation ? { information: rootInformation } : {}),\n ...(children.length > 0 ? { children } : {}),\n ...(links.length > 0 ? { links } : {}),\n };\n}\n"],"mappings":"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","names":["max","links","children"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rolexjs/local-platform",
3
- "version": "0.12.0-dev-20260223120451",
3
+ "version": "0.12.0-dev-20260228032306",
4
4
  "description": "Local filesystem Platform for RoleX — stores roles in .rolex/ directories",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -20,11 +20,13 @@
20
20
  "clean": "rm -rf dist"
21
21
  },
22
22
  "dependencies": {
23
- "@rolexjs/system": "0.12.0-dev-20260223120451",
24
- "@rolexjs/core": "0.12.0-dev-20260223120451",
25
- "@rolexjs/resourcex-types": "0.12.0-dev-20260223120451",
26
- "resourcexjs": "^2.8.0",
27
- "@resourcexjs/node-provider": "^2.8.0"
23
+ "@deepracticex/drizzle": "^0.2.0",
24
+ "@deepracticex/sqlite": "^0.2.0",
25
+ "@resourcexjs/node-provider": "^2.14.0",
26
+ "@rolexjs/core": "0.12.0-dev-20260228032306",
27
+ "@rolexjs/system": "0.12.0-dev-20260228032306",
28
+ "drizzle-orm": "^0.45.1",
29
+ "resourcexjs": "^2.14.0"
28
30
  },
29
31
  "devDependencies": {},
30
32
  "publishConfig": {