@markwasfy/loko 0.1.0 → 0.1.1
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 +57 -51
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,51 +1,57 @@
|
|
|
1
|
-
# loko
|
|
2
|
-
|
|
3
|
-
**Add offline support to any TypeScript app in 5 minutes. Bring your own backend.**
|
|
4
|
-
|
|
5
|
-
Offline storage + sync for SaaS CRUD apps. Framework agnostic. Backend agnostic. Zero dependencies.
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install loko
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
```ts
|
|
12
|
-
import { createSync, indexedDBStorage, restAdapter } from "loko";
|
|
13
|
-
|
|
14
|
-
const sync = createSync({
|
|
15
|
-
name: "myapp",
|
|
16
|
-
storage: indexedDBStorage(),
|
|
17
|
-
adapter: restAdapter({ url: "/api/sync" }),
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
const todos = sync.collection("todos");
|
|
21
|
-
await todos.put({ id: "1", text: "Buy milk", done: false }); // offline-first
|
|
22
|
-
await sync.sync(); // push + pull
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
##
|
|
26
|
-
|
|
27
|
-
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
- `
|
|
34
|
-
- `
|
|
35
|
-
- `
|
|
36
|
-
- `
|
|
37
|
-
- `
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
1
|
+
# loko
|
|
2
|
+
|
|
3
|
+
**Add offline support to any TypeScript app in 5 minutes. Bring your own backend.**
|
|
4
|
+
|
|
5
|
+
Offline storage + sync for SaaS CRUD apps. Framework agnostic. Backend agnostic. Zero dependencies.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @markwasfy/loko
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { createSync, indexedDBStorage, restAdapter } from "@markwasfy/loko";
|
|
13
|
+
|
|
14
|
+
const sync = createSync({
|
|
15
|
+
name: "myapp",
|
|
16
|
+
storage: indexedDBStorage(),
|
|
17
|
+
adapter: restAdapter({ url: "/api/sync" }),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const todos = sync.collection("todos");
|
|
21
|
+
await todos.put({ id: "1", text: "Buy milk", done: false }); // offline-first
|
|
22
|
+
await sync.sync(); // push + pull
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## How it works
|
|
26
|
+
|
|
27
|
+

|
|
28
|
+
|
|
29
|
+
Writes go to local storage first and notify subscribers immediately. `sync()` then pushes dirty records and pulls remote changes from your backend, using server-assigned versions to detect conflicts — all coordinated across tabs.
|
|
30
|
+
|
|
31
|
+
## API
|
|
32
|
+
|
|
33
|
+
- `createSync(config)` → `Sync`
|
|
34
|
+
- `config.storage` — `indexedDBStorage()` (default browser) or `memoryStorage()`
|
|
35
|
+
- `config.adapter` — `restAdapter({ url })` or your own `SyncAdapter` (omit for local-only)
|
|
36
|
+
- `config.conflict` — a `ConflictResolver` (defaults to `lastWriteWins()`)
|
|
37
|
+
- `config.autoSync` — `true` (default) | `false` | interval ms
|
|
38
|
+
- `sync.defineCollection(name, { primaryKey, indexes })` — declare a collection
|
|
39
|
+
- `sync.collection<T>(name)` — `get` · `all` · `put` · `bulkPut` · `delete` · `subscribe` · `subscribeOne`
|
|
40
|
+
- `sync.store(key, value)` / `sync.get(key)` — key→value sugar over the reserved `_kv` collection
|
|
41
|
+
- `sync.sync()` — push local changes, then pull remote changes
|
|
42
|
+
- `sync.status` and `sync.on("change" | "sync" | "status" | "error", cb)`
|
|
43
|
+
- `sync.registerBackgroundSync()` — opt into Service Worker Background Sync
|
|
44
|
+
|
|
45
|
+
## Extension points
|
|
46
|
+
|
|
47
|
+
- **`StorageAdapter`** — `indexedDBStorage()`, `memoryStorage()`, or your own
|
|
48
|
+
- **`SyncAdapter`** — `restAdapter()`, `memoryAdapter()` (in-memory server for tests), or your own
|
|
49
|
+
- **`ConflictResolver`** — `lastWriteWins()` or a custom `(local, remote) => StoredDoc`
|
|
50
|
+
|
|
51
|
+
Conflict **detection** is version-based (server-assigned), never clock-based. Resolution is **per record, not per field**.
|
|
52
|
+
|
|
53
|
+
See the [monorepo README](../../README.md) for the full guide, comparison table, and roadmap.
|
|
54
|
+
|
|
55
|
+
## License
|
|
56
|
+
|
|
57
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markwasfy/loko",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Add offline support to any TypeScript app in 5 minutes. Bring your own backend. Offline storage + sync for SaaS CRUD apps. Framework agnostic. Backend agnostic. Zero dependencies.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|