diff --git a/packages/core/src/database/schema.ts b/packages/core/src/database/schema.ts index 24739b20..96160df5 100644 --- a/packages/core/src/database/schema.ts +++ b/packages/core/src/database/schema.ts @@ -96,6 +96,7 @@ type ColumnType = U extends "varchar" ? BoolColumn : BasicColumn; +// eslint-disable-next-line @typescript-eslint/no-unused-vars function defineColumn(type: U): ColumnType { return { type, diff --git a/packages/core/src/database/schemaManager.ts b/packages/core/src/database/schemaManager.ts index c7ee758a..38fbfa06 100644 --- a/packages/core/src/database/schemaManager.ts +++ b/packages/core/src/database/schemaManager.ts @@ -1,7 +1,7 @@ import { DatabaseSchema, Migration } from "./databaseTypes"; import { TableSchema } from "./tableSchema"; import { Trigger } from "./trigger"; -import { delay, equalsIgnore, getElseSet } from "../tools"; +import { delay, equalsIgnore } from "../tools"; import { DatabaseContext } from "./contexts/databaseContext"; import logger from "../logger"; import { EmptyPromise, Nullable } from "../types"; @@ -176,62 +176,6 @@ export class SchemaManager { await context.updateDatabaseVersion(currentVersion); logger.info("successfully migrated storage", { from: previousVersion, to: currentVersion }); } - - private getShortest(previousVersion: number) { - const root: Root = { - children: [], - }; - const fromVersionMap: Map = new Map(); - - for (const migration of this.migrations) { - const fromMigrations = getElseSet(fromVersionMap, migration.fromVersion, () => []); - fromMigrations.push({ migration, children: [], parents: [] }); - } - for (const [from, value] of fromVersionMap.entries()) { - if (from === previousVersion) { - root.children.push(...value); - - for (const node of value) { - node.parents.push(root); - } - } - if (from <= previousVersion) { - continue; - } - for (const node of value) { - const nodes = fromVersionMap.get(node.migration.toVersion); - - if (nodes == null) { - continue; - } - node.children.push(...nodes); - - for (const child of nodes) { - child.parents.push(node); - } - } - } - const currentPathMap: Map = new Map(); - const visited = []; - const queue: Array = [root]; - - while (queue.length > 0) { - const firstElement: Root | Node = queue[0]; - queue.splice(0, 1); - - if (isNode(firstElement)) { - // TODO: 08.08.2019 implement this - } - } - } -} - -function isRoot(value: any): value is Root { - return value.children && !value.migration; -} - -function isNode(value: any): value is Node { - return value.children && value.migration; } interface Root { diff --git a/packages/scraper/src/externals/custom/common.ts b/packages/scraper/src/externals/custom/common.ts index ca2c029d..464aaddc 100644 --- a/packages/scraper/src/externals/custom/common.ts +++ b/packages/scraper/src/externals/custom/common.ts @@ -89,7 +89,7 @@ function traceWrap any>(target: T): T { const store = getStore() as undefined | TraceStore; // no store means no tracing, so exit as light weight as possible - if (!store || !store.get("enableTrace")) { + if (!store?.get("enableTrace")) { return target(...args); } diff --git a/packages/scraper/src/externals/direct/directTools.ts b/packages/scraper/src/externals/direct/directTools.ts index 5c3cf5a9..26afa58b 100644 --- a/packages/scraper/src/externals/direct/directTools.ts +++ b/packages/scraper/src/externals/direct/directTools.ts @@ -165,34 +165,6 @@ export interface SearchResult { done: boolean; } -function searchForWords( - linkSelector: string, - medium: TocSearchMedium, - uri: string, - searchLink: (parameter: string) => string, -): (searchString: string) => Promise { - return async (word: string): Promise => { - const $ = await request.getCheerio({ url: searchLink(word) }); - - const links = $(linkSelector); - - if (!links.length) { - return { done: true }; - } - for (let i = 0; i < links.length; i++) { - const linkElement = links.eq(i); - - const text = sanitizeString(getText(linkElement)); - - if (equalsIgnore(text, medium.title) || medium.synonyms.some((s) => equalsIgnore(text, s))) { - const tocLink = linkElement.attr("href") as string; - return { value: new url.URL(tocLink, uri).href, done: true }; - } - } - return { done: false }; - }; -} - export async function searchToc( medium: TocSearchMedium, tocScraper: TocScraper, @@ -472,10 +444,6 @@ function isUnusedPiece(value: Node): value is UnusedPiece { return value.type === "unusedPiece"; } -function isPartPiece(value: any): value is PartPiece { - return value.episodes; -} - function isTocMetaPiece(value: any): value is TocMetaPiece { return Number.isInteger(value.mediumType); } @@ -629,65 +597,6 @@ interface TocScrapeState { tocMeta?: InternalToc; } -function adjustPartialIndices(contentIndex: number, contents: InternalTocContent[], ascending: boolean): void { - const content = contents[contentIndex] as InternalTocEpisode; - const partialLimit = content.partCount; - - if (partialLimit) { - const totalIndex = content.totalIndex; - const currentPartialIndex = content.partialIndex; - - if (currentPartialIndex == null) { - logger.warn("partialLimit but no partialIndex for: " + stringify(content)); - } else { - for (let j = contentIndex + 1; j < contents.length; j++) { - const next = contents[j]; - - if (!isInternalEpisode(next) || !next.match) { - continue; - } - if (next.totalIndex !== totalIndex) { - break; - } - const nextPartialIndex = currentPartialIndex + (ascending ? 1 : -1); - - if (nextPartialIndex < 1 || nextPartialIndex > partialLimit) { - break; - } - if (next.partialIndex != null && next.partialIndex !== nextPartialIndex) { - logger.warn( - `trying to overwrite partialIndex on existing one with ${nextPartialIndex}: ${stringify(content)}`, - ); - } else { - next.partialIndex = nextPartialIndex; - next.combiIndex = combiIndex(next); - } - } - for (let j = contentIndex - 1; j >= 0; j--) { - const previous = contents[j]; - - if (!isInternalEpisode(previous) || !previous.match) { - continue; - } - if (previous.totalIndex !== totalIndex) { - break; - } - const nextPartialIndex = currentPartialIndex + (ascending ? -1 : 1); - - if (nextPartialIndex < 1 || nextPartialIndex > partialLimit) { - break; - } - if (previous.partialIndex != null && previous.partialIndex !== nextPartialIndex) { - logger.warn("trying to overwrite partialIndex on existing one: " + stringify(content)); - } else { - previous.partialIndex = nextPartialIndex; - previous.combiIndex = combiIndex(previous); - } - } - } - } -} - function convertToTocEpisode(totalIndex: number, partialIndex: number, index: number, value: UnusedPiece) { const episode: InternalTocEpisode = { type: "episode", @@ -809,11 +718,7 @@ function adjustTocContentsLinked(contents: TocLinkedList, state: TocScrapeState) } } let minPartialIndex; - let startPiecesCount = 0; for (const content of contents.iterate(ascending)) { - if (isUnusedPiece(content)) { - startPiecesCount++; - } if (isInternalEpisode(content)) { if (content.totalIndex === 0) { minPartialIndex = content.partialIndex; diff --git a/packages/scraper/src/externals/direct/mangaHasuScraper.ts b/packages/scraper/src/externals/direct/mangaHasuScraper.ts index 6db1fd80..7d0c12c1 100644 --- a/packages/scraper/src/externals/direct/mangaHasuScraper.ts +++ b/packages/scraper/src/externals/direct/mangaHasuScraper.ts @@ -136,7 +136,6 @@ async function scrapeNews(): Promise { continue; } let partIndices; - let partTitle; if (groups[2]) { partIndices = extractIndices(groups, 2, 3, 5); @@ -148,7 +147,7 @@ async function scrapeNews(): Promise { }); continue; } - partTitle = `Vol. ${partIndices.combi}`; + // partTitle = `Vol. ${partIndices.combi}`; // TODO: unused part title, should this be removed or used? } diff --git a/packages/scraper/src/externals/direct/mangadexScraper.ts b/packages/scraper/src/externals/direct/mangadexScraper.ts index c68f4eb3..2f075f43 100644 --- a/packages/scraper/src/externals/direct/mangadexScraper.ts +++ b/packages/scraper/src/externals/direct/mangadexScraper.ts @@ -46,6 +46,7 @@ interface ChapterResponse { status: string; } +// eslint-disable-next-line @typescript-eslint/no-unused-vars interface ChapterTocResponse { manga: MangaChapter; chapter: Record; @@ -225,7 +226,6 @@ async function scrapeNews(): Promise { continue; } let partIndices; - let partTitle; if (groups[2]) { partIndices = extractIndices(groups, 2, 3, 5); @@ -235,7 +235,7 @@ async function scrapeNews(): Promise { continue; } - partTitle = `Vol. ${partIndices.combi}`; + // partTitle = `Vol. ${partIndices.combi}`; // TODO: unused part title, should this be removed or used? } episodeNews.push({ diff --git a/packages/scraper/src/externals/direct/novelFullScraper.ts b/packages/scraper/src/externals/direct/novelFullScraper.ts index b389107b..4c3699b7 100644 --- a/packages/scraper/src/externals/direct/novelFullScraper.ts +++ b/packages/scraper/src/externals/direct/novelFullScraper.ts @@ -1,4 +1,4 @@ -import { EpisodeContent, Hook, Toc, TocContent, TocEpisode, TocPart, NewsScrapeResult } from "../types"; +import { EpisodeContent, Hook, Toc, TocContent, NewsScrapeResult } from "../types"; import { EpisodeNews, ReleaseState, @@ -24,7 +24,6 @@ import { scraperLog, getText, } from "./directTools"; -import { checkTocContent } from "../scraperTools"; import { ScraperError, UrlError } from "../errors"; import * as cheerio from "cheerio"; import request from "../request"; @@ -184,144 +183,6 @@ async function tocAdapterTooled(tocLink: string): Promise { return []; } -async function tocAdapter(tocLink: string): Promise { - const uri = BASE_URI; - - const linkMatch = tocLink.match("^https?://novelfull\\.com/([\\w-]+.html)$"); - if (!linkMatch) { - throw new UrlError("not a valid toc url for NovelFull: " + tocLink, tocLink); - } - const toc: { - title?: string; - content?: TocContent[]; - synonyms?: string[]; - mediumType: MediaType; - partsOnly?: boolean; - end?: boolean; - link: string; - } = { - link: tocLink, - mediumType: MediaType.TEXT, - }; - tocLink = `${BASE_URI}index.php/${linkMatch[1]}?page=`; - - for (let i = 1; ; i++) { - const $ = await request.getCheerio({ url: tocLink + i }); - - if ($('.info a[href="/status/Completed"]').length) { - toc.end = true; - } - const tocSnippet = await scrapeTocPage($, uri); - - if (!tocSnippet) { - break; - } - - if (!toc.title) { - toc.title = tocSnippet.title; - } else if (tocSnippet.title && tocSnippet.title !== toc.title) { - logger.warn(`Mismatched Title on Toc Pages: '${toc.title}' and '${tocSnippet.title}'`, { - url: tocLink, - scraper: "novelfull", - }); - return []; - } - if (!toc.content) { - toc.content = tocSnippet.content; - } else { - toc.content.push(...tocSnippet.content); - } - if (!toc.synonyms) { - toc.synonyms = tocSnippet.synonyms; - } else if (tocSnippet.synonyms) { - toc.synonyms.push(...tocSnippet.synonyms); - } - if ($(".pagination .last.disabled, .pagination .next.disabled").length) { - break; - } - // no novel has more than 300 toc pages (300 * 50 -> 15000 Chapters) - if (i > 300) { - logger.error(new ScraperError(`Could not reach end of TOC '${toc.link}'`)); - break; - } - } - - if (!toc.content || !toc.title) { - return []; - } - return [toc as Toc]; -} - -async function scrapeTocPage($: cheerio.CheerioAPI, uri: string): VoidablePromise { - // TODO: 20.07.2019 scrape alternative titles and author too - const mediumTitleElement = $(".desc .title").first(); - const mediumTitle = sanitizeString(getText(mediumTitleElement)); - - const content: TocContent[] = []; - const indexPartMap: Map = new Map(); - const items = $(".list-chapter li a"); - - const titleRegex = /(vol(\.|ume)?\s*((\d+)(\.(\d+))?).+)?((ch(\.|a?.?p?.?t?.?e?.?r?.?)?)|-)\s*((\d+)(\.(\d+))?)/i; - // TODO: 24.07.2019 has volume, 'intermission', 'gossips', 'skill introduction', 'summary' - // for now it skips those, maybe do it with lookAheads in the rows or sth similar - for (let i = 0; i < items.length; i++) { - const newsRow = items.eq(i); - - const link = new url.URL(newsRow.attr("href") as string, uri).href; - - const episodeTitle = sanitizeString(getText(newsRow)); - - const regexResult = titleRegex.exec(episodeTitle); - - if (!regexResult) { - scraperLog("warn", LogType.TITLE_FORMAT, "novelfull", { url: uri, unknown_title: episodeTitle }); - continue; - } - const partIndices = extractIndices(regexResult, 3, 4, 6); - const episodeIndices = extractIndices(regexResult, 10, 11, 13); - - if (!episodeIndices) { - throw new ScraperError(`title format changed on fullNovel, got no indices for '${episodeTitle}'`); - } - - const episode: TocEpisode = { - combiIndex: episodeIndices.combi, - totalIndex: episodeIndices.total, - partialIndex: episodeIndices.fraction, - url: link, - title: episodeTitle, - }; - checkTocContent(episode); - - if (partIndices) { - let part: Optional = indexPartMap.get(partIndices.combi); - - if (!part) { - part = { - episodes: [], - combiIndex: partIndices.combi, - totalIndex: partIndices.total, - partialIndex: partIndices.fraction, - title: "Vol." + partIndices.combi, - }; - checkTocContent(part, true); - - indexPartMap.set(partIndices.combi, part); - content.push(part); - } - part.episodes.push(episode); - } else { - content.push(episode); - } - } - return { - link: "", - content, - title: mediumTitle, - mediumType: MediaType.TEXT, - }; -} - async function newsAdapter(): Promise { const uri = BASE_URI; const $ = await request.getCheerio({ url: uri }); diff --git a/packages/scraper/src/jobs/queueTocs.ts b/packages/scraper/src/jobs/queueTocs.ts index 1d1a06a8..186d27be 100644 --- a/packages/scraper/src/jobs/queueTocs.ts +++ b/packages/scraper/src/jobs/queueTocs.ts @@ -20,4 +20,4 @@ export const queueTocsJob = async (): Promise => { deleteAfterRun: false, }; }); -}; \ No newline at end of file +}; diff --git a/packages/server/src/api/user.ts b/packages/server/src/api/user.ts index 57810934..dcdd672b 100644 --- a/packages/server/src/api/user.ts +++ b/packages/server/src/api/user.ts @@ -44,6 +44,7 @@ import { DownloadEpisode, downloadEpisodeSchema, getAllAppEventsSchema, + GetAssociatedEpisode, getAssociatedEpisodeSchema, GetNotifications, GetNotificationsCount, @@ -178,9 +179,11 @@ export const getLists = getAllLists; export const getAssociatedEpisode = createHandler( (req) => { - const url = extractQueryParam(req, "url"); + const { url }: GetAssociatedEpisode = req.query as any; return episodeStorage.getAssociatedEpisode(url); -}); + }, + { query: getAssociatedEpisodeSchema }, +); export const search = createHandler( (req) => { diff --git a/packages/server/src/misc/fillSystemEvents.ts b/packages/server/src/misc/fillSystemEvents.ts index 7c7a1144..8a1d0ca9 100644 --- a/packages/server/src/misc/fillSystemEvents.ts +++ b/packages/server/src/misc/fillSystemEvents.ts @@ -94,6 +94,7 @@ async function complete() { process.exit(0); } +// eslint-disable-next-line @typescript-eslint/no-unused-vars async function streamed() { const jobs = await jobStorage.getJobHistoryStream(new Date(), -1); diff --git a/packages/server/src/misc/openapi/exportOpenApi.ts b/packages/server/src/misc/openapi/exportOpenApi.ts index 63600cf3..2b81b7c0 100644 --- a/packages/server/src/misc/openapi/exportOpenApi.ts +++ b/packages/server/src/misc/openapi/exportOpenApi.ts @@ -1,5 +1,5 @@ -import ts from "typescript"; -import { +/* eslint-disable @typescript-eslint/no-unused-vars */ +import ts, { CallExpression, FunctionDeclaration, Identifier, @@ -27,6 +27,7 @@ import { enumNameSymbol, keyTypeSymbol, } from "./types"; +import { stringify } from "enterprise-core/dist/tools"; interface DocEntry { name?: string; @@ -125,6 +126,7 @@ interface NullType extends TypeResult { literalValue?: null; } +// eslint-disable-next-line @typescript-eslint/no-unused-vars interface PromiseType extends TypeResult { type: "Promise"; genericType: TypeResult; @@ -254,9 +256,9 @@ export function generateExpressApiObject(fileNames: string[], options: ts.Compil } class TypeInferrer { - private checker: ts.TypeChecker; + private readonly checker: ts.TypeChecker; private counter = 0; - private inErrorBlock = false; + private readonly inErrorBlock = false; public constructor(checker: ts.TypeChecker) { this.checker = checker; @@ -271,7 +273,7 @@ class TypeInferrer { const symbol = this.getSymbol(node); if (!symbol) { - log("No Symbol for Identifier: " + node); + log("No Symbol for Identifier: " + stringify(node)); } else { const type = this.checker.getTypeOfSymbolAtLocation(symbol, node); @@ -635,8 +637,8 @@ class TypeInferrer { } private convertRecordType(type: ts.Type) { - const keyType = type.aliasTypeArguments && type.aliasTypeArguments[0]; - const valueType = type.aliasTypeArguments && type.aliasTypeArguments[1]; + const keyType = type.aliasTypeArguments?.[0]; + const valueType = type.aliasTypeArguments?.[1]; if (!keyType || !valueType) { log("Missing either key or alias type for Record!"); @@ -650,7 +652,7 @@ class TypeInferrer { } private convertPartialType(type: ts.Type) { - const keyType = type.aliasTypeArguments && type.aliasTypeArguments[0]; + const keyType = type.aliasTypeArguments?.[0]; if (!keyType) { log("Missing type parameter for Partial!"); @@ -671,8 +673,8 @@ class TypeInferrer { } private convertPickType(type: ts.Type, typeNode?: ts.TypeNode) { - const targetType = type.aliasTypeArguments && type.aliasTypeArguments[0]; - const keysType = type.aliasTypeArguments && type.aliasTypeArguments[1]; + const targetType = type.aliasTypeArguments?.[0]; + const keysType = type.aliasTypeArguments?.[1]; if (!targetType || !keysType) { log("Missing target or keys type parameter for Pick!"); @@ -926,13 +928,13 @@ class TypeInferrer { } class Parser { - private routerVariables: Set = new Set(); - private routerMap: Map = new Map(); - private routeMap: Map = new Map(); + private readonly routerVariables: Set = new Set(); + private readonly routerMap: Map = new Map(); + private readonly routeMap: Map = new Map(); private currentlyConvertingRouter: Nullable = null; - private checker: ts.TypeChecker; + private readonly checker: ts.TypeChecker; public functionMap: Map = new Map(); - private inferrer: TypeInferrer; + private readonly inferrer: TypeInferrer; public constructor(checker: ts.TypeChecker) { this.checker = checker; @@ -966,7 +968,7 @@ class Parser { const routerEntry = this.routerMap.get(returnedRouter); if (!routerEntry) { - throw Error("No entry available for: " + returnedRouter); + throw Error("No entry available for: " + stringify(returnedRouter)); } this.currentlyConvertingRouter = returnedRouter; result[name] = this.routerEntryToResult(routerEntry); @@ -986,12 +988,14 @@ class Parser { continue; } if (subRouterSymbol === this.currentlyConvertingRouter) { - throw Error("Currently converting Router is recursively a sub router of itself!: " + subRouterSymbol); + throw Error( + "Currently converting Router is recursively a sub router of itself!: " + stringify(subRouterSymbol), + ); } const subRouterEntry = this.routerMap.get(subRouterSymbol); if (!subRouterEntry) { - throw Error("Sub router as no entry: " + subRouterSymbol); + throw Error("Sub router has no entry: " + stringify(subRouterSymbol)); } routerResult.subRouter[routerPath] = this.routerEntryToResult(subRouterEntry); } @@ -1055,7 +1059,7 @@ class Parser { } if (ts.isFunctionLike(initializer)) { stackElement = this.createStackElement(initializer, valueDeclaration.name); - } else if (ts.isIdentifierOrPrivateIdentifier(initializer)) { + } else if (ts.isMemberName(initializer)) { // TODO: 10.08.2020 middleware aliases like putProgress return this.middlewareToResult(initializer); } else { @@ -1089,7 +1093,7 @@ class Parser { middlewareResult.returnTypes[Number(code)] = response.body; } } - log(`Middleware ${middleware.getText()} has no returnType: ${middlewareResult.returnTypes == null}`); + log(`Middleware ${middleware.getText()} has no returnType: ${(middlewareResult.returnTypes == null) + ""}`); return middlewareResult; } @@ -1428,7 +1432,7 @@ class Parser { // or a call of a super type of express.Response like http.ServerResponse or http.OutgoingMessage log("Unknown call on response: " + callExpression.getText()); } - if (container.responseInfo[statusCode] && container.responseInfo[statusCode].body) { + if (container.responseInfo[statusCode]?.body) { // TODO: check really if same status code // merge if it is log("Response exists already!"); @@ -1560,7 +1564,6 @@ class Parser { const call = getFirst(initializer, SyntaxKind.CallExpression) as CallExpression; if (call.arguments.length !== 1) { log("Require exactly on argument for method 'route' on position: " + call.pos); - return; } else { const expression = call.arguments[0]; const routerEntry = this.getRouterEntry(routerSymbol); @@ -1905,7 +1908,7 @@ function nextNode(node: ts.Node): Nullable { // get the next node for the parent and look for the earliest node let earliestNode = nextNode(node.parent); - while (earliestNode && earliestNode.getChildCount()) { + while (earliestNode?.getChildCount()) { earliestNode = earliestNode.getChildAt(0); } return earliestNode; @@ -2158,10 +2161,10 @@ function toSchema(params?: TypeResult | null): SchemaObject | undefined { const requiredProperties = []; for (const [key, value] of Object.entries(obj.properties)) { - const property_schema = toSchema(value); + const propertySchema = toSchema(value); - if (property_schema) { - properties[key] = property_schema; + if (propertySchema) { + properties[key] = propertySchema; } if (value && !value.optional) { requiredProperties.push(key); diff --git a/packages/server/src/misc/openapi/generate.ts b/packages/server/src/misc/openapi/generate.ts index 988b70dc..1992c4dc 100644 --- a/packages/server/src/misc/openapi/generate.ts +++ b/packages/server/src/misc/openapi/generate.ts @@ -72,7 +72,7 @@ async function readHook(openApiObject: OpenApiObject) { } } -async function writeHook(openApiObject: OpenApiObject) { +export async function writeHook(openApiObject: OpenApiObject) { const hookOutput: any = {}; const methods = ["get", "delete", "post", "put"]; diff --git a/packages/server/src/misc/openapi/transformer.ts b/packages/server/src/misc/openapi/transformer.ts index 61c9c891..612b14fe 100644 --- a/packages/server/src/misc/openapi/transformer.ts +++ b/packages/server/src/misc/openapi/transformer.ts @@ -1,6 +1,6 @@ import handlebars from "handlebars"; import fs from "fs/promises"; -import { findAbsoluteProjectDirPath } from "enterprise-core/dist/tools"; +import { findAbsoluteProjectDirPath, stringify } from "enterprise-core/dist/tools"; import { join } from "path"; import { OpenApiObject, @@ -259,7 +259,7 @@ class TSTemplateGenerator extends TemplateGenerator { valueType = this.schemaToJSType(valueSchema as SchemaObject); } - return new handlebars.SafeString(`Record<${this.schemaToJSType(keyType).toString()}, ${valueType}>`); + return new handlebars.SafeString(`Record<${this.schemaToJSType(keyType).toString()}, ${stringify(valueType)}>`); } else if (schema.type === "integer") { return "number"; } @@ -318,7 +318,7 @@ class TSTemplateGenerator extends TemplateGenerator { const isStr = isString(value); // @ts-expect-error const name = enumValue[enumNameSymbol] ? enumValue[enumNameSymbol][index] : index; - return new handlebars.SafeString(`${name} = ${isStr ? '"' : ""}${value}${isStr ? '"' : ""},`); + return new handlebars.SafeString(`${name + ""} = ${isStr ? '"' : ""}${value + ""}${isStr ? '"' : ""},`); }); handlebars.registerHelper("toType", (type?: SchemaObject) => { @@ -431,23 +431,23 @@ class TSRequestValidatorGenerator extends TSTemplateGenerator { }); handlebars.registerHelper("toTSValue", (value) => { if (isString(value)) { - return new handlebars.SafeString(`"${value}"`); + return new handlebars.SafeString(`"${value + ""}"`); } else if (isBoolean(value)) { - return `${value}`; + return value + ""; } else if (isNumber(value)) { - return `${value}`; + return value + ""; } else if (value === null) { return "null"; } else if (value === undefined) { return "undefined"; } - throw Error(`Unknown TSValue: '${value}'`); + throw Error(`Unknown TSValue: '${value + ""}'`); }); handlebars.registerHelper("findEnumMember", (value: any, enumValues: any[]) => { const index = enumValues.indexOf(value); if (index < 0) { - throw Error(`Unknown EnumValue: '${value}'`); + throw Error(`Unknown EnumValue: '${value + ""}'`); } // @ts-expect-error return enumValues[enumNameSymbol] ? enumValues[enumNameSymbol][index] : index; diff --git a/packages/website/src/views/Lists.vue b/packages/website/src/views/Lists.vue index cbc409f3..714ea5da 100644 --- a/packages/website/src/views/Lists.vue +++ b/packages/website/src/views/Lists.vue @@ -194,8 +194,8 @@ import { SimpleMedium, ReleaseState as ReleaseStateType, } from "../siteTypes"; -import typeIcon from "../components/type-icon.vue"; -import releaseState from "../components/release-state.vue"; +import TypeIcon from "../components/type-icon.vue"; +import ReleaseState from "../components/release-state.vue"; import MediaFilter from "../components/media-filter.vue"; import { computed, ref, watchEffect } from "vue"; import { mergeMediaToc } from "../init";