@raclettejs/core 0.1.11 → 0.1.13

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 (94) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/dist/cli.js +97 -97
  3. package/dist/cli.js.map +7 -0
  4. package/dist/index.js +4 -4
  5. package/dist/index.js.map +7 -0
  6. package/package.json +4 -3
  7. package/services/backend/package.json +1 -0
  8. package/services/backend/src/core/payload/payloadTypes.ts +7 -0
  9. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/account/routes/route.account.get.ts +1 -1
  10. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/account/routes/route.account.getAll.ts +1 -1
  11. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/composition.model.ts +5 -0
  12. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/composition.schema.ts +1 -0
  13. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/composition.service.ts +1 -1
  14. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/routes/route.composition.get.ts +1 -1
  15. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/routes/route.composition.getAll.ts +1 -1
  16. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/interactionLink/helpers/payload.ts +6 -2
  17. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/interactionLink/routes/route.interactionLink.get.ts +1 -1
  18. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/interactionLink/routes/route.interactionLink.getAll.ts +1 -1
  19. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/project/routes/route.project.get.ts +1 -1
  20. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/project/routes/route.project.getAll.ts +1 -1
  21. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/index.ts +2 -1
  22. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/routes/route.tag.get.ts +1 -1
  23. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/routes/route.tag.getAll.ts +6 -2
  24. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/tag.service.ts +22 -1
  25. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/routes/route.user.get.ts +1 -1
  26. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/routes/route.user.getAll.ts +1 -1
  27. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/routes/route.user.remove.ts +3 -0
  28. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/user.service.ts +1 -2
  29. package/services/backend/src/corePlugins/raclette__core/frontend/generated-config.ts +12 -12
  30. package/services/backend/src/domains/index.ts +3 -0
  31. package/services/backend/src/domains/system/collections.service.ts +119 -0
  32. package/services/backend/src/domains/system/index.ts +8 -0
  33. package/services/backend/src/domains/system/routes/index.ts +5 -0
  34. package/services/backend/src/domains/system/routes/route.collection.getAll.ts +61 -0
  35. package/services/backend/src/domains/system/routes/route.collection.remove.ts +93 -0
  36. package/services/backend/src/types/custom-fastify.d.ts +1 -0
  37. package/services/backend/src/utils/request.utils.ts +28 -1
  38. package/services/backend/yarn.lock +11 -2
  39. package/services/frontend/package.json +1 -0
  40. package/services/frontend/src/core/constants/ApiClient.ts +6 -1
  41. package/services/frontend/src/core/lib/data/dataApi.ts +8 -1
  42. package/services/frontend/src/core/lib/data/fetchDataHandler.ts +58 -27
  43. package/services/frontend/src/core/lib/data/queryApi.ts +29 -8
  44. package/services/frontend/src/core/lib/data/responseTypeHandler.ts +27 -4
  45. package/services/frontend/src/core/lib/data/writeDataHandler.ts +1 -1
  46. package/services/frontend/src/core/lib/dataHelper.ts +8 -1
  47. package/services/frontend/src/core/lib/easteregg.ts +1 -1
  48. package/services/frontend/src/core/lib/eventEmitter.ts +1 -0
  49. package/services/frontend/src/core/lib/eventWhitelist.ts +11 -1
  50. package/services/frontend/src/core/lib/logger.ts +11 -3
  51. package/services/frontend/src/core/lib/userNotifier.ts +17 -17
  52. package/services/frontend/src/core/main.ts +3 -3
  53. package/services/frontend/src/core/setup/plugin-system/api/wrappers.ts +18 -1
  54. package/services/frontend/src/core/setup/plugin-system/registration/index.ts +1 -1
  55. package/services/frontend/src/core/setup/socketClient.ts +2 -2
  56. package/services/frontend/src/core/setup/socketEvents.ts +2 -2
  57. package/services/frontend/src/core/store/reducers/compositions/selectors.ts +2 -2
  58. package/services/frontend/src/core/store/reducers/data/index.ts +1 -1
  59. package/services/frontend/src/core/store/reducers/data/reducers.ts +3 -3
  60. package/services/frontend/src/core/store/reducers/queries/effects.ts +20 -1
  61. package/services/frontend/src/core/store/reducers/queries/index.ts +1 -0
  62. package/services/frontend/src/core/store/reducers/queries/reducers.ts +28 -1
  63. package/services/frontend/src/core/store/reducers/queriesCache/queryCacheHelper.ts +5 -4
  64. package/services/frontend/src/core/store/reducers/queriesCache/reducers.ts +4 -3
  65. package/services/frontend/src/core/store/state.ts +1 -1
  66. package/services/frontend/src/core/types/ApiClient.ts +1 -1
  67. package/services/frontend/src/core/types/DataApi.ts +4 -0
  68. package/services/frontend/src/core/types/Queries.ts +1 -0
  69. package/services/frontend/src/orchestrator/ProductOrchestrator.vue +19 -7
  70. package/services/frontend/src/orchestrator/WelcomeScreen.vue +40 -42
  71. package/services/frontend/src/orchestrator/assets/styles/tailwindStyles.css +3 -0
  72. package/services/frontend/src/orchestrator/assets/styles/themes/dark.ts +2 -2
  73. package/services/frontend/src/orchestrator/components/composition/CompositionOverlay.vue +11 -2
  74. package/services/frontend/src/orchestrator/components/composition/WidgetsLayoutLoader.vue +167 -58
  75. package/services/frontend/src/orchestrator/components/menu/DevIndicator.vue +122 -7
  76. package/services/frontend/src/orchestrator/components/menu/UserMenu.vue +38 -20
  77. package/services/frontend/src/orchestrator/components/snackbar/SnackStack.vue +17 -5
  78. package/services/frontend/src/orchestrator/composables/useCurrentComposition.ts +32 -4
  79. package/services/frontend/src/orchestrator/composables/usePageNavigation.ts +5 -1
  80. package/services/frontend/src/orchestrator/composables/usePluginApi.ts +113 -63
  81. package/services/frontend/src/orchestrator/composables/useRouteState.ts +0 -1
  82. package/services/frontend/src/orchestrator/composables/useVueQueryObservableHelper.ts +2 -0
  83. package/services/frontend/src/orchestrator/composables/useVueWriteOperationHelper.ts +5 -3
  84. package/services/frontend/src/orchestrator/composables/useWidgets/helperFunctions.ts +4 -1
  85. package/services/frontend/src/orchestrator/helpers/loginUserNotifications.ts +1 -1
  86. package/services/frontend/src/orchestrator/helpers/uiHelper.ts +1 -1
  87. package/services/frontend/src/orchestrator/i18n/de-DE.json +1 -0
  88. package/services/frontend/src/orchestrator/i18n/en-EU.json +1 -0
  89. package/services/frontend/src/orchestrator/i18n/sk.json +1 -0
  90. package/services/frontend/src/orchestrator/router/routeParserHelper.ts +4 -1
  91. package/services/frontend/src/orchestrator/router/routeStore.ts +78 -11
  92. package/services/frontend/tsconfig.app.json +1 -0
  93. package/services/frontend/yarn.lock +5 -0
  94. package/yarn.lock +4 -4
@@ -6,7 +6,11 @@ export default (fastify: PluginFastifyInstance) => {
6
6
 
7
7
  const handler = async (req: FastifyRequest, reply: FastifyReply) => {
8
8
  try {
9
- const payload = await tagService.readTags(fastify, req.requestParams)
9
+ const payload = await tagService.readTags(
10
+ fastify,
11
+ req.requestParams,
12
+ req.query,
13
+ )
10
14
 
11
15
  if (!payload || payload.length === 0) {
12
16
  return reply.code(204).send()
@@ -24,7 +28,7 @@ export default (fastify: PluginFastifyInstance) => {
24
28
  handler,
25
29
  onRequest: [fastify.authenticate],
26
30
  config: {
27
- type: "dataPush",
31
+ type: "dataRead",
28
32
  },
29
33
  schema: {
30
34
  summary: "Get all tags for the given project.",
@@ -101,6 +101,27 @@ export class TagService {
101
101
  return createTagPayload(fastify, [tag], requestData)
102
102
  }
103
103
 
104
+ /**
105
+ * Core function to read a tag by name – used for internal system functions mainly
106
+ */
107
+ async _readTagByTitle(
108
+ fastify: PluginFastifyInstance,
109
+ title: string,
110
+ ): Promise<TagType> {
111
+ try {
112
+ const tags = await this.tagModel.find({ title }).lean()
113
+
114
+ if (!tags) {
115
+ throw new Error(`Tag with title ${title} not found`)
116
+ }
117
+
118
+ return tags[0]
119
+ } catch (error: any) {
120
+ fastify.log.error(error.message)
121
+ throw error
122
+ }
123
+ }
124
+
104
125
  /**
105
126
  * Core function to read tags by ID or filter parameters (returns raw data)
106
127
  */
@@ -153,7 +174,7 @@ export class TagService {
153
174
 
154
175
  return createTagPayload(fastify, [tag], requestData)
155
176
  } else {
156
- const tags = await this._readTags(fastify, filter)
177
+ const tags = await this._readTags(fastify, filter, requestData.options)
157
178
 
158
179
  return createTagPayload(fastify, tags, requestData)
159
180
  }
@@ -39,7 +39,7 @@ export default (fastify: PluginFastifyInstance) => {
39
39
  handler,
40
40
  onRequest: [fastify.authenticate],
41
41
  config: {
42
- type: "dataPush",
42
+ type: "dataRead",
43
43
  },
44
44
  schema: {
45
45
  summary: "Get user",
@@ -39,7 +39,7 @@ export default (fastify: PluginFastifyInstance) => {
39
39
  handler,
40
40
  onRequest: [fastify.authenticate],
41
41
  config: {
42
- type: "dataPush",
42
+ type: "dataRead",
43
43
  },
44
44
  schema: {
45
45
  summary: "Get users",
@@ -19,6 +19,9 @@ export default (fastify: PluginFastifyInstance) => {
19
19
  reply: FastifyReply,
20
20
  ) => {
21
21
  try {
22
+ if (!req.user.isAdmin) {
23
+ throw new ForbiddenError("Only Admins can use this feature")
24
+ }
22
25
  if (req.user._id === req.params._id) {
23
26
  throw new ForbiddenError("A user cannot remove itself")
24
27
  }
@@ -168,9 +168,8 @@ export class UserService {
168
168
  fastify: PluginFastifyInstance,
169
169
  requestData: FrontendPayloadRequestData,
170
170
  filter: Record<string, any> = {},
171
- options: QueryOptions = {},
172
171
  ): Promise<FrontendPayload<PublicUser[]>> {
173
- const users = await this._readUsers(fastify, filter, options)
172
+ const users = await this._readUsers(fastify, filter, requestData.options)
174
173
 
175
174
  return createUserPayload(fastify, users, requestData)
176
175
  }
@@ -15,12 +15,12 @@ export default {
15
15
  getAll: {
16
16
  target: "/raclette__core/account/all",
17
17
  method: "get",
18
- storeActionType: "dataPush"
18
+ storeActionType: "dataRead"
19
19
  },
20
20
  get: {
21
21
  target: (payload) => `/raclette__core/account/${payload._id}`,
22
22
  method: "get",
23
- storeActionType: "dataPush"
23
+ storeActionType: "dataRead"
24
24
  },
25
25
  update: {
26
26
  target: (payload) => `/raclette__core/account/${payload._id}`,
@@ -83,12 +83,12 @@ export default {
83
83
  getAll: {
84
84
  target: "/raclette__core/interactionLink/all",
85
85
  method: "get",
86
- storeActionType: "dataPush"
86
+ storeActionType: "dataRead"
87
87
  },
88
88
  get: {
89
89
  target: (payload) => `/raclette__core/interactionLink/${payload._id}`,
90
90
  method: "get",
91
- storeActionType: "dataPush"
91
+ storeActionType: "dataRead"
92
92
  },
93
93
  update: {
94
94
  target: (payload) => `/raclette__core/interactionLink/${payload._id}`,
@@ -146,12 +146,12 @@ export default {
146
146
  getAll: {
147
147
  target: "/raclette__core/project/all",
148
148
  method: "get",
149
- storeActionType: "dataPush"
149
+ storeActionType: "dataRead"
150
150
  },
151
151
  get: {
152
152
  target: (payload) => `/raclette__core/project/${payload._id}`,
153
153
  method: "get",
154
- storeActionType: "dataPush"
154
+ storeActionType: "dataRead"
155
155
  },
156
156
  create: {
157
157
  target: "/raclette__core/project",
@@ -209,12 +209,12 @@ export default {
209
209
  getAll: {
210
210
  target: "/raclette__core/tag/all",
211
211
  method: "get",
212
- storeActionType: "dataPush"
212
+ storeActionType: "dataRead"
213
213
  },
214
214
  get: {
215
215
  target: (payload) => `/raclette__core/tag/${payload._id}`,
216
216
  method: "get",
217
- storeActionType: "dataPush"
217
+ storeActionType: "dataRead"
218
218
  },
219
219
  update: {
220
220
  target: (payload) => `/raclette__core/tag/${payload._id}`,
@@ -272,12 +272,12 @@ export default {
272
272
  getAll: {
273
273
  target: "/raclette__core/user/all",
274
274
  method: "get",
275
- storeActionType: "dataPush"
275
+ storeActionType: "dataRead"
276
276
  },
277
277
  get: {
278
278
  target: (payload) => `/raclette__core/user/${payload._id}`,
279
279
  method: "get",
280
- storeActionType: "dataPush"
280
+ storeActionType: "dataRead"
281
281
  },
282
282
  update: {
283
283
  target: (payload) => `/raclette__core/user/${payload._id}`,
@@ -335,12 +335,12 @@ export default {
335
335
  getAll: {
336
336
  target: "/raclette__core/composition/all",
337
337
  method: "get",
338
- storeActionType: "dataPush"
338
+ storeActionType: "dataRead"
339
339
  },
340
340
  get: {
341
341
  target: (payload) => `/raclette__core/composition/${payload._id}`,
342
342
  method: "get",
343
- storeActionType: "dataPush"
343
+ storeActionType: "dataRead"
344
344
  },
345
345
  update: {
346
346
  target: (payload) => `/raclette__core/composition/${payload._id}`,
@@ -6,6 +6,9 @@ import registerSystem from "./system"
6
6
  * Core service export all routes
7
7
  */
8
8
  const registerCore = async (fastify: FastifyInstance) => {
9
+ if (!fastify.core) {
10
+ fastify.core = {}
11
+ }
9
12
  registerSystem(fastify)
10
13
  }
11
14
 
@@ -0,0 +1,119 @@
1
+ import type { PluginFastifyInstance } from "types"
2
+ import mongoose, { type Connection } from "mongoose"
3
+
4
+ export interface CollectionInfo {
5
+ name: string
6
+ count: number
7
+ size: number
8
+ indexes: number
9
+ }
10
+
11
+ export class CollectionService {
12
+ private connection: Connection
13
+
14
+ constructor(connection: Connection) {
15
+ this.connection = connection
16
+ }
17
+
18
+ /**
19
+ * Get all collection names and their metadata
20
+ */
21
+ async getCollections(
22
+ fastify: PluginFastifyInstance,
23
+ ): Promise<CollectionInfo[]> {
24
+ try {
25
+ const db = this.connection.db
26
+ const collections = await db.listCollections().toArray()
27
+
28
+ const collectionInfos: CollectionInfo[] = []
29
+
30
+ for (const collection of collections) {
31
+ const collectionName = collection.name
32
+
33
+ // Get document count
34
+ const count = await db.collection(collectionName).countDocuments()
35
+
36
+ // Get collection stats using MongoDB command
37
+ const stats = await db.command({ collStats: collectionName })
38
+
39
+ collectionInfos.push({
40
+ name: collectionName,
41
+ count: count || 0,
42
+ size: stats.size || 0,
43
+ indexes: stats.nindexes || 0,
44
+ })
45
+ }
46
+
47
+ fastify.log.info(`[API] Retrieved ${collectionInfos.length} collections`)
48
+
49
+ return collectionInfos
50
+ } catch (error: any) {
51
+ fastify.log.error(error.message)
52
+ throw error
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Drop specific collections
58
+ */
59
+ async dropCollections(
60
+ fastify: PluginFastifyInstance,
61
+ collectionNames: string[],
62
+ ): Promise<{ dropped: string[]; failed: string[] }> {
63
+ try {
64
+ const db = this.connection.db
65
+ const dropped: string[] = []
66
+ const failed: string[] = []
67
+
68
+ for (const collectionName of collectionNames) {
69
+ try {
70
+ // Check if collection exists
71
+ const collections = await db
72
+ .listCollections({ name: collectionName })
73
+ .toArray()
74
+
75
+ if (collections.length === 0) {
76
+ fastify.log.warn(`Collection ${collectionName} does not exist`)
77
+ failed.push(collectionName)
78
+ continue
79
+ }
80
+
81
+ // Drop the collection
82
+ await db.collection(collectionName).drop()
83
+ dropped.push(collectionName)
84
+ fastify.log.info(`[API] Dropped collection: ${collectionName}`)
85
+ } catch (error: any) {
86
+ fastify.log.error(
87
+ `Failed to drop collection ${collectionName}: ${error.message}`,
88
+ )
89
+ failed.push(collectionName)
90
+ }
91
+ }
92
+
93
+ return { dropped, failed }
94
+ } catch (error: any) {
95
+ fastify.log.error(error.message)
96
+ throw error
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Drop all collections (use with extreme caution!)
102
+ */
103
+ async dropAllCollections(
104
+ fastify: PluginFastifyInstance,
105
+ ): Promise<{ dropped: string[]; failed: string[] }> {
106
+ try {
107
+ const collections = await this.getCollections(fastify)
108
+ const collectionNames = collections.map((c) => c.name)
109
+
110
+ return await this.dropCollections(fastify, collectionNames)
111
+ } catch (error: any) {
112
+ fastify.log.error(error.message)
113
+ throw error
114
+ }
115
+ }
116
+ }
117
+
118
+ export const createCollectionService = (connection: Connection) =>
119
+ new CollectionService(connection)
@@ -1,8 +1,16 @@
1
1
  import type { FastifyInstance } from "fastify"
2
+ import mongoose from "mongoose"
2
3
  import registerRoutes from "./routes"
4
+ import { createCollectionService } from "./collections.service"
3
5
 
4
6
  const registerSystem = (fastify: FastifyInstance) => {
5
7
  registerRoutes(fastify)
8
+
9
+ // create and pass in the model to your service
10
+ const collectionService = createCollectionService(mongoose.connection)
11
+
12
+ // decorate the service to the instance, so we can easily call it everywhere
13
+ fastify.core.collectionService = collectionService
6
14
  }
7
15
 
8
16
  export default registerSystem
@@ -7,6 +7,8 @@ import {
7
7
  import deploy from "./route.deploy"
8
8
  import login from "./route.user.login"
9
9
  import checkToken from "./route.user.checkToken"
10
+ import getAllCollections from "./route.collection.getAll"
11
+ import deleteCollections from "./route.collection.remove"
10
12
 
11
13
  const registerRoutes = async (fastify: FastifyInstance) => {
12
14
  await fastify.get("/system/deploy", deploy(fastify))
@@ -17,5 +19,8 @@ const registerRoutes = async (fastify: FastifyInstance) => {
17
19
  await fastify.get("/admin/cache/blocks", getBlockedLogins(fastify))
18
20
  await fastify.delete("/admin/cache/blocks/:key", resetLoginBlock(fastify))
19
21
  await fastify.delete("/admin/cache/blocks", resetAllLoginBlocks(fastify))
22
+
23
+ await fastify.get("/admin/collections/all", getAllCollections(fastify))
24
+ await fastify.delete("/admin/collections", deleteCollections(fastify))
20
25
  }
21
26
  export default registerRoutes
@@ -0,0 +1,61 @@
1
+ import type { FastifyReply, FastifyRequest } from "fastify"
2
+ import { PluginFastifyInstance } from "types"
3
+ import { ForbiddenError } from "@/utils/errors"
4
+
5
+ export default (fastify: PluginFastifyInstance) => {
6
+ const collectionService = fastify.core.collectionService
7
+
8
+ const handler = async (req: FastifyRequest, reply: FastifyReply) => {
9
+ try {
10
+ // Restrict to admin users only
11
+ if (!req.user.isAdmin) {
12
+ throw new ForbiddenError(
13
+ "Only Admins can access collection information",
14
+ )
15
+ }
16
+
17
+ const collections = await collectionService.getCollections(fastify)
18
+
19
+ return {
20
+ success: true,
21
+ data: collections,
22
+ total: collections.length,
23
+ }
24
+ } catch (error: any) {
25
+ fastify.log.error(error.message)
26
+ return reply.internalServerError(error.message)
27
+ }
28
+ }
29
+
30
+ return {
31
+ handler,
32
+ onRequest: [fastify.authenticate],
33
+ schema: {
34
+ summary: "Get all collections",
35
+ description:
36
+ "Retrieve all MongoDB collections with metadata (admin only, debug feature)",
37
+ tags: ["debug/collections"],
38
+ response: {
39
+ 200: {
40
+ type: "object",
41
+ properties: {
42
+ success: { type: "boolean" },
43
+ data: {
44
+ type: "array",
45
+ items: {
46
+ type: "object",
47
+ properties: {
48
+ name: { type: "string" },
49
+ count: { type: "number" },
50
+ size: { type: "number" },
51
+ indexes: { type: "number" },
52
+ },
53
+ },
54
+ },
55
+ total: { type: "number" },
56
+ },
57
+ },
58
+ },
59
+ },
60
+ }
61
+ }
@@ -0,0 +1,93 @@
1
+ import type { Static } from "@sinclair/typebox"
2
+ import type { FastifyReply, FastifyRequest } from "fastify"
3
+ import { PluginFastifyInstance } from "types"
4
+ import { Type } from "@sinclair/typebox"
5
+ import { ForbiddenError } from "@/utils/errors"
6
+
7
+ const BodySchema = Type.Object({
8
+ collections: Type.Array(Type.String(), {
9
+ description: "Array of collection names to drop",
10
+ minItems: 1,
11
+ }),
12
+ dropAll: Type.Optional(
13
+ Type.Boolean({
14
+ description:
15
+ "If true, drops all collections (overrides collections array)",
16
+ }),
17
+ ),
18
+ })
19
+ type Body = Static<typeof BodySchema>
20
+
21
+ export default (fastify: PluginFastifyInstance) => {
22
+ const collectionService = fastify.core.collectionService
23
+
24
+ const handler = async (
25
+ req: FastifyRequest<{
26
+ Body: Body
27
+ }>,
28
+ reply: FastifyReply,
29
+ ) => {
30
+ try {
31
+ // Restrict to admin users only
32
+ if (!req.user.isAdmin) {
33
+ throw new ForbiddenError("Only Admins can drop collections")
34
+ }
35
+
36
+ let result
37
+
38
+ if (req.body.dropAll) {
39
+ fastify.log.warn(
40
+ `[API] Admin ${req.user._id} is dropping ALL collections`,
41
+ )
42
+ result = await collectionService.dropAllCollections(fastify)
43
+ } else {
44
+ fastify.log.warn(
45
+ `[API] Admin ${req.user._id} is dropping collections: ${req.body.collections.join(", ")}`,
46
+ )
47
+ result = await collectionService.dropCollections(
48
+ fastify,
49
+ req.body.collections,
50
+ )
51
+ }
52
+
53
+ return {
54
+ success: true,
55
+ dropped: result.dropped,
56
+ failed: result.failed,
57
+ message: `Successfully dropped ${result.dropped.length} collection(s)`,
58
+ }
59
+ } catch (error: any) {
60
+ fastify.log.error(error.message)
61
+ return reply.internalServerError(error.message)
62
+ }
63
+ }
64
+
65
+ return {
66
+ handler,
67
+ onRequest: [fastify.authenticate],
68
+ schema: {
69
+ summary: "Drop collections",
70
+ description:
71
+ "Drop selected MongoDB collections (admin only, debug feature - USE WITH CAUTION)",
72
+ tags: ["debug/collections"],
73
+ body: BodySchema,
74
+ response: {
75
+ 200: {
76
+ type: "object",
77
+ properties: {
78
+ success: { type: "boolean" },
79
+ dropped: {
80
+ type: "array",
81
+ items: { type: "string" },
82
+ },
83
+ failed: {
84
+ type: "array",
85
+ items: { type: "string" },
86
+ },
87
+ message: { type: "string" },
88
+ },
89
+ },
90
+ },
91
+ },
92
+ }
93
+ }
@@ -25,6 +25,7 @@ declare module "fastify" {
25
25
  uos: Client
26
26
  http: HttpService
27
27
  taskManager: TaskManager
28
+ core: any
28
29
  }
29
30
 
30
31
  interface FastifyRequest {
@@ -11,7 +11,7 @@ export const createRequestParams = (
11
11
  req: RequestWithCommonHeaders,
12
12
  config: FastifyContextConfig,
13
13
  ): FrontendPayloadRequestData => {
14
- return {
14
+ const requestParams = {
15
15
  appSessionId: req.headers["app-session-id"] ?? "",
16
16
  appRequestCode: req.headers["app-request-code"] ?? "",
17
17
  requestId: req.id ?? "",
@@ -19,6 +19,33 @@ export const createRequestParams = (
19
19
  broadcast: req.headers["app-broadcast-channels"] ?? false,
20
20
  project: req.headers["current-project"] ?? "",
21
21
  userId: req.user?.id,
22
+ options: {},
22
23
  ...config,
23
24
  }
25
+ // put global query modifiers into requestParams and remove them from params
26
+ if (req?.query?.limit) {
27
+ requestParams.options.limit = req.query.limit
28
+ delete req.query.limit
29
+ }
30
+ if (req?.query?.offset) {
31
+ requestParams.options.offset = req.query.offset
32
+ delete req.query.offset
33
+ }
34
+ if (req?.query?.search) {
35
+ requestParams.options.search = req.query.search
36
+ delete req.query.search
37
+ }
38
+ if (req?.body?.limit) {
39
+ requestParams.options.limit = req.body.limit
40
+ delete req.body.limit
41
+ }
42
+ if (req?.body?.offset) {
43
+ requestParams.options.offset = req.body.offset
44
+ delete req.body.offset
45
+ }
46
+ if (req?.body?.search) {
47
+ requestParams.options.search = req.body.search
48
+ delete req.body.search
49
+ }
50
+ return requestParams
24
51
  }
@@ -345,7 +345,7 @@
345
345
  resolved "https://registry.yarnpkg.com/@lukeed/ms/-/ms-2.0.2.tgz#07f09e59a74c52f4d88c6db5c1054e819538e2a8"
346
346
  integrity sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==
347
347
 
348
- "@mongodb-js/saslprep@^1.1.9":
348
+ "@mongodb-js/saslprep@^1.1.9", "@mongodb-js/saslprep@^1.3.0":
349
349
  version "1.3.0"
350
350
  resolved "https://registry.yarnpkg.com/@mongodb-js/saslprep/-/saslprep-1.3.0.tgz#75bb770b4b0908047b6c6ac2ec841047660e1c82"
351
351
  integrity sha512-zlayKCsIjYb7/IdfqxorK5+xUMyi4vOKcFy10wKJYc63NSdKI8mNME+uJqfatkPmOSMMUiojrL58IePKBm3gvQ==
@@ -2431,7 +2431,7 @@ mnemonist@^0.40.0:
2431
2431
  dependencies:
2432
2432
  obliterator "^2.0.4"
2433
2433
 
2434
- mongodb-connection-string-url@^3.0.0:
2434
+ mongodb-connection-string-url@^3.0.0, mongodb-connection-string-url@^3.0.2:
2435
2435
  version "3.0.2"
2436
2436
  resolved "https://registry.yarnpkg.com/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz#e223089dfa0a5fa9bf505f8aedcbc67b077b33e7"
2437
2437
  integrity sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==
@@ -2439,6 +2439,15 @@ mongodb-connection-string-url@^3.0.0:
2439
2439
  "@types/whatwg-url" "^11.0.2"
2440
2440
  whatwg-url "^14.1.0 || ^13.0.0"
2441
2441
 
2442
+ mongodb@^6.20.0:
2443
+ version "6.20.0"
2444
+ resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-6.20.0.tgz#5212dcf512719385287aa4574265352eefb01d8e"
2445
+ integrity sha512-Tl6MEIU3K4Rq3TSHd+sZQqRBoGlFsOgNrH5ltAcFBV62Re3Fd+FcaVf8uSEQFOJ51SDowDVttBTONMfoYWrWlQ==
2446
+ dependencies:
2447
+ "@mongodb-js/saslprep" "^1.3.0"
2448
+ bson "^6.10.4"
2449
+ mongodb-connection-string-url "^3.0.2"
2450
+
2442
2451
  mongodb@~6.18.0:
2443
2452
  version "6.18.0"
2444
2453
  resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-6.18.0.tgz#8fab8f841443080924f2cdaa22727cdb7eb20dc3"
@@ -18,6 +18,7 @@
18
18
  "dependencies": {
19
19
  "@date-io/date-fns": "3.2.1",
20
20
  "@mdi/font": "7.4.47",
21
+ "@sinclair/typebox": "0.34.41",
21
22
  "@tailwindcss/vite": "4.1.13",
22
23
  "@tsconfig/node20": "20.1.6",
23
24
  "@vueuse/core": "13.9.0",
@@ -8,4 +8,9 @@ export const cudOperationTypesList = [
8
8
  "dataDelete",
9
9
  "dataHardDeleted",
10
10
  ] as const
11
- export const readOperationTypesList = ["dataPush", "dataAdd", "dataSync"]
11
+ export const readOperationTypesList = [
12
+ "dataReadModified",
13
+ "dataRead",
14
+ "dataAdd",
15
+ "dataSync",
16
+ ]
@@ -63,10 +63,17 @@ const $writeDataApi = (
63
63
  return resultData
64
64
  },
65
65
  // Method to complete the subjects when cleanup is needed
66
- destroy: () => {
66
+ remove: () => {
67
67
  isLoadingSubject$.complete()
68
68
  dataSubject$.complete()
69
69
  errorSubject$.complete()
70
+ responseSubject$.complete()
71
+ },
72
+ clear: () => {
73
+ dataSubject$.next({})
74
+ errorSubject$.next({})
75
+ isLoadingSubject$.next(false)
76
+ dataSubject$.next({})
70
77
  },
71
78
  }
72
79