@kaleabdenbel/llmweb 1.0.2 → 1.0.3
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 +1 -0
- package/dist/adapters/express.js +17 -7
- package/dist/adapters/express.mjs +131 -3
- package/dist/adapters/next.js +17 -7
- package/dist/adapters/next.mjs +131 -3
- package/dist/adapters/react.js +77 -15
- package/dist/adapters/react.mjs +182 -4
- package/dist/adapters/vanilla.js +17 -7
- package/dist/adapters/vanilla.mjs +131 -3
- package/dist/index.browser.js +175 -0
- package/dist/{chunk-HRF6I6KB.mjs → index.browser.mjs} +26 -21
- package/dist/index.js +29 -19
- package/dist/index.mjs +143 -6
- package/package.json +5 -3
- package/dist/adapters/express.d.ts +0 -5
- package/dist/adapters/next.d.ts +0 -18
- package/dist/adapters/react.d.ts +0 -15
- package/dist/adapters/vanilla.d.ts +0 -5
- package/dist/core/injector.d.ts +0 -11
- package/dist/core/merger.d.ts +0 -7
- package/dist/core/resolver.d.ts +0 -12
- package/dist/core/transformer.d.ts +0 -7
- package/dist/index.d.ts +0 -8
- package/dist/types/index.d.ts +0 -23
package/dist/adapters/react.mjs
CHANGED
|
@@ -1,7 +1,145 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
// src/adapters/react.tsx
|
|
2
|
+
import React from "react";
|
|
3
|
+
|
|
4
|
+
// src/core/resolver.ts
|
|
5
|
+
async function resolveAll(dynamicSources, options = {}) {
|
|
6
|
+
const keys = Object.keys(dynamicSources);
|
|
7
|
+
const results = await Promise.allSettled(
|
|
8
|
+
keys.map((key) => resolveSource(dynamicSources[key], options.timeout))
|
|
9
|
+
);
|
|
10
|
+
const data = {};
|
|
11
|
+
results.forEach((result, index) => {
|
|
12
|
+
const key = keys[index];
|
|
13
|
+
if (result.status === "fulfilled") {
|
|
14
|
+
data[key] = result.value;
|
|
15
|
+
} else {
|
|
16
|
+
console.error(`[llmweb] Failed to resolve source "${key}":`, result.reason);
|
|
17
|
+
data[key] = null;
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
return data;
|
|
21
|
+
}
|
|
22
|
+
async function resolveSource(source, timeoutMs) {
|
|
23
|
+
const { from } = source;
|
|
24
|
+
const controller = timeoutMs ? new AbortController() : null;
|
|
25
|
+
const signal = controller?.signal;
|
|
26
|
+
const timeoutPromise = timeoutMs ? new Promise(
|
|
27
|
+
(_, reject) => setTimeout(() => {
|
|
28
|
+
controller?.abort();
|
|
29
|
+
reject(new Error(`Timeout of ${timeoutMs}ms exceeded`));
|
|
30
|
+
}, timeoutMs)
|
|
31
|
+
) : null;
|
|
32
|
+
const resolvePromise = (async () => {
|
|
33
|
+
if (from.type === "fetch") {
|
|
34
|
+
if (!from.url) throw new Error("Fetch source requires a URL");
|
|
35
|
+
const response = await fetch(from.url, { signal });
|
|
36
|
+
if (!response.ok) throw new Error(`HTTP error ${response.status} for ${from.url}`);
|
|
37
|
+
return response.json();
|
|
38
|
+
}
|
|
39
|
+
if (from.type === "fn") {
|
|
40
|
+
if (!from.call) throw new Error('Function source requires a "call" property');
|
|
41
|
+
return from.call();
|
|
42
|
+
}
|
|
43
|
+
throw new Error(`Unsupported source type: ${from.type}`);
|
|
44
|
+
})();
|
|
45
|
+
if (timeoutPromise) {
|
|
46
|
+
return Promise.race([resolvePromise, timeoutPromise]);
|
|
47
|
+
}
|
|
48
|
+
return resolvePromise;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// src/core/transformer.ts
|
|
52
|
+
function transform(sourceData, schema) {
|
|
53
|
+
if (!sourceData) return sourceData;
|
|
54
|
+
if (Array.isArray(sourceData)) {
|
|
55
|
+
return sourceData.map((item) => transform(item, schema));
|
|
56
|
+
}
|
|
57
|
+
if (typeof sourceData !== "object") return sourceData;
|
|
58
|
+
const result = {};
|
|
59
|
+
for (const [targetKey, mapping] of Object.entries(schema)) {
|
|
60
|
+
if (typeof mapping === "string") {
|
|
61
|
+
result[targetKey] = getValueByPath(sourceData, mapping);
|
|
62
|
+
} else if (typeof mapping === "function") {
|
|
63
|
+
result[targetKey] = mapping(sourceData);
|
|
64
|
+
} else if (typeof mapping === "object" && mapping !== null) {
|
|
65
|
+
result[targetKey] = transform(sourceData, mapping);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
function getValueByPath(obj, path) {
|
|
71
|
+
return path.split(".").reduce((acc, part) => acc && acc[part], obj);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// src/core/merger.ts
|
|
75
|
+
function merge(staticData, dynamicResults) {
|
|
76
|
+
if (!staticData) return dynamicResults;
|
|
77
|
+
return {
|
|
78
|
+
...staticData,
|
|
79
|
+
...dynamicResults
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// src/core/compiler.ts
|
|
84
|
+
async function compileLLM(config, loader, options = {}) {
|
|
85
|
+
let staticTruth = {};
|
|
86
|
+
if (config.static) {
|
|
87
|
+
try {
|
|
88
|
+
const content = await loader(config.static);
|
|
89
|
+
if (content) {
|
|
90
|
+
staticTruth = JSON.parse(content);
|
|
91
|
+
}
|
|
92
|
+
} catch (error) {
|
|
93
|
+
if (options.failLoudly) {
|
|
94
|
+
throw new Error(`[llmweb] Static Truth Error: Failed to load/parse JSON at ${config.static}. ${error}`);
|
|
95
|
+
}
|
|
96
|
+
console.warn(`[llmweb] Warning: Could not load static JSON at ${config.static}. Proceeding with dynamic data only.`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const dynamicTruth = {};
|
|
100
|
+
if (config.dynamic) {
|
|
101
|
+
const rawResults = await resolveAll(config.dynamic, { timeout: options.timeout });
|
|
102
|
+
for (const [key, source] of Object.entries(config.dynamic)) {
|
|
103
|
+
const rawData = rawResults[key];
|
|
104
|
+
if (rawData === null && options.failLoudly) {
|
|
105
|
+
throw new Error(`[llmweb] Dynamic Truth Error: Source "${key}" failed to resolve.`);
|
|
106
|
+
}
|
|
107
|
+
if (rawData && source.map) {
|
|
108
|
+
try {
|
|
109
|
+
dynamicTruth[key] = transform(rawData, source.map);
|
|
110
|
+
} catch (error) {
|
|
111
|
+
if (options.failLoudly) {
|
|
112
|
+
throw new Error(`[llmweb] Transformation Error: Failed to map source "${key}". ${error}`);
|
|
113
|
+
}
|
|
114
|
+
console.error(`[llmweb] Warning: Mapping failed for "${key}". Using raw data.`);
|
|
115
|
+
dynamicTruth[key] = rawData;
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
dynamicTruth[key] = rawData;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return merge(staticTruth, dynamicTruth);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// src/index.ts
|
|
126
|
+
import { readFileSync } from "fs";
|
|
127
|
+
import { join } from "path";
|
|
128
|
+
|
|
129
|
+
// src/core/injector.ts
|
|
130
|
+
function toWindowString(data, key = "__LLM__") {
|
|
131
|
+
const json = JSON.stringify(data);
|
|
132
|
+
return `window.${key} = ${json};`;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// src/index.ts
|
|
136
|
+
var nodeLoader = async (path) => {
|
|
137
|
+
const fullPath = path.startsWith("/") ? path : join(process.cwd(), path);
|
|
138
|
+
return readFileSync(fullPath, "utf-8");
|
|
139
|
+
};
|
|
140
|
+
async function createLLMSource(config, options = {}) {
|
|
141
|
+
return compileLLM(config, nodeLoader, options);
|
|
142
|
+
}
|
|
5
143
|
|
|
6
144
|
// src/adapters/react.tsx
|
|
7
145
|
import { jsx } from "react/jsx-runtime";
|
|
@@ -34,6 +172,46 @@ async function LLMJson({
|
|
|
34
172
|
}
|
|
35
173
|
);
|
|
36
174
|
}
|
|
175
|
+
function LLMInjector({
|
|
176
|
+
config,
|
|
177
|
+
mode = "script",
|
|
178
|
+
targetKey = "__LLM__",
|
|
179
|
+
className
|
|
180
|
+
}) {
|
|
181
|
+
const [truth, setTruth] = React.useState(null);
|
|
182
|
+
React.useEffect(() => {
|
|
183
|
+
let mounted = true;
|
|
184
|
+
createLLMSource(config).then((data) => {
|
|
185
|
+
if (mounted) setTruth(data);
|
|
186
|
+
});
|
|
187
|
+
return () => {
|
|
188
|
+
mounted = false;
|
|
189
|
+
};
|
|
190
|
+
}, [config]);
|
|
191
|
+
if (!truth) return null;
|
|
192
|
+
if (mode === "window") {
|
|
193
|
+
const scriptBody = toWindowString(truth, targetKey);
|
|
194
|
+
return /* @__PURE__ */ jsx(
|
|
195
|
+
"script",
|
|
196
|
+
{
|
|
197
|
+
id: `llm-window-${targetKey}`,
|
|
198
|
+
dangerouslySetInnerHTML: { __html: scriptBody }
|
|
199
|
+
}
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
if (mode === "pre") {
|
|
203
|
+
return /* @__PURE__ */ jsx("pre", { id: "llm-truth-pre", className, children: JSON.stringify(truth, null, 2) });
|
|
204
|
+
}
|
|
205
|
+
return /* @__PURE__ */ jsx(
|
|
206
|
+
"script",
|
|
207
|
+
{
|
|
208
|
+
id: "llm-truth-script",
|
|
209
|
+
type: "application/llm+json",
|
|
210
|
+
dangerouslySetInnerHTML: { __html: JSON.stringify(truth) }
|
|
211
|
+
}
|
|
212
|
+
);
|
|
213
|
+
}
|
|
37
214
|
export {
|
|
215
|
+
LLMInjector,
|
|
38
216
|
LLMJson
|
|
39
217
|
};
|
package/dist/adapters/vanilla.js
CHANGED
|
@@ -103,16 +103,15 @@ function merge(staticData, dynamicResults) {
|
|
|
103
103
|
};
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
// src/
|
|
107
|
-
|
|
108
|
-
var import_node_path = require("path");
|
|
109
|
-
async function createLLMSource(config, options = {}) {
|
|
106
|
+
// src/core/compiler.ts
|
|
107
|
+
async function compileLLM(config, loader, options = {}) {
|
|
110
108
|
let staticTruth = {};
|
|
111
109
|
if (config.static) {
|
|
112
110
|
try {
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
111
|
+
const content = await loader(config.static);
|
|
112
|
+
if (content) {
|
|
113
|
+
staticTruth = JSON.parse(content);
|
|
114
|
+
}
|
|
116
115
|
} catch (error) {
|
|
117
116
|
if (options.failLoudly) {
|
|
118
117
|
throw new Error(`[llmweb] Static Truth Error: Failed to load/parse JSON at ${config.static}. ${error}`);
|
|
@@ -146,6 +145,17 @@ async function createLLMSource(config, options = {}) {
|
|
|
146
145
|
return merge(staticTruth, dynamicTruth);
|
|
147
146
|
}
|
|
148
147
|
|
|
148
|
+
// src/index.ts
|
|
149
|
+
var import_node_fs = require("fs");
|
|
150
|
+
var import_node_path = require("path");
|
|
151
|
+
var nodeLoader = async (path) => {
|
|
152
|
+
const fullPath = path.startsWith("/") ? path : (0, import_node_path.join)(process.cwd(), path);
|
|
153
|
+
return (0, import_node_fs.readFileSync)(fullPath, "utf-8");
|
|
154
|
+
};
|
|
155
|
+
async function createLLMSource(config, options = {}) {
|
|
156
|
+
return compileLLM(config, nodeLoader, options);
|
|
157
|
+
}
|
|
158
|
+
|
|
149
159
|
// src/adapters/vanilla.ts
|
|
150
160
|
async function inject(config, mode = "script", targetKey = "__LLM__") {
|
|
151
161
|
const truth = await createLLMSource(config);
|
|
@@ -1,6 +1,134 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
// src/core/resolver.ts
|
|
2
|
+
async function resolveAll(dynamicSources, options = {}) {
|
|
3
|
+
const keys = Object.keys(dynamicSources);
|
|
4
|
+
const results = await Promise.allSettled(
|
|
5
|
+
keys.map((key) => resolveSource(dynamicSources[key], options.timeout))
|
|
6
|
+
);
|
|
7
|
+
const data = {};
|
|
8
|
+
results.forEach((result, index) => {
|
|
9
|
+
const key = keys[index];
|
|
10
|
+
if (result.status === "fulfilled") {
|
|
11
|
+
data[key] = result.value;
|
|
12
|
+
} else {
|
|
13
|
+
console.error(`[llmweb] Failed to resolve source "${key}":`, result.reason);
|
|
14
|
+
data[key] = null;
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
return data;
|
|
18
|
+
}
|
|
19
|
+
async function resolveSource(source, timeoutMs) {
|
|
20
|
+
const { from } = source;
|
|
21
|
+
const controller = timeoutMs ? new AbortController() : null;
|
|
22
|
+
const signal = controller?.signal;
|
|
23
|
+
const timeoutPromise = timeoutMs ? new Promise(
|
|
24
|
+
(_, reject) => setTimeout(() => {
|
|
25
|
+
controller?.abort();
|
|
26
|
+
reject(new Error(`Timeout of ${timeoutMs}ms exceeded`));
|
|
27
|
+
}, timeoutMs)
|
|
28
|
+
) : null;
|
|
29
|
+
const resolvePromise = (async () => {
|
|
30
|
+
if (from.type === "fetch") {
|
|
31
|
+
if (!from.url) throw new Error("Fetch source requires a URL");
|
|
32
|
+
const response = await fetch(from.url, { signal });
|
|
33
|
+
if (!response.ok) throw new Error(`HTTP error ${response.status} for ${from.url}`);
|
|
34
|
+
return response.json();
|
|
35
|
+
}
|
|
36
|
+
if (from.type === "fn") {
|
|
37
|
+
if (!from.call) throw new Error('Function source requires a "call" property');
|
|
38
|
+
return from.call();
|
|
39
|
+
}
|
|
40
|
+
throw new Error(`Unsupported source type: ${from.type}`);
|
|
41
|
+
})();
|
|
42
|
+
if (timeoutPromise) {
|
|
43
|
+
return Promise.race([resolvePromise, timeoutPromise]);
|
|
44
|
+
}
|
|
45
|
+
return resolvePromise;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// src/core/transformer.ts
|
|
49
|
+
function transform(sourceData, schema) {
|
|
50
|
+
if (!sourceData) return sourceData;
|
|
51
|
+
if (Array.isArray(sourceData)) {
|
|
52
|
+
return sourceData.map((item) => transform(item, schema));
|
|
53
|
+
}
|
|
54
|
+
if (typeof sourceData !== "object") return sourceData;
|
|
55
|
+
const result = {};
|
|
56
|
+
for (const [targetKey, mapping] of Object.entries(schema)) {
|
|
57
|
+
if (typeof mapping === "string") {
|
|
58
|
+
result[targetKey] = getValueByPath(sourceData, mapping);
|
|
59
|
+
} else if (typeof mapping === "function") {
|
|
60
|
+
result[targetKey] = mapping(sourceData);
|
|
61
|
+
} else if (typeof mapping === "object" && mapping !== null) {
|
|
62
|
+
result[targetKey] = transform(sourceData, mapping);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
function getValueByPath(obj, path) {
|
|
68
|
+
return path.split(".").reduce((acc, part) => acc && acc[part], obj);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// src/core/merger.ts
|
|
72
|
+
function merge(staticData, dynamicResults) {
|
|
73
|
+
if (!staticData) return dynamicResults;
|
|
74
|
+
return {
|
|
75
|
+
...staticData,
|
|
76
|
+
...dynamicResults
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// src/core/compiler.ts
|
|
81
|
+
async function compileLLM(config, loader, options = {}) {
|
|
82
|
+
let staticTruth = {};
|
|
83
|
+
if (config.static) {
|
|
84
|
+
try {
|
|
85
|
+
const content = await loader(config.static);
|
|
86
|
+
if (content) {
|
|
87
|
+
staticTruth = JSON.parse(content);
|
|
88
|
+
}
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (options.failLoudly) {
|
|
91
|
+
throw new Error(`[llmweb] Static Truth Error: Failed to load/parse JSON at ${config.static}. ${error}`);
|
|
92
|
+
}
|
|
93
|
+
console.warn(`[llmweb] Warning: Could not load static JSON at ${config.static}. Proceeding with dynamic data only.`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const dynamicTruth = {};
|
|
97
|
+
if (config.dynamic) {
|
|
98
|
+
const rawResults = await resolveAll(config.dynamic, { timeout: options.timeout });
|
|
99
|
+
for (const [key, source] of Object.entries(config.dynamic)) {
|
|
100
|
+
const rawData = rawResults[key];
|
|
101
|
+
if (rawData === null && options.failLoudly) {
|
|
102
|
+
throw new Error(`[llmweb] Dynamic Truth Error: Source "${key}" failed to resolve.`);
|
|
103
|
+
}
|
|
104
|
+
if (rawData && source.map) {
|
|
105
|
+
try {
|
|
106
|
+
dynamicTruth[key] = transform(rawData, source.map);
|
|
107
|
+
} catch (error) {
|
|
108
|
+
if (options.failLoudly) {
|
|
109
|
+
throw new Error(`[llmweb] Transformation Error: Failed to map source "${key}". ${error}`);
|
|
110
|
+
}
|
|
111
|
+
console.error(`[llmweb] Warning: Mapping failed for "${key}". Using raw data.`);
|
|
112
|
+
dynamicTruth[key] = rawData;
|
|
113
|
+
}
|
|
114
|
+
} else {
|
|
115
|
+
dynamicTruth[key] = rawData;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return merge(staticTruth, dynamicTruth);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// src/index.ts
|
|
123
|
+
import { readFileSync } from "fs";
|
|
124
|
+
import { join } from "path";
|
|
125
|
+
var nodeLoader = async (path) => {
|
|
126
|
+
const fullPath = path.startsWith("/") ? path : join(process.cwd(), path);
|
|
127
|
+
return readFileSync(fullPath, "utf-8");
|
|
128
|
+
};
|
|
129
|
+
async function createLLMSource(config, options = {}) {
|
|
130
|
+
return compileLLM(config, nodeLoader, options);
|
|
131
|
+
}
|
|
4
132
|
|
|
5
133
|
// src/adapters/vanilla.ts
|
|
6
134
|
async function inject(config, mode = "script", targetKey = "__LLM__") {
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.browser.ts
|
|
21
|
+
var index_browser_exports = {};
|
|
22
|
+
__export(index_browser_exports, {
|
|
23
|
+
createLLMSource: () => createLLMSource,
|
|
24
|
+
toScriptString: () => toScriptString,
|
|
25
|
+
toWindowString: () => toWindowString,
|
|
26
|
+
transform: () => transform
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(index_browser_exports);
|
|
29
|
+
|
|
30
|
+
// src/core/resolver.ts
|
|
31
|
+
async function resolveAll(dynamicSources, options = {}) {
|
|
32
|
+
const keys = Object.keys(dynamicSources);
|
|
33
|
+
const results = await Promise.allSettled(
|
|
34
|
+
keys.map((key) => resolveSource(dynamicSources[key], options.timeout))
|
|
35
|
+
);
|
|
36
|
+
const data = {};
|
|
37
|
+
results.forEach((result, index) => {
|
|
38
|
+
const key = keys[index];
|
|
39
|
+
if (result.status === "fulfilled") {
|
|
40
|
+
data[key] = result.value;
|
|
41
|
+
} else {
|
|
42
|
+
console.error(`[llmweb] Failed to resolve source "${key}":`, result.reason);
|
|
43
|
+
data[key] = null;
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
return data;
|
|
47
|
+
}
|
|
48
|
+
async function resolveSource(source, timeoutMs) {
|
|
49
|
+
const { from } = source;
|
|
50
|
+
const controller = timeoutMs ? new AbortController() : null;
|
|
51
|
+
const signal = controller?.signal;
|
|
52
|
+
const timeoutPromise = timeoutMs ? new Promise(
|
|
53
|
+
(_, reject) => setTimeout(() => {
|
|
54
|
+
controller?.abort();
|
|
55
|
+
reject(new Error(`Timeout of ${timeoutMs}ms exceeded`));
|
|
56
|
+
}, timeoutMs)
|
|
57
|
+
) : null;
|
|
58
|
+
const resolvePromise = (async () => {
|
|
59
|
+
if (from.type === "fetch") {
|
|
60
|
+
if (!from.url) throw new Error("Fetch source requires a URL");
|
|
61
|
+
const response = await fetch(from.url, { signal });
|
|
62
|
+
if (!response.ok) throw new Error(`HTTP error ${response.status} for ${from.url}`);
|
|
63
|
+
return response.json();
|
|
64
|
+
}
|
|
65
|
+
if (from.type === "fn") {
|
|
66
|
+
if (!from.call) throw new Error('Function source requires a "call" property');
|
|
67
|
+
return from.call();
|
|
68
|
+
}
|
|
69
|
+
throw new Error(`Unsupported source type: ${from.type}`);
|
|
70
|
+
})();
|
|
71
|
+
if (timeoutPromise) {
|
|
72
|
+
return Promise.race([resolvePromise, timeoutPromise]);
|
|
73
|
+
}
|
|
74
|
+
return resolvePromise;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// src/core/transformer.ts
|
|
78
|
+
function transform(sourceData, schema) {
|
|
79
|
+
if (!sourceData) return sourceData;
|
|
80
|
+
if (Array.isArray(sourceData)) {
|
|
81
|
+
return sourceData.map((item) => transform(item, schema));
|
|
82
|
+
}
|
|
83
|
+
if (typeof sourceData !== "object") return sourceData;
|
|
84
|
+
const result = {};
|
|
85
|
+
for (const [targetKey, mapping] of Object.entries(schema)) {
|
|
86
|
+
if (typeof mapping === "string") {
|
|
87
|
+
result[targetKey] = getValueByPath(sourceData, mapping);
|
|
88
|
+
} else if (typeof mapping === "function") {
|
|
89
|
+
result[targetKey] = mapping(sourceData);
|
|
90
|
+
} else if (typeof mapping === "object" && mapping !== null) {
|
|
91
|
+
result[targetKey] = transform(sourceData, mapping);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
function getValueByPath(obj, path) {
|
|
97
|
+
return path.split(".").reduce((acc, part) => acc && acc[part], obj);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// src/core/merger.ts
|
|
101
|
+
function merge(staticData, dynamicResults) {
|
|
102
|
+
if (!staticData) return dynamicResults;
|
|
103
|
+
return {
|
|
104
|
+
...staticData,
|
|
105
|
+
...dynamicResults
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// src/core/compiler.ts
|
|
110
|
+
async function compileLLM(config, loader, options = {}) {
|
|
111
|
+
let staticTruth = {};
|
|
112
|
+
if (config.static) {
|
|
113
|
+
try {
|
|
114
|
+
const content = await loader(config.static);
|
|
115
|
+
if (content) {
|
|
116
|
+
staticTruth = JSON.parse(content);
|
|
117
|
+
}
|
|
118
|
+
} catch (error) {
|
|
119
|
+
if (options.failLoudly) {
|
|
120
|
+
throw new Error(`[llmweb] Static Truth Error: Failed to load/parse JSON at ${config.static}. ${error}`);
|
|
121
|
+
}
|
|
122
|
+
console.warn(`[llmweb] Warning: Could not load static JSON at ${config.static}. Proceeding with dynamic data only.`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const dynamicTruth = {};
|
|
126
|
+
if (config.dynamic) {
|
|
127
|
+
const rawResults = await resolveAll(config.dynamic, { timeout: options.timeout });
|
|
128
|
+
for (const [key, source] of Object.entries(config.dynamic)) {
|
|
129
|
+
const rawData = rawResults[key];
|
|
130
|
+
if (rawData === null && options.failLoudly) {
|
|
131
|
+
throw new Error(`[llmweb] Dynamic Truth Error: Source "${key}" failed to resolve.`);
|
|
132
|
+
}
|
|
133
|
+
if (rawData && source.map) {
|
|
134
|
+
try {
|
|
135
|
+
dynamicTruth[key] = transform(rawData, source.map);
|
|
136
|
+
} catch (error) {
|
|
137
|
+
if (options.failLoudly) {
|
|
138
|
+
throw new Error(`[llmweb] Transformation Error: Failed to map source "${key}". ${error}`);
|
|
139
|
+
}
|
|
140
|
+
console.error(`[llmweb] Warning: Mapping failed for "${key}". Using raw data.`);
|
|
141
|
+
dynamicTruth[key] = rawData;
|
|
142
|
+
}
|
|
143
|
+
} else {
|
|
144
|
+
dynamicTruth[key] = rawData;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return merge(staticTruth, dynamicTruth);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// src/core/injector.ts
|
|
152
|
+
function toScriptString(data) {
|
|
153
|
+
const json = JSON.stringify(data);
|
|
154
|
+
return `<script type="application/llm+json">${json}</script>`;
|
|
155
|
+
}
|
|
156
|
+
function toWindowString(data, key = "__LLM__") {
|
|
157
|
+
const json = JSON.stringify(data);
|
|
158
|
+
return `window.${key} = ${json};`;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// src/index.browser.ts
|
|
162
|
+
var browserLoader = async (path) => {
|
|
163
|
+
console.warn(`[llmweb] Static files cannot be loaded in the browser: ${path}. Please use dynamic sources or pass data directly.`);
|
|
164
|
+
return null;
|
|
165
|
+
};
|
|
166
|
+
async function createLLMSource(config, options = {}) {
|
|
167
|
+
return compileLLM(config, browserLoader, options);
|
|
168
|
+
}
|
|
169
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
170
|
+
0 && (module.exports = {
|
|
171
|
+
createLLMSource,
|
|
172
|
+
toScriptString,
|
|
173
|
+
toWindowString,
|
|
174
|
+
transform
|
|
175
|
+
});
|
|
@@ -77,28 +77,15 @@ function merge(staticData, dynamicResults) {
|
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
// src/
|
|
81
|
-
|
|
82
|
-
import { join } from "path";
|
|
83
|
-
|
|
84
|
-
// src/core/injector.ts
|
|
85
|
-
function toScriptString(data) {
|
|
86
|
-
const json = JSON.stringify(data);
|
|
87
|
-
return `<script type="application/llm+json">${json}</script>`;
|
|
88
|
-
}
|
|
89
|
-
function toWindowString(data, key = "__LLM__") {
|
|
90
|
-
const json = JSON.stringify(data);
|
|
91
|
-
return `window.${key} = ${json};`;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// src/index.ts
|
|
95
|
-
async function createLLMSource(config, options = {}) {
|
|
80
|
+
// src/core/compiler.ts
|
|
81
|
+
async function compileLLM(config, loader, options = {}) {
|
|
96
82
|
let staticTruth = {};
|
|
97
83
|
if (config.static) {
|
|
98
84
|
try {
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
85
|
+
const content = await loader(config.static);
|
|
86
|
+
if (content) {
|
|
87
|
+
staticTruth = JSON.parse(content);
|
|
88
|
+
}
|
|
102
89
|
} catch (error) {
|
|
103
90
|
if (options.failLoudly) {
|
|
104
91
|
throw new Error(`[llmweb] Static Truth Error: Failed to load/parse JSON at ${config.static}. ${error}`);
|
|
@@ -132,9 +119,27 @@ async function createLLMSource(config, options = {}) {
|
|
|
132
119
|
return merge(staticTruth, dynamicTruth);
|
|
133
120
|
}
|
|
134
121
|
|
|
122
|
+
// src/core/injector.ts
|
|
123
|
+
function toScriptString(data) {
|
|
124
|
+
const json = JSON.stringify(data);
|
|
125
|
+
return `<script type="application/llm+json">${json}</script>`;
|
|
126
|
+
}
|
|
127
|
+
function toWindowString(data, key = "__LLM__") {
|
|
128
|
+
const json = JSON.stringify(data);
|
|
129
|
+
return `window.${key} = ${json};`;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// src/index.browser.ts
|
|
133
|
+
var browserLoader = async (path) => {
|
|
134
|
+
console.warn(`[llmweb] Static files cannot be loaded in the browser: ${path}. Please use dynamic sources or pass data directly.`);
|
|
135
|
+
return null;
|
|
136
|
+
};
|
|
137
|
+
async function createLLMSource(config, options = {}) {
|
|
138
|
+
return compileLLM(config, browserLoader, options);
|
|
139
|
+
}
|
|
135
140
|
export {
|
|
136
|
-
|
|
141
|
+
createLLMSource,
|
|
137
142
|
toScriptString,
|
|
138
143
|
toWindowString,
|
|
139
|
-
|
|
144
|
+
transform
|
|
140
145
|
};
|
package/dist/index.js
CHANGED
|
@@ -106,28 +106,15 @@ function merge(staticData, dynamicResults) {
|
|
|
106
106
|
};
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
// src/
|
|
110
|
-
|
|
111
|
-
var import_node_path = require("path");
|
|
112
|
-
|
|
113
|
-
// src/core/injector.ts
|
|
114
|
-
function toScriptString(data) {
|
|
115
|
-
const json = JSON.stringify(data);
|
|
116
|
-
return `<script type="application/llm+json">${json}</script>`;
|
|
117
|
-
}
|
|
118
|
-
function toWindowString(data, key = "__LLM__") {
|
|
119
|
-
const json = JSON.stringify(data);
|
|
120
|
-
return `window.${key} = ${json};`;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// src/index.ts
|
|
124
|
-
async function createLLMSource(config, options = {}) {
|
|
109
|
+
// src/core/compiler.ts
|
|
110
|
+
async function compileLLM(config, loader, options = {}) {
|
|
125
111
|
let staticTruth = {};
|
|
126
112
|
if (config.static) {
|
|
127
113
|
try {
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
114
|
+
const content = await loader(config.static);
|
|
115
|
+
if (content) {
|
|
116
|
+
staticTruth = JSON.parse(content);
|
|
117
|
+
}
|
|
131
118
|
} catch (error) {
|
|
132
119
|
if (options.failLoudly) {
|
|
133
120
|
throw new Error(`[llmweb] Static Truth Error: Failed to load/parse JSON at ${config.static}. ${error}`);
|
|
@@ -160,6 +147,29 @@ async function createLLMSource(config, options = {}) {
|
|
|
160
147
|
}
|
|
161
148
|
return merge(staticTruth, dynamicTruth);
|
|
162
149
|
}
|
|
150
|
+
|
|
151
|
+
// src/index.ts
|
|
152
|
+
var import_node_fs = require("fs");
|
|
153
|
+
var import_node_path = require("path");
|
|
154
|
+
|
|
155
|
+
// src/core/injector.ts
|
|
156
|
+
function toScriptString(data) {
|
|
157
|
+
const json = JSON.stringify(data);
|
|
158
|
+
return `<script type="application/llm+json">${json}</script>`;
|
|
159
|
+
}
|
|
160
|
+
function toWindowString(data, key = "__LLM__") {
|
|
161
|
+
const json = JSON.stringify(data);
|
|
162
|
+
return `window.${key} = ${json};`;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// src/index.ts
|
|
166
|
+
var nodeLoader = async (path) => {
|
|
167
|
+
const fullPath = path.startsWith("/") ? path : (0, import_node_path.join)(process.cwd(), path);
|
|
168
|
+
return (0, import_node_fs.readFileSync)(fullPath, "utf-8");
|
|
169
|
+
};
|
|
170
|
+
async function createLLMSource(config, options = {}) {
|
|
171
|
+
return compileLLM(config, nodeLoader, options);
|
|
172
|
+
}
|
|
163
173
|
// Annotate the CommonJS export names for ESM import in node:
|
|
164
174
|
0 && (module.exports = {
|
|
165
175
|
createLLMSource,
|