Concorde decorator — @post. Sends data through API.postDetailed. The decorated property is ApiResult<T> | null: request, response, and typed result. Doc ID: docs/_decorators/post. Keywords: Concorde, supersoniks, docs/_decorators/post, post, @post, decorator, API.postDetailed, ApiResult | null, request, response, result, Endpoint, DataProviderKey, ApiResult, @supersoniks/concorde/decorators. URL: https://concorde.supersoniks.org/crawl/docs/_decorators/post.html.
@post
Sends data through API.postDetailed. The decorated property is ApiResult<T> | null: request, response, and typed result.
Pass an Endpoint<T> as the first argument and a DataProviderKey for the request body as the second. Import post and ApiResult from @supersoniks/concorde/decorators, and Endpoint from @supersoniks/concorde/utils/endpoint.
Configuration
Same as @get: scoped HTML.getApiConfiguration(host) by default, or DataProviderKey<APIConfiguration> as third argument. See API configuration for mock demos.
Optional PostOptions (third or fourth argument)
| Option | Description |
|---|---|
refetchEveryMs |
Re-post on an interval (ms). |
skipIfBodyMissing |
Skip when body publisher is null/undefined (default: true). |
autoPostOnBodyMutation |
Re-post when the body publisher mutates (default: true). false = manual via triggerKey.invalidate(). |
skipEmptyPlaceholder |
If true, a placeholder resolved to '' blocks the request (empty string only — not 0 or false). See Dynamic paths. |
triggerKey |
DataProviderKey — invalidate() re-runs the POST with the current body. |
When the POST runs again
- Body publisher
onInternalMutationwhenautoPostOnBodyMutationistrue(default). Plusieurs mutations synchrones dans la même frame sont regroupées en un seul POST viarequestAnimationFrame. - Endpoint path dependency changes (
${sessionId}on the host). - Configuration publisher mutation.
triggerKeypublisherinvalidate().refetchEveryMstimer (if set).
Import
import { post, publish, type ApiResult } from "@supersoniks/concorde/decorators";
import { Endpoint } from "@supersoniks/concorde/utils/endpoint";
import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
Minimal example
Mock service: POST /docs-mock-api/api/register (same route as sonic-submit demos). Publisher setup lives in decorators-demo-post.ts.
const syncRequest = new DataProviderKey<SyncRequest>("syncRequest");
const syncTrigger = new DataProviderKey<number>("syncTrigger");
@post(
new Endpoint<SyncResponse, { sessionId: string }>("sessions/${sessionId}/sync"),
syncRequest,
{ triggerKey: syncTrigger },
)
@state()
payload?: ApiResult<SyncResponse> | null;
Live demos
<docs-demo-sources for="demo-api-post"></docs-demo-sources>
<demo-api-post></demo-api-post>
Dynamic endpoint path — changing sessionId on the host re-runs the POST (POST /docs-mock-api/api/sessions/{id}/sync):
<docs-demo-sources for="demo-api-post-dynamic"></docs-demo-sources>
<demo-api-post-dynamic></demo-api-post-dynamic>
@post + @publish on the same property (see @publish):
<docs-demo-sources for="demo-api-post-publish"></docs-demo-sources>
<demo-api-post-publish></demo-api-post-publish>
Stale responses are ignored if the path or generation changed before the request finished.
Note: plusieurs composants @post sur la même page qui partagent le même bodyKey enverront chacun une requête à chaque mutation du body — utiliser une clé par composant (voir les deux démos live ci-dessus).
Path placeholders (${sessionId}, …): Dynamic path placeholders.