firebase-tools 11.16.0 → 11.16.1

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.
@@ -160,6 +160,9 @@ function toBackend(build, paramValues) {
160
160
  const bkEndpoints = [];
161
161
  for (const endpointId of Object.keys(build.endpoints)) {
162
162
  const bdEndpoint = build.endpoints[endpointId];
163
+ if (r.resolveBoolean(bdEndpoint.omit || false)) {
164
+ continue;
165
+ }
163
166
  let regions = bdEndpoint.region;
164
167
  if (typeof regions === "undefined") {
165
168
  regions = [api.functionsDefaultRegion];
@@ -167,9 +167,9 @@ class Fabricator {
167
167
  if (apiFunction.httpsTrigger) {
168
168
  apiFunction.httpsTrigger.securityLevel = "SECURE_ALWAYS";
169
169
  }
170
- apiFunction.sourceToken = await scraper.tokenPromise();
171
170
  const resultFunction = await this.functionExecutor
172
171
  .run(async () => {
172
+ apiFunction.sourceToken = await scraper.getToken();
173
173
  const op = await gcf.createFunction(apiFunction);
174
174
  return poller.pollOperation(Object.assign(Object.assign({}, gcfV1PollerOptions), { pollerName: `create-${endpoint.codebase}-${endpoint.region}-${endpoint.id}`, operationResourceName: op.name, onPoll: scraper.poller }));
175
175
  })
@@ -301,9 +301,9 @@ class Fabricator {
301
301
  throw new Error("Precondition failed");
302
302
  }
303
303
  const apiFunction = gcf.functionFromEndpoint(endpoint, sourceUrl);
304
- apiFunction.sourceToken = await scraper.tokenPromise();
305
304
  const resultFunction = await this.functionExecutor
306
305
  .run(async () => {
306
+ apiFunction.sourceToken = await scraper.getToken();
307
307
  const op = await gcf.updateFunction(apiFunction);
308
308
  return await poller.pollOperation(Object.assign(Object.assign({}, gcfV1PollerOptions), { pollerName: `update-${endpoint.codebase}-${endpoint.region}-${endpoint.id}`, operationResourceName: op.name, onPoll: scraper.poller }));
309
309
  })
@@ -1,18 +1,43 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SourceTokenScraper = void 0;
4
+ const error_1 = require("../../../error");
5
+ const functional_1 = require("../../../functional");
4
6
  const logger_1 = require("../../../logger");
5
7
  class SourceTokenScraper {
6
- constructor() {
7
- this.firstCall = true;
8
+ constructor(validDurationMs = 1500000) {
9
+ this.tokenValidDurationMs = validDurationMs;
8
10
  this.promise = new Promise((resolve) => (this.resolve = resolve));
11
+ this.fetchState = "NONE";
9
12
  }
10
- tokenPromise() {
11
- if (this.firstCall) {
12
- this.firstCall = false;
13
- return Promise.resolve(undefined);
13
+ async getToken() {
14
+ if (this.fetchState === "NONE") {
15
+ this.fetchState = "FETCHING";
16
+ return undefined;
14
17
  }
15
- return this.promise;
18
+ else if (this.fetchState === "FETCHING") {
19
+ return this.promise;
20
+ }
21
+ else if (this.fetchState === "VALID") {
22
+ if (this.isTokenExpired()) {
23
+ this.fetchState = "FETCHING";
24
+ this.promise = new Promise((resolve) => (this.resolve = resolve));
25
+ return undefined;
26
+ }
27
+ return this.promise;
28
+ }
29
+ else {
30
+ (0, functional_1.assertExhaustive)(this.fetchState);
31
+ }
32
+ }
33
+ isTokenExpired() {
34
+ if (this.expiry === undefined) {
35
+ throw new error_1.FirebaseError("Your deployment is checking the expiration of a source token that has not yet been polled. " +
36
+ "Hitting this case should never happen and should be considered a bug. " +
37
+ "Please file an issue at https://github.com/firebase/firebase-tools/issues " +
38
+ "and try deploying your functions again.");
39
+ }
40
+ return Date.now() >= this.expiry;
16
41
  }
17
42
  get poller() {
18
43
  return (op) => {
@@ -21,6 +46,8 @@ class SourceTokenScraper {
21
46
  const [, , , region] = ((_c = (_b = op.metadata) === null || _b === void 0 ? void 0 : _b.target) === null || _c === void 0 ? void 0 : _c.split("/")) || [];
22
47
  logger_1.logger.debug(`Got source token ${(_d = op.metadata) === null || _d === void 0 ? void 0 : _d.sourceToken} for region ${region}`);
23
48
  this.resolve((_e = op.metadata) === null || _e === void 0 ? void 0 : _e.sourceToken);
49
+ this.fetchState = "VALID";
50
+ this.expiry = Date.now() + this.tokenValidDurationMs;
24
51
  }
25
52
  };
26
53
  }
@@ -51,6 +51,7 @@ function assertBuildEndpoint(ep, id) {
51
51
  region: "array",
52
52
  platform: (platform) => build.AllFunctionsPlatforms.includes(platform),
53
53
  entryPoint: "string",
54
+ omit: "Field<boolean>?",
54
55
  availableMemoryMb: (mem) => mem === null || isCEL(mem) || build.isValidMemoryOption(mem),
55
56
  maxInstances: "Field<number>?",
56
57
  minInstances: "Field<number>?",
@@ -259,7 +260,7 @@ function parseEndpointForBuild(id, ep, project, defaultRegion, runtime) {
259
260
  if ("serviceAccountEmail" in ep) {
260
261
  parsed.serviceAccount = ep.serviceAccountEmail;
261
262
  }
262
- (0, proto_1.copyIfPresent)(parsed, ep, "availableMemoryMb", "cpu", "maxInstances", "minInstances", "concurrency", "timeoutSeconds", "vpc", "labels", "ingressSettings", "environmentVariables", "serviceAccount");
263
+ (0, proto_1.copyIfPresent)(parsed, ep, "omit", "availableMemoryMb", "cpu", "maxInstances", "minInstances", "concurrency", "timeoutSeconds", "vpc", "labels", "ingressSettings", "environmentVariables", "serviceAccount");
263
264
  (0, proto_1.convertIfPresent)(parsed, ep, "secretEnvironmentVariables", (senvs) => {
264
265
  if (!senvs) {
265
266
  return null;
@@ -27,6 +27,7 @@ async function downloadEmulator(name) {
27
27
  if (emulator.unzipDir) {
28
28
  await unzip(emulator.downloadPath, emulator.unzipDir);
29
29
  }
30
+ await new Promise((f) => setTimeout(f, 2000));
30
31
  const executablePath = emulator.binaryPath || emulator.downloadPath;
31
32
  fs.chmodSync(executablePath, 0o755);
32
33
  removeOldFiles(name, emulator);
@@ -54,7 +55,7 @@ function unzip(zipPath, unzipDir) {
54
55
  fs.createReadStream(zipPath)
55
56
  .pipe(unzipper.Extract({ path: unzipDir }))
56
57
  .on("error", reject)
57
- .on("finish", resolve);
58
+ .on("close", resolve);
58
59
  });
59
60
  }
60
61
  function removeOldFiles(name, emulator, removeAllVersions = false) {
@@ -40,9 +40,9 @@ const EMULATOR_UPDATE_DETAILS = {
40
40
  expectedChecksum: "a4944414518be206280b495f526f18bf",
41
41
  },
42
42
  pubsub: {
43
- version: "0.1.0",
44
- expectedSize: 36623622,
45
- expectedChecksum: "81704b24737d4968734d3e175f4cde71",
43
+ version: "0.7.1",
44
+ expectedSize: 65137179,
45
+ expectedChecksum: "b59a6e705031a54a69e5e1dced7ca9bf",
46
46
  },
47
47
  };
48
48
  exports.DownloadDetails = {
@@ -44,7 +44,7 @@ class ExtensionsEmulator {
44
44
  if (!functionsEmulator) {
45
45
  throw new error_1.FirebaseError("Extensions Emulator is running but Functions emulator is not. This should never happen.");
46
46
  }
47
- return functionsEmulator.getInfo();
47
+ return Object.assign(Object.assign({}, functionsEmulator.getInfo()), { name: this.getName() });
48
48
  }
49
49
  getName() {
50
50
  return types_1.Emulators.EXTENSIONS;
@@ -137,10 +137,11 @@ class FunctionsEmulator {
137
137
  method: req.method,
138
138
  path: `/functions/projects/${projectId}/triggers/${triggerId}`,
139
139
  headers: req.headers,
140
- }, resolve);
140
+ });
141
141
  trigReq.on("error", reject);
142
142
  trigReq.write(rawBody);
143
143
  trigReq.end();
144
+ resolve();
144
145
  });
145
146
  });
146
147
  });
@@ -4,9 +4,9 @@ exports.createFirebaseEndpoints = void 0;
4
4
  const emulatorLogger_1 = require("../../emulatorLogger");
5
5
  const types_1 = require("../../types");
6
6
  const uuid = require("uuid");
7
- const zlib_1 = require("zlib");
8
7
  const metadata_1 = require("../metadata");
9
8
  const express_1 = require("express");
9
+ const shared_1 = require("./shared");
10
10
  const registry_1 = require("../../registry");
11
11
  const multipart_1 = require("../multipart");
12
12
  const errors_1 = require("../errors");
@@ -17,7 +17,7 @@ function createFirebaseEndpoints(emulator) {
17
17
  const { storageLayer, uploadService } = emulator;
18
18
  if (process.env.STORAGE_EMULATOR_DEBUG) {
19
19
  firebaseStorageAPI.use((req, res, next) => {
20
- console.log("--------------INCOMING REQUEST--------------");
20
+ console.log("--------------INCOMING FIREBASE REQUEST--------------");
21
21
  console.log(`${req.method.toUpperCase()} ${req.path}`);
22
22
  console.log("-- query:");
23
23
  console.log(JSON.stringify(req.query, undefined, 2));
@@ -98,24 +98,7 @@ function createFirebaseEndpoints(emulator) {
98
98
  metadata.addDownloadToken(true);
99
99
  }
100
100
  if (req.query.alt === "media") {
101
- const isGZipped = metadata.contentEncoding === "gzip";
102
- if (isGZipped) {
103
- data = (0, zlib_1.gunzipSync)(data);
104
- }
105
- res.setHeader("Accept-Ranges", "bytes");
106
- res.setHeader("Content-Type", metadata.contentType || "application/octet-stream");
107
- res.setHeader("Content-Disposition", metadata.contentDisposition || "inline");
108
- setObjectHeaders(res, metadata, { "Content-Encoding": isGZipped ? "identity" : undefined });
109
- const byteRange = req.range(data.byteLength, { combine: true });
110
- if (Array.isArray(byteRange) && byteRange.type === "bytes" && byteRange.length > 0) {
111
- const range = byteRange[0];
112
- res.setHeader("Content-Range", `${byteRange.type} ${range.start}-${range.end}/${data.byteLength}`);
113
- res.status(206).end(data.slice(range.start, range.end + 1));
114
- }
115
- else {
116
- res.end(data);
117
- }
118
- return;
101
+ return (0, shared_1.sendFileBytes)(metadata, data, req, res);
119
102
  }
120
103
  return res.json(new metadata_1.OutgoingFirebaseMetadata(metadata));
121
104
  });
@@ -215,7 +198,7 @@ function createFirebaseEndpoints(emulator) {
215
198
  const upload = uploadService.startResumableUpload({
216
199
  bucketId,
217
200
  objectId,
218
- metadataRaw: JSON.stringify(req.body),
201
+ metadata: req.body,
219
202
  authorization: req.header("authorization"),
220
203
  });
221
204
  res.header("x-goog-upload-chunk-granularity", "10000");
@@ -330,7 +313,7 @@ function createFirebaseEndpoints(emulator) {
330
313
  const upload = uploadService.multipartUpload({
331
314
  bucketId,
332
315
  objectId,
333
- metadataRaw,
316
+ metadata: JSON.parse(metadataRaw),
334
317
  dataRaw: dataRaw,
335
318
  authorization: req.header("authorization"),
336
319
  });
@@ -480,14 +463,11 @@ function createFirebaseEndpoints(emulator) {
480
463
  return firebaseStorageAPI;
481
464
  }
482
465
  exports.createFirebaseEndpoints = createFirebaseEndpoints;
483
- function setObjectHeaders(res, metadata, headerOverride = { "Content-Encoding": undefined }) {
466
+ function setObjectHeaders(res, metadata) {
484
467
  if (metadata.contentDisposition) {
485
468
  res.setHeader("Content-Disposition", metadata.contentDisposition);
486
469
  }
487
- if (headerOverride["Content-Encoding"]) {
488
- res.setHeader("Content-Encoding", headerOverride["Content-Encoding"]);
489
- }
490
- else if (metadata.contentEncoding) {
470
+ if (metadata.contentEncoding) {
491
471
  res.setHeader("Content-Encoding", metadata.contentEncoding);
492
472
  }
493
473
  if (metadata.cacheControl) {
@@ -2,12 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createCloudEndpoints = void 0;
4
4
  const express_1 = require("express");
5
- const zlib_1 = require("zlib");
6
5
  const types_1 = require("../../types");
7
6
  const metadata_1 = require("../metadata");
7
+ const shared_1 = require("./shared");
8
8
  const registry_1 = require("../../registry");
9
9
  const emulatorLogger_1 = require("../../emulatorLogger");
10
- const crc_1 = require("../crc");
11
10
  const multipart_1 = require("../multipart");
12
11
  const upload_1 = require("../upload");
13
12
  const errors_1 = require("../errors");
@@ -17,7 +16,7 @@ function createCloudEndpoints(emulator) {
17
16
  const { adminStorageLayer, uploadService } = emulator;
18
17
  if (process.env.STORAGE_EMULATOR_DEBUG) {
19
18
  gcloudStorageAPI.use((req, res, next) => {
20
- console.log("--------------INCOMING REQUEST--------------");
19
+ console.log("--------------INCOMING GCS REQUEST--------------");
21
20
  console.log(`${req.method.toUpperCase()} ${req.path}`);
22
21
  console.log("-- query:");
23
22
  console.log(JSON.stringify(req.query, undefined, 2));
@@ -86,7 +85,7 @@ function createCloudEndpoints(emulator) {
86
85
  throw err;
87
86
  }
88
87
  if (req.query.alt === "media") {
89
- return sendFileBytes(getObjectResponse.metadata, getObjectResponse.data, req, res);
88
+ return (0, shared_1.sendFileBytes)(getObjectResponse.metadata, getObjectResponse.data, req, res);
90
89
  }
91
90
  return res.json(new metadata_1.CloudStorageObjectMetadata(getObjectResponse.metadata));
92
91
  });
@@ -110,7 +109,7 @@ function createCloudEndpoints(emulator) {
110
109
  }
111
110
  return res.json(new metadata_1.CloudStorageObjectMetadata(updatedMetadata));
112
111
  });
113
- gcloudStorageAPI.get("/b/:bucketId/o", async (req, res) => {
112
+ gcloudStorageAPI.get(["/b/:bucketId/o", "/storage/v1/b/:bucketId/o"], async (req, res) => {
114
113
  var _a;
115
114
  let listResponse;
116
115
  try {
@@ -228,10 +227,11 @@ function createCloudEndpoints(emulator) {
228
227
  res.sendStatus(400);
229
228
  return;
230
229
  }
230
+ const contentType = req.header("x-upload-content-type");
231
231
  const upload = uploadService.startResumableUpload({
232
232
  bucketId: req.params.bucketId,
233
233
  objectId: name,
234
- metadataRaw: JSON.stringify(req.body),
234
+ metadata: Object.assign({ contentType }, req.body),
235
235
  authorization: req.header("authorization"),
236
236
  });
237
237
  const uploadUrl = registry_1.EmulatorRegistry.url(types_1.Emulators.STORAGE, req);
@@ -256,6 +256,7 @@ function createCloudEndpoints(emulator) {
256
256
  }
257
257
  if (uploadType === "multipart") {
258
258
  const contentTypeHeader = req.header("content-type") || req.header("x-upload-content-type");
259
+ const contentType = req.header("x-upload-content-type");
259
260
  if (!contentTypeHeader) {
260
261
  return res.sendStatus(400);
261
262
  }
@@ -283,7 +284,7 @@ function createCloudEndpoints(emulator) {
283
284
  const upload = uploadService.multipartUpload({
284
285
  bucketId: req.params.bucketId,
285
286
  objectId: name,
286
- metadataRaw: metadataRaw,
287
+ metadata: Object.assign({ contentType }, JSON.parse(metadataRaw)),
287
288
  dataRaw: dataRaw,
288
289
  authorization: req.header("authorization"),
289
290
  });
@@ -318,7 +319,7 @@ function createCloudEndpoints(emulator) {
318
319
  }
319
320
  throw err;
320
321
  }
321
- return sendFileBytes(getObjectResponse.metadata, getObjectResponse.data, req, res);
322
+ return (0, shared_1.sendFileBytes)(getObjectResponse.metadata, getObjectResponse.data, req, res);
322
323
  });
323
324
  gcloudStorageAPI.post("/b/:bucketId/o/:objectId/:method(rewriteTo|copyTo)/b/:destBucketId/o/:destObjectId", (req, res, next) => {
324
325
  if (req.params.method === "rewriteTo" && req.query.rewriteToken) {
@@ -375,31 +376,6 @@ function createCloudEndpoints(emulator) {
375
376
  return gcloudStorageAPI;
376
377
  }
377
378
  exports.createCloudEndpoints = createCloudEndpoints;
378
- function sendFileBytes(md, data, req, res) {
379
- const isGZipped = md.contentEncoding === "gzip";
380
- if (isGZipped) {
381
- data = (0, zlib_1.gunzipSync)(data);
382
- }
383
- res.setHeader("Accept-Ranges", "bytes");
384
- res.setHeader("Content-Type", md.contentType || "application/octet-stream");
385
- res.setHeader("Content-Disposition", md.contentDisposition || "attachment");
386
- res.setHeader("Content-Encoding", isGZipped ? "identity" : md.contentEncoding || "");
387
- res.setHeader("ETag", md.etag);
388
- res.setHeader("Cache-Control", md.cacheControl || "");
389
- res.setHeader("x-goog-generation", `${md.generation}`);
390
- res.setHeader("x-goog-metadatageneration", `${md.metageneration}`);
391
- res.setHeader("x-goog-storage-class", md.storageClass);
392
- res.setHeader("x-goog-hash", `crc32c=${(0, crc_1.crc32cToString)(md.crc32c)},md5=${md.md5Hash}`);
393
- const byteRange = req.range(data.byteLength, { combine: true });
394
- if (Array.isArray(byteRange) && byteRange.type === "bytes" && byteRange.length > 0) {
395
- const range = byteRange[0];
396
- res.setHeader("Content-Range", `${byteRange.type} ${range.start}-${range.end}/${data.byteLength}`);
397
- res.status(206).end(data.slice(range.start, range.end + 1));
398
- }
399
- else {
400
- res.end(data);
401
- }
402
- }
403
379
  function sendObjectNotFound(req, res) {
404
380
  res.status(404);
405
381
  const message = `No such object: ${req.params.bucketId}/${req.params.objectId}`;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sendFileBytes = void 0;
4
+ const zlib_1 = require("zlib");
5
+ const crc_1 = require("../crc");
6
+ function sendFileBytes(md, data, req, res) {
7
+ let didGunzip = false;
8
+ if (md.contentEncoding === "gzip") {
9
+ const acceptEncoding = req.header("accept-encoding") || "";
10
+ const shouldGunzip = !acceptEncoding.includes("gzip");
11
+ if (shouldGunzip) {
12
+ data = (0, zlib_1.gunzipSync)(data);
13
+ didGunzip = true;
14
+ }
15
+ }
16
+ res.setHeader("Accept-Ranges", "bytes");
17
+ res.setHeader("Content-Type", md.contentType || "application/octet-stream");
18
+ res.setHeader("Content-Disposition", md.contentDisposition || "attachment");
19
+ if (didGunzip) {
20
+ res.setHeader("Transfer-Encoding", "chunked");
21
+ }
22
+ else {
23
+ res.setHeader("Content-Encoding", md.contentEncoding || "");
24
+ }
25
+ res.setHeader("ETag", md.etag);
26
+ res.setHeader("Cache-Control", md.cacheControl || "");
27
+ res.setHeader("x-goog-generation", `${md.generation}`);
28
+ res.setHeader("x-goog-metadatageneration", `${md.metageneration}`);
29
+ res.setHeader("x-goog-storage-class", md.storageClass);
30
+ res.setHeader("x-goog-hash", `crc32c=${(0, crc_1.crc32cToString)(md.crc32c)},md5=${md.md5Hash}`);
31
+ const shouldRespectContentRange = !didGunzip;
32
+ if (shouldRespectContentRange) {
33
+ const byteRange = req.range(data.byteLength, { combine: true });
34
+ if (Array.isArray(byteRange) && byteRange.type === "bytes" && byteRange.length > 0) {
35
+ const range = byteRange[0];
36
+ res.setHeader("Content-Range", `${byteRange.type} ${range.start}-${range.end}/${data.byteLength}`);
37
+ res.status(206).end(data.slice(range.start, range.end + 1));
38
+ return;
39
+ }
40
+ }
41
+ res.end(data);
42
+ }
43
+ exports.sendFileBytes = sendFileBytes;
@@ -3,6 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getStorageRulesConfig = void 0;
4
4
  const error_1 = require("../../../error");
5
5
  const fsutils_1 = require("../../../fsutils");
6
+ const constants_1 = require("../../constants");
7
+ const types_1 = require("../../types");
8
+ const emulatorLogger_1 = require("../../emulatorLogger");
6
9
  function getSourceFile(rules, options) {
7
10
  const path = options.config.path(rules);
8
11
  return { name: path, content: (0, fsutils_1.readFile)(path) };
@@ -10,6 +13,12 @@ function getSourceFile(rules, options) {
10
13
  function getStorageRulesConfig(projectId, options) {
11
14
  const storageConfig = options.config.data.storage;
12
15
  if (!storageConfig) {
16
+ if (constants_1.Constants.isDemoProject(projectId)) {
17
+ const storageLogger = emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.STORAGE);
18
+ storageLogger.logLabeled("BULLET", "storage", `Detected demo project ID "${projectId}", using a default (open) rules configuration.`);
19
+ const path = __dirname + "/../../../../templates/emulators/default_storage.rules";
20
+ return { name: path, content: (0, fsutils_1.readFile)(path) };
21
+ }
13
22
  throw new error_1.FirebaseError("Cannot start the Storage emulator without rules file specified in firebase.json: run 'firebase init' and set up your Storage configuration");
14
23
  }
15
24
  if (!Array.isArray(storageConfig)) {
@@ -50,7 +50,7 @@ class UploadService {
50
50
  objectId: request.objectId,
51
51
  uploadType: UploadType.MULTIPART,
52
52
  dataRaw: request.dataRaw,
53
- metadata: JSON.parse(request.metadataRaw),
53
+ metadata: request.metadata,
54
54
  authorization: request.authorization,
55
55
  });
56
56
  this._persistence.deleteFile(upload.path, true);
@@ -82,7 +82,7 @@ class UploadService {
82
82
  type: UploadType.RESUMABLE,
83
83
  path: this.getStagingFileName(id, request.bucketId, request.objectId),
84
84
  status: UploadStatus.ACTIVE,
85
- metadata: JSON.parse(request.metadataRaw),
85
+ metadata: request.metadata,
86
86
  size: 0,
87
87
  authorization: request.authorization,
88
88
  };
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "firebase-tools",
3
- "version": "11.16.0",
3
+ "version": "11.16.1",
4
4
  "lockfileVersion": 2,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "firebase-tools",
9
- "version": "11.16.0",
9
+ "version": "11.16.1",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@google-cloud/pubsub": "^3.0.1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "firebase-tools",
3
- "version": "11.16.0",
3
+ "version": "11.16.1",
4
4
  "description": "Command-Line Interface for Firebase",
5
5
  "main": "./lib/index.js",
6
6
  "bin": {
@@ -0,0 +1,8 @@
1
+ rules_version = '2';
2
+ service firebase.storage {
3
+ match /b/{bucket}/o {
4
+ match /{allPaths=**} {
5
+ allow read, write;
6
+ }
7
+ }
8
+ }
@@ -1,7 +1,7 @@
1
1
  package PACKAGE
2
2
 
3
3
  // Welcome to Cloud Functions for Firebase for Golang!
4
- // To get started, simply uncomment the below code or create your own.
4
+ // To get started, uncomment the below code or create your own.
5
5
  // Deploy with `firebase deploy`
6
6
 
7
7
  /*
@@ -1,7 +1,7 @@
1
1
  const functions = require("firebase-functions");
2
2
 
3
- // // Create and Deploy Your First Cloud Functions
4
- // // https://firebase.google.com/docs/functions/write-firebase-functions
3
+ // // Create and deploy your first functions
4
+ // // https://firebase.google.com/docs/functions/get-started
5
5
  //
6
6
  // exports.helloWorld = functions.https.onRequest((request, response) => {
7
7
  // functions.logger.info("Hello logs!", {structuredData: true});
@@ -1,6 +1,6 @@
1
1
  import * as functions from "firebase-functions";
2
2
 
3
- // // Start writing Firebase Functions
3
+ // // Start writing functions
4
4
  // // https://firebase.google.com/docs/functions/typescript
5
5
  //
6
6
  // export const helloWorld = functions.https.onRequest((request, response) => {