@kaleabdenbel/llmweb 1.0.2 → 1.0.4
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/cli.js +284 -0
- package/package.json +21 -9
- package/dist/adapters/express.d.ts +0 -5
- package/dist/adapters/express.js +0 -164
- package/dist/adapters/express.mjs +0 -19
- package/dist/adapters/next.d.ts +0 -18
- package/dist/adapters/next.js +0 -171
- package/dist/adapters/next.mjs +0 -25
- package/dist/adapters/react.d.ts +0 -15
- package/dist/adapters/react.js +0 -191
- package/dist/adapters/react.mjs +0 -39
- package/dist/adapters/vanilla.d.ts +0 -5
- package/dist/adapters/vanilla.js +0 -165
- package/dist/adapters/vanilla.mjs +0 -20
- package/dist/chunk-HRF6I6KB.mjs +0 -140
- 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/index.js +0 -169
- package/dist/index.mjs +0 -12
- package/dist/types/index.d.ts +0 -23
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@ The data compiler that transforms messy application state into LLM-readable trut
|
|
|
9
9
|
- **Static Truth**: Your contract with the world. Deterministic. Versioned.
|
|
10
10
|
- **Dynamic Truth**: Live data from APIs, Server Actions, or DB calls.
|
|
11
11
|
- **The Engine**: Compiles these into a single, structured JSON object for LLMs.
|
|
12
|
+
- **Framework Adapters**: Utilities for [Next.js](docs/next.md), [React](docs/react.md), [Express](docs/express.md), and [Vanilla JS](docs/vanilla.md).
|
|
12
13
|
|
|
13
14
|
## Installation
|
|
14
15
|
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
22
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
|
+
mod
|
|
24
|
+
));
|
|
25
|
+
|
|
26
|
+
// src/cli.ts
|
|
27
|
+
var import_commander2 = require("commander");
|
|
28
|
+
|
|
29
|
+
// src/cli/init.ts
|
|
30
|
+
var import_commander = require("commander");
|
|
31
|
+
var import_prompts = __toESM(require("prompts"));
|
|
32
|
+
|
|
33
|
+
// src/generators/config.ts
|
|
34
|
+
var import_fs = __toESM(require("fs"));
|
|
35
|
+
var import_path = __toESM(require("path"));
|
|
36
|
+
async function generateConfig(config) {
|
|
37
|
+
const cwd = process.cwd();
|
|
38
|
+
let publicData = [];
|
|
39
|
+
if (typeof config.public === "string") {
|
|
40
|
+
publicData = config.public.split(",").map((s) => s.trim()).filter(Boolean);
|
|
41
|
+
} else if (Array.isArray(config.public)) {
|
|
42
|
+
publicData = config.public;
|
|
43
|
+
}
|
|
44
|
+
let dynamicData = {};
|
|
45
|
+
if (typeof config.dynamic === "string") {
|
|
46
|
+
config.dynamic.split(",").forEach((pair) => {
|
|
47
|
+
const [key, value] = pair.split("=").map((s) => s.trim());
|
|
48
|
+
if (key && value) {
|
|
49
|
+
dynamicData[key] = value;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
} else if (typeof config.dynamic === "object") {
|
|
53
|
+
dynamicData = config.dynamic;
|
|
54
|
+
}
|
|
55
|
+
const llmWebConfig = {
|
|
56
|
+
name: config.name,
|
|
57
|
+
description: config.description || "",
|
|
58
|
+
type: config.type,
|
|
59
|
+
public: publicData,
|
|
60
|
+
dynamic: dynamicData,
|
|
61
|
+
version: "1.0.0"
|
|
62
|
+
};
|
|
63
|
+
const jsonPath = import_path.default.join(cwd, "llmweb.json");
|
|
64
|
+
import_fs.default.writeFileSync(jsonPath, JSON.stringify(llmWebConfig, null, 2));
|
|
65
|
+
console.log(`Created: ${jsonPath}`);
|
|
66
|
+
const mdPath = import_path.default.join(cwd, "llm.md");
|
|
67
|
+
const mdContent = `# ${config.name}
|
|
68
|
+
|
|
69
|
+
> ${config.description || "No description provided."}
|
|
70
|
+
|
|
71
|
+
This file is a machine-readable summary of the site structure for LLMs and Agents.
|
|
72
|
+
|
|
73
|
+
## Type
|
|
74
|
+
${config.type}
|
|
75
|
+
|
|
76
|
+
## Public Data
|
|
77
|
+
The following data is statically available:
|
|
78
|
+
${publicData.map((item) => `- ${item}`).join("\n") || "- None"}
|
|
79
|
+
|
|
80
|
+
## Dynamic Data
|
|
81
|
+
The following data changes frequently and should be fetched from the API:
|
|
82
|
+
${Object.entries(dynamicData).map(([key, value]) => `- **${key}**: \`${value}\``).join("\n") || "- None"}
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
Generated by [llmweb](https://github.com/kaleabdenbel/llmweb)
|
|
86
|
+
`;
|
|
87
|
+
import_fs.default.writeFileSync(mdPath, mdContent);
|
|
88
|
+
console.log(`Created: ${mdPath}`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// src/generators/frameworks.ts
|
|
92
|
+
var import_fs2 = __toESM(require("fs"));
|
|
93
|
+
var import_path2 = __toESM(require("path"));
|
|
94
|
+
async function generateFrameworkGlue(config) {
|
|
95
|
+
const cwd = process.cwd();
|
|
96
|
+
const framework = config.framework || "vite";
|
|
97
|
+
console.log(`Detected framework: ${framework}`);
|
|
98
|
+
if (framework === "vite" || framework === "react") {
|
|
99
|
+
const setupContent = `import { LLMSource } from '@kaleabdenbel/llmweb/adapters/react';
|
|
100
|
+
import config from './llmweb.json';
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Use this component in your root layout or App component.
|
|
104
|
+
* It will inject the machine-readable identity into your page.
|
|
105
|
+
*/
|
|
106
|
+
export function LLMIdentity() {
|
|
107
|
+
return <LLMSource config={config as any} />;
|
|
108
|
+
}
|
|
109
|
+
`;
|
|
110
|
+
const setupPath = import_path2.default.join(cwd, "llmweb.setup.tsx");
|
|
111
|
+
import_fs2.default.writeFileSync(setupPath, setupContent);
|
|
112
|
+
console.log(`Created: ${setupPath}`);
|
|
113
|
+
console.log("\nTIP: Import and use <LLMIdentity /> in your App.tsx or main.tsx\n");
|
|
114
|
+
} else if (framework === "next") {
|
|
115
|
+
const setupContent = `import { LLMSource } from '@kaleabdenbel/llmweb/adapters/next';
|
|
116
|
+
import config from './llmweb.json';
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Add this to your root layout.tsx
|
|
120
|
+
*/
|
|
121
|
+
export function LLMIdentity() {
|
|
122
|
+
return <LLMSource config={config as any} />;
|
|
123
|
+
}
|
|
124
|
+
`;
|
|
125
|
+
const setupPath = import_path2.default.join(cwd, "llmweb.setup.tsx");
|
|
126
|
+
import_fs2.default.writeFileSync(setupPath, setupContent);
|
|
127
|
+
console.log(`Created: ${setupPath}`);
|
|
128
|
+
} else {
|
|
129
|
+
console.log("Generic setup: Ensure `llmweb.json` and `llm.md` are served at the root of your site.");
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// src/cli/init.ts
|
|
134
|
+
var initCommand = new import_commander.Command("init").description("Initialize llmweb configuration for your project").option("--name <name>", "Project name").option("--type <type>", "Project type (marketing, docs, saas, content)").option("--public <items>", "Comma-separated list of public data types").option("--dynamic <items>", "Comma-separated list of dynamic data types (key=path)").option("--inject <type>", "Injection method (script, route, component)").option("--framework <framework>", "Framework (vite, next, vue)").action(async (options) => {
|
|
135
|
+
let config = { ...options };
|
|
136
|
+
if (!config.name || !config.type) {
|
|
137
|
+
const response = await (0, import_prompts.default)([
|
|
138
|
+
{
|
|
139
|
+
type: config.name ? null : "text",
|
|
140
|
+
name: "name",
|
|
141
|
+
message: "What is the name of your site?",
|
|
142
|
+
initial: "My Awesome Site"
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
type: "text",
|
|
146
|
+
name: "description",
|
|
147
|
+
message: "One sentence describing the product:"
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
type: config.type ? null : "select",
|
|
151
|
+
name: "type",
|
|
152
|
+
message: "Is this marketing, docs, SaaS, or content?",
|
|
153
|
+
choices: [
|
|
154
|
+
{ title: "Marketing", value: "marketing" },
|
|
155
|
+
{ title: "Docs", value: "docs" },
|
|
156
|
+
{ title: "SaaS", value: "saas" },
|
|
157
|
+
{ title: "Content", value: "content" }
|
|
158
|
+
]
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
type: "list",
|
|
162
|
+
name: "public",
|
|
163
|
+
message: "What data is always public? (comma separated)",
|
|
164
|
+
initial: "",
|
|
165
|
+
separator: ","
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
type: "text",
|
|
169
|
+
name: "dynamic",
|
|
170
|
+
message: "What data changes frequently? (format: key=route)",
|
|
171
|
+
hint: "announcements=/api/announcements"
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
type: "select",
|
|
175
|
+
name: "framework",
|
|
176
|
+
message: "Which framework are you using?",
|
|
177
|
+
choices: [
|
|
178
|
+
{ title: "Vite (React/Vue/Vanilla)", value: "vite" },
|
|
179
|
+
{ title: "Next.js", value: "next" },
|
|
180
|
+
{ title: "Other", value: "other" }
|
|
181
|
+
]
|
|
182
|
+
}
|
|
183
|
+
]);
|
|
184
|
+
config = { ...config, ...response };
|
|
185
|
+
}
|
|
186
|
+
if (typeof config.dynamic === "string" && config.dynamic.length > 0) {
|
|
187
|
+
}
|
|
188
|
+
console.log("Generating configuration...");
|
|
189
|
+
await generateConfig(config);
|
|
190
|
+
console.log("Generating framework glue...");
|
|
191
|
+
await generateFrameworkGlue(config);
|
|
192
|
+
console.log("Done! llmweb is ready.");
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// package.json
|
|
196
|
+
var package_default = {
|
|
197
|
+
name: "@kaleabdenbel/llmweb",
|
|
198
|
+
version: "1.0.4",
|
|
199
|
+
description: "A compiler for LLM-readable truth from static and dynamic sources.",
|
|
200
|
+
publishConfig: {
|
|
201
|
+
access: "public"
|
|
202
|
+
},
|
|
203
|
+
main: "./dist/index.js",
|
|
204
|
+
module: "./dist/index.mjs",
|
|
205
|
+
browser: "./dist/index.browser.mjs",
|
|
206
|
+
types: "./dist/index.d.ts",
|
|
207
|
+
exports: {
|
|
208
|
+
".": {
|
|
209
|
+
browser: "./dist/index.browser.mjs",
|
|
210
|
+
import: "./dist/index.mjs",
|
|
211
|
+
require: "./dist/index.js",
|
|
212
|
+
types: "./dist/index.d.ts"
|
|
213
|
+
},
|
|
214
|
+
"./adapters/next": {
|
|
215
|
+
import: "./dist/adapters/next.mjs",
|
|
216
|
+
require: "./dist/adapters/next.js",
|
|
217
|
+
types: "./dist/adapters/next.d.ts"
|
|
218
|
+
},
|
|
219
|
+
"./adapters/react": {
|
|
220
|
+
import: "./dist/adapters/react.mjs",
|
|
221
|
+
require: "./dist/adapters/react.js",
|
|
222
|
+
types: "./dist/adapters/react.d.ts"
|
|
223
|
+
},
|
|
224
|
+
"./adapters/vanilla": {
|
|
225
|
+
import: "./dist/adapters/vanilla.mjs",
|
|
226
|
+
require: "./dist/adapters/vanilla.js",
|
|
227
|
+
types: "./dist/adapters/vanilla.d.ts"
|
|
228
|
+
},
|
|
229
|
+
"./adapters/express": {
|
|
230
|
+
import: "./dist/adapters/express.mjs",
|
|
231
|
+
require: "./dist/adapters/express.js",
|
|
232
|
+
types: "./dist/adapters/express.d.ts"
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
files: [
|
|
236
|
+
"dist",
|
|
237
|
+
"LICENSE",
|
|
238
|
+
"README.md"
|
|
239
|
+
],
|
|
240
|
+
bin: {
|
|
241
|
+
llmweb: "./dist/cli.js"
|
|
242
|
+
},
|
|
243
|
+
scripts: {
|
|
244
|
+
build: "npm run build:lib && npm run build:cli",
|
|
245
|
+
"build:lib": "tsup src/index.ts src/index.browser.ts src/adapters/next.tsx src/adapters/react.tsx src/adapters/vanilla.ts src/adapters/express.ts --format cjs,esm --dts --clean --no-splitting",
|
|
246
|
+
"build:cli": "tsup src/cli.ts --format cjs --no-dts --clean --no-splitting",
|
|
247
|
+
dev: "npm run build:lib && npm run build:cli",
|
|
248
|
+
lint: "tsc",
|
|
249
|
+
test: "vitest run"
|
|
250
|
+
},
|
|
251
|
+
keywords: [
|
|
252
|
+
"llm",
|
|
253
|
+
"json",
|
|
254
|
+
"nextjs",
|
|
255
|
+
"api",
|
|
256
|
+
"metadata"
|
|
257
|
+
],
|
|
258
|
+
author: "Kaleab Denbel",
|
|
259
|
+
license: "MIT",
|
|
260
|
+
devDependencies: {
|
|
261
|
+
"@types/node": "^20.0.0",
|
|
262
|
+
"@types/prompts": "^2.4.9",
|
|
263
|
+
"@types/react": "^18.0.0",
|
|
264
|
+
next: "^14.0.0",
|
|
265
|
+
react: "^18.0.0",
|
|
266
|
+
tsup: "^8.0.0",
|
|
267
|
+
typescript: "^5.0.0",
|
|
268
|
+
vitest: "^1.0.0"
|
|
269
|
+
},
|
|
270
|
+
peerDependencies: {
|
|
271
|
+
next: ">=13",
|
|
272
|
+
react: ">=18"
|
|
273
|
+
},
|
|
274
|
+
dependencies: {
|
|
275
|
+
commander: "^14.0.3",
|
|
276
|
+
prompts: "^2.4.2"
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
// src/cli.ts
|
|
281
|
+
var program = new import_commander2.Command();
|
|
282
|
+
program.name("llmweb").description("A compiler for LLM-readable truth from static and dynamic sources.").version(package_default.version);
|
|
283
|
+
program.addCommand(initCommand);
|
|
284
|
+
program.parse(process.argv);
|
package/package.json
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaleabdenbel/llmweb",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "A compiler for LLM-readable truth from static and dynamic sources.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
8
8
|
"main": "./dist/index.js",
|
|
9
9
|
"module": "./dist/index.mjs",
|
|
10
|
+
"browser": "./dist/index.browser.mjs",
|
|
10
11
|
"types": "./dist/index.d.ts",
|
|
11
12
|
"exports": {
|
|
12
13
|
".": {
|
|
14
|
+
"browser": "./dist/index.browser.mjs",
|
|
13
15
|
"import": "./dist/index.mjs",
|
|
14
16
|
"require": "./dist/index.js",
|
|
15
17
|
"types": "./dist/index.d.ts"
|
|
@@ -40,9 +42,14 @@
|
|
|
40
42
|
"LICENSE",
|
|
41
43
|
"README.md"
|
|
42
44
|
],
|
|
45
|
+
"bin": {
|
|
46
|
+
"llmweb": "./dist/cli.js"
|
|
47
|
+
},
|
|
43
48
|
"scripts": {
|
|
44
|
-
"build": "
|
|
45
|
-
"
|
|
49
|
+
"build": "npm run build:lib && npm run build:cli",
|
|
50
|
+
"build:lib": "tsup src/index.ts src/index.browser.ts src/adapters/next.tsx src/adapters/react.tsx src/adapters/vanilla.ts src/adapters/express.ts --format cjs,esm --dts --clean --no-splitting",
|
|
51
|
+
"build:cli": "tsup src/cli.ts --format cjs --no-dts --clean --no-splitting",
|
|
52
|
+
"dev": "npm run build:lib && npm run build:cli",
|
|
46
53
|
"lint": "tsc",
|
|
47
54
|
"test": "vitest run"
|
|
48
55
|
},
|
|
@@ -56,16 +63,21 @@
|
|
|
56
63
|
"author": "Kaleab Denbel",
|
|
57
64
|
"license": "MIT",
|
|
58
65
|
"devDependencies": {
|
|
59
|
-
"typescript": "^5.0.0",
|
|
60
|
-
"tsup": "^8.0.0",
|
|
61
|
-
"vitest": "^1.0.0",
|
|
62
66
|
"@types/node": "^20.0.0",
|
|
67
|
+
"@types/prompts": "^2.4.9",
|
|
63
68
|
"@types/react": "^18.0.0",
|
|
69
|
+
"next": "^14.0.0",
|
|
64
70
|
"react": "^18.0.0",
|
|
65
|
-
"
|
|
71
|
+
"tsup": "^8.0.0",
|
|
72
|
+
"typescript": "^5.0.0",
|
|
73
|
+
"vitest": "^1.0.0"
|
|
66
74
|
},
|
|
67
75
|
"peerDependencies": {
|
|
68
|
-
"
|
|
69
|
-
"
|
|
76
|
+
"next": ">=13",
|
|
77
|
+
"react": ">=18"
|
|
78
|
+
},
|
|
79
|
+
"dependencies": {
|
|
80
|
+
"commander": "^14.0.3",
|
|
81
|
+
"prompts": "^2.4.2"
|
|
70
82
|
}
|
|
71
83
|
}
|
package/dist/adapters/express.js
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
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/adapters/express.ts
|
|
21
|
-
var express_exports = {};
|
|
22
|
-
__export(express_exports, {
|
|
23
|
-
llmMiddleware: () => llmMiddleware
|
|
24
|
-
});
|
|
25
|
-
module.exports = __toCommonJS(express_exports);
|
|
26
|
-
|
|
27
|
-
// src/core/resolver.ts
|
|
28
|
-
async function resolveAll(dynamicSources, options = {}) {
|
|
29
|
-
const keys = Object.keys(dynamicSources);
|
|
30
|
-
const results = await Promise.allSettled(
|
|
31
|
-
keys.map((key) => resolveSource(dynamicSources[key], options.timeout))
|
|
32
|
-
);
|
|
33
|
-
const data = {};
|
|
34
|
-
results.forEach((result, index) => {
|
|
35
|
-
const key = keys[index];
|
|
36
|
-
if (result.status === "fulfilled") {
|
|
37
|
-
data[key] = result.value;
|
|
38
|
-
} else {
|
|
39
|
-
console.error(`[llmweb] Failed to resolve source "${key}":`, result.reason);
|
|
40
|
-
data[key] = null;
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
return data;
|
|
44
|
-
}
|
|
45
|
-
async function resolveSource(source, timeoutMs) {
|
|
46
|
-
const { from } = source;
|
|
47
|
-
const controller = timeoutMs ? new AbortController() : null;
|
|
48
|
-
const signal = controller?.signal;
|
|
49
|
-
const timeoutPromise = timeoutMs ? new Promise(
|
|
50
|
-
(_, reject) => setTimeout(() => {
|
|
51
|
-
controller?.abort();
|
|
52
|
-
reject(new Error(`Timeout of ${timeoutMs}ms exceeded`));
|
|
53
|
-
}, timeoutMs)
|
|
54
|
-
) : null;
|
|
55
|
-
const resolvePromise = (async () => {
|
|
56
|
-
if (from.type === "fetch") {
|
|
57
|
-
if (!from.url) throw new Error("Fetch source requires a URL");
|
|
58
|
-
const response = await fetch(from.url, { signal });
|
|
59
|
-
if (!response.ok) throw new Error(`HTTP error ${response.status} for ${from.url}`);
|
|
60
|
-
return response.json();
|
|
61
|
-
}
|
|
62
|
-
if (from.type === "fn") {
|
|
63
|
-
if (!from.call) throw new Error('Function source requires a "call" property');
|
|
64
|
-
return from.call();
|
|
65
|
-
}
|
|
66
|
-
throw new Error(`Unsupported source type: ${from.type}`);
|
|
67
|
-
})();
|
|
68
|
-
if (timeoutPromise) {
|
|
69
|
-
return Promise.race([resolvePromise, timeoutPromise]);
|
|
70
|
-
}
|
|
71
|
-
return resolvePromise;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// src/core/transformer.ts
|
|
75
|
-
function transform(sourceData, schema) {
|
|
76
|
-
if (!sourceData) return sourceData;
|
|
77
|
-
if (Array.isArray(sourceData)) {
|
|
78
|
-
return sourceData.map((item) => transform(item, schema));
|
|
79
|
-
}
|
|
80
|
-
if (typeof sourceData !== "object") return sourceData;
|
|
81
|
-
const result = {};
|
|
82
|
-
for (const [targetKey, mapping] of Object.entries(schema)) {
|
|
83
|
-
if (typeof mapping === "string") {
|
|
84
|
-
result[targetKey] = getValueByPath(sourceData, mapping);
|
|
85
|
-
} else if (typeof mapping === "function") {
|
|
86
|
-
result[targetKey] = mapping(sourceData);
|
|
87
|
-
} else if (typeof mapping === "object" && mapping !== null) {
|
|
88
|
-
result[targetKey] = transform(sourceData, mapping);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
return result;
|
|
92
|
-
}
|
|
93
|
-
function getValueByPath(obj, path) {
|
|
94
|
-
return path.split(".").reduce((acc, part) => acc && acc[part], obj);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// src/core/merger.ts
|
|
98
|
-
function merge(staticData, dynamicResults) {
|
|
99
|
-
if (!staticData) return dynamicResults;
|
|
100
|
-
return {
|
|
101
|
-
...staticData,
|
|
102
|
-
...dynamicResults
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// src/index.ts
|
|
107
|
-
var import_node_fs = require("fs");
|
|
108
|
-
var import_node_path = require("path");
|
|
109
|
-
async function createLLMSource(config, options = {}) {
|
|
110
|
-
let staticTruth = {};
|
|
111
|
-
if (config.static) {
|
|
112
|
-
try {
|
|
113
|
-
const staticPath = config.static.startsWith("/") ? config.static : (0, import_node_path.join)(process.cwd(), config.static);
|
|
114
|
-
const content = (0, import_node_fs.readFileSync)(staticPath, "utf-8");
|
|
115
|
-
staticTruth = JSON.parse(content);
|
|
116
|
-
} catch (error) {
|
|
117
|
-
if (options.failLoudly) {
|
|
118
|
-
throw new Error(`[llmweb] Static Truth Error: Failed to load/parse JSON at ${config.static}. ${error}`);
|
|
119
|
-
}
|
|
120
|
-
console.warn(`[llmweb] Warning: Could not load static JSON at ${config.static}. Proceeding with dynamic data only.`);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
const dynamicTruth = {};
|
|
124
|
-
if (config.dynamic) {
|
|
125
|
-
const rawResults = await resolveAll(config.dynamic, { timeout: options.timeout });
|
|
126
|
-
for (const [key, source] of Object.entries(config.dynamic)) {
|
|
127
|
-
const rawData = rawResults[key];
|
|
128
|
-
if (rawData === null && options.failLoudly) {
|
|
129
|
-
throw new Error(`[llmweb] Dynamic Truth Error: Source "${key}" failed to resolve.`);
|
|
130
|
-
}
|
|
131
|
-
if (rawData && source.map) {
|
|
132
|
-
try {
|
|
133
|
-
dynamicTruth[key] = transform(rawData, source.map);
|
|
134
|
-
} catch (error) {
|
|
135
|
-
if (options.failLoudly) {
|
|
136
|
-
throw new Error(`[llmweb] Transformation Error: Failed to map source "${key}". ${error}`);
|
|
137
|
-
}
|
|
138
|
-
console.error(`[llmweb] Warning: Mapping failed for "${key}". Using raw data.`);
|
|
139
|
-
dynamicTruth[key] = rawData;
|
|
140
|
-
}
|
|
141
|
-
} else {
|
|
142
|
-
dynamicTruth[key] = rawData;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
return merge(staticTruth, dynamicTruth);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// src/adapters/express.ts
|
|
150
|
-
function llmMiddleware(config) {
|
|
151
|
-
return async (req, res, next) => {
|
|
152
|
-
try {
|
|
153
|
-
const truth = await createLLMSource(config);
|
|
154
|
-
res.status(200).json(truth);
|
|
155
|
-
} catch (error) {
|
|
156
|
-
console.error("[llmweb] Express middleware error:", error);
|
|
157
|
-
res.status(500).json({ error: "Internal Server Error" });
|
|
158
|
-
}
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
162
|
-
0 && (module.exports = {
|
|
163
|
-
llmMiddleware
|
|
164
|
-
});
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createLLMSource
|
|
3
|
-
} from "../chunk-HRF6I6KB.mjs";
|
|
4
|
-
|
|
5
|
-
// src/adapters/express.ts
|
|
6
|
-
function llmMiddleware(config) {
|
|
7
|
-
return async (req, res, next) => {
|
|
8
|
-
try {
|
|
9
|
-
const truth = await createLLMSource(config);
|
|
10
|
-
res.status(200).json(truth);
|
|
11
|
-
} catch (error) {
|
|
12
|
-
console.error("[llmweb] Express middleware error:", error);
|
|
13
|
-
res.status(500).json({ error: "Internal Server Error" });
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
export {
|
|
18
|
-
llmMiddleware
|
|
19
|
-
};
|
package/dist/adapters/next.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { LLMConfig } from "../types";
|
|
2
|
-
interface LLMJsonProps {
|
|
3
|
-
config: LLMConfig;
|
|
4
|
-
/**
|
|
5
|
-
* Optional custom styling for the rendered JSON if viewing in a browser.
|
|
6
|
-
*/
|
|
7
|
-
className?: string;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* A Next.js Server Component that resolves the LLM truth and renders it.
|
|
11
|
-
* By default, it renders a <pre> tag with the JSON string.
|
|
12
|
-
*/
|
|
13
|
-
export declare function LLMJson({ config, className }: LLMJsonProps): Promise<import("react/jsx-runtime").JSX.Element>;
|
|
14
|
-
/**
|
|
15
|
-
* A helper for Next.js App Router Route Handlers (route.ts).
|
|
16
|
-
*/
|
|
17
|
-
export declare function createLLMHandler(config: LLMConfig): () => Promise<Response>;
|
|
18
|
-
export {};
|