foobara-typescript-remote-command-generator 1.2.0 → 1.2.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9f783af32070cfcdc33c70d34c1b755a66a0a6bb3df7b7e8697345bdc1d148f7
4
- data.tar.gz: fdcfa71700d34b3c42163b586fc2f8cb1c90f420bef3fb76f7a8a5a8d29e6423
3
+ metadata.gz: 267ff33f2580961f0aae6027f8b986587950b26e5866297af2d2a461e3b8e954
4
+ data.tar.gz: e61dedc94508e92667d75d3b9bb35d2eab25b9d4a9485ad2a40e571417744039
5
5
  SHA512:
6
- metadata.gz: b5b5d35cc80f88622f2a4ea321574a7af55e9c61ec7bde32d42761a9d9511af07ced97894f4905962bb1803c1871d9a8ab4c9c83722df5caefffe7342b90e474
7
- data.tar.gz: 6d0a1fcb787dc719a330bd58953d42e387f931b35a2eb3d6168ab0d0dfbdec166a1f2215339ea7046b3edfc00473365cdca75e6846408014ed96a3f04d6ef3d8
6
+ metadata.gz: 4de3ce62b189e7696e63a10940325ec2a6bf1fed29a13b1c0b3087fb9ac30e8be82c16cf5102bf31d2ae945b5abdec888dbf0a4093d582d5ca2d2634a955054b
7
+ data.tar.gz: 2ff54bbac0ad37b6b29814f07226260ab732e02c73f25df1e9ed7b2950439ceeaf3aaff70d93ebc599672256eefdc057dbc710168715e1ca370132d645047529
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## [1.2.2] - 2026-01-24
2
+
3
+ - Add support for an app model named Model, which collide's with Foobara's Model
4
+ - Fixes a bug when the superclass we import collides with dependencies
5
+ - Fixes a bug where a dependency collides with something we're generating
6
+
7
+ ## [1.2.1] - 2025-12-19
8
+
9
+ - Handle some .foobara_delegate and #path deprecation warnings
10
+
1
11
  ## [1.2.0] - 2025-11-06
2
12
 
3
13
  - If an attribute isn't required but has a default, it will have a non-required create
@@ -30,22 +30,28 @@ module Foobara
30
30
  end
31
31
  end
32
32
 
33
+ def dependencies
34
+ [*super, superclass_generator]
35
+ end
36
+
37
+ def collision_winners
38
+ superclass_generator
39
+ end
40
+
41
+ def superclass_generator
42
+ @superclass_generator ||= LoadedEntityGenerator.new(relevant_manifest)
43
+ end
44
+
33
45
  def attributes_type_ts_type
34
46
  aggregate_attributes_ts_type
35
47
  end
36
48
 
37
49
  def ts_instance_path
38
- *prefix, name = scoped_path
39
- [*prefix, "#{name}Aggregate"]
40
- end
41
-
42
- def ts_instance_full_path
43
- *prefix, name = scoped_full_path
44
- [*prefix, "#{name}Aggregate"]
50
+ [*model_prefix, generated_type]
45
51
  end
46
52
 
47
- def import_destructure
48
- "{ #{scoped_short_name}Aggregate }"
53
+ def generated_type
54
+ "#{scoped_short_name}Aggregate"
49
55
  end
50
56
  end
51
57
  end
@@ -38,9 +38,12 @@ module Foobara
38
38
  aggregate_attributes_ts_type
39
39
  end
40
40
 
41
- def ts_instance_full_path
42
- *prefix, name = scoped_full_path
43
- [*prefix, "#{name}Aggregate"]
41
+ def ts_instance_path
42
+ [*model_prefix, generated_type]
43
+ end
44
+
45
+ def generated_type
46
+ "#{scoped_short_name}Aggregate"
44
47
  end
45
48
  end
46
49
  end
@@ -33,17 +33,11 @@ module Foobara
33
33
  end
34
34
 
35
35
  def ts_instance_path
36
- *prefix, name = scoped_path
37
- [*prefix, "#{name}Atom"]
36
+ [*model_prefix, generated_type]
38
37
  end
39
38
 
40
- def ts_instance_full_path
41
- *prefix, name = scoped_full_path
42
- [*prefix, "#{name}Atom"]
43
- end
44
-
45
- def import_destructure
46
- "{ #{scoped_short_name}Atom }"
39
+ def generated_type
40
+ "#{scoped_short_name}Atom"
47
41
  end
48
42
  end
49
43
  end
@@ -34,9 +34,12 @@ module Foobara
34
34
  end
35
35
  end
36
36
 
37
- def ts_instance_full_path
38
- *prefix, name = scoped_full_path
39
- [*prefix, "#{name}Atom"]
37
+ def ts_instance_path
38
+ [*model_prefix, generated_type]
39
+ end
40
+
41
+ def generated_type
42
+ "#{scoped_short_name}Atom"
40
43
  end
41
44
  end
42
45
  end
@@ -18,11 +18,13 @@ module Foobara
18
18
  @domain_generator ||= Services::DomainGenerator.new(domain)
19
19
  end
20
20
 
21
- foobara_delegate :organization_generator, :domain_name, :organization_name, to: :domain_generator
21
+ def organization_generator = domain_generator.organization_generator
22
+ def domain_name = domain_generator.domain_name
23
+ def organization_name = domain_generator.organization_name
22
24
 
23
25
  def errors_in_this_namespace
24
26
  @errors_in_this_namespace ||= possible_errors.values.map(&:error).uniq.sort_by(&:error_name).select do |error|
25
- error.parent&.path&.map(&:to_s) == path.map(&:to_s)
27
+ error.parent&.manifest_path&.map(&:to_s) == manifest_path.map(&:to_s)
26
28
  end.map do |error_manifest|
27
29
  Services::ErrorGenerator.new(error_manifest)
28
30
  end
@@ -10,11 +10,14 @@ module Foobara
10
10
  end
11
11
  end
12
12
 
13
- attr_accessor :dependencies, :name
13
+ attr_accessor :dependencies, :name, :will_define, :deps_are_for, :winners
14
14
 
15
- def initialize(dependencies, name:)
15
+ def initialize(dependencies, name:, deps_are_for:, will_define:, winners: nil)
16
+ self.deps_are_for = deps_are_for
17
+ self.will_define = will_define
16
18
  self.name = name
17
19
  self.dependencies = dependencies.to_set
20
+ self.winners = [*winners] if winners
18
21
 
19
22
  find_collisions
20
23
  end
@@ -57,18 +60,17 @@ module Foobara
57
60
  def non_colliding_root(dep)
58
61
  root = dep
59
62
  points = points_for(dep)
60
- points_climbed = 0
63
+ points_climbed = dep.ts_instance_path.size
61
64
 
62
65
  until points_climbed >= points
63
- # TODO: can't use scoped_path because sometimes we want UnloadedUser instead of User. How to fix??
64
- points_climbed += dep.scoped_path.size
66
+ points_climbed += dep.ts_instance_path.size
65
67
  root = root.parent
66
68
  end
67
69
 
68
70
  root
69
71
  end
70
72
 
71
- def points_for(dep)
73
+ def raw_points_for(dep)
72
74
  points = collision_data_for(dep).points
73
75
 
74
76
  unless points
@@ -80,6 +82,14 @@ module Foobara
80
82
  points
81
83
  end
82
84
 
85
+ def points_for(dep)
86
+ if winners&.include?(dep)
87
+ 0
88
+ else
89
+ raw_points_for(dep)
90
+ end
91
+ end
92
+
83
93
  def non_colliding_type_name(dep, points = points_for(dep))
84
94
  non_colliding_type_path(dep, points).join(".")
85
95
  end
@@ -89,16 +99,31 @@ module Foobara
89
99
  end
90
100
 
91
101
  def non_colliding_type_path(dep, points = points_for(dep))
92
- start_at = dep.ts_type_full_path.size - points - 1
93
- path = dep.ts_type_full_path[start_at..] || []
102
+ if points == 0
103
+ path = dep.ts_instance_path
104
+ return path.size == 1 ? path : [path.last]
105
+ end
106
+
107
+ path = dep.ts_instance_path
108
+ paths = [path]
109
+ points_climbed = path.size
94
110
 
95
- path.map(&:to_s)
111
+ until points_climbed >= points
112
+ dep = dep.parent
113
+ break unless dep
114
+
115
+ path = dep.ts_instance_path
116
+ paths.unshift(path)
117
+ points_climbed += path.size
118
+ end
119
+
120
+ paths.flatten
96
121
  end
97
122
 
98
123
  private
99
124
 
100
125
  def find_collisions
101
- dependencies.each do |dep|
126
+ [deps_are_for, *dependencies].each do |dep|
102
127
  collision_data = CollisionData.new
103
128
 
104
129
  points = 0
@@ -110,6 +135,10 @@ module Foobara
110
135
  dep != other_dep && name == non_colliding_type_name(other_dep, points)
111
136
  end
112
137
 
138
+ if will_define&.include?(name)
139
+ collisions << deps_are_for
140
+ end
141
+
113
142
  if collisions.empty?
114
143
  collision_data.points = points
115
144
  set_collision_data_for(dep, collision_data)
@@ -70,7 +70,7 @@ module Foobara
70
70
  @organization_generator ||= OrganizationGenerator.new(domain_manifest.organization)
71
71
  end
72
72
 
73
- foobara_delegate :organization_name, to: :organization_generator
73
+ def organization_name = organization_generator.organization_name
74
74
  end
75
75
  end
76
76
  end
@@ -14,6 +14,10 @@ module Foobara
14
14
  ["Entity", "Ambiguous.ts.erb"]
15
15
  end
16
16
 
17
+ def ts_instance_path
18
+ [*model_prefix, scoped_short_name]
19
+ end
20
+
17
21
  def entity_name(...)
18
22
  model_name(...)
19
23
  end
@@ -41,6 +45,14 @@ module Foobara
41
45
  def association_property_paths_ts
42
46
  associations.keys.map { |k| DataPath.parse(k).path.map(&:to_s) }.inspect
43
47
  end
48
+
49
+ def will_define
50
+ [generated_type]
51
+ end
52
+
53
+ def generated_type
54
+ entity_short_name
55
+ end
44
56
  end
45
57
  end
46
58
  end
@@ -41,7 +41,9 @@ module Foobara
41
41
  end
42
42
 
43
43
  def context_type_declaration
44
- @context_type_declaration ||= Manifest::TypeDeclaration.new(root_manifest, [*path, :context_type_declaration])
44
+ @context_type_declaration ||= Manifest::TypeDeclaration.new(
45
+ root_manifest, [*manifest_path, :context_type_declaration]
46
+ )
45
47
  end
46
48
 
47
49
  def context_ts_type
@@ -56,16 +58,6 @@ module Foobara
56
58
  def dependencies
57
59
  @dependencies ||= types_depended_on.select { |type| type.detached_entity? || type.custom? || type.model? }
58
60
  end
59
-
60
- def ts_type_full_path
61
- if parent.is_a?(CommandGenerator)
62
- p = super.dup
63
- p[-2] += "Errors"
64
- p
65
- else
66
- super
67
- end
68
- end
69
61
  end
70
62
  end
71
63
  end
@@ -13,17 +13,11 @@ module Foobara
13
13
  end
14
14
 
15
15
  def ts_instance_path
16
- *prefix, name = super
17
- [*prefix, "Loaded#{name}"]
16
+ [*model_prefix, generated_type]
18
17
  end
19
18
 
20
- def ts_instance_full_path
21
- *prefix, name = super
22
- [*prefix, "Loaded#{name}"]
23
- end
24
-
25
- def import_destructure
26
- "{ Loaded#{scoped_short_name} }"
19
+ def generated_type
20
+ "Loaded#{scoped_short_name}"
27
21
  end
28
22
  end
29
23
  end
@@ -23,6 +23,10 @@ module Foobara
23
23
  [*domain.scoped_full_path, "Types", *model_prefix, model_short_name, "#{model_short_name}.ts"]
24
24
  end
25
25
 
26
+ def ts_instance_path
27
+ [*model_prefix, scoped_short_name]
28
+ end
29
+
26
30
  def model_short_name
27
31
  type_short_name
28
32
  end
@@ -42,6 +46,14 @@ module Foobara
42
46
  def model_name_downcase
43
47
  type_name_downcase
44
48
  end
49
+
50
+ def generated_type
51
+ model_short_name
52
+ end
53
+
54
+ def import_destructure
55
+ "{ #{generated_type} }"
56
+ end
45
57
  end
46
58
  end
47
59
  end
@@ -120,10 +120,18 @@ module Foobara
120
120
  generator_for(dependency)
121
121
  end
122
122
 
123
- DependencyGroup.new(generators, name: scoped_full_path.join("."))
123
+ DependencyGroup.new(generators,
124
+ deps_are_for: self,
125
+ name: scoped_full_path.join("."),
126
+ will_define:,
127
+ winners: collision_winners)
124
128
  end
125
129
  end
126
130
 
131
+ def will_define
132
+ nil
133
+ end
134
+
127
135
  def dependency_roots
128
136
  return @dependency_roots if defined?(@dependency_roots)
129
137
 
@@ -137,6 +145,8 @@ module Foobara
137
145
  @dependency_roots = dependency_group.non_colliding_dependency_roots.sort_by(&:scoped_full_name)
138
146
  end
139
147
 
148
+ def collision_winners = nil
149
+
140
150
  def ts_instance_path
141
151
  scoped_path
142
152
  end
@@ -146,16 +156,11 @@ module Foobara
146
156
  end
147
157
 
148
158
  def ts_instance_full_path
149
- scoped_full_path
150
- end
151
-
152
- def ts_type_full_path
153
- ts_instance_full_path
159
+ [*parent&.scoped_full_path, *ts_instance_path]
154
160
  end
155
161
 
156
- foobara_delegate :organization_name,
157
- :domain_name,
158
- to: :relevant_manifest
162
+ def organization_name = relevant_manifest.organization_name
163
+ def domain_name = relevant_manifest.domain_name
159
164
 
160
165
  def import_path
161
166
  if import_path_array.size == 1
@@ -394,12 +399,15 @@ module Foobara
394
399
  dependency_group.non_colliding_type(generator)
395
400
  end
396
401
 
402
+ # Files generator checks that the relevant_manifest is the same but this is faster
397
403
  def ==(other)
398
- self.class == other.class && path == other.path && root_manifest == other.root_manifest
404
+ self.class == other.class &&
405
+ manifest_path == other.manifest_path &&
406
+ root_manifest == other.root_manifest
399
407
  end
400
408
 
401
409
  def hash
402
- path.hash
410
+ manifest_path.hash
403
411
  end
404
412
 
405
413
  def path_to_root
@@ -10,13 +10,12 @@ module Foobara
10
10
  ["Entity", "Unloaded.ts.erb"]
11
11
  end
12
12
 
13
- def ts_instance_full_path
14
- *prefix, name = super
15
- [*prefix, "Unloaded#{name}"]
13
+ def ts_instance_path
14
+ [*model_prefix, generated_type]
16
15
  end
17
16
 
18
- def import_destructure
19
- "{ Unloaded#{scoped_short_name} }"
17
+ def generated_type
18
+ "Unloaded#{scoped_short_name}"
20
19
  end
21
20
  end
22
21
  end
@@ -3,30 +3,20 @@ require_relative "generate_typescript"
3
3
  module Foobara
4
4
  module RemoteGenerator
5
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
6
+ def self.generator_key = "typescript-remote-commands"
22
7
 
23
8
  inputs do
24
9
  raw_manifest :associative_array, :allow_nil
25
10
  manifest_url :string, :allow_nil
26
11
  # TODO: should be able to delete this and inherit it
12
+ project_directory :string, :allow_nil, "This lets you specify a directory to run the linter or npm run build in"
27
13
  output_directory :string, default: "src/domains"
14
+ fail_if_does_not_pass_linter :boolean, default: false
28
15
  end
29
16
 
17
+ possible_error :missing_manifest
18
+ possible_error :failed_to_lint, context: -> { stdout :string, :required; stderr :string, :required }
19
+
30
20
  depends_on GenerateTypescript
31
21
 
32
22
  def execute
@@ -40,13 +30,16 @@ module Foobara
40
30
  end
41
31
 
42
32
  def validate
33
+ # TODO: kind of strange that we have to use a runtime error here. Maybe if input errors
34
+ # supported the concept of multiple inputs this would be cleaner?
43
35
  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
- )
36
+ # TODO: we should support a sugar like:
37
+ # add_runtime_error(
38
+ # :missing_manifest,
39
+ # "Must provide either raw_manifest or manifest_url",
40
+ # some_context_item: "blah"
41
+ # )
42
+ add_runtime_error(symbol: :missing_manifest, message: "Must provide either raw_manifest or manifest_url")
50
43
  end
51
44
  end
52
45
 
@@ -58,21 +51,33 @@ module Foobara
58
51
  end
59
52
 
60
53
  def run_post_generation_tasks
61
- eslint_fix
54
+ Dir.chdir(project_directory || output_directory) do
55
+ eslint_fix
56
+ end
62
57
  end
63
58
 
64
59
  def eslint_fix
65
60
  cmd = "npx eslint 'src/**/*.{js,jsx,ts,tsx}' --fix"
66
61
 
67
- Open3.popen3(cmd) do |_stdin, _stdout, stderr, wait_thr|
62
+ Open3.popen3(cmd) do |_stdin, stdout, stderr, wait_thr|
68
63
  exit_status = wait_thr.value
64
+
69
65
  unless exit_status.success?
70
66
  # :nocov:
71
- warn "WARNING: could not #{cmd}\n#{stderr.read}"
67
+ out = stdout.read
68
+ err = stderr.read
69
+
70
+ if fail_if_does_not_pass_linter?
71
+ add_runtime_error :failed_to_lint, stdout: out, stderr: err
72
+ else
73
+ warn "WARNING: could not #{cmd}\n#{out}\n#{err}"
74
+ end
72
75
  # :nocov:
73
76
  end
74
77
  end
75
78
  end
79
+
80
+ def fail_if_does_not_pass_linter? = fail_if_does_not_pass_linter
76
81
  end
77
82
  end
78
83
  end
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  <%= entity_short_name %>AttributesType
3
3
  } from "./Ambiguous"
4
- import { Loaded<%= entity_short_name %> } from "./Loaded"
4
+
5
5
  <% dependency_roots.each do |dependency_root| %>
6
6
  import <%= dependency_root.import_destructure %> from "<%= path_to_root %><%= dependency_root.import_path %>"
7
7
  <% end %>
@@ -1,4 +1,4 @@
1
- import { Model } from "<%= path_to_root %>base/Model"
1
+ import { Model as FoobaraModel } from "<%= path_to_root %>base/Model"
2
2
  <% dependency_roots.each do |dependency_root| %>
3
3
  import <%= dependency_root.import_destructure %> from "<%= path_to_root %><%= dependency_root.import_path %>"
4
4
  <% end %>
@@ -7,7 +7,7 @@ export interface <%= model_short_name %>AttributesType <%= attributes_type_ts_ty
7
7
 
8
8
  export class <%= model_short_name %><
9
9
  AttributesType extends <%= model_short_name %>AttributesType = <%= model_short_name %>AttributesType
10
- > extends Model<AttributesType> {
10
+ > extends FoobaraModel<AttributesType> {
11
11
  static readonly modelName: string = "<%= model_short_name %>"
12
12
 
13
13
  <% attribute_names.each do |attribute_name| %>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foobara-typescript-remote-command-generator
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miles Georgi