@supersoniks/concorde 4.9.91 → 4.9.93

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 (48) hide show
  1. package/ai/cursor/rules/concorde.mdc +7 -0
  2. package/ai/jetbrains/rules/concorde.md +6 -0
  3. package/ai/skills/concorde/SKILL.md +48 -0
  4. package/build-infos.json +1 -1
  5. package/concorde-core.bundle.js +257 -257
  6. package/concorde-core.es.js +3174 -3086
  7. package/dist/concorde-core.bundle.js +257 -257
  8. package/dist/concorde-core.es.js +3174 -3086
  9. package/dist/js/core/decorators/api.js +168 -63
  10. package/dist/js/core/decorators/api.js.map +1 -1
  11. package/dist/js/core/utils/api.js +29 -8
  12. package/dist/js/core/utils/api.js.map +1 -1
  13. package/dist/types/core/decorators/api.d.ts +30 -16
  14. package/dist/types/core/decorators/api.d.ts.map +1 -1
  15. package/dist/types/core/utils/api.d.ts +1 -1
  16. package/dist/types/core/utils/api.d.ts.map +1 -1
  17. package/docs/assets/{index-BL6WVF7g.css → index-D2Q3JyQ6.css} +1 -1
  18. package/docs/assets/{index-DVn8AeyA.js → index-DURr6O71.js} +466 -568
  19. package/docs/crawl/docs/_decorators/get.html +35 -10
  20. package/docs/crawl/docs/_decorators/patch.html +13 -5
  21. package/docs/crawl/docs/_decorators/post.html +39 -10
  22. package/docs/crawl/docs/_decorators/put.html +13 -5
  23. package/docs/crawl/hubs/decorators.html +43 -40
  24. package/docs/crawl/hubs/remote-data.html +43 -40
  25. package/docs/index.html +2 -2
  26. package/docs/llms-full.txt +98 -23
  27. package/docs/llms.txt +1 -1
  28. package/docs/src/docs/_decorators/get.md +39 -5
  29. package/docs/src/docs/_decorators/patch.md +8 -3
  30. package/docs/src/docs/_decorators/post.md +39 -6
  31. package/docs/src/docs/_decorators/put.md +8 -3
  32. package/docs/src/docs/search/docs-search.json +103 -183
  33. package/docs/src/tsconfig.json +268 -268
  34. package/package.json +1 -1
  35. package/src/core/decorators/api.post.spec.ts +101 -6
  36. package/src/core/decorators/api.spec.ts +137 -6
  37. package/src/core/decorators/api.ts +304 -148
  38. package/src/core/utils/api.spec.ts +73 -0
  39. package/src/core/utils/api.ts +44 -11
  40. package/src/docs/_decorators/get.md +43 -5
  41. package/src/docs/_decorators/patch.md +16 -2
  42. package/src/docs/_decorators/post.md +23 -7
  43. package/src/docs/_decorators/put.md +16 -2
  44. package/src/docs/components/docs-demo-sources.ts +22 -8
  45. package/src/docs/example/decorators-demo-post.ts +70 -0
  46. package/src/docs/example/decorators-demo-subscribe-publish-get-demos.ts +61 -2
  47. package/src/docs/search/docs-search.json +122 -7
  48. package/src/tsconfig.tsbuildinfo +1 -1
@@ -153,10 +153,11 @@ dp(c</pre>
153
153
  <section id="docs-_decorators-get" data-doc-id="docs/_decorators/get">
154
154
  <h2><a href="../docs/_decorators/get.html">@get</a></h2>
155
155
  <p><strong>Doc ID:</strong> <code>docs/_decorators/get</code> · <a href="../docs/_decorators/get.html">full page</a></p>
156
- <p>@get loads data and stores the result in an ApiResult&lt;T&gt; | null property.</p>
156
+ <p>@get loads data and stores the result in an optional ApiResult&lt;T&gt; property.</p>
157
157
  <pre class="doc-excerpt">@get
158
158
 
159
- @get loads data and stores the result in an ApiResult | null property.
159
+ @get loads data and stores the result in an optional ApiResult property.
160
+ The property is undefined until a result is available.
160
161
 
161
162
  - payload.result: typed data;
162
163
  - payload.response: the HTTP response;
@@ -168,7 +169,7 @@ const usersEndpoint = new Endpoint (&quot;users&quot;);
168
169
 
169
170
  @get(usersEndpoint)
170
171
  @state()
171
- payload: ApiResult | null = null;
172
+ payload?: ApiResult ;
172
173
 
173
174
  The first argument is always an
174
175
  Endpoint . API configuration is read
@@ -187,22 +188,20 @@ const usersGet = get(new Endpoint (&quot;users&quot;));
187
188
 
188
189
  @usersGet
189
190
  @state()
190
- payload: ApiResult | null = null;
191
+ payload?: ApiResult ;
191
192
 
192
- refresh() {
193
- usersGet.refetch(this);
193
+ async refresh() {
194
+ const payload = await usersGet.refetch(this);
195
+ console.log(payload?.result);
194
196
  }
195
197
 
196
- Options (GetOptions)
198
+ refetch(component) returns a Promise | undefined&gt; that resolves
199
+ after the GET has completed.
197
200
 
198
- Options are the second argument, or the third argument when an API
199
- configuration key is provided.
201
+ From a method decorator
200
202
 
201
- - skipEmptyPlaceholder: blocks the GET when ${prop} is &quot;&quot;.
202
- - refetchEveryMs: automatically runs the GET again after this interval
203
- (milliseconds). Omit the option, or use 0, to disable polling.
204
-
205
- With a configurat</pre>
203
+ The refetch can decorate a local method. The default is after; if the
204
+ method returns a Promise, the GET waits for its resol</pre>
206
205
  </section>
207
206
  <section id="docs-_decorators-patch" data-doc-id="docs/_decorators/patch">
208
207
  <h2><a href="../docs/_decorators/patch.html">@patch</a></h2>
@@ -222,14 +221,18 @@ const patchUser = patch(new Endpoint (&quot;users/42&quot;), bodyKey);
222
221
 
223
222
  @patchUser
224
223
  @state()
225
- payload: ApiResult | null = null;
224
+ payload?: ApiResult ;
226
225
 
227
226
  To run the operation again from the component:
228
227
 
229
- savePatch() {
230
- patchUser.send(this);
228
+ async savePatch() {
229
+ await patchUser.send(this);
231
230
  }
232
231
 
232
+ send(component) returns a Promise resolved after the PATCH completes. See
233
+ @post for the method-decorator form and the
234
+ when: &quot;before&quot; option.
235
+
233
236
  The PATCH is also sent automatically when the body mutates, unless
234
237
  autoPostOnBodyMutation: false is set. The available options are described in
235
238
  @post:
@@ -238,6 +241,7 @@ autoPostOnBodyMutation: false is set. The available options are described in
238
241
  - skipIfBodyMissing
239
242
  - refetchEveryMs
240
243
  - skipEmptyPlaceholder
244
+ - triggerKey
241
245
 
242
246
  Pass explicit API configuration as the third argument:
243
247
 
@@ -251,9 +255,7 @@ import { Endpoint } from &quot;@supersoniks/concorde/utils/endpoint&quot;;
251
255
 
252
256
  See also
253
257
 
254
- - @post — options and triggers
255
- - @put — full replacement
256
- - Dynamic path placeholders</pre>
258
+ - @post —</pre>
257
259
  </section>
258
260
  <section id="docs-_decorators-post" data-doc-id="docs/_decorators/post">
259
261
  <h2><a href="../docs/_decorators/post.html">@post</a></h2>
@@ -262,7 +264,8 @@ See also
262
264
  <pre class="doc-excerpt">@post
263
265
 
264
266
  @post sends the contents of a publisher and stores the response in an
265
- ApiResult | null property.
267
+ optional ApiResult property. The property is undefined until a result
268
+ is available.
266
269
 
267
270
  Minimal usage
268
271
 
@@ -273,7 +276,7 @@ const createUser = post(new Endpoint (&quot;users&quot;), userBodyKey);
273
276
 
274
277
  @createUser
275
278
  @state()
276
- payload: ApiResult | null = null;
279
+ payload?: ApiResult ;
277
280
 
278
281
  The current body is read from userBodyKey. By default, the POST is sent when
279
282
  the component connects and after each body mutation. Mutations in the same
@@ -289,23 +292,19 @@ From the component
289
292
  Keep the decorator to access send(component). The body is read again when the
290
293
  operation runs.
291
294
 
292
- saveAgain() {
293
- createUser.send(this);
295
+ async saveAgain() {
296
+ const payload = await createUser.send(this);
297
+ console.log(payload?.result);
294
298
  }
295
299
 
296
- send() is useful for “Save” or “Retry” buttons. It can repeat an operation
297
- with side effects.
300
+ send() returns a Promise | undefined&gt; that resolves after the
301
+ operation completes. It is useful for “Save” or “Retry” buttons and can repeat
302
+ an operation with side effects.
298
303
 
299
- Options (PostOptions)
304
+ From a method decorator
300
305
 
301
- Options are the third argument, or the fourth argument when a configuration key
302
- is provided.
303
-
304
- - autoPostOnBodyMutation: send after a body mutation (default: true). Set
305
- it to false to use send().
306
- - skipIfBodyMissing: skip when the body is null or undefined (default:
307
- true).
308
- - refetchE</pre>
306
+ The send action can decorate a local method. It runs after the method by
307
+ default, waits for an eventu</pre>
309
308
  </section>
310
309
  <section id="docs-_decorators-put" data-doc-id="docs/_decorators/put">
311
310
  <h2><a href="../docs/_decorators/put.html">@put</a></h2>
@@ -325,14 +324,18 @@ const updateUser = put(new Endpoint (&quot;users/42&quot;), bodyKey);
325
324
 
326
325
  @updateUser
327
326
  @state()
328
- payload: ApiResult | null = null;
327
+ payload?: ApiResult ;
329
328
 
330
329
  To run the operation again from the component:
331
330
 
332
- update() {
333
- updateUser.send(this);
331
+ async update() {
332
+ await updateUser.send(this);
334
333
  }
335
334
 
335
+ send(component) returns a Promise resolved after the PUT completes. See
336
+ @post for the method-decorator form and the
337
+ when: &quot;before&quot; option.
338
+
336
339
  The PUT is also sent automatically when the body mutates, unless
337
340
  autoPostOnBodyMutation: false is set. See
338
341
  @post for the option details:
@@ -341,6 +344,7 @@ autoPostOnBodyMutation: false is set. See
341
344
  - skipIfBodyMissing
342
345
  - refetchEveryMs
343
346
  - skipEmptyPlaceholder
347
+ - triggerKey
344
348
 
345
349
  Pass explicit API configuration as the third argument:
346
350
 
@@ -355,8 +359,7 @@ import { Endpoint } from &quot;@supersoniks/concorde/utils/endpoint&quot;;
355
359
  See also
356
360
 
357
361
  - @post — options and triggers
358
- - @patch — partial update
359
- - Dynamic path placeholders</pre>
362
+ - @</pre>
360
363
  </section>
361
364
  <section id="docs-_misc-api-configuration" data-doc-id="docs/_misc/api-configuration">
362
365
  <h2><a href="../docs/_misc/api-configuration.html">API configuration</a></h2>
package/docs/index.html CHANGED
@@ -10,8 +10,8 @@
10
10
  <!-- <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
11
11
  -->
12
12
  <script src="https://cdn.jsdelivr.net/npm/marked@13.0.3"></script>
13
- <script type="module" crossorigin src="./assets/index-DVn8AeyA.js"></script>
14
- <link rel="stylesheet" crossorigin href="./assets/index-BL6WVF7g.css">
13
+ <script type="module" crossorigin src="./assets/index-DURr6O71.js"></script>
14
+ <link rel="stylesheet" crossorigin href="./assets/index-D2Q3JyQ6.css">
15
15
  </head>
16
16
  <body class="px-6 lg:px-20">
17
17
  <sonic-theme
@@ -3134,16 +3134,17 @@ Shared data: Sharing data.
3134
3134
 
3135
3135
  - URL: https://concorde.supersoniks.org/crawl/docs/_decorators/get.html
3136
3136
  - Doc ID: docs/_decorators/get
3137
- - Keywords: Concorde, supersoniks, docs/_decorators/get, get, @get, decorator, ApiResult | null, payload.result, payload.response, payload.request,
3137
+ - Keywords: Concorde, supersoniks, docs/_decorators/get, get, @get, decorator, ApiResult, undefined, payload.result, payload.response, payload.request,
3138
3138
 
3139
3139
  The first argument is always an
3140
3140
  [, serviceURL, refetch(component),
3141
3141
 
3142
- ## Options (, skipEmptyPlaceholder
3142
+
3143
3143
 
3144
3144
  @get
3145
3145
 
3146
- @get loads data and stores the result in an ApiResult | null property.
3146
+ @get loads data and stores the result in an optional ApiResult property.
3147
+ The property is undefined until a result is available.
3147
3148
 
3148
3149
  - payload.result: typed data;
3149
3150
  - payload.response: the HTTP response;
@@ -3155,7 +3156,7 @@ const usersEndpoint = new Endpoint ("users");
3155
3156
 
3156
3157
  @get(usersEndpoint)
3157
3158
  @state()
3158
- payload: ApiResult | null = null;
3159
+ payload?: ApiResult ;
3159
3160
 
3160
3161
  The first argument is always an
3161
3162
  Endpoint . API configuration is read
@@ -3174,12 +3175,39 @@ const usersGet = get(new Endpoint ("users"));
3174
3175
 
3175
3176
  @usersGet
3176
3177
  @state()
3177
- payload: ApiResult | null = null;
3178
+ payload?: ApiResult ;
3179
+
3180
+ async refresh() {
3181
+ const payload = await usersGet.refetch(this);
3182
+ console.log(payload?.result);
3183
+ }
3184
+
3185
+ refetch(component) returns a Promise | undefined> that resolves
3186
+ after the GET has completed.
3187
+
3188
+ From a method decorator
3189
+
3190
+ The refetch can decorate a local method. The default is after; if the
3191
+ method returns a Promise, the GET waits for its resolution. The decorated method
3192
+ call also waits for the refetch to complete.
3193
+
3194
+ import { refetch } from "@supersoniks/concorde/decorators";
3178
3195
 
3179
- refresh() {
3180
- usersGet.refetch(this);
3196
+ @refetch(usersGet)
3197
+ async reload() {
3198
+ this.userId = "42";
3181
3199
  }
3182
3200
 
3201
+ Use { when: "before" } when the GET must complete before the method runs:
3202
+
3203
+ @refetch(usersGet, { when: "before" })
3204
+ reloadBefore() {
3205
+ // The refetch has completed before this method runs.
3206
+ }
3207
+
3208
+ The method decorator adds an explicit trigger; changes to dynamic endpoint
3209
+ properties and configuration publishers keep their existing automatic behavior.
3210
+
3183
3211
  Options (GetOptions)
3184
3212
 
3185
3213
  Options are the second argument, or the third argument when an API
@@ -3188,6 +3216,7 @@ configuration key is provided.
3188
3216
  - skipEmptyPlaceholder: blocks the GET when ${prop} is "".
3189
3217
  - refetchEveryMs: automatically runs the GET again after this interval
3190
3218
  (milliseconds). Omit the option, or use 0, to disable polling.
3219
+ - triggerKey: a publisher whose invalidate() runs the GET again.
3191
3220
 
3192
3221
  With a configuration key, use:
3193
3222
 
@@ -3198,6 +3227,7 @@ When the GET runs again
3198
3227
  - when the component connects and configuration is available;
3199
3228
  - when a property used in ${...} changes;
3200
3229
  - when a configuration publisher changes;
3230
+ - when the triggerKey publisher is invalidated;
3201
3231
  - after each response when refetchEveryMs is set.
3202
3232
 
3203
3233
  See Dynamic path placeholders for
@@ -3725,7 +3755,9 @@ Notes
3725
3755
 
3726
3756
  - URL: https://concorde.supersoniks.org/crawl/docs/_decorators/patch.html
3727
3757
  - Doc ID: docs/_decorators/patch
3728
- - Keywords: Concorde, supersoniks, docs/_decorators/patch, patch, @patch, decorator, Endpoint, DataProviderKey, ApiResult, send(component), autoPostOnBodyMutation: false, autoPostOnBodyMutation, skipIfBodyMissing, refetchEveryMs, skipEmptyPlaceholder
3758
+ - Keywords: Concorde, supersoniks, docs/_decorators/patch, patch, @patch, decorator, Endpoint, DataProviderKey, ApiResult, send(component),
3759
+
3760
+ , when: "before", autoPostOnBodyMutation: false, autoPostOnBodyMutation, skipIfBodyMissing
3729
3761
 
3730
3762
  @patch
3731
3763
 
@@ -3741,14 +3773,18 @@ const patchUser = patch(new Endpoint ("users/42"), bodyKey);
3741
3773
 
3742
3774
  @patchUser
3743
3775
  @state()
3744
- payload: ApiResult | null = null;
3776
+ payload?: ApiResult ;
3745
3777
 
3746
3778
  To run the operation again from the component:
3747
3779
 
3748
- savePatch() {
3749
- patchUser.send(this);
3780
+ async savePatch() {
3781
+ await patchUser.send(this);
3750
3782
  }
3751
3783
 
3784
+ send(component) returns a Promise resolved after the PATCH completes. See
3785
+ @post for the method-decorator form and the
3786
+ when: "before" option.
3787
+
3752
3788
  The PATCH is also sent automatically when the body mutates, unless
3753
3789
  autoPostOnBodyMutation: false is set. The available options are described in
3754
3790
  @post:
@@ -3757,6 +3793,7 @@ autoPostOnBodyMutation: false is set. The available options are described in
3757
3793
  - skipIfBodyMissing
3758
3794
  - refetchEveryMs
3759
3795
  - skipEmptyPlaceholder
3796
+ - triggerKey
3760
3797
 
3761
3798
  Pass explicit API configuration as the third argument:
3762
3799
 
@@ -3780,16 +3817,19 @@ See also
3780
3817
 
3781
3818
  - URL: https://concorde.supersoniks.org/crawl/docs/_decorators/post.html
3782
3819
  - Doc ID: docs/_decorators/post
3783
- - Keywords: Concorde, supersoniks, docs/_decorators/post, post, @post, decorator, ApiResult | null, Endpoint, DataProviderKey,
3820
+ - Keywords: Concorde, supersoniks, docs/_decorators/post, post, @post, decorator, ApiResult, undefined, Endpoint, DataProviderKey,
3784
3821
 
3785
3822
  The current body is read from , send(component),
3786
3823
 
3787
- , PostOptions, autoPostOnBodyMutation, true
3824
+ , returns a ,
3825
+
3826
+ Use
3788
3827
 
3789
3828
  @post
3790
3829
 
3791
3830
  @post sends the contents of a publisher and stores the response in an
3792
- ApiResult | null property.
3831
+ optional ApiResult property. The property is undefined until a result
3832
+ is available.
3793
3833
 
3794
3834
  Minimal usage
3795
3835
 
@@ -3800,7 +3840,7 @@ const createUser = post(new Endpoint ("users"), userBodyKey);
3800
3840
 
3801
3841
  @createUser
3802
3842
  @state()
3803
- payload: ApiResult | null = null;
3843
+ payload?: ApiResult ;
3804
3844
 
3805
3845
  The current body is read from userBodyKey. By default, the POST is sent when
3806
3846
  the component connects and after each body mutation. Mutations in the same
@@ -3816,12 +3856,38 @@ From the component
3816
3856
  Keep the decorator to access send(component). The body is read again when the
3817
3857
  operation runs.
3818
3858
 
3819
- saveAgain() {
3820
- createUser.send(this);
3859
+ async saveAgain() {
3860
+ const payload = await createUser.send(this);
3861
+ console.log(payload?.result);
3862
+ }
3863
+
3864
+ send() returns a Promise | undefined> that resolves after the
3865
+ operation completes. It is useful for “Save” or “Retry” buttons and can repeat
3866
+ an operation with side effects.
3867
+
3868
+ From a method decorator
3869
+
3870
+ The send action can decorate a local method. It runs after the method by
3871
+ default, waits for an eventual Promise to resolve, and the decorated method
3872
+ call waits for the send to complete:
3873
+
3874
+ import { send } from "@supersoniks/concorde/decorators";
3875
+
3876
+ @send(createUser)
3877
+ async save() {
3878
+ // Prepare local state or validate the form.
3879
+ }
3880
+
3881
+ Use { when: "before" } when the send must complete before the method runs:
3882
+
3883
+ @send(createUser, { when: "before" })
3884
+ saveBefore() {
3885
+ // The POST has completed before this method runs.
3821
3886
  }
3822
3887
 
3823
- send() is useful for “Save” or “Retry” buttons. It can repeat an operation
3824
- with side effects.
3888
+ The method decorator adds an explicit send. If the method also mutates the body
3889
+ publisher, set autoPostOnBodyMutation: false when the decorated method must
3890
+ be the only trigger.
3825
3891
 
3826
3892
  Options (PostOptions)
3827
3893
 
@@ -3836,6 +3902,7 @@ is provided.
3836
3902
  repeating the operation is intended.
3837
3903
  - skipEmptyPlaceholder: block the request when a ${...} placeholder is
3838
3904
  "".
3905
+ - triggerKey: a publisher whose invalidate() sends the POST again.
3839
3906
 
3840
3907
  With a configuration key:
3841
3908
 
@@ -3850,6 +3917,7 @@ When the POST is sent
3850
3917
  - after a body mutation, unless autoPostOnBodyMutation: false;
3851
3918
  - when a property used in ${...} changes;
3852
3919
  - when a configuration publisher changes;
3920
+ - when the triggerKey publisher is invalidated;
3853
3921
  - when send() is called;
3854
3922
  - after each response when refetchEveryMs is set.
3855
3923
 
@@ -3923,7 +3991,9 @@ Dynamic paths use the same placeholder rules as @bind / @subscribe. Resolution a
3923
3991
 
3924
3992
  - URL: https://concorde.supersoniks.org/crawl/docs/_decorators/put.html
3925
3993
  - Doc ID: docs/_decorators/put
3926
- - Keywords: Concorde, supersoniks, docs/_decorators/put, put, @put, decorator, Endpoint, DataProviderKey, ApiResult, send(component), autoPostOnBodyMutation: false, autoPostOnBodyMutation, skipIfBodyMissing, refetchEveryMs, skipEmptyPlaceholder
3994
+ - Keywords: Concorde, supersoniks, docs/_decorators/put, put, @put, decorator, Endpoint, DataProviderKey, ApiResult, send(component),
3995
+
3996
+ , when: "before", autoPostOnBodyMutation: false, autoPostOnBodyMutation, skipIfBodyMissing
3927
3997
 
3928
3998
  @put
3929
3999
 
@@ -3939,14 +4009,18 @@ const updateUser = put(new Endpoint ("users/42"), bodyKey);
3939
4009
 
3940
4010
  @updateUser
3941
4011
  @state()
3942
- payload: ApiResult | null = null;
4012
+ payload?: ApiResult ;
3943
4013
 
3944
4014
  To run the operation again from the component:
3945
4015
 
3946
- update() {
3947
- updateUser.send(this);
4016
+ async update() {
4017
+ await updateUser.send(this);
3948
4018
  }
3949
4019
 
4020
+ send(component) returns a Promise resolved after the PUT completes. See
4021
+ @post for the method-decorator form and the
4022
+ when: "before" option.
4023
+
3950
4024
  The PUT is also sent automatically when the body mutates, unless
3951
4025
  autoPostOnBodyMutation: false is set. See
3952
4026
  @post for the option details:
@@ -3955,6 +4029,7 @@ autoPostOnBodyMutation: false is set. See
3955
4029
  - skipIfBodyMissing
3956
4030
  - refetchEveryMs
3957
4031
  - skipEmptyPlaceholder
4032
+ - triggerKey
3958
4033
 
3959
4034
  Pass explicit API configuration as the third argument:
3960
4035
 
package/docs/llms.txt CHANGED
@@ -71,7 +71,7 @@ Custom
71
71
  - [@ancestorAttribute](https://concorde.supersoniks.org/crawl/docs/_decorators/ancestor-attribute.html) (docs/_decorators/ancestor-attribute): The @ancestorAttribute decorator automatically injects the value of an ancestor's attribute into a class property at the time of connectedCallback.
72
72
  - [@autoSubscribe](https://concorde.supersoniks.org/crawl/docs/_decorators/auto-subscribe.html) (docs/_decorators/auto-subscribe): > Legacy: prefer @subscribe + DataProviderKey. Examples below may still show PublisherManager for existing codebases.
73
73
  - [@bind](https://concorde.supersoniks.org/crawl/docs/_decorators/bind.html) (docs/_decorators/bind): Binds a class property to a path in a publisher. The property updates when publisher data changes.
74
- - [@get](https://concorde.supersoniks.org/crawl/docs/_decorators/get.html) (docs/_decorators/get): @get loads data and stores the result in an ApiResult<T> | null property.
74
+ - [@get](https://concorde.supersoniks.org/crawl/docs/_decorators/get.html) (docs/_decorators/get): @get loads data and stores the result in an optional ApiResult<T> property.
75
75
  - [@handle](https://concorde.supersoniks.org/crawl/docs/_decorators/handle.html) (docs/_decorators/handle): Typed callback on one or more DataProviderKey<T> paths: invokes the decorated method when a publisher assigns a value (calculations, side effects, updating other @state properties, etc.).
76
76
  - [@onAssign](https://concorde.supersoniks.org/crawl/docs/_decorators/on-assign.html) (docs/_decorators/on-assign): > New apps: use @handle with DataProviderKey (Data flow). @onAssign uses untyped string paths; it remains documented for existing codebases — see Migrating to @handle below.
77
77
  - [@patch](https://concorde.supersoniks.org/crawl/docs/_decorators/patch.html) (docs/_decorators/patch): @patch applies a partial update with the body from a publisher. It uses the
@@ -1,6 +1,7 @@
1
1
  # @get
2
2
 
3
- `@get` loads data and stores the result in an `ApiResult<T> | null` property.
3
+ `@get` loads data and stores the result in an optional `ApiResult<T>` property.
4
+ The property is `undefined` until a result is available.
4
5
 
5
6
  - `payload.result`: typed data;
6
7
  - `payload.response`: the HTTP response;
@@ -13,7 +14,7 @@ const usersEndpoint = new Endpoint<User[]>("users");
13
14
 
14
15
  @get(usersEndpoint)
15
16
  @state()
16
- payload: ApiResult<User[]> | null = null;
17
+ payload?: ApiResult<User[]>;
17
18
  ```
18
19
 
19
20
  The first argument is always an
@@ -34,13 +35,44 @@ const usersGet = get(new Endpoint<User[]>("users"));
34
35
 
35
36
  @usersGet
36
37
  @state()
37
- payload: ApiResult<User[]> | null = null;
38
+ payload?: ApiResult<User[]>;
38
39
 
39
- refresh() {
40
- usersGet.refetch(this);
40
+ async refresh() {
41
+ const payload = await usersGet.refetch(this);
42
+ console.log(payload?.result);
41
43
  }
42
44
  ```
43
45
 
46
+ `refetch(component)` returns a `Promise<ApiResult<T> | undefined>` that resolves
47
+ after the GET has completed.
48
+
49
+ ### From a method decorator
50
+
51
+ The refetch can decorate a local method. The default is `after`; if the
52
+ method returns a Promise, the GET waits for its resolution. The decorated method
53
+ call also waits for the refetch to complete.
54
+
55
+ ```typescript
56
+ import { refetch } from "@supersoniks/concorde/decorators";
57
+
58
+ @refetch(usersGet)
59
+ async reload() {
60
+ this.userId = "42";
61
+ }
62
+ ```
63
+
64
+ Use `{ when: "before" }` when the GET must complete before the method runs:
65
+
66
+ ```typescript
67
+ @refetch(usersGet, { when: "before" })
68
+ reloadBefore() {
69
+ // The refetch has completed before this method runs.
70
+ }
71
+ ```
72
+
73
+ The method decorator adds an explicit trigger; changes to dynamic endpoint
74
+ properties and configuration publishers keep their existing automatic behavior.
75
+
44
76
  ## Options (`GetOptions`)
45
77
 
46
78
  Options are the second argument, or the third argument when an API
@@ -49,6 +81,7 @@ configuration key is provided.
49
81
  - `skipEmptyPlaceholder`: blocks the GET when `${prop}` is `""`.
50
82
  - `refetchEveryMs`: automatically runs the GET again after this interval
51
83
  (milliseconds). Omit the option, or use `0`, to disable polling.
84
+ - `triggerKey`: a publisher whose `invalidate()` runs the GET again.
52
85
 
53
86
  With a configuration key, use:
54
87
 
@@ -61,6 +94,7 @@ With a configuration key, use:
61
94
  - when the component connects and configuration is available;
62
95
  - when a property used in `${...}` changes;
63
96
  - when a configuration publisher changes;
97
+ - when the `triggerKey` publisher is invalidated;
64
98
  - after each response when `refetchEveryMs` is set.
65
99
 
66
100
  See [Dynamic path placeholders](#docs/_misc/dynamic-path.md/dynamic-path) for
@@ -13,17 +13,21 @@ const patchUser = patch(new Endpoint<User>("users/42"), bodyKey);
13
13
 
14
14
  @patchUser
15
15
  @state()
16
- payload: ApiResult<User> | null = null;
16
+ payload?: ApiResult<User>;
17
17
  ```
18
18
 
19
19
  To run the operation again from the component:
20
20
 
21
21
  ```typescript
22
- savePatch() {
23
- patchUser.send(this);
22
+ async savePatch() {
23
+ await patchUser.send(this);
24
24
  }
25
25
  ```
26
26
 
27
+ `send(component)` returns a Promise resolved after the PATCH completes. See
28
+ [@post](#docs/_decorators/post.md/post) for the method-decorator form and the
29
+ `when: "before"` option.
30
+
27
31
  The PATCH is also sent automatically when the body mutates, unless
28
32
  `autoPostOnBodyMutation: false` is set. The available options are described in
29
33
  [@post](#docs/_decorators/post.md/post):
@@ -32,6 +36,7 @@ The PATCH is also sent automatically when the body mutates, unless
32
36
  - `skipIfBodyMissing`
33
37
  - `refetchEveryMs`
34
38
  - `skipEmptyPlaceholder`
39
+ - `triggerKey`
35
40
 
36
41
  Pass explicit API configuration as the third argument:
37
42
 
@@ -1,7 +1,8 @@
1
1
  # @post
2
2
 
3
3
  `@post` sends the contents of a publisher and stores the response in an
4
- `ApiResult<T> | null` property.
4
+ optional `ApiResult<T>` property. The property is `undefined` until a result
5
+ is available.
5
6
 
6
7
  ## Minimal usage
7
8
 
@@ -13,7 +14,7 @@ const createUser = post(new Endpoint<User>("users"), userBodyKey);
13
14
 
14
15
  @createUser
15
16
  @state()
16
- payload: ApiResult<User> | null = null;
17
+ payload?: ApiResult<User>;
17
18
  ```
18
19
 
19
20
  The current body is read from `userBodyKey`. By default, the POST is sent when
@@ -31,13 +32,43 @@ Keep the decorator to access `send(component)`. The body is read again when the
31
32
  operation runs.
32
33
 
33
34
  ```typescript
34
- saveAgain() {
35
- createUser.send(this);
35
+ async saveAgain() {
36
+ const payload = await createUser.send(this);
37
+ console.log(payload?.result);
36
38
  }
37
39
  ```
38
40
 
39
- `send()` is useful for “Save” or “Retry” buttons. It can repeat an operation
40
- with side effects.
41
+ `send()` returns a `Promise<ApiResult<T> | undefined>` that resolves after the
42
+ operation completes. It is useful for “Save” or “Retry” buttons and can repeat
43
+ an operation with side effects.
44
+
45
+ ### From a method decorator
46
+
47
+ The send action can decorate a local method. It runs after the method by
48
+ default, waits for an eventual Promise to resolve, and the decorated method
49
+ call waits for the send to complete:
50
+
51
+ ```typescript
52
+ import { send } from "@supersoniks/concorde/decorators";
53
+
54
+ @send(createUser)
55
+ async save() {
56
+ // Prepare local state or validate the form.
57
+ }
58
+ ```
59
+
60
+ Use `{ when: "before" }` when the send must complete before the method runs:
61
+
62
+ ```typescript
63
+ @send(createUser, { when: "before" })
64
+ saveBefore() {
65
+ // The POST has completed before this method runs.
66
+ }
67
+ ```
68
+
69
+ The method decorator adds an explicit send. If the method also mutates the body
70
+ publisher, set `autoPostOnBodyMutation: false` when the decorated method must
71
+ be the only trigger.
41
72
 
42
73
  ## Options (`PostOptions`)
43
74
 
@@ -52,6 +83,7 @@ is provided.
52
83
  repeating the operation is intended.
53
84
  - `skipEmptyPlaceholder`: block the request when a `${...}` placeholder is
54
85
  `""`.
86
+ - `triggerKey`: a publisher whose `invalidate()` sends the POST again.
55
87
 
56
88
  With a configuration key:
57
89
 
@@ -68,6 +100,7 @@ dynamic path details.
68
100
  - after a body mutation, unless `autoPostOnBodyMutation: false`;
69
101
  - when a property used in `${...}` changes;
70
102
  - when a configuration publisher changes;
103
+ - when the `triggerKey` publisher is invalidated;
71
104
  - when `send()` is called;
72
105
  - after each response when `refetchEveryMs` is set.
73
106