firebase-admin 9.12.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.
Files changed (84) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +90 -0
  3. package/lib/app-check/app-check-api-client-internal.js +197 -0
  4. package/lib/app-check/app-check.js +79 -0
  5. package/lib/app-check/index.d.ts +160 -0
  6. package/lib/app-check/index.js +19 -0
  7. package/lib/app-check/token-generator.js +161 -0
  8. package/lib/app-check/token-verifier.js +152 -0
  9. package/lib/auth/action-code-settings-builder.js +118 -0
  10. package/lib/auth/auth-api-request.js +1856 -0
  11. package/lib/auth/auth-config.js +636 -0
  12. package/lib/auth/auth.js +836 -0
  13. package/lib/auth/identifier.js +40 -0
  14. package/lib/auth/index.d.ts +1927 -0
  15. package/lib/auth/index.js +18 -0
  16. package/lib/auth/tenant-manager.js +140 -0
  17. package/lib/auth/tenant.js +171 -0
  18. package/lib/auth/token-generator.js +200 -0
  19. package/lib/auth/token-verifier.js +259 -0
  20. package/lib/auth/user-import-builder.js +387 -0
  21. package/lib/auth/user-record.js +346 -0
  22. package/lib/credential/credential-internal.js +391 -0
  23. package/lib/credential/credential.js +44 -0
  24. package/lib/credential/index.d.ts +169 -0
  25. package/lib/credential/index.js +23 -0
  26. package/lib/database/database-internal.js +266 -0
  27. package/lib/database/index.d.ts +89 -0
  28. package/lib/database/index.js +31 -0
  29. package/lib/default-namespace.js +31 -0
  30. package/lib/firebase-app.js +349 -0
  31. package/lib/firebase-namespace-api.d.ts +243 -0
  32. package/lib/firebase-namespace-api.js +18 -0
  33. package/lib/firebase-namespace.d.ts +31 -0
  34. package/lib/firebase-namespace.js +417 -0
  35. package/lib/firestore/firestore-internal.js +105 -0
  36. package/lib/firestore/index.d.ts +50 -0
  37. package/lib/firestore/index.js +47 -0
  38. package/lib/index.d.ts +24 -0
  39. package/lib/index.js +27 -0
  40. package/lib/installations/index.d.ts +81 -0
  41. package/lib/installations/index.js +18 -0
  42. package/lib/installations/installations-request-handler.js +117 -0
  43. package/lib/installations/installations.js +62 -0
  44. package/lib/instance-id/index.d.ts +83 -0
  45. package/lib/instance-id/index.js +18 -0
  46. package/lib/instance-id/instance-id.js +87 -0
  47. package/lib/machine-learning/index.d.ts +249 -0
  48. package/lib/machine-learning/index.js +18 -0
  49. package/lib/machine-learning/machine-learning-api-client.js +304 -0
  50. package/lib/machine-learning/machine-learning-utils.js +62 -0
  51. package/lib/machine-learning/machine-learning.js +364 -0
  52. package/lib/messaging/batch-request-internal.js +129 -0
  53. package/lib/messaging/index.d.ts +1174 -0
  54. package/lib/messaging/index.js +18 -0
  55. package/lib/messaging/messaging-api-request-internal.js +128 -0
  56. package/lib/messaging/messaging-errors-internal.js +106 -0
  57. package/lib/messaging/messaging-internal.js +484 -0
  58. package/lib/messaging/messaging.js +846 -0
  59. package/lib/project-management/android-app.js +176 -0
  60. package/lib/project-management/index.d.ts +363 -0
  61. package/lib/project-management/index.js +41 -0
  62. package/lib/project-management/ios-app.js +88 -0
  63. package/lib/project-management/project-management-api-request-internal.js +273 -0
  64. package/lib/project-management/project-management.js +254 -0
  65. package/lib/remote-config/index.d.ts +369 -0
  66. package/lib/remote-config/index.js +18 -0
  67. package/lib/remote-config/remote-config-api-client-internal.js +407 -0
  68. package/lib/remote-config/remote-config.js +304 -0
  69. package/lib/security-rules/index.d.ts +216 -0
  70. package/lib/security-rules/index.js +18 -0
  71. package/lib/security-rules/security-rules-api-client-internal.js +237 -0
  72. package/lib/security-rules/security-rules-internal.js +41 -0
  73. package/lib/security-rules/security-rules.js +310 -0
  74. package/lib/storage/index.d.ts +60 -0
  75. package/lib/storage/index.js +18 -0
  76. package/lib/storage/storage.js +123 -0
  77. package/lib/utils/api-request.js +845 -0
  78. package/lib/utils/crypto-signer.js +237 -0
  79. package/lib/utils/deep-copy.js +78 -0
  80. package/lib/utils/error.js +1063 -0
  81. package/lib/utils/index.js +217 -0
  82. package/lib/utils/jwt.js +355 -0
  83. package/lib/utils/validator.js +271 -0
  84. package/package.json +122 -0
@@ -0,0 +1,364 @@
1
+ /*! firebase-admin v9.12.0 */
2
+ "use strict";
3
+ /*!
4
+ * Copyright 2020 Google Inc.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.Model = exports.MachineLearning = void 0;
20
+ var machine_learning_api_client_1 = require("./machine-learning-api-client");
21
+ var error_1 = require("../utils/error");
22
+ var validator = require("../utils/validator");
23
+ var machine_learning_utils_1 = require("./machine-learning-utils");
24
+ var deep_copy_1 = require("../utils/deep-copy");
25
+ var utils = require("../utils");
26
+ /**
27
+ * The Firebase Machine Learning class
28
+ */
29
+ var MachineLearning = /** @class */ (function () {
30
+ /**
31
+ * @param {FirebaseApp} app The app for this ML service.
32
+ * @constructor
33
+ */
34
+ function MachineLearning(app) {
35
+ if (!validator.isNonNullObject(app) || !('options' in app)) {
36
+ throw new error_1.FirebaseError({
37
+ code: 'machine-learning/invalid-argument',
38
+ message: 'First argument passed to admin.machineLearning() must be a ' +
39
+ 'valid Firebase app instance.',
40
+ });
41
+ }
42
+ this.appInternal = app;
43
+ this.client = new machine_learning_api_client_1.MachineLearningApiClient(app);
44
+ }
45
+ Object.defineProperty(MachineLearning.prototype, "app", {
46
+ /**
47
+ * Returns the app associated with this ML instance.
48
+ *
49
+ * @return {FirebaseApp} The app associated with this ML instance.
50
+ */
51
+ get: function () {
52
+ return this.appInternal;
53
+ },
54
+ enumerable: false,
55
+ configurable: true
56
+ });
57
+ /**
58
+ * Creates a model in Firebase ML.
59
+ *
60
+ * @param {ModelOptions} model The model to create.
61
+ *
62
+ * @return {Promise<Model>} A Promise fulfilled with the created model.
63
+ */
64
+ MachineLearning.prototype.createModel = function (model) {
65
+ var _this = this;
66
+ return this.signUrlIfPresent(model)
67
+ .then(function (modelContent) { return _this.client.createModel(modelContent); })
68
+ .then(function (operation) { return _this.client.handleOperation(operation); })
69
+ .then(function (modelResponse) { return new Model(modelResponse, _this.client); });
70
+ };
71
+ /**
72
+ * Updates a model in Firebase ML.
73
+ *
74
+ * @param {string} modelId The id of the model to update.
75
+ * @param {ModelOptions} model The model fields to update.
76
+ *
77
+ * @return {Promise<Model>} A Promise fulfilled with the updated model.
78
+ */
79
+ MachineLearning.prototype.updateModel = function (modelId, model) {
80
+ var _this = this;
81
+ var updateMask = utils.generateUpdateMask(model);
82
+ return this.signUrlIfPresent(model)
83
+ .then(function (modelContent) { return _this.client.updateModel(modelId, modelContent, updateMask); })
84
+ .then(function (operation) { return _this.client.handleOperation(operation); })
85
+ .then(function (modelResponse) { return new Model(modelResponse, _this.client); });
86
+ };
87
+ /**
88
+ * Publishes a model in Firebase ML.
89
+ *
90
+ * @param {string} modelId The id of the model to publish.
91
+ *
92
+ * @return {Promise<Model>} A Promise fulfilled with the published model.
93
+ */
94
+ MachineLearning.prototype.publishModel = function (modelId) {
95
+ return this.setPublishStatus(modelId, true);
96
+ };
97
+ /**
98
+ * Unpublishes a model in Firebase ML.
99
+ *
100
+ * @param {string} modelId The id of the model to unpublish.
101
+ *
102
+ * @return {Promise<Model>} A Promise fulfilled with the unpublished model.
103
+ */
104
+ MachineLearning.prototype.unpublishModel = function (modelId) {
105
+ return this.setPublishStatus(modelId, false);
106
+ };
107
+ /**
108
+ * Gets a model from Firebase ML.
109
+ *
110
+ * @param {string} modelId The id of the model to get.
111
+ *
112
+ * @return {Promise<Model>} A Promise fulfilled with the unpublished model.
113
+ */
114
+ MachineLearning.prototype.getModel = function (modelId) {
115
+ var _this = this;
116
+ return this.client.getModel(modelId)
117
+ .then(function (modelResponse) { return new Model(modelResponse, _this.client); });
118
+ };
119
+ /**
120
+ * Lists models from Firebase ML.
121
+ *
122
+ * @param {ListModelsOptions} options The listing options.
123
+ *
124
+ * @return {Promise<{models: Model[], pageToken?: string}>} A promise that
125
+ * resolves with the current (filtered) list of models and the next page
126
+ * token. For the last page, an empty list of models and no page token are
127
+ * returned.
128
+ */
129
+ MachineLearning.prototype.listModels = function (options) {
130
+ var _this = this;
131
+ if (options === void 0) { options = {}; }
132
+ return this.client.listModels(options)
133
+ .then(function (resp) {
134
+ if (!validator.isNonNullObject(resp)) {
135
+ throw new machine_learning_utils_1.FirebaseMachineLearningError('invalid-argument', "Invalid ListModels response: " + JSON.stringify(resp));
136
+ }
137
+ var models = [];
138
+ if (resp.models) {
139
+ models = resp.models.map(function (rs) { return new Model(rs, _this.client); });
140
+ }
141
+ var result = { models: models };
142
+ if (resp.nextPageToken) {
143
+ result.pageToken = resp.nextPageToken;
144
+ }
145
+ return result;
146
+ });
147
+ };
148
+ /**
149
+ * Deletes a model from Firebase ML.
150
+ *
151
+ * @param {string} modelId The id of the model to delete.
152
+ */
153
+ MachineLearning.prototype.deleteModel = function (modelId) {
154
+ return this.client.deleteModel(modelId);
155
+ };
156
+ MachineLearning.prototype.setPublishStatus = function (modelId, publish) {
157
+ var _this = this;
158
+ var updateMask = ['state.published'];
159
+ var options = { state: { published: publish } };
160
+ return this.client.updateModel(modelId, options, updateMask)
161
+ .then(function (operation) { return _this.client.handleOperation(operation); })
162
+ .then(function (modelResponse) { return new Model(modelResponse, _this.client); });
163
+ };
164
+ MachineLearning.prototype.signUrlIfPresent = function (options) {
165
+ var modelOptions = deep_copy_1.deepCopy(options);
166
+ if (machine_learning_api_client_1.isGcsTfliteModelOptions(modelOptions)) {
167
+ return this.signUrl(modelOptions.tfliteModel.gcsTfliteUri)
168
+ .then(function (uri) {
169
+ modelOptions.tfliteModel.gcsTfliteUri = uri;
170
+ return modelOptions;
171
+ })
172
+ .catch(function (err) {
173
+ throw new machine_learning_utils_1.FirebaseMachineLearningError('internal-error', "Error during signing upload url: " + err.message);
174
+ });
175
+ }
176
+ return Promise.resolve(modelOptions);
177
+ };
178
+ MachineLearning.prototype.signUrl = function (unsignedUrl) {
179
+ var MINUTES_IN_MILLIS = 60 * 1000;
180
+ var URL_VALID_DURATION = 10 * MINUTES_IN_MILLIS;
181
+ var gcsRegex = /^gs:\/\/([a-z0-9_.-]{3,63})\/(.+)$/;
182
+ var matches = gcsRegex.exec(unsignedUrl);
183
+ if (!matches) {
184
+ throw new machine_learning_utils_1.FirebaseMachineLearningError('invalid-argument', "Invalid unsigned url: " + unsignedUrl);
185
+ }
186
+ var bucketName = matches[1];
187
+ var blobName = matches[2];
188
+ var bucket = this.appInternal.storage().bucket(bucketName);
189
+ var blob = bucket.file(blobName);
190
+ return blob.getSignedUrl({
191
+ action: 'read',
192
+ expires: Date.now() + URL_VALID_DURATION,
193
+ }).then(function (signUrl) { return signUrl[0]; });
194
+ };
195
+ return MachineLearning;
196
+ }());
197
+ exports.MachineLearning = MachineLearning;
198
+ /**
199
+ * A Firebase ML Model output object.
200
+ */
201
+ var Model = /** @class */ (function () {
202
+ function Model(model, client) {
203
+ this.model = Model.validateAndClone(model);
204
+ this.client = client;
205
+ }
206
+ Object.defineProperty(Model.prototype, "modelId", {
207
+ get: function () {
208
+ return extractModelId(this.model.name);
209
+ },
210
+ enumerable: false,
211
+ configurable: true
212
+ });
213
+ Object.defineProperty(Model.prototype, "displayName", {
214
+ get: function () {
215
+ return this.model.displayName;
216
+ },
217
+ enumerable: false,
218
+ configurable: true
219
+ });
220
+ Object.defineProperty(Model.prototype, "tags", {
221
+ get: function () {
222
+ return this.model.tags || [];
223
+ },
224
+ enumerable: false,
225
+ configurable: true
226
+ });
227
+ Object.defineProperty(Model.prototype, "createTime", {
228
+ get: function () {
229
+ return new Date(this.model.createTime).toUTCString();
230
+ },
231
+ enumerable: false,
232
+ configurable: true
233
+ });
234
+ Object.defineProperty(Model.prototype, "updateTime", {
235
+ get: function () {
236
+ return new Date(this.model.updateTime).toUTCString();
237
+ },
238
+ enumerable: false,
239
+ configurable: true
240
+ });
241
+ Object.defineProperty(Model.prototype, "validationError", {
242
+ get: function () {
243
+ var _a, _b;
244
+ return (_b = (_a = this.model.state) === null || _a === void 0 ? void 0 : _a.validationError) === null || _b === void 0 ? void 0 : _b.message;
245
+ },
246
+ enumerable: false,
247
+ configurable: true
248
+ });
249
+ Object.defineProperty(Model.prototype, "published", {
250
+ get: function () {
251
+ var _a;
252
+ return ((_a = this.model.state) === null || _a === void 0 ? void 0 : _a.published) || false;
253
+ },
254
+ enumerable: false,
255
+ configurable: true
256
+ });
257
+ Object.defineProperty(Model.prototype, "etag", {
258
+ get: function () {
259
+ return this.model.etag;
260
+ },
261
+ enumerable: false,
262
+ configurable: true
263
+ });
264
+ Object.defineProperty(Model.prototype, "modelHash", {
265
+ get: function () {
266
+ return this.model.modelHash;
267
+ },
268
+ enumerable: false,
269
+ configurable: true
270
+ });
271
+ Object.defineProperty(Model.prototype, "tfliteModel", {
272
+ get: function () {
273
+ // Make a copy so people can't directly modify the private this.model object.
274
+ return deep_copy_1.deepCopy(this.model.tfliteModel);
275
+ },
276
+ enumerable: false,
277
+ configurable: true
278
+ });
279
+ Object.defineProperty(Model.prototype, "locked", {
280
+ /**
281
+ * Locked indicates if there are active long running operations on the model.
282
+ * Models may not be modified when they are locked.
283
+ */
284
+ get: function () {
285
+ var _a, _b;
286
+ return ((_b = (_a = this.model.activeOperations) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0;
287
+ },
288
+ enumerable: false,
289
+ configurable: true
290
+ });
291
+ Model.prototype.toJSON = function () {
292
+ // We can't just return this.model because it has extra fields and
293
+ // different formats etc. So we build the expected model object.
294
+ var jsonModel = {
295
+ modelId: this.modelId,
296
+ displayName: this.displayName,
297
+ tags: this.tags,
298
+ createTime: this.createTime,
299
+ updateTime: this.updateTime,
300
+ published: this.published,
301
+ etag: this.etag,
302
+ locked: this.locked,
303
+ };
304
+ // Also add possibly undefined fields if they exist.
305
+ if (this.validationError) {
306
+ jsonModel['validationError'] = this.validationError;
307
+ }
308
+ if (this.modelHash) {
309
+ jsonModel['modelHash'] = this.modelHash;
310
+ }
311
+ if (this.tfliteModel) {
312
+ jsonModel['tfliteModel'] = this.tfliteModel;
313
+ }
314
+ return jsonModel;
315
+ };
316
+ /**
317
+ * Wait for the active operations on the model to complete.
318
+ * @param maxTimeMillis The number of milliseconds to wait for the model to be unlocked. If unspecified,
319
+ * a default will be used.
320
+ */
321
+ Model.prototype.waitForUnlocked = function (maxTimeMillis) {
322
+ var _this = this;
323
+ var _a, _b;
324
+ if (((_b = (_a = this.model.activeOperations) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0) {
325
+ // The client will always be defined on Models that have activeOperations
326
+ // because models with active operations came back from the server and
327
+ // were constructed with a non-empty client.
328
+ return this.client.handleOperation(this.model.activeOperations[0], { wait: true, maxTimeMillis: maxTimeMillis })
329
+ .then(function (modelResponse) {
330
+ _this.model = Model.validateAndClone(modelResponse);
331
+ });
332
+ }
333
+ return Promise.resolve();
334
+ };
335
+ Model.validateAndClone = function (model) {
336
+ if (!validator.isNonNullObject(model) ||
337
+ !validator.isNonEmptyString(model.name) ||
338
+ !validator.isNonEmptyString(model.createTime) ||
339
+ !validator.isNonEmptyString(model.updateTime) ||
340
+ !validator.isNonEmptyString(model.displayName) ||
341
+ !validator.isNonEmptyString(model.etag)) {
342
+ throw new machine_learning_utils_1.FirebaseMachineLearningError('invalid-server-response', "Invalid Model response: " + JSON.stringify(model));
343
+ }
344
+ var tmpModel = deep_copy_1.deepCopy(model);
345
+ // If tflite Model is specified, it must have a source consisting of
346
+ // oneof {gcsTfliteUri, automlModel}
347
+ if (model.tfliteModel &&
348
+ !validator.isNonEmptyString(model.tfliteModel.gcsTfliteUri) &&
349
+ !validator.isNonEmptyString(model.tfliteModel.automlModel)) {
350
+ // If we have some other source, ignore the whole tfliteModel.
351
+ delete tmpModel.tfliteModel;
352
+ }
353
+ // Remove '@type' field. We don't need it.
354
+ if (tmpModel['@type']) {
355
+ delete tmpModel['@type'];
356
+ }
357
+ return tmpModel;
358
+ };
359
+ return Model;
360
+ }());
361
+ exports.Model = Model;
362
+ function extractModelId(resourceName) {
363
+ return resourceName.split('/').pop();
364
+ }
@@ -0,0 +1,129 @@
1
+ /*! firebase-admin v9.12.0 */
2
+ "use strict";
3
+ /*!
4
+ * Copyright 2019 Google Inc.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.BatchRequestClient = void 0;
20
+ var api_request_1 = require("../utils/api-request");
21
+ var error_1 = require("../utils/error");
22
+ var PART_BOUNDARY = '__END_OF_PART__';
23
+ var TEN_SECONDS_IN_MILLIS = 10000;
24
+ /**
25
+ * An HTTP client that can be used to make batch requests. This client is not tied to any service
26
+ * (FCM or otherwise). Therefore it can be used to make batch requests to any service that allows
27
+ * it. If this requirement ever arises we can move this implementation to the utils module
28
+ * where it can be easily shared among other modules.
29
+ */
30
+ var BatchRequestClient = /** @class */ (function () {
31
+ /**
32
+ * @param {HttpClient} httpClient The client that will be used to make HTTP calls.
33
+ * @param {string} batchUrl The URL that accepts batch requests.
34
+ * @param {object=} commonHeaders Optional headers that will be included in all requests.
35
+ *
36
+ * @constructor
37
+ */
38
+ function BatchRequestClient(httpClient, batchUrl, commonHeaders) {
39
+ this.httpClient = httpClient;
40
+ this.batchUrl = batchUrl;
41
+ this.commonHeaders = commonHeaders;
42
+ }
43
+ /**
44
+ * Sends the given array of sub requests as a single batch, and parses the results into an array
45
+ * of HttpResponse objects.
46
+ *
47
+ * @param {SubRequest[]} requests An array of sub requests to send.
48
+ * @return {Promise<HttpResponse[]>} A promise that resolves when the send operation is complete.
49
+ */
50
+ BatchRequestClient.prototype.send = function (requests) {
51
+ var _this = this;
52
+ requests = requests.map(function (req) {
53
+ req.headers = Object.assign({}, _this.commonHeaders, req.headers);
54
+ return req;
55
+ });
56
+ var requestHeaders = {
57
+ 'Content-Type': "multipart/mixed; boundary=" + PART_BOUNDARY,
58
+ };
59
+ var request = {
60
+ method: 'POST',
61
+ url: this.batchUrl,
62
+ data: this.getMultipartPayload(requests),
63
+ headers: Object.assign({}, this.commonHeaders, requestHeaders),
64
+ timeout: TEN_SECONDS_IN_MILLIS,
65
+ };
66
+ return this.httpClient.send(request).then(function (response) {
67
+ if (!response.multipart) {
68
+ throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INTERNAL_ERROR, 'Expected a multipart response.');
69
+ }
70
+ return response.multipart.map(function (buff) {
71
+ return api_request_1.parseHttpResponse(buff, request);
72
+ });
73
+ });
74
+ };
75
+ BatchRequestClient.prototype.getMultipartPayload = function (requests) {
76
+ var buffer = '';
77
+ requests.forEach(function (request, idx) {
78
+ buffer += createPart(request, PART_BOUNDARY, idx);
79
+ });
80
+ buffer += "--" + PART_BOUNDARY + "--\r\n";
81
+ return Buffer.from(buffer, 'utf-8');
82
+ };
83
+ return BatchRequestClient;
84
+ }());
85
+ exports.BatchRequestClient = BatchRequestClient;
86
+ /**
87
+ * Creates a single part in a multipart HTTP request body. The part consists of several headers
88
+ * followed by the serialized sub request as the body. As per the requirements of the FCM batch
89
+ * API, sets the content-type header to application/http, and the content-transfer-encoding to
90
+ * binary.
91
+ *
92
+ * @param {SubRequest} request A sub request that will be used to populate the part.
93
+ * @param {string} boundary Multipart boundary string.
94
+ * @param {number} idx An index number that is used to set the content-id header.
95
+ * @return {string} The part as a string that can be included in the HTTP body.
96
+ */
97
+ function createPart(request, boundary, idx) {
98
+ var serializedRequest = serializeSubRequest(request);
99
+ var part = "--" + boundary + "\r\n";
100
+ part += "Content-Length: " + serializedRequest.length + "\r\n";
101
+ part += 'Content-Type: application/http\r\n';
102
+ part += "content-id: " + (idx + 1) + "\r\n";
103
+ part += 'content-transfer-encoding: binary\r\n';
104
+ part += '\r\n';
105
+ part += serializedRequest + "\r\n";
106
+ return part;
107
+ }
108
+ /**
109
+ * Serializes a sub request into a string that can be embedded in a multipart HTTP request. The
110
+ * format of the string is the wire format of a typical HTTP request, consisting of a header and a
111
+ * body.
112
+ *
113
+ * @param request {SubRequest} The sub request to be serialized.
114
+ * @return {string} String representation of the SubRequest.
115
+ */
116
+ function serializeSubRequest(request) {
117
+ var requestBody = JSON.stringify(request.body);
118
+ var messagePayload = "POST " + request.url + " HTTP/1.1\r\n";
119
+ messagePayload += "Content-Length: " + requestBody.length + "\r\n";
120
+ messagePayload += 'Content-Type: application/json; charset=UTF-8\r\n';
121
+ if (request.headers) {
122
+ Object.keys(request.headers).forEach(function (key) {
123
+ messagePayload += key + ": " + request.headers[key] + "\r\n";
124
+ });
125
+ }
126
+ messagePayload += '\r\n';
127
+ messagePayload += requestBody;
128
+ return messagePayload;
129
+ }