@storion/storion 1.0.0 → 1.0.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.
Files changed (2) hide show
  1. package/README.md +137 -75
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,17 +1,43 @@
1
- # storion
1
+ # Storion
2
2
 
3
- Framework-agnostic client-side database for the browser. Use it with **React**, **Vue**, **Angular**, or vanilla JS. No framework-specific code—just create databases, tables, save/fetch records, and run JSON queries on **localStorage**, **sessionStorage**, or **IndexedDB**.
3
+ **Framework-agnostic client-side database for the browser.** Use it with React, Vue, Angular, Svelte, or vanilla JS. Create databases, tables, save and fetch records, and run JSON queries on **localStorage**, **sessionStorage**, or **IndexedDB**.
4
+
5
+ [![npm](https://img.shields.io/npm/v/@storion/storion.svg)](https://www.npmjs.com/package/@storion/storion)
6
+ [![GitHub](https://img.shields.io/badge/GitHub-storionjs%2Fstorion-blue?logo=github)](https://github.com/storionjs/storion)
7
+
8
+ ---
9
+
10
+ ## Table of contents
11
+
12
+ - [Features](#features)
13
+ - [Install](#install)
14
+ - [Quick start](#quick-start)
15
+ - [Documentation](#documentation)
16
+ - [Database from config](#database-from-config)
17
+ - [Query language](#query-language)
18
+ - [Subscribing to changes](#subscribing-to-changes)
19
+ - [Cross-context sync (e.g. extensions)](#cross-context-sync-eg-extensions)
20
+ - [Storage backends](#storage-backends)
21
+ - [Usage with React / Vue / Angular](#usage-with-react--vue--angular)
22
+ - [API reference](#api-reference)
23
+ - [Links](#links)
24
+
25
+ ---
4
26
 
5
27
  ## Features
6
28
 
7
- - **Framework-agnostic** Works with any frontend (React, Vue, Angular, Svelte, etc.)
8
- - **Multiple stores** – Create databases in `localStorage`, `sessionStorage`, or `indexedDB`
9
- - **Tables** Define tables with columns (int, float, boolean, string) and optional foreign keys
10
- - **CRUD** Insert, fetch, update, and delete records
11
- - **Query engine** Run JSON queries (where, orderBy, limit, offset) directly on tables
12
- - **Config from file** Create a database from a config object or load config from a URL/file
13
- - **Change subscription** Subscribe to table or row changes so multiple components stay in sync when data is updated (no polling)
14
- - **Cross-context ready** Optional broadcaster + listener helpers so an extension, background script, or another tab can stream change events to your UI
29
+ | Feature | Description |
30
+ |--------|-------------|
31
+ | **Framework-agnostic** | Works with any frontend; no framework-specific code. |
32
+ | **Multiple stores** | Use `localStorage`, `sessionStorage`, or `indexedDB`. |
33
+ | **Tables & schema** | Define tables with columns (int, float, boolean, string, json) and optional foreign keys. |
34
+ | **CRUD** | Insert, fetch, update, and delete records with a simple API. |
35
+ | **Query engine** | Run JSON queries: `where`, `orderBy`, `limit`, `offset`. |
36
+ | **Config from file/URL** | Create a database from a config object or load config from a URL or file. |
37
+ | **Change subscription** | Subscribe to table or row changes so components stay in sync without polling. |
38
+ | **Cross-context** | Optional broadcaster + listener for extensions, background scripts, or multiple tabs. |
39
+
40
+ ---
15
41
 
16
42
  ## Install
17
43
 
@@ -19,12 +45,17 @@ Framework-agnostic client-side database for the browser. Use it with **React**,
19
45
  npm install @storion/storion
20
46
  ```
21
47
 
48
+ - **npm:** [https://www.npmjs.com/package/@storion/storion](https://www.npmjs.com/package/@storion/storion)
49
+ - **Source & issues:** [https://github.com/storionjs/storion](https://github.com/storionjs/storion)
50
+
51
+ ---
52
+
22
53
  ## Quick start
23
54
 
24
55
  ```js
25
56
  import { createDatabase } from '@storion/storion';
26
57
 
27
- // Create a database in localStorage (or sessionStorage / indexedDB)
58
+ // Create a database (localStorage, sessionStorage, or indexedDB)
28
59
  const db = await createDatabase({
29
60
  name: 'myapp',
30
61
  storage: 'localStorage'
@@ -59,13 +90,27 @@ await db.update('users', 1, { name: 'Alice Smith' });
59
90
  await db.delete('users', 2);
60
91
  ```
61
92
 
62
- ## Create database from config
93
+ ---
94
+
95
+ ## Documentation
96
+
97
+ | Document | Description |
98
+ |----------|-------------|
99
+ | [**API reference**](docs/API.md) | Full API for `createDatabase`, `Database` methods, and helpers. |
100
+ | [**Config format**](docs/CONFIG_FORMAT.md) | How to define tables and databases in a config object or JSON file. |
101
+ | [**Query language**](docs/QUERY_LANGUAGE.md) | `where`, `orderBy`, operators, and examples. |
102
+
103
+ ---
104
+
105
+ ## Database from config
63
106
 
64
107
  You can create a database and its tables from a **config object** (e.g. from a JSON file).
65
108
 
66
109
  ### Config in code
67
110
 
68
111
  ```js
112
+ import { createDatabase } from '@storion/storion';
113
+
69
114
  const config = {
70
115
  tables: {
71
116
  users: {
@@ -120,19 +165,21 @@ const db = await createDatabase({
120
165
  });
121
166
  ```
122
167
 
123
- Config format and options are described in [docs/CONFIG_FORMAT.md](docs/CONFIG_FORMAT.md).
168
+ See [Config format](docs/CONFIG_FORMAT.md) for the full schema and options.
124
169
 
125
- ## Query language
170
+ ---
126
171
 
127
- Use `db.query(tableName, query)` with a JSON query:
172
+ ## Query language
128
173
 
129
- - **where** – Filter: `{ field, op, value }` or `{ and: [...] }` / `{ or: [...] }`
130
- - **orderBy** – Sort: `[{ field, direction: 'asc' | 'desc' }]`
131
- - **limit** / **offset** – Pagination
174
+ Use `db.query(tableName, query)` with a JSON query object:
132
175
 
133
- Operators: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `contains`, `startsWith`, `endsWith`, `in`, `notIn`, `isNull`, `isNotNull`.
176
+ | Key | Description |
177
+ |-----|-------------|
178
+ | **where** | Filter: `{ field, op, value }` or `{ and: [...] }` / `{ or: [...] }`. |
179
+ | **orderBy** | Sort: `[{ field, direction: 'asc' \| 'desc' }]`. |
180
+ | **limit** / **offset** | Pagination. |
134
181
 
135
- Example:
182
+ **Operators:** `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `contains`, `startsWith`, `endsWith`, `in`, `notIn`, `isNull`, `isNotNull`.
136
183
 
137
184
  ```js
138
185
  const { rows, totalCount } = await db.query('users', {
@@ -148,11 +195,13 @@ const { rows, totalCount } = await db.query('users', {
148
195
  });
149
196
  ```
150
197
 
151
- Full reference: [docs/QUERY_LANGUAGE.md](docs/QUERY_LANGUAGE.md).
198
+ Full reference: [Query language](docs/QUERY_LANGUAGE.md).
199
+
200
+ ---
152
201
 
153
202
  ## Subscribing to changes
154
203
 
155
- When multiple components share the same `Database` instance, they can subscribe to change events so that when one component inserts, updates, or deletes data, the others receive an event and can refresh or react—without polling.
204
+ When multiple components share the same `Database` instance, they can subscribe to change events so that when one component inserts, updates, or deletes data, the others receive an event and can refresh—without polling.
156
205
 
157
206
  ```js
158
207
  const db = await createDatabase({ name: 'myapp', storage: 'localStorage' });
@@ -163,99 +212,79 @@ const unsubscribe = db.subscribe('todos', (event) => {
163
212
  // Refresh your UI or state here
164
213
  });
165
214
 
166
- // Or subscribe to all tables: db.subscribe((event) => { ... })
167
- // Or subscribe to one row: db.subscribe('todos', 1, (event) => { ... })
215
+ // Subscribe to all tables: db.subscribe((event) => { ... })
216
+ // Subscribe to one row: db.subscribe('todos', 1, (event) => { ... })
168
217
 
169
- // When done: unsubscribe();
218
+ // When done:
219
+ unsubscribe();
170
220
  ```
171
221
 
172
- Every matching subscriber receives the event (multiple components can subscribe to the same table or row). If no one subscribes, the database behaves as before. Full details: [docs/API.md#dbsubscribe](docs/API.md).
222
+ See [API db.subscribe](docs/API.md) for details.
223
+
224
+ ---
173
225
 
174
- ## Cross-context sync (extension ↔ webapp)
226
+ ## Cross-context sync (e.g. extensions)
175
227
 
176
- Storion can also be used as the **source of truth in one context** (e.g. a Chrome extension or background script) and stream change events to another context (e.g. a webapp UI) using a broadcaster + listener pattern.
228
+ Use Storion in one context (e.g. Chrome extension or background script) and stream change events to another (e.g. web app UI) with a broadcaster + listener.
177
229
 
178
230
  ```js
179
231
  import { createDatabase, createChangeListener } from '@storion/storion';
180
232
 
181
- // 1) Producer side (e.g. extension popup/background)
233
+ // 1) Producer (e.g. extension popup/background)
182
234
  const db = await createDatabase({ name: 'myapp', storage: 'localStorage' });
183
235
 
184
- // Forward normalized StorionChangeEvent payloads to the active tab.
185
236
  db.setChangeBroadcaster({
186
237
  async broadcastChange(event) {
187
- if (typeof chrome !== 'undefined' && chrome.tabs && chrome.tabs.query) {
188
- // Chrome extension context: send to the active tab's content script
238
+ if (typeof chrome !== 'undefined' && chrome.tabs?.query) {
189
239
  chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
190
- const tab = tabs && tabs[0];
191
- if (!tab || !tab.id) return;
192
- chrome.tabs.sendMessage(tab.id, { action: 'storionChangeEvent', event });
240
+ const tab = tabs?.[0];
241
+ if (tab?.id) chrome.tabs.sendMessage(tab.id, { action: 'storionChangeEvent', event });
193
242
  });
194
243
  } else {
195
- // Fallback: same-window postMessage (e.g. two iframes or tabs using BroadcastChannel)
196
244
  window.postMessage({ source: 'storion-change', payload: event }, '*');
197
245
  }
198
246
  }
199
247
  });
200
248
 
201
- // 2) Consumer side (e.g. webapp page or another tab)
249
+ // 2) Consumer (e.g. web app or another tab)
202
250
  const transport = {
203
251
  onMessage(handler) {
204
- function listener(ev) {
205
- if (!ev.data || ev.data.source !== 'storion-change') return;
252
+ const listener = (ev) => {
253
+ if (ev.data?.source !== 'storion-change') return;
206
254
  handler(ev.data.payload);
207
- }
255
+ };
208
256
  window.addEventListener('message', listener);
209
257
  return () => window.removeEventListener('message', listener);
210
258
  }
211
259
  };
212
260
 
213
261
  const stop = createChangeListener(transport, (event) => {
214
- // React to inserts/updates/deletes coming from another context
215
262
  console.log('Cross-context change:', event.type, event.tableName, event.row);
216
263
  });
217
-
218
- // later, when you no longer need updates:
219
- // stop();
264
+ // Later: stop();
220
265
  ```
221
266
 
222
- The same `StorionChangeEvent` payload is delivered to **local subscribers** and to the **broadcaster**, and `createChangeListener` normalizes incoming messages on the receiving side. See [docs/API.md#createChangeListenertransport-onchange](docs/API.md) for details and Chrome-extension-specific wiring in the Storion Studio README.
267
+ See [API createChangeListener](docs/API.md) and [API — setChangeBroadcaster](docs/API.md) for details.
223
268
 
224
- ## API overview
225
-
226
- | Method | Description |
227
- |--------|-------------|
228
- | `createDatabase(options)` | Create or connect to a DB (name, storage, optional config). |
229
- | `loadConfigFromUrl(url)` | Fetch config JSON from a URL. |
230
- | `loadConfigFromFile(file)` | Read config from a File (e.g. file input). |
231
- | `db.createTable(name, columns)` | Create a table. |
232
- | `db.listTables()` | List table names. |
233
- | `db.getTable(name)` | Get table structure and rows. |
234
- | `db.insert(table, row)` | Insert a row (id auto if omitted). |
235
- | `db.fetch(table, options?)` | Fetch rows (optional filter, sort, limit). |
236
- | `db.query(table, query)` | Run JSON query; returns `{ rows, totalCount }`. |
237
- | `db.update(table, id, data)` | Update a row by id. |
238
- | `db.delete(table, id)` | Delete a row by id. |
239
- | `db.deleteTable(name)` | Delete a table. |
240
- | `db.exportConfig()` | Export DB as config-like object. |
241
- | `db.subscribe(callback)` / `db.subscribe(table, callback)` / `db.subscribe(table, rowId, callback)` | Subscribe to change events; returns `unsubscribe()`. |
242
- | `db.unsubscribe(id)` | Remove a subscription by id. |
243
- | `db.setChangeBroadcaster(broadcaster)` | Optional: broadcast changes to another context (e.g. extension ↔ page). |
244
- | `createChangeListener(transport, onChange)` | Listen for change events coming from another context via a custom transport. |
245
-
246
- Full API: [docs/API.md](docs/API.md).
269
+ ---
247
270
 
248
271
  ## Storage backends
249
272
 
250
- - **localStorage** Persists across sessions; same origin; ~5MB typical.
251
- - **sessionStorage** – Cleared when the tab/window closes; same origin.
252
- - **indexedDB** Async; larger quota; good for bigger datasets.
273
+ | Backend | Description |
274
+ |---------|-------------|
275
+ | **localStorage** | Persists across sessions; same origin; ~5MB typical. |
276
+ | **sessionStorage** | Cleared when the tab/window closes; same origin. |
277
+ | **indexedDB** | Async; larger quota; good for bigger datasets. |
253
278
 
254
279
  All data for a given storage key is stored in one place (default key: `__LS_DB__`). Multiple logical databases (different `name`s) can coexist under the same key.
255
280
 
281
+ ---
282
+
256
283
  ## Usage with React / Vue / Angular
257
284
 
258
- Use the same API in any framework. Share one `Database` instance (e.g. via context, service, or singleton) so that `db.subscribe()` keeps all components in sync when data changes. Example with React:
285
+ Use the same API in any framework. Share one `Database` instance (e.g. via context, service, or singleton) so `db.subscribe()` keeps all components in sync.
286
+
287
+ **Example with React:**
259
288
 
260
289
  ```js
261
290
  import { createDatabase } from '@storion/storion';
@@ -290,8 +319,41 @@ function UserList() {
290
319
  }
291
320
  ```
292
321
 
293
- No framework-specific bindings—just call the async API and set state as needed.
322
+ No framework-specific bindings—call the async API and set state as needed.
323
+
324
+ ---
325
+
326
+ ## API reference
327
+
328
+ | Method / API | Description |
329
+ |--------------|-------------|
330
+ | `createDatabase(options)` | Create or connect to a DB (name, storage, optional config). |
331
+ | `loadConfigFromUrl(url)` | Fetch config JSON from a URL. |
332
+ | `loadConfigFromFile(file)` | Read config from a `File` (e.g. file input). |
333
+ | `db.createTable(name, columns)` | Create a table. |
334
+ | `db.listTables()` | List table names. |
335
+ | `db.getTable(name)` | Get table structure and rows. |
336
+ | `db.insert(table, row)` | Insert a row (id auto if omitted). |
337
+ | `db.fetch(table, options?)` | Fetch rows (optional filter, sort, limit). |
338
+ | `db.query(table, query)` | Run JSON query; returns `{ rows, totalCount }`. |
339
+ | `db.update(table, id, data)` | Update a row by id. |
340
+ | `db.delete(table, id)` | Delete a row by id. |
341
+ | `db.deleteTable(name)` | Delete a table. |
342
+ | `db.exportConfig()` | Export DB as config-like object. |
343
+ | `db.subscribe(callback)` / `db.subscribe(table, callback)` / `db.subscribe(table, rowId, callback)` | Subscribe to change events; returns `unsubscribe()`. |
344
+ | `db.unsubscribe(id)` | Remove a subscription by id. |
345
+ | `db.setChangeBroadcaster(broadcaster)` | Optional: broadcast changes to another context. |
346
+ | `createChangeListener(transport, onChange)` | Listen for change events from another context via a custom transport. |
347
+
348
+ Full details: [API reference](docs/API.md).
349
+
350
+ ---
294
351
 
295
- ## License
352
+ ## Links
296
353
 
297
- MIT
354
+ | Resource | URL |
355
+ |----------|-----|
356
+ | **GitHub** | [https://github.com/storionjs/storion](https://github.com/storionjs/storion) |
357
+ | **npm** | [https://www.npmjs.com/package/@storion/storion](https://www.npmjs.com/package/@storion/storion) |
358
+ | **Issues** | [https://github.com/storionjs/storion/issues](https://github.com/storionjs/storion/issues) |
359
+ | **License** | MIT |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storion/storion",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Framework-agnostic client-side database with localStorage, sessionStorage, and IndexedDB. Create databases, tables, save/fetch records, and run JSON queries.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",