@relipay/cli 0.1.0-beta.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.
- package/AGENTS.md +57 -0
- package/README.md +36 -0
- package/dist/commands/apps.d.ts +10 -0
- package/dist/commands/apps.d.ts.map +1 -0
- package/dist/commands/apps.js +77 -0
- package/dist/commands/apps.js.map +1 -0
- package/dist/commands/doctor.d.ts +11 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +80 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/init.d.ts +19 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +65 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/plans.d.ts +14 -0
- package/dist/commands/plans.d.ts.map +1 -0
- package/dist/commands/plans.js +105 -0
- package/dist/commands/plans.js.map +1 -0
- package/dist/commands/version.d.ts +3 -0
- package/dist/commands/version.d.ts.map +1 -0
- package/dist/commands/version.js +12 -0
- package/dist/commands/version.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api.d.ts +15 -0
- package/dist/lib/api.d.ts.map +1 -0
- package/dist/lib/api.js +45 -0
- package/dist/lib/api.js.map +1 -0
- package/dist/lib/output.d.ts +25 -0
- package/dist/lib/output.d.ts.map +1 -0
- package/dist/lib/output.js +44 -0
- package/dist/lib/output.js.map +1 -0
- package/package.json +48 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# AGENTS.md — `@relipay/cli`
|
|
2
|
+
|
|
3
|
+
You are an AI agent reading the ReliPay CLI. This file tells you how to use it correctly on the first try.
|
|
4
|
+
|
|
5
|
+
## Two design rules
|
|
6
|
+
|
|
7
|
+
1. **Every command is non-interactive when given enough flags.** No required prompts, no spinners, no readline. An agent can call `relipay init --tenant-name X --owner-email Y --app-name Z --app-slug s --json` and parse stdout without ever touching a TTY.
|
|
8
|
+
2. **`--json` is the structured-output toggle.** Pass it on any command and stdout is a single JSON document. Without it, the same data renders as friendly text. Errors always go to stderr; exit code is 0 on success, non-zero on failure.
|
|
9
|
+
|
|
10
|
+
## Required env (or flag overrides)
|
|
11
|
+
|
|
12
|
+
| Var | Override flag | Used for |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| `RELIPAY_URL` | `--api-url <url>` | Where the API is. e.g. `http://localhost:3030` or `https://relipay.example.com`. |
|
|
15
|
+
| `SUPER_ADMIN_KEY` | `--admin-key <hex>` | Bootstrap admin credential. Required for every command except `version`. |
|
|
16
|
+
|
|
17
|
+
`relipay doctor` checks both and returns a structured report — read its output before invoking other commands when you're not sure of the env state.
|
|
18
|
+
|
|
19
|
+
## Commands you should know
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
relipay version # CLI version
|
|
23
|
+
relipay doctor # config + connectivity diagnosis
|
|
24
|
+
relipay init --tenant-name … --owner-email … # one-shot bootstrap
|
|
25
|
+
--app-name … --app-slug …
|
|
26
|
+
relipay apps list [--tenant <id>] # Application CRUD
|
|
27
|
+
relipay apps get <id>
|
|
28
|
+
relipay apps create --tenant <id> --name … --slug …
|
|
29
|
+
relipay plans list --app <id> [--include-inactive]
|
|
30
|
+
relipay plans create --app <id> --slug … --name … # money is INTEGER
|
|
31
|
+
--amount <int> [--currency USD] [--interval MONTH|YEAR]
|
|
32
|
+
relipay plans set-active --app <id> --slug … --active true|false
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Add `--json` to any of them. Every error envelope (text or JSON) carries `code`, `message`, and `fix` — read `fix` first.
|
|
36
|
+
|
|
37
|
+
## What you should always do
|
|
38
|
+
|
|
39
|
+
1. **Run `relipay doctor --json` first** if you're not sure the environment is wired up. Parse the `checks` array; act on `fix` for any non-`ok`.
|
|
40
|
+
2. **Use `--json`.** Text output is for humans; for agents it's lossy.
|
|
41
|
+
3. **`--amount` is the smallest currency unit (cents).** `999` = $9.99. Floats are rejected to prevent silent rounding bugs.
|
|
42
|
+
4. **Save the rawKey from `init`.** It's printed once and is unrecoverable. The structured `init` output puts it at `data.apiKey.rawKey`.
|
|
43
|
+
|
|
44
|
+
## What you should never do
|
|
45
|
+
|
|
46
|
+
- Don't `npm install` `commander` or `yargs` to wrap this CLI. Call it directly.
|
|
47
|
+
- Don't pipe stdout through filters that swallow exit code (e.g. `relipay … | head`). Use `--json` and `jq`.
|
|
48
|
+
- Don't pass plaintext money values like `--amount 9.99`. The CLI rejects fractional amounts on purpose.
|
|
49
|
+
- Don't wrap commands in `expect`-style auto-input. There's nothing to type.
|
|
50
|
+
|
|
51
|
+
## Status
|
|
52
|
+
|
|
53
|
+
Phase 2.0 — first useful slice. `init`, `doctor`, `apps`, `plans`, `version` are wired. Future:
|
|
54
|
+
|
|
55
|
+
- `relipay coupons …`
|
|
56
|
+
- `relipay tunnel-webhooks` (the `stripe listen` equivalent — forwards a local server endpoint to the panel for development)
|
|
57
|
+
- `relipay api-keys list/create/revoke`
|
package/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# @relipay/cli
|
|
2
|
+
|
|
3
|
+
`relipay` — command-line interface for ReliPay deployments. Designed for both human developers and AI agents.
|
|
4
|
+
|
|
5
|
+
> **For AI agents**: start at [AGENTS.md](./AGENTS.md).
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add -g @relipay/cli
|
|
11
|
+
# or per-project
|
|
12
|
+
pnpm add -D @relipay/cli
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Use
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
export RELIPAY_URL=http://localhost:3030
|
|
19
|
+
export SUPER_ADMIN_KEY=$(openssl rand -hex 32) # whatever you set on the deployment
|
|
20
|
+
|
|
21
|
+
relipay doctor
|
|
22
|
+
|
|
23
|
+
relipay init \
|
|
24
|
+
--tenant-name "Acme" --owner-email ops@acme.com \
|
|
25
|
+
--app-name "Acme Prod" --app-slug acme-prod
|
|
26
|
+
|
|
27
|
+
relipay apps list
|
|
28
|
+
relipay plans create --app <id> --slug pro_monthly --name Pro --amount 999
|
|
29
|
+
relipay plans list --app <id>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Add `--json` to any command for machine-readable output.
|
|
33
|
+
|
|
34
|
+
## Status
|
|
35
|
+
|
|
36
|
+
Phase 2.0 scaffold. Commands today: `version`, `doctor`, `init`, `apps`, `plans`. See [AGENTS.md](./AGENTS.md) for what's coming.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `relipay apps …` — Application management.
|
|
3
|
+
*
|
|
4
|
+
* relipay apps list [--tenant <id>]
|
|
5
|
+
* relipay apps get <id>
|
|
6
|
+
* relipay apps create --tenant <id> --name <name> --slug <slug>
|
|
7
|
+
*/
|
|
8
|
+
import type { Command } from 'commander';
|
|
9
|
+
export declare function registerAppsCommand(program: Command): void;
|
|
10
|
+
//# sourceMappingURL=apps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../../src/commands/apps.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAazC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAwE1D"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `relipay apps …` — Application management.
|
|
3
|
+
*
|
|
4
|
+
* relipay apps list [--tenant <id>]
|
|
5
|
+
* relipay apps get <id>
|
|
6
|
+
* relipay apps create --tenant <id> --name <name> --slug <slug>
|
|
7
|
+
*/
|
|
8
|
+
import { ok, fail, readGlobalOpts } from '../lib/output.js';
|
|
9
|
+
import { adminRequest } from '../lib/api.js';
|
|
10
|
+
export function registerAppsCommand(program) {
|
|
11
|
+
const apps = program.command('apps').description('Manage Applications');
|
|
12
|
+
apps
|
|
13
|
+
.command('list')
|
|
14
|
+
.description('List Applications (optionally filter by --tenant)')
|
|
15
|
+
.option('--tenant <id>', 'Restrict to one Tenant id')
|
|
16
|
+
.action(async function (opts) {
|
|
17
|
+
const ctx = readGlobalOpts(this);
|
|
18
|
+
const path = opts.tenant
|
|
19
|
+
? `/api/v1/admin/applications?tenantId=${encodeURIComponent(opts.tenant)}`
|
|
20
|
+
: '/api/v1/admin/applications';
|
|
21
|
+
const data = await adminRequest({ ctx, method: 'GET', path });
|
|
22
|
+
ok(ctx, { applications: data }, (d) => {
|
|
23
|
+
if (d.applications.length === 0) {
|
|
24
|
+
process.stdout.write('(no applications)\n');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
for (const a of d.applications) {
|
|
28
|
+
process.stdout.write(`${a.id} ${a.slug.padEnd(20)} ${a.name}\n`);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
apps
|
|
33
|
+
.command('get <id>')
|
|
34
|
+
.description('Get an Application by id')
|
|
35
|
+
.action(async function (id) {
|
|
36
|
+
const ctx = readGlobalOpts(this);
|
|
37
|
+
const data = await adminRequest({
|
|
38
|
+
ctx,
|
|
39
|
+
method: 'GET',
|
|
40
|
+
path: `/api/v1/admin/applications/${encodeURIComponent(id)}`,
|
|
41
|
+
});
|
|
42
|
+
ok(ctx, data, (d) => {
|
|
43
|
+
process.stdout.write(`id: ${d.id}\n`);
|
|
44
|
+
process.stdout.write(`name: ${d.name}\n`);
|
|
45
|
+
process.stdout.write(`slug: ${d.slug}\n`);
|
|
46
|
+
process.stdout.write(`tenant: ${d.tenantId}\n`);
|
|
47
|
+
process.stdout.write(`publicKey: ${d.publicKey}\n`);
|
|
48
|
+
process.stdout.write(`created: ${d.createdAt}\n`);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
apps
|
|
52
|
+
.command('create')
|
|
53
|
+
.description('Create an Application under a Tenant')
|
|
54
|
+
.requiredOption('--tenant <id>')
|
|
55
|
+
.requiredOption('--name <name>')
|
|
56
|
+
.requiredOption('--slug <slug>')
|
|
57
|
+
.action(async function (opts) {
|
|
58
|
+
const ctx = readGlobalOpts(this);
|
|
59
|
+
if (!opts.tenant || !opts.name || !opts.slug) {
|
|
60
|
+
fail(ctx, {
|
|
61
|
+
code: 'CLI_APPS_CREATE_ARGS_MISSING',
|
|
62
|
+
message: 'apps create requires --tenant, --name, --slug.',
|
|
63
|
+
fix: 'Pass all three. See `relipay apps create --help`.',
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
const data = await adminRequest({
|
|
67
|
+
ctx,
|
|
68
|
+
method: 'POST',
|
|
69
|
+
path: '/api/v1/admin/applications',
|
|
70
|
+
body: { tenantId: opts.tenant, name: opts.name, slug: opts.slug },
|
|
71
|
+
});
|
|
72
|
+
ok(ctx, data, (d) => {
|
|
73
|
+
process.stdout.write(`✓ ${d.id} ${d.slug} (${d.publicKey})\n`);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=apps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apps.js","sourceRoot":"","sources":["../../src/commands/apps.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `relipay doctor` — diagnose connectivity + config.
|
|
3
|
+
*
|
|
4
|
+
* Designed for AI agents to read structured output and self-heal. Each check
|
|
5
|
+
* has a `name`, a `status` (`ok` / `warn` / `fail`), a human `message`, and
|
|
6
|
+
* (when not OK) a concrete `fix`. Exit code is non-zero if any `fail` check
|
|
7
|
+
* triggered.
|
|
8
|
+
*/
|
|
9
|
+
import type { Command } from 'commander';
|
|
10
|
+
export declare function registerDoctorCommand(program: Command): void;
|
|
11
|
+
//# sourceMappingURL=doctor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAU5D"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `relipay doctor` — diagnose connectivity + config.
|
|
3
|
+
*
|
|
4
|
+
* Designed for AI agents to read structured output and self-heal. Each check
|
|
5
|
+
* has a `name`, a `status` (`ok` / `warn` / `fail`), a human `message`, and
|
|
6
|
+
* (when not OK) a concrete `fix`. Exit code is non-zero if any `fail` check
|
|
7
|
+
* triggered.
|
|
8
|
+
*/
|
|
9
|
+
import { ok, readGlobalOpts } from '../lib/output.js';
|
|
10
|
+
export function registerDoctorCommand(program) {
|
|
11
|
+
program
|
|
12
|
+
.command('doctor')
|
|
13
|
+
.description('Diagnose CLI configuration + reach the ReliPay API')
|
|
14
|
+
.action(async function () {
|
|
15
|
+
const ctx = readGlobalOpts(this);
|
|
16
|
+
const checks = await runDoctorChecks(ctx);
|
|
17
|
+
ok(ctx, { checks }, renderChecks);
|
|
18
|
+
if (checks.some((c) => c.status === 'fail'))
|
|
19
|
+
process.exit(1);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
async function runDoctorChecks(ctx) {
|
|
23
|
+
const checks = [];
|
|
24
|
+
if (!ctx.apiUrl) {
|
|
25
|
+
checks.push({
|
|
26
|
+
name: 'api-url',
|
|
27
|
+
status: 'fail',
|
|
28
|
+
message: 'RELIPAY_URL is not set.',
|
|
29
|
+
fix: 'Set RELIPAY_URL in your environment, or pass --api-url=https://your-relipay.example.',
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
checks.push({ name: 'api-url', status: 'ok', message: `using ${ctx.apiUrl}` });
|
|
34
|
+
}
|
|
35
|
+
if (!ctx.adminKey) {
|
|
36
|
+
checks.push({
|
|
37
|
+
name: 'admin-key',
|
|
38
|
+
status: 'warn',
|
|
39
|
+
message: 'SUPER_ADMIN_KEY is not set — admin commands will fail.',
|
|
40
|
+
fix: 'Set SUPER_ADMIN_KEY in your environment, or pass --admin-key=<hex>.',
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
checks.push({ name: 'admin-key', status: 'ok', message: 'admin key present' });
|
|
45
|
+
}
|
|
46
|
+
if (ctx.apiUrl) {
|
|
47
|
+
try {
|
|
48
|
+
const res = await fetch(`${ctx.apiUrl.replace(/\/$/, '')}/health`);
|
|
49
|
+
if (res.ok) {
|
|
50
|
+
checks.push({ name: 'health', status: 'ok', message: 'API responded 200 to /health' });
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
checks.push({
|
|
54
|
+
name: 'health',
|
|
55
|
+
status: 'fail',
|
|
56
|
+
message: `API returned HTTP ${res.status} to /health.`,
|
|
57
|
+
fix: 'Check that the ReliPay API is running at the configured URL.',
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
checks.push({
|
|
63
|
+
name: 'health',
|
|
64
|
+
status: 'fail',
|
|
65
|
+
message: `Could not reach ${ctx.apiUrl}/health: ${err.message}`,
|
|
66
|
+
fix: 'Check network reachability + that ReliPay is running.',
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return checks;
|
|
71
|
+
}
|
|
72
|
+
function renderChecks(d) {
|
|
73
|
+
for (const c of d.checks) {
|
|
74
|
+
const symbol = c.status === 'ok' ? '✓' : c.status === 'warn' ? '!' : '✗';
|
|
75
|
+
process.stdout.write(`${symbol} ${c.name.padEnd(12)} ${c.message}\n`);
|
|
76
|
+
if (c.fix)
|
|
77
|
+
process.stdout.write(` fix: ${c.fix}\n`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `relipay init` — bootstrap a fresh deployment.
|
|
3
|
+
*
|
|
4
|
+
* One-shot, non-interactive when given the required flags:
|
|
5
|
+
*
|
|
6
|
+
* relipay init --tenant-name "Acme" --owner-email ops@acme.com \
|
|
7
|
+
* --app-name "Acme Prod" --app-slug acme-prod \
|
|
8
|
+
* --json
|
|
9
|
+
*
|
|
10
|
+
* Creates:
|
|
11
|
+
* 1. A Tenant.
|
|
12
|
+
* 2. An Application under that Tenant.
|
|
13
|
+
* 3. A live API key for the new Application.
|
|
14
|
+
*
|
|
15
|
+
* Returns all three. The raw API key is shown ONCE — store it immediately.
|
|
16
|
+
*/
|
|
17
|
+
import type { Command } from 'commander';
|
|
18
|
+
export declare function registerInitCommand(program: Command): void;
|
|
19
|
+
//# sourceMappingURL=init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYzC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyD1D"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `relipay init` — bootstrap a fresh deployment.
|
|
3
|
+
*
|
|
4
|
+
* One-shot, non-interactive when given the required flags:
|
|
5
|
+
*
|
|
6
|
+
* relipay init --tenant-name "Acme" --owner-email ops@acme.com \
|
|
7
|
+
* --app-name "Acme Prod" --app-slug acme-prod \
|
|
8
|
+
* --json
|
|
9
|
+
*
|
|
10
|
+
* Creates:
|
|
11
|
+
* 1. A Tenant.
|
|
12
|
+
* 2. An Application under that Tenant.
|
|
13
|
+
* 3. A live API key for the new Application.
|
|
14
|
+
*
|
|
15
|
+
* Returns all three. The raw API key is shown ONCE — store it immediately.
|
|
16
|
+
*/
|
|
17
|
+
import { ok, fail, readGlobalOpts } from '../lib/output.js';
|
|
18
|
+
import { adminRequest } from '../lib/api.js';
|
|
19
|
+
export function registerInitCommand(program) {
|
|
20
|
+
program
|
|
21
|
+
.command('init')
|
|
22
|
+
.description('Bootstrap a fresh ReliPay deployment: Tenant + Application + first API key.')
|
|
23
|
+
.requiredOption('--tenant-name <name>', 'Display name for the new Tenant')
|
|
24
|
+
.requiredOption('--owner-email <email>', 'Owner email for the new Tenant')
|
|
25
|
+
.requiredOption('--app-name <name>', 'Display name for the first Application')
|
|
26
|
+
.requiredOption('--app-slug <slug>', 'URL-safe slug for the first Application')
|
|
27
|
+
.option('--api-key-name <name>', 'Label for the first API key', 'cli')
|
|
28
|
+
.action(async function (opts) {
|
|
29
|
+
const ctx = readGlobalOpts(this);
|
|
30
|
+
if (!opts.tenantName || !opts.ownerEmail || !opts.appName || !opts.appSlug) {
|
|
31
|
+
fail(ctx, {
|
|
32
|
+
code: 'CLI_INIT_ARGS_MISSING',
|
|
33
|
+
message: 'init requires --tenant-name, --owner-email, --app-name, --app-slug.',
|
|
34
|
+
fix: 'Pass all four flags. See `relipay init --help`.',
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
const tenant = await adminRequest({
|
|
38
|
+
ctx,
|
|
39
|
+
method: 'POST',
|
|
40
|
+
path: '/api/v1/admin/tenants',
|
|
41
|
+
body: { name: opts.tenantName, ownerEmail: opts.ownerEmail },
|
|
42
|
+
});
|
|
43
|
+
const application = await adminRequest({
|
|
44
|
+
ctx,
|
|
45
|
+
method: 'POST',
|
|
46
|
+
path: '/api/v1/admin/applications',
|
|
47
|
+
body: { tenantId: tenant.id, name: opts.appName, slug: opts.appSlug },
|
|
48
|
+
});
|
|
49
|
+
const keyResp = await adminRequest({
|
|
50
|
+
ctx,
|
|
51
|
+
method: 'POST',
|
|
52
|
+
path: `/api/v1/admin/applications/${application.id}/api-keys`,
|
|
53
|
+
body: { name: opts.apiKeyName ?? 'cli', mode: 'live' },
|
|
54
|
+
});
|
|
55
|
+
ok(ctx, { tenant, application, apiKey: keyResp }, (d) => {
|
|
56
|
+
process.stdout.write(`✓ Tenant ${d.tenant.id} ${d.tenant.name}\n`);
|
|
57
|
+
process.stdout.write(`✓ Application ${d.application.id} ${d.application.slug}\n`);
|
|
58
|
+
process.stdout.write(`✓ Public key ${d.application.publicKey}\n`);
|
|
59
|
+
process.stdout.write(`✓ API key ${d.apiKey.apiKey.keyPrefix}…\n\n`);
|
|
60
|
+
process.stdout.write(`SECRET KEY (shown once — save it now):\n`);
|
|
61
|
+
process.stdout.write(` ${d.apiKey.rawKey}\n`);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAU7C,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,6EAA6E,CAAC;SAC1F,cAAc,CAAC,sBAAsB,EAAE,iCAAiC,CAAC;SACzE,cAAc,CAAC,uBAAuB,EAAE,gCAAgC,CAAC;SACzE,cAAc,CAAC,mBAAmB,EAAE,wCAAwC,CAAC;SAC7E,cAAc,CAAC,mBAAmB,EAAE,yCAAyC,CAAC;SAC9E,MAAM,CAAC,uBAAuB,EAAE,6BAA6B,EAAE,KAAK,CAAC;SACrE,MAAM,CAAC,KAAK,WAA0B,IAAiB;QACtD,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAC3E,IAAI,CAAC,GAAG,EAAE;gBACR,IAAI,EAAE,uBAAuB;gBAC7B,OAAO,EAAE,qEAAqE;gBAC9E,GAAG,EAAE,iDAAiD;aACvD,CAAC,CAAC;QACL,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,YAAY,CAAmD;YAClF,GAAG;YACH,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,uBAAuB;YAC7B,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE;SAC7D,CAAC,CAAC;QAEH,MAAM,WAAW,GAAG,MAAM,YAAY,CAInC;YACD,GAAG;YACH,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,4BAA4B;YAClC,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE;SACtE,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,MAAM,YAAY,CAI/B;YACD,GAAG;YACH,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,8BAA8B,WAAW,CAAC,EAAE,WAAW;YAC7D,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,UAAU,IAAI,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE;SACvD,CAAC,CAAC;QAEH,EAAE,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE;YACtD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC;YACzE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,CAAC;YACnF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,WAAW,CAAC,SAAS,IAAI,CAAC,CAAC;YACnE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,OAAO,CAAC,CAAC;YACxE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;YACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `relipay plans …` — Plan management.
|
|
3
|
+
*
|
|
4
|
+
* relipay plans list --app <id> [--include-inactive]
|
|
5
|
+
* relipay plans create --app <id> --slug <slug> --name <name> --amount <int>
|
|
6
|
+
* [--currency USD] [--interval MONTH|YEAR]
|
|
7
|
+
* relipay plans set-active --app <id> --slug <slug> --active true|false
|
|
8
|
+
*
|
|
9
|
+
* Money is the smallest currency unit (cents) — never floats. The CLI
|
|
10
|
+
* refuses fractional `--amount` values to prevent silent rounding bugs.
|
|
11
|
+
*/
|
|
12
|
+
import type { Command } from 'commander';
|
|
13
|
+
export declare function registerPlansCommand(program: Command): void;
|
|
14
|
+
//# sourceMappingURL=plans.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plans.d.ts","sourceRoot":"","sources":["../../src/commands/plans.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAezC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2G3D"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `relipay plans …` — Plan management.
|
|
3
|
+
*
|
|
4
|
+
* relipay plans list --app <id> [--include-inactive]
|
|
5
|
+
* relipay plans create --app <id> --slug <slug> --name <name> --amount <int>
|
|
6
|
+
* [--currency USD] [--interval MONTH|YEAR]
|
|
7
|
+
* relipay plans set-active --app <id> --slug <slug> --active true|false
|
|
8
|
+
*
|
|
9
|
+
* Money is the smallest currency unit (cents) — never floats. The CLI
|
|
10
|
+
* refuses fractional `--amount` values to prevent silent rounding bugs.
|
|
11
|
+
*/
|
|
12
|
+
import { ok, fail, readGlobalOpts } from '../lib/output.js';
|
|
13
|
+
import { adminRequest } from '../lib/api.js';
|
|
14
|
+
export function registerPlansCommand(program) {
|
|
15
|
+
const plans = program.command('plans').description('Manage Plans');
|
|
16
|
+
plans
|
|
17
|
+
.command('list')
|
|
18
|
+
.description('List Plans for an Application')
|
|
19
|
+
.requiredOption('--app <id>', 'Application id')
|
|
20
|
+
.option('--include-inactive', 'Include deactivated plans', false)
|
|
21
|
+
.action(async function (opts) {
|
|
22
|
+
const ctx = readGlobalOpts(this);
|
|
23
|
+
const path = `/api/v1/admin/applications/${encodeURIComponent(opts.app)}/plans${opts.includeInactive ? '?includeInactive=true' : ''}`;
|
|
24
|
+
const data = await adminRequest({ ctx, method: 'GET', path });
|
|
25
|
+
ok(ctx, { plans: data }, (d) => {
|
|
26
|
+
if (d.plans.length === 0) {
|
|
27
|
+
process.stdout.write('(no plans)\n');
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
for (const p of d.plans) {
|
|
31
|
+
const flag = p.active ? ' ' : ' [inactive] ';
|
|
32
|
+
process.stdout.write(`${p.slug.padEnd(20)} ${String(p.amount).padStart(8)} ${p.currency}/${p.interval}${flag}${p.name}\n`);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
plans
|
|
37
|
+
.command('create')
|
|
38
|
+
.description('Create a Plan')
|
|
39
|
+
.requiredOption('--app <id>', 'Application id')
|
|
40
|
+
.requiredOption('--slug <slug>')
|
|
41
|
+
.requiredOption('--name <name>')
|
|
42
|
+
.requiredOption('--amount <int>', 'Smallest currency unit, e.g. cents')
|
|
43
|
+
.option('--currency <code>', 'ISO 4217 — defaults to USD', 'USD')
|
|
44
|
+
.option('--interval <interval>', 'MONTH | YEAR', 'MONTH')
|
|
45
|
+
.action(async function (opts) {
|
|
46
|
+
const ctx = readGlobalOpts(this);
|
|
47
|
+
const amountInt = Number(opts.amount);
|
|
48
|
+
if (!Number.isInteger(amountInt) || amountInt < 0) {
|
|
49
|
+
fail(ctx, {
|
|
50
|
+
code: 'CLI_PLANS_AMOUNT_INVALID',
|
|
51
|
+
message: `--amount must be a non-negative integer (smallest currency unit). Got "${opts.amount}".`,
|
|
52
|
+
fix: 'Pass an integer like 999 (= $9.99 in USD). Floats are rejected to prevent silent rounding.',
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (!['MONTH', 'YEAR'].includes(opts.interval)) {
|
|
56
|
+
fail(ctx, {
|
|
57
|
+
code: 'CLI_PLANS_INTERVAL_INVALID',
|
|
58
|
+
message: `--interval must be MONTH or YEAR. Got "${opts.interval}".`,
|
|
59
|
+
fix: 'Use MONTH or YEAR.',
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
const data = await adminRequest({
|
|
63
|
+
ctx,
|
|
64
|
+
method: 'POST',
|
|
65
|
+
path: `/api/v1/admin/applications/${encodeURIComponent(opts.app)}/plans`,
|
|
66
|
+
body: {
|
|
67
|
+
slug: opts.slug,
|
|
68
|
+
name: opts.name,
|
|
69
|
+
amount: amountInt,
|
|
70
|
+
currency: opts.currency,
|
|
71
|
+
interval: opts.interval,
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
ok(ctx, data, (d) => {
|
|
75
|
+
process.stdout.write(`✓ ${d.slug} ${d.amount} ${d.currency}/${d.interval}\n`);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
plans
|
|
79
|
+
.command('set-active')
|
|
80
|
+
.description("Toggle a Plan's active flag")
|
|
81
|
+
.requiredOption('--app <id>', 'Application id')
|
|
82
|
+
.requiredOption('--slug <slug>')
|
|
83
|
+
.requiredOption('--active <bool>', 'true | false')
|
|
84
|
+
.action(async function (opts) {
|
|
85
|
+
const ctx = readGlobalOpts(this);
|
|
86
|
+
const active = opts.active === 'true';
|
|
87
|
+
if (!['true', 'false'].includes(opts.active)) {
|
|
88
|
+
fail(ctx, {
|
|
89
|
+
code: 'CLI_PLANS_ACTIVE_INVALID',
|
|
90
|
+
message: '--active must be "true" or "false".',
|
|
91
|
+
fix: 'Pass --active true or --active false.',
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
const data = await adminRequest({
|
|
95
|
+
ctx,
|
|
96
|
+
method: 'PATCH',
|
|
97
|
+
path: `/api/v1/admin/applications/${encodeURIComponent(opts.app)}/plans/${encodeURIComponent(opts.slug)}`,
|
|
98
|
+
body: { active },
|
|
99
|
+
});
|
|
100
|
+
ok(ctx, data, (d) => {
|
|
101
|
+
process.stdout.write(`✓ ${d.slug} → active=${d.active}\n`);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=plans.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plans.js","sourceRoot":"","sources":["../../src/commands/plans.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/commands/version.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAQ7D"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ok, readGlobalOpts } from '../lib/output.js';
|
|
2
|
+
const VERSION = '0.0.0';
|
|
3
|
+
export function registerVersionCommand(program) {
|
|
4
|
+
program
|
|
5
|
+
.command('version')
|
|
6
|
+
.description('Print the CLI version')
|
|
7
|
+
.action(function () {
|
|
8
|
+
const ctx = readGlobalOpts(this);
|
|
9
|
+
ok(ctx, { version: VERSION }, (d) => process.stdout.write(`${d.version}\n`));
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/commands/version.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEtD,MAAM,OAAO,GAAG,OAAO,CAAC;AAExB,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,OAAO;SACJ,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,uBAAuB,CAAC;SACpC,MAAM,CAAC;QACN,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;QACjC,EAAE,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;AACP,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* `relipay` — command-line interface.
|
|
4
|
+
*
|
|
5
|
+
* Two design rules drive everything in here (per PLAN.md §2.5 "AI-first DX"):
|
|
6
|
+
*
|
|
7
|
+
* 1. **Every command runs non-interactively when given enough flags.**
|
|
8
|
+
* No required prompts. An AI agent can call `relipay apps create
|
|
9
|
+
* --tenant tn_xxx --name "MyApp" --slug myapp --json` and parse the
|
|
10
|
+
* output without ever needing a TTY.
|
|
11
|
+
*
|
|
12
|
+
* 2. **Output is structured when asked.** Pass `--json` and you get a
|
|
13
|
+
* single JSON document on stdout suitable for `jq`. Without `--json`,
|
|
14
|
+
* the same data is rendered as friendly human text on stdout. Errors
|
|
15
|
+
* always go to stderr; exit code matches success.
|
|
16
|
+
*/
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;GAcG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* `relipay` — command-line interface.
|
|
4
|
+
*
|
|
5
|
+
* Two design rules drive everything in here (per PLAN.md §2.5 "AI-first DX"):
|
|
6
|
+
*
|
|
7
|
+
* 1. **Every command runs non-interactively when given enough flags.**
|
|
8
|
+
* No required prompts. An AI agent can call `relipay apps create
|
|
9
|
+
* --tenant tn_xxx --name "MyApp" --slug myapp --json` and parse the
|
|
10
|
+
* output without ever needing a TTY.
|
|
11
|
+
*
|
|
12
|
+
* 2. **Output is structured when asked.** Pass `--json` and you get a
|
|
13
|
+
* single JSON document on stdout suitable for `jq`. Without `--json`,
|
|
14
|
+
* the same data is rendered as friendly human text on stdout. Errors
|
|
15
|
+
* always go to stderr; exit code matches success.
|
|
16
|
+
*/
|
|
17
|
+
import { Command } from 'commander';
|
|
18
|
+
import { registerInitCommand } from './commands/init.js';
|
|
19
|
+
import { registerDoctorCommand } from './commands/doctor.js';
|
|
20
|
+
import { registerAppsCommand } from './commands/apps.js';
|
|
21
|
+
import { registerPlansCommand } from './commands/plans.js';
|
|
22
|
+
import { registerVersionCommand } from './commands/version.js';
|
|
23
|
+
const program = new Command();
|
|
24
|
+
program
|
|
25
|
+
.name('relipay')
|
|
26
|
+
.description('ReliPay command-line interface. Pass --json on any command for machine-readable output. ' +
|
|
27
|
+
'See packages/cli/AGENTS.md for the full agent-facing contract.')
|
|
28
|
+
.option('--api-url <url>', 'Override RELIPAY_URL', process.env.RELIPAY_URL)
|
|
29
|
+
.option('--admin-key <key>', 'Override SUPER_ADMIN_KEY', process.env.SUPER_ADMIN_KEY)
|
|
30
|
+
.option('--json', 'Emit machine-readable JSON on stdout (errors still go to stderr).')
|
|
31
|
+
.showHelpAfterError();
|
|
32
|
+
registerVersionCommand(program);
|
|
33
|
+
registerInitCommand(program);
|
|
34
|
+
registerDoctorCommand(program);
|
|
35
|
+
registerAppsCommand(program);
|
|
36
|
+
registerPlansCommand(program);
|
|
37
|
+
program.parseAsync(process.argv).catch((err) => {
|
|
38
|
+
// Top-level safety net. Individual commands handle their own errors and
|
|
39
|
+
// call process.exit(1); we only get here if a command throws something
|
|
40
|
+
// unhandled.
|
|
41
|
+
// eslint-disable-next-line no-console
|
|
42
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
43
|
+
process.exit(1);
|
|
44
|
+
});
|
|
45
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,SAAS,CAAC;KACf,WAAW,CACV,0FAA0F;IACxF,gEAAgE,CACnE;KACA,MAAM,CAAC,iBAAiB,EAAE,sBAAsB,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;KAC1E,MAAM,CAAC,mBAAmB,EAAE,0BAA0B,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;KACpF,MAAM,CAAC,QAAQ,EAAE,mEAAmE,CAAC;KACrF,kBAAkB,EAAE,CAAC;AAExB,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAE9B,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IACtD,wEAAwE;IACxE,uEAAuE;IACvE,aAAa;IACb,sCAAsC;IACtC,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thin admin-side fetch helper. The CLI calls `/api/v1/admin/*` routes
|
|
3
|
+
* with a Bearer header carrying SUPER_ADMIN_KEY. We don't use
|
|
4
|
+
* `@relipay/node` here because that SDK is for the *public* API
|
|
5
|
+
* (Application secret keys), not the admin surface.
|
|
6
|
+
*/
|
|
7
|
+
import { type OutputContext } from './output.js';
|
|
8
|
+
export interface RequestArgs {
|
|
9
|
+
ctx: OutputContext;
|
|
10
|
+
method: 'GET' | 'POST' | 'PATCH' | 'DELETE';
|
|
11
|
+
path: string;
|
|
12
|
+
body?: unknown;
|
|
13
|
+
}
|
|
14
|
+
export declare function adminRequest<T>(args: RequestArgs): Promise<T>;
|
|
15
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAQ,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAEvD,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,aAAa,CAAC;IACnB,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAOD,wBAAsB,YAAY,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,CAyCnE"}
|
package/dist/lib/api.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thin admin-side fetch helper. The CLI calls `/api/v1/admin/*` routes
|
|
3
|
+
* with a Bearer header carrying SUPER_ADMIN_KEY. We don't use
|
|
4
|
+
* `@relipay/node` here because that SDK is for the *public* API
|
|
5
|
+
* (Application secret keys), not the admin surface.
|
|
6
|
+
*/
|
|
7
|
+
import { fail } from './output.js';
|
|
8
|
+
export async function adminRequest(args) {
|
|
9
|
+
if (!args.ctx.apiUrl) {
|
|
10
|
+
fail(args.ctx, {
|
|
11
|
+
code: 'CLI_API_URL_MISSING',
|
|
12
|
+
message: 'No ReliPay API URL configured.',
|
|
13
|
+
fix: 'Set RELIPAY_URL in your environment, or pass --api-url=https://your-relipay.example.',
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
if (!args.ctx.adminKey) {
|
|
17
|
+
fail(args.ctx, {
|
|
18
|
+
code: 'CLI_ADMIN_KEY_MISSING',
|
|
19
|
+
message: 'No admin credential configured.',
|
|
20
|
+
fix: 'Set SUPER_ADMIN_KEY in your environment, or pass --admin-key=<hex>.',
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
const url = `${args.ctx.apiUrl.replace(/\/$/, '')}${args.path}`;
|
|
24
|
+
const res = await fetch(url, {
|
|
25
|
+
method: args.method,
|
|
26
|
+
headers: {
|
|
27
|
+
Authorization: `Bearer ${args.ctx.adminKey}`,
|
|
28
|
+
...(args.body !== undefined ? { 'Content-Type': 'application/json' } : {}),
|
|
29
|
+
},
|
|
30
|
+
...(args.body !== undefined ? { body: JSON.stringify(args.body) } : {}),
|
|
31
|
+
});
|
|
32
|
+
const json = (await res.json().catch(() => ({})));
|
|
33
|
+
if (!res.ok || ('success' in json && json.success === false)) {
|
|
34
|
+
if ('error' in json) {
|
|
35
|
+
fail(args.ctx, json.error);
|
|
36
|
+
}
|
|
37
|
+
fail(args.ctx, {
|
|
38
|
+
code: 'CLI_HTTP_ERROR',
|
|
39
|
+
message: `Request failed with HTTP ${res.status}.`,
|
|
40
|
+
fix: 'Check the ReliPay API logs for details.',
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return json.data;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAsB,MAAM,aAAa,CAAC;AAcvD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAI,IAAiB;IACrD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QACrB,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;YACb,IAAI,EAAE,qBAAqB;YAC3B,OAAO,EAAE,gCAAgC;YACzC,GAAG,EAAE,sFAAsF;SAC5F,CAAC,CAAC;IACL,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QACvB,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;YACb,IAAI,EAAE,uBAAuB;YAC7B,OAAO,EAAE,iCAAiC;YAC1C,GAAG,EAAE,qEAAqE;SAC3E,CAAC,CAAC;IACL,CAAC;IAED,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAChE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,OAAO,EAAE;YACP,aAAa,EAAE,UAAU,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE;YAC5C,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC3E;QACD,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACxE,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAE/B,CAAC;IAElB,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK,CAAC,EAAE,CAAC;QAC7D,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;YACpB,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;YACb,IAAI,EAAE,gBAAgB;YACtB,OAAO,EAAE,4BAA4B,GAAG,CAAC,MAAM,GAAG;YAClD,GAAG,EAAE,yCAAyC;SAC/C,CAAC,CAAC;IACL,CAAC;IACD,OAAQ,IAAmC,CAAC,IAAI,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output helpers — used by every command to emit either human-friendly text
|
|
3
|
+
* or machine-readable JSON, depending on the global `--json` flag.
|
|
4
|
+
*
|
|
5
|
+
* Errors always go to stderr; exit code is 0 on success, 1 on failure.
|
|
6
|
+
* Commands should return *data*, not call `process.exit` directly — the
|
|
7
|
+
* runner here decides on the right exit path.
|
|
8
|
+
*/
|
|
9
|
+
import type { Command } from 'commander';
|
|
10
|
+
export interface OutputContext {
|
|
11
|
+
json: boolean;
|
|
12
|
+
apiUrl: string | undefined;
|
|
13
|
+
adminKey: string | undefined;
|
|
14
|
+
}
|
|
15
|
+
/** Read globals (`--json`, `--api-url`, `--admin-key`) from any subcommand. */
|
|
16
|
+
export declare function readGlobalOpts(cmd: Command): OutputContext;
|
|
17
|
+
/** Print success output. JSON-mode: a single JSON document. Text mode: `render` runs. */
|
|
18
|
+
export declare function ok<T>(ctx: OutputContext, data: T, render: (d: T) => void): void;
|
|
19
|
+
/** Fail with an error envelope on stderr and a non-zero exit. */
|
|
20
|
+
export declare function fail(ctx: OutputContext, args: {
|
|
21
|
+
code: string;
|
|
22
|
+
message: string;
|
|
23
|
+
fix?: string;
|
|
24
|
+
}): never;
|
|
25
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/lib/output.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B;AAED,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,aAAa,CAU1D;AAED,yFAAyF;AACzF,wBAAgB,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,GAAG,IAAI,CAM/E;AAED,iEAAiE;AACjE,wBAAgB,IAAI,CAClB,GAAG,EAAE,aAAa,EAClB,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACpD,KAAK,CASP"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output helpers — used by every command to emit either human-friendly text
|
|
3
|
+
* or machine-readable JSON, depending on the global `--json` flag.
|
|
4
|
+
*
|
|
5
|
+
* Errors always go to stderr; exit code is 0 on success, 1 on failure.
|
|
6
|
+
* Commands should return *data*, not call `process.exit` directly — the
|
|
7
|
+
* runner here decides on the right exit path.
|
|
8
|
+
*/
|
|
9
|
+
/** Read globals (`--json`, `--api-url`, `--admin-key`) from any subcommand. */
|
|
10
|
+
export function readGlobalOpts(cmd) {
|
|
11
|
+
// commander attaches global opts to the root program; walk parents.
|
|
12
|
+
let root = cmd;
|
|
13
|
+
while (root.parent)
|
|
14
|
+
root = root.parent;
|
|
15
|
+
const opts = root.opts();
|
|
16
|
+
return {
|
|
17
|
+
json: Boolean(opts.json),
|
|
18
|
+
apiUrl: opts.apiUrl,
|
|
19
|
+
adminKey: opts.adminKey,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/** Print success output. JSON-mode: a single JSON document. Text mode: `render` runs. */
|
|
23
|
+
export function ok(ctx, data, render) {
|
|
24
|
+
if (ctx.json) {
|
|
25
|
+
process.stdout.write(JSON.stringify(data, null, 2) + '\n');
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
render(data);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** Fail with an error envelope on stderr and a non-zero exit. */
|
|
32
|
+
export function fail(ctx, args) {
|
|
33
|
+
if (ctx.json) {
|
|
34
|
+
process.stderr.write(JSON.stringify({ success: false, error: args }, null, 2) + '\n');
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
process.stderr.write(`error: ${args.message}\n`);
|
|
38
|
+
process.stderr.write(`code: ${args.code}\n`);
|
|
39
|
+
if (args.fix)
|
|
40
|
+
process.stderr.write(`fix: ${args.fix}\n`);
|
|
41
|
+
}
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/lib/output.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH,+EAA+E;AAC/E,MAAM,UAAU,cAAc,CAAC,GAAY;IACzC,oEAAoE;IACpE,IAAI,IAAI,GAAY,GAAG,CAAC;IACxB,OAAO,IAAI,CAAC,MAAM;QAAE,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAA0D,CAAC;IACjF,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;QACxB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;KACxB,CAAC;AACJ,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,EAAE,CAAI,GAAkB,EAAE,IAAO,EAAE,MAAsB;IACvE,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7D,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,IAAI,CAAC,CAAC;IACf,CAAC;AACH,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,IAAI,CAClB,GAAkB,EAClB,IAAqD;IAErD,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACxF,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC;QACjD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;QAC9C,IAAI,IAAI,CAAC,GAAG;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7D,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@relipay/cli",
|
|
3
|
+
"version": "0.1.0-beta.0",
|
|
4
|
+
"description": "ReliPay command-line interface — designed for both human developers and AI agents.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"relipay": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"AGENTS.md",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"keywords": [
|
|
23
|
+
"relipay",
|
|
24
|
+
"cli",
|
|
25
|
+
"auth",
|
|
26
|
+
"billing"
|
|
27
|
+
],
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"commander": "^12.1.0",
|
|
30
|
+
"@relipay/node": "0.1.0-beta.0",
|
|
31
|
+
"@relipay/shared-types": "0.1.0-beta.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/node": "^22.9.0",
|
|
35
|
+
"typescript": "^5.6.3",
|
|
36
|
+
"vitest": "^2.1.5"
|
|
37
|
+
},
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public",
|
|
40
|
+
"tag": "beta"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsc -p tsconfig.json && chmod +x dist/index.js",
|
|
44
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
45
|
+
"lint": "echo \"(eslint not yet wired)\"",
|
|
46
|
+
"test": "vitest run"
|
|
47
|
+
}
|
|
48
|
+
}
|