@lilaquadrat/design-core 0.2.1 → 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 (80) hide show
  1. package/README.md +76 -3
  2. package/html/index.server.html +1 -8
  3. package/package.json +54 -54
  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 +132 -0
  74. package/tooling/ssr-test/index.mjs +205 -203
  75. package/tooling/vite.d.ts +36 -0
  76. package/tooling/vite.js +234 -0
  77. package/src/interfaces/EditorConfiguration.interface.ts +0 -15
  78. package/tooling/preview.plugin.ts +0 -134
  79. package/tooling/stylelint.config.mjs +0 -24
  80. package/tooling/vite.ts +0 -260
@@ -0,0 +1,234 @@
1
+ import { fileURLToPath, URL } from 'node:url';
2
+ import { existsSync } from 'node:fs';
3
+ import { resolve } from 'node:path';
4
+
5
+ import { defineConfig } from 'vite';
6
+ import vue from '@vitejs/plugin-vue';
7
+
8
+ import { visualizer } from 'rollup-plugin-visualizer';
9
+
10
+ import previewBundle, { dropPreviewAssets, previewBuildOptions } from './preview.plugin.js';
11
+
12
+ function resolveTarget(mode) {
13
+
14
+ if(mode === 'production') return 'live';
15
+ if(mode === 'next') return 'next';
16
+
17
+ return 'local';
18
+
19
+ }
20
+
21
+ /**
22
+ * the html templates the ssr build emits alongside the bundle. a project may
23
+ * override either by keeping a file of the same name in its root, otherwise the
24
+ * package template is used.
25
+ */
26
+ function resolveTemplate(root, name) {
27
+
28
+ const projectTemplate = resolve(root, name);
29
+
30
+ if(existsSync(projectTemplate)) return projectTemplate;
31
+
32
+ return fileURLToPath(new URL(`../html/${name}`, import.meta.url));
33
+
34
+ }
35
+
36
+ export function createViteConfig(options) {
37
+
38
+ /**
39
+ * absolute on purpose: the globalVars below are prepended to every less file,
40
+ * including the ones inside the package, where a project relative path would
41
+ * resolve against node_modules
42
+ */
43
+ const lessDir = resolve(options.root, options.lessDir ?? './src/assets/less');
44
+ const ssrEntry = options.ssrEntry ?? '/src/server-entry.ts';
45
+ const ssrFixturesEntry = options.ssrFixturesEntry ?? '/src/ssr-test.fixtures.ts';
46
+
47
+ return defineConfig((settings) => {
48
+
49
+ const target = resolveTarget(settings.mode);
50
+ const isProduction = target === 'live';
51
+ /**
52
+ * shareable static module gallery: preview routes, hash history, no auth and
53
+ * inlined assets, so the output runs from file:// without a server
54
+ */
55
+ const isPreview = settings.mode === 'preview';
56
+ /**
57
+ * a second ssr bundle holding nothing but the design's fixtures, so the ssr
58
+ * preflight can read viewData and the registries while still rendering
59
+ * through the real dist/server build
60
+ */
61
+ const isSsrTest = settings.mode === 'ssr-test';
62
+ /**
63
+ * builds meant to be handed out rather than debugged: minified, no
64
+ * sourcemaps, no vue dev instrumentation
65
+ */
66
+ const isOptimized = isProduction || isPreview;
67
+ // const config = options.config[target];
68
+ const viteConfig = {
69
+ plugins: [
70
+ vue(),
71
+ visualizer(),
72
+ ...isPreview ? [previewBundle()] : [dropPreviewAssets()]
73
+ ],
74
+ base: './',
75
+ server: {
76
+ host: '0.0.0.0',
77
+ },
78
+ optimizeDeps: {
79
+ // design-core ships source, and its less needs the project variables
80
+ // injected below - a prebundle would not see them.
81
+ //
82
+ // @lilaquadrat/frontend rides along because design-core imports it:
83
+ // prebundling it there and serving it raw here would give the resize and
84
+ // inview singletons two module identities, and a second scroll listener
85
+ // with it
86
+ exclude: ['@lilaquadrat/design-core', '@lilaquadrat/frontend']
87
+ },
88
+ build: {
89
+ cssCodeSplit: false,
90
+ cssMinify: isOptimized,
91
+ sourcemap: !isOptimized,
92
+ minify: isOptimized,
93
+ rolldownOptions: {
94
+ output: {
95
+ dir: 'dist/app',
96
+ // rolldown chunking: only auth0 and qrcode get their own files,
97
+ // every other dependency stays in the entry. minSize 0 forces a
98
+ // group to be captured regardless of size; the global minSize keeps
99
+ // automatic grouping from emitting hundreds of tiny chunks.
100
+ codeSplitting: {
101
+ minSize: 30_000,
102
+ groups: [
103
+ { name: 'auth0', test: /[\\/]node_modules[\\/]@auth0[\\/]/, minSize: 0 },
104
+ { name: 'qrcode', test: /[\\/]node_modules[\\/]qrcode[\\/]/, minSize: 0 },
105
+ ],
106
+ },
107
+ assetFileNames: (assetInfo) => {
108
+
109
+ if (assetInfo.name?.endsWith('woff') || assetInfo.name?.endsWith('png')) {
110
+
111
+ return '[name][extname]';
112
+
113
+ }
114
+
115
+ return '[name]-[hash][extname]';
116
+
117
+ },
118
+ chunkFileNames: '[name]-[hash].js',
119
+ entryFileNames: '[name]-[hash].js',
120
+ }
121
+ }
122
+ },
123
+ css: {
124
+ devSourcemap: true,
125
+ preprocessorOptions: {
126
+ less: {
127
+ sourceMap: true,
128
+ globalVars: {
129
+ globalVariables: `true; @import (reference) "${lessDir}/variables.less";`,
130
+ globalMixins: `true; @import (reference) "${lessDir}/mixins.less";`,
131
+ globalFonts: `true; @import (reference) "${lessDir}/fonts.less";`,
132
+ },
133
+ }
134
+ }
135
+ },
136
+ resolve: {
137
+ alias: {
138
+ '~fonts': resolve(options.root, 'src/assets/fonts'),
139
+ '@': resolve(options.root, 'src'),
140
+ },
141
+ /**
142
+ * a linked @lilaquadrat/design-core resolves these from its own
143
+ * node_modules, which would give the app a second vue and a second
144
+ * pinia - one app instance registering into a store nobody reads.
145
+ * dedupe pins every shared runtime to the project copy.
146
+ */
147
+ dedupe: [
148
+ 'vue',
149
+ 'vue-router',
150
+ 'vue-i18n',
151
+ 'pinia',
152
+ // holds a static request cache, so a second copy would cache twice
153
+ '@lilaquadrat/sdk',
154
+ // resize and inview are singletons: a second copy means a second
155
+ // scroll listener and a second set of refs nobody reads
156
+ '@lilaquadrat/frontend',
157
+ '@auth0/auth0-spa-js',
158
+ 'axios',
159
+ 'dayjs',
160
+ ],
161
+ /**
162
+ * @lilaquadrat/studio is deliberately NOT deduped: it is the backend
163
+ * package and a project may still hold a copy for other reasons, while
164
+ * a second one costs nothing here.
165
+ *
166
+ * @lilaquadrat/interfaces is types only, so it has nothing to dedupe.
167
+ */
168
+ },
169
+ define: {
170
+ // '__FRONTEND_CONFIG__' : JSON.stringify(config),
171
+ '__TARGET__': JSON.stringify(target),
172
+ '__PREVIEW__': JSON.stringify(isPreview),
173
+ __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: isOptimized ? 'false' : 'true',
174
+ __VUE_PROD_DEVTOOLS__: isOptimized ? 'false' : 'true',
175
+ ...options.define
176
+ }
177
+ };
178
+
179
+ if (isPreview) {
180
+
181
+ viteConfig.build = previewBuildOptions(viteConfig.build);
182
+
183
+ }
184
+
185
+ if (settings.isSsrBuild) {
186
+
187
+ viteConfig.build = {
188
+ ...viteConfig.build,
189
+ rolldownOptions: {
190
+ input: isSsrTest ? ssrFixturesEntry : ssrEntry,
191
+ plugins: isSsrTest
192
+ ? []
193
+ : [
194
+ {
195
+ name: 'emit-html-templates',
196
+ async generateBundle() {
197
+
198
+ const { readFile } = await import('node:fs/promises');
199
+ const [mailHtml, serverHtml] = await Promise.all([
200
+ readFile(resolveTemplate(options.root, 'index.mail.html'), 'utf-8'),
201
+ readFile(resolveTemplate(options.root, 'index.server.html'), 'utf-8'),
202
+ ]);
203
+
204
+ this.emitFile({ type: 'asset', fileName: 'index.mail.html', source: mailHtml });
205
+ this.emitFile({ type: 'asset', fileName: 'index.server.html', source: serverHtml });
206
+
207
+ }
208
+ }
209
+ ],
210
+ output: {
211
+ ...viteConfig.build?.rolldownOptions?.output,
212
+ codeSplitting: false,
213
+ dir: isSsrTest ? 'dist/ssr-test' : 'dist/server',
214
+ entryFileNames: '[name].js',
215
+ }
216
+ },
217
+ ssrManifest: !isSsrTest,
218
+ }
219
+ viteConfig.ssr = {
220
+ target: 'webworker',
221
+ noExternal: true,
222
+ external: ['node:stream', 'http', 'https', 'crypto', 'path', 'highlight.js'],
223
+ }
224
+
225
+ }
226
+
227
+ return viteConfig;
228
+
229
+ });
230
+
231
+ }
232
+
233
+ export default createViteConfig;
234
+ export { previewBundle, dropPreviewAssets, previewBuildOptions };
@@ -1,15 +0,0 @@
1
- export interface EditorTitleDescription {
2
- short?: string
3
- full?: string
4
- }
5
- export default interface EditorConfiguration {
6
-
7
- editorUrl?: string
8
- breakpointTablet?: string
9
- breakpointDesktop?: string
10
- breakpointWide?: string
11
- preloadImages?: boolean
12
- title?: EditorTitleDescription
13
- description?: EditorTitleDescription
14
-
15
- }
@@ -1,134 +0,0 @@
1
- import type { Plugin, UserConfig } from 'vite';
2
-
3
- const OUTPUT_DIR = 'dist/preview';
4
- const PREVIEW_ASSET_DIR = 'previewAssets';
5
-
6
- function escapeRegExp (input: string) {
7
-
8
- return input.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
9
-
10
- }
11
-
12
- /**
13
- * drops the gallery fixture images from every build that is not the preview.
14
- *
15
- * the viewData fixtures import them statically, and vite emits an imported asset
16
- * while transforming - so even though rolldown tree shakes preview.view.vue out
17
- * of the app bundle, the images survive as orphans nobody references.
18
- */
19
- export function dropPreviewAssets (): Plugin {
20
-
21
- return {
22
- name : 'drop-preview-assets',
23
- enforce: 'post',
24
- apply : 'build',
25
- generateBundle (_options, bundle: Record<string, any>) {
26
-
27
- Object.keys(bundle).forEach((fileName) => {
28
-
29
- const single = bundle[fileName];
30
-
31
- if(single.type !== 'asset') return;
32
-
33
- const origins: string[] = [single.originalFileName, ...single.originalFileNames ?? []].filter(Boolean);
34
-
35
- if(origins.some((origin) => origin.includes(PREVIEW_ASSET_DIR))) delete bundle[fileName];
36
-
37
- });
38
-
39
- }
40
- };
41
-
42
- }
43
-
44
- /**
45
- * build overrides for the shareable static gallery (yarn build:preview).
46
- *
47
- * everything here exists because the output is opened straight from disk, where
48
- * each file is its own opaque origin.
49
- */
50
- export function previewBuildOptions (base: UserConfig['build']): UserConfig['build'] {
51
-
52
- return {
53
- ...base,
54
- /**
55
- * inline fonts and images as data URIs: browsers block the font fetches a
56
- * separate .woff would need
57
- */
58
- assetsInlineLimit: 512 * 1024,
59
- rolldownOptions : {
60
- ...base?.rolldownOptions,
61
- output: {
62
- ...base?.rolldownOptions?.output,
63
- // a single classic script: file:// blocks `type="module"` as cross origin
64
- dir : OUTPUT_DIR,
65
- format : 'iife',
66
- codeSplitting : false,
67
- entryFileNames: '[name].js',
68
- }
69
- }
70
- };
71
-
72
- }
73
-
74
- /**
75
- * folds the script and the stylesheet into index.html, so the preview is a self
76
- * contained file that opens over file:// with no server.
77
- */
78
- export default function previewBundle (): Plugin {
79
-
80
- return {
81
- name : 'preview-bundle',
82
- enforce: 'post',
83
- apply : 'build',
84
- generateBundle (_options, bundle: Record<string, any>) {
85
-
86
- const html = bundle['index.html'];
87
-
88
- if(!html) return;
89
-
90
- let source = html.source.toString();
91
- let script = '';
92
-
93
- Object.keys(bundle).forEach((fileName) => {
94
-
95
- const single = bundle[fileName];
96
-
97
- if(fileName === 'index.html') return;
98
-
99
- if(single.type === 'chunk') {
100
-
101
- // a literal </script> inside the code would end the tag early
102
- script += single.code.replace(/<\/script>/gi, '<\\/script>');
103
- source = source.replace(new RegExp(`<script[^>]*src="[^"]*${escapeRegExp(fileName)}"[^>]*></script>\\s*`), '');
104
- delete bundle[fileName];
105
- return;
106
-
107
- }
108
-
109
- if(fileName.endsWith('.css')) {
110
-
111
- // replacer functions only: a replacement string would expand $& and
112
- // $\` in the asset as substitution patterns
113
- source = source.replace(new RegExp(`<link[^>]*href="[^"]*${escapeRegExp(fileName)}"[^>]*>`), () => `<style>${single.source}</style>`);
114
- delete bundle[fileName];
115
-
116
- }
117
-
118
- });
119
-
120
- source = source.replace(/<link[^>]*rel="modulepreload"[^>]*>\s*/g, '');
121
- // the manifest is the one head asset a file:// origin cannot fetch
122
- source = source.replace(/<link[^>]*rel="manifest"[^>]*>\s*/g, '');
123
- Object.keys(bundle).filter((fileName) => fileName.endsWith('.webmanifest')).forEach((fileName) => delete bundle[fileName]);
124
-
125
- /**
126
- * at the end of the body, not in place: an inline script has no `defer`,
127
- * so in the head it would run before #app exists
128
- */
129
- html.source = source.replace('</body>', () => `<script>${script}</script>\n</body>`);
130
-
131
- }
132
- };
133
-
134
- }
@@ -1,24 +0,0 @@
1
- /** @type {import('stylelint').Config} */
2
- export default {
3
- 'extends': [
4
- 'stylelint-config-html',
5
- 'stylelint-config-recommended-vue'
6
- ],
7
- 'plugins': [
8
- 'stylelint-order'
9
- ],
10
- 'overrides': [
11
- {
12
- 'files' : ['*.vue', '**/*.vue'],
13
- 'customSyntax': 'postcss-html'
14
- },
15
- {
16
- 'files' : ['*.less', '**/*.less'],
17
- 'customSyntax': 'postcss-less'
18
- }
19
- ],
20
- 'rules': {
21
- 'media-query-no-invalid' : null,
22
- 'declaration-property-value-no-unknown': null
23
- }
24
- }
package/tooling/vite.ts DELETED
@@ -1,260 +0,0 @@
1
- import { fileURLToPath, URL } from 'node:url';
2
- import { existsSync } from 'node:fs';
3
- import { resolve } from 'node:path';
4
-
5
- import { defineConfig, type UserConfig } from 'vite';
6
- import vue from '@vitejs/plugin-vue';
7
-
8
- import { visualizer } from 'rollup-plugin-visualizer';
9
-
10
- import previewBundle, { dropPreviewAssets, previewBuildOptions } from './preview.plugin.ts';
11
-
12
- export type Target = 'local' | 'next' | 'live';
13
-
14
- export interface ViteFactoryOptions {
15
- /**
16
- * the project config keyed by target, as exported from its own config.ts.
17
- * it is only serialised into __FRONTEND_CONFIG__, so its shape is the
18
- * project's business
19
- */
20
- config: Record<Target, unknown>
21
- /**
22
- * absolute path to the project root (the folder holding index.html)
23
- */
24
- root: string
25
- /**
26
- * project relative path to the less folder holding variables, mixins and
27
- * fonts - these are the design and never ship with the package
28
- */
29
- lessDir?: string
30
- /**
31
- * project relative entry for the ssr build
32
- */
33
- ssrEntry?: string
34
- /**
35
- * project relative entry for the ssr preflight fixtures (mode ssr-test).
36
- * it exports the design's viewData and module registries so the test suite
37
- * can read them without a bundler of its own
38
- */
39
- ssrFixturesEntry?: string
40
- /**
41
- * additional defines merged over the framework ones
42
- */
43
- define?: Record<string, string>
44
- }
45
-
46
- function resolveTarget (mode: string): Target {
47
-
48
- if(mode === 'production') return 'live';
49
- if(mode === 'next') return 'next';
50
-
51
- return 'local';
52
-
53
- }
54
-
55
- /**
56
- * the html templates the ssr build emits alongside the bundle. a project may
57
- * override either by keeping a file of the same name in its root, otherwise the
58
- * package template is used.
59
- */
60
- function resolveTemplate (root: string, name: string) {
61
-
62
- const projectTemplate = resolve(root, name);
63
-
64
- if(existsSync(projectTemplate)) return projectTemplate;
65
-
66
- return fileURLToPath(new URL(`../html/${name}`, import.meta.url));
67
-
68
- }
69
-
70
- export function createViteConfig (options: ViteFactoryOptions) {
71
-
72
- /**
73
- * absolute on purpose: the globalVars below are prepended to every less file,
74
- * including the ones inside the package, where a project relative path would
75
- * resolve against node_modules
76
- */
77
- const lessDir = resolve(options.root, options.lessDir ?? './src/assets/less');
78
- const ssrEntry = options.ssrEntry ?? '/src/server-entry.ts';
79
- const ssrFixturesEntry = options.ssrFixturesEntry ?? '/src/ssr-test.fixtures.ts';
80
-
81
- return defineConfig((settings): UserConfig => {
82
-
83
- const target = resolveTarget(settings.mode);
84
- const isProduction = target === 'live';
85
- /**
86
- * shareable static module gallery: preview routes, hash history, no auth and
87
- * inlined assets, so the output runs from file:// without a server
88
- */
89
- const isPreview = settings.mode === 'preview';
90
- /**
91
- * a second ssr bundle holding nothing but the design's fixtures, so the ssr
92
- * preflight can read viewData and the registries while still rendering
93
- * through the real dist/server build
94
- */
95
- const isSsrTest = settings.mode === 'ssr-test';
96
- /**
97
- * builds meant to be handed out rather than debugged: minified, no
98
- * sourcemaps, no vue dev instrumentation
99
- */
100
- const isOptimized = isProduction || isPreview;
101
- const config = options.config[target];
102
- const viteConfig: UserConfig = {
103
- plugins: [
104
- vue(),
105
- visualizer(),
106
- ...isPreview ? [previewBundle()] : [dropPreviewAssets()]
107
- ],
108
- base : './',
109
- server: {
110
- host: '0.0.0.0',
111
- },
112
- optimizeDeps: {
113
- // design-core ships source, and its less needs the project variables
114
- // injected below - a prebundle would not see them.
115
- //
116
- // @lilaquadrat/frontend rides along because design-core imports it:
117
- // prebundling it there and serving it raw here would give the resize and
118
- // inview singletons two module identities, and a second scroll listener
119
- // with it
120
- exclude: ['@lilaquadrat/design-core', '@lilaquadrat/frontend']
121
- },
122
- build: {
123
- cssCodeSplit : false,
124
- cssMinify : isOptimized,
125
- sourcemap : !isOptimized,
126
- minify : isOptimized,
127
- rolldownOptions: {
128
- output: {
129
- dir : 'dist/app',
130
- // rolldown manual chunking: split deps into a vendor chunk, but
131
- // never emit a chunk smaller than minSize - small groups fall back
132
- // into the entry instead of producing hundreds of tiny files.
133
- codeSplitting: {
134
- minSize: 30_000,
135
- groups : [
136
- { name: 'qrcode', test: /[\\/]node_modules[\\/]qrcode[\\/]/, minSize: 0 },
137
- { name: 'vendor', test: /[\\/]node_modules[\\/]/ },
138
- ],
139
- },
140
- assetFileNames: (assetInfo: { name?: string }) => {
141
- if (assetInfo.name?.endsWith('woff') || assetInfo.name?.endsWith('png')) {
142
- return '[name][extname]';
143
- }
144
-
145
- return '[name]-[hash][extname]';
146
- },
147
- chunkFileNames: '[name]-[hash].js',
148
- entryFileNames: '[name]-[hash].js',
149
- }
150
- }
151
- },
152
- css: {
153
- devSourcemap : true,
154
- preprocessorOptions: {
155
- less: {
156
- sourceMap : true,
157
- globalVars: {
158
- globalVariables: `true; @import (reference) "${lessDir}/variables.less";`,
159
- globalMixins : `true; @import (reference) "${lessDir}/mixins.less";`,
160
- globalFonts : `true; @import (reference) "${lessDir}/fonts.less";`,
161
- },
162
- }
163
- }
164
- },
165
- resolve: {
166
- alias: {
167
- '~fonts': resolve(options.root, 'src/assets/fonts'),
168
- '@' : resolve(options.root, 'src'),
169
- },
170
- /**
171
- * a linked @lilaquadrat/design-core resolves these from its own
172
- * node_modules, which would give the app a second vue and a second
173
- * pinia - one app instance registering into a store nobody reads.
174
- * dedupe pins every shared runtime to the project copy.
175
- */
176
- dedupe: [
177
- 'vue',
178
- 'vue-router',
179
- 'vue-i18n',
180
- 'pinia',
181
- // holds a static request cache, so a second copy would cache twice
182
- '@lilaquadrat/sdk',
183
- // resize and inview are singletons: a second copy means a second
184
- // scroll listener and a second set of refs nobody reads
185
- '@lilaquadrat/frontend',
186
- '@auth0/auth0-spa-js',
187
- 'axios',
188
- 'dayjs',
189
- ],
190
- /**
191
- * @lilaquadrat/studio is deliberately NOT deduped: it is the backend
192
- * package and a project may still hold a copy for other reasons, while
193
- * a second one costs nothing here.
194
- *
195
- * @lilaquadrat/interfaces is types only, so it has nothing to dedupe.
196
- */
197
- },
198
- define: {
199
- '__FRONTEND_CONFIG__' : JSON.stringify(config),
200
- '__TARGET__' : JSON.stringify(target),
201
- '__PREVIEW__' : JSON.stringify(isPreview),
202
- __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: isOptimized ? 'false' : 'true',
203
- __VUE_PROD_DEVTOOLS__ : isOptimized ? 'false' : 'true',
204
- ...options.define
205
- }
206
- };
207
-
208
- if (isPreview) {
209
-
210
- viteConfig.build = previewBuildOptions(viteConfig.build);
211
-
212
- }
213
-
214
- if (settings.isSsrBuild) {
215
-
216
- viteConfig.build = {
217
- ...viteConfig.build,
218
- rolldownOptions: {
219
- input : isSsrTest ? ssrFixturesEntry : ssrEntry,
220
- plugins: isSsrTest ? [] : [
221
- {
222
- name: 'emit-html-templates',
223
- async generateBundle () {
224
- const { readFile } = await import('node:fs/promises');
225
- const [mailHtml, serverHtml] = await Promise.all([
226
- readFile(resolveTemplate(options.root, 'index.mail.html'), 'utf-8'),
227
- readFile(resolveTemplate(options.root, 'index.server.html'), 'utf-8'),
228
- ]);
229
-
230
- this.emitFile({ type: 'asset', fileName: 'index.mail.html', source: mailHtml });
231
- this.emitFile({ type: 'asset', fileName: 'index.server.html', source: serverHtml });
232
- }
233
- }
234
- ],
235
- output: {
236
- ...viteConfig.build?.rolldownOptions?.output,
237
- codeSplitting : false,
238
- inlineDynamicImports: true,
239
- dir : isSsrTest ? 'dist/ssr-test' : 'dist/server',
240
- entryFileNames : '[name].js',
241
- }
242
- },
243
- ssrManifest: !isSsrTest,
244
- }
245
- viteConfig.ssr = {
246
- target : 'webworker',
247
- noExternal: true,
248
- external : ['node:stream', 'http', 'https', 'crypto', 'path', 'highlight.js'],
249
- }
250
-
251
- }
252
-
253
- return viteConfig;
254
-
255
- });
256
-
257
- }
258
-
259
- export default createViteConfig;
260
- export { previewBundle, dropPreviewAssets, previewBuildOptions };