stroid 0.1.0 → 0.1.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.
Files changed (155) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +375 -468
  3. package/dist/_tsup-dts-rollup.d.cts +2411 -0
  4. package/dist/_tsup-dts-rollup.d.ts +2411 -0
  5. package/dist/async.cjs +29 -24
  6. package/dist/async.cjs.map +1 -0
  7. package/dist/async.d.cts +9 -40
  8. package/dist/async.d.ts +9 -40
  9. package/dist/async.js +29 -24
  10. package/dist/async.js.map +1 -0
  11. package/dist/computed.cjs +12 -10
  12. package/dist/computed.cjs.map +1 -0
  13. package/dist/computed.d.cts +7 -29
  14. package/dist/computed.d.ts +7 -29
  15. package/dist/computed.js +12 -10
  16. package/dist/computed.js.map +1 -0
  17. package/dist/core.cjs +17 -23
  18. package/dist/core.cjs.map +1 -0
  19. package/dist/core.d.cts +15 -5
  20. package/dist/core.d.ts +15 -5
  21. package/dist/core.js +17 -23
  22. package/dist/core.js.map +1 -0
  23. package/dist/devtools.cjs +2 -1
  24. package/dist/devtools.cjs.map +1 -0
  25. package/dist/devtools.d.cts +5 -19
  26. package/dist/devtools.d.ts +5 -19
  27. package/dist/devtools.js +2 -1
  28. package/dist/devtools.js.map +1 -0
  29. package/dist/feature.cjs +2 -0
  30. package/dist/feature.cjs.map +1 -0
  31. package/dist/feature.d.cts +14 -0
  32. package/dist/feature.d.ts +14 -0
  33. package/dist/feature.js +2 -0
  34. package/dist/feature.js.map +1 -0
  35. package/dist/helpers.cjs +17 -13
  36. package/dist/helpers.cjs.map +1 -0
  37. package/dist/helpers.d.cts +3 -29
  38. package/dist/helpers.d.ts +3 -29
  39. package/dist/helpers.js +17 -13
  40. package/dist/helpers.js.map +1 -0
  41. package/dist/index.cjs +26 -21
  42. package/dist/index.cjs.map +1 -0
  43. package/dist/index.d.cts +33 -130
  44. package/dist/index.d.ts +33 -130
  45. package/dist/index.js +26 -21
  46. package/dist/index.js.map +1 -0
  47. package/dist/install.cjs +2 -0
  48. package/dist/install.cjs.map +1 -0
  49. package/dist/install.d.cts +4 -0
  50. package/dist/install.d.ts +4 -0
  51. package/dist/install.js +2 -0
  52. package/dist/install.js.map +1 -0
  53. package/dist/persist.cjs +2 -1
  54. package/dist/persist.cjs.map +1 -0
  55. package/dist/persist.d.cts +1 -2
  56. package/dist/persist.d.ts +1 -2
  57. package/dist/persist.js +2 -1
  58. package/dist/persist.js.map +1 -0
  59. package/dist/react.cjs +27 -22
  60. package/dist/react.cjs.map +1 -0
  61. package/dist/react.d.cts +7 -52
  62. package/dist/react.d.ts +7 -52
  63. package/dist/react.js +27 -22
  64. package/dist/react.js.map +1 -0
  65. package/dist/runtime-admin.cjs +2 -1
  66. package/dist/runtime-admin.cjs.map +1 -0
  67. package/dist/runtime-admin.d.cts +2 -4
  68. package/dist/runtime-admin.d.ts +2 -4
  69. package/dist/runtime-admin.js +2 -1
  70. package/dist/runtime-admin.js.map +1 -0
  71. package/dist/runtime-tools.cjs +3 -2
  72. package/dist/runtime-tools.cjs.map +1 -0
  73. package/dist/runtime-tools.d.cts +9 -39
  74. package/dist/runtime-tools.d.ts +9 -39
  75. package/dist/runtime-tools.js +3 -2
  76. package/dist/runtime-tools.js.map +1 -0
  77. package/dist/selectors.cjs +2 -1
  78. package/dist/selectors.cjs.map +1 -0
  79. package/dist/selectors.d.cts +2 -4
  80. package/dist/selectors.d.ts +2 -4
  81. package/dist/selectors.js +2 -1
  82. package/dist/selectors.js.map +1 -0
  83. package/dist/server.cjs +11 -9
  84. package/dist/server.cjs.map +1 -0
  85. package/dist/server.d.cts +2 -14
  86. package/dist/server.d.ts +2 -14
  87. package/dist/server.js +11 -9
  88. package/dist/server.js.map +1 -0
  89. package/dist/sync.cjs +2 -1
  90. package/dist/sync.cjs.map +1 -0
  91. package/dist/sync.d.cts +1 -2
  92. package/dist/sync.d.ts +1 -2
  93. package/dist/sync.js +2 -1
  94. package/dist/sync.js.map +1 -0
  95. package/dist/testing.cjs +17 -13
  96. package/dist/testing.cjs.map +1 -0
  97. package/dist/testing.d.cts +4 -16
  98. package/dist/testing.d.ts +4 -16
  99. package/dist/testing.js +17 -13
  100. package/dist/testing.js.map +1 -0
  101. package/package.json +12 -3
  102. package/dist/async-cache-DFHwcBQL.d.cts +0 -52
  103. package/dist/async-cache-DFHwcBQL.d.ts +0 -52
  104. package/dist/computed-BbAZm1Dq.d.cts +0 -17
  105. package/dist/computed-CccdgY5j.d.ts +0 -17
  106. package/dist/options-CB35e3Xo.d.cts +0 -245
  107. package/dist/options-CB35e3Xo.d.ts +0 -245
  108. package/dist/types/adapters/options.d.ts +0 -247
  109. package/dist/types/async/clone.d.ts +0 -2
  110. package/dist/types/async/errors.d.ts +0 -3
  111. package/dist/types/async/inflight.d.ts +0 -13
  112. package/dist/types/async/rate.d.ts +0 -5
  113. package/dist/types/async/request.d.ts +0 -3
  114. package/dist/types/async-cache.d.ts +0 -57
  115. package/dist/types/async-fetch.d.ts +0 -37
  116. package/dist/types/async-registry.d.ts +0 -96
  117. package/dist/types/async-retry.d.ts +0 -10
  118. package/dist/types/async.d.ts +0 -2
  119. package/dist/types/computed-graph.d.ts +0 -31
  120. package/dist/types/computed.d.ts +0 -15
  121. package/dist/types/config.d.ts +0 -2
  122. package/dist/types/core.d.ts +0 -1
  123. package/dist/types/devfreeze.d.ts +0 -1
  124. package/dist/types/feature-registry.d.ts +0 -69
  125. package/dist/types/features/lifecycle.d.ts +0 -28
  126. package/dist/types/index.d.ts +0 -6
  127. package/dist/types/integrations/query.d.ts +0 -8
  128. package/dist/types/internals/config.d.ts +0 -62
  129. package/dist/types/internals/diagnostics.d.ts +0 -21
  130. package/dist/types/internals/hooks-warnings.d.ts +0 -6
  131. package/dist/types/internals/reporting.d.ts +0 -8
  132. package/dist/types/internals/store-admin.d.ts +0 -7
  133. package/dist/types/internals/store-ops.d.ts +0 -3
  134. package/dist/types/runtime-admin.d.ts +0 -2
  135. package/dist/types/store-lifecycle/bind.d.ts +0 -3
  136. package/dist/types/store-lifecycle/hooks.d.ts +0 -44
  137. package/dist/types/store-lifecycle/identity.d.ts +0 -23
  138. package/dist/types/store-lifecycle/registry.d.ts +0 -39
  139. package/dist/types/store-lifecycle/types.d.ts +0 -39
  140. package/dist/types/store-lifecycle/validation.d.ts +0 -45
  141. package/dist/types/store-lifecycle.d.ts +0 -20
  142. package/dist/types/store-name.d.ts +0 -19
  143. package/dist/types/store-notify.d.ts +0 -12
  144. package/dist/types/store-read.d.ts +0 -12
  145. package/dist/types/store-registry.d.ts +0 -74
  146. package/dist/types/store-transaction.d.ts +0 -12
  147. package/dist/types/store-write.d.ts +0 -45
  148. package/dist/types/store.d.ts +0 -7
  149. package/dist/types/utils/clone.d.ts +0 -4
  150. package/dist/types/utils/hash.d.ts +0 -8
  151. package/dist/types/utils/path.d.ts +0 -5
  152. package/dist/types/utils/validation.d.ts +0 -14
  153. package/dist/types/utils.d.ts +0 -5
  154. package/dist/types-grvlY4BX.d.cts +0 -37
  155. package/dist/types-grvlY4BX.d.ts +0 -37
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stroid",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Named-store state engine for JavaScript/React with optional persistence, async caching, sync, and devtools.",
5
5
  "keywords": [
6
6
  "state-management",
@@ -56,6 +56,14 @@
56
56
  "types": "./dist/async.d.ts",
57
57
  "import": "./dist/async.js"
58
58
  },
59
+ "./feature": {
60
+ "types": "./dist/feature.d.ts",
61
+ "import": "./dist/feature.js"
62
+ },
63
+ "./install": {
64
+ "types": "./dist/install.d.ts",
65
+ "import": "./dist/install.js"
66
+ },
59
67
  "./persist": {
60
68
  "types": "./dist/persist.d.ts",
61
69
  "import": "./dist/persist.js"
@@ -102,8 +110,8 @@
102
110
  "./dist/devtools.js"
103
111
  ],
104
112
  "scripts": {
105
- "test": "node --import ./tests/preload.mjs --import tsx --import ./tests/setup.ts --test tests/async-cleanup.test.ts tests/async-revalidate-cleanup.test.ts tests/async.test.ts tests/computed.test.ts tests/helpers.test.ts tests/options-adapter.test.ts tests/persist.test.ts tests/react-hooks.test.tsx tests/regressions.test.ts tests/selectors-devfreeze.test.ts tests/ssr-carrier.test.ts tests/store.core.test.ts tests/store.node-env.test.ts tests/strict-missing-features.test.ts tests/sync.core.test.ts tests/testing.test.ts tests/utils.test.ts",
106
- "test:coverage": "c8 --check-coverage --lines 80 --branches 80 --functions 80 --statements 80 node --import ./tests/preload.mjs --import tsx --import ./tests/setup.ts --test tests/async-cleanup.test.ts tests/async-revalidate-cleanup.test.ts tests/async.test.ts tests/computed.test.ts tests/helpers.test.ts tests/options-adapter.test.ts tests/persist.test.ts tests/react-hooks.test.tsx tests/regressions.test.ts tests/selectors-devfreeze.test.ts tests/ssr-carrier.test.ts tests/store.core.test.ts tests/store.node-env.test.ts tests/strict-missing-features.test.ts tests/sync.core.test.ts tests/testing.test.ts tests/utils.test.ts",
113
+ "test": "node --import ./tests/preload.mjs --import tsx --import ./tests/setup.ts --test tests/async-cleanup.test.ts tests/async-revalidate-cleanup.test.ts tests/async.test.ts tests/computed.test.ts tests/coverage-extra.test.ts tests/feature-api.test.ts tests/helpers.test.ts tests/options-adapter.test.ts tests/persist.test.ts tests/react-hooks.test.tsx tests/regressions.test.ts tests/selectors-devfreeze.test.ts tests/ssr-carrier.test.ts tests/store.core.test.ts tests/store.node-env.test.ts tests/strict-missing-features.test.ts tests/sync.core.test.ts tests/testing.test.ts tests/utils.test.ts",
114
+ "test:coverage": "c8 --check-coverage --lines 80 --branches 80 --functions 80 --statements 80 node --import ./tests/preload.mjs --import tsx --import ./tests/setup.ts --test tests/async-cleanup.test.ts tests/async-revalidate-cleanup.test.ts tests/async.test.ts tests/computed.test.ts tests/coverage-extra.test.ts tests/feature-api.test.ts tests/helpers.test.ts tests/options-adapter.test.ts tests/persist.test.ts tests/react-hooks.test.tsx tests/regressions.test.ts tests/selectors-devfreeze.test.ts tests/ssr-carrier.test.ts tests/store.core.test.ts tests/store.node-env.test.ts tests/strict-missing-features.test.ts tests/sync.core.test.ts tests/testing.test.ts tests/utils.test.ts",
107
115
  "test:heavy": "node --import tsx --test tests/heavy/store.heavy.ts",
108
116
  "test:types": "npm run build && tsc -p tsconfig.typetests.json",
109
117
  "typecheck": "tsc -p tsconfig.types.json",
@@ -118,6 +126,7 @@
118
126
  "react": ">=18"
119
127
  },
120
128
  "devDependencies": {
129
+ "@microsoft/api-extractor": "^7.57.7",
121
130
  "@testing-library/dom": "^10.4.0",
122
131
  "@testing-library/react": "^16.2.0",
123
132
  "@types/node": "^22.9.0",
@@ -1,52 +0,0 @@
1
- type AsyncStateSnapshot = {
2
- data?: unknown;
3
- loading: boolean;
4
- error: string | null;
5
- status: "idle" | "loading" | "success" | "error" | "aborted";
6
- cached?: boolean;
7
- revalidating?: boolean;
8
- };
9
- type AsyncStateAdapter = (ctx: {
10
- name: string;
11
- prev: unknown;
12
- next: AsyncStateSnapshot;
13
- set: (value: unknown | ((draft: any) => void)) => void;
14
- }) => void;
15
- interface FetchOptions {
16
- transform?: (result: unknown) => unknown;
17
- onSuccess?: (data: unknown) => void;
18
- onError?: (message: string) => void;
19
- /**
20
- * Optional adapter to write async state into a custom store shape.
21
- * When provided, default AsyncState writes are skipped.
22
- */
23
- stateAdapter?: AsyncStateAdapter;
24
- method?: string;
25
- headers?: Record<string, string>;
26
- body?: unknown;
27
- ttl?: number;
28
- staleWhileRevalidate?: boolean;
29
- dedupe?: boolean;
30
- retry?: number;
31
- retryDelay?: number;
32
- retryBackoff?: number;
33
- signal?: AbortSignal;
34
- cacheKey?: string;
35
- responseType?: "auto" | "json" | "text" | "arrayBuffer" | "blob" | "formData";
36
- /**
37
- * Auto-create the backing store if missing.
38
- * Defaults to the global config setting (true by default).
39
- */
40
- autoCreate?: boolean;
41
- /**
42
- * Clone strategy for transformed results.
43
- * - "none" (default): store by reference.
44
- * - "shallow": shallow clone objects/arrays.
45
- * - "deep": deep clone objects/arrays.
46
- */
47
- cloneResult?: "none" | "shallow" | "deep";
48
- }
49
-
50
- type FetchInput = string | Promise<unknown> | (() => string | Promise<unknown>);
51
-
52
- export type { AsyncStateAdapter as A, FetchOptions as F, FetchInput as a, AsyncStateSnapshot as b };
@@ -1,52 +0,0 @@
1
- type AsyncStateSnapshot = {
2
- data?: unknown;
3
- loading: boolean;
4
- error: string | null;
5
- status: "idle" | "loading" | "success" | "error" | "aborted";
6
- cached?: boolean;
7
- revalidating?: boolean;
8
- };
9
- type AsyncStateAdapter = (ctx: {
10
- name: string;
11
- prev: unknown;
12
- next: AsyncStateSnapshot;
13
- set: (value: unknown | ((draft: any) => void)) => void;
14
- }) => void;
15
- interface FetchOptions {
16
- transform?: (result: unknown) => unknown;
17
- onSuccess?: (data: unknown) => void;
18
- onError?: (message: string) => void;
19
- /**
20
- * Optional adapter to write async state into a custom store shape.
21
- * When provided, default AsyncState writes are skipped.
22
- */
23
- stateAdapter?: AsyncStateAdapter;
24
- method?: string;
25
- headers?: Record<string, string>;
26
- body?: unknown;
27
- ttl?: number;
28
- staleWhileRevalidate?: boolean;
29
- dedupe?: boolean;
30
- retry?: number;
31
- retryDelay?: number;
32
- retryBackoff?: number;
33
- signal?: AbortSignal;
34
- cacheKey?: string;
35
- responseType?: "auto" | "json" | "text" | "arrayBuffer" | "blob" | "formData";
36
- /**
37
- * Auto-create the backing store if missing.
38
- * Defaults to the global config setting (true by default).
39
- */
40
- autoCreate?: boolean;
41
- /**
42
- * Clone strategy for transformed results.
43
- * - "none" (default): store by reference.
44
- * - "shallow": shallow clone objects/arrays.
45
- * - "deep": deep clone objects/arrays.
46
- */
47
- cloneResult?: "none" | "shallow" | "deep";
48
- }
49
-
50
- type FetchInput = string | Promise<unknown> | (() => string | Promise<unknown>);
51
-
52
- export type { AsyncStateAdapter as A, FetchOptions as F, FetchInput as a, AsyncStateSnapshot as b };
@@ -1,17 +0,0 @@
1
- import { S as StoreName, a as StoreDefinition, b as StoreValue, c as StoreKey, d as StateFor } from './types-grvlY4BX.cjs';
2
-
3
- type ComputedOptions = {
4
- autoDispose?: boolean;
5
- onError?: (err: unknown) => void;
6
- };
7
- type DepHandle = StoreDefinition<string, StoreValue> | StoreKey<string, StoreValue>;
8
- type DepValue<T> = T extends StoreDefinition<string, infer S> ? Readonly<S> | null : T extends StoreKey<string, infer S> ? Readonly<S> | null : T extends StoreName ? Readonly<StateFor<T>> | null : StoreValue | null;
9
- declare function createComputed<TResult, Deps extends readonly (StoreName | DepHandle)[]>(name: string, deps: Deps, compute: (...args: {
10
- [K in keyof Deps]: DepValue<Deps[K]>;
11
- }) => TResult, options?: ComputedOptions): StoreDefinition<string, TResult> | undefined;
12
- declare const invalidateComputed: (name: string) => void;
13
- declare const deleteComputed: (name: string) => void;
14
- declare const isComputedStore: (name: string) => boolean;
15
- declare const _resetComputedForTests: () => void;
16
-
17
- export { _resetComputedForTests as _, isComputedStore as a, createComputed as c, deleteComputed as d, invalidateComputed as i };
@@ -1,17 +0,0 @@
1
- import { S as StoreName, a as StoreDefinition, b as StoreValue, c as StoreKey, d as StateFor } from './types-grvlY4BX.js';
2
-
3
- type ComputedOptions = {
4
- autoDispose?: boolean;
5
- onError?: (err: unknown) => void;
6
- };
7
- type DepHandle = StoreDefinition<string, StoreValue> | StoreKey<string, StoreValue>;
8
- type DepValue<T> = T extends StoreDefinition<string, infer S> ? Readonly<S> | null : T extends StoreKey<string, infer S> ? Readonly<S> | null : T extends StoreName ? Readonly<StateFor<T>> | null : StoreValue | null;
9
- declare function createComputed<TResult, Deps extends readonly (StoreName | DepHandle)[]>(name: string, deps: Deps, compute: (...args: {
10
- [K in keyof Deps]: DepValue<Deps[K]>;
11
- }) => TResult, options?: ComputedOptions): StoreDefinition<string, TResult> | undefined;
12
- declare const invalidateComputed: (name: string) => void;
13
- declare const deleteComputed: (name: string) => void;
14
- declare const isComputedStore: (name: string) => boolean;
15
- declare const _resetComputedForTests: () => void;
16
-
17
- export { _resetComputedForTests as _, isComputedStore as a, createComputed as c, deleteComputed as d, invalidateComputed as i };
@@ -1,245 +0,0 @@
1
- type StoreValue = unknown;
2
- interface PersistDriver {
3
- getItem?: (k: string) => string | null | Promise<string | null>;
4
- setItem?: (k: string, v: string) => void | Promise<void>;
5
- removeItem?: (k: string) => void | Promise<void>;
6
- [key: string]: unknown;
7
- }
8
- type StoreScope = "request" | "global" | "temp";
9
- type SnapshotMode = "deep" | "shallow" | "ref";
10
- type ValidateFn<State = StoreValue> = (next: State) => boolean | State;
11
- type SchemaValidateOption = {
12
- safeParse: (value: unknown) => {
13
- success: true;
14
- data: unknown;
15
- } | {
16
- success: false;
17
- error?: unknown;
18
- };
19
- } | {
20
- parse: (value: unknown) => unknown;
21
- } | {
22
- validateSync: (value: unknown) => unknown;
23
- } | {
24
- isValidSync: (value: unknown) => boolean;
25
- } | {
26
- validate: (value: unknown) => unknown;
27
- };
28
- type ValidateOption<State = StoreValue> = ValidateFn<State> | SchemaValidateOption;
29
- interface PersistOptions<State = StoreValue> {
30
- driver?: PersistDriver;
31
- storage?: PersistDriver;
32
- key?: string;
33
- serialize?: (v: unknown) => string;
34
- deserialize?: (v: string) => unknown;
35
- /**
36
- * Optional encryption hook for persisted payloads.
37
- *
38
- * Default is identity (no encryption). Data is stored in plaintext.
39
- */
40
- encrypt?: (v: string) => string;
41
- /**
42
- * Optional async encryption hook for persisted payloads.
43
- *
44
- * When provided, persistence will encrypt in the background and hydrate asynchronously.
45
- */
46
- encryptAsync?: (v: string) => Promise<string>;
47
- /**
48
- * Optional decryption hook for persisted payloads.
49
- *
50
- * Default is identity (no encryption). Data is stored in plaintext.
51
- */
52
- decrypt?: (v: string) => string;
53
- /**
54
- * Optional async decryption hook for persisted payloads.
55
- *
56
- * When provided, persistence will hydrate asynchronously after store creation.
57
- */
58
- decryptAsync?: (v: string) => Promise<string>;
59
- /**
60
- * Explicitly allow plaintext persistence when encrypt/decrypt are identity.
61
- *
62
- * In production builds, plaintext persistence is blocked unless this is true.
63
- */
64
- allowPlaintext?: boolean;
65
- /**
66
- * Marks this store's persisted data as sensitive (secrets/PII).
67
- *
68
- * When `true`, stroid throws at store creation time unless a non-identity
69
- * `encrypt` hook is provided.
70
- */
71
- sensitiveData?: boolean;
72
- /**
73
- * Integrity check mode for persisted payloads.
74
- * - "hash" (default): store and validate a checksum.
75
- * - "none": skip checksum generation/validation.
76
- * - "sha256": store a SHA-256 hash for stronger tamper detection (may be async in browsers).
77
- */
78
- checksum?: "hash" | "none" | "sha256";
79
- version?: number;
80
- migrations?: Record<number, (state: State) => State>;
81
- onMigrationFail?: "reset" | "keep" | ((state: unknown) => unknown);
82
- onStorageCleared?: (info: {
83
- name: string;
84
- key: string;
85
- reason: "clear" | "remove" | "missing";
86
- }) => void;
87
- }
88
- interface PersistConfig {
89
- driver: PersistDriver;
90
- key: string;
91
- serialize: (v: unknown) => string;
92
- deserialize: (v: string) => unknown;
93
- encrypt: (v: string) => string;
94
- decrypt: (v: string) => string;
95
- encryptAsync?: (v: string) => Promise<string>;
96
- decryptAsync?: (v: string) => Promise<string>;
97
- allowPlaintext?: boolean;
98
- sensitiveData?: boolean;
99
- checksum: "hash" | "none" | "sha256";
100
- onMigrationFail?: "reset" | "keep" | ((state: unknown) => unknown);
101
- onStorageCleared?: (info: {
102
- name: string;
103
- key: string;
104
- reason: "clear" | "remove" | "missing";
105
- }) => void;
106
- }
107
- interface MiddlewareCtx {
108
- action: string;
109
- name: string;
110
- prev: StoreValue;
111
- next: StoreValue;
112
- path: unknown;
113
- }
114
- interface SyncOptions {
115
- channel?: string;
116
- maxPayloadBytes?: number;
117
- /**
118
- * Optional shared token for lightweight cross-tab authentication.
119
- * When set, incoming sync messages without a matching token are rejected.
120
- */
121
- authToken?: string;
122
- conflictResolver?: (args: {
123
- local: StoreValue;
124
- incoming: StoreValue;
125
- localUpdated: number;
126
- incomingUpdated: number;
127
- }) => StoreValue | void;
128
- /**
129
- * Optional checksum mode for sync payloads.
130
- * - "hash" (default): include a checksum of the payload.
131
- * - "none": skip checksum generation.
132
- */
133
- checksum?: "hash" | "none";
134
- /**
135
- * Optional signer for sync payloads. The returned value is attached to the message as `auth`.
136
- */
137
- sign?: (payload: SyncMessage) => unknown;
138
- /**
139
- * Optional verifier for incoming sync payloads.
140
- * Return true to accept the message, false to reject it.
141
- */
142
- verify?: (payload: SyncMessage) => boolean;
143
- /**
144
- * Optional resolver for updatedAt timestamps when conflicts are resolved.
145
- */
146
- resolveUpdatedAt?: (args: {
147
- localUpdated: number;
148
- incomingUpdated: number | undefined;
149
- now: number;
150
- }) => number;
151
- }
152
- type SyncMessage = {
153
- v: number;
154
- protocol: number;
155
- type: "sync-request" | "sync-state";
156
- name: string;
157
- clock: number;
158
- source: string;
159
- updatedAt?: number;
160
- data?: StoreValue;
161
- checksum?: number | null;
162
- auth?: unknown;
163
- token?: string;
164
- requestedAt?: number;
165
- };
166
- interface DevtoolsOptions<State = StoreValue> {
167
- enabled?: boolean;
168
- historyLimit?: number;
169
- redactor?: (state: State) => State;
170
- }
171
- interface LifecycleOptions<State = StoreValue> {
172
- middleware?: Array<(ctx: MiddlewareCtx) => StoreValue | void>;
173
- onSet?: (prev: State, next: State) => void;
174
- onReset?: (prev: State, next: State) => void;
175
- onDelete?: (prev: State) => void;
176
- onCreate?: (initial: State) => void;
177
- }
178
- interface StoreOptions<State = StoreValue> {
179
- scope?: StoreScope;
180
- lazy?: boolean;
181
- /**
182
- * Allow `setStore(name, path, value)` to create missing **leaf** keys on object nodes.
183
- *
184
- * Default: `false` (strict path writes).
185
- *
186
- * Notes:
187
- * - Does not expand arrays (out-of-bounds indices are still rejected).
188
- * - Does not create missing intermediate objects for deep paths; define the shape up-front.
189
- */
190
- pathCreate?: boolean;
191
- validate?: ValidateOption<State>;
192
- persist?: boolean | string | PersistOptions<State>;
193
- devtools?: boolean | DevtoolsOptions<State>;
194
- lifecycle?: LifecycleOptions<State>;
195
- middleware?: Array<(ctx: MiddlewareCtx) => StoreValue | void>;
196
- onSet?: (prev: State, next: State) => void;
197
- onReset?: (prev: State, next: State) => void;
198
- onDelete?: (prev: State) => void;
199
- onCreate?: (initial: State) => void;
200
- onError?: (err: string) => void;
201
- /** @deprecated use validate instead */
202
- validator?: (next: State) => boolean;
203
- /** @deprecated use validate instead */
204
- schema?: unknown;
205
- migrations?: Record<number, (state: State) => State>;
206
- version?: number;
207
- redactor?: (state: State) => State;
208
- historyLimit?: number;
209
- allowSSRGlobalStore?: boolean;
210
- sync?: boolean | SyncOptions;
211
- /**
212
- * Snapshot cloning strategy used by subscriptions and selector snapshots.
213
- *
214
- * - "deep" (default): deep clone and dev-freeze snapshot values.
215
- * - "shallow": shallow clone (top-level) only; nested references are shared.
216
- * - "ref": return the live store reference (no cloning).
217
- */
218
- snapshot?: SnapshotMode;
219
- }
220
- interface NormalizedOptions {
221
- scope: StoreScope;
222
- lazy: boolean;
223
- pathCreate: boolean;
224
- persist: PersistConfig | null;
225
- devtools: boolean;
226
- middleware: Array<(ctx: MiddlewareCtx) => StoreValue | void>;
227
- onSet?: (prev: StoreValue, next: StoreValue) => void;
228
- onReset?: (prev: StoreValue, next: StoreValue) => void;
229
- onDelete?: (prev: StoreValue) => void;
230
- onCreate?: (initial: StoreValue) => void;
231
- onError?: (err: string) => void;
232
- validate?: ValidateOption;
233
- migrations: Record<number, (state: any) => any>;
234
- version: number;
235
- redactor?: (state: StoreValue) => StoreValue;
236
- historyLimit: number;
237
- allowSSRGlobalStore?: boolean;
238
- sync?: boolean | SyncOptions;
239
- snapshot: SnapshotMode;
240
- explicitPersist: boolean;
241
- explicitSync: boolean;
242
- explicitDevtools: boolean;
243
- }
244
-
245
- export type { MiddlewareCtx as M, NormalizedOptions as N, PersistOptions as P, StoreOptions as S, StoreValue as a, SnapshotMode as b, SyncOptions as c };
@@ -1,245 +0,0 @@
1
- type StoreValue = unknown;
2
- interface PersistDriver {
3
- getItem?: (k: string) => string | null | Promise<string | null>;
4
- setItem?: (k: string, v: string) => void | Promise<void>;
5
- removeItem?: (k: string) => void | Promise<void>;
6
- [key: string]: unknown;
7
- }
8
- type StoreScope = "request" | "global" | "temp";
9
- type SnapshotMode = "deep" | "shallow" | "ref";
10
- type ValidateFn<State = StoreValue> = (next: State) => boolean | State;
11
- type SchemaValidateOption = {
12
- safeParse: (value: unknown) => {
13
- success: true;
14
- data: unknown;
15
- } | {
16
- success: false;
17
- error?: unknown;
18
- };
19
- } | {
20
- parse: (value: unknown) => unknown;
21
- } | {
22
- validateSync: (value: unknown) => unknown;
23
- } | {
24
- isValidSync: (value: unknown) => boolean;
25
- } | {
26
- validate: (value: unknown) => unknown;
27
- };
28
- type ValidateOption<State = StoreValue> = ValidateFn<State> | SchemaValidateOption;
29
- interface PersistOptions<State = StoreValue> {
30
- driver?: PersistDriver;
31
- storage?: PersistDriver;
32
- key?: string;
33
- serialize?: (v: unknown) => string;
34
- deserialize?: (v: string) => unknown;
35
- /**
36
- * Optional encryption hook for persisted payloads.
37
- *
38
- * Default is identity (no encryption). Data is stored in plaintext.
39
- */
40
- encrypt?: (v: string) => string;
41
- /**
42
- * Optional async encryption hook for persisted payloads.
43
- *
44
- * When provided, persistence will encrypt in the background and hydrate asynchronously.
45
- */
46
- encryptAsync?: (v: string) => Promise<string>;
47
- /**
48
- * Optional decryption hook for persisted payloads.
49
- *
50
- * Default is identity (no encryption). Data is stored in plaintext.
51
- */
52
- decrypt?: (v: string) => string;
53
- /**
54
- * Optional async decryption hook for persisted payloads.
55
- *
56
- * When provided, persistence will hydrate asynchronously after store creation.
57
- */
58
- decryptAsync?: (v: string) => Promise<string>;
59
- /**
60
- * Explicitly allow plaintext persistence when encrypt/decrypt are identity.
61
- *
62
- * In production builds, plaintext persistence is blocked unless this is true.
63
- */
64
- allowPlaintext?: boolean;
65
- /**
66
- * Marks this store's persisted data as sensitive (secrets/PII).
67
- *
68
- * When `true`, stroid throws at store creation time unless a non-identity
69
- * `encrypt` hook is provided.
70
- */
71
- sensitiveData?: boolean;
72
- /**
73
- * Integrity check mode for persisted payloads.
74
- * - "hash" (default): store and validate a checksum.
75
- * - "none": skip checksum generation/validation.
76
- * - "sha256": store a SHA-256 hash for stronger tamper detection (may be async in browsers).
77
- */
78
- checksum?: "hash" | "none" | "sha256";
79
- version?: number;
80
- migrations?: Record<number, (state: State) => State>;
81
- onMigrationFail?: "reset" | "keep" | ((state: unknown) => unknown);
82
- onStorageCleared?: (info: {
83
- name: string;
84
- key: string;
85
- reason: "clear" | "remove" | "missing";
86
- }) => void;
87
- }
88
- interface PersistConfig {
89
- driver: PersistDriver;
90
- key: string;
91
- serialize: (v: unknown) => string;
92
- deserialize: (v: string) => unknown;
93
- encrypt: (v: string) => string;
94
- decrypt: (v: string) => string;
95
- encryptAsync?: (v: string) => Promise<string>;
96
- decryptAsync?: (v: string) => Promise<string>;
97
- allowPlaintext?: boolean;
98
- sensitiveData?: boolean;
99
- checksum: "hash" | "none" | "sha256";
100
- onMigrationFail?: "reset" | "keep" | ((state: unknown) => unknown);
101
- onStorageCleared?: (info: {
102
- name: string;
103
- key: string;
104
- reason: "clear" | "remove" | "missing";
105
- }) => void;
106
- }
107
- interface MiddlewareCtx {
108
- action: string;
109
- name: string;
110
- prev: StoreValue;
111
- next: StoreValue;
112
- path: unknown;
113
- }
114
- interface SyncOptions {
115
- channel?: string;
116
- maxPayloadBytes?: number;
117
- /**
118
- * Optional shared token for lightweight cross-tab authentication.
119
- * When set, incoming sync messages without a matching token are rejected.
120
- */
121
- authToken?: string;
122
- conflictResolver?: (args: {
123
- local: StoreValue;
124
- incoming: StoreValue;
125
- localUpdated: number;
126
- incomingUpdated: number;
127
- }) => StoreValue | void;
128
- /**
129
- * Optional checksum mode for sync payloads.
130
- * - "hash" (default): include a checksum of the payload.
131
- * - "none": skip checksum generation.
132
- */
133
- checksum?: "hash" | "none";
134
- /**
135
- * Optional signer for sync payloads. The returned value is attached to the message as `auth`.
136
- */
137
- sign?: (payload: SyncMessage) => unknown;
138
- /**
139
- * Optional verifier for incoming sync payloads.
140
- * Return true to accept the message, false to reject it.
141
- */
142
- verify?: (payload: SyncMessage) => boolean;
143
- /**
144
- * Optional resolver for updatedAt timestamps when conflicts are resolved.
145
- */
146
- resolveUpdatedAt?: (args: {
147
- localUpdated: number;
148
- incomingUpdated: number | undefined;
149
- now: number;
150
- }) => number;
151
- }
152
- type SyncMessage = {
153
- v: number;
154
- protocol: number;
155
- type: "sync-request" | "sync-state";
156
- name: string;
157
- clock: number;
158
- source: string;
159
- updatedAt?: number;
160
- data?: StoreValue;
161
- checksum?: number | null;
162
- auth?: unknown;
163
- token?: string;
164
- requestedAt?: number;
165
- };
166
- interface DevtoolsOptions<State = StoreValue> {
167
- enabled?: boolean;
168
- historyLimit?: number;
169
- redactor?: (state: State) => State;
170
- }
171
- interface LifecycleOptions<State = StoreValue> {
172
- middleware?: Array<(ctx: MiddlewareCtx) => StoreValue | void>;
173
- onSet?: (prev: State, next: State) => void;
174
- onReset?: (prev: State, next: State) => void;
175
- onDelete?: (prev: State) => void;
176
- onCreate?: (initial: State) => void;
177
- }
178
- interface StoreOptions<State = StoreValue> {
179
- scope?: StoreScope;
180
- lazy?: boolean;
181
- /**
182
- * Allow `setStore(name, path, value)` to create missing **leaf** keys on object nodes.
183
- *
184
- * Default: `false` (strict path writes).
185
- *
186
- * Notes:
187
- * - Does not expand arrays (out-of-bounds indices are still rejected).
188
- * - Does not create missing intermediate objects for deep paths; define the shape up-front.
189
- */
190
- pathCreate?: boolean;
191
- validate?: ValidateOption<State>;
192
- persist?: boolean | string | PersistOptions<State>;
193
- devtools?: boolean | DevtoolsOptions<State>;
194
- lifecycle?: LifecycleOptions<State>;
195
- middleware?: Array<(ctx: MiddlewareCtx) => StoreValue | void>;
196
- onSet?: (prev: State, next: State) => void;
197
- onReset?: (prev: State, next: State) => void;
198
- onDelete?: (prev: State) => void;
199
- onCreate?: (initial: State) => void;
200
- onError?: (err: string) => void;
201
- /** @deprecated use validate instead */
202
- validator?: (next: State) => boolean;
203
- /** @deprecated use validate instead */
204
- schema?: unknown;
205
- migrations?: Record<number, (state: State) => State>;
206
- version?: number;
207
- redactor?: (state: State) => State;
208
- historyLimit?: number;
209
- allowSSRGlobalStore?: boolean;
210
- sync?: boolean | SyncOptions;
211
- /**
212
- * Snapshot cloning strategy used by subscriptions and selector snapshots.
213
- *
214
- * - "deep" (default): deep clone and dev-freeze snapshot values.
215
- * - "shallow": shallow clone (top-level) only; nested references are shared.
216
- * - "ref": return the live store reference (no cloning).
217
- */
218
- snapshot?: SnapshotMode;
219
- }
220
- interface NormalizedOptions {
221
- scope: StoreScope;
222
- lazy: boolean;
223
- pathCreate: boolean;
224
- persist: PersistConfig | null;
225
- devtools: boolean;
226
- middleware: Array<(ctx: MiddlewareCtx) => StoreValue | void>;
227
- onSet?: (prev: StoreValue, next: StoreValue) => void;
228
- onReset?: (prev: StoreValue, next: StoreValue) => void;
229
- onDelete?: (prev: StoreValue) => void;
230
- onCreate?: (initial: StoreValue) => void;
231
- onError?: (err: string) => void;
232
- validate?: ValidateOption;
233
- migrations: Record<number, (state: any) => any>;
234
- version: number;
235
- redactor?: (state: StoreValue) => StoreValue;
236
- historyLimit: number;
237
- allowSSRGlobalStore?: boolean;
238
- sync?: boolean | SyncOptions;
239
- snapshot: SnapshotMode;
240
- explicitPersist: boolean;
241
- explicitSync: boolean;
242
- explicitDevtools: boolean;
243
- }
244
-
245
- export type { MiddlewareCtx as M, NormalizedOptions as N, PersistOptions as P, StoreOptions as S, StoreValue as a, SnapshotMode as b, SyncOptions as c };