@paralect/hive 0.0.2 → 0.0.4
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/cli/helpers/axiosAuth.js +12 -0
- package/cli/helpers/downloadDirectory.js +46 -0
- package/cli/helpers/execCommand.js +48 -0
- package/cli/helpers/isAuthorized.js +41 -0
- package/cli/helpers/isProjectInit.js +71 -0
- package/cli/helpers/mergeDirs.js +71 -0
- package/cli/hive.js +158 -43
- package/package.json +8 -3
- package/starter/.babelrc +3 -0
- package/starter/.dockerignore +1 -0
- package/starter/Dockerfile +16 -7
- package/starter/bin/deploy.sh +5 -0
- package/starter/deploy/api/Chart.yaml +6 -0
- package/starter/deploy/api/staging.yaml +3 -0
- package/starter/deploy/api/templates/deployment.yaml +44 -0
- package/starter/deploy/api/templates/ingress.yaml +26 -0
- package/starter/deploy/api/templates/service.yaml +14 -0
- package/starter/deploy/script/Dockerfile +39 -0
- package/starter/deploy/script/package-lock.json +1499 -0
- package/starter/deploy/script/package.json +12 -0
- package/starter/deploy/script/src/config.js +48 -0
- package/starter/deploy/script/src/index.js +106 -0
- package/starter/deploy/script/src/util.js +19 -0
- package/starter/package-lock.json +3363 -139
- package/starter/package.json +9 -1
- package/starter/src/app-config/index.js +10 -0
- package/starter/src/db.js +13 -3
- package/starter/src/emails/MyEmailComponent.jsx +16 -0
- package/starter/src/emails/compiled/MyEmailComponent.js +17 -0
- package/starter/src/helpers/getResourceEndpoints.js +15 -13
- package/starter/src/helpers/getResources.js +2 -1
- package/starter/src/helpers/getSchemas.js +3 -0
- package/starter/src/middlewares/shouldExist.js +24 -4
- package/starter/src/resources/health/endpoints/get.js +7 -0
- package/starter/src/resources/users/endpoints/getCurrentUser.js +4 -1
- package/starter/src/resources/users/endpoints/getUserProfile.js +3 -2
- package/starter/src/resources/users/methods/ensureUserCreated.js +7 -7
- package/starter/src/resources/users/users.schema.js +1 -1
- package/starter/src/routes/index.js +1 -1
- package/starter/src/services/emailService.js +15 -0
- package/starter/bin/init-project.sh +0 -22
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
|
|
3
|
+
module.exports = (options) => {
|
|
4
|
+
return axios({
|
|
5
|
+
...options,
|
|
6
|
+
// url: options.url.startsWith('http') ? options.url : `https://hive-api-test.paralect.co/${options.url}`,
|
|
7
|
+
url: options.url.startsWith('http') ? options.url : `http://localhost:3001/${options.url}`,
|
|
8
|
+
headers: {
|
|
9
|
+
...(options?.headers || {}),
|
|
10
|
+
...(process.env.HIVE_TOKEN ? { Authorization: `Bearer ${process.env.HIVE_TOKEN}` } : {})}
|
|
11
|
+
})
|
|
12
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const fs = require('fs-extra');
|
|
3
|
+
const axios = require('axios');
|
|
4
|
+
|
|
5
|
+
const GITHUB_API_URL = 'https://api.github.com/repos';
|
|
6
|
+
|
|
7
|
+
async function fetchDirectoryTree(owner, repo, dirPath) {
|
|
8
|
+
const url = `${GITHUB_API_URL}/${owner}/${repo}/contents/${dirPath}`;
|
|
9
|
+
const response = await axios.get(url);
|
|
10
|
+
return response.data;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function downloadFile(fileUrl, filePath) {
|
|
14
|
+
const response = await axios({
|
|
15
|
+
url: fileUrl,
|
|
16
|
+
method: 'GET',
|
|
17
|
+
responseType: 'stream'
|
|
18
|
+
});
|
|
19
|
+
await fs.ensureDir(path.dirname(filePath));
|
|
20
|
+
response.data.pipe(fs.createWriteStream(filePath));
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
response.data.on('end', resolve);
|
|
23
|
+
response.data.on('error', reject);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function downloadDirectory(pluginName, baseDir = '') {
|
|
28
|
+
const owner = 'paralect';
|
|
29
|
+
const repo = 'hive-plugins';
|
|
30
|
+
|
|
31
|
+
const destDir = path.join(process.cwd(), baseDir);
|
|
32
|
+
|
|
33
|
+
const tree = await fetchDirectoryTree(owner, repo, pluginName);
|
|
34
|
+
for (const item of tree) {
|
|
35
|
+
const relativePath = path.relative(pluginName, item.path);
|
|
36
|
+
const filePath = path.join(destDir, relativePath);
|
|
37
|
+
if (item.type === 'file') {
|
|
38
|
+
console.log(`Downloading ${item.path}...`);
|
|
39
|
+
await downloadFile(item.download_url, filePath);
|
|
40
|
+
} else if (item.type === 'dir') {
|
|
41
|
+
await downloadDirectory(item.path, path.join(baseDir, relativePath));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
module.exports = downloadDirectory;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
const execa = require('execa');
|
|
5
|
+
const mkdirp = require('mkdirp');
|
|
6
|
+
|
|
7
|
+
const execCommand = async (command, options = {}, outputFileSrc = null) => {
|
|
8
|
+
let commandParts = command;
|
|
9
|
+
|
|
10
|
+
if (typeof command === 'string') {
|
|
11
|
+
commandParts = command
|
|
12
|
+
.split(/ +(?=(?:(?:[^"]*"){2})*[^"]*$)/g)
|
|
13
|
+
.map((commandPart) => {
|
|
14
|
+
if (
|
|
15
|
+
commandPart[0] === '"' &&
|
|
16
|
+
commandPart[commandPart.length - 1] === '"'
|
|
17
|
+
) {
|
|
18
|
+
return commandPart.replace(/["]+/g, '', '');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return commandPart;
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// commandParts = command.split(' ').filter((part) => !!part.trim());
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const commandName = commandParts.shift();
|
|
28
|
+
const commandArguments = commandParts;
|
|
29
|
+
|
|
30
|
+
const process = execa(commandName, commandArguments, {
|
|
31
|
+
stdio: outputFileSrc ? 'pipe' : 'inherit',
|
|
32
|
+
...options,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
if (outputFileSrc) {
|
|
36
|
+
console.log('writing to outputFileSrc', outputFileSrc);
|
|
37
|
+
const dir = path.dirname(outputFileSrc);
|
|
38
|
+
|
|
39
|
+
await mkdirp(dir);
|
|
40
|
+
console.log(dir, fs.existsSync(dir));
|
|
41
|
+
|
|
42
|
+
process.stdout.pipe(fs.createWriteStream(outputFileSrc, { flags: 'a+' }));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return process;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
module.exports = execCommand;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const inquirer = require('inquirer');
|
|
3
|
+
|
|
4
|
+
module.exports = async () => {
|
|
5
|
+
if (!process.env.HIVE_TOKEN) {
|
|
6
|
+
const { email } = await inquirer.prompt([
|
|
7
|
+
{
|
|
8
|
+
type: 'input',
|
|
9
|
+
name: 'email',
|
|
10
|
+
message: 'Please enter your email:'
|
|
11
|
+
}
|
|
12
|
+
]);
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
await axios({ url: `https://hive-api-test.paralect.co/auth/login-code`, method: 'post', data: { email } });
|
|
16
|
+
|
|
17
|
+
const { code } = await inquirer.prompt([
|
|
18
|
+
{
|
|
19
|
+
type: 'input',
|
|
20
|
+
name: 'code',
|
|
21
|
+
message: `One time code (sent to ${email})`,
|
|
22
|
+
}
|
|
23
|
+
]);
|
|
24
|
+
|
|
25
|
+
const { token, user } = (await axios({ url: `https://hive-api-test.paralect.co/auth/verify-login`, method: 'post', data: { email, code } })).data;
|
|
26
|
+
|
|
27
|
+
console.log(`
|
|
28
|
+
You're now logged into Hive! Welcome 🐝
|
|
29
|
+
|
|
30
|
+
Important: to save access add HIVE_TOKEN to your env variables and your ~/.zshrc file
|
|
31
|
+
|
|
32
|
+
export HIVE_TOKEN=${token}`);
|
|
33
|
+
|
|
34
|
+
return { token, user };
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.error('An error occurred:', error.message);
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
return { token: process.env.HIVE_TOKEN };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const axios = require('./axiosAuth');
|
|
4
|
+
const inquirer = require('inquirer');
|
|
5
|
+
|
|
6
|
+
module.exports = async () => {
|
|
7
|
+
if (!process.env.PROJECT_ID) {
|
|
8
|
+
let projectConfigPath = path.resolve(process.env.HIVE_SRC, './hive.config.js');
|
|
9
|
+
|
|
10
|
+
if (fs.existsSync(projectConfigPath)) {
|
|
11
|
+
const config = require(projectConfigPath);
|
|
12
|
+
if (config.projectId) {
|
|
13
|
+
process.env.PROJECT_ID = config.projectId;
|
|
14
|
+
}
|
|
15
|
+
} else {
|
|
16
|
+
const projectPackageJsonPath = path.resolve(process.env.HIVE_SRC, './package.json');
|
|
17
|
+
|
|
18
|
+
let projectName;
|
|
19
|
+
|
|
20
|
+
if (fs.existsSync(projectPackageJsonPath)) {
|
|
21
|
+
const { name } = require(projectPackageJsonPath);
|
|
22
|
+
projectName = name;
|
|
23
|
+
} else {
|
|
24
|
+
const { name } = await inquirer.prompt([
|
|
25
|
+
{
|
|
26
|
+
type: 'input',
|
|
27
|
+
name: 'name',
|
|
28
|
+
message: 'Project Name'
|
|
29
|
+
}
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
projectName = name;
|
|
33
|
+
|
|
34
|
+
fs.writeFileSync(projectPackageJsonPath, `${JSON.stringify({
|
|
35
|
+
name: name,
|
|
36
|
+
|
|
37
|
+
scripts: {
|
|
38
|
+
"dev": "nodemon --watch . --exec hive run .",
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
dependencies: {
|
|
42
|
+
"@paralect/hive": "^0.0.4"
|
|
43
|
+
},
|
|
44
|
+
devDependencies: {
|
|
45
|
+
"nodemon": "^3.1.4"
|
|
46
|
+
}
|
|
47
|
+
}, null, 2)}`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const project = (await axios({ url: `projects`, method: 'post', data: { name: projectName } })).data;
|
|
51
|
+
|
|
52
|
+
fs.writeFileSync(projectConfigPath, `module.exports = { projectId: '${project._id}' } `);
|
|
53
|
+
|
|
54
|
+
const projectEnvPath = path.resolve(process.env.HIVE_SRC, './config/.env');
|
|
55
|
+
|
|
56
|
+
if (project?.envs?.staging) {
|
|
57
|
+
if (!fs.existsSync(path.resolve(process.env.HIVE_SRC, './config'))) {
|
|
58
|
+
fs.mkdirSync(path.resolve(process.env.HIVE_SRC, './config'));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
fs.writeFileSync(projectEnvPath, Object.keys(project.envs.staging).map(key => `${key}=${project.envs.staging[key]}`).join('\n'));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
console.log(`Successfully initialised project ${projectName}!`);
|
|
65
|
+
|
|
66
|
+
process.env.PROJECT_ID = project._id;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return { projectId: process.env.PROJECT_ID };
|
|
71
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
function shouldIgnore(filePath) {
|
|
6
|
+
const ignoredDirs = ['node_modules', 'dist', '.git'];
|
|
7
|
+
return ignoredDirs.some(dir => filePath.includes(path.sep + dir + path.sep));
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async function copyDir(src, dest) {
|
|
11
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
12
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
13
|
+
|
|
14
|
+
for (let entry of entries) {
|
|
15
|
+
const srcPath = path.join(src, entry.name);
|
|
16
|
+
const destPath = path.join(dest, entry.name);
|
|
17
|
+
|
|
18
|
+
if (shouldIgnore(srcPath)) {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (entry.isDirectory()) {
|
|
23
|
+
await copyDir(srcPath, destPath);
|
|
24
|
+
} else {
|
|
25
|
+
console.log('copy', srcPath, destPath)
|
|
26
|
+
await fs.copyFileSync(srcPath, destPath);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function copyRootFiles(sourceDir, destDir) {
|
|
32
|
+
try {
|
|
33
|
+
// Read all items in the source directory
|
|
34
|
+
const items = await fs.promises.readdir(sourceDir, { withFileTypes: true });
|
|
35
|
+
|
|
36
|
+
// Ensure the destination directory exists
|
|
37
|
+
await fs.promises.mkdir(destDir, { recursive: true });
|
|
38
|
+
|
|
39
|
+
// Iterate over each item
|
|
40
|
+
for (const item of items) {
|
|
41
|
+
const sourcePath = path.join(sourceDir, item.name);
|
|
42
|
+
const destPath = path.join(destDir, item.name);
|
|
43
|
+
|
|
44
|
+
// Check if the item is a file and not package.json
|
|
45
|
+
if (item.isFile() && item.name !== 'package.json') {
|
|
46
|
+
// Copy the file to the destination directory
|
|
47
|
+
await fs.promises.copyFile(sourcePath, destPath);
|
|
48
|
+
console.log(`Copied: ${sourcePath} -> ${destPath}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
console.log('Files copied successfully.');
|
|
53
|
+
} catch (error) {
|
|
54
|
+
console.error('An error occurred:', error.message);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function mergeDirectories(sourceDir1, sourceDir2, targetDir) {
|
|
59
|
+
// First, copy all contents from sourceDir1 to targetDir
|
|
60
|
+
await copyDir(sourceDir1, targetDir);
|
|
61
|
+
|
|
62
|
+
// Then, copy and extend/overwrite with contents from sourceDir2
|
|
63
|
+
await copyDir(sourceDir2, `${targetDir}/src`);
|
|
64
|
+
await copyRootFiles(sourceDir2, targetDir);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
module.exports = async ({ hiveSrc, outDir }) => {
|
|
68
|
+
await mergeDirectories(path.resolve(__dirname, './../../starter'), hiveSrc, outDir);
|
|
69
|
+
|
|
70
|
+
console.log('Merged resources');
|
|
71
|
+
}
|
package/cli/hive.js
CHANGED
|
@@ -1,50 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const { program } = require('commander');
|
|
4
|
-
const axios = require('axios');
|
|
5
|
-
const fs = require('fs-extra');
|
|
6
|
-
const path = require('path');
|
|
7
|
-
|
|
8
|
-
const GITHUB_API_URL = 'https://api.github.com/repos';
|
|
9
4
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const response = await axios({
|
|
18
|
-
url: fileUrl,
|
|
19
|
-
method: 'GET',
|
|
20
|
-
responseType: 'stream'
|
|
21
|
-
});
|
|
22
|
-
await fs.ensureDir(path.dirname(filePath));
|
|
23
|
-
response.data.pipe(fs.createWriteStream(filePath));
|
|
24
|
-
return new Promise((resolve, reject) => {
|
|
25
|
-
response.data.on('end', resolve);
|
|
26
|
-
response.data.on('error', reject);
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async function downloadDirectory(pluginName, baseDir = '') {
|
|
31
|
-
const owner = 'paralect';
|
|
32
|
-
const repo = 'hive-plugins';
|
|
33
|
-
|
|
34
|
-
const destDir = path.join(process.cwd(), baseDir);
|
|
35
|
-
|
|
36
|
-
const tree = await fetchDirectoryTree(owner, repo, pluginName);
|
|
37
|
-
for (const item of tree) {
|
|
38
|
-
const relativePath = path.relative(pluginName, item.path);
|
|
39
|
-
const filePath = path.join(destDir, relativePath);
|
|
40
|
-
if (item.type === 'file') {
|
|
41
|
-
console.log(`Downloading ${item.path}...`);
|
|
42
|
-
await downloadFile(item.download_url, filePath);
|
|
43
|
-
} else if (item.type === 'dir') {
|
|
44
|
-
await downloadDirectory(item.path, path.join(baseDir, relativePath));
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const isAuthorized = require('./helpers/isAuthorized');
|
|
7
|
+
const mergeDirs = require('./helpers/mergeDirs');
|
|
8
|
+
const execCommand = require('./helpers/execCommand');
|
|
9
|
+
const downloadDirectory = require('./helpers/downloadDirectory');
|
|
10
|
+
const axios = require('./helpers/axiosAuth');
|
|
11
|
+
const isProjectInit = require('./helpers/isProjectInit.js');
|
|
48
12
|
|
|
49
13
|
program
|
|
50
14
|
.command('run [dirPath]')
|
|
@@ -58,6 +22,66 @@ program
|
|
|
58
22
|
}
|
|
59
23
|
});
|
|
60
24
|
|
|
25
|
+
program
|
|
26
|
+
.command('deploy [imageTag]')
|
|
27
|
+
.description('Build and deploy Hive project from local machine docker + helm')
|
|
28
|
+
.action(async (imageTag) => {
|
|
29
|
+
process.env.HIVE_SRC = path.resolve(process.cwd());
|
|
30
|
+
|
|
31
|
+
if (!imageTag) {
|
|
32
|
+
const { stdout: branch } = await execCommand(
|
|
33
|
+
"git rev-parse --abbrev-ref HEAD",
|
|
34
|
+
{ stdio: "pipe" }
|
|
35
|
+
);
|
|
36
|
+
const { stdout: commitSHA } = await execCommand("git rev-parse HEAD", {
|
|
37
|
+
stdio: "pipe",
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
imageTag = `${branch}.${commitSHA}`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
console.log("Deploying Image Tag ", imageTag);
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
await isAuthorized();
|
|
47
|
+
const { projectId } = await isProjectInit();
|
|
48
|
+
console.log('project id', projectId)
|
|
49
|
+
const { isOk } = (
|
|
50
|
+
await axios({
|
|
51
|
+
// url: `http://localhost:3001/projects/${projectId}/deploy`,
|
|
52
|
+
url: `projects/${projectId}/deploy`,
|
|
53
|
+
method: 'post',
|
|
54
|
+
data: {
|
|
55
|
+
imageTag
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
).data;
|
|
59
|
+
|
|
60
|
+
console.log('Deployed');
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error('An error occurred:', error.message);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
program
|
|
67
|
+
.command('deploy-local')
|
|
68
|
+
.description('Build and deploy Hive project from local machine docker + helm')
|
|
69
|
+
.action(async () => {
|
|
70
|
+
try {
|
|
71
|
+
let outDir = path.resolve(process.cwd(), './dist');
|
|
72
|
+
await mergeDirs({ hiveSrc: path.resolve(process.cwd()), outDir });
|
|
73
|
+
|
|
74
|
+
console.log('outDir', path.resolve(outDir, `./deploy/script`))
|
|
75
|
+
await execCommand(`npm install --prefix ${path.resolve(outDir, `./deploy/script`)}`);
|
|
76
|
+
|
|
77
|
+
await execCommand('node ./index.js', {
|
|
78
|
+
cwd: path.resolve(outDir, `./deploy/script/src`)
|
|
79
|
+
});
|
|
80
|
+
} catch (error) {
|
|
81
|
+
console.error('An error occurred:', error.message);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
61
85
|
program
|
|
62
86
|
.command('install <plugin>')
|
|
63
87
|
.description('Installs Hive plugin')
|
|
@@ -71,4 +95,95 @@ program
|
|
|
71
95
|
}
|
|
72
96
|
});
|
|
73
97
|
|
|
98
|
+
program
|
|
99
|
+
.command('login')
|
|
100
|
+
.description('Login into Hive Cloud')
|
|
101
|
+
.action(async () => {
|
|
102
|
+
if (process.env.HIVE_TOKEN) {
|
|
103
|
+
const user = (await axios({ url: `users/me`, method: 'get' })).data;
|
|
104
|
+
|
|
105
|
+
console.log(`Already logged in!`, user);
|
|
106
|
+
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
program
|
|
113
|
+
.command('init')
|
|
114
|
+
.description('Init Hive Project')
|
|
115
|
+
.action(async () => {
|
|
116
|
+
try {
|
|
117
|
+
process.env.HIVE_SRC = path.resolve(process.cwd());
|
|
118
|
+
|
|
119
|
+
await isAuthorized();
|
|
120
|
+
await isProjectInit();
|
|
121
|
+
} catch (error) {
|
|
122
|
+
console.error('An error occurred:', error.message);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
program
|
|
127
|
+
.command('env-get <envName>')
|
|
128
|
+
.description('Get env variable')
|
|
129
|
+
.action(async (envName) => {
|
|
130
|
+
try {
|
|
131
|
+
process.env.HIVE_SRC = path.resolve(process.cwd());
|
|
132
|
+
|
|
133
|
+
await isAuthorized();
|
|
134
|
+
const { projectId } = await isProjectInit();
|
|
135
|
+
|
|
136
|
+
const { value } = (await axios({
|
|
137
|
+
method: 'post',
|
|
138
|
+
url: `projects/${projectId}/get-env`,
|
|
139
|
+
data: {
|
|
140
|
+
name: envName
|
|
141
|
+
}
|
|
142
|
+
})).data;
|
|
143
|
+
|
|
144
|
+
console.log(`${envName} value is ${value || '<empty>'}`)
|
|
145
|
+
} catch (error) {
|
|
146
|
+
console.error('An error occurred:', error.message);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
program
|
|
151
|
+
.command('env-set <envName> <envValue>')
|
|
152
|
+
.description('Set env variable')
|
|
153
|
+
.action(async (envName, envValue) => {
|
|
154
|
+
try {
|
|
155
|
+
process.env.HIVE_SRC = path.resolve(process.cwd());
|
|
156
|
+
|
|
157
|
+
await isAuthorized();
|
|
158
|
+
const { projectId } = await isProjectInit();
|
|
159
|
+
|
|
160
|
+
const { value } = (await axios({
|
|
161
|
+
method: 'post',
|
|
162
|
+
url: `projects/${projectId}/env`,
|
|
163
|
+
data: {
|
|
164
|
+
name: envName,
|
|
165
|
+
value: envValue,
|
|
166
|
+
}
|
|
167
|
+
})).data;
|
|
168
|
+
|
|
169
|
+
console.log(`Updated ${envName}`)
|
|
170
|
+
} catch (error) {
|
|
171
|
+
console.error('An error occurred:', error.message);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
// program
|
|
177
|
+
// .command('init [name]')
|
|
178
|
+
// .description('Installs Hive plugin')
|
|
179
|
+
// .action(async (plugin) => {
|
|
180
|
+
// try {
|
|
181
|
+
// const destDir = process.cwd();
|
|
182
|
+
|
|
183
|
+
// await downloadDirectory(plugin);
|
|
184
|
+
// } catch (error) {
|
|
185
|
+
// console.error('An error occurred:', error.message);
|
|
186
|
+
// }
|
|
187
|
+
// });
|
|
188
|
+
|
|
74
189
|
program.parse(process.argv);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paralect/hive",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
"@koa/multer": "3.0.0",
|
|
15
15
|
"@koa/router": "10.1.1",
|
|
16
16
|
"@paralect/node-mongo": "2.1.1",
|
|
17
|
+
"@react-email/components": "^0.0.20",
|
|
18
|
+
"@react-email/render": "^0.0.16",
|
|
17
19
|
"@sendgrid/mail": "7.6.1",
|
|
18
20
|
"@socket.io/redis-adapter": "7.1.0",
|
|
19
21
|
"@socket.io/redis-emitter": "4.1.1",
|
|
@@ -24,9 +26,11 @@
|
|
|
24
26
|
"commander": "^12.1.0",
|
|
25
27
|
"dotenv": "16.0.0",
|
|
26
28
|
"eslint-config-prettier": "8.5.0",
|
|
29
|
+
"execa": "^4.1.0",
|
|
27
30
|
"fs-extra": "^11.2.0",
|
|
28
31
|
"handlebars": "4.7.7",
|
|
29
|
-
"
|
|
32
|
+
"inquirer": "^8.2.6",
|
|
33
|
+
"joi": "^17.13.3",
|
|
30
34
|
"koa": "2.13.4",
|
|
31
35
|
"koa-bodyparser": "4.3.0",
|
|
32
36
|
"koa-helmet": "6.1.0",
|
|
@@ -35,11 +39,12 @@
|
|
|
35
39
|
"koa-qs": "3.0.0",
|
|
36
40
|
"lodash": "4.17.21",
|
|
37
41
|
"mjml": "4.12.0",
|
|
38
|
-
"mkdirp": "1.0.4",
|
|
42
|
+
"mkdirp": "^1.0.4",
|
|
39
43
|
"moment": "2.29.1",
|
|
40
44
|
"moment-duration-format": "2.3.2",
|
|
41
45
|
"multer": "1.4.4",
|
|
42
46
|
"node-schedule": "2.1.0",
|
|
47
|
+
"nodemailer": "^6.9.14",
|
|
43
48
|
"nodemon": "2.0.15",
|
|
44
49
|
"prettier": "2.6.2",
|
|
45
50
|
"psl": "1.8.0",
|
package/starter/.babelrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
node_modules
|
package/starter/Dockerfile
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
FROM --platform=linux/amd64 node:16.13.1-alpine3.13 as base
|
|
2
2
|
RUN apk add --no-cache python3 py3-pip
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
ENV NODE_ENV=production
|
|
5
|
+
ENV APP_ENV=production
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
WORKDIR /app
|
|
8
|
+
EXPOSE 3001
|
|
9
|
+
COPY ["./package*.json", "/app/"]
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
RUN npm set progress=false && npm config set depth 0
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
RUN npm set-script prepare ""
|
|
14
|
+
|
|
15
|
+
RUN npm ci --only=production --quiet
|
|
16
|
+
|
|
17
|
+
COPY ./ ./
|
|
18
|
+
|
|
19
|
+
RUN mkdir -p /project/logs
|
|
20
|
+
RUN touch /project/logs/log.txt
|
|
21
|
+
|
|
22
|
+
CMD npm start 2>&1 | tee /project/logs/log.txt
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
kind: Deployment
|
|
2
|
+
apiVersion: apps/v1
|
|
3
|
+
metadata:
|
|
4
|
+
name: {{ .Values.service }}
|
|
5
|
+
labels:
|
|
6
|
+
app: {{ .Values.service }}
|
|
7
|
+
spec:
|
|
8
|
+
replicas: 1
|
|
9
|
+
selector:
|
|
10
|
+
matchLabels:
|
|
11
|
+
app: {{ .Values.service }}
|
|
12
|
+
template:
|
|
13
|
+
metadata:
|
|
14
|
+
labels:
|
|
15
|
+
app: {{ .Values.service }}
|
|
16
|
+
spec:
|
|
17
|
+
restartPolicy: Always
|
|
18
|
+
containers:
|
|
19
|
+
- name: {{ .Values.service }}
|
|
20
|
+
image: {{ .Values.containerRegistry }}:{{ .Values.imagesVersion }}
|
|
21
|
+
env:
|
|
22
|
+
- name: PROJECT_ID
|
|
23
|
+
value: {{ .Values.projectId }}
|
|
24
|
+
{{- range .Values.env }}
|
|
25
|
+
- name: {{ .name }}
|
|
26
|
+
value: {{ .value }}
|
|
27
|
+
{{- end }}
|
|
28
|
+
imagePullPolicy: Always
|
|
29
|
+
livenessProbe:
|
|
30
|
+
httpGet:
|
|
31
|
+
path: /health
|
|
32
|
+
port: {{ .Values.port }}
|
|
33
|
+
initialDelaySeconds: 300
|
|
34
|
+
periodSeconds: 10
|
|
35
|
+
ports:
|
|
36
|
+
- containerPort: {{ .Values.port }}
|
|
37
|
+
protocol: TCP
|
|
38
|
+
nodeSelector:
|
|
39
|
+
doks.digitalocean.com/node-pool: {{ .Values.nodePool }}
|
|
40
|
+
strategy:
|
|
41
|
+
type: RollingUpdate
|
|
42
|
+
rollingUpdate:
|
|
43
|
+
maxUnavailable: 0
|
|
44
|
+
maxSurge: 1
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
kind: Ingress
|
|
2
|
+
apiVersion: networking.k8s.io/v1
|
|
3
|
+
metadata:
|
|
4
|
+
name: {{ .Values.service }}
|
|
5
|
+
labels:
|
|
6
|
+
app: {{ .Values.service }}
|
|
7
|
+
annotations:
|
|
8
|
+
nginx.ingress.kubernetes.io/proxy-read-timeout: "180"
|
|
9
|
+
nginx.ingress.kubernetes.io/proxy-body-size: "20m"
|
|
10
|
+
external-dns.alpha.kubernetes.io/hostname: {{ first .Values.domain }}
|
|
11
|
+
external-dns.alpha.kubernetes.io/ttl: "120" #optional
|
|
12
|
+
spec:
|
|
13
|
+
ingressClassName: nginx
|
|
14
|
+
rules:
|
|
15
|
+
{{- range $domain := .Values.domain }}
|
|
16
|
+
- host: {{ $domain }}
|
|
17
|
+
http:
|
|
18
|
+
paths:
|
|
19
|
+
- path: /
|
|
20
|
+
pathType: Prefix
|
|
21
|
+
backend:
|
|
22
|
+
service:
|
|
23
|
+
name: {{ $.Values.service }}
|
|
24
|
+
port:
|
|
25
|
+
number: {{ $.Values.port }}
|
|
26
|
+
{{- end}}
|