diff --git a/plugins/vite/README.md b/plugins/vite/README.md new file mode 100644 index 0000000..60eec6a --- /dev/null +++ b/plugins/vite/README.md @@ -0,0 +1,131 @@ +# @rep-protocol/vite + +Vite plugin for the [Runtime Environment Protocol (REP)](https://github.com/RuachTech/rep). Injects REP environment variables during development without needing the Go gateway. + +In production, this plugin does nothing — the REP gateway handles variable injection (and, in `embedded` mode, also serves your built static files). + +## Install + +```bash +pnpm add -D @rep-protocol/vite +# or +npm install -D @rep-protocol/vite +``` + +Peer dependency: `vite >= 4`. + +## Setup + +### 1. Add the plugin to `vite.config.ts` + +```ts +// vite.config.ts +import { defineConfig } from 'vite'; +import { repPlugin } from '@rep-protocol/vite'; + +export default defineConfig({ + plugins: [repPlugin()], +}); +``` + +The plugin is dev-only by construction: it injects the `` injection. +- The dev session-key endpoint has no rate limiting or single-use semantics — + production deployments must use the REP gateway. + +## Troubleshooting + +### `404` / no `#__rep__` script in development + +Ensure `repPlugin()` is in your `vite.config.ts` `plugins` array and that your +env file exists at the configured path (default `.env.local`, relative to the +project root). + +### `REPError: SENSITIVE variable "X" not found in payload` + +The variable isn't set in your `.env.local`. If it's optional, catch the error: + +```ts +const getOptionalKey = (): Promise => + rep.getSecure('OPTIONAL_KEY').catch(() => ''); +``` + +## License + +Apache-2.0 diff --git a/plugins/vite/package.json b/plugins/vite/package.json index 6f5ddbb..c26e5db 100644 --- a/plugins/vite/package.json +++ b/plugins/vite/package.json @@ -34,7 +34,7 @@ "dist" ], "scripts": { - "build": "tsup src/index.ts --format cjs,esm --dts", + "build": "tsup", "test": "vitest run", "test:watch": "vitest", "typecheck": "tsc --noEmit" diff --git a/plugins/vite/src/index.ts b/plugins/vite/src/index.ts index 26175cb..e26258f 100644 --- a/plugins/vite/src/index.ts +++ b/plugins/vite/src/index.ts @@ -1,12 +1,21 @@ -import { resolve, dirname } from 'node:path'; -import { readFileSync } from 'node:fs'; -import { fileURLToPath } from 'node:url'; +import { resolve } from 'node:path'; import type { Plugin, ViteDevServer, HtmlTagDescriptor } from 'vite'; import { generateKeys, type Keys } from './crypto.js'; import { readAndClassify, type ClassifiedVars } from './env.js'; import { scanValue } from './guardrails.js'; import { buildPayload, type PayloadResult } from './payload.js'; +// Injected at build time by tsup (see tsup.config.ts). Reading package.json at +// runtime via import.meta.url is unreliable here: consumers import this plugin +// inside vite.config.ts, which Vite bundles with esbuild — that rewrites +// import.meta.url, so the runtime read fails and the version falls back to +// 0.0.0. Baking the version in at build time avoids that entirely. +declare const __REP_VITE_VERSION__: string; + +function getPackageVersion(): string { + return typeof __REP_VITE_VERSION__ === 'string' ? __REP_VITE_VERSION__ : '0.0.0'; +} + export interface RepPluginOptions { /** Path to env file, relative to project root. Default: '.env.local' */ env?: string; @@ -14,16 +23,6 @@ export interface RepPluginOptions { strict?: boolean; } -function getPackageVersion(): string { - try { - const pkgPath = resolve(dirname(fileURLToPath(import.meta.url)), '..', 'package.json'); - const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')); - return pkg.version; - } catch { - return '0.0.0'; - } -} - export function repPlugin(options: RepPluginOptions = {}): Plugin { const envFile = options.env ?? '.env.local'; const strict = options.strict ?? false; diff --git a/plugins/vite/tsup.config.ts b/plugins/vite/tsup.config.ts new file mode 100644 index 0000000..0fd756a --- /dev/null +++ b/plugins/vite/tsup.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from 'tsup'; +import { readFileSync } from 'node:fs'; + +const { version } = JSON.parse(readFileSync(new URL('./package.json', import.meta.url), 'utf-8')); + +export default defineConfig({ + entry: ['src/index.ts'], + format: ['cjs', 'esm'], + dts: true, + // Bake the package version in at build time so it survives consumers that + // bundle their vite.config (which would otherwise rewrite import.meta.url). + define: { + __REP_VITE_VERSION__: JSON.stringify(version), + }, +});