diff --git a/apps/dev-playground/server/.env.dist b/apps/dev-playground/server/.env.dist index ae8f1a7..98ebe2a 100644 --- a/apps/dev-playground/server/.env.dist +++ b/apps/dev-playground/server/.env.dist @@ -1,8 +1,6 @@ DATABRICKS_HOST= DATABRICKS_WAREHOUSE_ID= DATABRICKS_WORKSPACE_ID= -DATABRICKS_APP_PORT=8000 -FLASK_RUN_HOST=0.0.0.0 NODE_ENV='development' OTEL_EXPORTER_OTLP_ENDPOINT='http://localhost:4318' OTEL_RESOURCE_ATTRIBUTES='service.sample_attribute=dev' diff --git a/packages/app-kit/src/analytics/analytics.ts b/packages/app-kit/src/analytics/analytics.ts index 9fd8b34..9253173 100644 --- a/packages/app-kit/src/analytics/analytics.ts +++ b/packages/app-kit/src/analytics/analytics.ts @@ -20,6 +20,7 @@ import type { export class AnalyticsPlugin extends Plugin { name = "analytics"; envVars = []; + requiresDatabricksClient = true; protected static description = "Analytics plugin for data analysis"; protected declare config: IAnalyticsConfig; diff --git a/packages/app-kit/src/plugin/plugin.ts b/packages/app-kit/src/plugin/plugin.ts index d39cbbb..df61c3b 100644 --- a/packages/app-kit/src/plugin/plugin.ts +++ b/packages/app-kit/src/plugin/plugin.ts @@ -41,6 +41,9 @@ export abstract class Plugin< protected telemetry: ITelemetry; protected abstract envVars: string[]; + /** If the plugin requires the Databricks client to be set in the request context */ + requiresDatabricksClient = false; + static phase: PluginPhase = "normal"; name: string; diff --git a/packages/app-kit/src/plugin/tests/plugin.test.ts b/packages/app-kit/src/plugin/tests/plugin.test.ts index b431b20..1095992 100644 --- a/packages/app-kit/src/plugin/tests/plugin.test.ts +++ b/packages/app-kit/src/plugin/tests/plugin.test.ts @@ -571,6 +571,22 @@ describe("Plugin", () => { }); }); + describe("requiresDatabricksClient", () => { + test("should default to false", () => { + const plugin = new TestPlugin(config); + expect(plugin.requiresDatabricksClient).toBe(false); + }); + + test("should allow plugins to override to true", () => { + class PluginWithDatabricksClient extends TestPlugin { + requiresDatabricksClient = true; + } + + const plugin = new PluginWithDatabricksClient(config); + expect(plugin.requiresDatabricksClient).toBe(true); + }); + }); + describe("integration scenarios", () => { test("should handle complex execution flow with all interceptors", async () => { const plugin = new TestPlugin({ diff --git a/packages/app-kit/src/server/index.ts b/packages/app-kit/src/server/index.ts index 679e548..aaae348 100644 --- a/packages/app-kit/src/server/index.ts +++ b/packages/app-kit/src/server/index.ts @@ -16,14 +16,14 @@ dotenv.config({ path: path.resolve(process.cwd(), "./server/.env") }); export class ServerPlugin extends Plugin { public static DEFAULT_CONFIG = { autoStart: true, - staticPath: path.resolve(process.cwd(), "client", "dist"), + staticPath: ServerPlugin.findDefaultStaticPath(), host: process.env.FLASK_RUN_HOST || "0.0.0.0", port: Number(process.env.DATABRICKS_APP_PORT) || 8000, watch: process.env.NODE_ENV === "development", }; public name = "server" as const; - public envVars = ["DATABRICKS_APP_PORT", "FLASK_RUN_HOST"]; + public envVars: string[] = []; private serverApplication: express.Application; private server: HTTPServer | null; private devModeManager?: DevModeManager; @@ -65,9 +65,8 @@ export class ServerPlugin extends Plugin { async start(): Promise { this.serverApplication.use(express.json()); - this.serverApplication.use(await databricksClientMiddleware()); - this.extendRoutes(); + await this.extendRoutes(); for (const extension of this.serverExtensions) { extension(this.serverApplication); @@ -156,7 +155,7 @@ export class ServerPlugin extends Plugin { return this; } - private extendRoutes() { + private async extendRoutes() { if (!this.config.plugins) return; this.serverApplication.get("/health", (_, res) => { @@ -169,6 +168,10 @@ export class ServerPlugin extends Plugin { if (plugin?.injectRoutes && typeof plugin.injectRoutes === "function") { const router = express.Router(); + // add databricks client middleware to the router if the plugin needs the request context + if (plugin.requiresDatabricksClient) + router.use(await databricksClientMiddleware()); + plugin.injectRoutes(router); this.serverApplication.use(`/api/${plugin.name}`, router); @@ -222,6 +225,17 @@ export class ServerPlugin extends Plugin { return configObject; } + private static findDefaultStaticPath() { + const staticPaths = ["dist", "client/dist", "build", "public", "out"]; + const cwd = process.cwd(); + for (const p of staticPaths) { + if (fs.existsSync(path.resolve(cwd, p, "index.html"))) { + return path.resolve(cwd, p); + } + } + return undefined; + } + private _gracefulShutdown() { console.log("Starting graceful shutdown..."); diff --git a/packages/app-kit/src/telemetry/telemetry-manager.ts b/packages/app-kit/src/telemetry/telemetry-manager.ts index 61b5514..f9b3484 100644 --- a/packages/app-kit/src/telemetry/telemetry-manager.ts +++ b/packages/app-kit/src/telemetry/telemetry-manager.ts @@ -66,9 +66,6 @@ export class TelemetryManager { if (this.sdk) return; if (!process.env.OTEL_EXPORTER_OTLP_ENDPOINT) { - console.log( - "[Telemetry] OTEL_EXPORTER_OTLP_ENDPOINT not set; telemetry disabled", - ); return; }