@supersoniks/concorde 4.2.1 → 4.3.0
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/README.md +163 -0
- package/build-infos.json +1 -1
- package/concorde-core.bundle.js +175 -171
- package/concorde-core.es.js +2490 -2246
- package/dist/concorde-core.bundle.js +175 -171
- package/dist/concorde-core.es.js +2490 -2246
- package/package.json +22 -1
- package/php/get-challenge.php +34 -0
- package/php/some-service.php +42 -0
- package/scripts/pre-build.mjs +4 -0
- package/src/core/_types/endpoint.ts +4 -0
- package/src/core/_types/key.ts +1 -0
- package/src/core/components/functional/example/example.ts +38 -6
- package/src/core/decorators/Subscriber.ts +2 -0
- package/src/core/decorators/api.spec.ts +150 -0
- package/src/core/decorators/api.ts +244 -0
- package/src/core/decorators/subscriber/bind.ts +57 -145
- package/src/core/decorators/subscriber/dynamicPath.ts +77 -0
- package/src/core/decorators/subscriber/dynamicPropertyWatch.ts +105 -0
- package/src/core/decorators/subscriber/onAssign.ts +11 -147
- package/src/core/decorators/subscriber/publish.spec.ts +21 -0
- package/src/core/decorators/subscriber/publish.ts +148 -0
- package/src/core/decorators/subscriber/publisherPath.ts +13 -0
- package/src/core/decorators/subscriber/subscribe.spec.ts +21 -0
- package/src/core/decorators/subscriber/subscribe.ts +32 -0
- package/src/core/decorators/subscriber/subscribe.type-test.ts +32 -0
- package/src/core/utils/api.ts +83 -15
- package/src/core/utils/dataProviderKey.spec.ts +34 -0
- package/src/core/utils/dataProviderKey.ts +86 -0
- package/src/core/utils/endpoint.spec.ts +41 -0
- package/src/core/utils/endpoint.ts +87 -0
- package/src/decorators.ts +14 -0
- package/src/docs/{_misc → _decorators}/ancestor-attribute.md +15 -31
- package/src/docs/_decorators/bind.md +164 -0
- package/src/docs/_decorators/get.md +65 -0
- package/src/docs/_decorators/publish.md +54 -0
- package/src/docs/_decorators/subscribe.md +36 -0
- package/src/docs/_misc/dataProviderKey.md +135 -0
- package/src/docs/_misc/endpoint.md +42 -0
- package/src/docs/example/decorators-demo-bind-demos.ts +210 -0
- package/src/docs/example/decorators-demo-geo.ts +45 -0
- package/src/docs/example/decorators-demo-init.ts +228 -0
- package/src/docs/example/decorators-demo-subscribe-publish-get-demos.ts +324 -0
- package/src/docs/example/decorators-demo.ts +12 -459
- package/src/docs/navigation/navigation.ts +27 -10
- package/src/docs/search/docs-search.json +1059 -609
- package/src/tsconfig-model.json +1 -1
- package/src/tsconfig.json +65 -1
- package/src/tsconfig.tsbuildinfo +1 -1
- package/src/utils.ts +8 -1
- package/vite.config.mts +11 -0
- package/src/docs/_misc/bind.md +0 -362
- /package/src/docs/{_misc → _decorators}/auto-subscribe.md +0 -0
- /package/src/docs/{_misc → _decorators}/on-assign.md +0 -0
- /package/src/docs/{_misc → _decorators}/wait-for-ancestors.md +0 -0
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import { html, LitElement } from "lit";
|
|
2
|
+
import { customElement, property, state } from "lit/decorators.js";
|
|
3
|
+
import {
|
|
4
|
+
get,
|
|
5
|
+
publish,
|
|
6
|
+
subscribe,
|
|
7
|
+
} from "@supersoniks/concorde/decorators";
|
|
8
|
+
import type {
|
|
9
|
+
APIConfiguration,
|
|
10
|
+
ApiGetResult,
|
|
11
|
+
} from "@supersoniks/concorde/core/utils/api";
|
|
12
|
+
import { DataProviderKey } from "@supersoniks/concorde/core/utils/dataProviderKey";
|
|
13
|
+
import { sub } from "@supersoniks/concorde/directives";
|
|
14
|
+
import { PublisherManager } from "@supersoniks/concorde/core/utils/PublisherProxy";
|
|
15
|
+
import { tailwind } from "../tailwind";
|
|
16
|
+
import "./decorators-demo-init";
|
|
17
|
+
import {
|
|
18
|
+
docsDemoDynApiConfKeyTemplate,
|
|
19
|
+
docsDemoGeoApiConfigurationKey,
|
|
20
|
+
geoCommunesApiGetEndpoint,
|
|
21
|
+
geoCommunesApiGetEndpointDynamic,
|
|
22
|
+
geoCommunesApiGetPublishKey,
|
|
23
|
+
type GeoCommuneRow,
|
|
24
|
+
} from "./decorators-demo-geo";
|
|
25
|
+
|
|
26
|
+
type PublishDemoData = {
|
|
27
|
+
email: string;
|
|
28
|
+
message: string;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const publishDemoKey = new DataProviderKey<PublishDemoData>("publishDemo");
|
|
32
|
+
|
|
33
|
+
@customElement("demo-publish")
|
|
34
|
+
export class DemoPublish extends LitElement {
|
|
35
|
+
static styles = [tailwind];
|
|
36
|
+
|
|
37
|
+
@publish(publishDemoKey.email)
|
|
38
|
+
@state()
|
|
39
|
+
email = "";
|
|
40
|
+
|
|
41
|
+
@publish(publishDemoKey.message)
|
|
42
|
+
@state()
|
|
43
|
+
message = "";
|
|
44
|
+
|
|
45
|
+
connectedCallback() {
|
|
46
|
+
super.connectedCallback();
|
|
47
|
+
PublisherManager.get("publishDemo").set({ email: "", message: "" });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
render() {
|
|
51
|
+
return html`
|
|
52
|
+
<div class="space-y-4">
|
|
53
|
+
<p class="text-sm text-neutral-600 dark:text-neutral-400">
|
|
54
|
+
Les champs publient vers le publisher ; les valeurs ci-dessous passent
|
|
55
|
+
par <code>sub()</code>.
|
|
56
|
+
</p>
|
|
57
|
+
<sonic-input
|
|
58
|
+
.value=${this.email}
|
|
59
|
+
@input=${(e: Event) =>
|
|
60
|
+
(this.email = (e.target as HTMLInputElement).value)}
|
|
61
|
+
label="Email"
|
|
62
|
+
placeholder="your@email.com"
|
|
63
|
+
></sonic-input>
|
|
64
|
+
<sonic-input
|
|
65
|
+
.value=${this.message}
|
|
66
|
+
@input=${(e: Event) =>
|
|
67
|
+
(this.message = (e.target as HTMLInputElement).value)}
|
|
68
|
+
label="Message"
|
|
69
|
+
placeholder="Type a message..."
|
|
70
|
+
></sonic-input>
|
|
71
|
+
<div
|
|
72
|
+
class="rounded border border-neutral-200 dark:border-neutral-700 p-3"
|
|
73
|
+
>
|
|
74
|
+
<p
|
|
75
|
+
class="text-xs font-medium text-neutral-500 dark:text-neutral-400 mb-1"
|
|
76
|
+
>
|
|
77
|
+
Published values (from sub):
|
|
78
|
+
</p>
|
|
79
|
+
<p>Email: ${sub("publishDemo.email") || "—"}</p>
|
|
80
|
+
<p>Message: ${sub("publishDemo.message") || "—"}</p>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
`;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@customElement("demo-api-get")
|
|
88
|
+
export class DemoApiGet extends LitElement {
|
|
89
|
+
static styles = [tailwind];
|
|
90
|
+
|
|
91
|
+
@get(geoCommunesApiGetEndpoint, docsDemoGeoApiConfigurationKey)
|
|
92
|
+
@state()
|
|
93
|
+
geoApiPayload?: ApiGetResult<GeoCommuneRow[]>;
|
|
94
|
+
|
|
95
|
+
render() {
|
|
96
|
+
const rows = this.geoApiPayload?.result;
|
|
97
|
+
const status = this.geoApiPayload?.response?.status;
|
|
98
|
+
return html`
|
|
99
|
+
<div class="space-y-2">
|
|
100
|
+
<p class="text-sm text-neutral-600 dark:text-neutral-400">
|
|
101
|
+
<code>@get</code> — même service que
|
|
102
|
+
<code>sonic-queue</code> (<code>https://geo.api.gouv.fr/</code>).
|
|
103
|
+
Propriété typée <code>ApiGetResult<T></code>.
|
|
104
|
+
</p>
|
|
105
|
+
${status != null
|
|
106
|
+
? html`<p class="text-xs text-neutral-500">HTTP ${status}</p>`
|
|
107
|
+
: ""}
|
|
108
|
+
${this.geoApiPayload === null
|
|
109
|
+
? html`<p class="text-neutral-500">Chargement…</p>`
|
|
110
|
+
: !rows || rows.length === 0
|
|
111
|
+
? html`<p class="text-neutral-500">Aucune commune</p>`
|
|
112
|
+
: html`
|
|
113
|
+
<ul class="list-disc pl-5 space-y-1">
|
|
114
|
+
${rows.map(
|
|
115
|
+
(c) =>
|
|
116
|
+
html`<li>
|
|
117
|
+
<span class="font-medium">${c.nom}</span>
|
|
118
|
+
<span class="text-neutral-500 text-sm">
|
|
119
|
+
— ${c.code}</span
|
|
120
|
+
>
|
|
121
|
+
</li>`,
|
|
122
|
+
)}
|
|
123
|
+
</ul>
|
|
124
|
+
`}
|
|
125
|
+
</div>
|
|
126
|
+
`;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@customElement("demo-api-get-configuration-key")
|
|
131
|
+
export class DemoApiGetConfigurationKey extends LitElement {
|
|
132
|
+
static styles = [tailwind];
|
|
133
|
+
|
|
134
|
+
@property({ type: String })
|
|
135
|
+
configSlot: "A" | "B" = "A";
|
|
136
|
+
|
|
137
|
+
@property({ type: Number })
|
|
138
|
+
communeLimit = 5;
|
|
139
|
+
|
|
140
|
+
@get(geoCommunesApiGetEndpointDynamic, docsDemoDynApiConfKeyTemplate)
|
|
141
|
+
@state()
|
|
142
|
+
geoApiPayloadDyn?: ApiGetResult<GeoCommuneRow[]>;
|
|
143
|
+
|
|
144
|
+
private touchCurrentConfigPublisher() {
|
|
145
|
+
const id = `docsDemoDynApiConf${this.configSlot}`;
|
|
146
|
+
const pub = PublisherManager.get(id);
|
|
147
|
+
const cur = pub.get() as APIConfiguration;
|
|
148
|
+
pub.set({
|
|
149
|
+
...cur,
|
|
150
|
+
blockUntilDone: !cur.blockUntilDone,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
render() {
|
|
155
|
+
const rows = this.geoApiPayloadDyn?.result;
|
|
156
|
+
const status = this.geoApiPayloadDyn?.response?.status;
|
|
157
|
+
return html`
|
|
158
|
+
<div class="space-y-3">
|
|
159
|
+
<p class="text-sm text-neutral-600 dark:text-neutral-400">
|
|
160
|
+
Config dynamique (<code>docsDemoDynApiConf\${configSlot}</code>) +
|
|
161
|
+
path d’endpoint avec <code>communeLimit</code>. « Toucher la config »
|
|
162
|
+
déclenche un nouveau GET.
|
|
163
|
+
</p>
|
|
164
|
+
<div class="flex flex-wrap gap-2 items-center">
|
|
165
|
+
<span class="text-xs text-neutral-500">Limite API :</span>
|
|
166
|
+
${[3, 5, 10].map(
|
|
167
|
+
(n) => html`
|
|
168
|
+
<sonic-button
|
|
169
|
+
size="sm"
|
|
170
|
+
type=${this.communeLimit === n ? "primary" : "neutral"}
|
|
171
|
+
@click=${() => {
|
|
172
|
+
this.communeLimit = n;
|
|
173
|
+
}}
|
|
174
|
+
>${n}</sonic-button
|
|
175
|
+
>
|
|
176
|
+
`,
|
|
177
|
+
)}
|
|
178
|
+
</div>
|
|
179
|
+
<div class="flex flex-wrap gap-2 items-center">
|
|
180
|
+
<span class="text-xs text-neutral-500">Publisher config :</span>
|
|
181
|
+
<sonic-button
|
|
182
|
+
size="sm"
|
|
183
|
+
type=${this.configSlot === "A" ? "primary" : "neutral"}
|
|
184
|
+
@click=${() => {
|
|
185
|
+
this.configSlot = "A";
|
|
186
|
+
}}
|
|
187
|
+
>docsDemoDynApiConfA</sonic-button
|
|
188
|
+
>
|
|
189
|
+
<sonic-button
|
|
190
|
+
size="sm"
|
|
191
|
+
type=${this.configSlot === "B" ? "primary" : "neutral"}
|
|
192
|
+
@click=${() => {
|
|
193
|
+
this.configSlot = "B";
|
|
194
|
+
}}
|
|
195
|
+
>docsDemoDynApiConfB</sonic-button
|
|
196
|
+
>
|
|
197
|
+
<sonic-button
|
|
198
|
+
size="sm"
|
|
199
|
+
@click=${() => this.touchCurrentConfigPublisher()}
|
|
200
|
+
>Toucher la config</sonic-button
|
|
201
|
+
>
|
|
202
|
+
</div>
|
|
203
|
+
${status != null
|
|
204
|
+
? html`<p class="text-xs text-neutral-500">
|
|
205
|
+
HTTP ${status} · limit=${this.communeLimit} · conf=
|
|
206
|
+
docsDemoDynApiConf${this.configSlot}
|
|
207
|
+
</p>`
|
|
208
|
+
: ""}
|
|
209
|
+
${this.geoApiPayloadDyn === null
|
|
210
|
+
? html`<p class="text-neutral-500">Chargement…</p>`
|
|
211
|
+
: !rows || rows.length === 0
|
|
212
|
+
? html`<p class="text-neutral-500">Aucune commune</p>`
|
|
213
|
+
: html`
|
|
214
|
+
<ul class="list-disc pl-5 space-y-1">
|
|
215
|
+
${rows.map(
|
|
216
|
+
(c) =>
|
|
217
|
+
html`<li>
|
|
218
|
+
<span class="font-medium">${c.nom}</span>
|
|
219
|
+
<span class="text-neutral-500 text-sm">
|
|
220
|
+
— ${c.code}</span
|
|
221
|
+
>
|
|
222
|
+
</li>`,
|
|
223
|
+
)}
|
|
224
|
+
</ul>
|
|
225
|
+
`}
|
|
226
|
+
</div>
|
|
227
|
+
`;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
@customElement("demo-api-get-publish-subscribe")
|
|
232
|
+
export class DemoApiGetPublishSubscribe extends LitElement {
|
|
233
|
+
static styles = [tailwind];
|
|
234
|
+
|
|
235
|
+
@get(geoCommunesApiGetEndpoint)
|
|
236
|
+
@publish(geoCommunesApiGetPublishKey)
|
|
237
|
+
@state()
|
|
238
|
+
geoApiPayloadPublished: ApiGetResult<GeoCommuneRow[]> | null = null;
|
|
239
|
+
|
|
240
|
+
@state()
|
|
241
|
+
@subscribe(geoCommunesApiGetPublishKey.result)
|
|
242
|
+
geoCommunesFromSubscribe: GeoCommuneRow[] | null = null;
|
|
243
|
+
|
|
244
|
+
render() {
|
|
245
|
+
const rows =
|
|
246
|
+
this.geoCommunesFromSubscribe ?? this.geoApiPayloadPublished?.result;
|
|
247
|
+
const status = this.geoApiPayloadPublished?.response?.status;
|
|
248
|
+
return html`
|
|
249
|
+
<div class="space-y-2">
|
|
250
|
+
<p class="text-sm text-neutral-600 dark:text-neutral-400">
|
|
251
|
+
<code>@get</code> (scoped) + <code>@publish</code> sur la clé du
|
|
252
|
+
payload + <code>@subscribe</code> sur <code>.result</code> — même
|
|
253
|
+
rendu que <code><demo-api-get></code> (doc @get).
|
|
254
|
+
</p>
|
|
255
|
+
${status != null
|
|
256
|
+
? html`<p class="text-xs text-neutral-500">HTTP ${status}</p>`
|
|
257
|
+
: ""}
|
|
258
|
+
${this.geoApiPayloadPublished === null
|
|
259
|
+
? html`<p class="text-neutral-500">Chargement…</p>`
|
|
260
|
+
: !rows || rows.length === 0
|
|
261
|
+
? html`<p class="text-neutral-500">Aucune commune</p>`
|
|
262
|
+
: html`
|
|
263
|
+
<ul class="list-disc pl-5 space-y-1">
|
|
264
|
+
${rows.map(
|
|
265
|
+
(c) =>
|
|
266
|
+
html`<li>
|
|
267
|
+
<span class="font-medium">${c.nom}</span>
|
|
268
|
+
<span class="text-neutral-500 text-sm">
|
|
269
|
+
— ${c.code}</span
|
|
270
|
+
>
|
|
271
|
+
</li>`,
|
|
272
|
+
)}
|
|
273
|
+
</ul>
|
|
274
|
+
`}
|
|
275
|
+
</div>
|
|
276
|
+
`;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
type User = { firstName: string; lastName: string; email: string };
|
|
281
|
+
|
|
282
|
+
@customElement("demo-subscribe-dynamic")
|
|
283
|
+
export class DemoSubscribeDynamic extends LitElement {
|
|
284
|
+
static styles = [tailwind];
|
|
285
|
+
|
|
286
|
+
@property({ type: Number })
|
|
287
|
+
userIndex = 0;
|
|
288
|
+
|
|
289
|
+
@subscribe(new DataProviderKey<User>("demoUsers.${userIndex}"))
|
|
290
|
+
@state()
|
|
291
|
+
user: User | null = null;
|
|
292
|
+
|
|
293
|
+
render() {
|
|
294
|
+
return html`
|
|
295
|
+
<div class="space-y-4">
|
|
296
|
+
<p class="text-sm text-neutral-600 dark:text-neutral-400">
|
|
297
|
+
<code>@subscribe</code> avec chemin dynamique
|
|
298
|
+
<code>demoUsers.\${userIndex}</code>
|
|
299
|
+
</p>
|
|
300
|
+
<sonic-input
|
|
301
|
+
type="number"
|
|
302
|
+
.value=${String(this.userIndex)}
|
|
303
|
+
@input=${(e: Event) =>
|
|
304
|
+
(this.userIndex = parseInt((e.target as HTMLInputElement).value))}
|
|
305
|
+
min="0"
|
|
306
|
+
max="9"
|
|
307
|
+
label="User index"
|
|
308
|
+
></sonic-input>
|
|
309
|
+
${this.user
|
|
310
|
+
? html`
|
|
311
|
+
<div
|
|
312
|
+
class="rounded border border-neutral-200 dark:border-neutral-700 p-3"
|
|
313
|
+
>
|
|
314
|
+
<p>${this.user.firstName} ${this.user.lastName}</p>
|
|
315
|
+
<p class="text-sm text-neutral-500">${this.user.email}</p>
|
|
316
|
+
</div>
|
|
317
|
+
`
|
|
318
|
+
: html`<p class="text-neutral-500">
|
|
319
|
+
No user at index ${this.userIndex}
|
|
320
|
+
</p>`}
|
|
321
|
+
</div>
|
|
322
|
+
`;
|
|
323
|
+
}
|
|
324
|
+
}
|