@norbix.ai/cli 0.1.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/LICENSE +21 -0
- package/README.md +121 -0
- package/bin/run.js +4 -0
- package/dist/base.js +100 -0
- package/dist/commands/account/billing-portal.js +21 -0
- package/dist/commands/account/profile.js +12 -0
- package/dist/commands/account/projects.js +12 -0
- package/dist/commands/account/regions.js +12 -0
- package/dist/commands/account/status.js +12 -0
- package/dist/commands/account/team.js +12 -0
- package/dist/commands/account/usage.js +12 -0
- package/dist/commands/api.js +87 -0
- package/dist/commands/apikeys/list.js +12 -0
- package/dist/commands/apikeys/regenerate.js +25 -0
- package/dist/commands/config/get.js +20 -0
- package/dist/commands/config/list.js +18 -0
- package/dist/commands/config/set.js +25 -0
- package/dist/commands/config/unset.js +20 -0
- package/dist/commands/db/aggregate.js +42 -0
- package/dist/commands/db/aggregates.js +16 -0
- package/dist/commands/db/count.js +26 -0
- package/dist/commands/db/delete.js +45 -0
- package/dist/commands/db/distinct.js +25 -0
- package/dist/commands/db/find.js +33 -0
- package/dist/commands/db/get.js +20 -0
- package/dist/commands/db/insert-many.js +29 -0
- package/dist/commands/db/insert.js +26 -0
- package/dist/commands/db/replace.js +25 -0
- package/dist/commands/db/schema.js +16 -0
- package/dist/commands/db/schemas.js +20 -0
- package/dist/commands/db/taxonomies.js +20 -0
- package/dist/commands/db/taxonomy.js +16 -0
- package/dist/commands/db/update.js +44 -0
- package/dist/commands/email/archive.js +16 -0
- package/dist/commands/email/campaign.js +21 -0
- package/dist/commands/email/campaigns.js +20 -0
- package/dist/commands/email/clone.js +16 -0
- package/dist/commands/email/delete.js +25 -0
- package/dist/commands/email/stop.js +31 -0
- package/dist/commands/email/template.js +16 -0
- package/dist/commands/email/templates.js +18 -0
- package/dist/commands/email/unarchive.js +16 -0
- package/dist/commands/env/delete.js +28 -0
- package/dist/commands/env/list.js +12 -0
- package/dist/commands/env/use.js +17 -0
- package/dist/commands/files/delete.js +34 -0
- package/dist/commands/files/download.js +45 -0
- package/dist/commands/files/info.js +27 -0
- package/dist/commands/files/list.js +30 -0
- package/dist/commands/files/sign.js +29 -0
- package/dist/commands/files/upload.js +62 -0
- package/dist/commands/integrations.js +34 -0
- package/dist/commands/login.js +65 -0
- package/dist/commands/logout.js +27 -0
- package/dist/commands/logs/list.js +38 -0
- package/dist/commands/logs/settings.js +12 -0
- package/dist/commands/logs/trail.js +18 -0
- package/dist/commands/module.js +48 -0
- package/dist/commands/payments/disable.js +16 -0
- package/dist/commands/payments/enable.js +16 -0
- package/dist/commands/payments/integrations.js +12 -0
- package/dist/commands/payments/trigger.js +16 -0
- package/dist/commands/payments/triggers.js +12 -0
- package/dist/commands/push/archive.js +16 -0
- package/dist/commands/push/campaign.js +21 -0
- package/dist/commands/push/campaigns.js +20 -0
- package/dist/commands/push/clone.js +16 -0
- package/dist/commands/push/delete.js +25 -0
- package/dist/commands/push/stop.js +30 -0
- package/dist/commands/push/template.js +16 -0
- package/dist/commands/push/templates.js +18 -0
- package/dist/commands/push/unarchive.js +16 -0
- package/dist/commands/scheduler/delete.js +25 -0
- package/dist/commands/scheduler/disable.js +16 -0
- package/dist/commands/scheduler/enable.js +16 -0
- package/dist/commands/scheduler/get.js +16 -0
- package/dist/commands/scheduler/list.js +20 -0
- package/dist/commands/sms/archive.js +16 -0
- package/dist/commands/sms/campaign.js +21 -0
- package/dist/commands/sms/campaigns.js +20 -0
- package/dist/commands/sms/clone.js +16 -0
- package/dist/commands/sms/delete.js +25 -0
- package/dist/commands/sms/stop.js +30 -0
- package/dist/commands/sms/template.js +16 -0
- package/dist/commands/sms/templates.js +18 -0
- package/dist/commands/sms/unarchive.js +16 -0
- package/dist/commands/users/block.js +16 -0
- package/dist/commands/users/delete.js +25 -0
- package/dist/commands/users/get.js +16 -0
- package/dist/commands/users/invite.js +16 -0
- package/dist/commands/users/list.js +27 -0
- package/dist/commands/users/policies.js +12 -0
- package/dist/commands/users/roles.js +12 -0
- package/dist/commands/users/unblock.js +16 -0
- package/dist/commands/webhooks/disable.js +18 -0
- package/dist/commands/webhooks/enable.js +18 -0
- package/dist/commands/webhooks/remove.js +30 -0
- package/dist/commands/webhooks/secret.js +34 -0
- package/dist/commands/webhooks/show.js +12 -0
- package/dist/commands/whoami.js +43 -0
- package/dist/lib/files.js +35 -0
- package/dist/lib/json.js +21 -0
- package/dist/lib/store.js +39 -0
- package/oclif.manifest.json +8497 -0
- package/package.json +114 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Args } from '@oclif/core';
|
|
2
|
+
import { writeFile } from 'node:fs/promises';
|
|
3
|
+
import { basename } from 'node:path';
|
|
4
|
+
import { BaseCommand } from '../../base.js';
|
|
5
|
+
import { integrationFlag, resolveIntegration } from '../../lib/files.js';
|
|
6
|
+
export default class FilesDownload extends BaseCommand {
|
|
7
|
+
static description = 'Download a file to disk (via a signed URL)';
|
|
8
|
+
static examples = [
|
|
9
|
+
'<%= config.bin %> files download invoices/2026/invoice.pdf',
|
|
10
|
+
'<%= config.bin %> files download invoices/2026/invoice.pdf ./local-copy.pdf',
|
|
11
|
+
];
|
|
12
|
+
static args = {
|
|
13
|
+
remote: Args.string({ required: true, description: 'Remote file path' }),
|
|
14
|
+
file: Args.string({
|
|
15
|
+
required: false,
|
|
16
|
+
description: 'Local target file (default: remote file name in current folder)',
|
|
17
|
+
}),
|
|
18
|
+
};
|
|
19
|
+
static flags = {
|
|
20
|
+
integration: integrationFlag,
|
|
21
|
+
};
|
|
22
|
+
async run() {
|
|
23
|
+
const { args, flags } = await this.parse(FilesDownload);
|
|
24
|
+
const client = this.client(flags);
|
|
25
|
+
const integration = resolveIntegration(flags.integration, this.readStore().filesIntegrationId);
|
|
26
|
+
if (!integration) {
|
|
27
|
+
this.error('No files integration ID. Pass --integration or run `norbix config set filesIntegrationId <id>`.');
|
|
28
|
+
}
|
|
29
|
+
const { url } = await client.api.files.getSignedUrl({
|
|
30
|
+
filesIntegrationId: integration,
|
|
31
|
+
path: args.remote,
|
|
32
|
+
});
|
|
33
|
+
if (!url)
|
|
34
|
+
this.error('Backend did not return a download URL.');
|
|
35
|
+
const res = await fetch(url);
|
|
36
|
+
if (!res.ok)
|
|
37
|
+
this.error(`Download failed: HTTP ${res.status} ${res.statusText}`);
|
|
38
|
+
const target = args.file ?? basename(args.remote);
|
|
39
|
+
const bytes = Buffer.from(await res.arrayBuffer());
|
|
40
|
+
await writeFile(target, bytes);
|
|
41
|
+
const result = { path: args.remote, savedTo: target, sizeBytes: bytes.length };
|
|
42
|
+
this.print(`Downloaded ${args.remote} → ${target} (${bytes.length} bytes).`);
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Args } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../base.js';
|
|
3
|
+
import { integrationFlag, resolveIntegration } from '../../lib/files.js';
|
|
4
|
+
export default class FilesInfo extends BaseCommand {
|
|
5
|
+
static description = 'Show metadata for one file';
|
|
6
|
+
static examples = ['<%= config.bin %> files info invoices/2026/invoice.pdf'];
|
|
7
|
+
static args = {
|
|
8
|
+
remote: Args.string({ required: true, description: 'Remote file path' }),
|
|
9
|
+
};
|
|
10
|
+
static flags = {
|
|
11
|
+
integration: integrationFlag,
|
|
12
|
+
};
|
|
13
|
+
async run() {
|
|
14
|
+
const { args, flags } = await this.parse(FilesInfo);
|
|
15
|
+
const client = this.client(flags);
|
|
16
|
+
const integration = resolveIntegration(flags.integration, this.readStore().filesIntegrationId);
|
|
17
|
+
if (!integration) {
|
|
18
|
+
this.error('No files integration ID. Pass --integration or run `norbix config set filesIntegrationId <id>`.');
|
|
19
|
+
}
|
|
20
|
+
const res = await client.api.files.getFileInfo({
|
|
21
|
+
filesIntegrationId: integration,
|
|
22
|
+
path: args.remote,
|
|
23
|
+
});
|
|
24
|
+
this.print(res);
|
|
25
|
+
return res;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Args } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../base.js';
|
|
3
|
+
import { integrationFlag, resolveIntegration } from '../../lib/files.js';
|
|
4
|
+
export default class FilesList extends BaseCommand {
|
|
5
|
+
static description = 'List files in a folder of a files integration';
|
|
6
|
+
static examples = [
|
|
7
|
+
'<%= config.bin %> files list --integration 66b2...',
|
|
8
|
+
'<%= config.bin %> files list invoices/2026',
|
|
9
|
+
];
|
|
10
|
+
static args = {
|
|
11
|
+
path: Args.string({ required: false, description: 'Folder path (default: root)' }),
|
|
12
|
+
};
|
|
13
|
+
static flags = {
|
|
14
|
+
integration: integrationFlag,
|
|
15
|
+
};
|
|
16
|
+
async run() {
|
|
17
|
+
const { args, flags } = await this.parse(FilesList);
|
|
18
|
+
const client = this.client(flags);
|
|
19
|
+
const integration = resolveIntegration(flags.integration, this.readStore().filesIntegrationId);
|
|
20
|
+
if (!integration) {
|
|
21
|
+
this.error('No files integration ID. Pass --integration or run `norbix config set filesIntegrationId <id>`.');
|
|
22
|
+
}
|
|
23
|
+
const res = await client.api.files.listFiles({
|
|
24
|
+
filesIntegrationId: integration,
|
|
25
|
+
path: args.path,
|
|
26
|
+
});
|
|
27
|
+
this.print(res);
|
|
28
|
+
return res;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../base.js';
|
|
3
|
+
import { integrationFlag, resolveIntegration } from '../../lib/files.js';
|
|
4
|
+
export default class FilesSign extends BaseCommand {
|
|
5
|
+
static description = 'Get a temporary signed download URL for a file';
|
|
6
|
+
static examples = ['<%= config.bin %> files sign invoices/2026/invoice.pdf --expires 3600'];
|
|
7
|
+
static args = {
|
|
8
|
+
remote: Args.string({ required: true, description: 'Remote file path' }),
|
|
9
|
+
};
|
|
10
|
+
static flags = {
|
|
11
|
+
integration: integrationFlag,
|
|
12
|
+
expires: Flags.integer({ description: 'URL lifetime in seconds' }),
|
|
13
|
+
};
|
|
14
|
+
async run() {
|
|
15
|
+
const { args, flags } = await this.parse(FilesSign);
|
|
16
|
+
const client = this.client(flags);
|
|
17
|
+
const integration = resolveIntegration(flags.integration, this.readStore().filesIntegrationId);
|
|
18
|
+
if (!integration) {
|
|
19
|
+
this.error('No files integration ID. Pass --integration or run `norbix config set filesIntegrationId <id>`.');
|
|
20
|
+
}
|
|
21
|
+
const res = await client.api.files.getSignedUrl({
|
|
22
|
+
filesIntegrationId: integration,
|
|
23
|
+
path: args.remote,
|
|
24
|
+
expirationSeconds: flags.expires,
|
|
25
|
+
});
|
|
26
|
+
this.print(res.url ?? res);
|
|
27
|
+
return res;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { basename } from 'node:path';
|
|
4
|
+
import { BaseCommand } from '../../base.js';
|
|
5
|
+
import { guessContentType, integrationFlag, resolveIntegration } from '../../lib/files.js';
|
|
6
|
+
export default class FilesUpload extends BaseCommand {
|
|
7
|
+
static description = `Upload a local file (three steps: get signed URL, PUT bytes, commit).`;
|
|
8
|
+
static examples = [
|
|
9
|
+
'<%= config.bin %> files upload ./invoice.pdf',
|
|
10
|
+
'<%= config.bin %> files upload ./invoice.pdf invoices/2026/invoice.pdf',
|
|
11
|
+
];
|
|
12
|
+
static args = {
|
|
13
|
+
file: Args.string({ required: true, description: 'Local file to upload' }),
|
|
14
|
+
remote: Args.string({
|
|
15
|
+
required: false,
|
|
16
|
+
description: 'Remote path (default: file name in the root folder)',
|
|
17
|
+
}),
|
|
18
|
+
};
|
|
19
|
+
static flags = {
|
|
20
|
+
integration: integrationFlag,
|
|
21
|
+
'content-type': Flags.string({ description: 'MIME type (default: guessed from extension)' }),
|
|
22
|
+
};
|
|
23
|
+
async run() {
|
|
24
|
+
const { args, flags } = await this.parse(FilesUpload);
|
|
25
|
+
const client = this.client(flags);
|
|
26
|
+
const integration = resolveIntegration(flags.integration, this.readStore().filesIntegrationId);
|
|
27
|
+
if (!integration) {
|
|
28
|
+
this.error('No files integration ID. Pass --integration or run `norbix config set filesIntegrationId <id>`.');
|
|
29
|
+
}
|
|
30
|
+
const data = await readFile(args.file);
|
|
31
|
+
const fileName = basename(args.file);
|
|
32
|
+
const remotePath = args.remote ?? fileName;
|
|
33
|
+
const contentType = flags['content-type'] ?? guessContentType(fileName);
|
|
34
|
+
// 1. Ask the backend for a signed upload URL.
|
|
35
|
+
const { url } = await client.api.files.requestUploadUrl({
|
|
36
|
+
filesIntegrationId: integration,
|
|
37
|
+
path: remotePath,
|
|
38
|
+
contentType,
|
|
39
|
+
});
|
|
40
|
+
if (!url)
|
|
41
|
+
this.error('Backend did not return an upload URL.');
|
|
42
|
+
// 2. PUT the bytes straight to storage.
|
|
43
|
+
const put = await fetch(url, {
|
|
44
|
+
method: 'PUT',
|
|
45
|
+
body: new Uint8Array(data),
|
|
46
|
+
headers: { 'Content-Type': contentType },
|
|
47
|
+
});
|
|
48
|
+
if (!put.ok)
|
|
49
|
+
this.error(`Upload failed: HTTP ${put.status} ${put.statusText}`);
|
|
50
|
+
// 3. Commit so the file becomes visible.
|
|
51
|
+
await client.api.files.commitUpload({
|
|
52
|
+
filesIntegrationId: integration,
|
|
53
|
+
path: remotePath,
|
|
54
|
+
contentType,
|
|
55
|
+
sizeBytes: data.length,
|
|
56
|
+
fileName,
|
|
57
|
+
});
|
|
58
|
+
const result = { path: remotePath, sizeBytes: data.length, contentType };
|
|
59
|
+
this.print(`Uploaded ${args.file} → ${remotePath} (${data.length} bytes).`);
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Args } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../base.js';
|
|
3
|
+
const MODULES = {
|
|
4
|
+
code: (c) => c.hub.code.getCodeIntegrations({}),
|
|
5
|
+
database: (c) => c.hub.database.getDatabaseIntegrations({}),
|
|
6
|
+
email: (c) => c.hub.notifications.getEmailIntegrations({}),
|
|
7
|
+
files: (c) => c.hub.files.getFilesIntegrations({}),
|
|
8
|
+
logs: (c) => c.hub.logs.getLoggingIntegrations({}),
|
|
9
|
+
membership: (c) => c.hub.membership.getMembershipIntegrations({}),
|
|
10
|
+
payments: (c) => c.hub.payments.getPaymentsIntegrations({}),
|
|
11
|
+
push: (c) => c.hub.notifications.getPushIntegrations({}),
|
|
12
|
+
sms: (c) => c.hub.notifications.getSmsIntegrations({}),
|
|
13
|
+
};
|
|
14
|
+
export default class Integrations extends BaseCommand {
|
|
15
|
+
static description = 'List the integrations of one module';
|
|
16
|
+
static examples = [
|
|
17
|
+
'<%= config.bin %> integrations database',
|
|
18
|
+
'<%= config.bin %> integrations email',
|
|
19
|
+
];
|
|
20
|
+
static args = {
|
|
21
|
+
module: Args.string({
|
|
22
|
+
required: true,
|
|
23
|
+
description: `One of: ${Object.keys(MODULES).sort().join(', ')}`,
|
|
24
|
+
options: Object.keys(MODULES).sort(),
|
|
25
|
+
}),
|
|
26
|
+
};
|
|
27
|
+
async run() {
|
|
28
|
+
const { args, flags } = await this.parse(Integrations);
|
|
29
|
+
const client = this.client(flags);
|
|
30
|
+
const res = await MODULES[args.module](client);
|
|
31
|
+
this.print(res);
|
|
32
|
+
return res;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { input, password as passwordPrompt } from '@inquirer/prompts';
|
|
2
|
+
import { Norbix } from '@norbix.ai/ts';
|
|
3
|
+
import { Flags } from '@oclif/core';
|
|
4
|
+
import { BaseCommand } from '../base.js';
|
|
5
|
+
import { writeStore } from '../lib/store.js';
|
|
6
|
+
export default class Login extends BaseCommand {
|
|
7
|
+
static description = `Log in to Norbix and store credentials on this machine.
|
|
8
|
+
|
|
9
|
+
Two ways to authenticate:
|
|
10
|
+
1. User login — prompts for user name and password, stores a bearer token.
|
|
11
|
+
2. API key — pass --api-key to store a long-lived key instead.`;
|
|
12
|
+
static examples = [
|
|
13
|
+
'<%= config.bin %> login',
|
|
14
|
+
'<%= config.bin %> login --user alice@example.com --project 5f1a...',
|
|
15
|
+
'<%= config.bin %> login --api-key nbk_live_... --project 5f1a...',
|
|
16
|
+
];
|
|
17
|
+
static flags = {
|
|
18
|
+
user: Flags.string({ char: 'u', description: 'User name (email)' }),
|
|
19
|
+
password: Flags.string({
|
|
20
|
+
char: 'p',
|
|
21
|
+
description: 'Password (prompted securely if omitted)',
|
|
22
|
+
}),
|
|
23
|
+
};
|
|
24
|
+
async run() {
|
|
25
|
+
const { flags } = await this.parse(Login);
|
|
26
|
+
const stored = this.readStore();
|
|
27
|
+
const projectId = flags.project ??
|
|
28
|
+
stored.projectId ??
|
|
29
|
+
(await input({ message: 'Project ID:', required: true }));
|
|
30
|
+
const region = flags.region ?? stored.region;
|
|
31
|
+
// Mode 1: API key.
|
|
32
|
+
if (flags['api-key']) {
|
|
33
|
+
writeStore(this.config.configDir, {
|
|
34
|
+
...stored,
|
|
35
|
+
projectId,
|
|
36
|
+
region,
|
|
37
|
+
apiKey: flags['api-key'],
|
|
38
|
+
bearerToken: undefined,
|
|
39
|
+
refreshToken: undefined,
|
|
40
|
+
userId: undefined,
|
|
41
|
+
userName: undefined,
|
|
42
|
+
});
|
|
43
|
+
this.print(`API key saved for project ${projectId}. Run \`norbix whoami\` to verify.`);
|
|
44
|
+
return { method: 'apiKey', projectId };
|
|
45
|
+
}
|
|
46
|
+
// Mode 2: user + password.
|
|
47
|
+
const userName = flags.user ?? (await input({ message: 'User name (email):', required: true }));
|
|
48
|
+
const pwd = flags.password ?? (await passwordPrompt({ message: 'Password:', mask: '*' }));
|
|
49
|
+
const client = new Norbix({ projectId, region, env: flags.env ?? stored.env, baseUrl: { api: stored.apiUrl, hub: stored.hubUrl } }, { envSource: {} });
|
|
50
|
+
const res = await client.login({ userName, password: pwd });
|
|
51
|
+
if (!res.bearerToken)
|
|
52
|
+
this.error('Login succeeded but no token was returned.');
|
|
53
|
+
writeStore(this.config.configDir, {
|
|
54
|
+
...stored,
|
|
55
|
+
projectId,
|
|
56
|
+
region,
|
|
57
|
+
bearerToken: res.bearerToken,
|
|
58
|
+
refreshToken: res.refreshToken,
|
|
59
|
+
userId: res.userId,
|
|
60
|
+
userName: res.userName ?? userName,
|
|
61
|
+
});
|
|
62
|
+
this.print(`Logged in as ${res.displayName ?? res.userName ?? userName} (project ${projectId}).`);
|
|
63
|
+
return { method: 'credentials', projectId, userId: res.userId, userName: res.userName ?? userName };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../base.js';
|
|
3
|
+
import { writeStore } from '../lib/store.js';
|
|
4
|
+
export default class Logout extends BaseCommand {
|
|
5
|
+
static description = 'Remove stored credentials from this machine';
|
|
6
|
+
static examples = ['<%= config.bin %> logout', '<%= config.bin %> logout --all'];
|
|
7
|
+
static flags = {
|
|
8
|
+
all: Flags.boolean({
|
|
9
|
+
description: 'Also remove the stored API key (default: only the login token)',
|
|
10
|
+
default: false,
|
|
11
|
+
}),
|
|
12
|
+
};
|
|
13
|
+
async run() {
|
|
14
|
+
const { flags } = await this.parse(Logout);
|
|
15
|
+
const stored = this.readStore();
|
|
16
|
+
writeStore(this.config.configDir, {
|
|
17
|
+
...stored,
|
|
18
|
+
bearerToken: undefined,
|
|
19
|
+
refreshToken: undefined,
|
|
20
|
+
userId: undefined,
|
|
21
|
+
userName: undefined,
|
|
22
|
+
...(flags.all ? { apiKey: undefined } : {}),
|
|
23
|
+
});
|
|
24
|
+
this.print(flags.all ? 'Logged out. API key removed too.' : 'Logged out.');
|
|
25
|
+
return { loggedOut: true, removedApiKey: flags.all };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../base.js';
|
|
3
|
+
export default class LogsList extends BaseCommand {
|
|
4
|
+
static description = 'Read project logs, newest first';
|
|
5
|
+
static examples = [
|
|
6
|
+
'<%= config.bin %> logs list',
|
|
7
|
+
'<%= config.bin %> logs list --level Error --module Database',
|
|
8
|
+
'<%= config.bin %> logs list --search "timeout" --page-size 100 --json',
|
|
9
|
+
];
|
|
10
|
+
static flags = {
|
|
11
|
+
level: Flags.string({ description: 'Severity: Information, Warning or Error' }),
|
|
12
|
+
module: Flags.string({ description: 'Module: Database, Email, Membership, ...' }),
|
|
13
|
+
search: Flags.string({ description: 'Free-text search over title and message' }),
|
|
14
|
+
'event-code': Flags.string({ description: 'Exact event code (e.g. db:record:insert)' }),
|
|
15
|
+
correlation: Flags.string({ description: 'Correlation ID filter' }),
|
|
16
|
+
from: Flags.string({ description: 'From timestamp (UTC, ISO 8601)' }),
|
|
17
|
+
to: Flags.string({ description: 'To timestamp (UTC, ISO 8601)' }),
|
|
18
|
+
'page-size': Flags.integer({ description: 'Records per page', default: 50 }),
|
|
19
|
+
after: Flags.string({ description: 'Cursor: fetch the page after this item' }),
|
|
20
|
+
};
|
|
21
|
+
async run() {
|
|
22
|
+
const { flags } = await this.parse(LogsList);
|
|
23
|
+
const client = this.client(flags);
|
|
24
|
+
const res = await client.hub.logs.getLogs({
|
|
25
|
+
level: flags.level,
|
|
26
|
+
module: flags.module,
|
|
27
|
+
search: flags.search,
|
|
28
|
+
eventCode: flags['event-code'],
|
|
29
|
+
logCorrelationId: flags.correlation,
|
|
30
|
+
fromUtc: flags.from,
|
|
31
|
+
toUtc: flags.to,
|
|
32
|
+
pageSize: flags['page-size'],
|
|
33
|
+
startingAfter: flags.after,
|
|
34
|
+
});
|
|
35
|
+
this.print(res);
|
|
36
|
+
return res;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base.js';
|
|
2
|
+
export default class LogsSettings extends BaseCommand {
|
|
3
|
+
static description = 'Show project log settings';
|
|
4
|
+
static examples = ['<%= config.bin %> logs settings'];
|
|
5
|
+
async run() {
|
|
6
|
+
const { flags } = await this.parse(LogsSettings);
|
|
7
|
+
const client = this.client(flags);
|
|
8
|
+
const res = await client.hub.logs.getLogSettings({});
|
|
9
|
+
this.print(res);
|
|
10
|
+
return res;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Args } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../base.js';
|
|
3
|
+
export default class LogsTrail extends BaseCommand {
|
|
4
|
+
static description = 'Show the full request trail for one correlation ID';
|
|
5
|
+
static examples = ['<%= config.bin %> logs trail 8f2c1b...'];
|
|
6
|
+
static args = {
|
|
7
|
+
correlationId: Args.string({ required: true, description: 'Correlation ID' }),
|
|
8
|
+
};
|
|
9
|
+
async run() {
|
|
10
|
+
const { args, flags } = await this.parse(LogsTrail);
|
|
11
|
+
const client = this.client(flags);
|
|
12
|
+
const res = await client.hub.logs.getLogsByCorrelationId({
|
|
13
|
+
targetCorrelationId: args.correlationId,
|
|
14
|
+
});
|
|
15
|
+
this.print(res);
|
|
16
|
+
return res;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { confirm } from '@inquirer/prompts';
|
|
2
|
+
import { Args, Flags } from '@oclif/core';
|
|
3
|
+
import { BaseCommand } from '../base.js';
|
|
4
|
+
const MODULES = {
|
|
5
|
+
code: { enable: (c) => c.hub.code.enableCode({}), disable: (c) => c.hub.code.disableCode({}) },
|
|
6
|
+
database: { enable: (c) => c.hub.database.enableDatabase({}), disable: (c) => c.hub.database.disableDatabase({}) },
|
|
7
|
+
email: { enable: (c) => c.hub.notifications.enableEmail({}), disable: (c) => c.hub.notifications.disableEmail({}) },
|
|
8
|
+
files: { enable: (c) => c.hub.files.enableFiles({}), disable: (c) => c.hub.files.disableFiles({}) },
|
|
9
|
+
logs: { enable: (c) => c.hub.logs.enableLogging({}), disable: (c) => c.hub.logs.disableLogging({}) },
|
|
10
|
+
membership: { enable: (c) => c.hub.membership.enableMembership({}), disable: (c) => c.hub.membership.disableMembership({}) },
|
|
11
|
+
payments: { enable: (c) => c.hub.payments.enablePayments({}), disable: (c) => c.hub.payments.disablePayments({}) },
|
|
12
|
+
push: { enable: (c) => c.hub.notifications.enablePush({}), disable: (c) => c.hub.notifications.disablePush({}) },
|
|
13
|
+
scheduler: { enable: (c) => c.hub.scheduler.enableScheduler({}), disable: (c) => c.hub.scheduler.disableScheduler({}) },
|
|
14
|
+
sms: { enable: (c) => c.hub.notifications.enableSms({}), disable: (c) => c.hub.notifications.disableSms({}) },
|
|
15
|
+
};
|
|
16
|
+
export default class Module extends BaseCommand {
|
|
17
|
+
static description = 'Enable or disable a whole project module';
|
|
18
|
+
static examples = [
|
|
19
|
+
'<%= config.bin %> module enable database',
|
|
20
|
+
'<%= config.bin %> module disable sms --yes',
|
|
21
|
+
];
|
|
22
|
+
static args = {
|
|
23
|
+
action: Args.string({ required: true, description: 'enable or disable', options: ['enable', 'disable'] }),
|
|
24
|
+
name: Args.string({
|
|
25
|
+
required: true,
|
|
26
|
+
description: `One of: ${Object.keys(MODULES).sort().join(', ')}`,
|
|
27
|
+
options: Object.keys(MODULES).sort(),
|
|
28
|
+
}),
|
|
29
|
+
};
|
|
30
|
+
static flags = {
|
|
31
|
+
yes: Flags.boolean({ char: 'y', description: 'Skip the confirmation prompt (disable only)', default: false }),
|
|
32
|
+
};
|
|
33
|
+
async run() {
|
|
34
|
+
const { args, flags } = await this.parse(Module);
|
|
35
|
+
const client = this.client(flags);
|
|
36
|
+
if (args.action === 'disable' && !flags.yes && process.stdout.isTTY) {
|
|
37
|
+
const ok = await confirm({
|
|
38
|
+
message: `Disable the "${args.name}" module for this project?`,
|
|
39
|
+
default: false,
|
|
40
|
+
});
|
|
41
|
+
if (!ok)
|
|
42
|
+
return this.print('Cancelled.');
|
|
43
|
+
}
|
|
44
|
+
const res = await MODULES[args.name][args.action](client);
|
|
45
|
+
this.print(`Module ${args.name} ${args.action}d.`);
|
|
46
|
+
return res;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Args } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../base.js';
|
|
3
|
+
export default class PaymentsDisable extends BaseCommand {
|
|
4
|
+
static description = 'Disable a payment trigger';
|
|
5
|
+
static examples = ['<%= config.bin %> payments disable 66b2f0a1...'];
|
|
6
|
+
static args = {
|
|
7
|
+
id: Args.string({ required: true, description: 'Trigger ID' }),
|
|
8
|
+
};
|
|
9
|
+
async run() {
|
|
10
|
+
const { args, flags } = await this.parse(PaymentsDisable);
|
|
11
|
+
const client = this.client(flags);
|
|
12
|
+
const res = await client.hub.payments.disablePaymentsTrigger({ triggerId: args.id });
|
|
13
|
+
this.print(`Trigger ${args.id} disabled.`);
|
|
14
|
+
return res;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Args } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../base.js';
|
|
3
|
+
export default class PaymentsEnable extends BaseCommand {
|
|
4
|
+
static description = 'Enable a payment trigger';
|
|
5
|
+
static examples = ['<%= config.bin %> payments enable 66b2f0a1...'];
|
|
6
|
+
static args = {
|
|
7
|
+
id: Args.string({ required: true, description: 'Trigger ID' }),
|
|
8
|
+
};
|
|
9
|
+
async run() {
|
|
10
|
+
const { args, flags } = await this.parse(PaymentsEnable);
|
|
11
|
+
const client = this.client(flags);
|
|
12
|
+
const res = await client.hub.payments.enablePaymentsTrigger({ triggerId: args.id });
|
|
13
|
+
this.print(`Trigger ${args.id} enabled.`);
|
|
14
|
+
return res;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base.js';
|
|
2
|
+
export default class PaymentsIntegrations extends BaseCommand {
|
|
3
|
+
static description = 'List payment integrations';
|
|
4
|
+
static examples = ['<%= config.bin %> payments integrations'];
|
|
5
|
+
async run() {
|
|
6
|
+
const { flags } = await this.parse(PaymentsIntegrations);
|
|
7
|
+
const client = this.client(flags);
|
|
8
|
+
const res = await client.hub.payments.getPaymentsIntegrations({});
|
|
9
|
+
this.print(res);
|
|
10
|
+
return res;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Args } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../base.js';
|
|
3
|
+
export default class PaymentsTrigger extends BaseCommand {
|
|
4
|
+
static description = 'Show one payment trigger';
|
|
5
|
+
static examples = ['<%= config.bin %> payments trigger 66b2f0a1...'];
|
|
6
|
+
static args = {
|
|
7
|
+
id: Args.string({ required: true, description: 'Trigger ID' }),
|
|
8
|
+
};
|
|
9
|
+
async run() {
|
|
10
|
+
const { args, flags } = await this.parse(PaymentsTrigger);
|
|
11
|
+
const client = this.client(flags);
|
|
12
|
+
const res = await client.hub.payments.getPaymentsTrigger({ id: args.id });
|
|
13
|
+
this.print(res);
|
|
14
|
+
return res;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base.js';
|
|
2
|
+
export default class PaymentsTriggers extends BaseCommand {
|
|
3
|
+
static description = 'List payment triggers';
|
|
4
|
+
static examples = ['<%= config.bin %> payments triggers'];
|
|
5
|
+
async run() {
|
|
6
|
+
const { flags } = await this.parse(PaymentsTriggers);
|
|
7
|
+
const client = this.client(flags);
|
|
8
|
+
const res = await client.hub.payments.getPaymentsTriggers({});
|
|
9
|
+
this.print(res);
|
|
10
|
+
return res;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Args } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../base.js';
|
|
3
|
+
export default class PushArchive extends BaseCommand {
|
|
4
|
+
static description = 'Archive a push template';
|
|
5
|
+
static examples = ['<%= config.bin %> push archive 66b2f0a1...'];
|
|
6
|
+
static args = {
|
|
7
|
+
id: Args.string({ required: true, description: 'Template ID' }),
|
|
8
|
+
};
|
|
9
|
+
async run() {
|
|
10
|
+
const { args, flags } = await this.parse(PushArchive);
|
|
11
|
+
const client = this.client(flags);
|
|
12
|
+
const res = await client.hub.notifications.archivePushTemplate({ id: args.id });
|
|
13
|
+
this.print(`Template ${args.id} archived.`);
|
|
14
|
+
return res;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../base.js';
|
|
3
|
+
export default class PushCampaign extends BaseCommand {
|
|
4
|
+
static description = 'Show one push campaign (or its statistics with --stats)';
|
|
5
|
+
static examples = ['<%= config.bin %> push campaign 66b2f0a1... --stats'];
|
|
6
|
+
static args = {
|
|
7
|
+
id: Args.string({ required: true, description: 'Campaign ID' }),
|
|
8
|
+
};
|
|
9
|
+
static flags = {
|
|
10
|
+
stats: Flags.boolean({ description: 'Show delivery statistics instead of the campaign itself', default: false }),
|
|
11
|
+
};
|
|
12
|
+
async run() {
|
|
13
|
+
const { args, flags } = await this.parse(PushCampaign);
|
|
14
|
+
const client = this.client(flags);
|
|
15
|
+
const res = flags.stats
|
|
16
|
+
? await client.hub.notifications.getPushCampaignStatistics({ id: args.id })
|
|
17
|
+
: await client.hub.notifications.getPushCampaign({ id: args.id });
|
|
18
|
+
this.print(res);
|
|
19
|
+
return res;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../base.js';
|
|
3
|
+
export default class PushCampaigns extends BaseCommand {
|
|
4
|
+
static description = 'List push campaigns';
|
|
5
|
+
static examples = ['<%= config.bin %> push campaigns'];
|
|
6
|
+
static flags = {
|
|
7
|
+
'page-size': Flags.integer({ description: 'Records per page' }),
|
|
8
|
+
after: Flags.string({ description: 'Cursor: fetch the page after this item' }),
|
|
9
|
+
};
|
|
10
|
+
async run() {
|
|
11
|
+
const { flags } = await this.parse(PushCampaigns);
|
|
12
|
+
const client = this.client(flags);
|
|
13
|
+
const res = await client.hub.notifications.getPushCampaigns({
|
|
14
|
+
pageSize: flags['page-size'],
|
|
15
|
+
startingAfter: flags.after,
|
|
16
|
+
});
|
|
17
|
+
this.print(res);
|
|
18
|
+
return res;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Args } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../base.js';
|
|
3
|
+
export default class PushClone extends BaseCommand {
|
|
4
|
+
static description = 'Clone a push template';
|
|
5
|
+
static examples = ['<%= config.bin %> push clone 66b2f0a1...'];
|
|
6
|
+
static args = {
|
|
7
|
+
id: Args.string({ required: true, description: 'Template ID' }),
|
|
8
|
+
};
|
|
9
|
+
async run() {
|
|
10
|
+
const { args, flags } = await this.parse(PushClone);
|
|
11
|
+
const client = this.client(flags);
|
|
12
|
+
const res = await client.hub.notifications.clonePushTemplate({ id: args.id });
|
|
13
|
+
this.print(`Template ${args.id} cloned.`);
|
|
14
|
+
return res;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { confirm } from '@inquirer/prompts';
|
|
2
|
+
import { Args, Flags } from '@oclif/core';
|
|
3
|
+
import { BaseCommand } from '../../base.js';
|
|
4
|
+
export default class PushDelete extends BaseCommand {
|
|
5
|
+
static description = 'Delete a push template';
|
|
6
|
+
static examples = ['<%= config.bin %> push delete 66b2f0a1... --yes'];
|
|
7
|
+
static args = {
|
|
8
|
+
id: Args.string({ required: true, description: 'Template ID' }),
|
|
9
|
+
};
|
|
10
|
+
static flags = {
|
|
11
|
+
yes: Flags.boolean({ char: 'y', description: 'Skip the confirmation prompt', default: false }),
|
|
12
|
+
};
|
|
13
|
+
async run() {
|
|
14
|
+
const { args, flags } = await this.parse(PushDelete);
|
|
15
|
+
const client = this.client(flags);
|
|
16
|
+
if (!flags.yes && process.stdout.isTTY) {
|
|
17
|
+
const ok = await confirm({ message: `Delete push template ${args.id}?`, default: false });
|
|
18
|
+
if (!ok)
|
|
19
|
+
return this.print('Cancelled.');
|
|
20
|
+
}
|
|
21
|
+
const res = await client.hub.notifications.deletePushTemplate({ id: args.id });
|
|
22
|
+
this.print(`Template ${args.id} deleted.`);
|
|
23
|
+
return res;
|
|
24
|
+
}
|
|
25
|
+
}
|