@mongoosejs/studio 0.1.11 → 0.1.12

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/README.md CHANGED
@@ -34,8 +34,10 @@ If you have a Mongoose Studio Pro API key, you can set it as follows:
34
34
  const opts = process.env.MONGOOSE_STUDIO_API_KEY ? { apiKey: process.env.MONGOOSE_STUDIO_API_KEY } : {};
35
35
  // Optionally specify which ChatGPT model to use for chat messages
36
36
  opts.model = 'gpt-4o-mini';
37
- // Provide your own OpenAI API key to run chat completions locally
37
+ // Provide your own OpenAI, Anthropic, or Google Gemini API key to run chat completions locally
38
38
  opts.openAIAPIKey = process.env.OPENAI_API_KEY;
39
+ opts.anthropicAPIKey = process.env.ANTHROPIC_API_KEY;
40
+ opts.googleGeminiAPIKey = process.env.GOOGLE_GEMINI_API_KEY;
39
41
 
40
42
  // Mount Mongoose Studio on '/studio'
41
43
  app.use('/studio', await studio('/studio/api', mongoose, opts));
@@ -88,8 +90,10 @@ const opts = {
88
90
  apiKey: process.env.MONGOOSE_STUDIO_API_KEY,
89
91
  // Optionally specify which ChatGPT model to use for chat messages
90
92
  model: 'gpt-4o-mini',
91
- // Provide your own OpenAI API key to run chat completions locally
92
- openAIAPIKey: process.env.OPENAI_API_KEY
93
+ // Provide your own OpenAI, Anthropic, or Google Gemini API key to run chat completions locally
94
+ openAIAPIKey: process.env.OPENAI_API_KEY,
95
+ anthropicAPIKey: process.env.ANTHROPIC_API_KEY,
96
+ googleGeminiAPIKey: process.env.GOOGLE_GEMINI_API_KEY
93
97
  };
94
98
  console.log('Creating Mongoose studio', opts);
95
99
  require('@mongoosejs/studio/frontend')(`/.netlify/functions/studio`, true, opts).then(() => {
@@ -108,7 +112,9 @@ const mongoose = require('mongoose');
108
112
  const handler = require('@mongoosejs/studio/backend/netlify')({
109
113
  apiKey: process.env.MONGOOSE_STUDIO_API_KEY,
110
114
  model: 'gpt-4o-mini',
111
- openAIAPIKey: process.env.OPENAI_API_KEY
115
+ openAIAPIKey: process.env.OPENAI_API_KEY,
116
+ anthropicAPIKey: process.env.ANTHROPIC_API_KEY,
117
+ googleGeminiAPIKey: process.env.GOOGLE_GEMINI_API_KEY
112
118
  }).handler;
113
119
 
114
120
  let conn = null;
@@ -1,22 +1,44 @@
1
1
  'use strict';
2
2
 
3
3
  const { createAnthropic } = require('@ai-sdk/anthropic');
4
+ const { createGoogleGenerativeAI } = require('@ai-sdk/google');
4
5
  const { createOpenAI } = require('@ai-sdk/openai');
5
6
  const { generateText } = require('ai');
6
7
 
7
8
  module.exports = async function callLLM(messages, system, options) {
8
9
  let provider = null;
9
10
  let model = null;
10
- if (options?.openAIAPIKey && options?.anthropicAPIKey) {
11
- throw new Error('Cannot set both OpenAI and Anthropic API keys');
12
- }
11
+ const providers = [];
13
12
 
14
13
  if (options?.openAIAPIKey) {
15
- provider = createOpenAI({ apiKey: options.openAIAPIKey });
16
- model = options?.model ?? 'gpt-4o-mini';
17
- } else if (options?.anthropicAPIKey) {
18
- provider = createAnthropic({ apiKey: options.anthropicAPIKey });
19
- model = options?.model ?? 'claude-haiku-4-5-20251001';
14
+ providers.push({
15
+ provider: createOpenAI({ apiKey: options.openAIAPIKey }),
16
+ model: options?.model ?? 'gpt-4o-mini'
17
+ });
18
+ }
19
+
20
+ if (options?.anthropicAPIKey) {
21
+ providers.push({
22
+ provider: createAnthropic({ apiKey: options.anthropicAPIKey }),
23
+ model: options?.model ?? 'claude-haiku-4-5-20251001'
24
+ });
25
+ }
26
+
27
+ if (options?.googleGeminiAPIKey) {
28
+ providers.push({
29
+ provider: createGoogleGenerativeAI({ apiKey: options.googleGeminiAPIKey }),
30
+ model: options?.model ?? 'gemini-2.5-flash'
31
+ });
32
+ }
33
+
34
+ if (providers.length > 1) {
35
+ throw new Error('Cannot set multiple LLM API keys');
36
+ }
37
+
38
+ if (providers.length > 0) {
39
+ const selected = providers[0];
40
+ provider = selected.provider;
41
+ model = selected.model;
20
42
  }
21
43
 
22
44
  if (provider) {
@@ -1,37 +1,66 @@
1
1
  'use strict';
2
2
 
3
3
  const { createAnthropic } = require('@ai-sdk/anthropic');
4
+ const { createGoogleGenerativeAI } = require('@ai-sdk/google');
4
5
  const { createOpenAI } = require('@ai-sdk/openai');
5
6
  const { streamText } = require('ai');
6
7
 
7
8
  module.exports = async function* streamLLM(messages, system, options) {
8
9
  let provider = null;
9
10
  let model = null;
10
- if (options?.openAIAPIKey && options?.anthropicAPIKey) {
11
- throw new Error('Cannot set both OpenAI and Anthropic API keys');
12
- }
11
+ const providers = [];
13
12
 
14
13
  if (options?.openAIAPIKey) {
15
- provider = createOpenAI({ apiKey: options.openAIAPIKey });
16
- model = options?.model ?? 'gpt-4o-mini';
17
- } else if (options?.anthropicAPIKey) {
18
- provider = createAnthropic({ apiKey: options.anthropicAPIKey });
19
- model = options?.model ?? 'claude-haiku-4-5-20251001';
14
+ providers.push({
15
+ provider: createOpenAI({ apiKey: options.openAIAPIKey }),
16
+ model: options?.model ?? 'gpt-4o-mini'
17
+ });
18
+ }
19
+
20
+ if (options?.anthropicAPIKey) {
21
+ providers.push({
22
+ provider: createAnthropic({ apiKey: options.anthropicAPIKey }),
23
+ model: options?.model ?? 'claude-haiku-4-5-20251001'
24
+ });
25
+ }
26
+
27
+ if (options?.googleGeminiAPIKey) {
28
+ providers.push({
29
+ provider: createGoogleGenerativeAI({ apiKey: options.googleGeminiAPIKey }),
30
+ model: options?.model ?? 'gemini-2.5-flash'
31
+ });
32
+ }
33
+
34
+ if (providers.length > 1) {
35
+ throw new Error('Cannot set multiple LLM API keys');
36
+ }
37
+
38
+ if (providers.length > 0) {
39
+ const selected = providers[0];
40
+ provider = selected.provider;
41
+ model = selected.model;
20
42
  }
21
43
 
22
44
  if (provider) {
45
+ let error = null;
23
46
  const { textStream } = streamText({
24
47
  model: provider(model),
25
48
  system,
26
- messages
49
+ messages,
50
+ onError(err) {
51
+ error = err.error;
52
+ }
27
53
  });
28
54
  for await (const chunk of textStream) {
29
55
  yield chunk;
30
56
  }
57
+ if (error) {
58
+ throw error;
59
+ }
31
60
  return;
32
61
  }
33
62
 
34
- // If not using OpenAI or Anthropic, fallback to Mongoose (no streaming)
63
+ // If not using OpenAI, Anthropic, or Google Gemini, fallback to Mongoose (no streaming)
35
64
  const headers = { 'Content-Type': 'application/json' };
36
65
  const response = await fetch('https://mongoose-js.netlify.app/.netlify/functions/getChatCompletion', {
37
66
  method: 'POST',
@@ -436,9 +436,9 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
436
436
  }
437
437
  if (data) {
438
438
  try {
439
- yield JSON.parse(data);
439
+ const res = JSON.parse(data);
440
+ yield res;
440
441
  } catch (err) {
441
- // If not JSON, yield as string
442
442
  yield data;
443
443
  }
444
444
  }
@@ -1105,6 +1105,8 @@ module.exports = app => app.component('chat', {
1105
1105
  }
1106
1106
  });
1107
1107
  }
1108
+ } else if (event.message) {
1109
+ throw new Error(event.message);
1108
1110
  }
1109
1111
  }
1110
1112
 
@@ -16937,7 +16939,7 @@ module.exports = function stringToParts(str) {
16937
16939
  /***/ ((module) => {
16938
16940
 
16939
16941
  "use strict";
16940
- module.exports = /*#__PURE__*/JSON.parse('{"name":"@mongoosejs/studio","version":"0.1.11","description":"A sleek, powerful MongoDB UI with built-in dashboarding and auth, seamlessly integrated with your Express, Vercel, or Netlify app.","homepage":"https://studio.mongoosejs.io/","repository":{"type":"git","url":"https://github.com/mongoosejs/studio"},"license":"Apache-2.0","dependencies":{"@ai-sdk/openai":"2.x","@ai-sdk/anthropic":"2.x","ai":"5.x","archetype":"0.13.1","csv-stringify":"6.3.0","ejson":"^2.2.3","extrovert":"^0.2.0","marked":"15.0.12","node-inspect-extracted":"3.x","tailwindcss":"3.4.0","vanillatoasts":"^1.6.0","vue":"3.x","webpack":"5.x"},"peerDependencies":{"mongoose":"7.x || 8.x || ^9.0.0"},"devDependencies":{"@masteringjs/eslint-config":"0.1.1","axios":"1.2.2","dedent":"^1.6.0","eslint":"9.30.0","express":"4.x","mocha":"10.2.0","mongoose":"9.x"},"scripts":{"lint":"eslint .","tailwind":"tailwindcss -o ./frontend/public/tw.css","tailwind:watch":"tailwindcss -o ./frontend/public/tw.css --watch","test":"mocha test/*.test.js"}}');
16942
+ module.exports = /*#__PURE__*/JSON.parse('{"name":"@mongoosejs/studio","version":"0.1.12","description":"A sleek, powerful MongoDB UI with built-in dashboarding and auth, seamlessly integrated with your Express, Vercel, or Netlify app.","homepage":"https://studio.mongoosejs.io/","repository":{"type":"git","url":"https://github.com/mongoosejs/studio"},"license":"Apache-2.0","dependencies":{"@ai-sdk/google":"2.x","@ai-sdk/openai":"2.x","@ai-sdk/anthropic":"2.x","ai":"5.x","archetype":"0.13.1","csv-stringify":"6.3.0","ejson":"^2.2.3","extrovert":"^0.2.0","marked":"15.0.12","node-inspect-extracted":"3.x","tailwindcss":"3.4.0","vanillatoasts":"^1.6.0","vue":"3.x","webpack":"5.x"},"peerDependencies":{"mongoose":"7.x || 8.x || ^9.0.0"},"devDependencies":{"@masteringjs/eslint-config":"0.1.1","axios":"1.2.2","dedent":"^1.6.0","eslint":"9.30.0","express":"4.x","mocha":"10.2.0","mongoose":"9.x"},"scripts":{"lint":"eslint .","tailwind":"tailwindcss -o ./frontend/public/tw.css","tailwind:watch":"tailwindcss -o ./frontend/public/tw.css --watch","test":"mocha test/*.test.js"}}');
16941
16943
 
16942
16944
  /***/ })
16943
16945
 
@@ -225,9 +225,9 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
225
225
  }
226
226
  if (data) {
227
227
  try {
228
- yield JSON.parse(data);
228
+ const res = JSON.parse(data);
229
+ yield res;
229
230
  } catch (err) {
230
- // If not JSON, yield as string
231
231
  yield data;
232
232
  }
233
233
  }
@@ -80,6 +80,8 @@ module.exports = app => app.component('chat', {
80
80
  }
81
81
  });
82
82
  }
83
+ } else if (event.message) {
84
+ throw new Error(event.message);
83
85
  }
84
86
  }
85
87
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mongoosejs/studio",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "A sleek, powerful MongoDB UI with built-in dashboarding and auth, seamlessly integrated with your Express, Vercel, or Netlify app.",
5
5
  "homepage": "https://studio.mongoosejs.io/",
6
6
  "repository": {
@@ -9,6 +9,7 @@
9
9
  },
10
10
  "license": "Apache-2.0",
11
11
  "dependencies": {
12
+ "@ai-sdk/google": "2.x",
12
13
  "@ai-sdk/openai": "2.x",
13
14
  "@ai-sdk/anthropic": "2.x",
14
15
  "ai": "5.x",