commet 1.1.0 → 1.2.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.
Files changed (2) hide show
  1. package/dist/index.js +485 -421
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -24,13 +24,13 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  ));
25
25
 
26
26
  // src/index.ts
27
- var import_chalk12 = __toESM(require("chalk"));
27
+ var import_chalk13 = __toESM(require("chalk"));
28
28
  var import_commander11 = require("commander");
29
29
 
30
30
  // package.json
31
31
  var package_default = {
32
32
  name: "commet",
33
- version: "1.1.0",
33
+ version: "1.2.0",
34
34
  description: "Commet CLI - Manage your billing platform from the command line",
35
35
  bin: {
36
36
  commet: "./bin/commet"
@@ -85,30 +85,237 @@ var package_default = {
85
85
  };
86
86
 
87
87
  // src/commands/create.ts
88
- var import_node_child_process = require("child_process");
88
+ var fs2 = __toESM(require("fs"));
89
+ var os2 = __toESM(require("os"));
90
+ var path2 = __toESM(require("path"));
91
+ var import_prompts = require("@inquirer/prompts");
92
+ var import_chalk3 = __toESM(require("chalk"));
93
+ var import_commander = require("commander");
94
+ var import_ora2 = __toESM(require("ora"));
95
+ var import_tar = require("tar");
96
+
97
+ // src/utils/config.ts
89
98
  var fs = __toESM(require("fs"));
90
99
  var os = __toESM(require("os"));
91
100
  var path = __toESM(require("path"));
92
- var import_prompts = require("@inquirer/prompts");
93
- var import_chalk2 = __toESM(require("chalk"));
94
- var import_commander = require("commander");
101
+ function getAuthPath() {
102
+ return path.join(os.homedir(), ".commet", "auth.json");
103
+ }
104
+ function getProjectConfigPath() {
105
+ return path.join(process.cwd(), ".commet", "config.json");
106
+ }
107
+ function getProjectConfigDir() {
108
+ return path.join(process.cwd(), ".commet");
109
+ }
110
+ function authExists() {
111
+ return fs.existsSync(getAuthPath());
112
+ }
113
+ function loadAuth() {
114
+ try {
115
+ const authPath = getAuthPath();
116
+ if (!fs.existsSync(authPath)) {
117
+ return null;
118
+ }
119
+ const data = fs.readFileSync(authPath, "utf8");
120
+ return JSON.parse(data);
121
+ } catch {
122
+ return null;
123
+ }
124
+ }
125
+ function saveAuth(data) {
126
+ const authPath = getAuthPath();
127
+ fs.mkdirSync(path.dirname(authPath), { recursive: true });
128
+ fs.writeFileSync(authPath, JSON.stringify(data, null, 2), "utf8");
129
+ }
130
+ function clearAuth() {
131
+ const authPath = getAuthPath();
132
+ if (fs.existsSync(authPath)) {
133
+ fs.unlinkSync(authPath);
134
+ }
135
+ }
136
+ function projectConfigExists() {
137
+ return fs.existsSync(getProjectConfigPath());
138
+ }
139
+ function loadProjectConfig() {
140
+ try {
141
+ const configPath = getProjectConfigPath();
142
+ if (!fs.existsSync(configPath)) {
143
+ return null;
144
+ }
145
+ const data = fs.readFileSync(configPath, "utf8");
146
+ return JSON.parse(data);
147
+ } catch {
148
+ return null;
149
+ }
150
+ }
151
+ function saveProjectConfig(data) {
152
+ const configDir = getProjectConfigDir();
153
+ const configPath = getProjectConfigPath();
154
+ fs.mkdirSync(configDir, { recursive: true });
155
+ fs.writeFileSync(configPath, JSON.stringify(data, null, 2), "utf8");
156
+ }
157
+ function clearProjectConfig() {
158
+ const configDir = getProjectConfigDir();
159
+ if (fs.existsSync(configDir)) {
160
+ fs.rmSync(configDir, { recursive: true, force: true });
161
+ }
162
+ }
163
+
164
+ // src/utils/api.ts
165
+ function getBaseURL(environment) {
166
+ if (environment === "production") {
167
+ return "https://commet.co";
168
+ }
169
+ return "https://sandbox.commet.co";
170
+ }
171
+ async function apiRequest(endpoint, options = {}) {
172
+ const auth = loadAuth();
173
+ if (!auth) {
174
+ return { error: "Not authenticated. Run `commet login` first." };
175
+ }
176
+ try {
177
+ const response = await fetch(endpoint, {
178
+ ...options,
179
+ headers: {
180
+ ...options.headers,
181
+ Authorization: `Bearer ${auth.token}`,
182
+ "Content-Type": "application/json"
183
+ }
184
+ });
185
+ if (!response.ok) {
186
+ const errorData = await response.json().catch(() => ({}));
187
+ return {
188
+ error: errorData.message || errorData.error || `Request failed with status ${response.status}`
189
+ };
190
+ }
191
+ const data = await response.json();
192
+ return { data };
193
+ } catch (error) {
194
+ return {
195
+ error: error instanceof Error ? error.message : "Unknown error occurred"
196
+ };
197
+ }
198
+ }
199
+
200
+ // src/utils/login-flow.ts
201
+ var import_chalk = __toESM(require("chalk"));
202
+ var import_open = __toESM(require("open"));
95
203
  var import_ora = __toESM(require("ora"));
96
- var import_tar = require("tar");
204
+ function sleep(ms) {
205
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
206
+ }
207
+ async function performLogin(environment) {
208
+ const baseURL = getBaseURL(environment);
209
+ const spinner = (0, import_ora.default)("Initiating login flow...").start();
210
+ try {
211
+ const deviceResponse = await fetch(`${baseURL}/api/auth/device/code`, {
212
+ method: "POST",
213
+ headers: { "Content-Type": "application/json" },
214
+ body: JSON.stringify({
215
+ client_id: "commet-cli",
216
+ scope: "openid profile email"
217
+ })
218
+ });
219
+ if (!deviceResponse.ok) {
220
+ spinner.fail("Failed to initiate login");
221
+ return false;
222
+ }
223
+ const deviceData = await deviceResponse.json();
224
+ const {
225
+ device_code,
226
+ user_code,
227
+ verification_uri_complete,
228
+ interval = 5
229
+ } = deviceData;
230
+ spinner.stop();
231
+ console.log(import_chalk.default.bold("\n\u{1F510} Commet CLI Login\n"));
232
+ console.log("Visit the following URL in your browser:");
233
+ console.log(import_chalk.default.cyan.underline(verification_uri_complete));
234
+ console.log("\nOr enter this code manually:");
235
+ console.log(import_chalk.default.bold.green(` ${user_code}`));
236
+ console.log(import_chalk.default.dim("\nOpening browser...\n"));
237
+ try {
238
+ await (0, import_open.default)(verification_uri_complete);
239
+ } catch {
240
+ console.log(import_chalk.default.yellow("\u26A0 Could not open browser automatically."));
241
+ }
242
+ const pollSpinner = (0, import_ora.default)("Waiting for authorization...").start();
243
+ let pollingInterval = interval;
244
+ let attempts = 0;
245
+ const maxAttempts = Math.floor(180 / pollingInterval);
246
+ while (attempts < maxAttempts) {
247
+ attempts++;
248
+ await sleep(pollingInterval * 1e3);
249
+ try {
250
+ const tokenResponse = await fetch(`${baseURL}/api/auth/device/token`, {
251
+ method: "POST",
252
+ headers: { "Content-Type": "application/json" },
253
+ body: JSON.stringify({
254
+ grant_type: "urn:ietf:params:oauth:grant-type:device_code",
255
+ device_code,
256
+ client_id: "commet-cli"
257
+ })
258
+ });
259
+ const tokenData = await tokenResponse.json();
260
+ if (tokenData.access_token) {
261
+ const authConfig = {
262
+ token: tokenData.access_token,
263
+ environment
264
+ };
265
+ if (tokenData.refresh_token) {
266
+ authConfig.refreshToken = tokenData.refresh_token;
267
+ }
268
+ if (tokenData.expires_in) {
269
+ authConfig.expiresAt = Date.now() + tokenData.expires_in * 1e3;
270
+ }
271
+ saveAuth(authConfig);
272
+ pollSpinner.succeed("Successfully logged in!");
273
+ return true;
274
+ }
275
+ if (tokenData.error === "authorization_pending") {
276
+ continue;
277
+ }
278
+ if (tokenData.error === "slow_down") {
279
+ pollingInterval += 5;
280
+ continue;
281
+ }
282
+ if (tokenData.error === "access_denied") {
283
+ pollSpinner.fail("Authorization denied");
284
+ return false;
285
+ }
286
+ if (tokenData.error === "expired_token") {
287
+ pollSpinner.fail("Code expired");
288
+ return false;
289
+ }
290
+ pollSpinner.fail("Authorization failed");
291
+ return false;
292
+ } catch {
293
+ pollSpinner.fail("Network error");
294
+ return false;
295
+ }
296
+ }
297
+ pollSpinner.fail("Login timed out");
298
+ return false;
299
+ } catch {
300
+ spinner.fail("Login failed");
301
+ return false;
302
+ }
303
+ }
97
304
 
98
305
  // src/utils/prompt-theme.ts
99
- var import_chalk = __toESM(require("chalk"));
100
- var commetColor = import_chalk.default.hex("#5BC0B0");
306
+ var import_chalk2 = __toESM(require("chalk"));
307
+ var commetColor = import_chalk2.default.hex("#5BC0B0");
101
308
  var promptTheme = {
102
309
  prefix: commetColor("\u276F"),
103
310
  style: {
104
311
  answer: commetColor,
105
- message: import_chalk.default.bold,
106
- error: import_chalk.default.red,
107
- help: import_chalk.default.dim,
312
+ message: import_chalk2.default.bold,
313
+ error: import_chalk2.default.red,
314
+ help: import_chalk2.default.dim,
108
315
  highlight: commetColor.bold,
109
316
  // Selected option in mint
110
- description: import_chalk.default.dim,
111
- defaultAnswer: import_chalk.default.dim
317
+ description: import_chalk2.default.dim,
318
+ defaultAnswer: import_chalk2.default.dim
112
319
  }
113
320
  };
114
321
 
@@ -118,43 +325,39 @@ var TEMPLATES = [
118
325
  {
119
326
  name: "fixed",
120
327
  dir: "fixed-saas",
328
+ templateId: "fixed-saas",
121
329
  description: "Fixed subscriptions (monthly/yearly plans)"
122
330
  },
123
331
  {
124
332
  name: "seats",
125
333
  dir: "team-saas",
334
+ templateId: "seat-based-saas",
126
335
  description: "Seat-based billing (per team member)"
127
336
  },
128
337
  {
129
338
  name: "credits",
130
339
  dir: "credits-saas",
340
+ templateId: "credits-saas",
131
341
  description: "Credit-based billing (prepaid usage blocks)"
132
342
  },
133
343
  {
134
344
  name: "usage-based",
135
345
  dir: "usage-based-saas",
346
+ templateId: "usage-based-saas",
136
347
  description: "Usage-based billing (metered, pay for what you use)"
137
348
  }
138
349
  ];
139
- function detectPackageManager() {
140
- const agent = process.env.npm_config_user_agent;
141
- if (!agent) return "npm";
142
- if (agent.startsWith("pnpm")) return "pnpm";
143
- if (agent.startsWith("yarn")) return "yarn";
144
- if (agent.startsWith("bun")) return "bun";
145
- return "npm";
146
- }
147
350
  async function downloadTemplate(templateDir, dest, ref) {
148
351
  const url = `https://codeload.github.com/${GITHUB_REPO}/tar.gz/${ref}`;
149
352
  const response = await fetch(url);
150
353
  if (!response.ok) {
151
354
  throw new Error(`Failed to download (HTTP ${response.status})`);
152
355
  }
153
- const tempFile = path.join(os.tmpdir(), `commet-${Date.now()}.tar.gz`);
356
+ const tempFile = path2.join(os2.tmpdir(), `commet-${Date.now()}.tar.gz`);
154
357
  try {
155
358
  const buffer = Buffer.from(await response.arrayBuffer());
156
- fs.writeFileSync(tempFile, buffer);
157
- fs.mkdirSync(dest, { recursive: true });
359
+ fs2.writeFileSync(tempFile, buffer);
360
+ fs2.mkdirSync(dest, { recursive: true });
158
361
  await (0, import_tar.extract)({
159
362
  file: tempFile,
160
363
  cwd: dest,
@@ -165,40 +368,49 @@ async function downloadTemplate(templateDir, dest, ref) {
165
368
  }
166
369
  });
167
370
  } finally {
168
- if (fs.existsSync(tempFile)) {
169
- fs.unlinkSync(tempFile);
371
+ if (fs2.existsSync(tempFile)) {
372
+ fs2.unlinkSync(tempFile);
170
373
  }
171
374
  }
172
- const files = fs.readdirSync(dest);
375
+ const files = fs2.readdirSync(dest);
173
376
  if (files.length === 0) {
174
377
  throw new Error(`Template "${templateDir}" not found in repository`);
175
378
  }
176
379
  }
177
380
  function updatePackageJson(dest, projectName) {
178
- const pkgPath = path.join(dest, "package.json");
179
- const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
381
+ const pkgPath = path2.join(dest, "package.json");
382
+ const pkg = JSON.parse(fs2.readFileSync(pkgPath, "utf-8"));
180
383
  pkg.name = projectName;
181
384
  pkg.version = "0.0.1";
182
385
  pkg.private = true;
183
- fs.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}
386
+ fs2.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}
184
387
  `);
185
388
  }
186
389
  function copyEnvExample(dest) {
187
- const examplePath = path.join(dest, ".env.example");
188
- const envPath = path.join(dest, ".env");
189
- if (fs.existsSync(examplePath)) {
190
- fs.copyFileSync(examplePath, envPath);
390
+ const examplePath = path2.join(dest, ".env.example");
391
+ const envPath = path2.join(dest, ".env");
392
+ if (fs2.existsSync(examplePath)) {
393
+ fs2.copyFileSync(examplePath, envPath);
191
394
  }
192
395
  }
396
+ function linkProject(dest, orgId, orgName, environment) {
397
+ const commetDir = path2.join(dest, ".commet");
398
+ fs2.mkdirSync(commetDir, { recursive: true });
399
+ fs2.writeFileSync(
400
+ path2.join(commetDir, "config.json"),
401
+ JSON.stringify({ orgId, orgName, environment }, null, 2),
402
+ "utf8"
403
+ );
404
+ }
193
405
  var createCommand = new import_commander.Command("create").description("Create a new Commet app from a template").argument("[name]", "Project name").option(
194
406
  "-t, --template <template>",
195
407
  "Template to use (fixed, seats, credits, usage-based)"
196
408
  ).option("--ref <ref>", "Git ref to fetch templates from", "main").option("--list", "List available templates").action(async (argName, opts) => {
197
409
  if (opts.list) {
198
- console.log(import_chalk2.default.bold("\nAvailable templates:\n"));
410
+ console.log(import_chalk3.default.bold("\nAvailable templates:\n"));
199
411
  for (const t of TEMPLATES) {
200
412
  console.log(
201
- ` ${commetColor(t.name.padEnd(14))}${import_chalk2.default.dim(t.description)}`
413
+ ` ${commetColor(t.name.padEnd(14))}${import_chalk3.default.dim(t.description)}`
202
414
  );
203
415
  }
204
416
  console.log();
@@ -213,19 +425,82 @@ var createCommand = new import_commander.Command("create").description("Create a
213
425
  });
214
426
  }
215
427
  } catch {
216
- console.log(import_chalk2.default.yellow("\n\u26A0 Cancelled"));
428
+ console.log(import_chalk3.default.yellow("\n\u26A0 Cancelled"));
217
429
  return;
218
430
  }
219
- const dest = path.resolve(projectName);
220
- if (fs.existsSync(dest)) {
221
- console.log(import_chalk2.default.red(`\u2717 Directory "${projectName}" already exists`));
431
+ const dest = path2.resolve(projectName);
432
+ if (fs2.existsSync(dest)) {
433
+ console.log(
434
+ import_chalk3.default.red(`\u2717 Directory "${projectName}" already exists`)
435
+ );
222
436
  return;
223
437
  }
438
+ if (!authExists()) {
439
+ let environment;
440
+ try {
441
+ environment = await (0, import_prompts.select)({
442
+ message: "Environment:",
443
+ choices: [
444
+ {
445
+ name: `Sandbox ${import_chalk3.default.dim("(Development)")}`,
446
+ value: "sandbox"
447
+ },
448
+ { name: "Production", value: "production" }
449
+ ],
450
+ default: "sandbox",
451
+ theme: promptTheme
452
+ });
453
+ } catch {
454
+ console.log(import_chalk3.default.yellow("\n\u26A0 Cancelled"));
455
+ return;
456
+ }
457
+ const loggedIn = await performLogin(environment);
458
+ if (!loggedIn) {
459
+ return;
460
+ }
461
+ }
462
+ const auth = loadAuth();
463
+ const baseURL = getBaseURL(auth.environment);
464
+ const orgsSpinner = (0, import_ora2.default)("Fetching organizations...").start();
465
+ const orgsResult = await apiRequest(`${baseURL}/api/cli/organizations`);
466
+ if (orgsResult.error || !orgsResult.data) {
467
+ orgsSpinner.fail("Failed to fetch organizations");
468
+ console.log(import_chalk3.default.dim(orgsResult.error));
469
+ return;
470
+ }
471
+ const { organizations } = orgsResult.data;
472
+ orgsSpinner.stop();
473
+ if (organizations.length === 0) {
474
+ console.log(import_chalk3.default.yellow("\u26A0 No organizations found"));
475
+ console.log(
476
+ import_chalk3.default.dim("Create an organization at https://commet.co first")
477
+ );
478
+ return;
479
+ }
480
+ let selectedOrg;
481
+ if (organizations.length === 1) {
482
+ selectedOrg = organizations[0];
483
+ } else {
484
+ try {
485
+ const orgId = await (0, import_prompts.select)({
486
+ message: "Organization:",
487
+ choices: organizations.map((org) => ({
488
+ name: `${org.name} ${import_chalk3.default.dim(`(${org.slug})`)}`,
489
+ value: org.id
490
+ })),
491
+ theme: promptTheme
492
+ });
493
+ selectedOrg = organizations.find((org) => org.id === orgId);
494
+ } catch {
495
+ console.log(import_chalk3.default.yellow("\n\u26A0 Cancelled"));
496
+ return;
497
+ }
498
+ }
224
499
  let template = TEMPLATES.find((t) => t.name === opts.template);
225
500
  if (opts.template && !template) {
226
- console.log(import_chalk2.default.red(`\u2717 Unknown template "${opts.template}"`));
501
+ console.log(import_chalk3.default.red(`\u2717 Unknown template "${opts.template}"`));
227
502
  console.log(
228
- import_chalk2.default.dim("Run `commet create --list` to see available templates")
503
+ import_chalk3.default.dim("Run `commet create --list` to see available templates")
229
504
  );
230
505
  return;
231
506
  }
@@ -234,7 +509,7 @@ var createCommand = new import_commander.Command("create").description("Create a
234
509
  const selected = await (0, import_prompts.select)({
235
510
  message: "Billing model:",
236
511
  choices: TEMPLATES.map((t) => ({
237
- name: `${t.name.padEnd(14)} ${import_chalk2.default.dim(t.description)}`,
512
+ name: `${t.name.padEnd(14)} ${import_chalk3.default.dim(t.description)}`,
238
513
  value: t.name
239
514
  })),
240
515
  theme: promptTheme
@@ -242,186 +517,91 @@ var createCommand = new import_commander.Command("create").description("Create a
242
517
  template = TEMPLATES.find((t) => t.name === selected);
243
518
  }
244
519
  } catch {
245
- console.log(import_chalk2.default.yellow("\n\u26A0 Cancelled"));
520
+ console.log(import_chalk3.default.yellow("\n\u26A0 Cancelled"));
246
521
  return;
247
522
  }
248
- const spinner = (0, import_ora.default)("Downloading template...").start();
523
+ const downloadSpinner = (0, import_ora2.default)("Downloading template...").start();
249
524
  try {
250
525
  await downloadTemplate(template.dir, dest, opts.ref);
251
- spinner.succeed("Template downloaded");
526
+ downloadSpinner.succeed("Template downloaded");
252
527
  } catch (error) {
253
- spinner.fail("Failed to download template");
528
+ downloadSpinner.fail("Failed to download template");
254
529
  if (error instanceof Error) {
255
- console.error(import_chalk2.default.red(error.message));
530
+ console.error(import_chalk3.default.red(error.message));
256
531
  }
257
- if (fs.existsSync(dest)) {
258
- fs.rmSync(dest, { recursive: true, force: true });
532
+ if (fs2.existsSync(dest)) {
533
+ fs2.rmSync(dest, { recursive: true, force: true });
259
534
  }
260
535
  return;
261
536
  }
262
537
  updatePackageJson(dest, projectName);
263
538
  copyEnvExample(dest);
264
- const pm = detectPackageManager();
265
- const installSpinner = (0, import_ora.default)(`Installing dependencies with ${pm}...`).start();
266
- try {
267
- (0, import_node_child_process.execSync)(`${pm} install`, { cwd: dest, stdio: "ignore" });
268
- installSpinner.succeed("Dependencies installed");
269
- } catch {
270
- installSpinner.warn("Could not install dependencies");
271
- console.log(import_chalk2.default.dim(` Run \`${pm} install\` manually`));
539
+ const planSpinner = (0, import_ora2.default)("Creating plans...").start();
540
+ const templateResult = await apiRequest(`${baseURL}/api/cli/templates`, {
541
+ method: "POST",
542
+ body: JSON.stringify({
543
+ templateId: template.templateId,
544
+ organizationId: selectedOrg.id
545
+ })
546
+ });
547
+ if (templateResult.error || !templateResult.data) {
548
+ planSpinner.fail("Failed to create plans");
549
+ console.log(import_chalk3.default.dim(templateResult.error));
550
+ } else {
551
+ planSpinner.succeed(
552
+ `Created ${templateResult.data.plansCreated} plans and ${templateResult.data.featuresCreated} features`
553
+ );
272
554
  }
273
- console.log(import_chalk2.default.green(`
555
+ linkProject(dest, selectedOrg.id, selectedOrg.name, auth.environment);
556
+ console.log(import_chalk3.default.green(`
274
557
  \u2713 Created ${projectName}`));
275
- console.log(import_chalk2.default.dim(` Template: ${template.name}`));
558
+ console.log(import_chalk3.default.dim(` Template: ${template.name}`));
559
+ console.log(import_chalk3.default.dim(` Organization: ${selectedOrg.name}`));
276
560
  console.log();
277
- console.log(` ${import_chalk2.default.cyan("cd")} ${projectName}`);
278
- console.log(` ${import_chalk2.default.dim("Update .env with your keys")}`);
279
- console.log(` ${import_chalk2.default.cyan(`${pm} dev`)}`);
561
+ console.log(` ${import_chalk3.default.cyan("cd")} ${projectName}`);
562
+ console.log(` ${import_chalk3.default.dim("Update .env with your keys")}`);
563
+ console.log(` ${import_chalk3.default.cyan("npm install")}`);
564
+ console.log(` ${import_chalk3.default.cyan("npm run dev")}`);
280
565
  console.log();
281
566
  });
282
567
 
283
568
  // src/commands/info.ts
284
- var import_chalk3 = __toESM(require("chalk"));
569
+ var import_chalk4 = __toESM(require("chalk"));
285
570
  var import_commander2 = require("commander");
286
-
287
- // src/utils/config.ts
288
- var fs2 = __toESM(require("fs"));
289
- var os2 = __toESM(require("os"));
290
- var path2 = __toESM(require("path"));
291
- function getAuthPath() {
292
- return path2.join(os2.homedir(), ".commet", "auth.json");
293
- }
294
- function getProjectConfigPath() {
295
- return path2.join(process.cwd(), ".commet", "config.json");
296
- }
297
- function getProjectConfigDir() {
298
- return path2.join(process.cwd(), ".commet");
299
- }
300
- function authExists() {
301
- return fs2.existsSync(getAuthPath());
302
- }
303
- function loadAuth() {
304
- try {
305
- const authPath = getAuthPath();
306
- if (!fs2.existsSync(authPath)) {
307
- return null;
308
- }
309
- const data = fs2.readFileSync(authPath, "utf8");
310
- return JSON.parse(data);
311
- } catch {
312
- return null;
313
- }
314
- }
315
- function saveAuth(data) {
316
- const authPath = getAuthPath();
317
- fs2.mkdirSync(path2.dirname(authPath), { recursive: true });
318
- fs2.writeFileSync(authPath, JSON.stringify(data, null, 2), "utf8");
319
- }
320
- function clearAuth() {
321
- const authPath = getAuthPath();
322
- if (fs2.existsSync(authPath)) {
323
- fs2.unlinkSync(authPath);
324
- }
325
- }
326
- function projectConfigExists() {
327
- return fs2.existsSync(getProjectConfigPath());
328
- }
329
- function loadProjectConfig() {
330
- try {
331
- const configPath = getProjectConfigPath();
332
- if (!fs2.existsSync(configPath)) {
333
- return null;
334
- }
335
- const data = fs2.readFileSync(configPath, "utf8");
336
- return JSON.parse(data);
337
- } catch {
338
- return null;
339
- }
340
- }
341
- function saveProjectConfig(data) {
342
- const configDir = getProjectConfigDir();
343
- const configPath = getProjectConfigPath();
344
- fs2.mkdirSync(configDir, { recursive: true });
345
- fs2.writeFileSync(configPath, JSON.stringify(data, null, 2), "utf8");
346
- }
347
- function clearProjectConfig() {
348
- const configDir = getProjectConfigDir();
349
- if (fs2.existsSync(configDir)) {
350
- fs2.rmSync(configDir, { recursive: true, force: true });
351
- }
352
- }
353
-
354
- // src/commands/info.ts
355
571
  var infoCommand = new import_commander2.Command("info").description("Display information about the current project").action(async () => {
356
- console.log(import_chalk3.default.bold("\n\u{1F4E6} Project Information\n"));
572
+ console.log(import_chalk4.default.bold("\n\u{1F4E6} Project Information\n"));
357
573
  if (!authExists()) {
358
- console.log(import_chalk3.default.yellow("Authentication: Not logged in"));
359
- console.log(import_chalk3.default.dim("Run `commet login` to authenticate\n"));
574
+ console.log(import_chalk4.default.yellow("Authentication: Not logged in"));
575
+ console.log(import_chalk4.default.dim("Run `commet login` to authenticate\n"));
360
576
  return;
361
577
  }
362
- console.log(import_chalk3.default.green("Authentication: Logged in \u2713"));
578
+ console.log(import_chalk4.default.green("Authentication: Logged in \u2713"));
363
579
  if (!projectConfigExists()) {
364
- console.log(import_chalk3.default.yellow("\nProject: Not linked"));
580
+ console.log(import_chalk4.default.yellow("\nProject: Not linked"));
365
581
  console.log(
366
- import_chalk3.default.dim("Run `commet link` to connect to an organization\n")
582
+ import_chalk4.default.dim("Run `commet link` to connect to an organization\n")
367
583
  );
368
584
  return;
369
585
  }
370
586
  const projectConfig = loadProjectConfig();
371
587
  if (!projectConfig) {
372
- console.log(import_chalk3.default.red("\nProject: Invalid configuration"));
588
+ console.log(import_chalk4.default.red("\nProject: Invalid configuration"));
373
589
  return;
374
590
  }
375
- console.log(import_chalk3.default.green("\nProject: Linked \u2713"));
376
- console.log(import_chalk3.default.dim(" Organization:"), projectConfig.orgName);
377
- console.log(import_chalk3.default.dim(" Organization ID:"), projectConfig.orgId);
378
- console.log(import_chalk3.default.dim(" Environment:"), projectConfig.environment);
591
+ console.log(import_chalk4.default.green("\nProject: Linked \u2713"));
592
+ console.log(import_chalk4.default.dim(" Organization:"), projectConfig.orgName);
593
+ console.log(import_chalk4.default.dim(" Organization ID:"), projectConfig.orgId);
594
+ console.log(import_chalk4.default.dim(" Environment:"), projectConfig.environment);
379
595
  console.log(
380
- import_chalk3.default.dim("\nRun `commet pull` to generate type definitions\n")
596
+ import_chalk4.default.dim("\nRun `commet pull` to generate type definitions\n")
381
597
  );
382
598
  });
383
599
 
384
600
  // src/commands/link.ts
385
601
  var import_prompts2 = require("@inquirer/prompts");
386
- var import_chalk4 = __toESM(require("chalk"));
602
+ var import_chalk5 = __toESM(require("chalk"));
387
603
  var import_commander3 = require("commander");
388
- var import_ora2 = __toESM(require("ora"));
389
-
390
- // src/utils/api.ts
391
- function getBaseURL(environment) {
392
- if (environment === "production") {
393
- return "https://commet.co";
394
- }
395
- return "https://sandbox.commet.co";
396
- }
397
- async function apiRequest(endpoint, options = {}) {
398
- const auth = loadAuth();
399
- if (!auth) {
400
- return { error: "Not authenticated. Run `commet login` first." };
401
- }
402
- try {
403
- const response = await fetch(endpoint, {
404
- ...options,
405
- headers: {
406
- ...options.headers,
407
- Authorization: `Bearer ${auth.token}`,
408
- "Content-Type": "application/json"
409
- }
410
- });
411
- if (!response.ok) {
412
- const errorData = await response.json().catch(() => ({}));
413
- return {
414
- error: errorData.message || errorData.error || `Request failed with status ${response.status}`
415
- };
416
- }
417
- const data = await response.json();
418
- return { data };
419
- } catch (error) {
420
- return {
421
- error: error instanceof Error ? error.message : "Unknown error occurred"
422
- };
423
- }
424
- }
604
+ var import_ora3 = __toESM(require("ora"));
425
605
 
426
606
  // src/utils/gitignore-updater.ts
427
607
  var fs3 = __toESM(require("fs"));
@@ -459,28 +639,28 @@ function updateGitignore(entry) {
459
639
  // src/commands/link.ts
460
640
  var linkCommand = new import_commander3.Command("link").description("Link this project to a Commet organization").action(async () => {
461
641
  if (!authExists()) {
462
- console.log(import_chalk4.default.red("\u2717 Not authenticated"));
463
- console.log(import_chalk4.default.dim("Run `commet login` first"));
642
+ console.log(import_chalk5.default.red("\u2717 Not authenticated"));
643
+ console.log(import_chalk5.default.dim("Run `commet login` first"));
464
644
  return;
465
645
  }
466
646
  if (projectConfigExists()) {
467
647
  const config = loadProjectConfig();
468
- console.log(import_chalk4.default.yellow("\u26A0 This project is already linked"));
648
+ console.log(import_chalk5.default.yellow("\u26A0 This project is already linked"));
469
649
  console.log(
470
- import_chalk4.default.dim(`Organization: ${config?.orgName} (${config?.environment})`)
650
+ import_chalk5.default.dim(`Organization: ${config?.orgName} (${config?.environment})`)
471
651
  );
472
652
  console.log(
473
- import_chalk4.default.dim(
653
+ import_chalk5.default.dim(
474
654
  "\nRun `commet unlink` first if you want to change the organization"
475
655
  )
476
656
  );
477
657
  return;
478
658
  }
479
- const spinner = (0, import_ora2.default)("Fetching organizations...").start();
659
+ const spinner = (0, import_ora3.default)("Fetching organizations...").start();
480
660
  const auth = loadAuth();
481
661
  if (!auth) {
482
662
  spinner.fail("Authentication error");
483
- console.log(import_chalk4.default.red("\u2717 Could not load authentication"));
663
+ console.log(import_chalk5.default.red("\u2717 Could not load authentication"));
484
664
  return;
485
665
  }
486
666
  const baseURL = getBaseURL(auth.environment);
@@ -489,15 +669,15 @@ var linkCommand = new import_commander3.Command("link").description("Link this p
489
669
  );
490
670
  if (result.error || !result.data) {
491
671
  spinner.fail("Failed to fetch organizations");
492
- console.error(import_chalk4.default.red("Error:"), result.error);
672
+ console.error(import_chalk5.default.red("Error:"), result.error);
493
673
  return;
494
674
  }
495
675
  const { organizations } = result.data;
496
676
  if (organizations.length === 0) {
497
677
  spinner.stop();
498
- console.log(import_chalk4.default.yellow("\u26A0 No organizations found"));
678
+ console.log(import_chalk5.default.yellow("\u26A0 No organizations found"));
499
679
  console.log(
500
- import_chalk4.default.dim("Create an organization at https://commet.co first")
680
+ import_chalk5.default.dim("Create an organization at https://commet.co first")
501
681
  );
502
682
  return;
503
683
  }
@@ -507,18 +687,18 @@ var linkCommand = new import_commander3.Command("link").description("Link this p
507
687
  orgId = await (0, import_prompts2.select)({
508
688
  message: "Select organization:",
509
689
  choices: organizations.map((org) => ({
510
- name: `${org.name} ${import_chalk4.default.dim(`(${org.slug})`)}`,
690
+ name: `${org.name} ${import_chalk5.default.dim(`(${org.slug})`)}`,
511
691
  value: org.id
512
692
  })),
513
693
  theme: promptTheme
514
694
  });
515
695
  } catch (error) {
516
- console.log(import_chalk4.default.yellow("\n\u26A0 Link cancelled"));
696
+ console.log(import_chalk5.default.yellow("\n\u26A0 Link cancelled"));
517
697
  return;
518
698
  }
519
699
  const selectedOrg = organizations.find((org) => org.id === orgId);
520
700
  if (!selectedOrg) {
521
- console.log(import_chalk4.default.red("\u2717 Organization not found"));
701
+ console.log(import_chalk5.default.red("\u2717 Organization not found"));
522
702
  return;
523
703
  }
524
704
  saveProjectConfig({
@@ -527,119 +707,119 @@ var linkCommand = new import_commander3.Command("link").description("Link this p
527
707
  environment: auth.environment
528
708
  });
529
709
  const gitignoreResult = updateGitignore(".commet/");
530
- console.log(import_chalk4.default.green("\n\u2713 Project linked successfully"));
531
- console.log(import_chalk4.default.dim(`Organization: ${selectedOrg.name}`));
532
- console.log(import_chalk4.default.dim(`Environment: ${auth.environment}`));
710
+ console.log(import_chalk5.default.green("\n\u2713 Project linked successfully"));
711
+ console.log(import_chalk5.default.dim(`Organization: ${selectedOrg.name}`));
712
+ console.log(import_chalk5.default.dim(`Environment: ${auth.environment}`));
533
713
  if (gitignoreResult.success) {
534
- console.log(import_chalk4.default.green("\u2713 Updated .gitignore"));
714
+ console.log(import_chalk5.default.green("\u2713 Updated .gitignore"));
535
715
  } else {
536
- console.log(import_chalk4.default.yellow("\u26A0 No .gitignore found"));
537
- console.log(import_chalk4.default.dim("Add .commet/ to your .gitignore file"));
716
+ console.log(import_chalk5.default.yellow("\u26A0 No .gitignore found"));
717
+ console.log(import_chalk5.default.dim("Add .commet/ to your .gitignore file"));
538
718
  }
539
- console.log(import_chalk4.default.dim("\nRun 'commet pull' to generate TypeScript types"));
719
+ console.log(import_chalk5.default.dim("\nRun 'commet pull' to generate TypeScript types"));
540
720
  });
541
721
 
542
722
  // src/commands/list.ts
543
- var import_chalk5 = __toESM(require("chalk"));
723
+ var import_chalk6 = __toESM(require("chalk"));
544
724
  var import_commander4 = require("commander");
545
- var import_ora3 = __toESM(require("ora"));
725
+ var import_ora4 = __toESM(require("ora"));
546
726
  var validTypes = ["features", "seats", "plans"];
547
727
  var listCommand = new import_commander4.Command("list").description("List features, seat types, or plans").argument("<type>", "Type to list (features, seats, or plans)").action(async (type) => {
548
728
  if (!validTypes.includes(type)) {
549
729
  console.log(
550
- import_chalk5.default.red('\u2717 Invalid type. Use "features", "seats", or "plans"')
730
+ import_chalk6.default.red('\u2717 Invalid type. Use "features", "seats", or "plans"')
551
731
  );
552
- console.log(import_chalk5.default.dim("\nExamples:"));
553
- console.log(import_chalk5.default.dim(" commet list features"));
554
- console.log(import_chalk5.default.dim(" commet list seats"));
555
- console.log(import_chalk5.default.dim(" commet list plans"));
732
+ console.log(import_chalk6.default.dim("\nExamples:"));
733
+ console.log(import_chalk6.default.dim(" commet list features"));
734
+ console.log(import_chalk6.default.dim(" commet list seats"));
735
+ console.log(import_chalk6.default.dim(" commet list plans"));
556
736
  return;
557
737
  }
558
738
  if (!authExists()) {
559
- console.log(import_chalk5.default.red("\u2717 Not authenticated"));
560
- console.log(import_chalk5.default.dim("Run `commet login` first"));
739
+ console.log(import_chalk6.default.red("\u2717 Not authenticated"));
740
+ console.log(import_chalk6.default.dim("Run `commet login` first"));
561
741
  return;
562
742
  }
563
743
  if (!projectConfigExists()) {
564
- console.log(import_chalk5.default.red("\u2717 Project not linked"));
744
+ console.log(import_chalk6.default.red("\u2717 Project not linked"));
565
745
  console.log(
566
- import_chalk5.default.dim("Run `commet link` first to connect to an organization")
746
+ import_chalk6.default.dim("Run `commet link` first to connect to an organization")
567
747
  );
568
748
  return;
569
749
  }
570
750
  const projectConfig = loadProjectConfig();
571
751
  if (!projectConfig) {
572
- console.log(import_chalk5.default.red("\u2717 Invalid project configuration"));
752
+ console.log(import_chalk6.default.red("\u2717 Invalid project configuration"));
573
753
  return;
574
754
  }
575
- const spinner = (0, import_ora3.default)(`Fetching ${type}...`).start();
755
+ const spinner = (0, import_ora4.default)(`Fetching ${type}...`).start();
576
756
  const baseURL = getBaseURL(projectConfig.environment);
577
757
  const result = await apiRequest(
578
758
  `${baseURL}/api/cli/types?orgId=${projectConfig.orgId}`
579
759
  );
580
760
  if (result.error || !result.data) {
581
761
  spinner.fail(`Failed to fetch ${type}`);
582
- console.error(import_chalk5.default.red("Error:"), result.error);
762
+ console.error(import_chalk6.default.red("Error:"), result.error);
583
763
  return;
584
764
  }
585
765
  spinner.stop();
586
766
  if (type === "features") {
587
767
  const { features } = result.data;
588
768
  if (features.length === 0) {
589
- console.log(import_chalk5.default.yellow("\u26A0 No features found"));
769
+ console.log(import_chalk6.default.yellow("\u26A0 No features found"));
590
770
  console.log(
591
- import_chalk5.default.dim("Create features in your Commet dashboard first")
771
+ import_chalk6.default.dim("Create features in your Commet dashboard first")
592
772
  );
593
773
  return;
594
774
  }
595
- console.log(import_chalk5.default.bold(`
775
+ console.log(import_chalk6.default.bold(`
596
776
  \u{1F4CA} Features (${features.length})
597
777
  `));
598
778
  for (const feature of features) {
599
- console.log(import_chalk5.default.green(`\u2022 ${feature.code} (${feature.type})`));
600
- console.log(import_chalk5.default.dim(` ${feature.name}`));
779
+ console.log(import_chalk6.default.green(`\u2022 ${feature.code} (${feature.type})`));
780
+ console.log(import_chalk6.default.dim(` ${feature.name}`));
601
781
  if (feature.description) {
602
- console.log(import_chalk5.default.dim(` ${feature.description}`));
782
+ console.log(import_chalk6.default.dim(` ${feature.description}`));
603
783
  }
604
784
  console.log("");
605
785
  }
606
786
  } else if (type === "seats") {
607
787
  const { seatTypes } = result.data;
608
788
  if (seatTypes.length === 0) {
609
- console.log(import_chalk5.default.yellow("\u26A0 No seat types found"));
789
+ console.log(import_chalk6.default.yellow("\u26A0 No seat types found"));
610
790
  console.log(
611
- import_chalk5.default.dim("Create seat types in your Commet dashboard first")
791
+ import_chalk6.default.dim("Create seat types in your Commet dashboard first")
612
792
  );
613
793
  return;
614
794
  }
615
- console.log(import_chalk5.default.bold(`
795
+ console.log(import_chalk6.default.bold(`
616
796
  \u{1F4BA} Seat Types (${seatTypes.length})
617
797
  `));
618
798
  for (const seatType of seatTypes) {
619
799
  console.log(
620
- import_chalk5.default.green(`\u2022 ${seatType.code}${seatType.isFree ? " (Free)" : ""}`)
800
+ import_chalk6.default.green(`\u2022 ${seatType.code}${seatType.isFree ? " (Free)" : ""}`)
621
801
  );
622
- console.log(import_chalk5.default.dim(` ${seatType.name}`));
802
+ console.log(import_chalk6.default.dim(` ${seatType.name}`));
623
803
  if (seatType.description) {
624
- console.log(import_chalk5.default.dim(` ${seatType.description}`));
804
+ console.log(import_chalk6.default.dim(` ${seatType.description}`));
625
805
  }
626
806
  console.log("");
627
807
  }
628
808
  } else {
629
809
  const { plans } = result.data;
630
810
  if (plans.length === 0) {
631
- console.log(import_chalk5.default.yellow("\u26A0 No plans found"));
632
- console.log(import_chalk5.default.dim("Create plans in your Commet dashboard first"));
811
+ console.log(import_chalk6.default.yellow("\u26A0 No plans found"));
812
+ console.log(import_chalk6.default.dim("Create plans in your Commet dashboard first"));
633
813
  return;
634
814
  }
635
- console.log(import_chalk5.default.bold(`
815
+ console.log(import_chalk6.default.bold(`
636
816
  \u{1F4CB} Plans (${plans.length})
637
817
  `));
638
818
  for (const plan of plans) {
639
- console.log(import_chalk5.default.green(`\u2022 ${plan.code}`));
640
- console.log(import_chalk5.default.dim(` ${plan.name}`));
819
+ console.log(import_chalk6.default.green(`\u2022 ${plan.code}`));
820
+ console.log(import_chalk6.default.dim(` ${plan.name}`));
641
821
  if (plan.description) {
642
- console.log(import_chalk5.default.dim(` ${plan.description}`));
822
+ console.log(import_chalk6.default.dim(` ${plan.description}`));
643
823
  }
644
824
  console.log("");
645
825
  }
@@ -648,16 +828,13 @@ var listCommand = new import_commander4.Command("list").description("List featur
648
828
 
649
829
  // src/commands/login.ts
650
830
  var import_prompts3 = require("@inquirer/prompts");
651
- var import_chalk6 = __toESM(require("chalk"));
831
+ var import_chalk7 = __toESM(require("chalk"));
652
832
  var import_commander5 = require("commander");
653
- var import_open = __toESM(require("open"));
654
- var import_ora4 = __toESM(require("ora"));
655
833
  var loginCommand = new import_commander5.Command("login").description("Authenticate with Commet").action(async () => {
656
834
  if (authExists()) {
657
- const auth = loadAuth();
658
- console.log(import_chalk6.default.yellow("\u26A0 You are already logged in."));
835
+ console.log(import_chalk7.default.yellow("\u26A0 You are already logged in."));
659
836
  console.log(
660
- import_chalk6.default.dim(
837
+ import_chalk7.default.dim(
661
838
  "Run `commet logout` first if you want to login with a different account."
662
839
  )
663
840
  );
@@ -669,7 +846,7 @@ var loginCommand = new import_commander5.Command("login").description("Authentic
669
846
  message: "Select environment to login:",
670
847
  choices: [
671
848
  {
672
- name: `Sandbox ${import_chalk6.default.dim("(Development)")}`,
849
+ name: `Sandbox ${import_chalk7.default.dim("(Development)")}`,
673
850
  value: "sandbox"
674
851
  },
675
852
  {
@@ -680,150 +857,37 @@ var loginCommand = new import_commander5.Command("login").description("Authentic
680
857
  default: "sandbox",
681
858
  theme: promptTheme
682
859
  });
683
- } catch (error) {
684
- console.log(import_chalk6.default.yellow("\n\u26A0 Login cancelled"));
860
+ } catch {
861
+ console.log(import_chalk7.default.yellow("\n\u26A0 Login cancelled"));
685
862
  return;
686
863
  }
687
- const spinner = (0, import_ora4.default)("Initiating login flow...").start();
688
- const baseURL = getBaseURL(environment);
689
- try {
690
- const deviceResponse = await fetch(`${baseURL}/api/auth/device/code`, {
691
- method: "POST",
692
- headers: { "Content-Type": "application/json" },
693
- body: JSON.stringify({
694
- client_id: "commet-cli",
695
- scope: "openid profile email"
696
- })
697
- });
698
- if (!deviceResponse.ok) {
699
- spinner.fail("Failed to initiate login");
700
- console.error(import_chalk6.default.red("Error:"), await deviceResponse.text());
701
- return;
702
- }
703
- const deviceData = await deviceResponse.json();
704
- const {
705
- device_code,
706
- user_code,
707
- verification_uri_complete,
708
- interval = 5
709
- } = deviceData;
710
- spinner.stop();
711
- console.log(import_chalk6.default.bold("\n\u{1F510} Commet CLI Login\n"));
712
- console.log("Visit the following URL in your browser:");
713
- console.log(import_chalk6.default.cyan.underline(verification_uri_complete));
714
- console.log("\nOr enter this code manually:");
715
- console.log(import_chalk6.default.bold.green(` ${user_code}`));
716
- console.log(import_chalk6.default.dim("\nOpening browser...\n"));
717
- try {
718
- await (0, import_open.default)(verification_uri_complete);
719
- } catch {
720
- console.log(import_chalk6.default.yellow("\u26A0 Could not open browser automatically."));
721
- }
722
- const pollSpinner = (0, import_ora4.default)("Waiting for authorization...").start();
723
- let pollingInterval = interval;
724
- let attempts = 0;
725
- const maxAttempts = 180 / pollingInterval;
726
- const poll = async () => {
727
- if (attempts >= maxAttempts) {
728
- pollSpinner.fail("Login timed out");
729
- console.log(import_chalk6.default.red("Authorization timed out. Please try again."));
730
- return;
731
- }
732
- attempts++;
733
- try {
734
- const tokenResponse = await fetch(
735
- `${baseURL}/api/auth/device/token`,
736
- {
737
- method: "POST",
738
- headers: { "Content-Type": "application/json" },
739
- body: JSON.stringify({
740
- grant_type: "urn:ietf:params:oauth:grant-type:device_code",
741
- device_code,
742
- client_id: "commet-cli"
743
- })
744
- }
745
- );
746
- const tokenData = await tokenResponse.json();
747
- if (tokenData.access_token) {
748
- const authConfig = {
749
- token: tokenData.access_token,
750
- environment
751
- };
752
- if (tokenData.refresh_token) {
753
- authConfig.refreshToken = tokenData.refresh_token;
754
- }
755
- if (tokenData.expires_in) {
756
- authConfig.expiresAt = Date.now() + tokenData.expires_in * 1e3;
757
- }
758
- saveAuth(authConfig);
759
- pollSpinner.succeed("Successfully logged in!");
760
- console.log(import_chalk6.default.green("\n\u2713 Authentication complete"));
761
- console.log(
762
- import_chalk6.default.dim(
763
- "\nNext steps:\n 1. Run `commet link` to connect a project\n 2. Run `commet pull` to generate types\n"
764
- )
765
- );
766
- return;
767
- }
768
- if (tokenData.error === "authorization_pending") {
769
- setTimeout(() => poll(), pollingInterval * 1e3);
770
- } else if (tokenData.error === "slow_down") {
771
- pollingInterval += 5;
772
- setTimeout(() => poll(), pollingInterval * 1e3);
773
- } else if (tokenData.error === "access_denied") {
774
- pollSpinner.fail("Authorization denied");
775
- console.log(import_chalk6.default.red("\n\u2717 You denied the authorization request."));
776
- return;
777
- } else if (tokenData.error === "expired_token") {
778
- pollSpinner.fail("Code expired");
779
- console.log(
780
- import_chalk6.default.red(
781
- "\n\u2717 The authorization code expired. Please try again."
782
- )
783
- );
784
- return;
785
- } else {
786
- pollSpinner.fail("Authorization failed");
787
- console.log(
788
- import_chalk6.default.red("\n\u2717 Error:"),
789
- tokenData.error || "Unknown error"
790
- );
791
- return;
792
- }
793
- } catch (error) {
794
- pollSpinner.fail("Network error");
795
- console.error(
796
- import_chalk6.default.red("Error:"),
797
- error instanceof Error ? error.message : "Unknown error"
798
- );
799
- }
800
- };
801
- poll();
802
- } catch (error) {
803
- spinner.fail("Login failed");
804
- console.error(
805
- import_chalk6.default.red("Error:"),
806
- error instanceof Error ? error.message : "Unknown error"
864
+ const success = await performLogin(environment);
865
+ if (success) {
866
+ console.log(import_chalk7.default.green("\n\u2713 Authentication complete"));
867
+ console.log(
868
+ import_chalk7.default.dim(
869
+ "\nNext steps:\n 1. Run `commet link` to connect a project\n 2. Run `commet pull` to generate types\n"
870
+ )
807
871
  );
808
872
  }
809
873
  });
810
874
 
811
875
  // src/commands/logout.ts
812
- var import_chalk7 = __toESM(require("chalk"));
876
+ var import_chalk8 = __toESM(require("chalk"));
813
877
  var import_commander6 = require("commander");
814
878
  var logoutCommand = new import_commander6.Command("logout").description("Log out of Commet").action(async () => {
815
879
  if (!authExists()) {
816
- console.log(import_chalk7.default.yellow("\u26A0 You are not logged in."));
880
+ console.log(import_chalk8.default.yellow("\u26A0 You are not logged in."));
817
881
  return;
818
882
  }
819
883
  clearAuth();
820
- console.log(import_chalk7.default.green("\u2713 Successfully logged out"));
884
+ console.log(import_chalk8.default.green("\u2713 Successfully logged out"));
821
885
  });
822
886
 
823
887
  // src/commands/pull.ts
824
888
  var fs6 = __toESM(require("fs"));
825
889
  var path6 = __toESM(require("path"));
826
- var import_chalk8 = __toESM(require("chalk"));
890
+ var import_chalk9 = __toESM(require("chalk"));
827
891
  var import_commander7 = require("commander");
828
892
  var import_ora5 = __toESM(require("ora"));
829
893
 
@@ -931,21 +995,21 @@ function updateTsConfig(entry) {
931
995
  // src/commands/pull.ts
932
996
  var pullCommand = new import_commander7.Command("pull").description("Pull type definitions from Commet").action(async () => {
933
997
  if (!authExists()) {
934
- console.log(import_chalk8.default.red("\u2717 Not authenticated"));
935
- console.log(import_chalk8.default.dim("Run `commet login` first"));
998
+ console.log(import_chalk9.default.red("\u2717 Not authenticated"));
999
+ console.log(import_chalk9.default.dim("Run `commet login` first"));
936
1000
  return;
937
1001
  }
938
1002
  const hasTsConfig = validateTypeScriptProject();
939
1003
  if (!projectConfigExists()) {
940
- console.log(import_chalk8.default.red("\u2717 Project not linked"));
1004
+ console.log(import_chalk9.default.red("\u2717 Project not linked"));
941
1005
  console.log(
942
- import_chalk8.default.dim("Run `commet link` first to connect to an organization")
1006
+ import_chalk9.default.dim("Run `commet link` first to connect to an organization")
943
1007
  );
944
1008
  return;
945
1009
  }
946
1010
  const projectConfig = loadProjectConfig();
947
1011
  if (!projectConfig) {
948
- console.log(import_chalk8.default.red("\u2717 Invalid project configuration"));
1012
+ console.log(import_chalk9.default.red("\u2717 Invalid project configuration"));
949
1013
  return;
950
1014
  }
951
1015
  const spinner = (0, import_ora5.default)("Fetching type definitions...").start();
@@ -955,7 +1019,7 @@ var pullCommand = new import_commander7.Command("pull").description("Pull type d
955
1019
  );
956
1020
  if (result.error || !result.data) {
957
1021
  spinner.fail("Failed to fetch types");
958
- console.error(import_chalk8.default.red("Error:"), result.error);
1022
+ console.error(import_chalk9.default.red("Error:"), result.error);
959
1023
  return;
960
1024
  }
961
1025
  const { seatTypes, features, plans } = result.data;
@@ -968,52 +1032,52 @@ var pullCommand = new import_commander7.Command("pull").description("Pull type d
968
1032
  if (hasTsConfig) {
969
1033
  const tsconfigResult = updateTsConfig(".commet/types.d.ts");
970
1034
  if (tsconfigResult.success) {
971
- console.log(import_chalk8.default.green("\u2713 Updated tsconfig.json"));
1035
+ console.log(import_chalk9.default.green("\u2713 Updated tsconfig.json"));
972
1036
  } else {
973
- console.log(import_chalk8.default.yellow("\u26A0 Could not update tsconfig.json"));
1037
+ console.log(import_chalk9.default.yellow("\u26A0 Could not update tsconfig.json"));
974
1038
  console.log(
975
- import_chalk8.default.dim(
1039
+ import_chalk9.default.dim(
976
1040
  'Add ".commet/types.d.ts" to your tsconfig.json include array'
977
1041
  )
978
1042
  );
979
1043
  }
980
1044
  } else {
981
- console.log(import_chalk8.default.yellow("\u26A0 No tsconfig.json found"));
1045
+ console.log(import_chalk9.default.yellow("\u26A0 No tsconfig.json found"));
982
1046
  console.log(
983
- import_chalk8.default.dim(
1047
+ import_chalk9.default.dim(
984
1048
  'Add ".commet/types.d.ts" to your tsconfig.json to enable types'
985
1049
  )
986
1050
  );
987
1051
  }
988
1052
  const gitignoreResult = updateGitignore(".commet/");
989
1053
  if (gitignoreResult.success) {
990
- console.log(import_chalk8.default.green("\u2713 Updated .gitignore"));
1054
+ console.log(import_chalk9.default.green("\u2713 Updated .gitignore"));
991
1055
  } else {
992
- console.log(import_chalk8.default.yellow("\u26A0 No .gitignore found"));
993
- console.log(import_chalk8.default.dim("Add .commet/ to your .gitignore file"));
1056
+ console.log(import_chalk9.default.yellow("\u26A0 No .gitignore found"));
1057
+ console.log(import_chalk9.default.dim("Add .commet/ to your .gitignore file"));
994
1058
  }
995
- console.log(import_chalk8.default.green("\nSuccess!"));
996
- console.log(import_chalk8.default.dim("\nGenerated types:"));
1059
+ console.log(import_chalk9.default.green("\nSuccess!"));
1060
+ console.log(import_chalk9.default.dim("\nGenerated types:"));
997
1061
  console.log(
998
- import_chalk8.default.dim(
1062
+ import_chalk9.default.dim(
999
1063
  ` Features: ${features.length > 0 ? features.map((f) => f.code).join(", ") : "none"}`
1000
1064
  )
1001
1065
  );
1002
1066
  console.log(
1003
- import_chalk8.default.dim(
1067
+ import_chalk9.default.dim(
1004
1068
  ` Seat types: ${seatTypes.length > 0 ? seatTypes.map((s) => s.code).join(", ") : "none"}`
1005
1069
  )
1006
1070
  );
1007
1071
  console.log(
1008
- import_chalk8.default.dim(
1072
+ import_chalk9.default.dim(
1009
1073
  ` Plans: ${plans.length > 0 ? plans.map((p) => p.code).join(", ") : "none"}`
1010
1074
  )
1011
1075
  );
1012
- console.log(import_chalk8.default.dim(`
1076
+ console.log(import_chalk9.default.dim(`
1013
1077
  Output: ${outputPath}`));
1014
1078
  if (seatTypes.length === 0 && plans.length === 0 && features.length === 0) {
1015
1079
  console.log(
1016
- import_chalk8.default.yellow(
1080
+ import_chalk9.default.yellow(
1017
1081
  "\n\u26A0 No types found. Create features, seat types, and plans in your Commet dashboard."
1018
1082
  )
1019
1083
  );
@@ -1022,19 +1086,19 @@ Output: ${outputPath}`));
1022
1086
 
1023
1087
  // src/commands/switch.ts
1024
1088
  var import_prompts4 = require("@inquirer/prompts");
1025
- var import_chalk9 = __toESM(require("chalk"));
1089
+ var import_chalk10 = __toESM(require("chalk"));
1026
1090
  var import_commander8 = require("commander");
1027
1091
  var import_ora6 = __toESM(require("ora"));
1028
1092
  var switchCommand = new import_commander8.Command("switch").description("Switch to a different organization").action(async () => {
1029
1093
  if (!authExists()) {
1030
- console.log(import_chalk9.default.red("\u2717 Not authenticated"));
1031
- console.log(import_chalk9.default.dim("Run `commet login` first"));
1094
+ console.log(import_chalk10.default.red("\u2717 Not authenticated"));
1095
+ console.log(import_chalk10.default.dim("Run `commet login` first"));
1032
1096
  return;
1033
1097
  }
1034
1098
  if (!projectConfigExists()) {
1035
- console.log(import_chalk9.default.yellow("\u26A0 Project not linked"));
1099
+ console.log(import_chalk10.default.yellow("\u26A0 Project not linked"));
1036
1100
  console.log(
1037
- import_chalk9.default.dim("Run `commet link` first to connect to an organization")
1101
+ import_chalk10.default.dim("Run `commet link` first to connect to an organization")
1038
1102
  );
1039
1103
  return;
1040
1104
  }
@@ -1042,7 +1106,7 @@ var switchCommand = new import_commander8.Command("switch").description("Switch
1042
1106
  const auth = loadAuth();
1043
1107
  if (!auth) {
1044
1108
  spinner.fail("Authentication error");
1045
- console.log(import_chalk9.default.red("\u2717 Could not load authentication"));
1109
+ console.log(import_chalk10.default.red("\u2717 Could not load authentication"));
1046
1110
  return;
1047
1111
  }
1048
1112
  const baseURL = getBaseURL(auth.environment);
@@ -1051,13 +1115,13 @@ var switchCommand = new import_commander8.Command("switch").description("Switch
1051
1115
  );
1052
1116
  if (result.error || !result.data) {
1053
1117
  spinner.fail("Failed to fetch organizations");
1054
- console.error(import_chalk9.default.red("Error:"), result.error);
1118
+ console.error(import_chalk10.default.red("Error:"), result.error);
1055
1119
  return;
1056
1120
  }
1057
1121
  const { organizations } = result.data;
1058
1122
  if (organizations.length === 0) {
1059
1123
  spinner.stop();
1060
- console.log(import_chalk9.default.yellow("\u26A0 No organizations found"));
1124
+ console.log(import_chalk10.default.yellow("\u26A0 No organizations found"));
1061
1125
  return;
1062
1126
  }
1063
1127
  spinner.stop();
@@ -1066,18 +1130,18 @@ var switchCommand = new import_commander8.Command("switch").description("Switch
1066
1130
  orgId = await (0, import_prompts4.select)({
1067
1131
  message: "Select organization:",
1068
1132
  choices: organizations.map((org) => ({
1069
- name: `${org.name} ${import_chalk9.default.dim(`(${org.slug})`)}`,
1133
+ name: `${org.name} ${import_chalk10.default.dim(`(${org.slug})`)}`,
1070
1134
  value: org.id
1071
1135
  })),
1072
1136
  theme: promptTheme
1073
1137
  });
1074
1138
  } catch (error) {
1075
- console.log(import_chalk9.default.yellow("\n\u26A0 Switch cancelled"));
1139
+ console.log(import_chalk10.default.yellow("\n\u26A0 Switch cancelled"));
1076
1140
  return;
1077
1141
  }
1078
1142
  const selectedOrg = organizations.find((org) => org.id === orgId);
1079
1143
  if (!selectedOrg) {
1080
- console.log(import_chalk9.default.red("\u2717 Organization not found"));
1144
+ console.log(import_chalk10.default.red("\u2717 Organization not found"));
1081
1145
  return;
1082
1146
  }
1083
1147
  saveProjectConfig({
@@ -1085,54 +1149,54 @@ var switchCommand = new import_commander8.Command("switch").description("Switch
1085
1149
  orgName: selectedOrg.name,
1086
1150
  environment: auth.environment
1087
1151
  });
1088
- console.log(import_chalk9.default.green("\n\u2713 Switched organization successfully!"));
1089
- console.log(import_chalk9.default.dim("\nNew configuration:"));
1090
- console.log(import_chalk9.default.dim(` Organization: ${selectedOrg.name}`));
1091
- console.log(import_chalk9.default.dim(` Environment: ${auth.environment}`));
1152
+ console.log(import_chalk10.default.green("\n\u2713 Switched organization successfully!"));
1153
+ console.log(import_chalk10.default.dim("\nNew configuration:"));
1154
+ console.log(import_chalk10.default.dim(` Organization: ${selectedOrg.name}`));
1155
+ console.log(import_chalk10.default.dim(` Environment: ${auth.environment}`));
1092
1156
  console.log(
1093
- import_chalk9.default.dim(
1157
+ import_chalk10.default.dim(
1094
1158
  "\nRun `commet pull` to update TypeScript types for this organization"
1095
1159
  )
1096
1160
  );
1097
1161
  });
1098
1162
 
1099
1163
  // src/commands/unlink.ts
1100
- var import_chalk10 = __toESM(require("chalk"));
1164
+ var import_chalk11 = __toESM(require("chalk"));
1101
1165
  var import_commander9 = require("commander");
1102
1166
  var unlinkCommand = new import_commander9.Command("unlink").description("Unlink this project from Commet").action(async () => {
1103
1167
  if (!projectConfigExists()) {
1104
1168
  console.log(
1105
- import_chalk10.default.yellow("\u26A0 This project is not linked to any organization")
1169
+ import_chalk11.default.yellow("\u26A0 This project is not linked to any organization")
1106
1170
  );
1107
1171
  return;
1108
1172
  }
1109
1173
  clearProjectConfig();
1110
- console.log(import_chalk10.default.green("\u2713 Project unlinked successfully"));
1111
- console.log(import_chalk10.default.dim("\u2713 Removed .commet/ directory"));
1174
+ console.log(import_chalk11.default.green("\u2713 Project unlinked successfully"));
1175
+ console.log(import_chalk11.default.dim("\u2713 Removed .commet/ directory"));
1112
1176
  console.log(
1113
- import_chalk10.default.dim("\nRun `commet link` to connect to a different organization")
1177
+ import_chalk11.default.dim("\nRun `commet link` to connect to a different organization")
1114
1178
  );
1115
1179
  });
1116
1180
 
1117
1181
  // src/commands/whoami.ts
1118
- var import_chalk11 = __toESM(require("chalk"));
1182
+ var import_chalk12 = __toESM(require("chalk"));
1119
1183
  var import_commander10 = require("commander");
1120
1184
  var whoamiCommand = new import_commander10.Command("whoami").description("Display current authentication and project status").action(async () => {
1121
1185
  if (!authExists()) {
1122
- console.log(import_chalk11.default.yellow("\u26A0 Not logged in"));
1123
- console.log(import_chalk11.default.dim("Run `commet login` to authenticate"));
1186
+ console.log(import_chalk12.default.yellow("\u26A0 Not logged in"));
1187
+ console.log(import_chalk12.default.dim("Run `commet login` to authenticate"));
1124
1188
  return;
1125
1189
  }
1126
- console.log(import_chalk11.default.green("\u2713 Logged in"));
1190
+ console.log(import_chalk12.default.green("\u2713 Logged in"));
1127
1191
  const projectConfig = loadProjectConfig();
1128
1192
  if (projectConfig) {
1129
- console.log(import_chalk11.default.bold("\nProject:"));
1130
- console.log(import_chalk11.default.dim("Organization:"), projectConfig.orgName);
1131
- console.log(import_chalk11.default.dim("Environment:"), projectConfig.environment);
1193
+ console.log(import_chalk12.default.bold("\nProject:"));
1194
+ console.log(import_chalk12.default.dim("Organization:"), projectConfig.orgName);
1195
+ console.log(import_chalk12.default.dim("Environment:"), projectConfig.environment);
1132
1196
  } else {
1133
- console.log(import_chalk11.default.yellow("\n\u26A0 No project linked"));
1197
+ console.log(import_chalk12.default.yellow("\n\u26A0 No project linked"));
1134
1198
  console.log(
1135
- import_chalk11.default.dim(
1199
+ import_chalk12.default.dim(
1136
1200
  "Run `commet link` to connect this directory to an organization"
1137
1201
  )
1138
1202
  );
@@ -1162,7 +1226,7 @@ try {
1162
1226
  if (error.message.includes("outputHelp")) {
1163
1227
  process.exit(0);
1164
1228
  }
1165
- console.error(import_chalk12.default.red("Error:"), error.message);
1229
+ console.error(import_chalk13.default.red("Error:"), error.message);
1166
1230
  }
1167
1231
  process.exit(1);
1168
1232
  }