typia 13.1.1 → 13.1.19
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 +21 -0
- package/lib/executable/FileSystemIdentity.js +183 -0
- package/lib/executable/FileSystemIdentity.js.map +1 -0
- package/lib/executable/FileSystemIdentity.mjs +129 -0
- package/lib/executable/FileSystemIdentity.mjs.map +1 -0
- package/lib/executable/TypiaGenerateWizard.js +264 -104
- package/lib/executable/TypiaGenerateWizard.js.map +1 -1
- package/lib/executable/TypiaGenerateWizard.mjs +233 -93
- 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 +17 -0
- package/lib/internal/_ProtobufReader.js +117 -45
- package/lib/internal/_ProtobufReader.js.map +1 -1
- package/lib/internal/_ProtobufReader.mjs +108 -39
- 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/_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 +2 -1
- package/lib/internal/_randomFormatByte.js.map +1 -1
- package/lib/internal/_randomFormatByte.mjs +2 -1
- package/lib/internal/_randomFormatByte.mjs.map +1 -1
- package/lib/internal/_randomFormatDate.d.ts +2 -0
- package/lib/internal/_randomFormatDate.js +3 -2
- package/lib/internal/_randomFormatDate.js.map +1 -1
- package/lib/internal/_randomFormatDate.mjs +3 -2
- package/lib/internal/_randomFormatDate.mjs.map +1 -1
- package/lib/internal/_randomFormatDatetime.d.ts +2 -0
- package/lib/internal/_randomFormatDatetime.js +3 -2
- package/lib/internal/_randomFormatDatetime.js.map +1 -1
- package/lib/internal/_randomFormatDatetime.mjs +3 -2
- package/lib/internal/_randomFormatDatetime.mjs.map +1 -1
- package/lib/internal/_randomFormatDuration.d.ts +2 -1
- package/lib/internal/_randomFormatDuration.js +3 -2
- package/lib/internal/_randomFormatDuration.js.map +1 -1
- package/lib/internal/_randomFormatDuration.mjs +3 -2
- 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 +2 -1
- package/lib/internal/_randomFormatIpv4.js.map +1 -1
- package/lib/internal/_randomFormatIpv4.mjs +2 -1
- package/lib/internal/_randomFormatIpv4.mjs.map +1 -1
- package/lib/internal/_randomFormatIpv6.d.ts +2 -1
- package/lib/internal/_randomFormatIpv6.js +2 -1
- package/lib/internal/_randomFormatIpv6.js.map +1 -1
- package/lib/internal/_randomFormatIpv6.mjs +2 -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 +8 -1
- package/lib/internal/_randomFormatJsonPointer.js.map +1 -1
- package/lib/internal/_randomFormatJsonPointer.mjs +5 -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 +2 -1
- package/lib/internal/_randomFormatRegex.js.map +1 -1
- package/lib/internal/_randomFormatRegex.mjs +2 -1
- package/lib/internal/_randomFormatRegex.mjs.map +1 -1
- package/lib/internal/_randomFormatRelativeJsonPointer.d.ts +2 -1
- package/lib/internal/_randomFormatRelativeJsonPointer.js +3 -2
- package/lib/internal/_randomFormatRelativeJsonPointer.js.map +1 -1
- package/lib/internal/_randomFormatRelativeJsonPointer.mjs +3 -2
- package/lib/internal/_randomFormatRelativeJsonPointer.mjs.map +1 -1
- package/lib/internal/_randomFormatTime.d.ts +2 -1
- package/lib/internal/_randomFormatTime.js +3 -2
- package/lib/internal/_randomFormatTime.js.map +1 -1
- package/lib/internal/_randomFormatTime.mjs +3 -2
- 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 +33 -0
- package/lib/internal/_randomStringLength.js +48 -0
- package/lib/internal/_randomStringLength.js.map +1 -0
- package/lib/internal/_randomStringLength.mjs +44 -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/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 +81 -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/command_routes_and_diagnostics_coverage_test.go +3 -1
- 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_union_discrimination_transform_test.go +289 -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_stringify_special_key_transform_test.go +238 -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/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/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_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_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 +228 -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 +159 -1
- 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/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 +7 -4
- 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 +60 -6
- package/native/core/factories/internal/metadata/emplace_metadata_object.go +116 -8
- package/native/core/factories/internal/metadata/iterate_metadata.go +6 -0
- package/native/core/factories/internal/metadata/iterate_metadata_function.go +4 -11
- package/native/core/factories/internal/metadata/iterate_metadata_intersection.go +8 -6
- package/native/core/factories/internal/metadata/iterate_metadata_map.go +9 -0
- package/native/core/factories/internal/metadata/iterate_metadata_native.go +27 -2
- package/native/core/factories/internal/metadata/iterate_metadata_set.go +9 -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 +393 -5
- 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/NotationJoiner.go +86 -28
- package/native/core/programmers/helpers/StringifyJoinder.go +32 -1
- package/native/core/programmers/helpers/UnionExplorer.go +203 -61
- package/native/core/programmers/helpers/joiner_branch_coverage_test.go +5 -3
- 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/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/openapi_v3_downgrader.go +641 -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 +52 -7
- package/native/core/programmers/json/JsonApplicationProgrammer.go +45 -11
- package/native/core/programmers/json/JsonSchemasProgrammer.go +12 -2
- package/native/core/programmers/llm/LlmApplicationProgrammer.go +12 -10
- 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 +40 -21
- 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 +270 -20
- package/native/core/schemas/metadata/MetadataDependency.go +388 -0
- package/native/core/schemas/metadata/MetadataObjectType.go +17 -4
- 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/package.json +16 -4
- package/src/executable/FileSystemIdentity.ts +189 -0
- package/src/executable/TypiaGenerateWizard.ts +377 -110
- package/src/functional.ts +30 -60
- package/src/internal/_ProtobufReader.ts +129 -43
- 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/_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 +4 -1
- package/src/internal/_randomFormatDate.ts +17 -12
- package/src/internal/_randomFormatDatetime.ts +15 -10
- package/src/internal/_randomFormatDuration.ts +16 -14
- 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 +3 -2
- package/src/internal/_randomFormatIpv6.ts +3 -2
- package/src/internal/_randomFormatIri.ts +3 -1
- package/src/internal/_randomFormatIriReference.ts +3 -1
- package/src/internal/_randomFormatJsonPointer.ts +8 -2
- package/src/internal/_randomFormatPassword.ts +11 -6
- package/src/internal/_randomFormatRegex.ts +4 -1
- package/src/internal/_randomFormatRelativeJsonPointer.ts +13 -6
- package/src/internal/_randomFormatTime.ts +13 -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 +26 -4
- package/src/internal/_randomStringLength.ts +72 -0
- package/src/internal/_stringLength.ts +5 -0
- package/src/internal/_validateReport.ts +5 -1
- package/src/internal/private/__notationRename.ts +24 -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/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/src/internal/private/__notationCapitalize.ts +0 -2
- package/src/internal/private/__notationUnsnake.ts +0 -24
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"os"
|
|
5
|
+
"os/exec"
|
|
6
|
+
"path/filepath"
|
|
7
|
+
"testing"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
// TestTupleOptionalCompareCloneTransform pins optional-trailing tuple semantics
|
|
11
|
+
// across is / compare.equals / plain.clone / plain.classify.
|
|
12
|
+
//
|
|
13
|
+
// Issue #2202: for a tuple with an omitted optional trailing element, `is`
|
|
14
|
+
// correctly validates with a length range (`1 <= length && 2 >= length`), but
|
|
15
|
+
// `compare.equals` emitted a hard `x.length === 2` gate and `plain.clone` /
|
|
16
|
+
// `plain.classify` materialized the absent element as a phantom `undefined`
|
|
17
|
+
// (`[input[0], input[1]]`). So `equals(["a"], ["a"])` was false (reflexivity
|
|
18
|
+
// broken; disagrees with `is`) and `clone(["a"])` was `["a", undefined]`
|
|
19
|
+
// (length 2), not deep-equal to its input. The three must honor the same
|
|
20
|
+
// optional-trailing semantics as `is`.
|
|
21
|
+
//
|
|
22
|
+
// 1. Transform is / equals / clone / classify over `[string, number?]` and
|
|
23
|
+
// `[string, number?, boolean?]`, plus fully-required and rest controls.
|
|
24
|
+
// 2. Require equals reflexive over omitted-optional values, clone/classify to
|
|
25
|
+
// produce the correct length with no phantom slot, and `equals(x, clone(x))`
|
|
26
|
+
// to hold for every is-valid x.
|
|
27
|
+
// 3. Require fully-populated tuples and rest tuples to be unchanged.
|
|
28
|
+
func TestTupleOptionalCompareCloneTransform(t *testing.T) {
|
|
29
|
+
project := tupleOptionalCompareCloneProject(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("tuple optional compare/clone transform failed: code=%d stderr=\n%s", code, errText)
|
|
40
|
+
}
|
|
41
|
+
tupleOptionalCompareCloneRunRuntimeCases(t, project, out)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
func tupleOptionalCompareCloneProject(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, "tuple-optional-")
|
|
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(tupleOptionalCompareCloneTSConfig), 0o644); err != nil {
|
|
63
|
+
t.Fatalf("write tsconfig: %v", err)
|
|
64
|
+
}
|
|
65
|
+
if err := os.WriteFile(filepath.Join(src, "main.ts"), []byte(tupleOptionalCompareCloneSource), 0o644); err != nil {
|
|
66
|
+
t.Fatalf("write source: %v", err)
|
|
67
|
+
}
|
|
68
|
+
return dir
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
func tupleOptionalCompareCloneRunRuntimeCases(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(tupleOptionalCompareCloneRuntimeRunner), 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("tuple optional compare/clone runtime cases failed: %v\n%s", err, output)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const tupleOptionalCompareCloneTSConfig = `{
|
|
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 tupleOptionalCompareCloneSource = `import typia from "typia";
|
|
114
|
+
|
|
115
|
+
export const isPair = typia.createIs<[string, number?]>();
|
|
116
|
+
export const equalsPair = typia.compare.createEquals<[string, number?]>();
|
|
117
|
+
export const clonePair = typia.plain.createClone<[string, number?]>();
|
|
118
|
+
export const classifyPair = typia.plain.createClassify<[string, number?]>();
|
|
119
|
+
|
|
120
|
+
export const isTriple = typia.createIs<[string, number?, boolean?]>();
|
|
121
|
+
export const equalsTriple = typia.compare.createEquals<[string, number?, boolean?]>();
|
|
122
|
+
export const cloneTriple = typia.plain.createClone<[string, number?, boolean?]>();
|
|
123
|
+
export const classifyTriple = typia.plain.createClassify<[string, number?, boolean?]>();
|
|
124
|
+
|
|
125
|
+
// boundary: a tuple whose only element is optional.
|
|
126
|
+
export const equalsSolo = typia.compare.createEquals<[number?]>();
|
|
127
|
+
export const cloneSolo = typia.plain.createClone<[number?]>();
|
|
128
|
+
|
|
129
|
+
// boundary: an optional trailing element that is itself a nested tuple.
|
|
130
|
+
export const equalsNested = typia.compare.createEquals<[string, [number, boolean]?]>();
|
|
131
|
+
export const cloneNested = typia.plain.createClone<[string, [number, boolean]?]>();
|
|
132
|
+
|
|
133
|
+
// control: a fully-required tuple must stay byte-identical.
|
|
134
|
+
export const equalsFixed = typia.compare.createEquals<[string, number]>();
|
|
135
|
+
export const cloneFixed = typia.plain.createClone<[string, number]>();
|
|
136
|
+
|
|
137
|
+
// control: a rest tuple must stay byte-identical.
|
|
138
|
+
export const equalsRest = typia.compare.createEquals<[string, ...number[]]>();
|
|
139
|
+
export const cloneRest = typia.plain.createClone<[string, ...number[]]>();
|
|
140
|
+
`
|
|
141
|
+
|
|
142
|
+
const tupleOptionalCompareCloneRuntimeRunner = `const mod = require("./main.cjs");
|
|
143
|
+
|
|
144
|
+
const expect = (label, actual, expected) => {
|
|
145
|
+
if (actual !== expected) {
|
|
146
|
+
throw new Error(label + ": expected " + expected + ", got " + actual);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
// A clone must be a distinct array, deep-equal to expected, with no phantom
|
|
151
|
+
// trailing slot (length matches, and the first out-of-range index is absent).
|
|
152
|
+
const expectClone = (label, result, expected) => {
|
|
153
|
+
if (!Array.isArray(result)) throw new Error(label + ": not an array");
|
|
154
|
+
if (result.length !== expected.length)
|
|
155
|
+
throw new Error(label + ": length " + result.length + " !== " + expected.length);
|
|
156
|
+
if (expected.length in result)
|
|
157
|
+
throw new Error(label + ": phantom slot at index " + expected.length);
|
|
158
|
+
for (let i = 0; i < expected.length; ++i)
|
|
159
|
+
if (result[i] !== expected[i])
|
|
160
|
+
throw new Error(label + ": [" + i + "] " + result[i] + " !== " + expected[i]);
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// --- is: the reference range semantics (unchanged) ---
|
|
164
|
+
expect("is pair omitted", mod.isPair(["a"]), true);
|
|
165
|
+
expect("is pair present", mod.isPair(["a", 1]), true);
|
|
166
|
+
expect("is pair too long", mod.isPair(["a", 1, 2]), false);
|
|
167
|
+
expect("is triple omitted", mod.isTriple(["a"]), true);
|
|
168
|
+
|
|
169
|
+
// --- equals: reflexive over omitted optional; matches is ---
|
|
170
|
+
expect("equals pair omitted reflexive", mod.equalsPair(["a"], ["a"]), true);
|
|
171
|
+
expect("equals pair omitted vs present", mod.equalsPair(["a"], ["a", 1]), false);
|
|
172
|
+
expect("equals pair present reflexive", mod.equalsPair(["a", 1], ["a", 1]), true);
|
|
173
|
+
expect("equals pair present differ", mod.equalsPair(["a", 1], ["a", 2]), false);
|
|
174
|
+
expect("equals triple omitted reflexive", mod.equalsTriple(["a"], ["a"]), true);
|
|
175
|
+
expect("equals triple mid present reflexive", mod.equalsTriple(["a", 1], ["a", 1]), true);
|
|
176
|
+
expect("equals triple full reflexive", mod.equalsTriple(["a", 1, true], ["a", 1, true]), true);
|
|
177
|
+
expect("equals triple omitted vs present", mod.equalsTriple(["a"], ["a", 1]), false);
|
|
178
|
+
|
|
179
|
+
// --- clone: correct length, no phantom undefined ---
|
|
180
|
+
expectClone("clone pair omitted", mod.clonePair(["a"]), ["a"]);
|
|
181
|
+
expectClone("clone pair present", mod.clonePair(["a", 1]), ["a", 1]);
|
|
182
|
+
expectClone("clone triple omitted", mod.cloneTriple(["a"]), ["a"]);
|
|
183
|
+
expectClone("clone triple mid present", mod.cloneTriple(["a", 1]), ["a", 1]);
|
|
184
|
+
expectClone("clone triple full", mod.cloneTriple(["a", 1, true]), ["a", 1, true]);
|
|
185
|
+
|
|
186
|
+
// --- classify: same tuple-inline path as clone ---
|
|
187
|
+
expectClone("classify pair omitted", mod.classifyPair(["a"]), ["a"]);
|
|
188
|
+
expectClone("classify triple omitted", mod.classifyTriple(["a"]), ["a"]);
|
|
189
|
+
|
|
190
|
+
// --- equals(x, clone(x)) holds for every is-valid x ---
|
|
191
|
+
for (const x of [["a"], ["a", 1]]) {
|
|
192
|
+
if (mod.isPair(x)) expect("equals pair (x, clone x) " + JSON.stringify(x), mod.equalsPair(x, mod.clonePair(x)), true);
|
|
193
|
+
}
|
|
194
|
+
for (const x of [["a"], ["a", 1], ["a", 1, true]]) {
|
|
195
|
+
if (mod.isTriple(x)) expect("equals triple (x, clone x) " + JSON.stringify(x), mod.equalsTriple(x, mod.cloneTriple(x)), true);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// --- boundary: only-optional tuple ---
|
|
199
|
+
expect("equals solo empty reflexive", mod.equalsSolo([], []), true);
|
|
200
|
+
expect("equals solo empty vs present", mod.equalsSolo([], [1]), false);
|
|
201
|
+
expect("equals solo present reflexive", mod.equalsSolo([1], [1]), true);
|
|
202
|
+
expectClone("clone solo empty", mod.cloneSolo([]), []);
|
|
203
|
+
expectClone("clone solo present", mod.cloneSolo([1]), [1]);
|
|
204
|
+
|
|
205
|
+
// --- boundary: nested tuple as the optional trailing element ---
|
|
206
|
+
expect("equals nested omitted reflexive", mod.equalsNested(["a"], ["a"]), true);
|
|
207
|
+
expect("equals nested present reflexive", mod.equalsNested(["a", [1, true]], ["a", [1, true]]), true);
|
|
208
|
+
expect("equals nested omitted vs present", mod.equalsNested(["a"], ["a", [1, true]]), false);
|
|
209
|
+
expectClone("clone nested omitted", mod.cloneNested(["a"]), ["a"]);
|
|
210
|
+
{
|
|
211
|
+
const nested = mod.cloneNested(["a", [1, true]]);
|
|
212
|
+
if (nested.length !== 2) throw new Error("clone nested present: outer length " + nested.length);
|
|
213
|
+
if (1 in nested === false) throw new Error("clone nested present: missing inner tuple");
|
|
214
|
+
expectClone("clone nested inner", nested[1], [1, true]);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// --- controls: fully-required and rest tuples unchanged ---
|
|
218
|
+
expect("equals fixed reflexive", mod.equalsFixed(["a", 1], ["a", 1]), true);
|
|
219
|
+
expect("equals fixed differ", mod.equalsFixed(["a", 1], ["a", 2]), false);
|
|
220
|
+
expectClone("clone fixed", mod.cloneFixed(["a", 1]), ["a", 1]);
|
|
221
|
+
|
|
222
|
+
expect("equals rest solo", mod.equalsRest(["a"], ["a"]), true);
|
|
223
|
+
expect("equals rest multi", mod.equalsRest(["a", 1, 2], ["a", 1, 2]), true);
|
|
224
|
+
expect("equals rest length differ", mod.equalsRest(["a", 1], ["a", 1, 2]), false);
|
|
225
|
+
expectClone("clone rest solo", mod.cloneRest(["a"]), ["a"]);
|
|
226
|
+
expectClone("clone rest multi", mod.cloneRest(["a", 1, 2]), ["a", 1, 2]);
|
|
227
|
+
`
|
|
@@ -4,8 +4,41 @@ func formatCheatSheet_RegexCall(text string) string {
|
|
|
4
4
|
return text + ".test($input)"
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
+
// formatCheatSheet_ALIASES maps an alternative `@format` spelling onto the
|
|
8
|
+
// canonical FormatCheatSheet key it means.
|
|
9
|
+
//
|
|
10
|
+
// An alias owns no validator. It resolves to the cheat sheet entry through
|
|
11
|
+
// formatCheatSheet_resolve, so FormatCheatSheet stays the single owner of every
|
|
12
|
+
// format's validator and a correction to one reaches every spelling of it. The
|
|
13
|
+
// aliases previously carried validator strings of their own, which made each of
|
|
14
|
+
// them a second implementation sharing a name and free to drift: `datetime`
|
|
15
|
+
// emitted `format: "date-time"` while validating with `new Date`, so it accepted
|
|
16
|
+
// February 30th and rejected the RFC 3339 leap second the cheat sheet handles.
|
|
17
|
+
//
|
|
18
|
+
// Aliases live beside the cheat sheet so that enumerating this file enumerates
|
|
19
|
+
// every owner of the `@format` contract.
|
|
20
|
+
var formatCheatSheet_ALIASES = map[string]string{
|
|
21
|
+
"datetime": "date-time",
|
|
22
|
+
"dateTime": "date-time",
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// formatCheatSheet_resolve resolves a written `@format` value to the canonical
|
|
26
|
+
// format name and the validator FormatCheatSheet owns for it, reporting whether
|
|
27
|
+
// the value names a supported format at all.
|
|
28
|
+
func formatCheatSheet_resolve(value string) (string, string, bool) {
|
|
29
|
+
name := value
|
|
30
|
+
if canonical, ok := formatCheatSheet_ALIASES[value]; ok {
|
|
31
|
+
name = canonical
|
|
32
|
+
}
|
|
33
|
+
validate, ok := FormatCheatSheet[name]
|
|
34
|
+
if ok == false {
|
|
35
|
+
return "", "", false
|
|
36
|
+
}
|
|
37
|
+
return name, validate, true
|
|
38
|
+
}
|
|
39
|
+
|
|
7
40
|
var FormatCheatSheet = map[string]string{
|
|
8
|
-
"byte":
|
|
41
|
+
"byte": `/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test($input)`,
|
|
9
42
|
"password": "true",
|
|
10
43
|
"regex": "(() => { try { new RegExp($input); return true; } catch { return false; } })()",
|
|
11
44
|
"uuid": "/^(?:urn:uuid:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i.test($input)",
|
|
@@ -13,16 +46,16 @@ var FormatCheatSheet = map[string]string{
|
|
|
13
46
|
"hostname": "/^(?=.{1,253}\\.?$)[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\\.[a-z0-9](?:[-0-9a-z]{0,61}[0-9a-z])?)*\\.?$/i.test($input)",
|
|
14
47
|
"idn-email": "/^(([^<>()[\\]\\.,;:\\s@\\\"]+(\\.[^<>()[\\]\\.,;:\\s@\\\"]+)*)|(\\\".+\\\"))@(([^<>()[\\]\\.,;:\\s@\\\"]+\\.)+[^<>()[\\]\\.,;:\\s@\\\"]{2,})$/i.test($input)",
|
|
15
48
|
"idn-hostname": "/^([a-z0-9\\u00a1-\\uffff0-9]+(-[a-z0-9\\u00a1-\\uffff0-9]+)*\\.)+[a-z\\u00a1-\\uffff]{2,}$/i.test($input)",
|
|
16
|
-
"iri": "/^[A-Za-z][
|
|
17
|
-
"iri-reference": "/^[A-Za-z][
|
|
49
|
+
"iri": `(() => !/[\u0000-\u0020\u007f-\u009f\ud800-\udfff"<>\\^\x60{|}]/u.test($input) && !/%(?![0-9A-Fa-f]{2})/u.test($input) && /^[A-Za-z][A-Za-z0-9+.-]*:/u.test($input))()`,
|
|
50
|
+
"iri-reference": `(() => { if (/[\u0000-\u0020\u007f-\u009f\ud800-\udfff"<>\\^\x60{|}]/u.test($input) || /%(?![0-9A-Fa-f]{2})/u.test($input)) return false; const colon = $input.indexOf(":"); const boundary = $input.search(/[/?#]/u); return colon === -1 || (boundary !== -1 && boundary < colon) || /^[A-Za-z][A-Za-z0-9+.-]*:/u.test($input); })()`,
|
|
18
51
|
"ipv4": "/^(?:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)$/.test($input)",
|
|
19
|
-
"ipv6":
|
|
52
|
+
"ipv6": `/^((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))$/i.test($input)`,
|
|
20
53
|
"uri": "/\\/|:/.test($input) && /^(?:[a-z][a-z0-9+\\-.]*:)(?:\\/?\\/(?:(?:[a-z0-9\\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\\.[a-z0-9\\-._~!$&'()*+,;=:]+)\\]|(?:(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)|(?:[a-z0-9\\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\\d*)?(?:\\/(?:[a-z0-9\\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\\/(?:(?:[a-z0-9\\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\\/(?:[a-z0-9\\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\\/(?:[a-z0-9\\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)(?:\\?(?:[a-z0-9\\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i.test($input)",
|
|
21
|
-
"uri-reference": "/^(?:[a-z][a-z0-9+\\-.]*:)?(?:\\/?\\/(?:(?:[a-z0-9\\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\\.[a-z0-9\\-._~!$&'()*+,;=:]+)\\]|(?:(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)|(?:[a-z0-9\\-._~!$&'
|
|
54
|
+
"uri-reference": "/^(?:(?:[a-z][a-z0-9+\\-.]*:)?(?:\\/?\\/(?:(?:[a-z0-9\\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\\.[a-z0-9\\-._~!$&'()*+,;=:]+)\\]|(?:(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)|(?:[a-z0-9\\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\\d*)?(?:\\/(?:[a-z0-9\\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\\/(?:(?:[a-z0-9\\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\\/(?:[a-z0-9\\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?)?|(?:[a-z][a-z0-9+\\-.]*:)(?:[a-z0-9\\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\\/(?:[a-z0-9\\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|(?:[a-z0-9\\-._~!$&'()*+,;=@]|%[0-9a-f]{2})+(?:\\/(?:[a-z0-9\\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)(?:\\?(?:[a-z0-9\\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i.test($input)",
|
|
22
55
|
"uri-template": "/^(?:(?:[^\\x00-\\x20\"'<>%\\\\^`{|}]|%[0-9a-f]{2})|\\{[+#./;?&=,!@|]?(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\\*)?(?:,(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\\*)?)*\\})*$/i.test($input)",
|
|
23
56
|
"url": "/^(?:https?|ftp):\\/\\/(?:[^\\s/?#@]+(?::[^\\s/?#@]*)?@)?(?:(?!(?:10|127)(?:\\.\\d{1,3}){3})(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?=.{1,253}(?::\\d{2,5})?(?:\\/[^\\s]*)?$)(?:[a-z0-9\\u00a1-\\uffff](?:[-a-z0-9\\u00a1-\\uffff]{0,61}[a-z0-9\\u00a1-\\uffff])?\\.)+(?:[a-z\\u00a1-\\uffff](?:[-a-z0-9\\u00a1-\\uffff]{0,61}[a-z0-9\\u00a1-\\uffff])))(?::\\d{2,5})?(?:\\/[^\\s]*)?$/iu.test($input)",
|
|
24
|
-
"date-time":
|
|
25
|
-
"date":
|
|
57
|
+
"date-time": `(() => { const match = /^([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])[Tt]((?:[01][0-9]|2[0-3])):([0-5][0-9]):([0-5][0-9]|60)(?:\.[0-9]+)?(?:[Zz]|([+-])((?:[01][0-9]|2[0-3])):([0-5][0-9]))$/.exec($input); if (match === null) return false; const year = Number(match[1]); const month = Number(match[2]); const day = Number(match[3]); if (day > [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month - 1] + (month === 2 && (year % 400 === 0 || (year % 4 === 0 && year % 100 !== 0)) ? 1 : 0)) return false; if (match[6] !== "60") return true; const instant = new Date(0); instant.setUTCFullYear(year, month - 1, day); instant.setUTCHours(Number(match[4]), Number(match[5]), 0, 0); const offset = match[7] === undefined ? 0 : (match[7] === "+" ? 1 : -1) * (Number(match[8]) * 60 + Number(match[9])); instant.setUTCMinutes(instant.getUTCMinutes() - offset); return instant.getUTCHours() === 23 && instant.getUTCMinutes() === 59 && ((instant.getUTCMonth() === 5 && instant.getUTCDate() === 30) || (instant.getUTCMonth() === 11 && instant.getUTCDate() === 31)); })()`,
|
|
58
|
+
"date": `(() => { const match = /^([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/.exec($input); if (match === null) return false; const year = Number(match[1]); const month = Number(match[2]); const day = Number(match[3]); return day <= [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month - 1] + (month === 2 && (year % 400 === 0 || (year % 4 === 0 && year % 100 !== 0)) ? 1 : 0); })()`,
|
|
26
59
|
"time": "/^([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](?:\\.[0-9]{1,9})?(Z|[+-]([01][0-9]|2[0-3]):[0-5][0-9])$/i.test($input)",
|
|
27
60
|
"duration": "/^P(?!$)((\\d+Y)?(\\d+M)?(\\d+D)?(T(?=\\d)(\\d+H)?(\\d+M)?(\\d+S)?)?|(\\d+W)?)$/.test($input)",
|
|
28
61
|
"json-pointer": "/^(?:\\/(?:[^~/]|~0|~1)*)*$/.test($input)",
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
package factories
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
|
-
"
|
|
4
|
+
"fmt"
|
|
5
5
|
"strings"
|
|
6
|
+
"unicode/utf8"
|
|
6
7
|
|
|
7
8
|
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
8
9
|
shimprinter "github.com/microsoft/typescript-go/shim/printer"
|
|
@@ -71,12 +72,138 @@ func (identifierFactoryNamespace) GetName(input *shimast.Expression) string {
|
|
|
71
72
|
return "unknown"
|
|
72
73
|
}
|
|
73
74
|
|
|
75
|
+
// Postfix renders the accessor for `str` as JavaScript source for a string
|
|
76
|
+
// literal, because callers splice the result straight into emitted text (see
|
|
77
|
+
// AssertProgrammer and ValidateProgrammer building `_path + <postfix>`).
|
|
78
|
+
//
|
|
79
|
+
// The value of that literal must equal what the runtime helper
|
|
80
|
+
// `typia/lib/internal/_accessExpressionAsString` computes for the same key,
|
|
81
|
+
// since dynamic keys take that runtime path while sole-literal keys are folded
|
|
82
|
+
// here at compile time. Both must produce one path grammar, which
|
|
83
|
+
// `typia/lib/internal/_createStandardSchema` parses back with JSON.parse.
|
|
84
|
+
//
|
|
85
|
+
// So there are two nested levels, and they escape for different readers. The
|
|
86
|
+
// key becomes JSON text, which is part of the path a user sees and JSON.parse
|
|
87
|
+
// reads. That text is then embedded in JavaScript source. Escaping only one
|
|
88
|
+
// level emits a file that does not parse; escaping both for the same reader
|
|
89
|
+
// makes the reported path disagree with the runtime helper.
|
|
74
90
|
func (identifierFactoryNamespace) Postfix(str string) string {
|
|
75
91
|
if identifierFactory_variable(str) {
|
|
76
|
-
return "
|
|
92
|
+
return identifierFactory_source("." + str)
|
|
77
93
|
}
|
|
78
|
-
|
|
79
|
-
|
|
94
|
+
return identifierFactory_source("[" + identifierFactory_json(str) + "]")
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// identifierFactory_json renders `str` as JSON text, matching JSON.stringify so
|
|
98
|
+
// that the path this lands in is the one _accessExpressionAsString builds for
|
|
99
|
+
// the same key at runtime, and so JSON.parse in _createStandardSchema reads the
|
|
100
|
+
// key back out.
|
|
101
|
+
func identifierFactory_json(str string) string {
|
|
102
|
+
return identifierFactory_quote(str, false)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// identifierFactory_source renders `str` as JavaScript source for a string
|
|
106
|
+
// literal whose value is exactly `str`.
|
|
107
|
+
//
|
|
108
|
+
// This is JSON's escape set plus the line separators. JSON string syntax is
|
|
109
|
+
// otherwise a subset of JavaScript's: both forbid a raw `"` and `\`, and JSON
|
|
110
|
+
// already escapes every character below U+0020, which covers the CR and LF that
|
|
111
|
+
// JavaScript also forbids raw. U+2028 and U+2029 are the whole difference, being
|
|
112
|
+
// line terminators to JavaScript but ordinary characters to JSON.
|
|
113
|
+
func identifierFactory_source(str string) string {
|
|
114
|
+
return identifierFactory_quote(str, true)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// identifierFactory_quote writes a quoted literal, escaping the line separators
|
|
118
|
+
// only when the reader is a JavaScript parser.
|
|
119
|
+
//
|
|
120
|
+
// strconv.Quote cannot serve either role: it escapes for Go, and Go and
|
|
121
|
+
// JavaScript disagree. Quote renders U+0007 as `\a` and a non-printable astral
|
|
122
|
+
// rune as `\U0001d173`; JavaScript has neither escape and decodes them as the
|
|
123
|
+
// identity escapes `a` and `U`, silently corrupting the key, while JSON.parse
|
|
124
|
+
// rejects both outright.
|
|
125
|
+
func identifierFactory_quote(str string, source bool) string {
|
|
126
|
+
var builder strings.Builder
|
|
127
|
+
builder.Grow(len(str) + 2)
|
|
128
|
+
builder.WriteByte('"')
|
|
129
|
+
for i := 0; i < len(str); {
|
|
130
|
+
if char := str[i]; char < utf8.RuneSelf {
|
|
131
|
+
i++
|
|
132
|
+
switch char {
|
|
133
|
+
case '"':
|
|
134
|
+
builder.WriteString("\\\"")
|
|
135
|
+
case '\\':
|
|
136
|
+
builder.WriteString("\\\\")
|
|
137
|
+
case '\b':
|
|
138
|
+
builder.WriteString("\\b")
|
|
139
|
+
case '\f':
|
|
140
|
+
builder.WriteString("\\f")
|
|
141
|
+
case '\n':
|
|
142
|
+
builder.WriteString("\\n")
|
|
143
|
+
case '\r':
|
|
144
|
+
builder.WriteString("\\r")
|
|
145
|
+
case '\t':
|
|
146
|
+
builder.WriteString("\\t")
|
|
147
|
+
default:
|
|
148
|
+
// JSON forbids a raw control character in a string, and JSON.parse
|
|
149
|
+
// throws on one rather than reporting the validation issue that the
|
|
150
|
+
// path belongs to. Every other ASCII byte is safe verbatim.
|
|
151
|
+
if char < 0x20 {
|
|
152
|
+
builder.WriteString(identifierFactory_unicode_escape(rune(char)))
|
|
153
|
+
} else {
|
|
154
|
+
builder.WriteByte(char)
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
continue
|
|
158
|
+
}
|
|
159
|
+
if unit, size := identifierFactory_surrogate(str[i:]); size != 0 {
|
|
160
|
+
// A lone surrogate reaches here WTF-8 encoded and has no valid UTF-8
|
|
161
|
+
// form, so it survives only as an escape. JSON.stringify does the same.
|
|
162
|
+
builder.WriteString(identifierFactory_unicode_escape(unit))
|
|
163
|
+
i += size
|
|
164
|
+
continue
|
|
165
|
+
}
|
|
166
|
+
rune_, size := utf8.DecodeRuneInString(str[i:])
|
|
167
|
+
if rune_ == utf8.RuneError && size == 1 {
|
|
168
|
+
// Not UTF-8 at all. No escape can denote the byte, so spend the
|
|
169
|
+
// replacement character and keep the literal well-formed; the
|
|
170
|
+
// alternative is emitting a file that does not parse.
|
|
171
|
+
builder.WriteString(identifierFactory_unicode_escape(utf8.RuneError))
|
|
172
|
+
i++
|
|
173
|
+
continue
|
|
174
|
+
}
|
|
175
|
+
if source && (rune_ == '\u2028' || rune_ == '\u2029') {
|
|
176
|
+
// A line terminator to JavaScript, so a raw one would end the literal on
|
|
177
|
+
// a target below ES2019. Escaping it in the source is invisible to the
|
|
178
|
+
// reader of the path, because JavaScript decodes it straight back.
|
|
179
|
+
builder.WriteString(identifierFactory_unicode_escape(rune_))
|
|
180
|
+
i += size
|
|
181
|
+
continue
|
|
182
|
+
}
|
|
183
|
+
builder.WriteString(str[i : i+size])
|
|
184
|
+
i += size
|
|
185
|
+
}
|
|
186
|
+
builder.WriteByte('"')
|
|
187
|
+
return builder.String()
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// identifierFactory_unicode_escape writes the `\uXXXX` form, which denotes one
|
|
191
|
+
// UTF-16 code unit and so only spans the Basic Multilingual Plane. Every caller
|
|
192
|
+
// passes a control character, a surrogate, or the replacement character; an
|
|
193
|
+
// astral rune needs no escape and must keep taking the verbatim path, because
|
|
194
|
+
// four hex digits cannot spell it.
|
|
195
|
+
func identifierFactory_unicode_escape(value rune) string {
|
|
196
|
+
return fmt.Sprintf("\\u%04x", value)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// identifierFactory_surrogate decodes a leading WTF-8 encoded surrogate code
|
|
200
|
+
// unit, which utf8.DecodeRuneInString reports as an error because no valid
|
|
201
|
+
// UTF-8 sequence denotes one.
|
|
202
|
+
func identifierFactory_surrogate(str string) (rune, int) {
|
|
203
|
+
if len(str) < 3 || str[0] != 0xed || str[1] < 0xa0 || str[1] > 0xbf || str[2] < 0x80 || str[2] > 0xbf {
|
|
204
|
+
return 0, 0
|
|
205
|
+
}
|
|
206
|
+
return rune(str[0]&0x0f)<<12 | rune(str[1]&0x3f)<<6 | rune(str[2]&0x3f), 3
|
|
80
207
|
}
|
|
81
208
|
|
|
82
209
|
func (identifierFactoryNamespace) Parameter(name any, typeNode *shimast.TypeNode, init *shimast.Node, emit ...*shimprinter.EmitContext) *shimast.Node {
|