@devorama/secrets 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.
@@ -0,0 +1,54 @@
1
+ // src/pull.ts
2
+ import { writeFileSync } from "fs";
3
+ import { execa } from "execa";
4
+ async function pull(options) {
5
+ const { service, envName, output, dryRun = false, verbose = false } = options;
6
+ const { stdout } = await execa("chamber", ["env", `${service}/${envName}`]);
7
+ if (verbose) console.log(`Retrieved variables from ${service}/${envName}`);
8
+ if (dryRun) {
9
+ console.log(`[dry-run] Would write to ${output}:
10
+ ${stdout}`);
11
+ return;
12
+ }
13
+ writeFileSync(output, stdout, "utf-8");
14
+ const count = stdout.split("\n").filter(Boolean).length;
15
+ console.log(`\u2713 Pulled ${count} variables to ${output}`);
16
+ }
17
+
18
+ // src/push.ts
19
+ import { readFileSync } from "fs";
20
+ import { execa as execa2 } from "execa";
21
+ function parseEnvContent(content) {
22
+ const result = {};
23
+ for (const line of content.split("\n")) {
24
+ const trimmed = line.trim();
25
+ if (!trimmed || trimmed.startsWith("#")) continue;
26
+ const idx = trimmed.indexOf("=");
27
+ if (idx === -1) continue;
28
+ const key = trimmed.slice(0, idx).trim();
29
+ const raw = trimmed.slice(idx + 1).trim();
30
+ result[key] = raw.replace(/^["']|["']$/g, "");
31
+ }
32
+ return result;
33
+ }
34
+ async function push(options) {
35
+ const { envFile, service, envName, dryRun = false, verbose = false } = options;
36
+ const content = readFileSync(envFile, "utf-8");
37
+ const entries = Object.entries(parseEnvContent(content));
38
+ if (verbose) console.log(`Found ${entries.length} variables in ${envFile}`);
39
+ for (const [key, value] of entries) {
40
+ if (verbose) console.log(` ${dryRun ? "[dry-run] " : ""}${key}`);
41
+ if (!dryRun) {
42
+ await execa2("chamber", ["write", `${service}/${envName}`, key, value]);
43
+ }
44
+ }
45
+ console.log(
46
+ `\u2713 ${dryRun ? "[dry-run] " : ""}Pushed ${entries.length} variables to ${service}/${envName}`
47
+ );
48
+ }
49
+
50
+ export {
51
+ pull,
52
+ push
53
+ };
54
+ //# sourceMappingURL=chunk-UBFSRMBE.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pull.ts","../src/push.ts"],"sourcesContent":["import { writeFileSync } from 'node:fs'\nimport { execa } from 'execa'\n\nexport interface PullOptions {\n service: string\n envName: string\n output: string\n dryRun?: boolean\n verbose?: boolean\n}\n\nexport async function pull(options: PullOptions): Promise<void> {\n const { service, envName, output, dryRun = false, verbose = false } = options\n\n const { stdout } = await execa('chamber', ['env', `${service}/${envName}`])\n\n if (verbose) console.log(`Retrieved variables from ${service}/${envName}`)\n\n if (dryRun) {\n console.log(`[dry-run] Would write to ${output}:\\n${stdout}`)\n return\n }\n\n writeFileSync(output, stdout, 'utf-8')\n const count = stdout.split('\\n').filter(Boolean).length\n console.log(`✓ Pulled ${count} variables to ${output}`)\n}\n","import { readFileSync } from 'node:fs'\nimport { execa } from 'execa'\n\nexport interface PushOptions {\n envFile: string\n service: string\n envName: string\n dryRun?: boolean\n verbose?: boolean\n}\n\nfunction parseEnvContent(content: string): Record<string, string> {\n const result: Record<string, string> = {}\n for (const line of content.split('\\n')) {\n const trimmed = line.trim()\n if (!trimmed || trimmed.startsWith('#')) continue\n const idx = trimmed.indexOf('=')\n if (idx === -1) continue\n const key = trimmed.slice(0, idx).trim()\n const raw = trimmed.slice(idx + 1).trim()\n result[key] = raw.replace(/^[\"']|[\"']$/g, '')\n }\n return result\n}\n\nexport async function push(options: PushOptions): Promise<void> {\n const { envFile, service, envName, dryRun = false, verbose = false } = options\n const content = readFileSync(envFile, 'utf-8')\n const entries = Object.entries(parseEnvContent(content))\n\n if (verbose) console.log(`Found ${entries.length} variables in ${envFile}`)\n\n for (const [key, value] of entries) {\n if (verbose) console.log(` ${dryRun ? '[dry-run] ' : ''}${key}`)\n if (!dryRun) {\n await execa('chamber', ['write', `${service}/${envName}`, key, value])\n }\n }\n\n console.log(\n `✓ ${dryRun ? '[dry-run] ' : ''}Pushed ${entries.length} variables to ${service}/${envName}`\n )\n}\n"],"mappings":";AAAA,SAAS,qBAAqB;AAC9B,SAAS,aAAa;AAUtB,eAAsB,KAAK,SAAqC;AAC9D,QAAM,EAAE,SAAS,SAAS,QAAQ,SAAS,OAAO,UAAU,MAAM,IAAI;AAEtE,QAAM,EAAE,OAAO,IAAI,MAAM,MAAM,WAAW,CAAC,OAAO,GAAG,OAAO,IAAI,OAAO,EAAE,CAAC;AAE1E,MAAI,QAAS,SAAQ,IAAI,4BAA4B,OAAO,IAAI,OAAO,EAAE;AAEzE,MAAI,QAAQ;AACV,YAAQ,IAAI,4BAA4B,MAAM;AAAA,EAAM,MAAM,EAAE;AAC5D;AAAA,EACF;AAEA,gBAAc,QAAQ,QAAQ,OAAO;AACrC,QAAM,QAAQ,OAAO,MAAM,IAAI,EAAE,OAAO,OAAO,EAAE;AACjD,UAAQ,IAAI,iBAAY,KAAK,iBAAiB,MAAM,EAAE;AACxD;;;AC1BA,SAAS,oBAAoB;AAC7B,SAAS,SAAAA,cAAa;AAUtB,SAAS,gBAAgB,SAAyC;AAChE,QAAM,SAAiC,CAAC;AACxC,aAAW,QAAQ,QAAQ,MAAM,IAAI,GAAG;AACtC,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,WAAW,QAAQ,WAAW,GAAG,EAAG;AACzC,UAAM,MAAM,QAAQ,QAAQ,GAAG;AAC/B,QAAI,QAAQ,GAAI;AAChB,UAAM,MAAM,QAAQ,MAAM,GAAG,GAAG,EAAE,KAAK;AACvC,UAAM,MAAM,QAAQ,MAAM,MAAM,CAAC,EAAE,KAAK;AACxC,WAAO,GAAG,IAAI,IAAI,QAAQ,gBAAgB,EAAE;AAAA,EAC9C;AACA,SAAO;AACT;AAEA,eAAsB,KAAK,SAAqC;AAC9D,QAAM,EAAE,SAAS,SAAS,SAAS,SAAS,OAAO,UAAU,MAAM,IAAI;AACvE,QAAM,UAAU,aAAa,SAAS,OAAO;AAC7C,QAAM,UAAU,OAAO,QAAQ,gBAAgB,OAAO,CAAC;AAEvD,MAAI,QAAS,SAAQ,IAAI,SAAS,QAAQ,MAAM,iBAAiB,OAAO,EAAE;AAE1E,aAAW,CAAC,KAAK,KAAK,KAAK,SAAS;AAClC,QAAI,QAAS,SAAQ,IAAI,KAAK,SAAS,eAAe,EAAE,GAAG,GAAG,EAAE;AAChE,QAAI,CAAC,QAAQ;AACX,YAAMA,OAAM,WAAW,CAAC,SAAS,GAAG,OAAO,IAAI,OAAO,IAAI,KAAK,KAAK,CAAC;AAAA,IACvE;AAAA,EACF;AAEA,UAAQ;AAAA,IACN,UAAK,SAAS,eAAe,EAAE,UAAU,QAAQ,MAAM,iBAAiB,OAAO,IAAI,OAAO;AAAA,EAC5F;AACF;","names":["execa"]}
package/dist/cli.d.cts ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ declare function checkPreflight(): void;
3
+
4
+ export { checkPreflight };
package/dist/cli.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ declare function checkPreflight(): void;
3
+
4
+ export { checkPreflight };
package/dist/cli.js ADDED
@@ -0,0 +1,133 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/cli.ts
22
+ var cli_exports = {};
23
+ __export(cli_exports, {
24
+ checkPreflight: () => checkPreflight
25
+ });
26
+ module.exports = __toCommonJS(cli_exports);
27
+
28
+ // ../../node_modules/.pnpm/tsup@8.5.1_postcss@8.5.14_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js
29
+ var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
30
+ var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
31
+
32
+ // src/cli.ts
33
+ var import_node_fs3 = require("fs");
34
+ var import_node_url = require("url");
35
+ var import_commander = require("commander");
36
+ var import_execa3 = require("execa");
37
+
38
+ // src/pull.ts
39
+ var import_node_fs = require("fs");
40
+ var import_execa = require("execa");
41
+ async function pull(options) {
42
+ const { service, envName, output, dryRun = false, verbose = false } = options;
43
+ const { stdout } = await (0, import_execa.execa)("chamber", ["env", `${service}/${envName}`]);
44
+ if (verbose) console.log(`Retrieved variables from ${service}/${envName}`);
45
+ if (dryRun) {
46
+ console.log(`[dry-run] Would write to ${output}:
47
+ ${stdout}`);
48
+ return;
49
+ }
50
+ (0, import_node_fs.writeFileSync)(output, stdout, "utf-8");
51
+ const count = stdout.split("\n").filter(Boolean).length;
52
+ console.log(`\u2713 Pulled ${count} variables to ${output}`);
53
+ }
54
+
55
+ // src/push.ts
56
+ var import_node_fs2 = require("fs");
57
+ var import_execa2 = require("execa");
58
+ function parseEnvContent(content) {
59
+ const result = {};
60
+ for (const line of content.split("\n")) {
61
+ const trimmed = line.trim();
62
+ if (!trimmed || trimmed.startsWith("#")) continue;
63
+ const idx = trimmed.indexOf("=");
64
+ if (idx === -1) continue;
65
+ const key = trimmed.slice(0, idx).trim();
66
+ const raw = trimmed.slice(idx + 1).trim();
67
+ result[key] = raw.replace(/^["']|["']$/g, "");
68
+ }
69
+ return result;
70
+ }
71
+ async function push(options) {
72
+ const { envFile, service, envName, dryRun = false, verbose = false } = options;
73
+ const content = (0, import_node_fs2.readFileSync)(envFile, "utf-8");
74
+ const entries = Object.entries(parseEnvContent(content));
75
+ if (verbose) console.log(`Found ${entries.length} variables in ${envFile}`);
76
+ for (const [key, value] of entries) {
77
+ if (verbose) console.log(` ${dryRun ? "[dry-run] " : ""}${key}`);
78
+ if (!dryRun) {
79
+ await (0, import_execa2.execa)("chamber", ["write", `${service}/${envName}`, key, value]);
80
+ }
81
+ }
82
+ console.log(
83
+ `\u2713 ${dryRun ? "[dry-run] " : ""}Pushed ${entries.length} variables to ${service}/${envName}`
84
+ );
85
+ }
86
+
87
+ // src/cli.ts
88
+ function checkPreflight() {
89
+ try {
90
+ (0, import_execa3.execaSync)("chamber", ["version"]);
91
+ } catch {
92
+ console.error("Error: `chamber` binary not found in PATH.");
93
+ console.error("Install: https://github.com/segmentio/chamber#installation");
94
+ process.exit(1);
95
+ }
96
+ const hasCredentials = process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY || Boolean(process.env.AWS_PROFILE) || (0, import_node_fs3.existsSync)(`${process.env.HOME}/.aws/credentials`);
97
+ if (!hasCredentials) {
98
+ console.error("Error: AWS credentials not configured.");
99
+ console.error("Set AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY, or configure ~/.aws/credentials");
100
+ process.exit(1);
101
+ }
102
+ }
103
+ var program = new import_commander.Command();
104
+ program.name("devtools").description("Devorama developer tools CLI").version("0.1.0");
105
+ var secretsCmd = program.command("secrets").description("Manage secrets via AWS Parameter Store");
106
+ secretsCmd.command("push").description("Push .env variables to AWS Parameter Store").option("--env <file>", ".env file to push", ".env").requiredOption("--service <name>", "Chamber service name").requiredOption("--env-name <name>", "Environment name (e.g. staging, production)").option("--dry-run", "Show what would be pushed without writing", false).option("--verbose", "Log each key being processed", false).action(async (opts) => {
107
+ checkPreflight();
108
+ await push({
109
+ envFile: opts.env,
110
+ service: opts.service,
111
+ envName: opts.envName,
112
+ dryRun: opts.dryRun,
113
+ verbose: opts.verbose
114
+ });
115
+ });
116
+ secretsCmd.command("pull").description("Pull variables from AWS Parameter Store to a .env file").requiredOption("--service <name>", "Chamber service name").requiredOption("--env-name <name>", "Environment name (e.g. staging, production)").option("--output <file>", "Output .env file path", ".env").option("--dry-run", "Show what would be written without creating the file", false).option("--verbose", "Log details", false).action(async (opts) => {
117
+ checkPreflight();
118
+ await pull({
119
+ service: opts.service,
120
+ envName: opts.envName,
121
+ output: opts.output,
122
+ dryRun: opts.dryRun,
123
+ verbose: opts.verbose
124
+ });
125
+ });
126
+ if (process.argv[1] === (0, import_node_url.fileURLToPath)(importMetaUrl)) {
127
+ program.parse();
128
+ }
129
+ // Annotate the CommonJS export names for ESM import in node:
130
+ 0 && (module.exports = {
131
+ checkPreflight
132
+ });
133
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts","../../../node_modules/.pnpm/tsup@8.5.1_postcss@8.5.14_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","../src/pull.ts","../src/push.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { existsSync } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { Command } from 'commander'\nimport { execaSync } from 'execa'\nimport { pull } from './pull'\nimport { push } from './push'\n\nexport function checkPreflight(): void {\n try {\n execaSync('chamber', ['version'])\n } catch {\n console.error('Error: `chamber` binary not found in PATH.')\n console.error('Install: https://github.com/segmentio/chamber#installation')\n process.exit(1)\n }\n\n const hasCredentials =\n (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) ||\n Boolean(process.env.AWS_PROFILE) ||\n existsSync(`${process.env.HOME}/.aws/credentials`)\n\n if (!hasCredentials) {\n console.error('Error: AWS credentials not configured.')\n console.error('Set AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY, or configure ~/.aws/credentials')\n process.exit(1)\n }\n}\n\nconst program = new Command()\n\nprogram.name('devtools').description('Devorama developer tools CLI').version('0.1.0')\n\nconst secretsCmd = program.command('secrets').description('Manage secrets via AWS Parameter Store')\n\nsecretsCmd\n .command('push')\n .description('Push .env variables to AWS Parameter Store')\n .option('--env <file>', '.env file to push', '.env')\n .requiredOption('--service <name>', 'Chamber service name')\n .requiredOption('--env-name <name>', 'Environment name (e.g. staging, production)')\n .option('--dry-run', 'Show what would be pushed without writing', false)\n .option('--verbose', 'Log each key being processed', false)\n .action(async (opts) => {\n checkPreflight()\n await push({\n envFile: opts.env,\n service: opts.service,\n envName: opts.envName,\n dryRun: opts.dryRun,\n verbose: opts.verbose,\n })\n })\n\nsecretsCmd\n .command('pull')\n .description('Pull variables from AWS Parameter Store to a .env file')\n .requiredOption('--service <name>', 'Chamber service name')\n .requiredOption('--env-name <name>', 'Environment name (e.g. staging, production)')\n .option('--output <file>', 'Output .env file path', '.env')\n .option('--dry-run', 'Show what would be written without creating the file', false)\n .option('--verbose', 'Log details', false)\n .action(async (opts) => {\n checkPreflight()\n await pull({\n service: opts.service,\n envName: opts.envName,\n output: opts.output,\n dryRun: opts.dryRun,\n verbose: opts.verbose,\n })\n })\n\n// Only parse argv when invoked directly (not when imported in tests)\nif (process.argv[1] === fileURLToPath(import.meta.url)) {\n program.parse()\n}\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import { writeFileSync } from 'node:fs'\nimport { execa } from 'execa'\n\nexport interface PullOptions {\n service: string\n envName: string\n output: string\n dryRun?: boolean\n verbose?: boolean\n}\n\nexport async function pull(options: PullOptions): Promise<void> {\n const { service, envName, output, dryRun = false, verbose = false } = options\n\n const { stdout } = await execa('chamber', ['env', `${service}/${envName}`])\n\n if (verbose) console.log(`Retrieved variables from ${service}/${envName}`)\n\n if (dryRun) {\n console.log(`[dry-run] Would write to ${output}:\\n${stdout}`)\n return\n }\n\n writeFileSync(output, stdout, 'utf-8')\n const count = stdout.split('\\n').filter(Boolean).length\n console.log(`✓ Pulled ${count} variables to ${output}`)\n}\n","import { readFileSync } from 'node:fs'\nimport { execa } from 'execa'\n\nexport interface PushOptions {\n envFile: string\n service: string\n envName: string\n dryRun?: boolean\n verbose?: boolean\n}\n\nfunction parseEnvContent(content: string): Record<string, string> {\n const result: Record<string, string> = {}\n for (const line of content.split('\\n')) {\n const trimmed = line.trim()\n if (!trimmed || trimmed.startsWith('#')) continue\n const idx = trimmed.indexOf('=')\n if (idx === -1) continue\n const key = trimmed.slice(0, idx).trim()\n const raw = trimmed.slice(idx + 1).trim()\n result[key] = raw.replace(/^[\"']|[\"']$/g, '')\n }\n return result\n}\n\nexport async function push(options: PushOptions): Promise<void> {\n const { envFile, service, envName, dryRun = false, verbose = false } = options\n const content = readFileSync(envFile, 'utf-8')\n const entries = Object.entries(parseEnvContent(content))\n\n if (verbose) console.log(`Found ${entries.length} variables in ${envFile}`)\n\n for (const [key, value] of entries) {\n if (verbose) console.log(` ${dryRun ? '[dry-run] ' : ''}${key}`)\n if (!dryRun) {\n await execa('chamber', ['write', `${service}/${envName}`, key, value])\n }\n }\n\n console.log(\n `✓ ${dryRun ? '[dry-run] ' : ''}Pushed ${entries.length} variables to ${service}/${envName}`\n )\n}\n"],"mappings":"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","names":["import_node_fs","import_execa","import_node_fs","import_execa"]}
package/dist/cli.mjs ADDED
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ pull,
4
+ push
5
+ } from "./chunk-UBFSRMBE.mjs";
6
+
7
+ // src/cli.ts
8
+ import { existsSync } from "fs";
9
+ import { fileURLToPath } from "url";
10
+ import { Command } from "commander";
11
+ import { execaSync } from "execa";
12
+ function checkPreflight() {
13
+ try {
14
+ execaSync("chamber", ["version"]);
15
+ } catch {
16
+ console.error("Error: `chamber` binary not found in PATH.");
17
+ console.error("Install: https://github.com/segmentio/chamber#installation");
18
+ process.exit(1);
19
+ }
20
+ const hasCredentials = process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY || Boolean(process.env.AWS_PROFILE) || existsSync(`${process.env.HOME}/.aws/credentials`);
21
+ if (!hasCredentials) {
22
+ console.error("Error: AWS credentials not configured.");
23
+ console.error("Set AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY, or configure ~/.aws/credentials");
24
+ process.exit(1);
25
+ }
26
+ }
27
+ var program = new Command();
28
+ program.name("devtools").description("Devorama developer tools CLI").version("0.1.0");
29
+ var secretsCmd = program.command("secrets").description("Manage secrets via AWS Parameter Store");
30
+ secretsCmd.command("push").description("Push .env variables to AWS Parameter Store").option("--env <file>", ".env file to push", ".env").requiredOption("--service <name>", "Chamber service name").requiredOption("--env-name <name>", "Environment name (e.g. staging, production)").option("--dry-run", "Show what would be pushed without writing", false).option("--verbose", "Log each key being processed", false).action(async (opts) => {
31
+ checkPreflight();
32
+ await push({
33
+ envFile: opts.env,
34
+ service: opts.service,
35
+ envName: opts.envName,
36
+ dryRun: opts.dryRun,
37
+ verbose: opts.verbose
38
+ });
39
+ });
40
+ secretsCmd.command("pull").description("Pull variables from AWS Parameter Store to a .env file").requiredOption("--service <name>", "Chamber service name").requiredOption("--env-name <name>", "Environment name (e.g. staging, production)").option("--output <file>", "Output .env file path", ".env").option("--dry-run", "Show what would be written without creating the file", false).option("--verbose", "Log details", false).action(async (opts) => {
41
+ checkPreflight();
42
+ await pull({
43
+ service: opts.service,
44
+ envName: opts.envName,
45
+ output: opts.output,
46
+ dryRun: opts.dryRun,
47
+ verbose: opts.verbose
48
+ });
49
+ });
50
+ if (process.argv[1] === fileURLToPath(import.meta.url)) {
51
+ program.parse();
52
+ }
53
+ export {
54
+ checkPreflight
55
+ };
56
+ //# sourceMappingURL=cli.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { existsSync } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { Command } from 'commander'\nimport { execaSync } from 'execa'\nimport { pull } from './pull'\nimport { push } from './push'\n\nexport function checkPreflight(): void {\n try {\n execaSync('chamber', ['version'])\n } catch {\n console.error('Error: `chamber` binary not found in PATH.')\n console.error('Install: https://github.com/segmentio/chamber#installation')\n process.exit(1)\n }\n\n const hasCredentials =\n (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) ||\n Boolean(process.env.AWS_PROFILE) ||\n existsSync(`${process.env.HOME}/.aws/credentials`)\n\n if (!hasCredentials) {\n console.error('Error: AWS credentials not configured.')\n console.error('Set AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY, or configure ~/.aws/credentials')\n process.exit(1)\n }\n}\n\nconst program = new Command()\n\nprogram.name('devtools').description('Devorama developer tools CLI').version('0.1.0')\n\nconst secretsCmd = program.command('secrets').description('Manage secrets via AWS Parameter Store')\n\nsecretsCmd\n .command('push')\n .description('Push .env variables to AWS Parameter Store')\n .option('--env <file>', '.env file to push', '.env')\n .requiredOption('--service <name>', 'Chamber service name')\n .requiredOption('--env-name <name>', 'Environment name (e.g. staging, production)')\n .option('--dry-run', 'Show what would be pushed without writing', false)\n .option('--verbose', 'Log each key being processed', false)\n .action(async (opts) => {\n checkPreflight()\n await push({\n envFile: opts.env,\n service: opts.service,\n envName: opts.envName,\n dryRun: opts.dryRun,\n verbose: opts.verbose,\n })\n })\n\nsecretsCmd\n .command('pull')\n .description('Pull variables from AWS Parameter Store to a .env file')\n .requiredOption('--service <name>', 'Chamber service name')\n .requiredOption('--env-name <name>', 'Environment name (e.g. staging, production)')\n .option('--output <file>', 'Output .env file path', '.env')\n .option('--dry-run', 'Show what would be written without creating the file', false)\n .option('--verbose', 'Log details', false)\n .action(async (opts) => {\n checkPreflight()\n await pull({\n service: opts.service,\n envName: opts.envName,\n output: opts.output,\n dryRun: opts.dryRun,\n verbose: opts.verbose,\n })\n })\n\n// Only parse argv when invoked directly (not when imported in tests)\nif (process.argv[1] === fileURLToPath(import.meta.url)) {\n program.parse()\n}\n"],"mappings":";;;;;;;AACA,SAAS,kBAAkB;AAC3B,SAAS,qBAAqB;AAC9B,SAAS,eAAe;AACxB,SAAS,iBAAiB;AAInB,SAAS,iBAAuB;AACrC,MAAI;AACF,cAAU,WAAW,CAAC,SAAS,CAAC;AAAA,EAClC,QAAQ;AACN,YAAQ,MAAM,4CAA4C;AAC1D,YAAQ,MAAM,4DAA4D;AAC1E,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,iBACH,QAAQ,IAAI,qBAAqB,QAAQ,IAAI,yBAC9C,QAAQ,QAAQ,IAAI,WAAW,KAC/B,WAAW,GAAG,QAAQ,IAAI,IAAI,mBAAmB;AAEnD,MAAI,CAAC,gBAAgB;AACnB,YAAQ,MAAM,wCAAwC;AACtD,YAAQ,MAAM,gFAAgF;AAC9F,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,IAAM,UAAU,IAAI,QAAQ;AAE5B,QAAQ,KAAK,UAAU,EAAE,YAAY,8BAA8B,EAAE,QAAQ,OAAO;AAEpF,IAAM,aAAa,QAAQ,QAAQ,SAAS,EAAE,YAAY,wCAAwC;AAElG,WACG,QAAQ,MAAM,EACd,YAAY,4CAA4C,EACxD,OAAO,gBAAgB,qBAAqB,MAAM,EAClD,eAAe,oBAAoB,sBAAsB,EACzD,eAAe,qBAAqB,6CAA6C,EACjF,OAAO,aAAa,6CAA6C,KAAK,EACtE,OAAO,aAAa,gCAAgC,KAAK,EACzD,OAAO,OAAO,SAAS;AACtB,iBAAe;AACf,QAAM,KAAK;AAAA,IACT,SAAS,KAAK;AAAA,IACd,SAAS,KAAK;AAAA,IACd,SAAS,KAAK;AAAA,IACd,QAAQ,KAAK;AAAA,IACb,SAAS,KAAK;AAAA,EAChB,CAAC;AACH,CAAC;AAEH,WACG,QAAQ,MAAM,EACd,YAAY,wDAAwD,EACpE,eAAe,oBAAoB,sBAAsB,EACzD,eAAe,qBAAqB,6CAA6C,EACjF,OAAO,mBAAmB,yBAAyB,MAAM,EACzD,OAAO,aAAa,wDAAwD,KAAK,EACjF,OAAO,aAAa,eAAe,KAAK,EACxC,OAAO,OAAO,SAAS;AACtB,iBAAe;AACf,QAAM,KAAK;AAAA,IACT,SAAS,KAAK;AAAA,IACd,SAAS,KAAK;AAAA,IACd,QAAQ,KAAK;AAAA,IACb,QAAQ,KAAK;AAAA,IACb,SAAS,KAAK;AAAA,EAChB,CAAC;AACH,CAAC;AAGH,IAAI,QAAQ,KAAK,CAAC,MAAM,cAAc,YAAY,GAAG,GAAG;AACtD,UAAQ,MAAM;AAChB;","names":[]}
@@ -0,0 +1,19 @@
1
+ interface PushOptions {
2
+ envFile: string;
3
+ service: string;
4
+ envName: string;
5
+ dryRun?: boolean;
6
+ verbose?: boolean;
7
+ }
8
+ declare function push(options: PushOptions): Promise<void>;
9
+
10
+ interface PullOptions {
11
+ service: string;
12
+ envName: string;
13
+ output: string;
14
+ dryRun?: boolean;
15
+ verbose?: boolean;
16
+ }
17
+ declare function pull(options: PullOptions): Promise<void>;
18
+
19
+ export { type PullOptions, type PushOptions, pull, push };
@@ -0,0 +1,19 @@
1
+ interface PushOptions {
2
+ envFile: string;
3
+ service: string;
4
+ envName: string;
5
+ dryRun?: boolean;
6
+ verbose?: boolean;
7
+ }
8
+ declare function push(options: PushOptions): Promise<void>;
9
+
10
+ interface PullOptions {
11
+ service: string;
12
+ envName: string;
13
+ output: string;
14
+ dryRun?: boolean;
15
+ verbose?: boolean;
16
+ }
17
+ declare function pull(options: PullOptions): Promise<void>;
18
+
19
+ export { type PullOptions, type PushOptions, pull, push };
package/dist/index.js ADDED
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ pull: () => pull,
24
+ push: () => push
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/push.ts
29
+ var import_node_fs = require("fs");
30
+ var import_execa = require("execa");
31
+ function parseEnvContent(content) {
32
+ const result = {};
33
+ for (const line of content.split("\n")) {
34
+ const trimmed = line.trim();
35
+ if (!trimmed || trimmed.startsWith("#")) continue;
36
+ const idx = trimmed.indexOf("=");
37
+ if (idx === -1) continue;
38
+ const key = trimmed.slice(0, idx).trim();
39
+ const raw = trimmed.slice(idx + 1).trim();
40
+ result[key] = raw.replace(/^["']|["']$/g, "");
41
+ }
42
+ return result;
43
+ }
44
+ async function push(options) {
45
+ const { envFile, service, envName, dryRun = false, verbose = false } = options;
46
+ const content = (0, import_node_fs.readFileSync)(envFile, "utf-8");
47
+ const entries = Object.entries(parseEnvContent(content));
48
+ if (verbose) console.log(`Found ${entries.length} variables in ${envFile}`);
49
+ for (const [key, value] of entries) {
50
+ if (verbose) console.log(` ${dryRun ? "[dry-run] " : ""}${key}`);
51
+ if (!dryRun) {
52
+ await (0, import_execa.execa)("chamber", ["write", `${service}/${envName}`, key, value]);
53
+ }
54
+ }
55
+ console.log(
56
+ `\u2713 ${dryRun ? "[dry-run] " : ""}Pushed ${entries.length} variables to ${service}/${envName}`
57
+ );
58
+ }
59
+
60
+ // src/pull.ts
61
+ var import_node_fs2 = require("fs");
62
+ var import_execa2 = require("execa");
63
+ async function pull(options) {
64
+ const { service, envName, output, dryRun = false, verbose = false } = options;
65
+ const { stdout } = await (0, import_execa2.execa)("chamber", ["env", `${service}/${envName}`]);
66
+ if (verbose) console.log(`Retrieved variables from ${service}/${envName}`);
67
+ if (dryRun) {
68
+ console.log(`[dry-run] Would write to ${output}:
69
+ ${stdout}`);
70
+ return;
71
+ }
72
+ (0, import_node_fs2.writeFileSync)(output, stdout, "utf-8");
73
+ const count = stdout.split("\n").filter(Boolean).length;
74
+ console.log(`\u2713 Pulled ${count} variables to ${output}`);
75
+ }
76
+ // Annotate the CommonJS export names for ESM import in node:
77
+ 0 && (module.exports = {
78
+ pull,
79
+ push
80
+ });
81
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/push.ts","../src/pull.ts"],"sourcesContent":["export { push } from './push'\nexport { pull } from './pull'\nexport type { PushOptions } from './push'\nexport type { PullOptions } from './pull'\n","import { readFileSync } from 'node:fs'\nimport { execa } from 'execa'\n\nexport interface PushOptions {\n envFile: string\n service: string\n envName: string\n dryRun?: boolean\n verbose?: boolean\n}\n\nfunction parseEnvContent(content: string): Record<string, string> {\n const result: Record<string, string> = {}\n for (const line of content.split('\\n')) {\n const trimmed = line.trim()\n if (!trimmed || trimmed.startsWith('#')) continue\n const idx = trimmed.indexOf('=')\n if (idx === -1) continue\n const key = trimmed.slice(0, idx).trim()\n const raw = trimmed.slice(idx + 1).trim()\n result[key] = raw.replace(/^[\"']|[\"']$/g, '')\n }\n return result\n}\n\nexport async function push(options: PushOptions): Promise<void> {\n const { envFile, service, envName, dryRun = false, verbose = false } = options\n const content = readFileSync(envFile, 'utf-8')\n const entries = Object.entries(parseEnvContent(content))\n\n if (verbose) console.log(`Found ${entries.length} variables in ${envFile}`)\n\n for (const [key, value] of entries) {\n if (verbose) console.log(` ${dryRun ? '[dry-run] ' : ''}${key}`)\n if (!dryRun) {\n await execa('chamber', ['write', `${service}/${envName}`, key, value])\n }\n }\n\n console.log(\n `✓ ${dryRun ? '[dry-run] ' : ''}Pushed ${entries.length} variables to ${service}/${envName}`\n )\n}\n","import { writeFileSync } from 'node:fs'\nimport { execa } from 'execa'\n\nexport interface PullOptions {\n service: string\n envName: string\n output: string\n dryRun?: boolean\n verbose?: boolean\n}\n\nexport async function pull(options: PullOptions): Promise<void> {\n const { service, envName, output, dryRun = false, verbose = false } = options\n\n const { stdout } = await execa('chamber', ['env', `${service}/${envName}`])\n\n if (verbose) console.log(`Retrieved variables from ${service}/${envName}`)\n\n if (dryRun) {\n console.log(`[dry-run] Would write to ${output}:\\n${stdout}`)\n return\n }\n\n writeFileSync(output, stdout, 'utf-8')\n const count = stdout.split('\\n').filter(Boolean).length\n console.log(`✓ Pulled ${count} variables to ${output}`)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,qBAA6B;AAC7B,mBAAsB;AAUtB,SAAS,gBAAgB,SAAyC;AAChE,QAAM,SAAiC,CAAC;AACxC,aAAW,QAAQ,QAAQ,MAAM,IAAI,GAAG;AACtC,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,WAAW,QAAQ,WAAW,GAAG,EAAG;AACzC,UAAM,MAAM,QAAQ,QAAQ,GAAG;AAC/B,QAAI,QAAQ,GAAI;AAChB,UAAM,MAAM,QAAQ,MAAM,GAAG,GAAG,EAAE,KAAK;AACvC,UAAM,MAAM,QAAQ,MAAM,MAAM,CAAC,EAAE,KAAK;AACxC,WAAO,GAAG,IAAI,IAAI,QAAQ,gBAAgB,EAAE;AAAA,EAC9C;AACA,SAAO;AACT;AAEA,eAAsB,KAAK,SAAqC;AAC9D,QAAM,EAAE,SAAS,SAAS,SAAS,SAAS,OAAO,UAAU,MAAM,IAAI;AACvE,QAAM,cAAU,6BAAa,SAAS,OAAO;AAC7C,QAAM,UAAU,OAAO,QAAQ,gBAAgB,OAAO,CAAC;AAEvD,MAAI,QAAS,SAAQ,IAAI,SAAS,QAAQ,MAAM,iBAAiB,OAAO,EAAE;AAE1E,aAAW,CAAC,KAAK,KAAK,KAAK,SAAS;AAClC,QAAI,QAAS,SAAQ,IAAI,KAAK,SAAS,eAAe,EAAE,GAAG,GAAG,EAAE;AAChE,QAAI,CAAC,QAAQ;AACX,gBAAM,oBAAM,WAAW,CAAC,SAAS,GAAG,OAAO,IAAI,OAAO,IAAI,KAAK,KAAK,CAAC;AAAA,IACvE;AAAA,EACF;AAEA,UAAQ;AAAA,IACN,UAAK,SAAS,eAAe,EAAE,UAAU,QAAQ,MAAM,iBAAiB,OAAO,IAAI,OAAO;AAAA,EAC5F;AACF;;;AC1CA,IAAAA,kBAA8B;AAC9B,IAAAC,gBAAsB;AAUtB,eAAsB,KAAK,SAAqC;AAC9D,QAAM,EAAE,SAAS,SAAS,QAAQ,SAAS,OAAO,UAAU,MAAM,IAAI;AAEtE,QAAM,EAAE,OAAO,IAAI,UAAM,qBAAM,WAAW,CAAC,OAAO,GAAG,OAAO,IAAI,OAAO,EAAE,CAAC;AAE1E,MAAI,QAAS,SAAQ,IAAI,4BAA4B,OAAO,IAAI,OAAO,EAAE;AAEzE,MAAI,QAAQ;AACV,YAAQ,IAAI,4BAA4B,MAAM;AAAA,EAAM,MAAM,EAAE;AAC5D;AAAA,EACF;AAEA,qCAAc,QAAQ,QAAQ,OAAO;AACrC,QAAM,QAAQ,OAAO,MAAM,IAAI,EAAE,OAAO,OAAO,EAAE;AACjD,UAAQ,IAAI,iBAAY,KAAK,iBAAiB,MAAM,EAAE;AACxD;","names":["import_node_fs","import_execa"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,9 @@
1
+ import {
2
+ pull,
3
+ push
4
+ } from "./chunk-UBFSRMBE.mjs";
5
+ export {
6
+ pull,
7
+ push
8
+ };
9
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@devorama/secrets",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "bin": {
6
+ "devtools": "./dist/cli.js"
7
+ },
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "main": "./dist/index.js",
16
+ "module": "./dist/index.mjs",
17
+ "types": "./dist/index.d.ts",
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "publishConfig": {
22
+ "access": "public"
23
+ },
24
+ "dependencies": {
25
+ "commander": "^12.1.0",
26
+ "execa": "^9.5.0"
27
+ },
28
+ "devDependencies": {
29
+ "@types/node": "^22.0.0",
30
+ "tsup": "^8.3.0",
31
+ "typescript": "^5.7.0",
32
+ "vitest": "^2.1.0"
33
+ },
34
+ "scripts": {
35
+ "build": "tsup",
36
+ "test": "vitest run",
37
+ "test:watch": "vitest",
38
+ "lint": "biome check ."
39
+ }
40
+ }