mirror of
https://github.com/cupcakearmy/morphus.git
synced 2025-12-15 19:04:59 +00:00
initial
This commit is contained in:
50
src/utils/caniuse.ts
Normal file
50
src/utils/caniuse.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import DeviceDetector from 'device-detector-js'
|
||||
import Avif from 'caniuse-db/features-json/avif.json'
|
||||
import WebP from 'caniuse-db/features-json/webp.json'
|
||||
|
||||
const detector = new DeviceDetector()
|
||||
|
||||
function findLowestCompatibleVersion(stat: Record<string, string>): string {
|
||||
const entries = Object.entries(stat).sort((a, b) => parseInt(a[0]) - parseInt(b[0]))
|
||||
for (const [version, support] of entries) {
|
||||
if (support.startsWith('y') || support.startsWith('a')) {
|
||||
return version
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const mapping = {
|
||||
'Internet Explorer': 'ie',
|
||||
'Microsoft Edge': 'edge',
|
||||
Firefox: 'firefox',
|
||||
Chrome: 'chrome',
|
||||
Safari: 'safari',
|
||||
Opera: 'opera',
|
||||
'Mobile Safari': 'ios_saf',
|
||||
'Opera Mini': 'op_mini',
|
||||
'Android Browser': 'android',
|
||||
'Chrome Mobile': 'and_chr',
|
||||
'Firefox Mobile': 'and_ff',
|
||||
'UC Browser': 'and_uc',
|
||||
'Samsung Browser': 'samsung',
|
||||
'QQ Browser': 'and_qq',
|
||||
}
|
||||
|
||||
function matchBrowserToStat(browser: DeviceDetector.DeviceDetectorResult): string {
|
||||
if (!browser.os || !browser.client) throw new Error('Invalid browser')
|
||||
if (browser.os.name === 'iOS') {
|
||||
return 'ios_saf'
|
||||
}
|
||||
if (browser.os.name in mapping) {
|
||||
return mapping[browser.os.name as keyof typeof mapping]
|
||||
}
|
||||
throw new Error('Could not determine mapping for browser')
|
||||
}
|
||||
|
||||
function match(feature: typeof Avif | typeof WebP, ua: string): boolean {
|
||||
const browser = detector.parse(ua)
|
||||
const stats = feature.stats[matchBrowserToStat(browser) as keyof typeof feature.stats]
|
||||
console.debug(stats)
|
||||
console.debug(findLowestCompatibleVersion(stats))
|
||||
return false
|
||||
}
|
||||
39
src/utils/utils.ts
Normal file
39
src/utils/utils.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { createHash } from 'crypto'
|
||||
import { validateSync, ValidatorOptions, ValidationError as VE } from 'class-validator'
|
||||
import { PassThrough, Readable } from 'stream'
|
||||
|
||||
export class ValidationError extends Error {
|
||||
override message: string
|
||||
|
||||
constructor(errors: VE[]) {
|
||||
super()
|
||||
this.message = errors
|
||||
.map((e) => Object.values(e.constraints!))
|
||||
.flat()
|
||||
.join(', ')
|
||||
}
|
||||
}
|
||||
|
||||
export function validateSyncOrFail(data: object, options: ValidatorOptions = {}) {
|
||||
options = Object.assign({ whitelist: true, forbidUnknownValues: true, skipMissingProperties: false }, options)
|
||||
const errors = validateSync(data, options)
|
||||
if (errors.length > 0) {
|
||||
throw new ValidationError(errors)
|
||||
}
|
||||
}
|
||||
|
||||
export function sha3(url: string) {
|
||||
return createHash('sha3-256').update(url).digest('hex')
|
||||
}
|
||||
|
||||
export function sortObjectByKeys<T extends object>(obj: T): T {
|
||||
return Object.fromEntries(Object.entries(obj).sort((a, b) => a[0].localeCompare(b[0]))) as T
|
||||
}
|
||||
|
||||
export function splitter(from: NodeJS.ReadableStream, ...streams: NodeJS.WritableStream[]) {
|
||||
const splitter = new PassThrough()
|
||||
for (const stream of streams) {
|
||||
splitter.pipe(stream)
|
||||
}
|
||||
from.pipe(splitter)
|
||||
}
|
||||
Reference in New Issue
Block a user