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