@ojolowoblue/lamba 1.0.3 → 1.0.5

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/README.md CHANGED
@@ -27,7 +27,7 @@ Deployed via CDN or installed via NPM, `lamba` injects a non-intrusive floating
27
27
  Include the script tag in your `index.html` file before your application bundle:
28
28
 
29
29
  ```html
30
- <script src="https://unpkg.com/@ojolowoblue/lamba"></script>
30
+ <script src="https://unpkg.com/@ojolowoblue/lamba" data-lamba-auto></script>
31
31
  ```
32
32
 
33
33
  That's it! A floating settings button (⚙️) will automatically appear in the bottom-right corner of your web page.
@@ -52,11 +52,11 @@ import lamba from '@ojolowoblue/lamba';
52
52
  lamba.init({
53
53
  position: 'bottom-right',
54
54
  env: {
55
- // Supports any env prefix (VITE_, NEXT_PUBLIC_, REACT_APP_, VUE_APP_, PUBLIC_) or custom keys:
55
+ // Supports any data type (strings, numbers, booleans, objects) & any prefix:
56
56
  NEXT_PUBLIC_API_URL: 'https://api.dev.example.com',
57
- REACT_APP_FEATURE_FLAG: 'false',
58
- VITE_ENABLE_ANALYTICS: 'true',
59
- API_BASE_URL: 'https://api.dev.example.com',
57
+ PORT: 3000,
58
+ VITE_ENABLE_ANALYTICS: true,
59
+ FEATURE_FLAGS: { newCheckout: true },
60
60
  },
61
61
  });
62
62
  ```
@@ -88,7 +88,7 @@ Wrap your existing `import.meta.env` (Vite) or `process.env` (Webpack/Next.js) o
88
88
  // src/config.ts
89
89
  import lamba from '@ojolowoblue/lamba';
90
90
 
91
- // Wrap your env object in a dynamic ES Proxy
91
+ // Wrap your env object in a dynamic ES Proxy (preserves primitive boolean & number types!)
92
92
  export const env = lamba.wrap(import.meta.env);
93
93
 
94
94
  // Access keys anywhere in your application:
@@ -121,15 +121,15 @@ import React from 'react';
121
121
  import { useLambaEnv } from '@ojolowoblue/lamba/react';
122
122
 
123
123
  export function UserDashboard() {
124
- const apiBase = useLambaEnv('VITE_API_BASE_URL', 'https://api.dev.com');
125
- const showBetaFeature = useLambaEnv('VITE_FEATURE_BETA_UI', 'false');
124
+ const apiBase = useLambaEnv<string>('VITE_API_BASE_URL', 'https://api.dev.com');
125
+ const isBetaEnabled = useLambaEnv<boolean>('VITE_FEATURE_BETA_UI', false);
126
126
 
127
127
  return (
128
128
  <div style={{ padding: '24px' }}>
129
129
  <h1>Dashboard</h1>
130
130
  <p>Connected Environment: <code>{apiBase}</code></p>
131
131
 
132
- {showBetaFeature === 'true' && (
132
+ {isBetaEnabled && (
133
133
  <div className="beta-banner">
134
134
  🚀 Beta UI Enabled Live via lamba!
135
135
  </div>
@@ -147,14 +147,14 @@ Import `useLambaEnv` from `lamba/vue` as a reactive composition Vue Ref:
147
147
  <script setup lang="ts">
148
148
  import { useLambaEnv } from '@ojolowoblue/lamba/vue';
149
149
 
150
- const apiBase = useLambaEnv('VITE_API_BASE_URL', 'https://api.dev.com');
151
- const featureFlag = useLambaEnv('VITE_NEW_HEADER', 'false');
150
+ const apiBase = useLambaEnv<string>('VITE_API_BASE_URL', 'https://api.dev.com');
151
+ const isNewHeader = useLambaEnv<boolean>('VITE_NEW_HEADER', false);
152
152
  </script>
153
153
 
154
154
  <template>
155
155
  <div class="container">
156
156
  <h2>Current Backend: {{ apiBase }}</h2>
157
- <header v-if="featureFlag === 'true'">
157
+ <header v-if="isNewHeader">
158
158
  <h3>✨ New Header Component</h3>
159
159
  </header>
160
160
  </div>
@@ -171,7 +171,7 @@ Initializes the lamba manager, hydrates saved overrides from `localStorage`, ena
171
171
 
172
172
  | Option | Type | Default | Description |
173
173
  | :--- | :--- | :--- | :--- |
174
- | `env` | `Record<string, string>` | `{}` | Initial default key-value pairs of environment variables. |
174
+ | `env` | `Record<string, any>` | `{}` | Initial default key-value pairs of environment variables (supports strings, numbers, booleans, objects). |
175
175
  | `enabled` | `boolean` | `true` | Set to `false` to disable lamba (e.g. in production builds). |
176
176
  | `position` | `'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left'` | `'bottom-right'` | Screen position for the floating widget launcher button. |
177
177
  | `secretKeysPattern` | `RegExp` | `/(KEY\|SECRET\|TOKEN\|PASSWORD\|AUTH\|PRIVATE)/i` | Regular expression to automatically obscure sensitive keys in the UI. |
@@ -183,11 +183,11 @@ Initializes the lamba manager, hydrates saved overrides from `localStorage`, ena
183
183
 
184
184
  ### Core Methods
185
185
 
186
- #### `lamba.get(key: string, fallback?: string): string`
187
- Returns the active value for the specified environment key (returns active override if present, otherwise default value or fallback).
186
+ #### `lamba.get<T = any>(key: string, fallback?: T): T`
187
+ Returns the active value for the specified environment key (returns active override if present, otherwise default value or fallback). Preserves numbers, booleans, and objects.
188
188
 
189
- #### `lamba.set(key: string, value: string): void`
190
- Programmatically overrides an environment variable live at runtime. The change is persisted in `localStorage` and triggers UI and listener updates.
189
+ #### `lamba.set(key: string, value: any): void`
190
+ Programmatically overrides an environment variable live at runtime with any data type. The change is persisted in `localStorage` and triggers UI and listener updates.
191
191
 
192
192
  #### `lamba.remove(key: string): void`
193
193
  Removes an override for a specific environment variable key, reverting it to its default value.
package/dist/index.d.mts CHANGED
@@ -1,21 +1,21 @@
1
1
  interface EnvVariable {
2
2
  key: string;
3
- value: string;
4
- defaultValue: string;
3
+ value: any;
4
+ defaultValue: any;
5
5
  isOverridden: boolean;
6
6
  isSecret?: boolean;
7
7
  }
8
8
  interface PresetProfile {
9
9
  id: string;
10
10
  name: string;
11
- overrides: Record<string, string>;
11
+ overrides: Record<string, any>;
12
12
  createdAt: number;
13
13
  }
14
14
  interface LambaOptions {
15
15
  /**
16
- * Initial environment variable key-values to supply to lamba.
16
+ * Initial environment variable key-values to supply to lamba. Accepts strings, numbers, booleans, objects, etc.
17
17
  */
18
- env?: Record<string, string>;
18
+ env?: Record<string, any>;
19
19
  /**
20
20
  * Whether lamba floating UI is enabled. Defaults to true in non-production or when specified.
21
21
  */
@@ -47,7 +47,7 @@ interface LambaOptions {
47
47
  */
48
48
  allowedPrefixes?: string | string[] | RegExp | null;
49
49
  }
50
- type EnvChangeListener = (key: string, value: string, isOverridden: boolean) => void;
50
+ type EnvChangeListener = (key: string, value: any, isOverridden: boolean) => void;
51
51
  type StoreChangeListener = (variables: Record<string, EnvVariable>, presets: PresetProfile[], activePresetId: string | null) => void;
52
52
 
53
53
  /**
@@ -70,7 +70,7 @@ declare class LambaManager {
70
70
  * Implicit ES Proxy object where properties like `lamba.env.VITE_API_BASE_URL`
71
71
  * return the live active overridden value automatically.
72
72
  */
73
- env: Record<string, string>;
73
+ env: Record<string, any>;
74
74
  constructor();
75
75
  /**
76
76
  * Wraps any environment object (such as `import.meta.env` or `process.env`)
@@ -84,11 +84,11 @@ declare class LambaManager {
84
84
  /**
85
85
  * Gets the active value of an environment variable (returns overridden value if active, otherwise default).
86
86
  */
87
- get(key: string, fallback?: string): string;
87
+ get<T = any>(key: string, fallback?: T): T;
88
88
  /**
89
89
  * Overrides an environment variable live at runtime.
90
90
  */
91
- set(key: string, value: string): void;
91
+ set(key: string, value: any): void;
92
92
  /**
93
93
  * Removes an override for a specific environment variable key.
94
94
  */
package/dist/index.d.ts CHANGED
@@ -1,21 +1,21 @@
1
1
  interface EnvVariable {
2
2
  key: string;
3
- value: string;
4
- defaultValue: string;
3
+ value: any;
4
+ defaultValue: any;
5
5
  isOverridden: boolean;
6
6
  isSecret?: boolean;
7
7
  }
8
8
  interface PresetProfile {
9
9
  id: string;
10
10
  name: string;
11
- overrides: Record<string, string>;
11
+ overrides: Record<string, any>;
12
12
  createdAt: number;
13
13
  }
14
14
  interface LambaOptions {
15
15
  /**
16
- * Initial environment variable key-values to supply to lamba.
16
+ * Initial environment variable key-values to supply to lamba. Accepts strings, numbers, booleans, objects, etc.
17
17
  */
18
- env?: Record<string, string>;
18
+ env?: Record<string, any>;
19
19
  /**
20
20
  * Whether lamba floating UI is enabled. Defaults to true in non-production or when specified.
21
21
  */
@@ -47,7 +47,7 @@ interface LambaOptions {
47
47
  */
48
48
  allowedPrefixes?: string | string[] | RegExp | null;
49
49
  }
50
- type EnvChangeListener = (key: string, value: string, isOverridden: boolean) => void;
50
+ type EnvChangeListener = (key: string, value: any, isOverridden: boolean) => void;
51
51
  type StoreChangeListener = (variables: Record<string, EnvVariable>, presets: PresetProfile[], activePresetId: string | null) => void;
52
52
 
53
53
  /**
@@ -70,7 +70,7 @@ declare class LambaManager {
70
70
  * Implicit ES Proxy object where properties like `lamba.env.VITE_API_BASE_URL`
71
71
  * return the live active overridden value automatically.
72
72
  */
73
- env: Record<string, string>;
73
+ env: Record<string, any>;
74
74
  constructor();
75
75
  /**
76
76
  * Wraps any environment object (such as `import.meta.env` or `process.env`)
@@ -84,11 +84,11 @@ declare class LambaManager {
84
84
  /**
85
85
  * Gets the active value of an environment variable (returns overridden value if active, otherwise default).
86
86
  */
87
- get(key: string, fallback?: string): string;
87
+ get<T = any>(key: string, fallback?: T): T;
88
88
  /**
89
89
  * Overrides an environment variable live at runtime.
90
90
  */
91
- set(key: string, value: string): void;
91
+ set(key: string, value: any): void;
92
92
  /**
93
93
  * Removes an override for a specific environment variable key.
94
94
  */
package/dist/index.js CHANGED
@@ -305,8 +305,9 @@ var EnvStore = class {
305
305
  }
306
306
  mergeDefaults(env) {
307
307
  let changed = false;
308
- for (const [key, defaultValue] of Object.entries(env)) {
308
+ for (const [key, rawDefault] of Object.entries(env)) {
309
309
  if (!this.isAllowedKey(key)) continue;
310
+ const defaultValue = rawDefault;
310
311
  const isOverridden = key in this.overrides;
311
312
  const currentValue = isOverridden ? this.overrides[key] : defaultValue;
312
313
  const isSecret = this.secretPattern.test(key);
@@ -493,9 +494,12 @@ var NetworkInterceptor = class {
493
494
  const allVars = this.store.getAll();
494
495
  let resultUrl = url;
495
496
  for (const varObj of Object.values(allVars)) {
496
- if (varObj.isOverridden && varObj.defaultValue && varObj.value) {
497
- const defaultBase = varObj.defaultValue.replace(/\/+$/, "");
498
- const overrideBase = varObj.value.replace(/\/+$/, "");
497
+ if (varObj.isOverridden && varObj.defaultValue !== void 0 && varObj.value !== void 0) {
498
+ const rawDefault = String(varObj.defaultValue ?? "");
499
+ const rawOverride = String(varObj.value ?? "");
500
+ if (!rawDefault || !rawOverride) continue;
501
+ const defaultBase = rawDefault.replace(/\/+$/, "");
502
+ const overrideBase = rawOverride.replace(/\/+$/, "");
499
503
  if (defaultBase && resultUrl.includes(defaultBase)) {
500
504
  resultUrl = resultUrl.replace(defaultBase, overrideBase);
501
505
  }
@@ -1359,7 +1363,15 @@ var ModalUI = class {
1359
1363
  `;
1360
1364
  const inputEl = card.querySelector(".var-input");
1361
1365
  inputEl.addEventListener("change", () => {
1362
- this.store.setOverride(varItem.key, inputEl.value);
1366
+ let val = inputEl.value;
1367
+ if (typeof varItem.defaultValue === "boolean") {
1368
+ if (val === "true") val = true;
1369
+ else if (val === "false") val = false;
1370
+ } else if (typeof varItem.defaultValue === "number") {
1371
+ const num = Number(val);
1372
+ if (!isNaN(num) && val.trim() !== "") val = num;
1373
+ }
1374
+ this.store.setOverride(varItem.key, val);
1363
1375
  });
1364
1376
  card.querySelector(".toggle-secret-btn")?.addEventListener("click", () => {
1365
1377
  this.secretVisibilityMap.set(varItem.key, !isVisible);
@@ -1371,7 +1383,9 @@ var ModalUI = class {
1371
1383
  return card;
1372
1384
  }
1373
1385
  escapeHtml(str) {
1374
- return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
1386
+ if (str === null || str === void 0) return "";
1387
+ const text = typeof str === "object" ? JSON.stringify(str) : String(str);
1388
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
1375
1389
  }
1376
1390
  };
1377
1391
 
@@ -1394,7 +1408,7 @@ var LambaManager = class {
1394
1408
  },
1395
1409
  set(_target, prop, value) {
1396
1410
  if (typeof prop === "string") {
1397
- self.set(prop, String(value));
1411
+ self.set(prop, value);
1398
1412
  return true;
1399
1413
  }
1400
1414
  return false;
@@ -1413,9 +1427,7 @@ var LambaManager = class {
1413
1427
  try {
1414
1428
  const defaultObj = {};
1415
1429
  for (const [k, v] of Object.entries(targetEnv)) {
1416
- if (typeof v === "string" || typeof v === "number" || typeof v === "boolean") {
1417
- defaultObj[k] = String(v);
1418
- }
1430
+ defaultObj[k] = v;
1419
1431
  }
1420
1432
  if (Object.keys(defaultObj).length > 0) {
1421
1433
  this.store.mergeDefaults(defaultObj);
@@ -1429,10 +1441,24 @@ var LambaManager = class {
1429
1441
  if (typeof prop === "string") {
1430
1442
  const overrideVal = self.get(prop);
1431
1443
  if (overrideVal !== void 0 && overrideVal !== "") {
1444
+ const targetVal = Reflect.get(target, prop);
1445
+ if (typeof targetVal === "boolean") {
1446
+ if (overrideVal === "true" || overrideVal === true) return true;
1447
+ if (overrideVal === "false" || overrideVal === false) return false;
1448
+ } else if (typeof targetVal === "number" && typeof overrideVal === "string") {
1449
+ const num = Number(overrideVal);
1450
+ if (!isNaN(num)) return num;
1451
+ }
1432
1452
  return overrideVal;
1433
1453
  }
1434
1454
  }
1435
1455
  return Reflect.get(target, prop);
1456
+ },
1457
+ set(target, prop, value) {
1458
+ if (typeof prop === "string") {
1459
+ self.set(prop, value);
1460
+ }
1461
+ return Reflect.set(target, prop, value);
1436
1462
  }
1437
1463
  });
1438
1464
  }
@@ -1485,7 +1511,7 @@ var LambaManager = class {
1485
1511
  if (!this.store) {
1486
1512
  this.init();
1487
1513
  }
1488
- return this.store?.get(key, fallback) ?? fallback ?? "";
1514
+ return this.store?.get(key, fallback) ?? fallback;
1489
1515
  }
1490
1516
  /**
1491
1517
  * Overrides an environment variable live at runtime.
@@ -1536,8 +1562,8 @@ var LambaManager = class {
1536
1562
  var lamba = new LambaManager();
1537
1563
  if (typeof window !== "undefined") {
1538
1564
  window.lamba = lamba;
1539
- const isCdnScript = document.currentScript !== null || !!document.querySelector('script[src*="lamba"]');
1540
- if (isCdnScript) {
1565
+ const currentScript = document.currentScript;
1566
+ if (currentScript && (currentScript.hasAttribute("data-lamba-auto") || currentScript.hasAttribute("data-auto-init"))) {
1541
1567
  lamba.init();
1542
1568
  }
1543
1569
  }