@sentroy-co/client-sdk 2.6.4 → 2.9.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/AGENTS.md +138 -2
- package/README.md +44 -1
- package/bin/sentroy.js +4 -0
- package/dist/cli/dotenv.d.ts +35 -0
- package/dist/cli/dotenv.d.ts.map +1 -0
- package/dist/cli/dotenv.js +125 -0
- package/dist/cli/dotenv.js.map +1 -0
- package/dist/cli/env.d.ts +11 -0
- package/dist/cli/env.d.ts.map +1 -0
- package/dist/cli/env.js +331 -0
- package/dist/cli/env.js.map +1 -0
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +105 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/vault/index.d.ts +73 -0
- package/dist/vault/index.d.ts.map +1 -0
- package/dist/vault/index.js +169 -0
- package/dist/vault/index.js.map +1 -0
- package/dist/vault/react.d.ts +27 -0
- package/dist/vault/react.d.ts.map +1 -0
- package/dist/vault/react.js +73 -0
- package/dist/vault/react.js.map +1 -0
- package/package.json +23 -3
- package/src/cli/dotenv.ts +146 -0
- package/src/cli/env.ts +402 -0
- package/src/cli/index.ts +122 -0
- package/src/vault/index.ts +198 -0
- package/src/vault/react.tsx +125 -0
package/AGENTS.md
CHANGED
|
@@ -675,11 +675,147 @@ import {
|
|
|
675
675
|
} from "@sentroy-co/client-sdk/react"
|
|
676
676
|
```
|
|
677
677
|
|
|
678
|
+
## Env Vault (`@sentroy-co/client-sdk/vault` + `/vault/react`)
|
|
679
|
+
|
|
680
|
+
Sentroy Env Vault — centralized runtime env management. Bootstrap is a
|
|
681
|
+
single env (`SENTROY_ENV_API_KEY`); the rest of your config lives in
|
|
682
|
+
the dashboard at `vault.sentroy.com`. Changing a variable does NOT
|
|
683
|
+
require an app rebuild — the next read picks up the new value once the
|
|
684
|
+
in-memory cache TTL elapses (5 min default).
|
|
685
|
+
|
|
686
|
+
This module is intentionally **separate** from the main `Sentroy`
|
|
687
|
+
client. They use different auth namespaces:
|
|
688
|
+
|
|
689
|
+
| Surface | Token format | Scope |
|
|
690
|
+
|---|---|---|
|
|
691
|
+
| `Sentroy` (mail/storage) | `stk_...` | per-company access token |
|
|
692
|
+
| Env Vault | `stk_env_...` | per-(project, environment) bootstrap token |
|
|
693
|
+
|
|
694
|
+
### Server: `getEnv()`
|
|
695
|
+
|
|
696
|
+
```ts
|
|
697
|
+
import {
|
|
698
|
+
configureEnvClient, // optional one-shot config
|
|
699
|
+
getEnv, // async, undefined if missing
|
|
700
|
+
getEnvOrThrow, // async, throws if missing
|
|
701
|
+
getAllEnvs, // bulk: { KEY: value, ... }
|
|
702
|
+
getPublicEnvs, // bulk: only `public: true` variables
|
|
703
|
+
preloadEnv, // eager hydrate at process boot
|
|
704
|
+
refreshEnvCache, // manual invalidation hook
|
|
705
|
+
setEnvCacheTTL, // runtime TTL override (seconds)
|
|
706
|
+
} from "@sentroy-co/client-sdk/vault"
|
|
707
|
+
|
|
708
|
+
// Optional — defaults pull from process.env
|
|
709
|
+
configureEnvClient({
|
|
710
|
+
baseUrl: "https://sentroy.com", // or self-hosted Sentroy URL
|
|
711
|
+
apiKey: process.env.SENTROY_ENV_API_KEY, // default
|
|
712
|
+
ttlSeconds: 300, // 5 min
|
|
713
|
+
timeoutMs: 5000,
|
|
714
|
+
})
|
|
715
|
+
|
|
716
|
+
await preloadEnv() // optional: fail-fast if token invalid
|
|
717
|
+
|
|
718
|
+
const dbUrl = await getEnv("DATABASE_URL") // string | undefined
|
|
719
|
+
const turn = await getEnvOrThrow("TURNSTILE_SECRET") // string
|
|
720
|
+
const all = await getAllEnvs() // includes private
|
|
721
|
+
const pub = await getPublicEnvs() // public:true only
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
### React: SSR-injected provider + hook
|
|
725
|
+
|
|
726
|
+
```tsx
|
|
727
|
+
// app/layout.tsx (server component)
|
|
728
|
+
import { getPublicEnvs } from "@sentroy-co/client-sdk/vault"
|
|
729
|
+
import { EnvProvider } from "@sentroy-co/client-sdk/vault/react"
|
|
730
|
+
|
|
731
|
+
export default async function RootLayout({ children }) {
|
|
732
|
+
const envs = await getPublicEnvs() // public:true only — never leak secrets
|
|
733
|
+
return (
|
|
734
|
+
<html>
|
|
735
|
+
<body>
|
|
736
|
+
<EnvProvider envs={envs}>{children}</EnvProvider>
|
|
737
|
+
</body>
|
|
738
|
+
</html>
|
|
739
|
+
)
|
|
740
|
+
}
|
|
741
|
+
```
|
|
742
|
+
|
|
743
|
+
```tsx
|
|
744
|
+
// any "use client" component
|
|
745
|
+
"use client"
|
|
746
|
+
import { useEnv, useAllEnvs, useEnvRefresh } from "@sentroy-co/client-sdk/vault/react"
|
|
747
|
+
|
|
748
|
+
function CaptchaWidget() {
|
|
749
|
+
const siteKey = useEnv("TURNSTILE_SITE_KEY") // string | undefined
|
|
750
|
+
if (!siteKey) return null
|
|
751
|
+
return <Turnstile siteKey={siteKey} />
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
function ConfigPanel() {
|
|
755
|
+
const all = useAllEnvs() // Record<string, string> — public envs only
|
|
756
|
+
const { refresh, loading } = useEnvRefresh()
|
|
757
|
+
return <button onClick={refresh} disabled={loading}>Refresh config</button>
|
|
758
|
+
}
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
### `EnvProvider` props
|
|
762
|
+
|
|
763
|
+
| Prop | Type | Default | Notes |
|
|
764
|
+
|---|---|---|---|
|
|
765
|
+
| `envs` | `Record<string, string>` | required | SSR-fetched public envs |
|
|
766
|
+
| `refreshUrl` | `string` | `/api/env-vault/public` | Endpoint for client polling |
|
|
767
|
+
| `apiKey` | `string` | `process.env.NEXT_PUBLIC_SENTROY_ENV_API_KEY` | Bearer token for browser polling |
|
|
768
|
+
| `refreshIntervalMs` | `number` | `300000` (5 min) | `0` to disable polling |
|
|
769
|
+
|
|
770
|
+
### Security notes
|
|
771
|
+
|
|
772
|
+
- `useEnv()` only ever returns variables marked `public: true` in the dashboard. Server-only secrets stay server-side.
|
|
773
|
+
- The provider's polling is best-effort; network failures keep the previous values (fail-soft).
|
|
774
|
+
- The bootstrap token is per-(project, environment). A `prod` token cannot read `staging` and vice versa.
|
|
775
|
+
- Variable values are AES-256-GCM encrypted at rest in the Sentroy vault DB. Decryption happens server-side just before the fetch endpoint streams the response.
|
|
776
|
+
|
|
777
|
+
### CLI (`sentroy env ...`)
|
|
778
|
+
|
|
779
|
+
The package ships a `sentroy` binary. After `npm install` (or `npm install -g`) it's available on `PATH`; `npx sentroy ...` works without a global install.
|
|
780
|
+
|
|
781
|
+
Auth is the same `SENTROY_ENV_API_KEY` used by `getEnv()` (or pass `--token=stk_env_...`). Base URL defaults to `https://sentroy.com` (override with `SENTROY_ENV_API_URL` or `--url=`). The token's (project, environment) scope is implicit — never specified on the CLI.
|
|
782
|
+
|
|
783
|
+
```bash
|
|
784
|
+
# Push a local file to the vault. Without --delete-missing it's upsert-only.
|
|
785
|
+
# With --delete-missing it's a full sync — any vault key not in the file
|
|
786
|
+
# is removed (CLI prompts for confirmation interactively).
|
|
787
|
+
sentroy env push .env.production --delete-missing
|
|
788
|
+
sentroy env push .env.production --dry-run # show diff, no writes
|
|
789
|
+
|
|
790
|
+
# Diff local vs vault without writing.
|
|
791
|
+
sentroy env diff .env.production --delete-missing
|
|
792
|
+
|
|
793
|
+
# Pull the vault into a local file. Refuses to overwrite without --force.
|
|
794
|
+
sentroy env pull .env.staging --force
|
|
795
|
+
|
|
796
|
+
# List keys (or KEY=value with --values; only public-flagged with --public-only).
|
|
797
|
+
sentroy env list
|
|
798
|
+
sentroy env list --values
|
|
799
|
+
sentroy env list --public-only
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
`push` requires the token to have `write` permission (toggle when generating the token in the dashboard). `pull`, `list`, and `diff` only need `read`.
|
|
803
|
+
|
|
804
|
+
The CLI parses the same `.env` flavour as the dashboard's developer mode:
|
|
805
|
+
|
|
806
|
+
- blank line resets pending description / public flag
|
|
807
|
+
- `# any comment` above a key becomes the variable's description
|
|
808
|
+
- `# @public` on its own line marks the next key as browser-readable
|
|
809
|
+
- `KEY="quoted with spaces"` and `KEY='single quoted'` both supported
|
|
810
|
+
- `export KEY=value` prefix is stripped
|
|
811
|
+
|
|
812
|
+
REST endpoint behind `push`: `POST /api/env-vault/push` with body `{ entries: [{key, value, public?, description?}], deleteMissing?: boolean }` and `Authorization: Bearer stk_env_...`. Response: `{ added, updated, unchanged, deleted, total, project, environment }`. Each insert/update/delete writes one audit log entry (checksum, no plaintext) tagged `source: "cli-push"`.
|
|
813
|
+
|
|
678
814
|
## Requirements
|
|
679
815
|
|
|
680
816
|
- Node.js 18+ (uses native `fetch`)
|
|
681
|
-
- React 18+ (only if you import from `/react`)
|
|
682
|
-
- Tailwind CSS in the host app (only for React components)
|
|
817
|
+
- React 18+ (only if you import from `/react` or `/vault/react`)
|
|
818
|
+
- Tailwind CSS in the host app (only for React UI components like `<MediaManager />`)
|
|
683
819
|
|
|
684
820
|
## Raw URL — for LLM/agent context windows
|
|
685
821
|
|
package/README.md
CHANGED
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
|
|
34
34
|
- **Mail** — verified domains, mailboxes, multi-language templates, IMAP-backed inbox, transactional and bulk send, suppressions, webhooks, audience lists, deliverability logs.
|
|
35
35
|
- **Storage** — isolated buckets, multipart uploads, image and media transformations, signed download URLs.
|
|
36
|
-
- **
|
|
36
|
+
- **Env Vault** — runtime env variable management (`@sentroy-co/client-sdk/vault`) — change a value in the dashboard, your app picks it up on the next read; no rebuild.
|
|
37
|
+
- **React drop-ins** — `<MediaManager />`, `<MediaManagerTrigger />` and `<EnvProvider>` / `useEnv()` (`@sentroy-co/client-sdk/react` + `@sentroy-co/client-sdk/vault/react`).
|
|
37
38
|
- **One client, two backends** — point at `https://sentroy.com` for the hosted platform, or your own deployment for self-hosted. Same API, same types.
|
|
38
39
|
|
|
39
40
|
## Install
|
|
@@ -77,6 +78,48 @@ console.log(media.url) // signed URL, served from the CDN
|
|
|
77
78
|
|
|
78
79
|
That's the smallest useful surface. Every other resource (`domains`, `mailboxes`, `templates`, `inbox`, `audience`, `webhooks`, `suppressions`, `logs`, `buckets`, `media`) follows the same `sentroy.<resource>.<verb>(...)` shape with full TypeScript types.
|
|
79
80
|
|
|
81
|
+
## Env Vault
|
|
82
|
+
|
|
83
|
+
Manage your env vars in the dashboard at [vault.sentroy.com](https://vault.sentroy.com), bootstrap your deploy with one token, and read values via a typed helper — no rebuild on change.
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
// server side
|
|
87
|
+
import { getEnv, getEnvOrThrow, preloadEnv } from "@sentroy-co/client-sdk/vault"
|
|
88
|
+
|
|
89
|
+
await preloadEnv() // optional fail-fast at boot
|
|
90
|
+
const dbUrl = await getEnv("DATABASE_URL")
|
|
91
|
+
const turnstile = await getEnvOrThrow("BETTER_AUTH_TURNSTILE_SECRET")
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
// React: SSR-injected provider + hook (no FOUC)
|
|
96
|
+
import { getPublicEnvs } from "@sentroy-co/client-sdk/vault"
|
|
97
|
+
import { EnvProvider, useEnv } from "@sentroy-co/client-sdk/vault/react"
|
|
98
|
+
|
|
99
|
+
// app/layout.tsx (server)
|
|
100
|
+
const envs = await getPublicEnvs()
|
|
101
|
+
return <EnvProvider envs={envs}>{children}</EnvProvider>
|
|
102
|
+
|
|
103
|
+
// any "use client" component
|
|
104
|
+
const siteKey = useEnv("TURNSTILE_SITE_KEY")
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Bootstrap is a single env: `SENTROY_ENV_API_KEY`. Public/private split is enforced server-side — the React hook only ever sees `public: true` variables. Full reference at [docs.sentroy.com/env-vault](https://docs.sentroy.com/env-vault).
|
|
108
|
+
|
|
109
|
+
### CLI
|
|
110
|
+
|
|
111
|
+
The package ships a `sentroy` CLI for syncing local `.env` files to the vault — useful for build pipelines and onboarding.
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
# Use SENTROY_ENV_API_KEY (or pass --token=stk_env_...)
|
|
115
|
+
npx sentroy env push .env.production --delete-missing
|
|
116
|
+
npx sentroy env diff .env.production
|
|
117
|
+
npx sentroy env pull .env.staging --force
|
|
118
|
+
npx sentroy env list --values --public-only
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The token's (project, environment) scope is implicit. `--delete-missing` makes the push a full sync — keys not in the local file are removed from the vault. The token must have `write` permission for `push`; everything else only needs `read`.
|
|
122
|
+
|
|
80
123
|
## Self-hosted vs hosted
|
|
81
124
|
|
|
82
125
|
The SDK is identical in both modes. Only `baseUrl` changes:
|
package/bin/sentroy.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
export interface DotenvEntry {
|
|
17
|
+
key: string;
|
|
18
|
+
value: string;
|
|
19
|
+
public: boolean;
|
|
20
|
+
description: string | null;
|
|
21
|
+
}
|
|
22
|
+
export interface DotenvParseResult {
|
|
23
|
+
entries: DotenvEntry[];
|
|
24
|
+
errors: {
|
|
25
|
+
line: number;
|
|
26
|
+
message: string;
|
|
27
|
+
}[];
|
|
28
|
+
}
|
|
29
|
+
export declare function parseDotenv(text: string): DotenvParseResult;
|
|
30
|
+
/**
|
|
31
|
+
* Inverse of parseDotenv — emit a .env document that round-trips through it.
|
|
32
|
+
* Quotes values that contain whitespace or shell-special characters.
|
|
33
|
+
*/
|
|
34
|
+
export declare function serializeDotenv(entries: DotenvEntry[]): string;
|
|
35
|
+
//# sourceMappingURL=dotenv.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dotenv.d.ts","sourceRoot":"","sources":["../../src/cli/dotenv.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,OAAO,CAAA;IACf,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAC5C;AAID,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CA2F3D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,CAkB9D"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Minimal .env parser + serializer used by the CLI.
|
|
4
|
+
*
|
|
5
|
+
* Format conventions (mirrors apps/core/components/admin/env-vault-content.tsx
|
|
6
|
+
* developer mode):
|
|
7
|
+
* - blank line resets pending description/public flag
|
|
8
|
+
* - `# @public` on its own line marks the next variable as browser-readable
|
|
9
|
+
* - `# any other text` becomes the next variable's description
|
|
10
|
+
* - `KEY=value` (unquoted)
|
|
11
|
+
* - `KEY="value with spaces"` (double-quoted; supports \n, \", \\ escapes)
|
|
12
|
+
* - `KEY='single quotes'` (single-quoted; literal)
|
|
13
|
+
* - `export KEY=value` (export prefix stripped)
|
|
14
|
+
*
|
|
15
|
+
* Anything else is reported as a parse error with the offending line number.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.parseDotenv = parseDotenv;
|
|
19
|
+
exports.serializeDotenv = serializeDotenv;
|
|
20
|
+
const KEY_PATTERN = /^[A-Z_][A-Z0-9_]*$/;
|
|
21
|
+
function parseDotenv(text) {
|
|
22
|
+
const lines = text.split(/\r?\n/);
|
|
23
|
+
const entries = [];
|
|
24
|
+
const errors = [];
|
|
25
|
+
const seen = new Set();
|
|
26
|
+
let pendingDescription = [];
|
|
27
|
+
let pendingPublic = false;
|
|
28
|
+
for (let i = 0; i < lines.length; i++) {
|
|
29
|
+
const raw = lines[i] ?? "";
|
|
30
|
+
const line = raw.trim();
|
|
31
|
+
if (line === "") {
|
|
32
|
+
pendingDescription = [];
|
|
33
|
+
pendingPublic = false;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (line.startsWith("#")) {
|
|
37
|
+
const body = line.slice(1).trim();
|
|
38
|
+
if (body === "@public") {
|
|
39
|
+
pendingPublic = true;
|
|
40
|
+
}
|
|
41
|
+
else if (body) {
|
|
42
|
+
pendingDescription.push(body);
|
|
43
|
+
}
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const work = line.startsWith("export ") ? line.slice(7).trimStart() : line;
|
|
47
|
+
const eq = work.indexOf("=");
|
|
48
|
+
if (eq <= 0) {
|
|
49
|
+
errors.push({
|
|
50
|
+
line: i + 1,
|
|
51
|
+
message: "invalid syntax (expected KEY=value)",
|
|
52
|
+
});
|
|
53
|
+
pendingDescription = [];
|
|
54
|
+
pendingPublic = false;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const key = work.slice(0, eq).trim();
|
|
58
|
+
let value = work.slice(eq + 1);
|
|
59
|
+
if (!KEY_PATTERN.test(key)) {
|
|
60
|
+
errors.push({
|
|
61
|
+
line: i + 1,
|
|
62
|
+
message: "key must match [A-Z_][A-Z0-9_]*",
|
|
63
|
+
});
|
|
64
|
+
pendingDescription = [];
|
|
65
|
+
pendingPublic = false;
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const trimmed = value.trim();
|
|
69
|
+
if ((trimmed.startsWith('"') && trimmed.endsWith('"')) ||
|
|
70
|
+
(trimmed.startsWith("'") && trimmed.endsWith("'"))) {
|
|
71
|
+
value = trimmed.slice(1, -1);
|
|
72
|
+
if (trimmed.startsWith('"')) {
|
|
73
|
+
value = value
|
|
74
|
+
.replace(/\\n/g, "\n")
|
|
75
|
+
.replace(/\\"/g, '"')
|
|
76
|
+
.replace(/\\\\/g, "\\");
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
value = trimmed;
|
|
81
|
+
}
|
|
82
|
+
if (seen.has(key)) {
|
|
83
|
+
errors.push({ line: i + 1, message: `duplicate key ${key}` });
|
|
84
|
+
pendingDescription = [];
|
|
85
|
+
pendingPublic = false;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
seen.add(key);
|
|
89
|
+
entries.push({
|
|
90
|
+
key,
|
|
91
|
+
value,
|
|
92
|
+
public: pendingPublic,
|
|
93
|
+
description: pendingDescription.length > 0 ? pendingDescription.join(" ") : null,
|
|
94
|
+
});
|
|
95
|
+
pendingDescription = [];
|
|
96
|
+
pendingPublic = false;
|
|
97
|
+
}
|
|
98
|
+
return { entries, errors };
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Inverse of parseDotenv — emit a .env document that round-trips through it.
|
|
102
|
+
* Quotes values that contain whitespace or shell-special characters.
|
|
103
|
+
*/
|
|
104
|
+
function serializeDotenv(entries) {
|
|
105
|
+
const blocks = [];
|
|
106
|
+
for (const e of entries) {
|
|
107
|
+
const parts = [];
|
|
108
|
+
if (e.description)
|
|
109
|
+
parts.push(`# ${e.description}`);
|
|
110
|
+
if (e.public)
|
|
111
|
+
parts.push("# @public");
|
|
112
|
+
const value = e.value;
|
|
113
|
+
const needsQuote = /[\s"'#$`\\]/.test(value) || value === "";
|
|
114
|
+
const escaped = needsQuote
|
|
115
|
+
? `"${value
|
|
116
|
+
.replace(/\\/g, "\\\\")
|
|
117
|
+
.replace(/"/g, '\\"')
|
|
118
|
+
.replace(/\n/g, "\\n")}"`
|
|
119
|
+
: value;
|
|
120
|
+
parts.push(`${e.key}=${escaped}`);
|
|
121
|
+
blocks.push(parts.join("\n"));
|
|
122
|
+
}
|
|
123
|
+
return blocks.join("\n\n") + (blocks.length > 0 ? "\n" : "");
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=dotenv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dotenv.js","sourceRoot":"","sources":["../../src/cli/dotenv.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `sentroy env <subcommand>` — vault sync from a local .env file.
|
|
3
|
+
*
|
|
4
|
+
* The token's (project, environment) scope is implicit; the CLI never
|
|
5
|
+
* asks for either since it can't change them.
|
|
6
|
+
*/
|
|
7
|
+
export declare function cmdPush(args: string[]): Promise<void>;
|
|
8
|
+
export declare function cmdPull(args: string[]): Promise<void>;
|
|
9
|
+
export declare function cmdList(args: string[]): Promise<void>;
|
|
10
|
+
export declare function cmdDiff(args: string[]): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/cli/env.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAgMH,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgF3D;AAID,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB3D;AAID,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmB3D;AAID,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAyB3D"}
|