commet 0.4.3 → 0.5.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 (3) hide show
  1. package/README.md +73 -25
  2. package/dist/index.js +155 -20
  3. package/package.json +2 -1
package/README.md CHANGED
@@ -18,10 +18,13 @@ yarn global add commet
18
18
  # 1. Authenticate with Commet
19
19
  commet login
20
20
 
21
- # 2. Link your project to an organization
21
+ # 2. Navigate to your project directory
22
+ cd apps/dashboard # Recommended: use TypeScript project with tsconfig.json
23
+
24
+ # 3. Link your project to an organization
22
25
  commet link
23
26
 
24
- # 3. Generate TypeScript types
27
+ # 4. Generate TypeScript types (automatically updates tsconfig.json and .gitignore if found)
25
28
  commet pull
26
29
  ```
27
30
 
@@ -68,10 +71,13 @@ commet whoami
68
71
  Link the current directory to a Commet organization.
69
72
 
70
73
  ```bash
74
+ cd apps/dashboard
71
75
  commet link
72
76
  ```
73
77
 
74
- Creates `.commet` file in the current directory with organization configuration.
78
+ **What it does:**
79
+ - Creates `.commet/config.json` with organization configuration
80
+ - Works anywhere, but for best experience use a TypeScript project directory
75
81
 
76
82
  #### `commet unlink`
77
83
 
@@ -104,36 +110,47 @@ commet info
104
110
  Generate TypeScript type definitions from your Commet configuration.
105
111
 
106
112
  ```bash
113
+ cd apps/dashboard # Recommended: TypeScript project directory
107
114
  commet pull
108
- # or specify output file
109
- commet pull -o types/commet.d.ts
110
115
  ```
111
116
 
112
- Creates `.commet.d.ts` with your event and seat types:
117
+ **What it does:**
118
+ 1. Generates `.commet/types.d.ts` with your event and seat types
119
+ 2. Automatically updates `tsconfig.json` to include the types file (if found)
120
+ 3. Automatically updates `.gitignore` to exclude `.commet/` directory
121
+
122
+ **Note:** Works anywhere, but if no `tsconfig.json` is found, you'll need to manually configure TypeScript to include the generated types.
123
+
124
+ **Generated types:**
113
125
 
114
126
  ```typescript
115
- // .commet.d.ts
116
- export type CommetEventType = "api_call" | "email_sent" | "payment_processed";
117
- export type CommetSeatType = "admin" | "editor" | "viewer";
127
+ // .commet/types.d.ts
128
+ declare module '@commet/node' {
129
+ interface CommetGeneratedTypes {
130
+ eventType: "api_call" | "email_sent" | "payment_processed";
131
+ seatType: "admin" | "editor" | "viewer";
132
+ }
133
+ }
134
+
135
+ export {};
118
136
  ```
119
137
 
120
- Use with the SDK:
138
+ **Usage with the SDK:**
121
139
 
122
140
  ```typescript
123
141
  import { Commet } from '@commet/node';
124
- import type { CommetEventType, CommetSeatType } from './.commet';
125
142
 
126
143
  const commet = new Commet({ apiKey: '...' });
127
144
 
128
- // Type-safe event tracking
129
- await commet.usage.events.create<CommetEventType>({
145
+ // Type-safe event tracking - autocomplete works automatically!
146
+ await commet.usage.events.create({
130
147
  customerId: 'cus_123',
131
148
  eventType: 'api_call', // Autocomplete works!
132
149
  timestamp: new Date().toISOString(),
133
150
  });
134
151
 
135
152
  // Type-safe seat management
136
- await commet.seats.add<CommetSeatType>('cus_123', 'admin', 5);
153
+ await commet.seats.add('cus_123', 'admin', 5);
137
154
  ```
138
155
 
139
156
  ### Type Inspection
@@ -171,7 +188,7 @@ Stores authentication credentials. Created by `commet login`.
171
188
 
172
189
  The `environment` field determines which platform your authentication is for (sandbox or production).
173
190
 
174
- ### Project Config (`.commet`)
191
+ ### Project Config (`.commet/config.json`)
175
192
 
176
193
  Stores project-specific configuration. Created by `commet link`.
177
194
 
@@ -183,7 +200,11 @@ Stores project-specific configuration. Created by `commet link`.
183
200
  }
184
201
  ```
185
202
 
186
- **Note:** Add `.commet` to `.gitignore` if different developers use different organizations.
203
+ **Note:** The `.commet/` directory is automatically added to `.gitignore` by `commet pull`. This directory contains:
204
+ - `config.json` - Project configuration
205
+ - `types.d.ts` - Generated TypeScript type definitions
206
+
207
+ Add `.commet/` to `.gitignore` if different developers use different organizations.
187
208
 
188
209
  ## Environments
189
210
 
@@ -206,20 +227,23 @@ Typical development workflow:
206
227
 
207
228
  ```bash
208
229
  # 1. One-time setup (Sandbox)
209
- commet login # Select "Sandbox"
210
- commet link # Choose your organization
230
+ commet login # Select "Sandbox"
231
+ cd apps/dashboard # Navigate to your TypeScript project (must have tsconfig.json)
232
+ commet link # Choose your organization
233
+ commet pull # Generate types (auto-updates tsconfig.json and .gitignore)
211
234
 
212
- # 2. Generate types when you add/change event or seat types
213
- commet pull
235
+ # 2. Develop with type-safe autocomplete
236
+ # Your IDE now has full autocomplete for event and seat types!
214
237
 
215
- # 3. Use types in your code with autocomplete
216
- # (see TypeScript examples above)
238
+ # 3. When you add/change event or seat types in dashboard
239
+ commet pull # Regenerate types
217
240
 
218
241
  # 4. When ready for production
219
242
  commet logout
220
- commet login # Select "Production"
221
- commet link # Link to production organization
222
- commet pull # Generate production types
243
+ commet login # Select "Production"
244
+ cd apps/dashboard # Same TypeScript project directory
245
+ commet link # Link to production organization
246
+ commet pull # Generate production types
223
247
  ```
224
248
 
225
249
  ## Troubleshooting
@@ -228,6 +252,20 @@ commet pull # Generate production types
228
252
 
229
253
  Run `commet login` to authenticate.
230
254
 
255
+ ### "No tsconfig.json found" (Warning)
256
+
257
+ This is just a warning - the CLI will still work, but won't automatically update your `tsconfig.json`.
258
+
259
+ For the best experience, run commands from a TypeScript project directory:
260
+
261
+ ```bash
262
+ cd apps/dashboard # Directory with tsconfig.json
263
+ commet link
264
+ commet pull
265
+ ```
266
+
267
+ The CLI will automatically add `.commet/types.d.ts` to your TypeScript configuration.
268
+
231
269
  ### "Project not linked"
232
270
 
233
271
  Run `commet link` to connect your project to an organization.
@@ -236,6 +274,16 @@ Run `commet link` to connect your project to an organization.
236
274
 
237
275
  Create event types and seat types in your Commet dashboard first, then run `commet pull`.
238
276
 
277
+ ### "Could not update tsconfig.json"
278
+
279
+ The CLI will show a warning but continue. Manually add `.commet/types.d.ts` to your `tsconfig.json`:
280
+
281
+ ```json
282
+ {
283
+ "include": [".commet/types.d.ts", "src/**/*"]
284
+ }
285
+ ```
286
+
239
287
  ### Authentication expired
240
288
 
241
289
  Run `commet login` again. Tokens expire after a certain period.
package/dist/index.js CHANGED
@@ -39,6 +39,9 @@ function getAuthPath() {
39
39
  return path.join(os.homedir(), ".commet", "auth.json");
40
40
  }
41
41
  function getProjectConfigPath() {
42
+ return path.join(process.cwd(), ".commet", "config.json");
43
+ }
44
+ function getProjectConfigDir() {
42
45
  return path.join(process.cwd(), ".commet");
43
46
  }
44
47
  function authExists() {
@@ -83,13 +86,15 @@ function loadProjectConfig() {
83
86
  }
84
87
  }
85
88
  function saveProjectConfig(data) {
89
+ const configDir = getProjectConfigDir();
86
90
  const configPath = getProjectConfigPath();
91
+ fs.mkdirSync(configDir, { recursive: true });
87
92
  fs.writeFileSync(configPath, JSON.stringify(data, null, 2), "utf8");
88
93
  }
89
94
  function clearProjectConfig() {
90
- const configPath = getProjectConfigPath();
91
- if (fs.existsSync(configPath)) {
92
- fs.unlinkSync(configPath);
95
+ const configDir = getProjectConfigDir();
96
+ if (fs.existsSync(configDir)) {
97
+ fs.rmSync(configDir, { recursive: true, force: true });
93
98
  }
94
99
  }
95
100
 
@@ -165,6 +170,39 @@ async function apiRequest(endpoint, options = {}) {
165
170
  }
166
171
  }
167
172
 
173
+ // src/utils/gitignore-updater.ts
174
+ var fs2 = __toESM(require("fs"));
175
+ var path2 = __toESM(require("path"));
176
+ function updateGitignore(entry) {
177
+ const cwd = process.cwd();
178
+ const gitignorePath = path2.join(cwd, ".gitignore");
179
+ try {
180
+ let content = "";
181
+ if (fs2.existsSync(gitignorePath)) {
182
+ content = fs2.readFileSync(gitignorePath, "utf8");
183
+ const lines = content.split("\n");
184
+ for (const line of lines) {
185
+ const trimmed = line.trim();
186
+ if (trimmed === entry) {
187
+ return { success: true };
188
+ }
189
+ }
190
+ }
191
+ if (content && !content.endsWith("\n")) {
192
+ content += "\n";
193
+ }
194
+ content += `${entry}
195
+ `;
196
+ fs2.writeFileSync(gitignorePath, content, "utf8");
197
+ return { success: true };
198
+ } catch (error) {
199
+ return {
200
+ success: false,
201
+ error: error instanceof Error ? error.message : "Unknown error updating .gitignore"
202
+ };
203
+ }
204
+ }
205
+
168
206
  // src/utils/prompt-theme.ts
169
207
  var import_chalk2 = __toESM(require("chalk"));
170
208
  var commetColor = import_chalk2.default.hex("#5BC0B0");
@@ -252,15 +290,17 @@ var linkCommand = new import_commander2.Command("link").description("Link this p
252
290
  orgName: selectedOrg.name,
253
291
  environment: auth.environment
254
292
  });
255
- console.log(import_chalk3.default.green("\n\u2713 Project linked successfully!"));
256
- console.log(import_chalk3.default.dim("\nProject configuration:"));
257
- console.log(import_chalk3.default.dim(` Organization: ${selectedOrg.name}`));
258
- console.log(import_chalk3.default.dim(` Environment: ${auth.environment}`));
259
- console.log(
260
- import_chalk3.default.dim(
261
- "\nNext step:\n Run `commet pull` to generate TypeScript types"
262
- )
263
- );
293
+ const gitignoreResult = updateGitignore(".commet/");
294
+ console.log(import_chalk3.default.green("\n\u2713 Project linked successfully"));
295
+ console.log(import_chalk3.default.dim(`Organization: ${selectedOrg.name}`));
296
+ console.log(import_chalk3.default.dim(`Environment: ${auth.environment}`));
297
+ if (gitignoreResult.success) {
298
+ console.log(import_chalk3.default.green("\u2713 Updated .gitignore"));
299
+ } else {
300
+ console.log(import_chalk3.default.yellow("\u26A0 No .gitignore found"));
301
+ console.log(import_chalk3.default.dim("Add .commet/ to your .gitignore file"));
302
+ }
303
+ console.log(import_chalk3.default.dim("\nRun 'commet pull' to generate TypeScript types"));
264
304
  });
265
305
 
266
306
  // src/commands/list.ts
@@ -523,12 +563,30 @@ var logoutCommand = new import_commander5.Command("logout").description("Log out
523
563
  });
524
564
 
525
565
  // src/commands/pull.ts
526
- var fs2 = __toESM(require("fs"));
527
- var path2 = __toESM(require("path"));
566
+ var fs5 = __toESM(require("fs"));
567
+ var path5 = __toESM(require("path"));
528
568
  var import_chalk7 = __toESM(require("chalk"));
529
569
  var import_commander6 = require("commander");
530
570
  var import_ora4 = __toESM(require("ora"));
531
571
 
572
+ // src/utils/environment-validator.ts
573
+ var fs3 = __toESM(require("fs"));
574
+ var path3 = __toESM(require("path"));
575
+ function validateTypeScriptProject() {
576
+ const cwd = process.cwd();
577
+ const tsconfigPath = path3.join(cwd, "tsconfig.json");
578
+ if (!fs3.existsSync(tsconfigPath)) {
579
+ return false;
580
+ }
581
+ try {
582
+ const content = fs3.readFileSync(tsconfigPath, "utf8");
583
+ JSON.parse(content);
584
+ return true;
585
+ } catch (error) {
586
+ return false;
587
+ }
588
+ }
589
+
532
590
  // src/utils/generator.ts
533
591
  function generateTypes(eventTypes, seatTypes) {
534
592
  const eventTypeUnion = eventTypes.length > 0 ? eventTypes.map((e) => `"${e.code}"`).join(" | ") : "string";
@@ -574,16 +632,61 @@ declare module '@commet/node' {
574
632
  seatType: ${seatTypeUnion};
575
633
  }
576
634
  }
635
+
636
+ // This export is required for TypeScript to treat this file as a module
637
+ // and apply the module augmentation above
638
+ export {};
577
639
  `;
578
640
  }
579
641
 
642
+ // src/utils/tsconfig-updater.ts
643
+ var fs4 = __toESM(require("fs"));
644
+ var path4 = __toESM(require("path"));
645
+ var import_jsonc_parser = require("jsonc-parser");
646
+ function updateTsConfig(entry) {
647
+ const cwd = process.cwd();
648
+ const tsconfigPath = path4.join(cwd, "tsconfig.json");
649
+ try {
650
+ if (!fs4.existsSync(tsconfigPath)) {
651
+ return {
652
+ success: false,
653
+ error: "tsconfig.json not found"
654
+ };
655
+ }
656
+ const content = fs4.readFileSync(tsconfigPath, "utf8");
657
+ const config = (0, import_jsonc_parser.parse)(content);
658
+ if (config.include && Array.isArray(config.include)) {
659
+ if (config.include.includes(entry)) {
660
+ return { success: true };
661
+ }
662
+ }
663
+ const currentInclude = config.include || [];
664
+ const newInclude = [...currentInclude, entry];
665
+ const edits = (0, import_jsonc_parser.modify)(content, ["include"], newInclude, {
666
+ formattingOptions: {
667
+ insertSpaces: true,
668
+ tabSize: 2
669
+ }
670
+ });
671
+ const updatedContent = (0, import_jsonc_parser.applyEdits)(content, edits);
672
+ fs4.writeFileSync(tsconfigPath, updatedContent, "utf8");
673
+ return { success: true };
674
+ } catch (error) {
675
+ return {
676
+ success: false,
677
+ error: error instanceof Error ? error.message : "Unknown error updating tsconfig.json"
678
+ };
679
+ }
680
+ }
681
+
580
682
  // src/commands/pull.ts
581
- var pullCommand = new import_commander6.Command("pull").description("Pull type definitions from Commet").option("-o, --output <file>", "Output file path", ".commet.d.ts").action(async (options) => {
683
+ var pullCommand = new import_commander6.Command("pull").description("Pull type definitions from Commet").action(async () => {
582
684
  if (!authExists()) {
583
685
  console.log(import_chalk7.default.red("\u2717 Not authenticated"));
584
686
  console.log(import_chalk7.default.dim("Run `commet login` first"));
585
687
  return;
586
688
  }
689
+ const hasTsConfig = validateTypeScriptProject();
587
690
  if (!projectConfigExists()) {
588
691
  console.log(import_chalk7.default.red("\u2717 Project not linked"));
589
692
  console.log(
@@ -608,10 +711,39 @@ var pullCommand = new import_commander6.Command("pull").description("Pull type d
608
711
  }
609
712
  const { eventTypes, seatTypes } = result.data;
610
713
  const typeDefinitions = generateTypes(eventTypes, seatTypes);
611
- const outputPath = path2.resolve(process.cwd(), options.output);
612
- fs2.writeFileSync(outputPath, typeDefinitions, "utf8");
714
+ const commetDir = path5.resolve(process.cwd(), ".commet");
715
+ const outputPath = path5.join(commetDir, "types.d.ts");
716
+ fs5.mkdirSync(commetDir, { recursive: true });
717
+ fs5.writeFileSync(outputPath, typeDefinitions, "utf8");
613
718
  spinner.succeed("Type definitions generated!");
614
- console.log(import_chalk7.default.green("\n\u2713 Success"));
719
+ if (hasTsConfig) {
720
+ const tsconfigResult = updateTsConfig(".commet/types.d.ts");
721
+ if (tsconfigResult.success) {
722
+ console.log(import_chalk7.default.green("\u2713 Updated tsconfig.json"));
723
+ } else {
724
+ console.log(import_chalk7.default.yellow("\u26A0 Could not update tsconfig.json"));
725
+ console.log(
726
+ import_chalk7.default.dim(
727
+ 'Add ".commet/types.d.ts" to your tsconfig.json include array'
728
+ )
729
+ );
730
+ }
731
+ } else {
732
+ console.log(import_chalk7.default.yellow("\u26A0 No tsconfig.json found"));
733
+ console.log(
734
+ import_chalk7.default.dim(
735
+ 'Add ".commet/types.d.ts" to your tsconfig.json to enable types'
736
+ )
737
+ );
738
+ }
739
+ const gitignoreResult = updateGitignore(".commet/");
740
+ if (gitignoreResult.success) {
741
+ console.log(import_chalk7.default.green("\u2713 Updated .gitignore"));
742
+ } else {
743
+ console.log(import_chalk7.default.yellow("\u26A0 No .gitignore found"));
744
+ console.log(import_chalk7.default.dim("Add .commet/ to your .gitignore file"));
745
+ }
746
+ console.log(import_chalk7.default.green("\nSuccess!"));
615
747
  console.log(import_chalk7.default.dim("\nGenerated types:"));
616
748
  console.log(
617
749
  import_chalk7.default.dim(
@@ -624,7 +756,7 @@ var pullCommand = new import_commander6.Command("pull").description("Pull type d
624
756
  )
625
757
  );
626
758
  console.log(import_chalk7.default.dim(`
627
- Output file: ${outputPath}`));
759
+ Output: ${outputPath}`));
628
760
  if (eventTypes.length === 0 && seatTypes.length === 0) {
629
761
  console.log(
630
762
  import_chalk7.default.yellow(
@@ -722,7 +854,10 @@ var unlinkCommand = new import_commander8.Command("unlink").description("Unlink
722
854
  }
723
855
  clearProjectConfig();
724
856
  console.log(import_chalk9.default.green("\u2713 Project unlinked successfully"));
725
- console.log(import_chalk9.default.dim("Run `commet link` to connect to an organization"));
857
+ console.log(import_chalk9.default.dim("\u2713 Removed .commet/ directory"));
858
+ console.log(
859
+ import_chalk9.default.dim("\nRun `commet link` to connect to a different organization")
860
+ );
726
861
  });
727
862
 
728
863
  // src/commands/whoami.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "commet",
3
- "version": "0.4.3",
3
+ "version": "0.5.0",
4
4
  "description": "Commet CLI - Manage your billing platform from the command line",
5
5
  "bin": {
6
6
  "commet": "./bin/commet"
@@ -22,6 +22,7 @@
22
22
  "@inquirer/prompts": "^7.8.6",
23
23
  "chalk": "^5.3.0",
24
24
  "commander": "^12.0.0",
25
+ "jsonc-parser": "^3.3.1",
25
26
  "open": "^10.0.0",
26
27
  "ora": "^7.0.1",
27
28
  "@commet/node": "0.5.0"