@supersoniks/concorde 4.2.1 → 4.4.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.
Files changed (75) hide show
  1. package/README.md +163 -0
  2. package/build-infos.json +1 -1
  3. package/concorde-core.bundle.js +585 -670
  4. package/concorde-core.es.js +7165 -9505
  5. package/dist/concorde-core.bundle.js +585 -670
  6. package/dist/concorde-core.es.js +7165 -9505
  7. package/docs/assets/index-DP1oMukw.js +4949 -0
  8. package/docs/assets/index-DZtxIZCW.css +1 -0
  9. package/docs/index.html +2 -2
  10. package/{src/docs/_misc → docs/src/docs/_decorators}/ancestor-attribute.md +15 -31
  11. package/docs/src/docs/_decorators/bind.md +164 -0
  12. package/docs/src/docs/_decorators/get.md +65 -0
  13. package/docs/src/docs/_decorators/publish.md +54 -0
  14. package/docs/src/docs/_decorators/subscribe.md +36 -0
  15. package/docs/src/docs/_misc/dataProviderKey.md +135 -0
  16. package/docs/src/docs/_misc/endpoint.md +42 -0
  17. package/docs/src/docs/search/docs-search.json +850 -710
  18. package/docs/src/tsconfig.json +43 -4
  19. package/package.json +25 -4
  20. package/php/get-challenge.php +34 -0
  21. package/php/some-service.php +42 -0
  22. package/scripts/pre-build.mjs +4 -0
  23. package/src/core/_types/endpoint.ts +4 -0
  24. package/src/core/_types/key.ts +1 -0
  25. package/src/core/components/functional/example/example.ts +38 -6
  26. package/src/core/decorators/Subscriber.ts +2 -0
  27. package/src/core/decorators/api.spec.ts +150 -0
  28. package/src/core/decorators/api.ts +244 -0
  29. package/src/core/decorators/subscriber/bind.ts +57 -145
  30. package/src/core/decorators/subscriber/dynamicPath.ts +77 -0
  31. package/src/core/decorators/subscriber/dynamicPropertyWatch.ts +105 -0
  32. package/src/core/decorators/subscriber/onAssign.ts +11 -147
  33. package/src/core/decorators/subscriber/publish.spec.ts +21 -0
  34. package/src/core/decorators/subscriber/publish.ts +148 -0
  35. package/src/core/decorators/subscriber/publisherPath.ts +13 -0
  36. package/src/core/decorators/subscriber/subscribe.spec.ts +21 -0
  37. package/src/core/decorators/subscriber/subscribe.ts +32 -0
  38. package/src/core/decorators/subscriber/subscribe.type-test.ts +32 -0
  39. package/src/core/utils/api.ts +83 -15
  40. package/src/core/utils/dataProviderKey.spec.ts +34 -0
  41. package/src/core/utils/dataProviderKey.ts +86 -0
  42. package/src/core/utils/endpoint.spec.ts +41 -0
  43. package/src/core/utils/endpoint.ts +87 -0
  44. package/src/decorators.ts +14 -0
  45. package/{docs/src/docs/_misc → src/docs/_decorators}/ancestor-attribute.md +15 -31
  46. package/src/docs/_decorators/bind.md +164 -0
  47. package/src/docs/_decorators/get.md +65 -0
  48. package/src/docs/_decorators/publish.md +54 -0
  49. package/src/docs/_decorators/subscribe.md +36 -0
  50. package/src/docs/_misc/dataProviderKey.md +135 -0
  51. package/src/docs/_misc/endpoint.md +42 -0
  52. package/src/docs/example/decorators-demo-bind-demos.ts +210 -0
  53. package/src/docs/example/decorators-demo-geo.ts +45 -0
  54. package/src/docs/example/decorators-demo-init.ts +228 -0
  55. package/src/docs/example/decorators-demo-subscribe-publish-get-demos.ts +324 -0
  56. package/src/docs/example/decorators-demo.ts +12 -459
  57. package/src/docs/navigation/navigation.ts +27 -10
  58. package/src/docs/search/docs-search.json +1059 -609
  59. package/src/tsconfig-model.json +1 -1
  60. package/src/tsconfig.json +65 -1
  61. package/src/tsconfig.tsbuildinfo +1 -1
  62. package/src/utils.ts +8 -1
  63. package/vite/config.js +25 -6
  64. package/vite.config.mts +13 -0
  65. package/docs/assets/index-B0IJ9I_B.js +0 -4918
  66. package/docs/assets/index-B3QHEJTV.css +0 -1
  67. package/docs/src/docs/_misc/bind.md +0 -436
  68. package/docs/src/docs/_misc/key.md +0 -135
  69. package/src/docs/_misc/bind.md +0 -362
  70. /package/docs/src/docs/{_misc → _decorators}/auto-subscribe.md +0 -0
  71. /package/docs/src/docs/{_misc → _decorators}/on-assign.md +0 -0
  72. /package/docs/src/docs/{_misc → _decorators}/wait-for-ancestors.md +0 -0
  73. /package/src/docs/{_misc → _decorators}/auto-subscribe.md +0 -0
  74. /package/src/docs/{_misc → _decorators}/on-assign.md +0 -0
  75. /package/src/docs/{_misc → _decorators}/wait-for-ancestors.md +0 -0
@@ -0,0 +1,135 @@
1
+ # DataProviderKey
2
+
3
+ The `DataProviderKey<T>` utility provides type-safe navigation through composite data structures. Each property or index access extends the path, and the final key can be retrieved via `toString()` or the `path` property.
4
+
5
+ For a **single HTTP path string** (no dot-syntax), see [Endpoint](#docs/_misc/endpoint.md/endpoint).
6
+
7
+ ## Principle
8
+
9
+ `DataProviderKey` uses a Proxy to intercept property access and build a cumulative path string. TypeScript infers the nested type at each level, so `myKey.items[0]` is correctly typed as `DataProviderKey<Item>` when `items` is `Item[]`.
10
+
11
+ ## Usage
12
+
13
+ ### Import
14
+
15
+ <sonic-code language="typescript">
16
+ <template>
17
+ import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
18
+ </template>
19
+ </sonic-code>
20
+
21
+ ### Basic example
22
+
23
+ <sonic-code language="typescript">
24
+ <template>
25
+ type Item = { id: string; name: string };
26
+ //
27
+ type Data = {
28
+ items: Item[];
29
+ count: number;
30
+ };
31
+ //
32
+ const myKey = new DataProviderKey&lt;Data&gt;("data").items[0];
33
+ // Equivalent to: new DataProviderKey&lt;Item&gt;("data.items.0")
34
+ myKey.toString(); // "data.items.0"
35
+ myKey.path; // same value
36
+ // myKey is typed as DataProviderKey&lt;Item&gt;
37
+ </template>
38
+ </sonic-code>
39
+
40
+ ### Object property access
41
+
42
+ <sonic-code language="typescript">
43
+ <template>
44
+ const key = new DataProviderKey&lt;Data&gt;("data");
45
+ const countKey = key.count;
46
+ countKey.path; // "data.count"
47
+ countKey.toString(); // "data.count"
48
+ </template>
49
+ </sonic-code>
50
+
51
+ ### Array index access
52
+
53
+ <sonic-code language="typescript">
54
+ <template>
55
+ const itemsKey = new DataProviderKey&lt;Data&gt;("data").items;
56
+ itemsKey.path; // "data.items"
57
+ // itemsKey is DataProviderKey&lt;Item[]&gt;
58
+ //
59
+ const firstItem = itemsKey[0];
60
+ firstItem.path; // "data.items.0"
61
+ // firstItem is DataProviderKey&lt;Item&gt;
62
+ </template>
63
+ </sonic-code>
64
+
65
+ ### Dynamic paths
66
+
67
+ Use placeholders `${prop}` or `{$prop}` in the path string. The path is resolved at runtime from the component's properties. The type remains declarative:
68
+
69
+ <sonic-code language="typescript">
70
+ <template>
71
+ type User = { name: string; email: string };
72
+ //
73
+ // Path resolved from component.userIndex at runtime
74
+ @subscribe(new DataProviderKey&lt;User&gt;("users.${userIndex}"))
75
+ @state()
76
+ user: User | null = null;
77
+ </template>
78
+ </sonic-code>
79
+
80
+ ## Path retrieval
81
+
82
+ The final path is built by concatenating each accessed property with a dot:
83
+
84
+ - `new DataProviderKey<T>("base")` → `"base"`
85
+ - `key.prop` → `"base.prop"`
86
+ - `key.items[0]` → `"base.items.0"`
87
+
88
+ Use `toString()` or `path` to get the full path string:
89
+
90
+ <sonic-code language="typescript">
91
+ <template>
92
+ const key = new DataProviderKey&lt;Data&gt;("data").count;
93
+ const pathString = key.toString(); // "data.count"
94
+ const pathProp = key.path; // "data.count"
95
+ </template>
96
+ </sonic-code>
97
+
98
+ ## Use cases
99
+
100
+ - **Type-safe bindings**: paths for `@bind`, `@subscribe`, `@publish`
101
+ - **Dynamic paths**: reusable keys with `${...}` placeholders
102
+ - **Form fields**: form data paths with compile-time checking
103
+
104
+ ## Integration with @subscribe and @publish
105
+
106
+ Use `DataProviderKey` with `@subscribe` (read-only) or `@publish` (write-only). The decorated property **must** match the key’s value type:
107
+
108
+ <sonic-code language="typescript">
109
+ <template>
110
+ import { subscribe } from "@supersoniks/concorde/decorators";
111
+ import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
112
+ //
113
+ type FormData = { email: string };
114
+ const formKey = new DataProviderKey&lt;FormData&gt;("formData");
115
+ //
116
+ @customElement("user-form")
117
+ export class UserForm extends LitElement {
118
+ @subscribe(formKey.email)
119
+ @state()
120
+ email = "";
121
+ //
122
+ render() {
123
+ return html`&lt;input .value=${this.email} @input=${(e) => this.email = (e.target as HTMLInputElement).value}&gt;`;
124
+ }
125
+ }
126
+ </template>
127
+ </sonic-code>
128
+
129
+ Both decorators support dynamic paths: `"base.${prop}"` in the constructor. A wrong property type (e.g. `number` for `DataProviderKey<string>`) is a TypeScript error.
130
+
131
+ ## Notes
132
+
133
+ - Function properties are excluded from navigation (no `key.method()` chaining)
134
+ - Primitives have no navigable properties
135
+ - The `path` property and `toString()` are equivalent for retrieving the key
@@ -0,0 +1,42 @@
1
+ # Endpoint
2
+
3
+ `Endpoint<T, U>` describes a single HTTP path (or a path accepted by `API.get`) and carries the expected response type `T`. Unlike [DataProviderKey](#docs/_misc/dataProviderKey.md/dataProviderKey), there is no dot-navigation: the path is one string.
4
+
5
+ The optional second generic `U` (default `any`) describes host properties used to resolve dynamic segments in the path (`${…}` / `{$…}`), for example with the [@get](#docs/_decorators/get.md/get) decorator.
6
+
7
+ ## Import
8
+
9
+ <sonic-code language="typescript">
10
+ <template>
11
+ import { Endpoint } from "@supersoniks/concorde/utils/endpoint";
12
+ </template>
13
+ </sonic-code>
14
+
15
+ ## Construction
16
+
17
+ <sonic-code language="typescript">
18
+ <template>
19
+ const users = new Endpoint&lt;User[]&gt;("users?limit=10");
20
+ users.path; // "users?limit=10"
21
+ //
22
+ const one = new Endpoint&lt;User, { userId: string }&gt;("users/${userId}");
23
+ // `userId` on the host class is observed when used with @get
24
+ </template>
25
+ </sonic-code>
26
+
27
+ ## Normalization
28
+
29
+ `Endpoint.normalizePath` trims the string, rejects an empty path, strips leading slashes for paths relative to `serviceURL`, collapses duplicate slashes, and validates absolute `http(s)://` URLs.
30
+
31
+ ## Publisher key for payloads
32
+
33
+ `getDataProviderKey()` returns a typed publisher key whose `path` matches the endpoint path (payload typing follows `ApiGetResult` for this endpoint). Useful when pairing `@get` with `@publish` / `@subscribe` (see [@get](#docs/_decorators/get.md/get)).
34
+
35
+ ## Data-provider paths
36
+
37
+ `Endpoint.looksLikeDataProviderPath(path)` returns true for strings shaped like `dataProvider(id)…`, which `API.get` can resolve without HTTP.
38
+
39
+ ## See also
40
+
41
+ - [@get](#docs/_decorators/get.md/get) — decorator that uses `Endpoint<T>`
42
+ - [DataProviderKey](#docs/_misc/dataProviderKey.md/dataProviderKey) — typed publisher paths (dot notation)
@@ -0,0 +1,210 @@
1
+ import { html, LitElement } from "lit";
2
+ import { customElement, property, state } from "lit/decorators.js";
3
+ import { bind } from "@supersoniks/concorde/decorators";
4
+ import { DataProviderKey } from "@supersoniks/concorde/core/utils/dataProviderKey";
5
+ import { sub } from "@supersoniks/concorde/directives";
6
+ import {
7
+ PublisherManager,
8
+ PublisherProxy,
9
+ } from "@supersoniks/concorde/core/utils/PublisherProxy";
10
+ import { Objects } from "@supersoniks/concorde/utils";
11
+ import { tailwind } from "../tailwind";
12
+ import "./decorators-demo-init";
13
+
14
+ @customElement("demo-bind")
15
+ export class DemoBind extends LitElement {
16
+ static styles = [tailwind];
17
+
18
+ @bind("demoData.firstName")
19
+ @state()
20
+ firstName = "";
21
+
22
+ @bind("demoData.lastName")
23
+ @state()
24
+ lastName: string = "";
25
+
26
+ @bind("demoData.count")
27
+ @state()
28
+ count: number = 0;
29
+
30
+ render() {
31
+ return html`
32
+ <div>
33
+ <sonic-button @click=${this.updateData}>Update Data</sonic-button>
34
+ </div>
35
+ <div class="p-3">
36
+ <p>Title: <strong>${this.firstName || "Not set"}</strong></p>
37
+ <p>User Name: <strong>${this.lastName || "Not set"}</strong></p>
38
+ <p>Number of updates: <strong>${this.count}</strong></p>
39
+ </div>
40
+ `;
41
+ }
42
+
43
+ updateData() {
44
+ const demoData = PublisherManager.get("demoData");
45
+ const demoUsers = PublisherManager.get("demoUsers");
46
+ const randomIndex = Math.floor(Math.random() * demoUsers.get().length);
47
+ const randomUser = demoUsers.get()[randomIndex];
48
+ demoData.set({
49
+ firstName: randomUser.firstName,
50
+ lastName: randomUser.lastName,
51
+ count: (demoData.count.get() || 0) + 1,
52
+ });
53
+ }
54
+ }
55
+
56
+ @customElement("demo-bind-reflect")
57
+ export class DemoBindReflect extends LitElement {
58
+ static styles = [tailwind];
59
+
60
+ @bind("bindReflectDemo.count", { reflect: true })
61
+ @state()
62
+ withReflect: number = 0;
63
+
64
+ @bind("bindReflectDemo.count")
65
+ @state()
66
+ withoutReflect: number = 0;
67
+
68
+ connectedCallback() {
69
+ super.connectedCallback();
70
+ this.resetData();
71
+ }
72
+
73
+ resetData() {
74
+ PublisherManager.get("bindReflectDemo").set({ count: 0 });
75
+ }
76
+ render() {
77
+ return html`
78
+ <div class="mb-3">
79
+ from publisher : ${sub("bindReflectDemo.count")} <br />
80
+ from component with reflect : ${this.withReflect} <br />
81
+ from component without reflect : ${this.withoutReflect}
82
+ </div>
83
+ <sonic-button @click=${() => this.withReflect++}
84
+ >Increment with reflect</sonic-button
85
+ >
86
+ <sonic-button @click=${() => this.withoutReflect++}
87
+ >Increment without reflect</sonic-button
88
+ >
89
+ <sonic-button @click=${this.resetData}>Reset publisher data</sonic-button>
90
+ `;
91
+ }
92
+ }
93
+
94
+ type BindReflectDemoData = { count: number };
95
+ const bindReflectDemoKey = new DataProviderKey<BindReflectDemoData>("bindReflectDemo");
96
+
97
+ @customElement("demo-bind-key")
98
+ export class DemoBindKey extends LitElement {
99
+ static styles = [tailwind];
100
+
101
+ @bind(bindReflectDemoKey.count, { reflect: true })
102
+ @state()
103
+ count: number = 0;
104
+
105
+ connectedCallback() {
106
+ super.connectedCallback();
107
+ PublisherManager.get("bindReflectDemo").set({ count: 0 });
108
+ }
109
+
110
+ render() {
111
+ return html`
112
+ <div class="mb-3">
113
+ <p>@bind with DataProviderKey&lt;number&gt; (type-safe): ${this.count}</p>
114
+ </div>
115
+ <sonic-button @click=${() => this.count++}>Increment</sonic-button>
116
+ `;
117
+ }
118
+ }
119
+
120
+ @customElement("demo-bind-dynamic")
121
+ export class DemoBindDynamic extends LitElement {
122
+ static styles = [tailwind];
123
+
124
+ @property({ type: String })
125
+ dataProvider: "demoUsers" | "demoUsersAlt" = "demoUsers";
126
+
127
+ @property({ type: Number })
128
+ userIndex: number = 1;
129
+
130
+ @bind("${dataProvider}.${userIndex}")
131
+ @state()
132
+ user: any = {};
133
+
134
+ updateUserIndex(e: Event) {
135
+ this.userIndex = parseInt((e.target as HTMLInputElement).value);
136
+ }
137
+
138
+ updateDataProvider(e: Event) {
139
+ this.dataProvider = (e.target as HTMLSelectElement).value as
140
+ | "demoUsers"
141
+ | "demoUsersAlt";
142
+ }
143
+
144
+ updateCurrentUserData() {
145
+ const usersPublisher = PublisherManager.get(this.dataProvider);
146
+ const userPublisher = Objects.traverse(usersPublisher, [
147
+ String(this.userIndex),
148
+ ]) as PublisherProxy;
149
+
150
+ if (userPublisher) {
151
+ const randomNames = [
152
+ { firstName: "Alice", lastName: "Wonder" },
153
+ { firstName: "Bob", lastName: "Builder" },
154
+ { firstName: "Charlie", lastName: "Chaplin" },
155
+ { firstName: "Diana", lastName: "Prince" },
156
+ { firstName: "Eve", lastName: "Adams" },
157
+ ];
158
+
159
+ const randomName =
160
+ randomNames[Math.floor(Math.random() * randomNames.length)];
161
+ const randomEmail = `${randomName.firstName.toLowerCase()}.${randomName.lastName.toLowerCase()}@example.com`;
162
+
163
+ const currentUser = userPublisher.get() || {};
164
+ userPublisher.set({
165
+ ...currentUser,
166
+ firstName: randomName.firstName,
167
+ lastName: randomName.lastName,
168
+ email: randomEmail,
169
+ });
170
+ }
171
+ }
172
+
173
+ render() {
174
+ return html`
175
+ <div class="flex flex-col gap-2">
176
+ <sonic-select
177
+ .value=${this.dataProvider}
178
+ label="Users set"
179
+ @change=${this.updateDataProvider}
180
+ >
181
+ <option value="demoUsers">First set of users</option>
182
+ <option value="demoUsersAlt">Second set of users</option>
183
+ </sonic-select>
184
+ <sonic-input
185
+ type="number"
186
+ .value=${this.userIndex}
187
+ @input=${this.updateUserIndex}
188
+ min="0"
189
+ max="9"
190
+ label="Index"
191
+ class="block"
192
+ >
193
+ </sonic-input>
194
+ <sonic-button @click=${this.updateCurrentUserData}
195
+ >Update current user data</sonic-button
196
+ >
197
+ <div class="flex flex-col gap-2 border p-2">
198
+ <div>
199
+ <sonic-icon name="user" library="heroicons"></sonic-icon>
200
+ ${this.user?.firstName} ${this.user?.lastName}
201
+ </div>
202
+ <div>
203
+ <sonic-icon name="envelope" library="heroicons"></sonic-icon>
204
+ ${this.user?.email}
205
+ </div>
206
+ </div>
207
+ </div>
208
+ `;
209
+ }
210
+ }
@@ -0,0 +1,45 @@
1
+ import type { APIConfiguration } from "@supersoniks/concorde/core/utils/api";
2
+ import type { ApiGetResult } from "@supersoniks/concorde/core/utils/api";
3
+ import { Endpoint } from "@supersoniks/concorde/core/utils/endpoint";
4
+ import { DataProviderKey } from "@supersoniks/concorde/core/utils/dataProviderKey";
5
+ import { PublisherManager } from "@supersoniks/concorde/core/utils/PublisherProxy";
6
+ import "./decorators-demo-init";
7
+
8
+ export type GeoCommuneRow = { nom: string; code: string };
9
+
10
+ export const geoApiDemoConfiguration: APIConfiguration = {
11
+ serviceURL: "https://geo.api.gouv.fr/",
12
+ token: null,
13
+ userName: null,
14
+ password: null,
15
+ authToken: null,
16
+ tokenProvider: null,
17
+ };
18
+
19
+ const docsDemoGeoApiConfigurationId = "docsDemoGeoApiConfiguration";
20
+ PublisherManager.get(docsDemoGeoApiConfigurationId).set(geoApiDemoConfiguration);
21
+
22
+ export const docsDemoGeoApiConfigurationKey = new DataProviderKey<APIConfiguration>(
23
+ docsDemoGeoApiConfigurationId,
24
+ );
25
+
26
+ export const geoCommunesApiGetEndpoint = new Endpoint<GeoCommuneRow[]>(
27
+ "communes?limit=5&fields=nom,code",
28
+ );
29
+
30
+ export const docsDemoDynApiConfKeyTemplate = new DataProviderKey<APIConfiguration>(
31
+ "docsDemoDynApiConf${configSlot}",
32
+ );
33
+
34
+ PublisherManager.get("docsDemoDynApiConfA").set(geoApiDemoConfiguration);
35
+ PublisherManager.get("docsDemoDynApiConfB").set({
36
+ ...geoApiDemoConfiguration,
37
+ serviceURL: "https://geo.api.gouv.fr/",
38
+ });
39
+
40
+ export const geoCommunesApiGetEndpointDynamic = new Endpoint<GeoCommuneRow[]>(
41
+ "communes?limit=${communeLimit}&fields=nom,code",
42
+ );
43
+
44
+ export const geoCommunesApiGetPublishKey =
45
+ new DataProviderKey<ApiGetResult<GeoCommuneRow[]>>(geoCommunesApiGetEndpoint.path);
@@ -0,0 +1,228 @@
1
+ import { PublisherManager } from "@supersoniks/concorde/core/utils/PublisherProxy";
2
+
3
+ export const ensurePublisherValue = <T>(
4
+ publisherId: string,
5
+ defaultValue: T,
6
+ ): void => {
7
+ const publisher = PublisherManager.get(publisherId);
8
+ const currentValue =
9
+ typeof publisher.get === "function" ? publisher.get() : undefined;
10
+
11
+ const isUnset =
12
+ currentValue === undefined ||
13
+ currentValue === null ||
14
+ (typeof currentValue === "object" &&
15
+ !Array.isArray(currentValue) &&
16
+ Object.keys(currentValue).length === 0);
17
+
18
+ if (isUnset) {
19
+ publisher.set(defaultValue as T);
20
+ }
21
+ };
22
+
23
+ export const initializeDecoratorsDemoData = () => {
24
+ ensurePublisherValue("demoData", {
25
+ title: "Initial Title",
26
+ user: { name: "Initial User" },
27
+ count: 0,
28
+ });
29
+
30
+ ensurePublisherValue("demoUser", {
31
+ name: "Demo User",
32
+ email: "demo@example.com",
33
+ });
34
+
35
+ ensurePublisherValue("demoSettings", {
36
+ theme: "light",
37
+ language: "en",
38
+ });
39
+
40
+ ensurePublisherValue("demoUserSettings", {
41
+ theme: "light",
42
+ language: "en",
43
+ });
44
+
45
+ ensurePublisherValue("autoValue1", 10);
46
+ ensurePublisherValue("autoValue2", 20);
47
+ ensurePublisherValue("waitAncestorDemo", {
48
+ message: "Context from ancestor",
49
+ });
50
+
51
+ ensurePublisherValue("combinedData", { title: "Combined Title" });
52
+ ensurePublisherValue("combinedUser", { name: "Combined User" });
53
+ ensurePublisherValue("combinedSettings", { theme: "dark" });
54
+
55
+ ensurePublisherValue("reflectData", {
56
+ title: "Initial Reflected Title",
57
+ count: 0,
58
+ });
59
+
60
+ ensurePublisherValue("publishDemo", {
61
+ email: "",
62
+ message: "",
63
+ });
64
+
65
+ ensurePublisherValue("dynamicProfiles", {
66
+ alpha: { info: { title: "Profil Alpha" } },
67
+ beta: { info: { title: "Profil Beta" } },
68
+ });
69
+
70
+ ensurePublisherValue("dynamicProfilesAlt", {
71
+ alpha: { info: { title: "Profil Alpha (Alt)" } },
72
+ beta: { info: { title: "Profil Beta (Alt)" } },
73
+ });
74
+
75
+ ensurePublisherValue("demoUsers", [
76
+ {
77
+ id: 1,
78
+ firstName: "Alice",
79
+ lastName: "Smith",
80
+ email: "alice.smith@example.com",
81
+ },
82
+ {
83
+ id: 2,
84
+ firstName: "Bob",
85
+ lastName: "Johnson",
86
+ email: "bob.johnson@example.com",
87
+ },
88
+ {
89
+ id: 3,
90
+ firstName: "Carol",
91
+ lastName: "Williams",
92
+ email: "carol.williams@example.com",
93
+ },
94
+ {
95
+ id: 4,
96
+ firstName: "David",
97
+ lastName: "Brown",
98
+ email: "david.brown@example.com",
99
+ },
100
+ {
101
+ id: 5,
102
+ firstName: "Eve",
103
+ lastName: "Jones",
104
+ email: "eve.jones@example.com",
105
+ },
106
+ {
107
+ id: 6,
108
+ firstName: "Frank",
109
+ lastName: "Garcia",
110
+ email: "frank.garcia@example.com",
111
+ },
112
+ {
113
+ id: 7,
114
+ firstName: "Grace",
115
+ lastName: "Miller",
116
+ email: "grace.miller@example.com",
117
+ },
118
+ {
119
+ id: 8,
120
+ firstName: "Henry",
121
+ lastName: "Davis",
122
+ email: "henry.davis@example.com",
123
+ },
124
+ {
125
+ id: 9,
126
+ firstName: "Ivy",
127
+ lastName: "Martinez",
128
+ email: "ivy.martinez@example.com",
129
+ },
130
+ {
131
+ id: 10,
132
+ firstName: "Jack",
133
+ lastName: "Taylor",
134
+ email: "jack.taylor@example.com",
135
+ },
136
+ ]);
137
+
138
+ ensurePublisherValue("demoUsersAlt", [
139
+ {
140
+ id: 11,
141
+ firstName: "Sophie",
142
+ lastName: "Lindquist",
143
+ email: "sophie.lindquist@example.com",
144
+ },
145
+ {
146
+ id: 12,
147
+ firstName: "Mateo",
148
+ lastName: "Ortega",
149
+ email: "mateo.ortega@example.com",
150
+ },
151
+ {
152
+ id: 13,
153
+ firstName: "Jin",
154
+ lastName: "Park",
155
+ email: "jin.park@example.com",
156
+ },
157
+ {
158
+ id: 14,
159
+ firstName: "Fatima",
160
+ lastName: "El-Sayed",
161
+ email: "fatima.el-sayed@example.com",
162
+ },
163
+ {
164
+ id: 15,
165
+ firstName: "Lars",
166
+ lastName: "Johansson",
167
+ email: "lars.johansson@example.com",
168
+ },
169
+ {
170
+ id: 16,
171
+ firstName: "Amara",
172
+ lastName: "Singh",
173
+ email: "amara.singh@example.com",
174
+ },
175
+ {
176
+ id: 17,
177
+ firstName: "Zuri",
178
+ lastName: "Okafor",
179
+ email: "zuri.okafor@example.com",
180
+ },
181
+ {
182
+ id: 18,
183
+ firstName: "Luca",
184
+ lastName: "Rossi",
185
+ email: "luca.rossi@example.com",
186
+ },
187
+ {
188
+ id: 19,
189
+ firstName: "Ava",
190
+ lastName: "Murphy",
191
+ email: "ava.murphy@example.com",
192
+ },
193
+ {
194
+ id: 20,
195
+ firstName: "Noah",
196
+ lastName: "Keller",
197
+ email: "noah.keller@example.com",
198
+ },
199
+ ]);
200
+
201
+ ensurePublisherValue("demoUsersSettings", [
202
+ { theme: "light", language: "en" },
203
+ { theme: "dark", language: "fr" },
204
+ { theme: "auto", language: "es" },
205
+ { theme: "light", language: "en" },
206
+ { theme: "dark", language: "fr" },
207
+ { theme: "auto", language: "es" },
208
+ { theme: "light", language: "en" },
209
+ { theme: "dark", language: "fr" },
210
+ { theme: "auto", language: "es" },
211
+ { theme: "light", language: "en" },
212
+ ]);
213
+
214
+ ensurePublisherValue("demoUsersAltSettings", [
215
+ { theme: "dark", language: "de" },
216
+ { theme: "light", language: "it" },
217
+ { theme: "auto", language: "ja" },
218
+ { theme: "dark", language: "pt" },
219
+ { theme: "light", language: "ru" },
220
+ { theme: "auto", language: "zh" },
221
+ { theme: "dark", language: "ar" },
222
+ { theme: "light", language: "sv" },
223
+ { theme: "auto", language: "nl" },
224
+ { theme: "dark", language: "pl" },
225
+ ]);
226
+ };
227
+
228
+ initializeDecoratorsDemoData();