@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.
@@ -1,7 +1,6 @@
1
- import {tRestfulObjectArrayValues, tStatefulApiData} from "variables/C6";
2
- import CarbonReact from "CarbonReact";
3
- import {KeysMatching} from "./KeysMatching";
4
-
1
+ import CarbonReact, { iCarbonReactState, tStatefulApiData } from "CarbonReact";
2
+ import { KeysMatching } from "./KeysMatching";
3
+ import { SubsetMatching } from "./SubsetMatching";
5
4
 
6
5
  export enum eUpdateInsertMethod {
7
6
  REPLACE,
@@ -9,123 +8,124 @@ export enum eUpdateInsertMethod {
9
8
  LAST,
10
9
  }
11
10
 
11
+ export interface iUpdateRestfulObjectArrays<
12
+ ObjectType extends {
13
+ [key: string]: any;
14
+ } = {},
15
+ S extends { [key: string]: any; } = CarbonReact['state'],
16
+ P = CarbonReact['props']
17
+ > {
18
+ instance: CarbonReact<P, S>;
19
+ dataOrCallback: ObjectType[] | ((state: Readonly<S>, props: Readonly<P>) => ObjectType[] | null);
20
+ stateKey: KeysMatching<S, tStatefulApiData<ObjectType>>;
21
+ uniqueObjectId: keyof ObjectType | (keyof ObjectType)[];
22
+ insertUpdateOrder: eUpdateInsertMethod;
23
+ callback?: () => void;
24
+ }
25
+
12
26
  /**
13
- *
14
- * merged with existing objects.uniqueObjectId || {}.
15
- * @param dataOrCallback
16
- * @param uniqueObjectId - the uniqueObjectId of the object to update; typically the primary key of the table.
17
- * @param stateKey -
18
- * @param insertUpdateOrder
19
- * @param callback - if you want to do something with the updated state, you can pass a callback here. Run as the second
20
- * parameter of setState.
27
+ * Updates or inserts objects in a stateful array, merging new data with existing objects.
28
+ * @param instance - The React component instance.
29
+ * @param dataOrCallback - Array of objects or a callback function returning an array of objects.
30
+ * @param stateKey - The key in the state where the data array is stored.
31
+ * @param uniqueObjectId - The unique identifier(s) for objects, typically the primary key of the table.
32
+ * @param insertUpdateOrder - The order in which new data should be inserted/updated.
33
+ * @param callback - Optional callback function to run after state update.
21
34
  */
22
- export default function updateRestfulObjectArrays<ObjectType = tRestfulObjectArrayValues, S = typeof CarbonReact.instance.state, P = typeof CarbonReact.instance.props>
23
- (dataOrCallback: ObjectType[] | (<K extends keyof S>(
24
- state: ((prevState: Readonly<S>, props: Readonly<P>) => (Pick<S, K> | S | null)) | (Pick<S, K> | S | null),
25
- callback?: () => void
26
- ) => null|(ObjectType[])),
27
- stateKey: KeysMatching<S, tStatefulApiData<ObjectType>>,
28
- uniqueObjectId: (keyof ObjectType) | (keyof ObjectType)[],
29
- insertUpdateOrder: eUpdateInsertMethod = eUpdateInsertMethod.LAST,
30
- callback?: () => void): void {
31
-
32
- const uniqueObjectIds = uniqueObjectId instanceof Array ? uniqueObjectId : [uniqueObjectId];
33
-
34
- const bootstrap = CarbonReact.instance;
35
-
36
- return bootstrap.setState((previousBootstrapState, props): {} => {
35
+ export default function updateRestfulObjectArrays<
36
+ ObjectType extends {
37
+ [key: string]: any;
38
+ } = {},
39
+ S extends { [key: string]: any; } = CarbonReact['state'],
40
+ P = CarbonReact['props']
41
+ >({
42
+ instance,
43
+ dataOrCallback,
44
+ stateKey,
45
+ uniqueObjectId,
46
+ insertUpdateOrder = eUpdateInsertMethod.LAST,
47
+ callback,
48
+ }: iUpdateRestfulObjectArrays<ObjectType, S, P>): void {
37
49
 
38
- let newOrReplacementData: null|(ObjectType[]) = [];
50
+ const uniqueObjectIds = Array.isArray(uniqueObjectId) ? uniqueObjectId : [uniqueObjectId];
39
51
 
40
- if (dataOrCallback instanceof Array) {
52
+ type ValidObject = SubsetMatching<S & iCarbonReactState, tStatefulApiData<ObjectType>>;
41
53
 
42
- newOrReplacementData = dataOrCallback
54
+ instance.setState((
55
+ previousBootstrapState: Readonly<S & iCarbonReactState>,
56
+ props: Readonly<P>
57
+ ): Pick<S & iCarbonReactState, keyof S> | null => {
43
58
 
44
- } else if (dataOrCallback instanceof Function) {
59
+ let newOrReplacementData: ObjectType[] | null = [];
45
60
 
46
- newOrReplacementData = dataOrCallback(previousBootstrapState, props);
61
+ if (Array.isArray(dataOrCallback)) {
47
62
 
48
- } else {
63
+ newOrReplacementData = dataOrCallback;
49
64
 
50
- throw Error('The dataOrCallback parameter was not an array or function')
65
+ } else if (typeof dataOrCallback === "function") {
51
66
 
52
- }
67
+ newOrReplacementData = dataOrCallback(previousBootstrapState, props);
53
68
 
54
- const findUniqueObjectIds = (item : ObjectType, value: ObjectType) => {
69
+ } else {
55
70
 
56
- let isMatch = true;
71
+ throw new Error("The dataOrCallback parameter must be an array or function");
57
72
 
58
- uniqueObjectIds.find(uniqueObjectId => {
59
-
60
- if (value[uniqueObjectId] !== item[uniqueObjectId]) {
61
-
62
- isMatch = false;
63
-
64
- return true;
73
+ }
65
74
 
66
- }
75
+ if (newOrReplacementData === null) {
76
+ return null
77
+ }
67
78
 
68
- return false;
79
+ const findUniqueObjectIds = (item: ObjectType, value: ObjectType) => {
80
+ return uniqueObjectIds.every((id) => item[id] === value[id]);
81
+ };
69
82
 
70
- })
83
+ const previousStateProperty = previousBootstrapState[stateKey] as tStatefulApiData<ObjectType> ?? [];
71
84
 
72
- return isMatch;
85
+ let updatedData: tStatefulApiData<ObjectType> = newOrReplacementData.map((value) => {
86
+ const existingObject = previousStateProperty?.find((item) =>
87
+ findUniqueObjectIds(item, value)
88
+ ) || {};
89
+ return { ...existingObject, ...value };
90
+ });
73
91
 
74
- }
92
+ const filterOutUpdated = (array: tStatefulApiData<ObjectType>) => {
93
+ return array?.filter((item) => !updatedData.some((value) => findUniqueObjectIds(item, value))) ?? [];
94
+ };
75
95
 
76
- const previousStateProperty : ObjectType[] = previousBootstrapState[stateKey];
96
+ let newState: Partial<ValidObject> = {};
77
97
 
78
- let updatedData : ObjectType[] = newOrReplacementData?.map(value => {
79
- return {
80
- ...previousStateProperty?.find(previousValue => findUniqueObjectIds(previousValue, value)) || {},
81
- ...value
82
- }
83
- }) ?? [];
84
-
85
- switch (insertUpdateOrder) {
86
- default:
87
- throw Error('The insertUpdateOrder (eUpdateInsertMethod) was not implemented')
88
- case eUpdateInsertMethod.LAST:
89
- return {
90
- [stateKey]: null === newOrReplacementData ? null : [
98
+ switch (insertUpdateOrder) {
99
+ case eUpdateInsertMethod.LAST:
100
+ newState[stateKey as keyof ValidObject] = [
101
+ ...filterOutUpdated(previousStateProperty),
91
102
  ...updatedData,
92
- ...(previousStateProperty?.filter(item => false === (updatedData?.find(value => findUniqueObjectIds(item, value)) || false)) ?? [])
93
- ]
94
- }
95
-
96
- case eUpdateInsertMethod.FIRST:
97
- return {
98
- [stateKey]: null === newOrReplacementData ? null : [
99
- ...(previousStateProperty?.filter(item => false === (updatedData?.find(value => findUniqueObjectIds(item, value)) || false)) ?? []),
103
+ ] as any;
104
+ break;
105
+ case eUpdateInsertMethod.FIRST:
106
+ newState[stateKey as keyof ValidObject] = [
100
107
  ...updatedData,
101
- ]
102
- }
103
- case eUpdateInsertMethod.REPLACE: {
104
-
105
- return {
106
- [stateKey]: [
107
- ...(previousStateProperty?.map(oldObject => {
108
-
109
- const index = updatedData.findIndex(item => findUniqueObjectIds(item, oldObject));
110
-
111
- if (-1 === index) {
112
-
113
- return oldObject
114
-
108
+ ...filterOutUpdated(previousStateProperty),
109
+ ] as any;
110
+ break;
111
+ case eUpdateInsertMethod.REPLACE:
112
+ newState[stateKey as keyof ValidObject] = [
113
+ ...(previousStateProperty?.map((oldObject) => {
114
+ const index = updatedData.findIndex((item) => findUniqueObjectIds(item, oldObject));
115
+ if (index !== -1) {
116
+ return updatedData.splice(index, 1)[0];
115
117
  }
116
-
117
- return updatedData.splice(index, 1).pop()
118
-
118
+ return oldObject;
119
119
  }) ?? []),
120
- ...updatedData
121
- ]
122
- };
120
+ ...updatedData,
121
+ ] as any;
122
+ break;
123
+ default:
124
+ throw new Error("The insertUpdateOrder (eUpdateInsertMethod) was not implemented");
123
125
  }
124
126
 
125
- }
126
-
127
- }, callback);
128
-
127
+ return newState as Pick<S & iCarbonReactState, keyof S>;
128
+ },
129
+ callback
130
+ );
129
131
  }
130
-
131
-
package/src/index.ts CHANGED
@@ -29,6 +29,7 @@ export { default as CarbonWebSocket } from "./components/WebSocket/CarbonWebSock
29
29
  export * from "./components/WebSocket/CarbonWebSocket";
30
30
  export * from "./hoc/GlobalHistory";
31
31
  export * from "./hoc/KeysMatching";
32
+ export * from "./hoc/SubsetMatching";
32
33
  export { default as addValidSQL } from "./hoc/addValidSQL";
33
34
  export * from "./hoc/addValidSQL";
34
35
  export { default as changed } from "./hoc/changed";
@@ -3226,7 +3226,7 @@ export type RestTableInterfaces = iCarbons
3226
3226
  | iWp_Users;
3227
3227
 
3228
3228
 
3229
- export type tStatefulApiData<T> = T[] | undefined | null;
3229
+
3230
3230
 
3231
3231
 
3232
3232
  // this refers to the value types of the keys above, aka values in the state