jitsu-cli 1.10.4 → 2.14.0-beta.101
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/bin/jitsu +3 -0
- package/build.mts +39 -0
- package/compiled/package.json +26 -29
- package/compiled/src/commands/build.js +43 -55
- package/compiled/src/commands/config/handlers.js +292 -0
- package/compiled/src/commands/config/index.js +148 -0
- package/compiled/src/commands/config/resources.js +88 -0
- package/compiled/src/commands/default-workspace.js +39 -0
- package/compiled/src/commands/deploy.js +90 -58
- package/compiled/src/commands/init.js +17 -21
- package/compiled/src/commands/login.js +24 -27
- package/compiled/src/commands/shared.js +12 -17
- package/compiled/src/commands/spec.js +31 -0
- package/compiled/src/commands/test.js +7 -10
- package/compiled/src/commands/whoami.js +8 -12
- package/compiled/src/index.js +39 -23
- package/compiled/src/lib/api-client.js +52 -0
- package/compiled/src/lib/auth-file.js +67 -0
- package/compiled/src/lib/body-builder.js +53 -0
- package/compiled/src/lib/body-fields.js +47 -0
- package/compiled/src/lib/chalk-code-highlight.js +15 -20
- package/compiled/src/lib/compiled-function.js +27 -29
- package/compiled/src/lib/dotted.js +34 -0
- package/compiled/src/lib/indent.js +3 -8
- package/compiled/src/lib/renderer.js +33 -0
- package/compiled/src/lib/spec.js +11 -0
- package/compiled/src/lib/template.js +7 -11
- package/compiled/src/lib/version.js +13 -20
- package/compiled/src/templates/functions.js +13 -18
- package/dist/main.js +45727 -86292
- package/dist/main.js.map +7 -1
- package/package.json +26 -29
- package/src/commands/build.ts +22 -27
- package/src/commands/config/handlers.ts +339 -0
- package/src/commands/config/index.ts +171 -0
- package/src/commands/config/resources.ts +110 -0
- package/src/commands/default-workspace.ts +44 -0
- package/src/commands/deploy.ts +96 -20
- package/src/commands/login.ts +3 -1
- package/src/commands/spec.ts +32 -0
- package/src/index.ts +34 -17
- package/src/lib/api-client.ts +64 -0
- package/src/lib/auth-file.ts +83 -0
- package/src/lib/body-builder.ts +68 -0
- package/src/lib/body-fields.ts +61 -0
- package/src/lib/compiled-function.ts +30 -23
- package/src/lib/dotted.ts +43 -0
- package/src/lib/renderer.ts +44 -0
- package/src/lib/spec.ts +32 -0
- package/tsconfig.json +2 -19
- package/.turbo/turbo-build.log +0 -28
- package/.turbo/turbo-clean.log +0 -5
- package/babel.config.cjs +0 -4
- package/dist/140.js +0 -452
- package/dist/140.js.map +0 -1
- package/dist/233.js +0 -4890
- package/dist/233.js.map +0 -1
- package/dist/445e7f36f8a19c2bf682.js +0 -900
- package/webpack.config.js +0 -49
|
@@ -1,24 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const fs_1 = require("fs");
|
|
9
|
-
const os_1 = require("os");
|
|
10
|
-
const readline_1 = tslib_1.__importDefault(require("readline"));
|
|
11
|
-
const chalk_code_highlight_1 = require("../lib/chalk-code-highlight");
|
|
12
|
-
const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
|
|
1
|
+
import { decrypt, randomId } from "juava";
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import { mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
4
|
+
import { homedir } from "os";
|
|
5
|
+
import readline from "readline";
|
|
6
|
+
import { b, red } from "../lib/chalk-code-highlight";
|
|
7
|
+
import inquirer from "inquirer";
|
|
13
8
|
const origin = "jitsu-cli";
|
|
14
|
-
async function logout({ force }) {
|
|
15
|
-
const jitsuFile = `${
|
|
9
|
+
export async function logout({ force }) {
|
|
10
|
+
const jitsuFile = `${homedir()}/.jitsu/jitsu-cli.json`;
|
|
16
11
|
if (fs.existsSync(jitsuFile)) {
|
|
17
12
|
if (force) {
|
|
18
13
|
fs.unlinkSync(jitsuFile);
|
|
19
14
|
}
|
|
20
15
|
else {
|
|
21
|
-
const { confirm } = await
|
|
16
|
+
const { confirm } = await inquirer.prompt([
|
|
22
17
|
{
|
|
23
18
|
type: "confirm",
|
|
24
19
|
name: "confirm",
|
|
@@ -40,15 +35,17 @@ async function logout({ force }) {
|
|
|
40
35
|
console.log("You are not logged in");
|
|
41
36
|
}
|
|
42
37
|
}
|
|
43
|
-
async function login({ host, apikey, force }) {
|
|
44
|
-
const
|
|
38
|
+
export async function login({ host, apikey, force }) {
|
|
39
|
+
const jitsuDir = `${homedir()}/.jitsu`;
|
|
40
|
+
fs.mkdirSync(jitsuDir, { recursive: true });
|
|
41
|
+
const jitsuFile = `${jitsuDir}/jitsu-cli.json`;
|
|
45
42
|
if (fs.existsSync(jitsuFile) && !force) {
|
|
46
|
-
const loginInfo = JSON.parse(
|
|
47
|
-
console.error(
|
|
43
|
+
const loginInfo = JSON.parse(readFileSync(jitsuFile, { encoding: "utf-8" }));
|
|
44
|
+
console.error(red(`Error: seems like you already logged into jitsu at ${loginInfo.host}. If you want to re-login again, use --force flag, or logout first with \`jitsu-cli logout\` command`));
|
|
48
45
|
process.exit(1);
|
|
49
46
|
}
|
|
50
47
|
if (apikey) {
|
|
51
|
-
|
|
48
|
+
writeFileSync(jitsuFile, JSON.stringify({ host, apikey }, null, 2));
|
|
52
49
|
console.info(`\nSuccess!`);
|
|
53
50
|
return;
|
|
54
51
|
}
|
|
@@ -65,9 +62,9 @@ async function login({ host, apikey, force }) {
|
|
|
65
62
|
url += "/";
|
|
66
63
|
}
|
|
67
64
|
try {
|
|
68
|
-
const c =
|
|
69
|
-
console.log(`Please open this url in your browser and log in:\n\n${
|
|
70
|
-
const rl =
|
|
65
|
+
const c = randomId(32);
|
|
66
|
+
console.log(`Please open this url in your browser and log in:\n\n${b(`${url}?origin=${origin}&c=${c}`)}`);
|
|
67
|
+
const rl = readline.createInterface({
|
|
71
68
|
input: process.stdin,
|
|
72
69
|
output: process.stdout,
|
|
73
70
|
});
|
|
@@ -86,14 +83,14 @@ function processCode(code, key, host) {
|
|
|
86
83
|
try {
|
|
87
84
|
const iv = `${origin}${code.substring(0, 16 - origin.length)}`;
|
|
88
85
|
const enc = code.substring(16 - origin.length);
|
|
89
|
-
const decoded =
|
|
86
|
+
const decoded = decrypt(key, iv, enc);
|
|
90
87
|
const { plaintext, id } = JSON.parse(decoded);
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
mkdirSync(`${homedir()}/.jitsu`, { recursive: true });
|
|
89
|
+
writeFileSync(`${homedir()}/.jitsu/jitsu-cli.json`, JSON.stringify({ host, apikey: `${id}:${plaintext}` }, null, 2));
|
|
93
90
|
console.info(`\nSuccess!`);
|
|
94
91
|
}
|
|
95
92
|
catch (e) {
|
|
96
|
-
console.error(`\n${
|
|
93
|
+
console.error(`\n${red("Incorrect code value")}`);
|
|
97
94
|
process.exit(1);
|
|
98
95
|
}
|
|
99
96
|
}
|
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const path_1 = tslib_1.__importDefault(require("path"));
|
|
7
|
-
const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
|
|
8
|
-
const fs_1 = require("fs");
|
|
9
|
-
const chalk_code_highlight_1 = require("../lib/chalk-code-highlight");
|
|
10
|
-
async function loadPackageJson(projectDir) {
|
|
1
|
+
import path from "path";
|
|
2
|
+
import inquirer from "inquirer";
|
|
3
|
+
import { existsSync, readFileSync } from "fs";
|
|
4
|
+
import { b, red } from "../lib/chalk-code-highlight";
|
|
5
|
+
export async function loadPackageJson(projectDir) {
|
|
11
6
|
let packageJson = loadPackageJson0(projectDir);
|
|
12
7
|
if (!packageJson) {
|
|
13
|
-
projectDir = (await
|
|
8
|
+
projectDir = (await inquirer.prompt([
|
|
14
9
|
{
|
|
15
10
|
type: "input",
|
|
16
11
|
name: "dir",
|
|
@@ -24,15 +19,15 @@ async function loadPackageJson(projectDir) {
|
|
|
24
19
|
}
|
|
25
20
|
return { projectDir, packageJson };
|
|
26
21
|
}
|
|
27
|
-
function loadPackageJson0(projectDir) {
|
|
28
|
-
const packageJsonPath =
|
|
29
|
-
if (!
|
|
30
|
-
console.error(
|
|
22
|
+
export function loadPackageJson0(projectDir) {
|
|
23
|
+
const packageJsonPath = path.resolve(projectDir, "package.json");
|
|
24
|
+
if (!existsSync(packageJsonPath)) {
|
|
25
|
+
console.error(red(`Can't find node.js project in: ${b(projectDir)}`));
|
|
31
26
|
return undefined;
|
|
32
27
|
}
|
|
33
|
-
const packageJson = JSON.parse(
|
|
28
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
34
29
|
if (!packageJson.devDependencies?.["jitsu-cli"]) {
|
|
35
|
-
console.error(
|
|
30
|
+
console.error(red(`directory ${b(projectDir)} doesn't contain jitsu-cli managed project`));
|
|
36
31
|
return undefined;
|
|
37
32
|
}
|
|
38
33
|
return packageJson;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { red } from "../lib/chalk-code-highlight";
|
|
3
|
+
import { normalizeHost, readAuthFile, resolveAuth } from "../lib/auth-file";
|
|
4
|
+
import { fetchSpec } from "../lib/spec";
|
|
5
|
+
import { DEFAULT_OUTPUT, SUPPORTED_OUTPUTS, print } from "../lib/renderer";
|
|
6
|
+
export function buildSpecCommand() {
|
|
7
|
+
return new Command("spec")
|
|
8
|
+
.description("Print the live OpenAPI spec served at /api/spec")
|
|
9
|
+
.option("-o, --output <format>", `Output format: ${SUPPORTED_OUTPUTS.join(", ")}`, DEFAULT_OUTPUT)
|
|
10
|
+
.option("-h, --host <host>", "Jitsu host (overrides ~/.jitsu/jitsu-cli.json)")
|
|
11
|
+
.option("-k, --apikey <api-key>", "API key (overrides ~/.jitsu/jitsu-cli.json)")
|
|
12
|
+
.action(async (opts) => {
|
|
13
|
+
try {
|
|
14
|
+
const auth = (() => {
|
|
15
|
+
try {
|
|
16
|
+
return resolveAuth(opts);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
const host = opts.host ?? readAuthFile()?.host ?? "https://use.jitsu.com";
|
|
20
|
+
return { host: normalizeHost(host), apikey: "anonymous" };
|
|
21
|
+
}
|
|
22
|
+
})();
|
|
23
|
+
const spec = await fetchSpec(auth);
|
|
24
|
+
print(spec, opts.output);
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
console.error(red(`Error: ${e instanceof Error ? e.message : String(e)}`));
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
async function test({ dir }) {
|
|
8
|
-
const { packageJson, projectDir } = await (0, shared_1.loadPackageJson)(dir || process.cwd());
|
|
9
|
-
console.log(`Running tests for ${(0, chalk_code_highlight_1.b)(packageJson.name)}`);
|
|
1
|
+
import { run as jest } from "jest-cli";
|
|
2
|
+
import { loadPackageJson } from "./shared";
|
|
3
|
+
import { b } from "../lib/chalk-code-highlight";
|
|
4
|
+
export async function test({ dir }) {
|
|
5
|
+
const { packageJson, projectDir } = await loadPackageJson(dir || process.cwd());
|
|
6
|
+
console.log(`Running tests for ${b(packageJson.name)}`);
|
|
10
7
|
const jestArgs = ["--passWithNoTests", "--projects", projectDir, "--preset", "ts-jest"];
|
|
11
|
-
await (
|
|
8
|
+
await jest(jestArgs);
|
|
12
9
|
}
|
|
@@ -1,19 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const fs = tslib_1.__importStar(require("fs"));
|
|
7
|
-
const fs_1 = require("fs");
|
|
8
|
-
const chalk_code_highlight_1 = require("../lib/chalk-code-highlight");
|
|
9
|
-
async function whoami({ host, apikey, force }) {
|
|
1
|
+
import { homedir } from "os";
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import { readFileSync } from "fs";
|
|
4
|
+
import { b } from "../lib/chalk-code-highlight";
|
|
5
|
+
export async function whoami({ host, apikey, force }) {
|
|
10
6
|
if (!apikey) {
|
|
11
|
-
const jitsuFile = `${
|
|
7
|
+
const jitsuFile = `${homedir()}/.jitsu/jitsu-cli.json`;
|
|
12
8
|
if (!fs.existsSync(jitsuFile)) {
|
|
13
9
|
console.log("You are not logged in. Log in with `jitsu-cli login` or provide --apikey option");
|
|
14
10
|
return;
|
|
15
11
|
}
|
|
16
|
-
const loginInfo = JSON.parse(
|
|
12
|
+
const loginInfo = JSON.parse(readFileSync(jitsuFile, { encoding: "utf-8" }));
|
|
17
13
|
if (loginInfo.host) {
|
|
18
14
|
host = loginInfo.host;
|
|
19
15
|
}
|
|
@@ -40,5 +36,5 @@ async function whoami({ host, apikey, force }) {
|
|
|
40
36
|
if (!me.auth) {
|
|
41
37
|
console.error(`Login is invalid. Please login once again with \`jitsu-cli login -f\`, or provide a valid --apikey option`);
|
|
42
38
|
}
|
|
43
|
-
console.log(`You are logged in as ${
|
|
39
|
+
console.log(`You are logged in as ${b(me.user.email)} at ${host}. Internal userId: ${b(me.user.internalId)}`);
|
|
44
40
|
}
|
package/compiled/src/index.js
CHANGED
|
@@ -1,44 +1,49 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
import figlet from "figlet";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { login, logout } from "./commands/login";
|
|
4
|
+
import { deploy } from "./commands/deploy";
|
|
5
|
+
import { init } from "./commands/init";
|
|
6
|
+
import { build } from "./commands/build";
|
|
7
|
+
import { test } from "./commands/test";
|
|
8
|
+
import { jitsuCliVersion, jitsuCliPackageName } from "./lib/version";
|
|
9
|
+
import { whoami } from "./commands/whoami";
|
|
10
|
+
import { buildConfigCommand } from "./commands/config";
|
|
11
|
+
import { buildSpecCommand } from "./commands/spec";
|
|
12
|
+
import { setDefaultWorkspace, unsetDefaultWorkspace } from "./commands/default-workspace";
|
|
13
|
+
import { preprocessArgv } from "./lib/body-fields";
|
|
14
|
+
process.argv = preprocessArgv(process.argv);
|
|
15
|
+
const isPipedStdout = !process.stdout.isTTY;
|
|
16
|
+
if (!isPipedStdout) {
|
|
17
|
+
process.stderr.write(figlet.textSync("Jitsu CLI", { horizontalLayout: "full" }) + "\n");
|
|
18
|
+
}
|
|
19
|
+
const p = new Command();
|
|
20
|
+
p.name(jitsuCliPackageName).description("Jitsu CLI — manage workspaces, configuration objects, and extensions");
|
|
16
21
|
p.command("init")
|
|
17
22
|
.description("Initialize a new Jitsu extension project")
|
|
18
23
|
.arguments("[dir]")
|
|
19
24
|
.option("-j, --jitsu-version <version>", "Jitsu version to use in package.json. (Optional)")
|
|
20
25
|
.option("--allow-non-empty-dir", "Allow to create project in non-empty directory. (Optional)")
|
|
21
|
-
.action(
|
|
26
|
+
.action(init);
|
|
22
27
|
p.command("build")
|
|
23
28
|
.description("Build the extension")
|
|
24
29
|
.option("-d, --dir <dir>", "the directory of project. (Optional). By default, current directory is used")
|
|
25
|
-
.action(
|
|
30
|
+
.action(build);
|
|
26
31
|
p.command("test")
|
|
27
32
|
.description("Run test provided with the extension")
|
|
28
33
|
.option("-d, --dir <dir>", "the directory of project. (Optional). By default, current directory is used")
|
|
29
|
-
.action(
|
|
34
|
+
.action(test);
|
|
30
35
|
p.command("whoami")
|
|
31
36
|
.description("Check if current user is logged in. Shows user's info if logged in")
|
|
32
37
|
.option("-h, --host <host>", "Jitsu host or base url", "https://use.jitsu.com")
|
|
33
38
|
.option("-k, --apikey <api-key>", "Jitsu user's Api Key. (Optional). Disables interactive login.")
|
|
34
|
-
.action(
|
|
39
|
+
.action(whoami);
|
|
35
40
|
p.command("login")
|
|
36
41
|
.description("Login to Jitsu and remember credentials in `~/.jitsu/jitsu-cli.json` file")
|
|
37
42
|
.option("-f, --force", "If user already logged in, replace existing session")
|
|
38
43
|
.option("-h, --host <host>", "Jitsu host or base url", "https://use.jitsu.com")
|
|
39
44
|
.option("-k, --apikey <api-key>", "Jitsu user's Api Key. (Optional). Disables interactive login.")
|
|
40
|
-
.action(
|
|
41
|
-
p.command("logout").description("Logout").option("-f, --force", "Do not ask for confirmation").action(
|
|
45
|
+
.action(login);
|
|
46
|
+
p.command("logout").description("Logout").option("-f, --force", "Do not ask for confirmation").action(logout);
|
|
42
47
|
p.command("deploy")
|
|
43
48
|
.description("Deploy functions to Jitsu project")
|
|
44
49
|
.option("-d, --dir <dir>", "the directory of project. (Optional). By default, current directory is used")
|
|
@@ -47,7 +52,18 @@ p.command("deploy")
|
|
|
47
52
|
.option("-w, --workspace <workspace-id>", "Id of workspace where to deploy function (Optional). By default, interactive prompt is shown to select workspace")
|
|
48
53
|
.option("-t, --type <type>", "entity type to deploy", "function")
|
|
49
54
|
.option("-n, --name <name...>", "limit deploy to provided entities only. (Optional)")
|
|
50
|
-
.action(
|
|
51
|
-
p.
|
|
55
|
+
.action(deploy);
|
|
56
|
+
p.command("set-default-workspace")
|
|
57
|
+
.description("Save a default workspace to ~/.jitsu/jitsu-cli.json. Subsequent `jitsu config` commands use it when -w is omitted.")
|
|
58
|
+
.argument("<id-or-slug>", "Workspace id or slug")
|
|
59
|
+
.option("-h, --host <host>", "Jitsu host (overrides ~/.jitsu/jitsu-cli.json)")
|
|
60
|
+
.option("-k, --apikey <api-key>", "API key in form keyId:secret (overrides ~/.jitsu/jitsu-cli.json)")
|
|
61
|
+
.action(setDefaultWorkspace);
|
|
62
|
+
p.command("unset-default-workspace")
|
|
63
|
+
.description("Remove the saved default workspace from ~/.jitsu/jitsu-cli.json")
|
|
64
|
+
.action(unsetDefaultWorkspace);
|
|
65
|
+
p.addCommand(buildConfigCommand());
|
|
66
|
+
p.addCommand(buildSpecCommand());
|
|
67
|
+
p.version(jitsuCliPackageName + " " + jitsuCliVersion, "-v, --version");
|
|
52
68
|
p.helpOption("--help", "display help for command");
|
|
53
69
|
p.parse();
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export class ApiError extends Error {
|
|
2
|
+
constructor(status, message, payload) {
|
|
3
|
+
super(message);
|
|
4
|
+
this.status = status;
|
|
5
|
+
this.payload = payload;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export class ApiClient {
|
|
9
|
+
constructor(auth) {
|
|
10
|
+
this.auth = auth;
|
|
11
|
+
}
|
|
12
|
+
url(path, query) {
|
|
13
|
+
const base = this.auth.host;
|
|
14
|
+
const p = path.startsWith("/") ? path : `/${path}`;
|
|
15
|
+
if (!query)
|
|
16
|
+
return `${base}${p}`;
|
|
17
|
+
const qs = Object.entries(query)
|
|
18
|
+
.filter(([, v]) => v !== undefined && v !== null && v !== "")
|
|
19
|
+
.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`)
|
|
20
|
+
.join("&");
|
|
21
|
+
return qs ? `${base}${p}?${qs}` : `${base}${p}`;
|
|
22
|
+
}
|
|
23
|
+
async request(req) {
|
|
24
|
+
const method = req.method ?? "GET";
|
|
25
|
+
const headers = {
|
|
26
|
+
Accept: "application/json",
|
|
27
|
+
Authorization: `Bearer ${this.auth.apikey}`,
|
|
28
|
+
};
|
|
29
|
+
let body;
|
|
30
|
+
if (req.body !== undefined) {
|
|
31
|
+
headers["Content-Type"] = "application/json";
|
|
32
|
+
body = JSON.stringify(req.body);
|
|
33
|
+
}
|
|
34
|
+
const res = await fetch(this.url(req.path, req.query), { method, headers, body });
|
|
35
|
+
const text = await res.text();
|
|
36
|
+
let parsed = text;
|
|
37
|
+
if (text && res.headers.get("content-type")?.includes("application/json")) {
|
|
38
|
+
try {
|
|
39
|
+
parsed = JSON.parse(text);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (!res.ok) {
|
|
45
|
+
const msg = (parsed && typeof parsed === "object" && "message" in parsed
|
|
46
|
+
? String(parsed.message)
|
|
47
|
+
: undefined) ?? `HTTP ${res.status} ${method} ${req.path}`;
|
|
48
|
+
throw new ApiError(res.status, msg, parsed);
|
|
49
|
+
}
|
|
50
|
+
return parsed;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import { mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
3
|
+
import { homedir } from "os";
|
|
4
|
+
const DEFAULT_HOST = "https://use.jitsu.com";
|
|
5
|
+
export function authFilePath() {
|
|
6
|
+
return `${homedir()}/.jitsu/jitsu-cli.json`;
|
|
7
|
+
}
|
|
8
|
+
export function readAuthFile() {
|
|
9
|
+
const path = authFilePath();
|
|
10
|
+
if (!fs.existsSync(path))
|
|
11
|
+
return undefined;
|
|
12
|
+
return JSON.parse(readFileSync(path, { encoding: "utf-8" }));
|
|
13
|
+
}
|
|
14
|
+
export function updateAuthFile(patch) {
|
|
15
|
+
const path = authFilePath();
|
|
16
|
+
const existing = readAuthFile() ?? {};
|
|
17
|
+
const next = { ...existing };
|
|
18
|
+
for (const [k, v] of Object.entries(patch)) {
|
|
19
|
+
if (v === undefined)
|
|
20
|
+
delete next[k];
|
|
21
|
+
else
|
|
22
|
+
next[k] = v;
|
|
23
|
+
}
|
|
24
|
+
mkdirSync(`${homedir()}/.jitsu`, { recursive: true });
|
|
25
|
+
writeFileSync(path, JSON.stringify(next, null, 2));
|
|
26
|
+
return next;
|
|
27
|
+
}
|
|
28
|
+
export function readDefaultWorkspace() {
|
|
29
|
+
return readAuthFile()?.defaultWorkspace;
|
|
30
|
+
}
|
|
31
|
+
export function resolveAuth(opts) {
|
|
32
|
+
let host = opts.host;
|
|
33
|
+
let apikey = opts.apikey;
|
|
34
|
+
if (!host || !apikey) {
|
|
35
|
+
const file = readAuthFile();
|
|
36
|
+
if (file) {
|
|
37
|
+
if (!host)
|
|
38
|
+
host = file.host;
|
|
39
|
+
if (!apikey)
|
|
40
|
+
apikey = file.apikey;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (!host)
|
|
44
|
+
host = process.env.JITSU_HOST;
|
|
45
|
+
if (!apikey)
|
|
46
|
+
apikey = process.env.JITSU_APIKEY;
|
|
47
|
+
if (!host)
|
|
48
|
+
host = DEFAULT_HOST;
|
|
49
|
+
if (!apikey) {
|
|
50
|
+
throw new Error("Not authenticated. Run `jitsu login`, set JITSU_APIKEY, or pass --apikey <key>.");
|
|
51
|
+
}
|
|
52
|
+
return { host: normalizeHost(host), apikey };
|
|
53
|
+
}
|
|
54
|
+
export function normalizeHost(host) {
|
|
55
|
+
let url = host;
|
|
56
|
+
if (!url.startsWith("http")) {
|
|
57
|
+
if (url.startsWith("localhost") || /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/.test(url)) {
|
|
58
|
+
url = "http://" + url;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
url = "https://" + url;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (url.endsWith("/"))
|
|
65
|
+
url = url.slice(0, -1);
|
|
66
|
+
return url;
|
|
67
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import yaml from "js-yaml";
|
|
3
|
+
import { parseScalar, setDottedPath } from "./dotted";
|
|
4
|
+
export function buildBody(sources) {
|
|
5
|
+
const layers = [];
|
|
6
|
+
if (sources.file)
|
|
7
|
+
layers.push(loadFile(sources.file));
|
|
8
|
+
if (sources.json)
|
|
9
|
+
layers.push(parseInlineJson(sources.json));
|
|
10
|
+
if (sources.fields && Object.keys(sources.fields).length > 0) {
|
|
11
|
+
const obj = {};
|
|
12
|
+
for (const [path, raw] of Object.entries(sources.fields)) {
|
|
13
|
+
setDottedPath(obj, path, parseScalar(raw));
|
|
14
|
+
}
|
|
15
|
+
layers.push(obj);
|
|
16
|
+
}
|
|
17
|
+
if (layers.length === 0)
|
|
18
|
+
return undefined;
|
|
19
|
+
return layers.reduce((acc, layer) => deepMerge(acc, layer), {});
|
|
20
|
+
}
|
|
21
|
+
function loadFile(path) {
|
|
22
|
+
const text = path === "-" ? fs.readFileSync(0, "utf-8") : fs.readFileSync(path, "utf-8");
|
|
23
|
+
const parsed = yaml.load(text);
|
|
24
|
+
if (parsed === null || parsed === undefined) {
|
|
25
|
+
throw new Error(`File ${path} parsed as empty`);
|
|
26
|
+
}
|
|
27
|
+
return parsed;
|
|
28
|
+
}
|
|
29
|
+
function parseInlineJson(s) {
|
|
30
|
+
try {
|
|
31
|
+
return JSON.parse(s);
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
throw new Error(`--json value is not valid JSON: ${e.message}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function isPlainObject(v) {
|
|
38
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
39
|
+
}
|
|
40
|
+
function deepMerge(target, source) {
|
|
41
|
+
if (!isPlainObject(target) || !isPlainObject(source))
|
|
42
|
+
return source;
|
|
43
|
+
const out = { ...target };
|
|
44
|
+
for (const [k, v] of Object.entries(source)) {
|
|
45
|
+
if (isPlainObject(v) && isPlainObject(out[k])) {
|
|
46
|
+
out[k] = deepMerge(out[k], v);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
out[k] = v;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
const RESERVED = new Set([
|
|
2
|
+
"workspace",
|
|
3
|
+
"output",
|
|
4
|
+
"host",
|
|
5
|
+
"apikey",
|
|
6
|
+
"file",
|
|
7
|
+
"json",
|
|
8
|
+
"cascade",
|
|
9
|
+
"strict",
|
|
10
|
+
"from",
|
|
11
|
+
"to",
|
|
12
|
+
"help",
|
|
13
|
+
"version",
|
|
14
|
+
]);
|
|
15
|
+
const fields = {};
|
|
16
|
+
function shouldExtract(argv) {
|
|
17
|
+
for (let i = 2; i < argv.length; i++) {
|
|
18
|
+
const a = argv[i];
|
|
19
|
+
if (a.startsWith("-"))
|
|
20
|
+
continue;
|
|
21
|
+
return a === "config";
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
export function preprocessArgv(argv) {
|
|
26
|
+
if (!shouldExtract(argv))
|
|
27
|
+
return argv;
|
|
28
|
+
const out = [];
|
|
29
|
+
for (const arg of argv) {
|
|
30
|
+
const m = /^--([a-zA-Z][\w.-]*)=([\s\S]*)$/.exec(arg);
|
|
31
|
+
if (m) {
|
|
32
|
+
const head = m[1].split(".")[0];
|
|
33
|
+
if (!RESERVED.has(head)) {
|
|
34
|
+
fields[m[1]] = m[2];
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
out.push(arg);
|
|
39
|
+
}
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
export function consumeBodyFields() {
|
|
43
|
+
const copy = { ...fields };
|
|
44
|
+
for (const k of Object.keys(fields))
|
|
45
|
+
delete fields[k];
|
|
46
|
+
return copy;
|
|
47
|
+
}
|
|
@@ -1,31 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
exports.chalkCode = chalkCode;
|
|
5
|
-
const tslib_1 = require("tslib");
|
|
6
|
-
const prismjs_1 = tslib_1.__importDefault(require("prismjs"));
|
|
7
|
-
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
8
|
-
exports.defaultColorScheme = {
|
|
1
|
+
import Prism from "prismjs";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
export const defaultColorScheme = {
|
|
9
4
|
punctuation: "#999",
|
|
10
5
|
operator: "#9a6e3a",
|
|
11
6
|
string: "#9a6e3a",
|
|
12
7
|
keyword: "b#07a",
|
|
13
8
|
"function-variable": null,
|
|
14
9
|
};
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
10
|
+
export const b = chalk.bold;
|
|
11
|
+
export const red = chalk.red;
|
|
12
|
+
export const green = chalk.green;
|
|
13
|
+
export const yellow = chalk.yellow;
|
|
19
14
|
function chalkString(expr, str) {
|
|
20
15
|
if (expr.startsWith("b")) {
|
|
21
|
-
return
|
|
16
|
+
return b(chalkString(expr.substring(1), str));
|
|
22
17
|
}
|
|
23
18
|
else {
|
|
24
|
-
return
|
|
19
|
+
return chalk.hex(expr)(str);
|
|
25
20
|
}
|
|
26
21
|
}
|
|
27
|
-
function chalkCode(code, lang, colorScheme =
|
|
28
|
-
return
|
|
22
|
+
export function chalkCode(code, lang, colorScheme = defaultColorScheme) {
|
|
23
|
+
return Prism.tokenize(code, Prism.languages.javascript)
|
|
29
24
|
.map(element => {
|
|
30
25
|
if (typeof element === "string") {
|
|
31
26
|
return element;
|
|
@@ -37,9 +32,9 @@ function chalkCode(code, lang, colorScheme = exports.defaultColorScheme) {
|
|
|
37
32
|
})
|
|
38
33
|
.join("");
|
|
39
34
|
}
|
|
40
|
-
chalkCode.typescript = (code, colorScheme =
|
|
41
|
-
return chalkCode(typeof code === "string" ? code : code.join("\n"),
|
|
35
|
+
chalkCode.typescript = (code, colorScheme = defaultColorScheme) => {
|
|
36
|
+
return chalkCode(typeof code === "string" ? code : code.join("\n"), Prism.languages.typescript, colorScheme);
|
|
42
37
|
};
|
|
43
|
-
chalkCode.json = (code, colorScheme =
|
|
44
|
-
return chalkCode(typeof code === "string" ? code : code.join("\n"),
|
|
38
|
+
chalkCode.json = (code, colorScheme = defaultColorScheme) => {
|
|
39
|
+
return chalkCode(typeof code === "string" ? code : code.join("\n"), Prism.languages.json, colorScheme);
|
|
45
40
|
};
|