jitsu-cli 0.7.2 → 0.9.0-alpha.169
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/build.js +58 -23
- package/lib/cli/extension/create.js +10 -10
- package/lib/cli/extension/exec.d.ts +2 -1
- package/lib/cli/extension/exec.js +201 -32
- package/lib/cli/extension/index.d.ts +3 -2
- package/lib/cli/extension/index.js +51 -13
- package/lib/cli/extension/template.d.ts +10 -7
- package/lib/cli/extension/template.js +101 -4
- package/lib/cli/extension/test.js +5 -5
- package/lib/cli/extension/validate-config.js +21 -33
- package/lib/lib/chalk-code-highlight.js +2 -2
- package/lib/lib/command/index.js +6 -4
- package/lib/lib/indent.js +1 -1
- package/lib/lib/log.d.ts +1 -0
- package/lib/lib/log.js +4 -1
- package/lib/lib/template.js +4 -4
- package/lib/lib/validation.d.ts +2 -0
- package/lib/lib/validation.js +23 -0
- package/lib/lib/version.d.ts +1 -1
- package/lib/lib/version.js +6 -6
- package/lib/package.json +13 -9
- package/lib/run.js +2 -2
- package/package.json +17 -13
- package/lib/lib/validator-helper.d.ts +0 -3
- package/lib/lib/validator-helper.js +0 -21
|
@@ -2,23 +2,45 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.build = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const path_1 =
|
|
6
|
-
const log_1 =
|
|
7
|
-
const chalk_1 =
|
|
8
|
-
const fs_1 =
|
|
5
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
6
|
+
const log_1 = tslib_1.__importDefault(require("../../lib/log"));
|
|
7
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
8
|
+
const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
9
9
|
const errors_1 = require("../../lib/errors");
|
|
10
10
|
const rollup_1 = require("rollup");
|
|
11
|
-
const rollup_plugin_typescript2_1 =
|
|
12
|
-
const plugin_multi_entry_1 =
|
|
13
|
-
const
|
|
14
|
-
const
|
|
11
|
+
const rollup_plugin_typescript2_1 = tslib_1.__importDefault(require("rollup-plugin-typescript2"));
|
|
12
|
+
const plugin_multi_entry_1 = tslib_1.__importDefault(require("@rollup/plugin-multi-entry"));
|
|
13
|
+
const plugin_json_1 = tslib_1.__importDefault(require("@rollup/plugin-json"));
|
|
14
|
+
const plugin_node_resolve_1 = tslib_1.__importDefault(require("@rollup/plugin-node-resolve"));
|
|
15
|
+
const plugin_commonjs_1 = tslib_1.__importDefault(require("@rollup/plugin-commonjs"));
|
|
15
16
|
const version_1 = require("../../lib/version");
|
|
16
17
|
const _1 = require("./");
|
|
17
|
-
const
|
|
18
|
+
const JSON5 = tslib_1.__importStar(require("json5"));
|
|
19
|
+
function fixNodeFetch(code) {
|
|
20
|
+
return code.replace("throw new TypeError('Expected signal to be an instanceof AbortSignal');", "");
|
|
21
|
+
}
|
|
22
|
+
function insertStreamReaderFacade(targetFile) {
|
|
23
|
+
return {
|
|
24
|
+
name: "insert-stream-reader-facade",
|
|
25
|
+
transform: async (code, id) => {
|
|
26
|
+
const [path] = id.split("?");
|
|
27
|
+
if (path === targetFile) {
|
|
28
|
+
let newCode = [
|
|
29
|
+
`import * as srcLib from "@jitsu/jlib/lib/sources-lib";`,
|
|
30
|
+
code,
|
|
31
|
+
";",
|
|
32
|
+
`export const __$srcLib = srcLib;`,
|
|
33
|
+
].join("\n");
|
|
34
|
+
return { code: newCode };
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
18
40
|
async function build(args) {
|
|
19
41
|
const directory = args?.[0] || "";
|
|
20
42
|
let projectBase = path_1.default.isAbsolute(directory) ? directory : path_1.default.resolve(process.cwd() + "/" + directory);
|
|
21
|
-
(0, log_1.default)().info("🔨 Building project in " + chalk_1.default.bold(projectBase));
|
|
43
|
+
(0, log_1.default)().info("🔨 Building project in " + chalk_1.default.bold(projectBase) + ` with ${version_1.jitsuPackageName}@${version_1.jitsuCliVersion} `);
|
|
22
44
|
if (!fs_1.default.existsSync(projectBase)) {
|
|
23
45
|
throw new Error(`Path ${projectBase} does not exist`);
|
|
24
46
|
}
|
|
@@ -28,7 +50,7 @@ async function build(args) {
|
|
|
28
50
|
}
|
|
29
51
|
let packageJson;
|
|
30
52
|
try {
|
|
31
|
-
packageJson =
|
|
53
|
+
packageJson = JSON5.parse(fs_1.default.readFileSync(packageFile, "utf8"));
|
|
32
54
|
}
|
|
33
55
|
catch (e) {
|
|
34
56
|
throw new Error((0, errors_1.appendError)(`Failed to parse package.json at ${projectBase}`, e));
|
|
@@ -48,7 +70,7 @@ async function build(args) {
|
|
|
48
70
|
};
|
|
49
71
|
}
|
|
50
72
|
(0, _1.validateTsConfig)(tsConfigPath);
|
|
51
|
-
(0, log_1.default)().info("Building project");
|
|
73
|
+
(0, log_1.default)().info("Building project...");
|
|
52
74
|
try {
|
|
53
75
|
let indexFile = path_1.default.resolve(projectBase, "src/index.ts");
|
|
54
76
|
if (!fs_1.default.existsSync(indexFile)) {
|
|
@@ -56,21 +78,36 @@ async function build(args) {
|
|
|
56
78
|
}
|
|
57
79
|
const bundle = await (0, rollup_1.rollup)({
|
|
58
80
|
input: [indexFile],
|
|
59
|
-
plugins: [
|
|
81
|
+
plugins: [
|
|
82
|
+
typescriptEnabled && (0, rollup_plugin_typescript2_1.default)({ cwd: projectBase }),
|
|
83
|
+
insertStreamReaderFacade(indexFile),
|
|
84
|
+
(0, plugin_multi_entry_1.default)(),
|
|
85
|
+
(0, plugin_node_resolve_1.default)({ preferBuiltins: false }),
|
|
86
|
+
(0, plugin_commonjs_1.default)(),
|
|
87
|
+
(0, plugin_json_1.default)(),
|
|
88
|
+
],
|
|
60
89
|
});
|
|
61
|
-
|
|
90
|
+
let format = "cjs";
|
|
62
91
|
let output = await bundle.generate({
|
|
63
|
-
generatedCode: "
|
|
64
|
-
format:
|
|
92
|
+
generatedCode: "es5",
|
|
93
|
+
format: format,
|
|
94
|
+
exports: "named",
|
|
95
|
+
banner: `//format=${format}`,
|
|
96
|
+
outro: [
|
|
97
|
+
`exports.buildInfo = {sdkVersion: "${version_1.jitsuCliVersion}", sdkPackage: "${version_1.jitsuPackageName}", buildTimestamp: "${new Date().toISOString()}"};`,
|
|
98
|
+
`exports.streamReader$StdoutFacade = exports.streamReader && __$srcLib.stdoutStreamReader(exports.streamReader);`,
|
|
99
|
+
].join("\n"),
|
|
65
100
|
});
|
|
101
|
+
let code = fixNodeFetch(output.output[0].code);
|
|
102
|
+
fs_1.default.mkdirSync(path_1.default.dirname(fullOutputPath), { recursive: true });
|
|
103
|
+
fs_1.default.writeFileSync(fullOutputPath, code);
|
|
66
104
|
(0, log_1.default)().info("Validating build");
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const exports = (0, _1.loadBuild)(code);
|
|
70
|
-
if (!exports.destination && !exports.transform) {
|
|
105
|
+
const exports = await (0, _1.loadBuild)(fullOutputPath);
|
|
106
|
+
if (!exports.destination && !exports.transform && !(exports.streamReader && exports.sourceCatalog)) {
|
|
71
107
|
return {
|
|
72
108
|
success: false,
|
|
73
|
-
message: `${chalk_1.default.bold(indexFile)} should export ${chalk_1.default.italic("destination")} or ${chalk_1.default.italic("
|
|
109
|
+
message: `${chalk_1.default.bold(indexFile)} should export ${chalk_1.default.italic("destination")}, ${chalk_1.default.italic("transform")} or both ${chalk_1.default.italic("streamReader")} and ${chalk_1.default.italic("sourceCatalog")} symbols. It exports: ` +
|
|
110
|
+
Object.keys(exports).join(", "),
|
|
74
111
|
};
|
|
75
112
|
}
|
|
76
113
|
else if (exports.destination && exports.transform) {
|
|
@@ -79,8 +116,6 @@ async function build(args) {
|
|
|
79
116
|
message: `${chalk_1.default.bold(indexFile)} exports both ${chalk_1.default.italic("destination")} and ${chalk_1.default.italic("transform")} symbol. It should export either of them` + Object.keys(exports).join(", "),
|
|
80
117
|
};
|
|
81
118
|
}
|
|
82
|
-
fs_1.default.mkdirSync(path_1.default.dirname(fullOutputPath), { recursive: true });
|
|
83
|
-
fs_1.default.writeFileSync(fullOutputPath, code);
|
|
84
119
|
}
|
|
85
120
|
catch (e) {
|
|
86
121
|
if (e.id && e.loc && e.frame) {
|
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.create = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const commander_1 =
|
|
6
|
-
const validate_npm_package_name_1 =
|
|
7
|
-
const inquirer_1 =
|
|
8
|
-
const chalk_1 =
|
|
9
|
-
const path_1 =
|
|
10
|
-
const fs_1 =
|
|
11
|
-
const log_1 =
|
|
5
|
+
const commander_1 = tslib_1.__importDefault(require("commander"));
|
|
6
|
+
const validate_npm_package_name_1 = tslib_1.__importDefault(require("validate-npm-package-name"));
|
|
7
|
+
const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
|
|
8
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
9
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
10
|
+
const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
11
|
+
const log_1 = tslib_1.__importDefault(require("../../lib/log"));
|
|
12
12
|
const template_1 = require("../../lib/template");
|
|
13
13
|
const template_2 = require("./template");
|
|
14
14
|
async function create(args) {
|
|
15
15
|
const program = new commander_1.default.Command();
|
|
16
|
-
program.option("-t, --type <project type>", "project type (destination or
|
|
16
|
+
program.option("-t, --type <project type>", "project type (destination or source)");
|
|
17
17
|
program.option("-d, --dir <project_dir>", "project dir");
|
|
18
18
|
program.option("-n, --name <project_name>", "project name");
|
|
19
19
|
program.option("-j, --jitsu-version <jitsu_version>", "Jitsu version");
|
|
@@ -33,9 +33,9 @@ async function create(args) {
|
|
|
33
33
|
message: [
|
|
34
34
|
`What is the type of extension?`,
|
|
35
35
|
` ${chalk_1.default.bold("destination")} adds a new type of HTTP-based destination to Jitsu`,
|
|
36
|
-
` ${chalk_1.default.bold("
|
|
36
|
+
` ${chalk_1.default.bold("source")} adds a new source extension to Jitsu`,
|
|
37
37
|
].join("\n"),
|
|
38
|
-
choices: ["destination", "
|
|
38
|
+
choices: ["destination", "source"],
|
|
39
39
|
},
|
|
40
40
|
])).package;
|
|
41
41
|
let packageName = cliOpts.name ||
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import { CommandResult } from "../../lib/command/types";
|
|
2
|
-
export declare function
|
|
2
|
+
export declare function execSourceExtension(args: string[]): Promise<CommandResult>;
|
|
3
|
+
export declare function execDestinationExtension(args: string[]): Promise<CommandResult>;
|
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.execDestinationExtension = exports.execSourceExtension = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const commander_1 =
|
|
6
|
-
const log_1 =
|
|
7
|
-
const chalk_1 =
|
|
8
|
-
const path_1 =
|
|
9
|
-
const
|
|
10
|
-
const fs_1 =
|
|
5
|
+
const commander_1 = tslib_1.__importDefault(require("commander"));
|
|
6
|
+
const log_1 = tslib_1.__importDefault(require("../../lib/log"));
|
|
7
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
8
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
9
|
+
const JSON5 = tslib_1.__importStar(require("json5"));
|
|
10
|
+
const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
11
11
|
const index_1 = require("./index");
|
|
12
12
|
const indent_1 = require("../../lib/indent");
|
|
13
13
|
const chalk_code_highlight_1 = require("../../lib/chalk-code-highlight");
|
|
14
|
-
const validator_helper_1 = require("../../lib/validator-helper");
|
|
15
14
|
const errors_1 = require("../../lib/errors");
|
|
15
|
+
const validation_1 = require("../../lib/validation");
|
|
16
|
+
const build_1 = require("./build");
|
|
17
|
+
const sources_lib_1 = require("@jitsu/jlib/lib/sources-lib");
|
|
16
18
|
function getJson(json, file) {
|
|
17
19
|
if (json) {
|
|
18
|
-
return
|
|
20
|
+
return JSON5.parse(json);
|
|
19
21
|
}
|
|
20
22
|
else {
|
|
21
23
|
if (!fs_1.default.existsSync(file)) {
|
|
22
24
|
throw new Error(`File ${file} does not exist!`);
|
|
23
25
|
}
|
|
24
|
-
return
|
|
26
|
+
return JSON5.parse(fs_1.default.readFileSync(file, "utf-8"));
|
|
25
27
|
}
|
|
26
28
|
}
|
|
27
29
|
function ellipsis(str, opts = { maxLen: 80 }) {
|
|
@@ -36,52 +38,219 @@ function toArray(obj) {
|
|
|
36
38
|
return obj;
|
|
37
39
|
}
|
|
38
40
|
}
|
|
39
|
-
async function
|
|
41
|
+
async function loadExtension(directory) {
|
|
42
|
+
let projectBase = path_1.default.isAbsolute(directory) ? directory : path_1.default.resolve(process.cwd() + "/" + directory);
|
|
43
|
+
let packageFile = path_1.default.resolve(projectBase, "package.json");
|
|
44
|
+
if (!fs_1.default.existsSync(packageFile)) {
|
|
45
|
+
throw new Error("Can't find package.json in " + projectBase);
|
|
46
|
+
}
|
|
47
|
+
let distFile = path_1.default.resolve(projectBase, (0, index_1.getDistFile)(JSON5.parse(fs_1.default.readFileSync(packageFile, "utf-8"))));
|
|
48
|
+
(0, log_1.default)().info("⌛️ Loading extension (don't forget to build it before running exec!). Source: " + chalk_1.default.bold(distFile));
|
|
49
|
+
if (!fs_1.default.existsSync(path_1.default.resolve(projectBase, distFile))) {
|
|
50
|
+
throw new Error(`Can't find dist file ${chalk_1.default.bold(distFile)}. Does this dir contains jitsu extension? Have you run yarn build? `);
|
|
51
|
+
}
|
|
52
|
+
let extension = await (0, index_1.loadBuild)(distFile);
|
|
53
|
+
return { extension, distFile, projectBase };
|
|
54
|
+
}
|
|
55
|
+
async function execSourceExtension(args) {
|
|
56
|
+
const program = new commander_1.default.Command();
|
|
57
|
+
program.option("-c, --config <config_file_or_json>", "Configuration file path or inline extension configuration JSON");
|
|
58
|
+
program.option("-d, --dir <project_dir>", "project dir");
|
|
59
|
+
program.option("-s, --stream-config <json>", "Stream configuration as an object.");
|
|
60
|
+
program.option("-t, --state <file>", "Saved state object to file");
|
|
61
|
+
program.parse(["dummy", "dummy", ...args]);
|
|
62
|
+
let cliOpts = program.opts();
|
|
63
|
+
let directory = cliOpts.dir || ".";
|
|
64
|
+
await (0, build_1.build)([directory]);
|
|
65
|
+
const { extension } = await loadExtension(directory);
|
|
66
|
+
if (!extension.streamReader) {
|
|
67
|
+
return { success: false, message: `Extension doesn't export ${chalk_1.default.bold("streamReader")} symbol` };
|
|
68
|
+
}
|
|
69
|
+
if (!extension.sourceCatalog) {
|
|
70
|
+
return { success: false, message: `Extension doesn't export ${chalk_1.default.bold("sourceCatalog")} symbol` };
|
|
71
|
+
}
|
|
72
|
+
let configObject;
|
|
73
|
+
try {
|
|
74
|
+
configObject = (0, index_1.getConfigJson)(cliOpts.config);
|
|
75
|
+
}
|
|
76
|
+
catch (e) {
|
|
77
|
+
return {
|
|
78
|
+
success: false,
|
|
79
|
+
message: `Can't parse config JSON: '${cliOpts.config}' ${e.message})`,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const stateFile = path_1.default.resolve(cliOpts.state || `./src-${extension?.descriptor?.id || ""}-state.json`);
|
|
83
|
+
const stateFilePresent = fs_1.default.existsSync(stateFile);
|
|
84
|
+
if (stateFilePresent) {
|
|
85
|
+
(0, log_1.default)().info(`Loading state from ${chalk_1.default.bold(path_1.default.isAbsolute(stateFile))}`);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
(0, log_1.default)().info(`State file is missing, starting with empty state ${chalk_1.default.bold(stateFile)}`);
|
|
89
|
+
}
|
|
90
|
+
const stateObject = stateFilePresent ? JSON5.parse(fs_1.default.readFileSync(stateFile, "utf-8")) : {};
|
|
91
|
+
if (!extension.validator) {
|
|
92
|
+
(0, log_1.default)().info("⚠️ Extension doesn't support connection validation");
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
(0, log_1.default)().info("⌛️ Validating connection parameters...");
|
|
96
|
+
let validationError = await (0, validation_1.validateConfiguration)(configObject, extension.validator);
|
|
97
|
+
if (validationError) {
|
|
98
|
+
return {
|
|
99
|
+
success: false,
|
|
100
|
+
message: `Configuration validation failed: ${validationError}`,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
(0, log_1.default)().info("🙌️ Configuration is valid!");
|
|
104
|
+
}
|
|
105
|
+
(0, log_1.default)().info("🏃 Getting available streams...");
|
|
106
|
+
let streams = await extension.sourceCatalog(configObject);
|
|
107
|
+
streams.forEach(stream => {
|
|
108
|
+
let paramsDocs = (stream.params ?? []).map(param => `${param.id} - ${param.displayName}`).join(", ");
|
|
109
|
+
(0, log_1.default)().info(`🌊 Stream: ${chalk_1.default.bold(stream.type)}. Parameters: ${paramsDocs.length > 0 ? paramsDocs : "none"}`);
|
|
110
|
+
});
|
|
111
|
+
let stream;
|
|
112
|
+
let streamConfigObject = cliOpts.streamConfig && JSON5.parse(cliOpts.streamConfig);
|
|
113
|
+
let mode = streamConfigObject?.mode;
|
|
114
|
+
if (streams.length > 1) {
|
|
115
|
+
if (!streamConfigObject) {
|
|
116
|
+
return {
|
|
117
|
+
success: false,
|
|
118
|
+
message: `The connector exports more than one (${streams.length}) streams. Please specify stream name and config as -s {stream: 'name', ...}`,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
if (!streamConfigObject?.name) {
|
|
122
|
+
return {
|
|
123
|
+
success: false,
|
|
124
|
+
message: `Connector defines multiple streams (${streams.map(s => s.type)}). Specify stream name as as: -s {name: 'name', ...}`,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
stream = streams.find(stream => stream.type === streamConfigObject?.name);
|
|
128
|
+
if (!stream) {
|
|
129
|
+
return { success: false, message: `Stream with ${streamConfigObject?.name} is not found` };
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
stream = streams[0];
|
|
134
|
+
}
|
|
135
|
+
const modes = stream.supportedModes;
|
|
136
|
+
if (!mode && modes.length > 1) {
|
|
137
|
+
return {
|
|
138
|
+
success: false,
|
|
139
|
+
message: `Stream ${stream.type} supports multiple modes (${modes.join(", ")}). Please specify mode as -s {mode: '${modes[0]}', ...}`,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
if (mode && !modes.includes(mode)) {
|
|
143
|
+
return {
|
|
144
|
+
success: false,
|
|
145
|
+
message: `Stream ${stream.type} doesn't support mode ${mode}. Supported modes: ${modes.join(", ")}`,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
const effectiveMode = mode || modes[0];
|
|
149
|
+
const resultTable = newTable();
|
|
150
|
+
const sink = (0, sources_lib_1.makeStreamSink)({
|
|
151
|
+
msg(msg) {
|
|
152
|
+
if (msg.type === "record") {
|
|
153
|
+
(0, log_1.default)().info("[" + msg.type + "] " + (msg.message ? JSON.stringify(msg.message) : ""));
|
|
154
|
+
add(resultTable, msg.message);
|
|
155
|
+
}
|
|
156
|
+
else if (msg.type === "log") {
|
|
157
|
+
(0, log_1.default)()[msg.message?.["level"].toLowerCase()]?.("[" + msg.type + "] " + msg.message?.["message"]);
|
|
158
|
+
}
|
|
159
|
+
else if (msg.type === "state") {
|
|
160
|
+
(0, log_1.default)().info("[" + msg.type + "] " + (msg.message ? JSON.stringify(msg.message) : ""));
|
|
161
|
+
(0, log_1.default)().info(`💾 State was modified. Saving to: ${chalk_1.default.bold(path_1.default.isAbsolute(stateFile))}`);
|
|
162
|
+
fs_1.default.writeFileSync(stateFile, JSON.stringify(msg.message, null, 2));
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
(0, log_1.default)().info("[" + msg.type + "] " + (msg.message ? JSON.stringify(msg.message) : ""));
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
}, effectiveMode);
|
|
169
|
+
let streamConfiguration = { parameters: streamConfigObject };
|
|
170
|
+
if (mode) {
|
|
171
|
+
streamConfiguration.mode = mode;
|
|
172
|
+
}
|
|
173
|
+
await extension.streamReader(configObject, stream.type, streamConfiguration, sink, {
|
|
174
|
+
state: (0, sources_lib_1.stateService)(stateObject, sink),
|
|
175
|
+
});
|
|
176
|
+
(0, log_1.default)().info("🏁 Result data:");
|
|
177
|
+
console.log(JSON.stringify(resultTable.rows, null, 2));
|
|
178
|
+
console.log("Special column types: \n" +
|
|
179
|
+
Object.entries(resultTable.columns)
|
|
180
|
+
.filter(([colName, colValue]) => colValue.types.length > 0)
|
|
181
|
+
.map(([colName, colValue]) => `\t${colName}: ${colValue.types}`)
|
|
182
|
+
.join("\n"));
|
|
183
|
+
return { success: true };
|
|
184
|
+
}
|
|
185
|
+
exports.execSourceExtension = execSourceExtension;
|
|
186
|
+
function newTable() {
|
|
187
|
+
return { rows: [], columns: {} };
|
|
188
|
+
}
|
|
189
|
+
function add(t, rec) {
|
|
190
|
+
const newRow = {};
|
|
191
|
+
for (const [key, val] of Object.entries(rec)) {
|
|
192
|
+
if (key.indexOf("__sql_type") !== 0) {
|
|
193
|
+
if (t.columns[key] === undefined) {
|
|
194
|
+
t.columns[key] = { types: [] };
|
|
195
|
+
t.rows.forEach(row => (row[key] = undefined));
|
|
196
|
+
}
|
|
197
|
+
newRow[key] = Array.isArray(val) ? JSON.stringify(val) : val;
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
const columnName = key.substring("__sql_type_".length);
|
|
201
|
+
if (t.columns[columnName] === undefined) {
|
|
202
|
+
t.columns[columnName] = { types: [] };
|
|
203
|
+
}
|
|
204
|
+
let uniqueTypes = new Set(t.columns[columnName].types);
|
|
205
|
+
uniqueTypes.add(val);
|
|
206
|
+
t.columns[columnName].types = [...uniqueTypes];
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
Object.keys(t.columns).forEach(col => {
|
|
210
|
+
if (newRow[col] === undefined) {
|
|
211
|
+
newRow[col] = undefined;
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
t.rows.push(newRow);
|
|
215
|
+
}
|
|
216
|
+
async function execDestinationExtension(args) {
|
|
40
217
|
const program = new commander_1.default.Command();
|
|
41
218
|
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 <
|
|
43
|
-
program.option("-o, --config-object <file path>", "Config json");
|
|
219
|
+
program.option("-c, --config <config_file_or_json>", "Configuration file path or inline extension configuration JSON");
|
|
44
220
|
program.option("-j, --json <event json>", "Events JSON for processing (alternative to -f). Could be one object, or array of objects");
|
|
45
221
|
program.option("-d, --dir <project_dir>", "project dir");
|
|
46
222
|
program.option("-v, --skip-validation", "To skip config validation");
|
|
47
223
|
program.parse(["dummy", "dummy", ...args]);
|
|
48
224
|
let cliOpts = program.opts();
|
|
49
225
|
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
226
|
if (!cliOpts.json && !cliOpts.file) {
|
|
56
227
|
return { success: false, message: "Please specify -j or -f" };
|
|
57
228
|
}
|
|
58
229
|
if (cliOpts.json && cliOpts.file) {
|
|
59
230
|
return { success: false, message: "Both options -f and -j are provided. You should use either, not both" };
|
|
60
231
|
}
|
|
61
|
-
if (cliOpts.config
|
|
62
|
-
return { success: false, message: "
|
|
232
|
+
if (!cliOpts.config) {
|
|
233
|
+
return { success: false, message: "Please define config object -c json_file_path or -c '{json_object:}'" };
|
|
63
234
|
}
|
|
64
|
-
|
|
65
|
-
|
|
235
|
+
let config;
|
|
236
|
+
try {
|
|
237
|
+
config = (0, index_1.getConfigJson)(cliOpts.config);
|
|
66
238
|
}
|
|
67
|
-
|
|
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))) {
|
|
239
|
+
catch (e) {
|
|
73
240
|
return {
|
|
74
241
|
success: false,
|
|
75
|
-
message: `Can't
|
|
242
|
+
message: `Can't parse config JSON: '${cliOpts.config}' ${e.message})`,
|
|
76
243
|
};
|
|
77
244
|
}
|
|
78
|
-
|
|
245
|
+
const { extension, projectBase } = await loadExtension(directory);
|
|
246
|
+
(0, log_1.default)().info("🛂 Executing tests destination on " + chalk_1.default.bold(projectBase));
|
|
247
|
+
let events = toArray(getJson(cliOpts.json, cliOpts.file));
|
|
79
248
|
if (!extension.destination) {
|
|
80
249
|
return { success: false, message: "Extension doesn't export destination function" };
|
|
81
250
|
}
|
|
82
251
|
if (!cliOpts.skipValidation && extension.validator) {
|
|
83
252
|
(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,
|
|
253
|
+
let configError = await (0, validation_1.validateConfiguration)(config, extension.validator);
|
|
85
254
|
if (configError) {
|
|
86
255
|
return { success: false, message: "Config is not valid: " + configError };
|
|
87
256
|
}
|
|
@@ -124,4 +293,4 @@ async function execExtension(args) {
|
|
|
124
293
|
}
|
|
125
294
|
return { success: true };
|
|
126
295
|
}
|
|
127
|
-
exports.
|
|
296
|
+
exports.execDestinationExtension = execDestinationExtension;
|
|
@@ -2,7 +2,8 @@ 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" | "exec">;
|
|
5
|
+
export declare const extensionCommands: CommandRegistry<"test" | "build" | "create" | "validate-config" | "exec" | "exec-src">;
|
|
6
6
|
export declare function validateTsConfig(tsConfigPath: string): void;
|
|
7
7
|
export declare function getDistFile(packageJson: any): any;
|
|
8
|
-
export declare function
|
|
8
|
+
export declare function getConfigJson(jsonOrFile: string): any;
|
|
9
|
+
export declare function loadBuild(file: string): Promise<Partial<JitsuExtensionExport>>;
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.loadBuild = exports.getDistFile = exports.validateTsConfig = exports.extensionCommands = exports.help = void 0;
|
|
3
|
+
exports.loadBuild = exports.getConfigJson = exports.getDistFile = exports.validateTsConfig = exports.extensionCommands = exports.help = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const chalk_1 =
|
|
5
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
6
6
|
const chalk_code_highlight_1 = require("../../lib/chalk-code-highlight");
|
|
7
|
-
const fs =
|
|
7
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
8
8
|
const indent_1 = require("../../lib/indent");
|
|
9
9
|
const create_1 = require("./create");
|
|
10
10
|
const build_1 = require("./build");
|
|
11
11
|
const test_1 = require("./test");
|
|
12
12
|
const validate_config_1 = require("./validate-config");
|
|
13
13
|
const template_1 = require("./template");
|
|
14
|
-
const
|
|
14
|
+
const json5_1 = tslib_1.__importDefault(require("json5"));
|
|
15
15
|
const exec_1 = require("./exec");
|
|
16
|
+
const readline = tslib_1.__importStar(require("readline"));
|
|
17
|
+
const sandbox_1 = require("@jitsu/node-bridge/sandbox");
|
|
16
18
|
global.fetch = require("cross-fetch");
|
|
17
19
|
const usage = `
|
|
18
20
|
· ${chalk_1.default.bold("jitsu-cli extension create")}
|
|
@@ -58,9 +60,14 @@ ${chalk_1.default.bold("COMMANDS")} ${(0, indent_1.align)(usage, { indent: 2, ln
|
|
|
58
60
|
`;
|
|
59
61
|
exports.extensionCommands = {
|
|
60
62
|
exec: {
|
|
61
|
-
exec: exec_1.
|
|
62
|
-
description: "Execute extension
|
|
63
|
-
help: ""
|
|
63
|
+
exec: exec_1.execDestinationExtension,
|
|
64
|
+
description: "Execute destination extension on a test dataset",
|
|
65
|
+
help: "",
|
|
66
|
+
},
|
|
67
|
+
"exec-src": {
|
|
68
|
+
exec: exec_1.execSourceExtension,
|
|
69
|
+
description: "Builds and execute source connector extension with a test credentials and output data",
|
|
70
|
+
help: "",
|
|
64
71
|
},
|
|
65
72
|
test: {
|
|
66
73
|
exec: test_1.test,
|
|
@@ -86,7 +93,7 @@ exports.extensionCommands = {
|
|
|
86
93
|
function validateTsConfig(tsConfigPath) {
|
|
87
94
|
let tsConfig;
|
|
88
95
|
try {
|
|
89
|
-
tsConfig =
|
|
96
|
+
tsConfig = json5_1.default.parse(fs.readFileSync(tsConfigPath, "utf8"));
|
|
90
97
|
}
|
|
91
98
|
catch (e) {
|
|
92
99
|
throw new Error(`${chalk_1.default.bold(tsConfigPath)} - syntax error: ${e.message}`);
|
|
@@ -100,10 +107,41 @@ function getDistFile(packageJson) {
|
|
|
100
107
|
return packageJson.main || "dist/index.js";
|
|
101
108
|
}
|
|
102
109
|
exports.getDistFile = getDistFile;
|
|
103
|
-
function
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
110
|
+
async function getFirstLine(pathToFile) {
|
|
111
|
+
const readable = fs.createReadStream(pathToFile);
|
|
112
|
+
const reader = readline.createInterface({ input: readable });
|
|
113
|
+
const line = await new Promise(resolve => {
|
|
114
|
+
reader.on("line", line => {
|
|
115
|
+
reader.close();
|
|
116
|
+
resolve(line);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
readable.close();
|
|
120
|
+
return line;
|
|
121
|
+
}
|
|
122
|
+
function getConfigJson(jsonOrFile) {
|
|
123
|
+
if (jsonOrFile.trim().startsWith("{") && jsonOrFile.trim().endsWith("}")) {
|
|
124
|
+
return json5_1.default.parse(jsonOrFile.trim());
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
if (!fs.existsSync(jsonOrFile)) {
|
|
128
|
+
throw new Error(`File ${jsonOrFile} does not exist!`);
|
|
129
|
+
}
|
|
130
|
+
return json5_1.default.parse(fs.readFileSync(jsonOrFile, "utf8"));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
exports.getConfigJson = getConfigJson;
|
|
134
|
+
async function loadBuild(file) {
|
|
135
|
+
let formatDefinition = await getFirstLine(file);
|
|
136
|
+
if (formatDefinition.trim() === "//format=es" || formatDefinition.trim() === "//format=esm") {
|
|
137
|
+
return Promise.resolve().then(() => tslib_1.__importStar(require(file)));
|
|
138
|
+
}
|
|
139
|
+
else if (formatDefinition.trim() === "//format=cjs" || formatDefinition.trim() === "//format=commonjs") {
|
|
140
|
+
const vm = (0, sandbox_1.sandbox)({ file });
|
|
141
|
+
return vm.runFile(file);
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
throw new Error(`Unsupported build format - ${formatDefinition}`);
|
|
145
|
+
}
|
|
108
146
|
}
|
|
109
147
|
exports.loadBuild = loadBuild;
|
|
@@ -1,27 +1,30 @@
|
|
|
1
1
|
import { ProjectTemplate } from "../../lib/template";
|
|
2
|
-
export declare type
|
|
2
|
+
export declare type TemplateVars = {
|
|
3
3
|
license?: "MIT" | "Other";
|
|
4
4
|
packageName: string;
|
|
5
|
-
type: "destination" | "transform";
|
|
5
|
+
type: "destination" | "source" | "transform";
|
|
6
6
|
jitsuVersion?: string;
|
|
7
7
|
};
|
|
8
|
-
export declare const packageJsonTemplate: ({ packageName, type, jitsuVersion }:
|
|
8
|
+
export declare const packageJsonTemplate: ({ packageName, type, jitsuVersion }: TemplateVars) => {
|
|
9
9
|
name: string;
|
|
10
10
|
version: string;
|
|
11
11
|
description: string;
|
|
12
12
|
main: string;
|
|
13
13
|
scripts: {
|
|
14
|
+
clean: string;
|
|
14
15
|
build: string;
|
|
15
16
|
test: string;
|
|
16
17
|
"validate-config": string;
|
|
18
|
+
execute: string;
|
|
17
19
|
};
|
|
18
20
|
devDependencies: {
|
|
19
21
|
"@jitsu/types": string;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
dependencies: {
|
|
22
|
+
"@jitsu/jlib": string;
|
|
23
|
+
"ts-jest": string;
|
|
23
24
|
"jitsu-cli": string;
|
|
24
25
|
tslib: string;
|
|
26
|
+
typescript: string;
|
|
25
27
|
};
|
|
28
|
+
dependencies: {};
|
|
26
29
|
};
|
|
27
|
-
export declare const extensionProjectTemplate: ProjectTemplate<
|
|
30
|
+
export declare const extensionProjectTemplate: ProjectTemplate<TemplateVars>;
|
|
@@ -8,18 +8,21 @@ const packageJsonTemplate = ({ packageName, type, jitsuVersion = undefined }) =>
|
|
|
8
8
|
description: `Jitsu ${type} - ${packageName}`,
|
|
9
9
|
main: `dist/${packageName}.js`,
|
|
10
10
|
scripts: {
|
|
11
|
+
clean: "rm -rf ./dist",
|
|
11
12
|
build: "jitsu-cli extension build",
|
|
12
13
|
test: "jitsu-cli extension test",
|
|
13
14
|
"validate-config": "jitsu-cli extension validate-config",
|
|
15
|
+
execute: `jitsu-cli extension ${type == "destination" ? "exec" : "exec-src"}`,
|
|
14
16
|
},
|
|
15
17
|
devDependencies: {
|
|
16
18
|
"@jitsu/types": `${jitsuVersion || "^" + version_1.jitsuCliVersion}`,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
dependencies: {
|
|
19
|
+
"@jitsu/jlib": `${jitsuVersion || "^" + version_1.jitsuCliVersion}`,
|
|
20
|
+
"ts-jest": "^27.0.7",
|
|
20
21
|
"jitsu-cli": `${jitsuVersion || "^" + version_1.jitsuCliVersion}`,
|
|
21
22
|
tslib: "^2.3.1",
|
|
23
|
+
typescript: "^4.5.2",
|
|
22
24
|
},
|
|
25
|
+
dependencies: {},
|
|
23
26
|
});
|
|
24
27
|
exports.packageJsonTemplate = packageJsonTemplate;
|
|
25
28
|
let destinationTest = ({ type = "destination" }) => {
|
|
@@ -72,6 +75,100 @@ let destinationCode = () => {
|
|
|
72
75
|
};
|
|
73
76
|
`;
|
|
74
77
|
};
|
|
78
|
+
let sourceCode = () => {
|
|
79
|
+
return `
|
|
80
|
+
import { SourceCatalog, StateService, StreamReader, StreamSink, StreamConfiguration } from "@jitsu/types/sources";
|
|
81
|
+
import { ConfigValidationResult, ExtensionDescriptor } from "@jitsu/types/extension";
|
|
82
|
+
|
|
83
|
+
export interface SourceConfig {
|
|
84
|
+
user_id: string
|
|
85
|
+
my_source_param: string;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface StreamConfig {
|
|
89
|
+
my_stream_param: string;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async function validator(config: SourceConfig): Promise<ConfigValidationResult> {
|
|
93
|
+
//TODO: Check that provided config data allows to connect to third party API
|
|
94
|
+
console.log("validator is not yet implemented");
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const descriptor: ExtensionDescriptor<SourceConfig> = {
|
|
99
|
+
id: "my_source",
|
|
100
|
+
displayName: "Source Example",
|
|
101
|
+
description:
|
|
102
|
+
"Example source that produces row with run number and source/stream configuration.",
|
|
103
|
+
configurationParameters: [
|
|
104
|
+
{
|
|
105
|
+
displayName: "User ID",
|
|
106
|
+
id: "user_id",
|
|
107
|
+
type: "string",
|
|
108
|
+
required: true,
|
|
109
|
+
documentation: "User Id",
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
displayName: "Example Parameter",
|
|
113
|
+
id: "my_source_param",
|
|
114
|
+
required: true,
|
|
115
|
+
type: "string",
|
|
116
|
+
documentation: \`
|
|
117
|
+
<div>
|
|
118
|
+
Example Parameter
|
|
119
|
+
</div>
|
|
120
|
+
\`,
|
|
121
|
+
}
|
|
122
|
+
],
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const sourceCatalog: SourceCatalog<SourceConfig, StreamConfig> = async config => {
|
|
126
|
+
return [
|
|
127
|
+
{
|
|
128
|
+
type: "my_source_runs",
|
|
129
|
+
supportedModes: ["incremental"],
|
|
130
|
+
params: [
|
|
131
|
+
{
|
|
132
|
+
id: "my_stream_param",
|
|
133
|
+
displayName: "Stream Parameter",
|
|
134
|
+
type: "string",
|
|
135
|
+
documentation: \`
|
|
136
|
+
<div>
|
|
137
|
+
Stream Parameter example.
|
|
138
|
+
</div>
|
|
139
|
+
\`,
|
|
140
|
+
required: true,
|
|
141
|
+
},
|
|
142
|
+
]
|
|
143
|
+
}
|
|
144
|
+
];
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const streamReader: StreamReader<SourceConfig, StreamConfig> = async (
|
|
148
|
+
sourceConfig: SourceConfig,
|
|
149
|
+
streamType: string,
|
|
150
|
+
streamConfiguration: StreamConfiguration<StreamConfig>,
|
|
151
|
+
streamSink: StreamSink,
|
|
152
|
+
services: { state: StateService }
|
|
153
|
+
) => {
|
|
154
|
+
//Example of saved state usage. Read previous run number:
|
|
155
|
+
let runNumber = services.state.get("run_number") || 0;
|
|
156
|
+
runNumber++
|
|
157
|
+
streamSink.log("INFO", "Run number: " + runNumber);
|
|
158
|
+
streamSink.addRecord({
|
|
159
|
+
$id: runNumber,
|
|
160
|
+
$recordTimestamp: new Date(),
|
|
161
|
+
type: streamType,
|
|
162
|
+
...sourceConfig,
|
|
163
|
+
...streamConfiguration.parameters
|
|
164
|
+
});
|
|
165
|
+
//Save last run number to state
|
|
166
|
+
services.state.set("run_number", runNumber);
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
export { streamReader, sourceCatalog, descriptor, validator };
|
|
170
|
+
`;
|
|
171
|
+
};
|
|
75
172
|
let transformCode = () => {
|
|
76
173
|
return `
|
|
77
174
|
import {Destination, DestinationMessage, JitsuDestinationContext} from "@jitsu/types/destination";
|
|
@@ -124,7 +221,7 @@ exports.extensionProjectTemplate = {
|
|
|
124
221
|
"__test__/destination.test.ts": destinationTest,
|
|
125
222
|
"src/destination.ts": vars => vars.type == "destination" && destinationCode(),
|
|
126
223
|
"src/transform.ts": vars => vars.type == "transform" && transformCode(),
|
|
127
|
-
"src/index.ts": vars => descriptor[vars.type](vars),
|
|
224
|
+
"src/index.ts": vars => (vars.type == "source" ? sourceCode() : descriptor[vars.type](vars)),
|
|
128
225
|
"package.json": exports.packageJsonTemplate,
|
|
129
226
|
"tsconfig.json": {
|
|
130
227
|
compilerOptions: {
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.test = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const path_1 =
|
|
6
|
-
const log_1 =
|
|
7
|
-
const chalk_1 =
|
|
8
|
-
const fs_1 =
|
|
5
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
6
|
+
const log_1 = tslib_1.__importDefault(require("../../lib/log"));
|
|
7
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
8
|
+
const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
9
9
|
const jest_cli_1 = require("jest-cli");
|
|
10
10
|
const _1 = require("./");
|
|
11
11
|
async function test(args) {
|
|
@@ -24,7 +24,7 @@ async function test(args) {
|
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
(0, _1.validateTsConfig)(tsConfigPath);
|
|
27
|
-
|
|
27
|
+
const jestArgs = ["--passWithNoTests", "--projects", projectBase];
|
|
28
28
|
if (typescriptEnabled) {
|
|
29
29
|
jestArgs.push("--preset", "ts-jest");
|
|
30
30
|
}
|
|
@@ -2,47 +2,36 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.validateConfig = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const commander_1 =
|
|
6
|
-
const chalk_1 =
|
|
7
|
-
const path_1 =
|
|
8
|
-
const fs_1 =
|
|
9
|
-
const
|
|
10
|
-
const log_1 =
|
|
5
|
+
const commander_1 = tslib_1.__importDefault(require("commander"));
|
|
6
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
7
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
8
|
+
const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
9
|
+
const json5_1 = tslib_1.__importDefault(require("json5"));
|
|
10
|
+
const log_1 = tslib_1.__importDefault(require("../../lib/log"));
|
|
11
11
|
const index_1 = require("./index");
|
|
12
|
-
const
|
|
12
|
+
const validation_1 = require("../../lib/validation");
|
|
13
13
|
async function validateConfig(args) {
|
|
14
14
|
const program = new commander_1.default.Command();
|
|
15
15
|
program.option("-d, --dir <project_dir>", "Project directory");
|
|
16
|
-
program.option("-c, --config <
|
|
17
|
-
program.option("-o, --config-object <config_json>", "Inline extension configuration JSON");
|
|
16
|
+
program.option("-c, --config <config_file_or_json>", "Configuration file path or inline extension configuration JSON");
|
|
18
17
|
program.argument("[project_dir]");
|
|
19
18
|
program.parse(["dummy", "dummy", ...args]);
|
|
20
19
|
const opts = program.opts();
|
|
21
|
-
if (!opts.
|
|
20
|
+
if (!opts.config) {
|
|
22
21
|
return {
|
|
23
22
|
success: false,
|
|
24
|
-
message:
|
|
23
|
+
message: "Please define config object -c json_file_path or -c '{json_object:}'",
|
|
25
24
|
};
|
|
26
25
|
}
|
|
27
26
|
let configObj;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
configObj = JSON5_1.default.parse(opts.configObject);
|
|
31
|
-
}
|
|
32
|
-
catch (e) {
|
|
33
|
-
return { success: false, message: `Malformed json (-j): ${e.message}` };
|
|
34
|
-
}
|
|
27
|
+
try {
|
|
28
|
+
configObj = (0, index_1.getConfigJson)(opts.config);
|
|
35
29
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
configObj = JSON5_1.default.parse(fs_1.default.readFileSync(opts.config, "utf8"));
|
|
42
|
-
}
|
|
43
|
-
catch (e) {
|
|
44
|
-
return { success: false, message: `Malformed json in file ${opts.config} (-f): ${e.message}` };
|
|
45
|
-
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
return {
|
|
32
|
+
success: false,
|
|
33
|
+
message: `Can't parse config JSON: '${opts.config}' ${e.message})`,
|
|
34
|
+
};
|
|
46
35
|
}
|
|
47
36
|
let projectDir = opts.dir || ".";
|
|
48
37
|
(0, log_1.default)().info("Project dir: " + projectDir);
|
|
@@ -50,21 +39,20 @@ async function validateConfig(args) {
|
|
|
50
39
|
if (!fs_1.default.existsSync(packageFile)) {
|
|
51
40
|
return { success: false, message: `Can't find package file ${packageFile}` };
|
|
52
41
|
}
|
|
53
|
-
let packageObj =
|
|
42
|
+
let packageObj = json5_1.default.parse(fs_1.default.readFileSync(packageFile, "utf8"));
|
|
54
43
|
let distFile = path_1.default.resolve(projectDir, (0, index_1.getDistFile)(packageObj));
|
|
55
44
|
(0, log_1.default)().info("Dist file: " + distFile);
|
|
56
45
|
if (!fs_1.default.existsSync(distFile)) {
|
|
57
46
|
return { success: false, message: `Can't find dist file (${distFile}). Forgot to run jitsu-cli extension build ?` };
|
|
58
47
|
}
|
|
59
48
|
(0, log_1.default)().info("🤔 Loading build from " + chalk_1.default.bold(distFile));
|
|
60
|
-
let build = (0, index_1.loadBuild)(
|
|
49
|
+
let build = await (0, index_1.loadBuild)(distFile);
|
|
61
50
|
(0, log_1.default)().info("👍 Module loaded!");
|
|
62
51
|
if (!build.validator) {
|
|
63
52
|
return { success: false, message: "Build doesn't export validator symbol" };
|
|
64
53
|
}
|
|
65
|
-
(0, log_1.default)().info("🤔 Validating configuration " +
|
|
66
|
-
|
|
67
|
-
let validationError = await (0, validator_helper_1.validateConfiguration)(configObj, build.validator);
|
|
54
|
+
(0, log_1.default)().info("🤔 Validating configuration " + JSON.stringify(configObj));
|
|
55
|
+
let validationError = await (0, validation_1.validateConfiguration)(configObj, build.validator);
|
|
68
56
|
if (validationError) {
|
|
69
57
|
return { success: false, message: `❌ ${validationError}` };
|
|
70
58
|
}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.chalkCode = exports.defaultColorScheme = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const prismjs_1 =
|
|
6
|
-
const chalk_1 =
|
|
5
|
+
const prismjs_1 = tslib_1.__importDefault(require("prismjs"));
|
|
6
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
7
7
|
exports.defaultColorScheme = {
|
|
8
8
|
punctuation: "#999",
|
|
9
9
|
operator: "#9a6e3a",
|
package/lib/lib/command/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.subcommands = exports.executeCommand = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const chalk_1 =
|
|
5
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
6
6
|
const version_1 = require("../version");
|
|
7
7
|
function captureCommand(command, args) {
|
|
8
8
|
let commandParts = command.split(" ");
|
|
@@ -71,9 +71,11 @@ function displayHelp(commands, helpOpts, cmd) {
|
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
const executeCommand = async (commands, args, helpOpts) => {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
if (version_1.jitsuCliVersion !== "0.0.0") {
|
|
75
|
+
const newVersion = await (0, version_1.hasNewerVersion)();
|
|
76
|
+
if (newVersion) {
|
|
77
|
+
console.log((0, version_1.getUpgradeMessage)(newVersion, version_1.jitsuCliVersion));
|
|
78
|
+
}
|
|
77
79
|
}
|
|
78
80
|
if (args.length === 0 || isHelpOption(args[0])) {
|
|
79
81
|
displayHelp(commands, helpOpts);
|
package/lib/lib/indent.js
CHANGED
package/lib/lib/log.d.ts
CHANGED
package/lib/lib/log.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
|
-
const chalk_1 =
|
|
4
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
5
5
|
function log(delegate, styling, msg, args) {
|
|
6
6
|
if (!msg) {
|
|
7
7
|
delegate("");
|
|
@@ -20,6 +20,9 @@ function getLog() {
|
|
|
20
20
|
error(msg, ...args) {
|
|
21
21
|
log(console.error, { prefix: "error", color: "red" }, msg, args);
|
|
22
22
|
},
|
|
23
|
+
warn(msg, ...args) {
|
|
24
|
+
log(console.warn, { prefix: "warn ", color: "yellow" }, msg, args);
|
|
25
|
+
},
|
|
23
26
|
spinInfo(args) { },
|
|
24
27
|
info(msg, ...args) {
|
|
25
28
|
log(console.info, { prefix: "info ", color: "cyan" }, msg, args);
|
package/lib/lib/template.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.write = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const
|
|
6
|
-
const fs =
|
|
5
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
6
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
7
7
|
const indent_1 = require("./indent");
|
|
8
8
|
function toTemplateFunction(template) {
|
|
9
9
|
if (template === null || template === undefined) {
|
|
@@ -18,8 +18,8 @@ function toTemplateFunction(template) {
|
|
|
18
18
|
}
|
|
19
19
|
function write(dir, template, vars) {
|
|
20
20
|
Object.entries(template).forEach(([fileName, template]) => {
|
|
21
|
-
let filePath =
|
|
22
|
-
let fileDir =
|
|
21
|
+
let filePath = path_1.default.resolve(dir, fileName);
|
|
22
|
+
let fileDir = path_1.default.dirname(filePath);
|
|
23
23
|
if (!fs.existsSync(fileDir)) {
|
|
24
24
|
fs.mkdirSync(fileDir, { recursive: true });
|
|
25
25
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateConfiguration = void 0;
|
|
4
|
+
async function validateConfiguration(config, validator) {
|
|
5
|
+
let validationResult;
|
|
6
|
+
try {
|
|
7
|
+
validationResult = await validator(config);
|
|
8
|
+
}
|
|
9
|
+
catch (e) {
|
|
10
|
+
return e?.message || "Unknown exception";
|
|
11
|
+
}
|
|
12
|
+
if (validationResult === true) {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
if (typeof validationResult === "string") {
|
|
16
|
+
return validationResult;
|
|
17
|
+
}
|
|
18
|
+
if (typeof validationResult === "object" && !validationResult.ok) {
|
|
19
|
+
return validationResult.message ?? "Unknown error";
|
|
20
|
+
}
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
exports.validateConfiguration = validateConfiguration;
|
package/lib/lib/version.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const jitsuCliVersion: string;
|
|
2
2
|
export declare const jitsuPackageName: string;
|
|
3
|
-
export declare function getUpgradeMessage(newVersion: string): string;
|
|
3
|
+
export declare function getUpgradeMessage(newVersion: string, oldVersion: string): string;
|
|
4
4
|
export declare function box(msg: string): string;
|
|
5
5
|
export declare function hasNewerVersion(): Promise<string | undefined>;
|
package/lib/lib/version.js
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.hasNewerVersion = exports.box = exports.getUpgradeMessage = exports.jitsuPackageName = exports.jitsuCliVersion = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const package_json_1 =
|
|
6
|
-
const chalk_1 =
|
|
7
|
-
const log_1 =
|
|
8
|
-
const preload_1 =
|
|
5
|
+
const package_json_1 = tslib_1.__importDefault(require("../../package.json"));
|
|
6
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
7
|
+
const log_1 = tslib_1.__importDefault(require("./log"));
|
|
8
|
+
const preload_1 = tslib_1.__importDefault(require("semver/preload"));
|
|
9
9
|
const fetch = require("cross-fetch");
|
|
10
10
|
exports.jitsuCliVersion = package_json_1.default.version;
|
|
11
11
|
exports.jitsuPackageName = package_json_1.default.name;
|
|
12
12
|
let newVersion = undefined;
|
|
13
|
-
function getUpgradeMessage(newVersion) {
|
|
14
|
-
return box(`🚀 New version of Jitsu CLI is available: ${newVersion}
|
|
13
|
+
function getUpgradeMessage(newVersion, oldVersion) {
|
|
14
|
+
return box(`🚀 New version of Jitsu CLI is available: ${oldVersion} → ${chalk_1.default.green(newVersion)} \n Run ${chalk_1.default.bold("npm install -g " + exports.jitsuPackageName)} or ${chalk_1.default.bold("yarn global install " + exports.jitsuPackageName)}`);
|
|
15
15
|
}
|
|
16
16
|
exports.getUpgradeMessage = getUpgradeMessage;
|
|
17
17
|
function padRight(str, minLen, symbol = " ") {
|
package/lib/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jitsu-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.0.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
10
|
"url": "https://github.com/jitsucom/jitsu-sdk",
|
|
11
|
-
"directory": "
|
|
11
|
+
"directory": "core/jitsu-cli"
|
|
12
12
|
},
|
|
13
13
|
"bugs": {
|
|
14
14
|
"url": "https://github.com/jitsucom/jitsu/issues"
|
|
@@ -22,13 +22,14 @@
|
|
|
22
22
|
"bin"
|
|
23
23
|
],
|
|
24
24
|
"scripts": {
|
|
25
|
-
"build": "
|
|
26
|
-
"
|
|
27
|
-
"clean:some": "rm -rf ./lib",
|
|
25
|
+
"build": "tsc -p . && mv ./lib/src/* ./lib/ && rmdir ./lib/src/",
|
|
26
|
+
"clean": "rm -rf ./lib",
|
|
28
27
|
"start": "ts-node src/index.ts",
|
|
28
|
+
"cli": "node lib/index.js",
|
|
29
29
|
"test": "jest --verbose ./__tests__"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
+
"@jitsu/types": "workspace:*",
|
|
32
33
|
"@babel/preset-env": "^7.16.4",
|
|
33
34
|
"@babel/preset-typescript": "^7.16.0",
|
|
34
35
|
"@types/commander": "^2.12.2",
|
|
@@ -37,15 +38,19 @@
|
|
|
37
38
|
"@types/jest-cli": "^24.3.0",
|
|
38
39
|
"@types/validate-npm-package-name": "^3.0.3",
|
|
39
40
|
"child_process": "^1.0.2",
|
|
40
|
-
"lerna": "^4.0.0",
|
|
41
41
|
"ts-node": "^10.4.0"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@
|
|
44
|
+
"@jitsu/jlib": "workspace:*",
|
|
45
|
+
"@jitsu/node-bridge": "workspace:*",
|
|
46
|
+
"@rollup/plugin-commonjs": "^22.0.0-14",
|
|
47
|
+
"@rollup/plugin-inject": "^4.0.4",
|
|
48
|
+
"@rollup/plugin-json": "^4.1.0",
|
|
45
49
|
"@rollup/plugin-multi-entry": "^4.1.0",
|
|
46
50
|
"@rollup/plugin-node-resolve": "^13.0.6",
|
|
47
51
|
"@types/prismjs": "^1.16.6",
|
|
48
52
|
"chalk": "^4.1.2",
|
|
53
|
+
"cli-table": "latest",
|
|
49
54
|
"commander": "^8.3.0",
|
|
50
55
|
"cross-fetch": "^3.1.4",
|
|
51
56
|
"inquirer": "^8.2.0",
|
|
@@ -64,6 +69,5 @@
|
|
|
64
69
|
"tslib": "^2.3.1",
|
|
65
70
|
"typescript": "^4.5.2",
|
|
66
71
|
"validate-npm-package-name": "^3.0.0"
|
|
67
|
-
}
|
|
68
|
-
"gitHead": "4a5222ce49da3cb6be58648c78b1111b39764fe1"
|
|
72
|
+
}
|
|
69
73
|
}
|
package/lib/run.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.run = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const chalk_1 =
|
|
5
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
6
6
|
const command_1 = require("./lib/command");
|
|
7
7
|
const extension_1 = require("./cli/extension");
|
|
8
|
-
const log_1 =
|
|
8
|
+
const log_1 = tslib_1.__importDefault(require("./lib/log"));
|
|
9
9
|
const version_1 = require("./lib/version");
|
|
10
10
|
const commands = {
|
|
11
11
|
extension: (0, command_1.subcommands)(extension_1.extensionCommands, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jitsu-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0-alpha.169",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
10
|
"url": "https://github.com/jitsucom/jitsu-sdk",
|
|
11
|
-
"directory": "
|
|
11
|
+
"directory": "core/jitsu-cli"
|
|
12
12
|
},
|
|
13
13
|
"bugs": {
|
|
14
14
|
"url": "https://github.com/jitsucom/jitsu/issues"
|
|
@@ -21,14 +21,8 @@
|
|
|
21
21
|
"lib",
|
|
22
22
|
"bin"
|
|
23
23
|
],
|
|
24
|
-
"scripts": {
|
|
25
|
-
"build": "yarn clean:some && tsc -p . && mv ./lib/src/* ./lib/ && rmdir ./lib/src/",
|
|
26
|
-
"global": "yarn install -g",
|
|
27
|
-
"clean:some": "rm -rf ./lib",
|
|
28
|
-
"start": "ts-node src/index.ts",
|
|
29
|
-
"test": "jest --verbose ./__tests__"
|
|
30
|
-
},
|
|
31
24
|
"devDependencies": {
|
|
25
|
+
"@jitsu/types": "0.9.0-alpha.169",
|
|
32
26
|
"@babel/preset-env": "^7.16.4",
|
|
33
27
|
"@babel/preset-typescript": "^7.16.0",
|
|
34
28
|
"@types/commander": "^2.12.2",
|
|
@@ -37,15 +31,19 @@
|
|
|
37
31
|
"@types/jest-cli": "^24.3.0",
|
|
38
32
|
"@types/validate-npm-package-name": "^3.0.3",
|
|
39
33
|
"child_process": "^1.0.2",
|
|
40
|
-
"lerna": "^4.0.0",
|
|
41
34
|
"ts-node": "^10.4.0"
|
|
42
35
|
},
|
|
43
36
|
"dependencies": {
|
|
44
|
-
"@
|
|
37
|
+
"@jitsu/jlib": "0.9.0-alpha.169",
|
|
38
|
+
"@jitsu/node-bridge": "0.9.0-alpha.169",
|
|
39
|
+
"@rollup/plugin-commonjs": "^22.0.0-14",
|
|
40
|
+
"@rollup/plugin-inject": "^4.0.4",
|
|
41
|
+
"@rollup/plugin-json": "^4.1.0",
|
|
45
42
|
"@rollup/plugin-multi-entry": "^4.1.0",
|
|
46
43
|
"@rollup/plugin-node-resolve": "^13.0.6",
|
|
47
44
|
"@types/prismjs": "^1.16.6",
|
|
48
45
|
"chalk": "^4.1.2",
|
|
46
|
+
"cli-table": "latest",
|
|
49
47
|
"commander": "^8.3.0",
|
|
50
48
|
"cross-fetch": "^3.1.4",
|
|
51
49
|
"inquirer": "^8.2.0",
|
|
@@ -65,5 +63,11 @@
|
|
|
65
63
|
"typescript": "^4.5.2",
|
|
66
64
|
"validate-npm-package-name": "^3.0.0"
|
|
67
65
|
},
|
|
68
|
-
"
|
|
69
|
-
|
|
66
|
+
"scripts": {
|
|
67
|
+
"build": "tsc -p . && mv ./lib/src/* ./lib/ && rmdir ./lib/src/",
|
|
68
|
+
"clean": "rm -rf ./lib",
|
|
69
|
+
"start": "ts-node src/index.ts",
|
|
70
|
+
"cli": "node lib/index.js",
|
|
71
|
+
"test": "jest --verbose ./__tests__"
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -1,3 +0,0 @@
|
|
|
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)>;
|
|
@@ -1,21 +0,0 @@
|
|
|
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;
|