@owox/ctl 0.26.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/README.md +46 -0
- package/bin/run.js +5 -0
- package/dist/base-command.d.ts +27 -0
- package/dist/base-command.js +92 -0
- package/dist/commands/auth/login.d.ts +41 -0
- package/dist/commands/auth/login.js +121 -0
- package/dist/commands/auth/logout.d.ts +18 -0
- package/dist/commands/auth/logout.js +30 -0
- package/dist/commands/auth/status.d.ts +24 -0
- package/dist/commands/auth/status.js +45 -0
- package/dist/commands/data-marts/list.d.ts +12 -0
- package/dist/commands/data-marts/list.js +25 -0
- package/dist/commands/destinations/list.d.ts +12 -0
- package/dist/commands/destinations/list.js +25 -0
- package/dist/commands/storages/list.d.ts +12 -0
- package/dist/commands/storages/list.js +25 -0
- package/dist/config-store.d.ts +24 -0
- package/dist/config-store.js +107 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/output.d.ts +25 -0
- package/dist/output.js +58 -0
- package/oclif.manifest.json +324 -0
- package/package.json +75 -0
package/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# @owox/ctl
|
|
2
|
+
|
|
3
|
+
OWOX Data Marts Control CLI.
|
|
4
|
+
|
|
5
|
+
`owox` runs and manages a local or self-managed OWOX Data Marts runtime.
|
|
6
|
+
`owox-ctl` controls an existing OWOX Data Marts instance through the HTTP API.
|
|
7
|
+
|
|
8
|
+
The full user documentation lives in [docs/api/owox-ctl.md](../../docs/api/owox-ctl.md).
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install -g @owox/ctl
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Authentication
|
|
17
|
+
|
|
18
|
+
For human use, prefer interactive login:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
owox-ctl auth login
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
For CI and agents, use environment variables. These override stored login config
|
|
25
|
+
and do not write secrets to disk:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
OWOX_API_ORIGIN=https://app.owox.com \
|
|
29
|
+
OWOX_API_KEY_ID=pmk_xxx \
|
|
30
|
+
OWOX_API_KEY_SECRET=xxx \
|
|
31
|
+
owox-ctl data-marts list --format json
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
You can also load these variables from an environment file:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
owox-ctl data-marts list --env-file .env --format json
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Access tokens are short-lived and kept in memory only for the current process.
|
|
41
|
+
They are never written to the local config file.
|
|
42
|
+
|
|
43
|
+
## Compatibility
|
|
44
|
+
|
|
45
|
+
CLI same version as server: supported.
|
|
46
|
+
CLI different version from server: best effort.
|
package/bin/run.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import { type EnvSetupConfig, type EnvSetupResult } from '@owox/internal-helpers';
|
|
3
|
+
import { OWOXApiClient, type OWOXApiClientOptions } from '@owox/api-client';
|
|
4
|
+
import { type OutputFormat, type TableColumn } from './output.js';
|
|
5
|
+
type BaseFlags = {
|
|
6
|
+
format?: string;
|
|
7
|
+
'no-color'?: boolean;
|
|
8
|
+
'env-file'?: string;
|
|
9
|
+
};
|
|
10
|
+
type SetupEnvironment = (config?: EnvSetupConfig) => EnvSetupResult;
|
|
11
|
+
export declare function setupEnvironmentFromFlags(flags: Pick<BaseFlags, 'env-file'>, setupEnvironment?: SetupEnvironment): void;
|
|
12
|
+
export declare abstract class BaseCommand extends Command {
|
|
13
|
+
static baseFlags: {
|
|
14
|
+
'env-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
'no-color': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
17
|
+
};
|
|
18
|
+
protected createClient(config: OWOXApiClientOptions): OWOXApiClient;
|
|
19
|
+
protected loadEnvironment(flags: Pick<BaseFlags, 'env-file'>): void;
|
|
20
|
+
protected getAuthenticatedClient(): Promise<OWOXApiClient>;
|
|
21
|
+
protected writeRows<T extends Record<string, unknown>>(rows: T[], columns: TableColumn<T>[], flags: BaseFlags): void;
|
|
22
|
+
protected handleCliError(error: unknown, flags: BaseFlags): never;
|
|
23
|
+
protected colorEnabled(flags: BaseFlags): boolean;
|
|
24
|
+
private normalizeError;
|
|
25
|
+
protected outputFormat(flags: BaseFlags): OutputFormat;
|
|
26
|
+
}
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Command, Flags } from '@oclif/core';
|
|
2
|
+
import { EnvManager } from '@owox/internal-helpers';
|
|
3
|
+
import { OWOXApiClient, OWOXApiError, OWOXAuthError, OWOXConfigError, } from '@owox/api-client';
|
|
4
|
+
import { ConfigStore, resolveAuthConfig } from './config-store.js';
|
|
5
|
+
import { renderJson, renderTable, shouldUseColor, } from './output.js';
|
|
6
|
+
export function setupEnvironmentFromFlags(flags, setupEnvironment = EnvManager.setupEnvironment.bind(EnvManager)) {
|
|
7
|
+
const envFileValue = flags['env-file'];
|
|
8
|
+
const envFile = typeof envFileValue === 'string' ? envFileValue : '';
|
|
9
|
+
const hasExplicitEnvFile = envFile.trim().length > 0;
|
|
10
|
+
const result = setupEnvironment({ envFile });
|
|
11
|
+
if (hasExplicitEnvFile && !result.success) {
|
|
12
|
+
throw new OWOXConfigError(`Failed to load environment file: ${envFile}`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export class BaseCommand extends Command {
|
|
16
|
+
static baseFlags = {
|
|
17
|
+
'env-file': Flags.string({
|
|
18
|
+
char: 'e',
|
|
19
|
+
description: 'Path to environment file to load variables from',
|
|
20
|
+
helpValue: '/path/to/.env',
|
|
21
|
+
}),
|
|
22
|
+
format: Flags.string({
|
|
23
|
+
default: 'table',
|
|
24
|
+
description: 'Output format',
|
|
25
|
+
options: ['table', 'json'],
|
|
26
|
+
}),
|
|
27
|
+
'no-color': Flags.boolean({
|
|
28
|
+
description: 'Disable color output',
|
|
29
|
+
}),
|
|
30
|
+
};
|
|
31
|
+
createClient(config) {
|
|
32
|
+
return new OWOXApiClient(config);
|
|
33
|
+
}
|
|
34
|
+
loadEnvironment(flags) {
|
|
35
|
+
setupEnvironmentFromFlags(flags);
|
|
36
|
+
}
|
|
37
|
+
async getAuthenticatedClient() {
|
|
38
|
+
const resolved = await resolveAuthConfig({ store: new ConfigStore() });
|
|
39
|
+
if (!resolved) {
|
|
40
|
+
throw new OWOXConfigError('Not authenticated. Run owox-ctl auth login or set OWOX_API_ORIGIN, OWOX_API_KEY_ID, and OWOX_API_KEY_SECRET.');
|
|
41
|
+
}
|
|
42
|
+
return this.createClient(resolved.config);
|
|
43
|
+
}
|
|
44
|
+
writeRows(rows, columns, flags) {
|
|
45
|
+
if (this.outputFormat(flags) === 'json') {
|
|
46
|
+
this.log(renderJson(rows));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
this.log(renderTable(rows, columns));
|
|
50
|
+
}
|
|
51
|
+
handleCliError(error, flags) {
|
|
52
|
+
const normalized = this.normalizeError(error);
|
|
53
|
+
if (this.outputFormat(flags) === 'json') {
|
|
54
|
+
process.stderr.write(`${renderJson({ error: normalized })}\n`);
|
|
55
|
+
this.exit(1);
|
|
56
|
+
}
|
|
57
|
+
this.error(normalized.message, {
|
|
58
|
+
code: normalized.code,
|
|
59
|
+
exit: 1,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
colorEnabled(flags) {
|
|
63
|
+
return shouldUseColor({
|
|
64
|
+
format: this.outputFormat(flags),
|
|
65
|
+
noColor: flags['no-color'],
|
|
66
|
+
stream: process.stdout,
|
|
67
|
+
env: process.env,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
normalizeError(error) {
|
|
71
|
+
if (error instanceof OWOXApiError || error instanceof OWOXAuthError) {
|
|
72
|
+
return {
|
|
73
|
+
message: error.message,
|
|
74
|
+
status: error.status,
|
|
75
|
+
code: error.code,
|
|
76
|
+
name: error.name,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
if (error instanceof OWOXConfigError || error instanceof Error) {
|
|
80
|
+
return {
|
|
81
|
+
message: error.message,
|
|
82
|
+
name: error.name,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
message: String(error),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
outputFormat(flags) {
|
|
90
|
+
return flags.format === 'json' ? 'json' : 'table';
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type OWOXApiClientOptions } from '@owox/api-client';
|
|
2
|
+
import { BaseCommand } from '../../base-command.js';
|
|
3
|
+
import { ConfigStore, type AuthConfig } from '../../config-store.js';
|
|
4
|
+
type Authenticator = {
|
|
5
|
+
authenticate(): Promise<void>;
|
|
6
|
+
};
|
|
7
|
+
type LoginDeps = {
|
|
8
|
+
store: ConfigStore;
|
|
9
|
+
createClient: (config: OWOXApiClientOptions) => Authenticator;
|
|
10
|
+
};
|
|
11
|
+
type LoginInput = {
|
|
12
|
+
apiOrigin: string;
|
|
13
|
+
apiKeyId: string;
|
|
14
|
+
apiKeySecret: string;
|
|
15
|
+
};
|
|
16
|
+
type LoginFlags = {
|
|
17
|
+
'api-origin'?: string;
|
|
18
|
+
'api-key-id'?: string;
|
|
19
|
+
'api-key-secret'?: string;
|
|
20
|
+
};
|
|
21
|
+
type LoginPrompts = {
|
|
22
|
+
promptText: (message: string) => Promise<string>;
|
|
23
|
+
promptSecret: (message: string) => Promise<string>;
|
|
24
|
+
};
|
|
25
|
+
export declare function performLogin(input: LoginInput, deps?: LoginDeps): Promise<AuthConfig>;
|
|
26
|
+
export declare function promptSecret(message: string, input?: NodeJS.ReadStream, output?: NodeJS.WriteStream): Promise<string>;
|
|
27
|
+
export declare function resolveLoginInput(flags: LoginFlags, env?: NodeJS.ProcessEnv, prompts?: LoginPrompts): Promise<LoginInput>;
|
|
28
|
+
export default class AuthLogin extends BaseCommand {
|
|
29
|
+
static description: string;
|
|
30
|
+
static examples: string[];
|
|
31
|
+
static flags: {
|
|
32
|
+
'api-origin': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
33
|
+
'api-key-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
34
|
+
'api-key-secret': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
35
|
+
'env-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
36
|
+
format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
37
|
+
'no-color': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
38
|
+
};
|
|
39
|
+
run(): Promise<void>;
|
|
40
|
+
}
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { OWOXApiClient } from '@owox/api-client';
|
|
3
|
+
import { createInterface } from 'node:readline/promises';
|
|
4
|
+
import { BaseCommand } from '../../base-command.js';
|
|
5
|
+
import { ConfigStore, maskApiKeyId } from '../../config-store.js';
|
|
6
|
+
import { colors, renderJson } from '../../output.js';
|
|
7
|
+
const defaultDeps = (store = new ConfigStore()) => ({
|
|
8
|
+
store,
|
|
9
|
+
createClient: config => new OWOXApiClient(config),
|
|
10
|
+
});
|
|
11
|
+
export async function performLogin(input, deps = defaultDeps()) {
|
|
12
|
+
const config = {
|
|
13
|
+
apiOrigin: input.apiOrigin.trim(),
|
|
14
|
+
apiKeyId: input.apiKeyId.trim(),
|
|
15
|
+
apiKeySecret: input.apiKeySecret,
|
|
16
|
+
};
|
|
17
|
+
await deps.createClient(config).authenticate();
|
|
18
|
+
await deps.store.save(config);
|
|
19
|
+
return config;
|
|
20
|
+
}
|
|
21
|
+
async function promptText(message, input = process.stdin, output = process.stdout) {
|
|
22
|
+
const readline = createInterface({
|
|
23
|
+
input,
|
|
24
|
+
output,
|
|
25
|
+
});
|
|
26
|
+
try {
|
|
27
|
+
return await readline.question(message);
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
readline.close();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export async function promptSecret(message, input = process.stdin, output = process.stdout) {
|
|
34
|
+
if (!input.isTTY) {
|
|
35
|
+
return promptText(message, input, output);
|
|
36
|
+
}
|
|
37
|
+
output.write(message);
|
|
38
|
+
input.setRawMode(true);
|
|
39
|
+
input.resume();
|
|
40
|
+
return new Promise((resolve, reject) => {
|
|
41
|
+
let value = '';
|
|
42
|
+
const cleanup = () => {
|
|
43
|
+
input.setRawMode(false);
|
|
44
|
+
input.off('data', onData);
|
|
45
|
+
input.pause();
|
|
46
|
+
output.write('\n');
|
|
47
|
+
};
|
|
48
|
+
const onData = (chunk) => {
|
|
49
|
+
const text = chunk.toString('utf8');
|
|
50
|
+
if (text === '\u0003') {
|
|
51
|
+
cleanup();
|
|
52
|
+
reject(new Error('Prompt cancelled'));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (text === '\r' || text === '\n') {
|
|
56
|
+
cleanup();
|
|
57
|
+
resolve(value);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (text === '\u007F') {
|
|
61
|
+
value = value.slice(0, -1);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
value += text;
|
|
65
|
+
};
|
|
66
|
+
input.on('data', onData);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
export async function resolveLoginInput(flags, env = process.env, prompts = { promptText, promptSecret }) {
|
|
70
|
+
return {
|
|
71
|
+
apiOrigin: flags['api-origin'] ??
|
|
72
|
+
env.OWOX_API_ORIGIN ??
|
|
73
|
+
(await prompts.promptText('OWOX Data Marts API origin: ')),
|
|
74
|
+
apiKeyId: flags['api-key-id'] ?? env.OWOX_API_KEY_ID ?? (await prompts.promptText('API key ID: ')),
|
|
75
|
+
apiKeySecret: flags['api-key-secret'] ??
|
|
76
|
+
env.OWOX_API_KEY_SECRET ??
|
|
77
|
+
(await prompts.promptSecret('API key secret: ')),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export default class AuthLogin extends BaseCommand {
|
|
81
|
+
static description = 'Authenticate with OWOX Data Marts';
|
|
82
|
+
static examples = [
|
|
83
|
+
'<%= config.bin %> auth login',
|
|
84
|
+
'<%= config.bin %> auth login --api-origin https://app.owox.com --api-key-id pmk_xxx --api-key-secret xxx',
|
|
85
|
+
];
|
|
86
|
+
static flags = {
|
|
87
|
+
...BaseCommand.baseFlags,
|
|
88
|
+
'api-origin': Flags.string({
|
|
89
|
+
description: 'OWOX Data Marts API origin, for example https://app.owox.com',
|
|
90
|
+
}),
|
|
91
|
+
'api-key-id': Flags.string({
|
|
92
|
+
description: 'API key ID',
|
|
93
|
+
}),
|
|
94
|
+
'api-key-secret': Flags.string({
|
|
95
|
+
description: 'API key secret',
|
|
96
|
+
}),
|
|
97
|
+
};
|
|
98
|
+
async run() {
|
|
99
|
+
const { flags } = await this.parse(AuthLogin);
|
|
100
|
+
try {
|
|
101
|
+
this.loadEnvironment(flags);
|
|
102
|
+
const config = await performLogin(await resolveLoginInput(flags), {
|
|
103
|
+
store: new ConfigStore(),
|
|
104
|
+
createClient: config => this.createClient(config),
|
|
105
|
+
});
|
|
106
|
+
if (this.outputFormat(flags) === 'json') {
|
|
107
|
+
this.log(renderJson({
|
|
108
|
+
apiOrigin: config.apiOrigin,
|
|
109
|
+
apiKeyId: maskApiKeyId(config.apiKeyId),
|
|
110
|
+
authenticated: true,
|
|
111
|
+
}));
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const palette = colors({ enabled: this.colorEnabled(flags) });
|
|
115
|
+
this.log(palette.success('Authenticated with OWOX Data Marts'));
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
this.handleCliError(error, flags);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command.js';
|
|
2
|
+
import { ConfigStore } from '../../config-store.js';
|
|
3
|
+
type LogoutDeps = {
|
|
4
|
+
store: ConfigStore;
|
|
5
|
+
};
|
|
6
|
+
export declare function performLogout(deps?: LogoutDeps): Promise<{
|
|
7
|
+
removed: boolean;
|
|
8
|
+
}>;
|
|
9
|
+
export default class AuthLogout extends BaseCommand {
|
|
10
|
+
static description: string;
|
|
11
|
+
static flags: {
|
|
12
|
+
'env-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
'no-color': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
|
+
};
|
|
16
|
+
run(): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command.js';
|
|
2
|
+
import { ConfigStore } from '../../config-store.js';
|
|
3
|
+
import { colors, renderJson } from '../../output.js';
|
|
4
|
+
export async function performLogout(deps = { store: new ConfigStore() }) {
|
|
5
|
+
return { removed: await deps.store.remove() };
|
|
6
|
+
}
|
|
7
|
+
export default class AuthLogout extends BaseCommand {
|
|
8
|
+
static description = 'Remove stored OWOX Data Marts credentials';
|
|
9
|
+
static flags = {
|
|
10
|
+
...BaseCommand.baseFlags,
|
|
11
|
+
};
|
|
12
|
+
async run() {
|
|
13
|
+
const { flags } = await this.parse(AuthLogout);
|
|
14
|
+
try {
|
|
15
|
+
this.loadEnvironment(flags);
|
|
16
|
+
const result = await performLogout({ store: new ConfigStore() });
|
|
17
|
+
if (this.outputFormat(flags) === 'json') {
|
|
18
|
+
this.log(renderJson({ loggedOut: true, removed: result.removed }));
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const palette = colors({ enabled: this.colorEnabled(flags) });
|
|
22
|
+
this.log(result.removed
|
|
23
|
+
? palette.success('Stored credentials removed')
|
|
24
|
+
: palette.warning('No stored credentials found'));
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
this.handleCliError(error, flags);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type OWOXApiClientOptions } from '@owox/api-client';
|
|
2
|
+
import { BaseCommand } from '../../base-command.js';
|
|
3
|
+
import { type AuthConfig } from '../../config-store.js';
|
|
4
|
+
type AuthStatus = {
|
|
5
|
+
apiOrigin: string;
|
|
6
|
+
apiKeyId: string;
|
|
7
|
+
authenticated: boolean;
|
|
8
|
+
};
|
|
9
|
+
type AuthStatusDeps = {
|
|
10
|
+
createClient: (config: OWOXApiClientOptions) => {
|
|
11
|
+
authenticate(): Promise<void>;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
export declare function getAuthStatus(config: AuthConfig, deps?: AuthStatusDeps): Promise<AuthStatus>;
|
|
15
|
+
export default class AuthStatusCommand extends BaseCommand {
|
|
16
|
+
static description: string;
|
|
17
|
+
static flags: {
|
|
18
|
+
'env-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
|
+
format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
|
+
'no-color': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
21
|
+
};
|
|
22
|
+
run(): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { OWOXApiClient } from '@owox/api-client';
|
|
2
|
+
import { BaseCommand } from '../../base-command.js';
|
|
3
|
+
import { ConfigStore, maskApiKeyId, resolveAuthConfig, } from '../../config-store.js';
|
|
4
|
+
import { renderJson, renderKeyValues } from '../../output.js';
|
|
5
|
+
export async function getAuthStatus(config, deps = { createClient: clientConfig => new OWOXApiClient(clientConfig) }) {
|
|
6
|
+
await deps.createClient(config).authenticate();
|
|
7
|
+
return {
|
|
8
|
+
apiOrigin: config.apiOrigin,
|
|
9
|
+
apiKeyId: maskApiKeyId(config.apiKeyId),
|
|
10
|
+
authenticated: true,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export default class AuthStatusCommand extends BaseCommand {
|
|
14
|
+
static description = 'Show OWOX Data Marts authentication status';
|
|
15
|
+
static flags = {
|
|
16
|
+
...BaseCommand.baseFlags,
|
|
17
|
+
};
|
|
18
|
+
async run() {
|
|
19
|
+
const { flags } = await this.parse(AuthStatusCommand);
|
|
20
|
+
try {
|
|
21
|
+
this.loadEnvironment(flags);
|
|
22
|
+
const resolved = await resolveAuthConfig({ store: new ConfigStore() });
|
|
23
|
+
if (!resolved) {
|
|
24
|
+
const status = { authenticated: false };
|
|
25
|
+
this.log(flags.format === 'json' ? renderJson(status) : renderKeyValues({ Authenticated: 'no' }));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const status = await getAuthStatus(resolved.config, {
|
|
29
|
+
createClient: config => this.createClient(config),
|
|
30
|
+
});
|
|
31
|
+
if (flags.format === 'json') {
|
|
32
|
+
this.log(renderJson(status));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
this.log(renderKeyValues({
|
|
36
|
+
'API origin': status.apiOrigin,
|
|
37
|
+
'API key ID': status.apiKeyId,
|
|
38
|
+
Authenticated: status.authenticated ? 'yes' : 'no',
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
this.handleCliError(error, flags);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { OWOXApiClient, OWOXDataMart } from '@owox/api-client';
|
|
2
|
+
import { BaseCommand } from '../../base-command.js';
|
|
3
|
+
export declare function listDataMarts(client: Pick<OWOXApiClient, 'dataMarts'>): Promise<OWOXDataMart[]>;
|
|
4
|
+
export default class DataMartsList extends BaseCommand {
|
|
5
|
+
static description: string;
|
|
6
|
+
static flags: {
|
|
7
|
+
'env-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
+
format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
'no-color': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
};
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command.js';
|
|
2
|
+
export async function listDataMarts(client) {
|
|
3
|
+
return client.dataMarts.list();
|
|
4
|
+
}
|
|
5
|
+
export default class DataMartsList extends BaseCommand {
|
|
6
|
+
static description = 'List data marts';
|
|
7
|
+
static flags = {
|
|
8
|
+
...BaseCommand.baseFlags,
|
|
9
|
+
};
|
|
10
|
+
async run() {
|
|
11
|
+
const { flags } = await this.parse(DataMartsList);
|
|
12
|
+
try {
|
|
13
|
+
this.loadEnvironment(flags);
|
|
14
|
+
const rows = await listDataMarts(await this.getAuthenticatedClient());
|
|
15
|
+
this.writeRows(rows, [
|
|
16
|
+
{ key: 'id', label: 'ID' },
|
|
17
|
+
{ key: 'title', label: 'Title' },
|
|
18
|
+
{ key: 'status', label: 'Status' },
|
|
19
|
+
], flags);
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
this.handleCliError(error, flags);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { OWOXApiClient, OWOXDestination } from '@owox/api-client';
|
|
2
|
+
import { BaseCommand } from '../../base-command.js';
|
|
3
|
+
export declare function listDestinations(client: Pick<OWOXApiClient, 'destinations'>): Promise<OWOXDestination[]>;
|
|
4
|
+
export default class DestinationsList extends BaseCommand {
|
|
5
|
+
static description: string;
|
|
6
|
+
static flags: {
|
|
7
|
+
'env-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
+
format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
'no-color': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
};
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command.js';
|
|
2
|
+
export async function listDestinations(client) {
|
|
3
|
+
return client.destinations.list();
|
|
4
|
+
}
|
|
5
|
+
export default class DestinationsList extends BaseCommand {
|
|
6
|
+
static description = 'List destinations';
|
|
7
|
+
static flags = {
|
|
8
|
+
...BaseCommand.baseFlags,
|
|
9
|
+
};
|
|
10
|
+
async run() {
|
|
11
|
+
const { flags } = await this.parse(DestinationsList);
|
|
12
|
+
try {
|
|
13
|
+
this.loadEnvironment(flags);
|
|
14
|
+
const rows = await listDestinations(await this.getAuthenticatedClient());
|
|
15
|
+
this.writeRows(rows, [
|
|
16
|
+
{ key: 'id', label: 'ID' },
|
|
17
|
+
{ key: 'title', label: 'Title' },
|
|
18
|
+
{ key: 'type', label: 'Type' },
|
|
19
|
+
], flags);
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
this.handleCliError(error, flags);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { OWOXApiClient, OWOXStorage } from '@owox/api-client';
|
|
2
|
+
import { BaseCommand } from '../../base-command.js';
|
|
3
|
+
export declare function listStorages(client: Pick<OWOXApiClient, 'storages'>): Promise<OWOXStorage[]>;
|
|
4
|
+
export default class StoragesList extends BaseCommand {
|
|
5
|
+
static description: string;
|
|
6
|
+
static flags: {
|
|
7
|
+
'env-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
+
format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
'no-color': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
};
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command.js';
|
|
2
|
+
export async function listStorages(client) {
|
|
3
|
+
return client.storages.list();
|
|
4
|
+
}
|
|
5
|
+
export default class StoragesList extends BaseCommand {
|
|
6
|
+
static description = 'List storages';
|
|
7
|
+
static flags = {
|
|
8
|
+
...BaseCommand.baseFlags,
|
|
9
|
+
};
|
|
10
|
+
async run() {
|
|
11
|
+
const { flags } = await this.parse(StoragesList);
|
|
12
|
+
try {
|
|
13
|
+
this.loadEnvironment(flags);
|
|
14
|
+
const rows = await listStorages(await this.getAuthenticatedClient());
|
|
15
|
+
this.writeRows(rows, [
|
|
16
|
+
{ key: 'id', label: 'ID' },
|
|
17
|
+
{ key: 'title', label: 'Title' },
|
|
18
|
+
{ key: 'type', label: 'Type' },
|
|
19
|
+
], flags);
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
this.handleCliError(error, flags);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type AuthConfig = {
|
|
2
|
+
apiOrigin: string;
|
|
3
|
+
apiKeyId: string;
|
|
4
|
+
apiKeySecret: string;
|
|
5
|
+
};
|
|
6
|
+
export type ResolvedAuthConfig = {
|
|
7
|
+
source: 'env' | 'stored';
|
|
8
|
+
config: AuthConfig;
|
|
9
|
+
};
|
|
10
|
+
type ResolveAuthConfigInput = {
|
|
11
|
+
env?: NodeJS.ProcessEnv;
|
|
12
|
+
store?: ConfigStore;
|
|
13
|
+
};
|
|
14
|
+
export declare function getDefaultConfigPath(env?: NodeJS.ProcessEnv): string;
|
|
15
|
+
export declare function maskApiKeyId(apiKeyId: string): string;
|
|
16
|
+
export declare class ConfigStore {
|
|
17
|
+
readonly path: string;
|
|
18
|
+
constructor(path?: string);
|
|
19
|
+
read(): Promise<AuthConfig | null>;
|
|
20
|
+
save(config: AuthConfig): Promise<void>;
|
|
21
|
+
remove(): Promise<boolean>;
|
|
22
|
+
}
|
|
23
|
+
export declare function resolveAuthConfig(input?: ResolveAuthConfigInput): Promise<ResolvedAuthConfig | null>;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { chmod, mkdir, readFile, rm, stat, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
import envPaths from 'env-paths';
|
|
4
|
+
import { OWOXConfigError } from '@owox/api-client';
|
|
5
|
+
function isAuthConfig(value) {
|
|
6
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
const record = value;
|
|
10
|
+
return (typeof record.apiOrigin === 'string' &&
|
|
11
|
+
typeof record.apiKeyId === 'string' &&
|
|
12
|
+
typeof record.apiKeySecret === 'string');
|
|
13
|
+
}
|
|
14
|
+
export function getDefaultConfigPath(env = process.env) {
|
|
15
|
+
if (env.OWOX_CTL_CONFIG_PATH) {
|
|
16
|
+
return env.OWOX_CTL_CONFIG_PATH;
|
|
17
|
+
}
|
|
18
|
+
return join(envPaths('owox', { suffix: '' }).config, 'ctl', 'config.json');
|
|
19
|
+
}
|
|
20
|
+
export function maskApiKeyId(apiKeyId) {
|
|
21
|
+
if (apiKeyId.length <= 8) {
|
|
22
|
+
return `${apiKeyId.slice(0, 2)}...`;
|
|
23
|
+
}
|
|
24
|
+
return `${apiKeyId.slice(0, 8)}...`;
|
|
25
|
+
}
|
|
26
|
+
export class ConfigStore {
|
|
27
|
+
path;
|
|
28
|
+
constructor(path = getDefaultConfigPath()) {
|
|
29
|
+
this.path = path;
|
|
30
|
+
}
|
|
31
|
+
async read() {
|
|
32
|
+
try {
|
|
33
|
+
const raw = await readFile(this.path, 'utf8');
|
|
34
|
+
const parsed = JSON.parse(raw);
|
|
35
|
+
if (!isAuthConfig(parsed)) {
|
|
36
|
+
throw new OWOXConfigError(`Invalid owox-ctl config file at ${this.path}`);
|
|
37
|
+
}
|
|
38
|
+
return parsed;
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
if (error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT') {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async save(config) {
|
|
48
|
+
await mkdir(dirname(this.path), { recursive: true, mode: 0o700 });
|
|
49
|
+
await chmod(dirname(this.path), 0o700).catch(() => undefined);
|
|
50
|
+
await writeFile(this.path, `${JSON.stringify(config, null, 2)}\n`, {
|
|
51
|
+
encoding: 'utf8',
|
|
52
|
+
mode: 0o600,
|
|
53
|
+
});
|
|
54
|
+
await chmod(this.path, 0o600).catch(() => undefined);
|
|
55
|
+
}
|
|
56
|
+
async remove() {
|
|
57
|
+
let removed = true;
|
|
58
|
+
try {
|
|
59
|
+
await rm(this.path);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
if (error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT') {
|
|
63
|
+
removed = false;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (removed) {
|
|
70
|
+
try {
|
|
71
|
+
await stat(this.path);
|
|
72
|
+
throw new OWOXConfigError(`Failed to remove owox-ctl config file at ${this.path}`);
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
if (!(error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT')) {
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return removed;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export async function resolveAuthConfig(input = {}) {
|
|
84
|
+
const env = input.env ?? process.env;
|
|
85
|
+
const store = input.store ?? new ConfigStore();
|
|
86
|
+
const envValues = {
|
|
87
|
+
apiOrigin: env.OWOX_API_ORIGIN,
|
|
88
|
+
apiKeyId: env.OWOX_API_KEY_ID,
|
|
89
|
+
apiKeySecret: env.OWOX_API_KEY_SECRET,
|
|
90
|
+
};
|
|
91
|
+
const hasAnyEnvValue = Object.values(envValues).some(value => value !== undefined);
|
|
92
|
+
if (hasAnyEnvValue) {
|
|
93
|
+
if (!envValues.apiOrigin || !envValues.apiKeyId || !envValues.apiKeySecret) {
|
|
94
|
+
throw new OWOXConfigError('OWOX_API_ORIGIN, OWOX_API_KEY_ID, and OWOX_API_KEY_SECRET must be set together');
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
source: 'env',
|
|
98
|
+
config: {
|
|
99
|
+
apiOrigin: envValues.apiOrigin,
|
|
100
|
+
apiKeyId: envValues.apiKeyId,
|
|
101
|
+
apiKeySecret: envValues.apiKeySecret,
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
const stored = await store.read();
|
|
106
|
+
return stored ? { source: 'stored', config: stored } : null;
|
|
107
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/output.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type OutputFormat = 'table' | 'json';
|
|
2
|
+
export type TableColumn<T extends Record<string, unknown>> = {
|
|
3
|
+
key: keyof T & string;
|
|
4
|
+
label: string;
|
|
5
|
+
get?: (row: T) => string | number | boolean | null | undefined;
|
|
6
|
+
};
|
|
7
|
+
export type ColorOptions = {
|
|
8
|
+
enabled: boolean;
|
|
9
|
+
};
|
|
10
|
+
export declare function shouldUseColor(options: {
|
|
11
|
+
format: OutputFormat;
|
|
12
|
+
noColor?: boolean;
|
|
13
|
+
stream?: NodeJS.WriteStream;
|
|
14
|
+
env?: NodeJS.ProcessEnv;
|
|
15
|
+
}): boolean;
|
|
16
|
+
export declare function colors(options: ColorOptions): {
|
|
17
|
+
bold: (text: string) => string;
|
|
18
|
+
dim: (text: string) => string;
|
|
19
|
+
error: (text: string) => string;
|
|
20
|
+
success: (text: string) => string;
|
|
21
|
+
warning: (text: string) => string;
|
|
22
|
+
};
|
|
23
|
+
export declare function renderJson(value: unknown): string;
|
|
24
|
+
export declare function renderTable<T extends Record<string, unknown>>(rows: T[], columns: TableColumn<T>[]): string;
|
|
25
|
+
export declare function renderKeyValues(values: Record<string, string | number | boolean>, options?: ColorOptions): string;
|
package/dist/output.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const ANSI = {
|
|
2
|
+
bold: ['\u001B[1m', '\u001B[22m'],
|
|
3
|
+
dim: ['\u001B[2m', '\u001B[22m'],
|
|
4
|
+
green: ['\u001B[32m', '\u001B[39m'],
|
|
5
|
+
red: ['\u001B[31m', '\u001B[39m'],
|
|
6
|
+
yellow: ['\u001B[33m', '\u001B[39m'],
|
|
7
|
+
};
|
|
8
|
+
export function shouldUseColor(options) {
|
|
9
|
+
if (options.format === 'json' || options.noColor || options.env?.NO_COLOR !== undefined) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
return options.stream?.isTTY === true;
|
|
13
|
+
}
|
|
14
|
+
function colorize(text, code, options) {
|
|
15
|
+
if (!options.enabled) {
|
|
16
|
+
return text;
|
|
17
|
+
}
|
|
18
|
+
const [open, close] = ANSI[code];
|
|
19
|
+
return `${open}${text}${close}`;
|
|
20
|
+
}
|
|
21
|
+
export function colors(options) {
|
|
22
|
+
return {
|
|
23
|
+
bold: (text) => colorize(text, 'bold', options),
|
|
24
|
+
dim: (text) => colorize(text, 'dim', options),
|
|
25
|
+
error: (text) => colorize(text, 'red', options),
|
|
26
|
+
success: (text) => colorize(text, 'green', options),
|
|
27
|
+
warning: (text) => colorize(text, 'yellow', options),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export function renderJson(value) {
|
|
31
|
+
return JSON.stringify(value, null, 2);
|
|
32
|
+
}
|
|
33
|
+
function stringifyCell(value) {
|
|
34
|
+
if (value === null || value === undefined) {
|
|
35
|
+
return '';
|
|
36
|
+
}
|
|
37
|
+
return String(value);
|
|
38
|
+
}
|
|
39
|
+
export function renderTable(rows, columns) {
|
|
40
|
+
if (rows.length === 0) {
|
|
41
|
+
return 'No results';
|
|
42
|
+
}
|
|
43
|
+
const renderedRows = rows.map(row => columns.map(column => stringifyCell(column.get ? column.get(row) : row[column.key])));
|
|
44
|
+
const widths = columns.map((column, columnIndex) => Math.max(column.label.length, ...renderedRows.map(row => row[columnIndex]?.length ?? 0)));
|
|
45
|
+
const renderLine = (values) => values.map((value, index) => value.padEnd(widths[index] ?? 0)).join(' ');
|
|
46
|
+
return [
|
|
47
|
+
renderLine(columns.map(column => column.label)),
|
|
48
|
+
renderLine(widths.map(width => '-'.repeat(width))),
|
|
49
|
+
...renderedRows.map(row => renderLine(row)),
|
|
50
|
+
].join('\n');
|
|
51
|
+
}
|
|
52
|
+
export function renderKeyValues(values, options = { enabled: false }) {
|
|
53
|
+
const labelWidth = Math.max(...Object.keys(values).map(label => label.length));
|
|
54
|
+
const palette = colors(options);
|
|
55
|
+
return Object.entries(values)
|
|
56
|
+
.map(([label, value]) => `${palette.bold(`${label}:`.padEnd(labelWidth + 1))} ${value}`)
|
|
57
|
+
.join('\n');
|
|
58
|
+
}
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
{
|
|
2
|
+
"commands": {
|
|
3
|
+
"auth:login": {
|
|
4
|
+
"aliases": [],
|
|
5
|
+
"args": {},
|
|
6
|
+
"description": "Authenticate with OWOX Data Marts",
|
|
7
|
+
"examples": [
|
|
8
|
+
"<%= config.bin %> auth login",
|
|
9
|
+
"<%= config.bin %> auth login --api-origin https://app.owox.com --api-key-id pmk_xxx --api-key-secret xxx"
|
|
10
|
+
],
|
|
11
|
+
"flags": {
|
|
12
|
+
"env-file": {
|
|
13
|
+
"char": "e",
|
|
14
|
+
"description": "Path to environment file to load variables from",
|
|
15
|
+
"name": "env-file",
|
|
16
|
+
"hasDynamicHelp": false,
|
|
17
|
+
"helpValue": "/path/to/.env",
|
|
18
|
+
"multiple": false,
|
|
19
|
+
"type": "option"
|
|
20
|
+
},
|
|
21
|
+
"format": {
|
|
22
|
+
"description": "Output format",
|
|
23
|
+
"name": "format",
|
|
24
|
+
"default": "table",
|
|
25
|
+
"hasDynamicHelp": false,
|
|
26
|
+
"multiple": false,
|
|
27
|
+
"options": [
|
|
28
|
+
"table",
|
|
29
|
+
"json"
|
|
30
|
+
],
|
|
31
|
+
"type": "option"
|
|
32
|
+
},
|
|
33
|
+
"no-color": {
|
|
34
|
+
"description": "Disable color output",
|
|
35
|
+
"name": "no-color",
|
|
36
|
+
"allowNo": false,
|
|
37
|
+
"type": "boolean"
|
|
38
|
+
},
|
|
39
|
+
"api-origin": {
|
|
40
|
+
"description": "OWOX Data Marts API origin, for example https://app.owox.com",
|
|
41
|
+
"name": "api-origin",
|
|
42
|
+
"hasDynamicHelp": false,
|
|
43
|
+
"multiple": false,
|
|
44
|
+
"type": "option"
|
|
45
|
+
},
|
|
46
|
+
"api-key-id": {
|
|
47
|
+
"description": "API key ID",
|
|
48
|
+
"name": "api-key-id",
|
|
49
|
+
"hasDynamicHelp": false,
|
|
50
|
+
"multiple": false,
|
|
51
|
+
"type": "option"
|
|
52
|
+
},
|
|
53
|
+
"api-key-secret": {
|
|
54
|
+
"description": "API key secret",
|
|
55
|
+
"name": "api-key-secret",
|
|
56
|
+
"hasDynamicHelp": false,
|
|
57
|
+
"multiple": false,
|
|
58
|
+
"type": "option"
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"hasDynamicHelp": false,
|
|
62
|
+
"hiddenAliases": [],
|
|
63
|
+
"id": "auth:login",
|
|
64
|
+
"pluginAlias": "@owox/ctl",
|
|
65
|
+
"pluginName": "@owox/ctl",
|
|
66
|
+
"pluginType": "core",
|
|
67
|
+
"strict": true,
|
|
68
|
+
"enableJsonFlag": false,
|
|
69
|
+
"isESM": true,
|
|
70
|
+
"relativePath": [
|
|
71
|
+
"dist",
|
|
72
|
+
"commands",
|
|
73
|
+
"auth",
|
|
74
|
+
"login.js"
|
|
75
|
+
]
|
|
76
|
+
},
|
|
77
|
+
"auth:logout": {
|
|
78
|
+
"aliases": [],
|
|
79
|
+
"args": {},
|
|
80
|
+
"description": "Remove stored OWOX Data Marts credentials",
|
|
81
|
+
"flags": {
|
|
82
|
+
"env-file": {
|
|
83
|
+
"char": "e",
|
|
84
|
+
"description": "Path to environment file to load variables from",
|
|
85
|
+
"name": "env-file",
|
|
86
|
+
"hasDynamicHelp": false,
|
|
87
|
+
"helpValue": "/path/to/.env",
|
|
88
|
+
"multiple": false,
|
|
89
|
+
"type": "option"
|
|
90
|
+
},
|
|
91
|
+
"format": {
|
|
92
|
+
"description": "Output format",
|
|
93
|
+
"name": "format",
|
|
94
|
+
"default": "table",
|
|
95
|
+
"hasDynamicHelp": false,
|
|
96
|
+
"multiple": false,
|
|
97
|
+
"options": [
|
|
98
|
+
"table",
|
|
99
|
+
"json"
|
|
100
|
+
],
|
|
101
|
+
"type": "option"
|
|
102
|
+
},
|
|
103
|
+
"no-color": {
|
|
104
|
+
"description": "Disable color output",
|
|
105
|
+
"name": "no-color",
|
|
106
|
+
"allowNo": false,
|
|
107
|
+
"type": "boolean"
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
"hasDynamicHelp": false,
|
|
111
|
+
"hiddenAliases": [],
|
|
112
|
+
"id": "auth:logout",
|
|
113
|
+
"pluginAlias": "@owox/ctl",
|
|
114
|
+
"pluginName": "@owox/ctl",
|
|
115
|
+
"pluginType": "core",
|
|
116
|
+
"strict": true,
|
|
117
|
+
"enableJsonFlag": false,
|
|
118
|
+
"isESM": true,
|
|
119
|
+
"relativePath": [
|
|
120
|
+
"dist",
|
|
121
|
+
"commands",
|
|
122
|
+
"auth",
|
|
123
|
+
"logout.js"
|
|
124
|
+
]
|
|
125
|
+
},
|
|
126
|
+
"auth:status": {
|
|
127
|
+
"aliases": [],
|
|
128
|
+
"args": {},
|
|
129
|
+
"description": "Show OWOX Data Marts authentication status",
|
|
130
|
+
"flags": {
|
|
131
|
+
"env-file": {
|
|
132
|
+
"char": "e",
|
|
133
|
+
"description": "Path to environment file to load variables from",
|
|
134
|
+
"name": "env-file",
|
|
135
|
+
"hasDynamicHelp": false,
|
|
136
|
+
"helpValue": "/path/to/.env",
|
|
137
|
+
"multiple": false,
|
|
138
|
+
"type": "option"
|
|
139
|
+
},
|
|
140
|
+
"format": {
|
|
141
|
+
"description": "Output format",
|
|
142
|
+
"name": "format",
|
|
143
|
+
"default": "table",
|
|
144
|
+
"hasDynamicHelp": false,
|
|
145
|
+
"multiple": false,
|
|
146
|
+
"options": [
|
|
147
|
+
"table",
|
|
148
|
+
"json"
|
|
149
|
+
],
|
|
150
|
+
"type": "option"
|
|
151
|
+
},
|
|
152
|
+
"no-color": {
|
|
153
|
+
"description": "Disable color output",
|
|
154
|
+
"name": "no-color",
|
|
155
|
+
"allowNo": false,
|
|
156
|
+
"type": "boolean"
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
"hasDynamicHelp": false,
|
|
160
|
+
"hiddenAliases": [],
|
|
161
|
+
"id": "auth:status",
|
|
162
|
+
"pluginAlias": "@owox/ctl",
|
|
163
|
+
"pluginName": "@owox/ctl",
|
|
164
|
+
"pluginType": "core",
|
|
165
|
+
"strict": true,
|
|
166
|
+
"enableJsonFlag": false,
|
|
167
|
+
"isESM": true,
|
|
168
|
+
"relativePath": [
|
|
169
|
+
"dist",
|
|
170
|
+
"commands",
|
|
171
|
+
"auth",
|
|
172
|
+
"status.js"
|
|
173
|
+
]
|
|
174
|
+
},
|
|
175
|
+
"data-marts:list": {
|
|
176
|
+
"aliases": [],
|
|
177
|
+
"args": {},
|
|
178
|
+
"description": "List data marts",
|
|
179
|
+
"flags": {
|
|
180
|
+
"env-file": {
|
|
181
|
+
"char": "e",
|
|
182
|
+
"description": "Path to environment file to load variables from",
|
|
183
|
+
"name": "env-file",
|
|
184
|
+
"hasDynamicHelp": false,
|
|
185
|
+
"helpValue": "/path/to/.env",
|
|
186
|
+
"multiple": false,
|
|
187
|
+
"type": "option"
|
|
188
|
+
},
|
|
189
|
+
"format": {
|
|
190
|
+
"description": "Output format",
|
|
191
|
+
"name": "format",
|
|
192
|
+
"default": "table",
|
|
193
|
+
"hasDynamicHelp": false,
|
|
194
|
+
"multiple": false,
|
|
195
|
+
"options": [
|
|
196
|
+
"table",
|
|
197
|
+
"json"
|
|
198
|
+
],
|
|
199
|
+
"type": "option"
|
|
200
|
+
},
|
|
201
|
+
"no-color": {
|
|
202
|
+
"description": "Disable color output",
|
|
203
|
+
"name": "no-color",
|
|
204
|
+
"allowNo": false,
|
|
205
|
+
"type": "boolean"
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
"hasDynamicHelp": false,
|
|
209
|
+
"hiddenAliases": [],
|
|
210
|
+
"id": "data-marts:list",
|
|
211
|
+
"pluginAlias": "@owox/ctl",
|
|
212
|
+
"pluginName": "@owox/ctl",
|
|
213
|
+
"pluginType": "core",
|
|
214
|
+
"strict": true,
|
|
215
|
+
"enableJsonFlag": false,
|
|
216
|
+
"isESM": true,
|
|
217
|
+
"relativePath": [
|
|
218
|
+
"dist",
|
|
219
|
+
"commands",
|
|
220
|
+
"data-marts",
|
|
221
|
+
"list.js"
|
|
222
|
+
]
|
|
223
|
+
},
|
|
224
|
+
"destinations:list": {
|
|
225
|
+
"aliases": [],
|
|
226
|
+
"args": {},
|
|
227
|
+
"description": "List destinations",
|
|
228
|
+
"flags": {
|
|
229
|
+
"env-file": {
|
|
230
|
+
"char": "e",
|
|
231
|
+
"description": "Path to environment file to load variables from",
|
|
232
|
+
"name": "env-file",
|
|
233
|
+
"hasDynamicHelp": false,
|
|
234
|
+
"helpValue": "/path/to/.env",
|
|
235
|
+
"multiple": false,
|
|
236
|
+
"type": "option"
|
|
237
|
+
},
|
|
238
|
+
"format": {
|
|
239
|
+
"description": "Output format",
|
|
240
|
+
"name": "format",
|
|
241
|
+
"default": "table",
|
|
242
|
+
"hasDynamicHelp": false,
|
|
243
|
+
"multiple": false,
|
|
244
|
+
"options": [
|
|
245
|
+
"table",
|
|
246
|
+
"json"
|
|
247
|
+
],
|
|
248
|
+
"type": "option"
|
|
249
|
+
},
|
|
250
|
+
"no-color": {
|
|
251
|
+
"description": "Disable color output",
|
|
252
|
+
"name": "no-color",
|
|
253
|
+
"allowNo": false,
|
|
254
|
+
"type": "boolean"
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
"hasDynamicHelp": false,
|
|
258
|
+
"hiddenAliases": [],
|
|
259
|
+
"id": "destinations:list",
|
|
260
|
+
"pluginAlias": "@owox/ctl",
|
|
261
|
+
"pluginName": "@owox/ctl",
|
|
262
|
+
"pluginType": "core",
|
|
263
|
+
"strict": true,
|
|
264
|
+
"enableJsonFlag": false,
|
|
265
|
+
"isESM": true,
|
|
266
|
+
"relativePath": [
|
|
267
|
+
"dist",
|
|
268
|
+
"commands",
|
|
269
|
+
"destinations",
|
|
270
|
+
"list.js"
|
|
271
|
+
]
|
|
272
|
+
},
|
|
273
|
+
"storages:list": {
|
|
274
|
+
"aliases": [],
|
|
275
|
+
"args": {},
|
|
276
|
+
"description": "List storages",
|
|
277
|
+
"flags": {
|
|
278
|
+
"env-file": {
|
|
279
|
+
"char": "e",
|
|
280
|
+
"description": "Path to environment file to load variables from",
|
|
281
|
+
"name": "env-file",
|
|
282
|
+
"hasDynamicHelp": false,
|
|
283
|
+
"helpValue": "/path/to/.env",
|
|
284
|
+
"multiple": false,
|
|
285
|
+
"type": "option"
|
|
286
|
+
},
|
|
287
|
+
"format": {
|
|
288
|
+
"description": "Output format",
|
|
289
|
+
"name": "format",
|
|
290
|
+
"default": "table",
|
|
291
|
+
"hasDynamicHelp": false,
|
|
292
|
+
"multiple": false,
|
|
293
|
+
"options": [
|
|
294
|
+
"table",
|
|
295
|
+
"json"
|
|
296
|
+
],
|
|
297
|
+
"type": "option"
|
|
298
|
+
},
|
|
299
|
+
"no-color": {
|
|
300
|
+
"description": "Disable color output",
|
|
301
|
+
"name": "no-color",
|
|
302
|
+
"allowNo": false,
|
|
303
|
+
"type": "boolean"
|
|
304
|
+
}
|
|
305
|
+
},
|
|
306
|
+
"hasDynamicHelp": false,
|
|
307
|
+
"hiddenAliases": [],
|
|
308
|
+
"id": "storages:list",
|
|
309
|
+
"pluginAlias": "@owox/ctl",
|
|
310
|
+
"pluginName": "@owox/ctl",
|
|
311
|
+
"pluginType": "core",
|
|
312
|
+
"strict": true,
|
|
313
|
+
"enableJsonFlag": false,
|
|
314
|
+
"isESM": true,
|
|
315
|
+
"relativePath": [
|
|
316
|
+
"dist",
|
|
317
|
+
"commands",
|
|
318
|
+
"storages",
|
|
319
|
+
"list.js"
|
|
320
|
+
]
|
|
321
|
+
}
|
|
322
|
+
},
|
|
323
|
+
"version": "0.26.0"
|
|
324
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@owox/ctl",
|
|
3
|
+
"description": "OWOX Data Marts Control CLI",
|
|
4
|
+
"version": "0.26.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"author": "OWOX",
|
|
7
|
+
"license": "ELv2",
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"access": "public"
|
|
10
|
+
},
|
|
11
|
+
"bin": {
|
|
12
|
+
"owox-ctl": "./bin/run.js"
|
|
13
|
+
},
|
|
14
|
+
"bugs": "https://github.com/OWOX/owox-data-marts/issues",
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@oclif/core": "^4",
|
|
17
|
+
"@oclif/plugin-help": "^6",
|
|
18
|
+
"@owox/api-client": "0.26.0",
|
|
19
|
+
"@owox/internal-helpers": "0.26.0",
|
|
20
|
+
"env-paths": "^3.0.0"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@owox/eslint-config": "*",
|
|
24
|
+
"@owox/prettier-config": "*",
|
|
25
|
+
"@types/jest": "29.5.14",
|
|
26
|
+
"@types/node": "^22.10.7",
|
|
27
|
+
"jest": "^30.2.0",
|
|
28
|
+
"shx": "^0.4.0",
|
|
29
|
+
"ts-jest": "^29.4.6"
|
|
30
|
+
},
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=22.16.0"
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"./bin",
|
|
36
|
+
"./dist/**/*.d.ts",
|
|
37
|
+
"./dist/**/*.js",
|
|
38
|
+
"./oclif.manifest.json"
|
|
39
|
+
],
|
|
40
|
+
"homepage": "https://github.com/OWOX/owox-data-marts",
|
|
41
|
+
"keywords": [
|
|
42
|
+
"owox",
|
|
43
|
+
"data-marts",
|
|
44
|
+
"cli",
|
|
45
|
+
"control"
|
|
46
|
+
],
|
|
47
|
+
"main": "dist/index.js",
|
|
48
|
+
"oclif": {
|
|
49
|
+
"bin": "owox-ctl",
|
|
50
|
+
"dirname": "owox-ctl",
|
|
51
|
+
"commands": "./dist/commands",
|
|
52
|
+
"plugins": [
|
|
53
|
+
"@oclif/plugin-help"
|
|
54
|
+
],
|
|
55
|
+
"topicSeparator": " "
|
|
56
|
+
},
|
|
57
|
+
"repository": "OWOX/owox-data-marts",
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "tsc",
|
|
60
|
+
"build:clean": "shx rm -rf dist oclif.manifest.json tsconfig.tsbuildinfo",
|
|
61
|
+
"build:dep": "npm run build -w @owox/internal-helpers --prefix ../.. && npm run build -w @owox/api-client --prefix ../..",
|
|
62
|
+
"clean": "npm run build:clean",
|
|
63
|
+
"format": "prettier --write \"**/*.{ts,js,json}\" --ignore-path ../../.prettierignore",
|
|
64
|
+
"format:check": "prettier --check \"**/*.{ts,js,json}\" --ignore-path ../../.prettierignore",
|
|
65
|
+
"lint": "eslint . --config ./eslint.config.js",
|
|
66
|
+
"lint:fix": "eslint . --fix --config ./eslint.config.js",
|
|
67
|
+
"prebuild": "npm run build:clean && npm run build:dep",
|
|
68
|
+
"prepack": "oclif manifest",
|
|
69
|
+
"prepublishOnly": "npm run lint && npm run typecheck",
|
|
70
|
+
"pretest": "npm run build:dep",
|
|
71
|
+
"test": "NODE_OPTIONS=--experimental-vm-modules jest --passWithNoTests",
|
|
72
|
+
"typecheck": "tsc --noEmit"
|
|
73
|
+
},
|
|
74
|
+
"types": "dist/index.d.ts"
|
|
75
|
+
}
|