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