1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
12 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
13 | return new (P || (P = Promise))(function (resolve, reject) {
|
14 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
15 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
16 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
17 | step((generator = generator.apply(thisArg, _arguments || [])).next());
|
18 | });
|
19 | };
|
20 | Object.defineProperty(exports, "__esModule", { value: true });
|
21 | exports.FileContainerApi = void 0;
|
22 |
|
23 | const stream = require("stream");
|
24 | const zlib = require("zlib");
|
25 | const httpm = require("typed-rest-client/HttpClient");
|
26 | const FileContainerApiBase = require("./FileContainerApiBase");
|
27 | const FileContainerInterfaces = require("./interfaces/FileContainerInterfaces");
|
28 | class FileContainerApi extends FileContainerApiBase.FileContainerApiBase {
|
29 | constructor(baseUrl, handlers, options) {
|
30 | super(baseUrl, handlers, options);
|
31 | }
|
32 | |
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 | getItem(containerId, scope, itemPath, downloadFileName) {
|
39 | return __awaiter(this, void 0, void 0, function* () {
|
40 | return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
41 | let routeValues = {
|
42 | containerId: containerId
|
43 | };
|
44 | let queryValues = {
|
45 | scope: scope,
|
46 | itemPath: itemPath,
|
47 | '$format': "OctetStream",
|
48 | downloadFileName: downloadFileName
|
49 | };
|
50 | try {
|
51 | let verData = yield this.vsoClient.getVersioningData("4.0-preview.4", "Container", "e4f5c81e-e250-447b-9fef-bd48471bea5e", routeValues, queryValues);
|
52 | let url = verData.requestUrl;
|
53 | let options = this.createRequestOptions('application/octet-stream', verData.apiVersion);
|
54 | let res = yield this.http.get(url);
|
55 | let rres = {};
|
56 | let statusCode = res.message.statusCode;
|
57 | rres.statusCode = statusCode;
|
58 |
|
59 | if (statusCode == httpm.HttpCodes.NotFound) {
|
60 | resolve(rres);
|
61 | }
|
62 | if (statusCode > 299) {
|
63 | let msg;
|
64 |
|
65 | let contents = yield res.readBody();
|
66 | let obj;
|
67 | if (contents && contents.length > 0) {
|
68 | obj = JSON.parse(contents);
|
69 | if (options && options.responseProcessor) {
|
70 | rres.result = options.responseProcessor(obj);
|
71 | }
|
72 | else {
|
73 | rres.result = obj;
|
74 | }
|
75 | }
|
76 | if (obj && obj.message) {
|
77 | msg = obj.message;
|
78 | }
|
79 | else {
|
80 | msg = "Failed request: (" + statusCode + ") " + res.message.url;
|
81 | }
|
82 | reject(new Error(msg));
|
83 | }
|
84 | else {
|
85 |
|
86 | if (res.message.headers["content-encoding"] === "gzip") {
|
87 | let unzipStream = zlib.createGunzip();
|
88 | res.message.pipe(unzipStream);
|
89 | rres.result = unzipStream;
|
90 | }
|
91 | else {
|
92 | rres.result = res.message;
|
93 | }
|
94 | resolve(rres);
|
95 | }
|
96 | }
|
97 | catch (err) {
|
98 | reject(err);
|
99 | }
|
100 | }));
|
101 | });
|
102 | }
|
103 | createItem(contentStream, uncompressedLength, containerId, itemPath, scope, options) {
|
104 | return new Promise((resolve, reject) => {
|
105 | let chunkStream = new ChunkStream(this, uncompressedLength, containerId, itemPath, scope, options);
|
106 | chunkStream.on('finish', () => {
|
107 | resolve(chunkStream.getItem());
|
108 | });
|
109 | contentStream.pipe(chunkStream);
|
110 | });
|
111 | }
|
112 |
|
113 | _createItem(customHeaders, contentStream, containerId, itemPath, scope, onResult) {
|
114 | var routeValues = {
|
115 | containerId: containerId
|
116 | };
|
117 | var queryValues = {
|
118 | itemPath: itemPath,
|
119 | scope: scope,
|
120 | };
|
121 | customHeaders = customHeaders || {};
|
122 | customHeaders["Content-Type"] = "";
|
123 | this.vsoClient.getVersioningData("4.0-preview.4", "Container", "e4f5c81e-e250-447b-9fef-bd48471bea5e", routeValues, queryValues)
|
124 | .then((versioningData) => {
|
125 | var url = versioningData.requestUrl;
|
126 | var serializationData = { responseTypeMetadata: FileContainerInterfaces.TypeInfo.FileContainerItem, responseIsCollection: false };
|
127 | let options = this.createRequestOptions('application/octet-stream', versioningData.apiVersion);
|
128 | options.additionalHeaders = customHeaders;
|
129 | this.rest.uploadStream('PUT', url, contentStream, options)
|
130 | .then((res) => {
|
131 | let ret = this.formatResponse(res.result, FileContainerInterfaces.TypeInfo.FileContainerItem, false);
|
132 | onResult(null, res.statusCode, ret);
|
133 | })
|
134 | .catch((err) => {
|
135 | onResult(err, err.statusCode, null);
|
136 | });
|
137 | }, (error) => {
|
138 | onResult(error, error.statusCode, null);
|
139 | });
|
140 | }
|
141 | }
|
142 | exports.FileContainerApi = FileContainerApi;
|
143 | class ChunkStream extends stream.Writable {
|
144 | constructor(api, uncompressedLength, containerId, itemPath, scope, options) {
|
145 | super();
|
146 | this._buffer = new Buffer(ChunkStream.ChunkSize);
|
147 | this._length = 0;
|
148 | this._startRange = 0;
|
149 | this._bytesToSend = 0;
|
150 | this._totalReceived = 0;
|
151 | this._api = api;
|
152 | this._options = options || {};
|
153 | this._uncompressedLength = uncompressedLength;
|
154 | this._containerId = containerId;
|
155 | this._itemPath = itemPath;
|
156 | this._scope = scope;
|
157 | this._bytesToSend = this._options.isGzipped ? this._options.compressedLength : uncompressedLength;
|
158 | }
|
159 | _write(data, encoding, callback) {
|
160 | let chunk = data;
|
161 | if (!chunk) {
|
162 | if (this._length == 0) {
|
163 | callback();
|
164 | }
|
165 | else {
|
166 |
|
167 | this._sendChunk(callback);
|
168 | }
|
169 | return;
|
170 | }
|
171 | let newBuffer = null;
|
172 | if (this._length + chunk.length > ChunkStream.ChunkSize) {
|
173 |
|
174 | let overflowPosition = chunk.length - (ChunkStream.ChunkSize - this._length);
|
175 | chunk.copy(this._buffer, this._length, 0, overflowPosition);
|
176 | this._length += overflowPosition;
|
177 | newBuffer = chunk.slice(overflowPosition);
|
178 | }
|
179 | else {
|
180 | chunk.copy(this._buffer, this._length, 0, chunk.length);
|
181 | this._length += chunk.length;
|
182 | }
|
183 | this._totalReceived += chunk.length;
|
184 | if (this._length >= ChunkStream.ChunkSize || this._totalReceived >= this._bytesToSend) {
|
185 | this._sendChunk(callback, newBuffer);
|
186 | }
|
187 | else {
|
188 | callback();
|
189 | }
|
190 | }
|
191 | _sendChunk(callback, newBuffer) {
|
192 | let endRange = this._startRange + this._length;
|
193 | let headers = {
|
194 | "Content-Range": "bytes " + this._startRange + "-" + (endRange - 1) + "/" + this._bytesToSend,
|
195 | "Content-Length": this._length
|
196 | };
|
197 | if (this._options.isGzipped) {
|
198 | headers["Accept-Encoding"] = "gzip";
|
199 | headers["Content-Encoding"] = "gzip";
|
200 | headers["x-tfs-filelength"] = this._uncompressedLength;
|
201 | }
|
202 | this._startRange = endRange;
|
203 | this._api._createItem(headers, new BufferStream(this._buffer, this._length), this._containerId, this._itemPath, this._scope, (err, statusCode, item) => {
|
204 | if (newBuffer) {
|
205 | this._length = newBuffer.length;
|
206 | newBuffer.copy(this._buffer);
|
207 | }
|
208 | else {
|
209 | this._length = 0;
|
210 | }
|
211 | this._item = item;
|
212 | callback(err);
|
213 | });
|
214 | }
|
215 | getItem() {
|
216 | return this._item;
|
217 | }
|
218 | }
|
219 | ChunkStream.ChunkSize = (16 * 1024 * 1024);
|
220 | class BufferStream extends stream.Readable {
|
221 | constructor(buffer, length) {
|
222 | super();
|
223 | this._position = 0;
|
224 | this._length = 0;
|
225 | this._buffer = buffer;
|
226 | this._length = length;
|
227 | }
|
228 | _read(size) {
|
229 | if (this._position >= this._length) {
|
230 | this.push(null);
|
231 | return;
|
232 | }
|
233 | let end = Math.min(this._position + size, this._length);
|
234 | this.push(this._buffer.slice(this._position, end));
|
235 | this._position = end;
|
236 | }
|
237 | }
|