@rep-protocol/sdk 0.1.2
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 +9 -0
- package/README.md +76 -0
- package/dist/index.d.mts +84 -0
- package/dist/index.d.ts +84 -0
- package/dist/index.js +14 -0
- package/dist/index.mjs +14 -0
- package/package.json +57 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Specification documents (spec/, schema/) are licensed under:
|
|
2
|
+
Creative Commons Attribution 4.0 International (CC BY 4.0)
|
|
3
|
+
https://creativecommons.org/licenses/by/4.0/
|
|
4
|
+
|
|
5
|
+
Reference implementations and tooling are licensed under:
|
|
6
|
+
Apache License, Version 2.0
|
|
7
|
+
https://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
|
|
9
|
+
Copyright 2026 Ruach Tech
|
package/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# @rep-protocol/sdk
|
|
2
|
+
|
|
3
|
+
Client SDK for the [Runtime Environment Protocol](https://github.com/ruachtech/rep).
|
|
4
|
+
|
|
5
|
+
Zero-dependency, framework-agnostic, ~1.5KB gzipped. Reads environment variables injected by the REP gateway at runtime — no build tool plugins, no framework coupling.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @rep-protocol/sdk
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { rep } from '@rep-protocol/sdk';
|
|
17
|
+
|
|
18
|
+
// PUBLIC tier — synchronous, immediate, no network call.
|
|
19
|
+
const apiUrl = rep.get('API_URL');
|
|
20
|
+
const flags = rep.get('FEATURE_FLAGS', '').split(',');
|
|
21
|
+
|
|
22
|
+
// SENSITIVE tier — async, fetches session key, decrypts.
|
|
23
|
+
const analyticsKey = await rep.getSecure('ANALYTICS_KEY');
|
|
24
|
+
|
|
25
|
+
// All public vars as a frozen object.
|
|
26
|
+
const all = rep.getAll();
|
|
27
|
+
|
|
28
|
+
// Verify payload integrity.
|
|
29
|
+
if (!rep.verify()) {
|
|
30
|
+
console.error('Config may have been tampered with!');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Hot reload (if gateway has --hot-reload enabled).
|
|
34
|
+
const unsub = rep.onChange('FEATURE_FLAGS', (newVal, oldVal) => {
|
|
35
|
+
console.log(`Flags changed: ${oldVal} → ${newVal}`);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Cleanup.
|
|
39
|
+
unsub();
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## API
|
|
43
|
+
|
|
44
|
+
| Method | Returns | Description |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| `rep.get(key, default?)` | `string \| undefined` | Synchronous. PUBLIC tier variable. |
|
|
47
|
+
| `rep.getSecure(key)` | `Promise<string>` | Async. SENSITIVE tier variable (decrypts via session key). |
|
|
48
|
+
| `rep.getAll()` | `Record<string, string>` | All PUBLIC vars as a frozen object. |
|
|
49
|
+
| `rep.verify()` | `boolean` | Check payload integrity. |
|
|
50
|
+
| `rep.meta()` | `REPMeta \| null` | Payload metadata (version, counts, status). |
|
|
51
|
+
| `rep.onChange(key, cb)` | `() => void` | Subscribe to hot reload changes. Returns unsubscribe fn. |
|
|
52
|
+
| `rep.onAnyChange(cb)` | `() => void` | Subscribe to all changes. Returns unsubscribe fn. |
|
|
53
|
+
|
|
54
|
+
## Development Mode
|
|
55
|
+
|
|
56
|
+
Without the REP gateway, `rep.get()` returns `undefined`. Use defaults:
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
const apiUrl = rep.get('API_URL', 'http://localhost:3000');
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Or mock the payload in your `index.html` during development:
|
|
63
|
+
|
|
64
|
+
```html
|
|
65
|
+
<script id="__rep__" type="application/json">
|
|
66
|
+
{"public":{"API_URL":"http://localhost:3000"},"_meta":{"version":"0.1.0","injected_at":"2026-01-01T00:00:00Z","integrity":"hmac-sha256:dev","ttl":0}}
|
|
67
|
+
</script>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Specification
|
|
71
|
+
|
|
72
|
+
Implements [REP-RFC-0001 §5 — Client SDK Specification](https://github.com/ruachtech/rep/blob/main/spec/REP-RFC-0001.md#5-client-sdk-specification).
|
|
73
|
+
|
|
74
|
+
## License
|
|
75
|
+
|
|
76
|
+
Apache 2.0
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @rep-protocol/sdk — Client SDK for the Runtime Environment Protocol.
|
|
3
|
+
*
|
|
4
|
+
* Zero-dependency, framework-agnostic SDK for reading environment variables
|
|
5
|
+
* injected by the REP gateway.
|
|
6
|
+
*
|
|
7
|
+
* PUBLIC tier variables are available synchronously via `rep.get()`.
|
|
8
|
+
* SENSITIVE tier variables require async decryption via `rep.getSecure()`.
|
|
9
|
+
*
|
|
10
|
+
* @see https://github.com/ruachtech/rep — REP-RFC-0001 §5
|
|
11
|
+
* @license Apache-2.0
|
|
12
|
+
* @version 0.1.0
|
|
13
|
+
*/
|
|
14
|
+
interface REPMeta {
|
|
15
|
+
version: string;
|
|
16
|
+
injectedAt: Date;
|
|
17
|
+
integrityValid: boolean;
|
|
18
|
+
publicCount: number;
|
|
19
|
+
sensitiveAvailable: boolean;
|
|
20
|
+
hotReloadAvailable: boolean;
|
|
21
|
+
}
|
|
22
|
+
type ChangeCallback = (newValue: string, oldValue: string | undefined) => void;
|
|
23
|
+
type AnyChangeCallback = (key: string, newValue: string, oldValue: string | undefined) => void;
|
|
24
|
+
/**
|
|
25
|
+
* Retrieve a PUBLIC tier variable. Synchronous — no network call.
|
|
26
|
+
*
|
|
27
|
+
* Per §5.2: when called with a defaultValue the return type narrows to string.
|
|
28
|
+
*
|
|
29
|
+
* @param key - Variable name (without REP_PUBLIC_ prefix).
|
|
30
|
+
* @param defaultValue - Fallback if the variable is not present.
|
|
31
|
+
*/
|
|
32
|
+
declare function get(key: string, defaultValue: string): string;
|
|
33
|
+
declare function get(key: string, defaultValue?: undefined): string | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Retrieve a SENSITIVE tier variable. Async — fetches a session key.
|
|
36
|
+
*
|
|
37
|
+
* Per §5.2, decrypted values are cached in memory for the page lifetime.
|
|
38
|
+
*
|
|
39
|
+
* @param key - Variable name (without REP_SENSITIVE_ prefix).
|
|
40
|
+
* @throws REPError if the session key endpoint is unreachable or decryption fails.
|
|
41
|
+
*/
|
|
42
|
+
declare function getSecure(key: string): Promise<string>;
|
|
43
|
+
/**
|
|
44
|
+
* Retrieve all PUBLIC tier variables as a frozen object. Synchronous.
|
|
45
|
+
*/
|
|
46
|
+
declare function getAll(): Readonly<Record<string, string>>;
|
|
47
|
+
/**
|
|
48
|
+
* Verify payload integrity. Synchronous check of the tamper flag.
|
|
49
|
+
* For full async SRI verification, use meta().integrityValid.
|
|
50
|
+
*/
|
|
51
|
+
declare function verify(): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Returns metadata about the current REP payload.
|
|
54
|
+
* Returns null if no payload is present.
|
|
55
|
+
*/
|
|
56
|
+
declare function meta(): REPMeta | null;
|
|
57
|
+
/**
|
|
58
|
+
* Register a callback for when a specific PUBLIC variable changes.
|
|
59
|
+
*
|
|
60
|
+
* If hot reload is not available, logs a warning and returns a no-op unsubscribe.
|
|
61
|
+
* Per §5.3 step 7: SSE connection is established lazily on first onChange call.
|
|
62
|
+
*/
|
|
63
|
+
declare function onChange(key: string, callback: ChangeCallback): () => void;
|
|
64
|
+
/**
|
|
65
|
+
* Register a callback for any variable change.
|
|
66
|
+
*/
|
|
67
|
+
declare function onAnyChange(callback: AnyChangeCallback): () => void;
|
|
68
|
+
/**
|
|
69
|
+
* The `rep` namespace object for convenient named import:
|
|
70
|
+
*
|
|
71
|
+
* import { rep } from '@rep-protocol/sdk';
|
|
72
|
+
* const url = rep.get('API_URL');
|
|
73
|
+
*/
|
|
74
|
+
declare const rep: {
|
|
75
|
+
get: typeof get;
|
|
76
|
+
getSecure: typeof getSecure;
|
|
77
|
+
getAll: typeof getAll;
|
|
78
|
+
verify: typeof verify;
|
|
79
|
+
meta: typeof meta;
|
|
80
|
+
onChange: typeof onChange;
|
|
81
|
+
onAnyChange: typeof onAnyChange;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export { rep as default, get, getAll, getSecure, meta, onAnyChange, onChange, rep, verify };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @rep-protocol/sdk — Client SDK for the Runtime Environment Protocol.
|
|
3
|
+
*
|
|
4
|
+
* Zero-dependency, framework-agnostic SDK for reading environment variables
|
|
5
|
+
* injected by the REP gateway.
|
|
6
|
+
*
|
|
7
|
+
* PUBLIC tier variables are available synchronously via `rep.get()`.
|
|
8
|
+
* SENSITIVE tier variables require async decryption via `rep.getSecure()`.
|
|
9
|
+
*
|
|
10
|
+
* @see https://github.com/ruachtech/rep — REP-RFC-0001 §5
|
|
11
|
+
* @license Apache-2.0
|
|
12
|
+
* @version 0.1.0
|
|
13
|
+
*/
|
|
14
|
+
interface REPMeta {
|
|
15
|
+
version: string;
|
|
16
|
+
injectedAt: Date;
|
|
17
|
+
integrityValid: boolean;
|
|
18
|
+
publicCount: number;
|
|
19
|
+
sensitiveAvailable: boolean;
|
|
20
|
+
hotReloadAvailable: boolean;
|
|
21
|
+
}
|
|
22
|
+
type ChangeCallback = (newValue: string, oldValue: string | undefined) => void;
|
|
23
|
+
type AnyChangeCallback = (key: string, newValue: string, oldValue: string | undefined) => void;
|
|
24
|
+
/**
|
|
25
|
+
* Retrieve a PUBLIC tier variable. Synchronous — no network call.
|
|
26
|
+
*
|
|
27
|
+
* Per §5.2: when called with a defaultValue the return type narrows to string.
|
|
28
|
+
*
|
|
29
|
+
* @param key - Variable name (without REP_PUBLIC_ prefix).
|
|
30
|
+
* @param defaultValue - Fallback if the variable is not present.
|
|
31
|
+
*/
|
|
32
|
+
declare function get(key: string, defaultValue: string): string;
|
|
33
|
+
declare function get(key: string, defaultValue?: undefined): string | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Retrieve a SENSITIVE tier variable. Async — fetches a session key.
|
|
36
|
+
*
|
|
37
|
+
* Per §5.2, decrypted values are cached in memory for the page lifetime.
|
|
38
|
+
*
|
|
39
|
+
* @param key - Variable name (without REP_SENSITIVE_ prefix).
|
|
40
|
+
* @throws REPError if the session key endpoint is unreachable or decryption fails.
|
|
41
|
+
*/
|
|
42
|
+
declare function getSecure(key: string): Promise<string>;
|
|
43
|
+
/**
|
|
44
|
+
* Retrieve all PUBLIC tier variables as a frozen object. Synchronous.
|
|
45
|
+
*/
|
|
46
|
+
declare function getAll(): Readonly<Record<string, string>>;
|
|
47
|
+
/**
|
|
48
|
+
* Verify payload integrity. Synchronous check of the tamper flag.
|
|
49
|
+
* For full async SRI verification, use meta().integrityValid.
|
|
50
|
+
*/
|
|
51
|
+
declare function verify(): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Returns metadata about the current REP payload.
|
|
54
|
+
* Returns null if no payload is present.
|
|
55
|
+
*/
|
|
56
|
+
declare function meta(): REPMeta | null;
|
|
57
|
+
/**
|
|
58
|
+
* Register a callback for when a specific PUBLIC variable changes.
|
|
59
|
+
*
|
|
60
|
+
* If hot reload is not available, logs a warning and returns a no-op unsubscribe.
|
|
61
|
+
* Per §5.3 step 7: SSE connection is established lazily on first onChange call.
|
|
62
|
+
*/
|
|
63
|
+
declare function onChange(key: string, callback: ChangeCallback): () => void;
|
|
64
|
+
/**
|
|
65
|
+
* Register a callback for any variable change.
|
|
66
|
+
*/
|
|
67
|
+
declare function onAnyChange(callback: AnyChangeCallback): () => void;
|
|
68
|
+
/**
|
|
69
|
+
* The `rep` namespace object for convenient named import:
|
|
70
|
+
*
|
|
71
|
+
* import { rep } from '@rep-protocol/sdk';
|
|
72
|
+
* const url = rep.get('API_URL');
|
|
73
|
+
*/
|
|
74
|
+
declare const rep: {
|
|
75
|
+
get: typeof get;
|
|
76
|
+
getSecure: typeof getSecure;
|
|
77
|
+
getAll: typeof getAll;
|
|
78
|
+
verify: typeof verify;
|
|
79
|
+
meta: typeof meta;
|
|
80
|
+
onChange: typeof onChange;
|
|
81
|
+
onAnyChange: typeof onAnyChange;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export { rep as default, get, getAll, getSecure, meta, onAnyChange, onChange, rep, verify };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";var b=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var I=Object.getOwnPropertyNames;var z=Object.prototype.hasOwnProperty;var N=(e,t)=>{for(var n in t)b(e,n,{get:t[n],enumerable:!0})},K=(e,t,n,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of I(t))!z.call(e,o)&&o!==n&&b(e,o,{get:()=>t[o],enumerable:!(a=O(t,o))||a.enumerable});return e};var T=e=>K(b({},"__esModule",{value:!0}),e);var H={};N(H,{default:()=>D,get:()=>E,getAll:()=>w,getSecure:()=>m,meta:()=>S,onAnyChange:()=>x,onChange:()=>R,rep:()=>V,verify:()=>C});module.exports=T(H);var g=class extends Error{constructor(t){super(`[REP] ${t}`),this.name="REPError"}},r=null,i=!1,v=!1,l=Object.freeze({}),p=null,d=null,c=new Map,f=new Set;function B(){if(typeof document>"u"){i=!1;return}let e=document.getElementById("__rep__");if(!e){i=!1;return}try{r=JSON.parse(e.textContent||"")}catch(n){console.error("[REP] Failed to parse payload:",n),i=!1;return}if(!r||!r.public||!r._meta){console.error("[REP] Payload is malformed \u2014 missing required fields."),i=!1;return}let t=e.getAttribute("data-rep-integrity");t&&$(e.textContent||"",t).then(n=>{n||(console.error("[REP] Integrity check failed \u2014 payload may have been tampered with."),v=!0)}),l=Object.freeze({...r.public}),i=!0}async function $(e,t){if(!t.startsWith("sha256-"))return!1;let n=t.slice(7);try{let o=new TextEncoder().encode(e),s=await crypto.subtle.digest("SHA-256",o),u=new Uint8Array(s);return btoa(String.fromCharCode(...u))===n}catch{return!1}}B();function E(e,t){if(!i)return t;let n=l[e];return n!==void 0?n:t}async function m(e){if(!i||!r)throw new g("REP payload not available.");if(!r.sensitive||!r._meta.key_endpoint)throw new g("No SENSITIVE tier variables in payload.");if(p&&e in p)return p[e];let t=await fetch(r._meta.key_endpoint);if(!t.ok)throw new g(`Session key request failed: ${t.status} ${t.statusText}`);let n=await t.json(),a=Uint8Array.from(atob(n.key),h=>h.charCodeAt(0)),o=Uint8Array.from(atob(r.sensitive),h=>h.charCodeAt(0)),s=o.slice(0,12),u=o.slice(12),_=await crypto.subtle.importKey("raw",a,{name:"AES-GCM"},!1,["decrypt"]),j=new TextEncoder().encode(r._meta.integrity),k=await crypto.subtle.decrypt({name:"AES-GCM",iv:s,additionalData:j},_,u),M=new TextDecoder,y=JSON.parse(M.decode(k));if(p=y,!(e in y))throw new g(`SENSITIVE variable "${e}" not found in payload.`);return y[e]}function w(){return l}function C(){return i&&!v}function S(){return!i||!r?null:{version:r._meta.version,injectedAt:new Date(r._meta.injected_at),integrityValid:!v,publicCount:Object.keys(r.public).length,sensitiveAvailable:!!r.sensitive,hotReloadAvailable:!!r._meta.hot_reload}}function R(e,t){return!i||!r?._meta.hot_reload?(console.warn(`[REP] Hot reload not available. onChange("${e}") is a no-op.`),()=>{}):(A(),c.has(e)||c.set(e,new Set),c.get(e).add(t),()=>{c.get(e)?.delete(t),c.get(e)?.size===0&&c.delete(e),P()})}function x(e){return!i||!r?._meta.hot_reload?(console.warn("[REP] Hot reload not available. onAnyChange() is a no-op."),()=>{}):(A(),f.add(e),()=>{f.delete(e),P()})}function A(){d||!r?._meta.hot_reload||(d=new EventSource(r._meta.hot_reload),d.addEventListener("rep:config:update",e=>{try{let t=JSON.parse(e.data),{key:n,value:a}=t,o=l[n],s={...l,[n]:a};l=Object.freeze(s),r&&(r.public[n]=a),c.get(n)?.forEach(u=>u(a,o)),f.forEach(u=>u(n,a,o))}catch(t){console.error("[REP] Failed to process hot reload event:",t)}}),d.addEventListener("rep:config:delete",e=>{try{let t=JSON.parse(e.data),{key:n}=t,a=l[n],o={...l};delete o[n],l=Object.freeze(o),r&&delete r.public[n],c.get(n)?.forEach(s=>s("",a)),f.forEach(s=>s(n,"",a))}catch(t){console.error("[REP] Failed to process hot reload delete:",t)}}),d.onerror=()=>{console.warn("[REP] Hot reload SSE connection lost. Will reconnect automatically.")})}function P(){c.size===0&&f.size===0&&d&&(d.close(),d=null)}var V={get:E,getSecure:m,getAll:w,verify:C,meta:S,onChange:R,onAnyChange:x},D=V;0&&(module.exports={get,getAll,getSecure,meta,onAnyChange,onChange,rep,verify});
|
|
2
|
+
/**
|
|
3
|
+
* @rep-protocol/sdk — Client SDK for the Runtime Environment Protocol.
|
|
4
|
+
*
|
|
5
|
+
* Zero-dependency, framework-agnostic SDK for reading environment variables
|
|
6
|
+
* injected by the REP gateway.
|
|
7
|
+
*
|
|
8
|
+
* PUBLIC tier variables are available synchronously via `rep.get()`.
|
|
9
|
+
* SENSITIVE tier variables require async decryption via `rep.getSecure()`.
|
|
10
|
+
*
|
|
11
|
+
* @see https://github.com/ruachtech/rep — REP-RFC-0001 §5
|
|
12
|
+
* @license Apache-2.0
|
|
13
|
+
* @version 0.1.0
|
|
14
|
+
*/
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
var g=class extends Error{constructor(t){super(`[REP] ${t}`),this.name="REPError"}},n=null,o=!1,b=!1,l=Object.freeze({}),p=null,d=null,c=new Map,f=new Set;function S(){if(typeof document>"u"){o=!1;return}let e=document.getElementById("__rep__");if(!e){o=!1;return}try{n=JSON.parse(e.textContent||"")}catch(r){console.error("[REP] Failed to parse payload:",r),o=!1;return}if(!n||!n.public||!n._meta){console.error("[REP] Payload is malformed \u2014 missing required fields."),o=!1;return}let t=e.getAttribute("data-rep-integrity");t&&R(e.textContent||"",t).then(r=>{r||(console.error("[REP] Integrity check failed \u2014 payload may have been tampered with."),b=!0)}),l=Object.freeze({...n.public}),o=!0}async function R(e,t){if(!t.startsWith("sha256-"))return!1;let r=t.slice(7);try{let i=new TextEncoder().encode(e),s=await crypto.subtle.digest("SHA-256",i),u=new Uint8Array(s);return btoa(String.fromCharCode(...u))===r}catch{return!1}}S();function x(e,t){if(!o)return t;let r=l[e];return r!==void 0?r:t}async function A(e){if(!o||!n)throw new g("REP payload not available.");if(!n.sensitive||!n._meta.key_endpoint)throw new g("No SENSITIVE tier variables in payload.");if(p&&e in p)return p[e];let t=await fetch(n._meta.key_endpoint);if(!t.ok)throw new g(`Session key request failed: ${t.status} ${t.statusText}`);let r=await t.json(),a=Uint8Array.from(atob(r.key),h=>h.charCodeAt(0)),i=Uint8Array.from(atob(n.sensitive),h=>h.charCodeAt(0)),s=i.slice(0,12),u=i.slice(12),v=await crypto.subtle.importKey("raw",a,{name:"AES-GCM"},!1,["decrypt"]),m=new TextEncoder().encode(n._meta.integrity),w=await crypto.subtle.decrypt({name:"AES-GCM",iv:s,additionalData:m},v,u),C=new TextDecoder,y=JSON.parse(C.decode(w));if(p=y,!(e in y))throw new g(`SENSITIVE variable "${e}" not found in payload.`);return y[e]}function P(){return l}function V(){return o&&!b}function j(){return!o||!n?null:{version:n._meta.version,injectedAt:new Date(n._meta.injected_at),integrityValid:!b,publicCount:Object.keys(n.public).length,sensitiveAvailable:!!n.sensitive,hotReloadAvailable:!!n._meta.hot_reload}}function k(e,t){return!o||!n?._meta.hot_reload?(console.warn(`[REP] Hot reload not available. onChange("${e}") is a no-op.`),()=>{}):(_(),c.has(e)||c.set(e,new Set),c.get(e).add(t),()=>{c.get(e)?.delete(t),c.get(e)?.size===0&&c.delete(e),E()})}function M(e){return!o||!n?._meta.hot_reload?(console.warn("[REP] Hot reload not available. onAnyChange() is a no-op."),()=>{}):(_(),f.add(e),()=>{f.delete(e),E()})}function _(){d||!n?._meta.hot_reload||(d=new EventSource(n._meta.hot_reload),d.addEventListener("rep:config:update",e=>{try{let t=JSON.parse(e.data),{key:r,value:a}=t,i=l[r],s={...l,[r]:a};l=Object.freeze(s),n&&(n.public[r]=a),c.get(r)?.forEach(u=>u(a,i)),f.forEach(u=>u(r,a,i))}catch(t){console.error("[REP] Failed to process hot reload event:",t)}}),d.addEventListener("rep:config:delete",e=>{try{let t=JSON.parse(e.data),{key:r}=t,a=l[r],i={...l};delete i[r],l=Object.freeze(i),n&&delete n.public[r],c.get(r)?.forEach(s=>s("",a)),f.forEach(s=>s(r,"",a))}catch(t){console.error("[REP] Failed to process hot reload delete:",t)}}),d.onerror=()=>{console.warn("[REP] Hot reload SSE connection lost. Will reconnect automatically.")})}function E(){c.size===0&&f.size===0&&d&&(d.close(),d=null)}var O={get:x,getSecure:A,getAll:P,verify:V,meta:j,onChange:k,onAnyChange:M},z=O;export{z as default,x as get,P as getAll,A as getSecure,j as meta,M as onAnyChange,k as onChange,O as rep,V as verify};
|
|
2
|
+
/**
|
|
3
|
+
* @rep-protocol/sdk — Client SDK for the Runtime Environment Protocol.
|
|
4
|
+
*
|
|
5
|
+
* Zero-dependency, framework-agnostic SDK for reading environment variables
|
|
6
|
+
* injected by the REP gateway.
|
|
7
|
+
*
|
|
8
|
+
* PUBLIC tier variables are available synchronously via `rep.get()`.
|
|
9
|
+
* SENSITIVE tier variables require async decryption via `rep.getSecure()`.
|
|
10
|
+
*
|
|
11
|
+
* @see https://github.com/ruachtech/rep — REP-RFC-0001 §5
|
|
12
|
+
* @license Apache-2.0
|
|
13
|
+
* @version 0.1.0
|
|
14
|
+
*/
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rep-protocol/sdk",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "Client SDK for the Runtime Environment Protocol (REP). Zero-dependency, framework-agnostic runtime env var access for browser applications.",
|
|
5
|
+
"author": "Ruach Tech",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/RuachTech/rep",
|
|
10
|
+
"directory": "sdk"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/RuachTech/rep#readme",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"environment-variables",
|
|
15
|
+
"runtime-config",
|
|
16
|
+
"docker",
|
|
17
|
+
"containers",
|
|
18
|
+
"frontend",
|
|
19
|
+
"twelve-factor",
|
|
20
|
+
"spa",
|
|
21
|
+
"react",
|
|
22
|
+
"vue",
|
|
23
|
+
"svelte",
|
|
24
|
+
"angular"
|
|
25
|
+
],
|
|
26
|
+
"main": "dist/index.cjs",
|
|
27
|
+
"module": "dist/index.mjs",
|
|
28
|
+
"types": "dist/index.d.ts",
|
|
29
|
+
"exports": {
|
|
30
|
+
".": {
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"import": "./dist/index.mjs",
|
|
33
|
+
"require": "./dist/index.cjs"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist"
|
|
38
|
+
],
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public",
|
|
41
|
+
"provenance": false
|
|
42
|
+
},
|
|
43
|
+
"sideEffects": false,
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"jsdom": "^28.1.0",
|
|
46
|
+
"tsup": "^8.0.0",
|
|
47
|
+
"typescript": "^5.4.0",
|
|
48
|
+
"vitest": "^1.6.0"
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean --minify",
|
|
52
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
53
|
+
"typecheck": "tsc --noEmit",
|
|
54
|
+
"test": "vitest run",
|
|
55
|
+
"test:watch": "vitest"
|
|
56
|
+
}
|
|
57
|
+
}
|