@jxsuite/studio 0.37.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/iframe-entry.js +622 -49
- package/dist/iframe-entry.js.map +15 -12
- package/dist/studio.css +1333 -0
- package/dist/studio.js +103709 -81001
- package/dist/studio.js.map +201 -157
- package/package.json +47 -45
- package/src/account-status.ts +39 -0
- package/src/browse/browse.ts +10 -14
- package/src/canvas/canvas-live-render.ts +21 -2
- package/src/canvas/canvas-render.ts +35 -16
- package/src/canvas/canvas-utils.ts +118 -72
- package/src/canvas/iframe-entry.ts +20 -0
- package/src/canvas/iframe-eval.ts +155 -0
- package/src/canvas/iframe-host.ts +132 -6
- package/src/canvas/iframe-inline-edit.ts +107 -1
- package/src/canvas/iframe-protocol.ts +43 -3
- package/src/canvas/iframe-render.ts +18 -0
- package/src/collab/collab-session.ts +23 -8
- package/src/collab/collab-state.ts +6 -3
- package/src/component-props.ts +104 -0
- package/src/editor/context-menu.ts +1 -1
- package/src/editor/inline-edit-apply.ts +36 -1
- package/src/editor/inline-edit.ts +58 -1
- package/src/editor/repeater-scope.ts +8 -13
- package/src/editor/shortcuts.ts +41 -12
- package/src/files/file-ops.ts +14 -0
- package/src/files/files.ts +56 -1
- package/src/format/format-host.ts +63 -1
- package/src/grid/cell-editors.ts +288 -0
- package/src/grid/cell-popovers.ts +108 -0
- package/src/grid/csv-codec.ts +122 -0
- package/src/grid/edit-buffer.ts +490 -0
- package/src/grid/grid-controller.ts +417 -0
- package/src/grid/grid-layout.ts +83 -0
- package/src/grid/grid-open.ts +167 -0
- package/src/grid/grid-panel.ts +302 -0
- package/src/grid/grid-source.ts +210 -0
- package/src/grid/grid-view.ts +367 -0
- package/src/grid/schema-columns.ts +261 -0
- package/src/grid/sources/connector-source.ts +217 -0
- package/src/grid/sources/content-source.ts +542 -0
- package/src/grid/sources/csv-file-source.ts +247 -0
- package/src/grid/tabulator-tables.d.ts +120 -0
- package/src/new-project/add-repo-modal.ts +183 -0
- package/src/new-project/new-project-modal.ts +22 -3
- package/src/page-params.ts +34 -8
- package/src/panels/ai-chat/chat-markdown.ts +2 -2
- package/src/panels/ai-panel.ts +61 -4
- package/src/panels/block-action-bar.ts +8 -3
- package/src/panels/chat-panel.ts +98 -0
- package/src/panels/data-grid.ts +241 -0
- package/src/panels/editors.ts +43 -17
- package/src/panels/events-panel.ts +137 -44
- package/src/panels/formula-workspace.ts +379 -0
- package/src/panels/frontmatter-fields.ts +231 -0
- package/src/panels/frontmatter-panel.ts +132 -0
- package/src/panels/git-panel.ts +1 -1
- package/src/panels/head-panel.ts +11 -175
- package/src/panels/properties-panel.ts +154 -144
- package/src/panels/right-panel.ts +9 -47
- package/src/panels/signals-panel.ts +217 -460
- package/src/panels/statement-editor.ts +710 -0
- package/src/panels/statusbar.ts +1 -1
- package/src/panels/style-panel.ts +25 -1
- package/src/panels/stylebook-panel.ts +0 -2
- package/src/panels/tab-bar.ts +175 -6
- package/src/panels/tab-strip.ts +62 -6
- package/src/panels/toolbar.ts +37 -3
- package/src/panels/welcome-screen.ts +50 -0
- package/src/platform-errors.ts +30 -0
- package/src/platforms/cloud.ts +172 -89
- package/src/platforms/devserver.ts +172 -0
- package/src/services/ai-project-tools.ts +541 -0
- package/src/services/ai-session-store.ts +28 -0
- package/src/services/ai-system-prompt.ts +194 -24
- package/src/services/ai-tools.ts +88 -21
- package/src/services/automation.ts +16 -0
- package/src/services/context-resolver.ts +73 -0
- package/src/services/data-service.ts +155 -0
- package/src/services/document-assistant.ts +81 -11
- package/src/services/gated-registry.ts +72 -0
- package/src/services/live-preview.ts +0 -0
- package/src/services/monaco-setup.ts +75 -26
- package/src/services/preview-eval.ts +68 -0
- package/src/services/project-adoption.ts +31 -0
- package/src/settings/contributed-section.ts +406 -0
- package/src/settings/extension-sections.ts +145 -0
- package/src/settings/schema-field-ui.ts +4 -2
- package/src/settings/settings-modal.ts +101 -42
- package/src/site-context.ts +12 -1
- package/src/store.ts +4 -0
- package/src/studio.ts +107 -52
- package/src/tabs/patch-ops.ts +25 -0
- package/src/tabs/tab.ts +39 -1
- package/src/tabs/transact.ts +61 -14
- package/src/types.ts +132 -1
- package/src/ui/dynamic-slot.ts +272 -0
- package/src/ui/expression-editor.ts +423 -125
- package/src/ui/field-row.ts +5 -0
- package/src/ui/form-controls.ts +322 -0
- package/src/ui/formula-catalog.ts +557 -0
- package/src/ui/formula-chips.ts +216 -0
- package/src/ui/formula-palette.ts +211 -0
- package/src/ui/layers.ts +40 -0
- package/src/ui/media-picker.ts +1 -1
- package/src/ui/panel-resize.ts +15 -1
- package/src/ui/progress-modal.ts +2 -2
- package/src/ui/schema-form.ts +524 -0
- package/src/utils/preview-format.ts +26 -0
- package/src/utils/studio-utils.ts +4 -3
- package/src/view.ts +4 -4
- package/src/workspace/workspace.ts +14 -0
- package/src/settings/content-types-editor.ts +0 -599
package/src/tabs/tab.ts
CHANGED
|
@@ -4,14 +4,16 @@ import { formatByName, formatForPath } from "../format/format-host";
|
|
|
4
4
|
import { normalizeArrayChildren } from "../state";
|
|
5
5
|
import type {
|
|
6
6
|
DocumentStackEntry,
|
|
7
|
+
FormulaEditDef,
|
|
7
8
|
FunctionEditDef,
|
|
8
9
|
GitBranchesResult,
|
|
9
10
|
GitDiffState,
|
|
10
11
|
GitStatusResult,
|
|
11
12
|
InlineEditDef,
|
|
13
|
+
JsonValue,
|
|
12
14
|
} from "../types";
|
|
13
15
|
import type { JxMutableNode } from "@jxsuite/schema/types";
|
|
14
|
-
import type { JxDocOp } from "./patch-ops";
|
|
16
|
+
import type { JxDocOp, JxFmOp } from "./patch-ops";
|
|
15
17
|
|
|
16
18
|
export interface TabUi {
|
|
17
19
|
rightTab: string;
|
|
@@ -20,12 +22,26 @@ export interface TabUi {
|
|
|
20
22
|
preview: boolean;
|
|
21
23
|
/** Show elements inherited from the page's layout (pages with an effective layout only). */
|
|
22
24
|
showLayout: boolean;
|
|
25
|
+
/** Above-canvas frontmatter Properties accordion expanded (content-collection docs, edit mode). */
|
|
26
|
+
frontmatterOpen: boolean;
|
|
23
27
|
/** Chosen literal values for dynamic route params (e.g. { sku: "mini-trencher" }). */
|
|
24
28
|
previewParams: Record<string, string>;
|
|
29
|
+
/**
|
|
30
|
+
* Chosen test values for a component doc's props (state entries), seeded into the canvas render
|
|
31
|
+
* so a non-instantiated component previews with real data (M6) — the previewParams mirror.
|
|
32
|
+
*/
|
|
33
|
+
previewProps: Record<string, JsonValue> | null;
|
|
25
34
|
zoom: number;
|
|
35
|
+
/**
|
|
36
|
+
* Edit-mode content zoom — browser-page-zoom semantics (content reflows at the zoomed effective
|
|
37
|
+
* width while the canvas footprint stays fixed), unlike `zoom` which pan/zooms the whole canvas.
|
|
38
|
+
*/
|
|
39
|
+
editZoom: number;
|
|
26
40
|
activeMedia: string | null;
|
|
27
41
|
activeSelector: string | null;
|
|
28
42
|
editingFunction: FunctionEditDef | null;
|
|
43
|
+
/** Full-screen formula workspace target ($expression editing); editingFunction wins if both set. */
|
|
44
|
+
editingFormula: FormulaEditDef | null;
|
|
29
45
|
featureToggles: Record<string, boolean>;
|
|
30
46
|
styleSections: Record<string, boolean>;
|
|
31
47
|
inspectorSections: Record<string, boolean>;
|
|
@@ -46,6 +62,18 @@ export interface TabUi {
|
|
|
46
62
|
pendingInlineEdit: InlineEditDef | null;
|
|
47
63
|
}
|
|
48
64
|
|
|
65
|
+
/**
|
|
66
|
+
* A live (iframe-evaluated) expression preview retained per editing target (M6). Stored on
|
|
67
|
+
* `session.canvas` beside `scope` — plain wire data (path-key → display-string pairs), rebuilt into
|
|
68
|
+
* an ExpressionPreview by services/live-preview.ts on read.
|
|
69
|
+
*/
|
|
70
|
+
export interface StoredLivePreview {
|
|
71
|
+
/** Serialized expression + context the values were computed for (staleness check). */
|
|
72
|
+
key: string;
|
|
73
|
+
values: [string, string][];
|
|
74
|
+
error: string | null;
|
|
75
|
+
}
|
|
76
|
+
|
|
49
77
|
interface HistorySnapshot {
|
|
50
78
|
/** Full document at this state (checkpoint), or null when the ops describe the transition. */
|
|
51
79
|
document: Record<string, unknown> | null;
|
|
@@ -57,6 +85,8 @@ interface HistorySnapshot {
|
|
|
57
85
|
forwardOps?: JxDocOp[] | null;
|
|
58
86
|
/** Replayable ops transforming this state back into the previous one. */
|
|
59
87
|
inverseOps?: JxDocOp[] | null;
|
|
88
|
+
/** Frontmatter key changes in this transaction (before/after values, replayed both ways). */
|
|
89
|
+
fmOps?: JxFmOp[] | null;
|
|
60
90
|
}
|
|
61
91
|
|
|
62
92
|
export interface Tab {
|
|
@@ -89,6 +119,9 @@ export interface Tab {
|
|
|
89
119
|
// The bridge as a `dataScope` message and read by the data-explorer panel. Plain data now —
|
|
90
120
|
// The old live `EffectScope` (with `.stop()`) moved into the iframe realm with buildScope.
|
|
91
121
|
scope: Record<string, unknown> | null;
|
|
122
|
+
// Latest live (iframe-evaluated) expression previews keyed by editing-target id, stored
|
|
123
|
+
// Beside `scope` the same way (services/live-preview.ts owns reads/writes).
|
|
124
|
+
livePreviews: Record<string, StoredLivePreview> | null;
|
|
92
125
|
error: string | null;
|
|
93
126
|
pendingInlineEdit: InlineEditDef | null;
|
|
94
127
|
};
|
|
@@ -109,8 +142,11 @@ function createDefaultUi(canvasMode: string, preview = false) {
|
|
|
109
142
|
activeMedia: null,
|
|
110
143
|
activeSelector: null,
|
|
111
144
|
canvasMode,
|
|
145
|
+
editZoom: 1,
|
|
146
|
+
editingFormula: null,
|
|
112
147
|
editingFunction: null,
|
|
113
148
|
featureToggles: {},
|
|
149
|
+
frontmatterOpen: true,
|
|
114
150
|
gitBranches: null,
|
|
115
151
|
gitCommitMessage: "",
|
|
116
152
|
gitDiffState: null,
|
|
@@ -121,6 +157,7 @@ function createDefaultUi(canvasMode: string, preview = false) {
|
|
|
121
157
|
pendingInlineEdit: null,
|
|
122
158
|
preview,
|
|
123
159
|
previewParams: {},
|
|
160
|
+
previewProps: null,
|
|
124
161
|
rightTab: "properties",
|
|
125
162
|
settingsTab: "stylebook",
|
|
126
163
|
showLayout: true,
|
|
@@ -204,6 +241,7 @@ export function createTab({
|
|
|
204
241
|
session: reactive({
|
|
205
242
|
canvas: {
|
|
206
243
|
error: null,
|
|
244
|
+
livePreviews: null,
|
|
207
245
|
pendingInlineEdit: null,
|
|
208
246
|
scope: null,
|
|
209
247
|
status: "idle",
|
package/src/tabs/transact.ts
CHANGED
|
@@ -8,16 +8,23 @@ import {
|
|
|
8
8
|
endRecording,
|
|
9
9
|
getPatchConsumer,
|
|
10
10
|
recordDocOp,
|
|
11
|
+
recordFmOp,
|
|
11
12
|
recordPatch,
|
|
12
13
|
} from "./patch-ops";
|
|
13
14
|
|
|
14
|
-
import type { JxDocOp, JxDocOpPair, TransactionRecord } from "./patch-ops";
|
|
15
|
+
import type { JxDocOp, JxDocOpPair, JxFmOp, TransactionRecord } from "./patch-ops";
|
|
15
16
|
|
|
16
17
|
import type { Tab } from "../tabs/tab";
|
|
17
18
|
import type { JxPath } from "../state";
|
|
18
19
|
|
|
19
20
|
import type { JsonValue } from "../types";
|
|
20
|
-
import type {
|
|
21
|
+
import type {
|
|
22
|
+
JxAttributeValue,
|
|
23
|
+
JxEventBinding,
|
|
24
|
+
JxMutableNode,
|
|
25
|
+
JxStateObject,
|
|
26
|
+
JxStyle,
|
|
27
|
+
} from "@jxsuite/schema/types";
|
|
21
28
|
import { ensureNestedStyle, getNestedStyle, isEventBinding } from "@jxsuite/schema/guards";
|
|
22
29
|
|
|
23
30
|
const HISTORY_LIMIT = 100;
|
|
@@ -205,10 +212,14 @@ function pushHistoryEntry(
|
|
|
205
212
|
selectionBefore: JxPath | null,
|
|
206
213
|
) {
|
|
207
214
|
const truncated = tab.history.snapshots.slice(0, tab.history.index + 1);
|
|
208
|
-
const useOps =
|
|
215
|
+
const useOps =
|
|
216
|
+
patchHistoryEnabled() &&
|
|
217
|
+
record.invertible &&
|
|
218
|
+
(record.docOps.length > 0 || record.fmOps.length > 0);
|
|
209
219
|
const needCheckpoint = !useOps || truncated.length % CHECKPOINT_INTERVAL === 0;
|
|
210
220
|
truncated.push({
|
|
211
221
|
document: needCheckpoint ? jsonClone(raw) : null,
|
|
222
|
+
fmOps: useOps && record.fmOps.length > 0 ? record.fmOps : null,
|
|
212
223
|
forwardOps: useOps ? record.docOps.map((p) => p.forward) : null,
|
|
213
224
|
inverseOps: useOps ? record.docOps.map((p) => p.inverse) : null,
|
|
214
225
|
selection: tab.session.selection ? [...tab.session.selection] : null,
|
|
@@ -343,7 +354,7 @@ function applyDocOp(tab: Tab, op: JxDocOp) {
|
|
|
343
354
|
toIndex: op.toIndex,
|
|
344
355
|
toParentPath: op.toParentPath,
|
|
345
356
|
});
|
|
346
|
-
|
|
357
|
+
break;
|
|
347
358
|
}
|
|
348
359
|
default: {
|
|
349
360
|
break;
|
|
@@ -471,14 +482,23 @@ export function undo(tab: Tab) {
|
|
|
471
482
|
}
|
|
472
483
|
const entry = tab.history.snapshots[tab.history.index]!;
|
|
473
484
|
const inverseOps = patchHistoryEnabled() ? entry.inverseOps : null;
|
|
474
|
-
|
|
485
|
+
const fmOps = patchHistoryEnabled() ? entry.fmOps : null;
|
|
486
|
+
if ((inverseOps && inverseOps.length > 0) || (fmOps && fmOps.length > 0)) {
|
|
475
487
|
// Surgical path: apply inverse ops through the normal transaction pipeline (the canvas
|
|
476
488
|
// Patches in place when it can), in reverse recording order.
|
|
477
489
|
transactDoc(
|
|
478
490
|
tab,
|
|
479
491
|
(t) => {
|
|
480
|
-
|
|
481
|
-
|
|
492
|
+
if (inverseOps) {
|
|
493
|
+
for (let i = inverseOps.length - 1; i >= 0; i--) {
|
|
494
|
+
applyDocOp(t, toRaw(inverseOps[i]) as JxDocOp);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
if (fmOps) {
|
|
498
|
+
for (let i = fmOps.length - 1; i >= 0; i--) {
|
|
499
|
+
const op = toRaw(fmOps[i]) as JxFmOp;
|
|
500
|
+
applyFmState(t, op.field, op.before);
|
|
501
|
+
}
|
|
482
502
|
}
|
|
483
503
|
},
|
|
484
504
|
{ origin: "history", skipHistory: true },
|
|
@@ -505,12 +525,21 @@ export function redo(tab: Tab) {
|
|
|
505
525
|
}
|
|
506
526
|
const entry = tab.history.snapshots[tab.history.index + 1]!;
|
|
507
527
|
const forwardOps = patchHistoryEnabled() ? entry.forwardOps : null;
|
|
508
|
-
|
|
528
|
+
const fmOps = patchHistoryEnabled() ? entry.fmOps : null;
|
|
529
|
+
if ((forwardOps && forwardOps.length > 0) || (fmOps && fmOps.length > 0)) {
|
|
509
530
|
transactDoc(
|
|
510
531
|
tab,
|
|
511
532
|
(t) => {
|
|
512
|
-
|
|
513
|
-
|
|
533
|
+
if (forwardOps) {
|
|
534
|
+
for (const op of forwardOps) {
|
|
535
|
+
applyDocOp(t, toRaw(op) as JxDocOp);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
if (fmOps) {
|
|
539
|
+
for (const op of fmOps) {
|
|
540
|
+
const raw = toRaw(op) as JxFmOp;
|
|
541
|
+
applyFmState(t, raw.field, raw.after);
|
|
542
|
+
}
|
|
514
543
|
}
|
|
515
544
|
},
|
|
516
545
|
{ origin: "history", skipHistory: true },
|
|
@@ -746,13 +775,13 @@ export function mutateUpdateStyle(tab: Tab, path: JxPath, prop: string, value: s
|
|
|
746
775
|
* @param {Tab} tab
|
|
747
776
|
* @param {JxPath} path
|
|
748
777
|
* @param {string} attr
|
|
749
|
-
* @param {
|
|
778
|
+
* @param {JxAttributeValue | undefined} value — a literal, `$ref` binding, or `${}` template.
|
|
750
779
|
*/
|
|
751
780
|
export function mutateUpdateAttribute(
|
|
752
781
|
tab: Tab,
|
|
753
782
|
path: JxPath,
|
|
754
783
|
attr: string,
|
|
755
|
-
value?:
|
|
784
|
+
value?: JxAttributeValue | undefined,
|
|
756
785
|
) {
|
|
757
786
|
const node = getNodeAtPath(tab.doc.document, path);
|
|
758
787
|
const attrsBefore = cloneValue(node.attributes);
|
|
@@ -1196,10 +1225,28 @@ export function mutateRenameSwitchCase(tab: Tab, path: JxPath, oldName: string,
|
|
|
1196
1225
|
* @param {JsonValue} value
|
|
1197
1226
|
*/
|
|
1198
1227
|
export function mutateUpdateFrontmatter(tab: Tab, field: string, value?: JsonValue) {
|
|
1199
|
-
|
|
1228
|
+
const fm = tab.doc.content.frontmatter;
|
|
1229
|
+
const before = Object.hasOwn(fm, field) ? cloneValue(fm[field]) : undefined;
|
|
1230
|
+
const deletes = value === undefined || value === null || value === "";
|
|
1231
|
+
if (deletes) {
|
|
1232
|
+
delete fm[field];
|
|
1233
|
+
} else {
|
|
1234
|
+
fm[field] = value;
|
|
1235
|
+
}
|
|
1236
|
+
const after = deletes ? undefined : cloneValue(value);
|
|
1237
|
+
recordFmOp({ after, before, field });
|
|
1238
|
+
tab.doc.dirty = true;
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
/**
|
|
1242
|
+
* Restore a frontmatter key to a recorded history state: `undefined` means the key was absent.
|
|
1243
|
+
* Unlike `mutateUpdateFrontmatter`, values like `""`/`false`/`null` are written verbatim (source
|
|
1244
|
+
* round-trips can put them there) and no fm op is recorded — history replay must not re-record.
|
|
1245
|
+
*/
|
|
1246
|
+
function applyFmState(tab: Tab, field: string, value: unknown) {
|
|
1247
|
+
if (value === undefined) {
|
|
1200
1248
|
delete tab.doc.content.frontmatter[field];
|
|
1201
1249
|
} else {
|
|
1202
1250
|
tab.doc.content.frontmatter[field] = value;
|
|
1203
1251
|
}
|
|
1204
|
-
tab.doc.dirty = true;
|
|
1205
1252
|
}
|
package/src/types.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
/// <reference lib="dom" />
|
|
2
2
|
import type { CollabHandle } from "@jxsuite/collab/provider";
|
|
3
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
ContentTypeSchema,
|
|
5
|
+
JxMutableNode,
|
|
6
|
+
JxPath,
|
|
7
|
+
ProjectConfig,
|
|
8
|
+
} from "@jxsuite/schema/types";
|
|
4
9
|
|
|
5
10
|
// ─── Wire types (the Studio Backend Protocol) ───────────────────────────────
|
|
6
11
|
/* The request/response shapes every backend serves live in @jxsuite/protocol;
|
|
@@ -11,7 +16,16 @@ import type {
|
|
|
11
16
|
CfConnection,
|
|
12
17
|
CodeServiceResult,
|
|
13
18
|
ComponentMeta,
|
|
19
|
+
DataConnectionsResponse,
|
|
20
|
+
DataConnectionTestResult,
|
|
21
|
+
DataPushResult,
|
|
22
|
+
DataRowDelete,
|
|
23
|
+
DataRowInsert,
|
|
24
|
+
DataRowsQuery,
|
|
25
|
+
DataRowsResult,
|
|
26
|
+
DataRowUpdate,
|
|
14
27
|
DirEntry,
|
|
28
|
+
ExtensionsInfo,
|
|
15
29
|
FsEvent,
|
|
16
30
|
GitBranchesResult,
|
|
17
31
|
GitLogEntry,
|
|
@@ -22,8 +36,11 @@ import type {
|
|
|
22
36
|
PackageInfo,
|
|
23
37
|
PackageOpResult,
|
|
24
38
|
ProjectListEntry,
|
|
39
|
+
ProjectSchemasResponse,
|
|
25
40
|
RecentProjectEntry,
|
|
26
41
|
RenameResult,
|
|
42
|
+
SecretsSetRequest,
|
|
43
|
+
SecretsSetResponse,
|
|
27
44
|
StarterInfo,
|
|
28
45
|
} from "@jxsuite/protocol";
|
|
29
46
|
|
|
@@ -35,8 +52,24 @@ export type {
|
|
|
35
52
|
CodeServiceResult,
|
|
36
53
|
ComponentMeta,
|
|
37
54
|
ComponentSlotMeta,
|
|
55
|
+
DataColumnMeta,
|
|
56
|
+
DataConnectionInfo,
|
|
57
|
+
DataConnectionsResponse,
|
|
58
|
+
DataConnectionTestResult,
|
|
59
|
+
DataConnectorInfo,
|
|
60
|
+
DataPushRequest,
|
|
61
|
+
DataPushResult,
|
|
62
|
+
DataPushStep,
|
|
63
|
+
DataRowDelete,
|
|
64
|
+
DataRowInsert,
|
|
65
|
+
DataRowsQuery,
|
|
66
|
+
DataRowsResult,
|
|
67
|
+
DataRowUpdate,
|
|
38
68
|
DirEntry,
|
|
39
69
|
ErrorBody,
|
|
70
|
+
ExtensionContributionInfo,
|
|
71
|
+
ExtensionProjectBlock,
|
|
72
|
+
ExtensionsInfo,
|
|
40
73
|
FsEvent,
|
|
41
74
|
GitBranchesResult,
|
|
42
75
|
GitFileStatus,
|
|
@@ -49,12 +82,36 @@ export type {
|
|
|
49
82
|
PackageInfo,
|
|
50
83
|
PackageOpResult,
|
|
51
84
|
ProjectListEntry,
|
|
85
|
+
ProjectSchemasResponse,
|
|
52
86
|
PullRequestInfo,
|
|
53
87
|
RecentProjectEntry,
|
|
54
88
|
RenameResult,
|
|
89
|
+
SecretsListResponse,
|
|
90
|
+
SecretsSetRequest,
|
|
91
|
+
SecretsSetResponse,
|
|
55
92
|
StarterInfo,
|
|
56
93
|
} from "@jxsuite/protocol";
|
|
57
94
|
|
|
95
|
+
/** Repository-access onboarding state returned by `StudioPlatform.getAccountStatus`. */
|
|
96
|
+
export interface AccountStatus {
|
|
97
|
+
/** GitHub App installations (personal + organization) visible to the signed-in user. */
|
|
98
|
+
installations: { id: number; account: string | null }[];
|
|
99
|
+
/** Where to install the App (github.com/apps/<slug>/installations/new), when known. */
|
|
100
|
+
appInstallUrl?: string;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** A repository visible to `StudioPlatform.listRepos` (the add-existing-repository picker). */
|
|
104
|
+
export interface RepoInfo {
|
|
105
|
+
owner: string;
|
|
106
|
+
name: string;
|
|
107
|
+
fullName: string;
|
|
108
|
+
private: boolean;
|
|
109
|
+
defaultBranch: string;
|
|
110
|
+
permission: "admin" | "write" | "read" | "none";
|
|
111
|
+
/** Already recognized as a Jx project (topic-tagged / cataloged). */
|
|
112
|
+
isJxProject: boolean;
|
|
113
|
+
}
|
|
114
|
+
|
|
58
115
|
export interface StudioPlatform {
|
|
59
116
|
id: string;
|
|
60
117
|
projectRoot: string;
|
|
@@ -126,8 +183,39 @@ export interface StudioPlatform {
|
|
|
126
183
|
searchFiles: (query: string, extensions?: string[]) => Promise<DirEntry[]>;
|
|
127
184
|
/** List the project's registered format classes (auto-discovered from imports). */
|
|
128
185
|
listFormats?: () => Promise<unknown[]>;
|
|
186
|
+
/**
|
|
187
|
+
* List the project's enabled extension packages with their project-section contributions
|
|
188
|
+
* (specs/extensions.md §9/§9.1) — the formats route's sibling `extensions` payload. Optional:
|
|
189
|
+
* platforms without it lose descriptor-contributed settings sections.
|
|
190
|
+
*/
|
|
191
|
+
listExtensions?: () => Promise<ExtensionsInfo[]>;
|
|
192
|
+
/**
|
|
193
|
+
* Fetch the project's generated entry schemas (project.schema.json / document.schema.json),
|
|
194
|
+
* PRE-BUNDLED into self-contained documents for editor registration. Optional: without it the
|
|
195
|
+
* JSON editor keeps the bundled core schemas.
|
|
196
|
+
*/
|
|
197
|
+
fetchProjectSchemas?: () => Promise<ProjectSchemasResponse>;
|
|
129
198
|
/** Invoke a format capability (parse/serialize) — { format, action, source?, doc?, options? }. */
|
|
130
199
|
formatAction?: (payload: Record<string, unknown>) => Promise<unknown>;
|
|
200
|
+
// ─── Data surface + secrets (owner console; specs/extensions.md §13) ────────
|
|
201
|
+
// Optional as a family: backends without the connector data routes omit them all, and Studio
|
|
202
|
+
// Hides the data grid and connection/push/test actions. Row CRUD is the ADMIN path — it
|
|
203
|
+
// Intentionally bypasses table permission rules; the backend boundary is the gate.
|
|
204
|
+
/** List connector connections with configured state, table names, and provider metadata. */
|
|
205
|
+
dataConnections?: () => Promise<DataConnectionsResponse>;
|
|
206
|
+
/** Probe one connection through the backend's connector registry. */
|
|
207
|
+
dataConnectionTest?: (connection: string) => Promise<DataConnectionTestResult>;
|
|
208
|
+
/** Additive schema push; `dryRun` compiles the plan without applying it. */
|
|
209
|
+
dataPush?: (opts?: { connection?: string; dryRun?: boolean }) => Promise<DataPushResult>;
|
|
210
|
+
/** Page a table's rows with introspected column metadata. */
|
|
211
|
+
dataRows?: (query: DataRowsQuery) => Promise<DataRowsResult>;
|
|
212
|
+
dataInsertRow?: (req: DataRowInsert) => Promise<{ row: Record<string, unknown> }>;
|
|
213
|
+
dataUpdateRow?: (req: DataRowUpdate) => Promise<{ row: Record<string, unknown> }>;
|
|
214
|
+
dataDeleteRow?: (req: DataRowDelete) => Promise<{ ok: boolean }>;
|
|
215
|
+
/** Configured secret env-var NAMES — never values. */
|
|
216
|
+
listSecrets?: () => Promise<string[]>;
|
|
217
|
+
/** Write/remove secrets in the backend store (.dev.vars locally); names-only response. */
|
|
218
|
+
setSecrets?: (req: SecretsSetRequest) => Promise<SecretsSetResponse>;
|
|
131
219
|
fetchPluginSchema: (src: string, prototype?: string, base?: string) => Promise<unknown>;
|
|
132
220
|
/**
|
|
133
221
|
* Resolve a class-prototype config through the backend's `/__jx_resolve__` pipeline (with the
|
|
@@ -235,6 +323,25 @@ export interface StudioPlatform {
|
|
|
235
323
|
// ─── Identity & hosting connections (publish surface) ───────────────────────
|
|
236
324
|
/** The signed-in user's identity, when the platform has one (cloud). */
|
|
237
325
|
getUser?: () => Promise<{ login: string; name?: string; avatarUrl?: string } | null>;
|
|
326
|
+
/**
|
|
327
|
+
* Repository-access onboarding state: the platform's GitHub App installations visible to this
|
|
328
|
+
* user and where to install the App. Cloud-only; when the list is empty Studio's welcome screen
|
|
329
|
+
* prompts the user to install the App (without it, no repos are reachable). Null = unknown (don't
|
|
330
|
+
* prompt).
|
|
331
|
+
*/
|
|
332
|
+
getAccountStatus?: () => Promise<AccountStatus | null>;
|
|
333
|
+
/**
|
|
334
|
+
* Browse every repository the platform's account link can reach — personal and organization repos
|
|
335
|
+
* covered by a GitHub App installation on cloud. Backs the "Add Existing Repository" picker;
|
|
336
|
+
* local platforms omit it (the OS picker / clone flow covers them).
|
|
337
|
+
*/
|
|
338
|
+
listRepos?: () => Promise<RepoInfo[]>;
|
|
339
|
+
/**
|
|
340
|
+
* Adopt an existing repository as a Jx project and return its catalogue root key (openable via
|
|
341
|
+
* the recent-projects path). Rejects with a structured message when the repository carries no
|
|
342
|
+
* project.json.
|
|
343
|
+
*/
|
|
344
|
+
importProject?: (opts: { owner: string; name: string }) => Promise<{ root: string }>;
|
|
238
345
|
/**
|
|
239
346
|
* Open a pull request for the current branch. Cloud platforms implement it against their session;
|
|
240
347
|
* local platforms omit it and Studio falls back to a direct GitHub API call with the user's
|
|
@@ -273,6 +380,18 @@ export interface StudioPlatform {
|
|
|
273
380
|
|
|
274
381
|
// ─── Studio Types ───────────────────────────────────────────────────────────
|
|
275
382
|
|
|
383
|
+
/**
|
|
384
|
+
* A project.json `content` section entry, as the studio consumes it. The parser extension owns the
|
|
385
|
+
* full shape (its project fragment schema is the validation source of truth); the studio only reads
|
|
386
|
+
* these fields.
|
|
387
|
+
*/
|
|
388
|
+
export interface ContentSectionEntry {
|
|
389
|
+
source?: string;
|
|
390
|
+
format?: string;
|
|
391
|
+
schema?: ContentTypeSchema;
|
|
392
|
+
$elements?: unknown[];
|
|
393
|
+
}
|
|
394
|
+
|
|
276
395
|
export interface CanvasPanel {
|
|
277
396
|
mediaName: string;
|
|
278
397
|
element: HTMLElement;
|
|
@@ -308,6 +427,18 @@ export interface FunctionEditDef {
|
|
|
308
427
|
parameters?: string[];
|
|
309
428
|
}
|
|
310
429
|
|
|
430
|
+
/**
|
|
431
|
+
* Identifies which document position's `$expression` the full-screen formula workspace is editing:
|
|
432
|
+
* a state entry (`type: "def"` + defName) or an element event binding (`type: "event"` + path +
|
|
433
|
+
* eventKey). Mirrors FunctionEditDef, the Monaco function editor's target shape.
|
|
434
|
+
*/
|
|
435
|
+
export interface FormulaEditDef {
|
|
436
|
+
type: "def" | "event";
|
|
437
|
+
defName?: string;
|
|
438
|
+
path?: JxPath;
|
|
439
|
+
eventKey?: string;
|
|
440
|
+
}
|
|
441
|
+
|
|
311
442
|
export interface GitDiffState {
|
|
312
443
|
filePath: string;
|
|
313
444
|
originalContent: string;
|