@supersoniks/concorde 4.9.9 → 4.9.92
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.
- package/build-infos.json +1 -1
- package/concorde-core.bundle.js +241 -241
- package/concorde-core.es.js +2931 -2851
- package/dist/concorde-core.bundle.js +241 -241
- package/dist/concorde-core.es.js +2931 -2851
- package/dist/js/core/decorators/api.js +146 -43
- package/dist/js/core/decorators/api.js.map +1 -1
- package/dist/js/decorators.js +4 -0
- package/dist/js/decorators.js.map +1 -1
- package/dist/types/core/decorators/api.d.ts +87 -60
- package/dist/types/core/decorators/api.d.ts.map +1 -1
- package/dist/types/decorators.d.ts +3 -1
- package/dist/types/decorators.d.ts.map +1 -1
- package/docs/assets/index-D2Q3JyQ6.css +1 -0
- package/docs/assets/{index-hElUgV9_.js → index-DURr6O71.js} +651 -736
- package/docs/crawl/docs/_decorators/get.html +89 -81
- package/docs/crawl/docs/_decorators/patch.html +43 -23
- package/docs/crawl/docs/_decorators/post.html +101 -72
- package/docs/crawl/docs/_decorators/put.html +44 -21
- package/docs/crawl/docs/_getting-started/ai-agents.html +45 -6
- package/docs/crawl/hubs/decorators.html +145 -70
- package/docs/crawl/hubs/remote-data.html +145 -70
- package/docs/index.html +2 -2
- package/docs/llms-full.txt +276 -147
- package/docs/llms.txt +4 -4
- package/docs/src/core/components/functional/queue/queue.md +0 -0
- package/docs/src/core/components/ui/button/button.md +0 -0
- package/docs/src/docs/_decorators/get.md +88 -80
- package/docs/src/docs/_decorators/patch.md +41 -25
- package/docs/src/docs/_decorators/post.md +104 -62
- package/docs/src/docs/_decorators/put.md +42 -24
- package/docs/src/docs/_getting-started/ai-agents.md +24 -4
- package/docs/src/docs/search/docs-search.json +182 -112
- package/docs/src/tsconfig.json +270 -267
- package/package.json +1 -1
- package/src/core/decorators/api.post.spec.ts +79 -1
- package/src/core/decorators/api.spec.ts +141 -1
- package/src/core/decorators/api.ts +330 -180
- package/src/decorators.ts +7 -0
- package/src/docs/_decorators/get.md +88 -80
- package/src/docs/_decorators/patch.md +41 -25
- package/src/docs/_decorators/post.md +104 -62
- package/src/docs/_decorators/put.md +42 -24
- package/src/docs/components/docs-demo-sources.ts +9 -14
- package/src/docs/example/decorators-demo-geo.ts +0 -21
- package/src/docs/example/decorators-demo-subscribe-publish-get-demos.ts +42 -133
- package/src/docs/search/docs-search.json +128 -133
- package/docs/assets/index-Bnp7gVaA.css +0 -1
|
@@ -4,8 +4,13 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>@get — Concorde</title>
|
|
7
|
-
<meta name="description" content="
|
|
8
|
-
<meta name="keywords" content="Concorde, supersoniks, docs/_decorators/get, get, @get, decorator,
|
|
7
|
+
<meta name="description" content="@get loads data and stores the result in an optional ApiResult<T> property.">
|
|
8
|
+
<meta name="keywords" content="Concorde, supersoniks, docs/_decorators/get, get, @get, decorator, ApiResult, undefined, payload.result, payload.response, payload.request,
|
|
9
|
+
|
|
10
|
+
The first argument is always an
|
|
11
|
+
[, serviceURL, refetch(component),
|
|
12
|
+
|
|
13
|
+
">
|
|
9
14
|
<meta name="concorde-doc-id" content="docs/_decorators/get">
|
|
10
15
|
<link rel="canonical" href="https://concorde.supersoniks.org/crawl/docs/_decorators/get.html">
|
|
11
16
|
</head>
|
|
@@ -15,104 +20,107 @@
|
|
|
15
20
|
</header>
|
|
16
21
|
<main>
|
|
17
22
|
<article>
|
|
18
|
-
<p class="doc-lead" id="doc-summary"><strong>Concorde decorator — @get</strong>.
|
|
23
|
+
<p class="doc-lead" id="doc-summary"><strong>Concorde decorator — @get</strong>. @get loads data and stores the result in an optional ApiResult<T> property. <span>Doc ID: <code>docs/_decorators/get</code>. Keywords: Concorde, supersoniks, docs/_decorators/get, get, @get, decorator, ApiResult, undefined, payload.result, payload.response, payload.request,
|
|
24
|
+
|
|
25
|
+
The first argument is always an
|
|
26
|
+
[, serviceURL, refetch(component),
|
|
27
|
+
|
|
28
|
+
. URL: <a href="https://concorde.supersoniks.org/crawl/docs/_decorators/get.html">https://concorde.supersoniks.org/crawl/docs/_decorators/get.html</a>.</span></p>
|
|
19
29
|
<h1 id="get">@get</h1>
|
|
20
|
-
<p>
|
|
21
|
-
|
|
22
|
-
<h2 id="configuration">Configuration</h2>
|
|
30
|
+
<p><code>@get</code> loads data and stores the result in an optional <code>ApiResult<T></code> property.
|
|
31
|
+
The property is <code>undefined</code> until a result is available.</p>
|
|
23
32
|
<ul>
|
|
24
|
-
<li><
|
|
25
|
-
<li><
|
|
33
|
+
<li><code>payload.result</code>: typed data;</li>
|
|
34
|
+
<li><code>payload.response</code>: the HTTP response;</li>
|
|
35
|
+
<li><code>payload.request</code>: the request that was sent.</li>
|
|
26
36
|
</ul>
|
|
27
|
-
<h2 id="
|
|
28
|
-
<
|
|
29
|
-
<h2 id="options-getoptions">Options (<code>GetOptions</code>)</h2>
|
|
30
|
-
<p>Pass as the <strong>second</strong> argument (scoped config) or <strong>third</strong> (with a configuration key). Same shape as send decorators where applicable:</p>
|
|
31
|
-
<table>
|
|
32
|
-
<thead>
|
|
33
|
-
<tr>
|
|
34
|
-
<th>Option</th>
|
|
35
|
-
<th>Description</th>
|
|
36
|
-
</tr>
|
|
37
|
-
</thead>
|
|
38
|
-
<tbody><tr>
|
|
39
|
-
<td><code>skipEmptyPlaceholder</code></td>
|
|
40
|
-
<td>Treat <code>""</code> as not ready (see <a href="../_misc/dynamic-path.html#dynamic-path">Dynamic path</a>).</td>
|
|
41
|
-
</tr>
|
|
42
|
-
<tr>
|
|
43
|
-
<td><code>refetchEveryMs</code></td>
|
|
44
|
-
<td>Automatic polling interval (ms). <code>0</code> or omitted = no polling.</td>
|
|
45
|
-
</tr>
|
|
46
|
-
<tr>
|
|
47
|
-
<td><code>triggerKey</code></td>
|
|
48
|
-
<td><code>DataProviderKey</code> — <code>PublisherManager.get(...).invalidate()</code> on that publisher re-runs the GET.</td>
|
|
49
|
-
</tr>
|
|
50
|
-
</tbody></table>
|
|
51
|
-
<h3 id="manual-refetch-triggerkey">Manual refetch (<code>triggerKey</code>)</h3>
|
|
52
|
-
<p>Same pattern as <a href="./post.html#post">@post</a>: a publisher acts as a <strong>signal</strong>, independent of the response payload.</p>
|
|
53
|
-
<pre><code class="language-typescript">import { get, type ApiResult } from "@supersoniks/concorde/decorators";
|
|
54
|
-
import { Endpoint } from "@supersoniks/concorde/utils/endpoint";
|
|
55
|
-
import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
|
|
56
|
-
import { dp } from "@supersoniks/concorde/core/utils/PublisherProxy";
|
|
37
|
+
<h2 id="minimal-usage">Minimal usage</h2>
|
|
38
|
+
<pre><code class="language-typescript">const usersEndpoint = new Endpoint<User[]>("users");
|
|
57
39
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
40
|
+
@get(usersEndpoint)
|
|
41
|
+
@state()
|
|
42
|
+
payload?: ApiResult<User[]>;
|
|
43
|
+
</code></pre>
|
|
44
|
+
<p>The first argument is always an
|
|
45
|
+
<a href="../_misc/endpoint.html#endpoint"><code>Endpoint<T></code></a>. API configuration is read
|
|
46
|
+
from the HTML scope (<code>serviceURL</code>, token, etc.), so the component is usually
|
|
47
|
+
placed below an element that provides this configuration.</p>
|
|
48
|
+
<h2 id="refetching-a-get">Refetching a GET</h2>
|
|
49
|
+
<h3 id="from-the-component">From the component</h3>
|
|
50
|
+
<p>Keep the decorator in a constant to access <code>refetch(component)</code>. Refetch only
|
|
51
|
+
targets the instance passed as the argument, even before it has received a
|
|
52
|
+
result.</p>
|
|
53
|
+
<pre><code class="language-typescript">const usersGet = get(new Endpoint<User[]>("users"));
|
|
64
54
|
|
|
65
|
-
@
|
|
66
|
-
triggerKey: geoCommunesRefreshKey,
|
|
67
|
-
})
|
|
55
|
+
@usersGet
|
|
68
56
|
@state()
|
|
69
|
-
payload
|
|
57
|
+
payload?: ApiResult<User[]>;
|
|
70
58
|
|
|
71
|
-
|
|
72
|
-
|
|
59
|
+
async refresh() {
|
|
60
|
+
const payload = await usersGet.refetch(this);
|
|
61
|
+
console.log(payload?.result);
|
|
62
|
+
}
|
|
63
|
+
</code></pre>
|
|
64
|
+
<p><code>refetch(component)</code> returns a <code>Promise<ApiResult<T> | undefined></code> that resolves
|
|
65
|
+
after the GET has completed.</p>
|
|
66
|
+
<h3 id="from-a-method-decorator">From a method decorator</h3>
|
|
67
|
+
<p>The refetch can decorate a local method. The default is <code>after</code>; if the
|
|
68
|
+
method returns a Promise, the GET waits for its resolution. The decorated method
|
|
69
|
+
call also waits for the refetch to complete.</p>
|
|
70
|
+
<pre><code class="language-typescript">import { refetch } from "@supersoniks/concorde/decorators";
|
|
71
|
+
|
|
72
|
+
@refetch(usersGet)
|
|
73
|
+
async reload() {
|
|
74
|
+
this.userId = "42";
|
|
75
|
+
}
|
|
76
|
+
</code></pre>
|
|
77
|
+
<p>Use <code>{ when: "before" }</code> when the GET must complete before the method runs:</p>
|
|
78
|
+
<pre><code class="language-typescript">@refetch(usersGet, { when: "before" })
|
|
79
|
+
reloadBefore() {
|
|
80
|
+
// The refetch has completed before this method runs.
|
|
81
|
+
}
|
|
82
|
+
</code></pre>
|
|
83
|
+
<p>The method decorator adds an explicit trigger; changes to dynamic endpoint
|
|
84
|
+
properties and configuration publishers keep their existing automatic behavior.</p>
|
|
85
|
+
<h2 id="options-getoptions">Options (<code>GetOptions</code>)</h2>
|
|
86
|
+
<p>Options are the second argument, or the third argument when an API
|
|
87
|
+
configuration key is provided.</p>
|
|
88
|
+
<ul>
|
|
89
|
+
<li><code>skipEmptyPlaceholder</code>: blocks the GET when <code>${prop}</code> is <code>""</code>.</li>
|
|
90
|
+
<li><code>refetchEveryMs</code>: automatically runs the GET again after this interval
|
|
91
|
+
(milliseconds). Omit the option, or use <code>0</code>, to disable polling.</li>
|
|
92
|
+
<li><code>triggerKey</code>: a publisher whose <code>invalidate()</code> runs the GET again.</li>
|
|
93
|
+
</ul>
|
|
94
|
+
<p>With a configuration key, use:</p>
|
|
95
|
+
<pre><code class="language-typescript">@get(usersEndpoint, apiConfigurationKey)
|
|
73
96
|
</code></pre>
|
|
74
|
-
<p>Prefer <code>triggerKey</code> over mutating the API configuration publisher when you only want to <strong>reload the same URL</strong> — no need to touch <code>serviceURL</code>, tokens, etc.</p>
|
|
75
|
-
<p>The docs mock adds an <strong><code>X-Fetched-At</code></strong> response header on <code>/docs-mock-api/geo/communes</code> so live demos can show when the last fetch happened (<code>response.headers.get("X-Fetched-At")</code>).</p>
|
|
76
97
|
<h2 id="when-the-get-runs-again">When the GET runs again</h2>
|
|
77
98
|
<ul>
|
|
78
|
-
<li>
|
|
79
|
-
<li
|
|
80
|
-
<li
|
|
81
|
-
<li
|
|
99
|
+
<li>when the component connects and configuration is available;</li>
|
|
100
|
+
<li>when a property used in <code>${...}</code> changes;</li>
|
|
101
|
+
<li>when a configuration publisher changes;</li>
|
|
102
|
+
<li>when the <code>triggerKey</code> publisher is invalidated;</li>
|
|
103
|
+
<li>after each response when <code>refetchEveryMs</code> is set.</li>
|
|
82
104
|
</ul>
|
|
105
|
+
<p>See <a href="../_misc/dynamic-path.html#dynamic-path">Dynamic path placeholders</a> for
|
|
106
|
+
dynamic path details.</p>
|
|
83
107
|
<h2 id="import">Import</h2>
|
|
84
108
|
<pre><code class="language-typescript">import { get, type ApiResult } from "@supersoniks/concorde/decorators";
|
|
85
|
-
import { Endpoint } from "@supersoniks/concorde/utils/endpoint";
|
|
86
109
|
import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
|
|
110
|
+
import { Endpoint } from "@supersoniks/concorde/utils/endpoint";
|
|
87
111
|
</code></pre>
|
|
88
|
-
<h2 id="
|
|
89
|
-
<p>Same demo service as <a href="../../core/components/functional/queue/queue.demo.ts"><code>sonic-queue</code></a> (<code>/docs-mock-api/geo/</code>). Publisher setup lives in <code>decorators-demo-geo.ts</code> and <code>decorators-demo-subscribe-publish-get-demos.ts</code>.</p>
|
|
90
|
-
<pre><code class="language-typescript">@get(new Endpoint<User>("users/${userId}"))
|
|
91
|
-
@state()
|
|
92
|
-
payload: ApiResult<User> | null = null;
|
|
93
|
-
</code></pre>
|
|
94
|
-
<h2 id="live-demos">Live demos</h2>
|
|
95
|
-
<p><code>@get</code> with <strong><code>triggerKey</code></strong> — refresh button + <code>X-Fetched-At</code> timestamp in the UI:</p>
|
|
112
|
+
<h2 id="demos">Demos</h2>
|
|
96
113
|
<pre><code><docs-demo-sources for="demo-api-get"></docs-demo-sources>
|
|
97
114
|
<demo-api-get></demo-api-get>
|
|
98
|
-
|
|
99
|
-
<p>Dynamic config and endpoint path. Manual refetch is triggered <strong>from a separate component</strong> (same <code>triggerKey</code> publisher):</p>
|
|
100
|
-
<pre><code><docs-demo-sources for="demo-api-get-configuration-key"></docs-demo-sources>
|
|
115
|
+
<docs-demo-sources for="demo-api-get-configuration-key"></docs-demo-sources>
|
|
101
116
|
<demo-api-get-configuration-key></demo-api-get-configuration-key>
|
|
102
|
-
<demo-api-get-refresh-remote></demo-api-get-refresh-remote>
|
|
103
117
|
</code></pre>
|
|
104
|
-
<p>
|
|
105
|
-
<
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
<p>Stale responses are ignored if the path or generation changed before the request finished.</p>
|
|
111
|
-
<h2 id="see-also">See also</h2>
|
|
112
|
-
<ul>
|
|
113
|
-
<li><a href="../_misc/dynamic-path.html#dynamic-path">Dynamic path placeholders</a></li>
|
|
114
|
-
<li><a href="./post.html#post">@post</a> · <a href="./put.html#put">@put</a> · <a href="./patch.html#patch">@patch</a> — send decorators (same path rules)</li>
|
|
115
|
-
</ul>
|
|
118
|
+
<p>See <a href="./post.html#post">@post</a>,
|
|
119
|
+
<a href="./put.html#put">@put</a>, and
|
|
120
|
+
<a href="./patch.html#patch">@patch</a> for write operations.</p>
|
|
121
|
+
<h2 id="advanced">Advanced</h2>
|
|
122
|
+
<p>External invalidation is currently available through <code>triggerKey</code>; it is kept
|
|
123
|
+
out of the main usage examples.</p>
|
|
116
124
|
|
|
117
125
|
</article>
|
|
118
126
|
</main>
|
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>@patch — Concorde</title>
|
|
7
|
-
<meta name="description" content="
|
|
8
|
-
<meta name="keywords" content="Concorde, supersoniks, docs/_decorators/patch, patch, @patch, decorator,
|
|
7
|
+
<meta name="description" content="@patch applies a partial update with the body from a publisher. It uses the">
|
|
8
|
+
<meta name="keywords" content="Concorde, supersoniks, docs/_decorators/patch, patch, @patch, decorator, Endpoint, DataProviderKey, ApiResult, send(component),
|
|
9
|
+
|
|
10
|
+
, when: "before", autoPostOnBodyMutation: false, autoPostOnBodyMutation, skipIfBodyMissing">
|
|
9
11
|
<meta name="concorde-doc-id" content="docs/_decorators/patch">
|
|
10
12
|
<link rel="canonical" href="https://concorde.supersoniks.org/crawl/docs/_decorators/patch.html">
|
|
11
13
|
</head>
|
|
@@ -15,34 +17,52 @@
|
|
|
15
17
|
</header>
|
|
16
18
|
<main>
|
|
17
19
|
<article>
|
|
18
|
-
<p class="doc-lead" id="doc-summary"><strong>Concorde decorator — @patch</strong>.
|
|
20
|
+
<p class="doc-lead" id="doc-summary"><strong>Concorde decorator — @patch</strong>. @patch applies a partial update with the body from a publisher. It uses the <span>Doc ID: <code>docs/_decorators/patch</code>. Keywords: Concorde, supersoniks, docs/_decorators/patch, patch, @patch, decorator, Endpoint, DataProviderKey, ApiResult, send(component),
|
|
21
|
+
|
|
22
|
+
, when: "before", autoPostOnBodyMutation: false, autoPostOnBodyMutation, skipIfBodyMissing. URL: <a href="https://concorde.supersoniks.org/crawl/docs/_decorators/patch.html">https://concorde.supersoniks.org/crawl/docs/_decorators/patch.html</a>.</span></p>
|
|
19
23
|
<h1 id="patch">@patch</h1>
|
|
20
|
-
<p
|
|
21
|
-
|
|
22
|
-
<
|
|
23
|
-
<
|
|
24
|
-
<h2 id="
|
|
25
|
-
<
|
|
24
|
+
<p><code>@patch</code> applies a partial update with the body from a publisher. It uses the
|
|
25
|
+
same model as <a href="./post.html#post">@post</a>:
|
|
26
|
+
<code>Endpoint<T></code>, <code>DataProviderKey<B></code>, <code>ApiResult<T></code>, options, and the
|
|
27
|
+
<code>send(component)</code> handle.</p>
|
|
28
|
+
<h2 id="minimal-usage">Minimal usage</h2>
|
|
29
|
+
<pre><code class="language-typescript">const bodyKey = new DataProviderKey<Partial<User>>("users.patch");
|
|
30
|
+
const patchUser = patch(new Endpoint<User>("users/42"), bodyKey);
|
|
31
|
+
|
|
32
|
+
@patchUser
|
|
33
|
+
@state()
|
|
34
|
+
payload?: ApiResult<User>;
|
|
35
|
+
</code></pre>
|
|
36
|
+
<p>To run the operation again from the component:</p>
|
|
37
|
+
<pre><code class="language-typescript">async savePatch() {
|
|
38
|
+
await patchUser.send(this);
|
|
39
|
+
}
|
|
40
|
+
</code></pre>
|
|
41
|
+
<p><code>send(component)</code> returns a Promise resolved after the PATCH completes. See
|
|
42
|
+
<a href="./post.html#post">@post</a> for the method-decorator form and the
|
|
43
|
+
<code>when: "before"</code> option.</p>
|
|
44
|
+
<p>The PATCH is also sent automatically when the body mutates, unless
|
|
45
|
+
<code>autoPostOnBodyMutation: false</code> is set. The available options are described in
|
|
46
|
+
<a href="./post.html#post">@post</a>:</p>
|
|
47
|
+
<ul>
|
|
48
|
+
<li><code>autoPostOnBodyMutation</code></li>
|
|
49
|
+
<li><code>skipIfBodyMissing</code></li>
|
|
50
|
+
<li><code>refetchEveryMs</code></li>
|
|
51
|
+
<li><code>skipEmptyPlaceholder</code></li>
|
|
52
|
+
<li><code>triggerKey</code></li>
|
|
53
|
+
</ul>
|
|
54
|
+
<p>Pass explicit API configuration as the third argument:</p>
|
|
55
|
+
<pre><code class="language-typescript">@patch(endpoint, bodyKey, apiConfigurationKey)
|
|
56
|
+
</code></pre>
|
|
26
57
|
<h2 id="import">Import</h2>
|
|
27
58
|
<pre><code class="language-typescript">import { patch, type ApiResult } from "@supersoniks/concorde/decorators";
|
|
28
|
-
import { Endpoint } from "@supersoniks/concorde/utils/endpoint";
|
|
29
59
|
import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
|
|
30
|
-
|
|
31
|
-
<h2 id="example">Example</h2>
|
|
32
|
-
<pre><code class="language-typescript">const patchBodyKey = new DataProviderKey&lt;Partial&lt;Resource&gt;&gt;("resourcePatch");
|
|
33
|
-
|
|
34
|
-
@patch(
|
|
35
|
-
new Endpoint&lt;Resource, { resourceId: string }&gt;("resources/${resourceId}"),
|
|
36
|
-
patchBodyKey,
|
|
37
|
-
{ skipEmptyPlaceholder: true },
|
|
38
|
-
)
|
|
39
|
-
@state()
|
|
40
|
-
payload?: ApiResult&lt;Resource&gt; | null;
|
|
60
|
+
import { Endpoint } from "@supersoniks/concorde/utils/endpoint";
|
|
41
61
|
</code></pre>
|
|
42
62
|
<h2 id="see-also">See also</h2>
|
|
43
63
|
<ul>
|
|
44
|
-
<li><a href="./post.html#post">@post</a> —
|
|
45
|
-
<li><a href="./put.html#put">@put</a> — full replacement
|
|
64
|
+
<li><a href="./post.html#post">@post</a> — options and triggers</li>
|
|
65
|
+
<li><a href="./put.html#put">@put</a> — full replacement</li>
|
|
46
66
|
<li><a href="../_misc/dynamic-path.html#dynamic-path">Dynamic path placeholders</a></li>
|
|
47
67
|
</ul>
|
|
48
68
|
|
|
@@ -4,8 +4,14 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>@post — Concorde</title>
|
|
7
|
-
<meta name="description" content="
|
|
8
|
-
<meta name="keywords" content="Concorde, supersoniks, docs/_decorators/post, post, @post, decorator,
|
|
7
|
+
<meta name="description" content="@post sends the contents of a publisher and stores the response in an">
|
|
8
|
+
<meta name="keywords" content="Concorde, supersoniks, docs/_decorators/post, post, @post, decorator, ApiResult, undefined, Endpoint, DataProviderKey,
|
|
9
|
+
|
|
10
|
+
The current body is read from , send(component),
|
|
11
|
+
|
|
12
|
+
, returns a ,
|
|
13
|
+
|
|
14
|
+
Use ">
|
|
9
15
|
<meta name="concorde-doc-id" content="docs/_decorators/post">
|
|
10
16
|
<link rel="canonical" href="https://concorde.supersoniks.org/crawl/docs/_decorators/post.html">
|
|
11
17
|
</head>
|
|
@@ -15,86 +21,109 @@
|
|
|
15
21
|
</header>
|
|
16
22
|
<main>
|
|
17
23
|
<article>
|
|
18
|
-
<p class="doc-lead" id="doc-summary"><strong>Concorde decorator — @post</strong>.
|
|
24
|
+
<p class="doc-lead" id="doc-summary"><strong>Concorde decorator — @post</strong>. @post sends the contents of a publisher and stores the response in an <span>Doc ID: <code>docs/_decorators/post</code>. Keywords: Concorde, supersoniks, docs/_decorators/post, post, @post, decorator, ApiResult, undefined, Endpoint, DataProviderKey,
|
|
25
|
+
|
|
26
|
+
The current body is read from , send(component),
|
|
27
|
+
|
|
28
|
+
, returns a ,
|
|
29
|
+
|
|
30
|
+
Use . URL: <a href="https://concorde.supersoniks.org/crawl/docs/_decorators/post.html">https://concorde.supersoniks.org/crawl/docs/_decorators/post.html</a>.</span></p>
|
|
19
31
|
<h1 id="post">@post</h1>
|
|
20
|
-
<p
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
<
|
|
24
|
-
<
|
|
25
|
-
<
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
</
|
|
32
|
-
<
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
<
|
|
37
|
-
<
|
|
38
|
-
<
|
|
39
|
-
</
|
|
40
|
-
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
<
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
<
|
|
32
|
+
<p><code>@post</code> sends the contents of a publisher and stores the response in an
|
|
33
|
+
optional <code>ApiResult<T></code> property. The property is <code>undefined</code> until a result
|
|
34
|
+
is available.</p>
|
|
35
|
+
<h2 id="minimal-usage">Minimal usage</h2>
|
|
36
|
+
<p>Pass an <code>Endpoint<T></code> and a <code>DataProviderKey<B></code> for the request body.</p>
|
|
37
|
+
<pre><code class="language-typescript">const userBodyKey = new DataProviderKey<CreateUser>("users.form");
|
|
38
|
+
const createUser = post(new Endpoint<User>("users"), userBodyKey);
|
|
39
|
+
|
|
40
|
+
@createUser
|
|
41
|
+
@state()
|
|
42
|
+
payload?: ApiResult<User>;
|
|
43
|
+
</code></pre>
|
|
44
|
+
<p>The current body is read from <code>userBodyKey</code>. By default, the POST is sent when
|
|
45
|
+
the component connects and after each body mutation. Mutations in the same
|
|
46
|
+
frame are coalesced into one request.</p>
|
|
47
|
+
<p>API configuration is read from the HTML scope, as with
|
|
48
|
+
<a href="./get.html#get">@get</a>.</p>
|
|
49
|
+
<h2 id="sending-the-post-again">Sending the POST again</h2>
|
|
50
|
+
<h3 id="from-the-component">From the component</h3>
|
|
51
|
+
<p>Keep the decorator to access <code>send(component)</code>. The body is read again when the
|
|
52
|
+
operation runs.</p>
|
|
53
|
+
<pre><code class="language-typescript">async saveAgain() {
|
|
54
|
+
const payload = await createUser.send(this);
|
|
55
|
+
console.log(payload?.result);
|
|
56
|
+
}
|
|
57
|
+
</code></pre>
|
|
58
|
+
<p><code>send()</code> returns a <code>Promise<ApiResult<T> | undefined></code> that resolves after the
|
|
59
|
+
operation completes. It is useful for “Save” or “Retry” buttons and can repeat
|
|
60
|
+
an operation with side effects.</p>
|
|
61
|
+
<h3 id="from-a-method-decorator">From a method decorator</h3>
|
|
62
|
+
<p>The send action can decorate a local method. It runs after the method by
|
|
63
|
+
default, waits for an eventual Promise to resolve, and the decorated method
|
|
64
|
+
call waits for the send to complete:</p>
|
|
65
|
+
<pre><code class="language-typescript">import { send } from "@supersoniks/concorde/decorators";
|
|
66
|
+
|
|
67
|
+
@send(createUser)
|
|
68
|
+
async save() {
|
|
69
|
+
// Prepare local state or validate the form.
|
|
70
|
+
}
|
|
71
|
+
</code></pre>
|
|
72
|
+
<p>Use <code>{ when: "before" }</code> when the send must complete before the method runs:</p>
|
|
73
|
+
<pre><code class="language-typescript">@send(createUser, { when: "before" })
|
|
74
|
+
saveBefore() {
|
|
75
|
+
// The POST has completed before this method runs.
|
|
76
|
+
}
|
|
77
|
+
</code></pre>
|
|
78
|
+
<p>The method decorator adds an explicit send. If the method also mutates the body
|
|
79
|
+
publisher, set <code>autoPostOnBodyMutation: false</code> when the decorated method must
|
|
80
|
+
be the only trigger.</p>
|
|
81
|
+
<h2 id="options-postoptions">Options (<code>PostOptions</code>)</h2>
|
|
82
|
+
<p>Options are the third argument, or the fourth argument when a configuration key
|
|
83
|
+
is provided.</p>
|
|
54
84
|
<ul>
|
|
55
|
-
<li
|
|
56
|
-
|
|
57
|
-
<li>
|
|
58
|
-
<
|
|
59
|
-
<li><code>refetchEveryMs</code
|
|
85
|
+
<li><code>autoPostOnBodyMutation</code>: send after a body mutation (default: <code>true</code>). Set
|
|
86
|
+
it to <code>false</code> to use <code>send()</code>.</li>
|
|
87
|
+
<li><code>skipIfBodyMissing</code>: skip when the body is <code>null</code> or <code>undefined</code> (default:
|
|
88
|
+
<code>true</code>).</li>
|
|
89
|
+
<li><code>refetchEveryMs</code>: repeat the POST at this interval. Use it only when
|
|
90
|
+
repeating the operation is intended.</li>
|
|
91
|
+
<li><code>skipEmptyPlaceholder</code>: block the request when a <code>${...}</code> placeholder is
|
|
92
|
+
<code>""</code>.</li>
|
|
93
|
+
<li><code>triggerKey</code>: a publisher whose <code>invalidate()</code> sends the POST again.</li>
|
|
94
|
+
</ul>
|
|
95
|
+
<p>With a configuration key:</p>
|
|
96
|
+
<pre><code class="language-typescript">@post(endpoint, userBodyKey, apiConfigurationKey)
|
|
97
|
+
</code></pre>
|
|
98
|
+
<p>See <a href="../_misc/dynamic-path.html#dynamic-path">Dynamic path placeholders</a> for
|
|
99
|
+
dynamic path details.</p>
|
|
100
|
+
<h2 id="when-the-post-is-sent">When the POST is sent</h2>
|
|
101
|
+
<ul>
|
|
102
|
+
<li>when the component connects and the body and configuration are available;</li>
|
|
103
|
+
<li>after a body mutation, unless <code>autoPostOnBodyMutation: false</code>;</li>
|
|
104
|
+
<li>when a property used in <code>${...}</code> changes;</li>
|
|
105
|
+
<li>when a configuration publisher changes;</li>
|
|
106
|
+
<li>when the <code>triggerKey</code> publisher is invalidated;</li>
|
|
107
|
+
<li>when <code>send()</code> is called;</li>
|
|
108
|
+
<li>after each response when <code>refetchEveryMs</code> is set.</li>
|
|
60
109
|
</ul>
|
|
61
110
|
<h2 id="import">Import</h2>
|
|
62
|
-
<pre><code class="language-typescript">import { post,
|
|
63
|
-
import { Endpoint } from "@supersoniks/concorde/utils/endpoint";
|
|
111
|
+
<pre><code class="language-typescript">import { post, type ApiResult } from "@supersoniks/concorde/decorators";
|
|
64
112
|
import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
|
|
113
|
+
import { Endpoint } from "@supersoniks/concorde/utils/endpoint";
|
|
65
114
|
</code></pre>
|
|
66
|
-
<h2 id="
|
|
67
|
-
<p>Mock service: <code>POST /docs-mock-api/api/register</code> (same route as <a href="../../core/components/functional/submit/submit.html#submit"><code>sonic-submit</code></a> demos). Publisher setup lives in <code>decorators-demo-post.ts</code>.</p>
|
|
68
|
-
<pre><code class="language-typescript">const syncRequest = new DataProviderKey&lt;SyncRequest&gt;("syncRequest");
|
|
69
|
-
const syncTrigger = new DataProviderKey&lt;number&gt;("syncTrigger");
|
|
70
|
-
|
|
71
|
-
@post(
|
|
72
|
-
new Endpoint&lt;SyncResponse, { sessionId: string }&gt;("sessions/${sessionId}/sync"),
|
|
73
|
-
syncRequest,
|
|
74
|
-
{ triggerKey: syncTrigger },
|
|
75
|
-
)
|
|
76
|
-
@state()
|
|
77
|
-
payload?: ApiResult&lt;SyncResponse&gt; | null;
|
|
78
|
-
</code></pre>
|
|
79
|
-
<h2 id="live-demos">Live demos</h2>
|
|
115
|
+
<h2 id="demos">Demos</h2>
|
|
80
116
|
<pre><code><docs-demo-sources for="demo-api-post"></docs-demo-sources>
|
|
81
117
|
<demo-api-post></demo-api-post>
|
|
82
|
-
|
|
83
|
-
<p>Dynamic endpoint path — changing <code>sessionId</code> on the host re-runs the POST (<code>POST /docs-mock-api/api/sessions/{id}/sync</code>):</p>
|
|
84
|
-
<pre><code><docs-demo-sources for="demo-api-post-dynamic"></docs-demo-sources>
|
|
118
|
+
<docs-demo-sources for="demo-api-post-dynamic"></docs-demo-sources>
|
|
85
119
|
<demo-api-post-dynamic></demo-api-post-dynamic>
|
|
86
120
|
</code></pre>
|
|
87
|
-
<p
|
|
88
|
-
<
|
|
89
|
-
|
|
90
|
-
</
|
|
91
|
-
<p>
|
|
92
|
-
|
|
93
|
-
<p>Path placeholders (<code>${sessionId}</code>, …): <a href="../_misc/dynamic-path.html#dynamic-path">Dynamic path placeholders</a>.</p>
|
|
94
|
-
<h2 id="see-also">See also</h2>
|
|
95
|
-
<ul>
|
|
96
|
-
<li><a href="./put.html#put">@put</a> · <a href="./patch.html#patch">@patch</a> — same decorator model, <code>PUT</code> / <code>PATCH</code> via <code>putDetailed</code> / <code>patchDetailed</code></li>
|
|
97
|
-
</ul>
|
|
121
|
+
<p>See <a href="./put.html#put">@put</a> and
|
|
122
|
+
<a href="./patch.html#patch">@patch</a>: they use the same model with a
|
|
123
|
+
different HTTP method.</p>
|
|
124
|
+
<h2 id="advanced">Advanced</h2>
|
|
125
|
+
<p>External invalidation is currently available through <code>triggerKey</code>; it is kept
|
|
126
|
+
out of the main usage examples.</p>
|
|
98
127
|
|
|
99
128
|
</article>
|
|
100
129
|
</main>
|