cell.svelte.ts

Declarations
#

3 declarations

view source

Cell
#

cell.svelte.ts view source

The Cell is the base class for schema-driven data models in Zzz. The goals are still evolving, but a main idea is to have fully reactive state that can be flexibly snapshotted and reinstantiated in a typesafe, extensible system that uses normal Svelte patterns.

The design aims for:

- Integration with Svelte's reactivity, encouraging single-depth inheritance with Svelte class patterns for both persistent and ephemeral state - Schema-driven parsing/validation and JSON serialization/deserialization (supporting snapshot and restore/replay patterns) via Zod - Custom property encoding/decoding for complex types, and no boilerplate for schema-inferrable properties - Lifecycle management with generic instantiation/registration and disposal (conceptually a WIP, partially implemented) - Runtime type metadata for reflection

Cells are automatically registered in the global registry by id, making them discoverable and referenceable throughout the system. Each cell has common properties including id and created/updated timestamps.

There are currently a lot of rough edges and missing features! My hope is that this could be generic enough to extract to a library, but it's not there yet. I assume there's a really nice design in this space that takes full advantage of Svelte runes.

Many things will be possible with this pattern, but it's still a work in progress.

generics

TSchema

constraint z.ZodType
default z.ZodType

inheritance

implements:

cid

readonly

id

type Uuid

created

type Datetime

updated

type Datetime

schema

type TSchema

readonly

schema_keys

type Array<SchemaKeys<TSchema>>

readonly

field_schemas

type Map<SchemaKeys<TSchema>, z.ZodType>

readonly

field_schema_info

type Map<SchemaKeys<TSchema>, SchemaClassInfo | null>

readonly

json

type z.output<TSchema>

readonly

json_serialized

type string

readonly

json_parsed

type z.ZodSafeParseResult<z.output<TSchema>>

readonly

app

type Frontend

readonly

decoders

Type-safe decoders for custom field decoding. Override in subclasses to handle special field types.

Each decoder function takes a value of any type and should either: 1. Return a value (including null) to be assigned to the property 2. Return undefined to use the default decoding behavior 3. Return HANDLED to indicate the decoder has fully processed the property (virtual properties MUST return HANDLED if they exist in schema but not in class)

type CellValueDecoder<TSchema>

protected

created_date

type Date

readonly

created_formatted_short_date

type string

readonly

created_formatted_datetime

type string

readonly

created_formatted_time

type string

readonly

updated_date

type Date

readonly

updated_formatted_short_date

type string

readonly

updated_formatted_datetime

type string

readonly

updated_formatted_time

type string

readonly

constructor

type new <TSchema extends z.ZodType = ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>>(schema: TSchema, options: CellOptions<TSchema>): Cell<TSchema>

schema
type TSchema
options
type CellOptions<TSchema>

init

Initialize the instance with options.json data if provided. Must be called before using the instance - the current pattern is calling it at the end of subclass constructors.

We should investigate deferring to callers so e.g. instantiating from the registry would init automatically, subclasses need no init logic (which can get unwieldy with inheritance), and then callers could always do custom init patterns if they wanted.

Can't be called automatically by the Cell's constructor because the subclass' constructor needs to run first to support field initialization. A design goal behind the Cell is to support normal TS and Svelte patterns with the most power and least intrusion. (there's a balance to find from Zzz's POV)

type (): void

protected
returns void

dispose

Clean up resources when this cell is no longer needed.

type (): void

returns void

[Symbol.dispose]

This is not supported in Safari, don't rely on this yet. Uncomment temporarily to experiment in dev.

type (): void

returns void

register

Register this cell in the global cell registry. Called automatically by init().

type (): void

protected
returns void

unregister

Unregister this cell from the global cell registry. Called automatically by dispose().

type (): void

protected
returns void

toJSON

For Svelte's $snapshot.

type (): output<TSchema>

returns output<TSchema>

to_json

Encodes the cell's serializable state as JSON. Use the derived cell.json if you don't need a fresh copy.

type (): output<TSchema>

returns output<TSchema>

set_json

Apply JSON data to this instance. Overwrites all properties including 'id'. Special-cases created and updated for synchronization.

type (value: input<TSchema> | undefined): void

value
type input<TSchema> | undefined
returns void

set_json_partial

Update only the specified properties on this instance. Preserves current values for any properties not included in the input.

type (partial_value: Partial<input<TSchema>>): void

partial_value
type Partial<input<TSchema>>
returns void

encode_property

Encode a value during serialization. Can be overridden for custom encoding logic. Defaults to Svelte's $state.snapshot, which handles most cases and uses toJSON when available, so overriding to_json is sufficient for most cases before overriding encode.

type (value: unknown, _key: string): unknown

value
type unknown
_key
type string
returns unknown

decode_property

Decode a value based on its schema type information. This handles instantiating classes, transforming arrays, and special types.

Complex property types might require custom handling in parser functions rather than using this general decoding mechanism.

type <K extends SchemaKeys<TSchema>>(value: unknown, key: K): any

value
type unknown
key
type K
returns any

assign_property

Process a single schema property during JSON deserialization. This method handles the workflow for mapping schema properties to instance properties.

Flow: 1. If a decoder exists for this property, try to use it 2. If decoder returns HANDLED, consider the property fully handled (short circuit) 3. If decoder returns a value other than HANDLED or undefined, use that value 4. If decoder returns undefined, fall through to standard decoding 5. For properties not directly represented in the class instance but defined in the schema, the decoder MUST return HANDLED to indicate proper handling

type (key: SchemaKeys<TSchema>, value: unknown): void

protected
key
type SchemaKeys<TSchema>
value
type unknown
returns void

clone

Generic clone method that works for any subclass.

type (json?: input<TSchema> | undefined, options?: CellOptions<TSchema> | undefined): this

json?
type input<TSchema> | undefined
optional
options?
type CellOptions<TSchema> | undefined
optional
returns this

CellOptions
#

cell.svelte.ts view source

CellOptions<TSchema>

Any options besides these declared ones are ignored, so they're safe to forward when subclassing without needing to extract the rest options.

generics

TSchema

constraint z.ZodType

app

json

type z.input<TSchema>

get_global_cell_count
#

cell.svelte.ts view source

(): number

A monotonic id for cell instances on the client. This is not reactive and never changes on the instance, whereas id can change. It's useful for ordering - the motivating usecase was correctly sorting objects with the same created millisecond.

This may cause issues based on how data gets queried, but at least it's stable once loaded. However we may need to revisit this if it causes problems.

returns

number

Depends on
#

Imported by
#