nuxt-ignis 0.3.1 → 0.3.3

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 (88) hide show
  1. package/.data/content/contents.sqlite +0 -0
  2. package/.env +3 -3
  3. package/.nuxt/app.config.mjs +227 -1
  4. package/.nuxt/components.d.ts +372 -140
  5. package/.nuxt/content/components.ts +93 -36
  6. package/.nuxt/dev/index.mjs +7609 -0
  7. package/.nuxt/dev/index.mjs.map +1 -0
  8. package/.nuxt/dist/server/client.manifest.json +2 -2
  9. package/.nuxt/dist/server/client.manifest.mjs +2 -2
  10. package/.nuxt/eslint.config.d.mts +2 -2
  11. package/.nuxt/eslint.config.mjs +2 -2
  12. package/.nuxt/imports.d.ts +59 -42
  13. package/.nuxt/manifest/latest.json +1 -1
  14. package/.nuxt/manifest/meta/dev.json +1 -1
  15. package/.nuxt/module/@nuxtjs-sitemap.d.ts +8 -8
  16. package/.nuxt/module/nuxt-robots.d.ts +3 -3
  17. package/.nuxt/module/nuxt-seo-utils.d.ts +6 -6
  18. package/.nuxt/module/nuxt-site-config.d.ts +8 -8
  19. package/.nuxt/nitro.json +4 -4
  20. package/.nuxt/nuxt.d.ts +11 -9
  21. package/.nuxt/nuxt.json +2 -2
  22. package/.nuxt/schema/nuxt.schema.d.ts +193 -0
  23. package/.nuxt/schema/nuxt.schema.json +261 -1
  24. package/.nuxt/tsconfig.json +133 -110
  25. package/.nuxt/tsconfig.server.json +82 -64
  26. package/.nuxt/types/app.config.d.ts +227 -1
  27. package/.nuxt/types/build.d.ts +2 -1
  28. package/.nuxt/types/i18n-plugin.d.ts +2 -2
  29. package/.nuxt/types/imports.d.ts +320 -264
  30. package/.nuxt/types/neon.d.ts +136 -34
  31. package/.nuxt/types/nitro-imports.d.ts +40 -40
  32. package/.nuxt/types/nitro-routes.d.ts +21 -18
  33. package/.nuxt/types/plugins.d.ts +38 -33
  34. package/.nuxt/types/schema.d.ts +110 -36
  35. package/.nuxt/types/ui.d.ts +1 -1
  36. package/.nuxt/ui/checkbox-group.ts +1 -1
  37. package/.nuxt/ui/context-menu.ts +2 -1
  38. package/.nuxt/ui/dropdown-menu.ts +2 -1
  39. package/.nuxt/ui/input-menu.ts +2 -2
  40. package/.nuxt/ui/navigation-menu.ts +43 -34
  41. package/.nuxt/ui/radio-group.ts +1 -1
  42. package/.nuxt/ui/select-menu.ts +2 -2
  43. package/.nuxt/ui/select.ts +2 -2
  44. package/.nuxt/ui/tooltip.ts +1 -1
  45. package/.nuxt/ui.css +4 -1
  46. package/app.vue +2 -2
  47. package/components/AppFeatureList.vue +5 -0
  48. package/composables/useValibot.ts +16 -0
  49. package/composables/useZod.ts +16 -0
  50. package/content.config.ts +6 -10
  51. package/features.ts +59 -6
  52. package/i18n/locales/en.json +2 -0
  53. package/nuxt.config.ts +15 -5
  54. package/package.json +20 -16
  55. package/plugins/errorHandler.ts +26 -0
  56. package/server/api/neonTest.ts +7 -5
  57. package/test/config/default.txt +16 -0
  58. package/test/config/equipment-1-composable.txt +22 -0
  59. package/test/config/equipment-2-plugins.txt +23 -0
  60. package/test/config/equipment-all.txt +28 -0
  61. package/test/config.test.ts +47 -0
  62. package/test/features/db-neon.txt +3 -0
  63. package/test/features/db-off.txt +3 -0
  64. package/test/features/db-supabase.txt +3 -0
  65. package/test/features/default.txt +3 -0
  66. package/test/features/disable-core.txt +3 -0
  67. package/test/features/enable-all.txt +4 -0
  68. package/test/features/equipment.txt +3 -0
  69. package/test/features/forms-formkit.txt +3 -0
  70. package/test/features/forms-off.txt +3 -0
  71. package/test/features/forms-vueform.txt +3 -0
  72. package/test/features/ui-nuxt-ui.txt +3 -0
  73. package/test/features/ui-off.txt +3 -0
  74. package/test/features/ui-tailwind.txt +4 -0
  75. package/test/features/validation-off.txt +3 -0
  76. package/test/features/validation-valibot.txt +4 -0
  77. package/test/features/validation-zod.txt +4 -0
  78. package/test/features.test.ts +239 -0
  79. package/utils/config/content.ts +35 -0
  80. package/utils/config/vueform.ts +25 -0
  81. package/utils/consola.ts +23 -13
  82. package/utils/content.ts +18 -0
  83. package/utils/tailwind.ts +19 -0
  84. package/utils/vueform.ts +19 -0
  85. package/vueform.config.ts +4 -18
  86. package/.nuxt/component-chunk.mjs +0 -1
  87. package/.nuxt/dist/server/server.mjs +0 -1
  88. package/.nuxt/tailwind/postcss.mjs +0 -15
@@ -43,24 +43,25 @@ export default {
43
43
  "linkLeadingIcon": "shrink-0 size-5",
44
44
  "linkLeadingAvatar": "shrink-0",
45
45
  "linkLeadingAvatarSize": "2xs",
46
- "linkTrailing": "ms-auto inline-flex gap-1.5 items-center",
46
+ "linkTrailing": "group ms-auto inline-flex gap-1.5 items-center",
47
47
  "linkTrailingBadge": "shrink-0",
48
48
  "linkTrailingBadgeSize": "sm",
49
49
  "linkTrailingIcon": "size-5 transform shrink-0 group-data-[state=open]:rotate-180 transition-transform duration-200",
50
50
  "linkLabel": "truncate",
51
51
  "linkLabelExternalIcon": "inline-block size-3 align-top text-dimmed",
52
- "childList": "",
52
+ "childList": "isolate",
53
+ "childLabel": "text-xs text-highlighted",
53
54
  "childItem": "",
54
- "childLink": "group size-full px-3 py-2 rounded-md flex items-start gap-2 text-start",
55
- "childLinkWrapper": "flex flex-col items-start",
55
+ "childLink": "group relative size-full flex items-start text-start text-sm before:absolute before:z-[-1] before:rounded-md focus:outline-none focus-visible:outline-none dark:focus-visible:outline-none focus-visible:before:ring-inset focus-visible:before:ring-2",
56
+ "childLinkWrapper": "min-w-0",
56
57
  "childLinkIcon": "size-5 shrink-0",
57
- "childLinkLabel": "font-semibold text-sm relative inline-flex",
58
+ "childLinkLabel": "truncate",
58
59
  "childLinkLabelExternalIcon": "inline-block size-3 align-top text-dimmed",
59
- "childLinkDescription": "text-sm text-muted",
60
+ "childLinkDescription": "text-muted",
60
61
  "separator": "px-2 h-px bg-border",
61
62
  "viewportWrapper": "absolute top-full left-0 flex w-full",
62
63
  "viewport": "relative overflow-hidden bg-default shadow-lg rounded-md ring ring-default h-(--reka-navigation-menu-viewport-height) w-full transition-[width,height,left] duration-200 origin-[top_center] data-[state=open]:animate-[scale-in_100ms_ease-out] data-[state=closed]:animate-[scale-out_100ms_ease-in] z-[1]",
63
- "content": "absolute top-0 left-0 w-full",
64
+ "content": "",
64
65
  "indicator": "absolute data-[state=visible]:animate-[fade-in_100ms_ease-out] data-[state=hidden]:animate-[fade-out_100ms_ease-in] data-[state=hidden]:opacity-0 bottom-0 z-[2] w-(--reka-navigation-menu-indicator-size) translate-x-(--reka-navigation-menu-indicator-position) flex h-2.5 items-end justify-center overflow-hidden transition-[translate,width] duration-200",
65
66
  "arrow": "relative top-[50%] size-2.5 rotate-45 border border-default bg-default z-[1] rounded-xs"
66
67
  },
@@ -68,31 +69,31 @@ export default {
68
69
  "color": {
69
70
  "primary": {
70
71
  "link": "focus-visible:before:ring-primary",
71
- "childLink": "focus-visible:outline-primary"
72
+ "childLink": "focus-visible:before:ring-primary"
72
73
  },
73
74
  "secondary": {
74
75
  "link": "focus-visible:before:ring-secondary",
75
- "childLink": "focus-visible:outline-secondary"
76
+ "childLink": "focus-visible:before:ring-secondary"
76
77
  },
77
78
  "success": {
78
79
  "link": "focus-visible:before:ring-success",
79
- "childLink": "focus-visible:outline-success"
80
+ "childLink": "focus-visible:before:ring-success"
80
81
  },
81
82
  "info": {
82
83
  "link": "focus-visible:before:ring-info",
83
- "childLink": "focus-visible:outline-info"
84
+ "childLink": "focus-visible:before:ring-info"
84
85
  },
85
86
  "warning": {
86
87
  "link": "focus-visible:before:ring-warning",
87
- "childLink": "focus-visible:outline-warning"
88
+ "childLink": "focus-visible:before:ring-warning"
88
89
  },
89
90
  "error": {
90
91
  "link": "focus-visible:before:ring-error",
91
- "childLink": "focus-visible:outline-error"
92
+ "childLink": "focus-visible:before:ring-error"
92
93
  },
93
94
  "neutral": {
94
95
  "link": "focus-visible:before:ring-inverted",
95
- "childLink": "focus-visible:outline-inverted"
96
+ "childLink": "focus-visible:before:ring-inverted"
96
97
  }
97
98
  },
98
99
  "highlightColor": {
@@ -114,11 +115,16 @@ export default {
114
115
  "list": "flex items-center",
115
116
  "item": "py-2",
116
117
  "link": "px-2.5 py-1.5 before:inset-x-px before:inset-y-0",
117
- "childList": "grid p-2"
118
+ "childList": "grid p-2",
119
+ "childLink": "px-3 py-2 gap-2 before:inset-x-px before:inset-y-0",
120
+ "childLinkLabel": "font-medium",
121
+ "content": "absolute top-0 left-0 w-full"
118
122
  },
119
123
  "vertical": {
120
124
  "root": "flex-col",
121
- "link": "flex-row px-2.5 py-1.5 before:inset-y-px before:inset-x-0"
125
+ "link": "flex-row px-2.5 py-1.5 before:inset-y-px before:inset-x-0",
126
+ "childLabel": "px-1.5 py-0.5",
127
+ "childLink": "p-1.5 gap-1.5 before:inset-y-px before:inset-x-0"
122
128
  }
123
129
  },
124
130
  "contentOrientation": {
@@ -132,15 +138,15 @@ export default {
132
138
  },
133
139
  "active": {
134
140
  "true": {
135
- "childLink": "bg-elevated text-highlighted",
141
+ "childLink": "before:bg-elevated text-highlighted",
136
142
  "childLinkIcon": "text-default"
137
143
  },
138
144
  "false": {
139
145
  "link": "text-muted",
140
146
  "linkLeadingIcon": "text-dimmed",
141
147
  "childLink": [
142
- "hover:bg-elevated/50 text-default hover:text-highlighted",
143
- "transition-colors"
148
+ "hover:before:bg-elevated/50 text-default hover:text-highlighted",
149
+ "transition-colors before:transition-colors"
144
150
  ],
145
151
  "childLinkIcon": [
146
152
  "text-dimmed group-hover:text-default",
@@ -179,6 +185,23 @@ export default {
179
185
  "content": "w-60"
180
186
  }
181
187
  },
188
+ {
189
+ "orientation": "vertical" as typeof orientation[number],
190
+ "collapsed": false,
191
+ "class": {
192
+ "childList": "ms-5 border-s border-default",
193
+ "childItem": "ps-1.5 -ms-px",
194
+ "content": "data-[state=open]:animate-[collapsible-down_200ms_ease-out] data-[state=closed]:animate-[collapsible-up_200ms_ease-out] overflow-hidden"
195
+ }
196
+ },
197
+ {
198
+ "orientation": "vertical" as typeof orientation[number],
199
+ "collapsed": true,
200
+ "class": {
201
+ "link": "px-1.5",
202
+ "content": "shadow-sm rounded-sm min-h-6 p-1"
203
+ }
204
+ },
182
205
  {
183
206
  "orientation": "horizontal" as typeof orientation[number],
184
207
  "highlight": true,
@@ -319,6 +342,7 @@ export default {
319
342
  "variant": "pill" as typeof variant[number],
320
343
  "active": true,
321
344
  "highlight": true,
345
+ "disabled": false,
322
346
  "class": {
323
347
  "link": [
324
348
  "hover:before:bg-elevated/50",
@@ -476,21 +500,6 @@ export default {
476
500
  "class": {
477
501
  "link": "after:bg-inverted"
478
502
  }
479
- },
480
- {
481
- "orientation": "vertical" as typeof orientation[number],
482
- "collapsed": false,
483
- "class": {
484
- "childList": "ms-5 border-s border-default",
485
- "childItem": "ps-1.5 -ms-px"
486
- }
487
- },
488
- {
489
- "orientation": "vertical" as typeof orientation[number],
490
- "collapsed": true,
491
- "class": {
492
- "link": "px-1.5"
493
- }
494
503
  }
495
504
  ],
496
505
  "defaultVariants": {
@@ -219,7 +219,7 @@ export default {
219
219
  "orientation": "horizontal" as typeof orientation[number],
220
220
  "variant": "table" as typeof variant[number],
221
221
  "class": {
222
- "item": "first-of-type:rounded-l-lg last-of-type:rounded-r-lg",
222
+ "item": "first-of-type:rounded-s-lg last-of-type:rounded-e-lg",
223
223
  "fieldset": "gap-0 -space-x-px"
224
224
  }
225
225
  },
@@ -40,10 +40,10 @@ export default {
40
40
  "placeholder": "truncate text-dimmed",
41
41
  "arrow": "fill-default",
42
42
  "content": [
43
- "max-h-60 w-(--reka-select-trigger-width) bg-default shadow-lg rounded-md ring ring-default overflow-hidden data-[state=open]:animate-[scale-in_100ms_ease-out] data-[state=closed]:animate-[scale-out_100ms_ease-in] origin-(--reka-select-content-transform-origin) pointer-events-auto",
43
+ "max-h-60 w-(--reka-select-trigger-width) bg-default shadow-lg rounded-md ring ring-default overflow-hidden data-[state=open]:animate-[scale-in_100ms_ease-out] data-[state=closed]:animate-[scale-out_100ms_ease-in] origin-(--reka-select-content-transform-origin) pointer-events-auto flex flex-col",
44
44
  "origin-(--reka-combobox-content-transform-origin) w-(--reka-combobox-trigger-width)"
45
45
  ],
46
- "viewport": "divide-y divide-default scroll-py-1",
46
+ "viewport": "relative divide-y divide-default scroll-py-1 overflow-y-auto flex-1",
47
47
  "group": "p-1 isolate",
48
48
  "empty": "py-2 text-center text-sm text-muted",
49
49
  "label": "font-semibold text-highlighted",
@@ -39,8 +39,8 @@ export default {
39
39
  "value": "truncate pointer-events-none",
40
40
  "placeholder": "truncate text-dimmed",
41
41
  "arrow": "fill-default",
42
- "content": "max-h-60 w-(--reka-select-trigger-width) bg-default shadow-lg rounded-md ring ring-default overflow-hidden data-[state=open]:animate-[scale-in_100ms_ease-out] data-[state=closed]:animate-[scale-out_100ms_ease-in] origin-(--reka-select-content-transform-origin) pointer-events-auto",
43
- "viewport": "divide-y divide-default scroll-py-1",
42
+ "content": "max-h-60 w-(--reka-select-trigger-width) bg-default shadow-lg rounded-md ring ring-default overflow-hidden data-[state=open]:animate-[scale-in_100ms_ease-out] data-[state=closed]:animate-[scale-out_100ms_ease-in] origin-(--reka-select-content-transform-origin) pointer-events-auto flex flex-col",
43
+ "viewport": "relative divide-y divide-default scroll-py-1 overflow-y-auto flex-1",
44
44
  "group": "p-1 isolate",
45
45
  "empty": "py-2 text-center text-sm text-muted",
46
46
  "label": "font-semibold text-highlighted",
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "slots": {
3
- "content": "flex items-center gap-1 bg-default text-highlighted shadow-sm rounded-sm ring ring-default h-6 px-2 py-1 text-xs select-none data-[state=delayed-open]:animate-[scale-in_100ms_ease-out] data-[state=closed]:animate-[scale-out_100ms_ease-in] origin-(--reka-tooltip-content-transform-origin) pointer-events-auto",
3
+ "content": "flex items-center gap-1 bg-default text-highlighted shadow-sm rounded-sm ring ring-default h-6 px-2.5 py-1 text-xs select-none data-[state=delayed-open]:animate-[scale-in_100ms_ease-out] data-[state=closed]:animate-[scale-out_100ms_ease-in] origin-(--reka-tooltip-content-transform-origin) pointer-events-auto",
4
4
  "arrow": "fill-default",
5
5
  "text": "truncate",
6
6
  "kbds": "hidden lg:inline-flex items-center shrink-0 gap-0.5 before:content-['·'] before:me-0.5",
package/.nuxt/ui.css CHANGED
@@ -1,6 +1,6 @@
1
1
  @source "./ui";
2
2
 
3
- @theme default inline {
3
+ @theme static {
4
4
  --color-old-neutral-50: oklch(98.5% 0 0);
5
5
  --color-old-neutral-100: oklch(97% 0 0);
6
6
  --color-old-neutral-200: oklch(92.2% 0 0);
@@ -12,6 +12,9 @@
12
12
  --color-old-neutral-800: oklch(26.9% 0 0);
13
13
  --color-old-neutral-900: oklch(20.5% 0 0);
14
14
  --color-old-neutral-950: oklch(14.5% 0 0);
15
+ }
16
+
17
+ @theme default inline {
15
18
  --color-primary-50: var(--ui-color-primary-50);
16
19
  --color-primary-100: var(--ui-color-primary-100);
17
20
  --color-primary-200: var(--ui-color-primary-200);
package/app.vue CHANGED
@@ -21,11 +21,11 @@ useHead({
21
21
  })
22
22
  initConsola()
23
23
 
24
- log.info('Nuxt Ignis was here!')
25
-
26
24
  const config = useRuntimeConfig().public.ignis
27
25
  const pages = config.pages
28
26
  const ui = config.ui || config.preset.ui
27
+
28
+ log.info('Nuxt Ignis initialized')
29
29
  </script>
30
30
 
31
31
  <style scoped>
@@ -30,6 +30,8 @@
30
30
  <AppFeature :active="i18n" :text="useIgnisT('features.i18n')" />
31
31
  <AppFeature :active="vueform" :text="useIgnisT('features.vueform')" />
32
32
  <AppFeature :active="formkit" :text="useIgnisT('features.formkit')" />
33
+ <AppFeature :active="valibot" :text="useIgnisT('features.valibot')" />
34
+ <AppFeature :active="zod" :text="useIgnisT('features.zod')" />
33
35
  <AppFeature :active="content" :text="useIgnisT('features.content')" />
34
36
  <AppFeature :active="seo" :text="useIgnisT('features.seo')" />
35
37
  <AppFeature :active="auth" :text="useIgnisT('features.auth')" />
@@ -63,6 +65,9 @@ const i18n = setup.i18n.enabled
63
65
  const forms = setup.preset.forms
64
66
  const vueform = forms === 'vueform' || (forms === 'off' && setup.vueform)
65
67
  const formkit = forms === 'formkit' || (forms === 'off' && setup.formkit.enabled)
68
+ const validation = setup.preset.validation
69
+ const valibot = validation === 'valibot' || (validation === 'off' && setup.valibot)
70
+ const zod = validation === 'zod' || (validation === 'off' && setup.zod)
66
71
  const content = setup.content
67
72
  const seo = setup.seo
68
73
  const auth = setup.auth
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Exposes Valibot schema validation functions. Requires `NUXT_PUBLIC_IGNIS_PRESET_VALIDATION=valibot` or `NUXT_PUBLIC_IGNIS_VALIBOT=true` to work properly.
3
+ *
4
+ * Usage: `const v = (await useValibot())!`
5
+ *
6
+ * @returns Valibot `v` object for schema validation
7
+ */
8
+ export const useValibot = async () => {
9
+ const config = useRuntimeConfig().public.ignis
10
+ if (config.preset.validation === 'valibot' || config.valibot === true) {
11
+ const valibot = await import('valibot')
12
+ return valibot
13
+ } else {
14
+ log.warn('Valibot is not enabled (set NUXT_PUBLIC_IGNIS_PRESET_VALIDATION=valibot or NUXT_PUBLIC_IGNIS_VALIBOT=true)')
15
+ }
16
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Exposes Zod schema validation functions. Requires `NUXT_PUBLIC_IGNIS_PRESET_VALIDATION=zod` or `NUXT_PUBLIC_IGNIS_ZOD=true` to work properly.
3
+ *
4
+ * Usage: `const z = (await useZod())!`
5
+ *
6
+ * @returns Zod `z` object for schema validation
7
+ */
8
+ export const useZod = async () => {
9
+ const config = useRuntimeConfig().public.ignis
10
+ if (config.preset.validation === 'zod' || config.zod === true) {
11
+ const zod = await import('zod/v4')
12
+ return zod.z
13
+ } else {
14
+ log.warn('Zod is not enabled (set NUXT_PUBLIC_IGNIS_PRESET_VALIDATION=zod or NUXT_PUBLIC_IGNIS_ZOD=true)')
15
+ }
16
+ }
package/content.config.ts CHANGED
@@ -1,12 +1,8 @@
1
- import { defineCollection, defineContentConfig } from '@nuxt/content'
1
+ // minimal config for Nuxt Content
2
+ // currently required to be loaded like this...
2
3
 
3
- export default defineContentConfig({
4
- // while it is not strictily necessary to have a default config file
5
- // it produces warning during startup when not presented
6
- collections: {
7
- content: defineCollection({
8
- source: '**',
9
- type: 'page',
10
- }),
11
- },
4
+ import { loadContentConfig } from './utils/content'
5
+
6
+ export default loadContentConfig({
7
+ // custom config here
12
8
  })
package/features.ts CHANGED
@@ -4,6 +4,7 @@ import { defu } from 'defu'
4
4
  import OpenProps from 'open-props'
5
5
  import tailwindcss from '@tailwindcss/vite'
6
6
  import { log } from './utils/consola'
7
+ import { ignisTailwindcssFix } from './utils/tailwind'
7
8
 
8
9
  const currentDir = dirname(fileURLToPath(import.meta.url))
9
10
 
@@ -37,11 +38,6 @@ export function setFeatures() {
37
38
  nuxtConfig.modules.push('@nuxt/image')
38
39
  }
39
40
 
40
- // https://pinia.vuejs.org/ssr/nuxt.html
41
- if (process.env.NUXT_PUBLIC_IGNIS_CORE_PINIA !== 'false') {
42
- nuxtConfig.modules.push('@pinia/nuxt')
43
- }
44
-
45
41
  // https://scripts.nuxt.com/
46
42
  if (process.env.NUXT_PUBLIC_IGNIS_CORE_SCRIPTS !== 'false') {
47
43
  nuxtConfig.modules.push('@nuxt/scripts')
@@ -57,6 +53,11 @@ export function setFeatures() {
57
53
  nuxtConfig.modules.push('@vueuse/nuxt')
58
54
  }
59
55
 
56
+ // https://pinia.vuejs.org/ssr/nuxt.html
57
+ if (process.env.NUXT_PUBLIC_IGNIS_CORE_PINIA !== 'false') {
58
+ nuxtConfig.modules.push('@pinia/nuxt')
59
+ }
60
+
60
61
  // 2. optional modules & features
61
62
  // (excluded unless enabled)
62
63
 
@@ -67,7 +68,9 @@ export function setFeatures() {
67
68
  process.env.NUXT_PUBLIC_IGNIS_PRESET_UI = uiPreset = 'off'
68
69
  }
69
70
 
71
+ let tailwindFixRequired = false
70
72
  if (uiPreset === 'nuxt-ui' || process.env.NUXT_PUBLIC_IGNIS_UI === 'true') {
73
+ tailwindFixRequired = true
71
74
  nuxtConfig.modules.push('@nuxt/ui')
72
75
  // import tailwind css file
73
76
  nuxtConfig = defu({
@@ -85,6 +88,7 @@ export function setFeatures() {
85
88
 
86
89
  // evaluate separate Tailwind CSS module
87
90
  if (uiPreset === 'tailwind' || (process.env.NUXT_PUBLIC_IGNIS_TAILWIND === 'true' && uiPreset !== 'nuxt-ui')) {
91
+ tailwindFixRequired = true
88
92
  // nuxtConfig.modules.push('@nuxtjs/tailwindcss') // temporary disabled until v7 is released
89
93
  extras.push('Tailwind CSS')
90
94
  // import tailwind css file
@@ -97,6 +101,15 @@ export function setFeatures() {
97
101
  }
98
102
  }
99
103
 
104
+ // TODO occasionaly check https://github.com/tailwindlabs/tailwindcss/discussions/16119 for solution
105
+ if (tailwindFixRequired) {
106
+ nuxtConfig = defu({
107
+ vite: {
108
+ plugins: [ignisTailwindcssFix],
109
+ },
110
+ }, nuxtConfig)
111
+ }
112
+
100
113
  // database
101
114
  let dbPreset = process.env.NUXT_PUBLIC_IGNIS_PRESET_DB
102
115
  if (dbPreset && !['neon', 'supabase'].includes(dbPreset)) {
@@ -163,6 +176,19 @@ export function setFeatures() {
163
176
  }, nuxtConfig)
164
177
  }
165
178
 
179
+ // validation
180
+ let validationPreset = process.env.NUXT_PUBLIC_IGNIS_PRESET_VALIDATION
181
+ if (validationPreset && !['zod', 'valibot'].includes(validationPreset)) {
182
+ // surpress other values
183
+ process.env.NUXT_PUBLIC_IGNIS_PRESET_VALIDATION = validationPreset = 'off'
184
+ }
185
+ if (validationPreset === 'zod' || process.env.NUXT_PUBLIC_IGNIS_ZOD === 'true') {
186
+ extras.push('zod')
187
+ }
188
+ if (validationPreset === 'valibot' || process.env.NUXT_PUBLIC_IGNIS_VALIBOT === 'true') {
189
+ extras.push('valibot')
190
+ }
191
+
166
192
  // seo
167
193
  // 2025/04 - must be before @nuxt/content (https://nuxtseo.com/docs/nuxt-seo/guides/nuxt-content)
168
194
  if (process.env.NUXT_PUBLIC_IGNIS_SEO === 'true') {
@@ -188,6 +214,29 @@ export function setFeatures() {
188
214
  nuxtConfig.modules.push('nuxt-auth-utils')
189
215
  }
190
216
 
217
+ // https://www.vue.equipment/
218
+ if (process.env.NUXT_PUBLIC_IGNIS_EQUIPMENT_ENABLED === 'true') {
219
+ nuxtConfig.modules.push('@maas/vue-equipment/nuxt')
220
+ // composables to be included
221
+ if (process.env.NUXT_PUBLIC_IGNIS_EQUIPMENT_COMPOSABLES) {
222
+ // values MUST be delimited by "," (spaces will be trimmed)
223
+ nuxtConfig = defu({
224
+ vueEquipment: {
225
+ composables: process.env.NUXT_PUBLIC_IGNIS_EQUIPMENT_COMPOSABLES.split(',').map(p => p?.trim()),
226
+ },
227
+ }, nuxtConfig)
228
+ }
229
+ // plugins to be included
230
+ if (process.env.NUXT_PUBLIC_IGNIS_EQUIPMENT_PLUGINS) {
231
+ // values MUST be delimited by "," (spaces will be trimmed)
232
+ nuxtConfig = defu({
233
+ vueEquipment: {
234
+ plugins: process.env.NUXT_PUBLIC_IGNIS_EQUIPMENT_PLUGINS.split(',').map(p => p?.trim()),
235
+ },
236
+ }, nuxtConfig)
237
+ }
238
+ }
239
+
191
240
  // Open Props CSS
192
241
  if (process.env.NUXT_PUBLIC_IGNIS_OPENPROPS === 'true') {
193
242
  extras.push('Open Props CSS')
@@ -230,12 +279,16 @@ export function setFeatures() {
230
279
  // this means e.g. 2 database modules or 2 form solutions
231
280
  if (process.env.NUXT_PUBLIC_IGNIS_WARN_DUPLICATES !== 'false') {
232
281
  const used = nuxtConfig.modules
233
- if (used.includes('nuxt-neon') && used.includes('nuxt-neon')) {
282
+ if (used.includes('nuxt-neon') && used.includes('@nuxtjs/supabase')) {
234
283
  log.warn('You have both DB connector modules (Neon and Supabase) active, which is not recommended. If this is intentional, you can use `process.env.NUXT_PUBLIC_IGNIS_WARN_DUPLICATES=false` to surpress this warning.')
235
284
  }
236
285
  if (used.includes('@vueform/nuxt') && used.includes('@formkit/nuxt')) {
237
286
  log.warn('You have both Form solution provider modules (Vueform and Formkit) active, which is not recommended. If this is intentional, you can use `process.env.NUXT_PUBLIC_IGNIS_WARN_DUPLICATES=false` to surpress this warning.')
238
287
  }
288
+ // validation - not imported as modules
289
+ if (extras.includes('zod') && extras.includes('valibot')) {
290
+ log.warn('You have both validation libraries (Zod and Valibot) active, which is not recommended. If this is intentional, you can use `process.env.NUXT_PUBLIC_IGNIS_WARN_DUPLICATES=false` to surpress this warning.')
291
+ }
239
292
  }
240
293
 
241
294
  // 5. verify results
@@ -24,6 +24,8 @@
24
24
  "neon" : "Neon for DB services",
25
25
  "formkit" : "FormKit for input forms",
26
26
  "vueform" : "Vueform for input forms",
27
+ "valibot" : "Valibot for schema validation",
28
+ "zod": "Zod for schema validation",
27
29
  "content" : "Nuxt Content for creating and editing content",
28
30
  "seo" : "Nuxt SEO collection of SEO-related modules",
29
31
  "auth" : "Nuxt Auth Utils for easy and secure authentication",
package/nuxt.config.ts CHANGED
@@ -12,7 +12,7 @@ const nuxtConfig = defu(ignisFeatures, {
12
12
  ],
13
13
 
14
14
  // https://nuxt.com/docs/api/nuxt-config#compatibilitydate
15
- compatibilityDate: '2025-05-21',
15
+ compatibilityDate: '2025-06-07',
16
16
 
17
17
  // simple eslint config - see eslint.config.mjs
18
18
  eslint: {
@@ -47,6 +47,9 @@ const nuxtConfig = defu(ignisFeatures, {
47
47
  level: 'info',
48
48
  },
49
49
 
50
+ // central error handler
51
+ error: true, // true/false
52
+
50
53
  // nuxt-related config
51
54
  ssr: true, // true/false
52
55
  pages: true, // true/false
@@ -56,6 +59,7 @@ const nuxtConfig = defu(ignisFeatures, {
56
59
  ui: 'off', // nuxt-ui/tailwind/off
57
60
  db: 'off', // neon/supabase/off
58
61
  forms: 'off', // formkit/vueform/off
62
+ validation: 'off', // valibot/zod/off
59
63
  },
60
64
 
61
65
  // core modules
@@ -64,11 +68,10 @@ const nuxtConfig = defu(ignisFeatures, {
64
68
  eslint: true,
65
69
  fonts: true,
66
70
  image: true,
67
- pinia: true,
68
- time: true,
69
71
  scripts: true,
70
72
  security: true,
71
73
  vueuse: true,
74
+ pinia: true,
72
75
  },
73
76
 
74
77
  // optional modules
@@ -87,14 +90,21 @@ const nuxtConfig = defu(ignisFeatures, {
87
90
  config: './formkit.config.ts', // path to config file
88
91
  },
89
92
  vueform: false, // true/false
93
+ valibot: false, // true/false
94
+ zod: false, // true/false
90
95
  content: false, // true/false
96
+ seo: false, // true/false
97
+ auth: false, // true/false
91
98
  openprops: false, // true/false
92
99
  pslo: {
93
100
  enabled: false, // true/false (elrh-pslo will (not) be used)
94
101
  content: false, // true/false (elrh-pslo will (not) be aplied on nuxt-content)
95
102
  },
96
- seo: false, // true/false
97
- auth: false, // true/false
103
+ equipment: {
104
+ enabled: false, // true/false
105
+ composables: '', // list of Vue Equipment composables
106
+ plugins: '', // list of Vue Equipment plugins
107
+ },
98
108
 
99
109
  // extra behavior
100
110
  warn: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-ignis",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Enhanced and customizable Nuxt application starter pack",
5
5
  "keywords": [
6
6
  "nuxt",
@@ -26,36 +26,40 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "@formkit/nuxt": "1.6.9",
29
- "@nuxt/content": "3.5.1",
29
+ "@maas/vue-equipment": "1.0.0-beta.30",
30
+ "@nuxt/content": "3.6.1",
30
31
  "@nuxt/eslint": "1.4.1",
31
32
  "@nuxt/fonts": "0.11.4",
32
33
  "@nuxt/image": "1.10.0",
33
- "@nuxt/scripts": "0.11.7",
34
- "@nuxt/ui": "3.1.2",
35
- "@nuxtjs/i18n": "9.5.4",
34
+ "@nuxt/scripts": "0.11.8",
35
+ "@nuxt/ui": "3.1.3",
36
+ "@nuxtjs/i18n": "9.5.5",
36
37
  "@nuxtjs/seo": "3.0.3",
37
- "@nuxtjs/supabase": "1.5.1",
38
+ "@nuxtjs/supabase": "1.5.2",
38
39
  "@nuxtjs/tailwindcss": "6.14.0",
39
- "@pinia/nuxt": "0.11.0",
40
- "@vueform/nuxt": "1.13.0",
41
- "@vueuse/core": "13.2.0",
42
- "@vueuse/nuxt": "13.2.0",
43
- "@tailwindcss/vite": "4.1.7",
40
+ "@pinia/nuxt": "0.11.1",
41
+ "@tailwindcss/vite": "4.1.10",
42
+ "@vueform/nuxt": "1.16.0",
43
+ "@vueuse/core": "13.4.0",
44
+ "@vueuse/nuxt": "13.4.0",
44
45
  "consola": "3.4.2",
46
+ "date-fns": "4.1.0",
45
47
  "defu": "6.1.4",
46
48
  "elrh-pslo": "1.1.6",
47
49
  "nuxt-auth-utils": "0.5.20",
48
- "nuxt-neon": "0.6.0",
50
+ "nuxt-neon": "0.6.2",
49
51
  "nuxt-security": "2.2.0",
50
52
  "nuxt-spec": "0.0.4",
51
53
  "open-props": "1.7.15",
52
- "pinia": "3.0.2",
54
+ "pinia": "3.0.3",
53
55
  "postcss-jit-props": "1.0.16",
54
- "typescript": "5.8.3"
56
+ "typescript": "5.8.3",
57
+ "valibot": "1.1.0",
58
+ "zod": "3.25.67"
55
59
  },
56
60
  "devDependencies": {
57
- "nuxt": "3.17.4",
58
- "vue": "3.5.14",
61
+ "nuxt": "3.17.5",
62
+ "vue": "3.5.16",
59
63
  "vue-router": "4.5.1"
60
64
  },
61
65
  "scripts": {
@@ -0,0 +1,26 @@
1
+ // This registeres custom error and warn handlers within Nuxt Ignis app.
2
+ // You can set NUXT_PUBLIC_IGNIS_ERROR to 'false' to disable this feature.
3
+
4
+ export default defineNuxtPlugin((nuxtApp) => {
5
+ if (useRuntimeConfig().public.ignis.error) {
6
+ nuxtApp.vueApp.config.errorHandler = (err, instance, info) => {
7
+ log.error(err)
8
+ // capture additional context
9
+ log.debug(`Nuxt Ignis error handler - raw error:\n${err}`)
10
+ log.debug(`Nuxt Ignis error handler - source:\n${instance?.$options?.__name || 'Unknown'} (${instance?.$options?.__file || '???'})`)
11
+ log.debug(`Nuxt Ignis error handler - additional error context:\n${info}`)
12
+ }
13
+ nuxtApp.vueApp.config.warnHandler = (msg, instance, trace) => {
14
+ log.warn(msg)
15
+ // capture additional context
16
+ log.debug(`Nuxt Ignis warn handler - raw warning:\n${msg}`)
17
+ log.debug(`Nuxt Ignis warn handler - source:\n${instance?.$options?.__name || 'Unknown'} (${instance?.$options?.__file || '???'})`)
18
+ log.debug(`Nuxt Ignis warn handler - additional warn context:\n${trace}`)
19
+ }
20
+ // set NUXT_PUBLIC_IGNIS_ERROR=false to turn them off
21
+ log.info('Nuxt Ignis error/warn handlers were registered')
22
+ } else {
23
+ // set NUXT_PUBLIC_IGNIS_ERROR=true to turn them on
24
+ log.info('Nuxt Ignis error/warn handlers were NOT registered')
25
+ }
26
+ })
@@ -3,11 +3,13 @@ export default defineEventHandler(async () => {
3
3
  if (config.preset.db === 'neon' || config.neon === true) {
4
4
  return await select(
5
5
  getNeonClient(),
6
- ['name', 'value'],
7
- 'playing_with_neon',
8
- [{ column: 'name', condition: 'LIKE', value: '\'test%\'' }],
9
- 'name DESC',
10
- 2,
6
+ {
7
+ columns: ['name', 'value'],
8
+ from: 'playing_with_neon',
9
+ where: { column: 'name', condition: 'LIKE', value: '\'test%\'' },
10
+ order: 'name DESC',
11
+ limit: 2,
12
+ },
11
13
  )
12
14
  } else {
13
15
  return 'Neon DB module not enabled'
@@ -0,0 +1,16 @@
1
+ {
2
+ "modules": [
3
+ "@nuxt/eslint",
4
+ "@nuxt/fonts",
5
+ "@nuxt/image",
6
+ "@nuxt/scripts",
7
+ "nuxt-security",
8
+ "@vueuse/nuxt",
9
+ "@pinia/nuxt",
10
+ ],
11
+ "vue": {
12
+ "compilerOptions": {
13
+ "isCustomElement": [Function],
14
+ },
15
+ },
16
+ }