@portel/photon 1.4.0 → 1.5.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 +287 -1160
- package/dist/auto-ui/beam.d.ts +9 -0
- package/dist/auto-ui/beam.d.ts.map +1 -0
- package/dist/auto-ui/beam.js +2381 -0
- package/dist/auto-ui/beam.js.map +1 -0
- package/dist/auto-ui/components/card.d.ts +13 -0
- package/dist/auto-ui/components/card.d.ts.map +1 -0
- package/dist/auto-ui/components/card.js +64 -0
- package/dist/auto-ui/components/card.js.map +1 -0
- package/dist/auto-ui/components/form.d.ts +15 -0
- package/dist/auto-ui/components/form.d.ts.map +1 -0
- package/dist/auto-ui/components/form.js +72 -0
- package/dist/auto-ui/components/form.js.map +1 -0
- package/dist/auto-ui/components/list.d.ts +13 -0
- package/dist/auto-ui/components/list.d.ts.map +1 -0
- package/dist/auto-ui/components/list.js +58 -0
- package/dist/auto-ui/components/list.js.map +1 -0
- package/dist/auto-ui/components/progress.d.ts +18 -0
- package/dist/auto-ui/components/progress.d.ts.map +1 -0
- package/dist/auto-ui/components/progress.js +125 -0
- package/dist/auto-ui/components/progress.js.map +1 -0
- package/dist/auto-ui/components/table.d.ts +13 -0
- package/dist/auto-ui/components/table.d.ts.map +1 -0
- package/dist/auto-ui/components/table.js +82 -0
- package/dist/auto-ui/components/table.js.map +1 -0
- package/dist/auto-ui/components/tree.d.ts +13 -0
- package/dist/auto-ui/components/tree.d.ts.map +1 -0
- package/dist/auto-ui/components/tree.js +61 -0
- package/dist/auto-ui/components/tree.js.map +1 -0
- package/dist/auto-ui/daemon-tools.d.ts +45 -0
- package/dist/auto-ui/daemon-tools.d.ts.map +1 -0
- package/dist/auto-ui/daemon-tools.js +580 -0
- package/dist/auto-ui/daemon-tools.js.map +1 -0
- package/dist/auto-ui/design-system/index.d.ts +21 -0
- package/dist/auto-ui/design-system/index.d.ts.map +1 -0
- package/dist/auto-ui/design-system/index.js +27 -0
- package/dist/auto-ui/design-system/index.js.map +1 -0
- package/dist/auto-ui/design-system/tokens.d.ts +9 -0
- package/dist/auto-ui/design-system/tokens.d.ts.map +1 -0
- package/dist/auto-ui/design-system/tokens.js +27 -0
- package/dist/auto-ui/design-system/tokens.js.map +1 -0
- package/dist/auto-ui/design-system/transaction-ui.d.ts +70 -0
- package/dist/auto-ui/design-system/transaction-ui.d.ts.map +1 -0
- package/dist/auto-ui/design-system/transaction-ui.js +982 -0
- package/dist/auto-ui/design-system/transaction-ui.js.map +1 -0
- package/dist/auto-ui/frontend/index.html +84 -0
- package/dist/auto-ui/index.d.ts +21 -0
- package/dist/auto-ui/index.d.ts.map +1 -0
- package/dist/auto-ui/index.js +25 -0
- package/dist/auto-ui/index.js.map +1 -0
- package/dist/auto-ui/openapi-generator.d.ts +71 -0
- package/dist/auto-ui/openapi-generator.d.ts.map +1 -0
- package/dist/auto-ui/openapi-generator.js +223 -0
- package/dist/auto-ui/openapi-generator.js.map +1 -0
- package/dist/auto-ui/photon-bridge.d.ts +159 -0
- package/dist/auto-ui/photon-bridge.d.ts.map +1 -0
- package/dist/auto-ui/photon-bridge.js +262 -0
- package/dist/auto-ui/photon-bridge.js.map +1 -0
- package/dist/auto-ui/photon-host.d.ts +113 -0
- package/dist/auto-ui/photon-host.d.ts.map +1 -0
- package/dist/auto-ui/photon-host.js +284 -0
- package/dist/auto-ui/photon-host.js.map +1 -0
- package/dist/auto-ui/platform-compat.d.ts +71 -0
- package/dist/auto-ui/platform-compat.d.ts.map +1 -0
- package/dist/auto-ui/platform-compat.js +574 -0
- package/dist/auto-ui/platform-compat.js.map +1 -0
- package/dist/auto-ui/playground-html.d.ts +15 -0
- package/dist/auto-ui/playground-html.d.ts.map +1 -0
- package/dist/auto-ui/playground-html.js +1113 -0
- package/dist/auto-ui/playground-html.js.map +1 -0
- package/dist/auto-ui/playground-server.d.ts +7 -0
- package/dist/auto-ui/playground-server.d.ts.map +1 -0
- package/dist/auto-ui/playground-server.js +840 -0
- package/dist/auto-ui/playground-server.js.map +1 -0
- package/dist/auto-ui/registry.d.ts +13 -0
- package/dist/auto-ui/registry.d.ts.map +1 -0
- package/dist/auto-ui/registry.js +62 -0
- package/dist/auto-ui/registry.js.map +1 -0
- package/dist/auto-ui/renderer.d.ts +14 -0
- package/dist/auto-ui/renderer.d.ts.map +1 -0
- package/dist/auto-ui/renderer.js +88 -0
- package/dist/auto-ui/renderer.js.map +1 -0
- package/dist/auto-ui/rendering/components.d.ts +29 -0
- package/dist/auto-ui/rendering/components.d.ts.map +1 -0
- package/dist/auto-ui/rendering/components.js +773 -0
- package/dist/auto-ui/rendering/components.js.map +1 -0
- package/dist/auto-ui/rendering/field-analyzer.d.ts +48 -0
- package/dist/auto-ui/rendering/field-analyzer.d.ts.map +1 -0
- package/dist/auto-ui/rendering/field-analyzer.js +270 -0
- package/dist/auto-ui/rendering/field-analyzer.js.map +1 -0
- package/dist/auto-ui/rendering/field-renderers.d.ts +64 -0
- package/dist/auto-ui/rendering/field-renderers.d.ts.map +1 -0
- package/dist/auto-ui/rendering/field-renderers.js +317 -0
- package/dist/auto-ui/rendering/field-renderers.js.map +1 -0
- package/dist/auto-ui/rendering/index.d.ts +28 -0
- package/dist/auto-ui/rendering/index.d.ts.map +1 -0
- package/dist/auto-ui/rendering/index.js +60 -0
- package/dist/auto-ui/rendering/index.js.map +1 -0
- package/dist/auto-ui/rendering/layout-selector.d.ts +48 -0
- package/dist/auto-ui/rendering/layout-selector.d.ts.map +1 -0
- package/dist/auto-ui/rendering/layout-selector.js +352 -0
- package/dist/auto-ui/rendering/layout-selector.js.map +1 -0
- package/dist/auto-ui/rendering/template-engine.d.ts +41 -0
- package/dist/auto-ui/rendering/template-engine.d.ts.map +1 -0
- package/dist/auto-ui/rendering/template-engine.js +238 -0
- package/dist/auto-ui/rendering/template-engine.js.map +1 -0
- package/dist/auto-ui/streamable-http-transport.d.ts +79 -0
- package/dist/auto-ui/streamable-http-transport.d.ts.map +1 -0
- package/dist/auto-ui/streamable-http-transport.js +1314 -0
- package/dist/auto-ui/streamable-http-transport.js.map +1 -0
- package/dist/auto-ui/types.d.ts +310 -0
- package/dist/auto-ui/types.d.ts.map +1 -0
- package/dist/auto-ui/types.js +71 -0
- package/dist/auto-ui/types.js.map +1 -0
- package/dist/beam.bundle.js +13506 -0
- package/dist/beam.bundle.js.map +7 -0
- package/dist/claude-code-plugin.d.ts.map +1 -1
- package/dist/claude-code-plugin.js +30 -30
- package/dist/claude-code-plugin.js.map +1 -1
- package/dist/cli/commands/info.d.ts +11 -0
- package/dist/cli/commands/info.d.ts.map +1 -0
- package/dist/cli/commands/info.js +313 -0
- package/dist/cli/commands/info.js.map +1 -0
- package/dist/cli/commands/marketplace.d.ts +11 -0
- package/dist/cli/commands/marketplace.d.ts.map +1 -0
- package/dist/cli/commands/marketplace.js +198 -0
- package/dist/cli/commands/marketplace.js.map +1 -0
- package/dist/cli/commands/package-app.d.ts +9 -0
- package/dist/cli/commands/package-app.d.ts.map +1 -0
- package/dist/cli/commands/package-app.js +191 -0
- package/dist/cli/commands/package-app.js.map +1 -0
- package/dist/cli/commands/package.d.ts +11 -0
- package/dist/cli/commands/package.d.ts.map +1 -0
- package/dist/cli/commands/package.js +573 -0
- package/dist/cli/commands/package.js.map +1 -0
- package/dist/cli-alias.d.ts.map +1 -1
- package/dist/cli-alias.js +30 -28
- package/dist/cli-alias.js.map +1 -1
- package/dist/cli-formatter.d.ts +8 -24
- package/dist/cli-formatter.d.ts.map +1 -1
- package/dist/cli-formatter.js +8 -325
- package/dist/cli-formatter.js.map +1 -1
- package/dist/cli.d.ts +15 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1157 -1132
- package/dist/cli.js.map +1 -1
- package/dist/daemon/client.d.ts +81 -0
- package/dist/daemon/client.d.ts.map +1 -1
- package/dist/daemon/client.js +583 -13
- package/dist/daemon/client.js.map +1 -1
- package/dist/daemon/manager.d.ts +46 -12
- package/dist/daemon/manager.d.ts.map +1 -1
- package/dist/daemon/manager.js +102 -61
- package/dist/daemon/manager.js.map +1 -1
- package/dist/daemon/protocol.d.ts +74 -6
- package/dist/daemon/protocol.d.ts.map +1 -1
- package/dist/daemon/protocol.js +76 -1
- package/dist/daemon/protocol.js.map +1 -1
- package/dist/daemon/server.d.ts +6 -6
- package/dist/daemon/server.js +778 -117
- package/dist/daemon/server.js.map +1 -1
- package/dist/daemon/session-manager.d.ts +8 -1
- package/dist/daemon/session-manager.d.ts.map +1 -1
- package/dist/daemon/session-manager.js +32 -9
- package/dist/daemon/session-manager.js.map +1 -1
- package/dist/deploy/cloudflare.d.ts +12 -0
- package/dist/deploy/cloudflare.d.ts.map +1 -0
- package/dist/deploy/cloudflare.js +216 -0
- package/dist/deploy/cloudflare.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts +172 -15
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +1132 -267
- package/dist/loader.js.map +1 -1
- package/dist/markdown-utils.d.ts +8 -0
- package/dist/markdown-utils.d.ts.map +1 -0
- package/dist/markdown-utils.js +63 -0
- package/dist/markdown-utils.js.map +1 -0
- package/dist/marketplace-manager.d.ts +10 -0
- package/dist/marketplace-manager.d.ts.map +1 -1
- package/dist/marketplace-manager.js +112 -28
- package/dist/marketplace-manager.js.map +1 -1
- package/dist/mcp-client.d.ts +9 -0
- package/dist/mcp-client.d.ts.map +1 -0
- package/dist/mcp-client.js +11 -0
- package/dist/mcp-client.js.map +1 -0
- package/dist/mcp-elicitation.d.ts +32 -0
- package/dist/mcp-elicitation.d.ts.map +1 -0
- package/dist/mcp-elicitation.js +26 -0
- package/dist/mcp-elicitation.js.map +1 -0
- package/dist/path-resolver.d.ts +9 -12
- package/dist/path-resolver.d.ts.map +1 -1
- package/dist/path-resolver.js +13 -43
- package/dist/path-resolver.js.map +1 -1
- package/dist/photon-cli-runner.d.ts.map +1 -1
- package/dist/photon-cli-runner.js +216 -73
- package/dist/photon-cli-runner.js.map +1 -1
- package/dist/photon-doc-extractor.d.ts +88 -0
- package/dist/photon-doc-extractor.d.ts.map +1 -1
- package/dist/photon-doc-extractor.js +536 -27
- package/dist/photon-doc-extractor.js.map +1 -1
- package/dist/photons/maker.photon.d.ts +182 -0
- package/dist/photons/maker.photon.d.ts.map +1 -0
- package/dist/photons/maker.photon.js +504 -0
- package/dist/photons/maker.photon.js.map +1 -0
- package/dist/photons/maker.photon.ts +626 -0
- package/dist/photons/marketplace.photon.d.ts +110 -0
- package/dist/photons/marketplace.photon.d.ts.map +1 -0
- package/dist/photons/marketplace.photon.js +260 -0
- package/dist/photons/marketplace.photon.js.map +1 -0
- package/dist/photons/marketplace.photon.ts +378 -0
- package/dist/photons/tunnel.photon.d.ts +80 -0
- package/dist/photons/tunnel.photon.d.ts.map +1 -0
- package/dist/photons/tunnel.photon.js +269 -0
- package/dist/photons/tunnel.photon.js.map +1 -0
- package/dist/photons/tunnel.photon.ts +345 -0
- package/dist/security-scanner.d.ts.map +1 -1
- package/dist/security-scanner.js +18 -15
- package/dist/security-scanner.js.map +1 -1
- package/dist/serv/auth/jwt.d.ts +89 -0
- package/dist/serv/auth/jwt.d.ts.map +1 -0
- package/dist/serv/auth/jwt.js +239 -0
- package/dist/serv/auth/jwt.js.map +1 -0
- package/dist/serv/auth/oauth.d.ts +117 -0
- package/dist/serv/auth/oauth.d.ts.map +1 -0
- package/dist/serv/auth/oauth.js +395 -0
- package/dist/serv/auth/oauth.js.map +1 -0
- package/dist/serv/auth/well-known.d.ts +60 -0
- package/dist/serv/auth/well-known.d.ts.map +1 -0
- package/dist/serv/auth/well-known.js +154 -0
- package/dist/serv/auth/well-known.js.map +1 -0
- package/dist/serv/db/d1-client.d.ts +65 -0
- package/dist/serv/db/d1-client.d.ts.map +1 -0
- package/dist/serv/db/d1-client.js +137 -0
- package/dist/serv/db/d1-client.js.map +1 -0
- package/dist/serv/db/d1-stores.d.ts +62 -0
- package/dist/serv/db/d1-stores.d.ts.map +1 -0
- package/dist/serv/db/d1-stores.js +307 -0
- package/dist/serv/db/d1-stores.js.map +1 -0
- package/dist/serv/index.d.ts +114 -0
- package/dist/serv/index.d.ts.map +1 -0
- package/dist/serv/index.js +172 -0
- package/dist/serv/index.js.map +1 -0
- package/dist/serv/local.d.ts +118 -0
- package/dist/serv/local.d.ts.map +1 -0
- package/dist/serv/local.js +392 -0
- package/dist/serv/local.js.map +1 -0
- package/dist/serv/middleware/auth.d.ts +66 -0
- package/dist/serv/middleware/auth.d.ts.map +1 -0
- package/dist/serv/middleware/auth.js +178 -0
- package/dist/serv/middleware/auth.js.map +1 -0
- package/dist/serv/middleware/tenant.d.ts +94 -0
- package/dist/serv/middleware/tenant.d.ts.map +1 -0
- package/dist/serv/middleware/tenant.js +152 -0
- package/dist/serv/middleware/tenant.js.map +1 -0
- package/dist/serv/runtime/executor.d.ts +76 -0
- package/dist/serv/runtime/executor.d.ts.map +1 -0
- package/dist/serv/runtime/executor.js +105 -0
- package/dist/serv/runtime/executor.js.map +1 -0
- package/dist/serv/runtime/index.d.ts +8 -0
- package/dist/serv/runtime/index.d.ts.map +1 -0
- package/dist/serv/runtime/index.js +10 -0
- package/dist/serv/runtime/index.js.map +1 -0
- package/dist/serv/runtime/oauth-context.d.ts +121 -0
- package/dist/serv/runtime/oauth-context.d.ts.map +1 -0
- package/dist/serv/runtime/oauth-context.js +153 -0
- package/dist/serv/runtime/oauth-context.js.map +1 -0
- package/dist/serv/session/kv-store.d.ts +54 -0
- package/dist/serv/session/kv-store.d.ts.map +1 -0
- package/dist/serv/session/kv-store.js +149 -0
- package/dist/serv/session/kv-store.js.map +1 -0
- package/dist/serv/session/store.d.ts +113 -0
- package/dist/serv/session/store.d.ts.map +1 -0
- package/dist/serv/session/store.js +284 -0
- package/dist/serv/session/store.js.map +1 -0
- package/dist/serv/types/index.d.ts +147 -0
- package/dist/serv/types/index.d.ts.map +1 -0
- package/dist/serv/types/index.js +8 -0
- package/dist/serv/types/index.js.map +1 -0
- package/dist/serv/vault/token-vault.d.ts +102 -0
- package/dist/serv/vault/token-vault.d.ts.map +1 -0
- package/dist/serv/vault/token-vault.js +177 -0
- package/dist/serv/vault/token-vault.js.map +1 -0
- package/dist/server.d.ts +173 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1622 -86
- package/dist/server.js.map +1 -1
- package/dist/shared/cli-sections.d.ts +6 -0
- package/dist/shared/cli-sections.d.ts.map +1 -0
- package/dist/shared/cli-sections.js +16 -0
- package/dist/shared/cli-sections.js.map +1 -0
- package/dist/shared/cli-utils.d.ts +81 -0
- package/dist/shared/cli-utils.d.ts.map +1 -0
- package/dist/shared/cli-utils.js +174 -0
- package/dist/shared/cli-utils.js.map +1 -0
- package/dist/shared/config-docs.d.ts +6 -0
- package/dist/shared/config-docs.d.ts.map +1 -0
- package/dist/shared/config-docs.js +6 -0
- package/dist/shared/config-docs.js.map +1 -0
- package/dist/shared/error-handler.d.ts +128 -0
- package/dist/shared/error-handler.d.ts.map +1 -0
- package/dist/shared/error-handler.js +342 -0
- package/dist/shared/error-handler.js.map +1 -0
- package/dist/shared/logger.d.ts +42 -0
- package/dist/shared/logger.d.ts.map +1 -0
- package/dist/shared/logger.js +123 -0
- package/dist/shared/logger.js.map +1 -0
- package/dist/shared/performance.d.ts +65 -0
- package/dist/shared/performance.d.ts.map +1 -0
- package/dist/shared/performance.js +136 -0
- package/dist/shared/performance.js.map +1 -0
- package/dist/shared/task-runner.d.ts +2 -0
- package/dist/shared/task-runner.d.ts.map +1 -0
- package/dist/shared/task-runner.js +16 -0
- package/dist/shared/task-runner.js.map +1 -0
- package/dist/shared/validation.d.ts +6 -0
- package/dist/shared/validation.d.ts.map +1 -0
- package/dist/shared/validation.js +6 -0
- package/dist/shared/validation.js.map +1 -0
- package/dist/shared-utils.d.ts +63 -0
- package/dist/shared-utils.d.ts.map +1 -0
- package/dist/shared-utils.js +123 -0
- package/dist/shared-utils.js.map +1 -0
- package/dist/template-manager.d.ts +23 -2
- package/dist/template-manager.d.ts.map +1 -1
- package/dist/template-manager.js +177 -88
- package/dist/template-manager.js.map +1 -1
- package/dist/test-client.d.ts.map +1 -1
- package/dist/test-client.js +10 -8
- package/dist/test-client.js.map +1 -1
- package/dist/test-runner.d.ts +52 -0
- package/dist/test-runner.d.ts.map +1 -0
- package/dist/test-runner.js +785 -0
- package/dist/test-runner.js.map +1 -0
- package/dist/testing.d.ts +103 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +163 -0
- package/dist/testing.js.map +1 -0
- package/dist/version-checker.d.ts.map +1 -1
- package/dist/version-checker.js +2 -2
- package/dist/version-checker.js.map +1 -1
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +5 -0
- package/dist/version.js.map +1 -0
- package/dist/watcher.d.ts +6 -3
- package/dist/watcher.d.ts.map +1 -1
- package/dist/watcher.js +49 -10
- package/dist/watcher.js.map +1 -1
- package/package.json +47 -7
- package/templates/cloudflare/worker.ts.template +381 -0
- package/templates/cloudflare/wrangler.toml.template +9 -0
- package/dist/base.d.ts +0 -58
- package/dist/base.d.ts.map +0 -1
- package/dist/base.js +0 -92
- package/dist/base.js.map +0 -1
- package/dist/dependency-manager.d.ts +0 -49
- package/dist/dependency-manager.d.ts.map +0 -1
- package/dist/dependency-manager.js +0 -165
- package/dist/dependency-manager.js.map +0 -1
- package/dist/registry-manager.d.ts +0 -76
- package/dist/registry-manager.d.ts.map +0 -1
- package/dist/registry-manager.js +0 -220
- package/dist/registry-manager.js.map +0 -1
- package/dist/schema-extractor.d.ts +0 -110
- package/dist/schema-extractor.d.ts.map +0 -1
- package/dist/schema-extractor.js +0 -727
- package/dist/schema-extractor.js.map +0 -1
- package/dist/test-marketplace-sources.d.ts +0 -5
- package/dist/test-marketplace-sources.d.ts.map +0 -1
- package/dist/test-marketplace-sources.js +0 -53
- package/dist/test-marketplace-sources.js.map +0 -1
- package/dist/types.d.ts +0 -109
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -12
- package/dist/types.js.map +0 -1
package/dist/daemon/client.js
CHANGED
|
@@ -3,18 +3,40 @@
|
|
|
3
3
|
*
|
|
4
4
|
* CLI client for communicating with daemon servers
|
|
5
5
|
* Sends commands via Unix socket / named pipe and receives results
|
|
6
|
+
* Supports bidirectional prompts - daemon can request user input
|
|
6
7
|
*/
|
|
7
8
|
import * as net from 'net';
|
|
8
9
|
import * as crypto from 'crypto';
|
|
9
|
-
import
|
|
10
|
+
import * as readline from 'readline';
|
|
11
|
+
import { getGlobalSocketPath } from './manager.js';
|
|
12
|
+
import { createLogger } from '../shared/logger.js';
|
|
13
|
+
import { getErrorMessage } from '../shared/error-handler.js';
|
|
10
14
|
// Generate session ID for this process
|
|
11
15
|
// This ensures all commands from the same terminal session share the same photon instance
|
|
12
16
|
const SESSION_ID = process.env.PHOTON_SESSION_ID || `cli-${process.pid}-${crypto.randomBytes(4).toString('hex')}`;
|
|
17
|
+
const logger = createLogger({ component: 'daemon-client', minimal: true });
|
|
18
|
+
/**
|
|
19
|
+
* Prompt user for input using readline
|
|
20
|
+
*/
|
|
21
|
+
async function promptUser(message, defaultValue) {
|
|
22
|
+
return new Promise((resolve) => {
|
|
23
|
+
const rl = readline.createInterface({
|
|
24
|
+
input: process.stdin,
|
|
25
|
+
output: process.stdout,
|
|
26
|
+
});
|
|
27
|
+
const prompt = defaultValue ? `${message} [${defaultValue}]: ` : `${message}: `;
|
|
28
|
+
rl.question(prompt, (answer) => {
|
|
29
|
+
rl.close();
|
|
30
|
+
resolve(answer || defaultValue || null);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
}
|
|
13
34
|
/**
|
|
14
35
|
* Send command to daemon and wait for response
|
|
36
|
+
* Handles bidirectional prompts - if daemon requests input, uses readline
|
|
15
37
|
*/
|
|
16
38
|
export async function sendCommand(photonName, method, args) {
|
|
17
|
-
const socketPath =
|
|
39
|
+
const socketPath = getGlobalSocketPath();
|
|
18
40
|
const requestId = `req_${Date.now()}_${Math.random()}`;
|
|
19
41
|
return new Promise((resolve, reject) => {
|
|
20
42
|
const client = net.createConnection(socketPath);
|
|
@@ -25,11 +47,12 @@ export async function sendCommand(photonName, method, args) {
|
|
|
25
47
|
client.destroy();
|
|
26
48
|
reject(new Error('Request timeout'));
|
|
27
49
|
}
|
|
28
|
-
},
|
|
50
|
+
}, 120000); // 2 minute timeout (longer for interactive prompts)
|
|
29
51
|
client.on('connect', () => {
|
|
30
52
|
const request = {
|
|
31
53
|
type: 'command',
|
|
32
54
|
id: requestId,
|
|
55
|
+
photonName,
|
|
33
56
|
sessionId: SESSION_ID,
|
|
34
57
|
clientType: 'cli',
|
|
35
58
|
method,
|
|
@@ -37,7 +60,7 @@ export async function sendCommand(photonName, method, args) {
|
|
|
37
60
|
};
|
|
38
61
|
client.write(JSON.stringify(request) + '\n');
|
|
39
62
|
});
|
|
40
|
-
client.on('data', (chunk) => {
|
|
63
|
+
client.on('data', async (chunk) => {
|
|
41
64
|
buffer += chunk.toString();
|
|
42
65
|
// Process complete JSON messages (newline-delimited)
|
|
43
66
|
const lines = buffer.split('\n');
|
|
@@ -48,27 +71,52 @@ export async function sendCommand(photonName, method, args) {
|
|
|
48
71
|
try {
|
|
49
72
|
const response = JSON.parse(line);
|
|
50
73
|
if (response.id === requestId) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
74
|
+
// Handle prompt request from daemon
|
|
75
|
+
if (response.type === 'prompt' && response.prompt) {
|
|
76
|
+
// Reset timeout while waiting for user input
|
|
77
|
+
clearTimeout(timeout);
|
|
78
|
+
// Get user input via readline
|
|
79
|
+
const userInput = await promptUser(response.prompt.message, response.prompt.default);
|
|
80
|
+
// Send prompt response back to daemon
|
|
81
|
+
const promptResponse = {
|
|
82
|
+
type: 'prompt_response',
|
|
83
|
+
id: requestId,
|
|
84
|
+
promptValue: userInput,
|
|
85
|
+
};
|
|
86
|
+
client.write(JSON.stringify(promptResponse) + '\n');
|
|
87
|
+
// Restart timeout for next response
|
|
88
|
+
setTimeout(() => {
|
|
89
|
+
if (!responseReceived) {
|
|
90
|
+
client.destroy();
|
|
91
|
+
reject(new Error('Request timeout'));
|
|
92
|
+
}
|
|
93
|
+
}, 120000);
|
|
56
94
|
}
|
|
57
|
-
|
|
95
|
+
// Handle final result
|
|
96
|
+
else if (response.type === 'result') {
|
|
97
|
+
responseReceived = true;
|
|
98
|
+
clearTimeout(timeout);
|
|
58
99
|
client.destroy();
|
|
59
100
|
resolve(response.data);
|
|
60
101
|
}
|
|
102
|
+
// Handle error
|
|
103
|
+
else if (response.type === 'error') {
|
|
104
|
+
responseReceived = true;
|
|
105
|
+
clearTimeout(timeout);
|
|
106
|
+
client.destroy();
|
|
107
|
+
reject(new Error(response.error || 'Unknown error'));
|
|
108
|
+
}
|
|
61
109
|
}
|
|
62
110
|
}
|
|
63
111
|
catch (error) {
|
|
64
|
-
|
|
112
|
+
logger.warn('Failed to parse daemon response', { error: getErrorMessage(error) });
|
|
65
113
|
}
|
|
66
114
|
}
|
|
67
115
|
});
|
|
68
116
|
client.on('error', (error) => {
|
|
69
117
|
clearTimeout(timeout);
|
|
70
118
|
client.destroy();
|
|
71
|
-
reject(new Error(`Connection error: ${error
|
|
119
|
+
reject(new Error(`Connection error: ${getErrorMessage(error)}`));
|
|
72
120
|
});
|
|
73
121
|
client.on('end', () => {
|
|
74
122
|
clearTimeout(timeout);
|
|
@@ -79,11 +127,480 @@ export async function sendCommand(photonName, method, args) {
|
|
|
79
127
|
});
|
|
80
128
|
});
|
|
81
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Subscribe to a channel on a daemon
|
|
132
|
+
* Returns an unsubscribe function
|
|
133
|
+
*/
|
|
134
|
+
export async function subscribeChannel(photonName, channel, handler, options) {
|
|
135
|
+
const socketPath = getGlobalSocketPath();
|
|
136
|
+
const subscribeId = `sub_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
137
|
+
return new Promise((resolve, reject) => {
|
|
138
|
+
const client = net.createConnection(socketPath);
|
|
139
|
+
let subscribed = false;
|
|
140
|
+
let buffer = '';
|
|
141
|
+
client.on('connect', () => {
|
|
142
|
+
// Send subscribe request
|
|
143
|
+
const request = {
|
|
144
|
+
type: 'subscribe',
|
|
145
|
+
id: subscribeId,
|
|
146
|
+
photonName,
|
|
147
|
+
channel,
|
|
148
|
+
clientType: 'beam',
|
|
149
|
+
lastEventId: options?.lastEventId,
|
|
150
|
+
};
|
|
151
|
+
client.write(JSON.stringify(request) + '\n');
|
|
152
|
+
});
|
|
153
|
+
client.on('data', (chunk) => {
|
|
154
|
+
buffer += chunk.toString();
|
|
155
|
+
// Process complete JSON messages (newline-delimited)
|
|
156
|
+
const lines = buffer.split('\n');
|
|
157
|
+
buffer = lines.pop() || '';
|
|
158
|
+
for (const line of lines) {
|
|
159
|
+
if (!line.trim())
|
|
160
|
+
continue;
|
|
161
|
+
try {
|
|
162
|
+
const response = JSON.parse(line);
|
|
163
|
+
// Handle subscription confirmation
|
|
164
|
+
if (response.id === subscribeId && response.type === 'result') {
|
|
165
|
+
subscribed = true;
|
|
166
|
+
// Return unsubscribe function
|
|
167
|
+
resolve(() => {
|
|
168
|
+
if (!client.destroyed) {
|
|
169
|
+
const unsubRequest = {
|
|
170
|
+
type: 'unsubscribe',
|
|
171
|
+
id: `unsub_${Date.now()}`,
|
|
172
|
+
photonName,
|
|
173
|
+
channel,
|
|
174
|
+
};
|
|
175
|
+
client.write(JSON.stringify(unsubRequest) + '\n');
|
|
176
|
+
client.end();
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
// Handle refresh-needed signal (lastEventId too old)
|
|
181
|
+
if (response.type === 'refresh_needed') {
|
|
182
|
+
if (options?.onRefreshNeeded) {
|
|
183
|
+
options.onRefreshNeeded();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// Handle channel messages (supports wildcard subscriptions)
|
|
187
|
+
if (response.type === 'channel_message' && response.channel) {
|
|
188
|
+
const isMatch = channel.endsWith(':*')
|
|
189
|
+
? response.channel.startsWith(channel.slice(0, -1)) // "kanban:*" matches "kanban:anything"
|
|
190
|
+
: response.channel === channel; // exact match
|
|
191
|
+
if (isMatch) {
|
|
192
|
+
handler(response.message, response.eventId);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// Handle errors
|
|
196
|
+
if (response.type === 'error' && response.id === subscribeId) {
|
|
197
|
+
reject(new Error(response.error || 'Subscription failed'));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
// Ignore parse errors for partial messages
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
client.on('error', (error) => {
|
|
206
|
+
if (!subscribed) {
|
|
207
|
+
reject(new Error(`Connection error: ${getErrorMessage(error)}`));
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
client.on('end', () => {
|
|
211
|
+
if (!subscribed) {
|
|
212
|
+
reject(new Error('Connection closed before subscription confirmed'));
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Publish a message to a channel on a daemon
|
|
219
|
+
*/
|
|
220
|
+
export async function publishToChannel(photonName, channel, message) {
|
|
221
|
+
const socketPath = getGlobalSocketPath();
|
|
222
|
+
const requestId = `pub_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
223
|
+
return new Promise((resolve, reject) => {
|
|
224
|
+
const client = net.createConnection(socketPath);
|
|
225
|
+
const timeout = setTimeout(() => {
|
|
226
|
+
client.destroy();
|
|
227
|
+
reject(new Error('Publish timeout'));
|
|
228
|
+
}, 5000);
|
|
229
|
+
client.on('connect', () => {
|
|
230
|
+
const request = {
|
|
231
|
+
type: 'publish',
|
|
232
|
+
id: requestId,
|
|
233
|
+
photonName,
|
|
234
|
+
channel,
|
|
235
|
+
message,
|
|
236
|
+
};
|
|
237
|
+
client.write(JSON.stringify(request) + '\n');
|
|
238
|
+
});
|
|
239
|
+
client.on('data', (chunk) => {
|
|
240
|
+
try {
|
|
241
|
+
const response = JSON.parse(chunk.toString().trim());
|
|
242
|
+
if (response.id === requestId) {
|
|
243
|
+
clearTimeout(timeout);
|
|
244
|
+
client.destroy();
|
|
245
|
+
if (response.type === 'result') {
|
|
246
|
+
resolve();
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
reject(new Error(response.error || 'Publish failed'));
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
// Ignore parse errors
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
client.on('error', (error) => {
|
|
258
|
+
clearTimeout(timeout);
|
|
259
|
+
client.destroy();
|
|
260
|
+
reject(new Error(`Connection error: ${getErrorMessage(error)}`));
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Acquire a distributed lock
|
|
266
|
+
* Returns true if lock acquired, false if already held
|
|
267
|
+
*/
|
|
268
|
+
export async function acquireLock(photonName, lockName, timeout) {
|
|
269
|
+
const socketPath = getGlobalSocketPath();
|
|
270
|
+
const requestId = `lock_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
271
|
+
return new Promise((resolve, reject) => {
|
|
272
|
+
const client = net.createConnection(socketPath);
|
|
273
|
+
const requestTimeout = setTimeout(() => {
|
|
274
|
+
client.destroy();
|
|
275
|
+
reject(new Error('Lock request timeout'));
|
|
276
|
+
}, 10000);
|
|
277
|
+
client.on('connect', () => {
|
|
278
|
+
const request = {
|
|
279
|
+
type: 'lock',
|
|
280
|
+
id: requestId,
|
|
281
|
+
photonName,
|
|
282
|
+
sessionId: SESSION_ID,
|
|
283
|
+
lockName,
|
|
284
|
+
lockTimeout: timeout,
|
|
285
|
+
};
|
|
286
|
+
client.write(JSON.stringify(request) + '\n');
|
|
287
|
+
});
|
|
288
|
+
client.on('data', (chunk) => {
|
|
289
|
+
try {
|
|
290
|
+
const response = JSON.parse(chunk.toString().trim());
|
|
291
|
+
if (response.id === requestId) {
|
|
292
|
+
clearTimeout(requestTimeout);
|
|
293
|
+
client.destroy();
|
|
294
|
+
if (response.type === 'result') {
|
|
295
|
+
resolve(response.data.acquired);
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
reject(new Error(response.error || 'Lock failed'));
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
// Ignore parse errors
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
client.on('error', (error) => {
|
|
307
|
+
clearTimeout(requestTimeout);
|
|
308
|
+
client.destroy();
|
|
309
|
+
reject(new Error(`Connection error: ${getErrorMessage(error)}`));
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Release a distributed lock
|
|
315
|
+
* Returns true if lock released, false if not held by this session
|
|
316
|
+
*/
|
|
317
|
+
export async function releaseLock(photonName, lockName) {
|
|
318
|
+
const socketPath = getGlobalSocketPath();
|
|
319
|
+
const requestId = `unlock_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
320
|
+
return new Promise((resolve, reject) => {
|
|
321
|
+
const client = net.createConnection(socketPath);
|
|
322
|
+
const timeout = setTimeout(() => {
|
|
323
|
+
client.destroy();
|
|
324
|
+
reject(new Error('Unlock request timeout'));
|
|
325
|
+
}, 5000);
|
|
326
|
+
client.on('connect', () => {
|
|
327
|
+
const request = {
|
|
328
|
+
type: 'unlock',
|
|
329
|
+
id: requestId,
|
|
330
|
+
photonName,
|
|
331
|
+
sessionId: SESSION_ID,
|
|
332
|
+
lockName,
|
|
333
|
+
};
|
|
334
|
+
client.write(JSON.stringify(request) + '\n');
|
|
335
|
+
});
|
|
336
|
+
client.on('data', (chunk) => {
|
|
337
|
+
try {
|
|
338
|
+
const response = JSON.parse(chunk.toString().trim());
|
|
339
|
+
if (response.id === requestId) {
|
|
340
|
+
clearTimeout(timeout);
|
|
341
|
+
client.destroy();
|
|
342
|
+
if (response.type === 'result') {
|
|
343
|
+
resolve(response.data.released);
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
reject(new Error(response.error || 'Unlock failed'));
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
catch {
|
|
351
|
+
// Ignore parse errors
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
client.on('error', (error) => {
|
|
355
|
+
clearTimeout(timeout);
|
|
356
|
+
client.destroy();
|
|
357
|
+
reject(new Error(`Connection error: ${getErrorMessage(error)}`));
|
|
358
|
+
});
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* List all active locks
|
|
363
|
+
*/
|
|
364
|
+
export async function listLocks(photonName) {
|
|
365
|
+
const socketPath = getGlobalSocketPath();
|
|
366
|
+
const requestId = `listlocks_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
367
|
+
return new Promise((resolve, reject) => {
|
|
368
|
+
const client = net.createConnection(socketPath);
|
|
369
|
+
const timeout = setTimeout(() => {
|
|
370
|
+
client.destroy();
|
|
371
|
+
reject(new Error('List locks request timeout'));
|
|
372
|
+
}, 5000);
|
|
373
|
+
client.on('connect', () => {
|
|
374
|
+
const request = {
|
|
375
|
+
type: 'list_locks',
|
|
376
|
+
id: requestId,
|
|
377
|
+
photonName,
|
|
378
|
+
};
|
|
379
|
+
client.write(JSON.stringify(request) + '\n');
|
|
380
|
+
});
|
|
381
|
+
client.on('data', (chunk) => {
|
|
382
|
+
try {
|
|
383
|
+
const response = JSON.parse(chunk.toString().trim());
|
|
384
|
+
if (response.id === requestId) {
|
|
385
|
+
clearTimeout(timeout);
|
|
386
|
+
client.destroy();
|
|
387
|
+
if (response.type === 'result') {
|
|
388
|
+
resolve(response.data.locks || []);
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
reject(new Error(response.error || 'List locks failed'));
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
catch {
|
|
396
|
+
// Ignore parse errors
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
client.on('error', (error) => {
|
|
400
|
+
clearTimeout(timeout);
|
|
401
|
+
client.destroy();
|
|
402
|
+
reject(new Error(`Connection error: ${getErrorMessage(error)}`));
|
|
403
|
+
});
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Schedule a recurring job
|
|
408
|
+
*/
|
|
409
|
+
export async function scheduleJob(photonName, jobId, method, cron, args) {
|
|
410
|
+
const socketPath = getGlobalSocketPath();
|
|
411
|
+
const requestId = `schedule_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
412
|
+
return new Promise((resolve, reject) => {
|
|
413
|
+
const client = net.createConnection(socketPath);
|
|
414
|
+
const timeout = setTimeout(() => {
|
|
415
|
+
client.destroy();
|
|
416
|
+
reject(new Error('Schedule request timeout'));
|
|
417
|
+
}, 5000);
|
|
418
|
+
client.on('connect', () => {
|
|
419
|
+
const request = {
|
|
420
|
+
type: 'schedule',
|
|
421
|
+
id: requestId,
|
|
422
|
+
photonName,
|
|
423
|
+
sessionId: SESSION_ID,
|
|
424
|
+
jobId,
|
|
425
|
+
method,
|
|
426
|
+
cron,
|
|
427
|
+
args,
|
|
428
|
+
};
|
|
429
|
+
client.write(JSON.stringify(request) + '\n');
|
|
430
|
+
});
|
|
431
|
+
client.on('data', (chunk) => {
|
|
432
|
+
try {
|
|
433
|
+
const response = JSON.parse(chunk.toString().trim());
|
|
434
|
+
if (response.id === requestId) {
|
|
435
|
+
clearTimeout(timeout);
|
|
436
|
+
client.destroy();
|
|
437
|
+
if (response.type === 'result') {
|
|
438
|
+
resolve(response.data);
|
|
439
|
+
}
|
|
440
|
+
else {
|
|
441
|
+
reject(new Error(response.error || 'Schedule failed'));
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
catch {
|
|
446
|
+
// Ignore parse errors
|
|
447
|
+
}
|
|
448
|
+
});
|
|
449
|
+
client.on('error', (error) => {
|
|
450
|
+
clearTimeout(timeout);
|
|
451
|
+
client.destroy();
|
|
452
|
+
reject(new Error(`Connection error: ${getErrorMessage(error)}`));
|
|
453
|
+
});
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Unschedule a job
|
|
458
|
+
*/
|
|
459
|
+
export async function unscheduleJob(photonName, jobId) {
|
|
460
|
+
const socketPath = getGlobalSocketPath();
|
|
461
|
+
const requestId = `unschedule_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
462
|
+
return new Promise((resolve, reject) => {
|
|
463
|
+
const client = net.createConnection(socketPath);
|
|
464
|
+
const timeout = setTimeout(() => {
|
|
465
|
+
client.destroy();
|
|
466
|
+
reject(new Error('Unschedule request timeout'));
|
|
467
|
+
}, 5000);
|
|
468
|
+
client.on('connect', () => {
|
|
469
|
+
const request = {
|
|
470
|
+
type: 'unschedule',
|
|
471
|
+
id: requestId,
|
|
472
|
+
photonName,
|
|
473
|
+
jobId,
|
|
474
|
+
};
|
|
475
|
+
client.write(JSON.stringify(request) + '\n');
|
|
476
|
+
});
|
|
477
|
+
client.on('data', (chunk) => {
|
|
478
|
+
try {
|
|
479
|
+
const response = JSON.parse(chunk.toString().trim());
|
|
480
|
+
if (response.id === requestId) {
|
|
481
|
+
clearTimeout(timeout);
|
|
482
|
+
client.destroy();
|
|
483
|
+
if (response.type === 'result') {
|
|
484
|
+
resolve(response.data.unscheduled);
|
|
485
|
+
}
|
|
486
|
+
else {
|
|
487
|
+
reject(new Error(response.error || 'Unschedule failed'));
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
catch {
|
|
492
|
+
// Ignore parse errors
|
|
493
|
+
}
|
|
494
|
+
});
|
|
495
|
+
client.on('error', (error) => {
|
|
496
|
+
clearTimeout(timeout);
|
|
497
|
+
client.destroy();
|
|
498
|
+
reject(new Error(`Connection error: ${getErrorMessage(error)}`));
|
|
499
|
+
});
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* List all scheduled jobs
|
|
504
|
+
*/
|
|
505
|
+
export async function listJobs(photonName) {
|
|
506
|
+
const socketPath = getGlobalSocketPath();
|
|
507
|
+
const requestId = `listjobs_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
508
|
+
return new Promise((resolve, reject) => {
|
|
509
|
+
const client = net.createConnection(socketPath);
|
|
510
|
+
const timeout = setTimeout(() => {
|
|
511
|
+
client.destroy();
|
|
512
|
+
reject(new Error('List jobs request timeout'));
|
|
513
|
+
}, 5000);
|
|
514
|
+
client.on('connect', () => {
|
|
515
|
+
const request = {
|
|
516
|
+
type: 'list_jobs',
|
|
517
|
+
id: requestId,
|
|
518
|
+
photonName,
|
|
519
|
+
};
|
|
520
|
+
client.write(JSON.stringify(request) + '\n');
|
|
521
|
+
});
|
|
522
|
+
client.on('data', (chunk) => {
|
|
523
|
+
try {
|
|
524
|
+
const response = JSON.parse(chunk.toString().trim());
|
|
525
|
+
if (response.id === requestId) {
|
|
526
|
+
clearTimeout(timeout);
|
|
527
|
+
client.destroy();
|
|
528
|
+
if (response.type === 'result') {
|
|
529
|
+
resolve(response.data.jobs || []);
|
|
530
|
+
}
|
|
531
|
+
else {
|
|
532
|
+
reject(new Error(response.error || 'List jobs failed'));
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
catch {
|
|
537
|
+
// Ignore parse errors
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
client.on('error', (error) => {
|
|
541
|
+
clearTimeout(timeout);
|
|
542
|
+
client.destroy();
|
|
543
|
+
reject(new Error(`Connection error: ${getErrorMessage(error)}`));
|
|
544
|
+
});
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Reload the daemon's photon code without losing state
|
|
549
|
+
* Called by dev server after hot-reload to sync daemon
|
|
550
|
+
*/
|
|
551
|
+
export async function reloadDaemon(photonName, photonPath) {
|
|
552
|
+
const socketPath = getGlobalSocketPath();
|
|
553
|
+
const requestId = `reload_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
554
|
+
return new Promise((resolve, reject) => {
|
|
555
|
+
const client = net.createConnection(socketPath);
|
|
556
|
+
const timeout = setTimeout(() => {
|
|
557
|
+
client.destroy();
|
|
558
|
+
reject(new Error('Reload request timeout'));
|
|
559
|
+
}, 30000); // 30 second timeout for reload
|
|
560
|
+
client.on('connect', () => {
|
|
561
|
+
const request = {
|
|
562
|
+
type: 'reload',
|
|
563
|
+
id: requestId,
|
|
564
|
+
photonName,
|
|
565
|
+
photonPath,
|
|
566
|
+
};
|
|
567
|
+
client.write(JSON.stringify(request) + '\n');
|
|
568
|
+
});
|
|
569
|
+
client.on('data', (chunk) => {
|
|
570
|
+
try {
|
|
571
|
+
const response = JSON.parse(chunk.toString().trim());
|
|
572
|
+
if (response.id === requestId) {
|
|
573
|
+
clearTimeout(timeout);
|
|
574
|
+
client.destroy();
|
|
575
|
+
if (response.type === 'result') {
|
|
576
|
+
const data = response.data;
|
|
577
|
+
resolve({
|
|
578
|
+
success: response.success ?? true,
|
|
579
|
+
error: data?.error,
|
|
580
|
+
sessionsUpdated: data?.sessionsUpdated,
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
else {
|
|
584
|
+
resolve({ success: false, error: response.error || 'Reload failed' });
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
catch {
|
|
589
|
+
// Ignore parse errors
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
client.on('error', (error) => {
|
|
593
|
+
clearTimeout(timeout);
|
|
594
|
+
client.destroy();
|
|
595
|
+
reject(new Error(`Connection error: ${getErrorMessage(error)}`));
|
|
596
|
+
});
|
|
597
|
+
});
|
|
598
|
+
}
|
|
82
599
|
/**
|
|
83
600
|
* Ping daemon to check if it's responsive
|
|
84
601
|
*/
|
|
85
602
|
export async function pingDaemon(photonName) {
|
|
86
|
-
const socketPath =
|
|
603
|
+
const socketPath = getGlobalSocketPath();
|
|
87
604
|
const requestId = `ping_${Date.now()}`;
|
|
88
605
|
return new Promise((resolve) => {
|
|
89
606
|
const client = net.createConnection(socketPath);
|
|
@@ -95,6 +612,7 @@ export async function pingDaemon(photonName) {
|
|
|
95
612
|
const request = {
|
|
96
613
|
type: 'ping',
|
|
97
614
|
id: requestId,
|
|
615
|
+
photonName,
|
|
98
616
|
};
|
|
99
617
|
client.write(JSON.stringify(request) + '\n');
|
|
100
618
|
});
|
|
@@ -123,4 +641,56 @@ export async function pingDaemon(photonName) {
|
|
|
123
641
|
});
|
|
124
642
|
});
|
|
125
643
|
}
|
|
644
|
+
/**
|
|
645
|
+
* Get events since a specific eventId for a channel
|
|
646
|
+
* Used for explicit replay when client has missed events
|
|
647
|
+
*/
|
|
648
|
+
export async function getEventsSince(photonName, channel, lastEventId) {
|
|
649
|
+
const socketPath = getGlobalSocketPath();
|
|
650
|
+
const requestId = `getevents_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
651
|
+
return new Promise((resolve, reject) => {
|
|
652
|
+
const client = net.createConnection(socketPath);
|
|
653
|
+
const timeout = setTimeout(() => {
|
|
654
|
+
client.destroy();
|
|
655
|
+
reject(new Error('Get events request timeout'));
|
|
656
|
+
}, 5000);
|
|
657
|
+
client.on('connect', () => {
|
|
658
|
+
const request = {
|
|
659
|
+
type: 'get_events_since',
|
|
660
|
+
id: requestId,
|
|
661
|
+
photonName,
|
|
662
|
+
channel,
|
|
663
|
+
lastEventId,
|
|
664
|
+
};
|
|
665
|
+
client.write(JSON.stringify(request) + '\n');
|
|
666
|
+
});
|
|
667
|
+
client.on('data', (chunk) => {
|
|
668
|
+
try {
|
|
669
|
+
const response = JSON.parse(chunk.toString().trim());
|
|
670
|
+
if (response.id === requestId) {
|
|
671
|
+
clearTimeout(timeout);
|
|
672
|
+
client.destroy();
|
|
673
|
+
if (response.type === 'result') {
|
|
674
|
+
const data = response.data;
|
|
675
|
+
resolve({
|
|
676
|
+
events: data.events || [],
|
|
677
|
+
refreshNeeded: data.refreshNeeded || false,
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
else {
|
|
681
|
+
reject(new Error(response.error || 'Get events failed'));
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
catch {
|
|
686
|
+
// Ignore parse errors
|
|
687
|
+
}
|
|
688
|
+
});
|
|
689
|
+
client.on('error', (error) => {
|
|
690
|
+
clearTimeout(timeout);
|
|
691
|
+
client.destroy();
|
|
692
|
+
reject(new Error(`Connection error: ${getErrorMessage(error)}`));
|
|
693
|
+
});
|
|
694
|
+
});
|
|
695
|
+
}
|
|
126
696
|
//# sourceMappingURL=client.js.map
|