@farm.js/cf-agent 0.1.0-beta.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/LICENSE +22 -0
- package/README.md +11 -0
- package/dist/index.d.ts +70 -0
- package/dist/index.js +321 -0
- package/dist/index.js.map +1 -0
- package/package.json +58 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Farm.js Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# @farm.js/cf-agent
|
|
2
|
+
|
|
3
|
+
First-class Cloudflare Agents integration for Farm.js
|
|
4
|
+
|
|
5
|
+
Farm.js is currently in beta.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @farm.js/cf-agent@beta
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
See the [Farm.js repository](https://github.com/farming-labs/farm.js) for documentation, examples, and support.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { FarmAgentRuntimeInstance, createAgentRuntimeIntegration } from '@farm.js/core/agent-runtime';
|
|
2
|
+
|
|
3
|
+
interface CloudflareAgentOutputOptions {
|
|
4
|
+
root: string;
|
|
5
|
+
outputDir: string;
|
|
6
|
+
config: string;
|
|
7
|
+
routePrefix: string;
|
|
8
|
+
environment?: string;
|
|
9
|
+
}
|
|
10
|
+
interface CloudflareAgentDeployMetadata {
|
|
11
|
+
version: 1;
|
|
12
|
+
provider: "cloudflare-agents";
|
|
13
|
+
config: string;
|
|
14
|
+
environment?: string;
|
|
15
|
+
}
|
|
16
|
+
interface CloudflareAgentOutput {
|
|
17
|
+
wrapperPath: string;
|
|
18
|
+
configPath: string;
|
|
19
|
+
metadataPath: string;
|
|
20
|
+
}
|
|
21
|
+
/** Compose Farm's Cloudflare module output with a Cloudflare Agents Worker. */
|
|
22
|
+
declare function writeCloudflareAgentOutput(options: CloudflareAgentOutputOptions): Promise<CloudflareAgentOutput>;
|
|
23
|
+
|
|
24
|
+
interface CloudflareAgentDevOptions {
|
|
25
|
+
/** Fixed Wrangler port. Farm chooses an available loopback port by default. */
|
|
26
|
+
port?: number;
|
|
27
|
+
/** Run Wrangler against Cloudflare's remote development environment. */
|
|
28
|
+
remote?: boolean;
|
|
29
|
+
/** Forward Wrangler output through Farm's logger. Defaults to true. */
|
|
30
|
+
logs?: boolean;
|
|
31
|
+
/** Maximum time to wait for Wrangler. Defaults to 60 seconds. */
|
|
32
|
+
timeoutMs?: number;
|
|
33
|
+
}
|
|
34
|
+
interface CloudflareAgentOptions {
|
|
35
|
+
/** Wrangler configuration, relative to farm.config.ts. Defaults to wrangler.jsonc. */
|
|
36
|
+
config?: string;
|
|
37
|
+
/** Same-origin route owned by Cloudflare Agents. Defaults to /agents. */
|
|
38
|
+
routePrefix?: string;
|
|
39
|
+
/** Use an already-running Workers runtime instead of starting Wrangler in development. */
|
|
40
|
+
origin?: string;
|
|
41
|
+
/** Wrangler environment passed to development and deployment commands. */
|
|
42
|
+
environment?: string;
|
|
43
|
+
/** Disable managed local development or configure the Wrangler process. */
|
|
44
|
+
dev?: false | CloudflareAgentDevOptions;
|
|
45
|
+
}
|
|
46
|
+
interface CloudflareAgentRuntime extends FarmAgentRuntimeInstance {
|
|
47
|
+
readonly config: string;
|
|
48
|
+
readonly environment?: string;
|
|
49
|
+
}
|
|
50
|
+
type BaseCloudflareAgentIntegration = ReturnType<typeof createAgentRuntimeIntegration>;
|
|
51
|
+
type CloudflareAgentIntegration = Omit<BaseCloudflareAgentIntegration, "instance"> & {
|
|
52
|
+
readonly instance: CloudflareAgentRuntime;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Runs Cloudflare Agents beside Farm in development and composes both into one Worker build.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* integrations: { agent: cfAgent() }
|
|
59
|
+
*/
|
|
60
|
+
declare function cfAgent(options?: CloudflareAgentOptions): CloudflareAgentIntegration;
|
|
61
|
+
declare function createWranglerDevArgs(input: {
|
|
62
|
+
binary: string;
|
|
63
|
+
config: string;
|
|
64
|
+
port: number;
|
|
65
|
+
remote?: boolean;
|
|
66
|
+
environment?: string;
|
|
67
|
+
}): string[];
|
|
68
|
+
declare function assertCloudflareAgentNodeVersion(version?: string): void;
|
|
69
|
+
|
|
70
|
+
export { type CloudflareAgentDeployMetadata, type CloudflareAgentDevOptions, type CloudflareAgentIntegration, type CloudflareAgentOptions, type CloudflareAgentOutput, type CloudflareAgentOutputOptions, type CloudflareAgentRuntime, assertCloudflareAgentNodeVersion, cfAgent, createWranglerDevArgs, writeCloudflareAgentOutput };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { resolve as resolve2 } from "path";
|
|
3
|
+
import {
|
|
4
|
+
createAgentRuntimeIntegration,
|
|
5
|
+
findAvailableAgentRuntimePort,
|
|
6
|
+
resolveProjectPackageBin,
|
|
7
|
+
startManagedAgentRuntime
|
|
8
|
+
} from "@farm.js/core/agent-runtime";
|
|
9
|
+
|
|
10
|
+
// src/output.ts
|
|
11
|
+
import { access, mkdir, readFile, stat, writeFile } from "fs/promises";
|
|
12
|
+
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "path";
|
|
13
|
+
import { parse, printParseErrorCode } from "jsonc-parser";
|
|
14
|
+
import { normalizeAgentRoutePrefix } from "@farm.js/core/agent-runtime";
|
|
15
|
+
var GENERATED_CONFIG_NAME = ".farm-cf-agent.wrangler.jsonc";
|
|
16
|
+
async function writeCloudflareAgentOutput(options) {
|
|
17
|
+
const root = resolve(options.root);
|
|
18
|
+
const outputDir = resolve(root, options.outputDir);
|
|
19
|
+
const configPath = resolve(root, options.config);
|
|
20
|
+
assertInsideRoot(root, configPath, "Wrangler config");
|
|
21
|
+
const configDirectory = dirname(configPath);
|
|
22
|
+
const config = await readWranglerConfig(configPath);
|
|
23
|
+
const agentEntryValue = config.main;
|
|
24
|
+
if (typeof agentEntryValue !== "string" || !agentEntryValue.trim()) {
|
|
25
|
+
throw new Error(`${configPath} must define a non-empty Wrangler main entry.`);
|
|
26
|
+
}
|
|
27
|
+
if (config.no_bundle === true) {
|
|
28
|
+
throw new Error("@farm.js/cf-agent requires Wrangler bundling; remove no_bundle: true.");
|
|
29
|
+
}
|
|
30
|
+
const agentEntry = resolve(configDirectory, agentEntryValue);
|
|
31
|
+
const farmEntry = join(outputDir, "server", "index.mjs");
|
|
32
|
+
const publicDirectory = join(outputDir, "public");
|
|
33
|
+
await assertFile(agentEntry, "Cloudflare agent entry");
|
|
34
|
+
await assertFile(farmEntry, "Farm Cloudflare module entry");
|
|
35
|
+
await assertDirectory(publicDirectory, "Farm public output");
|
|
36
|
+
const generatedDirectory = join(root, ".farm", "cf-agent");
|
|
37
|
+
const wrapperPath = join(generatedDirectory, "worker.mjs");
|
|
38
|
+
const generatedConfigPath = join(configDirectory, GENERATED_CONFIG_NAME);
|
|
39
|
+
const metadataPath = join(generatedDirectory, "deploy.json");
|
|
40
|
+
await mkdir(generatedDirectory, { recursive: true });
|
|
41
|
+
const routePrefix = normalizeAgentRoutePrefix(options.routePrefix);
|
|
42
|
+
await writeFile(
|
|
43
|
+
wrapperPath,
|
|
44
|
+
createCombinedWorkerSource({
|
|
45
|
+
wrapperPath,
|
|
46
|
+
farmEntry,
|
|
47
|
+
agentEntry,
|
|
48
|
+
routePrefix
|
|
49
|
+
})
|
|
50
|
+
);
|
|
51
|
+
const generatedConfig = createGeneratedWranglerConfig({
|
|
52
|
+
config,
|
|
53
|
+
configDirectory,
|
|
54
|
+
wrapperPath,
|
|
55
|
+
publicDirectory,
|
|
56
|
+
environment: options.environment
|
|
57
|
+
});
|
|
58
|
+
await writeFile(generatedConfigPath, `${JSON.stringify(generatedConfig, null, 2)}
|
|
59
|
+
`);
|
|
60
|
+
const metadata = {
|
|
61
|
+
version: 1,
|
|
62
|
+
provider: "cloudflare-agents",
|
|
63
|
+
config: toRootRelativePath(root, generatedConfigPath),
|
|
64
|
+
...options.environment ? { environment: options.environment } : {}
|
|
65
|
+
};
|
|
66
|
+
await writeFile(metadataPath, `${JSON.stringify(metadata, null, 2)}
|
|
67
|
+
`);
|
|
68
|
+
return {
|
|
69
|
+
wrapperPath,
|
|
70
|
+
configPath: generatedConfigPath,
|
|
71
|
+
metadataPath
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function createCombinedWorkerSource(input) {
|
|
75
|
+
const farmSpecifier = JSON.stringify(toImportSpecifier(input.wrapperPath, input.farmEntry));
|
|
76
|
+
const agentSpecifier = JSON.stringify(toImportSpecifier(input.wrapperPath, input.agentEntry));
|
|
77
|
+
const routePrefix = JSON.stringify(input.routePrefix);
|
|
78
|
+
return `import farmWorker from ${farmSpecifier};
|
|
79
|
+
import agentWorker from ${agentSpecifier};
|
|
80
|
+
export * from ${agentSpecifier};
|
|
81
|
+
|
|
82
|
+
const agentRoutePrefix = ${routePrefix};
|
|
83
|
+
|
|
84
|
+
function callFetch(worker, request, env, context, label) {
|
|
85
|
+
const handler = typeof worker === "function" ? worker : worker?.fetch;
|
|
86
|
+
if (typeof handler !== "function") {
|
|
87
|
+
throw new TypeError(label + " does not export a fetch handler.");
|
|
88
|
+
}
|
|
89
|
+
return handler.call(worker, request, env, context);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const worker = {
|
|
93
|
+
...agentWorker,
|
|
94
|
+
...farmWorker,
|
|
95
|
+
fetch(request, env, context) {
|
|
96
|
+
const pathname = new URL(request.url).pathname;
|
|
97
|
+
if (pathname === agentRoutePrefix || pathname.startsWith(agentRoutePrefix + "/")) {
|
|
98
|
+
return callFetch(agentWorker, request, env, context, "Cloudflare agent Worker");
|
|
99
|
+
}
|
|
100
|
+
return callFetch(farmWorker, request, env, context, "Farm Worker");
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export default worker;
|
|
105
|
+
`;
|
|
106
|
+
}
|
|
107
|
+
function createGeneratedWranglerConfig(input) {
|
|
108
|
+
const { $schema: _schema, ...config } = input.config;
|
|
109
|
+
const assets = readObject(config.assets, "Wrangler assets");
|
|
110
|
+
const generated = {
|
|
111
|
+
...config,
|
|
112
|
+
main: toConfigRelativePath(input.configDirectory, input.wrapperPath),
|
|
113
|
+
compatibility_flags: withNodeCompatibility(config.compatibility_flags),
|
|
114
|
+
assets: {
|
|
115
|
+
...assets,
|
|
116
|
+
directory: toConfigRelativePath(input.configDirectory, input.publicDirectory)
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
if (input.environment) {
|
|
120
|
+
const environments = readObject(config.env, "Wrangler env");
|
|
121
|
+
const selected = readObject(
|
|
122
|
+
environments[input.environment],
|
|
123
|
+
`Wrangler env.${input.environment}`
|
|
124
|
+
);
|
|
125
|
+
generated.env = {
|
|
126
|
+
...environments,
|
|
127
|
+
[input.environment]: {
|
|
128
|
+
...selected,
|
|
129
|
+
compatibility_flags: withNodeCompatibility(
|
|
130
|
+
selected.compatibility_flags ?? config.compatibility_flags
|
|
131
|
+
),
|
|
132
|
+
assets: {
|
|
133
|
+
...readObject(
|
|
134
|
+
selected.assets ?? config.assets,
|
|
135
|
+
`Wrangler env.${input.environment}.assets`
|
|
136
|
+
),
|
|
137
|
+
directory: toConfigRelativePath(input.configDirectory, input.publicDirectory)
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return generated;
|
|
143
|
+
}
|
|
144
|
+
async function readWranglerConfig(configPath) {
|
|
145
|
+
let source;
|
|
146
|
+
try {
|
|
147
|
+
source = await readFile(configPath, "utf8");
|
|
148
|
+
} catch {
|
|
149
|
+
throw new Error(`Wrangler config was not found at ${configPath}.`);
|
|
150
|
+
}
|
|
151
|
+
const errors = [];
|
|
152
|
+
const value = parse(source, errors, { allowTrailingComma: true });
|
|
153
|
+
if (errors.length) {
|
|
154
|
+
const details = errors.map((error) => `${printParseErrorCode(error.error)} at offset ${error.offset}`).join(", ");
|
|
155
|
+
throw new Error(`Unable to parse ${basename(configPath)}: ${details}.`);
|
|
156
|
+
}
|
|
157
|
+
if (!isObject(value)) {
|
|
158
|
+
throw new Error(`${configPath} must contain a Wrangler configuration object.`);
|
|
159
|
+
}
|
|
160
|
+
return value;
|
|
161
|
+
}
|
|
162
|
+
function withNodeCompatibility(value) {
|
|
163
|
+
if (value === void 0) return ["nodejs_compat"];
|
|
164
|
+
if (!Array.isArray(value) || !value.every((entry) => typeof entry === "string")) {
|
|
165
|
+
throw new Error("Wrangler compatibility_flags must be an array of strings.");
|
|
166
|
+
}
|
|
167
|
+
return value.includes("nodejs_compat") ? [...value] : [...value, "nodejs_compat"];
|
|
168
|
+
}
|
|
169
|
+
function readObject(value, label) {
|
|
170
|
+
if (value === void 0) return {};
|
|
171
|
+
if (!isObject(value)) {
|
|
172
|
+
throw new Error(`${label} must be an object.`);
|
|
173
|
+
}
|
|
174
|
+
return value;
|
|
175
|
+
}
|
|
176
|
+
function isObject(value) {
|
|
177
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
178
|
+
}
|
|
179
|
+
function toImportSpecifier(fromFile, target) {
|
|
180
|
+
const value = normalizePath(relative(dirname(fromFile), target));
|
|
181
|
+
return hasRelativePrefix(value) ? value : `./${value}`;
|
|
182
|
+
}
|
|
183
|
+
function toConfigRelativePath(configDirectory, target) {
|
|
184
|
+
const value = normalizePath(relative(configDirectory, target));
|
|
185
|
+
return hasRelativePrefix(value) ? value : `./${value}`;
|
|
186
|
+
}
|
|
187
|
+
function toRootRelativePath(root, target) {
|
|
188
|
+
return normalizePath(relative(root, target));
|
|
189
|
+
}
|
|
190
|
+
function normalizePath(value) {
|
|
191
|
+
return sep === "/" ? value : value.split(sep).join("/");
|
|
192
|
+
}
|
|
193
|
+
function hasRelativePrefix(value) {
|
|
194
|
+
return value.startsWith("./") || value.startsWith("../");
|
|
195
|
+
}
|
|
196
|
+
function assertInsideRoot(root, target, label) {
|
|
197
|
+
const pathFromRoot = relative(root, target);
|
|
198
|
+
if (pathFromRoot === ".." || pathFromRoot.startsWith(`..${sep}`) || isAbsolute(pathFromRoot)) {
|
|
199
|
+
throw new Error(`${label} must be inside the Farm project root.`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
async function assertFile(path, label) {
|
|
203
|
+
try {
|
|
204
|
+
await access(path);
|
|
205
|
+
} catch {
|
|
206
|
+
throw new Error(`${label} was not found at ${path}.`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
async function assertDirectory(path, label) {
|
|
210
|
+
try {
|
|
211
|
+
if (!(await stat(path)).isDirectory()) throw new Error();
|
|
212
|
+
} catch {
|
|
213
|
+
throw new Error(`${label} was not found at ${path}.`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// src/index.ts
|
|
218
|
+
var DEFAULT_CONFIG = "wrangler.jsonc";
|
|
219
|
+
var DEFAULT_ROUTE_PREFIX = "/agents";
|
|
220
|
+
function cfAgent(options = {}) {
|
|
221
|
+
const config = options.config || DEFAULT_CONFIG;
|
|
222
|
+
const routePrefix = options.routePrefix || DEFAULT_ROUTE_PREFIX;
|
|
223
|
+
const devOptions = options.dev === false ? void 0 : options.dev || {};
|
|
224
|
+
const externalOrigin = options.origin || process.env.CF_AGENT_ORIGIN?.trim();
|
|
225
|
+
return createAgentRuntimeIntegration({
|
|
226
|
+
provider: "cloudflare",
|
|
227
|
+
routePrefix,
|
|
228
|
+
serverRuntime: Boolean(externalOrigin),
|
|
229
|
+
origin: options.origin,
|
|
230
|
+
originEnv: "CF_AGENT_ORIGIN",
|
|
231
|
+
webSockets: true,
|
|
232
|
+
instance: {
|
|
233
|
+
config,
|
|
234
|
+
environment: options.environment
|
|
235
|
+
},
|
|
236
|
+
...devOptions ? {
|
|
237
|
+
async startDev(context) {
|
|
238
|
+
assertCloudflareAgentNodeVersion();
|
|
239
|
+
const binary = await resolveProjectPackageBin(context.root, "wrangler", "wrangler");
|
|
240
|
+
const port = devOptions.port ?? await findAvailableAgentRuntimePort();
|
|
241
|
+
assertPort(port);
|
|
242
|
+
const origin = `http://127.0.0.1:${port}`;
|
|
243
|
+
const showLogs = devOptions.logs !== false;
|
|
244
|
+
return startManagedAgentRuntime({
|
|
245
|
+
command: process.execPath,
|
|
246
|
+
args: createWranglerDevArgs({
|
|
247
|
+
binary,
|
|
248
|
+
config: resolve2(context.root, config),
|
|
249
|
+
port,
|
|
250
|
+
remote: devOptions.remote,
|
|
251
|
+
environment: options.environment
|
|
252
|
+
}),
|
|
253
|
+
cwd: context.root,
|
|
254
|
+
label: "Cloudflare Agents development server",
|
|
255
|
+
origin,
|
|
256
|
+
healthPath: "/",
|
|
257
|
+
timeoutMs: devOptions.timeoutMs ?? 6e4,
|
|
258
|
+
onOutput: showLogs ? (line, stream) => {
|
|
259
|
+
const message = `[cloudflare] ${line}`;
|
|
260
|
+
if (stream === "stderr") context.log.warn(message);
|
|
261
|
+
else context.log.info(message);
|
|
262
|
+
} : void 0
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
} : {},
|
|
266
|
+
...!externalOrigin ? {
|
|
267
|
+
async afterBuild(context) {
|
|
268
|
+
if (context.preset !== "cloudflare-module") {
|
|
269
|
+
throw new Error(
|
|
270
|
+
"@farm.js/cf-agent requires deploy.preset to be cloudflare-module so Farm and Durable Objects can share one Worker."
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
if (!context.outputDir) {
|
|
274
|
+
throw new Error("Farm did not report a Cloudflare build output directory.");
|
|
275
|
+
}
|
|
276
|
+
await writeCloudflareAgentOutput({
|
|
277
|
+
root: context.root,
|
|
278
|
+
outputDir: context.outputDir,
|
|
279
|
+
config,
|
|
280
|
+
routePrefix: context.routePrefix,
|
|
281
|
+
environment: options.environment
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
} : {}
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
function createWranglerDevArgs(input) {
|
|
288
|
+
return [
|
|
289
|
+
input.binary,
|
|
290
|
+
"dev",
|
|
291
|
+
"--config",
|
|
292
|
+
input.config,
|
|
293
|
+
"--ip",
|
|
294
|
+
"127.0.0.1",
|
|
295
|
+
"--port",
|
|
296
|
+
String(input.port),
|
|
297
|
+
"--show-interactive-dev-session=false",
|
|
298
|
+
...input.remote ? ["--remote"] : [],
|
|
299
|
+
...input.environment ? ["--env", input.environment] : []
|
|
300
|
+
];
|
|
301
|
+
}
|
|
302
|
+
function assertCloudflareAgentNodeVersion(version = process.versions.node) {
|
|
303
|
+
const major = Number.parseInt(version.split(".")[0] || "0", 10);
|
|
304
|
+
if (!Number.isFinite(major) || major < 22) {
|
|
305
|
+
throw new Error(
|
|
306
|
+
`Cloudflare Agents and Wrangler require Node.js 22 or newer. Farm is running Node.js ${version}.`
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
function assertPort(port) {
|
|
311
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
312
|
+
throw new Error("Cloudflare Agents dev.port must be an integer from 1 through 65535.");
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
export {
|
|
316
|
+
assertCloudflareAgentNodeVersion,
|
|
317
|
+
cfAgent,
|
|
318
|
+
createWranglerDevArgs,
|
|
319
|
+
writeCloudflareAgentOutput
|
|
320
|
+
};
|
|
321
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/output.ts"],"sourcesContent":["import { resolve } from \"node:path\";\nimport {\n createAgentRuntimeIntegration,\n findAvailableAgentRuntimePort,\n resolveProjectPackageBin,\n startManagedAgentRuntime,\n type FarmAgentRuntimeInstance,\n} from \"@farm.js/core/agent-runtime\";\nimport { writeCloudflareAgentOutput } from \"./output\";\n\nconst DEFAULT_CONFIG = \"wrangler.jsonc\";\nconst DEFAULT_ROUTE_PREFIX = \"/agents\";\n\nexport interface CloudflareAgentDevOptions {\n /** Fixed Wrangler port. Farm chooses an available loopback port by default. */\n port?: number;\n /** Run Wrangler against Cloudflare's remote development environment. */\n remote?: boolean;\n /** Forward Wrangler output through Farm's logger. Defaults to true. */\n logs?: boolean;\n /** Maximum time to wait for Wrangler. Defaults to 60 seconds. */\n timeoutMs?: number;\n}\n\nexport interface CloudflareAgentOptions {\n /** Wrangler configuration, relative to farm.config.ts. Defaults to wrangler.jsonc. */\n config?: string;\n /** Same-origin route owned by Cloudflare Agents. Defaults to /agents. */\n routePrefix?: string;\n /** Use an already-running Workers runtime instead of starting Wrangler in development. */\n origin?: string;\n /** Wrangler environment passed to development and deployment commands. */\n environment?: string;\n /** Disable managed local development or configure the Wrangler process. */\n dev?: false | CloudflareAgentDevOptions;\n}\n\nexport interface CloudflareAgentRuntime extends FarmAgentRuntimeInstance {\n readonly config: string;\n readonly environment?: string;\n}\n\ntype BaseCloudflareAgentIntegration = ReturnType<typeof createAgentRuntimeIntegration>;\nexport type CloudflareAgentIntegration = Omit<BaseCloudflareAgentIntegration, \"instance\"> & {\n readonly instance: CloudflareAgentRuntime;\n};\n\n/**\n * Runs Cloudflare Agents beside Farm in development and composes both into one Worker build.\n *\n * @example\n * integrations: { agent: cfAgent() }\n */\nexport function cfAgent(options: CloudflareAgentOptions = {}): CloudflareAgentIntegration {\n const config = options.config || DEFAULT_CONFIG;\n const routePrefix = options.routePrefix || DEFAULT_ROUTE_PREFIX;\n const devOptions = options.dev === false ? undefined : options.dev || {};\n const externalOrigin = options.origin || process.env.CF_AGENT_ORIGIN?.trim();\n\n return createAgentRuntimeIntegration({\n provider: \"cloudflare\",\n routePrefix,\n serverRuntime: Boolean(externalOrigin),\n origin: options.origin,\n originEnv: \"CF_AGENT_ORIGIN\",\n webSockets: true,\n instance: {\n config,\n environment: options.environment,\n },\n ...(devOptions\n ? {\n async startDev(context) {\n assertCloudflareAgentNodeVersion();\n const binary = await resolveProjectPackageBin(context.root, \"wrangler\", \"wrangler\");\n const port = devOptions.port ?? (await findAvailableAgentRuntimePort());\n assertPort(port);\n const origin = `http://127.0.0.1:${port}`;\n const showLogs = devOptions.logs !== false;\n\n return startManagedAgentRuntime({\n command: process.execPath,\n args: createWranglerDevArgs({\n binary,\n config: resolve(context.root, config),\n port,\n remote: devOptions.remote,\n environment: options.environment,\n }),\n cwd: context.root,\n label: \"Cloudflare Agents development server\",\n origin,\n healthPath: \"/\",\n timeoutMs: devOptions.timeoutMs ?? 60_000,\n onOutput: showLogs\n ? (line, stream) => {\n const message = `[cloudflare] ${line}`;\n if (stream === \"stderr\") context.log.warn(message);\n else context.log.info(message);\n }\n : undefined,\n });\n },\n }\n : {}),\n ...(!externalOrigin\n ? {\n async afterBuild(context) {\n if (context.preset !== \"cloudflare-module\") {\n throw new Error(\n \"@farm.js/cf-agent requires deploy.preset to be cloudflare-module so Farm and Durable Objects can share one Worker.\",\n );\n }\n if (!context.outputDir) {\n throw new Error(\"Farm did not report a Cloudflare build output directory.\");\n }\n\n await writeCloudflareAgentOutput({\n root: context.root,\n outputDir: context.outputDir,\n config,\n routePrefix: context.routePrefix,\n environment: options.environment,\n });\n },\n }\n : {}),\n }) as CloudflareAgentIntegration;\n}\n\nexport function createWranglerDevArgs(input: {\n binary: string;\n config: string;\n port: number;\n remote?: boolean;\n environment?: string;\n}): string[] {\n return [\n input.binary,\n \"dev\",\n \"--config\",\n input.config,\n \"--ip\",\n \"127.0.0.1\",\n \"--port\",\n String(input.port),\n \"--show-interactive-dev-session=false\",\n ...(input.remote ? [\"--remote\"] : []),\n ...(input.environment ? [\"--env\", input.environment] : []),\n ];\n}\n\nexport function assertCloudflareAgentNodeVersion(version = process.versions.node): void {\n const major = Number.parseInt(version.split(\".\")[0] || \"0\", 10);\n if (!Number.isFinite(major) || major < 22) {\n throw new Error(\n `Cloudflare Agents and Wrangler require Node.js 22 or newer. Farm is running Node.js ${version}.`,\n );\n }\n}\n\nfunction assertPort(port: number): void {\n if (!Number.isInteger(port) || port < 1 || port > 65_535) {\n throw new Error(\"Cloudflare Agents dev.port must be an integer from 1 through 65535.\");\n }\n}\n\nexport { writeCloudflareAgentOutput } from \"./output\";\nexport type {\n CloudflareAgentDeployMetadata,\n CloudflareAgentOutput,\n CloudflareAgentOutputOptions,\n} from \"./output\";\n","import { access, mkdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport { basename, dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport { parse, printParseErrorCode, type ParseError } from \"jsonc-parser\";\nimport { normalizeAgentRoutePrefix } from \"@farm.js/core/agent-runtime\";\n\nconst GENERATED_CONFIG_NAME = \".farm-cf-agent.wrangler.jsonc\";\n\nexport interface CloudflareAgentOutputOptions {\n root: string;\n outputDir: string;\n config: string;\n routePrefix: string;\n environment?: string;\n}\n\nexport interface CloudflareAgentDeployMetadata {\n version: 1;\n provider: \"cloudflare-agents\";\n config: string;\n environment?: string;\n}\n\nexport interface CloudflareAgentOutput {\n wrapperPath: string;\n configPath: string;\n metadataPath: string;\n}\n\ntype JsonObject = Record<string, unknown>;\n\n/** Compose Farm's Cloudflare module output with a Cloudflare Agents Worker. */\nexport async function writeCloudflareAgentOutput(\n options: CloudflareAgentOutputOptions,\n): Promise<CloudflareAgentOutput> {\n const root = resolve(options.root);\n const outputDir = resolve(root, options.outputDir);\n const configPath = resolve(root, options.config);\n assertInsideRoot(root, configPath, \"Wrangler config\");\n\n const configDirectory = dirname(configPath);\n const config = await readWranglerConfig(configPath);\n const agentEntryValue = config.main;\n if (typeof agentEntryValue !== \"string\" || !agentEntryValue.trim()) {\n throw new Error(`${configPath} must define a non-empty Wrangler main entry.`);\n }\n if (config.no_bundle === true) {\n throw new Error(\"@farm.js/cf-agent requires Wrangler bundling; remove no_bundle: true.\");\n }\n\n const agentEntry = resolve(configDirectory, agentEntryValue);\n const farmEntry = join(outputDir, \"server\", \"index.mjs\");\n const publicDirectory = join(outputDir, \"public\");\n await assertFile(agentEntry, \"Cloudflare agent entry\");\n await assertFile(farmEntry, \"Farm Cloudflare module entry\");\n await assertDirectory(publicDirectory, \"Farm public output\");\n\n const generatedDirectory = join(root, \".farm\", \"cf-agent\");\n const wrapperPath = join(generatedDirectory, \"worker.mjs\");\n const generatedConfigPath = join(configDirectory, GENERATED_CONFIG_NAME);\n const metadataPath = join(generatedDirectory, \"deploy.json\");\n await mkdir(generatedDirectory, { recursive: true });\n\n const routePrefix = normalizeAgentRoutePrefix(options.routePrefix);\n await writeFile(\n wrapperPath,\n createCombinedWorkerSource({\n wrapperPath,\n farmEntry,\n agentEntry,\n routePrefix,\n }),\n );\n\n const generatedConfig = createGeneratedWranglerConfig({\n config,\n configDirectory,\n wrapperPath,\n publicDirectory,\n environment: options.environment,\n });\n await writeFile(generatedConfigPath, `${JSON.stringify(generatedConfig, null, 2)}\\n`);\n\n const metadata: CloudflareAgentDeployMetadata = {\n version: 1,\n provider: \"cloudflare-agents\",\n config: toRootRelativePath(root, generatedConfigPath),\n ...(options.environment ? { environment: options.environment } : {}),\n };\n await writeFile(metadataPath, `${JSON.stringify(metadata, null, 2)}\\n`);\n\n return {\n wrapperPath,\n configPath: generatedConfigPath,\n metadataPath,\n };\n}\n\nfunction createCombinedWorkerSource(input: {\n wrapperPath: string;\n farmEntry: string;\n agentEntry: string;\n routePrefix: string;\n}): string {\n const farmSpecifier = JSON.stringify(toImportSpecifier(input.wrapperPath, input.farmEntry));\n const agentSpecifier = JSON.stringify(toImportSpecifier(input.wrapperPath, input.agentEntry));\n const routePrefix = JSON.stringify(input.routePrefix);\n\n return `import farmWorker from ${farmSpecifier};\nimport agentWorker from ${agentSpecifier};\nexport * from ${agentSpecifier};\n\nconst agentRoutePrefix = ${routePrefix};\n\nfunction callFetch(worker, request, env, context, label) {\n const handler = typeof worker === \"function\" ? worker : worker?.fetch;\n if (typeof handler !== \"function\") {\n throw new TypeError(label + \" does not export a fetch handler.\");\n }\n return handler.call(worker, request, env, context);\n}\n\nconst worker = {\n ...agentWorker,\n ...farmWorker,\n fetch(request, env, context) {\n const pathname = new URL(request.url).pathname;\n if (pathname === agentRoutePrefix || pathname.startsWith(agentRoutePrefix + \"/\")) {\n return callFetch(agentWorker, request, env, context, \"Cloudflare agent Worker\");\n }\n return callFetch(farmWorker, request, env, context, \"Farm Worker\");\n },\n};\n\nexport default worker;\n`;\n}\n\nfunction createGeneratedWranglerConfig(input: {\n config: JsonObject;\n configDirectory: string;\n wrapperPath: string;\n publicDirectory: string;\n environment?: string;\n}): JsonObject {\n const { $schema: _schema, ...config } = input.config;\n const assets = readObject(config.assets, \"Wrangler assets\");\n const generated: JsonObject = {\n ...config,\n main: toConfigRelativePath(input.configDirectory, input.wrapperPath),\n compatibility_flags: withNodeCompatibility(config.compatibility_flags),\n assets: {\n ...assets,\n directory: toConfigRelativePath(input.configDirectory, input.publicDirectory),\n },\n };\n\n if (input.environment) {\n const environments = readObject(config.env, \"Wrangler env\");\n const selected = readObject(\n environments[input.environment],\n `Wrangler env.${input.environment}`,\n );\n generated.env = {\n ...environments,\n [input.environment]: {\n ...selected,\n compatibility_flags: withNodeCompatibility(\n selected.compatibility_flags ?? config.compatibility_flags,\n ),\n assets: {\n ...readObject(\n selected.assets ?? config.assets,\n `Wrangler env.${input.environment}.assets`,\n ),\n directory: toConfigRelativePath(input.configDirectory, input.publicDirectory),\n },\n },\n };\n }\n\n return generated;\n}\n\nasync function readWranglerConfig(configPath: string): Promise<JsonObject> {\n let source: string;\n try {\n source = await readFile(configPath, \"utf8\");\n } catch {\n throw new Error(`Wrangler config was not found at ${configPath}.`);\n }\n\n const errors: ParseError[] = [];\n const value = parse(source, errors, { allowTrailingComma: true });\n if (errors.length) {\n const details = errors\n .map((error) => `${printParseErrorCode(error.error)} at offset ${error.offset}`)\n .join(\", \");\n throw new Error(`Unable to parse ${basename(configPath)}: ${details}.`);\n }\n if (!isObject(value)) {\n throw new Error(`${configPath} must contain a Wrangler configuration object.`);\n }\n return value;\n}\n\nfunction withNodeCompatibility(value: unknown): string[] {\n if (value === undefined) return [\"nodejs_compat\"];\n if (!Array.isArray(value) || !value.every((entry) => typeof entry === \"string\")) {\n throw new Error(\"Wrangler compatibility_flags must be an array of strings.\");\n }\n return value.includes(\"nodejs_compat\") ? [...value] : [...value, \"nodejs_compat\"];\n}\n\nfunction readObject(value: unknown, label: string): JsonObject {\n if (value === undefined) return {};\n if (!isObject(value)) {\n throw new Error(`${label} must be an object.`);\n }\n return value;\n}\n\nfunction isObject(value: unknown): value is JsonObject {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction toImportSpecifier(fromFile: string, target: string): string {\n const value = normalizePath(relative(dirname(fromFile), target));\n return hasRelativePrefix(value) ? value : `./${value}`;\n}\n\nfunction toConfigRelativePath(configDirectory: string, target: string): string {\n const value = normalizePath(relative(configDirectory, target));\n return hasRelativePrefix(value) ? value : `./${value}`;\n}\n\nfunction toRootRelativePath(root: string, target: string): string {\n return normalizePath(relative(root, target));\n}\n\nfunction normalizePath(value: string): string {\n return sep === \"/\" ? value : value.split(sep).join(\"/\");\n}\n\nfunction hasRelativePrefix(value: string): boolean {\n return value.startsWith(\"./\") || value.startsWith(\"../\");\n}\n\nfunction assertInsideRoot(root: string, target: string, label: string): void {\n const pathFromRoot = relative(root, target);\n if (pathFromRoot === \"..\" || pathFromRoot.startsWith(`..${sep}`) || isAbsolute(pathFromRoot)) {\n throw new Error(`${label} must be inside the Farm project root.`);\n }\n}\n\nasync function assertFile(path: string, label: string): Promise<void> {\n try {\n await access(path);\n } catch {\n throw new Error(`${label} was not found at ${path}.`);\n }\n}\n\nasync function assertDirectory(path: string, label: string): Promise<void> {\n try {\n if (!(await stat(path)).isDirectory()) throw new Error();\n } catch {\n throw new Error(`${label} was not found at ${path}.`);\n }\n}\n"],"mappings":"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","names":["resolve","resolve"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@farm.js/cf-agent",
|
|
3
|
+
"version": "0.1.0-beta.0",
|
|
4
|
+
"description": "First-class Cloudflare Agents integration for Farm.js",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"agents",
|
|
7
|
+
"cloudflare",
|
|
8
|
+
"durable-objects",
|
|
9
|
+
"farmjs"
|
|
10
|
+
],
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "https://github.com/farming-labs/farm.js",
|
|
15
|
+
"directory": "packages/farm-cf-agent"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"type": "module",
|
|
21
|
+
"main": "./dist/index.js",
|
|
22
|
+
"module": "./dist/index.js",
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"import": "./dist/index.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"jsonc-parser": "^3.3.1",
|
|
35
|
+
"@farm.js/core": "0.1.0-beta.0"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/node": "^20.10.5",
|
|
39
|
+
"agents": "0.17.4",
|
|
40
|
+
"tsup": "^8.5.1",
|
|
41
|
+
"typescript": "^5.3.3",
|
|
42
|
+
"vitest": "^1.6.1",
|
|
43
|
+
"wrangler": "4.111.0"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"agents": ">=0.17.4 <1",
|
|
47
|
+
"wrangler": ">=4.111.0 <5"
|
|
48
|
+
},
|
|
49
|
+
"engines": {
|
|
50
|
+
"node": ">=22"
|
|
51
|
+
},
|
|
52
|
+
"scripts": {
|
|
53
|
+
"build": "tsup",
|
|
54
|
+
"dev": "tsup --watch",
|
|
55
|
+
"test": "vitest run",
|
|
56
|
+
"type-check": "tsc --noEmit"
|
|
57
|
+
}
|
|
58
|
+
}
|