@supersoniks/concorde 4.9.9 → 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 +241 -241
- package/concorde-core.es.js +2908 -2845
- package/dist/concorde-core.bundle.js +241 -241
- package/dist/concorde-core.es.js +2908 -2845
- package/dist/js/core/decorators/api.js +92 -2
- 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 +82 -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-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 +1 -1
- 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/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 +128 -133
- package/docs/assets/index-Bnp7gVaA.css +0 -1
|
@@ -4744,6 +4744,51 @@
|
|
|
4744
4744
|
}
|
|
4745
4745
|
}
|
|
4746
4746
|
},
|
|
4747
|
+
{
|
|
4748
|
+
"search": "The decorator returned by get(...) can be kept as a typed handle. Its refetch(component) action targets only the connected component instance and works even before the first ApiResult exists:\n",
|
|
4749
|
+
"files": {
|
|
4750
|
+
"docs/_decorators/get.md": {
|
|
4751
|
+
"title": "@get",
|
|
4752
|
+
"hashes": {
|
|
4753
|
+
"local-refetch-handle": {
|
|
4754
|
+
"count": 1,
|
|
4755
|
+
"title": "Local refetch handle",
|
|
4756
|
+
"type": "paragraph"
|
|
4757
|
+
}
|
|
4758
|
+
}
|
|
4759
|
+
}
|
|
4760
|
+
}
|
|
4761
|
+
},
|
|
4762
|
+
{
|
|
4763
|
+
"search": "The inline form remains unchanged:\n",
|
|
4764
|
+
"files": {
|
|
4765
|
+
"docs/_decorators/get.md": {
|
|
4766
|
+
"title": "@get",
|
|
4767
|
+
"hashes": {
|
|
4768
|
+
"local-refetch-handle": {
|
|
4769
|
+
"count": 1,
|
|
4770
|
+
"title": "Local refetch handle",
|
|
4771
|
+
"type": "paragraph"
|
|
4772
|
+
}
|
|
4773
|
+
}
|
|
4774
|
+
}
|
|
4775
|
+
}
|
|
4776
|
+
},
|
|
4777
|
+
{
|
|
4778
|
+
"search": "For a refetch triggered from another component, keep using triggerKey and invalidate().\n",
|
|
4779
|
+
"files": {
|
|
4780
|
+
"docs/_decorators/get.md": {
|
|
4781
|
+
"title": "@get",
|
|
4782
|
+
"hashes": {
|
|
4783
|
+
"local-refetch-handle": {
|
|
4784
|
+
"count": 1,
|
|
4785
|
+
"title": "Local refetch handle",
|
|
4786
|
+
"type": "paragraph"
|
|
4787
|
+
}
|
|
4788
|
+
}
|
|
4789
|
+
}
|
|
4790
|
+
}
|
|
4791
|
+
},
|
|
4747
4792
|
{
|
|
4748
4793
|
"search": "Pass as the second argument (scoped config) or third (with a configuration key). Same shape as send decorators where applicable:\n",
|
|
4749
4794
|
"files": {
|
|
@@ -4759,6 +4804,51 @@
|
|
|
4759
4804
|
}
|
|
4760
4805
|
}
|
|
4761
4806
|
},
|
|
4807
|
+
{
|
|
4808
|
+
"search": "Same pattern as @post: a publisher acts as a signal, independent of the response payload.\n",
|
|
4809
|
+
"files": {
|
|
4810
|
+
"docs/_decorators/get.md": {
|
|
4811
|
+
"title": "@get",
|
|
4812
|
+
"hashes": {
|
|
4813
|
+
"manual-refetch-triggerkey": {
|
|
4814
|
+
"count": 1,
|
|
4815
|
+
"title": "Manual refetch (`triggerKey`)",
|
|
4816
|
+
"type": "paragraph"
|
|
4817
|
+
}
|
|
4818
|
+
}
|
|
4819
|
+
}
|
|
4820
|
+
}
|
|
4821
|
+
},
|
|
4822
|
+
{
|
|
4823
|
+
"search": "Prefer triggerKey over mutating the API configuration publisher when you only want to reload the same URL — no need to touch serviceURL, tokens, etc.\n",
|
|
4824
|
+
"files": {
|
|
4825
|
+
"docs/_decorators/get.md": {
|
|
4826
|
+
"title": "@get",
|
|
4827
|
+
"hashes": {
|
|
4828
|
+
"manual-refetch-triggerkey": {
|
|
4829
|
+
"count": 1,
|
|
4830
|
+
"title": "Manual refetch (`triggerKey`)",
|
|
4831
|
+
"type": "paragraph"
|
|
4832
|
+
}
|
|
4833
|
+
}
|
|
4834
|
+
}
|
|
4835
|
+
}
|
|
4836
|
+
},
|
|
4837
|
+
{
|
|
4838
|
+
"search": "The docs mock adds an X-Fetched-At response header on /docs-mock-api/geo/communes so live demos can show when the last fetch happened (response.headers.get("X-Fetched-At")).\n",
|
|
4839
|
+
"files": {
|
|
4840
|
+
"docs/_decorators/get.md": {
|
|
4841
|
+
"title": "@get",
|
|
4842
|
+
"hashes": {
|
|
4843
|
+
"manual-refetch-triggerkey": {
|
|
4844
|
+
"count": 1,
|
|
4845
|
+
"title": "Manual refetch (`triggerKey`)",
|
|
4846
|
+
"type": "paragraph"
|
|
4847
|
+
}
|
|
4848
|
+
}
|
|
4849
|
+
}
|
|
4850
|
+
}
|
|
4851
|
+
},
|
|
4762
4852
|
{
|
|
4763
4853
|
"search": "Same demo service as sonic-queue (/docs-mock-api/geo/). Publisher setup lives in decorators-demo-geo.ts and decorators-demo-subscribe-publish-get-demos.ts.\n",
|
|
4764
4854
|
"files": {
|
|
@@ -4775,7 +4865,22 @@
|
|
|
4775
4865
|
}
|
|
4776
4866
|
},
|
|
4777
4867
|
{
|
|
4778
|
-
"search": "
|
|
4868
|
+
"search": "@get with triggerKey — refresh button + X-Fetched-At timestamp in the UI:\n",
|
|
4869
|
+
"files": {
|
|
4870
|
+
"docs/_decorators/get.md": {
|
|
4871
|
+
"title": "@get",
|
|
4872
|
+
"hashes": {
|
|
4873
|
+
"live-demos": {
|
|
4874
|
+
"count": 1,
|
|
4875
|
+
"title": "Live demos",
|
|
4876
|
+
"type": "paragraph"
|
|
4877
|
+
}
|
|
4878
|
+
}
|
|
4879
|
+
}
|
|
4880
|
+
}
|
|
4881
|
+
},
|
|
4882
|
+
{
|
|
4883
|
+
"search": "Dynamic config and endpoint path. Manual refetch is triggered from a separate component (same triggerKey publisher):\n",
|
|
4779
4884
|
"files": {
|
|
4780
4885
|
"docs/_decorators/get.md": {
|
|
4781
4886
|
"title": "@get",
|
|
@@ -5884,6 +5989,36 @@
|
|
|
5884
5989
|
}
|
|
5885
5990
|
}
|
|
5886
5991
|
},
|
|
5992
|
+
{
|
|
5993
|
+
"search": "The decorator returned by post(...) can be kept as a typed handle. Its send(component) action re-runs the POST with the current body publisher:\n",
|
|
5994
|
+
"files": {
|
|
5995
|
+
"docs/_decorators/post.md": {
|
|
5996
|
+
"title": "@post",
|
|
5997
|
+
"hashes": {
|
|
5998
|
+
"local-send-handle": {
|
|
5999
|
+
"count": 1,
|
|
6000
|
+
"title": "Local send handle",
|
|
6001
|
+
"type": "paragraph"
|
|
6002
|
+
}
|
|
6003
|
+
}
|
|
6004
|
+
}
|
|
6005
|
+
}
|
|
6006
|
+
},
|
|
6007
|
+
{
|
|
6008
|
+
"search": "send() is an explicit write operation. It is intentionally distinct from GET invalidation because replaying a POST, PUT, or PATCH can have side effects.\n",
|
|
6009
|
+
"files": {
|
|
6010
|
+
"docs/_decorators/post.md": {
|
|
6011
|
+
"title": "@post",
|
|
6012
|
+
"hashes": {
|
|
6013
|
+
"local-send-handle": {
|
|
6014
|
+
"count": 1,
|
|
6015
|
+
"title": "Local send handle",
|
|
6016
|
+
"type": "paragraph"
|
|
6017
|
+
}
|
|
6018
|
+
}
|
|
6019
|
+
}
|
|
6020
|
+
}
|
|
6021
|
+
},
|
|
5887
6022
|
{
|
|
5888
6023
|
"search": "Mock service: POST /docs-mock-api/api/register (same route as sonic-submit demos). Publisher setup lives in decorators-demo-post.ts.\n",
|
|
5889
6024
|
"files": {
|
|
@@ -6874,6 +7009,21 @@
|
|
|
6874
7009
|
}
|
|
6875
7010
|
}
|
|
6876
7011
|
},
|
|
7012
|
+
{
|
|
7013
|
+
"search": "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.\n",
|
|
7014
|
+
"files": {
|
|
7015
|
+
"docs/_getting-started/ai-agents.md": {
|
|
7016
|
+
"title": "AI agents (skills & AGENTS.md)",
|
|
7017
|
+
"hashes": {
|
|
7018
|
+
"agentsmd-policy-non-invasive": {
|
|
7019
|
+
"count": 1,
|
|
7020
|
+
"title": "`AGENTS.md` policy (non-invasive)",
|
|
7021
|
+
"type": "paragraph"
|
|
7022
|
+
}
|
|
7023
|
+
}
|
|
7024
|
+
}
|
|
7025
|
+
}
|
|
7026
|
+
},
|
|
6877
7027
|
{
|
|
6878
7028
|
"search": "Source files in the npm package: node_modules/@supersoniks/concorde/ai/ (see also ai/README.md in the Concorde repository).\n",
|
|
6879
7029
|
"files": {
|
package/docs/src/tsconfig.json
CHANGED
|
@@ -789,6 +789,9 @@
|
|
|
789
789
|
"./utils/PublisherProxy": [
|
|
790
790
|
"/sites/concorde/src/core/utils/PublisherProxy.ts"
|
|
791
791
|
],
|
|
792
|
+
"./utils/SafariScrollGuard": [
|
|
793
|
+
"/sites/concorde/src/core/utils/SafariScrollGuard.ts"
|
|
794
|
+
],
|
|
792
795
|
"./utils/Utils": [
|
|
793
796
|
"/sites/concorde/src/core/utils/Utils.ts"
|
|
794
797
|
],
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@ import API, {
|
|
|
5
5
|
type ApiResult,
|
|
6
6
|
} from "@supersoniks/concorde/core/utils/api";
|
|
7
7
|
import { PublisherManager } from "@supersoniks/concorde/core/utils/PublisherProxy";
|
|
8
|
-
import { patch, post, put } from "./api";
|
|
8
|
+
import { patch, post, put, send } from "./api";
|
|
9
9
|
|
|
10
10
|
async function flushSendFrames() {
|
|
11
11
|
await new Promise<void>((resolve) => {
|
|
@@ -68,6 +68,84 @@ describe("post", () => {
|
|
|
68
68
|
expect(el.payload?.result).toEqual({ ok: true });
|
|
69
69
|
});
|
|
70
70
|
|
|
71
|
+
it("expose un send local avec le body courant", async () => {
|
|
72
|
+
const bodyPubId = "postSpecLocalSend";
|
|
73
|
+
const pub = PublisherManager.get(bodyPubId);
|
|
74
|
+
pub.set({ value: "first" });
|
|
75
|
+
const bodyKey = new DataProviderKey<{ value: string }>(bodyPubId);
|
|
76
|
+
const syncEp = new Endpoint<{ ok: boolean }>("items/local-send");
|
|
77
|
+
const localPost = post(syncEp, bodyKey);
|
|
78
|
+
const tag = "test-api-post-local-send";
|
|
79
|
+
|
|
80
|
+
class C extends HTMLElement {
|
|
81
|
+
@localPost
|
|
82
|
+
payload: ApiResult<{ ok: boolean }> | null = null;
|
|
83
|
+
}
|
|
84
|
+
if (!customElements.get(tag)) {
|
|
85
|
+
customElements.define(tag, C);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const wrap = document.createElement("div");
|
|
89
|
+
wrap.setAttribute("serviceURL", "https://api.example.test");
|
|
90
|
+
const el = document.createElement(tag) as InstanceType<typeof C>;
|
|
91
|
+
wrap.appendChild(el);
|
|
92
|
+
document.body.appendChild(wrap);
|
|
93
|
+
|
|
94
|
+
await flushSendFrames();
|
|
95
|
+
vi.mocked(API.prototype.postDetailed).mockClear();
|
|
96
|
+
|
|
97
|
+
pub.set({ value: "second" });
|
|
98
|
+
localPost.send(el);
|
|
99
|
+
await flushSendFrames();
|
|
100
|
+
|
|
101
|
+
expect(API.prototype.postDetailed).toHaveBeenCalledTimes(1);
|
|
102
|
+
expect(API.prototype.postDetailed).toHaveBeenCalledWith(
|
|
103
|
+
"items/local-send",
|
|
104
|
+
{ value: "second" },
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("peut décorer une méthode avec send après sa résolution", async () => {
|
|
109
|
+
const bodyPubId = "postSpecMethodSend";
|
|
110
|
+
const pub = PublisherManager.get(bodyPubId);
|
|
111
|
+
pub.set({ value: "first" });
|
|
112
|
+
const bodyKey = new DataProviderKey<{ value: string }>(bodyPubId);
|
|
113
|
+
const syncEp = new Endpoint<{ ok: boolean }>("items/method-send");
|
|
114
|
+
const localPost = post(syncEp, bodyKey);
|
|
115
|
+
const tag = "test-api-post-method-send";
|
|
116
|
+
|
|
117
|
+
class C extends HTMLElement {
|
|
118
|
+
@localPost
|
|
119
|
+
payload: ApiResult<{ ok: boolean }> | null = null;
|
|
120
|
+
|
|
121
|
+
@send(localPost)
|
|
122
|
+
async save() {
|
|
123
|
+
await Promise.resolve();
|
|
124
|
+
pub.set({ value: "after" });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (!customElements.get(tag)) {
|
|
128
|
+
customElements.define(tag, C);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const wrap = document.createElement("div");
|
|
132
|
+
wrap.setAttribute("serviceURL", "https://api.example.test");
|
|
133
|
+
const el = document.createElement(tag) as InstanceType<typeof C>;
|
|
134
|
+
wrap.appendChild(el);
|
|
135
|
+
document.body.appendChild(wrap);
|
|
136
|
+
|
|
137
|
+
await flushSendFrames();
|
|
138
|
+
vi.mocked(API.prototype.postDetailed).mockClear();
|
|
139
|
+
|
|
140
|
+
await el.save();
|
|
141
|
+
await flushSendFrames();
|
|
142
|
+
|
|
143
|
+
expect(API.prototype.postDetailed).toHaveBeenCalledWith(
|
|
144
|
+
"items/method-send",
|
|
145
|
+
{ value: "after" },
|
|
146
|
+
);
|
|
147
|
+
});
|
|
148
|
+
|
|
71
149
|
it("endpoint dynamique et relance quand le body publisher mute", async () => {
|
|
72
150
|
const bodyPubId = "postSpecBody2";
|
|
73
151
|
const pub = PublisherManager.get(bodyPubId);
|
|
@@ -6,7 +6,7 @@ import API, {
|
|
|
6
6
|
type ApiResult,
|
|
7
7
|
} from "@supersoniks/concorde/core/utils/api";
|
|
8
8
|
import { PublisherManager } from "@supersoniks/concorde/core/utils/PublisherProxy";
|
|
9
|
-
import { get } from "./api";
|
|
9
|
+
import { get, refetch } from "./api";
|
|
10
10
|
|
|
11
11
|
const staticConfig: APIConfiguration = {
|
|
12
12
|
serviceURL: "https://api.example.test",
|
|
@@ -190,6 +190,105 @@ describe("get", () => {
|
|
|
190
190
|
expect(el.payload?.result).toEqual({ id: "loaded" });
|
|
191
191
|
});
|
|
192
192
|
|
|
193
|
+
it("expose un refetch local avant et après le premier payload", async () => {
|
|
194
|
+
const pubId = "getSpecLocalRefetch";
|
|
195
|
+
PublisherManager.get(pubId).set(staticConfig);
|
|
196
|
+
const confKey = new DataProviderKey<APIConfiguration>(pubId);
|
|
197
|
+
const itemEp = new Endpoint<{ id: string }>("items/local");
|
|
198
|
+
const localGet = get(itemEp, confKey);
|
|
199
|
+
const tag = "test-api-get-local-refetch";
|
|
200
|
+
|
|
201
|
+
class C extends HTMLElement {
|
|
202
|
+
@localGet
|
|
203
|
+
payload: ApiResult<{ id: string }> | null = null;
|
|
204
|
+
}
|
|
205
|
+
if (!customElements.get(tag)) {
|
|
206
|
+
customElements.define(tag, C);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const el = document.createElement(tag) as InstanceType<typeof C>;
|
|
210
|
+
document.body.appendChild(el);
|
|
211
|
+
|
|
212
|
+
localGet.refetch(el);
|
|
213
|
+
await flushGetFrames();
|
|
214
|
+
expect(API.prototype.getDetailed).toHaveBeenCalledTimes(1);
|
|
215
|
+
|
|
216
|
+
vi.mocked(API.prototype.getDetailed).mockClear();
|
|
217
|
+
el.payload = mockPayload({ id: "manual" });
|
|
218
|
+
localGet.refetch(el);
|
|
219
|
+
await flushGetFrames();
|
|
220
|
+
|
|
221
|
+
expect(API.prototype.getDetailed).toHaveBeenCalledTimes(1);
|
|
222
|
+
expect(el.payload?.result).toEqual({ id: "loaded" });
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it("ne refait plus de GET avec un handle local après déconnexion", async () => {
|
|
226
|
+
const pubId = "getSpecLocalRefetchDisconnect";
|
|
227
|
+
PublisherManager.get(pubId).set(staticConfig);
|
|
228
|
+
const confKey = new DataProviderKey<APIConfiguration>(pubId);
|
|
229
|
+
const localGet = get(
|
|
230
|
+
new Endpoint<{ id: string }>("items/local-disconnect"),
|
|
231
|
+
confKey,
|
|
232
|
+
);
|
|
233
|
+
const tag = "test-api-get-local-refetch-disconnect";
|
|
234
|
+
|
|
235
|
+
class C extends HTMLElement {
|
|
236
|
+
@localGet
|
|
237
|
+
payload: ApiResult<{ id: string }> | null = null;
|
|
238
|
+
}
|
|
239
|
+
if (!customElements.get(tag)) {
|
|
240
|
+
customElements.define(tag, C);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const el = document.createElement(tag) as InstanceType<typeof C>;
|
|
244
|
+
document.body.appendChild(el);
|
|
245
|
+
await flushGetFrames();
|
|
246
|
+
vi.mocked(API.prototype.getDetailed).mockClear();
|
|
247
|
+
|
|
248
|
+
el.remove();
|
|
249
|
+
localGet.refetch(el);
|
|
250
|
+
await flushGetFrames();
|
|
251
|
+
|
|
252
|
+
expect(API.prototype.getDetailed).not.toHaveBeenCalled();
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it("peut décorer une méthode et refetcher après sa résolution", async () => {
|
|
256
|
+
const pubId = "getSpecMethodRefetch";
|
|
257
|
+
PublisherManager.get(pubId).set(staticConfig);
|
|
258
|
+
const confKey = new DataProviderKey<APIConfiguration>(pubId);
|
|
259
|
+
const rowEp = new Endpoint<{ id: string }, { rowId: string }>(
|
|
260
|
+
"rows/${rowId}",
|
|
261
|
+
);
|
|
262
|
+
const localGet = get(rowEp, confKey);
|
|
263
|
+
const tag = "test-api-get-method-refetch";
|
|
264
|
+
|
|
265
|
+
class C extends HTMLElement {
|
|
266
|
+
rowId = "42";
|
|
267
|
+
|
|
268
|
+
@localGet
|
|
269
|
+
payload: ApiResult<{ id: string }> | null = null;
|
|
270
|
+
|
|
271
|
+
@refetch(localGet)
|
|
272
|
+
async reload() {
|
|
273
|
+
await Promise.resolve();
|
|
274
|
+
this.rowId = "84";
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
if (!customElements.get(tag)) {
|
|
278
|
+
customElements.define(tag, C);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const el = document.createElement(tag) as InstanceType<typeof C>;
|
|
282
|
+
document.body.appendChild(el);
|
|
283
|
+
await flushGetFrames();
|
|
284
|
+
vi.mocked(API.prototype.getDetailed).mockClear();
|
|
285
|
+
|
|
286
|
+
await el.reload();
|
|
287
|
+
await flushGetFrames();
|
|
288
|
+
|
|
289
|
+
expect(API.prototype.getDetailed).toHaveBeenCalledWith("rows/84");
|
|
290
|
+
});
|
|
291
|
+
|
|
193
292
|
it("refetch automatique avec refetchEveryMs", async () => {
|
|
194
293
|
vi.useFakeTimers();
|
|
195
294
|
const itemEp = new Endpoint<{ id: string }>("items/1");
|