@flattype/models 1.5.0 → 1.6.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.
Files changed (2) hide show
  1. package/README.md +59 -4
  2. package/package.json +3 -3
package/README.md CHANGED
@@ -19,6 +19,7 @@
19
19
  <a href="https://www.npmjs.com/package/@flattype/react"><img src="https://img.shields.io/npm/v/@flattype/react?label=%40flattype%2Freact&color=8b6cff" alt="npm @flattype/react"></a>
20
20
  <a href="https://www.npmjs.com/package/@flattype/vue"><img src="https://img.shields.io/npm/v/@flattype/vue?label=%40flattype%2Fvue&color=8b6cff" alt="npm @flattype/vue"></a>
21
21
  <a href="https://www.npmjs.com/package/@flattype/angular"><img src="https://img.shields.io/npm/v/@flattype/angular?label=%40flattype%2Fangular&color=8b6cff" alt="npm @flattype/angular"></a>
22
+ <a href="https://www.npmjs.com/package/@flattype/svelte"><img src="https://img.shields.io/npm/v/@flattype/svelte?label=%40flattype%2Fsvelte&color=8b6cff" alt="npm @flattype/svelte"></a>
22
23
  <a href="https://github.com/karammm/flattype/actions/workflows/ci.yml"><img src="https://github.com/karammm/flattype/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
23
24
  <img src="https://img.shields.io/badge/core-3.7_KB_min%2Bgz-2fd4b2" alt="3.7 KB min+gz">
24
25
  <img src="https://img.shields.io/badge/dependencies-0-2fd4b2" alt="No third-party dependencies">
@@ -33,6 +34,7 @@
33
34
  <a href="#react"><b>React</b></a> ·
34
35
  <a href="#vue"><b>Vue</b></a> ·
35
36
  <a href="#angular"><b>Angular</b></a> ·
37
+ <a href="#svelte-and-solid"><b>Svelte &amp; Solid</b></a> ·
36
38
  <a href="#benchmarks"><b>Benchmarks</b></a> ·
37
39
  <a href="https://github.com/karammm/flattype/blob/main/CHANGELOG.md"><b>Changelog</b></a> ·
38
40
  <a href="https://github.com/karammm/flattype/blob/main/ROADMAP.md"><b>Roadmap</b></a>
@@ -41,10 +43,10 @@
41
43
  <p align="center">
42
44
  <a href="https://github.com/karammm/flattype/blob/main/docs/assets/flattype-intro.mp4">
43
45
  <img src="https://raw.githubusercontent.com/karammm/flattype/main/docs/assets/flattype-intro.gif" width="820"
44
- alt="FlatType.js in 71 seconds: an API response encoded to Flat Notation, how tables and dot paths keep it small, typed models mapped from snake_case JSON, an Express server answering in Flat Notation or JSON, React, Vue and Angular in real apps, and the size comparison with JSON and TOON">
46
+ alt="FlatType.js in 77 seconds: an API response encoded to Flat Notation, how tables and dot paths keep it small, typed models mapped from snake_case JSON, an Express server answering in Flat Notation or JSON, React, Vue, Angular and Svelte in real apps, and the size comparison with JSON and TOON">
45
47
  </a>
46
48
  <br>
47
- <sub>▶ <a href="https://github.com/karammm/flattype/blob/main/docs/assets/flattype-intro.mp4">Watch the 71-second intro in full quality</a>. Every result shown is real output, generated by <a href="https://github.com/karammm/flattype/blob/main/scripts/video/record.mjs"><code>scripts/video/record.mjs</code></a>.</sub>
49
+ <sub>▶ <a href="https://github.com/karammm/flattype/blob/main/docs/assets/flattype-intro.mp4">Watch the 77-second intro in full quality</a>. Every result shown is real output, generated by <a href="https://github.com/karammm/flattype/blob/main/scripts/video/record.mjs"><code>scripts/video/record.mjs</code></a>.</sub>
48
50
  </p>
49
51
 
50
52
  ---
@@ -103,7 +105,7 @@ app.use(flatExpress()); // server: res.json() answers in Flat Notation when the
103
105
  const users = await flatFetch("/api/users", { model: User, list: true }); // client: User[]
104
106
  ```
105
107
 
106
- And in React, Vue or Angular:
108
+ And in React, Vue, Angular, Svelte or Solid:
107
109
 
108
110
  ```tsx
109
111
  import { useFlat } from "@flattype/react"; // or "@flattype/vue": the same API, with refs
@@ -112,6 +114,10 @@ const { data: users, loading, error } = useFlat("/api/users", { model: User, lis
112
114
 
113
115
  // Angular: signals on top of HttpClient
114
116
  users = flatResource(() => "/api/users", { model: User, list: true }); // users.value(): User[] | undefined
117
+
118
+ // Svelte: a store, $users.data; Solid: a resource
119
+ const users = flatStore("/api/users", { model: User, list: true });
120
+ const [users] = createFlatResource(() => "/api/users", { model: User, list: true });
115
121
  ```
116
122
 
117
123
  ## Why FlatType
@@ -133,9 +139,10 @@ users = flatResource(() => "/api/users", { model: User, list: true }); // users.
133
139
  | [`@flattype/react`](https://github.com/karammm/flattype/blob/main/packages/react) | `useFlat`, `useFlatSuspense`, `useFlatStream`, `useModel`, `FlatProvider` | +1.4 KB |
134
140
  | [`@flattype/vue`](https://github.com/karammm/flattype/blob/main/packages/vue) | The same composables for Vue 3, with reactive URLs, plus the `createFlat()` plugin | +1.2 KB |
135
141
  | [`@flattype/angular`](https://github.com/karammm/flattype/blob/main/packages/angular) | `flatInterceptor` for HttpClient, the signal-based `flatResource` / `flatStream`, the `flatModel` pipe | +1.8 KB |
142
+ | [`@flattype/svelte`](https://github.com/karammm/flattype/blob/main/packages/svelte) | Svelte stores (`flatStore`, `flatStreamStore`, `modelStore`), and `/solid` with `createFlatResource` / `createFlatStream` | +1.1 KB / +0.9 KB |
136
143
  | [`@flattype/shared`](https://github.com/karammm/flattype/blob/main/packages/shared) | Shared TypeScript types | types only |
137
144
 
138
- Svelte bindings, Claude helpers and a CLI are planned. See the [roadmap](https://github.com/karammm/flattype/blob/main/ROADMAP.md).
145
+ Claude helpers and a CLI are planned. See the [roadmap](https://github.com/karammm/flattype/blob/main/ROADMAP.md).
139
146
 
140
147
  ## The format
141
148
 
@@ -381,6 +388,54 @@ export class UsersComponent {
381
388
 
382
389
  Angular 19+ (built with partial compilation, so it works with every later version). A runnable Angular 22 app with Playwright tests in three browsers is in [`examples/angular-app`](https://github.com/karammm/flattype/blob/main/examples/angular-app).
383
390
 
391
+ ## Svelte and Solid
392
+
393
+ ```bash
394
+ npm install @flattype/svelte @flattype/models
395
+ ```
396
+
397
+ **Svelte** (3, 4 and 5). The stores follow the Svelte store contract, so `$store` just works:
398
+
399
+ ```svelte
400
+ <script lang="ts">
401
+ import { createFlat } from "@flattype/svelte";
402
+ import { derived, writable } from "svelte/store";
403
+
404
+ const api = createFlat({ baseURL: "/api", headers: () => ({ authorization: `Bearer ${token}` }) });
405
+
406
+ const users = api.store("/users", { model: User, list: true }); // $users.data: User[] | undefined
407
+ const id = writable(1);
408
+ const user = api.store(derived(id, (i) => `/users/${i}`), { model: User }); // the URL can be a store
409
+ const events = api.streamStore("/export", { model: Row, table: "rows" }); // rows while downloading
410
+ </script>
411
+
412
+ {#each $users.data ?? [] as u (u.id)}<li>{u.fullName}</li>{/each}
413
+ <p>{$events.done ? "Done" : `Loading… ${$events.rows.length}`}</p>
414
+ ```
415
+
416
+ **Solid** (`@flattype/svelte/solid`):
417
+
418
+ ```tsx
419
+ import { createFlatResource, createFlatStream } from "@flattype/svelte/solid";
420
+
421
+ const [user, { refetch }] = createFlatResource(() => `/users/${props.id}`, { baseURL: "/api", model: User });
422
+ const events = createFlatStream(() => "/api/export", { model: Row, table: "rows" });
423
+
424
+ <Suspense fallback={<Spinner />}>
425
+ <Show when={user()}>{(u) => <h2>{u().fullName}</h2>}</Show>
426
+ </Suspense>;
427
+ ```
428
+
429
+ | API | What it does |
430
+ | --- | --- |
431
+ | `flatStore(url, options)` | A store of `{ data, error, loading }` plus `refetch()`. Lazy: it fetches on the first subscriber and aborts when the last one leaves. A URL store change aborts the old request |
432
+ | `flatStreamStore(url, options)` | A store of `{ rows, done, error }` plus `restart()`. One update per network chunk |
433
+ | `modelStore(source, Model)` | Maps another store's value to a model |
434
+ | `createFlatResource(() => url, options)` | A Solid resource, for `<Suspense>` and `<ErrorBoundary>`. Aborts on change and on cleanup |
435
+ | `createFlatStream(() => url, options)` | `rows`, `done` and `error` accessors plus `restart()` |
436
+
437
+ The stores also work in Solid, or anywhere else, through the store contract: `from(flatStore(...))`. Runnable apps with Playwright tests in three browsers are in [`examples/svelte-app`](https://github.com/karammm/flattype/blob/main/examples/svelte-app) and [`examples/solid-app`](https://github.com/karammm/flattype/blob/main/examples/solid-app).
438
+
384
439
  ## Benchmarks
385
440
 
386
441
  `pnpm compare` on the fixtures in [`fixtures/`](https://github.com/karammm/flattype/blob/main/fixtures/index.mjs) (Node 24, Apple Silicon):
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flattype/models",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "Typed models for API data: key mapping, coercion and defaults, from JSON or Flat Notation.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -33,8 +33,8 @@
33
33
  "flattype"
34
34
  ],
35
35
  "dependencies": {
36
- "@flattype/core": "1.5.0",
37
- "@flattype/shared": "1.5.0"
36
+ "@flattype/core": "1.6.0",
37
+ "@flattype/shared": "1.6.0"
38
38
  },
39
39
  "publishConfig": {
40
40
  "access": "public"