@supersoniks/concorde 4.9.7 → 4.9.91
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 +265 -265
- package/concorde-core.es.js +4600 -4385
- package/dist/concorde-core.bundle.js +265 -265
- package/dist/concorde-core.es.js +4600 -4385
- package/dist/js/core/components/functional/queue/queue.js +25 -153
- package/dist/js/core/components/functional/queue/queue.js.map +1 -1
- package/dist/js/core/components/ui/_css/scroll.js +2 -0
- package/dist/js/core/components/ui/_css/scroll.js.map +1 -1
- package/dist/js/core/decorators/api.js +92 -2
- package/dist/js/core/decorators/api.js.map +1 -1
- package/dist/js/core/utils/SafariScrollGuard.js +384 -0
- package/dist/js/core/utils/SafariScrollGuard.js.map +1 -0
- package/dist/js/decorators.js +4 -0
- package/dist/js/decorators.js.map +1 -1
- package/dist/js/utils.js +3 -0
- package/dist/js/utils.js.map +1 -1
- package/dist/types/core/components/functional/queue/queue.d.ts +8 -24
- package/dist/types/core/components/functional/queue/queue.d.ts.map +1 -1
- package/dist/types/core/components/ui/_css/scroll.d.ts.map +1 -1
- package/dist/types/core/decorators/api.d.ts +82 -60
- package/dist/types/core/decorators/api.d.ts.map +1 -1
- package/dist/types/core/utils/SafariScrollGuard.d.ts +36 -0
- package/dist/types/core/utils/SafariScrollGuard.d.ts.map +1 -0
- package/dist/types/decorators.d.ts +3 -1
- package/dist/types/decorators.d.ts.map +1 -1
- package/dist/types/utils.d.ts +1 -0
- package/dist/types/utils.d.ts.map +1 -1
- package/docs/assets/index-BL6WVF7g.css +1 -0
- package/docs/assets/{index-hElUgV9_.js → index-DVn8AeyA.js} +572 -555
- package/docs/crawl/docs/_decorators/get.html +64 -81
- package/docs/crawl/docs/_decorators/patch.html +35 -23
- package/docs/crawl/docs/_decorators/post.html +72 -72
- package/docs/crawl/docs/_decorators/put.html +36 -21
- package/docs/crawl/docs/_getting-started/ai-agents.html +45 -6
- package/docs/crawl/hubs/decorators.html +141 -69
- package/docs/crawl/hubs/remote-data.html +141 -69
- package/docs/index.html +2 -2
- package/docs/llms-full.txt +203 -149
- 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 +55 -81
- package/docs/src/docs/_decorators/patch.md +36 -25
- package/docs/src/docs/_decorators/post.md +71 -62
- package/docs/src/docs/_decorators/put.md +37 -24
- package/docs/src/docs/_getting-started/ai-agents.md +24 -4
- package/docs/src/docs/search/docs-search.json +151 -1
- package/docs/src/tsconfig.json +3 -0
- package/package.json +6 -2
- package/src/core/components/functional/queue/queue.ts +33 -164
- package/src/core/components/ui/_css/scroll.ts +3 -0
- package/src/core/decorators/api.post.spec.ts +79 -1
- package/src/core/decorators/api.spec.ts +100 -1
- package/src/core/decorators/api.ts +252 -138
- package/src/core/utils/SafariScrollGuard.ts +429 -0
- package/src/decorators.ts +7 -0
- package/src/docs/_decorators/get.md +81 -80
- package/src/docs/_decorators/patch.md +36 -25
- package/src/docs/_decorators/post.md +99 -62
- package/src/docs/_decorators/put.md +37 -24
- package/src/docs/components/docs-demo-sources.ts +1 -6
- package/src/docs/example/decorators-demo-geo.ts +0 -21
- package/src/docs/example/decorators-demo-subscribe-publish-get-demos.ts +41 -132
- package/src/docs/search/docs-search.json +156 -241
- package/src/docs/tailwind/css/tailwind.css +0 -0
- package/src/tsconfig.json +3 -0
- package/src/tsconfig.tsbuildinfo +1 -1
- package/src/utils.ts +13 -0
- package/vite.config.mts +4 -0
- package/vitest.setup.ts +22 -0
- package/docs/assets/index-Bnp7gVaA.css +0 -1
|
@@ -1,123 +1,97 @@
|
|
|
1
1
|
# @get
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`@get` loads data and stores the result in an `ApiResult<T> | null` property.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
- `payload.result`: typed data;
|
|
6
|
+
- `payload.response`: the HTTP response;
|
|
7
|
+
- `payload.request`: the request that was sent.
|
|
6
8
|
|
|
7
|
-
##
|
|
9
|
+
## Minimal usage
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
## Dynamic path
|
|
13
|
-
|
|
14
|
-
`${prop}` on the endpoint or config key is resolved on the host. While a placeholder is `null` or `undefined`, no GET runs. Optional `skipEmptyPlaceholder: true` also blocks `""` (empty string only). Details: [Dynamic path placeholders](#docs/_misc/dynamic-path.md/dynamic-path).
|
|
11
|
+
```typescript
|
|
12
|
+
const usersEndpoint = new Endpoint<User[]>("users");
|
|
15
13
|
|
|
16
|
-
|
|
14
|
+
@get(usersEndpoint)
|
|
15
|
+
@state()
|
|
16
|
+
payload: ApiResult<User[]> | null = null;
|
|
17
|
+
```
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
The first argument is always an
|
|
20
|
+
[`Endpoint<T>`](#docs/_misc/endpoint.md/endpoint). API configuration is read
|
|
21
|
+
from the HTML scope (`serviceURL`, token, etc.), so the component is usually
|
|
22
|
+
placed below an element that provides this configuration.
|
|
19
23
|
|
|
20
|
-
|
|
21
|
-
|--------|-------------|
|
|
22
|
-
| `skipEmptyPlaceholder` | Treat `""` as not ready (see [Dynamic path](#docs/_misc/dynamic-path.md/dynamic-path)). |
|
|
23
|
-
| `refetchEveryMs` | Automatic polling interval (ms). `0` or omitted = no polling. |
|
|
24
|
-
| `triggerKey` | `DataProviderKey` — `PublisherManager.get(...).invalidate()` on that publisher re-runs the GET. |
|
|
24
|
+
## Refetching a GET
|
|
25
25
|
|
|
26
|
-
###
|
|
26
|
+
### From the component
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
Keep the decorator in a constant to access `refetch(component)`. Refetch only
|
|
29
|
+
targets the instance passed as the argument, even before it has received a
|
|
30
|
+
result.
|
|
29
31
|
|
|
30
32
|
```typescript
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
import { dp } from "@supersoniks/concorde/core/utils/PublisherProxy";
|
|
35
|
-
|
|
36
|
-
const geoCommunesEndpoint = new Endpoint<GeoCommuneRow[]>(
|
|
37
|
-
"communes?limit=5&fields=nom,code",
|
|
38
|
-
);
|
|
39
|
-
const geoCommunesRefreshKey = new DataProviderKey<void>(
|
|
40
|
-
"docsDemoGeoCommunesRefresh",
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
@get(geoCommunesEndpoint, apiConfigurationKey, {
|
|
44
|
-
triggerKey: geoCommunesRefreshKey,
|
|
45
|
-
})
|
|
33
|
+
const usersGet = get(new Endpoint<User[]>("users"));
|
|
34
|
+
|
|
35
|
+
@usersGet
|
|
46
36
|
@state()
|
|
47
|
-
payload: ApiResult<
|
|
37
|
+
payload: ApiResult<User[]> | null = null;
|
|
48
38
|
|
|
49
|
-
|
|
50
|
-
|
|
39
|
+
refresh() {
|
|
40
|
+
usersGet.refetch(this);
|
|
41
|
+
}
|
|
51
42
|
```
|
|
52
43
|
|
|
53
|
-
|
|
44
|
+
## Options (`GetOptions`)
|
|
45
|
+
|
|
46
|
+
Options are the second argument, or the third argument when an API
|
|
47
|
+
configuration key is provided.
|
|
48
|
+
|
|
49
|
+
- `skipEmptyPlaceholder`: blocks the GET when `${prop}` is `""`.
|
|
50
|
+
- `refetchEveryMs`: automatically runs the GET again after this interval
|
|
51
|
+
(milliseconds). Omit the option, or use `0`, to disable polling.
|
|
54
52
|
|
|
55
|
-
|
|
53
|
+
With a configuration key, use:
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
@get(usersEndpoint, apiConfigurationKey)
|
|
57
|
+
```
|
|
56
58
|
|
|
57
59
|
## When the GET runs again
|
|
58
60
|
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
-
|
|
62
|
-
- `refetchEveryMs`
|
|
61
|
+
- when the component connects and configuration is available;
|
|
62
|
+
- when a property used in `${...}` changes;
|
|
63
|
+
- when a configuration publisher changes;
|
|
64
|
+
- after each response when `refetchEveryMs` is set.
|
|
65
|
+
|
|
66
|
+
See [Dynamic path placeholders](#docs/_misc/dynamic-path.md/dynamic-path) for
|
|
67
|
+
dynamic path details.
|
|
63
68
|
|
|
64
69
|
## Import
|
|
65
70
|
|
|
66
71
|
<sonic-code language="typescript">
|
|
67
72
|
<template>
|
|
68
73
|
import { get, type ApiResult } from "@supersoniks/concorde/decorators";
|
|
69
|
-
import { Endpoint } from "@supersoniks/concorde/utils/endpoint";
|
|
70
74
|
import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
|
|
75
|
+
import { Endpoint } from "@supersoniks/concorde/utils/endpoint";
|
|
71
76
|
</template>
|
|
72
77
|
</sonic-code>
|
|
73
78
|
|
|
74
|
-
##
|
|
75
|
-
|
|
76
|
-
Same demo service as [`sonic-queue`](../../core/components/functional/queue/queue.demo.ts) (`/docs-mock-api/geo/`). Publisher setup lives in `decorators-demo-geo.ts` and `decorators-demo-subscribe-publish-get-demos.ts`.
|
|
77
|
-
|
|
78
|
-
<sonic-code language="typescript">
|
|
79
|
-
<template>
|
|
80
|
-
@get(new Endpoint<User>("users/${userId}"))
|
|
81
|
-
@state()
|
|
82
|
-
payload: ApiResult<User> | null = null;
|
|
83
|
-
</template>
|
|
84
|
-
</sonic-code>
|
|
85
|
-
|
|
86
|
-
## Live demos
|
|
87
|
-
|
|
88
|
-
`@get` with **`triggerKey`** — refresh button + `X-Fetched-At` timestamp in the UI:
|
|
79
|
+
## Demos
|
|
89
80
|
|
|
90
81
|
<sonic-code>
|
|
91
82
|
<template>
|
|
92
83
|
<docs-demo-sources for="demo-api-get"></docs-demo-sources>
|
|
93
84
|
<demo-api-get></demo-api-get>
|
|
94
|
-
</template>
|
|
95
|
-
</sonic-code>
|
|
96
|
-
|
|
97
|
-
Dynamic config and endpoint path. Manual refetch is triggered **from a separate component** (same `triggerKey` publisher):
|
|
98
|
-
|
|
99
|
-
<sonic-code>
|
|
100
|
-
<template>
|
|
101
85
|
<docs-demo-sources for="demo-api-get-configuration-key"></docs-demo-sources>
|
|
102
86
|
<demo-api-get-configuration-key></demo-api-get-configuration-key>
|
|
103
|
-
<demo-api-get-refresh-remote></demo-api-get-refresh-remote>
|
|
104
|
-
</template>
|
|
105
|
-
</sonic-code>
|
|
106
|
-
|
|
107
|
-
Scoped `@get` with `@publish` / `@subscribe` on the payload (see [@publish](#docs/_decorators/publish.md/publish) and [@subscribe](#docs/_decorators/subscribe.md/subscribe)) — wrap under an ancestor with `serviceURL="/docs-mock-api/geo/"`:
|
|
108
|
-
|
|
109
|
-
<sonic-code>
|
|
110
|
-
<template>
|
|
111
|
-
<div serviceURL="/docs-mock-api/geo/">
|
|
112
|
-
<docs-demo-sources for="demo-api-get-publish-subscribe"></docs-demo-sources>
|
|
113
|
-
<demo-api-get-publish-subscribe></demo-api-get-publish-subscribe>
|
|
114
|
-
</div>
|
|
115
87
|
</template>
|
|
116
88
|
</sonic-code>
|
|
117
89
|
|
|
118
|
-
|
|
90
|
+
See [@post](#docs/_decorators/post.md/post),
|
|
91
|
+
[@put](#docs/_decorators/put.md/put), and
|
|
92
|
+
[@patch](#docs/_decorators/patch.md/patch) for write operations.
|
|
119
93
|
|
|
120
|
-
##
|
|
94
|
+
## Advanced
|
|
121
95
|
|
|
122
|
-
|
|
123
|
-
|
|
96
|
+
External invalidation is currently available through `triggerKey`; it is kept
|
|
97
|
+
out of the main usage examples.
|
|
@@ -1,45 +1,56 @@
|
|
|
1
1
|
# @patch
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`@patch` applies a partial update with the body from a publisher. It uses the
|
|
4
|
+
same model as [@post](#docs/_decorators/post.md/post):
|
|
5
|
+
`Endpoint<T>`, `DataProviderKey<B>`, `ApiResult<T>`, options, and the
|
|
6
|
+
`send(component)` handle.
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
## Minimal usage
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
```typescript
|
|
11
|
+
const bodyKey = new DataProviderKey<Partial<User>>("users.patch");
|
|
12
|
+
const patchUser = patch(new Endpoint<User>("users/42"), bodyKey);
|
|
8
13
|
|
|
9
|
-
|
|
14
|
+
@patchUser
|
|
15
|
+
@state()
|
|
16
|
+
payload: ApiResult<User> | null = null;
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
To run the operation again from the component:
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
savePatch() {
|
|
23
|
+
patchUser.send(this);
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The PATCH is also sent automatically when the body mutates, unless
|
|
28
|
+
`autoPostOnBodyMutation: false` is set. The available options are described in
|
|
29
|
+
[@post](#docs/_decorators/post.md/post):
|
|
10
30
|
|
|
11
|
-
|
|
31
|
+
- `autoPostOnBodyMutation`
|
|
32
|
+
- `skipIfBodyMissing`
|
|
33
|
+
- `refetchEveryMs`
|
|
34
|
+
- `skipEmptyPlaceholder`
|
|
12
35
|
|
|
13
|
-
|
|
36
|
+
Pass explicit API configuration as the third argument:
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
@patch(endpoint, bodyKey, apiConfigurationKey)
|
|
40
|
+
```
|
|
14
41
|
|
|
15
42
|
## Import
|
|
16
43
|
|
|
17
44
|
<sonic-code language="typescript">
|
|
18
45
|
<template>
|
|
19
46
|
import { patch, type ApiResult } from "@supersoniks/concorde/decorators";
|
|
20
|
-
import { Endpoint } from "@supersoniks/concorde/utils/endpoint";
|
|
21
47
|
import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
|
|
22
|
-
|
|
23
|
-
</sonic-code>
|
|
24
|
-
|
|
25
|
-
## Example
|
|
26
|
-
|
|
27
|
-
<sonic-code language="typescript">
|
|
28
|
-
<template>
|
|
29
|
-
const patchBodyKey = new DataProviderKey<Partial<Resource>>("resourcePatch");
|
|
30
|
-
|
|
31
|
-
@patch(
|
|
32
|
-
new Endpoint<Resource, { resourceId: string }>("resources/${resourceId}"),
|
|
33
|
-
patchBodyKey,
|
|
34
|
-
{ skipEmptyPlaceholder: true },
|
|
35
|
-
)
|
|
36
|
-
@state()
|
|
37
|
-
payload?: ApiResult<Resource> | null;
|
|
48
|
+
import { Endpoint } from "@supersoniks/concorde/utils/endpoint";
|
|
38
49
|
</template>
|
|
39
50
|
</sonic-code>
|
|
40
51
|
|
|
41
52
|
## See also
|
|
42
53
|
|
|
43
|
-
- [@post](#docs/_decorators/post.md/post) —
|
|
44
|
-
- [@put](#docs/_decorators/put.md/put) — full replacement
|
|
54
|
+
- [@post](#docs/_decorators/post.md/post) — options and triggers
|
|
55
|
+
- [@put](#docs/_decorators/put.md/put) — full replacement
|
|
45
56
|
- [Dynamic path placeholders](#docs/_misc/dynamic-path.md/dynamic-path)
|
|
@@ -1,93 +1,102 @@
|
|
|
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
5
|
|
|
5
|
-
|
|
6
|
+
## Minimal usage
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
Pass an `Endpoint<T>` and a `DataProviderKey<B>` for the request body.
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
```typescript
|
|
11
|
+
const userBodyKey = new DataProviderKey<CreateUser>("users.form");
|
|
12
|
+
const createUser = post(new Endpoint<User>("users"), userBodyKey);
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
@createUser
|
|
15
|
+
@state()
|
|
16
|
+
payload: ApiResult<User> | null = null;
|
|
17
|
+
```
|
|
12
18
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
| `skipIfBodyMissing` | Skip when body publisher is `null`/`undefined` (default: `true`). |
|
|
17
|
-
| `autoPostOnBodyMutation` | Re-post when the body publisher mutates (default: `true`). `false` = manual via `triggerKey.invalidate()`. |
|
|
18
|
-
| `skipEmptyPlaceholder` | If `true`, a placeholder resolved to `''` blocks the request (empty string only — not `0` or `false`). See [Dynamic paths](#docs/_misc/dynamic-path.md/dynamic-path). |
|
|
19
|
-
| `triggerKey` | `DataProviderKey` — `invalidate()` re-runs the POST with the current body. |
|
|
19
|
+
The current body is read from `userBodyKey`. By default, the POST is sent when
|
|
20
|
+
the component connects and after each body mutation. Mutations in the same
|
|
21
|
+
frame are coalesced into one request.
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
API configuration is read from the HTML scope, as with
|
|
24
|
+
[@get](#docs/_decorators/get.md/get).
|
|
22
25
|
|
|
23
|
-
|
|
24
|
-
- Endpoint path dependency changes (`${sessionId}` on the host).
|
|
25
|
-
- Configuration publisher mutation.
|
|
26
|
-
- `triggerKey` publisher `invalidate()`.
|
|
27
|
-
- `refetchEveryMs` timer (if set).
|
|
26
|
+
## Sending the POST again
|
|
28
27
|
|
|
29
|
-
|
|
28
|
+
### From the component
|
|
30
29
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
Keep the decorator to access `send(component)`. The body is read again when the
|
|
31
|
+
operation runs.
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
saveAgain() {
|
|
35
|
+
createUser.send(this);
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
`send()` is useful for “Save” or “Retry” buttons. It can repeat an operation
|
|
40
|
+
with side effects.
|
|
40
41
|
|
|
41
|
-
|
|
42
|
+
## Options (`PostOptions`)
|
|
43
|
+
|
|
44
|
+
Options are the third argument, or the fourth argument when a configuration key
|
|
45
|
+
is provided.
|
|
46
|
+
|
|
47
|
+
- `autoPostOnBodyMutation`: send after a body mutation (default: `true`). Set
|
|
48
|
+
it to `false` to use `send()`.
|
|
49
|
+
- `skipIfBodyMissing`: skip when the body is `null` or `undefined` (default:
|
|
50
|
+
`true`).
|
|
51
|
+
- `refetchEveryMs`: repeat the POST at this interval. Use it only when
|
|
52
|
+
repeating the operation is intended.
|
|
53
|
+
- `skipEmptyPlaceholder`: block the request when a `${...}` placeholder is
|
|
54
|
+
`""`.
|
|
55
|
+
|
|
56
|
+
With a configuration key:
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
@post(endpoint, userBodyKey, apiConfigurationKey)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
See [Dynamic path placeholders](#docs/_misc/dynamic-path.md/dynamic-path) for
|
|
63
|
+
dynamic path details.
|
|
64
|
+
|
|
65
|
+
## When the POST is sent
|
|
66
|
+
|
|
67
|
+
- when the component connects and the body and configuration are available;
|
|
68
|
+
- after a body mutation, unless `autoPostOnBodyMutation: false`;
|
|
69
|
+
- when a property used in `${...}` changes;
|
|
70
|
+
- when a configuration publisher changes;
|
|
71
|
+
- when `send()` is called;
|
|
72
|
+
- after each response when `refetchEveryMs` is set.
|
|
73
|
+
|
|
74
|
+
## Import
|
|
42
75
|
|
|
43
76
|
<sonic-code language="typescript">
|
|
44
77
|
<template>
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
@post(
|
|
49
|
-
new Endpoint<SyncResponse, { sessionId: string }>("sessions/${sessionId}/sync"),
|
|
50
|
-
syncRequest,
|
|
51
|
-
{ triggerKey: syncTrigger },
|
|
52
|
-
)
|
|
53
|
-
@state()
|
|
54
|
-
payload?: ApiResult<SyncResponse> | null;
|
|
78
|
+
import { post, type ApiResult } from "@supersoniks/concorde/decorators";
|
|
79
|
+
import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
|
|
80
|
+
import { Endpoint } from "@supersoniks/concorde/utils/endpoint";
|
|
55
81
|
</template>
|
|
56
82
|
</sonic-code>
|
|
57
83
|
|
|
58
|
-
##
|
|
84
|
+
## Demos
|
|
59
85
|
|
|
60
86
|
<sonic-code>
|
|
61
87
|
<template>
|
|
62
88
|
<docs-demo-sources for="demo-api-post"></docs-demo-sources>
|
|
63
89
|
<demo-api-post></demo-api-post>
|
|
64
|
-
</template>
|
|
65
|
-
</sonic-code>
|
|
66
|
-
|
|
67
|
-
Dynamic endpoint path — changing `sessionId` on the host re-runs the POST (`POST /docs-mock-api/api/sessions/{id}/sync`):
|
|
68
|
-
|
|
69
|
-
<sonic-code>
|
|
70
|
-
<template>
|
|
71
90
|
<docs-demo-sources for="demo-api-post-dynamic"></docs-demo-sources>
|
|
72
91
|
<demo-api-post-dynamic></demo-api-post-dynamic>
|
|
73
92
|
</template>
|
|
74
93
|
</sonic-code>
|
|
75
94
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
<template>
|
|
80
|
-
<docs-demo-sources for="demo-api-post-publish"></docs-demo-sources>
|
|
81
|
-
<demo-api-post-publish></demo-api-post-publish>
|
|
82
|
-
</template>
|
|
83
|
-
</sonic-code>
|
|
84
|
-
|
|
85
|
-
Stale responses are ignored if the path or generation changed before the request finished.
|
|
86
|
-
|
|
87
|
-
**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).
|
|
88
|
-
|
|
89
|
-
Path placeholders (`${sessionId}`, …): [Dynamic path placeholders](#docs/_misc/dynamic-path.md/dynamic-path).
|
|
95
|
+
See [@put](#docs/_decorators/put.md/put) and
|
|
96
|
+
[@patch](#docs/_decorators/patch.md/patch): they use the same model with a
|
|
97
|
+
different HTTP method.
|
|
90
98
|
|
|
91
|
-
##
|
|
99
|
+
## Advanced
|
|
92
100
|
|
|
93
|
-
|
|
101
|
+
External invalidation is currently available through `triggerKey`; it is kept
|
|
102
|
+
out of the main usage examples.
|
|
@@ -1,43 +1,56 @@
|
|
|
1
1
|
# @put
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`@put` replaces a resource with the body from a publisher. It uses exactly the
|
|
4
|
+
same model as [@post](#docs/_decorators/post.md/post):
|
|
5
|
+
`Endpoint<T>`, `DataProviderKey<B>`, `ApiResult<T>`, options, and the
|
|
6
|
+
`send(component)` handle.
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
## Minimal usage
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
```typescript
|
|
11
|
+
const bodyKey = new DataProviderKey<UpdateUser>("users.form");
|
|
12
|
+
const updateUser = put(new Endpoint<User>("users/42"), bodyKey);
|
|
8
13
|
|
|
9
|
-
|
|
14
|
+
@updateUser
|
|
15
|
+
@state()
|
|
16
|
+
payload: ApiResult<User> | null = null;
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
To run the operation again from the component:
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
update() {
|
|
23
|
+
updateUser.send(this);
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The PUT is also sent automatically when the body mutates, unless
|
|
28
|
+
`autoPostOnBodyMutation: false` is set. See
|
|
29
|
+
[@post](#docs/_decorators/post.md/post) for the option details:
|
|
10
30
|
|
|
11
|
-
|
|
31
|
+
- `autoPostOnBodyMutation`
|
|
32
|
+
- `skipIfBodyMissing`
|
|
33
|
+
- `refetchEveryMs`
|
|
34
|
+
- `skipEmptyPlaceholder`
|
|
12
35
|
|
|
13
|
-
|
|
36
|
+
Pass explicit API configuration as the third argument:
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
@put(endpoint, bodyKey, apiConfigurationKey)
|
|
40
|
+
```
|
|
14
41
|
|
|
15
42
|
## Import
|
|
16
43
|
|
|
17
44
|
<sonic-code language="typescript">
|
|
18
45
|
<template>
|
|
19
46
|
import { put, type ApiResult } from "@supersoniks/concorde/decorators";
|
|
20
|
-
import { Endpoint } from "@supersoniks/concorde/utils/endpoint";
|
|
21
47
|
import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
|
|
48
|
+
import { Endpoint } from "@supersoniks/concorde/utils/endpoint";
|
|
22
49
|
</template>
|
|
23
50
|
</sonic-code>
|
|
24
51
|
|
|
25
|
-
## Example
|
|
26
|
-
|
|
27
|
-
<sonic-code language="typescript">
|
|
28
|
-
<template>
|
|
29
|
-
const bodyKey = new DataProviderKey<UpdatePayload>("resourceBody");
|
|
30
|
-
|
|
31
|
-
@put(new Endpoint<Resource, { resourceId: string }>("resources/${resourceId}"), bodyKey)
|
|
32
|
-
@state()
|
|
33
|
-
payload?: ApiResult<Resource> | null;
|
|
34
|
-
</template>
|
|
35
|
-
</sonic-code>
|
|
36
|
-
|
|
37
|
-
Changing `resourceId` on the host re-runs the PUT when the path becomes ready — see [Dynamic path placeholders](#docs/_misc/dynamic-path.md/dynamic-path).
|
|
38
|
-
|
|
39
52
|
## See also
|
|
40
53
|
|
|
41
|
-
- [@post](#docs/_decorators/post.md/post) —
|
|
42
|
-
- [@patch](#docs/_decorators/patch.md/patch) — partial update
|
|
43
|
-
- [
|
|
54
|
+
- [@post](#docs/_decorators/post.md/post) — options and triggers
|
|
55
|
+
- [@patch](#docs/_decorators/patch.md/patch) — partial update
|
|
56
|
+
- [Dynamic path placeholders](#docs/_misc/dynamic-path.md/dynamic-path)
|
|
@@ -26,16 +26,36 @@ node node_modules/@supersoniks/concorde/scripts/ai-init.mjs
|
|
|
26
26
|
|
|
27
27
|
| Flag | Effect |
|
|
28
28
|
|------|--------|
|
|
29
|
-
| `--
|
|
30
|
-
| `--
|
|
29
|
+
| `--skip-agents` | Never write `AGENTS.md` (skills / rules only) |
|
|
30
|
+
| `--merge-agents` | Opt-in: keep the project preamble and append / refresh the Concorde block |
|
|
31
|
+
| `--force-agents` | Opt-in: **replace** the whole `AGENTS.md` (destructive) |
|
|
32
|
+
| `--overlay <dir>` | Extra rules/skills + optional `AGENTS.concorde.md` for project-only Concorde agent notes |
|
|
31
33
|
| `--cursor-only` | Install only `.cursor/skills` and `.cursor/rules` |
|
|
32
34
|
| `--jetbrains-only` | Install only `.aiassistant/rules/` |
|
|
33
35
|
|
|
36
|
+
## `AGENTS.md` policy (non-invasive)
|
|
37
|
+
|
|
38
|
+
| Situation | Default |
|
|
39
|
+
|-----------|---------|
|
|
40
|
+
| No `AGENTS.md` | Create the Concorde guide |
|
|
41
|
+
| File with `<!-- concorde-ai -->` | Refresh the managed zone only |
|
|
42
|
+
| File **without** marker (project notes) | **Left untouched** — skills / rules are enough |
|
|
43
|
+
| `--merge-agents` / `--force-agents` / `--skip-agents` | See flags above |
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
[optional project preamble — short, project-only]
|
|
47
|
+
<!-- concorde-ai -->
|
|
48
|
+
<package ai/AGENTS.md>
|
|
49
|
+
[--- + overlay AGENTS.concorde.md]
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Everything **after** `<!-- concorde-ai -->` is replaced on each `ai-init` run (idempotent). Do not paste a full copy of the Concorde guide above the marker — put project-specific notes in `AGENTS.concorde.md` (overlay). If the preamble duplicates package `AGENTS.md`, `ai-init` slims or drops it and prints a warning. Legacy filenames `AGENTS.overlay.md` / `AGENTS.starter.md` are still accepted with a deprecation warning.
|
|
53
|
+
|
|
34
54
|
## What gets installed
|
|
35
55
|
|
|
36
56
|
| Path | Role |
|
|
37
57
|
|------|------|
|
|
38
|
-
| `AGENTS.md` |
|
|
58
|
+
| `AGENTS.md` | Created only if missing; existing project-owned files are left alone unless `--merge-agents` / `--force-agents` |
|
|
39
59
|
| `.cursor/skills/concorde/` | Core Lit + DataProvider patterns |
|
|
40
60
|
| `.cursor/skills/concorde-imports/` | Short `@supersoniks/concorde/…` import paths |
|
|
41
61
|
| `.cursor/skills/concorde-scope/` | `serviceURL`, `formDataProvider`, API configuration |
|
|
@@ -49,7 +69,7 @@ node node_modules/@supersoniks/concorde/scripts/ai-init.mjs
|
|
|
49
69
|
|
|
50
70
|
1. **Starter project:** [Installation](#docs/_getting-started/concorde-outside.md/concorde-outside) — `yarn ai:sync` is wired in the kit.
|
|
51
71
|
2. **Existing / manual Vite project:** [Manual installation](#docs/_getting-started/concorde-manual-install.md/concorde-manual-install), then **`ai-init`** after `yarn add @supersoniks/concorde`.
|
|
52
|
-
3. Commit
|
|
72
|
+
3. Commit `.cursor/` and `.aiassistant/` (and `AGENTS.md` only if you opted in / it was created) if your team shares agent settings.
|
|
53
73
|
4. Re-run the same command when you bump `@supersoniks/concorde` to refresh skills from `node_modules/@supersoniks/concorde/ai/`.
|
|
54
74
|
5. In Cursor, skills under `.cursor/skills/` are picked up automatically; mention a skill in chat for focused tasks (e.g. migration → `concorde-get-set-dp`).
|
|
55
75
|
|