@equinor/cpl-utils 0.2.0 → 0.2.2

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.mts CHANGED
@@ -113,6 +113,67 @@ declare function hasCircularDependency<T extends object>(items: T[], idKey: keyo
113
113
  */
114
114
  declare function itemIsDefined<T>(item: T): item is Exclude<typeof item, undefined>;
115
115
 
116
+ type NestedRecord<K extends readonly string[]> = K extends [
117
+ infer First extends string,
118
+ ...infer Rest extends string[]
119
+ ] ? Record<First, NestedRecord<Rest>> : unknown;
120
+ /**
121
+ * Checks if an object has a nested property chain, using Object.prototype.hasOwnProperty at each level.
122
+ * Returns true if all keys exist and are objects (except the last, which can be any value).
123
+ *
124
+ * @template K - Tuple of string keys representing the property chain.
125
+ * @param object - The object to check.
126
+ * @param keys - The property chain to check for.
127
+ * @returns {boolean} True if the nested property exists, false otherwise.
128
+ *
129
+ * @example
130
+ * // Basic usage
131
+ * const apiError = { error: { message: 'Not found' } }
132
+ * if (
133
+ * objectHasOwnNestedProperty(apiError, 'error', 'message') &&
134
+ * typeof apiError.error.message === 'string'
135
+ * ) {
136
+ * return apiError.error.message
137
+ * }
138
+ *
139
+ * @example
140
+ * // Deeply nested object
141
+ * const data = { a: { b: { c: 42 } } }
142
+ * if (objectHasOwnNestedProperty(data, 'a', 'b', 'c')) {
143
+ * console.log(data.a.b.c) // 42
144
+ * }
145
+ *
146
+
147
+ * @example
148
+ * // Usage in a try/catch block to extract a deeply nested error message
149
+ * try {
150
+ * // ...some code that may throw
151
+ * } catch(error) {
152
+ * if (
153
+ * objectHasOwnNestedProperty(error, 'body', 'error', 'message') &&
154
+ * typeof error.body.error.message === 'string'
155
+ * ) {
156
+ * setErrorMessage(error.body.error.message)
157
+ * }
158
+ * }
159
+ *
160
+ * // Missing property
161
+ * const obj = { a: { b: {} } }
162
+ * objectHasOwnNestedProperty(obj, 'a', 'b', 'c') // false
163
+ *
164
+ * @example
165
+ * // Works with arrays as values
166
+ * const arrObj = { a: { b: [1, 2, 3] } }
167
+ * objectHasOwnNestedProperty(arrObj, 'a', 'b') // true
168
+ *
169
+ * @example
170
+ * // TypeScript type guard
171
+ * if (objectHasOwnNestedProperty(apiError, 'error', 'message')) {
172
+ * // apiError is now typed as { error: { message: unknown } }
173
+ * }
174
+ */
175
+ declare function objectHasOwnNestedProperty<K extends readonly string[]>(object: unknown, ...keys: K): object is NestedRecord<K>;
176
+
116
177
  /**
117
178
  * A better typed `Object.prototype.objectHasOwnOroperty`. It helps TypeScript
118
179
  * infer types when an object has multiple types with different properties.
@@ -144,4 +205,4 @@ declare function itemIsDefined<T>(item: T): item is Exclude<typeof item, undefin
144
205
  */
145
206
  declare function objectHasOwnProperty<Key extends PropertyKey>(object: object, key: Key): object is Record<Key, unknown>;
146
207
 
147
- export { type TreeNode, buildTreeNodes, hasCircularDependency, itemIsDefined, objectHasOwnProperty };
208
+ export { type TreeNode, buildTreeNodes, hasCircularDependency, itemIsDefined, objectHasOwnNestedProperty, objectHasOwnProperty };
package/dist/index.d.ts CHANGED
@@ -113,6 +113,67 @@ declare function hasCircularDependency<T extends object>(items: T[], idKey: keyo
113
113
  */
114
114
  declare function itemIsDefined<T>(item: T): item is Exclude<typeof item, undefined>;
115
115
 
116
+ type NestedRecord<K extends readonly string[]> = K extends [
117
+ infer First extends string,
118
+ ...infer Rest extends string[]
119
+ ] ? Record<First, NestedRecord<Rest>> : unknown;
120
+ /**
121
+ * Checks if an object has a nested property chain, using Object.prototype.hasOwnProperty at each level.
122
+ * Returns true if all keys exist and are objects (except the last, which can be any value).
123
+ *
124
+ * @template K - Tuple of string keys representing the property chain.
125
+ * @param object - The object to check.
126
+ * @param keys - The property chain to check for.
127
+ * @returns {boolean} True if the nested property exists, false otherwise.
128
+ *
129
+ * @example
130
+ * // Basic usage
131
+ * const apiError = { error: { message: 'Not found' } }
132
+ * if (
133
+ * objectHasOwnNestedProperty(apiError, 'error', 'message') &&
134
+ * typeof apiError.error.message === 'string'
135
+ * ) {
136
+ * return apiError.error.message
137
+ * }
138
+ *
139
+ * @example
140
+ * // Deeply nested object
141
+ * const data = { a: { b: { c: 42 } } }
142
+ * if (objectHasOwnNestedProperty(data, 'a', 'b', 'c')) {
143
+ * console.log(data.a.b.c) // 42
144
+ * }
145
+ *
146
+
147
+ * @example
148
+ * // Usage in a try/catch block to extract a deeply nested error message
149
+ * try {
150
+ * // ...some code that may throw
151
+ * } catch(error) {
152
+ * if (
153
+ * objectHasOwnNestedProperty(error, 'body', 'error', 'message') &&
154
+ * typeof error.body.error.message === 'string'
155
+ * ) {
156
+ * setErrorMessage(error.body.error.message)
157
+ * }
158
+ * }
159
+ *
160
+ * // Missing property
161
+ * const obj = { a: { b: {} } }
162
+ * objectHasOwnNestedProperty(obj, 'a', 'b', 'c') // false
163
+ *
164
+ * @example
165
+ * // Works with arrays as values
166
+ * const arrObj = { a: { b: [1, 2, 3] } }
167
+ * objectHasOwnNestedProperty(arrObj, 'a', 'b') // true
168
+ *
169
+ * @example
170
+ * // TypeScript type guard
171
+ * if (objectHasOwnNestedProperty(apiError, 'error', 'message')) {
172
+ * // apiError is now typed as { error: { message: unknown } }
173
+ * }
174
+ */
175
+ declare function objectHasOwnNestedProperty<K extends readonly string[]>(object: unknown, ...keys: K): object is NestedRecord<K>;
176
+
116
177
  /**
117
178
  * A better typed `Object.prototype.objectHasOwnOroperty`. It helps TypeScript
118
179
  * infer types when an object has multiple types with different properties.
@@ -144,4 +205,4 @@ declare function itemIsDefined<T>(item: T): item is Exclude<typeof item, undefin
144
205
  */
145
206
  declare function objectHasOwnProperty<Key extends PropertyKey>(object: object, key: Key): object is Record<Key, unknown>;
146
207
 
147
- export { type TreeNode, buildTreeNodes, hasCircularDependency, itemIsDefined, objectHasOwnProperty };
208
+ export { type TreeNode, buildTreeNodes, hasCircularDependency, itemIsDefined, objectHasOwnNestedProperty, objectHasOwnProperty };
package/dist/index.js CHANGED
@@ -2,7 +2,21 @@
2
2
  var __defProp = Object.defineProperty;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
8
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
+ var __spreadValues = (a, b) => {
10
+ for (var prop in b || (b = {}))
11
+ if (__hasOwnProp.call(b, prop))
12
+ __defNormalProp(a, prop, b[prop]);
13
+ if (__getOwnPropSymbols)
14
+ for (var prop of __getOwnPropSymbols(b)) {
15
+ if (__propIsEnum.call(b, prop))
16
+ __defNormalProp(a, prop, b[prop]);
17
+ }
18
+ return a;
19
+ };
6
20
  var __export = (target, all) => {
7
21
  for (var name in all)
8
22
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -23,6 +37,7 @@ __export(index_exports, {
23
37
  buildTreeNodes: () => buildTreeNodes,
24
38
  hasCircularDependency: () => hasCircularDependency,
25
39
  itemIsDefined: () => itemIsDefined,
40
+ objectHasOwnNestedProperty: () => objectHasOwnNestedProperty,
26
41
  objectHasOwnProperty: () => objectHasOwnProperty
27
42
  });
28
43
  module.exports = __toCommonJS(index_exports);
@@ -72,7 +87,8 @@ function buildTreeNodes(items, idKey, parentIdKey, options = {}) {
72
87
  if (!objectHasOwnProperty(item, idKey)) {
73
88
  throw new Error(`Item is missing idKey named '${String(idKey)}'`);
74
89
  }
75
- lookupTable.set(item[idKey], item);
90
+ const nodeCopy = __spreadValues({}, item);
91
+ lookupTable.set(item[idKey], nodeCopy);
76
92
  }
77
93
  const rootNodes = [];
78
94
  for (const item of lookupTable.values()) {
@@ -107,10 +123,26 @@ function buildTreeNodes(items, idKey, parentIdKey, options = {}) {
107
123
  function itemIsDefined(item) {
108
124
  return item !== void 0;
109
125
  }
126
+
127
+ // src/object-has-own-nested-property.ts
128
+ function objectHasOwnNestedProperty(object, ...keys) {
129
+ if (typeof object !== "object" || object === null) {
130
+ return false;
131
+ }
132
+ let currentObject = object;
133
+ for (const key of keys) {
134
+ if (!objectHasOwnProperty(currentObject, key) || typeof currentObject[key] !== "object" || currentObject[key] === null) {
135
+ return false;
136
+ }
137
+ currentObject = currentObject[key];
138
+ }
139
+ return true;
140
+ }
110
141
  // Annotate the CommonJS export names for ESM import in node:
111
142
  0 && (module.exports = {
112
143
  buildTreeNodes,
113
144
  hasCircularDependency,
114
145
  itemIsDefined,
146
+ objectHasOwnNestedProperty,
115
147
  objectHasOwnProperty
116
148
  });
package/dist/index.mjs CHANGED
@@ -1,3 +1,20 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
3
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
4
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
5
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
+ var __spreadValues = (a, b) => {
7
+ for (var prop in b || (b = {}))
8
+ if (__hasOwnProp.call(b, prop))
9
+ __defNormalProp(a, prop, b[prop]);
10
+ if (__getOwnPropSymbols)
11
+ for (var prop of __getOwnPropSymbols(b)) {
12
+ if (__propIsEnum.call(b, prop))
13
+ __defNormalProp(a, prop, b[prop]);
14
+ }
15
+ return a;
16
+ };
17
+
1
18
  // src/has-circular-dependency.ts
2
19
  function hasCircularDependency(items, idKey, parentIdKey) {
3
20
  const parentMap = /* @__PURE__ */ new Map();
@@ -43,7 +60,8 @@ function buildTreeNodes(items, idKey, parentIdKey, options = {}) {
43
60
  if (!objectHasOwnProperty(item, idKey)) {
44
61
  throw new Error(`Item is missing idKey named '${String(idKey)}'`);
45
62
  }
46
- lookupTable.set(item[idKey], item);
63
+ const nodeCopy = __spreadValues({}, item);
64
+ lookupTable.set(item[idKey], nodeCopy);
47
65
  }
48
66
  const rootNodes = [];
49
67
  for (const item of lookupTable.values()) {
@@ -78,9 +96,25 @@ function buildTreeNodes(items, idKey, parentIdKey, options = {}) {
78
96
  function itemIsDefined(item) {
79
97
  return item !== void 0;
80
98
  }
99
+
100
+ // src/object-has-own-nested-property.ts
101
+ function objectHasOwnNestedProperty(object, ...keys) {
102
+ if (typeof object !== "object" || object === null) {
103
+ return false;
104
+ }
105
+ let currentObject = object;
106
+ for (const key of keys) {
107
+ if (!objectHasOwnProperty(currentObject, key) || typeof currentObject[key] !== "object" || currentObject[key] === null) {
108
+ return false;
109
+ }
110
+ currentObject = currentObject[key];
111
+ }
112
+ return true;
113
+ }
81
114
  export {
82
115
  buildTreeNodes,
83
116
  hasCircularDependency,
84
117
  itemIsDefined,
118
+ objectHasOwnNestedProperty,
85
119
  objectHasOwnProperty
86
120
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@equinor/cpl-utils",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "license": "MIT",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",