@sentroy-co/client-sdk 2.8.0 → 2.12.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.
@@ -32,8 +32,10 @@ exports.refreshEnvCache = refreshEnvCache;
32
32
  exports.preloadEnv = preloadEnv;
33
33
  exports.getEnv = getEnv;
34
34
  exports.getEnvOrThrow = getEnvOrThrow;
35
+ exports.getEnvWithFallback = getEnvWithFallback;
35
36
  exports.getAllEnvs = getAllEnvs;
36
37
  exports.getPublicEnvs = getPublicEnvs;
38
+ exports.createVaultWebhookHandler = createVaultWebhookHandler;
37
39
  const DEFAULT_TTL_MS = 5 * 60 * 1000;
38
40
  const DEFAULT_BASE_URL = "https://sentroy.com";
39
41
  let resolvedBaseUrl = DEFAULT_BASE_URL;
@@ -148,6 +150,38 @@ async function getEnvOrThrow(key) {
148
150
  }
149
151
  return v;
150
152
  }
153
+ /**
154
+ * Migration helper — vault'tan oku, yoksa `process.env` fallback.
155
+ *
156
+ * Sentroy app'lerini kademeli olarak `process.env` → vault'a çevirirken
157
+ * "her ikisi de çalışsın" senaryosu için. Vault doldurulmamış / token
158
+ * eksik / fetch fail dönerse sessizce `process.env[key]`'e döner — eski
159
+ * deploy ile yeni kod bir arada çalışabilir.
160
+ *
161
+ * **Migration tamamlandıktan sonra** çağrı sitelerini `getEnv()` ya da
162
+ * `getEnvOrThrow()`'a çevir; fallback'i bırakmak silently process.env
163
+ * sızıntısı riskini taşır (kullanıcı vault'tan key'i sildi sansa bile
164
+ * eski process.env değeri etkili olur).
165
+ *
166
+ * Bootstrap path için (`SENTROY_ENV_API_KEY` set değil) doğrudan
167
+ * `process.env`'e döner — vault fetch denemez. Bu önemli: Sentroy app'i
168
+ * vault'sız boot edilebilir.
169
+ */
170
+ async function getEnvWithFallback(key) {
171
+ // Token yoksa bypass — vault fetch denemeyelim, log spam etmeyelim.
172
+ const apiKey = resolvedApiKey ?? readEnv("SENTROY_ENV_API_KEY");
173
+ if (!apiKey)
174
+ return readEnv(key);
175
+ try {
176
+ const v = await getEnv(key);
177
+ if (v !== undefined)
178
+ return v;
179
+ }
180
+ catch {
181
+ // Fetch fail / network down / 401 → sessizce fallback
182
+ }
183
+ return readEnv(key);
184
+ }
151
185
  /** Tüm env'leri map olarak döner (dump için kullanışlı). */
152
186
  async function getAllEnvs() {
153
187
  const c = await ensureCache();
@@ -166,4 +200,86 @@ async function getPublicEnvs() {
166
200
  }
167
201
  return out;
168
202
  }
203
+ const DEFAULT_MAX_AGE_MS = 5 * 60 * 1000;
204
+ async function timingSafeEqualHex(a, b) {
205
+ if (a.length !== b.length)
206
+ return false;
207
+ let diff = 0;
208
+ for (let i = 0; i < a.length; i++) {
209
+ diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
210
+ }
211
+ return diff === 0;
212
+ }
213
+ async function hmacSha256Hex(secret, body) {
214
+ // Web Crypto — Node 18+ + browser ikisi de destekler.
215
+ const encoder = new TextEncoder();
216
+ const key = await crypto.subtle.importKey("raw", encoder.encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
217
+ const sig = await crypto.subtle.sign("HMAC", key, encoder.encode(body));
218
+ const bytes = new Uint8Array(sig);
219
+ let hex = "";
220
+ for (const b of bytes)
221
+ hex += b.toString(16).padStart(2, "0");
222
+ return hex;
223
+ }
224
+ /**
225
+ * Bir Sentroy vault webhook receiver'ı için Request → Response handler
226
+ * üretir. Next.js App Router'da:
227
+ *
228
+ * // app/api/sentroy/vault-webhook/route.ts
229
+ * import { createVaultWebhookHandler } from "@sentroy-co/client-sdk/vault"
230
+ * export const POST = createVaultWebhookHandler({
231
+ * secret: process.env.SENTROY_VAULT_WEBHOOK_SECRET!,
232
+ * })
233
+ *
234
+ * Default davranış: imza doğruysa cache'i invalidate eder ve 200 döner.
235
+ * Hatalı/eksik imza → 401, eski timestamp → 401, body parse hatası → 400.
236
+ */
237
+ function createVaultWebhookHandler(options) {
238
+ const maxAgeMs = options.maxAgeMs ?? DEFAULT_MAX_AGE_MS;
239
+ return async (request) => {
240
+ const sigHeader = request.headers.get("x-sentroy-signature") || "";
241
+ const match = sigHeader.match(/^sha256=([a-f0-9]+)$/i);
242
+ if (!match) {
243
+ return new Response("missing or malformed X-Sentroy-Signature header", {
244
+ status: 401,
245
+ });
246
+ }
247
+ const providedSig = match[1].toLowerCase();
248
+ const body = await request.text();
249
+ const expected = await hmacSha256Hex(options.secret, body);
250
+ if (!(await timingSafeEqualHex(providedSig, expected))) {
251
+ return new Response("signature mismatch", { status: 401 });
252
+ }
253
+ let payload;
254
+ try {
255
+ payload = JSON.parse(body);
256
+ }
257
+ catch {
258
+ return new Response("invalid JSON body", { status: 400 });
259
+ }
260
+ if (maxAgeMs > 0) {
261
+ const age = Date.now() - (payload.timestamp ?? 0);
262
+ if (!Number.isFinite(age) || age < 0 || age > maxAgeMs) {
263
+ return new Response("payload timestamp outside acceptable window", {
264
+ status: 401,
265
+ });
266
+ }
267
+ }
268
+ try {
269
+ if (options.onChange) {
270
+ await options.onChange(payload);
271
+ }
272
+ else {
273
+ await refreshEnvCache();
274
+ }
275
+ }
276
+ catch (err) {
277
+ return new Response(`handler error: ${err instanceof Error ? err.message : String(err)}`, { status: 500 });
278
+ }
279
+ return new Response(JSON.stringify({ ok: true }), {
280
+ status: 200,
281
+ headers: { "Content-Type": "application/json" },
282
+ });
283
+ };
284
+ }
169
285
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/vault/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/vault/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;;AA8CH,gDAYC;AAGD,wCAEC;AAGD,0CAGC;AAGD,gCAEC;AAkED,wBAGC;AAGD,sCAQC;AAmBD,gDAaC;AAGD,gCAKC;AAGD,sCAOC;AA2ED,8DAqDC;AA5TD,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAA;AACpC,MAAM,gBAAgB,GAAG,qBAAqB,CAAA;AAa9C,IAAI,eAAe,GAAG,gBAAgB,CAAA;AACtC,IAAI,cAAkC,CAAA;AACtC,IAAI,UAAU,GAAG,cAAc,CAAA;AAC/B,IAAI,cAAc,GAAG,IAAI,CAAA;AACzB,IAAI,KAAK,GAAyB,IAAI,CAAA;AACtC,IAAI,cAAc,GAAyB,IAAI,CAAA;AAE/C,SAAS,OAAO,CAAC,IAAY;IAC3B,IAAI,OAAO,OAAO,KAAK,WAAW;QAAE,OAAO,SAAS,CAAA;IACpD,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;AAC5B,CAAC;AAED;;;GAGG;AACH,SAAgB,kBAAkB,CAAC,UAAyB,EAAE;IAC5D,IAAI,OAAO,CAAC,OAAO;QAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;;QAExE,eAAe,GAAG,CAChB,OAAO,CAAC,iCAAiC,CAAC;YAC1C,OAAO,CAAC,qBAAqB,CAAC;YAC9B,OAAO,CAAC,0BAA0B,CAAC;YACnC,gBAAgB,CACjB,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IACvB,cAAc,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAAA;IACjE,IAAI,OAAO,CAAC,UAAU;QAAE,UAAU,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAA;IAC9D,IAAI,OAAO,CAAC,SAAS;QAAE,cAAc,GAAG,OAAO,CAAC,SAAS,CAAA;AAC3D,CAAC;AAED,8EAA8E;AAC9E,SAAgB,cAAc,CAAC,OAAe;IAC5C,UAAU,GAAG,OAAO,GAAG,IAAI,CAAA;AAC7B,CAAC;AAED,8EAA8E;AACvE,KAAK,UAAU,eAAe;IACnC,KAAK,GAAG,IAAI,CAAA;IACZ,MAAM,WAAW,EAAE,CAAA;AACrB,CAAC;AAED,2EAA2E;AACpE,KAAK,UAAU,UAAU;IAC9B,MAAM,WAAW,EAAE,CAAA;AACrB,CAAC;AAED,KAAK,UAAU,cAAc;IAC3B,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,iEAAiE;QACjE,kBAAkB,EAAE,CAAA;IACtB,CAAC;IACD,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CACb,gEAAgE;YAC9D,2FAA2F,CAC9F,CAAA;IACH,CAAC;IACD,MAAM,GAAG,GAAG,GAAG,eAAe,sBAAsB,CAAA;IACpD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,cAAc,EAAE,EAAE;QACtD,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,cAAc,CAAC;QAC3C,KAAK,EAAE,UAAU;KAClB,CAAC,CAAA;IACF,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,2BAA2B,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,SAAS,GAAG,GAAG,CACvE,CAAA;IACH,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAM7B,CAAA;IACD,IAAI,CAAC,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;IACtE,MAAM,GAAG,GAAG,IAAI,GAAG,EAAuB,CAAA;IAC1C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS;QAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;IACtD,OAAO;QACL,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;QACrB,SAAS,EAAE,GAAG;QACd,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO;QAC1B,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW;KACnC,CAAA;AACH,CAAC;AAED,KAAK,UAAU,WAAW;IACxB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IACtB,IAAI,KAAK,IAAI,GAAG,GAAG,KAAK,CAAC,SAAS,GAAG,UAAU;QAAE,OAAO,KAAK,CAAA;IAC7D,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,cAAc,CAAA;QACpB,IAAI,KAAK;YAAE,OAAO,KAAK,CAAA;IACzB,CAAC;IACD,cAAc,GAAG,CAAC,KAAK,IAAI,EAAE;QAC3B,IAAI,CAAC;YACH,KAAK,GAAG,MAAM,cAAc,EAAE,CAAA;QAChC,CAAC;gBAAS,CAAC;YACT,cAAc,GAAG,IAAI,CAAA;QACvB,CAAC;IACH,CAAC,CAAC,EAAE,CAAA;IACJ,MAAM,cAAc,CAAA;IACpB,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;IAC9D,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;GAIG;AACI,KAAK,UAAU,MAAM,CAAC,GAAW;IACtC,MAAM,CAAC,GAAG,MAAM,WAAW,EAAE,CAAA;IAC7B,OAAO,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,KAAK,CAAA;AACpC,CAAC;AAED,8EAA8E;AACvE,KAAK,UAAU,aAAa,CAAC,GAAW;IAC7C,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,CAAA;IAC3B,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CACb,gCAAgC,GAAG,4BAA4B,KAAK,EAAE,OAAO,IAAI,GAAG,SAAS,KAAK,EAAE,WAAW,IAAI,GAAG,GAAG,CAC1H,CAAA;IACH,CAAC;IACD,OAAO,CAAC,CAAA;AACV,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACI,KAAK,UAAU,kBAAkB,CACtC,GAAW;IAEX,oEAAoE;IACpE,MAAM,MAAM,GAAG,cAAc,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAAA;IAC/D,IAAI,CAAC,MAAM;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,CAAA;IAChC,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,CAAA;QAC3B,IAAI,CAAC,KAAK,SAAS;YAAE,OAAO,CAAC,CAAA;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,sDAAsD;IACxD,CAAC;IACD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAA;AACrB,CAAC;AAED,4DAA4D;AACrD,KAAK,UAAU,UAAU;IAC9B,MAAM,CAAC,GAAG,MAAM,WAAW,EAAE,CAAA;IAC7B,MAAM,GAAG,GAA2B,EAAE,CAAA;IACtC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS;QAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAA;IAClD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,gEAAgE;AACzD,KAAK,UAAU,aAAa;IACjC,MAAM,CAAC,GAAG,MAAM,WAAW,EAAE,CAAA;IAC7B,MAAM,GAAG,GAA2B,EAAE,CAAA;IACtC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;QACjC,IAAI,CAAC,CAAC,MAAM;YAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAA;IAChC,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAkCD,MAAM,kBAAkB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAA;AAExC,KAAK,UAAU,kBAAkB,CAAC,CAAS,EAAE,CAAS;IACpD,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAA;IACvC,IAAI,IAAI,GAAG,CAAC,CAAA;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,IAAI,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;IAC3C,CAAC;IACD,OAAO,IAAI,KAAK,CAAC,CAAA;AACnB,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,MAAc,EAAE,IAAY;IACvD,sDAAsD;IACtD,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAA;IACjC,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CACvC,KAAK,EACL,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EACtB,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,EACjC,KAAK,EACL,CAAC,MAAM,CAAC,CACT,CAAA;IACD,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;IACvE,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAA;IACjC,IAAI,GAAG,GAAG,EAAE,CAAA;IACZ,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,GAAG,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IAC7D,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAgB,yBAAyB,CACvC,OAAyC;IAEzC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,kBAAkB,CAAA;IACvD,OAAO,KAAK,EAAE,OAAgB,EAAE,EAAE;QAChC,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,IAAI,EAAE,CAAA;QAClE,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAA;QACtD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,IAAI,QAAQ,CAAC,iDAAiD,EAAE;gBACrE,MAAM,EAAE,GAAG;aACZ,CAAC,CAAA;QACJ,CAAC;QACD,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAA;QAC1C,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,CAAA;QACjC,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;QAC1D,IAAI,CAAC,CAAC,MAAM,kBAAkB,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC;YACvD,OAAO,IAAI,QAAQ,CAAC,oBAAoB,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;QAC5D,CAAC;QAED,IAAI,OAA4B,CAAA;QAChC,IAAI,CAAC;YACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAwB,CAAA;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,QAAQ,CAAC,mBAAmB,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;QAC3D,CAAC;QAED,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;YACjB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,CAAC,CAAA;YACjD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,GAAG,GAAG,QAAQ,EAAE,CAAC;gBACvD,OAAO,IAAI,QAAQ,CAAC,6CAA6C,EAAE;oBACjE,MAAM,EAAE,GAAG;iBACZ,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;QAED,IAAI,CAAC;YACH,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACrB,MAAM,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;YACjC,CAAC;iBAAM,CAAC;gBACN,MAAM,eAAe,EAAE,CAAA;YACzB,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,IAAI,QAAQ,CACjB,kBAAkB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EACpE,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAA;QACH,CAAC;QAED,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE;YAChD,MAAM,EAAE,GAAG;YACX,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;SAChD,CAAC,CAAA;IACJ,CAAC,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -1,9 +1,12 @@
1
1
  {
2
2
  "name": "@sentroy-co/client-sdk",
3
- "version": "2.8.0",
4
- "description": "TypeScript SDK for the Sentroy platform — mail, storage, env vault + React components.",
3
+ "version": "2.12.0",
4
+ "description": "TypeScript SDK + CLI for the Sentroy platform — mail, storage, env vault + React components.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "sentroy": "./bin/sentroy.js"
9
+ },
7
10
  "exports": {
8
11
  ".": {
9
12
  "types": "./dist/index.d.ts",
@@ -39,6 +42,7 @@
39
42
  "files": [
40
43
  "dist",
41
44
  "src",
45
+ "bin",
42
46
  "AGENTS.md"
43
47
  ],
44
48
  "scripts": {
@@ -57,7 +61,9 @@
57
61
  "env",
58
62
  "vault",
59
63
  "secrets",
60
- "config"
64
+ "config",
65
+ "cli",
66
+ "dotenv"
61
67
  ],
62
68
  "repository": {
63
69
  "type": "git",
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Minimal .env parser + serializer used by the CLI.
3
+ *
4
+ * Format conventions (mirrors apps/core/components/admin/env-vault-content.tsx
5
+ * developer mode):
6
+ * - blank line resets pending description/public flag
7
+ * - `# @public` on its own line marks the next variable as browser-readable
8
+ * - `# any other text` becomes the next variable's description
9
+ * - `KEY=value` (unquoted)
10
+ * - `KEY="value with spaces"` (double-quoted; supports \n, \", \\ escapes)
11
+ * - `KEY='single quotes'` (single-quoted; literal)
12
+ * - `export KEY=value` (export prefix stripped)
13
+ *
14
+ * Anything else is reported as a parse error with the offending line number.
15
+ */
16
+
17
+ export interface DotenvEntry {
18
+ key: string
19
+ value: string
20
+ public: boolean
21
+ description: string | null
22
+ }
23
+
24
+ export interface DotenvParseResult {
25
+ entries: DotenvEntry[]
26
+ errors: { line: number; message: string }[]
27
+ }
28
+
29
+ const KEY_PATTERN = /^[A-Z_][A-Z0-9_]*$/
30
+
31
+ export function parseDotenv(text: string): DotenvParseResult {
32
+ const lines = text.split(/\r?\n/)
33
+ const entries: DotenvEntry[] = []
34
+ const errors: DotenvParseResult["errors"] = []
35
+ const seen = new Set<string>()
36
+
37
+ let pendingDescription: string[] = []
38
+ let pendingPublic = false
39
+
40
+ for (let i = 0; i < lines.length; i++) {
41
+ const raw = lines[i] ?? ""
42
+ const line = raw.trim()
43
+
44
+ if (line === "") {
45
+ pendingDescription = []
46
+ pendingPublic = false
47
+ continue
48
+ }
49
+
50
+ if (line.startsWith("#")) {
51
+ const body = line.slice(1).trim()
52
+ if (body === "@public") {
53
+ pendingPublic = true
54
+ } else if (body) {
55
+ pendingDescription.push(body)
56
+ }
57
+ continue
58
+ }
59
+
60
+ const work = line.startsWith("export ") ? line.slice(7).trimStart() : line
61
+ const eq = work.indexOf("=")
62
+ if (eq <= 0) {
63
+ errors.push({
64
+ line: i + 1,
65
+ message: "invalid syntax (expected KEY=value)",
66
+ })
67
+ pendingDescription = []
68
+ pendingPublic = false
69
+ continue
70
+ }
71
+
72
+ const key = work.slice(0, eq).trim()
73
+ let value = work.slice(eq + 1)
74
+
75
+ if (!KEY_PATTERN.test(key)) {
76
+ errors.push({
77
+ line: i + 1,
78
+ message: "key must match [A-Z_][A-Z0-9_]*",
79
+ })
80
+ pendingDescription = []
81
+ pendingPublic = false
82
+ continue
83
+ }
84
+
85
+ const trimmed = value.trim()
86
+ if (
87
+ (trimmed.startsWith('"') && trimmed.endsWith('"')) ||
88
+ (trimmed.startsWith("'") && trimmed.endsWith("'"))
89
+ ) {
90
+ value = trimmed.slice(1, -1)
91
+ if (trimmed.startsWith('"')) {
92
+ value = value
93
+ .replace(/\\n/g, "\n")
94
+ .replace(/\\"/g, '"')
95
+ .replace(/\\\\/g, "\\")
96
+ }
97
+ } else {
98
+ value = trimmed
99
+ }
100
+
101
+ if (seen.has(key)) {
102
+ errors.push({ line: i + 1, message: `duplicate key ${key}` })
103
+ pendingDescription = []
104
+ pendingPublic = false
105
+ continue
106
+ }
107
+ seen.add(key)
108
+
109
+ entries.push({
110
+ key,
111
+ value,
112
+ public: pendingPublic,
113
+ description:
114
+ pendingDescription.length > 0 ? pendingDescription.join(" ") : null,
115
+ })
116
+
117
+ pendingDescription = []
118
+ pendingPublic = false
119
+ }
120
+
121
+ return { entries, errors }
122
+ }
123
+
124
+ /**
125
+ * Inverse of parseDotenv — emit a .env document that round-trips through it.
126
+ * Quotes values that contain whitespace or shell-special characters.
127
+ */
128
+ export function serializeDotenv(entries: DotenvEntry[]): string {
129
+ const blocks: string[] = []
130
+ for (const e of entries) {
131
+ const parts: string[] = []
132
+ if (e.description) parts.push(`# ${e.description}`)
133
+ if (e.public) parts.push("# @public")
134
+ const value = e.value
135
+ const needsQuote = /[\s"'#$`\\]/.test(value) || value === ""
136
+ const escaped = needsQuote
137
+ ? `"${value
138
+ .replace(/\\/g, "\\\\")
139
+ .replace(/"/g, '\\"')
140
+ .replace(/\n/g, "\\n")}"`
141
+ : value
142
+ parts.push(`${e.key}=${escaped}`)
143
+ blocks.push(parts.join("\n"))
144
+ }
145
+ return blocks.join("\n\n") + (blocks.length > 0 ? "\n" : "")
146
+ }