videobook-engine 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +214 -0
  2. package/dist/artifacts.d.ts +20 -0
  3. package/dist/artifacts.d.ts.map +1 -0
  4. package/dist/artifacts.js +312 -0
  5. package/dist/artifacts.js.map +1 -0
  6. package/dist/books.d.ts +7 -0
  7. package/dist/books.d.ts.map +1 -0
  8. package/dist/books.js +27 -0
  9. package/dist/books.js.map +1 -0
  10. package/dist/cas.d.ts +26 -0
  11. package/dist/cas.d.ts.map +1 -0
  12. package/dist/cas.js +139 -0
  13. package/dist/cas.js.map +1 -0
  14. package/dist/communications.d.ts +15 -0
  15. package/dist/communications.d.ts.map +1 -0
  16. package/dist/communications.js +139 -0
  17. package/dist/communications.js.map +1 -0
  18. package/dist/context.d.ts +42 -0
  19. package/dist/context.d.ts.map +1 -0
  20. package/dist/context.js +197 -0
  21. package/dist/context.js.map +1 -0
  22. package/dist/domain.d.ts +32 -0
  23. package/dist/domain.d.ts.map +1 -0
  24. package/dist/domain.js +399 -0
  25. package/dist/domain.js.map +1 -0
  26. package/dist/engine-types.d.ts +548 -0
  27. package/dist/engine-types.d.ts.map +1 -0
  28. package/dist/engine-types.js +10 -0
  29. package/dist/engine-types.js.map +1 -0
  30. package/dist/engine.d.ts +213 -0
  31. package/dist/engine.d.ts.map +1 -0
  32. package/dist/engine.js +130 -0
  33. package/dist/engine.js.map +1 -0
  34. package/dist/files.d.ts +28 -0
  35. package/dist/files.d.ts.map +1 -0
  36. package/dist/files.js +476 -0
  37. package/dist/files.js.map +1 -0
  38. package/dist/history-types.d.ts +74 -0
  39. package/dist/history-types.d.ts.map +1 -0
  40. package/dist/history-types.js +2 -0
  41. package/dist/history-types.js.map +1 -0
  42. package/dist/history.d.ts +20 -0
  43. package/dist/history.d.ts.map +1 -0
  44. package/dist/history.js +921 -0
  45. package/dist/history.js.map +1 -0
  46. package/dist/ids.d.ts +4 -0
  47. package/dist/ids.d.ts.map +1 -0
  48. package/dist/ids.js +14 -0
  49. package/dist/ids.js.map +1 -0
  50. package/dist/index.d.ts +16 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +12 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/job-queue.d.ts +51 -0
  55. package/dist/job-queue.d.ts.map +1 -0
  56. package/dist/job-queue.js +443 -0
  57. package/dist/job-queue.js.map +1 -0
  58. package/dist/media.d.ts +7 -0
  59. package/dist/media.d.ts.map +1 -0
  60. package/dist/media.js +60 -0
  61. package/dist/media.js.map +1 -0
  62. package/dist/metadata.d.ts +21 -0
  63. package/dist/metadata.d.ts.map +1 -0
  64. package/dist/metadata.js +222 -0
  65. package/dist/metadata.js.map +1 -0
  66. package/dist/notebook/types.d.ts +51 -0
  67. package/dist/notebook/types.d.ts.map +1 -0
  68. package/dist/notebook/types.js +2 -0
  69. package/dist/notebook/types.js.map +1 -0
  70. package/dist/resolver.d.ts +15 -0
  71. package/dist/resolver.d.ts.map +1 -0
  72. package/dist/resolver.js +81 -0
  73. package/dist/resolver.js.map +1 -0
  74. package/dist/runtime-services.d.ts +65 -0
  75. package/dist/runtime-services.d.ts.map +1 -0
  76. package/dist/runtime-services.js +584 -0
  77. package/dist/runtime-services.js.map +1 -0
  78. package/dist/schema.d.ts +7 -0
  79. package/dist/schema.d.ts.map +1 -0
  80. package/dist/schema.js +509 -0
  81. package/dist/schema.js.map +1 -0
  82. package/dist/similarity.d.ts +4 -0
  83. package/dist/similarity.d.ts.map +1 -0
  84. package/dist/similarity.js +1551 -0
  85. package/dist/similarity.js.map +1 -0
  86. package/dist/status.d.ts +9 -0
  87. package/dist/status.d.ts.map +1 -0
  88. package/dist/status.js +231 -0
  89. package/dist/status.js.map +1 -0
  90. package/dist/storage.d.ts +7 -0
  91. package/dist/storage.d.ts.map +1 -0
  92. package/dist/storage.js +129 -0
  93. package/dist/storage.js.map +1 -0
  94. package/dist/store.d.ts +55 -0
  95. package/dist/store.d.ts.map +1 -0
  96. package/dist/store.js +378 -0
  97. package/dist/store.js.map +1 -0
  98. package/dist/timeline.d.ts +9 -0
  99. package/dist/timeline.d.ts.map +1 -0
  100. package/dist/timeline.js +236 -0
  101. package/dist/timeline.js.map +1 -0
  102. package/docs/engine-layout.md +489 -0
  103. package/package.json +55 -0
package/dist/cas.js ADDED
@@ -0,0 +1,139 @@
1
+ import { createHash } from "node:crypto";
2
+ import { createReadStream } from "node:fs";
3
+ import { constants, copyFile, mkdir, readFile, rename, rm, stat, writeFile, } from "node:fs/promises";
4
+ import * as path from "node:path";
5
+ import { v7 as uuidv7 } from "uuid";
6
+ export class ObjectStore {
7
+ remote;
8
+ root;
9
+ prefix;
10
+ constructor(root, remote, prefix = "superlzy-media/videobook/sha256") {
11
+ this.remote = remote;
12
+ this.root = root;
13
+ this.prefix = prefix.replace(/^\/+|\/+$/g, "");
14
+ }
15
+ async put(data) {
16
+ const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);
17
+ const hash = createHash("sha256").update(buffer).digest("hex");
18
+ const destination = this.pathFor(hash);
19
+ await mkdir(path.dirname(destination), { recursive: true });
20
+ const temporary = `${destination}.${uuidv7()}.tmp`;
21
+ try {
22
+ await writeFile(temporary, buffer, { flag: "wx" });
23
+ try {
24
+ await rename(temporary, destination);
25
+ }
26
+ catch (error) {
27
+ if (error.code !== "EEXIST")
28
+ throw error;
29
+ }
30
+ }
31
+ finally {
32
+ await rm(temporary, { force: true }).catch(() => undefined);
33
+ }
34
+ return { hash, size: buffer.byteLength, path: destination };
35
+ }
36
+ async import(sourcePath) {
37
+ const source = path.resolve(sourcePath);
38
+ const [hash, sourceStat] = await Promise.all([
39
+ hashFile(source),
40
+ stat(source),
41
+ ]);
42
+ const destination = this.pathFor(hash);
43
+ await mkdir(path.dirname(destination), { recursive: true });
44
+ try {
45
+ await copyFile(source, destination, constants.COPYFILE_EXCL);
46
+ }
47
+ catch (error) {
48
+ if (error.code !== "EEXIST")
49
+ throw error;
50
+ }
51
+ return { hash, size: sourceStat.size, path: destination };
52
+ }
53
+ async read(hash) {
54
+ await this.ensureLocal(hash);
55
+ return readFile(this.pathFor(hash));
56
+ }
57
+ /**
58
+ * Makes a content-addressed object available locally and returns its path
59
+ * without copying it into an artifact workspace.
60
+ */
61
+ async ensureLocalPath(hash) {
62
+ await this.ensureLocal(hash);
63
+ return this.pathFor(hash);
64
+ }
65
+ async materialize(hash, destinationPath) {
66
+ await this.ensureLocal(hash);
67
+ await mkdir(path.dirname(destinationPath), { recursive: true });
68
+ await copyFile(this.pathFor(hash), destinationPath);
69
+ }
70
+ async publish(hash, expectedSize) {
71
+ if (!this.remote)
72
+ return;
73
+ const key = this.keyFor(hash);
74
+ const current = await this.remote.head(key);
75
+ if (!current.exists) {
76
+ await this.remote.uploadFile(key, this.pathFor(hash));
77
+ }
78
+ else if (current.size !== undefined &&
79
+ current.size !== expectedSize) {
80
+ throw new Error(`Remote object size mismatch: ${hash}`);
81
+ }
82
+ const verified = await this.remote.head(key);
83
+ if (!verified.exists) {
84
+ throw new Error(`Remote object verification failed: ${hash}`);
85
+ }
86
+ if (verified.size !== undefined &&
87
+ verified.size !== expectedSize) {
88
+ throw new Error(`Remote object size mismatch: ${hash}`);
89
+ }
90
+ }
91
+ pathFor(hash) {
92
+ validateHash(hash);
93
+ return path.join(this.root, hash.slice(0, 2), hash);
94
+ }
95
+ keyFor(hash) {
96
+ validateHash(hash);
97
+ return `${this.prefix}/${hash.slice(0, 2)}/${hash}`;
98
+ }
99
+ async ensureLocal(hash) {
100
+ const destination = this.pathFor(hash);
101
+ try {
102
+ await stat(destination);
103
+ return;
104
+ }
105
+ catch (error) {
106
+ if (error.code !== "ENOENT")
107
+ throw error;
108
+ }
109
+ if (!this.remote)
110
+ throw new Error(`Object unavailable: ${hash}`);
111
+ await mkdir(path.dirname(destination), { recursive: true });
112
+ const temporary = `${destination}.${uuidv7()}.download`;
113
+ try {
114
+ await this.remote.downloadFile(this.keyFor(hash), temporary);
115
+ await rename(temporary, destination);
116
+ }
117
+ finally {
118
+ await rm(temporary, { force: true }).catch(() => undefined);
119
+ }
120
+ }
121
+ }
122
+ async function hashFile(filePath) {
123
+ const hash = createHash("sha256");
124
+ await new Promise((resolve, reject) => {
125
+ const input = createReadStream(filePath);
126
+ input.on("data", (chunk) => {
127
+ hash.update(chunk);
128
+ });
129
+ input.on("error", reject);
130
+ input.on("end", resolve);
131
+ });
132
+ return hash.digest("hex");
133
+ }
134
+ function validateHash(hash) {
135
+ if (!/^[a-f0-9]{64}$/.test(hash)) {
136
+ throw new Error(`Invalid SHA-256 hash: ${hash}`);
137
+ }
138
+ }
139
+ //# sourceMappingURL=cas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cas.js","sourceRoot":"","sources":["../src/cas.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { AppendMessageInput, EngineError, ListPromptHistoryArgs, Message, PromptHistoryEntry, RecordPromptArgs, Result } from "./engine-types.js";
2
+ import { EngineContext } from "./context.js";
3
+ export declare function createPromptsApi(context: EngineContext): {
4
+ record: (input: RecordPromptArgs) => Promise<Result<PromptHistoryEntry, EngineError>>;
5
+ list: (options?: ListPromptHistoryArgs) => Result<PromptHistoryEntry[], EngineError>;
6
+ count: (options?: Pick<ListPromptHistoryArgs, "surface">) => Result<number, EngineError>;
7
+ };
8
+ export declare function createMessagesApi(context: EngineContext): {
9
+ append: <T extends Record<string, unknown>>(input: AppendMessageInput<T>) => Promise<Result<Message<T>, EngineError>>;
10
+ list: <T = Record<string, unknown>>(options?: {
11
+ limit?: number;
12
+ role?: string;
13
+ }) => Result<Message<T>[], EngineError>;
14
+ };
15
+ //# sourceMappingURL=communications.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"communications.d.ts","sourceRoot":"","sources":["../src/communications.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,WAAW,EACX,qBAAqB,EACrB,OAAO,EACP,kBAAkB,EAClB,gBAAgB,EAChB,MAAM,EACP,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,aAAa,EAA0B,MAAM,cAAc,CAAC;AAmBrE,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa;oBAG1C,gBAAgB,KACtB,OAAO,CAAC,MAAM,CAAC,kBAAkB,EAAE,WAAW,CAAC,CAAC;qBAGxC,qBAAqB,KAC7B,MAAM,CAAC,kBAAkB,EAAE,EAAE,WAAW,CAAC;sBAGjC,IAAI,CAAC,qBAAqB,EAAE,SAAS,CAAC,KAC9C,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC;EAGjC;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,aAAa;aAE3C,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,SACjC,kBAAkB,CAAC,CAAC,CAAC,KAC3B,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;WACpC,CAAC,sCACG;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KACzC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,WAAW,CAAC;EAGvC"}
@@ -0,0 +1,139 @@
1
+ import { ok } from "./engine-types.js";
2
+ import { resultOf, syncResultOf } from "./context.js";
3
+ import { canonicalJson, parseJson } from "./store.js";
4
+ import { newUuidV7 } from "./ids.js";
5
+ export function createPromptsApi(context) {
6
+ return {
7
+ record: (input) => recordPrompt(context, input),
8
+ list: (options = {}) => syncResultOf(() => listPrompts(context, options)),
9
+ count: (options = {}) => syncResultOf(() => countPrompts(context, options)),
10
+ };
11
+ }
12
+ export function createMessagesApi(context) {
13
+ return {
14
+ append: (input) => appendMessage(context, input),
15
+ list: (options = {}) => syncResultOf(() => listMessages(context, options)),
16
+ };
17
+ }
18
+ async function recordPrompt(context, input) {
19
+ return resultOf(async () => {
20
+ const surface = input.surface.trim();
21
+ const prompt = input.prompt.trim();
22
+ if (!surface || !prompt) {
23
+ throw new Error("Prompt surface and prompt are required");
24
+ }
25
+ const promptId = newUuidV7();
26
+ const mutation = await context.store.semantic({
27
+ operation: "record_prompt",
28
+ details: { surface },
29
+ writeSet: [`prompt:${promptId}`],
30
+ }, ["prompt_entries"], (_operationId, now) => {
31
+ context.store.db
32
+ .prepare(`INSERT INTO prompt_entries(
33
+ prompt_id, surface, prompt, context_json, created_at
34
+ ) VALUES (?, ?, ?, ?, ?)`)
35
+ .run(promptId, surface, prompt, canonicalJson(input.context ?? {}), now);
36
+ return promptId;
37
+ });
38
+ return ok(promptFromRow(requiredPrompt(context, mutation.value)), mutation.revision);
39
+ });
40
+ }
41
+ function listPrompts(context, options) {
42
+ const clauses = [];
43
+ const params = [];
44
+ if (options.surface) {
45
+ clauses.push("surface=?");
46
+ params.push(options.surface);
47
+ }
48
+ params.push(Math.max(1, options.limit ?? 100));
49
+ const rows = context.store.db
50
+ .prepare(`SELECT prompt_id, surface, prompt, context_json, created_at
51
+ FROM prompt_entries
52
+ ${clauses.length ? `WHERE ${clauses.join(" AND ")}` : ""}
53
+ ORDER BY created_at DESC, prompt_id DESC
54
+ LIMIT ?`)
55
+ .all(...params);
56
+ return rows.map(promptFromRow);
57
+ }
58
+ function countPrompts(context, options) {
59
+ const row = options.surface
60
+ ? context.store.db
61
+ .prepare("SELECT COUNT(*) AS count FROM prompt_entries WHERE surface=?")
62
+ .get(options.surface)
63
+ : context.store.db
64
+ .prepare("SELECT COUNT(*) AS count FROM prompt_entries")
65
+ .get();
66
+ return row.count;
67
+ }
68
+ async function appendMessage(context, input) {
69
+ return resultOf(async () => {
70
+ const role = input.role.trim();
71
+ if (!role)
72
+ throw new Error("Message role is required");
73
+ const messageId = newUuidV7();
74
+ const mutation = await context.store.semantic({
75
+ operation: "append_message",
76
+ details: { messageId, role },
77
+ writeSet: [`message:${messageId}`],
78
+ }, ["messages"], (_operationId, now) => {
79
+ context.store.db
80
+ .prepare(`INSERT INTO messages(message_id, role, body_json, created_at)
81
+ VALUES (?, ?, ?, ?)`)
82
+ .run(messageId, role, canonicalJson(input.body), now);
83
+ });
84
+ return ok(messageFromRow(requiredMessage(context, messageId)), mutation.revision);
85
+ });
86
+ }
87
+ function listMessages(context, options) {
88
+ const clauses = [];
89
+ const params = [];
90
+ if (options.role) {
91
+ clauses.push("role=?");
92
+ params.push(options.role);
93
+ }
94
+ params.push(Math.max(1, options.limit ?? 100));
95
+ const rows = context.store.db
96
+ .prepare(`SELECT message_id, role, body_json, created_at
97
+ FROM messages
98
+ ${clauses.length ? `WHERE ${clauses.join(" AND ")}` : ""}
99
+ ORDER BY created_at DESC, message_id DESC
100
+ LIMIT ?`)
101
+ .all(...params);
102
+ return rows.reverse().map((messageFromRow));
103
+ }
104
+ function requiredPrompt(context, promptId) {
105
+ const row = context.store.db
106
+ .prepare(`SELECT prompt_id, surface, prompt, context_json, created_at
107
+ FROM prompt_entries WHERE prompt_id=?`)
108
+ .get(promptId);
109
+ if (!row)
110
+ throw new Error(`Prompt not found after insert: ${promptId}`);
111
+ return row;
112
+ }
113
+ function requiredMessage(context, messageId) {
114
+ const row = context.store.db
115
+ .prepare(`SELECT message_id, role, body_json, created_at
116
+ FROM messages WHERE message_id=?`)
117
+ .get(messageId);
118
+ if (!row)
119
+ throw new Error(`Message not found after insert: ${messageId}`);
120
+ return row;
121
+ }
122
+ function promptFromRow(row) {
123
+ return {
124
+ id: row.prompt_id,
125
+ surface: row.surface,
126
+ prompt: row.prompt,
127
+ context: parseJson(row.context_json, {}),
128
+ createdAt: row.created_at,
129
+ };
130
+ }
131
+ function messageFromRow(row) {
132
+ return {
133
+ messageId: row.message_id,
134
+ role: row.role,
135
+ body: parseJson(row.body_json, {}),
136
+ createdAt: row.created_at,
137
+ };
138
+ }
139
+ //# sourceMappingURL=communications.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"communications.js","sourceRoot":"","sources":["../src/communications.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import type { Artifact, ArtifactKind, Book, EngineConfig, EngineError, Result } from "./engine-types.js";
2
+ import { ObjectStore } from "./cas.js";
3
+ import { DoltStore } from "./store.js";
4
+ interface BookRow {
5
+ book_id: string;
6
+ slug: string;
7
+ created_at: number;
8
+ }
9
+ export interface ArtifactRow {
10
+ artifact_id: string;
11
+ slug: string;
12
+ kind: ArtifactKind;
13
+ created_at: number;
14
+ }
15
+ export interface FileRow {
16
+ artifact_id: string;
17
+ path: string;
18
+ object_hash: string;
19
+ size_bytes: number;
20
+ mtime_ms: number;
21
+ created_at: number;
22
+ }
23
+ export declare class EngineContext {
24
+ readonly store: DoltStore;
25
+ readonly objects: ObjectStore;
26
+ readonly config: EngineConfig;
27
+ constructor(config: EngineConfig);
28
+ bookRow(): BookRow;
29
+ book(row?: BookRow): Book;
30
+ artifactRow(reference: string): ArtifactRow;
31
+ artifactRowById(artifactId: string): ArtifactRow;
32
+ artifact(row: ArtifactRow): Artifact;
33
+ artifactPath(artifactId: string): string;
34
+ ensureArtifactWorkspace(artifactId: string): string;
35
+ close(): void;
36
+ }
37
+ export declare function normalizeBookSlug(input: string): string;
38
+ export declare function isValidBookSlug(input: string): boolean;
39
+ export declare function resultOf<T>(work: () => Promise<Result<T, EngineError> | T>): Promise<Result<T, EngineError>>;
40
+ export declare function syncResultOf<T>(work: () => T): Result<T, EngineError>;
41
+ export {};
42
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,QAAQ,EACR,YAAY,EACZ,IAAI,EACJ,YAAY,EACZ,WAAW,EACX,MAAM,EACP,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,SAAS,EAAe,MAAM,YAAY,CAAC;AAEpD,UAAU,OAAO;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,YAAY,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,OAAO;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,aAAa;IACxB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;gBAElB,MAAM,EAAE,YAAY;IA0DhC,OAAO,IAAI,OAAO;IAalB,IAAI,CAAC,GAAG,UAAiB,GAAG,IAAI;IAQhC,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW;IAqB3C,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,WAAW;IAiBhD,QAAQ,CAAC,GAAG,EAAE,WAAW,GAAG,QAAQ;IAUpC,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAIxC,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAMnD,KAAK,IAAI,IAAI;CAGd;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAUvD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAMtD;AAuCD,wBAAsB,QAAQ,CAAC,CAAC,EAC9B,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,GAC9C,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAcjC;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,WAAW,CAAC,CAMrE"}
@@ -0,0 +1,197 @@
1
+ import { existsSync, mkdirSync } from "node:fs";
2
+ import * as path from "node:path";
3
+ import { v7 as uuidv7 } from "uuid";
4
+ import { err } from "./engine-types.js";
5
+ import { ObjectStore } from "./cas.js";
6
+ import { DoltStore, EngineFault } from "./store.js";
7
+ export class EngineContext {
8
+ store;
9
+ objects;
10
+ config;
11
+ constructor(config) {
12
+ const storage = config.rootDir !== undefined
13
+ ? {
14
+ dataDir: path.join(path.resolve(config.rootDir), "data"),
15
+ workspaceDir: path.join(path.resolve(config.rootDir), "workspaces"),
16
+ }
17
+ : {
18
+ dataDir: path.resolve(config.dataDir),
19
+ workspaceDir: path.resolve(config.workspaceDir),
20
+ };
21
+ this.config = {
22
+ ...config,
23
+ ...storage,
24
+ rootDir: undefined,
25
+ };
26
+ if (storage.dataDir === storage.workspaceDir) {
27
+ throw new EngineFault({
28
+ code: "INVALID_INPUT",
29
+ message: "dataDir and workspaceDir must be different directories",
30
+ });
31
+ }
32
+ const databasePath = path.join(storage.dataDir, "videobook.db");
33
+ const initialBook = !existsSync(databasePath)
34
+ ? (() => {
35
+ if (!config.initialBookSlug) {
36
+ throw new EngineFault({
37
+ code: "INVALID_INPUT",
38
+ message: "initialBookSlug is required when creating a new engine root",
39
+ });
40
+ }
41
+ return {
42
+ bookId: uuidv7(),
43
+ slug: normalizeBookSlug(config.initialBookSlug),
44
+ };
45
+ })()
46
+ : undefined;
47
+ this.store = new DoltStore({
48
+ dataDir: this.config.dataDir,
49
+ workspaceDir: this.config.workspaceDir,
50
+ initialBook,
51
+ ...(config.catalogBackup
52
+ ? { catalogBackup: config.catalogBackup }
53
+ : {}),
54
+ });
55
+ this.objects = new ObjectStore(this.store.objectsDir, config.remoteObjects, config.objectPrefix);
56
+ }
57
+ bookRow() {
58
+ const row = this.store.db
59
+ .prepare("SELECT book_id, slug, created_at FROM book")
60
+ .get();
61
+ if (!row) {
62
+ throw new EngineFault({
63
+ code: "SCHEMA_INCOMPATIBLE",
64
+ message: "Book catalog is missing its singleton book record",
65
+ });
66
+ }
67
+ return row;
68
+ }
69
+ book(row = this.bookRow()) {
70
+ return {
71
+ bookId: row.book_id,
72
+ slug: row.slug,
73
+ createdAt: row.created_at,
74
+ };
75
+ }
76
+ artifactRow(reference) {
77
+ const row = this.store.db
78
+ .prepare(`SELECT artifact_id, slug, kind, created_at
79
+ FROM artifacts
80
+ WHERE artifact_id = ? OR slug = ?
81
+ ORDER BY CASE WHEN artifact_id = ? THEN 0 ELSE 1 END
82
+ LIMIT 1`)
83
+ .get(reference, reference, reference);
84
+ if (!row) {
85
+ throw new EngineFault({
86
+ code: "NOT_FOUND",
87
+ message: `Artifact not found: ${reference}`,
88
+ });
89
+ }
90
+ return row;
91
+ }
92
+ artifactRowById(artifactId) {
93
+ const row = this.store.db
94
+ .prepare(`SELECT artifact_id, slug, kind, created_at
95
+ FROM artifacts
96
+ WHERE artifact_id = ?`)
97
+ .get(artifactId);
98
+ if (!row) {
99
+ throw new EngineFault({
100
+ code: "NOT_FOUND",
101
+ message: `Artifact not found: ${artifactId}`,
102
+ });
103
+ }
104
+ return row;
105
+ }
106
+ artifact(row) {
107
+ return {
108
+ artifactId: row.artifact_id,
109
+ slug: row.slug,
110
+ kind: row.kind,
111
+ createdAt: row.created_at,
112
+ path: this.artifactPath(row.artifact_id),
113
+ };
114
+ }
115
+ artifactPath(artifactId) {
116
+ return path.join(this.store.workspaceDir, artifactId);
117
+ }
118
+ ensureArtifactWorkspace(artifactId) {
119
+ const workspace = this.artifactPath(artifactId);
120
+ mkdirSync(workspace, { recursive: true });
121
+ return workspace;
122
+ }
123
+ close() {
124
+ this.store.close();
125
+ }
126
+ }
127
+ export function normalizeBookSlug(input) {
128
+ const slug = input
129
+ .trim()
130
+ .toLowerCase()
131
+ .replace(/[^a-z0-9]+/g, "-")
132
+ .replace(/^-+|-+$/g, "");
133
+ if (!slug || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(slug)) {
134
+ throw new Error(`Invalid book slug: ${input}`);
135
+ }
136
+ return slug;
137
+ }
138
+ export function isValidBookSlug(input) {
139
+ try {
140
+ return normalizeBookSlug(input) === input;
141
+ }
142
+ catch {
143
+ return false;
144
+ }
145
+ }
146
+ function toError(error) {
147
+ if (error instanceof EngineFault)
148
+ return error.error;
149
+ const message = error instanceof Error ? error.message : String(error);
150
+ if (message.includes("artifacts_active_slug") ||
151
+ /UNIQUE constraint failed: artifacts\.slug/i.test(message)) {
152
+ return { code: "SLUG_CONFLICT", message };
153
+ }
154
+ if (/UNIQUE constraint failed/i.test(message)) {
155
+ return { code: "ALREADY_EXISTS", message };
156
+ }
157
+ if (/object unavailable/i.test(message)) {
158
+ return { code: "OBJECT_UNAVAILABLE", message };
159
+ }
160
+ if (error?.code === "ENOENT" ||
161
+ /not found/i.test(message)) {
162
+ return { code: "NOT_FOUND", message };
163
+ }
164
+ if (/already exists/i.test(message)) {
165
+ return { code: "ALREADY_EXISTS", message };
166
+ }
167
+ if (/\blocked\b|is locked/i.test(message)) {
168
+ return { code: "LOCKED", message };
169
+ }
170
+ if (/invalid|required|must |only terminal|outside the artifact workspace/i.test(message)) {
171
+ return { code: "INVALID_INPUT", message };
172
+ }
173
+ return { code: "IO_ERROR", message };
174
+ }
175
+ export async function resultOf(work) {
176
+ try {
177
+ const value = await work();
178
+ if (typeof value === "object" &&
179
+ value !== null &&
180
+ "ok" in value) {
181
+ return value;
182
+ }
183
+ return { ok: true, value: value };
184
+ }
185
+ catch (error) {
186
+ return err(toError(error));
187
+ }
188
+ }
189
+ export function syncResultOf(work) {
190
+ try {
191
+ return { ok: true, value: work() };
192
+ }
193
+ catch (error) {
194
+ return err(toError(error));
195
+ }
196
+ }
197
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import type { EntityDocument, EntityType, NotebookCell, NotebookDocument, NotebookEdge, NotebookRun } from "./notebook/types.js";
2
+ import type { EngineError, Result, Revision } from "./engine-types.js";
3
+ import { EngineContext } from "./context.js";
4
+ type NewNotebookCell = Omit<NotebookCell, "id"> & {
5
+ id?: string;
6
+ };
7
+ type NewNotebookEdge = Omit<NotebookEdge, "id"> & {
8
+ id?: string;
9
+ };
10
+ export declare function createEntitiesApi(context: EngineContext): {
11
+ create: (type: EntityType, name: string, input?: Partial<EntityDocument>) => Promise<Result<EntityDocument, EngineError>>;
12
+ list: (type?: EntityType) => EntityDocument[];
13
+ read: (entityId: string) => Result<EntityDocument, EngineError>;
14
+ write: (entity: EntityDocument) => Promise<Result<Revision, EngineError>>;
15
+ delete: (entityId: string) => Promise<Result<{
16
+ entityId: string;
17
+ }, EngineError>>;
18
+ };
19
+ export declare function createNotebooksApi(context: EngineContext): {
20
+ create: (name: string) => Promise<Result<NotebookDocument, EngineError>>;
21
+ createCell: (input: NewNotebookCell) => NotebookCell;
22
+ createEdge: (input: NewNotebookEdge) => NotebookEdge;
23
+ list: () => NotebookDocument[];
24
+ read: (notebookId: string) => Result<NotebookDocument, EngineError>;
25
+ write: (notebook: NotebookDocument) => Promise<Result<Revision, EngineError>>;
26
+ delete: (notebookId: string) => Promise<Result<{
27
+ notebookId: string;
28
+ }, EngineError>>;
29
+ recordRun: (run: NotebookRun) => Promise<Result<Revision, EngineError>>;
30
+ };
31
+ export {};
32
+ //# sourceMappingURL=domain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domain.d.ts","sourceRoot":"","sources":["../src/domain.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,UAAU,EACV,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAEvE,OAAO,EACL,aAAa,EAGd,MAAM,cAAc,CAAC;AA0CtB,KAAK,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAClE,KAAK,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAElE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,aAAa;mBAG5C,UAAU,QACV,MAAM,UACL,OAAO,CAAC,cAAc,CAAC,KAC7B,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;kBAEjC,UAAU,KAAG,cAAc,EAAE;qBAC1B,MAAM,KAAG,MAAM,CAAC,cAAc,EAAE,WAAW,CAAC;oBAE7C,cAAc,KAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;uBAG3D,MAAM,KACf,OAAO,CAAC,MAAM,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,WAAW,CAAC,CAAC;EAGxD;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,aAAa;mBAEtC,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;wBAElD,eAAe,KAAG,YAAY;wBAI9B,eAAe,KAAG,YAAY;gBAIxC,gBAAgB,EAAE;uBACT,MAAM,KAAG,MAAM,CAAC,gBAAgB,EAAE,WAAW,CAAC;sBAGrD,gBAAgB,KACzB,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;yBAE3B,MAAM,KACjB,OAAO,CAAC,MAAM,CAAC;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,EAAE,WAAW,CAAC,CAAC;qBAEtC,WAAW,KAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;EAGxE"}