@interopio/workspaces-api 3.5.5 → 3.5.7
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/changelog.md +5 -0
- package/dist/workspaces.es.js +179 -10
- package/dist/workspaces.es.js.map +1 -1
- package/dist/workspaces.umd.js +179 -10
- package/dist/workspaces.umd.js.map +1 -1
- package/dist/workspaces.umd.min.js +1 -1
- package/package.json +2 -2
- package/workspaces.d.ts +68 -4
package/dist/workspaces.umd.js
CHANGED
|
@@ -916,6 +916,13 @@
|
|
|
916
916
|
const isWindowInSwimlaneResultDecoder = object({
|
|
917
917
|
inWorkspace: boolean()
|
|
918
918
|
});
|
|
919
|
+
const iconDecoder = object({
|
|
920
|
+
base64Image: nonEmptyStringDecoder
|
|
921
|
+
});
|
|
922
|
+
const setIconArgumentsDecoder = object({
|
|
923
|
+
icon: iconDecoder,
|
|
924
|
+
frameId: nonEmptyStringDecoder
|
|
925
|
+
});
|
|
919
926
|
const allParentDecoder = oneOf(constant("workspace"), constant("row"), constant("column"), constant("group"));
|
|
920
927
|
const subParentDecoder = oneOf(constant("row"), constant("column"), constant("group"));
|
|
921
928
|
const frameStateDecoder = oneOf(constant("maximized"), constant("minimized"), constant("normal"));
|
|
@@ -1170,7 +1177,8 @@
|
|
|
1170
1177
|
widthInPx: optional(number()),
|
|
1171
1178
|
heightInPx: optional(number()),
|
|
1172
1179
|
isPinned: optional(boolean()),
|
|
1173
|
-
windowDragMode: optional(windowDragModeDecoder)
|
|
1180
|
+
windowDragMode: optional(windowDragModeDecoder),
|
|
1181
|
+
loadingStrategy: optional(loadingStrategyDecoder)
|
|
1174
1182
|
});
|
|
1175
1183
|
const baseChildSnapshotConfigDecoder = object({
|
|
1176
1184
|
frameId: nonEmptyStringDecoder,
|
|
@@ -1344,6 +1352,14 @@
|
|
|
1344
1352
|
const simpleItemConfigDecoder = object({
|
|
1345
1353
|
itemId: nonEmptyStringDecoder
|
|
1346
1354
|
});
|
|
1355
|
+
const closeOptionsDecoder = object({
|
|
1356
|
+
allowPrevent: optional(boolean()),
|
|
1357
|
+
showDialog: optional(boolean()),
|
|
1358
|
+
});
|
|
1359
|
+
const closeItemConfigDecoder = object({
|
|
1360
|
+
itemId: nonEmptyStringDecoder,
|
|
1361
|
+
closeOptions: optional(closeOptionsDecoder)
|
|
1362
|
+
});
|
|
1347
1363
|
const frameSnapshotConfigDecoder = object({
|
|
1348
1364
|
itemId: nonEmptyStringDecoder,
|
|
1349
1365
|
excludeIds: optional(boolean())
|
|
@@ -1517,6 +1533,9 @@
|
|
|
1517
1533
|
shortcut: nonEmptyStringDecoder,
|
|
1518
1534
|
frameId: nonEmptyStringDecoder
|
|
1519
1535
|
});
|
|
1536
|
+
const frameClosingDataDecoder = object({
|
|
1537
|
+
frameId: nonEmptyStringDecoder,
|
|
1538
|
+
});
|
|
1520
1539
|
const setMaximizationBoundaryAPIConfigDecoder = object({
|
|
1521
1540
|
enabled: boolean()
|
|
1522
1541
|
});
|
|
@@ -1531,6 +1550,13 @@
|
|
|
1531
1550
|
itemId: nonEmptyStringDecoder,
|
|
1532
1551
|
dragMode: windowDragModeDecoder
|
|
1533
1552
|
});
|
|
1553
|
+
const setLoadingStrategyDecoder = object({
|
|
1554
|
+
itemId: nonEmptyStringDecoder,
|
|
1555
|
+
strategy: loadingStrategyDecoder
|
|
1556
|
+
});
|
|
1557
|
+
const frameClosingResultDecoder = object({
|
|
1558
|
+
prevent: boolean()
|
|
1559
|
+
});
|
|
1534
1560
|
|
|
1535
1561
|
const webPlatformMethodName = "T42.Web.Platform.Control";
|
|
1536
1562
|
const webPlatformWspStreamName = "T42.Web.Platform.WSP.Stream";
|
|
@@ -1552,6 +1578,7 @@
|
|
|
1552
1578
|
};
|
|
1553
1579
|
const CLIENT_OPERATIONS = {
|
|
1554
1580
|
shortcutClicked: { name: "shortcutClicked", argsDecoder: shortcutClickedDataDecoder, resultDecoder: voidResultDecoder },
|
|
1581
|
+
frameClosing: { name: "frameClosing", argsDecoder: frameClosingDataDecoder, resultDecoder: frameClosingResultDecoder },
|
|
1555
1582
|
};
|
|
1556
1583
|
const OPERATIONS = {
|
|
1557
1584
|
ping: { name: "ping", resultDecoder: pingResultDecoder },
|
|
@@ -1573,7 +1600,7 @@
|
|
|
1573
1600
|
restoreItem: { name: "restoreItem", argsDecoder: simpleItemConfigDecoder, resultDecoder: voidResultDecoder },
|
|
1574
1601
|
maximizeItem: { name: "maximizeItem", argsDecoder: simpleItemConfigDecoder, resultDecoder: voidResultDecoder },
|
|
1575
1602
|
focusItem: { name: "focusItem", argsDecoder: simpleItemConfigDecoder, resultDecoder: voidResultDecoder },
|
|
1576
|
-
closeItem: { name: "closeItem", argsDecoder:
|
|
1603
|
+
closeItem: { name: "closeItem", argsDecoder: closeItemConfigDecoder, resultDecoder: voidResultDecoder },
|
|
1577
1604
|
resizeItem: { name: "resizeItem", argsDecoder: resizeItemConfigDecoder, resultDecoder: voidResultDecoder },
|
|
1578
1605
|
setMaximizationBoundary: { name: "setMaximizationBoundary", argsDecoder: setMaximizationBoundaryConfigDecoder, resultDecoder: voidResultDecoder },
|
|
1579
1606
|
changeFrameState: { name: "changeFrameState", argsDecoder: frameStateConfigDecoder, resultDecoder: voidResultDecoder },
|
|
@@ -1604,7 +1631,11 @@
|
|
|
1604
1631
|
hideLoadingAnimation: { name: "hideLoadingAnimation", argsDecoder: loadingAnimationConfigDecoder, resultDecoder: voidResultDecoder },
|
|
1605
1632
|
getPlatformFrameId: { name: "getPlatformFrameId", resultDecoder: getPlatformFrameIdResultDecoder },
|
|
1606
1633
|
operationCheck: { name: "operationCheck", argsDecoder: operationCheckConfigDecoder, resultDecoder: operationCheckResultDecoder },
|
|
1607
|
-
setWindowDragMode: { name: "setWindowDragMode", argsDecoder: setWindowDragModeDecoder, resultDecoder: voidResultDecoder }
|
|
1634
|
+
setWindowDragMode: { name: "setWindowDragMode", argsDecoder: setWindowDragModeDecoder, resultDecoder: voidResultDecoder },
|
|
1635
|
+
setLoadingStrategy: { name: "setLoadingStrategy", argsDecoder: setLoadingStrategyDecoder, resultDecoder: voidResultDecoder },
|
|
1636
|
+
getTaskbarIcon: { name: "getTaskbarIcon", resultDecoder: iconDecoder },
|
|
1637
|
+
setTaskbarIcon: { name: "setTaskbarIcon", argsDecoder: setIconArgumentsDecoder, resultDecoder: voidResultDecoder },
|
|
1638
|
+
subscribeToFrameClosing: { name: "subscribeToFrameClosing", argsDecoder: simpleItemConfigDecoder, resultDecoder: voidResultDecoder }
|
|
1608
1639
|
};
|
|
1609
1640
|
|
|
1610
1641
|
class PromiseWrapper {
|
|
@@ -1762,6 +1793,35 @@
|
|
|
1762
1793
|
};
|
|
1763
1794
|
return this.transport.onInternalMethodInvoked("control", wrappedCallback);
|
|
1764
1795
|
}
|
|
1796
|
+
onOperationWithResponse(callback) {
|
|
1797
|
+
const wrappedCallback = async (payload, caller) => {
|
|
1798
|
+
const operationName = payload.operation;
|
|
1799
|
+
const operationArgs = payload.data;
|
|
1800
|
+
const operationDefinition = Object.values(CLIENT_OPERATIONS).find((operation) => operation.name === operationName);
|
|
1801
|
+
if (!operationDefinition) {
|
|
1802
|
+
throw new Error(`Cannot find definition for operation name: ${operationName}`);
|
|
1803
|
+
}
|
|
1804
|
+
if (operationDefinition.argsDecoder) {
|
|
1805
|
+
try {
|
|
1806
|
+
operationDefinition.argsDecoder.runWithException(operationArgs);
|
|
1807
|
+
}
|
|
1808
|
+
catch (error) {
|
|
1809
|
+
throw new Error(`Unexpected internal outgoing validation error: ${error.message}, for input: ${JSON.stringify(error.input)}, for operation ${operationName}`);
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
const result = await callback(payload, caller);
|
|
1813
|
+
if (operationDefinition.resultDecoder) {
|
|
1814
|
+
try {
|
|
1815
|
+
operationDefinition.resultDecoder.runWithException(result);
|
|
1816
|
+
}
|
|
1817
|
+
catch (error) {
|
|
1818
|
+
throw new Error(`Unexpected internal outgoing result validation error: ${error.message}, for input: ${JSON.stringify(error.input)}, for operation ${operationName}`);
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
return result;
|
|
1822
|
+
};
|
|
1823
|
+
return this.transport.onInternalMethodInvoked("control", wrappedCallback);
|
|
1824
|
+
}
|
|
1765
1825
|
checkScopeMatch(scope, receivedIds) {
|
|
1766
1826
|
if (scope.type === "global") {
|
|
1767
1827
|
return true;
|
|
@@ -1975,7 +2035,7 @@
|
|
|
1975
2035
|
registerMethod(key) {
|
|
1976
2036
|
const method = INCOMING_METHODS[key];
|
|
1977
2037
|
return this.agm.register(method.name, (args, caller) => {
|
|
1978
|
-
this.registry.execute(key, args, caller);
|
|
2038
|
+
return Promise.all(this.registry.execute(key, args, caller));
|
|
1979
2039
|
});
|
|
1980
2040
|
}
|
|
1981
2041
|
}
|
|
@@ -2685,6 +2745,20 @@
|
|
|
2685
2745
|
}
|
|
2686
2746
|
return getData$3(this).config.windowDragMode;
|
|
2687
2747
|
}
|
|
2748
|
+
get loadingStrategy() {
|
|
2749
|
+
if (!isDesktop()) {
|
|
2750
|
+
console.warn("The workspace.loadingStrategy property is not supported in IO Connect Browser");
|
|
2751
|
+
}
|
|
2752
|
+
return getData$3(this).config.loadingStrategy;
|
|
2753
|
+
}
|
|
2754
|
+
async setLoadingStrategy(strategy) {
|
|
2755
|
+
if (!isDesktop()) {
|
|
2756
|
+
throw new Error("Not supported in IO Connect Browser");
|
|
2757
|
+
}
|
|
2758
|
+
const controller = getData$3(this).controller;
|
|
2759
|
+
await controller.setLoadingStrategy(this.id, strategy);
|
|
2760
|
+
await this.refreshReference();
|
|
2761
|
+
}
|
|
2688
2762
|
async removeChild(predicate) {
|
|
2689
2763
|
checkThrowCallback(predicate);
|
|
2690
2764
|
const child = this.children.find(predicate);
|
|
@@ -3414,6 +3488,21 @@
|
|
|
3414
3488
|
const myId = getData$1(this).summary.id;
|
|
3415
3489
|
return getData$1(this).controller.getFrameState(myId);
|
|
3416
3490
|
}
|
|
3491
|
+
setIcon(icon) {
|
|
3492
|
+
if (!isDesktop()) {
|
|
3493
|
+
throw new Error("frame.setIcon() is not supported in IO Connect Browser");
|
|
3494
|
+
}
|
|
3495
|
+
iconDecoder.runWithException(icon);
|
|
3496
|
+
const frameId = this.id;
|
|
3497
|
+
return getData$1(this).controller.setTaskbarIcon(icon, frameId);
|
|
3498
|
+
}
|
|
3499
|
+
getIcon() {
|
|
3500
|
+
if (!isDesktop()) {
|
|
3501
|
+
throw new Error("frame.getIcon() is not supported in IO Connect Browser");
|
|
3502
|
+
}
|
|
3503
|
+
const frameId = this.id;
|
|
3504
|
+
return getData$1(this).controller.getTaskbarIcon(frameId);
|
|
3505
|
+
}
|
|
3417
3506
|
async minimize() {
|
|
3418
3507
|
if (!isDesktop()) {
|
|
3419
3508
|
throw new Error("State operations are not supported in IO Connect Browser");
|
|
@@ -3435,9 +3524,10 @@
|
|
|
3435
3524
|
const myId = getData$1(this).summary.id;
|
|
3436
3525
|
return getData$1(this).controller.changeFrameState(myId, "normal");
|
|
3437
3526
|
}
|
|
3438
|
-
close() {
|
|
3527
|
+
close(options) {
|
|
3528
|
+
const validatedOptions = optional(closeOptionsDecoder).runWithException(options);
|
|
3439
3529
|
const myId = getData$1(this).summary.id;
|
|
3440
|
-
return getData$1(this).controller.
|
|
3530
|
+
return getData$1(this).controller.closeFrame(myId, validatedOptions);
|
|
3441
3531
|
}
|
|
3442
3532
|
snapshot() {
|
|
3443
3533
|
const myId = getData$1(this).summary.id;
|
|
@@ -3469,6 +3559,20 @@
|
|
|
3469
3559
|
}
|
|
3470
3560
|
return getData$1(this).controller.initFrame(this.id, config);
|
|
3471
3561
|
}
|
|
3562
|
+
async onClosing(callback) {
|
|
3563
|
+
if (!isDesktop()) {
|
|
3564
|
+
throw new Error("Frame closing operations are not supported in io.Connect Browser");
|
|
3565
|
+
}
|
|
3566
|
+
checkThrowCallback(callback);
|
|
3567
|
+
const wrappedCallback = async () => {
|
|
3568
|
+
let shouldPrevent = false;
|
|
3569
|
+
const preventClose = () => shouldPrevent = true;
|
|
3570
|
+
await callback({ prevent: preventClose });
|
|
3571
|
+
return { prevent: shouldPrevent };
|
|
3572
|
+
};
|
|
3573
|
+
const unsubscribe = await getData$1(this).controller.registerFrameOnClosing(this.id, wrappedCallback);
|
|
3574
|
+
return unsubscribe;
|
|
3575
|
+
}
|
|
3472
3576
|
async onClosed(callback) {
|
|
3473
3577
|
checkThrowCallback(callback);
|
|
3474
3578
|
const myId = getData$1(this).summary.id;
|
|
@@ -4154,6 +4258,12 @@
|
|
|
4154
4258
|
}
|
|
4155
4259
|
await this.bridge.send(OPERATIONS.bundleItem.name, { type, itemId });
|
|
4156
4260
|
}
|
|
4261
|
+
async getTaskbarIcon(frameId) {
|
|
4262
|
+
return await this.bridge.send(OPERATIONS.getTaskbarIcon.name, { frameId });
|
|
4263
|
+
}
|
|
4264
|
+
async setTaskbarIcon(icon, frameId) {
|
|
4265
|
+
await this.bridge.send(OPERATIONS.setTaskbarIcon.name, { icon, frameId });
|
|
4266
|
+
}
|
|
4157
4267
|
getWorkspaceContext(workspaceId) {
|
|
4158
4268
|
const contextName = `___workspace___${workspaceId}`;
|
|
4159
4269
|
return this.contexts.get(contextName);
|
|
@@ -4182,6 +4292,9 @@
|
|
|
4182
4292
|
async closeItem(itemId) {
|
|
4183
4293
|
await this.bridge.send(OPERATIONS.closeItem.name, { itemId });
|
|
4184
4294
|
}
|
|
4295
|
+
async closeFrame(itemId, closeOptions) {
|
|
4296
|
+
await this.bridge.send(OPERATIONS.closeItem.name, { itemId, closeOptions });
|
|
4297
|
+
}
|
|
4185
4298
|
async resizeItem(itemId, config) {
|
|
4186
4299
|
await this.bridge.send(OPERATIONS.resizeItem.name, Object.assign({}, { itemId }, config));
|
|
4187
4300
|
}
|
|
@@ -4364,6 +4477,10 @@
|
|
|
4364
4477
|
return {};
|
|
4365
4478
|
}
|
|
4366
4479
|
}
|
|
4480
|
+
async setLoadingStrategy(workspaceId, strategy) {
|
|
4481
|
+
await this.isOperationSupported(OPERATIONS.setLoadingStrategy.name);
|
|
4482
|
+
return this.bridge.send(OPERATIONS.setLoadingStrategy.name, { itemId: workspaceId, strategy });
|
|
4483
|
+
}
|
|
4367
4484
|
async isOperationSupported(operation) {
|
|
4368
4485
|
if (isDesktop()) {
|
|
4369
4486
|
return { isSupported: true };
|
|
@@ -4376,10 +4493,18 @@
|
|
|
4376
4493
|
bridge;
|
|
4377
4494
|
base;
|
|
4378
4495
|
shortcutsController;
|
|
4379
|
-
|
|
4496
|
+
closingController;
|
|
4497
|
+
constructor(bridge, base, shortcutsController, closingController) {
|
|
4380
4498
|
this.bridge = bridge;
|
|
4381
4499
|
this.base = base;
|
|
4382
4500
|
this.shortcutsController = shortcutsController;
|
|
4501
|
+
this.closingController = closingController;
|
|
4502
|
+
}
|
|
4503
|
+
setTaskbarIcon(icon, frameId) {
|
|
4504
|
+
return this.base.setTaskbarIcon(icon, frameId);
|
|
4505
|
+
}
|
|
4506
|
+
getTaskbarIcon(frameId) {
|
|
4507
|
+
return this.base.getTaskbarIcon(frameId);
|
|
4383
4508
|
}
|
|
4384
4509
|
checkIsWindowLoaded(windowId) {
|
|
4385
4510
|
return this.base.checkIsWindowLoaded(windowId);
|
|
@@ -4582,6 +4707,9 @@
|
|
|
4582
4707
|
async closeItem(itemId) {
|
|
4583
4708
|
return await this.base.closeItem(itemId);
|
|
4584
4709
|
}
|
|
4710
|
+
async closeFrame(itemId, closeOptions) {
|
|
4711
|
+
return await this.base.closeFrame(itemId, closeOptions);
|
|
4712
|
+
}
|
|
4585
4713
|
async resizeItem(itemId, config) {
|
|
4586
4714
|
return await this.base.resizeItem(itemId, config);
|
|
4587
4715
|
}
|
|
@@ -4682,6 +4810,12 @@
|
|
|
4682
4810
|
getPlatformFrameId() {
|
|
4683
4811
|
return this.base.getPlatformFrameId();
|
|
4684
4812
|
}
|
|
4813
|
+
setLoadingStrategy(workspaceId, strategy) {
|
|
4814
|
+
return this.base.setLoadingStrategy(workspaceId, strategy);
|
|
4815
|
+
}
|
|
4816
|
+
registerFrameOnClosing(frameId, callback) {
|
|
4817
|
+
return this.closingController.registerFrameOnClosing(frameId, callback);
|
|
4818
|
+
}
|
|
4685
4819
|
async handleCoreLocalSubscription(config, levelId) {
|
|
4686
4820
|
await this.bridge.createCoreEventSubscription();
|
|
4687
4821
|
config.scopeId = config.scopeId || levelId;
|
|
@@ -4755,7 +4889,7 @@
|
|
|
4755
4889
|
_shortcuts = CallbackFactory();
|
|
4756
4890
|
constructor(bridge) {
|
|
4757
4891
|
this.bridge = bridge;
|
|
4758
|
-
this.bridge.onOperation((payload
|
|
4892
|
+
this.bridge.onOperation((payload) => {
|
|
4759
4893
|
if (payload.operation === CLIENT_OPERATIONS.shortcutClicked.name) {
|
|
4760
4894
|
const data = payload.data;
|
|
4761
4895
|
this._shortcuts.execute(`${data.frameId}-${data.shortcut}`);
|
|
@@ -4772,6 +4906,34 @@
|
|
|
4772
4906
|
}
|
|
4773
4907
|
}
|
|
4774
4908
|
|
|
4909
|
+
class ClosingController {
|
|
4910
|
+
bridge;
|
|
4911
|
+
registry = CallbackFactory();
|
|
4912
|
+
constructor(bridge) {
|
|
4913
|
+
this.bridge = bridge;
|
|
4914
|
+
this.subscribeToFrameClosing();
|
|
4915
|
+
}
|
|
4916
|
+
async registerFrameOnClosing(frameId, callback) {
|
|
4917
|
+
await this.bridge.send(OPERATIONS.subscribeToFrameClosing.name, { itemId: frameId });
|
|
4918
|
+
return this.registry.add(frameId, callback);
|
|
4919
|
+
}
|
|
4920
|
+
subscribeToFrameClosing() {
|
|
4921
|
+
this.bridge.onOperationWithResponse(async (payload) => {
|
|
4922
|
+
if (payload.operation !== CLIENT_OPERATIONS.frameClosing.name) {
|
|
4923
|
+
return;
|
|
4924
|
+
}
|
|
4925
|
+
const data = payload.data;
|
|
4926
|
+
const frameClosingResult = await Promise.all(this.registry.execute(data.frameId));
|
|
4927
|
+
return this.aggregateFrameClosingResult(frameClosingResult);
|
|
4928
|
+
});
|
|
4929
|
+
}
|
|
4930
|
+
aggregateFrameClosingResult(results) {
|
|
4931
|
+
return {
|
|
4932
|
+
prevent: results.some((result) => result?.prevent)
|
|
4933
|
+
};
|
|
4934
|
+
}
|
|
4935
|
+
}
|
|
4936
|
+
|
|
4775
4937
|
class IoC {
|
|
4776
4938
|
agm;
|
|
4777
4939
|
windows;
|
|
@@ -4784,6 +4946,7 @@
|
|
|
4784
4946
|
_parentBaseInstance;
|
|
4785
4947
|
_baseController;
|
|
4786
4948
|
_shortcutsController;
|
|
4949
|
+
_closingController;
|
|
4787
4950
|
constructor(agm, windows, layouts, contexts) {
|
|
4788
4951
|
this.agm = agm;
|
|
4789
4952
|
this.windows = windows;
|
|
@@ -4798,7 +4961,7 @@
|
|
|
4798
4961
|
}
|
|
4799
4962
|
get controller() {
|
|
4800
4963
|
if (!this._controllerInstance) {
|
|
4801
|
-
this._controllerInstance = new MainController(this.bridge, this.baseController, this.shortcutsController);
|
|
4964
|
+
this._controllerInstance = new MainController(this.bridge, this.baseController, this.shortcutsController, this.closingController);
|
|
4802
4965
|
}
|
|
4803
4966
|
return this._controllerInstance;
|
|
4804
4967
|
}
|
|
@@ -4808,6 +4971,12 @@
|
|
|
4808
4971
|
}
|
|
4809
4972
|
return this._shortcutsController;
|
|
4810
4973
|
}
|
|
4974
|
+
get closingController() {
|
|
4975
|
+
if (!this._closingController) {
|
|
4976
|
+
this._closingController = new ClosingController(this.bridge);
|
|
4977
|
+
}
|
|
4978
|
+
return this._closingController;
|
|
4979
|
+
}
|
|
4811
4980
|
get bridge() {
|
|
4812
4981
|
if (!this._bridgeInstance) {
|
|
4813
4982
|
this._bridgeInstance = new Bridge(this.transport, CallbackFactory());
|
|
@@ -4941,7 +5110,7 @@
|
|
|
4941
5110
|
}
|
|
4942
5111
|
}
|
|
4943
5112
|
|
|
4944
|
-
var version = "3.5.
|
|
5113
|
+
var version = "3.5.7";
|
|
4945
5114
|
|
|
4946
5115
|
const composeAPI = (glue, ioc) => {
|
|
4947
5116
|
const controller = ioc.controller;
|