fabricjs-document-engine 0.4.0 → 0.6.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.
- package/README.md +87 -3
- package/dist/engine/create-document-engine.cjs +199 -6
- package/dist/engine/create-document-engine.d.cts +42 -0
- package/dist/engine/create-document-engine.d.ts +42 -0
- package/dist/engine/create-document-engine.js +199 -6
- package/dist/engine/errors.cjs +2 -0
- package/dist/engine/errors.d.cts +6 -1
- package/dist/engine/errors.d.ts +6 -1
- package/dist/engine/errors.js +2 -0
- package/dist/export/download-export.cjs +14 -0
- package/dist/export/download-export.d.cts +7 -0
- package/dist/export/download-export.d.ts +7 -0
- package/dist/export/download-export.js +14 -0
- package/dist/export/export-area.cjs +46 -0
- package/dist/export/export-area.js +46 -0
- package/dist/export/export-options.cjs +47 -0
- package/dist/export/export-options.d.cts +20 -0
- package/dist/export/export-options.d.ts +20 -0
- package/dist/export/export-options.js +46 -0
- package/dist/export/preflight-export.cjs +105 -0
- package/dist/export/preflight-export.d.cts +17 -0
- package/dist/export/preflight-export.d.ts +17 -0
- package/dist/export/preflight-export.js +105 -0
- package/dist/export/render-export.cjs +69 -0
- package/dist/export/render-export.js +65 -0
- package/dist/history/apply-state.cjs +1 -1
- package/dist/history/apply-state.js +1 -1
- package/dist/index.cjs +5 -0
- package/dist/index.d.cts +7 -2
- package/dist/index.d.ts +7 -2
- package/dist/index.js +3 -1
- package/dist/migrations/migrate-document.cjs +65 -0
- package/dist/migrations/migrate-document.d.cts +15 -0
- package/dist/migrations/migrate-document.d.ts +15 -0
- package/dist/migrations/migrate-document.js +63 -0
- package/dist/storage/key-value-storage.cjs +27 -1
- package/dist/storage/key-value-storage.d.cts +2 -1
- package/dist/storage/key-value-storage.d.ts +2 -1
- package/dist/storage/key-value-storage.js +27 -1
- package/dist/storage.d.cts +2 -1
- package/dist/storage.d.ts +2 -1
- package/dist/versions/document-version.cjs +20 -0
- package/dist/versions/document-version.d.cts +25 -0
- package/dist/versions/document-version.d.ts +25 -0
- package/dist/versions/document-version.js +17 -0
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const require_errors = require("../engine/errors.cjs");
|
|
2
|
+
const require_document_version = require("../versions/document-version.cjs");
|
|
2
3
|
//#region src/storage/key-value-storage.ts
|
|
3
4
|
function readRevision(json) {
|
|
4
5
|
if (json === null) return 0;
|
|
@@ -6,7 +7,19 @@ function readRevision(json) {
|
|
|
6
7
|
return typeof revision === "number" ? revision : 0;
|
|
7
8
|
}
|
|
8
9
|
function createKeyValueStorage(store, prefix) {
|
|
10
|
+
const versionMarker = "::version::";
|
|
9
11
|
const keyFor = (id) => `${prefix}${id}`;
|
|
12
|
+
const versionPrefixFor = (documentId) => `${keyFor(documentId)}${versionMarker}`;
|
|
13
|
+
const versionKeyFor = (documentId, versionId) => `${versionPrefixFor(documentId)}${versionId}`;
|
|
14
|
+
function readVersion(documentId, versionId) {
|
|
15
|
+
const json = store.read(versionKeyFor(documentId, versionId));
|
|
16
|
+
if (json === null) throw new require_errors.DocumentEngineError("VERSION_NOT_FOUND", `Document "${documentId}" has no version "${versionId}"`);
|
|
17
|
+
return JSON.parse(json);
|
|
18
|
+
}
|
|
19
|
+
function versionKeysOf(documentId) {
|
|
20
|
+
const versionPrefix = versionPrefixFor(documentId);
|
|
21
|
+
return store.keys().filter((key) => key.startsWith(versionPrefix));
|
|
22
|
+
}
|
|
10
23
|
return {
|
|
11
24
|
async loadDocument(id) {
|
|
12
25
|
const json = store.read(keyFor(id));
|
|
@@ -24,10 +37,23 @@ function createKeyValueStorage(store, prefix) {
|
|
|
24
37
|
return { revision };
|
|
25
38
|
},
|
|
26
39
|
async listDocuments() {
|
|
27
|
-
return store.keys().filter((key) => key.startsWith(prefix)).map((key) => key.slice(prefix.length));
|
|
40
|
+
return store.keys().filter((key) => key.startsWith(prefix) && !key.includes(versionMarker)).map((key) => key.slice(prefix.length));
|
|
28
41
|
},
|
|
29
42
|
async deleteDocument(id) {
|
|
43
|
+
versionKeysOf(id).forEach((key) => store.remove(key));
|
|
30
44
|
store.remove(keyFor(id));
|
|
45
|
+
},
|
|
46
|
+
async saveVersion(version) {
|
|
47
|
+
store.write(versionKeyFor(version.documentId, version.id), JSON.stringify(version));
|
|
48
|
+
},
|
|
49
|
+
async listVersions(documentId) {
|
|
50
|
+
return versionKeysOf(documentId).map((key) => require_document_version.summarize(JSON.parse(store.read(key) ?? "null"))).sort(require_document_version.newestFirst);
|
|
51
|
+
},
|
|
52
|
+
async loadVersion(documentId, versionId) {
|
|
53
|
+
return readVersion(documentId, versionId);
|
|
54
|
+
},
|
|
55
|
+
async deleteVersion(documentId, versionId) {
|
|
56
|
+
store.remove(versionKeyFor(documentId, versionId));
|
|
31
57
|
}
|
|
32
58
|
};
|
|
33
59
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { VersionStorage } from "../versions/document-version.cjs";
|
|
1
2
|
import { DocumentStorage } from "./storage-contract.cjs";
|
|
2
3
|
//#region src/storage/key-value-storage.d.ts
|
|
3
4
|
export interface KeyValueStore {
|
|
@@ -6,7 +7,7 @@ export interface KeyValueStore {
|
|
|
6
7
|
remove(key: string): void;
|
|
7
8
|
keys(): string[];
|
|
8
9
|
}
|
|
9
|
-
export interface ManagedDocumentStorage extends DocumentStorage {
|
|
10
|
+
export interface ManagedDocumentStorage extends DocumentStorage, VersionStorage {
|
|
10
11
|
listDocuments(): Promise<string[]>;
|
|
11
12
|
deleteDocument(id: string): Promise<void>;
|
|
12
13
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { VersionStorage } from "../versions/document-version.js";
|
|
1
2
|
import { DocumentStorage } from "./storage-contract.js";
|
|
2
3
|
//#region src/storage/key-value-storage.d.ts
|
|
3
4
|
export interface KeyValueStore {
|
|
@@ -6,7 +7,7 @@ export interface KeyValueStore {
|
|
|
6
7
|
remove(key: string): void;
|
|
7
8
|
keys(): string[];
|
|
8
9
|
}
|
|
9
|
-
export interface ManagedDocumentStorage extends DocumentStorage {
|
|
10
|
+
export interface ManagedDocumentStorage extends DocumentStorage, VersionStorage {
|
|
10
11
|
listDocuments(): Promise<string[]>;
|
|
11
12
|
deleteDocument(id: string): Promise<void>;
|
|
12
13
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DocumentEngineError, createConflictError } from "../engine/errors.js";
|
|
2
|
+
import { newestFirst, summarize } from "../versions/document-version.js";
|
|
2
3
|
//#region src/storage/key-value-storage.ts
|
|
3
4
|
function readRevision(json) {
|
|
4
5
|
if (json === null) return 0;
|
|
@@ -6,7 +7,19 @@ function readRevision(json) {
|
|
|
6
7
|
return typeof revision === "number" ? revision : 0;
|
|
7
8
|
}
|
|
8
9
|
function createKeyValueStorage(store, prefix) {
|
|
10
|
+
const versionMarker = "::version::";
|
|
9
11
|
const keyFor = (id) => `${prefix}${id}`;
|
|
12
|
+
const versionPrefixFor = (documentId) => `${keyFor(documentId)}${versionMarker}`;
|
|
13
|
+
const versionKeyFor = (documentId, versionId) => `${versionPrefixFor(documentId)}${versionId}`;
|
|
14
|
+
function readVersion(documentId, versionId) {
|
|
15
|
+
const json = store.read(versionKeyFor(documentId, versionId));
|
|
16
|
+
if (json === null) throw new DocumentEngineError("VERSION_NOT_FOUND", `Document "${documentId}" has no version "${versionId}"`);
|
|
17
|
+
return JSON.parse(json);
|
|
18
|
+
}
|
|
19
|
+
function versionKeysOf(documentId) {
|
|
20
|
+
const versionPrefix = versionPrefixFor(documentId);
|
|
21
|
+
return store.keys().filter((key) => key.startsWith(versionPrefix));
|
|
22
|
+
}
|
|
10
23
|
return {
|
|
11
24
|
async loadDocument(id) {
|
|
12
25
|
const json = store.read(keyFor(id));
|
|
@@ -24,10 +37,23 @@ function createKeyValueStorage(store, prefix) {
|
|
|
24
37
|
return { revision };
|
|
25
38
|
},
|
|
26
39
|
async listDocuments() {
|
|
27
|
-
return store.keys().filter((key) => key.startsWith(prefix)).map((key) => key.slice(prefix.length));
|
|
40
|
+
return store.keys().filter((key) => key.startsWith(prefix) && !key.includes(versionMarker)).map((key) => key.slice(prefix.length));
|
|
28
41
|
},
|
|
29
42
|
async deleteDocument(id) {
|
|
43
|
+
versionKeysOf(id).forEach((key) => store.remove(key));
|
|
30
44
|
store.remove(keyFor(id));
|
|
45
|
+
},
|
|
46
|
+
async saveVersion(version) {
|
|
47
|
+
store.write(versionKeyFor(version.documentId, version.id), JSON.stringify(version));
|
|
48
|
+
},
|
|
49
|
+
async listVersions(documentId) {
|
|
50
|
+
return versionKeysOf(documentId).map((key) => summarize(JSON.parse(store.read(key) ?? "null"))).sort(newestFirst);
|
|
51
|
+
},
|
|
52
|
+
async loadVersion(documentId, versionId) {
|
|
53
|
+
return readVersion(documentId, versionId);
|
|
54
|
+
},
|
|
55
|
+
async deleteVersion(documentId, versionId) {
|
|
56
|
+
store.remove(versionKeyFor(documentId, versionId));
|
|
31
57
|
}
|
|
32
58
|
};
|
|
33
59
|
}
|
package/dist/storage.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { DocumentVersion, VersionStorage, VersionSummary } from "./versions/document-version.cjs";
|
|
1
2
|
import { DocumentStorage, SaveContext, SaveResult } from "./storage/storage-contract.cjs";
|
|
2
3
|
import { KeyValueStore, ManagedDocumentStorage, createKeyValueStorage } from "./storage/key-value-storage.cjs";
|
|
3
4
|
import { createMemoryStorage } from "./storage/memory-storage.cjs";
|
|
4
5
|
import { LocalStorageOptions, createLocalStorage } from "./storage/local-storage.cjs";
|
|
5
|
-
export { type DocumentStorage, type KeyValueStore, type LocalStorageOptions, type ManagedDocumentStorage, type SaveContext, type SaveResult, createKeyValueStorage, createLocalStorage, createMemoryStorage };
|
|
6
|
+
export { type DocumentStorage, type DocumentVersion, type KeyValueStore, type LocalStorageOptions, type ManagedDocumentStorage, type SaveContext, type SaveResult, type VersionStorage, type VersionSummary, createKeyValueStorage, createLocalStorage, createMemoryStorage };
|
package/dist/storage.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { DocumentVersion, VersionStorage, VersionSummary } from "./versions/document-version.js";
|
|
1
2
|
import { DocumentStorage, SaveContext, SaveResult } from "./storage/storage-contract.js";
|
|
2
3
|
import { KeyValueStore, ManagedDocumentStorage, createKeyValueStorage } from "./storage/key-value-storage.js";
|
|
3
4
|
import { createMemoryStorage } from "./storage/memory-storage.js";
|
|
4
5
|
import { LocalStorageOptions, createLocalStorage } from "./storage/local-storage.js";
|
|
5
|
-
export { type DocumentStorage, type KeyValueStore, type LocalStorageOptions, type ManagedDocumentStorage, type SaveContext, type SaveResult, createKeyValueStorage, createLocalStorage, createMemoryStorage };
|
|
6
|
+
export { type DocumentStorage, type DocumentVersion, type KeyValueStore, type LocalStorageOptions, type ManagedDocumentStorage, type SaveContext, type SaveResult, type VersionStorage, type VersionSummary, createKeyValueStorage, createLocalStorage, createMemoryStorage };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/versions/document-version.ts
|
|
2
|
+
function summarize(version) {
|
|
3
|
+
const { document: _document, ...summary } = version;
|
|
4
|
+
return summary;
|
|
5
|
+
}
|
|
6
|
+
function newestFirst(first, second) {
|
|
7
|
+
return second.createdAt.localeCompare(first.createdAt);
|
|
8
|
+
}
|
|
9
|
+
function versionsToPrune(versions, keepAuto) {
|
|
10
|
+
return versions.filter((version) => version.kind === "auto").sort(newestFirst).slice(Math.max(0, keepAuto));
|
|
11
|
+
}
|
|
12
|
+
function supportsVersions(storage) {
|
|
13
|
+
const candidate = storage;
|
|
14
|
+
return typeof candidate?.saveVersion === "function" && typeof candidate.listVersions === "function" && typeof candidate.loadVersion === "function" && typeof candidate.deleteVersion === "function";
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
exports.newestFirst = newestFirst;
|
|
18
|
+
exports.summarize = summarize;
|
|
19
|
+
exports.supportsVersions = supportsVersions;
|
|
20
|
+
exports.versionsToPrune = versionsToPrune;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { FabricDocument } from "../document/document-format.cjs";
|
|
2
|
+
//#region src/versions/document-version.d.ts
|
|
3
|
+
export type VersionKind = "named" | "auto";
|
|
4
|
+
export interface VersionSummary {
|
|
5
|
+
id: string;
|
|
6
|
+
documentId: string;
|
|
7
|
+
name: string;
|
|
8
|
+
kind: VersionKind;
|
|
9
|
+
createdAt: string;
|
|
10
|
+
revision: number;
|
|
11
|
+
}
|
|
12
|
+
export interface DocumentVersion extends VersionSummary {
|
|
13
|
+
document: FabricDocument;
|
|
14
|
+
}
|
|
15
|
+
export interface VersionStorage {
|
|
16
|
+
saveVersion(version: DocumentVersion): Promise<void>;
|
|
17
|
+
listVersions(documentId: string): Promise<VersionSummary[]>;
|
|
18
|
+
loadVersion(documentId: string, versionId: string): Promise<DocumentVersion>;
|
|
19
|
+
deleteVersion(documentId: string, versionId: string): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
export interface VersionOptions {
|
|
22
|
+
keepAuto?: number;
|
|
23
|
+
autoEvery?: number;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { FabricDocument } from "../document/document-format.js";
|
|
2
|
+
//#region src/versions/document-version.d.ts
|
|
3
|
+
export type VersionKind = "named" | "auto";
|
|
4
|
+
export interface VersionSummary {
|
|
5
|
+
id: string;
|
|
6
|
+
documentId: string;
|
|
7
|
+
name: string;
|
|
8
|
+
kind: VersionKind;
|
|
9
|
+
createdAt: string;
|
|
10
|
+
revision: number;
|
|
11
|
+
}
|
|
12
|
+
export interface DocumentVersion extends VersionSummary {
|
|
13
|
+
document: FabricDocument;
|
|
14
|
+
}
|
|
15
|
+
export interface VersionStorage {
|
|
16
|
+
saveVersion(version: DocumentVersion): Promise<void>;
|
|
17
|
+
listVersions(documentId: string): Promise<VersionSummary[]>;
|
|
18
|
+
loadVersion(documentId: string, versionId: string): Promise<DocumentVersion>;
|
|
19
|
+
deleteVersion(documentId: string, versionId: string): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
export interface VersionOptions {
|
|
22
|
+
keepAuto?: number;
|
|
23
|
+
autoEvery?: number;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/versions/document-version.ts
|
|
2
|
+
function summarize(version) {
|
|
3
|
+
const { document: _document, ...summary } = version;
|
|
4
|
+
return summary;
|
|
5
|
+
}
|
|
6
|
+
function newestFirst(first, second) {
|
|
7
|
+
return second.createdAt.localeCompare(first.createdAt);
|
|
8
|
+
}
|
|
9
|
+
function versionsToPrune(versions, keepAuto) {
|
|
10
|
+
return versions.filter((version) => version.kind === "auto").sort(newestFirst).slice(Math.max(0, keepAuto));
|
|
11
|
+
}
|
|
12
|
+
function supportsVersions(storage) {
|
|
13
|
+
const candidate = storage;
|
|
14
|
+
return typeof candidate?.saveVersion === "function" && typeof candidate.listVersions === "function" && typeof candidate.loadVersion === "function" && typeof candidate.deleteVersion === "function";
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { newestFirst, summarize, supportsVersions, versionsToPrune };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fabricjs-document-engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Turn an existing Fabric.js canvas into a dependable editable document: stable object ids, versioned save and load, undo and redo, safe autosave with conflict protection, custom objects and clear errors.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fabric",
|