namefully 2.0.1 → 2.1.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.
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NameBuilder = void 0;
4
- const namefully_js_1 = require("./namefully.js");
5
4
  const validator_js_1 = require("./validator.js");
5
+ const namefully_js_1 = require("./namefully.js");
6
6
  class Builder {
7
7
  prebuild;
8
8
  postbuild;
@@ -70,11 +70,11 @@ class NameBuilder extends Builder {
70
70
  static use({ names, prebuild, postbuild, preclear, postclear, }) {
71
71
  return new NameBuilder(names ?? [], prebuild, postbuild, preclear, postclear);
72
72
  }
73
- build(config) {
73
+ build(options) {
74
74
  this.prebuild?.();
75
75
  const names = [...this.queue];
76
76
  validator_js_1.ArrayNameValidator.create().validate(names);
77
- this.instance = new namefully_js_1.Namefully(names, config);
77
+ this.instance = new namefully_js_1.Namefully(names, options);
78
78
  this.postbuild?.(this.instance);
79
79
  return this.instance;
80
80
  }
@@ -1,30 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ALLOWED_TOKENS = exports.MAX_NUMBER_OF_NAME_PARTS = exports.MIN_NUMBER_OF_NAME_PARTS = exports.VERSION = void 0;
4
- exports.VERSION = '2.0.1';
3
+ exports.ALLOWED_FORMAT_TOKENS = exports.MAX_NUMBER_OF_NAME_PARTS = exports.MIN_NUMBER_OF_NAME_PARTS = exports.VERSION = void 0;
4
+ exports.VERSION = '2.1.0';
5
5
  exports.MIN_NUMBER_OF_NAME_PARTS = 2;
6
6
  exports.MAX_NUMBER_OF_NAME_PARTS = 5;
7
- exports.ALLOWED_TOKENS = [
8
- '.',
9
- ',',
10
- ' ',
11
- '-',
12
- '_',
13
- 'b',
14
- 'B',
15
- 'f',
16
- 'F',
17
- 'l',
18
- 'L',
19
- 'm',
20
- 'M',
21
- 'n',
22
- 'N',
23
- 'o',
24
- 'O',
25
- 'p',
26
- 'P',
27
- 's',
28
- 'S',
29
- '$',
30
- ];
7
+ exports.ALLOWED_FORMAT_TOKENS = ` .,_-()[]<>'"bBfFlLmMnNoOpPsS$`;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deserialize = void 0;
4
+ const builder_js_1 = require("./builder.js");
5
+ const name_js_1 = require("./name.js");
6
+ const error_js_1 = require("./error.js");
7
+ function deserialize(data) {
8
+ try {
9
+ const parsed = typeof data === 'string' ? JSON.parse(data) : data;
10
+ if (!parsed || typeof parsed !== 'object') {
11
+ throw new error_js_1.InputError({
12
+ source: String(data),
13
+ message: 'invalid serialized data; must be an object or a string',
14
+ });
15
+ }
16
+ const { names, config } = parsed;
17
+ const { firstName: fn, lastName: ln, middleName: mn, prefix: px, suffix: sx } = names;
18
+ const builder = builder_js_1.NameBuilder.of();
19
+ if (px)
20
+ builder.add(name_js_1.Name.prefix(px));
21
+ if (sx)
22
+ builder.add(name_js_1.Name.suffix(sx));
23
+ if (mn)
24
+ builder.add(...mn.map((n) => name_js_1.Name.middle(n)));
25
+ builder.add(typeof fn === 'string' ? name_js_1.Name.first(fn) : new name_js_1.FirstName(fn.value, ...(fn.more ?? [])));
26
+ builder.add(typeof ln === 'string' ? name_js_1.Name.last(ln) : new name_js_1.LastName(ln.father, ln.mother));
27
+ return builder.build(config);
28
+ }
29
+ catch (error) {
30
+ if (error instanceof error_js_1.NameError)
31
+ throw error;
32
+ throw new error_js_1.UnknownError({
33
+ source: String(data),
34
+ message: 'could not deserialize data',
35
+ origin: error instanceof Error ? error : new Error(String(error)),
36
+ });
37
+ }
38
+ }
39
+ exports.deserialize = deserialize;
package/dist/cjs/error.js CHANGED
@@ -19,14 +19,11 @@ class NameError extends Error {
19
19
  this.name = 'NameError';
20
20
  }
21
21
  get sourceAsString() {
22
- let input = '';
23
- if (!this.source)
24
- input = '<undefined>';
25
22
  if (typeof this.source === 'string')
26
- input = this.source;
23
+ return this.source;
27
24
  if ((0, utils_js_1.isStringArray)(this.source))
28
- input = this.source.join(' ');
29
- return input;
25
+ return this.source.join(' ');
26
+ return '<undefined>';
30
27
  }
31
28
  get hasMessage() {
32
29
  return this.message.trim().length > 0;
@@ -90,12 +90,34 @@ class FullName {
90
90
  this.#suffix = name_js_1.Name.suffix(name instanceof name_js_1.Name ? name.value : name);
91
91
  return this;
92
92
  }
93
- has(namon) {
93
+ has(key) {
94
+ const namon = typeof key === 'string' ? types_js_1.Namon.cast(key) : key;
95
+ if (!namon)
96
+ return false;
94
97
  if (namon.equal(types_js_1.Namon.PREFIX))
95
98
  return !!this.#prefix;
96
99
  if (namon.equal(types_js_1.Namon.SUFFIX))
97
100
  return !!this.#suffix;
98
101
  return namon.equal(types_js_1.Namon.MIDDLE_NAME) ? this.#middleName.length > 0 : true;
99
102
  }
103
+ *toIterable(flat = false) {
104
+ if (this.#prefix)
105
+ yield this.#prefix;
106
+ if (flat) {
107
+ yield* this.#firstName.asNames;
108
+ yield* this.#middleName;
109
+ yield* this.#lastName.asNames;
110
+ }
111
+ else {
112
+ yield this.#firstName;
113
+ yield* this.#middleName;
114
+ yield this.#lastName;
115
+ }
116
+ if (this.#suffix)
117
+ yield this.#suffix;
118
+ }
119
+ *[Symbol.iterator]() {
120
+ yield* this.toIterable(true);
121
+ }
100
122
  }
101
123
  exports.FullName = FullName;
package/dist/cjs/index.js CHANGED
@@ -23,6 +23,7 @@ __exportStar(require("./builder.js"), exports);
23
23
  __exportStar(require("./config.js"), exports);
24
24
  var constants_js_1 = require("./constants.js");
25
25
  Object.defineProperty(exports, "version", { enumerable: true, get: function () { return constants_js_1.VERSION; } });
26
+ __exportStar(require("./data.js"), exports);
26
27
  __exportStar(require("./error.js"), exports);
27
28
  __exportStar(require("./fullname.js"), exports);
28
29
  __exportStar(require("./name.js"), exports);
package/dist/cjs/name.js CHANGED
@@ -75,8 +75,8 @@ class Name {
75
75
  return this;
76
76
  }
77
77
  validate(name) {
78
- if (name && name?.trim()?.length < 2) {
79
- throw new error_js_1.InputError({ source: name, message: 'must be 2+ characters' });
78
+ if (typeof name === 'string' && name.trim().length < 1) {
79
+ throw new error_js_1.InputError({ source: name, message: 'must be 1+ characters' });
80
80
  }
81
81
  }
82
82
  }
@@ -167,7 +167,7 @@ class LastName extends Name {
167
167
  return this.mother ?? '';
168
168
  case types_js_1.Surname.HYPHENATED:
169
169
  return this.hasMother ? `${this.value}-${this.#mother}` : this.value;
170
- case types_js_1.Surname.ALL:
170
+ default:
171
171
  return this.hasMother ? `${this.value} ${this.#mother}` : this.value;
172
172
  }
173
173
  }
@@ -2,10 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Namefully = void 0;
4
4
  const constants_js_1 = require("./constants.js");
5
- const error_js_1 = require("./error.js");
6
5
  const name_js_1 = require("./name.js");
7
- const types_js_1 = require("./types.js");
6
+ const error_js_1 = require("./error.js");
8
7
  const utils_js_1 = require("./utils.js");
8
+ const types_js_1 = require("./types.js");
9
9
  const parser_js_1 = require("./parser.js");
10
10
  class Namefully {
11
11
  #fullName;
@@ -65,25 +65,43 @@ class Namefully {
65
65
  get salutation() {
66
66
  return this.format('p l');
67
67
  }
68
+ get parts() {
69
+ return this.#fullName.toIterable();
70
+ }
71
+ get size() {
72
+ return Array.from(this.parts).length;
73
+ }
74
+ *[Symbol.iterator]() {
75
+ yield* this.#fullName.toIterable(true);
76
+ }
68
77
  toString() {
69
78
  return this.full;
70
79
  }
71
- get(namon) {
72
- if (namon.equal(types_js_1.Namon.PREFIX))
80
+ get(key) {
81
+ const namon = typeof key === 'string' ? types_js_1.Namon.cast(key) : key;
82
+ if (namon?.equal(types_js_1.Namon.PREFIX))
73
83
  return this.#fullName.prefix;
74
- if (namon.equal(types_js_1.Namon.FIRST_NAME))
84
+ if (namon?.equal(types_js_1.Namon.FIRST_NAME))
75
85
  return this.#fullName.firstName;
76
- if (namon.equal(types_js_1.Namon.MIDDLE_NAME))
86
+ if (namon?.equal(types_js_1.Namon.MIDDLE_NAME))
77
87
  return this.#fullName.middleName;
78
- if (namon.equal(types_js_1.Namon.LAST_NAME))
88
+ if (namon?.equal(types_js_1.Namon.LAST_NAME))
79
89
  return this.#fullName.lastName;
80
- if (namon.equal(types_js_1.Namon.SUFFIX))
90
+ if (namon?.equal(types_js_1.Namon.SUFFIX))
81
91
  return this.#fullName.suffix;
82
92
  return undefined;
83
93
  }
84
94
  equal(other) {
85
95
  return this.toString() === other.toString();
86
96
  }
97
+ deepEqual(other) {
98
+ const others = Array.from(other.parts);
99
+ for (const part of this.parts) {
100
+ if (!others.some((name) => name.equal(part)))
101
+ return false;
102
+ }
103
+ return true;
104
+ }
87
105
  toJson() {
88
106
  return {
89
107
  prefix: this.prefix,
@@ -182,7 +200,7 @@ class Namefully {
182
200
  case types_js_1.Flat.MID_LAST:
183
201
  name = hasMid ? [fn, m, l] : [fn, l];
184
202
  break;
185
- case types_js_1.Flat.ALL:
203
+ default:
186
204
  name = hasMid ? [f, m, l] : [f, l];
187
205
  break;
188
206
  }
@@ -204,7 +222,7 @@ class Namefully {
204
222
  case types_js_1.Flat.MID_LAST:
205
223
  name = hasMid ? [l, fn, m] : [l, fn];
206
224
  break;
207
- case types_js_1.Flat.ALL:
225
+ default:
208
226
  name = hasMid ? [l, f, m] : [l, f];
209
227
  break;
210
228
  }
@@ -245,7 +263,7 @@ class Namefully {
245
263
  let group = '';
246
264
  const formatted = [];
247
265
  for (const char of pattern) {
248
- if (constants_js_1.ALLOWED_TOKENS.indexOf(char) === -1) {
266
+ if (!constants_js_1.ALLOWED_FORMAT_TOKENS.includes(char)) {
249
267
  throw new error_js_1.NotAllowedError({
250
268
  source: this.full,
251
269
  operation: 'format',
@@ -317,12 +335,6 @@ class Namefully {
317
335
  }
318
336
  #map(char) {
319
337
  switch (char) {
320
- case '.':
321
- case ',':
322
- case ' ':
323
- case '-':
324
- case '_':
325
- return char;
326
338
  case 'b':
327
339
  return this.birth;
328
340
  case 'B':
@@ -364,18 +376,42 @@ class Namefully {
364
376
  case 'S':
365
377
  return this.suffix?.toUpperCase();
366
378
  case '$f':
367
- case '$F':
368
379
  return this.#fullName.firstName.value[0];
380
+ case '$F':
381
+ return this.#fullName.firstName.initials(true).join('');
369
382
  case '$l':
370
- case '$L':
371
383
  return this.#fullName.lastName.value[0];
384
+ case '$L':
385
+ return this.#fullName.lastName.initials().join('');
372
386
  case '$m':
373
- case '$M':
374
387
  return this.hasMiddle ? this.middle[0] : undefined;
388
+ case '$M':
389
+ return this.hasMiddle ? this.#fullName.middleName.map((n) => n.value[0]).join('') : undefined;
375
390
  default:
376
- return undefined;
391
+ return constants_js_1.ALLOWED_FORMAT_TOKENS.includes(char) ? char : undefined;
377
392
  }
378
393
  }
394
+ serialize() {
395
+ const { config, firstName: fn, lastName: ln } = this.#fullName;
396
+ return {
397
+ names: {
398
+ prefix: this.prefix,
399
+ firstName: fn.hasMore ? { value: fn.value, more: fn.more } : fn.value,
400
+ middleName: this.hasMiddle ? this.middleName() : undefined,
401
+ lastName: ln.hasMother ? { father: ln.father, mother: ln.mother } : ln.value,
402
+ suffix: this.suffix,
403
+ },
404
+ config: {
405
+ name: config.name,
406
+ orderedBy: config.orderedBy,
407
+ separator: config.separator.token,
408
+ title: config.title,
409
+ ending: config.ending,
410
+ bypass: config.bypass,
411
+ surname: config.surname,
412
+ },
413
+ };
414
+ }
379
415
  }
380
416
  exports.Namefully = Namefully;
381
417
  exports.default = (names, options) => {
@@ -84,16 +84,7 @@ exports.ArrayStringParser = ArrayStringParser;
84
84
  class NamaParser extends Parser {
85
85
  parse(options) {
86
86
  const config = config_js_1.Config.merge(options);
87
- if (config.bypass) {
88
- validator_js_1.NamaValidator.create().validateKeys(this.#asNama());
89
- }
90
- else {
91
- validator_js_1.NamaValidator.create().validate(this.#asNama());
92
- }
93
- return fullname_js_1.FullName.parse(this.raw, config);
94
- }
95
- #asNama() {
96
- return new Map(Object.entries(this.raw).map(([key, value]) => {
87
+ const names = new Map(Object.entries(this.raw).map(([key, value]) => {
97
88
  const namon = types_js_1.Namon.cast(key);
98
89
  if (!namon) {
99
90
  throw new error_js_1.InputError({
@@ -103,6 +94,13 @@ class NamaParser extends Parser {
103
94
  }
104
95
  return [namon, value];
105
96
  }));
97
+ if (config.bypass) {
98
+ validator_js_1.NamaValidator.create().validateKeys(names);
99
+ }
100
+ else {
101
+ validator_js_1.NamaValidator.create().validate(names);
102
+ }
103
+ return fullname_js_1.FullName.parse(this.raw, config);
106
104
  }
107
105
  }
108
106
  exports.NamaParser = NamaParser;
@@ -125,8 +123,8 @@ class ArrayNameParser extends Parser {
125
123
  fullName.middleName.push(name);
126
124
  }
127
125
  else if (name.isLastName) {
128
- const lastName = new name_js_1.LastName(name.value, name instanceof name_js_1.LastName ? name.mother : undefined, config.surname);
129
- fullName.setLastName(lastName);
126
+ const mother = name instanceof name_js_1.LastName ? name.mother : undefined;
127
+ fullName.setLastName(new name_js_1.LastName(name.value, mother, config.surname));
130
128
  }
131
129
  }
132
130
  return fullName;
package/dist/cjs/types.js CHANGED
@@ -56,6 +56,13 @@ class Namon {
56
56
  [Namon.LAST_NAME.key, Namon.LAST_NAME],
57
57
  [Namon.SUFFIX.key, Namon.SUFFIX],
58
58
  ]);
59
+ static aliases = {
60
+ [Namon.PREFIX.key]: ['prefix', 'px', 'p'],
61
+ [Namon.FIRST_NAME.key]: ['firstname', 'first', 'fn', 'f'],
62
+ [Namon.MIDDLE_NAME.key]: ['middlename', 'middle', 'mid', 'mn', 'm'],
63
+ [Namon.LAST_NAME.key]: ['lastname', 'last', 'ln', 'l'],
64
+ [Namon.SUFFIX.key]: ['suffix', 'sx', 's'],
65
+ };
59
66
  constructor(index, key) {
60
67
  this.index = index;
61
68
  this.key = key;
@@ -64,7 +71,9 @@ class Namon {
64
71
  return Namon.all.has(key);
65
72
  }
66
73
  static cast(key) {
67
- return Namon.has(key) ? Namon.all.get(key) : undefined;
74
+ const searchValue = String(key).toLowerCase();
75
+ const namon = Object.entries(Namon.aliases).find(([, list]) => list.includes(searchValue))?.[0];
76
+ return Namon.has(namon ?? '') ? Namon.all.get(key) : undefined;
68
77
  }
69
78
  toString() {
70
79
  return `Namon.${this.key}`;
@@ -104,6 +113,14 @@ class Separator {
104
113
  this.name = name;
105
114
  this.token = token;
106
115
  }
116
+ static cast(key) {
117
+ for (const [name, separator] of Separator.all) {
118
+ if (separator.token === key || name.toLowerCase() === key.toLowerCase()) {
119
+ return separator;
120
+ }
121
+ }
122
+ return undefined;
123
+ }
107
124
  toString() {
108
125
  return `Separator.${this.name}`;
109
126
  }
package/dist/cjs/utils.js CHANGED
@@ -73,16 +73,14 @@ exports.NameIndex = NameIndex;
73
73
  function capitalize(str, range = types_js_1.CapsRange.INITIAL) {
74
74
  if (!str || range === types_js_1.CapsRange.NONE)
75
75
  return str;
76
- const initial = str[0].toUpperCase();
77
- const rest = str.slice(1).toLowerCase();
76
+ const [initial, rest] = [str[0].toUpperCase(), str.slice(1).toLowerCase()];
78
77
  return range === types_js_1.CapsRange.INITIAL ? initial.concat(rest) : str.toUpperCase();
79
78
  }
80
79
  exports.capitalize = capitalize;
81
80
  function decapitalize(str, range = types_js_1.CapsRange.INITIAL) {
82
81
  if (!str || range === types_js_1.CapsRange.NONE)
83
82
  return str;
84
- const initial = str[0].toLowerCase();
85
- const rest = str.slice(1);
83
+ const [initial, rest] = [str[0].toLowerCase(), str.slice(1)];
86
84
  return range === types_js_1.CapsRange.INITIAL ? initial.concat(rest) : str.toLowerCase();
87
85
  }
88
86
  exports.decapitalize = decapitalize;
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Validators = exports.ArrayNameValidator = exports.ArrayStringValidator = exports.NamaValidator = void 0;
4
- const constants_js_1 = require("./constants.js");
5
- const error_js_1 = require("./error.js");
6
- const name_js_1 = require("./name.js");
7
4
  const types_js_1 = require("./types.js");
8
5
  const utils_js_1 = require("./utils.js");
6
+ const name_js_1 = require("./name.js");
7
+ const error_js_1 = require("./error.js");
8
+ const constants_js_1 = require("./constants.js");
9
9
  class ValidationRule {
10
10
  static base = /[a-zA-Z\u00C0-\u00D6\u00D8-\u00f6\u00f8-\u00ff\u0400-\u04FFΆ-ωΑ-ώ]/;
11
11
  static namon = new RegExp(`^${ValidationRule.base.source}+(([' -]${ValidationRule.base.source})?${ValidationRule.base.source}*)*$`);
@@ -21,7 +21,7 @@ class ArrayValidator {
21
21
  if (values.length === 0 || values.length < constants_js_1.MIN_NUMBER_OF_NAME_PARTS || values.length > constants_js_1.MAX_NUMBER_OF_NAME_PARTS) {
22
22
  throw new error_js_1.InputError({
23
23
  source: values.map((n) => n.toString()),
24
- message: `expecting a list of ${constants_js_1.MIN_NUMBER_OF_NAME_PARTS}-${constants_js_1.MIN_NUMBER_OF_NAME_PARTS} elements`,
24
+ message: `expecting a list of ${constants_js_1.MIN_NUMBER_OF_NAME_PARTS}-${constants_js_1.MAX_NUMBER_OF_NAME_PARTS} elements`,
25
25
  });
26
26
  }
27
27
  }
@@ -175,7 +175,7 @@ class NamaValidator {
175
175
  else if (nama.size < constants_js_1.MIN_NUMBER_OF_NAME_PARTS || nama.size > constants_js_1.MAX_NUMBER_OF_NAME_PARTS) {
176
176
  throw new error_js_1.InputError({
177
177
  source: [...nama.values()],
178
- message: `expecting ${constants_js_1.MIN_NUMBER_OF_NAME_PARTS}-${constants_js_1.MIN_NUMBER_OF_NAME_PARTS} fields`,
178
+ message: `expecting ${constants_js_1.MIN_NUMBER_OF_NAME_PARTS}-${constants_js_1.MAX_NUMBER_OF_NAME_PARTS} fields`,
179
179
  });
180
180
  }
181
181
  if (!nama.has(types_js_1.Namon.FIRST_NAME)) {
@@ -1,6 +1,6 @@
1
1
  import { Name } from './name.js';
2
2
  import { Config } from './config.js';
3
- import { Namefully } from './namefully.js';
3
+ import { Namefully, NameOptions } from './namefully.js';
4
4
  type VoidCallback = () => void;
5
5
  type Callback<Type, Return> = (value: Type) => Return;
6
6
  /**
@@ -70,6 +70,6 @@ export declare class NameBuilder extends Builder<Name, Namefully> {
70
70
  * Regardless of how the names are added, both first and last names must exist
71
71
  * to complete a fine build. Otherwise, it throws a NameError.
72
72
  */
73
- build(config?: Partial<Config>): Namefully;
73
+ build(options?: NameOptions): Namefully;
74
74
  }
75
75
  export {};
@@ -1,5 +1,5 @@
1
- import { Namefully } from './namefully.js';
2
1
  import { ArrayNameValidator } from './validator.js';
2
+ import { Namefully } from './namefully.js';
3
3
  class Builder {
4
4
  prebuild;
5
5
  postbuild;
@@ -67,11 +67,11 @@ export class NameBuilder extends Builder {
67
67
  static use({ names, prebuild, postbuild, preclear, postclear, }) {
68
68
  return new NameBuilder(names ?? [], prebuild, postbuild, preclear, postclear);
69
69
  }
70
- build(config) {
70
+ build(options) {
71
71
  this.prebuild?.();
72
72
  const names = [...this.queue];
73
73
  ArrayNameValidator.create().validate(names);
74
- this.instance = new Namefully(names, config);
74
+ this.instance = new Namefully(names, options);
75
75
  this.postbuild?.(this.instance);
76
76
  return this.instance;
77
77
  }
@@ -1,4 +1,4 @@
1
- export declare const VERSION = "2.0.1";
1
+ export declare const VERSION = "2.1.0";
2
2
  export declare const MIN_NUMBER_OF_NAME_PARTS = 2;
3
3
  export declare const MAX_NUMBER_OF_NAME_PARTS = 5;
4
- export declare const ALLOWED_TOKENS: string[];
4
+ export declare const ALLOWED_FORMAT_TOKENS = " .,_-()[]<>'\"bBfFlLmMnNoOpPsS$";
@@ -1,27 +1,4 @@
1
- export const VERSION = '2.0.1';
1
+ export const VERSION = '2.1.0';
2
2
  export const MIN_NUMBER_OF_NAME_PARTS = 2;
3
3
  export const MAX_NUMBER_OF_NAME_PARTS = 5;
4
- export const ALLOWED_TOKENS = [
5
- '.',
6
- ',',
7
- ' ',
8
- '-',
9
- '_',
10
- 'b',
11
- 'B',
12
- 'f',
13
- 'F',
14
- 'l',
15
- 'L',
16
- 'm',
17
- 'M',
18
- 'n',
19
- 'N',
20
- 'o',
21
- 'O',
22
- 'p',
23
- 'P',
24
- 's',
25
- 'S',
26
- '$',
27
- ];
4
+ export const ALLOWED_FORMAT_TOKENS = ` .,_-()[]<>'"bBfFlLmMnNoOpPsS$`;
@@ -0,0 +1,41 @@
1
+ import { type Namefully } from './namefully.js';
2
+ /** Serialized representation of a Namefully instance. */
3
+ export interface SerializedName {
4
+ /** The name data (with its hierarchy intact). */
5
+ names: {
6
+ prefix?: string;
7
+ firstName: string | {
8
+ value: string;
9
+ more?: string[];
10
+ };
11
+ middleName?: string[];
12
+ lastName: string | {
13
+ father: string;
14
+ mother?: string;
15
+ };
16
+ suffix?: string;
17
+ };
18
+ /** The configuration data. */
19
+ config: {
20
+ name: string;
21
+ orderedBy: string;
22
+ separator: string;
23
+ title: string;
24
+ ending: boolean;
25
+ bypass: boolean;
26
+ surname: string;
27
+ };
28
+ }
29
+ /**
30
+ * Deserializes a JSON object into a Namefully instance.
31
+ *
32
+ * This is the inverse operation of `serialize()`, reconstructing a Namefully
33
+ * instance from a previously serialized JSON object, preserving the name hierarchy.
34
+ *
35
+ * @param {SerializedName | string} data the serialized Namefully data (from `serialize()`
36
+ * or compatible format).
37
+ * @returns a new Namefully instance.
38
+ *
39
+ * @throws {NameError} if the data cannot be parsed or is invalid.
40
+ */
41
+ export declare function deserialize(data: SerializedName | string): Namefully;
@@ -0,0 +1,35 @@
1
+ import { NameBuilder } from './builder.js';
2
+ import { Name, FirstName, LastName } from './name.js';
3
+ import { InputError, NameError, UnknownError } from './error.js';
4
+ export function deserialize(data) {
5
+ try {
6
+ const parsed = typeof data === 'string' ? JSON.parse(data) : data;
7
+ if (!parsed || typeof parsed !== 'object') {
8
+ throw new InputError({
9
+ source: String(data),
10
+ message: 'invalid serialized data; must be an object or a string',
11
+ });
12
+ }
13
+ const { names, config } = parsed;
14
+ const { firstName: fn, lastName: ln, middleName: mn, prefix: px, suffix: sx } = names;
15
+ const builder = NameBuilder.of();
16
+ if (px)
17
+ builder.add(Name.prefix(px));
18
+ if (sx)
19
+ builder.add(Name.suffix(sx));
20
+ if (mn)
21
+ builder.add(...mn.map((n) => Name.middle(n)));
22
+ builder.add(typeof fn === 'string' ? Name.first(fn) : new FirstName(fn.value, ...(fn.more ?? [])));
23
+ builder.add(typeof ln === 'string' ? Name.last(ln) : new LastName(ln.father, ln.mother));
24
+ return builder.build(config);
25
+ }
26
+ catch (error) {
27
+ if (error instanceof NameError)
28
+ throw error;
29
+ throw new UnknownError({
30
+ source: String(data),
31
+ message: 'could not deserialize data',
32
+ origin: error instanceof Error ? error : new Error(String(error)),
33
+ });
34
+ }
35
+ }
@@ -40,8 +40,8 @@ export declare enum NameErrorType {
40
40
  * program failure. Au contraire, it is expected that a programmer using this utility
41
41
  * would consider validating a name using its own business rules. That is not
42
42
  * this utility's job to guess those rules. So, the predefined `ValidationRules`
43
- * obey some common validation techniques when it comes to sanitizing a person
44
- * name. For this reason, the [Config.bypass] is set to `true` by default,
43
+ * obey some common validation techniques when it comes to sanitizing a personal
44
+ * name. For this reason, the `Config.bypass` is set to `true` by default,
45
45
  * indicating that those predefined rules should be skipped for the sake of the
46
46
  * program.
47
47
  *
@@ -50,7 +50,7 @@ export declare enum NameErrorType {
50
50
  *
51
51
  * A name error intends to provide useful information about what causes the error
52
52
  * and let the user take initiative on what happens next to the given name:
53
- * reconstructing it or skipping it.
53
+ * reconstructing it or discarding it.
54
54
  */
55
55
  export declare class NameError extends Error {
56
56
  readonly source: NameSource;
@@ -58,8 +58,8 @@ export declare class NameError extends Error {
58
58
  /**
59
59
  * Creates an error with a message describing the issue for a name source.
60
60
  * @param source name input that caused the error
61
- * @param message a message describing the failure.
62
- * @param type of `NameErrorType`
61
+ * @param message describing the failure.
62
+ * @param type of error via `NameErrorType`
63
63
  */
64
64
  constructor(source: NameSource, message?: string, type?: NameErrorType);
65
65
  /** The actual source input which caused the error. */
@@ -72,9 +72,9 @@ export declare class NameError extends Error {
72
72
  /**
73
73
  * An error thrown when a name source input is incorrect.
74
74
  *
75
- * A `Name` is a name for this utility under certain criteria (i.e., 2+ chars),
75
+ * A `Name` is a name for this utility under certain criteria (i.e., 1+ chars),
76
76
  * hence, a wrong input will cause this kind of error. Another common reason
77
- * may be a wrong key in a Json name parsing mechanism.
77
+ * may be a wrong key in a JSON name parsing mechanism.
78
78
  *
79
79
  * Keep in mind that this error is different from a `ValidationError`.
80
80
  */