cf-envsync 0.1.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/README.md +518 -0
- package/dist/index.js +14635 -0
- package/package.json +40 -0
- package/src/define-config.ts +30 -0
- package/src/types/config.ts +65 -0
- package/src/types/env.ts +50 -0
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cf-envsync",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Sync .env files to Cloudflare Workers secrets, .dev.vars, and more",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": "./src/define-config.ts"
|
|
8
|
+
},
|
|
9
|
+
"bin": {
|
|
10
|
+
"envsync": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"src/define-config.ts",
|
|
15
|
+
"src/types"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"dev": "bun run src/index.ts",
|
|
19
|
+
"build": "bun build src/index.ts --outdir dist --target node --external jiti",
|
|
20
|
+
"prepublishOnly": "bun run build",
|
|
21
|
+
"test": "bun test"
|
|
22
|
+
},
|
|
23
|
+
"peerDependencies": {
|
|
24
|
+
"wrangler": ">=3"
|
|
25
|
+
},
|
|
26
|
+
"peerDependenciesMeta": {
|
|
27
|
+
"wrangler": {
|
|
28
|
+
"optional": true
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@dotenvx/dotenvx": "^1.52.0",
|
|
33
|
+
"citty": "^0.2.1",
|
|
34
|
+
"consola": "^3.4.2",
|
|
35
|
+
"jiti": "^2.4.2"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/node": "^22"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { EnvSyncConfig } from "./types/config.ts";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Define envsync configuration with full type checking and editor support.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* // envsync.config.ts
|
|
9
|
+
* import { defineConfig } from "cf-envsync";
|
|
10
|
+
*
|
|
11
|
+
* export default defineConfig({
|
|
12
|
+
* environments: ["local", "staging", "production"],
|
|
13
|
+
* envFiles: { pattern: ".env.{env}", local: ".env.local", perApp: true },
|
|
14
|
+
* encryption: "dotenvx",
|
|
15
|
+
* apps: {
|
|
16
|
+
* api: {
|
|
17
|
+
* path: "apps/api",
|
|
18
|
+
* workers: { staging: "my-api-staging", production: "my-api" },
|
|
19
|
+
* secrets: ["DATABASE_URL"],
|
|
20
|
+
* vars: ["API_URL"],
|
|
21
|
+
* },
|
|
22
|
+
* },
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export function defineConfig(config: EnvSyncConfig): EnvSyncConfig {
|
|
27
|
+
return config;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type { EnvSyncConfig, AppConfig } from "./types/config.ts";
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/** Root configuration (envsync.json) */
|
|
2
|
+
export interface EnvSyncConfig {
|
|
3
|
+
/** Supported environments */
|
|
4
|
+
environments: string[];
|
|
5
|
+
|
|
6
|
+
/** .env file mapping rules */
|
|
7
|
+
envFiles: {
|
|
8
|
+
/** Pattern for env files, e.g. ".env.{env}". local falls back to ".env" */
|
|
9
|
+
pattern: string;
|
|
10
|
+
/** Per-developer override file (gitignored), only for local env */
|
|
11
|
+
local: string;
|
|
12
|
+
/** Allow per-app .env.{env} files */
|
|
13
|
+
perApp: boolean;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/** Encryption method */
|
|
17
|
+
encryption: "dotenvx" | "none";
|
|
18
|
+
|
|
19
|
+
/** App definitions */
|
|
20
|
+
apps: Record<string, AppConfig>;
|
|
21
|
+
|
|
22
|
+
/** Shared secret keys (same value across multiple apps within an env) */
|
|
23
|
+
shared?: string[];
|
|
24
|
+
|
|
25
|
+
/** Per-developer local override configuration */
|
|
26
|
+
local?: {
|
|
27
|
+
/** Keys that each developer must set locally */
|
|
28
|
+
overrides?: string[];
|
|
29
|
+
/** Per-app developer override keys */
|
|
30
|
+
perApp?: Record<string, string[]>;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Configuration for a single app/worker */
|
|
35
|
+
export interface AppConfig {
|
|
36
|
+
/** Path to app directory relative to project root */
|
|
37
|
+
path: string;
|
|
38
|
+
/** Cloudflare Worker names per environment */
|
|
39
|
+
workers: Record<string, string>;
|
|
40
|
+
/** Secret keys for this app (pushed via wrangler secret) */
|
|
41
|
+
secrets?: string[];
|
|
42
|
+
/** Var keys for this app (non-secret env vars) */
|
|
43
|
+
vars?: string[];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Resolved config after defaults and path resolution */
|
|
47
|
+
export interface ResolvedConfig {
|
|
48
|
+
/** Absolute path to project root */
|
|
49
|
+
projectRoot: string;
|
|
50
|
+
/** Original config */
|
|
51
|
+
raw: EnvSyncConfig;
|
|
52
|
+
/** Available environments */
|
|
53
|
+
environments: string[];
|
|
54
|
+
/** Resolved app configs */
|
|
55
|
+
apps: Record<string, ResolvedAppConfig>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface ResolvedAppConfig extends AppConfig {
|
|
59
|
+
/** App name (key from config) */
|
|
60
|
+
name: string;
|
|
61
|
+
/** Absolute path to app directory */
|
|
62
|
+
absolutePath: string;
|
|
63
|
+
/** All keys this app needs (secrets + vars + local overrides) */
|
|
64
|
+
allKeys: string[];
|
|
65
|
+
}
|
package/src/types/env.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/** Simple key-value env map */
|
|
2
|
+
export type EnvMap = Record<string, string>;
|
|
3
|
+
|
|
4
|
+
/** An env entry with source tracking */
|
|
5
|
+
export interface EnvEntry {
|
|
6
|
+
key: string;
|
|
7
|
+
value: string;
|
|
8
|
+
/** Where this value came from (file path or description) */
|
|
9
|
+
source: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Diff between two env states */
|
|
13
|
+
export interface DiffEntry {
|
|
14
|
+
key: string;
|
|
15
|
+
status: "added" | "removed" | "changed" | "unchanged";
|
|
16
|
+
localValue?: string;
|
|
17
|
+
remoteValue?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Diff between two environments */
|
|
21
|
+
export interface EnvDiffEntry {
|
|
22
|
+
key: string;
|
|
23
|
+
status: "match" | "differs" | "missing-left" | "missing-right";
|
|
24
|
+
leftValue?: string;
|
|
25
|
+
rightValue?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Validation result for a single app in one environment */
|
|
29
|
+
export interface ValidationResult {
|
|
30
|
+
app: string;
|
|
31
|
+
environment: string;
|
|
32
|
+
/** Keys present in .env.example but missing from resolved env */
|
|
33
|
+
missingKeys: string[];
|
|
34
|
+
/** Keys present in resolved env but not in .env.example */
|
|
35
|
+
extraKeys: string[];
|
|
36
|
+
/** Per-dev override keys that are missing from .env.local */
|
|
37
|
+
missingOverrides: string[];
|
|
38
|
+
/** Overall pass/fail */
|
|
39
|
+
valid: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Result of loading and merging env layers */
|
|
43
|
+
export interface ResolvedEnv {
|
|
44
|
+
/** Final merged key-value pairs */
|
|
45
|
+
entries: EnvEntry[];
|
|
46
|
+
/** Map form for easy access */
|
|
47
|
+
map: EnvMap;
|
|
48
|
+
/** Sources that were loaded (in order) */
|
|
49
|
+
layers: string[];
|
|
50
|
+
}
|