@twin.org/core 0.0.1-next.24 → 0.0.1-next.26

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.
@@ -113,7 +113,12 @@ class Is {
113
113
  }
114
114
  try {
115
115
  const json = JSON.parse(value);
116
- return typeof json === "object";
116
+ return (Is.object(json) ||
117
+ Is.array(json) ||
118
+ Is.string(json) ||
119
+ Is.number(json) ||
120
+ Is.boolean(json) ||
121
+ Is.null(json));
117
122
  }
118
123
  catch {
119
124
  return false;
@@ -1534,6 +1539,18 @@ class Guards {
1534
1539
  throw new GuardError(source, "guard.stringEmpty", property, value);
1535
1540
  }
1536
1541
  }
1542
+ /**
1543
+ * Is the property a JSON value.
1544
+ * @param source The source of the error.
1545
+ * @param property The name of the property.
1546
+ * @param value The value to test.
1547
+ * @throws GuardError If the value does not match the assertion.
1548
+ */
1549
+ static json(source, property, value) {
1550
+ if (!Is.json(value)) {
1551
+ throw new GuardError(source, "guard.stringJson", property, value);
1552
+ }
1553
+ }
1537
1554
  /**
1538
1555
  * Is the property a base64 string.
1539
1556
  * @param source The source of the error.
@@ -2504,30 +2521,93 @@ class ObjectHelper {
2504
2521
  * @returns The property.
2505
2522
  */
2506
2523
  static propertyGet(obj, property) {
2507
- if (property.includes(".")) {
2508
- const parts = property.split(".");
2509
- let value = obj;
2510
- for (const part of parts) {
2511
- if (Is.object(value)) {
2512
- value = value[part];
2524
+ const pathParts = property.split(".");
2525
+ let pathValue = obj;
2526
+ for (const pathPart of pathParts) {
2527
+ // Is the path part numeric i.e. an array index.
2528
+ const arrayMatch = /^(\d+)$/.exec(pathPart);
2529
+ if (arrayMatch) {
2530
+ const arrayIndex = Number.parseInt(arrayMatch[1], 10);
2531
+ if (Is.arrayValue(pathValue) && arrayIndex < pathValue.length) {
2532
+ // There is no prop name so this is a direct array index on the current object
2533
+ pathValue = pathValue[arrayIndex];
2513
2534
  }
2514
2535
  else {
2536
+ // Array index for non array object so return
2515
2537
  return undefined;
2516
2538
  }
2517
2539
  }
2518
- return value;
2540
+ else if (Is.object(pathValue)) {
2541
+ // No array part in path so assume object sub property
2542
+ pathValue = pathValue[pathPart];
2543
+ }
2544
+ else {
2545
+ return undefined;
2546
+ }
2519
2547
  }
2520
- return Is.object(obj) ? obj[property] : undefined;
2548
+ return pathValue;
2521
2549
  }
2522
2550
  /**
2523
2551
  * Set the property of an unknown object.
2524
2552
  * @param obj The object to set the property from.
2525
2553
  * @param property The property to set.
2526
2554
  * @param value The value to set.
2555
+ * @throws GeneralError if the property target is not an object.
2527
2556
  */
2528
2557
  static propertySet(obj, property, value) {
2529
- if (Is.object(obj)) {
2530
- obj[property] = value;
2558
+ const pathParts = property.split(".");
2559
+ let pathValue = obj;
2560
+ let parentObj;
2561
+ for (let i = 0; i < pathParts.length; i++) {
2562
+ const pathPart = pathParts[i];
2563
+ // Is the path part numeric i.e. an array index.
2564
+ const arrayMatch = /^(\d+)$/.exec(pathPart);
2565
+ const arrayIndex = arrayMatch ? Number.parseInt(arrayMatch[1], 10) : -1;
2566
+ if (i === pathParts.length - 1) {
2567
+ // Last part of path so set the value
2568
+ if (arrayIndex >= 0) {
2569
+ if (Is.array(pathValue)) {
2570
+ pathValue[arrayIndex] = value;
2571
+ }
2572
+ else {
2573
+ throw new GeneralError(ObjectHelper._CLASS_NAME, "cannotSetArrayIndex", {
2574
+ property,
2575
+ index: arrayIndex
2576
+ });
2577
+ }
2578
+ }
2579
+ else if (Is.object(pathValue)) {
2580
+ pathValue[pathPart] = value;
2581
+ }
2582
+ else {
2583
+ throw new GeneralError(ObjectHelper._CLASS_NAME, "cannotSetProperty", { property });
2584
+ }
2585
+ }
2586
+ else {
2587
+ parentObj = pathValue;
2588
+ if (Is.object(pathValue)) {
2589
+ pathValue = pathValue[pathPart];
2590
+ }
2591
+ else if (Is.array(pathValue)) {
2592
+ pathValue = pathValue[arrayIndex];
2593
+ }
2594
+ if (Is.empty(pathValue)) {
2595
+ const nextArrayMatch = /^(\d+)$/.exec(pathParts[i + 1]);
2596
+ const nextArrayIndex = nextArrayMatch ? Number.parseInt(nextArrayMatch[1], 10) : -1;
2597
+ if (nextArrayIndex >= 0) {
2598
+ pathValue = [];
2599
+ }
2600
+ else {
2601
+ pathValue = {};
2602
+ }
2603
+ if (Is.object(parentObj)) {
2604
+ parentObj[pathPart] = pathValue;
2605
+ }
2606
+ else if (Is.array(parentObj)) {
2607
+ parentObj[arrayIndex] = pathValue;
2608
+ }
2609
+ }
2610
+ }
2531
2611
  }
2532
2612
  }
2533
2613
  /**
@@ -111,7 +111,12 @@ class Is {
111
111
  }
112
112
  try {
113
113
  const json = JSON.parse(value);
114
- return typeof json === "object";
114
+ return (Is.object(json) ||
115
+ Is.array(json) ||
116
+ Is.string(json) ||
117
+ Is.number(json) ||
118
+ Is.boolean(json) ||
119
+ Is.null(json));
115
120
  }
116
121
  catch {
117
122
  return false;
@@ -1532,6 +1537,18 @@ class Guards {
1532
1537
  throw new GuardError(source, "guard.stringEmpty", property, value);
1533
1538
  }
1534
1539
  }
1540
+ /**
1541
+ * Is the property a JSON value.
1542
+ * @param source The source of the error.
1543
+ * @param property The name of the property.
1544
+ * @param value The value to test.
1545
+ * @throws GuardError If the value does not match the assertion.
1546
+ */
1547
+ static json(source, property, value) {
1548
+ if (!Is.json(value)) {
1549
+ throw new GuardError(source, "guard.stringJson", property, value);
1550
+ }
1551
+ }
1535
1552
  /**
1536
1553
  * Is the property a base64 string.
1537
1554
  * @param source The source of the error.
@@ -2502,30 +2519,93 @@ class ObjectHelper {
2502
2519
  * @returns The property.
2503
2520
  */
2504
2521
  static propertyGet(obj, property) {
2505
- if (property.includes(".")) {
2506
- const parts = property.split(".");
2507
- let value = obj;
2508
- for (const part of parts) {
2509
- if (Is.object(value)) {
2510
- value = value[part];
2522
+ const pathParts = property.split(".");
2523
+ let pathValue = obj;
2524
+ for (const pathPart of pathParts) {
2525
+ // Is the path part numeric i.e. an array index.
2526
+ const arrayMatch = /^(\d+)$/.exec(pathPart);
2527
+ if (arrayMatch) {
2528
+ const arrayIndex = Number.parseInt(arrayMatch[1], 10);
2529
+ if (Is.arrayValue(pathValue) && arrayIndex < pathValue.length) {
2530
+ // There is no prop name so this is a direct array index on the current object
2531
+ pathValue = pathValue[arrayIndex];
2511
2532
  }
2512
2533
  else {
2534
+ // Array index for non array object so return
2513
2535
  return undefined;
2514
2536
  }
2515
2537
  }
2516
- return value;
2538
+ else if (Is.object(pathValue)) {
2539
+ // No array part in path so assume object sub property
2540
+ pathValue = pathValue[pathPart];
2541
+ }
2542
+ else {
2543
+ return undefined;
2544
+ }
2517
2545
  }
2518
- return Is.object(obj) ? obj[property] : undefined;
2546
+ return pathValue;
2519
2547
  }
2520
2548
  /**
2521
2549
  * Set the property of an unknown object.
2522
2550
  * @param obj The object to set the property from.
2523
2551
  * @param property The property to set.
2524
2552
  * @param value The value to set.
2553
+ * @throws GeneralError if the property target is not an object.
2525
2554
  */
2526
2555
  static propertySet(obj, property, value) {
2527
- if (Is.object(obj)) {
2528
- obj[property] = value;
2556
+ const pathParts = property.split(".");
2557
+ let pathValue = obj;
2558
+ let parentObj;
2559
+ for (let i = 0; i < pathParts.length; i++) {
2560
+ const pathPart = pathParts[i];
2561
+ // Is the path part numeric i.e. an array index.
2562
+ const arrayMatch = /^(\d+)$/.exec(pathPart);
2563
+ const arrayIndex = arrayMatch ? Number.parseInt(arrayMatch[1], 10) : -1;
2564
+ if (i === pathParts.length - 1) {
2565
+ // Last part of path so set the value
2566
+ if (arrayIndex >= 0) {
2567
+ if (Is.array(pathValue)) {
2568
+ pathValue[arrayIndex] = value;
2569
+ }
2570
+ else {
2571
+ throw new GeneralError(ObjectHelper._CLASS_NAME, "cannotSetArrayIndex", {
2572
+ property,
2573
+ index: arrayIndex
2574
+ });
2575
+ }
2576
+ }
2577
+ else if (Is.object(pathValue)) {
2578
+ pathValue[pathPart] = value;
2579
+ }
2580
+ else {
2581
+ throw new GeneralError(ObjectHelper._CLASS_NAME, "cannotSetProperty", { property });
2582
+ }
2583
+ }
2584
+ else {
2585
+ parentObj = pathValue;
2586
+ if (Is.object(pathValue)) {
2587
+ pathValue = pathValue[pathPart];
2588
+ }
2589
+ else if (Is.array(pathValue)) {
2590
+ pathValue = pathValue[arrayIndex];
2591
+ }
2592
+ if (Is.empty(pathValue)) {
2593
+ const nextArrayMatch = /^(\d+)$/.exec(pathParts[i + 1]);
2594
+ const nextArrayIndex = nextArrayMatch ? Number.parseInt(nextArrayMatch[1], 10) : -1;
2595
+ if (nextArrayIndex >= 0) {
2596
+ pathValue = [];
2597
+ }
2598
+ else {
2599
+ pathValue = {};
2600
+ }
2601
+ if (Is.object(parentObj)) {
2602
+ parentObj[pathPart] = pathValue;
2603
+ }
2604
+ else if (Is.array(parentObj)) {
2605
+ parentObj[arrayIndex] = pathValue;
2606
+ }
2607
+ }
2608
+ }
2529
2609
  }
2530
2610
  }
2531
2611
  /**
@@ -49,6 +49,7 @@ export declare class ObjectHelper {
49
49
  * @param obj The object to set the property from.
50
50
  * @param property The property to set.
51
51
  * @param value The value to set.
52
+ * @throws GeneralError if the property target is not an object.
52
53
  */
53
54
  static propertySet(obj: unknown, property: string, value: unknown): void;
54
55
  /**
@@ -26,6 +26,14 @@ export declare class Guards {
26
26
  * @throws GuardError If the value does not match the assertion.
27
27
  */
28
28
  static stringValue(source: string, property: string, value: unknown): asserts value is string;
29
+ /**
30
+ * Is the property a JSON value.
31
+ * @param source The source of the error.
32
+ * @param property The name of the property.
33
+ * @param value The value to test.
34
+ * @throws GuardError If the value does not match the assertion.
35
+ */
36
+ static json(source: string, property: string, value: unknown): asserts value is string;
29
37
  /**
30
38
  * Is the property a base64 string.
31
39
  * @param source The source of the error.
package/docs/changelog.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # @twin.org/core - Changelog
2
2
 
3
- ## 0.0.1-next.24
3
+ ## 0.0.1-next.26
4
4
 
5
5
  - Initial Release
@@ -122,6 +122,42 @@ GuardError If the value does not match the assertion.
122
122
 
123
123
  ***
124
124
 
125
+ ### json()
126
+
127
+ > `static` **json**(`source`, `property`, `value`): `asserts value is string`
128
+
129
+ Is the property a JSON value.
130
+
131
+ #### Parameters
132
+
133
+ ##### source
134
+
135
+ `string`
136
+
137
+ The source of the error.
138
+
139
+ ##### property
140
+
141
+ `string`
142
+
143
+ The name of the property.
144
+
145
+ ##### value
146
+
147
+ `unknown`
148
+
149
+ The value to test.
150
+
151
+ #### Returns
152
+
153
+ `asserts value is string`
154
+
155
+ #### Throws
156
+
157
+ GuardError If the value does not match the assertion.
158
+
159
+ ***
160
+
125
161
  ### stringBase64()
126
162
 
127
163
  > `static` **stringBase64**(`source`, `property`, `value`): `asserts value is string`
@@ -236,6 +236,10 @@ The value to set.
236
236
 
237
237
  `void`
238
238
 
239
+ #### Throws
240
+
241
+ GeneralError if the property target is not an object.
242
+
239
243
  ***
240
244
 
241
245
  ### propertyDelete()
package/locales/en.json CHANGED
@@ -51,6 +51,7 @@
51
51
  "stringBase58": "Property \"{property}\" must be a base58 encoded string, it is \"{value}\"",
52
52
  "stringHex": "Property \"{property}\" must be a hex string, it is \"{value}\"",
53
53
  "stringHexLength": "Property \"{property}\" must be a hex string of length \"{options}\", it is \"{value}\"",
54
+ "stringJson": "Property \"{property}\" must be a JSON string",
54
55
  "number": "Property \"{property}\" must be a number, it is \"{value}\"",
55
56
  "integer": "Property \"{property}\" must be an integer, it is \"{value}\"",
56
57
  "bigint": "Property \"{property}\" must be a bigint, it is \"{value}\"",
@@ -71,7 +72,9 @@
71
72
  "email": "Property \"{property}\" must be string in e-mail format, it is \"{value}\""
72
73
  },
73
74
  "objectHelper": {
74
- "failedBytesToJSON": "Failed converting bytes to JSON"
75
+ "failedBytesToJSON": "Failed converting bytes to JSON",
76
+ "cannotSetArrayIndex": "Cannot set property \"{property}\" using index \"{index}\" as it is not an array",
77
+ "cannotSetProperty": "Cannot set property \"{property}\" when the target is not an object"
75
78
  },
76
79
  "common": {
77
80
  "notImplementedMethod": "The method \"{method}\" has not been implemented",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twin.org/core",
3
- "version": "0.0.1-next.24",
3
+ "version": "0.0.1-next.26",
4
4
  "description": "Helper methods/classes for data type checking/validation/guarding/error handling",
5
5
  "repository": {
6
6
  "type": "git",
@@ -15,7 +15,7 @@
15
15
  },
16
16
  "dependencies": {
17
17
  "@twin.org/nameof": "next",
18
- "intl-messageformat": "10.7.12",
18
+ "intl-messageformat": "10.7.14",
19
19
  "rfc6902": "5.1.2"
20
20
  },
21
21
  "main": "./dist/cjs/index.cjs",