From b07f58e8a40aaffcadb62e243810a3a179aafbad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Moreau?= Date: Thu, 28 Nov 2024 21:15:06 +0100 Subject: [PATCH] Visualizer - Handle envs import (#42) * add env selector for the visualizer * add env option in drizzle lab cli * rework env loader --- apps/cli/README.md | 5 +- apps/cli/build.ts | 2 +- apps/cli/cli.ts | 27 +++++++--- apps/cli/package.json | 2 +- apps/cli/visualizer/entry.server.tsx | 6 +-- apps/cli/visualizer/routes/_index.tsx | 4 +- package-lock.json | 6 +-- packages/api/README.md | 1 + packages/api/package.json | 3 +- packages/api/src/config/env.node.ts | 29 +++++----- packages/api/src/config/loader.node.ts | 20 +++---- .../api/src/internal/import-module.node.ts | 21 ++++---- vscode-extension/CHANGELOG.md | 5 ++ vscode-extension/package-lock.json | 4 +- vscode-extension/package.json | 2 +- vscode-extension/src/extension.ts | 13 ++--- .../modules/internal/select-env.command.ts | 53 +++++++++++++++++++ .../modules/studio/open-studio/codelens.ts | 7 +-- .../src/modules/studio/open-studio/command.ts | 53 ------------------- vscode-extension/src/modules/studio/server.ts | 17 ++++-- .../visualizer/open-visualizer/codelens.ts | 5 +- .../visualizer/open-visualizer/command.ts | 3 +- .../src/modules/visualizer/server.ts | 18 ++++++- 23 files changed, 176 insertions(+), 130 deletions(-) create mode 100644 vscode-extension/src/modules/internal/select-env.command.ts diff --git a/apps/cli/README.md b/apps/cli/README.md index d20f47a..ed9d401 100644 --- a/apps/cli/README.md +++ b/apps/cli/README.md @@ -11,10 +11,11 @@ Usage: Flags: -c, --config string Path to drizzle config file --debug Enable log output (default: false) - --save-dir string Directory to save the visualizer data (default: ".drizzle-lab") - --project-id string A unique identifier for the current visualized project. It is used as filename to save the visualizer state. + --save-dir string Directory to save the visualizer data (default: ".drizzle") + --project-id string A unique identifier for the current visualized project. It is used as filename to save the visualizer state. (default: "visualizer") --ts-config string Path to tsconfig.json. It is used to resolve TypeScript paths aliases. (default: "./tsconfig.json") -p, --port number Port to run visualizer on (default: 64738) + -e, --env-path string Path to a .env file Global flags: -h, --help help for visualizer diff --git a/apps/cli/build.ts b/apps/cli/build.ts index f35a861..3751228 100644 --- a/apps/cli/build.ts +++ b/apps/cli/build.ts @@ -43,7 +43,7 @@ await bundle.write(config.output); await bundle.close(); // Add banner to dist/cli.js -const banner = `#!/usr/bin/env node\n`; +const banner = "#!/usr/bin/env node\n"; const cliFilePath = "dist/cli.js"; const originalContent = await fs.readFile(cliFilePath, "utf-8"); await fs.writeFile(cliFilePath, banner + originalContent); diff --git a/apps/cli/cli.ts b/apps/cli/cli.ts index 0fe8c0c..d51f5c6 100644 --- a/apps/cli/cli.ts +++ b/apps/cli/cli.ts @@ -3,8 +3,8 @@ import { spawnSync } from "node:child_process"; import { DRIZZLE_LAB_ENV_KEY, + getEnv, importDrizzleConfig, - DRIZZLE_LAB_TS_CONFIG_PATH, } from "@drizzle-lab/api/config/node"; import { command, string, run, boolean, number } from "@drizzle-team/brocli"; import chalk from "chalk"; @@ -17,23 +17,27 @@ const tsConfig = string() .desc( "Path to tsconfig.json. It is used to resolve TypeScript paths aliases.", ) - .default(DRIZZLE_LAB_TS_CONFIG_PATH); + .default(getEnv().DRIZZLE_LAB_TS_CONFIG_PATH); +const envPath = string() + .desc("Path to a .env file. It is used to load environment variables.") + .alias("e"); const visualizer = command({ name: "visualizer", options: { config: optionConfig, debug, - ["save-dir"]: string() + "save-dir": string() .desc("Directory to save the visualizer data") .default(".drizzle"), - ["project-id"]: string() + "project-id": string() .desc( "A unique identifier for the current visualized project. It is used as filename to save the visualizer state.", ) .default("visualizer"), - ["ts-config"]: tsConfig, + "ts-config": tsConfig, port: number().desc("Port to run visualizer on").default(64738).alias("p"), + "env-path": envPath, }, async transform(options) { const DRIZZLE_LAB_CWD = process.cwd(); @@ -46,6 +50,7 @@ const visualizer = command({ [DRIZZLE_LAB_ENV_KEY.PROJECT_ID]: options["project-id"], [DRIZZLE_LAB_ENV_KEY.CWD]: DRIZZLE_LAB_CWD, [DRIZZLE_LAB_ENV_KEY.TS_CONFIG_PATH]: options["ts-config"], + [DRIZZLE_LAB_ENV_KEY.ENV_FILE_PATH]: options["env-path"], } as const; process.env = { @@ -87,7 +92,7 @@ const visualizer = command({ ? spawnSync("vite", ["--host"], { stdio: "inherit", }) - : spawnSync(process.execPath, [`visualizer/server/index.mjs`], { + : spawnSync(process.execPath, ["visualizer/server/index.mjs"], { stdio: "inherit", cwd: import.meta.dirname, env: { @@ -104,11 +109,14 @@ const snapshot = command({ options: { config: optionConfig, debug, - ["ts-config"]: tsConfig, + "ts-config": tsConfig, + "env-path": envPath, }, transform: async (options) => { process.env[DRIZZLE_LAB_ENV_KEY.DEBUG] = String(options.debug); process.env[DRIZZLE_LAB_ENV_KEY.TS_CONFIG_PATH] = options["ts-config"]; + process.env[DRIZZLE_LAB_ENV_KEY.ENV_FILE_PATH] = options["env-path"]; + const config = await importDrizzleConfig(options.config); if (options.debug) { @@ -165,11 +173,14 @@ const sql = command({ options: { config: optionConfig, debug, - ["ts-config"]: tsConfig, + "ts-config": tsConfig, + "env-path": envPath, }, transform: async (options) => { process.env[DRIZZLE_LAB_ENV_KEY.DEBUG] = String(options.debug); process.env[DRIZZLE_LAB_ENV_KEY.TS_CONFIG_PATH] = options["ts-config"]; + process.env[DRIZZLE_LAB_ENV_KEY.ENV_FILE_PATH] = options["env-path"]; + const config = await importDrizzleConfig(options.config); if (options.debug) { diff --git a/apps/cli/package.json b/apps/cli/package.json index 04ee160..f99a66c 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -1,6 +1,6 @@ { "name": "drizzle-lab", - "version": "0.9.0", + "version": "0.10.0", "description": "Drizzle Lab CLI", "sideEffects": false, "type": "module", diff --git a/apps/cli/visualizer/entry.server.tsx b/apps/cli/visualizer/entry.server.tsx index 946471e..1a5c222 100644 --- a/apps/cli/visualizer/entry.server.tsx +++ b/apps/cli/visualizer/entry.server.tsx @@ -6,7 +6,7 @@ import { PassThrough } from "node:stream"; -import { DRIZZLE_LAB_DEBUG } from "@drizzle-lab/api/config/node"; +import { getEnv } from "@drizzle-lab/api/config/node"; import type { AppLoadContext, EntryContext } from "@remix-run/node"; import { createReadableStreamFromReadable } from "@remix-run/node"; import { RemixServer } from "@remix-run/react"; @@ -29,11 +29,11 @@ if (!global.__server) { // eslint-disable-next-line no-console console.log( `\n${chalk.green( - `Drizzle Visualizer`, + "Drizzle Visualizer", )} is up and running on ${chalk.blue(`http://127.0.0.1:${info.port}`)}\n`, ); }, - defaultLogger: DRIZZLE_LAB_DEBUG, + defaultLogger: getEnv().DRIZZLE_LAB_DEBUG, }); } diff --git a/apps/cli/visualizer/routes/_index.tsx b/apps/cli/visualizer/routes/_index.tsx index 085afba..bf9174c 100644 --- a/apps/cli/visualizer/routes/_index.tsx +++ b/apps/cli/visualizer/routes/_index.tsx @@ -4,7 +4,7 @@ import path from "node:path"; import { importDrizzleConfig, DRIZZLE_LAB_ENV_KEY, - DRIZZLE_LAB_DEBUG, + getEnv, } from "@drizzle-lab/api/config/node"; import { DrizzleVisualizer, @@ -61,7 +61,7 @@ export async function loader() { await fs.readFile(saveFilePath, "utf-8"), ) as NodePosition[]; } catch (e) { - if (DRIZZLE_LAB_DEBUG) { + if (getEnv().DRIZZLE_LAB_DEBUG) { console.warn( `Using default nodes positions. Reason is: ${ e instanceof Error ? e.message : "unknown" diff --git a/package-lock.json b/package-lock.json index 110d8d2..52bd136 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ }, "apps/cli": { "name": "drizzle-lab", - "version": "0.9.0", + "version": "0.10.0", "license": "MIT", "dependencies": { "@drizzle-lab/api": "*", @@ -11199,7 +11199,6 @@ "version": "16.4.5", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", - "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=12" @@ -25429,10 +25428,11 @@ }, "packages/api": { "name": "@drizzle-lab/api", - "version": "0.28.0", + "version": "0.29.0", "license": "MIT", "dependencies": { "chalk": "^5.3.0", + "dotenv": "^16.4.5", "glob": "^11.0.0", "jiti": "^2.4.0", "zod": "^3.23.8" diff --git a/packages/api/README.md b/packages/api/README.md index 013b17b..5783996 100644 --- a/packages/api/README.md +++ b/packages/api/README.md @@ -162,6 +162,7 @@ They are all optional. | `DRIZZLE_LAB_SAVE_DIR` | Directory to save output | `./drizzle` | | `DRIZZLE_LAB_PROJECT_ID` | Project ID to identify the project in json output | `drizzle-lab` | | `TS_CONFIG_PATH` | Path to tsconfig.json | `./tsconfig.json` | +| `DRIZZLE_LAB_ENV_FILE_PATH` | Path to env file | `undefined` | ## License diff --git a/packages/api/package.json b/packages/api/package.json index 14b0b4f..59271f1 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -1,6 +1,6 @@ { "name": "@drizzle-lab/api", - "version": "0.28.0", + "version": "0.29.0", "description": "Drizzle Lab API - Fork of Drizzle Kit API", "type": "module", "license": "MIT", @@ -198,6 +198,7 @@ }, "dependencies": { "chalk": "^5.3.0", + "dotenv": "^16.4.5", "glob": "^11.0.0", "jiti": "^2.4.0", "zod": "^3.23.8" diff --git a/packages/api/src/config/env.node.ts b/packages/api/src/config/env.node.ts index 2189ff1..b2d7119 100644 --- a/packages/api/src/config/env.node.ts +++ b/packages/api/src/config/env.node.ts @@ -5,20 +5,19 @@ export const DRIZZLE_LAB_ENV_KEY = { SAVE_DIR: "DRIZZLE_LAB_SAVE_DIR", PROJECT_ID: "DRIZZLE_LAB_PROJECT_ID", TS_CONFIG_PATH: "TS_CONFIG_PATH", + ENV_FILE_PATH: "DRIZZLE_LAB_ENV_FILE_PATH", } as const; -export const DRIZZLE_LAB_DEBUG = - process.env[DRIZZLE_LAB_ENV_KEY.DEBUG] === "true"; - -export const DRIZZLE_LAB_CWD = process.env[DRIZZLE_LAB_ENV_KEY.CWD] - ? `${process.env[DRIZZLE_LAB_ENV_KEY.CWD]}/` - : ""; - -export const DRIZZLE_LAB_CONFIG_PATH = - process.env[DRIZZLE_LAB_ENV_KEY.CONFIG_PATH]; - -export const DRIZZLE_LAB_PROJECT_ID = - process.env[DRIZZLE_LAB_ENV_KEY.PROJECT_ID]; - -export const DRIZZLE_LAB_TS_CONFIG_PATH = - process.env[DRIZZLE_LAB_ENV_KEY.TS_CONFIG_PATH] || "./tsconfig.json"; +export function getEnv() { + return { + DRIZZLE_LAB_DEBUG: process.env[DRIZZLE_LAB_ENV_KEY.DEBUG] === "true", + DRIZZLE_LAB_CWD: process.env[DRIZZLE_LAB_ENV_KEY.CWD] + ? `${process.env[DRIZZLE_LAB_ENV_KEY.CWD]}/` + : "", + DRIZZLE_LAB_CONFIG_PATH: process.env[DRIZZLE_LAB_ENV_KEY.CONFIG_PATH], + DRIZZLE_LAB_PROJECT_ID: process.env[DRIZZLE_LAB_ENV_KEY.PROJECT_ID], + DRIZZLE_LAB_TS_CONFIG_PATH: + process.env[DRIZZLE_LAB_ENV_KEY.TS_CONFIG_PATH] || "./tsconfig.json", + DRIZZLE_LAB_ENV_FILE_PATH: process.env[DRIZZLE_LAB_ENV_KEY.ENV_FILE_PATH], + }; +} diff --git a/packages/api/src/config/loader.node.ts b/packages/api/src/config/loader.node.ts index 5460302..7b34c5b 100644 --- a/packages/api/src/config/loader.node.ts +++ b/packages/api/src/config/loader.node.ts @@ -3,11 +3,7 @@ import Path from "node:path"; import { glob } from "glob"; -import { - DRIZZLE_LAB_CWD, - DRIZZLE_LAB_DEBUG, - DRIZZLE_LAB_PROJECT_ID, -} from "./env.node.ts"; +import { getEnv } from "./env.node.ts"; import { configCommonSchema } from "./schema.ts"; import { importModule } from "../internal/import-module.node.ts"; import { withStyle } from "../internal/style"; @@ -22,10 +18,10 @@ export type PartialConfig = Partial; */ export async function importDrizzleConfig(configPath?: string) { const defaultTsConfigExists = fs.existsSync( - Path.resolve(Path.join(DRIZZLE_LAB_CWD, "drizzle.config.ts")), + Path.resolve(Path.join(getEnv().DRIZZLE_LAB_CWD, "drizzle.config.ts")), ); const defaultJsConfigExists = fs.existsSync( - Path.resolve(Path.join(DRIZZLE_LAB_CWD, "drizzle.config.js")), + Path.resolve(Path.join(getEnv().DRIZZLE_LAB_CWD, "drizzle.config.js")), ); const defaultConfigPath = defaultTsConfigExists @@ -34,7 +30,7 @@ export async function importDrizzleConfig(configPath?: string) { ? "drizzle.config.js" : "drizzle.config.json"; - if (DRIZZLE_LAB_DEBUG && !configPath) { + if (getEnv().DRIZZLE_LAB_DEBUG && !configPath) { console.info( withStyle.info( `No config path provided, using default '${defaultConfigPath}'`, @@ -43,7 +39,7 @@ export async function importDrizzleConfig(configPath?: string) { } const path = Path.resolve( - Path.join(DRIZZLE_LAB_CWD, configPath ?? defaultConfigPath), + Path.join(getEnv().DRIZZLE_LAB_CWD, configPath ?? defaultConfigPath), ); if (!fs.existsSync(path)) { @@ -51,7 +47,7 @@ export async function importDrizzleConfig(configPath?: string) { throw new Error(); } - if (DRIZZLE_LAB_DEBUG) { + if (getEnv().DRIZZLE_LAB_DEBUG) { console.info(withStyle.info(`Reading config file '${path}'`)); } @@ -69,13 +65,13 @@ export async function importDrizzleConfig(configPath?: string) { return { ...config.data, schema: prepareFilenames(config.data.schema), - projectId: config.data.lab.projectId || DRIZZLE_LAB_PROJECT_ID, + projectId: config.data.lab.projectId || getEnv().DRIZZLE_LAB_PROJECT_ID, }; } const prepareFilenames = (paths: string[]) => { const matches = paths.reduce((matches, cur) => { - const globMatches = glob.sync(`${DRIZZLE_LAB_CWD}${cur}`); + const globMatches = glob.sync(`${getEnv().DRIZZLE_LAB_CWD}${cur}`); globMatches.forEach((it) => { const fileName = fs.lstatSync(it).isDirectory() ? null : Path.resolve(it); diff --git a/packages/api/src/internal/import-module.node.ts b/packages/api/src/internal/import-module.node.ts index 8f23c45..913d92d 100644 --- a/packages/api/src/internal/import-module.node.ts +++ b/packages/api/src/internal/import-module.node.ts @@ -3,16 +3,13 @@ import path from "node:path"; import { pathToFileURL } from "node:url"; import chalk from "chalk"; +import { config } from "dotenv"; import { createJiti } from "jiti"; -import { - DRIZZLE_LAB_CWD, - DRIZZLE_LAB_DEBUG, - DRIZZLE_LAB_TS_CONFIG_PATH, -} from "../config/env.node.ts"; +import { getEnv } from "../config/env.node.ts"; const jiti = createJiti(import.meta.url, { - alias: loadTsConfigPathsAlias(DRIZZLE_LAB_CWD), + alias: loadTsConfigPathsAlias(getEnv().DRIZZLE_LAB_CWD), moduleCache: false, }); @@ -24,11 +21,15 @@ let warned = false; * @node-only - This function is not supported in the browser. */ export async function importModule(path: string) { - if (DRIZZLE_LAB_DEBUG) { + if (getEnv().DRIZZLE_LAB_DEBUG) { console.log("[importModule] Importing module", path); } try { + if (getEnv().DRIZZLE_LAB_ENV_FILE_PATH) { + config({ path: getEnv().DRIZZLE_LAB_ENV_FILE_PATH }); + } + let module = await jiti.import<{ default: { default?: any } }>( pathToFileURL(path).href, ); @@ -52,7 +53,7 @@ export async function importModule(path: string) { return module; } catch (e) { - if (DRIZZLE_LAB_DEBUG) { + if (getEnv().DRIZZLE_LAB_DEBUG) { console.error( "[importModule] Failed to import module", path, @@ -65,7 +66,7 @@ export async function importModule(path: string) { function loadTsConfigPathsAlias(cwd: string) { try { - const tsconfigPath = path.resolve(cwd, DRIZZLE_LAB_TS_CONFIG_PATH); + const tsconfigPath = path.resolve(cwd, getEnv().DRIZZLE_LAB_TS_CONFIG_PATH); let rawImport = fs.readFileSync(tsconfigPath, "utf8"); // Remove single-line comments rawImport = rawImport.replace(/\/\/.*$/gm, ""); @@ -86,7 +87,7 @@ function loadTsConfigPathsAlias(cwd: string) { return acc; }, {}); - if (DRIZZLE_LAB_DEBUG) { + if (getEnv().DRIZZLE_LAB_DEBUG) { console.log("[tsconfig] Loading tsConfig path", tsconfigPath); console.log("[tsconfig] Loaded tsConfig", rawImport); console.log("[tsconfig] TS alias", alias); diff --git a/vscode-extension/CHANGELOG.md b/vscode-extension/CHANGELOG.md index 0382d36..3dce319 100644 --- a/vscode-extension/CHANGELOG.md +++ b/vscode-extension/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to the "drizzle-orm" extension will be documented in this fi Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. +## [0.9.0] + +- Upgrade to the latest drizzle-lab visualizer +- Support loading env files in the visualizer + ## [0.8.0] - New visualizer UI diff --git a/vscode-extension/package-lock.json b/vscode-extension/package-lock.json index 3376377..d8fcd99 100644 --- a/vscode-extension/package-lock.json +++ b/vscode-extension/package-lock.json @@ -1,12 +1,12 @@ { "name": "vscode-drizzle-orm", - "version": "0.8.0", + "version": "0.9.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "vscode-drizzle-orm", - "version": "0.8.0", + "version": "0.9.0", "license": "MIT", "devDependencies": { "@types/mocha": "^10.0.9", diff --git a/vscode-extension/package.json b/vscode-extension/package.json index d25c11f..2019cc7 100644 --- a/vscode-extension/package.json +++ b/vscode-extension/package.json @@ -3,7 +3,7 @@ "displayName": "Drizzle ORM", "description": "Adds schema visualizer for Drizzle ORM", "preview": true, - "version": "0.8.0", + "version": "0.9.0", "private": true, "icon": "icon.png", "license": "MIT", diff --git a/vscode-extension/src/extension.ts b/vscode-extension/src/extension.ts index a27efd5..f20e6e4 100644 --- a/vscode-extension/src/extension.ts +++ b/vscode-extension/src/extension.ts @@ -15,8 +15,6 @@ import { outputChannel } from "./utils"; import { OpenStudioCommand, OpenStudio, - SelectEnvAndOpenStudio, - SelectEnvAndOpenStudioCommand, } from "./modules/studio/open-studio/command"; import { StopStudioCommand, @@ -24,17 +22,20 @@ import { } from "./modules/studio/stop-studio/command"; import { OpenStudioCodeLens } from "./modules/studio/open-studio/codelens"; import { stopStudio } from "./modules/studio/server"; +import { + SelectEnv, + SelectEnvCommand, +} from "./modules/internal/select-env.command"; export function activate(context: vscode.ExtensionContext) { checkNodeVersion(); context.subscriptions.push( + /* Internal */ + vscode.commands.registerCommand(SelectEnvCommand, SelectEnv), + /* Studio */ vscode.commands.registerCommand(OpenStudioCommand, OpenStudio), - vscode.commands.registerCommand( - SelectEnvAndOpenStudioCommand, - SelectEnvAndOpenStudio, - ), vscode.commands.registerCommand(StopStudioCommand, StopStudio), vscode.languages.registerCodeLensProvider( { pattern: "**/*{drizzle,config}.ts", language: "typescript" }, diff --git a/vscode-extension/src/modules/internal/select-env.command.ts b/vscode-extension/src/modules/internal/select-env.command.ts new file mode 100644 index 0000000..28b1fd2 --- /dev/null +++ b/vscode-extension/src/modules/internal/select-env.command.ts @@ -0,0 +1,53 @@ +import * as vscode from "vscode"; + +export const SelectEnvCommand = "drizzle:select_env"; + +/* Local state */ +let $lastSelectedEnv: string | undefined; + +export async function SelectEnv(configPath: string, executeCommand: string) { + // Find .env files in the workspace + const envFiles = await vscode.workspace.findFiles( + "**/.env*", + "**/node_modules/**", + ); + + // Create quick pick items + const items = envFiles.map((file) => ({ + label: vscode.workspace.asRelativePath(file), + path: file.fsPath, + })); + + // Add option to not use an env file + items.unshift({ label: "None", path: "Don't use an env file" }); + + // Move last selected item to top if it exists + if ($lastSelectedEnv) { + const lastSelectedIndex = items.findIndex( + (item) => item.path === $lastSelectedEnv, + ); + if (lastSelectedIndex > -1) { + const [lastItem] = items.splice(lastSelectedIndex, 1); + items.unshift(lastItem); + } + } + + // Show quick pick + const selected = await vscode.window.showQuickPick(items, { + placeHolder: "Select an environment file", + }); + + if (selected) { + // Save the selection to workspace configuration (except for "None") + if (selected.label !== "None") { + $lastSelectedEnv = selected.path; + } + + // Call open studio command with the selected env file + await vscode.commands.executeCommand( + executeCommand, + configPath, + selected.label === "None" ? undefined : selected.path, + ); + } +} diff --git a/vscode-extension/src/modules/studio/open-studio/codelens.ts b/vscode-extension/src/modules/studio/open-studio/codelens.ts index f5ec518..eac9ede 100644 --- a/vscode-extension/src/modules/studio/open-studio/codelens.ts +++ b/vscode-extension/src/modules/studio/open-studio/codelens.ts @@ -2,7 +2,8 @@ import * as vscode from "vscode"; import { findDrizzleConfigLines } from "../../../utils"; import { findDrizzleKitPath } from "../server"; -import { SelectEnvAndOpenStudioCommand } from "./command"; +import { SelectEnvCommand } from "../../internal/select-env.command"; +import { OpenStudioCommand } from "./command"; export class OpenStudioCodeLens implements vscode.CodeLensProvider { async provideCodeLenses( @@ -23,9 +24,9 @@ export class OpenStudioCodeLens implements vscode.CodeLensProvider { return new vscode.CodeLens(range, { title: "🌧️ Open Drizzle Studio", - command: SelectEnvAndOpenStudioCommand, + command: SelectEnvCommand, tooltip: "Open Drizzle Studio", - arguments: [document.uri.fsPath], + arguments: [document.uri.fsPath, OpenStudioCommand], }); }, ); diff --git a/vscode-extension/src/modules/studio/open-studio/command.ts b/vscode-extension/src/modules/studio/open-studio/command.ts index 993e56e..9ee235a 100644 --- a/vscode-extension/src/modules/studio/open-studio/command.ts +++ b/vscode-extension/src/modules/studio/open-studio/command.ts @@ -46,56 +46,3 @@ export async function OpenStudio(...args: any[]) { return; } } - -export const SelectEnvAndOpenStudioCommand = - "drizzle.studio:select_env_and_open"; - -/* Local state */ -let $lastSelectedEnv: string | undefined; - -export async function SelectEnvAndOpenStudio(configPath: string) { - // Find .env files in the workspace - const envFiles = await vscode.workspace.findFiles( - "**/.env*", - "**/node_modules/**", - ); - - // Create quick pick items - const items = envFiles.map((file) => ({ - label: vscode.workspace.asRelativePath(file), - path: file.fsPath, - })); - - // Add option to not use an env file - items.unshift({ label: "None", path: "Don't use an env file" }); - - // Move last selected item to top if it exists - if ($lastSelectedEnv) { - const lastSelectedIndex = items.findIndex( - (item) => item.path === $lastSelectedEnv, - ); - if (lastSelectedIndex > -1) { - const [lastItem] = items.splice(lastSelectedIndex, 1); - items.unshift(lastItem); - } - } - - // Show quick pick - const selected = await vscode.window.showQuickPick(items, { - placeHolder: "Select an environment file", - }); - - if (selected) { - // Save the selection to workspace configuration (except for "None") - if (selected.label !== "None") { - $lastSelectedEnv = selected.path; - } - - // Call open studio command with the selected env file - await vscode.commands.executeCommand( - OpenStudioCommand, - configPath, - selected.label === "None" ? undefined : selected.path, - ); - } -} diff --git a/vscode-extension/src/modules/studio/server.ts b/vscode-extension/src/modules/studio/server.ts index d93f1a0..2e120c6 100644 --- a/vscode-extension/src/modules/studio/server.ts +++ b/vscode-extension/src/modules/studio/server.ts @@ -9,11 +9,12 @@ import { outputChannel } from "../../utils"; let $app: ChildProcessWithoutNullStreams | undefined = undefined; let $processIds: number[] = []; let $configPath: string | undefined = undefined; +let $envFilePath: string | undefined = undefined; /* Constants */ const OutputKey = "[Studio]"; -export async function startStudio(configPath: string, envFile?: string) { +export async function startStudio(configPath: string, envFilePath?: string) { return new Promise(async (resolve, reject) => { // if config path has changed, restart the server if ($configPath && $configPath !== configPath) { @@ -25,6 +26,16 @@ export async function startStudio(configPath: string, envFile?: string) { $configPath = configPath; + // if env path has changed, restart the server + if ($envFilePath !== envFilePath) { + outputChannel.appendLine( + `${OutputKey} Env file path changed. Killing server and restarting with new env file path: ${envFilePath}`, + ); + stopStudio(); + } + + $envFilePath = envFilePath; + // if app is already running on the same config path, return the existing app if ($app) { outputChannel.appendLine( @@ -33,9 +44,9 @@ export async function startStudio(configPath: string, envFile?: string) { return resolve(); } - const envFileArg = envFile ? ["--env-file", envFile] : []; + const envFileArg = envFilePath ? ["--env-file", envFilePath] : []; outputChannel.appendLine( - `${OutputKey} Using env file: ${envFile ? envFile : "none"}`, + `${OutputKey} Using env file: ${envFilePath ? envFilePath : "none"}`, ); const drizzleKitPath = findDrizzleKitPath($configPath); diff --git a/vscode-extension/src/modules/visualizer/open-visualizer/codelens.ts b/vscode-extension/src/modules/visualizer/open-visualizer/codelens.ts index 0fc4335..63ba6a8 100644 --- a/vscode-extension/src/modules/visualizer/open-visualizer/codelens.ts +++ b/vscode-extension/src/modules/visualizer/open-visualizer/codelens.ts @@ -2,6 +2,7 @@ import * as vscode from "vscode"; import { findDrizzleConfigLines } from "../../../utils"; import { OpenVisualizerCommand } from "./command"; +import { SelectEnvCommand } from "../../internal/select-env.command"; export class OpenVisualizerCodeLens implements vscode.CodeLensProvider { async provideCodeLenses( @@ -15,9 +16,9 @@ export class OpenVisualizerCodeLens implements vscode.CodeLensProvider { return new vscode.CodeLens(range, { title: "🌧️ Open Drizzle Visualizer", - command: OpenVisualizerCommand, + command: SelectEnvCommand, tooltip: "Open Drizzle Schema Visualizer", - arguments: [document.uri.fsPath], + arguments: [document.uri.fsPath, OpenVisualizerCommand], }); }); } diff --git a/vscode-extension/src/modules/visualizer/open-visualizer/command.ts b/vscode-extension/src/modules/visualizer/open-visualizer/command.ts index db851f6..ba34514 100644 --- a/vscode-extension/src/modules/visualizer/open-visualizer/command.ts +++ b/vscode-extension/src/modules/visualizer/open-visualizer/command.ts @@ -7,6 +7,7 @@ export const OpenVisualizerCommand = "drizzle.visualizer:open"; export async function OpenVisualizer(...args: any[]) { const OutputKey = `[${OpenVisualizerCommand}]`; const configPath = args[0]; + const envFilePath = args[1]; if (!configPath || typeof configPath !== "string") { toastError(`${OutputKey} Expected config path to be a string`); @@ -14,7 +15,7 @@ export async function OpenVisualizer(...args: any[]) { } try { - const { port } = await startVisualizer(configPath); + const { port } = await startVisualizer(configPath, envFilePath); const panel = createDrizzleVisualizerPanel(); panel.webview.html = render(` diff --git a/vscode-extension/src/modules/visualizer/server.ts b/vscode-extension/src/modules/visualizer/server.ts index 11a66ba..bb6fc0b 100644 --- a/vscode-extension/src/modules/visualizer/server.ts +++ b/vscode-extension/src/modules/visualizer/server.ts @@ -9,6 +9,7 @@ let $port: string | undefined = undefined; let $app: ChildProcessWithoutNullStreams | undefined = undefined; let $processIds: number[] = []; let $configPath: string | undefined = undefined; +let $envFilePath: string | undefined = undefined; /* Constants */ const OutputKey = "[Visualizer]"; @@ -20,7 +21,11 @@ interface ServerStartResult { port: string; } -export async function startVisualizer(configPath: string) { +export async function startVisualizer( + configPath: string, + envFilePath?: string, +) { + console.log("envFilePath", envFilePath); outputChannel.appendLine(`${OutputKey} extension cwd: ${extensionCwd}`); outputChannel.appendLine(`${OutputKey} apps cwd: ${appsCwd}`); outputChannel.appendLine( @@ -38,6 +43,16 @@ export async function startVisualizer(configPath: string) { $configPath = configPath; + // if env path has changed, restart the server + if ($envFilePath !== envFilePath) { + outputChannel.appendLine( + `${OutputKey} Env file path changed. Killing server and restarting with new env file path: ${envFilePath}`, + ); + stopVisualizer(); + } + + $envFilePath = envFilePath; + if (!$port) { // random port from 60_000 to 64_000 $port = String(Math.floor(Math.random() * 4000) + 60000); @@ -61,6 +76,7 @@ export async function startVisualizer(configPath: string) { PORT: $port, NODE_ENV: "production", TS_CONFIG_PATH: path.join(cwd, "tsconfig.json"), + DRIZZLE_LAB_ENV_FILE_PATH: envFilePath, }; $app = spawn(process.execPath, [binPath], {