Skip to content

Commit

Permalink
Work on decoupling studio server constituents (#3482)
Browse files Browse the repository at this point in the history
  • Loading branch information
Janpot committed Apr 30, 2024
1 parent 91254c5 commit 78e6b97
Show file tree
Hide file tree
Showing 14 changed files with 39 additions and 101 deletions.
1 change: 0 additions & 1 deletion packages/toolpad-studio/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export const WINDOW_PROP_TOOLPAD_APP_RENDER_PARAMS = '__TOOLPAD_APP_RENDER_PARAMS__';
export const RUNTIME_CONFIG_WINDOW_PROPERTY = '__TOOLPAD_RUNTIME_CONFIG__';
export const INITIAL_STATE_WINDOW_PROPERTY = '__initialToolpadState__';

export const TOOLPAD_TARGET_CE = 'CE';
Expand Down
3 changes: 1 addition & 2 deletions packages/toolpad-studio/src/server/DataManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import cors from 'cors';
import invariant from 'invariant';
import { errorFrom, serializeError, SerializedError } from '@toolpad/utils/errors';
import * as appDom from '@toolpad/studio-runtime/appDom';
import type { RuntimeConfig, Methods, ServerDataSource, ToolpadProjectOptions } from '../types';
import type { Methods, ServerDataSource, ToolpadProjectOptions } from '../types';
import serverDataSources from '../toolpadDataSources/server';
import applyTransform from '../toolpadDataSources/applyTransform';
import { asyncHandler } from '../utils/express';
Expand All @@ -29,7 +29,6 @@ interface IToolpadProject {
saveDom(dom: appDom.AppDom): Promise<void>;
functionsManager: FunctionsManager;
envManager: EnvManager;
getRuntimeConfig: () => Promise<RuntimeConfig>;
}

/**
Expand Down
2 changes: 0 additions & 2 deletions packages/toolpad-studio/src/server/EnvManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ interface IToolpadProject {
options: ToolpadProjectOptions;
events: Emitter<ProjectEvents>;
getRoot(): string;
invalidateQueries(): void;
}

/**
Expand Down Expand Up @@ -88,7 +87,6 @@ export default class EnvManager {
this.loadEnvFile();

this.project.events.emit('envChanged', {});
this.project.invalidateQueries();
};

this.watcher.on('add', handleChange);
Expand Down
4 changes: 0 additions & 4 deletions packages/toolpad-studio/src/server/FunctionsManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import * as url from 'node:url';
import type { GridRowId } from '@mui/x-data-grid';
import invariant from 'invariant';
import { Awaitable } from '@toolpad/utils/types';
import EnvManager from './EnvManager';
import { ProjectEvents, ToolpadProjectOptions } from '../types';
import * as functionsRuntime from './functionsRuntime';
import type { ExtractTypesParams, IntrospectionResult } from './functionsTypesWorker';
Expand Down Expand Up @@ -104,8 +103,6 @@ interface IToolpadProject {
events: Emitter<ProjectEvents>;
getRoot(): string;
getOutputFolder(): string;
envManager: EnvManager;
invalidateQueries(): void;
}

export default class FunctionsManager {
Expand Down Expand Up @@ -200,7 +197,6 @@ export default class FunctionsManager {

this.buildErrors = args.errors;

this.project.invalidateQueries();
this.project.events.emit('functionsChanged', {});
};

Expand Down
20 changes: 7 additions & 13 deletions packages/toolpad-studio/src/server/appServerWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import type { Plugin } from 'vite';
import { createRpcClient } from '@toolpad/utils/workerRpc';
import type * as appDom from '@toolpad/studio-runtime/appDom';
import { createViteConfig, getEditorHtmlContent } from './toolpadAppBuilder';
import type { RuntimeConfig } from '../types';
import type { ComponentEntry, PagesManifest } from './localMode';
import createRuntimeState from '../runtime/createRuntimeState';
import { postProcessHtml } from './toolpadAppServer';
Expand All @@ -27,15 +26,7 @@ invariant(
'The dev server must be started with NODE_ENV=development',
);

export interface ToolpadAppDevServerParams {
outDir: string;
config: RuntimeConfig;
root: string;
base: string;
customServer: boolean;
}

function devServerPlugin({ config }: ToolpadAppDevServerParams): Plugin {
function devServerPlugin(): Plugin {
return {
name: 'toolpad-dev-server',

Expand All @@ -51,7 +42,6 @@ function devServerPlugin({ config }: ToolpadAppDevServerParams): Plugin {
let html = await viteServer.transformIndexHtml(req.url, template);

html = postProcessHtml(html, {
config,
initialState: createRuntimeState({ dom }),
});

Expand All @@ -65,7 +55,11 @@ function devServerPlugin({ config }: ToolpadAppDevServerParams): Plugin {
};
}

export interface AppViteServerConfig extends ToolpadAppDevServerParams {
export interface AppViteServerConfig {
outDir: string;
root: string;
base: string;
customServer: boolean;
toolpadDevMode: boolean;
port: number;
mainThreadRpcPort: MessagePort;
Expand All @@ -75,7 +69,7 @@ export async function main({ port, ...config }: AppViteServerConfig) {
const { reloadComponents, viteConfig } = await createViteConfig({
...config,
dev: true,
plugins: [devServerPlugin(config)],
plugins: [devServerPlugin()],
getComponents,
getPagesManifest,
loadDom,
Expand Down
17 changes: 3 additions & 14 deletions packages/toolpad-studio/src/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,14 @@ async function createDevHandler(project: ToolpadProject) {

const appServerPath = path.resolve(currentDirectory, '../cli/appServerWorker.mjs');

const [wsPort, devPort, runtimeConfig] = await Promise.all([
getPort(),
getPort(),
project.getRuntimeConfig(),
]);
const [wsPort, devPort] = await Promise.all([getPort(), getPort()]);

const mainThreadRpcChannel = new MessageChannel();
const worker = new Worker(appServerPath, {
workerData: {
toolpadDevMode: project.options.toolpadDevMode,
outDir: project.getAppOutputFolder(),
base: project.options.base,
config: runtimeConfig,
root: project.getRoot(),
port: devPort,
mainThreadRpcPort: mainThreadRpcChannel.port1,
Expand Down Expand Up @@ -198,17 +193,15 @@ export interface ToolpadHandlerConfig {
dev: boolean;
dir: string;
base: string;
externalUrl: string;
toolpadDevMode?: boolean;
}

export async function createHandler({
dev = false,
dir = './toolpad',
base = '/prod',
externalUrl = 'http://localhost:3000',
}: ToolpadHandlerConfig): Promise<AppHandler> {
const project = await initProject({ dev, dir, externalUrl, base, customServer: true });
const project = await initProject({ dev, dir, base, customServer: true });
await project.start();

const appHandler = await createToolpadAppHandler(project);
Expand All @@ -223,14 +216,13 @@ export async function createHandler({

async function createToolpadHandler({
dev,
externalUrl,
base,
dir,
toolpadDevMode,
}: ToolpadHandlerConfig): Promise<AppHandler> {
const editorBasename = '/_toolpad';

const project = await initProject({ toolpadDevMode, dev, dir, externalUrl, base });
const project = await initProject({ toolpadDevMode, dev, dir, base });
await project.checkPlan();
await project.start();

Expand Down Expand Up @@ -373,15 +365,12 @@ export async function runApp({
}
}

const externalUrl = process.env.TOOLPAD_EXTERNAL_URL || `http://localhost:${port}`;

const server = await startToolpadServer({
dev,
base,
dir,
port,
toolpadDevMode: !!process.env.TOOLPAD_NEXT_DEV || toolpadDevMode,
externalUrl,
});

const toolpadUrl = `http://localhost:${server.port}/`;
Expand Down
25 changes: 5 additions & 20 deletions packages/toolpad-studio/src/server/localMode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,7 @@ import {
ResponseType as AppDomRestResponseType,
} from '../toolpadDataSources/rest/types';
import { LocalQuery } from '../toolpadDataSources/local/types';
import type {
RuntimeConfig,
ProjectEvents,
ToolpadProjectOptions,
CodeEditorFileType,
} from '../types';
import type { ProjectEvents, ToolpadProjectOptions, CodeEditorFileType } from '../types';
import EnvManager from './EnvManager';
import FunctionsManager, { CreateDataProviderOptions } from './FunctionsManager';
import { VersionInfo, checkVersion } from './versionInfo';
Expand Down Expand Up @@ -995,8 +990,6 @@ class ToolpadProject {

dataManager: DataManager;

invalidateQueries: () => void;

private alertedMissingVars = new Set<string>();

private lastVersionCheck = 0;
Expand Down Expand Up @@ -1025,7 +1018,7 @@ class ToolpadProject {
this.functionsManager = new FunctionsManager(this);
this.dataManager = new DataManager(this);

this.invalidateQueries = throttle(
const invalidateQueries = throttle(
() => {
this.events.emit('queriesInvalidated', {});
},
Expand All @@ -1034,6 +1027,9 @@ class ToolpadProject {
leading: false,
},
);

this.events.on('functionsChanged', invalidateQueries);
this.events.on('envChanged', invalidateQueries);
}

private initWatcher() {
Expand Down Expand Up @@ -1333,17 +1329,6 @@ class ToolpadProject {
return config;
}

async getRuntimeConfig(): Promise<RuntimeConfig> {
// When these fail, you are likely trying to retrieve this information during the
// Toolpad Studio build. It's fundamentally wrong to use this information as it strictly holds
// information about the running Toolpad Studio instance.
invariant(this.options.externalUrl, 'External URL is not set');

return {
externalUrl: this.options.externalUrl,
};
}

async writeBuildInfo() {
await writeFileRecursive(
this.getBuildInfoFile(),
Expand Down
3 changes: 0 additions & 3 deletions packages/toolpad-studio/src/server/projectRpcServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,6 @@ export function createRpcServer(project: ToolpadProject) {
createDataProvider: createMethod<typeof project.createDataProvider>(({ params }) => {
return project.createDataProvider(...params);
}),
getRuntimeConfig: createMethod<typeof project.getRuntimeConfig>(({ params }) => {
return project.getRuntimeConfig(...params);
}),
getComponents: createMethod<typeof project.getComponentsManifest>(({ params }) => {
return project.getComponentsManifest(...params);
}),
Expand Down
9 changes: 7 additions & 2 deletions packages/toolpad-studio/src/server/toolpadAppBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ export interface CreateViteConfigParams {
getPagesManifest: () => Promise<PagesManifest>;
}

export interface CreateViteConfigResult {
reloadComponents: () => Promise<void>;
viteConfig: InlineConfig;
}

export async function createViteConfig({
toolpadDevMode,
outDir,
Expand All @@ -101,7 +106,7 @@ export async function createViteConfig({
getComponents,
loadDom,
getPagesManifest,
}: CreateViteConfigParams) {
}: CreateViteConfigParams): Promise<CreateViteConfigResult> {
const mode = dev ? 'development' : 'production';

const initialDom = await loadDom();
Expand Down Expand Up @@ -308,7 +313,7 @@ if (import.meta.hot) {
'process.env.TOOLPAD_BUILD': JSON.stringify(TOOLPAD_BUILD),
'process.env.TOOLPAD_PLAN': JSON.stringify(plan),
},
} satisfies InlineConfig,
},
};
}

Expand Down
19 changes: 3 additions & 16 deletions packages/toolpad-studio/src/server/toolpadAppServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,19 @@ import { asyncHandler } from '../utils/express';
import { basicAuthUnauthorized, checkBasicAuthHeader } from './basicAuth';
import { createRpcServer } from './runtimeRpcServer';
import { createRpcHandler } from './rpc';
import { RUNTIME_CONFIG_WINDOW_PROPERTY, INITIAL_STATE_WINDOW_PROPERTY } from '../constants';
import { INITIAL_STATE_WINDOW_PROPERTY } from '../constants';
import createRuntimeState from '../runtime/createRuntimeState';
import type { RuntimeConfig } from '../types';
import type { RuntimeState } from '../runtime';
import { createAuthHandler, createRequireAuthMiddleware, getRequireAuthentication } from './auth';

export interface PostProcessHtmlParams {
config: RuntimeConfig;
initialState: RuntimeState;
}

export function postProcessHtml(
html: string,
{ config, initialState }: PostProcessHtmlParams,
): string {
const serializedConfig = serializeJavascript(config, { ignoreFunction: true });
export function postProcessHtml(html: string, { initialState }: PostProcessHtmlParams): string {
const serializedInitialState = serializeJavascript(initialState, { isJSON: true });

const toolpadScripts = [
`<script>window[${JSON.stringify(
RUNTIME_CONFIG_WINDOW_PROPERTY,
)}] = ${serializedConfig}</script>`,
`<script>window[${JSON.stringify(
INITIAL_STATE_WINDOW_PROPERTY,
)}] = ${serializedInitialState}</script>`,
Expand Down Expand Up @@ -80,15 +71,11 @@ export async function createProdHandler(project: ToolpadProject) {
asyncHandler(async (req, res) => {
const htmlFilePath = path.resolve(project.getAppOutputFolder(), './index.html');

const [runtimeConfig, dom] = await Promise.all([
project.getRuntimeConfig(),
project.loadDom(),
]);
const [dom] = await Promise.all([project.loadDom()]);

let html = await fs.readFile(htmlFilePath, { encoding: 'utf-8' });

html = postProcessHtml(html, {
config: runtimeConfig,
initialState: createRuntimeState({ dom }),
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,6 @@ export default function QueryEditorPanel({ draft, saved }: QueryEditorProps) {
const { dom } = useAppState();
const projectApi = useProjectApi();

const { data: runtimeConfig } = projectApi.useSuspenseQuery('getRuntimeConfig', []);

const connectionId =
appDom.deref(saved ? saved?.attributes?.connectionId : draft?.attributes?.connectionId) ?? null;

Expand Down Expand Up @@ -216,7 +214,6 @@ export default function QueryEditorPanel({ draft, saved }: QueryEditorProps) {
globalScope={pageState}
globalScopeMeta={globalScopeMeta}
execApi={execPrivate}
runtimeConfig={runtimeConfig}
settingsTab={
<QuerySettingsTab
{...{
Expand Down
Loading

0 comments on commit 78e6b97

Please sign in to comment.