@openfin/core 45.100.113 → 45.100.115

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/out/stub.js CHANGED
@@ -469,6 +469,26 @@ class EmitterBase extends Base {
469
469
  }
470
470
  _EmitterBase_emitterAccessor = new WeakMap(), _EmitterBase_deregisterOnceListeners = new WeakMap();
471
471
 
472
+ const V8Error = Error;
473
+ function isCallSiteArray(stack) {
474
+ if (!Array.isArray(stack) || stack.length === 0) {
475
+ return Array.isArray(stack);
476
+ }
477
+ const first = stack[0];
478
+ return typeof first === 'object' && first !== null && typeof first.getFileName === 'function';
479
+ }
480
+ function isStackFrameLine(line) {
481
+ return /^\s*at\s/.test(line) || line.includes('@');
482
+ }
483
+ /**
484
+ * Split a native `error.stack` string into frames and drop the dummy Error header plus `framesToRemove` frames.
485
+ * Safari/Firefox ignore V8's Error.prepareStackTrace, so `.stack` stays a string and `.slice(n)` would cut characters.
486
+ */
487
+ function stackStringToFrames(stack, framesToRemove) {
488
+ const lines = stack.split('\n').filter((line) => line.length > 0);
489
+ const start = lines[0] !== undefined && !isStackFrameLine(lines[0]) ? 1 : 0;
490
+ return lines.slice(start + framesToRemove);
491
+ }
472
492
  class UnexpectedActionError extends Error {
473
493
  }
474
494
  class DuplicateCorrelationError extends Error {
@@ -497,17 +517,17 @@ class DeserializedError extends Error {
497
517
  class RuntimeError extends Error {
498
518
  static trimEndCallSites(err, takeUntilRegex) {
499
519
  // save original props
500
- const length = Error.stackTraceLimit;
520
+ const length = V8Error.stackTraceLimit;
501
521
  // eslint-disable-next-line no-underscore-dangle
502
- const _prepareStackTrace = Error.prepareStackTrace;
522
+ const _prepareStackTrace = V8Error.prepareStackTrace;
503
523
  // This will be called when we access the `stack` property
504
- Error.prepareStackTrace = (_, stack) => stack;
524
+ V8Error.prepareStackTrace = (_, stack) => stack;
505
525
  // in channel errors, the error was already serialized so we need to handle both string and CallSite[]
506
526
  const isString = typeof err.stack === 'string';
507
527
  const stack = (isString ? err.stack?.split('\n') : err.stack) ?? [];
508
528
  // restore original props
509
- Error.prepareStackTrace = _prepareStackTrace;
510
- Error.stackTraceLimit = length;
529
+ V8Error.prepareStackTrace = _prepareStackTrace;
530
+ V8Error.stackTraceLimit = length;
511
531
  // stack is optional in non chromium contexts
512
532
  if (stack.length) {
513
533
  const newStack = [];
@@ -529,31 +549,47 @@ class RuntimeError extends Error {
529
549
  }
530
550
  }
531
551
  static getCallSite(callsToRemove = 0) {
532
- const length = Error.stackTraceLimit;
552
+ const length = V8Error.stackTraceLimit;
533
553
  const realCallsToRemove = callsToRemove + 1; // remove this call;
534
- Error.stackTraceLimit = length + realCallsToRemove;
554
+ const limit = typeof length === 'number' && Number.isFinite(length) ? length : 10;
535
555
  // eslint-disable-next-line no-underscore-dangle
536
- const _prepareStackTrace = Error.prepareStackTrace;
537
- // This will be called when we access the `stack` property
538
- Error.prepareStackTrace = (_, stack) => stack;
539
- // stack is optional in non chromium contexts
540
- const stack = new Error().stack?.slice(realCallsToRemove) ?? [];
541
- Error.prepareStackTrace = _prepareStackTrace;
542
- Error.stackTraceLimit = length;
543
- return stack;
556
+ const _prepareStackTrace = V8Error.prepareStackTrace;
557
+ try {
558
+ V8Error.stackTraceLimit = limit + realCallsToRemove;
559
+ // V8 only: accessing `.stack` invokes this and returns CallSite[]. Safari/Firefox ignore it.
560
+ V8Error.prepareStackTrace = (_, stack) => stack;
561
+ const rawStack = new Error().stack;
562
+ if (Array.isArray(rawStack)) {
563
+ return rawStack.slice(realCallsToRemove);
564
+ }
565
+ if (typeof rawStack === 'string' && rawStack.length > 0) {
566
+ return stackStringToFrames(rawStack, realCallsToRemove);
567
+ }
568
+ return [];
569
+ }
570
+ finally {
571
+ V8Error.prepareStackTrace = _prepareStackTrace;
572
+ V8Error.stackTraceLimit = length;
573
+ }
544
574
  }
545
575
  static prepareStackTrace(err, callSites) {
546
- if (typeof Error.prepareStackTrace === 'function') {
547
- return Error.prepareStackTrace(err, callSites);
548
- }
549
- // TODO: this is just a first iteration, we can make this "nicer" at some point
550
- // const EXCLUSIONS = ['IpcRenderer', 'Object.onMessage', 'Transport.onmessage', 'MessageReceiver.onmessage'];
551
- let stackTrace = `${err.name || 'Error'}: ${err.message || ''}\n`;
552
- stackTrace += callSites
553
- .map((line) => ` at ${line}`)
554
- // .filter((line) => !EXCLUSIONS.some((l) => line.includes(l)))
555
- .join('\n');
556
- return stackTrace;
576
+ const header = `${err.name || 'Error'}: ${err.message || ''}`;
577
+ const frames = typeof callSites === 'string' ? stackStringToFrames(callSites, 0) : callSites;
578
+ if (!Array.isArray(frames) || frames.length === 0) {
579
+ return header;
580
+ }
581
+ if (isCallSiteArray(frames)) {
582
+ const prepare = V8Error.prepareStackTrace;
583
+ // Only V8 CallSite[] may be passed to a user-supplied Error.prepareStackTrace.
584
+ if (typeof prepare === 'function') {
585
+ return prepare(err, frames);
586
+ }
587
+ // TODO: this is just a first iteration, we can make this "nicer" at some point
588
+ // const EXCLUSIONS = ['IpcRenderer', 'Object.onMessage', 'Transport.onmessage', 'MessageReceiver.onmessage'];
589
+ return `${header}\n${frames.map((line) => ` at ${line}`).join('\n')}`;
590
+ }
591
+ // Native Safari/Firefox frames already include their engine's format (`func@file:line:col`).
592
+ return `${header}\n${frames.join('\n')}`;
557
593
  }
558
594
  /*
559
595
 
@@ -2482,6 +2518,47 @@ class Application extends EmitterBase {
2482
2518
  constructor(wire, identity) {
2483
2519
  super(wire, 'application', identity.uuid);
2484
2520
  this.identity = identity;
2521
+ /**
2522
+ * @experimental
2523
+ * Retrieves a performance snapshot for all Windows, Views and Frames in the Application.
2524
+ *
2525
+ * By default, all custom marks and measures are collected, along with navigation/paint entries
2526
+ * and resource timing (`resources` defaults to `true`). Pass `include` to restrict custom
2527
+ * marks/measures to matching names (string substring or RegExp). Pass `browser: true` to also
2528
+ * include hereio internal runtime metrics.
2529
+ *
2530
+ * See also [MDN | Performance Mark API](https://developer.mozilla.org/en-US/docs/Web/API/Performance/mark)
2531
+ *
2532
+ * Note - only currently running WebContents will be captured, and performance entries can only be
2533
+ * captured for the current navigation of each.
2534
+ */
2535
+ this.getPerformanceStats = async (options = {}) => {
2536
+ /**
2537
+ * Returns a filter object compatible with JSON.stringify (regexs stringify to `{}`).
2538
+ * @param include Array of strings or regexps.
2539
+ */
2540
+ const getSerializableFilterObject = (include) => {
2541
+ return include.map((filter) => {
2542
+ if (filter instanceof RegExp) {
2543
+ return {
2544
+ type: 'regex',
2545
+ expression: filter.source,
2546
+ flags: filter.flags
2547
+ };
2548
+ }
2549
+ return filter;
2550
+ });
2551
+ };
2552
+ const { include, resources = true, browser = false } = options;
2553
+ const result = await this.wire.sendAction('get-application-performance-stats', {
2554
+ ...this.identity,
2555
+ // Omit `include` when unspecified so the runtime collects all custom marks/measures.
2556
+ ...(include !== undefined ? { include: getSerializableFilterObject(include) } : {}),
2557
+ resources,
2558
+ browser
2559
+ });
2560
+ return result.payload.data;
2561
+ };
2485
2562
  this.window = new _Window(this.wire, {
2486
2563
  uuid: this.identity.uuid,
2487
2564
  name: this.identity.uuid
@@ -13049,6 +13126,45 @@ class PrivateChannelProvider {
13049
13126
  }
13050
13127
  }
13051
13128
 
13129
+ /**
13130
+ * The default FDC3 user channels advertised by the Interop Broker.
13131
+ */
13132
+ const defaultColorChannels = {
13133
+ 'fdc3.channel.1': { name: 'Channel 1', color: 'red', glyph: '1' },
13134
+ 'fdc3.channel.2': { name: 'Channel 2', color: 'orange', glyph: '2' },
13135
+ 'fdc3.channel.3': { name: 'Channel 3', color: 'yellow', glyph: '3' },
13136
+ 'fdc3.channel.4': { name: 'Channel 4', color: 'green', glyph: '4' },
13137
+ 'fdc3.channel.5': { name: 'Channel 5', color: 'cyan', glyph: '5' },
13138
+ 'fdc3.channel.6': { name: 'Channel 6', color: 'blue', glyph: '6' },
13139
+ 'fdc3.channel.7': { name: 'Channel 7', color: 'magenta', glyph: '7' },
13140
+ 'fdc3.channel.8': { name: 'Channel 8', color: 'purple', glyph: '8' }
13141
+ };
13142
+ const legacyColorChannelIds = {
13143
+ red: 'fdc3.channel.1',
13144
+ orange: 'fdc3.channel.2',
13145
+ yellow: 'fdc3.channel.3',
13146
+ green: 'fdc3.channel.4',
13147
+ teal: 'fdc3.channel.5',
13148
+ blue: 'fdc3.channel.6',
13149
+ pink: 'fdc3.channel.7',
13150
+ // Legacy indigo (workspace) and purple (core) intentionally converge on the same FDC3 purple channel.
13151
+ indigo: 'fdc3.channel.8',
13152
+ purple: 'fdc3.channel.8'
13153
+ };
13154
+ /**
13155
+ * Converts a legacy color-named channel ID to its canonical FDC3 user-channel ID.
13156
+ * The removed legacy gray channel resolves to no channel.
13157
+ */
13158
+ function normalizeColorChannelId(colorChannelId) {
13159
+ if (colorChannelId === 'gray') {
13160
+ return undefined;
13161
+ }
13162
+ if (Object.prototype.hasOwnProperty.call(legacyColorChannelIds, colorChannelId)) {
13163
+ return legacyColorChannelIds[colorChannelId];
13164
+ }
13165
+ return colorChannelId;
13166
+ }
13167
+
13052
13168
  var __classPrivateFieldSet$9 = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
13053
13169
  if (kind === "m") throw new TypeError("Private method is not writable");
13054
13170
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
@@ -13061,50 +13177,7 @@ var __classPrivateFieldGet$9 = (undefined && undefined.__classPrivateFieldGet) |
13061
13177
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
13062
13178
  };
13063
13179
  var _InteropBroker_fdc3Info, _InteropBroker_contextGroups, _InteropBroker_providerPromise;
13064
- const defaultContextGroups = [
13065
- {
13066
- id: 'green',
13067
- displayMetadata: {
13068
- color: '#00CC88',
13069
- name: 'green'
13070
- }
13071
- },
13072
- {
13073
- id: 'purple',
13074
- displayMetadata: {
13075
- color: '#8C61FF',
13076
- name: 'purple'
13077
- }
13078
- },
13079
- {
13080
- id: 'orange',
13081
- displayMetadata: {
13082
- color: '#FF8C4C',
13083
- name: 'orange'
13084
- }
13085
- },
13086
- {
13087
- id: 'red',
13088
- displayMetadata: {
13089
- color: '#FF5E60',
13090
- name: 'red'
13091
- }
13092
- },
13093
- {
13094
- id: 'pink',
13095
- displayMetadata: {
13096
- color: '#FF8FB8',
13097
- name: 'pink'
13098
- }
13099
- },
13100
- {
13101
- id: 'yellow',
13102
- displayMetadata: {
13103
- color: '#E9FF8F',
13104
- name: 'yellow'
13105
- }
13106
- }
13107
- ];
13180
+ const defaultContextGroups = Object.entries(defaultColorChannels).map(([id, displayMetadata]) => ({ id, displayMetadata }));
13108
13181
  /**
13109
13182
  * {@link https://developers.openfin.co/of-docs/docs/enable-color-linking}
13110
13183
  *
@@ -13134,17 +13207,19 @@ const defaultContextGroups = [
13134
13207
  * "interopBrokerConfiguration": {
13135
13208
  * "contextGroups": [
13136
13209
  * {
13137
- * "id": "green",
13210
+ * "id": "fdc3.channel.4",
13138
13211
  * "displayMetadata": {
13139
- * "color": "#00CC88",
13140
- * "name": "green"
13212
+ * "color": "green",
13213
+ * "name": "Channel 4",
13214
+ * "glyph": "4"
13141
13215
  * }
13142
13216
  * },
13143
13217
  * {
13144
- * "id": "purple",
13218
+ * "id": "fdc3.channel.8",
13145
13219
  * "displayMetadata": {
13146
- * "color": "#8C61FF",
13147
- * "name": "purple"
13220
+ * "color": "purple",
13221
+ * "name": "Channel 8",
13222
+ * "glyph": "8"
13148
13223
  * }
13149
13224
  * },
13150
13225
  * ]
@@ -13307,9 +13382,13 @@ class InteropBroker extends Base {
13307
13382
  this.wire.sendAction('interop-broker-set-context-for-group').catch((e) => {
13308
13383
  // don't expose, analytics-only call
13309
13384
  });
13310
- const contextGroupState = this.contextGroupsById.get(contextGroupId);
13385
+ const normalizedContextGroupId = this.normalizeContextGroupId(contextGroupId);
13386
+ if (normalizedContextGroupId === undefined) {
13387
+ return;
13388
+ }
13389
+ const contextGroupState = this.contextGroupsById.get(normalizedContextGroupId);
13311
13390
  if (!contextGroupState) {
13312
- throw new Error(`Unable to set context for context group that isn't in the context group mapping: ${contextGroupId}.`);
13391
+ throw new Error(`Unable to set context for context group that isn't in the context group mapping: ${normalizedContextGroupId}.`);
13313
13392
  }
13314
13393
  const contextIntegrityCheckResult = InteropBroker.checkContextIntegrity(context);
13315
13394
  if (contextIntegrityCheckResult.isValid === false) {
@@ -13317,8 +13396,8 @@ class InteropBroker extends Base {
13317
13396
  }
13318
13397
  const broadcastedContextType = context.type;
13319
13398
  contextGroupState.set(broadcastedContextType, context);
13320
- this.lastContextMap.set(contextGroupId, broadcastedContextType);
13321
- const clientsInSameContextGroup = Array.from(this.interopClients.values()).filter((connectedClient) => connectedClient.contextGroupId === contextGroupId);
13399
+ this.lastContextMap.set(normalizedContextGroupId, broadcastedContextType);
13400
+ const clientsInSameContextGroup = Array.from(this.interopClients.values()).filter((connectedClient) => connectedClient.contextGroupId === normalizedContextGroupId);
13322
13401
  clientsInSameContextGroup.forEach((client) => {
13323
13402
  for (const [, handlerInfo] of client.contextHandlers) {
13324
13403
  if (InteropBroker.isContextTypeCompatible(broadcastedContextType, handlerInfo.contextType)) {
@@ -13364,10 +13443,20 @@ class InteropBroker extends Base {
13364
13443
  * @param joinContextGroupOptions - Id of the Context Group and identity of the entity to join to the group.
13365
13444
  * @param senderIdentity - Identity of the client sender.
13366
13445
  */
13367
- async joinContextGroup({ contextGroupId, target }, senderIdentity) {
13446
+ async joinContextGroup({ contextGroupId: requestedContextGroupId, target }, senderIdentity) {
13368
13447
  this.wire.sendAction('interop-broker-join-context-group').catch((e) => {
13369
13448
  // don't expose, analytics-only call
13370
13449
  });
13450
+ const contextGroupId = this.normalizeContextGroupId(requestedContextGroupId);
13451
+ if (contextGroupId === undefined) {
13452
+ if (target) {
13453
+ await this.removeFromContextGroup({ target }, senderIdentity);
13454
+ }
13455
+ else {
13456
+ await this.removeClientFromContextGroup(senderIdentity);
13457
+ }
13458
+ return;
13459
+ }
13371
13460
  if (this.sessionContextGroupMap.has(contextGroupId)) {
13372
13461
  throw new Error(BROKER_ERRORS.joinSessionContextGroupWithJoinContextGroup);
13373
13462
  }
@@ -13409,10 +13498,15 @@ class InteropBroker extends Base {
13409
13498
  * @param addClientToContextGroupOptions - Contains the contextGroupId
13410
13499
  * @param clientIdentity - Identity of the client sender.
13411
13500
  */
13412
- async addClientToContextGroup({ contextGroupId }, clientIdentity) {
13501
+ async addClientToContextGroup({ contextGroupId: requestedContextGroupId }, clientIdentity) {
13413
13502
  this.wire.sendAction('interop-broker-add-client-to-context-group').catch((e) => {
13414
13503
  // don't expose, analytics-only call
13415
13504
  });
13505
+ const contextGroupId = this.normalizeContextGroupId(requestedContextGroupId);
13506
+ if (contextGroupId === undefined) {
13507
+ await this.removeClientFromContextGroup(clientIdentity);
13508
+ return;
13509
+ }
13416
13510
  const clientSubscriptionState = this.getClientState(clientIdentity);
13417
13511
  if (!clientSubscriptionState) {
13418
13512
  throw new Error(`Client with Identity: ${clientIdentity.uuid} ${clientIdentity.name} not in Client State Map`);
@@ -13511,6 +13605,9 @@ class InteropBroker extends Base {
13511
13605
  clientState.contextGroupId = undefined;
13512
13606
  }
13513
13607
  await this.setCurrentContextGroupInClientOptions(clientIdentity, null);
13608
+ if (previousContextGroupId === undefined) {
13609
+ return;
13610
+ }
13514
13611
  // All settled will suppress uncaught exceptions. We don't want to await this because it could
13515
13612
  // result in the operation hanging.
13516
13613
  Promise.allSettled(this.channel.publish('client-changed-context-group', {
@@ -13548,7 +13645,11 @@ class InteropBroker extends Base {
13548
13645
  this.wire.sendAction('interop-broker-get-info-for-context-group').catch((e) => {
13549
13646
  // don't expose, analytics-only call
13550
13647
  });
13551
- return this.getContextGroups().find((contextGroup) => contextGroup.id === contextGroupId);
13648
+ const normalizedContextGroupId = this.normalizeContextGroupId(contextGroupId);
13649
+ if (normalizedContextGroupId === undefined) {
13650
+ return undefined;
13651
+ }
13652
+ return this.getContextGroups().find((contextGroup) => contextGroup.id === normalizedContextGroupId);
13552
13653
  }
13553
13654
  // Used by platform windows to get all clients for a context group.
13554
13655
  /**
@@ -13564,8 +13665,12 @@ class InteropBroker extends Base {
13564
13665
  this.wire.sendAction('interop-broker-get-all-clients-in-context-group').catch((e) => {
13565
13666
  // don't expose, analytics-only call
13566
13667
  });
13668
+ const normalizedContextGroupId = this.normalizeContextGroupId(contextGroupId);
13669
+ if (normalizedContextGroupId === undefined) {
13670
+ return [];
13671
+ }
13567
13672
  const clientsInContextGroup = Array.from(this.interopClients.values())
13568
- .filter((connectedClient) => connectedClient.contextGroupId === contextGroupId)
13673
+ .filter((connectedClient) => connectedClient.contextGroupId === normalizedContextGroupId)
13569
13674
  .map((subscriptionState) => {
13570
13675
  return subscriptionState.clientIdentity;
13571
13676
  });
@@ -14012,8 +14117,9 @@ class InteropBroker extends Base {
14012
14117
  }
14013
14118
  // Used to restore interop broker state in snapshots.
14014
14119
  applySnapshot(snapshot, options) {
14015
- const contextGroupStates = snapshot?.interopSnapshotDetails?.contextGroupStates;
14016
- if (contextGroupStates) {
14120
+ const incomingContextGroupStates = snapshot?.interopSnapshotDetails?.contextGroupStates;
14121
+ if (incomingContextGroupStates) {
14122
+ const contextGroupStates = this.normalizeContextGroupStates(incomingContextGroupStates);
14017
14123
  if (!options?.closeExistingWindows) {
14018
14124
  this.updateExistingClients(contextGroupStates);
14019
14125
  }
@@ -14158,6 +14264,23 @@ class InteropBroker extends Base {
14158
14264
  });
14159
14265
  return newObject;
14160
14266
  }
14267
+ normalizeContextGroupStates(incomingContextGroupStates) {
14268
+ const normalizedContextGroupStates = {};
14269
+ for (const [contextGroupId, contexts] of Object.entries(incomingContextGroupStates)) {
14270
+ const normalizedContextGroupId = this.normalizeContextGroupId(contextGroupId);
14271
+ if (normalizedContextGroupId !== undefined) {
14272
+ normalizedContextGroupStates[normalizedContextGroupId] = {
14273
+ ...normalizedContextGroupStates[normalizedContextGroupId],
14274
+ ...contexts
14275
+ };
14276
+ }
14277
+ }
14278
+ return normalizedContextGroupStates;
14279
+ }
14280
+ normalizeContextGroupId(contextGroupId) {
14281
+ const usesDefaultColorChannels = Object.keys(defaultColorChannels).every((defaultContextGroupId) => this.contextGroupsById.has(defaultContextGroupId));
14282
+ return usesDefaultColorChannels ? normalizeColorChannelId(contextGroupId) : contextGroupId;
14283
+ }
14161
14284
  // Util to check a client identity.
14162
14285
  static hasEndpointId(target) {
14163
14286
  return target.endpointId !== undefined;
@@ -14221,8 +14344,14 @@ class InteropBroker extends Base {
14221
14344
  clientIdentity
14222
14345
  };
14223
14346
  // Only allow the client to join a contextGroup that actually exists.
14224
- if (payload?.currentContextGroup && this.contextGroupsById.has(payload.currentContextGroup)) {
14225
- clientSubscriptionState.contextGroupId = payload?.currentContextGroup;
14347
+ const currentContextGroup = payload?.currentContextGroup
14348
+ ? this.normalizeContextGroupId(payload.currentContextGroup)
14349
+ : undefined;
14350
+ if (currentContextGroup && this.contextGroupsById.has(currentContextGroup)) {
14351
+ clientSubscriptionState.contextGroupId = currentContextGroup;
14352
+ if (currentContextGroup !== payload.currentContextGroup) {
14353
+ await this.setCurrentContextGroupInClientOptions(clientIdentity, currentContextGroup);
14354
+ }
14226
14355
  }
14227
14356
  this.interopClients.set(clientIdentity.endpointId, clientSubscriptionState);
14228
14357
  });
@@ -14792,7 +14921,7 @@ class InteropClient extends Base {
14792
14921
  *
14793
14922
  * getLastFocusedView()
14794
14923
  * .then(lastFocusedViewIdentity => {
14795
- * joinViewToContextGroup('red', lastFocusedViewIdentity)
14924
+ * joinViewToContextGroup('fdc3.channel.1', lastFocusedViewIdentity)
14796
14925
  * })
14797
14926
  * ```
14798
14927
  */
@@ -14842,7 +14971,7 @@ class InteropClient extends Base {
14842
14971
  *
14843
14972
  * @example
14844
14973
  * ```js
14845
- * fin.me.interop.getAllClientsInContextGroup('red')
14974
+ * fin.me.interop.getAllClientsInContextGroup('fdc3.channel.1')
14846
14975
  * .then(clientsInContextGroup => {
14847
14976
  * console.log(clientsInContextGroup)
14848
14977
  * })
@@ -14866,7 +14995,7 @@ class InteropClient extends Base {
14866
14995
  *
14867
14996
  * @example
14868
14997
  * ```js
14869
- * fin.me.interop.getInfoForContextGroup('red')
14998
+ * fin.me.interop.getInfoForContextGroup('fdc3.channel.1')
14870
14999
  * .then(contextGroupInfo => {
14871
15000
  * console.log(contextGroupInfo.displayMetadata.name)
14872
15001
  * console.log(contextGroupInfo.displayMetadata.color)
@@ -14955,12 +15084,12 @@ class InteropClient extends Base {
14955
15084
  *
14956
15085
  * @example
14957
15086
  * ```js
14958
- * await fin.me.interop.joinContextGroup('yellow');
15087
+ * await fin.me.interop.joinContextGroup('fdc3.channel.3');
14959
15088
  * await fin.me.interop.setContext({ type: 'instrument', id: { ticker: 'FOO' }});
14960
15089
  * const currentContext = await fin.me.interop.getCurrentContext();
14961
15090
  *
14962
15091
  * // with a specific context
14963
- * await fin.me.interop.joinContextGroup('yellow');
15092
+ * await fin.me.interop.joinContextGroup('fdc3.channel.3');
14964
15093
  * await fin.me.interop.setContext({ type: 'country', id: { ISOALPHA3: 'US' }});
14965
15094
  * await fin.me.interop.setContext({ type: 'instrument', id: { ticker: 'FOO' }});
14966
15095
  * const currentContext = await fin.me.interop.getCurrentContext('country');
@@ -15622,15 +15751,18 @@ class FDC3ModuleBase {
15622
15751
  async joinChannel(channelId) {
15623
15752
  this.wire.recordAnalytic('fdc3-join-channel');
15624
15753
  try {
15754
+ const contextGroup = await this.client.getInfoForContextGroup(channelId);
15755
+ if (!contextGroup) {
15756
+ console.error(`No User Channel was found with the ID "${channelId}". If this is an App Channel, use getOrCreateChannel instead.`);
15757
+ throw new Error(ChannelError.NoChannelFound);
15758
+ }
15625
15759
  return await this.client.joinContextGroup(channelId);
15626
15760
  }
15627
15761
  catch (error) {
15628
- if (error.message === BROKER_ERRORS.joinSessionContextGroupWithJoinContextGroup) {
15629
- console.error('The Channel you have tried to join is an App Channel. Custom Channels can only be defined by the Interop Broker through code or manifest configuration. Please use getOrCreateChannel.');
15630
- }
15631
- else {
15632
- console.error(error.message);
15762
+ if (error.message === ChannelError.NoChannelFound) {
15763
+ throw new Error(ChannelError.NoChannelFound);
15633
15764
  }
15765
+ console.error(error.message);
15634
15766
  if (error.message.startsWith('Attempting to join a context group that does not exist')) {
15635
15767
  throw new Error(ChannelError.NoChannelFound);
15636
15768
  }
@@ -16310,7 +16442,7 @@ class InteropModule extends Base {
16310
16442
  * @example
16311
16443
  * ```js
16312
16444
  * const interopConfig = {
16313
- * currentContextGroup: 'green'
16445
+ * currentContextGroup: 'fdc3.channel.4'
16314
16446
  * }
16315
16447
  *
16316
16448
  * const interopBroker = await fin.Interop.init('openfin');
@@ -17317,4 +17449,6 @@ const fin$1 = ((typeof window !== 'undefined' && window?.fin) ||
17317
17449
 
17318
17450
  exports.OpenFin = OpenFin;
17319
17451
  exports.default = OpenFin;
17452
+ exports.defaultColorChannels = defaultColorChannels;
17320
17453
  exports.fin = fin$1;
17454
+ exports.normalizeColorChannelId = normalizeColorChannelId;