jitsu-cli 0.6.0 → 0.7.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/lib/cli/extension/exec.d.ts +2 -0
- package/lib/cli/extension/exec.js +127 -0
- package/lib/cli/extension/index.d.ts +1 -1
- package/lib/cli/extension/index.js +6 -0
- package/lib/cli/extension/validate-config.js +14 -19
- package/lib/index.js +0 -3
- package/lib/lib/indent.d.ts +1 -0
- package/lib/lib/indent.js +13 -1
- package/lib/lib/validator-helper.d.ts +3 -0
- package/lib/lib/validator-helper.js +21 -0
- package/package.json +2 -2
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.execExtension = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const commander_1 = (0, tslib_1.__importDefault)(require("commander"));
|
|
6
|
+
const log_1 = (0, tslib_1.__importDefault)(require("../../lib/log"));
|
|
7
|
+
const chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
|
|
8
|
+
const path_1 = (0, tslib_1.__importDefault)(require("path"));
|
|
9
|
+
const JSON5_1 = (0, tslib_1.__importDefault)(require("JSON5"));
|
|
10
|
+
const fs_1 = (0, tslib_1.__importDefault)(require("fs"));
|
|
11
|
+
const index_1 = require("./index");
|
|
12
|
+
const indent_1 = require("../../lib/indent");
|
|
13
|
+
const chalk_code_highlight_1 = require("../../lib/chalk-code-highlight");
|
|
14
|
+
const validator_helper_1 = require("../../lib/validator-helper");
|
|
15
|
+
const errors_1 = require("../../lib/errors");
|
|
16
|
+
function getJson(json, file) {
|
|
17
|
+
if (json) {
|
|
18
|
+
return JSON5_1.default.parse(json);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
if (!fs_1.default.existsSync(file)) {
|
|
22
|
+
throw new Error(`File ${file} does not exist!`);
|
|
23
|
+
}
|
|
24
|
+
return JSON5_1.default.parse(fs_1.default.readFileSync(file, "utf-8"));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function ellipsis(str, opts = { maxLen: 80 }) {
|
|
28
|
+
const maxLen = opts?.maxLen || 80;
|
|
29
|
+
return str.length < maxLen ? str : str.substring(0, maxLen - 3) + "...";
|
|
30
|
+
}
|
|
31
|
+
function toArray(obj) {
|
|
32
|
+
if (!(typeof obj === "object" && Array.isArray(obj))) {
|
|
33
|
+
return [obj];
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
return obj;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function execExtension(args) {
|
|
40
|
+
const program = new commander_1.default.Command();
|
|
41
|
+
program.option("-f, --file <file path>", "Path to file with jitsu events. Could be either on object, or array of objects");
|
|
42
|
+
program.option("-c, --config <file path>", "Path to file with config ");
|
|
43
|
+
program.option("-o, --config-object <file path>", "Config json");
|
|
44
|
+
program.option("-j, --json <event json>", "Events JSON for processing (alternative to -f). Could be one object, or array of objects");
|
|
45
|
+
program.option("-d, --dir <project_dir>", "project dir");
|
|
46
|
+
program.option("-v, --skip-validation", "To skip config validation");
|
|
47
|
+
program.parse(["dummy", "dummy", ...args]);
|
|
48
|
+
let cliOpts = program.opts();
|
|
49
|
+
let directory = cliOpts.dir || ".";
|
|
50
|
+
let projectBase = path_1.default.isAbsolute(directory) ? directory : path_1.default.resolve(process.cwd() + "/" + directory);
|
|
51
|
+
let packageFile = path_1.default.resolve(projectBase, "package.json");
|
|
52
|
+
if (!fs_1.default.existsSync(packageFile)) {
|
|
53
|
+
return { success: false, message: "Can't find package.json in " + projectBase };
|
|
54
|
+
}
|
|
55
|
+
if (!cliOpts.json && !cliOpts.file) {
|
|
56
|
+
return { success: false, message: "Please specify -j or -f" };
|
|
57
|
+
}
|
|
58
|
+
if (cliOpts.json && cliOpts.file) {
|
|
59
|
+
return { success: false, message: "Both options -f and -j are provided. You should use either, not both" };
|
|
60
|
+
}
|
|
61
|
+
if (cliOpts.config && cliOpts.configObject) {
|
|
62
|
+
return { success: false, message: "Both options -o and -c are provided. You should use either, not both" };
|
|
63
|
+
}
|
|
64
|
+
if (!cliOpts.config && !cliOpts.configObject) {
|
|
65
|
+
return { success: false, message: "Please specify -o or -c" };
|
|
66
|
+
}
|
|
67
|
+
(0, log_1.default)().info("🛂 Executing tests destination on " + chalk_1.default.bold(projectBase));
|
|
68
|
+
let events = toArray(getJson(cliOpts.json, cliOpts.file));
|
|
69
|
+
let config = getJson(cliOpts.configObject, cliOpts.config);
|
|
70
|
+
let distFile = path_1.default.resolve(projectBase, (0, index_1.getDistFile)(JSON5_1.default.parse(fs_1.default.readFileSync(packageFile, "utf-8"))));
|
|
71
|
+
(0, log_1.default)().info("⌛️ Loading destination plugin (don't forget to build it before running exec!). Source: " + chalk_1.default.bold(distFile));
|
|
72
|
+
if (!fs_1.default.existsSync(path_1.default.resolve(projectBase, distFile))) {
|
|
73
|
+
return {
|
|
74
|
+
success: false,
|
|
75
|
+
message: `Can't find dist file ${chalk_1.default.bold(distFile)}. Does this dir contains jitsu extension? Have you run yarn build? `,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
let extension = (0, index_1.loadBuild)(fs_1.default.readFileSync(distFile, "utf-8"));
|
|
79
|
+
if (!extension.destination) {
|
|
80
|
+
return { success: false, message: "Extension doesn't export destination function" };
|
|
81
|
+
}
|
|
82
|
+
if (!cliOpts.skipValidation && extension.validator) {
|
|
83
|
+
(0, log_1.default)().info(`Validating configuration:${chalk_code_highlight_1.chalkCode.json((0, indent_1.align)(JSON.stringify(config, null, 2), { indent: 4, lnBefore: 1, lnAfter: 1 }))}`);
|
|
84
|
+
let configError = await (0, validator_helper_1.validateConfiguration)(config, extension.validator);
|
|
85
|
+
if (configError) {
|
|
86
|
+
return { success: false, message: "Config is not valid: " + configError };
|
|
87
|
+
}
|
|
88
|
+
(0, log_1.default)().info("✅ Configuration is valid!");
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
(0, log_1.default)().info("💡 Config validation will be skipped " +
|
|
92
|
+
(cliOpts.skipValidation ? " as per requested by -v flag" : ": extension does not have an exported validator"));
|
|
93
|
+
}
|
|
94
|
+
(0, log_1.default)().info("🏃 Running destination plugin on " + events.length + " events");
|
|
95
|
+
for (const ev of events) {
|
|
96
|
+
try {
|
|
97
|
+
let messages = await extension.destination(ev, {
|
|
98
|
+
destinationId: "test",
|
|
99
|
+
destinationType: "test",
|
|
100
|
+
config: config,
|
|
101
|
+
});
|
|
102
|
+
if (!messages) {
|
|
103
|
+
(0, log_1.default)().info("⚽ Event is skipped: " + ellipsis(JSON.stringify(ev)));
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
const messagesArray = Array.isArray(messages) ? messages : [messages];
|
|
107
|
+
(0, log_1.default)().info(`✅ Event emitted ${messagesArray.length} messages. Event JSON: ` + chalk_1.default.italic(ellipsis(JSON.stringify(ev))));
|
|
108
|
+
messagesArray.forEach(msg => {
|
|
109
|
+
(0, log_1.default)().info(` ${chalk_1.default.bold(msg.method)} ${msg.url}`);
|
|
110
|
+
if (msg.headers && Object.entries(msg).length > 0) {
|
|
111
|
+
Object.entries(msg.headers).forEach(([h, v]) => {
|
|
112
|
+
(0, log_1.default)().info(` ${chalk_1.default.bold(h)}: ${v}`);
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
if (msg.body) {
|
|
116
|
+
(0, log_1.default)().info(" Body:\n" + chalk_code_highlight_1.chalkCode.json((0, indent_1.align)(JSON.stringify((0, indent_1.jsonify)(msg.body), null, 2), { indent: 8 })));
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
catch (e) {
|
|
121
|
+
(0, log_1.default)().info(chalk_1.default.red((0, errors_1.appendError)("❌ Failed to process event", e) +
|
|
122
|
+
(0, indent_1.align)(JSON.stringify(ev, null, 2), { lnBefore: 1, lnAfter: 1, indent: 0 })));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return { success: true };
|
|
126
|
+
}
|
|
127
|
+
exports.execExtension = execExtension;
|
|
@@ -2,7 +2,7 @@ import { CommandRegistry } from "../../lib/command/types";
|
|
|
2
2
|
import { JitsuExtensionExport } from "@jitsu/types/extension";
|
|
3
3
|
import { Partial } from "rollup-plugin-typescript2/dist/partial";
|
|
4
4
|
export declare const help: string;
|
|
5
|
-
export declare const extensionCommands: CommandRegistry<"test" | "build" | "create" | "validate-config">;
|
|
5
|
+
export declare const extensionCommands: CommandRegistry<"test" | "build" | "create" | "validate-config" | "exec">;
|
|
6
6
|
export declare function validateTsConfig(tsConfigPath: string): void;
|
|
7
7
|
export declare function getDistFile(packageJson: any): any;
|
|
8
8
|
export declare function loadBuild(code: string): Partial<JitsuExtensionExport>;
|
|
@@ -12,6 +12,7 @@ const test_1 = require("./test");
|
|
|
12
12
|
const validate_config_1 = require("./validate-config");
|
|
13
13
|
const template_1 = require("./template");
|
|
14
14
|
const JSON5_1 = (0, tslib_1.__importDefault)(require("JSON5"));
|
|
15
|
+
const exec_1 = require("./exec");
|
|
15
16
|
global.fetch = require("cross-fetch");
|
|
16
17
|
const usage = `
|
|
17
18
|
· ${chalk_1.default.bold("jitsu-cli extension create")}
|
|
@@ -56,6 +57,11 @@ ${chalk_1.default.bold("TYPESCRIPT")}
|
|
|
56
57
|
${chalk_1.default.bold("COMMANDS")} ${(0, indent_1.align)(usage, { indent: 2, lnBefore: 2 })}
|
|
57
58
|
`;
|
|
58
59
|
exports.extensionCommands = {
|
|
60
|
+
exec: {
|
|
61
|
+
exec: exec_1.execExtension,
|
|
62
|
+
description: "Execute extension of a test data",
|
|
63
|
+
help: ""
|
|
64
|
+
},
|
|
59
65
|
test: {
|
|
60
66
|
exec: test_1.test,
|
|
61
67
|
description: "Execute test on extension",
|
|
@@ -9,38 +9,39 @@ const fs_1 = (0, tslib_1.__importDefault)(require("fs"));
|
|
|
9
9
|
const JSON5_1 = (0, tslib_1.__importDefault)(require("JSON5"));
|
|
10
10
|
const log_1 = (0, tslib_1.__importDefault)(require("../../lib/log"));
|
|
11
11
|
const index_1 = require("./index");
|
|
12
|
+
const validator_helper_1 = require("../../lib/validator-helper");
|
|
12
13
|
async function validateConfig(args) {
|
|
13
14
|
const program = new commander_1.default.Command();
|
|
14
15
|
program.option("-d, --dir <project_dir>", "Project directory");
|
|
15
|
-
program.option("-
|
|
16
|
-
program.option("-
|
|
16
|
+
program.option("-c, --config <config_file>", "Configuration file");
|
|
17
|
+
program.option("-o, --config-object <config_json>", "Inline extension configuration JSON");
|
|
17
18
|
program.argument("[project_dir]");
|
|
18
19
|
program.parse(["dummy", "dummy", ...args]);
|
|
19
20
|
const opts = program.opts();
|
|
20
|
-
if (!opts.
|
|
21
|
+
if (!opts.configObject && !opts.config) {
|
|
21
22
|
return {
|
|
22
23
|
success: false,
|
|
23
24
|
message: 'Please define config object either with -j "{embedded json}", or with -f json_file',
|
|
24
25
|
};
|
|
25
26
|
}
|
|
26
27
|
let configObj;
|
|
27
|
-
if (opts.
|
|
28
|
+
if (opts.configObject) {
|
|
28
29
|
try {
|
|
29
|
-
configObj = JSON5_1.default.parse(opts.
|
|
30
|
+
configObj = JSON5_1.default.parse(opts.configObject);
|
|
30
31
|
}
|
|
31
32
|
catch (e) {
|
|
32
33
|
return { success: false, message: `Malformed json (-j): ${e.message}` };
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
36
|
else {
|
|
36
|
-
if (!fs_1.default.existsSync(opts.
|
|
37
|
-
return { success: false, message: `${opts.
|
|
37
|
+
if (!fs_1.default.existsSync(opts.config)) {
|
|
38
|
+
return { success: false, message: `${opts.config} (-f) doesn't exist!` };
|
|
38
39
|
}
|
|
39
40
|
try {
|
|
40
|
-
configObj = JSON5_1.default.parse(fs_1.default.readFileSync(opts.
|
|
41
|
+
configObj = JSON5_1.default.parse(fs_1.default.readFileSync(opts.config, "utf8"));
|
|
41
42
|
}
|
|
42
43
|
catch (e) {
|
|
43
|
-
return { success: false, message: `Malformed json in file ${opts.
|
|
44
|
+
return { success: false, message: `Malformed json in file ${opts.config} (-f): ${e.message}` };
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
let projectDir = opts.dir || ".";
|
|
@@ -62,16 +63,10 @@ async function validateConfig(args) {
|
|
|
62
63
|
return { success: false, message: "Build doesn't export validator symbol" };
|
|
63
64
|
}
|
|
64
65
|
(0, log_1.default)().info("🤔 Validating configuration " +
|
|
65
|
-
(opts.
|
|
66
|
-
let
|
|
67
|
-
if (
|
|
68
|
-
return { success: false, message:
|
|
69
|
-
}
|
|
70
|
-
else if (typeof validationResult === "string") {
|
|
71
|
-
return { success: false, message: "❌ Config is not valid: " + validationResult };
|
|
72
|
-
}
|
|
73
|
-
else if (typeof validationResult === "object" && !validationResult.ok) {
|
|
74
|
-
return { success: false, message: "❌ Config is not valid: " + validationResult.message };
|
|
66
|
+
(opts.config ? `from file ${path_1.default.resolve(projectDir, opts.config)}` : JSON.stringify(configObj)));
|
|
67
|
+
let validationError = await (0, validator_helper_1.validateConfiguration)(configObj, build.validator);
|
|
68
|
+
if (validationError) {
|
|
69
|
+
return { success: false, message: `❌ ${validationError}` };
|
|
75
70
|
}
|
|
76
71
|
(0, log_1.default)().info("✅ Config is valid. Hooray!");
|
|
77
72
|
return { success: true };
|
package/lib/index.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const tslib_1 = require("tslib");
|
|
4
3
|
const run_1 = require("./run");
|
|
5
|
-
const log_1 = (0, tslib_1.__importDefault)(require("./lib/log"));
|
|
6
4
|
(async function () {
|
|
7
|
-
(0, log_1.default)().info("Args: " + process.argv);
|
|
8
5
|
const args = [...process.argv.slice(2)];
|
|
9
6
|
process.exit(await (0, run_1.run)(args));
|
|
10
7
|
})();
|
package/lib/lib/indent.d.ts
CHANGED
package/lib/lib/indent.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.align = exports.removeIndentation = void 0;
|
|
3
|
+
exports.jsonify = exports.align = exports.removeIndentation = void 0;
|
|
4
4
|
function getIndentSize(line) {
|
|
5
5
|
let idx = 0;
|
|
6
6
|
for (; line.charAt(idx) === " " && idx < line.length; idx++) { }
|
|
@@ -27,3 +27,15 @@ function align(text, { indent = 0, lnBefore = 0, lnAfter = 0 } = {}) {
|
|
|
27
27
|
].join("\n");
|
|
28
28
|
}
|
|
29
29
|
exports.align = align;
|
|
30
|
+
function jsonify(obj) {
|
|
31
|
+
if (typeof obj === 'string') {
|
|
32
|
+
try {
|
|
33
|
+
return JSON.parse(obj);
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
return obj;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return obj;
|
|
40
|
+
}
|
|
41
|
+
exports.jsonify = jsonify;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { ConfigValidationResult, ConfigValidator } from "@jitsu/types/extension";
|
|
2
|
+
export declare function validationResultToError(validationResult: ConfigValidationResult): string | undefined;
|
|
3
|
+
export declare function validateConfiguration(config: any, validator: ConfigValidator): Promise<(string | undefined)>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateConfiguration = exports.validationResultToError = void 0;
|
|
4
|
+
function validationResultToError(validationResult) {
|
|
5
|
+
if (typeof validationResult === "boolean" && !validationResult) {
|
|
6
|
+
return "Config is not valid, an exact reason isn't specified by validator";
|
|
7
|
+
}
|
|
8
|
+
else if (typeof validationResult === "string") {
|
|
9
|
+
return "Config is not valid: " + validationResult;
|
|
10
|
+
}
|
|
11
|
+
else if (typeof validationResult === "object" && !validationResult.ok) {
|
|
12
|
+
return "Config is not valid: " + validationResult.message;
|
|
13
|
+
}
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
exports.validationResultToError = validationResultToError;
|
|
17
|
+
async function validateConfiguration(config, validator) {
|
|
18
|
+
let validationResult = await validator(config);
|
|
19
|
+
return validationResultToError(validationResult);
|
|
20
|
+
}
|
|
21
|
+
exports.validateConfiguration = validateConfiguration;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jitsu-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -65,5 +65,5 @@
|
|
|
65
65
|
"typescript": "^4.5.2",
|
|
66
66
|
"validate-npm-package-name": "^3.0.0"
|
|
67
67
|
},
|
|
68
|
-
"gitHead": "
|
|
68
|
+
"gitHead": "4d54aac819fd941c52c15e1f7716c628d80bbdc5"
|
|
69
69
|
}
|