@lifestreamdynamics/vault-sdk 1.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/LICENSE +21 -0
- package/README.md +1121 -0
- package/dist/client.d.ts +143 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +286 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +28 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +49 -0
- package/dist/errors.js.map +1 -0
- package/dist/handle-error.d.ts +8 -0
- package/dist/handle-error.d.ts.map +1 -0
- package/dist/handle-error.js +35 -0
- package/dist/handle-error.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/audit-logger.d.ts +29 -0
- package/dist/lib/audit-logger.d.ts.map +1 -0
- package/dist/lib/audit-logger.js +99 -0
- package/dist/lib/audit-logger.js.map +1 -0
- package/dist/lib/encryption.d.ts +34 -0
- package/dist/lib/encryption.d.ts.map +1 -0
- package/dist/lib/encryption.js +87 -0
- package/dist/lib/encryption.js.map +1 -0
- package/dist/lib/signature.d.ts +47 -0
- package/dist/lib/signature.d.ts.map +1 -0
- package/dist/lib/signature.js +71 -0
- package/dist/lib/signature.js.map +1 -0
- package/dist/lib/token-manager.d.ts +80 -0
- package/dist/lib/token-manager.d.ts.map +1 -0
- package/dist/lib/token-manager.js +116 -0
- package/dist/lib/token-manager.js.map +1 -0
- package/dist/resources/admin.d.ts +280 -0
- package/dist/resources/admin.d.ts.map +1 -0
- package/dist/resources/admin.js +236 -0
- package/dist/resources/admin.js.map +1 -0
- package/dist/resources/ai.d.ts +184 -0
- package/dist/resources/ai.d.ts.map +1 -0
- package/dist/resources/ai.js +179 -0
- package/dist/resources/ai.js.map +1 -0
- package/dist/resources/api-keys.d.ts +172 -0
- package/dist/resources/api-keys.d.ts.map +1 -0
- package/dist/resources/api-keys.js +166 -0
- package/dist/resources/api-keys.js.map +1 -0
- package/dist/resources/connectors.d.ts +263 -0
- package/dist/resources/connectors.d.ts.map +1 -0
- package/dist/resources/connectors.js +226 -0
- package/dist/resources/connectors.js.map +1 -0
- package/dist/resources/documents.d.ts +334 -0
- package/dist/resources/documents.d.ts.map +1 -0
- package/dist/resources/documents.js +377 -0
- package/dist/resources/documents.js.map +1 -0
- package/dist/resources/hooks.d.ts +195 -0
- package/dist/resources/hooks.d.ts.map +1 -0
- package/dist/resources/hooks.js +166 -0
- package/dist/resources/hooks.js.map +1 -0
- package/dist/resources/publish.d.ts +165 -0
- package/dist/resources/publish.d.ts.map +1 -0
- package/dist/resources/publish.js +150 -0
- package/dist/resources/publish.js.map +1 -0
- package/dist/resources/search.d.ts +94 -0
- package/dist/resources/search.d.ts.map +1 -0
- package/dist/resources/search.js +76 -0
- package/dist/resources/search.js.map +1 -0
- package/dist/resources/shares.d.ts +130 -0
- package/dist/resources/shares.d.ts.map +1 -0
- package/dist/resources/shares.js +115 -0
- package/dist/resources/shares.js.map +1 -0
- package/dist/resources/subscription.d.ts +172 -0
- package/dist/resources/subscription.d.ts.map +1 -0
- package/dist/resources/subscription.js +166 -0
- package/dist/resources/subscription.js.map +1 -0
- package/dist/resources/teams.d.ts +356 -0
- package/dist/resources/teams.d.ts.map +1 -0
- package/dist/resources/teams.js +395 -0
- package/dist/resources/teams.js.map +1 -0
- package/dist/resources/user.d.ts +92 -0
- package/dist/resources/user.d.ts.map +1 -0
- package/dist/resources/user.js +64 -0
- package/dist/resources/user.js.map +1 -0
- package/dist/resources/vaults.d.ts +144 -0
- package/dist/resources/vaults.d.ts.map +1 -0
- package/dist/resources/vaults.js +158 -0
- package/dist/resources/vaults.js.map +1 -0
- package/dist/resources/webhooks.d.ts +187 -0
- package/dist/resources/webhooks.d.ts.map +1 -0
- package/dist/resources/webhooks.js +171 -0
- package/dist/resources/webhooks.js.map +1 -0
- package/dist/types/api.d.ts +17 -0
- package/dist/types/api.d.ts.map +1 -0
- package/dist/types/api.js +2 -0
- package/dist/types/api.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/resources.d.ts +5 -0
- package/dist/types/resources.d.ts.map +1 -0
- package/dist/types/resources.js +2 -0
- package/dist/types/resources.js.map +1 -0
- package/package.json +58 -0
package/README.md
ADDED
|
@@ -0,0 +1,1121 @@
|
|
|
1
|
+
# Lifestream Vault SDK
|
|
2
|
+
|
|
3
|
+
Official TypeScript SDK for the Lifestream Vault API. Build powerful integrations with your Lifestream Vault account using a modern, type-safe client library.
|
|
4
|
+
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://www.npmjs.com/package/@lifestream-vault/sdk)
|
|
7
|
+
|
|
8
|
+
## π Table of Contents
|
|
9
|
+
|
|
10
|
+
- [Features](#-features)
|
|
11
|
+
- [Installation](#-installation)
|
|
12
|
+
- [Quick Start](#-quick-start)
|
|
13
|
+
- [Authentication](#-authentication)
|
|
14
|
+
- [API Reference](#-api-reference)
|
|
15
|
+
- [Configuration](#-configuration)
|
|
16
|
+
- [Examples](#-examples)
|
|
17
|
+
- [Error Handling](#-error-handling)
|
|
18
|
+
- [TypeScript](#-typescript)
|
|
19
|
+
- [Advanced Features](#-advanced-features)
|
|
20
|
+
- [Documentation](#-documentation)
|
|
21
|
+
- [Related Packages](#-related-packages)
|
|
22
|
+
- [Troubleshooting](#-troubleshooting)
|
|
23
|
+
- [Support](#-support)
|
|
24
|
+
- [License](#-license)
|
|
25
|
+
|
|
26
|
+
## β¨ Features
|
|
27
|
+
|
|
28
|
+
- **Full API Coverage** - Complete support for all Lifestream Vault API endpoints
|
|
29
|
+
- **TypeScript First** - Built with TypeScript, includes full type definitions
|
|
30
|
+
- **Dual Authentication** - Supports both API keys (`lsv_k_*`) and JWT tokens
|
|
31
|
+
- **Auto Token Refresh** - Automatic JWT token renewal with configurable refresh buffer
|
|
32
|
+
- **Request Signing** - HMAC-SHA256 request signing for enhanced security
|
|
33
|
+
- **Client-Side Encryption** - Optional end-to-end encryption for vault content
|
|
34
|
+
- **Smart Error Handling** - Typed error classes with detailed context
|
|
35
|
+
- **Modern ESM** - ES modules for tree-shaking and optimal bundle size
|
|
36
|
+
- **Built on Ky** - Leverages the modern, lightweight HTTP client
|
|
37
|
+
- **Audit Logging** - Optional client-side request audit logging
|
|
38
|
+
- **Zero Dependencies** - Only requires `ky` for HTTP requests
|
|
39
|
+
|
|
40
|
+
## π¦ Installation
|
|
41
|
+
|
|
42
|
+
### NPM (Recommended)
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm install @lifestream-vault/sdk
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Yarn
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
yarn add @lifestream-vault/sdk
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### pnpm
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pnpm add @lifestream-vault/sdk
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### CDN
|
|
61
|
+
|
|
62
|
+
```html
|
|
63
|
+
<!-- ES Module -->
|
|
64
|
+
<script type="module">
|
|
65
|
+
import { LifestreamVaultClient } from 'https://unpkg.com/@lifestream-vault/sdk/dist/index.js';
|
|
66
|
+
</script>
|
|
67
|
+
|
|
68
|
+
<!-- Or via jsDelivr -->
|
|
69
|
+
<script type="module">
|
|
70
|
+
import { LifestreamVaultClient } from 'https://cdn.jsdelivr.net/npm/@lifestream-vault/sdk/+esm';
|
|
71
|
+
</script>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## π Quick Start
|
|
75
|
+
|
|
76
|
+
### Basic Usage with API Key
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { LifestreamVaultClient } from '@lifestream-vault/sdk';
|
|
80
|
+
|
|
81
|
+
const client = new LifestreamVaultClient({
|
|
82
|
+
baseUrl: 'https://vault.example.com',
|
|
83
|
+
apiKey: 'lsv_k_your_api_key_here',
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// List all vaults
|
|
87
|
+
const vaults = await client.vaults.list();
|
|
88
|
+
console.log(vaults);
|
|
89
|
+
|
|
90
|
+
// Get a document
|
|
91
|
+
const doc = await client.documents.get('vault-id', 'path/to/document.md');
|
|
92
|
+
console.log(doc.content);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Login with Email and Password
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { LifestreamVaultClient } from '@lifestream-vault/sdk';
|
|
99
|
+
|
|
100
|
+
const { client, tokens } = await LifestreamVaultClient.login(
|
|
101
|
+
'https://vault.example.com',
|
|
102
|
+
'user@example.com',
|
|
103
|
+
'your-password',
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
// Client is now authenticated with JWT tokens
|
|
107
|
+
const vaults = await client.vaults.list();
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Using an Existing JWT Token
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
const client = new LifestreamVaultClient({
|
|
114
|
+
baseUrl: 'https://vault.example.com',
|
|
115
|
+
accessToken: 'eyJhbGci...', // Your JWT access token
|
|
116
|
+
refreshToken: 'your_refresh_token', // Optional: enables auto-refresh
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Error Handling
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
import { LifestreamVaultClient, NotFoundError, AuthenticationError } from '@lifestream-vault/sdk';
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
const vault = await client.vaults.get('non-existent-id');
|
|
127
|
+
} catch (error) {
|
|
128
|
+
if (error instanceof NotFoundError) {
|
|
129
|
+
console.error('Vault not found:', error.message);
|
|
130
|
+
} else if (error instanceof AuthenticationError) {
|
|
131
|
+
console.error('Authentication failed:', error.message);
|
|
132
|
+
} else {
|
|
133
|
+
console.error('Unexpected error:', error);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## π Authentication
|
|
139
|
+
|
|
140
|
+
The SDK supports two authentication methods:
|
|
141
|
+
|
|
142
|
+
### 1. API Key Authentication
|
|
143
|
+
|
|
144
|
+
Best for server-side integrations, automation scripts, and long-running services.
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
const client = new LifestreamVaultClient({
|
|
148
|
+
baseUrl: 'https://vault.example.com',
|
|
149
|
+
apiKey: 'lsv_k_your_api_key_here', // Starts with 'lsv_k_'
|
|
150
|
+
});
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**Features:**
|
|
154
|
+
- Simple, static authentication
|
|
155
|
+
- No expiration or refresh required
|
|
156
|
+
- Automatic HMAC request signing for mutating operations
|
|
157
|
+
- Scoped permissions (read-only, read-write, or vault-specific)
|
|
158
|
+
|
|
159
|
+
**How to get an API key:**
|
|
160
|
+
1. Log in to your Lifestream Vault account
|
|
161
|
+
2. Navigate to Settings β API Keys
|
|
162
|
+
3. Click "Create API Key"
|
|
163
|
+
4. Configure scopes and expiration
|
|
164
|
+
5. Copy your key (starts with `lsv_k_`)
|
|
165
|
+
|
|
166
|
+
### 2. JWT Token Authentication
|
|
167
|
+
|
|
168
|
+
Best for user-facing applications and scenarios requiring user-specific permissions.
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
const client = new LifestreamVaultClient({
|
|
172
|
+
baseUrl: 'https://vault.example.com',
|
|
173
|
+
accessToken: 'eyJhbGci...', // Your JWT access token
|
|
174
|
+
refreshToken: 'your_refresh_token', // Optional but recommended
|
|
175
|
+
refreshBufferMs: 60000, // Refresh 60s before expiry (default)
|
|
176
|
+
onTokenRefresh: (tokens) => {
|
|
177
|
+
// Save new tokens to your storage
|
|
178
|
+
localStorage.setItem('accessToken', tokens.accessToken);
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**Features:**
|
|
184
|
+
- User-specific permissions
|
|
185
|
+
- Automatic token refresh (when `refreshToken` provided)
|
|
186
|
+
- Configurable refresh timing
|
|
187
|
+
- Token refresh callbacks for persistence
|
|
188
|
+
|
|
189
|
+
**Login Helper:**
|
|
190
|
+
```typescript
|
|
191
|
+
const { client, tokens, refreshToken } = await LifestreamVaultClient.login(
|
|
192
|
+
'https://vault.example.com',
|
|
193
|
+
'user@example.com',
|
|
194
|
+
'password',
|
|
195
|
+
{
|
|
196
|
+
onTokenRefresh: (newTokens) => {
|
|
197
|
+
// Persist tokens for session restoration
|
|
198
|
+
sessionStorage.setItem('tokens', JSON.stringify(newTokens));
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
);
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## π API Reference
|
|
205
|
+
|
|
206
|
+
The SDK provides resource-based access to all API endpoints:
|
|
207
|
+
|
|
208
|
+
### Vaults
|
|
209
|
+
|
|
210
|
+
Manage vault containers for organizing documents.
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
// List all vaults
|
|
214
|
+
const vaults = await client.vaults.list();
|
|
215
|
+
|
|
216
|
+
// Get a specific vault
|
|
217
|
+
const vault = await client.vaults.get('vault-id');
|
|
218
|
+
|
|
219
|
+
// Create a new vault
|
|
220
|
+
const newVault = await client.vaults.create({
|
|
221
|
+
name: 'My Notes',
|
|
222
|
+
slug: 'my-notes', // Optional: auto-generated from name
|
|
223
|
+
description: 'Personal notes and ideas',
|
|
224
|
+
encryptionEnabled: false,
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
// Update a vault
|
|
228
|
+
const updated = await client.vaults.update('vault-id', {
|
|
229
|
+
name: 'Updated Name',
|
|
230
|
+
description: 'New description',
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
// Delete a vault
|
|
234
|
+
await client.vaults.delete('vault-id');
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Documents
|
|
238
|
+
|
|
239
|
+
Read, write, and manage Markdown documents within vaults.
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
// List documents in a vault
|
|
243
|
+
const docs = await client.documents.list('vault-id');
|
|
244
|
+
|
|
245
|
+
// Get a document with content
|
|
246
|
+
const doc = await client.documents.get('vault-id', 'path/to/doc.md');
|
|
247
|
+
console.log(doc.content); // Raw Markdown content
|
|
248
|
+
|
|
249
|
+
// Create or update a document
|
|
250
|
+
await client.documents.put('vault-id', 'new-doc.md', '# Hello World\n\nMy content');
|
|
251
|
+
|
|
252
|
+
// Get document metadata only
|
|
253
|
+
const metadata = await client.documents.getMetadata('vault-id', 'path/to/doc.md');
|
|
254
|
+
|
|
255
|
+
// Delete a document
|
|
256
|
+
await client.documents.delete('vault-id', 'path/to/doc.md');
|
|
257
|
+
|
|
258
|
+
// Get directory tree structure
|
|
259
|
+
const tree = await client.documents.tree('vault-id');
|
|
260
|
+
|
|
261
|
+
// List document versions
|
|
262
|
+
const versions = await client.documents.listVersions('vault-id', 'path/to/doc.md');
|
|
263
|
+
|
|
264
|
+
// Get a specific version
|
|
265
|
+
const version = await client.documents.getVersion('vault-id', 'path/to/doc.md', 5);
|
|
266
|
+
|
|
267
|
+
// Compare versions (diff)
|
|
268
|
+
const diff = await client.documents.diffVersions('vault-id', 'path/to/doc.md', 3, 5);
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Search
|
|
272
|
+
|
|
273
|
+
Full-text search across your vaults with filtering.
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
// Search all vaults
|
|
277
|
+
const results = await client.search.search({
|
|
278
|
+
query: 'typescript',
|
|
279
|
+
vaultIds: ['vault-1', 'vault-2'], // Optional: filter by vaults
|
|
280
|
+
tags: ['code', 'tutorial'], // Optional: filter by tags
|
|
281
|
+
limit: 20,
|
|
282
|
+
offset: 0,
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
for (const result of results.results) {
|
|
286
|
+
console.log(result.title, result.highlight);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Get autocomplete suggestions
|
|
290
|
+
const suggestions = await client.search.autocomplete('type');
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### AI
|
|
294
|
+
|
|
295
|
+
AI-powered document chat and summarization.
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
// Create a chat session
|
|
299
|
+
const session = await client.ai.createSession({
|
|
300
|
+
vaultId: 'vault-id',
|
|
301
|
+
documentPaths: ['doc1.md', 'doc2.md'], // Optional: specific docs
|
|
302
|
+
systemPrompt: 'You are a helpful assistant.', // Optional
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
// Send a message
|
|
306
|
+
const response = await client.ai.sendMessage(session.id, {
|
|
307
|
+
message: 'Summarize the key points from these documents',
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
console.log(response.message); // AI response
|
|
311
|
+
|
|
312
|
+
// List all chat sessions
|
|
313
|
+
const sessions = await client.ai.listSessions();
|
|
314
|
+
|
|
315
|
+
// Get session details
|
|
316
|
+
const sessionDetail = await client.ai.getSession(session.id);
|
|
317
|
+
|
|
318
|
+
// Delete a session
|
|
319
|
+
await client.ai.deleteSession(session.id);
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Teams
|
|
323
|
+
|
|
324
|
+
Collaborate with team members on shared vaults.
|
|
325
|
+
|
|
326
|
+
```typescript
|
|
327
|
+
// List your teams
|
|
328
|
+
const teams = await client.teams.list();
|
|
329
|
+
|
|
330
|
+
// Create a team
|
|
331
|
+
const team = await client.teams.create({
|
|
332
|
+
name: 'Engineering',
|
|
333
|
+
description: 'Engineering team workspace',
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
// Add a member
|
|
337
|
+
await client.teams.addMember(team.id, {
|
|
338
|
+
email: 'colleague@example.com',
|
|
339
|
+
role: 'member', // 'admin' or 'member'
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
// Create a team vault
|
|
343
|
+
const teamVault = await client.teams.createVault(team.id, {
|
|
344
|
+
name: 'Team Docs',
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
// List team vaults
|
|
348
|
+
const teamVaults = await client.teams.listVaults(team.id);
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### API Keys
|
|
352
|
+
|
|
353
|
+
Manage API keys for programmatic access.
|
|
354
|
+
|
|
355
|
+
```typescript
|
|
356
|
+
// List API keys
|
|
357
|
+
const keys = await client.apiKeys.list();
|
|
358
|
+
|
|
359
|
+
// Create an API key
|
|
360
|
+
const apiKey = await client.apiKeys.create({
|
|
361
|
+
name: 'CI/CD Key',
|
|
362
|
+
scopes: ['vaults:read', 'documents:read'],
|
|
363
|
+
vaultId: 'vault-id', // Optional: scope to specific vault
|
|
364
|
+
expiresAt: '2026-12-31T23:59:59Z', // Optional
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
console.log(apiKey.secret); // Only shown once! Save it securely
|
|
368
|
+
|
|
369
|
+
// Delete an API key
|
|
370
|
+
await client.apiKeys.delete('key-id');
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### User
|
|
374
|
+
|
|
375
|
+
Manage user profile and storage information.
|
|
376
|
+
|
|
377
|
+
```typescript
|
|
378
|
+
// Get current user profile
|
|
379
|
+
const user = await client.user.get();
|
|
380
|
+
console.log(user.email, user.name);
|
|
381
|
+
|
|
382
|
+
// Get storage usage
|
|
383
|
+
const storage = await client.user.getStorage();
|
|
384
|
+
console.log(`Used: ${storage.totalBytes} / ${storage.limitBytes} bytes`);
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### Subscription
|
|
388
|
+
|
|
389
|
+
Manage subscription plans and billing.
|
|
390
|
+
|
|
391
|
+
```typescript
|
|
392
|
+
// Get current subscription
|
|
393
|
+
const subscription = await client.subscription.get();
|
|
394
|
+
console.log(subscription.tier); // 'free', 'pro', or 'business'
|
|
395
|
+
|
|
396
|
+
// Get available plans
|
|
397
|
+
const plans = await client.subscription.getPlans();
|
|
398
|
+
|
|
399
|
+
// Create a checkout session for upgrading
|
|
400
|
+
const checkout = await client.subscription.createCheckout({
|
|
401
|
+
planId: 'pro-monthly',
|
|
402
|
+
successUrl: 'https://example.com/success',
|
|
403
|
+
cancelUrl: 'https://example.com/cancel',
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
// Open checkout.url in browser for payment
|
|
407
|
+
|
|
408
|
+
// Create a billing portal session
|
|
409
|
+
const portal = await client.subscription.createPortalSession({
|
|
410
|
+
returnUrl: 'https://example.com/settings',
|
|
411
|
+
});
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
### Shares
|
|
415
|
+
|
|
416
|
+
Create temporary share links for documents.
|
|
417
|
+
|
|
418
|
+
```typescript
|
|
419
|
+
// Create a share link
|
|
420
|
+
const share = await client.shares.create({
|
|
421
|
+
vaultId: 'vault-id',
|
|
422
|
+
documentPath: 'path/to/doc.md',
|
|
423
|
+
expiresAt: '2026-03-01T00:00:00Z', // Optional
|
|
424
|
+
password: 'secret123', // Optional
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
console.log(share.shareUrl); // Share this URL
|
|
428
|
+
|
|
429
|
+
// List all shares
|
|
430
|
+
const shares = await client.shares.list();
|
|
431
|
+
|
|
432
|
+
// Revoke a share
|
|
433
|
+
await client.shares.delete('share-token');
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### Publish
|
|
437
|
+
|
|
438
|
+
Publish documents for public access.
|
|
439
|
+
|
|
440
|
+
```typescript
|
|
441
|
+
// Publish a document
|
|
442
|
+
const published = await client.publish.publish({
|
|
443
|
+
vaultId: 'vault-id',
|
|
444
|
+
documentPath: 'blog/post.md',
|
|
445
|
+
slug: 'my-blog-post', // Optional: auto-generated
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
console.log(published.publicUrl); // Public URL
|
|
449
|
+
|
|
450
|
+
// List published documents
|
|
451
|
+
const docs = await client.publish.list();
|
|
452
|
+
|
|
453
|
+
// Unpublish
|
|
454
|
+
await client.publish.unpublish('vault-id', 'blog/post.md');
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
### Connectors
|
|
458
|
+
|
|
459
|
+
Sync with external services like Google Drive.
|
|
460
|
+
|
|
461
|
+
```typescript
|
|
462
|
+
// List connectors
|
|
463
|
+
const connectors = await client.connectors.list();
|
|
464
|
+
|
|
465
|
+
// Create a Google Drive connector
|
|
466
|
+
const connector = await client.connectors.create({
|
|
467
|
+
vaultId: 'vault-id',
|
|
468
|
+
provider: 'google_drive',
|
|
469
|
+
config: {
|
|
470
|
+
folderId: 'google-drive-folder-id',
|
|
471
|
+
credentials: { /* OAuth credentials */ },
|
|
472
|
+
},
|
|
473
|
+
syncDirection: 'bidirectional',
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
// Test connection
|
|
477
|
+
const testResult = await client.connectors.testConnection(connector.id);
|
|
478
|
+
console.log(testResult.success);
|
|
479
|
+
|
|
480
|
+
// Trigger manual sync
|
|
481
|
+
await client.connectors.triggerSync(connector.id);
|
|
482
|
+
|
|
483
|
+
// View sync logs
|
|
484
|
+
const logs = await client.connectors.getSyncLogs(connector.id);
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
### Hooks
|
|
488
|
+
|
|
489
|
+
Configure internal event handlers for automation.
|
|
490
|
+
|
|
491
|
+
```typescript
|
|
492
|
+
// List hooks
|
|
493
|
+
const hooks = await client.hooks.list('vault-id');
|
|
494
|
+
|
|
495
|
+
// Create a hook
|
|
496
|
+
const hook = await client.hooks.create('vault-id', {
|
|
497
|
+
name: 'Auto-tag documents',
|
|
498
|
+
eventType: 'document.created',
|
|
499
|
+
handlerType: 'auto_tag',
|
|
500
|
+
config: {
|
|
501
|
+
tags: ['inbox'],
|
|
502
|
+
},
|
|
503
|
+
enabled: true,
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
// View hook executions
|
|
507
|
+
const executions = await client.hooks.getExecutions('vault-id', hook.id);
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
### Webhooks
|
|
511
|
+
|
|
512
|
+
Send HTTP notifications on vault events.
|
|
513
|
+
|
|
514
|
+
```typescript
|
|
515
|
+
// List webhooks
|
|
516
|
+
const webhooks = await client.webhooks.list('vault-id');
|
|
517
|
+
|
|
518
|
+
// Create a webhook
|
|
519
|
+
const webhook = await client.webhooks.create('vault-id', {
|
|
520
|
+
url: 'https://example.com/webhook',
|
|
521
|
+
events: ['document.created', 'document.updated'],
|
|
522
|
+
enabled: true,
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
console.log(webhook.secret); // Use for HMAC verification
|
|
526
|
+
|
|
527
|
+
// View delivery logs
|
|
528
|
+
const deliveries = await client.webhooks.getDeliveries('vault-id', webhook.id);
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
### Admin
|
|
532
|
+
|
|
533
|
+
Administrative operations (requires admin role).
|
|
534
|
+
|
|
535
|
+
```typescript
|
|
536
|
+
// Get system stats
|
|
537
|
+
const stats = await client.admin.getStats();
|
|
538
|
+
console.log(stats.totalUsers, stats.totalVaults);
|
|
539
|
+
|
|
540
|
+
// List all users (paginated)
|
|
541
|
+
const users = await client.admin.listUsers({ page: 1, limit: 50 });
|
|
542
|
+
|
|
543
|
+
// Get user details
|
|
544
|
+
const userDetail = await client.admin.getUser('user-id');
|
|
545
|
+
|
|
546
|
+
// Update user
|
|
547
|
+
await client.admin.updateUser('user-id', {
|
|
548
|
+
role: 'admin',
|
|
549
|
+
isActive: true,
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
// Get system health
|
|
553
|
+
const health = await client.admin.getHealth();
|
|
554
|
+
console.log(health.status); // 'healthy', 'degraded', or 'down'
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
## βοΈ Configuration
|
|
558
|
+
|
|
559
|
+
### ClientOptions
|
|
560
|
+
|
|
561
|
+
| Option | Type | Default | Description |
|
|
562
|
+
|--------|------|---------|-------------|
|
|
563
|
+
| `baseUrl` | `string` | **required** | Base URL of your Lifestream Vault server |
|
|
564
|
+
| `apiKey` | `string` | - | API key for authentication (starts with `lsv_k_`) |
|
|
565
|
+
| `accessToken` | `string` | - | JWT access token for user authentication |
|
|
566
|
+
| `refreshToken` | `string` | - | JWT refresh token for automatic renewal |
|
|
567
|
+
| `timeout` | `number` | `30000` | Request timeout in milliseconds |
|
|
568
|
+
| `refreshBufferMs` | `number` | `60000` | Milliseconds before expiry to trigger proactive refresh |
|
|
569
|
+
| `onTokenRefresh` | `function` | - | Callback when tokens are refreshed |
|
|
570
|
+
| `enableRequestSigning` | `boolean` | `true` (API keys) | Enable HMAC request signing |
|
|
571
|
+
| `enableAuditLogging` | `boolean` | `false` | Enable client-side audit logging |
|
|
572
|
+
| `auditLogPath` | `string` | `~/.lsvault/audit.log` | Path to audit log file |
|
|
573
|
+
|
|
574
|
+
### Full Configuration Example
|
|
575
|
+
|
|
576
|
+
```typescript
|
|
577
|
+
const client = new LifestreamVaultClient({
|
|
578
|
+
baseUrl: 'https://vault.example.com',
|
|
579
|
+
apiKey: 'lsv_k_your_api_key',
|
|
580
|
+
timeout: 60000, // 60 seconds
|
|
581
|
+
enableRequestSigning: true,
|
|
582
|
+
enableAuditLogging: true,
|
|
583
|
+
auditLogPath: '/var/log/lsvault-audit.log',
|
|
584
|
+
});
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
### JWT Configuration Example
|
|
588
|
+
|
|
589
|
+
```typescript
|
|
590
|
+
const client = new LifestreamVaultClient({
|
|
591
|
+
baseUrl: 'https://vault.example.com',
|
|
592
|
+
accessToken: 'eyJhbGci...',
|
|
593
|
+
refreshToken: 'refresh_token_here',
|
|
594
|
+
refreshBufferMs: 120000, // Refresh 2 minutes before expiry
|
|
595
|
+
onTokenRefresh: (tokens) => {
|
|
596
|
+
// Persist new tokens
|
|
597
|
+
localStorage.setItem('accessToken', tokens.accessToken);
|
|
598
|
+
console.log('Tokens refreshed successfully');
|
|
599
|
+
},
|
|
600
|
+
});
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
## π‘ Examples
|
|
604
|
+
|
|
605
|
+
### Create a Vault and Upload Documents
|
|
606
|
+
|
|
607
|
+
```typescript
|
|
608
|
+
import { LifestreamVaultClient } from '@lifestream-vault/sdk';
|
|
609
|
+
|
|
610
|
+
const client = new LifestreamVaultClient({
|
|
611
|
+
baseUrl: 'https://vault.example.com',
|
|
612
|
+
apiKey: 'lsv_k_your_api_key',
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
// Create a vault
|
|
616
|
+
const vault = await client.vaults.create({
|
|
617
|
+
name: 'Project Documentation',
|
|
618
|
+
description: 'Technical docs for the new project',
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
// Upload multiple documents
|
|
622
|
+
const docs = [
|
|
623
|
+
{ path: 'README.md', content: '# Project Overview\n\nWelcome!' },
|
|
624
|
+
{ path: 'setup/installation.md', content: '# Installation\n\n...' },
|
|
625
|
+
{ path: 'api/reference.md', content: '# API Reference\n\n...' },
|
|
626
|
+
];
|
|
627
|
+
|
|
628
|
+
for (const doc of docs) {
|
|
629
|
+
await client.documents.put(vault.id, doc.path, doc.content);
|
|
630
|
+
console.log(`Uploaded: ${doc.path}`);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
console.log('Vault created and documents uploaded successfully!');
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
### Search and Export Documents
|
|
637
|
+
|
|
638
|
+
```typescript
|
|
639
|
+
// Search for documents with specific tags
|
|
640
|
+
const results = await client.search.search({
|
|
641
|
+
query: 'API',
|
|
642
|
+
tags: ['documentation', 'tutorial'],
|
|
643
|
+
vaultIds: [vault.id],
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
// Export matching documents
|
|
647
|
+
for (const result of results.results) {
|
|
648
|
+
const doc = await client.documents.get(result.vaultId, result.path);
|
|
649
|
+
|
|
650
|
+
// Save to local file system
|
|
651
|
+
await fs.writeFile(`./export/${result.path}`, doc.content);
|
|
652
|
+
console.log(`Exported: ${result.path}`);
|
|
653
|
+
}
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
### AI-Powered Document Q&A
|
|
657
|
+
|
|
658
|
+
```typescript
|
|
659
|
+
// Create an AI session with specific documents
|
|
660
|
+
const session = await client.ai.createSession({
|
|
661
|
+
vaultId: vault.id,
|
|
662
|
+
documentPaths: ['api/reference.md', 'setup/installation.md'],
|
|
663
|
+
systemPrompt: 'You are a technical documentation assistant.',
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
// Ask questions about the documents
|
|
667
|
+
const response1 = await client.ai.sendMessage(session.id, {
|
|
668
|
+
message: 'What are the authentication methods supported?',
|
|
669
|
+
});
|
|
670
|
+
|
|
671
|
+
console.log('AI:', response1.message);
|
|
672
|
+
|
|
673
|
+
const response2 = await client.ai.sendMessage(session.id, {
|
|
674
|
+
message: 'How do I install the SDK?',
|
|
675
|
+
});
|
|
676
|
+
|
|
677
|
+
console.log('AI:', response2.message);
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
### Automated Backup Script
|
|
681
|
+
|
|
682
|
+
```typescript
|
|
683
|
+
import { LifestreamVaultClient } from '@lifestream-vault/sdk';
|
|
684
|
+
import fs from 'fs/promises';
|
|
685
|
+
import path from 'path';
|
|
686
|
+
|
|
687
|
+
const client = new LifestreamVaultClient({
|
|
688
|
+
baseUrl: 'https://vault.example.com',
|
|
689
|
+
apiKey: process.env.LSVAULT_API_KEY!,
|
|
690
|
+
});
|
|
691
|
+
|
|
692
|
+
async function backupAllVaults() {
|
|
693
|
+
const vaults = await client.vaults.list();
|
|
694
|
+
const backupDir = `./backups/${new Date().toISOString().split('T')[0]}`;
|
|
695
|
+
|
|
696
|
+
await fs.mkdir(backupDir, { recursive: true });
|
|
697
|
+
|
|
698
|
+
for (const vault of vaults) {
|
|
699
|
+
console.log(`Backing up vault: ${vault.name}`);
|
|
700
|
+
const documents = await client.documents.list(vault.id);
|
|
701
|
+
|
|
702
|
+
for (const doc of documents) {
|
|
703
|
+
const docData = await client.documents.get(vault.id, doc.path);
|
|
704
|
+
const filePath = path.join(backupDir, vault.slug, doc.path);
|
|
705
|
+
|
|
706
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
707
|
+
await fs.writeFile(filePath, docData.content);
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
console.log(`β Backed up ${documents.length} documents from ${vault.name}`);
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
console.log(`Backup completed: ${backupDir}`);
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
backupAllVaults().catch(console.error);
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
### Team Collaboration Setup
|
|
720
|
+
|
|
721
|
+
```typescript
|
|
722
|
+
// Create a team
|
|
723
|
+
const team = await client.teams.create({
|
|
724
|
+
name: 'Marketing Team',
|
|
725
|
+
description: 'Marketing team collaboration space',
|
|
726
|
+
});
|
|
727
|
+
|
|
728
|
+
// Add team members
|
|
729
|
+
const members = [
|
|
730
|
+
{ email: 'alice@example.com', role: 'admin' },
|
|
731
|
+
{ email: 'bob@example.com', role: 'member' },
|
|
732
|
+
{ email: 'carol@example.com', role: 'member' },
|
|
733
|
+
];
|
|
734
|
+
|
|
735
|
+
for (const member of members) {
|
|
736
|
+
await client.teams.addMember(team.id, member);
|
|
737
|
+
console.log(`Added ${member.email} as ${member.role}`);
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
// Create a shared vault for the team
|
|
741
|
+
const teamVault = await client.teams.createVault(team.id, {
|
|
742
|
+
name: 'Campaign Materials',
|
|
743
|
+
description: 'Shared marketing campaign documents',
|
|
744
|
+
});
|
|
745
|
+
|
|
746
|
+
// Upload initial documents
|
|
747
|
+
await client.documents.put(
|
|
748
|
+
teamVault.id,
|
|
749
|
+
'campaigns/2026-q1.md',
|
|
750
|
+
'# Q1 2026 Campaign\n\n## Goals\n- Increase brand awareness\n- Launch new product',
|
|
751
|
+
);
|
|
752
|
+
|
|
753
|
+
console.log('Team setup complete!');
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
## π¨ Error Handling
|
|
757
|
+
|
|
758
|
+
The SDK provides typed error classes for different error scenarios:
|
|
759
|
+
|
|
760
|
+
### Error Types
|
|
761
|
+
|
|
762
|
+
```typescript
|
|
763
|
+
import {
|
|
764
|
+
SDKError, // Base error class
|
|
765
|
+
ValidationError, // Invalid input or configuration
|
|
766
|
+
AuthenticationError,// Authentication failed
|
|
767
|
+
AuthorizationError, // Insufficient permissions
|
|
768
|
+
NotFoundError, // Resource not found
|
|
769
|
+
ConflictError, // Resource conflict (e.g., duplicate slug)
|
|
770
|
+
RateLimitError, // Rate limit exceeded
|
|
771
|
+
NetworkError, // Network or connection error
|
|
772
|
+
} from '@lifestream-vault/sdk';
|
|
773
|
+
```
|
|
774
|
+
|
|
775
|
+
### Handling Specific Errors
|
|
776
|
+
|
|
777
|
+
```typescript
|
|
778
|
+
try {
|
|
779
|
+
await client.vaults.create({ name: 'My Vault', slug: 'existing-slug' });
|
|
780
|
+
} catch (error) {
|
|
781
|
+
if (error instanceof ConflictError) {
|
|
782
|
+
console.error('A vault with this slug already exists');
|
|
783
|
+
} else if (error instanceof ValidationError) {
|
|
784
|
+
console.error('Invalid vault configuration:', error.message);
|
|
785
|
+
} else if (error instanceof RateLimitError) {
|
|
786
|
+
console.error('Rate limit exceeded. Try again later.');
|
|
787
|
+
} else {
|
|
788
|
+
console.error('Unexpected error:', error);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
### Error Properties
|
|
794
|
+
|
|
795
|
+
All SDK errors include:
|
|
796
|
+
|
|
797
|
+
```typescript
|
|
798
|
+
error.message // Human-readable error message
|
|
799
|
+
error.status // HTTP status code (if applicable)
|
|
800
|
+
error.context // Additional error context (resource type, ID, etc.)
|
|
801
|
+
```
|
|
802
|
+
|
|
803
|
+
### Retry Logic Example
|
|
804
|
+
|
|
805
|
+
```typescript
|
|
806
|
+
import { RateLimitError, NetworkError } from '@lifestream-vault/sdk';
|
|
807
|
+
|
|
808
|
+
async function fetchWithRetry(operation: () => Promise<any>, maxRetries = 3) {
|
|
809
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
810
|
+
try {
|
|
811
|
+
return await operation();
|
|
812
|
+
} catch (error) {
|
|
813
|
+
if (error instanceof RateLimitError || error instanceof NetworkError) {
|
|
814
|
+
if (i < maxRetries - 1) {
|
|
815
|
+
const delay = Math.pow(2, i) * 1000; // Exponential backoff
|
|
816
|
+
console.log(`Retrying in ${delay}ms...`);
|
|
817
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
818
|
+
continue;
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
throw error;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// Usage
|
|
827
|
+
const vaults = await fetchWithRetry(() => client.vaults.list());
|
|
828
|
+
```
|
|
829
|
+
|
|
830
|
+
## π TypeScript
|
|
831
|
+
|
|
832
|
+
The SDK is built with TypeScript and provides full type definitions out of the box.
|
|
833
|
+
|
|
834
|
+
### Type Imports
|
|
835
|
+
|
|
836
|
+
```typescript
|
|
837
|
+
import {
|
|
838
|
+
LifestreamVaultClient,
|
|
839
|
+
type ClientOptions,
|
|
840
|
+
type Vault,
|
|
841
|
+
type Document,
|
|
842
|
+
type DocumentWithContent,
|
|
843
|
+
type SearchResult,
|
|
844
|
+
type AiChatSession,
|
|
845
|
+
type Team,
|
|
846
|
+
type ApiKey,
|
|
847
|
+
type Subscription,
|
|
848
|
+
} from '@lifestream-vault/sdk';
|
|
849
|
+
```
|
|
850
|
+
|
|
851
|
+
### Type Safety
|
|
852
|
+
|
|
853
|
+
```typescript
|
|
854
|
+
// Compiler catches missing required fields
|
|
855
|
+
const vault = await client.vaults.create({
|
|
856
|
+
name: 'My Vault',
|
|
857
|
+
// slug is optional, auto-generated
|
|
858
|
+
// TypeScript won't let you pass invalid fields
|
|
859
|
+
});
|
|
860
|
+
|
|
861
|
+
// Full autocomplete and type checking
|
|
862
|
+
const doc = await client.documents.get('vault-id', 'path.md');
|
|
863
|
+
doc.content; // string
|
|
864
|
+
doc.document.tags; // string[]
|
|
865
|
+
doc.document.sizeBytes; // number
|
|
866
|
+
```
|
|
867
|
+
|
|
868
|
+
### Generic Error Handling
|
|
869
|
+
|
|
870
|
+
```typescript
|
|
871
|
+
import { SDKError } from '@lifestream-vault/sdk';
|
|
872
|
+
|
|
873
|
+
try {
|
|
874
|
+
await client.vaults.get('invalid-id');
|
|
875
|
+
} catch (error) {
|
|
876
|
+
if (error instanceof SDKError) {
|
|
877
|
+
// TypeScript knows about status, message, context
|
|
878
|
+
console.error(`Error ${error.status}: ${error.message}`);
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
```
|
|
882
|
+
|
|
883
|
+
## π§ Advanced Features
|
|
884
|
+
|
|
885
|
+
### Request Signing (HMAC-SHA256)
|
|
886
|
+
|
|
887
|
+
Automatically enabled for API key authentication. Adds signature headers to mutating requests (PUT, POST, DELETE, PATCH) for enhanced security.
|
|
888
|
+
|
|
889
|
+
```typescript
|
|
890
|
+
const client = new LifestreamVaultClient({
|
|
891
|
+
baseUrl: 'https://vault.example.com',
|
|
892
|
+
apiKey: 'lsv_k_your_api_key',
|
|
893
|
+
enableRequestSigning: true, // Default: true for API keys
|
|
894
|
+
});
|
|
895
|
+
|
|
896
|
+
// All mutating requests are now signed with HMAC-SHA256
|
|
897
|
+
await client.documents.put('vault-id', 'doc.md', 'content');
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
**Manual Signing:**
|
|
901
|
+
|
|
902
|
+
```typescript
|
|
903
|
+
import { signRequest } from '@lifestream-vault/sdk';
|
|
904
|
+
|
|
905
|
+
const headers = signRequest(
|
|
906
|
+
'lsv_k_your_api_key',
|
|
907
|
+
'POST',
|
|
908
|
+
'/api/v1/vaults',
|
|
909
|
+
JSON.stringify({ name: 'My Vault' }),
|
|
910
|
+
);
|
|
911
|
+
|
|
912
|
+
console.log(headers['X-Signature']); // HMAC signature
|
|
913
|
+
console.log(headers['X-Signature-Timestamp']); // ISO timestamp
|
|
914
|
+
console.log(headers['X-Signature-Nonce']); // Random nonce
|
|
915
|
+
```
|
|
916
|
+
|
|
917
|
+
### Audit Logging
|
|
918
|
+
|
|
919
|
+
Enable client-side request logging for compliance and debugging.
|
|
920
|
+
|
|
921
|
+
```typescript
|
|
922
|
+
const client = new LifestreamVaultClient({
|
|
923
|
+
baseUrl: 'https://vault.example.com',
|
|
924
|
+
apiKey: 'lsv_k_your_api_key',
|
|
925
|
+
enableAuditLogging: true,
|
|
926
|
+
auditLogPath: '/var/log/lsvault/audit.log',
|
|
927
|
+
});
|
|
928
|
+
|
|
929
|
+
// All requests are now logged to the audit file
|
|
930
|
+
await client.vaults.list();
|
|
931
|
+
|
|
932
|
+
// Log entry format:
|
|
933
|
+
// {"timestamp":"2026-02-14T10:30:00.000Z","method":"GET","path":"/api/v1/vaults","status":200,"durationMs":145}
|
|
934
|
+
```
|
|
935
|
+
|
|
936
|
+
**Standalone Audit Logger:**
|
|
937
|
+
|
|
938
|
+
```typescript
|
|
939
|
+
import { AuditLogger } from '@lifestream-vault/sdk';
|
|
940
|
+
|
|
941
|
+
const logger = new AuditLogger({ logPath: './custom-audit.log' });
|
|
942
|
+
|
|
943
|
+
logger.log({
|
|
944
|
+
timestamp: new Date().toISOString(),
|
|
945
|
+
method: 'POST',
|
|
946
|
+
path: '/api/v1/vaults',
|
|
947
|
+
status: 201,
|
|
948
|
+
durationMs: 234,
|
|
949
|
+
});
|
|
950
|
+
```
|
|
951
|
+
|
|
952
|
+
### Client-Side Encryption
|
|
953
|
+
|
|
954
|
+
Encrypt vault content client-side before uploading (requires encryption-enabled vault).
|
|
955
|
+
|
|
956
|
+
```typescript
|
|
957
|
+
import { generateVaultKey, encryptContent, decryptContent } from '@lifestream-vault/sdk';
|
|
958
|
+
|
|
959
|
+
// Generate a vault encryption key (save this securely!)
|
|
960
|
+
const vaultKey = generateVaultKey();
|
|
961
|
+
console.log('Save this key:', vaultKey); // Base64-encoded AES-256 key
|
|
962
|
+
|
|
963
|
+
// Create an encryption-enabled vault
|
|
964
|
+
const vault = await client.vaults.create({
|
|
965
|
+
name: 'Secure Vault',
|
|
966
|
+
encryptionEnabled: true,
|
|
967
|
+
});
|
|
968
|
+
|
|
969
|
+
// Encrypt content before uploading
|
|
970
|
+
const plaintext = '# Secret Document\n\nSensitive information here.';
|
|
971
|
+
const encrypted = encryptContent(plaintext, vaultKey);
|
|
972
|
+
|
|
973
|
+
await client.documents.put(vault.id, 'secret.md', encrypted);
|
|
974
|
+
|
|
975
|
+
// Decrypt when reading
|
|
976
|
+
const doc = await client.documents.get(vault.id, 'secret.md');
|
|
977
|
+
const decrypted = decryptContent(doc.content, vaultKey);
|
|
978
|
+
console.log(decrypted); // Original plaintext
|
|
979
|
+
```
|
|
980
|
+
|
|
981
|
+
**Note:** The server never sees your encryption key. Store it securely and never lose itβthere's no recovery mechanism.
|
|
982
|
+
|
|
983
|
+
### Token Management Utilities
|
|
984
|
+
|
|
985
|
+
```typescript
|
|
986
|
+
import { decodeJwtPayload, isTokenExpired } from '@lifestream-vault/sdk';
|
|
987
|
+
|
|
988
|
+
const token = 'eyJhbGci...';
|
|
989
|
+
|
|
990
|
+
// Decode JWT payload without verification
|
|
991
|
+
const payload = decodeJwtPayload(token);
|
|
992
|
+
console.log(payload.userId, payload.email);
|
|
993
|
+
|
|
994
|
+
// Check if token is expired
|
|
995
|
+
if (isTokenExpired(token)) {
|
|
996
|
+
console.log('Token has expired, need to refresh');
|
|
997
|
+
}
|
|
998
|
+
```
|
|
999
|
+
|
|
1000
|
+
### Direct HTTP Access
|
|
1001
|
+
|
|
1002
|
+
Access the underlying `ky` HTTP client for custom requests:
|
|
1003
|
+
|
|
1004
|
+
```typescript
|
|
1005
|
+
const client = new LifestreamVaultClient({
|
|
1006
|
+
baseUrl: 'https://vault.example.com',
|
|
1007
|
+
apiKey: 'lsv_k_your_api_key',
|
|
1008
|
+
});
|
|
1009
|
+
|
|
1010
|
+
// Make custom API requests
|
|
1011
|
+
const response = await client.http.get('custom/endpoint').json();
|
|
1012
|
+
|
|
1013
|
+
// The client is pre-configured with:
|
|
1014
|
+
// - Authentication headers
|
|
1015
|
+
// - Base URL (https://vault.example.com/api/v1)
|
|
1016
|
+
// - Timeout settings
|
|
1017
|
+
// - Request signing (if enabled)
|
|
1018
|
+
```
|
|
1019
|
+
|
|
1020
|
+
## π Documentation
|
|
1021
|
+
|
|
1022
|
+
For complete API documentation, guides, and examples, visit:
|
|
1023
|
+
|
|
1024
|
+
**[https://vault.lifestreamdynamics.com/docs](https://vault.lifestreamdynamics.com/docs)**
|
|
1025
|
+
|
|
1026
|
+
### Additional Resources
|
|
1027
|
+
|
|
1028
|
+
- **API Reference**: Full OpenAPI spec at your server's `/api/docs`
|
|
1029
|
+
- **Integration Guides**: Step-by-step tutorials for common use cases
|
|
1030
|
+
- **Best Practices**: Security, performance, and architecture recommendations
|
|
1031
|
+
- **Migration Guides**: Upgrade paths for major version changes
|
|
1032
|
+
|
|
1033
|
+
## π Related Packages
|
|
1034
|
+
|
|
1035
|
+
- **[@lifestream-vault/cli](https://www.npmjs.com/package/@lifestream-vault/cli)** - Command-line interface for Lifestream Vault
|
|
1036
|
+
- **[@lifestream-vault/shared](https://www.npmjs.com/package/@lifestream-vault/shared)** - Shared types and schemas
|
|
1037
|
+
|
|
1038
|
+
## π Troubleshooting
|
|
1039
|
+
|
|
1040
|
+
### Connection Issues
|
|
1041
|
+
|
|
1042
|
+
**Problem:** `NetworkError: Failed to fetch`
|
|
1043
|
+
|
|
1044
|
+
**Solutions:**
|
|
1045
|
+
- β
Verify the `baseUrl` is correct and accessible
|
|
1046
|
+
- β
Check network connectivity
|
|
1047
|
+
- β
Ensure CORS is configured on the server (for browser usage)
|
|
1048
|
+
- β
Try increasing the `timeout` option
|
|
1049
|
+
|
|
1050
|
+
### Authentication Failures
|
|
1051
|
+
|
|
1052
|
+
**Problem:** `AuthenticationError: Invalid credentials`
|
|
1053
|
+
|
|
1054
|
+
**Solutions:**
|
|
1055
|
+
- β
Verify your API key or JWT token is valid
|
|
1056
|
+
- β
Check that the API key starts with `lsv_k_`
|
|
1057
|
+
- β
Ensure the token hasn't expired
|
|
1058
|
+
- β
For JWT auth, verify the `refreshToken` is correct
|
|
1059
|
+
|
|
1060
|
+
### Rate Limiting
|
|
1061
|
+
|
|
1062
|
+
**Problem:** `RateLimitError: Too many requests`
|
|
1063
|
+
|
|
1064
|
+
**Solutions:**
|
|
1065
|
+
- β
Implement exponential backoff retry logic
|
|
1066
|
+
- β
Reduce request frequency
|
|
1067
|
+
- β
Consider upgrading your subscription plan
|
|
1068
|
+
- β
Cache frequently accessed data
|
|
1069
|
+
|
|
1070
|
+
### TypeScript Errors
|
|
1071
|
+
|
|
1072
|
+
**Problem:** Type errors when importing
|
|
1073
|
+
|
|
1074
|
+
**Solutions:**
|
|
1075
|
+
- β
Ensure TypeScript version is 5.0 or higher
|
|
1076
|
+
- β
Check that `moduleResolution` is set to `node16` or `bundler` in `tsconfig.json`
|
|
1077
|
+
- β
Verify `"type": "module"` in your `package.json` for ESM projects
|
|
1078
|
+
|
|
1079
|
+
### HMAC Signature Failures
|
|
1080
|
+
|
|
1081
|
+
**Problem:** `AuthorizationError: Invalid signature`
|
|
1082
|
+
|
|
1083
|
+
**Solutions:**
|
|
1084
|
+
- β
Ensure server and client clocks are synchronized
|
|
1085
|
+
- β
Verify `enableRequestSigning` is enabled on the client
|
|
1086
|
+
- β
Check that the API key is correct and has signing permissions
|
|
1087
|
+
- β
Ensure no middleware is modifying request bodies
|
|
1088
|
+
|
|
1089
|
+
### Token Refresh Not Working
|
|
1090
|
+
|
|
1091
|
+
**Problem:** `AuthenticationError` despite having a refresh token
|
|
1092
|
+
|
|
1093
|
+
**Solutions:**
|
|
1094
|
+
- β
Verify `refreshToken` is provided in `ClientOptions`
|
|
1095
|
+
- β
Check that the refresh token hasn't expired
|
|
1096
|
+
- β
Ensure `onTokenRefresh` callback is saving new tokens
|
|
1097
|
+
- β
Verify server-side refresh endpoint is accessible
|
|
1098
|
+
|
|
1099
|
+
## π¬ Support
|
|
1100
|
+
|
|
1101
|
+
Need help? We're here for you!
|
|
1102
|
+
|
|
1103
|
+
- **GitHub Issues**: [Report bugs or request features](https://github.com/lifestreamdynamics/lifestream-vault-sdk/issues)
|
|
1104
|
+
- **Email**: eric@lifestreamdynamics.com
|
|
1105
|
+
- **Documentation**: [vault.lifestreamdynamics.com/docs](https://vault.lifestreamdynamics.com/docs)
|
|
1106
|
+
|
|
1107
|
+
When reporting issues, please include:
|
|
1108
|
+
- SDK version (`npm list @lifestream-vault/sdk`)
|
|
1109
|
+
- Node.js version (`node --version`)
|
|
1110
|
+
- Error messages and stack traces
|
|
1111
|
+
- Minimal reproduction code (without sensitive credentials)
|
|
1112
|
+
|
|
1113
|
+
## π License
|
|
1114
|
+
|
|
1115
|
+
MIT License - see [LICENSE](./LICENSE) file for details.
|
|
1116
|
+
|
|
1117
|
+
Copyright (c) 2025-2026 Lifestream Dynamics
|
|
1118
|
+
|
|
1119
|
+
---
|
|
1120
|
+
|
|
1121
|
+
**Built with β€οΈ by [Lifestream Dynamics](https://lifestreamdynamics.com)**
|