@mongoosejs/studio 0.0.32 → 0.0.34

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.
@@ -19,23 +19,9 @@ module.exports = ({ db }) => async function getDashboard(params) {
19
19
 
20
20
  const dashboard = await Dashboard.findOne({ _id: dashboardId });
21
21
  if (evaluate) {
22
- const context = vm.createContext({ db });
23
22
  let result = null;
24
23
  try {
25
- result = await vm.runInContext(formatFunction(dashboard.code), context);
26
- if (result.$document?.model) {
27
- let schemaPaths = {};
28
- const Model = Dashboard.db.model(result.$document?.model);
29
- for (const path of Object.keys(Model.schema.paths)) {
30
- schemaPaths[path] = {
31
- instance: Model.schema.paths[path].instance,
32
- path,
33
- ref: Model.schema.paths[path].options?.ref,
34
- required: Model.schema.paths[path].options?.required
35
- };
36
- }
37
- result.$document.schemaPaths = schemaPaths;
38
- }
24
+ result = await dashboard.evaluate();
39
25
  } catch (error) {
40
26
  return { dashboard, error: { message: error.message } };
41
27
  }
@@ -44,8 +30,4 @@ module.exports = ({ db }) => async function getDashboard(params) {
44
30
  }
45
31
 
46
32
  return { dashboard };
47
- };
48
-
49
- const formatFunction = code => `(async function() {
50
- ${code}
51
- })();`
33
+ };
@@ -3,23 +3,30 @@
3
3
  const Archetype = require('archetype');
4
4
 
5
5
  const UpdateDashboardParams = new Archetype({
6
- dashboardId: {
7
- $type: 'string',
8
- $required: true
9
- },
10
- code: {
11
- $type: 'string',
12
- $required: true
13
- }
14
- }).compile('UpdateDashboardParams');
15
-
16
- module.exports = ({ db }) => async function updateDashboard(params) {
17
- const { dashboardId, code } = new UpdateDashboardParams(params);
6
+ dashboardId: {
7
+ $type: 'string',
8
+ $required: true
9
+ },
10
+ code: {
11
+ $type: 'string',
12
+ $required: true
13
+ }
14
+ }).compile('UpdateDashboardParams');
15
+
16
+ module.exports = ({ db }) => async function updateDashboard(params) {
17
+ const { dashboardId, code } = new UpdateDashboardParams(params);
18
+
19
+ const Dashboard = db.models[`__Studio_Dashboard`];
20
+
21
+ const doc = await Dashboard.
22
+ findByIdAndUpdate(dashboardId, { code }, { sanitizeFilter: true, returnDocument: 'after', overwriteImmutable: true });
18
23
 
19
- const Dashboard = db.models[`__Studio_Dashboard`];
20
-
21
- const doc = await Dashboard.
22
- findByIdAndUpdate(dashboardId, { code }, { sanitizeFilter: true, returnDocument: 'after', overwriteImmutable: true });
23
-
24
- return { doc };
25
- };
24
+ let result = null;
25
+ try {
26
+ result = await doc.evaluate();
27
+ } catch (error) {
28
+ return { doc, error: { message: error.message } };
29
+ }
30
+
31
+ return { doc, result };
32
+ };
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const mongoose = require('mongoose');
4
+ const vm = require('vm');
4
5
 
5
6
  const dashboardSchema = new mongoose.Schema({
6
7
  title: {
@@ -16,4 +17,29 @@ const dashboardSchema = new mongoose.Schema({
16
17
  }
17
18
  });
18
19
 
19
- module.exports = dashboardSchema;
20
+ dashboardSchema.methods.evaluate = async function evaluate() {
21
+ const context = vm.createContext({ db: this.constructor.db });
22
+ let result = null;
23
+ result = await vm.runInContext(formatFunction(this.code), context);
24
+ if (result.$document?.model) {
25
+ let schemaPaths = {};
26
+ const Model = this.constructor.db.model(result.$document?.model);
27
+ for (const path of Object.keys(Model.schema.paths)) {
28
+ schemaPaths[path] = {
29
+ instance: Model.schema.paths[path].instance,
30
+ path,
31
+ ref: Model.schema.paths[path].options?.ref,
32
+ required: Model.schema.paths[path].options?.required
33
+ };
34
+ }
35
+ result.$document.schemaPaths = schemaPaths;
36
+ }
37
+
38
+ return result;
39
+ };
40
+
41
+ module.exports = dashboardSchema;
42
+
43
+ const formatFunction = code => `(async function() {
44
+ ${code}
45
+ })();`
@@ -28,6 +28,16 @@ if (typeof config__setAuthorizationHeaderFrom === 'string' && config__setAuthori
28
28
  });
29
29
  }
30
30
 
31
+ client.interceptors.response.use(
32
+ res => res,
33
+ err => {
34
+ if (typeof err.response.data === 'string') {
35
+ throw new Error(`Error in ${err.config?.method} ${err.config?.url}: ${err.response.data}`);
36
+ }
37
+ throw err;
38
+ }
39
+ );
40
+
31
41
  if (false) {} else {
32
42
  exports.Dashboard = {
33
43
  createDashboard: function createDashboard(params) {
@@ -462,6 +472,7 @@ const template = __webpack_require__(/*! ./dashboard.html */ "./frontend/src/das
462
472
 
463
473
  module.exports = app => app.component('dashboard', {
464
474
  template: template,
475
+ props: ['dashboardId'],
465
476
  data: function() {
466
477
  return {
467
478
  status: 'loading',
@@ -476,12 +487,12 @@ module.exports = app => app.component('dashboard', {
476
487
  this.showEditor = !this.showEditor;
477
488
  },
478
489
  async updateCode(update) {
479
- this.code = update;
490
+ this.code = update.doc.code;
491
+ this.result = update.result;
480
492
  }
481
493
  },
482
494
  mounted: async function() {
483
- const dashboardId = this.$route.query.dashboardId;
484
- const { dashboard, result } = await api.Dashboard.getDashboard({ dashboardId: dashboardId, evaluate: true });
495
+ const { dashboard, result } = await api.Dashboard.getDashboard({ dashboardId: this.dashboardId, evaluate: true });
485
496
  if (!dashboard) {
486
497
  return;
487
498
  }
@@ -521,8 +532,11 @@ module.exports = app => app.component('edit-dashboard', {
521
532
  this.$emit('close')
522
533
  },
523
534
  async updateCode() {
524
- const { doc } = await api.Dashboard.updateDashboard({ dashboardId: this.dashboardId, code: this.editor.getValue() });
525
- this.$emit('update', doc.code);
535
+ const { doc, result } = await api.Dashboard.updateDashboard({
536
+ dashboardId: this.dashboardId,
537
+ code: this.editor.getValue()
538
+ });
539
+ this.$emit('update', { doc, result });
526
540
  this.editor.setValue(doc.code);
527
541
  this.closeEditor();
528
542
  }
@@ -1775,7 +1789,7 @@ module.exports = [
1775
1789
  component: 'dashboards'
1776
1790
  },
1777
1791
  {
1778
- path: '/dashboard',
1792
+ path: '/dashboard/:dashboardId',
1779
1793
  name: 'dashboard',
1780
1794
  component: 'dashboard'
1781
1795
  }
@@ -2500,7 +2514,7 @@ module.exports = "<div>\n <div v-if=\"Array.isArray(result)\">\n <div v-for=
2500
2514
  /***/ ((module) => {
2501
2515
 
2502
2516
  "use strict";
2503
- module.exports = "<div class=\"dashboard px-1\">\n <div v-if=\"dashboard\" class=\"max-w-5xl mx-auto\">\n <div class=\"flex items-center w-full\">\n <h2 class=\"mt-4 mb-4 text-gray-900 font-semibold text-xl grow shrink\">{{dashboard.title}}</h2>\n <div>\n <button\n v-if=\"!showEditor\"\n @click=\"showEditor = true\"\n type=\"button\"\n class=\"rounded-md bg-teal-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-teal-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600\">\n <img src=\"images/edit.svg\" class=\"inline h-[1em]\" /> Edit\n </button>\n </div>\n </div>\n <div v-if=\"!showEditor\" class=\"mt-4 mb-4\">\n <dashboard-result :result=\"result\"></dashboard-result>\n </div>\n <div v-if=\"showEditor\">\n <edit-dashboard :dashboardId=\"dashboard._id\" :code=\"code\" @close=\"showEditor=false;\" @update=\"updateCode\"></edit-dashboard>\n </div>\n \n </div>\n <div v-if=\"!dashboard && status === 'loaded'\">\n No dashboard with the given id could be found.\n </div>\n</div>";
2517
+ module.exports = "<div class=\"dashboard px-1\">\n <div v-if=\"dashboard\" class=\"max-w-5xl mx-auto\">\n <div class=\"flex items-center w-full\">\n <h2 class=\"mt-4 mb-4 text-gray-900 font-semibold text-xl grow shrink\">{{dashboard.title}}</h2>\n <div>\n <button\n v-if=\"!showEditor\"\n @click=\"showEditor = true\"\n type=\"button\"\n class=\"rounded-md bg-teal-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-teal-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600\">\n <img src=\"images/edit.svg\" class=\"inline h-[1em]\" /> Edit\n </button>\n </div>\n </div>\n <div v-if=\"!showEditor\" class=\"mt-4 mb-4\">\n <dashboard-result :result=\"result\"></dashboard-result>\n </div>\n <div v-if=\"showEditor\">\n <edit-dashboard\n :dashboardId=\"dashboard._id\"\n :code=\"code\"\n @close=\"showEditor=false;\"\n @update=\"updateCode\"></edit-dashboard>\n </div>\n \n </div>\n <div v-if=\"!dashboard && status === 'loaded'\">\n No dashboard with the given id could be found.\n </div>\n</div>";
2504
2518
 
2505
2519
  /***/ }),
2506
2520
 
@@ -2522,7 +2536,7 @@ module.exports = "<div>\n <textarea ref=\"codeEditor\">{{code}}</textarea>\n
2522
2536
  /***/ ((module) => {
2523
2537
 
2524
2538
  "use strict";
2525
- module.exports = "<div class=\"dashboards max-w-5xl mx-auto mt-8\">\n <div v-if=\"status === 'loaded' && dashboards.length === 0\">\n <div class=\"text-center\">\n <h3 class=\"mt-2 text-sm font-semibold text-gray-900\">No dashboards yet</h3>\n <p class=\"mt-1 text-sm text-gray-500\">Get started by creating a new dashboard.</p>\n <div class=\"mt-6\">\n <button type=\"button\" class=\"inline-flex items-center rounded-md bg-teal-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-teal-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600\">\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z\" />\n </svg>\n New Dashboard\n </button>\n </div>\n </div>\n </div>\n\n\n <div class=\"px-4 sm:px-6 lg:px-8\">\n <div class=\"sm:flex sm:items-center\">\n <div class=\"sm:flex-auto\">\n <h1 class=\"text-base font-semibold leading-6 text-gray-900\">Dashboards</h1>\n </div>\n <div class=\"mt-4 sm:ml-16 sm:mt-0 sm:flex-none\">\n <button\n type=\"button\"\n @click=\"showCreateDashboardModal = true\"\n class=\"block rounded-md bg-teal-600 px-3 py-2 text-center text-sm font-semibold text-white shadow-sm hover:bg-teal-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600\">Create New Dashboard</button>\n </div>\n </div>\n <div class=\"mt-8 flow-root\">\n <div class=\"-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8\">\n <div class=\"inline-block min-w-full py-2 align-middle\">\n <table class=\"min-w-full divide-y divide-gray-300\">\n <thead>\n <tr>\n <th scope=\"col\" class=\"py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6 lg:pl-8\">Title</th>\n <th scope=\"col\" class=\"px-3 py-3.5 text-left text-sm font-semibold text-gray-900 w-[50%]\">Description</th>\n <th scope=\"col\" class=\"relative py-3.5 pl-3 pr-4 sm:pr-6 lg:pr-8\">\n </th>\n <th scope=\"col\" class=\"relative py-3.5 pl-3 pr-4 sm:pr-6 lg:pr-8\">\n </th>\n </tr>\n </thead>\n <tbody class=\"divide-y divide-gray-200 bg-white\">\n <tr v-for=\"dashboard in dashboards\">\n <td class=\"whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-6 lg:pl-8\">{{dashboard.title}}</td>\n <td class=\"whitespace-nowrap px-3 py-4 text-sm text-gray-500 truncate w-[50%]\">{{dashboard.description}}</td>\n <td class=\"relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6 lg:pr-8\">\n <router-link\n :to=\"'dashboard?edit=true&dashboardId=' + dashboard._id\"\n class=\"text-teal-600 hover:text-teal-900\">\n Edit\n </router-link>\n </td>\n <td class=\"relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6 lg:pr-8\">\n <router-link\n :to=\"'dashboard?edit=true&dashboardId=' + dashboard._id\"\n class=\"text-teal-600 hover:text-teal-900\">\n View\n </router-link>\n </td>\n </tr>\n \n <!-- More people... -->\n </tbody>\n </table>\n </div>\n </div>\n </div>\n </div>\n\n <modal v-if=\"showCreateDashboardModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"showCreateDashboardModal = false;\">&times;</div>\n \n <create-dashboard></create-dashboard>\n </template>\n </modal>\n</div>";
2539
+ module.exports = "<div class=\"dashboards max-w-5xl mx-auto mt-8\">\n <div v-if=\"status === 'loaded' && dashboards.length === 0\">\n <div class=\"text-center\">\n <h3 class=\"mt-2 text-sm font-semibold text-gray-900\">No dashboards yet</h3>\n <p class=\"mt-1 text-sm text-gray-500\">Get started by creating a new dashboard.</p>\n <div class=\"mt-6\">\n <button type=\"button\" class=\"inline-flex items-center rounded-md bg-teal-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-teal-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600\">\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z\" />\n </svg>\n New Dashboard\n </button>\n </div>\n </div>\n </div>\n\n\n <div class=\"px-4 sm:px-6 lg:px-8\">\n <div class=\"sm:flex sm:items-center\">\n <div class=\"sm:flex-auto\">\n <h1 class=\"text-base font-semibold leading-6 text-gray-900\">Dashboards</h1>\n </div>\n <div class=\"mt-4 sm:ml-16 sm:mt-0 sm:flex-none\">\n <button\n type=\"button\"\n @click=\"showCreateDashboardModal = true\"\n class=\"block rounded-md bg-teal-600 px-3 py-2 text-center text-sm font-semibold text-white shadow-sm hover:bg-teal-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600\">Create New Dashboard</button>\n </div>\n </div>\n <div class=\"mt-8 flow-root\">\n <div class=\"-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8\">\n <div class=\"inline-block min-w-full py-2 align-middle\">\n <table class=\"min-w-full divide-y divide-gray-300\">\n <thead>\n <tr>\n <th scope=\"col\" class=\"py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6 lg:pl-8\">Title</th>\n <th scope=\"col\" class=\"px-3 py-3.5 text-left text-sm font-semibold text-gray-900 w-[50%]\">Description</th>\n <th scope=\"col\" class=\"relative py-3.5 pl-3 pr-4 sm:pr-6 lg:pr-8\">\n </th>\n <th scope=\"col\" class=\"relative py-3.5 pl-3 pr-4 sm:pr-6 lg:pr-8\">\n </th>\n </tr>\n </thead>\n <tbody class=\"divide-y divide-gray-200 bg-white\">\n <tr v-for=\"dashboard in dashboards\">\n <td class=\"whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-6 lg:pl-8\">{{dashboard.title}}</td>\n <td class=\"whitespace-nowrap px-3 py-4 text-sm text-gray-500 truncate w-[50%]\">{{dashboard.description}}</td>\n <td class=\"relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6 lg:pr-8\">\n <router-link\n :to=\"'/dashboard/' + dashboard._id + '?edit=true'\"\n class=\"text-teal-600 hover:text-teal-900\">\n Edit\n </router-link>\n </td>\n <td class=\"relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6 lg:pr-8\">\n <router-link\n :to=\"'/dashboard/' + dashboard._id\"\n class=\"text-teal-600 hover:text-teal-900\">\n View\n </router-link>\n </td>\n </tr>\n \n <!-- More people... -->\n </tbody>\n </table>\n </div>\n </div>\n </div>\n </div>\n\n <modal v-if=\"showCreateDashboardModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"showCreateDashboardModal = false;\">&times;</div>\n \n <create-dashboard></create-dashboard>\n </template>\n </modal>\n</div>";
2526
2540
 
2527
2541
  /***/ }),
2528
2542
 
@@ -18,6 +18,16 @@ if (typeof config__setAuthorizationHeaderFrom === 'string' && config__setAuthori
18
18
  });
19
19
  }
20
20
 
21
+ client.interceptors.response.use(
22
+ res => res,
23
+ err => {
24
+ if (typeof err.response.data === 'string') {
25
+ throw new Error(`Error in ${err.config?.method} ${err.config?.url}: ${err.response.data}`);
26
+ }
27
+ throw err;
28
+ }
29
+ );
30
+
21
31
  if (config__isLambda) {
22
32
  exports.Dashboard = {
23
33
  createDashboard(params) {
@@ -16,7 +16,11 @@
16
16
  <dashboard-result :result="result"></dashboard-result>
17
17
  </div>
18
18
  <div v-if="showEditor">
19
- <edit-dashboard :dashboardId="dashboard._id" :code="code" @close="showEditor=false;" @update="updateCode"></edit-dashboard>
19
+ <edit-dashboard
20
+ :dashboardId="dashboard._id"
21
+ :code="code"
22
+ @close="showEditor=false;"
23
+ @update="updateCode"></edit-dashboard>
20
24
  </div>
21
25
 
22
26
  </div>
@@ -5,6 +5,7 @@ const template = require('./dashboard.html');
5
5
 
6
6
  module.exports = app => app.component('dashboard', {
7
7
  template: template,
8
+ props: ['dashboardId'],
8
9
  data: function() {
9
10
  return {
10
11
  status: 'loading',
@@ -19,12 +20,12 @@ module.exports = app => app.component('dashboard', {
19
20
  this.showEditor = !this.showEditor;
20
21
  },
21
22
  async updateCode(update) {
22
- this.code = update;
23
+ this.code = update.doc.code;
24
+ this.result = update.result;
23
25
  }
24
26
  },
25
27
  mounted: async function() {
26
- const dashboardId = this.$route.query.dashboardId;
27
- const { dashboard, result } = await api.Dashboard.getDashboard({ dashboardId: dashboardId, evaluate: true });
28
+ const { dashboard, result } = await api.Dashboard.getDashboard({ dashboardId: this.dashboardId, evaluate: true });
28
29
  if (!dashboard) {
29
30
  return;
30
31
  }
@@ -17,8 +17,11 @@ module.exports = app => app.component('edit-dashboard', {
17
17
  this.$emit('close')
18
18
  },
19
19
  async updateCode() {
20
- const { doc } = await api.Dashboard.updateDashboard({ dashboardId: this.dashboardId, code: this.editor.getValue() });
21
- this.$emit('update', doc.code);
20
+ const { doc, result } = await api.Dashboard.updateDashboard({
21
+ dashboardId: this.dashboardId,
22
+ code: this.editor.getValue()
23
+ });
24
+ this.$emit('update', { doc, result });
22
25
  this.editor.setValue(doc.code);
23
26
  this.closeEditor();
24
27
  }
@@ -47,14 +47,14 @@
47
47
  <td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500 truncate w-[50%]">{{dashboard.description}}</td>
48
48
  <td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6 lg:pr-8">
49
49
  <router-link
50
- :to="'dashboard?edit=true&dashboardId=' + dashboard._id"
50
+ :to="'/dashboard/' + dashboard._id + '?edit=true'"
51
51
  class="text-teal-600 hover:text-teal-900">
52
52
  Edit
53
53
  </router-link>
54
54
  </td>
55
55
  <td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6 lg:pr-8">
56
56
  <router-link
57
- :to="'dashboard?edit=true&dashboardId=' + dashboard._id"
57
+ :to="'/dashboard/' + dashboard._id"
58
58
  class="text-teal-600 hover:text-teal-900">
59
59
  View
60
60
  </router-link>
@@ -27,7 +27,7 @@ module.exports = [
27
27
  component: 'dashboards'
28
28
  },
29
29
  {
30
- path: '/dashboard',
30
+ path: '/dashboard/:dashboardId',
31
31
  name: 'dashboard',
32
32
  component: 'dashboard'
33
33
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mongoosejs/studio",
3
- "version": "0.0.32",
3
+ "version": "0.0.34",
4
4
  "dependencies": {
5
5
  "archetype": "0.13.0",
6
6
  "csv-stringify": "6.3.0",