@interopio/workspaces-api 3.2.1 → 3.2.3
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/dist/workspaces.es.js +4295 -4648
- package/dist/workspaces.es.js.map +1 -1
- package/dist/workspaces.umd.js +5206 -5559
- package/dist/workspaces.umd.js.map +1 -1
- package/dist/workspaces.umd.min.js +1 -1
- package/package.json +36 -50
- package/workspaces.d.ts +8 -0
- package/rollup.config.js +0 -54
- package/src/builders/baseBuilder.ts +0 -50
- package/src/builders/parentBuilder.ts +0 -62
- package/src/builders/workspaceBuilder.ts +0 -102
- package/src/communication/bridge.ts +0 -263
- package/src/communication/constants.ts +0 -202
- package/src/communication/interop-transport.ts +0 -175
- package/src/controllers/base.ts +0 -487
- package/src/controllers/main.ts +0 -541
- package/src/controllers/shortcuts.ts +0 -28
- package/src/index.ts +0 -23
- package/src/main.ts +0 -415
- package/src/models/base/base.ts +0 -397
- package/src/models/column.ts +0 -187
- package/src/models/frame.ts +0 -368
- package/src/models/group.ts +0 -237
- package/src/models/row.ts +0 -188
- package/src/models/window.ts +0 -309
- package/src/models/workspace.ts +0 -717
- package/src/shared/decoders.ts +0 -939
- package/src/shared/ioc.ts +0 -227
- package/src/shared/privateDataManager.ts +0 -93
- package/src/shared/promisePlus.ts +0 -34
- package/src/shared/promiseWrapper.ts +0 -11
- package/src/types/builders.ts +0 -10
- package/src/types/controller.ts +0 -79
- package/src/types/glue.ts +0 -37
- package/src/types/ioc.ts +0 -33
- package/src/types/privateData.ts +0 -92
- package/src/types/protocol.ts +0 -453
- package/src/types/subscription.ts +0 -31
- package/temp.d.ts +0 -49
- package/tsconfig.json +0 -10
package/rollup.config.js
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
const typescript = require('rollup-plugin-typescript2');
|
|
2
|
-
const terser = require('@rollup/plugin-terser');
|
|
3
|
-
const commonjs = require('@rollup/plugin-commonjs');
|
|
4
|
-
const resolve = require('@rollup/plugin-node-resolve');
|
|
5
|
-
const json = require('@rollup/plugin-json');
|
|
6
|
-
const pkg = require('./package.json');
|
|
7
|
-
const del = require('rollup-plugin-delete');
|
|
8
|
-
|
|
9
|
-
module.exports = {
|
|
10
|
-
input: 'src/index.ts',
|
|
11
|
-
output: [
|
|
12
|
-
{
|
|
13
|
-
file: pkg.main,
|
|
14
|
-
name: 'workspaces',
|
|
15
|
-
format: 'umd',
|
|
16
|
-
sourcemap: true
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
file: './dist/workspaces.umd.min.js',
|
|
20
|
-
name: 'workspaces.min',
|
|
21
|
-
format: 'umd',
|
|
22
|
-
plugins: [terser()]
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
file: pkg.module,
|
|
26
|
-
format: 'es',
|
|
27
|
-
sourcemap: true
|
|
28
|
-
},
|
|
29
|
-
],
|
|
30
|
-
external: [
|
|
31
|
-
//...Object.keys(pkg.dependencies || {}),
|
|
32
|
-
...Object.keys(pkg.peerDependencies || {}),
|
|
33
|
-
],
|
|
34
|
-
|
|
35
|
-
plugins: [
|
|
36
|
-
del({ targets: 'dist/*' }),
|
|
37
|
-
typescript({
|
|
38
|
-
typescript: require('typescript')
|
|
39
|
-
}),
|
|
40
|
-
// Allow json resolution
|
|
41
|
-
json(),
|
|
42
|
-
// // Allow bundling cjs modules (unlike webpack, rollup doesn't understand cjs)
|
|
43
|
-
commonjs(),
|
|
44
|
-
// // Allow node_modules resolution, so you can use 'external' to control
|
|
45
|
-
// // which external modules to include in the bundle
|
|
46
|
-
// // https://github.com/rollup/rollup-plugin-node-resolve#usage
|
|
47
|
-
resolve({
|
|
48
|
-
mainFields: ['module', 'main', 'browser']
|
|
49
|
-
}),
|
|
50
|
-
|
|
51
|
-
// // Resolve source maps to the original source
|
|
52
|
-
// sourceMaps(),
|
|
53
|
-
],
|
|
54
|
-
};
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { ParentBuilder } from "./parentBuilder";
|
|
2
|
-
import { ChildDefinition, ChildBuilder } from "../types/builders";
|
|
3
|
-
import { parentDefinitionDecoder, swimlaneWindowDefinitionDecoder } from "../shared/decoders";
|
|
4
|
-
import { IOConnectWorkspaces } from "../../workspaces";
|
|
5
|
-
import { WorkspaceBuilder } from "./workspaceBuilder";
|
|
6
|
-
|
|
7
|
-
export class BaseBuilder {
|
|
8
|
-
|
|
9
|
-
constructor(
|
|
10
|
-
private readonly getBuilder: (config: IOConnectWorkspaces.BuilderConfig) => ParentBuilder | WorkspaceBuilder,
|
|
11
|
-
) { }
|
|
12
|
-
|
|
13
|
-
public wrapChildren(children: ChildDefinition[]): ChildBuilder[] {
|
|
14
|
-
return children.map((child) => {
|
|
15
|
-
if (child.type === "window") {
|
|
16
|
-
return child;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return this.getBuilder({ type: child.type, definition: child }) as ParentBuilder;
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
public add(type: "row" | "column" | "group", children: ChildBuilder[], definition?: IOConnectWorkspaces.BoxDefinition): ParentBuilder {
|
|
24
|
-
const validatedDefinition = parentDefinitionDecoder.runWithException(definition);
|
|
25
|
-
|
|
26
|
-
const childBuilder = this.getBuilder({ type, definition: validatedDefinition }) as ParentBuilder;
|
|
27
|
-
|
|
28
|
-
children.push(childBuilder);
|
|
29
|
-
|
|
30
|
-
return childBuilder;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
public addWindow(children: ChildBuilder[], definition: IOConnectWorkspaces.WorkspaceWindowDefinition): void {
|
|
34
|
-
const validatedDefinition = swimlaneWindowDefinitionDecoder.runWithException(definition);
|
|
35
|
-
|
|
36
|
-
validatedDefinition.type = "window";
|
|
37
|
-
|
|
38
|
-
children.push(validatedDefinition);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
public serializeChildren(children: ChildBuilder[]): ChildDefinition[] {
|
|
42
|
-
return children.map((child) => {
|
|
43
|
-
if (child instanceof ParentBuilder) {
|
|
44
|
-
return child.serialize();
|
|
45
|
-
} else {
|
|
46
|
-
return child as IOConnectWorkspaces.WorkspaceWindowDefinition;
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { BaseBuilder } from "./baseBuilder";
|
|
2
|
-
import { ChildBuilder } from "../types/builders";
|
|
3
|
-
import { IOConnectWorkspaces } from "../../workspaces";
|
|
4
|
-
|
|
5
|
-
interface PrivateData {
|
|
6
|
-
definition: IOConnectWorkspaces.BoxDefinition;
|
|
7
|
-
base: BaseBuilder;
|
|
8
|
-
children: ChildBuilder[];
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const privateData = new WeakMap<ParentBuilder, PrivateData>();
|
|
12
|
-
|
|
13
|
-
export class ParentBuilder implements ParentBuilder {
|
|
14
|
-
|
|
15
|
-
constructor(
|
|
16
|
-
definition: IOConnectWorkspaces.BoxDefinition,
|
|
17
|
-
base: BaseBuilder
|
|
18
|
-
) {
|
|
19
|
-
const children = base.wrapChildren(definition.children);
|
|
20
|
-
|
|
21
|
-
delete definition.children;
|
|
22
|
-
|
|
23
|
-
privateData.set(this, { base, children, definition });
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
public get type(): "column" | "row" | "group" {
|
|
27
|
-
return privateData.get(this).definition.type;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
public addColumn(definition?: IOConnectWorkspaces.BoxDefinition): ParentBuilder {
|
|
31
|
-
const base = privateData.get(this).base;
|
|
32
|
-
|
|
33
|
-
return base.add("column", privateData.get(this).children, definition);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
public addRow(definition?: IOConnectWorkspaces.BoxDefinition): ParentBuilder {
|
|
37
|
-
const base = privateData.get(this).base;
|
|
38
|
-
|
|
39
|
-
return base.add("row", privateData.get(this).children, definition);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
public addGroup(definition?: IOConnectWorkspaces.BoxDefinition): ParentBuilder {
|
|
43
|
-
const base = privateData.get(this).base;
|
|
44
|
-
|
|
45
|
-
return base.add("group", privateData.get(this).children, definition);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
public addWindow(definition: IOConnectWorkspaces.WorkspaceWindowDefinition): ParentBuilder {
|
|
49
|
-
const base = privateData.get(this).base;
|
|
50
|
-
|
|
51
|
-
base.addWindow(privateData.get(this).children, definition);
|
|
52
|
-
|
|
53
|
-
return this;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
public serialize(): IOConnectWorkspaces.BoxDefinition {
|
|
57
|
-
const definition = privateData.get(this).definition;
|
|
58
|
-
definition.children = privateData.get(this).base.serializeChildren(privateData.get(this).children);
|
|
59
|
-
return definition;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
}
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { BaseBuilder } from "./baseBuilder";
|
|
2
|
-
import { ChildBuilder } from "../types/builders";
|
|
3
|
-
import { ParentBuilder } from "./parentBuilder";
|
|
4
|
-
import { workspaceBuilderCreateConfigDecoder, nonNegativeNumberDecoder } from "../shared/decoders";
|
|
5
|
-
import { IOConnectWorkspaces } from "../../workspaces";
|
|
6
|
-
import { WorkspacesController } from "../types/controller";
|
|
7
|
-
|
|
8
|
-
interface PrivateData {
|
|
9
|
-
definition: IOConnectWorkspaces.WorkspaceDefinition;
|
|
10
|
-
children: ChildBuilder[];
|
|
11
|
-
base: BaseBuilder;
|
|
12
|
-
controller: WorkspacesController;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const privateData = new WeakMap<WorkspaceBuilder, PrivateData>();
|
|
16
|
-
|
|
17
|
-
export class WorkspaceBuilder implements WorkspaceBuilder {
|
|
18
|
-
|
|
19
|
-
constructor(
|
|
20
|
-
definition: IOConnectWorkspaces.WorkspaceDefinition,
|
|
21
|
-
base: BaseBuilder,
|
|
22
|
-
controller: WorkspacesController
|
|
23
|
-
) {
|
|
24
|
-
const children = base.wrapChildren(definition.children);
|
|
25
|
-
|
|
26
|
-
delete definition.children;
|
|
27
|
-
|
|
28
|
-
privateData.set(this, { base, children, definition, controller });
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
public addColumn(definition?: IOConnectWorkspaces.BoxDefinition): ParentBuilder {
|
|
32
|
-
const children = privateData.get(this).children;
|
|
33
|
-
|
|
34
|
-
const areAllColumns = children.every((child) => child instanceof ParentBuilder && child.type === "column");
|
|
35
|
-
|
|
36
|
-
if (!areAllColumns) {
|
|
37
|
-
throw new Error("Cannot add a column to this workspace, because there are already children of another type");
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const base = privateData.get(this).base;
|
|
41
|
-
|
|
42
|
-
return base.add("column", children, definition);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
public addRow(definition?: IOConnectWorkspaces.BoxDefinition): ParentBuilder {
|
|
46
|
-
const children = privateData.get(this).children;
|
|
47
|
-
|
|
48
|
-
const areAllRows = children.every((child) => child instanceof ParentBuilder && child.type === "row");
|
|
49
|
-
|
|
50
|
-
if (!areAllRows) {
|
|
51
|
-
throw new Error("Cannot add a row to this workspace, because there are already children of another type");
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const base = privateData.get(this).base;
|
|
55
|
-
|
|
56
|
-
return base.add("row", children, definition);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
public addGroup(definition?: IOConnectWorkspaces.BoxDefinition): ParentBuilder {
|
|
60
|
-
const children = privateData.get(this).children;
|
|
61
|
-
|
|
62
|
-
if (children.length !== 0) {
|
|
63
|
-
throw new Error("Cannot add a group to this workspace, because there are already defined children.");
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const base = privateData.get(this).base;
|
|
67
|
-
|
|
68
|
-
return base.add("group", children, definition);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
public addWindow(definition: IOConnectWorkspaces.WorkspaceWindowDefinition): WorkspaceBuilder {
|
|
72
|
-
const children = privateData.get(this).children;
|
|
73
|
-
|
|
74
|
-
if (children.length !== 0) {
|
|
75
|
-
throw new Error("Cannot add a window to this workspace, because there are already defined children.");
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const base = privateData.get(this).base;
|
|
79
|
-
|
|
80
|
-
base.addWindow(children, definition);
|
|
81
|
-
|
|
82
|
-
return this;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
public getChildAt(index: number): ChildBuilder {
|
|
86
|
-
nonNegativeNumberDecoder.runWithException(index);
|
|
87
|
-
const data = privateData.get(this).children;
|
|
88
|
-
|
|
89
|
-
return data[index];
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
public async create(config?: IOConnectWorkspaces.WorkspaceCreateConfig): Promise<IOConnectWorkspaces.Workspace> {
|
|
93
|
-
const saveConfig = workspaceBuilderCreateConfigDecoder.runWithException(config);
|
|
94
|
-
|
|
95
|
-
const definition = privateData.get(this).definition;
|
|
96
|
-
definition.children = privateData.get(this).base.serializeChildren(privateData.get(this).children);
|
|
97
|
-
|
|
98
|
-
const controller = privateData.get(this).controller;
|
|
99
|
-
|
|
100
|
-
return controller.createWorkspace(definition, saveConfig);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
import { CallbackRegistry, UnsubscribeFunction } from "callback-registry";
|
|
2
|
-
import { SubscriptionConfig, ActiveSubscription, WorkspaceEventType, WorkspaceEventAction, WorkspacePayload, WorkspaceEventScope, PendingSubscription } from "../types/subscription";
|
|
3
|
-
import { ClientOperations, CLIENT_OPERATIONS, STREAMS } from "./constants";
|
|
4
|
-
import { OPERATIONS } from "./constants";
|
|
5
|
-
import { eventTypeDecoder, streamRequestArgumentsDecoder, workspaceEventActionDecoder } from "../shared/decoders";
|
|
6
|
-
import { IOConnectWorkspaces } from "../../workspaces";
|
|
7
|
-
import { InteropTransport } from "./interop-transport";
|
|
8
|
-
import { PromiseWrapper } from "../shared/promiseWrapper";
|
|
9
|
-
import { Instance } from "../types/glue";
|
|
10
|
-
|
|
11
|
-
export class Bridge {
|
|
12
|
-
|
|
13
|
-
private readonly activeSubscriptions: ActiveSubscription[] = [];
|
|
14
|
-
private readonly pendingSubScriptions: PendingSubscription[] = [];
|
|
15
|
-
|
|
16
|
-
constructor(
|
|
17
|
-
private readonly transport: InteropTransport,
|
|
18
|
-
private readonly registry: CallbackRegistry
|
|
19
|
-
) { }
|
|
20
|
-
|
|
21
|
-
public async createCoreEventSubscription(): Promise<void> {
|
|
22
|
-
await this.transport.coreSubscriptionReady(this.handleCoreEvent.bind(this));
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
public handleCoreSubscription(config: SubscriptionConfig): UnsubscribeFunction {
|
|
26
|
-
const registryKey = `${config.eventType}-${config.action}`;
|
|
27
|
-
const scope = config.scope;
|
|
28
|
-
const scopeId = config.scopeId;
|
|
29
|
-
|
|
30
|
-
return this.registry.add(registryKey, (args) => {
|
|
31
|
-
const scopeConfig = {
|
|
32
|
-
type: scope,
|
|
33
|
-
id: scopeId
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const receivedIds = {
|
|
37
|
-
frame: args.frameSummary?.id || args.windowSummary?.config.frameId,
|
|
38
|
-
workspace: args.workspaceSummary?.id || args.windowSummary?.config.workspaceId,
|
|
39
|
-
container: args.containerSummary?.itemId,
|
|
40
|
-
window: args.windowSummary?.itemId
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
const shouldInvokeCallback = this.checkScopeMatch(scopeConfig, receivedIds);
|
|
44
|
-
|
|
45
|
-
if (!shouldInvokeCallback) {
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
config.callback(args);
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
54
|
-
public async send<T>(operationName: string, operationArgs?: any): Promise<T> {
|
|
55
|
-
|
|
56
|
-
const operationDefinition = Object.values(OPERATIONS).find((operation) => operation.name === operationName);
|
|
57
|
-
|
|
58
|
-
if (!operationDefinition) {
|
|
59
|
-
throw new Error(`Cannot find definition for operation name: ${operationName}`);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (operationDefinition.argsDecoder) {
|
|
63
|
-
try {
|
|
64
|
-
operationDefinition.argsDecoder.runWithException(operationArgs);
|
|
65
|
-
} catch (error) {
|
|
66
|
-
throw new Error(`Unexpected internal outgoing validation error: ${error.message}, for input: ${JSON.stringify(error.input)}, for operation ${operationName}`);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
try {
|
|
71
|
-
const operationResult = await this.transport.transmitControl(operationDefinition.name, operationArgs);
|
|
72
|
-
|
|
73
|
-
operationDefinition.resultDecoder.runWithException(operationResult);
|
|
74
|
-
|
|
75
|
-
return operationResult;
|
|
76
|
-
} catch (error) {
|
|
77
|
-
if (error.kind) {
|
|
78
|
-
throw new Error(`Unexpected internal incoming validation error: ${error.message}, for input: ${JSON.stringify(error.input)}, for operation ${operationName}`);
|
|
79
|
-
}
|
|
80
|
-
throw new Error(error.message);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
public async subscribe(config: SubscriptionConfig): Promise<IOConnectWorkspaces.Unsubscribe> {
|
|
85
|
-
const pendingSub = this.getPendingSubscription(config);
|
|
86
|
-
if (pendingSub) {
|
|
87
|
-
await pendingSub.promise;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
let activeSub = this.getActiveSubscription(config);
|
|
91
|
-
const registryKey = this.getRegistryKey(config);
|
|
92
|
-
|
|
93
|
-
if (!activeSub) {
|
|
94
|
-
const pendingPromise = new PromiseWrapper<void>();
|
|
95
|
-
const pendingSubscription = {
|
|
96
|
-
streamType: config.eventType,
|
|
97
|
-
level: config.scope,
|
|
98
|
-
levelId: config.scopeId,
|
|
99
|
-
promise: pendingPromise.promise
|
|
100
|
-
};
|
|
101
|
-
this.pendingSubScriptions.push(pendingSubscription);
|
|
102
|
-
try {
|
|
103
|
-
const stream = STREAMS[config.eventType];
|
|
104
|
-
const gdSub = await this.transport.subscribe(stream.name, this.getBranchKey(config), config.eventType);
|
|
105
|
-
|
|
106
|
-
gdSub.onData((streamData) => {
|
|
107
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
108
|
-
const data = streamData.data as { action: string; payload: any };
|
|
109
|
-
|
|
110
|
-
// important to decode without exception, because we do not want to throw an exception here
|
|
111
|
-
const requestedArgumentsResult = streamRequestArgumentsDecoder.run(streamData.requestArguments);
|
|
112
|
-
const actionResult = workspaceEventActionDecoder.run(data.action);
|
|
113
|
-
|
|
114
|
-
if (!requestedArgumentsResult.ok || !actionResult.ok) {
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const streamType = requestedArgumentsResult.result.type;
|
|
119
|
-
const branch = requestedArgumentsResult.result.branch;
|
|
120
|
-
|
|
121
|
-
const keyToExecute = `${streamType}-${branch}-${actionResult.result}`;
|
|
122
|
-
const validatedPayload = STREAMS[streamType].payloadDecoder.run(data.payload);
|
|
123
|
-
if (!validatedPayload.ok) {
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
this.registry.execute(keyToExecute, validatedPayload.result);
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
activeSub = {
|
|
131
|
-
streamType: config.eventType,
|
|
132
|
-
level: config.scope,
|
|
133
|
-
levelId: config.scopeId,
|
|
134
|
-
callbacksCount: 0,
|
|
135
|
-
gdSub
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
this.activeSubscriptions.push(activeSub);
|
|
139
|
-
|
|
140
|
-
pendingPromise.resolve();
|
|
141
|
-
} catch (error) {
|
|
142
|
-
pendingPromise.reject(error);
|
|
143
|
-
|
|
144
|
-
throw error;
|
|
145
|
-
} finally {
|
|
146
|
-
this.removePendingSubscription(pendingSubscription);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const unsubscribe = this.registry.add(registryKey, config.callback);
|
|
152
|
-
|
|
153
|
-
++activeSub.callbacksCount;
|
|
154
|
-
|
|
155
|
-
return (): void => {
|
|
156
|
-
unsubscribe();
|
|
157
|
-
--activeSub.callbacksCount;
|
|
158
|
-
|
|
159
|
-
if (activeSub.callbacksCount === 0) {
|
|
160
|
-
activeSub.gdSub.close();
|
|
161
|
-
this.activeSubscriptions.splice(this.activeSubscriptions.indexOf(activeSub), 1);
|
|
162
|
-
}
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
public onOperation(callback: (operation: ClientOperations, caller: Instance) => void) {
|
|
167
|
-
|
|
168
|
-
const wrappedCallback = (payload: ClientOperations, caller: Instance) => {
|
|
169
|
-
const operationName = payload.operation;
|
|
170
|
-
const operationArgs = payload.data;
|
|
171
|
-
const operationDefinition = Object.values(CLIENT_OPERATIONS).find((operation) => operation.name === operationName);
|
|
172
|
-
|
|
173
|
-
if (!operationDefinition) {
|
|
174
|
-
throw new Error(`Cannot find definition for operation name: ${operationName}`);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
if (operationDefinition.argsDecoder) {
|
|
178
|
-
try {
|
|
179
|
-
operationDefinition.argsDecoder.runWithException(operationArgs);
|
|
180
|
-
} catch (error) {
|
|
181
|
-
throw new Error(`Unexpected internal outgoing validation error: ${error.message}, for input: ${JSON.stringify(error.input)}, for operation ${operationName}`);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
callback(payload, caller);
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
return this.transport.onInternalMethodInvoked("control", wrappedCallback);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
private checkScopeMatch(scope: { type: WorkspaceEventScope; id?: string }, receivedIds: { frame: string; workspace: string; container: string; window: string }): boolean {
|
|
192
|
-
|
|
193
|
-
if (scope.type === "global") {
|
|
194
|
-
return true;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
if (scope.type === "frame" && scope.id === receivedIds.frame) {
|
|
198
|
-
return true;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
if (scope.type === "workspace" && scope.id === receivedIds.workspace) {
|
|
202
|
-
return true;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
if (scope.type === "container" && scope.id === receivedIds.container) {
|
|
206
|
-
return true;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
if (scope.type === "window" && scope.id === receivedIds.window) {
|
|
210
|
-
return true;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
return false;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
217
|
-
private handleCoreEvent(args: any): void {
|
|
218
|
-
const data = args.data;
|
|
219
|
-
try {
|
|
220
|
-
const verifiedAction: WorkspaceEventAction = workspaceEventActionDecoder.runWithException(data.action);
|
|
221
|
-
const verifiedType: WorkspaceEventType = eventTypeDecoder.runWithException(data.type);
|
|
222
|
-
const verifiedPayload: WorkspacePayload = STREAMS[verifiedType].payloadDecoder.runWithException(data.payload);
|
|
223
|
-
|
|
224
|
-
const registryKey = `${verifiedType}-${verifiedAction}`;
|
|
225
|
-
|
|
226
|
-
this.registry.execute(registryKey, verifiedPayload);
|
|
227
|
-
} catch (error) {
|
|
228
|
-
console.warn(`Cannot handle event with data ${JSON.stringify(data)}, because of validation error: ${error.message}`);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
private getBranchKey(config: SubscriptionConfig): string {
|
|
233
|
-
return config.scope === "global" ? config.scope : `${config.scope}_${config.scopeId}`;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
private getRegistryKey(config: SubscriptionConfig): string {
|
|
237
|
-
return `${config.eventType}-${this.getBranchKey(config)}-${config.action}`;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
private getActiveSubscription(config: SubscriptionConfig): ActiveSubscription {
|
|
241
|
-
return this.activeSubscriptions
|
|
242
|
-
.find((activeSub) => activeSub.streamType === config.eventType &&
|
|
243
|
-
activeSub.level === config.scope &&
|
|
244
|
-
activeSub.levelId === config.scopeId
|
|
245
|
-
);
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
private getPendingSubscription(config: SubscriptionConfig): PendingSubscription {
|
|
249
|
-
return this.pendingSubScriptions
|
|
250
|
-
.find((activeSub) => activeSub.streamType === config.eventType &&
|
|
251
|
-
activeSub.level === config.scope &&
|
|
252
|
-
activeSub.levelId === config.scopeId
|
|
253
|
-
);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
private removePendingSubscription(pendingSubscription: PendingSubscription): void {
|
|
257
|
-
const index = this.pendingSubScriptions.indexOf(pendingSubscription);
|
|
258
|
-
|
|
259
|
-
if (index >= 0) {
|
|
260
|
-
this.pendingSubScriptions.splice(index, 1);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
}
|