New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

jitsu-cli

Package Overview
Dependencies
Maintainers
0
Versions
77
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jitsu-cli - npm Package Compare versions

Comparing version

to
1.9.9-canary.1019.20241028095115

107

compiled/src/commands/build.js

@@ -25,38 +25,41 @@ "use strict";

}
const functionsDir = path_1.default.resolve(projectDir, "src/functions");
const files = (0, fs_1.readdirSync)(functionsDir);
try {
await buildFiles(projectDir);
}
catch (e) {
throw new Error(`Some of the functions failed to compile. See details above. Last error: ${e.message || "unknown"}`);
}
console.log(`${(0, chalk_code_highlight_1.b)("Build finished.")}`);
}
const run = async (cmd) => {
const child = (0, child_process_1.exec)(cmd, err => {
if (err) {
console.error(err);
return;
}
});
child.stdout?.pipe(process.stdout);
child.stderr?.pipe(process.stderr);
return new Promise(resolve => child.on("close", resolve));
};
async function buildFiles(projectDir, dir = "") {
let lastError = undefined;
const srcDir = path_1.default.resolve(projectDir, "src", dir);
const files = (0, fs_1.readdirSync)(srcDir);
if (files.length === 0) {
console.error(`No functions found in ${(0, chalk_code_highlight_1.b)("/src/functions")} directory`);
process.exit(0);
console.warn(`No functions found in ${(0, chalk_code_highlight_1.b)(srcDir)} directory`);
return;
}
let compiledFunction;
let lastError = undefined;
for (const file of files) {
if ((0, fs_1.lstatSync)(path_1.default.resolve(srcDir, file)).isDirectory()) {
try {
await buildFiles(projectDir, path_1.default.join(dir, file));
}
catch (e) {
lastError = e;
}
continue;
}
try {
const funcFile = path_1.default.resolve(functionsDir, file);
process.chdir(projectDir);
const rollupPlugins = [
(0, plugin_typescript_1.default)(),
(0, plugin_node_resolve_1.default)({ preferBuiltins: false }),
(0, plugin_commonjs_1.default)(),
(0, plugin_json_1.default)(),
];
const bundle = await (0, rollup_1.rollup)({
input: [funcFile],
plugins: rollupPlugins,
external: ["@jitsu/functions-lib"],
logLevel: "silent",
});
let format = "es";
let output = await bundle.generate({
dir: projectDir,
format: format,
});
(0, fs_1.mkdirSync)(path_1.default.resolve(projectDir, "dist/functions"), { recursive: true });
const compiledFunctionPath = `dist/functions/${file.replace(".ts", ".js")}`;
(0, fs_1.writeFileSync)(path_1.default.resolve(projectDir, compiledFunctionPath), output.output[0].code);
compiledFunction = await (0, compiled_function_1.getFunctionFromFilePath)(path_1.default.resolve(projectDir, compiledFunctionPath));
console.log([`${(0, chalk_code_highlight_1.green)(`✓`)} Function ${(0, chalk_code_highlight_1.b)(file)} compiled successfully`, ` slug = ${(0, chalk_code_highlight_1.b)(compiledFunction.meta.slug)}`]
.filter(Boolean)
.join("\n"));
await buildFile(projectDir, dir, file);
}

@@ -74,17 +77,33 @@ catch (e) {

if (lastError) {
throw new Error(`Some of the functions failed to compile. See details above. Last error: ${lastError?.message || "unknown"}`);
throw lastError;
}
console.log(`${(0, chalk_code_highlight_1.b)("Build finished.")}`);
}
const run = async (cmd) => {
const child = (0, child_process_1.exec)(cmd, err => {
if (err) {
console.error(err);
return;
}
async function buildFile(projectDir, dir, fileName) {
const funcFile = path_1.default.resolve(projectDir, "src", path_1.default.join(dir, fileName));
process.chdir(projectDir);
const rollupPlugins = [
(0, plugin_typescript_1.default)(),
(0, plugin_node_resolve_1.default)({ preferBuiltins: false }),
(0, plugin_commonjs_1.default)(),
(0, plugin_json_1.default)(),
];
const bundle = await (0, rollup_1.rollup)({
input: [funcFile],
plugins: rollupPlugins,
external: ["@jitsu/functions-lib"],
logLevel: "silent",
});
child.stdout?.pipe(process.stdout);
child.stderr?.pipe(process.stderr);
return new Promise(resolve => child.on("close", resolve));
};
let format = "es";
let output = await bundle.generate({
dir: projectDir,
format: format,
});
(0, fs_1.mkdirSync)(path_1.default.resolve(projectDir, "dist/" + dir), { recursive: true });
const compiledFunctionPath = `dist/${dir}/${fileName.replace(".ts", ".js")}`;
(0, fs_1.writeFileSync)(path_1.default.resolve(projectDir, compiledFunctionPath), output.output[0].code);
const compiledFunction = await (0, compiled_function_1.getFunctionFromFilePath)(path_1.default.resolve(projectDir, compiledFunctionPath), "function");
console.log([`${(0, chalk_code_highlight_1.green)(`✓`)} Function ${(0, chalk_code_highlight_1.b)(fileName)} compiled successfully`, ` slug = ${(0, chalk_code_highlight_1.b)(compiledFunction.meta.slug)}`]
.filter(Boolean)
.join("\n"));
}
function checkTypescript(projectDir) {

@@ -91,0 +110,0 @@ const tsconfigPath = path_1.default.resolve(projectDir, "tsconfig.json");

@@ -24,34 +24,6 @@ "use strict";

const { packageJson, projectDir } = await (0, shared_1.loadPackageJson)(dir || process.cwd());
const selected = names ? names.flatMap(n => n.split(",")).map(n => n.trim()) : undefined;
const configFile = `${(0, os_1.homedir)()}/.jitsu/jitsu-cli.json`;
const { host, apikey } = params.apikey
? { apikey: params.apikey, host: params.host || "https://use.jitsu.com" }
: readLoginFile();
const functionsDir = path_1.default.resolve(projectDir, "dist/functions");
if (!(0, fs_1.existsSync)(functionsDir)) {
console.error((0, chalk_code_highlight_1.red)(`Can't find dist directory: ${(0, chalk_code_highlight_1.b)(functionsDir)} . Please build project first.`));
process.exit(1);
}
console.log(`Deploying ${(0, chalk_code_highlight_1.b)(packageJson.name)} project.${selected ? ` (selected functions: ${selected.join(",")})` : ""}`);
const functionsFiles = (0, fs_1.readdirSync)(functionsDir);
if (functionsFiles.length === 0) {
console.error((0, chalk_code_highlight_1.red)(`Can't find function files in ${(0, chalk_code_highlight_1.b)("dist/functions")} directory. Please make sure that you have built the project.`));
process.exit(1);
}
const selectedFiles = [];
if (selected) {
const s = selected.map(n => (n.endsWith(".js") ? n : `${n.replace(".ts", "")}.js`));
for (const file of s) {
if (functionsFiles.includes(file)) {
selectedFiles.push(file);
}
else {
console.error((0, chalk_code_highlight_1.red)(`Can't find function file ${(0, chalk_code_highlight_1.b)(file)} in ${(0, chalk_code_highlight_1.b)("dist/functions")} directory. Please make sure that you have built the project.`));
process.exit(1);
}
}
}
else {
selectedFiles.push(...functionsFiles);
}
console.log(`Deploying ${(0, chalk_code_highlight_1.b)(packageJson.name)} project.${names && names.length > 0 ? ` (selected functions: ${names.join(",")})` : ""}`);
const res = await (0, node_fetch_1.default)(`${host}/api/workspace`, {

@@ -93,3 +65,2 @@ method: "GET",

const workspaceName = workspaceObj?.name;
const workspaceSlug = workspaceObj?.slug || workspaceObj?.id;
if (!workspaceId || !workspaceName) {

@@ -99,85 +70,143 @@ console.error((0, chalk_code_highlight_1.red)(`Workspace with id ${workspaceId} not found`));

}
await deployFunctions({ ...params, host, apikey, name: names }, projectDir, packageJson, workspaceObj, "function");
await deployFunctions({ ...params, host, apikey, name: names }, projectDir, packageJson, workspaceObj, "profile");
}
async function deployFunctions({ host, apikey, name: names }, projectDir, packageJson, workspace, kind) {
const selected = names ? names.flatMap(n => n.split(",")).map(n => n.trim()) : undefined;
const dir = `dist/${kind}s`;
const functionsDir = path_1.default.resolve(projectDir, dir);
const functionsFiles = (0, fs_1.readdirSync)(functionsDir);
if (functionsFiles.length === 0) {
console.warn((0, chalk_code_highlight_1.red)(`Can't find function files in ${(0, chalk_code_highlight_1.b)(dir)} directory. Please make sure that you have built the project.`));
process.exit(1);
}
const selectedFiles = [];
if (selected) {
const s = selected.map(n => (n.endsWith(".js") ? n : `${n.replace(".ts", "")}.js`));
for (const file of s) {
if (functionsFiles.includes(file)) {
selectedFiles.push(file);
}
else {
console.error((0, chalk_code_highlight_1.red)(`Can't find function file ${(0, chalk_code_highlight_1.b)(file)} in ${(0, chalk_code_highlight_1.b)(dir)} directory. Please make sure that you have built the project.`));
process.exit(1);
}
}
}
else {
selectedFiles.push(...functionsFiles);
}
let profileBuilders = [];
if (kind == "profile") {
const res = await (0, node_fetch_1.default)(`${host}/api/${workspace.id}/config/profile-builder`, {
method: "GET",
headers: {
Authorization: `Bearer ${apikey}`,
},
});
if (!res.ok) {
console.error((0, chalk_code_highlight_1.red)(`Cannot get profile builders list:\n${(0, chalk_code_highlight_1.b)(await res.text())}`));
process.exit(1);
}
profileBuilders = (await res.json()).profileBuilders;
}
for (const file of selectedFiles) {
console.log(`${(0, chalk_code_highlight_1.b)(`𝑓`)} Deploying function ${(0, chalk_code_highlight_1.b)(file)} to workspace ${workspaceName} (${host}/${workspaceSlug})`);
const code = (0, fs_1.readFileSync)(path_1.default.resolve(functionsDir, file), "utf-8");
const wrapped = await (0, compiled_function_1.getFunctionFromFilePath)(path_1.default.resolve(functionsDir, file));
const meta = wrapped.meta;
if (meta) {
console.log(` meta: slug=${meta.slug}, name=${meta.name || "not set"}`);
console.log(`${(0, chalk_code_highlight_1.b)(`𝑓`)} Deploying function ${(0, chalk_code_highlight_1.b)(path_1.default.basename(file))} to workspace ${workspace.name} (${host}/${workspace.slug || workspace.id})`);
await deployFunction({ host, apikey }, packageJson, workspace, kind, path_1.default.resolve(functionsDir, file), profileBuilders);
}
}
async function deployFunction({ host, apikey }, packageJson, workspace, kind, file, profileBuilders = []) {
const code = (0, fs_1.readFileSync)(file, "utf-8");
const wrapped = await (0, compiled_function_1.getFunctionFromFilePath)(file, kind, profileBuilders);
const meta = wrapped.meta;
if (meta) {
console.log(` meta: slug=${meta.slug}, name=${meta.name || "not set"}`);
}
else {
console.log(`File ${(0, chalk_code_highlight_1.b)(path_1.default.basename(file))} doesn't have function meta information. ${(0, chalk_code_highlight_1.red)("Skipping")}`);
return;
}
let existingFunctionId;
if (meta.slug) {
const res = await (0, node_fetch_1.default)(`${host}/api/${workspace.id}/config/function`, {
headers: {
Authorization: `Bearer ${apikey}`,
},
});
if (!res.ok) {
console.error((0, chalk_code_highlight_1.red)(`Cannot add function to workspace:\n${(0, chalk_code_highlight_1.b)(await res.text())}`));
process.exit(1);
}
else {
console.log(`File ${(0, chalk_code_highlight_1.b)(file)} doesn't have function meta information. ${(0, chalk_code_highlight_1.red)("Skipping")}`);
continue;
const existing = (await res.json());
existingFunctionId = existing.objects.find(f => f.slug === meta.slug || f.id === meta.id)?.id;
}
let existingFunctionId;
if (meta.slug) {
const res = await (0, node_fetch_1.default)(`${host}/api/${workspaceId}/config/function`, {
headers: {
Authorization: `Bearer ${apikey}`,
},
});
if (!res.ok) {
console.error((0, chalk_code_highlight_1.red)(`Cannot add function to workspace:\n${(0, chalk_code_highlight_1.b)(await res.text())}`));
process.exit(1);
}
else {
const existing = (await res.json());
existingFunctionId = existing.objects.find(f => f.slug === meta.slug)?.id;
}
}
let functionPayload = {};
if (kind === "profile") {
functionPayload = {
draft: code,
kind: "profile",
};
}
else {
functionPayload = {
code,
};
}
if (!existingFunctionId) {
const id = (0, cuid_1.default)();
const res = await (0, node_fetch_1.default)(`${host}/api/${workspace.id}/config/function`, {
method: "POST",
headers: {
Authorization: `Bearer ${apikey}`,
},
body: JSON.stringify({
id,
workspaceId: workspace.id,
type: "function",
origin: "jitsu-cli",
slug: meta.slug,
description: meta.description,
version: packageJson.version,
name: meta.name,
code,
...functionPayload,
}),
});
if (!res.ok) {
console.error((0, chalk_code_highlight_1.red)(`Cannot add function to workspace:\n${(0, chalk_code_highlight_1.b)(await res.text())}`));
process.exit(1);
}
if (!existingFunctionId) {
const id = (0, cuid_1.default)();
const res = await (0, node_fetch_1.default)(`${host}/api/${workspaceId}/config/function`, {
method: "POST",
headers: {
Authorization: `Bearer ${apikey}`,
},
body: JSON.stringify({
id,
workspaceId,
type: "function",
origin: "jitsu-cli",
slug: meta.slug,
description: meta.description,
version: packageJson.version,
name: meta.name,
code,
}),
});
if (!res.ok) {
console.error((0, chalk_code_highlight_1.red)(`Cannot add function to workspace:\n${(0, chalk_code_highlight_1.b)(await res.text())}`));
process.exit(1);
}
else {
console.log(`Function ${(0, chalk_code_highlight_1.b)(meta.name)} was successfully added to workspace ${workspaceName} with id: ${(0, chalk_code_highlight_1.b)(id)}`);
}
else {
console.log(`Function ${(0, chalk_code_highlight_1.b)(meta.name)} was successfully added to workspace ${workspace.name} with id: ${(0, chalk_code_highlight_1.b)(id)}`);
}
}
else {
const id = existingFunctionId;
const res = await (0, node_fetch_1.default)(`${host}/api/${workspace.id}/config/function/${id}`, {
method: "PUT",
headers: {
Authorization: `Bearer ${apikey}`,
},
body: JSON.stringify({
id: id,
workspaceId: workspace.id,
type: "function",
origin: "jitsu-cli",
slug: meta.slug,
description: meta.description,
version: packageJson.version,
name: meta.name,
...functionPayload,
}),
});
if (!res.ok) {
console.error((0, chalk_code_highlight_1.red)(`⚠ Cannot deploy function ${(0, chalk_code_highlight_1.b)(meta.slug)}(${id}):\n${(0, chalk_code_highlight_1.b)(await res.text())}`));
process.exit(1);
}
else {
const id = existingFunctionId;
const res = await (0, node_fetch_1.default)(`${host}/api/${workspaceId}/config/function/${id}`, {
method: "PUT",
headers: {
Authorization: `Bearer ${apikey}`,
},
body: JSON.stringify({
id: id,
workspaceId,
type: "function",
origin: "jitsu-cli",
slug: meta.slug,
description: meta.description,
version: packageJson.version,
name: meta.name,
code,
}),
});
if (!res.ok) {
console.error((0, chalk_code_highlight_1.red)(`⚠ Cannot deploy function ${(0, chalk_code_highlight_1.b)(meta.slug)}(${id}):\n${(0, chalk_code_highlight_1.b)(await res.text())}`));
process.exit(1);
}
else {
console.log(`${(0, chalk_code_highlight_1.green)(`✓`)} ${(0, chalk_code_highlight_1.b)(meta.name)} deployed successfully!`);
}
console.log(`${(0, chalk_code_highlight_1.green)(`✓`)} ${(0, chalk_code_highlight_1.b)(meta.name)} deployed successfully!`);
}
}
}

@@ -11,3 +11,3 @@ "use strict";

}
async function getFunctionFromFilePath(filePath) {
async function getFunctionFromFilePath(filePath, kind, profileBuilders = []) {
if (!fs_1.default.existsSync(filePath)) {

@@ -32,2 +32,16 @@ throw new Error(`Cannot load function from file ${filePath}: file doesn't exist`);

(0, juava_1.assertTrue)(typeof exports.default === "function", `Default export from ${filePath} is not a function`);
let name = exports.config?.name || exports.config?.slug || getSlug(filePath);
let id = exports.config?.id;
if (kind === "profile") {
const profileBuilderId = exports.config?.profileBuilderId;
const profileBuilder = profileBuilders.find(pb => pb.id === profileBuilderId);
if (!profileBuilder) {
throw new Error(`Cannot find profile builder with id ${profileBuilderId} for profile function ${filePath}. Please setup Profile Builder in UI first.`);
}
name = name || `${profileBuilder.name} function`;
id = id || profileBuilder.functions[0]?.functionId;
if (!id) {
throw new Error(`Cannot find function id for profile function ${filePath}. Please setup Profile Builder in UI first.`);
}
}
return {

@@ -37,3 +51,4 @@ func: exports.default,

slug: exports.config?.slug || getSlug(filePath),
name: exports.config?.name,
id: id,
name: name,
description: exports.config?.description,

@@ -40,0 +55,0 @@ },

@@ -65,7 +65,6 @@ "use strict";

return `
import { FunctionContext } from "@jitsu/protocols/functions";
import { AnalyticsServerEvent } from "@jitsu/protocols/analytics";
import { ProfileFunction } from "@jitsu/protocols/profile";
export const config = {
slug: "hello.ts", //id (uniq per workspace) used to identify function in Jitsu
slug: "profile-example.ts", //id (uniq per workspace) used to identify function in Jitsu
profileBuilderId: "", // id of Profile Builder object where this function will be used

@@ -75,5 +74,5 @@ description: ""

const helloWorldFunction: ProfileFunction = async ({ context, events, user}) => {
context.log.info("Profile func: " + user.userId)
const profile = {}
const profileExample: ProfileFunction = async ({ context, events, user}) => {
context.log.info("Profile func: " + user.id)
const profile = {} as any
for (const event of events) {

@@ -89,8 +88,8 @@ profile.lastMessageDate = Math.max(new Date(event.timestamp).getTime(),profile.lastMessageDate??0)

export default helloWorldFunction;
export default profileExample;
`;
};
const functionProjectTemplate = ({ packageName }) => ({
[`__test__/profiles/profile-example.test.ts`]: profileTest,
[`__test__/functions/hello.test.ts`]: functionTest,
[`__tests__/profiles/profile-example.test.ts`]: profileTest,
[`__tests__/functions/hello.test.ts`]: functionTest,
[`src/profiles/profile-example.ts`]: profileCode,

@@ -97,0 +96,0 @@ [`src/functions/hello.ts`]: functionCode,

{
"name": "jitsu-cli",
"version": "1.9.9-canary.990.20241015090416",
"version": "1.9.9-canary.1019.20241028095115",
"description": "",

@@ -55,5 +55,5 @@ "author": "Jitsu Dev Team <dev@jitsu.com>",

"webpack-cli": "^5.1.4",
"@jitsu/protocols": "1.9.9-canary.990.20241015090416",
"juava": "1.9.9-canary.990.20241015090416",
"@jitsu/functions-lib": "1.9.9-canary.990.20241015090416"
"@jitsu/protocols": "1.9.9-canary.1019.20241028095115",
"juava": "1.9.9-canary.1019.20241028095115",
"@jitsu/functions-lib": "1.9.9-canary.1019.20241028095115"
},

@@ -60,0 +60,0 @@ "scripts": {

import path from "path";
import { mkdirSync, readdirSync, writeFileSync, existsSync } from "fs";
import { mkdirSync, readdirSync, writeFileSync, existsSync, lstatSync } from "fs";
import typescript from "@rollup/plugin-typescript";

@@ -11,3 +11,3 @@ import resolve from "@rollup/plugin-node-resolve";

import { b, green, red } from "../lib/chalk-code-highlight";
import { CompiledFunction, getFunctionFromFilePath } from "../lib/compiled-function";
import { getFunctionFromFilePath } from "../lib/compiled-function";
import * as ts from "typescript";

@@ -25,48 +25,44 @@

//list files in src directory
const functionsDir = path.resolve(projectDir, "src/functions");
const files = readdirSync(functionsDir);
try {
await buildFiles(projectDir);
} catch (e: any) {
throw new Error(
`Some of the functions failed to compile. See details above. Last error: ${e.message || "unknown"}`
);
}
console.log(`${b("Build finished.")}`);
}
const run = async cmd => {
const child = exec(cmd, err => {
if (err) {
console.error(err);
return;
}
});
child.stdout?.pipe(process.stdout);
child.stderr?.pipe(process.stderr);
return new Promise(resolve => child.on("close", resolve));
};
async function buildFiles(projectDir: string, dir: string = "") {
let lastError: any = undefined;
const srcDir = path.resolve(projectDir, "src", dir);
const files = readdirSync(srcDir);
if (files.length === 0) {
console.error(`No functions found in ${b("/src/functions")} directory`);
process.exit(0);
console.warn(`No functions found in ${b(srcDir)} directory`);
return;
}
let compiledFunction: CompiledFunction;
let lastError: any = undefined;
for (const file of files) {
if (lstatSync(path.resolve(srcDir, file)).isDirectory()) {
try {
await buildFiles(projectDir, path.join(dir, file));
} catch (e: any) {
lastError = e;
}
continue;
}
try {
const funcFile = path.resolve(functionsDir, file);
process.chdir(projectDir);
const rollupPlugins = [
typescript(),
resolve({ preferBuiltins: false }),
commonjs(),
rollupJson(),
// terser(),
];
const bundle = await rollup({
input: [funcFile],
plugins: rollupPlugins,
external: ["@jitsu/functions-lib"],
logLevel: "silent",
});
let format: ModuleFormat = "es";
let output = await bundle.generate({
dir: projectDir,
format: format,
});
mkdirSync(path.resolve(projectDir, "dist/functions"), { recursive: true });
const compiledFunctionPath = `dist/functions/${file.replace(".ts", ".js")}`;
writeFileSync(path.resolve(projectDir, compiledFunctionPath), output.output[0].code);
//to verify that function is readable
compiledFunction = await getFunctionFromFilePath(path.resolve(projectDir, compiledFunctionPath));
console.log(
[`${green(`✓`)} Function ${b(file)} compiled successfully`, ` slug = ${b(compiledFunction.meta.slug)}`]
.filter(Boolean)
.join("\n")
);
await buildFile(projectDir, dir, file);
} catch (e: any) {

@@ -85,22 +81,43 @@ console.error(

if (lastError) {
throw new Error(
`Some of the functions failed to compile. See details above. Last error: ${lastError?.message || "unknown"}`
);
throw lastError;
}
console.log(`${b("Build finished.")}`);
}
const run = async cmd => {
const child = exec(cmd, err => {
if (err) {
console.error(err);
return;
}
async function buildFile(projectDir: string, dir: string, fileName: string) {
const funcFile = path.resolve(projectDir, "src", path.join(dir, fileName));
process.chdir(projectDir);
const rollupPlugins = [
typescript(),
resolve({ preferBuiltins: false }),
commonjs(),
rollupJson(),
// terser(),
];
const bundle = await rollup({
input: [funcFile],
plugins: rollupPlugins,
external: ["@jitsu/functions-lib"],
logLevel: "silent",
});
child.stdout?.pipe(process.stdout);
child.stderr?.pipe(process.stderr);
return new Promise(resolve => child.on("close", resolve));
};
let format: ModuleFormat = "es";
let output = await bundle.generate({
dir: projectDir,
format: format,
});
mkdirSync(path.resolve(projectDir, "dist/" + dir), { recursive: true });
const compiledFunctionPath = `dist/${dir}/${fileName.replace(".ts", ".js")}`;
writeFileSync(path.resolve(projectDir, compiledFunctionPath), output.output[0].code);
//to verify that function is readable
const compiledFunction = await getFunctionFromFilePath(path.resolve(projectDir, compiledFunctionPath), "function");
console.log(
[`${green(`✓`)} Function ${b(fileName)} compiled successfully`, ` slug = ${b(compiledFunction.meta.slug)}`]
.filter(Boolean)
.join("\n")
);
}
function checkTypescript(projectDir: string): string[] | void {

@@ -107,0 +124,0 @@ const tsconfigPath = path.resolve(projectDir, "tsconfig.json");

@@ -20,8 +20,3 @@ import path from "path";

export async function deploy({
dir,
workspace,
name: names,
...params
}: {
type Args = {
dir?: string;

@@ -32,8 +27,13 @@ workspace?: string;

host?: string;
}) {
};
type Workspace = {
id?: string;
name?: string[];
slug?: string;
};
export async function deploy({ dir, workspace, name: names, ...params }: Args) {
const { packageJson, projectDir } = await loadPackageJson(dir || process.cwd());
const selected = names ? names.flatMap(n => n.split(",")).map(n => n.trim()) : undefined;
const configFile = `${homedir()}/.jitsu/jitsu-cli.json`;
const { host, apikey } = params.apikey

@@ -43,42 +43,7 @@ ? { apikey: params.apikey, host: params.host || "https://use.jitsu.com" }

const functionsDir = path.resolve(projectDir, "dist/functions");
if (!existsSync(functionsDir)) {
console.error(red(`Can't find dist directory: ${b(functionsDir)} . Please build project first.`));
process.exit(1);
}
console.log(
`Deploying ${b(packageJson.name)} project.${selected ? ` (selected functions: ${selected.join(",")})` : ""}`
`Deploying ${b(packageJson.name)} project.${
names && names.length > 0 ? ` (selected functions: ${names.join(",")})` : ""
}`
);
const functionsFiles = readdirSync(functionsDir);
if (functionsFiles.length === 0) {
console.error(
red(
`Can't find function files in ${b(
"dist/functions"
)} directory. Please make sure that you have built the project.`
)
);
process.exit(1);
}
const selectedFiles: string[] = [];
if (selected) {
const s = selected.map(n => (n.endsWith(".js") ? n : `${n.replace(".ts", "")}.js`));
for (const file of s) {
if (functionsFiles.includes(file)) {
selectedFiles.push(file);
} else {
console.error(
red(
`Can't find function file ${b(file)} in ${b(
"dist/functions"
)} directory. Please make sure that you have built the project.`
)
);
process.exit(1);
}
}
} else {
selectedFiles.push(...functionsFiles);
}

@@ -123,3 +88,2 @@ const res = await fetch(`${host}/api/workspace`, {

const workspaceName = workspaceObj?.name;
const workspaceSlug = workspaceObj?.slug || workspaceObj?.id;
if (!workspaceId || !workspaceName) {

@@ -129,81 +93,174 @@ console.error(red(`Workspace with id ${workspaceId} not found`));

}
for (const file of selectedFiles) {
console.log(`${b(`𝑓`)} Deploying function ${b(file)} to workspace ${workspaceName} (${host}/${workspaceSlug})`);
const code = readFileSync(path.resolve(functionsDir, file), "utf-8");
const wrapped = await getFunctionFromFilePath(path.resolve(functionsDir, file));
const meta = wrapped.meta;
if (meta) {
console.log(` meta: slug=${meta.slug}, name=${meta.name || "not set"}`);
} else {
console.log(`File ${b(file)} doesn't have function meta information. ${red("Skipping")}`);
continue;
}
let existingFunctionId: string | undefined;
if (meta.slug) {
const res = await fetch(`${host}/api/${workspaceId}/config/function`, {
headers: {
Authorization: `Bearer ${apikey}`,
},
});
if (!res.ok) {
console.error(red(`Cannot add function to workspace:\n${b(await res.text())}`));
await deployFunctions({ ...params, host, apikey, name: names }, projectDir, packageJson, workspaceObj, "function");
await deployFunctions({ ...params, host, apikey, name: names }, projectDir, packageJson, workspaceObj, "profile");
}
async function deployFunctions(
{ host, apikey, name: names }: Args,
projectDir: string,
packageJson: any,
workspace: Workspace,
kind: "function" | "profile"
) {
const selected = names ? names.flatMap(n => n.split(",")).map(n => n.trim()) : undefined;
const dir = `dist/${kind}s`;
const functionsDir = path.resolve(projectDir, dir);
const functionsFiles = readdirSync(functionsDir);
if (functionsFiles.length === 0) {
console.warn(
red(`Can't find function files in ${b(dir)} directory. Please make sure that you have built the project.`)
);
process.exit(1);
}
const selectedFiles: string[] = [];
if (selected) {
const s = selected.map(n => (n.endsWith(".js") ? n : `${n.replace(".ts", "")}.js`));
for (const file of s) {
if (functionsFiles.includes(file)) {
selectedFiles.push(file);
} else {
console.error(
red(
`Can't find function file ${b(file)} in ${b(
dir
)} directory. Please make sure that you have built the project.`
)
);
process.exit(1);
} else {
const existing = (await res.json()) as any;
existingFunctionId = existing.objects.find(f => f.slug === meta.slug)?.id;
}
}
} else {
selectedFiles.push(...functionsFiles);
}
if (!existingFunctionId) {
const id = cuid();
const res = await fetch(`${host}/api/${workspaceId}/config/function`, {
method: "POST",
headers: {
Authorization: `Bearer ${apikey}`,
},
body: JSON.stringify({
id,
workspaceId,
type: "function",
origin: "jitsu-cli",
slug: meta.slug,
description: meta.description,
version: packageJson.version,
name: meta.name,
code,
}),
});
if (!res.ok) {
console.error(red(`Cannot add function to workspace:\n${b(await res.text())}`));
process.exit(1);
} else {
console.log(`Function ${b(meta.name)} was successfully added to workspace ${workspaceName} with id: ${b(id)}`);
}
let profileBuilders: any[] = [];
if (kind == "profile") {
const res = await fetch(`${host}/api/${workspace.id}/config/profile-builder`, {
method: "GET",
headers: {
Authorization: `Bearer ${apikey}`,
},
});
if (!res.ok) {
console.error(red(`Cannot get profile builders list:\n${b(await res.text())}`));
process.exit(1);
}
profileBuilders = ((await res.json()) as any).profileBuilders as any[];
}
for (const file of selectedFiles) {
console.log(
`${b(`𝑓`)} Deploying function ${b(path.basename(file))} to workspace ${workspace.name} (${host}/${
workspace.slug || workspace.id
})`
);
await deployFunction(
{ host, apikey },
packageJson,
workspace,
kind,
path.resolve(functionsDir, file),
profileBuilders
);
}
}
async function deployFunction(
{ host, apikey }: Args,
packageJson: any,
workspace: Workspace,
kind: "function" | "profile",
file: string,
profileBuilders: any[] = []
) {
const code = readFileSync(file, "utf-8");
const wrapped = await getFunctionFromFilePath(file, kind, profileBuilders);
const meta = wrapped.meta;
if (meta) {
console.log(` meta: slug=${meta.slug}, name=${meta.name || "not set"}`);
} else {
console.log(`File ${b(path.basename(file))} doesn't have function meta information. ${red("Skipping")}`);
return;
}
let existingFunctionId: string | undefined;
if (meta.slug) {
const res = await fetch(`${host}/api/${workspace.id}/config/function`, {
headers: {
Authorization: `Bearer ${apikey}`,
},
});
if (!res.ok) {
console.error(red(`Cannot add function to workspace:\n${b(await res.text())}`));
process.exit(1);
} else {
const id = existingFunctionId;
const res = await fetch(`${host}/api/${workspaceId}/config/function/${id}`, {
method: "PUT",
headers: {
Authorization: `Bearer ${apikey}`,
},
body: JSON.stringify({
id: id,
workspaceId,
type: "function",
origin: "jitsu-cli",
slug: meta.slug,
description: meta.description,
version: packageJson.version,
name: meta.name,
code,
}),
});
if (!res.ok) {
console.error(red(`⚠ Cannot deploy function ${b(meta.slug)}(${id}):\n${b(await res.text())}`));
process.exit(1);
} else {
console.log(`${green(`✓`)} ${b(meta.name)} deployed successfully!`);
}
const existing = (await res.json()) as any;
existingFunctionId = existing.objects.find(f => f.slug === meta.slug || f.id === meta.id)?.id;
}
}
let functionPayload = {};
if (kind === "profile") {
functionPayload = {
draft: code,
kind: "profile",
};
} else {
functionPayload = {
code,
};
}
if (!existingFunctionId) {
const id = cuid();
const res = await fetch(`${host}/api/${workspace.id}/config/function`, {
method: "POST",
headers: {
Authorization: `Bearer ${apikey}`,
},
body: JSON.stringify({
id,
workspaceId: workspace.id,
type: "function",
origin: "jitsu-cli",
slug: meta.slug,
description: meta.description,
version: packageJson.version,
name: meta.name,
// we always add code to the initial function creation
code,
...functionPayload,
}),
});
if (!res.ok) {
console.error(red(`Cannot add function to workspace:\n${b(await res.text())}`));
process.exit(1);
} else {
console.log(`Function ${b(meta.name)} was successfully added to workspace ${workspace.name} with id: ${b(id)}`);
}
} else {
const id = existingFunctionId;
const res = await fetch(`${host}/api/${workspace.id}/config/function/${id}`, {
method: "PUT",
headers: {
Authorization: `Bearer ${apikey}`,
},
body: JSON.stringify({
id: id,
workspaceId: workspace.id,
type: "function",
origin: "jitsu-cli",
slug: meta.slug,
description: meta.description,
version: packageJson.version,
name: meta.name,
...functionPayload,
}),
});
if (!res.ok) {
console.error(red(`⚠ Cannot deploy function ${b(meta.slug)}(${id}):\n${b(await res.text())}`));
process.exit(1);
} else {
console.log(`${green(`✓`)} ${b(meta.name)} deployed successfully!`);
}
}
}
import { JitsuFunction } from "@jitsu/protocols/functions";
import fs from "fs";
import { ModuleFormat, rollup } from "rollup";
import { rollup } from "rollup";
import { assertDefined, assertTrue } from "juava";

@@ -10,2 +10,3 @@

slug: string;
id?: string;
name?: string;

@@ -20,3 +21,7 @@ description?: string;

export async function getFunctionFromFilePath(filePath: string): Promise<CompiledFunction> {
export async function getFunctionFromFilePath(
filePath: string,
kind: "function" | "profile",
profileBuilders: any[] = []
): Promise<CompiledFunction> {
if (!fs.existsSync(filePath)) {

@@ -47,2 +52,21 @@ throw new Error(`Cannot load function from file ${filePath}: file doesn't exist`);

let name = exports.config?.name || exports.config?.slug || getSlug(filePath);
let id = exports.config?.id;
if (kind === "profile") {
const profileBuilderId = exports.config?.profileBuilderId;
const profileBuilder = profileBuilders.find(pb => pb.id === profileBuilderId);
if (!profileBuilder) {
throw new Error(
`Cannot find profile builder with id ${profileBuilderId} for profile function ${filePath}. Please setup Profile Builder in UI first.`
);
}
name = name || `${profileBuilder.name} function`;
id = id || profileBuilder.functions[0]?.functionId;
if (!id) {
throw new Error(
`Cannot find function id for profile function ${filePath}. Please setup Profile Builder in UI first.`
);
}
}
return {

@@ -52,3 +76,4 @@ func: exports.default,

slug: exports.config?.slug || getSlug(filePath),
name: exports.config?.name,
id: id,
name: name,
description: exports.config?.description,

@@ -55,0 +80,0 @@ },

@@ -73,7 +73,6 @@ import { ProjectTemplate } from "../lib/template";

return `
import { FunctionContext } from "@jitsu/protocols/functions";
import { AnalyticsServerEvent } from "@jitsu/protocols/analytics";
import { ProfileFunction } from "@jitsu/protocols/profile";
export const config = {
slug: "hello.ts", //id (uniq per workspace) used to identify function in Jitsu
slug: "profile-example.ts", //id (uniq per workspace) used to identify function in Jitsu
profileBuilderId: "", // id of Profile Builder object where this function will be used

@@ -83,5 +82,5 @@ description: ""

const helloWorldFunction: ProfileFunction = async ({ context, events, user}) => {
context.log.info("Profile func: " + user.userId)
const profile = {}
const profileExample: ProfileFunction = async ({ context, events, user}) => {
context.log.info("Profile func: " + user.id)
const profile = {} as any
for (const event of events) {

@@ -97,3 +96,3 @@ profile.lastMessageDate = Math.max(new Date(event.timestamp).getTime(),profile.lastMessageDate??0)

export default helloWorldFunction;
export default profileExample;
`;

@@ -103,4 +102,4 @@ };

export const functionProjectTemplate: ProjectTemplate<TemplateVars> = ({ packageName }: TemplateVars) => ({
[`__test__/profiles/profile-example.test.ts`]: profileTest,
[`__test__/functions/hello.test.ts`]: functionTest,
[`__tests__/profiles/profile-example.test.ts`]: profileTest,
[`__tests__/functions/hello.test.ts`]: functionTest,
[`src/profiles/profile-example.ts`]: profileCode,

@@ -107,0 +106,0 @@ [`src/functions/hello.ts`]: functionCode,

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet