@contextual-io/cli 0.1.1 → 0.1.3

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.
Files changed (55) hide show
  1. package/README.md +456 -1
  2. package/dist/commands/base.d.ts +41 -0
  3. package/dist/commands/base.js +164 -0
  4. package/dist/commands/config/add.d.ts +13 -0
  5. package/dist/commands/config/add.js +34 -0
  6. package/dist/commands/config/current.d.ts +10 -0
  7. package/dist/commands/config/current.js +15 -0
  8. package/dist/commands/config/delete.d.ts +10 -0
  9. package/dist/commands/config/delete.js +17 -0
  10. package/dist/commands/config/get.d.ts +12 -0
  11. package/dist/commands/config/get.js +25 -0
  12. package/dist/commands/config/list.d.ts +13 -0
  13. package/dist/commands/config/list.js +33 -0
  14. package/dist/commands/config/login.d.ts +8 -0
  15. package/dist/commands/config/login.js +21 -0
  16. package/dist/commands/config/use.d.ts +10 -0
  17. package/dist/commands/config/use.js +17 -0
  18. package/dist/commands/records/add.d.ts +14 -0
  19. package/dist/commands/records/add.js +73 -0
  20. package/dist/commands/records/delete.d.ts +13 -0
  21. package/dist/commands/records/delete.js +55 -0
  22. package/dist/commands/records/get.d.ts +13 -0
  23. package/dist/commands/records/get.js +53 -0
  24. package/dist/commands/records/list.d.ts +22 -0
  25. package/dist/commands/records/list.js +145 -0
  26. package/dist/commands/records/query.d.ts +19 -0
  27. package/dist/commands/records/query.js +134 -0
  28. package/dist/commands/records/replace.d.ts +14 -0
  29. package/dist/commands/records/replace.js +69 -0
  30. package/dist/index.d.ts +1 -0
  31. package/dist/index.js +1 -0
  32. package/dist/models/cli-configuration.d.ts +9 -0
  33. package/dist/models/cli-configuration.js +8 -0
  34. package/dist/models/errors.d.ts +5 -0
  35. package/dist/models/errors.js +14 -0
  36. package/dist/models/silo.d.ts +7 -0
  37. package/dist/models/silo.js +2 -0
  38. package/dist/models/uri.d.ts +7 -0
  39. package/dist/models/uri.js +7 -0
  40. package/dist/models/url-safe-id.d.ts +3 -0
  41. package/dist/models/url-safe-id.js +4 -0
  42. package/dist/models/user-config.d.ts +54 -0
  43. package/dist/models/user-config.js +24 -0
  44. package/dist/utils/auth.d.ts +6 -0
  45. package/dist/utils/auth.js +101 -0
  46. package/dist/utils/cli-configuration.d.ts +3 -0
  47. package/dist/utils/cli-configuration.js +19 -0
  48. package/dist/utils/endpoints.d.ts +3 -0
  49. package/dist/utils/endpoints.js +2 -0
  50. package/dist/utils/stream.d.ts +3 -0
  51. package/dist/utils/stream.js +21 -0
  52. package/dist/utils/time.d.ts +2 -0
  53. package/dist/utils/time.js +5 -0
  54. package/oclif.manifest.json +740 -2
  55. package/package.json +1 -1
@@ -0,0 +1,134 @@
1
+ import { Args, Flags } from "@oclif/core";
2
+ import fs, { createReadStream } from "node:fs";
3
+ import path from "node:path";
4
+ import { parseUri } from "../../models/uri.js";
5
+ import { getNativeObjectApiEndpoint } from "../../utils/endpoints.js";
6
+ import { readStreamToEnd } from "../../utils/stream.js";
7
+ import { endTime, startTime } from "../../utils/time.js";
8
+ import { BaseCommand } from "../base.js";
9
+ export default class RecordsQuery extends BaseCommand {
10
+ static args = {
11
+ "uri": Args.string({ description: "uri of type" }),
12
+ };
13
+ static description = "query records";
14
+ static examples = [
15
+ "<%= config.bin %> <%= command.id %> native-object:my-type",
16
+ "<%= config.bin %> <%= command.id %> --type my-type --query-file query.json",
17
+ "<%= config.bin %> <%= command.id %> --type my-type --order-by field1:desc --query-file query.json",
18
+ "<%= config.bin %> <%= command.id %> --type my-type --include-total --query-file query.json",
19
+ ];
20
+ static flags = {
21
+ export: Flags.boolean({
22
+ allowNo: false,
23
+ char: "e",
24
+ description: "export data as JSONL",
25
+ }),
26
+ "include-total": Flags.boolean({
27
+ allowNo: false,
28
+ description: "include total count",
29
+ }),
30
+ "order-by": Flags.string({
31
+ char: "o",
32
+ description: "order fields",
33
+ multiple: true,
34
+ }),
35
+ "page-size": Flags.integer({
36
+ description: "number of records per page",
37
+ max: 250,
38
+ min: 0,
39
+ }),
40
+ "page-token": Flags.string({
41
+ description: "page token to fetch",
42
+ }),
43
+ progress: Flags.boolean({
44
+ allowNo: false,
45
+ char: "p",
46
+ description: "show progress during export",
47
+ }),
48
+ "query-file": Flags.file({
49
+ char: "q",
50
+ default: "-",
51
+ description: "file to read. can read stdin if value is '-'",
52
+ }),
53
+ type: Flags.string({
54
+ char: "T",
55
+ description: "type",
56
+ }),
57
+ };
58
+ async run() {
59
+ const { uri } = this.args;
60
+ const { type: flagType } = this.flags;
61
+ let type = flagType;
62
+ if (uri) {
63
+ const { type: uriType } = parseUri(uri);
64
+ type = uriType;
65
+ }
66
+ if (!type) {
67
+ throw new Error("Type not provided");
68
+ }
69
+ const queryFile = this.flags["query-file"] === "-"
70
+ ? "-"
71
+ : path.resolve(this.flags["query-file"]);
72
+ if (queryFile && queryFile !== "-" && !fs.existsSync(queryFile)) {
73
+ throw new Error("File does not exist");
74
+ }
75
+ const query = JSON.parse((await readStreamToEnd(queryFile && queryFile !== "-"
76
+ ? createReadStream(queryFile)
77
+ : process.stdin)).join(""));
78
+ const params = {
79
+ query,
80
+ ...(this.flags["page-size"] && { pageSize: this.flags["page-size"] }),
81
+ ...(this.flags["page-token"] && { pageToken: this.flags["page-token"] }),
82
+ ...(this.flags["include-total"] && { includeTotal: true }),
83
+ ...(this.flags["order-by"] && { orderBy: this.flags["order-by"] }),
84
+ };
85
+ const runQuery = (params) => this.fetch(({ silo, tenantId }) => getNativeObjectApiEndpoint(tenantId, silo) + `/api/v1/$query/${type}`, {
86
+ body: JSON.stringify(params),
87
+ headers: {
88
+ "content-type": "application/json",
89
+ },
90
+ method: "POST",
91
+ });
92
+ if (this.flags.export) {
93
+ const pageSize = this.flags["page-size"] ?? 250;
94
+ params.pageSize = pageSize;
95
+ params.includeTotal = true;
96
+ const start = startTime();
97
+ let page = 1;
98
+ let nextPageToken;
99
+ let totalCount = 1;
100
+ do {
101
+ if (nextPageToken) {
102
+ params.pageToken = nextPageToken;
103
+ }
104
+ const xStart = startTime();
105
+ // eslint-disable-next-line no-await-in-loop
106
+ const x = await runQuery(params);
107
+ const xDuration = endTime(xStart);
108
+ if (x.totalCount) {
109
+ totalCount = x.totalCount;
110
+ }
111
+ x.items
112
+ .map(_ => JSON.stringify(_))
113
+ // eslint-disable-next-line unicorn/no-array-for-each
114
+ .forEach(_ => this.log(_));
115
+ nextPageToken = x.nextPageToken;
116
+ if (this.flags.progress) {
117
+ const duration = endTime(start);
118
+ const totalPages = Math.ceil(totalCount / pageSize);
119
+ const recsPerSec = Math.ceil((page * pageSize) / (duration * 1000));
120
+ const eta = (((duration / page) * (totalPages - page)) / 1000).toFixed(2);
121
+ process.stderr.write(`\r\u001B[Kexporting ${type} eta: ${eta}s totalCount: ${totalCount} page: ${page}/${totalPages} records/s: ${recsPerSec} lastCall: ${xDuration.toFixed(2)}ms`);
122
+ }
123
+ page++;
124
+ } while (nextPageToken);
125
+ if (this.flags.progress) {
126
+ process.stderr.write("\n");
127
+ }
128
+ }
129
+ else {
130
+ const rv = await runQuery(params);
131
+ this.logJson(rv);
132
+ }
133
+ }
134
+ }
@@ -0,0 +1,14 @@
1
+ import { BaseCommand } from "../base.js";
2
+ export default class RecordsReplace extends BaseCommand<typeof RecordsReplace> {
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
+ "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,69 @@
1
+ import { Args, Flags } from "@oclif/core";
2
+ import fs, { createReadStream } from "node:fs";
3
+ import path from "node:path";
4
+ import { parseUri } from "../../models/uri.js";
5
+ import { getNativeObjectApiEndpoint } from "../../utils/endpoints.js";
6
+ import { readStreamToEnd } from "../../utils/stream.js";
7
+ import { BaseCommand } from "../base.js";
8
+ export default class RecordsReplace extends BaseCommand {
9
+ static args = {
10
+ "uri": Args.string({ description: "uri of record" }),
11
+ };
12
+ static description = "replace a record";
13
+ static examples = [
14
+ "<%= config.bin %> <%= command.id %> native-object:my-type/instance-1 --input-file record.json",
15
+ "<%= config.bin %> <%= command.id %> native-object:my-type --id instance-1 --input-file record.json",
16
+ "<%= config.bin %> <%= command.id %> --type my-type --id instance-1 --input-file record.json",
17
+ ];
18
+ static flags = {
19
+ id: Flags.string({
20
+ char: "i",
21
+ description: "id",
22
+ }),
23
+ "input-file": Flags.file({
24
+ char: "i",
25
+ default: "-",
26
+ description: "file to read. can read stdin if value is '-'",
27
+ }),
28
+ type: Flags.string({
29
+ char: "T",
30
+ description: "type",
31
+ }),
32
+ };
33
+ async run() {
34
+ const { uri } = this.args;
35
+ const { id: flagId, type: flagType } = this.flags;
36
+ let type = flagType;
37
+ let lookup = flagId;
38
+ if (uri) {
39
+ const { id, type: uriType } = parseUri(uri);
40
+ type = uriType;
41
+ if (id) {
42
+ lookup = id;
43
+ }
44
+ }
45
+ if (!type) {
46
+ throw new Error("Type not provided");
47
+ }
48
+ if (!lookup) {
49
+ throw new Error("Id not provided");
50
+ }
51
+ const inputFile = this.flags["input-file"] === "-"
52
+ ? "-"
53
+ : path.resolve(this.flags["input-file"]);
54
+ if (inputFile && inputFile !== "-" && !fs.existsSync(inputFile)) {
55
+ throw new Error("File does not exist");
56
+ }
57
+ const input = (await readStreamToEnd(inputFile && inputFile !== "-"
58
+ ? createReadStream(inputFile)
59
+ : process.stdin)).join("");
60
+ const replace = (body) => this.fetch(({ silo, tenantId }) => getNativeObjectApiEndpoint(tenantId, silo) + `/api/v1/${type}/${lookup}`, {
61
+ body,
62
+ headers: {
63
+ "content-type": "application/json",
64
+ },
65
+ method: "PUT",
66
+ });
67
+ this.logJson(await replace(input));
68
+ }
69
+ }
@@ -0,0 +1 @@
1
+ export { run } from "@oclif/core";
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export { run } from "@oclif/core";
@@ -0,0 +1,9 @@
1
+ import { z } from "zod";
2
+ export declare const CliConfiguration: z.ZodObject<{
3
+ auth: z.ZodObject<{
4
+ audience: z.ZodString;
5
+ clientId: z.ZodString;
6
+ domain: z.ZodString;
7
+ }, z.core.$strip>;
8
+ }, z.core.$strip>;
9
+ export type CliConfiguration = z.infer<typeof CliConfiguration>;
@@ -0,0 +1,8 @@
1
+ import { z } from "zod";
2
+ export const CliConfiguration = z.object({
3
+ auth: z.object({
4
+ audience: z.string(),
5
+ clientId: z.string(),
6
+ domain: z.string(),
7
+ }),
8
+ });
@@ -0,0 +1,5 @@
1
+ export declare class HttpError extends Error {
2
+ readonly response: unknown;
3
+ readonly status: number;
4
+ constructor(message: string, response: unknown, status: number);
5
+ }
@@ -0,0 +1,14 @@
1
+ export class HttpError extends Error {
2
+ response;
3
+ status;
4
+ constructor(message, response, status) {
5
+ const msg = [
6
+ message,
7
+ `status ${status}`,
8
+ typeof response === "string" ? response : JSON.stringify(response, null, 2),
9
+ ].join("\n");
10
+ super(msg);
11
+ this.response = response;
12
+ this.status = status;
13
+ }
14
+ }
@@ -0,0 +1,7 @@
1
+ import { z } from "zod";
2
+ export declare const Silo: z.ZodEnum<{
3
+ prod: "prod";
4
+ qa: "qa";
5
+ dev: "dev";
6
+ }>;
7
+ export type Silo = z.infer<typeof Silo>;
@@ -0,0 +1,2 @@
1
+ import { z } from "zod";
2
+ export const Silo = z.enum(["prod", "qa", "dev"]);
@@ -0,0 +1,7 @@
1
+ import { z } from "zod";
2
+ export declare const Uri: z.ZodString;
3
+ export type Uri = z.infer<typeof Uri>;
4
+ export declare const parseUri: (uri: string) => {
5
+ id?: string;
6
+ type: string;
7
+ };
@@ -0,0 +1,7 @@
1
+ import { z } from "zod";
2
+ export const Uri = z.string().regex(/^native-object:[a-z0-9-]+(\/.+)?/);
3
+ export const parseUri = (uri) => {
4
+ const parsed = Uri.parse(uri);
5
+ const [type, id] = parsed.replace(/^native-object:/, "").split("/");
6
+ return { id, type };
7
+ };
@@ -0,0 +1,3 @@
1
+ import { z } from "zod";
2
+ export declare const UrlSafeId: z.ZodString;
3
+ export type UrlSafeId = z.infer<typeof UrlSafeId>;
@@ -0,0 +1,4 @@
1
+ import { z } from "zod";
2
+ export const UrlSafeId = z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, {
3
+ message: "this field must begin with a lowercase alphanumeric character, and can only contain lowercase alphanumeric characters and dashes",
4
+ });
@@ -0,0 +1,54 @@
1
+ import { z } from "zod";
2
+ export declare const AuthConfig: z.ZodObject<{
3
+ bearerToken: z.ZodString;
4
+ expiresAt: z.ZodString;
5
+ refreshToken: z.ZodOptional<z.ZodString>;
6
+ }, z.core.$strip>;
7
+ export type AuthConfig = z.infer<typeof AuthConfig>;
8
+ export declare const Config: z.ZodObject<{
9
+ silo: z.ZodEnum<{
10
+ prod: "prod";
11
+ qa: "qa";
12
+ dev: "dev";
13
+ }>;
14
+ tenantId: z.ZodString;
15
+ auth: z.ZodObject<{
16
+ audience: z.ZodString;
17
+ clientId: z.ZodString;
18
+ domain: z.ZodString;
19
+ }, z.core.$strip>;
20
+ bearerToken: z.ZodOptional<z.ZodString>;
21
+ expiresAt: z.ZodOptional<z.ZodString>;
22
+ refreshToken: z.ZodOptional<z.ZodOptional<z.ZodString>>;
23
+ }, z.core.$strip>;
24
+ export type Config = z.infer<typeof Config>;
25
+ export declare const CleanConfig: z.ZodObject<{
26
+ silo: z.ZodEnum<{
27
+ prod: "prod";
28
+ qa: "qa";
29
+ dev: "dev";
30
+ }>;
31
+ tenantId: z.ZodString;
32
+ configId: z.ZodString;
33
+ }, z.core.$strip>;
34
+ export type CleanConfig = z.infer<typeof CleanConfig>;
35
+ export declare const UserConfig: z.ZodObject<{
36
+ configs: z.ZodRecord<z.ZodString, z.ZodObject<{
37
+ silo: z.ZodEnum<{
38
+ prod: "prod";
39
+ qa: "qa";
40
+ dev: "dev";
41
+ }>;
42
+ tenantId: z.ZodString;
43
+ auth: z.ZodObject<{
44
+ audience: z.ZodString;
45
+ clientId: z.ZodString;
46
+ domain: z.ZodString;
47
+ }, z.core.$strip>;
48
+ bearerToken: z.ZodOptional<z.ZodString>;
49
+ expiresAt: z.ZodOptional<z.ZodString>;
50
+ refreshToken: z.ZodOptional<z.ZodOptional<z.ZodString>>;
51
+ }, z.core.$strip>>;
52
+ current: z.ZodOptional<z.ZodString>;
53
+ }, z.core.$strip>;
54
+ export type UserConfig = z.infer<typeof UserConfig>;
@@ -0,0 +1,24 @@
1
+ import { z } from "zod";
2
+ import { CliConfiguration } from "./cli-configuration.js";
3
+ import { Silo } from "./silo.js";
4
+ import { UrlSafeId } from "./url-safe-id.js";
5
+ export const AuthConfig = z.object({
6
+ bearerToken: z.string(),
7
+ expiresAt: z.string(),
8
+ refreshToken: z.string().optional(),
9
+ });
10
+ export const Config = z.object({
11
+ silo: Silo,
12
+ tenantId: UrlSafeId,
13
+ }).extend(CliConfiguration.shape)
14
+ .extend(AuthConfig.partial().shape);
15
+ export const CleanConfig = Config.pick({
16
+ silo: true,
17
+ tenantId: true,
18
+ }).extend({
19
+ configId: z.string(),
20
+ });
21
+ export const UserConfig = z.object({
22
+ configs: z.record(UrlSafeId, Config),
23
+ current: UrlSafeId.optional(),
24
+ });
@@ -0,0 +1,6 @@
1
+ import { CliConfiguration } from "../models/cli-configuration.js";
2
+ import { Silo } from "../models/silo.js";
3
+ import { AuthConfig } from "../models/user-config.js";
4
+ export declare const codeExchange: ({ audience, clientId, domain }: CliConfiguration["auth"]) => Promise<AuthConfig>;
5
+ export declare const rehydrateToken: ({ clientId, domain }: CliConfiguration["auth"], refreshToken: string) => Promise<AuthConfig>;
6
+ export declare const getUserProfile: (tenantId: string, silo: Silo, bearerToken: string) => Promise<any>;
@@ -0,0 +1,101 @@
1
+ /* eslint-disable camelcase */
2
+ import fetch from "cross-fetch";
3
+ import open from "open";
4
+ import { z } from "zod";
5
+ import { AuthConfig } from "../models/user-config.js";
6
+ import { getAuthApiEndpoint } from "./endpoints.js";
7
+ const scope = "offline_access openid";
8
+ const TokenResponse = z.object({
9
+ access_token: z.string(),
10
+ expires_in: z.number(),
11
+ refresh_token: z.string().optional(),
12
+ });
13
+ const parseTokenResponse = (tokenJson) => {
14
+ const { access_token, expires_in, refresh_token } = TokenResponse.parse(tokenJson);
15
+ const expiresAt = new Date();
16
+ expiresAt.setUTCSeconds(expiresAt.getUTCSeconds() + expires_in);
17
+ return AuthConfig.parse({
18
+ bearerToken: access_token,
19
+ expiresAt: expiresAt.toISOString(),
20
+ refreshToken: refresh_token,
21
+ });
22
+ };
23
+ export const codeExchange = async ({ audience, clientId, domain }) => {
24
+ const authEndpoint = `https://${domain}`;
25
+ const codeRsp = await fetch(`${authEndpoint}/oauth/device/code`, {
26
+ body: new URLSearchParams({
27
+ audience,
28
+ client_id: clientId,
29
+ scope,
30
+ }).toString(),
31
+ headers: {
32
+ "content-type": "application/x-www-form-urlencoded",
33
+ },
34
+ method: "POST",
35
+ });
36
+ const codeJson = await codeRsp.json();
37
+ const { device_code, interval, verification_uri_complete } = codeJson;
38
+ console.log("We've launched your web browser to complete the login process.");
39
+ console.log("Verification code: %s", device_code);
40
+ console.log();
41
+ console.log("Waiting for login to complete...");
42
+ await open(`${verification_uri_complete}&audience=${audience}`);
43
+ while (true) {
44
+ // eslint-disable-next-line no-await-in-loop
45
+ const tokenRsp = await fetch(`${authEndpoint}/oauth/token`, {
46
+ body: new URLSearchParams({
47
+ audience,
48
+ client_id: clientId,
49
+ device_code,
50
+ grant_type: "urn:ietf:params:oauth:grant-type:device_code",
51
+ }),
52
+ headers: {
53
+ "content-type": "application/x-www-form-urlencoded",
54
+ },
55
+ method: "POST",
56
+ });
57
+ // eslint-disable-next-line no-await-in-loop
58
+ const tokenJson = await tokenRsp.json();
59
+ if ("error" in tokenJson) {
60
+ switch (tokenJson.error) {
61
+ case "authorization_pending": {
62
+ break;
63
+ }
64
+ default: {
65
+ console.log("error", tokenJson);
66
+ }
67
+ }
68
+ // eslint-disable-next-line no-await-in-loop
69
+ await new Promise(resolve => { setTimeout(resolve, interval * 1000); });
70
+ }
71
+ else {
72
+ const rv = parseTokenResponse(tokenJson);
73
+ return rv;
74
+ }
75
+ }
76
+ };
77
+ export const rehydrateToken = async ({ clientId, domain }, refreshToken) => {
78
+ const refreshRsp = await fetch(`https://${domain}/oauth/token`, {
79
+ body: new URLSearchParams({
80
+ client_id: clientId,
81
+ grant_type: "refresh_token",
82
+ refresh_token: refreshToken,
83
+ scope,
84
+ }).toString(),
85
+ headers: {
86
+ "content-type": "application/x-www-form-urlencoded",
87
+ },
88
+ method: "POST",
89
+ });
90
+ const tokenJson = await refreshRsp.json();
91
+ return parseTokenResponse(tokenJson);
92
+ };
93
+ export const getUserProfile = async (tenantId, silo, bearerToken) => {
94
+ const rsp = await fetch(getAuthApiEndpoint(tenantId, silo) + "/api/v1/me/profile", {
95
+ headers: {
96
+ authorization: `Bearer ${bearerToken}`,
97
+ },
98
+ method: "GET",
99
+ });
100
+ return rsp.json();
101
+ };
@@ -0,0 +1,3 @@
1
+ import { CliConfiguration } from "../models/cli-configuration.js";
2
+ import { Silo } from "../models/silo.js";
3
+ export declare const getCliConfiguration: (tenantId: string, silo: Silo) => Promise<CliConfiguration>;
@@ -0,0 +1,19 @@
1
+ import fetch from "cross-fetch";
2
+ import { CliConfiguration } from "../models/cli-configuration.js";
3
+ import { getNativeObjectApiEndpoint } from "./endpoints.js";
4
+ export const getCliConfiguration = async (tenantId, silo) => {
5
+ const url = getNativeObjectApiEndpoint(tenantId, silo) + "/.well-known/cli-configuration";
6
+ let rsp;
7
+ try {
8
+ rsp = await fetch(url, {
9
+ method: "GET",
10
+ });
11
+ if (!rsp.ok)
12
+ throw new Error("not ok");
13
+ }
14
+ catch {
15
+ throw new Error(`unable to fetch cli configuration: ${JSON.stringify({ silo, tenantId })}`);
16
+ }
17
+ const val = await rsp.json();
18
+ return CliConfiguration.parse(val);
19
+ };
@@ -0,0 +1,3 @@
1
+ import { Silo } from "../models/silo.js";
2
+ export declare const getNativeObjectApiEndpoint: (tenantId: string, silo: Silo) => string;
3
+ export declare const getAuthApiEndpoint: (tenantId: string, silo: Silo) => string;
@@ -0,0 +1,2 @@
1
+ export const getNativeObjectApiEndpoint = (tenantId, silo) => `https://native-object.${tenantId}.my${silo === "prod" ? "" : `.${silo}`}.contextual.io`;
2
+ export const getAuthApiEndpoint = (tenantId, silo) => `https://auth.${tenantId}.my${silo === "prod" ? "" : `.${silo}`}.contextual.io`;
@@ -0,0 +1,3 @@
1
+ import { Readable, Transform } from "node:stream";
2
+ export declare const readStreamToEnd: <T = unknown>(stream: Readable) => Promise<T[]>;
3
+ export declare const mapStream: <I, O = I>(fn: (t: I) => Promise<O>) => Transform;
@@ -0,0 +1,21 @@
1
+ import { Transform } from "node:stream";
2
+ export const readStreamToEnd = (stream) => {
3
+ const chunks = [];
4
+ return new Promise((resolve, reject) => {
5
+ stream.on("data", chunk => chunks.push(chunk));
6
+ stream.on("error", err => reject(err));
7
+ stream.on("end", () => resolve(chunks));
8
+ });
9
+ };
10
+ export const mapStream = (fn) => new Transform({
11
+ objectMode: true,
12
+ async transform(chunk, _, callback) {
13
+ try {
14
+ const xxx = fn(chunk);
15
+ callback(null, (xxx instanceof Promise) ? await xxx : xxx);
16
+ }
17
+ catch (error) {
18
+ callback(error instanceof Error ? error : new Error(`${error}`));
19
+ }
20
+ },
21
+ });
@@ -0,0 +1,2 @@
1
+ export declare const startTime: () => [number, number];
2
+ export declare const endTime: (t: [number, number]) => number;
@@ -0,0 +1,5 @@
1
+ export const startTime = () => process.hrtime();
2
+ export const endTime = (t) => {
3
+ const time = process.hrtime(t);
4
+ return time[0] * 1e3 + time[1] / 1e6;
5
+ };