typia 13.1.19 → 13.3.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.
- package/lib/executable/FileSystemIdentity.d.ts +23 -0
- package/lib/executable/FileSystemIdentity.js +30 -0
- package/lib/executable/FileSystemIdentity.js.map +1 -1
- package/lib/executable/FileSystemIdentity.mjs +4 -0
- package/lib/executable/FileSystemIdentity.mjs.map +1 -1
- package/lib/executable/TypiaGenerateWizard.js +15 -9
- package/lib/executable/TypiaGenerateWizard.js.map +1 -1
- package/lib/executable/TypiaGenerateWizard.mjs +11 -7
- package/lib/executable/TypiaGenerateWizard.mjs.map +1 -1
- package/lib/http.d.ts +3 -3
- package/lib/http.js.map +1 -1
- package/lib/http.mjs.map +1 -1
- package/lib/internal/_ProtobufReader.d.ts +18 -3
- package/lib/internal/_ProtobufReader.js +39 -11
- package/lib/internal/_ProtobufReader.js.map +1 -1
- package/lib/internal/_ProtobufReader.mjs +37 -10
- package/lib/internal/_ProtobufReader.mjs.map +1 -1
- package/lib/internal/_assertGuard.js +13 -3
- package/lib/internal/_assertGuard.js.map +1 -1
- package/lib/internal/_assertGuard.mjs +4 -2
- package/lib/internal/_assertGuard.mjs.map +1 -1
- package/lib/internal/_isFormatIdnHostname.js +5 -1
- package/lib/internal/_isFormatIdnHostname.js.map +1 -1
- package/lib/internal/_isFormatIdnHostname.mjs +1 -1
- package/lib/internal/_isFormatIdnHostname.mjs.map +1 -1
- package/lib/internal/_isFormatTime.js +19 -2
- package/lib/internal/_isFormatTime.js.map +1 -1
- package/lib/internal/_isFormatTime.mjs +9 -2
- package/lib/internal/_isFormatTime.mjs.map +1 -1
- package/lib/internal/_jsonStringifyArray.d.ts +1 -0
- package/lib/internal/_jsonStringifyArray.js +48 -0
- package/lib/internal/_jsonStringifyArray.js.map +1 -0
- package/lib/internal/_jsonStringifyArray.mjs +40 -0
- package/lib/internal/_jsonStringifyArray.mjs.map +1 -0
- package/lib/internal/_jsonStringifyElement.d.ts +1 -0
- package/lib/internal/_jsonStringifyElement.js +23 -0
- package/lib/internal/_jsonStringifyElement.js.map +1 -0
- package/lib/internal/_jsonStringifyElement.mjs +23 -0
- package/lib/internal/_jsonStringifyElement.mjs.map +1 -0
- package/lib/internal/_jsonStringifyProperty.d.ts +1 -0
- package/lib/internal/_jsonStringifyProperty.js +31 -0
- package/lib/internal/_jsonStringifyProperty.js.map +1 -0
- package/lib/internal/_jsonStringifyProperty.mjs +31 -0
- package/lib/internal/_jsonStringifyProperty.mjs.map +1 -0
- package/lib/internal/_llmApplicationFinalize.js +1 -1
- package/lib/internal/_llmApplicationFinalize.js.map +1 -1
- package/lib/internal/_llmApplicationFinalize.mjs +1 -1
- package/lib/internal/_llmApplicationFinalize.mjs.map +1 -1
- package/lib/internal/_randomArray.js +37 -4
- package/lib/internal/_randomArray.js.map +1 -1
- package/lib/internal/_randomArray.mjs +16 -3
- package/lib/internal/_randomArray.mjs.map +1 -1
- package/lib/internal/_randomFormatByte.js +28 -2
- package/lib/internal/_randomFormatByte.js.map +1 -1
- package/lib/internal/_randomFormatByte.mjs +22 -3
- package/lib/internal/_randomFormatByte.mjs.map +1 -1
- package/lib/internal/_randomFormatDate.d.ts +3 -6
- package/lib/internal/_randomFormatDate.js +2 -10
- package/lib/internal/_randomFormatDate.js.map +1 -1
- package/lib/internal/_randomFormatDate.mjs +2 -6
- package/lib/internal/_randomFormatDate.mjs.map +1 -1
- package/lib/internal/_randomFormatDatetime.d.ts +3 -6
- package/lib/internal/_randomFormatDatetime.js +25 -8
- package/lib/internal/_randomFormatDatetime.js.map +1 -1
- package/lib/internal/_randomFormatDatetime.mjs +17 -7
- package/lib/internal/_randomFormatDatetime.mjs.map +1 -1
- package/lib/internal/_randomFormatDuration.js +23 -15
- package/lib/internal/_randomFormatDuration.js.map +1 -1
- package/lib/internal/_randomFormatDuration.mjs +23 -15
- package/lib/internal/_randomFormatDuration.mjs.map +1 -1
- package/lib/internal/_randomFormatHostname.d.ts +2 -2
- package/lib/internal/_randomFormatHostname.js +2 -2
- package/lib/internal/_randomFormatHostname.mjs +2 -2
- package/lib/internal/_randomFormatHostname.mjs.map +1 -1
- package/lib/internal/_randomFormatIdnHostname.js +9 -10
- package/lib/internal/_randomFormatIdnHostname.js.map +1 -1
- package/lib/internal/_randomFormatIdnHostname.mjs +3 -4
- package/lib/internal/_randomFormatIdnHostname.mjs.map +1 -1
- package/lib/internal/_randomFormatIpv4.js +31 -1
- package/lib/internal/_randomFormatIpv4.js.map +1 -1
- package/lib/internal/_randomFormatIpv4.mjs +23 -2
- package/lib/internal/_randomFormatIpv4.mjs.map +1 -1
- package/lib/internal/_randomFormatIpv6.js +57 -1
- package/lib/internal/_randomFormatIpv6.js.map +1 -1
- package/lib/internal/_randomFormatIpv6.mjs +45 -2
- package/lib/internal/_randomFormatIpv6.mjs.map +1 -1
- package/lib/internal/_randomFormatJsonPointer.js +14 -2
- package/lib/internal/_randomFormatJsonPointer.js.map +1 -1
- package/lib/internal/_randomFormatJsonPointer.mjs +13 -3
- package/lib/internal/_randomFormatJsonPointer.mjs.map +1 -1
- package/lib/internal/_randomFormatRegex.js +15 -2
- package/lib/internal/_randomFormatRegex.js.map +1 -1
- package/lib/internal/_randomFormatRegex.mjs +14 -3
- package/lib/internal/_randomFormatRegex.mjs.map +1 -1
- package/lib/internal/_randomFormatRelativeJsonPointer.js +19 -5
- package/lib/internal/_randomFormatRelativeJsonPointer.js.map +1 -1
- package/lib/internal/_randomFormatRelativeJsonPointer.mjs +21 -6
- package/lib/internal/_randomFormatRelativeJsonPointer.mjs.map +1 -1
- package/lib/internal/_randomFormatTime.js +38 -7
- package/lib/internal/_randomFormatTime.js.map +1 -1
- package/lib/internal/_randomFormatTime.mjs +40 -5
- package/lib/internal/_randomFormatTime.mjs.map +1 -1
- package/lib/internal/_randomPattern.js.map +1 -1
- package/lib/internal/_randomPattern.mjs.map +1 -1
- package/lib/internal/_randomStringLength.d.ts +41 -10
- package/lib/internal/_randomStringLength.js +49 -13
- package/lib/internal/_randomStringLength.js.map +1 -1
- package/lib/internal/_randomStringLength.mjs +48 -13
- package/lib/internal/_randomStringLength.mjs.map +1 -1
- package/lib/internal/private/__notationRename.js.map +1 -1
- package/lib/internal/private/__notationRename.mjs.map +1 -1
- package/lib/internal/private/__randomComposition.d.ts +31 -0
- package/lib/internal/private/__randomComposition.js +68 -0
- package/lib/internal/private/__randomComposition.js.map +1 -0
- package/lib/internal/private/__randomComposition.mjs +71 -0
- package/lib/internal/private/__randomComposition.mjs.map +1 -0
- package/lib/internal/private/__randomEpoch.d.ts +19 -0
- package/lib/internal/private/__randomEpoch.js +31 -0
- package/lib/internal/private/__randomEpoch.js.map +1 -0
- package/lib/internal/private/__randomEpoch.mjs +28 -0
- package/lib/internal/private/__randomEpoch.mjs.map +1 -0
- package/lib/json.d.ts +2 -2
- package/lib/json.js.map +1 -1
- package/lib/json.mjs.map +1 -1
- package/lib/module.d.ts +28 -13
- package/lib/module.js.map +1 -1
- package/lib/module.mjs.map +1 -1
- package/lib/notations.d.ts +4 -4
- package/lib/notations.js.map +1 -1
- package/lib/notations.mjs.map +1 -1
- package/lib/plain.d.ts +3 -3
- package/lib/plain.js.map +1 -1
- package/lib/plain.mjs.map +1 -1
- package/lib/protobuf.d.ts +2 -2
- package/lib/protobuf.js.map +1 -1
- package/lib/protobuf.mjs.map +1 -1
- package/native/cmd/ttsc-typia/assert_guard_factory_contract_test.go +17 -4
- package/native/cmd/ttsc-typia/build.go +3 -0
- package/native/cmd/ttsc-typia/callable_interface_function_semantics_transform_test.go +331 -0
- package/native/cmd/ttsc-typia/callable_type_literal_boundaries_transform_test.go +1184 -0
- package/native/cmd/ttsc-typia/compare_functional_union_membership_transform_test.go +434 -0
- package/native/cmd/ttsc-typia/compare_template_literal_union_transform_test.go +241 -0
- package/native/cmd/ttsc-typia/create_assert_error_factory_arity_test.go +309 -0
- package/native/cmd/ttsc-typia/default_library_spoof_native_identity_transform_test.go +216 -0
- package/native/cmd/ttsc-typia/json_schema_dynamic_key_determinism_transform_test.go +246 -0
- package/native/cmd/ttsc-typia/json_stringify_contextual_undefined_transform_test.go +556 -0
- package/native/cmd/ttsc-typia/lib_replacement_native_identity_transform_test.go +277 -0
- package/native/cmd/ttsc-typia/local_function_named_like_typia_operation_transform_test.go +185 -0
- package/native/cmd/ttsc-typia/native_named_intersection_union_transform_test.go +390 -0
- package/native/cmd/ttsc-typia/node_buffer_native_exports_is_transform_test.go +526 -0
- package/native/cmd/ttsc-typia/package_declaration_native_identity_is_transform_test.go +293 -0
- package/native/cmd/ttsc-typia/protobuf_diagnostic_code_transform_test.go +167 -0
- package/native/cmd/ttsc-typia/recursive_conditional_alias_name_transform_test.go +307 -0
- package/native/cmd/ttsc-typia/shadowed_typia_module_declaration_diagnostic_test.go +152 -0
- package/native/cmd/ttsc-typia/symbol_index_domain_transform_test.go +316 -0
- package/native/cmd/ttsc-typia/template_literal_type_tags_transform_test.go +1 -3
- package/native/cmd/ttsc-typia/transform.go +23 -0
- package/native/cmd/ttsc-typia/transform_helpers_test.go +166 -25
- package/native/cmd/ttsc-typia/user_global_native_identity_transform_test.go +484 -0
- package/native/core/factories/FormatCheatSheet.go +2 -2
- package/native/core/factories/MetadataCommentTagFactory.go +26 -11
- package/native/core/factories/ProtobufFactory.go +6 -1
- package/native/core/factories/factory_utility_coverage_test.go +896 -907
- package/native/core/factories/internal/metadata/MetadataHelper.go +190 -58
- package/native/core/factories/internal/metadata/emplace_metadata_object.go +25 -0
- package/native/core/factories/internal/metadata/iterate_metadata_function.go +1 -1
- package/native/core/factories/internal/metadata/iterate_metadata_intersection.go +103 -23
- package/native/core/factories/internal/metadata/iterate_metadata_map.go +3 -7
- package/native/core/factories/internal/metadata/iterate_metadata_native.go +32 -14
- package/native/core/factories/internal/metadata/iterate_metadata_set.go +3 -7
- package/native/core/factories/metadata_comment_tag_factory_coverage_test.go +2 -2
- package/native/core/programmers/RandomProgrammer.go +5 -2
- package/native/core/programmers/compare/CompareEqualProgrammer.go +27 -13
- package/native/core/programmers/helpers/FunctionProgrammer.go +6 -13
- package/native/core/programmers/helpers/StringifyJoinder.go +129 -50
- package/native/core/programmers/helpers/joiner_branch_coverage_test.go +116 -120
- package/native/core/programmers/iterate/iterate_check_coverage_test.go +76 -158
- package/native/core/programmers/iterate/iterate_utility_coverage_test.go +231 -270
- package/native/core/programmers/iterate/json_schema_object.go +49 -7
- package/native/core/programmers/iterate/json_schema_pattern_property_order_test.go +44 -0
- package/native/core/programmers/iterate/openapi_v3_downgrader.go +34 -1
- package/native/core/programmers/iterate/template_runtime_pattern.go +11 -0
- package/native/core/programmers/json/JsonStringifyProgrammer.go +47 -6
- package/native/core/programmers/llm/LlmApplicationProgrammer.go +9 -1
- package/native/core/programmers/protobuf/ProtobufMessageProgrammer.go +1 -1
- package/native/core/schemas/metadata/MetadataCollection.go +47 -14
- package/native/core/schemas/metadata/MetadataDefaultLibrary.go +81 -0
- package/native/core/schemas/metadata/MetadataObjectType.go +7 -18
- package/native/go.mod +4 -4
- package/native/transform/CallExpressionTransformer.go +167 -0
- package/native/transform/features/protobuf/ProtobufMessageTransformer.go +1 -1
- package/package.json +3 -7
- package/src/executable/FileSystemIdentity.ts +33 -0
- package/src/executable/TypiaGenerateWizard.ts +18 -12
- package/src/http.ts +18 -4
- package/src/internal/_ProtobufReader.ts +40 -11
- package/src/internal/_assertGuard.ts +13 -2
- package/src/internal/_isFormatIdnHostname.ts +5 -1
- package/src/internal/_isFormatTime.ts +19 -2
- package/src/internal/_jsonStringifyArray.ts +50 -0
- package/src/internal/_jsonStringifyElement.ts +19 -0
- package/src/internal/_jsonStringifyProperty.ts +30 -0
- package/src/internal/_llmApplicationFinalize.ts +6 -1
- package/src/internal/_randomArray.ts +42 -6
- package/src/internal/_randomFormatByte.ts +36 -4
- package/src/internal/_randomFormatDate.ts +4 -20
- package/src/internal/_randomFormatDatetime.ts +34 -20
- package/src/internal/_randomFormatDuration.ts +19 -4
- package/src/internal/_randomFormatHostname.ts +2 -2
- package/src/internal/_randomFormatIdnHostname.ts +8 -9
- package/src/internal/_randomFormatIpv4.ts +43 -3
- package/src/internal/_randomFormatIpv6.ts +67 -3
- package/src/internal/_randomFormatJsonPointer.ts +23 -3
- package/src/internal/_randomFormatRegex.ts +22 -6
- package/src/internal/_randomFormatRelativeJsonPointer.ts +23 -10
- package/src/internal/_randomFormatTime.ts +50 -12
- package/src/internal/_randomPattern.ts +4 -1
- package/src/internal/_randomStringLength.ts +61 -17
- package/src/internal/private/__notationRename.ts +1 -4
- package/src/internal/private/__randomComposition.ts +74 -0
- package/src/internal/private/__randomEpoch.ts +34 -0
- package/src/json.ts +16 -4
- package/src/module.ts +56 -22
- package/src/notations.ts +16 -4
- package/src/plain.ts +12 -3
- package/src/protobuf.ts +16 -4
- package/native/adapter/visit.go +0 -173
- package/native/adapter/visit_property_chain_edges_test.go +0 -129
- package/native/core/programmers/helpers/disable_function_programmer_declare.go +0 -10
- package/native/core/programmers/iterate/check_union_array_like.go +0 -422
- package/native/core/programmers/iterate/prune_object_properties.go +0 -105
- package/native/core/programmers/iterate/stringify_dynamic_properties.go +0 -219
- package/native/core/programmers/iterate/stringify_native.go +0 -14
- package/native/core/programmers/iterate/stringify_regular_properties.go +0 -112
- package/native/core/schemas/metadata/MetadataApplication.go +0 -41
|
@@ -1,21 +1,35 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
_ILengthProps,
|
|
3
|
+
_RANDOM_LENGTH_ERROR,
|
|
4
|
+
_randomLengthPick,
|
|
5
|
+
_randomLengthWindow,
|
|
6
|
+
} from "./_randomStringLength";
|
|
7
|
+
import { __randomDigits } from "./private/__randomComposition";
|
|
8
|
+
import { __IEpochProps, __randomEpoch } from "./private/__randomEpoch";
|
|
3
9
|
|
|
4
|
-
export const _randomFormatDatetime = (
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
maxLength
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
)
|
|
10
|
+
export const _randomFormatDatetime = (
|
|
11
|
+
props?: __IEpochProps & _ILengthProps,
|
|
12
|
+
) => {
|
|
13
|
+
const instant = (): string => new Date(__randomEpoch(props)).toISOString();
|
|
14
|
+
if (props?.minLength === undefined && props?.maxLength === undefined)
|
|
15
|
+
return instant();
|
|
16
|
+
// `YYYY-MM-DDTHH:MM:SS` plus `Z` is the shortest instant, and a fractional
|
|
17
|
+
// second grows it one digit at a time. Because that fraction needs both a dot
|
|
18
|
+
// and at least one digit, 21 is the single length between the two forms that
|
|
19
|
+
// no instant can have.
|
|
20
|
+
const window = _randomLengthWindow(props, {
|
|
21
|
+
minimum: SECONDS + 1,
|
|
22
|
+
spread: 8,
|
|
23
|
+
});
|
|
24
|
+
let length: number = _randomLengthPick(window);
|
|
25
|
+
if (length === SECONDS + 2)
|
|
26
|
+
length = window.high >= SECONDS + 3 ? SECONDS + 3 : SECONDS + 1;
|
|
27
|
+
if (length < window.low || length > window.high)
|
|
28
|
+
throw new Error(_RANDOM_LENGTH_ERROR);
|
|
29
|
+
const base: string = instant().substring(0, SECONDS);
|
|
30
|
+
return length === SECONDS + 1
|
|
31
|
+
? `${base}Z`
|
|
32
|
+
: `${base}.${__randomDigits(length - SECONDS - 2)}Z`;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const SECONDS = "0000-00-00T00:00:00".length;
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { _randomInteger } from "./_randomInteger";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
_ILengthProps,
|
|
4
|
+
_randomLengthPick,
|
|
5
|
+
_randomLengthWindow,
|
|
6
|
+
} from "./_randomStringLength";
|
|
7
|
+
import { __randomNumeric } from "./private/__randomComposition";
|
|
3
8
|
|
|
4
|
-
export const _randomFormatDuration = (props?: _ILengthProps): string =>
|
|
5
|
-
|
|
9
|
+
export const _randomFormatDuration = (props?: _ILengthProps): string => {
|
|
10
|
+
if (props?.minLength === undefined && props?.maxLength === undefined) {
|
|
6
11
|
const period: string = durate([
|
|
7
12
|
["Y", random(0, 100)],
|
|
8
13
|
["M", random(0, 12)],
|
|
@@ -15,7 +20,17 @@ export const _randomFormatDuration = (props?: _ILengthProps): string =>
|
|
|
15
20
|
]);
|
|
16
21
|
if (period.length + time.length === 0) return "PT0S";
|
|
17
22
|
return `P${period}${time.length ? "T" : ""}${time}`;
|
|
18
|
-
}
|
|
23
|
+
}
|
|
24
|
+
// A single designator carries an unbounded digit count, so `P<n>Y` expresses
|
|
25
|
+
// every length from three upward and `P1Y` is the shortest duration there is.
|
|
26
|
+
const length: number = _randomLengthPick(
|
|
27
|
+
_randomLengthWindow(props, { minimum: MINIMUM, spread: 6 }),
|
|
28
|
+
);
|
|
29
|
+
return `P${__randomNumeric(length - MINIMUM + 1)}Y`;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const MINIMUM = "P1Y".length;
|
|
33
|
+
|
|
19
34
|
const durate = (elements: [string, number][]) =>
|
|
20
35
|
elements
|
|
21
36
|
.filter(([_unit, value]) => value !== 0)
|
|
@@ -29,8 +29,8 @@ const pickLength = (props: _ILengthProps): number => {
|
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Builds dot-joined hostname labels totaling exactly `length` characters, each
|
|
32
|
-
* label within 63 chars. Shared with the idn-hostname generator, which
|
|
33
|
-
*
|
|
32
|
+
* label within 63 chars. Shared with the idn-hostname generator, which realizes
|
|
33
|
+
* its length the same way since #2317 gave the two formats one structure.
|
|
34
34
|
*/
|
|
35
35
|
export const _randomHostnameLabels = (length: number): string => {
|
|
36
36
|
const parts: string[] = [];
|
|
@@ -6,20 +6,19 @@ import { _ILengthProps } from "./_randomStringLength";
|
|
|
6
6
|
export const _randomFormatIdnHostname = (props?: _ILengthProps): string => {
|
|
7
7
|
if (props?.minLength === undefined && props?.maxLength === undefined)
|
|
8
8
|
return `${random(10)}.${random(3)}`;
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
|
|
14
|
-
return
|
|
9
|
+
// idn-hostname shares hostname's structure (a single label of 1..63 chars is
|
|
10
|
+
// valid, no dot or trailing label required), so the requested length is
|
|
11
|
+
// realized the same way: split it across dot-joined labels. #2317 dropped the
|
|
12
|
+
// mandatory dot and two-character trailing label this generator used to
|
|
13
|
+
// reserve, which is why it now realizes a length below four.
|
|
14
|
+
return _randomHostnameLabels(pickLength(props));
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
const MAX_TOTAL = 253;
|
|
18
|
-
const MIN_TOTAL = 4; // the shortest idn hostname, `x.yy`: label(1) + `.` + tld(2)
|
|
19
18
|
|
|
20
19
|
const pickLength = (props: _ILengthProps): number => {
|
|
21
|
-
let low: number = props.minLength === undefined ?
|
|
22
|
-
if (low <
|
|
20
|
+
let low: number = props.minLength === undefined ? 1 : props.minLength;
|
|
21
|
+
if (low < 1) low = 1;
|
|
23
22
|
const high: number =
|
|
24
23
|
props.maxLength === undefined
|
|
25
24
|
? Math.min(MAX_TOTAL, low + 14)
|
|
@@ -1,8 +1,37 @@
|
|
|
1
1
|
import { _randomInteger } from "./_randomInteger";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
_ILengthProps,
|
|
4
|
+
_randomLengthPick,
|
|
5
|
+
_randomLengthWindow,
|
|
6
|
+
} from "./_randomStringLength";
|
|
7
|
+
import { __randomComposition } from "./private/__randomComposition";
|
|
3
8
|
|
|
4
|
-
export const _randomFormatIpv4 = (props?: _ILengthProps): string =>
|
|
5
|
-
|
|
9
|
+
export const _randomFormatIpv4 = (props?: _ILengthProps): string => {
|
|
10
|
+
if (props?.minLength === undefined && props?.maxLength === undefined)
|
|
11
|
+
return new Array(4).fill(0).map(random).join(".");
|
|
12
|
+
// Three dots plus four octets of one to three digits: `0.0.0.0` is the
|
|
13
|
+
// shortest address and `255.255.255.255` the longest, and every length
|
|
14
|
+
// between them is reached by choosing how many digits each octet spends.
|
|
15
|
+
const length: number = _randomLengthPick(
|
|
16
|
+
_randomLengthWindow(props, {
|
|
17
|
+
minimum: 4 * DIGITS_MIN + DOTS,
|
|
18
|
+
maximum: 4 * DIGITS_MAX + DOTS,
|
|
19
|
+
spread: 8,
|
|
20
|
+
}),
|
|
21
|
+
);
|
|
22
|
+
return __randomComposition({
|
|
23
|
+
total: length - DOTS,
|
|
24
|
+
count: 4,
|
|
25
|
+
minimum: DIGITS_MIN,
|
|
26
|
+
maximum: DIGITS_MAX,
|
|
27
|
+
})
|
|
28
|
+
.map(octet)
|
|
29
|
+
.join(".");
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const DOTS = 3;
|
|
33
|
+
const DIGITS_MIN = 1;
|
|
34
|
+
const DIGITS_MAX = 3;
|
|
6
35
|
|
|
7
36
|
const random = () =>
|
|
8
37
|
_randomInteger({
|
|
@@ -10,3 +39,14 @@ const random = () =>
|
|
|
10
39
|
minimum: 0,
|
|
11
40
|
maximum: 255,
|
|
12
41
|
});
|
|
42
|
+
|
|
43
|
+
// An octet is bounded by 255, so a three-digit one starts at 100 and stops
|
|
44
|
+
// there rather than at 999.
|
|
45
|
+
const octet = (digits: number): string =>
|
|
46
|
+
String(
|
|
47
|
+
_randomInteger({
|
|
48
|
+
type: "integer",
|
|
49
|
+
minimum: digits === 1 ? 0 : Math.pow(10, digits - 1),
|
|
50
|
+
maximum: digits === 3 ? 255 : Math.pow(10, digits) - 1,
|
|
51
|
+
}),
|
|
52
|
+
);
|
|
@@ -1,8 +1,61 @@
|
|
|
1
|
+
import { _randomFormatIpv4 } from "./_randomFormatIpv4";
|
|
1
2
|
import { _randomInteger } from "./_randomInteger";
|
|
2
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
_ILengthProps,
|
|
5
|
+
_randomLengthPick,
|
|
6
|
+
_randomLengthWindow,
|
|
7
|
+
} from "./_randomStringLength";
|
|
8
|
+
import { __randomComposition } from "./private/__randomComposition";
|
|
3
9
|
|
|
4
|
-
export const _randomFormatIpv6 = (props?: _ILengthProps): string =>
|
|
5
|
-
|
|
10
|
+
export const _randomFormatIpv6 = (props?: _ILengthProps): string => {
|
|
11
|
+
if (props?.minLength === undefined && props?.maxLength === undefined)
|
|
12
|
+
return new Array(GROUPS).fill(0).map(random).join(":");
|
|
13
|
+
const length: number = _randomLengthPick(
|
|
14
|
+
_randomLengthWindow(props, {
|
|
15
|
+
minimum: SHORTEST,
|
|
16
|
+
maximum: LONGEST,
|
|
17
|
+
spread: 12,
|
|
18
|
+
}),
|
|
19
|
+
);
|
|
20
|
+
// `::` alone is the all-zero address, and the three forms below cover every
|
|
21
|
+
// length between it and the padded IPv4-suffixed address: a compressed prefix
|
|
22
|
+
// for the short ones, eight groups of one to four hexadecimal digits for the
|
|
23
|
+
// middle, and six groups plus a dotted-quad tail for the long ones.
|
|
24
|
+
if (length === SHORTEST) return "::";
|
|
25
|
+
if (length < GROUPS * DIGITS_MIN + COLONS) {
|
|
26
|
+
// `::` plus `count` groups spends one colon between each pair.
|
|
27
|
+
const count: number = Math.ceil((length - 1) / (DIGITS_MAX + 1));
|
|
28
|
+
return `::${compose(length - 1 - count, count)}`;
|
|
29
|
+
}
|
|
30
|
+
if (length <= GROUPS * DIGITS_MAX + COLONS)
|
|
31
|
+
return compose(length - COLONS, GROUPS);
|
|
32
|
+
// The dotted-quad tail is drawn at its longest so the six leading groups keep
|
|
33
|
+
// a composable number of digits.
|
|
34
|
+
const tail: string = _randomFormatIpv4({
|
|
35
|
+
minLength: IPV4_MAX,
|
|
36
|
+
maxLength: IPV4_MAX,
|
|
37
|
+
});
|
|
38
|
+
return `${compose(length - IPV4_MAX - EMBEDDED, EMBEDDED)}:${tail}`;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const GROUPS = 8;
|
|
42
|
+
const COLONS = GROUPS - 1;
|
|
43
|
+
const DIGITS_MIN = 1;
|
|
44
|
+
const DIGITS_MAX = 4;
|
|
45
|
+
const EMBEDDED = 6; // groups preceding a dotted-quad tail
|
|
46
|
+
const IPV4_MAX = "255.255.255.255".length;
|
|
47
|
+
const SHORTEST = "::".length;
|
|
48
|
+
const LONGEST = EMBEDDED * DIGITS_MAX + EMBEDDED + IPV4_MAX;
|
|
49
|
+
|
|
50
|
+
const compose = (digits: number, count: number): string =>
|
|
51
|
+
__randomComposition({
|
|
52
|
+
total: digits,
|
|
53
|
+
count,
|
|
54
|
+
minimum: DIGITS_MIN,
|
|
55
|
+
maximum: DIGITS_MAX,
|
|
56
|
+
})
|
|
57
|
+
.map(group)
|
|
58
|
+
.join(":");
|
|
6
59
|
|
|
7
60
|
const random = () =>
|
|
8
61
|
_randomInteger({
|
|
@@ -10,3 +63,14 @@ const random = () =>
|
|
|
10
63
|
minimum: 0,
|
|
11
64
|
maximum: 65_535,
|
|
12
65
|
}).toString(16);
|
|
66
|
+
|
|
67
|
+
const group = (digits: number): string => {
|
|
68
|
+
let text: string = "";
|
|
69
|
+
for (let i: number = 0; i < digits; ++i)
|
|
70
|
+
text += _randomInteger({
|
|
71
|
+
type: "integer",
|
|
72
|
+
minimum: 0,
|
|
73
|
+
maximum: 15,
|
|
74
|
+
}).toString(16);
|
|
75
|
+
return text;
|
|
76
|
+
};
|
|
@@ -1,13 +1,33 @@
|
|
|
1
1
|
import { _randomString } from "./_randomString";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
_ILengthProps,
|
|
4
|
+
_randomLengthPick,
|
|
5
|
+
_randomLengthWindow,
|
|
6
|
+
_randomSegmentLength,
|
|
7
|
+
} from "./_randomStringLength";
|
|
3
8
|
|
|
4
9
|
export const _randomFormatJsonPointer = (props?: _ILengthProps): string => {
|
|
5
10
|
if (props?.minLength === undefined && props?.maxLength === undefined)
|
|
6
|
-
return
|
|
11
|
+
return `${PREFIX}${random()}`;
|
|
7
12
|
// The `/components/schemas/` prefix (20 chars) is fixed; the reference token
|
|
8
13
|
// after it grows or shrinks to hit the requested length.
|
|
9
|
-
|
|
14
|
+
if (props.maxLength === undefined || props.maxLength >= PREFIX.length)
|
|
15
|
+
return `${PREFIX}${_randomSegmentLength(props, PREFIX.length, 10, 0)}`;
|
|
16
|
+
// Below that prefix a pointer still exists: the empty pointer addresses the
|
|
17
|
+
// whole document, and one `/`-prefixed token addresses a member of it.
|
|
18
|
+
const length: number = _randomLengthPick(
|
|
19
|
+
_randomLengthWindow(props, { minimum: 0, spread: 6 }),
|
|
20
|
+
);
|
|
21
|
+
return length === 0
|
|
22
|
+
? ""
|
|
23
|
+
: `/${_randomString({
|
|
24
|
+
type: "string",
|
|
25
|
+
minLength: length - 1,
|
|
26
|
+
maxLength: length - 1,
|
|
27
|
+
})}`;
|
|
10
28
|
};
|
|
11
29
|
|
|
30
|
+
const PREFIX = "/components/schemas/";
|
|
31
|
+
|
|
12
32
|
const random = () =>
|
|
13
33
|
_randomString({ type: "string", minLength: 10, maxLength: 10 });
|
|
@@ -1,7 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _randomString } from "./_randomString";
|
|
2
|
+
import {
|
|
3
|
+
_ILengthProps,
|
|
4
|
+
_randomLengthPick,
|
|
5
|
+
_randomLengthWindow,
|
|
6
|
+
} from "./_randomStringLength";
|
|
2
7
|
|
|
3
|
-
export const _randomFormatRegex = (props?: _ILengthProps): string =>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
+
export const _randomFormatRegex = (props?: _ILengthProps): string => {
|
|
9
|
+
// Every character `_randomString` emits is a literal in regular expression
|
|
10
|
+
// syntax, so a source of any length — including the empty source `new
|
|
11
|
+
// RegExp("")` accepts — compiles. An unconstrained draw is therefore an
|
|
12
|
+
// unconstrained string, and a constrained one fixes the length first.
|
|
13
|
+
if (props?.minLength === undefined && props?.maxLength === undefined)
|
|
14
|
+
return _randomString({ type: "string" });
|
|
15
|
+
const length: number = _randomLengthPick(
|
|
16
|
+
_randomLengthWindow(props, { minimum: 0, spread: 16 }),
|
|
17
|
+
);
|
|
18
|
+
return _randomString({
|
|
19
|
+
type: "string",
|
|
20
|
+
minLength: length,
|
|
21
|
+
maxLength: length,
|
|
22
|
+
});
|
|
23
|
+
};
|
|
@@ -1,15 +1,28 @@
|
|
|
1
1
|
import { _randomInteger } from "./_randomInteger";
|
|
2
|
-
import {
|
|
2
|
+
import { _randomString } from "./_randomString";
|
|
3
|
+
import {
|
|
4
|
+
_ILengthProps,
|
|
5
|
+
_randomLengthPick,
|
|
6
|
+
_randomLengthWindow,
|
|
7
|
+
} from "./_randomStringLength";
|
|
8
|
+
import { __randomNumeric } from "./private/__randomComposition";
|
|
3
9
|
|
|
4
10
|
export const _randomFormatRelativeJsonPointer = (
|
|
5
11
|
props?: _ILengthProps,
|
|
6
|
-
): string =>
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
})}#`,
|
|
12
|
+
): string => {
|
|
13
|
+
if (props?.minLength === undefined && props?.maxLength === undefined)
|
|
14
|
+
return `${_randomInteger({ type: "integer", minimum: 0, maximum: 10 })}#`;
|
|
15
|
+
// The leading non-negative integer stands alone as a pointer, so a single
|
|
16
|
+
// digit is the shortest form; `#` names the key and a `/`-prefixed token names
|
|
17
|
+
// a member, which absorbs any remaining length.
|
|
18
|
+
const length: number = _randomLengthPick(
|
|
19
|
+
_randomLengthWindow(props, { minimum: 1, spread: 6 }),
|
|
15
20
|
);
|
|
21
|
+
if (length === 1) return __randomNumeric(1);
|
|
22
|
+
if (length === 2) return `${__randomNumeric(1)}#`;
|
|
23
|
+
return `${__randomNumeric(1)}/${_randomString({
|
|
24
|
+
type: "string",
|
|
25
|
+
minLength: length - 2,
|
|
26
|
+
maxLength: length - 2,
|
|
27
|
+
})}`;
|
|
28
|
+
};
|
|
@@ -1,17 +1,55 @@
|
|
|
1
1
|
import { _randomInteger } from "./_randomInteger";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
_ILengthProps,
|
|
4
|
+
_RANDOM_LENGTH_ERROR,
|
|
5
|
+
_randomLengthPick,
|
|
6
|
+
_randomLengthWindow,
|
|
7
|
+
} from "./_randomStringLength";
|
|
8
|
+
import { __randomDigits } from "./private/__randomComposition";
|
|
3
9
|
|
|
4
|
-
export const _randomFormatTime = (props?: _ILengthProps): string =>
|
|
5
|
-
|
|
10
|
+
export const _randomFormatTime = (props?: _ILengthProps): string => {
|
|
11
|
+
const clock = (): string =>
|
|
6
12
|
new Date(
|
|
7
|
-
_randomInteger({
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
_randomInteger({ type: "integer", minimum: 0, maximum: DAY }),
|
|
14
|
+
).toISOString();
|
|
15
|
+
if (props?.minLength === undefined && props?.maxLength === undefined)
|
|
16
|
+
return clock().substring(11);
|
|
17
|
+
// `HH:MM:SS` carries a mandatory offset — one character as `Z`, six as
|
|
18
|
+
// `+HH:MM` — and an optional fraction between them that RFC 3339 leaves
|
|
19
|
+
// open above. Together they express 9 and every length from 11 upward; 10 is
|
|
20
|
+
// the one gap, because a fraction needs both a dot and a digit.
|
|
21
|
+
const window = _randomLengthWindow(props, {
|
|
22
|
+
minimum: CLOCK + 1,
|
|
23
|
+
spread: 6,
|
|
24
|
+
});
|
|
25
|
+
let length: number = _randomLengthPick(window);
|
|
26
|
+
if (length === CLOCK + 2)
|
|
27
|
+
length = window.high >= CLOCK + 3 ? CLOCK + 3 : CLOCK + 1;
|
|
28
|
+
if (length < window.low || length > window.high)
|
|
29
|
+
throw new Error(_RANDOM_LENGTH_ERROR);
|
|
30
|
+
const base: string = clock().substring(11, 11 + CLOCK);
|
|
31
|
+
if (length === CLOCK + 1) return `${base}Z`;
|
|
32
|
+
// The `Z` form reaches every remaining length by itself, so the numeric
|
|
33
|
+
// offset is a choice rather than a fallback: it spends six characters, which
|
|
34
|
+
// leaves either nothing (14, `HH:MM:SS+HH:MM`) or a whole fraction (16 and
|
|
35
|
+
// up). At 15 only the `Z` form fits, since the offset would demand a dot
|
|
36
|
+
// with no digit after it.
|
|
37
|
+
const fraction: number = length - CLOCK - OFFSET - 1;
|
|
38
|
+
return (fraction === -1 || fraction >= 1) &&
|
|
39
|
+
_randomInteger({ type: "integer", minimum: 0, maximum: 1 }) === 1
|
|
40
|
+
? fraction === -1
|
|
41
|
+
? `${base}${offset()}`
|
|
42
|
+
: `${base}.${__randomDigits(fraction)}${offset()}`
|
|
43
|
+
: `${base}.${__randomDigits(length - CLOCK - 2)}Z`;
|
|
44
|
+
};
|
|
16
45
|
|
|
17
46
|
const DAY = 86_400_000;
|
|
47
|
+
const CLOCK = "00:00:00".length;
|
|
48
|
+
const OFFSET = "+00:00".length;
|
|
49
|
+
|
|
50
|
+
const offset = (): string =>
|
|
51
|
+
`${_randomInteger({ type: "integer", minimum: 0, maximum: 1 }) === 0 ? "+" : "-"}${pad(
|
|
52
|
+
_randomInteger({ type: "integer", minimum: 0, maximum: 23 }),
|
|
53
|
+
)}:${pad(_randomInteger({ type: "integer", minimum: 0, maximum: 59 }))}`;
|
|
54
|
+
|
|
55
|
+
const pad = (value: number): string => String(value).padStart(2, "0");
|
|
@@ -2,7 +2,10 @@ import RandExp from "randexp";
|
|
|
2
2
|
|
|
3
3
|
import { _ILengthProps } from "./_randomStringLength";
|
|
4
4
|
|
|
5
|
-
export const _randomPattern = (
|
|
5
|
+
export const _randomPattern = (
|
|
6
|
+
regex: RegExp,
|
|
7
|
+
props?: _ILengthProps,
|
|
8
|
+
): string => {
|
|
6
9
|
const r: RandExp = new RandExp(regex);
|
|
7
10
|
const min: number | undefined = props?.minLength;
|
|
8
11
|
const max: number | undefined = props?.maxLength;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import { _randomInteger } from "./_randomInteger";
|
|
1
2
|
import { _randomString } from "./_randomString";
|
|
2
3
|
|
|
4
|
+
export const _RANDOM_LENGTH_ERROR =
|
|
5
|
+
"unable to generate a random string satisfying both the format and the length constraints.";
|
|
6
|
+
|
|
3
7
|
/**
|
|
4
8
|
* Length bounds forwarded to a string format or pattern generator.
|
|
5
9
|
*
|
|
@@ -18,10 +22,10 @@ export interface _ILengthProps {
|
|
|
18
22
|
* length `fixed + segment.length` lands inside the requested window.
|
|
19
23
|
*
|
|
20
24
|
* `fixed` is the number of characters the format always contributes around the
|
|
21
|
-
* segment, `fallback` is the segment length used when the leaf is
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
+
* segment, `fallback` is the segment length used when the leaf is unconstrained
|
|
26
|
+
* on that side, and `minimum` is the smallest segment the format still
|
|
27
|
+
* validates with. Throws when the window cannot be satisfied by this format's
|
|
28
|
+
* shape (e.g. `Format<"email"> & MaxLength<3>`).
|
|
25
29
|
*/
|
|
26
30
|
export const _randomSegmentLength = (
|
|
27
31
|
props: _ILengthProps | undefined,
|
|
@@ -36,21 +40,63 @@ export const _randomSegmentLength = (
|
|
|
36
40
|
// characters so the generated length varies, mirroring `_randomString`.
|
|
37
41
|
const high: number =
|
|
38
42
|
props?.maxLength === undefined ? low + fallback : props.maxLength - fixed;
|
|
39
|
-
if (high < low || high < minimum)
|
|
40
|
-
throw new Error(
|
|
41
|
-
"unable to generate a random string satisfying both the format and the length constraints.",
|
|
42
|
-
);
|
|
43
|
+
if (high < low || high < minimum) throw new Error(_RANDOM_LENGTH_ERROR);
|
|
43
44
|
return _randomString({ type: "string", minLength: low, maxLength: high });
|
|
44
45
|
};
|
|
45
46
|
|
|
46
47
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
48
|
+
* Intersects the requested length window with the lengths a format's grammar
|
|
49
|
+
* can express, and draws one of them.
|
|
50
|
+
*
|
|
51
|
+
* `minimum` and `maximum` are the shortest and longest values the format admits
|
|
52
|
+
* — omit `maximum` when the grammar is open above — and `spread` is how far
|
|
53
|
+
* past the floor an unbounded request may reach, so an open side still varies
|
|
54
|
+
* the way `_randomString` does. The caller draws from the returned window and
|
|
55
|
+
* applies whatever step its grammar has (base64 lengths are multiples of four,
|
|
56
|
+
* a fractional second needs at least one digit).
|
|
57
|
+
*
|
|
58
|
+
* Throws only when the window and the grammar do not overlap at all. That is
|
|
59
|
+
* the distinction the retry driver below cannot make: it redraws one shape, so
|
|
60
|
+
* it gives up on every length that shape never emits even when the format
|
|
61
|
+
* itself accepts one (issue #2284).
|
|
62
|
+
*/
|
|
63
|
+
export const _randomLengthWindow = (
|
|
64
|
+
props: _ILengthProps | undefined,
|
|
65
|
+
format: { minimum: number; maximum?: number; spread?: number },
|
|
66
|
+
): { low: number; high: number } => {
|
|
67
|
+
const ceiling: number = format.maximum ?? Number.MAX_SAFE_INTEGER;
|
|
68
|
+
const low: number = Math.max(
|
|
69
|
+
props?.minLength ?? format.minimum,
|
|
70
|
+
format.minimum,
|
|
71
|
+
);
|
|
72
|
+
const high: number = Math.min(
|
|
73
|
+
props?.maxLength ?? low + (format.spread ?? 0),
|
|
74
|
+
ceiling,
|
|
75
|
+
);
|
|
76
|
+
if (low > high) throw new Error(_RANDOM_LENGTH_ERROR);
|
|
77
|
+
return { low, high };
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/** Draws a length inside a window produced by {@link _randomLengthWindow}. */
|
|
81
|
+
export const _randomLengthPick = (window: {
|
|
82
|
+
low: number;
|
|
83
|
+
high: number;
|
|
84
|
+
}): number =>
|
|
85
|
+
_randomInteger({
|
|
86
|
+
type: "integer",
|
|
87
|
+
minimum: window.low,
|
|
88
|
+
maximum: window.high,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Wraps a fixed-length format generator (uuid, date) with the requested length
|
|
93
|
+
* window.
|
|
49
94
|
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
95
|
+
* Use it only where the grammar admits exactly one length, so a window that
|
|
96
|
+
* excludes it is genuinely unsatisfiable. A format that can express more than
|
|
97
|
+
* one length must build its value at a length drawn from
|
|
98
|
+
* {@link _randomLengthWindow} instead; redrawing one shape cannot reach a length
|
|
99
|
+
* that shape never emits.
|
|
54
100
|
*/
|
|
55
101
|
export const _randomFormatLength = (
|
|
56
102
|
props: _ILengthProps | undefined,
|
|
@@ -66,7 +112,5 @@ export const _randomFormatLength = (
|
|
|
66
112
|
)
|
|
67
113
|
return value;
|
|
68
114
|
}
|
|
69
|
-
throw new Error(
|
|
70
|
-
"unable to generate a random string satisfying both the format and the length constraints.",
|
|
71
|
-
);
|
|
115
|
+
throw new Error(_RANDOM_LENGTH_ERROR);
|
|
72
116
|
};
|
|
@@ -9,10 +9,7 @@
|
|
|
9
9
|
* collapsing it to the underscore-free `plain` path.
|
|
10
10
|
*/
|
|
11
11
|
export const __notationRename =
|
|
12
|
-
(props: {
|
|
13
|
-
plain: (str: string) => string;
|
|
14
|
-
snake: (str: string) => string;
|
|
15
|
-
}) =>
|
|
12
|
+
(props: { plain: (str: string) => string; snake: (str: string) => string }) =>
|
|
16
13
|
(str: string): string => {
|
|
17
14
|
let prefix: string = "";
|
|
18
15
|
while (str.startsWith("_")) {
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { _randomInteger } from "../_randomInteger";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Splits `total` into `count` parts, each inside `[minimum, maximum]`.
|
|
5
|
+
*
|
|
6
|
+
* Used where a format's length is the sum of its segments — an IPv4 octet spans
|
|
7
|
+
* one to three digits, an IPv6 group one to four — so a requested total length
|
|
8
|
+
* is realized by choosing how many characters each segment contributes instead
|
|
9
|
+
* of redrawing whole addresses and hoping one lands in the window (issue
|
|
10
|
+
* #2284).
|
|
11
|
+
*
|
|
12
|
+
* The caller guarantees `count * minimum <= total <= count * maximum`; each
|
|
13
|
+
* part is drawn from the range that still leaves the remaining parts
|
|
14
|
+
* satisfiable.
|
|
15
|
+
*/
|
|
16
|
+
export const __randomComposition = (props: {
|
|
17
|
+
total: number;
|
|
18
|
+
count: number;
|
|
19
|
+
minimum: number;
|
|
20
|
+
maximum: number;
|
|
21
|
+
}): number[] => {
|
|
22
|
+
const parts: number[] = [];
|
|
23
|
+
let remaining: number = props.total;
|
|
24
|
+
for (let i: number = 0; i < props.count; ++i) {
|
|
25
|
+
const rest: number = props.count - i - 1;
|
|
26
|
+
const value: number = _randomInteger({
|
|
27
|
+
type: "integer",
|
|
28
|
+
minimum: Math.max(props.minimum, remaining - rest * props.maximum),
|
|
29
|
+
maximum: Math.min(props.maximum, remaining - rest * props.minimum),
|
|
30
|
+
});
|
|
31
|
+
parts.push(value);
|
|
32
|
+
remaining -= value;
|
|
33
|
+
}
|
|
34
|
+
return parts;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Draws `length` characters of the base64 alphabet.
|
|
39
|
+
*
|
|
40
|
+
* The caller passes a multiple of four, which `format: "byte"` accepts without
|
|
41
|
+
* padding; every character below is in the alphabet its validator spells out,
|
|
42
|
+
* so the result needs no encoding step.
|
|
43
|
+
*/
|
|
44
|
+
export const __randomBase64 = (length: number): string => {
|
|
45
|
+
let text: string = "";
|
|
46
|
+
for (let i: number = 0; i < length; ++i)
|
|
47
|
+
text +=
|
|
48
|
+
BASE64[
|
|
49
|
+
_randomInteger({
|
|
50
|
+
type: "integer",
|
|
51
|
+
minimum: 0,
|
|
52
|
+
maximum: BASE64.length - 1,
|
|
53
|
+
})
|
|
54
|
+
];
|
|
55
|
+
return text;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const BASE64 =
|
|
59
|
+
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
60
|
+
|
|
61
|
+
/** Draws `length` decimal digits, leading zeros included. */
|
|
62
|
+
export const __randomDigits = (length: number): string => {
|
|
63
|
+
let text: string = "";
|
|
64
|
+
for (let i: number = 0; i < length; ++i)
|
|
65
|
+
text += String(_randomInteger({ type: "integer", minimum: 0, maximum: 9 }));
|
|
66
|
+
return text;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/** Draws a decimal number of exactly `length` digits without a leading zero. */
|
|
70
|
+
export const __randomNumeric = (length: number): string =>
|
|
71
|
+
length <= 1
|
|
72
|
+
? String(_randomInteger({ type: "integer", minimum: 0, maximum: 9 }))
|
|
73
|
+
: String(_randomInteger({ type: "integer", minimum: 1, maximum: 9 })) +
|
|
74
|
+
__randomDigits(length - 1);
|