@bluelibs/runner 3.1.0 → 3.1.1
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 +169 -10
- package/dist/defs.d.ts +1 -1
- package/dist/models/StoreRegistry.js +1 -1
- package/dist/models/StoreRegistry.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/recursion/README.md +3 -0
- package/src/__tests__/recursion/a.resource.ts +25 -0
- package/src/__tests__/recursion/b.resource.ts +33 -0
- package/src/__tests__/recursion/c.resource.ts +18 -0
- package/src/__tests__/run.dynamic-register-and-dependencies.test.ts +1185 -0
- package/src/defs.ts +1 -1
- package/src/models/StoreRegistry.ts +1 -1
package/README.md
CHANGED
|
@@ -530,6 +530,40 @@ const app = resource({
|
|
|
530
530
|
});
|
|
531
531
|
```
|
|
532
532
|
|
|
533
|
+
## Retrying Failed Operations
|
|
534
|
+
|
|
535
|
+
For when things go wrong, but you know they'll probably work if you just try again. The built-in retry middleware makes your tasks and resources more resilient to transient failures.
|
|
536
|
+
|
|
537
|
+
```typescript
|
|
538
|
+
import { globals } from "@bluelibs/runner";
|
|
539
|
+
|
|
540
|
+
const flakyApiCall = task({
|
|
541
|
+
id: "app.tasks.flakyApiCall",
|
|
542
|
+
middleware: [
|
|
543
|
+
globals.middleware.retry.with({
|
|
544
|
+
retries: 5, // Try up to 5 times
|
|
545
|
+
delayStrategy: (attempt) => 100 * Math.pow(2, attempt), // Exponential backoff
|
|
546
|
+
stopRetryIf: (error) => error.message === "Invalid credentials", // Don't retry auth errors
|
|
547
|
+
}),
|
|
548
|
+
],
|
|
549
|
+
run: async () => {
|
|
550
|
+
// This might fail due to network issues, rate limiting, etc.
|
|
551
|
+
return await fetchFromUnreliableService();
|
|
552
|
+
},
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
const app = resource({
|
|
556
|
+
id: "app",
|
|
557
|
+
register: [flakyApiCall],
|
|
558
|
+
});
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
The retry middleware can be configured with:
|
|
562
|
+
|
|
563
|
+
- `retries`: The maximum number of retry attempts (default: 3).
|
|
564
|
+
- `delayStrategy`: A function that returns the delay in milliseconds before the next attempt.
|
|
565
|
+
- `stopRetryIf`: A function to prevent retries for certain types of errors.
|
|
566
|
+
|
|
533
567
|
## Logging: Because Console.log Isn't Professional
|
|
534
568
|
|
|
535
569
|
_The structured logging system that actually makes debugging enjoyable_
|
|
@@ -928,16 +962,6 @@ await paymentLogger.info("Processing payment", { data: paymentData });
|
|
|
928
962
|
await authLogger.warn("Failed login attempt", { data: { email, ip } });
|
|
929
963
|
```
|
|
930
964
|
|
|
931
|
-
### Common Pitfalls
|
|
932
|
-
|
|
933
|
-
1. **Logging sensitive data**: Never log passwords, tokens, or PII
|
|
934
|
-
2. **Over-logging in hot paths**: Check print thresholds for expensive operations
|
|
935
|
-
3. **Forgetting error objects**: Always include the original error when logging failures
|
|
936
|
-
4. **Poor log levels**: Don't use `error` for expected conditions
|
|
937
|
-
5. **Missing context**: Include relevant identifiers (user ID, request ID, etc.)
|
|
938
|
-
|
|
939
|
-
The Logger system is designed to be fast, flexible, and non-intrusive. Use it liberally - good logging is the difference between debugging hell and debugging heaven.
|
|
940
|
-
|
|
941
965
|
## Meta: Tagging Your Components
|
|
942
966
|
|
|
943
967
|
Sometimes you want to attach metadata to your tasks and resources for documentation, filtering, or middleware logic:
|
|
@@ -1060,6 +1084,140 @@ const advancedTask = task({
|
|
|
1060
1084
|
});
|
|
1061
1085
|
```
|
|
1062
1086
|
|
|
1087
|
+
### Dependency Patterns: Static vs Dynamic
|
|
1088
|
+
|
|
1089
|
+
Dependencies can be defined in two ways - as a static object or as a function that returns an object. Each approach has its use cases:
|
|
1090
|
+
|
|
1091
|
+
```typescript
|
|
1092
|
+
// Static dependencies (most common)
|
|
1093
|
+
const userService = resource({
|
|
1094
|
+
id: "app.services.user",
|
|
1095
|
+
dependencies: { database, logger }, // Object - evaluated immediately
|
|
1096
|
+
init: async (_, { database, logger }) => {
|
|
1097
|
+
// Dependencies are available here
|
|
1098
|
+
},
|
|
1099
|
+
});
|
|
1100
|
+
|
|
1101
|
+
// Dynamic dependencies (for circular references or conditional dependencies)
|
|
1102
|
+
const advancedService = resource({
|
|
1103
|
+
id: "app.services.advanced",
|
|
1104
|
+
// A function gives you the chance
|
|
1105
|
+
dependencies: (config) => ({
|
|
1106
|
+
// Config is what you receive when you register tise resource with .with()
|
|
1107
|
+
// So you can have conditional dependencies based on resource configuration as well.
|
|
1108
|
+
database,
|
|
1109
|
+
logger,
|
|
1110
|
+
conditionalService:
|
|
1111
|
+
process.env.NODE_ENV === "production" ? serviceA : serviceB,
|
|
1112
|
+
}), // Function - evaluated when needed
|
|
1113
|
+
register: (config) => [
|
|
1114
|
+
// Config is what you receive when you register the resource with .with()
|
|
1115
|
+
// Register dependencies dynamically
|
|
1116
|
+
process.env.NODE_ENV === "production"
|
|
1117
|
+
? serviceA.with({ config: "value" })
|
|
1118
|
+
: serviceB.with({ config: "value" }),
|
|
1119
|
+
],
|
|
1120
|
+
init: async (_, { database, logger, conditionalService }) => {
|
|
1121
|
+
// Same interface, different evaluation timing
|
|
1122
|
+
},
|
|
1123
|
+
});
|
|
1124
|
+
```
|
|
1125
|
+
|
|
1126
|
+
The function pattern essentially gives you "just-in-time" dependency resolution instead of "eager" dependency resolution, which provides more flexibility and better handles complex dependency scenarios that arise in real-world applications.
|
|
1127
|
+
|
|
1128
|
+
**Performance note**: Function-based dependencies have minimal overhead - they're only called once during dependency resolution.
|
|
1129
|
+
|
|
1130
|
+
### Handling Circular "Type" Dependencies: Breaking the Chain
|
|
1131
|
+
|
|
1132
|
+
Sometimes you'll run into circular type dependencies because of your file structure not necessarily because of a real circular dependency. TypeScript struggles with these, but there's a way to handle it gracefully.
|
|
1133
|
+
|
|
1134
|
+
#### The Problem: Self-Referencing Types
|
|
1135
|
+
|
|
1136
|
+
Consider these resources that create a circular dependency:
|
|
1137
|
+
|
|
1138
|
+
```typescript
|
|
1139
|
+
// FILE: a.ts
|
|
1140
|
+
export const aResource = defineResource({
|
|
1141
|
+
dependencies: { b: bResource },
|
|
1142
|
+
// ... depends on B resource.
|
|
1143
|
+
});
|
|
1144
|
+
// For whatever reason, you decide to put the task in the same file.
|
|
1145
|
+
export const aTask = defineTask({
|
|
1146
|
+
dependencies: { a: aResource },
|
|
1147
|
+
});
|
|
1148
|
+
|
|
1149
|
+
// FILE: b.ts
|
|
1150
|
+
export const bResource = defineResource({
|
|
1151
|
+
id: "b.resource",
|
|
1152
|
+
dependencies: { c: cResource },
|
|
1153
|
+
});
|
|
1154
|
+
|
|
1155
|
+
// FILE: c.ts
|
|
1156
|
+
export const cResource = defineResource({
|
|
1157
|
+
id: "c.resource",
|
|
1158
|
+
dependencies: { aTask }, // Creates circular **type** dependency! Cannot infer types properly, even if the runner boots because there's no circular dependency.
|
|
1159
|
+
async init(_, { aTask }) {
|
|
1160
|
+
return `C depends on aTask`;
|
|
1161
|
+
},
|
|
1162
|
+
});
|
|
1163
|
+
```
|
|
1164
|
+
|
|
1165
|
+
A depends B depends C depends ATask. No circular dependency, yet Typescript struggles with these, but there's a way to handle it gracefully.
|
|
1166
|
+
|
|
1167
|
+
#### The Solution: Type Annotations
|
|
1168
|
+
|
|
1169
|
+
The fix is to explicitly type the resource that completes the circle using a simple assertion `IResource<Config, ReturnType>`. This breaks the TypeScript inference chain while maintaining runtime functionality:
|
|
1170
|
+
|
|
1171
|
+
```typescript
|
|
1172
|
+
// c.resource.ts - The key change
|
|
1173
|
+
import { IResource } from "../../defs";
|
|
1174
|
+
|
|
1175
|
+
export const cResource = defineResource({
|
|
1176
|
+
id: "c.resource",
|
|
1177
|
+
dependencies: { a: aResource },
|
|
1178
|
+
async init(_, { a }) {
|
|
1179
|
+
return `C depends on ${a}`;
|
|
1180
|
+
},
|
|
1181
|
+
}) as IResource<void, string>; // void because it has no config, string because it returns a string
|
|
1182
|
+
```
|
|
1183
|
+
|
|
1184
|
+
#### Why This Works
|
|
1185
|
+
|
|
1186
|
+
- **Runtime**: The circular dependency still works at runtime because the framework resolves dependencies dynamically
|
|
1187
|
+
- **TypeScript**: The explicit type annotation prevents TypeScript from trying to infer the return type based on the circular chain
|
|
1188
|
+
- **Type Safety**: You still get full type safety by explicitly declaring the return type (`string` in this example)
|
|
1189
|
+
|
|
1190
|
+
#### Best Practices
|
|
1191
|
+
|
|
1192
|
+
1. **Identify the "leaf" resource**: Choose the resource that logically should break the chain (often the one that doesn't need complex type inference)
|
|
1193
|
+
2. **Use explicit typing**: Add the `IResource<Dependencies, ReturnType>` type annotation
|
|
1194
|
+
3. **Document the decision**: Add a comment explaining why the explicit typing is needed
|
|
1195
|
+
4. **Consider refactoring**: If you have many circular dependencies, consider if your architecture could be simplified
|
|
1196
|
+
|
|
1197
|
+
#### Example with Dependencies
|
|
1198
|
+
|
|
1199
|
+
If your resource has dependencies, include them in the type:
|
|
1200
|
+
|
|
1201
|
+
```typescript
|
|
1202
|
+
type MyDependencies = {
|
|
1203
|
+
someService: SomeServiceType;
|
|
1204
|
+
anotherResource: AnotherResourceType;
|
|
1205
|
+
};
|
|
1206
|
+
|
|
1207
|
+
export const problematicResource = defineResource({
|
|
1208
|
+
id: "problematic.resource",
|
|
1209
|
+
dependencies: {
|
|
1210
|
+
/* ... */
|
|
1211
|
+
},
|
|
1212
|
+
async init(config, deps) {
|
|
1213
|
+
// Your logic here
|
|
1214
|
+
return someComplexObject;
|
|
1215
|
+
},
|
|
1216
|
+
}) as IResource<MyDependencies, ComplexReturnType>;
|
|
1217
|
+
```
|
|
1218
|
+
|
|
1219
|
+
This pattern allows you to maintain clean, type-safe code while handling the inevitable circular dependencies that arise in complex applications.
|
|
1220
|
+
|
|
1063
1221
|
## Real-World Example: The Complete Package
|
|
1064
1222
|
|
|
1065
1223
|
Here's a more realistic application structure that shows everything working together:
|
|
@@ -1259,6 +1417,7 @@ const testDatabase = resource({
|
|
|
1259
1417
|
init: async () => new MemoryDatabase(), // In-memory test database
|
|
1260
1418
|
});
|
|
1261
1419
|
|
|
1420
|
+
// Just like a shaworma wrap!
|
|
1262
1421
|
const testApp = resource({
|
|
1263
1422
|
id: "test.app",
|
|
1264
1423
|
register: [productionApp],
|
package/dist/defs.d.ts
CHANGED
|
@@ -204,7 +204,7 @@ export interface IEventEmission<TPayload = any> {
|
|
|
204
204
|
}
|
|
205
205
|
export interface IMiddlewareDefinition<TConfig = any, TDependencies extends DependencyMapType = any> {
|
|
206
206
|
id?: string | symbol;
|
|
207
|
-
dependencies?: TDependencies | (() => TDependencies);
|
|
207
|
+
dependencies?: TDependencies | ((config: TConfig) => TDependencies);
|
|
208
208
|
run: (input: IMiddlewareExecutionInput, dependencies: DependencyValuesType<TDependencies>, config: TConfig) => Promise<any>;
|
|
209
209
|
meta?: IMiddlewareMeta;
|
|
210
210
|
}
|
|
@@ -41,7 +41,7 @@ class StoreRegistry {
|
|
|
41
41
|
check && this.validator.checkIfIDExists(item.id);
|
|
42
42
|
item.dependencies =
|
|
43
43
|
typeof item.dependencies === "function"
|
|
44
|
-
? item.dependencies()
|
|
44
|
+
? item.dependencies(item.config)
|
|
45
45
|
: item.dependencies;
|
|
46
46
|
this.middlewares.set(item.id, {
|
|
47
47
|
middleware: item,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StoreRegistry.js","sourceRoot":"","sources":["../../src/models/StoreRegistry.ts"],"names":[],"mappings":";;;AAAA,kCAYiB;AACjB,mCAAmC;AACnC,sCAAmC;AAOnC,qDAAkD;AAElD,MAAa,aAAa;IACjB,KAAK,GAA+C,IAAI,GAAG,EAAE,CAAC;IAC9D,SAAS,GAAmD,IAAI,GAAG,EAAE,CAAC;IACtE,MAAM,GAAgD,IAAI,GAAG,EAAE,CAAC;IAChE,WAAW,GAChB,IAAI,GAAG,EAAE,CAAC;IAEJ,SAAS,CAAiB;IAElC;QACE,IAAI,CAAC,SAAS,GAAG,IAAI,+BAAc,CACjC,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,MAAM,EACX,IAAI,CAAC,WAAW,CACjB,CAAC;IACJ,CAAC;IAED,YAAY;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,gBAAgB,CAAI,IAAuB;QACzC,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YACvB,IAAI,CAAC,SAAS,CAAI,IAAI,CAAC,CAAC;QAC1B,CAAC;aAAM,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,IAAI,CAAC,aAAa,CAAI,IAAI,CAAC,CAAC;QAC9B,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,UAAU,CAAI,IAAI,CAAC,CAAC;QAC3B,CAAC;aAAM,IAAI,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,IAAI,CAAC,eAAe,CAAI,IAAI,CAAC,CAAC;QAChC,CAAC;aAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5C,IAAI,CAAC,uBAAuB,CAAI,IAAI,CAAC,CAAC;QACxC,CAAC;aAAM,CAAC;YACN,MAAM,eAAM,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IAED,eAAe,CAAI,IAAsB,EAAE,KAAK,GAAG,IAAI;QACrD,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEjD,IAAI,CAAC,YAAY;YACf,OAAO,IAAI,CAAC,YAAY,KAAK,UAAU;gBACrC,CAAC,CAAC,IAAI,CAAC,YAAY,
|
|
1
|
+
{"version":3,"file":"StoreRegistry.js","sourceRoot":"","sources":["../../src/models/StoreRegistry.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { defineResource, defineTask } from "../../define";
|
|
2
|
+
import { bResource } from "./b.resource";
|
|
3
|
+
|
|
4
|
+
export const aResource = defineResource({
|
|
5
|
+
id: "a.resource",
|
|
6
|
+
dependencies: {
|
|
7
|
+
b: bResource,
|
|
8
|
+
},
|
|
9
|
+
async init(_, { b }) {
|
|
10
|
+
const result: string = b;
|
|
11
|
+
// @ts-expect-error
|
|
12
|
+
const result2: number = b;
|
|
13
|
+
return `A depends on ${b}`;
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export const aTask = defineTask({
|
|
18
|
+
id: "a.task",
|
|
19
|
+
dependencies: {
|
|
20
|
+
a: aResource,
|
|
21
|
+
},
|
|
22
|
+
async run(_, { a }) {
|
|
23
|
+
return `Task A executed with dependency: ${a}`;
|
|
24
|
+
},
|
|
25
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { defineResource } from "../../define";
|
|
2
|
+
import { cResource } from "./c.resource";
|
|
3
|
+
|
|
4
|
+
export const bResource = defineResource({
|
|
5
|
+
id: "b.resource",
|
|
6
|
+
dependencies: {
|
|
7
|
+
c: cResource,
|
|
8
|
+
},
|
|
9
|
+
async init(_, { c }) {
|
|
10
|
+
const result: string = c;
|
|
11
|
+
// @ts-expect-error
|
|
12
|
+
const result2: number = c;
|
|
13
|
+
return `B depends on ${c}`;
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
export const b1Resource = defineResource({
|
|
17
|
+
id: "b.resource",
|
|
18
|
+
dependencies: {
|
|
19
|
+
c: cResource,
|
|
20
|
+
},
|
|
21
|
+
async init(_, { c }) {
|
|
22
|
+
return 123;
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
export const b2Resource = defineResource({
|
|
26
|
+
id: "b.resource",
|
|
27
|
+
dependencies: {
|
|
28
|
+
c: cResource,
|
|
29
|
+
},
|
|
30
|
+
async init(_, { c }) {
|
|
31
|
+
return true;
|
|
32
|
+
},
|
|
33
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineResource } from "../../define";
|
|
2
|
+
import { IResource } from "../../defs";
|
|
3
|
+
import { aResource, aTask } from "./a.resource";
|
|
4
|
+
import { b1Resource, b2Resource } from "./b.resource";
|
|
5
|
+
|
|
6
|
+
const value = Math.random() > 0.5 ? b1Resource : b2Resource;
|
|
7
|
+
|
|
8
|
+
export const cResource = defineResource({
|
|
9
|
+
id: "c.resource",
|
|
10
|
+
dependencies: {
|
|
11
|
+
aTask,
|
|
12
|
+
customResource: value,
|
|
13
|
+
},
|
|
14
|
+
async init(_, { aTask, customResource }) {
|
|
15
|
+
const result: string = await aTask(); // Still benefits of autocompletion
|
|
16
|
+
return `C depends on ${result}`;
|
|
17
|
+
},
|
|
18
|
+
}) as IResource<void, string>; // This is the key change.
|