CoreFileSystemWritableFileStream.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.CoreFileSystemWritableFileStream = void 0;
  4. const buffer_1 = require("@jsonjoy.com/fs-node-builtins/lib/internal/buffer");
  5. const util_1 = require("./util");
  6. const fs_node_utils_1 = require("@jsonjoy.com/fs-node-utils");
  7. const WS = (typeof WritableStream === 'undefined' ? require('stream/web').WritableStream : WritableStream);
  8. /**
  9. * @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemWritableFileStream
  10. */
  11. class CoreFileSystemWritableFileStream extends WS {
  12. constructor(core, path, keepExistingData = false, ctx) {
  13. let fd;
  14. super({
  15. start: controller => {
  16. if (ctx.locks.isLocked(path)) {
  17. throw (0, util_1.newNoModificationAllowedError)();
  18. }
  19. ctx.locks.acquireLock(path);
  20. const flags = keepExistingData ? fs_node_utils_1.FLAGS['r+'] : fs_node_utils_1.FLAGS.w;
  21. try {
  22. fd = core.open(path, flags, 438 /* MODE.FILE */);
  23. }
  24. catch (error) {
  25. ctx.locks.releaseLock(path);
  26. if (error && typeof error === 'object' && error.code === "EACCES" /* ERROR_CODE.EACCES */) {
  27. throw (0, util_1.newNotAllowedError)();
  28. }
  29. throw error;
  30. }
  31. },
  32. write: async (chunk) => {
  33. await this._write(chunk);
  34. },
  35. close: async () => {
  36. if (!this._closed && this._fd !== undefined) {
  37. core.close(this._fd);
  38. this._closed = true;
  39. ctx.locks.releaseLock(path);
  40. }
  41. },
  42. abort: async () => {
  43. if (!this._closed && this._fd !== undefined) {
  44. core.close(this._fd);
  45. this._closed = true;
  46. ctx.locks.releaseLock(path);
  47. }
  48. },
  49. });
  50. this._position = 0;
  51. this._closed = false;
  52. this._core = core;
  53. this._path = path;
  54. this._fd = fd;
  55. this._ctx = ctx;
  56. }
  57. /**
  58. * @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemWritableFileStream/seek
  59. */
  60. async seek(position) {
  61. if (this._closed) {
  62. throw new DOMException('The stream is closed.', 'InvalidStateError');
  63. }
  64. this._position = position;
  65. }
  66. /**
  67. * @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemWritableFileStream/truncate
  68. */
  69. async truncate(size) {
  70. if (this._closed) {
  71. throw new DOMException('The stream is closed.', 'InvalidStateError');
  72. }
  73. try {
  74. const link = this._core.getResolvedLinkOrThrow(this._path);
  75. const node = link.getNode();
  76. node.truncate(size);
  77. }
  78. catch (error) {
  79. if (error && typeof error === 'object' && error.code === "EACCES" /* ERROR_CODE.EACCES */) {
  80. throw (0, util_1.newNotAllowedError)();
  81. }
  82. throw error;
  83. }
  84. }
  85. async write(chunkOrParams) {
  86. await this._write(chunkOrParams);
  87. }
  88. async _write(chunkOrParams) {
  89. if (this._closed) {
  90. throw new DOMException('The stream is closed.', 'InvalidStateError');
  91. }
  92. if (this._fd === undefined) {
  93. throw new DOMException('The stream is not ready.', 'InvalidStateError');
  94. }
  95. try {
  96. if (this._isParams(chunkOrParams)) {
  97. const params = chunkOrParams;
  98. switch (params.type) {
  99. case 'write': {
  100. if (params.data !== undefined) {
  101. const buffer = this._dataToBuffer(params.data);
  102. const position = params.position !== undefined ? params.position : this._position;
  103. const written = this._core.write(this._fd, buffer, 0, buffer.length, position);
  104. if (params.position === undefined) {
  105. this._position += written;
  106. }
  107. }
  108. break;
  109. }
  110. case 'seek': {
  111. if (params.position !== undefined) {
  112. this._position = params.position;
  113. }
  114. break;
  115. }
  116. case 'truncate': {
  117. if (params.size !== undefined) {
  118. await this.truncate(params.size);
  119. }
  120. break;
  121. }
  122. }
  123. }
  124. else {
  125. // Direct data write
  126. const buffer = this._dataToBuffer(chunkOrParams);
  127. const written = this._core.write(this._fd, buffer, 0, buffer.length, this._position);
  128. this._position += written;
  129. }
  130. }
  131. catch (error) {
  132. if (error && typeof error === 'object' && error.code === "EACCES" /* ERROR_CODE.EACCES */) {
  133. throw (0, util_1.newNotAllowedError)();
  134. }
  135. throw error;
  136. }
  137. }
  138. _isParams(chunk) {
  139. return !!(chunk && typeof chunk === 'object' && 'type' in chunk);
  140. }
  141. _dataToBuffer(data) {
  142. if (typeof data === 'string') {
  143. return buffer_1.Buffer.from(data, 'utf8');
  144. }
  145. if (data instanceof buffer_1.Buffer) {
  146. return data;
  147. }
  148. if (data instanceof ArrayBuffer) {
  149. return buffer_1.Buffer.from(data);
  150. }
  151. if (ArrayBuffer.isView(data)) {
  152. return buffer_1.Buffer.from(data.buffer, data.byteOffset, data.byteLength);
  153. }
  154. if (data instanceof Blob) {
  155. // For Blob, we would need to read it asynchronously
  156. // This is a simplified implementation
  157. throw new Error('Blob data type not fully supported in this implementation');
  158. }
  159. throw new Error('Unsupported data type');
  160. }
  161. }
  162. exports.CoreFileSystemWritableFileStream = CoreFileSystemWritableFileStream;
  163. //# sourceMappingURL=CoreFileSystemWritableFileStream.js.map