foobara-typescript-remote-command-generator 0.0.1
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +7 -0
- data/LICENSE-APACHE.txt +202 -0
- data/LICENSE-MIT.txt +21 -0
- data/LICENSE.txt +8 -0
- data/README.md +55 -0
- data/lib/foobara/typescript_remote_command_generator.rb +13 -0
- data/src/remote_generator/association_depth.rb +11 -0
- data/src/remote_generator/generate_typescript.rb +85 -0
- data/src/remote_generator/services/aggregate_entity_generator.rb +49 -0
- data/src/remote_generator/services/aggregate_model_generator.rb +53 -0
- data/src/remote_generator/services/atom_entity_generator.rb +47 -0
- data/src/remote_generator/services/atom_model_generator.rb +49 -0
- data/src/remote_generator/services/command_errors_generator.rb +36 -0
- data/src/remote_generator/services/command_errors_index_generator.rb +31 -0
- data/src/remote_generator/services/command_generator.rb +41 -0
- data/src/remote_generator/services/command_inputs_generator.rb +33 -0
- data/src/remote_generator/services/command_manifest_generator.rb +13 -0
- data/src/remote_generator/services/command_result_generator.rb +80 -0
- data/src/remote_generator/services/dependency_group.rb +137 -0
- data/src/remote_generator/services/domain_config_generator.rb +21 -0
- data/src/remote_generator/services/domain_generator.rb +63 -0
- data/src/remote_generator/services/domain_manifest_generator.rb +17 -0
- data/src/remote_generator/services/entity_generator.rb +43 -0
- data/src/remote_generator/services/entity_manifest_generator.rb +10 -0
- data/src/remote_generator/services/entity_variants_generator.rb +47 -0
- data/src/remote_generator/services/error_generator.rb +68 -0
- data/src/remote_generator/services/loaded_entity_generator.rb +27 -0
- data/src/remote_generator/services/manifest_generator.rb +13 -0
- data/src/remote_generator/services/model_generator.rb +84 -0
- data/src/remote_generator/services/model_manifest_generator.rb +11 -0
- data/src/remote_generator/services/model_variants_generator.rb +35 -0
- data/src/remote_generator/services/organization_config_generator.rb +21 -0
- data/src/remote_generator/services/organization_generator.rb +41 -0
- data/src/remote_generator/services/organization_manifest_generator.rb +17 -0
- data/src/remote_generator/services/processor_class_generator.rb +18 -0
- data/src/remote_generator/services/root_manifest_generator.rb +13 -0
- data/src/remote_generator/services/typescript_from_manifest_base_generator.rb +293 -0
- data/src/remote_generator/services/unloaded_entity_generator.rb +25 -0
- data/src/remote_generator/write_typescript_to_disk.rb +78 -0
- data/src/remote_generator.rb +5 -0
- data/templates/Command/Errors.ts.erb +11 -0
- data/templates/Command/Inputs.ts.erb +5 -0
- data/templates/Command/Result.ts.erb +7 -0
- data/templates/Command/errors/index.ts.erb +3 -0
- data/templates/Command.ts.erb +11 -0
- data/templates/Domain/config.ts.erb +16 -0
- data/templates/Domain.ts.erb +17 -0
- data/templates/Entity/Aggregate.ts.erb +18 -0
- data/templates/Entity/Ambiguous.ts.erb +30 -0
- data/templates/Entity/Atom.ts.erb +18 -0
- data/templates/Entity/Loaded.ts.erb +14 -0
- data/templates/Entity/Unloaded.ts.erb +18 -0
- data/templates/EntityVariants.ts.erb +40 -0
- data/templates/Error.ts.erb +8 -0
- data/templates/Model/Aggregate.ts.erb +12 -0
- data/templates/Model/Atom.ts.erb +12 -0
- data/templates/Model/Model.ts.erb +18 -0
- data/templates/ModelVariants.ts.erb +26 -0
- data/templates/Organization/config.ts.erb +16 -0
- data/templates/Organization.ts.erb +8 -0
- data/templates/base/DataPath.ts +49 -0
- data/templates/base/Entity.ts +87 -0
- data/templates/base/Error.ts +29 -0
- data/templates/base/Model.ts +24 -0
- data/templates/base/Outcome.ts +42 -0
- data/templates/base/RemoteCommand.ts +87 -0
- metadata +142 -0
@@ -0,0 +1,84 @@
|
|
1
|
+
require_relative "typescript_from_manifest_base_generator"
|
2
|
+
|
3
|
+
module Foobara
|
4
|
+
module RemoteGenerator
|
5
|
+
class Services
|
6
|
+
class ModelGenerator < TypescriptFromManifestBaseGenerator
|
7
|
+
class << self
|
8
|
+
def new(relevant_manifest)
|
9
|
+
return super unless self == ModelGenerator
|
10
|
+
|
11
|
+
if relevant_manifest.entity?
|
12
|
+
EntityGenerator.new(relevant_manifest)
|
13
|
+
else
|
14
|
+
super
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
alias model_manifest relevant_manifest
|
20
|
+
|
21
|
+
def target_path
|
22
|
+
[*domain.scoped_full_path, "types", model_name, "#{model_name}.ts"]
|
23
|
+
end
|
24
|
+
|
25
|
+
def template_path
|
26
|
+
["Model", "Model.ts.erb"]
|
27
|
+
end
|
28
|
+
|
29
|
+
def scoped_full_path(points = nil)
|
30
|
+
full_path = model_manifest.scoped_full_path
|
31
|
+
|
32
|
+
if points
|
33
|
+
start_at = full_path.size - points - 1
|
34
|
+
full_path[start_at..]
|
35
|
+
else
|
36
|
+
full_path
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def model_name(points = nil)
|
41
|
+
if points
|
42
|
+
scoped_full_path(points).join(".")
|
43
|
+
else
|
44
|
+
scoped_path.join(".")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Do models have associations??
|
49
|
+
def model_generators
|
50
|
+
types_depended_on.select(&:model?).map do |model|
|
51
|
+
Services::ModelGenerator.new(model)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def dependencies
|
56
|
+
model_generators
|
57
|
+
end
|
58
|
+
|
59
|
+
def model_name_downcase
|
60
|
+
model_name[0].downcase + model_name[1..]
|
61
|
+
end
|
62
|
+
|
63
|
+
def attributes_type_ts_type
|
64
|
+
association_depth = AssociationDepth::AMBIGUOUS
|
65
|
+
foobara_type_to_ts_type(attributes_type, association_depth:, dependency_group:)
|
66
|
+
end
|
67
|
+
|
68
|
+
def atom_attributes_ts_type
|
69
|
+
association_depth = AssociationDepth::ATOM
|
70
|
+
foobara_type_to_ts_type(attributes_type, association_depth:, dependency_group:)
|
71
|
+
end
|
72
|
+
|
73
|
+
def aggregate_attributes_ts_type
|
74
|
+
association_depth = AssociationDepth::AGGREGATE
|
75
|
+
foobara_type_to_ts_type(attributes_type, association_depth:, dependency_group:)
|
76
|
+
end
|
77
|
+
|
78
|
+
def attribute_names
|
79
|
+
attributes_type.attribute_names
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Foobara
|
2
|
+
module RemoteGenerator
|
3
|
+
class Services
|
4
|
+
class ModelVariantsGenerator < ModelGenerator
|
5
|
+
def target_path
|
6
|
+
[*domain.scoped_full_path, "types", "#{model_name}.ts"]
|
7
|
+
end
|
8
|
+
|
9
|
+
def template_path
|
10
|
+
"ModelVariants.ts.erb"
|
11
|
+
end
|
12
|
+
|
13
|
+
def model_generator
|
14
|
+
ModelGenerator.new(model_manifest)
|
15
|
+
end
|
16
|
+
|
17
|
+
def atom_model_generator
|
18
|
+
AtomModelGenerator.new(model_manifest)
|
19
|
+
end
|
20
|
+
|
21
|
+
def aggregate_model_generator
|
22
|
+
AggregateModelGenerator.new(model_manifest)
|
23
|
+
end
|
24
|
+
|
25
|
+
def dependencies
|
26
|
+
if has_associations?
|
27
|
+
[model_generator, atom_model_generator, aggregate_model_generator]
|
28
|
+
else
|
29
|
+
[model_generator]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative "organization_generator"
|
2
|
+
|
3
|
+
module Foobara
|
4
|
+
module RemoteGenerator
|
5
|
+
class Services
|
6
|
+
class OrganizationConfigGenerator < OrganizationGenerator
|
7
|
+
def target_path
|
8
|
+
[*super[0..-2], "config.ts"]
|
9
|
+
end
|
10
|
+
|
11
|
+
def template_path
|
12
|
+
"Organization/config.ts.erb"
|
13
|
+
end
|
14
|
+
|
15
|
+
def dependencies
|
16
|
+
[]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative "typescript_from_manifest_base_generator"
|
2
|
+
|
3
|
+
module Foobara
|
4
|
+
module RemoteGenerator
|
5
|
+
class Services
|
6
|
+
class OrganizationGenerator < TypescriptFromManifestBaseGenerator
|
7
|
+
alias organization_manifest relevant_manifest
|
8
|
+
|
9
|
+
def import_destructure
|
10
|
+
"* as #{organization_name}"
|
11
|
+
end
|
12
|
+
|
13
|
+
def target_path
|
14
|
+
if global?
|
15
|
+
["GlobalOrganization", "index.ts"]
|
16
|
+
else
|
17
|
+
[*scoped_full_path, "index.ts"]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def template_path
|
22
|
+
"Organization.ts.erb"
|
23
|
+
end
|
24
|
+
|
25
|
+
def domain_generators
|
26
|
+
@domain_generators ||= organization_manifest.domains.map do |domain_manifest|
|
27
|
+
DomainGenerator.new(domain_manifest)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def dependencies
|
32
|
+
domain_generators
|
33
|
+
end
|
34
|
+
|
35
|
+
def organization_name
|
36
|
+
scoped_short_name || "GlobalOrganization"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative "manifest_generator"
|
2
|
+
|
3
|
+
module Foobara
|
4
|
+
module RemoteGenerator
|
5
|
+
class Services
|
6
|
+
class OrganizationManifestGenerator < ManifestGenerator
|
7
|
+
def target_path
|
8
|
+
if global?
|
9
|
+
["GlobalOrganization", "manifest.json"]
|
10
|
+
else
|
11
|
+
[*scoped_full_path, "manifest.json"]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative "typescript_from_manifest_base_generator"
|
2
|
+
|
3
|
+
module Foobara
|
4
|
+
module RemoteGenerator
|
5
|
+
class Services
|
6
|
+
class ProcessorClassGenerator < TypescriptFromManifestBaseGenerator
|
7
|
+
alias processor_class_manifest relevant_manifest
|
8
|
+
|
9
|
+
def target_path
|
10
|
+
*path, basename = scoped_full_path
|
11
|
+
basename = "#{basename}.ts"
|
12
|
+
|
13
|
+
["base", "processors", *path, basename]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,293 @@
|
|
1
|
+
# Where to put files?
|
2
|
+
# let's examine an error...
|
3
|
+
# if an error belongs to a command, let's put it in <command path>/errors/<error_name>.ts
|
4
|
+
# if an error belongs to a domain, let's put it in <domain path>/errors/<error_name>.ts
|
5
|
+
# if an error belongs to an organization, let's put it in <organization path>/errors/<error_name>.ts
|
6
|
+
# if an error belongs to a base processor, let's put it in base/processors/<processor path>/<error_name>.ts
|
7
|
+
# if an error belongs to nothing, let's put it in errors/<error_name>.ts
|
8
|
+
#
|
9
|
+
# so what is the official logic?
|
10
|
+
# if parent is a domain or org or nil,
|
11
|
+
# then we need to insert "errors" before the last element in the scoped_path.
|
12
|
+
# This is to help make the commands more first-class.
|
13
|
+
# otherwise, the thing will already be out of site. We could prepend the path with "base" and <parent_category>.
|
14
|
+
#
|
15
|
+
# Might just be safer though to leverage the parent's target_dir.
|
16
|
+
#
|
17
|
+
# So that logic would be...
|
18
|
+
# if parent is domain, nil, or org:
|
19
|
+
# <parent_target_dir>/errors/<error_name>.ts
|
20
|
+
# else
|
21
|
+
# <parent_target_dir>/<error_name>.ts
|
22
|
+
|
23
|
+
module Foobara
|
24
|
+
module RemoteGenerator
|
25
|
+
class Services
|
26
|
+
class TypescriptFromManifestBaseGenerator < Foobara::FilesGenerator
|
27
|
+
class << self
|
28
|
+
def manifest_to_generator_classes(manifest)
|
29
|
+
case manifest
|
30
|
+
when Manifest::Command
|
31
|
+
[
|
32
|
+
Services::CommandGenerator,
|
33
|
+
Services::CommandInputsGenerator,
|
34
|
+
Services::CommandResultGenerator,
|
35
|
+
Services::CommandErrorsGenerator,
|
36
|
+
Services::CommandErrorsIndexGenerator,
|
37
|
+
Services::CommandManifestGenerator
|
38
|
+
]
|
39
|
+
when Manifest::Domain
|
40
|
+
[
|
41
|
+
Services::DomainGenerator,
|
42
|
+
Services::DomainConfigGenerator,
|
43
|
+
Services::DomainManifestGenerator
|
44
|
+
]
|
45
|
+
when Manifest::Organization
|
46
|
+
[
|
47
|
+
Services::OrganizationGenerator,
|
48
|
+
Services::OrganizationConfigGenerator,
|
49
|
+
Services::OrganizationManifestGenerator
|
50
|
+
]
|
51
|
+
when Manifest::Entity
|
52
|
+
[
|
53
|
+
Services::EntityGenerator,
|
54
|
+
Services::EntityVariantsGenerator,
|
55
|
+
Services::EntityManifestGenerator
|
56
|
+
]
|
57
|
+
when Manifest::Model
|
58
|
+
[
|
59
|
+
Services::ModelGenerator,
|
60
|
+
Services::ModelVariantsGenerator,
|
61
|
+
Services::ModelManifestGenerator
|
62
|
+
]
|
63
|
+
when Manifest::Error
|
64
|
+
Services::ErrorGenerator
|
65
|
+
when Manifest::ProcessorClass
|
66
|
+
Services::ProcessorClassGenerator
|
67
|
+
when Manifest::RootManifest
|
68
|
+
Services::RootManifestGenerator
|
69
|
+
else
|
70
|
+
# :nocov:
|
71
|
+
raise "Not sure how build a generator for a #{manifest}"
|
72
|
+
# :nocov:
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def initialize(relevant_manifest)
|
78
|
+
unless relevant_manifest.is_a?(Manifest::BaseManifest)
|
79
|
+
# :nocov:
|
80
|
+
raise ArgumentError, "Expected a Foobara::Manifest, got #{relevant_manifest.class}"
|
81
|
+
# :nocov:
|
82
|
+
end
|
83
|
+
|
84
|
+
super
|
85
|
+
end
|
86
|
+
|
87
|
+
def templates_dir
|
88
|
+
"#{__dir__}/../../../templates"
|
89
|
+
end
|
90
|
+
|
91
|
+
def parent
|
92
|
+
if relevant_manifest.parent
|
93
|
+
generator_for(relevant_manifest.parent)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def dependency_group
|
98
|
+
@dependency_group ||= begin
|
99
|
+
generators = dependencies.map do |dependency|
|
100
|
+
generator_for(dependency)
|
101
|
+
end
|
102
|
+
|
103
|
+
DependencyGroup.new(generators, name: scoped_full_path.join("."))
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def dependency_roots
|
108
|
+
unless dependency_group
|
109
|
+
# :nocov:
|
110
|
+
raise "This generator was created without a " \
|
111
|
+
"dependency_group and therefore cannot call #{__method__}"
|
112
|
+
# :nocov:
|
113
|
+
end
|
114
|
+
|
115
|
+
dependency_group.non_colliding_dependency_roots.sort_by(&:scoped_full_name)
|
116
|
+
end
|
117
|
+
|
118
|
+
def ts_instance_name
|
119
|
+
ts_instance_path.join(".")
|
120
|
+
end
|
121
|
+
|
122
|
+
def ts_instance_path
|
123
|
+
scoped_path
|
124
|
+
end
|
125
|
+
|
126
|
+
def ts_instance_full_name
|
127
|
+
ts_instance_full_path.join(".")
|
128
|
+
end
|
129
|
+
|
130
|
+
def ts_instance_full_path
|
131
|
+
scoped_full_path
|
132
|
+
end
|
133
|
+
|
134
|
+
def ts_type_full_path
|
135
|
+
ts_instance_full_path
|
136
|
+
end
|
137
|
+
|
138
|
+
foobara_delegate :organization_name,
|
139
|
+
:domain_name,
|
140
|
+
to: :relevant_manifest
|
141
|
+
|
142
|
+
def import_path
|
143
|
+
if import_path_array.size == 1
|
144
|
+
"./#{import_path_array.first}"
|
145
|
+
else
|
146
|
+
import_path_array.join("/")
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def import_destructure
|
151
|
+
"{ #{scoped_name} }"
|
152
|
+
end
|
153
|
+
|
154
|
+
def import_path_array
|
155
|
+
path = if target_path.last == "index.ts"
|
156
|
+
target_path[0..-2]
|
157
|
+
else
|
158
|
+
target_path
|
159
|
+
end
|
160
|
+
|
161
|
+
path[-1] = path.last.gsub(/\.ts$/, "")
|
162
|
+
|
163
|
+
path
|
164
|
+
end
|
165
|
+
|
166
|
+
def value_to_ts_value(value)
|
167
|
+
case value
|
168
|
+
when ::String, Numeric
|
169
|
+
value.inspect
|
170
|
+
when ::Symbol
|
171
|
+
value.to_s.inspect
|
172
|
+
else
|
173
|
+
# :nocov:
|
174
|
+
raise "Not sure how to represent #{value} in typescript. Maybe implement it."
|
175
|
+
# :nocov:
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
# TODO: relocate this to a more reusable place
|
180
|
+
def foobara_type_to_ts_type(
|
181
|
+
type_declaration,
|
182
|
+
dependency_group: self.dependency_group,
|
183
|
+
name: nil,
|
184
|
+
association_depth: AssociationDepth::AMBIGUOUS,
|
185
|
+
initial: true
|
186
|
+
)
|
187
|
+
if type_declaration.is_a?(Manifest::Error)
|
188
|
+
error_generator = generator_for(type_declaration)
|
189
|
+
return dependency_group.non_colliding_type(error_generator)
|
190
|
+
end
|
191
|
+
|
192
|
+
type_string = if type_declaration.is_a?(Manifest::Attributes)
|
193
|
+
ts_type = attributes_to_ts_type(type_declaration, association_depth:, dependency_group:)
|
194
|
+
|
195
|
+
if name
|
196
|
+
return "interface #{name} #{ts_type}"
|
197
|
+
else
|
198
|
+
ts_type
|
199
|
+
end
|
200
|
+
elsif type_declaration.is_a?(Manifest::Array)
|
201
|
+
# TODO: which association_depth do we pass here?
|
202
|
+
ts_type = foobara_type_to_ts_type(
|
203
|
+
type_declaration.element_type,
|
204
|
+
association_depth:,
|
205
|
+
dependency_group:,
|
206
|
+
initial: false
|
207
|
+
)
|
208
|
+
"#{ts_type}[]"
|
209
|
+
else
|
210
|
+
type_symbol = type_declaration.type
|
211
|
+
|
212
|
+
case type_symbol
|
213
|
+
when "string", "boolean"
|
214
|
+
type_symbol
|
215
|
+
when "number", "integer", "float"
|
216
|
+
"number"
|
217
|
+
# TODO: should apply relevant processors to make email a real email type instead of "string"
|
218
|
+
when "symbol", "email"
|
219
|
+
"string"
|
220
|
+
when "duck"
|
221
|
+
"any"
|
222
|
+
when "datetime"
|
223
|
+
"Date"
|
224
|
+
else
|
225
|
+
if type_declaration.model?
|
226
|
+
model_to_ts_model_name(type_declaration, association_depth:, initial:)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
if type_string
|
232
|
+
if type_declaration.one_of
|
233
|
+
type_string = type_declaration.one_of.map(&:inspect).join(" | ")
|
234
|
+
end
|
235
|
+
|
236
|
+
if type_declaration.allows_nil?
|
237
|
+
type_string = "#{type_string} | null"
|
238
|
+
end
|
239
|
+
|
240
|
+
name ? "#{name} = #{type_string}" : type_string
|
241
|
+
else
|
242
|
+
# :nocov:
|
243
|
+
raise "Not sure how to convert #{type_declaration} to a TS type"
|
244
|
+
# :nocov:
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
def attributes_to_ts_type(attributes, dependency_group:, association_depth: AssociationDepth::AMBIGUOUS)
|
249
|
+
guts = attributes.attribute_declarations.map do |attribute_name, attribute_declaration|
|
250
|
+
" #{attribute_name}#{"?" unless attributes.required?(attribute_name)}: #{
|
251
|
+
foobara_type_to_ts_type(attribute_declaration, dependency_group:, association_depth:, initial: false)
|
252
|
+
}"
|
253
|
+
end.join("\n")
|
254
|
+
|
255
|
+
"{\n#{guts}\n}"
|
256
|
+
end
|
257
|
+
|
258
|
+
def model_to_ts_model_name(model, association_depth: AssociationDepth::AMBIGUOUS, initial: true)
|
259
|
+
model = model.to_type if model.is_a?(Manifest::TypeDeclaration)
|
260
|
+
|
261
|
+
generator_class = case association_depth
|
262
|
+
when AssociationDepth::AMBIGUOUS
|
263
|
+
Services::ModelGenerator
|
264
|
+
when AssociationDepth::ATOM
|
265
|
+
if !initial && model.entity?
|
266
|
+
Services::UnloadedEntityGenerator
|
267
|
+
else
|
268
|
+
Services::AtomModelGenerator
|
269
|
+
end
|
270
|
+
when AssociationDepth::AGGREGATE
|
271
|
+
Services::AggregateModelGenerator
|
272
|
+
else
|
273
|
+
# :nocov:
|
274
|
+
raise "Bad association_depth: #{association_depth}"
|
275
|
+
# :nocov:
|
276
|
+
end
|
277
|
+
|
278
|
+
generator = generator_class.new(model)
|
279
|
+
|
280
|
+
dependency_group.non_colliding_type(generator)
|
281
|
+
end
|
282
|
+
|
283
|
+
def ==(other)
|
284
|
+
self.class == other.class && path == other.path && root_manifest == other.root_manifest
|
285
|
+
end
|
286
|
+
|
287
|
+
def hash
|
288
|
+
path.hash
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Foobara
|
2
|
+
module RemoteGenerator
|
3
|
+
class Services
|
4
|
+
class UnloadedEntityGenerator < EntityGenerator
|
5
|
+
def target_path
|
6
|
+
[*domain.scoped_full_path, "types", entity_name, "Unloaded.ts"]
|
7
|
+
end
|
8
|
+
|
9
|
+
def template_path
|
10
|
+
["Entity", "Unloaded.ts.erb"]
|
11
|
+
end
|
12
|
+
|
13
|
+
def ts_instance_path
|
14
|
+
*prefix, name = super
|
15
|
+
[*prefix, "Unloaded#{name}"]
|
16
|
+
end
|
17
|
+
|
18
|
+
def ts_instance_full_path
|
19
|
+
*prefix, name = super
|
20
|
+
[*prefix, "Unloaded#{name}"]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require_relative "generate_typescript"
|
2
|
+
|
3
|
+
module Foobara
|
4
|
+
module RemoteGenerator
|
5
|
+
class WriteTypescriptToDisk < Generators::WriteGeneratedFilesToDisk
|
6
|
+
class << self
|
7
|
+
def generator_key
|
8
|
+
"typescript-remote-commands"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# TODO: shouldn't have to qualify DataError like this
|
13
|
+
class MissingManifestError < Value::DataError
|
14
|
+
class << self
|
15
|
+
def context_type_declaration
|
16
|
+
{}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
possible_error MissingManifestError
|
22
|
+
|
23
|
+
inputs do
|
24
|
+
raw_manifest :associative_array, :allow_nil
|
25
|
+
manifest_url :string, :allow_nil
|
26
|
+
# TODO: should be able to delete this and inherit it
|
27
|
+
output_directory :string, default: "src/domains"
|
28
|
+
end
|
29
|
+
|
30
|
+
depends_on GenerateTypescript
|
31
|
+
|
32
|
+
def execute
|
33
|
+
generate_typescript
|
34
|
+
generate_generated_files_json
|
35
|
+
delete_old_files_if_needed
|
36
|
+
write_all_files_to_disk
|
37
|
+
run_post_generation_tasks
|
38
|
+
|
39
|
+
stats
|
40
|
+
end
|
41
|
+
|
42
|
+
def validate
|
43
|
+
if raw_manifest.nil? && manifest_url.nil?
|
44
|
+
add_input_error(
|
45
|
+
MissingManifestError.new(
|
46
|
+
message: "Must provide either raw_manifest or manifest_url",
|
47
|
+
context: {}
|
48
|
+
)
|
49
|
+
)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def generate_typescript
|
54
|
+
# TODO: we need a way to allow values to be nil in type declarations
|
55
|
+
inputs = raw_manifest ? { raw_manifest: } : { manifest_url: }
|
56
|
+
|
57
|
+
self.paths_to_source_code = run_subcommand!(GenerateTypescript, inputs)
|
58
|
+
end
|
59
|
+
|
60
|
+
def run_post_generation_tasks
|
61
|
+
eslint_fix
|
62
|
+
end
|
63
|
+
|
64
|
+
def eslint_fix
|
65
|
+
cmd = "npx eslint 'src/**/*.{js,jsx,ts,tsx}' --fix"
|
66
|
+
|
67
|
+
Open3.popen3(cmd) do |_stdin, _stdout, stderr, wait_thr|
|
68
|
+
exit_status = wait_thr.value
|
69
|
+
unless exit_status.success?
|
70
|
+
# :nocov:
|
71
|
+
warn "WARNING: could not #{cmd}\n#{stderr.read}"
|
72
|
+
# :nocov:
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<% dependency_roots.each do |dependency_root| %>
|
2
|
+
import <%= dependency_root.import_destructure %> from "<%= path_to_root %><%= dependency_root.import_path %>"
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
export interface PossibleErrors {
|
6
|
+
<% possible_errors.keys.sort.each do |key| %>
|
7
|
+
"<%= key %>": <%= foobara_type_to_ts_type(possible_errors[key].error, dependency_group:) %>,
|
8
|
+
<% end %>
|
9
|
+
}
|
10
|
+
|
11
|
+
export type Error = <%= error_type_union %>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<% dependency_roots.each do |dependency_root| %>
|
2
|
+
import { <%= dependency_root.ts_instance_name %> } from "<%= path_to_root %><%= dependency_root.import_path %>"
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
type Result = <%= foobara_type_to_ts_type(result_type, dependency_group:, association_depth:) %>
|
6
|
+
|
7
|
+
export default Result
|