@optique/core 1.0.0-dev.1252 → 1.0.0-dev.1265
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/constructs.cjs +104 -13
- package/dist/constructs.js +104 -13
- package/dist/valueparser.cjs +64 -24
- package/dist/valueparser.js +64 -24
- package/package.json +1 -1
package/dist/constructs.cjs
CHANGED
|
@@ -9,6 +9,13 @@ const require_usage_internals = require('./usage-internals.cjs');
|
|
|
9
9
|
//#region src/constructs.ts
|
|
10
10
|
const inheritParentAnnotationsKey = Symbol.for("@optique/core/inheritParentAnnotations");
|
|
11
11
|
/**
|
|
12
|
+
* Internal symbol for exposing field-level parser pairs from `object()`
|
|
13
|
+
* and `merge()` parsers. This allows `merge()` to pre-complete dependency
|
|
14
|
+
* source fields from child parsers before resolving deferred states.
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
const fieldParsersKey = Symbol("fieldParsers");
|
|
18
|
+
/**
|
|
12
19
|
* Returns the field state with parent annotations inherited, respecting
|
|
13
20
|
* the parser's {@link inheritParentAnnotationsKey} flag. This is the
|
|
14
21
|
* same logic as {@link createFieldStateGetter} inside `object()` but
|
|
@@ -777,6 +784,64 @@ async function completeDependencySourceDefaultsAsync(context, parserPairs, regis
|
|
|
777
784
|
}
|
|
778
785
|
}
|
|
779
786
|
/**
|
|
787
|
+
* Collects field-level parser pairs from child parsers that expose them
|
|
788
|
+
* via {@link fieldParsersKey}. Used by `merge()` to gather field→parser
|
|
789
|
+
* mappings from its child `object()` (or nested `merge()`) parsers.
|
|
790
|
+
* @internal
|
|
791
|
+
*/
|
|
792
|
+
function collectChildFieldParsers(parsers) {
|
|
793
|
+
const pairs = [];
|
|
794
|
+
for (const parser of parsers) if (fieldParsersKey in parser) pairs.push(...parser[fieldParsersKey]);
|
|
795
|
+
return pairs;
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* Pre-completes dependency source fields and registers their values in
|
|
799
|
+
* the given registry. Unlike `completeDependencySourceDefaults()` (used
|
|
800
|
+
* by suggest), this function handles all four Phase 1 cases — including
|
|
801
|
+
* PendingDependencySourceState in arrays and wrappedDependencySourceMarker.
|
|
802
|
+
*
|
|
803
|
+
* The original state is NOT modified; only the registry is populated.
|
|
804
|
+
* @internal
|
|
805
|
+
*/
|
|
806
|
+
function preCompleteAndRegisterDependencies(state, fieldParserPairs, registry) {
|
|
807
|
+
for (const [field, fieldParser] of fieldParserPairs) {
|
|
808
|
+
const fieldState = state[field];
|
|
809
|
+
let completed;
|
|
810
|
+
if (Array.isArray(fieldState) && fieldState.length === 1 && require_dependency.isPendingDependencySourceState(fieldState[0])) completed = fieldParser.complete(fieldState);
|
|
811
|
+
else if (fieldState === void 0 && require_dependency.isPendingDependencySourceState(fieldParser.initialState)) completed = fieldParser.complete([fieldParser.initialState]);
|
|
812
|
+
else if (fieldState === void 0 && require_dependency.isWrappedDependencySource(fieldParser)) {
|
|
813
|
+
const pendingState = fieldParser[require_dependency.wrappedDependencySourceMarker];
|
|
814
|
+
completed = fieldParser.complete([pendingState]);
|
|
815
|
+
} else if (fieldState != null && !Array.isArray(fieldState) && !require_dependency.isDependencySourceState(fieldState) && (require_dependency.isWrappedDependencySource(fieldParser) || require_dependency.isPendingDependencySourceState(fieldParser.initialState))) {
|
|
816
|
+
const annotatedFieldState = getAnnotatedFieldState(state, field, fieldParser);
|
|
817
|
+
completed = fieldParser.complete(annotatedFieldState);
|
|
818
|
+
} else continue;
|
|
819
|
+
const depState = wrapAsDependencySourceState(completed, fieldParser);
|
|
820
|
+
if (depState) registerCompletedDependency(depState, registry);
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
/**
|
|
824
|
+
* Async version of {@link preCompleteAndRegisterDependencies}.
|
|
825
|
+
* @internal
|
|
826
|
+
*/
|
|
827
|
+
async function preCompleteAndRegisterDependenciesAsync(state, fieldParserPairs, registry) {
|
|
828
|
+
for (const [field, fieldParser] of fieldParserPairs) {
|
|
829
|
+
const fieldState = state[field];
|
|
830
|
+
let completed;
|
|
831
|
+
if (Array.isArray(fieldState) && fieldState.length === 1 && require_dependency.isPendingDependencySourceState(fieldState[0])) completed = await fieldParser.complete(fieldState);
|
|
832
|
+
else if (fieldState === void 0 && require_dependency.isPendingDependencySourceState(fieldParser.initialState)) completed = await fieldParser.complete([fieldParser.initialState]);
|
|
833
|
+
else if (fieldState === void 0 && require_dependency.isWrappedDependencySource(fieldParser)) {
|
|
834
|
+
const pendingState = fieldParser[require_dependency.wrappedDependencySourceMarker];
|
|
835
|
+
completed = await fieldParser.complete([pendingState]);
|
|
836
|
+
} else if (fieldState != null && !Array.isArray(fieldState) && !require_dependency.isDependencySourceState(fieldState) && (require_dependency.isWrappedDependencySource(fieldParser) || require_dependency.isPendingDependencySourceState(fieldParser.initialState))) {
|
|
837
|
+
const annotatedFieldState = getAnnotatedFieldState(state, field, fieldParser);
|
|
838
|
+
completed = await fieldParser.complete(annotatedFieldState);
|
|
839
|
+
} else continue;
|
|
840
|
+
const depState = wrapAsDependencySourceState(completed, fieldParser);
|
|
841
|
+
if (depState) registerCompletedDependency(depState, registry);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
/**
|
|
780
845
|
* Recursively collects dependency values from DependencySourceState objects
|
|
781
846
|
* found anywhere in the state tree.
|
|
782
847
|
* @internal
|
|
@@ -869,8 +934,8 @@ function resolveDeferred(state, registry, visited = /* @__PURE__ */ new WeakSet(
|
|
|
869
934
|
}
|
|
870
935
|
return state;
|
|
871
936
|
}
|
|
872
|
-
function resolveDeferredParseStates(fieldStates) {
|
|
873
|
-
const registry = new require_dependency.DependencyRegistry();
|
|
937
|
+
function resolveDeferredParseStates(fieldStates, initialRegistry) {
|
|
938
|
+
const registry = initialRegistry ?? new require_dependency.DependencyRegistry();
|
|
874
939
|
collectDependencies(fieldStates, registry);
|
|
875
940
|
return resolveDeferred(fieldStates, registry);
|
|
876
941
|
}
|
|
@@ -916,8 +981,8 @@ async function resolveDeferredAsync(state, registry, visited = /* @__PURE__ */ n
|
|
|
916
981
|
* Async version of resolveDeferredParseStates for async parsers.
|
|
917
982
|
* @internal
|
|
918
983
|
*/
|
|
919
|
-
async function resolveDeferredParseStatesAsync(fieldStates) {
|
|
920
|
-
const registry = new require_dependency.DependencyRegistry();
|
|
984
|
+
async function resolveDeferredParseStatesAsync(fieldStates, initialRegistry) {
|
|
985
|
+
const registry = initialRegistry ?? new require_dependency.DependencyRegistry();
|
|
921
986
|
collectDependencies(fieldStates, registry);
|
|
922
987
|
return await resolveDeferredAsync(fieldStates, registry);
|
|
923
988
|
}
|
|
@@ -1102,6 +1167,7 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
|
1102
1167
|
$mode: combinedMode,
|
|
1103
1168
|
$valueType: [],
|
|
1104
1169
|
$stateType: [],
|
|
1170
|
+
[fieldParsersKey]: parserPairs,
|
|
1105
1171
|
priority: Math.max(...parserKeys.map((k) => parsers[k].priority)),
|
|
1106
1172
|
usage: applyHiddenToUsage(parserPairs.flatMap(([_, p]) => p.usage), options.hidden),
|
|
1107
1173
|
get initialState() {
|
|
@@ -1724,10 +1790,12 @@ function merge(...args) {
|
|
|
1724
1790
|
error: require_message.message`No matching option or argument found.`
|
|
1725
1791
|
};
|
|
1726
1792
|
};
|
|
1793
|
+
const mergedFieldParsers = collectChildFieldParsers(parsers);
|
|
1727
1794
|
return {
|
|
1728
1795
|
$mode: combinedMode,
|
|
1729
1796
|
$valueType: [],
|
|
1730
1797
|
$stateType: [],
|
|
1798
|
+
[fieldParsersKey]: mergedFieldParsers,
|
|
1731
1799
|
priority: Math.max(...parsers.map((p) => p.priority)),
|
|
1732
1800
|
usage: applyHiddenToUsage(parsers.flatMap((p) => p.usage), options.hidden),
|
|
1733
1801
|
initialState,
|
|
@@ -1745,6 +1813,8 @@ function merge(...args) {
|
|
|
1745
1813
|
if (resolvedState && typeof resolvedState === "object") {
|
|
1746
1814
|
const extractedState = {};
|
|
1747
1815
|
for (const field in parser.initialState) extractedState[field] = field in resolvedState ? resolvedState[field] : parser.initialState[field];
|
|
1816
|
+
const annotations = require_annotations.getAnnotations(resolvedState);
|
|
1817
|
+
if (annotations !== void 0) return require_annotations.inheritAnnotations(resolvedState, extractedState);
|
|
1748
1818
|
return extractedState;
|
|
1749
1819
|
}
|
|
1750
1820
|
return parser.initialState;
|
|
@@ -1752,7 +1822,10 @@ function merge(...args) {
|
|
|
1752
1822
|
return parser.initialState;
|
|
1753
1823
|
};
|
|
1754
1824
|
if (!isAsync) {
|
|
1755
|
-
const
|
|
1825
|
+
const childFieldPairs = collectChildFieldParsers(syncParsers);
|
|
1826
|
+
const registry = new require_dependency.DependencyRegistry();
|
|
1827
|
+
preCompleteAndRegisterDependencies(state, childFieldPairs, registry);
|
|
1828
|
+
const resolvedState = resolveDeferredParseStates(state, registry);
|
|
1756
1829
|
const object$1 = {};
|
|
1757
1830
|
for (let i = 0; i < syncParsers.length; i++) {
|
|
1758
1831
|
const parser = syncParsers[i];
|
|
@@ -1767,7 +1840,10 @@ function merge(...args) {
|
|
|
1767
1840
|
};
|
|
1768
1841
|
}
|
|
1769
1842
|
return (async () => {
|
|
1770
|
-
const
|
|
1843
|
+
const childFieldPairs = collectChildFieldParsers(parsers);
|
|
1844
|
+
const registry = new require_dependency.DependencyRegistry();
|
|
1845
|
+
await preCompleteAndRegisterDependenciesAsync(state, childFieldPairs, registry);
|
|
1846
|
+
const resolvedState = await resolveDeferredParseStatesAsync(state, registry);
|
|
1771
1847
|
const object$1 = {};
|
|
1772
1848
|
for (let i = 0; i < parsers.length; i++) {
|
|
1773
1849
|
const parser = parsers[i];
|
|
@@ -1799,19 +1875,23 @@ function merge(...args) {
|
|
|
1799
1875
|
}
|
|
1800
1876
|
return p.initialState;
|
|
1801
1877
|
};
|
|
1802
|
-
const registry = context.dependencyRegistry ? context.dependencyRegistry.clone() : new require_dependency.DependencyRegistry();
|
|
1803
|
-
if (context.state && typeof context.state === "object") collectDependencies(context.state, registry);
|
|
1804
|
-
const contextWithRegistry = {
|
|
1805
|
-
...context,
|
|
1806
|
-
dependencyRegistry: registry
|
|
1807
|
-
};
|
|
1808
1878
|
if (isAsync) return async function* () {
|
|
1879
|
+
const registry$1 = context.dependencyRegistry ? context.dependencyRegistry.clone() : new require_dependency.DependencyRegistry();
|
|
1880
|
+
const childFieldPairs$1 = collectChildFieldParsers(parsers);
|
|
1881
|
+
if (context.state && typeof context.state === "object") {
|
|
1882
|
+
await preCompleteAndRegisterDependenciesAsync(context.state, childFieldPairs$1, registry$1);
|
|
1883
|
+
collectDependencies(context.state, registry$1);
|
|
1884
|
+
} else await completeDependencySourceDefaultsAsync(context, childFieldPairs$1, registry$1);
|
|
1885
|
+
const contextWithRegistry$1 = {
|
|
1886
|
+
...context,
|
|
1887
|
+
dependencyRegistry: registry$1
|
|
1888
|
+
};
|
|
1809
1889
|
const suggestions = [];
|
|
1810
1890
|
for (let i = 0; i < parsers.length; i++) {
|
|
1811
1891
|
const parser = parsers[i];
|
|
1812
1892
|
const parserState = extractState(parser, i);
|
|
1813
1893
|
const parserSuggestions = parser.suggest({
|
|
1814
|
-
...contextWithRegistry,
|
|
1894
|
+
...contextWithRegistry$1,
|
|
1815
1895
|
state: parserState
|
|
1816
1896
|
}, prefix);
|
|
1817
1897
|
if (parser.$mode === "async") for await (const s of parserSuggestions) suggestions.push(s);
|
|
@@ -1819,6 +1899,16 @@ function merge(...args) {
|
|
|
1819
1899
|
}
|
|
1820
1900
|
yield* require_suggestion.deduplicateSuggestions(suggestions);
|
|
1821
1901
|
}();
|
|
1902
|
+
const registry = context.dependencyRegistry ? context.dependencyRegistry.clone() : new require_dependency.DependencyRegistry();
|
|
1903
|
+
const childFieldPairs = collectChildFieldParsers(syncParsers);
|
|
1904
|
+
if (context.state && typeof context.state === "object") {
|
|
1905
|
+
preCompleteAndRegisterDependencies(context.state, childFieldPairs, registry);
|
|
1906
|
+
collectDependencies(context.state, registry);
|
|
1907
|
+
} else completeDependencySourceDefaults(context, childFieldPairs, registry);
|
|
1908
|
+
const contextWithRegistry = {
|
|
1909
|
+
...context,
|
|
1910
|
+
dependencyRegistry: registry
|
|
1911
|
+
};
|
|
1822
1912
|
return function* () {
|
|
1823
1913
|
const suggestions = [];
|
|
1824
1914
|
for (let i = 0; i < syncParsers.length; i++) {
|
|
@@ -2257,6 +2347,7 @@ function group(label, parser, options = {}) {
|
|
|
2257
2347
|
priority: parser.priority,
|
|
2258
2348
|
usage: applyHiddenToUsage(parser.usage, options.hidden),
|
|
2259
2349
|
initialState: parser.initialState,
|
|
2350
|
+
...fieldParsersKey in parser ? { [fieldParsersKey]: parser[fieldParsersKey] } : {},
|
|
2260
2351
|
...typeof parser.shouldDeferCompletion === "function" ? { shouldDeferCompletion: parser.shouldDeferCompletion.bind(parser) } : {},
|
|
2261
2352
|
parse: (context) => parser.parse(context),
|
|
2262
2353
|
complete: (state) => parser.complete(state),
|
package/dist/constructs.js
CHANGED
|
@@ -9,6 +9,13 @@ import { collectLeadingCandidates } from "./usage-internals.js";
|
|
|
9
9
|
//#region src/constructs.ts
|
|
10
10
|
const inheritParentAnnotationsKey = Symbol.for("@optique/core/inheritParentAnnotations");
|
|
11
11
|
/**
|
|
12
|
+
* Internal symbol for exposing field-level parser pairs from `object()`
|
|
13
|
+
* and `merge()` parsers. This allows `merge()` to pre-complete dependency
|
|
14
|
+
* source fields from child parsers before resolving deferred states.
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
const fieldParsersKey = Symbol("fieldParsers");
|
|
18
|
+
/**
|
|
12
19
|
* Returns the field state with parent annotations inherited, respecting
|
|
13
20
|
* the parser's {@link inheritParentAnnotationsKey} flag. This is the
|
|
14
21
|
* same logic as {@link createFieldStateGetter} inside `object()` but
|
|
@@ -777,6 +784,64 @@ async function completeDependencySourceDefaultsAsync(context, parserPairs, regis
|
|
|
777
784
|
}
|
|
778
785
|
}
|
|
779
786
|
/**
|
|
787
|
+
* Collects field-level parser pairs from child parsers that expose them
|
|
788
|
+
* via {@link fieldParsersKey}. Used by `merge()` to gather field→parser
|
|
789
|
+
* mappings from its child `object()` (or nested `merge()`) parsers.
|
|
790
|
+
* @internal
|
|
791
|
+
*/
|
|
792
|
+
function collectChildFieldParsers(parsers) {
|
|
793
|
+
const pairs = [];
|
|
794
|
+
for (const parser of parsers) if (fieldParsersKey in parser) pairs.push(...parser[fieldParsersKey]);
|
|
795
|
+
return pairs;
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* Pre-completes dependency source fields and registers their values in
|
|
799
|
+
* the given registry. Unlike `completeDependencySourceDefaults()` (used
|
|
800
|
+
* by suggest), this function handles all four Phase 1 cases — including
|
|
801
|
+
* PendingDependencySourceState in arrays and wrappedDependencySourceMarker.
|
|
802
|
+
*
|
|
803
|
+
* The original state is NOT modified; only the registry is populated.
|
|
804
|
+
* @internal
|
|
805
|
+
*/
|
|
806
|
+
function preCompleteAndRegisterDependencies(state, fieldParserPairs, registry) {
|
|
807
|
+
for (const [field, fieldParser] of fieldParserPairs) {
|
|
808
|
+
const fieldState = state[field];
|
|
809
|
+
let completed;
|
|
810
|
+
if (Array.isArray(fieldState) && fieldState.length === 1 && isPendingDependencySourceState(fieldState[0])) completed = fieldParser.complete(fieldState);
|
|
811
|
+
else if (fieldState === void 0 && isPendingDependencySourceState(fieldParser.initialState)) completed = fieldParser.complete([fieldParser.initialState]);
|
|
812
|
+
else if (fieldState === void 0 && isWrappedDependencySource(fieldParser)) {
|
|
813
|
+
const pendingState = fieldParser[wrappedDependencySourceMarker];
|
|
814
|
+
completed = fieldParser.complete([pendingState]);
|
|
815
|
+
} else if (fieldState != null && !Array.isArray(fieldState) && !isDependencySourceState(fieldState) && (isWrappedDependencySource(fieldParser) || isPendingDependencySourceState(fieldParser.initialState))) {
|
|
816
|
+
const annotatedFieldState = getAnnotatedFieldState(state, field, fieldParser);
|
|
817
|
+
completed = fieldParser.complete(annotatedFieldState);
|
|
818
|
+
} else continue;
|
|
819
|
+
const depState = wrapAsDependencySourceState(completed, fieldParser);
|
|
820
|
+
if (depState) registerCompletedDependency(depState, registry);
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
/**
|
|
824
|
+
* Async version of {@link preCompleteAndRegisterDependencies}.
|
|
825
|
+
* @internal
|
|
826
|
+
*/
|
|
827
|
+
async function preCompleteAndRegisterDependenciesAsync(state, fieldParserPairs, registry) {
|
|
828
|
+
for (const [field, fieldParser] of fieldParserPairs) {
|
|
829
|
+
const fieldState = state[field];
|
|
830
|
+
let completed;
|
|
831
|
+
if (Array.isArray(fieldState) && fieldState.length === 1 && isPendingDependencySourceState(fieldState[0])) completed = await fieldParser.complete(fieldState);
|
|
832
|
+
else if (fieldState === void 0 && isPendingDependencySourceState(fieldParser.initialState)) completed = await fieldParser.complete([fieldParser.initialState]);
|
|
833
|
+
else if (fieldState === void 0 && isWrappedDependencySource(fieldParser)) {
|
|
834
|
+
const pendingState = fieldParser[wrappedDependencySourceMarker];
|
|
835
|
+
completed = await fieldParser.complete([pendingState]);
|
|
836
|
+
} else if (fieldState != null && !Array.isArray(fieldState) && !isDependencySourceState(fieldState) && (isWrappedDependencySource(fieldParser) || isPendingDependencySourceState(fieldParser.initialState))) {
|
|
837
|
+
const annotatedFieldState = getAnnotatedFieldState(state, field, fieldParser);
|
|
838
|
+
completed = await fieldParser.complete(annotatedFieldState);
|
|
839
|
+
} else continue;
|
|
840
|
+
const depState = wrapAsDependencySourceState(completed, fieldParser);
|
|
841
|
+
if (depState) registerCompletedDependency(depState, registry);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
/**
|
|
780
845
|
* Recursively collects dependency values from DependencySourceState objects
|
|
781
846
|
* found anywhere in the state tree.
|
|
782
847
|
* @internal
|
|
@@ -869,8 +934,8 @@ function resolveDeferred(state, registry, visited = /* @__PURE__ */ new WeakSet(
|
|
|
869
934
|
}
|
|
870
935
|
return state;
|
|
871
936
|
}
|
|
872
|
-
function resolveDeferredParseStates(fieldStates) {
|
|
873
|
-
const registry = new DependencyRegistry();
|
|
937
|
+
function resolveDeferredParseStates(fieldStates, initialRegistry) {
|
|
938
|
+
const registry = initialRegistry ?? new DependencyRegistry();
|
|
874
939
|
collectDependencies(fieldStates, registry);
|
|
875
940
|
return resolveDeferred(fieldStates, registry);
|
|
876
941
|
}
|
|
@@ -916,8 +981,8 @@ async function resolveDeferredAsync(state, registry, visited = /* @__PURE__ */ n
|
|
|
916
981
|
* Async version of resolveDeferredParseStates for async parsers.
|
|
917
982
|
* @internal
|
|
918
983
|
*/
|
|
919
|
-
async function resolveDeferredParseStatesAsync(fieldStates) {
|
|
920
|
-
const registry = new DependencyRegistry();
|
|
984
|
+
async function resolveDeferredParseStatesAsync(fieldStates, initialRegistry) {
|
|
985
|
+
const registry = initialRegistry ?? new DependencyRegistry();
|
|
921
986
|
collectDependencies(fieldStates, registry);
|
|
922
987
|
return await resolveDeferredAsync(fieldStates, registry);
|
|
923
988
|
}
|
|
@@ -1102,6 +1167,7 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
|
1102
1167
|
$mode: combinedMode,
|
|
1103
1168
|
$valueType: [],
|
|
1104
1169
|
$stateType: [],
|
|
1170
|
+
[fieldParsersKey]: parserPairs,
|
|
1105
1171
|
priority: Math.max(...parserKeys.map((k) => parsers[k].priority)),
|
|
1106
1172
|
usage: applyHiddenToUsage(parserPairs.flatMap(([_, p]) => p.usage), options.hidden),
|
|
1107
1173
|
get initialState() {
|
|
@@ -1724,10 +1790,12 @@ function merge(...args) {
|
|
|
1724
1790
|
error: message`No matching option or argument found.`
|
|
1725
1791
|
};
|
|
1726
1792
|
};
|
|
1793
|
+
const mergedFieldParsers = collectChildFieldParsers(parsers);
|
|
1727
1794
|
return {
|
|
1728
1795
|
$mode: combinedMode,
|
|
1729
1796
|
$valueType: [],
|
|
1730
1797
|
$stateType: [],
|
|
1798
|
+
[fieldParsersKey]: mergedFieldParsers,
|
|
1731
1799
|
priority: Math.max(...parsers.map((p) => p.priority)),
|
|
1732
1800
|
usage: applyHiddenToUsage(parsers.flatMap((p) => p.usage), options.hidden),
|
|
1733
1801
|
initialState,
|
|
@@ -1745,6 +1813,8 @@ function merge(...args) {
|
|
|
1745
1813
|
if (resolvedState && typeof resolvedState === "object") {
|
|
1746
1814
|
const extractedState = {};
|
|
1747
1815
|
for (const field in parser.initialState) extractedState[field] = field in resolvedState ? resolvedState[field] : parser.initialState[field];
|
|
1816
|
+
const annotations = getAnnotations(resolvedState);
|
|
1817
|
+
if (annotations !== void 0) return inheritAnnotations(resolvedState, extractedState);
|
|
1748
1818
|
return extractedState;
|
|
1749
1819
|
}
|
|
1750
1820
|
return parser.initialState;
|
|
@@ -1752,7 +1822,10 @@ function merge(...args) {
|
|
|
1752
1822
|
return parser.initialState;
|
|
1753
1823
|
};
|
|
1754
1824
|
if (!isAsync) {
|
|
1755
|
-
const
|
|
1825
|
+
const childFieldPairs = collectChildFieldParsers(syncParsers);
|
|
1826
|
+
const registry = new DependencyRegistry();
|
|
1827
|
+
preCompleteAndRegisterDependencies(state, childFieldPairs, registry);
|
|
1828
|
+
const resolvedState = resolveDeferredParseStates(state, registry);
|
|
1756
1829
|
const object$1 = {};
|
|
1757
1830
|
for (let i = 0; i < syncParsers.length; i++) {
|
|
1758
1831
|
const parser = syncParsers[i];
|
|
@@ -1767,7 +1840,10 @@ function merge(...args) {
|
|
|
1767
1840
|
};
|
|
1768
1841
|
}
|
|
1769
1842
|
return (async () => {
|
|
1770
|
-
const
|
|
1843
|
+
const childFieldPairs = collectChildFieldParsers(parsers);
|
|
1844
|
+
const registry = new DependencyRegistry();
|
|
1845
|
+
await preCompleteAndRegisterDependenciesAsync(state, childFieldPairs, registry);
|
|
1846
|
+
const resolvedState = await resolveDeferredParseStatesAsync(state, registry);
|
|
1771
1847
|
const object$1 = {};
|
|
1772
1848
|
for (let i = 0; i < parsers.length; i++) {
|
|
1773
1849
|
const parser = parsers[i];
|
|
@@ -1799,19 +1875,23 @@ function merge(...args) {
|
|
|
1799
1875
|
}
|
|
1800
1876
|
return p.initialState;
|
|
1801
1877
|
};
|
|
1802
|
-
const registry = context.dependencyRegistry ? context.dependencyRegistry.clone() : new DependencyRegistry();
|
|
1803
|
-
if (context.state && typeof context.state === "object") collectDependencies(context.state, registry);
|
|
1804
|
-
const contextWithRegistry = {
|
|
1805
|
-
...context,
|
|
1806
|
-
dependencyRegistry: registry
|
|
1807
|
-
};
|
|
1808
1878
|
if (isAsync) return async function* () {
|
|
1879
|
+
const registry$1 = context.dependencyRegistry ? context.dependencyRegistry.clone() : new DependencyRegistry();
|
|
1880
|
+
const childFieldPairs$1 = collectChildFieldParsers(parsers);
|
|
1881
|
+
if (context.state && typeof context.state === "object") {
|
|
1882
|
+
await preCompleteAndRegisterDependenciesAsync(context.state, childFieldPairs$1, registry$1);
|
|
1883
|
+
collectDependencies(context.state, registry$1);
|
|
1884
|
+
} else await completeDependencySourceDefaultsAsync(context, childFieldPairs$1, registry$1);
|
|
1885
|
+
const contextWithRegistry$1 = {
|
|
1886
|
+
...context,
|
|
1887
|
+
dependencyRegistry: registry$1
|
|
1888
|
+
};
|
|
1809
1889
|
const suggestions = [];
|
|
1810
1890
|
for (let i = 0; i < parsers.length; i++) {
|
|
1811
1891
|
const parser = parsers[i];
|
|
1812
1892
|
const parserState = extractState(parser, i);
|
|
1813
1893
|
const parserSuggestions = parser.suggest({
|
|
1814
|
-
...contextWithRegistry,
|
|
1894
|
+
...contextWithRegistry$1,
|
|
1815
1895
|
state: parserState
|
|
1816
1896
|
}, prefix);
|
|
1817
1897
|
if (parser.$mode === "async") for await (const s of parserSuggestions) suggestions.push(s);
|
|
@@ -1819,6 +1899,16 @@ function merge(...args) {
|
|
|
1819
1899
|
}
|
|
1820
1900
|
yield* deduplicateSuggestions(suggestions);
|
|
1821
1901
|
}();
|
|
1902
|
+
const registry = context.dependencyRegistry ? context.dependencyRegistry.clone() : new DependencyRegistry();
|
|
1903
|
+
const childFieldPairs = collectChildFieldParsers(syncParsers);
|
|
1904
|
+
if (context.state && typeof context.state === "object") {
|
|
1905
|
+
preCompleteAndRegisterDependencies(context.state, childFieldPairs, registry);
|
|
1906
|
+
collectDependencies(context.state, registry);
|
|
1907
|
+
} else completeDependencySourceDefaults(context, childFieldPairs, registry);
|
|
1908
|
+
const contextWithRegistry = {
|
|
1909
|
+
...context,
|
|
1910
|
+
dependencyRegistry: registry
|
|
1911
|
+
};
|
|
1822
1912
|
return function* () {
|
|
1823
1913
|
const suggestions = [];
|
|
1824
1914
|
for (let i = 0; i < syncParsers.length; i++) {
|
|
@@ -2257,6 +2347,7 @@ function group(label, parser, options = {}) {
|
|
|
2257
2347
|
priority: parser.priority,
|
|
2258
2348
|
usage: applyHiddenToUsage(parser.usage, options.hidden),
|
|
2259
2349
|
initialState: parser.initialState,
|
|
2350
|
+
...fieldParsersKey in parser ? { [fieldParsersKey]: parser[fieldParsersKey] } : {},
|
|
2260
2351
|
...typeof parser.shouldDeferCompletion === "function" ? { shouldDeferCompletion: parser.shouldDeferCompletion.bind(parser) } : {},
|
|
2261
2352
|
parse: (context) => parser.parse(context),
|
|
2262
2353
|
complete: (state) => parser.complete(state),
|
package/dist/valueparser.cjs
CHANGED
|
@@ -499,6 +499,7 @@ function url(options = {}) {
|
|
|
499
499
|
originalProtocolsList.push(protocol);
|
|
500
500
|
normalizedProtocolsList.push(normalized);
|
|
501
501
|
}
|
|
502
|
+
if (originalProtocolsList.length === 0) throw new TypeError("allowedProtocols must not be empty.");
|
|
502
503
|
}
|
|
503
504
|
const originalProtocols = options.allowedProtocols != null ? Object.freeze(originalProtocolsList) : void 0;
|
|
504
505
|
const allowedProtocols = options.allowedProtocols != null ? Object.freeze(normalizedProtocolsList) : void 0;
|
|
@@ -517,7 +518,25 @@ function url(options = {}) {
|
|
|
517
518
|
const url$1 = new URL(input);
|
|
518
519
|
if (allowedProtocols != null && !allowedProtocols.includes(url$1.protocol)) return {
|
|
519
520
|
success: false,
|
|
520
|
-
error: disallowedProtocol ? typeof disallowedProtocol === "function" ? disallowedProtocol(url$1.protocol, originalProtocols) : disallowedProtocol :
|
|
521
|
+
error: disallowedProtocol ? typeof disallowedProtocol === "function" ? disallowedProtocol(url$1.protocol, originalProtocols) : disallowedProtocol : [
|
|
522
|
+
{
|
|
523
|
+
type: "text",
|
|
524
|
+
text: "URL protocol "
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
type: "value",
|
|
528
|
+
value: url$1.protocol
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
type: "text",
|
|
532
|
+
text: " is not allowed. Allowed protocols: "
|
|
533
|
+
},
|
|
534
|
+
...require_message.valueSet(originalProtocols, { locale: "en-US" }),
|
|
535
|
+
{
|
|
536
|
+
type: "text",
|
|
537
|
+
text: "."
|
|
538
|
+
}
|
|
539
|
+
]
|
|
521
540
|
};
|
|
522
541
|
return {
|
|
523
542
|
success: true,
|
|
@@ -1364,16 +1383,19 @@ function email(options) {
|
|
|
1364
1383
|
const allowDisplayName = options?.allowDisplayName ?? false;
|
|
1365
1384
|
const lowercase = options?.lowercase ?? false;
|
|
1366
1385
|
const allowedDomains = options?.allowedDomains != null ? Object.freeze([...options.allowedDomains]) : void 0;
|
|
1367
|
-
if (allowedDomains != null)
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1386
|
+
if (allowedDomains != null) {
|
|
1387
|
+
if (allowedDomains.length === 0) throw new TypeError("allowedDomains must not be empty.");
|
|
1388
|
+
for (let i = 0; i < allowedDomains.length; i++) {
|
|
1389
|
+
const entry = allowedDomains[i];
|
|
1390
|
+
if (typeof entry !== "string") throw new TypeError(`allowedDomains[${i}] must be a string, got ${typeof entry}.`);
|
|
1391
|
+
if (entry !== entry.trim()) throw new TypeError(`allowedDomains[${i}] must not have leading or trailing whitespace: ${JSON.stringify(entry)}`);
|
|
1392
|
+
if (entry.startsWith("@")) throw new TypeError(`allowedDomains[${i}] must not start with "@": ${JSON.stringify(entry)}`);
|
|
1393
|
+
if (entry === "" || !entry.includes(".")) throw new TypeError(`allowedDomains[${i}] is not a valid domain: ${JSON.stringify(entry)}`);
|
|
1394
|
+
if (entry.startsWith(".") || entry.endsWith(".") || entry.startsWith("-") || entry.endsWith("-")) throw new TypeError(`allowedDomains[${i}] is not a valid domain: ${JSON.stringify(entry)}`);
|
|
1395
|
+
const labels = entry.split(".");
|
|
1396
|
+
for (const label of labels) if (label.length === 0 || label.length > 63 || label.startsWith("-") || label.endsWith("-") || !/^[a-zA-Z0-9-]+$/.test(label)) throw new TypeError(`allowedDomains[${i}] is not a valid domain: ${JSON.stringify(entry)}`);
|
|
1397
|
+
if (labels.length === 4 && labels.every((label) => /^[0-9]+$/.test(label))) throw new TypeError(`allowedDomains[${i}] is not a valid domain: ${JSON.stringify(entry)}`);
|
|
1398
|
+
}
|
|
1377
1399
|
}
|
|
1378
1400
|
const invalidEmail = options?.errors?.invalidEmail;
|
|
1379
1401
|
const domainNotAllowed = options?.errors?.domainNotAllowed;
|
|
@@ -1489,7 +1511,12 @@ function email(options) {
|
|
|
1489
1511
|
},
|
|
1490
1512
|
{
|
|
1491
1513
|
type: "text",
|
|
1492
|
-
text:
|
|
1514
|
+
text: " is not allowed. Allowed domains: "
|
|
1515
|
+
},
|
|
1516
|
+
...require_message.valueSet(allowedDomains, { locale: "en-US" }),
|
|
1517
|
+
{
|
|
1518
|
+
type: "text",
|
|
1519
|
+
text: "."
|
|
1493
1520
|
}
|
|
1494
1521
|
];
|
|
1495
1522
|
return {
|
|
@@ -1535,7 +1562,12 @@ function email(options) {
|
|
|
1535
1562
|
},
|
|
1536
1563
|
{
|
|
1537
1564
|
type: "text",
|
|
1538
|
-
text:
|
|
1565
|
+
text: " is not allowed. Allowed domains: "
|
|
1566
|
+
},
|
|
1567
|
+
...require_message.valueSet(allowedDomains, { locale: "en-US" }),
|
|
1568
|
+
{
|
|
1569
|
+
type: "text",
|
|
1570
|
+
text: "."
|
|
1539
1571
|
}
|
|
1540
1572
|
];
|
|
1541
1573
|
return {
|
|
@@ -1849,8 +1881,8 @@ function macAddress(options) {
|
|
|
1849
1881
|
const caseOption = options?.case ?? "preserve";
|
|
1850
1882
|
const outputSeparator = options?.outputSeparator;
|
|
1851
1883
|
const metavar = options?.metavar ?? "MAC";
|
|
1852
|
-
const colonRegex = /^([0-9a-fA-F]{
|
|
1853
|
-
const hyphenRegex = /^([0-9a-fA-F]{
|
|
1884
|
+
const colonRegex = /^([0-9a-fA-F]{2}):([0-9a-fA-F]{2}):([0-9a-fA-F]{2}):([0-9a-fA-F]{2}):([0-9a-fA-F]{2}):([0-9a-fA-F]{2})$/;
|
|
1885
|
+
const hyphenRegex = /^([0-9a-fA-F]{2})-([0-9a-fA-F]{2})-([0-9a-fA-F]{2})-([0-9a-fA-F]{2})-([0-9a-fA-F]{2})-([0-9a-fA-F]{2})$/;
|
|
1854
1886
|
const dotRegex = /^([0-9a-fA-F]{4})\.([0-9a-fA-F]{4})\.([0-9a-fA-F]{4})$/;
|
|
1855
1887
|
const noneRegex = /^([0-9a-fA-F]{12})$/;
|
|
1856
1888
|
return {
|
|
@@ -1983,15 +2015,18 @@ function domain(options) {
|
|
|
1983
2015
|
const allowSubdomains = options?.allowSubdomains ?? true;
|
|
1984
2016
|
const allowedTlds = options?.allowedTlds != null ? Object.freeze([...options.allowedTlds]) : void 0;
|
|
1985
2017
|
const labelRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/;
|
|
1986
|
-
if (allowedTlds !== void 0)
|
|
1987
|
-
if (
|
|
1988
|
-
|
|
1989
|
-
|
|
2018
|
+
if (allowedTlds !== void 0) {
|
|
2019
|
+
if (allowedTlds.length === 0) throw new TypeError("allowedTlds must not be empty.");
|
|
2020
|
+
for (const [i, tld] of allowedTlds.entries()) {
|
|
2021
|
+
if (typeof tld !== "string") {
|
|
2022
|
+
const actualType = Array.isArray(tld) ? "array" : typeof tld;
|
|
2023
|
+
throw new TypeError(`allowedTlds[${i}] must be a string, but got ${actualType}.`);
|
|
2024
|
+
}
|
|
2025
|
+
if (tld.length === 0) throw new TypeError(`allowedTlds[${i}] must not be an empty string.`);
|
|
2026
|
+
if (tld.includes(".")) throw new TypeError(`allowedTlds[${i}] must not contain dots: ${JSON.stringify(tld)}.`);
|
|
2027
|
+
if (tld !== tld.trim()) throw new TypeError(`allowedTlds[${i}] must not have leading or trailing whitespace: ${JSON.stringify(tld)}.`);
|
|
2028
|
+
if (!labelRegex.test(tld)) throw new TypeError(`allowedTlds[${i}] is not a valid DNS label: ${JSON.stringify(tld)}.`);
|
|
1990
2029
|
}
|
|
1991
|
-
if (tld.length === 0) throw new TypeError(`allowedTlds[${i}] must not be an empty string.`);
|
|
1992
|
-
if (tld.includes(".")) throw new TypeError(`allowedTlds[${i}] must not contain dots: ${JSON.stringify(tld)}.`);
|
|
1993
|
-
if (tld !== tld.trim()) throw new TypeError(`allowedTlds[${i}] must not have leading or trailing whitespace: ${JSON.stringify(tld)}.`);
|
|
1994
|
-
if (!labelRegex.test(tld)) throw new TypeError(`allowedTlds[${i}] is not a valid DNS label: ${JSON.stringify(tld)}.`);
|
|
1995
2030
|
}
|
|
1996
2031
|
const allowedTldsLower = allowedTlds != null ? Object.freeze(allowedTlds.map((t) => t.toLowerCase())) : void 0;
|
|
1997
2032
|
const minLabels = options?.minLabels ?? 2;
|
|
@@ -2188,7 +2223,12 @@ function domain(options) {
|
|
|
2188
2223
|
},
|
|
2189
2224
|
{
|
|
2190
2225
|
type: "text",
|
|
2191
|
-
text:
|
|
2226
|
+
text: " is not allowed. Allowed TLDs: "
|
|
2227
|
+
},
|
|
2228
|
+
...require_message.valueSet(allowedTlds, { locale: "en-US" }),
|
|
2229
|
+
{
|
|
2230
|
+
type: "text",
|
|
2231
|
+
text: "."
|
|
2192
2232
|
}
|
|
2193
2233
|
];
|
|
2194
2234
|
return {
|
package/dist/valueparser.js
CHANGED
|
@@ -499,6 +499,7 @@ function url(options = {}) {
|
|
|
499
499
|
originalProtocolsList.push(protocol);
|
|
500
500
|
normalizedProtocolsList.push(normalized);
|
|
501
501
|
}
|
|
502
|
+
if (originalProtocolsList.length === 0) throw new TypeError("allowedProtocols must not be empty.");
|
|
502
503
|
}
|
|
503
504
|
const originalProtocols = options.allowedProtocols != null ? Object.freeze(originalProtocolsList) : void 0;
|
|
504
505
|
const allowedProtocols = options.allowedProtocols != null ? Object.freeze(normalizedProtocolsList) : void 0;
|
|
@@ -517,7 +518,25 @@ function url(options = {}) {
|
|
|
517
518
|
const url$1 = new URL(input);
|
|
518
519
|
if (allowedProtocols != null && !allowedProtocols.includes(url$1.protocol)) return {
|
|
519
520
|
success: false,
|
|
520
|
-
error: disallowedProtocol ? typeof disallowedProtocol === "function" ? disallowedProtocol(url$1.protocol, originalProtocols) : disallowedProtocol :
|
|
521
|
+
error: disallowedProtocol ? typeof disallowedProtocol === "function" ? disallowedProtocol(url$1.protocol, originalProtocols) : disallowedProtocol : [
|
|
522
|
+
{
|
|
523
|
+
type: "text",
|
|
524
|
+
text: "URL protocol "
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
type: "value",
|
|
528
|
+
value: url$1.protocol
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
type: "text",
|
|
532
|
+
text: " is not allowed. Allowed protocols: "
|
|
533
|
+
},
|
|
534
|
+
...valueSet(originalProtocols, { locale: "en-US" }),
|
|
535
|
+
{
|
|
536
|
+
type: "text",
|
|
537
|
+
text: "."
|
|
538
|
+
}
|
|
539
|
+
]
|
|
521
540
|
};
|
|
522
541
|
return {
|
|
523
542
|
success: true,
|
|
@@ -1364,16 +1383,19 @@ function email(options) {
|
|
|
1364
1383
|
const allowDisplayName = options?.allowDisplayName ?? false;
|
|
1365
1384
|
const lowercase = options?.lowercase ?? false;
|
|
1366
1385
|
const allowedDomains = options?.allowedDomains != null ? Object.freeze([...options.allowedDomains]) : void 0;
|
|
1367
|
-
if (allowedDomains != null)
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1386
|
+
if (allowedDomains != null) {
|
|
1387
|
+
if (allowedDomains.length === 0) throw new TypeError("allowedDomains must not be empty.");
|
|
1388
|
+
for (let i = 0; i < allowedDomains.length; i++) {
|
|
1389
|
+
const entry = allowedDomains[i];
|
|
1390
|
+
if (typeof entry !== "string") throw new TypeError(`allowedDomains[${i}] must be a string, got ${typeof entry}.`);
|
|
1391
|
+
if (entry !== entry.trim()) throw new TypeError(`allowedDomains[${i}] must not have leading or trailing whitespace: ${JSON.stringify(entry)}`);
|
|
1392
|
+
if (entry.startsWith("@")) throw new TypeError(`allowedDomains[${i}] must not start with "@": ${JSON.stringify(entry)}`);
|
|
1393
|
+
if (entry === "" || !entry.includes(".")) throw new TypeError(`allowedDomains[${i}] is not a valid domain: ${JSON.stringify(entry)}`);
|
|
1394
|
+
if (entry.startsWith(".") || entry.endsWith(".") || entry.startsWith("-") || entry.endsWith("-")) throw new TypeError(`allowedDomains[${i}] is not a valid domain: ${JSON.stringify(entry)}`);
|
|
1395
|
+
const labels = entry.split(".");
|
|
1396
|
+
for (const label of labels) if (label.length === 0 || label.length > 63 || label.startsWith("-") || label.endsWith("-") || !/^[a-zA-Z0-9-]+$/.test(label)) throw new TypeError(`allowedDomains[${i}] is not a valid domain: ${JSON.stringify(entry)}`);
|
|
1397
|
+
if (labels.length === 4 && labels.every((label) => /^[0-9]+$/.test(label))) throw new TypeError(`allowedDomains[${i}] is not a valid domain: ${JSON.stringify(entry)}`);
|
|
1398
|
+
}
|
|
1377
1399
|
}
|
|
1378
1400
|
const invalidEmail = options?.errors?.invalidEmail;
|
|
1379
1401
|
const domainNotAllowed = options?.errors?.domainNotAllowed;
|
|
@@ -1489,7 +1511,12 @@ function email(options) {
|
|
|
1489
1511
|
},
|
|
1490
1512
|
{
|
|
1491
1513
|
type: "text",
|
|
1492
|
-
text:
|
|
1514
|
+
text: " is not allowed. Allowed domains: "
|
|
1515
|
+
},
|
|
1516
|
+
...valueSet(allowedDomains, { locale: "en-US" }),
|
|
1517
|
+
{
|
|
1518
|
+
type: "text",
|
|
1519
|
+
text: "."
|
|
1493
1520
|
}
|
|
1494
1521
|
];
|
|
1495
1522
|
return {
|
|
@@ -1535,7 +1562,12 @@ function email(options) {
|
|
|
1535
1562
|
},
|
|
1536
1563
|
{
|
|
1537
1564
|
type: "text",
|
|
1538
|
-
text:
|
|
1565
|
+
text: " is not allowed. Allowed domains: "
|
|
1566
|
+
},
|
|
1567
|
+
...valueSet(allowedDomains, { locale: "en-US" }),
|
|
1568
|
+
{
|
|
1569
|
+
type: "text",
|
|
1570
|
+
text: "."
|
|
1539
1571
|
}
|
|
1540
1572
|
];
|
|
1541
1573
|
return {
|
|
@@ -1849,8 +1881,8 @@ function macAddress(options) {
|
|
|
1849
1881
|
const caseOption = options?.case ?? "preserve";
|
|
1850
1882
|
const outputSeparator = options?.outputSeparator;
|
|
1851
1883
|
const metavar = options?.metavar ?? "MAC";
|
|
1852
|
-
const colonRegex = /^([0-9a-fA-F]{
|
|
1853
|
-
const hyphenRegex = /^([0-9a-fA-F]{
|
|
1884
|
+
const colonRegex = /^([0-9a-fA-F]{2}):([0-9a-fA-F]{2}):([0-9a-fA-F]{2}):([0-9a-fA-F]{2}):([0-9a-fA-F]{2}):([0-9a-fA-F]{2})$/;
|
|
1885
|
+
const hyphenRegex = /^([0-9a-fA-F]{2})-([0-9a-fA-F]{2})-([0-9a-fA-F]{2})-([0-9a-fA-F]{2})-([0-9a-fA-F]{2})-([0-9a-fA-F]{2})$/;
|
|
1854
1886
|
const dotRegex = /^([0-9a-fA-F]{4})\.([0-9a-fA-F]{4})\.([0-9a-fA-F]{4})$/;
|
|
1855
1887
|
const noneRegex = /^([0-9a-fA-F]{12})$/;
|
|
1856
1888
|
return {
|
|
@@ -1983,15 +2015,18 @@ function domain(options) {
|
|
|
1983
2015
|
const allowSubdomains = options?.allowSubdomains ?? true;
|
|
1984
2016
|
const allowedTlds = options?.allowedTlds != null ? Object.freeze([...options.allowedTlds]) : void 0;
|
|
1985
2017
|
const labelRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/;
|
|
1986
|
-
if (allowedTlds !== void 0)
|
|
1987
|
-
if (
|
|
1988
|
-
|
|
1989
|
-
|
|
2018
|
+
if (allowedTlds !== void 0) {
|
|
2019
|
+
if (allowedTlds.length === 0) throw new TypeError("allowedTlds must not be empty.");
|
|
2020
|
+
for (const [i, tld] of allowedTlds.entries()) {
|
|
2021
|
+
if (typeof tld !== "string") {
|
|
2022
|
+
const actualType = Array.isArray(tld) ? "array" : typeof tld;
|
|
2023
|
+
throw new TypeError(`allowedTlds[${i}] must be a string, but got ${actualType}.`);
|
|
2024
|
+
}
|
|
2025
|
+
if (tld.length === 0) throw new TypeError(`allowedTlds[${i}] must not be an empty string.`);
|
|
2026
|
+
if (tld.includes(".")) throw new TypeError(`allowedTlds[${i}] must not contain dots: ${JSON.stringify(tld)}.`);
|
|
2027
|
+
if (tld !== tld.trim()) throw new TypeError(`allowedTlds[${i}] must not have leading or trailing whitespace: ${JSON.stringify(tld)}.`);
|
|
2028
|
+
if (!labelRegex.test(tld)) throw new TypeError(`allowedTlds[${i}] is not a valid DNS label: ${JSON.stringify(tld)}.`);
|
|
1990
2029
|
}
|
|
1991
|
-
if (tld.length === 0) throw new TypeError(`allowedTlds[${i}] must not be an empty string.`);
|
|
1992
|
-
if (tld.includes(".")) throw new TypeError(`allowedTlds[${i}] must not contain dots: ${JSON.stringify(tld)}.`);
|
|
1993
|
-
if (tld !== tld.trim()) throw new TypeError(`allowedTlds[${i}] must not have leading or trailing whitespace: ${JSON.stringify(tld)}.`);
|
|
1994
|
-
if (!labelRegex.test(tld)) throw new TypeError(`allowedTlds[${i}] is not a valid DNS label: ${JSON.stringify(tld)}.`);
|
|
1995
2030
|
}
|
|
1996
2031
|
const allowedTldsLower = allowedTlds != null ? Object.freeze(allowedTlds.map((t) => t.toLowerCase())) : void 0;
|
|
1997
2032
|
const minLabels = options?.minLabels ?? 2;
|
|
@@ -2188,7 +2223,12 @@ function domain(options) {
|
|
|
2188
2223
|
},
|
|
2189
2224
|
{
|
|
2190
2225
|
type: "text",
|
|
2191
|
-
text:
|
|
2226
|
+
text: " is not allowed. Allowed TLDs: "
|
|
2227
|
+
},
|
|
2228
|
+
...valueSet(allowedTlds, { locale: "en-US" }),
|
|
2229
|
+
{
|
|
2230
|
+
type: "text",
|
|
2231
|
+
text: "."
|
|
2192
2232
|
}
|
|
2193
2233
|
];
|
|
2194
2234
|
return {
|