@underlingscloud/cli 0.1.0 → 0.2.1

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.
@@ -1,2 +1,17 @@
1
1
  export declare const run: (commandParts: string[]) => Promise<void>;
2
- export declare const env: () => Promise<void>;
2
+ /**
3
+ * Print resolved environment variables.
4
+ *
5
+ * Options:
6
+ * --service <slug> Override service slug (otherwise reads from ulservice.json)
7
+ * --branch <name> Override branch (otherwise detects from git)
8
+ * --format <fmt> Output format: 'shell' (default), 'yaml', 'docker-build-args'
9
+ * --filter <prefix> Only include vars matching prefix (e.g. 'VITE_')
10
+ */
11
+ export declare const env: (options: {
12
+ service?: string;
13
+ branch?: string;
14
+ format?: string;
15
+ filter?: string;
16
+ }) => Promise<void>;
17
+ export declare function fetchServiceVariables(serviceSlug: string, branch: string, token: string): Promise<Record<string, string>>;
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.env = exports.run = void 0;
7
+ exports.fetchServiceVariables = fetchServiceVariables;
7
8
  const cross_spawn_1 = __importDefault(require("cross-spawn"));
8
9
  const child_process_1 = require("child_process");
9
10
  const chalk_1 = __importDefault(require("chalk"));
@@ -81,29 +82,92 @@ const run = async (commandParts) => {
81
82
  });
82
83
  };
83
84
  exports.run = run;
84
- const env = async () => {
85
+ /**
86
+ * Print resolved environment variables.
87
+ *
88
+ * Options:
89
+ * --service <slug> Override service slug (otherwise reads from ulservice.json)
90
+ * --branch <name> Override branch (otherwise detects from git)
91
+ * --format <fmt> Output format: 'shell' (default), 'yaml', 'docker-build-args'
92
+ * --filter <prefix> Only include vars matching prefix (e.g. 'VITE_')
93
+ */
94
+ const env = async (options) => {
85
95
  if (!(0, auth_1.isAuthenticated)()) {
86
96
  console.error(chalk_1.default.red('Error: You are not logged in.'));
87
- return;
97
+ process.exit(1);
88
98
  }
89
99
  const token = (0, auth_1.getAuthToken)();
90
- if (!(0, config_1.hasServiceConfig)()) {
91
- console.error(chalk_1.default.red('Error: No service config found in the current directory.'));
92
- return;
100
+ // Determine service slug
101
+ let serviceSlug = options.service;
102
+ if (!serviceSlug) {
103
+ if (!(0, config_1.hasServiceConfig)()) {
104
+ console.error(chalk_1.default.red('Error: No service config found. Use --service <slug> or run from a directory with ulservice.json.'));
105
+ process.exit(1);
106
+ }
107
+ serviceSlug = (0, config_1.readServiceConfig)().service;
93
108
  }
94
- const config = (0, config_1.readServiceConfig)();
95
- let branch;
96
- try {
97
- branch = (0, child_process_1.execSync)('git rev-parse --abbrev-ref HEAD').toString().trim();
109
+ // Determine branch
110
+ let branch = options.branch || 'main';
111
+ if (!options.branch) {
112
+ try {
113
+ branch = (0, child_process_1.execSync)('git rev-parse --abbrev-ref HEAD').toString().trim();
114
+ }
115
+ catch {
116
+ // Fall back to 'main' if not in a git repo
117
+ }
98
118
  }
99
- catch {
100
- console.error(chalk_1.default.red('Error: Could not determine git branch.'));
101
- return;
119
+ // Fetch vars
120
+ let envVars;
121
+ try {
122
+ envVars = await fetchServiceVariables(serviceSlug, branch, token);
102
123
  }
103
- console.log(chalk_1.default.blue(`Variables for ${config.service} on branch "${branch}":\n`));
104
- const envVars = await fetchServiceVariables(config.service, branch, token);
105
- for (const [key, value] of Object.entries(envVars).sort(([a], [b]) => a.localeCompare(b))) {
106
- console.log(`${chalk_1.default.cyan(key)}=${value}`);
124
+ catch (error) {
125
+ console.error(chalk_1.default.red('Failed to fetch variables:'), error.message);
126
+ process.exit(1);
127
+ }
128
+ // Apply filter
129
+ if (options.filter) {
130
+ const prefix = options.filter;
131
+ envVars = Object.fromEntries(Object.entries(envVars).filter(([key]) => key.startsWith(prefix)));
132
+ }
133
+ const format = options.format || 'shell';
134
+ const sorted = Object.entries(envVars).sort(([a], [b]) => a.localeCompare(b));
135
+ switch (format) {
136
+ case 'yaml':
137
+ // YAML format for gcloud --env-vars-file
138
+ for (const [key, value] of sorted) {
139
+ // YAML values with special chars need quoting
140
+ const needsQuote = /[:{}\[\],&*#?|\-<>=!%@`"'\n\\]/.test(value) || value.includes(' ');
141
+ if (needsQuote) {
142
+ // Use double-quoted YAML string, escaping backslashes and double quotes
143
+ const escaped = value.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n');
144
+ console.log(`${key}: "${escaped}"`);
145
+ }
146
+ else {
147
+ console.log(`${key}: ${value}`);
148
+ }
149
+ }
150
+ break;
151
+ case 'docker-build-args':
152
+ // Output as --build-arg KEY=VALUE flags for docker build
153
+ for (const [key, value] of sorted) {
154
+ console.log(`--build-arg ${key}=${value}`);
155
+ }
156
+ break;
157
+ case 'dotenv':
158
+ // .env file format
159
+ for (const [key, value] of sorted) {
160
+ const escaped = value.replace(/"/g, '\\"');
161
+ console.log(`${key}="${escaped}"`);
162
+ }
163
+ break;
164
+ case 'shell':
165
+ default:
166
+ // Human-readable shell format (default)
167
+ for (const [key, value] of sorted) {
168
+ console.log(`${chalk_1.default.cyan(key)}=${value}`);
169
+ }
170
+ break;
107
171
  }
108
172
  };
109
173
  exports.env = env;
package/dist/index.js CHANGED
@@ -94,8 +94,12 @@ program.command('run [command...]')
94
94
  // ─── Env ────────────────────────────────────────────────────────────────────
95
95
  program.command('env')
96
96
  .description('Print resolved environment variables for current service + branch')
97
- .action(async () => {
97
+ .option('-s, --service <slug>', 'Service slug (overrides ulservice.json)')
98
+ .option('-b, --branch <name>', 'Branch name (overrides git detection)')
99
+ .option('-f, --format <fmt>', 'Output format: shell, yaml, docker-build-args, dotenv', 'shell')
100
+ .option('--filter <prefix>', 'Only include vars matching prefix (e.g. VITE_)')
101
+ .action(async (options) => {
98
102
  const { env } = await Promise.resolve().then(() => __importStar(require('./commands/run')));
99
- await env();
103
+ await env(options);
100
104
  });
101
105
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@underlingscloud/cli",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "Underlings Developer Utilities CLI",
5
5
  "main": "dist/index.js",
6
6
  "bin": {