tiptap-apcore 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +407 -0
  2. package/dist/builder/AnnotationCatalog.d.ts +22 -0
  3. package/dist/builder/AnnotationCatalog.d.ts.map +1 -0
  4. package/dist/builder/AnnotationCatalog.js +269 -0
  5. package/dist/builder/AnnotationCatalog.js.map +1 -0
  6. package/dist/builder/ModuleBuilder.d.ts +42 -0
  7. package/dist/builder/ModuleBuilder.d.ts.map +1 -0
  8. package/dist/builder/ModuleBuilder.js +106 -0
  9. package/dist/builder/ModuleBuilder.js.map +1 -0
  10. package/dist/builder/SchemaCatalog.d.ts +20 -0
  11. package/dist/builder/SchemaCatalog.d.ts.map +1 -0
  12. package/dist/builder/SchemaCatalog.js +352 -0
  13. package/dist/builder/SchemaCatalog.js.map +1 -0
  14. package/dist/builder/index.d.ts +4 -0
  15. package/dist/builder/index.d.ts.map +1 -0
  16. package/dist/builder/index.js +5 -0
  17. package/dist/builder/index.js.map +1 -0
  18. package/dist/discovery/ExtensionScanner.d.ts +25 -0
  19. package/dist/discovery/ExtensionScanner.d.ts.map +1 -0
  20. package/dist/discovery/ExtensionScanner.js +61 -0
  21. package/dist/discovery/ExtensionScanner.js.map +1 -0
  22. package/dist/discovery/index.d.ts +2 -0
  23. package/dist/discovery/index.d.ts.map +1 -0
  24. package/dist/discovery/index.js +3 -0
  25. package/dist/discovery/index.js.map +1 -0
  26. package/dist/errors/TiptapModuleError.d.ts +18 -0
  27. package/dist/errors/TiptapModuleError.d.ts.map +1 -0
  28. package/dist/errors/TiptapModuleError.js +23 -0
  29. package/dist/errors/TiptapModuleError.js.map +1 -0
  30. package/dist/errors/index.d.ts +2 -0
  31. package/dist/errors/index.d.ts.map +1 -0
  32. package/dist/errors/index.js +2 -0
  33. package/dist/errors/index.js.map +1 -0
  34. package/dist/index.d.ts +19 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +17 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/runtime/TiptapExecutor.d.ts +20 -0
  39. package/dist/runtime/TiptapExecutor.d.ts.map +1 -0
  40. package/dist/runtime/TiptapExecutor.js +327 -0
  41. package/dist/runtime/TiptapExecutor.js.map +1 -0
  42. package/dist/runtime/TiptapRegistry.d.ts +35 -0
  43. package/dist/runtime/TiptapRegistry.d.ts.map +1 -0
  44. package/dist/runtime/TiptapRegistry.js +100 -0
  45. package/dist/runtime/TiptapRegistry.js.map +1 -0
  46. package/dist/runtime/index.d.ts +3 -0
  47. package/dist/runtime/index.d.ts.map +1 -0
  48. package/dist/runtime/index.js +4 -0
  49. package/dist/runtime/index.js.map +1 -0
  50. package/dist/security/AclGuard.d.ts +10 -0
  51. package/dist/security/AclGuard.d.ts.map +1 -0
  52. package/dist/security/AclGuard.js +96 -0
  53. package/dist/security/AclGuard.js.map +1 -0
  54. package/dist/security/index.d.ts +2 -0
  55. package/dist/security/index.d.ts.map +1 -0
  56. package/dist/security/index.js +2 -0
  57. package/dist/security/index.js.map +1 -0
  58. package/dist/server.d.ts +10 -0
  59. package/dist/server.d.ts.map +1 -0
  60. package/dist/server.js +9 -0
  61. package/dist/server.js.map +1 -0
  62. package/dist/types.d.ts +116 -0
  63. package/dist/types.d.ts.map +1 -0
  64. package/dist/types.js +8 -0
  65. package/dist/types.js.map +1 -0
  66. package/dist/withApcore.d.ts +14 -0
  67. package/dist/withApcore.d.ts.map +1 -0
  68. package/dist/withApcore.js +81 -0
  69. package/dist/withApcore.js.map +1 -0
  70. package/package.json +79 -0
@@ -0,0 +1,20 @@
1
+ import type { Executor, EditorLike } from "../types.js";
2
+ import type { TiptapRegistry } from "./TiptapRegistry.js";
3
+ import { AclGuard } from "../security/AclGuard.js";
4
+ export type { EditorLike, ChainLike } from "../types.js";
5
+ export declare class TiptapExecutor implements Executor {
6
+ readonly registry: TiptapRegistry;
7
+ private editor;
8
+ private aclGuard;
9
+ private sanitizeHtml;
10
+ constructor(editor: EditorLike, registry: TiptapRegistry, aclGuard: AclGuard, sanitizeHtml?: (html: string) => string);
11
+ call(moduleId: string, inputs: Record<string, unknown>): Promise<Record<string, unknown>>;
12
+ callAsync(moduleId: string, inputs: Record<string, unknown>): Promise<Record<string, unknown>>;
13
+ private extractCategory;
14
+ private extractCommandName;
15
+ private executeQuery;
16
+ private executeCommand;
17
+ private handleSelectText;
18
+ private buildArgs;
19
+ }
20
+ //# sourceMappingURL=TiptapExecutor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TiptapExecutor.d.ts","sourceRoot":"","sources":["../../src/runtime/TiptapExecutor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAa,MAAM,aAAa,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAInD,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AA4DzD,qBAAa,cAAe,YAAW,QAAQ;IAC7C,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,YAAY,CAAyC;gBAG3D,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,QAAQ,EAClB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM;IAQnC,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAuBzF,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAIpG,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,kBAAkB;IAM1B,OAAO,CAAC,YAAY;IAmDpB,OAAO,CAAC,cAAc;IAyCtB,OAAO,CAAC,gBAAgB;IAsCxB,OAAO,CAAC,SAAS;CAiHlB"}
@@ -0,0 +1,327 @@
1
+ import { TiptapModuleError, ErrorCodes } from "../errors/index.js";
2
+ // ── URL safety (C-1) ──────────────────────────────────────────────
3
+ const SAFE_PROTOCOLS = /^(https?|mailto|tel):/i;
4
+ const SAFE_RELATIVE = /^[/#?]/;
5
+ function isSafeUrl(url) {
6
+ if (typeof url !== "string")
7
+ return false;
8
+ const trimmed = url.trim();
9
+ return SAFE_PROTOCOLS.test(trimmed) || SAFE_RELATIVE.test(trimmed);
10
+ }
11
+ // ── Prototype pollution guard (C-2 + H-8) ─────────────────────────
12
+ const FORBIDDEN_PROPS = new Set([
13
+ "__proto__",
14
+ "constructor",
15
+ "prototype",
16
+ "toString",
17
+ "valueOf",
18
+ "hasOwnProperty",
19
+ ]);
20
+ // ── Input validation helpers (H-2) ────────────────────────────────
21
+ function requireString(inputs, field, moduleId) {
22
+ const val = inputs[field];
23
+ if (typeof val !== "string" || val.length === 0) {
24
+ throw new TiptapModuleError(ErrorCodes.SCHEMA_VALIDATION_ERROR, `'${field}' must be a non-empty string`, { moduleId, field });
25
+ }
26
+ return val;
27
+ }
28
+ function requireNumber(inputs, field, moduleId) {
29
+ const val = inputs[field];
30
+ if (typeof val !== "number" || !Number.isFinite(val)) {
31
+ throw new TiptapModuleError(ErrorCodes.SCHEMA_VALIDATION_ERROR, `'${field}' must be a finite number`, { moduleId, field });
32
+ }
33
+ return val;
34
+ }
35
+ // ── Executor ──────────────────────────────────────────────────────
36
+ export class TiptapExecutor {
37
+ registry;
38
+ editor;
39
+ aclGuard;
40
+ sanitizeHtml;
41
+ constructor(editor, registry, aclGuard, sanitizeHtml) {
42
+ this.editor = editor;
43
+ this.registry = registry;
44
+ this.aclGuard = aclGuard;
45
+ this.sanitizeHtml = sanitizeHtml;
46
+ }
47
+ async call(moduleId, inputs) {
48
+ // 1. Check editor ready
49
+ if (this.editor.isDestroyed) {
50
+ throw new TiptapModuleError(ErrorCodes.EDITOR_NOT_READY, "Editor is not ready", { editorDestroyed: true });
51
+ }
52
+ // 2. Resolve descriptor
53
+ const descriptor = this.registry.getDefinition(moduleId);
54
+ if (!descriptor) {
55
+ throw new TiptapModuleError(ErrorCodes.MODULE_NOT_FOUND, `Module '${moduleId}' not found`, { moduleId });
56
+ }
57
+ // 3. ACL check (throws ACL_DENIED)
58
+ this.aclGuard.check(moduleId, descriptor);
59
+ // 4. Route to handler
60
+ const category = this.extractCategory(moduleId);
61
+ if (category === "query") {
62
+ return this.executeQuery(moduleId, inputs);
63
+ }
64
+ return this.executeCommand(moduleId, inputs);
65
+ }
66
+ async callAsync(moduleId, inputs) {
67
+ return this.call(moduleId, inputs);
68
+ }
69
+ extractCategory(moduleId) {
70
+ // "tiptap.format.toggleBold" → "format"
71
+ const parts = moduleId.split(".");
72
+ return parts.length >= 2 ? parts[1] : "unknown";
73
+ }
74
+ extractCommandName(moduleId) {
75
+ // "tiptap.format.toggleBold" → "toggleBold"
76
+ const parts = moduleId.split(".");
77
+ return parts.length >= 3 ? parts[2] : moduleId;
78
+ }
79
+ executeQuery(moduleId, inputs) {
80
+ const commandName = this.extractCommandName(moduleId);
81
+ switch (commandName) {
82
+ case "getHTML":
83
+ return { html: this.editor.getHTML() };
84
+ case "getJSON":
85
+ return { json: this.editor.getJSON() };
86
+ case "getText": {
87
+ const options = {};
88
+ if (typeof inputs.blockSeparator === "string") {
89
+ options.blockSeparator = inputs.blockSeparator;
90
+ }
91
+ return { text: this.editor.getText(options) };
92
+ }
93
+ case "isActive": {
94
+ const name = requireString(inputs, "name", moduleId);
95
+ return { active: this.editor.isActive(name, inputs.attrs ?? {}) };
96
+ }
97
+ case "getAttributes": {
98
+ const typeOrName = requireString(inputs, "typeOrName", moduleId);
99
+ return { attributes: this.editor.getAttributes(typeOrName) };
100
+ }
101
+ case "isEmpty":
102
+ return { value: this.editor.isEmpty };
103
+ case "isEditable":
104
+ return { value: this.editor.isEditable };
105
+ case "isFocused":
106
+ return { value: this.editor.isFocused };
107
+ case "getCharacterCount": {
108
+ const cc = this.editor.storage?.characterCount;
109
+ if (!cc || typeof cc.characters !== "function") {
110
+ throw new TiptapModuleError(ErrorCodes.COMMAND_NOT_FOUND, "Character count extension not available", { moduleId, commandName });
111
+ }
112
+ return { count: cc.characters() };
113
+ }
114
+ case "getWordCount": {
115
+ const cc = this.editor.storage?.characterCount;
116
+ if (!cc || typeof cc.words !== "function") {
117
+ throw new TiptapModuleError(ErrorCodes.COMMAND_NOT_FOUND, "Character count extension not available", { moduleId, commandName });
118
+ }
119
+ return { count: cc.words() };
120
+ }
121
+ default:
122
+ throw new TiptapModuleError(ErrorCodes.COMMAND_NOT_FOUND, `Command '${commandName}' not available on editor`, { moduleId, commandName });
123
+ }
124
+ }
125
+ executeCommand(moduleId, inputs) {
126
+ const commandName = this.extractCommandName(moduleId);
127
+ // Built-in: selectText — find text content and set selection
128
+ if (commandName === "selectText") {
129
+ return this.handleSelectText(inputs, moduleId);
130
+ }
131
+ // C-2 + H-8: Prototype pollution / arbitrary command guard
132
+ if (FORBIDDEN_PROPS.has(commandName)) {
133
+ throw new TiptapModuleError(ErrorCodes.COMMAND_NOT_FOUND, `Command '${commandName}' is not allowed`, { moduleId, commandName });
134
+ }
135
+ // Build chain: editor.chain().focus().<commandName>(...args).run()
136
+ const chain = this.editor.chain().focus();
137
+ const commandFn = chain[commandName];
138
+ if (typeof commandFn !== "function") {
139
+ throw new TiptapModuleError(ErrorCodes.COMMAND_NOT_FOUND, `Command '${commandName}' not available on editor`, { moduleId, commandName });
140
+ }
141
+ // Spread input arguments into the command
142
+ const args = this.buildArgs(commandName, inputs, moduleId);
143
+ const resultChain = commandFn.call(chain, ...args);
144
+ const success = resultChain.run();
145
+ if (!success) {
146
+ // undo/redo return false when history stack is empty — this is a normal
147
+ // condition (editor is recreated per request), not an execution error.
148
+ if (commandName === "undo" || commandName === "redo") {
149
+ return { success: false, reason: `Nothing to ${commandName}` };
150
+ }
151
+ throw new TiptapModuleError(ErrorCodes.COMMAND_FAILED, `Command '${commandName}' failed`, { moduleId, commandName });
152
+ }
153
+ return { success: true };
154
+ }
155
+ handleSelectText(inputs, moduleId) {
156
+ const text = requireString(inputs, "text", moduleId);
157
+ const occurrence = typeof inputs.occurrence === "number" ? Math.max(1, inputs.occurrence) : 1;
158
+ const doc = this.editor.state.doc;
159
+ let count = 0;
160
+ let foundFrom = -1;
161
+ let foundTo = -1;
162
+ doc.descendants((node, pos) => {
163
+ if (foundFrom >= 0)
164
+ return false;
165
+ if (node.isText && node.text) {
166
+ let searchFrom = 0;
167
+ while (searchFrom < node.text.length) {
168
+ const idx = node.text.indexOf(text, searchFrom);
169
+ if (idx === -1)
170
+ break;
171
+ count++;
172
+ if (count === occurrence) {
173
+ foundFrom = pos + idx;
174
+ foundTo = foundFrom + text.length;
175
+ return false;
176
+ }
177
+ searchFrom = idx + 1;
178
+ }
179
+ }
180
+ });
181
+ if (foundFrom < 0) {
182
+ return { found: false };
183
+ }
184
+ // Set text selection around the found text
185
+ const chain = this.editor.chain().focus();
186
+ chain.setTextSelection({ from: foundFrom, to: foundTo }).run();
187
+ return { found: true, from: foundFrom, to: foundTo };
188
+ }
189
+ buildArgs(commandName, inputs, moduleId) {
190
+ // Map input object fields to positional command arguments based on command name
191
+ // Most commands take 0 or 1 args
192
+ switch (commandName) {
193
+ // Commands with no args
194
+ case "toggleBold":
195
+ case "toggleItalic":
196
+ case "toggleStrike":
197
+ case "toggleCode":
198
+ case "toggleUnderline":
199
+ case "toggleSubscript":
200
+ case "toggleSuperscript":
201
+ case "toggleBulletList":
202
+ case "toggleOrderedList":
203
+ case "toggleTaskList":
204
+ case "toggleBlockquote":
205
+ case "unsetAllMarks":
206
+ case "clearNodes":
207
+ case "setHardBreak":
208
+ case "setHorizontalRule":
209
+ case "unsetLink":
210
+ case "selectAll":
211
+ case "selectParentNode":
212
+ case "selectTextblockStart":
213
+ case "selectTextblockEnd":
214
+ case "blur":
215
+ case "scrollIntoView":
216
+ case "undo":
217
+ case "redo":
218
+ case "deleteSelection":
219
+ case "deleteCurrentNode":
220
+ case "cut":
221
+ case "joinBackward":
222
+ case "joinForward":
223
+ case "setBold":
224
+ case "unsetBold":
225
+ case "setItalic":
226
+ case "unsetItalic":
227
+ case "setStrike":
228
+ case "unsetStrike":
229
+ case "setCode":
230
+ case "unsetCode":
231
+ case "setBlockquote":
232
+ case "unsetBlockquote":
233
+ case "setParagraph":
234
+ case "exitCode":
235
+ return [];
236
+ case "splitBlock":
237
+ return inputs.keepMarks !== undefined ? [{ keepMarks: inputs.keepMarks }] : [];
238
+ // Commands with single object arg
239
+ case "toggleHeading":
240
+ return [{ level: inputs.level }];
241
+ case "setHeading":
242
+ return [{ level: inputs.level }];
243
+ case "toggleHighlight":
244
+ return inputs.color ? [{ color: inputs.color }] : [];
245
+ case "toggleCodeBlock":
246
+ return inputs.language ? [{ language: inputs.language }] : [];
247
+ case "setTextAlign":
248
+ return [inputs.alignment];
249
+ case "setMark":
250
+ return [inputs.typeOrName, inputs.attrs ?? {}];
251
+ case "unsetMark":
252
+ return [inputs.typeOrName];
253
+ case "updateAttributes":
254
+ return [inputs.typeOrName, inputs.attrs];
255
+ case "setLink": {
256
+ // C-1: URL protocol validation
257
+ if (!isSafeUrl(inputs.href)) {
258
+ throw new TiptapModuleError(ErrorCodes.SCHEMA_VALIDATION_ERROR, "Invalid or unsafe URL protocol", { field: "href" });
259
+ }
260
+ const linkAttrs = { href: inputs.href };
261
+ if (inputs.target !== undefined)
262
+ linkAttrs.target = inputs.target;
263
+ if (inputs.rel !== undefined)
264
+ linkAttrs.rel = inputs.rel;
265
+ return [linkAttrs];
266
+ }
267
+ // Content commands — H-1: sanitize HTML
268
+ case "insertContent": {
269
+ let value = inputs.value;
270
+ if (typeof value === "string" && this.sanitizeHtml) {
271
+ value = this.sanitizeHtml(value);
272
+ }
273
+ return [value, inputs.options ?? {}];
274
+ }
275
+ case "insertContentAt": {
276
+ const position = requireNumber(inputs, "position", moduleId);
277
+ let value = inputs.value;
278
+ if (typeof value === "string" && this.sanitizeHtml) {
279
+ value = this.sanitizeHtml(value);
280
+ }
281
+ return [position, value, inputs.options ?? {}];
282
+ }
283
+ case "setNode":
284
+ return [inputs.typeOrName, inputs.attrs ?? {}];
285
+ case "liftListItem":
286
+ case "sinkListItem":
287
+ return [inputs.typeOrName];
288
+ case "wrapIn":
289
+ return [inputs.typeOrName, inputs.attrs ?? {}];
290
+ case "lift":
291
+ return [inputs.typeOrName, inputs.attrs ?? {}];
292
+ case "splitListItem":
293
+ return [inputs.typeOrName, inputs.overrideAttrs ?? {}];
294
+ case "wrapInList":
295
+ return [inputs.typeOrName, inputs.attributes ?? {}];
296
+ case "toggleList":
297
+ return [inputs.listTypeOrName, inputs.itemTypeOrName, inputs.keepMarks ?? false, inputs.attributes ?? {}];
298
+ case "deleteNode":
299
+ return [inputs.typeOrName];
300
+ // Destructive commands
301
+ case "clearContent":
302
+ return inputs.emitUpdate !== undefined ? [inputs.emitUpdate] : [];
303
+ case "setContent": {
304
+ let value = inputs.value;
305
+ if (typeof value === "string" && this.sanitizeHtml) {
306
+ value = this.sanitizeHtml(value);
307
+ }
308
+ return [value, inputs.emitUpdate ?? true, inputs.parseOptions ?? {}];
309
+ }
310
+ case "deleteRange":
311
+ return [{ from: inputs.from, to: inputs.to }];
312
+ // Selection commands
313
+ case "setTextSelection":
314
+ return [inputs.position];
315
+ case "setNodeSelection": {
316
+ const position = requireNumber(inputs, "position", moduleId);
317
+ return [position];
318
+ }
319
+ case "focus":
320
+ return inputs.position !== undefined ? [inputs.position] : [];
321
+ default:
322
+ // Unknown commands: pass all inputs as single object arg
323
+ return Object.keys(inputs).length > 0 ? [inputs] : [];
324
+ }
325
+ }
326
+ }
327
+ //# sourceMappingURL=TiptapExecutor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TiptapExecutor.js","sourceRoot":"","sources":["../../src/runtime/TiptapExecutor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import type { Registry, ModuleDescriptor } from "../types.js";
2
+ /**
3
+ * TiptapRegistry implements the APCore Registry interface.
4
+ *
5
+ * Manages module descriptors with event-driven registration/unregistration
6
+ * and supports filtering by tags (OR logic) and/or prefix (startsWith).
7
+ */
8
+ export declare class TiptapRegistry implements Registry {
9
+ private modules;
10
+ private handlers;
11
+ private scanFn;
12
+ register(descriptor: ModuleDescriptor): void;
13
+ unregister(moduleId: string): void;
14
+ list(options?: {
15
+ tags?: string[] | null;
16
+ prefix?: string | null;
17
+ }): string[];
18
+ getDefinition(moduleId: string): ModuleDescriptor | null;
19
+ has(moduleId: string): boolean;
20
+ /** Returns an iterator over [moduleId, descriptor] pairs. */
21
+ iter(): IterableIterator<[string, ModuleDescriptor]>;
22
+ /** Number of registered modules. */
23
+ get count(): number;
24
+ /** Array of all registered module IDs. */
25
+ get moduleIds(): string[];
26
+ /** Clears any internal caches (no-op for now, reserved for future use). */
27
+ clearCache(): void;
28
+ on(event: string, callback: (...args: unknown[]) => void): () => void;
29
+ off(event: string, callback: (...args: unknown[]) => void): void;
30
+ removeAllListeners(event?: string): void;
31
+ discover(): Promise<number>;
32
+ setScanFunction(fn: () => number | Promise<number>): void;
33
+ private emit;
34
+ }
35
+ //# sourceMappingURL=TiptapRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TiptapRegistry.d.ts","sourceRoot":"","sources":["../../src/runtime/TiptapRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE9D;;;;;GAKG;AACH,qBAAa,cAAe,YAAW,QAAQ;IAC7C,OAAO,CAAC,OAAO,CAA4C;IAC3D,OAAO,CAAC,QAAQ,CACJ;IACZ,OAAO,CAAC,MAAM,CAAiD;IAE/D,QAAQ,CAAC,UAAU,EAAE,gBAAgB,GAAG,IAAI;IAK5C,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKlC,IAAI,CAAC,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,MAAM,EAAE;IAyB5E,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI;IAIxD,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAI9B,6DAA6D;IAC7D,IAAI,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAIpD,oCAAoC;IACpC,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,0CAA0C;IAC1C,IAAI,SAAS,IAAI,MAAM,EAAE,CAExB;IAED,2EAA2E;IAC3E,UAAU,IAAI,IAAI;IAKlB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,MAAM,IAAI;IAQrE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI;IAOhE,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAQlC,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC;IAOjC,eAAe,CAAC,EAAE,EAAE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI;IAIzD,OAAO,CAAC,IAAI;CAMb"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * TiptapRegistry implements the APCore Registry interface.
3
+ *
4
+ * Manages module descriptors with event-driven registration/unregistration
5
+ * and supports filtering by tags (OR logic) and/or prefix (startsWith).
6
+ */
7
+ export class TiptapRegistry {
8
+ modules = new Map();
9
+ handlers = new Map();
10
+ scanFn = null;
11
+ register(descriptor) {
12
+ this.modules.set(descriptor.moduleId, descriptor);
13
+ this.emit("register", descriptor.moduleId, descriptor);
14
+ }
15
+ unregister(moduleId) {
16
+ this.modules.delete(moduleId);
17
+ this.emit("unregister", moduleId);
18
+ }
19
+ list(options) {
20
+ let ids = Array.from(this.modules.keys());
21
+ if (!options) {
22
+ return ids;
23
+ }
24
+ const { tags, prefix } = options;
25
+ if (tags && tags.length > 0) {
26
+ ids = ids.filter((id) => {
27
+ const descriptor = this.modules.get(id);
28
+ const moduleTags = descriptor.tags ?? [];
29
+ // OR logic: module matches if it has ANY of the requested tags
30
+ return tags.some((tag) => moduleTags.includes(tag));
31
+ });
32
+ }
33
+ if (prefix) {
34
+ ids = ids.filter((id) => id.startsWith(prefix));
35
+ }
36
+ return ids;
37
+ }
38
+ getDefinition(moduleId) {
39
+ return this.modules.get(moduleId) ?? null;
40
+ }
41
+ has(moduleId) {
42
+ return this.modules.has(moduleId);
43
+ }
44
+ /** Returns an iterator over [moduleId, descriptor] pairs. */
45
+ iter() {
46
+ return this.modules.entries();
47
+ }
48
+ /** Number of registered modules. */
49
+ get count() {
50
+ return this.modules.size;
51
+ }
52
+ /** Array of all registered module IDs. */
53
+ get moduleIds() {
54
+ return Array.from(this.modules.keys());
55
+ }
56
+ /** Clears any internal caches (no-op for now, reserved for future use). */
57
+ clearCache() {
58
+ // TiptapRegistry has no caches currently; method provided for API parity
59
+ // with apcore-js Registry.
60
+ }
61
+ on(event, callback) {
62
+ if (!this.handlers.has(event)) {
63
+ this.handlers.set(event, []);
64
+ }
65
+ this.handlers.get(event).push(callback);
66
+ return () => this.off(event, callback);
67
+ }
68
+ off(event, callback) {
69
+ const callbacks = this.handlers.get(event);
70
+ if (!callbacks)
71
+ return;
72
+ const idx = callbacks.indexOf(callback);
73
+ if (idx !== -1)
74
+ callbacks.splice(idx, 1);
75
+ }
76
+ removeAllListeners(event) {
77
+ if (event) {
78
+ this.handlers.delete(event);
79
+ }
80
+ else {
81
+ this.handlers.clear();
82
+ }
83
+ }
84
+ async discover() {
85
+ if (this.scanFn) {
86
+ return this.scanFn();
87
+ }
88
+ return this.modules.size;
89
+ }
90
+ setScanFunction(fn) {
91
+ this.scanFn = fn;
92
+ }
93
+ emit(event, ...args) {
94
+ const callbacks = this.handlers.get(event);
95
+ if (callbacks) {
96
+ callbacks.forEach((cb) => cb(...args));
97
+ }
98
+ }
99
+ }
100
+ //# sourceMappingURL=TiptapRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TiptapRegistry.js","sourceRoot":"","sources":["../../src/runtime/TiptapRegistry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { TiptapRegistry } from "./TiptapRegistry.js";
2
+ export { TiptapExecutor } from "./TiptapExecutor.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,4 @@
1
+ // Runtime layer - TiptapRegistry, TiptapExecutor (Tasks 6, 9)
2
+ export { TiptapRegistry } from "./TiptapRegistry.js";
3
+ export { TiptapExecutor } from "./TiptapExecutor.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { AclConfig, Logger, ModuleDescriptor } from "../types.js";
2
+ export declare class AclGuard {
3
+ private config;
4
+ private logger;
5
+ constructor(config?: AclConfig, logger?: Logger);
6
+ check(moduleId: string, descriptor: ModuleDescriptor): void;
7
+ isAllowed(moduleId: string, descriptor: ModuleDescriptor): boolean;
8
+ private getDenialReason;
9
+ }
10
+ //# sourceMappingURL=AclGuard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AclGuard.d.ts","sourceRoot":"","sources":["../../src/security/AclGuard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AASvE,qBAAa,QAAQ;IACnB,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,MAAM,CAAqB;gBAEvB,MAAM,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,MAAM;IAK/C,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,gBAAgB,GAAG,IAAI;IAY3D,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,gBAAgB,GAAG,OAAO;IAwClE,OAAO,CAAC,eAAe;CAgDxB"}
@@ -0,0 +1,96 @@
1
+ import { TiptapModuleError, ErrorCodes } from "../errors/index.js";
2
+ const ROLE_TAGS = {
3
+ readonly: ["query"],
4
+ editor: ["query", "format", "content", "history", "selection"],
5
+ admin: ["query", "format", "content", "destructive", "history", "selection"],
6
+ };
7
+ export class AclGuard {
8
+ config;
9
+ logger;
10
+ constructor(config, logger) {
11
+ this.config = config;
12
+ this.logger = logger;
13
+ }
14
+ check(moduleId, descriptor) {
15
+ if (!this.isAllowed(moduleId, descriptor)) {
16
+ const reason = this.getDenialReason(moduleId, descriptor);
17
+ this.logger?.warn(`ACL denied: ${moduleId}`, { reason });
18
+ throw new TiptapModuleError(ErrorCodes.ACL_DENIED, `Access denied: module '${moduleId}' is not permitted`, { moduleId });
19
+ }
20
+ }
21
+ isAllowed(moduleId, descriptor) {
22
+ // No ACL config = all allowed (opt-in security)
23
+ if (!this.config)
24
+ return true;
25
+ const { denyModules, allowModules, denyTags, allowTags, role } = this.config;
26
+ const moduleTags = descriptor.tags ?? [];
27
+ // 1. denyModules (highest precedence)
28
+ if (denyModules?.includes(moduleId))
29
+ return false;
30
+ // 2. allowModules
31
+ if (allowModules && allowModules.length > 0) {
32
+ if (allowModules.includes(moduleId))
33
+ return true;
34
+ }
35
+ // 3. denyTags
36
+ if (denyTags && denyTags.length > 0) {
37
+ if (moduleTags.some((t) => denyTags.includes(t)))
38
+ return false;
39
+ }
40
+ // 4. allowTags
41
+ if (allowTags && allowTags.length > 0) {
42
+ if (moduleTags.some((t) => allowTags.includes(t)))
43
+ return true;
44
+ }
45
+ // 5. Role-based
46
+ if (role) {
47
+ const roleTags = ROLE_TAGS[role];
48
+ if (!roleTags)
49
+ return false;
50
+ return moduleTags.some((t) => roleTags.includes(t));
51
+ }
52
+ // 6. If any allow-list is present, default to deny; otherwise permissive
53
+ const hasAllowList = (allowModules && allowModules.length > 0) ||
54
+ (allowTags && allowTags.length > 0);
55
+ return !hasAllowList;
56
+ }
57
+ getDenialReason(moduleId, descriptor) {
58
+ if (!this.config)
59
+ return "No ACL config";
60
+ const { denyModules, denyTags, allowTags, allowModules, role } = this.config;
61
+ const moduleTags = descriptor.tags ?? [];
62
+ // 1. denyModules
63
+ if (denyModules?.includes(moduleId)) {
64
+ return `Module '${moduleId}' is in the denyModules list`;
65
+ }
66
+ // 2. allowModules set but module not in it
67
+ if (allowModules && allowModules.length > 0) {
68
+ if (!allowModules.includes(moduleId)) {
69
+ return `Module '${moduleId}' is not in the allowModules list`;
70
+ }
71
+ }
72
+ // 3. denyTags
73
+ if (denyTags && denyTags.length > 0) {
74
+ const denied = moduleTags.filter((t) => denyTags.includes(t));
75
+ if (denied.length > 0) {
76
+ return `Module tags [${denied.join(", ")}] are in the denyTags list`;
77
+ }
78
+ }
79
+ // 4. allowTags set but no overlap
80
+ if (allowTags && allowTags.length > 0) {
81
+ if (!moduleTags.some((t) => allowTags.includes(t))) {
82
+ return `Module tags [${moduleTags.join(", ")}] are not in the allowTags list`;
83
+ }
84
+ }
85
+ // 5. Role-based denial
86
+ if (role) {
87
+ const roleTags = ROLE_TAGS[role];
88
+ if (!roleTags) {
89
+ return `Unknown role '${role}'`;
90
+ }
91
+ return `Role '${role}' does not permit tags [${moduleTags.join(", ")}]`;
92
+ }
93
+ return "Access denied by policy";
94
+ }
95
+ }
96
+ //# sourceMappingURL=AclGuard.js.map