@envmanager-cli/cli 0.1.4 → 0.1.6

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 CHANGED
@@ -44,6 +44,7 @@ envmanager diff
44
44
  | `template` | Manage .env templates |
45
45
  | `validate` | Validate against schema |
46
46
  | `completion` | Generate shell completion script |
47
+ | `debug` | Collect diagnostic info for troubleshooting |
47
48
 
48
49
  ## Shell Completion
49
50
 
@@ -91,9 +92,19 @@ envmanager pull --project 1 --environment development
91
92
  envmanager pull --project my-api --environment production
92
93
  ```
93
94
 
95
+ ### Default Environment
96
+
97
+ When `-e` / `--environment` is omitted, it defaults to `development`. You can override the default in `envmanager.json`:
98
+
99
+ ```json
100
+ {
101
+ "environment": "staging"
102
+ }
103
+ ```
104
+
94
105
  ### Multiple Organizations
95
106
 
96
- If you belong to multiple organizations, use `--org` to specify which one:
107
+ If you belong to multiple organizations, the CLI auto-detects the organization from your project when possible. Use `--org` to specify explicitly if needed:
97
108
 
98
109
  ```bash
99
110
  envmanager pull --org "My Company" --project 1 --environment staging
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/bin/envmanager.ts
4
- import { Command as Command14 } from "commander";
4
+ import { Command as Command15 } from "commander";
5
5
 
6
6
  // src/commands/login.ts
7
7
  import { Command } from "commander";
@@ -88,7 +88,7 @@ function escapeHtml(str) {
88
88
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
89
89
  }
90
90
  async function startCallbackServer(expectedState, port = 8976) {
91
- return new Promise((resolve8, reject) => {
91
+ return new Promise((resolve9, reject) => {
92
92
  const timeout = setTimeout(() => {
93
93
  server.close();
94
94
  reject(new Error("Authentication timed out after 5 minutes"));
@@ -161,9 +161,9 @@ async function startCallbackServer(expectedState, port = 8976) {
161
161
  clearTimeout(timeout);
162
162
  server.close();
163
163
  if (apiKey) {
164
- resolve8({ apiKey });
164
+ resolve9({ apiKey });
165
165
  } else {
166
- resolve8({
166
+ resolve9({
167
167
  accessToken,
168
168
  refreshToken,
169
169
  expiresIn: parseInt(expiresIn || "3600", 10)
@@ -1287,7 +1287,7 @@ var diffCommand = new Command6("diff").description("Show differences between loc
1287
1287
  import { Command as Command7 } from "commander";
1288
1288
  import chalk8 from "chalk";
1289
1289
  import ora6 from "ora";
1290
- var listCommand = new Command7("list").description("List projects, environments, or variables").argument("[resource]", "Resource to list: projects, environments, variables", "projects").option("--org <name>", "Organization name (required if you belong to multiple)").option("-p, --project <name-or-id>", "Project name or ID (for environments/variables)").option("-e, --environment <name>", "Environment name (for variables)").option("-v, --verbose", "Show IDs").action(async (resource, options) => {
1290
+ var listCommand = new Command7("list").description("List projects, environments, or variables").argument("[resource]", "Resource to list: projects, environments, variables", "projects").option("--org <name>", "Organization name (required if you belong to multiple)").option("-p, --project <name-or-id>", "Project name or ID (for environments/variables)").option("-e, --environment <name>", 'Environment name (default: "development")').option("-v, --verbose", "Show IDs").action(async (resource, options) => {
1291
1291
  const spinner = ora6("Connecting...").start();
1292
1292
  try {
1293
1293
  const config = loadConfig();
@@ -1511,11 +1511,11 @@ async function subscribeToVariableChanges(environmentId, onEvent, onStatus) {
1511
1511
  onStatus?.("connected");
1512
1512
  }
1513
1513
  });
1514
- const subscription = await new Promise((resolve8, reject) => {
1514
+ const subscription = await new Promise((resolve9, reject) => {
1515
1515
  channel.subscribe(async (status, err) => {
1516
1516
  if (status === "SUBSCRIBED") {
1517
1517
  onStatus?.("connected");
1518
- resolve8({
1518
+ resolve9({
1519
1519
  channel,
1520
1520
  environmentId,
1521
1521
  unsubscribe: async () => {
@@ -2234,7 +2234,7 @@ import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsS
2234
2234
  import { resolve as resolve6 } from "path";
2235
2235
  import { parse as parseDotenv4 } from "dotenv";
2236
2236
  var templateCommand = new Command11("template").description("Manage environment templates");
2237
- templateCommand.command("generate").description("Generate .env file from template and EnvManager values").option("-t, --template <file>", "Template file (default: .env.template or .env.template.yaml)").option("-o, --output <file>", "Output file (default: .env)").option("-e, --environment <name>", "Environment name (default: from config)").option("-p, --project <id>", "Project ID (default: from config)").option("-f, --force", "Overwrite existing output file").action(async (options) => {
2237
+ templateCommand.command("generate").description("Generate .env file from template and EnvManager values").option("-t, --template <file>", "Template file (default: .env.template or .env.template.yaml)").option("-o, --output <file>", "Output file (default: .env)").option("-e, --environment <name>", 'Environment name (default: "development")').option("-p, --project <id>", "Project ID (default: from config)").option("-f, --force", "Overwrite existing output file").action(async (options) => {
2238
2238
  const spinner = ora9("Generating .env from template...").start();
2239
2239
  try {
2240
2240
  const config = loadConfig();
@@ -2336,7 +2336,7 @@ File ${outputPath} already exists. Use --force to overwrite.`));
2336
2336
  process.exit(1);
2337
2337
  }
2338
2338
  });
2339
- templateCommand.command("sync").description("Compare template with EnvManager and report differences").option("-t, --template <file>", "Template file (default: .env.template or .env.template.yaml)").option("-e, --environment <name>", "Environment name (default: from config)").option("-p, --project <id>", "Project ID (default: from config)").action(async (options) => {
2339
+ templateCommand.command("sync").description("Compare template with EnvManager and report differences").option("-t, --template <file>", "Template file (default: .env.template or .env.template.yaml)").option("-e, --environment <name>", 'Environment name (default: "development")').option("-p, --project <id>", "Project ID (default: from config)").action(async (options) => {
2340
2340
  const spinner = ora9("Comparing template with EnvManager...").start();
2341
2341
  try {
2342
2342
  const config = loadConfig();
@@ -2652,7 +2652,7 @@ function jsonToSchema(json) {
2652
2652
  }
2653
2653
 
2654
2654
  // src/commands/validate.ts
2655
- var validateCommand = new Command12("validate").description("Validate local .env file against schema from EnvManager or local file").option("-e, --environment <name>", "Environment name (default: from config)").option("-p, --project <id>", "Project ID (default: from config)").option("--org <name>", "Organization name (required if you belong to multiple)").option("-i, --input <file>", "Input .env file (default: .env)").option("-s, --schema <file>", "Local schema JSON file (skip fetching from EnvManager)").option("--strict", "Fail on warnings (extra variables not in schema)").action(async (options) => {
2655
+ var validateCommand = new Command12("validate").description("Validate local .env file against schema from EnvManager or local file").option("-e, --environment <name>", 'Environment name (default: "development")').option("-p, --project <id>", "Project ID (default: from config)").option("--org <name>", "Organization name (required if you belong to multiple)").option("-i, --input <file>", "Input .env file (default: .env)").option("-s, --schema <file>", "Local schema JSON file (skip fetching from EnvManager)").option("--strict", "Fail on warnings (extra variables not in schema)").action(async (options) => {
2656
2656
  const spinner = ora10("Validating environment...").start();
2657
2657
  try {
2658
2658
  const config = loadConfig();
@@ -2978,8 +2978,109 @@ var completionCommand = new Command13("completion").description("Generate shell
2978
2978
  }
2979
2979
  });
2980
2980
 
2981
+ // src/commands/debug.ts
2982
+ import { Command as Command14 } from "commander";
2983
+ import chalk14 from "chalk";
2984
+ import { readFileSync as readFileSync9 } from "fs";
2985
+ import { fileURLToPath } from "url";
2986
+ import { dirname as dirname2, resolve as resolve8 } from "path";
2987
+ function getCliVersion() {
2988
+ try {
2989
+ const __dirname2 = dirname2(fileURLToPath(import.meta.url));
2990
+ const pkg = JSON.parse(readFileSync9(resolve8(__dirname2, "../../package.json"), "utf-8"));
2991
+ return pkg.version || "unknown";
2992
+ } catch {
2993
+ return "unknown";
2994
+ }
2995
+ }
2996
+ var debugCommand = new Command14("debug").description("Collect diagnostic info for troubleshooting").action(async () => {
2997
+ const lines = [];
2998
+ const log = (msg) => lines.push(msg);
2999
+ log("=== EnvManager CLI Debug Report ===");
3000
+ log(`Timestamp: ${(/* @__PURE__ */ new Date()).toISOString()}`);
3001
+ log(`CLI Version: ${getCliVersion()}`);
3002
+ log(`Node: ${process.version}`);
3003
+ log(`Platform: ${process.platform} ${process.arch}`);
3004
+ log("");
3005
+ log("--- Config ---");
3006
+ const configPath = getConfigPath();
3007
+ const config = loadConfig();
3008
+ log(`Config file: ${configPath || "not found"}`);
3009
+ if (config) {
3010
+ log(` project_id: ${config.project_id || "not set"}`);
3011
+ log(` project_name: ${config.project_name || "not set"}`);
3012
+ log(` environment: ${config.environment || "not set"}`);
3013
+ log(` organization_id: ${config.organization_id || "not set"}`);
3014
+ log(` api_url: ${config.api_url || "not set"}`);
3015
+ }
3016
+ log("");
3017
+ log("--- Authentication ---");
3018
+ const envApiKey = getApiKeyFromEnv();
3019
+ const storedApiKey = getStoredApiKey();
3020
+ const storedApiUrl = getStoredApiUrl();
3021
+ const creds = getCredentials();
3022
+ if (envApiKey) {
3023
+ log(`Auth method: Environment API key (${envApiKey.substring(0, 11)}...)`);
3024
+ } else if (storedApiKey) {
3025
+ log(`Auth method: CLI session key (${storedApiKey.substring(0, 11)}...)`);
3026
+ } else if (creds?.accessToken) {
3027
+ log("Auth method: Legacy session tokens");
3028
+ if (creds.expiresAt) {
3029
+ const remaining = Math.round((creds.expiresAt - Date.now()) / 1e3);
3030
+ log(` Token expires in: ${remaining > 0 ? `${remaining}s` : "EXPIRED"}`);
3031
+ }
3032
+ } else {
3033
+ log("Auth method: Not authenticated");
3034
+ }
3035
+ log(`API URL: ${storedApiUrl || process.env.ENVMANAGER_API_URL || "default (production)"}`);
3036
+ log("");
3037
+ log("--- API Connection ---");
3038
+ try {
3039
+ const start = Date.now();
3040
+ const client = await createClient();
3041
+ const authTime = Date.now() - start;
3042
+ log(`Auth exchange: ${authTime}ms`);
3043
+ const userStart = Date.now();
3044
+ const { data: { user }, error: userError } = await client.auth.getUser();
3045
+ const userTime = Date.now() - userStart;
3046
+ log(`getUser: ${userTime}ms`);
3047
+ if (userError) {
3048
+ log(` ERROR: ${userError.message}`);
3049
+ } else if (user) {
3050
+ log(` User ID: ${user.id}`);
3051
+ log(` Email: ${user.email}`);
3052
+ }
3053
+ if (user) {
3054
+ const orgStart = Date.now();
3055
+ const { data: memberships, error: orgError } = await client.from("organization_members").select("organization_id, role, organizations(id, name)").eq("user_id", user.id);
3056
+ const orgTime = Date.now() - orgStart;
3057
+ log(`Org query: ${orgTime}ms`);
3058
+ if (orgError) {
3059
+ log(` ERROR: ${orgError.message}`);
3060
+ } else if (memberships) {
3061
+ log(` Organizations (${memberships.length}):`);
3062
+ memberships.forEach((m) => {
3063
+ const org = m.organizations;
3064
+ const orgName = Array.isArray(org) ? org[0]?.name : org?.name || "Unknown";
3065
+ const orgId = Array.isArray(org) ? org[0]?.id : org?.id || "?";
3066
+ log(` - ${orgName} (${m.role}) [${orgId.substring(0, 8)}...]`);
3067
+ });
3068
+ }
3069
+ }
3070
+ } catch (error) {
3071
+ log(` ERROR: ${error instanceof Error ? error.message : "Unknown error"}`);
3072
+ }
3073
+ log("");
3074
+ log("=== End Debug Report ===");
3075
+ const output = lines.join("\n");
3076
+ console.log(output);
3077
+ console.log("");
3078
+ console.log(chalk14.gray("Copy the output above and share it for troubleshooting."));
3079
+ console.log(chalk14.gray("Note: API keys are partially redacted. No secrets are exposed."));
3080
+ });
3081
+
2981
3082
  // src/bin/envmanager.ts
2982
- var program = new Command14();
3083
+ var program = new Command15();
2983
3084
  program.name("envmanager").description("CLI for EnvManager - secure environment variable management").version("0.1.0");
2984
3085
  program.addCommand(loginCommand);
2985
3086
  program.addCommand(logoutCommand);
@@ -2995,5 +3096,6 @@ program.addCommand(templateCommand);
2995
3096
  program.addCommand(validateCommand);
2996
3097
  program.addCommand(completionCommand);
2997
3098
  program.addCommand(completeCommand);
3099
+ program.addCommand(debugCommand);
2998
3100
  program.parse();
2999
3101
  //# sourceMappingURL=envmanager.js.map