pixel-data-js 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Carl Olsen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # Pixel Data JS
2
+
3
+ A library of functions for interacting with pixel data and ImageData objects.
4
+ This package is designed to be a tree-shake friendly list of functions.
5
+
6
+ ## Installation
7
+
8
+ `$ npm i pixel-data-js`
9
+
10
+
11
+ ## Example Usage
12
+
13
+
14
+ ## Building
15
+
16
+ `$ pnpm install`
17
+ `$ pnpm run build`
18
+
19
+ ## Testing
20
+
21
+ `$ pnpm run test`
22
+ `$ pnpm run test:mutation`
23
+
24
+ ## Releases Automation
25
+
26
+ - update `package.json` file version (example: `1.0.99`)
27
+ - manually create a github release with a tag matching the `package.json` version prefixed with `v` (example: `v1.0.99`)
28
+ - npm should be updated automatically
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ createPiniaSimplePersist: () => createPiniaSimplePersist,
24
+ makeSimplePersistMapper: () => makeSimplePersistMapper
25
+ });
26
+ module.exports = __toCommonJS(src_exports);
27
+
28
+ // src/plugin.ts
29
+ var import_pinia = require("pinia");
30
+ function createPiniaSimplePersist(globalOptions = {}) {
31
+ const makeKey = globalOptions.makeKey ?? ((id) => `pinia-${id}`);
32
+ return (context) => {
33
+ const { store, options } = context;
34
+ ensureStoreHasRestoreState(store);
35
+ ensureStoreHasSerializeState(store);
36
+ const persist = options.persist;
37
+ if (!persist) return;
38
+ const {
39
+ key = makeKey(store.$id),
40
+ storage = localStorage,
41
+ serializer = {
42
+ serialize: JSON.stringify,
43
+ deserialize: JSON.parse
44
+ },
45
+ debounce = 0,
46
+ beforeRestore,
47
+ afterRestore,
48
+ onRestoreError
49
+ } = { ...globalOptions, ...persist };
50
+ const restoreState = () => {
51
+ beforeRestore?.(context);
52
+ const stored = storage.getItem(key);
53
+ if (!stored) return;
54
+ try {
55
+ const data = serializer.deserialize(stored);
56
+ store.$restoreState(data);
57
+ afterRestore?.(context);
58
+ } catch (error) {
59
+ if (onRestoreError) {
60
+ onRestoreError(error instanceof Error ? error : new Error(String(error)));
61
+ } else {
62
+ throw error;
63
+ }
64
+ }
65
+ };
66
+ const saveState = () => {
67
+ const state = store.$serializeState();
68
+ const serialized = serializer.serialize(state);
69
+ storage.setItem(key, serialized);
70
+ };
71
+ let finalSave = saveState;
72
+ let cleanupDebounce;
73
+ if (debounce) {
74
+ const { debouncedFn, cleanup } = makeDebounce(saveState, debounce);
75
+ finalSave = debouncedFn;
76
+ cleanupDebounce = cleanup;
77
+ }
78
+ const unsubscribe = store.$subscribe(() => {
79
+ finalSave();
80
+ }, { detached: true });
81
+ const originalDispose = store.$dispose;
82
+ store.$dispose = function() {
83
+ unsubscribe();
84
+ cleanupDebounce?.();
85
+ originalDispose.call(this);
86
+ };
87
+ restoreState();
88
+ };
89
+ }
90
+ var makeDebounce = (callback, waitFor) => {
91
+ let timeout;
92
+ const debouncedFn = () => {
93
+ if (timeout) clearTimeout(timeout);
94
+ timeout = setTimeout(() => {
95
+ callback();
96
+ }, waitFor);
97
+ };
98
+ const cleanup = () => {
99
+ if (timeout) {
100
+ clearTimeout(timeout);
101
+ timeout = void 0;
102
+ }
103
+ };
104
+ return { debouncedFn, cleanup };
105
+ };
106
+ function ensureStoreHasRestoreState(store) {
107
+ if (typeof store.$restoreState !== "function") {
108
+ throw new Error("A store using pinia-simple-persist must have a $restoreState() method");
109
+ }
110
+ }
111
+ function ensureStoreHasSerializeState(store) {
112
+ if (typeof store.$serializeState !== "function") {
113
+ throw new Error("A store using pinia-simple-persist must have a $serializeState() method");
114
+ }
115
+ }
116
+
117
+ // src/mapper.ts
118
+ var import_vue = require("vue");
119
+ function makeSimplePersistMapper(state, defaults) {
120
+ return {
121
+ $serializeState() {
122
+ const out = {};
123
+ for (const key in state) {
124
+ const item = state[key];
125
+ let value;
126
+ if ((0, import_vue.isRef)(item)) {
127
+ value = item.value;
128
+ } else {
129
+ value = item;
130
+ }
131
+ out[key] = (0, import_vue.isReactive)(value) ? (0, import_vue.toRaw)(value) : value;
132
+ }
133
+ return out;
134
+ },
135
+ $restoreState(data) {
136
+ for (const key in state) {
137
+ if (!(key in data)) continue;
138
+ const item = state[key];
139
+ if ((0, import_vue.isRef)(item)) {
140
+ item.value = data[key];
141
+ } else if ((0, import_vue.isReactive)(item)) {
142
+ Object.assign(item, data[key]);
143
+ }
144
+ }
145
+ },
146
+ $reset() {
147
+ for (const key in state) {
148
+ const item = state[key];
149
+ if ((0, import_vue.isRef)(item)) {
150
+ item.value = defaults[key];
151
+ } else if ((0, import_vue.isReactive)(item)) {
152
+ Object.assign(item, defaults[key]);
153
+ }
154
+ }
155
+ }
156
+ };
157
+ }
158
+ // Annotate the CommonJS export names for ESM import in node:
159
+ 0 && (module.exports = {
160
+ createPiniaSimplePersist,
161
+ makeSimplePersistMapper
162
+ });
163
+ //# sourceMappingURL=index.dev.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/plugin.ts","../src/mapper.ts"],"sourcesContent":["export * from './plugin'\nexport { makeSimplePersistMapper } from './mapper'\n","import type { PiniaPluginContext } from 'pinia'\nimport 'pinia'\nimport type { Serializer, StorageLike } from './types'\n\nexport type BaseSimplePersistOptions<Serialized> = {\n storage?: StorageLike\n serializer?: Serializer<Serialized>,\n debounce?: number\n beforeRestore?: (context: PiniaPluginContext) => void\n afterRestore?: (context: PiniaPluginContext) => void,\n onRestoreError?: (err: Error) => void,\n}\n\nexport type GlobalSimplePersistOptions = BaseSimplePersistOptions<any> & {\n makeKey?: (storeId: string) => string,\n}\n\nexport type SimplePersistOptions<Serialized> = BaseSimplePersistOptions<Serialized> & {\n key?: string,\n}\n\nexport function createPiniaSimplePersist(globalOptions: GlobalSimplePersistOptions = {}) {\n const makeKey = globalOptions.makeKey ?? ((id: string) => `pinia-${id}`)\n\n return (context: PiniaPluginContext) => {\n const { store, options } = context\n\n ensureStoreHasRestoreState(store)\n ensureStoreHasSerializeState(store)\n\n const persist = options.persist as SimplePersistOptions<any> | undefined\n if (!persist) return\n\n const {\n key = makeKey(store.$id),\n storage = localStorage,\n serializer = {\n serialize: JSON.stringify,\n deserialize: JSON.parse,\n },\n debounce = 0,\n beforeRestore,\n afterRestore,\n onRestoreError,\n } = { ...globalOptions, ...persist }\n\n const restoreState = () => {\n beforeRestore?.(context)\n\n const stored = storage.getItem(key)\n if (!stored) return\n\n try {\n const data = serializer.deserialize(stored)\n store.$restoreState(data)\n afterRestore?.(context)\n } catch (error) {\n if (onRestoreError) {\n onRestoreError(error instanceof Error ? error : new Error(String(error)))\n } else {\n throw error\n }\n }\n }\n\n const saveState = () => {\n const state = store.$serializeState()\n const serialized = serializer.serialize(state)\n storage.setItem(key, serialized)\n }\n\n let finalSave = saveState\n let cleanupDebounce: (() => void) | undefined\n\n if (debounce) {\n const { debouncedFn, cleanup } = makeDebounce(saveState, debounce)\n finalSave = debouncedFn\n cleanupDebounce = cleanup\n }\n\n // Watch for changes and persist\n const unsubscribe = store.$subscribe(() => {\n finalSave()\n }, { detached: true })\n\n // Cleanup on store disposal\n const originalDispose = store.$dispose\n store.$dispose = function() {\n unsubscribe()\n cleanupDebounce?.()\n originalDispose.call(this)\n }\n\n // Restore state on initialization\n restoreState()\n }\n}\n\nconst makeDebounce = <T extends () => void>(\n callback: T,\n waitFor: number,\n) => {\n let timeout: ReturnType<typeof setTimeout> | undefined\n\n const debouncedFn = (): void => {\n if (timeout) clearTimeout(timeout)\n timeout = setTimeout(() => {\n callback()\n }, waitFor)\n }\n\n const cleanup = (): void => {\n if (timeout) {\n clearTimeout(timeout)\n timeout = undefined\n }\n }\n\n return { debouncedFn, cleanup }\n}\n\nfunction ensureStoreHasRestoreState<T>(store: T): asserts store is T & { $restoreState: (data: any) => void } {\n if (typeof (store as any).$restoreState !== 'function') {\n throw new Error('A store using pinia-simple-persist must have a $restoreState() method')\n }\n}\n\nfunction ensureStoreHasSerializeState<T>(store: T): asserts store is T & { $serializeState: () => any } {\n if (typeof (store as any).$serializeState !== 'function') {\n throw new Error('A store using pinia-simple-persist must have a $serializeState() method')\n }\n}\n","import type { Ref } from 'vue'\nimport { toRaw, isRef, isReactive } from 'vue'\n\ntype RefOrReactive<T> = Ref<T> | T\n\nexport function makeSimplePersistMapper<T extends Record<string, any>>(\n state: { [K in keyof T]: RefOrReactive<T[K]> },\n defaults: T,\n) {\n return {\n $serializeState(): T {\n const out = {} as T\n for (const key in state) {\n const item = state[key]\n let value: any\n\n if (isRef(item)) {\n value = item.value\n } else {\n value = item\n }\n\n out[key] = isReactive(value) ? toRaw(value) : value\n }\n return out\n },\n\n $restoreState(data: T) {\n for (const key in state) {\n if (!(key in data)) continue\n\n const item = state[key]\n\n if (isRef(item)) {\n item.value = data[key]\n } else if (isReactive(item)) {\n Object.assign(item, data[key])\n }\n }\n },\n\n $reset() {\n for (const key in state) {\n const item = state[key]\n\n if (isRef(item)) {\n item.value = defaults[key]\n } else if (isReactive(item)) {\n Object.assign(item, defaults[key])\n }\n }\n },\n }\n}"],"mappings":"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","names":[]}
@@ -0,0 +1,135 @@
1
+ // src/plugin.ts
2
+ import "pinia";
3
+ function createPiniaSimplePersist(globalOptions = {}) {
4
+ const makeKey = globalOptions.makeKey ?? ((id) => `pinia-${id}`);
5
+ return (context) => {
6
+ const { store, options } = context;
7
+ ensureStoreHasRestoreState(store);
8
+ ensureStoreHasSerializeState(store);
9
+ const persist = options.persist;
10
+ if (!persist) return;
11
+ const {
12
+ key = makeKey(store.$id),
13
+ storage = localStorage,
14
+ serializer = {
15
+ serialize: JSON.stringify,
16
+ deserialize: JSON.parse
17
+ },
18
+ debounce = 0,
19
+ beforeRestore,
20
+ afterRestore,
21
+ onRestoreError
22
+ } = { ...globalOptions, ...persist };
23
+ const restoreState = () => {
24
+ beforeRestore?.(context);
25
+ const stored = storage.getItem(key);
26
+ if (!stored) return;
27
+ try {
28
+ const data = serializer.deserialize(stored);
29
+ store.$restoreState(data);
30
+ afterRestore?.(context);
31
+ } catch (error) {
32
+ if (onRestoreError) {
33
+ onRestoreError(error instanceof Error ? error : new Error(String(error)));
34
+ } else {
35
+ throw error;
36
+ }
37
+ }
38
+ };
39
+ const saveState = () => {
40
+ const state = store.$serializeState();
41
+ const serialized = serializer.serialize(state);
42
+ storage.setItem(key, serialized);
43
+ };
44
+ let finalSave = saveState;
45
+ let cleanupDebounce;
46
+ if (debounce) {
47
+ const { debouncedFn, cleanup } = makeDebounce(saveState, debounce);
48
+ finalSave = debouncedFn;
49
+ cleanupDebounce = cleanup;
50
+ }
51
+ const unsubscribe = store.$subscribe(() => {
52
+ finalSave();
53
+ }, { detached: true });
54
+ const originalDispose = store.$dispose;
55
+ store.$dispose = function() {
56
+ unsubscribe();
57
+ cleanupDebounce?.();
58
+ originalDispose.call(this);
59
+ };
60
+ restoreState();
61
+ };
62
+ }
63
+ var makeDebounce = (callback, waitFor) => {
64
+ let timeout;
65
+ const debouncedFn = () => {
66
+ if (timeout) clearTimeout(timeout);
67
+ timeout = setTimeout(() => {
68
+ callback();
69
+ }, waitFor);
70
+ };
71
+ const cleanup = () => {
72
+ if (timeout) {
73
+ clearTimeout(timeout);
74
+ timeout = void 0;
75
+ }
76
+ };
77
+ return { debouncedFn, cleanup };
78
+ };
79
+ function ensureStoreHasRestoreState(store) {
80
+ if (typeof store.$restoreState !== "function") {
81
+ throw new Error("A store using pinia-simple-persist must have a $restoreState() method");
82
+ }
83
+ }
84
+ function ensureStoreHasSerializeState(store) {
85
+ if (typeof store.$serializeState !== "function") {
86
+ throw new Error("A store using pinia-simple-persist must have a $serializeState() method");
87
+ }
88
+ }
89
+
90
+ // src/mapper.ts
91
+ import { toRaw, isRef, isReactive } from "vue";
92
+ function makeSimplePersistMapper(state, defaults) {
93
+ return {
94
+ $serializeState() {
95
+ const out = {};
96
+ for (const key in state) {
97
+ const item = state[key];
98
+ let value;
99
+ if (isRef(item)) {
100
+ value = item.value;
101
+ } else {
102
+ value = item;
103
+ }
104
+ out[key] = isReactive(value) ? toRaw(value) : value;
105
+ }
106
+ return out;
107
+ },
108
+ $restoreState(data) {
109
+ for (const key in state) {
110
+ if (!(key in data)) continue;
111
+ const item = state[key];
112
+ if (isRef(item)) {
113
+ item.value = data[key];
114
+ } else if (isReactive(item)) {
115
+ Object.assign(item, data[key]);
116
+ }
117
+ }
118
+ },
119
+ $reset() {
120
+ for (const key in state) {
121
+ const item = state[key];
122
+ if (isRef(item)) {
123
+ item.value = defaults[key];
124
+ } else if (isReactive(item)) {
125
+ Object.assign(item, defaults[key]);
126
+ }
127
+ }
128
+ }
129
+ };
130
+ }
131
+ export {
132
+ createPiniaSimplePersist,
133
+ makeSimplePersistMapper
134
+ };
135
+ //# sourceMappingURL=index.dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/plugin.ts","../src/mapper.ts"],"sourcesContent":["import type { PiniaPluginContext } from 'pinia'\nimport 'pinia'\nimport type { Serializer, StorageLike } from './types'\n\nexport type BaseSimplePersistOptions<Serialized> = {\n storage?: StorageLike\n serializer?: Serializer<Serialized>,\n debounce?: number\n beforeRestore?: (context: PiniaPluginContext) => void\n afterRestore?: (context: PiniaPluginContext) => void,\n onRestoreError?: (err: Error) => void,\n}\n\nexport type GlobalSimplePersistOptions = BaseSimplePersistOptions<any> & {\n makeKey?: (storeId: string) => string,\n}\n\nexport type SimplePersistOptions<Serialized> = BaseSimplePersistOptions<Serialized> & {\n key?: string,\n}\n\nexport function createPiniaSimplePersist(globalOptions: GlobalSimplePersistOptions = {}) {\n const makeKey = globalOptions.makeKey ?? ((id: string) => `pinia-${id}`)\n\n return (context: PiniaPluginContext) => {\n const { store, options } = context\n\n ensureStoreHasRestoreState(store)\n ensureStoreHasSerializeState(store)\n\n const persist = options.persist as SimplePersistOptions<any> | undefined\n if (!persist) return\n\n const {\n key = makeKey(store.$id),\n storage = localStorage,\n serializer = {\n serialize: JSON.stringify,\n deserialize: JSON.parse,\n },\n debounce = 0,\n beforeRestore,\n afterRestore,\n onRestoreError,\n } = { ...globalOptions, ...persist }\n\n const restoreState = () => {\n beforeRestore?.(context)\n\n const stored = storage.getItem(key)\n if (!stored) return\n\n try {\n const data = serializer.deserialize(stored)\n store.$restoreState(data)\n afterRestore?.(context)\n } catch (error) {\n if (onRestoreError) {\n onRestoreError(error instanceof Error ? error : new Error(String(error)))\n } else {\n throw error\n }\n }\n }\n\n const saveState = () => {\n const state = store.$serializeState()\n const serialized = serializer.serialize(state)\n storage.setItem(key, serialized)\n }\n\n let finalSave = saveState\n let cleanupDebounce: (() => void) | undefined\n\n if (debounce) {\n const { debouncedFn, cleanup } = makeDebounce(saveState, debounce)\n finalSave = debouncedFn\n cleanupDebounce = cleanup\n }\n\n // Watch for changes and persist\n const unsubscribe = store.$subscribe(() => {\n finalSave()\n }, { detached: true })\n\n // Cleanup on store disposal\n const originalDispose = store.$dispose\n store.$dispose = function() {\n unsubscribe()\n cleanupDebounce?.()\n originalDispose.call(this)\n }\n\n // Restore state on initialization\n restoreState()\n }\n}\n\nconst makeDebounce = <T extends () => void>(\n callback: T,\n waitFor: number,\n) => {\n let timeout: ReturnType<typeof setTimeout> | undefined\n\n const debouncedFn = (): void => {\n if (timeout) clearTimeout(timeout)\n timeout = setTimeout(() => {\n callback()\n }, waitFor)\n }\n\n const cleanup = (): void => {\n if (timeout) {\n clearTimeout(timeout)\n timeout = undefined\n }\n }\n\n return { debouncedFn, cleanup }\n}\n\nfunction ensureStoreHasRestoreState<T>(store: T): asserts store is T & { $restoreState: (data: any) => void } {\n if (typeof (store as any).$restoreState !== 'function') {\n throw new Error('A store using pinia-simple-persist must have a $restoreState() method')\n }\n}\n\nfunction ensureStoreHasSerializeState<T>(store: T): asserts store is T & { $serializeState: () => any } {\n if (typeof (store as any).$serializeState !== 'function') {\n throw new Error('A store using pinia-simple-persist must have a $serializeState() method')\n }\n}\n","import type { Ref } from 'vue'\nimport { toRaw, isRef, isReactive } from 'vue'\n\ntype RefOrReactive<T> = Ref<T> | T\n\nexport function makeSimplePersistMapper<T extends Record<string, any>>(\n state: { [K in keyof T]: RefOrReactive<T[K]> },\n defaults: T,\n) {\n return {\n $serializeState(): T {\n const out = {} as T\n for (const key in state) {\n const item = state[key]\n let value: any\n\n if (isRef(item)) {\n value = item.value\n } else {\n value = item\n }\n\n out[key] = isReactive(value) ? toRaw(value) : value\n }\n return out\n },\n\n $restoreState(data: T) {\n for (const key in state) {\n if (!(key in data)) continue\n\n const item = state[key]\n\n if (isRef(item)) {\n item.value = data[key]\n } else if (isReactive(item)) {\n Object.assign(item, data[key])\n }\n }\n },\n\n $reset() {\n for (const key in state) {\n const item = state[key]\n\n if (isRef(item)) {\n item.value = defaults[key]\n } else if (isReactive(item)) {\n Object.assign(item, defaults[key])\n }\n }\n },\n }\n}"],"mappings":"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","names":[]}
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ createPiniaSimplePersist: () => createPiniaSimplePersist,
24
+ makeSimplePersistMapper: () => makeSimplePersistMapper
25
+ });
26
+ module.exports = __toCommonJS(src_exports);
27
+
28
+ // src/plugin.ts
29
+ var import_pinia = require("pinia");
30
+ function createPiniaSimplePersist(globalOptions = {}) {
31
+ const makeKey = globalOptions.makeKey ?? ((id) => `pinia-${id}`);
32
+ return (context) => {
33
+ const { store, options } = context;
34
+ ensureStoreHasRestoreState(store);
35
+ ensureStoreHasSerializeState(store);
36
+ const persist = options.persist;
37
+ if (!persist) return;
38
+ const {
39
+ key = makeKey(store.$id),
40
+ storage = localStorage,
41
+ serializer = {
42
+ serialize: JSON.stringify,
43
+ deserialize: JSON.parse
44
+ },
45
+ debounce = 0,
46
+ beforeRestore,
47
+ afterRestore,
48
+ onRestoreError
49
+ } = { ...globalOptions, ...persist };
50
+ const restoreState = () => {
51
+ beforeRestore?.(context);
52
+ const stored = storage.getItem(key);
53
+ if (!stored) return;
54
+ try {
55
+ const data = serializer.deserialize(stored);
56
+ store.$restoreState(data);
57
+ afterRestore?.(context);
58
+ } catch (error) {
59
+ if (onRestoreError) {
60
+ onRestoreError(error instanceof Error ? error : new Error(String(error)));
61
+ } else {
62
+ throw error;
63
+ }
64
+ }
65
+ };
66
+ const saveState = () => {
67
+ const state = store.$serializeState();
68
+ const serialized = serializer.serialize(state);
69
+ storage.setItem(key, serialized);
70
+ };
71
+ let finalSave = saveState;
72
+ let cleanupDebounce;
73
+ if (debounce) {
74
+ const { debouncedFn, cleanup } = makeDebounce(saveState, debounce);
75
+ finalSave = debouncedFn;
76
+ cleanupDebounce = cleanup;
77
+ }
78
+ const unsubscribe = store.$subscribe(() => {
79
+ finalSave();
80
+ }, { detached: true });
81
+ const originalDispose = store.$dispose;
82
+ store.$dispose = function() {
83
+ unsubscribe();
84
+ cleanupDebounce?.();
85
+ originalDispose.call(this);
86
+ };
87
+ restoreState();
88
+ };
89
+ }
90
+ var makeDebounce = (callback, waitFor) => {
91
+ let timeout;
92
+ const debouncedFn = () => {
93
+ if (timeout) clearTimeout(timeout);
94
+ timeout = setTimeout(() => {
95
+ callback();
96
+ }, waitFor);
97
+ };
98
+ const cleanup = () => {
99
+ if (timeout) {
100
+ clearTimeout(timeout);
101
+ timeout = void 0;
102
+ }
103
+ };
104
+ return { debouncedFn, cleanup };
105
+ };
106
+ function ensureStoreHasRestoreState(store) {
107
+ if (typeof store.$restoreState !== "function") {
108
+ throw new Error("A store using pinia-simple-persist must have a $restoreState() method");
109
+ }
110
+ }
111
+ function ensureStoreHasSerializeState(store) {
112
+ if (typeof store.$serializeState !== "function") {
113
+ throw new Error("A store using pinia-simple-persist must have a $serializeState() method");
114
+ }
115
+ }
116
+
117
+ // src/mapper.ts
118
+ var import_vue = require("vue");
119
+ function makeSimplePersistMapper(state, defaults) {
120
+ return {
121
+ $serializeState() {
122
+ const out = {};
123
+ for (const key in state) {
124
+ const item = state[key];
125
+ let value;
126
+ if ((0, import_vue.isRef)(item)) {
127
+ value = item.value;
128
+ } else {
129
+ value = item;
130
+ }
131
+ out[key] = (0, import_vue.isReactive)(value) ? (0, import_vue.toRaw)(value) : value;
132
+ }
133
+ return out;
134
+ },
135
+ $restoreState(data) {
136
+ for (const key in state) {
137
+ if (!(key in data)) continue;
138
+ const item = state[key];
139
+ if ((0, import_vue.isRef)(item)) {
140
+ item.value = data[key];
141
+ } else if ((0, import_vue.isReactive)(item)) {
142
+ Object.assign(item, data[key]);
143
+ }
144
+ }
145
+ },
146
+ $reset() {
147
+ for (const key in state) {
148
+ const item = state[key];
149
+ if ((0, import_vue.isRef)(item)) {
150
+ item.value = defaults[key];
151
+ } else if ((0, import_vue.isReactive)(item)) {
152
+ Object.assign(item, defaults[key]);
153
+ }
154
+ }
155
+ }
156
+ };
157
+ }
158
+ // Annotate the CommonJS export names for ESM import in node:
159
+ 0 && (module.exports = {
160
+ createPiniaSimplePersist,
161
+ makeSimplePersistMapper
162
+ });
163
+ //# sourceMappingURL=index.prod.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/plugin.ts","../src/mapper.ts"],"sourcesContent":["export * from './plugin'\nexport { makeSimplePersistMapper } from './mapper'\n","import type { PiniaPluginContext } from 'pinia'\nimport 'pinia'\nimport type { Serializer, StorageLike } from './types'\n\nexport type BaseSimplePersistOptions<Serialized> = {\n storage?: StorageLike\n serializer?: Serializer<Serialized>,\n debounce?: number\n beforeRestore?: (context: PiniaPluginContext) => void\n afterRestore?: (context: PiniaPluginContext) => void,\n onRestoreError?: (err: Error) => void,\n}\n\nexport type GlobalSimplePersistOptions = BaseSimplePersistOptions<any> & {\n makeKey?: (storeId: string) => string,\n}\n\nexport type SimplePersistOptions<Serialized> = BaseSimplePersistOptions<Serialized> & {\n key?: string,\n}\n\nexport function createPiniaSimplePersist(globalOptions: GlobalSimplePersistOptions = {}) {\n const makeKey = globalOptions.makeKey ?? ((id: string) => `pinia-${id}`)\n\n return (context: PiniaPluginContext) => {\n const { store, options } = context\n\n ensureStoreHasRestoreState(store)\n ensureStoreHasSerializeState(store)\n\n const persist = options.persist as SimplePersistOptions<any> | undefined\n if (!persist) return\n\n const {\n key = makeKey(store.$id),\n storage = localStorage,\n serializer = {\n serialize: JSON.stringify,\n deserialize: JSON.parse,\n },\n debounce = 0,\n beforeRestore,\n afterRestore,\n onRestoreError,\n } = { ...globalOptions, ...persist }\n\n const restoreState = () => {\n beforeRestore?.(context)\n\n const stored = storage.getItem(key)\n if (!stored) return\n\n try {\n const data = serializer.deserialize(stored)\n store.$restoreState(data)\n afterRestore?.(context)\n } catch (error) {\n if (onRestoreError) {\n onRestoreError(error instanceof Error ? error : new Error(String(error)))\n } else {\n throw error\n }\n }\n }\n\n const saveState = () => {\n const state = store.$serializeState()\n const serialized = serializer.serialize(state)\n storage.setItem(key, serialized)\n }\n\n let finalSave = saveState\n let cleanupDebounce: (() => void) | undefined\n\n if (debounce) {\n const { debouncedFn, cleanup } = makeDebounce(saveState, debounce)\n finalSave = debouncedFn\n cleanupDebounce = cleanup\n }\n\n // Watch for changes and persist\n const unsubscribe = store.$subscribe(() => {\n finalSave()\n }, { detached: true })\n\n // Cleanup on store disposal\n const originalDispose = store.$dispose\n store.$dispose = function() {\n unsubscribe()\n cleanupDebounce?.()\n originalDispose.call(this)\n }\n\n // Restore state on initialization\n restoreState()\n }\n}\n\nconst makeDebounce = <T extends () => void>(\n callback: T,\n waitFor: number,\n) => {\n let timeout: ReturnType<typeof setTimeout> | undefined\n\n const debouncedFn = (): void => {\n if (timeout) clearTimeout(timeout)\n timeout = setTimeout(() => {\n callback()\n }, waitFor)\n }\n\n const cleanup = (): void => {\n if (timeout) {\n clearTimeout(timeout)\n timeout = undefined\n }\n }\n\n return { debouncedFn, cleanup }\n}\n\nfunction ensureStoreHasRestoreState<T>(store: T): asserts store is T & { $restoreState: (data: any) => void } {\n if (typeof (store as any).$restoreState !== 'function') {\n throw new Error('A store using pinia-simple-persist must have a $restoreState() method')\n }\n}\n\nfunction ensureStoreHasSerializeState<T>(store: T): asserts store is T & { $serializeState: () => any } {\n if (typeof (store as any).$serializeState !== 'function') {\n throw new Error('A store using pinia-simple-persist must have a $serializeState() method')\n }\n}\n","import type { Ref } from 'vue'\nimport { toRaw, isRef, isReactive } from 'vue'\n\ntype RefOrReactive<T> = Ref<T> | T\n\nexport function makeSimplePersistMapper<T extends Record<string, any>>(\n state: { [K in keyof T]: RefOrReactive<T[K]> },\n defaults: T,\n) {\n return {\n $serializeState(): T {\n const out = {} as T\n for (const key in state) {\n const item = state[key]\n let value: any\n\n if (isRef(item)) {\n value = item.value\n } else {\n value = item\n }\n\n out[key] = isReactive(value) ? toRaw(value) : value\n }\n return out\n },\n\n $restoreState(data: T) {\n for (const key in state) {\n if (!(key in data)) continue\n\n const item = state[key]\n\n if (isRef(item)) {\n item.value = data[key]\n } else if (isReactive(item)) {\n Object.assign(item, data[key])\n }\n }\n },\n\n $reset() {\n for (const key in state) {\n const item = state[key]\n\n if (isRef(item)) {\n item.value = defaults[key]\n } else if (isReactive(item)) {\n Object.assign(item, defaults[key])\n }\n }\n },\n }\n}"],"mappings":"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","names":[]}
@@ -0,0 +1,68 @@
1
+ import { PiniaPluginContext } from 'pinia';
2
+ import { Ref } from 'vue';
3
+
4
+ /**
5
+ * Synchronous storage based on Web Storage API.
6
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Storage
7
+ */
8
+ interface StorageLike {
9
+ /**
10
+ * Get a key's value if it exists.
11
+ */
12
+ getItem: (key: string) => string | null;
13
+ /**
14
+ * Set a key with a value, or update it if it exists.
15
+ */
16
+ setItem: (key: string, value: string) => void;
17
+ }
18
+ interface Serializer<T> {
19
+ /**
20
+ * Serialize state into string before storing.
21
+ * @default JSON.stringify
22
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
23
+ */
24
+ serialize: (data: T) => string;
25
+ /**
26
+ * Deserializes string into state before hydrating.
27
+ * @default JSON.parse
28
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
29
+ */
30
+ deserialize: (data: string) => T;
31
+ }
32
+ declare module 'pinia' {
33
+ interface DefineStoreOptionsBase<S, Store> {
34
+ persist?: SimplePersistOptions<any> | boolean;
35
+ }
36
+ interface PiniaCustomProperties {
37
+ $persist: () => void;
38
+ $restoreState?: (data: any) => void;
39
+ $serializeState?: () => any;
40
+ }
41
+ }
42
+
43
+ type BaseSimplePersistOptions<Serialized> = {
44
+ storage?: StorageLike;
45
+ serializer?: Serializer<Serialized>;
46
+ debounce?: number;
47
+ beforeRestore?: (context: PiniaPluginContext) => void;
48
+ afterRestore?: (context: PiniaPluginContext) => void;
49
+ onRestoreError?: (err: Error) => void;
50
+ };
51
+ type GlobalSimplePersistOptions = BaseSimplePersistOptions<any> & {
52
+ makeKey?: (storeId: string) => string;
53
+ };
54
+ type SimplePersistOptions<Serialized> = BaseSimplePersistOptions<Serialized> & {
55
+ key?: string;
56
+ };
57
+ declare function createPiniaSimplePersist(globalOptions?: GlobalSimplePersistOptions): (context: PiniaPluginContext) => void;
58
+
59
+ type RefOrReactive<T> = Ref<T> | T;
60
+ declare function makeSimplePersistMapper<T extends Record<string, any>>(state: {
61
+ [K in keyof T]: RefOrReactive<T[K]>;
62
+ }, defaults: T): {
63
+ $serializeState(): T;
64
+ $restoreState(data: T): void;
65
+ $reset(): void;
66
+ };
67
+
68
+ export { type BaseSimplePersistOptions, type GlobalSimplePersistOptions, type SimplePersistOptions, createPiniaSimplePersist, makeSimplePersistMapper };
@@ -0,0 +1,135 @@
1
+ // src/plugin.ts
2
+ import "pinia";
3
+ function createPiniaSimplePersist(globalOptions = {}) {
4
+ const makeKey = globalOptions.makeKey ?? ((id) => `pinia-${id}`);
5
+ return (context) => {
6
+ const { store, options } = context;
7
+ ensureStoreHasRestoreState(store);
8
+ ensureStoreHasSerializeState(store);
9
+ const persist = options.persist;
10
+ if (!persist) return;
11
+ const {
12
+ key = makeKey(store.$id),
13
+ storage = localStorage,
14
+ serializer = {
15
+ serialize: JSON.stringify,
16
+ deserialize: JSON.parse
17
+ },
18
+ debounce = 0,
19
+ beforeRestore,
20
+ afterRestore,
21
+ onRestoreError
22
+ } = { ...globalOptions, ...persist };
23
+ const restoreState = () => {
24
+ beforeRestore?.(context);
25
+ const stored = storage.getItem(key);
26
+ if (!stored) return;
27
+ try {
28
+ const data = serializer.deserialize(stored);
29
+ store.$restoreState(data);
30
+ afterRestore?.(context);
31
+ } catch (error) {
32
+ if (onRestoreError) {
33
+ onRestoreError(error instanceof Error ? error : new Error(String(error)));
34
+ } else {
35
+ throw error;
36
+ }
37
+ }
38
+ };
39
+ const saveState = () => {
40
+ const state = store.$serializeState();
41
+ const serialized = serializer.serialize(state);
42
+ storage.setItem(key, serialized);
43
+ };
44
+ let finalSave = saveState;
45
+ let cleanupDebounce;
46
+ if (debounce) {
47
+ const { debouncedFn, cleanup } = makeDebounce(saveState, debounce);
48
+ finalSave = debouncedFn;
49
+ cleanupDebounce = cleanup;
50
+ }
51
+ const unsubscribe = store.$subscribe(() => {
52
+ finalSave();
53
+ }, { detached: true });
54
+ const originalDispose = store.$dispose;
55
+ store.$dispose = function() {
56
+ unsubscribe();
57
+ cleanupDebounce?.();
58
+ originalDispose.call(this);
59
+ };
60
+ restoreState();
61
+ };
62
+ }
63
+ var makeDebounce = (callback, waitFor) => {
64
+ let timeout;
65
+ const debouncedFn = () => {
66
+ if (timeout) clearTimeout(timeout);
67
+ timeout = setTimeout(() => {
68
+ callback();
69
+ }, waitFor);
70
+ };
71
+ const cleanup = () => {
72
+ if (timeout) {
73
+ clearTimeout(timeout);
74
+ timeout = void 0;
75
+ }
76
+ };
77
+ return { debouncedFn, cleanup };
78
+ };
79
+ function ensureStoreHasRestoreState(store) {
80
+ if (typeof store.$restoreState !== "function") {
81
+ throw new Error("A store using pinia-simple-persist must have a $restoreState() method");
82
+ }
83
+ }
84
+ function ensureStoreHasSerializeState(store) {
85
+ if (typeof store.$serializeState !== "function") {
86
+ throw new Error("A store using pinia-simple-persist must have a $serializeState() method");
87
+ }
88
+ }
89
+
90
+ // src/mapper.ts
91
+ import { toRaw, isRef, isReactive } from "vue";
92
+ function makeSimplePersistMapper(state, defaults) {
93
+ return {
94
+ $serializeState() {
95
+ const out = {};
96
+ for (const key in state) {
97
+ const item = state[key];
98
+ let value;
99
+ if (isRef(item)) {
100
+ value = item.value;
101
+ } else {
102
+ value = item;
103
+ }
104
+ out[key] = isReactive(value) ? toRaw(value) : value;
105
+ }
106
+ return out;
107
+ },
108
+ $restoreState(data) {
109
+ for (const key in state) {
110
+ if (!(key in data)) continue;
111
+ const item = state[key];
112
+ if (isRef(item)) {
113
+ item.value = data[key];
114
+ } else if (isReactive(item)) {
115
+ Object.assign(item, data[key]);
116
+ }
117
+ }
118
+ },
119
+ $reset() {
120
+ for (const key in state) {
121
+ const item = state[key];
122
+ if (isRef(item)) {
123
+ item.value = defaults[key];
124
+ } else if (isReactive(item)) {
125
+ Object.assign(item, defaults[key]);
126
+ }
127
+ }
128
+ }
129
+ };
130
+ }
131
+ export {
132
+ createPiniaSimplePersist,
133
+ makeSimplePersistMapper
134
+ };
135
+ //# sourceMappingURL=index.prod.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/plugin.ts","../src/mapper.ts"],"sourcesContent":["import type { PiniaPluginContext } from 'pinia'\nimport 'pinia'\nimport type { Serializer, StorageLike } from './types'\n\nexport type BaseSimplePersistOptions<Serialized> = {\n storage?: StorageLike\n serializer?: Serializer<Serialized>,\n debounce?: number\n beforeRestore?: (context: PiniaPluginContext) => void\n afterRestore?: (context: PiniaPluginContext) => void,\n onRestoreError?: (err: Error) => void,\n}\n\nexport type GlobalSimplePersistOptions = BaseSimplePersistOptions<any> & {\n makeKey?: (storeId: string) => string,\n}\n\nexport type SimplePersistOptions<Serialized> = BaseSimplePersistOptions<Serialized> & {\n key?: string,\n}\n\nexport function createPiniaSimplePersist(globalOptions: GlobalSimplePersistOptions = {}) {\n const makeKey = globalOptions.makeKey ?? ((id: string) => `pinia-${id}`)\n\n return (context: PiniaPluginContext) => {\n const { store, options } = context\n\n ensureStoreHasRestoreState(store)\n ensureStoreHasSerializeState(store)\n\n const persist = options.persist as SimplePersistOptions<any> | undefined\n if (!persist) return\n\n const {\n key = makeKey(store.$id),\n storage = localStorage,\n serializer = {\n serialize: JSON.stringify,\n deserialize: JSON.parse,\n },\n debounce = 0,\n beforeRestore,\n afterRestore,\n onRestoreError,\n } = { ...globalOptions, ...persist }\n\n const restoreState = () => {\n beforeRestore?.(context)\n\n const stored = storage.getItem(key)\n if (!stored) return\n\n try {\n const data = serializer.deserialize(stored)\n store.$restoreState(data)\n afterRestore?.(context)\n } catch (error) {\n if (onRestoreError) {\n onRestoreError(error instanceof Error ? error : new Error(String(error)))\n } else {\n throw error\n }\n }\n }\n\n const saveState = () => {\n const state = store.$serializeState()\n const serialized = serializer.serialize(state)\n storage.setItem(key, serialized)\n }\n\n let finalSave = saveState\n let cleanupDebounce: (() => void) | undefined\n\n if (debounce) {\n const { debouncedFn, cleanup } = makeDebounce(saveState, debounce)\n finalSave = debouncedFn\n cleanupDebounce = cleanup\n }\n\n // Watch for changes and persist\n const unsubscribe = store.$subscribe(() => {\n finalSave()\n }, { detached: true })\n\n // Cleanup on store disposal\n const originalDispose = store.$dispose\n store.$dispose = function() {\n unsubscribe()\n cleanupDebounce?.()\n originalDispose.call(this)\n }\n\n // Restore state on initialization\n restoreState()\n }\n}\n\nconst makeDebounce = <T extends () => void>(\n callback: T,\n waitFor: number,\n) => {\n let timeout: ReturnType<typeof setTimeout> | undefined\n\n const debouncedFn = (): void => {\n if (timeout) clearTimeout(timeout)\n timeout = setTimeout(() => {\n callback()\n }, waitFor)\n }\n\n const cleanup = (): void => {\n if (timeout) {\n clearTimeout(timeout)\n timeout = undefined\n }\n }\n\n return { debouncedFn, cleanup }\n}\n\nfunction ensureStoreHasRestoreState<T>(store: T): asserts store is T & { $restoreState: (data: any) => void } {\n if (typeof (store as any).$restoreState !== 'function') {\n throw new Error('A store using pinia-simple-persist must have a $restoreState() method')\n }\n}\n\nfunction ensureStoreHasSerializeState<T>(store: T): asserts store is T & { $serializeState: () => any } {\n if (typeof (store as any).$serializeState !== 'function') {\n throw new Error('A store using pinia-simple-persist must have a $serializeState() method')\n }\n}\n","import type { Ref } from 'vue'\nimport { toRaw, isRef, isReactive } from 'vue'\n\ntype RefOrReactive<T> = Ref<T> | T\n\nexport function makeSimplePersistMapper<T extends Record<string, any>>(\n state: { [K in keyof T]: RefOrReactive<T[K]> },\n defaults: T,\n) {\n return {\n $serializeState(): T {\n const out = {} as T\n for (const key in state) {\n const item = state[key]\n let value: any\n\n if (isRef(item)) {\n value = item.value\n } else {\n value = item\n }\n\n out[key] = isReactive(value) ? toRaw(value) : value\n }\n return out\n },\n\n $restoreState(data: T) {\n for (const key in state) {\n if (!(key in data)) continue\n\n const item = state[key]\n\n if (isRef(item)) {\n item.value = data[key]\n } else if (isReactive(item)) {\n Object.assign(item, data[key])\n }\n }\n },\n\n $reset() {\n for (const key in state) {\n const item = state[key]\n\n if (isRef(item)) {\n item.value = defaults[key]\n } else if (isReactive(item)) {\n Object.assign(item, defaults[key])\n }\n }\n },\n }\n}"],"mappings":";AACA,OAAO;AAoBA,SAAS,yBAAyB,gBAA4C,CAAC,GAAG;AACvF,QAAM,UAAU,cAAc,YAAY,CAAC,OAAe,SAAS,EAAE;AAErE,SAAO,CAAC,YAAgC;AACtC,UAAM,EAAE,OAAO,QAAQ,IAAI;AAE3B,+BAA2B,KAAK;AAChC,iCAA6B,KAAK;AAElC,UAAM,UAAU,QAAQ;AACxB,QAAI,CAAC,QAAS;AAEd,UAAM;AAAA,MACJ,MAAM,QAAQ,MAAM,GAAG;AAAA,MACvB,UAAU;AAAA,MACV,aAAa;AAAA,QACX,WAAW,KAAK;AAAA,QAChB,aAAa,KAAK;AAAA,MACpB;AAAA,MACA,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI,EAAE,GAAG,eAAe,GAAG,QAAQ;AAEnC,UAAM,eAAe,MAAM;AACzB,sBAAgB,OAAO;AAEvB,YAAM,SAAS,QAAQ,QAAQ,GAAG;AAClC,UAAI,CAAC,OAAQ;AAEb,UAAI;AACF,cAAM,OAAO,WAAW,YAAY,MAAM;AAC1C,cAAM,cAAc,IAAI;AACxB,uBAAe,OAAO;AAAA,MACxB,SAAS,OAAO;AACd,YAAI,gBAAgB;AAClB,yBAAe,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;AAAA,QAC1E,OAAO;AACL,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,YAAY,MAAM;AACtB,YAAM,QAAQ,MAAM,gBAAgB;AACpC,YAAM,aAAa,WAAW,UAAU,KAAK;AAC7C,cAAQ,QAAQ,KAAK,UAAU;AAAA,IACjC;AAEA,QAAI,YAAY;AAChB,QAAI;AAEJ,QAAI,UAAU;AACZ,YAAM,EAAE,aAAa,QAAQ,IAAI,aAAa,WAAW,QAAQ;AACjE,kBAAY;AACZ,wBAAkB;AAAA,IACpB;AAGA,UAAM,cAAc,MAAM,WAAW,MAAM;AACzC,gBAAU;AAAA,IACZ,GAAG,EAAE,UAAU,KAAK,CAAC;AAGrB,UAAM,kBAAkB,MAAM;AAC9B,UAAM,WAAW,WAAW;AAC1B,kBAAY;AACZ,wBAAkB;AAClB,sBAAgB,KAAK,IAAI;AAAA,IAC3B;AAGA,iBAAa;AAAA,EACf;AACF;AAEA,IAAM,eAAe,CACnB,UACA,YACG;AACH,MAAI;AAEJ,QAAM,cAAc,MAAY;AAC9B,QAAI,QAAS,cAAa,OAAO;AACjC,cAAU,WAAW,MAAM;AACzB,eAAS;AAAA,IACX,GAAG,OAAO;AAAA,EACZ;AAEA,QAAM,UAAU,MAAY;AAC1B,QAAI,SAAS;AACX,mBAAa,OAAO;AACpB,gBAAU;AAAA,IACZ;AAAA,EACF;AAEA,SAAO,EAAE,aAAa,QAAQ;AAChC;AAEA,SAAS,2BAA8B,OAAuE;AAC5G,MAAI,OAAQ,MAAc,kBAAkB,YAAY;AACtD,UAAM,IAAI,MAAM,uEAAuE;AAAA,EACzF;AACF;AAEA,SAAS,6BAAgC,OAA+D;AACtG,MAAI,OAAQ,MAAc,oBAAoB,YAAY;AACxD,UAAM,IAAI,MAAM,yEAAyE;AAAA,EAC3F;AACF;;;AClIA,SAAS,OAAO,OAAO,kBAAkB;AAIlC,SAAS,wBACd,OACA,UACA;AACA,SAAO;AAAA,IACL,kBAAqB;AACnB,YAAM,MAAM,CAAC;AACb,iBAAW,OAAO,OAAO;AACvB,cAAM,OAAO,MAAM,GAAG;AACtB,YAAI;AAEJ,YAAI,MAAM,IAAI,GAAG;AACf,kBAAQ,KAAK;AAAA,QACf,OAAO;AACL,kBAAQ;AAAA,QACV;AAEA,YAAI,GAAG,IAAI,WAAW,KAAK,IAAI,MAAM,KAAK,IAAI;AAAA,MAChD;AACA,aAAO;AAAA,IACT;AAAA,IAEA,cAAc,MAAS;AACrB,iBAAW,OAAO,OAAO;AACvB,YAAI,EAAE,OAAO,MAAO;AAEpB,cAAM,OAAO,MAAM,GAAG;AAEtB,YAAI,MAAM,IAAI,GAAG;AACf,eAAK,QAAQ,KAAK,GAAG;AAAA,QACvB,WAAW,WAAW,IAAI,GAAG;AAC3B,iBAAO,OAAO,MAAM,KAAK,GAAG,CAAC;AAAA,QAC/B;AAAA,MACF;AAAA,IACF;AAAA,IAEA,SAAS;AACP,iBAAW,OAAO,OAAO;AACvB,cAAM,OAAO,MAAM,GAAG;AAEtB,YAAI,MAAM,IAAI,GAAG;AACf,eAAK,QAAQ,SAAS,GAAG;AAAA,QAC3B,WAAW,WAAW,IAAI,GAAG;AAC3B,iBAAO,OAAO,MAAM,SAAS,GAAG,CAAC;AAAA,QACnC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "pixel-data-js",
3
+ "type": "module",
4
+ "version": "0.0.1",
5
+ "packageManager": "pnpm@10.30.0",
6
+ "description": "JS Pixel and ImageData operations",
7
+ "author": {
8
+ "name": "Carl Olsen",
9
+ "email": "unstoppablecarlolsen@gmail.com"
10
+ },
11
+ "license": "MIT",
12
+ "keywords": [
13
+ "ImageData",
14
+ "pixel",
15
+ "blit",
16
+ "image"
17
+ ],
18
+ "main": "./dist/index.prod.cjs",
19
+ "module": "./dist/index.prod.js",
20
+ "source": "./src/index.ts",
21
+ "types": "./dist/index.prod.d.ts",
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.prod.d.ts",
25
+ "source": "./src/index.ts",
26
+ "development": {
27
+ "require": "./dist/index.dev.cjs",
28
+ "import": "./dist/index.dev.js"
29
+ },
30
+ "production": {
31
+ "require": "./dist/index.prod.cjs",
32
+ "import": "./dist/index.prod.js"
33
+ },
34
+ "require": "./dist/index.prod.cjs",
35
+ "import": "./dist/index.prod.js"
36
+ }
37
+ },
38
+ "files": [
39
+ "dist/*",
40
+ "src/*",
41
+ "pnpm-lock.yaml",
42
+ "LICENSE",
43
+ "README.md"
44
+ ],
45
+ "scripts": {
46
+ "build": "tsup",
47
+ "test": "vitest --coverage",
48
+ "test:mutation": "stryker run",
49
+ "docs": "npx typedoc --entryPointStrategy Expand src"
50
+ },
51
+ "devDependencies": {
52
+ "@stryker-mutator/core": "^9.5.1",
53
+ "@stryker-mutator/typescript-checker": "^9.5.1",
54
+ "@stryker-mutator/vitest-runner": "^9.5.1",
55
+ "@types/node": "^25.2.3",
56
+ "@vitest/coverage-v8": "^4.0.18",
57
+ "esbuild": "^0.27.3",
58
+ "happy-dom": "^20.6.1",
59
+ "tsup": "^8.5.1",
60
+ "tsx": "^4.21.0",
61
+ "typedoc": "^0.28.17",
62
+ "typescript": "^5.9.3",
63
+ "vitest": "4.0.18"
64
+ },
65
+ "repository": {
66
+ "type": "git",
67
+ "url": "git+https://github.com/unstoppablecarl/pixel-data-js.git"
68
+ },
69
+ "bugs": {
70
+ "url": "https://github.com/unstoppablecarl/pixel-data-js/issues"
71
+ }
72
+ }
@@ -0,0 +1,40 @@
1
+ export type SerializedImageData = {
2
+ width: number,
3
+ height: number,
4
+ data: string,
5
+ }
6
+
7
+ /**
8
+ * Serialize for use in JSON. Stored as base64 encoded string.
9
+ */
10
+ export function serializeImageData<T extends ImageData>(imageData: T): SerializedImageData {
11
+ const binary = String.fromCharCode(...new Uint8Array(imageData.data.buffer))
12
+ const base64 = btoa(binary)
13
+
14
+ return {
15
+ width: imageData.width,
16
+ height: imageData.height,
17
+ data: base64,
18
+ }
19
+ }
20
+
21
+ export function serializeNullableImageData<T extends ImageData | null>(imageData: T): T extends null ? null : SerializedImageData {
22
+ if (!imageData) return null as any
23
+
24
+ return serializeImageData(imageData) as any
25
+ }
26
+
27
+ export function deserializeImageData<T extends SerializedImageData>(serialized: T): ImageData {
28
+ const binary = atob(serialized.data as string)
29
+ const bytes = new Uint8ClampedArray(binary.length)
30
+ for (let i = 0; i < binary.length; i++) {
31
+ bytes[i] = binary.charCodeAt(i)
32
+ }
33
+
34
+ return new ImageData(bytes, serialized.width, serialized.height) as any
35
+ }
36
+
37
+ export function deserializeNullableImageData<T extends SerializedImageData | null>(serialized: T): T extends null ? null : ImageData {
38
+ if (!serialized) return null as any
39
+ return deserializeImageData(serialized) as any
40
+ }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './ImageData/serialization'