doit-lib 1.0.0 → 1.2.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/dist/index.d.ts +33 -1
- package/dist/index.js +1 -1
- package/dist/index.js.gz +0 -0
- package/package.json +14 -7
package/dist/index.d.ts
CHANGED
|
@@ -20,6 +20,15 @@ export type Operation = {
|
|
|
20
20
|
op: 'batch';
|
|
21
21
|
ops: Operation[];
|
|
22
22
|
};
|
|
23
|
+
interface StorageAdapter {
|
|
24
|
+
getItem(key: string): string | null;
|
|
25
|
+
setItem(key: string, value: string): void;
|
|
26
|
+
removeItem(key: string): void;
|
|
27
|
+
}
|
|
28
|
+
interface PersistOptions {
|
|
29
|
+
to: StorageAdapter;
|
|
30
|
+
key?: string;
|
|
31
|
+
}
|
|
23
32
|
export declare class DoIt {
|
|
24
33
|
private state;
|
|
25
34
|
private undoStack;
|
|
@@ -29,17 +38,40 @@ export declare class DoIt {
|
|
|
29
38
|
private pathCache;
|
|
30
39
|
private historyDirty;
|
|
31
40
|
private cachedHistory;
|
|
41
|
+
private storage?;
|
|
42
|
+
private storageKey;
|
|
32
43
|
constructor(initialState?: any, options?: {
|
|
33
44
|
maxHistory?: number;
|
|
34
45
|
});
|
|
35
46
|
getState(): any;
|
|
36
47
|
getHistory(): any;
|
|
37
|
-
set(path: string, value: any):
|
|
48
|
+
set(path: string, value: any, internal?: boolean): {
|
|
49
|
+
undoOp: {
|
|
50
|
+
op: "set";
|
|
51
|
+
path: string;
|
|
52
|
+
value: any;
|
|
53
|
+
} | {
|
|
54
|
+
op: "delete";
|
|
55
|
+
path: string;
|
|
56
|
+
};
|
|
57
|
+
redoOp: {
|
|
58
|
+
op: "set";
|
|
59
|
+
path: string;
|
|
60
|
+
value: any;
|
|
61
|
+
};
|
|
62
|
+
} | undefined;
|
|
63
|
+
batch(callback: (batch: {
|
|
64
|
+
set: (path: string, value: any) => void;
|
|
65
|
+
}) => void): void;
|
|
38
66
|
undo(): boolean;
|
|
39
67
|
redo(): boolean;
|
|
40
68
|
clearHistory(): void;
|
|
69
|
+
persist(options: PersistOptions): this;
|
|
70
|
+
unpersist(): void;
|
|
41
71
|
subscribe(fn: (state: any, history: any) => void): () => void;
|
|
42
72
|
private notify;
|
|
73
|
+
private saveToStorage;
|
|
74
|
+
private loadFromStorage;
|
|
43
75
|
private getParsedPath;
|
|
44
76
|
private cloneValue;
|
|
45
77
|
}
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var p=/([^\.\[\]]+)|\[(\d+)\]|\[(\w+):([^\]]+)\]/g,y=class{constructor(e={},t={}){this.undoStack=[];this.redoStack=[];this.listeners=[];this.pathCache=new Map;this.historyDirty=!0;this.storageKey="doit-state";this.state=e,this.maxHistory=t.maxHistory||100}getState(){return this.state}getHistory(){return this.historyDirty?(this.cachedHistory={undo:this.undoStack.length,redo:this.redoStack.length,canUndo:this.undoStack.length>0,canRedo:this.redoStack.length>0},this.historyDirty=!1,this.cachedHistory):this.cachedHistory}set(e,t,s=!1){let i=this.getParsedPath(e),r=v(this.state,i);if(r.exists&&c(r.value,t))return;let a;r.missingIndex!==-1?a={op:"delete",path:g(i.slice(0,r.missingIndex+1))}:a={op:"set",path:e,value:this.cloneValue(r.value)};let o={op:"set",path:e,value:t};return u(this.state,o),s||(this.undoStack.push({undo:a,redo:o}),this.redoStack=[],this.undoStack.length>this.maxHistory&&this.undoStack.shift(),this.notify()),{undoOp:a,redoOp:o}}batch(e){let t=[],s=[];if(e({set:(o,h)=>{let l=this.set(o,h,!0);l&&(t.push(l.undoOp),s.push(l.redoOp))}}),t.length===0)return;let r={op:"batch",ops:t.reverse()},a={op:"batch",ops:s};this.undoStack.push({undo:r,redo:a}),this.redoStack=[],this.undoStack.length>this.maxHistory&&this.undoStack.shift(),this.notify()}undo(){if(this.undoStack.length===0)return!1;let e=this.undoStack.pop();return u(this.state,e.undo),this.redoStack.push(e),this.notify(),!0}redo(){if(this.redoStack.length===0)return!1;let e=this.redoStack.pop();return u(this.state,e.redo),this.undoStack.push(e),this.notify(),!0}clearHistory(){this.undoStack=[],this.redoStack=[],this.pathCache.clear(),this.notify()}persist(e){return this.storage=e.to,this.storageKey=e.key||"doit-state",this.loadFromStorage(),this}unpersist(){this.storage=void 0}subscribe(e){return this.listeners.push(e),()=>{this.listeners=this.listeners.filter(t=>t!==e)}}notify(){this.historyDirty=!0;let e=this.getHistory();this.listeners.forEach(t=>t(this.state,e)),this.saveToStorage()}saveToStorage(){if(this.storage)try{let e={state:this.state,undoStack:this.undoStack,redoStack:this.redoStack};this.storage.setItem(this.storageKey,JSON.stringify(e))}catch(e){console.error("Failed to save to storage:",e)}}loadFromStorage(){if(this.storage)try{let e=this.storage.getItem(this.storageKey);if(!e)return;let t=JSON.parse(e);t.state&&(this.state=t.state),t.undoStack&&(this.undoStack=t.undoStack),t.redoStack&&(this.redoStack=t.redoStack),this.notify()}catch(e){console.error("Failed to load from storage:",e)}}getParsedPath(e){let t=this.pathCache.get(e);if(!t&&(t=f(e),this.pathCache.set(e,t),this.pathCache.size>1e3)){let s=this.pathCache.keys().next().value;s&&this.pathCache.delete(s)}return t}cloneValue(e){if(e==null||typeof e!="object")return e;if(Array.isArray(e))return e.map(s=>this.cloneValue(s));let t={};for(let s in e)e.hasOwnProperty(s)&&(t[s]=this.cloneValue(e[s]));return t}};function f(n){let e=[],t;for(;t=p.exec(n);)if(t[1])e.push({type:"key",value:t[1]});else if(t[2])e.push({type:"index",value:Number(t[2])});else if(t[3]){let s=t[4];isNaN(Number(s))?(s.startsWith("'")&&s.endsWith("'")||s.startsWith('"')&&s.endsWith('"'))&&(s=s.slice(1,-1)):s=Number(s),e.push({type:"filter",key:t[3],value:s})}return e}function g(n){return n.map((e,t)=>{if(e.type==="key")return(t>0?".":"")+e.value;if(e.type==="index")return`[${e.value}]`;if(e.type==="filter"){let s=typeof e.value=="string"?`"${e.value}"`:e.value;return`[${e.key}:${s}]`}return""}).join("")}function v(n,e){let t=n;for(let s=0;s<e.length;s++){let i=e[s];if(t==null)return{exists:!1,value:void 0,missingIndex:s};if(i.type==="key"){if(!(i.value in t))return{exists:!1,value:void 0,missingIndex:s};t=t[i.value]}else if(i.type==="index"){if(!Array.isArray(t))return{exists:!1,value:void 0,missingIndex:s};if(i.value<0||i.value>=t.length)return{exists:!1,value:void 0,missingIndex:s};t=t[i.value]}else if(i.type==="filter"){if(!Array.isArray(t))return{exists:!1,value:void 0,missingIndex:s};let r=t.find(a=>a[i.key]==i.value);if(!r)return{exists:!1,value:void 0,missingIndex:s};t=r}}return{exists:!0,value:t,missingIndex:-1}}function u(n,e){if(e.op==="batch"){e.ops.forEach(i=>u(n,i));return}let t=f(e.path),s=n;if(e.op==="delete"){for(let r=0;r<t.length-1;r++){let a=t[r];if(s=d(s,a,!1),!s)return}let i=t[t.length-1];if(i.type==="key")delete s[i.value];else if(i.type==="index"&&Array.isArray(s))s.splice(i.value,1);else if(i.type==="filter"&&Array.isArray(s)){let r=s.findIndex(a=>a[i.key]==i.value);r!==-1&&s.splice(r,1)}}else if(e.op==="set"){for(let r=0;r<t.length-1;r++){let a=t[r];s=d(s,a,!0)}let i=t[t.length-1];if(i.type==="key")s[i.value]=e.value;else if(i.type==="index")s[i.value]=e.value;else if(i.type==="filter"&&Array.isArray(s)){let r=s.find(a=>a&&a[i.key]==i.value);if(r||(r={[i.key]:i.value},s.push(r)),typeof e.value=="object"&&!Array.isArray(e.value))Object.assign(r,e.value);else{let a=s.indexOf(r);s[a]={...r,...e.value}}}}}function d(n,e,t){if(e.type==="key")return(n[e.value]===void 0||typeof n[e.value]!="object")&&t&&(n[e.value]={}),n[e.value];if(e.type==="index")return t&&n[e.value]===void 0&&(n[e.value]={}),n[e.value];if(e.type==="filter"){if(!Array.isArray(n))return;let s=n.find(i=>i[e.key]==e.value);return!s&&t&&(s={[e.key]:e.value},n.push(s)),s}}function c(n,e){if(n===e)return!0;if(n==null||e==null||typeof n!="object"||typeof e!="object")return!1;let t=Object.keys(n),s=Object.keys(e);if(t.length!==s.length)return!1;for(let i of t)if(!s.includes(i)||!c(n[i],e[i]))return!1;return!0}export{y as DoIt,u as applyOperation,f as parsePath,v as probe,g as reconstructPath};
|
package/dist/index.js.gz
ADDED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "doit-lib",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"test": "vitest run",
|
|
9
|
-
"build": "tsc --emitDeclarationOnly && esbuild src/index.ts --bundle --minify --format=esm --outfile=dist/index.js"
|
|
10
|
-
"build-obfus": "tsc --emitDeclarationOnly && node build.mjs"
|
|
9
|
+
"build": "tsc --emitDeclarationOnly && esbuild src/index.ts --bundle --minify --format=esm --outfile=dist/index.js && gzip -k -f dist/index.js"
|
|
11
10
|
},
|
|
12
|
-
"keywords": [
|
|
11
|
+
"keywords": [
|
|
12
|
+
"undo-redo",
|
|
13
|
+
"state-management",
|
|
14
|
+
"framework-agnostic",
|
|
15
|
+
"typescript"
|
|
16
|
+
],
|
|
13
17
|
"author": {
|
|
14
18
|
"name": "Khalif",
|
|
15
19
|
"email": "",
|
|
@@ -17,13 +21,16 @@
|
|
|
17
21
|
},
|
|
18
22
|
"license": "MIT",
|
|
19
23
|
"description": "",
|
|
20
|
-
"files": [
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"README.md",
|
|
27
|
+
"LICENSE"
|
|
28
|
+
],
|
|
21
29
|
"devDependencies": {
|
|
22
30
|
"@types/node": "^25.0.3",
|
|
23
31
|
"esbuild": "^0.27.2",
|
|
24
|
-
"javascript-obfuscator": "^5.1.0",
|
|
25
32
|
"terser": "^5.44.1",
|
|
26
33
|
"typescript": "^5.9.3",
|
|
27
34
|
"vitest": "^4.0.16"
|
|
28
35
|
}
|
|
29
|
-
}
|
|
36
|
+
}
|