@canmingir/link-express 1.6.10 → 1.7.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.
Files changed (56) hide show
  1. package/.eslintrc.ts +29 -0
  2. package/index.ts +2 -0
  3. package/package.json +55 -12
  4. package/{prepare.js → prepare.ts} +1 -1
  5. package/src/{authorization.js → authorization.ts} +31 -9
  6. package/src/config.ts +112 -0
  7. package/src/dynamodb.ts +24 -0
  8. package/src/{error.js → error.ts} +30 -11
  9. package/src/express.ts +66 -0
  10. package/src/lib/{settings.js → settings.ts} +16 -4
  11. package/src/lib/test.ts +68 -0
  12. package/src/logger.ts +36 -0
  13. package/src/metrics/{dbMetrics.js → dbMetrics.ts} +37 -14
  14. package/src/models/Organization.model.ts +27 -0
  15. package/src/models/Permission.model.ts +48 -0
  16. package/src/models/Project.model.ts +50 -0
  17. package/src/models/Settings.model.ts +31 -0
  18. package/src/models/{index.js → index.ts} +8 -8
  19. package/src/platform.ts +55 -0
  20. package/src/postgres.ts +309 -0
  21. package/src/routes/index.ts +8 -0
  22. package/src/routes/metrics.ts +13 -0
  23. package/src/routes/oauth.ts +267 -0
  24. package/src/routes/{organizations.js → organizations.ts} +10 -8
  25. package/src/routes/{permissions.js → permissions.ts} +8 -6
  26. package/src/routes/{projects.js → projects.ts} +22 -16
  27. package/src/routes/settings.ts +31 -0
  28. package/src/schemas/{Organization.js → Organization.ts} +2 -2
  29. package/src/schemas/{Permission.js → Permission.ts} +2 -2
  30. package/src/schemas/{Project.js → Project.ts} +2 -2
  31. package/src/schemas/index.ts +5 -0
  32. package/src/sequelize.ts +13 -0
  33. package/src/{test.js → test.ts} +11 -13
  34. package/src/types/Organization.ts +9 -0
  35. package/src/types/Permission.ts +13 -0
  36. package/src/types/Project.ts +14 -0
  37. package/src/types/index.ts +5 -0
  38. package/tsconfig.json +32 -0
  39. package/.eslintrc.js +0 -20
  40. package/index.js +0 -1
  41. package/src/config.js +0 -21
  42. package/src/dynamodb.js +0 -18
  43. package/src/express.js +0 -58
  44. package/src/lib/test.js +0 -69
  45. package/src/models/Organization.js +0 -17
  46. package/src/models/Permission.js +0 -33
  47. package/src/models/Project.js +0 -37
  48. package/src/models/Settings.js +0 -21
  49. package/src/openapi.js +0 -40
  50. package/src/platform.js +0 -46
  51. package/src/postgres.js +0 -308
  52. package/src/routes/index.js +0 -15
  53. package/src/routes/metrics.js +0 -12
  54. package/src/routes/oauth.js +0 -213
  55. package/src/routes/settings.js +0 -25
  56. package/src/schemas/index.js +0 -5
package/src/config.js DELETED
@@ -1,21 +0,0 @@
1
- const _ = require("lodash");
2
- let _config = {};
3
-
4
- function init(config = {}) {
5
- _config = _.merge(
6
- {
7
- link: {},
8
- project: null,
9
- openapi: {},
10
- postgres: null,
11
- dynamodb: null,
12
- pushGateway: {},
13
- },
14
- config
15
- );
16
-
17
- return _config;
18
- }
19
-
20
- module.exports = () => _config;
21
- module.exports.init = init;
package/src/dynamodb.js DELETED
@@ -1,18 +0,0 @@
1
- const { DynamoDBClient } = require("@aws-sdk/client-dynamodb");
2
- const { DynamoDBDocumentClient } = require("@aws-sdk/lib-dynamodb");
3
-
4
- const config = require("./config");
5
- require("dotenv").config();
6
-
7
- const { dynamodb } = config();
8
-
9
- const client = new DynamoDBClient({
10
- region: dynamodb.region,
11
- credentials: {
12
- accessKeyId: process.env.AWS_ACCESS_KEY_ID,
13
- secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
14
- },
15
- });
16
- const docClient = DynamoDBDocumentClient.from(client);
17
-
18
- module.exports = { docClient };
package/src/express.js DELETED
@@ -1,58 +0,0 @@
1
- const express = require("express");
2
- require("express-async-errors");
3
-
4
- const cors = require("cors");
5
- const morgan = require("morgan");
6
- const helmet = require("helmet");
7
- const app = express();
8
-
9
- const metrics = require("./routes/metrics");
10
-
11
- const swaggerUi = require("swagger-ui-express");
12
- const openapi = require("./openapi");
13
- const error = require("./error");
14
- const authorization = require("./authorization");
15
- const settings = require("./routes/settings");
16
-
17
- const config = require("./config")();
18
-
19
- app.use(helmet());
20
- app.use(cors());
21
- app.use(morgan("tiny"));
22
-
23
- app.use(express.json(), (err, req, res, next) =>
24
- err ? res.status(422).end() : next()
25
- );
26
-
27
- if (config.project) {
28
- const oauth = require("./routes/oauth");
29
- app.use(
30
- "/oauth",
31
- express.urlencoded(),
32
- (err, req, res, next) => (err ? res.status(422).end() : next()),
33
- oauth
34
- );
35
- }
36
-
37
- app.use("/openapi", swaggerUi.serve, swaggerUi.setup(openapi));
38
- app.use("/metrics", metrics);
39
-
40
- setImmediate(() => {
41
- process.env.PROFILE === "TEST" && app.use(authorization.verify);
42
-
43
- if (config.project) {
44
- const permissions = require("./routes/permissions");
45
- const organizations = require("./routes/organizations");
46
- const projects = require("./routes/projects");
47
-
48
- app.use("/projects", projects);
49
- app.use("/organizations", organizations);
50
- app.use("/permissions", permissions);
51
- app.use("/projects/:projectId/settings", settings);
52
- }
53
-
54
- app.use((req, res) => res.status(404).end());
55
- app.use(error.handle);
56
- });
57
-
58
- module.exports = app;
package/src/lib/test.js DELETED
@@ -1,69 +0,0 @@
1
- require("dotenv").config({ path: ".env.test" });
2
- const { init } = require("../platform");
3
-
4
- init({
5
- project: {
6
- oauth: {
7
- jwt: {
8
- identifier: "email",
9
- },
10
- providers: {
11
- github: {
12
- tokenUrl: "https://github.com/login/oauth/access_token",
13
- userUrl: "https://api.github.com/user",
14
- clientId: "0c2844d3d19dc9293fc5",
15
- redirectUri: "http://localhost:5173/callback",
16
- userIdentifier: "id",
17
- userFields: {
18
- name: "name",
19
- displayName: "login",
20
- avatarUrl: "avatar_url",
21
- email: "email",
22
- },
23
- },
24
- },
25
- },
26
- },
27
- postgres: {
28
- uri: "sqlite::memory:",
29
- debug: true,
30
- sync: false,
31
- },
32
- });
33
-
34
- const models = require("../models");
35
-
36
- async function reset() {
37
- const { sequelize } = require("../postgres");
38
-
39
- if (await models.init()) {
40
- await sequelize.sync({ force: true });
41
- }
42
-
43
- const Organization = require("../models/Organization");
44
-
45
- const Project = require("../models/Project");
46
- const Permission = require("../models/Permission");
47
- const Settings = require("../models/Settings");
48
-
49
- await Organization.destroy({ truncate: true });
50
- await Project.destroy({ truncate: true });
51
- await Permission.destroy({ truncate: true });
52
- await Settings.destroy({ truncate: true });
53
-
54
- async function seed() {
55
- const { seed: organizations } = require("../seeds/Organization.json");
56
- const { seed: permissions } = require("../seeds/Permission.json");
57
- const { seed: projects } = require("../seeds/Project.json");
58
- const { seed: settings } = require("../seeds/Settings.json");
59
-
60
- await Organization.bulkCreate(organizations);
61
- await Project.bulkCreate(projects);
62
- await Permission.bulkCreate(permissions);
63
- await Settings.bulkCreate(settings);
64
- }
65
-
66
- await seed();
67
- }
68
-
69
- module.exports = { reset };
@@ -1,17 +0,0 @@
1
- const { sequelize } = require("../postgres");
2
- const { DataTypes, UUIDV4 } = require("sequelize");
3
-
4
- const Organization = sequelize.define("Organization", {
5
- id: {
6
- type: DataTypes.UUID,
7
- defaultValue: UUIDV4,
8
- primaryKey: true,
9
- allowNull: false,
10
- },
11
- name: {
12
- type: DataTypes.STRING,
13
- allowNull: false,
14
- },
15
- });
16
-
17
- module.exports = Organization;
@@ -1,33 +0,0 @@
1
- const { sequelize } = require("../postgres");
2
- const { DataTypes, UUIDV4 } = require("sequelize");
3
-
4
- const Permission = sequelize.define("Permission", {
5
- id: {
6
- type: DataTypes.UUID,
7
- defaultValue: UUIDV4,
8
- primaryKey: true,
9
- allowNull: false,
10
- },
11
- appId: {
12
- type: DataTypes.UUID,
13
- allowNull: false,
14
- },
15
- organizationId: {
16
- type: DataTypes.UUID,
17
- allowNull: false,
18
- },
19
- projectId: {
20
- type: DataTypes.UUID,
21
- allowNull: false,
22
- },
23
- userId: {
24
- type: DataTypes.STRING,
25
- allowNull: false,
26
- },
27
- role: {
28
- type: DataTypes.STRING,
29
- allowNull: false,
30
- },
31
- });
32
-
33
- module.exports = Permission;
@@ -1,37 +0,0 @@
1
- const { sequelize } = require("../postgres");
2
- const { DataTypes, UUIDV4 } = require("sequelize");
3
-
4
- const Project = sequelize.define("Project", {
5
- id: {
6
- type: DataTypes.UUID,
7
- defaultValue: UUIDV4,
8
- primaryKey: true,
9
- allowNull: false,
10
- },
11
- name: {
12
- type: DataTypes.STRING,
13
- allowNull: false,
14
- },
15
- icon: {
16
- type: DataTypes.STRING,
17
- allowNull: false,
18
- },
19
- description: {
20
- type: DataTypes.STRING,
21
- allowNull: true,
22
- },
23
- type: {
24
- type: DataTypes.STRING,
25
- allowNull: true,
26
- },
27
- organizationId: {
28
- type: DataTypes.UUID,
29
- allowNull: true,
30
- },
31
- coach: {
32
- type: DataTypes.STRING,
33
- allowNull: true,
34
- },
35
- });
36
-
37
- module.exports = Project;
@@ -1,21 +0,0 @@
1
- const { sequelize } = require("../postgres");
2
- const { DataTypes, UUIDV4 } = require("sequelize");
3
-
4
- const Settings = sequelize.define("Settings", {
5
- id: {
6
- type: DataTypes.UUID,
7
- defaultValue: UUIDV4,
8
- primaryKey: true,
9
- allowNull: false,
10
- },
11
- projectId: {
12
- type: DataTypes.UUID,
13
- allowNull: false,
14
- },
15
- settings: {
16
- type: DataTypes.JSONB,
17
- allowNull: false,
18
- },
19
- });
20
-
21
- module.exports = Settings;
package/src/openapi.js DELETED
@@ -1,40 +0,0 @@
1
- const { title, version } = require("./config")();
2
- const swaggerJsdoc = require("swagger-jsdoc");
3
- const j2s = require("joi-to-swagger");
4
-
5
- const swaggerSpec = swaggerJsdoc({
6
- definition: {
7
- openapi: "3.0.0",
8
- info: { title, version },
9
- servers: [{ url: "/api" }],
10
- },
11
-
12
- apis: [`${process.cwd()}/src/routes/*.js`],
13
- });
14
-
15
- swaggerSpec.components = {
16
- schemas: {},
17
- };
18
-
19
- let schemas;
20
- try {
21
- schemas = require(`${process.cwd()}/src/schemas`);
22
- } catch (error) {
23
- console.warn("[NUC]: Could not load schemas");
24
- schemas = {};
25
- }
26
-
27
- if (schemas && typeof schemas === "object") {
28
- if (schemas.default) {
29
- for (const schema in schemas) {
30
- try {
31
- const { swagger } = j2s(schemas[schema]);
32
- swaggerSpec.components.schemas[schema] = swagger;
33
- } catch (error) {
34
- console.warn(`Warning: Failed to process schema "${schema}":`);
35
- }
36
- }
37
- }
38
- }
39
-
40
- module.exports = swaggerSpec;
package/src/platform.js DELETED
@@ -1,46 +0,0 @@
1
- const fs = require("fs");
2
- const authorization = require("./authorization");
3
- const error = require("./error");
4
-
5
- let _express;
6
- let _postgres;
7
- let _dynamodb;
8
-
9
- function init(config = {}) {
10
- return new Promise((resolve, reject) => {
11
- try {
12
- require.extensions[".md"] = function (module, filename) {
13
- module.exports = fs.readFileSync(filename, "utf8").trim();
14
- };
15
-
16
- const { postgres, dynamodb } = require("./config").init(config);
17
-
18
- _express = require("./express");
19
-
20
- if (postgres) {
21
- _postgres = require("./postgres");
22
- }
23
-
24
- if (dynamodb) {
25
- _dynamodb = require("./dynamodb");
26
- }
27
-
28
- resolve();
29
- } catch (err) {
30
- reject(err);
31
- }
32
- });
33
- }
34
-
35
- module.exports = {
36
- init,
37
- express: () => _express,
38
- module: () => ({
39
- Postgres: _postgres,
40
- DynamoDB: _dynamodb,
41
- Kafka: {},
42
- }),
43
- require: (pkg) => require(pkg),
44
- authorization,
45
- error,
46
- };
package/src/postgres.js DELETED
@@ -1,308 +0,0 @@
1
- const { Sequelize, Model } = require("sequelize");
2
-
3
- const config = require("./config");
4
- const path = require("path");
5
- const fs = require("fs");
6
- const { DBMetrics } = require("./metrics/dbMetrics");
7
-
8
- const {
9
- postgres: { uri, debug = false, sync },
10
- project,
11
- metrics,
12
- } = config();
13
-
14
- let dbMetrics = null;
15
-
16
- if (metrics.enabled) {
17
- dbMetrics = new DBMetrics();
18
- dbMetrics.startPushgateway(metrics);
19
- }
20
-
21
- const originalDestroy = Model.prototype.destroy;
22
-
23
- Model.prototype.destroy = function (options = {}) {
24
- return originalDestroy.call(this, {
25
- ...options,
26
- individualHooks: true,
27
- });
28
- };
29
-
30
- const sequelize = new Sequelize(process.env.PG || uri, {
31
- logging: debug && console.log,
32
- define: {
33
- freezeTableName: true,
34
- underscored: true,
35
- timestamps: false,
36
- paranoid: false,
37
- },
38
- hooks: metrics.enabled
39
- ? {
40
- beforeFind: (options = {}) => {
41
- const timer = dbMetrics.dbReadLatency.startTimer();
42
- options.metricsTimer = timer;
43
- options.metricsType = "read";
44
- },
45
- afterFind: (result, options = {}) => {
46
- if (options?.metricsTimer) {
47
- options.metricsTimer();
48
- dbMetrics.dbReadOps.inc();
49
- }
50
- },
51
-
52
- beforeCreate: (instance, options = {}) => {
53
- const timer = dbMetrics.dbWriteLatency.startTimer();
54
- options.metricsTimer = timer;
55
- options.metricsType = "write";
56
- },
57
- afterCreate: (instance, options = {}) => {
58
- if (options?.metricsTimer) {
59
- options.metricsTimer();
60
- dbMetrics.dbWriteOps.inc();
61
- }
62
- },
63
-
64
- beforeUpdate: (instance, options = {}) => {
65
- const timer = dbMetrics.dbWriteLatency.startTimer();
66
- options.metricsTimer = timer;
67
- options.metricsType = "write";
68
- },
69
- afterUpdate: (instance, options = {}) => {
70
- if (options?.metricsTimer) {
71
- options.metricsTimer();
72
- dbMetrics.dbWriteOps.inc();
73
- }
74
- },
75
-
76
- beforeDestroy: (instance, options = {}) => {
77
- const timer = dbMetrics.dbWriteLatency.startTimer();
78
- options.metricsTimer = timer;
79
- options.metricsType = "write";
80
- },
81
- afterDestroy: (instance, options = {}) => {
82
- if (options?.metricsTimer) {
83
- options.metricsTimer();
84
- dbMetrics.dbWriteOps.inc();
85
- }
86
- },
87
-
88
- beforeBulkCreate: (instances, options = {}) => {
89
- const timer = dbMetrics.dbWriteLatency.startTimer();
90
- options.metricsTimer = timer;
91
- options.metricsType = "write";
92
- },
93
- afterBulkCreate: (instances, options = {}) => {
94
- if (options?.metricsTimer) {
95
- options.metricsTimer();
96
- dbMetrics.dbWriteOps.inc(instances.length || 1);
97
- }
98
- },
99
-
100
- beforeBulkUpdate: (instances, options = {}) => {
101
- const timer = dbMetrics.dbWriteLatency.startTimer();
102
- options.metricsTimer = timer;
103
- options.metricsType = "write";
104
- },
105
- afterBulkUpdate: (instances, options = {}) => {
106
- if (options?.metricsTimer) {
107
- options.metricsTimer();
108
- dbMetrics.dbWriteOps.inc(instances.length || 1);
109
- }
110
- },
111
-
112
- beforeBulkDestroy: (options = {}) => {
113
- const timer = dbMetrics.dbWriteLatency.startTimer();
114
- options.metricsTimer = timer;
115
- options.metricsType = "write";
116
- },
117
- afterBulkDestroy: (options = {}) => {
118
- if (options?.metricsTimer) {
119
- options.metricsTimer();
120
- dbMetrics.dbWriteOps.inc(1);
121
- }
122
- },
123
- }
124
- : {},
125
- });
126
-
127
- const seed = async () => {
128
- const currentWorkingDirectory = process.cwd();
129
- const baseDir = path.join(currentWorkingDirectory, "src", "models");
130
- const seedDir = path.join(currentWorkingDirectory, "src", "seeds");
131
-
132
- if (!fs.existsSync(seedDir)) {
133
- console.error(`[NUC] Seed directory not found at path: ${seedDir}`);
134
- return;
135
- }
136
-
137
- if (!fs.existsSync(baseDir)) {
138
- console.error(`[NUC] Model directory not found at path: ${baseDir}`);
139
- return;
140
- }
141
-
142
- let transaction = await sequelize.transaction();
143
-
144
- try {
145
- if (project) {
146
- const Organization = require("./models/Organization");
147
- const { seed: companiesSeed } = require("./seeds/Organization.json");
148
-
149
- await Organization.bulkCreate(companiesSeed, {
150
- transaction,
151
- validate: true,
152
- });
153
- console.log(`[NUC] Loading internal seed data for Organization`);
154
-
155
- if (fs.existsSync(path.join(seedDir, "Organization.json"))) {
156
- const seedData = require(path.join(seedDir, "Organization.json"));
157
- const seed = seedData["seed"];
158
- await Organization.bulkCreate(seed, {
159
- transaction,
160
- validate: true,
161
- });
162
- console.log(`[NUC] Loading seed data for Organization`);
163
- }
164
-
165
- const Project = require("./models/Project");
166
- const { seed: projectSeed } = require("./seeds/Project.json");
167
-
168
- try {
169
- const { seed: extProjectSeed } = require(path.join(
170
- seedDir,
171
- "Project.json"
172
- ));
173
- if (extProjectSeed) {
174
- projectSeed.push(...extProjectSeed);
175
- }
176
- console.log(
177
- `[NUC] Loading internal${
178
- extProjectSeed ? " and external" : ""
179
- } seed data for Project`
180
- );
181
- } catch (error) {
182
- console.log(`[NUC] Loading internal seed data for Project`);
183
- }
184
-
185
- await Project.bulkCreate(projectSeed, {
186
- transaction,
187
- validate: true,
188
- });
189
- }
190
-
191
- const fileNames = fs
192
- .readdirSync(baseDir)
193
- .filter(
194
- (fileName) =>
195
- path.extname(fileName) === ".js" &&
196
- !["index.js", "models.js"].includes(fileName)
197
- );
198
-
199
- const fileSequences = fileNames
200
- .map((fileName) => {
201
- const seedName = fileName.split(".")[0];
202
- const seederPath = path.join(seedDir, `${seedName}.json`);
203
-
204
- if (fs.existsSync(seederPath)) {
205
- const seedData = require(seederPath);
206
- return { sequence: seedData.sequence, fileName };
207
- }
208
- return null;
209
- })
210
- .filter(Boolean)
211
- .sort((a, b) => a.sequence - b.sequence);
212
-
213
- for (const { fileName } of fileSequences) {
214
- const seedName = fileName.split(".")[0];
215
- const seederPath = path.join(seedDir, `${seedName}.json`);
216
- const filePath = path.join(baseDir, fileName);
217
-
218
- try {
219
- const model = require(filePath);
220
- const seedData = require(seederPath);
221
- const seed = seedData["seed"];
222
-
223
- console.log(`[NUC] Loading seed data for ${fileName}`);
224
- await model.bulkCreate(seed, {
225
- transaction,
226
- validate: true,
227
- });
228
- } catch (error) {
229
- console.error(`[NUC] Error loading seed data for ${fileName}:`, error);
230
- throw error;
231
- }
232
- }
233
-
234
- if (project) {
235
- const Permission = require("./models/Permission");
236
- const { seed: permissionsSeed } = require("./seeds/Permission.json");
237
- try {
238
- const { seed: extPermissionsSeed } = require(path.join(
239
- seedDir,
240
- "Permission.json"
241
- ));
242
- if (extPermissionsSeed) {
243
- permissionsSeed.push(...extPermissionsSeed);
244
- }
245
- console.log(
246
- `[NUC] Loading internal${
247
- extPermissionsSeed ? " and external" : ""
248
- } seed data for Permission`
249
- );
250
- } catch (error) {
251
- console.log(`[NUC] Loading internal seed data for Permission`);
252
- }
253
-
254
- await Permission.bulkCreate(permissionsSeed, {
255
- transaction,
256
- validate: true,
257
- });
258
-
259
- const Settings = require("./models/Settings");
260
- const { seed: settingsSeed } = require("./seeds/Settings.json");
261
-
262
- try {
263
- const { seed: extSettingsSeed } = require(path.join(
264
- seedDir,
265
- "Settings.json"
266
- ));
267
- if (extSettingsSeed) {
268
- settingsSeed.push(...extSettingsSeed);
269
- }
270
- console.log(
271
- `[NUC] Loading internal${
272
- extSettingsSeed ? " and external" : ""
273
- } seed data for Settings`
274
- );
275
- } catch (error) {
276
- console.log(`[NUC] Loading internal seed data for Settings`);
277
- }
278
-
279
- await Settings.bulkCreate(settingsSeed, {
280
- transaction,
281
- validate: true,
282
- });
283
- }
284
-
285
- await transaction.commit();
286
- } catch (error) {
287
- if (transaction && !transaction.finished) {
288
- await transaction.rollback();
289
- }
290
- console.error("[NUC] Error during seed operation:", error);
291
- throw error;
292
- }
293
- };
294
-
295
- const associateModels = async () => {
296
- const models = require("./models");
297
- await models.init();
298
- };
299
-
300
- if (sync) {
301
- setImmediate(async () => {
302
- project && (await associateModels());
303
- await sequelize.sync({ force: true });
304
- await seed();
305
- });
306
- }
307
-
308
- module.exports = { sequelize, metrics };
@@ -1,15 +0,0 @@
1
- const metrics = require("./metrics");
2
- const permissions = require("./permissions");
3
- const oauth = require("./oauth");
4
- const organizations = require("./organizations");
5
- const projects = require("./projects");
6
- const settings = require("./settings");
7
-
8
- module.exports = {
9
- metrics,
10
- permissions,
11
- oauth,
12
- organizations,
13
- projects,
14
- settings,
15
- };
@@ -1,12 +0,0 @@
1
- const express = require("express");
2
- const router = express.Router();
3
- const os = require("os");
4
-
5
- router.get("/", (req, res) => {
6
- res.json({
7
- free: os.freemem(),
8
- total: os.totalmem(),
9
- });
10
- });
11
-
12
- module.exports = router;