@zyno-io/ts-reflection 26.803.2224

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.
Files changed (61) hide show
  1. package/README.md +13 -0
  2. package/dist/index.cjs +1 -0
  3. package/dist/index.d.ts +3 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +966 -0
  6. package/dist/reflection/annotations.d.ts +15 -0
  7. package/dist/reflection/annotations.d.ts.map +1 -0
  8. package/dist/reflection/compact-metadata.d.ts +18 -0
  9. package/dist/reflection/compact-metadata.d.ts.map +1 -0
  10. package/dist/reflection/conversion.d.ts +15 -0
  11. package/dist/reflection/conversion.d.ts.map +1 -0
  12. package/dist/reflection/deserializer.d.ts +15 -0
  13. package/dist/reflection/deserializer.d.ts.map +1 -0
  14. package/dist/reflection/errors.d.ts +8 -0
  15. package/dist/reflection/errors.d.ts.map +1 -0
  16. package/dist/reflection/index.d.ts +10 -0
  17. package/dist/reflection/index.d.ts.map +1 -0
  18. package/dist/reflection/metadata-store.d.ts +20 -0
  19. package/dist/reflection/metadata-store.d.ts.map +1 -0
  20. package/dist/reflection/model.d.ts +273 -0
  21. package/dist/reflection/model.d.ts.map +1 -0
  22. package/dist/reflection/primitive-conversion.d.ts +2 -0
  23. package/dist/reflection/primitive-conversion.d.ts.map +1 -0
  24. package/dist/reflection/reflection-class.d.ts +60 -0
  25. package/dist/reflection/reflection-class.d.ts.map +1 -0
  26. package/dist/reflection/type-utils.d.ts +34 -0
  27. package/dist/reflection/type-utils.d.ts.map +1 -0
  28. package/dist/type-compiler/download-prebuilt.cjs +114 -0
  29. package/dist/type-compiler/go/ast_expression.go +187 -0
  30. package/dist/type-compiler/go/ast_metadata.go +388 -0
  31. package/dist/type-compiler/go/collect.go +963 -0
  32. package/dist/type-compiler/go/compact_metadata.go +553 -0
  33. package/dist/type-compiler/go/emission_plan.go +340 -0
  34. package/dist/type-compiler/go/emit_ast.go +557 -0
  35. package/dist/type-compiler/go/emit_ast_test.go +558 -0
  36. package/dist/type-compiler/go/go.mod +10 -0
  37. package/dist/type-compiler/go/plugin.go +359 -0
  38. package/dist/type-compiler/go/plugin_test.go +1206 -0
  39. package/dist/type-compiler/go/precompute.go +86 -0
  40. package/dist/type-compiler/go/receive_type.go +912 -0
  41. package/dist/type-compiler/go/resolve.go +265 -0
  42. package/dist/type-compiler/go/source_scan.go +51 -0
  43. package/dist/type-compiler/go/text_parse.go +734 -0
  44. package/dist/type-compiler/go/type_expr.go +1291 -0
  45. package/dist/type-compiler/go/typia_expr.go +2316 -0
  46. package/dist/type-compiler/index.cjs +43 -0
  47. package/dist/type-compiler/pnp.cjs +474 -0
  48. package/dist/type-compiler/prebuilt.cjs +324 -0
  49. package/dist/type-metadata-runtime.cjs +1 -0
  50. package/dist/type-metadata-runtime.d.ts +2 -0
  51. package/dist/type-metadata-runtime.d.ts.map +1 -0
  52. package/dist/type-metadata-runtime.js +107 -0
  53. package/dist/types/index.d.ts +4 -0
  54. package/dist/types/index.d.ts.map +1 -0
  55. package/dist/types/primitives.d.ts +33 -0
  56. package/dist/types/primitives.d.ts.map +1 -0
  57. package/dist/types/runtime.d.ts +2 -0
  58. package/dist/types/runtime.d.ts.map +1 -0
  59. package/dist/types/type-annotations.d.ts +28 -0
  60. package/dist/types/type-annotations.d.ts.map +1 -0
  61. package/package.json +47 -0
@@ -0,0 +1,340 @@
1
+ package main
2
+
3
+ import (
4
+ "fmt"
5
+ "sort"
6
+ "strings"
7
+
8
+ shimast "github.com/microsoft/typescript-go/shim/ast"
9
+ "github.com/samchon/ttsc/packages/ttsc/driver"
10
+ )
11
+
12
+ type emissionPlans map[string]*fileEmissionPlan
13
+
14
+ type fileEmissionPlan struct {
15
+ calls map[int]callEmissionPlan
16
+ classes map[int]classEmissionPlan
17
+ aliases *expressionTemplate
18
+ metadataTypes []expressionTemplate
19
+ metadataTypeResolver string
20
+ commonJS bool
21
+ }
22
+
23
+ type callEmissionPlan struct {
24
+ name string
25
+ metadataArgIndex int
26
+ metadata expressionTemplate
27
+ }
28
+
29
+ type classEmissionPlan struct {
30
+ name string
31
+ metadata expressionTemplate
32
+ }
33
+
34
+ type metadataTypeInterner struct {
35
+ names map[string]string
36
+ expressions []expressionTemplate
37
+ prefix string
38
+ err error
39
+ }
40
+
41
+ func newMetadataTypeInterner(sourceText string) *metadataTypeInterner {
42
+ prefix := "__tsf_metadata_type"
43
+ for strings.Contains(sourceText, prefix) {
44
+ prefix = "_" + prefix
45
+ }
46
+ return &metadataTypeInterner{names: map[string]string{}, prefix: prefix}
47
+ }
48
+
49
+ func (interner *metadataTypeInterner) reference(expr string) string {
50
+ template, err := parseExpressionTemplate(expr)
51
+ if err != nil {
52
+ if interner.err == nil {
53
+ interner.err = err
54
+ }
55
+ return expr
56
+ }
57
+ if !isShareableMetadataType(template.parsed) {
58
+ return expr
59
+ }
60
+ if name := interner.names[expr]; name != "" {
61
+ return fmt.Sprintf("%s(%s)", interner.prefix, name)
62
+ }
63
+ name := fmt.Sprintf("%d", len(interner.expressions))
64
+ interner.names[expr] = name
65
+ interner.expressions = append(interner.expressions, template)
66
+ return fmt.Sprintf("%s(%s)", interner.prefix, name)
67
+ }
68
+
69
+ // Shared metadata is emitted at module scope. Only JSON data and primitive
70
+ // values that cannot capture a lexical binding are safe to move there. Class
71
+ // and validator thunks must remain at their original class or call site.
72
+ func isShareableMetadataType(expression *shimast.Node) bool {
73
+ encoding := encodeCompactMetadata(expression)
74
+ for _, reference := range encoding.references {
75
+ if reference == nil {
76
+ return false
77
+ }
78
+ switch reference.Kind {
79
+ case shimast.KindBigIntLiteral:
80
+ continue
81
+ case shimast.KindIdentifier:
82
+ if reference.Text() == "undefined" {
83
+ continue
84
+ }
85
+ }
86
+ return false
87
+ }
88
+ return true
89
+ }
90
+
91
+ func buildEmissionPlans(reg *registry, program *driver.Program, emitTypeAliases bool, emitMetadataRuntimeImport bool) (emissionPlans, error) {
92
+ plans := emissionPlans{}
93
+ for _, info := range reg.files {
94
+ if info == nil || info.file == nil || info.file.IsDeclarationFile {
95
+ continue
96
+ }
97
+ plan := &fileEmissionPlan{
98
+ calls: map[int]callEmissionPlan{},
99
+ classes: map[int]classEmissionPlan{},
100
+ }
101
+ metadataTypes := newMetadataTypeInterner(info.file.Text())
102
+ if program != nil && program.TSProgram != nil {
103
+ plan.commonJS = program.TSProgram.GetEmitModuleFormatOfFile(info.file).String() == "CommonJS"
104
+ }
105
+ for _, call := range info.calls {
106
+ if call.nodePos < 0 {
107
+ return nil, fmt.Errorf("%s:%d: metadata call %s could not be correlated to a CallExpression", info.file.FileName(), call.pos, call.name)
108
+ }
109
+ expr := metadataTypes.reference(cachedTypeExpr(info, reg, call.typeText, call.typeNode, call.pos, call.metadataText))
110
+ template, err := parseExpressionTemplate(expr)
111
+ if err != nil {
112
+ return nil, fmt.Errorf("%s:%d: metadata call %s: %w", info.file.FileName(), call.pos, call.name, err)
113
+ }
114
+ plan.calls[call.nodePos] = callEmissionPlan{
115
+ name: call.name,
116
+ metadataArgIndex: call.metadataArgIndex,
117
+ metadata: template,
118
+ }
119
+ }
120
+ classes := append([]*classInfo(nil), info.classes...)
121
+ sort.Slice(classes, func(i, j int) bool { return classes[i].pos < classes[j].pos })
122
+ for _, class := range classes {
123
+ if class.ambient {
124
+ continue
125
+ }
126
+ template, err := parseExpressionTemplate(classMetadata(info, reg, class, metadataTypes.reference))
127
+ if err != nil {
128
+ return nil, fmt.Errorf("%s:%d: class metadata for %s: %w", info.file.FileName(), class.pos, class.name, err)
129
+ }
130
+ plan.classes[class.pos] = classEmissionPlan{name: class.name, metadata: template}
131
+ }
132
+ if metadataTypes.err != nil {
133
+ return nil, fmt.Errorf("%s: shared metadata type: %w", info.file.FileName(), metadataTypes.err)
134
+ }
135
+ plan.metadataTypes = metadataTypes.expressions
136
+ if len(plan.metadataTypes) != 0 {
137
+ plan.metadataTypeResolver = metadataTypes.prefix
138
+ }
139
+ if emitTypeAliases && !hasAliasMetadataSourceDeclaration(info.file) {
140
+ if expr := aliasMetadataExpression(info, reg); expr != "" {
141
+ template, err := parseExpressionTemplate(expr)
142
+ if err != nil {
143
+ return nil, fmt.Errorf("%s: alias metadata: %w", info.file.FileName(), err)
144
+ }
145
+ plan.aliases = &template
146
+ }
147
+ }
148
+ if !emitMetadataRuntimeImport {
149
+ if requirement := metadataRuntimeRequirement(plan); requirement != "" {
150
+ return nil, fmt.Errorf(
151
+ "%s: %s requires %s, but emitMetadataRuntimeImport is false",
152
+ info.file.FileName(),
153
+ requirement,
154
+ compactMetadataRuntimeSpec,
155
+ )
156
+ }
157
+ }
158
+ if len(plan.calls) != 0 || len(plan.classes) != 0 || plan.aliases != nil {
159
+ plans[info.file.FileName()] = plan
160
+ }
161
+ }
162
+ return plans, nil
163
+ }
164
+
165
+ // metadataRuntimeRequirement reports the first generated construct that cannot
166
+ // be emitted without TSF's compact metadata runtime. Alias registries made only
167
+ // of JSON stay self-contained; all other current metadata surfaces use runtime
168
+ // decoding or a shared runtime registry by design.
169
+ func metadataRuntimeRequirement(plan *fileEmissionPlan) string {
170
+ if plan == nil {
171
+ return ""
172
+ }
173
+ if plan.aliases != nil && !compactMetadataIsPureJSON(plan.aliases.parsed) {
174
+ if names := runtimeAliasMetadataNames(plan.aliases.parsed); len(names) != 0 {
175
+ return "reflected alias metadata for " + strings.Join(names, ", ")
176
+ }
177
+ return "reflected alias metadata"
178
+ }
179
+ if len(plan.classes) != 0 {
180
+ return "reflected class metadata"
181
+ }
182
+ if len(plan.calls) != 0 {
183
+ return "reflected call metadata"
184
+ }
185
+ if len(plan.metadataTypes) != 0 {
186
+ return "the reflected metadata registry"
187
+ }
188
+ return ""
189
+ }
190
+
191
+ func runtimeAliasMetadataNames(metadata *shimast.Node) []string {
192
+ for metadata != nil && metadata.Kind == shimast.KindParenthesizedExpression {
193
+ metadata = metadata.AsParenthesizedExpression().Expression
194
+ }
195
+ if metadata == nil || metadata.Kind != shimast.KindObjectLiteralExpression {
196
+ return nil
197
+ }
198
+ names := []string{}
199
+ for _, property := range metadata.AsObjectLiteralExpression().Properties.Nodes {
200
+ name, ok := compactMetadataPropertyName(property)
201
+ if !ok {
202
+ continue
203
+ }
204
+ assignment := property.AsPropertyAssignment()
205
+ if assignment == nil || compactMetadataIsPureJSON(assignment.Initializer) {
206
+ continue
207
+ }
208
+ names = append(names, name)
209
+ }
210
+ return names
211
+ }
212
+
213
+ func compactMetadataIsPureJSON(metadata *shimast.Node) bool {
214
+ encoding := encodeCompactMetadata(metadata)
215
+ return len(encoding.references) == 0 && !strings.Contains(encoding.serialized, `"$tsf`)
216
+ }
217
+
218
+ func aliasMetadataExpression(info *fileInfo, reg *registry) string {
219
+ names := exportedTypeAliasNames(info, reg, map[string]bool{})
220
+ if len(names) == 0 {
221
+ return ""
222
+ }
223
+ entries := []string{}
224
+ for _, name := range names {
225
+ if alias, ok := info.aliases[name]; ok {
226
+ if len(alias.params) == 0 {
227
+ if expr := cachedAliasTypeExpr(info, reg, alias); expr != "" && !metadataExprTooLarge(expr) {
228
+ entries = append(entries, quote(name)+": "+withTypeName(expr, name))
229
+ }
230
+ }
231
+ continue
232
+ }
233
+ if decl, ok := chooseInterface(info, name, 0); ok {
234
+ if expr := interfaceObjectLiteralExpr(info, reg, name, decl, &typeContext{seen: map[string]bool{}}); !metadataExprTooLarge(expr) {
235
+ entries = append(entries, quote(name)+": "+expr)
236
+ }
237
+ continue
238
+ }
239
+ if alias, owner, _, ok := resolveExportedAlias(info, reg, name, map[string]bool{}); ok {
240
+ if len(alias.params) == 0 {
241
+ if expr := cachedAliasTypeExpr(owner, reg, alias); expr != "" && !metadataExprTooLarge(expr) {
242
+ entries = append(entries, quote(name)+": "+withTypeName(expr, name))
243
+ }
244
+ }
245
+ continue
246
+ }
247
+ if decl, owner, _, ok := resolveExportedInterfaceDecl(info, reg, name, map[string]bool{}); ok {
248
+ if expr := interfaceObjectLiteralExpr(owner, reg, name, decl, &typeContext{seen: map[string]bool{}}); !metadataExprTooLarge(expr) {
249
+ entries = append(entries, quote(name)+": "+expr)
250
+ }
251
+ }
252
+ }
253
+ if len(entries) == 0 {
254
+ return ""
255
+ }
256
+ return "{" + strings.Join(entries, ", ") + "}"
257
+ }
258
+
259
+ func cachedAliasTypeExpr(info *fileInfo, reg *registry, alias aliasInfo) string {
260
+ if alias.metadataTooLarge {
261
+ return ""
262
+ }
263
+ if strings.TrimSpace(alias.metadataText) != "" {
264
+ return alias.metadataText
265
+ }
266
+ return internalTypeExprForNode(info, reg, alias.body, alias.typeNode, alias.pos)
267
+ }
268
+
269
+ func metadataExprTooLarge(expr string) bool {
270
+ return len(expr) > 1000000
271
+ }
272
+
273
+ func hasAliasMetadataSourceDeclaration(file *shimast.SourceFile) bool {
274
+ if file == nil || file.Statements == nil {
275
+ return false
276
+ }
277
+ for _, statement := range file.Statements.Nodes {
278
+ if statement == nil || statement.Kind != shimast.KindVariableStatement {
279
+ continue
280
+ }
281
+ if statement.ModifierFlags()&shimast.ModifierFlagsAmbient != 0 {
282
+ continue
283
+ }
284
+ list := statement.AsVariableStatement().DeclarationList
285
+ if list == nil {
286
+ continue
287
+ }
288
+ for _, declaration := range list.AsVariableDeclarationList().Declarations.Nodes {
289
+ if declaration != nil && declaration.Name() != nil && declaration.Name().Kind == shimast.KindIdentifier && declaration.Name().Text() == "__tsfTypeAliases" {
290
+ return true
291
+ }
292
+ }
293
+ }
294
+ return false
295
+ }
296
+
297
+ func exportedTypeAliasNames(info *fileInfo, reg *registry, seen map[string]bool) []string {
298
+ if seen[info.moduleKey] {
299
+ return nil
300
+ }
301
+ seen[info.moduleKey] = true
302
+ names := map[string]bool{}
303
+ for name, alias := range info.aliases {
304
+ if alias.exported && len(alias.params) == 0 {
305
+ names[name] = true
306
+ }
307
+ }
308
+ for name, declarations := range info.interfaces {
309
+ for _, declaration := range declarations {
310
+ if declaration.exported {
311
+ names[name] = true
312
+ break
313
+ }
314
+ }
315
+ }
316
+ for name := range info.reexports {
317
+ if alias, _, _, ok := resolveExportedAlias(info, reg, name, map[string]bool{}); ok && len(alias.params) == 0 {
318
+ names[name] = true
319
+ continue
320
+ }
321
+ if _, _, _, ok := resolveExportedInterfaceDecl(info, reg, name, map[string]bool{}); ok {
322
+ names[name] = true
323
+ }
324
+ }
325
+ for _, ref := range info.exportStar {
326
+ target := reg.byPath[ref.source]
327
+ if target == nil {
328
+ continue
329
+ }
330
+ for _, name := range exportedTypeAliasNames(target, reg, seen) {
331
+ names[name] = true
332
+ }
333
+ }
334
+ out := make([]string, 0, len(names))
335
+ for name := range names {
336
+ out = append(out, name)
337
+ }
338
+ sort.Strings(out)
339
+ return out
340
+ }