@ojolowoblue/lamba 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ojolowo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom scientific or technical
10
+ work is furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,249 @@
1
+ # lamba ⚡
2
+
3
+ **`lamba`** is a universal, lightweight developer tool and browser widget for viewing, overriding, and swapping environment variables live in web applications (React, Vue, Next.js, Vite, Astro, Svelte, or Vanilla HTML/JS)—**without touching source code, restarting dev servers, or editing `.env` files.**
4
+
5
+ Deployed via CDN or installed via NPM, `lamba` injects a non-intrusive floating UI powered by **Shadow DOM encapsulation**. Devs, QA engineers, and project managers can test multiple API environments, toggle feature flags, switch authentication tokens, and swap backend clusters on the fly directly in the browser.
6
+
7
+ ---
8
+
9
+ ## 🌟 Key Features
10
+
11
+ - ⚡ **Zero-Setup CDN & NPM Support**: Add a single `<script>` tag or install via NPM/Yarn/PNPM.
12
+ - 🛡️ **Shadow DOM Encapsulation**: Modern glassmorphism UI rendered inside a Custom Element (`<lamba-widget>`), ensuring zero CSS style leakage into or out of your app.
13
+ - 🌐 **Automatic Network Interception**: Automatically intercepts outbound `fetch()` and `XMLHttpRequest` calls hitting default base URLs and redirects them to your live active environment overrides on the fly.
14
+ - 🎛️ **Preset Profile Manager**: Save named environment snapshots (e.g., *Staging API*, *Local Mock Server*, *QA Test Suite*, *Production Read-Only*) and switch between them with one click.
15
+ - 🔒 **Automatic Secret Masking**: Detects sensitive environment keys (`SECRET`, `TOKEN`, `PASSWORD`, `KEY`, `AUTH`, `PRIVATE`) and automatically masks them with toggle visibility.
16
+ - ⚛️ **Framework Agnostic + React & Vue Hooks**: Built-in `useLambaEnv` reactive hooks/composables for React and Vue, plus standard TypeScript APIs.
17
+ - 📁 **Bulk Import & Export**: Import existing `.env` files or export modified configurations directly to `.env` or JSON format.
18
+ - 💾 **Persistent Overrides**: Overridden variables persist seamlessly across page reloads using browser `localStorage`.
19
+
20
+ ---
21
+
22
+ ## 🚀 Quick Start
23
+
24
+ ### Option 1: CDN (Zero Build Setup)
25
+
26
+ Include the script tag in your `index.html` file before your application bundle:
27
+
28
+ ```html
29
+ <script src="https://unpkg.com/@ojolowoblue/lamba"></script>
30
+ ```
31
+
32
+ That's it! A floating settings button (⚙️) will automatically appear in the bottom-right corner of your web page.
33
+
34
+ ### Option 2: NPM / Package Manager
35
+
36
+ Install `lamba` in your project:
37
+
38
+ ```bash
39
+ npm install @ojolowoblue/lamba
40
+ # or
41
+ yarn add @ojolowoblue/lamba
42
+ # or
43
+ pnpm add @ojolowoblue/lamba
44
+ ```
45
+
46
+ Initialize `lamba` in your application entrypoint (`src/main.ts` or `src/index.js`):
47
+
48
+ ```typescript
49
+ import lamba from '@ojolowoblue/lamba';
50
+
51
+ lamba.init({
52
+ position: 'bottom-right',
53
+ env: {
54
+ VITE_API_BASE_URL: 'https://api.dev.example.com',
55
+ VITE_FEATURE_NEW_CHECKOUT: 'false',
56
+ VITE_ENABLE_ANALYTICS: 'true',
57
+ },
58
+ });
59
+ ```
60
+
61
+ ---
62
+
63
+ ## ⚡ How It Works & Implicit Operation
64
+
65
+ `lamba` is designed to be **100% implicit**. You don't need to refactor your codebase or replace standard environment variable accesses.
66
+
67
+ ### 1. Automatic Outbound Network URL Interception (`fetch` & `XHR`)
68
+
69
+ When you override a base URL variable in `lamba` (e.g., `VITE_API_BASE_URL` from `https://api.dev.com` to `https://staging.dev.com`), `lamba` automatically intercepts all outbound network requests targeting the original base URL and redirects them live!
70
+
71
+ ```typescript
72
+ // Developer writes standard code — ZERO changes required!
73
+ fetch('https://api.dev.com/v1/users')
74
+ .then(res => res.json())
75
+ .then(data => console.log(data));
76
+
77
+ // ⚡ Automatically redirected to https://staging.dev.com/v1/users when overridden in lamba UI!
78
+ ```
79
+
80
+ ### 2. Transparent Environment Wrapper (`lamba.wrap()`)
81
+
82
+ Wrap your existing `import.meta.env` (Vite) or `process.env` (Webpack/Next.js) object once:
83
+
84
+ ```typescript
85
+ // src/config.ts
86
+ import lamba from '@ojolowoblue/lamba';
87
+
88
+ // Wrap your env object in a dynamic ES Proxy
89
+ export const env = lamba.wrap(import.meta.env);
90
+
91
+ // Access keys anywhere in your application:
92
+ console.log(env.VITE_API_BASE_URL); // Automatically resolves live active override or default!
93
+ ```
94
+
95
+ ### 3. Implicit `lamba.env` & `process.env` Proxies
96
+
97
+ Access environment keys dynamically with natural object dot notation:
98
+
99
+ ```typescript
100
+ // Access live environment overrides directly:
101
+ const apiBase = lamba.env.VITE_API_BASE_URL;
102
+ const isDebug = lamba.env.VITE_DEBUG_MODE;
103
+
104
+ // Programmatically set overrides via property assignment:
105
+ lamba.env.VITE_API_BASE_URL = 'https://api.staging.example.com';
106
+ ```
107
+
108
+ ---
109
+
110
+ ## 📦 Framework Integrations
111
+
112
+ ### ⚛️ React Integration
113
+
114
+ Import `useLambaEnv` from `lamba/react` to subscribe your components reactively to environment changes:
115
+
116
+ ```tsx
117
+ import React from 'react';
118
+ import { useLambaEnv } from '@ojolowoblue/lamba/react';
119
+
120
+ export function UserDashboard() {
121
+ const apiBase = useLambaEnv('VITE_API_BASE_URL', 'https://api.dev.com');
122
+ const showBetaFeature = useLambaEnv('VITE_FEATURE_BETA_UI', 'false');
123
+
124
+ return (
125
+ <div style={{ padding: '24px' }}>
126
+ <h1>Dashboard</h1>
127
+ <p>Connected Environment: <code>{apiBase}</code></p>
128
+
129
+ {showBetaFeature === 'true' && (
130
+ <div className="beta-banner">
131
+ 🚀 Beta UI Enabled Live via lamba!
132
+ </div>
133
+ )}
134
+ </div>
135
+ );
136
+ }
137
+ ```
138
+
139
+ ### 🟢 Vue 3 Integration
140
+
141
+ Import `useLambaEnv` from `lamba/vue` as a reactive composition Vue Ref:
142
+
143
+ ```vue
144
+ <script setup lang="ts">
145
+ import { useLambaEnv } from '@ojolowoblue/lamba/vue';
146
+
147
+ const apiBase = useLambaEnv('VITE_API_BASE_URL', 'https://api.dev.com');
148
+ const featureFlag = useLambaEnv('VITE_NEW_HEADER', 'false');
149
+ </script>
150
+
151
+ <template>
152
+ <div class="container">
153
+ <h2>Current Backend: {{ apiBase }}</h2>
154
+ <header v-if="featureFlag === 'true'">
155
+ <h3>✨ New Header Component</h3>
156
+ </header>
157
+ </div>
158
+ </template>
159
+ ```
160
+
161
+ ---
162
+
163
+ ## 🛠️ Complete API Reference
164
+
165
+ ### `lamba.init(options?: LambaOptions): LambaManager`
166
+
167
+ Initializes the lamba manager, hydrates saved overrides from `localStorage`, enables network interceptors, and mounts the floating Shadow DOM UI.
168
+
169
+ | Option | Type | Default | Description |
170
+ | :--- | :--- | :--- | :--- |
171
+ | `env` | `Record<string, string>` | `{}` | Initial default key-value pairs of environment variables. |
172
+ | `enabled` | `boolean` | `true` | Set to `false` to disable lamba (e.g. in production builds). |
173
+ | `position` | `'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left'` | `'bottom-right'` | Screen position for the floating widget launcher button. |
174
+ | `secretKeysPattern` | `RegExp` | `/(KEY\|SECRET\|TOKEN\|PASSWORD\|AUTH\|PRIVATE)/i` | Regular expression to automatically obscure sensitive keys in the UI. |
175
+ | `autoFetchEnvFile` | `boolean` | `false` | Whether to attempt fetching root `/.env` file during local development. |
176
+ | `interceptNetworkRequests` | `boolean` | `true` | Whether to implicitly intercept `fetch` & `XHR` calls matching original base URLs. |
177
+
178
+ ---
179
+
180
+ ### Core Methods
181
+
182
+ #### `lamba.get(key: string, fallback?: string): string`
183
+ Returns the active value for the specified environment key (returns active override if present, otherwise default value or fallback).
184
+
185
+ #### `lamba.set(key: string, value: string): void`
186
+ Programmatically overrides an environment variable live at runtime. The change is persisted in `localStorage` and triggers UI and listener updates.
187
+
188
+ #### `lamba.remove(key: string): void`
189
+ Removes an override for a specific environment variable key, reverting it to its default value.
190
+
191
+ #### `lamba.reset(): void`
192
+ Clears all active environment overrides, reverting all keys back to their original default values.
193
+
194
+ #### `lamba.onChange(listener: EnvChangeListener): () => void`
195
+ Subscribes to live environment updates. Returns an `unsubscribe` function.
196
+
197
+ ```typescript
198
+ const unsubscribe = lamba.onChange((key, value, isOverridden) => {
199
+ console.log(`Environment variable ${key} changed to ${value} (Overridden: ${isOverridden})`);
200
+ });
201
+ ```
202
+
203
+ #### `lamba.wrap<T>(targetEnv: T): T`
204
+ Wraps an environment object in an ES Proxy that automatically intercepts property access to return active lamba overrides.
205
+
206
+ #### `lamba.open()` / `lamba.close()` / `lamba.toggle()`
207
+ Programmatically controls the visibility of the lamba modal panel.
208
+
209
+ ---
210
+
211
+ ## 🔒 Production Security Best Practice
212
+
213
+ To prevent end-users from overriding environment variables in production, conditionally initialize `lamba` only in non-production environments:
214
+
215
+ ```typescript
216
+ import lamba from '@ojolowoblue/lamba';
217
+
218
+ lamba.init({
219
+ enabled: process.env.NODE_ENV !== 'production',
220
+ env: {
221
+ VITE_API_URL: import.meta.env.VITE_API_URL,
222
+ },
223
+ });
224
+ ```
225
+
226
+ ---
227
+
228
+ ## ❓ Frequently Asked Questions (FAQ)
229
+
230
+ <details>
231
+ <summary><b>Does lamba modify my local <code>.env</code> files on disk?</b></summary>
232
+ <p>No. <code>lamba</code> operates entirely in browser memory and persists overrides in <code>localStorage</code>. It does not write to disk, so your git status remains clean.</p>
233
+ </details>
234
+
235
+ <details>
236
+ <summary><b>Do overrides persist when I refresh the page?</b></summary>
237
+ <p>Yes. Overrides and active preset profiles are saved in <code>localStorage</code> and automatically restored upon page reloads.</p>
238
+ </details>
239
+
240
+ <details>
241
+ <summary><b>Will lamba CSS affect my web application styles?</b></summary>
242
+ <p>No. All <code>lamba</code> UI components and styles are rendered inside a modern <b>Shadow DOM host element</b> (<code>&lt;lamba-widget&gt;</code>), guaranteeing 100% style isolation.</p>
243
+ </details>
244
+
245
+ ---
246
+
247
+ ## 📄 License
248
+
249
+ MIT License © 2026
@@ -0,0 +1,114 @@
1
+ interface EnvVariable {
2
+ key: string;
3
+ value: string;
4
+ defaultValue: string;
5
+ isOverridden: boolean;
6
+ isSecret?: boolean;
7
+ }
8
+ interface PresetProfile {
9
+ id: string;
10
+ name: string;
11
+ overrides: Record<string, string>;
12
+ createdAt: number;
13
+ }
14
+ interface LambaOptions {
15
+ /**
16
+ * Initial environment variable key-values to supply to lamba.
17
+ */
18
+ env?: Record<string, string>;
19
+ /**
20
+ * Whether lamba floating UI is enabled. Defaults to true in non-production or when specified.
21
+ */
22
+ enabled?: boolean;
23
+ /**
24
+ * Position of the floating launcher button.
25
+ * Options: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'
26
+ * Defaults to 'bottom-right'
27
+ */
28
+ position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
29
+ /**
30
+ * Secret keys regex pattern to automatically mask in the UI (e.g. API_KEY, SECRET, TOKEN, PASSWORD).
31
+ */
32
+ secretKeysPattern?: RegExp;
33
+ /**
34
+ * Whether to attempt auto-fetching `/.env` or `/.env.example` file in dev mode.
35
+ * Defaults to true.
36
+ */
37
+ autoFetchEnvFile?: boolean;
38
+ /**
39
+ * Whether to implicitly intercept fetch and XHR requests and rewrite default base URLs
40
+ * to overridden active environment URLs automatically.
41
+ * Defaults to true.
42
+ */
43
+ interceptNetworkRequests?: boolean;
44
+ }
45
+ type EnvChangeListener = (key: string, value: string, isOverridden: boolean) => void;
46
+ type StoreChangeListener = (variables: Record<string, EnvVariable>, presets: PresetProfile[], activePresetId: string | null) => void;
47
+
48
+ /**
49
+ * Parses raw .env string into a key-value Record.
50
+ */
51
+ declare function parseEnvString(rawText: string): Record<string, string>;
52
+ /**
53
+ * Stringifies a Record<string, string> into standard .env format.
54
+ */
55
+ declare function stringifyEnv(env: Record<string, string>): string;
56
+
57
+ declare class LambaManager {
58
+ private store;
59
+ private launcher;
60
+ private modal;
61
+ private networkInterceptor;
62
+ private options;
63
+ private isInitialized;
64
+ /**
65
+ * Implicit ES Proxy object where properties like `lamba.env.VITE_API_BASE_URL`
66
+ * return the live active overridden value automatically.
67
+ */
68
+ env: Record<string, string>;
69
+ constructor();
70
+ /**
71
+ * Wraps any environment object (such as `import.meta.env` or `process.env`)
72
+ * in a dynamic proxy that implicitly resolves live overrides from lamba.
73
+ */
74
+ wrap<T extends object>(targetEnv: T): T;
75
+ /**
76
+ * Initializes lamba with custom options and mounts the floating UI.
77
+ */
78
+ init(options?: LambaOptions): this;
79
+ /**
80
+ * Gets the active value of an environment variable (returns overridden value if active, otherwise default).
81
+ */
82
+ get(key: string, fallback?: string): string;
83
+ /**
84
+ * Overrides an environment variable live at runtime.
85
+ */
86
+ set(key: string, value: string): void;
87
+ /**
88
+ * Removes an override for a specific environment variable key.
89
+ */
90
+ remove(key: string): void;
91
+ /**
92
+ * Resets all environment variable overrides.
93
+ */
94
+ reset(): void;
95
+ /**
96
+ * Subscribes to environment variable changes.
97
+ */
98
+ onChange(listener: EnvChangeListener): () => void;
99
+ /**
100
+ * Programmatically opens the lamba floating modal.
101
+ */
102
+ open(): void;
103
+ /**
104
+ * Programmatically closes the lamba floating modal.
105
+ */
106
+ close(): void;
107
+ /**
108
+ * Programmatically toggles the lamba floating modal.
109
+ */
110
+ toggle(): void;
111
+ }
112
+ declare const lamba: LambaManager;
113
+
114
+ export { type EnvChangeListener, type EnvVariable, LambaManager, type LambaOptions, type PresetProfile, type StoreChangeListener, lamba as default, lamba, parseEnvString, stringifyEnv };
@@ -0,0 +1,114 @@
1
+ interface EnvVariable {
2
+ key: string;
3
+ value: string;
4
+ defaultValue: string;
5
+ isOverridden: boolean;
6
+ isSecret?: boolean;
7
+ }
8
+ interface PresetProfile {
9
+ id: string;
10
+ name: string;
11
+ overrides: Record<string, string>;
12
+ createdAt: number;
13
+ }
14
+ interface LambaOptions {
15
+ /**
16
+ * Initial environment variable key-values to supply to lamba.
17
+ */
18
+ env?: Record<string, string>;
19
+ /**
20
+ * Whether lamba floating UI is enabled. Defaults to true in non-production or when specified.
21
+ */
22
+ enabled?: boolean;
23
+ /**
24
+ * Position of the floating launcher button.
25
+ * Options: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'
26
+ * Defaults to 'bottom-right'
27
+ */
28
+ position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
29
+ /**
30
+ * Secret keys regex pattern to automatically mask in the UI (e.g. API_KEY, SECRET, TOKEN, PASSWORD).
31
+ */
32
+ secretKeysPattern?: RegExp;
33
+ /**
34
+ * Whether to attempt auto-fetching `/.env` or `/.env.example` file in dev mode.
35
+ * Defaults to true.
36
+ */
37
+ autoFetchEnvFile?: boolean;
38
+ /**
39
+ * Whether to implicitly intercept fetch and XHR requests and rewrite default base URLs
40
+ * to overridden active environment URLs automatically.
41
+ * Defaults to true.
42
+ */
43
+ interceptNetworkRequests?: boolean;
44
+ }
45
+ type EnvChangeListener = (key: string, value: string, isOverridden: boolean) => void;
46
+ type StoreChangeListener = (variables: Record<string, EnvVariable>, presets: PresetProfile[], activePresetId: string | null) => void;
47
+
48
+ /**
49
+ * Parses raw .env string into a key-value Record.
50
+ */
51
+ declare function parseEnvString(rawText: string): Record<string, string>;
52
+ /**
53
+ * Stringifies a Record<string, string> into standard .env format.
54
+ */
55
+ declare function stringifyEnv(env: Record<string, string>): string;
56
+
57
+ declare class LambaManager {
58
+ private store;
59
+ private launcher;
60
+ private modal;
61
+ private networkInterceptor;
62
+ private options;
63
+ private isInitialized;
64
+ /**
65
+ * Implicit ES Proxy object where properties like `lamba.env.VITE_API_BASE_URL`
66
+ * return the live active overridden value automatically.
67
+ */
68
+ env: Record<string, string>;
69
+ constructor();
70
+ /**
71
+ * Wraps any environment object (such as `import.meta.env` or `process.env`)
72
+ * in a dynamic proxy that implicitly resolves live overrides from lamba.
73
+ */
74
+ wrap<T extends object>(targetEnv: T): T;
75
+ /**
76
+ * Initializes lamba with custom options and mounts the floating UI.
77
+ */
78
+ init(options?: LambaOptions): this;
79
+ /**
80
+ * Gets the active value of an environment variable (returns overridden value if active, otherwise default).
81
+ */
82
+ get(key: string, fallback?: string): string;
83
+ /**
84
+ * Overrides an environment variable live at runtime.
85
+ */
86
+ set(key: string, value: string): void;
87
+ /**
88
+ * Removes an override for a specific environment variable key.
89
+ */
90
+ remove(key: string): void;
91
+ /**
92
+ * Resets all environment variable overrides.
93
+ */
94
+ reset(): void;
95
+ /**
96
+ * Subscribes to environment variable changes.
97
+ */
98
+ onChange(listener: EnvChangeListener): () => void;
99
+ /**
100
+ * Programmatically opens the lamba floating modal.
101
+ */
102
+ open(): void;
103
+ /**
104
+ * Programmatically closes the lamba floating modal.
105
+ */
106
+ close(): void;
107
+ /**
108
+ * Programmatically toggles the lamba floating modal.
109
+ */
110
+ toggle(): void;
111
+ }
112
+ declare const lamba: LambaManager;
113
+
114
+ export { type EnvChangeListener, type EnvVariable, LambaManager, type LambaOptions, type PresetProfile, type StoreChangeListener, lamba as default, lamba, parseEnvString, stringifyEnv };