coakka-v2-connector-electron 2.5.3 → 3.1.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 CHANGED
@@ -1,10 +1,12 @@
1
1
  # Consuming CoAkka Runtime Connector For Electron
2
2
 
3
- This is the Electron connector for the polyglot, multi-language, multi-platform
4
- CoAkka Runtime ecosystem. Install it through your normal application package
5
- feed. Electron remains the application framework dependency; this package owns
6
- the CoAkka runtime intent bridge and consumes the Node connector as the
7
- main-process runtime host.
3
+ ## Version `3.1.1`
4
+
5
+ Electron `3.1.1` is the first Electron connector release on Core generation
6
+ `3.1`. It installs `coakka-v2-connector-node@3.1.2` as an exact dependency.
7
+ The Node connector includes Core 3.1 r2, build
8
+ `6789dd16210fc01f17cca4d2b66a592d1ac79121`, ABI 1, for macOS ARM64,
9
+ Linux ARM64/x64 and Windows ARM64/x64.
8
10
 
9
11
  Use the package only from the Electron main process and preload boundary:
10
12
 
@@ -13,3 +15,44 @@ Use the package only from the Electron main process and preload boundary:
13
15
  - renderer: call `window.coakka.intent(...)`
14
16
 
15
17
  Do not import the runtime connector directly from renderer code.
18
+
19
+ Use Electron 42 or later and let npm install the declared Node dependency
20
+ when you install the Electron connector.
21
+
22
+ Keep `contextIsolation: true`, `nodeIntegration: false` and `sandbox: true` on
23
+ the application window. Compile your preload source into one CommonJS file
24
+ with a JavaScript bundler: include `coakka-v2-connector-electron/preload` in the
25
+ bundle and leave only `electron` external. Neither a runtime owner nor native
26
+ library loading belongs in the preload. The renderer receives only the
27
+ intent methods exposed by the context bridge, not general-purpose IPC access.
28
+
29
+ Supply `authorize` when registering main-process IPC handlers. Check the
30
+ window, main frame and trusted document URL using Electron's main-process
31
+ event; return literal `true` only for an accepted sender. Do not trust an
32
+ intent's `source` string as sender identity. Reject untrusted navigation and
33
+ window creation according to the application's policy.
34
+
35
+ Remove registered IPC handlers and await runtime close on every exit path.
36
+ A close does not cancel or join an application handler already executing; cancel
37
+ and join business tasks separately before releasing their application resources.
38
+ Late handler results cannot reply through the closing native owner.
39
+ A failed duplicate handler registration preserves the existing handler.
40
+ Startup snapshots report the runtime's accepted values; omitted CPU and
41
+ connection preferences use `AUTO` and `MULTIPLEXED`. Renderer intent deadlines
42
+ remain bounded (2 seconds when omitted, at most 30 seconds), and each IPC
43
+ batch defaults to the accepted runtime queue capacity capped at 64 values.
44
+ The inherited ask path requires no host worker-pool tuning; one lazy bounded
45
+ main-process scheduler advances Core-owned tickets without allocating one
46
+ worker for every ask.
47
+ An explicit batch maximum may not exceed that capacity or 256. Batches run in
48
+ input order and are not atomic: completed items are not rolled back on failure.
49
+ These intent limits belong to the Electron application boundary; they are
50
+ not a second native capability or configuration table.
51
+
52
+ ## Shutdown timing
53
+
54
+ Closing retires native work before releasing its resources. Host scheduling
55
+ and storage affect that latency: macOS qualification observed occasional
56
+ Runtime/File shutdowns taking about 2.4 seconds. That observation is not a
57
+ hard maximum. Release application resources only after close has returned
58
+ or its Promise has settled.
@@ -28,4 +28,4 @@ substantially equivalent infrastructure service.
28
28
  It does not replace either license.
29
29
 
30
30
  Public guidance and stable links are available in the
31
- [CoAkka package licensing guide](https://github.com/phuong-tran/coakka-samples/blob/main/docs/package-licensing.md).
31
+ [CoAkka package licensing guide](https://github.com/phuong-tran/coakka-samples/blob/83c4dd7de7290df064e79fcbbca1f470458142a0/docs/common/package-licensing.md).
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # CoAkka Runtime Connector For Electron
2
2
 
3
3
  <p align="center">
4
- <img src="https://raw.githubusercontent.com/phuong-tran/coakka-samples/main/docs/assets/brand/coakka-logo.png" alt="CoAkka" width="480">
4
+ <img src="https://raw.githubusercontent.com/phuong-tran/coakka-samples/main/docs/common/assets/brand/coakka-logo.png" alt="CoAkka" width="480">
5
5
  </p>
6
6
 
7
7
  **This is the Electron connector in the polyglot, multi-language,
@@ -12,15 +12,22 @@ contract used by Node.js, the JVM, Python, Go, C#, Rust, Swift, and other
12
12
  connector lanes.
13
13
 
14
14
  Kubernetes is supported but not required. Use the public
15
- [Ecosystem Overview](https://github.com/phuong-tran/coakka-samples/blob/main/docs/ecosystem-overview.md)
16
- and [Compatibility Matrix](https://github.com/phuong-tran/coakka-publish/blob/main/docs/compatibility-matrix.md)
15
+ [Ecosystem Overview](https://github.com/phuong-tran/coakka-samples/blob/main/docs/common/ecosystem-overview.md)
16
+ and [Compatibility Matrix](https://github.com/phuong-tran/coakka-publish/blob/main/docs/coakka-runtime/reference/compatibility-matrix.md)
17
17
  to select an exact package and native platform tuple.
18
18
  Start with the [CoAkka Documentation](https://github.com/phuong-tran/coakka-samples/blob/main/docs/README.md)
19
19
  for concepts, integration paths, operations, and runnable samples.
20
20
 
21
- Minimum hosts: Electron 42 and Node.js 22 in the Electron main process. The
22
- native runtime remains owned by main-process code; renderer and preload code
23
- do not load it directly.
21
+ Use Electron 42 or later. The Electron main process owns the runtime. Preload
22
+ and renderer code use a small intent API over IPC.
23
+
24
+ ## Version `3.1.1`
25
+
26
+ Electron `3.1.1` is the first Electron connector release on Core generation
27
+ `3.1`. Its exact dependency `coakka-v2-connector-node@3.1.2` includes Core
28
+ 3.1 r2, build `6789dd16210fc01f17cca4d2b66a592d1ac79121`, ABI 1. npm installs
29
+ the Node dependency automatically. Its native images cover macOS ARM64,
30
+ Linux ARM64/x64 and Windows ARM64/x64.
24
31
 
25
32
  ## New To CoAkka
26
33
 
@@ -36,25 +43,14 @@ Use these public repositories to orient first:
36
43
  | `coakka-samples` | Runnable examples and code you can inspect first. | https://github.com/phuong-tran/coakka-samples |
37
44
  | `coakka-publish` | Released packages, native archives, manifests, checksums, compatibility matrix, and release notes. | https://github.com/phuong-tran/coakka-publish |
38
45
 
39
- Run the matching sample:
46
+ Install the connector with npm.
40
47
 
41
48
  ```sh
42
- git clone https://github.com/phuong-tran/coakka-samples.git
43
- cd coakka-samples
44
- bash run.sh runtime electron basic
49
+ npm install coakka-v2-connector-electron@3.1.1
45
50
  ```
46
51
 
47
- No-checkout npm smoke:
48
- https://github.com/phuong-tran/coakka-samples/blob/main/docs/first-npm-smoke.md
49
-
50
- Samples docs directory:
51
- https://github.com/phuong-tran/coakka-samples/tree/main/docs
52
-
53
- That smoke explains the runtime mental model first: keep real HTTP or IPC at
54
- the app edge, but replace fake backend HTTP used only for work owned by the
55
- same app or team with a CoAkka target and explicit reply/deadletter behavior.
56
-
57
- The boundary is intentionally strict:
52
+ The following example routes an intent from a sandboxed window to a named
53
+ handler in the main process and returns the handler's reply to the renderer.
58
54
 
59
55
  - renderer JavaScript sends an intent through `ipcRenderer.invoke`
60
56
  - preload exposes only a small `coakka.intent(...)` API
@@ -69,16 +65,18 @@ The main-process options can forward the shared `connectionStrategy` and
69
65
  `security` startup specs. Capability/config/security getters and atomic apply
70
66
  results are exposed on `ElectronRuntimeIntentBridge`; renderer/preload code
71
67
  still never receives credential material. See
72
- [Connection Strategies](https://github.com/phuong-tran/coakka-samples/blob/main/docs/connection-strategies.md),
73
- [TLS and mTLS](https://github.com/phuong-tran/coakka-samples/blob/main/docs/tls-and-mtls.md),
74
- and [Troubleshooting](https://github.com/phuong-tran/coakka-samples/blob/main/docs/troubleshooting.md).
68
+ [Connection Strategies](https://github.com/phuong-tran/coakka-samples/blob/main/docs/coakka-runtime/reference/connection-strategies.md),
69
+ [TLS and mTLS](https://github.com/phuong-tran/coakka-samples/blob/main/docs/coakka-runtime/reference/tls-and-mtls.md),
70
+ and [Troubleshooting](https://github.com/phuong-tran/coakka-samples/blob/main/docs/coakka-runtime/operations/troubleshooting.md).
75
71
 
76
72
  ## Main Process
77
73
 
78
74
  ```js
79
- import { ipcMain } from "electron";
75
+ import { BrowserWindow, ipcMain } from "electron";
76
+ import { pathToFileURL } from "node:url";
80
77
  import {
81
78
  ElectronRuntimeIntentBridge,
79
+ localRoute,
82
80
  registerElectronIntentIpcHandler,
83
81
  } from "coakka-v2-connector-electron";
84
82
 
@@ -86,7 +84,7 @@ const target = "samples.electron.intent.echo";
86
84
  const bridge = ElectronRuntimeIntentBridge.start({
87
85
  systemName: "electron-app",
88
86
  nodeId: "electron-app-main",
89
- defaultTarget: target,
87
+ routes: [localRoute(target)],
90
88
  });
91
89
 
92
90
  bridge.registerJsonIntentHandler(target, async (intent) => ({
@@ -94,11 +92,32 @@ bridge.registerJsonIntentHandler(target, async (intent) => ({
94
92
  echo: intent.payload,
95
93
  }));
96
94
 
97
- registerElectronIntentIpcHandler(ipcMain, bridge);
95
+ // app.whenReady() has resolved. These are your application's absolute paths.
96
+ const window = new BrowserWindow({
97
+ webPreferences: {
98
+ preload: bundledPreloadPath,
99
+ contextIsolation: true,
100
+ nodeIntegration: false,
101
+ sandbox: true,
102
+ },
103
+ });
104
+ const trustedUrl = pathToFileURL(rendererHtmlPath).href;
105
+ const unregister = registerElectronIntentIpcHandler(ipcMain, bridge, {
106
+ authorize: (event) => event.sender === window.webContents &&
107
+ event.senderFrame === window.webContents.mainFrame &&
108
+ event.senderFrame.url === trustedUrl,
109
+ });
110
+ await window.loadFile(rendererHtmlPath);
111
+ // At application shutdown: unregister(), then await bridge.close().
98
112
  ```
99
113
 
100
114
  ## Preload
101
115
 
116
+ Bundle this application-owned source into one CommonJS preload file, leaving
117
+ only `electron` external. A sandboxed preload cannot load arbitrary package
118
+ files with `require`; do not disable the sandbox to make package imports work.
119
+ Use that bundled file as `bundledPreloadPath` above.
120
+
102
121
  ```js
103
122
  const { contextBridge, ipcRenderer } = require("electron");
104
123
  const { createCoAkkaPreloadApi } = require("coakka-v2-connector-electron/preload");
@@ -124,42 +143,62 @@ const result = await window.coakka.intent({
124
143
  });
125
144
  ```
126
145
 
127
- ## Smoke
128
-
129
- ```sh
130
- npm run build
131
- bash scripts/smoke-packaged-package.sh
132
- ```
133
-
134
- The packaged smoke installs the generated package into a disposable Electron
135
- app, loads a hidden renderer window, sends one renderer intent through preload
136
- and IPC, and verifies that the main process handles it through the runtime host
137
- exposed by its packaged Node connector dependency.
138
-
139
- Package metadata records the exact native generation, release channel, and
140
- supported platform tuple. Contact: `gabrielgun1983@gmail.com`.
146
+ ## Lifecycle And Admission
147
+
148
+ For sustained renderer traffic, `intentBatch([...])` amortizes a structured-clone
149
+ IPC round trip. Items execute sequentially through the same runtime ask path
150
+ and preserve order. The default maximum is the accepted queue capacity capped
151
+ at 64 intents; an explicit maximum cannot exceed that capacity or 256. A batch
152
+ is not atomic: earlier items remain completed if a later item fails, and later
153
+ items are not started. Prefer single intents for individual completion latency.
154
+
155
+ The application must authorize every single and batch IPC invocation. Only an
156
+ explicit `true` permits delivery; exceptions and every other value reject the
157
+ invocation. Match the expected window, main frame and trusted document, not
158
+ just a renderer-supplied source name. Remove IPC handlers when their owner
159
+ closes. Do not expose `ipcRenderer` itself through the context bridge.
160
+
161
+ Startup options are submitted to the native runtime; use
162
+ `runtimeStartupConfig()` for accepted configuration rather than reconstructing
163
+ it from input. Omitted policy uses `AUTO` and `MULTIPLEXED`. Main owns handlers
164
+ and runtime lifetime; a refused duplicate registration leaves the accepted
165
+ handler intact. Await `close()` to retire native ownership and registered
166
+ callbacks; a reader waiting for handler capacity is also awakened. Close does
167
+ not cancel or join already-running application handlers. Their late results
168
+ cannot submit native replies after close begins. Cancel/join application tasks
169
+ separately before releasing resources those tasks still use.
170
+ File and Stream Lane owners must also be explicitly closed by their owners.
171
+
172
+ Electron inherits the Node package's lazy bounded ask scheduler in the main
173
+ process. It requires no host worker-pool tuning and does not allocate one worker
174
+ per ask. The Electron wrapper adds no second scheduler or response matcher;
175
+ Core still owns ticket matching, timeout/cancellation and completion notifications.
176
+
177
+ Read the bundled `CONSUMING.md` for preload and renderer setup. The
178
+ [current package ledger](https://github.com/phuong-tran/coakka-samples/blob/main/docs/common/current-packages.md)
179
+ records registry availability.
141
180
 
142
181
  ## File Lane
143
182
 
144
183
  The Node dependency exposes `FileLane` to trusted Electron main-process code.
145
184
  Do not forward raw file paths, authorization tokens, or lane methods through
146
- preload/renderer IPC. See the shared [file-lane contract](https://github.com/phuong-tran/coakka-samples/blob/main/docs/runtime-file-transfer.md).
185
+ preload/renderer IPC. See the shared [file-lane contract](https://github.com/phuong-tran/coakka-samples/blob/main/docs/coakka-runtime/guides/runtime-file-transfer.md).
147
186
 
148
187
  ## Stream Lane
149
188
 
150
- Version `2.5.3` contains owner-aware File and Stream Lane connector surfaces for Electron main
151
- over exact native generation `2.5.1+26f7944de4a4e0598845a54e4775f9463a9e33be`. Keep runtime ownership in the
152
- main process and follow the public
153
- [streaming contract](https://github.com/phuong-tran/coakka-samples/blob/main/docs/runtime-streaming.md).
189
+ The matching Node dependency provides owner-aware File and Stream Lane surfaces
190
+ for trusted Electron main-process code. Keep runtime ownership in the main
191
+ process and follow the public
192
+ [streaming contract](https://github.com/phuong-tran/coakka-samples/blob/main/docs/coakka-runtime/guides/runtime-streaming.md).
154
193
  Electron re-exports Node's `FileReceiveGrant`, `StreamPublishGrant`, and
155
194
  `openOwned`/`prepare*Grant` methods only to main-process code. Follow the
156
- [owner-grant ONE/ALL sample](https://github.com/phuong-tran/coakka-samples/blob/main/docs/runtime-lane-owner-grants.md)
195
+ [owner-grant ONE/ALL sample](https://github.com/phuong-tran/coakka-samples/blob/main/docs/coakka-runtime/reference/runtime-lane-owner-grants.md)
157
196
  and keep serialized grants out of preload and renderer IPC.
158
197
 
159
198
  ## AI-Assisted Integration
160
199
 
161
200
  Before generating Electron integration code, read the public
162
- [AI-assisted integration guide](https://github.com/phuong-tran/coakka-samples/blob/main/docs/ai-assisted-integration.md)
201
+ [AI-assisted integration guide](https://github.com/phuong-tran/coakka-samples/blob/main/docs/coakka-runtime/guides/ai-assisted-integration.md)
163
202
  and the runnable Electron sample. Connection policy and native lane ownership
164
203
  belong to Electron main; renderer code sends validated intent only.
165
204
 
@@ -170,11 +209,11 @@ belong to Electron main; renderer code sends validated intent only.
170
209
 
171
210
  Connector source, generated bindings, type declarations, examples, and package
172
211
  documentation use the [Apache License, Version 2.0](https://github.com/phuong-tran/coakka-samples/blob/main/LICENSE).
173
- Bundled Native Core files use the [CoAkka Native Artifact License 1.2](https://github.com/phuong-tran/coakka-samples/blob/main/NATIVE-LICENSE.md).
212
+ Native Core files in the Node dependency use the [CoAkka Native Artifact License 1.2](https://github.com/phuong-tran/coakka-samples/blob/main/NATIVE-LICENSE.md).
174
213
  Those native terms permit ordinary application and SaaS use but require a
175
214
  separate agreement to sell or offer CoAkka itself as managed runtime or
176
215
  infrastructure.
177
216
 
178
- See [CoAkka Package Licensing](https://github.com/phuong-tran/coakka-samples/blob/main/docs/package-licensing.md)
217
+ See [CoAkka Package Licensing](https://github.com/phuong-tran/coakka-samples/blob/main/docs/common/package-licensing.md)
179
218
  for the file-scope map. The package also carries offline `LICENSE`,
180
219
  `NATIVE-LICENSE.md`, `PACKAGE-LICENSE.md`, and `NOTICE` copies.
package/dist/index.d.ts CHANGED
@@ -1,13 +1,14 @@
1
- import { type RuntimeCapabilitiesSnapshot, type RuntimeTcpConnectionApplyResult, type RuntimeTcpConnectionConfigSnapshot, type RuntimeTcpConnectionStrategySpec, type RuntimeTcpSecurityApplyResult, type RuntimeTcpSecurityInfoSnapshot, type RuntimeTcpSecuritySpec } from "coakka-v2-connector-node";
2
- export { RuntimeCapability, RuntimeTcpConnectionMode, RuntimeTcpSecurityMode, RuntimeTlsReloadMode, supportsRuntimeCapabilities, } from "coakka-v2-connector-node";
1
+ import { type ConnectorStartSpec, type RuntimeClientStats, type RuntimeCapabilitiesSnapshot, type RuntimeDeliverySnapshot, type RuntimeInfoSnapshot, type RuntimeStartupSnapshot, type RuntimeTcpConnectionApplyResult, type RuntimeTcpConnectionConfigSnapshot, type RuntimeTcpConnectionStrategySpec, type RuntimeTcpSecurityApplyResult, type RuntimeTcpSecurityInfoSnapshot, type RuntimeTcpSecuritySpec } from "coakka-v2-connector-node";
2
+ export { EndpointFlag, RuntimeCapability, RuntimeNetworkMode, RuntimeTcpConnectionMode, RuntimeTcpSecurityMode, RuntimeTlsReloadMode, RouteStrategy, embeddedNetwork, localRoute, networkNode, outboundOnlyNetwork, supportsRuntimeCapabilities, type EndpointSpec, type RouteSpec, type RuntimeNetworkConfig, } from "coakka-v2-connector-node";
3
3
  /**
4
4
  * File and Stream Lanes are available only to trusted Electron main-process
5
5
  * code. They are intentionally absent from preload and renderer intents so
6
6
  * file paths and bearer grants never cross that boundary implicitly.
7
7
  */
8
8
  export { FILE_LANE_DETAIL_MAX_BYTES, FILE_LANE_SHA256_BYTES, LANE_OWNER_GRANTS_FEATURE, FileLane, FileLaneError, FileLaneFlag, FileLaneSecurityMode, FileReceiveGrant, FileTransferDirection, FileTransferResult, FileTransferState, LaneOwnerGrantUnavailableError, STREAM_LANE_DETAIL_MAX_BYTES, STREAM_LANE_MAX_FRAME_BYTES, STREAM_LANE_MAX_WINDOW_BYTES, StreamConsumerDecision, StreamDirection, StreamFrameFlag, StreamLane, StreamLaneError, StreamLaneFlag, StreamLaneSecurityMode, StreamPublishGrant, StreamPressureReason, StreamPressureState, StreamResult, StreamSourceSignal, StreamState, type FileDigest, type FileLaneConfig, type FileLaneSecurityConfig, type FileLaneStats, type FileReceiveSpec, type FileSendSpec, type FileTransferSnapshot, type LaneOwnerConfig, type LaneOwnerEndpoint, type StreamConsumer, type StreamFrameMetadata, type StreamLaneConfig, type StreamLaneSecurityConfig, type StreamLaneStats, type StreamPressureSnapshot, type StreamPublishSpec, type StreamSessionSnapshot, type StreamSource, type StreamSourceFrame, type StreamSubscribeSpec, } from "coakka-v2-connector-node";
9
- export declare const COAKKA_ELECTRON_CONNECTOR_VERSION = "2.5.3";
9
+ export declare const COAKKA_ELECTRON_CONNECTOR_VERSION = "3.1.1";
10
10
  export declare const COAKKA_ELECTRON_INTENT_CHANNEL = "coakka:intent";
11
+ export declare const COAKKA_ELECTRON_INTENT_BATCH_CHANNEL = "coakka:intent-batch";
11
12
  export interface ElectronIntentPayloadIdentity {
12
13
  messageType: string;
13
14
  payloadSchemaVersion?: number;
@@ -29,47 +30,50 @@ export interface ElectronIntentResult {
29
30
  target: string;
30
31
  operation: string;
31
32
  payload: Record<string, unknown>;
32
- runtime: {
33
- generation: number;
34
- delivered: number;
35
- matchedResponses: number;
36
- matchedDeadletters: number;
33
+ payloadIdentity: {
34
+ messageType: string;
35
+ payloadSchemaVersion: number;
36
+ payloadFormat: "json";
37
37
  };
38
38
  }
39
- export interface ElectronRuntimeIntentBridgeOptions {
40
- systemName: string;
41
- nodeId: string;
42
- defaultTarget: string;
43
- routePort?: number;
44
- queueCapacity?: number;
45
- strictNoDrop?: boolean;
39
+ export interface ElectronRuntimeIntentBridgeOptions extends ConnectorStartSpec {
46
40
  runtimeLibPath?: string;
47
- connectionStrategy?: RuntimeTcpConnectionStrategySpec;
48
- security?: RuntimeTcpSecuritySpec;
49
41
  }
50
42
  export type ElectronJsonIntentHandler = (intent: ElectronIntentEnvelope) => Record<string, unknown> | Promise<Record<string, unknown>>;
51
43
  export interface IpcMainLike {
52
- handle(channel: string, listener: (event: unknown, intent: ElectronIntentEnvelope) => Promise<ElectronIntentResult>): void;
44
+ handle(channel: string, listener: (event: unknown, payload: unknown) => Promise<unknown>): void;
53
45
  removeHandler(channel: string): void;
54
46
  }
47
+ export interface ElectronIntentIpcRegistrationOptions {
48
+ channel?: string;
49
+ batchChannel?: string;
50
+ /** Defaults to Core's accepted queue capacity, capped at 64 IPC values. */
51
+ maximumBatchSize?: number;
52
+ /** App-owned sender/frame trust decision; only literal true permits dispatch. */
53
+ authorize(event: unknown): boolean | Promise<boolean>;
54
+ }
55
55
  export declare class ElectronRuntimeIntentBridge {
56
56
  private readonly runtimeHost;
57
- readonly defaultTarget: string;
58
57
  static start(options: ElectronRuntimeIntentBridgeOptions): ElectronRuntimeIntentBridge;
59
58
  private readonly handlers;
60
59
  private closed;
60
+ private closePromise;
61
61
  private constructor();
62
62
  registerJsonIntentHandler(target: string, handler: ElectronJsonIntentHandler): void;
63
63
  handleIntent(intent: ElectronIntentEnvelope): Promise<ElectronIntentResult>;
64
+ runtimeInfo(): RuntimeInfoSnapshot;
65
+ /** Connector-owned counters for trusted main-process diagnostics only. */
66
+ connectorStats(): RuntimeClientStats;
67
+ runtimeStartupConfig(): RuntimeStartupSnapshot & {
68
+ delivery: RuntimeDeliverySnapshot;
69
+ };
64
70
  runtimeCapabilities(): RuntimeCapabilitiesSnapshot;
65
71
  tcpConnectionConfig(): RuntimeTcpConnectionConfigSnapshot;
66
72
  tcpSecurityInfo(): RuntimeTcpSecurityInfoSnapshot;
67
- startupConnectionResult(): RuntimeTcpConnectionApplyResult | null;
68
- startupSecurityResult(): RuntimeTcpSecurityApplyResult | null;
69
73
  applyTcpConnectionStrategy(spec: RuntimeTcpConnectionStrategySpec): RuntimeTcpConnectionApplyResult;
70
74
  applyTcpSecurity(spec: RuntimeTcpSecuritySpec): RuntimeTcpSecurityApplyResult;
71
- close(): void;
75
+ close(): Promise<void>;
72
76
  private createRuntimeHandler;
73
77
  private requireOpen;
74
78
  }
75
- export declare function registerElectronIntentIpcHandler(ipcMain: IpcMainLike, bridge: ElectronRuntimeIntentBridge, channel?: string): () => void;
79
+ export declare function registerElectronIntentIpcHandler(ipcMain: IpcMainLike, bridge: ElectronRuntimeIntentBridge, options: ElectronIntentIpcRegistrationOptions): () => void;
package/dist/index.js CHANGED
@@ -1,191 +1 @@
1
- import { DeliveryHint, EndpointFlag, NodeRuntimeClient, PayloadFormat, PayloadIdentity, RuntimeHost, } from "coakka-v2-connector-node";
2
- export { RuntimeCapability, RuntimeTcpConnectionMode, RuntimeTcpSecurityMode, RuntimeTlsReloadMode, supportsRuntimeCapabilities, } from "coakka-v2-connector-node";
3
- /**
4
- * File and Stream Lanes are available only to trusted Electron main-process
5
- * code. They are intentionally absent from preload and renderer intents so
6
- * file paths and bearer grants never cross that boundary implicitly.
7
- */
8
- export { FILE_LANE_DETAIL_MAX_BYTES, FILE_LANE_SHA256_BYTES, LANE_OWNER_GRANTS_FEATURE, FileLane, FileLaneError, FileLaneFlag, FileLaneSecurityMode, FileReceiveGrant, FileTransferDirection, FileTransferResult, FileTransferState, LaneOwnerGrantUnavailableError, STREAM_LANE_DETAIL_MAX_BYTES, STREAM_LANE_MAX_FRAME_BYTES, STREAM_LANE_MAX_WINDOW_BYTES, StreamConsumerDecision, StreamDirection, StreamFrameFlag, StreamLane, StreamLaneError, StreamLaneFlag, StreamLaneSecurityMode, StreamPublishGrant, StreamPressureReason, StreamPressureState, StreamResult, StreamSourceSignal, StreamState, } from "coakka-v2-connector-node";
9
- export const COAKKA_ELECTRON_CONNECTOR_VERSION = "2.5.3";
10
- export const COAKKA_ELECTRON_INTENT_CHANNEL = "coakka:intent";
11
- const DEFAULT_ROUTE_PORT = 19481;
12
- export class ElectronRuntimeIntentBridge {
13
- runtimeHost;
14
- defaultTarget;
15
- static start(options) {
16
- const target = requireNonBlank(options.defaultTarget, "defaultTarget");
17
- const startSpec = {
18
- systemName: requireNonBlank(options.systemName, "systemName"),
19
- nodeId: requireNonBlank(options.nodeId, "nodeId"),
20
- queueCapacity: options.queueCapacity ?? 64,
21
- strictNoDrop: options.strictNoDrop ?? true,
22
- generation: 1,
23
- connectionStrategy: options.connectionStrategy,
24
- security: options.security,
25
- routes: [
26
- {
27
- target,
28
- endpoints: [
29
- {
30
- host: "127.0.0.1",
31
- port: options.routePort ?? DEFAULT_ROUTE_PORT,
32
- flags: EndpointFlag.LOCAL,
33
- },
34
- ],
35
- },
36
- ],
37
- };
38
- return new ElectronRuntimeIntentBridge(RuntimeHost.start(startSpec, options.runtimeLibPath), target);
39
- }
40
- handlers = new Map();
41
- closed = false;
42
- constructor(runtimeHost, defaultTarget) {
43
- this.runtimeHost = runtimeHost;
44
- this.defaultTarget = defaultTarget;
45
- }
46
- registerJsonIntentHandler(target, handler) {
47
- const normalizedTarget = requireNonBlank(target, "target");
48
- this.handlers.set(normalizedTarget, handler);
49
- this.runtimeHost.registerHandler(normalizedTarget, this.createRuntimeHandler(normalizedTarget), true);
50
- }
51
- async handleIntent(intent) {
52
- this.requireOpen();
53
- const normalized = normalizeIntent(intent);
54
- const identity = toPayloadIdentity(normalized.payloadIdentity);
55
- const response = await this.runtimeHost.askJson(normalized.source, normalized.target, normalized.payload, identity, normalized.timeoutMs ?? 2_000, normalized.operation, DeliveryHint.ROUTER_DEFAULT, normalized.headers ?? {});
56
- const clientStats = this.runtimeHost.clientStats();
57
- const runtimeStats = this.runtimeHost.stats();
58
- return {
59
- intentId: normalized.intentId,
60
- source: normalized.source,
61
- target: normalized.target,
62
- operation: normalized.operation,
63
- payload: response,
64
- runtime: {
65
- generation: runtimeStats.appliedGeneration,
66
- delivered: clientStats.deliveredRequests,
67
- matchedResponses: clientStats.matchedResponses,
68
- matchedDeadletters: clientStats.matchedDeadletters,
69
- },
70
- };
71
- }
72
- runtimeCapabilities() {
73
- return this.runtimeHost.runtimeCapabilities();
74
- }
75
- tcpConnectionConfig() {
76
- return this.runtimeHost.tcpConnectionConfig();
77
- }
78
- tcpSecurityInfo() {
79
- return this.runtimeHost.tcpSecurityInfo();
80
- }
81
- startupConnectionResult() {
82
- return this.runtimeHost.startupConnectionResult();
83
- }
84
- startupSecurityResult() {
85
- return this.runtimeHost.startupSecurityResult();
86
- }
87
- applyTcpConnectionStrategy(spec) {
88
- return this.runtimeHost.applyTcpConnectionStrategy(spec);
89
- }
90
- applyTcpSecurity(spec) {
91
- return this.runtimeHost.applyTcpSecurity(spec);
92
- }
93
- close() {
94
- if (this.closed) {
95
- return;
96
- }
97
- this.closed = true;
98
- this.runtimeHost.close();
99
- }
100
- createRuntimeHandler(target) {
101
- return async (request) => {
102
- const handler = this.handlers.get(target);
103
- if (handler == null) {
104
- throw new Error(`no Electron intent handler registered for target=${target}`);
105
- }
106
- const payload = JSON.parse(Buffer.from(request.payload).toString("utf8"));
107
- const resultPayload = await handler({
108
- intentId: request.message_id,
109
- source: request.source,
110
- target,
111
- operation: "intent",
112
- payload,
113
- payloadIdentity: {
114
- messageType: request.message_type,
115
- payloadSchemaVersion: request.payload_schema_version,
116
- payloadFormat: "json",
117
- },
118
- headers: request.headers,
119
- });
120
- return NodeRuntimeClient.makeJsonReplyFromRequestIdentity(request, target, resultPayload);
121
- };
122
- }
123
- requireOpen() {
124
- if (this.closed) {
125
- throw new Error("Electron runtime intent bridge is closed");
126
- }
127
- }
128
- }
129
- export function registerElectronIntentIpcHandler(ipcMain, bridge, channel = COAKKA_ELECTRON_INTENT_CHANNEL) {
130
- ipcMain.handle(channel, async (_event, intent) => bridge.handleIntent(intent));
131
- return () => ipcMain.removeHandler(channel);
132
- }
133
- function normalizeIntent(intent) {
134
- if (intent == null || typeof intent !== "object") {
135
- throw new Error("intent envelope is required");
136
- }
137
- return {
138
- intentId: requireNonBlank(intent.intentId, "intentId"),
139
- source: requireNonBlank(intent.source, "source"),
140
- target: requireNonBlank(intent.target, "target"),
141
- operation: requireNonBlank(intent.operation, "operation"),
142
- payload: requireJsonObject(intent.payload, "payload"),
143
- payloadIdentity: requirePayloadIdentity(intent.payloadIdentity),
144
- timeoutMs: normalizeTimeout(intent.timeoutMs),
145
- headers: normalizeHeaders(intent.headers),
146
- };
147
- }
148
- function toPayloadIdentity(identity) {
149
- return new PayloadIdentity(identity.messageType, identity.payloadSchemaVersion ?? 1, PayloadFormat.JSON).requireTyped("Electron intent payloadIdentity");
150
- }
151
- function requirePayloadIdentity(identity) {
152
- if (identity == null || typeof identity !== "object") {
153
- throw new Error("payloadIdentity is required");
154
- }
155
- return {
156
- messageType: requireNonBlank(identity.messageType, "payloadIdentity.messageType"),
157
- payloadSchemaVersion: identity.payloadSchemaVersion ?? 1,
158
- payloadFormat: "json",
159
- };
160
- }
161
- function requireJsonObject(value, what) {
162
- if (value == null || typeof value !== "object" || Array.isArray(value)) {
163
- throw new Error(`${what} must be a JSON object`);
164
- }
165
- return value;
166
- }
167
- function normalizeHeaders(headers) {
168
- if (headers == null) {
169
- return {};
170
- }
171
- const normalized = {};
172
- for (const [key, value] of Object.entries(headers)) {
173
- normalized[requireNonBlank(key, "header key")] = String(value);
174
- }
175
- return normalized;
176
- }
177
- function normalizeTimeout(timeoutMs) {
178
- if (timeoutMs == null) {
179
- return undefined;
180
- }
181
- if (!Number.isInteger(timeoutMs) || timeoutMs < 1) {
182
- throw new Error("timeoutMs must be a positive integer");
183
- }
184
- return timeoutMs;
185
- }
186
- function requireNonBlank(value, what) {
187
- if (typeof value !== "string" || value.trim() === "") {
188
- throw new Error(`${what} is required`);
189
- }
190
- return value;
191
- }
1
+ var S=Object.defineProperty;var a=(e,t)=>S(e,"name",{value:t,configurable:!0});import{DeliveryHint as w,NodeRuntimeClient as T,PayloadFormat as y,PayloadIdentity as f,RuntimeHost as I}from"coakka-v2-connector-node";import{EndpointFlag as z,RuntimeCapability as j,RuntimeNetworkMode as k,RuntimeTcpConnectionMode as B,RuntimeTcpSecurityMode as x,RuntimeTlsReloadMode as D,RouteStrategy as J,embeddedNetwork as V,localRoute as $,networkNode as v,outboundOnlyNetwork as K,supportsRuntimeCapabilities as U}from"coakka-v2-connector-node";import{FILE_LANE_DETAIL_MAX_BYTES as Y,FILE_LANE_SHA256_BYTES as G,LANE_OWNER_GRANTS_FEATURE as W,FileLane as Q,FileLaneError as Z,FileLaneFlag as ee,FileLaneSecurityMode as te,FileReceiveGrant as re,FileTransferDirection as ne,FileTransferResult as oe,FileTransferState as ae,LaneOwnerGrantUnavailableError as ie,STREAM_LANE_DETAIL_MAX_BYTES as se,STREAM_LANE_MAX_FRAME_BYTES as ue,STREAM_LANE_MAX_WINDOW_BYTES as le,StreamConsumerDecision as ce,StreamDirection as me,StreamFrameFlag as de,StreamLane as pe,StreamLaneError as he,StreamLaneFlag as ye,StreamLaneSecurityMode as fe,StreamPublishGrant as Ee,StreamPressureReason as Se,StreamPressureState as we,StreamResult as Te,StreamSourceSignal as Ie,StreamState as ge}from"coakka-v2-connector-node";var L="3.1.1",g="coakka:intent",_="coakka:intent-batch",C=2e3,p=3e4,h=class e{static{a(this,"ElectronRuntimeIntentBridge")}runtimeHost;static start(t){let{runtimeLibPath:r,...n}=t;return new e(I.start(n,r))}handlers=new Map;closed=!1;closePromise=null;constructor(t){this.runtimeHost=t}registerJsonIntentHandler(t,r){this.requireOpen();let n=i(t,"target");if(typeof r!="function")throw new TypeError("Electron intent handler must be a function");this.runtimeHost.registerHandler(n,this.createRuntimeHandler(n),!0),this.handlers.set(n,r)}async handleIntent(t){this.requireOpen();let r=N(t),n=O(r.payloadIdentity),o=await this.runtimeHost.askTyped(r.source,r.target,Buffer.from(JSON.stringify(r.payload)),n,r.timeoutMs??C,r.operation,w.ROUTER_DEFAULT,r.headers??{}),s=new f(o.message_type,o.payload_schema_version,o.payload_format).requireTyped("Electron intent response");if(s.payloadFormat!==y.JSON)throw new Error("Electron intent response payloadFormat must be json");let u=m(JSON.parse(Buffer.from(o.payload).toString("utf8")),"response payload");return{intentId:r.intentId,source:r.source,target:r.target,operation:r.operation,payload:u,payloadIdentity:{messageType:s.messageType,payloadSchemaVersion:s.payloadSchemaVersion,payloadFormat:"json"}}}runtimeInfo(){return this.requireOpen(),this.runtimeHost.runtimeInfo()}connectorStats(){return this.requireOpen(),this.runtimeHost.clientStats()}runtimeStartupConfig(){return this.requireOpen(),this.runtimeHost.runtimeStartupConfig()}runtimeCapabilities(){return this.requireOpen(),this.runtimeHost.runtimeCapabilities()}tcpConnectionConfig(){return this.requireOpen(),this.runtimeHost.tcpConnectionConfig()}tcpSecurityInfo(){return this.requireOpen(),this.runtimeHost.tcpSecurityInfo()}applyTcpConnectionStrategy(t){return this.requireOpen(),this.runtimeHost.applyTcpConnectionStrategy(t)}applyTcpSecurity(t){return this.requireOpen(),this.runtimeHost.applyTcpSecurity(t)}close(){return this.closePromise!=null?this.closePromise:(this.closed=!0,this.handlers.clear(),this.closePromise=this.runtimeHost.close(),this.closePromise)}createRuntimeHandler(t){return async r=>{let n=this.handlers.get(t);if(n==null)throw new Error(`no Electron intent handler registered for target=${t}`);let o=m(JSON.parse(Buffer.from(r.payload).toString("utf8")),"request payload"),s=await n({intentId:r.message_id,source:r.source,target:t,operation:i(r.headers.operation,"request operation"),payload:o,payloadIdentity:{messageType:r.message_type,payloadSchemaVersion:r.payload_schema_version,payloadFormat:"json"},headers:r.headers});return T.makeJsonReplyFromRequestIdentity(r,t,m(s,"handler response payload"))}}requireOpen(){if(this.closed)throw new Error("Electron runtime intent bridge is closed")}};function P(e,t,r){let n=i(r.channel??g,"IPC channel"),o=i(r.batchChannel??_,"IPC batch channel");if(n===o)throw new Error("Electron intent and batch IPC channels must be distinct");if(typeof r.authorize!="function")throw new Error("Electron intent IPC registration requires an authorize policy");let s=t.runtimeStartupConfig().queueCapacity,u=r.maximumBatchSize??Math.min(s,64);if(!Number.isInteger(u)||u<1||u>s||u>256)throw new Error(`maximumBatchSize must be an integer in 1..${Math.min(s,256)}`);e.handle(n,async(c,l)=>{if(await r.authorize(c)!==!0)throw new Error("Electron intent IPC sender is not authorized");return t.handleIntent(l)});try{e.handle(o,async(c,l)=>{if(await r.authorize(c)!==!0)throw new Error("Electron intent IPC sender is not authorized");if(!Array.isArray(l)||l.length<1||l.length>u)throw new Error(`Electron intent batch must contain 1..${u} intents`);let d=[];for(let E of l)d.push(await t.handleIntent(E));return d})}catch(c){throw e.removeHandler(n),c}return()=>{e.removeHandler(n),e.removeHandler(o)}}a(P,"registerElectronIntentIpcHandler");function N(e){if(e==null||typeof e!="object")throw new Error("intent envelope is required");return{intentId:i(e.intentId,"intentId"),source:i(e.source,"source"),target:i(e.target,"target"),operation:i(e.operation,"operation"),payload:m(e.payload,"payload"),payloadIdentity:A(e.payloadIdentity),timeoutMs:R(e.timeoutMs),headers:b(e.headers)}}a(N,"normalizeIntent");function O(e){return new f(e.messageType,e.payloadSchemaVersion??1,y.JSON).requireTyped("Electron intent payloadIdentity")}a(O,"toPayloadIdentity");function A(e){if(e==null||typeof e!="object")throw new Error("payloadIdentity is required");if(e.payloadFormat!=null&&e.payloadFormat!=="json")throw new Error("payloadIdentity.payloadFormat must be json");let t=e.payloadSchemaVersion??1;if(!Number.isInteger(t)||t<1||t>4294967295)throw new Error("payloadIdentity.payloadSchemaVersion must be an integer in 1..4294967295");return{messageType:i(e.messageType,"payloadIdentity.messageType"),payloadSchemaVersion:t,payloadFormat:"json"}}a(A,"requirePayloadIdentity");function m(e,t){if(e==null||typeof e!="object"||Array.isArray(e))throw new Error(`${t} must be a JSON object`);return e}a(m,"requireJsonObject");function b(e){if(e==null)return{};let t=Object.create(null);for(let[r,n]of Object.entries(e)){let o=i(r,"header key");if(["method","operation"].includes(o.toLowerCase()))throw new Error(`headers.${o} is reserved by the intent envelope`);if(typeof n!="string")throw new Error(`headers.${o} must be a string`);t[o]=n}return t}a(b,"normalizeHeaders");function R(e){if(e!=null){if(!Number.isInteger(e)||e<1||e>p)throw new Error(`timeoutMs must be an integer in 1..${p}`);return e}}a(R,"normalizeTimeout");function i(e,t){if(typeof e!="string"||e.trim()==="")throw new Error(`${t} is required`);return e}a(i,"requireNonBlank");export{L as COAKKA_ELECTRON_CONNECTOR_VERSION,_ as COAKKA_ELECTRON_INTENT_BATCH_CHANNEL,g as COAKKA_ELECTRON_INTENT_CHANNEL,h as ElectronRuntimeIntentBridge,z as EndpointFlag,Y as FILE_LANE_DETAIL_MAX_BYTES,G as FILE_LANE_SHA256_BYTES,Q as FileLane,Z as FileLaneError,ee as FileLaneFlag,te as FileLaneSecurityMode,re as FileReceiveGrant,ne as FileTransferDirection,oe as FileTransferResult,ae as FileTransferState,W as LANE_OWNER_GRANTS_FEATURE,ie as LaneOwnerGrantUnavailableError,J as RouteStrategy,j as RuntimeCapability,k as RuntimeNetworkMode,B as RuntimeTcpConnectionMode,x as RuntimeTcpSecurityMode,D as RuntimeTlsReloadMode,se as STREAM_LANE_DETAIL_MAX_BYTES,ue as STREAM_LANE_MAX_FRAME_BYTES,le as STREAM_LANE_MAX_WINDOW_BYTES,ce as StreamConsumerDecision,me as StreamDirection,de as StreamFrameFlag,pe as StreamLane,he as StreamLaneError,ye as StreamLaneFlag,fe as StreamLaneSecurityMode,Se as StreamPressureReason,we as StreamPressureState,Ee as StreamPublishGrant,Te as StreamResult,Ie as StreamSourceSignal,ge as StreamState,V as embeddedNetwork,$ as localRoute,v as networkNode,K as outboundOnlyNetwork,P as registerElectronIntentIpcHandler,U as supportsRuntimeCapabilities};
package/dist/preload.cjs CHANGED
@@ -1,16 +1 @@
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
- };
1
+ "use strict";var o=Object.defineProperty;var s=Object.getOwnPropertyDescriptor;var A=Object.getOwnPropertyNames;var k=Object.prototype.hasOwnProperty;var E=(r,t)=>o(r,"name",{value:t,configurable:!0});var C=(r,t)=>{for(var n in t)o(r,n,{get:t[n],enumerable:!0})},u=(r,t,n,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of A(t))!k.call(r,i)&&i!==n&&o(r,i,{get:()=>t[i],enumerable:!(e=s(t,i))||e.enumerable});return r};var T=r=>u(o({},"__esModule",{value:!0}),r);var a={};C(a,{COAKKA_ELECTRON_INTENT_BATCH_CHANNEL:()=>N,COAKKA_ELECTRON_INTENT_CHANNEL:()=>c,createCoAkkaPreloadApi:()=>_});module.exports=T(a);var c="coakka:intent",N="coakka:intent-batch";function _(r,t=c,n=N){if(typeof t!="string"||t.trim()==="")throw new Error("Electron intent IPC channel is required");if(typeof n!="string"||n.trim()==="")throw new Error("Electron intent batch IPC channel is required");if(t===n)throw new Error("Electron intent and batch IPC channels must be distinct");return{intent(e){return r.invoke(t,e)},intentBatch(e){return r.invoke(n,e)}}}E(_,"createCoAkkaPreloadApi");0&&(module.exports={COAKKA_ELECTRON_INTENT_BATCH_CHANNEL,COAKKA_ELECTRON_INTENT_CHANNEL,createCoAkkaPreloadApi});
package/dist/preload.d.ts CHANGED
@@ -1,8 +1,10 @@
1
1
  export declare const COAKKA_ELECTRON_INTENT_CHANNEL = "coakka:intent";
2
+ export declare const COAKKA_ELECTRON_INTENT_BATCH_CHANNEL = "coakka:intent-batch";
2
3
  export interface IpcRendererLike {
3
4
  invoke(channel: string, payload: unknown): Promise<unknown>;
4
5
  }
5
6
  export interface CoAkkaElectronPreloadApi {
6
7
  intent(intent: unknown): Promise<unknown>;
8
+ intentBatch(intents: readonly unknown[]): Promise<unknown>;
7
9
  }
8
- export declare function createCoAkkaPreloadApi(ipcRenderer: IpcRendererLike, channel?: string): CoAkkaElectronPreloadApi;
10
+ export declare function createCoAkkaPreloadApi(ipcRenderer: IpcRendererLike, channel?: string, batchChannel?: string): CoAkkaElectronPreloadApi;
package/dist/preload.js CHANGED
@@ -1,8 +1 @@
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
- }
1
+ var o=Object.defineProperty;var i=(r,t)=>o(r,"name",{value:t,configurable:!0});var E="coakka:intent",c="coakka:intent-batch";function s(r,t=E,n=c){if(typeof t!="string"||t.trim()==="")throw new Error("Electron intent IPC channel is required");if(typeof n!="string"||n.trim()==="")throw new Error("Electron intent batch IPC channel is required");if(t===n)throw new Error("Electron intent and batch IPC channels must be distinct");return{intent(e){return r.invoke(t,e)},intentBatch(e){return r.invoke(n,e)}}}i(s,"createCoAkkaPreloadApi");export{c as COAKKA_ELECTRON_INTENT_BATCH_CHANNEL,E as COAKKA_ELECTRON_INTENT_CHANNEL,s as createCoAkkaPreloadApi};
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "coakka-v2-connector-electron",
3
- "version": "2.5.3",
4
- "description": "Electron connector for the polyglot, multi-language, multi-platform CoAkka Runtime ecosystem",
3
+ "version": "3.1.1",
4
+ "description": "Electron connector for CoAkka Runtime, a native-backed polyglot distributed runtime for application-owned work",
5
5
  "license": "SEE LICENSE IN PACKAGE-LICENSE.md",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "git+https://github.com/phuong-tran/coakka-publish.git"
9
9
  },
10
- "homepage": "https://github.com/phuong-tran/coakka-samples/tree/main/runtime/electron",
10
+ "homepage": "https://github.com/phuong-tran/coakka-samples/tree/main/docs/coakka-runtime",
11
11
  "bugs": {
12
12
  "url": "https://github.com/phuong-tran/coakka-samples/issues"
13
13
  },
@@ -20,11 +20,13 @@
20
20
  "polyglot",
21
21
  "multi-language",
22
22
  "multi-platform",
23
- "ipc"
23
+ "ipc",
24
+ "distributed-runtime",
25
+ "application-owned-work"
24
26
  ],
25
27
  "type": "module",
26
28
  "engines": {
27
- "node": ">=22"
29
+ "node": ">=22.0.0"
28
30
  },
29
31
  "main": "./dist/index.js",
30
32
  "types": "./dist/index.d.ts",
@@ -48,20 +50,10 @@
48
50
  "NOTICE",
49
51
  "README.md"
50
52
  ],
51
- "scripts": {
52
- "build": "node scripts/build-package.mjs",
53
- "verify": "npm run build",
54
- "pack:release": "npm run build && node scripts/pack-release.mjs",
55
- "smoke:packaged": "bash scripts/smoke-packaged-package.sh"
56
- },
57
53
  "dependencies": {
58
- "coakka-v2-connector-node": "2.5.3"
54
+ "coakka-v2-connector-node": "3.1.2"
59
55
  },
60
56
  "peerDependencies": {
61
57
  "electron": ">=42"
62
- },
63
- "devDependencies": {
64
- "@types/node": "^22.0.0",
65
- "typescript": "^5.8.3"
66
58
  }
67
59
  }