@jxsuite/studio 0.28.2 → 0.28.4
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/dist/studio.js +86144 -83971
- package/dist/studio.js.map +229 -219
- package/package.json +5 -5
- package/src/browse/browse-modal.ts +9 -3
- package/src/browse/browse.ts +139 -82
- package/src/canvas/canvas-diff.ts +35 -18
- package/src/canvas/canvas-helpers.ts +55 -21
- package/src/canvas/canvas-live-render.ts +140 -89
- package/src/canvas/canvas-render.ts +127 -82
- package/src/canvas/canvas-utils.ts +68 -42
- package/src/canvas/nested-site-style.ts +15 -7
- package/src/editor/component-inline-edit.ts +90 -51
- package/src/editor/content-inline-edit.ts +75 -72
- package/src/editor/context-menu.ts +125 -71
- package/src/editor/convert-targets.ts +17 -13
- package/src/editor/convert-to-component.ts +51 -28
- package/src/editor/convert-to-repeater.ts +44 -19
- package/src/editor/inline-edit.ts +107 -52
- package/src/editor/inline-format.ts +128 -60
- package/src/editor/insertion-helper.ts +26 -14
- package/src/editor/shortcuts.ts +89 -43
- package/src/editor/slash-menu.ts +41 -26
- package/src/files/components.ts +9 -7
- package/src/files/file-ops.ts +53 -33
- package/src/files/files.ts +246 -143
- package/src/format/constraints.ts +25 -15
- package/src/format/format-host.ts +33 -10
- package/src/github/github-auth.ts +24 -14
- package/src/github/github-publish.ts +20 -14
- package/src/new-project/new-project-modal.ts +27 -18
- package/src/panels/activity-bar.ts +27 -26
- package/src/panels/ai-panel.ts +100 -44
- package/src/panels/block-action-bar.ts +84 -52
- package/src/panels/canvas-dnd.ts +47 -28
- package/src/panels/data-explorer.ts +24 -11
- package/src/panels/dnd.ts +148 -100
- package/src/panels/editors.ts +54 -37
- package/src/panels/elements-panel.ts +23 -13
- package/src/panels/events-panel.ts +48 -38
- package/src/panels/git-panel.ts +95 -60
- package/src/panels/head-panel.ts +138 -84
- package/src/panels/imports-panel.ts +66 -29
- package/src/panels/layers-panel.ts +80 -36
- package/src/panels/left-panel.ts +86 -53
- package/src/panels/overlays.ts +36 -19
- package/src/panels/panel-events.ts +48 -27
- package/src/panels/panel-scheduler.ts +41 -23
- package/src/panels/preview-render.ts +26 -26
- package/src/panels/properties-panel.ts +155 -118
- package/src/panels/pseudo-preview.ts +31 -15
- package/src/panels/quick-search.ts +28 -13
- package/src/panels/right-panel.ts +35 -24
- package/src/panels/shared.ts +46 -29
- package/src/panels/signals-panel.ts +303 -186
- package/src/panels/statusbar.ts +27 -12
- package/src/panels/style-inputs.ts +30 -24
- package/src/panels/style-panel.ts +130 -90
- package/src/panels/style-utils.ts +63 -23
- package/src/panels/stylebook-layers-panel.ts +27 -30
- package/src/panels/stylebook-panel.ts +140 -72
- package/src/panels/tab-strip.ts +21 -10
- package/src/panels/toolbar.ts +52 -40
- package/src/panels/welcome-screen.ts +1 -1
- package/src/platform.ts +2 -1
- package/src/platforms/devserver.ts +221 -105
- package/src/recent-projects.ts +15 -7
- package/src/resize-edges.ts +7 -5
- package/src/services/cem-export.ts +73 -57
- package/src/services/code-services.ts +52 -25
- package/src/services/monaco-setup.ts +5 -5
- package/src/settings/content-types-editor.ts +133 -62
- package/src/settings/css-vars-editor.ts +31 -14
- package/src/settings/defs-editor.ts +125 -63
- package/src/settings/general-settings.ts +11 -6
- package/src/settings/head-editor.ts +30 -15
- package/src/settings/schema-field-ui.ts +75 -35
- package/src/settings/settings-modal.ts +35 -17
- package/src/site-context.ts +80 -47
- package/src/state.ts +98 -65
- package/src/store.ts +42 -23
- package/src/studio.ts +165 -144
- package/src/tabs/tab.ts +51 -45
- package/src/tabs/transact.ts +230 -109
- package/src/types.ts +60 -51
- package/src/ui/button-group.ts +3 -2
- package/src/ui/color-selector.ts +33 -15
- package/src/ui/expression-editor.ts +139 -86
- package/src/ui/field-input.ts +35 -18
- package/src/ui/field-row.ts +1 -1
- package/src/ui/icons.ts +5 -6
- package/src/ui/layers.ts +33 -26
- package/src/ui/media-picker.ts +13 -7
- package/src/ui/panel-resize.ts +39 -20
- package/src/ui/spectrum.ts +4 -2
- package/src/ui/unit-selector.ts +20 -11
- package/src/ui/value-selector.ts +13 -7
- package/src/ui/widgets.ts +34 -18
- package/src/utils/canvas-media.ts +66 -33
- package/src/utils/edit-display.ts +43 -44
- package/src/utils/google-fonts.ts +10 -6
- package/src/utils/inherited-style.ts +22 -8
- package/src/utils/studio-utils.ts +88 -45
- package/src/view.ts +9 -5
- package/src/workspace/workspace.ts +49 -29
|
@@ -26,8 +26,12 @@ export function createDevServerPlatform() {
|
|
|
26
26
|
*/
|
|
27
27
|
function serverPath(rel: string) {
|
|
28
28
|
const r = rel.replaceAll("\\", "/");
|
|
29
|
-
if (!_projectRoot)
|
|
30
|
-
|
|
29
|
+
if (!_projectRoot) {
|
|
30
|
+
return r;
|
|
31
|
+
}
|
|
32
|
+
if (r === ".") {
|
|
33
|
+
return _projectRoot;
|
|
34
|
+
}
|
|
31
35
|
return `${_projectRoot}/${r}`;
|
|
32
36
|
}
|
|
33
37
|
|
|
@@ -38,8 +42,10 @@ export function createDevServerPlatform() {
|
|
|
38
42
|
*/
|
|
39
43
|
function stripRoot(path: string) {
|
|
40
44
|
const p = path.replaceAll("\\", "/");
|
|
41
|
-
if (!_projectRoot)
|
|
42
|
-
|
|
45
|
+
if (!_projectRoot) {
|
|
46
|
+
return p;
|
|
47
|
+
}
|
|
48
|
+
return p.startsWith(`${_projectRoot}/`) ? p.slice(_projectRoot.length + 1) : p;
|
|
43
49
|
}
|
|
44
50
|
|
|
45
51
|
return {
|
|
@@ -51,7 +57,9 @@ export function createDevServerPlatform() {
|
|
|
51
57
|
},
|
|
52
58
|
set projectRoot(v) {
|
|
53
59
|
_projectRoot = v || "";
|
|
54
|
-
if (_projectRoot)
|
|
60
|
+
if (_projectRoot) {
|
|
61
|
+
this.activate(_projectRoot);
|
|
62
|
+
}
|
|
55
63
|
},
|
|
56
64
|
|
|
57
65
|
/**
|
|
@@ -63,9 +71,9 @@ export function createDevServerPlatform() {
|
|
|
63
71
|
async activate(root?: string) {
|
|
64
72
|
const r = root ?? _projectRoot;
|
|
65
73
|
await fetch("/__studio/activate", {
|
|
66
|
-
method: "POST",
|
|
67
|
-
headers: { "Content-Type": "application/json" },
|
|
68
74
|
body: JSON.stringify({ root: r }),
|
|
75
|
+
headers: { "Content-Type": "application/json" },
|
|
76
|
+
method: "POST",
|
|
69
77
|
});
|
|
70
78
|
},
|
|
71
79
|
|
|
@@ -81,13 +89,15 @@ export function createDevServerPlatform() {
|
|
|
81
89
|
try {
|
|
82
90
|
dirHandle = await (
|
|
83
91
|
window as unknown as {
|
|
84
|
-
showDirectoryPicker(opts: { mode: string })
|
|
92
|
+
showDirectoryPicker: (opts: { mode: string }) => Promise<FileSystemDirectoryHandle>;
|
|
85
93
|
}
|
|
86
94
|
).showDirectoryPicker({ mode: "readwrite" });
|
|
87
|
-
} catch (
|
|
95
|
+
} catch (error) {
|
|
88
96
|
// User cancelled the picker
|
|
89
|
-
if (
|
|
90
|
-
|
|
97
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
throw error;
|
|
91
101
|
}
|
|
92
102
|
|
|
93
103
|
// Read project.json from the chosen directory
|
|
@@ -103,7 +113,9 @@ export function createDevServerPlatform() {
|
|
|
103
113
|
|
|
104
114
|
// Resolve server-relative path by matching against known sites
|
|
105
115
|
const sitesRes = await fetch("/__studio/sites");
|
|
106
|
-
if (!sitesRes.ok)
|
|
116
|
+
if (!sitesRes.ok) {
|
|
117
|
+
throw new Error("Failed to fetch site list from server");
|
|
118
|
+
}
|
|
107
119
|
const sites = await sitesRes.json();
|
|
108
120
|
const match = sites.find(
|
|
109
121
|
/** @param {{ config: unknown; path: string }} s */ (s: {
|
|
@@ -117,9 +129,13 @@ export function createDevServerPlatform() {
|
|
|
117
129
|
const findRes = await fetch(
|
|
118
130
|
`/__studio/find-project?name=${encodeURIComponent(dirHandle.name)}`,
|
|
119
131
|
);
|
|
120
|
-
if (!findRes.ok)
|
|
132
|
+
if (!findRes.ok) {
|
|
133
|
+
throw new Error("Could not locate project on disk");
|
|
134
|
+
}
|
|
121
135
|
const found = await findRes.json();
|
|
122
|
-
if (!found.path)
|
|
136
|
+
if (!found.path) {
|
|
137
|
+
throw new Error(`Could not find project directory "${dirHandle.name}"`);
|
|
138
|
+
}
|
|
123
139
|
_projectRoot = found.path;
|
|
124
140
|
} else {
|
|
125
141
|
_projectRoot = match.path;
|
|
@@ -131,9 +147,9 @@ export function createDevServerPlatform() {
|
|
|
131
147
|
return {
|
|
132
148
|
config,
|
|
133
149
|
handle: {
|
|
134
|
-
root: _projectRoot,
|
|
135
150
|
name: config.name || _projectRoot.split("/").pop(),
|
|
136
151
|
projectConfig: config,
|
|
152
|
+
root: _projectRoot,
|
|
137
153
|
},
|
|
138
154
|
};
|
|
139
155
|
},
|
|
@@ -148,9 +164,9 @@ export function createDevServerPlatform() {
|
|
|
148
164
|
fetch("/__studio/project"),
|
|
149
165
|
fetch("/__studio/project-info?dir=."),
|
|
150
166
|
]);
|
|
151
|
-
const meta = projectRes.ok ? await projectRes.json() : {
|
|
167
|
+
const meta = projectRes.ok ? await projectRes.json() : { name: "project", root: "." };
|
|
152
168
|
const info = infoRes.ok ? await infoRes.json() : { isSiteProject: false };
|
|
153
|
-
return {
|
|
169
|
+
return { info, meta };
|
|
154
170
|
} catch {
|
|
155
171
|
return null;
|
|
156
172
|
}
|
|
@@ -175,9 +191,9 @@ export function createDevServerPlatform() {
|
|
|
175
191
|
directory: string;
|
|
176
192
|
}) {
|
|
177
193
|
const res = await fetch("/__studio/create-project", {
|
|
178
|
-
method: "POST",
|
|
179
|
-
headers: { "Content-Type": "application/json" },
|
|
180
194
|
body: JSON.stringify(opts),
|
|
195
|
+
headers: { "Content-Type": "application/json" },
|
|
196
|
+
method: "POST",
|
|
181
197
|
});
|
|
182
198
|
if (!res.ok) {
|
|
183
199
|
const data = await res.json();
|
|
@@ -191,16 +207,22 @@ export function createDevServerPlatform() {
|
|
|
191
207
|
/** @param {string} dir */
|
|
192
208
|
async listDirectory(dir: string) {
|
|
193
209
|
const res = await fetch(`/__studio/files?dir=${encodeURIComponent(serverPath(dir))}`);
|
|
194
|
-
if (!res.ok)
|
|
210
|
+
if (!res.ok) {
|
|
211
|
+
throw new Error(`Failed to list directory: ${dir}`);
|
|
212
|
+
}
|
|
195
213
|
const entries = await res.json();
|
|
196
|
-
for (const e of entries)
|
|
214
|
+
for (const e of entries) {
|
|
215
|
+
e.path = stripRoot(e.path);
|
|
216
|
+
}
|
|
197
217
|
return entries;
|
|
198
218
|
},
|
|
199
219
|
|
|
200
220
|
/** @param {string} path */
|
|
201
221
|
async readFile(path: string) {
|
|
202
222
|
const res = await fetch(`/__studio/file?path=${encodeURIComponent(serverPath(path))}`);
|
|
203
|
-
if (!res.ok)
|
|
223
|
+
if (!res.ok) {
|
|
224
|
+
throw new Error(`Failed to read file: ${path}`);
|
|
225
|
+
}
|
|
204
226
|
const data = await res.json();
|
|
205
227
|
return data.content;
|
|
206
228
|
},
|
|
@@ -211,10 +233,12 @@ export function createDevServerPlatform() {
|
|
|
211
233
|
*/
|
|
212
234
|
async writeFile(path: string, content: string) {
|
|
213
235
|
const res = await fetch(`/__studio/file?path=${encodeURIComponent(serverPath(path))}`, {
|
|
214
|
-
method: "PUT",
|
|
215
236
|
body: content,
|
|
237
|
+
method: "PUT",
|
|
216
238
|
});
|
|
217
|
-
if (!res.ok)
|
|
239
|
+
if (!res.ok) {
|
|
240
|
+
throw new Error(`Failed to write file: ${path}`);
|
|
241
|
+
}
|
|
218
242
|
},
|
|
219
243
|
|
|
220
244
|
/**
|
|
@@ -223,12 +247,14 @@ export function createDevServerPlatform() {
|
|
|
223
247
|
* @param {string} path — project-relative destination path
|
|
224
248
|
* @param {File | Blob | ArrayBuffer} data — file content
|
|
225
249
|
*/
|
|
226
|
-
async uploadFile(path: string, data: File | Blob | ArrayBuffer) {
|
|
250
|
+
async uploadFile(path: string, data: string | File | Blob | ArrayBuffer) {
|
|
227
251
|
const res = await fetch(
|
|
228
252
|
`/__studio/file/upload?path=${encodeURIComponent(serverPath(path))}`,
|
|
229
|
-
{ method: "POST"
|
|
253
|
+
{ body: data, method: "POST" },
|
|
230
254
|
);
|
|
231
|
-
if (!res.ok)
|
|
255
|
+
if (!res.ok) {
|
|
256
|
+
throw new Error(`Upload failed: ${path}`);
|
|
257
|
+
}
|
|
232
258
|
return await res.json();
|
|
233
259
|
},
|
|
234
260
|
|
|
@@ -237,7 +263,9 @@ export function createDevServerPlatform() {
|
|
|
237
263
|
const res = await fetch(`/__studio/file?path=${encodeURIComponent(serverPath(path))}`, {
|
|
238
264
|
method: "DELETE",
|
|
239
265
|
});
|
|
240
|
-
if (!res.ok && res.status !== 404)
|
|
266
|
+
if (!res.ok && res.status !== 404) {
|
|
267
|
+
throw new Error(`Failed to delete file: ${path}`);
|
|
268
|
+
}
|
|
241
269
|
},
|
|
242
270
|
|
|
243
271
|
/**
|
|
@@ -246,11 +274,13 @@ export function createDevServerPlatform() {
|
|
|
246
274
|
*/
|
|
247
275
|
async renameFile(from: string, to: string) {
|
|
248
276
|
const res = await fetch("/__studio/file/rename", {
|
|
249
|
-
method: "POST",
|
|
250
|
-
headers: { "Content-Type": "application/json" },
|
|
251
277
|
body: JSON.stringify({ from: serverPath(from), to: serverPath(to) }),
|
|
278
|
+
headers: { "Content-Type": "application/json" },
|
|
279
|
+
method: "POST",
|
|
252
280
|
});
|
|
253
|
-
if (!res.ok)
|
|
281
|
+
if (!res.ok) {
|
|
282
|
+
throw new Error(`Failed to rename: ${from} → ${to}`);
|
|
283
|
+
}
|
|
254
284
|
},
|
|
255
285
|
|
|
256
286
|
/** @param {string} _path */
|
|
@@ -258,18 +288,22 @@ export function createDevServerPlatform() {
|
|
|
258
288
|
// The server creates directories implicitly when writing files.
|
|
259
289
|
// Write a placeholder and delete it, or rely on mkdir behavior.
|
|
260
290
|
// For now, use the writeFile + delete approach if directory creation
|
|
261
|
-
//
|
|
291
|
+
// Is explicitly needed. The server's writeFile already calls mkdir().
|
|
262
292
|
},
|
|
263
293
|
|
|
264
294
|
// ─── Component discovery ──────────────────────────────────────────────
|
|
265
295
|
|
|
266
296
|
/** @param {string} dir */
|
|
267
|
-
async discoverComponents(dir
|
|
297
|
+
async discoverComponents(dir?: string) {
|
|
268
298
|
const scanDir = dir || _projectRoot;
|
|
269
|
-
if (!scanDir)
|
|
299
|
+
if (!scanDir) {
|
|
300
|
+
return [];
|
|
301
|
+
}
|
|
270
302
|
const url = `/__studio/components?dir=${encodeURIComponent(scanDir)}`;
|
|
271
303
|
const res = await fetch(url);
|
|
272
|
-
if (!res.ok)
|
|
304
|
+
if (!res.ok) {
|
|
305
|
+
return [];
|
|
306
|
+
}
|
|
273
307
|
return await res.json();
|
|
274
308
|
},
|
|
275
309
|
|
|
@@ -278,28 +312,34 @@ export function createDevServerPlatform() {
|
|
|
278
312
|
/** @param {string} name */
|
|
279
313
|
async addPackage(name: string) {
|
|
280
314
|
const res = await fetch("/__studio/packages/add", {
|
|
281
|
-
method: "POST",
|
|
282
|
-
headers: { "Content-Type": "application/json" },
|
|
283
315
|
body: JSON.stringify({ name }),
|
|
316
|
+
headers: { "Content-Type": "application/json" },
|
|
317
|
+
method: "POST",
|
|
284
318
|
});
|
|
285
|
-
if (!res.ok)
|
|
319
|
+
if (!res.ok) {
|
|
320
|
+
throw new Error(await res.text());
|
|
321
|
+
}
|
|
286
322
|
return await res.json();
|
|
287
323
|
},
|
|
288
324
|
|
|
289
325
|
/** @param {string} name */
|
|
290
326
|
async removePackage(name: string) {
|
|
291
327
|
const res = await fetch("/__studio/packages/remove", {
|
|
292
|
-
method: "POST",
|
|
293
|
-
headers: { "Content-Type": "application/json" },
|
|
294
328
|
body: JSON.stringify({ name }),
|
|
329
|
+
headers: { "Content-Type": "application/json" },
|
|
330
|
+
method: "POST",
|
|
295
331
|
});
|
|
296
|
-
if (!res.ok)
|
|
332
|
+
if (!res.ok) {
|
|
333
|
+
throw new Error(await res.text());
|
|
334
|
+
}
|
|
297
335
|
return await res.json();
|
|
298
336
|
},
|
|
299
337
|
|
|
300
338
|
async listPackages() {
|
|
301
339
|
const res = await fetch("/__studio/packages");
|
|
302
|
-
if (!res.ok)
|
|
340
|
+
if (!res.ok) {
|
|
341
|
+
return [];
|
|
342
|
+
}
|
|
303
343
|
return await res.json();
|
|
304
344
|
},
|
|
305
345
|
|
|
@@ -312,11 +352,13 @@ export function createDevServerPlatform() {
|
|
|
312
352
|
async codeService(action: string, payload: unknown) {
|
|
313
353
|
try {
|
|
314
354
|
const res = await fetch(`/__studio/code/${action}`, {
|
|
315
|
-
method: "POST",
|
|
316
|
-
headers: { "Content-Type": "application/json" },
|
|
317
355
|
body: JSON.stringify(payload),
|
|
356
|
+
headers: { "Content-Type": "application/json" },
|
|
357
|
+
method: "POST",
|
|
318
358
|
});
|
|
319
|
-
if (!res.ok)
|
|
359
|
+
if (!res.ok) {
|
|
360
|
+
return null;
|
|
361
|
+
}
|
|
320
362
|
return await res.json();
|
|
321
363
|
} catch {
|
|
322
364
|
return null;
|
|
@@ -333,7 +375,9 @@ export function createDevServerPlatform() {
|
|
|
333
375
|
*/
|
|
334
376
|
async resolveSiteContext(filePath: string) {
|
|
335
377
|
const res = await fetch(`/__studio/resolve-site?path=${encodeURIComponent(filePath)}`);
|
|
336
|
-
if (!res.ok)
|
|
378
|
+
if (!res.ok) {
|
|
379
|
+
return { sitePath: null };
|
|
380
|
+
}
|
|
337
381
|
return await res.json();
|
|
338
382
|
},
|
|
339
383
|
|
|
@@ -343,11 +387,14 @@ export function createDevServerPlatform() {
|
|
|
343
387
|
async locateFile(name: string) {
|
|
344
388
|
try {
|
|
345
389
|
const res = await fetch("/__studio/locate", {
|
|
346
|
-
method: "POST",
|
|
347
|
-
headers: { "Content-Type": "application/json" },
|
|
348
390
|
body: JSON.stringify({ name }),
|
|
391
|
+
headers: { "Content-Type": "application/json" },
|
|
392
|
+
method: "POST",
|
|
349
393
|
});
|
|
350
|
-
if (res.ok)
|
|
394
|
+
if (res.ok) {
|
|
395
|
+
const body = await res.json();
|
|
396
|
+
return body.path || null;
|
|
397
|
+
}
|
|
351
398
|
} catch {}
|
|
352
399
|
return null;
|
|
353
400
|
},
|
|
@@ -362,9 +409,13 @@ export function createDevServerPlatform() {
|
|
|
362
409
|
const res = await fetch(
|
|
363
410
|
`/__studio/files?dir=${encodeURIComponent(serverPath("."))}&glob=${encodeURIComponent(glob)}`,
|
|
364
411
|
);
|
|
365
|
-
if (!res.ok)
|
|
412
|
+
if (!res.ok) {
|
|
413
|
+
return [];
|
|
414
|
+
}
|
|
366
415
|
const entries = await res.json();
|
|
367
|
-
for (const e of entries)
|
|
416
|
+
for (const e of entries) {
|
|
417
|
+
e.path = stripRoot(e.path);
|
|
418
|
+
}
|
|
368
419
|
return entries;
|
|
369
420
|
},
|
|
370
421
|
|
|
@@ -373,8 +424,11 @@ export function createDevServerPlatform() {
|
|
|
373
424
|
/** List the project's registered format classes (auto-discovered from imports). */
|
|
374
425
|
async listFormats() {
|
|
375
426
|
const res = await fetch(`/__studio/formats?dir=${encodeURIComponent(serverPath("."))}`);
|
|
376
|
-
if (!res.ok)
|
|
377
|
-
|
|
427
|
+
if (!res.ok) {
|
|
428
|
+
return [];
|
|
429
|
+
}
|
|
430
|
+
const body = await res.json();
|
|
431
|
+
return body.formats ?? [];
|
|
378
432
|
},
|
|
379
433
|
|
|
380
434
|
/**
|
|
@@ -384,12 +438,14 @@ export function createDevServerPlatform() {
|
|
|
384
438
|
*/
|
|
385
439
|
async formatAction(payload: Record<string, unknown>) {
|
|
386
440
|
const res = await fetch("/__studio/format", {
|
|
387
|
-
method: "POST",
|
|
388
|
-
headers: { "Content-Type": "application/json" },
|
|
389
441
|
body: JSON.stringify({ ...payload, dir: serverPath(".") }),
|
|
442
|
+
headers: { "Content-Type": "application/json" },
|
|
443
|
+
method: "POST",
|
|
390
444
|
});
|
|
391
445
|
const data = await res.json();
|
|
392
|
-
if (!res.ok)
|
|
446
|
+
if (!res.ok) {
|
|
447
|
+
throw new Error(data.error || "Format action failed");
|
|
448
|
+
}
|
|
393
449
|
return data.result;
|
|
394
450
|
},
|
|
395
451
|
|
|
@@ -400,12 +456,18 @@ export function createDevServerPlatform() {
|
|
|
400
456
|
* @param {string} prototype
|
|
401
457
|
* @param {string} base
|
|
402
458
|
*/
|
|
403
|
-
async fetchPluginSchema(src: string, prototype
|
|
459
|
+
async fetchPluginSchema(src: string, prototype?: string, base?: string) {
|
|
404
460
|
const params = new URLSearchParams({ src });
|
|
405
|
-
if (prototype)
|
|
406
|
-
|
|
461
|
+
if (prototype) {
|
|
462
|
+
params.set("prototype", prototype);
|
|
463
|
+
}
|
|
464
|
+
if (base) {
|
|
465
|
+
params.set("base", base);
|
|
466
|
+
}
|
|
407
467
|
const res = await fetch(`/__studio/plugin-schema?${params}`);
|
|
408
|
-
if (!res.ok)
|
|
468
|
+
if (!res.ok) {
|
|
469
|
+
return null;
|
|
470
|
+
}
|
|
409
471
|
const { schema } = await res.json();
|
|
410
472
|
return schema;
|
|
411
473
|
},
|
|
@@ -414,13 +476,17 @@ export function createDevServerPlatform() {
|
|
|
414
476
|
|
|
415
477
|
async gitStatus() {
|
|
416
478
|
const res = await fetch("/__studio/git/status");
|
|
417
|
-
if (!res.ok)
|
|
479
|
+
if (!res.ok) {
|
|
480
|
+
throw new Error(await res.text());
|
|
481
|
+
}
|
|
418
482
|
return await res.json();
|
|
419
483
|
},
|
|
420
484
|
|
|
421
485
|
async gitBranches() {
|
|
422
486
|
const res = await fetch("/__studio/git/branches");
|
|
423
|
-
if (!res.ok)
|
|
487
|
+
if (!res.ok) {
|
|
488
|
+
throw new Error(await res.text());
|
|
489
|
+
}
|
|
424
490
|
return await res.json();
|
|
425
491
|
},
|
|
426
492
|
|
|
@@ -428,101 +494,133 @@ export function createDevServerPlatform() {
|
|
|
428
494
|
async gitLog(limit?: number) {
|
|
429
495
|
const q = limit ? `?limit=${limit}` : "";
|
|
430
496
|
const res = await fetch(`/__studio/git/log${q}`);
|
|
431
|
-
if (!res.ok)
|
|
497
|
+
if (!res.ok) {
|
|
498
|
+
throw new Error(await res.text());
|
|
499
|
+
}
|
|
432
500
|
return await res.json();
|
|
433
501
|
},
|
|
434
502
|
|
|
435
503
|
/** @param {string[]} files */
|
|
436
504
|
async gitStage(files: string[]) {
|
|
437
505
|
const res = await fetch("/__studio/git/stage", {
|
|
438
|
-
method: "POST",
|
|
439
|
-
headers: { "Content-Type": "application/json" },
|
|
440
506
|
body: JSON.stringify({ files }),
|
|
507
|
+
headers: { "Content-Type": "application/json" },
|
|
508
|
+
method: "POST",
|
|
441
509
|
});
|
|
442
|
-
if (!res.ok)
|
|
510
|
+
if (!res.ok) {
|
|
511
|
+
const body = await res.json();
|
|
512
|
+
throw new Error(body.error);
|
|
513
|
+
}
|
|
443
514
|
return await res.json();
|
|
444
515
|
},
|
|
445
516
|
|
|
446
517
|
/** @param {string[]} files */
|
|
447
518
|
async gitUnstage(files: string[]) {
|
|
448
519
|
const res = await fetch("/__studio/git/unstage", {
|
|
449
|
-
method: "POST",
|
|
450
|
-
headers: { "Content-Type": "application/json" },
|
|
451
520
|
body: JSON.stringify({ files }),
|
|
521
|
+
headers: { "Content-Type": "application/json" },
|
|
522
|
+
method: "POST",
|
|
452
523
|
});
|
|
453
|
-
if (!res.ok)
|
|
524
|
+
if (!res.ok) {
|
|
525
|
+
const body = await res.json();
|
|
526
|
+
throw new Error(body.error);
|
|
527
|
+
}
|
|
454
528
|
return await res.json();
|
|
455
529
|
},
|
|
456
530
|
|
|
457
531
|
/** @param {string} message */
|
|
458
532
|
async gitCommit(message: string) {
|
|
459
533
|
const res = await fetch("/__studio/git/commit", {
|
|
460
|
-
method: "POST",
|
|
461
|
-
headers: { "Content-Type": "application/json" },
|
|
462
534
|
body: JSON.stringify({ message }),
|
|
535
|
+
headers: { "Content-Type": "application/json" },
|
|
536
|
+
method: "POST",
|
|
463
537
|
});
|
|
464
|
-
if (!res.ok)
|
|
538
|
+
if (!res.ok) {
|
|
539
|
+
const body = await res.json();
|
|
540
|
+
throw new Error(body.error);
|
|
541
|
+
}
|
|
465
542
|
return await res.json();
|
|
466
543
|
},
|
|
467
544
|
|
|
468
545
|
/** @param {{ setUpstream?: boolean }} [opts] */
|
|
469
546
|
async gitPush(opts?: { setUpstream?: boolean }) {
|
|
470
547
|
const res = await fetch("/__studio/git/push", {
|
|
471
|
-
method: "POST",
|
|
472
|
-
headers: { "Content-Type": "application/json" },
|
|
473
548
|
body: JSON.stringify(opts || {}),
|
|
549
|
+
headers: { "Content-Type": "application/json" },
|
|
550
|
+
method: "POST",
|
|
474
551
|
});
|
|
475
|
-
if (!res.ok)
|
|
552
|
+
if (!res.ok) {
|
|
553
|
+
const body = await res.json();
|
|
554
|
+
throw new Error(body.error);
|
|
555
|
+
}
|
|
476
556
|
return await res.json();
|
|
477
557
|
},
|
|
478
558
|
|
|
479
559
|
async gitPull() {
|
|
480
560
|
const res = await fetch("/__studio/git/pull", { method: "POST" });
|
|
481
|
-
if (!res.ok)
|
|
561
|
+
if (!res.ok) {
|
|
562
|
+
const body = await res.json();
|
|
563
|
+
throw new Error(body.error);
|
|
564
|
+
}
|
|
482
565
|
return await res.json();
|
|
483
566
|
},
|
|
484
567
|
|
|
485
568
|
async gitFetch() {
|
|
486
569
|
const res = await fetch("/__studio/git/fetch", { method: "POST" });
|
|
487
|
-
if (!res.ok)
|
|
570
|
+
if (!res.ok) {
|
|
571
|
+
const body = await res.json();
|
|
572
|
+
throw new Error(body.error);
|
|
573
|
+
}
|
|
488
574
|
return await res.json();
|
|
489
575
|
},
|
|
490
576
|
|
|
491
577
|
/** @param {string} branch */
|
|
492
578
|
async gitCheckout(branch: string) {
|
|
493
579
|
const res = await fetch("/__studio/git/checkout", {
|
|
494
|
-
method: "POST",
|
|
495
|
-
headers: { "Content-Type": "application/json" },
|
|
496
580
|
body: JSON.stringify({ branch }),
|
|
581
|
+
headers: { "Content-Type": "application/json" },
|
|
582
|
+
method: "POST",
|
|
497
583
|
});
|
|
498
|
-
if (!res.ok)
|
|
584
|
+
if (!res.ok) {
|
|
585
|
+
const body = await res.json();
|
|
586
|
+
throw new Error(body.error);
|
|
587
|
+
}
|
|
499
588
|
return await res.json();
|
|
500
589
|
},
|
|
501
590
|
|
|
502
591
|
/** @param {string} name */
|
|
503
592
|
async gitCreateBranch(name: string) {
|
|
504
593
|
const res = await fetch("/__studio/git/create-branch", {
|
|
505
|
-
method: "POST",
|
|
506
|
-
headers: { "Content-Type": "application/json" },
|
|
507
594
|
body: JSON.stringify({ name }),
|
|
595
|
+
headers: { "Content-Type": "application/json" },
|
|
596
|
+
method: "POST",
|
|
508
597
|
});
|
|
509
|
-
if (!res.ok)
|
|
598
|
+
if (!res.ok) {
|
|
599
|
+
const body = await res.json();
|
|
600
|
+
throw new Error(body.error);
|
|
601
|
+
}
|
|
510
602
|
return await res.json();
|
|
511
603
|
},
|
|
512
604
|
|
|
513
|
-
/** @param {string} path */
|
|
514
|
-
async gitDiff(path
|
|
515
|
-
const res = await fetch(`/__studio/git/diff?path=${encodeURIComponent(path)}`);
|
|
516
|
-
if (!res.ok)
|
|
605
|
+
/** @param {string} [path] */
|
|
606
|
+
async gitDiff(path?: string) {
|
|
607
|
+
const res = await fetch(`/__studio/git/diff?path=${encodeURIComponent(path ?? "")}`);
|
|
608
|
+
if (!res.ok) {
|
|
609
|
+
throw new Error(await res.text());
|
|
610
|
+
}
|
|
517
611
|
return await res.json();
|
|
518
612
|
},
|
|
519
613
|
|
|
520
614
|
/** @param {{ path: string; ref?: string }} opts */
|
|
521
615
|
async gitShow(opts: { path: string; ref?: string }) {
|
|
522
616
|
const params = new URLSearchParams({ path: opts.path });
|
|
523
|
-
if (opts.ref)
|
|
617
|
+
if (opts.ref) {
|
|
618
|
+
params.set("ref", opts.ref);
|
|
619
|
+
}
|
|
524
620
|
const res = await fetch(`/__studio/git/show?${params}`);
|
|
525
|
-
if (!res.ok)
|
|
621
|
+
if (!res.ok) {
|
|
622
|
+
throw new Error(await res.text());
|
|
623
|
+
}
|
|
526
624
|
const data = await res.json();
|
|
527
625
|
return data.content;
|
|
528
626
|
},
|
|
@@ -530,28 +628,37 @@ export function createDevServerPlatform() {
|
|
|
530
628
|
/** @param {string[]} files */
|
|
531
629
|
async gitDiscard(files: string[]) {
|
|
532
630
|
const res = await fetch("/__studio/git/discard", {
|
|
533
|
-
method: "POST",
|
|
534
|
-
headers: { "Content-Type": "application/json" },
|
|
535
631
|
body: JSON.stringify({ files }),
|
|
632
|
+
headers: { "Content-Type": "application/json" },
|
|
633
|
+
method: "POST",
|
|
536
634
|
});
|
|
537
|
-
if (!res.ok)
|
|
635
|
+
if (!res.ok) {
|
|
636
|
+
const body = await res.json();
|
|
637
|
+
throw new Error(body.error);
|
|
638
|
+
}
|
|
538
639
|
return await res.json();
|
|
539
640
|
},
|
|
540
641
|
|
|
541
642
|
/** @param {string} url */
|
|
542
643
|
async gitClone(url: string) {
|
|
543
644
|
const res = await fetch("/__studio/git/clone", {
|
|
544
|
-
method: "POST",
|
|
545
|
-
headers: { "Content-Type": "application/json" },
|
|
546
645
|
body: JSON.stringify({ url }),
|
|
646
|
+
headers: { "Content-Type": "application/json" },
|
|
647
|
+
method: "POST",
|
|
547
648
|
});
|
|
548
|
-
if (!res.ok)
|
|
649
|
+
if (!res.ok) {
|
|
650
|
+
const body = await res.json();
|
|
651
|
+
throw new Error(body.error);
|
|
652
|
+
}
|
|
549
653
|
return await res.json();
|
|
550
654
|
},
|
|
551
655
|
|
|
552
656
|
async gitInit() {
|
|
553
657
|
const res = await fetch("/__studio/git/init", { method: "POST" });
|
|
554
|
-
if (!res.ok)
|
|
658
|
+
if (!res.ok) {
|
|
659
|
+
const body = await res.json();
|
|
660
|
+
throw new Error(body.error);
|
|
661
|
+
}
|
|
555
662
|
},
|
|
556
663
|
|
|
557
664
|
/**
|
|
@@ -560,11 +667,14 @@ export function createDevServerPlatform() {
|
|
|
560
667
|
*/
|
|
561
668
|
async gitAddRemote(name: string, url: string) {
|
|
562
669
|
const res = await fetch("/__studio/git/add-remote", {
|
|
563
|
-
method: "POST",
|
|
564
|
-
headers: { "Content-Type": "application/json" },
|
|
565
670
|
body: JSON.stringify({ name, url }),
|
|
671
|
+
headers: { "Content-Type": "application/json" },
|
|
672
|
+
method: "POST",
|
|
566
673
|
});
|
|
567
|
-
if (!res.ok)
|
|
674
|
+
if (!res.ok) {
|
|
675
|
+
const body = await res.json();
|
|
676
|
+
throw new Error(body.error);
|
|
677
|
+
}
|
|
568
678
|
},
|
|
569
679
|
|
|
570
680
|
// ─── AI Assistant ───────────────────────────────────
|
|
@@ -577,22 +687,28 @@ export function createDevServerPlatform() {
|
|
|
577
687
|
/** @param {{ message: string; systemPrompt?: string }} opts */
|
|
578
688
|
async aiCreateSession(opts: { message: string; systemPrompt?: string }) {
|
|
579
689
|
const res = await fetch("/__studio/ai/session", {
|
|
580
|
-
method: "POST",
|
|
581
|
-
headers: { "Content-Type": "application/json" },
|
|
582
690
|
body: JSON.stringify(opts),
|
|
691
|
+
headers: { "Content-Type": "application/json" },
|
|
692
|
+
method: "POST",
|
|
583
693
|
});
|
|
584
|
-
if (!res.ok)
|
|
694
|
+
if (!res.ok) {
|
|
695
|
+
const body = await res.json();
|
|
696
|
+
throw new Error(body.error);
|
|
697
|
+
}
|
|
585
698
|
return await res.json();
|
|
586
699
|
},
|
|
587
700
|
|
|
588
701
|
/** @param {string} id @param {string} message */
|
|
589
702
|
async aiSendMessage(id: string, message: string) {
|
|
590
703
|
const res = await fetch(`/__studio/ai/session/${id}/message`, {
|
|
591
|
-
method: "POST",
|
|
592
|
-
headers: { "Content-Type": "application/json" },
|
|
593
704
|
body: JSON.stringify({ message }),
|
|
705
|
+
headers: { "Content-Type": "application/json" },
|
|
706
|
+
method: "POST",
|
|
594
707
|
});
|
|
595
|
-
if (!res.ok)
|
|
708
|
+
if (!res.ok) {
|
|
709
|
+
const body = await res.json();
|
|
710
|
+
throw new Error(body.error);
|
|
711
|
+
}
|
|
596
712
|
return await res.json();
|
|
597
713
|
},
|
|
598
714
|
|