From 883d452c034e0521703cfe4151892ad84bb8aac1 Mon Sep 17 00:00:00 2001 From: Ola Adebayo Date: Tue, 23 Jun 2026 17:12:07 +0100 Subject: [PATCH 1/2] fix(vite): bake package version in at build time getPackageVersion() read package.json at runtime via import.meta.url. When a consumer imports the plugin inside vite.config.ts, Vite bundles the config with esbuild and rewrites import.meta.url, so the read failed and the injected `data-rep-version` (and `_meta.version`) fell back to "0.0.0". Inject the version via a tsup `define` (tsup.config.ts) so it is baked into the bundle at build time, independent of how the consumer loads the plugin. --- plugins/vite/package.json | 2 +- plugins/vite/src/index.ts | 25 ++++++++++++------------- plugins/vite/tsup.config.ts | 15 +++++++++++++++ 3 files changed, 28 insertions(+), 14 deletions(-) create mode 100644 plugins/vite/tsup.config.ts 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), + }, +}); From 798306107875198712318caa3a67a0f6609dbade Mon Sep 17 00:00:00 2001 From: Ola Adebayo Date: Tue, 23 Jun 2026 17:12:07 +0100 Subject: [PATCH 2/2] docs(vite): add plugin README --- plugins/vite/README.md | 131 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 plugins/vite/README.md 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