Migration to Nuxt v4 file structure and dependencies update

This commit is contained in:
Clément Pons 2025-11-13 10:05:41 +01:00
parent dd4191bea6
commit dfbb31595e
90 changed files with 652 additions and 924 deletions

View File

@ -12,7 +12,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { Icon } from '@iconify/vue/dist/iconify.js'; import { Icon } from '@iconify/vue';
const { src, icon, text, size = 'medium' } = defineProps<{ const { src, icon, text, size = 'medium' } = defineProps<{
src: string src: string
icon?: string icon?: string

View File

@ -17,7 +17,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { Icon } from '@iconify/vue/dist/iconify.js'; import { Icon } from '@iconify/vue';
const { label, disabled = false, defaultOpen = false } = defineProps<{ const { label, disabled = false, defaultOpen = false } = defineProps<{
label?: string label?: string
disabled?: boolean disabled?: boolean

View File

@ -31,7 +31,7 @@
<script setup lang="ts" generic="T extends string | number | boolean | Record<string, any>"> <script setup lang="ts" generic="T extends string | number | boolean | Record<string, any>">
import { ComboboxInput, ComboboxTrigger, ComboboxViewport, ComboboxContent, ComboboxPortal, ComboboxRoot } from 'radix-vue' import { ComboboxInput, ComboboxTrigger, ComboboxViewport, ComboboxContent, ComboboxPortal, ComboboxRoot } from 'radix-vue'
import { Icon } from '@iconify/vue/dist/iconify.js'; import { Icon } from '@iconify/vue';
const { disabled = false, position = 'popper', multiple = false } = defineProps<{ const { disabled = false, position = 'popper', multiple = false } = defineProps<{
placeholder?: string placeholder?: string
disabled?: boolean disabled?: boolean

View File

@ -65,7 +65,7 @@
<script setup lang="ts"> <script setup lang="ts">
import type { DropdownOption } from './DropdownMenu.vue'; import type { DropdownOption } from './DropdownMenu.vue';
import { Icon } from '@iconify/vue/dist/iconify.js'; import { Icon } from '@iconify/vue';
const { options } = defineProps<{ const { options } = defineProps<{
options: DropdownOption[] options: DropdownOption[]

View File

@ -10,7 +10,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { Icon } from '@iconify/vue/dist/iconify.js'; import { Icon } from '@iconify/vue';
const { min = 0, max = 100, disabled = false, step = 1, label } = defineProps<{ const { min = 0, max = 100, disabled = false, step = 1, label } = defineProps<{
min?: number min?: number

View File

@ -15,7 +15,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { Icon } from '@iconify/vue/dist/iconify.js'; import { Icon } from '@iconify/vue';
export interface RadioOption { export interface RadioOption {
label: string label: string
value: string value: string

View File

@ -30,7 +30,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { SelectContent, SelectPortal, SelectRoot, SelectScrollDownButton, SelectScrollUpButton, SelectTrigger, SelectValue, SelectViewport } from 'radix-vue' import { SelectContent, SelectPortal, SelectRoot, SelectScrollDownButton, SelectScrollUpButton, SelectTrigger, SelectValue, SelectViewport } from 'radix-vue'
import { Icon } from '@iconify/vue/dist/iconify.js'; import { Icon } from '@iconify/vue';
const { disabled = false, position = 'popper' } = defineProps<{ const { disabled = false, position = 'popper' } = defineProps<{
placeholder?: string placeholder?: string
disabled?: boolean disabled?: boolean

View File

@ -8,7 +8,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { Icon } from '@iconify/vue/dist/iconify.js'; import { Icon } from '@iconify/vue';
import { SelectItem, SelectItemIndicator, SelectItemText } from 'radix-vue' import { SelectItem, SelectItemIndicator, SelectItemText } from 'radix-vue'
const { disabled = false, value } = defineProps<{ const { disabled = false, value } = defineProps<{
disabled?: boolean disabled?: boolean

View File

@ -15,7 +15,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { Icon } from '@iconify/vue/dist/iconify.js'; import { Icon } from '@iconify/vue';
const { label, disabled, onIcon, offIcon } = defineProps<{ const { label, disabled, onIcon, offIcon } = defineProps<{
label?: string label?: string
disabled?: boolean disabled?: boolean

View File

@ -12,7 +12,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { Icon } from '@iconify/vue/dist/iconify.js'; import { Icon } from '@iconify/vue';
const { placeholder } = defineProps<{ const { placeholder } = defineProps<{
placeholder?: string placeholder?: string

View File

@ -18,7 +18,7 @@
<script setup lang="ts"> <script setup lang="ts">
import type { NuxtError } from '#app'; import type { NuxtError } from '#app';
import { Icon } from '@iconify/vue/dist/iconify.js'; import { Icon } from '@iconify/vue';
const props = defineProps({ const props = defineProps({
error: Object as () => NuxtError error: Object as () => NuxtError

View File

@ -50,7 +50,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { Icon } from '@iconify/vue/dist/iconify.js'; import { Icon } from '@iconify/vue';
import { TreeDOM } from '#shared/tree'; import { TreeDOM } from '#shared/tree';
import { Content, iconByType } from '#shared/content.util'; import { Content, iconByType } from '#shared/content.util';
import { dom, icon } from '#shared/dom.util'; import { dom, icon } from '#shared/dom.util';

View File

@ -33,7 +33,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { format } from '#shared/general.util'; import { format } from '#shared/general.util';
import { iconByType } from '#shared/content.util'; import { iconByType } from '#shared/content.util';
import { Icon } from '@iconify/vue/dist/iconify.js'; import { Icon } from '@iconify/vue';
import { Toaster } from '#shared/components.util'; import { Toaster } from '#shared/components.util';
interface File interface File

View File

@ -14,7 +14,7 @@ const schemaList: Record<string, z.ZodObject<any> | null> = {
<script setup lang="ts"> <script setup lang="ts">
import { z } from 'zod/v4'; import { z } from 'zod/v4';
import { Icon } from '@iconify/vue/dist/iconify.js'; import { Icon } from '@iconify/vue';
import { Toaster } from '#shared/components.util'; import { Toaster } from '#shared/components.util';
definePageMeta({ definePageMeta({

View File

@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { Icon } from '@iconify/vue/dist/iconify.js'; import { Icon } from '@iconify/vue';
import { unifySlug } from '~/shared/general.util'; import { unifySlug } from '#shared/general.util';
definePageMeta({ definePageMeta({
guestsGoesTo: '/user/login', guestsGoesTo: '/user/login',

View File

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { Toaster } from '~/shared/components.util'; import { Toaster } from '#shared/components.util';
definePageMeta({ definePageMeta({
guestsGoesTo: '/user/login', guestsGoesTo: '/user/login',

View File

@ -52,7 +52,7 @@ import { button, loading } from '#shared/components.util';
import { dom, icon } from '#shared/dom.util'; import { dom, icon } from '#shared/dom.util';
import { modal, tooltip } from '#shared/floating.util'; import { modal, tooltip } from '#shared/floating.util';
import { Toaster } from '#shared/components.util'; import { Toaster } from '#shared/components.util';
import { Icon } from '@iconify/vue/dist/iconify.js'; import { Icon } from '@iconify/vue';
definePageMeta({ definePageMeta({
rights: ['admin', 'editor'], rights: ['admin', 'editor'],

View File

@ -18,7 +18,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { Icon } from '@iconify/vue/dist/iconify.js'; import { Icon } from '@iconify/vue';
definePageMeta({ definePageMeta({
layout: 'login', layout: 'login',

View File

@ -24,7 +24,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { Icon } from '@iconify/vue/dist/iconify.js'; import { Icon } from '@iconify/vue';
import { Toaster } from '#shared/components.util'; import { Toaster } from '#shared/components.util';
definePageMeta({ definePageMeta({

View File

@ -25,7 +25,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { Icon } from '@iconify/vue/dist/iconify.js'; import { Icon } from '@iconify/vue';
import { Toaster } from '#shared/components.util'; import { Toaster } from '#shared/components.util';
definePageMeta({ definePageMeta({

View File

@ -20,7 +20,7 @@
<script setup lang="ts"> <script setup lang="ts">
import type { ZodError } from 'zod/v4'; import type { ZodError } from 'zod/v4';
import { schema, type Login } from '~/schemas/login'; import { schema, type Login } from '~/schemas/login';
import { Icon } from '@iconify/vue/dist/iconify.js'; import { Icon } from '@iconify/vue';
import { Toaster } from '#shared/components.util'; import { Toaster } from '#shared/components.util';
definePageMeta({ definePageMeta({

View File

@ -30,7 +30,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { ZodError } from 'zod/v4'; import { ZodError } from 'zod/v4';
import { schema, type Registration } from '~/schemas/registration'; import { schema, type Registration } from '~/schemas/registration';
import { Icon } from '@iconify/vue/dist/iconify.js'; import { Icon } from '@iconify/vue';
import { Toaster } from '#shared/components.util'; import { Toaster } from '#shared/components.util';
definePageMeta({ definePageMeta({

1450
bun.lock

File diff suppressed because it is too large Load Diff

BIN
db.sqlite

Binary file not shown.

View File

@ -9,31 +9,31 @@
"migrate": "bun migrate.ts" "migrate": "bun migrate.ts"
}, },
"dependencies": { "dependencies": {
"@atlaskit/pragmatic-drag-and-drop": "^1.7.4", "@atlaskit/pragmatic-drag-and-drop": "^1.7.7",
"@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^2.1.1", "@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^2.1.2",
"@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.1.0", "@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.1.0",
"@codemirror/lang-markdown": "^6.3.3", "@codemirror/lang-markdown": "^6.5.0",
"@floating-ui/dom": "^1.7.2", "@floating-ui/dom": "^1.7.4",
"@iconify/vue": "^4.3.0", "@iconify/vue": "^5.0.0",
"@lezer/highlight": "^1.2.1", "@lezer/highlight": "^1.2.3",
"@markdoc/markdoc": "^0.5.2", "@markdoc/markdoc": "^0.5.4",
"@nuxtjs/color-mode": "^3.5.2", "@nuxtjs/color-mode": "^4.0.0",
"@nuxtjs/sitemap": "^7.4.3", "@nuxtjs/sitemap": "^7.4.7",
"@nuxtjs/tailwindcss": "^6.14.0", "@nuxtjs/tailwindcss": "^6.14.0",
"@vueuse/gesture": "^2.0.0", "@vueuse/gesture": "^2.0.0",
"@vueuse/math": "^13.5.0", "@vueuse/math": "^14.0.0",
"@vueuse/nuxt": "^13.5.0", "@vueuse/nuxt": "^14.0.0",
"codemirror": "^6.0.2", "codemirror": "^6.0.2",
"drizzle-orm": "^0.44.3", "drizzle-orm": "^0.44.7",
"hast": "^1.0.0", "hast": "^1.0.0",
"hast-util-heading": "^3.0.0", "hast-util-heading": "^3.0.0",
"hast-util-heading-rank": "^3.0.0", "hast-util-heading-rank": "^3.0.0",
"iconify-icon": "^2.3.0", "iconify-icon": "^3.0.2",
"lodash.capitalize": "^4.2.1", "lodash.capitalize": "^4.2.1",
"mdast-util-find-and-replace": "^3.0.2", "mdast-util-find-and-replace": "^3.0.2",
"nodemailer": "^7.0.5", "nodemailer": "^7.0.10",
"nuxt": "^4.0.1", "nuxt": "^4.2.1",
"nuxt-security": "^2.2.0", "nuxt-security": "^2.4.0",
"radix-vue": "^1.9.17", "radix-vue": "^1.9.17",
"rehype-raw": "^7.0.0", "rehype-raw": "^7.0.0",
"remark-breaks": "^4.0.0", "remark-breaks": "^4.0.0",
@ -47,18 +47,18 @@
"strip-markdown": "^6.0.0", "strip-markdown": "^6.0.0",
"unified": "^11.0.5", "unified": "^11.0.5",
"unist-util-visit": "^5.0.0", "unist-util-visit": "^5.0.0",
"vue": "^3.5.17", "vue": "^3.5.24",
"vue-router": "^4.5.1", "vue-router": "^4.6.3",
"zod": "^3.25.76" "zod": "^4.1.12"
}, },
"devDependencies": { "devDependencies": {
"@types/bun": "^1.2.19", "@types/bun": "^1.3.2",
"@types/lodash.capitalize": "^4.2.9", "@types/lodash.capitalize": "^4.2.9",
"@types/nodemailer": "^6.4.17", "@types/nodemailer": "^7.0.3",
"@types/unist": "^3.0.3", "@types/unist": "^3.0.3",
"better-sqlite3": "^12.2.0", "better-sqlite3": "^12.4.1",
"bun-types": "^1.2.19", "bun-types": "^1.3.2",
"drizzle-kit": "^0.31.4", "drizzle-kit": "^0.31.6",
"mdast-util-to-string": "^4.0.0", "mdast-util-to-string": "^4.0.0",
"rehype-stringify": "^10.0.1" "rehype-stringify": "^10.0.1"
} }

View File

@ -1,4 +1,4 @@
import { hasPermissions } from "~/shared/auth.util"; import { hasPermissions } from "#shared/auth.util";
import useDatabase from '~/composables/useDatabase'; import useDatabase from '~/composables/useDatabase';
import { and, eq, notInArray } from "drizzle-orm"; import { and, eq, notInArray } from "drizzle-orm";
import { z } from "zod"; import { z } from "zod";

View File

@ -1,4 +1,4 @@
import { hasPermissions } from "~/shared/auth.util"; import { hasPermissions } from "#shared/auth.util";
import useDatabase from '~/composables/useDatabase'; import useDatabase from '~/composables/useDatabase';
import { and, eq, notInArray } from "drizzle-orm"; import { and, eq, notInArray } from "drizzle-orm";
import { z } from "zod"; import { z } from "zod";

View File

@ -2,7 +2,7 @@ import useDatabase from '~/composables/useDatabase';
import { schema } from '~/schemas/login'; import { schema } from '~/schemas/login';
import type { UserSession, UserSessionRequired } from '~/types/auth'; import type { UserSession, UserSessionRequired } from '~/types/auth';
import { ZodError } from 'zod/v4'; import { ZodError } from 'zod/v4';
import { checkSession, logSession } from '~/server/utils/user'; import { checkSession, logSession } from '~/../server/utils/user';
import { usersTable } from '~/db/schema'; import { usersTable } from '~/db/schema';
import { eq, or, sql } from 'drizzle-orm'; import { eq, or, sql } from 'drizzle-orm';

View File

@ -3,7 +3,7 @@ import { ZodError } from 'zod/v4';
import useDatabase from '~/composables/useDatabase'; import useDatabase from '~/composables/useDatabase';
import { usersDataTable, usersTable } from '~/db/schema'; import { usersDataTable, usersTable } from '~/db/schema';
import { schema } from '~/schemas/registration'; import { schema } from '~/schemas/registration';
import { checkSession, logSession } from '~/server/utils/user'; import { checkSession, logSession } from '~/../server/utils/user';
import type { UserSession, UserSessionRequired } from '~/types/auth'; import type { UserSession, UserSessionRequired } from '~/types/auth';
import type { $ZodIssue } from 'zod/v4/core'; import type { $ZodIssue } from 'zod/v4/core';

View File

@ -3,7 +3,7 @@ import { eq, or } from 'drizzle-orm';
import { z } from 'zod/v4'; import { z } from 'zod/v4';
import useDatabase from '~/composables/useDatabase'; import useDatabase from '~/composables/useDatabase';
import { usersTable } from '~/db/schema'; import { usersTable } from '~/db/schema';
import sendMail from '~/server/tasks/mail'; import sendMail from '~/../server/tasks/mail';
const schema = z.object({ const schema = z.object({
profile: z.string(), profile: z.string(),

View File

@ -3,9 +3,9 @@ import { ZodError } from 'zod/v4';
import useDatabase from '~/composables/useDatabase'; import useDatabase from '~/composables/useDatabase';
import { usersDataTable, usersTable } from '~/db/schema'; import { usersDataTable, usersTable } from '~/db/schema';
import { schema } from '~/schemas/registration'; import { schema } from '~/schemas/registration';
import { checkSession, logSession } from '~/server/utils/user'; import { checkSession, logSession } from '~/../server/utils/user';
import type { UserSession, UserSessionRequired } from '~/types/auth'; import type { UserSession, UserSessionRequired } from '~/types/auth';
import sendMail from '~/server/tasks/mail'; import sendMail from '~/../server/tasks/mail';
import type { $ZodIssue } from 'zod/v4/core'; import type { $ZodIssue } from 'zod/v4/core';
interface SuccessHandler interface SuccessHandler

View File

@ -1,5 +1,5 @@
import { eventHandler } from 'h3'; import { eventHandler } from 'h3';
import { clearUserSession } from '~/server/utils/session'; import { clearUserSession } from '~/../server/utils/session';
export default eventHandler(async (event) => { export default eventHandler(async (event) => {
await clearUserSession(event); await clearUserSession(event);

View File

@ -1,5 +1,5 @@
import { eventHandler } from 'h3' import { eventHandler } from 'h3'
import { getUserSession, sessionHooks } from '~/server/utils/session' import { getUserSession, sessionHooks } from '~/../server/utils/session'
import type { UserSessionRequired } from '~/types/auth' import type { UserSessionRequired } from '~/types/auth'
export default eventHandler(async (event) => { export default eventHandler(async (event) => {

View File

@ -2,8 +2,8 @@ import { eq } from 'drizzle-orm';
import { z } from 'zod/v4'; import { z } from 'zod/v4';
import useDatabase from '~/composables/useDatabase'; import useDatabase from '~/composables/useDatabase';
import { campaignMembersTable, campaignTable } from '~/db/schema'; import { campaignMembersTable, campaignTable } from '~/db/schema';
import { CampaignValidation } from '~/shared/campaign.util'; import { CampaignValidation } from '#shared/campaign.util';
import { cryptURI } from '~/shared/general.util'; import { cryptURI } from '#shared/general.util';
export default defineEventHandler(async (e) => { export default defineEventHandler(async (e) => {
const body = await readValidatedBody(e, CampaignValidation.extend({ id: z.unknown(), }).safeParse); const body = await readValidatedBody(e, CampaignValidation.extend({ id: z.unknown(), }).safeParse);

View File

@ -1,7 +1,7 @@
import { eq } from 'drizzle-orm'; import { eq } from 'drizzle-orm';
import useDatabase from '~/composables/useDatabase'; import useDatabase from '~/composables/useDatabase';
import { campaignTable } from '~/db/schema'; import { campaignTable } from '~/db/schema';
import { CampaignValidation } from '~/shared/campaign.util'; import { CampaignValidation } from '#shared/campaign.util';
export default defineEventHandler(async (e) => { export default defineEventHandler(async (e) => {
const params = getRouterParam(e, "id"); const params = getRouterParam(e, "id");

View File

@ -2,7 +2,7 @@ import { hash } from "bun";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import useDatabase from "~/composables/useDatabase"; import useDatabase from "~/composables/useDatabase";
import { usersTable } from "~/db/schema"; import { usersTable } from "~/db/schema";
import sendMail from '~/server/tasks/mail'; import sendMail from '~/../server/tasks/mail';
export default defineEventHandler(async (e) => { export default defineEventHandler(async (e) => {
const session = await getUserSession(e); const session = await getUserSession(e);

View File

@ -1,7 +1,7 @@
import { and, eq, sql } from "drizzle-orm"; import { and, eq, sql } from "drizzle-orm";
import useDatabase from "~/composables/useDatabase"; import useDatabase from "~/composables/useDatabase";
import { campaignMembersTable, campaignTable } from "~/db/schema"; import { campaignMembersTable, campaignTable } from "~/db/schema";
import { decryptURI } from "~/shared/general.util"; import { decryptURI } from "#shared/general.util";
export default defineEventHandler(async (e) => { export default defineEventHandler(async (e) => {
const link = getRouterParam(e, "link"); const link = getRouterParam(e, "link");

View File

@ -1,4 +1,4 @@
import { iconExists, loadIcon } from 'iconify-icon'; import { iconLoaded, loadIcon } from 'iconify-icon';
export type Node = HTMLElement | SVGElement | Text | undefined; export type Node = HTMLElement | SVGElement | Text | undefined;
export type NodeChildren = Array<Node> | undefined; export type NodeChildren = Array<Node> | undefined;
@ -128,7 +128,7 @@ export function icon(name: string, properties?: IconProperties): HTMLElement
{ {
element = document.createElement('iconify-icon'); element = document.createElement('iconify-icon');
if(!iconExists(name)) if(!iconLoaded(name))
loadIcon(name); loadIcon(name);
element.setAttribute('icon', name); element.setAttribute('icon', name);