volter 0.0.171 → 0.0.172

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package",
3
3
  "name": "volter",
4
- "version": "0.0.171",
4
+ "version": "0.0.172",
5
5
  "description": "Secure, lightweight, and user-friendly modern JavaScript toolchain optimized for performance and minimalism.",
6
6
  "main": "index.ts",
7
7
  "module": "index.ts",
@@ -11,11 +11,13 @@
11
11
  },
12
12
  "exports": {
13
13
  "./*": {
14
- "types": "./dist/*.d.ts",
15
- "import": "./dist/*.js",
14
+ "types": "./src/*.d.ts",
15
+ "import": "./src/*.ts",
16
16
  "default": "./src/*.ts"
17
17
  }
18
18
  },
19
+ "types": "./src/types.d.ts",
20
+ "typings": "./src/types.d.ts",
19
21
  "devDependencies": {
20
22
  "typescript": "latest",
21
23
  "@types/bun": "latest"
@@ -23,7 +25,7 @@
23
25
  "peerDependencies": {},
24
26
  "dependencies": {
25
27
  "@paralleldrive/cuid2": "latest",
26
- "chalk": "latest",
28
+ "ansi-colors": "^4.1.3",
27
29
  "drizzle-orm": "latest",
28
30
  "zod": "latest"
29
31
  }
@@ -0,0 +1,21 @@
1
+ export declare interface CipherText {
2
+ text: string
3
+ iv: Uint8Array<ArrayBuffer>
4
+ buffer: ArrayBuffer
5
+ }
6
+
7
+ export declare function hash(password: string, hmac?: string): string
8
+
9
+ export declare function key(raw?: CryptoKey | Uint8Array<ArrayBuffer> | string): Promise<CryptoKey>
10
+ export declare function exportKey(key: CryptoKey, format: "raw" | "spki" | "pkcs8"): Promise<string>
11
+
12
+ export declare function cipher(text: string, key: CryptoKey | string): Promise<CipherText>
13
+ export declare function decipher(cipher: CipherText, key: CryptoKey | string): Promise<string>
14
+
15
+ export declare function keypair(): Promise<CryptoKeyPair>
16
+ export declare function encrypt(text: string, key: CryptoKey): Promise<Uint8Array<ArrayBuffer>>
17
+ export declare function decrypt(text: Uint8Array<ArrayBuffer>, key: CryptoKey): Promise<string>
18
+
19
+ export declare function signature(): Promise<CryptoKeyPair>
20
+ export declare function sign(message: string, key: CryptoKey): Promise<Uint8Array<ArrayBuffer>>
21
+ export declare function verifySign(message: string, signature: Uint8Array<ArrayBuffer>, key: CryptoKey): Promise<boolean>
package/src/crypto.ts ADDED
@@ -0,0 +1,151 @@
1
+ export function hash(password: string, hmac?: string): string {
2
+ const hasher = new Bun.CryptoHasher("sha256", hmac)
3
+ return hasher.update(password).digest("hex")
4
+ }
5
+
6
+ export interface CipherText {
7
+ text: string
8
+ iv: Uint8Array<ArrayBuffer>
9
+ buffer: ArrayBuffer
10
+ }
11
+
12
+ export async function cryptoKey(raw?: CryptoKey | Uint8Array<ArrayBuffer> | string): Promise<CryptoKey> {
13
+ if (raw) {
14
+ if (raw instanceof CryptoKey) return raw
15
+ if (raw instanceof Uint8Array) {
16
+ if (raw.length === 32) {
17
+ return await crypto.subtle.importKey("raw", raw, { name: "AES-GCM", length: 256 }, true, ["encrypt", "decrypt"])
18
+ }
19
+ return await crypto.subtle.importKey("raw", raw, { name: "AES-GCM", length: 256 }, true, ["encrypt", "decrypt"])
20
+ }
21
+ if (raw.length === 64) {
22
+ return await crypto.subtle.importKey(
23
+ "raw",
24
+ Uint8Array.fromHex(raw),
25
+ {
26
+ name: "AES-GCM",
27
+ length: 256,
28
+ },
29
+ true,
30
+ ["encrypt", "decrypt"],
31
+ )
32
+ } else {
33
+ return await crypto.subtle.importKey(
34
+ "raw",
35
+ Uint8Array.fromHex(hash(raw)),
36
+ {
37
+ name: "AES-GCM",
38
+ length: 256,
39
+ },
40
+ true,
41
+ ["encrypt", "decrypt"],
42
+ )
43
+ }
44
+ } else {
45
+ return await crypto.subtle.generateKey(
46
+ {
47
+ name: "AES-GCM",
48
+ length: 256,
49
+ },
50
+ true,
51
+ ["encrypt", "decrypt"],
52
+ )
53
+ }
54
+ }
55
+ export async function exportKey(key: CryptoKey, format: "raw" | "pkcs8" | "spki") {
56
+ const buffer = await crypto.subtle.exportKey(format, key)
57
+ return new Uint8Array(buffer).toBase64()
58
+ }
59
+
60
+ export async function generateECDSAKeyPair(): Promise<CryptoKeyPair> {
61
+ return await crypto.subtle.generateKey(
62
+ {
63
+ name: "ECDSA",
64
+ namedCurve: "P-256", // SECG curve
65
+ },
66
+ true,
67
+ ["sign", "verify"],
68
+ )
69
+ }
70
+
71
+ export async function exportJWK(key: CryptoKey): Promise<JsonWebKey> {
72
+ return await crypto.subtle.exportKey("jwk", key)
73
+ }
74
+
75
+ export async function importJWK(jwk: JsonWebKey, usage: KeyUsage[]): Promise<CryptoKey> {
76
+ return await crypto.subtle.importKey("jwk", jwk, { name: "ECDSA", namedCurve: "P-256" }, true, usage)
77
+ }
78
+
79
+ export async function sign(message: string, key: CryptoKey): Promise<Uint8Array<ArrayBuffer>> {
80
+ const data = new TextEncoder().encode(message)
81
+
82
+ const signature = await crypto.subtle.sign(
83
+ {
84
+ name: "ECDSA",
85
+ hash: { name: "SHA-256" },
86
+ },
87
+ key,
88
+ data,
89
+ )
90
+
91
+ return new Uint8Array(signature)
92
+ }
93
+ export async function verifySign(message: string, signature: Uint8Array<ArrayBuffer>, key: CryptoKey): Promise<boolean> {
94
+ const data = new TextEncoder().encode(message)
95
+
96
+ return await crypto.subtle.verify(
97
+ {
98
+ name: "ECDSA",
99
+ hash: { name: "SHA-256" },
100
+ },
101
+ key,
102
+ signature,
103
+ data,
104
+ )
105
+ }
106
+
107
+ export async function cipher(text: string, key: CryptoKey | string): Promise<CipherText> {
108
+ const encoder = new TextEncoder()
109
+
110
+ const data = encoder.encode(text)
111
+ const iv = crypto.getRandomValues(new Uint8Array(12))
112
+ const buffer = await crypto.subtle.encrypt({ name: "AES-GCM", iv: iv }, await cryptoKey(key), data)
113
+
114
+ return {
115
+ text: new Uint8Array(buffer).toHex(),
116
+ iv: iv,
117
+ buffer: buffer,
118
+ }
119
+ }
120
+ export async function decipher(cipher: CipherText, key: CryptoKey | string) {
121
+ const decoder = new TextDecoder()
122
+
123
+ const buffer = await crypto.subtle.decrypt({ name: "AES-GCM", iv: cipher.iv }, await cryptoKey(key), Uint8Array.fromHex(cipher.text))
124
+
125
+ const data = decoder.decode(buffer)
126
+
127
+ return data
128
+ }
129
+
130
+ export async function keypair(): Promise<CryptoKeyPair> {
131
+ return await crypto.subtle.generateKey(
132
+ {
133
+ name: "RSA-OAEP",
134
+ modulusLength: 2048,
135
+ publicExponent: new Uint8Array([0x01, 0x00, 0x01]), // 65537
136
+ hash: { name: "SHA-256" },
137
+ },
138
+ true,
139
+ ["encrypt", "decrypt"],
140
+ )
141
+ }
142
+ export async function encrypt(text: string, key: CryptoKey): Promise<Uint8Array<ArrayBuffer>> {
143
+ const data = new TextEncoder().encode(text)
144
+ const buffer = await crypto.subtle.encrypt({ name: "RSA-OAEP" }, key, data)
145
+ return new Uint8Array(buffer)
146
+ }
147
+ export async function decrypt(text: Uint8Array<ArrayBuffer>, key: CryptoKey): Promise<string> {
148
+ const buffer = await crypto.subtle.decrypt({ name: "RSA-OAEP" }, key, text)
149
+ const data = new TextDecoder().decode(buffer)
150
+ return data
151
+ }
package/src/network.ts ADDED
@@ -0,0 +1,34 @@
1
+ import os from "node:os"
2
+
3
+ interface Adapter {
4
+ adapter: string
5
+ networks: Bun.SocketAddress[]
6
+ }
7
+
8
+ export function listAdapters(): Adapter[] {
9
+ const interfaces = os.networkInterfaces()
10
+ const results: Adapter[] = []
11
+
12
+ for (const [name, infos] of Object.entries(interfaces)) {
13
+ if (!infos) continue
14
+
15
+ const networks: Bun.SocketAddress[] = []
16
+
17
+ for (const info of infos) {
18
+ if (!info.address) continue
19
+
20
+ networks.push({
21
+ address: info.address,
22
+ family: info.family,
23
+ port: 0,
24
+ })
25
+ }
26
+
27
+ results.push({
28
+ adapter: name,
29
+ networks,
30
+ })
31
+ }
32
+
33
+ return results
34
+ }
package/src/types.d.ts ADDED
@@ -0,0 +1,37 @@
1
+ declare module "volter/utils" {
2
+ export function createPIN(): string
3
+ export function createID(): string
4
+
5
+ export function timestamp(date?: Date): string
6
+
7
+ export function log(...message: unknown[]): void
8
+ export function error(...message: unknown[]): void
9
+ export function debug(...message: unknown[]): void
10
+
11
+ export function input(prompt?: string): string
12
+
13
+ export function prettifyRequest(request: Request): string
14
+ }
15
+
16
+ declare module "volter/crypto" {
17
+ export interface CipherText {
18
+ text: string
19
+ iv: Uint8Array<ArrayBuffer>
20
+ buffer: ArrayBuffer
21
+ }
22
+
23
+ export function hash(password: string, hmac?: string): string
24
+
25
+ export function key(raw?: CryptoKey | Uint8Array<ArrayBuffer> | string): Promise<CryptoKey>
26
+ export function exportKey(key: CryptoKey, format: "raw" | "spki" | "pkcs8"): Promise<string>
27
+
28
+ export function cipher(text: string, key: CryptoKey | string): Promise<CipherText>
29
+ export function decipher(cipher: CipherText, key: CryptoKey | string): Promise<string>
30
+
31
+ export function keypair(): Promise<CryptoKeyPair>
32
+ export function encrypt(text: string, key: CryptoKey): Promise<Uint8Array<ArrayBuffer>>
33
+ export function decrypt(text: Uint8Array<ArrayBuffer>, key: CryptoKey): Promise<string>
34
+
35
+ export function sign(message: string, key: CryptoKey): Promise<Uint8Array<ArrayBuffer>>
36
+ export function verifySign(message: string, signature: Uint8Array<ArrayBuffer>, key: CryptoKey): Promise<boolean>
37
+ }
package/src/utils.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ export declare function createPIN(): string
2
+ export declare function createID(): string
3
+
4
+ export declare function timestamp(date?: Date): string
5
+
6
+ export declare function log(...message: unknown[]): void
7
+ export declare function error(...message: unknown[]): void
8
+ export declare function debug(...message: unknown[]): void
9
+
10
+ export declare function input(prompt?: string): string
11
+
12
+ export declare function prettifyRequest(request: Request): string
package/src/utils.ts CHANGED
@@ -1,44 +1,43 @@
1
- import { privateDecrypt, publicEncrypt, randomInt } from "node:crypto"
2
- import os from "node:os"
3
- import chalk from "chalk"
4
- import cuid2 from "@paralleldrive/cuid2"
5
- import { generateKeyPairSync } from "node:crypto"
1
+ import ansi from "ansi-colors"
6
2
  import z from "zod"
7
- import type { SocketAddress } from "node:net"
3
+ import { init } from "@paralleldrive/cuid2"
8
4
 
9
5
  declare global {
10
6
  interface Request {
11
- ip: SocketAddress
7
+ ip: Bun.SocketAddress
12
8
  }
13
9
  }
14
10
 
15
11
  export const pin = z.string().min(6).max(6).regex(/\d{6}/)
16
12
 
17
- export function createPIN(): string {
18
- return randomInt(0, 1000000).toString().padStart(6, "0")
13
+ export function createRandom(length = 32) {
14
+ const bytes = crypto.getRandomValues(new Uint8Array(length))
15
+ return bytes
19
16
  }
20
- export const createID = cuid2.init({ length: 32 })
21
17
 
22
- export function hash(password: string): string {
23
- const hasher = new Bun.CryptoHasher("sha256")
24
- return hasher.update(password).digest("hex")
18
+ export const createID = init({ length: 32 })
19
+ export function createPIN(): string {
20
+ const array = new Uint32Array(1)
21
+ crypto.getRandomValues(array)
22
+ return ((array[0] ?? 0) % 1000000).toString().padStart(6, "0")
25
23
  }
26
24
 
27
- export function timestamp(): string
28
- export function timestamp(date: Date): string
29
25
  export function timestamp(date?: Date): string {
30
26
  if (!date) date = new Date()
31
27
  return date.toISOString().slice(0, 19).replace("T", " ")
32
28
  }
33
29
 
34
30
  export function log(...message: unknown[]) {
35
- console.log(chalk.gray(timestamp()), ...message)
31
+ console.log(ansi.gray(timestamp()), ...message)
36
32
  }
37
33
  export function error(...message: unknown[]) {
38
- console.error(chalk.red(timestamp()), ...message)
34
+ console.error(ansi.red(timestamp()), ...message)
35
+ }
36
+ export function debug(...message: unknown[]) {
37
+ console.log(ansi.gray(timestamp()), ...message)
39
38
  }
40
39
 
41
- export async function input(prompt: string = chalk.black("> ")) {
40
+ export async function input(prompt: string = ansi.black("> ")) {
42
41
  await Bun.stdout.write(prompt)
43
42
  for await (const line of console) {
44
43
  return line
@@ -49,7 +48,7 @@ export type HTTPLog = {
49
48
  timestamp: string
50
49
  method: string
51
50
  url: string
52
- IP: string
51
+ ip: string
53
52
  request_id?: string
54
53
  service?: string
55
54
  level: "info" | "warn" | "error"
@@ -63,7 +62,7 @@ export function formatRequest(req: Request): HTTPLog {
63
62
  timestamp: new Date().toISOString(),
64
63
  method: req.method,
65
64
  url: new URL(req.url).pathname,
66
- IP: req.headers.get("x-forwarded-for") ?? "unknown",
65
+ ip: req.headers.get("x-forwarded-for") ?? "unknown",
67
66
  request_id: req.headers.get("x-request-id") ?? "none",
68
67
  service: "app",
69
68
  level: "info",
@@ -74,75 +73,6 @@ export function formatRequest(req: Request): HTTPLog {
74
73
  * Returns a one-line pretty string with colors using chalk
75
74
  */
76
75
  export function prettifyRequest(req: Request): string {
77
- const url = chalk.white(new URL(req.url).pathname)
78
- return `${chalk.gray(timestamp())} ${chalk.red(req.ip.address)} ${chalk.green(req.method)} ${url}`
79
- }
80
-
81
- interface Adapter {
82
- adapter: string
83
- networks: Bun.SocketAddress[]
84
- }
85
-
86
- export function listAdapters(): Adapter[] {
87
- const interfaces = os.networkInterfaces()
88
- const results: Adapter[] = []
89
-
90
- for (const [name, infos] of Object.entries(interfaces)) {
91
- if (!infos) continue
92
-
93
- const networks: Bun.SocketAddress[] = []
94
-
95
- for (const info of infos) {
96
- if (!info.address) continue
97
-
98
- networks.push({
99
- address: info.address,
100
- family: info.family,
101
- port: 0,
102
- })
103
- }
104
-
105
- results.push({
106
- adapter: name,
107
- networks,
108
- })
109
- }
110
-
111
- return results
112
- }
113
-
114
- type KeyPair = {
115
- public: string
116
- private: string
117
- }
118
-
119
- export async function key(): Promise<KeyPair> {
120
- const { publicKey, privateKey } = generateKeyPairSync("rsa", {
121
- modulusLength: 2048,
122
- publicKeyEncoding: {
123
- type: "spki",
124
- format: "pem",
125
- },
126
- privateKeyEncoding: {
127
- type: "pkcs8",
128
- format: "pem",
129
- },
130
- })
131
-
132
- return {
133
- public: publicKey,
134
- private: privateKey,
135
- }
136
- }
137
-
138
- export function encrypt(key: string, data: string) {
139
- const buffer = Buffer.from(data, "utf-8")
140
- const encrypted = publicEncrypt(key, buffer)
141
- return encrypted.toString("hex")
142
- }
143
-
144
- export function decrypt(key: string, encrypted: string) {
145
- const buffer = Buffer.from(encrypted, "hex")
146
- const decrypted = privateDecrypt(key, buffer)
147
- return decrypted.toString("utf-8")
76
+ const url = ansi.white(new URL(req.url).pathname)
77
+ return `${ansi.gray(timestamp())} ${ansi.red(req.ip.address)} ${ansi.green(req.method)} ${url}`
148
78
  }
package/tsconfig.json CHANGED
@@ -1,23 +1,32 @@
1
1
  {
2
- "$schema": "https://json.schemastore.org/tsconfig",
3
- "compilerOptions": {
4
- "declaration": true,
5
- "declarationMap": true,
6
- "esModuleInterop": true,
7
- "incremental": false,
8
- "isolatedModules": true,
9
- "lib": ["es2022", "DOM", "DOM.Iterable"],
10
- "module": "NodeNext",
11
- "moduleDetection": "force",
12
- "moduleResolution": "NodeNext",
13
- "noUncheckedIndexedAccess": true,
14
- "resolveJsonModule": true,
15
- "skipLibCheck": true,
16
- "strict": true,
17
- "target": "ES2022",
18
- "outDir": "dist",
19
- "rootDir": "src"
20
- },
21
- "include": ["src"],
22
- "exclude": ["node_modules", "dist"]
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "compilerOptions": {
4
+ "declaration": true,
5
+ "declarationMap": true,
6
+ "esModuleInterop": true,
7
+ "incremental": false,
8
+ "isolatedModules": true,
9
+ "lib": [
10
+ "ESNext",
11
+ "DOM",
12
+ "DOM.Iterable"
13
+ ],
14
+ "module": "esnext",
15
+ "moduleDetection": "force",
16
+ "moduleResolution": "bundler",
17
+ "noUncheckedIndexedAccess": true,
18
+ "resolveJsonModule": true,
19
+ "skipLibCheck": true,
20
+ "strict": true,
21
+ "target": "esnext",
22
+ "outDir": "dist",
23
+ "rootDir": "src"
24
+ },
25
+ "include": [
26
+ "src"
27
+ ],
28
+ "exclude": [
29
+ "node_modules",
30
+ "dist"
31
+ ]
23
32
  }
package/src/receive.ts DELETED
@@ -1,33 +0,0 @@
1
- export interface Email {
2
- from: string
3
- to: string[]
4
- subject: string
5
- bcc?: string[]
6
- cc?: string[]
7
- scheduled_at?: Date
8
- reply_to?: string[]
9
- html?: string
10
- text?: string
11
- tags?: {
12
- name: string
13
- value: string
14
- }[]
15
- created_at: Date
16
- }
17
-
18
- export class Receive {
19
- constructor(key?: string) {
20
- this.key = key
21
- }
22
- key?: string
23
- emails(listener: (email: Email) => void) {
24
- const ws = new WebSocket("wss://mail.modlin.dev:84/emails", {
25
- headers: {
26
- authorization: this.key ? `Basic ${this.key}` : undefined,
27
- },
28
- })
29
- ws.onmessage = ev => listener(JSON.parse(ev.data))
30
- }
31
- }
32
-
33
- export default Receive
package/src/session.ts DELETED
@@ -1,37 +0,0 @@
1
- import { getRandomValues, randomBytes } from "node:crypto"
2
-
3
- function pad(input: string) {
4
- const result: string[] = []
5
- for (let i = 0; i < input.length; i++) {
6
- result.push(input[i] as string)
7
- if ((i + 1) % 4 === 0 && i !== input.length - 1) {
8
- result.push("-")
9
- }
10
- }
11
- return result.join("")
12
- }
13
-
14
- export function randomID() {
15
- const session = randomBytes(16).toHex()
16
-
17
- return pad(session)
18
- }
19
- export function randomPN(): string {
20
- const MAX = 100_000_000
21
- const LIMIT = Math.floor(0x1_0000_0000 / MAX) * MAX
22
- const buf = new Uint32Array(1)
23
-
24
- let v: number
25
- while (true) {
26
- getRandomValues(buf)
27
- v = buf[0] as number
28
- if (v < LIMIT) break
29
- }
30
-
31
- const padded = (v % MAX).toString().padStart(8, "0")
32
- return `${padded.slice(0, 4)} ${padded.slice(4)}`
33
- }
34
-
35
- do {
36
- console.log(randomID())
37
- } while (true)