coakka-v2-connector-electron 1.3.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/CONSUMING.md ADDED
@@ -0,0 +1,14 @@
1
+ # Consuming CoAkka Runtime Connector For Electron
2
+
3
+ Install the published package through your normal application package feed.
4
+ Electron itself remains the application framework dependency; this package owns
5
+ the CoAkka runtime intent bridge and consumes the published Node connector as
6
+ the main-process runtime host.
7
+
8
+ Use the package only from the Electron main process and preload boundary:
9
+
10
+ - main process: start `ElectronRuntimeIntentBridge`
11
+ - preload: expose `createCoAkkaPreloadApi(ipcRenderer)`
12
+ - renderer: call `window.coakka.intent(...)`
13
+
14
+ Do not import the runtime connector directly from renderer code.
package/LICENSE.md ADDED
@@ -0,0 +1,115 @@
1
+ # CoAkka Public Artifact Preview License 1.0
2
+
3
+ Effective: 2026-07-19
4
+
5
+ This repository is the public binary artifact surface for CoAkka. It contains
6
+ headers, native libraries, connector packages, Maven artifacts, checksums, and
7
+ artifact metadata. It is not a source-build repository.
8
+
9
+ Unless a specific release artifact includes different license terms, the
10
+ artifacts in this repository are made available under the following preview
11
+ terms.
12
+
13
+ This is not an OSI-approved open source license. The separate
14
+ `coakka-samples` repository may use a permissive open source license for sample
15
+ code and documentation; that sample license does not change the terms for the
16
+ artifacts distributed from this repository.
17
+
18
+ ## Definitions
19
+
20
+ `Artifacts` means the CoAkka binaries, headers, libraries, connector packages,
21
+ Maven artifacts, container-bundle files, checksums, manifests, and release
22
+ metadata distributed from this repository or from an official release page for
23
+ this repository.
24
+
25
+ `Production` means any environment that serves live end-user traffic, live
26
+ customer data, live operational data, revenue-generating workloads, or
27
+ customer-facing workloads outside development, test, CI, sample execution, or
28
+ proof-of-concept evaluation.
29
+
30
+ `Official sample images` means container images published by the CoAkka
31
+ project or repository owner, including the current
32
+ `docker.io/gabrielgun1983/*` sample image namespace and any future images
33
+ published under an official CoAkka container namespace, that bundle unmodified
34
+ artifacts solely to run official CoAkka samples.
35
+
36
+ ## Allowed Use
37
+
38
+ You may download, copy, and use the artifacts from this repository to:
39
+
40
+ - evaluate CoAkka locally
41
+ - run the official public samples
42
+ - build proof-of-concept integrations
43
+ - run development and test environments for applications that integrate with
44
+ CoAkka
45
+ - run CI jobs, automated tests, and integration verification for
46
+ non-production applications or evaluations
47
+ - run company evaluations, proofs of concept, and integration tests,
48
+ including evaluations inside commercial organizations
49
+ - redistribute unmodified CoAkka artifacts inside local development, test, or
50
+ sample environments, provided this notice and the included checksums or
51
+ manifests remain available
52
+ - pull, cache internally, and run official sample images for local development,
53
+ CI, test, sample execution, proof-of-concept integration, and evaluation
54
+
55
+ ## Reserved Uses
56
+
57
+ The following uses require a separate written license:
58
+
59
+ - selling, hosting, or offering CoAkka artifacts as a managed runtime service
60
+ - running CoAkka artifacts in production systems
61
+ - bundling CoAkka artifacts into a product distributed to customers
62
+ - redistributing CoAkka artifacts as part of a paid product, support package,
63
+ appliance, cloud image, or hosted service
64
+ - offering a product or service that presents modified CoAkka artifacts as
65
+ official CoAkka artifacts
66
+ - removing or obscuring copyright, license, checksum, or provenance notices
67
+ - reverse engineering artifacts except where that restriction is prohibited by
68
+ applicable law
69
+ - using the CoAkka name, package names, artifact names, image names, or other
70
+ project identifiers in a way that implies endorsement of an unofficial fork,
71
+ hosted service, or product
72
+
73
+ ## Official Samples
74
+
75
+ Official sample images may bundle unmodified artifacts solely so users can run
76
+ official CoAkka samples without installing the artifacts manually.
77
+
78
+ This sample-image permission does not grant third parties the right to create,
79
+ publish, sell, host, or distribute derivative images for production, customer
80
+ distribution, hosted services, paid support packages, appliances, or cloud
81
+ marketplace offerings.
82
+
83
+ ## Production Use
84
+
85
+ These preview terms are intended for developer evaluation, sample execution,
86
+ non-production proof-of-concept work, CI, and integration testing. Production
87
+ use, hosted service use, customer distribution, and paid redistribution require
88
+ explicit release terms or a separate written agreement.
89
+
90
+ For production, hosted service, customer distribution, paid redistribution, or
91
+ other commercial rights, contact the project through `SUPPORT.md`.
92
+
93
+ ## No Warranty
94
+
95
+ The artifacts are provided as-is, without warranties or conditions of any kind,
96
+ to the maximum extent permitted by applicable law.
97
+
98
+ ## Limitation Of Liability
99
+
100
+ To the maximum extent permitted by applicable law, the project contributors and
101
+ artifact publishers are not liable for any direct, indirect, incidental,
102
+ special, consequential, exemplary, or other damages arising from use of the
103
+ artifacts.
104
+
105
+ ## No Patent Or Trademark Grant
106
+
107
+ These preview terms do not grant patent rights, trademark rights, or rights to
108
+ use the CoAkka name beyond the limited artifact and sample uses allowed above.
109
+ Trademark use is governed by `TRADEMARKS.md`.
110
+
111
+ ## Legal Notice
112
+
113
+ This file is not legal advice. If your intended use depends on legal
114
+ interpretation of these terms, consult your own counsel or request a separate
115
+ written agreement.
package/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # CoAkka Runtime Connector For Electron
2
+
3
+ This package is the Electron main-process intent bridge for CoAkka runtime v2.
4
+
5
+ The boundary is intentionally strict:
6
+
7
+ - renderer JavaScript sends an intent through `ipcRenderer.invoke`
8
+ - preload exposes only a small `coakka.intent(...)` API
9
+ - the Electron main process owns `ElectronRuntimeIntentBridge`
10
+ - the main process converts the intent into runtime delivery and projects the
11
+ result back to the renderer
12
+
13
+ Renderer code does not import the runtime connector, does not know runtime
14
+ envelopes, and does not own native runtime lifecycle.
15
+
16
+ ## Main Process
17
+
18
+ ```js
19
+ import { ipcMain } from "electron";
20
+ import {
21
+ ElectronRuntimeIntentBridge,
22
+ registerElectronIntentIpcHandler,
23
+ } from "coakka-v2-connector-electron";
24
+
25
+ const target = "samples.electron.intent.echo";
26
+ const bridge = ElectronRuntimeIntentBridge.start({
27
+ systemName: "electron-app",
28
+ nodeId: "electron-app-main",
29
+ defaultTarget: target,
30
+ });
31
+
32
+ bridge.registerJsonIntentHandler(target, async (intent) => ({
33
+ handledBy: "electron-main",
34
+ echo: intent.payload,
35
+ }));
36
+
37
+ registerElectronIntentIpcHandler(ipcMain, bridge);
38
+ ```
39
+
40
+ ## Preload
41
+
42
+ ```js
43
+ const { contextBridge, ipcRenderer } = require("electron");
44
+ const { createCoAkkaPreloadApi } = require("coakka-v2-connector-electron/preload");
45
+
46
+ contextBridge.exposeInMainWorld("coakka", createCoAkkaPreloadApi(ipcRenderer));
47
+ ```
48
+
49
+ ## Renderer
50
+
51
+ ```js
52
+ const result = await window.coakka.intent({
53
+ intentId: "intent-1",
54
+ source: "electron-renderer",
55
+ target: "samples.electron.intent.echo",
56
+ operation: "echo",
57
+ payload: { message: "hello-electron-runtime" },
58
+ payloadIdentity: {
59
+ messageType: "samples.electron.intent.echo.request.v1",
60
+ payloadSchemaVersion: 1,
61
+ payloadFormat: "json",
62
+ },
63
+ timeoutMs: 2000,
64
+ });
65
+ ```
66
+
67
+ ## Smoke
68
+
69
+ ```sh
70
+ npm run build
71
+ bash scripts/smoke-packaged-package.sh
72
+ ```
73
+
74
+ The packaged smoke installs the generated package into a disposable Electron
75
+ app, loads a hidden renderer window, sends one renderer intent through preload
76
+ and IPC, and verifies that the main process handles it through the runtime
77
+ host exposed by the published Node connector package.
@@ -0,0 +1,58 @@
1
+ export declare const COAKKA_ELECTRON_CONNECTOR_VERSION = "1.3.1";
2
+ export declare const COAKKA_ELECTRON_INTENT_CHANNEL = "coakka:intent";
3
+ export interface ElectronIntentPayloadIdentity {
4
+ messageType: string;
5
+ payloadSchemaVersion?: number;
6
+ payloadFormat?: "json";
7
+ }
8
+ export interface ElectronIntentEnvelope {
9
+ intentId: string;
10
+ source: string;
11
+ target: string;
12
+ operation: string;
13
+ payload: Record<string, unknown>;
14
+ payloadIdentity: ElectronIntentPayloadIdentity;
15
+ timeoutMs?: number;
16
+ headers?: Record<string, string>;
17
+ }
18
+ export interface ElectronIntentResult {
19
+ intentId: string;
20
+ source: string;
21
+ target: string;
22
+ operation: string;
23
+ payload: Record<string, unknown>;
24
+ runtime: {
25
+ generation: number;
26
+ delivered: number;
27
+ matchedResponses: number;
28
+ matchedDeadletters: number;
29
+ };
30
+ }
31
+ export interface ElectronRuntimeIntentBridgeOptions {
32
+ systemName: string;
33
+ nodeId: string;
34
+ defaultTarget: string;
35
+ routePort?: number;
36
+ queueCapacity?: number;
37
+ strictNoDrop?: boolean;
38
+ runtimeLibPath?: string;
39
+ }
40
+ export type ElectronJsonIntentHandler = (intent: ElectronIntentEnvelope) => Record<string, unknown> | Promise<Record<string, unknown>>;
41
+ export interface IpcMainLike {
42
+ handle(channel: string, listener: (event: unknown, intent: ElectronIntentEnvelope) => Promise<ElectronIntentResult>): void;
43
+ removeHandler(channel: string): void;
44
+ }
45
+ export declare class ElectronRuntimeIntentBridge {
46
+ private readonly runtimeHost;
47
+ readonly defaultTarget: string;
48
+ static start(options: ElectronRuntimeIntentBridgeOptions): ElectronRuntimeIntentBridge;
49
+ private readonly handlers;
50
+ private closed;
51
+ private constructor();
52
+ registerJsonIntentHandler(target: string, handler: ElectronJsonIntentHandler): void;
53
+ handleIntent(intent: ElectronIntentEnvelope): Promise<ElectronIntentResult>;
54
+ close(): void;
55
+ private createRuntimeHandler;
56
+ private requireOpen;
57
+ }
58
+ export declare function registerElectronIntentIpcHandler(ipcMain: IpcMainLike, bridge: ElectronRuntimeIntentBridge, channel?: string): () => void;
package/dist/index.js ADDED
@@ -0,0 +1,161 @@
1
+ import { DeliveryHint, EndpointFlag, NodeRuntimeClient, PayloadFormat, PayloadIdentity, RuntimeHost, } from "coakka-v2-connector-node";
2
+ export const COAKKA_ELECTRON_CONNECTOR_VERSION = "1.3.1";
3
+ export const COAKKA_ELECTRON_INTENT_CHANNEL = "coakka:intent";
4
+ const DEFAULT_ROUTE_PORT = 19481;
5
+ export class ElectronRuntimeIntentBridge {
6
+ runtimeHost;
7
+ defaultTarget;
8
+ static start(options) {
9
+ const target = requireNonBlank(options.defaultTarget, "defaultTarget");
10
+ const startSpec = {
11
+ systemName: requireNonBlank(options.systemName, "systemName"),
12
+ nodeId: requireNonBlank(options.nodeId, "nodeId"),
13
+ queueCapacity: options.queueCapacity ?? 64,
14
+ strictNoDrop: options.strictNoDrop ?? true,
15
+ generation: 1,
16
+ routes: [
17
+ {
18
+ target,
19
+ endpoints: [
20
+ {
21
+ host: "127.0.0.1",
22
+ port: options.routePort ?? DEFAULT_ROUTE_PORT,
23
+ flags: EndpointFlag.LOCAL,
24
+ },
25
+ ],
26
+ },
27
+ ],
28
+ };
29
+ return new ElectronRuntimeIntentBridge(RuntimeHost.start(startSpec, options.runtimeLibPath), target);
30
+ }
31
+ handlers = new Map();
32
+ closed = false;
33
+ constructor(runtimeHost, defaultTarget) {
34
+ this.runtimeHost = runtimeHost;
35
+ this.defaultTarget = defaultTarget;
36
+ }
37
+ registerJsonIntentHandler(target, handler) {
38
+ const normalizedTarget = requireNonBlank(target, "target");
39
+ this.handlers.set(normalizedTarget, handler);
40
+ this.runtimeHost.registerHandler(normalizedTarget, this.createRuntimeHandler(normalizedTarget), true);
41
+ }
42
+ async handleIntent(intent) {
43
+ this.requireOpen();
44
+ const normalized = normalizeIntent(intent);
45
+ const identity = toPayloadIdentity(normalized.payloadIdentity);
46
+ const response = await this.runtimeHost.askJson(normalized.source, normalized.target, normalized.payload, identity, normalized.timeoutMs ?? 2_000, normalized.operation, DeliveryHint.ROUTER_DEFAULT, normalized.headers ?? {});
47
+ const clientStats = this.runtimeHost.clientStats();
48
+ const runtimeStats = this.runtimeHost.stats();
49
+ return {
50
+ intentId: normalized.intentId,
51
+ source: normalized.source,
52
+ target: normalized.target,
53
+ operation: normalized.operation,
54
+ payload: response,
55
+ runtime: {
56
+ generation: runtimeStats.appliedGeneration,
57
+ delivered: clientStats.deliveredRequests,
58
+ matchedResponses: clientStats.matchedResponses,
59
+ matchedDeadletters: clientStats.matchedDeadletters,
60
+ },
61
+ };
62
+ }
63
+ close() {
64
+ if (this.closed) {
65
+ return;
66
+ }
67
+ this.closed = true;
68
+ this.runtimeHost.close();
69
+ }
70
+ createRuntimeHandler(target) {
71
+ return async (request) => {
72
+ const handler = this.handlers.get(target);
73
+ if (handler == null) {
74
+ throw new Error(`no Electron intent handler registered for target=${target}`);
75
+ }
76
+ const payload = JSON.parse(Buffer.from(request.payload).toString("utf8"));
77
+ const resultPayload = await handler({
78
+ intentId: request.message_id,
79
+ source: request.source,
80
+ target,
81
+ operation: "intent",
82
+ payload,
83
+ payloadIdentity: {
84
+ messageType: request.message_type,
85
+ payloadSchemaVersion: request.payload_schema_version,
86
+ payloadFormat: "json",
87
+ },
88
+ headers: request.headers,
89
+ });
90
+ return NodeRuntimeClient.makeJsonReplyFromRequestIdentity(request, target, resultPayload);
91
+ };
92
+ }
93
+ requireOpen() {
94
+ if (this.closed) {
95
+ throw new Error("Electron runtime intent bridge is closed");
96
+ }
97
+ }
98
+ }
99
+ export function registerElectronIntentIpcHandler(ipcMain, bridge, channel = COAKKA_ELECTRON_INTENT_CHANNEL) {
100
+ ipcMain.handle(channel, async (_event, intent) => bridge.handleIntent(intent));
101
+ return () => ipcMain.removeHandler(channel);
102
+ }
103
+ function normalizeIntent(intent) {
104
+ if (intent == null || typeof intent !== "object") {
105
+ throw new Error("intent envelope is required");
106
+ }
107
+ return {
108
+ intentId: requireNonBlank(intent.intentId, "intentId"),
109
+ source: requireNonBlank(intent.source, "source"),
110
+ target: requireNonBlank(intent.target, "target"),
111
+ operation: requireNonBlank(intent.operation, "operation"),
112
+ payload: requireJsonObject(intent.payload, "payload"),
113
+ payloadIdentity: requirePayloadIdentity(intent.payloadIdentity),
114
+ timeoutMs: normalizeTimeout(intent.timeoutMs),
115
+ headers: normalizeHeaders(intent.headers),
116
+ };
117
+ }
118
+ function toPayloadIdentity(identity) {
119
+ return new PayloadIdentity(identity.messageType, identity.payloadSchemaVersion ?? 1, PayloadFormat.JSON).requireTyped("Electron intent payloadIdentity");
120
+ }
121
+ function requirePayloadIdentity(identity) {
122
+ if (identity == null || typeof identity !== "object") {
123
+ throw new Error("payloadIdentity is required");
124
+ }
125
+ return {
126
+ messageType: requireNonBlank(identity.messageType, "payloadIdentity.messageType"),
127
+ payloadSchemaVersion: identity.payloadSchemaVersion ?? 1,
128
+ payloadFormat: "json",
129
+ };
130
+ }
131
+ function requireJsonObject(value, what) {
132
+ if (value == null || typeof value !== "object" || Array.isArray(value)) {
133
+ throw new Error(`${what} must be a JSON object`);
134
+ }
135
+ return value;
136
+ }
137
+ function normalizeHeaders(headers) {
138
+ if (headers == null) {
139
+ return {};
140
+ }
141
+ const normalized = {};
142
+ for (const [key, value] of Object.entries(headers)) {
143
+ normalized[requireNonBlank(key, "header key")] = String(value);
144
+ }
145
+ return normalized;
146
+ }
147
+ function normalizeTimeout(timeoutMs) {
148
+ if (timeoutMs == null) {
149
+ return undefined;
150
+ }
151
+ if (!Number.isInteger(timeoutMs) || timeoutMs < 1) {
152
+ throw new Error("timeoutMs must be a positive integer");
153
+ }
154
+ return timeoutMs;
155
+ }
156
+ function requireNonBlank(value, what) {
157
+ if (typeof value !== "string" || value.trim() === "") {
158
+ throw new Error(`${what} is required`);
159
+ }
160
+ return value;
161
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+
3
+ const COAKKA_ELECTRON_INTENT_CHANNEL = "coakka:intent";
4
+
5
+ function createCoAkkaPreloadApi(ipcRenderer, channel = COAKKA_ELECTRON_INTENT_CHANNEL) {
6
+ return {
7
+ intent(intent) {
8
+ return ipcRenderer.invoke(channel, intent);
9
+ },
10
+ };
11
+ }
12
+
13
+ module.exports = {
14
+ COAKKA_ELECTRON_INTENT_CHANNEL,
15
+ createCoAkkaPreloadApi,
16
+ };
@@ -0,0 +1,8 @@
1
+ export declare const COAKKA_ELECTRON_INTENT_CHANNEL = "coakka:intent";
2
+ export interface IpcRendererLike {
3
+ invoke(channel: string, payload: unknown): Promise<unknown>;
4
+ }
5
+ export interface CoAkkaElectronPreloadApi {
6
+ intent(intent: unknown): Promise<unknown>;
7
+ }
8
+ export declare function createCoAkkaPreloadApi(ipcRenderer: IpcRendererLike, channel?: string): CoAkkaElectronPreloadApi;
@@ -0,0 +1,8 @@
1
+ export const COAKKA_ELECTRON_INTENT_CHANNEL = "coakka:intent";
2
+ export function createCoAkkaPreloadApi(ipcRenderer, channel = COAKKA_ELECTRON_INTENT_CHANNEL) {
3
+ return {
4
+ intent(intent) {
5
+ return ipcRenderer.invoke(channel, intent);
6
+ },
7
+ };
8
+ }
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "coakka-v2-connector-electron",
3
+ "version": "1.3.1",
4
+ "description": "Electron main-process intent bridge for the CoAkka runtime v2",
5
+ "license": "SEE LICENSE IN LICENSE.md",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ },
14
+ "./preload": {
15
+ "types": "./dist/preload.d.ts",
16
+ "import": "./dist/preload.js",
17
+ "require": "./dist/preload.cjs"
18
+ }
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "CONSUMING.md",
23
+ "LICENSE.md",
24
+ "README.md"
25
+ ],
26
+ "scripts": {
27
+ "build": "node scripts/build-package.mjs",
28
+ "verify": "npm run build",
29
+ "pack:release": "npm run build && node scripts/pack-release.mjs",
30
+ "smoke:packaged": "bash scripts/smoke-packaged-package.sh"
31
+ },
32
+ "dependencies": {
33
+ "coakka-v2-connector-node": "1.3.1"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "^24.0.0",
37
+ "typescript": "^5.8.3"
38
+ }
39
+ }