namefully 1.3.0 → 2.0.1

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 (51) hide show
  1. package/dist/{lib → cjs}/builder.js +15 -13
  2. package/dist/cjs/config.js +109 -0
  3. package/dist/{lib → cjs}/constants.js +1 -1
  4. package/dist/{lib → cjs}/error.js +9 -6
  5. package/dist/cjs/fullname.js +101 -0
  6. package/dist/{lib → cjs}/index.js +18 -15
  7. package/dist/cjs/name.js +214 -0
  8. package/dist/cjs/namefully.js +383 -0
  9. package/dist/cjs/package.json +1 -0
  10. package/dist/cjs/parser.js +135 -0
  11. package/dist/{lib → cjs}/types.js +40 -36
  12. package/dist/{lib → cjs}/utils.js +32 -37
  13. package/dist/cjs/validator.js +251 -0
  14. package/dist/{types → esm}/builder.d.ts +11 -9
  15. package/dist/esm/builder.js +78 -0
  16. package/dist/{types → esm}/config.d.ts +7 -2
  17. package/dist/esm/config.js +105 -0
  18. package/dist/{types → esm}/constants.d.ts +1 -1
  19. package/dist/esm/constants.js +27 -0
  20. package/dist/{types → esm}/error.d.ts +5 -10
  21. package/dist/esm/error.js +87 -0
  22. package/dist/{types/full-name.d.ts → esm/fullname.d.ts} +12 -14
  23. package/dist/esm/fullname.js +97 -0
  24. package/dist/esm/index.d.ts +25 -0
  25. package/dist/esm/index.js +12 -0
  26. package/dist/{types → esm}/name.d.ts +11 -18
  27. package/dist/esm/name.js +207 -0
  28. package/dist/{types → esm}/namefully.d.ts +68 -70
  29. package/dist/esm/namefully.js +379 -0
  30. package/dist/esm/package.json +1 -0
  31. package/dist/{types → esm}/parser.d.ts +4 -4
  32. package/dist/esm/parser.js +127 -0
  33. package/dist/{types → esm}/types.d.ts +16 -48
  34. package/dist/esm/types.js +106 -0
  35. package/dist/{types → esm}/utils.d.ts +4 -6
  36. package/dist/esm/utils.js +91 -0
  37. package/dist/{types → esm}/validator.d.ts +3 -3
  38. package/dist/esm/validator.js +244 -0
  39. package/dist/namefully.js +1556 -0
  40. package/dist/namefully.min.js +1 -0
  41. package/package.json +45 -28
  42. package/readme.md +15 -14
  43. package/dist/lib/config.js +0 -112
  44. package/dist/lib/full-name.js +0 -115
  45. package/dist/lib/name.js +0 -230
  46. package/dist/lib/namefully.js +0 -417
  47. package/dist/lib/parser.js +0 -144
  48. package/dist/lib/validator.js +0 -285
  49. package/dist/types/index.d.ts +0 -25
  50. package/dist/umd/namefully.js +0 -1931
  51. package/dist/umd/namefully.min.js +0 -1
@@ -0,0 +1,127 @@
1
+ import { Config } from './config.js';
2
+ import { NameIndex } from './utils.js';
3
+ import { InputError } from './error.js';
4
+ import { FullName } from './fullname.js';
5
+ import { Namon, Separator } from './types.js';
6
+ import { FirstName, LastName, Name } from './name.js';
7
+ import { ArrayStringValidator, ArrayNameValidator, NamaValidator } from './validator.js';
8
+ export class Parser {
9
+ raw;
10
+ constructor(raw) {
11
+ this.raw = raw;
12
+ }
13
+ static build(text, index) {
14
+ const parts = text.trim().split(Separator.SPACE.token);
15
+ const length = parts.length;
16
+ if (index instanceof NameIndex) {
17
+ const names = Object.entries(index.json())
18
+ .filter(([, position]) => position > -1 && position < length)
19
+ .map(([key, position]) => new Name(parts[position], Namon.all.get(key)));
20
+ return new ArrayNameParser(names);
21
+ }
22
+ if (length < 2) {
23
+ throw new InputError({
24
+ source: text,
25
+ message: 'cannot build from invalid input',
26
+ });
27
+ }
28
+ else if (length === 2 || length === 3) {
29
+ return new StringParser(text);
30
+ }
31
+ else {
32
+ const last = parts.pop();
33
+ const [first, ...middles] = parts;
34
+ return new ArrayStringParser([first, middles.join(' '), last]);
35
+ }
36
+ }
37
+ static buildAsync(text, index) {
38
+ try {
39
+ return Promise.resolve(Parser.build(text, index));
40
+ }
41
+ catch (error) {
42
+ return Promise.reject(error);
43
+ }
44
+ }
45
+ }
46
+ export class StringParser extends Parser {
47
+ parse(options) {
48
+ const config = Config.merge(options);
49
+ const names = this.raw.split(config.separator.token);
50
+ return new ArrayStringParser(names).parse(options);
51
+ }
52
+ }
53
+ export class ArrayStringParser extends Parser {
54
+ parse(options) {
55
+ const config = Config.merge(options);
56
+ const fullName = new FullName(config);
57
+ const raw = this.raw.map((n) => n.trim());
58
+ const index = NameIndex.when(config.orderedBy, raw.length);
59
+ const validator = new ArrayStringValidator(index);
60
+ if (config.bypass) {
61
+ validator.validateIndex(raw);
62
+ }
63
+ else {
64
+ validator.validate(raw);
65
+ }
66
+ const { firstName, lastName, middleName, prefix, suffix } = index;
67
+ fullName.setFirstName(new FirstName(raw[firstName]));
68
+ fullName.setLastName(new LastName(raw[lastName]));
69
+ if (raw.length >= 3)
70
+ fullName.setMiddleName(raw[middleName].split(config.separator.token));
71
+ if (raw.length >= 4)
72
+ fullName.setPrefix(Name.prefix(raw[prefix]));
73
+ if (raw.length === 5)
74
+ fullName.setSuffix(Name.suffix(raw[suffix]));
75
+ return fullName;
76
+ }
77
+ }
78
+ export class NamaParser extends Parser {
79
+ parse(options) {
80
+ const config = Config.merge(options);
81
+ if (config.bypass) {
82
+ NamaValidator.create().validateKeys(this.#asNama());
83
+ }
84
+ else {
85
+ NamaValidator.create().validate(this.#asNama());
86
+ }
87
+ return FullName.parse(this.raw, config);
88
+ }
89
+ #asNama() {
90
+ return new Map(Object.entries(this.raw).map(([key, value]) => {
91
+ const namon = Namon.cast(key);
92
+ if (!namon) {
93
+ throw new InputError({
94
+ source: Object.values(this.raw).join(' '),
95
+ message: `unsupported key "${key}"`,
96
+ });
97
+ }
98
+ return [namon, value];
99
+ }));
100
+ }
101
+ }
102
+ export class ArrayNameParser extends Parser {
103
+ parse(options) {
104
+ const config = Config.merge(options);
105
+ const fullName = new FullName(config);
106
+ ArrayNameValidator.create().validate(this.raw);
107
+ for (const name of this.raw) {
108
+ if (name.isPrefix) {
109
+ fullName.setPrefix(name);
110
+ }
111
+ else if (name.isSuffix) {
112
+ fullName.setSuffix(name);
113
+ }
114
+ else if (name.isFirstName) {
115
+ fullName.setFirstName(name instanceof FirstName ? name : new FirstName(name.value));
116
+ }
117
+ else if (name.isMiddleName) {
118
+ fullName.middleName.push(name);
119
+ }
120
+ else if (name.isLastName) {
121
+ const lastName = new LastName(name.value, name instanceof LastName ? name.mother : undefined, config.surname);
122
+ fullName.setLastName(lastName);
123
+ }
124
+ }
125
+ return fullName;
126
+ }
127
+ }
@@ -1,6 +1,4 @@
1
- /**
2
- * Make a type nullable.
3
- */
1
+ /** Make a type nullable. */
4
2
  export type Nullable<T> = T | null | undefined;
5
3
  /**
6
4
  * The abbreviation type to indicate whether or not to add period to a prefix
@@ -23,25 +21,19 @@ export declare enum Surname {
23
21
  HYPHENATED = "hyphenated",
24
22
  ALL = "all"
25
23
  }
26
- /**
27
- * The order of appearance of a `FullName`.
28
- */
24
+ /** The order of appearance of a `FullName`. */
29
25
  export declare enum NameOrder {
30
26
  FIRST_NAME = "firstName",
31
27
  LAST_NAME = "lastName"
32
28
  }
33
- /**
34
- * The types of name handled in this according the name standards.
35
- */
29
+ /** The types of name handled in this according the name standards. */
36
30
  export declare enum NameType {
37
31
  FIRST_NAME = "firstName",
38
32
  MIDDLE_NAME = "middleName",
39
33
  LAST_NAME = "lastName",
40
34
  BIRTH_NAME = "birthName"
41
35
  }
42
- /**
43
- * The possible variants to indicate how to flatten a `FullName`.
44
- */
36
+ /** The possible variants to indicate how to flatten a `FullName`. */
45
37
  export declare enum Flat {
46
38
  FIRST_NAME = "firstName",
47
39
  MIDDLE_NAME = "middleName",
@@ -50,17 +42,13 @@ export declare enum Flat {
50
42
  MID_LAST = "midLast",
51
43
  ALL = "all"
52
44
  }
53
- /**
54
- * The range to use when capitalizing a string content.
55
- */
45
+ /** The range to use when capitalizing a string content. */
56
46
  export declare enum CapsRange {
57
47
  NONE = 0,
58
48
  INITIAL = 1,
59
49
  ALL = 2
60
50
  }
61
- /**
62
- * The types of name handled in this utility according the name standards.
63
- */
51
+ /** The types of name handled in this utility according the name standards. */
64
52
  export declare class Namon {
65
53
  readonly index: number;
66
54
  readonly key: string;
@@ -69,35 +57,21 @@ export declare class Namon {
69
57
  static readonly MIDDLE_NAME: Namon;
70
58
  static readonly LAST_NAME: Namon;
71
59
  static readonly SUFFIX: Namon;
72
- /**
73
- * The list of supported name types.
74
- */
60
+ /** The list of supported name types. */
75
61
  static readonly values: Namon[];
76
- /**
77
- * All the predefined name types.
78
- */
62
+ /** All the predefined name types. */
79
63
  static readonly all: Map<string, Namon>;
80
64
  private constructor();
81
- /**
82
- * Whether this string key is part of the predefined keys.
83
- */
65
+ /** Whether this string key is part of the predefined keys. */
84
66
  static has(key: string): boolean;
85
- /**
86
- * Makes a string key a namon type.
87
- */
67
+ /** Makes a string key a namon type. */
88
68
  static cast(key: string): Nullable<Namon>;
89
- /**
90
- * String representation of this object.
91
- */
69
+ /** String representation of this object. */
92
70
  toString(): string;
93
- /**
94
- * Whether this and the other value are equal.
95
- */
71
+ /** Whether this and the other value are equal. */
96
72
  equal(other: Namon | unknown): boolean;
97
73
  }
98
- /**
99
- * The token used to indicate how to split string values.
100
- */
74
+ /** The token used to indicate how to split string values. */
101
75
  export declare class Separator {
102
76
  readonly name: string;
103
77
  readonly token: string;
@@ -111,17 +85,11 @@ export declare class Separator {
111
85
  static readonly SINGLE_QUOTE: Separator;
112
86
  static readonly SPACE: Separator;
113
87
  static readonly UNDERSCORE: Separator;
114
- /**
115
- * All the available separators.
116
- */
88
+ /** All the available separators. */
117
89
  static readonly all: Map<string, Separator>;
118
- /**
119
- * All the available tokens.
120
- */
90
+ /** All the available tokens. */
121
91
  static readonly tokens: string[];
122
92
  private constructor();
123
- /**
124
- * String representation of this object.
125
- */
93
+ /** String representation of this object. */
126
94
  toString(): string;
127
95
  }
@@ -0,0 +1,106 @@
1
+ export var Title;
2
+ (function (Title) {
3
+ Title["US"] = "US";
4
+ Title["UK"] = "UK";
5
+ })(Title || (Title = {}));
6
+ export var Surname;
7
+ (function (Surname) {
8
+ Surname["FATHER"] = "father";
9
+ Surname["MOTHER"] = "mother";
10
+ Surname["HYPHENATED"] = "hyphenated";
11
+ Surname["ALL"] = "all";
12
+ })(Surname || (Surname = {}));
13
+ export var NameOrder;
14
+ (function (NameOrder) {
15
+ NameOrder["FIRST_NAME"] = "firstName";
16
+ NameOrder["LAST_NAME"] = "lastName";
17
+ })(NameOrder || (NameOrder = {}));
18
+ export var NameType;
19
+ (function (NameType) {
20
+ NameType["FIRST_NAME"] = "firstName";
21
+ NameType["MIDDLE_NAME"] = "middleName";
22
+ NameType["LAST_NAME"] = "lastName";
23
+ NameType["BIRTH_NAME"] = "birthName";
24
+ })(NameType || (NameType = {}));
25
+ export var Flat;
26
+ (function (Flat) {
27
+ Flat["FIRST_NAME"] = "firstName";
28
+ Flat["MIDDLE_NAME"] = "middleName";
29
+ Flat["LAST_NAME"] = "lastName";
30
+ Flat["FIRST_MID"] = "firstMid";
31
+ Flat["MID_LAST"] = "midLast";
32
+ Flat["ALL"] = "all";
33
+ })(Flat || (Flat = {}));
34
+ export var CapsRange;
35
+ (function (CapsRange) {
36
+ CapsRange[CapsRange["NONE"] = 0] = "NONE";
37
+ CapsRange[CapsRange["INITIAL"] = 1] = "INITIAL";
38
+ CapsRange[CapsRange["ALL"] = 2] = "ALL";
39
+ })(CapsRange || (CapsRange = {}));
40
+ export class Namon {
41
+ index;
42
+ key;
43
+ static PREFIX = new Namon(0, 'prefix');
44
+ static FIRST_NAME = new Namon(1, 'firstName');
45
+ static MIDDLE_NAME = new Namon(2, 'middleName');
46
+ static LAST_NAME = new Namon(3, 'lastName');
47
+ static SUFFIX = new Namon(4, 'suffix');
48
+ static values = [Namon.PREFIX, Namon.FIRST_NAME, Namon.MIDDLE_NAME, Namon.LAST_NAME, Namon.SUFFIX];
49
+ static all = new Map([
50
+ [Namon.PREFIX.key, Namon.PREFIX],
51
+ [Namon.FIRST_NAME.key, Namon.FIRST_NAME],
52
+ [Namon.MIDDLE_NAME.key, Namon.MIDDLE_NAME],
53
+ [Namon.LAST_NAME.key, Namon.LAST_NAME],
54
+ [Namon.SUFFIX.key, Namon.SUFFIX],
55
+ ]);
56
+ constructor(index, key) {
57
+ this.index = index;
58
+ this.key = key;
59
+ }
60
+ static has(key) {
61
+ return Namon.all.has(key);
62
+ }
63
+ static cast(key) {
64
+ return Namon.has(key) ? Namon.all.get(key) : undefined;
65
+ }
66
+ toString() {
67
+ return `Namon.${this.key}`;
68
+ }
69
+ equal(other) {
70
+ return other instanceof Namon && other.index === this.index && other.key === this.key;
71
+ }
72
+ }
73
+ export class Separator {
74
+ name;
75
+ token;
76
+ static COMMA = new Separator('comma', ',');
77
+ static COLON = new Separator('colon', ':');
78
+ static DOUBLE_QUOTE = new Separator('doubleQuote', '"');
79
+ static EMPTY = new Separator('empty', '');
80
+ static HYPHEN = new Separator('hyphen', '-');
81
+ static PERIOD = new Separator('period', '.');
82
+ static SEMI_COLON = new Separator('semiColon', ';');
83
+ static SINGLE_QUOTE = new Separator('singleQuote', `'`);
84
+ static SPACE = new Separator('space', ' ');
85
+ static UNDERSCORE = new Separator('underscore', '_');
86
+ static all = new Map([
87
+ [Separator.COMMA.name, Separator.COMMA],
88
+ [Separator.COLON.name, Separator.COLON],
89
+ [Separator.DOUBLE_QUOTE.name, Separator.DOUBLE_QUOTE],
90
+ [Separator.EMPTY.name, Separator.EMPTY],
91
+ [Separator.HYPHEN.name, Separator.HYPHEN],
92
+ [Separator.PERIOD.name, Separator.PERIOD],
93
+ [Separator.SEMI_COLON.name, Separator.SEMI_COLON],
94
+ [Separator.SINGLE_QUOTE.name, Separator.SINGLE_QUOTE],
95
+ [Separator.SPACE.name, Separator.SPACE],
96
+ [Separator.UNDERSCORE.name, Separator.UNDERSCORE],
97
+ ]);
98
+ static tokens = [...Separator.all.values()].map((s) => s.token);
99
+ constructor(name, token) {
100
+ this.name = name;
101
+ this.token = token;
102
+ }
103
+ toString() {
104
+ return `Separator.${this.name}`;
105
+ }
106
+ }
@@ -1,6 +1,6 @@
1
- import { NameOrder, CapsRange } from './types';
1
+ import { NameOrder, CapsRange } from './types.js';
2
2
  /**
3
- * A fixed set of values to handle specific positions for list of names.
3
+ * A set of values to handle specific positions for list of names.
4
4
  *
5
5
  * As for list of names, this helps to follow a specific order based on the
6
6
  * count of elements. It is expected that the list has to be between two and
@@ -42,14 +42,12 @@ export declare class NameIndex {
42
42
  static when(order: NameOrder, count?: number): NameIndex;
43
43
  static only({ prefix, firstName, middleName, lastName, suffix }: Record<string, number>): NameIndex;
44
44
  toJson(): Record<string, number>;
45
+ json: () => Record<string, number>;
45
46
  }
46
- /**
47
- * Capitalizes a string via a `CapsRange` option.
48
- */
47
+ /** Capitalizes a string via a `CapsRange` option. */
49
48
  export declare function capitalize(str: string, range?: CapsRange): string;
50
49
  /** Decapitalizes a string via a `CapsRange` option. */
51
50
  export declare function decapitalize(str: string, range?: CapsRange): string;
52
51
  /** Toggles a string representation. */
53
52
  export declare function toggleCase(str: string): string;
54
53
  export declare function isStringArray(value?: unknown): boolean;
55
- export declare function isNameArray(value?: unknown): boolean;
@@ -0,0 +1,91 @@
1
+ import { NameOrder, CapsRange } from './types.js';
2
+ import { MIN_NUMBER_OF_NAME_PARTS, MAX_NUMBER_OF_NAME_PARTS } from './constants.js';
3
+ export class NameIndex {
4
+ prefix;
5
+ firstName;
6
+ middleName;
7
+ lastName;
8
+ suffix;
9
+ static get min() {
10
+ return MIN_NUMBER_OF_NAME_PARTS;
11
+ }
12
+ static get max() {
13
+ return MAX_NUMBER_OF_NAME_PARTS;
14
+ }
15
+ constructor(prefix, firstName, middleName, lastName, suffix) {
16
+ this.prefix = prefix;
17
+ this.firstName = firstName;
18
+ this.middleName = middleName;
19
+ this.lastName = lastName;
20
+ this.suffix = suffix;
21
+ }
22
+ static base() {
23
+ return new NameIndex(-1, 0, -1, 1, -1);
24
+ }
25
+ static when(order, count = 2) {
26
+ if (order === NameOrder.FIRST_NAME) {
27
+ switch (count) {
28
+ case 2:
29
+ return new NameIndex(-1, 0, -1, 1, -1);
30
+ case 3:
31
+ return new NameIndex(-1, 0, 1, 2, -1);
32
+ case 4:
33
+ return new NameIndex(0, 1, 2, 3, -1);
34
+ case 5:
35
+ return new NameIndex(0, 1, 2, 3, 4);
36
+ default:
37
+ return NameIndex.base();
38
+ }
39
+ }
40
+ else {
41
+ switch (count) {
42
+ case 2:
43
+ return new NameIndex(-1, 1, -1, 0, -1);
44
+ case 3:
45
+ return new NameIndex(-1, 1, 2, 0, -1);
46
+ case 4:
47
+ return new NameIndex(0, 2, 3, 1, -1);
48
+ case 5:
49
+ return new NameIndex(0, 2, 3, 1, 4);
50
+ default:
51
+ return NameIndex.base();
52
+ }
53
+ }
54
+ }
55
+ static only({ prefix = -1, firstName, middleName = -1, lastName, suffix = -1 }) {
56
+ return new NameIndex(prefix, firstName, middleName, lastName, suffix);
57
+ }
58
+ toJson() {
59
+ return {
60
+ prefix: this.prefix,
61
+ firstName: this.firstName,
62
+ middleName: this.middleName,
63
+ lastName: this.lastName,
64
+ suffix: this.suffix,
65
+ };
66
+ }
67
+ json = this.toJson;
68
+ }
69
+ export function capitalize(str, range = CapsRange.INITIAL) {
70
+ if (!str || range === CapsRange.NONE)
71
+ return str;
72
+ const initial = str[0].toUpperCase();
73
+ const rest = str.slice(1).toLowerCase();
74
+ return range === CapsRange.INITIAL ? initial.concat(rest) : str.toUpperCase();
75
+ }
76
+ export function decapitalize(str, range = CapsRange.INITIAL) {
77
+ if (!str || range === CapsRange.NONE)
78
+ return str;
79
+ const initial = str[0].toLowerCase();
80
+ const rest = str.slice(1);
81
+ return range === CapsRange.INITIAL ? initial.concat(rest) : str.toLowerCase();
82
+ }
83
+ export function toggleCase(str) {
84
+ return str
85
+ .split('')
86
+ .map((c) => (c === c.toUpperCase() ? c.toLowerCase() : c.toUpperCase()))
87
+ .join('');
88
+ }
89
+ export function isStringArray(value) {
90
+ return Array.isArray(value) && value.length > 0 && value.every((e) => typeof e === 'string');
91
+ }
@@ -1,6 +1,6 @@
1
- import { FirstName, LastName, Name } from './name';
2
- import { Namon } from './types';
3
- import { NameIndex } from './utils';
1
+ import { FirstName, LastName, Name } from './name.js';
2
+ import { Namon } from './types.js';
3
+ import { NameIndex } from './utils.js';
4
4
  export interface Validator<T> {
5
5
  validate(value: T): void;
6
6
  }