@lovable.dev/mcp-js 0.15.0 → 0.16.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/dist/{chunk-QC3DXQTH.js → chunk-DCWYK4CA.js} +34 -0
- package/dist/{chunk-RHDEW56Y.js → chunk-EZQVUNXB.js} +20 -11
- package/dist/{chunk-G4XA7IJM.js → chunk-H6BKTNJY.js} +199 -2
- package/dist/{chunk-VNRQPA4K.js → chunk-I5CAQUQI.js} +4 -3
- package/dist/{chunk-P3F324UC.js → chunk-MA5H6PSF.js} +0 -34
- package/dist/{chunk-LWHVXXKQ.js → chunk-SKSKC747.js} +1 -1
- package/dist/{chunk-QDKOF4UF.js → chunk-T24Z753F.js} +2 -2
- package/dist/{chunk-T2RED2TG.js → chunk-W2EZWPJ5.js} +19 -10
- package/dist/cli/extract-manifest.cjs +1 -1
- package/dist/cli/extract-manifest.js +4 -4
- package/dist/index.js +4 -4
- package/dist/protocols/mcp/index.cjs +239 -213
- package/dist/protocols/mcp/index.d.cts +1 -1
- package/dist/protocols/mcp/index.d.ts +1 -1
- package/dist/protocols/mcp/index.js +5 -6
- package/dist/protocols/oauth-metadata.js +4 -3
- package/dist/protocols/rest/index.cjs +241 -215
- package/dist/protocols/rest/index.d.cts +2 -2
- package/dist/protocols/rest/index.d.ts +2 -2
- package/dist/protocols/rest/index.js +6 -7
- package/dist/{recorder-B-eJU4Qu.d.ts → recorder-qlzUKFxG.d.ts} +3 -3
- package/dist/stacks/supabase/index.cjs +55 -19
- package/dist/stacks/supabase/index.js +10 -12
- package/dist/stacks/supabase/vite.cjs +28 -4
- package/dist/stacks/supabase/vite.js +28 -4
- package/dist/stacks/tanstack/index.cjs +255 -219
- package/dist/stacks/tanstack/index.js +8 -9
- package/package.json +1 -1
- package/dist/chunk-XQSTN54Y.js +0 -189
|
@@ -169,7 +169,7 @@ function resolveMetricsConfig(config = true) {
|
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
// package.json
|
|
172
|
-
var version = "0.
|
|
172
|
+
var version = "0.16.0";
|
|
173
173
|
|
|
174
174
|
// src/metrics/otlp.ts
|
|
175
175
|
var SCOPE_NAME = "@lovable.dev/mcp-js";
|
|
@@ -234,6 +234,10 @@ function nowUnixNano() {
|
|
|
234
234
|
function nowMs() {
|
|
235
235
|
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
236
236
|
}
|
|
237
|
+
function reportInvocation(recorder, ev) {
|
|
238
|
+
log.info("tool.invoked", { tool: ev.tool, method: ev.method, outcome: ev.outcome, durationMs: ev.durationMs });
|
|
239
|
+
recorder.record(ev);
|
|
240
|
+
}
|
|
237
241
|
var NOOP_RECORDER = {
|
|
238
242
|
record() {
|
|
239
243
|
},
|
|
@@ -270,12 +274,14 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
270
274
|
if (!config.enabled)
|
|
271
275
|
return NOOP_RECORDER;
|
|
272
276
|
const doFetch = deps.fetch ?? globalThis.fetch;
|
|
273
|
-
if (!doFetch)
|
|
277
|
+
if (!doFetch) {
|
|
278
|
+
log.warn("metrics.disabled_no_fetch", { endpoint: config.endpoint });
|
|
274
279
|
return NOOP_RECORDER;
|
|
280
|
+
}
|
|
275
281
|
const usesLovableEndpoint = config.endpoint === DEFAULT_METRICS_ENDPOINT;
|
|
276
282
|
const apiKey = usesLovableEndpoint ? (deps.getApiKey ?? (() => readRuntimeEnv(config.apiKeyEnvVar)))() : void 0;
|
|
277
283
|
if (usesLovableEndpoint && !apiKey) {
|
|
278
|
-
log.
|
|
284
|
+
log.warn("metrics.disabled_no_api_key", { envVar: config.apiKeyEnvVar, endpoint: config.endpoint });
|
|
279
285
|
return NOOP_RECORDER;
|
|
280
286
|
}
|
|
281
287
|
const waitUntil = deps.waitUntil ?? probeWaitUntil();
|
|
@@ -286,7 +292,8 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
286
292
|
try {
|
|
287
293
|
waitUntil(p);
|
|
288
294
|
return;
|
|
289
|
-
} catch {
|
|
295
|
+
} catch (err) {
|
|
296
|
+
log.warn("metrics.wait_until_failed", describeError(err));
|
|
290
297
|
}
|
|
291
298
|
}
|
|
292
299
|
void p.catch(() => {
|
|
@@ -306,6 +313,7 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
306
313
|
if (buffer.length === 0)
|
|
307
314
|
return;
|
|
308
315
|
const records = buffer.splice(0, buffer.length);
|
|
316
|
+
const dropped = records.length;
|
|
309
317
|
try {
|
|
310
318
|
const res = await doFetch(config.endpoint, {
|
|
311
319
|
method: "POST",
|
|
@@ -313,10 +321,11 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
313
321
|
body: buildLogsPayload(records, server),
|
|
314
322
|
keepalive: true
|
|
315
323
|
});
|
|
316
|
-
if (!res.ok)
|
|
317
|
-
log.
|
|
324
|
+
if (!res.ok) {
|
|
325
|
+
log.warn("metrics.flush_rejected", { status: res.status, dropped, endpoint: config.endpoint });
|
|
326
|
+
}
|
|
318
327
|
} catch (err) {
|
|
319
|
-
log.
|
|
328
|
+
log.warn("metrics.flush_failed", { ...describeError(err), dropped, endpoint: config.endpoint });
|
|
320
329
|
}
|
|
321
330
|
};
|
|
322
331
|
const ensureTimer = () => {
|
|
@@ -740,12 +749,13 @@ function assertRequiredScopes(auth, context) {
|
|
|
740
749
|
throw new OAuthTokenError(403, "insufficient_scope", "Additional OAuth scope is required");
|
|
741
750
|
}
|
|
742
751
|
}
|
|
743
|
-
function createRequestAuthorizer(mcp, options = {}) {
|
|
752
|
+
function createRequestAuthorizer(mcp, options = {}, recorder) {
|
|
744
753
|
const runtime = getOAuthRuntime(mcp, options);
|
|
745
754
|
return {
|
|
746
755
|
async authorize(request) {
|
|
747
756
|
if (runtime.kind === "unconfigured")
|
|
748
757
|
return { ok: true };
|
|
758
|
+
const startedAt = nowMs();
|
|
749
759
|
const token = parseBearerToken(request);
|
|
750
760
|
if (!token) {
|
|
751
761
|
log.info("auth.no_bearer_token", { outcome: "401" });
|
|
@@ -758,6 +768,12 @@ function createRequestAuthorizer(mcp, options = {}) {
|
|
|
758
768
|
} catch (err) {
|
|
759
769
|
if (err instanceof OAuthConfigurationError) {
|
|
760
770
|
log.error("auth.config_error", { ...describeError(err), outcome: "500" });
|
|
771
|
+
recorder?.record({
|
|
772
|
+
tool: null,
|
|
773
|
+
method: "authorize",
|
|
774
|
+
outcome: "auth_config_error",
|
|
775
|
+
durationMs: nowMs() - startedAt
|
|
776
|
+
});
|
|
761
777
|
return { ok: false, response: oauthConfigurationErrorResponse() };
|
|
762
778
|
}
|
|
763
779
|
if (err instanceof OAuthTokenError) {
|
|
@@ -863,14 +879,24 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
|
|
|
863
879
|
try {
|
|
864
880
|
result = await tool.handler(args, new ToolContext(auth));
|
|
865
881
|
} catch {
|
|
866
|
-
recorder
|
|
882
|
+
reportInvocation(recorder, {
|
|
883
|
+
tool: tool.name,
|
|
884
|
+
method: "tools/call",
|
|
885
|
+
outcome: "handler_error",
|
|
886
|
+
durationMs: nowMs() - start
|
|
887
|
+
});
|
|
867
888
|
return { content: [{ type: "text", text: "tool execution failed" }], isError: true };
|
|
868
889
|
}
|
|
869
890
|
if (result == null) {
|
|
870
|
-
recorder
|
|
891
|
+
reportInvocation(recorder, {
|
|
892
|
+
tool: tool.name,
|
|
893
|
+
method: "tools/call",
|
|
894
|
+
outcome: "handler_error",
|
|
895
|
+
durationMs: nowMs() - start
|
|
896
|
+
});
|
|
871
897
|
return { content: [{ type: "text", text: `tool "${tool.name}" returned no result` }], isError: true };
|
|
872
898
|
}
|
|
873
|
-
recorder
|
|
899
|
+
reportInvocation(recorder, {
|
|
874
900
|
tool: tool.name,
|
|
875
901
|
method: "tools/call",
|
|
876
902
|
outcome: result.isError ? "tool_error" : "ok",
|
|
@@ -880,7 +906,7 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
|
|
|
880
906
|
};
|
|
881
907
|
}
|
|
882
908
|
function createMcpProtocolHandler(mcp, options = {}, recorder = createRecorderForRuntime(mcp)) {
|
|
883
|
-
const authorizer = createRequestAuthorizer(mcp, options);
|
|
909
|
+
const authorizer = createRequestAuthorizer(mcp, options, recorder);
|
|
884
910
|
const handle = async (request) => {
|
|
885
911
|
const authResult = await authorizer.authorize(request);
|
|
886
912
|
if (!authResult.ok)
|
|
@@ -1010,9 +1036,9 @@ function buildMcpListing(mcp) {
|
|
|
1010
1036
|
}))
|
|
1011
1037
|
};
|
|
1012
1038
|
}
|
|
1013
|
-
function createListToolsHandler(mcp, options = {}) {
|
|
1039
|
+
function createListToolsHandler(mcp, options = {}, recorder = createRecorderForRuntime(mcp)) {
|
|
1014
1040
|
assertRestResourceBinding(mcp, options);
|
|
1015
|
-
const authorizer = createRequestAuthorizer(mcp, options);
|
|
1041
|
+
const authorizer = createRequestAuthorizer(mcp, options, recorder);
|
|
1016
1042
|
const handle = async (request) => {
|
|
1017
1043
|
const authResult = await authorizer.authorize(request);
|
|
1018
1044
|
if (!authResult.ok)
|
|
@@ -1045,7 +1071,7 @@ function isEmptyArgs(value) {
|
|
|
1045
1071
|
}
|
|
1046
1072
|
function createInvokeToolHandler(mcp, options = {}, recorder = createRecorderForRuntime(mcp)) {
|
|
1047
1073
|
assertRestResourceBinding(mcp, options);
|
|
1048
|
-
const authorizer = createRequestAuthorizer(mcp, options);
|
|
1074
|
+
const authorizer = createRequestAuthorizer(mcp, options, recorder);
|
|
1049
1075
|
const handle = async (request, toolName) => {
|
|
1050
1076
|
const authResult = await authorizer.authorize(request);
|
|
1051
1077
|
if (!authResult.ok)
|
|
@@ -1103,20 +1129,30 @@ function createInvokeToolHandler(mcp, options = {}, recorder = createRecorderFor
|
|
|
1103
1129
|
try {
|
|
1104
1130
|
result = await tool.handler(args, new ToolContext(authResult.auth));
|
|
1105
1131
|
} catch {
|
|
1106
|
-
recorder
|
|
1132
|
+
reportInvocation(recorder, {
|
|
1133
|
+
tool: tool.name,
|
|
1134
|
+
method: "tools/call",
|
|
1135
|
+
outcome: "handler_error",
|
|
1136
|
+
durationMs: nowMs() - start
|
|
1137
|
+
});
|
|
1107
1138
|
return new Response(JSON.stringify({ error: "handler threw", tool: toolName }), {
|
|
1108
1139
|
status: 500,
|
|
1109
1140
|
headers: JSON_HEADERS
|
|
1110
1141
|
});
|
|
1111
1142
|
}
|
|
1112
1143
|
if (result == null) {
|
|
1113
|
-
recorder
|
|
1144
|
+
reportInvocation(recorder, {
|
|
1145
|
+
tool: tool.name,
|
|
1146
|
+
method: "tools/call",
|
|
1147
|
+
outcome: "handler_error",
|
|
1148
|
+
durationMs: nowMs() - start
|
|
1149
|
+
});
|
|
1114
1150
|
return new Response(JSON.stringify({ error: `tool "${toolName}" returned no result` }), {
|
|
1115
1151
|
status: 500,
|
|
1116
1152
|
headers: JSON_HEADERS
|
|
1117
1153
|
});
|
|
1118
1154
|
}
|
|
1119
|
-
recorder
|
|
1155
|
+
reportInvocation(recorder, {
|
|
1120
1156
|
tool: tool.name,
|
|
1121
1157
|
method: "tools/call",
|
|
1122
1158
|
outcome: result.isError ? "tool_error" : "ok",
|
|
@@ -1183,7 +1219,7 @@ function createSupabaseHandler(mcp, options = {}) {
|
|
|
1183
1219
|
const runtimeOptions = resourcePath === void 0 ? {} : { resourcePath, ...metadataPath ? { metadataPath } : {} };
|
|
1184
1220
|
const recorder = createRecorderForRuntime(mcp);
|
|
1185
1221
|
const mcpHandler = createMcpProtocolHandler(mcp, runtimeOptions, recorder);
|
|
1186
|
-
const listToolsHandler = createListToolsHandler(mcp, runtimeOptions);
|
|
1222
|
+
const listToolsHandler = createListToolsHandler(mcp, runtimeOptions, recorder);
|
|
1187
1223
|
const invokeToolHandler = createInvokeToolHandler(mcp, runtimeOptions, recorder);
|
|
1188
1224
|
const metadataHandler = createOAuthProtectedResourceMetadataHandler(mcp, runtimeOptions);
|
|
1189
1225
|
return async (request) => {
|
|
@@ -3,26 +3,24 @@ import {
|
|
|
3
3
|
} from "../../chunk-UQK5UO6C.js";
|
|
4
4
|
import {
|
|
5
5
|
createMcpProtocolHandler
|
|
6
|
-
} from "../../chunk-
|
|
6
|
+
} from "../../chunk-EZQVUNXB.js";
|
|
7
7
|
import {
|
|
8
8
|
createOAuthProtectedResourceMetadataHandler
|
|
9
|
-
} from "../../chunk-
|
|
9
|
+
} from "../../chunk-T24Z753F.js";
|
|
10
10
|
import {
|
|
11
11
|
createInvokeToolHandler
|
|
12
|
-
} from "../../chunk-
|
|
12
|
+
} from "../../chunk-W2EZWPJ5.js";
|
|
13
13
|
import {
|
|
14
14
|
createListToolsHandler
|
|
15
|
-
} from "../../chunk-
|
|
15
|
+
} from "../../chunk-I5CAQUQI.js";
|
|
16
|
+
import "../../chunk-MA5H6PSF.js";
|
|
16
17
|
import {
|
|
18
|
+
assertResourcePathShape,
|
|
17
19
|
createRecorderForRuntime
|
|
18
|
-
} from "../../chunk-
|
|
19
|
-
import "../../chunk-P3F324UC.js";
|
|
20
|
-
import {
|
|
21
|
-
assertResourcePathShape
|
|
22
|
-
} from "../../chunk-G4XA7IJM.js";
|
|
20
|
+
} from "../../chunk-H6BKTNJY.js";
|
|
23
21
|
import {
|
|
24
22
|
trimTrailingSlash
|
|
25
|
-
} from "../../chunk-
|
|
23
|
+
} from "../../chunk-DCWYK4CA.js";
|
|
26
24
|
import {
|
|
27
25
|
OAUTH_PROTECTED_RESOURCE_METADATA_PATH
|
|
28
26
|
} from "../../chunk-6DXGZZA4.js";
|
|
@@ -30,7 +28,7 @@ import {
|
|
|
30
28
|
FUNCTIONS_MOUNT_PREFIX,
|
|
31
29
|
assertFunctionName
|
|
32
30
|
} from "../../chunk-XQWJN6DC.js";
|
|
33
|
-
import "../../chunk-
|
|
31
|
+
import "../../chunk-SKSKC747.js";
|
|
34
32
|
|
|
35
33
|
// src/stacks/supabase/handler.ts
|
|
36
34
|
function deriveResourcePath(options) {
|
|
@@ -70,7 +68,7 @@ function createSupabaseHandler(mcp, options = {}) {
|
|
|
70
68
|
const runtimeOptions = resourcePath === void 0 ? {} : { resourcePath, ...metadataPath ? { metadataPath } : {} };
|
|
71
69
|
const recorder = createRecorderForRuntime(mcp);
|
|
72
70
|
const mcpHandler = createMcpProtocolHandler(mcp, runtimeOptions, recorder);
|
|
73
|
-
const listToolsHandler = createListToolsHandler(mcp, runtimeOptions);
|
|
71
|
+
const listToolsHandler = createListToolsHandler(mcp, runtimeOptions, recorder);
|
|
74
72
|
const invokeToolHandler = createInvokeToolHandler(mcp, runtimeOptions, recorder);
|
|
75
73
|
const metadataHandler = createOAuthProtectedResourceMetadataHandler(mcp, runtimeOptions);
|
|
76
74
|
return async (request) => {
|
|
@@ -25,6 +25,7 @@ __export(vite_exports, {
|
|
|
25
25
|
});
|
|
26
26
|
module.exports = __toCommonJS(vite_exports);
|
|
27
27
|
var import_node_path2 = require("path");
|
|
28
|
+
var import_vite = require("vite");
|
|
28
29
|
|
|
29
30
|
// src/stacks/supabase/emit.ts
|
|
30
31
|
var import_esbuild = require("esbuild");
|
|
@@ -32,7 +33,7 @@ var import_node_fs = require("fs");
|
|
|
32
33
|
var import_node_path = require("path");
|
|
33
34
|
|
|
34
35
|
// package.json
|
|
35
|
-
var version = "0.
|
|
36
|
+
var version = "0.16.0";
|
|
36
37
|
|
|
37
38
|
// src/core/fs-errors.ts
|
|
38
39
|
function isFileMissing(err) {
|
|
@@ -129,7 +130,16 @@ function externalizeBareAsNpm(versions) {
|
|
|
129
130
|
}
|
|
130
131
|
};
|
|
131
132
|
}
|
|
132
|
-
|
|
133
|
+
function importMetaEnvDefines(inlineEnv) {
|
|
134
|
+
const env = inlineEnv ?? {};
|
|
135
|
+
const defines = { "import.meta.env": JSON.stringify(env) };
|
|
136
|
+
for (const [key, value] of Object.entries(env)) {
|
|
137
|
+
if (/^[A-Za-z_$][\w$]*$/.test(key))
|
|
138
|
+
defines[`import.meta.env.${key}`] = JSON.stringify(value);
|
|
139
|
+
}
|
|
140
|
+
return defines;
|
|
141
|
+
}
|
|
142
|
+
async function bundleFunctionEntry(projectRoot, mcpEntryAbs, functionName, inlineEnv) {
|
|
133
143
|
const versions = readProjectDependencyVersions(projectRoot);
|
|
134
144
|
const wrapper = `import mcp from ${JSON.stringify(mcpEntryAbs)};
|
|
135
145
|
import { createSupabaseHandler } from "@lovable.dev/mcp-js/stacks/supabase";
|
|
@@ -145,6 +155,7 @@ Deno.serve(createSupabaseHandler(mcp, { functionName: ${JSON.stringify(functionN
|
|
|
145
155
|
target: "esnext",
|
|
146
156
|
absWorkingDir: projectRoot,
|
|
147
157
|
logLevel: "silent",
|
|
158
|
+
define: importMetaEnvDefines(inlineEnv),
|
|
148
159
|
plugins: [externalizeBareAsNpm(versions)]
|
|
149
160
|
});
|
|
150
161
|
const out = result.outputFiles[0]?.text ?? "";
|
|
@@ -183,7 +194,7 @@ async function syncSupabaseFunction(options) {
|
|
|
183
194
|
cleanupOrphans(paths.functionDir, /* @__PURE__ */ new Set(), removed);
|
|
184
195
|
return { written, removed, inputs: [] };
|
|
185
196
|
}
|
|
186
|
-
const { code, inputs } = await bundleFunctionEntry(projectRoot, paths.mcpEntryAbs, functionName);
|
|
197
|
+
const { code, inputs } = await bundleFunctionEntry(projectRoot, paths.mcpEntryAbs, functionName, options.inlineEnv);
|
|
187
198
|
if (writeIfChanged(paths.functionEntry, code, hasGeneratedBanner)) {
|
|
188
199
|
written.push(paths.functionEntry);
|
|
189
200
|
}
|
|
@@ -227,6 +238,16 @@ function cleanupOrphans(functionDir, expected, removed) {
|
|
|
227
238
|
function normalizePath(p) {
|
|
228
239
|
return p.split(import_node_path2.sep).join("/");
|
|
229
240
|
}
|
|
241
|
+
function productionImportMetaEnv(config) {
|
|
242
|
+
return {
|
|
243
|
+
...(0, import_vite.loadEnv)("production", config.envDir, config.envPrefix),
|
|
244
|
+
MODE: "production",
|
|
245
|
+
BASE_URL: config.base ?? "/",
|
|
246
|
+
DEV: false,
|
|
247
|
+
PROD: true,
|
|
248
|
+
SSR: false
|
|
249
|
+
};
|
|
250
|
+
}
|
|
230
251
|
function mcpPlugin(options = {}) {
|
|
231
252
|
const mcpEntryOption = options.mcpEntry ?? DEFAULT_MCP_ENTRY;
|
|
232
253
|
const functionsDirOption = options.functionsDir ?? DEFAULT_FUNCTIONS_DIR;
|
|
@@ -234,13 +255,15 @@ function mcpPlugin(options = {}) {
|
|
|
234
255
|
const urlPath = `${FUNCTIONS_MOUNT_PREFIX}${functionName}`;
|
|
235
256
|
let projectRoot = process.cwd();
|
|
236
257
|
let mcpEntryAbs = (0, import_node_path2.resolve)(projectRoot, mcpEntryOption);
|
|
258
|
+
let inlineEnv = {};
|
|
237
259
|
let watchedInputs = /* @__PURE__ */ new Set();
|
|
238
260
|
const regenerate = async () => {
|
|
239
261
|
const { inputs } = await syncSupabaseFunction({
|
|
240
262
|
projectRoot,
|
|
241
263
|
mcpEntry: mcpEntryOption,
|
|
242
264
|
functionsDir: functionsDirOption,
|
|
243
|
-
functionName
|
|
265
|
+
functionName,
|
|
266
|
+
inlineEnv
|
|
244
267
|
});
|
|
245
268
|
watchedInputs = new Set(inputs.map(normalizePath));
|
|
246
269
|
};
|
|
@@ -258,6 +281,7 @@ function mcpPlugin(options = {}) {
|
|
|
258
281
|
async configResolved(config) {
|
|
259
282
|
projectRoot = config.root;
|
|
260
283
|
mcpEntryAbs = (0, import_node_path2.resolve)(projectRoot, mcpEntryOption);
|
|
284
|
+
inlineEnv = productionImportMetaEnv(config);
|
|
261
285
|
await regenerate();
|
|
262
286
|
},
|
|
263
287
|
configureServer(server) {
|
|
@@ -7,10 +7,11 @@ import {
|
|
|
7
7
|
} from "../../chunk-XQWJN6DC.js";
|
|
8
8
|
import {
|
|
9
9
|
version
|
|
10
|
-
} from "../../chunk-
|
|
10
|
+
} from "../../chunk-SKSKC747.js";
|
|
11
11
|
|
|
12
12
|
// src/stacks/supabase/vite.ts
|
|
13
13
|
import { resolve as resolve2, sep as sep2 } from "path";
|
|
14
|
+
import { loadEnv } from "vite";
|
|
14
15
|
|
|
15
16
|
// src/stacks/supabase/emit.ts
|
|
16
17
|
import { build } from "esbuild";
|
|
@@ -95,7 +96,16 @@ function externalizeBareAsNpm(versions) {
|
|
|
95
96
|
}
|
|
96
97
|
};
|
|
97
98
|
}
|
|
98
|
-
|
|
99
|
+
function importMetaEnvDefines(inlineEnv) {
|
|
100
|
+
const env = inlineEnv ?? {};
|
|
101
|
+
const defines = { "import.meta.env": JSON.stringify(env) };
|
|
102
|
+
for (const [key, value] of Object.entries(env)) {
|
|
103
|
+
if (/^[A-Za-z_$][\w$]*$/.test(key))
|
|
104
|
+
defines[`import.meta.env.${key}`] = JSON.stringify(value);
|
|
105
|
+
}
|
|
106
|
+
return defines;
|
|
107
|
+
}
|
|
108
|
+
async function bundleFunctionEntry(projectRoot, mcpEntryAbs, functionName, inlineEnv) {
|
|
99
109
|
const versions = readProjectDependencyVersions(projectRoot);
|
|
100
110
|
const wrapper = `import mcp from ${JSON.stringify(mcpEntryAbs)};
|
|
101
111
|
import { createSupabaseHandler } from "@lovable.dev/mcp-js/stacks/supabase";
|
|
@@ -111,6 +121,7 @@ Deno.serve(createSupabaseHandler(mcp, { functionName: ${JSON.stringify(functionN
|
|
|
111
121
|
target: "esnext",
|
|
112
122
|
absWorkingDir: projectRoot,
|
|
113
123
|
logLevel: "silent",
|
|
124
|
+
define: importMetaEnvDefines(inlineEnv),
|
|
114
125
|
plugins: [externalizeBareAsNpm(versions)]
|
|
115
126
|
});
|
|
116
127
|
const out = result.outputFiles[0]?.text ?? "";
|
|
@@ -149,7 +160,7 @@ async function syncSupabaseFunction(options) {
|
|
|
149
160
|
cleanupOrphans(paths.functionDir, /* @__PURE__ */ new Set(), removed);
|
|
150
161
|
return { written, removed, inputs: [] };
|
|
151
162
|
}
|
|
152
|
-
const { code, inputs } = await bundleFunctionEntry(projectRoot, paths.mcpEntryAbs, functionName);
|
|
163
|
+
const { code, inputs } = await bundleFunctionEntry(projectRoot, paths.mcpEntryAbs, functionName, options.inlineEnv);
|
|
153
164
|
if (writeIfChanged(paths.functionEntry, code, hasGeneratedBanner)) {
|
|
154
165
|
written.push(paths.functionEntry);
|
|
155
166
|
}
|
|
@@ -193,6 +204,16 @@ function cleanupOrphans(functionDir, expected, removed) {
|
|
|
193
204
|
function normalizePath(p) {
|
|
194
205
|
return p.split(sep2).join("/");
|
|
195
206
|
}
|
|
207
|
+
function productionImportMetaEnv(config) {
|
|
208
|
+
return {
|
|
209
|
+
...loadEnv("production", config.envDir, config.envPrefix),
|
|
210
|
+
MODE: "production",
|
|
211
|
+
BASE_URL: config.base ?? "/",
|
|
212
|
+
DEV: false,
|
|
213
|
+
PROD: true,
|
|
214
|
+
SSR: false
|
|
215
|
+
};
|
|
216
|
+
}
|
|
196
217
|
function mcpPlugin(options = {}) {
|
|
197
218
|
const mcpEntryOption = options.mcpEntry ?? DEFAULT_MCP_ENTRY;
|
|
198
219
|
const functionsDirOption = options.functionsDir ?? DEFAULT_FUNCTIONS_DIR;
|
|
@@ -200,13 +221,15 @@ function mcpPlugin(options = {}) {
|
|
|
200
221
|
const urlPath = `${FUNCTIONS_MOUNT_PREFIX}${functionName}`;
|
|
201
222
|
let projectRoot = process.cwd();
|
|
202
223
|
let mcpEntryAbs = resolve2(projectRoot, mcpEntryOption);
|
|
224
|
+
let inlineEnv = {};
|
|
203
225
|
let watchedInputs = /* @__PURE__ */ new Set();
|
|
204
226
|
const regenerate = async () => {
|
|
205
227
|
const { inputs } = await syncSupabaseFunction({
|
|
206
228
|
projectRoot,
|
|
207
229
|
mcpEntry: mcpEntryOption,
|
|
208
230
|
functionsDir: functionsDirOption,
|
|
209
|
-
functionName
|
|
231
|
+
functionName,
|
|
232
|
+
inlineEnv
|
|
210
233
|
});
|
|
211
234
|
watchedInputs = new Set(inputs.map(normalizePath));
|
|
212
235
|
};
|
|
@@ -224,6 +247,7 @@ function mcpPlugin(options = {}) {
|
|
|
224
247
|
async configResolved(config) {
|
|
225
248
|
projectRoot = config.root;
|
|
226
249
|
mcpEntryAbs = resolve2(projectRoot, mcpEntryOption);
|
|
250
|
+
inlineEnv = productionImportMetaEnv(config);
|
|
227
251
|
await regenerate();
|
|
228
252
|
},
|
|
229
253
|
configureServer(server) {
|