Skip to content

Commit

Permalink
Make unified server run in dev mode.
Browse files Browse the repository at this point in the history
- **Move initialization code out of `index.html` and make
`unified-server` work in dev mode.**
- **Teach `remote-board-server` some more about unified server URLs.**
- **Teach unified server to load assets.**
- **Fix build.**
- **docs(changeset): Make unified server run in dev mode.**

Progress on #4342.
  • Loading branch information
dglazkov authored Feb 9, 2025
1 parent 0e39243 commit bdf469e
Show file tree
Hide file tree
Showing 22 changed files with 347 additions and 220 deletions.
8 changes: 8 additions & 0 deletions .changeset/neat-roses-hope.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@breadboard-ai/unified-server": minor
"@breadboard-ai/remote-board-server": patch
"@breadboard-ai/visual-editor": patch
"@google-labs/breadboard-schema": patch
---

Make unified server run in dev mode.
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 27 additions & 9 deletions packages/remote-board-server/src/remote-board-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ export class RemoteBoardServer extends EventTarget implements BoardServer {
}

static async from(url: string, title: string, user: User) {
// Add a slash at the end of the URL string, because all URL future
// construction will depend on it.
const endsWithSlash = url.endsWith("/");
if (!endsWithSlash) url = `${url}/`;
try {
const configuration = {
url: new URL(url),
Expand Down Expand Up @@ -398,11 +402,7 @@ export class RemoteBoardServer extends EventTarget implements BoardServer {

const projects: BoardServerProject[] = [];
try {
const request = createRequest(
`${this.url}/boards`,
this.user.apiKey,
"GET"
);
const request = this.#requestWithKey("boards", "GET");

const response = await fetch(request);
const files: BoardServerListingItem[] = await response.json();
Expand All @@ -429,7 +429,7 @@ export class RemoteBoardServer extends EventTarget implements BoardServer {
]);

const project: BoardServerProject = {
url: new URL(`${this.url}/boards/${item.path}`),
url: new URL(`boards/${item.path}`, this.url),
metadata: {
owner: item.username ?? "Unknown",
tags: item.tags,
Expand All @@ -443,7 +443,7 @@ export class RemoteBoardServer extends EventTarget implements BoardServer {
}
} catch (err) {
console.warn(
`[Remote Board Server]: Unable to connect to ${this.url}`,
`[Remote Board Server]: Unable to connect to "${this.url}"`,
err
);
}
Expand Down Expand Up @@ -485,7 +485,7 @@ export class RemoteBoardServer extends EventTarget implements BoardServer {

for (const [owner, nodes] of kits.entries()) {
const title = `@${owner}'s Components`;
const url = `${this.url}/kits/@${owner}/all`;
const url = new URL(`kits/@${owner}/all`, this.url).href;
this.kits = this.kits.filter((kit) => kit.title !== title);
this.kits.push({
title,
Expand All @@ -509,6 +509,24 @@ export class RemoteBoardServer extends EventTarget implements BoardServer {
return false;
}

return `${this.url.href}proxy?API_KEY=${this.user.apiKey}`;
return this.#withKey("proxy").href;
}

#withKey(path: string): URL {
const result = new URL(path, this.url);
result.searchParams.set("API_KEY", this.user.apiKey);
return result;
}

#requestWithKey(path: string, method: string, body?: unknown): Request {
const url = this.#withKey(path);
const init: RequestInit = {
method,
credentials: "include",
};
if (body) {
init.body = JSON.stringify(body);
}
return new Request(url.href, init);
}
}
8 changes: 7 additions & 1 deletion packages/schema/src/tests/util/get-json-files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ import * as fs from "fs";

export function getJsonFiles(
directory: string,
ignorePatterns: string[] = ["node_modules", ".wireit", "dist"]
ignorePatterns: string[] = [
"node_modules",
".wireit",
"dist",
"build",
"dist_test",
]
): string[] {
const files = fs.readdirSync(directory);
const jsonFiles = files
Expand Down
3 changes: 3 additions & 0 deletions packages/unified-server/.env.development
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
VITE_CONNECTION_SERVER_URL=http://localhost:3000/connection
VITE_LANGUAGE_PACK=@breadboard-ai/shared-ui/strings/en_US
VITE_ASSET_PACK=/icons/
5 changes: 5 additions & 0 deletions packages/unified-server/.env.production
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# To connect the Visual Editor to a Connection Server, provide the Connection
# Server URL here.
VITE_CONNECTION_SERVER_URL=
VITE_LANGUAGE_PACK=@breadboard-ai/shared-ui/strings/en_US
VITE_ASSET_PACK=/icons/
1 change: 1 addition & 0 deletions packages/unified-server/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
public
index.html
icons
17 changes: 10 additions & 7 deletions packages/unified-server/package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
{
"name": "@breadboard-ai/unified-server",
"publishConfig": {
"registry": "https://wombat-dressing-room.appspot.com"
},
"private": true,
"version": "0.0.1",
"description": "serves visual editor, board server, and connection server from a single origin",
Expand Down Expand Up @@ -38,13 +35,18 @@
"build:tsc": {
"command": "tsc",
"dependencies": [
"../board-server:build",
"../connection-server:build"
"../board-server:build:tsc",
"../connection-server:build:tsc",
"../visual-editor:build:tsc"
]
},
"dev": {
"command": "tsx src/server/main.ts",
"service": true
"command": "export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project) && node .",
"service": true,
"dependencies": [
"build:tsc",
"copy-assets"
]
},
"test": {
"command": "ava",
Expand Down Expand Up @@ -101,6 +103,7 @@
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0",
"ava": "^5.2.0",
"dotenv": "^16.4.7",
"typescript": "^5.7.3",
"wireit": "^0.14.10"
},
Expand Down
6 changes: 6 additions & 0 deletions packages/unified-server/scripts/copy-assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,23 @@ import { join } from "path";
const unifiedServerRoot = join(import.meta.dirname, "..");
const unifiedServerAssetsDir = join(unifiedServerRoot, "public");
const unifiedServerIndexHtml = join(unifiedServerRoot, "index.html");
const unifiedServerIconsDir = join(unifiedServerRoot, "icons");

const visualEditorRoot = join(unifiedServerRoot, "../visual-editor");
const visualEditorAssetsDir = join(visualEditorRoot, "public");
const visualEditorIndexHtml = join(visualEditorRoot, "index.html");
const visualEditorIconsDir = join(visualEditorRoot, "icons");

async function main() {
return Promise.all([
cp(visualEditorAssetsDir, unifiedServerAssetsDir, {
force: true,
recursive: true,
}),
cp(visualEditorIconsDir, unifiedServerIconsDir, {
force: true,
recursive: true,
}),
cp(visualEditorIndexHtml, unifiedServerIndexHtml),
]);
}
Expand Down
19 changes: 0 additions & 19 deletions packages/unified-server/src/index.ts

This file was deleted.

56 changes: 56 additions & 0 deletions packages/unified-server/src/init.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
* @license
* Copyright 2024 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

import * as pkg from "../package.json" with { type: "json" };
import * as StringsHelper from "@breadboard-ai/shared-ui/strings";

const icon = document.createElement("link");
icon.rel = "icon";
icon.type = "image/svg+xml";
icon.href = MAIN_ICON;
document.head.appendChild(icon);

const assetPack = document.createElement("style");
assetPack.textContent = ASSET_PACK;
document.head.appendChild(assetPack);

const params = new URLSearchParams(location.search);
if (params.has("dark")) {
globalThis.localStorage.setItem("dark-theme", "true");
} else if (params.has("light")) {
globalThis.localStorage.removeItem("dark-theme");
}

if (globalThis.localStorage.getItem("dark-theme") === "true") {
document.documentElement.classList.add("dark-theme");
}

async function init() {
const version = pkg.default.version;
await StringsHelper.initFrom(LANGUAGE_PACK);

const { Main } = await import("@breadboard-ai/visual-editor");
const { SettingsStore } = await import(
"@breadboard-ai/shared-ui/data/settings-store.js"
);

const config = {
settings: SettingsStore.instance(),
version,
};

window.oncontextmenu = (evt) => evt.preventDefault();

const main = new Main(config);
document.body.appendChild(main);

const Strings = StringsHelper.forSection("Global");
console.log(
`[${Strings.from("APP_NAME")} Visual Editor: Version ${version}]`
);
}

init();
5 changes: 5 additions & 0 deletions packages/unified-server/src/vite-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// <reference types="vite/client" />

declare const MAIN_ICON: string;
declare const ASSET_PACK: string;
declare const LANGUAGE_PACK: unknown;
5 changes: 3 additions & 2 deletions packages/unified-server/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"target": "ES2022"
"target": "ES2022",
"resolveJsonModule": true
},
"include": ["src/**/*", "tests/**/*"],
"include": ["src/**/*", "tests/**/*"]
}
26 changes: 9 additions & 17 deletions packages/unified-server/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,16 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { defineConfig, UserConfig } from "vite";
import { config } from "dotenv";
import { loadEnv, defineConfig, UserConfig } from "vite";
import { configureAssets } from "@breadboard-ai/visual-editor/vite";

export default defineConfig(async (): Promise<UserConfig> => {
const languagePackUrl = import.meta.resolve(
"@breadboard-ai/shared-ui/strings/en_US"
);
export default defineConfig(async ({ mode }): Promise<UserConfig> => {
config();

let languagePack;
try {
languagePack = (await import(languagePackUrl)).default;
} catch (err) {
throw new Error("Unable to import language pack");
}
const envConfig = { ...loadEnv(mode!, process.cwd()) };

const define = await configureAssets(__dirname, envConfig);

return {
optimizeDeps: { esbuildOptions: { target: "esnext" } },
Expand All @@ -30,12 +27,7 @@ export default defineConfig(async (): Promise<UserConfig> => {
formats: ["es"],
},
},
define: {
LANGUAGE_PACK: JSON.stringify(languagePack),
ASSET_PACK: "{}",
ASSET_PACK_ICONS: "[]",
MAIN_ICON: JSON.stringify("main.svg"),
},
define,
resolve: {
dedupe: ["lit"],
},
Expand Down
52 changes: 1 addition & 51 deletions packages/visual-editor/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,55 +11,5 @@
<title>Breadboard - Visual Editor</title>
</head>
<body>
<script type="module">
import * as pkg from "./package.json";
import * as StringsHelper from "@breadboard-ai/shared-ui/strings";

const icon = document.createElement("link");
icon.rel = "icon";
icon.type = "image/svg+xml";
icon.href = MAIN_ICON;
document.head.appendChild(icon);

const assetPack = document.createElement("style");
assetPack.textContent = ASSET_PACK;
document.head.appendChild(assetPack);

const params = new URLSearchParams(location.search);
if (params.has("dark")) {
globalThis.localStorage.setItem("dark-theme", "true");
} else if (params.has("light")) {
globalThis.localStorage.removeItem("dark-theme");
}

if (globalThis.localStorage.getItem("dark-theme") === "true") {
document.documentElement.classList.add("dark-theme");
}

async function init() {
await StringsHelper.initFrom(LANGUAGE_PACK);

const { Main } = await import("./src/index.ts");
const { SettingsStore } = await import(
"@breadboard-ai/shared-ui/data/settings-store.js"
);

const config = {
settings: SettingsStore.instance(),
version: pkg.version,
};

window.oncontextmenu = (evt) => evt.preventDefault();

const main = new Main(config);
document.body.appendChild(main);

const Strings = StringsHelper.forSection("Global");
console.log(
`[${Strings.from("APP_NAME")} Visual Editor: Version ${pkg.version}]`
);
}

init();
</script>
<script type="module" src="./src/init.ts"></script>
</body>
Loading

0 comments on commit bdf469e

Please sign in to comment.