typia 13.0.1 → 13.1.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.
@@ -14,7 +14,7 @@ type ImportProgrammer struct {
14
14
  options_ ImportProgrammer_IOptions
15
15
  // emit_ switches import emission to AST-integration mode. When set, imports
16
16
  // become namespace imports created by emit_.Factory, and every reference is a
17
- // member access on NewGeneratedNameForNode so tsgo's module transform owns the
17
+ // member access on a cloned unique name so tsgo's module transform owns the
18
18
  // CommonJS aliasing. Nil keeps the legacy text-emission path with named,
19
19
  // default, namespace imports and bare identifier references.
20
20
  emit_ *shimprinter.EmitContext
@@ -51,6 +51,7 @@ type ImportProgrammer_TypeProps struct {
51
51
  type importProgrammer_asset struct {
52
52
  file string
53
53
  modSpec *shimast.Node
54
+ binding *shimast.Node
54
55
  Default *ImportProgrammer_IDefault
55
56
  namespace *ImportProgrammer_INamespace
56
57
  instances map[string]ImportProgrammer_IInstance
@@ -80,8 +81,7 @@ func (p *ImportProgrammer) SetEmitContext(ec *shimprinter.EmitContext) {
80
81
  }
81
82
 
82
83
  // moduleSpecifier returns the asset's module-specifier string literal, allocated
83
- // once and reused as the stable key for NewGeneratedNameForNode so the namespace
84
- // alias prints identically in the import declaration and every reference.
84
+ // once and reused by the namespace import declaration.
85
85
  func (p *ImportProgrammer) moduleSpecifier(asset *importProgrammer_asset) *shimast.Node {
86
86
  if asset.modSpec == nil {
87
87
  asset.modSpec = p.emit_.Factory.NewStringLiteral(asset.file, shimast.TokenFlagsNone)
@@ -89,11 +89,20 @@ func (p *ImportProgrammer) moduleSpecifier(asset *importProgrammer_asset) *shima
89
89
  return asset.modSpec
90
90
  }
91
91
 
92
+ // namespaceName returns a clone of the asset's unique generated identifier.
93
+ // Clones preserve the generated-name id while keeping distinct AST parents.
94
+ func (p *ImportProgrammer) namespaceName(asset *importProgrammer_asset) *shimast.Node {
95
+ if asset.binding == nil {
96
+ asset.binding = p.emit_.Factory.NewUniqueName(importProgrammer_moduleIdentifier(asset.file))
97
+ }
98
+ return asset.binding.Clone(p.emit_.Factory)
99
+ }
100
+
92
101
  // member builds `<namespace>.<name>` for the file, where <namespace> is the
93
102
  // generated name tsgo's module-transform binds to `require(file)`.
94
103
  func (p *ImportProgrammer) member(asset *importProgrammer_asset, name string) *shimast.Node {
95
104
  return p.emit_.Factory.NewPropertyAccessExpression(
96
- p.emit_.Factory.NewGeneratedNameForNode(p.moduleSpecifier(asset)),
105
+ p.namespaceName(asset),
97
106
  nil,
98
107
  p.emit_.Factory.NewIdentifier(name),
99
108
  shimast.NodeFlagsNone,
@@ -137,7 +146,7 @@ func (p *ImportProgrammer) Namespace(props ImportProgrammer_INamespace) *shimast
137
146
  asset.namespace = &copy
138
147
  }
139
148
  if p.emit_ != nil {
140
- return p.emit_.Factory.NewGeneratedNameForNode(p.moduleSpecifier(asset))
149
+ return p.namespaceName(asset)
141
150
  }
142
151
  return EmitFactory(p.emit_, importProgrammer_factory).NewIdentifier(asset.namespace.Name)
143
152
  }
@@ -222,7 +231,7 @@ func (p *ImportProgrammer) ToStatements() []*shimast.Node {
222
231
  p.emit_.Factory.NewImportClause(
223
232
  0,
224
233
  nil,
225
- p.emit_.Factory.NewNamespaceImport(p.emit_.Factory.NewGeneratedNameForNode(modSpec)),
234
+ p.emit_.Factory.NewNamespaceImport(p.namespaceName(asset)),
226
235
  ),
227
236
  modSpec,
228
237
  nil,
@@ -334,6 +343,31 @@ func importProgrammer_fileRank(file string) int {
334
343
  return 500
335
344
  }
336
345
 
346
+ func importProgrammer_moduleIdentifier(file string) string {
347
+ if index := strings.LastIndexAny(file, "/\\"); index != -1 {
348
+ file = file[index+1:]
349
+ }
350
+ if file == "" {
351
+ return "module"
352
+ }
353
+ var builder strings.Builder
354
+ for i := 0; i < len(file); i++ {
355
+ ch := file[i]
356
+ if i == 0 && '0' <= ch && ch <= '9' {
357
+ builder.WriteByte('_')
358
+ }
359
+ if ('a' <= ch && ch <= 'z') ||
360
+ ('A' <= ch && ch <= 'Z') ||
361
+ ('0' <= ch && ch <= '9') ||
362
+ ch == '_' {
363
+ builder.WriteByte(ch)
364
+ } else {
365
+ builder.WriteByte('_')
366
+ }
367
+ }
368
+ return builder.String()
369
+ }
370
+
337
371
  func (p *ImportProgrammer) take(file string) *importProgrammer_asset {
338
372
  if asset, ok := p.assets_[file]; ok {
339
373
  return asset
@@ -0,0 +1,29 @@
1
+ //go:build typia_native_internal
2
+ // +build typia_native_internal
3
+
4
+ package context
5
+
6
+ import "testing"
7
+
8
+ // TestImportProgrammerModuleIdentifier verifies module names become valid bases.
9
+ //
10
+ // Unique generated names still need a readable JavaScript identifier base.
11
+ // Scoped packages, punctuation, leading digits, and Windows-style separators
12
+ // must not reintroduce invalid namespace import bindings.
13
+ //
14
+ // 1. Convert representative internal, scoped, numeric, and empty module names.
15
+ // 2. Assert each result matches the identifier base used by the printer.
16
+ func TestImportProgrammerModuleIdentifier(t *testing.T) {
17
+ cases := map[string]string{
18
+ "typia/lib/internal/_randomNumber": "_randomNumber",
19
+ "@scope/package-name": "package_name",
20
+ "123-module": "_123_module",
21
+ `scope\windows-name`: "windows_name",
22
+ "": "module",
23
+ }
24
+ for input, expected := range cases {
25
+ if actual := importProgrammer_moduleIdentifier(input); actual != expected {
26
+ t.Fatalf("identifier mismatch for %q: expected %q, got %q", input, expected, actual)
27
+ }
28
+ }
29
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typia",
3
- "version": "13.0.1",
3
+ "version": "13.1.0",
4
4
  "description": "Superfast runtime validators with only one line",
5
5
  "main": "lib/index.js",
6
6
  "exports": {
@@ -50,8 +50,8 @@
50
50
  "inquirer": "^8.2.5",
51
51
  "randexp": "^0.5.3",
52
52
  "tinyglobby": "^0.2.12",
53
- "@typia/utils": "^13.0.1",
54
- "@typia/interface": "^13.0.1"
53
+ "@typia/interface": "^13.1.0",
54
+ "@typia/utils": "^13.1.0"
55
55
  },
56
56
  "devDependencies": {
57
57
  "@types/inquirer": "^8.2.5",
@@ -60,7 +60,7 @@
60
60
  "rimraf": "^6.1.2",
61
61
  "rolldown": "^1.1.5",
62
62
  "suppress-warnings": "^1.0.2",
63
- "ttsc": "^0.17.3",
63
+ "ttsc": "^0.18.4",
64
64
  "typescript": "^7.0.2"
65
65
  },
66
66
  "sideEffects": false,