firebase-tools 13.11.4 → 13.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 (35) hide show
  1. package/lib/auth.js +14 -15
  2. package/lib/commands/dataconnect-sdk-generate.js +4 -3
  3. package/lib/commands/ext-dev-init.js +25 -26
  4. package/lib/commands/init.js +9 -5
  5. package/lib/config.js +6 -1
  6. package/lib/dataconnect/fileUtils.js +8 -6
  7. package/lib/dataconnect/load.js +4 -3
  8. package/lib/deploy/dataconnect/prepare.js +1 -1
  9. package/lib/emulator/controller.js +0 -1
  10. package/lib/emulator/dataconnectEmulator.js +6 -3
  11. package/lib/emulator/downloadableEmulators.js +0 -1
  12. package/lib/emulator/storage/rules/config.js +4 -2
  13. package/lib/hosting/implicitInit.js +2 -2
  14. package/lib/init/features/dataconnect/index.js +12 -11
  15. package/lib/init/features/dataconnect/sdk.js +120 -0
  16. package/lib/init/features/firestore/indexes.js +2 -2
  17. package/lib/init/features/firestore/rules.js +2 -2
  18. package/lib/init/features/functions/javascript.js +6 -8
  19. package/lib/init/features/functions/python.js +4 -6
  20. package/lib/init/features/functions/typescript.js +8 -10
  21. package/lib/init/features/hosting/index.js +3 -3
  22. package/lib/init/features/index.js +3 -1
  23. package/lib/init/features/storage.js +2 -2
  24. package/lib/init/index.js +1 -0
  25. package/lib/listFiles.js +1 -0
  26. package/lib/management/apps.js +2 -2
  27. package/lib/templates.js +23 -0
  28. package/lib/utils.js +2 -2
  29. package/package.json +1 -1
  30. package/schema/connector-yaml.json +36 -4
  31. package/schema/dataconnect-yaml.json +4 -0
  32. package/schema/firebase-config.json +0 -8
  33. package/templates/_gitignore +3 -0
  34. package/templates/init/dataconnect/connector.yaml +11 -0
  35. package/templates/init/dataconnect/dataconnect.yaml +1 -0
package/lib/auth.js CHANGED
@@ -3,14 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.addAdditionalAccount = exports.logout = exports.getAccessToken = exports.findAccountByEmail = exports.loginGithub = exports.loginGoogle = exports.setGlobalDefaultAccount = exports.setProjectAccount = exports.loginAdditionalAccount = exports.selectAccount = exports.setRefreshToken = exports.setActiveAccount = exports.getAllAccounts = exports.getAdditionalAccounts = exports.getProjectDefaultAccount = exports.getGlobalDefaultAccount = void 0;
4
4
  const clc = require("colorette");
5
5
  const FormData = require("form-data");
6
- const fs = require("fs");
7
6
  const http = require("http");
8
7
  const jwt = require("jsonwebtoken");
9
8
  const opn = require("open");
10
- const path = require("path");
11
9
  const portfinder = require("portfinder");
12
10
  const url = require("url");
13
- const util = require("util");
14
11
  const apiv2 = require("./apiv2");
15
12
  const configstore_1 = require("./configstore");
16
13
  const error_1 = require("./error");
@@ -23,6 +20,7 @@ const uuid_1 = require("uuid");
23
20
  const crypto_1 = require("crypto");
24
21
  const track_1 = require("./track");
25
22
  const api_1 = require("./api");
23
+ const templates_1 = require("./templates");
26
24
  portfinder.setBasePort(9005);
27
25
  function getGlobalDefaultAccount() {
28
26
  const user = configstore_1.configstore.get("user");
@@ -261,13 +259,12 @@ async function getGithubTokensFromAuthorizationCode(code, callbackUrl) {
261
259
  });
262
260
  return res.body.access_token;
263
261
  }
264
- async function respondWithFile(req, res, statusCode, filename) {
265
- const response = await util.promisify(fs.readFile)(path.join(__dirname, filename));
262
+ function respondHtml(req, res, statusCode, html) {
266
263
  res.writeHead(statusCode, {
267
- "Content-Length": response.length,
264
+ "Content-Length": html.length,
268
265
  "Content-Type": "text/html",
269
266
  });
270
- res.end(response);
267
+ res.end(html);
271
268
  req.socket.destroy();
272
269
  }
273
270
  function urlsafeBase64(base64string) {
@@ -319,8 +316,8 @@ async function loginRemotely() {
319
316
  async function loginWithLocalhostGoogle(port, userHint) {
320
317
  const callbackUrl = getCallbackUrl(port);
321
318
  const authUrl = getLoginUrl(callbackUrl, userHint);
322
- const successTemplate = "../templates/loginSuccess.html";
323
- const tokens = await loginWithLocalhost(port, callbackUrl, authUrl, successTemplate, getTokensFromAuthorizationCode);
319
+ const successHtml = await (0, templates_1.readTemplate)("loginSuccess.html");
320
+ const tokens = await loginWithLocalhost(port, callbackUrl, authUrl, successHtml, getTokensFromAuthorizationCode);
324
321
  void (0, track_1.trackGA4)("login", { method: "google_localhost" });
325
322
  return {
326
323
  user: jwt.decode(tokens.id_token, { json: true }),
@@ -331,30 +328,32 @@ async function loginWithLocalhostGoogle(port, userHint) {
331
328
  async function loginWithLocalhostGitHub(port) {
332
329
  const callbackUrl = getCallbackUrl(port);
333
330
  const authUrl = getGithubLoginUrl(callbackUrl);
334
- const successTemplate = "../templates/loginSuccessGithub.html";
335
- const tokens = await loginWithLocalhost(port, callbackUrl, authUrl, successTemplate, getGithubTokensFromAuthorizationCode);
331
+ const successHtml = await (0, templates_1.readTemplate)("loginSuccessGithub.html");
332
+ const tokens = await loginWithLocalhost(port, callbackUrl, authUrl, successHtml, getGithubTokensFromAuthorizationCode);
336
333
  void (0, track_1.trackGA4)("login", { method: "github_localhost" });
337
334
  return tokens;
338
335
  }
339
- async function loginWithLocalhost(port, callbackUrl, authUrl, successTemplate, getTokens) {
336
+ async function loginWithLocalhost(port, callbackUrl, authUrl, successHtml, getTokens) {
340
337
  return new Promise((resolve, reject) => {
341
338
  const server = http.createServer(async (req, res) => {
342
339
  const query = url.parse(`${req.url}`, true).query || {};
343
340
  const queryState = query.state;
344
341
  const queryCode = query.code;
345
342
  if (queryState !== _nonce || typeof queryCode !== "string") {
346
- await respondWithFile(req, res, 400, "../templates/loginFailure.html");
343
+ const html = await (0, templates_1.readTemplate)("loginFailure.html");
344
+ respondHtml(req, res, 400, html);
347
345
  reject(new error_1.FirebaseError("Unexpected error while logging in"));
348
346
  server.close();
349
347
  return;
350
348
  }
351
349
  try {
352
350
  const tokens = await getTokens(queryCode, callbackUrl);
353
- await respondWithFile(req, res, 200, successTemplate);
351
+ respondHtml(req, res, 200, successHtml);
354
352
  resolve(tokens);
355
353
  }
356
354
  catch (err) {
357
- await respondWithFile(req, res, 400, "../templates/loginFailure.html");
355
+ const html = await (0, templates_1.readTemplate)("loginFailure.html");
356
+ respondHtml(req, res, 400, html);
358
357
  reject(err);
359
358
  }
360
359
  server.close();
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.command = void 0;
4
4
  const path = require("path");
5
+ const clc = require("colorette");
5
6
  const command_1 = require("../command");
6
7
  const dataconnectEmulator_1 = require("../emulator/dataconnectEmulator");
7
8
  const projectUtils_1 = require("../projectUtils");
@@ -19,7 +20,7 @@ exports.command = new command_1.Command("dataconnect:sdk:generate")
19
20
  const cwd = options.cwd || process.cwd();
20
21
  configDir = path.resolve(path.join(cwd), configDir);
21
22
  }
22
- const serviceInfo = await (0, load_1.load)(projectId, service.location, configDir);
23
+ const serviceInfo = await (0, load_1.load)(projectId, configDir);
23
24
  const hasGeneratables = serviceInfo.connectorInfo.some((c) => {
24
25
  var _a, _b, _c;
25
26
  return (((_a = c.connectorYaml.generate) === null || _a === void 0 ? void 0 : _a.javascriptSdk) ||
@@ -28,13 +29,13 @@ exports.command = new command_1.Command("dataconnect:sdk:generate")
28
29
  });
29
30
  if (!hasGeneratables) {
30
31
  logger_1.logger.warn("No generated SDKs have been declared in connector.yaml files.");
31
- logger_1.logger.warn("See https://firebase.google.com/docs/data-connect/quickstart#configure-sdk-outputs for examples of how to configure generated SDKs.");
32
+ logger_1.logger.warn(`Run ${clc.bold("firebase init dataconnect:sdk")} to configure a generated SDK.`);
33
+ logger_1.logger.warn(`See https://firebase.google.com/docs/data-connect/gp/web-sdk for more details of how to configure generated SDKs.`);
32
34
  return;
33
35
  }
34
36
  for (const conn of serviceInfo.connectorInfo) {
35
37
  const output = await dataconnectEmulator_1.DataConnectEmulator.generate({
36
38
  configDir,
37
- locationId: service.location,
38
39
  connectorId: conn.connectorYaml.connectorId,
39
40
  });
40
41
  logger_1.logger.info(output);
@@ -1,8 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.command = void 0;
4
- const fs = require("fs");
5
- const path = require("path");
6
4
  const marked_1 = require("marked");
7
5
  const TerminalRenderer = require("marked-terminal");
8
6
  const checkMinRequiredVersion_1 = require("../checkMinRequiredVersion");
@@ -12,19 +10,18 @@ const error_1 = require("../error");
12
10
  const prompt_1 = require("../prompt");
13
11
  const logger_1 = require("../logger");
14
12
  const npmDependencies = require("../init/features/functions/npm-dependencies");
13
+ const templates_1 = require("../templates");
15
14
  marked_1.marked.setOptions({
16
15
  renderer: new TerminalRenderer(),
17
16
  });
18
- const TEMPLATE_ROOT = path.resolve(__dirname, "../../templates/extensions/");
19
- const FUNCTIONS_ROOT = path.resolve(__dirname, "../../templates/init/functions/");
20
17
  function readCommonTemplates() {
21
18
  return {
22
- integrationTestFirebaseJsonTemplate: fs.readFileSync(path.join(TEMPLATE_ROOT, "integration-test.json"), "utf8"),
23
- integrationTestEnvTemplate: fs.readFileSync(path.join(TEMPLATE_ROOT, "integration-test.env"), "utf8"),
24
- extSpecTemplate: fs.readFileSync(path.join(TEMPLATE_ROOT, "extension.yaml"), "utf8"),
25
- preinstallTemplate: fs.readFileSync(path.join(TEMPLATE_ROOT, "PREINSTALL.md"), "utf8"),
26
- postinstallTemplate: fs.readFileSync(path.join(TEMPLATE_ROOT, "POSTINSTALL.md"), "utf8"),
27
- changelogTemplate: fs.readFileSync(path.join(TEMPLATE_ROOT, "CL-template.md"), "utf8"),
19
+ integrationTestFirebaseJsonTemplate: (0, templates_1.readTemplateSync)("extensions/integration-test.json"),
20
+ integrationTestEnvTemplate: (0, templates_1.readTemplateSync)("extensions/integration-test.env"),
21
+ extSpecTemplate: (0, templates_1.readTemplateSync)("extensions/extension.yaml"),
22
+ preinstallTemplate: (0, templates_1.readTemplateSync)("extensions/PREINSTALL.md"),
23
+ postinstallTemplate: (0, templates_1.readTemplateSync)("extensions/POSTINSTALL.md"),
24
+ changelogTemplate: (0, templates_1.readTemplateSync)("extensions/CL-template.md"),
28
25
  };
29
26
  }
30
27
  exports.command = new command_1.Command("ext:dev:init")
@@ -34,6 +31,7 @@ exports.command = new command_1.Command("ext:dev:init")
34
31
  const cwd = options.cwd || process.cwd();
35
32
  const config = new config_1.Config({}, { projectDir: cwd, cwd: cwd });
36
33
  try {
34
+ let welcome;
37
35
  const lang = await (0, prompt_1.promptOnce)({
38
36
  type: "list",
39
37
  name: "language",
@@ -53,10 +51,12 @@ exports.command = new command_1.Command("ext:dev:init")
53
51
  switch (lang) {
54
52
  case "javascript": {
55
53
  await javascriptSelected(config);
54
+ welcome = (0, templates_1.readTemplateSync)("extensions/javascript/WELCOME.md");
56
55
  break;
57
56
  }
58
57
  case "typescript": {
59
58
  await typescriptSelected(config);
59
+ welcome = (0, templates_1.readTemplateSync)("extensions/typescript/WELCOME.md");
60
60
  break;
61
61
  }
62
62
  default: {
@@ -64,7 +64,6 @@ exports.command = new command_1.Command("ext:dev:init")
64
64
  }
65
65
  }
66
66
  await npmDependencies.askInstallDependencies({ source: "functions" }, config);
67
- const welcome = fs.readFileSync(path.join(TEMPLATE_ROOT, lang, "WELCOME.md"), "utf8");
68
67
  return logger_1.logger.info("\n" + (0, marked_1.marked)(welcome));
69
68
  }
70
69
  catch (err) {
@@ -77,15 +76,15 @@ exports.command = new command_1.Command("ext:dev:init")
77
76
  }
78
77
  });
79
78
  async function typescriptSelected(config) {
80
- const packageLintingTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "typescript", "package.lint.json"), "utf8");
81
- const packageNoLintingTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "typescript", "package.nolint.json"), "utf8");
82
- const tsconfigTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "typescript", "tsconfig.json"), "utf8");
83
- const tsconfigDevTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "typescript", "tsconfig.dev.json"), "utf8");
84
- const indexTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "typescript", "index.ts"), "utf8");
85
- const integrationTestTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "typescript", "integration-test.ts"), "utf8");
86
- const gitignoreTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "typescript", "_gitignore"), "utf8");
87
- const mocharcTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "typescript", "_mocharc"), "utf8");
88
- const eslintTemplate = fs.readFileSync(path.join(FUNCTIONS_ROOT, "typescript", "_eslintrc"), "utf8");
79
+ const packageLintingTemplate = (0, templates_1.readTemplateSync)("extensions/typescript/package.lint.json");
80
+ const packageNoLintingTemplate = (0, templates_1.readTemplateSync)("extensions/typescript/package.nolint.json");
81
+ const tsconfigTemplate = (0, templates_1.readTemplateSync)("extensions/typescript/tsconfig.json");
82
+ const tsconfigDevTemplate = (0, templates_1.readTemplateSync)("extensions/typescript/tsconfig.dev.json");
83
+ const indexTemplate = (0, templates_1.readTemplateSync)("extensions/typescript/index.ts");
84
+ const integrationTestTemplate = (0, templates_1.readTemplateSync)("extensions/typescript/integration-test.ts");
85
+ const gitignoreTemplate = (0, templates_1.readTemplateSync)("extensions/typescript/_gitignore");
86
+ const mocharcTemplate = (0, templates_1.readTemplateSync)("extensions/typescript/_mocharc");
87
+ const eslintTemplate = (0, templates_1.readTemplateSync)("init/functions/typescript/_eslintrc");
89
88
  const lint = await (0, prompt_1.promptOnce)({
90
89
  name: "lint",
91
90
  type: "confirm",
@@ -116,12 +115,12 @@ async function typescriptSelected(config) {
116
115
  await config.askWriteProjectFile("functions/.gitignore", gitignoreTemplate);
117
116
  }
118
117
  async function javascriptSelected(config) {
119
- const indexTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "javascript", "index.js"), "utf8");
120
- const integrationTestTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "javascript", "integration-test.js"), "utf8");
121
- const packageLintingTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "javascript", "package.lint.json"), "utf8");
122
- const packageNoLintingTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "javascript", "package.nolint.json"), "utf8");
123
- const gitignoreTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "javascript", "_gitignore"), "utf8");
124
- const eslintTemplate = fs.readFileSync(path.join(FUNCTIONS_ROOT, "javascript", "_eslintrc"), "utf8");
118
+ const indexTemplate = (0, templates_1.readTemplateSync)("extensions/javascript/index.js");
119
+ const integrationTestTemplate = (0, templates_1.readTemplateSync)("extensions/javascript/integration-test.js");
120
+ const packageLintingTemplate = (0, templates_1.readTemplateSync)("extensions/javascript/package.lint.json");
121
+ const packageNoLintingTemplate = (0, templates_1.readTemplateSync)("extensions/javascript/package.nolint.json");
122
+ const gitignoreTemplate = (0, templates_1.readTemplateSync)("extensions/javascript/_gitignore");
123
+ const eslintTemplate = (0, templates_1.readTemplateSync)("init/functions/javascript/_eslintrc");
125
124
  const lint = await (0, prompt_1.promptOnce)({
126
125
  name: "lint",
127
126
  type: "confirm",
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.initAction = exports.command = void 0;
4
4
  const clc = require("colorette");
5
- const fs = require("fs");
6
5
  const os = require("os");
7
6
  const path = require("path");
8
7
  const command_1 = require("../command");
@@ -15,10 +14,10 @@ const requireAuth_1 = require("../requireAuth");
15
14
  const fsutils = require("../fsutils");
16
15
  const utils = require("../utils");
17
16
  const experiments_1 = require("../experiments");
17
+ const templates_1 = require("../templates");
18
18
  const homeDir = os.homedir();
19
- const TEMPLATE_ROOT = path.resolve(__dirname, "../../templates/");
20
- const BANNER_TEXT = fs.readFileSync(path.join(TEMPLATE_ROOT, "banner.txt"), "utf8");
21
- const GITIGNORE_TEMPLATE = fs.readFileSync(path.join(TEMPLATE_ROOT, "_gitignore"), "utf8");
19
+ const BANNER_TEXT = (0, templates_1.readTemplateSync)("banner.txt");
20
+ const GITIGNORE_TEMPLATE = (0, templates_1.readTemplateSync)("_gitignore");
22
21
  function isOutside(from, to) {
23
22
  return !!/^\.\./.exec(path.relative(from, to));
24
23
  }
@@ -78,7 +77,12 @@ if ((0, experiments_1.isEnabled)("genkit")) {
78
77
  }
79
78
  choices.push({
80
79
  value: "dataconnect",
81
- name: "Data Connect: Set up a Firebase Data Connect service.",
80
+ name: "Data Connect: Set up a Firebase Data Connect service",
81
+ checked: false,
82
+ });
83
+ choices.push({
84
+ value: "dataconnect:sdk",
85
+ name: "Data Connect: Set up a generated SDK for your Firebase Data Connect service",
82
86
  checked: false,
83
87
  });
84
88
  const featureNames = choices.map((choice) => choice.value);
package/lib/config.js CHANGED
@@ -18,7 +18,7 @@ const loadCJSON_1 = require("./loadCJSON");
18
18
  const parseBoltRules = require("./parseBoltRules");
19
19
  class Config {
20
20
  constructor(src, options = {}) {
21
- var _a;
21
+ var _a, _b;
22
22
  this.data = {};
23
23
  this.defaults = {};
24
24
  this.notes = {};
@@ -54,6 +54,11 @@ class Config {
54
54
  }
55
55
  }
56
56
  }
57
+ if (((_b = this._src.dataconnect) === null || _b === void 0 ? void 0 : _b.location) ||
58
+ (Array.isArray(this._src.dataconnect) && this._src.dataconnect.some((c) => c === null || c === void 0 ? void 0 : c.location))) {
59
+ utils.logLabeledWarning("dataconnect", "'location' has been moved from 'firebase.json' to 'dataconnect.yaml'. " +
60
+ "Please remove 'dataconnect.location' from 'firebase.json' and add it as top level field to 'dataconnect.yaml' instead ");
61
+ }
57
62
  }
58
63
  materialize(target) {
59
64
  const val = _.get(this._src, target);
@@ -11,12 +11,11 @@ function readFirebaseJson(config) {
11
11
  return [];
12
12
  }
13
13
  const validator = (cfg) => {
14
- if (!cfg["source"] && !cfg["location"]) {
15
- throw new error_1.FirebaseError("Invalid firebase.json: DataConnect requires `source` and `location`");
14
+ if (!cfg["source"]) {
15
+ throw new error_1.FirebaseError("Invalid firebase.json: DataConnect requires `source`");
16
16
  }
17
17
  return {
18
18
  source: cfg["source"],
19
- location: cfg["location"],
20
19
  };
21
20
  };
22
21
  const configs = config.get("dataconnect");
@@ -27,7 +26,7 @@ function readFirebaseJson(config) {
27
26
  return configs.map(validator);
28
27
  }
29
28
  else {
30
- throw new error_1.FirebaseError("Invalid firebase.json: dataconnect should be of the form { source: string, location: string }");
29
+ throw new error_1.FirebaseError("Invalid firebase.json: dataconnect should be of the form { source: string }");
31
30
  }
32
31
  }
33
32
  exports.readFirebaseJson = readFirebaseJson;
@@ -38,6 +37,9 @@ async function readDataConnectYaml(sourceDirectory) {
38
37
  }
39
38
  exports.readDataConnectYaml = readDataConnectYaml;
40
39
  function validateDataConnectYaml(unvalidated) {
40
+ if (!unvalidated["location"]) {
41
+ throw new error_1.FirebaseError("Missing required field 'location' in dataconnect.yaml");
42
+ }
41
43
  return unvalidated;
42
44
  }
43
45
  async function readConnectorYaml(sourceDirectory) {
@@ -74,13 +76,13 @@ async function pickService(projectId, config, serviceId) {
74
76
  throw new error_1.FirebaseError("No Data Connect services found in firebase.json.");
75
77
  }
76
78
  else if (serviceCfgs.length === 1) {
77
- serviceInfo = await (0, load_1.load)(projectId, serviceCfgs[0].location, serviceCfgs[0].source);
79
+ serviceInfo = await (0, load_1.load)(projectId, serviceCfgs[0].source);
78
80
  }
79
81
  else {
80
82
  if (!serviceId) {
81
83
  throw new error_1.FirebaseError("Multiple Data Connect services found in firebase.json. Please specify a service ID to use.");
82
84
  }
83
- const infos = await Promise.all(serviceCfgs.map((c) => (0, load_1.load)(projectId, c.location, c.source)));
85
+ const infos = await Promise.all(serviceCfgs.map((c) => (0, load_1.load)(projectId, c.source)));
84
86
  const maybe = infos.find((i) => i.dataConnectYaml.serviceId === serviceId);
85
87
  if (!maybe) {
86
88
  throw new error_1.FirebaseError(`No service named ${serviceId} declared in firebase.json.`);
@@ -4,9 +4,9 @@ exports.load = void 0;
4
4
  const path = require("path");
5
5
  const fileUtils = require("./fileUtils");
6
6
  const types_1 = require("./types");
7
- async function load(projectId, locationId, sourceDirectory) {
7
+ async function load(projectId, sourceDirectory) {
8
8
  const dataConnectYaml = await fileUtils.readDataConnectYaml(sourceDirectory);
9
- const serviceName = `projects/${projectId}/locations/${locationId}/services/${dataConnectYaml.serviceId}`;
9
+ const serviceName = `projects/${projectId}/locations/${dataConnectYaml.location}/services/${dataConnectYaml.serviceId}`;
10
10
  const schemaDir = path.join(sourceDirectory, dataConnectYaml.schema.source);
11
11
  const schemaGQLs = await fileUtils.readGQLFiles(schemaDir);
12
12
  const connectorInfo = await Promise.all(dataConnectYaml.connectorDirs.map(async (dir) => {
@@ -14,6 +14,7 @@ async function load(projectId, locationId, sourceDirectory) {
14
14
  const connectorYaml = await fileUtils.readConnectorYaml(connectorDir);
15
15
  const connectorGqls = await fileUtils.readGQLFiles(connectorDir);
16
16
  return {
17
+ directory: connectorDir,
17
18
  connectorYaml,
18
19
  connector: {
19
20
  name: `${serviceName}/connectors/${connectorYaml.connectorId}`,
@@ -28,7 +29,7 @@ async function load(projectId, locationId, sourceDirectory) {
28
29
  sourceDirectory,
29
30
  schema: {
30
31
  name: `${serviceName}/schemas/${types_1.SCHEMA_ID}`,
31
- primaryDatasource: (0, types_1.toDatasource)(projectId, locationId, dataConnectYaml.schema.datasource),
32
+ primaryDatasource: (0, types_1.toDatasource)(projectId, dataConnectYaml.location, dataConnectYaml.schema.datasource),
32
33
  source: {
33
34
  files: schemaGQLs,
34
35
  },
@@ -18,7 +18,7 @@ async function default_1(context, options) {
18
18
  const serviceCfgs = (0, fileUtils_1.readFirebaseJson)(options.config);
19
19
  utils.logLabeledBullet("dataconnect", `Preparing to deploy`);
20
20
  const filters = (0, filters_1.getResourceFilters)(options);
21
- const serviceInfos = await Promise.all(serviceCfgs.map((c) => (0, load_1.load)(projectId, c.location, path.join(options.cwd || process.cwd(), c.source))));
21
+ const serviceInfos = await Promise.all(serviceCfgs.map((c) => (0, load_1.load)(projectId, path.join(options.cwd || process.cwd(), c.source))));
22
22
  for (const si of serviceInfos) {
23
23
  si.deploymentMetadata = await (0, build_1.build)(options, si.sourceDirectory);
24
24
  }
@@ -535,7 +535,6 @@ async function startAll(options, showUI = true, runningTestScript = false) {
535
535
  projectId,
536
536
  auto_download: true,
537
537
  configDir,
538
- locationId: config[0].location,
539
538
  rc: options.rc,
540
539
  });
541
540
  await startEmulator(dataConnectEmulator);
@@ -13,6 +13,7 @@ const types_2 = require("../dataconnect/types");
13
13
  const portUtils_1 = require("./portUtils");
14
14
  const apiv2_1 = require("../apiv2");
15
15
  const registry_1 = require("./registry");
16
+ const logger_1 = require("../logger");
16
17
  const load_1 = require("../dataconnect/load");
17
18
  const utils_1 = require("../utils");
18
19
  const events_1 = require("events");
@@ -50,7 +51,6 @@ class DataConnectEmulator {
50
51
  auto_download: this.args.auto_download,
51
52
  listen: (0, portUtils_1.listenSpecsToString)(this.args.listen),
52
53
  config_dir: this.args.configDir,
53
- service_location: this.args.locationId,
54
54
  });
55
55
  this.usingExistingEmulator = false;
56
56
  }
@@ -93,16 +93,19 @@ class DataConnectEmulator {
93
93
  "--logtostderr",
94
94
  "-v=2",
95
95
  "generate",
96
- `--service_location=${args.locationId}`,
97
96
  `--config_dir=${args.configDir}`,
98
97
  `--connector_id=${args.connectorId}`,
99
98
  ];
100
99
  const res = childProcess.spawnSync(commandInfo.binary, cmd, { encoding: "utf-8" });
100
+ logger_1.logger.info(res.stderr);
101
101
  if (res.error) {
102
102
  throw new error_1.FirebaseError(`Error starting up Data Connect generate: ${res.error.message}`, {
103
103
  original: res.error,
104
104
  });
105
105
  }
106
+ if (res.status !== 0) {
107
+ throw new error_1.FirebaseError(`Unable to generate your Data Connect SDKs (exit code ${res.status}): ${res.stderr}`);
108
+ }
106
109
  return res.stdout;
107
110
  }
108
111
  static async build(args) {
@@ -140,7 +143,7 @@ class DataConnectEmulator {
140
143
  if (!emuInfo) {
141
144
  return false;
142
145
  }
143
- const serviceInfo = await (0, load_1.load)(this.args.projectId, this.args.locationId, this.args.configDir);
146
+ const serviceInfo = await (0, load_1.load)(this.args.projectId, this.args.configDir);
144
147
  const sameService = emuInfo.services.find((s) => serviceInfo.dataConnectYaml.serviceId === s.serviceId);
145
148
  if (!sameService) {
146
149
  throw new error_1.FirebaseError(`There is a Data Connect emulator already running on ${this.args.listen[0].address}:${this.args.listen[0].port}, but it is emulating a different service. Please stop that instance of the Data Connect emulator, or specify a different port in 'firebase.json'`);
@@ -243,7 +243,6 @@ const Commands = {
243
243
  optionalArgs: [
244
244
  "listen",
245
245
  "config_dir",
246
- "service_location",
247
246
  "disable_sdk_generation",
248
247
  "resolvers_emulator",
249
248
  "rpc_retry_count",
@@ -6,6 +6,7 @@ const fsutils_1 = require("../../../fsutils");
6
6
  const constants_1 = require("../../constants");
7
7
  const types_1 = require("../../types");
8
8
  const emulatorLogger_1 = require("../../emulatorLogger");
9
+ const templates_1 = require("../../../templates");
9
10
  function getSourceFile(rules, options) {
10
11
  const path = options.config.path(rules);
11
12
  return { name: path, content: (0, fsutils_1.readFile)(path) };
@@ -48,6 +49,7 @@ function getStorageRulesConfig(projectId, options) {
48
49
  }
49
50
  exports.getStorageRulesConfig = getStorageRulesConfig;
50
51
  function defaultStorageRules() {
51
- const path = __dirname + "/../../../../templates/emulators/default_storage.rules";
52
- return { name: path, content: (0, fsutils_1.readFile)(path) };
52
+ const defaultRulesPath = "emulators/default_storage.rules";
53
+ const name = (0, templates_1.absoluteTemplateFilePath)(defaultRulesPath);
54
+ return { name, content: (0, fsutils_1.readFile)(name) };
53
55
  }
@@ -3,13 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.implicitInit = void 0;
4
4
  const _ = require("lodash");
5
5
  const clc = require("colorette");
6
- const fs = require("fs");
7
6
  const fetchWebSetup_1 = require("../fetchWebSetup");
8
7
  const utils = require("../utils");
9
8
  const logger_1 = require("../logger");
10
9
  const registry_1 = require("../emulator/registry");
11
10
  const types_1 = require("../emulator/types");
12
- const INIT_TEMPLATE = fs.readFileSync(__dirname + "/../../templates/hosting/init.js", "utf8");
11
+ const templates_1 = require("../templates");
12
+ const INIT_TEMPLATE = (0, templates_1.readTemplateSync)("hosting/init.js");
13
13
  async function implicitInit(options) {
14
14
  let config;
15
15
  try {
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.doSetup = void 0;
4
4
  const path_1 = require("path");
5
+ const clc = require("colorette");
5
6
  const prompt_1 = require("../../../prompt");
6
- const fs_1 = require("fs");
7
7
  const provisionCloudSql_1 = require("../../../dataconnect/provisionCloudSql");
8
8
  const freeTrial_1 = require("../../../dataconnect/freeTrial");
9
9
  const cloudsql = require("../../../gcp/cloudsql/cloudsqladmin");
@@ -12,12 +12,13 @@ const client_1 = require("../../../dataconnect/client");
12
12
  const emulators_1 = require("../emulators");
13
13
  const names_1 = require("../../../dataconnect/names");
14
14
  const logger_1 = require("../../../logger");
15
- const TEMPLATE_ROOT = (0, path_1.resolve)(__dirname, "../../../../templates/init/dataconnect/");
16
- const DATACONNECT_YAML_TEMPLATE = (0, fs_1.readFileSync)((0, path_1.join)(TEMPLATE_ROOT, "dataconnect.yaml"), "utf8");
17
- const CONNECTOR_YAML_TEMPLATE = (0, fs_1.readFileSync)((0, path_1.join)(TEMPLATE_ROOT, "connector.yaml"), "utf8");
18
- const SCHEMA_TEMPLATE = (0, fs_1.readFileSync)((0, path_1.join)(TEMPLATE_ROOT, "schema.gql"), "utf8");
19
- const QUERIES_TEMPLATE = (0, fs_1.readFileSync)((0, path_1.join)(TEMPLATE_ROOT, "queries.gql"), "utf8");
20
- const MUTATIONS_TEMPLATE = (0, fs_1.readFileSync)((0, path_1.join)(TEMPLATE_ROOT, "mutations.gql"), "utf8");
15
+ const templates_1 = require("../../../templates");
16
+ const utils_1 = require("../../../utils");
17
+ const DATACONNECT_YAML_TEMPLATE = (0, templates_1.readTemplateSync)("init/dataconnect/dataconnect.yaml");
18
+ const CONNECTOR_YAML_TEMPLATE = (0, templates_1.readTemplateSync)("init/dataconnect/connector.yaml");
19
+ const SCHEMA_TEMPLATE = (0, templates_1.readTemplateSync)("init/dataconnect/schema.gql");
20
+ const QUERIES_TEMPLATE = (0, templates_1.readTemplateSync)("init/dataconnect/queries.gql");
21
+ const MUTATIONS_TEMPLATE = (0, templates_1.readTemplateSync)("init/dataconnect/mutations.gql");
21
22
  async function doSetup(setup, config) {
22
23
  var _a, _b, _c;
23
24
  let info = {
@@ -47,10 +48,7 @@ async function doSetup(setup, config) {
47
48
  const dir = config.get("dataconnect.source") || "dataconnect";
48
49
  const subbedDataconnectYaml = subValues(DATACONNECT_YAML_TEMPLATE, info);
49
50
  const subbedConnectorYaml = subValues(CONNECTOR_YAML_TEMPLATE, info);
50
- if (!config.has("dataconnect")) {
51
- config.set("dataconnect.source", dir);
52
- config.set("dataconnect.location", info.locationId);
53
- }
51
+ config.set("dataconnect", { source: dir });
54
52
  await config.askWriteProjectFile((0, path_1.join)(dir, "dataconnect.yaml"), subbedDataconnectYaml);
55
53
  await config.askWriteProjectFile((0, path_1.join)(dir, "schema", "schema.gql"), SCHEMA_TEMPLATE);
56
54
  await config.askWriteProjectFile((0, path_1.join)(dir, info.connectorId, "connector.yaml"), subbedConnectorYaml);
@@ -71,6 +69,8 @@ async function doSetup(setup, config) {
71
69
  waitForCreation: false,
72
70
  });
73
71
  }
72
+ logger_1.logger.info("");
73
+ (0, utils_1.logSuccess)(`If you'd like to generate an SDK for your new connector, run ${clc.bold("firebase init dataconnect:sdk")}`);
74
74
  }
75
75
  exports.doSetup = doSetup;
76
76
  function subValues(template, replacementValues) {
@@ -79,6 +79,7 @@ function subValues(template, replacementValues) {
79
79
  cloudSqlDatabase: "__cloudSqlDatabase__",
80
80
  cloudSqlInstanceId: "__cloudSqlInstanceId__",
81
81
  connectorId: "__connectorId__",
82
+ locationId: "__location__",
82
83
  };
83
84
  let replaced = template;
84
85
  for (const [k, v] of Object.entries(replacementValues)) {
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.doSetup = void 0;
4
+ const yaml = require("yaml");
5
+ const fs = require("fs-extra");
6
+ const prompt_1 = require("../../../prompt");
7
+ const clc = require("colorette");
8
+ const path = require("path");
9
+ const fileUtils_1 = require("../../../dataconnect/fileUtils");
10
+ const load_1 = require("../../../dataconnect/load");
11
+ const logger_1 = require("../../../logger");
12
+ const dataconnectEmulator_1 = require("../../../emulator/dataconnectEmulator");
13
+ const IOS = "ios";
14
+ const WEB = "web";
15
+ const ANDROID = "android";
16
+ async function doSetup(setup, config) {
17
+ var _a, _b, _c, _d, _e, _f, _g, _h;
18
+ const serviceCfgs = (0, fileUtils_1.readFirebaseJson)(config);
19
+ const serviceInfos = await Promise.all(serviceCfgs.map((c) => (0, load_1.load)(setup.projectId || "", path.join(process.cwd(), c.source))));
20
+ const connectorChoices = serviceInfos
21
+ .map((si) => {
22
+ return si.connectorInfo.map((ci) => {
23
+ return {
24
+ name: `${si.dataConnectYaml.serviceId}/${ci.connectorYaml.connectorId}`,
25
+ value: ci,
26
+ };
27
+ });
28
+ })
29
+ .flat();
30
+ if (!connectorChoices.length) {
31
+ logger_1.logger.info(`Your config has no connectors to set up SDKs for. Run ${clc.bold("firebase init dataconnect")} to set up a service and conenctors.`);
32
+ return;
33
+ }
34
+ const connectorInfo = await (0, prompt_1.promptOnce)({
35
+ message: "Which connector do you want set up a generated SDK for?",
36
+ type: "list",
37
+ choices: connectorChoices,
38
+ });
39
+ const platforms = await (0, prompt_1.promptOnce)({
40
+ message: "Which platforms do you want to set up a generated SDK for?",
41
+ type: "checkbox",
42
+ choices: [
43
+ { name: "iOS (Swift)", value: IOS },
44
+ { name: "Web (JavaScript)", value: WEB },
45
+ { name: "Androd (Kotlin)", value: ANDROID },
46
+ ],
47
+ });
48
+ const newConnectorYaml = JSON.parse(JSON.stringify(connectorInfo.connectorYaml));
49
+ if (!newConnectorYaml.generate) {
50
+ newConnectorYaml.generate = {};
51
+ }
52
+ if (platforms.includes(IOS)) {
53
+ const defaultOutputDir = (_a = newConnectorYaml.generate.swiftSdk) === null || _a === void 0 ? void 0 : _a.outputDir;
54
+ const outputDir = await (0, prompt_1.promptOnce)({
55
+ message: `What directory do you want to write your Swift SDK code to? (If not absolute, path will be relative to '${connectorInfo.directory}')`,
56
+ type: "input",
57
+ default: defaultOutputDir,
58
+ });
59
+ const swiftSdk = { outputDir };
60
+ newConnectorYaml.generate.swiftSdk = swiftSdk;
61
+ }
62
+ if (platforms.includes(WEB)) {
63
+ const outputDir = await (0, prompt_1.promptOnce)({
64
+ message: `What directory do you want to write your JavaScript SDK code to? (If not absolute, path will be relative to '${connectorInfo.directory}')`,
65
+ type: "input",
66
+ default: (_b = newConnectorYaml.generate.javascriptSdk) === null || _b === void 0 ? void 0 : _b.outputDir,
67
+ });
68
+ const pkg = await (0, prompt_1.promptOnce)({
69
+ message: "What package name do you want to use for your JavaScript SDK?",
70
+ type: "input",
71
+ default: (_d = (_c = newConnectorYaml.generate.javascriptSdk) === null || _c === void 0 ? void 0 : _c.package) !== null && _d !== void 0 ? _d : `@firebasegen/${connectorInfo.connectorYaml.connectorId}`,
72
+ });
73
+ const packageJSONDir = await (0, prompt_1.promptOnce)({
74
+ message: "Which directory contains the package.json that you would like to add the JavaScript SDK dependency to? (Leave blank to skip)",
75
+ type: "input",
76
+ default: (_e = newConnectorYaml.generate.javascriptSdk) === null || _e === void 0 ? void 0 : _e.packageJSONDir,
77
+ });
78
+ const javascriptSdk = {
79
+ outputDir,
80
+ package: pkg,
81
+ };
82
+ if (packageJSONDir) {
83
+ javascriptSdk.packageJSONDir = packageJSONDir;
84
+ }
85
+ newConnectorYaml.generate.javascriptSdk = javascriptSdk;
86
+ }
87
+ if (platforms.includes(ANDROID)) {
88
+ const outputDir = await (0, prompt_1.promptOnce)({
89
+ message: `What directory do you want to write your Kotlin SDK code to? (If not absolute, path will be relative to '${connectorInfo.directory}')`,
90
+ type: "input",
91
+ default: (_f = newConnectorYaml.generate.kotlinSdk) === null || _f === void 0 ? void 0 : _f.outputDir,
92
+ });
93
+ const pkg = await (0, prompt_1.promptOnce)({
94
+ message: "What package name do you want to use for your Kotlin SDK?",
95
+ type: "input",
96
+ default: (_h = (_g = newConnectorYaml.generate.kotlinSdk) === null || _g === void 0 ? void 0 : _g.package) !== null && _h !== void 0 ? _h : `com.google.firebase.dataconnect.connectors.${connectorInfo.connectorYaml.connectorId}`,
97
+ });
98
+ const kotlinSdk = {
99
+ outputDir,
100
+ package: pkg,
101
+ };
102
+ newConnectorYaml.generate.kotlinSdk = kotlinSdk;
103
+ }
104
+ const connectorYamlContents = yaml.stringify(newConnectorYaml);
105
+ const connectorYamlPath = `${connectorInfo.directory}/connector.yaml`;
106
+ fs.writeFileSync(connectorYamlPath, connectorYamlContents, "utf8");
107
+ logger_1.logger.info(`Wrote new config to ${connectorYamlPath}`);
108
+ if (setup.projectId &&
109
+ (await (0, prompt_1.confirm)({
110
+ message: "Would you like to generate SDK code now?",
111
+ default: true,
112
+ }))) {
113
+ await dataconnectEmulator_1.DataConnectEmulator.generate({
114
+ configDir: connectorInfo.directory,
115
+ connectorId: connectorInfo.connectorYaml.connectorId,
116
+ });
117
+ logger_1.logger.info(`Generated SDK code for ${connectorInfo.connectorYaml.connectorId}`);
118
+ }
119
+ }
120
+ exports.doSetup = doSetup;
@@ -2,14 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.initIndexes = void 0;
4
4
  const clc = require("colorette");
5
- const fs = require("fs");
6
5
  const error_1 = require("../../../error");
7
6
  const api = require("../../../firestore/api");
8
7
  const fsutils = require("../../../fsutils");
9
8
  const prompt_1 = require("../../../prompt");
10
9
  const logger_1 = require("../../../logger");
10
+ const templates_1 = require("../../../templates");
11
11
  const indexes = new api.FirestoreApi();
12
- const INDEXES_TEMPLATE = fs.readFileSync(__dirname + "/../../../../templates/init/firestore/firestore.indexes.json", "utf8");
12
+ const INDEXES_TEMPLATE = (0, templates_1.readTemplateSync)("init/firestore/firestore.indexes.json");
13
13
  function initIndexes(setup, config) {
14
14
  logger_1.logger.info();
15
15
  logger_1.logger.info("Firestore indexes allow you to perform complex queries while");
@@ -2,14 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.initRules = void 0;
4
4
  const clc = require("colorette");
5
- const fs = require("fs");
6
5
  const gcp = require("../../../gcp");
7
6
  const fsutils = require("../../../fsutils");
8
7
  const prompt_1 = require("../../../prompt");
9
8
  const logger_1 = require("../../../logger");
10
9
  const utils = require("../../../utils");
10
+ const templates_1 = require("../../../templates");
11
11
  const DEFAULT_RULES_FILE = "firestore.rules";
12
- const RULES_TEMPLATE = fs.readFileSync(__dirname + "/../../../../templates/init/firestore/firestore.rules", "utf8");
12
+ const RULES_TEMPLATE = (0, templates_1.readTemplateSync)("init/firestore/firestore.rules");
13
13
  function initRules(setup, config) {
14
14
  logger_1.logger.info();
15
15
  logger_1.logger.info("Firestore Security Rules allow you to define how and when to allow");
@@ -1,17 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.setup = void 0;
4
- const fs = require("fs");
5
- const path = require("path");
6
4
  const npm_dependencies_1 = require("./npm-dependencies");
7
5
  const prompt_1 = require("../../../prompt");
8
6
  const projectConfig_1 = require("../../../functions/projectConfig");
9
- const TEMPLATE_ROOT = path.resolve(__dirname, "../../../../templates/init/functions/javascript/");
10
- const INDEX_TEMPLATE = fs.readFileSync(path.join(TEMPLATE_ROOT, "index.js"), "utf8");
11
- const PACKAGE_LINTING_TEMPLATE = fs.readFileSync(path.join(TEMPLATE_ROOT, "package.lint.json"), "utf8");
12
- const PACKAGE_NO_LINTING_TEMPLATE = fs.readFileSync(path.join(TEMPLATE_ROOT, "package.nolint.json"), "utf8");
13
- const ESLINT_TEMPLATE = fs.readFileSync(path.join(TEMPLATE_ROOT, "_eslintrc"), "utf8");
14
- const GITIGNORE_TEMPLATE = fs.readFileSync(path.join(TEMPLATE_ROOT, "_gitignore"), "utf8");
7
+ const templates_1 = require("../../../templates");
8
+ const INDEX_TEMPLATE = (0, templates_1.readTemplateSync)("init/functions/javascript/index.js");
9
+ const PACKAGE_LINTING_TEMPLATE = (0, templates_1.readTemplateSync)("init/functions/javascript/package.lint.json");
10
+ const PACKAGE_NO_LINTING_TEMPLATE = (0, templates_1.readTemplateSync)("init/functions/javascript/package.nolint.json");
11
+ const ESLINT_TEMPLATE = (0, templates_1.readTemplateSync)("init/functions/javascript/_eslintrc");
12
+ const GITIGNORE_TEMPLATE = (0, templates_1.readTemplateSync)("init/functions/javascript/_gitignore");
15
13
  function setup(setup, config) {
16
14
  return (0, prompt_1.prompt)(setup.functions, [
17
15
  {
@@ -1,17 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.setup = void 0;
4
- const fs = require("fs");
5
4
  const spawn = require("cross-spawn");
6
- const path = require("path");
7
5
  const python_1 = require("../../../deploy/functions/runtimes/python");
8
6
  const python_2 = require("../../../functions/python");
9
7
  const prompt_1 = require("../../../prompt");
10
8
  const supported_1 = require("../../../deploy/functions/runtimes/supported");
11
- const TEMPLATE_ROOT = path.resolve(__dirname, "../../../../templates/init/functions/python");
12
- const MAIN_TEMPLATE = fs.readFileSync(path.join(TEMPLATE_ROOT, "main.py"), "utf8");
13
- const REQUIREMENTS_TEMPLATE = fs.readFileSync(path.join(TEMPLATE_ROOT, "requirements.txt"), "utf8");
14
- const GITIGNORE_TEMPLATE = fs.readFileSync(path.join(TEMPLATE_ROOT, "_gitignore"), "utf8");
9
+ const templates_1 = require("../../../templates");
10
+ const MAIN_TEMPLATE = (0, templates_1.readTemplateSync)("init/functions/python/main.py");
11
+ const REQUIREMENTS_TEMPLATE = (0, templates_1.readTemplateSync)("init/functions/python/requirements.txt");
12
+ const GITIGNORE_TEMPLATE = (0, templates_1.readTemplateSync)("init/functions/python/_gitignore");
15
13
  async function setup(setup, config) {
16
14
  await config.askWriteProjectFile(`${setup.functions.source}/requirements.txt`, REQUIREMENTS_TEMPLATE);
17
15
  await config.askWriteProjectFile(`${setup.functions.source}/.gitignore`, GITIGNORE_TEMPLATE);
@@ -1,19 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.setup = void 0;
4
- const fs = require("fs");
5
- const path = require("path");
6
4
  const npm_dependencies_1 = require("./npm-dependencies");
7
5
  const prompt_1 = require("../../../prompt");
8
6
  const projectConfig_1 = require("../../../functions/projectConfig");
9
- const TEMPLATE_ROOT = path.resolve(__dirname, "../../../../templates/init/functions/typescript/");
10
- const PACKAGE_LINTING_TEMPLATE = fs.readFileSync(path.join(TEMPLATE_ROOT, "package.lint.json"), "utf8");
11
- const PACKAGE_NO_LINTING_TEMPLATE = fs.readFileSync(path.join(TEMPLATE_ROOT, "package.nolint.json"), "utf8");
12
- const ESLINT_TEMPLATE = fs.readFileSync(path.join(TEMPLATE_ROOT, "_eslintrc"), "utf8");
13
- const TSCONFIG_TEMPLATE = fs.readFileSync(path.join(TEMPLATE_ROOT, "tsconfig.json"), "utf8");
14
- const TSCONFIG_DEV_TEMPLATE = fs.readFileSync(path.join(TEMPLATE_ROOT, "tsconfig.dev.json"), "utf8");
15
- const INDEX_TEMPLATE = fs.readFileSync(path.join(TEMPLATE_ROOT, "index.ts"), "utf8");
16
- const GITIGNORE_TEMPLATE = fs.readFileSync(path.join(TEMPLATE_ROOT, "_gitignore"), "utf8");
7
+ const templates_1 = require("../../../templates");
8
+ const PACKAGE_LINTING_TEMPLATE = (0, templates_1.readTemplateSync)("init/functions/typescript/package.lint.json");
9
+ const PACKAGE_NO_LINTING_TEMPLATE = (0, templates_1.readTemplateSync)("init/functions/typescript/package.nolint.json");
10
+ const ESLINT_TEMPLATE = (0, templates_1.readTemplateSync)("init/functions/typescript/_eslintrc");
11
+ const TSCONFIG_TEMPLATE = (0, templates_1.readTemplateSync)("init/functions/typescript/tsconfig.json");
12
+ const TSCONFIG_DEV_TEMPLATE = (0, templates_1.readTemplateSync)("init/functions/typescript/tsconfig.dev.json");
13
+ const INDEX_TEMPLATE = (0, templates_1.readTemplateSync)("init/functions/typescript/index.ts");
14
+ const GITIGNORE_TEMPLATE = (0, templates_1.readTemplateSync)("init/functions/typescript/_gitignore");
17
15
  function setup(setup, config) {
18
16
  return (0, prompt_1.prompt)(setup.functions, [
19
17
  {
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.doSetup = void 0;
4
4
  const clc = require("colorette");
5
- const fs = require("fs");
6
5
  const rimraf_1 = require("rimraf");
7
6
  const path_1 = require("path");
8
7
  const apiv2_1 = require("../../../apiv2");
@@ -15,8 +14,9 @@ const experiments = require("../../../experiments");
15
14
  const getDefaultHostingSite_1 = require("../../../getDefaultHostingSite");
16
15
  const utils_1 = require("../../../utils");
17
16
  const interactive_1 = require("../../../hosting/interactive");
18
- const INDEX_TEMPLATE = fs.readFileSync(__dirname + "/../../../../templates/init/hosting/index.html", "utf8");
19
- const MISSING_TEMPLATE = fs.readFileSync(__dirname + "/../../../../templates/init/hosting/404.html", "utf8");
17
+ const templates_1 = require("../../../templates");
18
+ const INDEX_TEMPLATE = (0, templates_1.readTemplateSync)("init/hosting/index.html");
19
+ const MISSING_TEMPLATE = (0, templates_1.readTemplateSync)("init/hosting/404.html");
20
20
  const DEFAULT_IGNORES = ["firebase.json", "**/.*", "**/node_modules/**"];
21
21
  async function doSetup(setup, config, options) {
22
22
  var _a;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.genkit = exports.apphosting = exports.dataconnect = exports.hostingGithub = exports.remoteconfig = exports.project = exports.extensions = exports.emulators = exports.storage = exports.hosting = exports.functions = exports.firestore = exports.database = exports.account = void 0;
3
+ exports.genkit = exports.apphosting = exports.dataconnectSdk = exports.dataconnect = exports.hostingGithub = exports.remoteconfig = exports.project = exports.extensions = exports.emulators = exports.storage = exports.hosting = exports.functions = exports.firestore = exports.database = exports.account = void 0;
4
4
  var account_1 = require("./account");
5
5
  Object.defineProperty(exports, "account", { enumerable: true, get: function () { return account_1.doSetup; } });
6
6
  var database_1 = require("./database");
@@ -25,6 +25,8 @@ var github_1 = require("./hosting/github");
25
25
  Object.defineProperty(exports, "hostingGithub", { enumerable: true, get: function () { return github_1.initGitHub; } });
26
26
  var dataconnect_1 = require("./dataconnect");
27
27
  Object.defineProperty(exports, "dataconnect", { enumerable: true, get: function () { return dataconnect_1.doSetup; } });
28
+ var sdk_1 = require("./dataconnect/sdk");
29
+ Object.defineProperty(exports, "dataconnectSdk", { enumerable: true, get: function () { return sdk_1.doSetup; } });
28
30
  var apphosting_1 = require("../../apphosting");
29
31
  Object.defineProperty(exports, "apphosting", { enumerable: true, get: function () { return apphosting_1.doSetup; } });
30
32
  var genkit_1 = require("./genkit");
@@ -2,11 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.doSetup = void 0;
4
4
  const clc = require("colorette");
5
- const fs = require("fs");
6
5
  const logger_1 = require("../../logger");
7
6
  const prompt_1 = require("../../prompt");
8
7
  const ensureCloudResourceLocation_1 = require("../../ensureCloudResourceLocation");
9
- const RULES_TEMPLATE = fs.readFileSync(__dirname + "/../../../templates/init/storage/storage.rules", "utf8");
8
+ const templates_1 = require("../../templates");
9
+ const RULES_TEMPLATE = (0, templates_1.readTemplateSync)("init/storage/storage.rules");
10
10
  async function doSetup(setup, config) {
11
11
  setup.config.storage = {};
12
12
  (0, ensureCloudResourceLocation_1.ensureLocationSet)(setup.projectLocation, "Cloud Storage");
package/lib/init/index.js CHANGED
@@ -11,6 +11,7 @@ const featureFns = new Map([
11
11
  ["database", features.database],
12
12
  ["firestore", features.firestore],
13
13
  ["dataconnect", features.dataconnect],
14
+ ["dataconnect:sdk", features.dataconnectSdk],
14
15
  ["functions", features.functions],
15
16
  ["hosting", features.hosting],
16
17
  ["storage", features.storage],
package/lib/listFiles.js CHANGED
@@ -9,6 +9,7 @@ function listFiles(cwd, ignore = []) {
9
9
  follow: true,
10
10
  ignore: ["**/firebase-debug.log", "**/firebase-debug.*.log", ".firebase/*"].concat(ignore),
11
11
  nodir: true,
12
+ posix: true,
12
13
  });
13
14
  }
14
15
  exports.listFiles = listFiles;
@@ -1,12 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.deleteAppAndroidSha = exports.createAppAndroidSha = exports.listAppAndroidSha = exports.getAppConfig = exports.getAppConfigFile = exports.listFirebaseApps = exports.createWebApp = exports.createAndroidApp = exports.createIosApp = exports.getAppPlatform = exports.ShaCertificateType = exports.AppPlatform = exports.APP_LIST_PAGE_SIZE = void 0;
4
- const fs = require("fs");
5
4
  const apiv2_1 = require("../apiv2");
6
5
  const api_1 = require("../api");
7
6
  const error_1 = require("../error");
8
7
  const logger_1 = require("../logger");
9
8
  const operation_poller_1 = require("../operation-poller");
9
+ const templates_1 = require("../templates");
10
10
  const TIMEOUT_MILLIS = 30000;
11
11
  exports.APP_LIST_PAGE_SIZE = 100;
12
12
  const CREATE_APP_API_REQUEST_TIMEOUT_MILLIS = 15000;
@@ -182,7 +182,7 @@ function getAppConfigResourceString(appId, platform) {
182
182
  }
183
183
  function parseConfigFromResponse(responseBody, platform) {
184
184
  if (platform === AppPlatform.WEB) {
185
- const JS_TEMPLATE = fs.readFileSync(__dirname + "/../../templates/setup/web.js", "utf8");
185
+ const JS_TEMPLATE = (0, templates_1.readTemplateSync)("setup/web.js");
186
186
  return {
187
187
  fileName: WEB_CONFIG_FILE_NAME,
188
188
  fileContents: JS_TEMPLATE.replace("{/*--CONFIG--*/}", JSON.stringify(responseBody, null, 2)),
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readTemplate = exports.readTemplateSync = exports.absoluteTemplateFilePath = void 0;
4
+ const fs_1 = require("fs");
5
+ const promises_1 = require("fs/promises");
6
+ const path_1 = require("path");
7
+ const utils_1 = require("./utils");
8
+ const TEMPLATE_ENCODING = "utf8";
9
+ function absoluteTemplateFilePath(relPath) {
10
+ if ((0, utils_1.isVSCodeExtension)()) {
11
+ return (0, path_1.resolve)(__dirname, "templates", relPath);
12
+ }
13
+ return (0, path_1.resolve)(__dirname, "../templates", relPath);
14
+ }
15
+ exports.absoluteTemplateFilePath = absoluteTemplateFilePath;
16
+ function readTemplateSync(relPath) {
17
+ return (0, fs_1.readFileSync)(absoluteTemplateFilePath(relPath), TEMPLATE_ENCODING);
18
+ }
19
+ exports.readTemplateSync = readTemplateSync;
20
+ function readTemplate(relPath) {
21
+ return (0, promises_1.readFile)(absoluteTemplateFilePath(relPath), TEMPLATE_ENCODING);
22
+ }
23
+ exports.readTemplate = readTemplate;
package/lib/utils.js CHANGED
@@ -23,6 +23,7 @@ const configstore_1 = require("./configstore");
23
23
  const error_1 = require("./error");
24
24
  const logger_1 = require("./logger");
25
25
  const prompt_1 = require("./prompt");
26
+ const templates_1 = require("./templates");
26
27
  exports.IS_WINDOWS = process.platform === "win32";
27
28
  const SUCCESS_CHAR = exports.IS_WINDOWS ? "+" : "✔";
28
29
  const WARNING_CHAR = exports.IS_WINDOWS ? "!" : "⚠";
@@ -504,8 +505,7 @@ async function openInBrowser(url) {
504
505
  }
505
506
  exports.openInBrowser = openInBrowser;
506
507
  async function openInBrowserPopup(url, buttonText) {
507
- const popupPage = fs
508
- .readFileSync(path.join(__dirname, "../templates/popup.html"), { encoding: "utf-8" })
508
+ const popupPage = (0, templates_1.readTemplateSync)("popup.html")
509
509
  .replace("${url}", url)
510
510
  .replace("${buttonText}", buttonText);
511
511
  const port = await (0, portfinder_1.getPortPromise)();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "firebase-tools",
3
- "version": "13.11.4",
3
+ "version": "13.12.0",
4
4
  "description": "Command-Line Interface for Firebase",
5
5
  "main": "./lib/index.js",
6
6
  "bin": {
@@ -2,7 +2,39 @@
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "additionalProperties": false,
4
4
  "definitions": {
5
- "generatable": {
5
+ "javascriptSdk": {
6
+ "additionalProperties": true,
7
+ "type": "object",
8
+ "properties": {
9
+ "outputDir": {
10
+ "type": "string",
11
+ "description": "Path to the directory where generated files should be written to."
12
+ },
13
+ "package": {
14
+ "type": "string",
15
+ "description": "The package name to use for the generated code."
16
+ },
17
+ "packageJSONDir": {
18
+ "type": "string",
19
+ "description": "The directory containining the package.json to install the generated package in."
20
+ }
21
+ }
22
+ },
23
+ "kotlinSdk": {
24
+ "additionalProperties": true,
25
+ "type": "object",
26
+ "properties": {
27
+ "outputDir": {
28
+ "type": "string",
29
+ "description": "Path to the directory where generated files should be written to."
30
+ },
31
+ "package": {
32
+ "type": "string",
33
+ "description": "The package name to use for the generated code."
34
+ }
35
+ }
36
+ },
37
+ "swiftSdk": {
6
38
  "additionalProperties": true,
7
39
  "type": "object",
8
40
  "properties": {
@@ -30,21 +62,21 @@
30
62
  "javascriptSdk": {
31
63
  "type": "array",
32
64
  "items": {
33
- "$ref": "#/definitions/generatable"
65
+ "$ref": "#/definitions/javascriptSdk"
34
66
  },
35
67
  "description": "Configuration for a generated Javascript SDK"
36
68
  },
37
69
  "kotlinSdk": {
38
70
  "type": "array",
39
71
  "items": {
40
- "$ref": "#/definitions/generatable"
72
+ "$ref": "#/definitions/kotlinSdk"
41
73
  },
42
74
  "description": "Configuration for a generated Kotlin SDK"
43
75
  },
44
76
  "swiftSdk": {
45
77
  "type": "array",
46
78
  "items": {
47
- "$ref": "#/definitions/generatable"
79
+ "$ref": "#/definitions/swiftSdk"
48
80
  },
49
81
  "description": "Configuration for a generated Swift SDK"
50
82
  }
@@ -58,6 +58,10 @@
58
58
  "type": "string",
59
59
  "description": "The ID of the Firebase Data Connect service."
60
60
  },
61
+ "location": {
62
+ "type": "string",
63
+ "description": "The region of the Firebase Data Connect service."
64
+ },
61
65
  "connectorDirs": {
62
66
  "type": "array",
63
67
  "items": {
@@ -276,9 +276,6 @@
276
276
  {
277
277
  "additionalProperties": false,
278
278
  "properties": {
279
- "location": {
280
- "type": "string"
281
- },
282
279
  "postdeploy": {
283
280
  "anyOf": [
284
281
  {
@@ -310,7 +307,6 @@
310
307
  }
311
308
  },
312
309
  "required": [
313
- "location",
314
310
  "source"
315
311
  ],
316
312
  "type": "object"
@@ -319,9 +315,6 @@
319
315
  "items": {
320
316
  "additionalProperties": false,
321
317
  "properties": {
322
- "location": {
323
- "type": "string"
324
- },
325
318
  "postdeploy": {
326
319
  "anyOf": [
327
320
  {
@@ -353,7 +346,6 @@
353
346
  }
354
347
  },
355
348
  "required": [
356
- "location",
357
349
  "source"
358
350
  ],
359
351
  "type": "object"
@@ -64,3 +64,6 @@ node_modules/
64
64
 
65
65
  # dotenv environment variables file
66
66
  .env
67
+
68
+ # dataconnect generated files
69
+ .dataconnect
@@ -1,2 +1,13 @@
1
1
  connectorId: "__connectorId__"
2
2
  authMode: "PUBLIC"
3
+ ## ## Here's an example of how to add generated SDKs.
4
+ ## ## You'll need to replace the outputDirs with ones pointing to where you want the generated code in your app.
5
+ # generate:
6
+ # javascriptSdk:
7
+ # outputDir: <Path where you want the generated SDK to be written to, relative to this file>
8
+ # package: "@firebasegen/my-connector"
9
+ # packageJSONDir: < Optional. Path to your Javascript app's package.json>
10
+ # swiftSdk:
11
+ # outputDir: <Path where you want the generated SDK to be written to, relative to this file>
12
+ # kotlinSdk:
13
+ # outputDir: <Path where you want the generated SDK to be written to, relative to this file>
@@ -1,5 +1,6 @@
1
1
  specVersion: "v1alpha"
2
2
  serviceId: "__serviceId__"
3
+ location: "__location__"
3
4
  schema:
4
5
  source: "./schema"
5
6
  datasource: