typia 13.1.1 → 13.2.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/README.md +3 -0
- package/lib/_virtual/_rolldown/runtime.mjs +1 -5
- package/lib/executable/FileSystemIdentity.d.ts +44 -0
- package/lib/executable/FileSystemIdentity.js +213 -0
- package/lib/executable/FileSystemIdentity.js.map +1 -0
- package/lib/executable/FileSystemIdentity.mjs +133 -0
- package/lib/executable/FileSystemIdentity.mjs.map +1 -0
- package/lib/executable/TypiaGenerateWizard.js +272 -106
- package/lib/executable/TypiaGenerateWizard.js.map +1 -1
- package/lib/executable/TypiaGenerateWizard.mjs +239 -95
- package/lib/executable/TypiaGenerateWizard.mjs.map +1 -1
- package/lib/functional.d.ts +15 -12
- package/lib/functional.js.map +1 -1
- package/lib/functional.mjs.map +1 -1
- package/lib/internal/_ProtobufReader.d.ts +32 -0
- package/lib/internal/_ProtobufReader.js +148 -48
- package/lib/internal/_ProtobufReader.js.map +1 -1
- package/lib/internal/_ProtobufReader.mjs +137 -41
- package/lib/internal/_ProtobufReader.mjs.map +1 -1
- package/lib/internal/_createStandardSchema.js +18 -1
- package/lib/internal/_createStandardSchema.js.map +1 -1
- package/lib/internal/_createStandardSchema.mjs +12 -1
- package/lib/internal/_createStandardSchema.mjs.map +1 -1
- package/lib/internal/_decimal.d.ts +14 -0
- package/lib/internal/_decimal.js +61 -0
- package/lib/internal/_decimal.js.map +1 -0
- package/lib/internal/_decimal.mjs +49 -0
- package/lib/internal/_decimal.mjs.map +1 -0
- package/lib/internal/_httpQueryParseURLSearchParams.js +23 -2
- package/lib/internal/_httpQueryParseURLSearchParams.js.map +1 -1
- package/lib/internal/_httpQueryParseURLSearchParams.mjs +20 -2
- package/lib/internal/_httpQueryParseURLSearchParams.mjs.map +1 -1
- package/lib/internal/_isFormatByte.js +2 -5
- package/lib/internal/_isFormatByte.js.map +1 -1
- package/lib/internal/_isFormatByte.mjs +2 -5
- package/lib/internal/_isFormatByte.mjs.map +1 -1
- package/lib/internal/_isFormatDate.js +15 -2
- package/lib/internal/_isFormatDate.js.map +1 -1
- package/lib/internal/_isFormatDate.mjs +22 -2
- package/lib/internal/_isFormatDate.mjs.map +1 -1
- package/lib/internal/_isFormatDateTime.js +21 -2
- package/lib/internal/_isFormatDateTime.js.map +1 -1
- package/lib/internal/_isFormatDateTime.mjs +13 -2
- package/lib/internal/_isFormatDateTime.mjs.map +1 -1
- package/lib/internal/_isFormatIri.js +3 -2
- package/lib/internal/_isFormatIri.js.map +1 -1
- package/lib/internal/_isFormatIri.mjs +3 -2
- package/lib/internal/_isFormatIri.mjs.map +1 -1
- package/lib/internal/_isFormatIriReference.js +10 -2
- package/lib/internal/_isFormatIriReference.js.map +1 -1
- package/lib/internal/_isFormatIriReference.mjs +9 -2
- package/lib/internal/_isFormatIriReference.mjs.map +1 -1
- package/lib/internal/_isFormatUriReference.js +1 -1
- package/lib/internal/_isFormatUriReference.js.map +1 -1
- package/lib/internal/_isFormatUriReference.mjs +1 -1
- package/lib/internal/_isFormatUriReference.mjs.map +1 -1
- package/lib/internal/_isMultipleOf.d.ts +1 -0
- package/lib/internal/_isMultipleOf.js +13 -0
- package/lib/internal/_isMultipleOf.js.map +1 -0
- package/lib/internal/_isMultipleOf.mjs +12 -0
- package/lib/internal/_isMultipleOf.mjs.map +1 -0
- package/lib/internal/_isTypeFloat.js +1 -1
- package/lib/internal/_isTypeFloat.js.map +1 -1
- package/lib/internal/_isTypeFloat.mjs +1 -1
- package/lib/internal/_isTypeFloat.mjs.map +1 -1
- package/lib/internal/_isTypeInt64.js +1 -0
- package/lib/internal/_isTypeInt64.js.map +1 -1
- package/lib/internal/_isTypeInt64.mjs.map +1 -1
- package/lib/internal/_isTypeInt64Bigint.d.ts +1 -0
- package/lib/internal/_isTypeInt64Bigint.js +15 -0
- package/lib/internal/_isTypeInt64Bigint.js.map +1 -0
- package/lib/internal/_isTypeInt64Bigint.mjs +8 -0
- package/lib/internal/_isTypeInt64Bigint.mjs.map +1 -0
- package/lib/internal/_isTypeUint64.js +1 -0
- package/lib/internal/_isTypeUint64.js.map +1 -1
- package/lib/internal/_isTypeUint64.mjs.map +1 -1
- package/lib/internal/_isTypeUint64Bigint.d.ts +1 -0
- package/lib/internal/_isTypeUint64Bigint.js +10 -0
- package/lib/internal/_isTypeUint64Bigint.js.map +1 -0
- package/lib/internal/_isTypeUint64Bigint.mjs +8 -0
- package/lib/internal/_isTypeUint64Bigint.mjs.map +1 -0
- package/lib/internal/_isUniqueItems.js +96 -109
- package/lib/internal/_isUniqueItems.js.map +1 -1
- package/lib/internal/_isUniqueItems.mjs +62 -50
- package/lib/internal/_isUniqueItems.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/_notationAny.js +8 -1
- package/lib/internal/_notationAny.js.map +1 -1
- package/lib/internal/_notationAny.mjs +7 -1
- package/lib/internal/_notationAny.mjs.map +1 -1
- package/lib/internal/_notationAssign.d.ts +1 -0
- package/lib/internal/_notationAssign.js +18 -0
- package/lib/internal/_notationAssign.js.map +1 -0
- package/lib/internal/_notationAssign.mjs +17 -0
- package/lib/internal/_notationAssign.mjs.map +1 -0
- package/lib/internal/_notationCamel.js +30 -9
- package/lib/internal/_notationCamel.js.map +1 -1
- package/lib/internal/_notationCamel.mjs +13 -5
- package/lib/internal/_notationCamel.mjs.map +1 -1
- package/lib/internal/_notationKebab.d.ts +1 -0
- package/lib/internal/_notationKebab.js +15 -0
- package/lib/internal/_notationKebab.js.map +1 -0
- package/lib/internal/_notationKebab.mjs +15 -0
- package/lib/internal/_notationKebab.mjs.map +1 -0
- package/lib/internal/_notationKeyCollision.d.ts +1 -0
- package/lib/internal/_notationKeyCollision.js +8 -0
- package/lib/internal/_notationKeyCollision.js.map +1 -0
- package/lib/internal/_notationKeyCollision.mjs +8 -0
- package/lib/internal/_notationKeyCollision.mjs.map +1 -0
- package/lib/internal/_notationPascal.js +20 -5
- package/lib/internal/_notationPascal.js.map +1 -1
- package/lib/internal/_notationPascal.mjs +10 -5
- package/lib/internal/_notationPascal.mjs.map +1 -1
- package/lib/internal/_notationSnake.js +25 -22
- package/lib/internal/_notationSnake.js.map +1 -1
- package/lib/internal/_notationSnake.mjs +11 -11
- package/lib/internal/_notationSnake.mjs.map +1 -1
- package/lib/internal/_plainCloneAny.js +174 -38
- package/lib/internal/_plainCloneAny.js.map +1 -1
- package/lib/internal/_plainCloneAny.mjs +126 -22
- package/lib/internal/_plainCloneAny.mjs.map +1 -1
- package/lib/internal/_randomArray.d.ts +1 -1
- package/lib/internal/_randomArray.js +11 -4
- package/lib/internal/_randomArray.js.map +1 -1
- package/lib/internal/_randomArray.mjs +9 -3
- package/lib/internal/_randomArray.mjs.map +1 -1
- package/lib/internal/_randomFormatByte.d.ts +2 -1
- package/lib/internal/_randomFormatByte.js +25 -1
- package/lib/internal/_randomFormatByte.js.map +1 -1
- package/lib/internal/_randomFormatByte.mjs +20 -1
- package/lib/internal/_randomFormatByte.mjs.map +1 -1
- package/lib/internal/_randomFormatDate.d.ts +3 -4
- package/lib/internal/_randomFormatDate.js +3 -10
- package/lib/internal/_randomFormatDate.js.map +1 -1
- package/lib/internal/_randomFormatDate.mjs +3 -6
- package/lib/internal/_randomFormatDate.mjs.map +1 -1
- package/lib/internal/_randomFormatDatetime.d.ts +3 -4
- package/lib/internal/_randomFormatDatetime.js +26 -8
- package/lib/internal/_randomFormatDatetime.js.map +1 -1
- package/lib/internal/_randomFormatDatetime.mjs +17 -6
- package/lib/internal/_randomFormatDatetime.mjs.map +1 -1
- package/lib/internal/_randomFormatDuration.d.ts +2 -1
- package/lib/internal/_randomFormatDuration.js +23 -14
- package/lib/internal/_randomFormatDuration.js.map +1 -1
- package/lib/internal/_randomFormatDuration.mjs +22 -13
- package/lib/internal/_randomFormatDuration.mjs.map +1 -1
- package/lib/internal/_randomFormatEmail.d.ts +2 -1
- package/lib/internal/_randomFormatEmail.js +8 -1
- package/lib/internal/_randomFormatEmail.js.map +1 -1
- package/lib/internal/_randomFormatEmail.mjs +5 -1
- package/lib/internal/_randomFormatEmail.mjs.map +1 -1
- package/lib/internal/_randomFormatHostname.d.ts +8 -1
- package/lib/internal/_randomFormatHostname.js +45 -2
- package/lib/internal/_randomFormatHostname.js.map +1 -1
- package/lib/internal/_randomFormatHostname.mjs +38 -2
- package/lib/internal/_randomFormatHostname.mjs.map +1 -1
- package/lib/internal/_randomFormatIdnEmail.d.ts +2 -1
- package/lib/internal/_randomFormatIdnEmail.js +16 -2
- package/lib/internal/_randomFormatIdnEmail.js.map +1 -1
- package/lib/internal/_randomFormatIdnEmail.mjs +11 -2
- package/lib/internal/_randomFormatIdnEmail.mjs.map +1 -1
- package/lib/internal/_randomFormatIdnHostname.d.ts +2 -1
- package/lib/internal/_randomFormatIdnHostname.js +26 -1
- package/lib/internal/_randomFormatIdnHostname.js.map +1 -1
- package/lib/internal/_randomFormatIdnHostname.mjs +25 -2
- package/lib/internal/_randomFormatIdnHostname.mjs.map +1 -1
- package/lib/internal/_randomFormatIpv4.d.ts +2 -1
- package/lib/internal/_randomFormatIpv4.js +32 -1
- package/lib/internal/_randomFormatIpv4.js.map +1 -1
- package/lib/internal/_randomFormatIpv4.mjs +23 -1
- package/lib/internal/_randomFormatIpv4.mjs.map +1 -1
- package/lib/internal/_randomFormatIpv6.d.ts +2 -1
- package/lib/internal/_randomFormatIpv6.js +58 -1
- package/lib/internal/_randomFormatIpv6.js.map +1 -1
- package/lib/internal/_randomFormatIpv6.mjs +45 -1
- package/lib/internal/_randomFormatIpv6.mjs.map +1 -1
- package/lib/internal/_randomFormatIri.d.ts +2 -1
- package/lib/internal/_randomFormatIri.js +1 -1
- package/lib/internal/_randomFormatIri.js.map +1 -1
- package/lib/internal/_randomFormatIri.mjs +1 -1
- package/lib/internal/_randomFormatIri.mjs.map +1 -1
- package/lib/internal/_randomFormatIriReference.d.ts +2 -1
- package/lib/internal/_randomFormatIriReference.js +1 -1
- package/lib/internal/_randomFormatIriReference.js.map +1 -1
- package/lib/internal/_randomFormatIriReference.mjs +1 -1
- package/lib/internal/_randomFormatIriReference.mjs.map +1 -1
- package/lib/internal/_randomFormatJsonPointer.d.ts +2 -1
- package/lib/internal/_randomFormatJsonPointer.js +20 -1
- package/lib/internal/_randomFormatJsonPointer.js.map +1 -1
- package/lib/internal/_randomFormatJsonPointer.mjs +15 -1
- package/lib/internal/_randomFormatJsonPointer.mjs.map +1 -1
- package/lib/internal/_randomFormatPassword.d.ts +2 -1
- package/lib/internal/_randomFormatPassword.js +7 -5
- package/lib/internal/_randomFormatPassword.js.map +1 -1
- package/lib/internal/_randomFormatPassword.mjs +5 -1
- package/lib/internal/_randomFormatPassword.mjs.map +1 -1
- package/lib/internal/_randomFormatRegex.d.ts +2 -1
- package/lib/internal/_randomFormatRegex.js +15 -1
- package/lib/internal/_randomFormatRegex.js.map +1 -1
- package/lib/internal/_randomFormatRegex.mjs +14 -1
- package/lib/internal/_randomFormatRegex.mjs.map +1 -1
- package/lib/internal/_randomFormatRelativeJsonPointer.d.ts +2 -1
- package/lib/internal/_randomFormatRelativeJsonPointer.js +20 -5
- package/lib/internal/_randomFormatRelativeJsonPointer.js.map +1 -1
- package/lib/internal/_randomFormatRelativeJsonPointer.mjs +21 -5
- package/lib/internal/_randomFormatRelativeJsonPointer.mjs.map +1 -1
- package/lib/internal/_randomFormatTime.d.ts +2 -1
- package/lib/internal/_randomFormatTime.js +34 -7
- package/lib/internal/_randomFormatTime.js.map +1 -1
- package/lib/internal/_randomFormatTime.mjs +37 -4
- package/lib/internal/_randomFormatTime.mjs.map +1 -1
- package/lib/internal/_randomFormatUri.d.ts +2 -1
- package/lib/internal/_randomFormatUri.js +1 -1
- package/lib/internal/_randomFormatUri.js.map +1 -1
- package/lib/internal/_randomFormatUri.mjs +1 -1
- package/lib/internal/_randomFormatUri.mjs.map +1 -1
- package/lib/internal/_randomFormatUriReference.d.ts +2 -1
- package/lib/internal/_randomFormatUriReference.js +1 -1
- package/lib/internal/_randomFormatUriReference.js.map +1 -1
- package/lib/internal/_randomFormatUriReference.mjs +1 -1
- package/lib/internal/_randomFormatUriReference.mjs.map +1 -1
- package/lib/internal/_randomFormatUriTemplate.d.ts +2 -1
- package/lib/internal/_randomFormatUriTemplate.js +1 -1
- package/lib/internal/_randomFormatUriTemplate.js.map +1 -1
- package/lib/internal/_randomFormatUriTemplate.mjs +1 -1
- package/lib/internal/_randomFormatUriTemplate.mjs.map +1 -1
- package/lib/internal/_randomFormatUrl.d.ts +2 -1
- package/lib/internal/_randomFormatUrl.js +21 -1
- package/lib/internal/_randomFormatUrl.js.map +1 -1
- package/lib/internal/_randomFormatUrl.mjs +18 -1
- package/lib/internal/_randomFormatUrl.mjs.map +1 -1
- package/lib/internal/_randomFormatUuid.d.ts +2 -1
- package/lib/internal/_randomFormatUuid.js +3 -2
- package/lib/internal/_randomFormatUuid.js.map +1 -1
- package/lib/internal/_randomFormatUuid.mjs +3 -2
- package/lib/internal/_randomFormatUuid.mjs.map +1 -1
- package/lib/internal/_randomInteger.js +59 -28
- package/lib/internal/_randomInteger.js.map +1 -1
- package/lib/internal/_randomInteger.mjs +56 -16
- package/lib/internal/_randomInteger.mjs.map +1 -1
- package/lib/internal/_randomMultiple.d.ts +8 -0
- package/lib/internal/_randomMultiple.js +168 -0
- package/lib/internal/_randomMultiple.js.map +1 -0
- package/lib/internal/_randomMultiple.mjs +158 -0
- package/lib/internal/_randomMultiple.mjs.map +1 -0
- package/lib/internal/_randomNumber.js +42 -42
- package/lib/internal/_randomNumber.js.map +1 -1
- package/lib/internal/_randomNumber.mjs +41 -27
- package/lib/internal/_randomNumber.mjs.map +1 -1
- package/lib/internal/_randomPattern.d.ts +2 -1
- package/lib/internal/_randomPattern.js +19 -4
- package/lib/internal/_randomPattern.js.map +1 -1
- package/lib/internal/_randomPattern.mjs +10 -4
- package/lib/internal/_randomPattern.mjs.map +1 -1
- package/lib/internal/_randomStringLength.d.ts +64 -0
- package/lib/internal/_randomStringLength.js +84 -0
- package/lib/internal/_randomStringLength.js.map +1 -0
- package/lib/internal/_randomStringLength.mjs +79 -0
- package/lib/internal/_randomStringLength.mjs.map +1 -0
- package/lib/internal/_stringLength.d.ts +1 -0
- package/lib/internal/_stringLength.js +11 -0
- package/lib/internal/_stringLength.js.map +1 -0
- package/lib/internal/_stringLength.mjs +10 -0
- package/lib/internal/_stringLength.mjs.map +1 -0
- package/lib/internal/_validateReport.js +4 -1
- package/lib/internal/_validateReport.js.map +1 -1
- package/lib/internal/_validateReport.mjs +2 -1
- package/lib/internal/_validateReport.mjs.map +1 -1
- package/lib/internal/private/__notationRename.d.ts +14 -0
- package/lib/internal/private/__notationRename.js +25 -0
- package/lib/internal/private/__notationRename.js.map +1 -0
- package/lib/internal/private/__notationRename.mjs +24 -0
- package/lib/internal/private/__notationRename.mjs.map +1 -0
- package/lib/internal/private/__randomComposition.d.ts +23 -0
- package/lib/internal/private/__randomComposition.js +48 -0
- package/lib/internal/private/__randomComposition.js.map +1 -0
- package/lib/internal/private/__randomComposition.mjs +54 -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.mjs.map +1 -1
- package/lib/module.d.ts +2 -2
- package/lib/module.js.map +1 -1
- package/lib/module.mjs.map +1 -1
- package/lib/notations.d.ts +20 -4
- package/lib/notations.js.map +1 -1
- package/lib/notations.mjs.map +1 -1
- package/native/adapter/plugin_options.go +117 -0
- package/native/adapter/plugin_options_payload_matrix_test.go +181 -0
- package/native/cmd/ttsc-typia/any_array_type_tags_transform_test.go +63 -9
- package/native/cmd/ttsc-typia/assert_guard_factory_contract_test.go +152 -0
- package/native/cmd/ttsc-typia/build.go +84 -64
- package/native/cmd/ttsc-typia/build_no_emit_preserves_analysis_options_test.go +67 -0
- package/native/cmd/ttsc-typia/build_no_emit_transform_diagnostics_test.go +138 -0
- package/native/cmd/ttsc-typia/build_plugin_options_come_from_payload_test.go +48 -0
- package/native/cmd/ttsc-typia/build_transactional_emit_success_test.go +81 -0
- package/native/cmd/ttsc-typia/build_transform_failure_atomicity_test.go +138 -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/command_routes_and_diagnostics_coverage_test.go +3 -1
- package/native/cmd/ttsc-typia/compare_functional_union_membership_transform_test.go +434 -0
- package/native/cmd/ttsc-typia/compare_less_nan_transform_test.go +98 -0
- package/native/cmd/ttsc-typia/compare_native_object_overmatch_transform_test.go +161 -0
- package/native/cmd/ttsc-typia/compare_nondiscriminable_union_transform_test.go +343 -0
- package/native/cmd/ttsc-typia/compare_template_literal_union_transform_test.go +241 -0
- package/native/cmd/ttsc-typia/compare_union_discrimination_transform_test.go +289 -0
- package/native/cmd/ttsc-typia/default_library_spoof_native_identity_transform_test.go +216 -0
- package/native/cmd/ttsc-typia/escaped_property_key_path_transform_test.go +193 -0
- package/native/cmd/ttsc-typia/finite_option_number_leaf_transform_test.go +240 -0
- package/native/cmd/ttsc-typia/functional_promised_type_transform_test.go +220 -0
- package/native/cmd/ttsc-typia/functional_receiver_transform_test.go +232 -0
- package/native/cmd/ttsc-typia/is_object_function_member_transform_test.go +205 -0
- package/native/cmd/ttsc-typia/json_application_alias_function_validation_transform_test.go +151 -0
- package/native/cmd/ttsc-typia/json_is_stringify_finite_number_transform_test.go +198 -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/json_stringify_special_key_transform_test.go +238 -0
- package/native/cmd/ttsc-typia/lib_replacement_native_identity_transform_test.go +277 -0
- package/native/cmd/ttsc-typia/main_wasm.go +21 -2
- package/native/cmd/ttsc-typia/native_collection_identity_is_transform_test.go +234 -0
- package/native/cmd/ttsc-typia/native_generic_name_guard_is_transform_test.go +194 -0
- package/native/cmd/ttsc-typia/native_name_collision_is_transform_test.go +204 -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/non_trailing_rest_tuple_transform_test.go +23 -11
- package/native/cmd/ttsc-typia/notation_dynamic_keys_transform_test.go +286 -0
- package/native/cmd/ttsc-typia/notation_kebab_case_transform_test.go +1 -1
- package/native/cmd/ttsc-typia/notation_literal_collision_transform_test.go +164 -0
- package/native/cmd/ttsc-typia/notation_pascal_case_transform_test.go +230 -0
- package/native/cmd/ttsc-typia/notation_unicode_key_transform_test.go +309 -0
- package/native/cmd/ttsc-typia/package_declaration_native_identity_is_transform_test.go +293 -0
- package/native/cmd/ttsc-typia/pattern_line_terminator_escape_transform_test.go +224 -0
- package/native/cmd/ttsc-typia/plain_prune_union_object_overmatch_transform_test.go +219 -0
- package/native/cmd/ttsc-typia/plugin_options_payload_helpers_test.go +181 -0
- package/native/cmd/ttsc-typia/private_field_filter_is_transform_test.go +278 -0
- package/native/cmd/ttsc-typia/project_catalog_transform_coverage_test.go +73 -27
- package/native/cmd/ttsc-typia/project_dependencies_barrel_reexport_transform_test.go +120 -0
- package/native/cmd/ttsc-typia/project_dependencies_collapsed_alias_transform_test.go +134 -0
- package/native/cmd/ttsc-typia/project_dependencies_custom_lib_name_transform_test.go +135 -0
- package/native/cmd/ttsc-typia/project_dependencies_default_barrel_transform_test.go +114 -0
- package/native/cmd/ttsc-typia/project_dependencies_empty_heritage_transform_test.go +100 -0
- package/native/cmd/ttsc-typia/project_dependencies_envelope_transform_test.go +148 -0
- package/native/cmd/ttsc-typia/project_dependencies_index_signature_alias_transform_test.go +139 -0
- package/native/cmd/ttsc-typia/project_dependencies_local_reexport_transform_test.go +122 -0
- package/native/cmd/ttsc-typia/project_dependencies_signature_alias_transform_test.go +125 -0
- package/native/cmd/ttsc-typia/project_dependencies_star_barrel_transform_test.go +112 -0
- package/native/cmd/ttsc-typia/project_reference_graph_envelope_transform_test.go +190 -0
- package/native/cmd/ttsc-typia/protobuf_diagnostic_code_transform_test.go +167 -0
- package/native/cmd/ttsc-typia/protobuf_is_encode_finite_number_transform_test.go +98 -0
- package/native/cmd/ttsc-typia/protobuf_sequence_field_numbers_transform_test.go +52 -22
- package/native/cmd/ttsc-typia/symbol_index_domain_transform_test.go +316 -0
- package/native/cmd/ttsc-typia/symbol_key_member_filter_transform_test.go +279 -0
- package/native/cmd/ttsc-typia/template_interpolation_type_tags_transform_test.go +86 -23
- package/native/cmd/ttsc-typia/template_literal_type_tags_transform_test.go +3 -1
- package/native/cmd/ttsc-typia/transform.go +251 -39
- package/native/cmd/ttsc-typia/{transform_declaration_source_produces_no_js_test.go → transform_declaration_source_produces_no_javascript_test.go} +10 -2
- package/native/cmd/ttsc-typia/transform_fixtures_emit_coverage_test.go +21 -4
- package/native/cmd/ttsc-typia/transform_helpers_test.go +236 -3
- package/native/cmd/ttsc-typia/transform_plugin_options_come_from_payload_test.go +43 -0
- package/native/cmd/ttsc-typia/transform_single_file_failure_atomicity_test.go +114 -0
- package/native/cmd/ttsc-typia/transform_single_file_failure_writes_no_stdout_test.go +43 -0
- package/native/cmd/ttsc-typia/transform_single_file_js_distinguishes_same_basename_sources_test.go +81 -0
- package/native/cmd/ttsc-typia/transform_single_file_js_empty_emit_reports_no_output_test.go +100 -0
- package/native/cmd/ttsc-typia/transform_single_file_js_locates_output_across_layouts_test.go +160 -0
- package/native/cmd/ttsc-typia/transform_single_file_success_publishes_artifact_test.go +54 -0
- package/native/cmd/ttsc-typia/transform_wasm_host_argv_reports_diagnostics_test.go +39 -0
- package/native/cmd/ttsc-typia/tuple_optional_compare_clone_transform_test.go +227 -0
- package/native/cmd/ttsc-typia/user_global_native_identity_transform_test.go +484 -0
- package/native/core/factories/FormatCheatSheet.go +40 -7
- package/native/core/factories/IdentifierFactory.go +131 -4
- package/native/core/factories/MetadataCommentTagFactory.go +83 -40
- package/native/core/factories/MetadataTypeTagFactory.go +13 -1
- package/native/core/factories/NumericRangeFactory.go +60 -17
- package/native/core/factories/ProtobufFactory.go +13 -5
- package/native/core/factories/factory_utility_coverage_test.go +8 -2
- package/native/core/factories/format_alias_resolves_to_cheat_sheet_test.go +57 -0
- package/native/core/factories/format_alias_table_targets_the_cheat_sheet_test.go +44 -0
- package/native/core/factories/identifier_factory_postfix_escapes_every_key_test.go +147 -0
- package/native/core/factories/identifier_factory_postfix_survives_every_code_point_test.go +86 -0
- package/native/core/factories/internal/metadata/MetadataHelper.go +226 -17
- package/native/core/factories/internal/metadata/emplace_metadata_object.go +141 -8
- package/native/core/factories/internal/metadata/iterate_metadata.go +6 -0
- package/native/core/factories/internal/metadata/iterate_metadata_function.go +5 -12
- package/native/core/factories/internal/metadata/iterate_metadata_intersection.go +111 -29
- package/native/core/factories/internal/metadata/iterate_metadata_map.go +5 -0
- package/native/core/factories/internal/metadata/iterate_metadata_native.go +45 -2
- package/native/core/factories/internal/metadata/iterate_metadata_set.go +5 -0
- package/native/core/factories/internal/metadata/type_arguments_precondition_test.go +70 -0
- package/native/core/factories/metadata_comment_tag_factory_coverage_test.go +39 -0
- package/native/core/factories/metadata_comment_tag_factory_exclusivity_matches_interface_test.go +84 -0
- package/native/core/factories/metadata_type_tag_factory_accepts_legal_tag_combinations_test.go +60 -0
- package/native/core/factories/metadata_type_tag_factory_declarations_test.go +86 -0
- package/native/core/factories/metadata_type_tag_factory_keeps_bool_form_exclusivity_test.go +38 -0
- package/native/core/factories/metadata_type_tag_factory_rejects_cross_kind_exclusive_tags_test.go +65 -0
- package/native/core/factories/metadata_type_tag_factory_rejects_duplicated_array_form_tags_test.go +41 -0
- package/native/core/factories/numeric_range_factory_enforces_64bit_bounds_test.go +69 -0
- package/native/core/factories/protobuf_recovery_ownership_test.go +64 -0
- package/native/core/programmers/IsProgrammer.go +15 -1
- package/native/core/programmers/RandomProgrammer.go +51 -14
- package/native/core/programmers/compare/CompareEqualProgrammer.go +410 -8
- package/native/core/programmers/compare/CompareLessProgrammer.go +4 -2
- package/native/core/programmers/functional/FunctionalAssertFunctionProgrammer.go +4 -6
- package/native/core/programmers/functional/FunctionalAssertParametersProgrammer.go +5 -13
- package/native/core/programmers/functional/FunctionalAssertReturnProgrammer.go +6 -14
- package/native/core/programmers/functional/FunctionalIsFunctionProgrammer.go +4 -6
- package/native/core/programmers/functional/FunctionalIsParametersProgrammer.go +49 -14
- package/native/core/programmers/functional/FunctionalIsReturnProgrammer.go +5 -13
- package/native/core/programmers/functional/FunctionalValidateFunctionProgrammer.go +4 -6
- package/native/core/programmers/functional/FunctionalValidateParametersProgrammer.go +5 -13
- package/native/core/programmers/functional/FunctionalValidateReturnProgrammer.go +5 -13
- package/native/core/programmers/functional/internal/FunctionalGeneralProgrammer.go +4 -17
- package/native/core/programmers/helpers/CloneJoiner.go +32 -0
- package/native/core/programmers/helpers/FunctionProgrammer.go +6 -13
- package/native/core/programmers/helpers/NotationJoiner.go +86 -28
- package/native/core/programmers/helpers/StringifyJoinder.go +161 -51
- package/native/core/programmers/helpers/UnionExplorer.go +203 -61
- package/native/core/programmers/helpers/joiner_branch_coverage_test.go +116 -118
- package/native/core/programmers/helpers/union_explorer_coverage_test.go +1 -1
- package/native/core/programmers/internal/CheckerProgrammer.go +100 -48
- package/native/core/programmers/iterate/check_template.go +344 -32
- 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_discriminator.go +36 -10
- package/native/core/programmers/iterate/json_schema_discriminator_declaration_syntax_test.go +205 -0
- 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 +674 -0
- package/native/core/programmers/iterate/openapi_v3_downgrader_boolean_default_test.go +95 -0
- package/native/core/programmers/iterate/openapi_v3_downgrader_test.go +123 -0
- package/native/core/programmers/iterate/template_interpolation_tags_test.go +40 -8
- package/native/core/programmers/iterate/template_runtime_pattern.go +63 -7
- package/native/core/programmers/json/JsonApplicationProgrammer.go +45 -11
- package/native/core/programmers/json/JsonSchemasProgrammer.go +12 -2
- package/native/core/programmers/json/JsonStringifyProgrammer.go +47 -6
- package/native/core/programmers/llm/LlmApplicationProgrammer.go +21 -11
- package/native/core/programmers/llm/LlmSchemaProgrammer.go +23 -6
- package/native/core/programmers/llm/llm_reference_codec_test.go +24 -0
- package/native/core/programmers/notations/NotationGeneralProgrammer.go +183 -67
- package/native/core/programmers/notations/notation_general_helpers_test.go +1 -3
- package/native/core/programmers/notations/notation_general_programmer_pascal_multiword_test.go +72 -0
- package/native/core/programmers/notations/notation_general_programmer_underscore_boundary_test.go +68 -0
- package/native/core/programmers/plain/PlainClassifyProgrammer.go +23 -15
- package/native/core/programmers/plain/PlainCloneProgrammer.go +20 -7
- package/native/core/programmers/plain/PlainPruneProgrammer.go +19 -5
- package/native/core/programmers/plain/plain_tuple_seed_recovery_ownership_test.go +25 -0
- package/native/core/programmers/protobuf/ProtobufDecodeProgrammer.go +37 -28
- package/native/core/programmers/protobuf/ProtobufMessageProgrammer.go +41 -22
- package/native/core/programmers/protobuf/protobuf_programmer_helper_coverage_test.go +26 -0
- package/native/core/programmers/random_programmer_length_argument_test.go +53 -0
- package/native/core/schemas/metadata/MetadataCollection.go +266 -25
- package/native/core/schemas/metadata/MetadataDefaultLibrary.go +81 -0
- package/native/core/schemas/metadata/MetadataDependency.go +388 -0
- package/native/core/schemas/metadata/MetadataObjectType.go +24 -22
- package/native/core/schemas/metadata/metadata_collection_generic_argument_dot_test.go +122 -0
- package/native/core/schemas/metadata/metadata_collection_name_allocation_test.go +147 -0
- package/native/core/schemas/metadata/metadata_collection_openapi_name_cascade_test.go +55 -0
- package/native/core/schemas/metadata/metadata_collection_openapi_name_test.go +68 -0
- package/native/core/utils/PatternUtil.go +13 -0
- package/native/core/utils/PromiseTypeFactory.go +59 -0
- package/native/core/utils/ProtobufNameEncoder.go +8 -0
- package/native/core/utils/promise_type_factory_semantics_test.go +118 -0
- package/native/go.mod +9 -1
- package/native/transform/CallExpressionTransformer.go +12 -0
- package/native/transform/features/json/JsonApplicationTransformer.go +1 -1
- package/native/transform/features/json/JsonSchemaTransformer.go +1 -1
- package/native/transform/features/json/JsonSchemasTransformer.go +5 -4
- package/native/transform/features/protobuf/ProtobufMessageTransformer.go +1 -1
- package/package.json +12 -4
- package/src/executable/FileSystemIdentity.ts +222 -0
- package/src/executable/TypiaGenerateWizard.ts +386 -113
- package/src/functional.ts +30 -60
- package/src/internal/_ProtobufReader.ts +161 -46
- package/src/internal/_createStandardSchema.ts +15 -1
- package/src/internal/_decimal.ts +69 -0
- package/src/internal/_httpQueryParseURLSearchParams.ts +24 -2
- package/src/internal/_isFormatByte.ts +2 -5
- package/src/internal/_isFormatDate.ts +15 -2
- package/src/internal/_isFormatDateTime.ts +28 -2
- package/src/internal/_isFormatIri.ts +5 -2
- package/src/internal/_isFormatIriReference.ts +11 -3
- package/src/internal/_isFormatUriReference.ts +1 -1
- package/src/internal/_isMultipleOf.ts +8 -0
- package/src/internal/_isTypeFloat.ts +1 -1
- package/src/internal/_isTypeInt64.ts +1 -0
- package/src/internal/_isTypeInt64Bigint.ts +12 -0
- package/src/internal/_isTypeUint64.ts +1 -0
- package/src/internal/_isTypeUint64Bigint.ts +7 -0
- package/src/internal/_isUniqueItems.ts +134 -132
- 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/_notationAny.ts +9 -4
- package/src/internal/_notationAssign.ts +20 -0
- package/src/internal/_notationCamel.ts +31 -10
- package/src/internal/_notationKebab.ts +11 -0
- package/src/internal/_notationKeyCollision.ts +9 -0
- package/src/internal/_notationPascal.ts +19 -6
- package/src/internal/_notationSnake.ts +24 -21
- package/src/internal/_plainCloneAny.ts +208 -33
- package/src/internal/_randomArray.ts +13 -4
- package/src/internal/_randomFormatByte.ts +31 -1
- package/src/internal/_randomFormatDate.ts +6 -17
- package/src/internal/_randomFormatDatetime.ts +34 -15
- package/src/internal/_randomFormatDuration.ts +30 -13
- package/src/internal/_randomFormatEmail.ts +8 -2
- package/src/internal/_randomFormatHostname.ts +48 -1
- package/src/internal/_randomFormatIdnEmail.ts +18 -2
- package/src/internal/_randomFormatIdnHostname.ts +34 -2
- package/src/internal/_randomFormatIpv4.ts +43 -2
- package/src/internal/_randomFormatIpv6.ts +67 -2
- package/src/internal/_randomFormatIri.ts +3 -1
- package/src/internal/_randomFormatIriReference.ts +3 -1
- package/src/internal/_randomFormatJsonPointer.ts +28 -2
- package/src/internal/_randomFormatPassword.ts +11 -6
- package/src/internal/_randomFormatRegex.ts +22 -1
- package/src/internal/_randomFormatRelativeJsonPointer.ts +26 -6
- package/src/internal/_randomFormatTime.ts +46 -10
- package/src/internal/_randomFormatUri.ts +3 -1
- package/src/internal/_randomFormatUriReference.ts +3 -1
- package/src/internal/_randomFormatUriTemplate.ts +3 -1
- package/src/internal/_randomFormatUrl.ts +25 -2
- package/src/internal/_randomFormatUuid.ts +10 -6
- package/src/internal/_randomInteger.ts +87 -40
- package/src/internal/_randomMultiple.ts +245 -0
- package/src/internal/_randomNumber.ts +72 -55
- package/src/internal/_randomPattern.ts +29 -4
- package/src/internal/_randomStringLength.ts +116 -0
- package/src/internal/_stringLength.ts +5 -0
- package/src/internal/_validateReport.ts +5 -1
- package/src/internal/private/__notationRename.ts +21 -0
- package/src/internal/private/__randomComposition.ts +50 -0
- package/src/internal/private/__randomEpoch.ts +34 -0
- package/src/json.ts +2 -2
- package/src/module.ts +4 -6
- package/src/notations.ts +20 -4
- package/lib/internal/private/__notationCapitalize.d.ts +0 -1
- package/lib/internal/private/__notationCapitalize.js +0 -6
- package/lib/internal/private/__notationCapitalize.js.map +0 -1
- package/lib/internal/private/__notationCapitalize.mjs +0 -6
- package/lib/internal/private/__notationCapitalize.mjs.map +0 -1
- package/lib/internal/private/__notationUnsnake.d.ts +0 -4
- package/lib/internal/private/__notationUnsnake.js +0 -26
- package/lib/internal/private/__notationUnsnake.js.map +0 -1
- package/lib/internal/private/__notationUnsnake.mjs +0 -15
- package/lib/internal/private/__notationUnsnake.mjs.map +0 -1
- package/native/adapter/visit.go +0 -173
- package/native/adapter/visit_property_chain_edges_test.go +0 -129
- package/native/cmd/ttsc-typia/plugin_options_missing_config_test.go +0 -26
- package/native/cmd/ttsc-typia/plugin_options_undefined_false_test.go +0 -36
- 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
- package/src/internal/private/__notationCapitalize.ts +0 -2
- package/src/internal/private/__notationUnsnake.ts +0 -24
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"os"
|
|
5
|
+
"os/exec"
|
|
6
|
+
"path/filepath"
|
|
7
|
+
"strings"
|
|
8
|
+
"testing"
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
// TestPatternLineTerminatorEscapeTransform verifies that a line terminator in a
|
|
12
|
+
// structural (template-literal-type or dynamic-key) pattern is escaped before it
|
|
13
|
+
// is spliced into an emitted `RegExp(/.../)` literal.
|
|
14
|
+
//
|
|
15
|
+
// A JavaScript regex literal cannot contain a raw line terminator, so a template
|
|
16
|
+
// literal type or dynamic key whose literal part holds one of the four
|
|
17
|
+
// ECMAScript LineTerminators (LF, CR, U+2028, U+2029) produced an unparsable
|
|
18
|
+
// module while the transform still exited 0 (a false-green). `PatternUtil.Escape`
|
|
19
|
+
// escaped the regex metacharacters but not the line terminators, and it is the
|
|
20
|
+
// single source feeding every regex-literal sink (`check_template`,
|
|
21
|
+
// `stringify_dynamic_properties`, `prune_object_properties`, and the
|
|
22
|
+
// clone/prune/classify/notation joiners), so one fixture that drives `is`,
|
|
23
|
+
// `json.stringify`, `clone`, `prune`, and `notations` over line-terminator
|
|
24
|
+
// patterns exercises them all (#2211).
|
|
25
|
+
//
|
|
26
|
+
// 1. Transform a fixture whose template literal types and Record dynamic keys
|
|
27
|
+
// carry each of the four line terminators, across every affected operation.
|
|
28
|
+
// 2. Assert the transform exits 0 and `node --check` accepts the whole emit as
|
|
29
|
+
// JavaScript -- RED before the fix (raw LF/CR/LS/PS in a regex literal).
|
|
30
|
+
// 3. Execute the emit and assert each `is` predicate matches a
|
|
31
|
+
// line-terminator-containing value and rejects a value that lacks it.
|
|
32
|
+
func TestPatternLineTerminatorEscapeTransform(t *testing.T) {
|
|
33
|
+
project := patternLineTerminatorProject(t)
|
|
34
|
+
js := patternLineTerminatorTransform(t, project)
|
|
35
|
+
// A line-terminator-free template still lowers to its historical pattern, so
|
|
36
|
+
// nothing but the escaped line terminators changes.
|
|
37
|
+
if !strings.Contains(js, "RegExp(/^prefix(.*)postfix$/)") {
|
|
38
|
+
t.Fatalf("line-terminator-free pattern must keep its historical form:\n%s", js)
|
|
39
|
+
}
|
|
40
|
+
patternLineTerminatorCheckSyntax(t, project, js)
|
|
41
|
+
patternLineTerminatorRunRuntimeCases(t, project, js)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
func patternLineTerminatorProject(t *testing.T) string {
|
|
45
|
+
t.Helper()
|
|
46
|
+
root := ttscTypiaTestRepoRoot(t)
|
|
47
|
+
base := filepath.Join(root, "packages", "typia", "native", ".tmp-ttsc-typia-tests")
|
|
48
|
+
if err := os.MkdirAll(base, 0o755); err != nil {
|
|
49
|
+
t.Fatalf("mkdir temp base: %v", err)
|
|
50
|
+
}
|
|
51
|
+
dir, err := os.MkdirTemp(base, "pattern-line-terminator-")
|
|
52
|
+
if err != nil {
|
|
53
|
+
t.Fatalf("create temp fixture: %v", err)
|
|
54
|
+
}
|
|
55
|
+
t.Cleanup(func() {
|
|
56
|
+
_ = os.RemoveAll(dir)
|
|
57
|
+
})
|
|
58
|
+
src := filepath.Join(dir, "src")
|
|
59
|
+
if err := os.MkdirAll(src, 0o755); err != nil {
|
|
60
|
+
t.Fatalf("mkdir fixture src: %v", err)
|
|
61
|
+
}
|
|
62
|
+
if err := os.WriteFile(filepath.Join(dir, "tsconfig.json"), []byte(patternLineTerminatorTSConfig), 0o644); err != nil {
|
|
63
|
+
t.Fatalf("write tsconfig: %v", err)
|
|
64
|
+
}
|
|
65
|
+
if err := os.WriteFile(filepath.Join(src, "main.ts"), []byte(patternLineTerminatorSource), 0o644); err != nil {
|
|
66
|
+
t.Fatalf("write source: %v", err)
|
|
67
|
+
}
|
|
68
|
+
return dir
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
func patternLineTerminatorTransform(t *testing.T, project string) string {
|
|
72
|
+
t.Helper()
|
|
73
|
+
out, errText, code := ttscTypiaTestCapture(func() int {
|
|
74
|
+
return runTransform([]string{
|
|
75
|
+
"--cwd", project,
|
|
76
|
+
"--tsconfig", "tsconfig.json",
|
|
77
|
+
"--file", "src/main.ts",
|
|
78
|
+
"--output", "js",
|
|
79
|
+
})
|
|
80
|
+
})
|
|
81
|
+
if code != 0 {
|
|
82
|
+
t.Fatalf("line terminator pattern transform failed: code=%d stderr=\n%s", code, errText)
|
|
83
|
+
}
|
|
84
|
+
return out
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// patternLineTerminatorCheckSyntax runs node against the emit exactly as it would
|
|
88
|
+
// ship. node --check only parses, so the unresolved typia imports in the
|
|
89
|
+
// untouched output do not matter, which keeps this a check of the real artifact.
|
|
90
|
+
func patternLineTerminatorCheckSyntax(t *testing.T, project string, js string) {
|
|
91
|
+
t.Helper()
|
|
92
|
+
node, err := exec.LookPath("node")
|
|
93
|
+
if err != nil {
|
|
94
|
+
t.Skip("node executable not found")
|
|
95
|
+
}
|
|
96
|
+
emitted := filepath.Join(project, "emitted.cjs")
|
|
97
|
+
if err := os.WriteFile(emitted, []byte(js), 0o644); err != nil {
|
|
98
|
+
t.Fatalf("write emitted module: %v", err)
|
|
99
|
+
}
|
|
100
|
+
if output, err := exec.Command(node, "--check", emitted).CombinedOutput(); err != nil {
|
|
101
|
+
t.Fatalf("emitted module is not valid JavaScript: %v\n%s\n--- emit ---\n%s", err, output, js)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
func patternLineTerminatorRunRuntimeCases(t *testing.T, project string, js string) {
|
|
106
|
+
t.Helper()
|
|
107
|
+
node, err := exec.LookPath("node")
|
|
108
|
+
if err != nil {
|
|
109
|
+
t.Skip("node executable not found")
|
|
110
|
+
}
|
|
111
|
+
runtimeDir := filepath.Join(project, "runtime")
|
|
112
|
+
if err := os.MkdirAll(runtimeDir, 0o755); err != nil {
|
|
113
|
+
t.Fatalf("mkdir runtime dir: %v", err)
|
|
114
|
+
}
|
|
115
|
+
ttscTypiaTestWriteCommonRuntimeStubs(t, runtimeDir)
|
|
116
|
+
// json.stringify pulls in _jsonStringifyNumber, which the shared rewrite does
|
|
117
|
+
// not map; stub it locally so the whole module loads. The runner only exercises
|
|
118
|
+
// the `is` predicates, so the stub body is immaterial.
|
|
119
|
+
if err := os.WriteFile(filepath.Join(runtimeDir, "json-stringify-number-stub.cjs"), []byte(patternLineTerminatorNumberStub), 0o644); err != nil {
|
|
120
|
+
t.Fatalf("write json stringify number stub: %v", err)
|
|
121
|
+
}
|
|
122
|
+
runtimeJS := strings.ReplaceAll(js, `require("typia/lib/internal/_jsonStringifyNumber")`, `require("./json-stringify-number-stub.cjs")`)
|
|
123
|
+
runtimeJS = ttscTypiaTestRewriteCommonJS(t, runtimeJS)
|
|
124
|
+
if err := os.WriteFile(filepath.Join(runtimeDir, "main.cjs"), []byte(runtimeJS), 0o644); err != nil {
|
|
125
|
+
t.Fatalf("write runtime module: %v", err)
|
|
126
|
+
}
|
|
127
|
+
runner := filepath.Join(runtimeDir, "run.cjs")
|
|
128
|
+
if err := os.WriteFile(runner, []byte(patternLineTerminatorRuntimeRunner), 0o644); err != nil {
|
|
129
|
+
t.Fatalf("write runtime runner: %v", err)
|
|
130
|
+
}
|
|
131
|
+
cmd := exec.Command(node, runner)
|
|
132
|
+
cmd.Dir = runtimeDir
|
|
133
|
+
if output, err := cmd.CombinedOutput(); err != nil {
|
|
134
|
+
t.Fatalf("line terminator pattern runtime cases failed: %v\n%s", err, output)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const patternLineTerminatorNumberStub = `module.exports._jsonStringifyNumber = (value) => String(value);
|
|
139
|
+
`
|
|
140
|
+
|
|
141
|
+
const patternLineTerminatorTSConfig = `{
|
|
142
|
+
"compilerOptions": {
|
|
143
|
+
"target": "ES2022",
|
|
144
|
+
"module": "commonjs",
|
|
145
|
+
"moduleResolution": "bundler",
|
|
146
|
+
"ignoreDeprecations": "6.0",
|
|
147
|
+
"types": ["*"],
|
|
148
|
+
"esModuleInterop": true,
|
|
149
|
+
"strict": true,
|
|
150
|
+
"skipLibCheck": true
|
|
151
|
+
},
|
|
152
|
+
"include": ["src"]
|
|
153
|
+
}
|
|
154
|
+
`
|
|
155
|
+
|
|
156
|
+
// The template literal types embed the line terminators as TypeScript escapes
|
|
157
|
+
// (backslash n, backslash r, backslash u2028, backslash u2029), which the
|
|
158
|
+
// compiler folds into real line terminator characters in the literal type --
|
|
159
|
+
// the exact trigger.
|
|
160
|
+
const patternLineTerminatorSource = `import typia from "typia";
|
|
161
|
+
|
|
162
|
+
export const isLF = typia.createIs<` + "`a\\n${string}b`" + `>();
|
|
163
|
+
export const isCR = typia.createIs<` + "`a\\r${string}b`" + `>();
|
|
164
|
+
export const isLS = typia.createIs<` + "`a\\u2028${string}b`" + `>();
|
|
165
|
+
export const isPS = typia.createIs<` + "`a\\u2029${string}b`" + `>();
|
|
166
|
+
export const isControl = typia.createIs<` + "`prefix${string}postfix`" + `>();
|
|
167
|
+
|
|
168
|
+
type LFRecord = Record<` + "`a\\n${string}`" + `, number>;
|
|
169
|
+
export const isRecord = typia.createIs<LFRecord>();
|
|
170
|
+
export const stringifyRecord = typia.json.createStringify<LFRecord>();
|
|
171
|
+
export const cloneRecord = typia.plain.createClone<LFRecord>();
|
|
172
|
+
export const pruneRecord = typia.plain.createPrune<LFRecord>();
|
|
173
|
+
export const camelRecord = typia.notations.createCamel<LFRecord>();
|
|
174
|
+
`
|
|
175
|
+
|
|
176
|
+
// Every value's only line terminator is the one the template's literal part
|
|
177
|
+
// pins, so the trailing `(.*)` (dot excludes newlines) still matches the tail.
|
|
178
|
+
// LF/CR go in as JS escapes and U+2028/U+2029 via String.fromCharCode so this
|
|
179
|
+
// source carries no raw line terminator of its own.
|
|
180
|
+
const patternLineTerminatorRuntimeRunner = `const mod = require("./main.cjs");
|
|
181
|
+
|
|
182
|
+
const LS = String.fromCharCode(0x2028);
|
|
183
|
+
const PS = String.fromCharCode(0x2029);
|
|
184
|
+
const cases = [
|
|
185
|
+
["isLF", "a\nZZb", "aZZb"],
|
|
186
|
+
["isCR", "a\rZZb", "aZZb"],
|
|
187
|
+
["isLS", "a" + LS + "ZZb", "aZZb"],
|
|
188
|
+
["isPS", "a" + PS + "ZZb", "aZZb"],
|
|
189
|
+
];
|
|
190
|
+
for (const [name, good, bad] of cases) {
|
|
191
|
+
if (mod[name](good) !== true) {
|
|
192
|
+
throw new Error(name + " must accept a value carrying its line terminator: " + JSON.stringify(good));
|
|
193
|
+
}
|
|
194
|
+
if (mod[name](bad) !== false) {
|
|
195
|
+
throw new Error(name + " must reject a value lacking its line terminator: " + JSON.stringify(bad));
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (mod.isControl("prefix_mid_postfix") !== true) {
|
|
200
|
+
throw new Error("line-terminator-free template must still accept a conforming value");
|
|
201
|
+
}
|
|
202
|
+
if (mod.isControl("nope") !== false) {
|
|
203
|
+
throw new Error("line-terminator-free template must still reject a non-conforming value");
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// A Record index signature only constrains keys its key pattern matches, so the
|
|
207
|
+
// newline in the key regex is what decides which keys get the number check. A
|
|
208
|
+
// matching key with a bad value must fail, while a near-miss key that lacks the
|
|
209
|
+
// newline is not matched (and so is left unchecked) -- together they prove the
|
|
210
|
+
// escaped line terminator is load-bearing in the emitted regex.
|
|
211
|
+
const goodRecord = {};
|
|
212
|
+
goodRecord["a\nkey"] = 1;
|
|
213
|
+
if (mod.isRecord(goodRecord) !== true) {
|
|
214
|
+
throw new Error("Record: a matching key with a number value must pass");
|
|
215
|
+
}
|
|
216
|
+
const matchedBadValue = {};
|
|
217
|
+
matchedBadValue["a\nkey"] = "not a number";
|
|
218
|
+
if (mod.isRecord(matchedBadValue) !== false) {
|
|
219
|
+
throw new Error("Record: a newline-matching key with a non-number value must fail");
|
|
220
|
+
}
|
|
221
|
+
if (mod.isRecord({ "axkey": "not a number" }) !== true) {
|
|
222
|
+
throw new Error("Record: a key lacking the newline must not match the pattern, so it stays unchecked");
|
|
223
|
+
}
|
|
224
|
+
`
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"os"
|
|
5
|
+
"os/exec"
|
|
6
|
+
"path/filepath"
|
|
7
|
+
"testing"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
// TestPlainPruneUnionObjectOvermatchTransform pins prune over mixed unions.
|
|
11
|
+
//
|
|
12
|
+
// PlainPruneProgrammer emits one independent `if` per union member, and the
|
|
13
|
+
// object arm's guard is `IsObject` with `CheckArray:false`, which also matches
|
|
14
|
+
// arrays and native instances. With no `else` the array/native arm AND the
|
|
15
|
+
// object arm both run, so `Object.keys(input)` on a value another arm already
|
|
16
|
+
// owns gets its slots deleted: a typed array throws on `delete input[0]`, a
|
|
17
|
+
// plain array collapses to holes, and a native's own properties are stripped.
|
|
18
|
+
// clone/classify resolve the same unions with a mutually exclusive ladder, so
|
|
19
|
+
// the object arm is only reached when the value is a plain object. This test
|
|
20
|
+
// drives every native kind unioned with an object in both orders, plus an
|
|
21
|
+
// object∪tuple, and requires the native/array/tuple value to survive intact.
|
|
22
|
+
//
|
|
23
|
+
// 1. Transform prune factories over native|object, object|native, array|object
|
|
24
|
+
// and object|tuple unions.
|
|
25
|
+
// 2. Execute prune against a typed array, Date, Map, Set, RegExp, plain array,
|
|
26
|
+
// and tuple, requiring each to keep its identity and own state.
|
|
27
|
+
// 3. Require the object arm still prunes an ordinary object member.
|
|
28
|
+
func TestPlainPruneUnionObjectOvermatchTransform(t *testing.T) {
|
|
29
|
+
project := plainPruneUnionObjectOvermatchProject(t)
|
|
30
|
+
out, errText, code := ttscTypiaTestCapture(func() int {
|
|
31
|
+
return runTransform([]string{
|
|
32
|
+
"--cwd", project,
|
|
33
|
+
"--tsconfig", "tsconfig.json",
|
|
34
|
+
"--file", "src/main.ts",
|
|
35
|
+
"--output", "js",
|
|
36
|
+
})
|
|
37
|
+
})
|
|
38
|
+
if code != 0 {
|
|
39
|
+
t.Fatalf("prune union/object over-match transform failed: code=%d stderr=\n%s", code, errText)
|
|
40
|
+
}
|
|
41
|
+
plainPruneUnionObjectOvermatchRunRuntimeCases(t, project, out)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
func plainPruneUnionObjectOvermatchProject(t *testing.T) string {
|
|
45
|
+
t.Helper()
|
|
46
|
+
root := ttscTypiaTestRepoRoot(t)
|
|
47
|
+
base := filepath.Join(root, "packages", "typia", "native", ".tmp-ttsc-typia-tests")
|
|
48
|
+
if err := os.MkdirAll(base, 0o755); err != nil {
|
|
49
|
+
t.Fatalf("mkdir temp base: %v", err)
|
|
50
|
+
}
|
|
51
|
+
dir, err := os.MkdirTemp(base, "plain-prune-union-object-")
|
|
52
|
+
if err != nil {
|
|
53
|
+
t.Fatalf("create temp fixture: %v", err)
|
|
54
|
+
}
|
|
55
|
+
t.Cleanup(func() {
|
|
56
|
+
_ = os.RemoveAll(dir)
|
|
57
|
+
})
|
|
58
|
+
src := filepath.Join(dir, "src")
|
|
59
|
+
if err := os.MkdirAll(src, 0o755); err != nil {
|
|
60
|
+
t.Fatalf("mkdir fixture src: %v", err)
|
|
61
|
+
}
|
|
62
|
+
if err := os.WriteFile(filepath.Join(dir, "tsconfig.json"), []byte(plainPruneUnionObjectOvermatchTSConfig), 0o644); err != nil {
|
|
63
|
+
t.Fatalf("write tsconfig: %v", err)
|
|
64
|
+
}
|
|
65
|
+
if err := os.WriteFile(filepath.Join(src, "main.ts"), []byte(plainPruneUnionObjectOvermatchSource), 0o644); err != nil {
|
|
66
|
+
t.Fatalf("write source: %v", err)
|
|
67
|
+
}
|
|
68
|
+
return dir
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
func plainPruneUnionObjectOvermatchRunRuntimeCases(t *testing.T, project string, js string) {
|
|
72
|
+
t.Helper()
|
|
73
|
+
node, err := exec.LookPath("node")
|
|
74
|
+
if err != nil {
|
|
75
|
+
t.Skip("node executable not found")
|
|
76
|
+
}
|
|
77
|
+
runtimeDir := filepath.Join(project, "runtime")
|
|
78
|
+
if err := os.MkdirAll(runtimeDir, 0o755); err != nil {
|
|
79
|
+
t.Fatalf("mkdir runtime dir: %v", err)
|
|
80
|
+
}
|
|
81
|
+
ttscTypiaTestWriteCommonRuntimeStubs(t, runtimeDir)
|
|
82
|
+
runtimeJS := ttscTypiaTestRewriteCommonJS(t, js)
|
|
83
|
+
if err := os.WriteFile(filepath.Join(runtimeDir, "main.cjs"), []byte(runtimeJS), 0o644); err != nil {
|
|
84
|
+
t.Fatalf("write runtime module: %v", err)
|
|
85
|
+
}
|
|
86
|
+
runner := filepath.Join(runtimeDir, "run.cjs")
|
|
87
|
+
if err := os.WriteFile(runner, []byte(plainPruneUnionObjectOvermatchRuntimeRunner), 0o644); err != nil {
|
|
88
|
+
t.Fatalf("write runtime runner: %v", err)
|
|
89
|
+
}
|
|
90
|
+
cmd := exec.Command(node, runner)
|
|
91
|
+
cmd.Dir = runtimeDir
|
|
92
|
+
output, err := cmd.CombinedOutput()
|
|
93
|
+
if err != nil {
|
|
94
|
+
t.Fatalf("prune union/object over-match runtime cases failed: %v\n%s", err, output)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const plainPruneUnionObjectOvermatchTSConfig = `{
|
|
99
|
+
"compilerOptions": {
|
|
100
|
+
"target": "ES2022",
|
|
101
|
+
"module": "commonjs",
|
|
102
|
+
"moduleResolution": "bundler",
|
|
103
|
+
"ignoreDeprecations": "6.0",
|
|
104
|
+
"types": ["*"],
|
|
105
|
+
"esModuleInterop": true,
|
|
106
|
+
"strict": true,
|
|
107
|
+
"skipLibCheck": true
|
|
108
|
+
},
|
|
109
|
+
"include": ["src"]
|
|
110
|
+
}
|
|
111
|
+
`
|
|
112
|
+
|
|
113
|
+
const plainPruneUnionObjectOvermatchSource = `import typia from "typia";
|
|
114
|
+
|
|
115
|
+
interface IBox {
|
|
116
|
+
x: number;
|
|
117
|
+
}
|
|
118
|
+
interface IElem {
|
|
119
|
+
y: number;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export const pruneBytesFirst = typia.plain.createPrune<Uint8Array | IBox>();
|
|
123
|
+
export const pruneBytesLast = typia.plain.createPrune<IBox | Uint8Array>();
|
|
124
|
+
export const pruneDateFirst = typia.plain.createPrune<Date | IBox>();
|
|
125
|
+
export const pruneDateLast = typia.plain.createPrune<IBox | Date>();
|
|
126
|
+
export const pruneMap = typia.plain.createPrune<Map<string, number> | IBox>();
|
|
127
|
+
export const pruneSet = typia.plain.createPrune<IBox | Set<number>>();
|
|
128
|
+
export const pruneRegExp = typia.plain.createPrune<RegExp | IBox>();
|
|
129
|
+
export const pruneArray = typia.plain.createPrune<IElem[] | IBox>();
|
|
130
|
+
export const pruneTuple = typia.plain.createPrune<IBox | [IElem, IElem]>();
|
|
131
|
+
`
|
|
132
|
+
|
|
133
|
+
const plainPruneUnionObjectOvermatchRuntimeRunner = `const mod = require("./main.cjs");
|
|
134
|
+
|
|
135
|
+
const fail = (label, detail) => {
|
|
136
|
+
throw new Error(label + ": " + detail);
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// 1. A typed array must survive prune untouched (the buggy object arm throws
|
|
140
|
+
// "Cannot delete property '0'" while deleting its integer-indexed slots).
|
|
141
|
+
for (const [label, prune] of [
|
|
142
|
+
["Uint8Array | IBox", mod.pruneBytesFirst],
|
|
143
|
+
["IBox | Uint8Array", mod.pruneBytesLast],
|
|
144
|
+
]) {
|
|
145
|
+
const bytes = new Uint8Array([1, 2, 3]);
|
|
146
|
+
prune(bytes);
|
|
147
|
+
if (!(bytes instanceof Uint8Array) || bytes.length !== 3 || bytes[0] !== 1 || bytes[1] !== 2 || bytes[2] !== 3)
|
|
148
|
+
fail(label, "typed array corrupted -> " + JSON.stringify(Array.from(bytes)));
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// 2. A Date must keep its time and its own state; the object arm strips own keys.
|
|
152
|
+
for (const [label, prune] of [
|
|
153
|
+
["Date | IBox", mod.pruneDateFirst],
|
|
154
|
+
["IBox | Date", mod.pruneDateLast],
|
|
155
|
+
]) {
|
|
156
|
+
const date = new Date(1000);
|
|
157
|
+
date.tag = "keep";
|
|
158
|
+
prune(date);
|
|
159
|
+
if (!(date instanceof Date) || date.getTime() !== 1000)
|
|
160
|
+
fail(label, "Date time corrupted -> " + date.getTime());
|
|
161
|
+
if (date.tag !== "keep")
|
|
162
|
+
fail(label, "Date own property stripped");
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// 3. A Map / Set must keep their contents and own state.
|
|
166
|
+
{
|
|
167
|
+
const map = new Map([["a", 1]]);
|
|
168
|
+
map.tag = "keep";
|
|
169
|
+
mod.pruneMap(map);
|
|
170
|
+
if (!(map instanceof Map) || map.size !== 1 || map.get("a") !== 1 || map.tag !== "keep")
|
|
171
|
+
fail("Map<string,number> | IBox", "Map corrupted");
|
|
172
|
+
}
|
|
173
|
+
{
|
|
174
|
+
const set = new Set([7]);
|
|
175
|
+
set.tag = "keep";
|
|
176
|
+
mod.pruneSet(set);
|
|
177
|
+
if (!(set instanceof Set) || set.size !== 1 || set.has(7) === false || set.tag !== "keep")
|
|
178
|
+
fail("IBox | Set<number>", "Set corrupted");
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// 4. A RegExp with equal source but its own state must survive.
|
|
182
|
+
{
|
|
183
|
+
const re = /abc/gi;
|
|
184
|
+
re.tag = "keep";
|
|
185
|
+
mod.pruneRegExp(re);
|
|
186
|
+
if (!(re instanceof RegExp) || re.source !== "abc" || re.flags !== "gi" || re.tag !== "keep")
|
|
187
|
+
fail("RegExp | IBox", "RegExp corrupted");
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// 5. A plain array must be pruned element-by-element, not deleted to holes.
|
|
191
|
+
{
|
|
192
|
+
const arr = [{ y: 1, extra: 2 }, { y: 3, extra: 4 }];
|
|
193
|
+
mod.pruneArray(arr);
|
|
194
|
+
if (!Array.isArray(arr) || arr.length !== 2)
|
|
195
|
+
fail("IElem[] | IBox", "array shape corrupted -> " + JSON.stringify(arr));
|
|
196
|
+
if (arr[0] === undefined || arr[1] === undefined)
|
|
197
|
+
fail("IElem[] | IBox", "array slot deleted -> " + JSON.stringify(arr));
|
|
198
|
+
if (arr[0].y !== 1 || arr[1].y !== 3 || "extra" in arr[0] || "extra" in arr[1])
|
|
199
|
+
fail("IElem[] | IBox", "array elements not pruned as objects -> " + JSON.stringify(arr));
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// 6. An object∪tuple must prune the tuple positionally, not delete its slots.
|
|
203
|
+
{
|
|
204
|
+
const tuple = [{ y: 1, extra: 2 }, { y: 3, extra: 4 }];
|
|
205
|
+
mod.pruneTuple(tuple);
|
|
206
|
+
if (!Array.isArray(tuple) || tuple.length !== 2 || tuple[0] === undefined || tuple[1] === undefined)
|
|
207
|
+
fail("IBox | [IElem, IElem]", "tuple slot deleted -> " + JSON.stringify(tuple));
|
|
208
|
+
if (tuple[0].y !== 1 || tuple[1].y !== 3 || "extra" in tuple[0] || "extra" in tuple[1])
|
|
209
|
+
fail("IBox | [IElem, IElem]", "tuple elements not pruned -> " + JSON.stringify(tuple));
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// 7. The object arm must still prune an ordinary object member (nothing lost).
|
|
213
|
+
{
|
|
214
|
+
const box = { x: 1, junk: "drop" };
|
|
215
|
+
mod.pruneBytesFirst(box);
|
|
216
|
+
if (box.x !== 1 || "junk" in box)
|
|
217
|
+
fail("Uint8Array | IBox", "object member not pruned -> " + JSON.stringify(box));
|
|
218
|
+
}
|
|
219
|
+
`
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"os"
|
|
5
|
+
"path/filepath"
|
|
6
|
+
"strings"
|
|
7
|
+
"testing"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
// pluginOptionsPayloadCase is one row of the #1887 regression matrix: a project
|
|
11
|
+
// whose tsconfig the user wrote a particular way, the payload ttsc resolves that
|
|
12
|
+
// tsconfig into and hands the plugin, and whether typia's `functional` option is
|
|
13
|
+
// on as a result.
|
|
14
|
+
//
|
|
15
|
+
// `functional` is the probe because its effect is visible in the transform's own
|
|
16
|
+
// output: with the option on, a function-typed property becomes significant and
|
|
17
|
+
// the emitted validator checks it; with the option off, the property is skipped.
|
|
18
|
+
type pluginOptionsPayloadCase struct {
|
|
19
|
+
name string
|
|
20
|
+
// base is a base tsconfig the leaf `extends`, or "" for a single-file project.
|
|
21
|
+
base string
|
|
22
|
+
// leafPlugins is the `compilerOptions.plugins` text of the leaf tsconfig, or
|
|
23
|
+
// "" when the leaf declares no plugins at all.
|
|
24
|
+
leafPlugins string
|
|
25
|
+
// payload is the `--plugins-json` manifest ttsc sends for this project.
|
|
26
|
+
payload string
|
|
27
|
+
// functional is whether the emitted validator must check the function-typed
|
|
28
|
+
// property.
|
|
29
|
+
functional bool
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// pluginOptionsPayloadCases returns the matrix every host must satisfy.
|
|
33
|
+
//
|
|
34
|
+
// Each row pairs the tsconfig the user wrote with the payload the host resolves
|
|
35
|
+
// it into, so the oracle is ttsc's plugin contract rather than typia's current
|
|
36
|
+
// output. The rows are the reproduction table of samchon/typia#1887: the
|
|
37
|
+
// comment and sibling-entry rows prove typia no longer matches option names
|
|
38
|
+
// against raw tsconfig text, and the `extends` row proves it no longer ignores
|
|
39
|
+
// the entry that loaded it.
|
|
40
|
+
func pluginOptionsPayloadCases() []pluginOptionsPayloadCase {
|
|
41
|
+
return []pluginOptionsPayloadCase{
|
|
42
|
+
{
|
|
43
|
+
// The documented shape, and the only one the old scrape read correctly.
|
|
44
|
+
// Pins behavior that must not change.
|
|
45
|
+
name: "option inline on typia's entry",
|
|
46
|
+
leafPlugins: `[{ "transform": "typia/lib/transform", "functional": true }]`,
|
|
47
|
+
payload: `[{"config":{"transform":"typia/lib/transform","functional":true},"name":"typia","stage":"transform"}]`,
|
|
48
|
+
functional: true,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
// The user disabled the option. tsconfig is JSONC, so the host drops the
|
|
52
|
+
// comment and typia's entry carries nothing.
|
|
53
|
+
name: "option commented out with a line comment",
|
|
54
|
+
leafPlugins: `[{
|
|
55
|
+
"transform": "typia/lib/transform"
|
|
56
|
+
// "functional": true
|
|
57
|
+
}]`,
|
|
58
|
+
payload: `[{"config":{"transform":"typia/lib/transform"},"name":"typia","stage":"transform"}]`,
|
|
59
|
+
functional: false,
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: "option commented out with a block comment",
|
|
63
|
+
leafPlugins: `[{
|
|
64
|
+
"transform": "typia/lib/transform"
|
|
65
|
+
/* "functional": true */
|
|
66
|
+
}]`,
|
|
67
|
+
payload: `[{"config":{"transform":"typia/lib/transform"},"name":"typia","stage":"transform"}]`,
|
|
68
|
+
functional: false,
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
// A transform host carries every transform-stage plugin's entry. The
|
|
72
|
+
// option belongs to the sibling, and reading it would be reading someone
|
|
73
|
+
// else's configuration.
|
|
74
|
+
name: "option owned by another plugin's entry",
|
|
75
|
+
leafPlugins: `[
|
|
76
|
+
{ "transform": "other/lib/transform", "functional": true },
|
|
77
|
+
{ "transform": "typia/lib/transform" }
|
|
78
|
+
]`,
|
|
79
|
+
payload: `[
|
|
80
|
+
{"config":{"transform":"other/lib/transform","functional":true},"name":"other","stage":"transform"},
|
|
81
|
+
{"config":{"transform":"typia/lib/transform"},"name":"typia","stage":"transform"}
|
|
82
|
+
]`,
|
|
83
|
+
functional: false,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
// The standard monorepo layout: a shared base declares the plugin and its
|
|
87
|
+
// options, the leaf only extends it. The host resolved the chain and sent
|
|
88
|
+
// the merged entry -- which is why the plugin is running at all.
|
|
89
|
+
name: "option declared in a base tsconfig the leaf extends",
|
|
90
|
+
base: `{
|
|
91
|
+
"compilerOptions": {
|
|
92
|
+
"plugins": [{ "transform": "typia/lib/transform", "functional": true }]
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
`,
|
|
96
|
+
payload: `[{"config":{"transform":"typia/lib/transform","functional":true},"name":"typia","stage":"transform"}]`,
|
|
97
|
+
functional: true,
|
|
98
|
+
},
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// pluginOptionsPayloadProject materializes one matrix row as a real project: the
|
|
103
|
+
// tsconfig exactly as the user wrote it (comments, sibling entries, `extends`
|
|
104
|
+
// chain and all), a typia stub to resolve the import against, and a source file
|
|
105
|
+
// with a function-typed property for the option to act on.
|
|
106
|
+
func pluginOptionsPayloadProject(t *testing.T, tc pluginOptionsPayloadCase) string {
|
|
107
|
+
t.Helper()
|
|
108
|
+
project := t.TempDir()
|
|
109
|
+
src := filepath.Join(project, "src")
|
|
110
|
+
if err := os.MkdirAll(src, 0o755); err != nil {
|
|
111
|
+
t.Fatalf("mkdir fixture src: %v", err)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
extends := ""
|
|
115
|
+
if tc.base != "" {
|
|
116
|
+
if err := os.WriteFile(filepath.Join(project, "tsconfig.base.json"), []byte(tc.base), 0o644); err != nil {
|
|
117
|
+
t.Fatalf("write base tsconfig: %v", err)
|
|
118
|
+
}
|
|
119
|
+
extends = `"extends": "./tsconfig.base.json",
|
|
120
|
+
`
|
|
121
|
+
}
|
|
122
|
+
plugins := ""
|
|
123
|
+
if tc.leafPlugins != "" {
|
|
124
|
+
plugins = `,
|
|
125
|
+
"plugins": ` + tc.leafPlugins
|
|
126
|
+
}
|
|
127
|
+
config := `{
|
|
128
|
+
` + extends + `"compilerOptions": {
|
|
129
|
+
"target": "ES2022",
|
|
130
|
+
"module": "commonjs",
|
|
131
|
+
"moduleResolution": "bundler",
|
|
132
|
+
"ignoreDeprecations": "6.0",
|
|
133
|
+
"types": ["*"],
|
|
134
|
+
"esModuleInterop": true,
|
|
135
|
+
"strict": true,
|
|
136
|
+
"skipLibCheck": true,
|
|
137
|
+
"rootDir": "src",
|
|
138
|
+
"outDir": "dist"` + plugins + `
|
|
139
|
+
},
|
|
140
|
+
"include": ["src"]
|
|
141
|
+
}
|
|
142
|
+
`
|
|
143
|
+
if err := os.WriteFile(filepath.Join(project, "tsconfig.json"), []byte(config), 0o644); err != nil {
|
|
144
|
+
t.Fatalf("write tsconfig: %v", err)
|
|
145
|
+
}
|
|
146
|
+
transformDiagnosticWriteTypiaStub(t, project)
|
|
147
|
+
if err := os.WriteFile(filepath.Join(src, "main.ts"), []byte(pluginOptionsPayloadSource), 0o644); err != nil {
|
|
148
|
+
t.Fatalf("write source: %v", err)
|
|
149
|
+
}
|
|
150
|
+
return project
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// pluginOptionsPayloadAssert checks one host's output against the row's expected
|
|
154
|
+
// option state.
|
|
155
|
+
func pluginOptionsPayloadAssert(t *testing.T, tc pluginOptionsPayloadCase, output string) {
|
|
156
|
+
t.Helper()
|
|
157
|
+
checked := pluginOptionsPayloadFunctionalCheck(output)
|
|
158
|
+
if checked == tc.functional {
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
if tc.functional {
|
|
162
|
+
t.Fatalf("functional is configured on but the validator skipped the function property:\n%s", output)
|
|
163
|
+
}
|
|
164
|
+
t.Fatalf("functional is not configured but the validator checked the function property:\n%s", output)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
func pluginOptionsPayloadFunctionalCheck(output string) bool {
|
|
168
|
+
return strings.Contains(output, pluginOptionsPayloadFunctionalNeedle)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// pluginOptionsPayloadFunctionalNeedle is the guard typia emits for the
|
|
172
|
+
// function-typed property only when `functional` is enabled.
|
|
173
|
+
const pluginOptionsPayloadFunctionalNeedle = `"function" === typeof input.cb`
|
|
174
|
+
|
|
175
|
+
const pluginOptionsPayloadSource = `import typia from "typia";
|
|
176
|
+
export interface IX {
|
|
177
|
+
value: number;
|
|
178
|
+
cb: () => void;
|
|
179
|
+
}
|
|
180
|
+
export const check = (input: unknown): boolean => typia.is<IX>(input);
|
|
181
|
+
`
|