@valkyriestudios/utils 12.21.0 → 12.22.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/README.md CHANGED
@@ -787,7 +787,7 @@ isFormData(new FormData()); // TRUE
787
787
  isFormData({hi: 'there'}); // FALSE
788
788
  ```
789
789
 
790
- ### formdata/toObject(val:FormData)
790
+ ### formdata/toObject(val:FormData, {raw?:string[]} = {})
791
791
  Converts an instance of FormData to an object
792
792
  ```typescript
793
793
  import toObject from '@valkyriestudios/utils/formdata/toObject';
@@ -800,6 +800,46 @@ form.append('emptyField', '');
800
800
  toObject(form); // {name: 'Alice', hobbies: ['reading', 'writing'], emptyField: ''}
801
801
  ```
802
802
 
803
+ Automatically converts strings to numbers and booleans, and nests objects/arrays based on key structures:
804
+ ```typescript
805
+ const form = new FormData();
806
+ form.append('user[0].name', 'Alice');
807
+ form.append('user[1].age', '25');
808
+ form.append('enabled', 'false');
809
+ form.append('config.isGood', 'true');
810
+ form.append('config.amount', ' 50 ');
811
+
812
+ toObject(form); /* {
813
+ user: [
814
+ {name: 'Alice'},
815
+ {age: 25},
816
+ ],
817
+ enabled: false,
818
+ config: {
819
+ isGood: true,
820
+ amount: 50,
821
+ },
822
+ } */
823
+ ```
824
+
825
+ Allows blacklisting keys that should not be normalized into numbers/booleans but should remain as they are:
826
+ ```typescript
827
+ const form = new FormData();
828
+ form.append('pincode', '0123');
829
+ form.append('enabled', 'false');
830
+ form.append('config.isGood', 'true');
831
+ form.append('config.amount', ' 50 ');
832
+
833
+ toObject(form, {raw: ['pincode']}); /* {
834
+ pincode: '0123',
835
+ enabled: false,
836
+ config: {
837
+ isGood: true,
838
+ amount: 50,
839
+ },
840
+ } */
841
+ ```
842
+
803
843
  ### hash/guid()
804
844
  Generate a unique identifier (guid) according to RFC4122
805
845
  ```typescript
@@ -1,3 +1,9 @@
1
+ type toObjectConfig = {
2
+ /**
3
+ * Pass array of keys that should not be normalized into number/bool when seen
4
+ */
5
+ raw?: string[];
6
+ };
1
7
  /**
2
8
  * Converts a FormData instance to a json object
3
9
  * Eg:
@@ -11,6 +17,7 @@
11
17
  * {name: 'Alice', hobbies: ['reading', 'writing'], emptyField: ''}
12
18
  *
13
19
  * @param {FormData} val - FormData instance to convert to an object
20
+ * @param {}
14
21
  */
15
- declare function toObject<T extends Record<string, unknown>>(form: FormData): T;
22
+ declare function toObject<T extends Record<string, unknown>>(form: FormData, config?: toObjectConfig): T;
16
23
  export { toObject, toObject as default };
@@ -2,22 +2,57 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.toObject = toObject;
4
4
  exports.default = toObject;
5
- function toObject(form) {
6
- if (!(form instanceof FormData))
7
- throw new Error('formdata/toObject: Value is not an instance of FormData');
8
- const acc = {};
9
- form.forEach((value, key) => {
10
- if (acc[key] !== undefined) {
11
- if (Array.isArray(acc[key])) {
12
- acc[key].push(value);
5
+ const RGX_CLOSE = /\]/g;
6
+ function assignValue(acc, rawkey, value) {
7
+ let cursor = acc;
8
+ const keys = rawkey.replace(RGX_CLOSE, '').split(/\[|\./);
9
+ for (let i = 0; i < keys.length; i++) {
10
+ const key = keys[i];
11
+ if (i === keys.length - 1) {
12
+ if (cursor[key] !== undefined) {
13
+ if (Array.isArray(cursor[key])) {
14
+ cursor[key].push(value);
15
+ }
16
+ else {
17
+ cursor[key] = [cursor[key], value];
18
+ }
13
19
  }
14
20
  else {
15
- acc[key] = [acc[key], value];
21
+ cursor[key] = value;
16
22
  }
23
+ return;
24
+ }
25
+ if (Array.isArray(cursor)) {
26
+ const index = Number(key);
27
+ if (!cursor[index])
28
+ cursor[index] = isNaN(Number(keys[i + 1])) ? {} : [];
29
+ cursor = cursor[index];
17
30
  }
18
31
  else {
19
- acc[key] = value;
32
+ if (!cursor[key])
33
+ cursor[key] = isNaN(Number(keys[i + 1])) ? {} : [];
34
+ cursor = cursor[key];
35
+ }
36
+ }
37
+ }
38
+ function toObject(form, config) {
39
+ if (!(form instanceof FormData))
40
+ throw new Error('formdata/toObject: Value is not an instance of FormData');
41
+ const set = new Set(Array.isArray(config?.raw) ? config.raw : []);
42
+ const acc = {};
43
+ form.forEach((value, key) => {
44
+ let normalizedValue = value;
45
+ if (typeof value === 'string' && !set.has(key)) {
46
+ const lower = value.toLowerCase();
47
+ normalizedValue = (lower === 'true'
48
+ ? true
49
+ : lower === 'false'
50
+ ? false
51
+ : !isNaN(Number(value)) && value.trim() !== ''
52
+ ? Number(value)
53
+ : value);
20
54
  }
55
+ assignValue(acc, key, normalizedValue);
21
56
  });
22
57
  return acc;
23
58
  }
package/index.d.ts CHANGED
@@ -226,7 +226,10 @@ declare module "formdata/is" {
226
226
  export { isFormData, isFormData as default };
227
227
  }
228
228
  declare module "formdata/toObject" {
229
- function toObject<T extends Record<string, unknown>>(form: FormData): T;
229
+ type toObjectConfig = {
230
+ raw?: string[];
231
+ };
232
+ function toObject<T extends Record<string, unknown>>(form: FormData, config?: toObjectConfig): T;
230
233
  export { toObject, toObject as default };
231
234
  }
232
235
  declare module "formdata/index" {
package/package.json CHANGED
@@ -1 +1 @@
1
- { "name": "@valkyriestudios/utils", "version": "12.21.0", "description": "A collection of single-function utilities for common tasks", "author": { "name": "Peter Vermeulen", "url": "https://www.linkedin.com/in/petervermeulen1/" }, "keywords": [ "utility", "library", "javascript", "js", "node", "bun" ], "license": "MIT", "repository": { "type": "git", "url": "git+https://github.com/ValkyrieStudios/utils.git" }, "bugs": { "url": "https://github.com/ValkyrieStudios/utils/issues" }, "homepage": "https://github.com/ValkyrieStudios/utils#readme", "types": "index.d.ts" }
1
+ { "name": "@valkyriestudios/utils", "version": "12.22.0", "description": "A collection of single-function utilities for common tasks", "author": { "name": "Peter Vermeulen", "url": "https://www.linkedin.com/in/petervermeulen1/" }, "keywords": [ "utility", "library", "javascript", "js", "node", "bun" ], "license": "MIT", "repository": { "type": "git", "url": "git+https://github.com/ValkyrieStudios/utils.git" }, "bugs": { "url": "https://github.com/ValkyrieStudios/utils/issues" }, "homepage": "https://github.com/ValkyrieStudios/utils#readme", "types": "index.d.ts" }