@mongoosejs/studio 0.5.14 → 0.6.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.
- package/AGENTS.md +69 -2
- package/README.md +24 -0
- package/backend/actions/ChatMessage/executeScript.js +14 -6
- package/backend/actions/ChatThread/createChatMessage.js +7 -4
- package/backend/actions/ChatThread/getChatThread.js +7 -4
- package/backend/actions/ChatThread/listChatThreads.js +5 -2
- package/backend/actions/ChatThread/shareChatThread.js +5 -2
- package/backend/actions/ChatThread/streamChatMessage.js +7 -4
- package/backend/actions/ChatThread/toggleAgentMode.js +5 -2
- package/backend/actions/Dashboard/createDashboard.js +3 -0
- package/backend/actions/Dashboard/deleteDashboard.js +9 -3
- package/backend/actions/Dashboard/getDashboard.js +23 -11
- package/backend/actions/Dashboard/getDashboards.js +8 -2
- package/backend/actions/Dashboard/updateDashboard.js +8 -2
- package/backend/actions/Model/addField.js +8 -2
- package/backend/actions/Model/analyzeSchema.js +15 -5
- package/backend/actions/Model/createChatMessage.js +3 -0
- package/backend/actions/Model/createDocument.js +3 -0
- package/backend/actions/Model/deleteDocument.js +8 -2
- package/backend/actions/Model/deleteDocuments.js +8 -2
- package/backend/actions/Model/dropCollection.js +3 -0
- package/backend/actions/Model/dropIndex.js +3 -0
- package/backend/actions/Model/executeDocumentScript.js +14 -3
- package/backend/actions/Model/exportQueryResults.js +12 -2
- package/backend/actions/Model/getCollectionInfo.js +14 -4
- package/backend/actions/Model/getDocument.js +12 -2
- package/backend/actions/Model/getDocuments.js +13 -3
- package/backend/actions/Model/getDocumentsStream.js +13 -3
- package/backend/actions/Model/getEstimatedDocumentCounts.js +12 -2
- package/backend/actions/Model/getIndexes.js +3 -0
- package/backend/actions/Model/getSuggestedProjection.js +3 -0
- package/backend/actions/Model/listModels.js +3 -0
- package/backend/actions/Model/streamChatMessage.js +3 -0
- package/backend/actions/Model/streamDocumentChanges.js +3 -0
- package/backend/actions/Model/updateDocument.js +8 -2
- package/backend/actions/Model/updateDocuments.js +8 -2
- package/backend/actions/Model/validateDocument.js +12 -2
- package/backend/actions/Script/createScript.js +36 -0
- package/backend/actions/Script/executeScript.js +89 -0
- package/backend/actions/Script/getScript.js +43 -0
- package/backend/actions/Script/index.js +5 -0
- package/backend/actions/Task/cancelTask.js +5 -2
- package/backend/actions/Task/getTaskOverview.js +6 -3
- package/backend/actions/Task/getTasks.js +6 -3
- package/backend/actions/Task/getTasksOverTime.js +6 -3
- package/backend/actions/Task/rescheduleTask.js +5 -2
- package/backend/actions/Task/runTask.js +5 -2
- package/backend/actions/index.js +1 -0
- package/backend/authorize.js +6 -1
- package/backend/db/scriptSchema.js +29 -0
- package/backend/helpers/operationOptions.js +26 -0
- package/backend/helpers/readOperationOptions.js +31 -0
- package/backend/index.js +2 -0
- package/backend/integrations/mothership.js +28 -0
- package/backend/mcp.js +140 -0
- package/backend/netlify.js +5 -3
- package/backend/next.js +5 -3
- package/backend/sandbox/createSandbox.js +2 -2
- package/backend/sandbox/createScriptDb.js +40 -23
- package/backend/util/archetypeToZodSchema.js +74 -0
- package/docs/mcp-oauth.md +106 -0
- package/eslint.config.js +1 -0
- package/eval/agent/run.js +1 -1
- package/express.js +183 -41
- package/frontend/index.js +3 -0
- package/frontend/public/app.js +441 -48
- package/frontend/public/tw.css +8 -0
- package/frontend/src/api.js +22 -0
- package/frontend/src/index.js +9 -1
- package/frontend/src/mcp/mcp.html +55 -0
- package/frontend/src/mcp/mcp.js +27 -0
- package/frontend/src/navbar/navbar.html +8 -0
- package/frontend/src/navbar/navbar.js +3 -0
- package/frontend/src/routes.js +16 -0
- package/frontend/src/script/script.html +105 -0
- package/frontend/src/script/script.js +98 -0
- package/index.d.ts +10 -1
- package/nest.d.ts +3 -0
- package/package.json +5 -3
- package/vercel.d.ts +2 -0
- package/CLAUDE.md +0 -7
package/frontend/public/app.js
CHANGED
|
@@ -1204,6 +1204,17 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
|
|
|
1204
1204
|
return client.post('', { action: 'ChatMessage.executeScript', ...params }).then(res => res.data);
|
|
1205
1205
|
}
|
|
1206
1206
|
};
|
|
1207
|
+
exports.Script = {
|
|
1208
|
+
createScript(params) {
|
|
1209
|
+
return client.post('', { action: 'Script.createScript', ...params }).then(res => res.data);
|
|
1210
|
+
},
|
|
1211
|
+
executeScript(params) {
|
|
1212
|
+
return client.post('', { action: 'Script.executeScript', ...params }).then(res => res.data);
|
|
1213
|
+
},
|
|
1214
|
+
getScript(params) {
|
|
1215
|
+
return client.post('', { action: 'Script.getScript', ...params }).then(res => res.data);
|
|
1216
|
+
}
|
|
1217
|
+
};
|
|
1207
1218
|
exports.Model = {
|
|
1208
1219
|
addField(params) {
|
|
1209
1220
|
return client.post('', { action: 'Model.addField', ...params }).then(res => res.data);
|
|
@@ -1403,6 +1414,17 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
|
|
|
1403
1414
|
return client.post('/ChatMessage/executeScript', params).then(res => res.data);
|
|
1404
1415
|
}
|
|
1405
1416
|
};
|
|
1417
|
+
exports.Script = {
|
|
1418
|
+
createScript: function createScript(params) {
|
|
1419
|
+
return client.post('/Script/createScript', params).then(res => res.data);
|
|
1420
|
+
},
|
|
1421
|
+
executeScript: function executeScript(params) {
|
|
1422
|
+
return client.post('/Script/executeScript', params).then(res => res.data);
|
|
1423
|
+
},
|
|
1424
|
+
getScript: function getScript(params) {
|
|
1425
|
+
return client.post('/Script/getScript', params).then(res => res.data);
|
|
1426
|
+
}
|
|
1427
|
+
};
|
|
1406
1428
|
exports.Model = {
|
|
1407
1429
|
addField(params) {
|
|
1408
1430
|
return client.post('/Model/addField', params).then(res => res.data);
|
|
@@ -7851,7 +7873,7 @@ const {
|
|
|
7851
7873
|
} = __webpack_require__(/*! ./_util/recent-pages-history */ "./frontend/src/_util/recent-pages-history.js");
|
|
7852
7874
|
appendCSS(__webpack_require__(/*! vue-toastification/dist/index.css */ "./node_modules/vue-toastification/dist/index.css"));
|
|
7853
7875
|
|
|
7854
|
-
const TRACKED_RECENT_PAGE_ROUTE_NAMES = new Set(['model', 'document', 'dashboard', 'chat']);
|
|
7876
|
+
const TRACKED_RECENT_PAGE_ROUTE_NAMES = new Set(['model', 'document', 'dashboard', 'chat', 'script']);
|
|
7855
7877
|
const CHAT_ROUTE_NAMES = new Set(['chat index', 'chat']);
|
|
7856
7878
|
|
|
7857
7879
|
function formatHistoryLabel(route) {
|
|
@@ -7873,6 +7895,9 @@ function formatHistoryLabel(route) {
|
|
|
7873
7895
|
if (route.name === 'chat') {
|
|
7874
7896
|
return route.params?.threadId ? `Chat: ${route.params.threadId}` : 'Chat';
|
|
7875
7897
|
}
|
|
7898
|
+
if (route.name === 'script') {
|
|
7899
|
+
return route.params?.scriptId ? `Script: ${route.params.scriptId}` : 'Script';
|
|
7900
|
+
}
|
|
7876
7901
|
const normalizedPath = route.path.replace(/^\//, '');
|
|
7877
7902
|
return normalizedPath || 'Home';
|
|
7878
7903
|
}
|
|
@@ -8160,6 +8185,11 @@ const router = VueRouter.createRouter({
|
|
|
8160
8185
|
|
|
8161
8186
|
// Add global navigation guard
|
|
8162
8187
|
router.beforeEach((to, from, next) => {
|
|
8188
|
+
if (to.name === 'mcp' && window.MONGOOSE_STUDIO_CONFIG.mcp === false) {
|
|
8189
|
+
next({ name: window.state?.roles?.[0] === 'dashboards' ? 'dashboards' : 'root' });
|
|
8190
|
+
return;
|
|
8191
|
+
}
|
|
8192
|
+
|
|
8163
8193
|
// Skip auth check for authorized (public) routes
|
|
8164
8194
|
if (to.meta.authorized) {
|
|
8165
8195
|
next();
|
|
@@ -8888,6 +8918,44 @@ module.exports = app => app.component('list-subdocument', {
|
|
|
8888
8918
|
});
|
|
8889
8919
|
|
|
8890
8920
|
|
|
8921
|
+
/***/ },
|
|
8922
|
+
|
|
8923
|
+
/***/ "./frontend/src/mcp/mcp.js"
|
|
8924
|
+
/*!*********************************!*\
|
|
8925
|
+
!*** ./frontend/src/mcp/mcp.js ***!
|
|
8926
|
+
\*********************************/
|
|
8927
|
+
(module, __unused_webpack_exports, __webpack_require__) {
|
|
8928
|
+
|
|
8929
|
+
"use strict";
|
|
8930
|
+
|
|
8931
|
+
|
|
8932
|
+
const template = __webpack_require__(/*! ./mcp.html */ "./frontend/src/mcp/mcp.html");
|
|
8933
|
+
|
|
8934
|
+
module.exports = {
|
|
8935
|
+
template,
|
|
8936
|
+
computed: {
|
|
8937
|
+
mcpUrl() {
|
|
8938
|
+
const configuredUrl = window.MONGOOSE_STUDIO_CONFIG.mcpUrl;
|
|
8939
|
+
if (configuredUrl) {
|
|
8940
|
+
return configuredUrl;
|
|
8941
|
+
}
|
|
8942
|
+
|
|
8943
|
+
const url = new URL(window.location.href);
|
|
8944
|
+
url.hash = '';
|
|
8945
|
+
url.search = '';
|
|
8946
|
+
url.pathname = `${url.pathname.replace(/\/+$/, '')}/mcp`;
|
|
8947
|
+
return url.toString();
|
|
8948
|
+
}
|
|
8949
|
+
},
|
|
8950
|
+
methods: {
|
|
8951
|
+
async copyMCPUrl() {
|
|
8952
|
+
await navigator.clipboard.writeText(this.mcpUrl);
|
|
8953
|
+
this.$toast.success('MCP URL copied!');
|
|
8954
|
+
}
|
|
8955
|
+
}
|
|
8956
|
+
};
|
|
8957
|
+
|
|
8958
|
+
|
|
8891
8959
|
/***/ },
|
|
8892
8960
|
|
|
8893
8961
|
/***/ "./frontend/src/modal/modal.js"
|
|
@@ -11739,6 +11807,9 @@ module.exports = app => app.component('navbar', {
|
|
|
11739
11807
|
hasTaskVisualizer() {
|
|
11740
11808
|
return !!window.MONGOOSE_STUDIO_CONFIG.enableTaskVisualizer;
|
|
11741
11809
|
},
|
|
11810
|
+
mcpEnabled() {
|
|
11811
|
+
return window.MONGOOSE_STUDIO_CONFIG.mcp !== false;
|
|
11812
|
+
},
|
|
11742
11813
|
recentPagesList() {
|
|
11743
11814
|
return this.localRecentPages;
|
|
11744
11815
|
},
|
|
@@ -11938,6 +12009,14 @@ module.exports = {
|
|
|
11938
12009
|
authorized: false
|
|
11939
12010
|
}
|
|
11940
12011
|
},
|
|
12012
|
+
{
|
|
12013
|
+
path: '/mcp',
|
|
12014
|
+
name: 'mcp',
|
|
12015
|
+
component: 'mcp',
|
|
12016
|
+
meta: {
|
|
12017
|
+
authorized: true
|
|
12018
|
+
}
|
|
12019
|
+
},
|
|
11941
12020
|
{
|
|
11942
12021
|
path: '/tasks',
|
|
11943
12022
|
name: 'tasks',
|
|
@@ -11977,6 +12056,14 @@ module.exports = {
|
|
|
11977
12056
|
meta: {
|
|
11978
12057
|
authorized: true
|
|
11979
12058
|
}
|
|
12059
|
+
},
|
|
12060
|
+
{
|
|
12061
|
+
path: '/script/:scriptId',
|
|
12062
|
+
name: 'script',
|
|
12063
|
+
component: 'script',
|
|
12064
|
+
meta: {
|
|
12065
|
+
authorized: true
|
|
12066
|
+
}
|
|
11980
12067
|
}
|
|
11981
12068
|
],
|
|
11982
12069
|
roleAccess,
|
|
@@ -11984,6 +12071,115 @@ module.exports = {
|
|
|
11984
12071
|
};
|
|
11985
12072
|
|
|
11986
12073
|
|
|
12074
|
+
/***/ },
|
|
12075
|
+
|
|
12076
|
+
/***/ "./frontend/src/script/script.js"
|
|
12077
|
+
/*!***************************************!*\
|
|
12078
|
+
!*** ./frontend/src/script/script.js ***!
|
|
12079
|
+
\***************************************/
|
|
12080
|
+
(module, __unused_webpack_exports, __webpack_require__) {
|
|
12081
|
+
|
|
12082
|
+
"use strict";
|
|
12083
|
+
/* global Prism */
|
|
12084
|
+
|
|
12085
|
+
|
|
12086
|
+
const api = __webpack_require__(/*! ../api */ "./frontend/src/api.js");
|
|
12087
|
+
const baseComponent = __webpack_require__(/*! ../_util/baseComponent */ "./frontend/src/_util/baseComponent.js");
|
|
12088
|
+
const template = __webpack_require__(/*! ./script.html */ "./frontend/src/script/script.html");
|
|
12089
|
+
|
|
12090
|
+
module.exports = {
|
|
12091
|
+
template,
|
|
12092
|
+
extends: baseComponent,
|
|
12093
|
+
props: ['scriptId'],
|
|
12094
|
+
inject: ['state'],
|
|
12095
|
+
data() {
|
|
12096
|
+
return {
|
|
12097
|
+
status: 'loading',
|
|
12098
|
+
script: null,
|
|
12099
|
+
editedScript: '',
|
|
12100
|
+
isEditing: false,
|
|
12101
|
+
activeTab: 'code',
|
|
12102
|
+
selectedRunMode: 'run',
|
|
12103
|
+
showRunDropdown: false
|
|
12104
|
+
};
|
|
12105
|
+
},
|
|
12106
|
+
computed: {
|
|
12107
|
+
canUseDryRun() {
|
|
12108
|
+
return this.state.capabilities?.supportsTransactions !== false;
|
|
12109
|
+
},
|
|
12110
|
+
selectedRunLabel() {
|
|
12111
|
+
return this.selectedRunMode === 'dryRun' ? 'Dry Run' : 'Run';
|
|
12112
|
+
},
|
|
12113
|
+
isDryRunResult() {
|
|
12114
|
+
return this.script?.executionFinishedAt != null && this.script?.dryRun === true;
|
|
12115
|
+
}
|
|
12116
|
+
},
|
|
12117
|
+
methods: {
|
|
12118
|
+
async loadScript() {
|
|
12119
|
+
this.status = 'loading';
|
|
12120
|
+
try {
|
|
12121
|
+
const { script } = await api.Script.getScript({ scriptId: this.scriptId });
|
|
12122
|
+
this.script = script;
|
|
12123
|
+
this.editedScript = script.script;
|
|
12124
|
+
this.activeTab = script.executionResult == null ? 'code' : 'output';
|
|
12125
|
+
} finally {
|
|
12126
|
+
this.status = 'loaded';
|
|
12127
|
+
this.highlightCode();
|
|
12128
|
+
}
|
|
12129
|
+
},
|
|
12130
|
+
startEditing() {
|
|
12131
|
+
this.editedScript = this.script.script;
|
|
12132
|
+
this.isEditing = true;
|
|
12133
|
+
this.activeTab = 'code';
|
|
12134
|
+
},
|
|
12135
|
+
cancelEditing() {
|
|
12136
|
+
this.editedScript = this.script.script;
|
|
12137
|
+
this.isEditing = false;
|
|
12138
|
+
this.highlightCode();
|
|
12139
|
+
},
|
|
12140
|
+
selectRunMode(mode) {
|
|
12141
|
+
if (mode === 'dryRun' && !this.canUseDryRun) {
|
|
12142
|
+
return;
|
|
12143
|
+
}
|
|
12144
|
+
this.selectedRunMode = mode;
|
|
12145
|
+
this.showRunDropdown = false;
|
|
12146
|
+
},
|
|
12147
|
+
async executeScript() {
|
|
12148
|
+
this.showRunDropdown = false;
|
|
12149
|
+
try {
|
|
12150
|
+
const { script } = await api.Script.executeScript({
|
|
12151
|
+
scriptId: this.scriptId,
|
|
12152
|
+
script: this.isEditing ? this.editedScript : this.script.script,
|
|
12153
|
+
dryRun: this.selectedRunMode === 'dryRun'
|
|
12154
|
+
});
|
|
12155
|
+
this.script = script;
|
|
12156
|
+
this.editedScript = script.script;
|
|
12157
|
+
this.isEditing = false;
|
|
12158
|
+
this.activeTab = 'output';
|
|
12159
|
+
this.$toast.success(this.script.dryRun ? 'Dry run completed!' : 'Script executed successfully!');
|
|
12160
|
+
} catch (err) {
|
|
12161
|
+
const { script } = await api.Script.getScript({ scriptId: this.scriptId });
|
|
12162
|
+
this.script = script;
|
|
12163
|
+
this.editedScript = script.script;
|
|
12164
|
+
this.isEditing = false;
|
|
12165
|
+
this.activeTab = 'output';
|
|
12166
|
+
throw err;
|
|
12167
|
+
}
|
|
12168
|
+
},
|
|
12169
|
+
highlightCode() {
|
|
12170
|
+
this.$nextTick(() => {
|
|
12171
|
+
if (this.$refs.code) {
|
|
12172
|
+
Prism.highlightElement(this.$refs.code);
|
|
12173
|
+
}
|
|
12174
|
+
});
|
|
12175
|
+
}
|
|
12176
|
+
},
|
|
12177
|
+
mounted() {
|
|
12178
|
+
return this.loadScript();
|
|
12179
|
+
}
|
|
12180
|
+
};
|
|
12181
|
+
|
|
12182
|
+
|
|
11987
12183
|
/***/ },
|
|
11988
12184
|
|
|
11989
12185
|
/***/ "./frontend/src/splash/splash.js"
|
|
@@ -13573,6 +13769,9 @@ const map = {
|
|
|
13573
13769
|
"./list-subdocument/list-subdocument.css": "./frontend/src/list-subdocument/list-subdocument.css",
|
|
13574
13770
|
"./list-subdocument/list-subdocument.html": "./frontend/src/list-subdocument/list-subdocument.html",
|
|
13575
13771
|
"./list-subdocument/list-subdocument.js": "./frontend/src/list-subdocument/list-subdocument.js",
|
|
13772
|
+
"./mcp/mcp": "./frontend/src/mcp/mcp.js",
|
|
13773
|
+
"./mcp/mcp.html": "./frontend/src/mcp/mcp.html",
|
|
13774
|
+
"./mcp/mcp.js": "./frontend/src/mcp/mcp.js",
|
|
13576
13775
|
"./modal/modal": "./frontend/src/modal/modal.js",
|
|
13577
13776
|
"./modal/modal.css": "./frontend/src/modal/modal.css",
|
|
13578
13777
|
"./modal/modal.html": "./frontend/src/modal/modal.html",
|
|
@@ -13606,6 +13805,9 @@ const map = {
|
|
|
13606
13805
|
"./pro-upgrade-modal/pro-upgrade-modal.js": "./frontend/src/pro-upgrade-modal/pro-upgrade-modal.js",
|
|
13607
13806
|
"./routes": "./frontend/src/routes.js",
|
|
13608
13807
|
"./routes.js": "./frontend/src/routes.js",
|
|
13808
|
+
"./script/script": "./frontend/src/script/script.js",
|
|
13809
|
+
"./script/script.html": "./frontend/src/script/script.html",
|
|
13810
|
+
"./script/script.js": "./frontend/src/script/script.js",
|
|
13609
13811
|
"./splash/splash": "./frontend/src/splash/splash.js",
|
|
13610
13812
|
"./splash/splash.html": "./frontend/src/splash/splash.html",
|
|
13611
13813
|
"./splash/splash.js": "./frontend/src/splash/splash.js",
|
|
@@ -13721,7 +13923,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
13721
13923
|
/* harmony export */ });
|
|
13722
13924
|
/* harmony import */ var _vue_shared__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @vue/shared */ "./node_modules/@vue/shared/dist/shared.esm-bundler.js");
|
|
13723
13925
|
/**
|
|
13724
|
-
* @vue/reactivity v3.5.
|
|
13926
|
+
* @vue/reactivity v3.5.43
|
|
13725
13927
|
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
|
13726
13928
|
* @license MIT
|
|
13727
13929
|
**/
|
|
@@ -14496,7 +14698,9 @@ function reactiveReadArray(array) {
|
|
|
14496
14698
|
const raw = toRaw(array);
|
|
14497
14699
|
if (raw === array) return raw;
|
|
14498
14700
|
track(raw, "iterate", ARRAY_ITERATE_KEY);
|
|
14499
|
-
|
|
14701
|
+
if (isShallow(array)) return raw;
|
|
14702
|
+
if (!isReadonly(array)) return raw.map(toReactive);
|
|
14703
|
+
return isReactive(array) ? raw.map((item) => toReadonly(toReactive(item))) : raw.map(toReadonly);
|
|
14500
14704
|
}
|
|
14501
14705
|
function shallowReadArray(arr) {
|
|
14502
14706
|
track(arr = toRaw(arr), "iterate", ARRAY_ITERATE_KEY);
|
|
@@ -15894,7 +16098,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
15894
16098
|
/* harmony import */ var _vue_reactivity__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @vue/reactivity */ "./node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js");
|
|
15895
16099
|
/* harmony import */ var _vue_shared__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @vue/shared */ "./node_modules/@vue/shared/dist/shared.esm-bundler.js");
|
|
15896
16100
|
/**
|
|
15897
|
-
* @vue/runtime-core v3.5.
|
|
16101
|
+
* @vue/runtime-core v3.5.43
|
|
15898
16102
|
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
|
15899
16103
|
* @license MIT
|
|
15900
16104
|
**/
|
|
@@ -17962,13 +18166,15 @@ function createHydrationFunctions(rendererInternals) {
|
|
|
17962
18166
|
getContainerType(container),
|
|
17963
18167
|
optimized
|
|
17964
18168
|
);
|
|
17965
|
-
if (isAsyncWrapper(vnode) && !vnode.component.subTree) {
|
|
18169
|
+
if ((isAsyncWrapper(vnode) || vnode.component.asyncDep) && !vnode.component.subTree) {
|
|
17966
18170
|
let subTree;
|
|
17967
18171
|
if (isFragmentStart) {
|
|
17968
18172
|
subTree = createVNode(Static);
|
|
17969
18173
|
subTree.anchor = nextNode ? nextNode.previousSibling : container.lastChild;
|
|
17970
18174
|
} else {
|
|
17971
|
-
subTree = node.nodeType === 3 ? createTextVNode("") : createVNode(
|
|
18175
|
+
subTree = node.nodeType === 3 ? createTextVNode("") : createVNode(
|
|
18176
|
+
node.nodeType === 8 ? Comment : "div"
|
|
18177
|
+
);
|
|
17972
18178
|
}
|
|
17973
18179
|
subTree.el = node;
|
|
17974
18180
|
vnode.component.subTree = subTree;
|
|
@@ -21446,6 +21652,12 @@ function baseCreateRenderer(options, createHydrationFns) {
|
|
|
21446
21652
|
optimized = false;
|
|
21447
21653
|
n2.dynamicChildren = null;
|
|
21448
21654
|
}
|
|
21655
|
+
if (n2.dynamicChildren && n1 && n1.dynamicChildren && n1.dynamicChildren.hasOnce) {
|
|
21656
|
+
if (n2.dynamicChildren === _vue_shared__WEBPACK_IMPORTED_MODULE_1__.EMPTY_ARR) {
|
|
21657
|
+
n2.dynamicChildren = [];
|
|
21658
|
+
}
|
|
21659
|
+
n2.dynamicChildren.hasOnce = true;
|
|
21660
|
+
}
|
|
21449
21661
|
const { type, ref, shapeFlag } = n2;
|
|
21450
21662
|
switch (type) {
|
|
21451
21663
|
case Text:
|
|
@@ -22052,6 +22264,7 @@ function baseCreateRenderer(options, createHydrationFns) {
|
|
|
22052
22264
|
if (true) {
|
|
22053
22265
|
pushWarningContext(n2);
|
|
22054
22266
|
}
|
|
22267
|
+
n2.el = n1.el;
|
|
22055
22268
|
updateComponentPreRender(instance, n2, optimized);
|
|
22056
22269
|
if (true) {
|
|
22057
22270
|
popWarningContext();
|
|
@@ -22643,7 +22856,7 @@ function baseCreateRenderer(options, createHydrationFns) {
|
|
|
22643
22856
|
cacheIndex,
|
|
22644
22857
|
memo
|
|
22645
22858
|
} = vnode;
|
|
22646
|
-
if (patchFlag === -2) {
|
|
22859
|
+
if (patchFlag === -2 || dynamicChildren && dynamicChildren.hasOnce) {
|
|
22647
22860
|
optimized = false;
|
|
22648
22861
|
}
|
|
22649
22862
|
if (ref != null) {
|
|
@@ -22651,7 +22864,7 @@ function baseCreateRenderer(options, createHydrationFns) {
|
|
|
22651
22864
|
setRef(ref, null, parentSuspense, vnode, true);
|
|
22652
22865
|
(0,_vue_reactivity__WEBPACK_IMPORTED_MODULE_0__.resetTracking)();
|
|
22653
22866
|
}
|
|
22654
|
-
if (cacheIndex != null) {
|
|
22867
|
+
if (cacheIndex != null && (!vnode.ctx || vnode.ctx === parentComponent)) {
|
|
22655
22868
|
parentComponent.renderCache[cacheIndex] = void 0;
|
|
22656
22869
|
}
|
|
22657
22870
|
if (shapeFlag & 256) {
|
|
@@ -22732,6 +22945,9 @@ function baseCreateRenderer(options, createHydrationFns) {
|
|
|
22732
22945
|
}
|
|
22733
22946
|
if (type === Static) {
|
|
22734
22947
|
removeStaticNode(vnode);
|
|
22948
|
+
if (transition && !transition.persisted && transition.afterLeave) {
|
|
22949
|
+
transition.afterLeave();
|
|
22950
|
+
}
|
|
22735
22951
|
return;
|
|
22736
22952
|
}
|
|
22737
22953
|
const performRemove = () => {
|
|
@@ -22775,6 +22991,9 @@ function baseCreateRenderer(options, createHydrationFns) {
|
|
|
22775
22991
|
if (job) {
|
|
22776
22992
|
job.flags |= 8;
|
|
22777
22993
|
unmount(subTree, instance, parentSuspense, doRemove);
|
|
22994
|
+
} else if (instance.vnode.el && subTree) {
|
|
22995
|
+
subTree.transition = instance.vnode.transition;
|
|
22996
|
+
unmount(subTree, instance, parentSuspense, doRemove);
|
|
22778
22997
|
}
|
|
22779
22998
|
if (um) {
|
|
22780
22999
|
queuePostRenderEffect(um, parentSuspense);
|
|
@@ -22989,7 +23208,7 @@ const SuspenseImpl = {
|
|
|
22989
23208
|
rendererInternals
|
|
22990
23209
|
);
|
|
22991
23210
|
} else {
|
|
22992
|
-
if (parentSuspense && parentSuspense.deps > 0 && !n1.suspense.isInFallback) {
|
|
23211
|
+
if (parentSuspense && parentSuspense.deps > 0 && !n1.suspense.isInFallback && !parentSuspense.isHydrating) {
|
|
22993
23212
|
n2.suspense = n1.suspense;
|
|
22994
23213
|
n2.suspense.vnode = n2;
|
|
22995
23214
|
n2.el = n1.el;
|
|
@@ -23075,10 +23294,12 @@ function patchSuspense(n1, n2, container, anchor, parentComponent, namespace, sl
|
|
|
23075
23294
|
if (pendingBranch) {
|
|
23076
23295
|
suspense.pendingBranch = newBranch;
|
|
23077
23296
|
if (isSameVNodeType(pendingBranch, newBranch)) {
|
|
23297
|
+
suspense.deps++;
|
|
23078
23298
|
patch(
|
|
23079
23299
|
pendingBranch,
|
|
23080
23300
|
newBranch,
|
|
23081
|
-
|
|
23301
|
+
// a hydrating pending branch is adopted SSR DOM, already in place
|
|
23302
|
+
isHydrating ? container : suspense.hiddenContainer,
|
|
23082
23303
|
null,
|
|
23083
23304
|
parentComponent,
|
|
23084
23305
|
suspense,
|
|
@@ -23086,6 +23307,7 @@ function patchSuspense(n1, n2, container, anchor, parentComponent, namespace, sl
|
|
|
23086
23307
|
slotScopeIds,
|
|
23087
23308
|
optimized
|
|
23088
23309
|
);
|
|
23310
|
+
suspense.deps--;
|
|
23089
23311
|
if (suspense.deps <= 0) {
|
|
23090
23312
|
suspense.resolve();
|
|
23091
23313
|
} else if (isInFallback) {
|
|
@@ -23351,6 +23573,7 @@ function createSuspenseBoundary(vnode, parentSuspense, parentComponent, containe
|
|
|
23351
23573
|
suspense.effects = [];
|
|
23352
23574
|
if (isSuspensible) {
|
|
23353
23575
|
if (parentSuspense && parentSuspense.pendingBranch && parentSuspenseId === parentSuspense.pendingId) {
|
|
23576
|
+
parentSuspenseId = void 0;
|
|
23354
23577
|
parentSuspense.deps--;
|
|
23355
23578
|
if (parentSuspense.deps === 0 && !sync) {
|
|
23356
23579
|
parentSuspense.resolve();
|
|
@@ -23424,6 +23647,12 @@ function createSuspenseBoundary(vnode, parentSuspense, parentComponent, containe
|
|
|
23424
23647
|
return;
|
|
23425
23648
|
}
|
|
23426
23649
|
unsetCurrentInstance();
|
|
23650
|
+
if (hydratedEl && !instance.scope.active) {
|
|
23651
|
+
if (isInPendingSuspense && --suspense.deps === 0) {
|
|
23652
|
+
suspense.resolve();
|
|
23653
|
+
}
|
|
23654
|
+
return;
|
|
23655
|
+
}
|
|
23427
23656
|
instance.asyncResolved = true;
|
|
23428
23657
|
const { vnode: vnode2 } = instance;
|
|
23429
23658
|
if (true) {
|
|
@@ -23845,7 +24074,8 @@ function cloneVNode(vnode, extraProps, mergeRef = false, cloneTransition = false
|
|
|
23845
24074
|
el: vnode.el,
|
|
23846
24075
|
anchor: vnode.anchor,
|
|
23847
24076
|
ctx: vnode.ctx,
|
|
23848
|
-
ce: vnode.ce
|
|
24077
|
+
ce: vnode.ce,
|
|
24078
|
+
cacheIndex: vnode.cacheIndex
|
|
23849
24079
|
};
|
|
23850
24080
|
if (transition && cloneTransition) {
|
|
23851
24081
|
setTransitionHooks(
|
|
@@ -24652,7 +24882,7 @@ function isMemoSame(cached, memo) {
|
|
|
24652
24882
|
return true;
|
|
24653
24883
|
}
|
|
24654
24884
|
|
|
24655
|
-
const version = "3.5.
|
|
24885
|
+
const version = "3.5.43";
|
|
24656
24886
|
const warn = true ? warn$1 : 0;
|
|
24657
24887
|
const ErrorTypeStrings = ErrorTypeStrings$1 ;
|
|
24658
24888
|
const devtools = true ? devtools$1 : 0;
|
|
@@ -24863,7 +25093,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
24863
25093
|
/* harmony import */ var _vue_runtime_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @vue/runtime-core */ "./node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js");
|
|
24864
25094
|
/* harmony import */ var _vue_runtime_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @vue/shared */ "./node_modules/@vue/shared/dist/shared.esm-bundler.js");
|
|
24865
25095
|
/**
|
|
24866
|
-
* @vue/runtime-dom v3.5.
|
|
25096
|
+
* @vue/runtime-dom v3.5.43
|
|
24867
25097
|
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
|
24868
25098
|
* @license MIT
|
|
24869
25099
|
**/
|
|
@@ -27011,7 +27241,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
27011
27241
|
/* harmony export */ toTypeString: () => (/* binding */ toTypeString)
|
|
27012
27242
|
/* harmony export */ });
|
|
27013
27243
|
/**
|
|
27014
|
-
* @vue/shared v3.5.
|
|
27244
|
+
* @vue/shared v3.5.43
|
|
27015
27245
|
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
|
27016
27246
|
* @license MIT
|
|
27017
27247
|
**/
|
|
@@ -27279,10 +27509,10 @@ function normalizeStyle(value) {
|
|
|
27279
27509
|
}
|
|
27280
27510
|
const listDelimiterRE = /;(?![^(]*\))/g;
|
|
27281
27511
|
const propertyDelimiterRE = /:([^]+)/;
|
|
27282
|
-
const styleCommentRE =
|
|
27512
|
+
const styleCommentRE = /"(?:[^"\\]|\\[^])*"|'(?:[^'\\]|\\[^])*'|\\[^]|\/\*[^]*?\*\//g;
|
|
27283
27513
|
function parseStringStyle(cssText) {
|
|
27284
27514
|
const ret = {};
|
|
27285
|
-
cssText.replace(styleCommentRE, "").split(listDelimiterRE).forEach((item) => {
|
|
27515
|
+
cssText.replace(styleCommentRE, (match) => match.startsWith("/*") ? "" : match).split(listDelimiterRE).forEach((item) => {
|
|
27286
27516
|
if (item) {
|
|
27287
27517
|
const tmp = item.split(propertyDelimiterRE);
|
|
27288
27518
|
tmp.length > 1 && (ret[tmp[0].trim()] = tmp[1].trim());
|
|
@@ -27443,22 +27673,22 @@ function getEscapedCssVarName(key, doubleEscape) {
|
|
|
27443
27673
|
);
|
|
27444
27674
|
}
|
|
27445
27675
|
|
|
27446
|
-
function looseCompareArrays(a, b) {
|
|
27676
|
+
function looseCompareArrays(a, b, seen) {
|
|
27447
27677
|
if (a.length !== b.length) return false;
|
|
27448
27678
|
let equal = true;
|
|
27449
27679
|
for (let i = 0; equal && i < a.length; i++) {
|
|
27450
|
-
equal = looseEqual(a[i], b[i]);
|
|
27680
|
+
equal = looseEqual(a[i], b[i], seen);
|
|
27451
27681
|
}
|
|
27452
27682
|
return equal;
|
|
27453
27683
|
}
|
|
27454
|
-
function looseCompareCollections(a, b) {
|
|
27684
|
+
function looseCompareCollections(a, b, seen) {
|
|
27455
27685
|
if (a.size !== b.size) return false;
|
|
27456
27686
|
const candidates = Array.from(b);
|
|
27457
27687
|
const matched = new Uint8Array(candidates.length);
|
|
27458
27688
|
for (const item of a) {
|
|
27459
27689
|
let index = -1;
|
|
27460
27690
|
for (let i = 0; i < candidates.length; i++) {
|
|
27461
|
-
if (!matched[i] && looseEqual(item, candidates[i])) {
|
|
27691
|
+
if (!matched[i] && looseEqual(item, candidates[i], seen)) {
|
|
27462
27692
|
index = i;
|
|
27463
27693
|
break;
|
|
27464
27694
|
}
|
|
@@ -27468,7 +27698,47 @@ function looseCompareCollections(a, b) {
|
|
|
27468
27698
|
}
|
|
27469
27699
|
return true;
|
|
27470
27700
|
}
|
|
27471
|
-
function
|
|
27701
|
+
function looseCompareObjects(a, b, seen) {
|
|
27702
|
+
let aValidType = isMap(a);
|
|
27703
|
+
let bValidType = isMap(b);
|
|
27704
|
+
if (aValidType || bValidType) {
|
|
27705
|
+
return aValidType && bValidType ? looseCompareCollections(a, b, seen) : false;
|
|
27706
|
+
}
|
|
27707
|
+
aValidType = isSet(a);
|
|
27708
|
+
bValidType = isSet(b);
|
|
27709
|
+
if (aValidType || bValidType) {
|
|
27710
|
+
return aValidType && bValidType ? looseCompareCollections(a, b, seen) : false;
|
|
27711
|
+
}
|
|
27712
|
+
const aKeysCount = Object.keys(a).length;
|
|
27713
|
+
const bKeysCount = Object.keys(b).length;
|
|
27714
|
+
if (aKeysCount !== bKeysCount) {
|
|
27715
|
+
return false;
|
|
27716
|
+
}
|
|
27717
|
+
for (const key in a) {
|
|
27718
|
+
const aHasKey = a.hasOwnProperty(key);
|
|
27719
|
+
const bHasKey = b.hasOwnProperty(key);
|
|
27720
|
+
if (aHasKey && !bHasKey || !aHasKey && bHasKey || !looseEqual(a[key], b[key], seen)) {
|
|
27721
|
+
return false;
|
|
27722
|
+
}
|
|
27723
|
+
}
|
|
27724
|
+
return String(a) === String(b);
|
|
27725
|
+
}
|
|
27726
|
+
function looseCompareNested(a, b, seen, compare) {
|
|
27727
|
+
if (!seen) {
|
|
27728
|
+
seen = [/* @__PURE__ */ new Map(), /* @__PURE__ */ new Map()];
|
|
27729
|
+
}
|
|
27730
|
+
const [seenA, seenB] = seen;
|
|
27731
|
+
if (seenA.has(a) || seenB.has(b)) {
|
|
27732
|
+
return seenA.get(a) === b && seenB.get(b) === a;
|
|
27733
|
+
}
|
|
27734
|
+
seenA.set(a, b);
|
|
27735
|
+
seenB.set(b, a);
|
|
27736
|
+
const equal = compare(a, b, seen);
|
|
27737
|
+
seenA.delete(a);
|
|
27738
|
+
seenB.delete(b);
|
|
27739
|
+
return equal;
|
|
27740
|
+
}
|
|
27741
|
+
function looseEqual(a, b, seen) {
|
|
27472
27742
|
if (a === b) return true;
|
|
27473
27743
|
let aValidType = isDate(a);
|
|
27474
27744
|
let bValidType = isDate(b);
|
|
@@ -27483,7 +27753,7 @@ function looseEqual(a, b) {
|
|
|
27483
27753
|
aValidType = isArray(a);
|
|
27484
27754
|
bValidType = isArray(b);
|
|
27485
27755
|
if (aValidType || bValidType) {
|
|
27486
|
-
return aValidType && bValidType ?
|
|
27756
|
+
return aValidType && bValidType ? looseCompareNested(a, b, seen, looseCompareArrays) : false;
|
|
27487
27757
|
}
|
|
27488
27758
|
aValidType = isObject(a);
|
|
27489
27759
|
bValidType = isObject(b);
|
|
@@ -27491,28 +27761,7 @@ function looseEqual(a, b) {
|
|
|
27491
27761
|
if (!aValidType || !bValidType) {
|
|
27492
27762
|
return false;
|
|
27493
27763
|
}
|
|
27494
|
-
|
|
27495
|
-
bValidType = isMap(b);
|
|
27496
|
-
if (aValidType || bValidType) {
|
|
27497
|
-
return aValidType && bValidType ? looseCompareCollections(a, b) : false;
|
|
27498
|
-
}
|
|
27499
|
-
aValidType = isSet(a);
|
|
27500
|
-
bValidType = isSet(b);
|
|
27501
|
-
if (aValidType || bValidType) {
|
|
27502
|
-
return aValidType && bValidType ? looseCompareCollections(a, b) : false;
|
|
27503
|
-
}
|
|
27504
|
-
const aKeysCount = Object.keys(a).length;
|
|
27505
|
-
const bKeysCount = Object.keys(b).length;
|
|
27506
|
-
if (aKeysCount !== bKeysCount) {
|
|
27507
|
-
return false;
|
|
27508
|
-
}
|
|
27509
|
-
for (const key in a) {
|
|
27510
|
-
const aHasKey = a.hasOwnProperty(key);
|
|
27511
|
-
const bHasKey = b.hasOwnProperty(key);
|
|
27512
|
-
if (aHasKey && !bHasKey || !aHasKey && bHasKey || !looseEqual(a[key], b[key])) {
|
|
27513
|
-
return false;
|
|
27514
|
-
}
|
|
27515
|
-
}
|
|
27764
|
+
return looseCompareNested(a, b, seen, looseCompareObjects);
|
|
27516
27765
|
}
|
|
27517
27766
|
return String(a) === String(b);
|
|
27518
27767
|
}
|
|
@@ -52001,6 +52250,128 @@ function parseUtf8ValidationOption(options) {
|
|
|
52001
52250
|
|
|
52002
52251
|
/***/ },
|
|
52003
52252
|
|
|
52253
|
+
/***/ "./node_modules/mongoose/node_modules/mongodb/lib/bson.js"
|
|
52254
|
+
/*!****************************************************************!*\
|
|
52255
|
+
!*** ./node_modules/mongoose/node_modules/mongodb/lib/bson.js ***!
|
|
52256
|
+
\****************************************************************/
|
|
52257
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
52258
|
+
|
|
52259
|
+
"use strict";
|
|
52260
|
+
|
|
52261
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
52262
|
+
exports.setUint32LE = exports.readUint8 = exports.readInt32LE = exports.UUID = exports.Timestamp = exports.serialize = exports.ObjectId = exports.NumberUtils = exports.MinKey = exports.MaxKey = exports.Long = exports.Int32 = exports.EJSON = exports.Double = exports.deserialize = exports.Decimal128 = exports.DBRef = exports.Code = exports.calculateObjectSize = exports.ByteUtils = exports.BSONType = exports.BSONSymbol = exports.BSONRegExp = exports.BSONError = exports.BSON = exports.Binary = void 0;
|
|
52263
|
+
exports.parseToElementsToArray = parseToElementsToArray;
|
|
52264
|
+
exports.pluckBSONSerializeOptions = pluckBSONSerializeOptions;
|
|
52265
|
+
exports.resolveBSONOptions = resolveBSONOptions;
|
|
52266
|
+
exports.parseUtf8ValidationOption = parseUtf8ValidationOption;
|
|
52267
|
+
/* eslint-disable no-restricted-imports */
|
|
52268
|
+
const bson_1 = __webpack_require__(/*! bson */ "./node_modules/bson/lib/bson.mjs");
|
|
52269
|
+
var bson_2 = __webpack_require__(/*! bson */ "./node_modules/bson/lib/bson.mjs");
|
|
52270
|
+
Object.defineProperty(exports, "Binary", ({ enumerable: true, get: function () { return bson_2.Binary; } }));
|
|
52271
|
+
Object.defineProperty(exports, "BSON", ({ enumerable: true, get: function () { return bson_2.BSON; } }));
|
|
52272
|
+
Object.defineProperty(exports, "BSONError", ({ enumerable: true, get: function () { return bson_2.BSONError; } }));
|
|
52273
|
+
Object.defineProperty(exports, "BSONRegExp", ({ enumerable: true, get: function () { return bson_2.BSONRegExp; } }));
|
|
52274
|
+
Object.defineProperty(exports, "BSONSymbol", ({ enumerable: true, get: function () { return bson_2.BSONSymbol; } }));
|
|
52275
|
+
Object.defineProperty(exports, "BSONType", ({ enumerable: true, get: function () { return bson_2.BSONType; } }));
|
|
52276
|
+
Object.defineProperty(exports, "ByteUtils", ({ enumerable: true, get: function () { return bson_2.ByteUtils; } }));
|
|
52277
|
+
Object.defineProperty(exports, "calculateObjectSize", ({ enumerable: true, get: function () { return bson_2.calculateObjectSize; } }));
|
|
52278
|
+
Object.defineProperty(exports, "Code", ({ enumerable: true, get: function () { return bson_2.Code; } }));
|
|
52279
|
+
Object.defineProperty(exports, "DBRef", ({ enumerable: true, get: function () { return bson_2.DBRef; } }));
|
|
52280
|
+
Object.defineProperty(exports, "Decimal128", ({ enumerable: true, get: function () { return bson_2.Decimal128; } }));
|
|
52281
|
+
Object.defineProperty(exports, "deserialize", ({ enumerable: true, get: function () { return bson_2.deserialize; } }));
|
|
52282
|
+
Object.defineProperty(exports, "Double", ({ enumerable: true, get: function () { return bson_2.Double; } }));
|
|
52283
|
+
Object.defineProperty(exports, "EJSON", ({ enumerable: true, get: function () { return bson_2.EJSON; } }));
|
|
52284
|
+
Object.defineProperty(exports, "Int32", ({ enumerable: true, get: function () { return bson_2.Int32; } }));
|
|
52285
|
+
Object.defineProperty(exports, "Long", ({ enumerable: true, get: function () { return bson_2.Long; } }));
|
|
52286
|
+
Object.defineProperty(exports, "MaxKey", ({ enumerable: true, get: function () { return bson_2.MaxKey; } }));
|
|
52287
|
+
Object.defineProperty(exports, "MinKey", ({ enumerable: true, get: function () { return bson_2.MinKey; } }));
|
|
52288
|
+
Object.defineProperty(exports, "NumberUtils", ({ enumerable: true, get: function () { return bson_2.NumberUtils; } }));
|
|
52289
|
+
Object.defineProperty(exports, "ObjectId", ({ enumerable: true, get: function () { return bson_2.ObjectId; } }));
|
|
52290
|
+
Object.defineProperty(exports, "serialize", ({ enumerable: true, get: function () { return bson_2.serialize; } }));
|
|
52291
|
+
Object.defineProperty(exports, "Timestamp", ({ enumerable: true, get: function () { return bson_2.Timestamp; } }));
|
|
52292
|
+
Object.defineProperty(exports, "UUID", ({ enumerable: true, get: function () { return bson_2.UUID; } }));
|
|
52293
|
+
function parseToElementsToArray(bytes, offset) {
|
|
52294
|
+
const res = bson_1.BSON.onDemand.parseToElements(bytes, offset);
|
|
52295
|
+
return Array.isArray(res) ? res : [...res];
|
|
52296
|
+
}
|
|
52297
|
+
// validates buffer inputs, used for read operations
|
|
52298
|
+
const validateBufferInputs = (buffer, offset, length) => {
|
|
52299
|
+
if (offset < 0 || offset + length > buffer.length) {
|
|
52300
|
+
throw new RangeError(`Attempt to access memory outside buffer bounds: buffer length: ${buffer.length}, offset: ${offset}, length: ${length}`);
|
|
52301
|
+
}
|
|
52302
|
+
};
|
|
52303
|
+
// readInt32LE, reads a 32-bit integer from buffer at given offset
|
|
52304
|
+
// throws if offset is out of bounds
|
|
52305
|
+
const readInt32LE = (buffer, offset) => {
|
|
52306
|
+
validateBufferInputs(buffer, offset, 4);
|
|
52307
|
+
return bson_1.NumberUtils.getInt32LE(buffer, offset);
|
|
52308
|
+
};
|
|
52309
|
+
exports.readInt32LE = readInt32LE;
|
|
52310
|
+
// readUint8, reads a single unsigned byte from buffer at given offset
|
|
52311
|
+
const readUint8 = (buffer, offset) => {
|
|
52312
|
+
validateBufferInputs(buffer, offset, 1);
|
|
52313
|
+
return buffer[offset];
|
|
52314
|
+
};
|
|
52315
|
+
exports.readUint8 = readUint8;
|
|
52316
|
+
const setUint32LE = (destination, offset, value) => {
|
|
52317
|
+
destination[offset] = value;
|
|
52318
|
+
value >>>= 8;
|
|
52319
|
+
destination[offset + 1] = value;
|
|
52320
|
+
value >>>= 8;
|
|
52321
|
+
destination[offset + 2] = value;
|
|
52322
|
+
value >>>= 8;
|
|
52323
|
+
destination[offset + 3] = value;
|
|
52324
|
+
return 4;
|
|
52325
|
+
};
|
|
52326
|
+
exports.setUint32LE = setUint32LE;
|
|
52327
|
+
function pluckBSONSerializeOptions(options) {
|
|
52328
|
+
const { fieldsAsRaw, useBigInt64, promoteValues, promoteBuffers, promoteLongs, serializeFunctions, ignoreUndefined, bsonRegExp, raw, enableUtf8Validation } = options;
|
|
52329
|
+
return {
|
|
52330
|
+
fieldsAsRaw,
|
|
52331
|
+
useBigInt64,
|
|
52332
|
+
promoteValues,
|
|
52333
|
+
promoteBuffers,
|
|
52334
|
+
promoteLongs,
|
|
52335
|
+
serializeFunctions,
|
|
52336
|
+
ignoreUndefined,
|
|
52337
|
+
bsonRegExp,
|
|
52338
|
+
raw,
|
|
52339
|
+
enableUtf8Validation
|
|
52340
|
+
};
|
|
52341
|
+
}
|
|
52342
|
+
/**
|
|
52343
|
+
* Merge the given BSONSerializeOptions, preferring options over the parent's options, and
|
|
52344
|
+
* substituting defaults for values not set.
|
|
52345
|
+
*
|
|
52346
|
+
* @internal
|
|
52347
|
+
*/
|
|
52348
|
+
function resolveBSONOptions(options, parent) {
|
|
52349
|
+
const parentOptions = parent?.bsonOptions;
|
|
52350
|
+
return {
|
|
52351
|
+
raw: options?.raw ?? parentOptions?.raw ?? false,
|
|
52352
|
+
useBigInt64: options?.useBigInt64 ?? parentOptions?.useBigInt64 ?? false,
|
|
52353
|
+
promoteLongs: options?.promoteLongs ?? parentOptions?.promoteLongs ?? true,
|
|
52354
|
+
promoteValues: options?.promoteValues ?? parentOptions?.promoteValues ?? true,
|
|
52355
|
+
promoteBuffers: options?.promoteBuffers ?? parentOptions?.promoteBuffers ?? false,
|
|
52356
|
+
ignoreUndefined: options?.ignoreUndefined ?? parentOptions?.ignoreUndefined ?? false,
|
|
52357
|
+
bsonRegExp: options?.bsonRegExp ?? parentOptions?.bsonRegExp ?? false,
|
|
52358
|
+
serializeFunctions: options?.serializeFunctions ?? parentOptions?.serializeFunctions ?? false,
|
|
52359
|
+
fieldsAsRaw: options?.fieldsAsRaw ?? parentOptions?.fieldsAsRaw ?? {},
|
|
52360
|
+
enableUtf8Validation: options?.enableUtf8Validation ?? parentOptions?.enableUtf8Validation ?? true
|
|
52361
|
+
};
|
|
52362
|
+
}
|
|
52363
|
+
/** @internal */
|
|
52364
|
+
function parseUtf8ValidationOption(options) {
|
|
52365
|
+
const enableUtf8Validation = options?.enableUtf8Validation;
|
|
52366
|
+
if (enableUtf8Validation === false) {
|
|
52367
|
+
return { utf8: false };
|
|
52368
|
+
}
|
|
52369
|
+
return { utf8: { writeErrors: false } };
|
|
52370
|
+
}
|
|
52371
|
+
//# sourceMappingURL=bson.js.map
|
|
52372
|
+
|
|
52373
|
+
/***/ },
|
|
52374
|
+
|
|
52004
52375
|
/***/ "./node_modules/mpath/index.js"
|
|
52005
52376
|
/*!*************************************!*\
|
|
52006
52377
|
!*** ./node_modules/mpath/index.js ***!
|
|
@@ -52758,7 +53129,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
52758
53129
|
/* harmony import */ var _vue_runtime_dom__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @vue/runtime-dom */ "./node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js");
|
|
52759
53130
|
/* harmony import */ var _vue_runtime_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @vue/runtime-dom */ "./node_modules/@vue/runtime-dom/dist/runtime-dom.esm-bundler.js");
|
|
52760
53131
|
/**
|
|
52761
|
-
* vue v3.5.
|
|
53132
|
+
* vue v3.5.43
|
|
52762
53133
|
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
|
52763
53134
|
* @license MIT
|
|
52764
53135
|
**/
|
|
@@ -54543,6 +54914,17 @@ module.exports = "<div class=\"list-subdocument tooltip\">\n <div>{{shortenValu
|
|
|
54543
54914
|
|
|
54544
54915
|
/***/ },
|
|
54545
54916
|
|
|
54917
|
+
/***/ "./frontend/src/mcp/mcp.html"
|
|
54918
|
+
/*!***********************************!*\
|
|
54919
|
+
!*** ./frontend/src/mcp/mcp.html ***!
|
|
54920
|
+
\***********************************/
|
|
54921
|
+
(module) {
|
|
54922
|
+
|
|
54923
|
+
"use strict";
|
|
54924
|
+
module.exports = "<div class=\"mx-auto max-w-5xl py-6 px-2\">\n <h1 class=\"text-xl font-bold text-content\">MCP</h1>\n <p class=\"mt-2 text-sm text-content-secondary\">\n Connect an MCP client such as Claude or ChatGPT to this Mongoose Studio workspace.\n </p>\n\n <div class=\"mt-6 rounded-lg border border-edge bg-surface p-4\">\n <label for=\"mcp-url\" class=\"block text-sm font-medium text-content\">MCP URL</label>\n <div class=\"mt-2 flex gap-2\">\n <input\n id=\"mcp-url\"\n type=\"text\"\n readonly\n :value=\"mcpUrl\"\n class=\"min-w-0 flex-1 rounded-md bg-muted px-3 py-2 font-mono text-sm text-content outline outline-1 -outline-offset-1 outline-edge-strong\"\n />\n <async-button\n type=\"button\"\n @click=\"copyMCPUrl\"\n class=\"rounded-md bg-primary px-4 py-2 text-sm font-semibold text-primary-text shadow-sm hover:bg-primary-hover\">\n Copy\n </async-button>\n </div>\n </div>\n\n <div class=\"mt-8 grid gap-6 text-sm text-content-secondary\">\n <section>\n <h2 class=\"text-base font-semibold text-content\">Authentication and network access</h2>\n <p class=\"mt-2\">\n Without a Mongoose Studio API key, the MCP endpoint uses the deployment's\n <code class=\"rounded bg-muted px-1 py-0.5\">bindIp</code> restrictions. By default, this means an MCP client can only connect from localhost.\n </p>\n <p class=\"mt-2\">\n With an API key, MCP clients such as Claude and ChatGPT connect through OAuth. You will be prompted to sign in to Mongoose Studio and approve the connection before the client receives access.\n </p>\n </section>\n\n <section>\n <h2 class=\"text-base font-semibold text-content\">Permissions</h2>\n <p class=\"mt-2\">\n When an API key is configured, MCP access is scoped to the signed-in user's workspace permissions. During authorization, the user can explicitly grant fewer permissions, such as read-only access or a lower execution time limit. An MCP connection can never receive more access than that user already has.\n </p>\n </section>\n\n <section>\n <h2 class=\"text-base font-semibold text-content\">Supported operations</h2>\n <p class=\"mt-2\">\n The MCP server supports database CRUD operations, dashboards, and script creation. It does not execute standalone scripts directly.\n </p>\n <p class=\"mt-2\">\n An MCP client can create a script and return a Mongoose Studio URL. A person can then open that URL, review or edit the code, and choose whether to dry run or execute it.\n </p>\n </section>\n </div>\n</div>\n";
|
|
54925
|
+
|
|
54926
|
+
/***/ },
|
|
54927
|
+
|
|
54546
54928
|
/***/ "./frontend/src/modal/modal.css"
|
|
54547
54929
|
/*!**************************************!*\
|
|
54548
54930
|
!*** ./frontend/src/modal/modal.css ***!
|
|
@@ -54649,7 +55031,7 @@ module.exports = ".active {\n text-decoration: underline;\n}\n\n.navbar .nav-le
|
|
|
54649
55031
|
(module) {
|
|
54650
55032
|
|
|
54651
55033
|
"use strict";
|
|
54652
|
-
module.exports = "<div>\n<div class=\"navbar w-full bg-page border-b border-edge !h-[55px] hidden md:grid grid-cols-[1fr_auto_1fr] items-stretch px-4\">\n <!-- Left: Logo + Brand -->\n <div class=\"flex items-center gap-2 self-center\">\n <router-link class=\"flex items-center gap-2\" :to=\"{ name: defaultRoute }\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-10 text-primary\" viewBox=\"0 0 250 250\" fill=\"currentColor\" aria-label=\"Mongoose Studio Logo\">\n <path d=\"M 241.66,125.01 C 237.81,112.98 227.41,111.95 216.76,110.36 C 215.12,95.83 210.99,83.09 202.29,70.33 C 202.99,68.37 201.92,66.65 200.74,65.11 C 183.14,41.46 157.52,27 124.66,27 C 92.62,27 66.09,40.77 48.28,63.38 C 46.21,65.85 46.26,67.71 47.12,69.36 C 37.81,81.15 33.21,93.78 30.99,109.86 C 20.19,110.58 11.71,115.92 9.04,124.94 C 3.28,145.66 5.62,157.95 10.01,169.16 C 16.14,184.65 29.12,186.31 36.04,185.81 C 42.48,185.68 44.94,184.31 44.72,182.11 C 44.26,177.79 41.01,165.31 41.01,149.12 C 41.01,138.22 43.19,127.74 46.21,117.7 C 47.51,113.33 44.66,112.05 39.16,110.28 C 41.01,96.88 45.88,84.85 52.61,73.79 C 55.17,75.56 58.07,74.88 59.61,72.71 C 75.86,54.31 97.89,45.16 124.61,45.16 C 149.71,45.16 171.91,55.91 189.29,73.47 C 191.95,76.59 193.91,76.67 197.6,74.42 C 204.93,86.26 208.28,98.24 208.98,110.39 C 203.84,111.81 201.28,113.19 202.92,118.61 C 206.51,128.99 207.92,137.93 207.92,148.73 C 207.92,162.11 204.8,174.71 202.84,182.71 C 201.92,186.23 204.31,186.91 210.79,186.99 H 213.91 C 225.87,186.61 235.39,180.64 239.49,169.05 C 244.83,155.26 245.08,138.01 241.66,125.01 Z\"/>\n <path d=\"M 124.71,70.81 C 79.63,70.81 47.49,107.12 47.49,148.72 C 47.49,169.16 56.41,188.19 73.71,200.61 L 73.96,200.77 C 77.43,177.81 84.16,162.21 95.29,145.42 C 92.04,137.09 91.71,130.87 92.62,120.83 C 93.81,111.23 96.08,107.12 102.19,107.68 C 110.04,108.87 117.98,116.18 126.22,124.96 C 139.89,124.05 157.81,131.25 178.33,139.09 C 183.11,140.86 183.72,142.63 182.97,148.33 C 179.45,160.93 170.86,166.63 158.11,174.05 C 143.09,183.07 141.13,199.42 153.88,220.09 L 153.96,221.01 L 154.71,221.17 C 181.31,208.43 201.34,181.01 201.34,148.72 C 201.34,108.15 169.29,70.81 124.71,70.81 Z\"/>\n </svg>\n <span class=\"text-base font-semibold text-content whitespace-nowrap\">Mongoose Studio</span>\n </router-link>\n </div>\n <!-- Center: Nav Links -->\n <nav class=\"flex items-stretch gap-6\">\n <a v-if=\"hasAccess(roles, 'root')\"\n href=\"#/\"\n class=\"inline-flex items-center px-1 border-b-2 text-sm font-medium\"\n :class=\"documentView ? 'text-content border-primary' : 'border-transparent text-content-tertiary hover:text-content'\">Documents</a>\n <span v-else class=\"inline-flex items-center px-1 border-b-2 border-transparent text-sm font-medium text-gray-300 cursor-not-allowed\" aria-disabled=\"true\">\n Documents\n <svg class=\"h-4 w-4 ml-1\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a v-if=\"hasAccess(roles, 'dashboards')\"\n href=\"#/dashboards\"\n class=\"inline-flex items-center px-1 border-b-2 text-sm font-medium\"\n :class=\"dashboardView ? 'text-content border-primary' : 'border-transparent text-content-tertiary hover:text-content'\">Dashboards</a>\n <span v-else class=\"inline-flex items-center px-1 border-b-2 border-transparent text-sm font-medium text-gray-300 cursor-not-allowed\">\n Dashboards\n <svg class=\"h-4 w-4 ml-1\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a v-if=\"hasAccess(roles, 'chat') && supportsAI\"\n href=\"#/chat\"\n class=\"inline-flex items-center px-1 border-b-2 text-sm font-medium\"\n :class=\"chatView ? 'text-content border-primary' : 'border-transparent text-content-tertiary hover:text-content'\">Chat</a>\n <span v-else-if=\"hasAccess(roles, 'chat') && !supportsAI\"\n class=\"inline-flex items-center px-1 border-b-2 border-transparent text-sm font-medium text-gray-300 cursor-not-allowed\"\n :title=\"chatDisabledReason\">\n Chat\n <svg class=\"h-4 w-4 ml-1\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <span v-else class=\"inline-flex items-center px-1 border-b-2 border-transparent text-sm font-medium text-gray-300 cursor-not-allowed\">\n Chat\n <svg class=\"h-4 w-4 ml-1\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a\n v-if=\"hasTaskVisualizer\"\n href=\"#/tasks\"\n class=\"inline-flex items-center px-1 border-b-2 text-sm font-medium\"\n :class=\"taskView ? 'text-content border-primary' : 'border-transparent text-content-tertiary hover:text-content'\">\n Tasks\n </a>\n <a\n href=\"https://studio.mongoosejs.io/docs\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"inline-flex items-center px-1 border-b-2 border-transparent text-sm font-medium text-content-tertiary hover:text-content\"\n >\n Docs\n </a>\n </nav>\n <!-- Right: Env Badge + User -->\n <div class=\"flex items-center justify-end gap-3 self-center\">\n <button\n type=\"button\"\n class=\"inline-flex items-center justify-center rounded-md p-2 text-content-tertiary hover:bg-muted hover:text-content-secondary\"\n title=\"Recent pages\"\n aria-label=\"Recent pages\"\n aria-haspopup=\"dialog\"\n :aria-expanded=\"showRecentPagesModal ? 'true' : 'false'\"\n @click=\"openRecentPagesModal\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"h-5 w-5\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n </button>\n <div\n v-if=\"!!state.nodeEnv\"\n title=\"NODE_ENV\"\n class=\"inline-flex items-center rounded px-2 py-1 text-xs text-content-tertiary bg-surface border border-edge gap-2\"\n >\n <span\n :class=\"warnEnv ? 'bg-red-400' : 'bg-yellow-400'\"\n class=\"inline-block rounded-full\"\n style=\"width: 0.5em; height: 0.5em;\"\n ></span>\n <span>{{state.nodeEnv}}</span>\n </div>\n <button\n v-if=\"!user || !hasAPIKey\"\n type=\"button\"\n @click=\"toggleDarkMode\"\n :title=\"darkMode ? 'Switch to light mode' : 'Switch to dark mode'\"\n class=\"inline-flex items-center justify-center rounded-md p-2 text-content-tertiary hover:text-content-secondary hover:bg-muted\"\n aria-label=\"Toggle dark mode\">\n <svg v-if=\"darkMode\" xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z\"/>\n </svg>\n <svg v-else xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z\"/>\n </svg>\n </button>\n <div class=\"flex items-center\" v-if=\"!user && hasAPIKey\">\n <button\n type=\"button\"\n @click=\"loginWithGithub\"\n class=\"rounded bg-primary px-2 py-2 text-sm font-semibold text-primary-text shadow-sm hover:bg-primary-hover focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\">\n Login\n </button>\n </div>\n <div v-if=\"user && hasAPIKey\" class=\"flex items-center relative\" v-clickOutside=\"hideFlyout\">\n <button type=\"button\" @click=\"showFlyout = !showFlyout\" class=\"relative flex rounded-full text-sm focus:outline-none focus:ring-2 focus:ring-gray-300\" id=\"user-menu-button\" aria-expanded=\"false\" aria-haspopup=\"true\">\n <span class=\"absolute -inset-1.5\"></span>\n <span class=\"sr-only\">Open user menu</span>\n <img class=\"size-8 rounded-full\" :src=\"user.picture\" alt=\"\">\n </button>\n\n <div\n v-if=\"showFlyout\"\n class=\"absolute right-0 top-[90%] w-48 origin-top-right rounded-md bg-surface py-1 shadow-lg ring-1 ring-black/5 focus:outline-none\"\n role=\"menu\"\n aria-orientation=\"vertical\"\n aria-labelledby=\"user-menu-button\"\n style=\"z-index: 10000\"\n tabindex=\"-1\">\n <button\n type=\"button\"\n @click=\"toggleDarkMode(); showFlyout = false\"\n class=\"w-full cursor-pointer block px-4 py-2 text-sm text-content-secondary hover:bg-primary-subtle text-left flex items-center gap-2\"\n role=\"menuitem\"\n tabindex=\"-1\">\n <svg v-if=\"darkMode\" xmlns=\"http://www.w3.org/2000/svg\" class=\"h-4 w-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z\"/></svg>\n <svg v-else xmlns=\"http://www.w3.org/2000/svg\" class=\"h-4 w-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z\"/></svg>\n {{ darkMode ? 'Light mode' : 'Dark mode' }}\n </button>\n <router-link to=\"/team\" v-if=\"hasAccess(roles, 'team')\" @click=\"showFlyout = false\" class=\"cursor-pointer block px-4 py-2 text-sm text-content-secondary hover:bg-primary-subtle\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">Team</router-link>\n <span v-else class=\"block px-4 py-2 text-sm text-gray-300 cursor-not-allowed\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">\n Team\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <span @click=\"logout\" class=\"cursor-pointer block px-4 py-2 text-sm text-content-secondary hover:bg-primary-subtle\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">Sign out</span>\n </div>\n </div>\n </div>\n</div>\n<!-- Mobile navbar -->\n<div class=\"navbar w-full bg-page flex justify-between border-b border-edge !h-[55px] md:hidden\">\n <div class=\"flex items-center gap-2 pl-4\">\n <router-link class=\"flex items-center gap-2\" :to=\"{ name: defaultRoute }\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-8 text-primary\" viewBox=\"0 0 250 250\" fill=\"currentColor\" aria-label=\"Mongoose Studio Logo\">\n <path d=\"M 241.66,125.01 C 237.81,112.98 227.41,111.95 216.76,110.36 C 215.12,95.83 210.99,83.09 202.29,70.33 C 202.99,68.37 201.92,66.65 200.74,65.11 C 183.14,41.46 157.52,27 124.66,27 C 92.62,27 66.09,40.77 48.28,63.38 C 46.21,65.85 46.26,67.71 47.12,69.36 C 37.81,81.15 33.21,93.78 30.99,109.86 C 20.19,110.58 11.71,115.92 9.04,124.94 C 3.28,145.66 5.62,157.95 10.01,169.16 C 16.14,184.65 29.12,186.31 36.04,185.81 C 42.48,185.68 44.94,184.31 44.72,182.11 C 44.26,177.79 41.01,165.31 41.01,149.12 C 41.01,138.22 43.19,127.74 46.21,117.7 C 47.51,113.33 44.66,112.05 39.16,110.28 C 41.01,96.88 45.88,84.85 52.61,73.79 C 55.17,75.56 58.07,74.88 59.61,72.71 C 75.86,54.31 97.89,45.16 124.61,45.16 C 149.71,45.16 171.91,55.91 189.29,73.47 C 191.95,76.59 193.91,76.67 197.6,74.42 C 204.93,86.26 208.28,98.24 208.98,110.39 C 203.84,111.81 201.28,113.19 202.92,118.61 C 206.51,128.99 207.92,137.93 207.92,148.73 C 207.92,162.11 204.8,174.71 202.84,182.71 C 201.92,186.23 204.31,186.91 210.79,186.99 H 213.91 C 225.87,186.61 235.39,180.64 239.49,169.05 C 244.83,155.26 245.08,138.01 241.66,125.01 Z\"/>\n <path d=\"M 124.71,70.81 C 79.63,70.81 47.49,107.12 47.49,148.72 C 47.49,169.16 56.41,188.19 73.71,200.61 L 73.96,200.77 C 77.43,177.81 84.16,162.21 95.29,145.42 C 92.04,137.09 91.71,130.87 92.62,120.83 C 93.81,111.23 96.08,107.12 102.19,107.68 C 110.04,108.87 117.98,116.18 126.22,124.96 C 139.89,124.05 157.81,131.25 178.33,139.09 C 183.11,140.86 183.72,142.63 182.97,148.33 C 179.45,160.93 170.86,166.63 158.11,174.05 C 143.09,183.07 141.13,199.42 153.88,220.09 L 153.96,221.01 L 154.71,221.17 C 181.31,208.43 201.34,181.01 201.34,148.72 C 201.34,108.15 169.29,70.81 124.71,70.81 Z\"/>\n </svg>\n <span class=\"text-base font-semibold text-content\">Mongoose Studio</span>\n </router-link>\n </div>\n <div class=\"flex items-center gap-1 pr-2\">\n <button\n type=\"button\"\n class=\"rounded-md p-2 text-content-tertiary hover:bg-muted hover:text-content-secondary md:hidden\"\n title=\"Recent pages\"\n aria-label=\"Recent pages\"\n aria-haspopup=\"dialog\"\n :aria-expanded=\"showRecentPagesModal ? 'true' : 'false'\"\n @click=\"openRecentPagesModal\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"h-6 w-6\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n </button>\n <!-- Mobile menu toggle, controls the 'mobileMenuOpen' state. -->\n <button type=\"button\" id=\"open-mobile-menu\" class=\"-ml-2 rounded-md p-2 text-gray-400\">\n <span class=\"sr-only\">Open menu</span>\n <svg class=\"h-6 w-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5\" />\n </svg>\n </button>\n </div>\n\n <!-- Mobile menu mask -->\n <div id=\"mobile-menu-mask\" class=\"fixed inset-0 bg-black bg-opacity-40 z-40 hidden\"></div>\n <!-- Mobile menu drawer -->\n <div id=\"mobile-menu\" style=\"z-index: 100000\" class=\"fixed inset-0 bg-page shadow-lg transform translate-x-full transition-transform duration-200 ease-in-out flex flex-col\">\n <div class=\"flex items-center justify-between px-4 !h-[55px] border-b border-edge\">\n <router-link :to=\"{ name: defaultRoute }\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-[32px] text-primary\" viewBox=\"0 0 250 250\" fill=\"currentColor\" aria-label=\"Mongoose Studio Logo\">\n <path d=\"M 241.66,125.01 C 237.81,112.98 227.41,111.95 216.76,110.36 C 215.12,95.83 210.99,83.09 202.29,70.33 C 202.99,68.37 201.92,66.65 200.74,65.11 C 183.14,41.46 157.52,27 124.66,27 C 92.62,27 66.09,40.77 48.28,63.38 C 46.21,65.85 46.26,67.71 47.12,69.36 C 37.81,81.15 33.21,93.78 30.99,109.86 C 20.19,110.58 11.71,115.92 9.04,124.94 C 3.28,145.66 5.62,157.95 10.01,169.16 C 16.14,184.65 29.12,186.31 36.04,185.81 C 42.48,185.68 44.94,184.31 44.72,182.11 C 44.26,177.79 41.01,165.31 41.01,149.12 C 41.01,138.22 43.19,127.74 46.21,117.7 C 47.51,113.33 44.66,112.05 39.16,110.28 C 41.01,96.88 45.88,84.85 52.61,73.79 C 55.17,75.56 58.07,74.88 59.61,72.71 C 75.86,54.31 97.89,45.16 124.61,45.16 C 149.71,45.16 171.91,55.91 189.29,73.47 C 191.95,76.59 193.91,76.67 197.6,74.42 C 204.93,86.26 208.28,98.24 208.98,110.39 C 203.84,111.81 201.28,113.19 202.92,118.61 C 206.51,128.99 207.92,137.93 207.92,148.73 C 207.92,162.11 204.8,174.71 202.84,182.71 C 201.92,186.23 204.31,186.91 210.79,186.99 H 213.91 C 225.87,186.61 235.39,180.64 239.49,169.05 C 244.83,155.26 245.08,138.01 241.66,125.01 Z\"/>\n <path d=\"M 124.71,70.81 C 79.63,70.81 47.49,107.12 47.49,148.72 C 47.49,169.16 56.41,188.19 73.71,200.61 L 73.96,200.77 C 77.43,177.81 84.16,162.21 95.29,145.42 C 92.04,137.09 91.71,130.87 92.62,120.83 C 93.81,111.23 96.08,107.12 102.19,107.68 C 110.04,108.87 117.98,116.18 126.22,124.96 C 139.89,124.05 157.81,131.25 178.33,139.09 C 183.11,140.86 183.72,142.63 182.97,148.33 C 179.45,160.93 170.86,166.63 158.11,174.05 C 143.09,183.07 141.13,199.42 153.88,220.09 L 153.96,221.01 L 154.71,221.17 C 181.31,208.43 201.34,181.01 201.34,148.72 C 201.34,108.15 169.29,70.81 124.71,70.81 Z\"/>\n </svg>\n </router-link>\n <button type=\"button\" id=\"close-mobile-menu\" class=\"text-gray-400 p-2 rounded-md\">\n <span class=\"sr-only\">Close menu</span>\n <svg class=\"h-6 w-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n <nav class=\"flex-1 px-4 py-4 space-y-2\">\n <div class=\"flex items-center gap-2 px-3 py-2\" v-if=\"!user || !hasAPIKey\">\n <button\n type=\"button\"\n @click=\"toggleDarkMode\"\n class=\"inline-flex items-center gap-2 rounded-md px-3 py-2 text-base font-medium text-content-secondary hover:bg-muted\"\n aria-label=\"Toggle dark mode\">\n <svg v-if=\"darkMode\" xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z\"/></svg>\n <svg v-else xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z\"/></svg>\n <span>{{ darkMode ? 'Light mode' : 'Dark mode' }}</span>\n </button>\n </div>\n <a v-if=\"hasAccess(roles, 'root')\"\n href=\"#/\"\n class=\"block px-3 py-2 rounded-md text-base font-medium\"\n :class=\"documentView ? 'text-content bg-primary-subtle' : 'text-content-secondary hover:bg-muted'\">Documents</a>\n <span v-else class=\"block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed\">\n Documents\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a v-if=\"hasAccess(roles, 'dashboards')\"\n href=\"#/dashboards\"\n class=\"block px-3 py-2 rounded-md text-base font-medium\"\n :class=\"dashboardView ? 'text-content bg-primary-subtle' : 'text-content-secondary hover:bg-muted'\">Dashboards</a>\n <span v-else class=\"block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed\">\n Dashboards\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a v-if=\"hasAccess(roles, 'chat') && supportsAI\"\n href=\"#/chat\"\n class=\"block px-3 py-2 rounded-md text-base font-medium\"\n :class=\"chatView ? 'text-content bg-primary-subtle' : 'text-content-secondary hover:bg-muted'\">Chat</a>\n <span v-else-if=\"hasAccess(roles, 'chat') && !supportsAI\"\n class=\"block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed\"\n :title=\"chatDisabledReason\">\n Chat\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <span v-else class=\"block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed\">\n Chat\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a v-if=\"hasTaskVisualizer\"\n href=\"#/tasks\"\n class=\"block px-3 py-2 rounded-md text-base font-medium\"\n :class=\"taskView ? 'text-content bg-primary-subtle' : 'text-content-secondary hover:bg-muted'\">Tasks</a>\n <div v-if=\"!user && hasAPIKey\" class=\"mt-4\">\n <button\n type=\"button\"\n @click=\"loginWithGithub\"\n class=\"w-full rounded bg-muted text-content px-3 py-2 text-base font-semibold shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\">\n Login\n </button>\n </div>\n <div v-if=\"user && hasAPIKey\" class=\"mt-4\">\n <div class=\"flex items-center gap-3 px-3 py-2 bg-page rounded-md\">\n <img class=\"size-8 rounded-full\" :src=\"user.picture\" alt=\"\">\n <span class=\"text-content font-medium\">{{ user.name }}</span>\n </div>\n <div class=\"mt-2 space-y-1\">\n <button\n type=\"button\"\n @click=\"toggleDarkMode\"\n class=\"w-full inline-flex items-center gap-2 px-3 py-2 rounded-md text-base text-content-secondary hover:bg-primary-subtle text-left\">\n <svg v-if=\"darkMode\" xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z\"/></svg>\n <svg v-else xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z\"/></svg>\n {{ darkMode ? 'Light mode' : 'Dark mode' }}\n </button>\n <router-link to=\"/team\" v-if=\"hasAccess(roles, 'team')\" class=\"block px-3 py-2 rounded-md text-base text-content-secondary hover:bg-primary-subtle\">Team</router-link>\n <span v-else class=\"block px-3 py-2 rounded-md text-base text-gray-300 cursor-not-allowed\">\n Team\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <span @click=\"logout\" class=\"block px-3 py-2 rounded-md text-base text-content-secondary hover:bg-primary-subtle cursor-pointer\">Sign out</span>\n </div>\n </div>\n </nav>\n </div>\n</div>\n\n<modal\n v-if=\"showRecentPagesModal\"\n flush-container\n containerClass=\"!max-w-md !w-[min(94vw,28rem)] !overflow-hidden !rounded-lg !border !border-edge !bg-surface !shadow-xl dark:!bg-shark-900 text-content\"\n bodyClass=\"modal-recent-pages-body !p-0\"\n>\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"closeRecentPagesModal\" role=\"button\" aria-label=\"Close recent pages\">×</div>\n <div\n class=\"shrink-0 flex items-center gap-3 border-b border-edge bg-surface px-4 py-4 pr-12 dark:bg-shark-900\"\n >\n <h2 class=\"m-0 text-lg font-semibold text-content\">Recent pages</h2>\n <button\n type=\"button\"\n class=\"rounded px-2 py-1 text-sm font-medium text-content-secondary hover:bg-muted disabled:opacity-50\"\n @click=\"clearRecentPagesHistory\"\n :disabled=\"recentPagesList.length === 0\"\n >\n Clear\n </button>\n </div>\n <div class=\"modal-recent-pages-scroll\">\n <div\n v-if=\"recentPagesList.length === 0\"\n class=\"m-4 rounded border border-dashed border-edge px-3 py-6 text-center text-sm text-content-tertiary\"\n >\n No recent pages yet.\n </div>\n <button\n v-for=\"entry in recentPagesList\"\n :key=\"entry.path + '-' + entry.visitedAt\"\n type=\"button\"\n class=\"w-full px-4 py-2.5 text-left hover:bg-muted\"\n :class=\"entry.path === $route.fullPath ? 'bg-primary-subtle' : ''\"\n @click=\"goToRecentPage(entry)\"\n >\n <div class=\"truncate text-sm font-medium text-content\">{{ entry.label }}</div>\n <div class=\"truncate font-mono text-xs text-content-tertiary\">{{ entry.path }}</div>\n </button>\n </div>\n </template>\n</modal>\n</div>\n";
|
|
55034
|
+
module.exports = "<div>\n<div class=\"navbar w-full bg-page border-b border-edge !h-[55px] hidden md:grid grid-cols-[1fr_auto_1fr] items-stretch px-4\">\n <!-- Left: Logo + Brand -->\n <div class=\"flex items-center gap-2 self-center\">\n <router-link class=\"flex items-center gap-2\" :to=\"{ name: defaultRoute }\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-10 text-primary\" viewBox=\"0 0 250 250\" fill=\"currentColor\" aria-label=\"Mongoose Studio Logo\">\n <path d=\"M 241.66,125.01 C 237.81,112.98 227.41,111.95 216.76,110.36 C 215.12,95.83 210.99,83.09 202.29,70.33 C 202.99,68.37 201.92,66.65 200.74,65.11 C 183.14,41.46 157.52,27 124.66,27 C 92.62,27 66.09,40.77 48.28,63.38 C 46.21,65.85 46.26,67.71 47.12,69.36 C 37.81,81.15 33.21,93.78 30.99,109.86 C 20.19,110.58 11.71,115.92 9.04,124.94 C 3.28,145.66 5.62,157.95 10.01,169.16 C 16.14,184.65 29.12,186.31 36.04,185.81 C 42.48,185.68 44.94,184.31 44.72,182.11 C 44.26,177.79 41.01,165.31 41.01,149.12 C 41.01,138.22 43.19,127.74 46.21,117.7 C 47.51,113.33 44.66,112.05 39.16,110.28 C 41.01,96.88 45.88,84.85 52.61,73.79 C 55.17,75.56 58.07,74.88 59.61,72.71 C 75.86,54.31 97.89,45.16 124.61,45.16 C 149.71,45.16 171.91,55.91 189.29,73.47 C 191.95,76.59 193.91,76.67 197.6,74.42 C 204.93,86.26 208.28,98.24 208.98,110.39 C 203.84,111.81 201.28,113.19 202.92,118.61 C 206.51,128.99 207.92,137.93 207.92,148.73 C 207.92,162.11 204.8,174.71 202.84,182.71 C 201.92,186.23 204.31,186.91 210.79,186.99 H 213.91 C 225.87,186.61 235.39,180.64 239.49,169.05 C 244.83,155.26 245.08,138.01 241.66,125.01 Z\"/>\n <path d=\"M 124.71,70.81 C 79.63,70.81 47.49,107.12 47.49,148.72 C 47.49,169.16 56.41,188.19 73.71,200.61 L 73.96,200.77 C 77.43,177.81 84.16,162.21 95.29,145.42 C 92.04,137.09 91.71,130.87 92.62,120.83 C 93.81,111.23 96.08,107.12 102.19,107.68 C 110.04,108.87 117.98,116.18 126.22,124.96 C 139.89,124.05 157.81,131.25 178.33,139.09 C 183.11,140.86 183.72,142.63 182.97,148.33 C 179.45,160.93 170.86,166.63 158.11,174.05 C 143.09,183.07 141.13,199.42 153.88,220.09 L 153.96,221.01 L 154.71,221.17 C 181.31,208.43 201.34,181.01 201.34,148.72 C 201.34,108.15 169.29,70.81 124.71,70.81 Z\"/>\n </svg>\n <span class=\"text-base font-semibold text-content whitespace-nowrap\">Mongoose Studio</span>\n </router-link>\n </div>\n <!-- Center: Nav Links -->\n <nav class=\"flex items-stretch gap-6\">\n <a v-if=\"hasAccess(roles, 'root')\"\n href=\"#/\"\n class=\"inline-flex items-center px-1 border-b-2 text-sm font-medium\"\n :class=\"documentView ? 'text-content border-primary' : 'border-transparent text-content-tertiary hover:text-content'\">Documents</a>\n <span v-else class=\"inline-flex items-center px-1 border-b-2 border-transparent text-sm font-medium text-gray-300 cursor-not-allowed\" aria-disabled=\"true\">\n Documents\n <svg class=\"h-4 w-4 ml-1\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a v-if=\"hasAccess(roles, 'dashboards')\"\n href=\"#/dashboards\"\n class=\"inline-flex items-center px-1 border-b-2 text-sm font-medium\"\n :class=\"dashboardView ? 'text-content border-primary' : 'border-transparent text-content-tertiary hover:text-content'\">Dashboards</a>\n <span v-else class=\"inline-flex items-center px-1 border-b-2 border-transparent text-sm font-medium text-gray-300 cursor-not-allowed\">\n Dashboards\n <svg class=\"h-4 w-4 ml-1\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a v-if=\"hasAccess(roles, 'chat') && supportsAI\"\n href=\"#/chat\"\n class=\"inline-flex items-center px-1 border-b-2 text-sm font-medium\"\n :class=\"chatView ? 'text-content border-primary' : 'border-transparent text-content-tertiary hover:text-content'\">Chat</a>\n <span v-else-if=\"hasAccess(roles, 'chat') && !supportsAI\"\n class=\"inline-flex items-center px-1 border-b-2 border-transparent text-sm font-medium text-gray-300 cursor-not-allowed\"\n :title=\"chatDisabledReason\">\n Chat\n <svg class=\"h-4 w-4 ml-1\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <span v-else class=\"inline-flex items-center px-1 border-b-2 border-transparent text-sm font-medium text-gray-300 cursor-not-allowed\">\n Chat\n <svg class=\"h-4 w-4 ml-1\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a\n v-if=\"hasTaskVisualizer\"\n href=\"#/tasks\"\n class=\"inline-flex items-center px-1 border-b-2 text-sm font-medium\"\n :class=\"taskView ? 'text-content border-primary' : 'border-transparent text-content-tertiary hover:text-content'\">\n Tasks\n </a>\n <a\n href=\"https://studio.mongoosejs.io/docs\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"inline-flex items-center px-1 border-b-2 border-transparent text-sm font-medium text-content-tertiary hover:text-content\"\n >\n Docs\n </a>\n </nav>\n <!-- Right: Env Badge + User -->\n <div class=\"flex items-center justify-end gap-3 self-center\">\n <button\n type=\"button\"\n class=\"inline-flex items-center justify-center rounded-md p-2 text-content-tertiary hover:bg-muted hover:text-content-secondary\"\n title=\"Recent pages\"\n aria-label=\"Recent pages\"\n aria-haspopup=\"dialog\"\n :aria-expanded=\"showRecentPagesModal ? 'true' : 'false'\"\n @click=\"openRecentPagesModal\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"h-5 w-5\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n </button>\n <div\n v-if=\"!!state.nodeEnv\"\n title=\"NODE_ENV\"\n class=\"inline-flex items-center rounded px-2 py-1 text-xs text-content-tertiary bg-surface border border-edge gap-2\"\n >\n <span\n :class=\"warnEnv ? 'bg-red-400' : 'bg-yellow-400'\"\n class=\"inline-block rounded-full\"\n style=\"width: 0.5em; height: 0.5em;\"\n ></span>\n <span>{{state.nodeEnv}}</span>\n </div>\n <button\n v-if=\"!user || !hasAPIKey\"\n type=\"button\"\n @click=\"toggleDarkMode\"\n :title=\"darkMode ? 'Switch to light mode' : 'Switch to dark mode'\"\n class=\"inline-flex items-center justify-center rounded-md p-2 text-content-tertiary hover:text-content-secondary hover:bg-muted\"\n aria-label=\"Toggle dark mode\">\n <svg v-if=\"darkMode\" xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z\"/>\n </svg>\n <svg v-else xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z\"/>\n </svg>\n </button>\n <div class=\"flex items-center\" v-if=\"!user && hasAPIKey\">\n <button\n type=\"button\"\n @click=\"loginWithGithub\"\n class=\"rounded bg-primary px-2 py-2 text-sm font-semibold text-primary-text shadow-sm hover:bg-primary-hover focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\">\n Login\n </button>\n </div>\n <div v-if=\"user && hasAPIKey\" class=\"flex items-center relative\" v-clickOutside=\"hideFlyout\">\n <button type=\"button\" @click=\"showFlyout = !showFlyout\" class=\"relative flex rounded-full text-sm focus:outline-none focus:ring-2 focus:ring-gray-300\" id=\"user-menu-button\" aria-expanded=\"false\" aria-haspopup=\"true\">\n <span class=\"absolute -inset-1.5\"></span>\n <span class=\"sr-only\">Open user menu</span>\n <img class=\"size-8 rounded-full\" :src=\"user.picture\" alt=\"\">\n </button>\n\n <div\n v-if=\"showFlyout\"\n class=\"absolute right-0 top-[90%] w-48 origin-top-right rounded-md bg-surface py-1 shadow-lg ring-1 ring-black/5 focus:outline-none\"\n role=\"menu\"\n aria-orientation=\"vertical\"\n aria-labelledby=\"user-menu-button\"\n style=\"z-index: 10000\"\n tabindex=\"-1\">\n <button\n type=\"button\"\n @click=\"toggleDarkMode(); showFlyout = false\"\n class=\"w-full cursor-pointer block px-4 py-2 text-sm text-content-secondary hover:bg-primary-subtle text-left flex items-center gap-2\"\n role=\"menuitem\"\n tabindex=\"-1\">\n <svg v-if=\"darkMode\" xmlns=\"http://www.w3.org/2000/svg\" class=\"h-4 w-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z\"/></svg>\n <svg v-else xmlns=\"http://www.w3.org/2000/svg\" class=\"h-4 w-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z\"/></svg>\n {{ darkMode ? 'Light mode' : 'Dark mode' }}\n </button>\n <router-link to=\"/team\" v-if=\"hasAccess(roles, 'team')\" @click=\"showFlyout = false\" class=\"cursor-pointer block px-4 py-2 text-sm text-content-secondary hover:bg-primary-subtle\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">Team</router-link>\n <span v-else class=\"block px-4 py-2 text-sm text-gray-300 cursor-not-allowed\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">\n Team\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <router-link v-if=\"mcpEnabled\" to=\"/mcp\" @click=\"showFlyout = false\" class=\"cursor-pointer block px-4 py-2 text-sm text-content-secondary hover:bg-primary-subtle\" role=\"menuitem\" tabindex=\"-1\">MCP</router-link>\n <span v-else class=\"block px-4 py-2 text-sm text-gray-300 cursor-not-allowed\" role=\"menuitem\" title=\"MCP is disabled for this deployment\">\n MCP\n </span>\n <span @click=\"logout\" class=\"cursor-pointer block px-4 py-2 text-sm text-content-secondary hover:bg-primary-subtle\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">Sign out</span>\n </div>\n </div>\n </div>\n</div>\n<!-- Mobile navbar -->\n<div class=\"navbar w-full bg-page flex justify-between border-b border-edge !h-[55px] md:hidden\">\n <div class=\"flex items-center gap-2 pl-4\">\n <router-link class=\"flex items-center gap-2\" :to=\"{ name: defaultRoute }\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-8 text-primary\" viewBox=\"0 0 250 250\" fill=\"currentColor\" aria-label=\"Mongoose Studio Logo\">\n <path d=\"M 241.66,125.01 C 237.81,112.98 227.41,111.95 216.76,110.36 C 215.12,95.83 210.99,83.09 202.29,70.33 C 202.99,68.37 201.92,66.65 200.74,65.11 C 183.14,41.46 157.52,27 124.66,27 C 92.62,27 66.09,40.77 48.28,63.38 C 46.21,65.85 46.26,67.71 47.12,69.36 C 37.81,81.15 33.21,93.78 30.99,109.86 C 20.19,110.58 11.71,115.92 9.04,124.94 C 3.28,145.66 5.62,157.95 10.01,169.16 C 16.14,184.65 29.12,186.31 36.04,185.81 C 42.48,185.68 44.94,184.31 44.72,182.11 C 44.26,177.79 41.01,165.31 41.01,149.12 C 41.01,138.22 43.19,127.74 46.21,117.7 C 47.51,113.33 44.66,112.05 39.16,110.28 C 41.01,96.88 45.88,84.85 52.61,73.79 C 55.17,75.56 58.07,74.88 59.61,72.71 C 75.86,54.31 97.89,45.16 124.61,45.16 C 149.71,45.16 171.91,55.91 189.29,73.47 C 191.95,76.59 193.91,76.67 197.6,74.42 C 204.93,86.26 208.28,98.24 208.98,110.39 C 203.84,111.81 201.28,113.19 202.92,118.61 C 206.51,128.99 207.92,137.93 207.92,148.73 C 207.92,162.11 204.8,174.71 202.84,182.71 C 201.92,186.23 204.31,186.91 210.79,186.99 H 213.91 C 225.87,186.61 235.39,180.64 239.49,169.05 C 244.83,155.26 245.08,138.01 241.66,125.01 Z\"/>\n <path d=\"M 124.71,70.81 C 79.63,70.81 47.49,107.12 47.49,148.72 C 47.49,169.16 56.41,188.19 73.71,200.61 L 73.96,200.77 C 77.43,177.81 84.16,162.21 95.29,145.42 C 92.04,137.09 91.71,130.87 92.62,120.83 C 93.81,111.23 96.08,107.12 102.19,107.68 C 110.04,108.87 117.98,116.18 126.22,124.96 C 139.89,124.05 157.81,131.25 178.33,139.09 C 183.11,140.86 183.72,142.63 182.97,148.33 C 179.45,160.93 170.86,166.63 158.11,174.05 C 143.09,183.07 141.13,199.42 153.88,220.09 L 153.96,221.01 L 154.71,221.17 C 181.31,208.43 201.34,181.01 201.34,148.72 C 201.34,108.15 169.29,70.81 124.71,70.81 Z\"/>\n </svg>\n <span class=\"text-base font-semibold text-content\">Mongoose Studio</span>\n </router-link>\n </div>\n <div class=\"flex items-center gap-1 pr-2\">\n <button\n type=\"button\"\n class=\"rounded-md p-2 text-content-tertiary hover:bg-muted hover:text-content-secondary md:hidden\"\n title=\"Recent pages\"\n aria-label=\"Recent pages\"\n aria-haspopup=\"dialog\"\n :aria-expanded=\"showRecentPagesModal ? 'true' : 'false'\"\n @click=\"openRecentPagesModal\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"h-6 w-6\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n </button>\n <!-- Mobile menu toggle, controls the 'mobileMenuOpen' state. -->\n <button type=\"button\" id=\"open-mobile-menu\" class=\"-ml-2 rounded-md p-2 text-gray-400\">\n <span class=\"sr-only\">Open menu</span>\n <svg class=\"h-6 w-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5\" />\n </svg>\n </button>\n </div>\n\n <!-- Mobile menu mask -->\n <div id=\"mobile-menu-mask\" class=\"fixed inset-0 bg-black bg-opacity-40 z-40 hidden\"></div>\n <!-- Mobile menu drawer -->\n <div id=\"mobile-menu\" style=\"z-index: 100000\" class=\"fixed inset-0 bg-page shadow-lg transform translate-x-full transition-transform duration-200 ease-in-out flex flex-col\">\n <div class=\"flex items-center justify-between px-4 !h-[55px] border-b border-edge\">\n <router-link :to=\"{ name: defaultRoute }\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-[32px] text-primary\" viewBox=\"0 0 250 250\" fill=\"currentColor\" aria-label=\"Mongoose Studio Logo\">\n <path d=\"M 241.66,125.01 C 237.81,112.98 227.41,111.95 216.76,110.36 C 215.12,95.83 210.99,83.09 202.29,70.33 C 202.99,68.37 201.92,66.65 200.74,65.11 C 183.14,41.46 157.52,27 124.66,27 C 92.62,27 66.09,40.77 48.28,63.38 C 46.21,65.85 46.26,67.71 47.12,69.36 C 37.81,81.15 33.21,93.78 30.99,109.86 C 20.19,110.58 11.71,115.92 9.04,124.94 C 3.28,145.66 5.62,157.95 10.01,169.16 C 16.14,184.65 29.12,186.31 36.04,185.81 C 42.48,185.68 44.94,184.31 44.72,182.11 C 44.26,177.79 41.01,165.31 41.01,149.12 C 41.01,138.22 43.19,127.74 46.21,117.7 C 47.51,113.33 44.66,112.05 39.16,110.28 C 41.01,96.88 45.88,84.85 52.61,73.79 C 55.17,75.56 58.07,74.88 59.61,72.71 C 75.86,54.31 97.89,45.16 124.61,45.16 C 149.71,45.16 171.91,55.91 189.29,73.47 C 191.95,76.59 193.91,76.67 197.6,74.42 C 204.93,86.26 208.28,98.24 208.98,110.39 C 203.84,111.81 201.28,113.19 202.92,118.61 C 206.51,128.99 207.92,137.93 207.92,148.73 C 207.92,162.11 204.8,174.71 202.84,182.71 C 201.92,186.23 204.31,186.91 210.79,186.99 H 213.91 C 225.87,186.61 235.39,180.64 239.49,169.05 C 244.83,155.26 245.08,138.01 241.66,125.01 Z\"/>\n <path d=\"M 124.71,70.81 C 79.63,70.81 47.49,107.12 47.49,148.72 C 47.49,169.16 56.41,188.19 73.71,200.61 L 73.96,200.77 C 77.43,177.81 84.16,162.21 95.29,145.42 C 92.04,137.09 91.71,130.87 92.62,120.83 C 93.81,111.23 96.08,107.12 102.19,107.68 C 110.04,108.87 117.98,116.18 126.22,124.96 C 139.89,124.05 157.81,131.25 178.33,139.09 C 183.11,140.86 183.72,142.63 182.97,148.33 C 179.45,160.93 170.86,166.63 158.11,174.05 C 143.09,183.07 141.13,199.42 153.88,220.09 L 153.96,221.01 L 154.71,221.17 C 181.31,208.43 201.34,181.01 201.34,148.72 C 201.34,108.15 169.29,70.81 124.71,70.81 Z\"/>\n </svg>\n </router-link>\n <button type=\"button\" id=\"close-mobile-menu\" class=\"text-gray-400 p-2 rounded-md\">\n <span class=\"sr-only\">Close menu</span>\n <svg class=\"h-6 w-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n <nav class=\"flex-1 px-4 py-4 space-y-2\">\n <div class=\"flex items-center gap-2 px-3 py-2\" v-if=\"!user || !hasAPIKey\">\n <button\n type=\"button\"\n @click=\"toggleDarkMode\"\n class=\"inline-flex items-center gap-2 rounded-md px-3 py-2 text-base font-medium text-content-secondary hover:bg-muted\"\n aria-label=\"Toggle dark mode\">\n <svg v-if=\"darkMode\" xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z\"/></svg>\n <svg v-else xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z\"/></svg>\n <span>{{ darkMode ? 'Light mode' : 'Dark mode' }}</span>\n </button>\n </div>\n <a v-if=\"hasAccess(roles, 'root')\"\n href=\"#/\"\n class=\"block px-3 py-2 rounded-md text-base font-medium\"\n :class=\"documentView ? 'text-content bg-primary-subtle' : 'text-content-secondary hover:bg-muted'\">Documents</a>\n <span v-else class=\"block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed\">\n Documents\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a v-if=\"hasAccess(roles, 'dashboards')\"\n href=\"#/dashboards\"\n class=\"block px-3 py-2 rounded-md text-base font-medium\"\n :class=\"dashboardView ? 'text-content bg-primary-subtle' : 'text-content-secondary hover:bg-muted'\">Dashboards</a>\n <span v-else class=\"block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed\">\n Dashboards\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a v-if=\"hasAccess(roles, 'chat') && supportsAI\"\n href=\"#/chat\"\n class=\"block px-3 py-2 rounded-md text-base font-medium\"\n :class=\"chatView ? 'text-content bg-primary-subtle' : 'text-content-secondary hover:bg-muted'\">Chat</a>\n <span v-else-if=\"hasAccess(roles, 'chat') && !supportsAI\"\n class=\"block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed\"\n :title=\"chatDisabledReason\">\n Chat\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <span v-else class=\"block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed\">\n Chat\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a v-if=\"hasTaskVisualizer\"\n href=\"#/tasks\"\n class=\"block px-3 py-2 rounded-md text-base font-medium\"\n :class=\"taskView ? 'text-content bg-primary-subtle' : 'text-content-secondary hover:bg-muted'\">Tasks</a>\n <div v-if=\"!user && hasAPIKey\" class=\"mt-4\">\n <button\n type=\"button\"\n @click=\"loginWithGithub\"\n class=\"w-full rounded bg-muted text-content px-3 py-2 text-base font-semibold shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\">\n Login\n </button>\n </div>\n <div v-if=\"user && hasAPIKey\" class=\"mt-4\">\n <div class=\"flex items-center gap-3 px-3 py-2 bg-page rounded-md\">\n <img class=\"size-8 rounded-full\" :src=\"user.picture\" alt=\"\">\n <span class=\"text-content font-medium\">{{ user.name }}</span>\n </div>\n <div class=\"mt-2 space-y-1\">\n <button\n type=\"button\"\n @click=\"toggleDarkMode\"\n class=\"w-full inline-flex items-center gap-2 px-3 py-2 rounded-md text-base text-content-secondary hover:bg-primary-subtle text-left\">\n <svg v-if=\"darkMode\" xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z\"/></svg>\n <svg v-else xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path d=\"M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z\"/></svg>\n {{ darkMode ? 'Light mode' : 'Dark mode' }}\n </button>\n <router-link to=\"/team\" v-if=\"hasAccess(roles, 'team')\" class=\"block px-3 py-2 rounded-md text-base text-content-secondary hover:bg-primary-subtle\">Team</router-link>\n <span v-else class=\"block px-3 py-2 rounded-md text-base text-gray-300 cursor-not-allowed\">\n Team\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <router-link v-if=\"mcpEnabled\" to=\"/mcp\" class=\"block px-3 py-2 rounded-md text-base text-content-secondary hover:bg-primary-subtle\">MCP</router-link>\n <span v-else class=\"block px-3 py-2 rounded-md text-base text-gray-300 cursor-not-allowed\" title=\"MCP is disabled for this deployment\">\n MCP\n </span>\n <span @click=\"logout\" class=\"block px-3 py-2 rounded-md text-base text-content-secondary hover:bg-primary-subtle cursor-pointer\">Sign out</span>\n </div>\n </div>\n </nav>\n </div>\n</div>\n\n<modal\n v-if=\"showRecentPagesModal\"\n flush-container\n containerClass=\"!max-w-md !w-[min(94vw,28rem)] !overflow-hidden !rounded-lg !border !border-edge !bg-surface !shadow-xl dark:!bg-shark-900 text-content\"\n bodyClass=\"modal-recent-pages-body !p-0\"\n>\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"closeRecentPagesModal\" role=\"button\" aria-label=\"Close recent pages\">×</div>\n <div\n class=\"shrink-0 flex items-center gap-3 border-b border-edge bg-surface px-4 py-4 pr-12 dark:bg-shark-900\"\n >\n <h2 class=\"m-0 text-lg font-semibold text-content\">Recent pages</h2>\n <button\n type=\"button\"\n class=\"rounded px-2 py-1 text-sm font-medium text-content-secondary hover:bg-muted disabled:opacity-50\"\n @click=\"clearRecentPagesHistory\"\n :disabled=\"recentPagesList.length === 0\"\n >\n Clear\n </button>\n </div>\n <div class=\"modal-recent-pages-scroll\">\n <div\n v-if=\"recentPagesList.length === 0\"\n class=\"m-4 rounded border border-dashed border-edge px-3 py-6 text-center text-sm text-content-tertiary\"\n >\n No recent pages yet.\n </div>\n <button\n v-for=\"entry in recentPagesList\"\n :key=\"entry.path + '-' + entry.visitedAt\"\n type=\"button\"\n class=\"w-full px-4 py-2.5 text-left hover:bg-muted\"\n :class=\"entry.path === $route.fullPath ? 'bg-primary-subtle' : ''\"\n @click=\"goToRecentPage(entry)\"\n >\n <div class=\"truncate text-sm font-medium text-content\">{{ entry.label }}</div>\n <div class=\"truncate font-mono text-xs text-content-tertiary\">{{ entry.path }}</div>\n </button>\n </div>\n </template>\n</modal>\n</div>\n";
|
|
54653
55035
|
|
|
54654
55036
|
/***/ },
|
|
54655
55037
|
|
|
@@ -54664,6 +55046,17 @@ module.exports = "<modal v-if=\"show\" containerClass=\"!max-w-md\">\n <templat
|
|
|
54664
55046
|
|
|
54665
55047
|
/***/ },
|
|
54666
55048
|
|
|
55049
|
+
/***/ "./frontend/src/script/script.html"
|
|
55050
|
+
/*!*****************************************!*\
|
|
55051
|
+
!*** ./frontend/src/script/script.html ***!
|
|
55052
|
+
\*****************************************/
|
|
55053
|
+
(module) {
|
|
55054
|
+
|
|
55055
|
+
"use strict";
|
|
55056
|
+
module.exports = "<div class=\"px-4 py-6\">\n <div v-if=\"status === 'loading'\" class=\"max-w-5xl mx-auto text-center\">\n <img src=\"images/loader.gif\" class=\"inline mt-10\" alt=\"Loading script\">\n </div>\n\n <div v-else-if=\"script\" class=\"max-w-5xl mx-auto\">\n <div class=\"flex items-center justify-between mb-4\">\n <div>\n <h1 class=\"text-xl font-semibold text-content\">Script</h1>\n <p class=\"text-xs text-content-tertiary font-mono\">{{ script._id }}</p>\n </div>\n <div class=\"flex items-center\">\n <button\n v-if=\"!isEditing\"\n class=\"px-3 py-1.5 mr-2 text-sm bg-gray-700 text-white rounded hover:bg-gray-600\"\n @click=\"startEditing\">\n Edit\n </button>\n <div class=\"relative flex items-center\">\n <async-button\n class=\"px-3 py-1.5 text-sm bg-primary hover:bg-primary-hover text-primary-text rounded-l-md\"\n @click=\"executeScript\">\n {{ selectedRunLabel }}\n </async-button>\n <button\n class=\"px-1.5 py-1.5 text-sm bg-primary hover:bg-primary-hover text-primary-text border-l border-black/10 rounded-r-md\"\n @click.stop=\"showRunDropdown = !showRunDropdown\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <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\" />\n </svg>\n </button>\n <div\n v-if=\"showRunDropdown\"\n class=\"absolute right-0 top-full z-10 mt-1 w-40 rounded-md bg-surface py-1 shadow-lg ring-1 ring-black/5\">\n <button class=\"block w-full px-4 py-2 text-left text-xs text-content-secondary hover:bg-muted\" @click=\"selectRunMode('run')\">\n Run\n </button>\n <button\n class=\"block w-full px-4 py-2 text-left text-xs\"\n :class=\"canUseDryRun ? 'text-content-secondary hover:bg-muted' : 'cursor-not-allowed text-gray-400'\"\n :disabled=\"!canUseDryRun\"\n :title=\"canUseDryRun ? null : 'Dry run mode requires MongoDB transaction support'\"\n @click=\"selectRunMode('dryRun')\">\n Dry Run\n </button>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"relative border rounded bg-surface text-content text-sm overflow-hidden\">\n <div class=\"flex border-b py-1 pl-1 text-xs font-medium bg-surface\">\n <button\n class=\"px-4 py-1 rounded-l-md border-r border-edge-strong font-semibold\"\n :class=\"activeTab === 'code' ? 'bg-gray-700 text-white shadow' : 'bg-muted text-gray-600'\"\n @click=\"activeTab = 'code'\">\n Code\n </button>\n <button\n class=\"px-4 py-1 rounded-r-md font-semibold\"\n :class=\"activeTab === 'output' ? 'bg-gray-700 text-white shadow' : 'bg-muted text-gray-600'\"\n @click=\"activeTab = 'output'\">\n Output<span v-if=\"isDryRunResult\" class=\"ml-1\">[Dry Run]</span>\n </button>\n </div>\n\n <div v-show=\"activeTab === 'code'\" class=\"max-h-[65vh] overflow-y-auto\">\n <div v-if=\"isEditing\" class=\"flex flex-col\">\n <ace-editor\n v-model=\"editedScript\"\n mode=\"javascript\"\n :line-numbers=\"true\"\n class=\"w-full h-[55vh] min-h-[300px]\"\n />\n <div class=\"flex justify-end p-2 border-t border-edge\">\n <button class=\"px-3 py-1.5 text-xs bg-gray-300 text-gray-800 rounded hover:bg-gray-400\" @click=\"cancelEditing\">\n Cancel\n </button>\n </div>\n </div>\n <pre v-else class=\"whitespace-pre-wrap !my-0 bg-muted\"><code ref=\"code\" class=\"language-javascript\" v-text=\"script.script\"></code></pre>\n </div>\n\n <div v-show=\"activeTab === 'output'\" class=\"p-3 max-h-[65vh] overflow-y-auto border-t\">\n <div v-if=\"script.executionResult?.error\" class=\"rounded-md bg-red-50 p-4 mb-3 text-sm text-red-800\">\n {{ script.executionResult.error }}\n </div>\n <dashboard-result\n v-if=\"script.executionResult?.output != null\"\n :result=\"script.executionResult.output\">\n </dashboard-result>\n <pre v-else-if=\"!script.executionResult?.error\">No output</pre>\n\n <div v-if=\"script.executionResult?.logs\" class=\"mt-3 pt-3 border-t border-edge\">\n <div class=\"text-xs font-semibold text-gray-600 uppercase tracking-wide\">Console</div>\n <pre class=\"mt-1 bg-muted text-content p-3 rounded whitespace-pre-wrap overflow-x-auto max-h-[280px]\">{{ script.executionResult.logs }}</pre>\n </div>\n </div>\n </div>\n </div>\n\n <div v-else class=\"max-w-5xl mx-auto text-content-secondary\">\n No script with the given id could be found.\n </div>\n</div>\n";
|
|
55057
|
+
|
|
55058
|
+
/***/ },
|
|
55059
|
+
|
|
54667
55060
|
/***/ "./frontend/src/splash/splash.html"
|
|
54668
55061
|
/*!*****************************************!*\
|
|
54669
55062
|
!*** ./frontend/src/splash/splash.html ***!
|
|
@@ -60234,7 +60627,7 @@ exports.validatorErrorSymbol = Symbol('mongoose#validatorError');
|
|
|
60234
60627
|
|
|
60235
60628
|
|
|
60236
60629
|
|
|
60237
|
-
const ObjectId = (__webpack_require__(/*! mongodb/lib/bson */ "./node_modules/mongodb/lib/bson.js").ObjectId);
|
|
60630
|
+
const ObjectId = (__webpack_require__(/*! mongodb/lib/bson */ "./node_modules/mongoose/node_modules/mongodb/lib/bson.js").ObjectId);
|
|
60238
60631
|
const objectIdSymbol = (__webpack_require__(/*! ../helpers/symbols */ "./node_modules/mongoose/lib/helpers/symbols.js").objectIdSymbol);
|
|
60239
60632
|
|
|
60240
60633
|
/**
|
|
@@ -66262,7 +66655,7 @@ var src_default = VueToastificationPlugin;
|
|
|
66262
66655
|
(module) {
|
|
66263
66656
|
|
|
66264
66657
|
"use strict";
|
|
66265
|
-
module.exports = /*#__PURE__*/JSON.parse('{"name":"@mongoosejs/studio","version":"0.
|
|
66658
|
+
module.exports = /*#__PURE__*/JSON.parse('{"name":"@mongoosejs/studio","version":"0.6.0","description":"AI-Powered Data Workspace for MongoDB: Turn your MongoDB data into dashboards, maps, and interactive workflows - powered by your Mongoose models and AI.","homepage":"https://mongoosestudio.app/","repository":{"type":"git","url":"https://github.com/mongoosejs/studio"},"license":"Apache-2.0","dependencies":{"@ai-sdk/anthropic":"2.x","@ai-sdk/google":"2.x","@ai-sdk/openai":"2.x","@modelcontextprotocol/sdk":"^1.30.1","ace-builds":"^1.43.6","ai":"5.x","archetype":"0.13.1","csv-stringify":"6.3.0","ejson":"^2.2.3","extrovert":"^0.2.1","marked":"15.0.12","mpath":"^0.9.0","node-inspect-extracted":"3.x","regexp.escape":"^2.0.1","tailwindcss":"3.4.0","time-commando":"1.0.1","typescript":"^6.0.2","vue":"3.x","vue-toastification":"^2.0.0-rc.5","webpack":"5.x","xss":"^1.0.15","zod":"^4.6.5"},"peerDependencies":{"@nestjs/common":"10.x || 11.x","mongoose":"7.x || 8.x || ^9.0.0"},"peerDependenciesMeta":{"@nestjs/common":{"optional":true}},"optionalPeerDependencies":{"@mongoosejs/task":"0.5.x || 0.6.x"},"devDependencies":{"@masteringjs/eslint-config":"0.1.1","axios":"1.2.2","dedent":"^1.6.0","eslint":"9.30.0","@nestjs/common":"^11.1.9","express":"4.x","mocha":"10.2.0","mongodb-memory-server":"^11.0.1","mongoose":"9.x","sinon":"^21.0.1"},"scripts":{"lint":"eslint .","seed":"node seed/index.js","start":"node ./local.js","tailwind":"tailwindcss -o ./frontend/public/tw.css","tailwind:watch":"tailwindcss -o ./frontend/public/tw.css --watch","test":"mocha test/*.test.js","test:frontend":"mocha test/frontend/*.test.js","eval:agent":"node eval/agent/run.js"}}');
|
|
66266
66659
|
|
|
66267
66660
|
/***/ }
|
|
66268
66661
|
|