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
@@ -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

@@ -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

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -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",
13 changes: 0 additions & 13 deletions resources/js/app.ts
Original file line number Diff line number Diff line change
@@ -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({
4 changes: 2 additions & 2 deletions resources/js/components/AppHeader.vue
Original file line number Diff line number Diff line change
@@ -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';
@@ -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);
2 changes: 1 addition & 1 deletion resources/js/components/AppSidebarHeader.vue
Original file line number Diff line number Diff line change
@@ -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>
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>
8 changes: 2 additions & 6 deletions resources/js/components/UserInfo.vue
Original file line number Diff line number Diff line change
@@ -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>
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;

@@ -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>
4 changes: 2 additions & 2 deletions resources/js/layouts/settings/Layout.vue
Original file line number Diff line number Diff line change
@@ -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[] = [
@@ -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>
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>
@@ -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]"
>
@@ -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"
15 changes: 15 additions & 0 deletions resources/js/ssr.ts
Original file line number Diff line number Diff line change
@@ -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;
}

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
@@ -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. */
@@ -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"
]
}