@jxsuite/studio 5.7.0 → 6.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/chunks/{2020-cs2sb9t1.js → 2020-nkxms0ay.js} +3 -3
- package/dist/chunks/adapter-m948ab5f.js +4 -0
- package/dist/chunks/{cf-account-picker-882a7ecm.js → cf-account-picker-n8hr38v7.js} +3 -3
- package/dist/chunks/cf-settings-356xdtne.js +4 -0
- package/dist/chunks/components-yk3t844e.js +4 -0
- package/dist/chunks/content-source-bawmyc09.js +4 -0
- package/dist/chunks/{convert-to-repeater-grfep2w8.js → convert-to-repeater-7wns8kf1.js} +3 -3
- package/dist/chunks/editor-6sc8nacq.js +4 -0
- package/dist/chunks/entry-commands-8ay9fh81.js +4 -0
- package/dist/chunks/{extension-sections-dp8endhx.js → extension-sections-na7rj3nr.js} +3 -3
- package/dist/chunks/file-ops-gye0qw56.js +4 -0
- package/dist/chunks/files-dmc2xvcq.js +4 -0
- package/dist/chunks/format-host-t76b53f8.js +4 -0
- package/dist/chunks/fs-events-cg4tpz06.js +4 -0
- package/dist/chunks/git-panel-yef7bshy.js +4 -0
- package/dist/chunks/{grid-view-5amhg604.js → grid-view-7tt4bxw1.js} +6 -6
- package/dist/chunks/iframe-host-tmz30gfp.js +4 -0
- package/dist/chunks/{index-9ydfe04y.js → index-gybvv7a6.js} +3 -3
- package/dist/chunks/index-nag78a9h.js +4 -0
- package/dist/chunks/{javascript-d9pqgc2p.js → javascript-rnvdp3k4.js} +2 -2
- package/dist/chunks/{jsonMode-800yvbem.js → jsonMode-zhwsprqk.js} +5 -5
- package/dist/chunks/jx-validate-3gbp5nkn.js +4 -0
- package/dist/chunks/layers-fvz99859.js +4 -0
- package/dist/chunks/layers-panel-gchmbf9p.js +4 -0
- package/dist/chunks/lit-html-9agdspkt.js +4 -0
- package/dist/chunks/media-picker-rhjvyy00.js +4 -0
- package/dist/chunks/menu-2e4y9j7b.js +4 -0
- package/dist/chunks/{monaco-binding-62dtmgbf.js → monaco-binding-2jnhjjvr.js} +3 -3
- package/dist/chunks/monaco-buffer-rp21359g.js +4 -0
- package/dist/chunks/{monaco-setup-tj13ndtm.js → monaco-setup-vhh7gayr.js} +3 -3
- package/dist/chunks/notify-h3www560.js +4 -0
- package/dist/chunks/platform-hz34wcd7.js +4 -0
- package/dist/chunks/publish-panel-exsmjzyj.js +4 -0
- package/dist/chunks/quick-search-pgaqeh0m.js +4 -0
- package/dist/chunks/references-2cgdxnb8.js +4 -0
- package/dist/chunks/right-panel-jf856w5w.js +4 -0
- package/dist/chunks/section-registry-jnf8r5gy.js +4 -0
- package/dist/chunks/studio-0f55h9ye.js +5 -0
- package/dist/chunks/{studio-hjbg8d5y.js → studio-0sqdhnew.js} +7 -7
- package/dist/chunks/{studio-1wvfxkyy.js → studio-0x3jyb8r.js} +4 -4
- package/dist/chunks/{studio-yr04mv2j.js → studio-19x1c75w.js} +4 -4
- package/dist/chunks/{studio-evwgp1ym.js → studio-2sqcndak.js} +4 -4
- package/dist/chunks/{studio-cvbkkfqb.js → studio-3aey7dd3.js} +4 -4
- package/dist/chunks/{studio-888knnkc.js → studio-3bpdkq2s.js} +4 -4
- package/dist/chunks/{studio-ceb34dxj.js → studio-47y6fbpf.js} +4 -4
- package/dist/chunks/{studio-c6w3tq7t.js → studio-4m3826v2.js} +4 -4
- package/dist/chunks/studio-4nx2dj1g.js +4 -0
- package/dist/chunks/{studio-p7c1agz0.js → studio-4xv5s47r.js} +5 -5
- package/dist/chunks/{studio-sxc0zvpt.js → studio-5g0ag7c0.js} +3 -3
- package/dist/chunks/{studio-semd1s8s.js → studio-5g4t8v6w.js} +4 -4
- package/dist/chunks/studio-5py436sf.js +5 -0
- package/dist/chunks/{studio-aje966s9.js → studio-77kt594t.js} +4 -4
- package/dist/chunks/{studio-56z7evx4.js → studio-8f87n763.js} +6 -6
- package/dist/chunks/studio-8mb00b84.js +5 -0
- package/dist/chunks/studio-8p51gq2h.js +6 -0
- package/dist/chunks/studio-954ds834.js +5 -0
- package/dist/chunks/{studio-xta2vxp6.js → studio-9ft45c83.js} +6 -6
- package/dist/chunks/studio-a2138x5k.js +7 -0
- package/dist/chunks/studio-a9yzstqj.js +5 -0
- package/dist/chunks/{studio-gp02nqnw.js → studio-acdksxx6.js} +4 -4
- package/dist/chunks/{studio-edbtvcd1.js → studio-anyrgzvb.js} +4 -4
- package/dist/chunks/{studio-dkn3x3hz.js → studio-ar8jcf2y.js} +4 -4
- package/dist/chunks/{studio-xry7tk3z.js → studio-bmn4mn9j.js} +5 -5
- package/dist/chunks/{studio-03wwfvyt.js → studio-cpxkgjrj.js} +4 -4
- package/dist/chunks/{studio-spf2skgc.js → studio-e7xxa0sj.js} +4 -4
- package/dist/chunks/{studio-01qza1n3.js → studio-ecaz25vk.js} +4 -4
- package/dist/chunks/{studio-5e9zsamh.js → studio-fzdywr6p.js} +6 -6
- package/dist/chunks/{studio-65fhspdd.js → studio-g5fmf0c1.js} +4 -4
- package/dist/chunks/studio-g7nse7zb.js +5 -0
- package/dist/chunks/studio-geq1ea6k.js +14 -0
- package/dist/chunks/{studio-n78gjfy8.js → studio-ghkb32r8.js} +4 -4
- package/dist/chunks/{studio-222rqyyc.js → studio-ghrhy2y7.js} +4 -4
- package/dist/chunks/{studio-a7xqhc3n.js → studio-grawhey1.js} +4 -4
- package/dist/chunks/{studio-eh0rac07.js → studio-h0xgswew.js} +4 -4
- package/dist/chunks/{studio-wma2c6g8.js → studio-h9c4p2tx.js} +4 -4
- package/dist/chunks/studio-jyzj5cxs.js +5 -0
- package/dist/chunks/{studio-x92tgnee.js → studio-mgx8yhnz.js} +31 -31
- package/dist/chunks/{studio-0scebvb9.js → studio-mpb04y1d.js} +5 -5
- package/dist/chunks/{studio-xy3tv3az.js → studio-n17mty64.js} +4 -4
- package/dist/chunks/{studio-gfn1kpxj.js → studio-nwh2eqsk.js} +5 -5
- package/dist/chunks/{studio-nt06yybj.js → studio-pxg4ap1e.js} +3 -3
- package/dist/chunks/{studio-zpnk016a.js → studio-q1h883bt.js} +5 -5
- package/dist/chunks/{studio-c6zdm25z.js → studio-q4tv82h7.js} +6 -6
- package/dist/chunks/{studio-st75kn99.js → studio-qbj760tx.js} +5 -5
- package/dist/chunks/{studio-y7jehjrp.js → studio-qpqa7vk3.js} +4 -4
- package/dist/chunks/{studio-j6gnhvaa.js → studio-qqz8e5gk.js} +4 -4
- package/dist/chunks/{studio-skzanb0k.js → studio-qvasen3f.js} +4 -4
- package/dist/chunks/studio-rggdb3hm.js +5 -0
- package/dist/chunks/{studio-4xppwncr.js → studio-sghy936h.js} +3 -3
- package/dist/chunks/{studio-9mqfamps.js → studio-skprc6ef.js} +4 -4
- package/dist/chunks/{studio-1x8x26k3.js → studio-tt2nactf.js} +4 -4
- package/dist/chunks/{studio-54g077x3.js → studio-txjjzrsm.js} +5 -5
- package/dist/chunks/{studio-f195h2hq.js → studio-tyasmc39.js} +4 -4
- package/dist/chunks/{studio-0bbxhhce.js → studio-v2bvmbjj.js} +4 -4
- package/dist/chunks/{studio-pwqfmt4p.js → studio-vk9ezads.js} +4 -4
- package/dist/chunks/{studio-fqq890ap.js → studio-vzacdfsc.js} +3 -3
- package/dist/chunks/{studio-zd4kayn2.js → studio-w4c0xmrw.js} +4 -4
- package/dist/chunks/{studio-tw7rre6s.js → studio-wfjqhhbk.js} +4 -4
- package/dist/chunks/{studio-tp642n5g.js → studio-wgh5kxpj.js} +4 -4
- package/dist/chunks/studio-xasj0796.js +5 -0
- package/dist/chunks/{studio-tzegmy4w.js → studio-y78s8r2n.js} +4 -4
- package/dist/chunks/{studio-7pgy3xaf.js → studio-z8w183sh.js} +4 -4
- package/dist/chunks/{studio-01kbbqg3.js → studio-zscd9ty4.js} +124 -124
- package/dist/chunks/{studio-mwxgyn9h.js → studio-zxp13sss.js} +6 -6
- package/dist/chunks/{studio-r3kaka4d.js → studio-zygnmm01.js} +4 -4
- package/dist/chunks/{tsMode-k9s9fcag.js → tsMode-gr0m4dzr.js} +5 -5
- package/dist/chunks/workspace-m15qtcqp.js +4 -0
- package/dist/chunks/{ws-client-0ja08haa.js → ws-client-nf61frr1.js} +3 -3
- package/dist/iframe-entry.js +3 -3
- package/dist/manifest.json +62 -62
- package/dist/studio.js +83 -83
- package/package.json +11 -11
- package/src/new-project/add-repo-modal.ts +459 -59
- package/src/platforms/cloud.ts +95 -18
- package/src/publish/pages-service.ts +7 -0
- package/src/publish/publish-panel.ts +16 -2
- package/src/surfaces/add-repo.json +721 -224
- package/src/surfaces/add-repo.ts +196 -31
- package/src/types.ts +42 -3
- package/src/ui/schema-form.ts +6 -2
- package/src/utils/project-dir.ts +24 -0
- package/dist/chunks/adapter-y5gdq19c.js +0 -4
- package/dist/chunks/cf-settings-20dznc3j.js +0 -4
- package/dist/chunks/components-q037dya7.js +0 -4
- package/dist/chunks/content-source-37x3vsap.js +0 -4
- package/dist/chunks/editor-j5sq149q.js +0 -4
- package/dist/chunks/entry-commands-c5h3nqck.js +0 -4
- package/dist/chunks/file-ops-937cvqk6.js +0 -4
- package/dist/chunks/files-tznwe1p1.js +0 -4
- package/dist/chunks/format-host-e2pjvd25.js +0 -4
- package/dist/chunks/fs-events-fv64ak3s.js +0 -4
- package/dist/chunks/git-panel-gb713ttc.js +0 -4
- package/dist/chunks/iframe-host-t819mcg5.js +0 -4
- package/dist/chunks/index-m0x5ztax.js +0 -4
- package/dist/chunks/jx-validate-zc9zp77s.js +0 -4
- package/dist/chunks/layers-4bsr82wz.js +0 -4
- package/dist/chunks/layers-panel-b6shnaax.js +0 -4
- package/dist/chunks/lit-html-cfn61dn7.js +0 -4
- package/dist/chunks/media-picker-ej0kdh1j.js +0 -4
- package/dist/chunks/menu-rtxf9chb.js +0 -4
- package/dist/chunks/monaco-buffer-nn4dtx27.js +0 -4
- package/dist/chunks/notify-ahs57a2z.js +0 -4
- package/dist/chunks/platform-v9xyfkbx.js +0 -4
- package/dist/chunks/publish-panel-bq36xcmj.js +0 -4
- package/dist/chunks/quick-search-zm00h9dh.js +0 -4
- package/dist/chunks/references-99ws0b0m.js +0 -4
- package/dist/chunks/right-panel-pq2f71q3.js +0 -4
- package/dist/chunks/section-registry-b2yzp9sw.js +0 -4
- package/dist/chunks/studio-0k9mvpgj.js +0 -14
- package/dist/chunks/studio-1a99w39s.js +0 -5
- package/dist/chunks/studio-693nhyky.js +0 -5
- package/dist/chunks/studio-aqmph6k4.js +0 -5
- package/dist/chunks/studio-c9d3pxf7.js +0 -5
- package/dist/chunks/studio-cxt150pj.js +0 -7
- package/dist/chunks/studio-e6re3rk1.js +0 -5
- package/dist/chunks/studio-frb0qbf7.js +0 -6
- package/dist/chunks/studio-gh97gngt.js +0 -5
- package/dist/chunks/studio-nbxqcgvf.js +0 -5
- package/dist/chunks/studio-t1eedsyx.js +0 -4
- package/dist/chunks/studio-vavmwshr.js +0 -5
- package/dist/chunks/studio-xk0z6msk.js +0 -5
- package/dist/chunks/workspace-b69mgm0e.js +0 -4
package/src/platforms/cloud.ts
CHANGED
|
@@ -48,6 +48,7 @@ import type {
|
|
|
48
48
|
ReferencesResult,
|
|
49
49
|
RenameResult,
|
|
50
50
|
RepoInfo,
|
|
51
|
+
RepoProjects,
|
|
51
52
|
StarterInfo,
|
|
52
53
|
StudioPlatform,
|
|
53
54
|
} from "../types";
|
|
@@ -56,12 +57,21 @@ import type { ReadFilesRequest, ReadFilesResult, UploadResult } from "@jxsuite/p
|
|
|
56
57
|
import { reportActionRequired } from "../account/action-required";
|
|
57
58
|
import { offeredActions, retryHint } from "../platform-errors";
|
|
58
59
|
import { createReadBatcher } from "./read-batcher";
|
|
60
|
+
import { normalizeProjectDir } from "../utils/project-dir";
|
|
59
61
|
import type { BatchAnswer } from "./read-batcher";
|
|
60
62
|
|
|
63
|
+
// Re-exported for the cloud shell and its tests, which spell folders through this entry.
|
|
64
|
+
export { normalizeProjectDir } from "../utils/project-dir";
|
|
65
|
+
|
|
61
66
|
export interface CloudProject {
|
|
62
67
|
owner: string;
|
|
63
68
|
repo: string;
|
|
64
69
|
branch: string;
|
|
70
|
+
/**
|
|
71
|
+
* The folder holding the project's `project.json`, relative to the repository root and already
|
|
72
|
+
* normalized ({@link normalizeProjectDir}); absent or `""` when the project IS the repository.
|
|
73
|
+
*/
|
|
74
|
+
dir?: string;
|
|
65
75
|
}
|
|
66
76
|
|
|
67
77
|
interface ProjectInfoWire {
|
|
@@ -213,12 +223,45 @@ async function reportRefusal(res: Response): Promise<void> {
|
|
|
213
223
|
});
|
|
214
224
|
}
|
|
215
225
|
|
|
216
|
-
/**
|
|
226
|
+
/**
|
|
227
|
+
* The revision a session reads: the branch, then `:` and the project folder when there is one.
|
|
228
|
+
*
|
|
229
|
+
* Git's own `<rev>:<path>` notation, and unambiguous for the reason git can use it: `:` is one of
|
|
230
|
+
* the characters a ref name may never contain (git-check-ref-format), so the FIRST colon always
|
|
231
|
+
* ends the branch, however many slashes the branch or the folder holds.
|
|
232
|
+
*/
|
|
233
|
+
export function revisionSpec(project: CloudProject): string {
|
|
234
|
+
return project.dir ? `${project.branch}:${project.dir}` : project.branch;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/** Split a {@link revisionSpec} back into its branch and folder; null when either half is unusable. */
|
|
238
|
+
function parseRevisionSpec(spec: string): { branch: string; dir?: string } | null {
|
|
239
|
+
const colon = spec.indexOf(":");
|
|
240
|
+
const branch = colon === -1 ? spec : spec.slice(0, colon);
|
|
241
|
+
const dir = colon === -1 ? "" : normalizeProjectDir(spec.slice(colon + 1));
|
|
242
|
+
if (!branch || dir === null) {
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
return dir ? { branch, dir } : { branch };
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Editor URL for a project session (mirrors the shell's route):
|
|
250
|
+
* `/edit/<owner>/<repo>@<branch>[:<folder>]`. The branch is one encoded component, so its slashes
|
|
251
|
+
* travel as `%2F`; the folder keeps its slashes, so a subfolder project's address reads as the path
|
|
252
|
+
* it is.
|
|
253
|
+
*/
|
|
217
254
|
export function editUrl(project: CloudProject): string {
|
|
218
|
-
|
|
255
|
+
const folder = project.dir
|
|
256
|
+
? `:${project.dir
|
|
257
|
+
.split("/")
|
|
258
|
+
.map((segment) => encodeURIComponent(segment))
|
|
259
|
+
.join("/")}`
|
|
260
|
+
: "";
|
|
261
|
+
return `/edit/${project.owner}/${project.repo}@${encodeURIComponent(project.branch)}${folder}`;
|
|
219
262
|
}
|
|
220
263
|
|
|
221
|
-
/** Parse an /edit/:owner/:repo@:branch path (editUrl's inverse); null when it is not one. */
|
|
264
|
+
/** Parse an /edit/:owner/:repo@:branch[:dir] path (editUrl's inverse); null when it is not one. */
|
|
222
265
|
export function parseEditPath(pathname: string): CloudProject | null {
|
|
223
266
|
/* Asset routers may normalize "@" to "%40", so decode the whole path first
|
|
224
267
|
(branch slashes survive: `.+` spans them). */
|
|
@@ -232,22 +275,27 @@ export function parseEditPath(pathname: string): CloudProject | null {
|
|
|
232
275
|
if (!match) {
|
|
233
276
|
return null;
|
|
234
277
|
}
|
|
235
|
-
const [, owner, repo,
|
|
236
|
-
|
|
278
|
+
const [, owner, repo, spec] = match;
|
|
279
|
+
const revision = spec ? parseRevisionSpec(spec) : null;
|
|
280
|
+
if (!owner || !repo || !revision) {
|
|
237
281
|
return null;
|
|
238
282
|
}
|
|
239
|
-
return { owner, repo,
|
|
283
|
+
return { owner, repo, ...revision };
|
|
240
284
|
}
|
|
241
285
|
|
|
242
|
-
/**
|
|
286
|
+
/**
|
|
287
|
+
* Gateway base path for a project session. The revision spec — branch and folder — is ONE encoded
|
|
288
|
+
* segment, so the gateway's route shape is the same for a subfolder project as for a repository,
|
|
289
|
+
* and the folder's slashes cannot be mistaken for the session's own sub-path.
|
|
290
|
+
*/
|
|
243
291
|
export function sessionBase(project: CloudProject): string {
|
|
244
|
-
const { owner, repo
|
|
245
|
-
return `/api/v1/p/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/${encodeURIComponent(
|
|
292
|
+
const { owner, repo } = project;
|
|
293
|
+
return `/api/v1/p/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/${encodeURIComponent(revisionSpec(project))}/studio`;
|
|
246
294
|
}
|
|
247
295
|
|
|
248
|
-
/** Catalogue/recents root key for a project: "owner/repo@branch". */
|
|
296
|
+
/** Catalogue/recents root key for a project: "owner/repo@branch", plus ":dir" for a subfolder. */
|
|
249
297
|
export function projectRootKey(project: CloudProject): string {
|
|
250
|
-
return `${project.owner}/${project.repo}@${project
|
|
298
|
+
return `${project.owner}/${project.repo}@${revisionSpec(project)}`;
|
|
251
299
|
}
|
|
252
300
|
|
|
253
301
|
/**
|
|
@@ -559,17 +607,18 @@ function awaitAction(popup: Window): Promise<ActionOutcome> {
|
|
|
559
607
|
});
|
|
560
608
|
}
|
|
561
609
|
|
|
562
|
-
/** Parse an "owner/repo@branch" root key; null when malformed. */
|
|
610
|
+
/** Parse an "owner/repo@branch[:dir]" root key; null when malformed. */
|
|
563
611
|
export function parseRootKey(root: string): CloudProject | null {
|
|
564
612
|
const match = /^([^/@]+)\/([^/@]+)@(.+)$/.exec(root);
|
|
565
613
|
if (!match) {
|
|
566
614
|
return null;
|
|
567
615
|
}
|
|
568
|
-
const [, owner, repo,
|
|
569
|
-
|
|
616
|
+
const [, owner, repo, spec] = match;
|
|
617
|
+
const revision = spec ? parseRevisionSpec(spec) : null;
|
|
618
|
+
if (!owner || !repo || !revision) {
|
|
570
619
|
return null;
|
|
571
620
|
}
|
|
572
|
-
return { owner, repo,
|
|
621
|
+
return { owner, repo, ...revision };
|
|
573
622
|
}
|
|
574
623
|
|
|
575
624
|
/** Every project this account can open, straight off the wire; [] when the catalogue is unreachable. */
|
|
@@ -1558,13 +1607,40 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
|
|
|
1558
1607
|
}));
|
|
1559
1608
|
},
|
|
1560
1609
|
|
|
1561
|
-
/**
|
|
1562
|
-
|
|
1610
|
+
/**
|
|
1611
|
+
* The folders of a repository that hold a project.json, read from its default branch. The
|
|
1612
|
+
* platform drops vendored folders and other tools' `project.json` (Nx's), and says when the
|
|
1613
|
+
* repository was too large to list in full.
|
|
1614
|
+
*/
|
|
1615
|
+
async listRepoProjects(repo: { owner: string; name: string }): Promise<RepoProjects> {
|
|
1616
|
+
const res = await fetch(
|
|
1617
|
+
`/api/v1/repos/${encodeURIComponent(repo.owner)}/${encodeURIComponent(repo.name)}/projects`,
|
|
1618
|
+
{ credentials: "include" },
|
|
1619
|
+
);
|
|
1620
|
+
const found = await okJson<RepoProjects>(res, "Failed to look for projects");
|
|
1621
|
+
/* Canonical on the way in, so a location the reader picks is spelled the way the root key,
|
|
1622
|
+
the editor URL and the session will spell it; anything that climbs out is not offered. */
|
|
1623
|
+
const locations: RepoProjects["locations"] = [];
|
|
1624
|
+
for (const location of found.locations) {
|
|
1625
|
+
const dir = normalizeProjectDir(location.dir);
|
|
1626
|
+
if (dir !== null) {
|
|
1627
|
+
locations.push(location.name ? { dir, name: location.name } : { dir });
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
return { branch: found.branch, locations, truncated: found.truncated === true };
|
|
1631
|
+
},
|
|
1632
|
+
|
|
1633
|
+
/** Adopt an existing repo (or one folder of it) as a Jx project; resolves to its root key. */
|
|
1634
|
+
async importProject(opts: { owner: string; name: string; dir?: string }) {
|
|
1635
|
+
const dir = normalizeProjectDir(opts.dir ?? "");
|
|
1636
|
+
if (dir === null) {
|
|
1637
|
+
throw new Error("The project folder must stay inside the repository.");
|
|
1638
|
+
}
|
|
1563
1639
|
const res = await fetch("/api/v1/projects/import", {
|
|
1564
1640
|
method: "POST",
|
|
1565
1641
|
credentials: "include",
|
|
1566
1642
|
headers: { "Content-Type": "application/json" },
|
|
1567
|
-
body: JSON.stringify(opts),
|
|
1643
|
+
body: JSON.stringify({ owner: opts.owner, name: opts.name, ...(dir ? { dir } : {}) }),
|
|
1568
1644
|
});
|
|
1569
1645
|
const imported = await okJson<{ owner: string; name: string; defaultBranch: string }>(
|
|
1570
1646
|
res,
|
|
@@ -1575,6 +1651,7 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
|
|
|
1575
1651
|
owner: imported.owner,
|
|
1576
1652
|
repo: imported.name,
|
|
1577
1653
|
branch: imported.defaultBranch,
|
|
1654
|
+
...(dir ? { dir } : {}),
|
|
1578
1655
|
}),
|
|
1579
1656
|
};
|
|
1580
1657
|
},
|
|
@@ -36,6 +36,12 @@ export interface ConnectOptions {
|
|
|
36
36
|
productionBranch: string;
|
|
37
37
|
owner: string;
|
|
38
38
|
repo: string;
|
|
39
|
+
/**
|
|
40
|
+
* The folder of the repository the project lives in, when it is not the root (a cloud project
|
|
41
|
+
* opened from a subfolder). Pages builds there, so `bunx jx build` finds that project's
|
|
42
|
+
* `project.json` and `dist` is that project's output.
|
|
43
|
+
*/
|
|
44
|
+
rootDir?: string;
|
|
39
45
|
}
|
|
40
46
|
|
|
41
47
|
/** True when the active platform can reach the Cloudflare API. */
|
|
@@ -106,6 +112,7 @@ export async function createPagesProject(opts: ConnectOptions): Promise<PagesPro
|
|
|
106
112
|
build_config: {
|
|
107
113
|
build_command: "bunx jx build",
|
|
108
114
|
destination_dir: "dist",
|
|
115
|
+
...(opts.rootDir ? { root_dir: opts.rootDir } : {}),
|
|
109
116
|
},
|
|
110
117
|
source: {
|
|
111
118
|
type: "github",
|
|
@@ -19,12 +19,12 @@
|
|
|
19
19
|
* HTML, in the accessibility tree and in every DOM dump. It is gone, and the document is now the
|
|
20
20
|
* thing that makes it impossible rather than the thing that remembers not to — the field binds no
|
|
21
21
|
* `value` at all, and the draft lives in the adapter's closure until {@link saveToken} reads it. A
|
|
22
|
-
* stored token is reported as
|
|
22
|
+
* stored token is reported as _stored_, the field is only ever drawn for a REPLACEMENT the reader
|
|
23
23
|
* asked for, and revoking lives where every other credential's does — Preferences › Accounts
|
|
24
24
|
* (`studio.md` §15 rule 1: a surface never prints the secret it describes).
|
|
25
25
|
*
|
|
26
|
-
* @docs studio/publish/cloudflare
|
|
27
26
|
* @license MIT
|
|
27
|
+
* @docs studio/publish/cloudflare
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
30
|
import type { DeployConfig, ProjectConfig } from "@jxsuite/schema/types";
|
|
@@ -36,6 +36,7 @@ import { resetModelCache } from "../services/ai-models";
|
|
|
36
36
|
import { projectState } from "../store";
|
|
37
37
|
import type { CfConnection } from "../types";
|
|
38
38
|
import { layerHost } from "../ui/layers";
|
|
39
|
+
import { normalizeProjectDir } from "../utils/project-dir";
|
|
39
40
|
import { openPublishSurface } from "../surfaces/publish";
|
|
40
41
|
import type { PublishForm, PublishSurfaceHandle, PublishView } from "../surfaces/publish";
|
|
41
42
|
import type { CfAccount, PagesDeploymentInfo } from "./pages-service";
|
|
@@ -82,6 +83,17 @@ function prefillRepo(): { owner: string; repo: string } {
|
|
|
82
83
|
return match ? { owner: match[1]!, repo: match[2]! } : { owner: "", repo: "" };
|
|
83
84
|
}
|
|
84
85
|
|
|
86
|
+
/**
|
|
87
|
+
* The repository folder a cloud project lives in ("owner/repo@branch:sites/blog"), or "" for one
|
|
88
|
+
* that is the whole repository and for every non-cloud root. Not a form field: the folder is the
|
|
89
|
+
* project's identity rather than a choice, and a Pages project that built anywhere else would build
|
|
90
|
+
* a different project, or none.
|
|
91
|
+
*/
|
|
92
|
+
function projectFolder(): string {
|
|
93
|
+
const spec = /^[\w.-]+\/[\w.-]+@[^:]+:(.+)$/.exec(getPlatform().projectRoot)?.[1] ?? "";
|
|
94
|
+
return normalizeProjectDir(spec) ?? "";
|
|
95
|
+
}
|
|
96
|
+
|
|
85
97
|
/** The connected Pages project, as the surface takes it: strings, never a config object. */
|
|
86
98
|
function deployView(): { projectName: string; productionUrl: string } | null {
|
|
87
99
|
const deploy: DeployConfig | undefined = currentDeploy();
|
|
@@ -257,12 +269,14 @@ async function submitConnect(): Promise<void> {
|
|
|
257
269
|
_error = "";
|
|
258
270
|
paint();
|
|
259
271
|
try {
|
|
272
|
+
const rootDir = projectFolder();
|
|
260
273
|
const deploy = await connectDeploy(config, {
|
|
261
274
|
accountId: _form.accountId,
|
|
262
275
|
owner: _form.owner,
|
|
263
276
|
productionBranch: _form.branch || "main",
|
|
264
277
|
projectName: _form.projectName,
|
|
265
278
|
repo: _form.repo,
|
|
279
|
+
...(rootDir ? { rootDir } : {}),
|
|
266
280
|
});
|
|
267
281
|
_deployment = await latestDeployment(deploy).catch(() => null);
|
|
268
282
|
} catch (error) {
|