Skip to content

Commit 140ecb8

Browse files
committed
make @packages/network an independent bundle
1 parent 0a74184 commit 140ecb8

15 files changed

+89
-64
lines changed

guides/esm-migration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ When migrating some of these projects away from the `ts-node` entry [see `@packa
5353
- [x] packages/launcher ✅ **COMPLETED**
5454
- [x] packages/launchpad ✅ **COMPLETED**
5555
- [x] packages/net-stubbing ✅ **COMPLETED**
56-
- [ ] packages/network **PARTIAL** - entry point is JS
56+
- [x] packages/network **COMPLETED**
5757
- [x] packages/packherd-require ✅ **COMPLETED**
5858
- [ ] packages/proxy **PARTIAL** - entry point is JS
5959
- [x] packages/reporter ✅ **COMPLETED**

packages/network/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
cjs/
2+
esm/

packages/network/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ See the individual class files in [`./lib`](./lib) for more information.
1818

1919
## Building
2020

21-
Note: you should not ever need to build the .js files manually. `@packages/ts` provides require-time transpilation when in development.
21+
We currently build a CommonJS and an ESM version of this package. However, since this package is only consumed via CommonJS, we currently only build the CommonJS variant of the package.
2222

2323
```shell
2424
yarn workspace @packages/network build-prod

packages/network/lib/agent.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ export class CombinedAgent {
262262
}
263263
}
264264

265-
const getProxyOrTargetOverrideForUrl = (href) => {
265+
const getProxyOrTargetOverrideForUrl = (href: string) => {
266266
// HTTP_PROXY_TARGET_FOR_ORIGIN_REQUESTS is used for Cypress in Cypress E2E testing and will
267267
// force the parent Cypress server to treat the child Cypress server like a proxy without
268268
// having HTTP_PROXY set and will force traffic ONLY bound to that origin to behave
@@ -395,7 +395,7 @@ class HttpsAgent extends https.Agent {
395395
const port = options.uri?.port || '443'
396396
const hostname = options.uri?.hostname || 'localhost'
397397

398-
createProxySock({ proxy, shouldRetry: options.shouldRetry }, (originalErr?, proxySocket?, triggerRetry?) => {
398+
createProxySock({ proxy, shouldRetry: options.shouldRetry }, (originalErr?: Error, proxySocket?: net.Socket, triggerRetry?: (err: Error) => void) => {
399399
if (originalErr) {
400400
const err: any = new Error(`A connection to the upstream proxy could not be established: ${originalErr.message}`)
401401

@@ -406,12 +406,12 @@ class HttpsAgent extends https.Agent {
406406
}
407407

408408
const onClose = () => {
409-
triggerRetry(new Error('ERR_EMPTY_RESPONSE: The upstream proxy closed the socket after connecting but before sending a response.'))
409+
triggerRetry?.(new Error('ERR_EMPTY_RESPONSE: The upstream proxy closed the socket after connecting but before sending a response.'))
410410
}
411411

412412
const onError = (err: Error) => {
413-
triggerRetry(err)
414-
proxySocket.destroy()
413+
triggerRetry?.(err)
414+
proxySocket?.destroy()
415415
}
416416

417417
let buffer = ''
@@ -423,15 +423,15 @@ class HttpsAgent extends https.Agent {
423423

424424
if (!_.includes(buffer, _.repeat(CRLF, 2))) {
425425
// haven't received end of headers yet, keep buffering
426-
proxySocket.once('data', onData)
426+
proxySocket?.once('data', onData)
427427

428428
return
429429
}
430430

431431
// we've now gotten enough of a response not to retry
432432
// connecting to the proxy
433-
proxySocket.removeListener('error', onError)
434-
proxySocket.removeListener('close', onClose)
433+
proxySocket?.removeListener('error', onError)
434+
proxySocket?.removeListener('close', onClose)
435435

436436
if (!isResponseStatusCode200(buffer)) {
437437
return cb(new Error(`Error establishing proxy connection. Response from server was: ${buffer}`), undefined)
@@ -453,14 +453,14 @@ class HttpsAgent extends https.Agent {
453453
cb(undefined, proxySocket)
454454
}
455455

456-
proxySocket.once('close', onClose)
457-
proxySocket.once('error', onError)
458-
proxySocket.once('data', onData)
456+
proxySocket?.once('close', onClose)
457+
proxySocket?.once('error', onError)
458+
proxySocket?.once('data', onData)
459459

460460
const connectReq = buildConnectReqHead(hostname, port, proxy)
461461

462-
proxySocket.setNoDelay(true)
463-
proxySocket.write(connectReq)
462+
proxySocket?.setNoDelay(true)
463+
proxySocket?.write(connectReq)
464464
})
465465
}
466466
}

packages/network/lib/allow-destroy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import type net from 'net'
1010
export function allowDestroy (server: net.Server) {
1111
let connections: net.Socket[] = []
1212

13-
function trackConn (conn) {
13+
function trackConn (conn: net.Socket) {
1414
connections.push(conn)
1515

1616
conn.on('close', () => {

packages/network/lib/blocked.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@ import _ from 'lodash'
22
import minimatch from 'minimatch'
33
import { stripProtocolAndDefaultPorts } from './uri'
44

5-
export function matches (urlToCheck, blockHosts) {
5+
export function matches (urlToCheck: string, blockHosts: string[]) {
66
// normalize into flat array
7-
blockHosts = [].concat(blockHosts)
7+
const blockHostsNormalized: string[] = ([] as string[]).concat(blockHosts)
88

9-
urlToCheck = stripProtocolAndDefaultPorts(urlToCheck)
9+
const urlToCheckStripped = stripProtocolAndDefaultPorts(urlToCheck) as string
1010

1111
// use minimatch against the url
1212
// to see if any match
13-
const matchUrl = (hostMatcher) => {
14-
return minimatch(urlToCheck, hostMatcher)
13+
const matchUrl = (hostMatcher: string) => {
14+
return minimatch(urlToCheckStripped, hostMatcher)
1515
}
1616

17-
return _.find(blockHosts, matchUrl)
17+
return _.find(blockHostsNormalized, matchUrl)
1818
}

packages/network/lib/client-certificates.ts

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ import { URL, Url } from 'url'
22
import debugModule from 'debug'
33
import minimatch from 'minimatch'
44
import fs from 'fs-extra'
5-
6-
const { pki, asn1, pkcs12, util } = require('node-forge')
5+
import { pki, asn1, pkcs12, util } from 'node-forge'
76

87
const debug = debugModule('cypress:network:client-certificates')
98

@@ -195,7 +194,22 @@ export const clientCertificateStoreSingleton = new ClientCertificateStore()
195194
* network ClientCertificateStore
196195
* @param config
197196
*/
198-
export function loadClientCertificateConfig (config) {
197+
198+
type Config = {
199+
projectRoot: string
200+
clientCertificates: Array<{
201+
url: string
202+
ca: string[]
203+
certs: Array<{
204+
cert: string
205+
key: string
206+
passphrase: string
207+
pfx: string
208+
}>
209+
}>
210+
}
211+
212+
export function loadClientCertificateConfig (config: Config) {
199213
const { clientCertificates } = config
200214

201215
let index = 0
@@ -218,7 +232,7 @@ export function loadClientCertificateConfig (config) {
218232
const caRaw = loadBinaryFromFile(ca)
219233

220234
try {
221-
pki.certificateFromPem(caRaw)
235+
pki.certificateFromPem(caRaw.toString())
222236
} catch (error: any) {
223237
throw new Error(`Cannot parse CA cert: ${error.message}`)
224238
}
@@ -248,10 +262,10 @@ export function loadClientCertificateConfig (config) {
248262

249263
debug(`loading PEM cert from '${cert.cert}'`)
250264
const pemRaw = loadBinaryFromFile(cert.cert)
251-
let pemParsed = undefined
265+
let pemParsed: pki.Certificate | undefined = undefined
252266

253267
try {
254-
pemParsed = pki.certificateFromPem(pemRaw)
268+
pemParsed = pki.certificateFromPem(pemRaw.toString())
255269
} catch (error: any) {
256270
throw new Error(`Cannot parse PEM cert: ${error.message}`)
257271
}
@@ -270,13 +284,13 @@ export function loadClientCertificateConfig (config) {
270284

271285
try {
272286
if (passphrase) {
273-
if (!pki.decryptRsaPrivateKey(pemKeyRaw, passphrase)) {
287+
if (!pki.decryptRsaPrivateKey(pemKeyRaw.toString(), passphrase)) {
274288
throw new Error(
275289
`Cannot decrypt PEM key with supplied passphrase (check the passphrase file content and that it doesn't have unexpected whitespace at the end)`,
276290
)
277291
}
278292
} else {
279-
if (!pki.privateKeyFromPem(pemKeyRaw)) {
293+
if (!pki.privateKeyFromPem(pemKeyRaw.toString())) {
280294
throw new Error('Cannot load PEM key')
281295
}
282296
}
@@ -363,7 +377,7 @@ function loadTextFromFile (filepath: string): string {
363377
/**
364378
* Extract subject from supplied pem instance
365379
*/
366-
function extractSubjectFromPem (pem): string {
380+
function extractSubjectFromPem (pem: pki.Certificate): string {
367381
try {
368382
return pem.subject.attributes
369383
.map((attr) => [attr.shortName, attr.value].join('='))
@@ -391,9 +405,16 @@ function loadPfx (pfx: Buffer, passphrase: string | undefined) {
391405
/**
392406
* Extract subject from supplied pfx instance
393407
*/
394-
function extractSubjectFromPfx (pfx) {
408+
function extractSubjectFromPfx (pfx: pkcs12.Pkcs12Pfx) {
395409
try {
396-
const certs = pfx.getBags({ bagType: pki.oids.certBag })[pki.oids.certBag].map((item) => item.cert)
410+
const bags = pfx.getBags({ bagType: pki.oids.certBag })
411+
const certBag = bags[pki.oids.certBag]
412+
413+
if (!certBag || certBag.length === 0) {
414+
throw new Error('No certificate bag found in PFX file')
415+
}
416+
417+
const certs = certBag.map((item) => item.cert) as pki.Certificate[]
397418

398419
return certs[0].subject.attributes.map((attr) => [attr.shortName, attr.value].join('=')).join(', ')
399420
} catch (e: any) {

packages/network/lib/connect.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export function getAddress (port: number, hostname: string): Bluebird<net.Addres
5858
.any()
5959
}
6060

61-
export function getDelayForRetry (iteration) {
61+
export function getDelayForRetry (iteration: number) {
6262
return [0, 100, 200, 200][iteration]
6363
}
6464

@@ -67,10 +67,10 @@ export interface RetryingOptions {
6767
port: number
6868
host: string | undefined
6969
useTls: boolean
70-
getDelayMsForRetry: (iteration: number, err: Error) => number | undefined
70+
getDelayMsForRetry: (iteration: number, err: Error | undefined) => number | undefined
7171
}
7272

73-
function createSocket (opts: RetryingOptions, onConnect): net.Socket {
73+
function createSocket (opts: RetryingOptions, onConnect: () => void): net.Socket {
7474
const netOpts = _.defaults(_.pick(opts, 'family', 'host', 'port'), {
7575
family: 4,
7676
})
@@ -91,7 +91,7 @@ export function createRetryingSocket (
9191
}
9292

9393
function tryConnect (iteration = 0) {
94-
const retry = (err) => {
94+
const retry = (err: Error | undefined) => {
9595
const delay = opts.getDelayMsForRetry(iteration, err)
9696

9797
if (typeof delay === 'undefined') {
@@ -107,7 +107,7 @@ export function createRetryingSocket (
107107
}, delay)
108108
}
109109

110-
function onError (err) {
110+
function onError (err: Error) {
111111
sock.on('error', (err) => {
112112
debug('second error received on retried socket %o', { opts, iteration, err })
113113
})

packages/network/lib/cors.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ declare module 'url' {
200200
}
201201
}
202202

203-
export function urlMatchesOriginProtectionSpace (urlStr, origin) {
203+
export function urlMatchesOriginProtectionSpace (urlStr: string, origin: string) {
204204
const normalizedUrl = uri.addDefaultPort(urlStr).format()
205205
const normalizedOrigin = uri.addDefaultPort(origin).format()
206206

packages/network/package.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@
22
"name": "@packages/network",
33
"version": "0.0.0-development",
44
"private": true,
5-
"main": "index.js",
5+
"main": "cjs/index.js",
66
"scripts": {
77
"build": "yarn build:esm && yarn build:cjs",
8-
"build-old": "tsc --project .",
98
"build-prod": "yarn build",
109
"build:cjs": "rimraf cjs && tsc -p tsconfig.cjs.json",
1110
"build:esm": "rimraf esm && tsc -p tsconfig.esm.json",
@@ -18,7 +17,8 @@
1817
"test-debug": "npx vitest --inspect-brk --no-file-parallelism --test-timeout=0 --hook-timeout=0",
1918
"test-unit": "vitest run",
2019
"test-watch": "yarn test-unit --watch",
21-
"tslint": "tslint --config ../ts/tslint.json --project ."
20+
"tslint": "tslint --config ../ts/tslint.json --project .",
21+
"watch": "tsc -p tsconfig.cjs.json --watch"
2222
},
2323
"dependencies": {
2424
"@cypress/parse-domain": "2.4.0",
@@ -38,7 +38,9 @@
3838
"@packages/https-proxy": "0.0.0-development",
3939
"@packages/socket": "0.0.0-development",
4040
"@types/concat-stream": "1.6.0",
41+
"@types/proxy-from-env": "1.0.4",
4142
"express": "4.21.0",
43+
"rimraf": "6.0.1",
4244
"typescript": "~5.4.5",
4345
"vitest": "^3.2.4"
4446
},
@@ -47,5 +49,6 @@
4749
"esm"
4850
],
4951
"types": "./lib/index.ts",
52+
"module": "esm/index.js",
5053
"nx": {}
5154
}

0 commit comments

Comments
 (0)