jspurefix 5.6.2 → 5.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/DEMO_PORT_PLAN.md +1 -1
- package/README.md +256 -587
- package/dist/transport/ascii/ascii-session.d.ts +1 -0
- package/dist/transport/ascii/ascii-session.js +19 -0
- package/dist/transport/ascii/ascii-session.js.map +1 -1
- package/dist/transport/http/http-acceptor.js +2 -2
- package/dist/transport/http/http-acceptor.js.map +1 -1
- package/dist/transport/session/fix-session.d.ts +1 -0
- package/dist/transport/session/fix-session.js +7 -0
- package/dist/transport/session/fix-session.js.map +1 -1
- package/jsfix.test_client.txt +75 -71
- package/jsfix.test_server.txt +72 -68
- package/package.json +2 -4
- package/src/transport/ascii/ascii-session.ts +20 -0
- package/src/transport/http/http-acceptor.ts +2 -2
- package/src/transport/session/fix-session.ts +14 -0
- package/src/util/unzip.js +54 -184
package/src/util/unzip.js
CHANGED
|
@@ -1,202 +1,72 @@
|
|
|
1
1
|
const yauzl = require('yauzl')
|
|
2
2
|
const path = require('path')
|
|
3
3
|
const fs = require('fs')
|
|
4
|
-
const
|
|
5
|
-
const Transform = require('stream').Transform
|
|
4
|
+
const { pipeline } = require('stream/promises')
|
|
6
5
|
|
|
7
|
-
//
|
|
6
|
+
// Extracts a zip file into the current working directory.
|
|
7
|
+
//
|
|
8
|
+
// Replaces an older copy of the yauzl example unzip script. The previous
|
|
9
|
+
// version drove a 60Hz progress interval via terminal backspaces and did
|
|
10
|
+
// not attach error handlers to any of the streams in its pipeline. In a
|
|
11
|
+
// non-TTY environment (eg. GitHub Actions) the backspaces produced
|
|
12
|
+
// unreadable output; worse, if any stream errored silently the script
|
|
13
|
+
// hung forever and CI runs were cancelled at the workflow timeout.
|
|
14
|
+
//
|
|
15
|
+
// Follows the canonical yauzl lazyEntries pattern: install 'entry' /
|
|
16
|
+
// 'end' / 'error' handlers once on the zipfile, drive the next read
|
|
17
|
+
// with zipfile.readEntry() at the end of each entry's work.
|
|
18
|
+
// NB: requires yauzl >= 3.3.1 — 3.3.0 truncates inflated streams on
|
|
19
|
+
// Node 26+ (the next entry's readStream stalls without emitting 'end').
|
|
8
20
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
let endArg
|
|
13
|
-
const args = process.argv.slice(2)
|
|
14
|
-
for (let i = 0; i < args.length; i++) {
|
|
15
|
-
const arg = args[i]
|
|
16
|
-
if (arg === '--offset') {
|
|
17
|
-
i += 1
|
|
18
|
-
offsetArg = parseInt(args[i])
|
|
19
|
-
if (isNaN(offsetArg)) throw new Error('--offset argument not parsable as an int')
|
|
20
|
-
} else if (arg === '--len') {
|
|
21
|
-
i += 1
|
|
22
|
-
lenArg = parseInt(args[i])
|
|
23
|
-
if (isNaN(lenArg)) throw new Error('--len argument not parsable as an int')
|
|
24
|
-
} else if (arg === '--end') {
|
|
25
|
-
i += 1
|
|
26
|
-
endArg = parseInt(args[i])
|
|
27
|
-
if (isNaN(endArg)) throw new Error('--end argument not parsable as an int')
|
|
28
|
-
} else if (['-h', '--help'].includes(arg)) {
|
|
29
|
-
// print help
|
|
30
|
-
zipFilePath = null
|
|
31
|
-
break
|
|
32
|
-
} else if (/^--/.test(arg)) {
|
|
33
|
-
throw new Error('unrecognized option: ' + arg)
|
|
34
|
-
} else {
|
|
35
|
-
if (zipFilePath != null) throw new Error('too many arguments')
|
|
36
|
-
zipFilePath = arg
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
if (zipFilePath == null || /^-/.test(zipFilePath) || (lenArg != null && endArg != null)) {
|
|
40
|
-
console.log(
|
|
41
|
-
'usage: node unzip.js [options] path/to/file.zip\n' +
|
|
42
|
-
'\n' +
|
|
43
|
-
'unzips the specified zip file into the current directory\n' +
|
|
44
|
-
'\n' +
|
|
45
|
-
'options:\n' +
|
|
46
|
-
' --offset START\n' +
|
|
47
|
-
' --len LEN\n' +
|
|
48
|
-
' --end END\n' +
|
|
49
|
-
' interprets the middle of the specified file as a zipfile.\n' +
|
|
50
|
-
' starting START number of bytes in from the beginning (default 0).\n' +
|
|
51
|
-
' end with length of LEN (default is all the way to the end of the file).\n' +
|
|
52
|
-
' or end at byte offset END (exclusive) (default is the end of the file).\n' +
|
|
53
|
-
' end can be negative to count backwards from the end of the file\n' +
|
|
54
|
-
' (example, `--end -1` excludes the last byte of the file).\n' +
|
|
55
|
-
'')
|
|
21
|
+
const zipFilePath = process.argv[2]
|
|
22
|
+
if (!zipFilePath) {
|
|
23
|
+
console.error('usage: node unzip.js path/to/file.zip')
|
|
56
24
|
process.exit(1)
|
|
57
25
|
}
|
|
58
26
|
|
|
59
|
-
function
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (err == null) return cb() // already exists
|
|
63
|
-
|
|
64
|
-
const parent = path.dirname(dir)
|
|
65
|
-
mkdirp(parent, function () {
|
|
66
|
-
process.stdout.write(dir.replace(/\/$/, '') + '/\n')
|
|
67
|
-
fs.mkdir(dir, cb)
|
|
68
|
-
})
|
|
69
|
-
})
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (offsetArg != null || lenArg != null || endArg != null) {
|
|
73
|
-
openMiddleOfFile(zipFilePath, { lazyEntries: true }, offsetArg, lenArg, endArg, handleZipFile)
|
|
74
|
-
} else {
|
|
75
|
-
yauzl.open(zipFilePath, { lazyEntries: true }, handleZipFile)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function openMiddleOfFile (zipFilePath, options, offsetArg, lenArg, endArg, handleZipFile) {
|
|
79
|
-
fs.open(zipFilePath, 'r', function (err, fd) {
|
|
80
|
-
if (err != null) throw err
|
|
81
|
-
fs.fstat(fd, function (err, stats) {
|
|
27
|
+
function extract (zipFilePath) {
|
|
28
|
+
return new Promise((resolve, reject) => {
|
|
29
|
+
yauzl.open(zipFilePath, { lazyEntries: true }, (err, zipfile) => {
|
|
82
30
|
if (err) {
|
|
83
|
-
|
|
31
|
+
reject(err)
|
|
32
|
+
return
|
|
84
33
|
}
|
|
85
|
-
// resolve optional parameters
|
|
86
|
-
if (offsetArg == null) offsetArg = 0
|
|
87
|
-
if (lenArg == null && endArg == null) endArg = stats.size
|
|
88
|
-
if (endArg == null) endArg = lenArg + offsetArg
|
|
89
|
-
else if (endArg < 0) endArg = stats.size + endArg
|
|
90
|
-
// validate parameters
|
|
91
|
-
if (offsetArg < 0) throw new Error('--offset < 0')
|
|
92
|
-
if (lenArg < 0) throw new Error('--len < 0')
|
|
93
|
-
if (offsetArg > endArg) throw new Error('--offset > --end')
|
|
94
|
-
if (endArg > stats.size) throw new Error('--end/--len goes past EOF')
|
|
95
34
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
yauzl.RandomAccessReader.call(this)
|
|
99
|
-
}
|
|
100
|
-
util.inherits(MiddleOfFileReader, yauzl.RandomAccessReader)
|
|
101
|
-
// implement required and option methods
|
|
102
|
-
MiddleOfFileReader.prototype._readStreamForRange = function (start, end) {
|
|
103
|
-
return fs.createReadStream(null, {
|
|
104
|
-
fd,
|
|
105
|
-
// shift the start and end offsets
|
|
106
|
-
start: start + offsetArg,
|
|
107
|
-
end: end + offsetArg - 1, // the -1 is because fs.createReadStream()'s end option is inclusive
|
|
108
|
-
autoClose: false
|
|
109
|
-
})
|
|
110
|
-
}
|
|
111
|
-
MiddleOfFileReader.prototype.read = function (buffer, offset, length, position, callback) {
|
|
112
|
-
// shift the position
|
|
113
|
-
fs.read(fd, buffer, offset, length, position + offsetArg, callback)
|
|
114
|
-
}
|
|
115
|
-
MiddleOfFileReader.prototype.close = function (callback) {
|
|
116
|
-
fs.close(fd, callback)
|
|
117
|
-
}
|
|
35
|
+
zipfile.on('error', reject)
|
|
36
|
+
zipfile.on('end', resolve)
|
|
118
37
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
})
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function handleZipFile (err, zipfile) {
|
|
125
|
-
if (err) throw err
|
|
38
|
+
zipfile.on('entry', (entry) => {
|
|
39
|
+
const next = () => zipfile.readEntry()
|
|
126
40
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
133
|
-
function decrementHandleCount () {
|
|
134
|
-
handleCount--
|
|
135
|
-
if (handleCount === 0) {
|
|
136
|
-
console.log('all input and output handles closed')
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
incrementHandleCount()
|
|
141
|
-
zipfile.on('close', function () {
|
|
142
|
-
console.log('closed input file')
|
|
143
|
-
decrementHandleCount()
|
|
144
|
-
})
|
|
41
|
+
if (/\/$/.test(entry.fileName)) {
|
|
42
|
+
fs.promises.mkdir(entry.fileName, { recursive: true })
|
|
43
|
+
.then(next, reject)
|
|
44
|
+
return
|
|
45
|
+
}
|
|
145
46
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
zipfile.readEntry()
|
|
153
|
-
})
|
|
154
|
-
} else {
|
|
155
|
-
// ensure parent directory exists
|
|
156
|
-
mkdirp(path.dirname(entry.fileName), function () {
|
|
157
|
-
zipfile.openReadStream(entry, function (err, readStream) {
|
|
158
|
-
if (err) throw err
|
|
159
|
-
// report progress through large files
|
|
160
|
-
let byteCount = 0
|
|
161
|
-
const totalBytes = entry.uncompressedSize
|
|
162
|
-
let lastReportedString = byteCount + '/' + totalBytes + ' 0%'
|
|
163
|
-
process.stdout.write(entry.fileName + '...' + lastReportedString)
|
|
164
|
-
function reportString (msg) {
|
|
165
|
-
let clearString = ''
|
|
166
|
-
for (let i = 0; i < lastReportedString.length; i++) {
|
|
167
|
-
clearString += '\b'
|
|
168
|
-
if (i >= msg.length) {
|
|
169
|
-
clearString += ' \b'
|
|
47
|
+
fs.promises.mkdir(path.dirname(entry.fileName), { recursive: true })
|
|
48
|
+
.then(() => new Promise((res, rej) => {
|
|
49
|
+
zipfile.openReadStream(entry, (err, readStream) => {
|
|
50
|
+
if (err) {
|
|
51
|
+
rej(err)
|
|
52
|
+
return
|
|
170
53
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
const filter = new Transform()
|
|
180
|
-
filter._transform = function (chunk, encoding, cb) {
|
|
181
|
-
byteCount += chunk.length
|
|
182
|
-
cb(null, chunk)
|
|
183
|
-
}
|
|
184
|
-
filter._flush = function (cb) {
|
|
185
|
-
clearInterval(progressInterval)
|
|
186
|
-
reportString('')
|
|
187
|
-
// delete the "..."
|
|
188
|
-
process.stdout.write('\b \b\b \b\b \b\n')
|
|
189
|
-
cb()
|
|
190
|
-
zipfile.readEntry()
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// pump file contents
|
|
194
|
-
const writeStream = fs.createWriteStream(entry.fileName)
|
|
195
|
-
incrementHandleCount()
|
|
196
|
-
writeStream.on('close', decrementHandleCount)
|
|
197
|
-
readStream.pipe(filter).pipe(writeStream)
|
|
198
|
-
})
|
|
54
|
+
pipeline(readStream, fs.createWriteStream(entry.fileName))
|
|
55
|
+
.then(() => {
|
|
56
|
+
console.log(`${entry.fileName} (${entry.uncompressedSize} bytes)`)
|
|
57
|
+
res()
|
|
58
|
+
}, rej)
|
|
59
|
+
})
|
|
60
|
+
}))
|
|
61
|
+
.then(next, reject)
|
|
199
62
|
})
|
|
200
|
-
|
|
63
|
+
|
|
64
|
+
zipfile.readEntry()
|
|
65
|
+
})
|
|
201
66
|
})
|
|
202
67
|
}
|
|
68
|
+
|
|
69
|
+
extract(zipFilePath).catch((err) => {
|
|
70
|
+
console.error(`unzip failed: ${err.message}`)
|
|
71
|
+
process.exit(1)
|
|
72
|
+
})
|