@vaiftechnologies/vaif-client 0.1.1 → 0.2.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 +554 -0
- package/dist/{index.mjs → index.cjs} +1339 -150
- package/dist/{index.d.mts → index.d.cts} +1407 -100
- package/dist/index.d.ts +1407 -100
- package/dist/index.js +1280 -189
- package/package.json +7 -4
|
@@ -1,3 +1,166 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
RealtimeChannel: () => RealtimeChannel,
|
|
24
|
+
VaifAI: () => VaifAI,
|
|
25
|
+
VaifAdmin: () => VaifAdmin,
|
|
26
|
+
VaifApiKeys: () => VaifApiKeys,
|
|
27
|
+
VaifAuth: () => VaifAuth,
|
|
28
|
+
VaifAuthError: () => VaifAuthError,
|
|
29
|
+
VaifClient: () => VaifClient,
|
|
30
|
+
VaifConflictError: () => VaifConflictError,
|
|
31
|
+
VaifDatabase: () => VaifDatabase,
|
|
32
|
+
VaifError: () => VaifError,
|
|
33
|
+
VaifFunctions: () => VaifFunctions,
|
|
34
|
+
VaifIntegrations: () => VaifIntegrations,
|
|
35
|
+
VaifNetworkError: () => VaifNetworkError,
|
|
36
|
+
VaifNotFoundError: () => VaifNotFoundError,
|
|
37
|
+
VaifProjects: () => VaifProjects,
|
|
38
|
+
VaifRateLimitError: () => VaifRateLimitError,
|
|
39
|
+
VaifRealtime: () => VaifRealtime,
|
|
40
|
+
VaifSchema: () => VaifSchema,
|
|
41
|
+
VaifStorage: () => VaifStorage,
|
|
42
|
+
VaifTimeoutError: () => VaifTimeoutError,
|
|
43
|
+
VaifTypeGen: () => VaifTypeGen,
|
|
44
|
+
VaifValidationError: () => VaifValidationError,
|
|
45
|
+
createClient: () => createClient,
|
|
46
|
+
createTypeGen: () => createTypeGen,
|
|
47
|
+
createVaifClient: () => createClient,
|
|
48
|
+
isVaifAuthError: () => isVaifAuthError,
|
|
49
|
+
isVaifConflictError: () => isVaifConflictError,
|
|
50
|
+
isVaifError: () => isVaifError,
|
|
51
|
+
isVaifNetworkError: () => isVaifNetworkError,
|
|
52
|
+
isVaifNotFoundError: () => isVaifNotFoundError,
|
|
53
|
+
isVaifRateLimitError: () => isVaifRateLimitError,
|
|
54
|
+
isVaifTimeoutError: () => isVaifTimeoutError,
|
|
55
|
+
isVaifValidationError: () => isVaifValidationError
|
|
56
|
+
});
|
|
57
|
+
module.exports = __toCommonJS(index_exports);
|
|
58
|
+
|
|
59
|
+
// src/errors.ts
|
|
60
|
+
var VaifError = class _VaifError extends Error {
|
|
61
|
+
constructor(message, options) {
|
|
62
|
+
super(message);
|
|
63
|
+
this.name = "VaifError";
|
|
64
|
+
this.code = options.code;
|
|
65
|
+
this.statusCode = options.statusCode;
|
|
66
|
+
this.requestId = options.requestId;
|
|
67
|
+
this.details = options.details;
|
|
68
|
+
const ErrorWithCapture = Error;
|
|
69
|
+
if (ErrorWithCapture.captureStackTrace) {
|
|
70
|
+
ErrorWithCapture.captureStackTrace(this, _VaifError);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
toJSON() {
|
|
74
|
+
return {
|
|
75
|
+
name: this.name,
|
|
76
|
+
message: this.message,
|
|
77
|
+
code: this.code,
|
|
78
|
+
statusCode: this.statusCode,
|
|
79
|
+
requestId: this.requestId,
|
|
80
|
+
details: this.details
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
var VaifAuthError = class extends VaifError {
|
|
85
|
+
constructor(message, options) {
|
|
86
|
+
super(message, {
|
|
87
|
+
code: options?.code ?? "AUTH_ERROR",
|
|
88
|
+
statusCode: options?.statusCode ?? 401,
|
|
89
|
+
requestId: options?.requestId
|
|
90
|
+
});
|
|
91
|
+
this.name = "VaifAuthError";
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
var VaifValidationError = class extends VaifError {
|
|
95
|
+
constructor(message, options) {
|
|
96
|
+
super(message, {
|
|
97
|
+
code: "VALIDATION_ERROR",
|
|
98
|
+
statusCode: 400,
|
|
99
|
+
requestId: options?.requestId,
|
|
100
|
+
details: options?.details ?? options?.fieldErrors
|
|
101
|
+
});
|
|
102
|
+
this.name = "VaifValidationError";
|
|
103
|
+
this.fieldErrors = options?.fieldErrors;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
var VaifNetworkError = class extends VaifError {
|
|
107
|
+
constructor(message, cause) {
|
|
108
|
+
super(message, { code: "NETWORK_ERROR" });
|
|
109
|
+
this.name = "VaifNetworkError";
|
|
110
|
+
this.cause = cause;
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
var VaifRateLimitError = class extends VaifError {
|
|
114
|
+
constructor(message, retryAfter) {
|
|
115
|
+
super(message, { code: "RATE_LIMITED", statusCode: 429 });
|
|
116
|
+
this.name = "VaifRateLimitError";
|
|
117
|
+
this.retryAfter = retryAfter;
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
var VaifNotFoundError = class extends VaifError {
|
|
121
|
+
constructor(message, requestId) {
|
|
122
|
+
super(message, { code: "NOT_FOUND", statusCode: 404, requestId });
|
|
123
|
+
this.name = "VaifNotFoundError";
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
var VaifConflictError = class extends VaifError {
|
|
127
|
+
constructor(message, requestId) {
|
|
128
|
+
super(message, { code: "CONFLICT", statusCode: 409, requestId });
|
|
129
|
+
this.name = "VaifConflictError";
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
var VaifTimeoutError = class extends VaifNetworkError {
|
|
133
|
+
constructor(message, timeoutMs) {
|
|
134
|
+
super(message);
|
|
135
|
+
this.name = "VaifTimeoutError";
|
|
136
|
+
this.timeoutMs = timeoutMs;
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
function isVaifError(error) {
|
|
140
|
+
return error instanceof VaifError;
|
|
141
|
+
}
|
|
142
|
+
function isVaifAuthError(error) {
|
|
143
|
+
return error instanceof VaifAuthError;
|
|
144
|
+
}
|
|
145
|
+
function isVaifValidationError(error) {
|
|
146
|
+
return error instanceof VaifValidationError;
|
|
147
|
+
}
|
|
148
|
+
function isVaifNetworkError(error) {
|
|
149
|
+
return error instanceof VaifNetworkError;
|
|
150
|
+
}
|
|
151
|
+
function isVaifRateLimitError(error) {
|
|
152
|
+
return error instanceof VaifRateLimitError;
|
|
153
|
+
}
|
|
154
|
+
function isVaifNotFoundError(error) {
|
|
155
|
+
return error instanceof VaifNotFoundError;
|
|
156
|
+
}
|
|
157
|
+
function isVaifConflictError(error) {
|
|
158
|
+
return error instanceof VaifConflictError;
|
|
159
|
+
}
|
|
160
|
+
function isVaifTimeoutError(error) {
|
|
161
|
+
return error instanceof VaifTimeoutError;
|
|
162
|
+
}
|
|
163
|
+
|
|
1
164
|
// src/lib/database.ts
|
|
2
165
|
var VaifDatabase = class {
|
|
3
166
|
constructor(client) {
|
|
@@ -6,6 +169,9 @@ var VaifDatabase = class {
|
|
|
6
169
|
/**
|
|
7
170
|
* Start a query on a table
|
|
8
171
|
*
|
|
172
|
+
* @param table - Table name to query
|
|
173
|
+
* @returns A query builder for chaining operations
|
|
174
|
+
*
|
|
9
175
|
* @example
|
|
10
176
|
* ```typescript
|
|
11
177
|
* const users = await vaif.db.from('users').select('*').execute();
|
|
@@ -17,6 +183,10 @@ var VaifDatabase = class {
|
|
|
17
183
|
/**
|
|
18
184
|
* Execute raw SQL query (admin only)
|
|
19
185
|
*
|
|
186
|
+
* @param sql - SQL query string with $1, $2, etc. parameter placeholders
|
|
187
|
+
* @param params - Parameter values for the query
|
|
188
|
+
* @returns Query result with typed rows
|
|
189
|
+
*
|
|
20
190
|
* @example
|
|
21
191
|
* ```typescript
|
|
22
192
|
* const result = await vaif.db.raw('SELECT * FROM users WHERE id = $1', [userId]);
|
|
@@ -44,7 +214,16 @@ var VaifDatabase = class {
|
|
|
44
214
|
};
|
|
45
215
|
}
|
|
46
216
|
/**
|
|
47
|
-
* Execute a
|
|
217
|
+
* Execute a stored procedure (RPC call)
|
|
218
|
+
*
|
|
219
|
+
* @param functionName - Name of the database function to call
|
|
220
|
+
* @param params - Parameters to pass to the function
|
|
221
|
+
* @returns Query result with the function's return value
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* ```typescript
|
|
225
|
+
* const result = await vaif.db.rpc('get_user_stats', { userId: '123' });
|
|
226
|
+
* ```
|
|
48
227
|
*/
|
|
49
228
|
async rpc(functionName, params) {
|
|
50
229
|
const response = await this.client.request(`/db/rpc/${functionName}`, {
|
|
@@ -133,72 +312,85 @@ var QueryBuilder = class {
|
|
|
133
312
|
this.onConflictUpdate = data;
|
|
134
313
|
return this;
|
|
135
314
|
}
|
|
136
|
-
|
|
315
|
+
/** Filter by equality (column = value) */
|
|
137
316
|
eq(column, value) {
|
|
138
317
|
this.addFilter(column, this.negateNext ? "neq" : "eq", value);
|
|
139
318
|
this.negateNext = false;
|
|
140
319
|
return this;
|
|
141
320
|
}
|
|
321
|
+
/** Filter by inequality (column != value) */
|
|
142
322
|
neq(column, value) {
|
|
143
323
|
this.addFilter(column, this.negateNext ? "eq" : "neq", value);
|
|
144
324
|
this.negateNext = false;
|
|
145
325
|
return this;
|
|
146
326
|
}
|
|
327
|
+
/** Filter by greater than (column > value) */
|
|
147
328
|
gt(column, value) {
|
|
148
329
|
this.addFilter(column, this.negateNext ? "lte" : "gt", value);
|
|
149
330
|
this.negateNext = false;
|
|
150
331
|
return this;
|
|
151
332
|
}
|
|
333
|
+
/** Filter by greater than or equal (column >= value) */
|
|
152
334
|
gte(column, value) {
|
|
153
335
|
this.addFilter(column, this.negateNext ? "lt" : "gte", value);
|
|
154
336
|
this.negateNext = false;
|
|
155
337
|
return this;
|
|
156
338
|
}
|
|
339
|
+
/** Filter by less than (column < value) */
|
|
157
340
|
lt(column, value) {
|
|
158
341
|
this.addFilter(column, this.negateNext ? "gte" : "lt", value);
|
|
159
342
|
this.negateNext = false;
|
|
160
343
|
return this;
|
|
161
344
|
}
|
|
345
|
+
/** Filter by less than or equal (column <= value) */
|
|
162
346
|
lte(column, value) {
|
|
163
347
|
this.addFilter(column, this.negateNext ? "gt" : "lte", value);
|
|
164
348
|
this.negateNext = false;
|
|
165
349
|
return this;
|
|
166
350
|
}
|
|
351
|
+
/** Filter by pattern matching (case-sensitive LIKE) */
|
|
167
352
|
like(column, pattern) {
|
|
168
353
|
this.addFilter(column, this.negateNext ? "nlike" : "like", pattern);
|
|
169
354
|
this.negateNext = false;
|
|
170
355
|
return this;
|
|
171
356
|
}
|
|
357
|
+
/** Filter by pattern matching (case-insensitive ILIKE) */
|
|
172
358
|
ilike(column, pattern) {
|
|
173
359
|
this.addFilter(column, this.negateNext ? "nilike" : "ilike", pattern);
|
|
174
360
|
this.negateNext = false;
|
|
175
361
|
return this;
|
|
176
362
|
}
|
|
363
|
+
/** Filter by IS (null/boolean checks) */
|
|
177
364
|
is(column, value) {
|
|
178
365
|
this.addFilter(column, this.negateNext ? "isnot" : "is", value);
|
|
179
366
|
this.negateNext = false;
|
|
180
367
|
return this;
|
|
181
368
|
}
|
|
369
|
+
/** Filter by inclusion in an array of values */
|
|
182
370
|
in(column, values) {
|
|
183
371
|
this.addFilter(column, this.negateNext ? "nin" : "in", values);
|
|
184
372
|
this.negateNext = false;
|
|
185
373
|
return this;
|
|
186
374
|
}
|
|
375
|
+
/** Filter by array containment (@>) */
|
|
187
376
|
contains(column, value) {
|
|
188
377
|
this.addFilter(column, "cs", value);
|
|
189
378
|
this.negateNext = false;
|
|
190
379
|
return this;
|
|
191
380
|
}
|
|
381
|
+
/** Filter by array being contained by (<@) */
|
|
192
382
|
containedBy(column, value) {
|
|
193
383
|
this.addFilter(column, "cd", value);
|
|
194
384
|
this.negateNext = false;
|
|
195
385
|
return this;
|
|
196
386
|
}
|
|
387
|
+
/** Filter by array overlap (&&) */
|
|
197
388
|
overlaps(column, value) {
|
|
198
389
|
this.addFilter(column, "ov", value);
|
|
199
390
|
this.negateNext = false;
|
|
200
391
|
return this;
|
|
201
392
|
}
|
|
393
|
+
/** Full-text search filter */
|
|
202
394
|
textSearch(column, query, options) {
|
|
203
395
|
this.addFilter(column, "fts", query, options?.config);
|
|
204
396
|
this.negateNext = false;
|
|
@@ -1813,6 +2005,42 @@ var VaifAI = class {
|
|
|
1813
2005
|
}
|
|
1814
2006
|
return { data: response.data, error: null };
|
|
1815
2007
|
}
|
|
2008
|
+
/**
|
|
2009
|
+
* Generate a plan for schema or other tasks using AI
|
|
2010
|
+
*
|
|
2011
|
+
* @example
|
|
2012
|
+
* ```typescript
|
|
2013
|
+
* const { data, error } = await vaif.ai.generatePlan({
|
|
2014
|
+
* projectId: 'your-project-id',
|
|
2015
|
+
* prompt: 'Create a users table with email and password',
|
|
2016
|
+
* taskType: 'plan_schema',
|
|
2017
|
+
* mode: 'balanced'
|
|
2018
|
+
* });
|
|
2019
|
+
* ```
|
|
2020
|
+
*/
|
|
2021
|
+
async generatePlan(request) {
|
|
2022
|
+
const response = await this.client.request("/ai/plan", {
|
|
2023
|
+
method: "POST",
|
|
2024
|
+
body: request
|
|
2025
|
+
});
|
|
2026
|
+
if (response.error) {
|
|
2027
|
+
return {
|
|
2028
|
+
ok: false,
|
|
2029
|
+
plan: { steps: [] },
|
|
2030
|
+
costEstimateCents: 0,
|
|
2031
|
+
error: {
|
|
2032
|
+
message: response.error.message,
|
|
2033
|
+
code: response.error.code,
|
|
2034
|
+
status: response.status
|
|
2035
|
+
}
|
|
2036
|
+
};
|
|
2037
|
+
}
|
|
2038
|
+
return response.data ?? {
|
|
2039
|
+
ok: false,
|
|
2040
|
+
plan: { steps: [] },
|
|
2041
|
+
costEstimateCents: 0
|
|
2042
|
+
};
|
|
2043
|
+
}
|
|
1816
2044
|
/**
|
|
1817
2045
|
* Generate SQL migration from schema diff
|
|
1818
2046
|
*/
|
|
@@ -1838,6 +2066,260 @@ var VaifAI = class {
|
|
|
1838
2066
|
}
|
|
1839
2067
|
return { data: response.data, error: null };
|
|
1840
2068
|
}
|
|
2069
|
+
/**
|
|
2070
|
+
* Get Copilot observability metrics for the current project
|
|
2071
|
+
*
|
|
2072
|
+
* @example
|
|
2073
|
+
* ```typescript
|
|
2074
|
+
* const { data, error } = await vaif.ai.getCopilotMetrics({ range: '24h' });
|
|
2075
|
+
* console.log(`Success rate: ${data.summary.successRate}%`);
|
|
2076
|
+
* console.log(`Total tokens: ${data.summary.totalTokens}`);
|
|
2077
|
+
* ```
|
|
2078
|
+
*/
|
|
2079
|
+
async getCopilotMetrics(options = {}) {
|
|
2080
|
+
const config = this.client.getConfig();
|
|
2081
|
+
const range = options.range ?? "24h";
|
|
2082
|
+
const response = await this.client.request(
|
|
2083
|
+
`/copilot/metrics/${config.projectId}?range=${range}`,
|
|
2084
|
+
{ method: "GET" }
|
|
2085
|
+
);
|
|
2086
|
+
if (response.error) {
|
|
2087
|
+
return {
|
|
2088
|
+
data: null,
|
|
2089
|
+
error: {
|
|
2090
|
+
message: response.error.message,
|
|
2091
|
+
code: response.error.code,
|
|
2092
|
+
status: response.status
|
|
2093
|
+
}
|
|
2094
|
+
};
|
|
2095
|
+
}
|
|
2096
|
+
return { data: response.data, error: null };
|
|
2097
|
+
}
|
|
2098
|
+
/**
|
|
2099
|
+
* Get Copilot observability metrics for an organization
|
|
2100
|
+
*
|
|
2101
|
+
* @example
|
|
2102
|
+
* ```typescript
|
|
2103
|
+
* const { data, error } = await vaif.ai.getCopilotOrgMetrics(orgId, { range: '7d' });
|
|
2104
|
+
* console.log(`Total requests: ${data.summary.totalRequests}`);
|
|
2105
|
+
* console.log(`Projects: ${data.summary.uniqueProjects}`);
|
|
2106
|
+
* ```
|
|
2107
|
+
*/
|
|
2108
|
+
async getCopilotOrgMetrics(orgId, options = {}) {
|
|
2109
|
+
const range = options.range ?? "24h";
|
|
2110
|
+
const response = await this.client.request(
|
|
2111
|
+
`/copilot/metrics/org/${orgId}?range=${range}`,
|
|
2112
|
+
{ method: "GET" }
|
|
2113
|
+
);
|
|
2114
|
+
if (response.error) {
|
|
2115
|
+
return {
|
|
2116
|
+
data: null,
|
|
2117
|
+
error: {
|
|
2118
|
+
message: response.error.message,
|
|
2119
|
+
code: response.error.code,
|
|
2120
|
+
status: response.status
|
|
2121
|
+
}
|
|
2122
|
+
};
|
|
2123
|
+
}
|
|
2124
|
+
return { data: response.data, error: null };
|
|
2125
|
+
}
|
|
2126
|
+
};
|
|
2127
|
+
|
|
2128
|
+
// src/lib/schema.ts
|
|
2129
|
+
var VaifSchema = class {
|
|
2130
|
+
constructor(client) {
|
|
2131
|
+
this.client = client;
|
|
2132
|
+
}
|
|
2133
|
+
/**
|
|
2134
|
+
* Preview schema changes without applying them
|
|
2135
|
+
*
|
|
2136
|
+
* @example
|
|
2137
|
+
* ```typescript
|
|
2138
|
+
* const result = await vaif.schema.preview({
|
|
2139
|
+
* projectId: 'your-project-id',
|
|
2140
|
+
* definition: {
|
|
2141
|
+
* tables: [
|
|
2142
|
+
* { name: 'users', columns: [{ name: 'id', type: 'uuid', primaryKey: true }] }
|
|
2143
|
+
* ]
|
|
2144
|
+
* }
|
|
2145
|
+
* });
|
|
2146
|
+
*
|
|
2147
|
+
* if (result.ok) {
|
|
2148
|
+
* console.log('Plan steps:', result.plan);
|
|
2149
|
+
* console.log('SQL:', result.upSql);
|
|
2150
|
+
* }
|
|
2151
|
+
* ```
|
|
2152
|
+
*/
|
|
2153
|
+
async preview(request) {
|
|
2154
|
+
const response = await this.client.request(
|
|
2155
|
+
"/schema-engine/preview",
|
|
2156
|
+
{
|
|
2157
|
+
method: "POST",
|
|
2158
|
+
body: request
|
|
2159
|
+
}
|
|
2160
|
+
);
|
|
2161
|
+
if (response.error) {
|
|
2162
|
+
return {
|
|
2163
|
+
ok: false,
|
|
2164
|
+
projectSchema: "",
|
|
2165
|
+
plan: [],
|
|
2166
|
+
upSql: "",
|
|
2167
|
+
downSql: "",
|
|
2168
|
+
warnings: [],
|
|
2169
|
+
error: {
|
|
2170
|
+
message: response.error.message,
|
|
2171
|
+
code: response.error.code,
|
|
2172
|
+
status: response.status,
|
|
2173
|
+
details: response.error.details
|
|
2174
|
+
}
|
|
2175
|
+
};
|
|
2176
|
+
}
|
|
2177
|
+
return response.data ?? {
|
|
2178
|
+
ok: false,
|
|
2179
|
+
projectSchema: "",
|
|
2180
|
+
plan: [],
|
|
2181
|
+
upSql: "",
|
|
2182
|
+
downSql: "",
|
|
2183
|
+
warnings: []
|
|
2184
|
+
};
|
|
2185
|
+
}
|
|
2186
|
+
/**
|
|
2187
|
+
* Apply schema changes to the database
|
|
2188
|
+
*
|
|
2189
|
+
* @example
|
|
2190
|
+
* ```typescript
|
|
2191
|
+
* const result = await vaif.schema.apply({
|
|
2192
|
+
* projectId: 'your-project-id',
|
|
2193
|
+
* definition: {
|
|
2194
|
+
* tables: [
|
|
2195
|
+
* { name: 'users', columns: [{ name: 'id', type: 'uuid', primaryKey: true }] }
|
|
2196
|
+
* ]
|
|
2197
|
+
* },
|
|
2198
|
+
* migrationName: 'add_users_table'
|
|
2199
|
+
* });
|
|
2200
|
+
*
|
|
2201
|
+
* if (result.ok) {
|
|
2202
|
+
* console.log('Applied:', result.appliedSteps, 'steps');
|
|
2203
|
+
* }
|
|
2204
|
+
* ```
|
|
2205
|
+
*/
|
|
2206
|
+
async apply(request) {
|
|
2207
|
+
const response = await this.client.request(
|
|
2208
|
+
"/schema-engine/apply",
|
|
2209
|
+
{
|
|
2210
|
+
method: "POST",
|
|
2211
|
+
body: request
|
|
2212
|
+
}
|
|
2213
|
+
);
|
|
2214
|
+
if (response.error) {
|
|
2215
|
+
return {
|
|
2216
|
+
ok: false,
|
|
2217
|
+
projectSchema: "",
|
|
2218
|
+
migration: {
|
|
2219
|
+
id: "",
|
|
2220
|
+
name: "",
|
|
2221
|
+
status: "failed",
|
|
2222
|
+
appliedAt: ""
|
|
2223
|
+
},
|
|
2224
|
+
appliedSteps: 0,
|
|
2225
|
+
error: {
|
|
2226
|
+
message: response.error.message,
|
|
2227
|
+
code: response.error.code,
|
|
2228
|
+
status: response.status,
|
|
2229
|
+
details: response.error.details
|
|
2230
|
+
}
|
|
2231
|
+
};
|
|
2232
|
+
}
|
|
2233
|
+
return response.data ?? {
|
|
2234
|
+
ok: false,
|
|
2235
|
+
projectSchema: "",
|
|
2236
|
+
migration: {
|
|
2237
|
+
id: "",
|
|
2238
|
+
name: "",
|
|
2239
|
+
status: "failed",
|
|
2240
|
+
appliedAt: ""
|
|
2241
|
+
},
|
|
2242
|
+
appliedSteps: 0
|
|
2243
|
+
};
|
|
2244
|
+
}
|
|
2245
|
+
/**
|
|
2246
|
+
* Introspect current database schema
|
|
2247
|
+
*
|
|
2248
|
+
* @example
|
|
2249
|
+
* ```typescript
|
|
2250
|
+
* const result = await vaif.schema.introspect('your-project-id');
|
|
2251
|
+
*
|
|
2252
|
+
* if (result.ok) {
|
|
2253
|
+
* console.log('Tables:', result.tables);
|
|
2254
|
+
* }
|
|
2255
|
+
* ```
|
|
2256
|
+
*/
|
|
2257
|
+
async introspect(projectId, envId) {
|
|
2258
|
+
const params = {};
|
|
2259
|
+
if (envId) {
|
|
2260
|
+
params.envId = envId;
|
|
2261
|
+
}
|
|
2262
|
+
const response = await this.client.request(
|
|
2263
|
+
`/schema-engine/introspect/${projectId}`,
|
|
2264
|
+
{ params }
|
|
2265
|
+
);
|
|
2266
|
+
if (response.error) {
|
|
2267
|
+
return {
|
|
2268
|
+
ok: false,
|
|
2269
|
+
schemaExists: false,
|
|
2270
|
+
tables: [],
|
|
2271
|
+
error: {
|
|
2272
|
+
message: response.error.message,
|
|
2273
|
+
code: response.error.code,
|
|
2274
|
+
status: response.status
|
|
2275
|
+
}
|
|
2276
|
+
};
|
|
2277
|
+
}
|
|
2278
|
+
return response.data ?? {
|
|
2279
|
+
ok: false,
|
|
2280
|
+
schemaExists: false,
|
|
2281
|
+
tables: []
|
|
2282
|
+
};
|
|
2283
|
+
}
|
|
2284
|
+
/**
|
|
2285
|
+
* Get migration history for a project
|
|
2286
|
+
*
|
|
2287
|
+
* @example
|
|
2288
|
+
* ```typescript
|
|
2289
|
+
* const result = await vaif.schema.getMigrations('your-project-id');
|
|
2290
|
+
*
|
|
2291
|
+
* if (result.ok) {
|
|
2292
|
+
* for (const migration of result.migrations) {
|
|
2293
|
+
* console.log(migration.name, migration.status);
|
|
2294
|
+
* }
|
|
2295
|
+
* }
|
|
2296
|
+
* ```
|
|
2297
|
+
*/
|
|
2298
|
+
async getMigrations(projectId, options) {
|
|
2299
|
+
const params = {};
|
|
2300
|
+
if (options?.limit) {
|
|
2301
|
+
params.limit = String(options.limit);
|
|
2302
|
+
}
|
|
2303
|
+
const response = await this.client.request(
|
|
2304
|
+
`/schema-engine/migrations/project/${projectId}`,
|
|
2305
|
+
{ params }
|
|
2306
|
+
);
|
|
2307
|
+
if (response.error) {
|
|
2308
|
+
return {
|
|
2309
|
+
ok: false,
|
|
2310
|
+
migrations: [],
|
|
2311
|
+
error: {
|
|
2312
|
+
message: response.error.message,
|
|
2313
|
+
code: response.error.code,
|
|
2314
|
+
status: response.status
|
|
2315
|
+
}
|
|
2316
|
+
};
|
|
2317
|
+
}
|
|
2318
|
+
return response.data ?? {
|
|
2319
|
+
ok: false,
|
|
2320
|
+
migrations: []
|
|
2321
|
+
};
|
|
2322
|
+
}
|
|
1841
2323
|
};
|
|
1842
2324
|
|
|
1843
2325
|
// src/lib/typegen.ts
|
|
@@ -1958,7 +2440,7 @@ var VaifTypeGen = class {
|
|
|
1958
2440
|
lines.push("");
|
|
1959
2441
|
}
|
|
1960
2442
|
}
|
|
1961
|
-
|
|
2443
|
+
const filteredTables = dbSchema.tables.filter((t) => {
|
|
1962
2444
|
if (tables.length > 0 && !tables.includes(t.name)) return false;
|
|
1963
2445
|
if (excludeTables.includes(t.name)) return false;
|
|
1964
2446
|
return true;
|
|
@@ -2050,7 +2532,7 @@ var VaifTypeGen = class {
|
|
|
2050
2532
|
lines.push("");
|
|
2051
2533
|
}
|
|
2052
2534
|
}
|
|
2053
|
-
|
|
2535
|
+
const filteredTables = (schema.tables || []).filter((t) => {
|
|
2054
2536
|
if (tables.length > 0 && !tables.includes(t.name)) return false;
|
|
2055
2537
|
if (excludeTables.includes(t.name)) return false;
|
|
2056
2538
|
return true;
|
|
@@ -2442,55 +2924,631 @@ var VaifAdmin = class {
|
|
|
2442
2924
|
}
|
|
2443
2925
|
};
|
|
2444
2926
|
|
|
2445
|
-
// src/lib/
|
|
2446
|
-
var
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
var memoryStorage = {
|
|
2450
|
-
data: /* @__PURE__ */ new Map(),
|
|
2451
|
-
getItem(key) {
|
|
2452
|
-
return this.data.get(key) ?? null;
|
|
2453
|
-
},
|
|
2454
|
-
setItem(key, value) {
|
|
2455
|
-
this.data.set(key, value);
|
|
2456
|
-
},
|
|
2457
|
-
removeItem(key) {
|
|
2458
|
-
this.data.delete(key);
|
|
2927
|
+
// src/lib/projects.ts
|
|
2928
|
+
var VaifProjects = class {
|
|
2929
|
+
constructor(client) {
|
|
2930
|
+
this.client = client;
|
|
2459
2931
|
}
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
return new VaifClient(options);
|
|
2468
|
-
}
|
|
2469
|
-
var VaifClient = class {
|
|
2470
|
-
constructor(options) {
|
|
2471
|
-
this.accessToken = null;
|
|
2472
|
-
const isAdminClient = options.baseUrl || options.accessToken;
|
|
2473
|
-
if (!isAdminClient) {
|
|
2474
|
-
if (!options.projectId) {
|
|
2475
|
-
throw new Error("projectId is required");
|
|
2476
|
-
}
|
|
2477
|
-
if (!options.apiKey) {
|
|
2478
|
-
throw new Error("apiKey is required");
|
|
2479
|
-
}
|
|
2932
|
+
/**
|
|
2933
|
+
* List all projects the user has access to
|
|
2934
|
+
*/
|
|
2935
|
+
async list(options) {
|
|
2936
|
+
const params = {};
|
|
2937
|
+
if (options?.orgId) {
|
|
2938
|
+
params.orgId = options.orgId;
|
|
2480
2939
|
}
|
|
2481
|
-
this.
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2940
|
+
const response = await this.client.request("/projects", { params });
|
|
2941
|
+
if (response.error) {
|
|
2942
|
+
throw new Error(response.error.message);
|
|
2943
|
+
}
|
|
2944
|
+
return response.data ?? [];
|
|
2945
|
+
}
|
|
2946
|
+
/**
|
|
2947
|
+
* Get a specific project by ID
|
|
2948
|
+
*/
|
|
2949
|
+
async get(projectId) {
|
|
2950
|
+
const response = await this.client.request(
|
|
2951
|
+
`/projects/${projectId}`
|
|
2952
|
+
);
|
|
2953
|
+
if (response.error) {
|
|
2954
|
+
throw new Error(response.error.message);
|
|
2955
|
+
}
|
|
2956
|
+
return response.data ?? { project: {}, environments: [] };
|
|
2957
|
+
}
|
|
2958
|
+
/**
|
|
2959
|
+
* Create a new project
|
|
2960
|
+
*/
|
|
2961
|
+
async create(options) {
|
|
2962
|
+
const response = await this.client.request(
|
|
2963
|
+
"/projects",
|
|
2964
|
+
{
|
|
2965
|
+
method: "POST",
|
|
2966
|
+
body: options
|
|
2967
|
+
}
|
|
2968
|
+
);
|
|
2969
|
+
if (response.error) {
|
|
2970
|
+
throw new Error(response.error.message);
|
|
2971
|
+
}
|
|
2972
|
+
return response.data ?? { project: {}, environments: [] };
|
|
2973
|
+
}
|
|
2974
|
+
/**
|
|
2975
|
+
* Update a project
|
|
2976
|
+
*/
|
|
2977
|
+
async update(projectId, options) {
|
|
2978
|
+
const response = await this.client.request(
|
|
2979
|
+
`/projects/${projectId}`,
|
|
2980
|
+
{
|
|
2981
|
+
method: "PATCH",
|
|
2982
|
+
body: options
|
|
2983
|
+
}
|
|
2984
|
+
);
|
|
2985
|
+
if (response.error) {
|
|
2986
|
+
throw new Error(response.error.message);
|
|
2987
|
+
}
|
|
2988
|
+
return response.data ?? { project: {} };
|
|
2989
|
+
}
|
|
2990
|
+
/**
|
|
2991
|
+
* Delete a project
|
|
2992
|
+
*/
|
|
2993
|
+
async delete(projectId) {
|
|
2994
|
+
const response = await this.client.request(
|
|
2995
|
+
`/projects/${projectId}`,
|
|
2996
|
+
{
|
|
2997
|
+
method: "DELETE"
|
|
2998
|
+
}
|
|
2999
|
+
);
|
|
3000
|
+
if (response.error) {
|
|
3001
|
+
throw new Error(response.error.message);
|
|
3002
|
+
}
|
|
3003
|
+
}
|
|
3004
|
+
/**
|
|
3005
|
+
* List API keys for a project
|
|
3006
|
+
*/
|
|
3007
|
+
async listApiKeys(projectId) {
|
|
3008
|
+
const response = await this.client.request(
|
|
3009
|
+
`/projects/${projectId}/api-keys`
|
|
3010
|
+
);
|
|
3011
|
+
if (response.error) {
|
|
3012
|
+
throw new Error(response.error.message);
|
|
3013
|
+
}
|
|
3014
|
+
return response.data?.keys ?? [];
|
|
3015
|
+
}
|
|
3016
|
+
/**
|
|
3017
|
+
* Alias for listApiKeys
|
|
3018
|
+
*/
|
|
3019
|
+
async getApiKeys(projectId) {
|
|
3020
|
+
return this.listApiKeys(projectId);
|
|
3021
|
+
}
|
|
3022
|
+
/**
|
|
3023
|
+
* Create an API key for a project
|
|
3024
|
+
*/
|
|
3025
|
+
async createApiKey(projectId, options) {
|
|
3026
|
+
const response = await this.client.request(
|
|
3027
|
+
`/projects/${projectId}/api-keys`,
|
|
3028
|
+
{
|
|
3029
|
+
method: "POST",
|
|
3030
|
+
body: options ?? {}
|
|
3031
|
+
}
|
|
3032
|
+
);
|
|
3033
|
+
if (response.error) {
|
|
3034
|
+
throw new Error(response.error.message);
|
|
3035
|
+
}
|
|
3036
|
+
return response.data ?? { apiKeyId: "", apiKey: "" };
|
|
3037
|
+
}
|
|
3038
|
+
/**
|
|
3039
|
+
* Revoke an API key
|
|
3040
|
+
*/
|
|
3041
|
+
async revokeApiKey(projectId, keyId) {
|
|
3042
|
+
const response = await this.client.request(
|
|
3043
|
+
`/projects/${projectId}/api-keys/${keyId}/revoke`,
|
|
3044
|
+
{
|
|
3045
|
+
method: "POST"
|
|
3046
|
+
}
|
|
3047
|
+
);
|
|
3048
|
+
if (response.error) {
|
|
3049
|
+
throw new Error(response.error.message);
|
|
3050
|
+
}
|
|
3051
|
+
}
|
|
3052
|
+
/**
|
|
3053
|
+
* Rotate an API key (revoke and create new)
|
|
3054
|
+
*/
|
|
3055
|
+
async rotateApiKey(projectId, keyId) {
|
|
3056
|
+
const response = await this.client.request(
|
|
3057
|
+
`/projects/${projectId}/api-keys/${keyId}/rotate`,
|
|
3058
|
+
{
|
|
3059
|
+
method: "POST"
|
|
3060
|
+
}
|
|
3061
|
+
);
|
|
3062
|
+
if (response.error) {
|
|
3063
|
+
throw new Error(response.error.message);
|
|
3064
|
+
}
|
|
3065
|
+
return response.data ?? { apiKeyId: "", apiKey: "" };
|
|
3066
|
+
}
|
|
3067
|
+
// Project Settings Methods
|
|
3068
|
+
/**
|
|
3069
|
+
* Get project settings
|
|
3070
|
+
*/
|
|
3071
|
+
async getSettings(projectId) {
|
|
3072
|
+
const response = await this.client.request(
|
|
3073
|
+
`/projects/${projectId}/settings`
|
|
3074
|
+
);
|
|
3075
|
+
if (response.error) {
|
|
3076
|
+
throw new Error(response.error.message);
|
|
3077
|
+
}
|
|
3078
|
+
return response.data ?? {};
|
|
3079
|
+
}
|
|
3080
|
+
/**
|
|
3081
|
+
* Get compute settings
|
|
3082
|
+
*/
|
|
3083
|
+
async getComputeSettings(projectId) {
|
|
3084
|
+
const response = await this.client.request(
|
|
3085
|
+
`/projects/${projectId}/settings/compute`
|
|
3086
|
+
);
|
|
3087
|
+
if (response.error) {
|
|
3088
|
+
throw new Error(response.error.message);
|
|
3089
|
+
}
|
|
3090
|
+
return response.data ?? {
|
|
3091
|
+
tier: "starter",
|
|
3092
|
+
diskSize: 1,
|
|
3093
|
+
region: "us-east-1",
|
|
3094
|
+
autoScaling: false,
|
|
3095
|
+
maxInstances: 1
|
|
3096
|
+
};
|
|
3097
|
+
}
|
|
3098
|
+
/**
|
|
3099
|
+
* Update compute settings
|
|
3100
|
+
*/
|
|
3101
|
+
async updateComputeSettings(projectId, settings) {
|
|
3102
|
+
const response = await this.client.request(
|
|
3103
|
+
`/projects/${projectId}/settings/compute`,
|
|
3104
|
+
{
|
|
3105
|
+
method: "PATCH",
|
|
3106
|
+
body: settings
|
|
3107
|
+
}
|
|
3108
|
+
);
|
|
3109
|
+
if (response.error) {
|
|
3110
|
+
throw new Error(response.error.message);
|
|
3111
|
+
}
|
|
3112
|
+
return response.data ?? {};
|
|
3113
|
+
}
|
|
3114
|
+
/**
|
|
3115
|
+
* Get API settings
|
|
3116
|
+
*/
|
|
3117
|
+
async getApiSettings(projectId) {
|
|
3118
|
+
const response = await this.client.request(
|
|
3119
|
+
`/projects/${projectId}/settings/api`
|
|
3120
|
+
);
|
|
3121
|
+
if (response.error) {
|
|
3122
|
+
throw new Error(response.error.message);
|
|
3123
|
+
}
|
|
3124
|
+
return response.data ?? {
|
|
3125
|
+
apiVersion: "v1",
|
|
3126
|
+
rateLimit: 100,
|
|
3127
|
+
corsEnabled: true,
|
|
3128
|
+
corsOrigins: ["*"],
|
|
3129
|
+
customDomain: ""
|
|
3130
|
+
};
|
|
3131
|
+
}
|
|
3132
|
+
/**
|
|
3133
|
+
* Update API settings
|
|
3134
|
+
*/
|
|
3135
|
+
async updateApiSettings(projectId, settings) {
|
|
3136
|
+
const response = await this.client.request(
|
|
3137
|
+
`/projects/${projectId}/settings/api`,
|
|
3138
|
+
{
|
|
3139
|
+
method: "PATCH",
|
|
3140
|
+
body: settings
|
|
3141
|
+
}
|
|
3142
|
+
);
|
|
3143
|
+
if (response.error) {
|
|
3144
|
+
throw new Error(response.error.message);
|
|
3145
|
+
}
|
|
3146
|
+
return response.data ?? {};
|
|
3147
|
+
}
|
|
3148
|
+
/**
|
|
3149
|
+
* Get JWT settings
|
|
3150
|
+
*/
|
|
3151
|
+
async getJwtSettings(projectId) {
|
|
3152
|
+
const response = await this.client.request(
|
|
3153
|
+
`/projects/${projectId}/settings/jwt`
|
|
3154
|
+
);
|
|
3155
|
+
if (response.error) {
|
|
3156
|
+
throw new Error(response.error.message);
|
|
3157
|
+
}
|
|
3158
|
+
return response.data ?? {
|
|
3159
|
+
algorithm: "HS256",
|
|
3160
|
+
accessTokenExpiry: 3600,
|
|
3161
|
+
refreshTokenExpiry: 604800,
|
|
3162
|
+
refreshTokenEnabled: true,
|
|
3163
|
+
rotateOnUse: true,
|
|
3164
|
+
secretHint: "********",
|
|
3165
|
+
lastRotated: null
|
|
3166
|
+
};
|
|
3167
|
+
}
|
|
3168
|
+
/**
|
|
3169
|
+
* Update JWT settings
|
|
3170
|
+
*/
|
|
3171
|
+
async updateJwtSettings(projectId, settings) {
|
|
3172
|
+
const response = await this.client.request(
|
|
3173
|
+
`/projects/${projectId}/settings/jwt`,
|
|
3174
|
+
{
|
|
3175
|
+
method: "PATCH",
|
|
3176
|
+
body: settings
|
|
3177
|
+
}
|
|
3178
|
+
);
|
|
3179
|
+
if (response.error) {
|
|
3180
|
+
throw new Error(response.error.message);
|
|
3181
|
+
}
|
|
3182
|
+
return response.data ?? {};
|
|
3183
|
+
}
|
|
3184
|
+
/**
|
|
3185
|
+
* Rotate JWT secret
|
|
3186
|
+
*/
|
|
3187
|
+
async rotateJwtSecret(projectId) {
|
|
3188
|
+
const response = await this.client.request(
|
|
3189
|
+
`/projects/${projectId}/settings/jwt/rotate`,
|
|
3190
|
+
{
|
|
3191
|
+
method: "POST"
|
|
3192
|
+
}
|
|
3193
|
+
);
|
|
3194
|
+
if (response.error) {
|
|
3195
|
+
throw new Error(response.error.message);
|
|
3196
|
+
}
|
|
3197
|
+
return response.data ?? { secretHint: "", lastRotated: "" };
|
|
3198
|
+
}
|
|
3199
|
+
/**
|
|
3200
|
+
* Get addons configuration
|
|
3201
|
+
*/
|
|
3202
|
+
async getAddons(projectId) {
|
|
3203
|
+
const response = await this.client.request(
|
|
3204
|
+
`/projects/${projectId}/settings/addons`
|
|
3205
|
+
);
|
|
3206
|
+
if (response.error) {
|
|
3207
|
+
throw new Error(response.error.message);
|
|
3208
|
+
}
|
|
3209
|
+
return response.data ?? {
|
|
3210
|
+
enabledAddons: [],
|
|
3211
|
+
currentTier: "free"
|
|
3212
|
+
};
|
|
3213
|
+
}
|
|
3214
|
+
/**
|
|
3215
|
+
* Update addons configuration
|
|
3216
|
+
*/
|
|
3217
|
+
async updateAddons(projectId, enabledAddons) {
|
|
3218
|
+
const response = await this.client.request(
|
|
3219
|
+
`/projects/${projectId}/settings/addons`,
|
|
3220
|
+
{
|
|
3221
|
+
method: "PATCH",
|
|
3222
|
+
body: { enabledAddons }
|
|
3223
|
+
}
|
|
3224
|
+
);
|
|
3225
|
+
if (response.error) {
|
|
3226
|
+
throw new Error(response.error.message);
|
|
3227
|
+
}
|
|
3228
|
+
return response.data ?? {};
|
|
3229
|
+
}
|
|
3230
|
+
};
|
|
3231
|
+
|
|
3232
|
+
// src/lib/apiKeys.ts
|
|
3233
|
+
var VaifApiKeys = class {
|
|
3234
|
+
constructor(client) {
|
|
3235
|
+
this.client = client;
|
|
3236
|
+
}
|
|
3237
|
+
/**
|
|
3238
|
+
* List API keys for a project
|
|
3239
|
+
*/
|
|
3240
|
+
async list(projectId) {
|
|
3241
|
+
const response = await this.client.request(
|
|
3242
|
+
`/projects/${projectId}/api-keys`
|
|
3243
|
+
);
|
|
3244
|
+
if (response.error) {
|
|
3245
|
+
throw new Error(response.error.message);
|
|
3246
|
+
}
|
|
3247
|
+
const keys = response.data?.keys ?? [];
|
|
3248
|
+
return keys.map((key) => ({
|
|
3249
|
+
...key,
|
|
3250
|
+
keyHint: key.keyHint || `vaif_${key.id.slice(0, 8)}...`,
|
|
3251
|
+
permissions: key.scopes || key.permissions || ["read"]
|
|
3252
|
+
}));
|
|
3253
|
+
}
|
|
3254
|
+
/**
|
|
3255
|
+
* Create a new API key
|
|
3256
|
+
*/
|
|
3257
|
+
async create(options) {
|
|
3258
|
+
const { projectId, ...body } = options;
|
|
3259
|
+
const requestBody = { ...body };
|
|
3260
|
+
if (options.permissions && !options.scopes) {
|
|
3261
|
+
const scopeMap = {
|
|
3262
|
+
read: "crud",
|
|
3263
|
+
write: "crud",
|
|
3264
|
+
admin: "crud",
|
|
3265
|
+
functions: "functions",
|
|
3266
|
+
storage: "storage",
|
|
3267
|
+
realtime: "realtime"
|
|
3268
|
+
};
|
|
3269
|
+
requestBody.scopes = options.permissions.map((p) => scopeMap[p] || p).filter((v, i, a) => a.indexOf(v) === i);
|
|
3270
|
+
}
|
|
3271
|
+
if (options.expiresIn && options.expiresIn !== "never") {
|
|
3272
|
+
const durationMatch = options.expiresIn.match(/^(\d+)([dmy])$/);
|
|
3273
|
+
if (durationMatch) {
|
|
3274
|
+
const amount = parseInt(durationMatch[1], 10);
|
|
3275
|
+
const unit = durationMatch[2];
|
|
3276
|
+
const now = /* @__PURE__ */ new Date();
|
|
3277
|
+
switch (unit) {
|
|
3278
|
+
case "d":
|
|
3279
|
+
now.setDate(now.getDate() + amount);
|
|
3280
|
+
break;
|
|
3281
|
+
case "m":
|
|
3282
|
+
now.setMonth(now.getMonth() + amount);
|
|
3283
|
+
break;
|
|
3284
|
+
case "y":
|
|
3285
|
+
now.setFullYear(now.getFullYear() + amount);
|
|
3286
|
+
break;
|
|
3287
|
+
}
|
|
3288
|
+
requestBody.expiresAt = now.toISOString();
|
|
3289
|
+
}
|
|
3290
|
+
}
|
|
3291
|
+
const response = await this.client.request(
|
|
3292
|
+
`/projects/${projectId}/api-keys`,
|
|
3293
|
+
{
|
|
3294
|
+
method: "POST",
|
|
3295
|
+
body: requestBody
|
|
3296
|
+
}
|
|
3297
|
+
);
|
|
3298
|
+
if (response.error) {
|
|
3299
|
+
throw new Error(response.error.message);
|
|
3300
|
+
}
|
|
3301
|
+
return {
|
|
3302
|
+
id: response.data?.apiKeyId ?? "",
|
|
3303
|
+
key: response.data?.apiKey ?? "",
|
|
3304
|
+
name: options.name ?? null,
|
|
3305
|
+
permissions: options.permissions ?? ["read"],
|
|
3306
|
+
expiresAt: requestBody.expiresAt ?? null
|
|
3307
|
+
};
|
|
3308
|
+
}
|
|
3309
|
+
/**
|
|
3310
|
+
* Revoke an API key
|
|
3311
|
+
*/
|
|
3312
|
+
async revoke(keyId, projectId) {
|
|
3313
|
+
if (!projectId) {
|
|
3314
|
+
throw new Error("projectId is required to revoke an API key");
|
|
3315
|
+
}
|
|
3316
|
+
const response = await this.client.request(
|
|
3317
|
+
`/projects/${projectId}/api-keys/${keyId}/revoke`,
|
|
3318
|
+
{
|
|
3319
|
+
method: "POST"
|
|
3320
|
+
}
|
|
3321
|
+
);
|
|
3322
|
+
if (response.error) {
|
|
3323
|
+
throw new Error(response.error.message);
|
|
3324
|
+
}
|
|
3325
|
+
}
|
|
3326
|
+
/**
|
|
3327
|
+
* Rotate an API key
|
|
3328
|
+
*/
|
|
3329
|
+
async rotate(keyId, projectId) {
|
|
3330
|
+
const response = await this.client.request(
|
|
3331
|
+
`/projects/${projectId}/api-keys/${keyId}/rotate`,
|
|
3332
|
+
{
|
|
3333
|
+
method: "POST"
|
|
3334
|
+
}
|
|
3335
|
+
);
|
|
3336
|
+
if (response.error) {
|
|
3337
|
+
throw new Error(response.error.message);
|
|
3338
|
+
}
|
|
3339
|
+
return {
|
|
3340
|
+
id: response.data?.apiKeyId ?? "",
|
|
3341
|
+
key: response.data?.apiKey ?? "",
|
|
3342
|
+
name: null,
|
|
3343
|
+
permissions: [],
|
|
3344
|
+
expiresAt: null
|
|
3345
|
+
};
|
|
3346
|
+
}
|
|
3347
|
+
/**
|
|
3348
|
+
* Update an API key
|
|
3349
|
+
*/
|
|
3350
|
+
async update(projectId, keyId, options) {
|
|
3351
|
+
const response = await this.client.request(
|
|
3352
|
+
`/projects/${projectId}/api-keys/${keyId}`,
|
|
3353
|
+
{
|
|
3354
|
+
method: "PATCH",
|
|
3355
|
+
body: options
|
|
3356
|
+
}
|
|
3357
|
+
);
|
|
3358
|
+
if (response.error) {
|
|
3359
|
+
throw new Error(response.error.message);
|
|
3360
|
+
}
|
|
3361
|
+
return response.data?.apiKey ?? {};
|
|
3362
|
+
}
|
|
3363
|
+
};
|
|
3364
|
+
|
|
3365
|
+
// src/lib/integrations.ts
|
|
3366
|
+
var VaifIntegrations = class {
|
|
3367
|
+
constructor(client) {
|
|
3368
|
+
this.client = client;
|
|
3369
|
+
}
|
|
3370
|
+
/**
|
|
3371
|
+
* List integrations for a project
|
|
3372
|
+
*/
|
|
3373
|
+
async list(projectId) {
|
|
3374
|
+
const response = await this.client.request(
|
|
3375
|
+
`/integrations/subscriptions/project/${projectId}`
|
|
3376
|
+
);
|
|
3377
|
+
if (response.error) {
|
|
3378
|
+
throw new Error(response.error.message);
|
|
3379
|
+
}
|
|
3380
|
+
return (response.data?.subscriptions ?? []).map((sub) => ({
|
|
3381
|
+
...sub,
|
|
3382
|
+
enabled: !sub.updatedAt || true
|
|
3383
|
+
// Default to enabled if no explicit disabled state
|
|
3384
|
+
}));
|
|
3385
|
+
}
|
|
3386
|
+
/**
|
|
3387
|
+
* Create a new integration
|
|
3388
|
+
*/
|
|
3389
|
+
async create(options) {
|
|
3390
|
+
const response = await this.client.request(
|
|
3391
|
+
"/integrations/subscriptions",
|
|
3392
|
+
{
|
|
3393
|
+
method: "POST",
|
|
3394
|
+
body: options
|
|
3395
|
+
}
|
|
3396
|
+
);
|
|
3397
|
+
if (response.error) {
|
|
3398
|
+
throw new Error(response.error.message);
|
|
3399
|
+
}
|
|
3400
|
+
return response.data?.subscription ?? {};
|
|
3401
|
+
}
|
|
3402
|
+
/**
|
|
3403
|
+
* Update an integration
|
|
3404
|
+
*/
|
|
3405
|
+
async update(integrationId, options) {
|
|
3406
|
+
const response = await this.client.request(
|
|
3407
|
+
`/integrations/subscriptions/${integrationId}`,
|
|
3408
|
+
{
|
|
3409
|
+
method: "PATCH",
|
|
3410
|
+
body: options
|
|
3411
|
+
}
|
|
3412
|
+
);
|
|
3413
|
+
if (response.error) {
|
|
3414
|
+
throw new Error(response.error.message);
|
|
3415
|
+
}
|
|
3416
|
+
return response.data?.subscription ?? {};
|
|
3417
|
+
}
|
|
3418
|
+
/**
|
|
3419
|
+
* Delete an integration
|
|
3420
|
+
*/
|
|
3421
|
+
async delete(integrationId) {
|
|
3422
|
+
const response = await this.client.request(
|
|
3423
|
+
`/integrations/subscriptions/${integrationId}`,
|
|
3424
|
+
{
|
|
3425
|
+
method: "DELETE"
|
|
3426
|
+
}
|
|
3427
|
+
);
|
|
3428
|
+
if (response.error) {
|
|
3429
|
+
throw new Error(response.error.message);
|
|
3430
|
+
}
|
|
3431
|
+
}
|
|
3432
|
+
/**
|
|
3433
|
+
* Test an integration
|
|
3434
|
+
*/
|
|
3435
|
+
async test(integrationId) {
|
|
3436
|
+
const response = await this.client.request(
|
|
3437
|
+
`/integrations/subscriptions/${integrationId}/test`,
|
|
3438
|
+
{
|
|
3439
|
+
method: "POST"
|
|
3440
|
+
}
|
|
3441
|
+
);
|
|
3442
|
+
if (response.error) {
|
|
3443
|
+
throw new Error(response.error.message);
|
|
3444
|
+
}
|
|
3445
|
+
}
|
|
3446
|
+
/**
|
|
3447
|
+
* Get webhook deliveries for an integration
|
|
3448
|
+
*/
|
|
3449
|
+
async getDeliveries(integrationId) {
|
|
3450
|
+
const response = await this.client.request(
|
|
3451
|
+
`/integrations/deliveries/subscription/${integrationId}`
|
|
3452
|
+
);
|
|
3453
|
+
if (response.error) {
|
|
3454
|
+
throw new Error(response.error.message);
|
|
3455
|
+
}
|
|
3456
|
+
return response.data?.deliveries ?? [];
|
|
3457
|
+
}
|
|
3458
|
+
/**
|
|
3459
|
+
* Get failed deliveries (DLQ) for a project
|
|
3460
|
+
*/
|
|
3461
|
+
async getFailedDeliveries(projectId, limit) {
|
|
3462
|
+
const params = {};
|
|
3463
|
+
if (limit) {
|
|
3464
|
+
params.limit = String(limit);
|
|
3465
|
+
}
|
|
3466
|
+
const response = await this.client.request(
|
|
3467
|
+
`/integrations/dlq/project/${projectId}`,
|
|
3468
|
+
{ params }
|
|
3469
|
+
);
|
|
3470
|
+
if (response.error) {
|
|
3471
|
+
throw new Error(response.error.message);
|
|
3472
|
+
}
|
|
3473
|
+
return response.data?.deliveries ?? [];
|
|
3474
|
+
}
|
|
3475
|
+
};
|
|
3476
|
+
|
|
3477
|
+
// src/lib/client.ts
|
|
3478
|
+
var DEFAULT_API_URL = "https://api.vaif.studio";
|
|
3479
|
+
var DEFAULT_REALTIME_URL = "wss://realtime.vaif.studio";
|
|
3480
|
+
var DEFAULT_TIMEOUT = 3e4;
|
|
3481
|
+
var DEFAULT_RETRY = {
|
|
3482
|
+
maxRetries: 3,
|
|
3483
|
+
retryDelay: 1e3,
|
|
3484
|
+
maxRetryDelay: 3e4,
|
|
3485
|
+
backoffMultiplier: 2,
|
|
3486
|
+
retryOn: [429, 500, 502, 503, 504],
|
|
3487
|
+
retryOnNetworkError: true
|
|
3488
|
+
};
|
|
3489
|
+
var memoryStorage = {
|
|
3490
|
+
data: /* @__PURE__ */ new Map(),
|
|
3491
|
+
getItem(key) {
|
|
3492
|
+
return this.data.get(key) ?? null;
|
|
3493
|
+
},
|
|
3494
|
+
setItem(key, value) {
|
|
3495
|
+
this.data.set(key, value);
|
|
3496
|
+
},
|
|
3497
|
+
removeItem(key) {
|
|
3498
|
+
this.data.delete(key);
|
|
3499
|
+
}
|
|
3500
|
+
};
|
|
3501
|
+
var browserStorage = typeof window !== "undefined" && window.localStorage ? {
|
|
3502
|
+
getItem: (key) => window.localStorage.getItem(key),
|
|
3503
|
+
setItem: (key, value) => window.localStorage.setItem(key, value),
|
|
3504
|
+
removeItem: (key) => window.localStorage.removeItem(key)
|
|
3505
|
+
} : null;
|
|
3506
|
+
function calculateRetryDelay(attempt, config) {
|
|
3507
|
+
const exponentialDelay = config.retryDelay * Math.pow(config.backoffMultiplier, attempt);
|
|
3508
|
+
const cappedDelay = Math.min(exponentialDelay, config.maxRetryDelay);
|
|
3509
|
+
const jitter = 0.5 + Math.random();
|
|
3510
|
+
return Math.floor(cappedDelay * jitter);
|
|
3511
|
+
}
|
|
3512
|
+
function isRetryableStatus(status, config) {
|
|
3513
|
+
return config.retryOn.includes(status);
|
|
3514
|
+
}
|
|
3515
|
+
function sleep(ms) {
|
|
3516
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3517
|
+
}
|
|
3518
|
+
function createClient(options) {
|
|
3519
|
+
return new VaifClient(options);
|
|
3520
|
+
}
|
|
3521
|
+
var VaifClient = class {
|
|
3522
|
+
constructor(options) {
|
|
3523
|
+
this.accessToken = null;
|
|
3524
|
+
const isAdminClient = options.baseUrl || options.accessToken;
|
|
3525
|
+
if (!isAdminClient) {
|
|
3526
|
+
if (!options.projectId) {
|
|
3527
|
+
throw new VaifError("projectId is required", { code: "INVALID_CONFIG" });
|
|
3528
|
+
}
|
|
3529
|
+
if (!options.apiKey) {
|
|
3530
|
+
throw new VaifError("apiKey is required", { code: "INVALID_CONFIG" });
|
|
3531
|
+
}
|
|
3532
|
+
}
|
|
3533
|
+
this.config = {
|
|
3534
|
+
projectId: options.projectId ?? "",
|
|
3535
|
+
apiKey: options.apiKey ?? "",
|
|
3536
|
+
apiKeyHeader: options.apiKeyHeader ?? "apikey",
|
|
3537
|
+
apiUrl: options.baseUrl ?? options.apiUrl ?? DEFAULT_API_URL,
|
|
3538
|
+
realtimeUrl: options.realtimeUrl ?? DEFAULT_REALTIME_URL,
|
|
3539
|
+
timeout: options.timeout ?? DEFAULT_TIMEOUT,
|
|
3540
|
+
headers: options.headers ?? {},
|
|
3541
|
+
debug: options.debug ?? false,
|
|
3542
|
+
autoRefreshToken: options.autoRefreshToken ?? true,
|
|
3543
|
+
persistSession: options.persistSession ?? true,
|
|
3544
|
+
storage: options.storage ?? browserStorage ?? memoryStorage,
|
|
3545
|
+
retry: {
|
|
3546
|
+
...DEFAULT_RETRY,
|
|
3547
|
+
...options.retry,
|
|
3548
|
+
retryOn: options.retry?.retryOn ?? DEFAULT_RETRY.retryOn
|
|
3549
|
+
},
|
|
3550
|
+
interceptors: options.interceptors ?? {}
|
|
3551
|
+
};
|
|
2494
3552
|
if (options.accessToken) {
|
|
2495
3553
|
this.accessToken = options.accessToken;
|
|
2496
3554
|
}
|
|
@@ -2500,124 +3558,236 @@ var VaifClient = class {
|
|
|
2500
3558
|
this.functions = new VaifFunctions(this);
|
|
2501
3559
|
this.auth = new VaifAuth(this);
|
|
2502
3560
|
this.ai = new VaifAI(this);
|
|
3561
|
+
this.schema = new VaifSchema(this);
|
|
2503
3562
|
this.typegen = new VaifTypeGen(this);
|
|
2504
3563
|
this.admin = new VaifAdmin(this);
|
|
3564
|
+
this.projects = new VaifProjects(this);
|
|
3565
|
+
this.apiKeys = new VaifApiKeys(this);
|
|
3566
|
+
this.integrations = new VaifIntegrations(this);
|
|
2505
3567
|
this.restoreSession();
|
|
2506
3568
|
}
|
|
2507
|
-
/**
|
|
2508
|
-
* Get current configuration
|
|
2509
|
-
*/
|
|
3569
|
+
/** Get current configuration */
|
|
2510
3570
|
getConfig() {
|
|
2511
3571
|
return this.config;
|
|
2512
3572
|
}
|
|
2513
|
-
/**
|
|
2514
|
-
* Set access token for authenticated requests
|
|
2515
|
-
*/
|
|
3573
|
+
/** Set access token for authenticated requests */
|
|
2516
3574
|
setAccessToken(token) {
|
|
2517
3575
|
this.accessToken = token;
|
|
2518
3576
|
}
|
|
2519
|
-
/**
|
|
2520
|
-
* Get current access token
|
|
2521
|
-
*/
|
|
3577
|
+
/** Get current access token */
|
|
2522
3578
|
getAccessToken() {
|
|
2523
3579
|
return this.accessToken;
|
|
2524
3580
|
}
|
|
2525
3581
|
/**
|
|
2526
|
-
* Make an authenticated API request
|
|
3582
|
+
* Make an authenticated API request with automatic retry and interceptors
|
|
3583
|
+
*
|
|
3584
|
+
* @param path - API path (relative to base URL)
|
|
3585
|
+
* @param options - Request options (method, body, params, etc.)
|
|
3586
|
+
* @returns Typed API response with data, error, status, and headers
|
|
2527
3587
|
*/
|
|
2528
3588
|
async request(path, options = {}) {
|
|
2529
|
-
const
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
3589
|
+
const { retry, interceptors } = this.config;
|
|
3590
|
+
for (let attempt = 0; attempt <= retry.maxRetries; attempt++) {
|
|
3591
|
+
const startTime = Date.now();
|
|
3592
|
+
const url = new URL(path, this.config.apiUrl);
|
|
3593
|
+
if (options.params) {
|
|
3594
|
+
Object.entries(options.params).forEach(([key, value]) => {
|
|
3595
|
+
if (value !== void 0) {
|
|
3596
|
+
url.searchParams.set(key, String(value));
|
|
3597
|
+
}
|
|
3598
|
+
});
|
|
3599
|
+
}
|
|
3600
|
+
const headers = {
|
|
3601
|
+
"Content-Type": "application/json",
|
|
3602
|
+
...this.config.headers,
|
|
3603
|
+
...options.headers
|
|
3604
|
+
};
|
|
3605
|
+
if (this.config.projectId) {
|
|
3606
|
+
headers["X-Project-ID"] = this.config.projectId;
|
|
3607
|
+
}
|
|
3608
|
+
if (this.config.apiKey) {
|
|
3609
|
+
headers[this.config.apiKeyHeader] = this.config.apiKey;
|
|
3610
|
+
}
|
|
3611
|
+
if (this.accessToken) {
|
|
3612
|
+
headers.Authorization = `Bearer ${this.accessToken}`;
|
|
3613
|
+
}
|
|
3614
|
+
let requestContext = {
|
|
3615
|
+
url: url.toString(),
|
|
3616
|
+
path,
|
|
3617
|
+
method: options.method ?? "GET",
|
|
3618
|
+
headers: { ...headers },
|
|
3619
|
+
body: options.body && options.method !== "GET" ? JSON.stringify(options.body) : void 0,
|
|
3620
|
+
attempt
|
|
3621
|
+
};
|
|
3622
|
+
if (interceptors.onRequest) {
|
|
3623
|
+
try {
|
|
3624
|
+
const modified = await interceptors.onRequest(requestContext);
|
|
3625
|
+
if (modified) {
|
|
3626
|
+
requestContext = modified;
|
|
3627
|
+
}
|
|
3628
|
+
} catch {
|
|
2534
3629
|
}
|
|
2535
|
-
});
|
|
2536
|
-
}
|
|
2537
|
-
const headers = {
|
|
2538
|
-
"Content-Type": "application/json",
|
|
2539
|
-
...this.config.headers,
|
|
2540
|
-
...options.headers
|
|
2541
|
-
};
|
|
2542
|
-
if (this.config.projectId) {
|
|
2543
|
-
headers["X-Project-ID"] = this.config.projectId;
|
|
2544
|
-
}
|
|
2545
|
-
if (this.config.apiKey) {
|
|
2546
|
-
headers[this.config.apiKeyHeader] = this.config.apiKey;
|
|
2547
|
-
}
|
|
2548
|
-
if (this.accessToken) {
|
|
2549
|
-
headers.Authorization = `Bearer ${this.accessToken}`;
|
|
2550
|
-
}
|
|
2551
|
-
const fetchOptions = {
|
|
2552
|
-
method: options.method ?? "GET",
|
|
2553
|
-
headers,
|
|
2554
|
-
signal: options.signal
|
|
2555
|
-
};
|
|
2556
|
-
if (options.body && options.method !== "GET") {
|
|
2557
|
-
fetchOptions.body = JSON.stringify(options.body);
|
|
2558
|
-
}
|
|
2559
|
-
const timeoutMs = options.timeout ?? this.config.timeout;
|
|
2560
|
-
const timeoutController = new AbortController();
|
|
2561
|
-
const timeoutId = setTimeout(() => timeoutController.abort(), timeoutMs);
|
|
2562
|
-
if (options.signal) {
|
|
2563
|
-
options.signal.addEventListener("abort", () => timeoutController.abort());
|
|
2564
|
-
}
|
|
2565
|
-
fetchOptions.signal = timeoutController.signal;
|
|
2566
|
-
try {
|
|
2567
|
-
if (this.config.debug) {
|
|
2568
|
-
console.log(`[VAIF] ${options.method ?? "GET"} ${url.toString()}`);
|
|
2569
3630
|
}
|
|
2570
|
-
const
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
if (
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
3631
|
+
const fetchOptions = {
|
|
3632
|
+
method: requestContext.method,
|
|
3633
|
+
headers: requestContext.headers,
|
|
3634
|
+
signal: options.signal
|
|
3635
|
+
};
|
|
3636
|
+
if (requestContext.body) {
|
|
3637
|
+
fetchOptions.body = requestContext.body;
|
|
3638
|
+
}
|
|
3639
|
+
const timeoutMs = options.timeout ?? this.config.timeout;
|
|
3640
|
+
const timeoutController = new AbortController();
|
|
3641
|
+
const timeoutId = setTimeout(() => timeoutController.abort(), timeoutMs);
|
|
3642
|
+
if (options.signal) {
|
|
3643
|
+
options.signal.addEventListener("abort", () => timeoutController.abort());
|
|
3644
|
+
}
|
|
3645
|
+
fetchOptions.signal = timeoutController.signal;
|
|
3646
|
+
try {
|
|
3647
|
+
if (this.config.debug) {
|
|
3648
|
+
console.log(`[VAIF] ${requestContext.method} ${requestContext.url} (attempt ${attempt + 1})`);
|
|
3649
|
+
}
|
|
3650
|
+
const response = await fetch(requestContext.url, fetchOptions);
|
|
3651
|
+
clearTimeout(timeoutId);
|
|
3652
|
+
const durationMs = Date.now() - startTime;
|
|
3653
|
+
const contentType = response.headers.get("content-type");
|
|
3654
|
+
let data = null;
|
|
3655
|
+
let error = null;
|
|
3656
|
+
if (contentType?.includes("application/json")) {
|
|
3657
|
+
const json = await response.json();
|
|
3658
|
+
if (response.ok) {
|
|
3659
|
+
data = json;
|
|
3660
|
+
} else {
|
|
3661
|
+
error = {
|
|
3662
|
+
message: json.message ?? json.error ?? "Request failed",
|
|
3663
|
+
code: json.code,
|
|
3664
|
+
status: response.status,
|
|
3665
|
+
details: json.details,
|
|
3666
|
+
requestId: response.headers.get("x-request-id") ?? void 0
|
|
3667
|
+
};
|
|
3668
|
+
}
|
|
3669
|
+
} else if (!response.ok) {
|
|
2580
3670
|
error = {
|
|
2581
|
-
message:
|
|
2582
|
-
|
|
2583
|
-
status: response.status,
|
|
2584
|
-
details: json.details,
|
|
2585
|
-
requestId: response.headers.get("x-request-id") ?? void 0
|
|
3671
|
+
message: `Request failed with status ${response.status}`,
|
|
3672
|
+
status: response.status
|
|
2586
3673
|
};
|
|
2587
3674
|
}
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
3675
|
+
const responseHeaders = {};
|
|
3676
|
+
response.headers.forEach((value, key) => {
|
|
3677
|
+
responseHeaders[key] = value;
|
|
3678
|
+
});
|
|
3679
|
+
if (error && attempt < retry.maxRetries && isRetryableStatus(response.status, retry)) {
|
|
3680
|
+
if (interceptors.onError) {
|
|
3681
|
+
try {
|
|
3682
|
+
await interceptors.onError({
|
|
3683
|
+
request: requestContext,
|
|
3684
|
+
error: new VaifError(error.message, {
|
|
3685
|
+
code: error.code ?? "REQUEST_ERROR",
|
|
3686
|
+
statusCode: response.status
|
|
3687
|
+
}),
|
|
3688
|
+
durationMs,
|
|
3689
|
+
willRetry: true
|
|
3690
|
+
});
|
|
3691
|
+
} catch {
|
|
3692
|
+
}
|
|
3693
|
+
}
|
|
3694
|
+
const delay = calculateRetryDelay(attempt, retry);
|
|
3695
|
+
if (this.config.debug) {
|
|
3696
|
+
console.log(`[VAIF] Retrying in ${delay}ms (attempt ${attempt + 2}/${retry.maxRetries + 1})`);
|
|
3697
|
+
}
|
|
3698
|
+
await sleep(delay);
|
|
3699
|
+
continue;
|
|
3700
|
+
}
|
|
3701
|
+
if (!error && interceptors.onResponse) {
|
|
3702
|
+
try {
|
|
3703
|
+
await interceptors.onResponse({
|
|
3704
|
+
request: requestContext,
|
|
3705
|
+
data,
|
|
3706
|
+
status: response.status,
|
|
3707
|
+
headers: responseHeaders,
|
|
3708
|
+
durationMs
|
|
3709
|
+
});
|
|
3710
|
+
} catch {
|
|
3711
|
+
}
|
|
3712
|
+
}
|
|
3713
|
+
if (error && interceptors.onError) {
|
|
3714
|
+
try {
|
|
3715
|
+
await interceptors.onError({
|
|
3716
|
+
request: requestContext,
|
|
3717
|
+
error: new VaifError(error.message, {
|
|
3718
|
+
code: error.code ?? "REQUEST_ERROR",
|
|
3719
|
+
statusCode: response.status
|
|
3720
|
+
}),
|
|
3721
|
+
durationMs,
|
|
3722
|
+
willRetry: false
|
|
3723
|
+
});
|
|
3724
|
+
} catch {
|
|
3725
|
+
}
|
|
3726
|
+
}
|
|
3727
|
+
return {
|
|
3728
|
+
data,
|
|
3729
|
+
error,
|
|
3730
|
+
status: response.status,
|
|
3731
|
+
headers: responseHeaders
|
|
3732
|
+
};
|
|
3733
|
+
} catch (err) {
|
|
3734
|
+
clearTimeout(timeoutId);
|
|
3735
|
+
const durationMs = Date.now() - startTime;
|
|
3736
|
+
const isTimeout = err instanceof Error && err.name === "AbortError";
|
|
3737
|
+
const isNetworkError = !isTimeout;
|
|
3738
|
+
if (isNetworkError && retry.retryOnNetworkError && attempt < retry.maxRetries) {
|
|
3739
|
+
if (interceptors.onError) {
|
|
3740
|
+
try {
|
|
3741
|
+
await interceptors.onError({
|
|
3742
|
+
request: requestContext,
|
|
3743
|
+
error: err instanceof Error ? err : new Error(String(err)),
|
|
3744
|
+
durationMs,
|
|
3745
|
+
willRetry: true
|
|
3746
|
+
});
|
|
3747
|
+
} catch {
|
|
3748
|
+
}
|
|
3749
|
+
}
|
|
3750
|
+
const delay = calculateRetryDelay(attempt, retry);
|
|
3751
|
+
if (this.config.debug) {
|
|
3752
|
+
console.log(`[VAIF] Network error, retrying in ${delay}ms`);
|
|
3753
|
+
}
|
|
3754
|
+
await sleep(delay);
|
|
3755
|
+
continue;
|
|
3756
|
+
}
|
|
3757
|
+
const error = {
|
|
3758
|
+
message: err instanceof Error ? isTimeout ? "Request timed out" : err.message : "Unknown error",
|
|
3759
|
+
code: isTimeout ? "TIMEOUT" : "NETWORK_ERROR"
|
|
3760
|
+
};
|
|
3761
|
+
if (interceptors.onError) {
|
|
3762
|
+
try {
|
|
3763
|
+
await interceptors.onError({
|
|
3764
|
+
request: requestContext,
|
|
3765
|
+
error: isTimeout ? new VaifTimeoutError("Request timed out", timeoutMs) : new VaifNetworkError(
|
|
3766
|
+
err instanceof Error ? err.message : "Network error",
|
|
3767
|
+
err instanceof Error ? err : void 0
|
|
3768
|
+
),
|
|
3769
|
+
durationMs,
|
|
3770
|
+
willRetry: false
|
|
3771
|
+
});
|
|
3772
|
+
} catch {
|
|
3773
|
+
}
|
|
3774
|
+
}
|
|
3775
|
+
return {
|
|
3776
|
+
data: null,
|
|
3777
|
+
error,
|
|
3778
|
+
status: 0,
|
|
3779
|
+
headers: {}
|
|
2592
3780
|
};
|
|
2593
3781
|
}
|
|
2594
|
-
const responseHeaders = {};
|
|
2595
|
-
response.headers.forEach((value, key) => {
|
|
2596
|
-
responseHeaders[key] = value;
|
|
2597
|
-
});
|
|
2598
|
-
return {
|
|
2599
|
-
data,
|
|
2600
|
-
error,
|
|
2601
|
-
status: response.status,
|
|
2602
|
-
headers: responseHeaders
|
|
2603
|
-
};
|
|
2604
|
-
} catch (err) {
|
|
2605
|
-
clearTimeout(timeoutId);
|
|
2606
|
-
const error = {
|
|
2607
|
-
message: err instanceof Error ? err.name === "AbortError" ? "Request timed out" : err.message : "Unknown error",
|
|
2608
|
-
code: err instanceof Error && err.name === "AbortError" ? "TIMEOUT" : "NETWORK_ERROR"
|
|
2609
|
-
};
|
|
2610
|
-
return {
|
|
2611
|
-
data: null,
|
|
2612
|
-
error,
|
|
2613
|
-
status: 0,
|
|
2614
|
-
headers: {}
|
|
2615
|
-
};
|
|
2616
3782
|
}
|
|
3783
|
+
return {
|
|
3784
|
+
data: null,
|
|
3785
|
+
error: { message: "Max retries exceeded", code: "MAX_RETRIES" },
|
|
3786
|
+
status: 0,
|
|
3787
|
+
headers: {}
|
|
3788
|
+
};
|
|
2617
3789
|
}
|
|
2618
|
-
/**
|
|
2619
|
-
* Restore session from storage
|
|
2620
|
-
*/
|
|
3790
|
+
/** Restore session from storage */
|
|
2621
3791
|
async restoreSession() {
|
|
2622
3792
|
if (!this.config.persistSession) return;
|
|
2623
3793
|
try {
|
|
@@ -2633,27 +3803,46 @@ var VaifClient = class {
|
|
|
2633
3803
|
} catch {
|
|
2634
3804
|
}
|
|
2635
3805
|
}
|
|
2636
|
-
/**
|
|
2637
|
-
* Log debug messages
|
|
2638
|
-
*/
|
|
3806
|
+
/** Log debug messages */
|
|
2639
3807
|
debug(...args) {
|
|
2640
3808
|
if (this.config.debug) {
|
|
2641
3809
|
console.log("[VAIF]", ...args);
|
|
2642
3810
|
}
|
|
2643
3811
|
}
|
|
2644
3812
|
};
|
|
2645
|
-
export
|
|
3813
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
3814
|
+
0 && (module.exports = {
|
|
2646
3815
|
RealtimeChannel,
|
|
2647
3816
|
VaifAI,
|
|
2648
3817
|
VaifAdmin,
|
|
3818
|
+
VaifApiKeys,
|
|
2649
3819
|
VaifAuth,
|
|
3820
|
+
VaifAuthError,
|
|
2650
3821
|
VaifClient,
|
|
3822
|
+
VaifConflictError,
|
|
2651
3823
|
VaifDatabase,
|
|
3824
|
+
VaifError,
|
|
2652
3825
|
VaifFunctions,
|
|
3826
|
+
VaifIntegrations,
|
|
3827
|
+
VaifNetworkError,
|
|
3828
|
+
VaifNotFoundError,
|
|
3829
|
+
VaifProjects,
|
|
3830
|
+
VaifRateLimitError,
|
|
2653
3831
|
VaifRealtime,
|
|
3832
|
+
VaifSchema,
|
|
2654
3833
|
VaifStorage,
|
|
3834
|
+
VaifTimeoutError,
|
|
2655
3835
|
VaifTypeGen,
|
|
3836
|
+
VaifValidationError,
|
|
2656
3837
|
createClient,
|
|
2657
3838
|
createTypeGen,
|
|
2658
|
-
|
|
2659
|
-
|
|
3839
|
+
createVaifClient,
|
|
3840
|
+
isVaifAuthError,
|
|
3841
|
+
isVaifConflictError,
|
|
3842
|
+
isVaifError,
|
|
3843
|
+
isVaifNetworkError,
|
|
3844
|
+
isVaifNotFoundError,
|
|
3845
|
+
isVaifRateLimitError,
|
|
3846
|
+
isVaifTimeoutError,
|
|
3847
|
+
isVaifValidationError
|
|
3848
|
+
});
|