@carbonorm/carbonreact 3.6.1 → 4.0.0

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/index.d.ts CHANGED
@@ -28,6 +28,7 @@ export { default as CarbonWebSocket } from "./components/WebSocket/CarbonWebSock
28
28
  export * from "./components/WebSocket/CarbonWebSocket";
29
29
  export * from "./hoc/GlobalHistory";
30
30
  export * from "./hoc/KeysMatching";
31
+ export * from "./hoc/SubsetMatching";
31
32
  export { default as addValidSQL } from "./hoc/addValidSQL";
32
33
  export * from "./hoc/addValidSQL";
33
34
  export { default as changed } from "./hoc/changed";
package/dist/index.esm.js CHANGED
@@ -1409,11 +1409,11 @@ function hexToRgb (hex) {
1409
1409
 
1410
1410
  var styles = {"maintenance-hero":"C5KSPNF","maintenanceHero":"C5KSPNF","httpStatusCode":"NhyRQts","centeredContainer":"nA4Uno6","errorTextGeneral":"yJAgaUs","errorKeys":"SRIoY4m","error-values":"xQIsoNw","errorValues":"xQIsoNw","error-pre":"C6eWpJ3","errorPre":"C6eWpJ3","line-number":"NFRyo7M","lineNumber":"NFRyo7M","cl":"vR2jbfr","slide":"OO2C-Wp"};
1411
1411
 
1412
- var BackendThrowable = () => {
1413
- const bootstrap = CarbonReact.instance;
1414
- const currentThrowable = bootstrap.state.backendThrowable[0];
1415
- console.log([bootstrap.state.backendThrowable, currentThrowable]);
1416
- return jsxRuntime_2("div", { className: styles.maintenanceHero, children: [jsxRuntime_1("h1", { className: styles.httpStatusCode, children: currentThrowable?.status || 500 }), jsxRuntime_1(OutsideClickHandler, { onOutsideClick: () => bootstrap.setState(currentState => ({ backendThrowable: currentState.backendThrowable.slice(1) })), children: jsxRuntime_1("div", { className: styles.centeredContainer, children: Object.keys(currentThrowable).map((key, index) => {
1412
+ var BackendThrowable = (props) => {
1413
+ const { instance } = props;
1414
+ const currentThrowable = instance.state.backendThrowable[0];
1415
+ console.log([instance.state.backendThrowable, currentThrowable]);
1416
+ return jsxRuntime_2("div", { className: styles.maintenanceHero, children: [jsxRuntime_1("h1", { className: styles.httpStatusCode, children: currentThrowable?.status || 500 }), jsxRuntime_1(OutsideClickHandler, { onOutsideClick: () => instance.setState(currentState => ({ backendThrowable: currentState.backendThrowable.slice(1) })), children: jsxRuntime_1("div", { className: styles.centeredContainer, children: Object.keys(currentThrowable).map((key, index) => {
1417
1417
  const valueIsString = typeof currentThrowable[key] === 'string';
1418
1418
  const valueIsCode = 'THROWN NEAR' === key;
1419
1419
  return jsxRuntime_2("div", { children: [jsxRuntime_2("div", { className: styles.errorTextGeneral, children: [" > ", jsxRuntime_1("span", { className: styles.errorKeys, children: key }), ":", valueIsString
@@ -3922,14 +3922,14 @@ function Popup({ open = true, handleClose, children, maxWidth, }) {
3922
3922
  const isProduction = window.location.host.split(".")[0] === "www";
3923
3923
 
3924
3924
  function addAlert(props) {
3925
- CarbonReact.instance.setState(previousState => ({
3925
+ props.instance.setState(previousState => ({
3926
3926
  alertsWaiting: previousState.alertsWaiting.length === 0
3927
3927
  ? [props]
3928
3928
  : [...previousState.alertsWaiting, props]
3929
3929
  }));
3930
3930
  }
3931
- function Alert() {
3932
- const { alertsWaiting, backendThrowable } = CarbonReact.instance.state;
3931
+ function Alert({ instance }) {
3932
+ const { alertsWaiting, backendThrowable } = instance.state;
3933
3933
  let alert = undefined;
3934
3934
  const alertWaiting = alertsWaiting.length + backendThrowable.length;
3935
3935
  if (backendThrowable.length !== 0) {
@@ -3944,8 +3944,9 @@ function Alert() {
3944
3944
  color: 'primary',
3945
3945
  });
3946
3946
  }
3947
- const backendThrowable = CarbonReact.instance.state.backendThrowable[0];
3947
+ const backendThrowable = instance.state.backendThrowable[0];
3948
3948
  alert = {
3949
+ instance: instance,
3949
3950
  title: "Oh no! An issue occurred!",
3950
3951
  text: backendThrowable?.['DropInGaming\\PHP\\Errors\\DropException'] ?? 'An unknown issue occurred. Please try again.',
3951
3952
  timeout: 0,
@@ -3956,7 +3957,7 @@ function Alert() {
3956
3957
  backendThrowable: backendThrowable,
3957
3958
  then: (value) => {
3958
3959
  if (value === 'Expand') {
3959
- CarbonReact.instance.setState(previousState => {
3960
+ instance.setState(previousState => {
3960
3961
  let backendThrowable = previousState.backendThrowable.pop();
3961
3962
  if (backendThrowable === undefined) {
3962
3963
  return {
@@ -3970,7 +3971,7 @@ function Alert() {
3970
3971
  });
3971
3972
  }
3972
3973
  else {
3973
- CarbonReact.instance.setState(previousState => ({
3974
+ instance.setState(previousState => ({
3974
3975
  backendThrowable: previousState.backendThrowable.slice(1)
3975
3976
  }));
3976
3977
  }
@@ -3984,15 +3985,14 @@ function Alert() {
3984
3985
  return null;
3985
3986
  }
3986
3987
  const timeout = alert?.timeout || 15000;
3987
- const bootstrap = CarbonReact.instance;
3988
- const dig = getStyles();
3988
+ const styles = getStyles();
3989
3989
  let cancelTimeout = null;
3990
3990
  const handleClose = () => {
3991
3991
  if (null !== cancelTimeout) {
3992
3992
  clearTimeout(cancelTimeout);
3993
3993
  }
3994
3994
  if (alert?.backendThrowable === undefined) {
3995
- bootstrap.setState(previousState => ({
3995
+ instance.setState(previousState => ({
3996
3996
  alertsWaiting: previousState.alertsWaiting.slice(1)
3997
3997
  }));
3998
3998
  }
@@ -4006,25 +4006,26 @@ function Alert() {
4006
4006
  handleClose();
4007
4007
  }, timeout);
4008
4008
  }
4009
- return jsxRuntime_1(Popup, { handleClose: handleClose, children: jsxRuntime_2("div", { className: classNames("model-content", dig.rounded0, dig.border0), style: {
4009
+ return jsxRuntime_1(Popup, { handleClose: handleClose, children: jsxRuntime_2("div", { className: classNames("model-content", styles.rounded0, styles.border0), style: {
4010
4010
  maxWidth: '75vw',
4011
4011
  maxHeight: '75vh',
4012
- }, children: [jsxRuntime_2("div", { className: classNames(dig.modalHeader, dig.rounded0, dig.border0, {
4012
+ }, children: [jsxRuntime_2("div", { className: classNames(styles.modalHeader, styles.rounded0, styles.border0, {
4013
4013
  // icon?: "warning" | "error" | "success" | "info" | "question"
4014
- [dig.bg_primary]: "info" === alert.icon || alert.icon === undefined || alert.icon === null,
4015
- [dig.bg_success]: "success" === alert.icon,
4016
- [dig.bg_warning]: "warning" === alert.icon,
4017
- [dig.bg_danger]: "error" === alert.icon, // TODO - change to red
4018
- [dig.bgPrimary]: "question" === alert.icon,
4019
- }), children: [jsxRuntime_2("h3", { className: classNames(dig.modalTitle, dig.textDark), id: "staticBackdropLabel", children: ["#", alertWaiting, " ", alert.title] }), jsxRuntime_1("div", { onClick: handleClose, children: jsxRuntime_1(FontAwesomeIcon, { icon: faClose, size: 'xl' }) })] }), jsxRuntime_1("div", { className: classNames(dig.modalBody, dig.border0, dig.textWhite), children: jsxRuntime_2("div", { className: dig.textCenter, children: [alert.text, alert.component] }) }), undefined !== alert.buttons &&
4020
- jsxRuntime_2("div", { className: classNames(dig.modalFooter, dig.border0, dig.rounded0), children: [alert.footerText && jsxRuntime_1("div", { className: classNames(dig.textCenter, dig.textWhite), children: alert.footerText }), alert.buttons?.map((button, index) => {
4021
- return jsxRuntime_1("button", { className: classNames(dig.btn, dig.btnLg, {
4014
+ [styles.bg_primary]: "info" === alert.icon || alert.icon === undefined || alert.icon === null,
4015
+ [styles.bg_success]: "success" === alert.icon,
4016
+ [styles.bg_warning]: "warning" === alert.icon,
4017
+ [styles.bg_danger]: "error" === alert.icon, // TODO - change to red
4018
+ [styles.bgPrimary]: "question" === alert.icon,
4019
+ }), children: [jsxRuntime_2("h3", { className: classNames(styles.modalTitle, styles.textDark), id: "staticBackdropLabel", children: ["#", alertWaiting, " ", alert.title] }), jsxRuntime_1("div", { onClick: handleClose, children: jsxRuntime_1(FontAwesomeIcon, { icon: faClose, size: 'xl' }) })] }), jsxRuntime_1("div", { className: classNames(styles.modalBody, styles.border0, styles.textWhite), children: jsxRuntime_2("div", { className: styles.textCenter, children: [alert.text, alert.component] }) }), undefined !== alert.buttons &&
4020
+ jsxRuntime_2("div", { className: classNames(styles.modalFooter, styles.border0, styles.rounded0), children: [alert.footerText &&
4021
+ jsxRuntime_1("div", { className: classNames(styles.textCenter, styles.textWhite), children: alert.footerText }), alert.buttons?.map((button, index) => {
4022
+ return jsxRuntime_1("button", { className: classNames(styles.btn, styles.btnLg, {
4022
4023
  // todo - color: "default" | "primary" | "secondary" | "inherit" | "danger" | "info" | "success" | "warning" | undefined,
4023
- [dig.bg_success]: "success" === button.color,
4024
- [dig.bg_danger]: "danger" === button.color,
4025
- [dig.bg_primary]: "primary" === button.color,
4026
- [dig.bg_warning]: "warning" === button.color,
4027
- }, "btn-Yes", dig.rounded0), onClick: () => {
4024
+ [styles.bg_success]: "success" === button.color,
4025
+ [styles.bg_danger]: "danger" === button.color,
4026
+ [styles.bg_primary]: "primary" === button.color,
4027
+ [styles.bg_warning]: "warning" === button.color,
4028
+ }, "btn-Yes", styles.rounded0), onClick: () => {
4028
4029
  handleClose();
4029
4030
  alert?.then?.(button.value ?? button.text);
4030
4031
  }, children: button.text }, index);
@@ -4062,14 +4063,16 @@ const useEffectOnce = (effect) => {
4062
4063
  * @function connect
4063
4064
  * This function establishes a connection with the websocket and also ensures constant reconnection if connection closes
4064
4065
  **/
4065
- function initiateWebsocket({ TABLES = undefined, WsLiveUpdates = undefined, url = 'ws' + (window.location.protocol === 'https:' ? 's' : '') + '://' + window.location.host + '/carbonorm/websocket', timeoutSeconds = 250, heartbeatSeconds = 60 } = {}) {
4066
- const { websocket } = CarbonReact.instance.state;
4066
+ function initiateWebsocket(props) {
4067
+ let { instance, TABLES = undefined, WsLiveUpdates = undefined, url = 'ws' + (window.location.protocol === 'https:' ? 's' : '') + '://' + window.location.host + '/carbonorm/websocket', timeoutSeconds = 250, heartbeatSeconds = 60 } = props;
4068
+ const { websocket } = instance.state;
4067
4069
  if (!("WebSocket" in window)) {
4068
4070
  // todo - store that this has been shown in the state
4069
4071
  addAlert({
4070
4072
  title: 'Browser does not support websockets, live updates will fail. You may need to refresh the page to see the newest content.',
4071
4073
  text: 'Please use a modern browser.',
4072
4074
  icon: 'warning',
4075
+ instance
4073
4076
  });
4074
4077
  }
4075
4078
  if (false === (undefined === websocket || null === websocket)) {
@@ -4078,14 +4081,14 @@ function initiateWebsocket({ TABLES = undefined, WsLiveUpdates = undefined, url
4078
4081
  let connectInterval;
4079
4082
  const connection = new WebSocket(url);
4080
4083
  console.log("Connecting websocket url", url);
4081
- CarbonReact.instance.setState({
4084
+ instance.setState({
4082
4085
  websocket: connection
4083
4086
  }, () => {
4084
4087
  connection.onopen = () => {
4085
4088
  console.log('WebSocket Client Connected To :: ' + url);
4086
4089
  clearTimeout(connectInterval); // clear Interval on open of websocket connection
4087
4090
  function heartbeat() {
4088
- const { websocket } = CarbonReact.instance.state;
4091
+ const { websocket } = instance.state;
4089
4092
  if (!websocket)
4090
4093
  return;
4091
4094
  if (websocket.readyState !== 1)
@@ -4100,7 +4103,7 @@ function initiateWebsocket({ TABLES = undefined, WsLiveUpdates = undefined, url
4100
4103
  if (message.data === 'pong') {
4101
4104
  return;
4102
4105
  }
4103
- CarbonReact.instance.setState((prevState) => ({
4106
+ instance.setState((prevState) => ({
4104
4107
  websocketEvents: prevState.websocketEvents.concat(message),
4105
4108
  websocketData: prevState.websocketData.concat(parsedData), // JSON.parse no good - base64?
4106
4109
  }), () => {
@@ -4124,7 +4127,7 @@ function initiateWebsocket({ TABLES = undefined, WsLiveUpdates = undefined, url
4124
4127
  }
4125
4128
  console.log('todo - going to impl REST', TABLE_NAME, METHOD, REQUEST_PRIMARY_KEY, parsedData?.REST);
4126
4129
  const TABLE_NAME_SHORT = TABLE_NAME.substring(TABLE_PREFIX.length);
4127
- const currentCache = CarbonReact.instance.state[TABLE_NAME_SHORT];
4130
+ const currentCache = instance.state[TABLE_NAME_SHORT];
4128
4131
  // just because we have a websocket update, doesn't mean we need the update
4129
4132
  // check to see if the primary key is in the current cache
4130
4133
  const c6Table = TABLES[TABLE_NAME_SHORT] ?? null;
@@ -4161,7 +4164,7 @@ function initiateWebsocket({ TABLES = undefined, WsLiveUpdates = undefined, url
4161
4164
  }
4162
4165
  });
4163
4166
  };
4164
- window.addEventListener("focus", () => initiateWebsocket());
4167
+ window.addEventListener("focus", () => initiateWebsocket(props));
4165
4168
  // websocket onclose event listener
4166
4169
  connection.addEventListener('close', event => {
4167
4170
  let reason;
@@ -4170,7 +4173,7 @@ function initiateWebsocket({ TABLES = undefined, WsLiveUpdates = undefined, url
4170
4173
  const retrySeconds = Math.min(5000, (timeoutSeconds + timeoutSeconds) * 1000);
4171
4174
  timeoutSeconds = retrySeconds;
4172
4175
  console.log(`WebSocket reconnect will be attempted in ${retrySeconds} second(s).`);
4173
- connectInterval = setTimeout(() => initiateWebsocket(), retrySeconds);
4176
+ connectInterval = setTimeout(() => initiateWebsocket(props), retrySeconds);
4174
4177
  };
4175
4178
  // See https://www.rfc-editor.org/rfc/rfc6455#section-7.4.1
4176
4179
  switch (event.code) {
@@ -4234,6 +4237,106 @@ function CarbonWebSocket (props) {
4234
4237
  return null;
4235
4238
  }
4236
4239
 
4240
+ var eUpdateInsertMethod;
4241
+ (function (eUpdateInsertMethod) {
4242
+ eUpdateInsertMethod[eUpdateInsertMethod["REPLACE"] = 0] = "REPLACE";
4243
+ eUpdateInsertMethod[eUpdateInsertMethod["FIRST"] = 1] = "FIRST";
4244
+ eUpdateInsertMethod[eUpdateInsertMethod["LAST"] = 2] = "LAST";
4245
+ })(eUpdateInsertMethod || (eUpdateInsertMethod = {}));
4246
+ /**
4247
+ * Updates or inserts objects in a stateful array, merging new data with existing objects.
4248
+ * @param instance - The React component instance.
4249
+ * @param dataOrCallback - Array of objects or a callback function returning an array of objects.
4250
+ * @param stateKey - The key in the state where the data array is stored.
4251
+ * @param uniqueObjectId - The unique identifier(s) for objects, typically the primary key of the table.
4252
+ * @param insertUpdateOrder - The order in which new data should be inserted/updated.
4253
+ * @param callback - Optional callback function to run after state update.
4254
+ */
4255
+ function updateRestfulObjectArrays({ instance, dataOrCallback, stateKey, uniqueObjectId, insertUpdateOrder = eUpdateInsertMethod.LAST, callback, }) {
4256
+ const uniqueObjectIds = Array.isArray(uniqueObjectId) ? uniqueObjectId : [uniqueObjectId];
4257
+ instance.setState((previousBootstrapState, props) => {
4258
+ let newOrReplacementData = [];
4259
+ if (Array.isArray(dataOrCallback)) {
4260
+ newOrReplacementData = dataOrCallback;
4261
+ }
4262
+ else if (typeof dataOrCallback === "function") {
4263
+ newOrReplacementData = dataOrCallback(previousBootstrapState, props);
4264
+ }
4265
+ else {
4266
+ throw new Error("The dataOrCallback parameter must be an array or function");
4267
+ }
4268
+ if (newOrReplacementData === null) {
4269
+ return null;
4270
+ }
4271
+ const findUniqueObjectIds = (item, value) => {
4272
+ return uniqueObjectIds.every((id) => item[id] === value[id]);
4273
+ };
4274
+ const previousStateProperty = previousBootstrapState[stateKey] ?? [];
4275
+ let updatedData = newOrReplacementData.map((value) => {
4276
+ const existingObject = previousStateProperty?.find((item) => findUniqueObjectIds(item, value)) || {};
4277
+ return { ...existingObject, ...value };
4278
+ });
4279
+ const filterOutUpdated = (array) => {
4280
+ return array?.filter((item) => !updatedData.some((value) => findUniqueObjectIds(item, value))) ?? [];
4281
+ };
4282
+ let newState = {};
4283
+ switch (insertUpdateOrder) {
4284
+ case eUpdateInsertMethod.LAST:
4285
+ newState[stateKey] = [
4286
+ ...filterOutUpdated(previousStateProperty),
4287
+ ...updatedData,
4288
+ ];
4289
+ break;
4290
+ case eUpdateInsertMethod.FIRST:
4291
+ newState[stateKey] = [
4292
+ ...updatedData,
4293
+ ...filterOutUpdated(previousStateProperty),
4294
+ ];
4295
+ break;
4296
+ case eUpdateInsertMethod.REPLACE:
4297
+ newState[stateKey] = [
4298
+ ...(previousStateProperty?.map((oldObject) => {
4299
+ const index = updatedData.findIndex((item) => findUniqueObjectIds(item, oldObject));
4300
+ if (index !== -1) {
4301
+ return updatedData.splice(index, 1)[0];
4302
+ }
4303
+ return oldObject;
4304
+ }) ?? []),
4305
+ ...updatedData,
4306
+ ];
4307
+ break;
4308
+ default:
4309
+ throw new Error("The insertUpdateOrder (eUpdateInsertMethod) was not implemented");
4310
+ }
4311
+ return newState;
4312
+ }, callback);
4313
+ }
4314
+
4315
+ function deleteRestfulObjectArrays({ instance, dataOrCallback, stateKey, uniqueObjectId, callback }) {
4316
+ const uniqueObjectIds = Array.isArray(uniqueObjectId) ? uniqueObjectId : [uniqueObjectId];
4317
+ instance.setState((previousBootstrapState, props) => {
4318
+ let newOrReplacementData = [];
4319
+ if (Array.isArray(dataOrCallback)) {
4320
+ newOrReplacementData = dataOrCallback;
4321
+ }
4322
+ else if (typeof dataOrCallback === 'function') {
4323
+ const callbackReturn = dataOrCallback(previousBootstrapState, props);
4324
+ if (callbackReturn === null) {
4325
+ return null; // No updates needed (noop)
4326
+ }
4327
+ newOrReplacementData = callbackReturn;
4328
+ }
4329
+ else {
4330
+ throw new Error('The dataOrCallback parameter was not an array or function');
4331
+ }
4332
+ const previousStateProperty = previousBootstrapState[stateKey];
4333
+ const updatedStateProperty = previousStateProperty?.filter(item => !newOrReplacementData.some(value => uniqueObjectIds.every(uniqueId => value[uniqueId] === item[uniqueId]))) ?? [];
4334
+ return {
4335
+ [stateKey]: updatedStateProperty
4336
+ };
4337
+ }, callback);
4338
+ }
4339
+
4237
4340
  const initialRequiredCarbonORMState = {
4238
4341
  alertsWaiting: [],
4239
4342
  backendThrowable: [],
@@ -4254,28 +4357,45 @@ function isJsonString(str) {
4254
4357
  }
4255
4358
  return true;
4256
4359
  }
4257
- // Create a context
4258
- const CarbonReact = class extends Component {
4259
- static instance;
4360
+ const persistentStateMap = new Map();
4361
+ class CarbonReact extends Component {
4260
4362
  context = createContext(this.state);
4261
- static persistentState = undefined;
4363
+ // Private static member
4364
+ // we actually implement this in the constructor todo - test this
4365
+ static instance;
4366
+ target;
4367
+ updateRestfulObjectArrays = (rest) => updateRestfulObjectArrays({
4368
+ instance: this,
4369
+ ...rest
4370
+ });
4371
+ deleteRestfulObjectArrays = (rest) => deleteRestfulObjectArrays({
4372
+ instance: this,
4373
+ ...rest
4374
+ });
4262
4375
  static lastLocation = window.location.pathname;
4263
4376
  // @link https://github.com/welldone-software/why-did-you-render
4264
4377
  // noinspection JSUnusedGlobalSymbols
4265
4378
  static whyDidYouRender = true;
4266
4379
  constructor(props) {
4267
4380
  super(props);
4381
+ this.target = new.target;
4268
4382
  console.log('CarbonORM TSX CONSTRUCTOR');
4269
- if (CarbonReact.persistentState !== undefined && this.props.shouldStatePersist !== false) {
4270
- this.state = CarbonReact.persistentState;
4383
+ // this is the magic that allows each class that's extends this to have a static instance - a singleton pattern
4384
+ // new.target is a meta-property introduced in ES6 that references the constructor that was directly invoked with the new keyword.
4385
+ Object.assign(new.target, {
4386
+ instance: this
4387
+ });
4388
+ if (this.props.instanceId && persistentStateMap.has(this.props.instanceId)) {
4389
+ this.state = persistentStateMap.get(this.props.instanceId);
4271
4390
  }
4272
4391
  else {
4392
+ // This should only ever be done here, when the full state is being trashed.
4393
+ // todo - does this suck in context of multiple instances?
4394
+ clearCache({
4395
+ ignoreWarning: true
4396
+ });
4273
4397
  this.state = initialCarbonReactState;
4274
4398
  }
4275
- // This should only ever be done here, when the full state is being trashed.
4276
- clearCache({
4277
- ignoreWarning: true
4278
- });
4279
4399
  /** We can think of our app as having one state; this state.
4280
4400
  * Long-term, I'd like us to store this state to local storage and only load updates on reload...
4281
4401
  * Class based components are far easier to manage state in local storage and pass state down to children.
@@ -4283,15 +4403,9 @@ const CarbonReact = class extends Component {
4283
4403
  * components' tend to be shorter syntactically and bonus points if it's stateless.
4284
4404
  **/
4285
4405
  }
4286
- static getState() {
4287
- return CarbonReact.instance.state;
4288
- }
4289
4406
  shouldComponentUpdate(nextProps, nextState, _nextContext) {
4290
- if (this.props.shouldStatePersist === false) {
4291
- CarbonReact.persistentState = undefined;
4292
- }
4293
- else {
4294
- CarbonReact.persistentState = nextState;
4407
+ if (this.props.instanceId) {
4408
+ persistentStateMap.set(this.props.instanceId, nextState);
4295
4409
  }
4296
4410
  changed(this.constructor.name + ' (C6Api)', 'props', this.props, nextProps);
4297
4411
  changed(this.constructor.name + ' (C6Api)', 'state', this.state, nextState);
@@ -4313,13 +4427,13 @@ const CarbonReact = class extends Component {
4313
4427
  console.log('%c color (' + colorHex + ')', 'color: ' + colorHex);
4314
4428
  const nest = jsxRuntime_1(Nest, { position: 'fixed', backgroundColor: '', color: hexToRgb(colorHex), count: 100 });
4315
4429
  if (this.state.backendThrowable.length > 0) {
4316
- return jsxRuntime_2(jsxRuntime_3, { children: [nest, jsxRuntime_1(BackendThrowable, {})] });
4430
+ return jsxRuntime_2(jsxRuntime_3, { children: [nest, jsxRuntime_1(BackendThrowable, { instance: CarbonReact.instance })] });
4317
4431
  }
4318
4432
  const Context = this.context.Provider;
4319
4433
  return jsxRuntime_2(jsxRuntime_3, { children: [jsxRuntime_1(GlobalHistory, {}), this.props.websocket &&
4320
- jsxRuntime_1(CarbonWebSocket, { ...(true === this.props.websocket ? {} : this.props.websocket) }), jsxRuntime_1(Context, { value: this.state, children: this.props.children }), jsxRuntime_1(ToastContainer, {})] });
4434
+ jsxRuntime_1(CarbonWebSocket, { ...(true === this.props.websocket ? {} : this.props.websocket), instance: CarbonReact.instance }), jsxRuntime_1(Context, { value: this.state, children: this.props.children }), jsxRuntime_1(ToastContainer, {})] });
4321
4435
  }
4322
- };
4436
+ }
4323
4437
 
4324
4438
  var getStatefulObjectWithWhere = ({ request }) => {
4325
4439
  console.log('request', request);
@@ -4376,44 +4490,6 @@ function addValidSQL$1 (sql) {
4376
4490
  addValidSQL.push({ [expect.getState().currentTestName.replaceAll(" ", "_").toLowerCase()]: sql });
4377
4491
  }
4378
4492
 
4379
- //ObjectType, UniqueIdType extends keyof ObjectType
4380
- // @link https://www.typescriptlang.org/docs/handbook/2/mapped-types.html
4381
- function deleteRestfulObjectArrays(dataOrCallback, stateKey, uniqueObjectId, callback) {
4382
- const uniqueObjectIds = uniqueObjectId instanceof Array ? uniqueObjectId : [uniqueObjectId];
4383
- return CarbonReact.instance.setState((previousBootstrapState, props) => {
4384
- let newOrReplacementData = [];
4385
- if (dataOrCallback instanceof Array) {
4386
- newOrReplacementData = dataOrCallback;
4387
- }
4388
- else if (dataOrCallback instanceof Function) {
4389
- let callbackReturn = dataOrCallback(previousBootstrapState, props);
4390
- if (null === callbackReturn) {
4391
- return;
4392
- }
4393
- newOrReplacementData = callbackReturn;
4394
- }
4395
- else {
4396
- throw Error('The dataOrCallback parameter was not an array or function');
4397
- }
4398
- const previousStateProperty = previousBootstrapState[stateKey];
4399
- return {
4400
- [stateKey]: [
4401
- ...previousStateProperty?.filter(item => false === (newOrReplacementData?.find(value => {
4402
- let isMatch = true;
4403
- uniqueObjectIds.find(uniqueObjectId => {
4404
- if (value[uniqueObjectId] !== item[uniqueObjectId]) {
4405
- isMatch = false;
4406
- return true;
4407
- }
4408
- return false;
4409
- });
4410
- return isMatch;
4411
- }) || false)) || []
4412
- ]
4413
- };
4414
- }, callback);
4415
- }
4416
-
4417
4493
  // @link https://stackoverflow.com/questions/31721250/how-to-target-edge-browser-with-javascript
4418
4494
  // Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) \
4419
4495
  // Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.26
@@ -4553,89 +4629,6 @@ function setupTests ({ sqlDirectory = './logs/rest/', logsDirectory = './logs/te
4553
4629
  }, 65000);
4554
4630
  }
4555
4631
 
4556
- var eUpdateInsertMethod;
4557
- (function (eUpdateInsertMethod) {
4558
- eUpdateInsertMethod[eUpdateInsertMethod["REPLACE"] = 0] = "REPLACE";
4559
- eUpdateInsertMethod[eUpdateInsertMethod["FIRST"] = 1] = "FIRST";
4560
- eUpdateInsertMethod[eUpdateInsertMethod["LAST"] = 2] = "LAST";
4561
- })(eUpdateInsertMethod || (eUpdateInsertMethod = {}));
4562
- /**
4563
- *
4564
- * merged with existing objects.uniqueObjectId || {}.
4565
- * @param dataOrCallback
4566
- * @param uniqueObjectId - the uniqueObjectId of the object to update; typically the primary key of the table.
4567
- * @param stateKey -
4568
- * @param insertUpdateOrder
4569
- * @param callback - if you want to do something with the updated state, you can pass a callback here. Run as the second
4570
- * parameter of setState.
4571
- */
4572
- function updateRestfulObjectArrays(dataOrCallback, stateKey, uniqueObjectId, insertUpdateOrder = eUpdateInsertMethod.LAST, callback) {
4573
- const uniqueObjectIds = uniqueObjectId instanceof Array ? uniqueObjectId : [uniqueObjectId];
4574
- const bootstrap = CarbonReact.instance;
4575
- return bootstrap.setState((previousBootstrapState, props) => {
4576
- let newOrReplacementData = [];
4577
- if (dataOrCallback instanceof Array) {
4578
- newOrReplacementData = dataOrCallback;
4579
- }
4580
- else if (dataOrCallback instanceof Function) {
4581
- newOrReplacementData = dataOrCallback(previousBootstrapState, props);
4582
- }
4583
- else {
4584
- throw Error('The dataOrCallback parameter was not an array or function');
4585
- }
4586
- const findUniqueObjectIds = (item, value) => {
4587
- let isMatch = true;
4588
- uniqueObjectIds.find(uniqueObjectId => {
4589
- if (value[uniqueObjectId] !== item[uniqueObjectId]) {
4590
- isMatch = false;
4591
- return true;
4592
- }
4593
- return false;
4594
- });
4595
- return isMatch;
4596
- };
4597
- const previousStateProperty = previousBootstrapState[stateKey];
4598
- let updatedData = newOrReplacementData?.map(value => {
4599
- return {
4600
- ...previousStateProperty?.find(previousValue => findUniqueObjectIds(previousValue, value)) || {},
4601
- ...value
4602
- };
4603
- }) ?? [];
4604
- switch (insertUpdateOrder) {
4605
- default:
4606
- throw Error('The insertUpdateOrder (eUpdateInsertMethod) was not implemented');
4607
- case eUpdateInsertMethod.LAST:
4608
- return {
4609
- [stateKey]: null === newOrReplacementData ? null : [
4610
- ...updatedData,
4611
- ...(previousStateProperty?.filter(item => false === (updatedData?.find(value => findUniqueObjectIds(item, value)) || false)) ?? [])
4612
- ]
4613
- };
4614
- case eUpdateInsertMethod.FIRST:
4615
- return {
4616
- [stateKey]: null === newOrReplacementData ? null : [
4617
- ...(previousStateProperty?.filter(item => false === (updatedData?.find(value => findUniqueObjectIds(item, value)) || false)) ?? []),
4618
- ...updatedData,
4619
- ]
4620
- };
4621
- case eUpdateInsertMethod.REPLACE: {
4622
- return {
4623
- [stateKey]: [
4624
- ...(previousStateProperty?.map(oldObject => {
4625
- const index = updatedData.findIndex(item => findUniqueObjectIds(item, oldObject));
4626
- if (-1 === index) {
4627
- return oldObject;
4628
- }
4629
- return updatedData.splice(index, 1).pop();
4630
- }) ?? []),
4631
- ...updatedData
4632
- ]
4633
- };
4634
- }
4635
- }
4636
- }, callback);
4637
- }
4638
-
4639
4632
  // @link https://stackoverflow.com/questions/6735414/php-data-uri-to-file
4640
4633
  // @link https://www.tutorialspoint.com/convert-image-to-data-uri-with-javascript
4641
4634
  async function toDataURL(src, fileType, callback) {