0.5.0 • Published 4 months ago

@maal/svelte-data v0.5.0

Weekly downloads
-
License
MIT
Repository
-
Last release
4 months ago

Svelte.Data - Svelte

Logo

Package aiming to make it easier to manage data with advanced features in Svelte apps

Important

Your tsconfig.json must be set to "moduleResolution": "bundler"

Components

EnhancedSelect

For scenarios when the native <select> element does not suffice.

Example

<form on:submit|preventDefault={onSubmit} style="width: 100%;">
	<EnhancedSelect name="users" pool={users} values={[1, 3]} force multiple let:values let:pool>
		<svelte:fragment slot="summary">
			{@const filtered = pool.filter((user) => values.includes(user.id))}
			<input type="text" readonly style="width: 100%" value={filtered.map((user) => user.username).join(", ")} />
		</svelte:fragment>
		<div class="selector">
			{@const filtered = filterOptions(users)}
			<input type="search" style="width: 100%" placeholder="Employee" name="name" />
			<input type="search" style="width: 100%" placeholder="Employee" name="username" />
			<EnhancedOption {registerOption} togglesAll>
				<input tabindex="-1" type="checkbox" checked={allChecked} />
				{#if allChecked}Uncheck all{:else}Check all{/if} ({filtered.length})
			</EnhancedOption>
			{#each filtered as user (user.id)}
				<EnhancedOption {registerOption} value={user.id} item={user} let:checked
					><input tabindex="-1" type="checkbox" {checked} />{user.name}</EnhancedOption>
			{/each}
		</div>
	</EnhancedSelect>
	<button type="submit">submit</button>
</form>

Syncer

Handle pulling and pushing a value to and from a replication source

NameReplication source
LocalStorageSyncerwindow.localStorage
SessionStorageSyncerwindow.sessionStorage
CookieSyncerdocument.cookie

Scenarios

Examples on how you can employ these components in different scenarios:

Sync value to window.localStorage

import { LocalStorageSyncer } from "@maal/svelte-data/sync";
import { writable } from "svelte/store";

const syncer = new LocalStorageSyncer("key", "initialValue");
export const someStore = writable<string>(syncer.pull());
someStore.subscribe((value) => syncer.push(value));

Recommendations for handling remote data

Recommendation: For models, use classes. Not interfaces.
Reason: interfaces exist to tell TypeScript that "this object is guaranteed to have these members".
This is fine at build-time, but when dealing with data stored at various locations at runtime, we can't guarantee that.

Did the REST endpoint you are calling change? Did the user modify the data stored in localStorage? Was there a JSON property that could be null that your code has not accounted for?

All of these problems are dealt with when doing the following:

1. Make sure the Response is what you expect it to be

import { ensureArray } from "@maal/svelte-data/types";

Response.prototype.ensureSuccess = function (): Response {
	if (!this.ok) {
		throw new Error(`Expected status code indicating success, got: ${this.status} ${this.statusText}`);
	}
	return this;
};

export class TestHTTP {
	public async getForecasts(): Promise<WeatherForecast[]> {
		const res = await window.fetch("http://localhost:5173/api/weatherforecast");
		return ensureArray(await res.ensureSuccess().json()).map((el) => new WeatherForecast(el));
	}
}

2. Make sure the JSON is what you expect it to be

import { ensureObject, ensureDateString, ensureNumber, ensureString } from "@maal/svelte-data";

export class WeatherForecast {
	date: Date;

	temperatureC: number;

	temperatureF: number;

	summary: string | null;

	public constructor(something: unknown) {
		const o = ensureObject(something);
		this.date = ensureDateString(o.date);
		this.temperatureC = ensureNumber(o.temperatureC);
		this.temperatureF = ensureNumber(o.temperatureF);
		this.summary = ensureString(o.summary);
	}
}

HTTPClient

Using HTTPClient does these things for you:

import { HTTPClient } from "@maal/svelte-data/http";
import { WeatherForecast } from "$lib/models/WeatherForecast.js";

/** @static */
export class TestHTTP {
	/** TODOC */
	private static httpClient = new HTTPClient("http://localhost:5173/api/", { redirect: "manual", credentials: "include" });

	/** @param fetch This is only needed for SSR */
	public static async getForecasts(fetch?: typeof window.fetch): Promise<WeatherForecast[]> {
		return await this.httpClient
			.get("weatherforecast")
			.withFetch(fetch) // If you are fetching server-side in SvelteKit's `load` function
			.fromJSONArray((something) => new WeatherForecast(something));
	}
}
0.5.0

4 months ago

0.4.9

4 months ago

0.4.8

4 months ago

0.4.5

5 months ago

0.4.4

5 months ago

0.4.7

5 months ago

0.4.6

5 months ago

0.4.3

5 months ago

0.4.2

5 months ago

0.4.1

5 months ago

0.4.0

5 months ago

0.3.9

6 months ago

0.3.0

7 months ago

0.3.6

6 months ago

0.2.7

8 months ago

0.3.5

6 months ago

0.2.6

8 months ago

0.3.8

6 months ago

0.2.9

8 months ago

0.3.7

6 months ago

0.2.8

8 months ago

0.3.2

7 months ago

0.3.4

6 months ago

0.2.1

12 months ago

0.2.0

12 months ago

0.1.8

1 year ago

0.1.7

1 year ago

0.1.9

12 months ago

0.2.3

11 months ago

0.2.2

11 months ago

0.2.5

11 months ago

0.2.4

11 months ago

0.1.6

1 year ago

0.1.5

1 year ago

0.1.4

1 year ago

0.1.3

1 year ago

0.1.2

1 year ago

0.1.1

1 year ago

0.1.0

1 year ago