@salesforce/vite-plugin-lwc-ui-bundle 1.134.5 → 2.0.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/README.md +46 -27
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/plugins/proxy.d.ts +1 -1
- package/dist/providers/index.d.ts +1 -2
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +0 -3
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/lds/index.d.ts +72 -10
- package/dist/providers/lds/index.d.ts.map +1 -1
- package/dist/providers/lds/index.js +58 -12
- package/dist/providers/lds/index.js.map +1 -1
- package/dist/providers/lds/runtime.js +177 -17
- package/dist/providers/lds/runtime.js.map +1 -1
- package/docs/consumer-guide.md +44 -114
- package/package.json +9 -13
- package/skills/setup-lwc-vite-plugin/SKILL.md +168 -27
- package/skills/setup-lwc-vite-plugin/references/bootstrap-js-patterns.md +1 -1
- package/skills/setup-lwc-vite-plugin/references/known-pitfalls.md +153 -45
- package/dist/providers/lightning-graphql/index.d.ts +0 -10
- package/dist/providers/lightning-graphql/index.d.ts.map +0 -1
- package/dist/providers/lightning-graphql/index.js +0 -24
- package/dist/providers/lightning-graphql/index.js.map +0 -1
- package/dist/providers/lightning-graphql/runtime.js +0 -103
- package/dist/providers/lightning-graphql/runtime.js.map +0 -1
|
@@ -1,11 +1,35 @@
|
|
|
1
1
|
import { JSONSchema } from '@conduit-client/jsonschema-validate';
|
|
2
2
|
import { Plugin } from 'vite';
|
|
3
3
|
import { ReadInvokerShape } from './types';
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* MCP dispatch descriptor. Nested under `mcp` on every adapter config so
|
|
6
|
+
* additional MCP-specific fields (auth, transport, retry policy) can join
|
|
7
|
+
* later without reshaping every consumer entry.
|
|
8
|
+
*/
|
|
9
|
+
export interface LdsAdapterMcpDispatch {
|
|
6
10
|
toolName: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Base shape every LDS adapter config extends. Holds the dispatch surface in
|
|
14
|
+
* one place so new backings (e.g. `http`) can land as sibling optional fields
|
|
15
|
+
* without forking each adapter interface. Dual registration is supported at
|
|
16
|
+
* the type level — runtime execution still targets a single backing per call.
|
|
17
|
+
*/
|
|
18
|
+
export interface LdsAdapterConfigBase {
|
|
19
|
+
mcp?: LdsAdapterMcpDispatch;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* LDS adapter configs whose input is validated against a JSON Schema at
|
|
23
|
+
* invoke time — wire, imperative-mutation, imperative-read. GraphQL variants
|
|
24
|
+
* skip this base because they pass `{ query, variables }` through to the
|
|
25
|
+
* configured MCP tool with no schema check.
|
|
26
|
+
*/
|
|
27
|
+
export interface LdsSchemaValidatedAdapterConfig extends LdsAdapterConfigBase {
|
|
7
28
|
configJsonSchema: JSONSchema;
|
|
8
29
|
}
|
|
30
|
+
export interface LdsWireAdapterConfig extends LdsSchemaValidatedAdapterConfig {
|
|
31
|
+
type: "wire";
|
|
32
|
+
}
|
|
9
33
|
/**
|
|
10
34
|
* Imperative **mutation** adapter. Always an async
|
|
11
35
|
* `(config) => Promise<Data>` that throws on validation or tool error —
|
|
@@ -14,10 +38,8 @@ export interface LdsWireAdapterConfig {
|
|
|
14
38
|
* `subscribe`/`refresh` make no sense on write, and allowing them here
|
|
15
39
|
* would drift off-platform from on-platform semantics.
|
|
16
40
|
*/
|
|
17
|
-
export interface LdsImperativeMutationAdapterConfig {
|
|
41
|
+
export interface LdsImperativeMutationAdapterConfig extends LdsSchemaValidatedAdapterConfig {
|
|
18
42
|
type: "imperative-mutation";
|
|
19
|
-
toolName: string;
|
|
20
|
-
configJsonSchema: JSONSchema;
|
|
21
43
|
}
|
|
22
44
|
/**
|
|
23
45
|
* Public alias for the read-shape union defined in `runtime.ts`. Re-exported
|
|
@@ -30,13 +52,53 @@ export interface LdsImperativeMutationAdapterConfig {
|
|
|
30
52
|
* surface for code ported verbatim.
|
|
31
53
|
*/
|
|
32
54
|
export type LdsImperativeReadInvokerShape = ReadInvokerShape;
|
|
33
|
-
export interface LdsImperativeReadAdapterConfig {
|
|
55
|
+
export interface LdsImperativeReadAdapterConfig extends LdsSchemaValidatedAdapterConfig {
|
|
34
56
|
type: "imperative-read";
|
|
35
57
|
invokerShape: LdsImperativeReadInvokerShape;
|
|
36
|
-
toolName: string;
|
|
37
|
-
configJsonSchema: JSONSchema;
|
|
38
58
|
}
|
|
39
|
-
|
|
59
|
+
/**
|
|
60
|
+
* GraphQL wire adapter. Emits `{ data, errors, refresh }` (distinct from the
|
|
61
|
+
* base wire `{ data, error }`). No `configJsonSchema` — the adapter passes
|
|
62
|
+
* `{ query, variables }` through to the configured MCP tool.
|
|
63
|
+
*/
|
|
64
|
+
export interface LdsGraphqlWireAdapterConfig extends LdsAdapterConfigBase {
|
|
65
|
+
type: "graphql-wire";
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Imperative GraphQL mutation — `(config) => Promise<{ data, errors }>`.
|
|
69
|
+
* Errors are routed in-band to the `errors[]` envelope rather than thrown,
|
|
70
|
+
* matching on-platform `toGraphQLResponseFromFailure`.
|
|
71
|
+
*/
|
|
72
|
+
export interface LdsGraphqlMutationAdapterConfig extends LdsAdapterConfigBase {
|
|
73
|
+
type: "graphql-mutation";
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Read-shape discriminator for imperative GraphQL adapters. Mirrors the
|
|
77
|
+
* `imperative-read` `invokerShape` field so the two families share a pattern:
|
|
78
|
+
* one `type` discriminator + a shape field that selects the return surface.
|
|
79
|
+
*
|
|
80
|
+
* - `query` — `Promise<{ data, errors, subscribe }>` (on-platform
|
|
81
|
+
* `GraphQLImperativeBindingsService` without `exposeRefresh`).
|
|
82
|
+
* - `query-refreshable` — `Promise<{ data, errors, subscribe, refresh }>`
|
|
83
|
+
* (same service with `exposeRefresh: true`).
|
|
84
|
+
* - `legacy` — `{ invoke(config, context, callback),
|
|
85
|
+
* subscribe(config, context, callback): Unsubscribe }`, the older callback
|
|
86
|
+
* surface served by `GraphQLLegacyImperativeBindingsService`.
|
|
87
|
+
*
|
|
88
|
+
* `subscribe` is a deliberate no-op off-platform (no reactive store).
|
|
89
|
+
*/
|
|
90
|
+
export type LdsGraphqlImperativeReadInvokerShape = "query" | "query-refreshable" | "legacy";
|
|
91
|
+
/**
|
|
92
|
+
* Imperative GraphQL read adapter. The `invokerShape` picks the return
|
|
93
|
+
* surface — see {@link LdsGraphqlImperativeReadInvokerShape}. Errors are
|
|
94
|
+
* routed in-band to `errors[]` (for `query`/`query-refreshable`) or into the
|
|
95
|
+
* callback payload (for `legacy`); no shape throws on tool errors.
|
|
96
|
+
*/
|
|
97
|
+
export interface LdsGraphqlImperativeReadAdapterConfig extends LdsAdapterConfigBase {
|
|
98
|
+
type: "graphql-imperative-read";
|
|
99
|
+
invokerShape: LdsGraphqlImperativeReadInvokerShape;
|
|
100
|
+
}
|
|
101
|
+
export type LdsAdapterConfig = LdsWireAdapterConfig | LdsImperativeMutationAdapterConfig | LdsImperativeReadAdapterConfig | LdsGraphqlWireAdapterConfig | LdsGraphqlMutationAdapterConfig | LdsGraphqlImperativeReadAdapterConfig;
|
|
40
102
|
export type LdsAdapterRegistry = Record<string, Record<string, LdsAdapterConfig>>;
|
|
41
103
|
/**
|
|
42
104
|
* LDS provider — rewrites registered `lightning/*` imports (e.g.
|
|
@@ -61,5 +123,5 @@ export type LdsAdapterRegistry = Record<string, Record<string, LdsAdapterConfig>
|
|
|
61
123
|
* Only specifiers present in the `adapters` registry are intercepted; imports from
|
|
62
124
|
* unregistered specifiers pass through unchanged.
|
|
63
125
|
*/
|
|
64
|
-
export declare function lds(
|
|
126
|
+
export declare function lds(overrides?: LdsAdapterRegistry): Plugin;
|
|
65
127
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/lds/index.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AAGtE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACnC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/lds/index.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AAGtE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACnC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAuChD;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACrC,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACpC,GAAG,CAAC,EAAE,qBAAqB,CAAC;CAC5B;AAED;;;;;GAKG;AACH,MAAM,WAAW,+BAAgC,SAAQ,oBAAoB;IAC5E,gBAAgB,EAAE,UAAU,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAqB,SAAQ,+BAA+B;IAC5E,IAAI,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kCAAmC,SAAQ,+BAA+B;IAC1F,IAAI,EAAE,qBAAqB,CAAC;CAC5B;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,6BAA6B,GAAG,gBAAgB,CAAC;AAE7D,MAAM,WAAW,8BAA+B,SAAQ,+BAA+B;IACtF,IAAI,EAAE,iBAAiB,CAAC;IACxB,YAAY,EAAE,6BAA6B,CAAC;CAC5C;AAED;;;;GAIG;AACH,MAAM,WAAW,2BAA4B,SAAQ,oBAAoB;IACxE,IAAI,EAAE,cAAc,CAAC;CACrB;AAED;;;;GAIG;AACH,MAAM,WAAW,+BAAgC,SAAQ,oBAAoB;IAC5E,IAAI,EAAE,kBAAkB,CAAC;CACzB;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,oCAAoC,GAAG,OAAO,GAAG,mBAAmB,GAAG,QAAQ,CAAC;AAE5F;;;;;GAKG;AACH,MAAM,WAAW,qCAAsC,SAAQ,oBAAoB;IAClF,IAAI,EAAE,yBAAyB,CAAC;IAChC,YAAY,EAAE,oCAAoC,CAAC;CACnD;AAED,MAAM,MAAM,gBAAgB,GACzB,oBAAoB,GACpB,kCAAkC,GAClC,8BAA8B,GAC9B,2BAA2B,GAC3B,+BAA+B,GAC/B,qCAAqC,CAAC;AAEzC,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;AA4KlF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,GAAG,CAAC,SAAS,GAAE,kBAAuB,GAAG,MAAM,CA+G9D"}
|
|
@@ -5,15 +5,17 @@ import { init, parse } from "es-module-lexer";
|
|
|
5
5
|
import MagicString from "magic-string";
|
|
6
6
|
const ADAPTER_PREFIX = "sf-lds-adapter:";
|
|
7
7
|
const ADAPTER_ID_PREFIX = "\0" + ADAPTER_PREFIX;
|
|
8
|
-
const adapterBaseSource =
|
|
9
|
-
join(dirname(fileURLToPath(import.meta.url)), "runtime.js"),
|
|
10
|
-
"utf-8"
|
|
8
|
+
const adapterBaseSource = stripTopLevelExports(
|
|
9
|
+
readFileSync(join(dirname(fileURLToPath(import.meta.url)), "runtime.js"), "utf-8")
|
|
11
10
|
);
|
|
11
|
+
function stripTopLevelExports(source) {
|
|
12
|
+
return source.replace(/^export\s+(?=(?:async\s+)?function\s)/gm, "").replace(/^export\s*\{[^}]*};?\s*$/gm, "");
|
|
13
|
+
}
|
|
12
14
|
const DEFAULT_ADAPTERS = {
|
|
13
15
|
"lightning/uiRecordApi": {
|
|
14
16
|
getRecord: {
|
|
15
17
|
type: "wire",
|
|
16
|
-
toolName: "getRecordMcpTool",
|
|
18
|
+
mcp: { toolName: "getRecordMcpTool" },
|
|
17
19
|
configJsonSchema: {
|
|
18
20
|
type: "object",
|
|
19
21
|
properties: {
|
|
@@ -53,7 +55,7 @@ const DEFAULT_ADAPTERS = {
|
|
|
53
55
|
},
|
|
54
56
|
createRecord: {
|
|
55
57
|
type: "imperative-mutation",
|
|
56
|
-
toolName: "createRecordMcpTool",
|
|
58
|
+
mcp: { toolName: "createRecordMcpTool" },
|
|
57
59
|
configJsonSchema: {
|
|
58
60
|
type: "object",
|
|
59
61
|
properties: {
|
|
@@ -71,7 +73,7 @@ const DEFAULT_ADAPTERS = {
|
|
|
71
73
|
},
|
|
72
74
|
updateRecord: {
|
|
73
75
|
type: "imperative-mutation",
|
|
74
|
-
toolName: "updateRecordMcpTool",
|
|
76
|
+
mcp: { toolName: "updateRecordMcpTool" },
|
|
75
77
|
configJsonSchema: {
|
|
76
78
|
type: "object",
|
|
77
79
|
properties: {
|
|
@@ -95,7 +97,7 @@ const DEFAULT_ADAPTERS = {
|
|
|
95
97
|
getObjectInfo_imperative: {
|
|
96
98
|
type: "imperative-read",
|
|
97
99
|
invokerShape: "legacy",
|
|
98
|
-
toolName: "getObjectInfoMcpTool",
|
|
100
|
+
mcp: { toolName: "getObjectInfoMcpTool" },
|
|
99
101
|
configJsonSchema: {
|
|
100
102
|
type: "object",
|
|
101
103
|
properties: {
|
|
@@ -105,8 +107,37 @@ const DEFAULT_ADAPTERS = {
|
|
|
105
107
|
additionalProperties: false
|
|
106
108
|
}
|
|
107
109
|
}
|
|
110
|
+
},
|
|
111
|
+
// `lightning/graphql` — on-platform exports `gql`, the `graphql` wire
|
|
112
|
+
// adapter, and `executeMutation`. Only `graphql` and `executeMutation`
|
|
113
|
+
// are registry entries; `gql` rides along automatically for any specifier
|
|
114
|
+
// that has at least one graphql-typed entry (emitted by the load hook).
|
|
115
|
+
"lightning/graphql": {
|
|
116
|
+
graphql: { type: "graphql-wire", mcp: { toolName: "graphqlQuery" } },
|
|
117
|
+
executeMutation: { type: "graphql-mutation", mcp: { toolName: "graphqlQuery" } }
|
|
108
118
|
}
|
|
109
119
|
};
|
|
120
|
+
function isGraphqlSpecifier(moduleAdapters) {
|
|
121
|
+
return Object.values(moduleAdapters).some(
|
|
122
|
+
(entry) => entry.type === "graphql-wire" || entry.type === "graphql-mutation" || entry.type === "graphql-imperative-read"
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
function factoryFor(type) {
|
|
126
|
+
switch (type) {
|
|
127
|
+
case "wire":
|
|
128
|
+
return "createWireAdapter";
|
|
129
|
+
case "imperative-mutation":
|
|
130
|
+
return "createMutationAdapter";
|
|
131
|
+
case "imperative-read":
|
|
132
|
+
return "createReadAdapter";
|
|
133
|
+
case "graphql-wire":
|
|
134
|
+
return "createGraphQLWireAdapter";
|
|
135
|
+
case "graphql-mutation":
|
|
136
|
+
return "createGraphQLMutationAdapter";
|
|
137
|
+
case "graphql-imperative-read":
|
|
138
|
+
return "createGraphQLImperativeReadAdapter";
|
|
139
|
+
}
|
|
140
|
+
}
|
|
110
141
|
function parseImportSpecifiers(bracesContent) {
|
|
111
142
|
return bracesContent.split(",").map((s) => s.trim()).filter(Boolean).map((entry) => {
|
|
112
143
|
const asIdx = entry.indexOf(" as ");
|
|
@@ -114,8 +145,20 @@ function parseImportSpecifiers(bracesContent) {
|
|
|
114
145
|
return { original, full: entry };
|
|
115
146
|
});
|
|
116
147
|
}
|
|
117
|
-
function
|
|
118
|
-
const
|
|
148
|
+
function mergeWithDefaults(overrides) {
|
|
149
|
+
const merged = { ...DEFAULT_ADAPTERS };
|
|
150
|
+
for (const [specifier, entries] of Object.entries(overrides)) {
|
|
151
|
+
merged[specifier] = { ...DEFAULT_ADAPTERS[specifier] ?? {}, ...entries };
|
|
152
|
+
}
|
|
153
|
+
return merged;
|
|
154
|
+
}
|
|
155
|
+
function lds(overrides = {}) {
|
|
156
|
+
const adapters = mergeWithDefaults(overrides);
|
|
157
|
+
const graphqlSpecifiers = new Set(
|
|
158
|
+
Object.entries(adapters).filter(([, moduleAdapters]) => isGraphqlSpecifier(moduleAdapters)).map(([specifier]) => specifier)
|
|
159
|
+
);
|
|
160
|
+
const transformSpecifiers = Object.keys(adapters).filter((s) => !graphqlSpecifiers.has(s));
|
|
161
|
+
const specifierSnippets = transformSpecifiers.flatMap((s) => [`'${s}'`, `"${s}"`]);
|
|
119
162
|
return {
|
|
120
163
|
name: "vite-plugin-lds",
|
|
121
164
|
enforce: "pre",
|
|
@@ -132,7 +175,7 @@ function lds(adapters = DEFAULT_ADAPTERS) {
|
|
|
132
175
|
return null;
|
|
133
176
|
}
|
|
134
177
|
const relevant = imports.filter(
|
|
135
|
-
(imp) => imp.d === -1 && imp.n !== void 0 && imp.n in adapters
|
|
178
|
+
(imp) => imp.d === -1 && imp.n !== void 0 && imp.n in adapters && !graphqlSpecifiers.has(imp.n)
|
|
136
179
|
);
|
|
137
180
|
if (relevant.length === 0) return null;
|
|
138
181
|
const s = new MagicString(code);
|
|
@@ -164,6 +207,7 @@ function lds(adapters = DEFAULT_ADAPTERS) {
|
|
|
164
207
|
return { code: s.toString(), map: s.generateMap({ hires: true }) };
|
|
165
208
|
},
|
|
166
209
|
resolveId(id) {
|
|
210
|
+
if (graphqlSpecifiers.has(id)) return ADAPTER_ID_PREFIX + id;
|
|
167
211
|
if (id.startsWith(ADAPTER_PREFIX)) return ADAPTER_ID_PREFIX + id.slice(ADAPTER_PREFIX.length);
|
|
168
212
|
return null;
|
|
169
213
|
},
|
|
@@ -175,11 +219,13 @@ function lds(adapters = DEFAULT_ADAPTERS) {
|
|
|
175
219
|
const lines = [adapterBaseSource];
|
|
176
220
|
for (const [name, entry] of Object.entries(moduleAdapters)) {
|
|
177
221
|
const { type, ...cfg } = entry;
|
|
178
|
-
const factory = type === "wire" ? "createWireAdapter" : type === "imperative-mutation" ? "createMutationAdapter" : "createReadAdapter";
|
|
179
222
|
lines.push(
|
|
180
|
-
`export const ${name} = ${
|
|
223
|
+
`export const ${name} = ${factoryFor(type)}(${JSON.stringify(name)}, ${JSON.stringify(cfg)});`
|
|
181
224
|
);
|
|
182
225
|
}
|
|
226
|
+
if (graphqlSpecifiers.has(specifier)) {
|
|
227
|
+
lines.push("export { gql };");
|
|
228
|
+
}
|
|
183
229
|
return lines.join("\n");
|
|
184
230
|
}
|
|
185
231
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/providers/lds/index.ts"],"sourcesContent":["/**\n * Copyright (c) 2026, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport { readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { JSONSchema } from \"@conduit-client/jsonschema-validate\";\nimport { init, parse } from \"es-module-lexer\";\nimport MagicString from \"magic-string\";\nimport type { Plugin } from \"vite\";\nimport type { ReadInvokerShape } from \"./types\";\n\n// prefix to write into transformed source code\nconst ADAPTER_PREFIX = \"sf-lds-adapter:\";\n// prefix used to ID the adapter when loading the virtual module\nconst ADAPTER_ID_PREFIX = \"\\0\" + ADAPTER_PREFIX;\n\n// the source of the adapter base module — reused across virtual modules so\n// each generated specifier emits the createWireAdapter / createMutationAdapter /\n// createReadAdapter factories once\nconst adapterBaseSource = readFileSync(\n\tjoin(dirname(fileURLToPath(import.meta.url)), \"runtime.js\"),\n\t\"utf-8\",\n);\n\nexport interface LdsWireAdapterConfig {\n\ttype: \"wire\";\n\ttoolName: string;\n\tconfigJsonSchema: JSONSchema;\n}\n\n/**\n * Imperative **mutation** adapter. Always an async\n * `(config) => Promise<Data>` that throws on validation or tool error —\n * matching OneStore's `DefaultImperativeBindingsService`, the only service a\n * mutation ever uses on platform. Mutations do not carry an `invokerShape`:\n * `subscribe`/`refresh` make no sense on write, and allowing them here\n * would drift off-platform from on-platform semantics.\n */\nexport interface LdsImperativeMutationAdapterConfig {\n\ttype: \"imperative-mutation\";\n\ttoolName: string;\n\tconfigJsonSchema: JSONSchema;\n}\n\n/**\n * Public alias for the read-shape union defined in `runtime.ts`. Re-exported\n * from this module so consumers don't have to import from the runtime entry\n * point, while keeping the union pinned to one source of truth.\n *\n * Off-platform there is no store, so `subscribe` is a deliberate no-op\n * (callback never fires, returned unsubscribe is idempotent) and `refresh`\n * re-executes the underlying MCP tool. This preserves the OneStore API\n * surface for code ported verbatim.\n */\nexport type LdsImperativeReadInvokerShape = ReadInvokerShape;\n\nexport interface LdsImperativeReadAdapterConfig {\n\ttype: \"imperative-read\";\n\tinvokerShape: LdsImperativeReadInvokerShape;\n\ttoolName: string;\n\tconfigJsonSchema: JSONSchema;\n}\n\nexport type LdsAdapterConfig =\n\t| LdsWireAdapterConfig\n\t| LdsImperativeMutationAdapterConfig\n\t| LdsImperativeReadAdapterConfig;\n\nexport type LdsAdapterRegistry = Record<string, Record<string, LdsAdapterConfig>>;\n\n/**\n * Default adapter registry.\n * Maps LDS module specifiers to MCP tool-backed implementations. Entries can be\n * wire adapters (`type: 'wire'`), imperative mutations (`type: 'imperative-mutation'`),\n * or imperative reads (`type: 'imperative-read'` + `invokerShape`).\n * Add entries here to support additional lightning/* exports.\n */\nconst DEFAULT_ADAPTERS: LdsAdapterRegistry = {\n\t\"lightning/uiRecordApi\": {\n\t\tgetRecord: {\n\t\t\ttype: \"wire\",\n\t\t\ttoolName: \"getRecordMcpTool\",\n\t\t\tconfigJsonSchema: {\n\t\t\t\ttype: \"object\",\n\t\t\t\tproperties: {\n\t\t\t\t\trecordId: { type: \"string\" },\n\t\t\t\t\tlayoutTypes: {\n\t\t\t\t\t\tanyOf: [{ type: \"array\", items: { type: \"string\" } }, { type: \"null\" }],\n\t\t\t\t\t},\n\t\t\t\t\tfields: {\n\t\t\t\t\t\tanyOf: [{ type: \"array\", items: { type: \"string\" } }, { type: \"null\" }],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\trequired: [\"recordId\"],\n\t\t\t\tadditionalProperties: false,\n\t\t\t\tanyOf: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tfields: { type: \"array\", items: { type: \"string\" }, minItems: 1 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\trequired: [\"fields\"],\n\t\t\t\t\t\tadditionalProperties: true,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tlayoutTypes: {\n\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\titems: { type: \"string\" },\n\t\t\t\t\t\t\t\tminItems: 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\trequired: [\"layoutTypes\"],\n\t\t\t\t\t\tadditionalProperties: true,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t},\n\t\tcreateRecord: {\n\t\t\ttype: \"imperative-mutation\",\n\t\t\ttoolName: \"createRecordMcpTool\",\n\t\t\tconfigJsonSchema: {\n\t\t\t\ttype: \"object\",\n\t\t\t\tproperties: {\n\t\t\t\t\tapiName: { type: \"string\" },\n\t\t\t\t\tfields: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {},\n\t\t\t\t\t\trequired: [],\n\t\t\t\t\t\tadditionalProperties: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\trequired: [\"apiName\", \"fields\"],\n\t\t\t\tadditionalProperties: false,\n\t\t\t},\n\t\t},\n\t\tupdateRecord: {\n\t\t\ttype: \"imperative-mutation\",\n\t\t\ttoolName: \"updateRecordMcpTool\",\n\t\t\tconfigJsonSchema: {\n\t\t\t\ttype: \"object\",\n\t\t\t\tproperties: {\n\t\t\t\t\trecordId: { type: \"string\" },\n\t\t\t\t\tfields: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {},\n\t\t\t\t\t\trequired: [],\n\t\t\t\t\t\tadditionalProperties: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\trequired: [\"recordId\", \"fields\"],\n\t\t\t\tadditionalProperties: false,\n\t\t\t},\n\t\t},\n\t},\n\t\"lightning/uiObjectInfoApi\": {\n\t\t// On-platform this is a `{ invoke, subscribe }` callback surface\n\t\t// emitting `{ data, error }`. The legacy invoker shape preserves that\n\t\t// contract verbatim, so ported consumers keep their call sites.\n\t\tgetObjectInfo_imperative: {\n\t\t\ttype: \"imperative-read\",\n\t\t\tinvokerShape: \"legacy\",\n\t\t\ttoolName: \"getObjectInfoMcpTool\",\n\t\t\tconfigJsonSchema: {\n\t\t\t\ttype: \"object\",\n\t\t\t\tproperties: {\n\t\t\t\t\tobjectApiName: { type: \"string\" },\n\t\t\t\t},\n\t\t\t\trequired: [\"objectApiName\"],\n\t\t\t\tadditionalProperties: false,\n\t\t\t},\n\t\t},\n\t},\n};\n\nfunction parseImportSpecifiers(bracesContent: string): { original: string; full: string }[] {\n\treturn bracesContent\n\t\t.split(\",\")\n\t\t.map((s) => s.trim())\n\t\t.filter(Boolean)\n\t\t.map((entry) => {\n\t\t\tconst asIdx = entry.indexOf(\" as \");\n\t\t\tconst original = asIdx !== -1 ? entry.slice(0, asIdx).trim() : entry.trim();\n\t\t\treturn { original, full: entry };\n\t\t});\n}\n\n/**\n * LDS provider — rewrites registered `lightning/*` imports (e.g.\n * `lightning/uiRecordApi`) to MCP-tool-backed virtual modules. Unregistered\n * exports pass through to the normal `lightning/*` resolution.\n *\n * Three Vite hooks do the work:\n *\n * - **`transform`** — parses each `.js` / `.ts` file with `es-module-lexer`,\n * finds named imports from registered specifiers, and rewrites them to pull\n * registered names from `sf-lds-adapter:<specifier>` while leaving\n * unregistered names pointing at the original specifier.\n *\n * - **`resolveId`** — maps `sf-lds-adapter:<specifier>` to a `\\0`-prefixed\n * virtual module ID, preventing Rollup from attempting a filesystem lookup.\n *\n * - **`load`** — generates the virtual module, emitting an MCP-backed\n * `createWireAdapter(...)` class for every `type: 'wire'` entry,\n * `createMutationAdapter(...)` for every `type: 'imperative-mutation'` entry,\n * and `createReadAdapter(...)` for every `type: 'imperative-read'` entry.\n *\n * Only specifiers present in the `adapters` registry are intercepted; imports from\n * unregistered specifiers pass through unchanged.\n */\nexport function lds(adapters: LdsAdapterRegistry = DEFAULT_ADAPTERS): Plugin {\n\tconst specifierSnippets = Object.keys(adapters).flatMap((s) => [`'${s}'`, `\"${s}\"`]);\n\n\treturn {\n\t\tname: \"vite-plugin-lds\",\n\t\tenforce: \"pre\",\n\n\t\tasync transform(code, id) {\n\t\t\tconst cleanId = id.split(\"?\")[0] ?? id;\n\t\t\tif (!cleanId.endsWith(\".js\") && !cleanId.endsWith(\".ts\")) return null;\n\t\t\tif (cleanId.includes(\"/node_modules/\")) return null;\n\t\t\tif (!specifierSnippets.some((snippet) => code.includes(snippet))) return null;\n\n\t\t\tawait init;\n\n\t\t\tlet imports: ReturnType<typeof parse>[0];\n\t\t\ttry {\n\t\t\t\t[imports] = parse(code);\n\t\t\t} catch {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst relevant = imports.filter(\n\t\t\t\t(imp) => imp.d === -1 && imp.n !== undefined && imp.n in adapters,\n\t\t\t);\n\t\t\tif (relevant.length === 0) return null;\n\n\t\t\tconst s = new MagicString(code);\n\t\t\tlet changed = false;\n\n\t\t\tfor (const imp of relevant) {\n\t\t\t\tconst { ss: start, se: end, n: specifier } = imp;\n\t\t\t\tconst statement = code.slice(start, end);\n\n\t\t\t\tconst openBrace = statement.indexOf(\"{\");\n\t\t\t\tconst closeBrace = statement.indexOf(\"}\");\n\t\t\t\tif (openBrace === -1 || closeBrace === -1) continue;\n\n\t\t\t\tconst bracesContent = statement.slice(openBrace + 1, closeBrace);\n\t\t\t\tconst moduleAdapters = adapters[specifier!]!;\n\t\t\t\tconst parsedImport = parseImportSpecifiers(bracesContent);\n\t\t\t\tconst registered = parsedImport.filter((p) => p.original in moduleAdapters);\n\t\t\t\tconst unregistered = parsedImport.filter((p) => !(p.original in moduleAdapters));\n\n\t\t\t\tif (registered.length === 0) continue;\n\n\t\t\t\tconst parts: string[] = [\n\t\t\t\t\t`import { ${registered.map((p) => p.full).join(\", \")} } from '${ADAPTER_PREFIX}${specifier}';`,\n\t\t\t\t];\n\n\t\t\t\tif (unregistered.length > 0) {\n\t\t\t\t\tparts.push(\n\t\t\t\t\t\t`import { ${unregistered.map((p) => p.full).join(\", \")} } from '${specifier}';`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\ts.overwrite(start, end, parts.join(\"\\n\"));\n\t\t\t\tchanged = true;\n\t\t\t}\n\n\t\t\tif (!changed) return null;\n\t\t\treturn { code: s.toString(), map: s.generateMap({ hires: true }) };\n\t\t},\n\n\t\tresolveId(id) {\n\t\t\tif (id.startsWith(ADAPTER_PREFIX)) return ADAPTER_ID_PREFIX + id.slice(ADAPTER_PREFIX.length);\n\t\t\treturn null;\n\t\t},\n\n\t\tload(id) {\n\t\t\tif (!id.startsWith(ADAPTER_ID_PREFIX)) return null;\n\n\t\t\tconst specifier = id.slice(ADAPTER_ID_PREFIX.length);\n\t\t\tconst moduleAdapters = adapters[specifier];\n\t\t\tif (!moduleAdapters) return null;\n\n\t\t\t// create lines of code used to create MCP tool based adapters\n\t\t\tconst lines: string[] = [adapterBaseSource];\n\t\t\tfor (const [name, entry] of Object.entries(moduleAdapters)) {\n\t\t\t\tconst { type, ...cfg } = entry;\n\t\t\t\tconst factory =\n\t\t\t\t\ttype === \"wire\"\n\t\t\t\t\t\t? \"createWireAdapter\"\n\t\t\t\t\t\t: type === \"imperative-mutation\"\n\t\t\t\t\t\t\t? \"createMutationAdapter\"\n\t\t\t\t\t\t\t: \"createReadAdapter\";\n\t\t\t\tlines.push(\n\t\t\t\t\t`export const ${name} = ${factory}(${JSON.stringify(name)}, ${JSON.stringify(cfg)});`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn lines.join(\"\\n\");\n\t\t},\n\t};\n}\n"],"names":[],"mappings":";;;;;AAeA,MAAM,iBAAiB;AAEvB,MAAM,oBAAoB,OAAO;AAKjC,MAAM,oBAAoB;AAAA,EACzB,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC,GAAG,YAAY;AAAA,EAC1D;AACD;AAuDA,MAAM,mBAAuC;AAAA,EAC5C,yBAAyB;AAAA,IACxB,WAAW;AAAA,MACV,MAAM;AAAA,MACN,UAAU;AAAA,MACV,kBAAkB;AAAA,QACjB,MAAM;AAAA,QACN,YAAY;AAAA,UACX,UAAU,EAAE,MAAM,SAAA;AAAA,UAClB,aAAa;AAAA,YACZ,OAAO,CAAC,EAAE,MAAM,SAAS,OAAO,EAAE,MAAM,SAAA,EAAS,GAAK,EAAE,MAAM,QAAQ;AAAA,UAAA;AAAA,UAEvE,QAAQ;AAAA,YACP,OAAO,CAAC,EAAE,MAAM,SAAS,OAAO,EAAE,MAAM,SAAA,EAAS,GAAK,EAAE,MAAM,QAAQ;AAAA,UAAA;AAAA,QACvE;AAAA,QAED,UAAU,CAAC,UAAU;AAAA,QACrB,sBAAsB;AAAA,QACtB,OAAO;AAAA,UACN;AAAA,YACC,MAAM;AAAA,YACN,YAAY;AAAA,cACX,QAAQ,EAAE,MAAM,SAAS,OAAO,EAAE,MAAM,YAAY,UAAU,EAAA;AAAA,YAAE;AAAA,YAEjE,UAAU,CAAC,QAAQ;AAAA,YACnB,sBAAsB;AAAA,UAAA;AAAA,UAEvB;AAAA,YACC,MAAM;AAAA,YACN,YAAY;AAAA,cACX,aAAa;AAAA,gBACZ,MAAM;AAAA,gBACN,OAAO,EAAE,MAAM,SAAA;AAAA,gBACf,UAAU;AAAA,cAAA;AAAA,YACX;AAAA,YAED,UAAU,CAAC,aAAa;AAAA,YACxB,sBAAsB;AAAA,UAAA;AAAA,QACvB;AAAA,MACD;AAAA,IACD;AAAA,IAED,cAAc;AAAA,MACb,MAAM;AAAA,MACN,UAAU;AAAA,MACV,kBAAkB;AAAA,QACjB,MAAM;AAAA,QACN,YAAY;AAAA,UACX,SAAS,EAAE,MAAM,SAAA;AAAA,UACjB,QAAQ;AAAA,YACP,MAAM;AAAA,YACN,YAAY,CAAA;AAAA,YACZ,UAAU,CAAA;AAAA,YACV,sBAAsB;AAAA,UAAA;AAAA,QACvB;AAAA,QAED,UAAU,CAAC,WAAW,QAAQ;AAAA,QAC9B,sBAAsB;AAAA,MAAA;AAAA,IACvB;AAAA,IAED,cAAc;AAAA,MACb,MAAM;AAAA,MACN,UAAU;AAAA,MACV,kBAAkB;AAAA,QACjB,MAAM;AAAA,QACN,YAAY;AAAA,UACX,UAAU,EAAE,MAAM,SAAA;AAAA,UAClB,QAAQ;AAAA,YACP,MAAM;AAAA,YACN,YAAY,CAAA;AAAA,YACZ,UAAU,CAAA;AAAA,YACV,sBAAsB;AAAA,UAAA;AAAA,QACvB;AAAA,QAED,UAAU,CAAC,YAAY,QAAQ;AAAA,QAC/B,sBAAsB;AAAA,MAAA;AAAA,IACvB;AAAA,EACD;AAAA,EAED,6BAA6B;AAAA;AAAA;AAAA;AAAA,IAI5B,0BAA0B;AAAA,MACzB,MAAM;AAAA,MACN,cAAc;AAAA,MACd,UAAU;AAAA,MACV,kBAAkB;AAAA,QACjB,MAAM;AAAA,QACN,YAAY;AAAA,UACX,eAAe,EAAE,MAAM,SAAA;AAAA,QAAS;AAAA,QAEjC,UAAU,CAAC,eAAe;AAAA,QAC1B,sBAAsB;AAAA,MAAA;AAAA,IACvB;AAAA,EACD;AAEF;AAEA,SAAS,sBAAsB,eAA6D;AAC3F,SAAO,cACL,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAA,CAAM,EACnB,OAAO,OAAO,EACd,IAAI,CAAC,UAAU;AACf,UAAM,QAAQ,MAAM,QAAQ,MAAM;AAClC,UAAM,WAAW,UAAU,KAAK,MAAM,MAAM,GAAG,KAAK,EAAE,SAAS,MAAM,KAAA;AACrE,WAAO,EAAE,UAAU,MAAM,MAAA;AAAA,EAC1B,CAAC;AACH;AAyBO,SAAS,IAAI,WAA+B,kBAA0B;AAC5E,QAAM,oBAAoB,OAAO,KAAK,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,GAAG,CAAC;AAEnF,SAAO;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IAET,MAAM,UAAU,MAAM,IAAI;AACzB,YAAM,UAAU,GAAG,MAAM,GAAG,EAAE,CAAC,KAAK;AACpC,UAAI,CAAC,QAAQ,SAAS,KAAK,KAAK,CAAC,QAAQ,SAAS,KAAK,EAAG,QAAO;AACjE,UAAI,QAAQ,SAAS,gBAAgB,EAAG,QAAO;AAC/C,UAAI,CAAC,kBAAkB,KAAK,CAAC,YAAY,KAAK,SAAS,OAAO,CAAC,EAAG,QAAO;AAEzE,YAAM;AAEN,UAAI;AACJ,UAAI;AACH,SAAC,OAAO,IAAI,MAAM,IAAI;AAAA,MACvB,QAAQ;AACP,eAAO;AAAA,MACR;AAEA,YAAM,WAAW,QAAQ;AAAA,QACxB,CAAC,QAAQ,IAAI,MAAM,MAAM,IAAI,MAAM,UAAa,IAAI,KAAK;AAAA,MAAA;AAE1D,UAAI,SAAS,WAAW,EAAG,QAAO;AAElC,YAAM,IAAI,IAAI,YAAY,IAAI;AAC9B,UAAI,UAAU;AAEd,iBAAW,OAAO,UAAU;AAC3B,cAAM,EAAE,IAAI,OAAO,IAAI,KAAK,GAAG,cAAc;AAC7C,cAAM,YAAY,KAAK,MAAM,OAAO,GAAG;AAEvC,cAAM,YAAY,UAAU,QAAQ,GAAG;AACvC,cAAM,aAAa,UAAU,QAAQ,GAAG;AACxC,YAAI,cAAc,MAAM,eAAe,GAAI;AAE3C,cAAM,gBAAgB,UAAU,MAAM,YAAY,GAAG,UAAU;AAC/D,cAAM,iBAAiB,SAAS,SAAU;AAC1C,cAAM,eAAe,sBAAsB,aAAa;AACxD,cAAM,aAAa,aAAa,OAAO,CAAC,MAAM,EAAE,YAAY,cAAc;AAC1E,cAAM,eAAe,aAAa,OAAO,CAAC,MAAM,EAAE,EAAE,YAAY,eAAe;AAE/E,YAAI,WAAW,WAAW,EAAG;AAE7B,cAAM,QAAkB;AAAA,UACvB,YAAY,WAAW,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC,YAAY,cAAc,GAAG,SAAS;AAAA,QAAA;AAG3F,YAAI,aAAa,SAAS,GAAG;AAC5B,gBAAM;AAAA,YACL,YAAY,aAAa,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC,YAAY,SAAS;AAAA,UAAA;AAAA,QAE7E;AAEA,UAAE,UAAU,OAAO,KAAK,MAAM,KAAK,IAAI,CAAC;AACxC,kBAAU;AAAA,MACX;AAEA,UAAI,CAAC,QAAS,QAAO;AACrB,aAAO,EAAE,MAAM,EAAE,YAAY,KAAK,EAAE,YAAY,EAAE,OAAO,KAAA,CAAM,EAAA;AAAA,IAChE;AAAA,IAEA,UAAU,IAAI;AACb,UAAI,GAAG,WAAW,cAAc,UAAU,oBAAoB,GAAG,MAAM,eAAe,MAAM;AAC5F,aAAO;AAAA,IACR;AAAA,IAEA,KAAK,IAAI;AACR,UAAI,CAAC,GAAG,WAAW,iBAAiB,EAAG,QAAO;AAE9C,YAAM,YAAY,GAAG,MAAM,kBAAkB,MAAM;AACnD,YAAM,iBAAiB,SAAS,SAAS;AACzC,UAAI,CAAC,eAAgB,QAAO;AAG5B,YAAM,QAAkB,CAAC,iBAAiB;AAC1C,iBAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,cAAc,GAAG;AAC3D,cAAM,EAAE,MAAM,GAAG,IAAA,IAAQ;AACzB,cAAM,UACL,SAAS,SACN,sBACA,SAAS,wBACR,0BACA;AACL,cAAM;AAAA,UACL,gBAAgB,IAAI,MAAM,OAAO,IAAI,KAAK,UAAU,IAAI,CAAC,KAAK,KAAK,UAAU,GAAG,CAAC;AAAA,QAAA;AAAA,MAEnF;AACA,aAAO,MAAM,KAAK,IAAI;AAAA,IACvB;AAAA,EAAA;AAEF;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/providers/lds/index.ts"],"sourcesContent":["/**\n * Copyright (c) 2026, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nimport { readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { JSONSchema } from \"@conduit-client/jsonschema-validate\";\nimport { init, parse } from \"es-module-lexer\";\nimport MagicString from \"magic-string\";\nimport type { Plugin } from \"vite\";\nimport type { ReadInvokerShape } from \"./types\";\n\n// prefix to write into transformed source code\nconst ADAPTER_PREFIX = \"sf-lds-adapter:\";\n// prefix used to ID the adapter when loading the virtual module\nconst ADAPTER_ID_PREFIX = \"\\0\" + ADAPTER_PREFIX;\n\n// the source of the adapter base module — reused across virtual modules so\n// each generated specifier emits the factories once.\n//\n// Top-level exports from the runtime module are stripped so every factory and\n// `gql` becomes a private binding inside the virtual module. The load hook\n// then controls exactly which names are exported per specifier: adapter\n// entries from the registry, plus `gql` for graphql specifiers. Without this,\n// the built `runtime.js` (trailing `export { …, gql, createWireAdapter, … }`)\n// and the source `runtime.ts` (per-declaration `export function gql …`) both\n// produce a `SyntaxError: Duplicate export of 'gql'` when the load hook also\n// appends `export { gql };`. They also leak the factory names as exports on\n// every LDS virtual module, which isn't a public contract we want.\nconst adapterBaseSource = stripTopLevelExports(\n\treadFileSync(join(dirname(fileURLToPath(import.meta.url)), \"runtime.js\"), \"utf-8\"),\n);\n\n/**\n * Removes top-level ES-module `export` keywords from the embedded runtime\n * source so its declarations survive as private bindings inside the virtual\n * module. Handles two shapes:\n * 1. Per-declaration: `export function foo …` / `export async function foo`\n * → the `export ` prefix is dropped.\n * 2. Trailing re-export clause: `export { foo, bar };` → deleted entirely.\n * Inner occurrences (inside function bodies, comments, strings) are not\n * affected because the source is a flat module with exports only at column 0.\n */\nfunction stripTopLevelExports(source: string): string {\n\treturn source\n\t\t.replace(/^export\\s+(?=(?:async\\s+)?function\\s)/gm, \"\")\n\t\t.replace(/^export\\s*\\{[^}]*};?\\s*$/gm, \"\");\n}\n\n/**\n * MCP dispatch descriptor. Nested under `mcp` on every adapter config so\n * additional MCP-specific fields (auth, transport, retry policy) can join\n * later without reshaping every consumer entry.\n */\nexport interface LdsAdapterMcpDispatch {\n\ttoolName: string;\n}\n\n/**\n * Base shape every LDS adapter config extends. Holds the dispatch surface in\n * one place so new backings (e.g. `http`) can land as sibling optional fields\n * without forking each adapter interface. Dual registration is supported at\n * the type level — runtime execution still targets a single backing per call.\n */\nexport interface LdsAdapterConfigBase {\n\tmcp?: LdsAdapterMcpDispatch;\n}\n\n/**\n * LDS adapter configs whose input is validated against a JSON Schema at\n * invoke time — wire, imperative-mutation, imperative-read. GraphQL variants\n * skip this base because they pass `{ query, variables }` through to the\n * configured MCP tool with no schema check.\n */\nexport interface LdsSchemaValidatedAdapterConfig extends LdsAdapterConfigBase {\n\tconfigJsonSchema: JSONSchema;\n}\n\nexport interface LdsWireAdapterConfig extends LdsSchemaValidatedAdapterConfig {\n\ttype: \"wire\";\n}\n\n/**\n * Imperative **mutation** adapter. Always an async\n * `(config) => Promise<Data>` that throws on validation or tool error —\n * matching OneStore's `DefaultImperativeBindingsService`, the only service a\n * mutation ever uses on platform. Mutations do not carry an `invokerShape`:\n * `subscribe`/`refresh` make no sense on write, and allowing them here\n * would drift off-platform from on-platform semantics.\n */\nexport interface LdsImperativeMutationAdapterConfig extends LdsSchemaValidatedAdapterConfig {\n\ttype: \"imperative-mutation\";\n}\n\n/**\n * Public alias for the read-shape union defined in `runtime.ts`. Re-exported\n * from this module so consumers don't have to import from the runtime entry\n * point, while keeping the union pinned to one source of truth.\n *\n * Off-platform there is no store, so `subscribe` is a deliberate no-op\n * (callback never fires, returned unsubscribe is idempotent) and `refresh`\n * re-executes the underlying MCP tool. This preserves the OneStore API\n * surface for code ported verbatim.\n */\nexport type LdsImperativeReadInvokerShape = ReadInvokerShape;\n\nexport interface LdsImperativeReadAdapterConfig extends LdsSchemaValidatedAdapterConfig {\n\ttype: \"imperative-read\";\n\tinvokerShape: LdsImperativeReadInvokerShape;\n}\n\n/**\n * GraphQL wire adapter. Emits `{ data, errors, refresh }` (distinct from the\n * base wire `{ data, error }`). No `configJsonSchema` — the adapter passes\n * `{ query, variables }` through to the configured MCP tool.\n */\nexport interface LdsGraphqlWireAdapterConfig extends LdsAdapterConfigBase {\n\ttype: \"graphql-wire\";\n}\n\n/**\n * Imperative GraphQL mutation — `(config) => Promise<{ data, errors }>`.\n * Errors are routed in-band to the `errors[]` envelope rather than thrown,\n * matching on-platform `toGraphQLResponseFromFailure`.\n */\nexport interface LdsGraphqlMutationAdapterConfig extends LdsAdapterConfigBase {\n\ttype: \"graphql-mutation\";\n}\n\n/**\n * Read-shape discriminator for imperative GraphQL adapters. Mirrors the\n * `imperative-read` `invokerShape` field so the two families share a pattern:\n * one `type` discriminator + a shape field that selects the return surface.\n *\n * - `query` — `Promise<{ data, errors, subscribe }>` (on-platform\n * `GraphQLImperativeBindingsService` without `exposeRefresh`).\n * - `query-refreshable` — `Promise<{ data, errors, subscribe, refresh }>`\n * (same service with `exposeRefresh: true`).\n * - `legacy` — `{ invoke(config, context, callback),\n * subscribe(config, context, callback): Unsubscribe }`, the older callback\n * surface served by `GraphQLLegacyImperativeBindingsService`.\n *\n * `subscribe` is a deliberate no-op off-platform (no reactive store).\n */\nexport type LdsGraphqlImperativeReadInvokerShape = \"query\" | \"query-refreshable\" | \"legacy\";\n\n/**\n * Imperative GraphQL read adapter. The `invokerShape` picks the return\n * surface — see {@link LdsGraphqlImperativeReadInvokerShape}. Errors are\n * routed in-band to `errors[]` (for `query`/`query-refreshable`) or into the\n * callback payload (for `legacy`); no shape throws on tool errors.\n */\nexport interface LdsGraphqlImperativeReadAdapterConfig extends LdsAdapterConfigBase {\n\ttype: \"graphql-imperative-read\";\n\tinvokerShape: LdsGraphqlImperativeReadInvokerShape;\n}\n\nexport type LdsAdapterConfig =\n\t| LdsWireAdapterConfig\n\t| LdsImperativeMutationAdapterConfig\n\t| LdsImperativeReadAdapterConfig\n\t| LdsGraphqlWireAdapterConfig\n\t| LdsGraphqlMutationAdapterConfig\n\t| LdsGraphqlImperativeReadAdapterConfig;\n\nexport type LdsAdapterRegistry = Record<string, Record<string, LdsAdapterConfig>>;\n\n/**\n * Default adapter registry.\n * Maps LDS module specifiers to MCP tool-backed implementations. Entries can be\n * wire adapters (`type: 'wire'`), imperative mutations (`type: 'imperative-mutation'`),\n * or imperative reads (`type: 'imperative-read'` + `invokerShape`).\n * Add entries here to support additional lightning/* exports.\n */\nconst DEFAULT_ADAPTERS: LdsAdapterRegistry = {\n\t\"lightning/uiRecordApi\": {\n\t\tgetRecord: {\n\t\t\ttype: \"wire\",\n\t\t\tmcp: { toolName: \"getRecordMcpTool\" },\n\t\t\tconfigJsonSchema: {\n\t\t\t\ttype: \"object\",\n\t\t\t\tproperties: {\n\t\t\t\t\trecordId: { type: \"string\" },\n\t\t\t\t\tlayoutTypes: {\n\t\t\t\t\t\tanyOf: [{ type: \"array\", items: { type: \"string\" } }, { type: \"null\" }],\n\t\t\t\t\t},\n\t\t\t\t\tfields: {\n\t\t\t\t\t\tanyOf: [{ type: \"array\", items: { type: \"string\" } }, { type: \"null\" }],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\trequired: [\"recordId\"],\n\t\t\t\tadditionalProperties: false,\n\t\t\t\tanyOf: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tfields: { type: \"array\", items: { type: \"string\" }, minItems: 1 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\trequired: [\"fields\"],\n\t\t\t\t\t\tadditionalProperties: true,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tlayoutTypes: {\n\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\titems: { type: \"string\" },\n\t\t\t\t\t\t\t\tminItems: 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\trequired: [\"layoutTypes\"],\n\t\t\t\t\t\tadditionalProperties: true,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t},\n\t\tcreateRecord: {\n\t\t\ttype: \"imperative-mutation\",\n\t\t\tmcp: { toolName: \"createRecordMcpTool\" },\n\t\t\tconfigJsonSchema: {\n\t\t\t\ttype: \"object\",\n\t\t\t\tproperties: {\n\t\t\t\t\tapiName: { type: \"string\" },\n\t\t\t\t\tfields: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {},\n\t\t\t\t\t\trequired: [],\n\t\t\t\t\t\tadditionalProperties: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\trequired: [\"apiName\", \"fields\"],\n\t\t\t\tadditionalProperties: false,\n\t\t\t},\n\t\t},\n\t\tupdateRecord: {\n\t\t\ttype: \"imperative-mutation\",\n\t\t\tmcp: { toolName: \"updateRecordMcpTool\" },\n\t\t\tconfigJsonSchema: {\n\t\t\t\ttype: \"object\",\n\t\t\t\tproperties: {\n\t\t\t\t\trecordId: { type: \"string\" },\n\t\t\t\t\tfields: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {},\n\t\t\t\t\t\trequired: [],\n\t\t\t\t\t\tadditionalProperties: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\trequired: [\"recordId\", \"fields\"],\n\t\t\t\tadditionalProperties: false,\n\t\t\t},\n\t\t},\n\t},\n\t\"lightning/uiObjectInfoApi\": {\n\t\t// On-platform this is a `{ invoke, subscribe }` callback surface\n\t\t// emitting `{ data, error }`. The legacy invoker shape preserves that\n\t\t// contract verbatim, so ported consumers keep their call sites.\n\t\tgetObjectInfo_imperative: {\n\t\t\ttype: \"imperative-read\",\n\t\t\tinvokerShape: \"legacy\",\n\t\t\tmcp: { toolName: \"getObjectInfoMcpTool\" },\n\t\t\tconfigJsonSchema: {\n\t\t\t\ttype: \"object\",\n\t\t\t\tproperties: {\n\t\t\t\t\tobjectApiName: { type: \"string\" },\n\t\t\t\t},\n\t\t\t\trequired: [\"objectApiName\"],\n\t\t\t\tadditionalProperties: false,\n\t\t\t},\n\t\t},\n\t},\n\t// `lightning/graphql` — on-platform exports `gql`, the `graphql` wire\n\t// adapter, and `executeMutation`. Only `graphql` and `executeMutation`\n\t// are registry entries; `gql` rides along automatically for any specifier\n\t// that has at least one graphql-typed entry (emitted by the load hook).\n\t\"lightning/graphql\": {\n\t\tgraphql: { type: \"graphql-wire\", mcp: { toolName: \"graphqlQuery\" } },\n\t\texecuteMutation: { type: \"graphql-mutation\", mcp: { toolName: \"graphqlQuery\" } },\n\t},\n};\n\n/** True when any entry in a module's adapter map is a `graphql-*` type. */\nfunction isGraphqlSpecifier(moduleAdapters: Record<string, LdsAdapterConfig>): boolean {\n\treturn Object.values(moduleAdapters).some(\n\t\t(entry) =>\n\t\t\tentry.type === \"graphql-wire\" ||\n\t\t\tentry.type === \"graphql-mutation\" ||\n\t\t\tentry.type === \"graphql-imperative-read\",\n\t);\n}\n\n/** Maps a config discriminator to the factory name emitted in the virtual module. */\nfunction factoryFor(type: LdsAdapterConfig[\"type\"]): string {\n\tswitch (type) {\n\t\tcase \"wire\":\n\t\t\treturn \"createWireAdapter\";\n\t\tcase \"imperative-mutation\":\n\t\t\treturn \"createMutationAdapter\";\n\t\tcase \"imperative-read\":\n\t\t\treturn \"createReadAdapter\";\n\t\tcase \"graphql-wire\":\n\t\t\treturn \"createGraphQLWireAdapter\";\n\t\tcase \"graphql-mutation\":\n\t\t\treturn \"createGraphQLMutationAdapter\";\n\t\tcase \"graphql-imperative-read\":\n\t\t\treturn \"createGraphQLImperativeReadAdapter\";\n\t}\n}\n\nfunction parseImportSpecifiers(bracesContent: string): { original: string; full: string }[] {\n\treturn bracesContent\n\t\t.split(\",\")\n\t\t.map((s) => s.trim())\n\t\t.filter(Boolean)\n\t\t.map((entry) => {\n\t\t\tconst asIdx = entry.indexOf(\" as \");\n\t\t\tconst original = asIdx !== -1 ? entry.slice(0, asIdx).trim() : entry.trim();\n\t\t\treturn { original, full: entry };\n\t\t});\n}\n\n/**\n * Deep-merges user overrides onto the default registry: every specifier from\n * both sides is preserved, and per-specifier entries are merged so a consumer\n * can override `getRecord` without losing `createRecord`, or register a new\n * entry on `lightning/graphql` without losing `graphql` / `executeMutation`.\n * Pass an empty object to get just the defaults. To opt out of a default\n * entry, pass the same specifier with a different entry of the same key.\n */\nfunction mergeWithDefaults(overrides: LdsAdapterRegistry): LdsAdapterRegistry {\n\tconst merged: LdsAdapterRegistry = { ...DEFAULT_ADAPTERS };\n\tfor (const [specifier, entries] of Object.entries(overrides)) {\n\t\tmerged[specifier] = { ...(DEFAULT_ADAPTERS[specifier] ?? {}), ...entries };\n\t}\n\treturn merged;\n}\n\n/**\n * LDS provider — rewrites registered `lightning/*` imports (e.g.\n * `lightning/uiRecordApi`) to MCP-tool-backed virtual modules. Unregistered\n * exports pass through to the normal `lightning/*` resolution.\n *\n * Three Vite hooks do the work:\n *\n * - **`transform`** — parses each `.js` / `.ts` file with `es-module-lexer`,\n * finds named imports from registered specifiers, and rewrites them to pull\n * registered names from `sf-lds-adapter:<specifier>` while leaving\n * unregistered names pointing at the original specifier.\n *\n * - **`resolveId`** — maps `sf-lds-adapter:<specifier>` to a `\\0`-prefixed\n * virtual module ID, preventing Rollup from attempting a filesystem lookup.\n *\n * - **`load`** — generates the virtual module, emitting an MCP-backed\n * `createWireAdapter(...)` class for every `type: 'wire'` entry,\n * `createMutationAdapter(...)` for every `type: 'imperative-mutation'` entry,\n * and `createReadAdapter(...)` for every `type: 'imperative-read'` entry.\n *\n * Only specifiers present in the `adapters` registry are intercepted; imports from\n * unregistered specifiers pass through unchanged.\n */\nexport function lds(overrides: LdsAdapterRegistry = {}): Plugin {\n\tconst adapters = mergeWithDefaults(overrides);\n\t// Graphql specifiers are owned whole by the virtual module — every export\n\t// (adapters + `gql`) lives there, so the transform hook should not split\n\t// their imports. Non-graphql specifiers still go through transform so\n\t// unregistered names pass through to the real `lightning/*` module.\n\tconst graphqlSpecifiers = new Set<string>(\n\t\tObject.entries(adapters)\n\t\t\t.filter(([, moduleAdapters]) => isGraphqlSpecifier(moduleAdapters))\n\t\t\t.map(([specifier]) => specifier),\n\t);\n\tconst transformSpecifiers = Object.keys(adapters).filter((s) => !graphqlSpecifiers.has(s));\n\tconst specifierSnippets = transformSpecifiers.flatMap((s) => [`'${s}'`, `\"${s}\"`]);\n\n\treturn {\n\t\tname: \"vite-plugin-lds\",\n\t\tenforce: \"pre\",\n\n\t\tasync transform(code, id) {\n\t\t\tconst cleanId = id.split(\"?\")[0] ?? id;\n\t\t\tif (!cleanId.endsWith(\".js\") && !cleanId.endsWith(\".ts\")) return null;\n\t\t\tif (cleanId.includes(\"/node_modules/\")) return null;\n\t\t\tif (!specifierSnippets.some((snippet) => code.includes(snippet))) return null;\n\n\t\t\tawait init;\n\n\t\t\tlet imports: ReturnType<typeof parse>[0];\n\t\t\ttry {\n\t\t\t\t[imports] = parse(code);\n\t\t\t} catch {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst relevant = imports.filter(\n\t\t\t\t(imp) =>\n\t\t\t\t\timp.d === -1 && imp.n !== undefined && imp.n in adapters && !graphqlSpecifiers.has(imp.n),\n\t\t\t);\n\t\t\tif (relevant.length === 0) return null;\n\n\t\t\tconst s = new MagicString(code);\n\t\t\tlet changed = false;\n\n\t\t\tfor (const imp of relevant) {\n\t\t\t\tconst { ss: start, se: end, n: specifier } = imp;\n\t\t\t\tconst statement = code.slice(start, end);\n\n\t\t\t\tconst openBrace = statement.indexOf(\"{\");\n\t\t\t\tconst closeBrace = statement.indexOf(\"}\");\n\t\t\t\tif (openBrace === -1 || closeBrace === -1) continue;\n\n\t\t\t\tconst bracesContent = statement.slice(openBrace + 1, closeBrace);\n\t\t\t\tconst moduleAdapters = adapters[specifier!]!;\n\t\t\t\tconst parsedImport = parseImportSpecifiers(bracesContent);\n\t\t\t\tconst registered = parsedImport.filter((p) => p.original in moduleAdapters);\n\t\t\t\tconst unregistered = parsedImport.filter((p) => !(p.original in moduleAdapters));\n\n\t\t\t\tif (registered.length === 0) continue;\n\n\t\t\t\tconst parts: string[] = [\n\t\t\t\t\t`import { ${registered.map((p) => p.full).join(\", \")} } from '${ADAPTER_PREFIX}${specifier}';`,\n\t\t\t\t];\n\n\t\t\t\tif (unregistered.length > 0) {\n\t\t\t\t\tparts.push(\n\t\t\t\t\t\t`import { ${unregistered.map((p) => p.full).join(\", \")} } from '${specifier}';`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\ts.overwrite(start, end, parts.join(\"\\n\"));\n\t\t\t\tchanged = true;\n\t\t\t}\n\n\t\t\tif (!changed) return null;\n\t\t\treturn { code: s.toString(), map: s.generateMap({ hires: true }) };\n\t\t},\n\n\t\tresolveId(id) {\n\t\t\t// Graphql specifiers are intercepted raw — no transform hook split\n\t\t\t// — and mapped into the same `\\0sf-lds-adapter:` virtual namespace\n\t\t\t// so the load hook emits one module per specifier.\n\t\t\tif (graphqlSpecifiers.has(id)) return ADAPTER_ID_PREFIX + id;\n\t\t\tif (id.startsWith(ADAPTER_PREFIX)) return ADAPTER_ID_PREFIX + id.slice(ADAPTER_PREFIX.length);\n\t\t\treturn null;\n\t\t},\n\n\t\tload(id) {\n\t\t\tif (!id.startsWith(ADAPTER_ID_PREFIX)) return null;\n\n\t\t\tconst specifier = id.slice(ADAPTER_ID_PREFIX.length);\n\t\t\tconst moduleAdapters = adapters[specifier];\n\t\t\tif (!moduleAdapters) return null;\n\n\t\t\t// create lines of code used to create MCP tool based adapters\n\t\t\tconst lines: string[] = [adapterBaseSource];\n\t\t\tfor (const [name, entry] of Object.entries(moduleAdapters)) {\n\t\t\t\tconst { type, ...cfg } = entry;\n\t\t\t\tlines.push(\n\t\t\t\t\t`export const ${name} = ${factoryFor(type)}(${JSON.stringify(name)}, ${JSON.stringify(cfg)});`,\n\t\t\t\t);\n\t\t\t}\n\t\t\t// `gql` rides along with any specifier that declares a graphql\n\t\t\t// adapter, so `import { gql } from 'lightning/graphql'` (or any\n\t\t\t// aliased form) keeps resolving even when no adapters are\n\t\t\t// imported alongside it. The binding itself is a private function\n\t\t\t// inside `adapterBaseSource` after `stripTopLevelExports`.\n\t\t\tif (graphqlSpecifiers.has(specifier)) {\n\t\t\t\tlines.push(\"export { gql };\");\n\t\t\t}\n\t\t\treturn lines.join(\"\\n\");\n\t\t},\n\t};\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { buildDefaultImperativeBindingsServiceDescriptor, buildQueryImperativeBindingsServiceDescriptor, buildSubscribableImperativeBindingsServiceDescriptor, buildLegacyImperativeBindingsServiceDescriptor } from "@conduit-client/service-bindings-imperative/v1";
|
|
2
2
|
import { buildLWCWireBindingsServiceDescriptor } from "@conduit-client/service-bindings-lwc/v1";
|
|
3
3
|
import { err, ok, toError, buildSubscribableResult } from "@conduit-client/utils";
|
|
4
|
-
import { getChatSDK } from "@salesforce/sdk-chat";
|
|
4
|
+
import { getChatSDK } from "@salesforce/platform-sdk-chat";
|
|
5
5
|
function normalizeMcpResponse(raw) {
|
|
6
6
|
if (raw && typeof raw === "object" && "structuredContent" in raw) {
|
|
7
7
|
return raw.structuredContent;
|
|
@@ -22,6 +22,22 @@ function normalizeMcpResponse(raw) {
|
|
|
22
22
|
}
|
|
23
23
|
return raw ?? {};
|
|
24
24
|
}
|
|
25
|
+
function resolveMcpToolName(adapterName, cfg) {
|
|
26
|
+
const toolName = cfg.mcp?.toolName;
|
|
27
|
+
if (!toolName) {
|
|
28
|
+
throw new Error(`[${adapterName}] no dispatch backing configured — expected \`mcp.toolName\`.`);
|
|
29
|
+
}
|
|
30
|
+
return toolName;
|
|
31
|
+
}
|
|
32
|
+
async function getCallTool(adapterName) {
|
|
33
|
+
const sdk = await getChatSDK();
|
|
34
|
+
if (typeof sdk.callTool !== "function") {
|
|
35
|
+
throw new Error(
|
|
36
|
+
`[${adapterName}] sdk.callTool is not available on this surface. Make sure window.openai is configured or the component is running in an MCP Apps / OpenAI chat context.`
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
return sdk.callTool.bind(sdk);
|
|
40
|
+
}
|
|
25
41
|
function extractToolErrorText(raw) {
|
|
26
42
|
const content = raw.content;
|
|
27
43
|
if (!Array.isArray(content)) return "";
|
|
@@ -41,15 +57,8 @@ class McpToolCommand {
|
|
|
41
57
|
}
|
|
42
58
|
async execute() {
|
|
43
59
|
try {
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
return err(
|
|
47
|
-
new Error(
|
|
48
|
-
`[${this.adapterName}] sdk.callTool is not available on this surface. Make sure window.openai is configured or the component is running in an MCP Apps / OpenAI chat context.`
|
|
49
|
-
)
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
const raw = await app.callTool({
|
|
60
|
+
const callTool = await getCallTool(this.adapterName);
|
|
61
|
+
const raw = await callTool({
|
|
53
62
|
toolName: this.toolName,
|
|
54
63
|
params: this.params ?? void 0
|
|
55
64
|
});
|
|
@@ -81,6 +90,13 @@ class McpToolSubscribableCommand {
|
|
|
81
90
|
this.unwrap
|
|
82
91
|
);
|
|
83
92
|
const result = await base.execute();
|
|
93
|
+
const subscribers = /* @__PURE__ */ new Set();
|
|
94
|
+
const subscribe = (cb) => {
|
|
95
|
+
subscribers.add(cb);
|
|
96
|
+
return () => {
|
|
97
|
+
subscribers.delete(cb);
|
|
98
|
+
};
|
|
99
|
+
};
|
|
84
100
|
const refresh = async () => {
|
|
85
101
|
const next = await new McpToolCommand(
|
|
86
102
|
this.adapterName,
|
|
@@ -88,9 +104,10 @@ class McpToolSubscribableCommand {
|
|
|
88
104
|
this.params,
|
|
89
105
|
this.unwrap
|
|
90
106
|
).execute();
|
|
107
|
+
subscribers.forEach((cb) => cb(next));
|
|
91
108
|
return next.isOk() ? ok(void 0) : err(next.error);
|
|
92
109
|
};
|
|
93
|
-
return buildSubscribableResult(result,
|
|
110
|
+
return buildSubscribableResult(result, subscribe, refresh);
|
|
94
111
|
}
|
|
95
112
|
}
|
|
96
113
|
const defaultImperativeService = buildDefaultImperativeBindingsServiceDescriptor().service;
|
|
@@ -98,23 +115,25 @@ const queryImperativeService = buildQueryImperativeBindingsServiceDescriptor().s
|
|
|
98
115
|
const subscribableImperativeService = buildSubscribableImperativeBindingsServiceDescriptor().service;
|
|
99
116
|
const legacyImperativeService = buildLegacyImperativeBindingsServiceDescriptor().service;
|
|
100
117
|
function createMutationAdapter(name, cfg) {
|
|
118
|
+
const toolName = resolveMcpToolName(name, cfg);
|
|
101
119
|
const getCommand = (options) => {
|
|
102
120
|
options.assertIsValid(options.params[0], cfg.configJsonSchema);
|
|
103
|
-
return new McpToolCommand(name,
|
|
121
|
+
return new McpToolCommand(name, toolName, options.params[0]);
|
|
104
122
|
};
|
|
105
123
|
const invoker = defaultImperativeService.bind(getCommand);
|
|
106
124
|
return (...params) => Promise.resolve(invoker(...params));
|
|
107
125
|
}
|
|
108
126
|
function createReadAdapter(name, cfg) {
|
|
127
|
+
const toolName = resolveMcpToolName(name, cfg);
|
|
109
128
|
const getSubscribableCommand = (options) => {
|
|
110
129
|
options.assertIsValid(options.params[0], cfg.configJsonSchema);
|
|
111
|
-
return new McpToolSubscribableCommand(name,
|
|
130
|
+
return new McpToolSubscribableCommand(name, toolName, options.params[0]);
|
|
112
131
|
};
|
|
113
132
|
switch (cfg.invokerShape) {
|
|
114
133
|
case "query": {
|
|
115
134
|
const getCommand = (options) => {
|
|
116
135
|
options.assertIsValid(options.params[0], cfg.configJsonSchema);
|
|
117
|
-
return new McpToolCommand(name,
|
|
136
|
+
return new McpToolCommand(name, toolName, options.params[0]);
|
|
118
137
|
};
|
|
119
138
|
const invoker = queryImperativeService.bind(getCommand);
|
|
120
139
|
return (...params) => Promise.resolve(invoker(...params));
|
|
@@ -136,7 +155,7 @@ function createReadAdapter(name, cfg) {
|
|
|
136
155
|
case "legacy": {
|
|
137
156
|
const getLegacyCommand = (options) => {
|
|
138
157
|
options.assertIsValid(options.config, cfg.configJsonSchema);
|
|
139
|
-
return new McpToolSubscribableCommand(name,
|
|
158
|
+
return new McpToolSubscribableCommand(name, toolName, options.config);
|
|
140
159
|
};
|
|
141
160
|
return legacyImperativeService.bind(getLegacyCommand);
|
|
142
161
|
}
|
|
@@ -155,14 +174,155 @@ function unwrapWireEnvelope(payload) {
|
|
|
155
174
|
return ok(envelope?.data);
|
|
156
175
|
}
|
|
157
176
|
function createWireAdapter(name, cfg) {
|
|
177
|
+
const toolName = resolveMcpToolName(name, cfg);
|
|
158
178
|
return lwcWireBindingsService.bind(
|
|
159
|
-
(config) => new McpToolCommand(name,
|
|
179
|
+
(config) => new McpToolCommand(name, toolName, config, unwrapWireEnvelope),
|
|
160
180
|
cfg.configJsonSchema
|
|
161
181
|
);
|
|
162
182
|
}
|
|
183
|
+
function gql(strings, ...values) {
|
|
184
|
+
let result = "";
|
|
185
|
+
strings.forEach((string, i) => {
|
|
186
|
+
result += string;
|
|
187
|
+
if (i < values.length) result += String(values[i]);
|
|
188
|
+
});
|
|
189
|
+
return result.trim();
|
|
190
|
+
}
|
|
191
|
+
async function runGraphqlQuery(adapterName, toolName, config) {
|
|
192
|
+
const { query, variables } = config;
|
|
193
|
+
if (!query) return { data: void 0, errors: void 0 };
|
|
194
|
+
const callTool = await getCallTool(adapterName);
|
|
195
|
+
const raw = await callTool({
|
|
196
|
+
toolName,
|
|
197
|
+
params: { query, variables: variables ?? {} }
|
|
198
|
+
});
|
|
199
|
+
return normalizeMcpResponse(raw) ?? {};
|
|
200
|
+
}
|
|
201
|
+
function toGraphqlErrorResult(error) {
|
|
202
|
+
return { data: void 0, errors: [{ message: error.message }] };
|
|
203
|
+
}
|
|
204
|
+
async function runGraphqlQuerySafe(adapterName, toolName, config) {
|
|
205
|
+
try {
|
|
206
|
+
return await runGraphqlQuery(adapterName, toolName, config);
|
|
207
|
+
} catch (error) {
|
|
208
|
+
return toGraphqlErrorResult(error);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
function createGraphQLWireAdapter(name, cfg) {
|
|
212
|
+
const toolName = resolveMcpToolName(name, cfg);
|
|
213
|
+
return class {
|
|
214
|
+
_dataCallback;
|
|
215
|
+
_config;
|
|
216
|
+
_connected = false;
|
|
217
|
+
constructor(dataCallback) {
|
|
218
|
+
this._dataCallback = dataCallback;
|
|
219
|
+
}
|
|
220
|
+
connect() {
|
|
221
|
+
this._connected = true;
|
|
222
|
+
void this._fetch();
|
|
223
|
+
}
|
|
224
|
+
disconnect() {
|
|
225
|
+
this._connected = false;
|
|
226
|
+
}
|
|
227
|
+
update(config) {
|
|
228
|
+
this._config = config;
|
|
229
|
+
if (!this._connected || this._config === void 0) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
void this._fetch();
|
|
233
|
+
}
|
|
234
|
+
refresh() {
|
|
235
|
+
return this._fetch();
|
|
236
|
+
}
|
|
237
|
+
async _fetch() {
|
|
238
|
+
this._emit(await runGraphqlQuerySafe(name, toolName, this._config ?? {}));
|
|
239
|
+
}
|
|
240
|
+
_emit({ data, errors }) {
|
|
241
|
+
this._dataCallback({
|
|
242
|
+
data,
|
|
243
|
+
errors: errors?.length ? errors : void 0,
|
|
244
|
+
refresh: () => this.refresh()
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
function createGraphQLMutationAdapter(name, cfg) {
|
|
250
|
+
const toolName = resolveMcpToolName(name, cfg);
|
|
251
|
+
return async (config) => {
|
|
252
|
+
if (!config?.query) return { data: void 0, errors: [{ message: "No query provided" }] };
|
|
253
|
+
return runGraphqlQuerySafe(name, toolName, config);
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
function createGraphQLImperativeReadAdapter(name, cfg) {
|
|
257
|
+
const toolName = resolveMcpToolName(name, cfg);
|
|
258
|
+
if (cfg.invokerShape === "legacy") {
|
|
259
|
+
async function run(config, callback) {
|
|
260
|
+
if (!config?.query) {
|
|
261
|
+
callback({ data: void 0, errors: void 0 });
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
const result = await runGraphqlQuerySafe(name, toolName, config);
|
|
265
|
+
callback({
|
|
266
|
+
data: result.data,
|
|
267
|
+
errors: result.errors?.length ? result.errors : void 0
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
return {
|
|
271
|
+
invoke(config, _context, callback) {
|
|
272
|
+
void run(config, callback);
|
|
273
|
+
},
|
|
274
|
+
subscribe(config, _context, callback) {
|
|
275
|
+
void run(config, callback);
|
|
276
|
+
return noopUnsubscribe;
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
if (cfg.invokerShape === "query-refreshable") {
|
|
281
|
+
return async (config) => {
|
|
282
|
+
const result = await runGraphqlQuerySafe(name, toolName, config);
|
|
283
|
+
if (result.errors?.length) {
|
|
284
|
+
return { data: void 0, errors: result.errors };
|
|
285
|
+
}
|
|
286
|
+
const subscribers = /* @__PURE__ */ new Set();
|
|
287
|
+
return {
|
|
288
|
+
data: result.data,
|
|
289
|
+
errors: void 0,
|
|
290
|
+
subscribe: (cb) => {
|
|
291
|
+
subscribers.add(cb);
|
|
292
|
+
return () => {
|
|
293
|
+
subscribers.delete(cb);
|
|
294
|
+
};
|
|
295
|
+
},
|
|
296
|
+
refresh: async () => {
|
|
297
|
+
const fresh = await runGraphqlQuerySafe(name, toolName, config);
|
|
298
|
+
const payload = {
|
|
299
|
+
data: fresh.data,
|
|
300
|
+
errors: fresh.errors?.length ? fresh.errors : void 0
|
|
301
|
+
};
|
|
302
|
+
subscribers.forEach((cb) => cb(payload));
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
return async (config) => {
|
|
308
|
+
const result = await runGraphqlQuerySafe(name, toolName, config);
|
|
309
|
+
if (result.errors?.length) {
|
|
310
|
+
return { data: void 0, errors: result.errors };
|
|
311
|
+
}
|
|
312
|
+
return {
|
|
313
|
+
data: result.data,
|
|
314
|
+
errors: void 0,
|
|
315
|
+
subscribe: noopSubscribe
|
|
316
|
+
};
|
|
317
|
+
};
|
|
318
|
+
}
|
|
163
319
|
export {
|
|
320
|
+
createGraphQLImperativeReadAdapter,
|
|
321
|
+
createGraphQLMutationAdapter,
|
|
322
|
+
createGraphQLWireAdapter,
|
|
164
323
|
createMutationAdapter,
|
|
165
324
|
createReadAdapter,
|
|
166
|
-
createWireAdapter
|
|
325
|
+
createWireAdapter,
|
|
326
|
+
gql
|
|
167
327
|
};
|
|
168
328
|
//# sourceMappingURL=runtime.js.map
|