@lovable.dev/sdk 0.1.3 → 0.1.5
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 +6 -3
- package/dist/index.d.ts +393 -17
- package/dist/index.js +341 -45
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
// src/types.ts
|
|
2
|
+
var ApiError = class extends Error {
|
|
3
|
+
status;
|
|
4
|
+
type;
|
|
5
|
+
detail;
|
|
6
|
+
constructor(status, message, type, detail) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.type = type;
|
|
10
|
+
this.detail = detail;
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
|
|
1
14
|
// src/client.ts
|
|
2
15
|
var DEFAULT_BASE_URL = "https://api.lovable.dev";
|
|
3
16
|
function normalizeBaseUrl(url) {
|
|
@@ -9,25 +22,36 @@ function normalizeBaseUrl(url) {
|
|
|
9
22
|
return normalized;
|
|
10
23
|
}
|
|
11
24
|
var LovableClient = class {
|
|
12
|
-
|
|
25
|
+
authHeaders;
|
|
13
26
|
baseUrl;
|
|
27
|
+
extraHeaders;
|
|
14
28
|
constructor(options) {
|
|
15
|
-
|
|
16
|
-
|
|
29
|
+
const hasApiKey = !!options.apiKey;
|
|
30
|
+
const hasBearerToken = !!options.bearerToken;
|
|
31
|
+
if (!hasApiKey && !hasBearerToken) {
|
|
32
|
+
throw new Error("Either apiKey or bearerToken is required");
|
|
33
|
+
}
|
|
34
|
+
if (hasApiKey && hasBearerToken) {
|
|
35
|
+
throw new Error("Provide either apiKey or bearerToken, not both");
|
|
17
36
|
}
|
|
18
|
-
this.
|
|
37
|
+
this.authHeaders = hasApiKey ? { "Lovable-API-Key": options.apiKey } : { Authorization: `Bearer ${options.bearerToken}` };
|
|
19
38
|
this.baseUrl = normalizeBaseUrl(options.baseUrl);
|
|
39
|
+
this.extraHeaders = options.headers ?? {};
|
|
20
40
|
}
|
|
21
|
-
async
|
|
41
|
+
async rawRequest(method, path, body) {
|
|
22
42
|
const url = `${this.baseUrl}${path}`;
|
|
23
43
|
const headers = {
|
|
24
|
-
|
|
25
|
-
|
|
44
|
+
...this.authHeaders,
|
|
45
|
+
...this.extraHeaders,
|
|
46
|
+
Accept: "application/json"
|
|
26
47
|
};
|
|
48
|
+
if (body !== void 0) {
|
|
49
|
+
headers["Content-Type"] = "application/json";
|
|
50
|
+
}
|
|
27
51
|
const response = await fetch(url, {
|
|
28
52
|
method,
|
|
29
53
|
headers,
|
|
30
|
-
body: body ? JSON.stringify(body) : void 0
|
|
54
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
31
55
|
});
|
|
32
56
|
if (!response.ok) {
|
|
33
57
|
let errorBody;
|
|
@@ -35,17 +59,22 @@ var LovableClient = class {
|
|
|
35
59
|
errorBody = await response.json();
|
|
36
60
|
} catch {
|
|
37
61
|
}
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
error.type = errorBody?.title;
|
|
41
|
-
error.detail = errorBody?.detail;
|
|
42
|
-
throw error;
|
|
62
|
+
const message = errorBody?.message ?? errorBody?.title ?? `HTTP ${response.status}: ${response.statusText}`;
|
|
63
|
+
throw new ApiError(response.status, message, errorBody?.title, errorBody?.detail);
|
|
43
64
|
}
|
|
65
|
+
return response;
|
|
66
|
+
}
|
|
67
|
+
async request(method, path, body) {
|
|
68
|
+
const response = await this.rawRequest(method, path, body);
|
|
44
69
|
if (response.status === 204) {
|
|
45
70
|
return void 0;
|
|
46
71
|
}
|
|
47
72
|
return response.json();
|
|
48
73
|
}
|
|
74
|
+
async requestText(method, path) {
|
|
75
|
+
const response = await this.rawRequest(method, path);
|
|
76
|
+
return response.text();
|
|
77
|
+
}
|
|
49
78
|
/**
|
|
50
79
|
* Get the current authenticated user and their workspaces.
|
|
51
80
|
* Useful for validating an API key and discovering workspace IDs.
|
|
@@ -68,25 +97,36 @@ var LovableClient = class {
|
|
|
68
97
|
return response.workspace;
|
|
69
98
|
}
|
|
70
99
|
/**
|
|
71
|
-
* List projects in a workspace
|
|
100
|
+
* List projects in a workspace.
|
|
101
|
+
* Supports full-text search, filtering by visibility/publish status/folder/creator,
|
|
102
|
+
* and pagination via offset or cursor.
|
|
72
103
|
*/
|
|
73
104
|
async listProjects(workspaceId, options) {
|
|
74
105
|
const params = new URLSearchParams();
|
|
75
|
-
if (options?.
|
|
76
|
-
if (options?.cursor) params.set("cursor", options.cursor);
|
|
106
|
+
if (options?.query) params.set("q", options.query);
|
|
77
107
|
if (options?.visibility) params.set("visibility", options.visibility);
|
|
108
|
+
if (options?.publish_status) params.set("publish_status", options.publish_status);
|
|
109
|
+
if (options?.folder_id) params.set("folder_id", options.folder_id);
|
|
110
|
+
if (options?.user_id) params.set("user_id", options.user_id);
|
|
111
|
+
if (options?.sort_by) params.set("sort_by", options.sort_by);
|
|
112
|
+
if (options?.sort_order) params.set("sort_order", options.sort_order);
|
|
113
|
+
if (options?.viewed_by_me) params.set("viewed_by_me", "true");
|
|
114
|
+
if (options?.limit !== void 0) params.set("limit", String(options.limit));
|
|
115
|
+
if (options?.offset !== void 0) params.set("offset", String(options.offset));
|
|
116
|
+
if (options?.cursor) params.set("cursor", options.cursor);
|
|
78
117
|
const query = params.toString();
|
|
79
118
|
const path = `/v1/workspaces/${workspaceId}/projects${query ? `?${query}` : ""}`;
|
|
80
|
-
|
|
81
|
-
return response.projects ?? [];
|
|
119
|
+
return this.request("GET", path);
|
|
82
120
|
}
|
|
83
121
|
/**
|
|
84
122
|
* Create a new project in a workspace
|
|
85
123
|
*/
|
|
86
124
|
async createProject(workspaceId, options) {
|
|
87
|
-
let
|
|
88
|
-
if (options.
|
|
89
|
-
|
|
125
|
+
let fileRefs;
|
|
126
|
+
if (options.uploadedFiles?.length) {
|
|
127
|
+
fileRefs = options.uploadedFiles;
|
|
128
|
+
} else if (options.files?.length) {
|
|
129
|
+
fileRefs = await this.uploadFiles(options.files);
|
|
90
130
|
}
|
|
91
131
|
const body = {
|
|
92
132
|
description: options.description,
|
|
@@ -96,49 +136,53 @@ var LovableClient = class {
|
|
|
96
136
|
if (options.techStack) {
|
|
97
137
|
body.tech_stack = options.techStack;
|
|
98
138
|
}
|
|
99
|
-
|
|
100
|
-
|
|
139
|
+
if (options.selectedLibraries?.length) {
|
|
140
|
+
body.selected_libraries = options.selectedLibraries;
|
|
141
|
+
}
|
|
142
|
+
if (options.initialMessage) {
|
|
101
143
|
body.initial_message = options.initialMessage;
|
|
102
144
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const chatBody = {
|
|
106
|
-
message: options.initialMessage,
|
|
107
|
-
files: uploadedFiles
|
|
108
|
-
};
|
|
109
|
-
await this.request("POST", `/v1/projects/${project.id}/messages`, chatBody);
|
|
145
|
+
if (fileRefs?.length) {
|
|
146
|
+
body.files = fileRefs;
|
|
110
147
|
}
|
|
148
|
+
const project = await this.request("POST", `/v1/workspaces/${workspaceId}/projects`, body);
|
|
111
149
|
return project;
|
|
112
150
|
}
|
|
113
151
|
/**
|
|
114
|
-
* Send a chat message to a project
|
|
152
|
+
* Send a chat message to a project.
|
|
115
153
|
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
154
|
+
* The API accepts the message and processes it in the background.
|
|
155
|
+
* Returns the message ID and status. Use `waitForMessageCompletion()`
|
|
156
|
+
* to poll for the AI response, or `waitForResponse()` for SSE streaming.
|
|
118
157
|
*/
|
|
119
158
|
async chat(projectId, options) {
|
|
120
|
-
let
|
|
121
|
-
if (options.
|
|
122
|
-
|
|
159
|
+
let fileRefs;
|
|
160
|
+
if (options.uploadedFiles?.length) {
|
|
161
|
+
fileRefs = options.uploadedFiles;
|
|
162
|
+
} else if (options.files?.length) {
|
|
163
|
+
fileRefs = await this.uploadFiles(options.files);
|
|
123
164
|
}
|
|
124
165
|
const body = {
|
|
125
166
|
message: options.message
|
|
126
167
|
};
|
|
127
|
-
if (
|
|
128
|
-
body.files =
|
|
168
|
+
if (fileRefs) {
|
|
169
|
+
body.files = fileRefs;
|
|
129
170
|
}
|
|
130
|
-
if (options.
|
|
131
|
-
body.
|
|
171
|
+
if (options.planMode) {
|
|
172
|
+
body.plan_mode = true;
|
|
132
173
|
}
|
|
133
174
|
if (options.customModel) {
|
|
134
175
|
body.custom_model_endpoint = options.customModel.endpoint;
|
|
135
176
|
body.custom_model_api_key = options.customModel.apiKey;
|
|
136
177
|
body.custom_model_name = options.customModel.modelName;
|
|
137
178
|
}
|
|
179
|
+
if (options.customModelDisableRace) {
|
|
180
|
+
body.custom_model_disable_race = true;
|
|
181
|
+
}
|
|
138
182
|
if (options.continuation) {
|
|
139
183
|
body.continuation = options.continuation;
|
|
140
184
|
}
|
|
141
|
-
|
|
185
|
+
return this.request("POST", `/v1/projects/${projectId}/messages`, body);
|
|
142
186
|
}
|
|
143
187
|
/**
|
|
144
188
|
* Invite a user to a workspace as a collaborator
|
|
@@ -240,6 +284,257 @@ var LovableClient = class {
|
|
|
240
284
|
async getDatabaseConnectionInfo(projectId) {
|
|
241
285
|
return this.request("GET", `/v1/projects/${projectId}/database/connection-info`);
|
|
242
286
|
}
|
|
287
|
+
// ---------------------------------------------------------------------------
|
|
288
|
+
// Messages
|
|
289
|
+
// ---------------------------------------------------------------------------
|
|
290
|
+
/**
|
|
291
|
+
* Get a message by ID. Returns the message content, status, and (for user messages)
|
|
292
|
+
* the AI response if available. Use to poll for completion after `chat()`.
|
|
293
|
+
*/
|
|
294
|
+
async getMessage(projectId, messageId) {
|
|
295
|
+
return this.request("GET", `/v1/projects/${projectId}/messages/${messageId}`);
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Poll for message completion. Waits until the AI response reaches a terminal
|
|
299
|
+
* status (completed, stopped) or the timeout expires.
|
|
300
|
+
*
|
|
301
|
+
* Handles edge cases: 404 grace period for race conditions between queue
|
|
302
|
+
* dequeue and event creation, and queue pause detection.
|
|
303
|
+
*/
|
|
304
|
+
async waitForMessageCompletion(projectId, messageId, options) {
|
|
305
|
+
const pollInterval = options?.pollInterval ?? 3e3;
|
|
306
|
+
const timeout = options?.timeout ?? 6e5;
|
|
307
|
+
const deadline = Date.now() + timeout;
|
|
308
|
+
let notFoundSince = null;
|
|
309
|
+
const notFoundGraceMs = 15e3;
|
|
310
|
+
while (Date.now() < deadline) {
|
|
311
|
+
try {
|
|
312
|
+
const msg = await this.getMessage(projectId, messageId);
|
|
313
|
+
notFoundSince = null;
|
|
314
|
+
if (msg.status === "queued") {
|
|
315
|
+
if (msg.queue_paused && msg.queue_pause_reason !== "hitl_tool") {
|
|
316
|
+
return {
|
|
317
|
+
status: "error",
|
|
318
|
+
message_id: messageId,
|
|
319
|
+
content: "",
|
|
320
|
+
error: `Message is queued (position ${msg.queue_position ?? "unknown"}) but the queue is paused` + (msg.queue_pause_reason ? ` (reason: ${msg.queue_pause_reason})` : "") + `. Unpause the queue in the Lovable editor, or use wait=false to return immediately.`
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
await sleep(pollInterval);
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
const ai = msg.response;
|
|
327
|
+
if (ai) {
|
|
328
|
+
if (ai.status === "completed" || ai.status === "stopped") {
|
|
329
|
+
return {
|
|
330
|
+
status: ai.status === "completed" ? "completed" : "error",
|
|
331
|
+
message_id: ai.message_id,
|
|
332
|
+
content: ai.content,
|
|
333
|
+
edit_id: ai.edit_id,
|
|
334
|
+
commit_sha: ai.commit_sha,
|
|
335
|
+
summary: ai.summary,
|
|
336
|
+
cost_credits: ai.cost_credits
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
if (msg.role === "assistant") {
|
|
341
|
+
if (msg.status === "completed" || msg.status === "stopped") {
|
|
342
|
+
return {
|
|
343
|
+
status: msg.status === "completed" ? "completed" : "error",
|
|
344
|
+
message_id: msg.message_id,
|
|
345
|
+
content: msg.content,
|
|
346
|
+
edit_id: msg.edit_id,
|
|
347
|
+
commit_sha: msg.commit_sha,
|
|
348
|
+
summary: msg.summary,
|
|
349
|
+
cost_credits: msg.cost_credits
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
await sleep(pollInterval);
|
|
354
|
+
} catch (err) {
|
|
355
|
+
if (err instanceof ApiError && err.status === 404) {
|
|
356
|
+
if (notFoundSince === null) {
|
|
357
|
+
notFoundSince = Date.now();
|
|
358
|
+
}
|
|
359
|
+
if (Date.now() - notFoundSince < notFoundGraceMs) {
|
|
360
|
+
await sleep(pollInterval);
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
return {
|
|
364
|
+
status: "error",
|
|
365
|
+
message_id: messageId,
|
|
366
|
+
content: "",
|
|
367
|
+
error: "Message not found. It may have been deleted from the queue."
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
await sleep(pollInterval);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return {
|
|
374
|
+
status: "timeout",
|
|
375
|
+
message_id: messageId,
|
|
376
|
+
content: "",
|
|
377
|
+
error: `Agent did not finish within ${timeout / 1e3}s`
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
// ---------------------------------------------------------------------------
|
|
381
|
+
// Knowledge
|
|
382
|
+
// ---------------------------------------------------------------------------
|
|
383
|
+
/** Get workspace knowledge (custom instructions for the AI agent). */
|
|
384
|
+
async getWorkspaceKnowledge(workspaceId) {
|
|
385
|
+
return this.request("GET", `/v1/workspaces/${workspaceId}/knowledge`);
|
|
386
|
+
}
|
|
387
|
+
/** Set workspace knowledge. Max 10,000 characters. */
|
|
388
|
+
async setWorkspaceKnowledge(workspaceId, content) {
|
|
389
|
+
return this.request("PUT", `/v1/workspaces/${workspaceId}/knowledge`, { content });
|
|
390
|
+
}
|
|
391
|
+
/** Get project knowledge (custom instructions for the AI agent). */
|
|
392
|
+
async getProjectKnowledge(projectId) {
|
|
393
|
+
return this.request("GET", `/v1/projects/${projectId}/knowledge`);
|
|
394
|
+
}
|
|
395
|
+
/** Set project knowledge. Max 10,000 characters. */
|
|
396
|
+
async setProjectKnowledge(projectId, content) {
|
|
397
|
+
return this.request("PUT", `/v1/projects/${projectId}/knowledge`, { content });
|
|
398
|
+
}
|
|
399
|
+
// ---------------------------------------------------------------------------
|
|
400
|
+
// Git operations
|
|
401
|
+
// ---------------------------------------------------------------------------
|
|
402
|
+
/**
|
|
403
|
+
* Get the structured diff for a message or commit.
|
|
404
|
+
* Pass `messageId` to get the diff for a specific AI message,
|
|
405
|
+
* or `sha` for a specific commit.
|
|
406
|
+
*/
|
|
407
|
+
async getDiff(projectId, params) {
|
|
408
|
+
const qs = new URLSearchParams();
|
|
409
|
+
if (params.messageId) qs.set("message_id", params.messageId);
|
|
410
|
+
if (params.sha) qs.set("sha", params.sha);
|
|
411
|
+
if (params.baseSha) qs.set("base_sha", params.baseSha);
|
|
412
|
+
return this.request("GET", `/v1/projects/${projectId}/git/diff?${qs.toString()}`);
|
|
413
|
+
}
|
|
414
|
+
/** List all files in a project at a specific git ref. */
|
|
415
|
+
async listFiles(projectId, ref) {
|
|
416
|
+
const qs = new URLSearchParams({ ref });
|
|
417
|
+
return this.request("GET", `/v1/projects/${projectId}/git/files?${qs.toString()}`);
|
|
418
|
+
}
|
|
419
|
+
/** Read the raw content of a single file at a specific git ref. Returns text. */
|
|
420
|
+
async readFile(projectId, path, ref) {
|
|
421
|
+
const qs = new URLSearchParams({ path, ref });
|
|
422
|
+
return this.requestText("GET", `/v1/projects/${projectId}/git/file?${qs.toString()}`);
|
|
423
|
+
}
|
|
424
|
+
// ---------------------------------------------------------------------------
|
|
425
|
+
// Edits
|
|
426
|
+
// ---------------------------------------------------------------------------
|
|
427
|
+
/** List the edit history of a project. */
|
|
428
|
+
async listEdits(projectId, params) {
|
|
429
|
+
const qs = new URLSearchParams();
|
|
430
|
+
if (params?.limit !== void 0) qs.set("limit", String(params.limit));
|
|
431
|
+
if (params?.before) qs.set("before", params.before);
|
|
432
|
+
const suffix = qs.toString() ? `?${qs.toString()}` : "";
|
|
433
|
+
return this.request("GET", `/v1/projects/${projectId}/edits${suffix}`);
|
|
434
|
+
}
|
|
435
|
+
// ---------------------------------------------------------------------------
|
|
436
|
+
// File upload
|
|
437
|
+
// ---------------------------------------------------------------------------
|
|
438
|
+
/** Get a presigned URL for uploading a file. Returns the upload URL and file ID. */
|
|
439
|
+
async getFileUploadUrl(params) {
|
|
440
|
+
return this.request("POST", "/v1/files/upload-url", params);
|
|
441
|
+
}
|
|
442
|
+
// ---------------------------------------------------------------------------
|
|
443
|
+
// Visibility
|
|
444
|
+
// ---------------------------------------------------------------------------
|
|
445
|
+
/** Set a project's visibility (draft, private, or public). */
|
|
446
|
+
async setProjectVisibility(projectId, visibility) {
|
|
447
|
+
return this.request("PUT", `/v1/projects/${projectId}/visibility`, { visibility });
|
|
448
|
+
}
|
|
449
|
+
/** Set a folder's visibility (personal or workspace). */
|
|
450
|
+
async setFolderVisibility(workspaceId, folderId, visibility) {
|
|
451
|
+
return this.request("PUT", `/v1/workspaces/${workspaceId}/folders/${folderId}/visibility`, {
|
|
452
|
+
visibility
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
// ---------------------------------------------------------------------------
|
|
456
|
+
// Library & template projects
|
|
457
|
+
// ---------------------------------------------------------------------------
|
|
458
|
+
/** List available design system library projects in a workspace. */
|
|
459
|
+
async listLibraryProjects(workspaceId) {
|
|
460
|
+
return this.request(
|
|
461
|
+
"GET",
|
|
462
|
+
`/v1/workspaces/${workspaceId}/available-library-projects`
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
/** List available template projects in a workspace. */
|
|
466
|
+
async listTemplateProjects(workspaceId) {
|
|
467
|
+
return this.request(
|
|
468
|
+
"GET",
|
|
469
|
+
`/v1/workspaces/${workspaceId}/available-template-projects`
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
// ---------------------------------------------------------------------------
|
|
473
|
+
// MCP servers
|
|
474
|
+
// ---------------------------------------------------------------------------
|
|
475
|
+
/** List all MCP servers connected to a workspace. */
|
|
476
|
+
async listMCPServers(workspaceId) {
|
|
477
|
+
return this.request("GET", `/v1/workspaces/${workspaceId}/mcp-servers`);
|
|
478
|
+
}
|
|
479
|
+
/** Add an MCP server to a workspace. The server URL is tested before saving. */
|
|
480
|
+
async addMCPServer(workspaceId, body) {
|
|
481
|
+
return this.request("POST", `/v1/workspaces/${workspaceId}/mcp-servers`, body);
|
|
482
|
+
}
|
|
483
|
+
/** Remove an MCP server from a workspace. */
|
|
484
|
+
async removeMCPServer(workspaceId, serverId) {
|
|
485
|
+
return this.request("DELETE", `/v1/workspaces/${workspaceId}/mcp-servers/${serverId}`);
|
|
486
|
+
}
|
|
487
|
+
/** Browse available MCP server templates (catalog). */
|
|
488
|
+
async listMCPCatalog(workspaceId) {
|
|
489
|
+
return this.request("GET", `/v1/workspaces/${workspaceId}/mcp-catalog`);
|
|
490
|
+
}
|
|
491
|
+
// ---------------------------------------------------------------------------
|
|
492
|
+
// Connectors
|
|
493
|
+
// ---------------------------------------------------------------------------
|
|
494
|
+
/** List standard (OAuth-based) connectors in a workspace. */
|
|
495
|
+
async listStandardConnectors(workspaceId) {
|
|
496
|
+
return this.request(
|
|
497
|
+
"GET",
|
|
498
|
+
`/v1/workspaces/${workspaceId}/connectors/standard`
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
/** List seamless (zero-config) connectors in a workspace. */
|
|
502
|
+
async listSeamlessConnectors(workspaceId) {
|
|
503
|
+
return this.request(
|
|
504
|
+
"GET",
|
|
505
|
+
`/v1/workspaces/${workspaceId}/connectors/seamless`
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
/** List MCP connectors in a workspace. */
|
|
509
|
+
async listMCPConnectors(workspaceId) {
|
|
510
|
+
return this.request(
|
|
511
|
+
"GET",
|
|
512
|
+
`/v1/workspaces/${workspaceId}/connectors/mcp`
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
/** List authenticated connections (accounts) in a workspace. */
|
|
516
|
+
async listConnections(workspaceId, params) {
|
|
517
|
+
const qs = new URLSearchParams();
|
|
518
|
+
if (params?.connector_id) qs.set("connector_id", params.connector_id);
|
|
519
|
+
const suffix = qs.toString() ? `?${qs.toString()}` : "";
|
|
520
|
+
return this.request("GET", `/v1/workspaces/${workspaceId}/connections${suffix}`);
|
|
521
|
+
}
|
|
522
|
+
// ---------------------------------------------------------------------------
|
|
523
|
+
// Analytics
|
|
524
|
+
// ---------------------------------------------------------------------------
|
|
525
|
+
/** Get historical analytics for a published project. */
|
|
526
|
+
async getProjectAnalytics(projectId, params) {
|
|
527
|
+
const qs = new URLSearchParams({
|
|
528
|
+
startDate: params.startDate,
|
|
529
|
+
endDate: params.endDate
|
|
530
|
+
});
|
|
531
|
+
if (params.granularity) qs.set("granularity", params.granularity);
|
|
532
|
+
return this.request("GET", `/v1/projects/${projectId}/analytics?${qs.toString()}`);
|
|
533
|
+
}
|
|
534
|
+
/** Get real-time visitor trend for a published project. */
|
|
535
|
+
async getProjectAnalyticsTrend(projectId) {
|
|
536
|
+
return this.request("GET", `/v1/projects/${projectId}/analytics/trend`);
|
|
537
|
+
}
|
|
243
538
|
/**
|
|
244
539
|
* Publish a project.
|
|
245
540
|
*
|
|
@@ -277,6 +572,7 @@ var LovableClient = class {
|
|
|
277
572
|
workspace_id: options.workspaceId,
|
|
278
573
|
include_history: options.includeHistory,
|
|
279
574
|
include_custom_knowledge: options.includeCustomKnowledge,
|
|
575
|
+
project_name: options.projectName,
|
|
280
576
|
skip_initial_remix_message: options.skipInitialRemixMessage,
|
|
281
577
|
skip_integrations: options.skipIntegrations,
|
|
282
578
|
include_agent_state: options.includeAgentState
|
|
@@ -386,14 +682,13 @@ var LovableClient = class {
|
|
|
386
682
|
try {
|
|
387
683
|
const response = await fetch(url, {
|
|
388
684
|
headers: {
|
|
389
|
-
|
|
685
|
+
...this.authHeaders,
|
|
686
|
+
...this.extraHeaders
|
|
390
687
|
},
|
|
391
688
|
signal: controller.signal
|
|
392
689
|
});
|
|
393
690
|
if (!response.ok) {
|
|
394
|
-
|
|
395
|
-
error.status = response.status;
|
|
396
|
-
throw error;
|
|
691
|
+
throw new ApiError(response.status, `Failed to connect to message stream: HTTP ${response.status}`);
|
|
397
692
|
}
|
|
398
693
|
if (!response.body) {
|
|
399
694
|
throw new Error("Response body is not readable");
|
|
@@ -606,6 +901,7 @@ function sleep(ms) {
|
|
|
606
901
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
607
902
|
}
|
|
608
903
|
export {
|
|
904
|
+
ApiError,
|
|
609
905
|
LovableClient
|
|
610
906
|
};
|
|
611
907
|
//# sourceMappingURL=index.js.map
|