@grest-ts/testkit 0.0.5
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/LICENSE +21 -0
- package/README.md +413 -0
- package/dist/src/GGBundleTest.d.ts +8 -0
- package/dist/src/GGBundleTest.d.ts.map +1 -0
- package/dist/src/GGBundleTest.js +75 -0
- package/dist/src/GGBundleTest.js.map +1 -0
- package/dist/src/GGTest.d.ts +131 -0
- package/dist/src/GGTest.d.ts.map +1 -0
- package/dist/src/GGTest.js +245 -0
- package/dist/src/GGTest.js.map +1 -0
- package/dist/src/GGTestContext.d.ts +36 -0
- package/dist/src/GGTestContext.d.ts.map +1 -0
- package/dist/src/GGTestContext.js +63 -0
- package/dist/src/GGTestContext.js.map +1 -0
- package/dist/src/GGTestRunner.d.ts +108 -0
- package/dist/src/GGTestRunner.d.ts.map +1 -0
- package/dist/src/GGTestRunner.js +242 -0
- package/dist/src/GGTestRunner.js.map +1 -0
- package/dist/src/GGTestRuntime.d.ts +103 -0
- package/dist/src/GGTestRuntime.d.ts.map +1 -0
- package/dist/src/GGTestRuntime.js +219 -0
- package/dist/src/GGTestRuntime.js.map +1 -0
- package/dist/src/GGTestRuntimeWorker.d.ts +41 -0
- package/dist/src/GGTestRuntimeWorker.d.ts.map +1 -0
- package/dist/src/GGTestRuntimeWorker.js +136 -0
- package/dist/src/GGTestRuntimeWorker.js.map +1 -0
- package/dist/src/GGTestSharedRef.d.ts +35 -0
- package/dist/src/GGTestSharedRef.d.ts.map +1 -0
- package/dist/src/GGTestSharedRef.js +126 -0
- package/dist/src/GGTestSharedRef.js.map +1 -0
- package/dist/src/GGTestkitExtensionsDiscovery.d.ts +21 -0
- package/dist/src/GGTestkitExtensionsDiscovery.d.ts.map +1 -0
- package/dist/src/GGTestkitExtensionsDiscovery.js +24 -0
- package/dist/src/GGTestkitExtensionsDiscovery.js.map +1 -0
- package/dist/src/IGGLocalDiscoveryServer.d.ts +16 -0
- package/dist/src/IGGLocalDiscoveryServer.d.ts.map +1 -0
- package/dist/src/IGGLocalDiscoveryServer.js +2 -0
- package/dist/src/IGGLocalDiscoveryServer.js.map +1 -0
- package/dist/src/callOn/GGCallOnSelector.d.ts +42 -0
- package/dist/src/callOn/GGCallOnSelector.d.ts.map +1 -0
- package/dist/src/callOn/GGCallOnSelector.js +35 -0
- package/dist/src/callOn/GGCallOnSelector.js.map +1 -0
- package/dist/src/callOn/GGContractClass.implement.d.ts +8 -0
- package/dist/src/callOn/GGContractClass.implement.d.ts.map +1 -0
- package/dist/src/callOn/GGContractClass.implement.js +31 -0
- package/dist/src/callOn/GGContractClass.implement.js.map +1 -0
- package/dist/src/callOn/GGTestActionForLocatorOnCall.d.ts +28 -0
- package/dist/src/callOn/GGTestActionForLocatorOnCall.d.ts.map +1 -0
- package/dist/src/callOn/GGTestActionForLocatorOnCall.js +118 -0
- package/dist/src/callOn/GGTestActionForLocatorOnCall.js.map +1 -0
- package/dist/src/callOn/TestableIPC.d.ts +72 -0
- package/dist/src/callOn/TestableIPC.d.ts.map +1 -0
- package/dist/src/callOn/TestableIPC.js +34 -0
- package/dist/src/callOn/TestableIPC.js.map +1 -0
- package/dist/src/callOn/callOn.d.ts +113 -0
- package/dist/src/callOn/callOn.d.ts.map +1 -0
- package/dist/src/callOn/callOn.js +122 -0
- package/dist/src/callOn/callOn.js.map +1 -0
- package/dist/src/callOn/registerOnCallHandler.d.ts +13 -0
- package/dist/src/callOn/registerOnCallHandler.d.ts.map +1 -0
- package/dist/src/callOn/registerOnCallHandler.js +111 -0
- package/dist/src/callOn/registerOnCallHandler.js.map +1 -0
- package/dist/src/index-node.d.ts +35 -0
- package/dist/src/index-node.d.ts.map +1 -0
- package/dist/src/index-node.js +50 -0
- package/dist/src/index-node.js.map +1 -0
- package/dist/src/mockable/GGMockable.d.ts +19 -0
- package/dist/src/mockable/GGMockable.d.ts.map +1 -0
- package/dist/src/mockable/GGMockable.js +2 -0
- package/dist/src/mockable/GGMockable.js.map +1 -0
- package/dist/src/mockable/GGMockableCall.d.ts +2 -0
- package/dist/src/mockable/GGMockableCall.d.ts.map +1 -0
- package/dist/src/mockable/GGMockableCall.js +41 -0
- package/dist/src/mockable/GGMockableCall.js.map +1 -0
- package/dist/src/mockable/GGMockableIPC.d.ts +17 -0
- package/dist/src/mockable/GGMockableIPC.d.ts.map +1 -0
- package/dist/src/mockable/GGMockableIPC.js +8 -0
- package/dist/src/mockable/GGMockableIPC.js.map +1 -0
- package/dist/src/mockable/GGMockableInterceptor.d.ts +24 -0
- package/dist/src/mockable/GGMockableInterceptor.d.ts.map +1 -0
- package/dist/src/mockable/GGMockableInterceptor.js +32 -0
- package/dist/src/mockable/GGMockableInterceptor.js.map +1 -0
- package/dist/src/mockable/GGMockableInterceptorsServer.d.ts +12 -0
- package/dist/src/mockable/GGMockableInterceptorsServer.d.ts.map +1 -0
- package/dist/src/mockable/GGMockableInterceptorsServer.js +55 -0
- package/dist/src/mockable/GGMockableInterceptorsServer.js.map +1 -0
- package/dist/src/mockable/mockable.d.ts +46 -0
- package/dist/src/mockable/mockable.d.ts.map +1 -0
- package/dist/src/mockable/mockable.js +47 -0
- package/dist/src/mockable/mockable.js.map +1 -0
- package/dist/src/runner/InlineRunner.d.ts +12 -0
- package/dist/src/runner/InlineRunner.d.ts.map +1 -0
- package/dist/src/runner/InlineRunner.js +42 -0
- package/dist/src/runner/InlineRunner.js.map +1 -0
- package/dist/src/runner/IsolatedRunner.d.ts +17 -0
- package/dist/src/runner/IsolatedRunner.d.ts.map +1 -0
- package/dist/src/runner/IsolatedRunner.js +155 -0
- package/dist/src/runner/IsolatedRunner.js.map +1 -0
- package/dist/src/runner/RuntimeRunner.d.ts +14 -0
- package/dist/src/runner/RuntimeRunner.d.ts.map +1 -0
- package/dist/src/runner/RuntimeRunner.js +2 -0
- package/dist/src/runner/RuntimeRunner.js.map +1 -0
- package/dist/src/runner/WorkerRunner.d.ts +17 -0
- package/dist/src/runner/WorkerRunner.d.ts.map +1 -0
- package/dist/src/runner/WorkerRunner.js +155 -0
- package/dist/src/runner/WorkerRunner.js.map +1 -0
- package/dist/src/runner/isolated-loader.mjs +91 -0
- package/dist/src/runner/worker-loader.mjs +49 -0
- package/dist/src/testers/GGCallInterceptor.d.ts +71 -0
- package/dist/src/testers/GGCallInterceptor.d.ts.map +1 -0
- package/dist/src/testers/GGCallInterceptor.js +170 -0
- package/dist/src/testers/GGCallInterceptor.js.map +1 -0
- package/dist/src/testers/GGMockWith.d.ts +30 -0
- package/dist/src/testers/GGMockWith.d.ts.map +1 -0
- package/dist/src/testers/GGMockWith.js +70 -0
- package/dist/src/testers/GGMockWith.js.map +1 -0
- package/dist/src/testers/GGSpyWith.d.ts +40 -0
- package/dist/src/testers/GGSpyWith.d.ts.map +1 -0
- package/dist/src/testers/GGSpyWith.js +90 -0
- package/dist/src/testers/GGSpyWith.js.map +1 -0
- package/dist/src/testers/GGTestAction.d.ts +126 -0
- package/dist/src/testers/GGTestAction.d.ts.map +1 -0
- package/dist/src/testers/GGTestAction.js +245 -0
- package/dist/src/testers/GGTestAction.js.map +1 -0
- package/dist/src/testers/GGTestComponent.d.ts +15 -0
- package/dist/src/testers/GGTestComponent.d.ts.map +1 -0
- package/dist/src/testers/GGTestComponent.js +2 -0
- package/dist/src/testers/GGTestComponent.js.map +1 -0
- package/dist/src/testers/GGTestSelector.d.ts +54 -0
- package/dist/src/testers/GGTestSelector.d.ts.map +1 -0
- package/dist/src/testers/GGTestSelector.js +179 -0
- package/dist/src/testers/GGTestSelector.js.map +1 -0
- package/dist/src/testers/IGGTestInterceptor.d.ts +8 -0
- package/dist/src/testers/IGGTestInterceptor.d.ts.map +1 -0
- package/dist/src/testers/IGGTestInterceptor.js +2 -0
- package/dist/src/testers/IGGTestInterceptor.js.map +1 -0
- package/dist/src/testers/IGGTestWith.d.ts +13 -0
- package/dist/src/testers/IGGTestWith.d.ts.map +1 -0
- package/dist/src/testers/IGGTestWith.js +2 -0
- package/dist/src/testers/IGGTestWith.js.map +1 -0
- package/dist/src/testers/RuntimeSelector.d.ts +117 -0
- package/dist/src/testers/RuntimeSelector.d.ts.map +1 -0
- package/dist/src/testers/RuntimeSelector.js +2 -0
- package/dist/src/testers/RuntimeSelector.js.map +1 -0
- package/dist/src/tsconfig.json +17 -0
- package/dist/src/utils/GGExpectations.d.ts +18 -0
- package/dist/src/utils/GGExpectations.d.ts.map +1 -0
- package/dist/src/utils/GGExpectations.js +59 -0
- package/dist/src/utils/GGExpectations.js.map +1 -0
- package/dist/src/utils/GGTestError.d.ts +13 -0
- package/dist/src/utils/GGTestError.d.ts.map +1 -0
- package/dist/src/utils/GGTestError.js +26 -0
- package/dist/src/utils/GGTestError.js.map +1 -0
- package/dist/src/utils/captureStack.d.ts +9 -0
- package/dist/src/utils/captureStack.d.ts.map +1 -0
- package/dist/src/utils/captureStack.js +51 -0
- package/dist/src/utils/captureStack.js.map +1 -0
- package/dist/tsconfig.publish.tsbuildinfo +1 -0
- package/package.json +66 -0
- package/src/GGBundleTest.ts +89 -0
- package/src/GGTest.ts +318 -0
- package/src/GGTestContext.ts +74 -0
- package/src/GGTestRunner.ts +308 -0
- package/src/GGTestRuntime.ts +265 -0
- package/src/GGTestRuntimeWorker.ts +159 -0
- package/src/GGTestSharedRef.ts +116 -0
- package/src/GGTestkitExtensionsDiscovery.ts +26 -0
- package/src/IGGLocalDiscoveryServer.ts +16 -0
- package/src/callOn/GGCallOnSelector.ts +61 -0
- package/src/callOn/GGContractClass.implement.ts +43 -0
- package/src/callOn/GGTestActionForLocatorOnCall.ts +134 -0
- package/src/callOn/TestableIPC.ts +81 -0
- package/src/callOn/callOn.ts +224 -0
- package/src/callOn/registerOnCallHandler.ts +123 -0
- package/src/index-node.ts +64 -0
- package/src/mockable/GGMockable.ts +22 -0
- package/src/mockable/GGMockableCall.ts +45 -0
- package/src/mockable/GGMockableIPC.ts +20 -0
- package/src/mockable/GGMockableInterceptor.ts +44 -0
- package/src/mockable/GGMockableInterceptorsServer.ts +69 -0
- package/src/mockable/mockable.ts +71 -0
- package/src/runner/InlineRunner.ts +47 -0
- package/src/runner/IsolatedRunner.ts +179 -0
- package/src/runner/RuntimeRunner.ts +15 -0
- package/src/runner/WorkerRunner.ts +179 -0
- package/src/runner/isolated-loader.mjs +91 -0
- package/src/runner/worker-loader.mjs +49 -0
- package/src/testers/GGCallInterceptor.ts +224 -0
- package/src/testers/GGMockWith.ts +92 -0
- package/src/testers/GGSpyWith.ts +115 -0
- package/src/testers/GGTestAction.ts +333 -0
- package/src/testers/GGTestComponent.ts +16 -0
- package/src/testers/GGTestSelector.ts +223 -0
- package/src/testers/IGGTestInterceptor.ts +11 -0
- package/src/testers/IGGTestWith.ts +15 -0
- package/src/testers/RuntimeSelector.ts +151 -0
- package/src/tsconfig.json +17 -0
- package/src/utils/GGExpectations.ts +78 -0
- package/src/utils/GGTestError.ts +37 -0
- package/src/utils/captureStack.ts +54 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test action for invoking methods via GGLocator lookup.
|
|
3
|
+
*
|
|
4
|
+
* Used for:
|
|
5
|
+
* - @testable services (key: @testable:ClassName)
|
|
6
|
+
* - Direct contract calls (key: @contract:ContractName)
|
|
7
|
+
* - Custom GGLocatorKey lookups
|
|
8
|
+
*
|
|
9
|
+
* Extends GGTestAction to support .with() for mocks/spies and
|
|
10
|
+
* response expectations like .toMatchObject(), .toEqual().
|
|
11
|
+
*/
|
|
12
|
+
import { GGTestAction } from "../testers/GGTestAction.js";
|
|
13
|
+
import { GG_TEST_RUNNER } from "../GGTestRunner.js";
|
|
14
|
+
import { TestableIPC } from "./TestableIPC.js";
|
|
15
|
+
import { GGTestError } from "../utils/GGTestError.js";
|
|
16
|
+
/**
|
|
17
|
+
* Serialize a GGContext to a plain object for IPC transfer.
|
|
18
|
+
* Flattens the context hierarchy into a single object.
|
|
19
|
+
*/
|
|
20
|
+
function serializeContext(ctx) {
|
|
21
|
+
const result = {};
|
|
22
|
+
// Access the private values map via type assertion
|
|
23
|
+
const ctxAny = ctx;
|
|
24
|
+
if (ctxAny.values instanceof Map) {
|
|
25
|
+
for (const [key, value] of ctxAny.values) {
|
|
26
|
+
result[key] = value;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// Also serialize parent context values (child values take precedence)
|
|
30
|
+
if (ctxAny.parent) {
|
|
31
|
+
const parentValues = serializeContext(ctxAny.parent);
|
|
32
|
+
return { ...parentValues, ...result };
|
|
33
|
+
}
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Action for invoking a method via GGLocator lookup over IPC.
|
|
38
|
+
*
|
|
39
|
+
* @typeParam T - The expected return type of the method
|
|
40
|
+
*/
|
|
41
|
+
export class GGTestActionForLocatorOnCall extends GGTestAction {
|
|
42
|
+
keyName;
|
|
43
|
+
methodName;
|
|
44
|
+
args;
|
|
45
|
+
targetRuntimes;
|
|
46
|
+
constructor(ctx, keyName, methodName, args, targetRuntimes) {
|
|
47
|
+
const config = {
|
|
48
|
+
noResponse: false,
|
|
49
|
+
logData: {
|
|
50
|
+
message: `[${keyName}.${methodName}]`,
|
|
51
|
+
request: args.length > 0 ? args : undefined
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
super(ctx, config);
|
|
55
|
+
this.keyName = keyName;
|
|
56
|
+
this.methodName = methodName;
|
|
57
|
+
this.args = args;
|
|
58
|
+
this.targetRuntimes = targetRuntimes;
|
|
59
|
+
}
|
|
60
|
+
// -------------------------------------------------
|
|
61
|
+
// Action execution
|
|
62
|
+
// -------------------------------------------------
|
|
63
|
+
async executeAction() {
|
|
64
|
+
const runner = GG_TEST_RUNNER.get();
|
|
65
|
+
// Use target runtimes if provided, otherwise all runtimes
|
|
66
|
+
const searchRuntimes = this.targetRuntimes ?? runner.getAllRuntimes();
|
|
67
|
+
// Find runtimes that have this key registered
|
|
68
|
+
const candidates = searchRuntimes.filter(r => r.hasLocatorKey(this.keyName));
|
|
69
|
+
if (candidates.length === 0) {
|
|
70
|
+
// No runtime has this key - provide helpful error
|
|
71
|
+
const allRuntimes = runner.getAllRuntimes();
|
|
72
|
+
if (allRuntimes.length === 0) {
|
|
73
|
+
throw new GGTestError({
|
|
74
|
+
test: `No runtimes available to invoke ${this.keyName}.${this.methodName}`,
|
|
75
|
+
expected: "At least one runtime to be started",
|
|
76
|
+
received: "No runtimes found"
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
throw new GGTestError({
|
|
80
|
+
test: `Instance '${this.keyName}' not found in any runtime`,
|
|
81
|
+
expected: `A @testable instance registered with key '${this.keyName}'`,
|
|
82
|
+
received: `Key not registered in any of ${allRuntimes.length} runtime(s): ${allRuntimes.map(r => r.name).join(', ')}`
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
if (candidates.length > 1) {
|
|
86
|
+
// Check if all candidates are the same runtime class - if so, just use first one
|
|
87
|
+
const uniqueClassNames = new Set(candidates.map(r => r.className));
|
|
88
|
+
if (uniqueClassNames.size > 1) {
|
|
89
|
+
// Different runtime classes have this key - actual ambiguity
|
|
90
|
+
throw new GGTestError({
|
|
91
|
+
test: `Multiple different runtimes have '${this.keyName}' registered`,
|
|
92
|
+
expected: `Key '${this.keyName}' to be unique across different runtime classes, or use explicit runtime targeting`,
|
|
93
|
+
received: `Found in ${candidates.length} runtimes with different classes: ${[...uniqueClassNames].join(', ')}`
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
// Same runtime class - just use first instance (they're identical)
|
|
97
|
+
}
|
|
98
|
+
// Exactly one runtime has this key - send IPC directly
|
|
99
|
+
const runtime = candidates[0];
|
|
100
|
+
const context = this.ctx ? serializeContext(this.ctx) : undefined;
|
|
101
|
+
const result = await runtime.sendCommand(TestableIPC.invoke, {
|
|
102
|
+
keyName: this.keyName,
|
|
103
|
+
methodName: this.methodName,
|
|
104
|
+
args: this.args,
|
|
105
|
+
context
|
|
106
|
+
});
|
|
107
|
+
if (result.success) {
|
|
108
|
+
return result.result;
|
|
109
|
+
}
|
|
110
|
+
throw new GGTestError({
|
|
111
|
+
test: `Error invoking ${this.keyName}.${this.methodName}`,
|
|
112
|
+
expected: "Method to execute successfully",
|
|
113
|
+
received: result.error || "Unknown error",
|
|
114
|
+
extra: result.stack
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=GGTestActionForLocatorOnCall.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGTestActionForLocatorOnCall.js","sourceRoot":"","sources":["../../../src/callOn/GGTestActionForLocatorOnCall.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IPC protocol definitions for GGLocator-based service invocation.
|
|
3
|
+
*
|
|
4
|
+
* Defines the messages exchanged between test runner and runtime worker
|
|
5
|
+
* for invoking methods on registered instances (@testable, @contract, etc.).
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Serialized context data for IPC transfer.
|
|
9
|
+
* Contains flattened key-value pairs from GGContext.
|
|
10
|
+
*/
|
|
11
|
+
export type SerializedContext = Record<string, any>;
|
|
12
|
+
/**
|
|
13
|
+
* Payload for invoking a method on a registered instance.
|
|
14
|
+
*/
|
|
15
|
+
export interface TestableInvokePayload {
|
|
16
|
+
/** The GGLocatorKey name (e.g., "@testable:ServiceB", "@contract:ChainApi", or custom key) */
|
|
17
|
+
keyName: string;
|
|
18
|
+
/** The method name to invoke */
|
|
19
|
+
methodName: string;
|
|
20
|
+
/** Arguments to pass to the method (as array) */
|
|
21
|
+
args: any[];
|
|
22
|
+
/** Serialized GGContext data to restore on the worker side */
|
|
23
|
+
context?: SerializedContext;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Result from invoking a testable method.
|
|
27
|
+
*/
|
|
28
|
+
export interface TestableInvokeResult {
|
|
29
|
+
/** Whether the invocation succeeded */
|
|
30
|
+
success: boolean;
|
|
31
|
+
/** The return value from the method (if success) */
|
|
32
|
+
result?: any;
|
|
33
|
+
/** Error message (if failed) */
|
|
34
|
+
error?: string;
|
|
35
|
+
/** Error stack trace (if failed) */
|
|
36
|
+
stack?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Payload for registering locator keys from a runtime.
|
|
40
|
+
*/
|
|
41
|
+
export interface KeyRegistrationPayload {
|
|
42
|
+
/** Runtime ID sending the registration */
|
|
43
|
+
runtimeId: string;
|
|
44
|
+
/** All GGLocatorKey names registered in this runtime */
|
|
45
|
+
keys: string[];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* IPC endpoints for testable service invocation.
|
|
49
|
+
*/
|
|
50
|
+
export declare const TestableIPC: {
|
|
51
|
+
/**
|
|
52
|
+
* Messages FROM test server TO worker.
|
|
53
|
+
*/
|
|
54
|
+
client: {
|
|
55
|
+
/**
|
|
56
|
+
* Invoke a method on a testable service instance.
|
|
57
|
+
*/
|
|
58
|
+
invoke: import("@grest-ts/ipc").IPCClientRequest<TestableInvokePayload, TestableInvokeResult>;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Messages FROM worker TO test server.
|
|
62
|
+
*/
|
|
63
|
+
server: {
|
|
64
|
+
/**
|
|
65
|
+
* Register all locator keys available in a runtime.
|
|
66
|
+
* Sent from worker to test runner after compose completes.
|
|
67
|
+
*/
|
|
68
|
+
registerKeys: import("@grest-ts/ipc").IPCServerRequest<KeyRegistrationPayload, void>;
|
|
69
|
+
};
|
|
70
|
+
invoke: import("@grest-ts/ipc").IPCClientRequest<TestableInvokePayload, TestableInvokeResult>;
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=TestableIPC.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TestableIPC.d.ts","sourceRoot":"","sources":["../../../src/callOn/TestableIPC.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,qBAAqB;IAClC,8FAA8F;IAC9F,OAAO,EAAE,MAAM,CAAC;IAChB,gCAAgC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,8DAA8D;IAC9D,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACjC,uCAAuC;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,oDAAoD;IACpD,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACnC,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,IAAI,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;GAEG;AACH,eAAO,MAAM,WAAW;IACpB;;OAEG;;QAEC;;WAEG;;;IAIP;;OAEG;;QAEC;;;WAGG;;;;CAMV,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IPC protocol definitions for GGLocator-based service invocation.
|
|
3
|
+
*
|
|
4
|
+
* Defines the messages exchanged between test runner and runtime worker
|
|
5
|
+
* for invoking methods on registered instances (@testable, @contract, etc.).
|
|
6
|
+
*/
|
|
7
|
+
import { IPCClient, IPCServer } from "@grest-ts/ipc";
|
|
8
|
+
/**
|
|
9
|
+
* IPC endpoints for testable service invocation.
|
|
10
|
+
*/
|
|
11
|
+
export const TestableIPC = {
|
|
12
|
+
/**
|
|
13
|
+
* Messages FROM test server TO worker.
|
|
14
|
+
*/
|
|
15
|
+
client: {
|
|
16
|
+
/**
|
|
17
|
+
* Invoke a method on a testable service instance.
|
|
18
|
+
*/
|
|
19
|
+
invoke: IPCClient.defineRequest("testable/invoke"),
|
|
20
|
+
},
|
|
21
|
+
/**
|
|
22
|
+
* Messages FROM worker TO test server.
|
|
23
|
+
*/
|
|
24
|
+
server: {
|
|
25
|
+
/**
|
|
26
|
+
* Register all locator keys available in a runtime.
|
|
27
|
+
* Sent from worker to test runner after compose completes.
|
|
28
|
+
*/
|
|
29
|
+
registerKeys: IPCServer.defineRequest("testable/register-keys"),
|
|
30
|
+
},
|
|
31
|
+
// Legacy alias for backwards compatibility
|
|
32
|
+
invoke: IPCClient.defineRequest("testable/invoke"),
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=TestableIPC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TestableIPC.js","sourceRoot":"","sources":["../../../src/callOn/TestableIPC.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAC,SAAS,EAAE,SAAS,EAAC,MAAM,eAAe,CAAC;AA8CnD;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACvB;;OAEG;IACH,MAAM,EAAE;QACJ;;WAEG;QACH,MAAM,EAAE,SAAS,CAAC,aAAa,CAA8C,iBAAiB,CAAC;KAClG;IAED;;OAEG;IACH,MAAM,EAAE;QACJ;;;WAGG;QACH,YAAY,EAAE,SAAS,CAAC,aAAa,CAA+B,wBAAwB,CAAC;KAChG;IAED,2CAA2C;IAC3C,MAAM,EAAE,SAAS,CAAC,aAAa,CAA8C,iBAAiB,CAAC;CAClG,CAAC"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified callOn function for invoking methods on runtime instances.
|
|
3
|
+
*
|
|
4
|
+
* Works with:
|
|
5
|
+
* - @testable classes: Direct service invocation via IPC
|
|
6
|
+
* - GGLocatorKey: Direct instance lookup via IPC
|
|
7
|
+
* - GGContractClass: Contract implementation lookup via IPC
|
|
8
|
+
* - Contract holders (HTTP APIs, etc.): Delegated to their own factory
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* // Call @testable service
|
|
12
|
+
* await callOn(MyService).doSomething("hello")
|
|
13
|
+
*
|
|
14
|
+
* // Call HTTP API (goes through HTTP transport)
|
|
15
|
+
* await callOn(ChainApi).quickWeatherCheck({city: "NYC"})
|
|
16
|
+
*
|
|
17
|
+
* // Call contract directly (skips HTTP, uses IPC)
|
|
18
|
+
* await callOn(ChainApiContract).quickWeatherCheck({city: "NYC"})
|
|
19
|
+
*
|
|
20
|
+
* // With context
|
|
21
|
+
* await callOn(MyService, ctx).doSomething("hello")
|
|
22
|
+
*/
|
|
23
|
+
import { GGLocatorKey } from "@grest-ts/locator";
|
|
24
|
+
import { GGTestActionForLocatorOnCall } from "./GGTestActionForLocatorOnCall";
|
|
25
|
+
import { GGContractApiDefinition, GGContractClass, GGContractMethod } from "@grest-ts/schema";
|
|
26
|
+
import { GGContext } from "@grest-ts/context";
|
|
27
|
+
import type { GGTestRuntime } from "../GGTestRuntime";
|
|
28
|
+
/**
|
|
29
|
+
* Symbol used by contract holders (HTTP APIs, WebSocket APIs, etc.) to provide
|
|
30
|
+
* their own callOn proxy. This allows protocols to control how calls are made
|
|
31
|
+
* without callOn needing to know about specific protocols.
|
|
32
|
+
*
|
|
33
|
+
* The factory can return anything - there's no constraint on the return type.
|
|
34
|
+
* Each protocol fully controls what methods and types are available.
|
|
35
|
+
*/
|
|
36
|
+
export declare const CALL_ON_FACTORY: unique symbol;
|
|
37
|
+
/**
|
|
38
|
+
* Marker interface for targets that provide their own callOn proxy.
|
|
39
|
+
* The factory can return any type - protocols have full control.
|
|
40
|
+
*/
|
|
41
|
+
export interface GGCallOnFactory {
|
|
42
|
+
[CALL_ON_FACTORY](ctx?: GGContext): unknown;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Maps a class's async methods to GGLocatorLookupTestAction calls.
|
|
46
|
+
* Used for @testable classes and GGLocatorKey lookups.
|
|
47
|
+
*/
|
|
48
|
+
export type LocatorLookupAccess<T> = {
|
|
49
|
+
[K in keyof T]: T[K] extends (...args: infer A) => Promise<infer R> ? (...args: A) => GGTestActionForLocatorOnCall<R> : never;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Maps contract methods to GGLocatorLookupTestAction calls.
|
|
53
|
+
* Used for direct GGContractClass lookups via IPC.
|
|
54
|
+
*/
|
|
55
|
+
export type ContractLocatorAccess<TContract> = {
|
|
56
|
+
[K in keyof TContract]: TContract[K] extends GGContractMethod<infer Input, infer Output> ? Input extends undefined ? () => GGTestActionForLocatorOnCall<Output> : (data: Input) => GGTestActionForLocatorOnCall<Output> : never;
|
|
57
|
+
};
|
|
58
|
+
export type GGTestCallOnCollection<T> = {
|
|
59
|
+
[K in keyof T]: GGTestCallOn<T[K]>;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Resolves the return type for callOn(target):
|
|
63
|
+
* - Factory targets → extract factory's return type (protocol controls everything)
|
|
64
|
+
* - GGContractClass → ContractLocatorAccess (IPC)
|
|
65
|
+
* - Constructor/GGLocatorKey → LocatorLookupAccess (IPC)
|
|
66
|
+
* - Plain objects → recurse into properties
|
|
67
|
+
*/
|
|
68
|
+
export type GGTestCallOn<T> = T extends {
|
|
69
|
+
[CALL_ON_FACTORY]: (ctx?: GGContext) => infer R;
|
|
70
|
+
} ? R : T extends GGContractClass<infer TContract> ? ContractLocatorAccess<TContract> : T extends GGLocatorKey<infer Instance> ? LocatorLookupAccess<Instance> : T extends new (...args: any[]) => infer Instance ? LocatorLookupAccess<Instance> : T extends object ? {
|
|
71
|
+
[K in keyof T]: GGTestCallOn<T[K]>;
|
|
72
|
+
} : never;
|
|
73
|
+
/**
|
|
74
|
+
* Invoke methods on runtime instances via a unified interface.
|
|
75
|
+
*
|
|
76
|
+
* Resolution order:
|
|
77
|
+
* 1. Factory symbol (HTTP APIs, WebSocket APIs provide their own)
|
|
78
|
+
* 2. GGContractClass → IPC lookup via @contract: prefix
|
|
79
|
+
* 3. GGLocatorKey → IPC lookup via key name
|
|
80
|
+
* 4. Simple class → IPC lookup via @testable: prefix
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* await callOn(MyService, ctx).doSomething("hello")
|
|
84
|
+
* await callOn(ChainApi, ctx).quickWeatherCheck({city: "NYC"})
|
|
85
|
+
* await callOn(ChainApiContract, ctx).quickWeatherCheck({city: "NYC"})
|
|
86
|
+
*/
|
|
87
|
+
export declare function callOn<T extends GGCallOnFactory>(target: T, ctx?: GGContext): GGTestCallOn<T>;
|
|
88
|
+
export declare function callOn<T extends GGContractApiDefinition>(target: GGContractClass<T>, ctx?: GGContext): ContractLocatorAccess<T>;
|
|
89
|
+
export declare function callOn<T>(target: GGLocatorKey<T>, ctx?: GGContext): LocatorLookupAccess<T>;
|
|
90
|
+
export declare function callOn<T extends new (...args: any[]) => any>(target: T, ctx?: GGContext): LocatorLookupAccess<InstanceType<T>>;
|
|
91
|
+
export declare function callOn<T extends object>(target: T, ctx?: GGContext): GGTestCallOn<T>;
|
|
92
|
+
/**
|
|
93
|
+
* Invoke methods on runtime instances, targeting specific runtimes.
|
|
94
|
+
* Use this when you need to explicitly select which runtime to call
|
|
95
|
+
* when multiple different runtime classes have the same service.
|
|
96
|
+
*
|
|
97
|
+
* @param target - The target to call (class, GGLocatorKey, or GGContractClass)
|
|
98
|
+
* @param runtimes - The specific runtimes to target
|
|
99
|
+
* @param ctx - Optional context for the call
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* const f = GGTest.startWorker({chain: ChainRuntime, weather: WeatherOnlyRuntime});
|
|
103
|
+
* // Both have WeatherService - explicitly target one:
|
|
104
|
+
* await f.chain.callOn(WeatherService).getWeather("Test")
|
|
105
|
+
*/
|
|
106
|
+
export declare function callOnTargeted<T>(target: T, runtimes: GGTestRuntime[], ctx?: GGContext): GGTestCallOn<T>;
|
|
107
|
+
/**
|
|
108
|
+
* Process a collection of targets and create callOn proxies for each.
|
|
109
|
+
* It can be a recursive object where all "testable things" are replaced with callOn(X) handlers.
|
|
110
|
+
* {serviceA: ApiA, sub: { serviceB: ApiB}} -> {serviceA: callOn(ApiA), sub: { serviceB: callOn(ApiB)}}
|
|
111
|
+
*/
|
|
112
|
+
export declare function callOnCollection<T extends object | any[]>(target: T, ctx?: GGContext): GGTestCallOnCollection<T>;
|
|
113
|
+
//# sourceMappingURL=callOn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callOn.d.ts","sourceRoot":"","sources":["../../../src/callOn/callOn.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified callOn function for invoking methods on runtime instances.
|
|
3
|
+
*
|
|
4
|
+
* Works with:
|
|
5
|
+
* - @testable classes: Direct service invocation via IPC
|
|
6
|
+
* - GGLocatorKey: Direct instance lookup via IPC
|
|
7
|
+
* - GGContractClass: Contract implementation lookup via IPC
|
|
8
|
+
* - Contract holders (HTTP APIs, etc.): Delegated to their own factory
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* // Call @testable service
|
|
12
|
+
* await callOn(MyService).doSomething("hello")
|
|
13
|
+
*
|
|
14
|
+
* // Call HTTP API (goes through HTTP transport)
|
|
15
|
+
* await callOn(ChainApi).quickWeatherCheck({city: "NYC"})
|
|
16
|
+
*
|
|
17
|
+
* // Call contract directly (skips HTTP, uses IPC)
|
|
18
|
+
* await callOn(ChainApiContract).quickWeatherCheck({city: "NYC"})
|
|
19
|
+
*
|
|
20
|
+
* // With context
|
|
21
|
+
* await callOn(MyService, ctx).doSomething("hello")
|
|
22
|
+
*/
|
|
23
|
+
import { GGLocatorKey } from "@grest-ts/locator";
|
|
24
|
+
import { GGTestActionForLocatorOnCall } from "./GGTestActionForLocatorOnCall.js";
|
|
25
|
+
import { LOCATOR_KEY_PREFIX_FOR_TESTABLE } from "@grest-ts/testkit-runtime";
|
|
26
|
+
import { GGContractClass } from "@grest-ts/schema";
|
|
27
|
+
import { GGContext } from "@grest-ts/context";
|
|
28
|
+
import { LOCATOR_KEY_PREFIX_FOR_CONTRACT } from "./GGContractClass.implement.js";
|
|
29
|
+
// ============================================================================
|
|
30
|
+
// Factory symbol for protocol-specific callOn support
|
|
31
|
+
// ============================================================================
|
|
32
|
+
/**
|
|
33
|
+
* Symbol used by contract holders (HTTP APIs, WebSocket APIs, etc.) to provide
|
|
34
|
+
* their own callOn proxy. This allows protocols to control how calls are made
|
|
35
|
+
* without callOn needing to know about specific protocols.
|
|
36
|
+
*
|
|
37
|
+
* The factory can return anything - there's no constraint on the return type.
|
|
38
|
+
* Each protocol fully controls what methods and types are available.
|
|
39
|
+
*/
|
|
40
|
+
export const CALL_ON_FACTORY = Symbol.for("gg:callOnFactory");
|
|
41
|
+
// ============================================================================
|
|
42
|
+
// The callOn function
|
|
43
|
+
// ============================================================================
|
|
44
|
+
/**
|
|
45
|
+
* Check if target implements the CALL_ON_FACTORY interface.
|
|
46
|
+
*/
|
|
47
|
+
function hasCallOnFactory(target) {
|
|
48
|
+
return target != null && typeof target[CALL_ON_FACTORY] === 'function';
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Check if target is a simple class (constructor function).
|
|
52
|
+
*/
|
|
53
|
+
function isSimpleClass(value) {
|
|
54
|
+
return typeof value === 'function' && value.prototype !== undefined && value.prototype.constructor === value;
|
|
55
|
+
}
|
|
56
|
+
export function callOn(target, ctx) {
|
|
57
|
+
ctx ??= new GGContext("Test");
|
|
58
|
+
if (hasCallOnFactory(target)) {
|
|
59
|
+
return target[CALL_ON_FACTORY](ctx);
|
|
60
|
+
}
|
|
61
|
+
const keyName = resolveKeyName(target);
|
|
62
|
+
return createCallOnProxy(keyName, ctx);
|
|
63
|
+
}
|
|
64
|
+
// ============================================================================
|
|
65
|
+
// Helper functions for key resolution
|
|
66
|
+
// ============================================================================
|
|
67
|
+
/**
|
|
68
|
+
* Resolve a target to its locator key name.
|
|
69
|
+
* Handles GGContractClass, GGLocatorKey, and simple classes.
|
|
70
|
+
*/
|
|
71
|
+
function resolveKeyName(target) {
|
|
72
|
+
if (target instanceof GGContractClass) {
|
|
73
|
+
return LOCATOR_KEY_PREFIX_FOR_CONTRACT + target.name;
|
|
74
|
+
}
|
|
75
|
+
if (target instanceof GGLocatorKey) {
|
|
76
|
+
return target.name;
|
|
77
|
+
}
|
|
78
|
+
if (isSimpleClass(target)) {
|
|
79
|
+
return LOCATOR_KEY_PREFIX_FOR_TESTABLE + target.name;
|
|
80
|
+
}
|
|
81
|
+
throw new Error(`Unknown callOn target: ${target?.name ?? target?.constructor?.name ?? typeof target}`);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Create a proxy that intercepts method calls and returns GGTestActionForLocatorOnCall.
|
|
85
|
+
*/
|
|
86
|
+
function createCallOnProxy(keyName, ctx, targetRuntimes) {
|
|
87
|
+
return new Proxy({}, {
|
|
88
|
+
get(_, methodName) {
|
|
89
|
+
return (...args) => new GGTestActionForLocatorOnCall(ctx, keyName, methodName, args, targetRuntimes);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
export function callOnTargeted(target, runtimes, ctx) {
|
|
94
|
+
ctx ??= new GGContext("Test");
|
|
95
|
+
// Factory targets don't support runtime targeting - they control their own routing
|
|
96
|
+
if (hasCallOnFactory(target)) {
|
|
97
|
+
return target[CALL_ON_FACTORY](ctx);
|
|
98
|
+
}
|
|
99
|
+
const keyName = resolveKeyName(target);
|
|
100
|
+
return createCallOnProxy(keyName, ctx, runtimes);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Process a collection of targets and create callOn proxies for each.
|
|
104
|
+
* It can be a recursive object where all "testable things" are replaced with callOn(X) handlers.
|
|
105
|
+
* {serviceA: ApiA, sub: { serviceB: ApiB}} -> {serviceA: callOn(ApiA), sub: { serviceB: callOn(ApiB)}}
|
|
106
|
+
*/
|
|
107
|
+
export function callOnCollection(target, ctx) {
|
|
108
|
+
const result = Array.isArray(target) ? [] : {};
|
|
109
|
+
for (const key in target) {
|
|
110
|
+
const value = target[key];
|
|
111
|
+
if (value != null) {
|
|
112
|
+
if (hasCallOnFactory(value) || value instanceof GGContractClass || value instanceof GGLocatorKey || isSimpleClass(value)) {
|
|
113
|
+
result[key] = callOn(value, ctx);
|
|
114
|
+
}
|
|
115
|
+
else if (typeof value === 'object') {
|
|
116
|
+
result[key] = callOnCollection(value, ctx);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return result;
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=callOn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callOn.js","sourceRoot":"","sources":["../../../src/callOn/callOn.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worker-side handler for GGLocator-based service invocation.
|
|
3
|
+
*
|
|
4
|
+
* Receives IPC requests from tests to invoke methods on registered instances
|
|
5
|
+
* (@testable, @contract, etc.) and returns the results.
|
|
6
|
+
*/
|
|
7
|
+
import { GGTestRuntimeWorker } from "../GGTestRuntimeWorker";
|
|
8
|
+
/**
|
|
9
|
+
* Register the locator lookup handler on the worker.
|
|
10
|
+
* Called during worker initialization.
|
|
11
|
+
*/
|
|
12
|
+
export declare function registerOnCallHandler(worker: GGTestRuntimeWorker): void;
|
|
13
|
+
//# sourceMappingURL=registerOnCallHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registerOnCallHandler.d.ts","sourceRoot":"","sources":["../../../src/callOn/registerOnCallHandler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAC,mBAAmB,EAAC,MAAM,wBAAwB,CAAC;AAsB3D;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CA8DvE"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worker-side handler for GGLocator-based service invocation.
|
|
3
|
+
*
|
|
4
|
+
* Receives IPC requests from tests to invoke methods on registered instances
|
|
5
|
+
* (@testable, @contract, etc.) and returns the results.
|
|
6
|
+
*/
|
|
7
|
+
import { GGLocator, GGLocatorKey } from "@grest-ts/locator";
|
|
8
|
+
import { GGLog } from "@grest-ts/logger";
|
|
9
|
+
import { TestableIPC } from "./TestableIPC.js";
|
|
10
|
+
import { GGContext } from "@grest-ts/context";
|
|
11
|
+
/**
|
|
12
|
+
* Context for logging
|
|
13
|
+
*/
|
|
14
|
+
const LOG_CONTEXT = { name: "GGLocatorWorkerHandler" };
|
|
15
|
+
/**
|
|
16
|
+
* Deserialize context data into a GGContext.
|
|
17
|
+
* Directly populates the internal values map.
|
|
18
|
+
*/
|
|
19
|
+
function deserializeContext(data) {
|
|
20
|
+
const ctx = new GGContext("ipc-context");
|
|
21
|
+
// Access internal values map and populate directly
|
|
22
|
+
const ctxAny = ctx;
|
|
23
|
+
for (const [keyName, value] of Object.entries(data)) {
|
|
24
|
+
ctxAny.values.set(keyName, value);
|
|
25
|
+
}
|
|
26
|
+
return ctx;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Register the locator lookup handler on the worker.
|
|
30
|
+
* Called during worker initialization.
|
|
31
|
+
*/
|
|
32
|
+
export function registerOnCallHandler(worker) {
|
|
33
|
+
worker.onIpcRequest(TestableIPC.invoke, async (payload) => {
|
|
34
|
+
const { keyName, methodName, args, context } = payload;
|
|
35
|
+
GGLog.debug(LOG_CONTEXT, `Invoking ${keyName}.${methodName}`, { args, hasContext: !!context });
|
|
36
|
+
try {
|
|
37
|
+
// Look up the instance in the current scope
|
|
38
|
+
const scope = GGLocator.tryGetScope();
|
|
39
|
+
if (!scope) {
|
|
40
|
+
return {
|
|
41
|
+
success: false,
|
|
42
|
+
error: `No GGLocator scope available - is the runtime running?`
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const key = new GGLocatorKey(keyName);
|
|
46
|
+
const instance = scope.tryGet(key);
|
|
47
|
+
if (!instance) {
|
|
48
|
+
return {
|
|
49
|
+
success: false,
|
|
50
|
+
error: `Instance '${keyName}' not found in GGLocator. ` +
|
|
51
|
+
`Make sure the class is decorated with @testable or registered during compose().`
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
// Check if method exists
|
|
55
|
+
const method = instance[methodName];
|
|
56
|
+
if (typeof method !== 'function') {
|
|
57
|
+
return {
|
|
58
|
+
success: false,
|
|
59
|
+
error: `Method '${methodName}' not found on instance '${keyName}'. ` +
|
|
60
|
+
`Available methods: ${getMethodNames(instance).join(', ')}`
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
// Invoke the method, optionally within the provided context
|
|
64
|
+
let result;
|
|
65
|
+
if (context) {
|
|
66
|
+
const ctx = deserializeContext(context);
|
|
67
|
+
result = await ctx.run(() => method.apply(instance, args));
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
result = await method.apply(instance, args);
|
|
71
|
+
}
|
|
72
|
+
GGLog.debug(LOG_CONTEXT, `Invocation ${keyName}.${methodName} completed`, { result });
|
|
73
|
+
return {
|
|
74
|
+
success: true,
|
|
75
|
+
result
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
GGLog.error(LOG_CONTEXT, `Error invoking ${keyName}.${methodName}`, error);
|
|
80
|
+
return {
|
|
81
|
+
success: false,
|
|
82
|
+
error: error.message || String(error),
|
|
83
|
+
stack: error.stack
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Get method names from an instance for error messages.
|
|
90
|
+
*/
|
|
91
|
+
function getMethodNames(instance) {
|
|
92
|
+
const names = [];
|
|
93
|
+
let proto = Object.getPrototypeOf(instance);
|
|
94
|
+
while (proto && proto !== Object.prototype) {
|
|
95
|
+
const propNames = Object.getOwnPropertyNames(proto)
|
|
96
|
+
.filter(name => {
|
|
97
|
+
if (name === 'constructor')
|
|
98
|
+
return false;
|
|
99
|
+
try {
|
|
100
|
+
return typeof proto[name] === 'function';
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
names.push(...propNames);
|
|
107
|
+
proto = Object.getPrototypeOf(proto);
|
|
108
|
+
}
|
|
109
|
+
return [...new Set(names)].sort();
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=registerOnCallHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registerOnCallHandler.js","sourceRoot":"","sources":["../../../src/callOn/registerOnCallHandler.ts"],"names":[],"mappings":"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"}
|