@paralect/hive 0.1.48 → 0.1.50-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/commands/deslop.md +12 -0
- package/.hive/.babelrc +3 -0
- package/.hive/.cursor/commands/add-endpoint.md +262 -0
- package/.hive/.cursor/commands/add-handler.md +137 -0
- package/.hive/.cursor/commands/add-middleware.md +95 -0
- package/.hive/.cursor/commands/add-resource.md +71 -0
- package/.hive/.cursor/commands/add-scheduler.md +138 -0
- package/.hive/.cursor/commands/add-service.md +188 -0
- package/.hive/.cursor/skills/hive-auth/SKILL.md +134 -0
- package/.hive/.cursor/skills/hive-database/SKILL.md +103 -0
- package/.hive/.cursor/skills/hive-endpoint/SKILL.md +103 -0
- package/.hive/.cursor/skills/hive-handler/SKILL.md +88 -0
- package/.hive/.cursor/skills/hive-mapping/SKILL.md +85 -0
- package/.hive/.cursor/skills/hive-middleware/SKILL.md +104 -0
- package/.hive/.cursor/skills/hive-overview/SKILL.md +50 -0
- package/.hive/.cursor/skills/hive-scheduler/SKILL.md +94 -0
- package/.hive/.cursor/skills/hive-schema/SKILL.md +73 -0
- package/.hive/.cursor/skills/hive-service/SKILL.md +90 -0
- package/.hive/.dockerignore +1 -0
- package/.hive/Dockerfile +22 -0
- package/.hive/Dockerfile.dev +33 -0
- package/.hive/Dockerfile.prod +29 -0
- package/.hive/README.md +11 -0
- package/.hive/bin/deploy.sh +5 -0
- package/.hive/bin/start.sh +2 -0
- package/.hive/bootstrap-hive.js +118 -0
- package/.hive/deploy/api/Chart.yaml +6 -0
- package/.hive/deploy/api/staging.yaml +3 -0
- package/.hive/deploy/api/templates/deployment.yaml +44 -0
- package/.hive/deploy/api/templates/ingress.yaml +26 -0
- package/.hive/deploy/api/templates/service.yaml +14 -0
- package/.hive/deploy/script/Dockerfile +39 -0
- package/.hive/deploy/script/package-lock.json +1499 -0
- package/.hive/deploy/script/package.json +12 -0
- package/.hive/deploy/script/src/config.js +48 -0
- package/.hive/deploy/script/src/index.js +108 -0
- package/.hive/deploy/script/src/util.js +19 -0
- package/.hive/initial-data.json +176 -0
- package/.hive/package-lock.json +10242 -0
- package/.hive/package.json +98 -0
- package/.hive/ship_logo.png +0 -0
- package/.hive/src/app-config/app.js +3 -0
- package/.hive/src/app-config/assertEnv.js +15 -0
- package/.hive/src/app-config/index.js +62 -0
- package/.hive/src/app.js +69 -0
- package/.hive/src/assets/emails/components/header.mjml +13 -0
- package/.hive/src/assets/emails/dist/.gitkeep +0 -0
- package/.hive/src/assets/emails/signup-welcome.mjml +34 -0
- package/.hive/src/assets/emails/styles/index.mjml +77 -0
- package/.hive/src/autoMap/addHandlers.js +142 -0
- package/.hive/src/autoMap/getDependentFields.js +37 -0
- package/.hive/src/autoMap/mapSchema.js +99 -0
- package/.hive/src/autoMap/schemaMappings.js +13 -0
- package/.hive/src/autoMap/schemaMappings.json +3 -0
- package/.hive/src/bullMqBus.js +21 -0
- package/.hive/src/bullMqWrapper.js +23 -0
- package/.hive/src/db.js +52 -0
- package/.hive/src/emails/MyEmailComponent.jsx +14 -0
- package/.hive/src/emails/compiled/MyEmailComponent.js +18 -0
- package/.hive/src/emails/compiled/compiled/MyEmailComponent.js +18 -0
- package/.hive/src/helpers/db/ifUpdated.js +22 -0
- package/.hive/src/helpers/getMiddlewares.js +38 -0
- package/.hive/src/helpers/getResourceEndpoints.js +28 -0
- package/.hive/src/helpers/getResources.js +32 -0
- package/.hive/src/helpers/getSchemas.js +50 -0
- package/.hive/src/helpers/importHandlers.js +29 -0
- package/.hive/src/helpers/isZodArray.js +13 -0
- package/.hive/src/helpers/prettierFormat.js +8 -0
- package/.hive/src/helpers/schema/db.schema.js +9 -0
- package/.hive/src/helpers/schema/pagination.schema.js +14 -0
- package/.hive/src/ioEmitter.js +9 -0
- package/.hive/src/jsconfig.json +5 -0
- package/.hive/src/lib/node-mongo/.github/workflows/npm-publish.yml +32 -0
- package/.hive/src/lib/node-mongo/API.md +654 -0
- package/.hive/src/lib/node-mongo/CHANGELOG.md +98 -0
- package/.hive/src/lib/node-mongo/README.md +97 -0
- package/.hive/src/lib/node-mongo/package-lock.json +3682 -0
- package/.hive/src/lib/node-mongo/package.json +74 -0
- package/.hive/src/lib/node-mongo/src/index.js +64 -0
- package/.hive/src/lib/node-mongo/src/mongo-query-service.js +78 -0
- package/.hive/src/lib/node-mongo/src/mongo-service-error.js +15 -0
- package/.hive/src/lib/node-mongo/src/mongo-service.js +303 -0
- package/.hive/src/logger.js +43 -0
- package/.hive/src/middlewares/allowNoAuth.js +9 -0
- package/.hive/src/middlewares/attachUser.js +41 -0
- package/.hive/src/middlewares/global/extractUserTokens.js +15 -0
- package/.hive/src/middlewares/global/tryToAttachUser.js +33 -0
- package/.hive/src/middlewares/isAuthorized.js +18 -0
- package/.hive/src/middlewares/shouldExist.js +37 -0
- package/.hive/src/middlewares/shouldNotExist.js +19 -0
- package/.hive/src/middlewares/uploadFile.js +5 -0
- package/.hive/src/middlewares/validate.js +32 -0
- package/.hive/src/migrations/migration.js +8 -0
- package/.hive/src/migrations/migration.service.js +73 -0
- package/.hive/src/migrations/migrations/1.js +22 -0
- package/.hive/src/migrations/migrations-log/migration-log.schema.js +13 -0
- package/.hive/src/migrations/migrations-log/migration-log.service.js +50 -0
- package/.hive/src/migrations/migrations.schema.js +6 -0
- package/.hive/src/migrations/migrator.js +75 -0
- package/.hive/src/migrator.js +4 -0
- package/.hive/src/resources/_dev/endpoints/triggerSchedulerHandler.js +32 -0
- package/.hive/src/resources/health/endpoints/get.js +19 -0
- package/.hive/src/resources/schemaMappings/schemaMappings.schema.js +6 -0
- package/.hive/src/resources/tokens/methods/generateSecureToken.js +9 -0
- package/.hive/src/resources/tokens/methods/setToken.js +8 -0
- package/.hive/src/resources/tokens/methods/storeToken.js +35 -0
- package/.hive/src/resources/tokens/tokens.schema.js +11 -0
- package/.hive/src/resources/users/endpoints/getCurrentUser.js +14 -0
- package/.hive/src/resources/users/endpoints/getUserProfile.js +19 -0
- package/.hive/src/resources/users/handlers/test.js +1 -0
- package/.hive/src/resources/users/methods/ensureUserCreated.js +68 -0
- package/.hive/src/resources/users/users.schema.js +16 -0
- package/.hive/src/routes/index.js +172 -0
- package/.hive/src/routes/middlewares/attachCustomErrors.js +28 -0
- package/.hive/src/routes/middlewares/routeErrorHandler.js +27 -0
- package/.hive/src/scheduler/handlers/sendDailyReport.example.js +7 -0
- package/.hive/src/scheduler.js +32 -0
- package/.hive/src/security.util.js +38 -0
- package/.hive/src/services/emailService.js +15 -0
- package/.hive/src/services/globalTest.js +0 -0
- package/.hive/src/services/setCookie.js +21 -0
- package/.hive/src/socketIo.js +99 -0
- package/.hive/tsconfig.json +31 -0
- package/AGENTS.md +96 -0
- package/README.md +271 -0
- package/cli/helpers/docker.js +59 -0
- package/cli/helpers/envCheck.js +123 -0
- package/cli/helpers/findPort.js +32 -0
- package/cli/hive.js +155 -15
- package/package.json +1 -1
- package/starter/.cursor/commands/add-endpoint.md +262 -0
- package/starter/.cursor/commands/add-handler.md +137 -0
- package/starter/.cursor/commands/add-middleware.md +95 -0
- package/starter/.cursor/commands/add-resource.md +71 -0
- package/starter/.cursor/commands/add-scheduler.md +138 -0
- package/starter/.cursor/commands/add-service.md +188 -0
- package/starter/.cursor/skills/hive-auth/SKILL.md +134 -0
- package/starter/.cursor/skills/hive-database/SKILL.md +103 -0
- package/starter/.cursor/skills/hive-endpoint/SKILL.md +103 -0
- package/starter/.cursor/skills/hive-handler/SKILL.md +88 -0
- package/starter/.cursor/skills/hive-mapping/SKILL.md +85 -0
- package/starter/.cursor/skills/hive-middleware/SKILL.md +104 -0
- package/starter/.cursor/skills/hive-overview/SKILL.md +50 -0
- package/starter/.cursor/skills/hive-scheduler/SKILL.md +94 -0
- package/starter/.cursor/skills/hive-schema/SKILL.md +73 -0
- package/starter/.cursor/skills/hive-service/SKILL.md +90 -0
- package/starter/src/app.js +4 -3
- package/test-app/.cursor/commands/add-endpoint.md +262 -0
- package/test-app/.cursor/commands/add-handler.md +137 -0
- package/test-app/.cursor/commands/add-middleware.md +95 -0
- package/test-app/.cursor/commands/add-resource.md +71 -0
- package/test-app/.cursor/commands/add-scheduler.md +138 -0
- package/test-app/.cursor/commands/add-service.md +188 -0
- package/test-app/.cursor/skills/hive-auth/SKILL.md +134 -0
- package/test-app/.cursor/skills/hive-database/SKILL.md +103 -0
- package/test-app/.cursor/skills/hive-endpoint/SKILL.md +103 -0
- package/test-app/.cursor/skills/hive-handler/SKILL.md +88 -0
- package/test-app/.cursor/skills/hive-mapping/SKILL.md +85 -0
- package/test-app/.cursor/skills/hive-middleware/SKILL.md +104 -0
- package/test-app/.cursor/skills/hive-overview/SKILL.md +50 -0
- package/test-app/.cursor/skills/hive-scheduler/SKILL.md +94 -0
- package/test-app/.cursor/skills/hive-schema/SKILL.md +73 -0
- package/test-app/.cursor/skills/hive-service/SKILL.md +90 -0
- package/test-app/package-lock.json +8684 -0
- package/test-app/package.json +21 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import db from '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
|
+
}
|
|
18
|
+
|
|
19
|
+
export default (
|
|
20
|
+
resourceName,
|
|
21
|
+
{
|
|
22
|
+
criteria = (ctx) => ({ _id: ctx.params[`${singularize(resourceName)}Id`] }),
|
|
23
|
+
ctxName = resourceName,
|
|
24
|
+
} = {}
|
|
25
|
+
) => {
|
|
26
|
+
return async (ctx, next) => {
|
|
27
|
+
const doc = await db.services[resourceName].findOne(criteria(ctx));
|
|
28
|
+
ctx.state[ctxName] = doc;
|
|
29
|
+
ctx.state[singularize(resourceName)] = doc;
|
|
30
|
+
|
|
31
|
+
if (!doc) {
|
|
32
|
+
ctx.throw(404, { message: `${resourceName} not found` });
|
|
33
|
+
} else {
|
|
34
|
+
await next();
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
import db from 'db';
|
|
3
|
+
|
|
4
|
+
export default (
|
|
5
|
+
resourceName,
|
|
6
|
+
{ criteria = (ctx) => ({ name: ctx.validatedData.name }) } = {}
|
|
7
|
+
) => {
|
|
8
|
+
return async (ctx, next) => {
|
|
9
|
+
const doc = await db.services[resourceName].findOne(criteria(ctx));
|
|
10
|
+
|
|
11
|
+
if (doc) {
|
|
12
|
+
ctx.throw(400, {
|
|
13
|
+
message: `${_.capitalize(resourceName)} already exists`,
|
|
14
|
+
});
|
|
15
|
+
} else {
|
|
16
|
+
await next();
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
|
|
2
|
+
const formatError = (zodError) => {
|
|
3
|
+
const errors = {};
|
|
4
|
+
|
|
5
|
+
zodError.issues.forEach((error) => {
|
|
6
|
+
const key = error.path.join('.');
|
|
7
|
+
|
|
8
|
+
if (!errors[key]) {
|
|
9
|
+
errors[key] = [];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
(errors[key]).push(error.message);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
return errors;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const validate = (schema) => async (ctx, next) => {
|
|
19
|
+
const result = await schema.passthrough().safeParseAsync({
|
|
20
|
+
...(ctx.request.body),
|
|
21
|
+
...ctx.query,
|
|
22
|
+
...ctx.params,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
if (!result.success) ctx.throw(400, { clientErrors: formatError(result.error) });
|
|
26
|
+
|
|
27
|
+
ctx.validatedData = result.data;
|
|
28
|
+
|
|
29
|
+
await next();
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default validate;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import db from "db";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import _ from "lodash";
|
|
5
|
+
import validateSchema from "./migrations.schema";
|
|
6
|
+
|
|
7
|
+
const service = db.createService("__migrationVersion", {
|
|
8
|
+
validate: validateSchema,
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const migrationsPath = path.join(__dirname, "migrations");
|
|
12
|
+
|
|
13
|
+
const _id = "migration_version";
|
|
14
|
+
|
|
15
|
+
const getMigrationNames = () =>
|
|
16
|
+
new Promise((resolve, reject) => {
|
|
17
|
+
fs.readdir(migrationsPath, (err, files) => {
|
|
18
|
+
if (err) {
|
|
19
|
+
reject(err);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
resolve(files);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
service.getCurrentMigrationVersion = () =>
|
|
27
|
+
service.findOne({ _id }).then((doc) => {
|
|
28
|
+
if (!doc) {
|
|
29
|
+
return 0;
|
|
30
|
+
}
|
|
31
|
+
return doc.version;
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
service.getMigrations = () => {
|
|
35
|
+
let migrations = null;
|
|
36
|
+
return getMigrationNames()
|
|
37
|
+
.then((names) => {
|
|
38
|
+
migrations = names.map((name) => {
|
|
39
|
+
const migrationPath = path.join(migrationsPath, name);
|
|
40
|
+
// eslint-disable-next-line import/no-dynamic-require, global-require
|
|
41
|
+
// return require(migrationPath);
|
|
42
|
+
});
|
|
43
|
+
return migrations;
|
|
44
|
+
})
|
|
45
|
+
.catch((err) => {
|
|
46
|
+
throw err;
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
service.setNewMigrationVersion = (version) =>
|
|
51
|
+
service.atomic.findOneAndUpdate(
|
|
52
|
+
{ _id },
|
|
53
|
+
{
|
|
54
|
+
$set: {
|
|
55
|
+
version,
|
|
56
|
+
},
|
|
57
|
+
$setOnInsert: {
|
|
58
|
+
_id,
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
{ upsert: true }
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
service.promiseLimit = (documents = [], limit, operator) => {
|
|
65
|
+
const chunks = _.chunk(documents, limit);
|
|
66
|
+
return chunks.reduce((init, chunk) => {
|
|
67
|
+
return init.then(() => {
|
|
68
|
+
return Promise.all(chunk.map((c) => operator(c)));
|
|
69
|
+
});
|
|
70
|
+
}, Promise.resolve());
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default service;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import Migration from 'migrations/migration';
|
|
2
|
+
// const migrationService = require('migrations/migration.service');
|
|
3
|
+
//
|
|
4
|
+
// const userService = require('resources/user/user.service');
|
|
5
|
+
|
|
6
|
+
const migration = new Migration(1, "Example");
|
|
7
|
+
|
|
8
|
+
migration.migrate = async () => {
|
|
9
|
+
// const userIds = await userService.distinct('_id', {
|
|
10
|
+
// isEmailVerified: true,
|
|
11
|
+
// });
|
|
12
|
+
//
|
|
13
|
+
// await migrationService.promiseLimit(userIds, 50, (userId) => userService.updateOne(
|
|
14
|
+
// { _id: userId },
|
|
15
|
+
// (old) => ({
|
|
16
|
+
// ...old,
|
|
17
|
+
// isEmailVerified: false,
|
|
18
|
+
// }),
|
|
19
|
+
// ));
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default migration;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import dbSchema from 'helpers/schema/db.schema';
|
|
3
|
+
|
|
4
|
+
export default dbSchema.extend({
|
|
5
|
+
startTime: z.date(),
|
|
6
|
+
finishTime: z.date().optional(),
|
|
7
|
+
status: z.string(),
|
|
8
|
+
error: z.string().optional(),
|
|
9
|
+
errorStack: z.string().optional(),
|
|
10
|
+
duration: z.string().optional(),
|
|
11
|
+
migrationVersion: z.number(),
|
|
12
|
+
});
|
|
13
|
+
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import db from 'db';
|
|
2
|
+
import validateSchema from './migration-log.schema.js';
|
|
3
|
+
|
|
4
|
+
const service = db.createService("__migrationLog", {
|
|
5
|
+
validate: validateSchema,
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
service.startMigrationLog = (_id, startTime, migrationVersion) => {
|
|
9
|
+
return service.atomic.findOneAndUpdate(
|
|
10
|
+
{ _id },
|
|
11
|
+
{
|
|
12
|
+
$set: {
|
|
13
|
+
migrationVersion,
|
|
14
|
+
startTime,
|
|
15
|
+
status: "running",
|
|
16
|
+
},
|
|
17
|
+
$setOnInsert: {
|
|
18
|
+
_id,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
{ upsert: true }
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
service.failMigrationLog = (_id, finishTime, err) =>
|
|
26
|
+
service.atomic.update(
|
|
27
|
+
{ _id },
|
|
28
|
+
{
|
|
29
|
+
$set: {
|
|
30
|
+
finishTime,
|
|
31
|
+
status: "failed",
|
|
32
|
+
error: err.message,
|
|
33
|
+
errorStack: err.stack,
|
|
34
|
+
},
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
service.finishMigrationLog = (_id, finishTime, duration) =>
|
|
39
|
+
service.atomic.update(
|
|
40
|
+
{ _id },
|
|
41
|
+
{
|
|
42
|
+
$set: {
|
|
43
|
+
finishTime,
|
|
44
|
+
status: "completed",
|
|
45
|
+
duration,
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
export default service;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import 'moment-duration-format';
|
|
2
|
+
import moment from 'moment';
|
|
3
|
+
import logger from 'logger';
|
|
4
|
+
import migrationLogService from './migrations-log/migration-log.service';
|
|
5
|
+
import migrationService from './migration.service';
|
|
6
|
+
|
|
7
|
+
const migrator = {};
|
|
8
|
+
|
|
9
|
+
const run = async (migrations, curVersion) => {
|
|
10
|
+
const newMigrations = migrations
|
|
11
|
+
.filter((migration) => migration.version > curVersion)
|
|
12
|
+
.sort((a, b) => a.version - b.version);
|
|
13
|
+
|
|
14
|
+
if (!newMigrations.length) {
|
|
15
|
+
logger.info(`No new migrations found, stopping the process.
|
|
16
|
+
Current database version is ${curVersion}`);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let migrationLogId;
|
|
21
|
+
let migration;
|
|
22
|
+
let lastMigrationVersion;
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
for (migration of newMigrations) {
|
|
26
|
+
//eslint-disable-line
|
|
27
|
+
migrationLogId = migrationService.generateId();
|
|
28
|
+
const startTime = new Date();
|
|
29
|
+
await migrationLogService.startMigrationLog(
|
|
30
|
+
migrationLogId,
|
|
31
|
+
startTime,
|
|
32
|
+
migration.version
|
|
33
|
+
); //eslint-disable-line
|
|
34
|
+
logger.info(
|
|
35
|
+
`Migration #${migration.version} is running: ${migration.description}`
|
|
36
|
+
);
|
|
37
|
+
await migration.migrate(); //eslint-disable-line
|
|
38
|
+
|
|
39
|
+
lastMigrationVersion = migration.version;
|
|
40
|
+
await migrationService.setNewMigrationVersion(migration.version); //eslint-disable-line
|
|
41
|
+
const finishTime = new Date();
|
|
42
|
+
const duration = moment
|
|
43
|
+
.duration(finishTime - startTime)
|
|
44
|
+
.format("h [hrs], m [min], s [sec], S [ms]");
|
|
45
|
+
|
|
46
|
+
await migrationLogService.finishMigrationLog(
|
|
47
|
+
migrationLogId,
|
|
48
|
+
finishTime,
|
|
49
|
+
duration
|
|
50
|
+
); //eslint-disable-line
|
|
51
|
+
logger.info(
|
|
52
|
+
`Database has been updated to the version #${migration.version}`
|
|
53
|
+
);
|
|
54
|
+
logger.info(`Time of migration #${migration.version}: ${duration}`);
|
|
55
|
+
}
|
|
56
|
+
logger.info(`All migrations has been finished, stopping the process.
|
|
57
|
+
Current database version is: ${lastMigrationVersion}`);
|
|
58
|
+
} catch (err) {
|
|
59
|
+
logger.error(`Failed to update migration to version ${migration.version}`);
|
|
60
|
+
logger.error(err);
|
|
61
|
+
await migrationLogService.failMigrationLog(migrationLogId, new Date(), err);
|
|
62
|
+
throw err;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
migrator.exec = async () => {
|
|
67
|
+
const [migrations, currentVersion] = await Promise.all([
|
|
68
|
+
migrationService.getMigrations(),
|
|
69
|
+
migrationService.getCurrentMigrationVersion(),
|
|
70
|
+
]);
|
|
71
|
+
await run(migrations, currentVersion);
|
|
72
|
+
process.exit(0);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export default migrator;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
export const endpoint = {
|
|
4
|
+
method: "put",
|
|
5
|
+
url: "/trigger-scheduler-handler",
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const requestSchema = z.object({
|
|
9
|
+
name: z.string(),
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export const handler = async (ctx) => {
|
|
13
|
+
const { name } = ctx.validatedData;
|
|
14
|
+
|
|
15
|
+
const schedulerHandler = await (import(`${process.env.HIVE_SRC}/scheduler/handlers/${name}`));
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
const data = await schedulerHandler.handler();
|
|
19
|
+
|
|
20
|
+
ctx.body = {
|
|
21
|
+
ok: true,
|
|
22
|
+
data,
|
|
23
|
+
};
|
|
24
|
+
} catch (err) {
|
|
25
|
+
ctx.body = {
|
|
26
|
+
ok: false,
|
|
27
|
+
err: err.message,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const middlewares = ['allowNoAuth'];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { render } from '@react-email/render';
|
|
2
|
+
import { MyEmailComponent } from 'emails/compiled/MyEmailComponent';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
export const handler = (ctx) => {
|
|
6
|
+
const emailHtml = render(React.createElement(MyEmailComponent, { name: 'test' }));
|
|
7
|
+
|
|
8
|
+
ctx.body = emailHtml;
|
|
9
|
+
ctx.status = 200;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const endpoint = {
|
|
13
|
+
method: "get",
|
|
14
|
+
url: "/",
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default {
|
|
18
|
+
handler, endpoint
|
|
19
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import db from 'db';
|
|
2
|
+
import crypto from 'crypto';
|
|
3
|
+
import util from 'util';
|
|
4
|
+
|
|
5
|
+
const randomBytes = util.promisify(crypto.randomBytes, crypto);
|
|
6
|
+
|
|
7
|
+
import setCookie from 'services/setCookie';
|
|
8
|
+
|
|
9
|
+
const tokenService = db.services.tokens;
|
|
10
|
+
|
|
11
|
+
const generateSecureToken = async (tokenLength = 32) => {
|
|
12
|
+
const buf = await randomBytes(tokenLength);
|
|
13
|
+
return buf.toString('hex');
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default async (ctx, { userId, metadata = null }) => {
|
|
17
|
+
const token = await generateSecureToken();
|
|
18
|
+
const otp = await generateSecureToken();
|
|
19
|
+
|
|
20
|
+
await tokenService.create({
|
|
21
|
+
token,
|
|
22
|
+
user: {
|
|
23
|
+
_id: userId,
|
|
24
|
+
},
|
|
25
|
+
otp,
|
|
26
|
+
...(metadata ? { metadata } : {})
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
setCookie(ctx, { name: 'access_token', value: token });
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
token,
|
|
33
|
+
otp,
|
|
34
|
+
};
|
|
35
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import dbSchema from 'helpers/schema/db.schema';
|
|
3
|
+
|
|
4
|
+
export default dbSchema.extend({
|
|
5
|
+
user: z.object({
|
|
6
|
+
_id: z.string(),
|
|
7
|
+
}),
|
|
8
|
+
token: z.string(),
|
|
9
|
+
otp: z.string().nullable().optional(),
|
|
10
|
+
metadata: z.object({}).optional()
|
|
11
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import isAuthorized from 'middlewares/isAuthorized';
|
|
3
|
+
|
|
4
|
+
export const handler = async (ctx) => {
|
|
5
|
+
ctx.body = ctx.state.user;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const middlewares = [isAuthorized];
|
|
9
|
+
export const requestSchema = z.object({});
|
|
10
|
+
|
|
11
|
+
export const endpoint = {
|
|
12
|
+
method: "GET",
|
|
13
|
+
url: "/me",
|
|
14
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import db from 'db';
|
|
3
|
+
|
|
4
|
+
const userService = db.services.users;
|
|
5
|
+
|
|
6
|
+
export const handler = async (ctx) => {
|
|
7
|
+
const { userId } = ctx.params;
|
|
8
|
+
const user = await userService.findOne({ _id: userId });
|
|
9
|
+
ctx.body = user;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const requestSchema = z.object({
|
|
13
|
+
userId: z.string(),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export const endpoint = {
|
|
17
|
+
method: "GET",
|
|
18
|
+
url: "/profile/:userId",
|
|
19
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
console.log('hello from handler');
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import db from 'db';
|
|
2
|
+
import _ from 'lodash';
|
|
3
|
+
import slug from 'slug';
|
|
4
|
+
|
|
5
|
+
const userService = db.services.users;
|
|
6
|
+
|
|
7
|
+
const formatUsername = ({ username, fullName, email }) => {
|
|
8
|
+
return (
|
|
9
|
+
username ||
|
|
10
|
+
fullName ? slug(`${fullName.split(' ')[0]} ${fullName.split(' ')[1] || ''}`, '.') : email?.split('@')[0]
|
|
11
|
+
);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const createUserAccount = async (userData) => {
|
|
15
|
+
let username = formatUsername({ fullName: userData.fullName, email: userData.email });
|
|
16
|
+
|
|
17
|
+
if (await userService.exists({ username })) {
|
|
18
|
+
username += _.random(1000, 9999);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const user = await userService.create({
|
|
22
|
+
fullName: userData.fullName,
|
|
23
|
+
username,
|
|
24
|
+
email: userData.email,
|
|
25
|
+
isEmailVerified: true,
|
|
26
|
+
avatarUrl: userData.avatarUrl,
|
|
27
|
+
oauth: userData.oauth,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
return user;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const ensureUserCreated = async (userData) => {
|
|
34
|
+
const user = await userService.findOne({ email: userData.email });
|
|
35
|
+
|
|
36
|
+
if (user) {
|
|
37
|
+
if (userData.oauth) {
|
|
38
|
+
const changedUser = await userService.updateOne(
|
|
39
|
+
{ _id: user._id },
|
|
40
|
+
(old) => {
|
|
41
|
+
const newUser = old;
|
|
42
|
+
newUser.oauth = old.oauth || {};
|
|
43
|
+
newUser.oauth = {
|
|
44
|
+
...newUser.oauth,
|
|
45
|
+
...userData.oauth
|
|
46
|
+
}
|
|
47
|
+
newUser.isEmailVerified = true;
|
|
48
|
+
|
|
49
|
+
return newUser;
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
return { user: changedUser, isNew: false };
|
|
54
|
+
} else {
|
|
55
|
+
return { user, isNew: false };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
user: await createUserAccount(userData),
|
|
61
|
+
isNew: true,
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export default async (userData) => {
|
|
66
|
+
const { user, isNew } = await ensureUserCreated(userData);
|
|
67
|
+
return user;
|
|
68
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import dbSchema from 'helpers/schema/db.schema';
|
|
3
|
+
|
|
4
|
+
const users = dbSchema.extend({
|
|
5
|
+
email: z.string().email(),
|
|
6
|
+
fullName: z.string(),
|
|
7
|
+
avatarUrl: z.string().url().optional(),
|
|
8
|
+
|
|
9
|
+
password: z.string(),
|
|
10
|
+
|
|
11
|
+
oauth: z.object({
|
|
12
|
+
google: z.object({}),
|
|
13
|
+
}).optional(),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export default users;
|