dodopayments-cli 3.5.0 → 3.6.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.
- package/.github/workflows/pr.yml +33 -0
- package/.github/workflows/publish.yml +10 -2
- package/README.md +3 -1
- package/dist/index.js +741 -616
- package/package.json +4 -2
- package/scripts/build.ts +0 -136
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dodopayments-cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.1",
|
|
4
4
|
"description": "Official Dodo Payments CLI — manage payments, customers, products, subscriptions, and webhooks from your terminal. Includes an interactive TUI, an AI assistant powered by MCP, and offline webhook testing.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dodopayments",
|
|
@@ -43,12 +43,14 @@
|
|
|
43
43
|
"scripts": {
|
|
44
44
|
"setup-dev": "npm i && bun ./fetch-cross-deps",
|
|
45
45
|
"build": "bun run scripts/build.ts",
|
|
46
|
+
"test": "bun run build && bun test",
|
|
46
47
|
"build-native": "bun run build-binaries.ts",
|
|
47
48
|
"dev": "bun src/index.ts"
|
|
48
49
|
},
|
|
49
50
|
"dependencies": {
|
|
50
51
|
"@ai-sdk/mcp": "^1.0.36",
|
|
51
52
|
"@ai-sdk/openai": "^3.0.54",
|
|
53
|
+
"@clack/prompts": "^1.7.0",
|
|
52
54
|
"@dodopayments/express": "^0.2.8",
|
|
53
55
|
"@dodopayments/nextjs": "^0.3.6",
|
|
54
56
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
@@ -57,7 +59,7 @@
|
|
|
57
59
|
"@opentui/solid": "0.2.3",
|
|
58
60
|
"ai": "^6.0.168",
|
|
59
61
|
"chalk": "^5.6.2",
|
|
60
|
-
"dodopayments": "^2.
|
|
62
|
+
"dodopayments": "^2.45.0",
|
|
61
63
|
"dodopayments-mcp": "^2.32.0",
|
|
62
64
|
"mcp-remote": "^0.1.38",
|
|
63
65
|
"node-machine-id": "^1.1.12",
|
package/scripts/build.ts
DELETED
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Production bundler. Bun's `bun build` does NOT honor bunfig.toml's
|
|
3
|
-
* preload (per OpenTUI #122), so we drive Bun.build directly with the
|
|
4
|
-
* @opentui/solid bun-plugin to apply the Solid babel transform on every
|
|
5
|
-
* `.tsx/.jsx` file.
|
|
6
|
-
*
|
|
7
|
-
* The runtime path uses bunfig.toml's preload instead -- both code paths
|
|
8
|
-
* end up registering the same plugin, just at different lifecycles.
|
|
9
|
-
*
|
|
10
|
-
* After bundling, we inject a tiny Node-compatible prelude that re-execs
|
|
11
|
-
* the bundle under Bun if it's launched by Node. This is required because
|
|
12
|
-
* `target: 'bun'` emits Bun-only runtime APIs (e.g. `import.meta.require`)
|
|
13
|
-
* and our native deps (@opentui/core) load through Bun's loader.
|
|
14
|
-
*
|
|
15
|
-
* Without this prelude, `bun install -g dodopayments-cli` works on disk
|
|
16
|
-
* but the symlinked `dodo` binary is invoked via `#!/usr/bin/env node`,
|
|
17
|
-
* which crashes immediately with "Qg is not a function" because Node has
|
|
18
|
-
* no `import.meta.require`. The prelude makes Node hand control off to
|
|
19
|
-
* Bun transparently, and gives a clear error if Bun isn't installed.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
import { readFileSync, writeFileSync } from 'node:fs';
|
|
23
|
-
import solidPlugin from '@opentui/solid/bun-plugin';
|
|
24
|
-
|
|
25
|
-
const result = await Bun.build({
|
|
26
|
-
entrypoints: ['./src/index.ts'],
|
|
27
|
-
outdir: './dist',
|
|
28
|
-
target: 'bun',
|
|
29
|
-
minify: true,
|
|
30
|
-
plugins: [solidPlugin],
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
if (!result.success) {
|
|
34
|
-
console.error('Build failed.');
|
|
35
|
-
for (const message of result.logs) console.error(message);
|
|
36
|
-
process.exit(1);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const main = result.outputs.find((o) => o.kind === 'entry-point');
|
|
40
|
-
if (!main) {
|
|
41
|
-
console.error('Build succeeded but no entry-point output was produced.');
|
|
42
|
-
process.exit(1);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const outPath = main.path;
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Node-safe prelude. Must contain ZERO Bun-only APIs.
|
|
49
|
-
*
|
|
50
|
-
* Why this works:
|
|
51
|
-
* - Top-level await in ESM BLOCKS subsequent top-level statements
|
|
52
|
-
* until it resolves. So under Node, the `await import(...)` inside
|
|
53
|
-
* the `if` block runs to completion (and calls process.exit) before
|
|
54
|
-
* any of the bundle's Bun-only top-level code is reached.
|
|
55
|
-
* - Under Bun, the `if` is skipped and the bundle runs normally.
|
|
56
|
-
*
|
|
57
|
-
* Why not wrap the rest of the bundle in `else { ... }`:
|
|
58
|
-
* - The bundle contains top-level `import ...` declarations, which
|
|
59
|
-
* are syntactically forbidden inside a block. So we cannot wrap.
|
|
60
|
-
* Instead we rely on `process.exit()` inside the `if` to keep Node
|
|
61
|
-
* from ever continuing past it.
|
|
62
|
-
*
|
|
63
|
-
* Bun detection:
|
|
64
|
-
* - `typeof Bun !== 'undefined'` is the documented way to detect Bun.
|
|
65
|
-
* Node has no such global. Deno also lacks it; Deno would also fail
|
|
66
|
-
* on other Bun-only bits below, so the explicit error message is
|
|
67
|
-
* the correct outcome for any non-Bun runtime.
|
|
68
|
-
*/
|
|
69
|
-
const prelude = `if (typeof Bun === 'undefined') {
|
|
70
|
-
const { spawnSync } = await import('node:child_process');
|
|
71
|
-
const { existsSync } = await import('node:fs');
|
|
72
|
-
const { fileURLToPath } = await import('node:url');
|
|
73
|
-
const path = await import('node:path');
|
|
74
|
-
const os = await import('node:os');
|
|
75
|
-
|
|
76
|
-
const scriptPath = fileURLToPath(import.meta.url);
|
|
77
|
-
const isWindows = process.platform === 'win32';
|
|
78
|
-
|
|
79
|
-
const which = spawnSync(isWindows ? 'where' : 'which', ['bun'], { encoding: 'utf8' });
|
|
80
|
-
let bun = null;
|
|
81
|
-
if (which.status === 0 && which.stdout) {
|
|
82
|
-
const first = which.stdout.split(/\\r?\\n/).find(Boolean);
|
|
83
|
-
if (first && existsSync(first)) bun = first;
|
|
84
|
-
}
|
|
85
|
-
if (!bun) {
|
|
86
|
-
const candidates = [
|
|
87
|
-
path.join(os.homedir(), '.bun', 'bin', isWindows ? 'bun.exe' : 'bun'),
|
|
88
|
-
'/usr/local/bin/bun',
|
|
89
|
-
'/opt/homebrew/bin/bun',
|
|
90
|
-
];
|
|
91
|
-
for (const c of candidates) {
|
|
92
|
-
if (existsSync(c)) { bun = c; break; }
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (!bun) {
|
|
97
|
-
process.stderr.write(
|
|
98
|
-
'dodopayments-cli requires the Bun runtime when installed via npm/bun.\\n' +
|
|
99
|
-
'\\n' +
|
|
100
|
-
'Install Bun: https://bun.com/docs/installation\\n' +
|
|
101
|
-
'Or download a standalone binary (no runtime required):\\n' +
|
|
102
|
-
' https://github.com/dodopayments/dodopayments-cli/releases\\n'
|
|
103
|
-
);
|
|
104
|
-
process.exit(1);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const child = spawnSync(bun, [scriptPath, ...process.argv.slice(2)], {
|
|
108
|
-
stdio: 'inherit',
|
|
109
|
-
env: process.env,
|
|
110
|
-
});
|
|
111
|
-
if (child.error) {
|
|
112
|
-
process.stderr.write('Failed to launch bun: ' + child.error.message + '\\n');
|
|
113
|
-
process.exit(1);
|
|
114
|
-
}
|
|
115
|
-
if (typeof child.signal === 'string' && child.signal) {
|
|
116
|
-
process.kill(process.pid, child.signal);
|
|
117
|
-
}
|
|
118
|
-
process.exit(child.status ?? 0);
|
|
119
|
-
}
|
|
120
|
-
`;
|
|
121
|
-
|
|
122
|
-
const original = readFileSync(outPath, 'utf8');
|
|
123
|
-
|
|
124
|
-
// Splice the prelude immediately after the shebang (Bun emits it on line 1
|
|
125
|
-
// when bundling an executable). Everything below the shebang is untouched.
|
|
126
|
-
const newlineIdx = original.indexOf('\n');
|
|
127
|
-
const firstLine = newlineIdx >= 0 ? original.slice(0, newlineIdx) : '';
|
|
128
|
-
const hasShebang = firstLine.startsWith('#!');
|
|
129
|
-
const shebang = hasShebang ? firstLine : '';
|
|
130
|
-
const body = hasShebang ? original.slice(newlineIdx + 1) : original;
|
|
131
|
-
|
|
132
|
-
const patched = (shebang ? `${shebang}\n` : '') + prelude + body;
|
|
133
|
-
writeFileSync(outPath, patched);
|
|
134
|
-
|
|
135
|
-
const sizeKb = (Buffer.byteLength(patched, 'utf8') / 1024).toFixed(0);
|
|
136
|
-
console.log(`\u2713 Built ${outPath} (${sizeKb} KB)`);
|