@openfin/core 31.74.31 → 32.75.6

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.
Files changed (50) hide show
  1. package/package.json +1 -1
  2. package/src/OpenFin.d.ts +46 -12
  3. package/src/api/application/Instance.js +23 -5
  4. package/src/api/base.d.ts +1 -2
  5. package/src/api/base.js +1 -2
  6. package/src/api/events/system.d.ts +6 -3
  7. package/src/api/fin.js +1 -2
  8. package/src/api/interappbus/channel/protocols/classic/strategy.js +24 -6
  9. package/src/api/interappbus/index.js +1 -1
  10. package/src/api/interop/InteropClient.d.ts +1 -1
  11. package/src/api/interop/InteropClient.js +1 -1
  12. package/src/api/interop/SessionContextGroupBroker.d.ts +1 -1
  13. package/src/api/interop/SessionContextGroupBroker.js +5 -4
  14. package/src/api/interop/SessionContextGroupClient.js +1 -1
  15. package/src/api/interop/fdc3/PrivateChannelProvider.d.ts +1 -1
  16. package/src/api/interop/fdc3/PrivateChannelProvider.js +1 -8
  17. package/src/api/interop/fdc3/fdc3-1.2.js +34 -1
  18. package/src/api/interop/fdc3/utils.js +24 -4
  19. package/src/api/platform/Factory.d.ts +2 -1
  20. package/src/api/platform/Instance.d.ts +5 -4
  21. package/src/api/platform/Instance.js +2 -1
  22. package/src/api/platform/layout/Factory.js +5 -3
  23. package/src/api/platform/layout/Instance.js +3 -0
  24. package/src/api/platform/layout/controllers/layout-entities-controller.d.ts +6 -2
  25. package/src/api/platform/layout/controllers/layout-entities-controller.js +40 -8
  26. package/src/api/platform/layout/controllers/tab-drag-controller.d.ts +2 -1
  27. package/src/api/platform/layout/entities/layout-entities.d.ts +12 -2
  28. package/src/api/platform/layout/entities/layout-entities.js +14 -2
  29. package/src/api/platform/layout/utils/layout-traversal.d.ts +1 -0
  30. package/src/api/platform/layout/utils/layout-traversal.js +11 -11
  31. package/src/api/platform/provider.d.ts +2 -1
  32. package/src/api/system/index.d.ts +9 -0
  33. package/src/api/system/index.js +31 -2
  34. package/src/api/view/Instance.d.ts +6 -3
  35. package/src/api/view/Instance.js +9 -7
  36. package/src/api/webcontents/main.d.ts +1 -22
  37. package/src/api/window/Instance.d.ts +3 -0
  38. package/src/api/window/Instance.js +3 -0
  39. package/src/shapes/protocol.d.ts +1 -0
  40. package/src/transport/transport-errors.d.ts +9 -1
  41. package/src/transport/transport-errors.js +45 -2
  42. package/src/transport/transport.d.ts +15 -5
  43. package/src/transport/transport.js +48 -20
  44. package/src/util/channel-api-relay.js +11 -1
  45. package/src/util/errors.d.ts +1 -0
  46. package/src/util/errors.js +1 -0
  47. package/src/util/ref-counter.d.ts +1 -1
  48. package/src/util/ref-counter.js +3 -2
  49. package/src/transport/fin_store.d.ts +0 -4
  50. package/src/transport/fin_store.js +0 -16
@@ -9,7 +9,9 @@ type ViewCreationOrReference = OpenFin.Identity | OpenFin.PlatformViewCreationOp
9
9
  export declare class LayoutEntitiesController {
10
10
  private layoutManager;
11
11
  private layoutContentCache;
12
+ private wire;
12
13
  constructor(layoutManager: any, layoutContentCache: LayoutContentCache);
14
+ private analytics;
13
15
  /**
14
16
  * @internal
15
17
  * @returns the root contentItem of the layout.
@@ -86,6 +88,7 @@ export declare class LayoutEntitiesController {
86
88
  * @throws If the view does not exist, fails to create, or the stack does not exist.
87
89
  */
88
90
  addViewToStack: (stackEntityId: string, viewCreationOrReference: ViewCreationOrReference, { index }?: OpenFin.AddViewToStackOptions) => Promise<OpenFin.Identity>;
91
+ private findViewInStack;
89
92
  /**
90
93
  * @internal
91
94
  * Removes a view from the given stack. If it's the only view, the stack will be destroyed, unless window creation
@@ -101,15 +104,16 @@ export declare class LayoutEntitiesController {
101
104
  * Creates a new adjacent 'stack' and adds the views to it at the specified position
102
105
  * @param targetId Entity id of the content item to add a stack adjacent to it
103
106
  * @param views List of identities or view creation options of the views to include in the stack
104
- * @param options Creation options, defaults to position: 'right'
107
+ * @param options Creation options, defaults to { position: 'right' }
105
108
  * @returns the Entity Id of the new stack
106
109
  */
107
- createAdjacentStack: (targetId: string, views: ViewCreationOrReference[], options: {
110
+ createAdjacentStack: (targetId: string, views: ViewCreationOrReference[], { position }?: {
108
111
  position?: OpenFin.LayoutPosition;
109
112
  }) => Promise<string>;
110
113
  getAdjacentStacks: ({ targetId, edge }: {
111
114
  targetId: string;
112
115
  edge: OpenFin.LayoutPosition;
113
116
  }) => Promise<Pick<OpenFin.LayoutEntityDefinition, 'entityId'>[]>;
117
+ setStackActiveView: (stackEntityId: string, viewIdentity: OpenFin.Identity) => Promise<void>;
114
118
  }
115
119
  export {};
@@ -20,11 +20,17 @@ class LayoutEntitiesController {
20
20
  layoutManager, layoutContentCache) {
21
21
  this.layoutManager = layoutManager;
22
22
  this.layoutContentCache = layoutContentCache;
23
+ this.analytics = (topic) => {
24
+ this.wire.sendAction(`layout-controller-${topic}`).catch(() => {
25
+ // don't expose
26
+ });
27
+ };
23
28
  /**
24
29
  * @internal
25
30
  * @returns the root contentItem of the layout.
26
31
  */
27
32
  this.getRoot = () => {
33
+ this.analytics('get-root');
28
34
  const root = this.layoutManager.layout.root.contentItems[0];
29
35
  return {
30
36
  // TODO: fix typing
@@ -41,6 +47,7 @@ class LayoutEntitiesController {
41
47
  */
42
48
  this.getStackByView = async (view) => {
43
49
  var _a, _b, _c, _d;
50
+ this.analytics('get-stack-by-view');
44
51
  const viewComponent = this.layoutManager.getViewComponent(view);
45
52
  if (!viewComponent || ((_b = (_a = viewComponent.container) === null || _a === void 0 ? void 0 : _a.parent) === null || _b === void 0 ? void 0 : _b.parent.type) !== 'stack') {
46
53
  return undefined;
@@ -63,6 +70,7 @@ class LayoutEntitiesController {
63
70
  * @throws if the content item associated with the entity id does not exist or is not a stack.
64
71
  */
65
72
  this.getStackViews = (id) => {
73
+ this.analytics('get-stack-views');
66
74
  const stack = this.layoutContentCache.getContentItemOrThrow(id, ['stack']);
67
75
  const views = stack.contentItems.map((ci) => {
68
76
  var _a;
@@ -80,6 +88,7 @@ class LayoutEntitiesController {
80
88
  */
81
89
  this.isRoot = (id) => {
82
90
  var _a;
91
+ this.analytics('is-root');
83
92
  const ci = this.layoutContentCache.getContentItemOrThrow(id);
84
93
  return !!((_a = ci.parent) === null || _a === void 0 ? void 0 : _a.isRoot);
85
94
  };
@@ -90,6 +99,7 @@ class LayoutEntitiesController {
90
99
  * @returns True if the content item exists and belongs to the layout.
91
100
  */
92
101
  this.exists = (entityId) => {
102
+ this.analytics('exists');
93
103
  return this.layoutContentCache.hasKey(entityId);
94
104
  };
95
105
  /**
@@ -109,6 +119,7 @@ class LayoutEntitiesController {
109
119
  * @throws If the view does not exist, fails to create, or the stack does not exist.
110
120
  */
111
121
  this.addViewToStack = async (stackEntityId, viewCreationOrReference, { index } = { index: 0 }) => {
122
+ this.analytics('add-view-to-stack');
112
123
  const currentStack = this.layoutContentCache.getContentItemOrThrow(stackEntityId);
113
124
  if (index && index > currentStack.contentItems.length + 1) {
114
125
  throw new Error(`Index '${index}' out of range, please exclude the index or specify a number between 0 and ${currentStack.contentItems.length}`);
@@ -123,6 +134,9 @@ class LayoutEntitiesController {
123
134
  });
124
135
  return identity;
125
136
  };
137
+ this.findViewInStack = (stack, viewIdentity) => {
138
+ return stack.contentItems.find((ci) => { var _a, _b; return ((_b = (_a = ci.config) === null || _a === void 0 ? void 0 : _a.componentState) === null || _b === void 0 ? void 0 : _b.name) === viewIdentity.name; });
139
+ };
126
140
  /**
127
141
  * @internal
128
142
  * Removes a view from the given stack. If it's the only view, the stack will be destroyed, unless window creation
@@ -133,9 +147,11 @@ class LayoutEntitiesController {
133
147
  * @throws If the stack does not exist or the view does not exist or belong to the stack.
134
148
  */
135
149
  this.removeViewFromStack = async (stackEntityId, view) => {
136
- const views = this.getStackViews(stackEntityId);
137
- if (!views.find((existingView) => existingView.name === view.name)) {
138
- throw new Error(`Tried to remove a view ('${view.name}') which does not exist in the stack.`);
150
+ this.analytics('remove-view-from-stack');
151
+ const stack = this.layoutContentCache.getContentItemOrThrow(stackEntityId, ['stack']);
152
+ const viewInstance = this.findViewInStack(stack, view);
153
+ if (!viewInstance) {
154
+ throw new Error(`Tried to remove a view ('${view.name}') which does not belong to the stack.`);
139
155
  }
140
156
  await this.layoutManager.platform.closeView(view);
141
157
  };
@@ -144,14 +160,14 @@ class LayoutEntitiesController {
144
160
  * Creates a new adjacent 'stack' and adds the views to it at the specified position
145
161
  * @param targetId Entity id of the content item to add a stack adjacent to it
146
162
  * @param views List of identities or view creation options of the views to include in the stack
147
- * @param options Creation options, defaults to position: 'right'
163
+ * @param options Creation options, defaults to { position: 'right' }
148
164
  * @returns the Entity Id of the new stack
149
165
  */
150
- this.createAdjacentStack = async (targetId, views, options) => {
151
- if (views.length === 0) {
152
- throw new Error('Cannot create stack with empty view array.');
166
+ this.createAdjacentStack = async (targetId, views, { position = 'right' } = {}) => {
167
+ this.analytics('create-adjacent-stack');
168
+ if (!Array.isArray(views) || views.length === 0) {
169
+ throw new Error('The parameter "views" must be an array with at least 1 element.');
153
170
  }
154
- const { position = 'right' } = options;
155
171
  if (!['top', 'bottom', 'left', 'right'].includes(position)) {
156
172
  throw new Error(`Invalid position '${position}' specified.`);
157
173
  }
@@ -176,12 +192,23 @@ class LayoutEntitiesController {
176
192
  return entityId;
177
193
  };
178
194
  this.getAdjacentStacks = async ({ targetId, edge }) => {
195
+ this.analytics('get-adjacent-stacks');
179
196
  const contentItem = this.layoutContentCache.getContentItemOrThrow(targetId);
180
197
  // call utils helper to traverse and return adjacent stacks
181
198
  return (0, layout_traversal_1.getAdjacentStacks)(contentItem, edge).map((stack) => ({
182
199
  entityId: this.layoutContentCache.getOrCreateEntityId(stack),
183
200
  }));
184
201
  };
202
+ this.setStackActiveView = async (stackEntityId, viewIdentity) => {
203
+ this.analytics('set-stack-active-view');
204
+ const stack = this.layoutContentCache.getContentItemOrThrow(stackEntityId, ['stack']);
205
+ const view = this.findViewInStack(stack, viewIdentity);
206
+ if (!view) {
207
+ throw new Error(`Tried to set a view ('${viewIdentity.name}') as active when it does not belong to the stack.`);
208
+ }
209
+ stack.setActiveContentItem(view, true);
210
+ };
211
+ this.wire = this.layoutManager.platform.wire;
185
212
  }
186
213
  /**
187
214
  * @internal
@@ -192,6 +219,7 @@ class LayoutEntitiesController {
192
219
  * @throws if the entity associated with {@link id} is not in the entity cache, does not belogn to a layout, or is not a column/row.
193
220
  */
194
221
  getContent(id) {
222
+ this.analytics('get-content');
195
223
  const ci = this.layoutContentCache.getContentItemOrThrow(id, ['column', 'row']);
196
224
  return ci.contentItems.map((item) => ({
197
225
  type: item.type,
@@ -208,6 +236,7 @@ class LayoutEntitiesController {
208
236
  * content item or has been removed from the layout entirely.
209
237
  */
210
238
  getParent(id) {
239
+ this.analytics('get-parent');
211
240
  const ci = this.layoutContentCache.getContentItemOrThrow(id);
212
241
  if (ci.parent && !ci.parent.isRoot && ci.parent.contentItems.includes(ci)) {
213
242
  return {
@@ -252,4 +281,7 @@ __decorate([
252
281
  __decorate([
253
282
  (0, decorators_1.expose)()
254
283
  ], LayoutEntitiesController.prototype, "getAdjacentStacks", void 0);
284
+ __decorate([
285
+ (0, decorators_1.expose)()
286
+ ], LayoutEntitiesController.prototype, "setStackActiveView", void 0);
255
287
  exports.LayoutEntitiesController = LayoutEntitiesController;
@@ -1,6 +1,6 @@
1
1
  import type * as OpenFin from '../../../../OpenFin';
2
2
  import { ViewOverlay } from '../utils/view-overlay';
3
- import { View } from '../../../view';
3
+ type View = OpenFin.View;
4
4
  /**
5
5
  * Set of apis used to facilitate tab drag interactions without needing to hide views.
6
6
  * @ignore
@@ -56,3 +56,4 @@ export declare class TabDragController {
56
56
  */
57
57
  observeOverlay: (dropZonePreview: HTMLElement) => Promise<void>;
58
58
  }
59
+ export {};
@@ -63,8 +63,8 @@ export declare abstract class LayoutNode {
63
63
  }) => Promise<TabStack>;
64
64
  /**
65
65
  * Finds the immediate adjacent layout item given an edge Position
66
- * @param edgePosition
67
- * @returns either {@link TabStack} or {@link ColumnOrRow} that was found, or `undefined` if there is no item with that edgePosition
66
+ * @param edge
67
+ * @returns an array of {@link TabStack} found, if none found returns an empty array.
68
68
  */
69
69
  getAdjacentStacks: (edge: OpenFin.LayoutPosition) => Promise<TabStack[]>;
70
70
  }
@@ -114,6 +114,16 @@ export declare class TabStack extends LayoutNode {
114
114
  * @throws If the {@link TabStack} has been destroyed.
115
115
  */
116
116
  removeView: (view: OpenFin.Identity) => Promise<void>;
117
+ /**
118
+ * Sets the active view of the {@link TabStack} without focusing it.
119
+ * @param view {@link OpenFin.Identity Identity} of the view to activate.
120
+ * @returns Promise which resolves with void once the view has been activated.
121
+ * @throws If the {@link TabStack} has been destroyed.
122
+ * @throws If the view does not exist.
123
+ * @tutorial TabStack.setActiveView
124
+ * @experimental
125
+ */
126
+ setActiveView: (view: OpenFin.Identity) => Promise<void>;
117
127
  }
118
128
  /**
119
129
  * A {@link ColumnOrRow} is used to manage the state of a ColumnOrRow within an OpenFin Layout.
@@ -74,8 +74,8 @@ class LayoutNode {
74
74
  };
75
75
  /**
76
76
  * Finds the immediate adjacent layout item given an edge Position
77
- * @param edgePosition
78
- * @returns either {@link TabStack} or {@link ColumnOrRow} that was found, or `undefined` if there is no item with that edgePosition
77
+ * @param edge
78
+ * @returns an array of {@link TabStack} found, if none found returns an empty array.
79
79
  */
80
80
  this.getAdjacentStacks = async (edge) => {
81
81
  const adjacentStacks = await __classPrivateFieldGet(this, _LayoutNode_client, "f").getAdjacentStacks({
@@ -171,6 +171,18 @@ class TabStack extends LayoutNode {
171
171
  this.removeView = async (view) => {
172
172
  await __classPrivateFieldGet(this, _TabStack_client, "f").removeViewFromStack(this.entityId, view);
173
173
  };
174
+ /**
175
+ * Sets the active view of the {@link TabStack} without focusing it.
176
+ * @param view {@link OpenFin.Identity Identity} of the view to activate.
177
+ * @returns Promise which resolves with void once the view has been activated.
178
+ * @throws If the {@link TabStack} has been destroyed.
179
+ * @throws If the view does not exist.
180
+ * @tutorial TabStack.setActiveView
181
+ * @experimental
182
+ */
183
+ this.setActiveView = async (view) => {
184
+ await __classPrivateFieldGet(this, _TabStack_client, "f").setStackActiveView(this.entityId, view);
185
+ };
174
186
  __classPrivateFieldSet(this, _TabStack_client, client, "f");
175
187
  }
176
188
  }
@@ -1,3 +1,4 @@
1
1
  import type * as OpenFin from '../../../../OpenFin';
2
2
  export declare const getAdjacentItem: (component: GoldenLayout.ContentItem, edge: OpenFin.LayoutPosition) => GoldenLayout.ContentItem | undefined;
3
+ export declare const doShareEdge: (from: GoldenLayout.ContentItem, to: GoldenLayout.ContentItem, edge: OpenFin.LayoutPosition) => boolean;
3
4
  export declare const getAdjacentStacks: (item: GoldenLayout.ContentItem, edge: OpenFin.LayoutPosition) => GoldenLayout.ContentItem[];
@@ -1,9 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getAdjacentStacks = exports.getAdjacentItem = void 0;
3
+ exports.getAdjacentStacks = exports.doShareEdge = exports.getAdjacentItem = void 0;
4
4
  const getAdjacentItem = (component, edge) => {
5
5
  const { parent } = component;
6
- // need to handle the case where a stack is the parent content item
7
6
  if (parent.isRoot) {
8
7
  return undefined;
9
8
  }
@@ -19,25 +18,26 @@ const getAdjacentItem = (component, edge) => {
19
18
  return (0, exports.getAdjacentItem)(parent, edge);
20
19
  };
21
20
  exports.getAdjacentItem = getAdjacentItem;
22
- const doShareEdge = (a, b, edge) => {
21
+ const doShareEdge = (from, to, edge) => {
23
22
  var _a, _b;
24
- const boundsA = (_a = a.element.get(0)) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
25
- const boundsB = (_b = b.element.get(0)) === null || _b === void 0 ? void 0 : _b.getBoundingClientRect();
26
- if (!boundsA || !boundsB) {
23
+ const boundsFrom = (_a = from.element.get(0)) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
24
+ const boundsTo = (_b = to.element.get(0)) === null || _b === void 0 ? void 0 : _b.getBoundingClientRect();
25
+ if (!boundsFrom || !boundsTo) {
27
26
  return false;
28
27
  }
29
28
  if (['top', 'bottom'].includes(edge)) {
30
- return ((boundsB.left >= boundsA.left && boundsB.left < boundsA.right) ||
31
- (boundsB.right > boundsA.left && boundsB.right <= boundsA.right));
29
+ const horizontallyOutOfBounds = boundsFrom.right < boundsTo.left || boundsFrom.left > boundsTo.right;
30
+ return !horizontallyOutOfBounds;
32
31
  }
33
- return ((boundsB.top >= boundsA.top && boundsB.top < boundsA.bottom) ||
34
- (boundsB.bottom > boundsA.top && boundsB.bottom <= boundsA.bottom));
32
+ const verticallyOutOfBounds = boundsFrom.bottom < boundsTo.top || boundsFrom.top > boundsTo.bottom;
33
+ return !verticallyOutOfBounds;
35
34
  };
35
+ exports.doShareEdge = doShareEdge;
36
36
  const getAdjacentStacks = (item, edge) => {
37
37
  const targetContainer = ['top', 'bottom'].includes(edge) ? 'row' : 'column';
38
38
  const findEdgeStacks = (component) => {
39
39
  if (component.type === 'stack') {
40
- if (doShareEdge(item, component, edge)) {
40
+ if ((0, exports.doShareEdge)(item, component, edge)) {
41
41
  return [component];
42
42
  }
43
43
  return [];
@@ -1,5 +1,5 @@
1
- import { WindowOptionsChangedEvent } from '../events/window';
2
1
  import * as OpenFin from '../../OpenFin';
2
+ type WindowOptionsChangedEvent = OpenFin.WindowEvents.WindowOptionsChangedEvent;
3
3
  /**
4
4
  * This class handles Platform actions. It does not need to be used directly by developers.
5
5
  * However, its methods can be overriden by passing an `overrideCallback` to {@link Platform#init Platform.init}
@@ -160,3 +160,4 @@ export interface PlatformProvider {
160
160
  */
161
161
  handleViewsAndWindowClose(windowId: OpenFin.Identity, userDecision: OpenFin.BeforeUnloadUserDecision): Promise<void>;
162
162
  }
163
+ export {};
@@ -460,6 +460,15 @@ export default class System extends EmitterBase<OpenFin.SystemEvent> {
460
460
  */
461
461
  getServiceConfiguration(serviceIdentifier: OpenFin.ServiceIdentifier): Promise<OpenFin.ServiceConfiguration>;
462
462
  protected getSystemAppConfig(name: string): Promise<any>;
463
+ /**
464
+ * Registers a system shutdown handler so user can do some cleanup before system is shutting down.
465
+ * Note: Once system shutdown starts, you are unable to cancel it.
466
+ * @param { SystemShutdownHandler } handler system shutdown handler
467
+ * @return {Promise.<void>}
468
+ * @tutorial System.registerShutdownHandler
469
+ * @experimental
470
+ */
471
+ registerShutdownHandler(handler: OpenFin.SystemShutdownHandler): Promise<void>;
463
472
  /**
464
473
  * Signals the RVM to perform a health check and returns the results as json.
465
474
  * @return {Promise.<string[]>}
@@ -538,7 +538,7 @@ class System extends base_1.EmitterBase {
538
538
  const dlError = (payload) => {
539
539
  cleanListeners();
540
540
  const { reason, err: error } = payload;
541
- reject(new transport_errors_1.RuntimeError({ reason, error }));
541
+ reject(new transport_errors_1.RuntimeError({ reason, error }, transport_errors_1.RuntimeError.getCallSite(3)));
542
542
  };
543
543
  const dlComplete = () => {
544
544
  cleanListeners();
@@ -568,6 +568,7 @@ class System extends base_1.EmitterBase {
568
568
  * @tutorial System.downloadRuntime
569
569
  */
570
570
  downloadRuntime(options, progressListener) {
571
+ const callsites = transport_errors_1.RuntimeError.getCallSite();
571
572
  return new Promise((resolve, reject) => {
572
573
  // node.js environment not supported
573
574
  if (this.wire.environment.constructor.name === 'NodeEnvironment') {
@@ -593,7 +594,7 @@ class System extends base_1.EmitterBase {
593
594
  const dlError = (payload) => {
594
595
  cleanListeners();
595
596
  const { reason, err: error } = payload;
596
- reject(new transport_errors_1.RuntimeError({ reason, error }));
597
+ reject(new transport_errors_1.RuntimeError({ reason, error }, callsites));
597
598
  };
598
599
  const dlComplete = () => {
599
600
  cleanListeners();
@@ -735,6 +736,34 @@ class System extends base_1.EmitterBase {
735
736
  }
736
737
  return this.wire.sendAction('get-system-app-configuration', { name }).then(({ payload }) => payload.data);
737
738
  }
739
+ /**
740
+ * Registers a system shutdown handler so user can do some cleanup before system is shutting down.
741
+ * Note: Once system shutdown starts, you are unable to cancel it.
742
+ * @param { SystemShutdownHandler } handler system shutdown handler
743
+ * @return {Promise.<void>}
744
+ * @tutorial System.registerShutdownHandler
745
+ * @experimental
746
+ */
747
+ async registerShutdownHandler(handler) {
748
+ this.wire.sendAction('system-register-shutdown-handler').catch((e) => {
749
+ // don't expose, analytics-only call
750
+ });
751
+ const SystemShutdownEventName = 'system-shutdown';
752
+ const SystemShutdownHandledEventName = 'system-shutdown-handled';
753
+ const { uuid, name } = this.wire.me;
754
+ const shutdownHandler = (payload) => {
755
+ const proceed = () => {
756
+ // notify core that the app is ready for shutdown
757
+ this.wire.environment.raiseEvent(`application/${SystemShutdownHandledEventName}`, {
758
+ uuid,
759
+ name,
760
+ topic: 'application'
761
+ });
762
+ };
763
+ handler({ proceed });
764
+ };
765
+ this.on(SystemShutdownEventName, shutdownHandler);
766
+ }
738
767
  /**
739
768
  * Signals the RVM to perform a health check and returns the results as json.
740
769
  * @return {Promise.<string[]>}
@@ -1,8 +1,8 @@
1
1
  import type * as OpenFin from '../../OpenFin';
2
2
  import { Transport } from '../../transport/transport';
3
- import { ViewEvent } from '../events/view';
4
3
  import { WebContents } from '../webcontents/main';
5
4
  type UpdatableViewOptions = OpenFin.UpdatableViewOptions;
5
+ type ViewEvent = OpenFin.ViewEvent;
6
6
  /**
7
7
  * @PORTED
8
8
  * @typedef {object} View~options
@@ -144,6 +144,9 @@ type UpdatableViewOptions = OpenFin.UpdatableViewOptions;
144
144
  * @property {string} [processAffinity=<application uuid>]
145
145
  * A string to attempt to group renderers together. Will only be used if pages are on the same origin.
146
146
  *
147
+ * @property {boolean} [spellCheck=false]
148
+ * Enable spell check in input text fields for the view.
149
+ *
147
150
  * @property {Identity} [target]
148
151
  * The identity of the window this view should be attached to.
149
152
  *
@@ -447,10 +450,10 @@ export declare class View extends WebContents<ViewEvent> {
447
450
  getCurrentWindow: () => Promise<OpenFin.Window>;
448
451
  /**
449
452
  * Retrieves the current {@link TabStack} of the view if it belongs to one.
450
- * @return {Promise<TabStack | undefined>} The {@link TabStack} this view belongs to.
453
+ * @return {Promise<TabStack>} The {@link TabStack} this view belongs to.
451
454
  * @throws if this view does not belong to a TabStack or if the window has been destroyed.
452
455
  */
453
- getCurrentStack: () => Promise<OpenFin.TabStack | undefined>;
456
+ getCurrentStack: () => Promise<OpenFin.TabStack>;
454
457
  /**
455
458
  * Triggers the before-unload handler for the View, if one is set. Returns `true` if the handler is trying to prevent the View from unloading, and `false` if it isn't.
456
459
  * Only enabled when setting enableBeforeUnload: true in your View options. If this option is not enabled it will always return false.
@@ -155,6 +155,9 @@ const window_1 = require("../window");
155
155
  * @property {string} [processAffinity=<application uuid>]
156
156
  * A string to attempt to group renderers together. Will only be used if pages are on the same origin.
157
157
  *
158
+ * @property {boolean} [spellCheck=false]
159
+ * Enable spell check in input text fields for the view.
160
+ *
158
161
  * @property {Identity} [target]
159
162
  * The identity of the window this view should be attached to.
160
163
  *
@@ -459,23 +462,22 @@ class View extends main_1.WebContents {
459
462
  };
460
463
  /**
461
464
  * Retrieves the current {@link TabStack} of the view if it belongs to one.
462
- * @return {Promise<TabStack | undefined>} The {@link TabStack} this view belongs to.
465
+ * @return {Promise<TabStack>} The {@link TabStack} this view belongs to.
463
466
  * @throws if this view does not belong to a TabStack or if the window has been destroyed.
464
467
  */
465
468
  this.getCurrentStack = async () => {
469
+ this.wire.sendAction('view-get-current-stack').catch(() => {
470
+ // don't expose
471
+ });
466
472
  try {
467
473
  const layoutWindow = await this.getCurrentWindow();
468
474
  const providerChannelClient = await __classPrivateFieldGet(this, _View_providerChannelClient, "f").getValue();
469
475
  const client = await layout_entities_1.LayoutNode.newLayoutEntitiesClient(providerChannelClient, layout_constants_1.LAYOUT_CONTROLLER_ID, layoutWindow.identity);
470
- const stackDefinition = await client.getStackByView(this.identity);
476
+ const stackDefinition = (await client.getStackByView(this.identity));
471
477
  return layout_entities_1.LayoutNode.getEntity(stackDefinition, client);
472
478
  }
473
479
  catch (error) {
474
- const e = new transport_errors_1.RuntimeError({ reason: 'This view does not belong to a stack.' });
475
- // TODO: @pierre to fix
476
- // @ts-expect-error pending PR !3459 to fix runtime errors
477
- e.cause = error;
478
- throw e;
480
+ throw new transport_errors_1.RuntimeError({ reason: 'This view does not belong to a stack.', error });
479
481
  }
480
482
  };
481
483
  /**
@@ -2,31 +2,10 @@ import type * as OpenFin from '../../OpenFin';
2
2
  import { EmitterBase } from '../base';
3
3
  import { Transport } from '../../transport/transport';
4
4
  import { BaseEvent } from '../events/base';
5
- /**
6
- * Configuration for page capture.
7
- */
8
- export interface CapturePageOptions {
9
- /**
10
- * The area of the window to be captured.
11
- */
12
- area?: OpenFin.Rectangle;
13
- /**
14
- * @defaultValue 'png'
15
- *
16
- * The format of the captured image. Can be 'png', 'jpg', or 'bmp'.
17
- */
18
- format?: 'bmp' | 'jpg' | 'png';
19
- /**
20
- * @defaultValue 100
21
- *
22
- * Quality of JPEG image. Between 0 - 100.
23
- */
24
- quality?: number;
25
- }
26
5
  export declare class WebContents<T extends BaseEvent> extends EmitterBase<T> {
27
6
  entityType: string;
28
7
  constructor(wire: Transport, identity: OpenFin.Identity, entityType: string);
29
- capturePage(options?: CapturePageOptions): Promise<string>;
8
+ capturePage(options?: OpenFin.CapturePageOptions): Promise<string>;
30
9
  executeJavaScript(code: string): Promise<void>;
31
10
  getZoomLevel(): Promise<number>;
32
11
  setZoomLevel(level: number): Promise<void>;
@@ -334,6 +334,9 @@ import { WebContents } from '../webcontents/main';
334
334
  * _Note: Caveats of small windows are no Aero Snap and drag to/from maximize._
335
335
  * _Windows 10: Requires `maximizable` to be false. Resizing with the mouse is only possible down to 38x39 px._
336
336
  *
337
+ * @property {boolean} [spellCheck=false]
338
+ * Enable spell check in input text fields for the window.
339
+ *
337
340
  * @property {string} [state="normal"]
338
341
  * The visible state of the window on creation.
339
342
  * One of:
@@ -341,6 +341,9 @@ const view_1 = require("../view");
341
341
  * _Note: Caveats of small windows are no Aero Snap and drag to/from maximize._
342
342
  * _Windows 10: Requires `maximizable` to be false. Resizing with the mouse is only possible down to 38x39 px._
343
343
  *
344
+ * @property {boolean} [spellCheck=false]
345
+ * Enable spell check in input text fields for the window.
346
+ *
344
347
  * @property {string} [state="normal"]
345
348
  * The visible state of the window on creation.
346
349
  * One of:
@@ -148,6 +148,7 @@ export interface ProtocolMap extends ProtocolMapBase {
148
148
  request: void;
149
149
  response: OpenFin.PrinterInfo[];
150
150
  };
151
+ 'system-register-shutdown-handler': VoidCall;
151
152
  }
152
153
  type ApiCall<Request, Response> = {
153
154
  request: Request;
@@ -1,3 +1,4 @@
1
+ /// <reference types="node" />
1
2
  import { ErrorPlainObject } from '../util/errors';
2
3
  export type ReadyState = 'CONNECTING' | 'OPEN' | 'CLOSING' | 'CLOSED';
3
4
  export declare class DisconnectedError extends Error {
@@ -18,6 +19,13 @@ export type RuntimeErrorPayload = {
18
19
  reason: string;
19
20
  error?: ErrorPlainObject;
20
21
  };
22
+ declare class InternalError<T extends ErrorPlainObject = ErrorPlainObject> extends Error {
23
+ constructor(err: T);
24
+ }
21
25
  export declare class RuntimeError extends Error {
22
- constructor(payload: RuntimeErrorPayload);
26
+ cause?: InternalError;
27
+ static getCallSite(callsToRemove?: number): NodeJS.CallSite[];
28
+ static prepareStackTrace(err: Error, callSites: NodeJS.CallSite[]): string;
29
+ constructor(payload: RuntimeErrorPayload, callSites?: NodeJS.CallSite[]);
23
30
  }
31
+ export {};
@@ -23,13 +23,56 @@ exports.NotImplementedError = NotImplementedError;
23
23
  class NotSupportedError extends Error {
24
24
  }
25
25
  exports.NotSupportedError = NotSupportedError;
26
+ class InternalError extends Error {
27
+ constructor(err) {
28
+ const { message, name, stack, ...rest } = err;
29
+ super(message);
30
+ this.name = name || 'Error';
31
+ this.stack = stack !== null && stack !== void 0 ? stack : this.toString();
32
+ Object.keys(rest).forEach(key => {
33
+ this[key] = rest[key];
34
+ });
35
+ }
36
+ }
37
+ // For documentation of the error methods being used see here: https://v8.dev/docs/stack-trace-api
26
38
  class RuntimeError extends Error {
27
- constructor(payload) {
39
+ static getCallSite(callsToRemove = 0) {
40
+ var _a, _b;
41
+ const length = Error.stackTraceLimit;
42
+ const realCallsToRemove = callsToRemove + 1; // remove this call;
43
+ Error.stackTraceLimit = length + realCallsToRemove;
44
+ // eslint-disable-next-line no-underscore-dangle
45
+ const _prepareStackTrace = Error.prepareStackTrace;
46
+ // This will be called when we access the `stack` property
47
+ Error.prepareStackTrace = (_, stack) => stack;
48
+ // stack is optional in non chromium contexts
49
+ const stack = (_b = (_a = new Error().stack) === null || _a === void 0 ? void 0 : _a.slice(realCallsToRemove)) !== null && _b !== void 0 ? _b : [];
50
+ Error.prepareStackTrace = _prepareStackTrace;
51
+ Error.stackTraceLimit = length;
52
+ return stack;
53
+ }
54
+ static prepareStackTrace(err, callSites) {
55
+ if (typeof Error.prepareStackTrace === 'function') {
56
+ return Error.prepareStackTrace(err, callSites);
57
+ }
58
+ let string = "";
59
+ string += err.name || "Error";
60
+ string += `: ${err.message || ""}`;
61
+ for (const callSite of callSites) {
62
+ string += `\n at ${callSite.toString()}`;
63
+ }
64
+ return string;
65
+ }
66
+ ;
67
+ constructor(payload, callSites) {
28
68
  const { reason, error } = payload;
29
69
  super(reason);
30
70
  this.name = 'RuntimeError';
31
71
  if (error === null || error === void 0 ? void 0 : error.stack) {
32
- this.stack = error.stack;
72
+ this.cause = new InternalError(error);
73
+ }
74
+ if (callSites) {
75
+ this.stack = RuntimeError.prepareStackTrace(this, callSites);
33
76
  }
34
77
  }
35
78
  }