mayar 0.1.9 → 1.0.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/README.md +133 -47
- package/package.json +10 -2
- package/src/api.js +2 -1
- package/src/cli.js +122 -31
- package/src/commands/balance.js +1 -1
- package/src/commands/bundling.js +36 -0
- package/src/commands/credit.js +72 -0
- package/src/commands/customer.js +5 -7
- package/src/commands/discount.js +52 -0
- package/src/commands/installment.js +44 -0
- package/src/commands/invoice.js +53 -25
- package/src/commands/login.js +74 -0
- package/src/commands/membership.js +92 -0
- package/src/commands/payment-link.js +23 -0
- package/src/commands/payment.js +30 -14
- package/src/commands/product.js +97 -18
- package/src/commands/qrcode.js +35 -5
- package/src/commands/review.js +90 -18
- package/src/commands/saas.js +18 -0
- package/src/commands/software.js +17 -0
- package/src/commands/transaction.js +39 -12
- package/src/commands/webhook.js +46 -13
- package/src/config.js +18 -1
- package/src/util.js +28 -1
package/README.md
CHANGED
|
@@ -4,13 +4,28 @@ Command-line interface for the [Mayar](https://docs.mayar.id) API. Zero runtime
|
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
|
+
**One-liner (no npm required):**
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
curl -fsSL https://raw.githubusercontent.com/mayarid/mayar-cli/main/install.sh | sh
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Downloads the latest tarball from the npm registry, extracts to `~/.local/share/mayar`, and symlinks the binary to `~/.local/bin/mayar`. Requires only `node>=18`, `curl`, and `tar`. Override paths or pin a version:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
MAYAR_VERSION=0.1.9 MAYAR_BIN_DIR=/usr/local/bin \
|
|
17
|
+
curl -fsSL https://raw.githubusercontent.com/mayarid/mayar-cli/main/install.sh | sh
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Via npm:**
|
|
21
|
+
|
|
7
22
|
```bash
|
|
8
23
|
npm install -g mayar
|
|
9
24
|
# or run without installing:
|
|
10
25
|
npx mayar --help
|
|
11
26
|
```
|
|
12
27
|
|
|
13
|
-
|
|
28
|
+
**From source:**
|
|
14
29
|
|
|
15
30
|
```bash
|
|
16
31
|
git clone https://github.com/mayarid/mayar-cli.git
|
|
@@ -55,75 +70,138 @@ mayar --api-key YOUR_KEY_HERE balance
|
|
|
55
70
|
|
|
56
71
|
Get your API key from [web.mayar.id](https://web.mayar.id) → Integration → API Key.
|
|
57
72
|
|
|
73
|
+
> **v1.0.0 — Mayar API v2.** All commands now target `/hl/v2/...`. Pagination switched from `--page`/`--pageSize` to cursor-based `--limit`/`--after` (returned in the previous response's `nextStartingAfter`). The `--pageSize` flag is still accepted as an alias for `--limit`.
|
|
74
|
+
|
|
58
75
|
## Commands
|
|
59
76
|
|
|
60
77
|
```
|
|
61
78
|
Setup
|
|
62
|
-
init
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
config reset
|
|
79
|
+
init First-time setup (interactive, masked input)
|
|
80
|
+
login [--no-browser] Sign in via Google OAuth
|
|
81
|
+
api-key <key> Save API key non-interactively
|
|
82
|
+
config show|reset Inspect or remove the saved config
|
|
66
83
|
|
|
67
84
|
Account
|
|
68
|
-
whoami
|
|
69
|
-
balance GET
|
|
85
|
+
whoami Merchant identity (JWT decode + live verify)
|
|
86
|
+
balance GET /hl/v2/balances
|
|
70
87
|
|
|
71
88
|
Invoices
|
|
72
|
-
invoice list [--
|
|
73
|
-
invoice get <id>
|
|
74
|
-
invoice close <id>
|
|
75
|
-
invoice
|
|
76
|
-
invoice
|
|
89
|
+
invoice list [--limit --after --status --search]
|
|
90
|
+
invoice get <id>
|
|
91
|
+
invoice close <id> | reopen <id> POST /hl/v2/invoices/{id}/{open|close}
|
|
92
|
+
invoice status <id> <action> action ∈ open|close|active|closed|unlisted
|
|
93
|
+
invoice edit <id> --data <json|@file>
|
|
94
|
+
invoice filter --email <email> [--limit --after --status --search]
|
|
95
|
+
invoice create --data <json|@file>
|
|
77
96
|
|
|
78
97
|
Products
|
|
79
|
-
product list [--
|
|
80
|
-
product search <keyword>
|
|
81
|
-
product type <
|
|
82
|
-
product get <id>
|
|
83
|
-
product close <id>
|
|
84
|
-
product
|
|
98
|
+
product list [--limit --after --search --type --stock]
|
|
99
|
+
product search <keyword>
|
|
100
|
+
product type <ebook|course|membership|saas|event|webinar|…>
|
|
101
|
+
product get <id>
|
|
102
|
+
product close | reopen | status <id> <action>
|
|
103
|
+
product transactions <id> [--limit --after --status --customerId]
|
|
104
|
+
product create --type <T> --data <json|@file>
|
|
105
|
+
T ∈ ebook|digital|event|webinar|generic|payment-link
|
|
106
|
+
product edit <id> --type <T> --data <json|@file>
|
|
85
107
|
|
|
86
108
|
Single payment requests
|
|
87
|
-
payment list
|
|
88
|
-
payment get <id>
|
|
89
|
-
payment close <id>
|
|
90
|
-
payment
|
|
91
|
-
payment create --data <json|@file>
|
|
109
|
+
payment list [--limit --after --status]
|
|
110
|
+
payment get <id>
|
|
111
|
+
payment close | reopen | status <id> <action>
|
|
112
|
+
payment edit <id> --data <json|@file>
|
|
113
|
+
payment create --data <json|@file>
|
|
92
114
|
|
|
93
115
|
Customers
|
|
94
|
-
customer list
|
|
95
|
-
customer create --data <json|@file>
|
|
96
|
-
customer search <email>
|
|
97
|
-
customer update <
|
|
98
|
-
customer magic-link <email>
|
|
116
|
+
customer list GET /hl/v2/customers
|
|
117
|
+
customer create --data <json|@file>
|
|
118
|
+
customer search <email> GET /hl/v2/customers/detail?email=
|
|
119
|
+
customer update <fromEmail> <toEmail>
|
|
120
|
+
customer magic-link <email> POST /hl/v2/customers/portal-login
|
|
99
121
|
|
|
100
122
|
Transactions
|
|
101
|
-
tx list [--
|
|
102
|
-
tx unpaid [--
|
|
103
|
-
tx daily
|
|
123
|
+
tx list [--limit --after --status --customerId --type --startAt --endAt]
|
|
124
|
+
tx unpaid [--limit --after --status --customerId --startAt --endAt]
|
|
125
|
+
tx daily
|
|
126
|
+
tx product <productId> [--limit --after --status]
|
|
104
127
|
|
|
105
128
|
Reviews
|
|
106
|
-
review list [--
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
129
|
+
review list [--limit --after --status --paymentLinkId --rating]
|
|
130
|
+
review stats [productId] merchant-wide or per-product
|
|
131
|
+
review create --data <json|@file>
|
|
132
|
+
review update <id> --data <json|@file>
|
|
133
|
+
review bulk-status --data <json> [{id,status: ACTIVE|ARCHIVED|INACTIVE}, …]
|
|
134
|
+
review product <paymentLinkId> [--limit --after --rating]
|
|
135
|
+
review product-customer <paymentLinkId> --customerId <id>
|
|
136
|
+
|
|
137
|
+
Discounts (coupons)
|
|
138
|
+
discount create --data <json|@file>
|
|
139
|
+
discount get <id>
|
|
140
|
+
discount validate <code> <paymentLinkId>
|
|
141
|
+
discount check <code>
|
|
142
|
+
|
|
143
|
+
Bundling
|
|
144
|
+
bundling list [--limit --after]
|
|
145
|
+
bundling get <id>
|
|
146
|
+
|
|
147
|
+
Installments
|
|
148
|
+
installment list [--limit --after --status --customerId]
|
|
149
|
+
installment get <id>
|
|
150
|
+
installment create --data <json|@file>
|
|
151
|
+
|
|
152
|
+
Memberships
|
|
153
|
+
membership members --productId <id> [--limit --after]
|
|
154
|
+
membership tiers --productId <id> [--limit --after]
|
|
155
|
+
membership register --data <json|@file>
|
|
156
|
+
membership get <memberId> --productId <id>
|
|
157
|
+
membership update <memberId> --productId <id> [--data <json|@file>]
|
|
158
|
+
membership cancel <memberId> --productId <id>
|
|
159
|
+
membership create-invoice <memberId> --productId <id>
|
|
160
|
+
|
|
161
|
+
Credit wallets
|
|
162
|
+
credit balance --customerId <id> --productId <id> [--tierId <id>]
|
|
163
|
+
credit add --data <json|@file> {customerId, productId, amount}
|
|
164
|
+
credit spend --data <json|@file> {customerId, productId, amount}
|
|
165
|
+
credit history <customerId> --productId <id> [--page N --limit N]
|
|
166
|
+
credit register-usage --data <json|@file>
|
|
167
|
+
credit register-membership --data <json|@file>
|
|
168
|
+
credit checkout --data <json|@file>
|
|
169
|
+
|
|
170
|
+
SaaS licensing
|
|
171
|
+
saas activate <licenseCode> <productId> POST /saas/v2/license/activate
|
|
172
|
+
saas deactivate <licenseCode> <productId> POST /saas/v2/license/deactivate
|
|
173
|
+
saas verify <licenseCode> <productId> POST /saas/v2/license/verify
|
|
174
|
+
|
|
175
|
+
Software licensing
|
|
176
|
+
software verify <licenseCode> <productId> POST /software/v2/license/verify
|
|
177
|
+
|
|
178
|
+
QR & payment channels
|
|
179
|
+
qrcode <amount> POST /hl/v2/qr-codes/create
|
|
180
|
+
qrcode static GET /hl/v2/qr-codes/static
|
|
181
|
+
qrcode channels GET /hl/v2/payment-channels
|
|
110
182
|
|
|
111
183
|
Webhooks
|
|
112
|
-
webhook register <url>
|
|
113
|
-
webhook test <url>
|
|
114
|
-
webhook history
|
|
184
|
+
webhook register <url> POST /hl/v2/webhooks/update
|
|
185
|
+
webhook test <url>
|
|
186
|
+
webhook history [--limit --after --status --type --startAt --endAt]
|
|
187
|
+
webhook new-history [--limit --after]
|
|
188
|
+
webhook retry <historyId>
|
|
115
189
|
|
|
116
190
|
Global flags
|
|
117
191
|
--json Output raw JSON instead of pretty tables
|
|
118
192
|
--api-key <key> Use this API key for the run (also accepts --api-key=KEY)
|
|
119
|
-
--
|
|
120
|
-
--
|
|
193
|
+
--limit N Page size (default 10, max 50)
|
|
194
|
+
--after CURSOR Pagination cursor (from previous nextStartingAfter)
|
|
195
|
+
--pageSize N Alias for --limit
|
|
196
|
+
--data <json|@file> Inline JSON, or @path to a JSON file
|
|
121
197
|
-h, --help Show help
|
|
122
198
|
-v, --version Show version
|
|
123
199
|
|
|
124
200
|
Environment
|
|
125
|
-
MAYAR_API_KEY
|
|
126
|
-
MAYAR_API_URL Override API base URL
|
|
201
|
+
MAYAR_API_KEY Used when --api-key is absent and no config is saved
|
|
202
|
+
MAYAR_API_URL Override API base URL
|
|
203
|
+
MAYAR_AUTH_URL Override auth server base URL (used by 'login')
|
|
204
|
+
NODE_ENV=development Target the sandbox (*.mayar.club) instead of production
|
|
127
205
|
```
|
|
128
206
|
|
|
129
207
|
## Examples
|
|
@@ -135,9 +213,10 @@ mayar whoami
|
|
|
135
213
|
# Account balance
|
|
136
214
|
mayar balance
|
|
137
215
|
|
|
138
|
-
# Paginated lists
|
|
139
|
-
mayar invoice list --
|
|
140
|
-
mayar
|
|
216
|
+
# Paginated lists (v2 cursor pagination)
|
|
217
|
+
mayar invoice list --limit 20
|
|
218
|
+
mayar invoice list --limit 20 --after 1730000000000 # next page
|
|
219
|
+
mayar product type ebook --limit 50
|
|
141
220
|
|
|
142
221
|
# Search
|
|
143
222
|
mayar product search "kelas python"
|
|
@@ -168,7 +247,13 @@ mayar qrcode 10000
|
|
|
168
247
|
# Webhooks
|
|
169
248
|
mayar webhook register https://example.com/hooks/mayar
|
|
170
249
|
mayar webhook test https://example.com/hooks/mayar
|
|
171
|
-
mayar webhook history --
|
|
250
|
+
mayar webhook history --limit 20
|
|
251
|
+
|
|
252
|
+
# Membership members
|
|
253
|
+
mayar membership members --productId prd-42 --limit 20
|
|
254
|
+
|
|
255
|
+
# SaaS license verify
|
|
256
|
+
mayar saas verify LIC-123 prd-42
|
|
172
257
|
|
|
173
258
|
# Pipe raw JSON to jq
|
|
174
259
|
mayar invoice list --json | jq '.data[] | {id, status}'
|
|
@@ -190,4 +275,5 @@ To rotate keys: `mayar config reset && mayar init`.
|
|
|
190
275
|
- All requests use `Authorization: Bearer <key>`. Errors print `API <status> — <message>` and exit non-zero.
|
|
191
276
|
- `--data @file.json` reads from disk; `--data '{...}'` reads inline JSON.
|
|
192
277
|
- `MAYAR_API_URL` overrides the base URL — useful for staging or custom proxy environments.
|
|
193
|
-
- `mayar whoami` decodes the JWT locally and verifies the key live against `/hl/
|
|
278
|
+
- `mayar whoami` decodes the JWT locally and verifies the key live against `/hl/v2/balances`.
|
|
279
|
+
- **v1.0.0 migration**: all API paths moved from `/hl/v1/*` to `/hl/v2/*`. `--page` is no longer used (v2 has no page numbers); the cursor is returned as `nextStartingAfter` in each response and passed as `--after` for the next page.
|
package/package.json
CHANGED
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mayar",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Zero-dependency Node.js CLI for the Mayar API (production endpoint).",
|
|
5
5
|
"bin": {
|
|
6
6
|
"mayar": "bin/mayar.js"
|
|
7
7
|
},
|
|
8
8
|
"main": "src/cli.js",
|
|
9
9
|
"scripts": {
|
|
10
|
-
"start": "node bin/mayar.js"
|
|
10
|
+
"start": "node bin/mayar.js",
|
|
11
|
+
"test": "node --test",
|
|
12
|
+
"test:coverage": "node --test --experimental-test-coverage"
|
|
11
13
|
},
|
|
12
14
|
"engines": {
|
|
13
15
|
"node": ">=18"
|
|
14
16
|
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@mayaross/auth": "^1.0.0"
|
|
19
|
+
},
|
|
20
|
+
"bundleDependencies": [
|
|
21
|
+
"@mayaross/auth"
|
|
22
|
+
],
|
|
15
23
|
"keywords": [
|
|
16
24
|
"mayar",
|
|
17
25
|
"mayar-api",
|
package/src/api.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
const https = require('https');
|
|
2
2
|
const { URL } = require('url');
|
|
3
|
+
const config = require('./config');
|
|
3
4
|
|
|
4
|
-
const BASE_URL =
|
|
5
|
+
const BASE_URL = config.apiBaseUrl();
|
|
5
6
|
const VERSION = require('../package.json').version;
|
|
6
7
|
|
|
7
8
|
function request(method, pathname, { apiKey, body, query } = {}) {
|
package/src/cli.js
CHANGED
|
@@ -3,13 +3,14 @@ const config = require('./config');
|
|
|
3
3
|
|
|
4
4
|
const VERSION = require('../package.json').version;
|
|
5
5
|
|
|
6
|
-
const HELP = () => `${ui.bold('mayar')} ${ui.dim('— Mayar API CLI (
|
|
6
|
+
const HELP = () => `${ui.bold('mayar')} ${ui.dim('— Mayar API CLI (v2)')}
|
|
7
7
|
|
|
8
8
|
${ui.bold('Usage:')}
|
|
9
9
|
mayar <command> [args] [flags]
|
|
10
10
|
|
|
11
11
|
${ui.bold('Setup:')}
|
|
12
12
|
init Run first-time setup (or re-configure API key)
|
|
13
|
+
login [--no-browser] Sign in via browser (Google OAuth) and save auth token
|
|
13
14
|
api-key <key> Save API key non-interactively
|
|
14
15
|
config show Show config path and masked API key
|
|
15
16
|
config reset Remove the saved API key
|
|
@@ -19,64 +20,132 @@ ${ui.bold('Account:')}
|
|
|
19
20
|
balance Get account balance
|
|
20
21
|
|
|
21
22
|
${ui.bold('Invoices:')}
|
|
22
|
-
invoice list [--
|
|
23
|
+
invoice list [--limit N --after CURSOR]
|
|
23
24
|
invoice get <id>
|
|
24
25
|
invoice close <id>
|
|
25
26
|
invoice reopen <id>
|
|
26
|
-
invoice
|
|
27
|
+
invoice status <id> <open|close|active|closed|unlisted>
|
|
28
|
+
invoice edit <id> --data <json|@file>
|
|
29
|
+
invoice filter --email <email> [--limit N --after CURSOR]
|
|
30
|
+
invoice create --data <json|@file>
|
|
27
31
|
|
|
28
32
|
${ui.bold('Products:')}
|
|
29
|
-
product list [--
|
|
33
|
+
product list [--limit N --after CURSOR --search Q --type T]
|
|
30
34
|
product search <keyword>
|
|
31
35
|
product type <ebook|course|membership|saas|event|webinar|...>
|
|
32
36
|
product get <id>
|
|
33
37
|
product close <id>
|
|
34
38
|
product reopen <id>
|
|
39
|
+
product status <id> <open|close|active|closed|unlisted>
|
|
40
|
+
product transactions <id> [--limit N --after CURSOR]
|
|
41
|
+
product create --type <T> --data <json|@file>
|
|
42
|
+
product edit <id> --data <json|@file>
|
|
43
|
+
product sort <generic_link|event|webinar|digital_product> [--limit --after]
|
|
44
|
+
|
|
45
|
+
${ui.bold('Payment links (alt route):')}
|
|
46
|
+
payment-link edit <id> --data <json|@file> Alias for /hl/v2/payment-links/{id}/update
|
|
35
47
|
|
|
36
48
|
${ui.bold('Single payment requests:')}
|
|
37
|
-
payment list
|
|
49
|
+
payment list [--limit N --after CURSOR --status paid|unpaid|closed]
|
|
38
50
|
payment get <id>
|
|
39
|
-
payment
|
|
40
|
-
payment
|
|
41
|
-
payment create --data <json|@file
|
|
51
|
+
payment status <id> <open|close|active|closed|unlisted>
|
|
52
|
+
payment edit <id> --data <json|@file>
|
|
53
|
+
payment create --data <json|@file>
|
|
42
54
|
|
|
43
55
|
${ui.bold('Customers:')}
|
|
44
|
-
customer list
|
|
45
|
-
customer create --data <json|@file
|
|
46
|
-
customer search <email>
|
|
56
|
+
customer list
|
|
57
|
+
customer create --data <json|@file>
|
|
58
|
+
customer search <email>
|
|
47
59
|
customer update <fromEmail> <toEmail>
|
|
48
|
-
customer magic-link <email>
|
|
60
|
+
customer magic-link <email>
|
|
49
61
|
|
|
50
62
|
${ui.bold('Transactions:')}
|
|
51
|
-
tx list [--
|
|
52
|
-
tx unpaid [--
|
|
53
|
-
tx daily
|
|
63
|
+
tx list [--limit N --after CURSOR --status --customerId --startAt --endAt]
|
|
64
|
+
tx unpaid [--limit N --after CURSOR]
|
|
65
|
+
tx daily
|
|
66
|
+
tx product <productId> [--limit N --after CURSOR]
|
|
54
67
|
|
|
55
68
|
${ui.bold('Reviews:')}
|
|
56
|
-
review list [--
|
|
69
|
+
review list [--limit N --after CURSOR --status --paymentLinkId --rating]
|
|
70
|
+
review stats [productId]
|
|
71
|
+
review create --data <json|@file>
|
|
72
|
+
review update <id> --data <json|@file>
|
|
73
|
+
review bulk-status --data <json|@file> (array of {id,status})
|
|
74
|
+
review product <paymentLinkId> [--limit N --after CURSOR]
|
|
75
|
+
review product-customer <paymentLinkId> --customerId <id>
|
|
76
|
+
|
|
77
|
+
${ui.bold('Discounts (coupons):')}
|
|
78
|
+
discount create --data <json|@file>
|
|
79
|
+
discount get <id>
|
|
80
|
+
discount validate <code> <paymentLinkId>
|
|
81
|
+
discount check <code>
|
|
82
|
+
|
|
83
|
+
${ui.bold('Bundling:')}
|
|
84
|
+
bundling list [--limit N --after CURSOR]
|
|
85
|
+
bundling get <id>
|
|
86
|
+
|
|
87
|
+
${ui.bold('Installments:')}
|
|
88
|
+
installment list [--limit N --after CURSOR]
|
|
89
|
+
installment get <id>
|
|
90
|
+
installment create --data <json|@file>
|
|
91
|
+
|
|
92
|
+
${ui.bold('Memberships:')}
|
|
93
|
+
membership members --productId <id> [--limit N --after CURSOR]
|
|
94
|
+
membership tiers --productId <id> [--limit N --after CURSOR]
|
|
95
|
+
membership register --data <json|@file>
|
|
96
|
+
membership get <memberId> --productId <id>
|
|
97
|
+
membership update <memberId> --productId <id> [--data <json|@file>]
|
|
98
|
+
membership cancel <memberId> --productId <id>
|
|
99
|
+
membership create-invoice <memberId> --productId <id>
|
|
57
100
|
|
|
58
|
-
${ui.bold('
|
|
59
|
-
|
|
101
|
+
${ui.bold('Credit wallets:')}
|
|
102
|
+
credit balance --customerId <id> --productId <id> [--tierId <id>]
|
|
103
|
+
credit add --data <json|@file> ({customerId, productId, amount})
|
|
104
|
+
credit spend --data <json|@file> ({customerId, productId, amount})
|
|
105
|
+
credit history <customerId> --productId <id> [--page N --limit N]
|
|
106
|
+
credit register-usage --data <json|@file>
|
|
107
|
+
credit register-membership --data <json|@file>
|
|
108
|
+
credit checkout --data <json|@file>
|
|
109
|
+
|
|
110
|
+
${ui.bold('SaaS licensing:')}
|
|
111
|
+
saas activate <licenseCode> <productId>
|
|
112
|
+
saas deactivate <licenseCode> <productId>
|
|
113
|
+
saas verify <licenseCode> <productId>
|
|
114
|
+
|
|
115
|
+
${ui.bold('Software licensing:')}
|
|
116
|
+
software verify <licenseCode> <productId>
|
|
117
|
+
|
|
118
|
+
${ui.bold('QR & payment channels:')}
|
|
119
|
+
qrcode <amount> Dynamic QR for the given amount
|
|
120
|
+
qrcode static Merchant's static QRIS image
|
|
121
|
+
qrcode channels List enabled payment channels
|
|
60
122
|
|
|
61
123
|
${ui.bold('Webhooks:')}
|
|
62
124
|
webhook register <url>
|
|
63
125
|
webhook test <url>
|
|
64
|
-
webhook history [--
|
|
126
|
+
webhook history [--limit N --after CURSOR]
|
|
127
|
+
webhook new-history [--limit N --after CURSOR]
|
|
128
|
+
webhook retry <historyId>
|
|
65
129
|
|
|
66
130
|
${ui.bold('Global flags:')}
|
|
67
131
|
--json Output raw JSON instead of formatted tables
|
|
68
132
|
--api-key <key> Use this API key for the run (overrides env + saved config)
|
|
69
|
-
--
|
|
70
|
-
--
|
|
133
|
+
--limit N Page size (v2, default 10, max 50)
|
|
134
|
+
--after CURSOR Cursor for next page (from previous response's nextStartingAfter)
|
|
135
|
+
--pageSize N Alias for --limit
|
|
136
|
+
--data <json|@file> Inline JSON or @path to a JSON file
|
|
71
137
|
-h, --help Show help
|
|
72
138
|
-v, --version Show version
|
|
73
139
|
|
|
74
140
|
${ui.bold('Environment:')}
|
|
75
141
|
MAYAR_API_KEY Used when --api-key is not given and no config is saved
|
|
76
|
-
MAYAR_API_URL Override API base URL
|
|
142
|
+
MAYAR_API_URL Override API base URL
|
|
143
|
+
MAYAR_AUTH_URL Override auth server base URL (used by 'login')
|
|
144
|
+
NODE_ENV=development Target the sandbox (api/auth .mayar.club) instead of production
|
|
77
145
|
|
|
78
146
|
${ui.dim('Resolution order: --api-key flag > MAYAR_API_KEY env > saved config.')}
|
|
79
|
-
${ui.dim('
|
|
147
|
+
${ui.dim('API endpoint: MAYAR_API_URL, else NODE_ENV=development → api.mayar.club, else api.mayar.id')}
|
|
148
|
+
${ui.dim('Auth endpoint: MAYAR_AUTH_URL, else NODE_ENV=development → auth.mayar.club, else auth.mayar.id')}
|
|
80
149
|
${ui.dim('Config: ~/.config/mayar/config.json (chmod 600)')}
|
|
81
150
|
`;
|
|
82
151
|
|
|
@@ -88,10 +157,13 @@ function parseFlags(argv) {
|
|
|
88
157
|
if (a === '--') { positional.push(...argv.slice(i + 1)); break; }
|
|
89
158
|
if (a === '--json') flags.json = true;
|
|
90
159
|
else if (a === '--force') flags.force = true;
|
|
160
|
+
else if (a === '--no-browser') flags['no-browser'] = true;
|
|
91
161
|
else if (a === '--api-key') flags.apiKey = argv[++i];
|
|
92
162
|
else if (a.startsWith('--api-key=')) flags.apiKey = a.slice('--api-key='.length);
|
|
93
163
|
else if (a === '--page') flags.page = argv[++i];
|
|
94
164
|
else if (a === '--pageSize' || a === '--page-size') flags.pageSize = argv[++i];
|
|
165
|
+
else if (a === '--limit') flags.limit = argv[++i];
|
|
166
|
+
else if (a === '--after' || a === '--starting-after' || a === '--startingAfter') flags.after = argv[++i];
|
|
95
167
|
else if (a === '--data') flags.data = argv[++i];
|
|
96
168
|
else if (a === '-h' || a === '--help') flags.help = true;
|
|
97
169
|
else if (a === '-v' || a === '--version') flags.version = true;
|
|
@@ -111,7 +183,6 @@ async function ensureKey(flags) {
|
|
|
111
183
|
if (process.env.MAYAR_API_KEY) return process.env.MAYAR_API_KEY;
|
|
112
184
|
const cfg = config.load();
|
|
113
185
|
if (cfg && cfg.apiKey) return cfg.apiKey;
|
|
114
|
-
// First-run flow
|
|
115
186
|
ui.printBanner();
|
|
116
187
|
process.stdout.write(`${ui.bold('Welcome to Mayar CLI.')}\n`);
|
|
117
188
|
process.stdout.write(`No API key found. Get yours from ${ui.cyan('https://web.mayar.id')} → Integration → API Key.\n\n`);
|
|
@@ -136,13 +207,10 @@ async function run(argv) {
|
|
|
136
207
|
|
|
137
208
|
try {
|
|
138
209
|
if (cmd === 'help') { process.stdout.write(HELP()); return; }
|
|
139
|
-
if (cmd === 'init') {
|
|
140
|
-
|
|
141
|
-
return await init.run({ flags });
|
|
142
|
-
}
|
|
210
|
+
if (cmd === 'init') { return await require('./commands/init').run({ flags }); }
|
|
211
|
+
if (cmd === 'login') { return await require('./commands/login').run({ flags }); }
|
|
143
212
|
if (cmd === 'api-key' || cmd === 'apikey') {
|
|
144
|
-
|
|
145
|
-
return await apikey.run({ positional: [sub, ...rest].filter((x) => x !== undefined) });
|
|
213
|
+
return await require('./commands/apikey').run({ positional: [sub, ...rest].filter((x) => x !== undefined) });
|
|
146
214
|
}
|
|
147
215
|
if (cmd === 'config') {
|
|
148
216
|
if (sub === 'show') {
|
|
@@ -168,17 +236,40 @@ async function run(argv) {
|
|
|
168
236
|
whoami: './commands/whoami',
|
|
169
237
|
balance: './commands/balance',
|
|
170
238
|
invoice: './commands/invoice',
|
|
239
|
+
invoices: './commands/invoice',
|
|
171
240
|
product: './commands/product',
|
|
241
|
+
products: './commands/product',
|
|
172
242
|
payment: './commands/payment',
|
|
243
|
+
payments: './commands/payment',
|
|
173
244
|
customer: './commands/customer',
|
|
245
|
+
customers: './commands/customer',
|
|
174
246
|
tx: './commands/transaction',
|
|
175
247
|
transaction: './commands/transaction',
|
|
176
248
|
transactions: './commands/transaction',
|
|
177
249
|
qr: './commands/qrcode',
|
|
178
250
|
qrcode: './commands/qrcode',
|
|
179
251
|
webhook: './commands/webhook',
|
|
252
|
+
webhooks: './commands/webhook',
|
|
180
253
|
review: './commands/review',
|
|
181
254
|
reviews: './commands/review',
|
|
255
|
+
discount: './commands/discount',
|
|
256
|
+
discounts: './commands/discount',
|
|
257
|
+
coupon: './commands/discount',
|
|
258
|
+
coupons: './commands/discount',
|
|
259
|
+
bundling: './commands/bundling',
|
|
260
|
+
bundlings: './commands/bundling',
|
|
261
|
+
installment: './commands/installment',
|
|
262
|
+
installments: './commands/installment',
|
|
263
|
+
membership: './commands/membership',
|
|
264
|
+
memberships: './commands/membership',
|
|
265
|
+
credit: './commands/credit',
|
|
266
|
+
credits: './commands/credit',
|
|
267
|
+
saas: './commands/saas',
|
|
268
|
+
software: './commands/software',
|
|
269
|
+
'payment-link': './commands/payment-link',
|
|
270
|
+
paymentlink: './commands/payment-link',
|
|
271
|
+
'payment-links': './commands/payment-link',
|
|
272
|
+
plink: './commands/payment-link',
|
|
182
273
|
};
|
|
183
274
|
const handler = handlers[cmd];
|
|
184
275
|
if (!handler) {
|
|
@@ -196,4 +287,4 @@ async function run(argv) {
|
|
|
196
287
|
}
|
|
197
288
|
}
|
|
198
289
|
|
|
199
|
-
module.exports = { run };
|
|
290
|
+
module.exports = { run, parseFlags };
|
package/src/commands/balance.js
CHANGED
|
@@ -3,7 +3,7 @@ const ui = require('../ui');
|
|
|
3
3
|
const { checkResp } = require('../util');
|
|
4
4
|
|
|
5
5
|
async function run({ apiKey, flags }) {
|
|
6
|
-
const res = await api.request('GET', '/hl/
|
|
6
|
+
const res = await api.request('GET', '/hl/v2/balances', { apiKey });
|
|
7
7
|
checkResp(res);
|
|
8
8
|
if (flags.json) return ui.jsonOut(res.body);
|
|
9
9
|
const d = (res.body && res.body.data) || {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const api = require('../api');
|
|
2
|
+
const ui = require('../ui');
|
|
3
|
+
const { checkResp, pagination, cursorFooter } = require('../util');
|
|
4
|
+
|
|
5
|
+
const USAGE = 'Usage: mayar bundling <list|get>';
|
|
6
|
+
|
|
7
|
+
async function run({ apiKey, flags, positional }) {
|
|
8
|
+
const [sub, ...rest] = positional;
|
|
9
|
+
switch (sub) {
|
|
10
|
+
case undefined:
|
|
11
|
+
case 'list': {
|
|
12
|
+
const res = await api.request('GET', '/hl/v2/bundling', {
|
|
13
|
+
apiKey, query: pagination(flags),
|
|
14
|
+
});
|
|
15
|
+
checkResp(res);
|
|
16
|
+
if (flags.json) return ui.jsonOut(res.body);
|
|
17
|
+
const data = (res.body && res.body.data) || [];
|
|
18
|
+
const rows = data.map((b) => ({
|
|
19
|
+
id: b.id, name: b.name, amount: b.amount, status: b.status,
|
|
20
|
+
}));
|
|
21
|
+
ui.table(rows, ['id', 'name', 'amount', 'status']);
|
|
22
|
+
cursorFooter(res.body, data.length);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
case 'get':
|
|
26
|
+
case 'detail': {
|
|
27
|
+
if (!rest[0]) throw new Error('Usage: mayar bundling get <id>');
|
|
28
|
+
const res = await api.request('GET', `/hl/v2/bundling/${encodeURIComponent(rest[0])}`, { apiKey });
|
|
29
|
+
checkResp(res); ui.jsonOut(res.body); return;
|
|
30
|
+
}
|
|
31
|
+
default:
|
|
32
|
+
throw new Error(USAGE);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = { run };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const api = require('../api');
|
|
2
|
+
const ui = require('../ui');
|
|
3
|
+
const { checkResp, readData } = require('../util');
|
|
4
|
+
|
|
5
|
+
const USAGE = 'Usage: mayar credit <balance|add|spend|history|register-usage|register-membership|checkout>';
|
|
6
|
+
|
|
7
|
+
async function run({ apiKey, flags, positional }) {
|
|
8
|
+
const [sub, ...rest] = positional;
|
|
9
|
+
switch (sub) {
|
|
10
|
+
case 'balance': {
|
|
11
|
+
if (!flags.customerId) throw new Error('mayar credit balance requires --customerId <id>');
|
|
12
|
+
if (!flags.productId) throw new Error('mayar credit balance requires --productId <id>');
|
|
13
|
+
const res = await api.request('GET', '/hl/v2/credit/customer/balance', {
|
|
14
|
+
apiKey,
|
|
15
|
+
query: {
|
|
16
|
+
customerId: flags.customerId,
|
|
17
|
+
productId: flags.productId,
|
|
18
|
+
membershipTierId: flags.tierId || flags.membershipTierId,
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
checkResp(res); ui.jsonOut(res.body); return;
|
|
22
|
+
}
|
|
23
|
+
case 'add': {
|
|
24
|
+
const body = readData(flags.data);
|
|
25
|
+
if (!body) throw new Error('mayar credit add requires --data <json|@file> ({customerId,productId,amount})');
|
|
26
|
+
const res = await api.request('POST', '/hl/v2/credit/customer/add-credit', { apiKey, body });
|
|
27
|
+
checkResp(res); ui.jsonOut(res.body); return;
|
|
28
|
+
}
|
|
29
|
+
case 'spend': {
|
|
30
|
+
const body = readData(flags.data);
|
|
31
|
+
if (!body) throw new Error('mayar credit spend requires --data <json|@file> ({customerId,productId,amount})');
|
|
32
|
+
const res = await api.request('POST', '/hl/v2/credit/customer/spend', { apiKey, body });
|
|
33
|
+
checkResp(res); ui.jsonOut(res.body); return;
|
|
34
|
+
}
|
|
35
|
+
case 'history': {
|
|
36
|
+
if (!rest[0]) throw new Error('Usage: mayar credit history <customerId> --productId <id>');
|
|
37
|
+
if (!flags.productId) throw new Error('mayar credit history requires --productId <id>');
|
|
38
|
+
const res = await api.request('GET', `/hl/v2/credit/customer/paginate-credit-history/${encodeURIComponent(rest[0])}`, {
|
|
39
|
+
apiKey,
|
|
40
|
+
query: {
|
|
41
|
+
productId: flags.productId,
|
|
42
|
+
page: flags.page,
|
|
43
|
+
limit: flags.limit,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
checkResp(res); ui.jsonOut(res.body); return;
|
|
47
|
+
}
|
|
48
|
+
case 'register-usage': {
|
|
49
|
+
const body = readData(flags.data);
|
|
50
|
+
if (!body) throw new Error('mayar credit register-usage requires --data <json|@file>');
|
|
51
|
+
const res = await api.request('POST', '/hl/v2/credit/credit-usage/customer/regist', { apiKey, body });
|
|
52
|
+
checkResp(res); ui.jsonOut(res.body); return;
|
|
53
|
+
}
|
|
54
|
+
case 'register-membership': {
|
|
55
|
+
const body = readData(flags.data);
|
|
56
|
+
if (!body) throw new Error('mayar credit register-membership requires --data <json|@file>');
|
|
57
|
+
const res = await api.request('POST', '/hl/v2/credit/membership/customer/regist', { apiKey, body });
|
|
58
|
+
checkResp(res); ui.jsonOut(res.body); return;
|
|
59
|
+
}
|
|
60
|
+
case 'checkout':
|
|
61
|
+
case 'generate-checkout': {
|
|
62
|
+
const body = readData(flags.data);
|
|
63
|
+
if (!body) throw new Error('mayar credit checkout requires --data <json|@file>');
|
|
64
|
+
const res = await api.request('POST', '/hl/v2/credit/generate/immutable/checkout', { apiKey, body });
|
|
65
|
+
checkResp(res); ui.jsonOut(res.body); return;
|
|
66
|
+
}
|
|
67
|
+
default:
|
|
68
|
+
throw new Error(USAGE);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
module.exports = { run };
|