foobara-typescript-remote-command-generator 1.2.7 → 1.3.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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/lib/foobara/typescript_remote_command_generator.rb +1 -6
  4. data/src/{remote_generator/generate_typescript.rb → generate_typescript.rb} +13 -4
  5. data/src/{remote_generator/services → generators}/aggregate_entity_generator.rb +2 -2
  6. data/src/{remote_generator/services → generators}/aggregate_model_generator.rb +3 -3
  7. data/src/{remote_generator/services → generators}/atom_entity_generator.rb +3 -3
  8. data/src/{remote_generator/services → generators}/atom_model_generator.rb +3 -3
  9. data/src/{remote_generator/services → generators}/auth/access_tokens_generator.rb +1 -1
  10. data/src/generators/auth/login_command_generator.rb +29 -0
  11. data/src/{remote_generator/services → generators}/auth/login_generator.rb +4 -2
  12. data/src/generators/auth/logout_command_generator.rb +29 -0
  13. data/src/{remote_generator/services → generators}/auth/logout_generator.rb +4 -2
  14. data/src/{remote_generator/services → generators}/auth/refresh_login_generator.rb +4 -2
  15. data/src/generators/auth/requires_auth_command_generator.rb +27 -0
  16. data/src/{remote_generator/services → generators}/auth/requires_auth_generator.rb +4 -2
  17. data/src/{remote_generator/services → generators}/command_cast_result_generator.rb +6 -6
  18. data/src/{remote_generator/services → generators}/command_errors_generator.rb +2 -2
  19. data/src/{remote_generator/services → generators}/command_errors_index_generator.rb +1 -1
  20. data/src/generators/command_generator.rb +209 -0
  21. data/src/{remote_generator/services → generators}/command_inputs_generator.rb +1 -1
  22. data/src/{remote_generator/services → generators}/command_manifest_generator.rb +1 -1
  23. data/src/{remote_generator/services → generators}/command_result_generator.rb +1 -1
  24. data/src/{remote_generator/services → generators}/dependency_group.rb +2 -2
  25. data/src/{remote_generator/services → generators}/domain_config_generator.rb +1 -1
  26. data/src/{remote_generator/services → generators}/domain_generator.rb +1 -1
  27. data/src/{remote_generator/services → generators}/domain_manifest_generator.rb +1 -1
  28. data/src/{remote_generator/services → generators}/entity_generator.rb +1 -1
  29. data/src/{remote_generator/services → generators}/entity_manifest_generator.rb +1 -1
  30. data/src/{remote_generator/services → generators}/entity_variants_generator.rb +1 -1
  31. data/src/{remote_generator/services → generators}/error_generator.rb +1 -1
  32. data/src/{remote_generator/services → generators}/loaded_entity_generator.rb +1 -1
  33. data/src/{remote_generator/services → generators}/manifest_generator.rb +1 -1
  34. data/src/{remote_generator/services → generators}/model_generator.rb +1 -1
  35. data/src/{remote_generator/services → generators}/model_manifest_generator.rb +1 -1
  36. data/src/{remote_generator/services → generators}/model_variants_generator.rb +1 -1
  37. data/src/{remote_generator/services → generators}/organization_config_generator.rb +1 -1
  38. data/src/{remote_generator/services → generators}/organization_generator.rb +1 -1
  39. data/src/{remote_generator/services → generators}/organization_manifest_generator.rb +1 -1
  40. data/src/{remote_generator/services → generators}/processor_class_generator.rb +1 -1
  41. data/src/generators/remote_command_generator.rb +41 -0
  42. data/src/{remote_generator/services → generators}/root_manifest_generator.rb +1 -1
  43. data/src/{remote_generator/services → generators}/type_generator.rb +3 -3
  44. data/src/{remote_generator/services → generators}/typescript_from_manifest_base_generator.rb +42 -38
  45. data/src/{remote_generator/services → generators}/unloaded_entity_generator.rb +1 -1
  46. data/src/remote_generator.rb +21 -0
  47. data/src/{remote_generator/write_typescript_to_disk.rb → write_typescript_to_disk.rb} +10 -1
  48. data/templates/Command.ts.erb +39 -1
  49. data/templates/base/QueryCache.ts +48 -0
  50. data/templates/base/{RemoteCommand.ts → RemoteCommand.ts.erb} +22 -0
  51. metadata +46 -45
  52. data/src/remote_generator/services/auth/login_command_generator.rb +0 -17
  53. data/src/remote_generator/services/auth/logout_command_generator.rb +0 -17
  54. data/src/remote_generator/services/auth/requires_auth_command_generator.rb +0 -15
  55. data/src/remote_generator/services/command_generator.rb +0 -87
  56. /data/src/{remote_generator/association_depth.rb → association_depth.rb} +0 -0
@@ -2,7 +2,7 @@ require_relative "typescript_from_manifest_base_generator"
2
2
 
3
3
  module Foobara
4
4
  module RemoteGenerator
5
- class Services
5
+ module Generators
6
6
  class DomainGenerator < TypescriptFromManifestBaseGenerator
7
7
  alias domain_manifest relevant_manifest
8
8
 
@@ -2,7 +2,7 @@ require_relative "manifest_generator"
2
2
 
3
3
  module Foobara
4
4
  module RemoteGenerator
5
- class Services
5
+ module Generators
6
6
  class DomainManifestGenerator < ManifestGenerator
7
7
  def target_path
8
8
  if global?
@@ -2,7 +2,7 @@ require_relative "model_generator"
2
2
 
3
3
  module Foobara
4
4
  module RemoteGenerator
5
- class Services
5
+ module Generators
6
6
  class EntityGenerator < ModelGenerator
7
7
  alias entity_manifest relevant_manifest
8
8
 
@@ -2,7 +2,7 @@ require_relative "model_manifest_generator"
2
2
 
3
3
  module Foobara
4
4
  module RemoteGenerator
5
- class Services
5
+ module Generators
6
6
  class EntityManifestGenerator < ModelManifestGenerator
7
7
  end
8
8
  end
@@ -2,7 +2,7 @@ require_relative "model_variants_generator"
2
2
 
3
3
  module Foobara
4
4
  module RemoteGenerator
5
- class Services
5
+ module Generators
6
6
  class EntityVariantsGenerator < EntityGenerator
7
7
  def target_path
8
8
  *prefix, _entity_name, _file = super
@@ -2,7 +2,7 @@ require_relative "typescript_from_manifest_base_generator"
2
2
 
3
3
  module Foobara
4
4
  module RemoteGenerator
5
- class Services
5
+ module Generators
6
6
  class ErrorGenerator < TypescriptFromManifestBaseGenerator
7
7
  alias error_manifest relevant_manifest
8
8
 
@@ -2,7 +2,7 @@ require_relative "entity_generator"
2
2
 
3
3
  module Foobara
4
4
  module RemoteGenerator
5
- class Services
5
+ module Generators
6
6
  class LoadedEntityGenerator < EntityGenerator
7
7
  def target_path
8
8
  [*super[..-2], "Loaded.ts"]
@@ -2,7 +2,7 @@ require_relative "typescript_from_manifest_base_generator"
2
2
 
3
3
  module Foobara
4
4
  module RemoteGenerator
5
- class Services
5
+ module Generators
6
6
  class ManifestGenerator < TypescriptFromManifestBaseGenerator
7
7
  def generate(_elements_to_generate)
8
8
  JSON.pretty_generate(relevant_manifest.relevant_manifest)
@@ -3,7 +3,7 @@ require_relative "type_generator"
3
3
 
4
4
  module Foobara
5
5
  module RemoteGenerator
6
- class Services
6
+ module Generators
7
7
  class ModelGenerator < TypeGenerator
8
8
  class << self
9
9
  def new(relevant_manifest)
@@ -1,6 +1,6 @@
1
1
  module Foobara
2
2
  module RemoteGenerator
3
- class Services
3
+ module Generators
4
4
  class ModelManifestGenerator < ManifestGenerator
5
5
  def target_path
6
6
  [*domain.scoped_full_path, "Types", *model_prefix, scoped_short_name, "manifest.json"]
@@ -1,6 +1,6 @@
1
1
  module Foobara
2
2
  module RemoteGenerator
3
- class Services
3
+ module Generators
4
4
  class ModelVariantsGenerator < ModelGenerator
5
5
  def target_path
6
6
  [*domain.scoped_full_path, "Types", *model_prefix, "#{scoped_short_name}.ts"]
@@ -2,7 +2,7 @@ require_relative "organization_generator"
2
2
 
3
3
  module Foobara
4
4
  module RemoteGenerator
5
- class Services
5
+ module Generators
6
6
  class OrganizationConfigGenerator < OrganizationGenerator
7
7
  def target_path
8
8
  [*super[0..-2], "config.ts"]
@@ -2,7 +2,7 @@ require_relative "typescript_from_manifest_base_generator"
2
2
 
3
3
  module Foobara
4
4
  module RemoteGenerator
5
- class Services
5
+ module Generators
6
6
  class OrganizationGenerator < TypescriptFromManifestBaseGenerator
7
7
  alias organization_manifest relevant_manifest
8
8
 
@@ -2,7 +2,7 @@ require_relative "manifest_generator"
2
2
 
3
3
  module Foobara
4
4
  module RemoteGenerator
5
- class Services
5
+ module Generators
6
6
  class OrganizationManifestGenerator < ManifestGenerator
7
7
  def target_path
8
8
  if global?
@@ -2,7 +2,7 @@ require_relative "typescript_from_manifest_base_generator"
2
2
 
3
3
  module Foobara
4
4
  module RemoteGenerator
5
- class Services
5
+ module Generators
6
6
  class ProcessorClassGenerator < TypescriptFromManifestBaseGenerator
7
7
  alias processor_class_manifest relevant_manifest
8
8
 
@@ -0,0 +1,41 @@
1
+ module Foobara
2
+ module RemoteGenerator
3
+ module Generators
4
+ class RemoteCommandGenerator < TypescriptFromManifestBaseGenerator
5
+ def import_destructure
6
+ ts_instance_path.first
7
+ end
8
+
9
+ def ts_instance_path
10
+ ["RemoteCommand"]
11
+ end
12
+
13
+ def ts_instance_full_path
14
+ ["RemoteCommand"]
15
+ end
16
+
17
+ def template_path
18
+ ["base", "RemoteCommand.ts.erb"]
19
+ end
20
+
21
+ def hash
22
+ template_path.hash
23
+ end
24
+
25
+ def domain_reference
26
+ "global_organization::global_domain"
27
+ end
28
+
29
+ # TODO: awkward to have this here hmmm... maybe create a manifest for these static files?
30
+ # something doesn't feel right about this.
31
+ def domain
32
+ Manifest::Domain.new(root_manifest, [:domain, domain_reference])
33
+ end
34
+
35
+ def scoped_full_name
36
+ ts_instance_path.first
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -2,7 +2,7 @@ require_relative "manifest_generator"
2
2
 
3
3
  module Foobara
4
4
  module RemoteGenerator
5
- class Services
5
+ module Generators
6
6
  class RootManifestGenerator < ManifestGenerator
7
7
  def target_path
8
8
  ["manifest.json"]
@@ -2,7 +2,7 @@ require_relative "typescript_from_manifest_base_generator"
2
2
 
3
3
  module Foobara
4
4
  module RemoteGenerator
5
- class Services
5
+ module Generators
6
6
  class TypeGenerator < TypescriptFromManifestBaseGenerator
7
7
  class << self
8
8
  def lru_cache
@@ -100,13 +100,13 @@ module Foobara
100
100
 
101
101
  def model_generators
102
102
  @model_generators ||= types_depended_on.select(&:model?).reject(&:builtin?).map do |model|
103
- Services::ModelGenerator.new(model)
103
+ ModelGenerator.new(model)
104
104
  end
105
105
  end
106
106
 
107
107
  def custom_type_generators
108
108
  @custom_type_generators ||= types_depended_on.reject(&:builtin?).reject(&:model?).map do |type|
109
- Services::TypeGenerator.new(type)
109
+ TypeGenerator.new(type)
110
110
  end
111
111
  end
112
112
 
@@ -22,7 +22,7 @@
22
22
 
23
23
  module Foobara
24
24
  module RemoteGenerator
25
- class Services
25
+ module Generators
26
26
  class TypescriptFromManifestBaseGenerator < Foobara::FilesGenerator
27
27
  class << self
28
28
  def manifest_to_generator_classes(manifest)
@@ -30,62 +30,62 @@ module Foobara
30
30
  when Manifest::Command
31
31
  generator_classes = case manifest.full_command_name
32
32
  when "Foobara::Auth::RefreshLogin"
33
- Services::Auth::RefreshLoginGenerator
33
+ Auth::RefreshLoginGenerator
34
34
  when "Foobara::Auth::Login"
35
- Services::Auth::LoginGenerator
35
+ Auth::LoginGenerator
36
36
  when "Foobara::Auth::Logout"
37
- Services::Auth::LogoutGenerator
37
+ Auth::LogoutGenerator
38
38
  when /\bGetCurrentUser$/
39
- Services::Auth::RequiresAuthGenerator
39
+ Auth::RequiresAuthGenerator
40
40
  else
41
41
  if manifest.requires_authentication?
42
- Services::Auth::RequiresAuthGenerator
42
+ Auth::RequiresAuthGenerator
43
43
  else
44
- Services::CommandGenerator
44
+ CommandGenerator
45
45
  end
46
46
  end
47
47
 
48
48
  [
49
49
  *generator_classes,
50
- Services::CommandInputsGenerator,
51
- Services::CommandResultGenerator,
52
- Services::CommandCastResultGenerator,
53
- Services::CommandErrorsGenerator,
54
- Services::CommandErrorsIndexGenerator,
55
- Services::CommandManifestGenerator
50
+ CommandInputsGenerator,
51
+ CommandResultGenerator,
52
+ CommandCastResultGenerator,
53
+ CommandErrorsGenerator,
54
+ CommandErrorsIndexGenerator,
55
+ CommandManifestGenerator
56
56
  ]
57
57
  when Manifest::Domain
58
58
  [
59
- Services::DomainGenerator,
60
- Services::DomainConfigGenerator,
61
- Services::DomainManifestGenerator
59
+ DomainGenerator,
60
+ DomainConfigGenerator,
61
+ DomainManifestGenerator
62
62
  ]
63
63
  when Manifest::Organization
64
64
  [
65
- Services::OrganizationGenerator,
66
- Services::OrganizationConfigGenerator,
67
- Services::OrganizationManifestGenerator
65
+ OrganizationGenerator,
66
+ OrganizationConfigGenerator,
67
+ OrganizationManifestGenerator
68
68
  ]
69
69
  when Manifest::Entity, Manifest::DetachedEntity
70
70
  [
71
- Services::EntityGenerator,
72
- Services::EntityVariantsGenerator,
73
- Services::EntityManifestGenerator
71
+ EntityGenerator,
72
+ EntityVariantsGenerator,
73
+ EntityManifestGenerator
74
74
  ]
75
75
  when Manifest::Model
76
76
  [
77
- Services::ModelGenerator,
78
- Services::ModelVariantsGenerator,
79
- Services::ModelManifestGenerator
77
+ ModelGenerator,
78
+ ModelVariantsGenerator,
79
+ ModelManifestGenerator
80
80
  ]
81
81
  when Manifest::Error
82
- Services::ErrorGenerator
82
+ ErrorGenerator
83
83
  when Manifest::ProcessorClass
84
- Services::ProcessorClassGenerator
84
+ ProcessorClassGenerator
85
85
  when Manifest::RootManifest
86
- Services::RootManifestGenerator
86
+ RootManifestGenerator
87
87
  when Manifest::Type
88
- Services::TypeGenerator
88
+ TypeGenerator
89
89
  else
90
90
  # :nocov:
91
91
  raise "Not sure how build a generator for a #{manifest}"
@@ -94,18 +94,18 @@ module Foobara
94
94
  end
95
95
  end
96
96
 
97
- def initialize(relevant_manifest)
98
- unless relevant_manifest.is_a?(Manifest::BaseManifest)
97
+ def initialize(relevant_manifest = (none_given = true))
98
+ if none_given || relevant_manifest.is_a?(Manifest::BaseManifest)
99
+ super
100
+ else
99
101
  # :nocov:
100
102
  raise ArgumentError, "Expected a Foobara::Manifest, got #{relevant_manifest.class}"
101
103
  # :nocov:
102
104
  end
103
-
104
- super
105
105
  end
106
106
 
107
107
  def templates_dir
108
- "#{__dir__}/../../../templates"
108
+ "#{__dir__}/../../templates"
109
109
  end
110
110
 
111
111
  def parent
@@ -389,15 +389,15 @@ module Foobara
389
389
 
390
390
  generator_class = case association_depth
391
391
  when AssociationDepth::AMBIGUOUS
392
- Services::ModelGenerator
392
+ ModelGenerator
393
393
  when AssociationDepth::ATOM
394
394
  if !initial && model.detached_entity?
395
- Services::UnloadedEntityGenerator
395
+ UnloadedEntityGenerator
396
396
  else
397
- Services::AtomModelGenerator
397
+ AtomModelGenerator
398
398
  end
399
399
  when AssociationDepth::AGGREGATE
400
- Services::AggregateModelGenerator
400
+ AggregateModelGenerator
401
401
  else
402
402
  # :nocov:
403
403
  raise "Bad association_depth: #{association_depth}"
@@ -431,6 +431,10 @@ module Foobara
431
431
  path = super
432
432
  path.empty? ? "./" : path
433
433
  end
434
+
435
+ def auto_dirty_queries?
436
+ RemoteGenerator.auto_dirty_queries?
437
+ end
434
438
  end
435
439
  end
436
440
  end
@@ -1,6 +1,6 @@
1
1
  module Foobara
2
2
  module RemoteGenerator
3
- class Services
3
+ module Generators
4
4
  class UnloadedEntityGenerator < EntityGenerator
5
5
  def target_path
6
6
  [*super[..-2], "Unloaded.ts"]
@@ -1,5 +1,26 @@
1
1
  module Foobara
2
2
  module RemoteGenerator
3
3
  foobara_domain!
4
+
5
+ class << self
6
+ def auto_dirty_queries(auto_dirty_queries)
7
+ if auto_dirty_queries == @auto_dirty_queries
8
+ yield
9
+ else
10
+ old = @auto_dirty_queries
11
+ begin
12
+ @auto_dirty_queries = auto_dirty_queries
13
+ yield
14
+ ensure
15
+ @auto_dirty_queries = old
16
+ end
17
+ end
18
+ @auto_dirty_queries = auto_dirty_queries
19
+ end
20
+
21
+ def auto_dirty_queries?
22
+ @auto_dirty_queries
23
+ end
24
+ end
4
25
  end
5
26
  end
@@ -2,7 +2,7 @@ require_relative "generate_typescript"
2
2
 
3
3
  module Foobara
4
4
  module RemoteGenerator
5
- class WriteTypescriptToDisk < Generators::WriteGeneratedFilesToDisk
5
+ class WriteTypescriptToDisk < Foobara::Generators::WriteGeneratedFilesToDisk
6
6
  def self.generator_key = "typescript-remote-commands"
7
7
 
8
8
  inputs do
@@ -14,6 +14,7 @@ module Foobara
14
14
  description: "This lets you specify a directory to run the linter or npm run build in"
15
15
  output_directory :string, default: "src/domains"
16
16
  fail_if_does_not_pass_linter :boolean, default: false
17
+ auto_dirty_queries :boolean, default: false
17
18
  end
18
19
 
19
20
  possible_error :missing_manifest
@@ -49,9 +50,17 @@ module Foobara
49
50
  # TODO: we need a way to allow values to be nil in type declarations
50
51
  inputs = raw_manifest ? { raw_manifest: } : { manifest_url: }
51
52
 
53
+ if auto_dirty_queries?
54
+ inputs[:auto_dirty_queries] = auto_dirty_queries
55
+ end
56
+
52
57
  self.paths_to_source_code = run_subcommand!(GenerateTypescript, inputs)
53
58
  end
54
59
 
60
+ def auto_dirty_queries?
61
+ auto_dirty_queries
62
+ end
63
+
55
64
  def run_post_generation_tasks
56
65
  Dir.chdir(project_directory || output_directory) do
57
66
  eslint_fix
@@ -1,4 +1,6 @@
1
- import <%= base_class_name %> from "<%= path_to_root %><%= base_class_path %>"
1
+ <% dependency_roots.each do |dependency_root| %>
2
+ import <%= dependency_root.import_destructure %> from "<%= path_to_root %><%= dependency_root.import_path %>"
3
+ <% end %>
2
4
 
3
5
  import Inputs from "./Inputs"
4
6
  import Result from "./Result"
@@ -7,6 +9,7 @@ import { Error } from "./Errors"
7
9
  import castJsonResult from "./castJsonResult"
8
10
  <% end %>
9
11
 
12
+
10
13
  export class <%= command_name %> extends <%= base_class_name %><Inputs, Result, Error> {
11
14
  static readonly organizationName = "<%= organization_name %>"
12
15
  static readonly domainName = "<%= domain_name %>"
@@ -17,4 +20,39 @@ export class <%= command_name %> extends <%= base_class_name %><Inputs, Result,
17
20
  return castJsonResult(json)
18
21
  }
19
22
  <% end %>
23
+
24
+ <% if queries_that_are_dirtied_by_this_command.any? %>
25
+ dirties (): Array<[any] | [any, string, any]> {
26
+ <% if queries_dirtied_without_inputs.any? %>
27
+ const queries: Array<[any] | [any, string, any]> = [
28
+ <% queries_dirtied_without_inputs.each do |query| %>
29
+ [<%= dependency_group.non_colliding_type(query) %>],
30
+ <% end %>
31
+ ]
32
+ <% end %>
33
+
34
+ <% if queries_dirtied_with_inputs.any? %>
35
+ <% queries_dirtied_with_inputs.each_pair do |query, value_path_and_query_input_path| %>
36
+ <% value_path_and_query_input_path => [value_path, query_input_path] %>
37
+ <% if value_path.first == :result %>
38
+ queries.push([
39
+ <%= dependency_group.non_colliding_type(query) %>,
40
+ <%= query_input_path.to_s.inspect %>,
41
+ this.<%= value_path.join(".") %>
42
+ ])
43
+ <% else %>
44
+ if (this.<%= value_path.join("?.") %> != null) {
45
+ queries.push([
46
+ <%= dependency_group.non_colliding_type(query) %>,
47
+ <%= query_input_path.to_s.inspect %>,
48
+ this.<%= value_path.join(".") %>
49
+ ])
50
+ }
51
+ <% end %>
52
+ <% end %>
53
+ <% end %>
54
+
55
+ return queries
56
+ }
57
+ <% end %>
20
58
  }
@@ -38,6 +38,54 @@ export function forEachQuery (callback: (query: Query<RemoteCommand<any, any, an
38
38
  queryCache.forEach(callback)
39
39
  }
40
40
 
41
+ interface DirtyQueryEvent {
42
+ commandName: string
43
+ propertyName: string | undefined
44
+ value: string | number | undefined
45
+ }
46
+
47
+ let dirtyQueryChannel: BroadcastChannel | null = null
48
+
49
+ if (typeof BroadcastChannel !== 'undefined') {
50
+ dirtyQueryChannel = new BroadcastChannel('dirty-query')
51
+
52
+ dirtyQueryChannel.addEventListener('message', (event: MessageEvent<DirtyQueryEvent>) => {
53
+ const { commandName, propertyName, value } = event.data
54
+
55
+ dirtyQuery(commandName, propertyName, value, { skipBroadcast: true })
56
+ })
57
+ }
58
+
59
+ export function dirtyQuery<CommandT extends RemoteCommand<any, any, any>> (
60
+ commandClass: RemoteCommandConstructor<CommandT> | string,
61
+ propertyName: string | undefined = undefined,
62
+ propertyValue: string | number | undefined = undefined,
63
+ options: { skipBroadcast: boolean } = { skipBroadcast: false }) {
64
+ if (typeof commandClass !== 'string') {
65
+ commandClass = commandClass.fullCommandName
66
+ }
67
+
68
+ forEachQuery((query) => {
69
+ if (query.CommandClass.fullCommandName === commandClass) {
70
+ if (query.inputs == null || Object.keys(query.inputs).length === 0) {
71
+ query.setDirty()
72
+ } else {
73
+ if (propertyName != null) {
74
+ if (query.inputs[propertyName] !== propertyValue) {
75
+ return
76
+ }
77
+ }
78
+
79
+ query.setDirty()
80
+ }
81
+ }
82
+ })
83
+
84
+ if (dirtyQueryChannel != null && !options.skipBroadcast) {
85
+ dirtyQueryChannel.postMessage({ commandName: commandClass, propertyName, value: propertyValue })
86
+ }
87
+ }
88
+
41
89
  function toKey<CommandT extends RemoteCommand<any, any, any>> (
42
90
  CommandClass: RemoteCommandConstructor<CommandT>,
43
91
  inputs: InputsOf<CommandT> | undefined
@@ -1,5 +1,8 @@
1
1
  import { type Outcome, SuccessfulOutcome, ErrorOutcome } from './Outcome'
2
2
  import { type FoobaraError } from './Error'
3
+ <% if auto_dirty_queries? %>
4
+ import { dirtyQuery } from './QueryCache'
5
+ <% end %>
3
6
 
4
7
  export default abstract class RemoteCommand<Inputs, Result, CommandError extends FoobaraError> {
5
8
  static _urlBase: string | undefined
@@ -105,6 +108,10 @@ export default abstract class RemoteCommand<Inputs, Result, CommandError extends
105
108
  return json
106
109
  }
107
110
 
111
+ <% if auto_dirty_queries? %>
112
+ dirties (): Array<[any] | [any, string, any]> { return [] }
113
+ <% end %>
114
+
108
115
  async _handleResponse (response: Response): Promise<Outcome<Result, CommandError>> {
109
116
  const text = await response.text()
110
117
  const body = JSON.parse(text)
@@ -114,6 +121,7 @@ export default abstract class RemoteCommand<Inputs, Result, CommandError extends
114
121
 
115
122
  this.outcome = new SuccessfulOutcome<Result, CommandError>(result)
116
123
  this.commandState = 'succeeded'
124
+ this.dirtyQueries()
117
125
  } else if (response.status === 422 || response.status === 401 || response.status === 403) {
118
126
  this.commandState = 'errored'
119
127
  this.outcome = new ErrorOutcome<Result, CommandError>(body)
@@ -124,4 +132,18 @@ export default abstract class RemoteCommand<Inputs, Result, CommandError extends
124
132
 
125
133
  return this.outcome
126
134
  }
135
+
136
+ <% if auto_dirty_queries? %>
137
+ dirtyQueries () {
138
+ for (const [commandClass, inputs] of this.dirties()) {
139
+ if (inputs != null) {
140
+ for (const [propertyName, value] of Object.entries(inputs)) {
141
+ dirtyQuery(commandClass, propertyName, value)
142
+ }
143
+ } else {
144
+ dirtyQuery(commandClass)
145
+ }
146
+ }
147
+ }
148
+ <% end %>
127
149
  }