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 +6 -4
- package/src/crypto.d.ts +21 -0
- package/src/crypto.ts +151 -0
- package/src/network.ts +34 -0
- package/src/types.d.ts +37 -0
- package/src/utils.d.ts +12 -0
- package/src/utils.ts +21 -91
- package/tsconfig.json +30 -21
- package/src/receive.ts +0 -33
- package/src/session.ts +0 -37
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.
|
|
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": "./
|
|
15
|
-
"import": "./
|
|
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
|
-
"
|
|
28
|
+
"ansi-colors": "^4.1.3",
|
|
27
29
|
"drizzle-orm": "latest",
|
|
28
30
|
"zod": "latest"
|
|
29
31
|
}
|
package/src/crypto.d.ts
ADDED
|
@@ -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
|
|
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
|
|
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
|
|
18
|
-
|
|
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
|
|
23
|
-
|
|
24
|
-
|
|
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(
|
|
31
|
+
console.log(ansi.gray(timestamp()), ...message)
|
|
36
32
|
}
|
|
37
33
|
export function error(...message: unknown[]) {
|
|
38
|
-
console.error(
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
78
|
-
return `${
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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)
|