mycelia-kernel-plugin 1.0.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 (53) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +248 -0
  3. package/bin/cli.js +433 -0
  4. package/package.json +63 -0
  5. package/src/builder/context-resolver.js +62 -0
  6. package/src/builder/dependency-graph-cache.js +105 -0
  7. package/src/builder/dependency-graph.js +141 -0
  8. package/src/builder/facet-validator.js +43 -0
  9. package/src/builder/hook-processor.js +271 -0
  10. package/src/builder/index.js +13 -0
  11. package/src/builder/subsystem-builder.js +104 -0
  12. package/src/builder/utils.js +165 -0
  13. package/src/contract/contracts/hierarchy.contract.js +60 -0
  14. package/src/contract/contracts/index.js +17 -0
  15. package/src/contract/contracts/listeners.contract.js +66 -0
  16. package/src/contract/contracts/processor.contract.js +47 -0
  17. package/src/contract/contracts/queue.contract.js +58 -0
  18. package/src/contract/contracts/router.contract.js +53 -0
  19. package/src/contract/contracts/scheduler.contract.js +65 -0
  20. package/src/contract/contracts/server.contract.js +88 -0
  21. package/src/contract/contracts/speak.contract.js +50 -0
  22. package/src/contract/contracts/storage.contract.js +107 -0
  23. package/src/contract/contracts/websocket.contract.js +90 -0
  24. package/src/contract/facet-contract-registry.js +155 -0
  25. package/src/contract/facet-contract.js +136 -0
  26. package/src/contract/index.js +63 -0
  27. package/src/core/create-hook.js +63 -0
  28. package/src/core/facet.js +189 -0
  29. package/src/core/index.js +3 -0
  30. package/src/hooks/listeners/handler-group-manager.js +88 -0
  31. package/src/hooks/listeners/listener-manager-policies.js +229 -0
  32. package/src/hooks/listeners/listener-manager.js +668 -0
  33. package/src/hooks/listeners/listener-registry.js +176 -0
  34. package/src/hooks/listeners/listener-statistics.js +106 -0
  35. package/src/hooks/listeners/pattern-matcher.js +283 -0
  36. package/src/hooks/listeners/use-listeners.js +164 -0
  37. package/src/hooks/queue/bounded-queue.js +341 -0
  38. package/src/hooks/queue/circular-buffer.js +231 -0
  39. package/src/hooks/queue/subsystem-queue-manager.js +198 -0
  40. package/src/hooks/queue/use-queue.js +96 -0
  41. package/src/hooks/speak/use-speak.js +79 -0
  42. package/src/index.js +49 -0
  43. package/src/manager/facet-manager-transaction.js +45 -0
  44. package/src/manager/facet-manager.js +570 -0
  45. package/src/manager/index.js +3 -0
  46. package/src/system/base-subsystem.js +416 -0
  47. package/src/system/base-subsystem.utils.js +106 -0
  48. package/src/system/index.js +4 -0
  49. package/src/system/standalone-plugin-system.js +70 -0
  50. package/src/utils/debug-flag.js +34 -0
  51. package/src/utils/find-facet.js +30 -0
  52. package/src/utils/logger.js +84 -0
  53. package/src/utils/semver.js +221 -0
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Server Facet Contract
3
+ *
4
+ * Defines the contract that server facets must satisfy.
5
+ * Ensures all required HTTP server methods are implemented and validates
6
+ * internal structure for compatibility with different server implementations (Fastify, Express).
7
+ *
8
+ * @example
9
+ * import { serverContract } from './server.contract.js';
10
+ *
11
+ * // Enforce contract on a server facet
12
+ * serverContract.enforce(ctx, api, subsystem, serverFacet);
13
+ */
14
+ import { createFacetContract } from '../facet-contract.js';
15
+
16
+ /**
17
+ * Server Facet Contract
18
+ *
19
+ * Required methods:
20
+ * - Lifecycle: start, stop, isRunning
21
+ * - Route Registration (Single): get, post, put, patch, delete, all
22
+ * - Route Registration (Batch): registerRoutes, registerMyceliaRoutes
23
+ * - Middleware: use, useRoute
24
+ * - Error Handling: setErrorHandler
25
+ * - Server Info: getAddress, getPort
26
+ * - Mycelia Integration: registerMyceliaRoute, registerMyceliaCommand, registerMyceliaQuery
27
+ *
28
+ * Required properties:
29
+ * - _server: Internal server instance (Fastify/Express)
30
+ * - _isRunning: Running state flag
31
+ *
32
+ * Custom validation:
33
+ * - Validates _server is an object (not null or primitive)
34
+ * - Validates _isRunning is a boolean
35
+ */
36
+ export const serverContract = createFacetContract({
37
+ name: 'server',
38
+ requiredMethods: [
39
+ // Lifecycle
40
+ 'start',
41
+ 'stop',
42
+ 'isRunning',
43
+
44
+ // Route Registration (Single)
45
+ 'get',
46
+ 'post',
47
+ 'put',
48
+ 'patch',
49
+ 'delete',
50
+ 'all', // All HTTP methods
51
+
52
+ // Route Registration (Batch)
53
+ 'registerRoutes', // Register multiple routes at once
54
+ 'registerMyceliaRoutes', // Register multiple Mycelia routes at once
55
+
56
+ // Middleware
57
+ 'use', // Global middleware
58
+ 'useRoute', // Route-specific middleware
59
+
60
+ // Error Handling
61
+ 'setErrorHandler',
62
+
63
+ // Server Info
64
+ 'getAddress',
65
+ 'getPort',
66
+
67
+ // Integration
68
+ 'registerMyceliaRoute', // Register Mycelia route as HTTP endpoint
69
+ 'registerMyceliaCommand', // Register Mycelia command as HTTP endpoint
70
+ 'registerMyceliaQuery' // Register Mycelia query as HTTP endpoint
71
+ ],
72
+ requiredProperties: [
73
+ '_server', // Internal server instance (Fastify/Express)
74
+ '_isRunning' // Running state flag
75
+ ],
76
+ validate: (ctx, api, subsystem, facet) => {
77
+ // Validate _server is an object
78
+ if (typeof facet._server !== 'object' || facet._server === null) {
79
+ throw new Error('Server facet _server must be an object');
80
+ }
81
+
82
+ // Validate _isRunning is a boolean
83
+ if (typeof facet._isRunning !== 'boolean') {
84
+ throw new Error('Server facet _isRunning must be a boolean');
85
+ }
86
+ }
87
+ });
88
+
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Speak Contract
3
+ *
4
+ * Defines the interface for facets that provide speaking/printing functionality.
5
+ * This is a simple example contract for demonstration purposes.
6
+ *
7
+ * @example
8
+ * // Create a speak contract
9
+ * const speakContract = createFacetContract({
10
+ * name: 'speak',
11
+ * requiredMethods: ['say', 'sayLine'],
12
+ * requiredProperties: []
13
+ * });
14
+ */
15
+ import { createFacetContract } from '../facet-contract.js';
16
+
17
+ export const speakContract = createFacetContract({
18
+ name: 'speak',
19
+ requiredMethods: ['say', 'sayLine'],
20
+ requiredProperties: [],
21
+ validate: (ctx, api, subsystem, facet) => {
22
+ const errors = [];
23
+
24
+ // Validate say method
25
+ if (typeof facet.say !== 'function') {
26
+ errors.push('speak facet must have a say() method');
27
+ } else {
28
+ // Check method signature (should accept at least one argument)
29
+ if (facet.say.length < 1) {
30
+ errors.push('speak.say() method must accept at least one argument (message)');
31
+ }
32
+ }
33
+
34
+ // Validate sayLine method
35
+ if (typeof facet.sayLine !== 'function') {
36
+ errors.push('speak facet must have a sayLine() method');
37
+ } else {
38
+ // Check method signature (should accept at least one argument)
39
+ if (facet.sayLine.length < 1) {
40
+ errors.push('speak.sayLine() method must accept at least one argument (message)');
41
+ }
42
+ }
43
+
44
+ return {
45
+ valid: errors.length === 0,
46
+ errors
47
+ };
48
+ }
49
+ });
50
+
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Storage Facet Contract
3
+ *
4
+ * Defines the contract that storage facets must satisfy.
5
+ * Ensures all required storage methods are implemented and validates
6
+ * internal structure for compatibility with other hooks.
7
+ *
8
+ * @example
9
+ * import { storageContract } from './storage.contract.js';
10
+ *
11
+ * // Enforce contract on a storage facet
12
+ * storageContract.enforce(ctx, api, subsystem, storageFacet);
13
+ */
14
+ import { createFacetContract } from '../facet-contract.js';
15
+
16
+ /**
17
+ * Storage Facet Contract
18
+ *
19
+ * Required methods:
20
+ * - get: Retrieve a value by key
21
+ * - set: Store a value by key
22
+ * - delete: Delete a value by key
23
+ * - has: Check if a key exists
24
+ * - getMany: Retrieve multiple values by keys
25
+ * - setMany: Store multiple key-value pairs
26
+ * - deleteMany: Delete multiple keys
27
+ * - list: List all keys (or keys matching pattern)
28
+ * - query: Query values by filter criteria
29
+ * - count: Count keys/entries
30
+ * - createNamespace: Create a new namespace/collection
31
+ * - deleteNamespace: Delete a namespace/collection
32
+ * - listNamespaces: List all namespaces
33
+ * - beginTransaction: Begin a transaction (optional)
34
+ * - commit: Commit a transaction (optional)
35
+ * - rollback: Rollback a transaction (optional)
36
+ * - getMetadata: Get metadata for a key
37
+ * - setMetadata: Set metadata for a key
38
+ * - clear: Clear all data (or data in namespace)
39
+ * - getStatus: Get storage status/health
40
+ *
41
+ * Required properties:
42
+ * - _storageBackend: Internal storage backend instance
43
+ * - _config: Storage configuration
44
+ *
45
+ * Optional properties:
46
+ * - supportsTransactions: Whether backend supports transactions
47
+ * - supportsQuery: Whether backend supports query operations
48
+ * - supportsMetadata: Whether backend supports metadata
49
+ *
50
+ * Custom validation:
51
+ * - Validates _storageBackend is an object (not null or primitive)
52
+ * - Validates _config is an object
53
+ */
54
+ export const storageContract = createFacetContract({
55
+ name: 'storage',
56
+ requiredMethods: [
57
+ 'get',
58
+ 'set',
59
+ 'delete',
60
+ 'has',
61
+ 'getMany',
62
+ 'setMany',
63
+ 'deleteMany',
64
+ 'list',
65
+ 'query',
66
+ 'count',
67
+ 'createNamespace',
68
+ 'deleteNamespace',
69
+ 'listNamespaces',
70
+ 'getMetadata',
71
+ 'setMetadata',
72
+ 'clear',
73
+ 'getStatus'
74
+ ],
75
+ requiredProperties: [
76
+ '_storageBackend',
77
+ '_config'
78
+ ],
79
+ validate: (ctx, api, subsystem, facet) => {
80
+ // Validate that _storageBackend is an object (not null or primitive)
81
+ if (typeof facet._storageBackend !== 'object' || facet._storageBackend === null) {
82
+ throw new Error('Storage facet _storageBackend must be an object');
83
+ }
84
+
85
+ // Validate _config is an object
86
+ if (typeof facet._config !== 'object' || facet._config === null) {
87
+ throw new Error('Storage facet _config must be an object');
88
+ }
89
+
90
+ // Validate optional properties have correct types if present
91
+ if ('supportsTransactions' in facet && typeof facet.supportsTransactions !== 'boolean') {
92
+ throw new Error('Storage facet supportsTransactions must be a boolean');
93
+ }
94
+
95
+ if ('supportsQuery' in facet && typeof facet.supportsQuery !== 'boolean') {
96
+ throw new Error('Storage facet supportsQuery must be a boolean');
97
+ }
98
+
99
+ if ('supportsMetadata' in facet && typeof facet.supportsMetadata !== 'boolean') {
100
+ throw new Error('Storage facet supportsMetadata must be a boolean');
101
+ }
102
+ }
103
+ });
104
+
105
+
106
+
107
+
@@ -0,0 +1,90 @@
1
+ /**
2
+ * WebSocket Facet Contract
3
+ *
4
+ * Defines the contract that WebSocket facets must satisfy.
5
+ * Ensures all required WebSocket server methods are implemented and validates
6
+ * internal structure for compatibility with different WebSocket implementations (ws, uWebSockets.js).
7
+ *
8
+ * @example
9
+ * import { websocketContract } from './websocket.contract.js';
10
+ *
11
+ * // Enforce contract on a WebSocket facet
12
+ * websocketContract.enforce(ctx, api, subsystem, websocketFacet);
13
+ */
14
+ import { createFacetContract } from '../facet-contract.js';
15
+
16
+ /**
17
+ * WebSocket Facet Contract
18
+ *
19
+ * Required methods:
20
+ * - Lifecycle: start, stop, isRunning
21
+ * - Server Info: getAddress, getPort
22
+ * - Connection Management: getConnection, getAllConnections, getConnectionCount, closeConnection
23
+ * - Message Sending: send, broadcast
24
+ * - Connection Lifecycle Handlers: onConnection, onDisconnection, onError
25
+ * - Message Routing: registerMessageHandler, routeMessage
26
+ *
27
+ * Required properties:
28
+ * - _server: Internal WebSocket server instance
29
+ * - _isRunning: Running state flag
30
+ * - _connections: Connection manager/registry
31
+ *
32
+ * Custom validation:
33
+ * - Validates _server is an object (not null or primitive)
34
+ * - Validates _isRunning is a boolean
35
+ * - Validates _connections exists
36
+ */
37
+ export const websocketContract = createFacetContract({
38
+ name: 'websocket',
39
+ requiredMethods: [
40
+ // Lifecycle
41
+ 'start',
42
+ 'stop',
43
+ 'isRunning',
44
+
45
+ // Server Info
46
+ 'getAddress',
47
+ 'getPort',
48
+
49
+ // Connection Management
50
+ 'getConnection',
51
+ 'getAllConnections',
52
+ 'getConnectionCount',
53
+ 'closeConnection',
54
+
55
+ // Message Sending
56
+ 'send',
57
+ 'broadcast',
58
+
59
+ // Connection Lifecycle Handlers
60
+ 'onConnection',
61
+ 'onDisconnection',
62
+ 'onError',
63
+
64
+ // Message Routing
65
+ 'registerMessageHandler',
66
+ 'routeMessage'
67
+ ],
68
+ requiredProperties: [
69
+ '_server', // Internal WebSocket server instance
70
+ '_isRunning', // Running state flag
71
+ '_connections' // Connection manager/registry
72
+ ],
73
+ validate: (ctx, api, subsystem, facet) => {
74
+ // Validate _server is an object
75
+ if (typeof facet._server !== 'object' || facet._server === null) {
76
+ throw new Error('WebSocket facet _server must be an object');
77
+ }
78
+
79
+ // Validate _isRunning is a boolean
80
+ if (typeof facet._isRunning !== 'boolean') {
81
+ throw new Error('WebSocket facet _isRunning must be a boolean');
82
+ }
83
+
84
+ // Validate _connections exists (could be Map, object, or manager instance)
85
+ if (!facet._connections) {
86
+ throw new Error('WebSocket facet _connections must be defined');
87
+ }
88
+ }
89
+ });
90
+
@@ -0,0 +1,155 @@
1
+ /**
2
+ * FacetContractRegistry Class
3
+ *
4
+ * Manages a collection of facet contracts, allowing registration and enforcement
5
+ * of contracts on facets by name.
6
+ *
7
+ * @example
8
+ * import { FacetContractRegistry } from './facet-contract-registry.js';
9
+ * import { createFacetContract } from './facet-contract.js';
10
+ *
11
+ * const registry = new FacetContractRegistry();
12
+ *
13
+ * const routerContract = createFacetContract({
14
+ * name: 'router',
15
+ * requiredMethods: ['registerRoute', 'match']
16
+ * });
17
+ *
18
+ * registry.register(routerContract);
19
+ *
20
+ * // Later, enforce the contract
21
+ * registry.enforce('router', ctx, api, subsystem, routerFacet);
22
+ */
23
+ import { FacetContract } from './facet-contract.js';
24
+
25
+ export class FacetContractRegistry {
26
+ /**
27
+ * Map of contract name → FacetContract instance
28
+ * @private
29
+ * @type {Map<string, FacetContract>}
30
+ */
31
+ #contracts = new Map();
32
+
33
+ /**
34
+ * Creates a new FacetContractRegistry
35
+ */
36
+ constructor() {
37
+ // No initialization needed
38
+ }
39
+
40
+ /**
41
+ * Registers a facet contract in the registry
42
+ *
43
+ * @param {FacetContract} contract - FacetContract instance to register
44
+ * @returns {FacetContract} The registered contract
45
+ * @throws {Error} If contract is invalid or a contract with the same name already exists
46
+ */
47
+ register(contract) {
48
+ if (!contract || typeof contract !== 'object') {
49
+ throw new Error('FacetContractRegistry.register: contract must be an object');
50
+ }
51
+ if (!(contract instanceof FacetContract)) {
52
+ throw new Error('FacetContractRegistry.register: contract must be a FacetContract instance');
53
+ }
54
+ if (!contract.name || typeof contract.name !== 'string') {
55
+ throw new Error('FacetContractRegistry.register: contract must have a string name property');
56
+ }
57
+
58
+ if (this.#contracts.has(contract.name)) {
59
+ throw new Error(`FacetContractRegistry.register: contract with name '${contract.name}' already exists`);
60
+ }
61
+
62
+ this.#contracts.set(contract.name, contract);
63
+ return contract;
64
+ }
65
+
66
+ /**
67
+ * Checks if a contract exists for the given name
68
+ *
69
+ * @param {string} name - Contract name to check
70
+ * @returns {boolean} True if contract exists
71
+ */
72
+ has(name) {
73
+ if (typeof name !== 'string') {
74
+ return false;
75
+ }
76
+ return this.#contracts.has(name);
77
+ }
78
+
79
+ /**
80
+ * Gets a contract by name
81
+ *
82
+ * @param {string} name - Contract name
83
+ * @returns {FacetContract|undefined} Contract instance or undefined if not found
84
+ */
85
+ get(name) {
86
+ if (typeof name !== 'string') {
87
+ return undefined;
88
+ }
89
+ return this.#contracts.get(name);
90
+ }
91
+
92
+ /**
93
+ * Enforces a contract on a facet
94
+ *
95
+ * Looks up the contract by name and delegates to its enforce method.
96
+ *
97
+ * @param {string} name - Name of the contract to enforce
98
+ * @param {Object} ctx - Context object
99
+ * @param {Object} api - Subsystem API object
100
+ * @param {BaseSubsystem} subsystem - Subsystem instance
101
+ * @param {Facet} facet - Facet to validate
102
+ * @throws {Error} If contract not found or validation fails
103
+ */
104
+ enforce(name, ctx, api, subsystem, facet) {
105
+ if (typeof name !== 'string' || !name) {
106
+ throw new Error('FacetContractRegistry.enforce: name must be a non-empty string');
107
+ }
108
+
109
+ const contract = this.#contracts.get(name);
110
+ if (!contract) {
111
+ throw new Error(`FacetContractRegistry.enforce: no contract found for name '${name}'`);
112
+ }
113
+
114
+ contract.enforce(ctx, api, subsystem, facet);
115
+ }
116
+
117
+ /**
118
+ * Removes a contract from the registry
119
+ *
120
+ * @param {string} name - Contract name to remove
121
+ * @returns {boolean} True if contract was removed, false if not found
122
+ */
123
+ remove(name) {
124
+ if (typeof name !== 'string') {
125
+ return false;
126
+ }
127
+ return this.#contracts.delete(name);
128
+ }
129
+
130
+ /**
131
+ * Lists all registered contract names
132
+ *
133
+ * @returns {Array<string>} Array of contract names
134
+ */
135
+ list() {
136
+ return Array.from(this.#contracts.keys());
137
+ }
138
+
139
+ /**
140
+ * Gets the number of registered contracts
141
+ *
142
+ * @returns {number} Number of contracts
143
+ */
144
+ size() {
145
+ return this.#contracts.size;
146
+ }
147
+
148
+ /**
149
+ * Clears all contracts from the registry
150
+ */
151
+ clear() {
152
+ this.#contracts.clear();
153
+ }
154
+ }
155
+
@@ -0,0 +1,136 @@
1
+ /**
2
+ * FacetContract Class
3
+ *
4
+ * Defines a contract that facets must satisfy, including required methods,
5
+ * required properties, and optional custom validation logic.
6
+ *
7
+ * @example
8
+ * const routerContract = new FacetContract('router', {
9
+ * requiredMethods: ['registerRoute', 'match'],
10
+ * requiredProperties: ['_routeRegistry']
11
+ * }, (ctx, api, subsystem, facet) => {
12
+ * // Additional custom validation
13
+ * });
14
+ *
15
+ * routerContract.enforce(ctx, api, subsystem, routerFacet);
16
+ */
17
+ export class FacetContract {
18
+ #validate = null;
19
+
20
+ /**
21
+ * Create a new FacetContract
22
+ *
23
+ * @param {string} name - Name of the contract (usually same as facet kind)
24
+ * @param {Object} requirements - Requirements object
25
+ * @param {Array<string>} [requirements.requiredMethods=[]] - Array of required method names that must be implemented
26
+ * @param {Array<string>} [requirements.requiredProperties=[]] - Array of required property names that must exist
27
+ * @param {Function} [validate] - Optional validation function with signature (ctx, api, subsystem, facet)
28
+ */
29
+ constructor(name, requirements = {}, validate = null) {
30
+ if (!name || typeof name !== 'string') {
31
+ throw new Error('FacetContract: name must be a non-empty string');
32
+ }
33
+ if (!requirements || typeof requirements !== 'object' || Array.isArray(requirements)) {
34
+ throw new Error('FacetContract: requirements must be an object');
35
+ }
36
+ if (validate !== null && typeof validate !== 'function') {
37
+ throw new Error('FacetContract: validate must be a function or null');
38
+ }
39
+
40
+ this.name = name;
41
+ this.requiredMethods = Array.isArray(requirements.requiredMethods)
42
+ ? [...requirements.requiredMethods]
43
+ : [];
44
+ this.requiredProperties = Array.isArray(requirements.requiredProperties)
45
+ ? [...requirements.requiredProperties]
46
+ : [];
47
+ this.#validate = validate;
48
+ }
49
+
50
+ /**
51
+ * Enforce the contract on a facet
52
+ *
53
+ * Checks that all required methods and properties exist on the facet,
54
+ * then runs the custom validation function if provided.
55
+ *
56
+ * @param {Object} ctx - Context object
57
+ * @param {Object} api - Subsystem API object
58
+ * @param {BaseSubsystem} subsystem - Subsystem instance
59
+ * @param {Facet} facet - Facet to validate
60
+ * @throws {Error} If required methods or properties are missing or validation fails
61
+ */
62
+ enforce(ctx, api, subsystem, facet) {
63
+ if (!facet || typeof facet !== 'object') {
64
+ throw new Error(`FacetContract '${this.name}': facet must be an object`);
65
+ }
66
+
67
+ // Check that all required methods are implemented
68
+ const missingMethods = [];
69
+ for (const methodName of this.requiredMethods) {
70
+ if (typeof facet[methodName] !== 'function') {
71
+ missingMethods.push(methodName);
72
+ }
73
+ }
74
+
75
+ if (missingMethods.length > 0) {
76
+ throw new Error(
77
+ `FacetContract '${this.name}': facet is missing required methods: ${missingMethods.join(', ')}`
78
+ );
79
+ }
80
+
81
+ // Check that all required properties exist
82
+ const missingProperties = [];
83
+ for (const propertyName of this.requiredProperties) {
84
+ if (!(propertyName in facet) || facet[propertyName] === undefined) {
85
+ missingProperties.push(propertyName);
86
+ }
87
+ }
88
+
89
+ if (missingProperties.length > 0) {
90
+ throw new Error(
91
+ `FacetContract '${this.name}': facet is missing required properties: ${missingProperties.join(', ')}`
92
+ );
93
+ }
94
+
95
+ // Run custom validation if provided
96
+ if (this.#validate !== null) {
97
+ try {
98
+ this.#validate(ctx, api, subsystem, facet);
99
+ } catch (error) {
100
+ throw new Error(
101
+ `FacetContract '${this.name}': validation failed: ${error.message}`
102
+ );
103
+ }
104
+ }
105
+ }
106
+ }
107
+
108
+ /**
109
+ * FacetContract Factory Function
110
+ *
111
+ * Creates a FacetContract instance with validation and error handling.
112
+ *
113
+ * @param {Object} options - Contract configuration
114
+ * @param {string} options.name - Name of the contract (usually same as facet kind)
115
+ * @param {Array<string>} [options.requiredMethods=[]] - Array of required method names that must be implemented
116
+ * @param {Array<string>} [options.requiredProperties=[]] - Array of required property names that must exist
117
+ * @param {Function} [options.validate] - Optional validation function with signature (ctx, api, subsystem, facet)
118
+ * @returns {FacetContract} New FacetContract instance
119
+ *
120
+ * @example
121
+ * const routerContract = createFacetContract({
122
+ * name: 'router',
123
+ * requiredMethods: ['registerRoute', 'match', 'route'],
124
+ * requiredProperties: ['_routeRegistry'],
125
+ * validate: (ctx, api, subsystem, facet) => {
126
+ * // Additional custom validation
127
+ * if (typeof facet._routeRegistry !== 'object') {
128
+ * throw new Error('Router facet _routeRegistry must be an object');
129
+ * }
130
+ * }
131
+ * });
132
+ */
133
+ export function createFacetContract({ name, requiredMethods = [], requiredProperties = [], validate = null }) {
134
+ return new FacetContract(name, { requiredMethods, requiredProperties }, validate);
135
+ }
136
+
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Facet Contract Registry Index
3
+ *
4
+ * Creates a default FacetContractRegistry instance and registers all available
5
+ * facet contracts. This provides a centralized registry for enforcing contracts
6
+ * on facets throughout the system.
7
+ *
8
+ * @example
9
+ * import { defaultContractRegistry } from './index.js';
10
+ *
11
+ * // Enforce a contract on a facet
12
+ * defaultContractRegistry.enforce('router', ctx, api, subsystem, routerFacet);
13
+ *
14
+ * // Check if a contract exists
15
+ * if (defaultContractRegistry.has('queue')) {
16
+ * // Contract is available
17
+ * }
18
+ */
19
+ import { FacetContractRegistry } from './facet-contract-registry.js';
20
+ import { routerContract } from './contracts/router.contract.js';
21
+ import { queueContract } from './contracts/queue.contract.js';
22
+ import { processorContract } from './contracts/processor.contract.js';
23
+ import { listenersContract } from './contracts/listeners.contract.js';
24
+ import { hierarchyContract } from './contracts/hierarchy.contract.js';
25
+ import { schedulerContract } from './contracts/scheduler.contract.js';
26
+ import { serverContract } from './contracts/server.contract.js';
27
+ import { speakContract } from './contracts/speak.contract.js';
28
+ import { websocketContract } from './contracts/websocket.contract.js';
29
+ import { storageContract } from './contracts/storage.contract.js';
30
+
31
+ /**
32
+ * Default Facet Contract Registry
33
+ *
34
+ * Pre-configured registry with all standard facet contracts registered.
35
+ */
36
+ export const defaultContractRegistry = new FacetContractRegistry();
37
+
38
+ // Register all available contracts
39
+ defaultContractRegistry.register(routerContract);
40
+ defaultContractRegistry.register(queueContract);
41
+ defaultContractRegistry.register(processorContract);
42
+ defaultContractRegistry.register(listenersContract);
43
+ defaultContractRegistry.register(hierarchyContract);
44
+ defaultContractRegistry.register(schedulerContract);
45
+ defaultContractRegistry.register(serverContract);
46
+ defaultContractRegistry.register(speakContract);
47
+ defaultContractRegistry.register(websocketContract);
48
+ defaultContractRegistry.register(storageContract);
49
+
50
+ // Also export the registry class and individual contracts for flexibility
51
+ export { FacetContractRegistry } from './facet-contract-registry.js';
52
+ export { FacetContract, createFacetContract } from './facet-contract.js';
53
+ export { routerContract } from './contracts/router.contract.js';
54
+ export { queueContract } from './contracts/queue.contract.js';
55
+ export { processorContract } from './contracts/processor.contract.js';
56
+ export { listenersContract } from './contracts/listeners.contract.js';
57
+ export { hierarchyContract } from './contracts/hierarchy.contract.js';
58
+ export { schedulerContract } from './contracts/scheduler.contract.js';
59
+ export { serverContract } from './contracts/server.contract.js';
60
+ export { speakContract } from './contracts/speak.contract.js';
61
+ export { websocketContract } from './contracts/websocket.contract.js';
62
+ export { storageContract } from './contracts/storage.contract.js';
63
+