Skip to content

Commit 7641ade

Browse files
AchoArnoldCopilot
andcommitted
fix(web): resolve Codacy static analysis type-safety warnings
- Add explicit type annotations to resolve @typescript-eslint/no-unsafe-* rules - Cast useRuntimeConfig().public to Record<string, string> for type safety - Use String#endsWith() instead of manual char comparison in stores/app.ts - Import type from ofetch for createApiFetch return type - Use relative imports in useFilters.ts instead of ~ alias - Add explicit useAuthStore imports in middleware and firebase plugin - Type the firebase compat dynamic import callback parameter - Add Plugin type annotation for vPhoneInput - Add nuxt-shims.d.ts for Nuxt auto-import type declarations - Update tsconfig.json with paths and include for external analysis tools Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 3ede7e4 commit 7641ade

8 files changed

Lines changed: 99 additions & 29 deletions

File tree

web/app/composables/useApi.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { $Fetch } from "ofetch";
2+
13
let authToken: string | null = null;
24
let apiKey: string | null = null;
35

@@ -9,9 +11,9 @@ export function setApiKey(key: string | null) {
911
apiKey = key;
1012
}
1113

12-
function createApiFetch() {
14+
function createApiFetch(): $Fetch {
1315
const config = useRuntimeConfig();
14-
const baseURL = config.public.apiBaseUrl as string;
16+
const baseURL = (config.public as Record<string, string>).apiBaseUrl;
1517

1618
return $fetch.create({
1719
baseURL,

web/app/composables/useFilters.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import {
66
formatDecimal,
77
formatBillingPeriod,
88
humanizeTime,
9-
} from "~/utils/filters";
10-
import { capitalize } from "~/utils/capitalize";
9+
} from "../utils/filters";
10+
import { capitalize } from "../utils/capitalize";
1111

1212
export function useFilters() {
1313
return {

web/app/middleware/auth.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
export default defineNuxtRouteMiddleware((to) => {
1+
import { useAuthStore } from "../stores/auth";
2+
3+
export default defineNuxtRouteMiddleware((to: { path: string }) => {
24
const authStore = useAuthStore();
35
if (authStore.authUser === null) {
46
return navigateTo({ path: "/login", query: { to: to.path } });

web/app/plugins/firebase.client.ts

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,49 @@
11
import { initializeApp, getApps } from "firebase/app";
2+
import type { FirebaseApp } from "firebase/app";
23
import { getAuth, onAuthStateChanged } from "firebase/auth";
4+
import { useAuthStore } from "../stores/auth";
35

46
export default defineNuxtPlugin(() => {
57
const config = useRuntimeConfig();
8+
const publicConfig = config.public as Record<string, string>;
69

710
// Skip initialization if no API key is configured
8-
if (!config.public.firebaseApiKey) {
11+
if (!publicConfig.firebaseApiKey) {
912
console.warn(
1013
"[firebase] No FIREBASE_API_KEY configured. Auth will not work.",
1114
);
1215
return;
1316
}
1417

1518
const firebaseConfig = {
16-
apiKey: config.public.firebaseApiKey,
17-
authDomain: config.public.firebaseAuthDomain,
18-
projectId: config.public.firebaseProjectId,
19-
storageBucket: config.public.firebaseStorageBucket,
20-
messagingSenderId: config.public.firebaseMessagingSenderId,
21-
appId: config.public.firebaseAppId,
22-
measurementId: config.public.firebaseMeasurementId,
19+
apiKey: publicConfig.firebaseApiKey,
20+
authDomain: publicConfig.firebaseAuthDomain,
21+
projectId: publicConfig.firebaseProjectId,
22+
storageBucket: publicConfig.firebaseStorageBucket,
23+
messagingSenderId: publicConfig.firebaseMessagingSenderId,
24+
appId: publicConfig.firebaseAppId,
25+
measurementId: publicConfig.firebaseMeasurementId,
2326
};
2427

2528
// Initialize Firebase (only once)
26-
const app =
29+
const app: FirebaseApp =
2730
getApps().length === 0 ? initializeApp(firebaseConfig) : getApps()[0];
2831
const auth = getAuth(app);
2932

3033
// Also initialize the compat SDK for FirebaseUI
3134
if (import.meta.client) {
32-
import("firebase/compat/app").then((firebase) => {
33-
if (!firebase.default.apps.length) {
34-
firebase.default.initializeApp(firebaseConfig);
35-
}
36-
});
35+
import("firebase/compat/app").then(
36+
(firebase: {
37+
default: {
38+
apps: unknown[];
39+
initializeApp: (config: typeof firebaseConfig) => void;
40+
};
41+
}) => {
42+
if (!firebase.default.apps.length) {
43+
firebase.default.initializeApp(firebaseConfig);
44+
}
45+
},
46+
);
3747
}
3848

3949
// Listen for auth state changes and update the auth store

web/app/plugins/vPhoneInput.client.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ import {
55
autocompletePhoneCountryInput,
66
VPhoneCountryFlagSvg,
77
} from "v-phone-input";
8+
import type { Plugin } from "vue";
89

910
export default defineNuxtPlugin((nuxtApp) => {
10-
const vPhoneInput = createVPhoneInput({
11+
const vPhoneInput: Plugin = createVPhoneInput({
1112
...autocompletePhoneCountryInput,
1213
countryDisplayComponent: VPhoneCountryFlagSvg,
1314
validate: null,

web/app/stores/app.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,24 @@ export const useAppStore = defineStore("app", () => {
1414
const polling = ref(false);
1515

1616
const appData = computed<AppData>(() => {
17-
let url = (config.public.appUrl as string) || "";
18-
if (url.length > 0 && url[url.length - 1] === "/") {
17+
const publicConfig = config.public as Record<string, string>;
18+
let url = publicConfig.appUrl || "";
19+
if (url.endsWith("/")) {
1920
url = url.substring(0, url.length - 1);
2021
}
2122
return {
2223
url,
23-
env: config.public.appEnv as string,
24-
appDownloadUrl: config.public.appDownloadUrl as string,
25-
documentationUrl: config.public.appDocumentationUrl as string,
26-
githubUrl: config.public.appGithubUrl as string,
27-
name: config.public.appName as string,
24+
env: publicConfig.appEnv,
25+
appDownloadUrl: publicConfig.appDownloadUrl,
26+
documentationUrl: publicConfig.appDocumentationUrl,
27+
githubUrl: publicConfig.appGithubUrl,
28+
name: publicConfig.appName,
2829
};
2930
});
3031

31-
const isLocal = computed(() => config.public.appEnv === "local");
32+
const isLocal = computed(
33+
() => (config.public as Record<string, string>).appEnv === "local",
34+
);
3235

3336
function setPolling(value: boolean) {
3437
polling.value = value;

web/app/types/nuxt-shims.d.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* Type declarations for Nuxt auto-imports.
3+
* These are normally generated in .nuxt/ by `nuxt prepare` but are provided
4+
* here so that external static analysis tools (e.g. Codacy) can resolve types
5+
* without running the Nuxt build pipeline.
6+
*/
7+
8+
import type { $Fetch } from "ofetch";
9+
import type { App } from "vue";
10+
11+
declare global {
12+
// Nuxt composables
13+
function useRuntimeConfig(): {
14+
public: Record<string, string>;
15+
[key: string]: unknown;
16+
};
17+
18+
// Nuxt fetch utility
19+
const $fetch: $Fetch;
20+
21+
// Nuxt plugin helper
22+
function defineNuxtPlugin(
23+
plugin: (nuxtApp: { vueApp: App }) => void | Record<string, unknown>,
24+
): unknown;
25+
26+
// Nuxt route middleware helper
27+
function defineNuxtRouteMiddleware(
28+
middleware: (to: {
29+
path: string;
30+
query?: Record<string, string>;
31+
}) => unknown,
32+
): unknown;
33+
34+
// Nuxt navigation
35+
function navigateTo(
36+
to: string | { path: string; query?: Record<string, string | undefined> },
37+
): unknown;
38+
}
39+
40+
export {};

web/tsconfig.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,17 @@
1414
{
1515
"path": "./.nuxt/tsconfig.node.json"
1616
}
17-
]
17+
],
18+
"compilerOptions": {
19+
"strict": true,
20+
"moduleResolution": "bundler",
21+
"module": "ESNext",
22+
"target": "ESNext",
23+
"paths": {
24+
"~/*": ["./app/*"],
25+
"~~/*": ["./*"],
26+
"#imports": ["./app/types/nuxt-shims"]
27+
}
28+
},
29+
"include": ["app/**/*.ts", "app/**/*.d.ts", "shared/**/*.ts"]
1830
}

0 commit comments

Comments
 (0)