httpcat-cli 0.0.25 → 0.0.27-rc.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 (67) hide show
  1. package/.github/workflows/README.md +19 -2
  2. package/.github/workflows/ci.yml +31 -20
  3. package/.github/workflows/homebrew-tap.yml +1 -1
  4. package/.github/workflows/rc-publish.yml +169 -0
  5. package/.github/workflows/release.yml +223 -71
  6. package/README.md +113 -71
  7. package/bun.lock +2933 -0
  8. package/dist/commands/account.d.ts.map +1 -1
  9. package/dist/commands/account.js +14 -7
  10. package/dist/commands/account.js.map +1 -1
  11. package/dist/commands/balances.d.ts.map +1 -0
  12. package/dist/commands/balances.js +171 -0
  13. package/dist/commands/balances.js.map +1 -0
  14. package/dist/commands/buy.d.ts.map +1 -1
  15. package/dist/commands/buy.js +746 -24
  16. package/dist/commands/buy.js.map +1 -1
  17. package/dist/commands/chat.d.ts.map +1 -1
  18. package/dist/commands/chat.js +467 -906
  19. package/dist/commands/chat.js.map +1 -1
  20. package/dist/commands/claim.d.ts.map +1 -0
  21. package/dist/commands/claim.js +65 -0
  22. package/dist/commands/claim.js.map +1 -0
  23. package/dist/commands/create.d.ts.map +1 -1
  24. package/dist/commands/create.js +0 -1
  25. package/dist/commands/create.js.map +1 -1
  26. package/dist/commands/info.d.ts.map +1 -1
  27. package/dist/commands/info.js +128 -26
  28. package/dist/commands/info.js.map +1 -1
  29. package/dist/commands/list.d.ts.map +1 -1
  30. package/dist/commands/list.js +30 -23
  31. package/dist/commands/list.js.map +1 -1
  32. package/dist/commands/positions.d.ts.map +1 -1
  33. package/dist/commands/positions.js +178 -105
  34. package/dist/commands/positions.js.map +1 -1
  35. package/dist/commands/sell.d.ts.map +1 -1
  36. package/dist/commands/sell.js +713 -24
  37. package/dist/commands/sell.js.map +1 -1
  38. package/dist/index.js +417 -109
  39. package/dist/index.js.map +1 -1
  40. package/dist/interactive/shell.d.ts.map +1 -1
  41. package/dist/interactive/shell.js +328 -179
  42. package/dist/interactive/shell.js.map +1 -1
  43. package/dist/mcp/tools.d.ts.map +1 -1
  44. package/dist/mcp/tools.js +8 -8
  45. package/dist/mcp/tools.js.map +1 -1
  46. package/dist/utils/constants.d.ts.map +1 -0
  47. package/dist/utils/constants.js +66 -0
  48. package/dist/utils/constants.js.map +1 -0
  49. package/dist/utils/formatting.d.ts.map +1 -1
  50. package/dist/utils/formatting.js +3 -5
  51. package/dist/utils/formatting.js.map +1 -1
  52. package/dist/utils/token-resolver.d.ts.map +1 -1
  53. package/dist/utils/token-resolver.js +71 -40
  54. package/dist/utils/token-resolver.js.map +1 -1
  55. package/dist/utils/validation.d.ts.map +1 -1
  56. package/dist/utils/validation.js +4 -3
  57. package/dist/utils/validation.js.map +1 -1
  58. package/jest.config.js +1 -1
  59. package/package.json +19 -13
  60. package/.claude/settings.local.json +0 -41
  61. package/dist/commands/balance.d.ts.map +0 -1
  62. package/dist/commands/balance.js +0 -112
  63. package/dist/commands/balance.js.map +0 -1
  64. package/homebrew-httpcat/Formula/httpcat.rb +0 -18
  65. package/homebrew-httpcat/README.md +0 -31
  66. package/homebrew-httpcat/homebrew-httpcat/Formula/httpcat.rb +0 -18
  67. package/homebrew-httpcat/homebrew-httpcat/README.md +0 -31
@@ -2,24 +2,28 @@ name: Release
2
2
 
3
3
  on:
4
4
  push:
5
+ branches:
6
+ - main
5
7
  tags:
6
- - 'v*.*.*' # Triggers on semantic version tags (e.g., v1.2.3)
8
+ - "v*.*.*" # Triggers on semantic version tags (e.g., v1.2.3)
7
9
  workflow_dispatch:
8
10
  inputs:
9
11
  version:
10
- description: 'Version to release (e.g., 1.2.3)'
11
- required: true
12
+ description: "Version to release (e.g., 1.2.3). Leave empty for auto-detection from commits."
13
+ required: false
12
14
  type: string
13
15
 
14
16
  env:
15
- NODE_VERSION: '20'
16
- REGISTRY_URL: 'https://registry.npmjs.org'
17
+ NODE_VERSION: "20"
18
+ REGISTRY_URL: "https://registry.npmjs.org"
17
19
 
18
20
  jobs:
19
21
  # Job 1: Validate and prepare release
20
22
  prepare:
21
23
  name: Prepare Release
22
24
  runs-on: ubuntu-latest
25
+ permissions:
26
+ contents: write # For creating tags
23
27
  outputs:
24
28
  version: ${{ steps.version.outputs.version }}
25
29
  tag: ${{ steps.version.outputs.tag }}
@@ -27,54 +31,188 @@ jobs:
27
31
  release-notes: ${{ steps.notes.outputs.notes }}
28
32
  steps:
29
33
  - name: Checkout code
30
- uses: actions/checkout@v4
34
+ uses: actions/checkout@v6
31
35
  with:
32
- fetch-depth: 0 # Full history for changelog generation
36
+ fetch-depth: 0 # Full history for changelog generation
37
+ token: ${{ secrets.GITHUB_TOKEN }}
33
38
 
34
39
  - name: Setup Node.js
35
- uses: actions/setup-node@v4
40
+ uses: actions/setup-node@v6
36
41
  with:
37
42
  node-version: ${{ env.NODE_VERSION }}
38
43
  registry-url: ${{ env.REGISTRY_URL }}
39
44
 
40
- - name: Extract version from tag
45
+ - name: Determine version
41
46
  id: version
42
- run: |
43
- if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
44
- VERSION="${{ github.event.inputs.version }}"
45
- # Remove 'v' prefix if present
46
- VERSION=${VERSION#v}
47
- else
48
- # Extract from tag (e.g., v1.2.3 -> 1.2.3)
49
- VERSION=${GITHUB_REF#refs/tags/v}
50
- fi
51
-
52
- # Validate semantic version format
53
- if ! echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9-]+(\.[0-9]+)?)?$'; then
54
- echo "❌ Invalid version format: $VERSION"
55
- echo "Expected format: X.Y.Z or X.Y.Z-prerelease"
56
- exit 1
57
- fi
58
-
59
- echo "version=$VERSION" >> $GITHUB_OUTPUT
60
- echo "tag=v$VERSION" >> $GITHUB_OUTPUT
61
- echo "npm-version=$VERSION" >> $GITHUB_OUTPUT
62
- echo "✅ Version: $VERSION"
47
+ uses: actions/github-script@v8
48
+ with:
49
+ script: |
50
+ const fs = require('fs');
51
+ const { execSync } = require('child_process');
52
+
53
+ let version;
54
+
55
+ if (context.eventName === 'workflow_dispatch' && context.payload.inputs.version) {
56
+ // Manual workflow dispatch with version provided
57
+ version = context.payload.inputs.version.replace(/^v/, '');
58
+ } else if (context.ref.startsWith('refs/tags/')) {
59
+ // Tag-based release
60
+ version = context.ref.replace('refs/tags/v', '');
61
+ } else {
62
+ // Push to main - auto-detect version bump from commits
63
+ console.log('🔍 Analyzing commits to determine version bump...');
64
+
65
+ // Get current version from package.json
66
+ const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
67
+ const currentVersion = packageJson.version.replace(/-.*$/, '');
68
+ console.log(`Current version: ${currentVersion}`);
69
+
70
+ // Get last release tag
71
+ let lastTag;
72
+ try {
73
+ const { data: releases } = await github.rest.repos.listReleases({
74
+ owner: context.repo.owner,
75
+ repo: context.repo.repo,
76
+ per_page: 1
77
+ });
78
+ lastTag = releases.length > 0 ? releases[0].tag_name : null;
79
+ } catch (e) {
80
+ console.log('Could not fetch releases, trying git tags...');
81
+ try {
82
+ lastTag = execSync('git describe --tags --abbrev=0', { encoding: 'utf8' }).trim();
83
+ } catch (e2) {
84
+ lastTag = null;
85
+ }
86
+ }
87
+
88
+ // Get commits to analyze
89
+ let compareData;
90
+ if (lastTag) {
91
+ console.log(`Last release tag: ${lastTag}`);
92
+
93
+ // Get commits since last tag
94
+ let baseSha;
95
+ try {
96
+ const { data: tagData } = await github.rest.git.getRef({
97
+ owner: context.repo.owner,
98
+ repo: context.repo.repo,
99
+ ref: `tags/${lastTag}`
100
+ });
101
+ baseSha = tagData.object.sha;
102
+ } catch (e) {
103
+ try {
104
+ const { data: commitData } = await github.rest.repos.getCommit({
105
+ owner: context.repo.owner,
106
+ repo: context.repo.repo,
107
+ ref: lastTag
108
+ });
109
+ baseSha = commitData.sha;
110
+ } catch (e2) {
111
+ baseSha = null;
112
+ }
113
+ }
114
+
115
+ const response = await github.rest.repos.compareCommits({
116
+ owner: context.repo.owner,
117
+ repo: context.repo.repo,
118
+ base: baseSha || 'main',
119
+ head: context.sha
120
+ });
121
+ compareData = response.data;
122
+ } else {
123
+ console.log('⚠️ No previous tags found, analyzing recent commits...');
124
+ // Get recent commits (last 50) to determine bump type
125
+ const response = await github.rest.repos.listCommits({
126
+ owner: context.repo.owner,
127
+ repo: context.repo.repo,
128
+ per_page: 50
129
+ });
130
+ compareData = { commits: response.data };
131
+ }
132
+
133
+ // Analyze commit messages for version bump type
134
+ let bumpType = 'patch'; // Default to patch
135
+
136
+ for (const commit of compareData.commits) {
137
+ const message = commit.commit.message;
138
+ const firstLine = message.split('\n')[0];
139
+
140
+ if (/^BREAKING/i.test(firstLine)) {
141
+ bumpType = 'major';
142
+ break; // Major takes precedence, no need to check further
143
+ } else if (/^(feat|feature)[(:]/i.test(firstLine)) {
144
+ if (bumpType !== 'major') {
145
+ bumpType = 'minor';
146
+ }
147
+ } else if (/^fix[(]/i.test(firstLine)) {
148
+ // Keep as patch if not already minor or major
149
+ if (bumpType === 'patch') {
150
+ bumpType = 'patch';
151
+ }
152
+ }
153
+ }
154
+
155
+ console.log(`Detected bump type: ${bumpType}`);
156
+
157
+ // Calculate new version
158
+ const [major, minor, patch] = currentVersion.split('.').map(Number);
159
+ let newVersion;
160
+
161
+ if (bumpType === 'major') {
162
+ newVersion = `${major + 1}.0.0`;
163
+ } else if (bumpType === 'minor') {
164
+ newVersion = `${major}.${minor + 1}.0`;
165
+ } else {
166
+ newVersion = `${major}.${minor}.${patch + 1}`;
167
+ }
168
+
169
+ version = newVersion;
170
+ console.log(`✅ New version: ${version}`);
171
+ }
172
+
173
+ // Validate semantic version format
174
+ if (!/^\d+\.\d+\.\d+(-[a-zA-Z0-9-]+(\.[0-9]+)?)?$/.test(version)) {
175
+ throw new Error(`Invalid version format: ${version}. Expected format: X.Y.Z or X.Y.Z-prerelease`);
176
+ }
177
+
178
+ core.setOutput('version', version);
179
+ core.setOutput('tag', `v${version}`);
180
+ core.setOutput('npm-version', version);
181
+ console.log(`✅ Final version: ${version}`);
63
182
 
64
- - name: Verify version in package.json
183
+ - name: Update package.json version
65
184
  run: |
66
185
  CURRENT_VERSION=$(node -p "require('./package.json').version")
67
186
  RELEASE_VERSION="${{ steps.version.outputs.version }}"
68
-
187
+
69
188
  if [ "$CURRENT_VERSION" != "$RELEASE_VERSION" ]; then
70
- echo "⚠️ Warning: package.json version ($CURRENT_VERSION) doesn't match release version ($RELEASE_VERSION)"
71
- echo "Updating package.json..."
189
+ echo "Updating package.json from $CURRENT_VERSION to $RELEASE_VERSION..."
72
190
  npm version "$RELEASE_VERSION" --no-git-tag-version --allow-same-version
191
+ else
192
+ echo "✅ package.json already at version $RELEASE_VERSION"
193
+ fi
194
+
195
+ - name: Create and push git tag
196
+ if: github.event_name == 'push' && startsWith(github.ref, 'refs/heads/')
197
+ run: |
198
+ TAG="${{ steps.version.outputs.tag }}"
199
+ VERSION="${{ steps.version.outputs.version }}"
200
+
201
+ # Check if tag already exists
202
+ if git rev-parse "$TAG" >/dev/null 2>&1; then
203
+ echo "⚠️ Tag $TAG already exists, skipping tag creation"
204
+ else
205
+ echo "Creating tag $TAG..."
206
+ git config user.name "github-actions[bot]"
207
+ git config user.email "github-actions[bot]@users.noreply.github.com"
208
+ git tag -a "$TAG" -m "Release $VERSION"
209
+ git push origin "$TAG"
210
+ echo "✅ Tag $TAG created and pushed"
73
211
  fi
74
212
 
75
213
  - name: Generate release notes
76
214
  id: notes
77
- uses: actions/github-script@v7
215
+ uses: actions/github-script@v8
78
216
  with:
79
217
  script: |
80
218
  const { data: releases } = await github.rest.repos.listReleases({
@@ -82,10 +220,10 @@ jobs:
82
220
  repo: context.repo.repo,
83
221
  per_page: 1
84
222
  });
85
-
223
+
86
224
  const lastTag = releases.length > 0 ? releases[0].tag_name : null;
87
225
  const currentTag = 'v${{ steps.version.outputs.version }}';
88
-
226
+
89
227
  // Get commits since last release
90
228
  let baseSha;
91
229
  if (lastTag) {
@@ -114,21 +252,21 @@ jobs:
114
252
  });
115
253
  baseSha = branchData.commit.sha;
116
254
  }
117
-
255
+
118
256
  const { data: commits } = await github.rest.repos.compareCommits({
119
257
  owner: context.repo.owner,
120
258
  repo: context.repo.repo,
121
259
  base: baseSha,
122
260
  head: context.sha
123
261
  });
124
-
262
+
125
263
  // Categorize commits
126
264
  const features = [];
127
265
  const fixes = [];
128
266
  const docs = [];
129
267
  const chore = [];
130
268
  const breaking = [];
131
-
269
+
132
270
  for (const commit of commits.commits) {
133
271
  const message = commit.commit.message;
134
272
  const firstLine = message.split('\n')[0];
@@ -145,29 +283,29 @@ jobs:
145
283
  chore.push(`- ${firstLine}`);
146
284
  }
147
285
  }
148
-
286
+
149
287
  let notes = `## 🎉 Release ${{ steps.version.outputs.version }}\n\n`;
150
-
288
+
151
289
  if (breaking.length > 0) {
152
290
  notes += `### ⚠️ Breaking Changes\n${breaking.join('\n')}\n\n`;
153
291
  }
154
-
292
+
155
293
  if (features.length > 0) {
156
294
  notes += `### ✨ Features\n${features.join('\n')}\n\n`;
157
295
  }
158
-
296
+
159
297
  if (fixes.length > 0) {
160
298
  notes += `### 🐛 Bug Fixes\n${fixes.join('\n')}\n\n`;
161
299
  }
162
-
300
+
163
301
  if (docs.length > 0) {
164
302
  notes += `### 📚 Documentation\n${docs.join('\n')}\n\n`;
165
303
  }
166
-
304
+
167
305
  if (chore.length > 0 && chore.length < 10) {
168
306
  notes += `### 🔧 Other Changes\n${chore.join('\n')}\n\n`;
169
307
  }
170
-
308
+
171
309
  notes += `### 📦 Installation\n\n`;
172
310
  notes += `\`\`\`bash\n`;
173
311
  notes += `# npm\n`;
@@ -177,7 +315,7 @@ jobs:
177
315
  notes += `\`\`\`\n\n`;
178
316
  notes += `---\n\n`;
179
317
  notes += `**Full Changelog**: https://github.com/${{ github.repository }}/compare/${lastTag || 'main'}...${currentTag}`;
180
-
318
+
181
319
  core.setOutput('notes', notes);
182
320
  console.log('Generated release notes');
183
321
 
@@ -188,31 +326,35 @@ jobs:
188
326
  needs: prepare
189
327
  steps:
190
328
  - name: Checkout code
191
- uses: actions/checkout@v4
329
+ uses: actions/checkout@v6
330
+
331
+ - name: Setup Bun
332
+ uses: oven-sh/setup-bun@v1
333
+ with:
334
+ bun-version: latest
192
335
 
193
336
  - name: Setup Node.js
194
- uses: actions/setup-node@v4
337
+ uses: actions/setup-node@v6
195
338
  with:
196
339
  node-version: ${{ env.NODE_VERSION }}
197
- cache: 'yarn'
198
340
 
199
341
  - name: Install dependencies
200
- run: yarn install --frozen-lockfile
342
+ run: bun install --frozen-lockfile
201
343
 
202
344
  - name: Run linter (if configured)
203
345
  continue-on-error: true
204
346
  run: |
205
347
  if [ -f ".eslintrc" ] || [ -f ".eslintrc.js" ] || [ -f ".eslintrc.json" ]; then
206
- yarn lint
348
+ bun run lint
207
349
  else
208
350
  echo "No linter configured, skipping..."
209
351
  fi
210
352
 
211
353
  - name: Run tests
212
- run: yarn test
354
+ run: bun test
213
355
 
214
356
  - name: Build
215
- run: yarn build
357
+ run: bun run build
216
358
 
217
359
  - name: Verify build output
218
360
  run: |
@@ -232,31 +374,41 @@ jobs:
232
374
  url: https://www.npmjs.com/package/httpcat-cli
233
375
  permissions:
234
376
  contents: read
235
- id-token: write # For npm provenance
377
+ id-token: write # Required for OIDC trusted publishing (no token needed!)
236
378
  steps:
237
379
  - name: Checkout code
238
- uses: actions/checkout@v4
380
+ uses: actions/checkout@v6
239
381
 
240
382
  - name: Setup Node.js
241
- uses: actions/setup-node@v4
383
+ uses: actions/setup-node@v6
242
384
  with:
243
385
  node-version: ${{ env.NODE_VERSION }}
244
386
  registry-url: ${{ env.REGISTRY_URL }}
245
387
 
388
+ - name: Update npm to latest
389
+ run: npm install -g npm@latest
390
+ # npm 11.5.1+ required for trusted publishing (OIDC)
391
+
246
392
  - name: Update package.json version
247
393
  run: |
248
394
  npm version "${{ needs.prepare.outputs.version }}" --no-git-tag-version --allow-same-version
249
395
 
396
+ - name: Setup Bun
397
+ uses: oven-sh/setup-bun@v1
398
+ with:
399
+ bun-version: latest
400
+
250
401
  - name: Install dependencies
251
- run: yarn install --frozen-lockfile
402
+ run: bun install --frozen-lockfile
252
403
 
253
404
  - name: Build
254
- run: yarn build
405
+ run: bun run build
255
406
 
256
407
  - name: Publish to npm
257
- run: npm publish --provenance --access public
258
- env:
259
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
408
+ run: npm publish --access public
409
+ # Uses trusted publishing (OIDC) - no token needed!
410
+ # Configure trusted publisher at: https://www.npmjs.com/package/httpcat-cli/settings
411
+ # Provenance is automatically generated when using trusted publishing
260
412
 
261
413
  - name: Verify npm publication
262
414
  run: |
@@ -276,7 +428,7 @@ jobs:
276
428
  needs: [prepare, publish-npm]
277
429
  steps:
278
430
  - name: Checkout code
279
- uses: actions/checkout@v4
431
+ uses: actions/checkout@v6
280
432
  with:
281
433
  token: ${{ secrets.GITHUB_TOKEN }}
282
434
 
@@ -298,7 +450,7 @@ jobs:
298
450
  run: |
299
451
  VERSION="${{ needs.prepare.outputs.version }}"
300
452
  TARBALL_URL="https://registry.npmjs.org/httpcat-cli/-/httpcat-cli-${VERSION}.tgz"
301
-
453
+
302
454
  echo "Downloading tarball to calculate SHA256..."
303
455
  curl -L -o package.tgz "$TARBALL_URL"
304
456
  SHA256=$(shasum -a 256 package.tgz | cut -d' ' -f1)
@@ -310,18 +462,18 @@ jobs:
310
462
  VERSION="${{ needs.prepare.outputs.version }}"
311
463
  SHA256="${{ steps.npm-sha.outputs.sha256 }}"
312
464
  FORMULA_FILE="homebrew-httpcat/Formula/httpcat.rb"
313
-
465
+
314
466
  # Update version
315
467
  sed -i.bak "s|url \".*httpcat-cli-.*\.tgz\"|url \"https://registry.npmjs.org/httpcat-cli/-/httpcat-cli-${VERSION}.tgz\"|" "$FORMULA_FILE"
316
-
468
+
317
469
  # Update SHA256
318
470
  sed -i.bak "s|sha256 \".*\"|sha256 \"${SHA256}\"|" "$FORMULA_FILE"
319
-
471
+
320
472
  # Update test version
321
473
  sed -i.bak "s|assert_match \".*\"|assert_match \"${VERSION}\"|" "$FORMULA_FILE"
322
-
474
+
323
475
  rm -f "${FORMULA_FILE}.bak"
324
-
476
+
325
477
  echo "✅ Updated Homebrew formula:"
326
478
  cat "$FORMULA_FILE"
327
479
 
@@ -342,7 +494,7 @@ jobs:
342
494
  contents: write
343
495
  steps:
344
496
  - name: Create GitHub Release
345
- uses: softprops/action-gh-release@v1
497
+ uses: softprops/action-gh-release@v2
346
498
  with:
347
499
  tag_name: ${{ needs.prepare.outputs.tag }}
348
500
  name: Release ${{ needs.prepare.outputs.version }}