@mongoosejs/studio 0.4.1 → 0.5.1
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.
- package/backend/actions/ChatMessage/executeScript.js +17 -25
- package/backend/actions/Model/exportQueryResults.js +2 -4
- package/backend/actions/getCapabilities.js +42 -0
- package/backend/actions/index.js +1 -1
- package/backend/db/chatMessageSchema.js +2 -1
- package/backend/next.js +5 -1
- package/backend/sandbox/createSandbox.js +83 -0
- package/backend/sandbox/createScriptDb.js +201 -0
- package/frontend/public/app.js +142 -49
- package/frontend/public/tw.css +4 -0
- package/frontend/src/api.js +6 -0
- package/frontend/src/chat/chat-message/chat-message.html +1 -0
- package/frontend/src/chat/chat-message/chat-message.js +4 -3
- package/frontend/src/chat/chat-message-script/chat-message-script.html +98 -16
- package/frontend/src/chat/chat-message-script/chat-message-script.js +77 -17
- package/frontend/src/chat/chat.html +5 -1
- package/frontend/src/chat/chat.js +11 -2
- package/frontend/src/modal/modal.css +0 -1
- package/frontend/src/models/models.js +2 -2
- package/frontend/src/models/projection-search/projection-search.js +2 -2
- package/package.json +2 -2
- package/backend/actions/Script/execute.js +0 -20
- package/backend/actions/Script/index.js +0 -3
package/frontend/src/api.js
CHANGED
|
@@ -29,6 +29,9 @@ client.interceptors.response.use(
|
|
|
29
29
|
);
|
|
30
30
|
|
|
31
31
|
if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
|
|
32
|
+
exports.getCapabilities = function getCapabilities() {
|
|
33
|
+
return client.post('', { action: 'getCapabilities' }).then(res => res.data);
|
|
34
|
+
};
|
|
32
35
|
exports.status = function status() {
|
|
33
36
|
return client.post('', { action: 'status' }).then(res => res.data);
|
|
34
37
|
};
|
|
@@ -205,6 +208,9 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
|
|
|
205
208
|
}
|
|
206
209
|
};
|
|
207
210
|
} else {
|
|
211
|
+
exports.getCapabilities = function getCapabilities() {
|
|
212
|
+
return client.get('/getCapabilities').then(res => res.data);
|
|
213
|
+
};
|
|
208
214
|
exports.status = function status() {
|
|
209
215
|
return client.get('/status').then(res => res.data);
|
|
210
216
|
};
|
|
@@ -6,7 +6,7 @@ const template = require('./chat-message.html');
|
|
|
6
6
|
|
|
7
7
|
module.exports = app => app.component('chat-message', {
|
|
8
8
|
template: template,
|
|
9
|
-
props: ['message', 'targetDashboardId'],
|
|
9
|
+
props: ['message', 'targetDashboardId', 'capabilities'],
|
|
10
10
|
computed: {
|
|
11
11
|
styleForMessage() {
|
|
12
12
|
return this.message.role === 'user' ? 'p-3 bg-muted' : 'py-3 pr-3';
|
|
@@ -62,10 +62,11 @@ module.exports = app => app.component('chat-message', {
|
|
|
62
62
|
if (input.limit && input.limit !== 10) parts.push('limit=' + input.limit);
|
|
63
63
|
return parts.length ? '(' + parts.join(', ') + ')' : '';
|
|
64
64
|
},
|
|
65
|
-
async executeScript(message, script) {
|
|
65
|
+
async executeScript(message, script, dryRun) {
|
|
66
66
|
const { chatMessage } = await api.ChatMessage.executeScript({
|
|
67
67
|
chatMessageId: message._id,
|
|
68
|
-
script
|
|
68
|
+
script,
|
|
69
|
+
dryRun
|
|
69
70
|
});
|
|
70
71
|
message.executionResult = chatMessage.executionResult;
|
|
71
72
|
console.log(message);
|
|
@@ -20,17 +20,19 @@
|
|
|
20
20
|
: 'bg-muted hover:bg-muted text-gray-600'
|
|
21
21
|
]"
|
|
22
22
|
@click="activeTab = 'output'">
|
|
23
|
-
Output
|
|
23
|
+
<span>Output</span>
|
|
24
|
+
<span v-if="isDryRunResult" class="ml-1">[Dry Run]</span>
|
|
25
|
+
<span
|
|
26
|
+
v-if="isDryRunResult"
|
|
27
|
+
class="ml-1 inline-flex align-middle cursor-pointer"
|
|
28
|
+
title="This output was produced in dry run mode"
|
|
29
|
+
@click.stop="openDryRunInfoModal">
|
|
30
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" viewBox="0 0 20 20" fill="currentColor">
|
|
31
|
+
<path fill-rule="evenodd" d="M18 10A8 8 0 112 10a8 8 0 0116 0zm-7-3a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 102 0v-3a1 1 0 00-1-1H9z" clip-rule="evenodd" />
|
|
32
|
+
</svg>
|
|
33
|
+
</span>
|
|
24
34
|
</button>
|
|
25
35
|
<div class="ml-auto mr-1 flex items-center">
|
|
26
|
-
<button
|
|
27
|
-
v-if="activeTab === 'output'"
|
|
28
|
-
class="px-2 py-1 mr-1 text-xs bg-gray-700 text-white border-none rounded cursor-pointer hover:bg-primary-hover transition-colors flex items-center"
|
|
29
|
-
@click="openDetailModal">
|
|
30
|
-
<svg xmlns="http://www.w3.org/2000/svg" style="height: 1.2em;" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
31
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 1v4m0 0h-4m4 0l-5-5" />
|
|
32
|
-
</svg>
|
|
33
|
-
</button>
|
|
34
36
|
<button
|
|
35
37
|
v-if="activeTab === 'code' && !isEditing"
|
|
36
38
|
class="px-2 py-1 mr-1 text-xs bg-gray-700 text-white border-none rounded cursor-pointer hover:bg-gray-600 transition-colors flex items-center"
|
|
@@ -39,12 +41,58 @@
|
|
|
39
41
|
<path d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM4 13.5V16h2.5l7.086-7.086-2.828-2.828L4 13.5z" />
|
|
40
42
|
</svg>
|
|
41
43
|
</button>
|
|
42
|
-
<
|
|
43
|
-
v-if="
|
|
44
|
-
class="px-2 py-1 text-xs bg-
|
|
45
|
-
@click="
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
<button
|
|
45
|
+
v-if="activeTab === 'output'"
|
|
46
|
+
class="px-2 py-1 mr-1 text-xs bg-gray-700 text-white border-none rounded cursor-pointer hover:bg-primary-hover transition-colors flex items-center"
|
|
47
|
+
@click="openDetailModal">
|
|
48
|
+
<svg xmlns="http://www.w3.org/2000/svg" style="height: 1.2em;" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
49
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 1v4m0 0h-4m4 0l-5-5" />
|
|
50
|
+
</svg>
|
|
51
|
+
</button>
|
|
52
|
+
<div v-if="!isEditing" class="relative mr-1" ref="runDropdown">
|
|
53
|
+
<div class="flex items-center">
|
|
54
|
+
<button
|
|
55
|
+
class="px-2 py-1 text-xs bg-primary hover:bg-primary-hover text-primary-text border-none rounded-l-md cursor-pointer transition-colors disabled:bg-gray-400 disabled:cursor-not-allowed"
|
|
56
|
+
:disabled="isExecuting"
|
|
57
|
+
@click="executeScript()">
|
|
58
|
+
{{ selectedRunLabel }}
|
|
59
|
+
</button>
|
|
60
|
+
<button
|
|
61
|
+
class="px-1 py-1 text-xs bg-primary hover:bg-primary-hover text-primary-text border-l border-black/10 rounded-r-md cursor-pointer transition-colors disabled:bg-gray-400 disabled:cursor-not-allowed"
|
|
62
|
+
:disabled="isExecuting"
|
|
63
|
+
@click.stop="toggleRunDropdown">
|
|
64
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" viewBox="0 0 20 20" fill="currentColor">
|
|
65
|
+
<path fill-rule="evenodd" d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z" clip-rule="evenodd" />
|
|
66
|
+
</svg>
|
|
67
|
+
</button>
|
|
68
|
+
<button
|
|
69
|
+
class="ml-1 px-1 py-1 text-content-secondary hover:bg-muted rounded cursor-pointer transition-colors"
|
|
70
|
+
@click="openRunInfoModal"
|
|
71
|
+
title="How run works">
|
|
72
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" viewBox="0 0 20 20" fill="currentColor">
|
|
73
|
+
<path fill-rule="evenodd" d="M18 10A8 8 0 112 10a8 8 0 0116 0zm-7-3a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 102 0v-3a1 1 0 00-1-1H9z" clip-rule="evenodd" />
|
|
74
|
+
</svg>
|
|
75
|
+
</button>
|
|
76
|
+
</div>
|
|
77
|
+
<div
|
|
78
|
+
v-if="showRunDropdown"
|
|
79
|
+
class="absolute right-0 z-10 mt-1 w-40 origin-top-right rounded-md bg-surface py-1 shadow-lg ring-1 ring-black/5">
|
|
80
|
+
<button
|
|
81
|
+
class="block w-full text-left px-4 py-2 text-xs text-content-secondary hover:bg-muted"
|
|
82
|
+
:disabled="isExecuting"
|
|
83
|
+
@click="selectRunMode('run')">
|
|
84
|
+
Run
|
|
85
|
+
</button>
|
|
86
|
+
<button
|
|
87
|
+
class="block w-full text-left px-4 py-2 text-xs"
|
|
88
|
+
:class="isExecuting ? 'cursor-not-allowed text-gray-400' : canUseDryRun ? 'text-content-secondary hover:bg-muted' : 'cursor-not-allowed text-gray-400'"
|
|
89
|
+
:aria-disabled="!canUseDryRun"
|
|
90
|
+
:title="dryRunDisabledTitle"
|
|
91
|
+
@click="selectRunMode('dryRun')">
|
|
92
|
+
Dry Run
|
|
93
|
+
</button>
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
48
96
|
<div class="relative ml-1" ref="dropdown">
|
|
49
97
|
<button
|
|
50
98
|
@click.stop="toggleDropdown"
|
|
@@ -100,7 +148,7 @@
|
|
|
100
148
|
</button>
|
|
101
149
|
<async-button
|
|
102
150
|
class="px-2 py-1 text-xs bg-blue-600 text-white border-none rounded cursor-pointer hover:bg-blue-700 transition-colors disabled:bg-gray-400"
|
|
103
|
-
@click="executeScript">
|
|
151
|
+
@click="executeScript(false)">
|
|
104
152
|
Execute
|
|
105
153
|
</async-button>
|
|
106
154
|
</div>
|
|
@@ -134,6 +182,40 @@
|
|
|
134
182
|
</div>
|
|
135
183
|
</template>
|
|
136
184
|
</modal>
|
|
185
|
+
<modal v-if="showRunInfoModal">
|
|
186
|
+
<template #body>
|
|
187
|
+
<div class="modal-exit" @click="showRunInfoModal = false">×</div>
|
|
188
|
+
<div>
|
|
189
|
+
<div class="mt-4 text-content font-semibold">How Run Works</div>
|
|
190
|
+
<p class="mt-4 text-sm text-content-secondary">
|
|
191
|
+
Run executes the script shown in this message on the server with access to your Mongoose models through <code class="bg-muted px-1 rounded">db.models</code>. The latest script is saved back onto the chat message.
|
|
192
|
+
</p>
|
|
193
|
+
<p class="mt-2 text-sm text-content-secondary">
|
|
194
|
+
Output and console logs are stored on the message, and the Output tab updates to show the latest result.
|
|
195
|
+
</p>
|
|
196
|
+
<p class="mt-2 text-sm text-content-secondary">
|
|
197
|
+
Dry Run executes the same script inside a MongoDB transaction. Studio attaches the transaction session to Mongoose model and collection calls, captures the output and logs, then aborts the transaction so writes are rolled back.
|
|
198
|
+
</p>
|
|
199
|
+
<p class="mt-2 text-sm text-content-secondary">
|
|
200
|
+
Dry Run requires MongoDB transaction support. It is intended for previewing what a script would return before persisting changes.
|
|
201
|
+
</p>
|
|
202
|
+
</div>
|
|
203
|
+
</template>
|
|
204
|
+
</modal>
|
|
205
|
+
<modal v-if="showDryRunInfoModal">
|
|
206
|
+
<template #body>
|
|
207
|
+
<div class="modal-exit" @click="showDryRunInfoModal = false">×</div>
|
|
208
|
+
<div>
|
|
209
|
+
<div class="mt-4 text-content font-semibold">Dry Run Output</div>
|
|
210
|
+
<p class="mt-4 text-sm text-content-secondary">
|
|
211
|
+
This output was produced in dry run mode. The script ran on the server inside a MongoDB transaction, and Studio aborted that transaction after the script finished.
|
|
212
|
+
</p>
|
|
213
|
+
<p class="mt-2 text-sm text-content-secondary">
|
|
214
|
+
No data changes from the script were persisted. The displayed output and console logs were saved on the chat message so you can review what the script returned.
|
|
215
|
+
</p>
|
|
216
|
+
</div>
|
|
217
|
+
</template>
|
|
218
|
+
</modal>
|
|
137
219
|
<modal v-if="showCreateDashboardModal">
|
|
138
220
|
<template #body>
|
|
139
221
|
<div class="modal-exit" @click="showCreateDashboardModal = false">×</div>
|
|
@@ -6,15 +6,20 @@ const template = require('./chat-message-script.html');
|
|
|
6
6
|
|
|
7
7
|
module.exports = app => app.component('chat-message-script', {
|
|
8
8
|
template,
|
|
9
|
-
props: ['message', 'script', 'language', 'targetDashboardId'],
|
|
9
|
+
props: ['message', 'script', 'language', 'targetDashboardId', 'capabilities'],
|
|
10
10
|
emits: ['copyMessage'],
|
|
11
11
|
data() {
|
|
12
12
|
return {
|
|
13
13
|
activeTab: 'code',
|
|
14
|
+
selectedRunMode: 'run',
|
|
14
15
|
showDetailModal: false,
|
|
16
|
+
showRunInfoModal: false,
|
|
17
|
+
showDryRunInfoModal: false,
|
|
15
18
|
showCreateDashboardModal: false,
|
|
16
19
|
showOverwriteDashboardConfirmationModal: false,
|
|
20
|
+
showRunDropdown: false,
|
|
17
21
|
showDropdown: false,
|
|
22
|
+
isExecuting: false,
|
|
18
23
|
newDashboardTitle: '',
|
|
19
24
|
dashboardCode: '',
|
|
20
25
|
createError: null,
|
|
@@ -30,32 +35,60 @@ module.exports = app => app.component('chat-message-script', {
|
|
|
30
35
|
},
|
|
31
36
|
canOverwriteDashboard() {
|
|
32
37
|
return !!this.targetDashboardId;
|
|
38
|
+
},
|
|
39
|
+
canUseDryRun() {
|
|
40
|
+
return this.capabilities?.supportsTransactions !== false;
|
|
41
|
+
},
|
|
42
|
+
dryRunDisabledTitle() {
|
|
43
|
+
return this.canUseDryRun ? null : 'dry run mode requires MongoDB transactions support';
|
|
44
|
+
},
|
|
45
|
+
isDryRunResult() {
|
|
46
|
+
return !!this.message.executionResult?.dryRun;
|
|
47
|
+
},
|
|
48
|
+
selectedRunLabel() {
|
|
49
|
+
return this.selectedRunMode === 'dryRun' ? 'Dry Run' : 'Run';
|
|
33
50
|
}
|
|
34
51
|
},
|
|
35
52
|
methods: {
|
|
36
|
-
async executeScript() {
|
|
53
|
+
async executeScript(dryRun = this.selectedRunMode === 'dryRun') {
|
|
37
54
|
const scriptToRun = this.isEditing ? this.editedScript : this.script;
|
|
55
|
+
if (this.isExecuting) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
this.showRunDropdown = false;
|
|
38
59
|
this.editedScript = scriptToRun;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
this.
|
|
49
|
-
|
|
50
|
-
this.
|
|
60
|
+
this.isExecuting = true;
|
|
61
|
+
try {
|
|
62
|
+
const { chatMessage } = await api.ChatMessage.executeScript({
|
|
63
|
+
chatMessageId: this.message._id,
|
|
64
|
+
script: scriptToRun,
|
|
65
|
+
dryRun
|
|
66
|
+
});
|
|
67
|
+
this.message.executionResult = chatMessage.executionResult;
|
|
68
|
+
this.message.script = chatMessage.script;
|
|
69
|
+
this.message.content = chatMessage.content;
|
|
70
|
+
this.editedScript = chatMessage.script;
|
|
71
|
+
if (this.isEditing) {
|
|
72
|
+
this.finishEditing();
|
|
73
|
+
} else {
|
|
74
|
+
this.highlightCode();
|
|
75
|
+
}
|
|
76
|
+
this.activeTab = 'output';
|
|
77
|
+
this.$toast.success('Script executed successfully!');
|
|
78
|
+
return chatMessage;
|
|
79
|
+
} finally {
|
|
80
|
+
this.isExecuting = false;
|
|
51
81
|
}
|
|
52
|
-
this.activeTab = 'output';
|
|
53
|
-
this.$toast.success('Script executed successfully!');
|
|
54
|
-
return chatMessage;
|
|
55
82
|
},
|
|
56
83
|
openDetailModal() {
|
|
57
84
|
this.showDetailModal = true;
|
|
58
85
|
},
|
|
86
|
+
openRunInfoModal() {
|
|
87
|
+
this.showRunInfoModal = true;
|
|
88
|
+
},
|
|
89
|
+
openDryRunInfoModal() {
|
|
90
|
+
this.showDryRunInfoModal = true;
|
|
91
|
+
},
|
|
59
92
|
openCreateDashboardModal() {
|
|
60
93
|
this.newDashboardTitle = '';
|
|
61
94
|
this.dashboardCode = this.script;
|
|
@@ -72,6 +105,21 @@ module.exports = app => app.component('chat-message-script', {
|
|
|
72
105
|
},
|
|
73
106
|
toggleDropdown() {
|
|
74
107
|
this.showDropdown = !this.showDropdown;
|
|
108
|
+
this.showRunDropdown = false;
|
|
109
|
+
},
|
|
110
|
+
toggleRunDropdown() {
|
|
111
|
+
this.showRunDropdown = !this.showRunDropdown;
|
|
112
|
+
this.showDropdown = false;
|
|
113
|
+
},
|
|
114
|
+
selectRunMode(mode) {
|
|
115
|
+
if (this.isExecuting) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (mode === 'dryRun' && !this.canUseDryRun) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
this.selectedRunMode = mode;
|
|
122
|
+
this.showRunDropdown = false;
|
|
75
123
|
},
|
|
76
124
|
startEditing() {
|
|
77
125
|
this.isEditing = true;
|
|
@@ -97,7 +145,11 @@ module.exports = app => app.component('chat-message-script', {
|
|
|
97
145
|
});
|
|
98
146
|
},
|
|
99
147
|
handleBodyClick(event) {
|
|
148
|
+
const runDropdown = this.$refs.runDropdown;
|
|
100
149
|
const dropdown = this.$refs.dropdown;
|
|
150
|
+
if (runDropdown && typeof runDropdown.contains === 'function' && !runDropdown.contains(event.target)) {
|
|
151
|
+
this.showRunDropdown = false;
|
|
152
|
+
}
|
|
101
153
|
if (dropdown && typeof dropdown.contains === 'function' && !dropdown.contains(event.target)) {
|
|
102
154
|
this.showDropdown = false;
|
|
103
155
|
}
|
|
@@ -172,6 +224,14 @@ module.exports = app => app.component('chat-message-script', {
|
|
|
172
224
|
this.editedScript = newScript;
|
|
173
225
|
this.highlightCode();
|
|
174
226
|
}
|
|
227
|
+
},
|
|
228
|
+
capabilities: {
|
|
229
|
+
immediate: true,
|
|
230
|
+
handler(capabilities) {
|
|
231
|
+
if (capabilities?.supportsTransactions === false && this.selectedRunMode === 'dryRun') {
|
|
232
|
+
this.selectedRunMode = 'run';
|
|
233
|
+
}
|
|
234
|
+
}
|
|
175
235
|
}
|
|
176
236
|
},
|
|
177
237
|
mounted() {
|
|
@@ -112,7 +112,11 @@
|
|
|
112
112
|
</div>
|
|
113
113
|
<ul role="list" class="space-y-4" v-else>
|
|
114
114
|
<li v-for="message in chatMessages" :key="message._id">
|
|
115
|
-
<chat-message
|
|
115
|
+
<chat-message
|
|
116
|
+
:message="message"
|
|
117
|
+
:target-dashboard-id="currentThread?.dashboardId"
|
|
118
|
+
:capabilities="capabilities">
|
|
119
|
+
</chat-message>
|
|
116
120
|
</li>
|
|
117
121
|
</ul>
|
|
118
122
|
</div>
|
|
@@ -23,7 +23,12 @@ module.exports = {
|
|
|
23
23
|
sharingThread: false,
|
|
24
24
|
threadSearch: '',
|
|
25
25
|
showProUpgradeModal: false,
|
|
26
|
-
agentTools: agentToolMetadata
|
|
26
|
+
agentTools: agentToolMetadata,
|
|
27
|
+
capabilities: {
|
|
28
|
+
supportsChangeStreams: false,
|
|
29
|
+
supportsTransactions: true,
|
|
30
|
+
supportsAI: false
|
|
31
|
+
}
|
|
27
32
|
}),
|
|
28
33
|
methods: {
|
|
29
34
|
async sendMessage() {
|
|
@@ -300,8 +305,12 @@ module.exports = {
|
|
|
300
305
|
|
|
301
306
|
this.draftAgentMode = this.getAgentModePreference();
|
|
302
307
|
this.chatThreadId = this.threadId;
|
|
303
|
-
const { chatThreads } = await
|
|
308
|
+
const [{ chatThreads }, { capabilities }] = await Promise.all([
|
|
309
|
+
api.ChatThread.listChatThreads(),
|
|
310
|
+
api.getCapabilities()
|
|
311
|
+
]);
|
|
304
312
|
this.chatThreads = chatThreads;
|
|
313
|
+
this.capabilities = capabilities;
|
|
305
314
|
if (this.chatThreadId) {
|
|
306
315
|
await this.syncCurrentThreadAgentMode();
|
|
307
316
|
const { chatMessages } = await api.ChatThread.getChatThread({ chatThreadId: this.chatThreadId });
|
|
@@ -1058,8 +1058,8 @@ module.exports = app => app.component('models', {
|
|
|
1058
1058
|
const projectionPaths = this.normalizeProjectionPathsForDisplay(routeProjectionInput);
|
|
1059
1059
|
const fromProjectionInput = Array.isArray(projectionPaths) ?
|
|
1060
1060
|
projectionPaths
|
|
1061
|
-
|
|
1062
|
-
|
|
1061
|
+
.map(path => this.schemaPaths.find(p => p.path === path))
|
|
1062
|
+
.filter(Boolean) :
|
|
1063
1063
|
[];
|
|
1064
1064
|
this.filteredPaths = fromProjectionInput;
|
|
1065
1065
|
} else {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mongoosejs/studio",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.5.1",
|
|
4
|
+
"description": "AI-Powered Data Workspace for MongoDB: Turn your MongoDB data into dashboards, maps, and interactive workflows - powered by your Mongoose models and AI.",
|
|
5
5
|
"homepage": "https://mongoosestudio.app/",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const Archetype = require('archetype');
|
|
4
|
-
|
|
5
|
-
const ExecuteParams = new Archetype({
|
|
6
|
-
code: {
|
|
7
|
-
$type: 'string',
|
|
8
|
-
$required: true
|
|
9
|
-
}
|
|
10
|
-
}).compile('ExecuteParams');
|
|
11
|
-
|
|
12
|
-
module.exports = ({ db }) => async function execute(params) {
|
|
13
|
-
const { code } = new ExecuteParams(params);
|
|
14
|
-
|
|
15
|
-
const res = eval(code);
|
|
16
|
-
|
|
17
|
-
return {
|
|
18
|
-
res
|
|
19
|
-
};
|
|
20
|
-
};
|