/ concept-collection / stan-web-ide
Sign in
concept-collection / stan-web-ide
stan-web-ide / src / ide.ts
122 lines · 4.5 KBCodeBlameHistory
4e434baSeed the GitHub workspace locally after publishJeremy Magland 1import { attachGitHubSourceControl, createIndexedDBFileSystem, createWorkbench, transplantGitHubWorkspace, type Workbench, type WorkbenchTheme, type WorkspaceFileSystem } from 'minwebide';
2import { githubWorkspaceDbName } from './githubOpen';
ad7d2c4CSV table view: default editor for .csv filesJeremy Magland 3import { createCsvTableProvider } from './csvTable';
21efcb6stan web IDE: run Stan sampling in the browserJeremy Magland 4import { openProjectFileSystem, touchProject, type ProjectInfo } from './projects';
f66b0fbOpen GitHub repos as workspaces via #/github/<spec>Jeremy Magland 5import { createResultsViewProvider } from './stan/resultsView';
21efcb6stan web IDE: run Stan sampling in the browserJeremy Magland 6import { createStanRunner } from './stan/runner';
7import { createSampleEditorProvider } from './stan/sampleEditor';
8import { showServerDialog } from './stan/serverDialog';
9import { getServerUrl, onDidChangeServerUrl, probeServer } from './stan/settings';
f66b0fbOpen GitHub repos as workspaces via #/github/<spec>Jeremy Magland 11export interface StanWorkbench {
12 readonly workbench: Workbench;
13 dispose(): void;
17 * Assembles the Stan workbench (runner, custom editors, compile-server status
18 * item) on a file system. Shared by project IDEs and GitHub repo IDEs; does
19 * not own `fs` — the caller disposes it.
20 */
21export async function openStanWorkbench(container: HTMLElement, fs: WorkspaceFileSystem, workspaceName: string, theme: WorkbenchTheme): Promise<StanWorkbench> {
21efcb6stan web IDE: run Stan sampling in the browserJeremy Magland 22 const workbench = createWorkbench(container, {
23 fileSystem: fs,
24 theme,
f66b0fbOpen GitHub repos as workspaces via #/github/<spec>Jeremy Magland 25 workspaceName,
f66b0fbOpen GitHub repos as workspaces via #/github/<spec>Jeremy Magland 27 const stan = createStanRunner(fs, (path) => workbench.openFile(fs.root.with({ path })));
21efcb6stan web IDE: run Stan sampling in the browserJeremy Magland 28 workbench.registerRunner(stan.runner);
29 workbench.registerCustomEditor(createSampleEditorProvider(fs, workbench, { stop: stan.stop }));
f66b0fbOpen GitHub repos as workspaces via #/github/<spec>Jeremy Magland 30 workbench.registerCustomEditor(createResultsViewProvider(fs));
ad7d2c4CSV table view: default editor for .csv filesJeremy Magland 31 workbench.registerCustomEditor(createCsvTableProvider());
33 // compile-server status: shows connectivity, click to change the URL
34 let disposed = false;
35 const refreshServerItem = async () => {
36 const url = getServerUrl();
37 workbench.statusBar.setItem('stan-server', 'right', 'Stan server: checking...', {
38 icon: 'server',
39 title: `${url}\nClick to change the compilation server`,
40 onClick: () => showServerDialog(container),
41 });
42 const ok = await probeServer(url);
43 if (disposed || url !== getServerUrl()) {
44 return;
45 }
46 workbench.statusBar.setItem('stan-server', 'right', `Stan server: ${ok ? 'connected' : 'offline'}`, {
47 icon: ok ? 'server' : 'warning',
48 title: `${url}${ok ? 'connected' : 'not reachable'}\nClick to change the compilation server`,
49 onClick: () => showServerDialog(container),
50 });
51 };
52 void refreshServerItem();
53 const serverListener = onDidChangeServerUrl(() => void refreshServerItem());
56 workbench,
57 dispose() {
58 disposed = true;
59 serverListener.dispose();
60 stan.dispose();
61 workbench.dispose();
62 },
63 };
66/** Opens the most useful starting file, if any. */
67export async function openStartingFile(fs: WorkspaceFileSystem, workbench: Workbench): Promise<void> {
21efcb6stan web IDE: run Stan sampling in the browserJeremy Magland 68 for (const path of ['/fit.sample', '/main.stan', '/README.md']) {
69 const uri = fs.root.with({ path });
70 if (await fs.fileService.exists(uri)) {
71 await workbench.openFile(uri);
74 }
77/** Opens the IDE for a project. Returns a disposable view. */
78export async function openIde(container: HTMLElement, project: ProjectInfo, theme: WorkbenchTheme): Promise<{ dispose(): void }> {
79 touchProject(project.id);
80 document.title = `${project.name} — stan web IDE`;
82 const fs = await openProjectFileSystem(project.id);
83 const ide = await openStanWorkbench(container, fs, project.name, theme);
85 // the project indicator: click to go back to the project list
86 ide.workbench.statusBar.setItem('project', 'left', project.name, {
87 icon: 'folder-opened',
88 title: 'Back to projects',
89 onClick: () => { location.hash = '#/'; },
90 });
91 // replace the default branding item with the project indicator
92 ide.workbench.statusBar.removeItem('branding');
94 // source control: publish this project to a new GitHub repo, or — once
95 // published — track changes and push
96 const sourceControl = await attachGitHubSourceControl(ide.workbench, fs, {
97 appName: 'stan web IDE',
98 defaultRepoName: project.name,
4e434baSeed the GitHub workspace locally after publishJeremy Magland 99 // after publishing, seed the repo's own workspace from the local copy
100 // (no re-download — the local state IS the pushed state) and make its
101 // route the canonical place to work
102 onPublished: async ({ owner, repo }) => {
103 const ghFs = await createIndexedDBFileSystem({ dbName: githubWorkspaceDbName({ owner, repo }) });
104 try {
105 await transplantGitHubWorkspace(fs, ghFs);
106 } finally {
107 ghFs.dispose();
108 }
109 location.hash = `#/github/${owner}/${repo}`;
110 },
113 await openStartingFile(fs, ide.workbench);
115 return {
116 dispose() {
f66b0fbOpen GitHub repos as workspaces via #/github/<spec>Jeremy Magland 117 sourceControl.dispose();
118 ide.dispose();
21efcb6stan web IDE: run Stan sampling in the browserJeremy Magland 119 fs.dispose();
120 },
121 };
moveopenescclose