@bluelibs/runner 4.8.0 → 4.8.2
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/AI.md +44 -5
- package/README.md +24 -25
- package/dist/browser/index.cjs +362 -175
- package/dist/browser/index.cjs.map +1 -1
- package/dist/browser/index.mjs +362 -175
- package/dist/browser/index.mjs.map +1 -1
- package/dist/edge/index.cjs +362 -175
- package/dist/edge/index.cjs.map +1 -1
- package/dist/edge/index.mjs +362 -175
- package/dist/edge/index.mjs.map +1 -1
- package/dist/globals/globalResources.d.ts +17 -8
- package/dist/globals/resources/httpClientFactory.resource.d.ts +28 -0
- package/dist/http-client.d.ts +1 -3
- package/dist/index.d.ts +15 -8
- package/dist/node/http-mixed-client.d.ts +3 -0
- package/dist/node/node.cjs +1125 -4525
- package/dist/node/node.cjs.map +1 -1
- package/dist/node/node.d.ts +93 -0
- package/dist/node/node.mjs +1121 -4523
- package/dist/node/node.mjs.map +1 -1
- package/dist/node/resources/http-mixed-client.factory.resource.d.ts +17 -0
- package/dist/node/resources/http-smart-client.factory.resource.d.ts +16 -0
- package/dist/universal/index.cjs +362 -175
- package/dist/universal/index.cjs.map +1 -1
- package/dist/universal/index.mjs +362 -175
- package/dist/universal/index.mjs.map +1 -1
- package/package.json +1 -1
package/AI.md
CHANGED
|
@@ -50,7 +50,7 @@ const createUser = r
|
|
|
50
50
|
.dependencies({ logger: globals.resources.logger })
|
|
51
51
|
.inputSchema<{ name: string }>({ parse: (value) => value })
|
|
52
52
|
.resultSchema<{ id: string; name: string }>({ parse: (value) => value })
|
|
53
|
-
.run(async (
|
|
53
|
+
.run(async (input, { logger }) => {
|
|
54
54
|
await logger.info(`Creating user ${input.name}`);
|
|
55
55
|
return { id: "user-1", name: input.name };
|
|
56
56
|
})
|
|
@@ -104,7 +104,7 @@ const sendEmail = r
|
|
|
104
104
|
loggingMiddleware.with({ label: "email" }),
|
|
105
105
|
tracingMiddleware,
|
|
106
106
|
])
|
|
107
|
-
.run(async (
|
|
107
|
+
.run(async (input, { emailer }) => {
|
|
108
108
|
await emailer.send(input);
|
|
109
109
|
return { delivered: true };
|
|
110
110
|
})
|
|
@@ -131,9 +131,9 @@ const userRegistered = r
|
|
|
131
131
|
const registerUser = r
|
|
132
132
|
.task("app.tasks.registerUser")
|
|
133
133
|
.dependencies({ userRegistered, userService })
|
|
134
|
-
.run(async (
|
|
134
|
+
.run(async (input, deps) => {
|
|
135
135
|
const user = await deps.userService.create(input);
|
|
136
|
-
await deps.userRegistered
|
|
136
|
+
await deps.userRegistered({ userId: user.id, email: user.email });
|
|
137
137
|
return user;
|
|
138
138
|
})
|
|
139
139
|
.build();
|
|
@@ -309,7 +309,46 @@ const root = r
|
|
|
309
309
|
.build();
|
|
310
310
|
```
|
|
311
311
|
|
|
312
|
-
|
|
312
|
+
### HTTP Client Factory (Recommended)
|
|
313
|
+
|
|
314
|
+
The `globals.resources.httpClientFactory` automatically injects serializer, error registry, and async contexts from the store:
|
|
315
|
+
|
|
316
|
+
```ts
|
|
317
|
+
import { r, globals } from "@bluelibs/runner";
|
|
318
|
+
|
|
319
|
+
const myTask = r
|
|
320
|
+
.task("app.tasks.callRemote")
|
|
321
|
+
.dependencies({ clientFactory: globals.resources.httpClientFactory })
|
|
322
|
+
.run(async (input, { clientFactory }) => {
|
|
323
|
+
// Client automatically has serializer, errors, and contexts injected
|
|
324
|
+
const client = clientFactory({
|
|
325
|
+
baseUrl: process.env.API_URL,
|
|
326
|
+
auth: { token: process.env.API_TOKEN },
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
return await client.task("remote.task", input);
|
|
330
|
+
})
|
|
331
|
+
.build();
|
|
332
|
+
|
|
333
|
+
// Node streaming clients via Node DI factories
|
|
334
|
+
import { globals as nodeGlobals } from "@bluelibs/runner/node";
|
|
335
|
+
|
|
336
|
+
const nodeTask = r
|
|
337
|
+
.task("app.tasks.streamingCall")
|
|
338
|
+
.dependencies({ smartFactory: nodeGlobals.resources.httpSmartClientFactory })
|
|
339
|
+
.run(async (input, { smartFactory }) => {
|
|
340
|
+
const client = smartFactory({
|
|
341
|
+
baseUrl: process.env.API_URL,
|
|
342
|
+
});
|
|
343
|
+
// Supports duplex streams and multipart uploads
|
|
344
|
+
return await client.task("remote.streaming.task", input);
|
|
345
|
+
})
|
|
346
|
+
.build();
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### Direct Client Creation (Legacy)
|
|
350
|
+
|
|
351
|
+
You can also create clients directly without DI (manual serializer/error/context passing):
|
|
313
352
|
|
|
314
353
|
```ts
|
|
315
354
|
import { createHttpClient } from "@bluelibs/runner";
|
package/README.md
CHANGED
|
@@ -76,7 +76,7 @@ const createUser = r
|
|
|
76
76
|
.task("app.tasks.createUser")
|
|
77
77
|
.dependencies({ server, logger: globals.resources.logger })
|
|
78
78
|
.inputSchema<{ name: string }>({ parse: (value) => value })
|
|
79
|
-
.run(async (
|
|
79
|
+
.run(async (input, { server, logger }) => {
|
|
80
80
|
await logger.info(`Creating ${input.name}`);
|
|
81
81
|
return { id: "user-123", name: input.name };
|
|
82
82
|
})
|
|
@@ -144,7 +144,7 @@ import { r } from "@bluelibs/runner";
|
|
|
144
144
|
const sendEmail = r
|
|
145
145
|
.task("app.tasks.sendEmail")
|
|
146
146
|
.dependencies({ emailService, logger })
|
|
147
|
-
.run(async (
|
|
147
|
+
.run(async (input, { emailService, logger }) => {
|
|
148
148
|
await logger.info(`Sending email to ${input.to}`);
|
|
149
149
|
return emailService.send(input);
|
|
150
150
|
})
|
|
@@ -280,9 +280,9 @@ const userRegistered = r
|
|
|
280
280
|
const registerUser = r
|
|
281
281
|
.task("app.tasks.registerUser")
|
|
282
282
|
.dependencies({ userService, userRegistered })
|
|
283
|
-
.run(async (
|
|
283
|
+
.run(async (input, { userService, userRegistered }) => {
|
|
284
284
|
const user = await userService.createUser(input);
|
|
285
|
-
await userRegistered
|
|
285
|
+
await userRegistered({ userId: user.id, email: user.email });
|
|
286
286
|
return user;
|
|
287
287
|
})
|
|
288
288
|
.build();
|
|
@@ -491,7 +491,7 @@ const authMiddleware = r.middleware
|
|
|
491
491
|
const adminTask = r
|
|
492
492
|
.task("app.tasks.adminOnly")
|
|
493
493
|
.middleware([authMiddleware.with({ requiredRole: "admin" })])
|
|
494
|
-
.run(async (
|
|
494
|
+
.run(async (input) => "Secret admin data")
|
|
495
495
|
.build();
|
|
496
496
|
```
|
|
497
497
|
|
|
@@ -531,7 +531,7 @@ const resourceAuthMiddleware = r.middleware
|
|
|
531
531
|
const adminTask = r
|
|
532
532
|
.task("app.tasks.adminOnly")
|
|
533
533
|
.middleware([authMiddleware.with({ requiredRole: "admin" })])
|
|
534
|
-
.run(async (
|
|
534
|
+
.run(async (input: { user: { role: string } }) => ({
|
|
535
535
|
user: { role: input.user.role, verified: true },
|
|
536
536
|
}))
|
|
537
537
|
.build();
|
|
@@ -599,7 +599,7 @@ const loggingMiddleware = r.middleware
|
|
|
599
599
|
const loggedTask = r
|
|
600
600
|
.task("app.tasks.logged")
|
|
601
601
|
.middleware([loggingMiddleware.with({ includeTimestamp: true })])
|
|
602
|
-
.run(async (
|
|
602
|
+
.run(async (input: { data: string }) => ({
|
|
603
603
|
data: input.data.toUpperCase(),
|
|
604
604
|
}))
|
|
605
605
|
.build();
|
|
@@ -620,7 +620,7 @@ import { r } from "@bluelibs/runner";
|
|
|
620
620
|
const apiTask = r
|
|
621
621
|
.task("app.tasks.getUserData")
|
|
622
622
|
.tags(["api", "public", "cacheable"])
|
|
623
|
-
.run(async (
|
|
623
|
+
.run(async (input) => getUserFromDatabase(input as any))
|
|
624
624
|
.build();
|
|
625
625
|
|
|
626
626
|
// Structured tags with configuration
|
|
@@ -629,7 +629,7 @@ const httpTag = r.tag<{ method: string; path: string }>("http.route").build();
|
|
|
629
629
|
const getUserTask = r
|
|
630
630
|
.task("app.tasks.getUser")
|
|
631
631
|
.tags(["api", httpTag.with({ method: "GET", path: "/users/:id" })])
|
|
632
|
-
.run(async (
|
|
632
|
+
.run(async (input) => getUserFromDatabase((input as any).id))
|
|
633
633
|
.build();
|
|
634
634
|
```
|
|
635
635
|
|
|
@@ -760,7 +760,7 @@ const userNotFoundError = r
|
|
|
760
760
|
const getUser = r
|
|
761
761
|
.task("app.tasks.getUser")
|
|
762
762
|
.dependencies({ userNotFoundError })
|
|
763
|
-
.run(async (
|
|
763
|
+
.run(async (input, { userNotFoundError }) => {
|
|
764
764
|
userNotFoundError.throw({ code: 404, message: `User ${input} not found` });
|
|
765
765
|
})
|
|
766
766
|
.build();
|
|
@@ -884,7 +884,7 @@ import { r, run } from "@bluelibs/runner";
|
|
|
884
884
|
|
|
885
885
|
const calculatorTask = r
|
|
886
886
|
.task("app.tasks.calculator")
|
|
887
|
-
.run(async (
|
|
887
|
+
.run(async (input: { value: number }) => {
|
|
888
888
|
console.log("3. Task is running...");
|
|
889
889
|
return { result: input.value + 1 };
|
|
890
890
|
})
|
|
@@ -949,7 +949,7 @@ const userRegistration = r
|
|
|
949
949
|
emailService: emailService.optional(), // Optional - won't fail if missing
|
|
950
950
|
analytics: analyticsService.optional(), // Optional - graceful degradation
|
|
951
951
|
})
|
|
952
|
-
.run(async (
|
|
952
|
+
.run(async (input, { database, emailService, analytics }) => {
|
|
953
953
|
// Create user (required)
|
|
954
954
|
const user = await database.users.create(userData);
|
|
955
955
|
|
|
@@ -1051,12 +1051,13 @@ app = app.build();
|
|
|
1051
1051
|
const remoteTasksTunnel = r
|
|
1052
1052
|
.resource("app.tunnels.http")
|
|
1053
1053
|
.tags([globals.tags.tunnel])
|
|
1054
|
-
.
|
|
1054
|
+
.dependencies({ createClient: globals.resource.httpClientFactory })
|
|
1055
|
+
.init(async (_, { createClient }) => ({
|
|
1055
1056
|
mode: "client", // or "server", or "none", or "both" for emulating network infrastructure
|
|
1056
1057
|
transport: "http", // the only one supported for now
|
|
1057
1058
|
// Selectively forward tasks starting with "remote.tasks."
|
|
1058
1059
|
tasks: (t) => t.id.startsWith("remote.tasks."),
|
|
1059
|
-
client:
|
|
1060
|
+
client: createClient({
|
|
1060
1061
|
url: "http://remote-runner:8080/__runner",
|
|
1061
1062
|
}),
|
|
1062
1063
|
}))
|
|
@@ -1184,9 +1185,7 @@ import type {
|
|
|
1184
1185
|
// Task example
|
|
1185
1186
|
const add = r
|
|
1186
1187
|
.task("calc.add")
|
|
1187
|
-
.run(
|
|
1188
|
-
async ({ input }: { input: { a: number; b: number } }) => input.a + input.b,
|
|
1189
|
-
)
|
|
1188
|
+
.run(async (input: { a: number; b: number }) => input.a + input.b)
|
|
1190
1189
|
.build();
|
|
1191
1190
|
|
|
1192
1191
|
type AddInput = ExtractTaskInput<typeof add>; // { a: number; b: number }
|
|
@@ -1245,7 +1244,7 @@ const requestMiddleware = r.middleware
|
|
|
1245
1244
|
const handleRequest = r
|
|
1246
1245
|
.task("app.handleRequest")
|
|
1247
1246
|
.middleware([requestMiddleware])
|
|
1248
|
-
.run(async (
|
|
1247
|
+
.run(async (input: { path: string }) => {
|
|
1249
1248
|
const request = requestContext.use();
|
|
1250
1249
|
console.log(`Processing ${input.path} (Request ID: ${request.requestId})`);
|
|
1251
1250
|
return { success: true, requestId: request.requestId };
|
|
@@ -1395,7 +1394,7 @@ const expensiveTask = r
|
|
|
1395
1394
|
keyBuilder: (taskId, input) => `${taskId}-${(input as any).userId}`, // optional key builder
|
|
1396
1395
|
}),
|
|
1397
1396
|
])
|
|
1398
|
-
.run(async (
|
|
1397
|
+
.run(async (input: { userId: string }) => {
|
|
1399
1398
|
// This expensive operation will be cached
|
|
1400
1399
|
return await doExpensiveCalculation(input.userId);
|
|
1401
1400
|
})
|
|
@@ -1423,7 +1422,7 @@ import { r } from "@bluelibs/runner";
|
|
|
1423
1422
|
|
|
1424
1423
|
const redisCacheFactory = r
|
|
1425
1424
|
.task("globals.tasks.cacheFactory") // Same ID as the default task
|
|
1426
|
-
.run(async (
|
|
1425
|
+
.run(async (input: { input: any }) => new RedisCache(input))
|
|
1427
1426
|
.build();
|
|
1428
1427
|
|
|
1429
1428
|
const app = r
|
|
@@ -1468,7 +1467,7 @@ Here are real performance metrics from our comprehensive benchmark suite on an M
|
|
|
1468
1467
|
const userTask = r
|
|
1469
1468
|
.task("user.create")
|
|
1470
1469
|
.middleware([auth, logging, metrics])
|
|
1471
|
-
.run(async (
|
|
1470
|
+
.run(async (input) => database.users.create(input as any))
|
|
1472
1471
|
.build();
|
|
1473
1472
|
|
|
1474
1473
|
// 1000 executions = ~5ms total time
|
|
@@ -1528,7 +1527,7 @@ const database = r
|
|
|
1528
1527
|
const expensiveTask = r
|
|
1529
1528
|
.task("app.performance.expensive")
|
|
1530
1529
|
.middleware([globals.middleware.cache.with({ ttl: 60000 })])
|
|
1531
|
-
.run(async (
|
|
1530
|
+
.run(async (input) => {
|
|
1532
1531
|
// This expensive computation is cached
|
|
1533
1532
|
return performExpensiveCalculation(input);
|
|
1534
1533
|
})
|
|
@@ -1751,7 +1750,7 @@ The logger accepts rich, structured data that makes debugging actually useful:
|
|
|
1751
1750
|
const userTask = r
|
|
1752
1751
|
.task("app.tasks.user.create")
|
|
1753
1752
|
.dependencies({ logger: globals.resources.logger })
|
|
1754
|
-
.run(async (
|
|
1753
|
+
.run(async (input, { logger }) => {
|
|
1755
1754
|
// Basic message
|
|
1756
1755
|
logger.info("Creating new user");
|
|
1757
1756
|
|
|
@@ -2028,7 +2027,7 @@ const criticalTask = r
|
|
|
2028
2027
|
logTaskOnError: true,
|
|
2029
2028
|
}),
|
|
2030
2029
|
])
|
|
2031
|
-
.run(async (
|
|
2030
|
+
.run(async (input) => {
|
|
2032
2031
|
// This task will have verbose debug logging
|
|
2033
2032
|
return await processPayment(input as any);
|
|
2034
2033
|
})
|
|
@@ -2719,7 +2718,7 @@ type UserData = z.infer<typeof userSchema>;
|
|
|
2719
2718
|
const createUser = r
|
|
2720
2719
|
.task("app.tasks.createUser.zod")
|
|
2721
2720
|
.inputSchema(userSchema)
|
|
2722
|
-
.run(async (
|
|
2721
|
+
.run(async (input: { input: UserData }) => {
|
|
2723
2722
|
// Both runtime validation AND compile-time typing
|
|
2724
2723
|
return { id: "user-123", ...input };
|
|
2725
2724
|
})
|