ts errors

This commit is contained in:
Hayden 2023-02-17 18:56:29 -09:00
parent af3b34a4ba
commit 13d3c727ba
No known key found for this signature in database
GPG key ID: 17CF79474E257545
17 changed files with 68 additions and 59 deletions

View file

@ -38,12 +38,10 @@
default: "", default: "",
}, },
modelValue: { modelValue: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type: Array as () => any[], type: Array as () => any[],
default: null, default: null,
}, },
items: { items: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type: Array as () => any[], type: Array as () => any[],
required: true, required: true,
}, },

View file

@ -24,12 +24,10 @@
default: "", default: "",
}, },
modelValue: { modelValue: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type: [Object, String] as any, type: [Object, String] as any,
default: null, default: null,
}, },
items: { items: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type: Array as () => any[], type: Array as () => any[],
required: true, required: true,
}, },
@ -86,7 +84,6 @@
{ immediate: true } { immediate: true }
); );
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function compare(a: any, b: any): boolean { function compare(a: any, b: any): boolean {
if (a === b) { if (a === b) {
return true; return true;

View file

@ -1,7 +1,6 @@
import { UseConfirmDialogRevealResult, UseConfirmDialogReturn } from "@vueuse/core"; import { UseConfirmDialogRevealResult, UseConfirmDialogReturn } from "@vueuse/core";
import { Ref } from "vue"; import { Ref } from "vue";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type Store = UseConfirmDialogReturn<any, boolean, boolean> & { type Store = UseConfirmDialogReturn<any, boolean, boolean> & {
text: Ref<string>; text: Ref<string>;
setup: boolean; setup: boolean;
@ -23,7 +22,7 @@ const store: Partial<Store> = {
export function useConfirm(): Store { export function useConfirm(): Store {
if (!store.setup) { if (!store.setup) {
store.setup = true; store.setup = true;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const { isRevealed, reveal, confirm, cancel } = useConfirmDialog<any, boolean, boolean>(); const { isRevealed, reveal, confirm, cancel } = useConfirmDialog<any, boolean, boolean>();
store.isRevealed = isRevealed; store.isRevealed = isRevealed;
store.reveal = reveal; store.reveal = reveal;

View file

@ -7,7 +7,7 @@ export function useRouteQuery(q: string, def: string[]): WritableComputedRef<str
export function useRouteQuery(q: string, def: string): WritableComputedRef<string>; export function useRouteQuery(q: string, def: string): WritableComputedRef<string>;
export function useRouteQuery(q: string, def: boolean): WritableComputedRef<boolean>; export function useRouteQuery(q: string, def: boolean): WritableComputedRef<boolean>;
export function useRouteQuery(q: string, def: number): WritableComputedRef<number>; export function useRouteQuery(q: string, def: number): WritableComputedRef<number>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function useRouteQuery(q: string, def: any): WritableComputedRef<any> { export function useRouteQuery(q: string, def: any): WritableComputedRef<any> {
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();

View file

@ -16,13 +16,13 @@ export function useTheme(): UseTheme {
preferences.value.theme = newTheme; preferences.value.theme = newTheme;
if (htmlEl) { if (htmlEl) {
htmlEl.value.setAttribute("data-theme", newTheme); htmlEl.value?.setAttribute("data-theme", newTheme);
} }
themeRef.value = newTheme; themeRef.value = newTheme;
}; };
const htmlEl = ref<HTMLElement>(null); const htmlEl = ref<HTMLElement | null>();
onMounted(() => { onMounted(() => {
if (htmlEl.value) { if (htmlEl.value) {

View file

@ -9,13 +9,13 @@ import { Requests } from "../../../requests";
function itemField(id = null): ItemField { function itemField(id = null): ItemField {
return { return {
id, id: id ?? "",
name: faker.lorem.word(), name: faker.lorem.word(),
type: "text", type: "text",
textValue: faker.lorem.sentence(), textValue: faker.lorem.sentence(),
booleanValue: false, booleanValue: false,
numberValue: faker.datatype.number(), numberValue: faker.datatype.number(),
timeValue: null, timeValue: "",
}; };
} }
@ -32,8 +32,9 @@ function user(): UserRegistration {
}; };
} }
function location(): LocationCreate { function location(parentId: string | null = null): LocationCreate {
return { return {
parentId,
name: faker.address.city(), name: faker.address.city(),
description: faker.lorem.sentence(), description: faker.lorem.sentence(),
}; };
@ -56,7 +57,7 @@ function publicClient(): PublicApi {
function userClient(token: string): UserClient { function userClient(token: string): UserClient {
overrideParts(config.BASE_URL, "/api/v1"); overrideParts(config.BASE_URL, "/api/v1");
const requests = new Requests("", token); const requests = new Requests("", token);
return new UserClient(requests); return new UserClient(requests, "");
} }
type TestUser = { type TestUser = {
@ -75,7 +76,7 @@ async function userSingleUse(): Promise<TestUser> {
expect(result.status).toBe(200); expect(result.status).toBe(200);
return { return {
client: new UserClient(new Requests("", result.data.token)), client: new UserClient(new Requests("", result.data.token), result.data.attachmentToken),
user: usr, user: usr,
}; };
} }

View file

@ -1,6 +1,6 @@
import { faker } from "@faker-js/faker"; import { faker } from "@faker-js/faker";
import { describe, test, expect } from "vitest"; import { describe, test, expect } from "vitest";
import { ItemField, LocationOut } from "../../types/data-contracts"; import { ItemField, ItemUpdate, LocationOut } from "../../types/data-contracts";
import { AttachmentTypes } from "../../types/non-generated"; import { AttachmentTypes } from "../../types/non-generated";
import { UserClient } from "../../user"; import { UserClient } from "../../user";
import { factories } from "../factories"; import { factories } from "../factories";
@ -14,6 +14,7 @@ describe("user should be able to create an item and add an attachment", () => {
*/ */
async function useLocation(api: UserClient): Promise<[LocationOut, () => Promise<void>]> { async function useLocation(api: UserClient): Promise<[LocationOut, () => Promise<void>]> {
const { response, data } = await api.locations.create({ const { response, data } = await api.locations.create({
parentId: null,
name: `__test__.location.name_${increment}`, name: `__test__.location.name_${increment}`,
description: `__test__.location.description_${increment}`, description: `__test__.location.description_${increment}`,
}); });
@ -86,12 +87,12 @@ describe("user should be able to create an item and add an attachment", () => {
const itemUpdate = { const itemUpdate = {
parentId: null, parentId: null,
...item, ...item,
locationId: item.location.id, locationId: item.location?.id || null,
labelIds: item.labels.map(l => l.id), labelIds: item.labels.map(l => l.id),
fields, fields,
}; };
const { response: updateResponse, data: item2 } = await api.items.update(item.id, itemUpdate); const { response: updateResponse, data: item2 } = await api.items.update(item.id, itemUpdate as ItemUpdate);
expect(updateResponse.status).toBe(200); expect(updateResponse.status).toBe(200);
expect(item2.fields).toHaveLength(fields.length); expect(item2.fields).toHaveLength(fields.length);
@ -104,7 +105,7 @@ describe("user should be able to create an item and add an attachment", () => {
itemUpdate.fields = [fields[0], fields[1]]; itemUpdate.fields = [fields[0], fields[1]];
const { response: updateResponse2, data: item3 } = await api.items.update(item.id, itemUpdate); const { response: updateResponse2, data: item3 } = await api.items.update(item.id, itemUpdate as ItemUpdate);
expect(updateResponse2.status).toBe(200); expect(updateResponse2.status).toBe(200);
expect(item3.fields).toHaveLength(2); expect(item3.fields).toHaveLength(2);

View file

@ -49,6 +49,8 @@ describe("locations lifecycle (create, update, delete)", () => {
const [location, cleanup] = await useLocation(api); const [location, cleanup] = await useLocation(api);
const updateData = { const updateData = {
id: location.id,
parentId: location.parent?.id,
name: "test-location-updated", name: "test-location-updated",
description: "test-description-updated", description: "test-description-updated",
}; };

View file

@ -77,13 +77,13 @@ function importFileGenerator(entries: number): ImportObj[] {
describe("group related statistics tests", () => { describe("group related statistics tests", () => {
const TOTAL_ITEMS = 30; const TOTAL_ITEMS = 30;
let api: UserClient | undefined; let tAPI: UserClient | undefined;
const imports = importFileGenerator(TOTAL_ITEMS); const imports = importFileGenerator(TOTAL_ITEMS);
beforeAll(async () => { beforeAll(async () => {
// -- Setup -- // -- Setup --
const { client } = await factories.client.singleUse(); const { client } = await factories.client.singleUse();
api = client; tAPI = client;
const csv = toCsv(imports); const csv = toCsv(imports);
@ -92,6 +92,13 @@ describe("group related statistics tests", () => {
expect(setupResp.status).toBe(204); expect(setupResp.status).toBe(204);
}); });
if (!tAPI) {
throw new Error("API is not defined");
}
// cast api to concrete type
const api = tAPI;
// Write to file system for debugging // Write to file system for debugging
// fs.writeFileSync("test.csv", csv); // fs.writeFileSync("test.csv", csv);
test("Validate Group Statistics", async () => { test("Validate Group Statistics", async () => {

View file

@ -9,8 +9,8 @@ type BaseApiType = {
[key: string]: any; [key: string]: any;
}; };
export function hasKey(obj: object, key: string): obj is Required<BaseApiType> { export function hasKey(obj: Record<string, any>, key: string): obj is Required<BaseApiType> {
return typeof obj[key] === "string"; return key in obj ? typeof obj[key] === "string" : false;
} }
export function parseDate<T>(obj: T, keys: Array<keyof T> = []): T { export function parseDate<T>(obj: T, keys: Array<keyof T> = []): T {

View file

@ -141,4 +141,8 @@ export class ItemsApi extends BaseAPI {
data: formData, data: formData,
}); });
} }
exportURL() {
return route("/items/export");
}
} }

View file

@ -1,27 +1,7 @@
import { BaseAPI, route } from "../base"; import { BaseAPI, route } from "../base";
export class ReportsAPI extends BaseAPI { export class ReportsAPI extends BaseAPI {
async billOfMaterials(): Promise<void> { billOfMaterialsURL(): string {
const { data: stream, error } = await this.http.get<ReadableStream>({ url: route("/reporting/bill-of-materials") }); return route("/reporting/bill-of-materials");
if (error) {
return;
}
const reader = stream.getReader();
let data = "";
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
data += new TextDecoder("utf-8").decode(value);
}
const blob = new Blob([data], { type: "text/tsv" });
const link = document.createElement("a");
link.href = window.URL.createObjectURL(blob);
link.download = "bill-of-materials.tsv";
link.click();
} }
} }

View file

@ -76,6 +76,7 @@ export class Requests {
const token = this.token(); const token = this.token();
if (token !== "" && payload.headers !== undefined) { if (token !== "" && payload.headers !== undefined) {
// @ts-expect-error - we know that the header is there
payload.headers["Authorization"] = token; // eslint-disable-line dot-notation payload.headers["Authorization"] = token; // eslint-disable-line dot-notation
} }
@ -83,6 +84,7 @@ export class Requests {
if (rargs.data) { if (rargs.data) {
payload.body = rargs.data; payload.body = rargs.data;
} else { } else {
// @ts-expect-error - we know that the header is there
payload.headers["Content-Type"] = "application/json"; payload.headers["Content-Type"] = "application/json";
payload.body = JSON.stringify(rargs.body); payload.body = JSON.stringify(rargs.body);
} }

View file

@ -50,16 +50,16 @@
name: "Created", name: "Created",
text: location.value?.createdAt, text: location.value?.createdAt,
type: "date", type: "date",
}, } as AnyDetail,
{ {
name: "Updated", name: "Updated",
text: location.value?.updatedAt, text: location.value?.updatedAt,
type: "date", type: "date",
}, } as AnyDetail,
{ {
name: "Database ID", name: "Database ID",
text: location.value?.id, text: location.value?.id,
}, } as AnyDetail,
]; ];
} }
@ -120,7 +120,6 @@
const locationStore = useLocationStore(); const locationStore = useLocationStore();
const locations = computed(() => locationStore.allLocations); const locations = computed(() => locationStore.allLocations);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const parent = ref<LocationSummary | any>({}); const parent = ref<LocationSummary | any>({});
</script> </script>

View file

@ -14,13 +14,17 @@ export const useLabelStore = defineStore("labels", {
*/ */
labels(state): LabelOut[] { labels(state): LabelOut[] {
if (state.allLabels === null) { if (state.allLabels === null) {
Promise.resolve(this.refresh()); this.client.labels.getAll().then(result => {
if (result.error) {
console.error(result.error);
} }
return state.allLabels; });
}
return state.allLabels ?? [];
}, },
}, },
actions: { actions: {
async refresh(): Promise<LabelOut[]> { async refresh() {
const result = await this.client.labels.getAll(); const result = await this.client.labels.getAll();
if (result.error) { if (result.error) {
return result; return result;

View file

@ -1,4 +1,5 @@
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { LocationsApi } from "~~/lib/api/classes/locations";
import { LocationOutCount } from "~~/lib/api/types/data-contracts"; import { LocationOutCount } from "~~/lib/api/types/data-contracts";
export const useLocationStore = defineStore("locations", { export const useLocationStore = defineStore("locations", {
@ -15,19 +16,33 @@ export const useLocationStore = defineStore("locations", {
*/ */
parentLocations(state): LocationOutCount[] { parentLocations(state): LocationOutCount[] {
if (state.parents === null) { if (state.parents === null) {
Promise.resolve(this.refreshParents()); this.client.locations.getAll({ filterChildren: true }).then(result => {
if (result.error) {
console.error(result.error);
return;
} }
return state.parents;
this.parents = result.data.items;
});
}
return state.parents ?? [];
}, },
allLocations(state): LocationOutCount[] { allLocations(state): LocationOutCount[] {
if (state.Locations === null) { if (state.Locations === null) {
Promise.resolve(this.refreshChildren()); this.client.locations.getAll({ filterChildren: false }).then(result => {
if (result.error) {
console.error(result.error);
return;
} }
return state.Locations;
this.Locations = result.data.items;
});
}
return state.Locations ?? [];
}, },
}, },
actions: { actions: {
async refreshParents(): Promise<LocationOutCount[]> { async refreshParents(): ReturnType<LocationsApi["getAll"]> {
const result = await this.client.locations.getAll({ filterChildren: true }); const result = await this.client.locations.getAll({ filterChildren: true });
if (result.error) { if (result.error) {
return result; return result;
@ -36,7 +51,7 @@ export const useLocationStore = defineStore("locations", {
this.parents = result.data.items; this.parents = result.data.items;
return result; return result;
}, },
async refreshChildren(): Promise<LocationOutCount[]> { async refreshChildren(): ReturnType<LocationsApi["getAll"]> {
const result = await this.client.locations.getAll({ filterChildren: false }); const result = await this.client.locations.getAll({ filterChildren: false });
if (result.error) { if (result.error) {
return result; return result;

View file

@ -13,7 +13,7 @@ export const setup = () => {
export const teardown = () => { export const teardown = () => {
if (process.env.TEST_SHUTDOWN_API_SERVER) { if (process.env.TEST_SHUTDOWN_API_SERVER) {
const pc = exec("pkill -SIGTERM api"); // Kill background API process const pc = exec("pkill -SIGTERM api"); // Kill background API process
pc.stdout.on("data", data => { pc.stdout?.on("data", data => {
console.log(`stdout: ${data}`); console.log(`stdout: ${data}`);
}); });
} }