@w100n/documents 0.4.0 → 0.11.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 (61) hide show
  1. package/dist/SheetView-3XTEV2VT.css +319 -0
  2. package/dist/SheetView-3XTEV2VT.css.map +1 -0
  3. package/dist/SheetView-TXHS5WJC.js +928 -0
  4. package/dist/SheetView-TXHS5WJC.js.map +1 -0
  5. package/dist/TextEditor-4YETNX4T.js +983 -0
  6. package/dist/TextEditor-4YETNX4T.js.map +1 -0
  7. package/dist/caveat-cyrillic-XVO43JCM.woff2 +0 -0
  8. package/dist/caveat-latin-IUBKKMHQ.woff2 +0 -0
  9. package/dist/caveat-latin-ext-5S7R5SZN.woff2 +0 -0
  10. package/dist/chunk-EM4U6OC5.js +3447 -0
  11. package/dist/chunk-EM4U6OC5.js.map +1 -0
  12. package/dist/chunk-FPGPEIW5.js +196 -0
  13. package/dist/chunk-FPGPEIW5.js.map +1 -0
  14. package/dist/chunk-ISOOUYLI.js +150 -0
  15. package/dist/chunk-ISOOUYLI.js.map +1 -0
  16. package/dist/{chunk-KEV4R7W5.js → chunk-L765DZPO.js} +9 -1
  17. package/dist/chunk-L765DZPO.js.map +1 -0
  18. package/dist/chunk-QDH7EZAF.js +27 -0
  19. package/dist/chunk-QDH7EZAF.js.map +1 -0
  20. package/dist/chunk-TDP6OJET.js +31 -0
  21. package/dist/chunk-TDP6OJET.js.map +1 -0
  22. package/dist/chunk-TNSN4ZQ5.js +2909 -0
  23. package/dist/chunk-TNSN4ZQ5.js.map +1 -0
  24. package/dist/collab.cjs +6312 -0
  25. package/dist/collab.cjs.map +1 -0
  26. package/dist/collab.d.cts +39 -0
  27. package/dist/collab.d.ts +39 -0
  28. package/dist/collab.js +30 -0
  29. package/dist/collab.js.map +1 -0
  30. package/dist/grid-EI5JNZAA.js +88 -0
  31. package/dist/grid-EI5JNZAA.js.map +1 -0
  32. package/dist/index.cjs +12191 -486
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.css +3632 -728
  35. package/dist/index.css.map +1 -1
  36. package/dist/index.d.cts +144 -11
  37. package/dist/index.d.ts +144 -11
  38. package/dist/index.js +3389 -439
  39. package/dist/index.js.map +1 -1
  40. package/dist/kinds.cjs +71 -0
  41. package/dist/kinds.cjs.map +1 -0
  42. package/dist/kinds.d.cts +11 -0
  43. package/dist/kinds.d.ts +11 -0
  44. package/dist/kinds.js +14 -0
  45. package/dist/kinds.js.map +1 -0
  46. package/dist/memory.cjs +59 -7
  47. package/dist/memory.cjs.map +1 -1
  48. package/dist/memory.d.cts +7 -2
  49. package/dist/memory.d.ts +7 -2
  50. package/dist/memory.js +57 -8
  51. package/dist/memory.js.map +1 -1
  52. package/dist/pdfWrite-EM6GJDBF.js +76 -0
  53. package/dist/pdfWrite-EM6GJDBF.js.map +1 -0
  54. package/dist/types-B5oF25dn.d.cts +165 -0
  55. package/dist/types-B5oF25dn.d.ts +165 -0
  56. package/dist/write-DaVtTJCS.d.cts +6 -0
  57. package/dist/write-DaVtTJCS.d.ts +6 -0
  58. package/package.json +50 -3
  59. package/dist/chunk-KEV4R7W5.js.map +0 -1
  60. package/dist/types-DshXPnWA.d.cts +0 -62
  61. package/dist/types-DshXPnWA.d.ts +0 -62
package/dist/kinds.cjs ADDED
@@ -0,0 +1,71 @@
1
+ 'use client';
2
+ "use strict";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/kinds.ts
22
+ var kinds_exports = {};
23
+ __export(kinds_exports, {
24
+ kindOf: () => kindOf,
25
+ kinds: () => kinds,
26
+ matches: () => matches,
27
+ readable: () => readable
28
+ });
29
+ module.exports = __toCommonJS(kinds_exports);
30
+ var byExtension = {
31
+ docx: "docx",
32
+ md: "markdown",
33
+ markdown: "markdown",
34
+ pdf: "pdf",
35
+ xlsx: "sheet",
36
+ csv: "sheet",
37
+ xls: "sheet",
38
+ ods: "sheet",
39
+ tsv: "sheet",
40
+ html: "slides",
41
+ htm: "slides"
42
+ };
43
+ var byMime = {
44
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
45
+ "text/markdown": "markdown",
46
+ "application/pdf": "pdf",
47
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "sheet",
48
+ "text/csv": "sheet",
49
+ "text/html": "slides"
50
+ };
51
+ var kinds = ["docx", "markdown", "pdf", "sheet", "slides"];
52
+ function kindOf(name, mimeType) {
53
+ const extension = name.includes(".") ? name.split(".").pop().toLowerCase() : "";
54
+ return byExtension[extension] ?? (mimeType ? byMime[mimeType.split(";")[0].trim().toLowerCase()] : void 0) ?? null;
55
+ }
56
+ function readable(name, mimeType) {
57
+ const kind = kindOf(name, mimeType);
58
+ return kind !== "sheet" || /\.(xlsx|csv)$/i.test(name) || /spreadsheetml|text\/csv/.test(mimeType ?? "") ? kind : null;
59
+ }
60
+ function matches(doc, query, kind) {
61
+ const words = query.toLocaleLowerCase().split(/\s+/).filter(Boolean);
62
+ return (kind === "all" || doc.kind === kind) && words.every((word) => doc.name.toLocaleLowerCase().includes(word));
63
+ }
64
+ // Annotate the CommonJS export names for ESM import in node:
65
+ 0 && (module.exports = {
66
+ kindOf,
67
+ kinds,
68
+ matches,
69
+ readable
70
+ });
71
+ //# sourceMappingURL=kinds.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/kinds.ts"],"sourcesContent":["import type { DocumentKind } from './types';\n\nconst byExtension: Record<string, DocumentKind> = {\n docx: 'docx', md: 'markdown', markdown: 'markdown', pdf: 'pdf', xlsx: 'sheet', csv: 'sheet', xls: 'sheet', ods: 'sheet', tsv: 'sheet', html: 'slides', htm: 'slides',\n};\n\nconst byMime: Record<string, DocumentKind> = {\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'docx',\n 'text/markdown': 'markdown',\n 'application/pdf': 'pdf',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'sheet',\n 'text/csv': 'sheet',\n 'text/html': 'slides',\n};\n\nexport const kinds: DocumentKind[] = ['docx', 'markdown', 'pdf', 'sheet', 'slides'];\n\nexport function kindOf(name: string, mimeType?: string | null): DocumentKind | null {\n const extension = name.includes('.') ? name.split('.').pop()!.toLowerCase() : '';\n return byExtension[extension] ?? (mimeType ? byMime[mimeType.split(';')[0].trim().toLowerCase()] : undefined) ?? null;\n}\n\nexport function readable(name: string, mimeType?: string | null): DocumentKind | null {\n const kind = kindOf(name, mimeType);\n return kind !== 'sheet' || /\\.(xlsx|csv)$/i.test(name) || /spreadsheetml|text\\/csv/.test(mimeType ?? '') ? kind : null;\n}\n\nexport function matches(doc: { name: string; kind: DocumentKind }, query: string, kind: DocumentKind | 'all') {\n const words = query.toLocaleLowerCase().split(/\\s+/).filter(Boolean);\n return (kind === 'all' || doc.kind === kind) && words.every(word => doc.name.toLocaleLowerCase().includes(word));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,IAAM,cAA4C;AAAA,EAChD,MAAM;AAAA,EAAQ,IAAI;AAAA,EAAY,UAAU;AAAA,EAAY,KAAK;AAAA,EAAO,MAAM;AAAA,EAAS,KAAK;AAAA,EAAS,KAAK;AAAA,EAAS,KAAK;AAAA,EAAS,KAAK;AAAA,EAAS,MAAM;AAAA,EAAU,KAAK;AAC9J;AAEA,IAAM,SAAuC;AAAA,EAC3C,2EAA2E;AAAA,EAC3E,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,qEAAqE;AAAA,EACrE,YAAY;AAAA,EACZ,aAAa;AACf;AAEO,IAAM,QAAwB,CAAC,QAAQ,YAAY,OAAO,SAAS,QAAQ;AAE3E,SAAS,OAAO,MAAc,UAA+C;AAClF,QAAM,YAAY,KAAK,SAAS,GAAG,IAAI,KAAK,MAAM,GAAG,EAAE,IAAI,EAAG,YAAY,IAAI;AAC9E,SAAO,YAAY,SAAS,MAAM,WAAW,OAAO,SAAS,MAAM,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,IAAI,WAAc;AACnH;AAEO,SAAS,SAAS,MAAc,UAA+C;AACpF,QAAM,OAAO,OAAO,MAAM,QAAQ;AAClC,SAAO,SAAS,WAAW,iBAAiB,KAAK,IAAI,KAAK,0BAA0B,KAAK,YAAY,EAAE,IAAI,OAAO;AACpH;AAEO,SAAS,QAAQ,KAA2C,OAAe,MAA4B;AAC5G,QAAM,QAAQ,MAAM,kBAAkB,EAAE,MAAM,KAAK,EAAE,OAAO,OAAO;AACnE,UAAQ,SAAS,SAAS,IAAI,SAAS,SAAS,MAAM,MAAM,UAAQ,IAAI,KAAK,kBAAkB,EAAE,SAAS,IAAI,CAAC;AACjH;","names":[]}
@@ -0,0 +1,11 @@
1
+ import { b as DocumentKind } from './types-B5oF25dn.cjs';
2
+
3
+ declare const kinds: DocumentKind[];
4
+ declare function kindOf(name: string, mimeType?: string | null): DocumentKind | null;
5
+ declare function readable(name: string, mimeType?: string | null): DocumentKind | null;
6
+ declare function matches(doc: {
7
+ name: string;
8
+ kind: DocumentKind;
9
+ }, query: string, kind: DocumentKind | 'all'): boolean;
10
+
11
+ export { kindOf, kinds, matches, readable };
@@ -0,0 +1,11 @@
1
+ import { b as DocumentKind } from './types-B5oF25dn.js';
2
+
3
+ declare const kinds: DocumentKind[];
4
+ declare function kindOf(name: string, mimeType?: string | null): DocumentKind | null;
5
+ declare function readable(name: string, mimeType?: string | null): DocumentKind | null;
6
+ declare function matches(doc: {
7
+ name: string;
8
+ kind: DocumentKind;
9
+ }, query: string, kind: DocumentKind | 'all'): boolean;
10
+
11
+ export { kindOf, kinds, matches, readable };
package/dist/kinds.js ADDED
@@ -0,0 +1,14 @@
1
+ 'use client';
2
+ import {
3
+ kindOf,
4
+ kinds,
5
+ matches,
6
+ readable
7
+ } from "./chunk-L765DZPO.js";
8
+ export {
9
+ kindOf,
10
+ kinds,
11
+ matches,
12
+ readable
13
+ };
14
+ //# sourceMappingURL=kinds.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/dist/memory.cjs CHANGED
@@ -33,6 +33,9 @@ var byExtension = {
33
33
  pdf: "pdf",
34
34
  xlsx: "sheet",
35
35
  csv: "sheet",
36
+ xls: "sheet",
37
+ ods: "sheet",
38
+ tsv: "sheet",
36
39
  html: "slides",
37
40
  htm: "slides"
38
41
  };
@@ -50,13 +53,19 @@ function kindOf(name, mimeType) {
50
53
  }
51
54
 
52
55
  // src/memory.ts
56
+ var mimes = { pdf: "application/pdf", docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", md: "text/markdown" };
53
57
  var encode = (bytes) => typeof bytes === "string" ? new TextEncoder().encode(bytes).buffer : bytes;
54
- function memoryHost({ me, spaces, files }) {
58
+ function memoryHost({ me, spaces, files, collab }) {
55
59
  const find = (id) => {
56
60
  const file = files.find((item) => item.id === id);
57
61
  if (!file) throw new Error("document not found");
58
62
  return file;
59
63
  };
64
+ const own = (file, commentId) => {
65
+ const found = file.comments?.find((c) => c.id === commentId);
66
+ if (!found || found.author.id !== me.id) throw new Error("only the author changes a comment");
67
+ return found;
68
+ };
60
69
  const summary = (file) => ({
61
70
  id: file.id,
62
71
  spaceId: file.spaceId,
@@ -67,30 +76,73 @@ function memoryHost({ me, spaces, files }) {
67
76
  updatedBy: me,
68
77
  folder: file.folder ?? null
69
78
  });
79
+ const archive = (file, bytes, note) => {
80
+ const versions = [{ id: file.version ?? `v${(file.versions?.length ?? 0) + 1}`, createdAt: file.updatedAt ?? "2026-10-19T09:00:00Z", bytes: file.bytes, note: file.note }, ...file.versions ?? []];
81
+ const version = `v${versions.length + 1}`;
82
+ Object.assign(file, { versions, version, bytes, note, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
83
+ return version;
84
+ };
70
85
  return {
71
86
  me,
87
+ ...collab ? { collab: { url: `memory:${collab}`, token: async () => me.id } } : {},
72
88
  spaces: async () => spaces,
73
89
  documents: async (spaceId) => files.filter((file) => file.spaceId === spaceId && kindOf(file.name)).map(summary),
74
- document: async (id) => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights } }),
90
+ document: async (id) => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights }, live: !!collab }),
75
91
  versions: async (id) => {
76
92
  const file = find(id);
77
93
  return [
78
- { id: "current", createdAt: summary(file).updatedAt, size: summary(file).size, author: me, current: true },
94
+ { id: file.version ?? "current", createdAt: summary(file).updatedAt, size: summary(file).size, author: me, note: file.note ?? null, current: true },
79
95
  ...(file.versions ?? []).map((v) => ({ id: v.id, createdAt: v.createdAt, size: encode(v.bytes).byteLength, author: me, note: v.note ?? null, current: false }))
80
96
  ];
81
97
  },
82
98
  content: async (id, versionId) => {
83
99
  const file = find(id);
84
- const old = versionId && versionId !== "current" ? file.versions?.find((v) => v.id === versionId) : void 0;
100
+ const old = versionId && versionId !== "current" && versionId !== file.version ? file.versions?.find((v) => v.id === versionId) : void 0;
85
101
  return encode(old ? old.bytes : file.bytes);
86
102
  },
87
103
  restore: async (id, versionId) => {
88
104
  const file = find(id);
89
105
  const old = file.versions?.find((v) => v.id === versionId);
90
106
  if (!old) throw new Error("version not found");
91
- file.versions = [{ id: `v${(file.versions?.length ?? 0) + 1}`, createdAt: file.updatedAt ?? "2026-10-19T09:00:00Z", bytes: file.bytes }, ...file.versions ?? []];
92
- file.bytes = old.bytes;
93
- file.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
107
+ archive(file, old.bytes);
108
+ },
109
+ save: async (id, bytes, note) => ({ versionId: archive(find(id), bytes, note) }),
110
+ signatures: async (id) => [...find(id).signatures ?? []].reverse(),
111
+ sign: async (id, entry) => {
112
+ const file = find(id);
113
+ const signature = { id: `s${(file.signatures?.length ?? 0) + 1}`, signer: me, signedAt: (/* @__PURE__ */ new Date()).toISOString(), ...entry };
114
+ file.signatures = [...file.signatures ?? [], signature];
115
+ return signature;
116
+ },
117
+ comments: async (id) => [...find(id).comments ?? []],
118
+ comment: async (id, entry) => {
119
+ const file = find(id);
120
+ let n = (file.comments?.length ?? 0) + 1;
121
+ while (file.comments?.some((c) => c.id === `c${n}`)) n++;
122
+ const made = { id: `c${n}`, documentId: id, author: me, body: entry.body, createdAt: (/* @__PURE__ */ new Date()).toISOString(), quote: entry.quote, replyTo: entry.replyTo, resolved: false };
123
+ file.comments = [...file.comments ?? [], made];
124
+ return made;
125
+ },
126
+ resolveComment: async (id, commentId, resolved) => {
127
+ const file = find(id);
128
+ file.comments = (file.comments ?? []).map((c) => c.id === commentId ? { ...c, resolved } : c);
129
+ },
130
+ editComment: async (id, commentId, body) => {
131
+ const file = find(id);
132
+ const mine = own(file, commentId);
133
+ const edited = { ...mine, body };
134
+ file.comments = file.comments.map((c) => c === mine ? edited : c);
135
+ return edited;
136
+ },
137
+ deleteComment: async (id, commentId) => {
138
+ const file = find(id);
139
+ if (!file.comments?.find((c) => c.id === commentId)?.author.id.startsWith("guest:")) own(file, commentId);
140
+ file.comments = file.comments.filter((c) => c.id !== commentId && c.replyTo !== commentId);
141
+ },
142
+ exportAs: async (id, format) => {
143
+ const file = find(id);
144
+ if ((format === "md" ? "markdown" : format) !== kindOf(file.name)) throw new Error("this format needs a converter on the host");
145
+ return new Blob([encode(file.bytes)], { type: mimes[format] });
94
146
  }
95
147
  };
96
148
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/memory.ts","../src/kinds.ts"],"sourcesContent":["import { kindOf } from './kinds';\nimport type { DocumentsHost, Person, Rights, Space } from './types';\n\ntype Bytes = ArrayBuffer | string;\n\nexport type MemoryFile = {\n id: string;\n spaceId: string;\n name: string;\n folder?: string;\n bytes: Bytes;\n updatedAt?: string;\n rights?: Partial<Rights>;\n versions?: { id: string; createdAt: string; bytes: Bytes; note?: string }[];\n};\n\nconst encode = (bytes: Bytes) => typeof bytes === 'string' ? new TextEncoder().encode(bytes).buffer as ArrayBuffer : bytes;\n\nexport function memoryHost({ me, spaces, files }: { me: Person; spaces: Space[]; files: MemoryFile[] }): DocumentsHost {\n const find = (id: string) => {\n const file = files.find(item => item.id === id);\n if (!file) throw new Error('document not found');\n return file;\n };\n const summary = (file: MemoryFile) => ({\n id: file.id, spaceId: file.spaceId, name: file.name, kind: kindOf(file.name)!, size: encode(file.bytes).byteLength,\n updatedAt: file.updatedAt ?? '2026-10-19T09:00:00Z', updatedBy: me, folder: file.folder ?? null,\n });\n return {\n me,\n spaces: async () => spaces,\n documents: async spaceId => files.filter(file => file.spaceId === spaceId && kindOf(file.name)).map(summary),\n document: async id => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights } }),\n versions: async id => {\n const file = find(id);\n return [\n { id: 'current', createdAt: summary(file).updatedAt, size: summary(file).size, author: me, current: true },\n ...(file.versions ?? []).map(v => ({ id: v.id, createdAt: v.createdAt, size: encode(v.bytes).byteLength, author: me, note: v.note ?? null, current: false })),\n ];\n },\n content: async (id, versionId) => {\n const file = find(id);\n const old = versionId && versionId !== 'current' ? file.versions?.find(v => v.id === versionId) : undefined;\n return encode(old ? old.bytes : file.bytes);\n },\n restore: async (id, versionId) => {\n const file = find(id);\n const old = file.versions?.find(v => v.id === versionId);\n if (!old) throw new Error('version not found');\n file.versions = [{ id: `v${(file.versions?.length ?? 0) + 1}`, createdAt: file.updatedAt ?? '2026-10-19T09:00:00Z', bytes: file.bytes }, ...(file.versions ?? [])];\n file.bytes = old.bytes;\n file.updatedAt = new Date().toISOString();\n },\n };\n}\n","import type { DocumentKind } from './types';\n\nconst byExtension: Record<string, DocumentKind> = {\n docx: 'docx', md: 'markdown', markdown: 'markdown', pdf: 'pdf', xlsx: 'sheet', csv: 'sheet', html: 'slides', htm: 'slides',\n};\n\nconst byMime: Record<string, DocumentKind> = {\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'docx',\n 'text/markdown': 'markdown',\n 'application/pdf': 'pdf',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'sheet',\n 'text/csv': 'sheet',\n 'text/html': 'slides',\n};\n\nexport const kinds: DocumentKind[] = ['docx', 'markdown', 'pdf', 'sheet', 'slides'];\n\nexport function kindOf(name: string, mimeType?: string | null): DocumentKind | null {\n const extension = name.includes('.') ? name.split('.').pop()!.toLowerCase() : '';\n return byExtension[extension] ?? (mimeType ? byMime[mimeType.split(';')[0].trim().toLowerCase()] : undefined) ?? null;\n}\n\nexport function matches(doc: { name: string; kind: DocumentKind }, query: string, kind: DocumentKind | 'all') {\n const words = query.toLocaleLowerCase().split(/\\s+/).filter(Boolean);\n return (kind === 'all' || doc.kind === kind) && words.every(word => doc.name.toLocaleLowerCase().includes(word));\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/memory.ts","../src/kinds.ts"],"sourcesContent":["import { kindOf } from './kinds';\nimport type { Comment, DocumentsHost, Person, Rights, Signature, Space } from './types';\n\ntype Bytes = ArrayBuffer | string;\n\nexport type MemoryFile = {\n id: string;\n spaceId: string;\n name: string;\n folder?: string;\n bytes: Bytes;\n version?: string;\n note?: string;\n updatedAt?: string;\n rights?: Partial<Rights>;\n versions?: { id: string; createdAt: string; bytes: Bytes; note?: string }[];\n signatures?: Signature[];\n comments?: Comment[];\n};\n\nconst mimes = { pdf: 'application/pdf', docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', md: 'text/markdown' };\n\nconst encode = (bytes: Bytes) => typeof bytes === 'string' ? new TextEncoder().encode(bytes).buffer as ArrayBuffer : bytes;\n\nexport function memoryHost({ me, spaces, files, collab }: { me: Person; spaces: Space[]; files: MemoryFile[]; collab?: string }): DocumentsHost {\n const find = (id: string) => {\n const file = files.find(item => item.id === id);\n if (!file) throw new Error('document not found');\n return file;\n };\n const own = (file: MemoryFile, commentId: string) => {\n const found = file.comments?.find(c => c.id === commentId);\n if (!found || found.author.id !== me.id) throw new Error('only the author changes a comment');\n return found;\n };\n const summary = (file: MemoryFile) => ({\n id: file.id, spaceId: file.spaceId, name: file.name, kind: kindOf(file.name)!, size: encode(file.bytes).byteLength,\n updatedAt: file.updatedAt ?? '2026-10-19T09:00:00Z', updatedBy: me, folder: file.folder ?? null,\n });\n const archive = (file: MemoryFile, bytes: Bytes, note?: string) => {\n const versions = [{ id: file.version ?? `v${(file.versions?.length ?? 0) + 1}`, createdAt: file.updatedAt ?? '2026-10-19T09:00:00Z', bytes: file.bytes, note: file.note }, ...(file.versions ?? [])];\n const version = `v${versions.length + 1}`;\n Object.assign(file, { versions, version, bytes, note, updatedAt: new Date().toISOString() });\n return version;\n };\n return {\n me,\n ...(collab ? { collab: { url: `memory:${collab}`, token: async () => me.id } } : {}),\n spaces: async () => spaces,\n documents: async spaceId => files.filter(file => file.spaceId === spaceId && kindOf(file.name)).map(summary),\n document: async id => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights }, live: !!collab }),\n versions: async id => {\n const file = find(id);\n return [\n { id: file.version ?? 'current', createdAt: summary(file).updatedAt, size: summary(file).size, author: me, note: file.note ?? null, current: true },\n ...(file.versions ?? []).map(v => ({ id: v.id, createdAt: v.createdAt, size: encode(v.bytes).byteLength, author: me, note: v.note ?? null, current: false })),\n ];\n },\n content: async (id, versionId) => {\n const file = find(id);\n const old = versionId && versionId !== 'current' && versionId !== file.version ? file.versions?.find(v => v.id === versionId) : undefined;\n return encode(old ? old.bytes : file.bytes);\n },\n restore: async (id, versionId) => {\n const file = find(id);\n const old = file.versions?.find(v => v.id === versionId);\n if (!old) throw new Error('version not found');\n archive(file, old.bytes);\n },\n save: async (id, bytes, note) => ({ versionId: archive(find(id), bytes, note) }),\n signatures: async id => [...(find(id).signatures ?? [])].reverse(),\n sign: async (id, entry) => {\n const file = find(id);\n const signature = { id: `s${(file.signatures?.length ?? 0) + 1}`, signer: me, signedAt: new Date().toISOString(), ...entry };\n file.signatures = [...(file.signatures ?? []), signature];\n return signature;\n },\n comments: async id => [...(find(id).comments ?? [])],\n comment: async (id, entry) => {\n const file = find(id);\n let n = (file.comments?.length ?? 0) + 1;\n while (file.comments?.some(c => c.id === `c${n}`)) n++;\n const made: Comment = { id: `c${n}`, documentId: id, author: me, body: entry.body, createdAt: new Date().toISOString(), quote: entry.quote, replyTo: entry.replyTo, resolved: false };\n file.comments = [...(file.comments ?? []), made];\n return made;\n },\n resolveComment: async (id, commentId, resolved) => {\n const file = find(id);\n file.comments = (file.comments ?? []).map(c => c.id === commentId ? { ...c, resolved } : c);\n },\n editComment: async (id, commentId, body) => {\n const file = find(id);\n const mine = own(file, commentId);\n const edited = { ...mine, body };\n file.comments = file.comments!.map(c => c === mine ? edited : c);\n return edited;\n },\n deleteComment: async (id, commentId) => {\n const file = find(id);\n if (!file.comments?.find(c => c.id === commentId)?.author.id.startsWith('guest:')) own(file, commentId);\n file.comments = file.comments!.filter(c => c.id !== commentId && c.replyTo !== commentId);\n },\n exportAs: async (id, format) => {\n const file = find(id);\n if ((format === 'md' ? 'markdown' : format) !== kindOf(file.name)) throw new Error('this format needs a converter on the host');\n return new Blob([encode(file.bytes)], { type: mimes[format] });\n },\n };\n}\n","import type { DocumentKind } from './types';\n\nconst byExtension: Record<string, DocumentKind> = {\n docx: 'docx', md: 'markdown', markdown: 'markdown', pdf: 'pdf', xlsx: 'sheet', csv: 'sheet', xls: 'sheet', ods: 'sheet', tsv: 'sheet', html: 'slides', htm: 'slides',\n};\n\nconst byMime: Record<string, DocumentKind> = {\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'docx',\n 'text/markdown': 'markdown',\n 'application/pdf': 'pdf',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'sheet',\n 'text/csv': 'sheet',\n 'text/html': 'slides',\n};\n\nexport const kinds: DocumentKind[] = ['docx', 'markdown', 'pdf', 'sheet', 'slides'];\n\nexport function kindOf(name: string, mimeType?: string | null): DocumentKind | null {\n const extension = name.includes('.') ? name.split('.').pop()!.toLowerCase() : '';\n return byExtension[extension] ?? (mimeType ? byMime[mimeType.split(';')[0].trim().toLowerCase()] : undefined) ?? null;\n}\n\nexport function readable(name: string, mimeType?: string | null): DocumentKind | null {\n const kind = kindOf(name, mimeType);\n return kind !== 'sheet' || /\\.(xlsx|csv)$/i.test(name) || /spreadsheetml|text\\/csv/.test(mimeType ?? '') ? kind : null;\n}\n\nexport function matches(doc: { name: string; kind: DocumentKind }, query: string, kind: DocumentKind | 'all') {\n const words = query.toLocaleLowerCase().split(/\\s+/).filter(Boolean);\n return (kind === 'all' || doc.kind === kind) && words.every(word => doc.name.toLocaleLowerCase().includes(word));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEA,IAAM,cAA4C;AAAA,EAChD,MAAM;AAAA,EAAQ,IAAI;AAAA,EAAY,UAAU;AAAA,EAAY,KAAK;AAAA,EAAO,MAAM;AAAA,EAAS,KAAK;AAAA,EAAS,KAAK;AAAA,EAAS,KAAK;AAAA,EAAS,KAAK;AAAA,EAAS,MAAM;AAAA,EAAU,KAAK;AAC9J;AAEA,IAAM,SAAuC;AAAA,EAC3C,2EAA2E;AAAA,EAC3E,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,qEAAqE;AAAA,EACrE,YAAY;AAAA,EACZ,aAAa;AACf;AAIO,SAAS,OAAO,MAAc,UAA+C;AAClF,QAAM,YAAY,KAAK,SAAS,GAAG,IAAI,KAAK,MAAM,GAAG,EAAE,IAAI,EAAG,YAAY,IAAI;AAC9E,SAAO,YAAY,SAAS,MAAM,WAAW,OAAO,SAAS,MAAM,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,IAAI,WAAc;AACnH;;;ADAA,IAAM,QAAQ,EAAE,KAAK,mBAAmB,MAAM,2EAA2E,IAAI,gBAAgB;AAE7I,IAAM,SAAS,CAAC,UAAiB,OAAO,UAAU,WAAW,IAAI,YAAY,EAAE,OAAO,KAAK,EAAE,SAAwB;AAE9G,SAAS,WAAW,EAAE,IAAI,QAAQ,OAAO,OAAO,GAAyF;AAC9I,QAAM,OAAO,CAAC,OAAe;AAC3B,UAAM,OAAO,MAAM,KAAK,UAAQ,KAAK,OAAO,EAAE;AAC9C,QAAI,CAAC,KAAM,OAAM,IAAI,MAAM,oBAAoB;AAC/C,WAAO;AAAA,EACT;AACA,QAAM,MAAM,CAAC,MAAkB,cAAsB;AACnD,UAAM,QAAQ,KAAK,UAAU,KAAK,OAAK,EAAE,OAAO,SAAS;AACzD,QAAI,CAAC,SAAS,MAAM,OAAO,OAAO,GAAG,GAAI,OAAM,IAAI,MAAM,mCAAmC;AAC5F,WAAO;AAAA,EACT;AACA,QAAM,UAAU,CAAC,UAAsB;AAAA,IACrC,IAAI,KAAK;AAAA,IAAI,SAAS,KAAK;AAAA,IAAS,MAAM,KAAK;AAAA,IAAM,MAAM,OAAO,KAAK,IAAI;AAAA,IAAI,MAAM,OAAO,KAAK,KAAK,EAAE;AAAA,IACxG,WAAW,KAAK,aAAa;AAAA,IAAwB,WAAW;AAAA,IAAI,QAAQ,KAAK,UAAU;AAAA,EAC7F;AACA,QAAM,UAAU,CAAC,MAAkB,OAAc,SAAkB;AACjE,UAAM,WAAW,CAAC,EAAE,IAAI,KAAK,WAAW,KAAK,KAAK,UAAU,UAAU,KAAK,CAAC,IAAI,WAAW,KAAK,aAAa,wBAAwB,OAAO,KAAK,OAAO,MAAM,KAAK,KAAK,GAAG,GAAI,KAAK,YAAY,CAAC,CAAE;AACnM,UAAM,UAAU,IAAI,SAAS,SAAS,CAAC;AACvC,WAAO,OAAO,MAAM,EAAE,UAAU,SAAS,OAAO,MAAM,YAAW,oBAAI,KAAK,GAAE,YAAY,EAAE,CAAC;AAC3F,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL;AAAA,IACA,GAAI,SAAS,EAAE,QAAQ,EAAE,KAAK,UAAU,MAAM,IAAI,OAAO,YAAY,GAAG,GAAG,EAAE,IAAI,CAAC;AAAA,IAClF,QAAQ,YAAY;AAAA,IACpB,WAAW,OAAM,YAAW,MAAM,OAAO,UAAQ,KAAK,YAAY,WAAW,OAAO,KAAK,IAAI,CAAC,EAAE,IAAI,OAAO;AAAA,IAC3G,UAAU,OAAM,QAAO,EAAE,GAAG,QAAQ,KAAK,EAAE,CAAC,GAAG,QAAQ,EAAE,MAAM,MAAM,SAAS,MAAM,MAAM,MAAM,GAAG,KAAK,EAAE,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC,OAAO;AAAA,IACrI,UAAU,OAAM,OAAM;AACpB,YAAM,OAAO,KAAK,EAAE;AACpB,aAAO;AAAA,QACL,EAAE,IAAI,KAAK,WAAW,WAAW,WAAW,QAAQ,IAAI,EAAE,WAAW,MAAM,QAAQ,IAAI,EAAE,MAAM,QAAQ,IAAI,MAAM,KAAK,QAAQ,MAAM,SAAS,KAAK;AAAA,QAClJ,IAAI,KAAK,YAAY,CAAC,GAAG,IAAI,QAAM,EAAE,IAAI,EAAE,IAAI,WAAW,EAAE,WAAW,MAAM,OAAO,EAAE,KAAK,EAAE,YAAY,QAAQ,IAAI,MAAM,EAAE,QAAQ,MAAM,SAAS,MAAM,EAAE;AAAA,MAC9J;AAAA,IACF;AAAA,IACA,SAAS,OAAO,IAAI,cAAc;AAChC,YAAM,OAAO,KAAK,EAAE;AACpB,YAAM,MAAM,aAAa,cAAc,aAAa,cAAc,KAAK,UAAU,KAAK,UAAU,KAAK,OAAK,EAAE,OAAO,SAAS,IAAI;AAChI,aAAO,OAAO,MAAM,IAAI,QAAQ,KAAK,KAAK;AAAA,IAC5C;AAAA,IACA,SAAS,OAAO,IAAI,cAAc;AAChC,YAAM,OAAO,KAAK,EAAE;AACpB,YAAM,MAAM,KAAK,UAAU,KAAK,OAAK,EAAE,OAAO,SAAS;AACvD,UAAI,CAAC,IAAK,OAAM,IAAI,MAAM,mBAAmB;AAC7C,cAAQ,MAAM,IAAI,KAAK;AAAA,IACzB;AAAA,IACA,MAAM,OAAO,IAAI,OAAO,UAAU,EAAE,WAAW,QAAQ,KAAK,EAAE,GAAG,OAAO,IAAI,EAAE;AAAA,IAC9E,YAAY,OAAM,OAAM,CAAC,GAAI,KAAK,EAAE,EAAE,cAAc,CAAC,CAAE,EAAE,QAAQ;AAAA,IACjE,MAAM,OAAO,IAAI,UAAU;AACzB,YAAM,OAAO,KAAK,EAAE;AACpB,YAAM,YAAY,EAAE,IAAI,KAAK,KAAK,YAAY,UAAU,KAAK,CAAC,IAAI,QAAQ,IAAI,WAAU,oBAAI,KAAK,GAAE,YAAY,GAAG,GAAG,MAAM;AAC3H,WAAK,aAAa,CAAC,GAAI,KAAK,cAAc,CAAC,GAAI,SAAS;AACxD,aAAO;AAAA,IACT;AAAA,IACA,UAAU,OAAM,OAAM,CAAC,GAAI,KAAK,EAAE,EAAE,YAAY,CAAC,CAAE;AAAA,IACnD,SAAS,OAAO,IAAI,UAAU;AAC5B,YAAM,OAAO,KAAK,EAAE;AACpB,UAAI,KAAK,KAAK,UAAU,UAAU,KAAK;AACvC,aAAO,KAAK,UAAU,KAAK,OAAK,EAAE,OAAO,IAAI,CAAC,EAAE,EAAG;AACnD,YAAM,OAAgB,EAAE,IAAI,IAAI,CAAC,IAAI,YAAY,IAAI,QAAQ,IAAI,MAAM,MAAM,MAAM,YAAW,oBAAI,KAAK,GAAE,YAAY,GAAG,OAAO,MAAM,OAAO,SAAS,MAAM,SAAS,UAAU,MAAM;AACpL,WAAK,WAAW,CAAC,GAAI,KAAK,YAAY,CAAC,GAAI,IAAI;AAC/C,aAAO;AAAA,IACT;AAAA,IACA,gBAAgB,OAAO,IAAI,WAAW,aAAa;AACjD,YAAM,OAAO,KAAK,EAAE;AACpB,WAAK,YAAY,KAAK,YAAY,CAAC,GAAG,IAAI,OAAK,EAAE,OAAO,YAAY,EAAE,GAAG,GAAG,SAAS,IAAI,CAAC;AAAA,IAC5F;AAAA,IACA,aAAa,OAAO,IAAI,WAAW,SAAS;AAC1C,YAAM,OAAO,KAAK,EAAE;AACpB,YAAM,OAAO,IAAI,MAAM,SAAS;AAChC,YAAM,SAAS,EAAE,GAAG,MAAM,KAAK;AAC/B,WAAK,WAAW,KAAK,SAAU,IAAI,OAAK,MAAM,OAAO,SAAS,CAAC;AAC/D,aAAO;AAAA,IACT;AAAA,IACA,eAAe,OAAO,IAAI,cAAc;AACtC,YAAM,OAAO,KAAK,EAAE;AACpB,UAAI,CAAC,KAAK,UAAU,KAAK,OAAK,EAAE,OAAO,SAAS,GAAG,OAAO,GAAG,WAAW,QAAQ,EAAG,KAAI,MAAM,SAAS;AACtG,WAAK,WAAW,KAAK,SAAU,OAAO,OAAK,EAAE,OAAO,aAAa,EAAE,YAAY,SAAS;AAAA,IAC1F;AAAA,IACA,UAAU,OAAO,IAAI,WAAW;AAC9B,YAAM,OAAO,KAAK,EAAE;AACpB,WAAK,WAAW,OAAO,aAAa,YAAY,OAAO,KAAK,IAAI,EAAG,OAAM,IAAI,MAAM,2CAA2C;AAC9H,aAAO,IAAI,KAAK,CAAC,OAAO,KAAK,KAAK,CAAC,GAAG,EAAE,MAAM,MAAM,MAAM,EAAE,CAAC;AAAA,IAC/D;AAAA,EACF;AACF;","names":[]}
package/dist/memory.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { R as Rights, e as Person, S as Space, D as DocumentsHost } from './types-DshXPnWA.cjs';
1
+ import { R as Rights, S as Signature, C as Comment, h as Person, j as Space, D as DocumentsHost } from './types-B5oF25dn.cjs';
2
2
 
3
3
  type Bytes = ArrayBuffer | string;
4
4
  type MemoryFile = {
@@ -7,6 +7,8 @@ type MemoryFile = {
7
7
  name: string;
8
8
  folder?: string;
9
9
  bytes: Bytes;
10
+ version?: string;
11
+ note?: string;
10
12
  updatedAt?: string;
11
13
  rights?: Partial<Rights>;
12
14
  versions?: {
@@ -15,11 +17,14 @@ type MemoryFile = {
15
17
  bytes: Bytes;
16
18
  note?: string;
17
19
  }[];
20
+ signatures?: Signature[];
21
+ comments?: Comment[];
18
22
  };
19
- declare function memoryHost({ me, spaces, files }: {
23
+ declare function memoryHost({ me, spaces, files, collab }: {
20
24
  me: Person;
21
25
  spaces: Space[];
22
26
  files: MemoryFile[];
27
+ collab?: string;
23
28
  }): DocumentsHost;
24
29
 
25
30
  export { type MemoryFile, memoryHost };
package/dist/memory.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { R as Rights, e as Person, S as Space, D as DocumentsHost } from './types-DshXPnWA.js';
1
+ import { R as Rights, S as Signature, C as Comment, h as Person, j as Space, D as DocumentsHost } from './types-B5oF25dn.js';
2
2
 
3
3
  type Bytes = ArrayBuffer | string;
4
4
  type MemoryFile = {
@@ -7,6 +7,8 @@ type MemoryFile = {
7
7
  name: string;
8
8
  folder?: string;
9
9
  bytes: Bytes;
10
+ version?: string;
11
+ note?: string;
10
12
  updatedAt?: string;
11
13
  rights?: Partial<Rights>;
12
14
  versions?: {
@@ -15,11 +17,14 @@ type MemoryFile = {
15
17
  bytes: Bytes;
16
18
  note?: string;
17
19
  }[];
20
+ signatures?: Signature[];
21
+ comments?: Comment[];
18
22
  };
19
- declare function memoryHost({ me, spaces, files }: {
23
+ declare function memoryHost({ me, spaces, files, collab }: {
20
24
  me: Person;
21
25
  spaces: Space[];
22
26
  files: MemoryFile[];
27
+ collab?: string;
23
28
  }): DocumentsHost;
24
29
 
25
30
  export { type MemoryFile, memoryHost };
package/dist/memory.js CHANGED
@@ -1,16 +1,22 @@
1
1
  'use client';
2
2
  import {
3
3
  kindOf
4
- } from "./chunk-KEV4R7W5.js";
4
+ } from "./chunk-L765DZPO.js";
5
5
 
6
6
  // src/memory.ts
7
+ var mimes = { pdf: "application/pdf", docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", md: "text/markdown" };
7
8
  var encode = (bytes) => typeof bytes === "string" ? new TextEncoder().encode(bytes).buffer : bytes;
8
- function memoryHost({ me, spaces, files }) {
9
+ function memoryHost({ me, spaces, files, collab }) {
9
10
  const find = (id) => {
10
11
  const file = files.find((item) => item.id === id);
11
12
  if (!file) throw new Error("document not found");
12
13
  return file;
13
14
  };
15
+ const own = (file, commentId) => {
16
+ const found = file.comments?.find((c) => c.id === commentId);
17
+ if (!found || found.author.id !== me.id) throw new Error("only the author changes a comment");
18
+ return found;
19
+ };
14
20
  const summary = (file) => ({
15
21
  id: file.id,
16
22
  spaceId: file.spaceId,
@@ -21,30 +27,73 @@ function memoryHost({ me, spaces, files }) {
21
27
  updatedBy: me,
22
28
  folder: file.folder ?? null
23
29
  });
30
+ const archive = (file, bytes, note) => {
31
+ const versions = [{ id: file.version ?? `v${(file.versions?.length ?? 0) + 1}`, createdAt: file.updatedAt ?? "2026-10-19T09:00:00Z", bytes: file.bytes, note: file.note }, ...file.versions ?? []];
32
+ const version = `v${versions.length + 1}`;
33
+ Object.assign(file, { versions, version, bytes, note, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
34
+ return version;
35
+ };
24
36
  return {
25
37
  me,
38
+ ...collab ? { collab: { url: `memory:${collab}`, token: async () => me.id } } : {},
26
39
  spaces: async () => spaces,
27
40
  documents: async (spaceId) => files.filter((file) => file.spaceId === spaceId && kindOf(file.name)).map(summary),
28
- document: async (id) => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights } }),
41
+ document: async (id) => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights }, live: !!collab }),
29
42
  versions: async (id) => {
30
43
  const file = find(id);
31
44
  return [
32
- { id: "current", createdAt: summary(file).updatedAt, size: summary(file).size, author: me, current: true },
45
+ { id: file.version ?? "current", createdAt: summary(file).updatedAt, size: summary(file).size, author: me, note: file.note ?? null, current: true },
33
46
  ...(file.versions ?? []).map((v) => ({ id: v.id, createdAt: v.createdAt, size: encode(v.bytes).byteLength, author: me, note: v.note ?? null, current: false }))
34
47
  ];
35
48
  },
36
49
  content: async (id, versionId) => {
37
50
  const file = find(id);
38
- const old = versionId && versionId !== "current" ? file.versions?.find((v) => v.id === versionId) : void 0;
51
+ const old = versionId && versionId !== "current" && versionId !== file.version ? file.versions?.find((v) => v.id === versionId) : void 0;
39
52
  return encode(old ? old.bytes : file.bytes);
40
53
  },
41
54
  restore: async (id, versionId) => {
42
55
  const file = find(id);
43
56
  const old = file.versions?.find((v) => v.id === versionId);
44
57
  if (!old) throw new Error("version not found");
45
- file.versions = [{ id: `v${(file.versions?.length ?? 0) + 1}`, createdAt: file.updatedAt ?? "2026-10-19T09:00:00Z", bytes: file.bytes }, ...file.versions ?? []];
46
- file.bytes = old.bytes;
47
- file.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
58
+ archive(file, old.bytes);
59
+ },
60
+ save: async (id, bytes, note) => ({ versionId: archive(find(id), bytes, note) }),
61
+ signatures: async (id) => [...find(id).signatures ?? []].reverse(),
62
+ sign: async (id, entry) => {
63
+ const file = find(id);
64
+ const signature = { id: `s${(file.signatures?.length ?? 0) + 1}`, signer: me, signedAt: (/* @__PURE__ */ new Date()).toISOString(), ...entry };
65
+ file.signatures = [...file.signatures ?? [], signature];
66
+ return signature;
67
+ },
68
+ comments: async (id) => [...find(id).comments ?? []],
69
+ comment: async (id, entry) => {
70
+ const file = find(id);
71
+ let n = (file.comments?.length ?? 0) + 1;
72
+ while (file.comments?.some((c) => c.id === `c${n}`)) n++;
73
+ const made = { id: `c${n}`, documentId: id, author: me, body: entry.body, createdAt: (/* @__PURE__ */ new Date()).toISOString(), quote: entry.quote, replyTo: entry.replyTo, resolved: false };
74
+ file.comments = [...file.comments ?? [], made];
75
+ return made;
76
+ },
77
+ resolveComment: async (id, commentId, resolved) => {
78
+ const file = find(id);
79
+ file.comments = (file.comments ?? []).map((c) => c.id === commentId ? { ...c, resolved } : c);
80
+ },
81
+ editComment: async (id, commentId, body) => {
82
+ const file = find(id);
83
+ const mine = own(file, commentId);
84
+ const edited = { ...mine, body };
85
+ file.comments = file.comments.map((c) => c === mine ? edited : c);
86
+ return edited;
87
+ },
88
+ deleteComment: async (id, commentId) => {
89
+ const file = find(id);
90
+ if (!file.comments?.find((c) => c.id === commentId)?.author.id.startsWith("guest:")) own(file, commentId);
91
+ file.comments = file.comments.filter((c) => c.id !== commentId && c.replyTo !== commentId);
92
+ },
93
+ exportAs: async (id, format) => {
94
+ const file = find(id);
95
+ if ((format === "md" ? "markdown" : format) !== kindOf(file.name)) throw new Error("this format needs a converter on the host");
96
+ return new Blob([encode(file.bytes)], { type: mimes[format] });
48
97
  }
49
98
  };
50
99
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/memory.ts"],"sourcesContent":["import { kindOf } from './kinds';\nimport type { DocumentsHost, Person, Rights, Space } from './types';\n\ntype Bytes = ArrayBuffer | string;\n\nexport type MemoryFile = {\n id: string;\n spaceId: string;\n name: string;\n folder?: string;\n bytes: Bytes;\n updatedAt?: string;\n rights?: Partial<Rights>;\n versions?: { id: string; createdAt: string; bytes: Bytes; note?: string }[];\n};\n\nconst encode = (bytes: Bytes) => typeof bytes === 'string' ? new TextEncoder().encode(bytes).buffer as ArrayBuffer : bytes;\n\nexport function memoryHost({ me, spaces, files }: { me: Person; spaces: Space[]; files: MemoryFile[] }): DocumentsHost {\n const find = (id: string) => {\n const file = files.find(item => item.id === id);\n if (!file) throw new Error('document not found');\n return file;\n };\n const summary = (file: MemoryFile) => ({\n id: file.id, spaceId: file.spaceId, name: file.name, kind: kindOf(file.name)!, size: encode(file.bytes).byteLength,\n updatedAt: file.updatedAt ?? '2026-10-19T09:00:00Z', updatedBy: me, folder: file.folder ?? null,\n });\n return {\n me,\n spaces: async () => spaces,\n documents: async spaceId => files.filter(file => file.spaceId === spaceId && kindOf(file.name)).map(summary),\n document: async id => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights } }),\n versions: async id => {\n const file = find(id);\n return [\n { id: 'current', createdAt: summary(file).updatedAt, size: summary(file).size, author: me, current: true },\n ...(file.versions ?? []).map(v => ({ id: v.id, createdAt: v.createdAt, size: encode(v.bytes).byteLength, author: me, note: v.note ?? null, current: false })),\n ];\n },\n content: async (id, versionId) => {\n const file = find(id);\n const old = versionId && versionId !== 'current' ? file.versions?.find(v => v.id === versionId) : undefined;\n return encode(old ? old.bytes : file.bytes);\n },\n restore: async (id, versionId) => {\n const file = find(id);\n const old = file.versions?.find(v => v.id === versionId);\n if (!old) throw new Error('version not found');\n file.versions = [{ id: `v${(file.versions?.length ?? 0) + 1}`, createdAt: file.updatedAt ?? '2026-10-19T09:00:00Z', bytes: file.bytes }, ...(file.versions ?? [])];\n file.bytes = old.bytes;\n file.updatedAt = new Date().toISOString();\n },\n };\n}\n"],"mappings":";;;;;;AAgBA,IAAM,SAAS,CAAC,UAAiB,OAAO,UAAU,WAAW,IAAI,YAAY,EAAE,OAAO,KAAK,EAAE,SAAwB;AAE9G,SAAS,WAAW,EAAE,IAAI,QAAQ,MAAM,GAAwE;AACrH,QAAM,OAAO,CAAC,OAAe;AAC3B,UAAM,OAAO,MAAM,KAAK,UAAQ,KAAK,OAAO,EAAE;AAC9C,QAAI,CAAC,KAAM,OAAM,IAAI,MAAM,oBAAoB;AAC/C,WAAO;AAAA,EACT;AACA,QAAM,UAAU,CAAC,UAAsB;AAAA,IACrC,IAAI,KAAK;AAAA,IAAI,SAAS,KAAK;AAAA,IAAS,MAAM,KAAK;AAAA,IAAM,MAAM,OAAO,KAAK,IAAI;AAAA,IAAI,MAAM,OAAO,KAAK,KAAK,EAAE;AAAA,IACxG,WAAW,KAAK,aAAa;AAAA,IAAwB,WAAW;AAAA,IAAI,QAAQ,KAAK,UAAU;AAAA,EAC7F;AACA,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,YAAY;AAAA,IACpB,WAAW,OAAM,YAAW,MAAM,OAAO,UAAQ,KAAK,YAAY,WAAW,OAAO,KAAK,IAAI,CAAC,EAAE,IAAI,OAAO;AAAA,IAC3G,UAAU,OAAM,QAAO,EAAE,GAAG,QAAQ,KAAK,EAAE,CAAC,GAAG,QAAQ,EAAE,MAAM,MAAM,SAAS,MAAM,MAAM,MAAM,GAAG,KAAK,EAAE,EAAE,OAAO,EAAE;AAAA,IACrH,UAAU,OAAM,OAAM;AACpB,YAAM,OAAO,KAAK,EAAE;AACpB,aAAO;AAAA,QACL,EAAE,IAAI,WAAW,WAAW,QAAQ,IAAI,EAAE,WAAW,MAAM,QAAQ,IAAI,EAAE,MAAM,QAAQ,IAAI,SAAS,KAAK;AAAA,QACzG,IAAI,KAAK,YAAY,CAAC,GAAG,IAAI,QAAM,EAAE,IAAI,EAAE,IAAI,WAAW,EAAE,WAAW,MAAM,OAAO,EAAE,KAAK,EAAE,YAAY,QAAQ,IAAI,MAAM,EAAE,QAAQ,MAAM,SAAS,MAAM,EAAE;AAAA,MAC9J;AAAA,IACF;AAAA,IACA,SAAS,OAAO,IAAI,cAAc;AAChC,YAAM,OAAO,KAAK,EAAE;AACpB,YAAM,MAAM,aAAa,cAAc,YAAY,KAAK,UAAU,KAAK,OAAK,EAAE,OAAO,SAAS,IAAI;AAClG,aAAO,OAAO,MAAM,IAAI,QAAQ,KAAK,KAAK;AAAA,IAC5C;AAAA,IACA,SAAS,OAAO,IAAI,cAAc;AAChC,YAAM,OAAO,KAAK,EAAE;AACpB,YAAM,MAAM,KAAK,UAAU,KAAK,OAAK,EAAE,OAAO,SAAS;AACvD,UAAI,CAAC,IAAK,OAAM,IAAI,MAAM,mBAAmB;AAC7C,WAAK,WAAW,CAAC,EAAE,IAAI,KAAK,KAAK,UAAU,UAAU,KAAK,CAAC,IAAI,WAAW,KAAK,aAAa,wBAAwB,OAAO,KAAK,MAAM,GAAG,GAAI,KAAK,YAAY,CAAC,CAAE;AACjK,WAAK,QAAQ,IAAI;AACjB,WAAK,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,IAC1C;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/memory.ts"],"sourcesContent":["import { kindOf } from './kinds';\nimport type { Comment, DocumentsHost, Person, Rights, Signature, Space } from './types';\n\ntype Bytes = ArrayBuffer | string;\n\nexport type MemoryFile = {\n id: string;\n spaceId: string;\n name: string;\n folder?: string;\n bytes: Bytes;\n version?: string;\n note?: string;\n updatedAt?: string;\n rights?: Partial<Rights>;\n versions?: { id: string; createdAt: string; bytes: Bytes; note?: string }[];\n signatures?: Signature[];\n comments?: Comment[];\n};\n\nconst mimes = { pdf: 'application/pdf', docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', md: 'text/markdown' };\n\nconst encode = (bytes: Bytes) => typeof bytes === 'string' ? new TextEncoder().encode(bytes).buffer as ArrayBuffer : bytes;\n\nexport function memoryHost({ me, spaces, files, collab }: { me: Person; spaces: Space[]; files: MemoryFile[]; collab?: string }): DocumentsHost {\n const find = (id: string) => {\n const file = files.find(item => item.id === id);\n if (!file) throw new Error('document not found');\n return file;\n };\n const own = (file: MemoryFile, commentId: string) => {\n const found = file.comments?.find(c => c.id === commentId);\n if (!found || found.author.id !== me.id) throw new Error('only the author changes a comment');\n return found;\n };\n const summary = (file: MemoryFile) => ({\n id: file.id, spaceId: file.spaceId, name: file.name, kind: kindOf(file.name)!, size: encode(file.bytes).byteLength,\n updatedAt: file.updatedAt ?? '2026-10-19T09:00:00Z', updatedBy: me, folder: file.folder ?? null,\n });\n const archive = (file: MemoryFile, bytes: Bytes, note?: string) => {\n const versions = [{ id: file.version ?? `v${(file.versions?.length ?? 0) + 1}`, createdAt: file.updatedAt ?? '2026-10-19T09:00:00Z', bytes: file.bytes, note: file.note }, ...(file.versions ?? [])];\n const version = `v${versions.length + 1}`;\n Object.assign(file, { versions, version, bytes, note, updatedAt: new Date().toISOString() });\n return version;\n };\n return {\n me,\n ...(collab ? { collab: { url: `memory:${collab}`, token: async () => me.id } } : {}),\n spaces: async () => spaces,\n documents: async spaceId => files.filter(file => file.spaceId === spaceId && kindOf(file.name)).map(summary),\n document: async id => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights }, live: !!collab }),\n versions: async id => {\n const file = find(id);\n return [\n { id: file.version ?? 'current', createdAt: summary(file).updatedAt, size: summary(file).size, author: me, note: file.note ?? null, current: true },\n ...(file.versions ?? []).map(v => ({ id: v.id, createdAt: v.createdAt, size: encode(v.bytes).byteLength, author: me, note: v.note ?? null, current: false })),\n ];\n },\n content: async (id, versionId) => {\n const file = find(id);\n const old = versionId && versionId !== 'current' && versionId !== file.version ? file.versions?.find(v => v.id === versionId) : undefined;\n return encode(old ? old.bytes : file.bytes);\n },\n restore: async (id, versionId) => {\n const file = find(id);\n const old = file.versions?.find(v => v.id === versionId);\n if (!old) throw new Error('version not found');\n archive(file, old.bytes);\n },\n save: async (id, bytes, note) => ({ versionId: archive(find(id), bytes, note) }),\n signatures: async id => [...(find(id).signatures ?? [])].reverse(),\n sign: async (id, entry) => {\n const file = find(id);\n const signature = { id: `s${(file.signatures?.length ?? 0) + 1}`, signer: me, signedAt: new Date().toISOString(), ...entry };\n file.signatures = [...(file.signatures ?? []), signature];\n return signature;\n },\n comments: async id => [...(find(id).comments ?? [])],\n comment: async (id, entry) => {\n const file = find(id);\n let n = (file.comments?.length ?? 0) + 1;\n while (file.comments?.some(c => c.id === `c${n}`)) n++;\n const made: Comment = { id: `c${n}`, documentId: id, author: me, body: entry.body, createdAt: new Date().toISOString(), quote: entry.quote, replyTo: entry.replyTo, resolved: false };\n file.comments = [...(file.comments ?? []), made];\n return made;\n },\n resolveComment: async (id, commentId, resolved) => {\n const file = find(id);\n file.comments = (file.comments ?? []).map(c => c.id === commentId ? { ...c, resolved } : c);\n },\n editComment: async (id, commentId, body) => {\n const file = find(id);\n const mine = own(file, commentId);\n const edited = { ...mine, body };\n file.comments = file.comments!.map(c => c === mine ? edited : c);\n return edited;\n },\n deleteComment: async (id, commentId) => {\n const file = find(id);\n if (!file.comments?.find(c => c.id === commentId)?.author.id.startsWith('guest:')) own(file, commentId);\n file.comments = file.comments!.filter(c => c.id !== commentId && c.replyTo !== commentId);\n },\n exportAs: async (id, format) => {\n const file = find(id);\n if ((format === 'md' ? 'markdown' : format) !== kindOf(file.name)) throw new Error('this format needs a converter on the host');\n return new Blob([encode(file.bytes)], { type: mimes[format] });\n },\n };\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,76 @@
1
+ 'use client';
2
+
3
+ // src/viewers/pdfWrite.ts
4
+ import { init } from "@embedpdf/pdfium";
5
+ import { PdfiumNative } from "@embedpdf/engines/pdfium";
6
+ import { PDF_FORM_FIELD_TYPE, PdfAnnotationSubtype, PdfBlendMode } from "@embedpdf/models";
7
+ var engine = null;
8
+ var rect = (box) => ({ origin: { x: box.x, y: box.y }, size: { width: box.w, height: box.h } });
9
+ var around = (boxes) => {
10
+ const x = Math.min(...boxes.map((b) => b.x));
11
+ const y = Math.min(...boxes.map((b) => b.y));
12
+ return { x, y, w: Math.max(...boxes.map((b) => b.x + b.w)) - x, h: Math.max(...boxes.map((b) => b.y + b.h)) - y };
13
+ };
14
+ var png = (url) => Uint8Array.from(atob(url.slice(url.indexOf(",") + 1)), (c) => c.charCodeAt(0)).buffer;
15
+ var types = { highlight: PdfAnnotationSubtype.HIGHLIGHT, underline: PdfAnnotationSubtype.UNDERLINE, strike: PdfAnnotationSubtype.STRIKEOUT };
16
+ function annotation(mark) {
17
+ const base = { id: mark.id, pageIndex: mark.page - 1, author: mark.author, created: new Date(mark.at), modified: new Date(mark.at) };
18
+ if (mark.kind === "note") {
19
+ return { ...base, type: PdfAnnotationSubtype.TEXT, rect: rect({ ...mark.spot, w: 20, h: 20 }), contents: mark.text, strokeColor: mark.color, opacity: 1 };
20
+ }
21
+ if (mark.kind === "ink") {
22
+ const spread = mark.width / 2 + 1;
23
+ const bounds = around(mark.lines.flat().map((p) => ({ x: p.x - spread, y: p.y - spread, w: spread * 2, h: spread * 2 })));
24
+ return { ...base, type: PdfAnnotationSubtype.INK, rect: rect(bounds), inkList: mark.lines.map((points) => ({ points })), strokeColor: mark.color, strokeWidth: mark.width, opacity: 1 };
25
+ }
26
+ if (mark.kind === "sign") return { ...base, type: PdfAnnotationSubtype.STAMP, rect: rect(mark.box) };
27
+ return {
28
+ ...base,
29
+ type: types[mark.kind],
30
+ rect: rect(around(mark.rects)),
31
+ segmentRects: mark.rects.map(rect),
32
+ contents: mark.text,
33
+ strokeColor: mark.color,
34
+ opacity: 1,
35
+ ...mark.kind === "highlight" ? { blendMode: PdfBlendMode.Multiply } : {}
36
+ };
37
+ }
38
+ async function write(bytes, marks, fields) {
39
+ engine ?? (engine = init({}).then((module) => new PdfiumNative(module)));
40
+ const pdfium = await engine;
41
+ const doc = await pdfium.openDocumentBuffer({ id: Math.random().toString(36).slice(2), content: bytes.slice(0) }).toPromise();
42
+ try {
43
+ for (const n of new Set(fields.map((field) => field.page))) {
44
+ const page = doc.pages[n - 1];
45
+ const widgets = await pdfium.getPageAnnoWidgets(doc, page).toPromise();
46
+ for (const field of fields.filter((f) => f.page === n)) {
47
+ const centre = (r) => Math.hypot(r.origin.x + r.size.width / 2 - field.box.x - field.box.w / 2, r.origin.y + r.size.height / 2 - field.box.y - field.box.h / 2);
48
+ const widget = widgets.filter((w) => w.field.name === field.name).sort((a, b) => centre(a.rect) - centre(b.rect))[0];
49
+ if (!widget) continue;
50
+ const { type } = widget.field;
51
+ if (type === PDF_FORM_FIELD_TYPE.TEXTFIELD) {
52
+ await pdfium.setFormFieldValue(doc, page, widget, { kind: "text", text: String(field.value) }).toPromise();
53
+ } else if (type === PDF_FORM_FIELD_TYPE.CHECKBOX || type === PDF_FORM_FIELD_TYPE.RADIOBUTTON && field.value === true) {
54
+ await pdfium.setFormFieldValue(doc, page, widget, { kind: "checked", checked: field.value === true }).toPromise();
55
+ } else if ("options" in widget.field && Array.isArray(field.value)) {
56
+ for (const [index, option] of widget.field.options.entries()) {
57
+ const wanted = field.value.includes(option.label);
58
+ if (wanted !== option.isSelected) await pdfium.setFormFieldValue(doc, page, widget, { kind: "selection", index, isSelected: wanted }).toPromise();
59
+ }
60
+ }
61
+ }
62
+ }
63
+ for (const mark of marks) {
64
+ const page = doc.pages[mark.page - 1];
65
+ if (mark.kind === "sign") await pdfium.createPageAnnotation(doc, page, annotation(mark), { data: png(mark.image), mimeType: "image/png" }).toPromise();
66
+ else await pdfium.createPageAnnotation(doc, page, annotation(mark)).toPromise();
67
+ }
68
+ return await pdfium.saveAsCopy(doc).toPromise();
69
+ } finally {
70
+ await pdfium.closeDocument(doc).toPromise();
71
+ }
72
+ }
73
+ export {
74
+ write
75
+ };
76
+ //# sourceMappingURL=pdfWrite-EM6GJDBF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/viewers/pdfWrite.ts"],"sourcesContent":["import { init } from '@embedpdf/pdfium';\nimport { PdfiumNative } from '@embedpdf/engines/pdfium';\nimport { PDF_FORM_FIELD_TYPE, PdfAnnotationSubtype, PdfBlendMode, type PdfAnnotationObject, type Rect } from '@embedpdf/models';\nimport type { SignatureMethod } from '../types';\n\nexport type Point = { x: number; y: number };\nexport type Box = Point & { w: number; h: number };\n\nexport type Mark = { id: string; page: number; author: string; at: string } & (\n | { kind: 'highlight' | 'underline' | 'strike'; rects: Box[]; text: string; color: string }\n | { kind: 'note'; spot: Point; text: string; color: string }\n | { kind: 'ink'; lines: Point[][]; width: number; color: string }\n | { kind: 'sign'; box: Box; image: string; method: SignatureMethod }\n);\n\nexport type Field = { page: number; name: string; box: Box; value: string | boolean | string[] };\n\nlet engine: Promise<PdfiumNative> | null = null;\n\nconst rect = (box: Box): Rect => ({ origin: { x: box.x, y: box.y }, size: { width: box.w, height: box.h } });\n\nconst around = (boxes: Box[]): Box => {\n const x = Math.min(...boxes.map(b => b.x));\n const y = Math.min(...boxes.map(b => b.y));\n return { x, y, w: Math.max(...boxes.map(b => b.x + b.w)) - x, h: Math.max(...boxes.map(b => b.y + b.h)) - y };\n};\n\nconst png = (url: string) => Uint8Array.from(atob(url.slice(url.indexOf(',') + 1)), c => c.charCodeAt(0)).buffer;\n\nconst types = { highlight: PdfAnnotationSubtype.HIGHLIGHT, underline: PdfAnnotationSubtype.UNDERLINE, strike: PdfAnnotationSubtype.STRIKEOUT } as const;\n\nfunction annotation(mark: Mark): PdfAnnotationObject {\n const base = { id: mark.id, pageIndex: mark.page - 1, author: mark.author, created: new Date(mark.at), modified: new Date(mark.at) };\n if (mark.kind === 'note') {\n return { ...base, type: PdfAnnotationSubtype.TEXT, rect: rect({ ...mark.spot, w: 20, h: 20 }), contents: mark.text, strokeColor: mark.color, opacity: 1 };\n }\n if (mark.kind === 'ink') {\n const spread = mark.width / 2 + 1;\n const bounds = around(mark.lines.flat().map(p => ({ x: p.x - spread, y: p.y - spread, w: spread * 2, h: spread * 2 })));\n return { ...base, type: PdfAnnotationSubtype.INK, rect: rect(bounds), inkList: mark.lines.map(points => ({ points })), strokeColor: mark.color, strokeWidth: mark.width, opacity: 1 };\n }\n if (mark.kind === 'sign') return { ...base, type: PdfAnnotationSubtype.STAMP, rect: rect(mark.box) };\n return {\n ...base, type: types[mark.kind], rect: rect(around(mark.rects)), segmentRects: mark.rects.map(rect), contents: mark.text, strokeColor: mark.color, opacity: 1,\n ...(mark.kind === 'highlight' ? { blendMode: PdfBlendMode.Multiply } : {}),\n } as PdfAnnotationObject;\n}\n\nexport async function write(bytes: ArrayBuffer, marks: Mark[], fields: Field[]): Promise<ArrayBuffer> {\n engine ??= init({}).then(module => new PdfiumNative(module));\n const pdfium = await engine;\n const doc = await pdfium.openDocumentBuffer({ id: Math.random().toString(36).slice(2), content: bytes.slice(0) }).toPromise();\n try {\n for (const n of new Set(fields.map(field => field.page))) {\n const page = doc.pages[n - 1];\n const widgets = await pdfium.getPageAnnoWidgets(doc, page).toPromise();\n for (const field of fields.filter(f => f.page === n)) {\n const centre = (r: Rect) => Math.hypot(r.origin.x + r.size.width / 2 - field.box.x - field.box.w / 2, r.origin.y + r.size.height / 2 - field.box.y - field.box.h / 2);\n const widget = widgets.filter(w => w.field.name === field.name).sort((a, b) => centre(a.rect) - centre(b.rect))[0];\n if (!widget) continue;\n const { type } = widget.field;\n if (type === PDF_FORM_FIELD_TYPE.TEXTFIELD) {\n await pdfium.setFormFieldValue(doc, page, widget, { kind: 'text', text: String(field.value) }).toPromise();\n } else if (type === PDF_FORM_FIELD_TYPE.CHECKBOX || (type === PDF_FORM_FIELD_TYPE.RADIOBUTTON && field.value === true)) {\n await pdfium.setFormFieldValue(doc, page, widget, { kind: 'checked', checked: field.value === true }).toPromise();\n } else if ('options' in widget.field && Array.isArray(field.value)) {\n for (const [index, option] of widget.field.options.entries()) {\n const wanted = field.value.includes(option.label);\n if (wanted !== option.isSelected) await pdfium.setFormFieldValue(doc, page, widget, { kind: 'selection', index, isSelected: wanted }).toPromise();\n }\n }\n }\n }\n for (const mark of marks) {\n const page = doc.pages[mark.page - 1];\n if (mark.kind === 'sign') await pdfium.createPageAnnotation(doc, page, annotation(mark), { data: png(mark.image), mimeType: 'image/png' } as never).toPromise();\n else await pdfium.createPageAnnotation(doc, page, annotation(mark)).toPromise();\n }\n return await pdfium.saveAsCopy(doc).toPromise();\n } finally {\n await pdfium.closeDocument(doc).toPromise();\n }\n}\n"],"mappings":"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","names":[]}