Skip to content

Type checking in the build process #52

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
9 changes: 6 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ jobs:
node-version: '22'
cache: 'npm'

- name: Install Node Dependencies
run: npm ci

- name: Install Dependencies
run: composer install --no-interaction --prefer-dist --optimize-autoloader

Expand All @@ -46,6 +43,12 @@ jobs:
- name: Publish Ziggy Configuration
run: php artisan ziggy:generate

- name: Install Node Dependencies
run: npm ci

- name: Validate typescript
run: npm run type:check

- name: Build Assets
run: npm run build

Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
"type": "module",
"scripts": {
"build": "vite build",
"build:ssr": "vite build && vite build --ssr",
"build:ssr": "vite build --ssr",
"dev": "vite",
"format": "prettier --write resources/",
"format:check": "prettier --check resources/",
"lint": "eslint . --fix"
"lint": "eslint . --fix",
"type:check": "vue-tsc --noEmit"
},
"devDependencies": {
"@eslint/js": "^9.19.0",
Expand Down
13 changes: 0 additions & 13 deletions resources/js/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,6 @@ import { createApp, h } from 'vue';
import { ZiggyVue } from 'ziggy-js';
import { initializeTheme } from './composables/useAppearance';

// Extend ImportMeta interface for Vite...
declare module 'vite/client' {
interface ImportMetaEnv {
readonly VITE_APP_NAME: string;
[key: string]: string | boolean | undefined;
}

interface ImportMeta {
readonly env: ImportMetaEnv;
readonly glob: <T>(pattern: string) => Record<string, () => Promise<T>>;
}
}

const appName = import.meta.env.VITE_APP_NAME || 'Laravel';

createInertiaApp({
Expand Down
4 changes: 2 additions & 2 deletions resources/js/components/AppHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from '@/co
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import UserMenuContent from '@/components/UserMenuContent.vue';
import { getInitials } from '@/composables/useInitials';
import type { BreadcrumbItem, NavItem } from '@/types';
import type { BreadcrumbItem, NavItem, SharedData } from '@/types';
import { Link, usePage } from '@inertiajs/vue3';
import { BookOpen, Folder, LayoutGrid, Menu, Search } from 'lucide-vue-next';
import { computed } from 'vue';
Expand All @@ -29,7 +29,7 @@ const props = withDefaults(defineProps<Props>(), {
breadcrumbs: () => [],
});

const page = usePage();
const page = usePage<SharedData>();
const auth = computed(() => page.props.auth);

const isCurrentRoute = computed(() => (url: string) => page.url === url);
Expand Down
2 changes: 1 addition & 1 deletion resources/js/components/AppSidebarHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ defineProps<{
>
<div class="flex items-center gap-2">
<SidebarTrigger class="-ml-1" />
<template v-if="breadcrumbs.length > 0">
<template v-if="breadcrumbs && breadcrumbs.length > 0">
<Breadcrumbs :breadcrumbs="breadcrumbs" />
</template>
</div>
Expand Down
9 changes: 3 additions & 6 deletions resources/js/components/TextLink.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
<script setup lang="ts">
import { Link } from '@inertiajs/vue3';
import { InertiaLinkProps, Link } from '@inertiajs/vue3';

interface Props {
href: string;
interface Props extends Pick<InertiaLinkProps, "href" | "method" | "as"> {
tabindex?: number;
method?: string;
as?: string;
}
};

defineProps<Props>();
</script>
Expand Down
8 changes: 2 additions & 6 deletions resources/js/components/UserInfo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,22 @@
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { useInitials } from '@/composables/useInitials';
import type { User } from '@/types';
import { computed } from 'vue';

interface Props {
user: User;
showEmail?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
withDefaults(defineProps<Props>(), {
showEmail: false,
});

const { getInitials } = useInitials();

// Compute whether we should show the avatar image
const showAvatar = computed(() => props.user.avatar && props.user.avatar !== '');
</script>

<template>
<Avatar class="h-8 w-8 overflow-hidden rounded-lg">
<AvatarImage v-if="showAvatar" :src="user.avatar" :alt="user.name" />
<AvatarImage v-if="user.avatar && user.avatar !== ''" :src="user.avatar" :alt="user.name" />
<AvatarFallback class="rounded-lg text-black dark:text-white">
{{ getInitials(user.name) }}
</AvatarFallback>
Expand Down
5 changes: 3 additions & 2 deletions resources/js/layouts/auth/AuthSplitLayout.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<script setup lang="ts">
import AppLogoIcon from '@/components/AppLogoIcon.vue';
import { SharedData } from '@/types';
import { Link, usePage } from '@inertiajs/vue3';

const page = usePage();
const page = usePage<SharedData>();
const name = page.props.name;
const quote = page.props.quote;

Expand All @@ -20,7 +21,7 @@ defineProps<{
<AppLogoIcon class="mr-2 size-8 fill-current text-white" />
{{ name }}
</Link>
<div v-if="quote" class="relative z-20 mt-auto">
<div v-if="quote && quote" class="relative z-20 mt-auto">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does the extra && quote do for that v-if where it's already checking if there is a quote?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, @christophstockinger, do you happen to know why there is this extra && quote here. LMK

<blockquote class="space-y-2">
<p class="text-lg">&ldquo;{{ quote.message }}&rdquo;</p>
<footer class="text-sm text-neutral-300">{{ quote.author }}</footer>
Expand Down
4 changes: 2 additions & 2 deletions resources/js/layouts/settings/Layout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import Heading from '@/components/Heading.vue';
import { Button } from '@/components/ui/button';
import { Separator } from '@/components/ui/separator';
import { type NavItem } from '@/types';
import type { NavItem, SharedData } from '@/types';
import { Link, usePage } from '@inertiajs/vue3';

const sidebarNavItems: NavItem[] = [
Expand All @@ -20,7 +20,7 @@ const sidebarNavItems: NavItem[] = [
},
];

const page = usePage();
const page = usePage<SharedData>();

const currentPath = page.props.ziggy?.location ? new URL(page.props.ziggy.location).pathname : '';
</script>
Expand Down
10 changes: 9 additions & 1 deletion resources/js/pages/Welcome.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<script setup lang="ts">
import { SharedData } from '@/types';
import { Head, Link } from '@inertiajs/vue3';

const props = defineProps<SharedData>();
</script>

<template>
Expand All @@ -11,7 +14,7 @@ import { Head, Link } from '@inertiajs/vue3';
<header class="not-has-[nav]:hidden mb-6 w-full max-w-[335px] text-sm lg:max-w-4xl">
<nav class="flex items-center justify-end gap-4">
<Link
v-if="$page.props.auth.user"
v-if="props.auth.user"
:href="route('dashboard')"
class="inline-block rounded-sm border border-[#19140035] px-5 py-1.5 text-sm leading-normal text-[#1b1b18] hover:border-[#1915014a] dark:border-[#3E3E3A] dark:text-[#EDEDEC] dark:hover:border-[#62605b]"
>
Expand Down Expand Up @@ -214,6 +217,11 @@ import { Head, Link } from '@inertiajs/vue3';
stroke-width="1"
/>
</g>
<!-- Workaround: -->
<!-- 'plus-darker' is a valid value for the mixBlendMode key according to MDN -->
<!-- However, the csstype library, which is used by @vue/runtime-dom, does not support this value. -->
<!-- @see https://developer.mozilla.org/de/docs/Web/CSS/mix-blend-mode -->
<!-- @vue-ignore -->
<g
:style="{ mixBlendMode: 'plus-darker' }"
class="duration-750 starting:translate-y-4 starting:opacity-0 translate-y-0 opacity-100 transition-all delay-300"
Expand Down
15 changes: 15 additions & 0 deletions resources/js/ssr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,44 @@ import { route as ziggyRoute } from 'ziggy-js';

const appName = import.meta.env.VITE_APP_NAME || 'Laravel';

/**
* Added eslint-disable-next-line @typescript-eslint/ban-ts-comment and @ts-ignore to fix the error.
* I'm not sure if the fix really leads to a type-safe Javascript. However, it looks like a javascript hack to me, which is perfectly legitimate.
*/

createServer((page) =>
createInertiaApp({
page,
render: renderToString,
title: (title) => `${title} - ${appName}`,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
resolve: (name) => resolvePageComponent(`./pages/${name}.vue`, import.meta.glob('./pages/**/*.vue')),
setup({ App, props, plugin }) {
const app = createSSRApp({ render: () => h(App, props) });

// Configure Ziggy for SSR...
const ziggyConfig = {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
...page.props.ziggy,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
location: new URL(page.props.ziggy.location),
};

// Create route function...
const route = (name: string, params?: any, absolute?: boolean) => ziggyRoute(name, params, absolute, ziggyConfig);

// Make route function available globally...
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
app.config.globalProperties.route = route;

// Make route function available globally for SSR...
if (typeof window === 'undefined') {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
global.route = route;
}

Expand Down
5 changes: 0 additions & 5 deletions resources/js/types/globals.d.ts

This file was deleted.

7 changes: 3 additions & 4 deletions resources/js/types/ziggy.d.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { RouteParams, Router } from 'ziggy-js';
import type { route as routeFn } from 'ziggy-js';

declare global {
function route(): Router;
function route(name: string, params?: RouteParams<typeof name> | undefined, absolute?: boolean): string;
const route: typeof routeFn;
}

declare module '@vue/runtime-core' {
interface ComponentCustomProperties {
route: typeof route;
route: typeof routeFn;
}
}
11 changes: 4 additions & 7 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,7 @@
},
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
"types": [
"vite/client",
"vue/tsx",
"./resources/js/types"
] /* Specify type package names to be included without being referenced in a source file. */,
//"types": [] /* Specify type package names to be included without being referenced in a source file. */,
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
// "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
Expand Down Expand Up @@ -122,7 +118,8 @@
"include": [
"resources/js/**/*.ts",
"resources/js/**/*.d.ts",
"resources/js/**/*.tsx",
"resources/js/**/*.vue"
"resources/js/**/*.tsx",
"resources/js/**/*.vue",
"node_modules/vite/client.d.ts"
]
}