tinybase 7.1.0-beta.0 → 7.1.0-beta.2

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 (46) hide show
  1. package/@types/persisters/index.d.ts +3 -3
  2. package/@types/persisters/with-schemas/index.d.ts +6 -6
  3. package/@types/schematizers/index.d.ts +41 -0
  4. package/@types/schematizers/schematizer-typebox/index.d.ts +116 -0
  5. package/@types/schematizers/schematizer-typebox/with-schemas/index.d.ts +8 -0
  6. package/@types/schematizers/schematizer-zod/index.d.ts +113 -0
  7. package/@types/schematizers/schematizer-zod/with-schemas/index.d.ts +7 -0
  8. package/@types/schematizers/with-schemas/index.d.ts +12 -0
  9. package/@types/ui-react/index.d.ts +2 -2
  10. package/@types/ui-react/with-schemas/index.d.ts +4 -4
  11. package/agents.md +144 -0
  12. package/index.js +2 -1
  13. package/mergeable-store/index.js +2 -1
  14. package/mergeable-store/with-schemas/index.js +2 -1
  15. package/min/schematizers/index.js +1 -0
  16. package/min/schematizers/index.js.gz +0 -0
  17. package/min/schematizers/schematizer-typebox/index.js +1 -0
  18. package/min/schematizers/schematizer-typebox/index.js.gz +0 -0
  19. package/min/schematizers/schematizer-typebox/with-schemas/index.js +1 -0
  20. package/min/schematizers/schematizer-typebox/with-schemas/index.js.gz +0 -0
  21. package/min/schematizers/schematizer-zod/index.js +1 -0
  22. package/min/schematizers/schematizer-zod/index.js.gz +0 -0
  23. package/min/schematizers/schematizer-zod/with-schemas/index.js +1 -0
  24. package/min/schematizers/schematizer-zod/with-schemas/index.js.gz +0 -0
  25. package/min/schematizers/with-schemas/index.js +1 -0
  26. package/min/schematizers/with-schemas/index.js.gz +0 -0
  27. package/omni/index.js +2 -1
  28. package/omni/with-schemas/index.js +2 -1
  29. package/package.json +121 -5
  30. package/queries/index.js +2 -1
  31. package/queries/with-schemas/index.js +2 -1
  32. package/readme.md +13 -13
  33. package/releases.md +62 -38
  34. package/schematizers/index.js +1 -0
  35. package/schematizers/schematizer-typebox/index.js +106 -0
  36. package/schematizers/schematizer-typebox/with-schemas/index.js +106 -0
  37. package/schematizers/schematizer-zod/index.js +102 -0
  38. package/schematizers/schematizer-zod/with-schemas/index.js +102 -0
  39. package/schematizers/with-schemas/index.js +1 -0
  40. package/store/index.js +2 -1
  41. package/store/with-schemas/index.js +2 -1
  42. package/ui-react-dom/index.js +2 -1
  43. package/ui-react-dom/with-schemas/index.js +2 -1
  44. package/ui-react-inspector/index.js +2 -1
  45. package/ui-react-inspector/with-schemas/index.js +2 -1
  46. package/with-schemas/index.js +2 -1
@@ -232,8 +232,8 @@ export type PersisterListener<Persist extends Persists = Persists.StoreOnly> = (
232
232
  * @category Listener
233
233
  * @since v5.3.0
234
234
  */
235
- export type StatusListener<Persist extends Persists = Persists.StoreOnly> = (
236
- persister: Persister<Persist>,
235
+ export type StatusListener<Persister extends AnyPersister = AnyPersister> = (
236
+ persister: Persister,
237
237
  status: Status,
238
238
  ) => void;
239
239
 
@@ -1465,7 +1465,7 @@ export interface Persister<Persist extends Persists = Persists.StoreOnly> {
1465
1465
  * @category Listener
1466
1466
  * @since v5.3.0
1467
1467
  */
1468
- addStatusListener(listener: StatusListener<Persist>): Id;
1468
+ addStatusListener(listener: StatusListener<this>): Id;
1469
1469
 
1470
1470
  /**
1471
1471
  * The delListener method removes a listener that was previously added to the
@@ -283,8 +283,8 @@ export type PersisterListener<
283
283
  * This has schema-based typing. The following is a simplified representation:
284
284
  *
285
285
  * ```ts override
286
- * export type StatusListener<Persist extends Persists = Persists.StoreOnly> = (
287
- * persister: Persister<Persist>,
286
+ * export type StatusListener<Persister extends AnyPersister = AnyPersister> = (
287
+ * persister: Persister,
288
288
  * status: Status,
289
289
  * ) => void;
290
290
  * ```
@@ -301,8 +301,8 @@ export type PersisterListener<
301
301
  */
302
302
  export type StatusListener<
303
303
  Schemas extends OptionalSchemas,
304
- Persist extends Persists = Persists.StoreOnly,
305
- > = (persister: Persister<Schemas, Persist>, status: Status) => void;
304
+ Persister extends AnyPersister<Schemas> = AnyPersister<Schemas>,
305
+ > = (persister: Persister, status: Status) => void;
306
306
 
307
307
  /**
308
308
  * The PersisterStats type describes the number of times a Persister object has
@@ -1536,7 +1536,7 @@ export interface Persister<
1536
1536
  * This has schema-based typing. The following is a simplified representation:
1537
1537
  *
1538
1538
  * ```ts override
1539
- * addStatusListener(listener: StatusListener<Persist>): Id;
1539
+ * addStatusListener(listener: StatusListener<this>): Id;
1540
1540
  * ```
1541
1541
  *
1542
1542
  * The provided listener is a StatusListener function, and will be called with
@@ -1573,7 +1573,7 @@ export interface Persister<
1573
1573
  * @category Listener
1574
1574
  * @since v5.3.0
1575
1575
  */
1576
- addStatusListener(listener: StatusListener<Schemas, Persist>): Id;
1576
+ addStatusListener(listener: StatusListener<Schemas, this>): Id;
1577
1577
 
1578
1578
  /**
1579
1579
  * The delListener method removes a listener that was previously added to the
@@ -0,0 +1,41 @@
1
+ /**
2
+ * The schematizers module provides utilities for converting schemas from
3
+ * popular validation libraries into TinyBase's schema format.
4
+ *
5
+ * Schematizers perform "best-effort" conversion, extracting basic type
6
+ * information (string, number, boolean) and default values while discarding
7
+ * complex validation rules that TinyBase doesn't support.
8
+ * @packageDocumentation
9
+ * @module schematizers
10
+ * @since v7.1.0
11
+ */
12
+ import type {TablesSchema, ValuesSchema} from '../store/index.d.ts';
13
+
14
+ /**
15
+ * The Schematizer interface represents a schema converter that can transform
16
+ * external validation library schemas into TinyBase TablesSchema and
17
+ * ValuesSchema formats.
18
+ * @category Schematizer
19
+ * @since v7.1.0
20
+ */
21
+ export interface Schematizer {
22
+ /**
23
+ * The toTablesSchema method converts a mapping of external schemas into a
24
+ * TinyBase TablesSchema.
25
+ * @param schemas - A mapping of table IDs to external schema objects.
26
+ * @returns A TinyBase TablesSchema.
27
+ * @category Conversion
28
+ * @since v7.1.0
29
+ */
30
+ toTablesSchema(schemas: any): TablesSchema;
31
+
32
+ /**
33
+ * The toValuesSchema method converts a mapping of external schemas into a
34
+ * TinyBase ValuesSchema.
35
+ * @param schemas - A mapping of value IDs to external schema objects.
36
+ * @returns A TinyBase ValuesSchema.
37
+ * @category Conversion
38
+ * @since v7.1.0
39
+ */
40
+ toValuesSchema(schemas: any): ValuesSchema;
41
+ }
@@ -0,0 +1,116 @@
1
+ /**
2
+ * The schematizer-typebox module provides conversion utilities for TypeBox
3
+ * schemas.
4
+ * @packageDocumentation
5
+ * @module schematizer-typebox
6
+ * @since v7.1.0
7
+ */
8
+ import type {TablesSchema, ValuesSchema} from '../../store/index.d.ts';
9
+ import type {Schematizer} from '../index.d.ts';
10
+
11
+ /**
12
+ * The TypeBoxSchematizer interface represents a schematizer specifically for
13
+ * converting TypeBox schemas into TinyBase schemas.
14
+ * @category Schematizer
15
+ * @since v7.1.0
16
+ */
17
+ export interface TypeBoxSchematizer extends Schematizer {
18
+ /**
19
+ * The toTablesSchema method converts a mapping of TypeBox object schemas into a
20
+ * TinyBase TablesSchema.
21
+ *
22
+ * This method extracts basic type information (string, number, boolean),
23
+ * default values, and nullable flags from TypeBox schemas. Complex validation
24
+ * rules like min/max, patterns, formats, and custom validators are ignored.
25
+ * @param schemas - A mapping of table IDs to TypeBox object schemas.
26
+ * @returns A TinyBase TablesSchema.
27
+ * @example
28
+ * This example converts TypeBox schemas to TinyBase format.
29
+ *
30
+ * ```js
31
+ * import {Type} from '@sinclair/typebox';
32
+ * import {createStore} from 'tinybase';
33
+ * import {createTypeBoxSchematizer} from 'tinybase/schematizers/schematizer-typebox';
34
+ *
35
+ * const schematizer = createTypeBoxSchematizer();
36
+ *
37
+ * const tablesSchema = schematizer.toTablesSchema({
38
+ * pets: Type.Object({
39
+ * species: Type.String(),
40
+ * age: Type.Number(),
41
+ * sold: Type.Boolean({default: false}),
42
+ * }),
43
+ * });
44
+ *
45
+ * const store = createStore().setTablesSchema(tablesSchema);
46
+ * store.setRow('pets', 'fido', {species: 'dog', age: 3});
47
+ * console.log(store.getRow('pets', 'fido'));
48
+ * // -> {species: 'dog', age: 3, sold: false}
49
+ * ```
50
+ * @category Conversion
51
+ * @since v7.1.0
52
+ */
53
+ toTablesSchema(schemas: {[tableId: string]: any}): TablesSchema;
54
+
55
+ /**
56
+ * The toValuesSchema method converts a mapping of TypeBox schemas into a
57
+ * TinyBase ValuesSchema.
58
+ *
59
+ * This method extracts basic type information (string, number, boolean),
60
+ * default values, and nullable flags from TypeBox schemas.
61
+ * @param schemas - A mapping of value IDs to TypeBox schemas.
62
+ * @returns A TinyBase ValuesSchema.
63
+ * @example
64
+ * This example converts TypeBox schemas to TinyBase ValuesSchema format.
65
+ *
66
+ * ```js
67
+ * import {Type} from '@sinclair/typebox';
68
+ * import {createStore} from 'tinybase';
69
+ * import {createTypeBoxSchematizer} from 'tinybase/schematizers/schematizer-typebox';
70
+ *
71
+ * const schematizer = createTypeBoxSchematizer();
72
+ *
73
+ * const valuesSchema = schematizer.toValuesSchema({
74
+ * theme: Type.String({default: 'light'}),
75
+ * count: Type.Number(),
76
+ * isOpen: Type.Boolean(),
77
+ * });
78
+ *
79
+ * const store = createStore().setValuesSchema(valuesSchema);
80
+ * store.setValue('count', 42);
81
+ * console.log(store.getValues());
82
+ * // -> {theme: 'light', count: 42}
83
+ * ```
84
+ * @category Conversion
85
+ * @since v7.1.0
86
+ */
87
+ toValuesSchema(schemas: {[valueId: string]: any}): ValuesSchema;
88
+ }
89
+
90
+ /**
91
+ * The createTypeBoxSchematizer function creates a TypeBoxSchematizer object
92
+ * that can convert TypeBox schemas into TinyBase schemas.
93
+ *
94
+ * The schematizer is stateless and can be reused for multiple conversions.
95
+ * @returns A new TypeBoxSchematizer instance.
96
+ * @example
97
+ * This example creates a TypeBox schematizer and uses it to convert schemas.
98
+ *
99
+ * ```js
100
+ * import {Type} from '@sinclair/typebox';
101
+ * import {createTypeBoxSchematizer} from 'tinybase/schematizers/schematizer-typebox';
102
+ *
103
+ * const schematizer = createTypeBoxSchematizer();
104
+ *
105
+ * const tablesSchema = schematizer.toTablesSchema({
106
+ * pets: Type.Object({
107
+ * species: Type.String(),
108
+ * }),
109
+ * });
110
+ * console.log(tablesSchema);
111
+ * // -> {pets: {species: {type: 'string'}}}
112
+ * ```
113
+ * @category Creation
114
+ * @since v7.1.0
115
+ */
116
+ export function createTypeBoxSchematizer(): TypeBoxSchematizer;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * The schematizer-typebox module provides conversion utilities for TypeBox
3
+ * schemas.
4
+ * @packageDocumentation
5
+ * @module schematizer-typebox
6
+ * @since v7.1.0
7
+ */
8
+ export type {TypeBoxSchematizer, createTypeBoxSchematizer} from '../index.d.ts';
@@ -0,0 +1,113 @@
1
+ /**
2
+ * The schematizer-zod module provides conversion utilities for Zod schemas.
3
+ * @packageDocumentation
4
+ * @module schematizer-zod
5
+ * @since v7.1.0
6
+ */
7
+ import type {TablesSchema, ValuesSchema} from '../../store/index.d.ts';
8
+ import type {Schematizer} from '../index.d.ts';
9
+
10
+ /**
11
+ * The ZodSchematizer interface represents a schematizer specifically for
12
+ * converting Zod schemas into TinyBase schemas.
13
+ * @category Schematizer
14
+ * @since v7.1.0
15
+ */
16
+ export interface ZodSchematizer extends Schematizer {
17
+ /**
18
+ * The toTablesSchema method converts a mapping of Zod object schemas into a
19
+ * TinyBase TablesSchema.
20
+ *
21
+ * This method extracts basic type information (string, number, boolean),
22
+ * default values, and nullable flags from Zod schemas. Complex validation
23
+ * rules like min/max, regex patterns, refinements, and transforms are ignored.
24
+ * @param schemas - A mapping of table IDs to Zod object schemas.
25
+ * @returns A TinyBase TablesSchema.
26
+ * @example
27
+ * This example converts Zod schemas to TinyBase format.
28
+ *
29
+ * ```js
30
+ * import {createStore} from 'tinybase';
31
+ * import {createZodSchematizer} from 'tinybase/schematizers/schematizer-zod';
32
+ * import {z} from 'zod';
33
+ *
34
+ * const schematizer = createZodSchematizer();
35
+ *
36
+ * const tablesSchema = schematizer.toTablesSchema({
37
+ * pets: z.object({
38
+ * species: z.string(),
39
+ * age: z.number(),
40
+ * sold: z.boolean().default(false),
41
+ * }),
42
+ * });
43
+ *
44
+ * const store = createStore().setTablesSchema(tablesSchema);
45
+ * store.setRow('pets', 'fido', {species: 'dog', age: 3});
46
+ * console.log(store.getRow('pets', 'fido'));
47
+ * // -> {species: 'dog', age: 3, sold: false}
48
+ * ```
49
+ * @category Conversion
50
+ * @since v7.1.0
51
+ */
52
+ toTablesSchema(schemas: {[tableId: string]: any}): TablesSchema;
53
+
54
+ /**
55
+ * The toValuesSchema method converts a mapping of Zod schemas into a TinyBase
56
+ * ValuesSchema.
57
+ *
58
+ * This method extracts basic type information and default values from Zod
59
+ * schemas.
60
+ * @param schemas - A mapping of value IDs to Zod schemas.
61
+ * @returns A TinyBase ValuesSchema.
62
+ * @example
63
+ * This example converts Zod value schemas.
64
+ *
65
+ * ```js
66
+ * import {createStore} from 'tinybase';
67
+ * import {createZodSchematizer} from 'tinybase/schematizers/schematizer-zod';
68
+ * import {z} from 'zod';
69
+ *
70
+ * const schematizer = createZodSchematizer();
71
+ *
72
+ * const valuesSchema = schematizer.toValuesSchema({
73
+ * theme: z.string().default('light'),
74
+ * count: z.number(),
75
+ * });
76
+ *
77
+ * const store = createStore().setValuesSchema(valuesSchema);
78
+ * console.log(store.getValues());
79
+ * // -> {theme: 'light'}
80
+ * ```
81
+ * @category Conversion
82
+ * @since v7.1.0
83
+ */
84
+ toValuesSchema(schemas: {[valueId: string]: any}): ValuesSchema;
85
+ }
86
+
87
+ /**
88
+ * The createZodSchematizer function creates a ZodSchematizer object that can
89
+ * convert Zod schemas into TinyBase schemas.
90
+ *
91
+ * The schematizer is stateless and can be reused for multiple conversions.
92
+ * @returns A new ZodSchematizer instance.
93
+ * @example
94
+ * This example creates a Zod schematizer and uses it to convert schemas.
95
+ *
96
+ * ```js
97
+ * import {createZodSchematizer} from 'tinybase/schematizers/schematizer-zod';
98
+ * import {z} from 'zod';
99
+ *
100
+ * const schematizer = createZodSchematizer();
101
+ *
102
+ * const tablesSchema = schematizer.toTablesSchema({
103
+ * pets: z.object({
104
+ * species: z.string(),
105
+ * }),
106
+ * });
107
+ * console.log(tablesSchema);
108
+ * // -> {pets: {species: {type: 'string'}}}
109
+ * ```
110
+ * @category Creation
111
+ * @since v7.1.0
112
+ */
113
+ export function createZodSchematizer(): ZodSchematizer;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * The schematizer-zod module provides conversion utilities for Zod schemas.
3
+ * @packageDocumentation
4
+ * @module schematizer-zod
5
+ * @since v7.1.0
6
+ */
7
+ export type {ZodSchematizer, createZodSchematizer} from '../index.d.ts';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * The schematizers module provides utilities for converting schemas from
3
+ * popular validation libraries into TinyBase's schema format.
4
+ *
5
+ * Schematizers perform "best-effort" conversion, extracting basic type
6
+ * information (string, number, boolean) and default values while discarding
7
+ * complex validation rules that TinyBase doesn't support.
8
+ * @packageDocumentation
9
+ * @module schematizers
10
+ * @since v7.1.0
11
+ */
12
+ export type {Schematizer} from '../index.d.ts';
@@ -12475,7 +12475,7 @@ export function usePersisterStatus(
12475
12475
  * @since v5.3.0
12476
12476
  */
12477
12477
  export function usePersisterStatusListener(
12478
- listener: StatusListener<Persists.StoreOrMergeableStore>,
12478
+ listener: StatusListener,
12479
12479
  listenerDeps?: React.DependencyList,
12480
12480
  persisterOrPersisterId?: PersisterOrPersisterId,
12481
12481
  ): void;
@@ -13053,7 +13053,7 @@ export function useSynchronizerStatus(
13053
13053
  * @since v5.3.0
13054
13054
  */
13055
13055
  export function useSynchronizerStatusListener(
13056
- listener: StatusListener<Persists.MergeableStoreOnly>,
13056
+ listener: StatusListener,
13057
13057
  listenerDeps?: React.DependencyList,
13058
13058
  synchronizerOrSynchronizerId?: SynchronizerOrSynchronizerId,
13059
13059
  ): void;
@@ -13487,7 +13487,7 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
13487
13487
  *
13488
13488
  * ```ts override
13489
13489
  * usePersisterStatusListener(
13490
- * listener: StatusListener<Persists.StoreOrMergeableStore>,
13490
+ * listener: StatusListener,
13491
13491
  * listenerDeps?: React.DependencyList,
13492
13492
  * persisterOrPersisterId?: PersisterOrPersisterId,
13493
13493
  * ): void;
@@ -13553,7 +13553,7 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
13553
13553
  * @since v5.3.0
13554
13554
  */
13555
13555
  usePersisterStatusListener: (
13556
- listener: StatusListener<Schemas, Persists.StoreOrMergeableStore>,
13556
+ listener: StatusListener<Schemas>,
13557
13557
  listenerDeps?: React.DependencyList,
13558
13558
  persisterOrPersisterId?: PersisterOrPersisterId<Schemas>,
13559
13559
  ) => void;
@@ -14039,7 +14039,7 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
14039
14039
  *
14040
14040
  * ```ts override
14041
14041
  * useSynchronizerStatusListener(
14042
- * listener: StatusListener<Persists.MergeableStoreOnly>,
14042
+ * listener: StatusListener,
14043
14043
  * listenerDeps?: React.DependencyList,
14044
14044
  * synchronizerOrSynchronizerId?: SynchronizerOrSynchronizerId,
14045
14045
  * ): void;
@@ -14105,7 +14105,7 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
14105
14105
  * @since v5.3.0
14106
14106
  */
14107
14107
  useSynchronizerStatusListener: (
14108
- listener: StatusListener<Schemas, Persists.StoreOrMergeableStore>,
14108
+ listener: StatusListener<Schemas>,
14109
14109
  listenerDeps?: React.DependencyList,
14110
14110
  synchronizerOrSynchronizerId?: SynchronizerOrSynchronizerId<Schemas>,
14111
14111
  ) => void;
package/agents.md CHANGED
@@ -341,3 +341,147 @@ npx vitest run ./test/unit/documentation.test.ts --retry=0
341
341
  2. **Guide Content**: Edit markdown files in `/site/guides/`
342
342
  3. **Release Notes**: Edit `/site/guides/16_releases.md` (not `/releases.md`)
343
343
  4. **Always run documentation tests** after changes to verify examples work
344
+
345
+ ## Creating New Schematizers
346
+
347
+ Schematizers convert external schema validation libraries (like Zod) to TinyBase
348
+ schemas. Follow this pattern:
349
+
350
+ ### Module Structure
351
+
352
+ ```
353
+ src/@types/schematizers/schematizer-{library}/
354
+ index.d.ts # Type definitions
355
+ docs.js # Documentation
356
+ with-schemas/
357
+ index.d.ts # Re-exports for schema-aware variants
358
+ src/schematizers/schematizer-{library}/
359
+ index.ts # Implementation
360
+ ```
361
+
362
+ ### Factory Pattern
363
+
364
+ ```typescript
365
+ export const createZodSchematizer: typeof createZodSchematizerDecl = () => {
366
+ const toTablesSchema = (schemas: {[tableId: string]: any}): TablesSchema => {
367
+ // Best-effort conversion logic
368
+ };
369
+
370
+ const toValuesSchema = (schemas: {[valueId: string]: any}): ValuesSchema => {
371
+ // Best-effort conversion logic
372
+ };
373
+
374
+ return objFreeze({
375
+ toTablesSchema,
376
+ toValuesSchema,
377
+ });
378
+ };
379
+ ```
380
+
381
+ ### Conversion Strategy
382
+
383
+ - Extract basic types only: `string`, `number`, `boolean`
384
+ - Handle defaults via schema introspection
385
+ - Support nullable and optional modifiers
386
+ - **Ignore** complex types (arrays, objects, etc.) - they won't appear in output
387
+ - Use recursive unwrapping for wrapper types (e.g., `ZodOptional`, `ZodNullable`,
388
+ `ZodDefault`)
389
+
390
+ ### Implementation Idioms
391
+
392
+ - Use `objForEach` for iteration, not `for...in` loops
393
+ - Use `ifNotUndefined` for conditional logic
394
+ - Use `objIsEmpty` to filter out empty table schemas
395
+ - Extract string constants to module-level (e.g., `TYPE`, `DEFAULT`,
396
+ `ALLOW_NULL`)
397
+ - Freeze the returned schematizer object with `objFreeze`
398
+
399
+ ### Example Conversion Logic
400
+
401
+ ```typescript
402
+ const unwrap = (
403
+ schema: any,
404
+ defaultValue?: any,
405
+ allowNull?: boolean,
406
+ ): [any, any, boolean] => {
407
+ const typeName = schema._def?.typeName;
408
+ return typeName === ZOD_OPTIONAL
409
+ ? unwrap(schema._def.innerType, defaultValue, allowNull)
410
+ : typeName === ZOD_NULLABLE
411
+ ? unwrap(schema._def.innerType, defaultValue, true)
412
+ : typeName === ZOD_DEFAULT
413
+ ? unwrap(schema._def.innerType, schema._def.defaultValue(), allowNull)
414
+ : [schema, defaultValue, allowNull ?? false];
415
+ };
416
+ ```
417
+
418
+ ### Build Configuration
419
+
420
+ - Add module to `ALL_MODULES` array in `gulpfile.mjs`
421
+ - Add peer dependency to `package.json` (marked as optional)
422
+ - Add as dev dependency for testing
423
+
424
+ ### Testing
425
+
426
+ - Create comprehensive test suite in
427
+ `test/unit/schematizers/schematizer-{library}.test.ts`
428
+ - Test basic type conversion, defaults, nullable, optional
429
+ - Test unsupported types are filtered out
430
+ - Test integration with actual TinyBase stores
431
+ - Inline schemas directly in test calls (no intermediate variables unless needed
432
+ multiple times)
433
+
434
+ ### Documentation Testing
435
+
436
+ Add library import to `test/unit/documentation.test.ts`:
437
+
438
+ ```typescript
439
+ import * as z from 'zod';
440
+ import * as TinyBaseSchematizersZod from 'tinybase/schematizers/schematizer-zod';
441
+
442
+ (globalThis as any).modules = {
443
+ ...
444
+ 'tinybase/schematizers/schematizer-zod': TinyBaseSchematizersZod,
445
+ zod: z,
446
+ };
447
+ ```
448
+
449
+ ## Guide Writing Best Practices
450
+
451
+ ### Examples Run Sequentially
452
+
453
+ All code examples in a guide file are concatenated and executed as a test:
454
+
455
+ - Use unique variable names (`store`, `store2`, `store3`) to avoid redeclaration
456
+ - First example includes all imports, later examples reuse them
457
+ - Clean up between examples if needed (`store.delTables()`)
458
+
459
+ ### Inline Simple Values
460
+
461
+ - Prefer inline schemas/data in method calls over intermediate variables
462
+ - Only extract to variables when used multiple times
463
+ - Keeps examples concise and focused
464
+
465
+ ### Guide Chains
466
+
467
+ - Each guide's summary should link to the next guide in sequence
468
+ - Pattern: "For that we proceed to the [Next Topic] guide."
469
+ - Creates a natural learning path
470
+
471
+ ## Release Notes Updates
472
+
473
+ When adding a new feature:
474
+
475
+ 1. **Update `/site/guides/16_releases.md`** (NOT `/releases.md`):
476
+ - Add new version section at the top
477
+ - Include working code example that will be tested
478
+ - Link to relevant guide if applicable
479
+ - Use past releases as template for structure
480
+
481
+ 2. **Update `/site/home/index.md`**:
482
+ - Update the "NEW!" link to point to new version:
483
+ `<a href='/guides/releases/#v7-1'>`
484
+ - Update the tagline:
485
+ `<span id="one-with">"The one with Schematizers!"</span>`
486
+
487
+ 3. **Generated files update automatically** during build process
package/index.js CHANGED
@@ -7,6 +7,7 @@ const FUNCTION = getTypeOf(getTypeOf);
7
7
  const TYPE = 'type';
8
8
  const DEFAULT = 'default';
9
9
  const ALLOW_NULL = 'allowNull';
10
+ const NULL = 'null';
10
11
  const SUM = 'sum';
11
12
  const AVG = 'avg';
12
13
  const MIN = 'min';
@@ -94,7 +95,7 @@ const arrayShift = (array) => array.shift();
94
95
 
95
96
  const getCellOrValueType = (cellOrValue) => {
96
97
  if (isNull(cellOrValue)) {
97
- return 'null';
98
+ return NULL;
98
99
  }
99
100
  const type = getTypeOf(cellOrValue);
100
101
  return isTypeStringOrBoolean(type) ||
@@ -7,6 +7,7 @@ const FUNCTION = getTypeOf(getTypeOf);
7
7
  const TYPE = 'type';
8
8
  const DEFAULT = 'default';
9
9
  const ALLOW_NULL = 'allowNull';
10
+ const NULL = 'null';
10
11
  const LISTENER = 'Listener';
11
12
  const SET = 'set';
12
13
  const ADD = 'add';
@@ -63,7 +64,7 @@ const tryCatch = async (action, then1, then2) => {
63
64
 
64
65
  const getCellOrValueType = (cellOrValue) => {
65
66
  if (isNull(cellOrValue)) {
66
- return 'null';
67
+ return NULL;
67
68
  }
68
69
  const type = getTypeOf(cellOrValue);
69
70
  return isTypeStringOrBoolean(type) ||
@@ -7,6 +7,7 @@ const FUNCTION = getTypeOf(getTypeOf);
7
7
  const TYPE = 'type';
8
8
  const DEFAULT = 'default';
9
9
  const ALLOW_NULL = 'allowNull';
10
+ const NULL = 'null';
10
11
  const LISTENER = 'Listener';
11
12
  const SET = 'set';
12
13
  const ADD = 'add';
@@ -63,7 +64,7 @@ const tryCatch = async (action, then1, then2) => {
63
64
 
64
65
  const getCellOrValueType = (cellOrValue) => {
65
66
  if (isNull(cellOrValue)) {
66
- return 'null';
67
+ return NULL;
67
68
  }
68
69
  const type = getTypeOf(cellOrValue);
69
70
  return isTypeStringOrBoolean(type) ||
@@ -0,0 +1 @@
1
+
Binary file
@@ -0,0 +1 @@
1
+ const t=t=>typeof t,e=t(""),r=t(!0),n=t(0),o="type",s="default",c="null",l=t=>(e,r,n)=>t(e)?n?.():r(e),u=t=>null==t,f=l(u),p=l(t=>void 0===t),a=Object,y=t=>a.getPrototypeOf(t),i=a.entries,h=a.keys,m=a.freeze,d=(t=[])=>a.fromEntries(t),O=(t,e)=>((t,e)=>t.forEach(e))(i(t),([t,r])=>e(r,t)),b="anyOf",g=(t,e,r)=>{if(t?.[b]){const r=t[b],n=r.some(t=>t?.type===c),o=r.find(t=>t?.type!==c);if(n&&o)return g(o,e??t?.[s],!0)}return[t,e??t?.[s],r??!1]},v=()=>{const t=t=>{const[c,l,u]=g(t),f=c?.type;if(f!==e&&f!==n&&f!==r)return;const a={[o]:f};return p(l,t=>{a[s]=t}),u&&(a.allowNull=!0),a};return m({toTablesSchema:e=>{const r=d();return O(e,(e,n)=>{const o=d();var s;p(e?.properties,e=>O(e,(e,r)=>p(t(e),t=>{o[r]=t}))),(t=>!u(t)&&f(y(t),t=>t==a.prototype||u(y(t)),()=>!0))(s=o)&&0==(t=>h(t).length)(s)||(r[n]=o)}),r},toValuesSchema:e=>{const r=d();return O(e,(e,n)=>p(t(e),t=>{r[n]=t})),r}})};export{v as createTypeBoxSchematizer};
@@ -0,0 +1 @@
1
+ const t=t=>typeof t,e=t(""),r=t(!0),n=t(0),o="type",s="default",c="null",l=t=>(e,r,n)=>t(e)?n?.():r(e),u=t=>null==t,f=l(u),p=l(t=>void 0===t),a=Object,y=t=>a.getPrototypeOf(t),i=a.entries,h=a.keys,m=a.freeze,d=(t=[])=>a.fromEntries(t),O=(t,e)=>((t,e)=>t.forEach(e))(i(t),([t,r])=>e(r,t)),b="anyOf",g=(t,e,r)=>{if(t?.[b]){const r=t[b],n=r.some(t=>t?.type===c),o=r.find(t=>t?.type!==c);if(n&&o)return g(o,e??t?.[s],!0)}return[t,e??t?.[s],r??!1]},v=()=>{const t=t=>{const[c,l,u]=g(t),f=c?.type;if(f!==e&&f!==n&&f!==r)return;const a={[o]:f};return p(l,t=>{a[s]=t}),u&&(a.allowNull=!0),a};return m({toTablesSchema:e=>{const r=d();return O(e,(e,n)=>{const o=d();var s;p(e?.properties,e=>O(e,(e,r)=>p(t(e),t=>{o[r]=t}))),(t=>!u(t)&&f(y(t),t=>t==a.prototype||u(y(t)),()=>!0))(s=o)&&0==(t=>h(t).length)(s)||(r[n]=o)}),r},toValuesSchema:e=>{const r=d();return O(e,(e,n)=>p(t(e),t=>{r[n]=t})),r}})};export{v as createTypeBoxSchematizer};
@@ -0,0 +1 @@
1
+ const e=e=>typeof e,t=e(""),n=e(!0),r=e(0),o="type",l="default",f=e=>(t,n,r)=>e(t)?r?.():n(t),s=e=>null==e,a=f(s),p=f(e=>void 0===e),u=Object,c=e=>u.getPrototypeOf(e),y=u.entries,d=u.keys,i=u.freeze,h=(e=[])=>u.fromEntries(e),T=(e,t)=>((e,t)=>e.forEach(t))(y(e),([e,n])=>t(n,e)),b=(e,t,n)=>{const r=e?.def?.type;return"optional"===r?b(e.def.innerType,t,n):"nullable"===r?b(e.def.innerType,t,!0):r===l?b(e.def.innerType,e.def.defaultValue,n):[e,t,n??!1]},m=()=>{const e=e=>{const[f,s,a]=b(e),u=f?.type;if(u!==t&&u!==r&&u!==n)return;const c={[o]:u};return p(s,e=>{c[l]=e}),a&&(c.allowNull=!0),c};return i({toTablesSchema:t=>{const n=h();return T(t,(t,r)=>{const o=h();var l;p(t?.def?.shape,t=>T(t,(t,n)=>p(e(t),e=>{o[n]=e}))),(e=>!s(e)&&a(c(e),e=>e==u.prototype||s(c(e)),()=>!0))(l=o)&&0==(e=>d(e).length)(l)||(n[r]=o)}),n},toValuesSchema:t=>{const n=h();return T(t,(t,r)=>p(e(t),e=>{n[r]=e})),n}})};export{m as createZodSchematizer};
@@ -0,0 +1 @@
1
+ const e=e=>typeof e,t=e(""),n=e(!0),r=e(0),o="type",l="default",f=e=>(t,n,r)=>e(t)?r?.():n(t),s=e=>null==e,a=f(s),p=f(e=>void 0===e),u=Object,c=e=>u.getPrototypeOf(e),y=u.entries,d=u.keys,i=u.freeze,h=(e=[])=>u.fromEntries(e),T=(e,t)=>((e,t)=>e.forEach(t))(y(e),([e,n])=>t(n,e)),b=(e,t,n)=>{const r=e?.def?.type;return"optional"===r?b(e.def.innerType,t,n):"nullable"===r?b(e.def.innerType,t,!0):r===l?b(e.def.innerType,e.def.defaultValue,n):[e,t,n??!1]},m=()=>{const e=e=>{const[f,s,a]=b(e),u=f?.type;if(u!==t&&u!==r&&u!==n)return;const c={[o]:u};return p(s,e=>{c[l]=e}),a&&(c.allowNull=!0),c};return i({toTablesSchema:t=>{const n=h();return T(t,(t,r)=>{const o=h();var l;p(t?.def?.shape,t=>T(t,(t,n)=>p(e(t),e=>{o[n]=e}))),(e=>!s(e)&&a(c(e),e=>e==u.prototype||s(c(e)),()=>!0))(l=o)&&0==(e=>d(e).length)(l)||(n[r]=o)}),n},toValuesSchema:t=>{const n=h();return T(t,(t,r)=>p(e(t),e=>{n[r]=e})),n}})};export{m as createZodSchematizer};