@nxtedition/lib 21.6.3 → 21.8.0
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/app.js +124 -60
- package/couch.js +1 -1
- package/merge-ranges.js +7 -1
- package/package.json +1 -1
- package/s3.js +10 -11
package/app.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import * as inspector from 'node:inspector'
|
|
2
2
|
import os from 'node:os'
|
|
3
|
+
import http from 'node:http'
|
|
3
4
|
import net from 'node:net'
|
|
4
5
|
import assert from 'node:assert'
|
|
6
|
+
import cluster from 'node:cluster'
|
|
5
7
|
import stream from 'node:stream'
|
|
6
8
|
import { Buffer } from 'node:buffer'
|
|
7
9
|
import { getDockerSecretsSync } from './docker-secrets.js'
|
|
@@ -802,46 +804,138 @@ export function makeApp(appConfig, onTerminate) {
|
|
|
802
804
|
}
|
|
803
805
|
}
|
|
804
806
|
|
|
805
|
-
|
|
806
|
-
|
|
807
|
+
if (appConfig.inspect !== false && !cluster.isWorker) {
|
|
808
|
+
// TODO (fix): What about cluster?
|
|
807
809
|
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
const { type, id } = data
|
|
810
|
+
const inspectBC = new BroadcastChannel('nxt:inspect')
|
|
811
|
+
let inspectOpen = false
|
|
811
812
|
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
813
|
+
if (!isMainThread) {
|
|
814
|
+
inspectBC.onmessage = ({ data }) => {
|
|
815
|
+
const { type, id } = data
|
|
816
|
+
|
|
817
|
+
if (id !== threadId) {
|
|
818
|
+
return
|
|
819
|
+
}
|
|
815
820
|
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
+
if (type === 'inspect:open') {
|
|
822
|
+
// TODO (fix): What happens if you call inspect:open multiple times?
|
|
823
|
+
if (!inspectOpen) {
|
|
824
|
+
inspector.open(data.port, data.hostname)
|
|
825
|
+
inspectOpen = true
|
|
826
|
+
}
|
|
827
|
+
} else if (type === 'inspect:close') {
|
|
828
|
+
if (inspectOpen) {
|
|
829
|
+
inspector.close()
|
|
830
|
+
inspectOpen = false
|
|
831
|
+
}
|
|
832
|
+
}
|
|
821
833
|
}
|
|
822
|
-
}
|
|
823
834
|
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
+
inspectBC.postMessage({
|
|
836
|
+
type: 'inspect:register',
|
|
837
|
+
id: threadId,
|
|
838
|
+
worker: {
|
|
839
|
+
id: threadId,
|
|
840
|
+
name: serviceName,
|
|
841
|
+
module: serviceModule,
|
|
842
|
+
version: serviceVersion,
|
|
843
|
+
workerId: serviceWorkerId,
|
|
844
|
+
instanceId: serviceInstanceId,
|
|
845
|
+
threadId,
|
|
846
|
+
processId: process.pid,
|
|
847
|
+
},
|
|
848
|
+
})
|
|
849
|
+
destroyers.unshift(() => {
|
|
850
|
+
if (inspectOpen) {
|
|
851
|
+
inspector.close()
|
|
852
|
+
inspectOpen = false
|
|
853
|
+
}
|
|
854
|
+
inspectBC.postMessage({ type: 'inspect:unregister', id: threadId })
|
|
855
|
+
setTimeout(() => {
|
|
856
|
+
inspectBC.close()
|
|
857
|
+
}, 100)
|
|
858
|
+
})
|
|
859
|
+
} else {
|
|
860
|
+
const inspectMap = new Set()
|
|
861
|
+
|
|
862
|
+
inspectBC.onmessage = ({ data }) => {
|
|
863
|
+
const { type, worker } = data
|
|
835
864
|
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
865
|
+
if (type === 'inspect:register') {
|
|
866
|
+
inspectMap.set(data.id, worker)
|
|
867
|
+
} else if (type === 'inspect:unregister') {
|
|
868
|
+
inspectMap.delete(data.id)
|
|
869
|
+
}
|
|
840
870
|
}
|
|
871
|
+
destroyers.unshift(() => inspectBC.close())
|
|
872
|
+
|
|
873
|
+
// TODO (fix): Determinisitc port also in dev mode... hash of something?
|
|
874
|
+
const port =
|
|
875
|
+
appConfig.inspect?.port ?? (isProduction ? 38603 : Math.floor(38000 + Math.random() * 1000))
|
|
876
|
+
const server = http
|
|
877
|
+
.createServer(async (req, res) => {
|
|
878
|
+
try {
|
|
879
|
+
// TOOD (fix); Better matching...
|
|
880
|
+
if (!req.url.startsWith('/inspect')) {
|
|
881
|
+
res.statusCode = 404
|
|
882
|
+
res.end()
|
|
883
|
+
return
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
if (req.method === 'GET') {
|
|
887
|
+
res.end(
|
|
888
|
+
JSON.stringify({
|
|
889
|
+
workers: Array.from(inspectMap.values()),
|
|
890
|
+
}),
|
|
891
|
+
)
|
|
892
|
+
return
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
if (req.method === 'POST') {
|
|
896
|
+
const m = req.url.match(/^\/inspect\/([^/]+)/)
|
|
897
|
+
if (!m) {
|
|
898
|
+
res.statusCode = 404
|
|
899
|
+
res.end()
|
|
900
|
+
return
|
|
901
|
+
} else {
|
|
902
|
+
const { port, hostname } = await json(req)
|
|
903
|
+
|
|
904
|
+
// TODO (fix): What about return value & errors?
|
|
905
|
+
inspectBC.postMessage({
|
|
906
|
+
type: port || hostname ? 'inspect:open' : 'inspect:close',
|
|
907
|
+
id: parseInt(m[1]),
|
|
908
|
+
port,
|
|
909
|
+
hostname,
|
|
910
|
+
})
|
|
911
|
+
|
|
912
|
+
res.end()
|
|
913
|
+
return
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
res.statusCode = 405
|
|
918
|
+
res.end()
|
|
919
|
+
} catch (err) {
|
|
920
|
+
logger?.error({ err }, 'inspect http error')
|
|
921
|
+
|
|
922
|
+
if (res.headersSent) {
|
|
923
|
+
res.destroy()
|
|
924
|
+
} else {
|
|
925
|
+
res.statusCode = 500
|
|
926
|
+
res.end()
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
})
|
|
930
|
+
.listen(port)
|
|
931
|
+
|
|
932
|
+
logger.debug({ port }, 'inspect listening')
|
|
933
|
+
|
|
934
|
+
destroyers.unshift(() => new Promise((resolve) => server.close(resolve)))
|
|
841
935
|
}
|
|
842
|
-
destroyers.unshift(() => inspectBC.close())
|
|
843
936
|
}
|
|
844
937
|
|
|
938
|
+
// TODO (fix): Deprecate
|
|
845
939
|
if (appConfig.http) {
|
|
846
940
|
const httpConfig = { ...appConfig.http, ...config.http }
|
|
847
941
|
|
|
@@ -864,36 +958,6 @@ export function makeApp(appConfig, onTerminate) {
|
|
|
864
958
|
return next()
|
|
865
959
|
}
|
|
866
960
|
},
|
|
867
|
-
async ({ req, res }, next) => {
|
|
868
|
-
if (req.url.startsWith('/inspect')) {
|
|
869
|
-
if (req.method === 'GET') {
|
|
870
|
-
res.end(JSON.stringify({ workers: Array.from(inspectSet).map((id) => ({ id })) }))
|
|
871
|
-
} else if (req.method === 'POST') {
|
|
872
|
-
const m = req.url.match(/^\/inspect\/([^/]+)/)
|
|
873
|
-
if (!m) {
|
|
874
|
-
res.statusCode = 404
|
|
875
|
-
res.end()
|
|
876
|
-
} else {
|
|
877
|
-
const { port, hostname } = await json(req)
|
|
878
|
-
|
|
879
|
-
// TODO (fix): What about return value & errors?
|
|
880
|
-
inspectBC.postMessage({
|
|
881
|
-
type: port || hostname ? 'inspect:open' : 'inspect:close',
|
|
882
|
-
id: m[1],
|
|
883
|
-
port,
|
|
884
|
-
hostname,
|
|
885
|
-
})
|
|
886
|
-
|
|
887
|
-
res.end()
|
|
888
|
-
}
|
|
889
|
-
} else {
|
|
890
|
-
res.statusCode = 405
|
|
891
|
-
res.end()
|
|
892
|
-
}
|
|
893
|
-
} else {
|
|
894
|
-
return next()
|
|
895
|
-
}
|
|
896
|
-
},
|
|
897
961
|
appConfig.http.request
|
|
898
962
|
? appConfig.http.request
|
|
899
963
|
: typeof appConfig.http === 'function'
|
package/couch.js
CHANGED
|
@@ -119,7 +119,7 @@ export function makeCouch(opts) {
|
|
|
119
119
|
* @param {string} [options.since=null] - The sequence number to start from.
|
|
120
120
|
* @param {number} [options.highWaterMark=128 * 1024] - Buffering.
|
|
121
121
|
* @param {object} [options.selector=null] - The selector to filter changes.
|
|
122
|
-
* @
|
|
122
|
+
* @return {AsyncGenerator<Array<{ id: string, seq?: string, doc?: Object, deleted?: boolean, changes: Array<{ rev: string }>}> & { lastSeq: string | null | 0 }}
|
|
123
123
|
*/
|
|
124
124
|
async function* changes({ client = defaultClient, signal = null, logger, ...options } = {}) {
|
|
125
125
|
const params = {}
|
package/merge-ranges.js
CHANGED
|
@@ -29,7 +29,13 @@ export default function mergeRanges(ranges) {
|
|
|
29
29
|
const range = ranges[n]
|
|
30
30
|
const top = stack[stack.length - 1]
|
|
31
31
|
|
|
32
|
-
if (
|
|
32
|
+
if (
|
|
33
|
+
!Array.isArray(range) ||
|
|
34
|
+
range.length !== 2 ||
|
|
35
|
+
!Number.isFinite(range[0]) ||
|
|
36
|
+
!Number.isFinite(range[1]) ||
|
|
37
|
+
range[0] > range[1]
|
|
38
|
+
) {
|
|
33
39
|
continue
|
|
34
40
|
}
|
|
35
41
|
|
package/package.json
CHANGED
package/s3.js
CHANGED
|
@@ -10,13 +10,13 @@ const QUEUE = new PQueue({ concurrency: 8 })
|
|
|
10
10
|
const MD5_HEX_EXPR = /^[A-F0-9]{32}$/i
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* @
|
|
14
|
-
* @
|
|
13
|
+
* @import { Dispatcher } from 'undici'
|
|
14
|
+
* @import { S3ClientConfig, CreateMultipartUploadRequest } from '@aws-sdk/client-s3'
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
export class S3Client extends AWS.S3Client {
|
|
18
18
|
/**
|
|
19
|
-
* @param {S3ClientConfig} config
|
|
19
|
+
* @param {S3ClientConfig & { dispatcher?: Dispatcher }} config
|
|
20
20
|
*/
|
|
21
21
|
constructor(config) {
|
|
22
22
|
const { dispatcher, ...options } = config
|
|
@@ -79,12 +79,11 @@ class UndiciRequestHandler extends NodeHttpHandler {
|
|
|
79
79
|
* @param {Object} options.logger - The logger to use.
|
|
80
80
|
* @param {number} [options.partSize=16e6] - The size of each part in the multipart upload.
|
|
81
81
|
* @param {PQueue} [options.queue] - The queue to use for part uploads.
|
|
82
|
-
* @param {
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* @param {number} [options.params.ContentLength] - The length of the object.
|
|
82
|
+
* @param {CreateMultipartUploadRequest & {
|
|
83
|
+
* Body: Buffer | NodeJS.ReadStream,
|
|
84
|
+
* ContentMD5?: string,
|
|
85
|
+
* ContentLength?: number,
|
|
86
|
+
* }} options.params - The parameters for the upload.
|
|
88
87
|
* @returns {Promise<Object>} The result of the upload.
|
|
89
88
|
*/
|
|
90
89
|
export async function upload({
|
|
@@ -107,7 +106,7 @@ export async function upload({
|
|
|
107
106
|
throw new Error('Invalid params')
|
|
108
107
|
}
|
|
109
108
|
|
|
110
|
-
const { Body, Key, Bucket, ContentMD5, ContentLength } = params
|
|
109
|
+
const { Body, Key, Bucket, ContentMD5, ContentLength, ...createMultipartParams } = params
|
|
111
110
|
|
|
112
111
|
const size = ContentLength != null ? Number(ContentLength) : null
|
|
113
112
|
|
|
@@ -144,7 +143,7 @@ export async function upload({
|
|
|
144
143
|
}
|
|
145
144
|
|
|
146
145
|
const multipartUploadOutput = await s3.send(
|
|
147
|
-
new AWS.CreateMultipartUploadCommand({ Bucket, Key }),
|
|
146
|
+
new AWS.CreateMultipartUploadCommand({ ...createMultipartParams, Bucket, Key }),
|
|
148
147
|
{ abortSignal: uploader.signal },
|
|
149
148
|
)
|
|
150
149
|
uploader.signal.throwIfAborted()
|