foobara-typescript-remote-command-generator 1.2.5 → 1.2.7

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: 36ad5c92589d7b37a31298d44d7b3f3ccd6b3537a90d96816d9c35eb8cf7730d
4
- data.tar.gz: 1d9d7564f82a39eec11aa36d5f1270a569a2936501ec87694933b67a8aeb6699
3
+ metadata.gz: 4b6ba29a2e9cc4baa0b854c2af01f8f9765d784d731f71a27d664c09280050c2
4
+ data.tar.gz: 13e3647fdf41efa57db365b7b2ecb652691491cc720dc605548820e0883f0c60
5
5
  SHA512:
6
- metadata.gz: '0381acb1520c210bf2c3062c33841e2b90938877d3945b81130232c032f8c00798570bbb460fc48bc344920e4f50f0eb717481676335c063c0517824b2ebd964'
7
- data.tar.gz: a51174dd6ef504fcb130c287281b1df30c0c0ffae7e651cc9d8b8718ac10b5d1c594d29e3194b934439c7a35700b2ae342542ab98f45a591c9d51640cd46a39a
6
+ metadata.gz: c6abab21d2187b784d2cf1887c9b5e7d48b11d440819e4215215f37f5ef9c4ea3df0dd6daa79be1a07733440915b26c62bf340ad16c78b4d93617557d834193b
7
+ data.tar.gz: 47ce45d8450081c5fc6029f7dc9df67c968103a7e40edda520d2a263452e014cfa54d3123f35ab346002d1bdf490c792ef8419b5cf917f09d47898254c9090f1
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## [1.2.7] - 2026-02-16
2
+
3
+ - Make generated castJsonResult.ts files undefined-safe
4
+
5
+ ## [1.2.6] - 2026-02-16
6
+
7
+ - Make use of guaranteed_to_exist to avoid marking present delegates as optional
8
+ - Make queries automatically run regardless of inputs presence
9
+
1
10
  ## [1.2.5] - 2026-01-27
2
11
 
3
12
  - Fix circular dependency that happens if an item from this domain collides
@@ -116,24 +116,24 @@ module Foobara
116
116
  value: "element")
117
117
  result << "})"
118
118
  elsif child_cast_tree.is_a?(::Hash)
119
- # TODO: either test this codepath or delete it
119
+ # TODO: either test this code path or delete it
120
120
  # :nocov:
121
121
  property = path_part =~ /\A\d+\z/ ? path_part.to_i : "\"#{path_part}\""
122
122
 
123
123
  result << cast_json_result_function_body(child_cast_tree,
124
124
  parent:,
125
125
  property:,
126
- value: "#{parent}.#{path_part}")
126
+ value: "#{parent}?.#{path_part}")
127
127
  # :nocov:
128
128
  elsif child_cast_tree.is_a?(CastTree)
129
129
  result << cast_json_result_function_body(child_cast_tree.children,
130
- parent: "#{parent}.#{path_part}")
130
+ parent: "#{parent}?.#{path_part}")
131
131
 
132
132
  property = path_part =~ /\A\d+\z/ ? path_part.to_i : "\"#{path_part}\""
133
133
  result << _ts_cast_expression(child_cast_tree,
134
134
  parent:,
135
135
  property:,
136
- value: "#{parent}.#{path_part}")
136
+ value: "#{parent}?.#{path_part}")
137
137
  else
138
138
  # :nocov:
139
139
  raise "Not sure how to handle a #{cast_tree.class}: #{cast_tree}"
@@ -164,9 +164,9 @@ module Foobara
164
164
  if property.nil?
165
165
  parent
166
166
  elsif property =~ /\A"(.*)"\z/
167
- "#{parent}.#{$1}"
167
+ "#{parent}?.#{$1}"
168
168
  else
169
- "#{parent}[#{property}]"
169
+ "#{parent}?.[#{property}]"
170
170
  end
171
171
  else
172
172
  # TODO: either test this path or raise
@@ -183,21 +183,29 @@ module Foobara
183
183
 
184
184
  type_symbol = type.type_symbol
185
185
 
186
- value ||= lvalue
186
+ value ||= lvalue.dup
187
+ lvalue = lvalue.gsub("?.[", "[").gsub("?.", ".")
188
+ present_value = value.gsub("?.[", "[").gsub("?.", ".")
187
189
 
188
- if type_symbol == :date || type_symbol == :datetime
189
- "#{lvalue} = new Date(#{value})"
190
- elsif type.model?
191
- ts_model_name = model_to_ts_model_name(type,
192
- association_depth:,
193
- initial: cast_tree.initial)
190
+ expression = "if (#{value} !== undefined) {\n"
194
191
 
195
- "#{lvalue} = new #{ts_model_name}(#{value})"
196
- else
197
- # :nocov:
198
- raise "Not sure how to cast type #{type} to a Typescript expression"
199
- # :nocov:
200
- end
192
+ expression += if type_symbol == :date || type_symbol == :datetime
193
+ "#{lvalue} = new Date(#{present_value})"
194
+ elsif type.model?
195
+ ts_model_name = model_to_ts_model_name(type,
196
+ association_depth:,
197
+ initial: cast_tree.initial)
198
+
199
+ "#{lvalue} = new #{ts_model_name}(#{present_value})"
200
+ else
201
+ # :nocov:
202
+ raise "Not sure how to cast type #{type} to a Typescript expression"
203
+ # :nocov:
204
+ end
205
+
206
+ expression += "\n}"
207
+
208
+ expression
201
209
  end
202
210
 
203
211
  def _construct_cast_tree(type_declaration, initial: false)
@@ -285,21 +285,26 @@ module Foobara
285
285
  if model_and_entity_free
286
286
  model_type = type_declaration.to_type
287
287
 
288
- translated_type = if type_declaration.detached_entity?
289
- model_type.primary_key_type
290
- else
291
- model_type.attributes_type
292
- end
293
-
294
- foobara_type_to_ts_type(
295
- translated_type,
296
- association_depth:,
297
- dependency_group:,
298
- initial:,
299
- model_and_entity_free:,
300
- is_output:,
301
- parent: model_type
302
- )
288
+ if type_declaration.detached_entity?
289
+ foobara_type_to_ts_type(
290
+ model_type.primary_key_type,
291
+ association_depth:,
292
+ dependency_group:,
293
+ initial:,
294
+ model_and_entity_free:,
295
+ is_output:,
296
+ parent: model_type
297
+ )
298
+ else
299
+ attributes_to_ts_type(
300
+ model_type.attributes_type,
301
+ association_depth:,
302
+ dependency_group:,
303
+ model_and_entity_free:,
304
+ is_output:,
305
+ parent: model_type
306
+ )
307
+ end
303
308
  else
304
309
  model_to_ts_model_name(type_declaration, association_depth:, initial:)
305
310
  end
@@ -342,18 +347,22 @@ module Foobara
342
347
  # or something.
343
348
  if attributes.has_attribute_declarations?
344
349
  guts = attributes.attribute_declarations.map do |attribute_name, attribute_declaration|
345
- is_required = attributes.required?(attribute_name)
350
+ exists = attributes.required?(attribute_name)
346
351
 
347
- if !is_required && is_output
352
+ if !exists && parent&.model?
353
+ exists = parent.guaranteed_to_exist?(attribute_name)
354
+ end
355
+
356
+ if !exists && is_output
348
357
  default = attributes.default_for(attribute_name)
349
358
 
350
359
  if default || default == false ||
351
360
  (parent&.detached_entity? && attribute_name == parent.primary_key_name.to_sym)
352
- is_required = true
361
+ exists = true
353
362
  end
354
363
  end
355
364
 
356
- " #{attribute_name}#{"?" unless is_required}: #{
365
+ " #{attribute_name}#{"?" unless exists}: #{
357
366
  foobara_type_to_ts_type(
358
367
  attribute_declaration,
359
368
  dependency_group:,
@@ -7,7 +7,7 @@ export default class LoginCommand<Inputs, Result, Error extends FoobaraError<any
7
7
  extends RemoteCommand<Inputs, Result, Error> {
8
8
  async _handleResponse (response: Response): Promise<Outcome<Result, Error>> {
9
9
  if (response.ok) {
10
- const accessToken: string | null = response.headers.get('X-Access-Token')
10
+ const accessToken: string | null = response.headers.get('x-access-token')
11
11
 
12
12
  if (accessToken != null) {
13
13
  handleLogin(this.urlBase, accessToken)
@@ -2,6 +2,7 @@ import type Query from '../../../base/Query'
2
2
  import type RemoteCommand from '../../../base/RemoteCommand'
3
3
  import { forEachQuery } from '../../../base/QueryCache'
4
4
 
5
+ // TODO: Why is this in here? It seems general-purpose not auth-specific
5
6
  function dirtyAllQueries () {
6
7
  forEachQuery((query: Query<RemoteCommand<any, any, any>>) => {
7
8
  query.setDirty()
@@ -10,28 +11,49 @@ function dirtyAllQueries () {
10
11
 
11
12
  const accessTokens = new Map<string, string>()
12
13
 
14
+ interface AuthMessage {
15
+ type: 'login' | 'logout'
16
+ baseUrl: string
17
+ }
18
+
19
+ const login = (baseUrl: string, accessToken: string): void => {
20
+ accessTokens.set(baseUrl, accessToken)
21
+ dirtyAllQueries()
22
+ }
23
+
13
24
  const logout = (urlBase: string): void => {
14
25
  accessTokens.delete(urlBase)
15
26
  dirtyAllQueries()
16
27
  }
28
+
29
+ // These functions gets overridden with a form that broadcasts the event if BroadcastChannel is available
30
+ let handleLogin: (baseUrl: string, accessToken: string) => void = login
17
31
  let handleLogout: (baseUrl: string) => void = logout
18
32
 
19
33
  const tokenForUrl = (baseUrl: string): string | undefined => accessTokens.get(baseUrl)
20
- const handleLogin: (baseUrl: string, accessToken: string) => void = (baseUrl, accessToken) => {
21
- accessTokens.set(baseUrl, accessToken)
22
- dirtyAllQueries()
23
- }
24
34
 
25
35
  if (typeof BroadcastChannel !== 'undefined') {
26
36
  const logoutChannel = new BroadcastChannel('foobara-auth-events')
27
37
 
28
- logoutChannel.addEventListener('message', (event: MessageEvent<string>) => {
29
- accessTokens.delete(event.data)
38
+ logoutChannel.addEventListener('message', (event: MessageEvent<AuthMessage>) => {
39
+ const { type, baseUrl } = event.data
40
+
41
+ if (type === 'login') {
42
+ dirtyAllQueries()
43
+ } else if (type === 'logout') {
44
+ logout(baseUrl)
45
+ } else {
46
+ throw new Error(`Unknown auth message type: ${JSON.stringify(type)}`)
47
+ }
30
48
  })
31
49
 
32
50
  handleLogout = (baseUrl: string) => {
33
51
  logout(baseUrl)
34
- logoutChannel.postMessage(baseUrl)
52
+ logoutChannel.postMessage({ baseUrl, type: 'logout' })
53
+ }
54
+ handleLogin = (baseUrl: string, accessToken: string) => {
55
+ login(baseUrl, accessToken)
56
+ logoutChannel.postMessage({ baseUrl, type: 'login' })
35
57
  }
36
58
  }
37
59
 
@@ -16,6 +16,7 @@ export function getQuery<CommandT extends RemoteCommand<any, any, any>> (
16
16
  }
17
17
 
18
18
  let query: Query<CommandT>
19
+
19
20
  if (arguments.length === 2) {
20
21
  query = new Query<CommandT>(CommandClass, inputs)
21
22
  query.run()
@@ -48,12 +48,7 @@ export default function useQuery<CommandT extends RemoteCommand<any, any, any>>
48
48
  let query = queryRef.current
49
49
 
50
50
  if (query == null) {
51
- if (arguments.length === 2) {
52
- query = getQuery(CommandClass, inputs as InputsOf<CommandT>)
53
- } else {
54
- query = getQuery(CommandClass)
55
- }
56
-
51
+ query = getQuery(CommandClass, inputs)
57
52
  queryRef.current = query
58
53
  }
59
54
 
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.5
4
+ version: 1.2.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miles Georgi