@lilaquadrat/design-core 0.2.2 → 0.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.
Files changed (78) hide show
  1. package/README.md +71 -3
  2. package/html/index.server.html +1 -8
  3. package/package.json +53 -53
  4. package/src/client-entry.ts +8 -8
  5. package/src/components/partials/error.partial.vue +19 -19
  6. package/src/components/partials/main-components.partial.vue +75 -70
  7. package/src/components/partials/qrcode.partial.vue +8 -8
  8. package/src/functions/AuthProviderFactory.ts +30 -0
  9. package/src/functions/PaymenyProviderFactory.ts +11 -11
  10. package/src/functions/auth0.provider.ts +75 -0
  11. package/src/functions/keycloak.provider.ts +228 -0
  12. package/src/functions/lila-dom.ts +50 -50
  13. package/src/functions/shopify.provider.ts +176 -154
  14. package/src/functions/stripe.provider.ts +120 -108
  15. package/src/globals.d.ts +1 -2
  16. package/src/index.ts +9 -7
  17. package/src/interfaces/AuthCallbackResult.interface.ts +5 -0
  18. package/src/interfaces/AuthConfig.interface.ts +13 -0
  19. package/src/interfaces/AuthProvider.interface.ts +15 -0
  20. package/src/interfaces/FrontendConfig.interface.ts +11 -40
  21. package/src/interfaces/GenericEvents.interface.ts +1 -1
  22. package/src/interfaces/IdTokenExtended.interface.ts +13 -4
  23. package/src/interfaces/PaymentProvider.interface.ts +2 -2
  24. package/src/interfaces/RenderOptions.interface.ts +12 -0
  25. package/src/libs/ActionNotice.ts +125 -125
  26. package/src/libs/Models.class.ts +219 -221
  27. package/src/main.ts +41 -36
  28. package/src/mixins/createCookieString.ts +50 -36
  29. package/src/mixins/createModelDeclaration.ts +22 -19
  30. package/src/mixins/createRouter.ts +12 -12
  31. package/src/mixins/date.ts +4 -2
  32. package/src/mixins/formatSize.ts +5 -5
  33. package/src/mixins/getAnchor.ts +1 -1
  34. package/src/mixins/getRoutes.ts +13 -25
  35. package/src/mixins/hasSlotContent.ts +22 -16
  36. package/src/mixins/hooks.ts +101 -60
  37. package/src/mixins/loadComponents.ts +60 -58
  38. package/src/mixins/logger.ts +17 -13
  39. package/src/mixins/replaceVariables.ts +10 -8
  40. package/src/mixins/scroll.ts +61 -45
  41. package/src/models/Address.model.ts +7 -7
  42. package/src/models/Contact.model.ts +14 -14
  43. package/src/plugins/analytics.ts +198 -0
  44. package/src/plugins/auth.ts +74 -60
  45. package/src/plugins/currency.ts +10 -10
  46. package/src/plugins/events.ts +101 -97
  47. package/src/plugins/filters.ts +21 -18
  48. package/src/plugins/replacer.ts +7 -6
  49. package/src/plugins/signupFlow.ts +45 -43
  50. package/src/plugins/traceable.ts +28 -26
  51. package/src/plugins/translations.ts +9 -9
  52. package/src/plugins/youtube.ts +39 -34
  53. package/src/routes.ts +108 -108
  54. package/src/server-entry.ts +75 -77
  55. package/src/stores/calls.store.ts +14 -14
  56. package/src/stores/cart.store.ts +116 -107
  57. package/src/stores/content.store.ts +87 -45
  58. package/src/stores/editor.store.ts +16 -16
  59. package/src/stores/files.store.ts +72 -72
  60. package/src/stores/main.store.ts +155 -109
  61. package/src/stores/user.store.ts +72 -68
  62. package/src/translations/de.ts +127 -127
  63. package/src/views/content.view.vue +81 -143
  64. package/src/views/download.view.vue +25 -23
  65. package/src/views/editor.view.vue +150 -125
  66. package/src/views/login.view.vue +35 -36
  67. package/src/views/signup-account.view.vue +14 -14
  68. package/tooling/cypress/config.ts +68 -54
  69. package/tooling/cypress/manifest-utils.mjs +34 -22
  70. package/tooling/cypress/run-parallel.mjs +41 -35
  71. package/tooling/cypress/support/commands.ts +458 -300
  72. package/tooling/eslint.config.js +1 -223
  73. package/tooling/preview.plugin.js +68 -68
  74. package/tooling/ssr-test/index.mjs +205 -203
  75. package/tooling/vite.d.ts +0 -6
  76. package/tooling/vite.js +170 -162
  77. package/src/interfaces/EditorConfiguration.interface.ts +0 -15
  78. package/tooling/stylelint.config.mjs +0 -24
package/README.md CHANGED
@@ -28,7 +28,7 @@ longer means porting framework changes by hand into every project.
28
28
  | `views/*` | content, editor, login, signup-account, download |
29
29
  | `partials/*` | client-only, main-components, error, qrcode, action, mediadetection |
30
30
  | `translations/de` | framework wording only - validation, lists, files, signup, order |
31
- | `vite`, `eslint`, `stylelint`, `cypress` | build and test tooling |
31
+ | `vite`, `eslint`, `cypress` | build and test tooling |
32
32
 
33
33
  ## What is NOT in here, on purpose
34
34
 
@@ -125,13 +125,81 @@ import de from '@/translations/de';
125
125
  addMessages('de', de);
126
126
  ```
127
127
 
128
- ### eslint, stylelint, cypress
128
+ ### authentication
129
+
130
+ Authentication is selected by the runtime configuration, not by the Vue plugin.
131
+ The environment's `auth` configuration is carried into the rendered main store.
132
+ For Keycloak:
133
+
134
+ ```ts
135
+ auth: {
136
+ type: 'keycloak',
137
+ url: 'https://auth.example.com',
138
+ realm: 'studio',
139
+ clientId: 'design',
140
+ }
141
+ ```
142
+
143
+ Keycloak uses the authorization-code flow with PKCE. Register the app's URLs as
144
+ valid redirect URIs and its origin as a web origin on the public client. Explicit
145
+ login and signup return to `/login-callback` on the app's origin; `redirectUri`
146
+ can override it in the frontend auth configuration. Startup is passive by default:
147
+ opening or reloading a public page does not start a login redirect. Login and
148
+ signup redirects only happen when explicitly triggered; incoming authentication
149
+ callbacks are still processed during startup.
150
+
151
+ To restore an existing SSO session after a reload, explicitly set
152
+ `silentCheckSsoRedirectUri` to a consumer-hosted Keycloak silent-check page. The
153
+ core does not ship that page. This opts into an iframe-only SSO check, with
154
+ top-level redirect fallback disabled. If silent authentication is unavailable,
155
+ users must explicitly log in again. Without this configuration, sessions are not
156
+ automatically restored after a reload. Tokens stay in memory.
157
+
158
+ Auth0 configuration uses the same discriminator with its existing SDK options:
159
+
160
+ ```ts
161
+ auth: {
162
+ type: 'auth0',
163
+ options: {
164
+ domain: 'tenant.eu.auth0.com',
165
+ clientId: 'public-client-id',
166
+ authorizationParams: {
167
+ redirect_uri: 'https://app.example.com/login-callback',
168
+ audience: 'https://api.example.com',
169
+ },
170
+ },
171
+ }
172
+ ```
173
+
174
+ The shared environment schema currently describes Keycloak; the frontend's
175
+ `AuthConfig` additionally supports Auth0. Existing rendered `auth0Options` and
176
+ direct `auth.init(auth0Options)` calls remain supported. `auth` takes precedence
177
+ over legacy `auth0Options` when both are present. There are no built-in tenant
178
+ credentials or localhost callback URLs.
179
+
180
+ `auth` and `useAuth` from `plugins/auth` remain the provider-neutral entry points.
181
+ `functions/AuthProviderFactory` dynamically imports only the selected adapter;
182
+ the adapters own all runtime SDK imports. Do not statically import or re-export
183
+ the adapters from an application entry point or combine them in a vendor chunk.
184
+ Installing the SDKs does not load them in the browser: the consuming build emits
185
+ separate lazy chunks. With no auth configuration (or `initAuth: false`), neither
186
+ provider is initialized or loaded. Preview, editor and server startup skip auth.
187
+
188
+ Focused auth and browser chunk-graph tests (Node 22+, no live identity server required):
189
+
190
+ ```sh
191
+ yarn node --experimental-strip-types --test tests/auth.test.ts
192
+ ```
193
+
194
+ ### eslint, cypress
129
195
 
130
196
  ```js
131
197
  // eslint.config.js
132
- export { default } from '@lilaquadrat/design-core/eslint';
198
+ export { default } from '@lilaquadrat/frontend/eslint';
133
199
  ```
134
200
 
201
+ The `@lilaquadrat/design-core/eslint` export also forwards to this shared config.
202
+
135
203
  ```ts
136
204
  // cypress.config.ts
137
205
  import { createCypressConfig } from '@lilaquadrat/design-core/cypress';
@@ -4,16 +4,9 @@
4
4
  <head>
5
5
  <meta charset="UTF-8">
6
6
 
7
- <link rel="apple-touch-icon" sizes="180x180" href="<!--cdn-->/apple-touch-icon.png">
8
- <link rel="icon" type="image/png" sizes="32x32" href="<!--cdn-->/favicon-32x32.png">
9
- <link rel="icon" type="image/png" sizes="16x16" href="<!--cdn-->/favicon-16x16.png">
10
- <link rel="manifest" href="<!--cdn-->/site.webmanifest">
11
- <link rel="mask-icon" href="<!--cdn-->/safari-pinned-tab.svg" color="#5bbad5">
12
- <meta name="msapplication-TileColor" content="#da532c">
13
- <meta name="theme-color" content="#ffffff">
7
+ <!--metalinks-->
14
8
 
15
9
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
16
- <meta name="description" content="<!--description-->">
17
10
  <title><!--sitetitle--></title>
18
11
  <link rel="preconnect" href="<!--cdn-->">
19
12
  <link rel="stylesheet" href="<!--style-->">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lilaquadrat/design-core",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "framework layer shared by every lilaquadrat STUDIO design: app bootstrap, router, stores, plugins and build tooling",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -49,7 +49,6 @@
49
49
  "./html/*": "./html/*",
50
50
  "./vite": "./tooling/vite.js",
51
51
  "./eslint": "./tooling/eslint.config.js",
52
- "./stylelint": "./tooling/stylelint.config.mjs",
53
52
  "./cypress": "./tooling/cypress/config.ts",
54
53
  "./ssr-test": "./tooling/ssr-test/index.mjs",
55
54
  "./cypress/*": "./tooling/cypress/*"
@@ -61,27 +60,31 @@
61
60
  "release": "standard-version"
62
61
  },
63
62
  "peerDependencies": {
64
- "@auth0/auth0-spa-js": "^2.1.3",
65
- "@lilaquadrat/frontend": ">=0.2.0",
66
- "@lilaquadrat/interfaces": ">=1.48.0",
67
- "@lilaquadrat/sdk": "^0.1.2",
68
- "axios": "^1.9.0",
69
- "cypress": "^15.0.0",
70
- "dayjs": "^1.11.13",
71
- "eslint": "^9.25.1",
72
- "less": "^4.3.0",
63
+ "@auth0/auth0-spa-js": "^2.30.0",
64
+ "@lilaquadrat/frontend": ">=0.2.19",
65
+ "@lilaquadrat/interfaces": ">=1.57.0",
66
+ "@lilaquadrat/sdk": "^0.2.2",
67
+ "@vue/devtools-api": "^8.2.1",
68
+ "axios": "^1.21.0",
69
+ "cypress": "^16.0.0",
70
+ "dayjs": "^1.11.23",
71
+ "eslint": "^10.14.0",
72
+ "keycloak-js": "^26.2.5",
73
+ "less": "^4.9.1",
73
74
  "object-path": "^0.11.8",
74
- "pinia": "^3.0.2",
75
+ "pinia": "^4.1.0",
75
76
  "qrcode": "^1.5.4",
76
- "rollup-plugin-visualizer": "^5.14.0",
77
- "stylelint": "^16.19.1",
78
- "uuid": "^11.1.0",
79
- "vite": "^8.0.0",
80
- "vue": "^3.5.13",
81
- "vue-i18n": "^11.4.4",
82
- "vue-router": "^4.5.1"
77
+ "rollup-plugin-visualizer": "^7.1.1",
78
+ "uuid": "^14.0.3",
79
+ "vite": "^8.3.5",
80
+ "vue": "^3.5.44",
81
+ "vue-i18n": "^11.4.17",
82
+ "vue-router": "^5.4.0"
83
83
  },
84
84
  "peerDependenciesMeta": {
85
+ "@vue/devtools-api": {
86
+ "optional": true
87
+ },
85
88
  "cypress": {
86
89
  "optional": true
87
90
  },
@@ -94,52 +97,49 @@
94
97
  "rollup-plugin-visualizer": {
95
98
  "optional": true
96
99
  },
97
- "stylelint": {
98
- "optional": true
99
- },
100
100
  "vite": {
101
101
  "optional": true
102
102
  }
103
103
  },
104
104
  "devDependencies": {
105
- "@auth0/auth0-spa-js": "2.1.3",
106
- "@eslint/js": "^9.25.1",
107
- "@lilaquadrat/frontend": "^0.2.0",
108
- "@lilaquadrat/interfaces": "1.48.0",
109
- "@lilaquadrat/sdk": "^0.1.2",
110
- "@types/node": "^22.15.3",
105
+ "@auth0/auth0-spa-js": "2.30.0",
106
+ "@eslint/js": "^10.0.1",
107
+ "@lilaquadrat/frontend": "^0.2.19",
108
+ "@lilaquadrat/interfaces": "^2.0.0",
109
+ "@lilaquadrat/sdk": "^0.2.2",
110
+ "@types/node": "^26.6.6",
111
111
  "@types/object-path": "^0.11.4",
112
112
  "@types/qrcode": "^1.5.5",
113
- "@types/uuid": "^10.0.0",
114
113
  "@types/youtube": "^0.1.0",
115
- "@typescript-eslint/eslint-plugin": "^8.31.1",
116
- "@typescript-eslint/parser": "^8.31.1",
117
- "@vitejs/plugin-vue": "^5.2.3",
118
- "@vue/eslint-config-typescript": "^14.5.0",
119
- "@vue/tsconfig": "^0.7.0",
120
- "axios": "^1.9.0",
121
- "commitizen": "^4.3.1",
122
- "cypress": "^15.10.0",
114
+ "@typescript-eslint/eslint-plugin": "^8.72.1",
115
+ "@typescript-eslint/parser": "^8.72.1",
116
+ "@vitejs/plugin-vue": "^6.0.10",
117
+ "@vue/devtools-api": "^8.2.1",
118
+ "@vue/eslint-config-typescript": "^14.9.0",
119
+ "@vue/tsconfig": "^0.9.1",
120
+ "axios": "^1.21.0",
121
+ "commitizen": "^4.3.2",
122
+ "cypress": "^16.2.1",
123
123
  "cz-conventional-changelog": "^3.3.0",
124
- "dayjs": "^1.11.13",
125
- "eslint": "^9.25.1",
126
- "eslint-plugin-vue": "^10.1.0",
127
- "globals": "^16.0.0",
128
- "less": "^4.3.0",
124
+ "dayjs": "^1.11.23",
125
+ "eslint": "^10.14.0",
126
+ "eslint-plugin-vue": "^10.12.0",
127
+ "globals": "^17.14.0",
128
+ "keycloak-js": "^26.2.5",
129
+ "less": "^4.9.1",
129
130
  "object-path": "^0.11.8",
130
- "pinia": "^3.0.2",
131
+ "pinia": "^4.1.0",
131
132
  "qrcode": "^1.5.4",
132
- "rollup-plugin-visualizer": "^5.14.0",
133
+ "rollup-plugin-visualizer": "^7.1.1",
133
134
  "standard-version": "^9.5.0",
134
- "stylelint": "^16.19.1",
135
- "typescript": "~5.8.3",
136
- "uuid": "^11.1.0",
137
- "vite": "^8.0.15",
138
- "vue": "^3.5.13",
139
- "vue-eslint-parser": "^10.1.3",
140
- "vue-i18n": "^11.4.4",
141
- "vue-router": "^4.5.1",
142
- "vue-tsc": "^2.2.10"
135
+ "typescript": "~6.0.3",
136
+ "uuid": "^14.0.3",
137
+ "vite": "^8.3.5",
138
+ "vue": "^3.5.44",
139
+ "vue-eslint-parser": "^10.4.1",
140
+ "vue-i18n": "^11.4.17",
141
+ "vue-router": "^5.4.0",
142
+ "vue-tsc": "^3.3.14"
143
143
  },
144
144
  "config": {
145
145
  "commitizen": {
@@ -8,20 +8,20 @@ import { getAppInstance, type AppComponents } from './main';
8
8
  * boots the browser app. the project passes its own root component, module
9
9
  * registries and route sets - everything else is framework.
10
10
  */
11
- export function createClientEntry (options: { components: AppComponents, routes: RouteSets, initAuth?: boolean }) {
11
+ export function createClientEntry(options: { components: AppComponents, routes: RouteSets, initAuth?: boolean }) {
12
12
 
13
- const { app, router } = getAppInstance({}, getRoutes(options.routes), !!window.__INITIAL_STATE__, options.components);
13
+ const { app, router } = getAppInstance({}, getRoutes(options.routes), !!window.__INITIAL_STATE__, options.components);
14
14
 
15
- // the static preview has no backend: skip the auth0 init and the customer call
16
- hooks(router, { initAuth: options.initAuth ?? !__PREVIEW__ }, 'client');
15
+ // the static preview has no backend: skip auth init and the customer call
16
+ hooks(router, { initAuth: options.initAuth ?? !__PREVIEW__ }, 'client');
17
17
 
18
- router.isReady().then(() => {
18
+ router.isReady().then(() => {
19
19
 
20
- app.mount('#app');
20
+ app.mount('#app');
21
21
 
22
- });
22
+ });
23
23
 
24
- return { app, router };
24
+ return { app, router };
25
25
 
26
26
  }
27
27
 
@@ -17,21 +17,21 @@ const data = ref<SDKResponse<BasicData<Content>>>();
17
17
 
18
18
  watch(props, () => getContent());
19
19
 
20
- function getFilename () {
20
+ function getFilename() {
21
21
 
22
- if(props.hint) return props.hint;
22
+ if(props.hint) return props.hint;
23
23
 
24
- const nameArray: string[] = ['error', props.status.toString()];
24
+ const nameArray: string[] = ['error', props.status.toString()];
25
25
 
26
- if(props.type) nameArray.push(props.type);
26
+ if(props.type) nameArray.push(props.type);
27
27
 
28
- return nameArray.join('-');
28
+ return nameArray.join('-');
29
29
 
30
30
  }
31
31
 
32
- async function getContent () {
32
+ async function getContent() {
33
33
 
34
- data.value = await store.getContent({filename: getFilename()}, 'public') as SDKResponse<BasicData<Content>>;
34
+ data.value = await store.getContent({filename: getFilename()}, 'public') as SDKResponse<BasicData<Content>>;
35
35
 
36
36
  }
37
37
 
@@ -39,31 +39,31 @@ onBeforeMount(async () => await getContent());
39
39
 
40
40
  const useData = computed(() => {
41
41
 
42
- if(data?.value?.data?.modules) return data.value?.data;
42
+ if(data?.value?.data?.modules) return data.value?.data;
43
43
 
44
- if(store.staticData) {
44
+ if(store.staticData) {
45
45
 
46
- if(props.hint) {
46
+ if(props.hint) {
47
47
 
48
- return store.staticData[props.hint];
48
+ return store.staticData[props.hint];
49
49
 
50
- }
50
+ }
51
51
 
52
- if(props.status > 0) {
52
+ if(props.status > 0) {
53
53
 
54
- return store.staticData[props.status];
54
+ return store.staticData[props.status];
55
55
 
56
- }
56
+ }
57
57
 
58
- }
58
+ }
59
59
 
60
- return undefined;
60
+ return undefined;
61
61
 
62
62
  });
63
63
  const contentMerged = computed(() => {
64
64
 
65
- if(useData.value) return prepareContent(useData.value);
66
- return prepareContent({})
65
+ if(useData.value) return prepareContent(useData.value);
66
+ return prepareContent({})
67
67
 
68
68
  });
69
69
 
@@ -27,137 +27,142 @@ const isLocked = computed(() => contentType.value == 'members' && userStore.lock
27
27
  watch(route, () => getContent());
28
28
  watch(() => userStore.locked, () => {
29
29
 
30
- if(!userStore.locked) {
31
- getContent();
32
- }
30
+ if(!userStore.locked) {
31
+
32
+ getContent();
33
+
34
+ }
33
35
 
34
36
  });
35
37
 
36
38
  onBeforeMount(async () => await getContent());
37
39
  onServerPrefetch(() => getStoreContent());
38
40
 
39
- function getStoreContent () {
41
+ function getStoreContent() {
40
42
 
41
- const contentId = HelpersPlugin.getFilename(route.meta.contentType as 'public' | 'members', props.type);
42
- const storeContent = contentStore.findByFilename(contentId);
43
+ const contentId = HelpersPlugin.getFilename(route.meta.contentType as 'public' | 'members', props.type);
44
+ const storeContent = contentStore.findByFilename(contentId);
43
45
 
44
- if(!storeContent) return;
46
+ if(!storeContent) return;
45
47
 
46
- data.value = {
47
- data : storeContent,
48
- status: 200,
49
- };
48
+ data.value = {
49
+ data: storeContent,
50
+ status: 200,
51
+ };
50
52
 
51
- loading.value = 200;
53
+ loading.value = 200;
52
54
 
53
- dataMerged.value = mergeContent(data.value.data);
55
+ dataMerged.value = mergeContent(data.value.data);
54
56
 
55
57
  }
56
58
 
57
- async function getContent () {
59
+ async function getContent() {
58
60
 
59
- getStoreContent();
61
+ getStoreContent();
60
62
 
61
- const contentId = HelpersPlugin.getFilename(route.meta.contentType as 'public' | 'members', props.type);
63
+ const contentId = HelpersPlugin.getFilename(route.meta.contentType as 'public' | 'members', props.type);
62
64
 
63
- if(data.value?.data?.id === contentId) {
65
+ if(data.value?.data?.id === contentId) {
64
66
 
65
- return;
67
+ return;
66
68
 
67
- }
69
+ }
68
70
 
69
- if(isLocked.value) {
71
+ if(isLocked.value) {
70
72
 
71
- loading.value = 0;
72
- error.value = true;
73
+ loading.value = 0;
74
+ error.value = true;
73
75
 
74
- return;
75
- }
76
+ return;
77
+
78
+ }
76
79
 
77
- if(contentType.value !== typeCache.value) {
80
+ if(contentType.value !== typeCache.value) {
78
81
 
79
- loading.value = 0;
80
- error.value = false;
81
- data.value = undefined;
82
+ loading.value = 0;
83
+ error.value = false;
84
+ data.value = undefined;
82
85
 
83
- }
86
+ }
84
87
 
85
- const storeData = contentStore.findByFilename(contentId);
88
+ const storeData = contentStore.findByFilename(contentId);
86
89
 
87
- if(storeData) {
90
+ if(storeData) {
88
91
 
89
- data.value = {data: storeData, status: 200};
90
- loading.value = 200;
91
- return;
92
+ data.value = {data: storeData, status: 200};
93
+ loading.value = 200;
94
+ return;
92
95
 
93
- }
96
+ }
94
97
 
95
- // get content only if there is a difference between the current and the needed content
96
- if (data.value?.data?.id !== contentId && loading.value === 0) {
98
+ // get content only if there is a difference between the current and the needed content
99
+ if (data.value?.data?.id !== contentId && loading.value === 0) {
97
100
 
98
- loading.value = 100;
101
+ loading.value = 100;
99
102
 
100
- try {
103
+ try {
101
104
 
102
- data.value = await store.getContent({filename: contentId}, contentType.value) as SDKResponse<BasicData<Content>>;
103
- loading.value = data.value.status;
105
+ data.value = await store.getContent({filename: contentId}, contentType.value) as SDKResponse<BasicData<Content>>;
106
+ loading.value = data.value.status;
104
107
 
105
- } catch (e: any) {
108
+ } catch (e: any) {
106
109
 
107
- data.value = undefined;
108
- error.value = true;
109
- loading.value = e?.response?.status;
110
+ data.value = undefined;
111
+ error.value = true;
112
+ loading.value = e?.response?.status;
110
113
 
111
- }
114
+ }
112
115
 
113
- if(data.value?.status === 403 || data.value?.status === 401) {
116
+ if(data.value?.status === 403 || data.value?.status === 401) {
114
117
 
115
- error.value = true;
116
- loading.value = data.value?.status;
117
- data.value = undefined;
118
+ error.value = true;
119
+ loading.value = data.value?.status;
120
+ data.value = undefined;
118
121
 
119
- }
122
+ }
120
123
 
121
- typeCache.value = route.meta.contentType as string;
124
+ typeCache.value = route.meta.contentType as string;
122
125
 
123
- }
126
+ }
124
127
 
125
- if(data.value) {
128
+ if(data.value) {
126
129
 
127
- dataMerged.value = mergeContent(data.value?.data);
130
+ dataMerged.value = mergeContent(data.value?.data);
128
131
 
129
- } else {
132
+ } else {
130
133
 
131
- dataMerged.value = undefined;
134
+ dataMerged.value = undefined;
132
135
 
133
- }
136
+ }
134
137
 
135
138
  }
136
139
 
137
- function mergeContent (baseContent: BasicData<Content>) {
140
+ function mergeContent(baseContent: BasicData<Content>) {
138
141
 
139
- if(baseContent) {
142
+ if(baseContent) {
140
143
 
141
- const safeData = hardCopy(baseContent);
144
+ const safeData = hardCopy(baseContent);
142
145
 
143
- if(safeData.modules) {
144
- /**
146
+ if(safeData.modules) {
147
+
148
+ /**
145
149
  * content without generic data is the normal case for a static page, and
146
150
  * generateDataWithContent reads Object.keys of what it is given - so it
147
151
  * throws on undefined instead of returning nothing
148
152
  */
149
- if(safeData.genericData) {
153
+ if(safeData.genericData) {
150
154
 
151
- distributeGenericData(safeData.modules, generateDataWithContent(safeData.genericData as GenericData));
155
+ distributeGenericData(safeData.modules, generateDataWithContent(safeData.genericData as GenericData));
152
156
 
153
- }
154
- }
157
+ }
158
+
159
+ }
155
160
 
156
- return prepareContent(safeData);
161
+ return prepareContent(safeData);
157
162
 
158
- }
163
+ }
159
164
 
160
- return undefined;
165
+ return undefined;
161
166
 
162
167
  }
163
168
 
@@ -9,21 +9,21 @@ const qrCanvas = ref<HTMLCanvasElement | null>(null);
9
9
 
10
10
  onMounted(() => {
11
11
 
12
- renderQRCode();
12
+ renderQRCode();
13
13
 
14
14
  });
15
15
 
16
16
  const renderQRCode = () => {
17
17
 
18
- if (qrCanvas.value) {
18
+ if (qrCanvas.value) {
19
19
 
20
- QRCode.toCanvas(qrCanvas.value, props.content, {
21
- errorCorrectionLevel: 'M',
22
- margin : 5,
23
- width : 250,
24
- })
20
+ QRCode.toCanvas(qrCanvas.value, props.content, {
21
+ errorCorrectionLevel: 'M',
22
+ margin: 5,
23
+ width: 250,
24
+ })
25
25
 
26
- }
26
+ }
27
27
 
28
28
  };
29
29
 
@@ -0,0 +1,30 @@
1
+ import type AuthConfig from '../interfaces/AuthConfig.interface';
2
+ import type AuthProvider from '../interfaces/AuthProvider.interface';
3
+
4
+ export default async function AuthProviderFactory(config: AuthConfig): Promise<AuthProvider> {
5
+
6
+ // These targets inline dynamic imports, so eliminate the SDK branches at build time.
7
+ if (import.meta.env.SSR || (typeof __PREVIEW__ !== 'undefined' && __PREVIEW__)) {
8
+
9
+ throw new Error('AUTH_UNAVAILABLE_FOR_TARGET');
10
+
11
+ }
12
+
13
+ switch (config.type) {
14
+ case 'auth0': {
15
+
16
+ const { default: Auth0Provider } = await import('./auth0.provider');
17
+ return new Auth0Provider(config.options);
18
+
19
+ }
20
+ case 'keycloak': {
21
+
22
+ const { default: KeycloakProvider } = await import('./keycloak.provider');
23
+ return new KeycloakProvider(config);
24
+
25
+ }
26
+ default:
27
+ throw new Error('AUTH_PROVIDER_UNAVAILABLE');
28
+ }
29
+
30
+ }