nodestack-client 1.2.0 â 2.0.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.
- package/README.md +120 -7
- package/dist/Client.d.ts +12 -0
- package/dist/Client.d.ts.map +1 -1
- package/dist/auth/BaseAuthStore.d.ts.map +1 -1
- package/dist/auth/LocalAuthStore.d.ts.map +1 -1
- package/dist/errors/ClientResponseError.d.ts.map +1 -1
- package/dist/index.cjs +315 -4
- package/dist/index.cjs.map +3 -3
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +322 -4
- package/dist/index.mjs.map +3 -3
- package/dist/services/AdminService.d.ts.map +1 -1
- package/dist/services/AppService.d.ts +30 -0
- package/dist/services/AppService.d.ts.map +1 -0
- package/dist/services/BaseService.d.ts +1 -0
- package/dist/services/BaseService.d.ts.map +1 -1
- package/dist/services/CollectionService.d.ts +2 -0
- package/dist/services/CollectionService.d.ts.map +1 -1
- package/dist/services/DemoService.d.ts.map +1 -1
- package/dist/services/FileService.d.ts +1 -0
- package/dist/services/FileService.d.ts.map +1 -1
- package/dist/services/RealtimeService.d.ts.map +1 -1
- package/dist/services/RecordService.d.ts.map +1 -1
- package/dist/services/SnapshotService.d.ts +38 -0
- package/dist/services/SnapshotService.d.ts.map +1 -0
- package/dist/services/WebhookService.d.ts +72 -0
- package/dist/services/WebhookService.d.ts.map +1 -0
- package/dist/types.d.ts +151 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
# ð nodestack-client
|
|
2
2
|
|
|
3
|
-
> **The Official Lightweight, Type-Safe JavaScript & TypeScript Client SDK for [NodeStack](https://github.com/satya-jugran/
|
|
3
|
+
> **The Official Lightweight, Type-Safe JavaScript & TypeScript Client SDK for [NodeStack](https://github.com/satya-jugran/nodestack)**
|
|
4
4
|
>
|
|
5
5
|
> Published on npm: [`nodestack-client`](https://www.npmjs.com/package/nodestack-client)
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/nodestack-client)
|
|
8
|
-
[](https://www.typescriptlang.org/)
|
|
9
9
|
[](https://opensource.org/licenses/MIT)
|
|
10
10
|
|
|
11
11
|
A zero-dependency, isomorphic JavaScript and TypeScript client for NodeStack with out-of-the-box support for:
|
|
12
12
|
- ⥠**Zero runtime dependencies**: Built purely on standard Web APIs (`fetch`, `FormData`, `AbortController`, `EventSource`).
|
|
13
13
|
- ðŠķ **Ultra-lightweight footprint**: `< 10 KB` minified + gzipped.
|
|
14
|
+
- ðĒ **Multi-Application & App Scoping (v2.0)**: Fluent `client.app(slug)` scoping with automatic `x-nodestack-app` header injection, scoped SSE streams, and administrative `client.apps` management.
|
|
14
15
|
- ð **Pluggable & Reactive Auth**: `LocalAuthStore` (localStorage), `MemoryAuthStore` (Node/SSR/testing), and reactive `onChange` state subscriptions.
|
|
15
16
|
- ðĶ **Fluent Record CRUD & Batch Pagination**: `getList`, `getFullList`, `getFirstListItem`, `create`, `update`, `delete`, `export`, and `import`.
|
|
17
|
+
- ð **SQLite FTS5 Full-Text Search**: Embedded BM25 relevance ranking, keyword prefix matching, and contextual snippet highlighting.
|
|
18
|
+
- ð **Outbound Webhooks Service**: Programmatic webhook registration, test dispatch, delivery inspection, and HMAC-SHA256 signature verification (`client.webhooks`).
|
|
16
19
|
- ð **File Uploads & Protected File URLs**: Seamless `FormData` file uploads and URL generation with automatic token appending.
|
|
17
20
|
- ðĄ **Multiplexed Realtime SSE**: Single persistent connection with auto-handshake (`NS_CONNECT`), dynamic subscription sync, and automatic reconnection.
|
|
18
21
|
- ðŊ **100% Type Safety**: Works seamlessly with `nodestack typegen` and `GET /api/types.d.ts` for autocompleted collection names and typed record returns.
|
|
19
|
-
- ð **Isomorphic**: Modern Browsers, React / Next.js (SSR + Client), Vue, Svelte, Node.js (
|
|
22
|
+
- ð **Isomorphic**: Modern Browsers, React / Next.js (SSR + Client), Vue, Svelte, Node.js (20+ / 22+ / 24+), Bun, Deno, and React Native.
|
|
20
23
|
|
|
21
24
|
---
|
|
22
25
|
|
|
@@ -97,6 +100,63 @@ const serverClient = new NodeStackClient('http://127.0.0.1:8090', {
|
|
|
97
100
|
|
|
98
101
|
---
|
|
99
102
|
|
|
103
|
+
## ðĒ Multi-Application & App Scoping (v2.0)
|
|
104
|
+
|
|
105
|
+
NodeStack v2.0 supports hosting multiple isolated applications on a single backend instance. `nodestack-client` makes targeting and managing applications seamless:
|
|
106
|
+
|
|
107
|
+
### 1. Scoped Client Instances (`client.app`)
|
|
108
|
+
Call `client.app(slug)` to create a scoped client. It shares the same connection config and auth store (or a custom one) while automatically scoping all requests:
|
|
109
|
+
- Automatically injects `x-nodestack-app: slug` on all collection requests.
|
|
110
|
+
- Scopes Realtime SSE streams (`/api/realtime?app=slug`).
|
|
111
|
+
- Generates scoped file URLs (`/api/apps/:appId/files/...`).
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
const client = new NodeStackClient('http://127.0.0.1:8090');
|
|
115
|
+
|
|
116
|
+
// Scope to the 'ecommerce' application
|
|
117
|
+
const shopClient = client.app('ecommerce');
|
|
118
|
+
|
|
119
|
+
// All queries now operate within 'ecommerce' SQLite database
|
|
120
|
+
const products = await shopClient.collection('products').getList(1, 20);
|
|
121
|
+
|
|
122
|
+
// File URLs automatically point to the app-scoped file route:
|
|
123
|
+
// http://127.0.0.1:8090/api/apps/ecommerce/files/products/rec_123/image.png
|
|
124
|
+
const imgUrl = shopClient.files.getUrl(products.items[0], products.items[0].cover);
|
|
125
|
+
|
|
126
|
+
// Realtime SSE scoped to 'ecommerce'
|
|
127
|
+
shopClient.collection('orders').subscribe('*', (e) => {
|
|
128
|
+
console.log('New shop order:', e.record);
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### 2. Multi-App Management Service (`client.apps`)
|
|
133
|
+
Administrative scripts or superusers can provision, inspect, and delete applications programmatically:
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
// Authenticate as superuser
|
|
137
|
+
await client.admins.authWithPassword('admin@nodestack.io', 'AdminPass123!');
|
|
138
|
+
|
|
139
|
+
// List hosted applications
|
|
140
|
+
const apps = await client.apps.getList(1, 50);
|
|
141
|
+
|
|
142
|
+
// Create a new app from a starter template ('saas' | 'blog' | 'ecommerce' | 'blank')
|
|
143
|
+
const newApp = await client.apps.create({
|
|
144
|
+
name: 'Analytics Dashboard',
|
|
145
|
+
slug: 'analytics',
|
|
146
|
+
template: 'saas',
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// Update app details
|
|
150
|
+
await client.apps.update(newApp.id, {
|
|
151
|
+
name: 'Analytics Production',
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// Delete an application (deletes its SQLite DB & uploaded files)
|
|
155
|
+
await client.apps.delete(newApp.id);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
100
160
|
## ð Record Operations (CRUD)
|
|
101
161
|
|
|
102
162
|
### 1. Fetch Paginated Records (`getList`)
|
|
@@ -110,7 +170,21 @@ const result = await client.collection('posts').getList(1, 10, {
|
|
|
110
170
|
console.log(result.page, result.totalPages, result.items);
|
|
111
171
|
```
|
|
112
172
|
|
|
113
|
-
### 2.
|
|
173
|
+
### 2. Full-Text Search with BM25 Scoring & Snippets (`search`)
|
|
174
|
+
Query records using embedded SQLite FTS5 with BM25 relevance ranking and keyword highlight snippets:
|
|
175
|
+
```typescript
|
|
176
|
+
const searchResults = await client.collection('posts').getList(1, 10, {
|
|
177
|
+
search: 'distributed systems',
|
|
178
|
+
snippetTag: 'mark', // Highlight tag (default: <mark>)
|
|
179
|
+
snippetLength: 25, // Max words per snippet excerpt
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
console.log(searchResults.items[0]._score); // BM25 relevance score
|
|
183
|
+
console.log(searchResults.items[0]._snippet); // Best matching snippet excerpt
|
|
184
|
+
console.log(searchResults.items[0]._snippets); // Per-field snippet map: { title: "...", content: "..." }
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### 3. Fetch All Records Across Pages (`getFullList`)
|
|
114
188
|
Auto-paginates in batches and returns all matching records as a single array:
|
|
115
189
|
```typescript
|
|
116
190
|
const allPosts = await client.collection('posts').getFullList({
|
|
@@ -119,13 +193,13 @@ const allPosts = await client.collection('posts').getFullList({
|
|
|
119
193
|
});
|
|
120
194
|
```
|
|
121
195
|
|
|
122
|
-
###
|
|
196
|
+
### 4. Find First Matching Record (`getFirstListItem`)
|
|
123
197
|
```typescript
|
|
124
198
|
// Throws ClientResponseError(404) if no match is found
|
|
125
199
|
const post = await client.collection('posts').getFirstListItem("slug = 'hello-world'");
|
|
126
200
|
```
|
|
127
201
|
|
|
128
|
-
###
|
|
202
|
+
### 5. Create Record (JSON or File Uploads)
|
|
129
203
|
```typescript
|
|
130
204
|
// Plain JSON
|
|
131
205
|
const newPost = await client.collection('posts').create({
|
|
@@ -141,7 +215,7 @@ formData.append('coverImage', fileInput.files[0]);
|
|
|
141
215
|
const postWithImage = await client.collection('posts').create(formData);
|
|
142
216
|
```
|
|
143
217
|
|
|
144
|
-
###
|
|
218
|
+
### 6. Update & Delete Records
|
|
145
219
|
```typescript
|
|
146
220
|
// Update
|
|
147
221
|
const updated = await client.collection('posts').update('rec_123', {
|
|
@@ -280,6 +354,45 @@ client.setChaos(null);
|
|
|
280
354
|
|
|
281
355
|
---
|
|
282
356
|
|
|
357
|
+
## ð Outbound Webhooks Management & Signature Verification
|
|
358
|
+
|
|
359
|
+
Manage outbound webhook subscriptions, inspect delivery logs, and cryptographically verify incoming webhook payloads:
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
// 1. Create a webhook subscription
|
|
363
|
+
const webhook = await client.webhooks.create({
|
|
364
|
+
name: 'Slack Order Dispatcher',
|
|
365
|
+
url: 'https://api.myapp.com/webhooks/orders',
|
|
366
|
+
collection: 'orders',
|
|
367
|
+
action: 'create', // 'create' | 'update' | 'delete' | '*'
|
|
368
|
+
secret: 'whsec_9948a8cf38b1e42c',
|
|
369
|
+
enabled: true,
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
// 2. Dispatch an instant test payload
|
|
373
|
+
await client.webhooks.test(webhook.id, { test: true });
|
|
374
|
+
|
|
375
|
+
// 3. Inspect delivery history logs
|
|
376
|
+
const deliveries = await client.webhooks.getDeliveries({
|
|
377
|
+
webhookId: webhook.id,
|
|
378
|
+
status: 'failed',
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
// 4. Retry a failed delivery attempt
|
|
382
|
+
if (deliveries.items.length > 0) {
|
|
383
|
+
await client.webhooks.retryDelivery(deliveries.items[0].id);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// 5. Verify HMAC-SHA256 signature in your receiving server/microservice
|
|
387
|
+
const isValid = client.webhooks.verifySignature(
|
|
388
|
+
rawRequestBodyString,
|
|
389
|
+
requestHeaders['x-nodestack-signature'],
|
|
390
|
+
'whsec_9948a8cf38b1e42c'
|
|
391
|
+
);
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
283
396
|
## ð License
|
|
284
397
|
|
|
285
398
|
MIT ÂĐ NodeStack Contributors
|
package/dist/Client.d.ts
CHANGED
|
@@ -5,6 +5,9 @@ import { RealtimeService } from './services/RealtimeService';
|
|
|
5
5
|
import { AdminService } from './services/AdminService';
|
|
6
6
|
import { CollectionService } from './services/CollectionService';
|
|
7
7
|
import { DemoService } from './services/DemoService';
|
|
8
|
+
import { SnapshotService } from './services/SnapshotService';
|
|
9
|
+
import { WebhookService } from './services/WebhookService';
|
|
10
|
+
import { AppService } from './services/AppService';
|
|
8
11
|
import type { ClientOptions, SendOptions, RecordModel, ChaosOptions } from './types';
|
|
9
12
|
/**
|
|
10
13
|
* Main NodeStack Client SDK entry point.
|
|
@@ -16,7 +19,11 @@ export declare class NodeStackClient<TCollections extends Record<string, any> =
|
|
|
16
19
|
readonly realtime: RealtimeService;
|
|
17
20
|
readonly admins: AdminService;
|
|
18
21
|
readonly collections: CollectionService;
|
|
22
|
+
readonly snapshots: SnapshotService;
|
|
19
23
|
readonly demo: DemoService;
|
|
24
|
+
readonly webhooks: WebhookService;
|
|
25
|
+
readonly apps: AppService;
|
|
26
|
+
readonly appSlug?: string;
|
|
20
27
|
private customFetch?;
|
|
21
28
|
private defaultHeaders;
|
|
22
29
|
private defaultTimeout;
|
|
@@ -63,5 +70,10 @@ export declare class NodeStackClient<TCollections extends Record<string, any> =
|
|
|
63
70
|
* Fetches system metrics & analytics (Admin only).
|
|
64
71
|
*/
|
|
65
72
|
metrics(): Promise<any>;
|
|
73
|
+
/**
|
|
74
|
+
* Returns a new NodeStackClient instance scoped to a specific application/MVP.
|
|
75
|
+
* Inherits baseUrl, authStore, customFetch, defaultHeaders, and defaultTimeout.
|
|
76
|
+
*/
|
|
77
|
+
app<TAppCollections extends Record<string, any> = Record<string, RecordModel>>(slug: string, options?: Partial<ClientOptions>): NodeStackClient<TAppCollections>;
|
|
66
78
|
}
|
|
67
79
|
//# sourceMappingURL=Client.d.ts.map
|
package/dist/Client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Client.d.ts","sourceRoot":"","sources":["../src/Client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EACX,WAAW,EACX,YAAY,EACb,MAAM,SAAS,CAAC;AAEjB;;GAEG;AACH,qBAAa,eAAe,CAAC,YAAY,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC;IACjG,SAAgB,OAAO,EAAE,MAAM,CAAC;IAChC,SAAgB,SAAS,EAAE,aAAa,CAAC;IACzC,SAAgB,KAAK,EAAE,WAAW,CAAC;IACnC,SAAgB,QAAQ,EAAE,eAAe,CAAC;IAC1C,SAAgB,MAAM,EAAE,YAAY,CAAC;IACrC,SAAgB,WAAW,EAAE,iBAAiB,CAAC;IAC/C,SAAgB,IAAI,EAAE,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"Client.d.ts","sourceRoot":"","sources":["../src/Client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseAuthStore.d.ts","sourceRoot":"","sources":["../../src/auth/BaseAuthStore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAExD,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,UAAU,GAAG,IAAI,KAAK,IAAI,CAAC;AAEjG;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAqC1E;AAED;;GAEG;AACH,8BAAsB,aAAa;IACjC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAM;IAC9B,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,UAAU,GAAG,IAAI,CAAQ;IACzD,OAAO,CAAC,UAAU,CAAsC;IAExD,IAAW,KAAK,IAAI,MAAM,CAEzB;IAED,IAAW,KAAK,IAAI,WAAW,GAAG,UAAU,GAAG,IAAI,CAElD;IAED;;OAEG;IACH,IAAW,OAAO,IAAI,OAAO,CAgB5B;IAED;;OAEG;IACI,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,UAAU,GAAG,IAAI,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"BaseAuthStore.d.ts","sourceRoot":"","sources":["../../src/auth/BaseAuthStore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAExD,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,UAAU,GAAG,IAAI,KAAK,IAAI,CAAC;AAEjG;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAqC1E;AAED;;GAEG;AACH,8BAAsB,aAAa;IACjC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAM;IAC9B,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,UAAU,GAAG,IAAI,CAAQ;IACzD,OAAO,CAAC,UAAU,CAAsC;IAExD,IAAW,KAAK,IAAI,MAAM,CAEzB;IAED,IAAW,KAAK,IAAI,WAAW,GAAG,UAAU,GAAG,IAAI,CAElD;IAED;;OAEG;IACH,IAAW,OAAO,IAAI,OAAO,CAgB5B;IAED;;OAEG;IACI,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,UAAU,GAAG,IAAI,GAAG,IAAI,CAIxE;IAED;;OAEG;IACI,KAAK,IAAI,IAAI,CAInB;IAED;;;OAGG;IACI,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,EAAE,eAAe,UAAQ,GAAG,MAAM,IAAI,CAajF;IAED;;OAEG;IACH,SAAS,CAAC,MAAM,IAAI,IAAI,CAQvB;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocalAuthStore.d.ts","sourceRoot":"","sources":["../../src/auth/LocalAuthStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAExD,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACpC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAID;;;;GAIG;AACH,qBAAa,cAAe,SAAQ,aAAa;IAC/C,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAC,CAAc;
|
|
1
|
+
{"version":3,"file":"LocalAuthStore.d.ts","sourceRoot":"","sources":["../../src/auth/LocalAuthStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAExD,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACpC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAID;;;;GAIG;AACH,qBAAa,cAAe,SAAQ,aAAa;IAC/C,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAC,CAAc;IAE9B,YAAY,UAAU,GAAE,MAA4B,EAAE,aAAa,CAAC,EAAE,WAAW,EAWhF;IAED,OAAO,CAAC,WAAW;IAiBH,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,UAAU,GAAG,IAAI,GAAG,IAAI,CAgBjF;IAEe,KAAK,IAAI,IAAI,CAU5B;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClientResponseError.d.ts","sourceRoot":"","sources":["../../src/errors/ClientResponseError.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,0BAA0B;IACzC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,GAAG,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,SAAgB,GAAG,EAAE,MAAM,CAAC;IAC5B,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,SAAgB,IAAI,EAAE,GAAG,CAAC;IAC1B,SAAgB,OAAO,EAAE,OAAO,CAAC;IACjC,SAAgB,aAAa,CAAC,EAAE,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"ClientResponseError.d.ts","sourceRoot":"","sources":["../../src/errors/ClientResponseError.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,0BAA0B;IACzC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,GAAG,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,SAAgB,GAAG,EAAE,MAAM,CAAC;IAC5B,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,SAAgB,IAAI,EAAE,GAAG,CAAC;IAC1B,SAAgB,OAAO,EAAE,OAAO,CAAC;IACjC,SAAgB,aAAa,CAAC,EAAE,GAAG,CAAC;IAEpC,YAAY,OAAO,GAAE,0BAA+B,EAiBnD;IAEM,MAAM;QAET,IAAI;QACJ,OAAO;QACP,GAAG;QACH,MAAM;QACN,IAAI;QACJ,OAAO;MAEV;CACF"}
|
package/dist/index.cjs
CHANGED
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
AdminService: () => AdminService,
|
|
24
|
+
AppService: () => AppService,
|
|
24
25
|
BaseAuthStore: () => BaseAuthStore,
|
|
25
26
|
BaseService: () => BaseService,
|
|
26
27
|
ClientResponseError: () => ClientResponseError,
|
|
@@ -32,8 +33,12 @@ __export(index_exports, {
|
|
|
32
33
|
NodeStackClient: () => NodeStackClient,
|
|
33
34
|
RealtimeService: () => RealtimeService,
|
|
34
35
|
RecordService: () => RecordService,
|
|
36
|
+
SnapshotService: () => SnapshotService,
|
|
37
|
+
WebhookService: () => WebhookService,
|
|
38
|
+
computeWebhookSignature: () => computeWebhookSignature,
|
|
35
39
|
decodeJwtPayload: () => decodeJwtPayload,
|
|
36
|
-
default: () => NodeStackClient
|
|
40
|
+
default: () => NodeStackClient,
|
|
41
|
+
verifyWebhookSignature: () => verifyWebhookSignature
|
|
37
42
|
});
|
|
38
43
|
module.exports = __toCommonJS(index_exports);
|
|
39
44
|
|
|
@@ -463,7 +468,8 @@ var FileService = class extends BaseService {
|
|
|
463
468
|
const cleanCol = encodeURIComponent(collectionName);
|
|
464
469
|
const cleanId = encodeURIComponent(recordId);
|
|
465
470
|
const cleanFile = encodeURIComponent(filename);
|
|
466
|
-
|
|
471
|
+
const appSlug = options.app || this.client.appSlug;
|
|
472
|
+
let url = appSlug && appSlug !== "default" ? `${cleanBase}/api/apps/${encodeURIComponent(appSlug)}/files/${cleanCol}/${cleanId}/${cleanFile}` : `${cleanBase}/api/files/${cleanCol}/${cleanId}/${cleanFile}`;
|
|
467
473
|
const queryParts = [];
|
|
468
474
|
if (options.download) {
|
|
469
475
|
queryParts.push("download=1");
|
|
@@ -536,8 +542,16 @@ var RealtimeService = class extends BaseService {
|
|
|
536
542
|
const EventSourceClass = this.getEventSourceConstructor();
|
|
537
543
|
const base = (this.client.baseUrl || "").replace(/\/+$/, "");
|
|
538
544
|
let url = `${base}/api/realtime`;
|
|
545
|
+
const queryParams = new URLSearchParams();
|
|
539
546
|
if (this.client.authStore.token) {
|
|
540
|
-
|
|
547
|
+
queryParams.append("token", this.client.authStore.token);
|
|
548
|
+
}
|
|
549
|
+
if (this.client.appSlug) {
|
|
550
|
+
queryParams.append("app", this.client.appSlug);
|
|
551
|
+
}
|
|
552
|
+
const qs = queryParams.toString();
|
|
553
|
+
if (qs) {
|
|
554
|
+
url += `?${qs}`;
|
|
541
555
|
}
|
|
542
556
|
this.eventSource = new EventSourceClass(url);
|
|
543
557
|
const handleConnect = async (event) => {
|
|
@@ -769,6 +783,8 @@ var AdminService = class extends BaseService {
|
|
|
769
783
|
|
|
770
784
|
// src/services/CollectionService.ts
|
|
771
785
|
var CollectionService = class extends BaseService {
|
|
786
|
+
list = this.getList.bind(this);
|
|
787
|
+
get = this.getOne.bind(this);
|
|
772
788
|
/**
|
|
773
789
|
* Retrieves all collection schema models.
|
|
774
790
|
*/
|
|
@@ -875,15 +891,288 @@ var DemoService = class extends BaseService {
|
|
|
875
891
|
}
|
|
876
892
|
};
|
|
877
893
|
|
|
894
|
+
// src/services/SnapshotService.ts
|
|
895
|
+
var SnapshotService = class extends BaseService {
|
|
896
|
+
/**
|
|
897
|
+
* Retrieves all snapshots, active baseline, and live drift information.
|
|
898
|
+
*/
|
|
899
|
+
async list() {
|
|
900
|
+
return this.send("/api/snapshots", {
|
|
901
|
+
method: "GET"
|
|
902
|
+
});
|
|
903
|
+
}
|
|
904
|
+
/**
|
|
905
|
+
* Alias for list() to retrieve status.
|
|
906
|
+
*/
|
|
907
|
+
async getStatus() {
|
|
908
|
+
return this.list();
|
|
909
|
+
}
|
|
910
|
+
/**
|
|
911
|
+
* Creates a new application state snapshot.
|
|
912
|
+
* If snapshot limit (10) is reached, evictOldest: true can be passed to confirm eviction of the oldest.
|
|
913
|
+
*/
|
|
914
|
+
async create(options) {
|
|
915
|
+
return this.send("/api/snapshots", {
|
|
916
|
+
method: "POST",
|
|
917
|
+
body: options || {}
|
|
918
|
+
});
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* Retrieves a specific snapshot by ID.
|
|
922
|
+
*/
|
|
923
|
+
async get(id) {
|
|
924
|
+
return this.send(`/api/snapshots/${encodeURIComponent(id)}`, {
|
|
925
|
+
method: "GET"
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
/**
|
|
929
|
+
* Restores application state to a specific snapshot.
|
|
930
|
+
* Note: Future snapshots are NOT deleted; history remains intact.
|
|
931
|
+
*/
|
|
932
|
+
async restore(id) {
|
|
933
|
+
return this.send(`/api/snapshots/${encodeURIComponent(id)}/restore`, {
|
|
934
|
+
method: "POST"
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
/**
|
|
938
|
+
* Deletes a specific snapshot by ID.
|
|
939
|
+
*/
|
|
940
|
+
async delete(id) {
|
|
941
|
+
return this.send(`/api/snapshots/${encodeURIComponent(id)}`, {
|
|
942
|
+
method: "DELETE"
|
|
943
|
+
});
|
|
944
|
+
}
|
|
945
|
+
/**
|
|
946
|
+
* Clears all saved snapshots.
|
|
947
|
+
*/
|
|
948
|
+
async clear() {
|
|
949
|
+
return this.send("/api/snapshots", {
|
|
950
|
+
method: "DELETE"
|
|
951
|
+
});
|
|
952
|
+
}
|
|
953
|
+
};
|
|
954
|
+
|
|
955
|
+
// src/services/WebhookService.ts
|
|
956
|
+
function computeWebhookSignature(payload, secret) {
|
|
957
|
+
const str = typeof payload === "string" ? payload : JSON.stringify(payload);
|
|
958
|
+
try {
|
|
959
|
+
const nodeCrypto = typeof require !== "undefined" ? require("crypto") : typeof globalThis !== "undefined" ? globalThis.require?.("crypto") || globalThis.crypto : null;
|
|
960
|
+
if (nodeCrypto && typeof nodeCrypto.createHmac === "function") {
|
|
961
|
+
return nodeCrypto.createHmac("sha256", secret).update(str, "utf8").digest("hex");
|
|
962
|
+
}
|
|
963
|
+
} catch {
|
|
964
|
+
}
|
|
965
|
+
throw new Error("[NodeStackClient] HMAC-SHA256 computation requires crypto module.");
|
|
966
|
+
}
|
|
967
|
+
function verifyWebhookSignature(payload, signatureHeader, secret) {
|
|
968
|
+
if (!signatureHeader || !secret) return false;
|
|
969
|
+
let expected = "";
|
|
970
|
+
try {
|
|
971
|
+
expected = computeWebhookSignature(payload, secret);
|
|
972
|
+
} catch {
|
|
973
|
+
return false;
|
|
974
|
+
}
|
|
975
|
+
let cleanHeader = signatureHeader.trim();
|
|
976
|
+
if (cleanHeader.startsWith("sha256=")) {
|
|
977
|
+
cleanHeader = cleanHeader.substring(7);
|
|
978
|
+
} else if (cleanHeader.startsWith("sha256:")) {
|
|
979
|
+
cleanHeader = cleanHeader.substring(7);
|
|
980
|
+
}
|
|
981
|
+
if (cleanHeader.length !== expected.length) return false;
|
|
982
|
+
try {
|
|
983
|
+
const nodeCrypto = typeof require !== "undefined" ? require("crypto") : typeof globalThis !== "undefined" ? globalThis.require?.("crypto") : null;
|
|
984
|
+
const buf = typeof Buffer !== "undefined" ? Buffer : typeof globalThis !== "undefined" ? globalThis.Buffer : null;
|
|
985
|
+
if (nodeCrypto && typeof nodeCrypto.timingSafeEqual === "function" && buf) {
|
|
986
|
+
return nodeCrypto.timingSafeEqual(buf.from(cleanHeader, "hex"), buf.from(expected, "hex"));
|
|
987
|
+
}
|
|
988
|
+
} catch {
|
|
989
|
+
}
|
|
990
|
+
let diff = 0;
|
|
991
|
+
for (let i = 0; i < cleanHeader.length; i++) {
|
|
992
|
+
diff |= cleanHeader.charCodeAt(i) ^ expected.charCodeAt(i);
|
|
993
|
+
}
|
|
994
|
+
return diff === 0;
|
|
995
|
+
}
|
|
996
|
+
var WebhookService = class extends BaseService {
|
|
997
|
+
/**
|
|
998
|
+
* Retrieves all configured outbound webhooks.
|
|
999
|
+
*/
|
|
1000
|
+
async getList(options = {}) {
|
|
1001
|
+
const res = await this.send("/api/webhooks", {
|
|
1002
|
+
method: "GET",
|
|
1003
|
+
query: options
|
|
1004
|
+
});
|
|
1005
|
+
return Array.isArray(res) ? res : [];
|
|
1006
|
+
}
|
|
1007
|
+
/**
|
|
1008
|
+
* Retrieves a single webhook by ID.
|
|
1009
|
+
*/
|
|
1010
|
+
async getOne(id) {
|
|
1011
|
+
return this.send(`/api/webhooks/${encodeURIComponent(id)}`, {
|
|
1012
|
+
method: "GET"
|
|
1013
|
+
});
|
|
1014
|
+
}
|
|
1015
|
+
/**
|
|
1016
|
+
* Creates a new outbound webhook configuration.
|
|
1017
|
+
*/
|
|
1018
|
+
async create(data) {
|
|
1019
|
+
return this.send("/api/webhooks", {
|
|
1020
|
+
method: "POST",
|
|
1021
|
+
body: data
|
|
1022
|
+
});
|
|
1023
|
+
}
|
|
1024
|
+
/**
|
|
1025
|
+
* Updates an existing webhook configuration.
|
|
1026
|
+
*/
|
|
1027
|
+
async update(id, data) {
|
|
1028
|
+
return this.send(`/api/webhooks/${encodeURIComponent(id)}`, {
|
|
1029
|
+
method: "PATCH",
|
|
1030
|
+
body: data
|
|
1031
|
+
});
|
|
1032
|
+
}
|
|
1033
|
+
/**
|
|
1034
|
+
* Deletes a configured webhook by ID.
|
|
1035
|
+
*/
|
|
1036
|
+
async delete(id) {
|
|
1037
|
+
await this.send(`/api/webhooks/${encodeURIComponent(id)}`, {
|
|
1038
|
+
method: "DELETE"
|
|
1039
|
+
});
|
|
1040
|
+
return true;
|
|
1041
|
+
}
|
|
1042
|
+
/**
|
|
1043
|
+
* Dispatches a live test event to the target webhook endpoint with an optional payload.
|
|
1044
|
+
*/
|
|
1045
|
+
async test(id, payload) {
|
|
1046
|
+
return this.send(`/api/webhooks/${encodeURIComponent(id)}/test`, {
|
|
1047
|
+
method: "POST",
|
|
1048
|
+
body: payload !== void 0 ? { payload } : {}
|
|
1049
|
+
});
|
|
1050
|
+
}
|
|
1051
|
+
/**
|
|
1052
|
+
* Retrieves overall webhook health and delivery statistics.
|
|
1053
|
+
*/
|
|
1054
|
+
async getStats() {
|
|
1055
|
+
return this.send("/api/webhooks/stats", {
|
|
1056
|
+
method: "GET"
|
|
1057
|
+
});
|
|
1058
|
+
}
|
|
1059
|
+
/**
|
|
1060
|
+
* Queries paginated webhook delivery logs with optional filtering by webhook ID, collection, status, or search.
|
|
1061
|
+
*/
|
|
1062
|
+
async getDeliveries(options = {}) {
|
|
1063
|
+
return this.send("/api/webhooks/deliveries", {
|
|
1064
|
+
method: "GET",
|
|
1065
|
+
query: options
|
|
1066
|
+
});
|
|
1067
|
+
}
|
|
1068
|
+
/**
|
|
1069
|
+
* Retrieves complete delivery log details including headers and request/response payloads.
|
|
1070
|
+
*/
|
|
1071
|
+
async getDelivery(id) {
|
|
1072
|
+
return this.send(`/api/webhooks/deliveries/${encodeURIComponent(id)}`, {
|
|
1073
|
+
method: "GET"
|
|
1074
|
+
});
|
|
1075
|
+
}
|
|
1076
|
+
/**
|
|
1077
|
+
* Manually retries a failed delivery attempt to its target endpoint.
|
|
1078
|
+
*/
|
|
1079
|
+
async retryDelivery(id) {
|
|
1080
|
+
return this.send(`/api/webhooks/deliveries/${encodeURIComponent(id)}/retry`, {
|
|
1081
|
+
method: "POST"
|
|
1082
|
+
});
|
|
1083
|
+
}
|
|
1084
|
+
/**
|
|
1085
|
+
* Clears delivery history logs. If olderThanDays is specified, only deletes logs older than that many days.
|
|
1086
|
+
*/
|
|
1087
|
+
async clearDeliveries(olderThanDays) {
|
|
1088
|
+
const query = {};
|
|
1089
|
+
if (olderThanDays !== void 0 && olderThanDays !== null) {
|
|
1090
|
+
query.olderThanDays = olderThanDays;
|
|
1091
|
+
}
|
|
1092
|
+
return this.send("/api/webhooks/deliveries", {
|
|
1093
|
+
method: "DELETE",
|
|
1094
|
+
query
|
|
1095
|
+
});
|
|
1096
|
+
}
|
|
1097
|
+
/**
|
|
1098
|
+
* Verifies an incoming X-NodeStack-Signature header against the expected secret.
|
|
1099
|
+
*/
|
|
1100
|
+
verifySignature(payload, signatureHeader, secret) {
|
|
1101
|
+
return verifyWebhookSignature(payload, signatureHeader, secret);
|
|
1102
|
+
}
|
|
1103
|
+
/**
|
|
1104
|
+
* Computes an HMAC-SHA256 signature for a payload and secret string.
|
|
1105
|
+
*/
|
|
1106
|
+
computeSignature(payload, secret) {
|
|
1107
|
+
return computeWebhookSignature(payload, secret);
|
|
1108
|
+
}
|
|
1109
|
+
static verifySignature = verifyWebhookSignature;
|
|
1110
|
+
static computeSignature = computeWebhookSignature;
|
|
1111
|
+
};
|
|
1112
|
+
|
|
1113
|
+
// src/services/AppService.ts
|
|
1114
|
+
var AppService = class extends BaseService {
|
|
1115
|
+
list = this.getList.bind(this);
|
|
1116
|
+
get = this.getOne.bind(this);
|
|
1117
|
+
/**
|
|
1118
|
+
* Retrieves all configured applications.
|
|
1119
|
+
*/
|
|
1120
|
+
async getList() {
|
|
1121
|
+
const res = await this.send("/api/apps", {
|
|
1122
|
+
method: "GET"
|
|
1123
|
+
});
|
|
1124
|
+
return Array.isArray(res) ? res : res?.items || [];
|
|
1125
|
+
}
|
|
1126
|
+
/**
|
|
1127
|
+
* Retrieves a single application by ID or slug.
|
|
1128
|
+
*/
|
|
1129
|
+
async getOne(appId) {
|
|
1130
|
+
return this.send(`/api/apps/${encodeURIComponent(appId)}`, {
|
|
1131
|
+
method: "GET"
|
|
1132
|
+
});
|
|
1133
|
+
}
|
|
1134
|
+
/**
|
|
1135
|
+
* Creates a new application.
|
|
1136
|
+
*/
|
|
1137
|
+
async create(data) {
|
|
1138
|
+
return this.send("/api/apps", {
|
|
1139
|
+
method: "POST",
|
|
1140
|
+
body: data
|
|
1141
|
+
});
|
|
1142
|
+
}
|
|
1143
|
+
/**
|
|
1144
|
+
* Updates an existing application.
|
|
1145
|
+
*/
|
|
1146
|
+
async update(appId, data) {
|
|
1147
|
+
return this.send(`/api/apps/${encodeURIComponent(appId)}`, {
|
|
1148
|
+
method: "PATCH",
|
|
1149
|
+
body: data
|
|
1150
|
+
});
|
|
1151
|
+
}
|
|
1152
|
+
/**
|
|
1153
|
+
* Deletes an application by ID or slug.
|
|
1154
|
+
*/
|
|
1155
|
+
async delete(appId) {
|
|
1156
|
+
await this.send(`/api/apps/${encodeURIComponent(appId)}`, {
|
|
1157
|
+
method: "DELETE"
|
|
1158
|
+
});
|
|
1159
|
+
return true;
|
|
1160
|
+
}
|
|
1161
|
+
};
|
|
1162
|
+
|
|
878
1163
|
// src/Client.ts
|
|
879
|
-
var NodeStackClient = class {
|
|
1164
|
+
var NodeStackClient = class _NodeStackClient {
|
|
880
1165
|
baseUrl;
|
|
881
1166
|
authStore;
|
|
882
1167
|
files;
|
|
883
1168
|
realtime;
|
|
884
1169
|
admins;
|
|
885
1170
|
collections;
|
|
1171
|
+
snapshots;
|
|
886
1172
|
demo;
|
|
1173
|
+
webhooks;
|
|
1174
|
+
apps;
|
|
1175
|
+
appSlug;
|
|
887
1176
|
customFetch;
|
|
888
1177
|
defaultHeaders;
|
|
889
1178
|
defaultTimeout;
|
|
@@ -896,11 +1185,15 @@ var NodeStackClient = class {
|
|
|
896
1185
|
this.defaultHeaders = options.headers || {};
|
|
897
1186
|
this.defaultTimeout = options.timeout || 12e4;
|
|
898
1187
|
this.chaosOptions = options.chaos ? { ...options.chaos } : null;
|
|
1188
|
+
this.appSlug = options.app;
|
|
899
1189
|
this.files = new FileService(this);
|
|
900
1190
|
this.realtime = new RealtimeService(this, options.EventSource);
|
|
901
1191
|
this.admins = new AdminService(this);
|
|
902
1192
|
this.collections = new CollectionService(this);
|
|
1193
|
+
this.snapshots = new SnapshotService(this);
|
|
903
1194
|
this.demo = new DemoService(this);
|
|
1195
|
+
this.webhooks = new WebhookService(this);
|
|
1196
|
+
this.apps = new AppService(this);
|
|
904
1197
|
}
|
|
905
1198
|
/**
|
|
906
1199
|
* Dynamically configure latency & chaos simulation options for all future requests.
|
|
@@ -954,6 +1247,9 @@ var NodeStackClient = class {
|
|
|
954
1247
|
if (this.authStore.token && !headers["Authorization"] && !headers["authorization"]) {
|
|
955
1248
|
headers["Authorization"] = `Bearer ${this.authStore.token}`;
|
|
956
1249
|
}
|
|
1250
|
+
if (this.appSlug && !headers["x-nodestack-app"] && !headers["X-NodeStack-App"]) {
|
|
1251
|
+
headers["x-nodestack-app"] = this.appSlug;
|
|
1252
|
+
}
|
|
957
1253
|
const effectiveChaos = {
|
|
958
1254
|
...this.chaosOptions || {},
|
|
959
1255
|
...options.chaos || {},
|
|
@@ -1070,6 +1366,21 @@ var NodeStackClient = class {
|
|
|
1070
1366
|
async metrics() {
|
|
1071
1367
|
return this.send("/api/metrics", { method: "GET" });
|
|
1072
1368
|
}
|
|
1369
|
+
/**
|
|
1370
|
+
* Returns a new NodeStackClient instance scoped to a specific application/MVP.
|
|
1371
|
+
* Inherits baseUrl, authStore, customFetch, defaultHeaders, and defaultTimeout.
|
|
1372
|
+
*/
|
|
1373
|
+
app(slug, options = {}) {
|
|
1374
|
+
return new _NodeStackClient(this.baseUrl, {
|
|
1375
|
+
authStore: options.authStore || this.authStore,
|
|
1376
|
+
fetch: options.fetch || this.customFetch,
|
|
1377
|
+
headers: { ...this.defaultHeaders, ...options.headers || {} },
|
|
1378
|
+
timeout: options.timeout !== void 0 ? options.timeout : this.defaultTimeout,
|
|
1379
|
+
chaos: options.chaos !== void 0 ? options.chaos ? { ...options.chaos } : void 0 : this.chaosOptions ? { ...this.chaosOptions } : void 0,
|
|
1380
|
+
app: slug,
|
|
1381
|
+
EventSource: options.EventSource || this.realtime.customEventSource
|
|
1382
|
+
});
|
|
1383
|
+
}
|
|
1073
1384
|
};
|
|
1074
1385
|
|
|
1075
1386
|
// src/auth/MemoryAuthStore.ts
|