@sweidos/eidos 1.0.17 → 1.0.20
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 +115 -17
- package/dist/eidos.cjs.js +4 -746
- package/dist/eidos.cjs.js.map +1 -1
- package/dist/eidos.es.js +420 -555
- package/dist/eidos.es.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/query.cjs.js +48 -0
- package/dist/query.d.ts +81 -0
- package/dist/query.js +48 -0
- package/dist/vite.cjs.js +31 -0
- package/dist/vite.d.ts +28 -0
- package/dist/vite.js +31 -0
- package/package.json +30 -4
package/README.md
CHANGED
|
@@ -72,7 +72,7 @@ pnpm add @sweidos/eidos
|
|
|
72
72
|
cp node_modules/@sweidos/eidos/dist/eidos-sw.js public/eidos-sw.js
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
> **Vite users** —
|
|
75
|
+
> **Vite users** — use the [first-class Vite plugin](#vite-plugin) to automate this.
|
|
76
76
|
|
|
77
77
|
### 3. Wrap your app
|
|
78
78
|
|
|
@@ -115,7 +115,16 @@ export const createOrder = action(
|
|
|
115
115
|
### 5. Use in components
|
|
116
116
|
|
|
117
117
|
```tsx
|
|
118
|
-
// TanStack Query
|
|
118
|
+
// TanStack Query — first-class hooks
|
|
119
|
+
import { useEidosQuery, useEidosMutation } from '@sweidos/eidos/query'
|
|
120
|
+
|
|
121
|
+
const { data, isPending } = useEidosQuery<Product[]>(products)
|
|
122
|
+
|
|
123
|
+
const mutation = useEidosMutation(createOrder, {
|
|
124
|
+
invalidates: [products], // clears cache + refetches on success
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
// Or with plain useQuery
|
|
119
128
|
const { data } = useQuery(products.query<Product[]>())
|
|
120
129
|
|
|
121
130
|
// Or plain async
|
|
@@ -499,26 +508,96 @@ eidos/
|
|
|
499
508
|
|
|
500
509
|
## Vite Plugin
|
|
501
510
|
|
|
502
|
-
|
|
511
|
+
`@sweidos/eidos` ships a first-class Vite plugin via the `@sweidos/eidos/vite` subpath. It automatically copies `eidos-sw.js` from the installed package into your `public/` directory on every build and dev-server start — keeping the SW in sync with the installed version.
|
|
503
512
|
|
|
504
513
|
```ts
|
|
505
514
|
// vite.config.ts
|
|
506
|
-
import {
|
|
507
|
-
import {
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
515
|
+
import { eidos } from '@sweidos/eidos/vite'
|
|
516
|
+
import { defineConfig } from 'vite'
|
|
517
|
+
|
|
518
|
+
export default defineConfig({
|
|
519
|
+
plugins: [eidos()],
|
|
520
|
+
})
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
**Options:**
|
|
524
|
+
|
|
525
|
+
```ts
|
|
526
|
+
eidos({
|
|
527
|
+
swDest: 'public/eidos-sw.js', // default — relative to project root
|
|
528
|
+
})
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
No more manual `cp` step. The plugin runs on `buildStart` (prod builds) and `configureServer` (dev).
|
|
532
|
+
|
|
533
|
+
---
|
|
534
|
+
|
|
535
|
+
## TanStack Query Integration
|
|
536
|
+
|
|
537
|
+
`@sweidos/eidos/query` provides first-class hooks for [TanStack Query v5](https://tanstack.com/query/latest). Requires `@tanstack/react-query` — already optional in Eidos, just install it.
|
|
538
|
+
|
|
539
|
+
### Setup (once)
|
|
540
|
+
|
|
541
|
+
```ts
|
|
542
|
+
// main.tsx
|
|
543
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|
544
|
+
import { withEidosQueryClient } from '@sweidos/eidos/query'
|
|
545
|
+
|
|
546
|
+
const queryClient = new QueryClient()
|
|
547
|
+
withEidosQueryClient(queryClient) // bridges handle.invalidate() → TQ cache
|
|
548
|
+
|
|
549
|
+
root.render(
|
|
550
|
+
<QueryClientProvider client={queryClient}>
|
|
551
|
+
<EidosProvider swPath="/eidos-sw.js">
|
|
552
|
+
<App />
|
|
553
|
+
</EidosProvider>
|
|
554
|
+
</QueryClientProvider>
|
|
555
|
+
)
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
### `useEidosQuery(handle, options?)`
|
|
559
|
+
|
|
560
|
+
Wraps `useQuery` with Eidos-smart defaults:
|
|
561
|
+
- `networkMode: 'always'` — Eidos owns offline; queries run even when `navigator.onLine` is false
|
|
562
|
+
- `retry: false` — Eidos handles retries at the SW/replay layer
|
|
563
|
+
|
|
564
|
+
```tsx
|
|
565
|
+
import { useEidosQuery } from '@sweidos/eidos/query'
|
|
566
|
+
|
|
567
|
+
function ProductList() {
|
|
568
|
+
const { data, isPending, isError } = useEidosQuery<Product[]>(products)
|
|
569
|
+
// ...
|
|
570
|
+
}
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
### `useEidosMutation(handle, options?)`
|
|
574
|
+
|
|
575
|
+
Wraps `useMutation` for a single-argument action handle:
|
|
576
|
+
- `networkMode: 'always'` — action queues offline automatically
|
|
577
|
+
- `invalidates` — clears Eidos cache + invalidates TQ entries on success
|
|
578
|
+
|
|
579
|
+
```tsx
|
|
580
|
+
import { useEidosMutation } from '@sweidos/eidos/query'
|
|
581
|
+
|
|
582
|
+
function OrderForm() {
|
|
583
|
+
const mutation = useEidosMutation(createOrder, {
|
|
584
|
+
invalidates: [products], // refetch product list after order
|
|
585
|
+
onSuccess(data) {
|
|
586
|
+
if ('queued' in data) toast('Saved offline — will sync when back online')
|
|
587
|
+
else toast(`Order #${data.id} created!`)
|
|
517
588
|
},
|
|
518
|
-
}
|
|
589
|
+
})
|
|
590
|
+
|
|
591
|
+
return <button onClick={() => mutation.mutate({ productId: 1, qty: 2 })}>Buy</button>
|
|
519
592
|
}
|
|
520
593
|
```
|
|
521
594
|
|
|
595
|
+
### `withEidosQueryClient(client)`
|
|
596
|
+
|
|
597
|
+
Registers a `QueryClient` with Eidos. After calling this:
|
|
598
|
+
- `handle.invalidate()` also calls `queryClient.invalidateQueries({ queryKey: ['eidos', url] })`
|
|
599
|
+
- Both systems stay in sync automatically, even when cache is cleared outside of mutations
|
|
600
|
+
|
|
522
601
|
---
|
|
523
602
|
|
|
524
603
|
## Known Limitations
|
|
@@ -529,6 +608,7 @@ function eidosPlugin() {
|
|
|
529
608
|
| Query string ignored | Resources match by pathname (or full URL for cross-origin). `/api/products?page=2` and `/api/products` share the same SW rule but are cached as separate entries. |
|
|
530
609
|
| Module-scope actions | `action()` must be called at module scope so functions are registered before a page reload triggers queue replay. |
|
|
531
610
|
| Single SW | `EidosProvider` assumes one SW at `/eidos-sw.js`. Multiple registrations are unsupported. |
|
|
611
|
+
| React in main bundle | The published ESM bundle is a single file — consumers who import `resource()` or `eidosStore` (no React) still pull in the `react` import declaration. Since `react` is an optional peer dep, bundlers handle it correctly (import is skipped if unused), but Vue/Svelte projects should ensure `react` is available as a dep. A future `preserveModules` refactor will fix this properly. |
|
|
532
612
|
|
|
533
613
|
---
|
|
534
614
|
|
|
@@ -541,9 +621,27 @@ function eidosPlugin() {
|
|
|
541
621
|
- [x] URL pattern matching (`*`, `**`, `:param`)
|
|
542
622
|
- [x] Cross-origin resource support
|
|
543
623
|
- [x] Background Sync API integration
|
|
544
|
-
- [
|
|
624
|
+
- [x] Vite plugin (`@sweidos/eidos/vite` subpath — ships in the main package)
|
|
545
625
|
- [x] Vue / Svelte bindings (framework-agnostic reactive stores)
|
|
546
|
-
- [
|
|
626
|
+
- [x] TanStack Query integration (`@sweidos/eidos/query` subpath — `useEidosQuery`, `useEidosMutation`, `withEidosQueryClient`)
|
|
627
|
+
|
|
628
|
+
**Core reliability**
|
|
629
|
+
- [ ] Optimistic updates — `onOptimistic` / `onRollback` callbacks on `action()` for instant UI feedback before server confirms
|
|
630
|
+
- [ ] Conflict resolution hook — `onConflict` callback when replaying a queued action returns 4xx; decide per-item: retry, skip, or merge
|
|
631
|
+
- [ ] Queue prioritization — `priority: 'high' | 'normal' | 'low'` on `action()`; high-priority items replay first
|
|
632
|
+
|
|
633
|
+
**DX / Tooling**
|
|
634
|
+
- [ ] Devtools panel component — drop-in `<EidosDevtools />` showing cache entries, queue state, replay status, and offline toggle
|
|
635
|
+
- [ ] Testing utilities (`@sweidos/eidos/testing`) — `mockOffline()`, `drainQueue()`, `getCachedEntry(url)` for Vitest / Playwright
|
|
636
|
+
- [ ] SvelteKit / Next.js adapters — SSR-aware init helpers that skip SW registration server-side
|
|
637
|
+
|
|
638
|
+
**Performance**
|
|
639
|
+
- [ ] Request deduplication — multiple simultaneous `resource.fetch()` calls share one in-flight network request
|
|
640
|
+
- [ ] Cache warming — `warmCache(handles[])` bulk-prefetches a list of resources on init (e.g. on login)
|
|
641
|
+
|
|
642
|
+
**Ecosystem**
|
|
643
|
+
- [ ] React Native support — AsyncStorage + fetch-based backend (no Cache API / SW); same `resource` / `action` API surface
|
|
644
|
+
- [ ] OpenAPI codegen CLI — `npx eidos-gen ./openapi.json` generates typed `resource()` and `action()` declarations
|
|
547
645
|
|
|
548
646
|
---
|
|
549
647
|
|