@bluelibs/runner 3.3.1 → 3.4.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.
Files changed (75) hide show
  1. package/README.md +437 -33
  2. package/dist/define.d.ts +5 -5
  3. package/dist/define.js +22 -2
  4. package/dist/define.js.map +1 -1
  5. package/dist/defs.d.ts +55 -21
  6. package/dist/defs.js.map +1 -1
  7. package/dist/defs.returnTag.d.ts +36 -0
  8. package/dist/defs.returnTag.js +4 -0
  9. package/dist/defs.returnTag.js.map +1 -0
  10. package/dist/errors.d.ts +60 -10
  11. package/dist/errors.js +103 -12
  12. package/dist/errors.js.map +1 -1
  13. package/dist/globals/globalMiddleware.d.ts +4 -4
  14. package/dist/globals/globalResources.d.ts +28 -10
  15. package/dist/globals/middleware/cache.middleware.d.ts +9 -9
  16. package/dist/globals/resources/queue.resource.d.ts +5 -2
  17. package/dist/index.d.ts +33 -14
  18. package/dist/index.js +2 -1
  19. package/dist/index.js.map +1 -1
  20. package/dist/models/DependencyProcessor.js +4 -4
  21. package/dist/models/DependencyProcessor.js.map +1 -1
  22. package/dist/models/EventManager.js +10 -1
  23. package/dist/models/EventManager.js.map +1 -1
  24. package/dist/models/Logger.d.ts +8 -0
  25. package/dist/models/Logger.js +24 -0
  26. package/dist/models/Logger.js.map +1 -1
  27. package/dist/models/OverrideManager.js +1 -1
  28. package/dist/models/OverrideManager.js.map +1 -1
  29. package/dist/models/ResourceInitializer.d.ts +2 -2
  30. package/dist/models/ResourceInitializer.js.map +1 -1
  31. package/dist/models/Store.d.ts +2 -2
  32. package/dist/models/Store.js +1 -1
  33. package/dist/models/Store.js.map +1 -1
  34. package/dist/models/StoreConstants.d.ts +6 -3
  35. package/dist/models/StoreRegistry.d.ts +2 -2
  36. package/dist/models/StoreRegistry.js +1 -1
  37. package/dist/models/StoreRegistry.js.map +1 -1
  38. package/dist/models/StoreTypes.d.ts +3 -3
  39. package/dist/models/StoreValidator.js +5 -5
  40. package/dist/models/StoreValidator.js.map +1 -1
  41. package/dist/models/TaskRunner.js +10 -0
  42. package/dist/models/TaskRunner.js.map +1 -1
  43. package/dist/run.d.ts +3 -3
  44. package/dist/run.js +1 -1
  45. package/dist/run.js.map +1 -1
  46. package/dist/t1.d.ts +1 -0
  47. package/dist/t1.js +13 -0
  48. package/dist/t1.js.map +1 -0
  49. package/dist/testing.d.ts +1 -1
  50. package/package.json +2 -2
  51. package/src/__tests__/errors.test.ts +92 -11
  52. package/src/__tests__/models/EventManager.test.ts +0 -1
  53. package/src/__tests__/models/Logger.test.ts +82 -5
  54. package/src/__tests__/recursion/c.resource.ts +1 -1
  55. package/src/__tests__/run.overrides.test.ts +3 -3
  56. package/src/__tests__/typesafety.test.ts +112 -9
  57. package/src/__tests__/validation-edge-cases.test.ts +111 -0
  58. package/src/__tests__/validation-interface.test.ts +428 -0
  59. package/src/define.ts +47 -15
  60. package/src/defs.returnTag.ts +91 -0
  61. package/src/defs.ts +84 -27
  62. package/src/errors.ts +95 -23
  63. package/src/index.ts +1 -0
  64. package/src/models/DependencyProcessor.ts +9 -5
  65. package/src/models/EventManager.ts +12 -3
  66. package/src/models/Logger.ts +28 -0
  67. package/src/models/OverrideManager.ts +2 -7
  68. package/src/models/ResourceInitializer.ts +8 -3
  69. package/src/models/Store.ts +3 -3
  70. package/src/models/StoreRegistry.ts +2 -2
  71. package/src/models/StoreTypes.ts +4 -3
  72. package/src/models/StoreValidator.ts +6 -6
  73. package/src/models/TaskRunner.ts +10 -1
  74. package/src/run.ts +8 -5
  75. package/src/testing.ts +1 -1
package/README.md CHANGED
@@ -4,7 +4,7 @@ _Or: How I Learned to Stop Worrying and Love Dependency Injection_
4
4
 
5
5
  <p align="center">
6
6
  <a href="https://github.com/bluelibs/runner/actions/workflows/ci.yml"><img src="https://github.com/bluelibs/runner/actions/workflows/ci.yml/badge.svg?branch=main" alt="Build Status" /></a>
7
- <a href="https://coveralls.io/github/bluelibs/runner?branch=main"><img src="https://coveralls.io/repos/github/bluelibs/runner/badge.svg?branch=main" alt="Coverage Status" /></a>
7
+ <a href="https://github.com/bluelibs/runner"><img src="https://img.shields.io/badge/coverage-100%25-brightgreen" alt="Coverage 100% is enforced. Code does not build without 100% on all branches, lines, etc." /></a>
8
8
  <a href="https://bluelibs.github.io/runner/" target="_blank"><img src="https://img.shields.io/badge/read-typedocs-blue" alt="Docs" /></a>
9
9
  <a href="https://github.com/bluelibs/runner" target="_blank"><img src="https://img.shields.io/badge/github-blue" alt="GitHub" /></a>
10
10
  </p>
@@ -616,18 +616,32 @@ const businessTask = task({
616
616
  id: "app.tasks.business",
617
617
  dependencies: { logger: globals.resources.logger },
618
618
  run: async (_, { logger }) => {
619
- logger.info("Starting business process");
620
- logger.warn("This might take a while");
619
+ logger.info("Starting business process"); // ✅ Visible by default
620
+ logger.warn("This might take a while"); // ✅ Visible by default
621
621
  logger.error("Oops, something went wrong", {
622
+ // ✅ Visible by default
622
623
  error: new Error("Database connection failed"),
623
624
  });
624
625
  logger.critical("System is on fire", {
626
+ // ✅ Visible by default
625
627
  data: { temperature: "9000°C" },
626
628
  });
629
+ logger.debug("Debug information"); // ❌ Hidden by default
630
+ logger.trace("Very detailed trace"); // ❌ Hidden by default
627
631
  },
628
632
  });
629
633
  ```
630
634
 
635
+ **Good news!** Logs at `info` level and above are visible by default, so you'll see your application logs immediately without any configuration. For development and debugging, you can easily show more detailed logs:
636
+
637
+ ```bash
638
+ # Show debug logs and framework internals
639
+ RUNNER_LOG_LEVEL=debug node your-app.js
640
+
641
+ # Hide all logs for production
642
+ RUNNER_DISABLE_LOGS=true node your-app.js
643
+ ```
644
+
631
645
  ### Log Levels: From Whispers to Screams
632
646
 
633
647
  The logger supports six log levels with increasing severity:
@@ -733,18 +747,31 @@ const requestHandler = task({
733
747
 
734
748
  ### Print Threshold: Control What Shows Up
735
749
 
736
- By default, logs are just events - they don't print to console unless you tell them to. Set a print threshold to automatically output logs at or above a certain level:
750
+ By default, logs at `info` level and above are automatically printed to console for better developer experience. You can easily control this behavior through environment variables or by setting a print threshold programmatically:
751
+
752
+ #### Environment Variable Controls
753
+
754
+ ```bash
755
+ # Disable all logging output
756
+ RUNNER_DISABLE_LOGS=true node your-app.js
757
+
758
+ # Set specific log level (trace, debug, info, warn, error, critical)
759
+ RUNNER_LOG_LEVEL=debug node your-app.js
760
+ RUNNER_LOG_LEVEL=error node your-app.js
761
+ ```
762
+
763
+ #### Programmatic Control
737
764
 
738
765
  ```typescript
739
- // Set up log printing (they don't print by default)
766
+ // Override the default print threshold programmatically
740
767
  const setupLogging = task({
741
768
  id: "app.logging.setup",
742
769
  on: globals.resources.logger.events.afterInit,
743
770
  run: async (event) => {
744
771
  const logger = event.data.value;
745
772
 
746
- // Print info level and above (info, warn, error, critical)
747
- logger.setPrintThreshold("info");
773
+ // Print debug level and above (debug, info, warn, error, critical)
774
+ logger.setPrintThreshold("debug");
748
775
 
749
776
  // Print only errors and critical issues
750
777
  logger.setPrintThreshold("error");
@@ -1171,16 +1198,16 @@ const performanceMiddleware = middleware({
1171
1198
  id: "app.middleware.performance",
1172
1199
  run: async ({ task, next }) => {
1173
1200
  const tags = task.definition.meta?.tags || [];
1174
- const perfConfig = performanceTag.extract(tags);
1201
+ const perfConfigTag = performanceTag.extract(tags); // or easier: .extract(task.definition)
1175
1202
 
1176
- if (perfConfig) {
1203
+ if (perfConfigTag) {
1177
1204
  const startTime = Date.now();
1178
1205
 
1179
1206
  try {
1180
1207
  const result = await next(task.input);
1181
1208
  const duration = Date.now() - startTime;
1182
1209
 
1183
- if (duration > perfConfig.config.criticalAboveMs) {
1210
+ if (duration > perfConfigTag.config.criticalAboveMs) {
1184
1211
  await alerting.critical(
1185
1212
  `Task ${task.definition.id} took ${duration}ms`
1186
1213
  );
@@ -1202,36 +1229,70 @@ const performanceMiddleware = middleware({
1202
1229
  return next(task.input);
1203
1230
  },
1204
1231
  });
1232
+ ```
1205
1233
 
1206
- const rateLimitMiddleware = middleware({
1207
- id: "app.middleware.rateLimit",
1208
- dependencies: { redis },
1209
- run: async ({ task, next }, { redis }) => {
1210
- // Extraction can be done at task.definition level or at task.definition.meta.tags
1211
- const rateLimitCurrentTag = rateLimitTag.extract(task.definition);
1234
+ #### Contract Tags: Enforcing Return Types
1212
1235
 
1213
- // Alternative way
1214
- const tags = task.definition.meta?.tags;
1215
- const rateLimitCurrentTag = rateLimitTag.extract(tags);
1236
+ You can attach contracts to tags to enforce the shape of a task's returned value and a resource's `init()` value at compile time. Contracts are specified via the second generic of `defineTag<TConfig, TContract>`.
1216
1237
 
1217
- if (rateLimitCurrentTag) {
1218
- const key = `rateLimit:${task.definition.id}`;
1219
- const current = await redis.incr(key);
1238
+ ```typescript
1239
+ // A tag that enforces the returned value to include { name: string }
1240
+ const userContract = tag<void, { name: string }>({ id: "contract.user" });
1220
1241
 
1221
- if (current === 1) {
1222
- await redis.expire(key, 60); // 1 minute window
1223
- }
1242
+ // Another tag that enforces { age: number }
1243
+ const ageContract = tag<void, { age: number }>({ id: "contract.age" });
1224
1244
 
1225
- if (current > rateLimitCurrentTag.config.maxRequestsPerMinute) {
1226
- throw new Error("Rate limit exceeded");
1227
- }
1228
- }
1245
+ // Works with configured tags too
1246
+ const preferenceContract = tag<{ locale: string }, { preferredLocale: string }>(
1247
+ { id: "contract.preferences" }
1248
+ );
1249
+ ```
1229
1250
 
1230
- return next(task.input);
1251
+ When these tags are present in `meta.tags`, the returned value must satisfy the intersection of all contract types:
1252
+
1253
+ ```typescript
1254
+ // Task: the awaited return value must satisfy { name: string } & { age: number }
1255
+ const getProfile = task({
1256
+ id: "app.tasks.getProfile",
1257
+ meta: {
1258
+ tags: [
1259
+ userContract,
1260
+ ageContract,
1261
+ preferenceContract.with({ locale: "en" }),
1262
+ ],
1263
+ },
1264
+ run: async () => {
1265
+ return { name: "Ada", age: 37, preferredLocale: "en" }; // OK
1266
+ },
1267
+ });
1268
+
1269
+ // Resource: init() return must satisfy the same intersection
1270
+ const profileService = resource({
1271
+ id: "app.resources.profileService",
1272
+ meta: { tags: [userContract, ageContract] },
1273
+ init: async () => {
1274
+ return { name: "Ada", age: 37 }; // OK
1231
1275
  },
1232
1276
  });
1233
1277
  ```
1234
1278
 
1279
+ If the returned value does not satisfy the intersection, TypeScript surfaces a readable, verbose type error that includes what was expected and what was received.
1280
+
1281
+ ```typescript
1282
+ const badTask = task({
1283
+ id: "app.tasks.bad",
1284
+ meta: { tags: [userContract, ageContract] },
1285
+ // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
1286
+ run: async () => ({ name: "Ada" }), // Missing { age: number }
1287
+ // Type error includes a helpful shape similar to:
1288
+ // ContractViolationError<
1289
+ // { message: "Value does not satisfy all tag contracts";
1290
+ // expected: { name: string } & { age: number };
1291
+ // received: { name: string } }
1292
+ // >
1293
+ });
1294
+ ```
1295
+
1235
1296
  ### When to Use Metadata
1236
1297
 
1237
1298
  #### ✅ Great Use Cases
@@ -1375,9 +1436,8 @@ function getApiTasks(store: Store) {
1375
1436
 
1376
1437
  // Find all tasks with specific performance requirements
1377
1438
  function getPerformanceCriticalTasks(store: Store) {
1378
- return store.getAllTasks().filter((task) => {
1379
- const tags = task.meta?.tags || [];
1380
- return performanceTag.extract(tags) !== null;
1439
+ return store.tasks.values().filter(({ task }) => {
1440
+ return performanceTag.extract(task) !== null;
1381
1441
  });
1382
1442
  }
1383
1443
  ```
@@ -1512,6 +1572,350 @@ const app = resource({
1512
1572
  });
1513
1573
  ```
1514
1574
 
1575
+ ### Runtime Input and Config Validation
1576
+
1577
+ BlueLibs Runner includes a generic validation interface that works with any validation library, including [Zod](https://zod.dev/), [Yup](https://github.com/jquense/yup), [Joi](https://joi.dev/), and others. The framework provides runtime validation with excellent TypeScript inference while remaining library-agnostic.
1578
+
1579
+ #### The Validation Interface
1580
+
1581
+ The framework defines a simple `IValidationSchema<T>` interface that any validation library can implement:
1582
+
1583
+ ```typescript
1584
+ interface IValidationSchema<T> {
1585
+ parse(input: unknown): T;
1586
+ }
1587
+ ```
1588
+
1589
+ Popular validation libraries already implement this interface:
1590
+
1591
+ - **Zod**: `.parse()` method works directly
1592
+ - **Yup**: Use `.validateSync()` or create a wrapper
1593
+ - **Joi**: Use `.assert()` or create a wrapper
1594
+ - **Custom validators**: Implement the interface yourself
1595
+
1596
+ #### Task Input Validation
1597
+
1598
+ Add an `inputSchema` to any task to validate inputs before execution:
1599
+
1600
+ ```typescript
1601
+ import { z } from "zod";
1602
+ import { task, resource, run } from "@bluelibs/runner";
1603
+
1604
+ const userSchema = z.object({
1605
+ name: z.string().min(2),
1606
+ email: z.string().email(),
1607
+ age: z.number().min(0).max(150),
1608
+ });
1609
+
1610
+ const createUserTask = task({
1611
+ id: "app.tasks.createUser",
1612
+ inputSchema: userSchema, // Works directly with Zod!
1613
+ run: async (userData) => {
1614
+ // userData is validated and properly typed
1615
+ return { id: "user-123", ...userData };
1616
+ },
1617
+ });
1618
+
1619
+ const app = resource({
1620
+ id: "app",
1621
+ register: [createUserTask],
1622
+ dependencies: { createUserTask },
1623
+ init: async (_, { createUserTask }) => {
1624
+ // This works - valid input
1625
+ const user = await createUserTask({
1626
+ name: "John Doe",
1627
+ email: "john@example.com",
1628
+ age: 30,
1629
+ });
1630
+
1631
+ // This throws a validation error at runtime
1632
+ try {
1633
+ await createUserTask({
1634
+ name: "J", // Too short
1635
+ email: "invalid-email", // Invalid format
1636
+ age: -5, // Negative age
1637
+ });
1638
+ } catch (error) {
1639
+ console.log(error.message);
1640
+ // "Task input validation failed for app.tasks.createUser: ..."
1641
+ }
1642
+ },
1643
+ });
1644
+ ```
1645
+
1646
+ #### Resource Config Validation (Fail Fast)
1647
+
1648
+ Add a `configSchema` to resources to validate configurations. **Validation happens immediately when `.with()` is called**, ensuring configuration errors are caught early:
1649
+
1650
+ ```typescript
1651
+ const databaseConfigSchema = z.object({
1652
+ host: z.string(),
1653
+ port: z.number().min(1).max(65535),
1654
+ database: z.string(),
1655
+ ssl: z.boolean().default(false), // Optional with default
1656
+ });
1657
+
1658
+ const databaseResource = resource({
1659
+ id: "app.resources.database",
1660
+ configSchema: databaseConfigSchema, // Validation on .with()
1661
+ init: async (config) => {
1662
+ // config is already validated and has proper types
1663
+ return createConnection({
1664
+ host: config.host,
1665
+ port: config.port,
1666
+ database: config.database,
1667
+ ssl: config.ssl,
1668
+ });
1669
+ },
1670
+ });
1671
+
1672
+ // Validation happens here, not during init!
1673
+ try {
1674
+ const configuredResource = databaseResource.with({
1675
+ host: "localhost",
1676
+ port: 99999, // Invalid: port too high
1677
+ database: "myapp",
1678
+ });
1679
+ } catch (error) {
1680
+ // "Resource config validation failed for app.resources.database: ..."
1681
+ }
1682
+
1683
+ const app = resource({
1684
+ id: "app",
1685
+ register: [
1686
+ databaseResource.with({
1687
+ host: "localhost",
1688
+ port: 5432,
1689
+ database: "myapp",
1690
+ // ssl defaults to false
1691
+ }),
1692
+ ],
1693
+ });
1694
+ ```
1695
+
1696
+ #### Event Payload Validation
1697
+
1698
+ Add a `payloadSchema` to events to validate payloads every time they're emitted:
1699
+
1700
+ ```typescript
1701
+ const userActionSchema = z.object({
1702
+ userId: z.string().uuid(),
1703
+ action: z.enum(["created", "updated", "deleted"]),
1704
+ timestamp: z.date().default(() => new Date()),
1705
+ });
1706
+
1707
+ const userActionEvent = event({
1708
+ id: "app.events.userAction",
1709
+ payloadSchema: userActionSchema, // Validates on emit
1710
+ });
1711
+
1712
+ const notificationTask = task({
1713
+ id: "app.tasks.sendNotification",
1714
+ on: userActionEvent,
1715
+ run: async (eventData) => {
1716
+ // eventData.data is validated and properly typed
1717
+ console.log(`User ${eventData.data.userId} was ${eventData.data.action}`);
1718
+ },
1719
+ });
1720
+
1721
+ const app = resource({
1722
+ id: "app",
1723
+ register: [userActionEvent, notificationTask],
1724
+ dependencies: { userActionEvent },
1725
+ init: async (_, { userActionEvent }) => {
1726
+ // This works - valid payload
1727
+ await userActionEvent({
1728
+ userId: "123e4567-e89b-12d3-a456-426614174000",
1729
+ action: "created",
1730
+ });
1731
+
1732
+ // This throws validation error when emitted
1733
+ try {
1734
+ await userActionEvent({
1735
+ userId: "invalid-uuid",
1736
+ action: "unknown",
1737
+ });
1738
+ } catch (error) {
1739
+ // "Event payload validation failed for app.events.userAction: ..."
1740
+ }
1741
+ },
1742
+ });
1743
+ ```
1744
+
1745
+ #### Middleware Config Validation (Fail Fast)
1746
+
1747
+ Add a `configSchema` to middleware to validate configurations. Like resources, **validation happens immediately when `.with()` is called**:
1748
+
1749
+ ```typescript
1750
+ const timingConfigSchema = z.object({
1751
+ timeout: z.number().positive(),
1752
+ logLevel: z.enum(["debug", "info", "warn", "error"]).default("info"),
1753
+ logSuccessful: z.boolean().default(true),
1754
+ });
1755
+
1756
+ const timingMiddleware = middleware({
1757
+ id: "app.middleware.timing",
1758
+ configSchema: timingConfigSchema, // Validation on .with()
1759
+ run: async ({ next }, _, config) => {
1760
+ const start = Date.now();
1761
+ try {
1762
+ const result = await next();
1763
+ const duration = Date.now() - start;
1764
+ if (config.logSuccessful && config.logLevel === "debug") {
1765
+ console.log(`Operation completed in ${duration}ms`);
1766
+ }
1767
+ return result;
1768
+ } catch (error) {
1769
+ const duration = Date.now() - start;
1770
+ console.log(`Operation failed after ${duration}ms`);
1771
+ throw error;
1772
+ }
1773
+ },
1774
+ });
1775
+
1776
+ // Validation happens here, not during execution!
1777
+ try {
1778
+ const configuredMiddleware = timingMiddleware.with({
1779
+ timeout: -5, // Invalid: negative timeout
1780
+ logLevel: "invalid", // Invalid: not in enum
1781
+ });
1782
+ } catch (error) {
1783
+ // "Middleware config validation failed for app.middleware.timing: ..."
1784
+ }
1785
+
1786
+ const myTask = task({
1787
+ id: "app.tasks.example",
1788
+ middleware: [
1789
+ timingMiddleware.with({
1790
+ timeout: 5000,
1791
+ logLevel: "debug",
1792
+ logSuccessful: true,
1793
+ }),
1794
+ ],
1795
+ run: async () => "success",
1796
+ });
1797
+ ```
1798
+
1799
+ #### Advanced Validation Features
1800
+
1801
+ Any validation library features work with the generic interface. Here's an example with transformations and refinements:
1802
+
1803
+ ```typescript
1804
+ const advancedSchema = z
1805
+ .object({
1806
+ userId: z.string().uuid(),
1807
+ amount: z.string().transform((val) => parseFloat(val)), // Transform string to number
1808
+ currency: z.enum(["USD", "EUR", "GBP"]),
1809
+ metadata: z.record(z.string()).optional(),
1810
+ })
1811
+ .refine((data) => data.amount > 0, {
1812
+ message: "Amount must be positive",
1813
+ path: ["amount"],
1814
+ });
1815
+
1816
+ const paymentTask = task({
1817
+ id: "app.tasks.payment",
1818
+ inputSchema: advancedSchema,
1819
+ run: async (payment) => {
1820
+ // payment.amount is now a number (transformed from string)
1821
+ // All validations have passed
1822
+ return processPayment(payment);
1823
+ },
1824
+ });
1825
+ ```
1826
+
1827
+ #### Error Handling
1828
+
1829
+ Validation errors are thrown with clear, descriptive messages that include the component ID:
1830
+
1831
+ ```typescript
1832
+ // Task validation error format:
1833
+ // "Task input validation failed for {taskId}: {validationErrorMessage}"
1834
+
1835
+ // Resource validation error format (thrown on .with() call):
1836
+ // "Resource config validation failed for {resourceId}: {validationErrorMessage}"
1837
+
1838
+ // Event validation error format (thrown on emit):
1839
+ // "Event payload validation failed for {eventId}: {validationErrorMessage}"
1840
+
1841
+ // Middleware validation error format (thrown on .with() call):
1842
+ // "Middleware config validation failed for {middlewareId}: {validationErrorMessage}"
1843
+ ```
1844
+
1845
+ #### Using Different Validation Libraries
1846
+
1847
+ The framework works with any validation library that implements the `IValidationSchema<T>` interface:
1848
+
1849
+ ```typescript
1850
+ // Zod (works directly)
1851
+ import { z } from "zod";
1852
+ const zodSchema = z.string().email();
1853
+
1854
+ // Yup (with wrapper)
1855
+ import * as yup from "yup";
1856
+ const yupSchema = {
1857
+ parse: (input: unknown) => yup.string().email().validateSync(input),
1858
+ };
1859
+
1860
+ // Joi (with wrapper)
1861
+ import Joi from "joi";
1862
+ const joiSchema = {
1863
+ parse: (input: unknown) => {
1864
+ const { error, value } = Joi.string().email().validate(input);
1865
+ if (error) throw error;
1866
+ return value;
1867
+ },
1868
+ };
1869
+
1870
+ // Custom validation
1871
+ const customSchema = {
1872
+ parse: (input: unknown) => {
1873
+ if (typeof input !== "string" || !input.includes("@")) {
1874
+ throw new Error("Must be a valid email");
1875
+ }
1876
+ return input;
1877
+ },
1878
+ };
1879
+ ```
1880
+
1881
+ #### When to Use Validation
1882
+
1883
+ - **API boundaries**: Validating user inputs from HTTP requests
1884
+ - **External data**: Processing data from files, databases, or APIs
1885
+ - **Configuration**: Ensuring environment variables and configs are correct (fail fast)
1886
+ - **Event payloads**: Validating data in event-driven architectures
1887
+ - **Middleware configs**: Validating middleware settings at registration time (fail fast)
1888
+
1889
+ #### Performance Notes
1890
+
1891
+ - Validation only runs when schemas are provided (zero overhead when not used)
1892
+ - Resource and middleware validation happens once at registration time (`.with()`)
1893
+ - Task and event validation happens at runtime
1894
+ - Consider the validation library's performance characteristics for your use case
1895
+ - All major validation libraries are optimized for runtime validation
1896
+
1897
+ #### TypeScript Integration
1898
+
1899
+ While runtime validation happens with your chosen library, TypeScript still enforces compile-time types. For the best experience:
1900
+
1901
+ ```typescript
1902
+ // With Zod, define your type and schema together
1903
+ type UserData = z.infer<typeof userSchema>;
1904
+
1905
+ const userSchema = z.object({
1906
+ name: z.string(),
1907
+ email: z.string().email(),
1908
+ });
1909
+
1910
+ const createUser = task({
1911
+ inputSchema: userSchema,
1912
+ run: async (input: UserData) => {
1913
+ // Both runtime validation AND compile-time typing
1914
+ return { id: "user-123", ...input };
1915
+ },
1916
+ });
1917
+ ```
1918
+
1515
1919
  ### Internal Services: For When You Need Direct Access
1516
1920
 
1517
1921
  We expose the internal services for advanced use cases (but try not to use them unless you really need to):
package/dist/define.d.ts CHANGED
@@ -5,9 +5,9 @@
5
5
  * metadata: anonymous IDs, file path tags (for better debugging), lifecycle
6
6
  * events, and global middleware flags. See README for high-level concepts.
7
7
  */
8
- import { ITask, ITaskDefinition, IResource, IResourceWithConfig, IResourceDefinition, IEventDefinition, IMiddlewareDefinition, DependencyMapType, DependencyValuesType, IMiddleware, IEvent, RegisterableItems, ITag, ITagDefinition } from "./defs";
9
- export declare function defineTask<Input = undefined, Output extends Promise<any> = any, Deps extends DependencyMapType = any, TOn extends "*" | IEventDefinition | undefined = undefined>(taskConfig: ITaskDefinition<Input, Output, Deps, TOn>): ITask<Input, Output, Deps, TOn>;
10
- export declare function defineResource<TConfig = void, TValue = any, TDeps extends DependencyMapType = {}, TPrivate = any>(constConfig: IResourceDefinition<TConfig, TValue, TDeps, TPrivate>): IResource<TConfig, TValue, TDeps, TPrivate>;
8
+ import { ITask, ITaskDefinition, IResource, IResourceWithConfig, IResourceDefinition, IEventDefinition, IMiddlewareDefinition, DependencyMapType, DependencyValuesType, IMiddleware, IEvent, RegisterableItems, ITag, ITagDefinition, ITaskMeta, IResourceMeta } from "./defs";
9
+ export declare function defineTask<Input = undefined, Output extends Promise<any> = any, Deps extends DependencyMapType = any, TOn extends "*" | IEventDefinition | undefined = undefined, TMeta extends ITaskMeta = any>(taskConfig: ITaskDefinition<Input, Output, Deps, TOn, TMeta>): ITask<Input, Output, Deps, TOn, TMeta>;
10
+ export declare function defineResource<TConfig = void, TValue extends Promise<any> = Promise<any>, TDeps extends DependencyMapType = {}, TPrivate = any, TMeta extends IResourceMeta = any>(constConfig: IResourceDefinition<TConfig, TValue, TDeps, TPrivate, any, any, TMeta>): IResource<TConfig, TValue, TDeps, TPrivate, TMeta>;
11
11
  /**
12
12
  * Creates an "index" resource which groups multiple registerable items under
13
13
  * a single dependency. The resulting resource registers every item, depends
@@ -16,7 +16,7 @@ export declare function defineResource<TConfig = void, TValue = any, TDeps exten
16
16
  */
17
17
  export declare function defineIndex<T extends Record<string, RegisterableItems>, D extends {
18
18
  [K in keyof T]: T[K] extends IResourceWithConfig<any, any, any> ? T[K]["resource"] : T[K];
19
- } & DependencyMapType>(items: T): IResource<void, DependencyValuesType<D>, D>;
19
+ } & DependencyMapType>(items: T): IResource<void, Promise<DependencyValuesType<D>>, D>;
20
20
  export declare function defineEvent<TPayload = void>(config?: IEventDefinition<TPayload>): IEvent<TPayload>;
21
21
  export type MiddlewareEverywhereOptions = {
22
22
  /**
@@ -46,4 +46,4 @@ export declare function defineOverride<T extends IMiddleware<any, any>>(base: T,
46
46
  * - `.with(config)` to create configured instances
47
47
  * - `.extract(tags)` to extract this tag from a list of tags
48
48
  */
49
- export declare function defineTag<TConfig = void>(definition: ITagDefinition<TConfig>): ITag<TConfig>;
49
+ export declare function defineTag<TConfig = void, TEnforceContract = void>(definition: ITagDefinition<TConfig, TEnforceContract>): ITag<TConfig, TEnforceContract>;
package/dist/define.js CHANGED
@@ -42,6 +42,7 @@ function defineTask(taskConfig) {
42
42
  run: taskConfig.run,
43
43
  on: taskConfig.on,
44
44
  listenerOrder: taskConfig.listenerOrder,
45
+ inputSchema: taskConfig.inputSchema,
45
46
  events: {
46
47
  beforeRun: {
47
48
  ...defineEvent({
@@ -96,7 +97,17 @@ function defineResource(constConfig) {
96
97
  overrides: constConfig.overrides || [],
97
98
  init: constConfig.init,
98
99
  context: constConfig.context,
100
+ configSchema: constConfig.configSchema,
99
101
  with: function (config) {
102
+ // Validate config with schema if provided (fail fast)
103
+ if (this.configSchema) {
104
+ try {
105
+ config = this.configSchema.parse(config);
106
+ }
107
+ catch (error) {
108
+ throw new errors_1.ValidationError("Resource config", this.id, error instanceof Error ? error : new Error(String(error)));
109
+ }
110
+ }
100
111
  return {
101
112
  [defs_1.symbolResourceWithConfig]: true,
102
113
  id: this.id,
@@ -130,7 +141,7 @@ function defineResource(constConfig) {
130
141
  [defs_1.symbolFilePath]: filePath,
131
142
  },
132
143
  },
133
- meta: constConfig.meta || {},
144
+ meta: (constConfig.meta || {}),
134
145
  middleware: constConfig.middleware || [],
135
146
  };
136
147
  }
@@ -198,6 +209,15 @@ function defineMiddleware(middlewareDef) {
198
209
  return {
199
210
  ...object,
200
211
  with: (config) => {
212
+ // Validate config with schema if provided (fail fast)
213
+ if (object.configSchema) {
214
+ try {
215
+ config = object.configSchema.parse(config);
216
+ }
217
+ catch (error) {
218
+ throw new errors_1.ValidationError("Middleware config", object.id, error instanceof Error ? error : new Error(String(error)));
219
+ }
220
+ }
201
221
  return {
202
222
  ...object,
203
223
  [defs_1.symbolMiddlewareConfigured]: true,
@@ -214,7 +234,7 @@ function defineMiddleware(middlewareDef) {
214
234
  [defs_1.symbolMiddlewareEverywhereTasks]: tasks,
215
235
  [defs_1.symbolMiddlewareEverywhereResources]: resources,
216
236
  everywhere() {
217
- throw errors_1.Errors.middlewareAlreadyGlobal(object.id);
237
+ throw new errors_1.MiddlewareAlreadyGlobalError(object.id);
218
238
  },
219
239
  };
220
240
  },
@@ -1 +1 @@
1
- {"version":3,"file":"define.js","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"define.js","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"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"}