index.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. exports.WriteStreamSync = exports.WriteStream = exports.ReadStreamSync = exports.ReadStream = void 0;
  7. const events_1 = __importDefault(require("events"));
  8. const fs_1 = __importDefault(require("fs"));
  9. const minipass_1 = require("minipass");
  10. const writev = fs_1.default.writev;
  11. const _autoClose = Symbol('_autoClose');
  12. const _close = Symbol('_close');
  13. const _ended = Symbol('_ended');
  14. const _fd = Symbol('_fd');
  15. const _finished = Symbol('_finished');
  16. const _flags = Symbol('_flags');
  17. const _flush = Symbol('_flush');
  18. const _handleChunk = Symbol('_handleChunk');
  19. const _makeBuf = Symbol('_makeBuf');
  20. const _mode = Symbol('_mode');
  21. const _needDrain = Symbol('_needDrain');
  22. const _onerror = Symbol('_onerror');
  23. const _onopen = Symbol('_onopen');
  24. const _onread = Symbol('_onread');
  25. const _onwrite = Symbol('_onwrite');
  26. const _open = Symbol('_open');
  27. const _path = Symbol('_path');
  28. const _pos = Symbol('_pos');
  29. const _queue = Symbol('_queue');
  30. const _read = Symbol('_read');
  31. const _readSize = Symbol('_readSize');
  32. const _reading = Symbol('_reading');
  33. const _remain = Symbol('_remain');
  34. const _size = Symbol('_size');
  35. const _write = Symbol('_write');
  36. const _writing = Symbol('_writing');
  37. const _defaultFlag = Symbol('_defaultFlag');
  38. const _errored = Symbol('_errored');
  39. class ReadStream extends minipass_1.Minipass {
  40. [_errored] = false;
  41. [_fd];
  42. [_path];
  43. [_readSize];
  44. [_reading] = false;
  45. [_size];
  46. [_remain];
  47. [_autoClose];
  48. constructor(path, opt) {
  49. opt = opt || {};
  50. super(opt);
  51. this.readable = true;
  52. this.writable = false;
  53. if (typeof path !== 'string') {
  54. throw new TypeError('path must be a string');
  55. }
  56. this[_errored] = false;
  57. this[_fd] = typeof opt.fd === 'number' ? opt.fd : undefined;
  58. this[_path] = path;
  59. this[_readSize] = opt.readSize || 16 * 1024 * 1024;
  60. this[_reading] = false;
  61. this[_size] = typeof opt.size === 'number' ? opt.size : Infinity;
  62. this[_remain] = this[_size];
  63. this[_autoClose] =
  64. typeof opt.autoClose === 'boolean' ? opt.autoClose : true;
  65. if (typeof this[_fd] === 'number') {
  66. this[_read]();
  67. }
  68. else {
  69. this[_open]();
  70. }
  71. }
  72. get fd() {
  73. return this[_fd];
  74. }
  75. get path() {
  76. return this[_path];
  77. }
  78. //@ts-ignore
  79. write() {
  80. throw new TypeError('this is a readable stream');
  81. }
  82. //@ts-ignore
  83. end() {
  84. throw new TypeError('this is a readable stream');
  85. }
  86. [_open]() {
  87. fs_1.default.open(this[_path], 'r', (er, fd) => this[_onopen](er, fd));
  88. }
  89. [_onopen](er, fd) {
  90. if (er) {
  91. this[_onerror](er);
  92. }
  93. else {
  94. this[_fd] = fd;
  95. this.emit('open', fd);
  96. this[_read]();
  97. }
  98. }
  99. [_makeBuf]() {
  100. return Buffer.allocUnsafe(Math.min(this[_readSize], this[_remain]));
  101. }
  102. [_read]() {
  103. if (!this[_reading]) {
  104. this[_reading] = true;
  105. const buf = this[_makeBuf]();
  106. /* c8 ignore start */
  107. if (buf.length === 0) {
  108. return process.nextTick(() => this[_onread](null, 0, buf));
  109. }
  110. /* c8 ignore stop */
  111. fs_1.default.read(this[_fd], buf, 0, buf.length, null, (er, br, b) => this[_onread](er, br, b));
  112. }
  113. }
  114. [_onread](er, br, buf) {
  115. this[_reading] = false;
  116. if (er) {
  117. this[_onerror](er);
  118. }
  119. else if (this[_handleChunk](br, buf)) {
  120. this[_read]();
  121. }
  122. }
  123. [_close]() {
  124. if (this[_autoClose] && typeof this[_fd] === 'number') {
  125. const fd = this[_fd];
  126. this[_fd] = undefined;
  127. fs_1.default.close(fd, er => er ? this.emit('error', er) : this.emit('close'));
  128. }
  129. }
  130. [_onerror](er) {
  131. this[_reading] = true;
  132. this[_close]();
  133. this.emit('error', er);
  134. }
  135. [_handleChunk](br, buf) {
  136. let ret = false;
  137. // no effect if infinite
  138. this[_remain] -= br;
  139. if (br > 0) {
  140. ret = super.write(br < buf.length ? buf.subarray(0, br) : buf);
  141. }
  142. if (br === 0 || this[_remain] <= 0) {
  143. ret = false;
  144. this[_close]();
  145. super.end();
  146. }
  147. return ret;
  148. }
  149. emit(ev, ...args) {
  150. switch (ev) {
  151. case 'prefinish':
  152. case 'finish':
  153. return false;
  154. case 'drain':
  155. if (typeof this[_fd] === 'number') {
  156. this[_read]();
  157. }
  158. return false;
  159. case 'error':
  160. if (this[_errored]) {
  161. return false;
  162. }
  163. this[_errored] = true;
  164. return super.emit(ev, ...args);
  165. default:
  166. return super.emit(ev, ...args);
  167. }
  168. }
  169. }
  170. exports.ReadStream = ReadStream;
  171. class ReadStreamSync extends ReadStream {
  172. [_open]() {
  173. let threw = true;
  174. try {
  175. this[_onopen](null, fs_1.default.openSync(this[_path], 'r'));
  176. threw = false;
  177. }
  178. finally {
  179. if (threw) {
  180. this[_close]();
  181. }
  182. }
  183. }
  184. [_read]() {
  185. let threw = true;
  186. try {
  187. if (!this[_reading]) {
  188. this[_reading] = true;
  189. do {
  190. const buf = this[_makeBuf]();
  191. /* c8 ignore start */
  192. const br = buf.length === 0
  193. ? 0
  194. : fs_1.default.readSync(this[_fd], buf, 0, buf.length, null);
  195. /* c8 ignore stop */
  196. if (!this[_handleChunk](br, buf)) {
  197. break;
  198. }
  199. } while (true);
  200. this[_reading] = false;
  201. }
  202. threw = false;
  203. }
  204. finally {
  205. if (threw) {
  206. this[_close]();
  207. }
  208. }
  209. }
  210. [_close]() {
  211. if (this[_autoClose] && typeof this[_fd] === 'number') {
  212. const fd = this[_fd];
  213. this[_fd] = undefined;
  214. fs_1.default.closeSync(fd);
  215. this.emit('close');
  216. }
  217. }
  218. }
  219. exports.ReadStreamSync = ReadStreamSync;
  220. class WriteStream extends events_1.default {
  221. readable = false;
  222. writable = true;
  223. [_errored] = false;
  224. [_writing] = false;
  225. [_ended] = false;
  226. [_queue] = [];
  227. [_needDrain] = false;
  228. [_path];
  229. [_mode];
  230. [_autoClose];
  231. [_fd];
  232. [_defaultFlag];
  233. [_flags];
  234. [_finished] = false;
  235. [_pos];
  236. constructor(path, opt) {
  237. opt = opt || {};
  238. super(opt);
  239. this[_path] = path;
  240. this[_fd] = typeof opt.fd === 'number' ? opt.fd : undefined;
  241. this[_mode] = opt.mode === undefined ? 0o666 : opt.mode;
  242. this[_pos] = typeof opt.start === 'number' ? opt.start : undefined;
  243. this[_autoClose] =
  244. typeof opt.autoClose === 'boolean' ? opt.autoClose : true;
  245. // truncating makes no sense when writing into the middle
  246. const defaultFlag = this[_pos] !== undefined ? 'r+' : 'w';
  247. this[_defaultFlag] = opt.flags === undefined;
  248. this[_flags] = opt.flags === undefined ? defaultFlag : opt.flags;
  249. if (this[_fd] === undefined) {
  250. this[_open]();
  251. }
  252. }
  253. emit(ev, ...args) {
  254. if (ev === 'error') {
  255. if (this[_errored]) {
  256. return false;
  257. }
  258. this[_errored] = true;
  259. }
  260. return super.emit(ev, ...args);
  261. }
  262. get fd() {
  263. return this[_fd];
  264. }
  265. get path() {
  266. return this[_path];
  267. }
  268. [_onerror](er) {
  269. this[_close]();
  270. this[_writing] = true;
  271. this.emit('error', er);
  272. }
  273. [_open]() {
  274. fs_1.default.open(this[_path], this[_flags], this[_mode], (er, fd) => this[_onopen](er, fd));
  275. }
  276. [_onopen](er, fd) {
  277. if (this[_defaultFlag] &&
  278. this[_flags] === 'r+' &&
  279. er &&
  280. er.code === 'ENOENT') {
  281. this[_flags] = 'w';
  282. this[_open]();
  283. }
  284. else if (er) {
  285. this[_onerror](er);
  286. }
  287. else {
  288. this[_fd] = fd;
  289. this.emit('open', fd);
  290. if (!this[_writing]) {
  291. this[_flush]();
  292. }
  293. }
  294. }
  295. end(buf, enc) {
  296. if (buf) {
  297. //@ts-ignore
  298. this.write(buf, enc);
  299. }
  300. this[_ended] = true;
  301. // synthetic after-write logic, where drain/finish live
  302. if (!this[_writing] &&
  303. !this[_queue].length &&
  304. typeof this[_fd] === 'number') {
  305. this[_onwrite](null, 0);
  306. }
  307. return this;
  308. }
  309. write(buf, enc) {
  310. if (typeof buf === 'string') {
  311. buf = Buffer.from(buf, enc);
  312. }
  313. if (this[_ended]) {
  314. this.emit('error', new Error('write() after end()'));
  315. return false;
  316. }
  317. if (this[_fd] === undefined || this[_writing] || this[_queue].length) {
  318. this[_queue].push(buf);
  319. this[_needDrain] = true;
  320. return false;
  321. }
  322. this[_writing] = true;
  323. this[_write](buf);
  324. return true;
  325. }
  326. [_write](buf) {
  327. fs_1.default.write(this[_fd], buf, 0, buf.length, this[_pos], (er, bw) => this[_onwrite](er, bw));
  328. }
  329. [_onwrite](er, bw) {
  330. if (er) {
  331. this[_onerror](er);
  332. }
  333. else {
  334. if (this[_pos] !== undefined && typeof bw === 'number') {
  335. this[_pos] += bw;
  336. }
  337. if (this[_queue].length) {
  338. this[_flush]();
  339. }
  340. else {
  341. this[_writing] = false;
  342. if (this[_ended] && !this[_finished]) {
  343. this[_finished] = true;
  344. this[_close]();
  345. this.emit('finish');
  346. }
  347. else if (this[_needDrain]) {
  348. this[_needDrain] = false;
  349. this.emit('drain');
  350. }
  351. }
  352. }
  353. }
  354. [_flush]() {
  355. if (this[_queue].length === 0) {
  356. if (this[_ended]) {
  357. this[_onwrite](null, 0);
  358. }
  359. }
  360. else if (this[_queue].length === 1) {
  361. this[_write](this[_queue].pop());
  362. }
  363. else {
  364. const iovec = this[_queue];
  365. this[_queue] = [];
  366. writev(this[_fd], iovec, this[_pos], (er, bw) => this[_onwrite](er, bw));
  367. }
  368. }
  369. [_close]() {
  370. if (this[_autoClose] && typeof this[_fd] === 'number') {
  371. const fd = this[_fd];
  372. this[_fd] = undefined;
  373. fs_1.default.close(fd, er => er ? this.emit('error', er) : this.emit('close'));
  374. }
  375. }
  376. }
  377. exports.WriteStream = WriteStream;
  378. class WriteStreamSync extends WriteStream {
  379. [_open]() {
  380. let fd;
  381. // only wrap in a try{} block if we know we'll retry, to avoid
  382. // the rethrow obscuring the error's source frame in most cases.
  383. if (this[_defaultFlag] && this[_flags] === 'r+') {
  384. try {
  385. fd = fs_1.default.openSync(this[_path], this[_flags], this[_mode]);
  386. }
  387. catch (er) {
  388. if (er?.code === 'ENOENT') {
  389. this[_flags] = 'w';
  390. return this[_open]();
  391. }
  392. else {
  393. throw er;
  394. }
  395. }
  396. }
  397. else {
  398. fd = fs_1.default.openSync(this[_path], this[_flags], this[_mode]);
  399. }
  400. this[_onopen](null, fd);
  401. }
  402. [_close]() {
  403. if (this[_autoClose] && typeof this[_fd] === 'number') {
  404. const fd = this[_fd];
  405. this[_fd] = undefined;
  406. fs_1.default.closeSync(fd);
  407. this.emit('close');
  408. }
  409. }
  410. [_write](buf) {
  411. // throw the original, but try to close if it fails
  412. let threw = true;
  413. try {
  414. this[_onwrite](null, fs_1.default.writeSync(this[_fd], buf, 0, buf.length, this[_pos]));
  415. threw = false;
  416. }
  417. finally {
  418. if (threw) {
  419. try {
  420. this[_close]();
  421. }
  422. catch {
  423. // ok error
  424. }
  425. }
  426. }
  427. }
  428. }
  429. exports.WriteStreamSync = WriteStreamSync;
  430. //# sourceMappingURL=index.js.map