@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.
@@ -0,0 +1,560 @@
1
+ "use strict";var lamba=(()=>{var O=Object.defineProperty;var _=Object.getOwnPropertyDescriptor;var B=Object.getOwnPropertyNames;var q=Object.prototype.hasOwnProperty;var j=(s,e)=>{for(var r in e)O(s,r,{get:e[r],enumerable:!0})},F=(s,e,r,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of B(e))!q.call(s,a)&&a!==r&&O(s,a,{get:()=>e[a],enumerable:!(t=_(e,a))||t.enumerable});return s};var U=s=>F(O({},"__esModule",{value:!0}),s);var D={};j(D,{LambaManager:()=>S,default:()=>z,lamba:()=>L,parseEnvString:()=>u,stringifyEnv:()=>f});var R="__lamba_presets__",P="__lamba_active_preset__",g=class{constructor(){this.presets=[];this.activePresetId=null;this.loadFromStorage()}loadFromStorage(){if(!(typeof localStorage>"u"))try{let e=localStorage.getItem(R);e&&(this.presets=JSON.parse(e)),this.activePresetId=localStorage.getItem(P)}catch(e){console.warn("[lamba] Failed to parse presets from localStorage",e)}}saveToStorage(){if(!(typeof localStorage>"u"))try{localStorage.setItem(R,JSON.stringify(this.presets)),this.activePresetId?localStorage.setItem(P,this.activePresetId):localStorage.removeItem(P)}catch(e){console.warn("[lamba] Failed to save presets to localStorage",e)}}getPresets(){return[...this.presets]}getActivePresetId(){return this.activePresetId}createPreset(e,r){let t={id:"preset_"+Math.random().toString(36).substring(2,9),name:e.trim()||"Untitled Preset",overrides:{...r},createdAt:Date.now()};return this.presets.push(t),this.saveToStorage(),t}deletePreset(e){this.presets=this.presets.filter(r=>r.id!==e),this.activePresetId===e&&(this.activePresetId=null),this.saveToStorage()}setActivePreset(e){if(!e)return this.activePresetId=null,this.saveToStorage(),null;let r=this.presets.find(t=>t.id===e);return r?(this.activePresetId=e,this.saveToStorage(),r):null}};function u(s){let e={},r=s.split(`
2
+ `);for(let t of r){if(t=t.trim(),!t||t.startsWith("#"))continue;t.startsWith("export ")&&(t=t.slice(7).trim());let a=t.indexOf("=");if(a===-1)continue;let i=t.slice(0,a).trim(),n=t.slice(a+1).trim();(n.startsWith('"')&&n.endsWith('"')||n.startsWith("'")&&n.endsWith("'"))&&(n=n.slice(1,-1)),n=n.replace(/\\n/g,`
3
+ `),i&&(e[i]=n)}return e}function f(s){return Object.entries(s).map(([e,r])=>{let a=r.includes(" ")||r.includes(`
4
+ `)||r.includes("#")?`"${r.replace(/"/g,'\\"')}"`:r;return`${e}=${a}`}).join(`
5
+ `)}function M(){let s={};if(typeof window>"u")return s;try{let e=window.process;if(e&&e.env&&typeof e.env=="object")for(let[r,t]of Object.entries(e.env))(typeof t=="string"||typeof t=="number"||typeof t=="boolean")&&(s[r]=String(t))}catch{}try{let e=window.__ENV__||window.ENV;if(e&&typeof e=="object")for(let[r,t]of Object.entries(e))(typeof t=="string"||typeof t=="number"||typeof t=="boolean")&&(s[r]=String(t))}catch{}try{document.querySelectorAll("meta").forEach(r=>{let t=r.getAttribute("name"),a=r.getAttribute("content");if(!(!t||a===null))if(t.startsWith("env:")){let i=t.slice(4);s[i]=a}else t==="lamba-env"&&new URLSearchParams(a).forEach((n,l)=>{s[l]=n})})}catch{}return s}async function T(){let s=["/.env","/.env.local","/.env.example"];for(let e of s)try{let r=await fetch(e,{headers:{Accept:"text/plain"}});if(r.ok){let t=await r.text();if(t&&t.includes("="))return u(t)}}catch{}return{}}var H="__lamba_overrides__",N=/(KEY|SECRET|TOKEN|PASSWORD|AUTH|PRIVATE|CREDENTIAL|SIGNATURE)/i,x=class{constructor(e={}){this.variables=new Map;this.overrides={};this.envChangeListeners=new Set;this.storeChangeListeners=new Set;this.secretPattern=e.secretKeysPattern||N,this.presetManager=new g,this.loadOverridesFromStorage(),e.env&&this.mergeDefaults(e.env);let r=M();this.mergeDefaults(r),e.autoFetchEnvFile===!0&&typeof window<"u"&&T().then(t=>{Object.keys(t).length>0&&this.mergeDefaults(t)}),this.patchProcessEnv()}loadOverridesFromStorage(){if(!(typeof localStorage>"u"))try{let e=localStorage.getItem(H);e&&(this.overrides=JSON.parse(e))}catch(e){console.warn("[lamba] Failed to parse overrides from localStorage",e)}}saveOverridesToStorage(){if(!(typeof localStorage>"u"))try{localStorage.setItem(H,JSON.stringify(this.overrides))}catch(e){console.warn("[lamba] Failed to save overrides to localStorage",e)}}patchProcessEnv(){if(typeof window>"u")return;let e=window;e.process?e.process.env||(e.process.env={}):e.process={env:{}};let r=this,t=e.process.env;try{e.process.env=new Proxy(t,{get(a,i){if(typeof i=="string"){let n=r.get(i);if(n!==void 0)return n}return a[i]},set(a,i,n){return a[i]=n,!0}})}catch{}}mergeDefaults(e){let r=!1;for(let[t,a]of Object.entries(e)){let i=t in this.overrides,n=i?this.overrides[t]:a,l=this.secretPattern.test(t),c=this.variables.get(t);c?c.defaultValue!==a&&(c.defaultValue=a,c.isOverridden||(c.value=a),r=!0):(this.variables.set(t,{key:t,value:n,defaultValue:a,isOverridden:i,isSecret:l}),r=!0)}r&&this.notifyStoreChanged()}get(e,r){if(e in this.overrides)return this.overrides[e];let t=this.variables.get(e);return t?t.value:r}getAll(){let e={};return this.variables.forEach((r,t)=>{e[t]={...r}}),e}getOverrides(){return{...this.overrides}}setOverride(e,r){let t=e.trim();if(!t)return;this.overrides[t]=r,this.saveOverridesToStorage();let a=this.variables.get(t);a?(a.value=r,a.isOverridden=!0):(a={key:t,value:r,defaultValue:"",isOverridden:!0,isSecret:this.secretPattern.test(t)},this.variables.set(t,a)),this.emitEnvChange(t,r,!0),this.notifyStoreChanged()}removeOverride(e){if(e in this.overrides){delete this.overrides[e],this.saveOverridesToStorage();let r=this.variables.get(e);r&&(r.value=r.defaultValue,r.isOverridden=!1,this.emitEnvChange(e,r.value,!1)),this.notifyStoreChanged()}}resetAllOverrides(){let e=Object.keys(this.overrides);this.overrides={},this.saveOverridesToStorage(),this.presetManager.setActivePreset(null),e.forEach(r=>{let t=this.variables.get(r);t&&(t.value=t.defaultValue,t.isOverridden=!1,this.emitEnvChange(r,t.value,!1))}),this.notifyStoreChanged()}applyPreset(e){let r=this.presetManager.setActivePreset(e);if(this.overrides=r?{...r.overrides}:{},this.saveOverridesToStorage(),this.variables.forEach((t,a)=>{a in this.overrides?(t.value=this.overrides[a],t.isOverridden=!0):(t.value=t.defaultValue,t.isOverridden=!1),this.emitEnvChange(a,t.value,t.isOverridden)}),r)for(let[t,a]of Object.entries(r.overrides))this.variables.has(t)||(this.variables.set(t,{key:t,value:a,defaultValue:"",isOverridden:!0,isSecret:this.secretPattern.test(t)}),this.emitEnvChange(t,a,!0));this.notifyStoreChanged()}subscribeEnvChange(e){return this.envChangeListeners.add(e),()=>this.envChangeListeners.delete(e)}subscribeStoreChange(e){return this.storeChangeListeners.add(e),()=>this.storeChangeListeners.delete(e)}emitEnvChange(e,r,t){this.envChangeListeners.forEach(a=>a(e,r,t)),typeof window<"u"&&window.dispatchEvent(new CustomEvent("lamba:env-change",{detail:{key:e,value:r,isOverridden:t}}))}notifyStoreChanged(){let e=this.getAll(),r=this.presetManager.getPresets(),t=this.presetManager.getActivePresetId();this.storeChangeListeners.forEach(a=>a(e,r,t))}};var y=class{constructor(e){this.originalFetch=null;this.originalXHRPost=null;this.isIntercepting=!1;this.store=e}enable(){typeof window>"u"||this.isIntercepting||(this.patchFetch(),this.patchXHR(),this.isIntercepting=!0)}disable(){typeof window>"u"||!this.isIntercepting||(this.originalFetch&&(window.fetch=this.originalFetch,this.originalFetch=null),this.originalXHRPost&&(XMLHttpRequest.prototype.open=this.originalXHRPost,this.originalXHRPost=null),this.isIntercepting=!1)}rewriteUrl(e){if(typeof e!="string")return e;let r=this.store.getAll(),t=e;for(let a of Object.values(r))if(a.isOverridden&&a.defaultValue&&a.value){let i=a.defaultValue.replace(/\/+$/,""),n=a.value.replace(/\/+$/,"");i&&t.includes(i)&&(t=t.replace(i,n))}return t}patchFetch(){if(!window.fetch)return;this.originalFetch=window.fetch;let e=this;window.fetch=function(r,t){let a=r;if(typeof r=="string")a=e.rewriteUrl(r);else if(r instanceof URL){let i=e.rewriteUrl(r.toString());a=new URL(i)}else if(r instanceof Request){let i=e.rewriteUrl(r.url);i!==r.url&&(a=new Request(i,r))}return e.originalFetch.call(this,a,t)}}patchXHR(){if(!window.XMLHttpRequest)return;this.originalXHRPost=XMLHttpRequest.prototype.open;let e=this;XMLHttpRequest.prototype.open=function(r,t,a=!0,i,n){let l=typeof t=="string"?t:t.toString(),c=e.rewriteUrl(l);return e.originalXHRPost.call(this,r,c,a,i??null,n??null)}}};var A=`
6
+ :host {
7
+ --lamba-bg-main: #0f172a;
8
+ --lamba-bg-card: #1e293b;
9
+ --lamba-bg-hover: #334155;
10
+ --lamba-border: rgba(255, 255, 255, 0.1);
11
+ --lamba-text-primary: #f8fafc;
12
+ --lamba-text-secondary: #94a3b8;
13
+ --lamba-primary: #6366f1;
14
+ --lamba-primary-hover: #4f46e5;
15
+ --lamba-accent: #06b6d4;
16
+ --lamba-success: #10b981;
17
+ --lamba-danger: #ef4444;
18
+ --lamba-warning: #f59e0b;
19
+ --lamba-font: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
20
+ --lamba-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.5), 0 8px 10px -6px rgba(0, 0, 0, 0.4);
21
+
22
+ font-family: var(--lamba-font);
23
+ font-size: 14px;
24
+ line-height: 1.5;
25
+ color: var(--lamba-text-primary);
26
+ box-sizing: border-box;
27
+ z-index: 999999;
28
+ }
29
+
30
+ *, *:before, *:after {
31
+ box-sizing: border-box;
32
+ }
33
+
34
+ /* Floating Launcher Button */
35
+ .lamba-launcher {
36
+ position: fixed;
37
+ z-index: 999999;
38
+ width: 52px;
39
+ height: 52px;
40
+ border-radius: 50%;
41
+ background: linear-gradient(135deg, #6366f1 0%, #4f46e5 100%);
42
+ color: #ffffff;
43
+ display: flex;
44
+ align-items: center;
45
+ justify-content: center;
46
+ cursor: pointer;
47
+ box-shadow: 0 10px 15px -3px rgba(99, 102, 241, 0.4), 0 4px 6px -4px rgba(99, 102, 241, 0.2);
48
+ border: 1px solid rgba(255, 255, 255, 0.2);
49
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
50
+ user-select: none;
51
+ }
52
+
53
+ .lamba-launcher:hover {
54
+ transform: scale(1.08);
55
+ box-shadow: 0 14px 20px -3px rgba(99, 102, 241, 0.6), 0 6px 8px -4px rgba(99, 102, 241, 0.3);
56
+ }
57
+
58
+ .lamba-launcher:active {
59
+ transform: scale(0.95);
60
+ }
61
+
62
+ .lamba-launcher-bottom-right { bottom: 24px; right: 24px; }
63
+ .lamba-launcher-bottom-left { bottom: 24px; left: 24px; }
64
+ .lamba-launcher-top-right { top: 24px; right: 24px; }
65
+ .lamba-launcher-top-left { top: 24px; left: 24px; }
66
+
67
+ .lamba-badge {
68
+ position: absolute;
69
+ top: -4px;
70
+ right: -4px;
71
+ background: var(--lamba-accent);
72
+ color: #000;
73
+ font-size: 11px;
74
+ font-weight: 700;
75
+ min-width: 20px;
76
+ height: 20px;
77
+ border-radius: 10px;
78
+ display: flex;
79
+ align-items: center;
80
+ justify-content: center;
81
+ padding: 0 5px;
82
+ border: 2px solid var(--lamba-bg-main);
83
+ box-shadow: 0 2px 4px rgba(0,0,0,0.2);
84
+ animation: pulse-scale 2s infinite;
85
+ }
86
+
87
+ @keyframes pulse-scale {
88
+ 0%, 100% { transform: scale(1); }
89
+ 50% { transform: scale(1.15); }
90
+ }
91
+
92
+ /* Modal Overlay */
93
+ .lamba-overlay {
94
+ position: fixed;
95
+ top: 0;
96
+ left: 0;
97
+ width: 100vw;
98
+ height: 100vh;
99
+ background: rgba(15, 23, 42, 0.7);
100
+ backdrop-filter: blur(8px);
101
+ z-index: 999998;
102
+ opacity: 0;
103
+ visibility: hidden;
104
+ transition: opacity 0.25s ease, visibility 0.25s ease;
105
+ display: flex;
106
+ align-items: center;
107
+ justify-content: center;
108
+ padding: 20px;
109
+ }
110
+
111
+ .lamba-overlay.active {
112
+ opacity: 1;
113
+ visibility: visible;
114
+ }
115
+
116
+ /* Main Modal Panel */
117
+ .lamba-modal {
118
+ width: 100%;
119
+ max-width: 820px;
120
+ max-height: 85vh;
121
+ background: var(--lamba-bg-main);
122
+ border: 1px solid var(--lamba-border);
123
+ border-radius: 16px;
124
+ box-shadow: var(--lamba-shadow);
125
+ display: flex;
126
+ flex-direction: column;
127
+ overflow: hidden;
128
+ transform: translateY(20px) scale(0.96);
129
+ transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);
130
+ }
131
+
132
+ .lamba-overlay.active .lamba-modal {
133
+ transform: translateY(0) scale(1);
134
+ }
135
+
136
+ /* Header */
137
+ .lamba-header {
138
+ padding: 20px 24px;
139
+ border-bottom: 1px solid var(--lamba-border);
140
+ display: flex;
141
+ align-items: center;
142
+ justify-content: space-between;
143
+ background: rgba(30, 41, 59, 0.4);
144
+ }
145
+
146
+ .lamba-brand {
147
+ display: flex;
148
+ align-items: center;
149
+ gap: 12px;
150
+ }
151
+
152
+ .lamba-logo {
153
+ font-size: 18px;
154
+ font-weight: 800;
155
+ letter-spacing: -0.5px;
156
+ background: linear-gradient(135deg, #a5b4fc 0%, #6366f1 100%);
157
+ -webkit-background-clip: text;
158
+ -webkit-text-fill-color: transparent;
159
+ display: flex;
160
+ align-items: center;
161
+ gap: 8px;
162
+ }
163
+
164
+ .lamba-tag {
165
+ background: rgba(99, 102, 241, 0.15);
166
+ color: #a5b4fc;
167
+ font-size: 11px;
168
+ padding: 2px 8px;
169
+ border-radius: 6px;
170
+ font-weight: 600;
171
+ border: 1px solid rgba(99, 102, 241, 0.3);
172
+ }
173
+
174
+ .lamba-close-btn {
175
+ background: transparent;
176
+ border: none;
177
+ color: var(--lamba-text-secondary);
178
+ cursor: pointer;
179
+ padding: 6px;
180
+ border-radius: 8px;
181
+ display: flex;
182
+ align-items: center;
183
+ justify-content: center;
184
+ transition: background 0.15s ease, color 0.15s ease;
185
+ }
186
+
187
+ .lamba-close-btn:hover {
188
+ background: var(--lamba-bg-hover);
189
+ color: var(--lamba-text-primary);
190
+ }
191
+
192
+ /* Controls Bar (Search & Filters) */
193
+ .lamba-controls {
194
+ padding: 16px 24px;
195
+ border-bottom: 1px solid var(--lamba-border);
196
+ display: flex;
197
+ gap: 12px;
198
+ align-items: center;
199
+ flex-wrap: wrap;
200
+ background: var(--lamba-bg-main);
201
+ }
202
+
203
+ .lamba-search-box {
204
+ flex: 1;
205
+ min-width: 220px;
206
+ position: relative;
207
+ }
208
+
209
+ .lamba-search-input {
210
+ width: 100%;
211
+ padding: 10px 14px 10px 38px;
212
+ background: var(--lamba-bg-card);
213
+ border: 1px solid var(--lamba-border);
214
+ border-radius: 8px;
215
+ color: var(--lamba-text-primary);
216
+ font-size: 13px;
217
+ outline: none;
218
+ transition: border-color 0.15s ease;
219
+ }
220
+
221
+ .lamba-search-input:focus {
222
+ border-color: var(--lamba-primary);
223
+ }
224
+
225
+ .lamba-search-icon {
226
+ position: absolute;
227
+ left: 12px;
228
+ top: 50%;
229
+ transform: translateY(-50%);
230
+ color: var(--lamba-text-secondary);
231
+ pointer-events: none;
232
+ }
233
+
234
+ .lamba-tabs {
235
+ display: flex;
236
+ gap: 4px;
237
+ background: var(--lamba-bg-card);
238
+ padding: 4px;
239
+ border-radius: 8px;
240
+ border: 1px solid var(--lamba-border);
241
+ }
242
+
243
+ .lamba-tab {
244
+ background: transparent;
245
+ border: none;
246
+ color: var(--lamba-text-secondary);
247
+ padding: 6px 12px;
248
+ border-radius: 6px;
249
+ font-size: 12px;
250
+ font-weight: 600;
251
+ cursor: pointer;
252
+ transition: all 0.15s ease;
253
+ }
254
+
255
+ .lamba-tab.active {
256
+ background: var(--lamba-primary);
257
+ color: #ffffff;
258
+ }
259
+
260
+ /* Preset Bar */
261
+ .lamba-presets-bar {
262
+ padding: 12px 24px;
263
+ background: rgba(30, 41, 59, 0.3);
264
+ border-bottom: 1px solid var(--lamba-border);
265
+ display: flex;
266
+ align-items: center;
267
+ justify-content: space-between;
268
+ gap: 12px;
269
+ }
270
+
271
+ .lamba-preset-selector {
272
+ display: flex;
273
+ align-items: center;
274
+ gap: 8px;
275
+ font-size: 13px;
276
+ }
277
+
278
+ .lamba-select {
279
+ background: var(--lamba-bg-card);
280
+ color: var(--lamba-text-primary);
281
+ border: 1px solid var(--lamba-border);
282
+ padding: 6px 12px;
283
+ border-radius: 6px;
284
+ outline: none;
285
+ font-size: 13px;
286
+ cursor: pointer;
287
+ }
288
+
289
+ /* List Content */
290
+ .lamba-content {
291
+ flex: 1;
292
+ overflow-y: auto;
293
+ padding: 16px 24px;
294
+ display: flex;
295
+ flex-direction: column;
296
+ gap: 12px;
297
+ }
298
+
299
+ .lamba-content::-webkit-scrollbar {
300
+ width: 6px;
301
+ }
302
+
303
+ .lamba-content::-webkit-scrollbar-track {
304
+ background: transparent;
305
+ }
306
+
307
+ .lamba-content::-webkit-scrollbar-thumb {
308
+ background: var(--lamba-bg-hover);
309
+ border-radius: 3px;
310
+ }
311
+
312
+ /* Variable Row Card */
313
+ .lamba-var-card {
314
+ background: var(--lamba-bg-card);
315
+ border: 1px solid var(--lamba-border);
316
+ border-radius: 10px;
317
+ padding: 14px 16px;
318
+ display: flex;
319
+ flex-direction: column;
320
+ gap: 8px;
321
+ transition: border-color 0.15s ease;
322
+ }
323
+
324
+ .lamba-var-card.is-overridden {
325
+ border-color: rgba(99, 102, 241, 0.5);
326
+ background: linear-gradient(180deg, var(--lamba-bg-card) 0%, rgba(99, 102, 241, 0.05) 100%);
327
+ }
328
+
329
+ .lamba-var-meta {
330
+ display: flex;
331
+ align-items: center;
332
+ justify-content: space-between;
333
+ }
334
+
335
+ .lamba-var-key {
336
+ font-weight: 700;
337
+ font-family: monospace;
338
+ color: #a5b4fc;
339
+ font-size: 13px;
340
+ display: flex;
341
+ align-items: center;
342
+ gap: 8px;
343
+ }
344
+
345
+ .lamba-modified-pill {
346
+ font-size: 10px;
347
+ font-weight: 700;
348
+ background: rgba(16, 185, 129, 0.2);
349
+ color: #34d399;
350
+ padding: 2px 6px;
351
+ border-radius: 4px;
352
+ border: 1px solid rgba(16, 185, 129, 0.4);
353
+ }
354
+
355
+ .lamba-var-actions {
356
+ display: flex;
357
+ align-items: center;
358
+ gap: 6px;
359
+ }
360
+
361
+ .lamba-icon-btn {
362
+ background: transparent;
363
+ border: none;
364
+ color: var(--lamba-text-secondary);
365
+ cursor: pointer;
366
+ padding: 4px;
367
+ border-radius: 4px;
368
+ display: flex;
369
+ align-items: center;
370
+ justify-content: center;
371
+ transition: background 0.15s ease, color 0.15s ease;
372
+ }
373
+
374
+ .lamba-icon-btn:hover {
375
+ background: var(--lamba-bg-hover);
376
+ color: var(--lamba-text-primary);
377
+ }
378
+
379
+ .lamba-var-input-group {
380
+ display: flex;
381
+ gap: 8px;
382
+ }
383
+
384
+ .lamba-input {
385
+ flex: 1;
386
+ background: var(--lamba-bg-main);
387
+ border: 1px solid var(--lamba-border);
388
+ color: var(--lamba-text-primary);
389
+ padding: 8px 12px;
390
+ border-radius: 6px;
391
+ font-family: monospace;
392
+ font-size: 13px;
393
+ outline: none;
394
+ }
395
+
396
+ .lamba-input:focus {
397
+ border-color: var(--lamba-primary);
398
+ }
399
+
400
+ .lamba-diff {
401
+ font-size: 11px;
402
+ color: var(--lamba-text-secondary);
403
+ font-family: monospace;
404
+ padding-left: 2px;
405
+ }
406
+
407
+ .lamba-diff-val {
408
+ color: var(--lamba-warning);
409
+ }
410
+
411
+ /* Empty State */
412
+ .lamba-empty {
413
+ padding: 40px 20px;
414
+ text-align: center;
415
+ color: var(--lamba-text-secondary);
416
+ }
417
+
418
+ /* Footer Actions Bar */
419
+ .lamba-footer {
420
+ padding: 16px 24px;
421
+ border-top: 1px solid var(--lamba-border);
422
+ background: rgba(30, 41, 59, 0.4);
423
+ display: flex;
424
+ align-items: center;
425
+ justify-content: space-between;
426
+ gap: 12px;
427
+ flex-wrap: wrap;
428
+ }
429
+
430
+ .lamba-btn {
431
+ background: var(--lamba-bg-card);
432
+ color: var(--lamba-text-primary);
433
+ border: 1px solid var(--lamba-border);
434
+ padding: 8px 14px;
435
+ border-radius: 8px;
436
+ font-size: 12px;
437
+ font-weight: 600;
438
+ cursor: pointer;
439
+ display: flex;
440
+ align-items: center;
441
+ gap: 6px;
442
+ transition: all 0.15s ease;
443
+ }
444
+
445
+ .lamba-btn:hover {
446
+ background: var(--lamba-bg-hover);
447
+ }
448
+
449
+ .lamba-btn-primary {
450
+ background: var(--lamba-primary);
451
+ border-color: var(--lamba-primary);
452
+ color: #ffffff;
453
+ }
454
+
455
+ .lamba-btn-primary:hover {
456
+ background: var(--lamba-primary-hover);
457
+ }
458
+
459
+ .lamba-btn-danger {
460
+ background: rgba(239, 68, 68, 0.15);
461
+ color: #fca5a5;
462
+ border-color: rgba(239, 68, 68, 0.3);
463
+ }
464
+
465
+ .lamba-btn-danger:hover {
466
+ background: rgba(239, 68, 68, 0.3);
467
+ }
468
+ `;function I(){if(typeof document>"u")throw new Error("[lamba] Document object not available.");let s=document.getElementById("lamba-root");s||(s=document.createElement("lamba-widget"),s.id="lamba-root",document.body.appendChild(s));let e=s.shadowRoot;if(!e){e=s.attachShadow({mode:"open"});let r=document.createElement("style");r.textContent=A,e.appendChild(r)}return{host:s,shadowRoot:e}}var w=class{constructor(e,r="bottom-right",t){this.onClickCallback=t,this.element=document.createElement("div"),this.element.className=`lamba-launcher lamba-launcher-${r}`,this.element.title="Open lamba Environment Controls",this.element.innerHTML=`
469
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
470
+ <path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/>
471
+ <circle cx="12" cy="12" r="3"/>
472
+ </svg>
473
+ `,this.badgeElement=document.createElement("div"),this.badgeElement.className="lamba-badge",this.badgeElement.style.display="none",this.element.appendChild(this.badgeElement),this.element.addEventListener("click",()=>this.onClickCallback()),e.appendChild(this.element)}updateBadgeCount(e){e>0?(this.badgeElement.textContent=String(e),this.badgeElement.style.display="flex"):this.badgeElement.style.display="none"}setVisible(e){this.element.style.display=e?"flex":"none"}};var E=class{constructor(e,r,t){this.activeTab="all";this.searchQuery="";this.secretVisibilityMap=new Map;this.isOpen=!1;this.store=r,this.overlay=document.createElement("div"),this.overlay.className="lamba-overlay",this.modal=document.createElement("div"),this.modal.className="lamba-modal";let a=document.createElement("div");a.className="lamba-header",a.innerHTML=`
474
+ <div class="lamba-brand">
475
+ <div class="lamba-logo">
476
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
477
+ <path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"/>
478
+ </svg>
479
+ lamba
480
+ </div>
481
+ <span class="lamba-tag">Dev Environment Override</span>
482
+ </div>
483
+ <button class="lamba-close-btn" title="Close modal">
484
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
485
+ <line x1="18" y1="6" x2="6" y2="18"></line>
486
+ <line x1="6" y1="6" x2="18" y2="18"></line>
487
+ </svg>
488
+ </button>
489
+ `,a.querySelector(".lamba-close-btn")?.addEventListener("click",()=>{this.close(),t()});let i=document.createElement("div");i.className="lamba-controls";let n=document.createElement("div");n.className="lamba-search-box",n.innerHTML=`
490
+ <svg class="lamba-search-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
491
+ <circle cx="11" cy="11" r="8"></circle>
492
+ <line x1="21" y1="21" x2="16.65" y2="16.65"></line>
493
+ </svg>
494
+ <input type="text" class="lamba-search-input" placeholder="Search environment keys or values..." />
495
+ `,this.searchInput=n.querySelector(".lamba-search-input"),this.searchInput.addEventListener("input",o=>{this.searchQuery=o.target.value.toLowerCase(),this.render()});let l=document.createElement("div");l.className="lamba-tabs",l.innerHTML=`
496
+ <button class="lamba-tab active" data-tab="all">All</button>
497
+ <button class="lamba-tab" data-tab="overridden">Modified</button>
498
+ <button class="lamba-tab" data-tab="secrets">Secrets</button>
499
+ `,this.tabAllBtn=l.querySelector('[data-tab="all"]'),this.tabOverriddenBtn=l.querySelector('[data-tab="overridden"]'),this.tabSecretsBtn=l.querySelector('[data-tab="secrets"]'),l.querySelectorAll(".lamba-tab").forEach(o=>{o.addEventListener("click",d=>{l.querySelectorAll(".lamba-tab").forEach(h=>h.classList.remove("active"));let b=d.currentTarget;b.classList.add("active"),this.activeTab=b.getAttribute("data-tab"),this.render()})}),i.appendChild(n),i.appendChild(l);let c=document.createElement("div");c.className="lamba-presets-bar",c.innerHTML=`
500
+ <div class="lamba-preset-selector">
501
+ <span style="color: var(--lamba-text-secondary); font-weight: 600;">Preset Profile:</span>
502
+ <select class="lamba-select lamba-preset-dropdown">
503
+ <option value="">Default (Current Overrides)</option>
504
+ </select>
505
+ </div>
506
+ <button class="lamba-btn lamba-save-preset-btn">
507
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
508
+ <path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path>
509
+ <polyline points="17 21 17 13 7 13 7 21"></polyline>
510
+ <polyline points="7 3 7 8 15 8"></polyline>
511
+ </svg>
512
+ Save as Preset
513
+ </button>
514
+ `,this.presetSelect=c.querySelector(".lamba-preset-dropdown"),this.presetSelect.addEventListener("change",()=>{let o=this.presetSelect.value||null;this.store.applyPreset(o)}),this.savePresetBtn=c.querySelector(".lamba-save-preset-btn"),this.savePresetBtn.addEventListener("click",()=>{let o=prompt("Enter a name for this Environment Preset Profile:","Staging Environment");if(o){let d=this.store.getOverrides();this.store.presetManager.createPreset(o,d),this.updatePresetDropdown()}}),this.contentList=document.createElement("div"),this.contentList.className="lamba-content";let p=document.createElement("div");p.className="lamba-footer",p.innerHTML=`
515
+ <div style="display: flex; gap: 8px;">
516
+ <button class="lamba-btn lamba-add-var-btn">
517
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
518
+ <line x1="12" y1="5" x2="12" y2="19"></line>
519
+ <line x1="5" y1="12" x2="19" y2="12"></line>
520
+ </svg>
521
+ Add Variable
522
+ </button>
523
+ <button class="lamba-btn lamba-import-btn">Import .env</button>
524
+ <button class="lamba-btn lamba-export-btn">Export .env</button>
525
+ </div>
526
+ <div style="display: flex; gap: 8px;">
527
+ <button class="lamba-btn lamba-btn-danger lamba-reset-all-btn">Reset All</button>
528
+ <button class="lamba-btn lamba-btn-primary lamba-reload-btn">Reload Page</button>
529
+ </div>
530
+ `,p.querySelector(".lamba-add-var-btn")?.addEventListener("click",()=>{let o=prompt("Enter new environment variable key name (e.g. VITE_API_URL):");if(o){let d=prompt(`Enter value for ${o}:`)||"";this.store.setOverride(o,d)}}),p.querySelector(".lamba-import-btn")?.addEventListener("click",()=>{let o=document.createElement("input");o.type="file",o.accept=".env,.txt",o.onchange=d=>{let b=d.target.files[0];if(b){let h=new FileReader;h.onload=m=>{let v=m.target?.result;if(v){let k=u(v);for(let[C,V]of Object.entries(k))this.store.setOverride(C,V)}},h.readAsText(b)}},o.click()}),p.querySelector(".lamba-export-btn")?.addEventListener("click",()=>{let o=this.store.getAll(),d={};for(let[k,C]of Object.entries(o))d[k]=C.value;let b=f(d),h=new Blob([b],{type:"text/plain"}),m=URL.createObjectURL(h),v=document.createElement("a");v.href=m,v.download=".env",v.click(),URL.revokeObjectURL(m)}),p.querySelector(".lamba-reset-all-btn")?.addEventListener("click",()=>{confirm("Are you sure you want to reset all overridden environment variables?")&&this.store.resetAllOverrides()}),p.querySelector(".lamba-reload-btn")?.addEventListener("click",()=>{window.location.reload()}),this.modal.appendChild(a),this.modal.appendChild(i),this.modal.appendChild(c),this.modal.appendChild(this.contentList),this.modal.appendChild(p),this.overlay.appendChild(this.modal),this.overlay.addEventListener("click",o=>{o.target===this.overlay&&(this.close(),t())}),e.appendChild(this.overlay),this.store.subscribeStoreChange(()=>{this.isOpen&&(this.updatePresetDropdown(),this.render())})}open(){this.isOpen=!0,this.updatePresetDropdown(),this.render(),this.overlay.classList.add("active")}close(){this.isOpen=!1,this.overlay.classList.remove("active")}toggle(){this.isOpen?this.close():this.open()}updatePresetDropdown(){let e=this.store.presetManager.getPresets(),r=this.store.presetManager.getActivePresetId();this.presetSelect.innerHTML='<option value="">Default (Custom Overrides)</option>',e.forEach(t=>{let a=document.createElement("option");a.value=t.id,a.textContent=t.name,t.id===r&&(a.selected=!0),this.presetSelect.appendChild(a)})}render(){let e=this.store.getAll(),r=Object.values(e);if(this.activeTab==="overridden"?r=r.filter(t=>t.isOverridden):this.activeTab==="secrets"&&(r=r.filter(t=>t.isSecret)),this.searchQuery&&(r=r.filter(t=>t.key.toLowerCase().includes(this.searchQuery)||t.value.toLowerCase().includes(this.searchQuery))),r.sort((t,a)=>t.isOverridden!==a.isOverridden?t.isOverridden?-1:1:t.key.localeCompare(a.key)),this.contentList.innerHTML="",r.length===0){let t=document.createElement("div");t.className="lamba-empty",t.textContent=this.searchQuery||this.activeTab!=="all"?"No environment variables match your current filter.":'No environment variables found or registered. Click "+ Add Variable" or "Import .env" to get started.',this.contentList.appendChild(t);return}r.forEach(t=>{let a=this.createVarCard(t);this.contentList.appendChild(a)})}createVarCard(e){let r=document.createElement("div");r.className=`lamba-var-card ${e.isOverridden?"is-overridden":""}`;let t=this.secretVisibilityMap.get(e.key)??!e.isSecret;r.innerHTML=`
531
+ <div class="lamba-var-meta">
532
+ <div class="lamba-var-key">
533
+ ${e.key}
534
+ ${e.isOverridden?'<span class="lamba-modified-pill">MODIFIED</span>':""}
535
+ ${e.isSecret?'<span style="font-size:10px; color:var(--lamba-warning); font-weight:600;">SECRET</span>':""}
536
+ </div>
537
+ <div class="lamba-var-actions">
538
+ ${e.isSecret?`<button class="lamba-icon-btn toggle-secret-btn" title="${t?"Hide secret":"Show secret"}">
539
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
540
+ ${t?'<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/>':'<path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/>'}
541
+ </svg>
542
+ </button>`:""}
543
+ ${e.isOverridden?`<button class="lamba-icon-btn reset-var-btn" title="Reset to default">
544
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
545
+ <path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/>
546
+ <path d="M3 3v5h5"/>
547
+ </svg>
548
+ </button>`:""}
549
+ </div>
550
+ </div>
551
+ <div class="lamba-var-input-group">
552
+ <input
553
+ type="${t?"text":"password"}"
554
+ class="lamba-input var-input"
555
+ value="${this.escapeHtml(e.value)}"
556
+ placeholder="Value..."
557
+ />
558
+ </div>
559
+ ${e.isOverridden&&e.defaultValue?`<div class="lamba-diff">Original default: <span class="lamba-diff-val">${this.escapeHtml(e.defaultValue)}</span></div>`:""}
560
+ `;let a=r.querySelector(".var-input");return a.addEventListener("change",()=>{this.store.setOverride(e.key,a.value)}),r.querySelector(".toggle-secret-btn")?.addEventListener("click",()=>{this.secretVisibilityMap.set(e.key,!t),this.render()}),r.querySelector(".reset-var-btn")?.addEventListener("click",()=>{this.store.removeOverride(e.key)}),r}escapeHtml(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}};var S=class{constructor(){this.store=null;this.launcher=null;this.modal=null;this.networkInterceptor=null;this.options={};this.isInitialized=!1;let e=this;this.env=new Proxy({},{get(r,t){if(typeof t=="string")return e.get(t)},set(r,t,a){return typeof t=="string"?(e.set(t,String(a)),!0):!1}})}wrap(e){let r=this;return new Proxy(e,{get(t,a){if(typeof a=="string"){let i=r.get(a);if(i!==void 0&&i!=="")return i}return Reflect.get(t,a)}})}init(e={}){if(typeof window>"u")return this;if(this.isInitialized)return this;if(this.options={enabled:!0,position:"bottom-right",autoFetchEnvFile:!1,interceptNetworkRequests:!0,...e},this.options.enabled===!1)return this;this.store=new x(this.options),this.options.interceptNetworkRequests!==!1&&(this.networkInterceptor=new y(this.store),this.networkInterceptor.enable());let r=()=>{if(this.launcher||!this.store)return;let{shadowRoot:t}=I();this.modal=new E(t,this.store,()=>{}),this.launcher=new w(t,this.options.position,()=>{this.modal?.toggle()});let a=Object.keys(this.store.getOverrides()).length;this.launcher.updateBadgeCount(a),this.store.subscribeStoreChange(()=>{let i=Object.keys(this.store.getOverrides()).length;this.launcher?.updateBadgeCount(i)})};return document.readyState==="loading"?document.addEventListener("DOMContentLoaded",r):r(),this.isInitialized=!0,this}get(e,r){return this.store||this.init(),this.store?.get(e,r)??r??""}set(e,r){this.store||this.init(),this.store?.setOverride(e,r)}remove(e){this.store?.removeOverride(e)}reset(){this.store?.resetAllOverrides()}onChange(e){return this.store||this.init(),this.store?.subscribeEnvChange(e)??(()=>{})}open(){this.modal?.open()}close(){this.modal?.close()}toggle(){this.modal?.toggle()}},L=new S;typeof window<"u"&&(window.lamba=L,(document.currentScript!==null||document.querySelector('script[src*="lamba"]'))&&L.init());var z=L;return U(D);})();
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@ojolowoblue/lamba",
3
+ "version": "1.0.0",
4
+ "description": "A universal dev tool for viewing, overriding, and swapping environment variables live in web applications.",
5
+ "main": "./dist/index.cjs",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "unpkg": "./dist/lamba.min.js",
9
+ "jsdelivr": "./dist/lamba.min.js",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.mjs",
14
+ "require": "./dist/index.cjs"
15
+ },
16
+ "./react": {
17
+ "types": "./dist/integrations/react.d.ts",
18
+ "import": "./dist/integrations/react.mjs",
19
+ "require": "./dist/integrations/react.js"
20
+ },
21
+ "./vue": {
22
+ "types": "./dist/integrations/vue.d.ts",
23
+ "import": "./dist/integrations/vue.mjs",
24
+ "require": "./dist/integrations/vue.js"
25
+ }
26
+ },
27
+ "files": [
28
+ "dist"
29
+ ],
30
+ "scripts": {
31
+ "dev": "tsup --watch",
32
+ "build": "tsup",
33
+ "typecheck": "tsc --noEmit"
34
+ },
35
+ "keywords": [
36
+ "env",
37
+ "dotenv",
38
+ "dev-tool",
39
+ "environment-variables",
40
+ "react",
41
+ "vue",
42
+ "nextjs",
43
+ "astro",
44
+ "vite",
45
+ "unpkg"
46
+ ],
47
+ "author": "AG",
48
+ "license": "MIT",
49
+ "peerDependencies": {
50
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
51
+ "vue": "^3.0.0"
52
+ },
53
+ "peerDependenciesMeta": {
54
+ "react": {
55
+ "optional": true
56
+ },
57
+ "vue": {
58
+ "optional": true
59
+ }
60
+ },
61
+ "devDependencies": {
62
+ "@types/react": "^18.3.3",
63
+ "react": "^18.3.1",
64
+ "tsup": "^8.0.2",
65
+ "typescript": "^5.4.5",
66
+ "vue": "^3.4.27"
67
+ }
68
+ }