@contextual-io/cli 0.1.1 → 0.1.2
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 +456 -1
- package/dist/commands/base.d.ts +41 -0
- package/dist/commands/base.js +164 -0
- package/dist/commands/config/add.d.ts +13 -0
- package/dist/commands/config/add.js +34 -0
- package/dist/commands/config/current.d.ts +10 -0
- package/dist/commands/config/current.js +15 -0
- package/dist/commands/config/delete.d.ts +10 -0
- package/dist/commands/config/delete.js +17 -0
- package/dist/commands/config/get.d.ts +12 -0
- package/dist/commands/config/get.js +25 -0
- package/dist/commands/config/list.d.ts +13 -0
- package/dist/commands/config/list.js +33 -0
- package/dist/commands/config/login.d.ts +8 -0
- package/dist/commands/config/login.js +21 -0
- package/dist/commands/config/use.d.ts +10 -0
- package/dist/commands/config/use.js +17 -0
- package/dist/commands/records/add.d.ts +14 -0
- package/dist/commands/records/add.js +73 -0
- package/dist/commands/records/delete.d.ts +13 -0
- package/dist/commands/records/delete.js +55 -0
- package/dist/commands/records/get.d.ts +13 -0
- package/dist/commands/records/get.js +53 -0
- package/dist/commands/records/list.d.ts +22 -0
- package/dist/commands/records/list.js +145 -0
- package/dist/commands/records/query.d.ts +19 -0
- package/dist/commands/records/query.js +134 -0
- package/dist/commands/records/replace.d.ts +14 -0
- package/dist/commands/records/replace.js +69 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/models/cli-configuration.d.ts +9 -0
- package/dist/models/cli-configuration.js +8 -0
- package/dist/models/errors.d.ts +5 -0
- package/dist/models/errors.js +14 -0
- package/dist/models/silo.d.ts +7 -0
- package/dist/models/silo.js +2 -0
- package/dist/models/uri.d.ts +7 -0
- package/dist/models/uri.js +7 -0
- package/dist/models/url-safe-id.d.ts +3 -0
- package/dist/models/url-safe-id.js +4 -0
- package/dist/models/user-config.d.ts +54 -0
- package/dist/models/user-config.js +24 -0
- package/dist/utils/auth.d.ts +6 -0
- package/dist/utils/auth.js +101 -0
- package/dist/utils/cli-configuration.d.ts +3 -0
- package/dist/utils/cli-configuration.js +19 -0
- package/dist/utils/endpoints.d.ts +3 -0
- package/dist/utils/endpoints.js +2 -0
- package/dist/utils/stream.d.ts +3 -0
- package/dist/utils/stream.js +21 -0
- package/dist/utils/time.d.ts +2 -0
- package/dist/utils/time.js +5 -0
- package/oclif.manifest.json +740 -2
- package/package.json +1 -1
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Args, Flags } from "@oclif/core";
|
|
2
|
+
import { Silo } from "../../models/silo.js";
|
|
3
|
+
import { UrlSafeId } from "../../models/url-safe-id.js";
|
|
4
|
+
import { getCliConfiguration } from "../../utils/cli-configuration.js";
|
|
5
|
+
import { BaseConfigCommand } from "../base.js";
|
|
6
|
+
export default class ConfigAdd extends BaseConfigCommand {
|
|
7
|
+
static args = {
|
|
8
|
+
"config-id": Args.string({ description: "id of config", required: true }),
|
|
9
|
+
};
|
|
10
|
+
static description = "add a new config";
|
|
11
|
+
static examples = [
|
|
12
|
+
"<%= config.bin %> <%= command.id %> some-config-id --tenant-id my-tenant",
|
|
13
|
+
];
|
|
14
|
+
static flags = {
|
|
15
|
+
silo: Flags.string({
|
|
16
|
+
char: "s",
|
|
17
|
+
default: "prod",
|
|
18
|
+
description: "silo",
|
|
19
|
+
options: [...Silo.options.values()],
|
|
20
|
+
}),
|
|
21
|
+
"tenant-id": Flags.string({ char: "t", description: "tenant id (if different from config id)" }),
|
|
22
|
+
};
|
|
23
|
+
async run() {
|
|
24
|
+
const configId = UrlSafeId.parse(this.args["config-id"]);
|
|
25
|
+
const tenantId = UrlSafeId.optional().parse(this.flags["tenant-id"]) ?? configId;
|
|
26
|
+
const silo = Silo.parse(this.flags.silo);
|
|
27
|
+
const cliConfig = await getCliConfiguration(tenantId, silo);
|
|
28
|
+
this.userConfig.upsert(configId, {
|
|
29
|
+
silo,
|
|
30
|
+
tenantId,
|
|
31
|
+
...cliConfig,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CleanConfig } from "../../models/user-config.js";
|
|
2
|
+
import { BaseConfigCommand } from "../base.js";
|
|
3
|
+
export default class ConfigCurrent extends BaseConfigCommand<typeof ConfigCurrent> {
|
|
4
|
+
static args: {};
|
|
5
|
+
static description: string;
|
|
6
|
+
static enableJsonFlag: boolean;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {};
|
|
9
|
+
run(): Promise<CleanConfig>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BaseConfigCommand } from "../base.js";
|
|
2
|
+
export default class ConfigCurrent extends BaseConfigCommand {
|
|
3
|
+
static args = {};
|
|
4
|
+
static description = "get the current config";
|
|
5
|
+
static enableJsonFlag = true;
|
|
6
|
+
static examples = [
|
|
7
|
+
"<%= config.bin %> <%= command.id %>",
|
|
8
|
+
];
|
|
9
|
+
static flags = {};
|
|
10
|
+
async run() {
|
|
11
|
+
const { config, lookup } = await this.userConfig.get();
|
|
12
|
+
this.log(lookup);
|
|
13
|
+
return this.userConfig.clean(lookup, config);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { BaseConfigCommand } from "../base.js";
|
|
2
|
+
export default class ConfigDelete extends BaseConfigCommand<typeof ConfigDelete> {
|
|
3
|
+
static args: {
|
|
4
|
+
"config-id": import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
5
|
+
};
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {};
|
|
9
|
+
run(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Args } from "@oclif/core";
|
|
2
|
+
import { UrlSafeId } from "../../models/url-safe-id.js";
|
|
3
|
+
import { BaseConfigCommand } from "../base.js";
|
|
4
|
+
export default class ConfigDelete extends BaseConfigCommand {
|
|
5
|
+
static args = {
|
|
6
|
+
"config-id": Args.string({ description: "id of config", required: true }),
|
|
7
|
+
};
|
|
8
|
+
static description = "delete a config";
|
|
9
|
+
static examples = [
|
|
10
|
+
"<%= config.bin %> <%= command.id %> some-config-id",
|
|
11
|
+
];
|
|
12
|
+
static flags = {};
|
|
13
|
+
async run() {
|
|
14
|
+
const configId = UrlSafeId.parse(this.args["config-id"]);
|
|
15
|
+
this.userConfig.remove(configId);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { CleanConfig } from "../../models/user-config.js";
|
|
2
|
+
import { BaseConfigCommand } from "../base.js";
|
|
3
|
+
export default class ConfigGet extends BaseConfigCommand<typeof ConfigGet> {
|
|
4
|
+
static args: {
|
|
5
|
+
"config-id": import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
6
|
+
};
|
|
7
|
+
static description: string;
|
|
8
|
+
static enableJsonFlag: boolean;
|
|
9
|
+
static examples: string[];
|
|
10
|
+
static flags: {};
|
|
11
|
+
run(): Promise<CleanConfig>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Args } from "@oclif/core";
|
|
2
|
+
import { makeTable } from "@oclif/table";
|
|
3
|
+
import { UrlSafeId } from "../../models/url-safe-id.js";
|
|
4
|
+
import { BaseConfigCommand } from "../base.js";
|
|
5
|
+
export default class ConfigGet extends BaseConfigCommand {
|
|
6
|
+
static args = {
|
|
7
|
+
"config-id": Args.string({ description: "id of config" }),
|
|
8
|
+
};
|
|
9
|
+
static description = "get a specific config";
|
|
10
|
+
static enableJsonFlag = true;
|
|
11
|
+
static examples = [
|
|
12
|
+
"<%= config.bin %> <%= command.id %>",
|
|
13
|
+
"<%= config.bin %> <%= command.id %> some-config-id",
|
|
14
|
+
];
|
|
15
|
+
static flags = {};
|
|
16
|
+
async run() {
|
|
17
|
+
const configId = UrlSafeId.optional().parse(this.args["config-id"]);
|
|
18
|
+
const { config, lookup } = await this.userConfig.get(configId);
|
|
19
|
+
const rv = this.userConfig.clean(lookup, config);
|
|
20
|
+
this.log(makeTable({
|
|
21
|
+
data: [rv],
|
|
22
|
+
}));
|
|
23
|
+
return rv;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { CleanConfig } from "../../models/user-config.js";
|
|
2
|
+
import { BaseConfigCommand } from "../base.js";
|
|
3
|
+
export default class ConfigList extends BaseConfigCommand<typeof ConfigList> {
|
|
4
|
+
static args: {};
|
|
5
|
+
static description: string;
|
|
6
|
+
static enableJsonFlag: boolean;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {};
|
|
9
|
+
run(): Promise<{
|
|
10
|
+
configs: CleanConfig[];
|
|
11
|
+
current?: string;
|
|
12
|
+
}>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { makeTable } from "@oclif/table";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { BaseConfigCommand } from "../base.js";
|
|
4
|
+
export default class ConfigList extends BaseConfigCommand {
|
|
5
|
+
static args = {};
|
|
6
|
+
static description = "list all available configs";
|
|
7
|
+
static enableJsonFlag = true;
|
|
8
|
+
static examples = [
|
|
9
|
+
"<%= config.bin %> <%= command.id %>",
|
|
10
|
+
];
|
|
11
|
+
static flags = {};
|
|
12
|
+
async run() {
|
|
13
|
+
const userConfig = this.userConfig.read();
|
|
14
|
+
const colorize = (config) => {
|
|
15
|
+
if (config.configId !== userConfig.current)
|
|
16
|
+
return config;
|
|
17
|
+
return {
|
|
18
|
+
configId: chalk.bold(chalk.yellow(config.configId)),
|
|
19
|
+
silo: chalk.bold(chalk.yellow(config.silo)),
|
|
20
|
+
tenantId: chalk.bold(chalk.yellow(config.tenantId)),
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
const configs = Object.entries(userConfig.configs)
|
|
24
|
+
.map(([configId, config]) => this.userConfig.clean(configId, config));
|
|
25
|
+
this.log(makeTable({
|
|
26
|
+
data: configs.map(c => colorize(c)),
|
|
27
|
+
}));
|
|
28
|
+
return {
|
|
29
|
+
configs,
|
|
30
|
+
current: userConfig.current,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { codeExchange, getUserProfile } from "../../utils/auth.js";
|
|
2
|
+
import { BaseConfigCommand } from "../base.js";
|
|
3
|
+
export default class ConfigLogin extends BaseConfigCommand {
|
|
4
|
+
static args = {};
|
|
5
|
+
static description = "login using the current config";
|
|
6
|
+
static examples = [
|
|
7
|
+
"<%= config.bin %> <%= command.id %>",
|
|
8
|
+
];
|
|
9
|
+
static flags = {};
|
|
10
|
+
async run() {
|
|
11
|
+
const { config, lookup } = await this.userConfig.get();
|
|
12
|
+
const auth = await codeExchange(config.auth);
|
|
13
|
+
const { email } = await getUserProfile(config.tenantId, config.silo, auth.bearerToken);
|
|
14
|
+
console.log("Logged in as %s.", email);
|
|
15
|
+
console.log("Welcome to Contextual!");
|
|
16
|
+
this.userConfig.upsert(lookup, {
|
|
17
|
+
...config,
|
|
18
|
+
...auth,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { BaseConfigCommand } from "../base.js";
|
|
2
|
+
export default class ConfigUse extends BaseConfigCommand<typeof ConfigUse> {
|
|
3
|
+
static args: {
|
|
4
|
+
"config-id": import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
5
|
+
};
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {};
|
|
9
|
+
run(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Args } from "@oclif/core";
|
|
2
|
+
import { UrlSafeId } from "../../models/url-safe-id.js";
|
|
3
|
+
import { BaseConfigCommand } from "../base.js";
|
|
4
|
+
export default class ConfigUse extends BaseConfigCommand {
|
|
5
|
+
static args = {
|
|
6
|
+
"config-id": Args.string({ description: "id of config", required: true }),
|
|
7
|
+
};
|
|
8
|
+
static description = "use a config";
|
|
9
|
+
static examples = [
|
|
10
|
+
"<%= config.bin %> <%= command.id %> some-config-id",
|
|
11
|
+
];
|
|
12
|
+
static flags = {};
|
|
13
|
+
async run() {
|
|
14
|
+
const configId = UrlSafeId.parse(this.args["config-id"]);
|
|
15
|
+
await this.userConfig.use(configId);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseCommand } from "../base.js";
|
|
2
|
+
export default class RecordsAdd extends BaseCommand<typeof RecordsAdd> {
|
|
3
|
+
static aliases: string[];
|
|
4
|
+
static args: {
|
|
5
|
+
uri: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
6
|
+
};
|
|
7
|
+
static description: string;
|
|
8
|
+
static examples: string[];
|
|
9
|
+
static flags: {
|
|
10
|
+
"input-file": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
type: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Args, Flags } from "@oclif/core";
|
|
2
|
+
import fs, { createReadStream } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import jsonl from "stream-json/jsonl/Parser.js";
|
|
5
|
+
import { parseUri } from "../../models/uri.js";
|
|
6
|
+
import { getNativeObjectApiEndpoint } from "../../utils/endpoints.js";
|
|
7
|
+
import { mapStream, readStreamToEnd } from "../../utils/stream.js";
|
|
8
|
+
import { BaseCommand } from "../base.js";
|
|
9
|
+
export default class RecordsAdd extends BaseCommand {
|
|
10
|
+
static aliases = ["create", "import"];
|
|
11
|
+
static args = {
|
|
12
|
+
"uri": Args.string({ description: "uri of type" }),
|
|
13
|
+
};
|
|
14
|
+
static description = "create record(s)";
|
|
15
|
+
static examples = [
|
|
16
|
+
"<%= config.bin %> <%= command.id %> native-object:my-type",
|
|
17
|
+
"<%= config.bin %> <%= command.id %> --type my-type --input-file records.json",
|
|
18
|
+
];
|
|
19
|
+
static flags = {
|
|
20
|
+
"input-file": Flags.file({
|
|
21
|
+
char: "i",
|
|
22
|
+
default: "-",
|
|
23
|
+
description: "file to read. can read stdin if value is '-'",
|
|
24
|
+
}),
|
|
25
|
+
type: Flags.string({
|
|
26
|
+
char: "T",
|
|
27
|
+
description: "type",
|
|
28
|
+
}),
|
|
29
|
+
};
|
|
30
|
+
async run() {
|
|
31
|
+
const { uri } = this.args;
|
|
32
|
+
const { type: flagType } = this.flags;
|
|
33
|
+
let type = flagType;
|
|
34
|
+
if (uri) {
|
|
35
|
+
const { type: uriType } = parseUri(uri);
|
|
36
|
+
type = uriType;
|
|
37
|
+
}
|
|
38
|
+
if (!type) {
|
|
39
|
+
throw new Error("Type not provided");
|
|
40
|
+
}
|
|
41
|
+
const inputFile = this.flags["input-file"] === "-"
|
|
42
|
+
? "-"
|
|
43
|
+
: path.resolve(this.flags["input-file"]);
|
|
44
|
+
if (inputFile && inputFile !== "-" && !fs.existsSync(inputFile)) {
|
|
45
|
+
throw new Error("File does not exist");
|
|
46
|
+
}
|
|
47
|
+
const stream = inputFile && inputFile !== "-"
|
|
48
|
+
? createReadStream(inputFile)
|
|
49
|
+
: process.stdin;
|
|
50
|
+
const records = await readStreamToEnd(stream
|
|
51
|
+
.pipe(jsonl.parser())
|
|
52
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
53
|
+
.pipe(mapStream(async (x) => x.value))
|
|
54
|
+
.pipe(mapStream(async (x) => JSON.stringify(x))));
|
|
55
|
+
const create = (body) => this.fetch(({ silo, tenantId }) => getNativeObjectApiEndpoint(tenantId, silo) + `/api/v1/${type}`, {
|
|
56
|
+
body,
|
|
57
|
+
headers: {
|
|
58
|
+
"content-type": "application/json",
|
|
59
|
+
},
|
|
60
|
+
method: "POST",
|
|
61
|
+
});
|
|
62
|
+
for (const record of records) {
|
|
63
|
+
// eslint-disable-next-line no-await-in-loop
|
|
64
|
+
const rv = await create(record);
|
|
65
|
+
if (records.length > 1) {
|
|
66
|
+
this.log(JSON.stringify(rv));
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
this.logJson(rv);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BaseCommand } from "../base.js";
|
|
2
|
+
export default class RecordsDelete extends BaseCommand<typeof RecordsDelete> {
|
|
3
|
+
static args: {
|
|
4
|
+
uri: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
5
|
+
};
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
id: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
type: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Args, Flags } from "@oclif/core";
|
|
2
|
+
import { parseUri } from "../../models/uri.js";
|
|
3
|
+
import { getNativeObjectApiEndpoint } from "../../utils/endpoints.js";
|
|
4
|
+
import { BaseCommand } from "../base.js";
|
|
5
|
+
export default class RecordsDelete extends BaseCommand {
|
|
6
|
+
static args = {
|
|
7
|
+
"uri": Args.string({ description: "uri of record" }),
|
|
8
|
+
};
|
|
9
|
+
static description = "delete record(s)";
|
|
10
|
+
static examples = [
|
|
11
|
+
"<%= config.bin %> <%= command.id %> native-object:my-type/instance-1",
|
|
12
|
+
"<%= config.bin %> <%= command.id %> native-object:my-type --id instance-1",
|
|
13
|
+
"<%= config.bin %> <%= command.id %> native-object:my-type --id instance-1 --id instance-2",
|
|
14
|
+
"<%= config.bin %> <%= command.id %> --type my-type --id instance-1",
|
|
15
|
+
"<%= config.bin %> <%= command.id %> --type my-type --id instance-1 --id instance-2",
|
|
16
|
+
];
|
|
17
|
+
static flags = {
|
|
18
|
+
id: Flags.string({
|
|
19
|
+
char: "i",
|
|
20
|
+
description: "id(s)",
|
|
21
|
+
multiple: true,
|
|
22
|
+
}),
|
|
23
|
+
type: Flags.string({
|
|
24
|
+
char: "T",
|
|
25
|
+
description: "type",
|
|
26
|
+
}),
|
|
27
|
+
};
|
|
28
|
+
async run() {
|
|
29
|
+
const { uri } = this.args;
|
|
30
|
+
const { id: flagIds, type: flagType } = this.flags;
|
|
31
|
+
let type = flagType;
|
|
32
|
+
let ids = flagIds;
|
|
33
|
+
if (uri) {
|
|
34
|
+
const { id, type: uriType } = parseUri(uri);
|
|
35
|
+
type = uriType;
|
|
36
|
+
if (id) {
|
|
37
|
+
ids = [id];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (!type) {
|
|
41
|
+
throw new Error("Type not provided");
|
|
42
|
+
}
|
|
43
|
+
if (!ids?.length) {
|
|
44
|
+
throw new Error("Id not provided");
|
|
45
|
+
}
|
|
46
|
+
const deleteRecord = (id) => this.fetch(({ silo, tenantId }) => getNativeObjectApiEndpoint(tenantId, silo) + `/api/v1/${type}/${id}`, {
|
|
47
|
+
method: "DELETE",
|
|
48
|
+
});
|
|
49
|
+
if (ids.length === 1) {
|
|
50
|
+
await deleteRecord(ids[0]);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
await Promise.all(ids.map(i => deleteRecord(i)));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BaseCommand } from "../base.js";
|
|
2
|
+
export default class RecordsGet extends BaseCommand<typeof RecordsGet> {
|
|
3
|
+
static args: {
|
|
4
|
+
uri: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
5
|
+
};
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
id: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
type: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Args, Flags } from "@oclif/core";
|
|
2
|
+
import { parseUri } from "../../models/uri.js";
|
|
3
|
+
import { getNativeObjectApiEndpoint } from "../../utils/endpoints.js";
|
|
4
|
+
import { BaseCommand } from "../base.js";
|
|
5
|
+
export default class RecordsGet extends BaseCommand {
|
|
6
|
+
static args = {
|
|
7
|
+
"uri": Args.string({ description: "uri of record" }),
|
|
8
|
+
};
|
|
9
|
+
static description = "get a record";
|
|
10
|
+
static examples = [
|
|
11
|
+
"<%= config.bin %> <%= command.id %> native-object:my-type/instance-1",
|
|
12
|
+
"<%= config.bin %> <%= command.id %> native-object:my-type --id instance-1",
|
|
13
|
+
"<%= config.bin %> <%= command.id %> native-object:my-type --id instance-1 --id instance-2",
|
|
14
|
+
"<%= config.bin %> <%= command.id %> --type my-type --id instance-1",
|
|
15
|
+
"<%= config.bin %> <%= command.id %> --type my-type --id instance-1 --id instance-2",
|
|
16
|
+
];
|
|
17
|
+
static flags = {
|
|
18
|
+
id: Flags.string({
|
|
19
|
+
char: "i",
|
|
20
|
+
description: "id(s)",
|
|
21
|
+
multiple: true,
|
|
22
|
+
}),
|
|
23
|
+
type: Flags.string({
|
|
24
|
+
char: "T",
|
|
25
|
+
description: "type",
|
|
26
|
+
}),
|
|
27
|
+
};
|
|
28
|
+
async run() {
|
|
29
|
+
const { uri } = this.args;
|
|
30
|
+
const { id: flagIds, type: flagType } = this.flags;
|
|
31
|
+
let type = flagType;
|
|
32
|
+
let ids = flagIds;
|
|
33
|
+
if (uri) {
|
|
34
|
+
const { id, type: uriType } = parseUri(uri);
|
|
35
|
+
type = uriType;
|
|
36
|
+
if (id) {
|
|
37
|
+
ids = [id];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (!type) {
|
|
41
|
+
throw new Error("Type not provided");
|
|
42
|
+
}
|
|
43
|
+
if (!ids?.length) {
|
|
44
|
+
throw new Error("Id not provided");
|
|
45
|
+
}
|
|
46
|
+
const getRecord = (id) => this.fetch(({ silo, tenantId }) => getNativeObjectApiEndpoint(tenantId, silo) + `/api/v1/${type}/${id}`);
|
|
47
|
+
if (ids.length === 1) {
|
|
48
|
+
this.logJson(await getRecord(ids[0]));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
this.logJson(await Promise.all(ids.map(i => getRecord(i))));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { BaseCommand } from "../base.js";
|
|
2
|
+
export default class RecordsList extends BaseCommand<typeof RecordsList> {
|
|
3
|
+
static args: {
|
|
4
|
+
uri: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
5
|
+
};
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
"exact-search": import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
export: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
from: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
"include-total": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
|
+
"order-by": import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
"page-size": import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
"page-token": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
progress: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
17
|
+
search: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
|
+
to: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
|
+
type: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
|
+
};
|
|
21
|
+
run(): Promise<void>;
|
|
22
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/* eslint-disable unicorn/no-array-reduce */
|
|
2
|
+
import { Args, Flags } from "@oclif/core";
|
|
3
|
+
import { parseUri } from "../../models/uri.js";
|
|
4
|
+
import { getNativeObjectApiEndpoint } from "../../utils/endpoints.js";
|
|
5
|
+
import { endTime, startTime } from "../../utils/time.js";
|
|
6
|
+
import { BaseCommand } from "../base.js";
|
|
7
|
+
const flagArrayToParam = (cmd, values) => values
|
|
8
|
+
.map(_ => _.split("="))
|
|
9
|
+
.map(([k, v]) => ({ [`${cmd}.${k}`]: v }))
|
|
10
|
+
.reduce((a, b) => ({ ...a, ...b }), {});
|
|
11
|
+
export default class RecordsList extends BaseCommand {
|
|
12
|
+
static args = {
|
|
13
|
+
"uri": Args.string({ description: "uri of type" }),
|
|
14
|
+
};
|
|
15
|
+
static description = "list records";
|
|
16
|
+
static examples = [
|
|
17
|
+
"<%= config.bin %> <%= command.id %> native-object:my-type",
|
|
18
|
+
"<%= config.bin %> <%= command.id %> --type my-type",
|
|
19
|
+
"<%= config.bin %> <%= command.id %> --type my-type --order-by field1:desc",
|
|
20
|
+
"<%= config.bin %> <%= command.id %> --type my-type -s field1=value1 -s field2=value2 --include-total",
|
|
21
|
+
];
|
|
22
|
+
static flags = {
|
|
23
|
+
"exact-search": Flags.string({
|
|
24
|
+
char: "S",
|
|
25
|
+
description: "search fields exactly",
|
|
26
|
+
multiple: true,
|
|
27
|
+
}),
|
|
28
|
+
export: Flags.boolean({
|
|
29
|
+
allowNo: false,
|
|
30
|
+
char: "e",
|
|
31
|
+
description: "export data as JSONL",
|
|
32
|
+
}),
|
|
33
|
+
from: Flags.string({
|
|
34
|
+
char: "f",
|
|
35
|
+
description: "search from",
|
|
36
|
+
multiple: true,
|
|
37
|
+
}),
|
|
38
|
+
"include-total": Flags.boolean({
|
|
39
|
+
allowNo: false,
|
|
40
|
+
description: "include total count",
|
|
41
|
+
}),
|
|
42
|
+
"order-by": Flags.string({
|
|
43
|
+
char: "o",
|
|
44
|
+
description: "order fields",
|
|
45
|
+
multiple: true,
|
|
46
|
+
}),
|
|
47
|
+
"page-size": Flags.integer({
|
|
48
|
+
description: "number of records per page",
|
|
49
|
+
max: 250,
|
|
50
|
+
min: 0,
|
|
51
|
+
}),
|
|
52
|
+
"page-token": Flags.string({
|
|
53
|
+
description: "page token to fetch",
|
|
54
|
+
}),
|
|
55
|
+
progress: Flags.boolean({
|
|
56
|
+
allowNo: false,
|
|
57
|
+
char: "p",
|
|
58
|
+
description: "show progress during export",
|
|
59
|
+
}),
|
|
60
|
+
search: Flags.string({
|
|
61
|
+
char: "s",
|
|
62
|
+
description: "search fields",
|
|
63
|
+
multiple: true,
|
|
64
|
+
}),
|
|
65
|
+
to: Flags.string({
|
|
66
|
+
char: "t",
|
|
67
|
+
description: "search to",
|
|
68
|
+
multiple: true,
|
|
69
|
+
}),
|
|
70
|
+
type: Flags.string({
|
|
71
|
+
char: "T",
|
|
72
|
+
description: "type",
|
|
73
|
+
}),
|
|
74
|
+
};
|
|
75
|
+
async run() {
|
|
76
|
+
const { uri } = this.args;
|
|
77
|
+
const { type: flagType } = this.flags;
|
|
78
|
+
let type = flagType;
|
|
79
|
+
if (uri) {
|
|
80
|
+
const { type: uriType } = parseUri(uri);
|
|
81
|
+
type = uriType;
|
|
82
|
+
}
|
|
83
|
+
if (!type) {
|
|
84
|
+
throw new Error("Type not provided");
|
|
85
|
+
}
|
|
86
|
+
const params = {
|
|
87
|
+
...(this.flags["page-size"] && { pageSize: this.flags["page-size"] }),
|
|
88
|
+
...(this.flags["page-token"] && { pageToken: this.flags["page-token"] }),
|
|
89
|
+
...(this.flags["include-total"] && { includeTotal: true }),
|
|
90
|
+
...(this.flags["order-by"] && { orderBy: this.flags["order-by"] }),
|
|
91
|
+
...flagArrayToParam("search", this.flags.search ?? []),
|
|
92
|
+
...flagArrayToParam("exactSearch", this.flags["exact-search"] ?? []),
|
|
93
|
+
...flagArrayToParam("from", this.flags.from ?? []),
|
|
94
|
+
...flagArrayToParam("to", this.flags.to ?? []),
|
|
95
|
+
};
|
|
96
|
+
const list = (params) => this.fetch(({ silo, tenantId }) => getNativeObjectApiEndpoint(tenantId, silo) + `/api/v1/$page/${type}`, {
|
|
97
|
+
body: JSON.stringify(params),
|
|
98
|
+
headers: {
|
|
99
|
+
"content-type": "application/json",
|
|
100
|
+
},
|
|
101
|
+
method: "POST",
|
|
102
|
+
});
|
|
103
|
+
if (this.flags.export) {
|
|
104
|
+
const pageSize = this.flags["page-size"] ?? 250;
|
|
105
|
+
params.pageSize = pageSize;
|
|
106
|
+
params.includeTotal = true;
|
|
107
|
+
const start = startTime();
|
|
108
|
+
let page = 1;
|
|
109
|
+
let nextPageToken;
|
|
110
|
+
let totalCount = 1;
|
|
111
|
+
do {
|
|
112
|
+
if (nextPageToken) {
|
|
113
|
+
params.pageToken = nextPageToken;
|
|
114
|
+
}
|
|
115
|
+
const xStart = startTime();
|
|
116
|
+
// eslint-disable-next-line no-await-in-loop
|
|
117
|
+
const x = await list(params);
|
|
118
|
+
const xDuration = endTime(xStart);
|
|
119
|
+
if (x.totalCount) {
|
|
120
|
+
totalCount = x.totalCount;
|
|
121
|
+
}
|
|
122
|
+
x.items
|
|
123
|
+
.map(_ => JSON.stringify(_))
|
|
124
|
+
// eslint-disable-next-line unicorn/no-array-for-each
|
|
125
|
+
.forEach(_ => this.log(_));
|
|
126
|
+
nextPageToken = x.nextPageToken;
|
|
127
|
+
if (this.flags.progress) {
|
|
128
|
+
const duration = endTime(start);
|
|
129
|
+
const totalPages = Math.ceil(totalCount / pageSize);
|
|
130
|
+
const recsPerSec = Math.ceil((page * pageSize) / (duration * 1000));
|
|
131
|
+
const eta = (((duration / page) * (totalPages - page)) / 1000).toFixed(2);
|
|
132
|
+
process.stderr.write(`\r\u001B[Kexporting ${type} eta: ${eta}s totalCount: ${totalCount} page: ${page}/${totalPages} records/s: ${recsPerSec} lastCall: ${xDuration.toFixed(2)}ms`);
|
|
133
|
+
}
|
|
134
|
+
page++;
|
|
135
|
+
} while (nextPageToken);
|
|
136
|
+
if (this.flags.progress) {
|
|
137
|
+
process.stderr.write("\n");
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
const rv = await list(params);
|
|
142
|
+
this.logJson(rv);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { BaseCommand } from "../base.js";
|
|
2
|
+
export default class RecordsQuery extends BaseCommand<typeof RecordsQuery> {
|
|
3
|
+
static args: {
|
|
4
|
+
uri: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
5
|
+
};
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
export: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
"include-total": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
"order-by": import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
"page-size": import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
"page-token": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
progress: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
|
+
"query-file": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
type: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
|
+
};
|
|
18
|
+
run(): Promise<void>;
|
|
19
|
+
}
|