threadforge 0.1.1 → 0.2.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 +52 -20
- package/bin/forge.js +2 -1058
- package/bin/host-commands.d.ts +2 -0
- package/bin/host-commands.d.ts.map +1 -0
- package/bin/host-commands.js +7 -8
- package/bin/platform-commands.d.ts +2 -0
- package/bin/platform-commands.d.ts.map +1 -0
- package/bin/platform-commands.js +118 -36
- package/dist/cli/base-command.d.ts +12 -0
- package/dist/cli/base-command.d.ts.map +1 -0
- package/dist/cli/base-command.js +25 -0
- package/dist/cli/base-command.js.map +1 -0
- package/dist/cli/commands/build.d.ts +10 -0
- package/dist/cli/commands/build.d.ts.map +1 -0
- package/dist/cli/commands/build.js +110 -0
- package/dist/cli/commands/build.js.map +1 -0
- package/dist/cli/commands/deploy.d.ts +12 -0
- package/dist/cli/commands/deploy.d.ts.map +1 -0
- package/dist/cli/commands/deploy.js +143 -0
- package/dist/cli/commands/deploy.js.map +1 -0
- package/dist/cli/commands/dev.d.ts +10 -0
- package/dist/cli/commands/dev.d.ts.map +1 -0
- package/dist/cli/commands/dev.js +138 -0
- package/dist/cli/commands/dev.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +10 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +76 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/host.d.ts +8 -0
- package/dist/cli/commands/host.d.ts.map +1 -0
- package/dist/cli/commands/host.js +20 -0
- package/dist/cli/commands/host.js.map +1 -0
- package/dist/cli/commands/init.d.ts +16 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +246 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/platform.d.ts +8 -0
- package/dist/cli/commands/platform.d.ts.map +1 -0
- package/dist/cli/commands/platform.js +20 -0
- package/dist/cli/commands/platform.js.map +1 -0
- package/dist/cli/commands/restart.d.ts +8 -0
- package/dist/cli/commands/restart.d.ts.map +1 -0
- package/dist/cli/commands/restart.js +13 -0
- package/dist/cli/commands/restart.js.map +1 -0
- package/dist/cli/commands/scaffold/frontend.d.ts +10 -0
- package/dist/cli/commands/scaffold/frontend.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/frontend.js +130 -0
- package/dist/cli/commands/scaffold/frontend.js.map +1 -0
- package/dist/cli/commands/scaffold/react.d.ts +7 -0
- package/dist/cli/commands/scaffold/react.d.ts.map +1 -0
- package/dist/cli/commands/scaffold/react.js +12 -0
- package/dist/cli/commands/scaffold/react.js.map +1 -0
- package/dist/cli/commands/scale.d.ts +8 -0
- package/dist/cli/commands/scale.d.ts.map +1 -0
- package/dist/cli/commands/scale.js +13 -0
- package/dist/cli/commands/scale.js.map +1 -0
- package/dist/cli/commands/start.d.ts +10 -0
- package/dist/cli/commands/start.d.ts.map +1 -0
- package/dist/cli/commands/start.js +71 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/commands/status.d.ts +11 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +60 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/stop.d.ts +10 -0
- package/dist/cli/commands/stop.d.ts.map +1 -0
- package/dist/cli/commands/stop.js +89 -0
- package/dist/cli/commands/stop.js.map +1 -0
- package/dist/cli/util/config-discovery.d.ts +8 -0
- package/dist/cli/util/config-discovery.d.ts.map +1 -0
- package/dist/cli/util/config-discovery.js +70 -0
- package/dist/cli/util/config-discovery.js.map +1 -0
- package/dist/cli/util/config-patcher.d.ts +17 -0
- package/dist/cli/util/config-patcher.d.ts.map +1 -0
- package/dist/cli/util/config-patcher.js +439 -0
- package/dist/cli/util/config-patcher.js.map +1 -0
- package/dist/cli/util/frontend-dev.d.ts +8 -0
- package/dist/cli/util/frontend-dev.d.ts.map +1 -0
- package/dist/cli/util/frontend-dev.js +117 -0
- package/dist/cli/util/frontend-dev.js.map +1 -0
- package/dist/cli/util/process.d.ts +5 -0
- package/dist/cli/util/process.d.ts.map +1 -0
- package/dist/cli/util/process.js +17 -0
- package/dist/cli/util/process.js.map +1 -0
- package/dist/cli/util/templates.d.ts +10 -0
- package/dist/cli/util/templates.d.ts.map +1 -0
- package/dist/cli/util/templates.js +157 -0
- package/dist/cli/util/templates.js.map +1 -0
- package/dist/core/AlertSink.d.ts +83 -0
- package/dist/core/AlertSink.d.ts.map +1 -0
- package/dist/core/AlertSink.js +126 -0
- package/dist/core/AlertSink.js.map +1 -0
- package/dist/core/DirectMessageBus.d.ts +88 -0
- package/dist/core/DirectMessageBus.d.ts.map +1 -0
- package/dist/core/DirectMessageBus.js +352 -0
- package/dist/core/DirectMessageBus.js.map +1 -0
- package/dist/core/EndpointResolver.d.ts +111 -0
- package/dist/core/EndpointResolver.d.ts.map +1 -0
- package/dist/core/EndpointResolver.js +336 -0
- package/dist/core/EndpointResolver.js.map +1 -0
- package/dist/core/ForgeContext.d.ts +221 -0
- package/dist/core/ForgeContext.d.ts.map +1 -0
- package/dist/core/ForgeContext.js +1169 -0
- package/dist/core/ForgeContext.js.map +1 -0
- package/dist/core/ForgeEndpoints.d.ts +71 -0
- package/dist/core/ForgeEndpoints.d.ts.map +1 -0
- package/dist/core/ForgeEndpoints.js +442 -0
- package/dist/core/ForgeEndpoints.js.map +1 -0
- package/dist/core/ForgeHost.d.ts +82 -0
- package/dist/core/ForgeHost.d.ts.map +1 -0
- package/dist/core/ForgeHost.js +107 -0
- package/dist/core/ForgeHost.js.map +1 -0
- package/dist/core/ForgePlatform.d.ts +96 -0
- package/dist/core/ForgePlatform.d.ts.map +1 -0
- package/dist/core/ForgePlatform.js +136 -0
- package/dist/core/ForgePlatform.js.map +1 -0
- package/dist/core/ForgeWebSocket.d.ts +56 -0
- package/dist/core/ForgeWebSocket.d.ts.map +1 -0
- package/dist/core/ForgeWebSocket.js +415 -0
- package/dist/core/ForgeWebSocket.js.map +1 -0
- package/dist/core/Ingress.d.ts +329 -0
- package/dist/core/Ingress.d.ts.map +1 -0
- package/dist/core/Ingress.js +694 -0
- package/dist/core/Ingress.js.map +1 -0
- package/dist/core/Interceptors.d.ts +134 -0
- package/dist/core/Interceptors.d.ts.map +1 -0
- package/dist/core/Interceptors.js +416 -0
- package/dist/core/Interceptors.js.map +1 -0
- package/dist/core/Logger.d.ts +20 -0
- package/dist/core/Logger.d.ts.map +1 -0
- package/dist/core/Logger.js +77 -0
- package/dist/core/Logger.js.map +1 -0
- package/dist/core/MessageBus.d.ts +15 -0
- package/dist/core/MessageBus.d.ts.map +1 -0
- package/dist/core/MessageBus.js +18 -0
- package/dist/core/MessageBus.js.map +1 -0
- package/dist/core/Prometheus.d.ts +80 -0
- package/dist/core/Prometheus.d.ts.map +1 -0
- package/dist/core/Prometheus.js +332 -0
- package/dist/core/Prometheus.js.map +1 -0
- package/dist/core/RequestContext.d.ts +214 -0
- package/dist/core/RequestContext.d.ts.map +1 -0
- package/dist/core/RequestContext.js +556 -0
- package/dist/core/RequestContext.js.map +1 -0
- package/dist/core/Router.d.ts +45 -0
- package/dist/core/Router.d.ts.map +1 -0
- package/dist/core/Router.js +285 -0
- package/dist/core/Router.js.map +1 -0
- package/dist/core/RoutingStrategy.d.ts +116 -0
- package/dist/core/RoutingStrategy.d.ts.map +1 -0
- package/dist/core/RoutingStrategy.js +306 -0
- package/dist/core/RoutingStrategy.js.map +1 -0
- package/dist/core/RpcConfig.d.ts +72 -0
- package/dist/core/RpcConfig.d.ts.map +1 -0
- package/dist/core/RpcConfig.js +127 -0
- package/dist/core/RpcConfig.js.map +1 -0
- package/dist/core/SignatureCache.d.ts +81 -0
- package/dist/core/SignatureCache.d.ts.map +1 -0
- package/dist/core/SignatureCache.js +172 -0
- package/dist/core/SignatureCache.js.map +1 -0
- package/dist/core/StaticFileServer.d.ts +34 -0
- package/dist/core/StaticFileServer.d.ts.map +1 -0
- package/dist/core/StaticFileServer.js +497 -0
- package/dist/core/StaticFileServer.js.map +1 -0
- package/dist/core/Supervisor.d.ts +198 -0
- package/dist/core/Supervisor.d.ts.map +1 -0
- package/dist/core/Supervisor.js +1418 -0
- package/dist/core/Supervisor.js.map +1 -0
- package/dist/core/ThreadAllocator.d.ts +52 -0
- package/dist/core/ThreadAllocator.d.ts.map +1 -0
- package/dist/core/ThreadAllocator.js +174 -0
- package/dist/core/ThreadAllocator.js.map +1 -0
- package/dist/core/WorkerChannelManager.d.ts +130 -0
- package/dist/core/WorkerChannelManager.d.ts.map +1 -0
- package/dist/core/WorkerChannelManager.js +956 -0
- package/dist/core/WorkerChannelManager.js.map +1 -0
- package/dist/core/config-enums.d.ts +41 -0
- package/dist/core/config-enums.d.ts.map +1 -0
- package/dist/core/config-enums.js +59 -0
- package/dist/core/config-enums.js.map +1 -0
- package/dist/core/config.d.ts +159 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +694 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/host-config.d.ts +146 -0
- package/dist/core/host-config.d.ts.map +1 -0
- package/dist/core/host-config.js +312 -0
- package/dist/core/host-config.js.map +1 -0
- package/dist/core/ipc-errors.d.ts +27 -0
- package/dist/core/ipc-errors.d.ts.map +1 -0
- package/dist/core/ipc-errors.js +36 -0
- package/dist/core/ipc-errors.js.map +1 -0
- package/dist/core/network-utils.d.ts +35 -0
- package/dist/core/network-utils.d.ts.map +1 -0
- package/dist/core/network-utils.js +145 -0
- package/dist/core/network-utils.js.map +1 -0
- package/dist/core/platform-config.d.ts +142 -0
- package/dist/core/platform-config.d.ts.map +1 -0
- package/dist/core/platform-config.js +299 -0
- package/dist/core/platform-config.js.map +1 -0
- package/dist/decorators/ServiceProxy.d.ts +175 -0
- package/dist/decorators/ServiceProxy.d.ts.map +1 -0
- package/dist/decorators/ServiceProxy.js +969 -0
- package/dist/decorators/ServiceProxy.js.map +1 -0
- package/dist/decorators/index.d.ts +146 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/dist/decorators/index.js +545 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/deploy/NginxGenerator.d.ts +165 -0
- package/dist/deploy/NginxGenerator.d.ts.map +1 -0
- package/dist/deploy/NginxGenerator.js +781 -0
- package/dist/deploy/NginxGenerator.js.map +1 -0
- package/dist/deploy/PlatformManifestGenerator.d.ts +43 -0
- package/dist/deploy/PlatformManifestGenerator.d.ts.map +1 -0
- package/dist/deploy/PlatformManifestGenerator.js +80 -0
- package/dist/deploy/PlatformManifestGenerator.js.map +1 -0
- package/dist/deploy/RouteManifestGenerator.d.ts +42 -0
- package/dist/deploy/RouteManifestGenerator.d.ts.map +1 -0
- package/dist/deploy/RouteManifestGenerator.js +105 -0
- package/dist/deploy/RouteManifestGenerator.js.map +1 -0
- package/dist/deploy/index.d.ts +210 -0
- package/dist/deploy/index.d.ts.map +1 -0
- package/dist/deploy/index.js +918 -0
- package/dist/deploy/index.js.map +1 -0
- package/dist/frontend/FrontendDevLifecycle.d.ts +26 -0
- package/dist/frontend/FrontendDevLifecycle.d.ts.map +1 -0
- package/dist/frontend/FrontendDevLifecycle.js +60 -0
- package/dist/frontend/FrontendDevLifecycle.js.map +1 -0
- package/dist/frontend/FrontendPluginOrchestrator.d.ts +64 -0
- package/dist/frontend/FrontendPluginOrchestrator.d.ts.map +1 -0
- package/dist/frontend/FrontendPluginOrchestrator.js +167 -0
- package/dist/frontend/FrontendPluginOrchestrator.js.map +1 -0
- package/dist/frontend/SiteResolver.d.ts +33 -0
- package/dist/frontend/SiteResolver.d.ts.map +1 -0
- package/dist/frontend/SiteResolver.js +53 -0
- package/dist/frontend/SiteResolver.js.map +1 -0
- package/dist/frontend/StaticMountRegistry.d.ts +36 -0
- package/dist/frontend/StaticMountRegistry.d.ts.map +1 -0
- package/dist/frontend/StaticMountRegistry.js +94 -0
- package/dist/frontend/StaticMountRegistry.js.map +1 -0
- package/dist/frontend/index.d.ts +7 -0
- package/dist/frontend/index.d.ts.map +1 -0
- package/{src → dist}/frontend/index.js +4 -2
- package/dist/frontend/index.js.map +1 -0
- package/dist/frontend/pathUtils.d.ts +8 -0
- package/dist/frontend/pathUtils.d.ts.map +1 -0
- package/dist/frontend/pathUtils.js +17 -0
- package/dist/frontend/pathUtils.js.map +1 -0
- package/dist/frontend/plugins/index.d.ts +2 -0
- package/dist/frontend/plugins/index.d.ts.map +1 -0
- package/{src → dist}/frontend/plugins/index.js +1 -1
- package/dist/frontend/plugins/index.js.map +1 -0
- package/dist/frontend/plugins/viteFrontend.d.ts +51 -0
- package/dist/frontend/plugins/viteFrontend.d.ts.map +1 -0
- package/dist/frontend/plugins/viteFrontend.js +134 -0
- package/dist/frontend/plugins/viteFrontend.js.map +1 -0
- package/dist/frontend/types.d.ts +25 -0
- package/dist/frontend/types.d.ts.map +1 -0
- package/dist/frontend/types.js +2 -0
- package/dist/frontend/types.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/internals.d.ts +21 -0
- package/dist/internals.d.ts.map +1 -0
- package/{src → dist}/internals.js +12 -14
- package/dist/internals.js.map +1 -0
- package/dist/plugins/PluginManager.d.ts +209 -0
- package/dist/plugins/PluginManager.d.ts.map +1 -0
- package/dist/plugins/PluginManager.js +365 -0
- package/dist/plugins/PluginManager.js.map +1 -0
- package/dist/plugins/ScopedPostgres.d.ts +78 -0
- package/dist/plugins/ScopedPostgres.d.ts.map +1 -0
- package/dist/plugins/ScopedPostgres.js +190 -0
- package/dist/plugins/ScopedPostgres.js.map +1 -0
- package/dist/plugins/ScopedRedis.d.ts +88 -0
- package/dist/plugins/ScopedRedis.d.ts.map +1 -0
- package/dist/plugins/ScopedRedis.js +169 -0
- package/dist/plugins/ScopedRedis.js.map +1 -0
- package/dist/plugins/index.d.ts +289 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +1942 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/types.d.ts +59 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/types.js +2 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/registry/ServiceRegistry.d.ts +305 -0
- package/dist/registry/ServiceRegistry.d.ts.map +1 -0
- package/dist/registry/ServiceRegistry.js +735 -0
- package/dist/registry/ServiceRegistry.js.map +1 -0
- package/dist/scaling/ScaleAdvisor.d.ts +214 -0
- package/dist/scaling/ScaleAdvisor.d.ts.map +1 -0
- package/dist/scaling/ScaleAdvisor.js +526 -0
- package/dist/scaling/ScaleAdvisor.js.map +1 -0
- package/dist/services/Service.d.ts +164 -0
- package/dist/services/Service.d.ts.map +1 -0
- package/dist/services/Service.js +106 -0
- package/dist/services/Service.js.map +1 -0
- package/dist/services/worker-bootstrap.d.ts +15 -0
- package/dist/services/worker-bootstrap.d.ts.map +1 -0
- package/dist/services/worker-bootstrap.js +744 -0
- package/dist/services/worker-bootstrap.js.map +1 -0
- package/dist/templates/auth-service.d.ts +42 -0
- package/dist/templates/auth-service.d.ts.map +1 -0
- package/dist/templates/auth-service.js +54 -0
- package/dist/templates/auth-service.js.map +1 -0
- package/dist/templates/identity-service.d.ts +50 -0
- package/dist/templates/identity-service.d.ts.map +1 -0
- package/dist/templates/identity-service.js +62 -0
- package/dist/templates/identity-service.js.map +1 -0
- package/dist/types/contract.d.ts +120 -0
- package/dist/types/contract.d.ts.map +1 -0
- package/dist/types/contract.js +69 -0
- package/dist/types/contract.js.map +1 -0
- package/package.json +78 -20
- package/src/core/DirectMessageBus.js +0 -364
- package/src/core/EndpointResolver.js +0 -259
- package/src/core/ForgeContext.js +0 -2236
- package/src/core/ForgeHost.js +0 -122
- package/src/core/ForgePlatform.js +0 -145
- package/src/core/Ingress.js +0 -768
- package/src/core/Interceptors.js +0 -420
- package/src/core/MessageBus.js +0 -321
- package/src/core/Prometheus.js +0 -305
- package/src/core/RequestContext.js +0 -413
- package/src/core/RoutingStrategy.js +0 -330
- package/src/core/Supervisor.js +0 -1349
- package/src/core/ThreadAllocator.js +0 -196
- package/src/core/WorkerChannelManager.js +0 -879
- package/src/core/config.js +0 -637
- package/src/core/host-config.js +0 -311
- package/src/core/network-utils.js +0 -166
- package/src/core/platform-config.js +0 -308
- package/src/decorators/ServiceProxy.js +0 -904
- package/src/decorators/index.js +0 -571
- package/src/deploy/NginxGenerator.js +0 -865
- package/src/deploy/PlatformManifestGenerator.js +0 -96
- package/src/deploy/RouteManifestGenerator.js +0 -112
- package/src/deploy/index.js +0 -984
- package/src/frontend/FrontendDevLifecycle.js +0 -65
- package/src/frontend/FrontendPluginOrchestrator.js +0 -187
- package/src/frontend/SiteResolver.js +0 -63
- package/src/frontend/StaticMountRegistry.js +0 -90
- package/src/frontend/plugins/viteFrontend.js +0 -79
- package/src/frontend/types.js +0 -35
- package/src/index.js +0 -58
- package/src/plugins/PluginManager.js +0 -537
- package/src/plugins/ScopedPostgres.js +0 -192
- package/src/plugins/ScopedRedis.js +0 -142
- package/src/plugins/index.js +0 -1756
- package/src/registry/ServiceRegistry.js +0 -797
- package/src/scaling/ScaleAdvisor.js +0 -442
- package/src/services/Service.js +0 -195
- package/src/services/worker-bootstrap.js +0 -679
- package/src/templates/auth-service.js +0 -65
- package/src/templates/identity-service.js +0 -75
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template builders for init and scaffold commands.
|
|
3
|
+
*/
|
|
4
|
+
export function buildDefaultInitConfig(configImportPath, mode = "none") {
|
|
5
|
+
const importClause = mode === "react" ? "defineServices, ServiceType, viteFrontend" : "defineServices, ServiceType";
|
|
6
|
+
const baseConfig = `import { ${importClause} } from '${configImportPath}';
|
|
7
|
+
|
|
8
|
+
export default defineServices({
|
|
9
|
+
api: {
|
|
10
|
+
entry: './services/api.js',
|
|
11
|
+
type: ServiceType.EDGE,
|
|
12
|
+
port: 3000,
|
|
13
|
+
threads: 'auto',
|
|
14
|
+
// connects: ['otherService'], // add services this one calls
|
|
15
|
+
},
|
|
16
|
+
}`;
|
|
17
|
+
if (mode === "none") {
|
|
18
|
+
return `${baseConfig});
|
|
19
|
+
`;
|
|
20
|
+
}
|
|
21
|
+
if (mode === "static") {
|
|
22
|
+
return `${baseConfig}, {
|
|
23
|
+
sites: {
|
|
24
|
+
app: {
|
|
25
|
+
siteId: 'app',
|
|
26
|
+
services: ['api'],
|
|
27
|
+
domains: [],
|
|
28
|
+
frontend: {
|
|
29
|
+
outDir: './public',
|
|
30
|
+
basePath: '/',
|
|
31
|
+
spaFallback: true,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
`;
|
|
37
|
+
}
|
|
38
|
+
return `${baseConfig}, {
|
|
39
|
+
frontendPlugins: [viteFrontend()],
|
|
40
|
+
sites: {
|
|
41
|
+
app: {
|
|
42
|
+
siteId: 'app',
|
|
43
|
+
services: ['api'],
|
|
44
|
+
domains: [],
|
|
45
|
+
frontend: {
|
|
46
|
+
plugin: 'vite',
|
|
47
|
+
root: './web',
|
|
48
|
+
outDir: '.threadforge/build/app',
|
|
49
|
+
basePath: '/',
|
|
50
|
+
spaFallback: true,
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
`;
|
|
56
|
+
}
|
|
57
|
+
export function buildDefaultPublicIndexHtml() {
|
|
58
|
+
return `<!DOCTYPE html>
|
|
59
|
+
<html lang="en">
|
|
60
|
+
<head>
|
|
61
|
+
<meta charset="UTF-8">
|
|
62
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
63
|
+
<title>ThreadForge App</title>
|
|
64
|
+
</head>
|
|
65
|
+
<body>
|
|
66
|
+
<h1>ThreadForge is running!</h1>
|
|
67
|
+
<p>Hello from <span id="name">...</span></p>
|
|
68
|
+
<script>
|
|
69
|
+
fetch('/hello/World').then(r => r.json()).then(d => {
|
|
70
|
+
document.getElementById('name').textContent = d.message;
|
|
71
|
+
});
|
|
72
|
+
</script>
|
|
73
|
+
</body>
|
|
74
|
+
</html>
|
|
75
|
+
`;
|
|
76
|
+
}
|
|
77
|
+
export function buildDefaultReactWebPackageJson() {
|
|
78
|
+
return `${JSON.stringify({
|
|
79
|
+
name: "app-web",
|
|
80
|
+
private: true,
|
|
81
|
+
version: "1.0.0",
|
|
82
|
+
type: "module",
|
|
83
|
+
scripts: {
|
|
84
|
+
build: "vite build",
|
|
85
|
+
dev: "vite",
|
|
86
|
+
},
|
|
87
|
+
dependencies: {
|
|
88
|
+
react: "^18.3.1",
|
|
89
|
+
"react-dom": "^18.3.1",
|
|
90
|
+
},
|
|
91
|
+
devDependencies: {
|
|
92
|
+
vite: "^5.4.10",
|
|
93
|
+
},
|
|
94
|
+
}, null, 2)}\n`;
|
|
95
|
+
}
|
|
96
|
+
export function buildDefaultReactWebIndexHtml() {
|
|
97
|
+
return `<!doctype html>
|
|
98
|
+
<html lang="en">
|
|
99
|
+
<head>
|
|
100
|
+
<meta charset="UTF-8" />
|
|
101
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
102
|
+
<title>ThreadForge React App</title>
|
|
103
|
+
</head>
|
|
104
|
+
<body>
|
|
105
|
+
<div id="root"></div>
|
|
106
|
+
<script type="module" src="/src/main.jsx"></script>
|
|
107
|
+
</body>
|
|
108
|
+
</html>
|
|
109
|
+
`;
|
|
110
|
+
}
|
|
111
|
+
export function buildDefaultReactWebMainJsx() {
|
|
112
|
+
return `import React from 'react';
|
|
113
|
+
import { createRoot } from 'react-dom/client';
|
|
114
|
+
|
|
115
|
+
function App() {
|
|
116
|
+
return <h1>Hello World</h1>;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
createRoot(document.getElementById('root')).render(<App />);
|
|
120
|
+
`;
|
|
121
|
+
}
|
|
122
|
+
export function generateDeployTemplate() {
|
|
123
|
+
return `// forge.deploy.js \u2014 Multi-machine deployment manifest
|
|
124
|
+
// Edit this file with your node addresses, then run: forge deploy
|
|
125
|
+
|
|
126
|
+
export default {
|
|
127
|
+
cluster: 'my-saas',
|
|
128
|
+
|
|
129
|
+
nodes: {
|
|
130
|
+
'web-1': {
|
|
131
|
+
host: '10.0.1.10',
|
|
132
|
+
services: ['gateway'],
|
|
133
|
+
role: 'edge',
|
|
134
|
+
},
|
|
135
|
+
'api-1': {
|
|
136
|
+
host: '10.0.1.20',
|
|
137
|
+
services: ['users'],
|
|
138
|
+
role: 'api',
|
|
139
|
+
},
|
|
140
|
+
'worker-1': {
|
|
141
|
+
host: '10.0.1.30',
|
|
142
|
+
services: ['notifications'],
|
|
143
|
+
role: 'worker',
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
registry: 'multicast',
|
|
148
|
+
httpBasePort: 4000,
|
|
149
|
+
metricsPort: 9090,
|
|
150
|
+
forgeProxy: {
|
|
151
|
+
host: '127.0.0.1',
|
|
152
|
+
port: 8080,
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
`;
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../../src/cli/util/templates.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,sBAAsB,CACpC,gBAAwB,EACxB,OAAoC,MAAM;IAE1C,MAAM,YAAY,GAChB,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,2CAA2C,CAAC,CAAC,CAAC,6BAA6B,CAAC;IACjG,MAAM,UAAU,GAAG,YAAY,YAAY,YAAY,gBAAgB;;;;;;;;;;EAUvE,CAAC;IAED,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,OAAO,GAAG,UAAU;CACvB,CAAC;IACA,CAAC;IAED,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,OAAO,GAAG,UAAU;;;;;;;;;;;;;;CAcvB,CAAC;IACA,CAAC;IAED,OAAO,GAAG,UAAU;;;;;;;;;;;;;;;;;CAiBrB,CAAC;AACF,CAAC;AAED,MAAM,UAAU,2BAA2B;IACzC,OAAO;;;;;;;;;;;;;;;;;CAiBR,CAAC;AACF,CAAC;AAED,MAAM,UAAU,+BAA+B;IAC7C,OAAO,GAAG,IAAI,CAAC,SAAS,CACtB;QACE,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE;YACP,KAAK,EAAE,YAAY;YACnB,GAAG,EAAE,MAAM;SACZ;QACD,YAAY,EAAE;YACZ,KAAK,EAAE,SAAS;YAChB,WAAW,EAAE,SAAS;SACvB;QACD,eAAe,EAAE;YACf,IAAI,EAAE,SAAS;SAChB;KACF,EACD,IAAI,EACJ,CAAC,CACF,IAAI,CAAC;AACR,CAAC;AAED,MAAM,UAAU,6BAA6B;IAC3C,OAAO;;;;;;;;;;;;CAYR,CAAC;AACF,CAAC;AAED,MAAM,UAAU,2BAA2B;IACzC,OAAO;;;;;;;;CAQR,CAAC;AACF,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgCR,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AlertSink — Pluggable alert delivery for critical runtime events.
|
|
3
|
+
*
|
|
4
|
+
* Emits alerts for crash loops, restart limit exhaustion, heartbeat
|
|
5
|
+
* timeouts, and other critical Supervisor events. Ships with a
|
|
6
|
+
* webhook-based default implementation; custom sinks can be provided
|
|
7
|
+
* via the `alerts.sink` config field.
|
|
8
|
+
*
|
|
9
|
+
* Configuration (forge.config):
|
|
10
|
+
*
|
|
11
|
+
* alerts: {
|
|
12
|
+
* webhook: 'https://hooks.slack.com/...',
|
|
13
|
+
* // Optional overrides:
|
|
14
|
+
* headers: { Authorization: 'Bearer ...' },
|
|
15
|
+
* retries: 3,
|
|
16
|
+
* retryDelayMs: 1000,
|
|
17
|
+
* retryMaxDelayMs: 30000,
|
|
18
|
+
* }
|
|
19
|
+
*/
|
|
20
|
+
export type AlertSeverity = "critical" | "warning" | "info";
|
|
21
|
+
export interface Alert {
|
|
22
|
+
/** Machine-readable event type */
|
|
23
|
+
event: string;
|
|
24
|
+
/** Human-readable summary */
|
|
25
|
+
message: string;
|
|
26
|
+
severity: AlertSeverity;
|
|
27
|
+
/** ISO-8601 timestamp */
|
|
28
|
+
timestamp: string;
|
|
29
|
+
/** Additional structured data */
|
|
30
|
+
details: Record<string, unknown>;
|
|
31
|
+
}
|
|
32
|
+
export interface AlertSinkConfig {
|
|
33
|
+
/** Webhook URL for alert delivery */
|
|
34
|
+
webhook?: string;
|
|
35
|
+
/** Additional headers to include in webhook requests */
|
|
36
|
+
headers?: Record<string, string>;
|
|
37
|
+
/** Maximum number of retry attempts for failed deliveries (default: 3) */
|
|
38
|
+
retries?: number;
|
|
39
|
+
/** Base delay in ms for exponential backoff (default: 1000) */
|
|
40
|
+
retryDelayMs?: number;
|
|
41
|
+
/** Maximum delay in ms for exponential backoff (default: 30000) */
|
|
42
|
+
retryMaxDelayMs?: number;
|
|
43
|
+
/** Custom sink function — overrides webhook when provided */
|
|
44
|
+
sink?: (alert: Alert) => Promise<void>;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* AlertSink delivers alerts to external systems with retry/backoff.
|
|
48
|
+
*
|
|
49
|
+
* Delivery is fire-and-forget from the caller's perspective — failed
|
|
50
|
+
* alerts are logged but never block the Supervisor's main loop.
|
|
51
|
+
*/
|
|
52
|
+
export declare class AlertSink {
|
|
53
|
+
private _config;
|
|
54
|
+
private _retries;
|
|
55
|
+
private _retryDelayMs;
|
|
56
|
+
private _retryMaxDelayMs;
|
|
57
|
+
private _deliveryQueue;
|
|
58
|
+
private _stopped;
|
|
59
|
+
constructor(config?: AlertSinkConfig);
|
|
60
|
+
/** Whether this sink has a delivery target configured */
|
|
61
|
+
get isConfigured(): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Emit an alert. Delivery is non-blocking — errors are caught and logged.
|
|
64
|
+
* Alerts are serialized (one at a time) to avoid overwhelming the webhook.
|
|
65
|
+
*/
|
|
66
|
+
emit(event: string, message: string, severity?: AlertSeverity, details?: Record<string, unknown>): void;
|
|
67
|
+
/**
|
|
68
|
+
* Wait for all pending alert deliveries to complete.
|
|
69
|
+
* Useful for graceful shutdown.
|
|
70
|
+
*/
|
|
71
|
+
flush(): Promise<void>;
|
|
72
|
+
/** Stop accepting new alerts and drain pending deliveries */
|
|
73
|
+
stop(): Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Deliver a single alert with retry/backoff.
|
|
76
|
+
*/
|
|
77
|
+
private _deliver;
|
|
78
|
+
/**
|
|
79
|
+
* Send an alert via HTTP webhook POST.
|
|
80
|
+
*/
|
|
81
|
+
private _deliverWebhook;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=AlertSink.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AlertSink.d.ts","sourceRoot":"","sources":["../../src/core/AlertSink.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;AAE5D,MAAM,WAAW,KAAK;IACpB,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,aAAa,CAAC;IACxB,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,iCAAiC;IACjC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC9B,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+DAA+D;IAC/D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mEAAmE;IACnE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6DAA6D;IAC7D,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC;AAED;;;;;GAKG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,QAAQ,CAAU;gBAEd,MAAM,GAAE,eAAoB;IASxC,yDAAyD;IACzD,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED;;;OAGG;IACH,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,GAAE,aAAyB,EAAE,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI;IAiBtH;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,6DAA6D;IACvD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B;;OAEG;YACW,QAAQ;IA2BtB;;OAEG;YACW,eAAe;CAuB9B"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AlertSink — Pluggable alert delivery for critical runtime events.
|
|
3
|
+
*
|
|
4
|
+
* Emits alerts for crash loops, restart limit exhaustion, heartbeat
|
|
5
|
+
* timeouts, and other critical Supervisor events. Ships with a
|
|
6
|
+
* webhook-based default implementation; custom sinks can be provided
|
|
7
|
+
* via the `alerts.sink` config field.
|
|
8
|
+
*
|
|
9
|
+
* Configuration (forge.config):
|
|
10
|
+
*
|
|
11
|
+
* alerts: {
|
|
12
|
+
* webhook: 'https://hooks.slack.com/...',
|
|
13
|
+
* // Optional overrides:
|
|
14
|
+
* headers: { Authorization: 'Bearer ...' },
|
|
15
|
+
* retries: 3,
|
|
16
|
+
* retryDelayMs: 1000,
|
|
17
|
+
* retryMaxDelayMs: 30000,
|
|
18
|
+
* }
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* AlertSink delivers alerts to external systems with retry/backoff.
|
|
22
|
+
*
|
|
23
|
+
* Delivery is fire-and-forget from the caller's perspective — failed
|
|
24
|
+
* alerts are logged but never block the Supervisor's main loop.
|
|
25
|
+
*/
|
|
26
|
+
export class AlertSink {
|
|
27
|
+
_config;
|
|
28
|
+
_retries;
|
|
29
|
+
_retryDelayMs;
|
|
30
|
+
_retryMaxDelayMs;
|
|
31
|
+
_deliveryQueue;
|
|
32
|
+
_stopped;
|
|
33
|
+
constructor(config = {}) {
|
|
34
|
+
this._config = config;
|
|
35
|
+
this._retries = config.retries ?? 3;
|
|
36
|
+
this._retryDelayMs = config.retryDelayMs ?? 1000;
|
|
37
|
+
this._retryMaxDelayMs = config.retryMaxDelayMs ?? 30000;
|
|
38
|
+
this._deliveryQueue = Promise.resolve();
|
|
39
|
+
this._stopped = false;
|
|
40
|
+
}
|
|
41
|
+
/** Whether this sink has a delivery target configured */
|
|
42
|
+
get isConfigured() {
|
|
43
|
+
return Boolean(this._config.webhook || this._config.sink);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Emit an alert. Delivery is non-blocking — errors are caught and logged.
|
|
47
|
+
* Alerts are serialized (one at a time) to avoid overwhelming the webhook.
|
|
48
|
+
*/
|
|
49
|
+
emit(event, message, severity = "warning", details = {}) {
|
|
50
|
+
if (!this.isConfigured || this._stopped)
|
|
51
|
+
return;
|
|
52
|
+
const alert = {
|
|
53
|
+
event,
|
|
54
|
+
message,
|
|
55
|
+
severity,
|
|
56
|
+
timestamp: new Date().toISOString(),
|
|
57
|
+
details,
|
|
58
|
+
};
|
|
59
|
+
// Chain onto the delivery queue so alerts are sent sequentially
|
|
60
|
+
this._deliveryQueue = this._deliveryQueue.then(() => this._deliver(alert)).catch(() => {
|
|
61
|
+
/* swallowed — _deliver already logs failures */
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Wait for all pending alert deliveries to complete.
|
|
66
|
+
* Useful for graceful shutdown.
|
|
67
|
+
*/
|
|
68
|
+
async flush() {
|
|
69
|
+
await this._deliveryQueue;
|
|
70
|
+
}
|
|
71
|
+
/** Stop accepting new alerts and drain pending deliveries */
|
|
72
|
+
async stop() {
|
|
73
|
+
this._stopped = true;
|
|
74
|
+
await this.flush();
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Deliver a single alert with retry/backoff.
|
|
78
|
+
*/
|
|
79
|
+
async _deliver(alert) {
|
|
80
|
+
for (let attempt = 0; attempt <= this._retries; attempt++) {
|
|
81
|
+
try {
|
|
82
|
+
if (this._config.sink) {
|
|
83
|
+
await this._config.sink(alert);
|
|
84
|
+
}
|
|
85
|
+
else if (this._config.webhook) {
|
|
86
|
+
await this._deliverWebhook(alert);
|
|
87
|
+
}
|
|
88
|
+
return; // success
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
const isLastAttempt = attempt >= this._retries;
|
|
92
|
+
if (isLastAttempt) {
|
|
93
|
+
console.error(`[AlertSink] Failed to deliver alert "${alert.event}" after ${this._retries + 1} attempts: ${err.message}`);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
// Exponential backoff with jitter
|
|
97
|
+
const delay = Math.min(this._retryDelayMs * 2 ** attempt + Math.random() * this._retryDelayMs, this._retryMaxDelayMs);
|
|
98
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Send an alert via HTTP webhook POST.
|
|
104
|
+
*/
|
|
105
|
+
async _deliverWebhook(alert) {
|
|
106
|
+
const url = this._config.webhook;
|
|
107
|
+
const headers = {
|
|
108
|
+
"Content-Type": "application/json",
|
|
109
|
+
...this._config.headers,
|
|
110
|
+
};
|
|
111
|
+
const resp = await fetch(url, {
|
|
112
|
+
method: "POST",
|
|
113
|
+
headers,
|
|
114
|
+
body: JSON.stringify(alert),
|
|
115
|
+
signal: AbortSignal.timeout(10_000),
|
|
116
|
+
});
|
|
117
|
+
if (!resp.ok) {
|
|
118
|
+
// Consume the body to avoid leaking connections
|
|
119
|
+
await resp.text().catch(() => { });
|
|
120
|
+
throw new Error(`Webhook returned ${resp.status}`);
|
|
121
|
+
}
|
|
122
|
+
// Consume the body to avoid leaking connections
|
|
123
|
+
await resp.text().catch(() => { });
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=AlertSink.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AlertSink.js","sourceRoot":"","sources":["../../src/core/AlertSink.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
interface WorkerLike {
|
|
3
|
+
id?: number;
|
|
4
|
+
threadId?: number;
|
|
5
|
+
process?: {
|
|
6
|
+
connected: boolean;
|
|
7
|
+
};
|
|
8
|
+
isDead?: () => boolean;
|
|
9
|
+
isConnected?: () => boolean;
|
|
10
|
+
send: (message: unknown) => void;
|
|
11
|
+
on: (event: string, listener: (...args: unknown[]) => void) => this;
|
|
12
|
+
off: (event: string, listener: (...args: unknown[]) => void) => this;
|
|
13
|
+
}
|
|
14
|
+
interface WorkerEntry {
|
|
15
|
+
id: number;
|
|
16
|
+
worker: WorkerLike;
|
|
17
|
+
mode: string;
|
|
18
|
+
socketPath: string | null;
|
|
19
|
+
_messageHandler?: (msg: unknown) => void;
|
|
20
|
+
_errorHandler?: (err: unknown) => void;
|
|
21
|
+
}
|
|
22
|
+
interface UnregisterOptions {
|
|
23
|
+
suppressBroadcast?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface ServiceStats {
|
|
26
|
+
workerCount: number;
|
|
27
|
+
ids: number[];
|
|
28
|
+
directSockets: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* DirectMessageBus — Unix Domain Socket Mesh (Supervisor Side)
|
|
32
|
+
*
|
|
33
|
+
* The fundamental problem: cluster.Worker.send() can only transfer
|
|
34
|
+
* sockets/servers, not MessagePort objects. So we can't use MessageChannel
|
|
35
|
+
* for direct worker-to-worker communication in cluster mode.
|
|
36
|
+
*
|
|
37
|
+
* Solution: Each worker opens a Unix domain socket server. Workers connect
|
|
38
|
+
* directly to each other via these sockets. The supervisor only tells
|
|
39
|
+
* workers WHERE to connect (socket paths), then gets out of the way.
|
|
40
|
+
*
|
|
41
|
+
* Architecture:
|
|
42
|
+
*
|
|
43
|
+
* SETUP (supervisor involved briefly):
|
|
44
|
+
* 1. Each worker starts a UDS server at /tmp/forge-{pid}/{service}-{worker}.sock
|
|
45
|
+
* 2. Worker reports its socket path to supervisor via IPC
|
|
46
|
+
* 3. Supervisor broadcasts the full socket registry to all workers
|
|
47
|
+
* 4. Workers establish direct connections to each other
|
|
48
|
+
*
|
|
49
|
+
* RUNTIME (supervisor NOT involved in message routing):
|
|
50
|
+
* Worker A ──UDS──► Worker B (direct, length-prefixed JSON)
|
|
51
|
+
* Worker B ──UDS──► Worker A
|
|
52
|
+
*
|
|
53
|
+
* Supervisor only handles:
|
|
54
|
+
* - Socket path registry distribution (one-time + on new workers)
|
|
55
|
+
* - Health checks (periodic pull, not per-message)
|
|
56
|
+
* - Worker lifecycle (restart, scale)
|
|
57
|
+
*/
|
|
58
|
+
export declare class DirectMessageBus extends EventEmitter {
|
|
59
|
+
workers: Map<string, WorkerEntry[]>;
|
|
60
|
+
socketRegistry: Map<string, string>;
|
|
61
|
+
_registeredWorkerIds: Set<number>;
|
|
62
|
+
_workerErrorHandlers: WeakMap<WorkerLike, (err: unknown) => void>;
|
|
63
|
+
_connections: Map<string, Set<string>>;
|
|
64
|
+
_socketDir: string;
|
|
65
|
+
_broadcastTimer: ReturnType<typeof setTimeout> | null;
|
|
66
|
+
constructor();
|
|
67
|
+
get socketDir(): string;
|
|
68
|
+
/**
|
|
69
|
+
* Register a worker. Tell it to start a UDS server, then
|
|
70
|
+
* broadcast the updated registry to all workers.
|
|
71
|
+
*/
|
|
72
|
+
registerWorker(serviceName: string, worker: WorkerLike, mode?: string): void;
|
|
73
|
+
_scheduleBroadcast(): void;
|
|
74
|
+
_sendInitSocket(worker: WorkerLike, serviceName: string, workerId: number): void;
|
|
75
|
+
_sendRegistryTo(worker: WorkerLike): void;
|
|
76
|
+
_broadcastRegistry(): void;
|
|
77
|
+
unregisterWorker(serviceName: string, workerId: number, options?: UnregisterOptions): void;
|
|
78
|
+
unregisterService(serviceName: string): void;
|
|
79
|
+
requestHealthChecks(): void;
|
|
80
|
+
stats(): Record<string, ServiceStats>;
|
|
81
|
+
/**
|
|
82
|
+
* CR-IPC-9: Get the connection matrix for debugging.
|
|
83
|
+
*/
|
|
84
|
+
getConnectionMatrix(): Record<string, string[]>;
|
|
85
|
+
cleanup(): void;
|
|
86
|
+
}
|
|
87
|
+
export {};
|
|
88
|
+
//# sourceMappingURL=DirectMessageBus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DirectMessageBus.d.ts","sourceRoot":"","sources":["../../src/core/DirectMessageBus.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAM3C,UAAU,UAAU;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC;IAC5B,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACjC,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,KAAK,IAAI,CAAC;IACpE,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,KAAK,IAAI,CAAC;CACtE;AAED,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC;AAWD,UAAU,iBAAiB;IACzB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;CACvB;AA6CD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IACpC,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,oBAAoB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAClC,oBAAoB,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC,CAAC;IAClE,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,IAAI,CAAC;;IAwBtD,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED;;;OAGG;IACH,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,GAAE,MAAkB,GAAG,IAAI;IAuGvF,kBAAkB,IAAI,IAAI;IAc1B,eAAe,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAgBhF,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAoBzC,kBAAkB,IAAI,IAAI;IAQ1B,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,IAAI;IAkC9F,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAO5C,mBAAmB,IAAI,IAAI;IAe3B,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC;IAYrC;;OAEG;IACH,mBAAmB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAQ/C,OAAO,IAAI,IAAI;CAQhB"}
|