Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/typecheck.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Frontend TypeScript

on:
push:
branches:
- develop
paths:
- "frontend/**"
- ".github/workflows/typecheck.yml"
pull_request:
paths:
- "frontend/**"
- ".github/workflows/typecheck.yml"

concurrency:
group: typecheck-forms_pro-${{ github.event.number || github.sha }}
cancel-in-progress: true

jobs:
typecheck:
name: TypeScript
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "24"
cache: "yarn"
cache-dependency-path: frontend/yarn.lock

- name: Install dependencies
working-directory: frontend
run: yarn install --frozen-lockfile

- name: Type check
working-directory: frontend
run: yarn typecheck
4 changes: 3 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"build": "vite build --base=/assets/forms_pro/frontend/ && yarn copy-html-entry",
"preview": "vite preview",
"lint": "biome check --write .",
"typecheck": "./typecheck.sh",
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n frontend/package.json

Repository: BuildWithHussain/forms_pro

Length of output: 1500


🏁 Script executed:

cat -n frontend/typecheck.sh

Repository: BuildWithHussain/forms_pro

Length of output: 568


🏁 Script executed:

rg 'vue-tsc' frontend/

Repository: BuildWithHussain/forms_pro

Length of output: 52


Use vue-tsc instead of tsc to type-check .vue files.

Plain tsc --noEmit only checks .ts/.tsx files; it cannot parse or type-check Vue SFCs. Your current typecheck.sh uses tsc --noEmit, which means any type errors in <script lang="ts"> blocks in .vue files are silently ignored. This is a Vue 3 + TypeScript project, so vue-tsc is the correct tool.

  1. Add vue-tsc as a dev dependency.
  2. Replace tsc --noEmit with vue-tsc --noEmit in typecheck.sh.

Without this, the CI typecheck step provides a false sense of safety — the codebase can have undetected type errors in Vue components.

🤖 Prompt for AI Agents
In `@frontend/package.json` at line 11, The typecheck step currently runs tsc
--noEmit (referenced in the "typecheck" script and typecheck.sh) which doesn't
type-check Vue SFCs; install vue-tsc as a devDependency and update typecheck.sh
(and the "typecheck" script if it invokes tsc) to run vue-tsc --noEmit instead
of tsc --noEmit so .vue <script lang="ts"> blocks are properly type-checked.

"copy-html-entry": "cp ../forms_pro/public/frontend/index.html ../forms_pro/www/forms.html"
},
"dependencies": {
Expand Down Expand Up @@ -35,6 +36,7 @@
"tailwindcss": "^3.4.15",
"typescript": "^5.9.3",
"vite": "^5.4.10",
"vitest": "^2.1.8"
"vitest": "^2.1.8",
"vue-tsc": "^3.2.4"
}
}
2 changes: 2 additions & 0 deletions frontend/src/components/fields/Attachment.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const props = defineProps({

const emit = defineEmits(["update:value"]);

// @ts-ignore
const value = defineModel<string>();

const inPreview = ref(false);
Expand Down Expand Up @@ -68,6 +69,7 @@ const handleRemove = () => {
v-bind="props.field"
@success="(file: FileType) => handleChange(file)"
>
<!-- @vue-ignore -->
<template #default="{ uploading, progress, error, openFileSelector }">
<Button @click="openFileSelector()" :loading="uploading">
{{ uploading ? `Uploading ${progress}%` : "Upload" }}
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/form/manage/AccessSection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ function setPermission(row: any, column: any, value: boolean) {
}"
row-key="email"
>
<!-- @vue-ignore -->
<template #cell="{ item, row, column }">
<div
v-if="column.key === 'full_name'"
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/Dashboard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
/>
</div>
</template>
<template #actions="{ close }">
<template #actions>
<Button
class="w-full"
variant="solid"
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const routes: RouteRecordRaw[] = [
name: "Form Submission Page",
component: () => import("@/pages/SubmissionPage.vue"),
meta: { allowGuest: true },
beforeEnter: async (to, from) => {
beforeEnter: async (to, _from) => {
const loginRequired = await isLoginRequired(to.params.route as string);

if (loginRequired && !session.isLoggedIn) {
Expand All @@ -54,7 +54,7 @@ const router = createRouter({
routes,
});

router.beforeEach(async (to, from, next) => {
router.beforeEach(async (to, _from, next) => {
let isLoggedIn = session.isLoggedIn;
try {
await userResource.promise;
Expand Down
1 change: 1 addition & 0 deletions frontend/src/socket.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { io, Socket } from "socket.io-client";
// @ts-ignore
import { socketio_port } from "../../../../sites/common_site_config.json";

let socket: Socket | null = null;
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/stores/editForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { defineStore } from "pinia";
import { ref, computed } from "vue";
import { createDocumentResource, createResource } from "frappe-ui";
import { mapDoctypeFieldForForm } from "@/utils/form_fields";
import { FormField } from "@/types/formfield";
import { FormField, FormFieldTypes } from "@/types/formfield";
import { Form } from "@/types/form";
import { toast } from "vue-sonner";

Expand Down Expand Up @@ -155,7 +155,7 @@ export const useEditForm = defineStore("editForm", () => {
if (formResource.value?.doc) {
const newField: FormField = {
idx: formResource.value.doc.fields.length + 1,
fieldtype,
fieldtype: fieldtype as FormFieldTypes,
label: "",
fieldname: "",
options: "",
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/stores/editSubmission.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createDocumentResource, createResource } from "frappe-ui";
import { createDocumentResource } from "frappe-ui";
import { defineStore } from "pinia";
import { computed, ref } from "vue";
import { toast } from "vue-sonner";
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/stores/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export const useUser = defineStore("user", () => {
userTeamsResource.fetch();
}

// @ts-ignore
function getCurrentTeamFromAllTeams() {
return userTeams.value?.find((team) => team.is_current);
}
Expand Down Expand Up @@ -95,7 +96,7 @@ export const useUser = defineStore("user", () => {
team_name: teamName,
};
},
onSuccess(data: CreateTeamResponse) {
onSuccess() {
userTeamsResource.reload();
toast.success("Team created successfully");
},
Expand Down
5 changes: 3 additions & 2 deletions frontend/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "bundler",
Expand All @@ -20,6 +20,7 @@
"@/*": ["src/*"]
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "src/main.ts"],
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "src/main.ts", "types.d.ts"],
"exclude": ["node_modules"],
"references": [{ "path": "./tsconfig.node.json" }]
}
13 changes: 13 additions & 0 deletions frontend/typecheck.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash
# Typecheck script that filters out errors from node_modules
# Doing this because frappe-ui has a lot of errors that are not related to our code
OUTPUT=$(vue-tsc --noEmit 2>&1)
ERRORS=$(echo "$OUTPUT" | grep -E "^(src/|error TS)" | grep -v "node_modules/")

if [ -n "$ERRORS" ]; then
echo "$ERRORS"
exit 1
else
echo "Type check completed successfully (node_modules errors ignored)"
exit 0
fi
6 changes: 6 additions & 0 deletions frontend/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Global type declarations to handle Vue files
declare module "*.vue" {
import type { DefineComponent } from "vue";
const component: DefineComponent<{}, {}, any>;
export default component;
}
Loading