typia 13.1.19 → 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/lib/executable/FileSystemIdentity.d.ts +23 -0
- package/lib/executable/FileSystemIdentity.js +30 -0
- package/lib/executable/FileSystemIdentity.js.map +1 -1
- package/lib/executable/FileSystemIdentity.mjs +4 -0
- package/lib/executable/FileSystemIdentity.mjs.map +1 -1
- package/lib/executable/TypiaGenerateWizard.js +15 -9
- package/lib/executable/TypiaGenerateWizard.js.map +1 -1
- package/lib/executable/TypiaGenerateWizard.mjs +11 -7
- package/lib/executable/TypiaGenerateWizard.mjs.map +1 -1
- package/lib/internal/_ProtobufReader.d.ts +18 -3
- package/lib/internal/_ProtobufReader.js +39 -11
- package/lib/internal/_ProtobufReader.js.map +1 -1
- package/lib/internal/_ProtobufReader.mjs +37 -10
- package/lib/internal/_ProtobufReader.mjs.map +1 -1
- package/lib/internal/_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/_randomFormatByte.js +24 -1
- package/lib/internal/_randomFormatByte.js.map +1 -1
- package/lib/internal/_randomFormatByte.mjs +20 -2
- package/lib/internal/_randomFormatByte.mjs.map +1 -1
- package/lib/internal/_randomFormatDate.d.ts +3 -6
- package/lib/internal/_randomFormatDate.js +2 -10
- package/lib/internal/_randomFormatDate.js.map +1 -1
- package/lib/internal/_randomFormatDate.mjs +2 -6
- package/lib/internal/_randomFormatDate.mjs.map +1 -1
- package/lib/internal/_randomFormatDatetime.d.ts +3 -6
- package/lib/internal/_randomFormatDatetime.js +25 -8
- package/lib/internal/_randomFormatDatetime.js.map +1 -1
- package/lib/internal/_randomFormatDatetime.mjs +17 -7
- package/lib/internal/_randomFormatDatetime.mjs.map +1 -1
- package/lib/internal/_randomFormatDuration.js +23 -15
- package/lib/internal/_randomFormatDuration.js.map +1 -1
- package/lib/internal/_randomFormatDuration.mjs +23 -15
- package/lib/internal/_randomFormatDuration.mjs.map +1 -1
- package/lib/internal/_randomFormatIpv4.js +31 -1
- package/lib/internal/_randomFormatIpv4.js.map +1 -1
- package/lib/internal/_randomFormatIpv4.mjs +23 -2
- package/lib/internal/_randomFormatIpv4.mjs.map +1 -1
- package/lib/internal/_randomFormatIpv6.js +57 -1
- package/lib/internal/_randomFormatIpv6.js.map +1 -1
- package/lib/internal/_randomFormatIpv6.mjs +45 -2
- package/lib/internal/_randomFormatIpv6.mjs.map +1 -1
- package/lib/internal/_randomFormatJsonPointer.js +14 -2
- package/lib/internal/_randomFormatJsonPointer.js.map +1 -1
- package/lib/internal/_randomFormatJsonPointer.mjs +13 -3
- package/lib/internal/_randomFormatJsonPointer.mjs.map +1 -1
- package/lib/internal/_randomFormatRegex.js +14 -1
- package/lib/internal/_randomFormatRegex.js.map +1 -1
- package/lib/internal/_randomFormatRegex.mjs +14 -2
- package/lib/internal/_randomFormatRegex.mjs.map +1 -1
- package/lib/internal/_randomFormatRelativeJsonPointer.js +19 -5
- package/lib/internal/_randomFormatRelativeJsonPointer.js.map +1 -1
- package/lib/internal/_randomFormatRelativeJsonPointer.mjs +21 -6
- package/lib/internal/_randomFormatRelativeJsonPointer.mjs.map +1 -1
- package/lib/internal/_randomFormatTime.js +33 -7
- package/lib/internal/_randomFormatTime.js.map +1 -1
- package/lib/internal/_randomFormatTime.mjs +37 -5
- package/lib/internal/_randomFormatTime.mjs.map +1 -1
- package/lib/internal/_randomPattern.js.map +1 -1
- package/lib/internal/_randomPattern.mjs.map +1 -1
- package/lib/internal/_randomStringLength.d.ts +41 -10
- package/lib/internal/_randomStringLength.js +49 -13
- package/lib/internal/_randomStringLength.js.map +1 -1
- package/lib/internal/_randomStringLength.mjs +48 -13
- package/lib/internal/_randomStringLength.mjs.map +1 -1
- package/lib/internal/private/__notationRename.js.map +1 -1
- package/lib/internal/private/__notationRename.mjs.map +1 -1
- package/lib/internal/private/__randomComposition.d.ts +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/native/cmd/ttsc-typia/build.go +3 -0
- package/native/cmd/ttsc-typia/callable_interface_function_semantics_transform_test.go +331 -0
- package/native/cmd/ttsc-typia/callable_type_literal_boundaries_transform_test.go +1184 -0
- package/native/cmd/ttsc-typia/compare_functional_union_membership_transform_test.go +434 -0
- package/native/cmd/ttsc-typia/compare_template_literal_union_transform_test.go +241 -0
- package/native/cmd/ttsc-typia/default_library_spoof_native_identity_transform_test.go +216 -0
- package/native/cmd/ttsc-typia/json_schema_dynamic_key_determinism_transform_test.go +246 -0
- package/native/cmd/ttsc-typia/json_stringify_contextual_undefined_transform_test.go +556 -0
- package/native/cmd/ttsc-typia/lib_replacement_native_identity_transform_test.go +277 -0
- package/native/cmd/ttsc-typia/native_named_intersection_union_transform_test.go +390 -0
- package/native/cmd/ttsc-typia/node_buffer_native_exports_is_transform_test.go +526 -0
- package/native/cmd/ttsc-typia/package_declaration_native_identity_is_transform_test.go +293 -0
- package/native/cmd/ttsc-typia/protobuf_diagnostic_code_transform_test.go +167 -0
- package/native/cmd/ttsc-typia/symbol_index_domain_transform_test.go +316 -0
- package/native/cmd/ttsc-typia/transform.go +23 -0
- package/native/cmd/ttsc-typia/transform_helpers_test.go +77 -2
- package/native/cmd/ttsc-typia/user_global_native_identity_transform_test.go +484 -0
- package/native/core/factories/ProtobufFactory.go +6 -1
- package/native/core/factories/internal/metadata/MetadataHelper.go +185 -30
- package/native/core/factories/internal/metadata/emplace_metadata_object.go +25 -0
- package/native/core/factories/internal/metadata/iterate_metadata_function.go +1 -1
- package/native/core/factories/internal/metadata/iterate_metadata_intersection.go +103 -23
- package/native/core/factories/internal/metadata/iterate_metadata_map.go +3 -7
- package/native/core/factories/internal/metadata/iterate_metadata_native.go +32 -14
- package/native/core/factories/internal/metadata/iterate_metadata_set.go +3 -7
- package/native/core/programmers/compare/CompareEqualProgrammer.go +27 -13
- package/native/core/programmers/helpers/FunctionProgrammer.go +6 -13
- package/native/core/programmers/helpers/StringifyJoinder.go +129 -50
- package/native/core/programmers/helpers/joiner_branch_coverage_test.go +116 -120
- package/native/core/programmers/iterate/iterate_check_coverage_test.go +76 -158
- package/native/core/programmers/iterate/iterate_utility_coverage_test.go +231 -270
- package/native/core/programmers/iterate/json_schema_object.go +49 -7
- package/native/core/programmers/iterate/json_schema_pattern_property_order_test.go +44 -0
- package/native/core/programmers/iterate/openapi_v3_downgrader.go +34 -1
- package/native/core/programmers/iterate/template_runtime_pattern.go +11 -0
- package/native/core/programmers/json/JsonStringifyProgrammer.go +47 -6
- package/native/core/programmers/llm/LlmApplicationProgrammer.go +9 -1
- package/native/core/programmers/protobuf/ProtobufMessageProgrammer.go +1 -1
- package/native/core/schemas/metadata/MetadataCollection.go +0 -9
- package/native/core/schemas/metadata/MetadataDefaultLibrary.go +81 -0
- package/native/core/schemas/metadata/MetadataObjectType.go +7 -18
- package/native/go.mod +4 -4
- package/native/transform/features/protobuf/ProtobufMessageTransformer.go +1 -1
- package/package.json +3 -7
- package/src/executable/FileSystemIdentity.ts +33 -0
- package/src/executable/TypiaGenerateWizard.ts +18 -12
- package/src/internal/_ProtobufReader.ts +40 -11
- 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/_randomFormatByte.ts +30 -3
- package/src/internal/_randomFormatDate.ts +4 -20
- package/src/internal/_randomFormatDatetime.ts +34 -20
- package/src/internal/_randomFormatDuration.ts +19 -4
- package/src/internal/_randomFormatIpv4.ts +43 -3
- package/src/internal/_randomFormatIpv6.ts +67 -3
- package/src/internal/_randomFormatJsonPointer.ts +23 -3
- package/src/internal/_randomFormatRegex.ts +21 -3
- package/src/internal/_randomFormatRelativeJsonPointer.ts +23 -10
- package/src/internal/_randomFormatTime.ts +45 -12
- package/src/internal/_randomPattern.ts +4 -1
- package/src/internal/_randomStringLength.ts +61 -17
- package/src/internal/private/__notationRename.ts +1 -4
- package/src/internal/private/__randomComposition.ts +50 -0
- package/src/internal/private/__randomEpoch.ts +34 -0
- package/native/adapter/visit.go +0 -173
- package/native/adapter/visit_property_chain_edges_test.go +0 -129
- package/native/core/programmers/helpers/disable_function_programmer_declare.go +0 -10
- package/native/core/programmers/iterate/check_union_array_like.go +0 -422
- package/native/core/programmers/iterate/prune_object_properties.go +0 -105
- package/native/core/programmers/iterate/stringify_dynamic_properties.go +0 -219
- package/native/core/programmers/iterate/stringify_native.go +0 -14
- package/native/core/programmers/iterate/stringify_regular_properties.go +0 -112
- package/native/core/schemas/metadata/MetadataApplication.go +0 -41
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"fmt"
|
|
5
|
+
"os"
|
|
6
|
+
"os/exec"
|
|
7
|
+
"path/filepath"
|
|
8
|
+
"strings"
|
|
9
|
+
"testing"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
// TestPackageDeclarationNativeIdentityIsTransform pins runtime-native identity
|
|
13
|
+
// across ordinary package declarations and the genuine global controls (#2239).
|
|
14
|
+
//
|
|
15
|
+
// A declaration file is a normal published TypeScript package surface, so its
|
|
16
|
+
// source form cannot by itself establish that a Date/Map/Set/WeakMap symbol is
|
|
17
|
+
// the JavaScript native. The package types below are checker-equivalent to local
|
|
18
|
+
// structural controls and must keep their own members. Conversely, real global
|
|
19
|
+
// Date/Map/Set/WeakMap/WeakSet and Node-provided File/Blob types must retain
|
|
20
|
+
// their native checks.
|
|
21
|
+
//
|
|
22
|
+
// 1. Publish colliding structural declarations through a fixture package's
|
|
23
|
+
// index.d.ts and transform validators for them plus local controls.
|
|
24
|
+
// 2. Transform genuine global validators with DOM libraries excluded, making
|
|
25
|
+
// File and Blob come from the installed @types/node declaration package.
|
|
26
|
+
// 3. Inspect the emitted classification and execute all validators in Node,
|
|
27
|
+
// requiring an exact case count so an omitted branch cannot pass silently.
|
|
28
|
+
func TestPackageDeclarationNativeIdentityIsTransform(t *testing.T) {
|
|
29
|
+
project := packageDeclarationNativeIdentityProject(t)
|
|
30
|
+
transform := func(file string) string {
|
|
31
|
+
t.Helper()
|
|
32
|
+
out, errText, code := ttscTypiaTestCapture(func() int {
|
|
33
|
+
return runTransform([]string{
|
|
34
|
+
"--cwd", project,
|
|
35
|
+
"--tsconfig", "tsconfig.json",
|
|
36
|
+
"--file", file,
|
|
37
|
+
"--output", "js",
|
|
38
|
+
})
|
|
39
|
+
})
|
|
40
|
+
if code != 0 {
|
|
41
|
+
t.Fatalf("package declaration native identity transform %s failed: code=%d stderr=\n%s", file, code, errText)
|
|
42
|
+
}
|
|
43
|
+
return out
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
packageJS := transform("src/package.ts")
|
|
47
|
+
nativeJS := transform("src/native.ts")
|
|
48
|
+
failures := []string{}
|
|
49
|
+
for _, member := range []string{"stamp", "brandMap", "brandSet", "brandWeakMap"} {
|
|
50
|
+
if !strings.Contains(packageJS, member) {
|
|
51
|
+
failures = append(failures, fmt.Sprintf("package declaration member %q was dropped", member))
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
for _, gone := range []string{"instanceof Date", "instanceof Map", "instanceof Set", "instanceof WeakMap"} {
|
|
55
|
+
if strings.Contains(packageJS, gone) {
|
|
56
|
+
failures = append(failures, fmt.Sprintf("package declaration collision kept %q", gone))
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
for _, kept := range []string{
|
|
60
|
+
"instanceof Date",
|
|
61
|
+
"instanceof Map",
|
|
62
|
+
"instanceof Set",
|
|
63
|
+
"instanceof WeakMap",
|
|
64
|
+
"instanceof WeakSet",
|
|
65
|
+
"instanceof File",
|
|
66
|
+
"instanceof Blob",
|
|
67
|
+
} {
|
|
68
|
+
if !strings.Contains(nativeJS, kept) {
|
|
69
|
+
failures = append(failures, fmt.Sprintf("genuine native path %q was dropped", kept))
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
output, runtimeErr := packageDeclarationNativeIdentityRun(t, project, packageJS, nativeJS)
|
|
73
|
+
if runtimeErr != nil {
|
|
74
|
+
failures = append(failures, fmt.Sprintf("runtime matrix failed: %v\n%s", runtimeErr, output))
|
|
75
|
+
}
|
|
76
|
+
const expected = "RAN 30 CASES"
|
|
77
|
+
if !strings.Contains(output, expected) {
|
|
78
|
+
failures = append(failures, fmt.Sprintf("runtime runner did not report %q; got:\n%s", expected, output))
|
|
79
|
+
}
|
|
80
|
+
if len(failures) != 0 {
|
|
81
|
+
t.Fatalf("package declaration native identity mismatches:\n%s\n\npackage emit:\n%s\n\nnative emit:\n%s", strings.Join(failures, "\n"), packageJS, nativeJS)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
func packageDeclarationNativeIdentityProject(t *testing.T) string {
|
|
86
|
+
t.Helper()
|
|
87
|
+
root := ttscTypiaTestRepoRoot(t)
|
|
88
|
+
base := filepath.Join(root, "packages", "typia", "native", ".tmp-ttsc-typia-tests")
|
|
89
|
+
if err := os.MkdirAll(base, 0o755); err != nil {
|
|
90
|
+
t.Fatalf("mkdir temp base: %v", err)
|
|
91
|
+
}
|
|
92
|
+
dir, err := os.MkdirTemp(base, "package-declaration-native-identity-")
|
|
93
|
+
if err != nil {
|
|
94
|
+
t.Fatalf("create temp fixture: %v", err)
|
|
95
|
+
}
|
|
96
|
+
t.Cleanup(func() {
|
|
97
|
+
_ = os.RemoveAll(dir)
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
src := filepath.Join(dir, "src")
|
|
101
|
+
dependency := filepath.Join(dir, "node_modules", "native-name-package")
|
|
102
|
+
for _, path := range []string{src, dependency} {
|
|
103
|
+
if err := os.MkdirAll(path, 0o755); err != nil {
|
|
104
|
+
t.Fatalf("mkdir fixture path %s: %v", path, err)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
files := map[string]string{
|
|
108
|
+
filepath.Join(dir, "tsconfig.json"): packageDeclarationNativeIdentityTSConfig,
|
|
109
|
+
filepath.Join(dependency, "package.json"): packageDeclarationNativeIdentityPackageJSON,
|
|
110
|
+
filepath.Join(dependency, "index.d.ts"): packageDeclarationNativeIdentityDeclarations,
|
|
111
|
+
filepath.Join(src, "package.ts"): packageDeclarationNativeIdentitySource,
|
|
112
|
+
filepath.Join(src, "native.ts"): packageDeclarationNativeIdentityNativeSource,
|
|
113
|
+
}
|
|
114
|
+
for path, content := range files {
|
|
115
|
+
if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
|
|
116
|
+
t.Fatalf("write fixture file %s: %v", path, err)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return dir
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
func packageDeclarationNativeIdentityRun(t *testing.T, project string, packageJS string, nativeJS string) (string, error) {
|
|
123
|
+
t.Helper()
|
|
124
|
+
node, err := exec.LookPath("node")
|
|
125
|
+
if err != nil {
|
|
126
|
+
t.Skip("node executable not found")
|
|
127
|
+
return "", nil
|
|
128
|
+
}
|
|
129
|
+
runtimeDir := filepath.Join(project, "runtime")
|
|
130
|
+
if err := os.MkdirAll(runtimeDir, 0o755); err != nil {
|
|
131
|
+
t.Fatalf("mkdir runtime dir: %v", err)
|
|
132
|
+
}
|
|
133
|
+
ttscTypiaTestWriteCommonRuntimeStubs(t, runtimeDir)
|
|
134
|
+
modules := map[string]string{
|
|
135
|
+
"package.cjs": ttscTypiaTestRewriteCommonJS(t, packageJS),
|
|
136
|
+
"native.cjs": ttscTypiaTestRewriteCommonJS(t, nativeJS),
|
|
137
|
+
"run.cjs": packageDeclarationNativeIdentityRuntimeRunner,
|
|
138
|
+
}
|
|
139
|
+
for name, content := range modules {
|
|
140
|
+
if err := os.WriteFile(filepath.Join(runtimeDir, name), []byte(content), 0o644); err != nil {
|
|
141
|
+
t.Fatalf("write runtime file %s: %v", name, err)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
cmd := exec.Command(node, filepath.Join(runtimeDir, "run.cjs"))
|
|
145
|
+
cmd.Dir = runtimeDir
|
|
146
|
+
output, err := cmd.CombinedOutput()
|
|
147
|
+
return string(output), err
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const packageDeclarationNativeIdentityTSConfig = `{
|
|
151
|
+
"compilerOptions": {
|
|
152
|
+
"target": "ES2022",
|
|
153
|
+
"module": "commonjs",
|
|
154
|
+
"moduleResolution": "bundler",
|
|
155
|
+
"ignoreDeprecations": "6.0",
|
|
156
|
+
"lib": ["ES2022"],
|
|
157
|
+
"types": ["node"],
|
|
158
|
+
"esModuleInterop": true,
|
|
159
|
+
"strict": true,
|
|
160
|
+
"skipLibCheck": true
|
|
161
|
+
},
|
|
162
|
+
"include": ["src"]
|
|
163
|
+
}
|
|
164
|
+
`
|
|
165
|
+
|
|
166
|
+
const packageDeclarationNativeIdentityPackageJSON = `{
|
|
167
|
+
"name": "native-name-package",
|
|
168
|
+
"version": "1.0.0",
|
|
169
|
+
"types": "index.d.ts"
|
|
170
|
+
}
|
|
171
|
+
`
|
|
172
|
+
|
|
173
|
+
const packageDeclarationNativeIdentityDeclarations = `export interface Date {
|
|
174
|
+
stamp: number;
|
|
175
|
+
}
|
|
176
|
+
export interface Map<K, V> {
|
|
177
|
+
brandMap: K;
|
|
178
|
+
valueMap: V;
|
|
179
|
+
}
|
|
180
|
+
export interface Set<T> {
|
|
181
|
+
brandSet: T;
|
|
182
|
+
}
|
|
183
|
+
export interface WeakMap<K extends object, V> {
|
|
184
|
+
brandWeakMap: K;
|
|
185
|
+
valueWeakMap: V;
|
|
186
|
+
}
|
|
187
|
+
`
|
|
188
|
+
|
|
189
|
+
const packageDeclarationNativeIdentitySource = `import typia from "typia";
|
|
190
|
+
import type {
|
|
191
|
+
Date as PackageDate,
|
|
192
|
+
Map as PackageMap,
|
|
193
|
+
Set as PackageSet,
|
|
194
|
+
WeakMap as PackageWeakMap,
|
|
195
|
+
} from "native-name-package";
|
|
196
|
+
|
|
197
|
+
interface LocalDate {
|
|
198
|
+
stamp: number;
|
|
199
|
+
}
|
|
200
|
+
interface LocalMap<K, V> {
|
|
201
|
+
brandMap: K;
|
|
202
|
+
valueMap: V;
|
|
203
|
+
}
|
|
204
|
+
interface LocalSet<T> {
|
|
205
|
+
brandSet: T;
|
|
206
|
+
}
|
|
207
|
+
interface LocalWeakMap<K extends object, V> {
|
|
208
|
+
brandWeakMap: K;
|
|
209
|
+
valueWeakMap: V;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
type Assert<T extends true> = T;
|
|
213
|
+
type Same<X, Y> = [X] extends [Y]
|
|
214
|
+
? [Y] extends [X]
|
|
215
|
+
? true
|
|
216
|
+
: false
|
|
217
|
+
: false;
|
|
218
|
+
type _PackageDateIsLocal = Assert<Same<PackageDate, LocalDate>>;
|
|
219
|
+
type _PackageMapIsLocal = Assert<Same<PackageMap<string, number>, LocalMap<string, number>>>;
|
|
220
|
+
type _PackageSetIsLocal = Assert<Same<PackageSet<string>, LocalSet<string>>>;
|
|
221
|
+
type _PackageWeakMapIsLocal = Assert<Same<PackageWeakMap<object, string>, LocalWeakMap<object, string>>>;
|
|
222
|
+
|
|
223
|
+
export const isPackageDate = typia.createIs<PackageDate>();
|
|
224
|
+
export const isPackageMap = typia.createIs<PackageMap<string, number>>();
|
|
225
|
+
export const isPackageSet = typia.createIs<PackageSet<string>>();
|
|
226
|
+
export const isPackageWeakMap = typia.createIs<PackageWeakMap<object, string>>();
|
|
227
|
+
export const isLocalDate = typia.createIs<LocalDate>();
|
|
228
|
+
export const isLocalMap = typia.createIs<LocalMap<string, number>>();
|
|
229
|
+
export const isLocalSet = typia.createIs<LocalSet<string>>();
|
|
230
|
+
export const isLocalWeakMap = typia.createIs<LocalWeakMap<object, string>>();
|
|
231
|
+
`
|
|
232
|
+
|
|
233
|
+
const packageDeclarationNativeIdentityNativeSource = `import typia from "typia";
|
|
234
|
+
|
|
235
|
+
export const isNativeDate = typia.createIs<Date>();
|
|
236
|
+
export const isNativeMap = typia.createIs<Map<string, number>>();
|
|
237
|
+
export const isNativeSet = typia.createIs<Set<string>>();
|
|
238
|
+
export const isNativeWeakMap = typia.createIs<WeakMap<object, string>>();
|
|
239
|
+
export const isNativeWeakSet = typia.createIs<WeakSet<object>>();
|
|
240
|
+
export const isNativeFile = typia.createIs<File>();
|
|
241
|
+
export const isNativeBlob = typia.createIs<Blob>();
|
|
242
|
+
`
|
|
243
|
+
|
|
244
|
+
const packageDeclarationNativeIdentityRuntimeRunner = `const packageTypes = require("./package.cjs");
|
|
245
|
+
const natives = require("./native.cjs");
|
|
246
|
+
|
|
247
|
+
let ran = 0;
|
|
248
|
+
const failures = [];
|
|
249
|
+
const eq = (name, actual, expected) => {
|
|
250
|
+
ran += 1;
|
|
251
|
+
if (actual !== expected) {
|
|
252
|
+
failures.push(name + ": expected " + expected + " but got " + actual);
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
eq("package Date valid", packageTypes.isPackageDate({ stamp: 1 }), true);
|
|
257
|
+
eq("package Date invalid", packageTypes.isPackageDate({}), false);
|
|
258
|
+
eq("package Date rejects native", packageTypes.isPackageDate(new Date()), false);
|
|
259
|
+
eq("package Map valid", packageTypes.isPackageMap({ brandMap: "x", valueMap: 1 }), true);
|
|
260
|
+
eq("package Map invalid", packageTypes.isPackageMap({ brandMap: "x" }), false);
|
|
261
|
+
eq("package Map rejects native", packageTypes.isPackageMap(new Map([["x", 1]])), false);
|
|
262
|
+
eq("package Set valid", packageTypes.isPackageSet({ brandSet: "x" }), true);
|
|
263
|
+
eq("package Set invalid", packageTypes.isPackageSet({}), false);
|
|
264
|
+
eq("package Set rejects native", packageTypes.isPackageSet(new Set(["x"])), false);
|
|
265
|
+
eq("package WeakMap valid", packageTypes.isPackageWeakMap({ brandWeakMap: {}, valueWeakMap: "x" }), true);
|
|
266
|
+
eq("package WeakMap invalid", packageTypes.isPackageWeakMap({ brandWeakMap: {} }), false);
|
|
267
|
+
eq("package WeakMap rejects native", packageTypes.isPackageWeakMap(new WeakMap()), false);
|
|
268
|
+
|
|
269
|
+
eq("local Date control", packageTypes.isLocalDate({ stamp: 1 }), true);
|
|
270
|
+
eq("local Map control", packageTypes.isLocalMap({ brandMap: "x", valueMap: 1 }), true);
|
|
271
|
+
eq("local Set control", packageTypes.isLocalSet({ brandSet: "x" }), true);
|
|
272
|
+
eq("local WeakMap control", packageTypes.isLocalWeakMap({ brandWeakMap: {}, valueWeakMap: "x" }), true);
|
|
273
|
+
|
|
274
|
+
eq("native Date real", natives.isNativeDate(new Date()), true);
|
|
275
|
+
eq("native Date plain", natives.isNativeDate({}), false);
|
|
276
|
+
eq("native Map real", natives.isNativeMap(new Map([["x", 1]])), true);
|
|
277
|
+
eq("native Map plain", natives.isNativeMap({}), false);
|
|
278
|
+
eq("native Set real", natives.isNativeSet(new Set(["x"])), true);
|
|
279
|
+
eq("native Set plain", natives.isNativeSet({}), false);
|
|
280
|
+
eq("native WeakMap real", natives.isNativeWeakMap(new WeakMap()), true);
|
|
281
|
+
eq("native WeakMap plain", natives.isNativeWeakMap({}), false);
|
|
282
|
+
eq("native WeakSet real", natives.isNativeWeakSet(new WeakSet()), true);
|
|
283
|
+
eq("native WeakSet plain", natives.isNativeWeakSet({}), false);
|
|
284
|
+
eq("Node File real", natives.isNativeFile(new File(["x"], "x.txt")), true);
|
|
285
|
+
eq("Node File plain", natives.isNativeFile({ name: "x.txt", size: 1 }), false);
|
|
286
|
+
eq("Node Blob real", natives.isNativeBlob(new Blob(["x"])), true);
|
|
287
|
+
eq("Node Blob plain", natives.isNativeBlob({ size: 1, type: "text/plain" }), false);
|
|
288
|
+
|
|
289
|
+
console.log("RAN " + ran + " CASES");
|
|
290
|
+
if (failures.length !== 0) {
|
|
291
|
+
throw new Error("MISMATCHES:\n" + failures.join("\n"));
|
|
292
|
+
}
|
|
293
|
+
`
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"os"
|
|
5
|
+
"path/filepath"
|
|
6
|
+
"regexp"
|
|
7
|
+
"sort"
|
|
8
|
+
"strings"
|
|
9
|
+
"testing"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
// TestProtobufDiagnosticCodeTransform verifies that a rejected protobuf call
|
|
13
|
+
// site is named by its own API in the diagnostic code (#2285).
|
|
14
|
+
//
|
|
15
|
+
// `ProtobufFactory.Metadata` used to compose the code as `"typia.protobuf." +
|
|
16
|
+
// props.Method`, while the encode and decode programmers pass the whole call
|
|
17
|
+
// accessor (`ModuloMethodText`, the same text `TypeGuardError.method` carries).
|
|
18
|
+
// Sixteen of the seventeen entry points therefore reported
|
|
19
|
+
// `TS(typia.protobuf.typia.protobuf.encode)`; only `protobuf.message` was
|
|
20
|
+
// correct, because its programmer passed a bare literal. The code is the only
|
|
21
|
+
// machine-readable identity a typia rejection has, so a code that names no API
|
|
22
|
+
// is a silent loss for anyone searching it.
|
|
23
|
+
//
|
|
24
|
+
// The oracle is the fixture source, not another copy of the expected string: a
|
|
25
|
+
// diagnostic code is correct only when the accessor it names is literally the
|
|
26
|
+
// accessor written at a call site in that file. A concatenation defect cannot
|
|
27
|
+
// satisfy that, and neither can a misspelling.
|
|
28
|
+
//
|
|
29
|
+
// 1. Write one fixture that calls every protobuf entry point with `bigint`,
|
|
30
|
+
// which none of them supports.
|
|
31
|
+
// 2. Transform it and collect every diagnostic code the transform reported.
|
|
32
|
+
// 3. Require each code to be an accessor present in the fixture, and require
|
|
33
|
+
// every entry point to have been named.
|
|
34
|
+
func TestProtobufDiagnosticCodeTransform(t *testing.T) {
|
|
35
|
+
methods := []string{
|
|
36
|
+
"message",
|
|
37
|
+
"encode",
|
|
38
|
+
"decode",
|
|
39
|
+
"assertEncode",
|
|
40
|
+
"assertDecode",
|
|
41
|
+
"isEncode",
|
|
42
|
+
"isDecode",
|
|
43
|
+
"validateEncode",
|
|
44
|
+
"validateDecode",
|
|
45
|
+
"createEncode",
|
|
46
|
+
"createDecode",
|
|
47
|
+
"createAssertEncode",
|
|
48
|
+
"createAssertDecode",
|
|
49
|
+
"createIsEncode",
|
|
50
|
+
"createIsDecode",
|
|
51
|
+
"createValidateEncode",
|
|
52
|
+
"createValidateDecode",
|
|
53
|
+
}
|
|
54
|
+
project, source := protobufDiagnosticCodeProject(t, methods)
|
|
55
|
+
out, errText, code := ttscTypiaTestCapture(func() int {
|
|
56
|
+
return runTransform([]string{
|
|
57
|
+
"--cwd", project,
|
|
58
|
+
"--tsconfig", "tsconfig.json",
|
|
59
|
+
})
|
|
60
|
+
})
|
|
61
|
+
if code == 0 {
|
|
62
|
+
t.Fatalf("protobuf fixture transformed successfully, want failure:\nstdout=%s\nstderr=%s", out, errText)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
codes := map[string]bool{}
|
|
66
|
+
for _, match := range protobufDiagnosticCodePattern.FindAllStringSubmatch(out, -1) {
|
|
67
|
+
codes[match[1]] = true
|
|
68
|
+
}
|
|
69
|
+
if len(codes) == 0 {
|
|
70
|
+
t.Fatalf("no typia diagnostic code was reported:\nstdout=%s\nstderr=%s", out, errText)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
unnamed := []string{}
|
|
74
|
+
for reported := range codes {
|
|
75
|
+
if !strings.Contains(source, reported+"<") {
|
|
76
|
+
unnamed = append(unnamed, reported)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
sort.Strings(unnamed)
|
|
80
|
+
if len(unnamed) != 0 {
|
|
81
|
+
t.Fatalf(
|
|
82
|
+
"diagnostic code(s) name no call site in the fixture: %s",
|
|
83
|
+
strings.Join(unnamed, ", "),
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
missing := []string{}
|
|
88
|
+
for _, method := range methods {
|
|
89
|
+
if !codes["typia.protobuf."+method] {
|
|
90
|
+
missing = append(missing, method)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if len(missing) != 0 {
|
|
94
|
+
t.Fatalf(
|
|
95
|
+
"no diagnostic named these entry points: %s\nstdout=%s",
|
|
96
|
+
strings.Join(missing, ", "),
|
|
97
|
+
out,
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// The command reports diagnostics as JSON, and `code` is the field ttsc renders
|
|
103
|
+
// as `error TS(<code>)`; reading it here keeps the assertion on the value the
|
|
104
|
+
// transform produced rather than on one renderer's formatting.
|
|
105
|
+
var protobufDiagnosticCodePattern = regexp.MustCompile(`"code":"([^"]+)"`)
|
|
106
|
+
|
|
107
|
+
func protobufDiagnosticCodeProject(t *testing.T, methods []string) (string, string) {
|
|
108
|
+
t.Helper()
|
|
109
|
+
root := ttscTypiaTestRepoRoot(t)
|
|
110
|
+
base := filepath.Join(root, "packages", "typia", "native", ".tmp-ttsc-typia-tests")
|
|
111
|
+
if err := os.MkdirAll(base, 0o755); err != nil {
|
|
112
|
+
t.Fatalf("mkdir temp base: %v", err)
|
|
113
|
+
}
|
|
114
|
+
dir, err := os.MkdirTemp(base, "protobuf-code-")
|
|
115
|
+
if err != nil {
|
|
116
|
+
t.Fatalf("create temp fixture: %v", err)
|
|
117
|
+
}
|
|
118
|
+
t.Cleanup(func() {
|
|
119
|
+
_ = os.RemoveAll(dir)
|
|
120
|
+
})
|
|
121
|
+
src := filepath.Join(dir, "src")
|
|
122
|
+
if err := os.MkdirAll(src, 0o755); err != nil {
|
|
123
|
+
t.Fatalf("mkdir fixture src: %v", err)
|
|
124
|
+
}
|
|
125
|
+
if err := os.WriteFile(filepath.Join(dir, "tsconfig.json"), []byte(protobufDiagnosticCodeTSConfig), 0o644); err != nil {
|
|
126
|
+
t.Fatalf("write tsconfig: %v", err)
|
|
127
|
+
}
|
|
128
|
+
lines := []string{`import typia from "typia";`, ""}
|
|
129
|
+
for _, method := range methods {
|
|
130
|
+
lines = append(lines, protobufDiagnosticCodeCall(method))
|
|
131
|
+
}
|
|
132
|
+
source := strings.Join(lines, "\n") + "\n"
|
|
133
|
+
if err := os.WriteFile(filepath.Join(src, "main.ts"), []byte(source), 0o644); err != nil {
|
|
134
|
+
t.Fatalf("write source: %v", err)
|
|
135
|
+
}
|
|
136
|
+
return dir, source
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// protobufDiagnosticCodeCall writes the call form each entry point takes: the
|
|
140
|
+
// factories take no value argument, the encoders take the message, and the
|
|
141
|
+
// decoders take the buffer.
|
|
142
|
+
func protobufDiagnosticCodeCall(method string) string {
|
|
143
|
+
call := "typia.protobuf." + method + "<bigint>"
|
|
144
|
+
switch {
|
|
145
|
+
case method == "message" || strings.HasPrefix(method, "create"):
|
|
146
|
+
return call + "();"
|
|
147
|
+
case strings.HasSuffix(method, "Decode"):
|
|
148
|
+
return call + "(new Uint8Array());"
|
|
149
|
+
default:
|
|
150
|
+
return call + "(1n as any);"
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const protobufDiagnosticCodeTSConfig = `{
|
|
155
|
+
"compilerOptions": {
|
|
156
|
+
"target": "ES2022",
|
|
157
|
+
"module": "commonjs",
|
|
158
|
+
"moduleResolution": "bundler",
|
|
159
|
+
"ignoreDeprecations": "6.0",
|
|
160
|
+
"types": ["*"],
|
|
161
|
+
"esModuleInterop": true,
|
|
162
|
+
"strict": true,
|
|
163
|
+
"skipLibCheck": true
|
|
164
|
+
},
|
|
165
|
+
"include": ["src"]
|
|
166
|
+
}
|
|
167
|
+
`
|