@glitchproof/form-field-generator 1.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.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +491 -0
  3. package/dist/__test__/convert.test.d.ts +2 -0
  4. package/dist/__test__/convert.test.d.ts.map +1 -0
  5. package/dist/__test__/convert.test.js +429 -0
  6. package/dist/__test__/convert.test.js.map +1 -0
  7. package/dist/__test__/create-index-formatter.test.d.ts +2 -0
  8. package/dist/__test__/create-index-formatter.test.d.ts.map +1 -0
  9. package/dist/__test__/create-index-formatter.test.js +17 -0
  10. package/dist/__test__/create-index-formatter.test.js.map +1 -0
  11. package/dist/__test__/is-list.test.d.ts +2 -0
  12. package/dist/__test__/is-list.test.d.ts.map +1 -0
  13. package/dist/__test__/is-list.test.js +13 -0
  14. package/dist/__test__/is-list.test.js.map +1 -0
  15. package/dist/__test__/to-snake-case.test.d.ts +2 -0
  16. package/dist/__test__/to-snake-case.test.d.ts.map +1 -0
  17. package/dist/__test__/to-snake-case.test.js +14 -0
  18. package/dist/__test__/to-snake-case.test.js.map +1 -0
  19. package/dist/core/convert.d.ts +3 -0
  20. package/dist/core/convert.d.ts.map +1 -0
  21. package/dist/core/convert.js +55 -0
  22. package/dist/core/convert.js.map +1 -0
  23. package/dist/index.d.ts +4 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +4 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/type.d.ts +61 -0
  28. package/dist/type.d.ts.map +1 -0
  29. package/dist/type.js +2 -0
  30. package/dist/type.js.map +1 -0
  31. package/dist/utils/create-index-formatter.d.ts +2 -0
  32. package/dist/utils/create-index-formatter.d.ts.map +1 -0
  33. package/dist/utils/create-index-formatter.js +15 -0
  34. package/dist/utils/create-index-formatter.js.map +1 -0
  35. package/dist/utils/is-list.d.ts +2 -0
  36. package/dist/utils/is-list.d.ts.map +1 -0
  37. package/dist/utils/is-list.js +2 -0
  38. package/dist/utils/is-list.js.map +1 -0
  39. package/dist/utils/to-snake-case.d.ts +2 -0
  40. package/dist/utils/to-snake-case.d.ts.map +1 -0
  41. package/dist/utils/to-snake-case.js +10 -0
  42. package/dist/utils/to-snake-case.js.map +1 -0
  43. package/package.json +46 -0
package/dist/type.d.ts ADDED
@@ -0,0 +1,61 @@
1
+ export type Context = {
2
+ path: string;
3
+ };
4
+ type FieldsGroup<Field extends Object.DICT_NESTED_VALUES,
5
+ /**
6
+ * The path of the deeply nested fields.
7
+ * Example: first layer name => name,
8
+ * second layer {city: { name: "nameOfCity" }} => city.nameOfCity ,
9
+ * third layer is a array version {country: { name: "nameOfCountry", cities: [{ name: "nameOfCity" }] }} => country.nameOfCountry.cities.${number}.nameOfCity as a function with deeply listed counted arguments
10
+ */
11
+ Path extends string,
12
+ /**
13
+ * The name of the key of the field.
14
+ * Example: 'name' => 'NAME'
15
+ * Example: '{city: { name: "nameOfCity" }} => 'city'
16
+ * Example: '{cities: [{ name: "nameOfCity" }] }} => 'cities'
17
+ * Example: '{cities: [{ name: "nameOfCity", someProperty: { name: "nameOfProperty" } }] }} => nameOfProperty
18
+ */
19
+ FieldName extends string> = {
20
+ /**
21
+ * The key of the object field to use it's parent object name.
22
+ * Example: '{city: { KEY: "city", name: "nameOfCity" }}
23
+ */
24
+ readonly KEY: FieldName;
25
+ /**
26
+ * The path of the deeply nested fields.
27
+ * If Path is listed it generate function for naming
28
+ * Example { country: { place: { name: "nameOfPlace" } } } => { $COUNTRY: { PATH: () => `country`, NAME: 'nameOfCountry', $PLACE: { PATH: 'country.place', NAME: 'nameOfPlace' } } }
29
+ * Example {country: { name: "nameOfCountry", city: { name: "nameOfCity" } }} to { $COUNTRY: { PATH: () => `country.${number}`, NAME: 'nameOfCountry', $CITIES: { PATH: () => `path.to.country.cities`, NAME: 'nameOfCity', $CITY: { PATH: () => `path.to.country.cities.${number}`, NAME: 'nameOfCity' } } } }
30
+ */
31
+ readonly PATH: Utils.PathGenerator<Path>;
32
+ } & {
33
+ [KEY in keyof Field as Field[KEY] extends string ? Utils.TO_NAME<KEY> : never]: Field[KEY];
34
+ } & {
35
+ [KEY in keyof Utils.SubArrayElement<Field> as Utils.ObjectFieldNameGenerator<KEY & string,
36
+ /**
37
+ * The type of the sub array element for get inside object
38
+ */
39
+ Utils.SubArrayElement<Field>> /**
40
+ * If the sub array element is an object, generate the fields for the object.
41
+ * Otherwise generate the fields path for the array.
42
+ */]: Utils.SubArrayElement<Field>[KEY] extends Object.DICT_NESTED_VALUES ? FieldsGroup<Utils.SubArrayElement<Field>[KEY], `${Path}.${number}.${KEY & string}`, KEY & string> : Utils.ListFieldAccessor<`${Path}.${number}.${KEY & string}`>;
43
+ } & {
44
+ [KEY in keyof Field as Field[KEY] extends Object.DICT_NESTED_VALUES ? Utils.ExceptNumber<KEY, Utils.TO_OBJECT_FIELD_NAME<KEY>> : never /**
45
+ * If the key is an object, generate the fields for the object.
46
+ */]: Field[KEY] extends Object.DICT_OBJECT_VALUE ? FieldsGroup<Field[KEY], `${Path}.${KEY & string}`, KEY & string> : Field[KEY] extends Object.DICT_ARRAY_VALUE ? FieldsGroup<Field[KEY], `${Path}.${KEY & string}`, KEY & string> : never;
47
+ } & {
48
+ [KEY in keyof Field as Field[KEY] extends string ? Utils.TO_FIELD_NAME<KEY> : never /**
49
+ * If the path is listed before, generate the fields for the array.
50
+ * else generate the fields path for the object.
51
+ */]: Utils.IsListedBefore<Path> extends true ? Utils.ListFieldAccessor<`${Path}.${Field[KEY] & string}`> : `${Path}.${Field[KEY] & string}`;
52
+ };
53
+ export type GenerateFields<Fields extends Object.DICT> = {
54
+ [KEY in keyof Fields as Fields[KEY] extends string ? Utils.TO_FIELD_NAME<KEY> : never]: Fields[KEY];
55
+ } & {
56
+ [KEY in keyof Fields as Fields[KEY] extends string ? Utils.TO_NAME<KEY> : never]: Fields[KEY];
57
+ } & {
58
+ [KEY in keyof Fields as Fields[KEY] extends Object.DICT_NESTED_VALUES ? Utils.TO_OBJECT_FIELD_NAME<KEY> : never]: Fields[KEY] extends Object.DICT_NESTED_VALUES ? FieldsGroup<Fields[KEY], KEY & string, KEY & string> : never;
59
+ };
60
+ export {};
61
+ //# sourceMappingURL=type.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../src/type.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GAAG;IACpB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,KAAK,WAAW,CACd,KAAK,SAAS,MAAM,CAAC,kBAAkB;AACvC;;;;;GAKG;AACH,IAAI,SAAS,MAAM;AACnB;;;;;;GAMG;AACH,SAAS,SAAS,MAAM,IACtB;IACF;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;CAC1C,GAAG;KAMD,GAAG,IAAI,MAAM,KAAK,IAAI,KAAK,CAAC,GAAG,CAAC,SAAS,MAAM,GAC5C,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,GAClB,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC;CACvB,GAAG;KAMD,GAAG,IAAI,MAAM,KAAK,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,wBAAwB,CAC1E,GAAG,GAAG,MAAM;IACZ;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,KAAK,CAAC,CAC7B,CAAC;;;OAGC,GAAG,KAAK,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,kBAAkB,GACrE,WAAW,CACT,KAAK,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EACjC,GAAG,IAAI,IAAI,MAAM,IAAI,GAAG,GAAG,MAAM,EAAE,EACnC,GAAG,GAAG,MAAM,CACb,GACD,KAAK,CAAC,iBAAiB,CAAC,GAAG,IAAI,IAAI,MAAM,IAAI,GAAG,GAAG,MAAM,EAAE,CAAC;CACjE,GAAG;KAKD,GAAG,IAAI,MAAM,KAAK,IAAI,KAAK,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,kBAAkB,GAI/D,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,GACxD,KAAK,CAAC;;KAEP,GAAG,KAAK,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,iBAAiB,GAI7C,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,IAAI,GAAG,GAAG,MAAM,EAAE,EAAE,GAAG,GAAG,MAAM,CAAC,GAIhE,KAAK,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,gBAAgB,GACxC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,IAAI,GAAG,GAAG,MAAM,EAAE,EAAE,GAAG,GAAG,MAAM,CAAC,GAChE,KAAK;CACZ,GAAG;KAOD,GAAG,IAAI,MAAM,KAAK,IAAI,KAAK,CAAC,GAAG,CAAC,SAAS,MAAM,GAC5C,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,GACxB,KAAK,CAAC;;;KAGP,GAAG,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,IAAI,GACzC,KAAK,CAAC,iBAAiB,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,MAAM,EAAE,CAAC,GACzD,GAAG,IAAI,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,MAAM,EAAE;CACrC,CAAC;AAEF,MAAM,MAAM,cAAc,CAAC,MAAM,SAAS,MAAM,CAAC,IAAI,IAAI;KAItD,GAAG,IAAI,MAAM,MAAM,IAAI,MAAM,CAAC,GAAG,CAAC,SAAS,MAAM,GAC9C,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,GACxB,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC;CACxB,GAAG;KAID,GAAG,IAAI,MAAM,MAAM,IAAI,MAAM,CAAC,GAAG,CAAC,SAAS,MAAM,GAC9C,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,GAClB,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC;CACxB,GAAG;KAID,GAAG,IAAI,MAAM,MAAM,IAAI,MAAM,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,kBAAkB,GACjE,KAAK,CAAC,oBAAoB,CAAC,GAAG,CAAC,GAC/B,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,kBAAkB,GACrD,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,MAAM,EAAE,GAAG,GAAG,MAAM,CAAC,GACpD,KAAK;CACV,CAAC"}
package/dist/type.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=type.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type.js","sourceRoot":"","sources":["../src/type.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export declare const createIndexFormatter: (template: string) => ((...args: number[]) => string);
2
+ //# sourceMappingURL=create-index-formatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-index-formatter.d.ts","sourceRoot":"","sources":["../../src/utils/create-index-formatter.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,GAC/B,UAAU,MAAM,KACf,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE,KAAK,MAAM,CAkBhC,CAAC"}
@@ -0,0 +1,15 @@
1
+ export const createIndexFormatter = (template) => {
2
+ const requiredCount = (template.match(/#/g) || []).length;
3
+ return (...args) => {
4
+ if (args.length !== requiredCount) {
5
+ throw new Error(`Formatter Mismatch: Template requires ${requiredCount} arguments, but received ${args.length}.`);
6
+ }
7
+ let argIndex = 0;
8
+ return template.replace(/#/g, () => {
9
+ const replacement = String(args[argIndex]);
10
+ argIndex++;
11
+ return replacement;
12
+ });
13
+ };
14
+ };
15
+ //# sourceMappingURL=create-index-formatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-index-formatter.js","sourceRoot":"","sources":["../../src/utils/create-index-formatter.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,QAAgB,EACiB,EAAE;IACnC,MAAM,aAAa,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;IAE1D,OAAO,CAAC,GAAG,IAAc,EAAU,EAAE;QACnC,IAAI,IAAI,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CACb,yCAAyC,aAAa,4BAA4B,IAAI,CAAC,MAAM,GAAG,CACjG,CAAC;QACJ,CAAC;QAED,IAAI,QAAQ,GAAG,CAAC,CAAC;QAEjB,OAAO,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE;YACjC,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC3C,QAAQ,EAAE,CAAC;YACX,OAAO,WAAW,CAAC;QACrB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const isListed: (path: string) => boolean;
2
+ //# sourceMappingURL=is-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-list.d.ts","sourceRoot":"","sources":["../../src/utils/is-list.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ,GAAI,MAAM,MAAM,YAAyB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export const isListed = (path) => path.includes('.#.');
2
+ //# sourceMappingURL=is-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-list.js","sourceRoot":"","sources":["../../src/utils/is-list.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const toSnakeCase: (str: string) => string;
2
+ //# sourceMappingURL=to-snake-case.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"to-snake-case.d.ts","sourceRoot":"","sources":["../../src/utils/to-snake-case.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,GAAI,KAAK,MAAM,WAStC,CAAC"}
@@ -0,0 +1,10 @@
1
+ export const toSnakeCase = (str) => {
2
+ if (!str || typeof str !== 'string') {
3
+ return '';
4
+ }
5
+ return str
6
+ .replace(/([a-z])([A-Z])/g, '$1_$2')
7
+ .replace(/([A-Z])([A-Z][a-z])/g, '$1_$2')
8
+ .toLowerCase();
9
+ };
10
+ //# sourceMappingURL=to-snake-case.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"to-snake-case.js","sourceRoot":"","sources":["../../src/utils/to-snake-case.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,GAAW,EAAE,EAAE;IACzC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QACpC,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,GAAG;SACP,OAAO,CAAC,iBAAiB,EAAE,OAAO,CAAC;SACnC,OAAO,CAAC,sBAAsB,EAAE,OAAO,CAAC;SACxC,WAAW,EAAE,CAAC;AACnB,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@glitchproof/form-field-generator",
3
+ "version": "1.0.0",
4
+ "description": "> Type-safe field path generation for nested objects and arrays",
5
+ "scripts": {
6
+ "build": "tsc",
7
+ "ci": "bun run build && bun format:check && bun test",
8
+ "format": "prettier --write .",
9
+ "format:src": "prettier --write src/**/*.ts",
10
+ "format:check": "prettier --write --check .",
11
+ "format:check:src": "prettier --check src/**/*.ts",
12
+ "test": "vitest run",
13
+ "local:release": "changeset version && changeset publish",
14
+ "prepublishOnly": "bun ci",
15
+ "changeset": "changeset",
16
+ "version-packages": "changeset version",
17
+ "release": "changeset publish"
18
+ },
19
+ "keywords": [
20
+ "react hook form",
21
+ "field-name-generator",
22
+ "fields generator"
23
+ ],
24
+ "author": "GlitchTruth",
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "git+https://github.com/RashadNazarzade/generate-fields.git"
28
+ },
29
+ "files": [
30
+ "dist"
31
+ ],
32
+ "type": "module",
33
+ "main": "dist/index.js",
34
+ "license": "MIT",
35
+ "devDependencies": {
36
+ "@changesets/cli": "^2.29.7",
37
+ "prettier": "^3.6.2",
38
+ "typescript": "^5.9.3",
39
+ "vitest": "^4.0.10"
40
+ },
41
+ "types": "./dist/index.d.ts",
42
+ "bugs": {
43
+ "url": "https://github.com/RashadNazarzade/generate-fields/issues"
44
+ },
45
+ "homepage": "https://github.com/RashadNazarzade/generate-fields#readme"
46
+ }