@jaypie/fabric 0.2.0 → 0.2.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.
Files changed (47) hide show
  1. package/dist/cjs/ServiceSuite.d.ts +3 -1
  2. package/dist/cjs/commander/index.cjs +42 -11
  3. package/dist/cjs/commander/index.cjs.map +1 -1
  4. package/dist/cjs/data/index.cjs +40 -11
  5. package/dist/cjs/data/index.cjs.map +1 -1
  6. package/dist/cjs/http/index.cjs +43 -13
  7. package/dist/cjs/http/index.cjs.map +1 -1
  8. package/dist/cjs/index.cjs +50 -21
  9. package/dist/cjs/index.cjs.map +1 -1
  10. package/dist/cjs/index.d.ts +1 -1
  11. package/dist/cjs/lambda/index.cjs +42 -11
  12. package/dist/cjs/lambda/index.cjs.map +1 -1
  13. package/dist/cjs/llm/index.cjs +42 -11
  14. package/dist/cjs/llm/index.cjs.map +1 -1
  15. package/dist/cjs/mcp/FabricMcpServer.d.ts +1 -1
  16. package/dist/cjs/mcp/index.cjs +43 -12
  17. package/dist/cjs/mcp/index.cjs.map +1 -1
  18. package/dist/cjs/models/base.d.ts +6 -6
  19. package/dist/cjs/resolveService.d.ts +7 -4
  20. package/dist/cjs/service.d.ts +6 -4
  21. package/dist/cjs/types.d.ts +9 -3
  22. package/dist/cjs/websocket/fabricWebSocket.d.ts +120 -0
  23. package/dist/cjs/websocket/index.d.ts +2 -0
  24. package/dist/esm/ServiceSuite.d.ts +3 -1
  25. package/dist/esm/commander/index.js +42 -11
  26. package/dist/esm/commander/index.js.map +1 -1
  27. package/dist/esm/data/index.js +40 -11
  28. package/dist/esm/data/index.js.map +1 -1
  29. package/dist/esm/http/index.js +43 -13
  30. package/dist/esm/http/index.js.map +1 -1
  31. package/dist/esm/index.d.ts +1 -1
  32. package/dist/esm/index.js +50 -21
  33. package/dist/esm/index.js.map +1 -1
  34. package/dist/esm/lambda/index.js +42 -11
  35. package/dist/esm/lambda/index.js.map +1 -1
  36. package/dist/esm/llm/index.js +42 -11
  37. package/dist/esm/llm/index.js.map +1 -1
  38. package/dist/esm/mcp/FabricMcpServer.d.ts +1 -1
  39. package/dist/esm/mcp/index.js +43 -12
  40. package/dist/esm/mcp/index.js.map +1 -1
  41. package/dist/esm/models/base.d.ts +6 -6
  42. package/dist/esm/resolveService.d.ts +7 -4
  43. package/dist/esm/service.d.ts +6 -4
  44. package/dist/esm/types.d.ts +9 -3
  45. package/dist/esm/websocket/fabricWebSocket.d.ts +120 -0
  46. package/dist/esm/websocket/index.d.ts +2 -0
  47. package/package.json +6 -1
package/dist/esm/index.js CHANGED
@@ -32,7 +32,7 @@ const FABRIC_MODEL_FIELDS = {
32
32
  // Identity (required)
33
33
  ID: "id",
34
34
  // Schema
35
- CLASS: "class",
35
+ CATEGORY: "category",
36
36
  MODEL: "model",
37
37
  TYPE: "type",
38
38
  // Storage
@@ -797,8 +797,8 @@ const DEFAULT_INDEXES = [
797
797
  sparse: true,
798
798
  },
799
799
  {
800
- name: "indexClass",
801
- pk: ["scope", "model", "class"],
800
+ name: "indexCategory",
801
+ pk: ["scope", "model", "category"],
802
802
  sk: ["sequence"],
803
803
  sparse: true,
804
804
  },
@@ -1457,42 +1457,68 @@ async function processField(fieldName, value, definition) {
1457
1457
  function isService(value) {
1458
1458
  return typeof value === "function" && "$fabric" in value;
1459
1459
  }
1460
+ /**
1461
+ * Run serializer hook if provided
1462
+ * Returns transformed output or original if serializer returns undefined/null/void
1463
+ */
1464
+ async function runSerializer(data, serializer, context) {
1465
+ if (!serializer) {
1466
+ return data.output;
1467
+ }
1468
+ const result = await serializer(data, context);
1469
+ if (result !== undefined && result !== null) {
1470
+ return result;
1471
+ }
1472
+ return data.output;
1473
+ }
1460
1474
  /**
1461
1475
  * Fabric a service function
1462
1476
  *
1463
- * Service builds a function that initiates a "controller" step that:
1477
+ * Service builds a function that:
1464
1478
  * - Parses the input if it is a string to object
1465
1479
  * - Fabrics each input field to its type
1466
1480
  * - Calls the validation function or regular expression or checks the array
1467
- * - Calls the service function and returns the response
1481
+ * - Calls the service function
1482
+ * - Calls the serializer hook (can transform output)
1483
+ * - Returns the response
1468
1484
  *
1469
1485
  * The returned function has config properties for introspection.
1470
1486
  */
1471
1487
  function fabricService(config) {
1472
- const { input: inputDefinitions, service } = config;
1488
+ const { input: inputDefinitions, serializer, service } = config;
1473
1489
  const handler = async (rawInput, context) => {
1474
1490
  // Parse input (handles string JSON)
1475
1491
  const parsedInput = parseInput(rawInput);
1476
1492
  // If no input definitions, pass through to service or return parsed input
1477
1493
  if (!inputDefinitions) {
1494
+ let output;
1478
1495
  if (service) {
1479
- return service(parsedInput, context);
1496
+ output = await service(parsedInput, context);
1497
+ }
1498
+ else {
1499
+ output = parsedInput;
1480
1500
  }
1481
- return parsedInput;
1501
+ // Run serializer
1502
+ return (await runSerializer({ input: parsedInput, output }, serializer, context));
1482
1503
  }
1483
1504
  // Process all fields in parallel
1484
1505
  const entries = Object.entries(inputDefinitions);
1485
1506
  const processedValues = await Promise.all(entries.map(([fieldName, definition]) => processField(fieldName, parsedInput[fieldName], definition)));
1486
1507
  // Build processed input object
1487
- const processedInput = {};
1508
+ const processedInputObj = {};
1488
1509
  entries.forEach(([fieldName], index) => {
1489
- processedInput[fieldName] = processedValues[index];
1510
+ processedInputObj[fieldName] = processedValues[index];
1490
1511
  });
1491
- // Return processed input if no service, otherwise call service
1512
+ // Call service or return processed input
1513
+ let output;
1492
1514
  if (service) {
1493
- return service(processedInput, context);
1515
+ output = await service(processedInputObj, context);
1516
+ }
1517
+ else {
1518
+ output = processedInputObj;
1494
1519
  }
1495
- return processedInput;
1520
+ // Run serializer hook
1521
+ return (await runSerializer({ input: processedInputObj, output }, serializer, context));
1496
1522
  };
1497
1523
  // Attach config properties directly to handler for flat access
1498
1524
  const typedHandler = handler;
@@ -1503,6 +1529,8 @@ function fabricService(config) {
1503
1529
  typedHandler.description = config.description;
1504
1530
  if (config.input !== undefined)
1505
1531
  typedHandler.input = config.input;
1532
+ if (config.serializer !== undefined)
1533
+ typedHandler.serializer = config.serializer;
1506
1534
  if (config.service !== undefined)
1507
1535
  typedHandler.service = config.service;
1508
1536
  return typedHandler;
@@ -1521,6 +1549,7 @@ function fabricService(config) {
1521
1549
  * - `alias` overrides service.alias
1522
1550
  * - `description` overrides service.description
1523
1551
  * - `input` overrides service.input
1552
+ * - `serializer` overrides service.serializer
1524
1553
  *
1525
1554
  * The original Service is never mutated - a new Service is created when overrides
1526
1555
  * are applied.
@@ -1544,7 +1573,7 @@ function fabricService(config) {
1544
1573
  * ```
1545
1574
  */
1546
1575
  function resolveService(config) {
1547
- const { alias, description, input, service } = config;
1576
+ const { alias, description, input, serializer, service } = config;
1548
1577
  if (isService(service)) {
1549
1578
  // Service is pre-instantiated - config fields act as overrides
1550
1579
  // Create new Service with merged properties (config overrides service)
@@ -1552,6 +1581,7 @@ function resolveService(config) {
1552
1581
  alias: alias ?? service.alias,
1553
1582
  description: description ?? service.description,
1554
1583
  input: input ?? service.input,
1584
+ serializer: serializer ?? service.serializer,
1555
1585
  service: service.service,
1556
1586
  });
1557
1587
  }
@@ -1560,6 +1590,7 @@ function resolveService(config) {
1560
1590
  alias,
1561
1591
  description,
1562
1592
  input,
1593
+ serializer,
1563
1594
  service,
1564
1595
  });
1565
1596
  }
@@ -1626,7 +1657,9 @@ function extractEnumValues(type) {
1626
1657
  return undefined;
1627
1658
  // Check if it's a validated string enum (array of strings, possibly with RegExp)
1628
1659
  const stringValues = type.filter((item) => typeof item === "string");
1629
- if (stringValues.length > 0 && stringValues.length === type.filter((item) => typeof item === "string").length) {
1660
+ if (stringValues.length > 0 &&
1661
+ stringValues.length ===
1662
+ type.filter((item) => typeof item === "string").length) {
1630
1663
  // All non-RegExp items are strings
1631
1664
  return stringValues;
1632
1665
  }
@@ -1665,7 +1698,6 @@ function hasRequiredInputs(inputs) {
1665
1698
  */
1666
1699
  function createServiceSuite(config) {
1667
1700
  const { name, version } = config;
1668
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1669
1701
  const serviceRegistry = new Map();
1670
1702
  const categorySet = new Set();
1671
1703
  const suite = {
@@ -1692,9 +1724,8 @@ function createServiceSuite(config) {
1692
1724
  }
1693
1725
  return entry.service(inputs);
1694
1726
  },
1695
- register(
1696
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1697
- service, category) {
1727
+ register(service, options) {
1728
+ const { category } = options;
1698
1729
  const serviceName = service.alias;
1699
1730
  if (!serviceName) {
1700
1731
  throw new Error("Service must have an alias to be registered");
@@ -1710,11 +1741,9 @@ function createServiceSuite(config) {
1710
1741
  serviceRegistry.set(serviceName, { service, meta });
1711
1742
  categorySet.add(category);
1712
1743
  },
1713
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1714
1744
  getServiceFunctions() {
1715
1745
  return Array.from(serviceRegistry.values()).map((entry) => entry.service);
1716
1746
  },
1717
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1718
1747
  getServiceFunction(serviceName) {
1719
1748
  return serviceRegistry.get(serviceName)?.service;
1720
1749
  },