Skip to content

Commit bf5c4f9

Browse files
committed
export site/lib/log-generation/sorbet-enums.json and site/lib/log-generation/sorbet-log-structs.json
1 parent 5670fdd commit bf5c4f9

File tree

3 files changed

+195
-3
lines changed

3 files changed

+195
-3
lines changed

site/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ next-env.d.ts
4444
# Exported log types and keys (generated by ./scripts/export_typescript_types.rb)
4545
lib/log-generation/log-types.ts
4646
lib/log-generation/log-keys.json
47+
lib/log-generation/sorbet-enums.json
48+
lib/log-generation/sorbet-log-structs.json
4749

4850
# Generated HTML - YARD docs, coverage reports, etc.
4951
public/yard/

test/tools/log_types_exporter_test.rb

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ def test_generates_typescript_types
4040

4141
# Test that it includes the union type
4242
assert_includes content, "export type Log =", "Should export Log union type"
43+
44+
# Check if the enums JSON file was created
45+
enums_json_file = File.join(File.dirname(@output_ts_file), "sorbet-enums.json")
46+
assert_path_exists enums_json_file, "Enums JSON file should have been created"
47+
48+
# Check if the log structs JSON file was created
49+
structs_json_file = File.join(File.dirname(@output_ts_file), "sorbet-log-structs.json")
50+
assert_path_exists structs_json_file, "Log structs JSON file should have been created"
4351
end
4452

4553
def test_generate_typescript_definitions
@@ -322,4 +330,87 @@ def test_exports_all_log_types_array
322330
assert_includes all_types_content, log_type, "AllLogTypes array should contain #{log_type}"
323331
end
324332
end
333+
334+
def test_exports_enums_to_json
335+
# Get the temp directory for output
336+
enums_json_file = File.join(@temp_dir, "sorbet-enums.json")
337+
338+
# Get the data
339+
data = @exporter.send(:generate_data)
340+
341+
# Export enums to JSON
342+
@exporter.export_enums_to_json(data[:enums], enums_json_file)
343+
344+
# Verify file exists
345+
assert_path_exists enums_json_file, "Enums JSON file should have been created"
346+
347+
# Read and parse the JSON
348+
json_data = JSON.parse(File.read(enums_json_file))
349+
350+
# Verify structure
351+
assert json_data.is_a?(Hash), "JSON data should be a hash"
352+
353+
# Check for specific enums
354+
assert json_data.key?("LogStruct::LogLevel"), "Should include LogStruct::LogLevel"
355+
assert json_data.key?("LogStruct::Source"), "Should include LogStruct::Source"
356+
assert json_data.key?("LogStruct::LogEvent"), "Should include LogStruct::LogEvent"
357+
358+
# Check that values are properly structured
359+
log_level_values = json_data["LogStruct::LogLevel"]
360+
assert log_level_values.is_a?(Array), "Values should be an array"
361+
assert log_level_values.first.is_a?(Hash), "Each value should be a hash"
362+
assert log_level_values.first.key?("name"), "Each value should have a name"
363+
assert log_level_values.first.key?("value"), "Each value should have a value"
364+
365+
# Check for specific enum values
366+
log_level_values.each do |value|
367+
if value["name"] == "Info"
368+
assert_equal "info", value["value"], "Info enum should serialize as 'info'"
369+
end
370+
end
371+
end
372+
373+
def test_exports_log_structs_to_json
374+
# Get the temp directory for output
375+
structs_json_file = File.join(@temp_dir, "sorbet-log-structs.json")
376+
377+
# Get the data
378+
data = @exporter.send(:generate_data)
379+
380+
# Export log structs to JSON
381+
@exporter.export_log_structs_to_json(data[:logs], structs_json_file)
382+
383+
# Verify file exists
384+
assert_path_exists structs_json_file, "Log structs JSON file should have been created"
385+
386+
# Read and parse the JSON
387+
json_data = JSON.parse(File.read(structs_json_file))
388+
389+
# Verify structure
390+
assert json_data.is_a?(Hash), "JSON data should be a hash"
391+
392+
# Check for specific structs
393+
assert json_data.key?("LogStruct::Log::Request"), "Should include LogStruct::Log::Request"
394+
assert json_data.key?("LogStruct::Log::Error"), "Should include LogStruct::Log::Error"
395+
assert json_data.key?("LogStruct::Log::Plain"), "Should include LogStruct::Log::Plain"
396+
397+
# Check struct structure
398+
request_struct = json_data["LogStruct::Log::Request"]
399+
assert_equal "Request", request_struct["name"], "Should have correct name"
400+
assert request_struct.key?("fields"), "Should have fields"
401+
402+
# Check field structure
403+
fields = request_struct["fields"]
404+
assert fields.is_a?(Hash), "Fields should be a hash"
405+
406+
# Check specific fields
407+
assert fields.key?("path"), "Should have path field"
408+
assert fields.key?("status"), "Should have status field"
409+
assert fields.key?("duration"), "Should have duration field"
410+
411+
# Check field types
412+
assert_equal "string", fields["path"]["type"], "Path should be a string"
413+
assert_equal "integer", fields["status"]["type"], "Status should be an integer"
414+
assert_equal "number", fields["duration"]["type"], "Duration should be a number"
415+
end
325416
end

tools/log_types_exporter.rb

Lines changed: 102 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ def initialize(output_ts_file = DEFAULT_OUTPUT_TS_FILE, log_struct_classes = nil
2828
# Public method to export TypeScript definitions and JSON key mappings to files
2929
sig { void }
3030
def export
31+
# Get the data once and reuse for all exports
32+
data = generate_data
33+
3134
# Export TypeScript definitions
3235
puts "Exporting LogStruct types to TypeScript..."
3336
puts "Output file: #{@output_ts_file}"
@@ -36,7 +39,7 @@ def export
3639
FileUtils.mkdir_p(File.dirname(@output_ts_file))
3740

3841
# Generate the TypeScript content
39-
content = generate_typescript_definitions
42+
content = generate_typescript(data)
4043

4144
# Write to file
4245
File.write(@output_ts_file, content)
@@ -45,6 +48,9 @@ def export
4548

4649
# Export LOG_KEYS mapping to JSON
4750
export_keys_to_json
51+
52+
# Export enums and log structs to JSON
53+
export_data_to_json(data)
4854
end
4955

5056
# Export LOG_KEYS mapping to a JSON file
@@ -70,15 +76,108 @@ def export_keys_to_json(output_json_file = nil)
7076
puts "Exported key mappings to #{output_json_file}"
7177
end
7278

79+
# Export both enums and log structs to JSON files
80+
sig { params(data: T::Hash[Symbol, T.untyped]).void }
81+
def export_data_to_json(data)
82+
# Export enums to JSON
83+
export_enums_to_json(data[:enums])
84+
85+
# Export log structs to JSON
86+
export_log_structs_to_json(data[:logs])
87+
end
88+
89+
# Export Sorbet enums to a JSON file
90+
sig { params(enums_data: T::Hash[Symbol, T::Array[String]], output_json_file: T.nilable(String)).void }
91+
def export_enums_to_json(enums_data, output_json_file = nil)
92+
# Default to the same directory as the TypeScript file
93+
output_json_file ||= File.join(File.dirname(@output_ts_file), "sorbet-enums.json")
94+
95+
puts "Exporting Sorbet enums to JSON..."
96+
puts "Output file: #{output_json_file}"
97+
98+
# Create output directory if needed
99+
FileUtils.mkdir_p(File.dirname(output_json_file))
100+
101+
# Format enum data for JSON
102+
json_enum_data = {}
103+
104+
# For each enum, get the full class name and values
105+
T::Enum.subclasses
106+
.select { |klass| klass.name.to_s.start_with?("LogStruct::") }
107+
.each do |enum_class|
108+
# Get the full enum name (e.g., "LogStruct::LogLevel")
109+
full_name = enum_class.name.to_s
110+
111+
# Get the simple name (e.g., "LogLevel")
112+
simple_name = full_name.split("::").last
113+
114+
# Skip if we don't have data for this enum
115+
next unless enums_data.key?(simple_name.to_sym)
116+
117+
# Map enum values to their constant names
118+
values_with_names = enum_class.values.map do |value|
119+
constant_name = enum_class.constants.find { |const_name| enum_class.const_get(const_name) == value }&.to_s
120+
serialized = value.serialize
121+
122+
# Return a hash with name and value
123+
{
124+
name: constant_name,
125+
value: serialized
126+
}
127+
end
128+
129+
# Add to the JSON data
130+
json_enum_data[full_name] = values_with_names
131+
end
132+
133+
# Write to file with pretty formatting
134+
File.write(output_json_file, JSON.pretty_generate(json_enum_data))
135+
136+
puts "Exported Sorbet enums to #{output_json_file}"
137+
end
138+
139+
# Export LogStruct log structs to a JSON file
140+
sig { params(logs_data: T::Hash[String, T::Hash[Symbol, T.untyped]], output_json_file: T.nilable(String)).void }
141+
def export_log_structs_to_json(logs_data, output_json_file = nil)
142+
# Default to the same directory as the TypeScript file
143+
output_json_file ||= File.join(File.dirname(@output_ts_file), "sorbet-log-structs.json")
144+
145+
puts "Exporting LogStruct log structs to JSON..."
146+
puts "Output file: #{output_json_file}"
147+
148+
# Create output directory if needed
149+
FileUtils.mkdir_p(File.dirname(output_json_file))
150+
151+
# Format structs data for JSON
152+
json_structs_data = {}
153+
154+
# Process each log struct class
155+
logs_data.each do |struct_name, struct_info|
156+
# Get the full class name
157+
full_name = "LogStruct::Log::#{struct_name}"
158+
159+
# Add to the structs data
160+
json_structs_data[full_name] = {
161+
name: struct_name,
162+
fields: struct_info[:fields].transform_keys(&:to_s)
163+
}
164+
end
165+
166+
# Write to file with pretty formatting
167+
File.write(output_json_file, JSON.pretty_generate(json_structs_data))
168+
169+
puts "Exported LogStruct log structs to #{output_json_file}"
170+
end
171+
73172
# Public method to generate TypeScript definitions as a string
74173
# This is the method we can test easily without file I/O
75174
sig { returns(String) }
76175
def generate_typescript_definitions
77176
# Get the data
78-
log_types_data = generate_data
177+
data = generate_data
79178

80179
# Transform data to TypeScript
81-
generate_typescript(log_types_data)
180+
generate_typescript(data)
82181
end
83182

84183
sig { returns(T::Hash[Symbol, T.untyped]) }

0 commit comments

Comments
 (0)