@mongoosejs/studio 0.2.11 → 0.2.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.
@@ -0,0 +1,38 @@
1
+ 'use strict';
2
+
3
+ const Archetype = require('archetype');
4
+ const authorize = require('../../authorize');
5
+
6
+ const GetEstimatedDocumentCountsParams = new Archetype({
7
+ roles: {
8
+ $type: ['string']
9
+ }
10
+ }).compile('GetEstimatedDocumentCountsParams');
11
+
12
+ module.exports = ({ db }) => async function getEstimatedDocumentCounts(params) {
13
+ const { roles } = new GetEstimatedDocumentCountsParams(params);
14
+ await authorize('Model.getEstimatedDocumentCounts', roles);
15
+
16
+ const modelNames = Object.keys(db.models)
17
+ .filter(key => !key.startsWith('__Studio_'))
18
+ .sort();
19
+
20
+ const results = await Promise.allSettled(
21
+ modelNames.map(name => {
22
+ const Model = db.models[name];
23
+ return Model.estimatedDocumentCount().exec();
24
+ })
25
+ );
26
+
27
+ const counts = {};
28
+ results.forEach((result, index) => {
29
+ const name = modelNames[index];
30
+ if (result.status === 'fulfilled' && typeof result.value === 'number') {
31
+ counts[name] = result.value;
32
+ } else {
33
+ counts[name] = null;
34
+ }
35
+ });
36
+
37
+ return { counts };
38
+ };
@@ -13,6 +13,7 @@ exports.getDocuments = require('./getDocuments');
13
13
  exports.getDocumentsStream = require('./getDocumentsStream');
14
14
  exports.getCollectionInfo = require('./getCollectionInfo');
15
15
  exports.getIndexes = require('./getIndexes');
16
+ exports.getEstimatedDocumentCounts = require('./getEstimatedDocumentCounts');
16
17
  exports.listModels = require('./listModels');
17
18
  exports.streamDocumentChanges = require('./streamDocumentChanges');
18
19
  exports.streamChatMessage = require('./streamChatMessage');
@@ -27,7 +27,8 @@ module.exports = ({ db, changeStream }) => async function* streamDocumentChanges
27
27
  throw new Error(`Model ${model} not found`);
28
28
  }
29
29
 
30
- if (!changeStream) {
30
+ const stream = changeStream();
31
+ if (!stream) {
31
32
  throw new Error('Change streams are not enabled');
32
33
  }
33
34
 
@@ -79,9 +80,9 @@ module.exports = ({ db, changeStream }) => async function* streamDocumentChanges
79
80
  enqueue({ type: 'end' });
80
81
  }
81
82
 
82
- changeStream.on('change', handleChange);
83
- changeStream.on('error', handleError);
84
- changeStream.on('end', handleEnd);
83
+ stream.on('change', handleChange);
84
+ stream.on('error', handleError);
85
+ stream.on('end', handleEnd);
85
86
 
86
87
  try {
87
88
  while (true) {
@@ -112,9 +113,9 @@ module.exports = ({ db, changeStream }) => async function* streamDocumentChanges
112
113
  }
113
114
  }
114
115
  } finally {
115
- changeStream.off('change', handleChange);
116
- changeStream.off('error', handleError);
117
- changeStream.off('end', handleEnd);
116
+ stream.off('change', handleChange);
117
+ stream.off('error', handleError);
118
+ stream.off('end', handleEnd);
118
119
  if (resolveQueue) {
119
120
  resolveQueue();
120
121
  resolveQueue = null;
@@ -4,7 +4,8 @@ const Archetype = require('archetype');
4
4
 
5
5
  const GetTasksParams = new Archetype({
6
6
  start: {
7
- $type: Date
7
+ $type: Date,
8
+ $required: true
8
9
  },
9
10
  end: {
10
11
  $type: Date
@@ -31,22 +32,24 @@ module.exports = ({ db }) => async function getTasks(params) {
31
32
  }
32
33
  if (status) {
33
34
  filter.status = status;
35
+ } else {
36
+ filter.status = { $in: ['pending', 'in_progress', 'succeeded', 'failed', 'cancelled', 'unknown'] };
34
37
  }
35
38
  if (name) {
36
39
  filter.name = { $regex: name, $options: 'i' };
37
40
  }
38
41
 
39
42
  const tasks = await Task.find(filter);
40
-
43
+
41
44
  // Define all possible statuses
42
45
  const allStatuses = ['pending', 'in_progress', 'succeeded', 'failed', 'cancelled', 'unknown'];
43
-
46
+
44
47
  // Initialize groupedTasks with all statuses
45
48
  const groupedTasks = allStatuses.reduce((groups, status) => {
46
49
  groups[status] = [];
47
50
  return groups;
48
51
  }, {});
49
-
52
+
50
53
  // Group tasks by status
51
54
  tasks.forEach(task => {
52
55
  const taskStatus = task.status || 'unknown';
@@ -54,9 +57,9 @@ module.exports = ({ db }) => async function getTasks(params) {
54
57
  groupedTasks[taskStatus].push(task);
55
58
  }
56
59
  });
57
-
60
+
58
61
  return {
59
62
  tasks,
60
63
  groupedTasks
61
64
  };
62
- };
65
+ };
@@ -22,6 +22,7 @@ const actionsToRequiredRoles = {
22
22
  'Model.getDocument': ['owner', 'admin', 'member', 'readonly'],
23
23
  'Model.getDocuments': ['owner', 'admin', 'member', 'readonly'],
24
24
  'Model.getDocumentsStream': ['owner', 'admin', 'member', 'readonly'],
25
+ 'Model.getEstimatedDocumentCounts': ['owner', 'admin', 'member', 'readonly'],
25
26
  'Model.getIndexes': ['owner', 'admin', 'member', 'readonly'],
26
27
  'Model.listModels': ['owner', 'admin', 'member', 'readonly'],
27
28
  'Model.streamDocumentChanges': ['owner', 'admin', 'member', 'readonly'],
package/backend/index.js CHANGED
@@ -18,10 +18,18 @@ module.exports = function backend(db, studioConnection, options) {
18
18
 
19
19
  let changeStream = null;
20
20
  if (options?.changeStream) {
21
- changeStream = db.watch();
21
+ const conn = db instanceof mongoose.Mongoose ? db.connection : db;
22
+ if (conn.readyState !== mongoose.Connection.STATES.connected) {
23
+ conn._waitForConnect().then(() => {
24
+ changeStream = conn.watch();
25
+ });
26
+ } else {
27
+ changeStream = conn.watch();
28
+ }
29
+
22
30
  }
23
31
 
24
- const actions = applySpec(Actions, { db, studioConnection, options, changeStream });
25
- actions.services = { changeStream };
32
+ const actions = applySpec(Actions, { db, studioConnection, options, changeStream: () => changeStream });
33
+ actions.services = { changeStream: () => changeStream };
26
34
  return actions;
27
35
  };
package/eslint.config.js CHANGED
@@ -42,7 +42,8 @@ module.exports = defineConfig([
42
42
  navigator: true,
43
43
  TextDecoder: true,
44
44
  AbortController: true,
45
- clearTimeout: true
45
+ clearTimeout: true,
46
+ requestAnimationFrame: true
46
47
  },
47
48
  sourceType: 'commonjs'
48
49
  },
package/express.js CHANGED
@@ -33,6 +33,7 @@ module.exports = async function mongooseStudioExpressApp(apiUrl, conn, options)
33
33
 
34
34
  apiUrl = apiUrl || 'api';
35
35
  const backend = Backend(conn, options.studioConnection, options);
36
+ delete backend.services;
36
37
 
37
38
  router.use(
38
39
  '/api',