@burdenoff/be-sdk 2026.911.1 → 2026.917.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.
- package/dist/chunk-Z32KFAPT.js +165 -0
- package/dist/chunk-Z32KFAPT.js.map +1 -0
- package/dist/index-B2jIInhp.d.ts +76 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/validation/index.d.ts +1 -0
- package/dist/validation/index.js +4 -0
- package/dist/validation/index.js.map +1 -0
- package/package.json +7 -3
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { __export, __name } from './chunk-XE4OXN2W.js';
|
|
2
|
+
|
|
3
|
+
// src/validation/index.ts
|
|
4
|
+
var validation_exports = {};
|
|
5
|
+
__export(validation_exports, {
|
|
6
|
+
NAME_MAX_LENGTH: () => NAME_MAX_LENGTH,
|
|
7
|
+
NAME_MIN_LENGTH: () => NAME_MIN_LENGTH,
|
|
8
|
+
USERNAME_MAX_LENGTH: () => USERNAME_MAX_LENGTH,
|
|
9
|
+
USERNAME_MIN_LENGTH: () => USERNAME_MIN_LENGTH,
|
|
10
|
+
lengthInCodePoints: () => lengthInCodePoints,
|
|
11
|
+
validateName: () => validateName,
|
|
12
|
+
validateUserFields: () => validateUserFields,
|
|
13
|
+
validateUsername: () => validateUsername
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// src/validation/name.ts
|
|
17
|
+
var NAME_MIN_LENGTH = 1;
|
|
18
|
+
var NAME_MAX_LENGTH = 100;
|
|
19
|
+
var NAME_ALLOWED_CHARS = /^[\p{L}\p{M} '.\-\u00B7\u30FB\u200C\u200D]*\p{L}[\p{L}\p{M} '.\-\u00B7\u30FB\u200C\u200D]*$/u;
|
|
20
|
+
var TYPOGRAPHIC_APOSTROPHES = /[\u2018\u2019\u02BC]/g;
|
|
21
|
+
var TYPOGRAPHIC_HYPHENS = /[\u2010\u2011]/g;
|
|
22
|
+
function lengthInCodePoints(s) {
|
|
23
|
+
return [
|
|
24
|
+
...s
|
|
25
|
+
].length;
|
|
26
|
+
}
|
|
27
|
+
__name(lengthInCodePoints, "lengthInCodePoints");
|
|
28
|
+
function validateName(name) {
|
|
29
|
+
const trimmed = (name ?? "").normalize("NFC").replace(TYPOGRAPHIC_APOSTROPHES, "'").replace(TYPOGRAPHIC_HYPHENS, "-").trim();
|
|
30
|
+
if (lengthInCodePoints(trimmed) < NAME_MIN_LENGTH) {
|
|
31
|
+
return {
|
|
32
|
+
valid: false,
|
|
33
|
+
code: "required",
|
|
34
|
+
message: "Name is required"
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
if (lengthInCodePoints(trimmed) > NAME_MAX_LENGTH) {
|
|
38
|
+
return {
|
|
39
|
+
valid: false,
|
|
40
|
+
code: "too_long",
|
|
41
|
+
message: `Name must be ${NAME_MAX_LENGTH} characters or fewer`
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
if (!NAME_ALLOWED_CHARS.test(trimmed)) {
|
|
45
|
+
if (!/\p{L}/u.test(trimmed)) {
|
|
46
|
+
return {
|
|
47
|
+
valid: false,
|
|
48
|
+
code: "no_letter",
|
|
49
|
+
message: "Name must contain at least one letter"
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
valid: false,
|
|
54
|
+
code: "invalid_chars",
|
|
55
|
+
message: "Name can only contain letters, spaces, periods, hyphens, and apostrophes"
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
valid: true,
|
|
60
|
+
value: trimmed
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
__name(validateName, "validateName");
|
|
64
|
+
|
|
65
|
+
// src/validation/username.ts
|
|
66
|
+
var USERNAME_MIN_LENGTH = 3;
|
|
67
|
+
var USERNAME_MAX_LENGTH = 30;
|
|
68
|
+
var USERNAME_ALLOWED_CHARS = /^[a-zA-Z0-9_-]+$/;
|
|
69
|
+
function validateUsername(username) {
|
|
70
|
+
const errors = [];
|
|
71
|
+
const value = (username ?? "").trim();
|
|
72
|
+
if (lengthInCodePoints(value) === 0) {
|
|
73
|
+
errors.push({
|
|
74
|
+
code: "required",
|
|
75
|
+
message: "Username is required"
|
|
76
|
+
});
|
|
77
|
+
return {
|
|
78
|
+
valid: false,
|
|
79
|
+
errors
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
if (lengthInCodePoints(value) < USERNAME_MIN_LENGTH) {
|
|
83
|
+
errors.push({
|
|
84
|
+
code: "too_short",
|
|
85
|
+
message: `Username must be at least ${USERNAME_MIN_LENGTH} characters`
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
if (lengthInCodePoints(value) > USERNAME_MAX_LENGTH) {
|
|
89
|
+
errors.push({
|
|
90
|
+
code: "too_long",
|
|
91
|
+
message: `Username must be ${USERNAME_MAX_LENGTH} characters or fewer`
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
if (!USERNAME_ALLOWED_CHARS.test(value)) {
|
|
95
|
+
errors.push({
|
|
96
|
+
code: "invalid_chars",
|
|
97
|
+
message: "Username can only contain letters, numbers, underscores, and hyphens"
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
if (lengthInCodePoints(value) >= USERNAME_MIN_LENGTH && lengthInCodePoints(value) <= USERNAME_MAX_LENGTH && !/[a-zA-Z]/.test(value)) {
|
|
101
|
+
errors.push({
|
|
102
|
+
code: "no_letter",
|
|
103
|
+
message: "Username must contain at least one letter"
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return errors.length === 0 ? {
|
|
107
|
+
valid: true,
|
|
108
|
+
value
|
|
109
|
+
} : {
|
|
110
|
+
valid: false,
|
|
111
|
+
errors
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
__name(validateUsername, "validateUsername");
|
|
115
|
+
|
|
116
|
+
// src/validation/userFields.ts
|
|
117
|
+
function validateUserFields(input, options = {}) {
|
|
118
|
+
const requireAll = options.requireAll ?? true;
|
|
119
|
+
const errors = [];
|
|
120
|
+
const isBlank = /* @__PURE__ */ __name((v) => !v || v.trim().length === 0, "isBlank");
|
|
121
|
+
const firstName = !isBlank(input.firstName) || requireAll ? validateName(input.firstName) : null;
|
|
122
|
+
if (firstName && !firstName.valid) {
|
|
123
|
+
errors.push({
|
|
124
|
+
field: "firstName",
|
|
125
|
+
code: firstName.code,
|
|
126
|
+
message: firstName.message
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
const lastName = !isBlank(input.lastName) || requireAll ? validateName(input.lastName) : null;
|
|
130
|
+
if (lastName && !lastName.valid) {
|
|
131
|
+
errors.push({
|
|
132
|
+
field: "lastName",
|
|
133
|
+
code: lastName.code,
|
|
134
|
+
message: lastName.message
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
const username = !isBlank(input.username) || requireAll ? validateUsername(input.username) : null;
|
|
138
|
+
if (username && !username.valid) {
|
|
139
|
+
for (const e of username.errors) {
|
|
140
|
+
errors.push({
|
|
141
|
+
field: "username",
|
|
142
|
+
code: e.code,
|
|
143
|
+
message: e.message
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (errors.length > 0) return {
|
|
148
|
+
valid: false,
|
|
149
|
+
errors
|
|
150
|
+
};
|
|
151
|
+
const valueOr = /* @__PURE__ */ __name((result, fallback) => result ? result.value : (fallback ?? "").trim(), "valueOr");
|
|
152
|
+
return {
|
|
153
|
+
valid: true,
|
|
154
|
+
values: {
|
|
155
|
+
firstName: valueOr(firstName, input.firstName),
|
|
156
|
+
lastName: valueOr(lastName, input.lastName),
|
|
157
|
+
username: valueOr(username, input.username)
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
__name(validateUserFields, "validateUserFields");
|
|
162
|
+
|
|
163
|
+
export { NAME_MAX_LENGTH, NAME_MIN_LENGTH, USERNAME_MAX_LENGTH, USERNAME_MIN_LENGTH, lengthInCodePoints, validateName, validateUserFields, validateUsername, validation_exports };
|
|
164
|
+
//# sourceMappingURL=chunk-Z32KFAPT.js.map
|
|
165
|
+
//# sourceMappingURL=chunk-Z32KFAPT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/validation/index.ts","../src/validation/name.ts","../src/validation/username.ts","../src/validation/userFields.ts"],"names":["NAME_MIN_LENGTH","NAME_MAX_LENGTH","NAME_ALLOWED_CHARS","TYPOGRAPHIC_APOSTROPHES","TYPOGRAPHIC_HYPHENS","lengthInCodePoints","s","length","validateName","name","trimmed","normalize","replace","trim","valid","code","message","test","value","USERNAME_MIN_LENGTH","USERNAME_MAX_LENGTH","USERNAME_ALLOWED_CHARS","validateUsername","username","errors","push","validateUserFields","input","options","requireAll","isBlank","v","firstName","field","lastName","e","valueOr","result","fallback","values"],"mappings":"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","file":"chunk-Z32KFAPT.js","sourcesContent":["/**\n * Server-side validators for user-identity fields (firstName, lastName,\n * username). Mirrors the client-side validators in\n * `microfe-auth/src/auth/utils/validation.ts` so the same invariant holds\n * whether the call arrives via the UI form, the GraphQL API directly,\n * or a programmatic client. See BOFF-7261.\n */\n\nexport { validateName, lengthInCodePoints, NAME_MIN_LENGTH, NAME_MAX_LENGTH } from './name.js';\nexport type { NameErrorCode, NameValidationResult } from './name.js';\n\nexport { validateUsername, USERNAME_MIN_LENGTH, USERNAME_MAX_LENGTH } from './username.js';\nexport type { UsernameErrorCode, UsernameValidationResult } from './username.js';\n\nexport { validateUserFields } from './userFields.js';\nexport type { UserFieldKey, UserFieldError, ValidatedUserFields, UserFieldsValidationResult } from './userFields.js';\n","/**\n * Validate a person's name (first or last).\n *\n * Mirrors `microfe-auth/src/auth/utils/validation.ts:validateName` from\n * the BOFF-7214 client-side PR (#59) so the server and the client apply\n * the same invariant. Do not edit one without editing the other — the\n * two must stay byte-identical or client-passes-but-server-rejects errors\n * will surface in production (BOFF-7261 acceptance criteria).\n *\n * Rules:\n * - 1–100 Unicode code points (NOT JavaScript `.length`, which counts\n * UTF-16 code units — see `lengthInCodePoints`).\n * - must contain at least one letter (`\\p{L}`)\n * - allowed characters: letters, marks, literal space, hyphen,\n * apostrophe, period, middle-dot (U+00B7, U+30FB), and zero-width\n * join controls (U+200C, U+200D)\n * - typographic apostrophes (U+2018 / U+2019 / U+02BC) and\n * typographic hyphens (U+2010 / U+2011) are folded to their ASCII\n * equivalents before storage\n * - NFC normalisation runs before trim/length so combining-mark\n * sequences (e.g. `e\\u0301` for `é`) fold to their precomposed form\n *\n * Accepts `string | undefined | null` because the GraphQL input types\n * declare these fields as optional. An absent value fails validation.\n *\n * On success the result carries the canonicalised `value` (NFC,\n * typographic apostrophes folded to ASCII, trimmed) so the caller can\n * persist the exact same string the validator approved — otherwise the\n * validated string and the value written to the database would diverge.\n *\n * Returns a structured result so the caller can map each error code to\n * a distinct i18n key.\n */\n\nexport type NameErrorCode = 'required' | 'too_long' | 'no_letter' | 'invalid_chars';\n\nexport type NameValidationResult =\n | { valid: true; value: string }\n | { valid: false; code: NameErrorCode; message: string };\n\nexport const NAME_MIN_LENGTH = 1;\nexport const NAME_MAX_LENGTH = 100;\n\n/**\n * Allowed characters for a name. Every character must be a letter,\n * mark, literal space, hyphen, apostrophe, period, middle-dot, or join\n * control. Must contain at least one letter.\n *\n * Note: a literal space, not `\\s` — `\\s` matches tabs/newlines/other\n * Unicode whitespace which has no business being inside a person's name.\n *\n * Middle-dot codepoints U+00B7 and U+30FB are allowed as-is, NOT folded\n * to `.` — they're orthographically distinct and silently rewriting the\n * user's name would corrupt their identity.\n */\nconst NAME_ALLOWED_CHARS =\n /^[\\p{L}\\p{M} '.\\-\\u00B7\\u30FB\\u200C\\u200D]*\\p{L}[\\p{L}\\p{M} '.\\-\\u00B7\\u30FB\\u200C\\u200D]*$/u;\nconst TYPOGRAPHIC_APOSTROPHES = /[\\u2018\\u2019\\u02BC]/g;\nconst TYPOGRAPHIC_HYPHENS = /[\\u2010\\u2011]/g;\n\n/**\n * Count Unicode code points in `s` instead of UTF-16 code units. Names\n * written in scripts that live in the supplementary plane (Adlam 𞤁𞤔𞤣,\n * many CJK extensions, etc.) have each letter encoded as two UTF-16 units,\n * so a 51-letter Adlam name would otherwise be miscounted as 102 and\n * rejected as too long.\n *\n * Code-point counting is sufficient for the name validator — grapheme-\n * cluster counting would also handle emoji ZWJ sequences, but the name\n * regex already disallows emoji.\n */\nexport function lengthInCodePoints(s: string): number {\n return [...s].length;\n}\n\nexport function validateName(name: string | undefined | null): NameValidationResult {\n const trimmed = (name ?? '')\n .normalize('NFC')\n .replace(TYPOGRAPHIC_APOSTROPHES, \"'\")\n .replace(TYPOGRAPHIC_HYPHENS, '-')\n .trim();\n\n if (lengthInCodePoints(trimmed) < NAME_MIN_LENGTH) {\n return { valid: false, code: 'required', message: 'Name is required' };\n }\n\n if (lengthInCodePoints(trimmed) > NAME_MAX_LENGTH) {\n return {\n valid: false,\n code: 'too_long',\n message: `Name must be ${NAME_MAX_LENGTH} characters or fewer`,\n };\n }\n\n if (!NAME_ALLOWED_CHARS.test(trimmed)) {\n if (!/\\p{L}/u.test(trimmed)) {\n return {\n valid: false,\n code: 'no_letter',\n message: 'Name must contain at least one letter',\n };\n }\n return {\n valid: false,\n code: 'invalid_chars',\n message: 'Name can only contain letters, spaces, periods, hyphens, and apostrophes',\n };\n }\n\n return { valid: true, value: trimmed };\n}\n","/**\n * Validate a username.\n *\n * Mirrors `microfe-auth/src/auth/utils/validation.ts:validateUsername`\n * from the BOFF-7214 client-side PR (#59). Do not edit one without\n * editing the other.\n *\n * Rules:\n * - 3–30 Unicode code points (NOT JavaScript `.length`)\n * - allow-list `[a-zA-Z0-9_-]`\n * - must contain at least one letter (so `12345` fails — this is the\n * specific BOFF-7214 invariant; a pure-numeric username used to\n * pass the character allow-list alone)\n * - surrounding whitespace is trimmed before validation so a pasted\n * `\" alice_01 \"` doesn't fail with a misleading \"invalid chars\"\n * error\n *\n * On success the result carries the trimmed `value` so the caller\n * persists the same string the validator approved.\n *\n * Returns a structured result with a list of errors so the caller can\n * render every failing rule at once.\n */\n\nimport { lengthInCodePoints } from './name.js';\n\nexport type UsernameErrorCode = 'required' | 'too_short' | 'too_long' | 'invalid_chars' | 'no_letter';\n\nexport type UsernameValidationResult =\n | { valid: true; value: string }\n | {\n valid: false;\n errors: Array<{ code: UsernameErrorCode; message: string }>;\n };\n\nexport const USERNAME_MIN_LENGTH = 3;\nexport const USERNAME_MAX_LENGTH = 30;\nconst USERNAME_ALLOWED_CHARS = /^[a-zA-Z0-9_-]+$/;\n\nexport function validateUsername(username: string | undefined | null): UsernameValidationResult {\n const errors: Array<{ code: UsernameErrorCode; message: string }> = [];\n const value = (username ?? '').trim();\n\n if (lengthInCodePoints(value) === 0) {\n errors.push({ code: 'required', message: 'Username is required' });\n return { valid: false, errors };\n }\n\n if (lengthInCodePoints(value) < USERNAME_MIN_LENGTH) {\n errors.push({\n code: 'too_short',\n message: `Username must be at least ${USERNAME_MIN_LENGTH} characters`,\n });\n }\n\n if (lengthInCodePoints(value) > USERNAME_MAX_LENGTH) {\n errors.push({\n code: 'too_long',\n message: `Username must be ${USERNAME_MAX_LENGTH} characters or fewer`,\n });\n }\n\n if (!USERNAME_ALLOWED_CHARS.test(value)) {\n errors.push({\n code: 'invalid_chars',\n message: 'Username can only contain letters, numbers, underscores, and hyphens',\n });\n }\n\n // Must contain at least one letter — guards against all-numeric or\n // all-symbol usernames slipping through. Pure numeric values like\n // \"12345\" previously passed the character allow-list alone. Only\n // check this when the length is in range so a too-short value doesn't\n // get two errors.\n if (\n lengthInCodePoints(value) >= USERNAME_MIN_LENGTH &&\n lengthInCodePoints(value) <= USERNAME_MAX_LENGTH &&\n !/[a-zA-Z]/.test(value)\n ) {\n errors.push({\n code: 'no_letter',\n message: 'Username must contain at least one letter',\n });\n }\n\n return errors.length === 0 ? { valid: true, value } : { valid: false, errors };\n}\n","/**\n * Bundle validation across all three user-identity fields.\n *\n * Mirrors `microfe-auth/src/auth/utils/validation.ts:validateUserFields`\n * from the BOFF-7214 client-side PR (#59). Do not edit one without\n * editing the other.\n *\n * Use this on the server in `signUp`, `updateCurrentUserProfile`, and\n * `updateUser` so the BOFF-7214 invariant — `firstName` / `lastName`\n * contain a letter, `username` contains a letter — holds at every\n * mutation surface, not just signup (BOFF-7261).\n *\n * `requireAll` controls how blank fields are treated:\n * - `true` (default): used by `signUp` — every field must validate.\n * An empty field fails with `code: \"required\"`.\n * - `false`: used by `updateCurrentUserProfile` / `updateUser` — an\n * existing user whose optional `firstName` / `lastName` is unset\n * (e.g. provisioned via an identity provider) can still update\n * unrelated fields like phone or role. Blank fields are skipped.\n *\n * On success, the result carries the canonicalised values from each\n * individual validator (NFC, typographic apostrophes folded to ASCII,\n * trimmed) so the caller writes the same strings the validators approved\n * — no validate/submit divergence.\n */\n\nimport { validateName } from './name.js';\nimport { validateUsername } from './username.js';\n\nexport type UserFieldKey = 'firstName' | 'lastName' | 'username';\n\nexport interface UserFieldError {\n field: UserFieldKey;\n code: string;\n message: string;\n}\n\nexport interface ValidatedUserFields {\n firstName: string;\n lastName: string;\n username: string;\n}\n\nexport type UserFieldsValidationResult =\n | { valid: true; values: ValidatedUserFields }\n | { valid: false; errors: UserFieldError[] };\n\nexport function validateUserFields(\n input: {\n firstName?: string | null;\n lastName?: string | null;\n username?: string | null;\n },\n options: { requireAll?: boolean } = {}\n): UserFieldsValidationResult {\n const requireAll = options.requireAll ?? true;\n const errors: UserFieldError[] = [];\n\n const isBlank = (v: string | null | undefined): boolean => !v || v.trim().length === 0;\n\n const firstName = !isBlank(input.firstName) || requireAll ? validateName(input.firstName) : null;\n if (firstName && !firstName.valid) {\n errors.push({\n field: 'firstName',\n code: firstName.code,\n message: firstName.message,\n });\n }\n\n const lastName = !isBlank(input.lastName) || requireAll ? validateName(input.lastName) : null;\n if (lastName && !lastName.valid) {\n errors.push({\n field: 'lastName',\n code: lastName.code,\n message: lastName.message,\n });\n }\n\n const username = !isBlank(input.username) || requireAll ? validateUsername(input.username) : null;\n if (username && !username.valid) {\n for (const e of username.errors) {\n errors.push({ field: 'username', code: e.code, message: e.message });\n }\n }\n\n if (errors.length > 0) return { valid: false, errors };\n\n const valueOr = (result: { valid: true; value: string } | null, fallback: string | null | undefined): string =>\n result ? result.value : (fallback ?? '').trim();\n\n return {\n valid: true,\n values: {\n firstName: valueOr(firstName as { valid: true; value: string } | null, input.firstName),\n lastName: valueOr(lastName as { valid: true; value: string } | null, input.lastName),\n username: valueOr(username as { valid: true; value: string } | null, input.username),\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
type NameErrorCode = 'required' | 'too_long' | 'no_letter' | 'invalid_chars';
|
|
2
|
+
type NameValidationResult = {
|
|
3
|
+
valid: true;
|
|
4
|
+
value: string;
|
|
5
|
+
} | {
|
|
6
|
+
valid: false;
|
|
7
|
+
code: NameErrorCode;
|
|
8
|
+
message: string;
|
|
9
|
+
};
|
|
10
|
+
declare const NAME_MIN_LENGTH = 1;
|
|
11
|
+
declare const NAME_MAX_LENGTH = 100;
|
|
12
|
+
declare function lengthInCodePoints(s: string): number;
|
|
13
|
+
declare function validateName(name: string | undefined | null): NameValidationResult;
|
|
14
|
+
|
|
15
|
+
type UsernameErrorCode = 'required' | 'too_short' | 'too_long' | 'invalid_chars' | 'no_letter';
|
|
16
|
+
type UsernameValidationResult = {
|
|
17
|
+
valid: true;
|
|
18
|
+
value: string;
|
|
19
|
+
} | {
|
|
20
|
+
valid: false;
|
|
21
|
+
errors: Array<{
|
|
22
|
+
code: UsernameErrorCode;
|
|
23
|
+
message: string;
|
|
24
|
+
}>;
|
|
25
|
+
};
|
|
26
|
+
declare const USERNAME_MIN_LENGTH = 3;
|
|
27
|
+
declare const USERNAME_MAX_LENGTH = 30;
|
|
28
|
+
declare function validateUsername(username: string | undefined | null): UsernameValidationResult;
|
|
29
|
+
|
|
30
|
+
type UserFieldKey = 'firstName' | 'lastName' | 'username';
|
|
31
|
+
interface UserFieldError {
|
|
32
|
+
field: UserFieldKey;
|
|
33
|
+
code: string;
|
|
34
|
+
message: string;
|
|
35
|
+
}
|
|
36
|
+
interface ValidatedUserFields {
|
|
37
|
+
firstName: string;
|
|
38
|
+
lastName: string;
|
|
39
|
+
username: string;
|
|
40
|
+
}
|
|
41
|
+
type UserFieldsValidationResult = {
|
|
42
|
+
valid: true;
|
|
43
|
+
values: ValidatedUserFields;
|
|
44
|
+
} | {
|
|
45
|
+
valid: false;
|
|
46
|
+
errors: UserFieldError[];
|
|
47
|
+
};
|
|
48
|
+
declare function validateUserFields(input: {
|
|
49
|
+
firstName?: string | null;
|
|
50
|
+
lastName?: string | null;
|
|
51
|
+
username?: string | null;
|
|
52
|
+
}, options?: {
|
|
53
|
+
requireAll?: boolean;
|
|
54
|
+
}): UserFieldsValidationResult;
|
|
55
|
+
|
|
56
|
+
declare const index_NAME_MAX_LENGTH: typeof NAME_MAX_LENGTH;
|
|
57
|
+
declare const index_NAME_MIN_LENGTH: typeof NAME_MIN_LENGTH;
|
|
58
|
+
type index_NameErrorCode = NameErrorCode;
|
|
59
|
+
type index_NameValidationResult = NameValidationResult;
|
|
60
|
+
declare const index_USERNAME_MAX_LENGTH: typeof USERNAME_MAX_LENGTH;
|
|
61
|
+
declare const index_USERNAME_MIN_LENGTH: typeof USERNAME_MIN_LENGTH;
|
|
62
|
+
type index_UserFieldError = UserFieldError;
|
|
63
|
+
type index_UserFieldKey = UserFieldKey;
|
|
64
|
+
type index_UserFieldsValidationResult = UserFieldsValidationResult;
|
|
65
|
+
type index_UsernameErrorCode = UsernameErrorCode;
|
|
66
|
+
type index_UsernameValidationResult = UsernameValidationResult;
|
|
67
|
+
type index_ValidatedUserFields = ValidatedUserFields;
|
|
68
|
+
declare const index_lengthInCodePoints: typeof lengthInCodePoints;
|
|
69
|
+
declare const index_validateName: typeof validateName;
|
|
70
|
+
declare const index_validateUserFields: typeof validateUserFields;
|
|
71
|
+
declare const index_validateUsername: typeof validateUsername;
|
|
72
|
+
declare namespace index {
|
|
73
|
+
export { index_NAME_MAX_LENGTH as NAME_MAX_LENGTH, index_NAME_MIN_LENGTH as NAME_MIN_LENGTH, type index_NameErrorCode as NameErrorCode, type index_NameValidationResult as NameValidationResult, index_USERNAME_MAX_LENGTH as USERNAME_MAX_LENGTH, index_USERNAME_MIN_LENGTH as USERNAME_MIN_LENGTH, type index_UserFieldError as UserFieldError, type index_UserFieldKey as UserFieldKey, type index_UserFieldsValidationResult as UserFieldsValidationResult, type index_UsernameErrorCode as UsernameErrorCode, type index_UsernameValidationResult as UsernameValidationResult, type index_ValidatedUserFields as ValidatedUserFields, index_lengthInCodePoints as lengthInCodePoints, index_validateName as validateName, index_validateUserFields as validateUserFields, index_validateUsername as validateUsername };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export { NAME_MAX_LENGTH as N, USERNAME_MAX_LENGTH as U, type ValidatedUserFields as V, NAME_MIN_LENGTH as a, type NameErrorCode as b, type NameValidationResult as c, USERNAME_MIN_LENGTH as d, type UserFieldError as e, type UserFieldKey as f, type UserFieldsValidationResult as g, type UsernameErrorCode as h, type UsernameValidationResult as i, index as j, validateUserFields as k, lengthInCodePoints as l, validateUsername as m, validateName as v };
|
package/dist/index.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ export { i as Gateway } from './index-Dy6neH2G.js';
|
|
|
37
37
|
export { i as FeatureFlags } from './index-By4Rxoj1.js';
|
|
38
38
|
export { i as Captcha, R as RecaptchaVerifyOptions, a as RecaptchaVerifyResult, b as isCaptchaEnabled, v as verifyCaptcha, c as verifyCaptchaIfEnabled } from './index-B70b5mYS.js';
|
|
39
39
|
export { i as Platform } from './index-PJZzGd8r.js';
|
|
40
|
+
export { N as NAME_MAX_LENGTH, a as NAME_MIN_LENGTH, b as NameErrorCode, c as NameValidationResult, U as USERNAME_MAX_LENGTH, d as USERNAME_MIN_LENGTH, e as UserFieldError, f as UserFieldKey, g as UserFieldsValidationResult, h as UsernameErrorCode, i as UsernameValidationResult, V as ValidatedUserFields, j as Validation, l as lengthInCodePoints, v as validateName, k as validateUserFields, m as validateUsername } from './index-B2jIInhp.js';
|
|
40
41
|
export { C as CircuitBreakerConfig, h as DEFAULT_CIRCUIT_BREAKER_CONFIG, i as DEFAULT_GATEWAY_RETRY_CONFIG, D as DEFAULT_GATEWAY_ROUTING, b as DEFAULT_LAYER_RESOURCES, c as DEFAULT_LAYER_STREAMS, f as GatewayRequestHeaders, g as GatewayRetryConfig, G as GatewayRoutingConfig, L as LayerConfig, a as LayerFullConfig, d as LayerGatewayConfig, e as LayerResourceUrls, S as ServiceLayer } from './layer-GNAVXBMf.js';
|
|
41
42
|
export { S as ShutdownDisposable, d as disposeAll, g as getRegisteredDisposableCount, r as registerDisposable, u as unregisterDisposable } from './shutdown-registry-CW9LryO8.js';
|
|
42
43
|
import './types-BAHkj1GE.js';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { TemporalClient, TemporalClientFactory, TemporalModule, TemporalWorker, TemporalWorkerFactory, TemporalWorkerManager } from './chunk-YNDJQRI3.js';
|
|
2
2
|
import { ActivityModule, UsageModule, TrackerModule } from './chunk-KW55Q6TA.js';
|
|
3
3
|
export { ActivityModule, TrackerModule, UsageModule } from './chunk-KW55Q6TA.js';
|
|
4
|
+
export { NAME_MAX_LENGTH, NAME_MIN_LENGTH, USERNAME_MAX_LENGTH, USERNAME_MIN_LENGTH, validation_exports as Validation, lengthInCodePoints, validateName, validateUserFields, validateUsername } from './chunk-Z32KFAPT.js';
|
|
4
5
|
export { platform_exports as Platform } from './chunk-Z5BURBFZ.js';
|
|
5
6
|
export { prisma_exports as Prisma } from './chunk-YAQ7GNAC.js';
|
|
6
7
|
import { RBACModule } from './chunk-5JNHVKHG.js';
|