@paralect/hive 0.0.3 → 0.0.5

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.
@@ -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, './app-config/.env');
55
+
56
+ if (project?.envs?.staging) {
57
+ if (!fs.existsSync(path.resolve(process.env.HIVE_SRC, './app-config'))) {
58
+ fs.mkdirSync(path.resolve(process.env.HIVE_SRC, './app-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
- async function fetchDirectoryTree(owner, repo, dirPath) {
11
- const url = `${GITHUB_API_URL}/${owner}/${repo}/contents/${dirPath}`;
12
- const response = await axios.get(url);
13
- return response.data;
14
- }
15
-
16
- async function downloadFile(fileUrl, filePath) {
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",
3
+ "version": "0.0.5",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -26,8 +26,10 @@
26
26
  "commander": "^12.1.0",
27
27
  "dotenv": "16.0.0",
28
28
  "eslint-config-prettier": "8.5.0",
29
+ "execa": "^4.1.0",
29
30
  "fs-extra": "^11.2.0",
30
31
  "handlebars": "4.7.7",
32
+ "inquirer": "^8.2.6",
31
33
  "joi": "^17.13.3",
32
34
  "koa": "2.13.4",
33
35
  "koa-bodyparser": "4.3.0",
@@ -37,7 +39,7 @@
37
39
  "koa-qs": "3.0.0",
38
40
  "lodash": "4.17.21",
39
41
  "mjml": "4.12.0",
40
- "mkdirp": "1.0.4",
42
+ "mkdirp": "^1.0.4",
41
43
  "moment": "2.29.1",
42
44
  "moment-duration-format": "2.3.2",
43
45
  "multer": "1.4.4",
@@ -0,0 +1 @@
1
+ node_modules
@@ -1,4 +1,4 @@
1
- FROM node:16.13.1-alpine3.13 as base
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
4
  ENV NODE_ENV=production
@@ -21,9 +21,10 @@ spec:
21
21
  env:
22
22
  - name: PROJECT_ID
23
23
  value: {{ .Values.projectId }}
24
- env:
25
- - name: MONGODB_URI
26
- value: {{ .Values.mongoDbUri }}
24
+ {{- range .Values.env }}
25
+ - name: {{ .name }}
26
+ value: {{ .value }}
27
+ {{- end }}
27
28
  imagePullPolicy: Always
28
29
  livenessProbe:
29
30
  httpGet:
@@ -1,4 +1,4 @@
1
- FROM node:16.13.1-alpine3.13
1
+ FROM --platform=linux/amd64 node:16.13.1-alpine3.13
2
2
 
3
3
  RUN apk add docker
4
4
 
@@ -31,7 +31,7 @@ const pushToKubernetes = async ({ imageTag, appName, deployConfig }) => {
31
31
  fs.writeFileSync(`${config.home}/.kube/config`, config.kubeConfig);
32
32
  }
33
33
 
34
- let projectId = 'test';
34
+ let projectId = process.env.PROJECT_ID || 'core';
35
35
  let attachedDomains;
36
36
 
37
37
  await execCommand(
@@ -42,10 +42,11 @@ const pushToKubernetes = async ({ imageTag, appName, deployConfig }) => {
42
42
  --set imagesVersion=${imageTag} \
43
43
  --set domain={hive-api-${projectId}.paralect.co} \
44
44
  --set projectId=${projectId} \
45
- --set mongoDbUri='${process.env.MONGODB_URI}'
45
+ --set env\[0\].name=MONGODB_URI \
46
+ --set env\[0\].value='${process.env.MONGODB_URI}' \
46
47
  -f ${deployDir}/staging.yaml --timeout 35m`,
47
48
  {
48
- cwd: `/app`,
49
+ // cwd: `/app`,
49
50
  }
50
51
  );
51
52
  };
@@ -17,7 +17,7 @@
17
17
  },
18
18
  "scripts": {
19
19
  "build-assets": "mjml ./src/assets/emails/*.mjml -o ./src/assets/emails/dist/",
20
- "build-emails": "babel src/emails --out-dir src/emails/dist",
20
+ "build-emails": "babel src/emails --out-dir src/emails/compiled",
21
21
  "dev": "nodemon --watch src src/app.js",
22
22
  "init-project": "./bin/init-project.sh",
23
23
  "start": "node src/app.js",
@@ -20,7 +20,6 @@ module.exports = async (resourceName) => {
20
20
  )).map( f => ({ name: f }))];
21
21
  }
22
22
 
23
- console.log('endpointFiles', resourceName, endpointFiles);
24
23
  return endpointFiles.map(({ name, isHiveEndpoint }) => ({
25
24
  file: isHiveEndpoint ? `${process.env.HIVE_SRC}/resources/${resourceName}/endpoints/${name}`: `${__dirname}/../resources/${resourceName}/endpoints/${name}`,
26
25
  name: _.last(name.split("/")).replace(".js", ""),
@@ -1,12 +1,32 @@
1
- const db = require("db");
1
+ const db = require('db');
2
+
3
+ function singularize(word) {
4
+ const endings = {
5
+ ves: 'fe',
6
+ ies: 'y',
7
+ i: 'us',
8
+ zes: 'ze',
9
+ ses: 's',
10
+ es: 'e',
11
+ s: '',
12
+ };
13
+ return word.replace(
14
+ new RegExp(`(${Object.keys(endings).join('|')})$`),
15
+ (r) => endings[r]
16
+ );
17
+ }
2
18
 
3
19
  module.exports = (
4
20
  resourceName,
5
- { criteria = (ctx) => ({ _id: ctx.params[`${resourceName}Id`] }) } = {}
21
+ {
22
+ criteria = (ctx) => ({ _id: ctx.params[`${singularize(resourceName)}Id`] }),
23
+ ctxName = resourceName,
24
+ } = {}
6
25
  ) => {
7
26
  return async (ctx, next) => {
8
27
  const doc = await db.services[resourceName].findOne(criteria(ctx));
9
- ctx.state[resourceName] = doc;
28
+ ctx.state[ctxName] = doc;
29
+ ctx.state[singularize(resourceName)] = doc;
10
30
 
11
31
  if (!doc) {
12
32
  ctx.throw(404, { message: `${resourceName} not found` });
@@ -14,4 +34,4 @@ module.exports = (
14
34
  await next();
15
35
  }
16
36
  };
17
- };
37
+ };
@@ -1,5 +1,5 @@
1
1
  const { render } = require('@react-email/render');
2
- const { MyEmailComponent } = require('emails/dist/MyEmailComponent');
2
+ const { MyEmailComponent } = require('emails/compiled/MyEmailComponent');
3
3
  const React = require('react');
4
4
 
5
5
  const handler = (ctx) => {
@@ -3,15 +3,15 @@ const slug = require('slug');
3
3
 
4
4
  const userService = require('db').services.users;
5
5
 
6
- const formatUsername = ({ username, fullName }) => {
6
+ const formatUsername = ({ username, fullName, email }) => {
7
7
  return (
8
8
  username ||
9
- slug(`${fullName.split(' ')[0]} ${fullName.split(' ')[1] || ''}`, '.')
9
+ fullName ? slug(`${fullName.split(' ')[0]} ${fullName.split(' ')[1] || ''}`, '.') : email?.split('@')[0]
10
10
  );
11
11
  };
12
12
 
13
13
  const createUserAccount = async (userData) => {
14
- let username = formatUsername({ fullName: userData.fullName });
14
+ let username = formatUsername({ fullName: userData.fullName, email: userData.email });
15
15
 
16
16
  if (await userService.exists({ username })) {
17
17
  username += _.random(1000, 9999);
@@ -49,9 +49,9 @@ const ensureUserCreated = async (userData) => {
49
49
  }
50
50
  );
51
51
 
52
- return { user: changedUser, isNew: true };
52
+ return { user: changedUser, isNew: false };
53
53
  } else {
54
- throw new Error(`User with email ${userData.email} already exists`);
54
+ return { user, isNew: false };
55
55
  }
56
56
  }
57
57
 
@@ -62,6 +62,6 @@ const ensureUserCreated = async (userData) => {
62
62
  };
63
63
 
64
64
  module.exports = async (userData) => {
65
- const { updatedUser, isNew } = await ensureUserCreated(userData);
66
- return updatedUser;
65
+ const { user, isNew } = await ensureUserCreated(userData);
66
+ return user;
67
67
  };
@@ -6,8 +6,8 @@ const users = Joi.object({
6
6
  updatedOn: Joi.date(),
7
7
 
8
8
  email: Joi.string().email().required(),
9
- fullName: Joi.string().required(),
10
9
  username: Joi.string().required(),
10
+ fullName: Joi.string(),
11
11
  avatarUrl: Joi.string().uri(),
12
12
 
13
13
  password: Joi.string(),