@sveltebase/state 0.3.4 → 0.4.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 CHANGED
@@ -5,12 +5,18 @@ Small state helpers for Svelte 5.
5
5
  This package exports two classes:
6
6
 
7
7
  - `State<T>`: simple reactive in-memory state
8
- - `PersistentState<TSchema>`: reactive state backed by cookies and validated with `zod`
8
+ - `PersistentState<TSchema>`: reactive state backed by cookies and validated with a Standard Schema-compatible validator
9
9
 
10
10
  ## Install
11
11
 
12
12
  ~~~bash
13
- bun add @sveltebase/state zod svelte
13
+ bun add @sveltebase/state svelte
14
+ ~~~
15
+
16
+ If you want to use `zod` as your schema library:
17
+
18
+ ~~~bash
19
+ bun add zod
14
20
  ~~~
15
21
 
16
22
  ## Exports
@@ -46,7 +52,7 @@ Cookie-backed state with schema validation.
46
52
  It:
47
53
 
48
54
  - reads from cookies
49
- - validates with `zod`
55
+ - validates with a Standard Schema-compatible validator
50
56
  - writes updates back to cookies
51
57
  - can load the initial value during SSR
52
58
 
@@ -97,10 +103,9 @@ export async function load({ cookies }) {
97
103
  import { z } from "zod";
98
104
  import { PersistentState } from "@sveltebase/state";
99
105
 
100
- export const locale = new PersistentState(
101
- "locale",
102
- z.enum(["en", "uz"]).default("en")
103
- );
106
+ const localeSchema = z.enum(["en", "uz"]).default("en");
107
+
108
+ export const locale = new PersistentState("locale", localeSchema);
104
109
  ~~~
105
110
 
106
111
  With this setup:
@@ -116,7 +121,7 @@ With this setup:
116
121
  Creates a persistent state value.
117
122
 
118
123
  - `key`: cookie name
119
- - `schema`: `zod` schema for parsing and validation
124
+ - `schema`: Standard Schema-compatible validator used for parsing and validation, such as a `zod` schema
120
125
 
121
126
  ### `persistentState.current`
122
127
 
@@ -149,4 +154,5 @@ type Cookie = {
149
154
  - `PersistentState` stores JSON in cookies
150
155
  - invalid cookie data falls back to the schema result
151
156
  - `init(...)` is for server-side initialization
157
+ - any Standard Schema-compatible library can be used here, including `zod`
152
158
  - this package is designed for Svelte 5
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export { PersistentState, State } from "./state.svelte.js";
2
- export type { MaybeGetter } from "./state.svelte.js";
2
+ export type { InferInput, InferOutput, MaybeGetter, StandardSchemaV1 } from "./state.svelte.js";
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC3D,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC3D,YAAY,EACV,UAAU,EACV,WAAW,EACX,WAAW,EACX,gBAAgB,EACjB,MAAM,mBAAmB,CAAC"}
@@ -1,17 +1,43 @@
1
- import { z } from "zod";
2
1
  export type MaybeGetter<T> = T | (() => T);
3
- export declare class PersistentState<TSchema extends z.ZodTypeAny> {
2
+ export interface StandardSchemaV1<Input = unknown, Output = Input> {
3
+ readonly "~standard": {
4
+ readonly version: 1;
5
+ readonly vendor: string;
6
+ readonly validate: (value: unknown) => {
7
+ readonly value: Output;
8
+ readonly issues?: undefined;
9
+ } | {
10
+ readonly issues: ReadonlyArray<{
11
+ readonly message: string;
12
+ }>;
13
+ } | Promise<{
14
+ readonly value: Output;
15
+ readonly issues?: undefined;
16
+ } | {
17
+ readonly issues: ReadonlyArray<{
18
+ readonly message: string;
19
+ }>;
20
+ }>;
21
+ readonly types?: {
22
+ readonly input: Input;
23
+ readonly output: Output;
24
+ };
25
+ };
26
+ }
27
+ export type InferInput<TSchema extends StandardSchemaV1> = NonNullable<TSchema["~standard"]["types"]>["input"];
28
+ export type InferOutput<TSchema extends StandardSchemaV1> = NonNullable<TSchema["~standard"]["types"]>["output"];
29
+ export declare class PersistentState<TSchema extends StandardSchemaV1> {
4
30
  #private;
5
31
  private storageKey;
6
32
  private schema;
7
33
  constructor(key: string, schema: TSchema);
8
- get current(): z.output<TSchema>;
9
- set current(newValue: z.output<TSchema>);
34
+ get current(): InferOutput<TSchema>;
35
+ set current(newValue: InferOutput<TSchema>);
10
36
  init(cookies: MaybeGetter<{
11
37
  name: string;
12
38
  value: string;
13
39
  }[]>): void;
14
- set(fn: (value: z.output<TSchema>) => z.output<TSchema>): void;
40
+ set(fn: (value: InferOutput<TSchema>) => InferOutput<TSchema>): void;
15
41
  private static hydrate;
16
42
  }
17
43
  export declare class State<T> {
@@ -1 +1 @@
1
- {"version":3,"file":"state.svelte.d.ts","sourceRoot":"","sources":["../src/state.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AAE3C,qBAAa,eAAe,CAAC,OAAO,SAAS,CAAC,CAAC,UAAU;;IAIvD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,MAAM,CAAU;gBAEZ,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO;IAmBxC,IAAI,OAAO,IAIW,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAFtC;IAED,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAEtC;IAEM,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAyB5D,GAAG,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;IAI9D,OAAO,CAAC,MAAM,CAAC,OAAO;CAiBvB;AAED,qBAAa,KAAK,CAAC,CAAC;;gBAGN,YAAY,EAAE,CAAC;IAI3B,IAAI,OAAO,IAIQ,CAAC,CAFnB;IAED,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,EAEnB;IAED,GAAG,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC;CAGxB"}
1
+ {"version":3,"file":"state.svelte.d.ts","sourceRoot":"","sources":["../src/state.svelte.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AAE3C,MAAM,WAAW,gBAAgB,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,KAAK;IAC/D,QAAQ,CAAC,WAAW,EAAE;QACpB,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;QACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,QAAQ,EAAE,CACjB,KAAK,EAAE,OAAO,KAEZ;YAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAA;SAAE,GACvD;YAAE,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;gBAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,GAChE,OAAO,CACH;YAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAA;SAAE,GACvD;YAAE,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;gBAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,CACnE,CAAC;QACN,QAAQ,CAAC,KAAK,CAAC,EAAE;YACf,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;YACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;SACzB,CAAC;KACH,CAAC;CACH;AAED,MAAM,MAAM,UAAU,CAAC,OAAO,SAAS,gBAAgB,IACrD,WAAW,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AAEtD,MAAM,MAAM,WAAW,CAAC,OAAO,SAAS,gBAAgB,IACtD,WAAW,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;AAEvD,qBAAa,eAAe,CAAC,OAAO,SAAS,gBAAgB;;IAI3D,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,MAAM,CAAU;gBAEZ,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO;IAmBxC,IAAI,OAAO,IAIW,WAAW,CAAC,OAAO,CAAC,CAFzC;IAED,IAAI,OAAO,CAAC,QAAQ,EAAE,WAAW,CAAC,OAAO,CAAC,EAEzC;IAEM,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAyB5D,GAAG,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,WAAW,CAAC,OAAO,CAAC;IAIpE,OAAO,CAAC,MAAM,CAAC,OAAO;CAoBvB;AAED,qBAAa,KAAK,CAAC,CAAC;;gBAGN,YAAY,EAAE,CAAC;IAI3B,IAAI,OAAO,IAIQ,CAAC,CAFnB;IAED,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,EAEnB;IAED,GAAG,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC;CAGxB"}
@@ -1,4 +1,3 @@
1
- import { z } from "zod";
2
1
  import { Cookies } from "@sveltebase/utils";
3
2
  export class PersistentState {
4
3
  #value = $state();
@@ -25,7 +24,7 @@ export class PersistentState {
25
24
  return this.#value;
26
25
  }
27
26
  set current(newValue) {
28
- this.#value = this.schema.parse(newValue);
27
+ this.#value = parseSchema(this.schema, newValue);
29
28
  }
30
29
  init(cookies) {
31
30
  if (this.#initialized || hasWindow()) {
@@ -38,7 +37,7 @@ export class PersistentState {
38
37
  return;
39
38
  }
40
39
  try {
41
- const parsed = this.schema.parse(JSON.parse(rawCookie.value));
40
+ const parsed = parseSchema(this.schema, JSON.parse(rawCookie.value));
42
41
  if (JSON.stringify(parsed) !== JSON.stringify(this.#value)) {
43
42
  this.#value = parsed;
44
43
  }
@@ -52,18 +51,18 @@ export class PersistentState {
52
51
  }
53
52
  static hydrate(key, schema) {
54
53
  if (!hasWindow()) {
55
- return schema.parse(undefined);
54
+ return parseSchema(schema, undefined);
56
55
  }
57
56
  const rawCookie = Cookies.get(key);
58
57
  if (rawCookie) {
59
58
  try {
60
- return schema.parse(JSON.parse(rawCookie));
59
+ return parseSchema(schema, JSON.parse(rawCookie));
61
60
  }
62
61
  catch {
63
62
  console.warn(`[PersistentState] Invalid data for "${key}". Resetting.`);
64
63
  }
65
64
  }
66
- return schema.parse(undefined);
65
+ return parseSchema(schema, undefined);
67
66
  }
68
67
  }
69
68
  export class State {
@@ -84,6 +83,16 @@ export class State {
84
83
  function unwrap(value) {
85
84
  return typeof value === "function" ? value() : value;
86
85
  }
86
+ function parseSchema(schema, value) {
87
+ const result = schema["~standard"].validate(value);
88
+ if (result instanceof Promise) {
89
+ throw new Error("[PersistentState] Async schemas are not supported.");
90
+ }
91
+ if (result.issues) {
92
+ throw new Error(result.issues.map((issue) => issue.message).join(", ") || "Validation failed.");
93
+ }
94
+ return result.value;
95
+ }
87
96
  function hasWindow() {
88
97
  return typeof window !== "undefined";
89
98
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltebase/state",
3
- "version": "0.3.4",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -18,8 +18,7 @@
18
18
  }
19
19
  },
20
20
  "dependencies": {
21
- "@sveltebase/utils": "0.3.4",
22
- "zod": "^4.1.11"
21
+ "@sveltebase/utils": "0.4.0"
23
22
  },
24
23
  "peerDependencies": {
25
24
  "svelte": "^5.0.0"