mayar 0.2.0 → 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 CHANGED
@@ -70,75 +70,138 @@ mayar --api-key YOUR_KEY_HERE balance
70
70
 
71
71
  Get your API key from [web.mayar.id](https://web.mayar.id) → Integration → API Key.
72
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
+
73
75
  ## Commands
74
76
 
75
77
  ```
76
78
  Setup
77
- init Run first-time setup (interactive, masked input)
78
- api-key <key> Save API key non-interactively (e.g. for scripts)
79
- config show Show masked saved key and config path
80
- config reset Remove the saved key
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
81
83
 
82
84
  Account
83
- whoami Show merchant identity (decoded from JWT) + verify key
84
- balance GET /hl/v1/balance
85
+ whoami Merchant identity (JWT decode + live verify)
86
+ balance GET /hl/v2/balances
85
87
 
86
88
  Invoices
87
- invoice list [--page N --pageSize N] GET /hl/v1/invoice
88
- invoice get <id> GET /hl/v1/invoice/{id}
89
- invoice close <id> GET /hl/v1/invoice/close/{id}
90
- invoice reopen <id> GET /hl/v1/invoice/open/{id}
91
- invoice create --data <json|@file> POST /hl/v1/invoice/create
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>
92
96
 
93
97
  Products
94
- product list [--page N --pageSize N] GET /hl/v1/product
95
- product search <keyword> GET /hl/v1/product?search=...
96
- product type <type> [--page ...] GET /hl/v1/product/type/{type}
97
- product get <id> GET /hl/v1/product/{id}
98
- product close <id> GET /hl/v1/product/close/{id}
99
- product reopen <id> GET /hl/v1/product/open/{id}
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>
100
107
 
101
108
  Single payment requests
102
- payment list GET /hl/v1/payment
103
- payment get <id> GET /hl/v1/payment/{id}
104
- payment close <id> GET /hl/v1/payment/close/{id}
105
- payment reopen <id> GET /hl/v1/payment/open/{id}
106
- payment create --data <json|@file> POST /hl/v1/payment/create
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>
107
114
 
108
115
  Customers
109
- customer list [--page ...] GET /hl/v1/customer
110
- customer create --data <json|@file> POST /hl/v1/customer/create
111
- customer search <email> GET /hl/v1/customer/detail?email=
112
- customer update <from> <to> POST /hl/v1/customer/update
113
- customer magic-link <email> POST /hl/v1/customer/login/portal
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
114
121
 
115
122
  Transactions
116
- tx list [--page ...] GET /hl/v1/transactions (paid)
117
- tx unpaid [--page ...] GET /hl/v1/transactions/unpaid
118
- tx daily GET /hl/v1/transactions/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]
119
127
 
120
128
  Reviews
121
- review list [--page ...] GET /hl/v1/reviews
122
-
123
- Dynamic QR
124
- qrcode <amount> POST /hl/v1/qrcode/create
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
125
182
 
126
183
  Webhooks
127
- webhook register <url> GET /hl/v1/webhook/register
128
- webhook test <url> POST /hl/v1/webhook/test
129
- webhook history [--page ...] GET /hl/v1/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>
130
189
 
131
190
  Global flags
132
191
  --json Output raw JSON instead of pretty tables
133
192
  --api-key <key> Use this API key for the run (also accepts --api-key=KEY)
134
- --page N Pagination page (default 1)
135
- --pageSize N Pagination page size (default 10)
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
136
197
  -h, --help Show help
137
198
  -v, --version Show version
138
199
 
139
200
  Environment
140
- MAYAR_API_KEY API key — used when --api-key flag is absent and no config is saved
141
- MAYAR_API_URL Override API base URL (default: https://api.mayar.id)
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
142
205
  ```
143
206
 
144
207
  ## Examples
@@ -150,9 +213,10 @@ mayar whoami
150
213
  # Account balance
151
214
  mayar balance
152
215
 
153
- # Paginated lists
154
- mayar invoice list --page 1 --pageSize 20
155
- mayar product type ebook --pageSize 50
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
156
220
 
157
221
  # Search
158
222
  mayar product search "kelas python"
@@ -183,7 +247,13 @@ mayar qrcode 10000
183
247
  # Webhooks
184
248
  mayar webhook register https://example.com/hooks/mayar
185
249
  mayar webhook test https://example.com/hooks/mayar
186
- mayar webhook history --page 1 --pageSize 20
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
187
257
 
188
258
  # Pipe raw JSON to jq
189
259
  mayar invoice list --json | jq '.data[] | {id, status}'
@@ -205,4 +275,5 @@ To rotate keys: `mayar config reset && mayar init`.
205
275
  - All requests use `Authorization: Bearer <key>`. Errors print `API <status> — <message>` and exit non-zero.
206
276
  - `--data @file.json` reads from disk; `--data '{...}'` reads inline JSON.
207
277
  - `MAYAR_API_URL` overrides the base URL — useful for staging or custom proxy environments.
208
- - `mayar whoami` decodes the JWT locally and verifies the key live against `/hl/v1/balance`.
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,6 +1,6 @@
1
1
  {
2
2
  "name": "mayar",
3
- "version": "0.2.0",
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"
package/src/cli.js CHANGED
@@ -3,7 +3,7 @@ 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 (production)')}
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]
@@ -20,55 +20,120 @@ ${ui.bold('Account:')}
20
20
  balance Get account balance
21
21
 
22
22
  ${ui.bold('Invoices:')}
23
- invoice list [--page N --pageSize N]
23
+ invoice list [--limit N --after CURSOR]
24
24
  invoice get <id>
25
25
  invoice close <id>
26
26
  invoice reopen <id>
27
- invoice create --data <json|@file.json>
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>
28
31
 
29
32
  ${ui.bold('Products:')}
30
- product list [--page N --pageSize N]
33
+ product list [--limit N --after CURSOR --search Q --type T]
31
34
  product search <keyword>
32
35
  product type <ebook|course|membership|saas|event|webinar|...>
33
36
  product get <id>
34
37
  product close <id>
35
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
36
47
 
37
48
  ${ui.bold('Single payment requests:')}
38
- payment list
49
+ payment list [--limit N --after CURSOR --status paid|unpaid|closed]
39
50
  payment get <id>
40
- payment close <id>
41
- payment reopen <id>
42
- payment create --data <json|@file.json>
51
+ payment status <id> <open|close|active|closed|unlisted>
52
+ payment edit <id> --data <json|@file>
53
+ payment create --data <json|@file>
43
54
 
44
55
  ${ui.bold('Customers:')}
45
- customer list [--page N --pageSize N]
46
- customer create --data <json|@file.json>
47
- customer search <email> Look up a customer by email
56
+ customer list
57
+ customer create --data <json|@file>
58
+ customer search <email>
48
59
  customer update <fromEmail> <toEmail>
49
- customer magic-link <email> Email a portal login link to the customer
60
+ customer magic-link <email>
50
61
 
51
62
  ${ui.bold('Transactions:')}
52
- tx list [--page N --pageSize N] Paid transactions
53
- tx unpaid [--page N --pageSize N] Unpaid transactions
54
- tx daily Today's totals (volume + count)
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]
55
67
 
56
68
  ${ui.bold('Reviews:')}
57
- review list [--page N --pageSize N]
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>
58
100
 
59
- ${ui.bold('Dynamic QR:')}
60
- qrcode <amount>
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
61
122
 
62
123
  ${ui.bold('Webhooks:')}
63
124
  webhook register <url>
64
125
  webhook test <url>
65
- webhook history [--page N --pageSize N]
126
+ webhook history [--limit N --after CURSOR]
127
+ webhook new-history [--limit N --after CURSOR]
128
+ webhook retry <historyId>
66
129
 
67
130
  ${ui.bold('Global flags:')}
68
131
  --json Output raw JSON instead of formatted tables
69
132
  --api-key <key> Use this API key for the run (overrides env + saved config)
70
- --page N Pagination page (default 1)
71
- --pageSize N Pagination page size (default 10)
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
72
137
  -h, --help Show help
73
138
  -v, --version Show version
74
139
 
@@ -97,6 +162,8 @@ function parseFlags(argv) {
97
162
  else if (a.startsWith('--api-key=')) flags.apiKey = a.slice('--api-key='.length);
98
163
  else if (a === '--page') flags.page = argv[++i];
99
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];
100
167
  else if (a === '--data') flags.data = argv[++i];
101
168
  else if (a === '-h' || a === '--help') flags.help = true;
102
169
  else if (a === '-v' || a === '--version') flags.version = true;
@@ -116,7 +183,6 @@ async function ensureKey(flags) {
116
183
  if (process.env.MAYAR_API_KEY) return process.env.MAYAR_API_KEY;
117
184
  const cfg = config.load();
118
185
  if (cfg && cfg.apiKey) return cfg.apiKey;
119
- // First-run flow
120
186
  ui.printBanner();
121
187
  process.stdout.write(`${ui.bold('Welcome to Mayar CLI.')}\n`);
122
188
  process.stdout.write(`No API key found. Get yours from ${ui.cyan('https://web.mayar.id')} → Integration → API Key.\n\n`);
@@ -141,17 +207,10 @@ async function run(argv) {
141
207
 
142
208
  try {
143
209
  if (cmd === 'help') { process.stdout.write(HELP()); return; }
144
- if (cmd === 'init') {
145
- const init = require('./commands/init');
146
- return await init.run({ flags });
147
- }
148
- if (cmd === 'login') {
149
- const login = require('./commands/login');
150
- return await login.run({ flags });
151
- }
210
+ if (cmd === 'init') { return await require('./commands/init').run({ flags }); }
211
+ if (cmd === 'login') { return await require('./commands/login').run({ flags }); }
152
212
  if (cmd === 'api-key' || cmd === 'apikey') {
153
- const apikey = require('./commands/apikey');
154
- 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) });
155
214
  }
156
215
  if (cmd === 'config') {
157
216
  if (sub === 'show') {
@@ -177,17 +236,40 @@ async function run(argv) {
177
236
  whoami: './commands/whoami',
178
237
  balance: './commands/balance',
179
238
  invoice: './commands/invoice',
239
+ invoices: './commands/invoice',
180
240
  product: './commands/product',
241
+ products: './commands/product',
181
242
  payment: './commands/payment',
243
+ payments: './commands/payment',
182
244
  customer: './commands/customer',
245
+ customers: './commands/customer',
183
246
  tx: './commands/transaction',
184
247
  transaction: './commands/transaction',
185
248
  transactions: './commands/transaction',
186
249
  qr: './commands/qrcode',
187
250
  qrcode: './commands/qrcode',
188
251
  webhook: './commands/webhook',
252
+ webhooks: './commands/webhook',
189
253
  review: './commands/review',
190
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',
191
273
  };
192
274
  const handler = handlers[cmd];
193
275
  if (!handler) {
@@ -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/v1/balance', { apiKey });
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 };
@@ -8,9 +8,7 @@ async function run({ apiKey, flags, positional }) {
8
8
  const [sub, ...rest] = positional;
9
9
  switch (sub) {
10
10
  case 'list': {
11
- const res = await api.request('GET', '/hl/v1/customer', {
12
- apiKey, query: { page: flags.page, pageSize: flags.pageSize },
13
- });
11
+ const res = await api.request('GET', '/hl/v2/customers', { apiKey });
14
12
  checkResp(res);
15
13
  if (flags.json) return ui.jsonOut(res.body);
16
14
  const data = (res.body && res.body.data) || [];
@@ -23,19 +21,19 @@ async function run({ apiKey, flags, positional }) {
23
21
  case 'create': {
24
22
  const body = readData(flags.data);
25
23
  if (!body) throw new Error('mayar customer create requires --data \'{"name":"...","email":"...","mobile":"..."}\'');
26
- const res = await api.request('POST', '/hl/v1/customer/create', { apiKey, body });
24
+ const res = await api.request('POST', '/hl/v2/customers/create', { apiKey, body });
27
25
  checkResp(res); ui.jsonOut(res.body); return;
28
26
  }
29
27
  case 'search': {
30
28
  if (!rest[0]) throw new Error('Usage: mayar customer search <email>');
31
- const res = await api.request('GET', '/hl/v1/customer/detail', {
29
+ const res = await api.request('GET', '/hl/v2/customers/detail', {
32
30
  apiKey, query: { email: rest[0] },
33
31
  });
34
32
  checkResp(res); ui.jsonOut(res.body); return;
35
33
  }
36
34
  case 'update': {
37
35
  if (rest.length < 2) throw new Error('Usage: mayar customer update <fromEmail> <toEmail>');
38
- const res = await api.request('POST', '/hl/v1/customer/update', {
36
+ const res = await api.request('POST', '/hl/v2/customers/update', {
39
37
  apiKey, body: { fromEmail: rest[0], toEmail: rest[1] },
40
38
  });
41
39
  checkResp(res); ui.jsonOut(res.body); return;
@@ -43,7 +41,7 @@ async function run({ apiKey, flags, positional }) {
43
41
  case 'magic-link':
44
42
  case 'magiclink': {
45
43
  if (!rest[0]) throw new Error('Usage: mayar customer magic-link <email>');
46
- const res = await api.request('POST', '/hl/v1/customer/login/portal', {
44
+ const res = await api.request('POST', '/hl/v2/customers/portal-login', {
47
45
  apiKey, body: { email: rest[0] },
48
46
  });
49
47
  checkResp(res); ui.jsonOut(res.body); return;