diff --git a/auth/oauth.ts b/auth/oauth.ts index 7031518..e064f6d 100644 --- a/auth/oauth.ts +++ b/auth/oauth.ts @@ -71,10 +71,9 @@ export const initProvider: OAuthProviderInitializer = ({ clientId, authReqUrl, r if (response.error) { console.error('Error fetching token:', response.error) throw new Error(response.error) - } else { - console.log('Access Token:', response.accessToken) - return response } + + return response }) }, } diff --git a/biome.json b/biome.json index c7cad30..7342b97 100644 --- a/biome.json +++ b/biome.json @@ -17,6 +17,17 @@ "trailingCommas": "es5" } }, + "linter": { + "rules": { + "suspicious": { + "noExplicitAny": "off" + }, + "style": { + "useTemplate": "off" + } + }, + "ignore": ["*.test.ts"] + }, "files": { "ignore": ["node_modules", "dist", "build", "*.min.js", "*.d.ts", ".vscode"] } diff --git a/cli/cli-utils.ts b/cli/cli-utils.ts index 3d8f789..8cfe527 100644 --- a/cli/cli-utils.ts +++ b/cli/cli-utils.ts @@ -79,22 +79,18 @@ export function parseArgument( } export async function parseCliArgs(): Promise { - try { - const args = getArguments() - const parsedArgs: ParsedArgs = {} + const args = getArguments() + const parsedArgs: ParsedArgs = {} - for (let i = 0; i < args.length; i++) { - const { key, value } = parseArgument(args[i], args[i + 1]) + for (let i = 0; i < args.length; i++) { + const { key, value } = parseArgument(args[i], args[i + 1]) - if (key) { - parsedArgs[key] = value - } + if (key) { + parsedArgs[key] = value } - - return parsedArgs - } catch (error) { - throw error } + + return parsedArgs } export const getAdditionalPrompt = () => @@ -112,6 +108,7 @@ export const getAdditionalPrompt = () => export const chooseActions = async (actionsConfig: Record): Promise> => { cliLog('\nChoose actions (separated by commas):') const actions = Object.keys(actionsConfig) + actions.forEach((action, index) => { cliLog(`${index + 1}. ${action}`) }) @@ -128,14 +125,14 @@ export const chooseActions = async (actionsConfig: Record): Promise }) }) - const selectedIndexes = actionIndexes.split(',').map((index) => parseInt(index.trim()) - 1) + const selectedIndexes = actionIndexes.split(',').map((index) => Number.parseInt(index.trim()) - 1) const validSelection = selectedIndexes.every((index) => index >= 0 && index < actions.length) if (validSelection) { return selectedIndexes.map((index) => actions[index] as keyof typeof actionsConfig) - } else { - cliLog('Invalid input, please try again.') - return chooseActions(actionsConfig) } + + cliLog('Invalid input, please try again.') + return chooseActions(actionsConfig) } diff --git a/cli/create-cli-factory.ts b/cli/create-cli-factory.ts index 9712b42..ff06aa3 100644 --- a/cli/create-cli-factory.ts +++ b/cli/create-cli-factory.ts @@ -25,40 +25,28 @@ export function createCliFactory>({ }) const processInput = async () => { - try { - const commandLineArgs = await parseCliArgs() + const commandLineArgs = await parseCliArgs() - const userInput = await getUserInput() + const userInput = await getUserInput() - // Handle user input and command line arguments... - return { commandLineArgs, userInput } - } catch (error) { - throw error - } + // Handle user input and command line arguments... + return { commandLineArgs, userInput } } const executeActions = async () => { - try { - const additionalPrompt = await getAdditionalPrompt() + const additionalPrompt = await getAdditionalPrompt() - const chosenActions = await chooseActions(actionsConfig) + const chosenActions = await chooseActions(actionsConfig) - // Execute chosen actions... + // Execute chosen actions... - return { additionalPrompt, chosenActions } - } catch (error) { - throw error - } + return { additionalPrompt, chosenActions } } const handleFiles = ({ filePath, fileContent }: { filePath: string; fileContent: string }) => { - try { - factory.directoryExists({ path: filePath }) + factory.directoryExists({ path: filePath }) - factory.createFile(filePath, fileContent) - } catch (error) { - throw error - } + factory.createFile(filePath, fileContent) } return { diff --git a/cookies/cookie-utils.test.ts b/cookies/cookie-utils.test.ts index 4a1c8eb..e9d0515 100644 --- a/cookies/cookie-utils.test.ts +++ b/cookies/cookie-utils.test.ts @@ -1,10 +1,16 @@ import { afterEach, describe, expect, it } from 'bun:test' import { parseCookieData, retrieveRawCookieValue, stringifyCookieData } from './cookie-utils' -declare var document: { - cookie: any +// declare var document: { +// cookie: any +// } +const mockDocument = { + cookie: '', } +// Mock global document +global.document = mockDocument as any + describe('Cookie Helpers', () => { describe('parseCookieData', () => { it('should parse JSON string to object', () => { diff --git a/cookies/cookie-utils.ts b/cookies/cookie-utils.ts index ba5164d..b871990 100644 --- a/cookies/cookie-utils.ts +++ b/cookies/cookie-utils.ts @@ -1,6 +1,6 @@ import type { CookieOptions } from './cookie-types' -declare var document: { +declare const document: { cookie: any } @@ -19,9 +19,9 @@ export const parseCookieData = (data: string | null): T | null => { export const stringifyCookieData = (data: T): string => { if (typeof data === 'string') { return data - } else { - return JSON.stringify(data) } + + return JSON.stringify(data) } export const retrieveRawCookieValue = (name: string): string | null => { @@ -55,11 +55,11 @@ export const encodeCookie = (cookieKey: string, value: T, options: CookieOpti } if (options.secure) { - cookieString += `; secure` + cookieString += '; secure' } if (options.httpOnly) { - cookieString += `; httpOnly` + cookieString += '; httpOnly' } return cookieString @@ -73,10 +73,10 @@ export function parseCookies(cookiesString: string) { const cookies: { [name: string]: string } = {} const pairs = cookiesString.split(';') - pairs.forEach((pair) => { - const [name, ...rest] = pair.split('=') - cookies[name.trim()] = rest.join('=').trim() - }) + for (const pair of pairs) { + const [name, ...value] = pair.split('=') + cookies[name.trim()] = value.join('=').trim() + } return cookies } diff --git a/htmlody/css-engine.test.ts b/htmlody/css-engine.test.ts index 6587e21..3e66044 100644 --- a/htmlody/css-engine.test.ts +++ b/htmlody/css-engine.test.ts @@ -39,11 +39,11 @@ describe('generateCSS', () => { const result = generateCSS(mockNodeMap) const expectedCss = - `.flex { display: flex; }\n` + - `.m-1 { margin: 0.25rem; }\n` + - `.w-1/2 { width: 50%; }\n` + - `.h-1/2 { height: 50%; }\n` + - `.p-1 { padding: 0.25rem; }\n` + '.flex { display: flex; }\n' + + '.m-1 { margin: 0.25rem; }\n' + + '.w-1/2 { width: 50%; }\n' + + '.h-1/2 { height: 50%; }\n' + + '.p-1 { padding: 0.25rem; }\n' expect(result).toEqual(expectedCss) }) @@ -136,7 +136,7 @@ describe('generateColorVariables', () => { it('should generate CSS variables for colors', () => { const result = generateColorVariables() - expect(result).toContain(`--red-50`) + expect(result).toContain('--red-50') expect(result).toContain(':root {\n--red-50: #1A0000;') expect(result).toContain('--slate-300: #4E5A65;') @@ -148,10 +148,10 @@ describe('generateShades', () => { const result = generateShades('red') expect(result).toHaveLength(10) - result.forEach((shade) => { + for (const shade of result) { // validate that each shade is a valid hex color expect(shade).toHaveLength(7) - }) + } expect(result[0][0]).toBe('#') // first shade, first charact }) diff --git a/htmlody/css-engine.ts b/htmlody/css-engine.ts index ecaa198..18dc317 100644 --- a/htmlody/css-engine.ts +++ b/htmlody/css-engine.ts @@ -88,10 +88,10 @@ function generateCssSelector(breakpoint: string, className: string): string { function processClassRecords(classRecords: ResponsiveClassRecord, usedClasses: Set): string | null { let cssStr = '' - Object.entries(classRecords).forEach(([breakpoint, classRecord]) => { + for (const [breakpoint, classRecord] of Object.entries(classRecords)) { const classNames = extractClassNames(classRecord) - classNames.forEach((className) => { + for (const className of classNames) { const fullClassName = breakpoint === '*' ? className : `${breakpoint}_${className}` if (!usedClasses.has(fullClassName)) { @@ -102,8 +102,8 @@ function processClassRecords(classRecords: ResponsiveClassRecord, usedClasses: S cssStr += `${selector}\n` } } - }) - }) + } + } if (!cssStr) return null return cssStr @@ -118,10 +118,10 @@ export function processNode(node: JsonTagElNode, usedClas } if (node.child) { - Object.values(node.child).forEach((childNode) => { + for (const childNode of Object.values(node.child)) { const childNodeStr = processNode(childNode, usedClasses) if (childNodeStr) cssStr += childNodeStr - }) + } } return cssStr || null @@ -135,11 +135,10 @@ export function generateCSS< const usedClasses = new Set() let cssStr = '' - Object.values(nodeMap).forEach((node) => { + for (const node of Object.values(nodeMap)) { const nodeStr = processNode(node, usedClasses) - if (nodeStr) cssStr += nodeStr - }) + } if (!cssStr) return null return cssStr @@ -297,7 +296,8 @@ export function generateShades(color: ColorType): string[] { // and greater than 1 will lighten it const factors = [0.1, 0.3, 0.5, 0.7, 0.9, 1, 1.1, 1.3, 1.5, 1.7] factors.forEach((factor, index) => { - let adjustedColor + let adjustedColor: ReturnType | ReturnType + if (index < 5) { // Darken the color for shades 50-400 adjustedColor = adjustBrightness(baseColor, factor) diff --git a/htmlody/htmlody-utils.ts b/htmlody/htmlody-utils.ts index cf9ab02..2703ddb 100644 --- a/htmlody/htmlody-utils.ts +++ b/htmlody/htmlody-utils.ts @@ -47,10 +47,11 @@ export function isValidAttributesString(attributesStr: string): boolean { export function collectClassNames(node: JsonTagElNode, uniqueClassNames: Set) { if (node.attributes && typeof node.attributes.class === 'string') { const classList = node.attributes.class.split(' ') - classList.forEach((cls) => uniqueClassNames.add(cls)) + for (const cls of classList) { + uniqueClassNames.add(cls) + } } } - export const children = (children: JsonTagElNode[]) => { const returnChildren: JsonHtmlNodeTree = {} diff --git a/htmlody/json-to-html-engine.test.ts b/htmlody/json-to-html-engine.test.ts index 0caa805..5a01ad3 100644 --- a/htmlody/json-to-html-engine.test.ts +++ b/htmlody/json-to-html-engine.test.ts @@ -240,7 +240,7 @@ describe('renderNodeToHtml', () => { id: 'sample-id', class: 'sample-class', }, - children: { + child: { span_id1: { tag: 'span', content: 'Child Content', @@ -293,7 +293,7 @@ describe('createNodeFactory', () => { id: 'sample-id', class: 'sample-class', }, - children: { + child: { span_id1: { tag: 'span', content: 'Child Content', diff --git a/htmlody/json-to-html-engine.ts b/htmlody/json-to-html-engine.ts index b60a00b..9133e87 100644 --- a/htmlody/json-to-html-engine.ts +++ b/htmlody/json-to-html-engine.ts @@ -168,14 +168,20 @@ const generateTitleNode = (title: string): JsonTagElNode => { } } -const generateMetaTagNode = (meta: { name: string; content: string }): JsonTagElNode => { +const generateMetaTagNode = (meta: { + name: string + content: string +}): JsonTagElNode => { return { tag: 'meta', attributes: { name: meta.name, content: meta.content }, } } -const generateLinkTagNode = (link: { rel: string; href: string }): JsonTagElNode => { +const generateLinkTagNode = (link: { + rel: string + href: string +}): JsonTagElNode => { return { tag: 'link', attributes: { rel: link.rel, href: link.href }, @@ -189,7 +195,11 @@ const generateStyleTagNode = (content: string): JsonTagElNode => { } } -const generateScriptTagNode = (script: { src?: string; type?: string; content: string }): JsonTagElNode => { +const generateScriptTagNode = (script: { + src?: string + type?: string + content: string +}): JsonTagElNode => { const node: JsonTagElNode = { tag: 'script', attributes: {}, @@ -279,7 +289,18 @@ export const htmlodyBuilder = < const renderNodeTreeToHtml = (nodeMap: JsonHtmlNodeTree, pluginsOverride?: Plugins): string => { const activePlugins = pluginsOverride || effectivePlugins return Object.keys(nodeMap) - .map((id) => renderNodeWithPlugins(nodeMap[id], activePlugins)) + .map((id) => { + const node = nodeMap[id] + const childrenHtml = node.child ? renderNodeTreeToHtml(node.child, activePlugins) : '' + return renderNodeWithPlugins( + { + ...node, + content: node.content || '', // Remove childrenHtml from here + child: node.child, // Pass child to renderNodeWithPlugins + }, + activePlugins + ) + }) .join('') } diff --git a/jwt/jwt-server-utils.ts b/jwt/jwt-server-utils.ts index a17692d..cda6016 100644 --- a/jwt/jwt-server-utils.ts +++ b/jwt/jwt-server-utils.ts @@ -15,7 +15,7 @@ export function encrypt(data: string, secret: string): string { export function decrypt(encryptedData: string, secret: string): string { try { const algorithm = 'aes-256-gcm' - const key = crypto.createHash('sha256').update(secret).digest() // Ensure 256-bit key + const key = crypto.createHash('sha256').update(secret).digest() const [ivHex, encrypted, authTagHex] = encryptedData.split('.') const iv = Buffer.from(ivHex, 'hex') const decipher = crypto.createDecipheriv(algorithm, key, iv) @@ -24,6 +24,9 @@ export function decrypt(encryptedData: string, secret: string): string { decrypted += decipher.final('utf8') return decrypted } catch (e) { + if (e instanceof Error && e.message.includes('Unsupported state or unable to authenticate data')) { + throw new Error('Unable to decrypt token: Data integrity check failed') + } console.error(e) throw new Error('Unable to decrypt token') } diff --git a/sqlite/sqlite-utils/crud-string-utils.test.ts b/sqlite/sqlite-utils/crud-string-utils.test.ts index e74d6f9..caac01f 100644 --- a/sqlite/sqlite-utils/crud-string-utils.test.ts +++ b/sqlite/sqlite-utils/crud-string-utils.test.ts @@ -6,7 +6,7 @@ test('insertQueryString', () => { const tableName = 'users' const item = { name: 'Alice', age: 30 } const query = insertQueryString(tableName, item) - const expectedQuery = `INSERT INTO users (name, age) VALUES (?, ?)` + const expectedQuery = 'INSERT INTO users (name, age) VALUES (?, ?)' expect(query).toBe(expectedQuery) }) @@ -14,7 +14,7 @@ test('insertQueryString', () => { test('selectAllTableQueryString', () => { const tableName = 'users' const query = selectAllTableQueryString(tableName) - const expectedQuery = `SELECT * FROM users;` + const expectedQuery = 'SELECT * FROM users;' expect(query).toBe(expectedQuery) }) @@ -22,7 +22,7 @@ test('selectAllTableQueryString', () => { test('deleteQueryString', () => { const tableName = 'users' const query = deleteQueryString(tableName) - const expectedQuery = `delete FROM users WHERE id = $id;` + const expectedQuery = 'delete FROM users WHERE id = $id;' expect(query).toBe(expectedQuery) }) @@ -31,6 +31,6 @@ test('updateQueryString', () => { const tableName = 'users' const item = { name: 'John', age: 25 } // example item const query = updateQueryString(tableName, item) - const expectedQuery = `UPDATE users SET name = $name, age = $age WHERE id = $id;` + const expectedQuery = 'UPDATE users SET name = $name, age = $age WHERE id = $id;' expect(query).toBe(expectedQuery) }) diff --git a/state/state-manager.ts b/state/state-manager.ts index 9a5d749..af7ae97 100644 --- a/state/state-manager.ts +++ b/state/state-manager.ts @@ -4,7 +4,7 @@ import { createStateDispatchers } from './create-state-dispatchers' export type AllowedStateKeys = boolean | string | number export const createStateManager = (initialState: State) => { - let currentState: State = initialState + const currentState: State = initialState const stateChangeCallbacks: { [Key in keyof State]?: Array<(newValue: State[Key]) => void> @@ -13,7 +13,9 @@ export const createStateManager = (initialState: State) => const listeners: Array<() => void> = [] function broadcast() { - listeners.forEach((fn) => fn()) + for (const fn of listeners) { + fn() + } } function subscribe(listener: () => void) { diff --git a/utils/classy.ts b/utils/classy.ts index 6184150..bec0685 100644 --- a/utils/classy.ts +++ b/utils/classy.ts @@ -6,21 +6,21 @@ interface ClassNameMap { export function classy(...args: ClassName[]): string { const classes: string[] = [] - args.forEach((arg) => { - if (arg == null) return + for (const arg of args) { + if (arg == null) continue if (typeof arg === 'string' || typeof arg === 'number') { classes.push(arg.toString()) - } else if (arg instanceof Array) { + } else if (Array.isArray(arg)) { classes.push(classy(...arg)) } else if (typeof arg === 'object') { - Object.keys(arg).forEach((key) => { + for (const key in arg) { if (arg[key]) { classes.push(key) } - }) + } } - }) + } return classes.join(' ') }