Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: impl md5 #1

Merged
merged 3 commits into from
Aug 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,6 @@ jobs:
- name: Run Linter
run: pnpm turbo lint
- name: Run Tests
run: pnpm turbo test
run: pnpm turbo test:cov
- name: Check Package
run: pnpm turbo lint:publint
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
node_modules/

# Build Artifacts
.rollup.cache/
.tsbuildinfo
.turbo/
dist/
Expand All @@ -20,3 +21,4 @@ coverage/

# IDEs
.idea
this.code-workspace
3 changes: 3 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"recommendations": ["biomejs.biome", "denoland.vscode-deno"]
}
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"biome.enabled": true,
"deno.enable": false,
"deno.enablePaths": ["./@kindspells/internal-tools"]
}
14 changes: 9 additions & 5 deletions @kindspells/dev-configs/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,21 @@
"incremental": true,

/* Language and Environment */
"target": "ES2020",
"target": "es2020",
"lib": ["es2020", "DOM", "DOM.Iterable"],

/* Modules */
"module": "ES2020",
"module": "es2020",
"moduleResolution": "Bundler",
"baseUrl": "./src/",
"allowArbitraryExtensions": true,
"allowImportingTsExtensions": true,
"resolvePackageJsonExports": true,
"resolvePackageJsonImports": true,
"resolveJsonModule": true,

/* JavaScript Support */
"allowJs": true,
"checkJs": true,
"allowJs": false,
"checkJs": false,

/* Emit */
"noEmit": true,
Expand All @@ -31,6 +31,10 @@
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,

/* Declarations */
"declaration": true,
"isolatedDeclarations": true,

/* Type Checking */
"strict": true,
"noUnusedLocals": true,
Expand Down
33 changes: 31 additions & 2 deletions @kindspells/ts-crypto/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,45 @@
"private": false,
"version": "0.0.1",
"license": "MIT",
"main": "./dist/main.cjs",
"module": "./dist/main.mjs",
"types": "./dist/main.d.cts",
"files": ["dist"],
"exports": {
"import": {
"types": "./dist/main.d.mts",
"default": "./dist/main.mjs"
},
"require": {
"types": "./dist/main.d.cts",
"default": "./dist/main.cjs"
}
},
"scripts": {
"build": "rm -rf dist/* && rollup --config rollup.config.mjs",
"format": "pnpm biome check --write --files-ignore-unknown=true .",
"format-staged": "biome-check-staged",
"lint": "pnpm biome check --files-ignore-unknown=true .",
"lint": "pnpm lint:biome",
"lint:biome": "pnpm biome check --files-ignore-unknown=true .",
"lint:publint": "publint",
"prepublishOnly": "pnpm lint && pnpm build",
"test": "vitest -c vitest.config.mts run",
"test:cov": "vitest -c vitest.config.mts run --coverage",
"typecheck": "tsc --incremental true --tsBuildInfoFile .tsbuildinfo --noEmit -p ./tsconfig.json"
},
"devDependencies": {
"@biomejs/biome": "^1.8.3",
"@kindspells/dev-configs": "workspace:*",
"typescript": "^5.5.4"
"@types/node": "^22.1.0",
"@vitest/coverage-v8": "^2.0.5",
"get-tsconfig": "^4.7.6",
"publint": "^0.2.9",
"rollup": "^4.20.0",
"rollup-plugin-dts": "^6.1.1",
"rollup-plugin-esbuild": "^6.1.1",
"tslib": "^2.6.3",
"typescript": "^5.5.4",
"vitest": "^2.0.5"
},
"engines": {
"node": ">=20.0"
Expand Down
38 changes: 38 additions & 0 deletions @kindspells/ts-crypto/rollup.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { dirname } from 'node:path'
import { fileURLToPath } from 'node:url'

import { getTsconfig } from 'get-tsconfig'
import { defineConfig } from 'rollup'
import dts from 'rollup-plugin-dts'
import esbuild from 'rollup-plugin-esbuild'

const projectDir = dirname(fileURLToPath(import.meta.url))
const tsconfig = getTsconfig(projectDir)
const target = tsconfig?.config.compilerOptions?.target ?? 'es2020'

const input = 'src/main.mts'

export default defineConfig([
{
input,
output: [
{ format: 'cjs', file: 'dist/main.cjs', sourcemap: true },
{ format: 'esm', file: 'dist/main.mjs', sourcemap: true },
],
plugins: [
esbuild({
target: ['node20', 'node22', target],
loaders: { '.mts': 'ts' },
minify: true,
}),
],
},
{
input,
output: [
{ format: 'cjs', file: 'dist/main.d.cts' },
{ format: 'esm', file: 'dist/main.d.mts' },
],
plugins: [dts()],
},
])
32 changes: 32 additions & 0 deletions @kindspells/ts-crypto/src/encoding/hex.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const numToHexL: { [key: number]: string } = {}
const numToHexU: { [key: number]: string } = {}
const hexToNum: { [key: string]: number } = {}

for (let i = 0; i < 256; i++) {
const hex = i.toString(16).padStart(2, '0')
numToHexL[i] = hex // Number.toString returns lowercase
numToHexU[i] = hex.toUpperCase()
hexToNum[hex] = i
}

export function fromHex(hex: string): Uint8Array {
const _hex = hex.toLowerCase()
const buffer = new Uint8Array(_hex.length >> 1)

for (let i = 0; i < _hex.length; i += 2) {
// biome-ignore lint/style/noNonNullAssertion: it is up to the caller to ensure that `hex` is a valid input
buffer[i >> 1] = hexToNum[_hex.slice(i, i + 2)]!
}
return buffer
}

export function toHex(buffer: Uint8Array, lowerCase = true): string {
const table = lowerCase ? numToHexL : numToHexU

let hex = ''
for (const byte of buffer) {
hex += table[byte]
}

return hex
}
86 changes: 86 additions & 0 deletions @kindspells/ts-crypto/src/encoding/tests/hex.test.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { describe, expect, it } from 'vitest'

import { fromHex, toHex } from '../hex.mts'

describe('fromHex', () => {
it('returns a buffer of length 0 for an empty string', () => {
const buffer = fromHex('')
expect(buffer).toBeInstanceOf(Uint8Array)
expect(buffer).toHaveLength(0)
})

it('returns a buffer of length 1 for a single byte hex string', () => {
const buffer = fromHex('00')
expect(buffer).toBeInstanceOf(Uint8Array)
expect(buffer).toHaveLength(1)
expect(buffer[0]).toBe(0)
})

it('returns a buffer of length 1 for a single byte hex string with lowercase letters', () => {
const buffer = fromHex('ff')
expect(buffer).toBeInstanceOf(Uint8Array)
expect(buffer).toHaveLength(1)
expect(buffer[0]).toBe(255)
})

it('returns a buffer of length 1 for a single byte hex string with uppercase letters', () => {
const buffer = fromHex('FF')
expect(buffer).toBeInstanceOf(Uint8Array)
expect(buffer).toHaveLength(1)
expect(buffer[0]).toBe(255)
})

it('returns a buffer of length 2 for a two byte hex string', () => {
const buffer = fromHex('00ff')
expect(buffer).toBeInstanceOf(Uint8Array)
expect(buffer).toHaveLength(2)
expect(buffer[0]).toBe(0)
expect(buffer[1]).toBe(255)
})

it('works with mixed case hex strings', () => {
const buffer = fromHex('fF')
expect(buffer).toBeInstanceOf(Uint8Array)
expect(buffer).toHaveLength(1)
expect(buffer[0]).toBe(255)
})

it('works with long hex strings', () => {
const buffer = fromHex('0123456789abcdef')
expect(buffer).toBeInstanceOf(Uint8Array)
expect(buffer).toHaveLength(8)
expect(buffer).toEqual(new Uint8Array([1, 35, 69, 103, 137, 171, 205, 239]))
})
})

describe('toHex', () => {
it('returns an empty string for a buffer of length 0', () => {
const hex = toHex(new Uint8Array([]))
expect(hex).toBe('')
})

it('returns a single byte hex string for a buffer of length 1', () => {
const hex = toHex(new Uint8Array([0]))
expect(hex).toBe('00')
})

it('returns a single byte hex string with lowercase letters for a buffer of length 1', () => {
const hex = toHex(new Uint8Array([255]))
expect(hex).toBe('ff')
})

it('returns a single byte hex string with uppercase letters for a buffer of length 1', () => {
const hex = toHex(new Uint8Array([255]), false)
expect(hex).toBe('FF')
})

it('returns a two byte hex string for a buffer of length 2', () => {
const hex = toHex(new Uint8Array([0, 255]))
expect(hex).toBe('00ff')
})

it('works with long buffers', () => {
const hex = toHex(new Uint8Array([1, 35, 69, 103, 137, 171, 205, 239]))
expect(hex).toBe('0123456789abcdef')
})
})
9 changes: 9 additions & 0 deletions @kindspells/ts-crypto/src/hashes/hashes.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export interface Hasher {
reset(): this
update(data: BufferSource): this
digest(): Promise<ArrayBuffer> | ArrayBuffer
}

export type HashFunction = (
data: BufferSource,
) => Promise<ArrayBuffer> | ArrayBuffer
Loading