@syncvault/sdk 1.0.0 → 1.1.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 CHANGED
@@ -105,33 +105,59 @@ List all files for this app.
105
105
  #### `vault.delete(path)`
106
106
  Delete a file.
107
107
 
108
- ### Metadata Methods
108
+ ### Metadata Methods (Preferences)
109
109
 
110
- App metadata is unencrypted data stored server-side. Use it for app-specific logic like subscription status, feature flags, or user preferences that don't need encryption.
110
+ Metadata is unencrypted data for app preferences like theme, timezone, language. Use it for settings that don't need encryption and are needed for app logic.
111
111
 
112
112
  #### `vault.getMetadata()`
113
- Get app metadata for the current user.
113
+ Get preferences for the current user.
114
114
 
115
115
  #### `vault.setMetadata(metadata)`
116
- Set app metadata (replaces all existing metadata).
116
+ Set preferences (replaces all existing).
117
117
 
118
118
  #### `vault.updateMetadata(metadata)`
119
- Update app metadata (merges with existing metadata).
119
+ Update preferences (merges with existing).
120
120
 
121
121
  ```javascript
122
- // Example: Store subscription status
122
+ // Example: Store user preferences
123
123
  await vault.setMetadata({
124
- subscriptionActive: true,
125
- subscriptionExpiresAt: '2026-12-31',
126
- plan: 'premium'
124
+ theme: 'dark',
125
+ timezone: 'UTC',
126
+ language: 'en'
127
127
  });
128
128
 
129
- // Read metadata
130
- const meta = await vault.getMetadata();
131
- console.log(meta.subscriptionActive); // true
129
+ // Read preferences
130
+ const prefs = await vault.getMetadata();
131
+ console.log(prefs.theme); // 'dark'
132
132
 
133
133
  // Update specific fields
134
- await vault.updateMetadata({ lastLogin: new Date().toISOString() });
134
+ await vault.updateMetadata({ language: 'es' });
135
+ ```
136
+
137
+ ### Entitlements Methods
138
+
139
+ Entitlements are read-only data set by the developer's backend. Use them for subscription status, feature flags, etc. Users can read but not modify entitlements.
140
+
141
+ #### `vault.getEntitlements()`
142
+ Get entitlements for the current user.
143
+
144
+ ```javascript
145
+ // Read entitlements (set by developer backend)
146
+ const entitlements = await vault.getEntitlements();
147
+ console.log(entitlements.plan); // 'premium'
148
+ console.log(entitlements.features); // ['advanced', 'export']
149
+ ```
150
+
151
+ ### Quota Methods
152
+
153
+ #### `vault.getQuota()`
154
+ Get user's storage quota information.
155
+
156
+ ```javascript
157
+ const quota = await vault.getQuota();
158
+ console.log(quota.quotaBytes); // 10485760 (10MB) or null if unlimited
159
+ console.log(quota.usedBytes); // 1048576 (1MB)
160
+ console.log(quota.unlimited); // false
135
161
  ```
136
162
 
137
163
  ### State Methods
@@ -158,4 +184,29 @@ Users see these permissions during OAuth authorization.
158
184
 
159
185
  All data is encrypted client-side using AES-256-GCM with a key derived from the user's password using PBKDF2 (100,000 iterations). The server never sees unencrypted data.
160
186
 
161
- Note: Metadata is NOT encrypted - use it only for non-sensitive app logic.
187
+ Note: Metadata (preferences) and entitlements are NOT encrypted - use them only for non-sensitive settings and subscription status.
188
+
189
+ ## Setting Entitlements (Developer Backend)
190
+
191
+ Entitlements can only be set from your backend using both the app token and secret token:
192
+
193
+ ```javascript
194
+ // On your backend (e.g., after payment webhook)
195
+ await fetch(`https://api.syncvault.dev/api/entitlements/${userId}`, {
196
+ method: 'PUT',
197
+ headers: {
198
+ 'Content-Type': 'application/json',
199
+ 'X-App-Token': process.env.SYNCVAULT_APP_TOKEN,
200
+ 'X-Secret-Token': process.env.SYNCVAULT_SECRET_TOKEN
201
+ },
202
+ body: JSON.stringify({
203
+ entitlements: {
204
+ plan: 'premium',
205
+ features: ['advanced', 'export'],
206
+ expiresAt: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toISOString()
207
+ }
208
+ })
209
+ });
210
+ ```
211
+
212
+ Never expose the secret token in client-side code.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@syncvault/sdk",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "SyncVault SDK - Zero-knowledge encrypted sync for Node.js and browsers",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/index.d.ts CHANGED
@@ -27,6 +27,14 @@ export interface DeleteResponse {
27
27
 
28
28
  export type Metadata = Record<string, unknown>;
29
29
 
30
+ export type Entitlements = Record<string, unknown>;
31
+
32
+ export interface QuotaInfo {
33
+ quotaBytes: number | null;
34
+ usedBytes: number;
35
+ unlimited: boolean;
36
+ }
37
+
30
38
  export declare class SyncVault {
31
39
  constructor(options: SyncVaultOptions);
32
40
 
@@ -45,11 +53,17 @@ export declare class SyncVault {
45
53
  list(): Promise<FileInfo[]>;
46
54
  delete(path: string): Promise<DeleteResponse>;
47
55
 
48
- // Metadata operations (unencrypted server-side data)
56
+ // Metadata operations (unencrypted, for app preferences like theme, timezone)
49
57
  getMetadata<T extends Metadata = Metadata>(): Promise<T>;
50
58
  setMetadata<T extends Metadata = Metadata>(metadata: T): Promise<T>;
51
59
  updateMetadata<T extends Metadata = Metadata>(metadata: Partial<T>): Promise<T>;
52
60
 
61
+ // Entitlements (read-only, set by developer's backend for subscriptions, feature flags)
62
+ getEntitlements<T extends Entitlements = Entitlements>(): Promise<T>;
63
+
64
+ // Quota info
65
+ getQuota(): Promise<QuotaInfo>;
66
+
53
67
  // State
54
68
  isAuthenticated(): boolean;
55
69
  logout(): void;
package/src/index.js CHANGED
@@ -2,6 +2,15 @@ import { encrypt, decrypt, prepareAuthPassword } from './crypto.js';
2
2
 
3
3
  const DEFAULT_SERVER = 'https://api.syncvault.dev';
4
4
 
5
+ export class SyncVaultError extends Error {
6
+ constructor(message, statusCode, data) {
7
+ super(message);
8
+ this.name = 'SyncVaultError';
9
+ this.statusCode = statusCode;
10
+ this.data = data;
11
+ }
12
+ }
13
+
5
14
  export class SyncVault {
6
15
  constructor(options = {}) {
7
16
  if (!options.appToken) {
@@ -186,6 +195,26 @@ export class SyncVault {
186
195
  return response.metadata;
187
196
  }
188
197
 
198
+ /**
199
+ * Get entitlements for current user (read-only, set by developer's backend)
200
+ * Entitlements are used for subscription status, feature flags, etc.
201
+ */
202
+ async getEntitlements() {
203
+ this._checkAuth();
204
+
205
+ const response = await this._request('/api/sync/entitlements');
206
+ return response.entitlements;
207
+ }
208
+
209
+ /**
210
+ * Get user storage quota info for the current app
211
+ */
212
+ async getQuota() {
213
+ this._checkAuth();
214
+
215
+ return this._request('/api/sync/quota');
216
+ }
217
+
189
218
  /**
190
219
  * Check if user is authenticated
191
220
  */
@@ -239,7 +268,11 @@ export class SyncVault {
239
268
  const data = await response.json();
240
269
 
241
270
  if (!response.ok) {
242
- throw new Error(data.error || 'Request failed');
271
+ throw new SyncVaultError(
272
+ data.error || 'Request failed',
273
+ response.status,
274
+ data
275
+ );
243
276
  }
244
277
 
245
278
  return data;