@flowerforce/flowerbase 1.6.2 → 1.6.3-beta.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 (42) hide show
  1. package/README.md +49 -87
  2. package/dist/auth/controller.d.ts.map +1 -1
  3. package/dist/auth/controller.js +15 -3
  4. package/dist/auth/providers/anon-user/controller.d.ts.map +1 -1
  5. package/dist/auth/providers/anon-user/controller.js +5 -1
  6. package/dist/auth/providers/custom-function/schema.d.ts +1 -0
  7. package/dist/auth/providers/custom-function/schema.d.ts.map +1 -1
  8. package/dist/auth/providers/custom-function/schema.js +1 -0
  9. package/dist/auth/utils.d.ts +7 -0
  10. package/dist/auth/utils.d.ts.map +1 -1
  11. package/dist/auth/utils.js +6 -0
  12. package/dist/constants.d.ts +12 -0
  13. package/dist/constants.d.ts.map +1 -1
  14. package/dist/constants.js +26 -5
  15. package/dist/features/endpoints/utils.d.ts.map +1 -1
  16. package/dist/features/endpoints/utils.js +18 -0
  17. package/dist/features/functions/controller.d.ts.map +1 -1
  18. package/dist/features/functions/controller.js +10 -2
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +11 -1
  21. package/dist/monitoring/plugin.d.ts +7 -0
  22. package/dist/monitoring/plugin.d.ts.map +1 -0
  23. package/dist/monitoring/plugin.js +1347 -0
  24. package/dist/utils/initializer/exposeRoutes.d.ts.map +1 -1
  25. package/dist/utils/initializer/exposeRoutes.js +10 -2
  26. package/dist/utils/initializer/registerPlugins.d.ts.map +1 -1
  27. package/dist/utils/initializer/registerPlugins.js +10 -1
  28. package/package.json +5 -3
  29. package/src/auth/controller.ts +15 -1
  30. package/src/auth/providers/anon-user/controller.ts +5 -0
  31. package/src/auth/providers/custom-function/schema.ts +23 -24
  32. package/src/auth/utils.ts +6 -0
  33. package/src/constants.ts +22 -0
  34. package/src/features/endpoints/utils.ts +18 -0
  35. package/src/features/functions/controller.ts +10 -2
  36. package/src/index.ts +10 -1
  37. package/src/monitoring/plugin.ts +1528 -0
  38. package/src/monitoring/ui.css +983 -0
  39. package/src/monitoring/ui.html +289 -0
  40. package/src/monitoring/ui.js +1826 -0
  41. package/src/utils/initializer/exposeRoutes.ts +10 -2
  42. package/src/utils/initializer/registerPlugins.ts +13 -2
@@ -1 +1 @@
1
- {"version":3,"file":"exposeRoutes.d.ts","sourceRoot":"","sources":["../../../src/utils/initializer/exposeRoutes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAOzC;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAU,SAAS,eAAe,kBA2E1D,CAAA"}
1
+ {"version":3,"file":"exposeRoutes.d.ts","sourceRoot":"","sources":["../../../src/utils/initializer/exposeRoutes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAOzC;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAU,SAAS,eAAe,kBAmF1D,CAAA"}
@@ -22,7 +22,11 @@ const crypto_1 = require("../crypto");
22
22
  */
23
23
  const exposeRoutes = (fastify) => __awaiter(void 0, void 0, void 0, function* () {
24
24
  try {
25
- fastify.get(`${constants_1.API_VERSION}/app/:appId/location`, (req) => __awaiter(void 0, void 0, void 0, function* () {
25
+ fastify.get(`${constants_1.API_VERSION}/app/:appId/location`, {
26
+ schema: {
27
+ tags: ['System']
28
+ }
29
+ }, (req) => __awaiter(void 0, void 0, void 0, function* () {
26
30
  var _a, _b, _c;
27
31
  const schema = (_a = constants_1.DEFAULT_CONFIG === null || constants_1.DEFAULT_CONFIG === void 0 ? void 0 : constants_1.DEFAULT_CONFIG.HTTPS_SCHEMA) !== null && _a !== void 0 ? _a : 'http';
28
32
  const headerHost = (_b = req.headers.host) !== null && _b !== void 0 ? _b : 'localhost:3000';
@@ -37,7 +41,11 @@ const exposeRoutes = (fastify) => __awaiter(void 0, void 0, void 0, function* ()
37
41
  ws_hostname: `${wsSchema}://${host}`
38
42
  };
39
43
  }));
40
- fastify.get('/health', () => __awaiter(void 0, void 0, void 0, function* () {
44
+ fastify.get('/health', {
45
+ schema: {
46
+ tags: ['System']
47
+ }
48
+ }, () => __awaiter(void 0, void 0, void 0, function* () {
41
49
  return ({
42
50
  status: 'ok',
43
51
  uptime: (0, node_process_1.uptime)()
@@ -1 +1 @@
1
- {"version":3,"file":"registerPlugins.d.ts","sourceRoot":"","sources":["../../../src/utils/initializer/registerPlugins.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAOnC,OAAO,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAA;AAE9D,KAAK,gBAAgB,GAAG,eAAe,CAAC,UAAU,CAAC,CAAA;AAGnD,KAAK,qBAAqB,GAAG;IAC3B,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,SAAS,CAAA;IACxB,UAAU,CAAC,EAAE,UAAU,CAAA;CACxB,CAAA;AAQD;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAAU,gEAMnC,qBAAqB,kBAsBvB,CAAA"}
1
+ {"version":3,"file":"registerPlugins.d.ts","sourceRoot":"","sources":["../../../src/utils/initializer/registerPlugins.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAOnC,OAAO,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAA;AAG9D,KAAK,gBAAgB,GAAG,eAAe,CAAC,UAAU,CAAC,CAAA;AAGnD,KAAK,qBAAqB,GAAG;IAC3B,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,SAAS,CAAA;IACxB,UAAU,CAAC,EAAE,UAAU,CAAA;CACxB,CAAA;AAQD;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAAU,gEAMnC,qBAAqB,kBAsBvB,CAAA"}
@@ -22,6 +22,7 @@ const controller_2 = require("../../auth/providers/anon-user/controller");
22
22
  const controller_3 = require("../../auth/providers/custom-function/controller");
23
23
  const controller_4 = require("../../auth/providers/local-userpass/controller");
24
24
  const constants_1 = require("../../constants");
25
+ const plugin_1 = __importDefault(require("../../monitoring/plugin"));
25
26
  /**
26
27
  * > Used to register all plugins
27
28
  * @param register -> the fastify register method
@@ -65,7 +66,7 @@ const getRegisterConfig = (_a) => __awaiter(void 0, [_a], void 0, function* ({ m
65
66
  origin: '*',
66
67
  methods: ['POST', 'GET']
67
68
  };
68
- return [
69
+ const baseConfig = [
69
70
  {
70
71
  pluginName: 'cors',
71
72
  plugin: cors_1.default,
@@ -125,4 +126,12 @@ const getRegisterConfig = (_a) => __awaiter(void 0, [_a], void 0, function* ({ m
125
126
  }
126
127
  }
127
128
  ];
129
+ if (constants_1.DEFAULT_CONFIG.MONIT_ENABLED) {
130
+ baseConfig.splice(2, 0, {
131
+ pluginName: 'monitoringPlugin',
132
+ plugin: plugin_1.default,
133
+ options: { basePath: '/monit' }
134
+ });
135
+ }
136
+ return baseConfig;
128
137
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowerforce/flowerbase",
3
- "version": "1.6.2",
3
+ "version": "1.6.3-beta.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -20,13 +20,15 @@
20
20
  "author": "",
21
21
  "license": "MIT",
22
22
  "dependencies": {
23
+ "@aws-sdk/client-lambda": "^3.974.0",
24
+ "@aws-sdk/client-s3": "^3.974.0",
25
+ "@aws-sdk/s3-request-presigner": "^3.975.0",
23
26
  "@fastify/cors": "^10.0.1",
24
27
  "@fastify/jwt": "^9.0.1",
25
28
  "@fastify/mongodb": "^9.0.1",
26
29
  "@fastify/swagger": "^9.5.1",
27
30
  "@fastify/swagger-ui": "^5.2.3",
28
- "@aws-sdk/client-lambda": "^3.974.0",
29
- "@aws-sdk/client-s3": "^3.974.0",
31
+ "@fastify/websocket": "^11.2.0",
30
32
  "bson": "^6.8.0",
31
33
  "dotenv": "^16.4.7",
32
34
  "fastify": "^5.0.0",
@@ -47,7 +47,11 @@ export async function authController(app: FastifyInstance) {
47
47
  * @param {import('fastify').FastifyRequest} req - The request object.
48
48
  * @returns {Promise<Object>} A promise resolving with the user's profile data.
49
49
  */
50
- app.get(AUTH_ENDPOINTS.PROFILE, async function (req) {
50
+ app.get(AUTH_ENDPOINTS.PROFILE, {
51
+ schema: {
52
+ tags: ['Auth']
53
+ }
54
+ }, async function (req) {
51
55
  if (req.user.typ !== 'access') {
52
56
  throw new Error('Access token required')
53
57
  }
@@ -76,6 +80,11 @@ export async function authController(app: FastifyInstance) {
76
80
  */
77
81
  app.post<{ Reply: SessionCreatedDto }>(
78
82
  AUTH_ENDPOINTS.SESSION,
83
+ {
84
+ schema: {
85
+ tags: ['Auth']
86
+ }
87
+ },
79
88
  async function (req, res) {
80
89
  if (req.user.typ !== 'refresh') {
81
90
  throw new Error(AUTH_ERRORS.INVALID_TOKEN)
@@ -125,6 +134,11 @@ export async function authController(app: FastifyInstance) {
125
134
  */
126
135
  app.delete(
127
136
  AUTH_ENDPOINTS.SESSION,
137
+ {
138
+ schema: {
139
+ tags: ['Auth']
140
+ }
141
+ },
128
142
  async function (req, res) {
129
143
  const authHeader = req.headers.authorization
130
144
  if (!authHeader?.startsWith('Bearer ')) {
@@ -31,6 +31,11 @@ export async function anonUserController(app: FastifyInstance) {
31
31
 
32
32
  app.post<LoginDto>(
33
33
  AUTH_ENDPOINTS.LOGIN,
34
+ {
35
+ schema: {
36
+ tags: ['Auth']
37
+ }
38
+ },
34
39
  async function () {
35
40
  const anonProvider = AUTH_CONFIG.authProviders?.['anon-user']
36
41
  if (!anonProvider || anonProvider.disabled) {
@@ -1,25 +1,24 @@
1
1
  export const LOGIN_SCHEMA = {
2
- body: {
3
- type: 'object',
4
- properties:
5
- {
6
- apiKey: { type: 'string' },
7
- options: {
8
- type: "object",
9
- properties: {
10
- device: {
11
- type: "object",
12
- properties: {
13
- sdkVersion: { type: 'string' },
14
- platform: { type: 'string' },
15
- platformVersion: { type: 'string' }
16
- }
17
- }
18
-
19
- }
20
- },
21
-
22
- },
23
- required: ['apiKey', 'options']
24
- }
25
- }
2
+ tags: ['Auth'],
3
+ body: {
4
+ type: 'object',
5
+ properties:
6
+ {
7
+ apiKey: { type: 'string' },
8
+ options: {
9
+ type: "object",
10
+ properties: {
11
+ device: {
12
+ type: "object",
13
+ properties: {
14
+ sdkVersion: { type: 'string' },
15
+ platform: { type: 'string' },
16
+ platformVersion: { type: 'string' }
17
+ }
18
+ }
19
+ }
20
+ },
21
+ },
22
+ required: ['apiKey', 'options']
23
+ }
24
+ }
package/src/auth/utils.ts CHANGED
@@ -5,6 +5,7 @@ import path from 'path'
5
5
  const CHARSET =
6
6
  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_=+[]{};:,.<>?";
7
7
  export const LOGIN_SCHEMA = {
8
+ tags: ['Auth'],
8
9
  body: {
9
10
  type: 'object',
10
11
  properties: {
@@ -21,6 +22,7 @@ export const LOGIN_SCHEMA = {
21
22
  }
22
23
 
23
24
  export const RESET_SEND_SCHEMA = {
25
+ tags: ['Auth'],
24
26
  body: {
25
27
  type: 'object',
26
28
  properties: {
@@ -36,6 +38,7 @@ export const RESET_SEND_SCHEMA = {
36
38
  }
37
39
 
38
40
  export const RESET_CALL_SCHEMA = {
41
+ tags: ['Auth'],
39
42
  body: {
40
43
  type: 'object',
41
44
  properties: {
@@ -53,6 +56,7 @@ export const RESET_CALL_SCHEMA = {
53
56
  }
54
57
 
55
58
  export const CONFIRM_RESET_SCHEMA = {
59
+ tags: ['Auth'],
56
60
  body: {
57
61
  type: 'object',
58
62
  properties: {
@@ -65,6 +69,7 @@ export const CONFIRM_RESET_SCHEMA = {
65
69
  }
66
70
 
67
71
  export const CONFIRM_USER_SCHEMA = {
72
+ tags: ['Auth'],
68
73
  body: {
69
74
  type: 'object',
70
75
  properties: {
@@ -78,6 +83,7 @@ export const CONFIRM_USER_SCHEMA = {
78
83
  export const RESET_SCHEMA = RESET_SEND_SCHEMA
79
84
 
80
85
  export const REGISTRATION_SCHEMA = {
86
+ tags: ['Auth'],
81
87
  body: {
82
88
  type: 'object',
83
89
  properties: {
package/src/constants.ts CHANGED
@@ -6,6 +6,13 @@ const parseBoolean = (value?: string) => {
6
6
  return ['1', 'true', 'yes', 'on'].includes(value.toLowerCase())
7
7
  }
8
8
 
9
+ const monitUser = process.env.MONIT_USER || process.env.SWAGGER_UI_USER || ''
10
+ const monitPassword = process.env.MONIT_PASSWORD || process.env.SWAGGER_UI_PASSWORD || ''
11
+ const monitEnabledEnv = process.env.MONIT_ENABLED
12
+ const monitEnabled = typeof monitEnabledEnv === 'string'
13
+ ? parseBoolean(monitEnabledEnv)
14
+ : false
15
+
9
16
  const {
10
17
  database_name,
11
18
  collection_name = 'users',
@@ -32,6 +39,21 @@ export const DEFAULT_CONFIG = {
32
39
  SWAGGER_ENABLED: parseBoolean(process.env.SWAGGER_ENABLED),
33
40
  SWAGGER_UI_USER: process.env.SWAGGER_UI_USER || '',
34
41
  SWAGGER_UI_PASSWORD: process.env.SWAGGER_UI_PASSWORD || '',
42
+ MONIT_ENABLED: monitEnabled,
43
+ MONIT_USER: monitUser,
44
+ MONIT_PASSWORD: monitPassword,
45
+ MONIT_CACHE_HOURS: Number(process.env.MONIT_CACHE_HOURS) || 24,
46
+ MONIT_MAX_EVENTS: Number(process.env.MONIT_MAX_EVENTS) || 5000,
47
+ MONIT_CAPTURE_CONSOLE: parseBoolean(process.env.MONIT_CAPTURE_CONSOLE ?? 'true'),
48
+ MONIT_REDACT_ERROR_DETAILS: parseBoolean(process.env.MONIT_REDACT_ERROR_DETAILS ?? 'true'),
49
+ MONIT_ALLOWED_IPS: (process.env.MONIT_ALLOWED_IPS ?? '')
50
+ .split(',')
51
+ .map((item) => item.trim())
52
+ .filter(Boolean),
53
+ MONIT_RATE_LIMIT_WINDOW_MS: Number(process.env.MONIT_RATE_LIMIT_WINDOW_MS) || 60_000,
54
+ MONIT_RATE_LIMIT_MAX: Number(process.env.MONIT_RATE_LIMIT_MAX) || 120,
55
+ MONIT_ALLOW_INVOKE: parseBoolean(process.env.MONIT_ALLOW_INVOKE ?? 'true'),
56
+ MONIT_ALLOW_EDIT: parseBoolean(process.env.MONIT_ALLOW_EDIT ?? 'true'),
35
57
  CORS_OPTIONS: {
36
58
  origin: "*",
37
59
  methods: ["GET", "POST", "PUT", "DELETE"] as ALLOWED_METHODS[]
@@ -60,31 +60,49 @@ export const getMethodsConfig = (
60
60
  config: {
61
61
  rawBody: true
62
62
  },
63
+ schema: {
64
+ tags: ['Endpoints']
65
+ }
63
66
  }, handler),
64
67
  GET: () => app.get(endpoint, {
65
68
  config: {
66
69
  rawBody: true
67
70
  },
71
+ schema: {
72
+ tags: ['Endpoints']
73
+ }
68
74
  }, handler),
69
75
  POST: () => app.post(endpoint, {
70
76
  config: {
71
77
  rawBody: true
72
78
  },
79
+ schema: {
80
+ tags: ['Endpoints']
81
+ }
73
82
  }, handler),
74
83
  PUT: () => app.put(endpoint, {
75
84
  config: {
76
85
  rawBody: true
77
86
  },
87
+ schema: {
88
+ tags: ['Endpoints']
89
+ }
78
90
  }, handler),
79
91
  PATCH: () => app.patch(endpoint, {
80
92
  config: {
81
93
  rawBody: true
82
94
  },
95
+ schema: {
96
+ tags: ['Endpoints']
97
+ }
83
98
  }, handler),
84
99
  DELETE: () => app.delete(endpoint, {
85
100
  config: {
86
101
  rawBody: true
87
102
  },
103
+ schema: {
104
+ tags: ['Endpoints']
105
+ }
88
106
  }, handler)
89
107
  })
90
108
 
@@ -62,7 +62,11 @@ export const functionsController: FunctionController = async (
62
62
 
63
63
  const streams = {} as Record<string, ChangeStream<Document, Document>>
64
64
 
65
- app.post<{ Body: FunctionCallDto }>('/call', async (req, res) => {
65
+ app.post<{ Body: FunctionCallDto }>('/call', {
66
+ schema: {
67
+ tags: ['Functions']
68
+ }
69
+ }, async (req, res) => {
66
70
  const user = getRequestUser(req)
67
71
  if (!user || user.typ !== 'access') {
68
72
  throw new Error('Access token required')
@@ -148,7 +152,11 @@ export const functionsController: FunctionController = async (
148
152
  })
149
153
  app.get<{
150
154
  Querystring: FunctionCallBase64Dto
151
- }>('/call', async (req, res) => {
155
+ }>('/call', {
156
+ schema: {
157
+ tags: ['Functions']
158
+ }
159
+ }, async (req, res) => {
152
160
  const { query } = req
153
161
  const user = getRequestUser(req)
154
162
  if (!user || user.typ !== 'access') {
package/src/index.ts CHANGED
@@ -132,7 +132,16 @@ export async function initialize({
132
132
  },
133
133
  staticCSP: true,
134
134
  transformStaticCSP: (header) => header,
135
- transformSpecification: (swaggerObject,) => { return swaggerObject },
135
+ transformSpecification: (swaggerObject) => {
136
+ if (!swaggerObject || !swaggerObject.paths) return swaggerObject
137
+ const filteredPaths = { ...swaggerObject.paths }
138
+ Object.keys(filteredPaths).forEach((path) => {
139
+ if (path === '/monit' || path.startsWith('/monit/')) {
140
+ delete filteredPaths[path]
141
+ }
142
+ })
143
+ return { ...swaggerObject, paths: filteredPaths }
144
+ },
136
145
  transformSpecificationClone: true
137
146
  })
138
147
  }