Skip to content

Commit 6414063

Browse files
author
wackfx
committed
Reworked from source cloudflare branch
feat: reran transpile fix linter feat: final touches + test files squashed 2 commits fix: Polyfills bulk (to please linter) fix: Removed MD5 + put back SHA in the digest() squashed 5 commits fix: cloudflare workers deployment feat: fixed auth fix: encrypt not found in worker :( fix: postgres SASL fix: linting
1 parent 5217b47 commit 6414063

File tree

7 files changed

+155
-76
lines changed

7 files changed

+155
-76
lines changed

cf/polyfills.js

Lines changed: 86 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -13,61 +13,69 @@ const IPv4Reg = new RegExp(`^${v4Str}$`)
1313
const v6Seg = '(?:[0-9a-fA-F]{1,4})'
1414
const IPv6Reg = new RegExp(
1515
'^(' +
16-
`(?:${v6Seg}:){7}(?:${v6Seg}|:)|` +
17-
`(?:${v6Seg}:){6}(?:${v4Str}|:${v6Seg}|:)|` +
18-
`(?:${v6Seg}:){5}(?::${v4Str}|(:${v6Seg}){1,2}|:)|` +
19-
`(?:${v6Seg}:){4}(?:(:${v6Seg}){0,1}:${v4Str}|(:${v6Seg}){1,3}|:)|` +
20-
`(?:${v6Seg}:){3}(?:(:${v6Seg}){0,2}:${v4Str}|(:${v6Seg}){1,4}|:)|` +
21-
`(?:${v6Seg}:){2}(?:(:${v6Seg}){0,3}:${v4Str}|(:${v6Seg}){1,5}|:)|` +
22-
`(?:${v6Seg}:){1}(?:(:${v6Seg}){0,4}:${v4Str}|(:${v6Seg}){1,6}|:)|` +
23-
`(?::((?::${v6Seg}){0,5}:${v4Str}|(?::${v6Seg}){1,7}|:))` +
24-
')(%[0-9a-zA-Z-.:]{1,})?$'
16+
`(?:${v6Seg}:){7}(?:${v6Seg}|:)|` +
17+
`(?:${v6Seg}:){6}(?:${v4Str}|:${v6Seg}|:)|` +
18+
`(?:${v6Seg}:){5}(?::${v4Str}|(:${v6Seg}){1,2}|:)|` +
19+
`(?:${v6Seg}:){4}(?:(:${v6Seg}){0,1}:${v4Str}|(:${v6Seg}){1,3}|:)|` +
20+
`(?:${v6Seg}:){3}(?:(:${v6Seg}){0,2}:${v4Str}|(:${v6Seg}){1,4}|:)|` +
21+
`(?:${v6Seg}:){2}(?:(:${v6Seg}){0,3}:${v4Str}|(:${v6Seg}){1,5}|:)|` +
22+
`(?:${v6Seg}:){1}(?:(:${v6Seg}){0,4}:${v4Str}|(:${v6Seg}){1,6}|:)|` +
23+
`(?::((?::${v6Seg}){0,5}:${v4Str}|(?::${v6Seg}){1,7}|:))` +
24+
')(%[0-9a-zA-Z-.:]{1,})?$'
2525
)
2626

2727
const textEncoder = new TextEncoder()
2828
export const crypto = {
29-
randomBytes: l => Crypto.getRandomValues(Buffer.alloc(l)),
30-
pbkdf2Sync: async(password, salt, iterations, keylen) => Crypto.subtle.deriveBits(
31-
{
32-
name: 'PBKDF2',
33-
hash: 'SHA-256',
34-
salt,
35-
iterations
36-
},
37-
await Crypto.subtle.importKey(
38-
'raw',
39-
textEncoder.encode(password),
40-
'PBKDF2',
41-
false,
29+
randomBytes: (l) => Crypto.getRandomValues(Buffer.alloc(l)),
30+
pbkdf2Sync: async (password, salt, iterations, keylen) =>
31+
Crypto.subtle.deriveBits(
32+
{
33+
name: 'PBKDF2',
34+
hash: 'SHA-256',
35+
salt,
36+
iterations
37+
},
38+
await Crypto.subtle.importKey(
39+
'raw',
40+
textEncoder.encode(password),
41+
'PBKDF2',
42+
false,
43+
['deriveBits']
44+
),
45+
keylen * 8,
4246
['deriveBits']
4347
),
44-
keylen * 8,
45-
['deriveBits']
46-
),
4748
createHash: (type) => ({
4849
update: (x) => ({
4950
digest: () => {
50-
return type === 'sha256'
51-
? Crypto.subtle.digest('SHA-256', x)
52-
: Crypto.subtle.digest('MD5', x)
51+
if (type !== 'sha256')
52+
throw Error('createHash only supports sha256 on cloudflare.')
53+
if (!(x instanceof Uint8Array))
54+
x = textEncoder.encode(x)
55+
return Crypto.subtle.digest('SHA-256', x)
5356
}
5457
})
5558
}),
5659
createHmac: (type, key) => ({
57-
update: x => ({
58-
digest: async() => Buffer.from(await Crypto.subtle.sign(
59-
'HMAC',
60-
await Crypto.subtle.importKey('raw', key, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']),
61-
textEncoder.encode(x)
62-
))
60+
update: (x) => ({
61+
digest: async () =>
62+
Buffer.from(
63+
await Crypto.subtle.sign(
64+
'HMAC',
65+
await Crypto.subtle.importKey(
66+
'raw',
67+
key,
68+
{ name: 'HMAC', hash: 'SHA-256' },
69+
false,
70+
['sign']
71+
),
72+
textEncoder.encode(x)
73+
)
74+
)
6375
})
6476
})
6577
}
6678

67-
export const process = {
68-
env: {}
69-
}
70-
7179
export const os = {
7280
userInfo() {
7381
return { username: 'postgres' }
@@ -81,19 +89,23 @@ export const fs = {
8189
}
8290

8391
export const net = {
84-
isIP: x => RegExp.prototype.test.call(IPv4Reg, x) ? 4 : RegExp.prototype.test.call(IPv6Reg, x) ? 6 : 0,
92+
isIP: (x) =>
93+
RegExp.prototype.test.call(IPv4Reg, x)
94+
? 4
95+
: RegExp.prototype.test.call(IPv6Reg, x)
96+
? 6
97+
: 0,
8598
Socket
8699
}
87100

88101
export { setImmediate, clearImmediate }
89102

90103
export const tls = {
91-
connect(x) {
92-
const tcp = x.socket
104+
connect({ socket: tcp, servername }) {
93105
tcp.writer.releaseLock()
94106
tcp.reader.releaseLock()
95107
tcp.readyState = 'upgrading'
96-
tcp.raw = tcp.raw.startTls({ servername: x.servername })
108+
tcp.raw = tcp.raw.startTls({ servername })
97109
tcp.raw.closed.then(
98110
() => tcp.emit('close'),
99111
(e) => tcp.emit('error', e)
@@ -133,7 +145,7 @@ function Socket() {
133145
() => {
134146
tcp.readyState !== 'upgrade'
135147
? close()
136-
: (tcp.readyState = 'open', tcp.emit('secureConnect'))
148+
: ((tcp.readyState = 'open'), tcp.emit('secureConnect'))
137149
},
138150
(e) => tcp.emit('error', e)
139151
)
@@ -151,8 +163,7 @@ function Socket() {
151163
}
152164

153165
function close() {
154-
if (tcp.readyState === 'closed')
155-
return
166+
if (tcp.readyState === 'closed') return
156167

157168
tcp.readyState = 'closed'
158169
tcp.emit('close')
@@ -164,9 +175,7 @@ function Socket() {
164175
}
165176

166177
function end(data) {
167-
return data
168-
? tcp.write(data, () => tcp.raw.close())
169-
: tcp.raw.close()
178+
return data ? tcp.write(data, () => tcp.raw.close()) : tcp.raw.close()
170179
}
171180

172181
function destroy() {
@@ -178,7 +187,7 @@ function Socket() {
178187
try {
179188
let done
180189
, value
181-
while (({ done, value } = await tcp.reader.read(), !done))
190+
while ((({ done, value } = await tcp.reader.read()), !done))
182191
tcp.emit('data', Buffer.from(value))
183192
} catch (err) {
184193
error(err)
@@ -211,3 +220,31 @@ function setImmediate(fn) {
211220
function clearImmediate(id) {
212221
tasks.delete(id)
213222
}
223+
224+
const nowOffset = Date.now()
225+
const now = () => Date.now() - nowOffset
226+
const hrtime = (previousTimestamp) => {
227+
const baseNow = Math.floor((Date.now() - now()) * 1e-3)
228+
const clocktime = now() * 1e-3
229+
let seconds = Math.floor(clocktime) + baseNow
230+
let nanoseconds = Math.floor((clocktime % 1) * 1e9)
231+
232+
if (previousTimestamp) {
233+
seconds = seconds - previousTimestamp[0]
234+
nanoseconds = nanoseconds - previousTimestamp[1]
235+
if (nanoseconds < 0) {
236+
seconds--
237+
nanoseconds += 1e9
238+
}
239+
}
240+
return [seconds, nanoseconds]
241+
}
242+
hrtime.bigint = () => {
243+
const time = hrtime()
244+
return BigInt(`${time[0]}${time[1]}`)
245+
}
246+
247+
export const process = {
248+
env: {},
249+
hrtime
250+
}

cf/src/connection.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
import { process } from '../polyfills.js'
21
import { Buffer } from 'node:buffer'
3-
import { setImmediate, clearImmediate } from '../polyfills.js'
4-
import { net } from '../polyfills.js'
5-
import { tls } from '../polyfills.js'
6-
import { crypto } from '../polyfills.js'
2+
import { setImmediate, clearImmediate, process, net, tls, crypto } from '../polyfills.js'
73
import Stream from 'node:stream'
84

95
import { stringify, handleValue, arrayParser, arraySerializer } from './types.js'
@@ -131,7 +127,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
131127
try {
132128
x = options.socket
133129
? (await Promise.resolve(options.socket(options)))
134-
: net.Socket()
130+
: await net.Socket()
135131
} catch (e) {
136132
error(e)
137133
return

cf/src/index.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import { process } from '../polyfills.js'
2-
import { os } from '../polyfills.js'
3-
import { fs } from '../polyfills.js'
1+
import { process, os, fs } from '../polyfills.js'
42

53
import {
64
mergeUserTypes,

cf/test-pages.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Add your database url and run this file with
2+
// npx wrangler pages dev ./cf --script-path test-pages.js --compatibility-date=2023-06-20 --log-level=debug --compatibility-flag=nodejs_compat
3+
import postgres from './src/index'
4+
const DATABASE_URL = ''
5+
6+
export default {
7+
async fetch(request, env) {
8+
const url = new URL(request.url);
9+
if (url.pathname.includes('/favicon.ico')) {
10+
return new Response('')
11+
}
12+
if (url.pathname.startsWith('/')) {
13+
const sql = postgres(DATABASE_URL)
14+
const rows = await sql`SELECT table_name FROM information_schema.columns`
15+
return new Response(rows.map((e) => e.table_name).join('\n'))
16+
}
17+
18+
// Otherwise, serve the static assets.
19+
// Without this, the Worker will error and no assets will be served.
20+
return env.ASSETS.fetch(request)
21+
},
22+
}

cf/test-worker.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Add your database url and run this file with
2+
// npx wrangler dev ./cf/test-worker.js --compatibility-date=2023-06-20 --log-level=debug --compatibility-flag=nodejs_compat
3+
import postgres from './src/index'
4+
const DATABASE_URL = ''
5+
6+
export default {
7+
async fetch(request, env, ctx) {
8+
if (request.url.includes('/favicon.ico'))
9+
return new Response()
10+
11+
const sql = postgres(DATABASE_URL)
12+
const rows = await sql`SELECT table_name FROM information_schema.columns`
13+
return new Response(rows.map((e) => e.table_name).join('\n'))
14+
},
15+
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,4 @@
5656
"pg",
5757
"database"
5858
]
59-
}
59+
}

transpile.cf.js

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,49 @@
11
import fs from 'fs'
22
import path from 'path'
33

4-
const empty = x => fs.readdirSync(x).forEach(f => fs.unlinkSync(path.join(x, f)))
5-
, ensureEmpty = x => !fs.existsSync(x) ? fs.mkdirSync(x) : empty(x)
4+
const empty = (x) =>
5+
fs.readdirSync(x).forEach((f) => fs.unlinkSync(path.join(x, f)))
6+
, ensureEmpty = (x) => (!fs.existsSync(x) ? fs.mkdirSync(x) : empty(x))
67
, root = 'cf'
78
, src = path.join(root, 'src')
89

910
ensureEmpty(src)
1011

11-
fs.readdirSync('src').forEach(name =>
12+
fs.readdirSync('src').forEach((name) =>
1213
fs.writeFileSync(
1314
path.join(src, name),
1415
transpile(fs.readFileSync(path.join('src', name), 'utf8'), name, 'src')
1516
)
1617
)
1718

1819
function transpile(x) {
19-
const timers = x.includes('setImmediate')
20-
? 'import { setImmediate, clearImmediate } from \'../polyfills.js\'\n'
21-
: ''
22-
23-
const process = x.includes('process.')
24-
? 'import { process } from \'../polyfills.js\'\n'
25-
: ''
20+
const polyfills = [
21+
x.includes('setImmediate') ? ['setImmediate', 'clearImmediate'] : undefined,
22+
x.includes('process') ? ['process'] : undefined,
23+
x.includes('import net from \'net\'') ? ['net'] : undefined,
24+
x.includes('import tls from \'tls\'') ? ['tls'] : undefined,
25+
x.includes('import crypto from \'crypto\'') ? ['crypto'] : undefined,
26+
x.includes('import os from \'os\'') ? ['os'] : undefined,
27+
x.includes('import fs from \'fs\'') ? ['fs'] : undefined
28+
].filter(Boolean).flat()
2629

2730
const buffer = x.includes('Buffer')
2831
? 'import { Buffer } from \'node:buffer\'\n'
2932
: ''
3033

31-
return process + buffer + timers + x
32-
.replace('import net from \'net\'', 'import { net } from \'../polyfills.js\'')
33-
.replace('import tls from \'tls\'', 'import { tls } from \'../polyfills.js\'')
34-
.replace('import crypto from \'crypto\'', 'import { crypto } from \'../polyfills.js\'')
35-
.replace('import os from \'os\'', 'import { os } from \'../polyfills.js\'')
36-
.replace('import fs from \'fs\'', 'import { fs } from \'../polyfills.js\'')
37-
.replace(/ from '([a-z_]+)'/g, ' from \'node:$1\'')
34+
return (
35+
buffer +
36+
// bulk add polyfills
37+
(polyfills.length ? `import { ${polyfills.join(', ')} } from '../polyfills.js'\n` : '') +
38+
x
39+
.replace(': net.Socket()', ': await net.Socket()')
40+
.replace('import Stream from \'stream\'', 'import Stream from \'node:stream\'')
41+
// cleanup polyfills
42+
.replace('import crypto from \'crypto\'\n', '')
43+
.replace('import net from \'net\'\n', '')
44+
.replace('import tls from \'tls\'\n', '')
45+
.replace('import os from \'os\'\n', '')
46+
.replace('import fs from \'fs\'\n', '')
47+
.replace(/ from '([a-z_]+)'/g, ' from \'node:$1\'')
48+
)
3849
}

0 commit comments

Comments
 (0)