simondotm / nx-firebase

Firebase plugin for Nx Monorepos
https://www.npmjs.com/package/@simondotm/nx-firebase
MIT License
175 stars 31 forks source link

--watch seems to have no effect #41

Closed johngrimsey closed 1 year ago

johngrimsey commented 2 years ago

This lib is great!

I have created an app named functions.

nx run functions:build --watch

Is building but finishing up without watching. Am I doing something wrong? The functions:emulate behaves the same. It builds fine and launches the emulator suite without issue but it doesn't watch for changes.

Thanks

dpietrzyk commented 2 years ago

Is there any update / temporary workaround for this issue? :/

dpietrzyk commented 2 years ago

A nice workaround for this issue is to create a custom nx-watch executor and use it instead of --watch flag: https://gist.github.com/jhesgodi/2d530753c551ace665a8c3010d3a719c

johngrimsey commented 2 years ago

@simondotm Heads-up, at present iterating on Cloud Functions code is a little painful:

Would be amazing to be able to run a watched build and emulators in one command, and have functions restart gracefully when functions code is changed 🙏

romshiri commented 2 years ago

Any elegant solution for that? @dpietrzyk mind sharing a bit more on what you did?

LaysDragon commented 1 year ago

Build watch stop working for @simondotm/nx-firebase@0.3.3, nx@13.10.6 and typescript@4.6.2 in my project environment.Seems the api change somehow. I make a patch for this

replace

const result = yield compile_typescript_files_1.default(normalizedOptions, context, appRoot, dependencies);

with

        normalizedOptions.deleteOutputPath = false;
        let result = yield compile_typescript_files_1.default(normalizedOptions, context, appRoot, dependencies);
        if(normalizedOptions.watch){
          result = { success: true };
          yield new Promise((resolve)=>{
            ['exit','SIGTERM','SIGINT','SIGHUP'].forEach(signal=>process.once(signal, ()=>resolve()));
          });
        }
        return Object.assign(Object.assign({}, result), { outputPath: normalizedOptions.outputPath });

replace

      return compilation_1.compileTypeScript({
        outputPath: options.normalizedOutputPath,
        projectName: context.projectName,
        projectRoot: libRoot,
        tsConfig: tsConfigPath,
        deleteOutputPath: options.deleteOutputPath,
        rootDir: options.srcRootForCompilationRoot,
        watch: options.watch,
      });

with

    if(options.watch){
      return compilation_1.compileTypeScriptWatcher({
        outputPath: options.normalizedOutputPath,
        projectName: context.projectName,
        projectRoot: libRoot,
        tsConfig: tsConfigPath,
        deleteOutputPath: options.deleteOutputPath,
        rootDir: options.srcRootForCompilationRoot,
        watch: options.watch,
    });
    }else{
      return compilation_1.compileTypeScript({
        outputPath: options.normalizedOutputPath,
        projectName: context.projectName,
        projectRoot: libRoot,
        tsConfig: tsConfigPath,
        deleteOutputPath: options.deleteOutputPath,
        rootDir: options.srcRootForCompilationRoot,
        watch: options.watch,
    });
    }

notice Its also need to use patch from #44 and #48 to make this build executor complete working under nx 13 Here is my version of final patch include fix watch issue

@simondotm+nx-firebase+0.3.3.patch

diff --git a/node_modules/@simondotm/nx-firebase/src/executors/build/build.js b/node_modules/@simondotm/nx-firebase/src/executors/build/build.js
index ba14795..838601e 100644
--- a/node_modules/@simondotm/nx-firebase/src/executors/build/build.js
+++ b/node_modules/@simondotm/nx-firebase/src/executors/build/build.js
@@ -15,7 +15,7 @@ const normalize_options_1 = require("./node/package/utils/normalize-options");
 const cli_1 = require("./node/package/utils/cli");
 const workspace_1 = require("@nrwl/workspace");
 const fs_extra_1 = require("fs-extra");
-const fileutils_1 = require("@nrwl/workspace/src/utilities/fileutils");
+const { copy } = require("fs-extra/lib/copy");
 const ENABLE_DEBUG = false;
 function debugLog(...args) {
     if (ENABLE_DEBUG) {
@@ -42,7 +42,7 @@ function runExecutor(options, context) {
         debugLog("Running Executor for Firebase Build for project '" + context.projectName + "'");
         debugLog('options=', options);
         // get the project graph; returns an object containing all nodes in the workspace, files, and dependencies
-        const projGraph = project_graph_1.createProjectGraph();
+        const projGraph = yield project_graph_1.createProjectGraphAsync('4.0');
         // nx firebase functions are essentially @nrwl/node:package libraries, but are added to the project
         // as applications as they are fundamentally the deployable "application" output of a build pipeline.
         // Due to this, we can import standard node libraries as dependencies from within the workspace
@@ -69,7 +69,7 @@ function runExecutor(options, context) {
         // there aren't really any assets needed for firebase functions
         // but left here for compatibility with node:package
         debugLog("- Copying functions assets");
-        yield assets_1.copyAssetFiles(normalizedOptions.files);
+        yield Promise.all(normalizedOptions.files.map((file) => copy(file.input, file.output)));
         // ensure the output package file has typings and a correct "main" entry point
         update_package_json_1.default(normalizedOptions, context);
         // Process Firebase Functions dependencies
@@ -93,7 +93,7 @@ function runExecutor(options, context) {
             return node;
         });
         const nonBuildableDeps = projectDeps.filter((dep) => {
-            return ((dep.type === 'lib') && (dep.data.targets['build'] === undefined));
+            return ((dep) && (dep.type === 'lib') && (dep.data.targets['build'] === undefined));
         });
         //console.log("nonBuildableDeps=", JSON.stringify(nonBuildableDeps, null, 3));
         // automatically add any dependencies this application has to the output "package.json"
@@ -144,9 +144,9 @@ function runExecutor(options, context) {
         const incompatibleNestedDeps = [];
         // rewrite references to library packages in the functions package.json
         // to be local package references to the copies we made
-        const functionsPackageFile = `${options.outputPath}/package.json`;
+        const functionsPackageFile = `${options.outputPath}/package.json`
+        const functionsPackageJson = devkit_1.readJsonFile(functionsPackageFile);
         debugLog("- functions PackageFile=" + functionsPackageFile);
-        const functionsPackageJson = workspace_1.readJsonFile(functionsPackageFile);
         const functionsPackageDeps = functionsPackageJson.dependencies;
         if (functionsPackageDeps) {
             debugLog("- Updating local dependencies for Firebase functions package.json");
@@ -164,7 +164,7 @@ function runExecutor(options, context) {
                 }
             }
         }
-        fileutils_1.writeJsonFile(functionsPackageFile, functionsPackageJson);
+        devkit_1.writeJsonFile(functionsPackageFile, functionsPackageJson);
         devkit_1.logger.log("- Updated firebase functions package.json");
         debugLog("functions package deps = ", JSON.stringify(functionsPackageDeps, null, 3));
         // Final dep check before we compile for:
@@ -192,7 +192,13 @@ function runExecutor(options, context) {
         // So that we can support --watch (https://github.com/simondotm/nx-firebase/issues/11)
         // We run tsc as the last step, but we disable `deleteOutputPath` so that our previous steps are not deleted.
         normalizedOptions.deleteOutputPath = false;
-        const result = yield compile_typescript_files_1.default(normalizedOptions, context, appRoot, dependencies);
+        let result = yield compile_typescript_files_1.default(normalizedOptions, context, appRoot, dependencies);
+        if(normalizedOptions.watch){
+          result = { success: true };
+          yield new Promise((resolve)=>{
+            ['exit','SIGTERM','SIGINT','SIGHUP'].forEach(signal=>process.once(signal, ()=>resolve()));
+          });
+        }
         return Object.assign(Object.assign({}, result), { outputPath: normalizedOptions.outputPath });
     });
 }
diff --git a/node_modules/@simondotm/nx-firebase/src/executors/build/node/package/package.js b/node_modules/@simondotm/nx-firebase/src/executors/build/node/package/package.js
index a3218e7..43a4dc7 100644
--- a/node_modules/@simondotm/nx-firebase/src/executors/build/node/package/package.js
+++ b/node_modules/@simondotm/nx-firebase/src/executors/build/node/package/package.js
@@ -11,7 +11,7 @@ const normalize_options_1 = require("./utils/normalize-options");
 const cli_1 = require("./utils/cli");
 function packageExecutor(options, context) {
     return tslib_1.__awaiter(this, void 0, void 0, function* () {
-        const projGraph = project_graph_1.createProjectGraph();
+        const projGraph = yield project_graph_1.createProjectGraphAsync('4.0');
         const libRoot = context.workspace.projects[context.projectName].root;
         const normalizedOptions = normalize_options_1.default(options, context, libRoot);
         const { target, dependencies } = buildable_libs_utils_1.calculateProjectDependencies(projGraph, context.root, context.projectName, context.targetName, context.configurationName);
diff --git a/node_modules/@simondotm/nx-firebase/src/executors/build/node/package/utils/cli.js b/node_modules/@simondotm/nx-firebase/src/executors/build/node/package/utils/cli.js
index db9311d..4501336 100644
--- a/node_modules/@simondotm/nx-firebase/src/executors/build/node/package/utils/cli.js
+++ b/node_modules/@simondotm/nx-firebase/src/executors/build/node/package/utils/cli.js
@@ -1,11 +1,11 @@
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
-const fileutils_1 = require("@nrwl/workspace/src/utilities/fileutils");
+const devkit_1 = require("@nrwl/devkit");
 const fs_extra_1 = require("fs-extra");
 function addCliWrapper(options, context) {
-    const packageJson = fileutils_1.readJsonFile(`${options.outputPath}/package.json`);
+    const packageJson = devkit_1.readJsonFile(`${options.outputPath}/package.json`);
     const binFile = `${options.outputPath}/index.bin.js`;
-    fileutils_1.writeToFile(binFile, `#!/usr/bin/env node
+    devkit_1.writeToFile(binFile, `#!/usr/bin/env node
 'use strict';
 require('${packageJson.main}');
 `);
@@ -13,7 +13,7 @@ require('${packageJson.main}');
     packageJson.bin = {
         [context.projectName]: './index.bin.js',
     };
-    fileutils_1.writeJsonFile(`${options.outputPath}/package.json`, packageJson);
+    devkit_1.writeJsonFile(`${options.outputPath}/package.json`, packageJson);
 }
 exports.default = addCliWrapper;
 //# sourceMappingURL=cli.js.map
\ No newline at end of file
diff --git a/node_modules/@simondotm/nx-firebase/src/executors/build/node/package/utils/compile-typescript-files.js b/node_modules/@simondotm/nx-firebase/src/executors/build/node/package/utils/compile-typescript-files.js
index adfea2c..f0c3e65 100644
--- a/node_modules/@simondotm/nx-firebase/src/executors/build/node/package/utils/compile-typescript-files.js
+++ b/node_modules/@simondotm/nx-firebase/src/executors/build/node/package/utils/compile-typescript-files.js
@@ -8,7 +8,8 @@ function compileTypeScriptFiles(options, context, libRoot, projectDependencies)
     if (projectDependencies.length > 0) {
         tsConfigPath = buildable_libs_utils_1.createTmpTsConfig(tsConfigPath, context.root, libRoot, projectDependencies);
     }
-    return compilation_1.compileTypeScript({
+    if(options.watch){
+      return compilation_1.compileTypeScriptWatcher({
         outputPath: options.normalizedOutputPath,
         projectName: context.projectName,
         projectRoot: libRoot,
@@ -16,7 +17,19 @@ function compileTypeScriptFiles(options, context, libRoot, projectDependencies)
         deleteOutputPath: options.deleteOutputPath,
         rootDir: options.srcRootForCompilationRoot,
         watch: options.watch,
-    });
+      });
+    }else{
+      return compilation_1.compileTypeScript({
+        outputPath: options.normalizedOutputPath,
+        projectName: context.projectName,
+        projectRoot: libRoot,
+        tsConfig: tsConfigPath,
+        deleteOutputPath: options.deleteOutputPath,
+        rootDir: options.srcRootForCompilationRoot,
+        watch: options.watch,
+      });
+    }
+
 }
 exports.default = compileTypeScriptFiles;
 //# sourceMappingURL=compile-typescript-files.js.map
diff --git a/node_modules/@simondotm/nx-firebase/src/executors/build/node/package/utils/update-package-json.js b/node_modules/@simondotm/nx-firebase/src/executors/build/node/package/utils/update-package-json.js
index 533b391..32b713a 100644
--- a/node_modules/@simondotm/nx-firebase/src/executors/build/node/package/utils/update-package-json.js
+++ b/node_modules/@simondotm/nx-firebase/src/executors/build/node/package/utils/update-package-json.js
@@ -1,19 +1,19 @@
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
-const fileutils_1 = require("@nrwl/workspace/src/utilities/fileutils");
+const devkit_1 = require("@nrwl/devkit");
 const path_1 = require("path");
 function updatePackageJson(options, context) {
     const mainFile = path_1.basename(options.main).replace(/\.[tj]s$/, '');
     const typingsFile = `${mainFile}.d.ts`;
     const mainJsFile = `${mainFile}.js`;
-    const packageJson = fileutils_1.readJsonFile(path_1.join(context.root, options.packageJson));
+    const packageJson = devkit_1.readJsonFile(path_1.join(context.root, options.packageJson));
     if (!packageJson.main) {
         packageJson.main = `${options.relativeMainFileOutput}${mainJsFile}`;
     }
     if (!packageJson.typings) {
         packageJson.typings = `${options.relativeMainFileOutput}${typingsFile}`;
     }
-    fileutils_1.writeJsonFile(`${options.outputPath}/package.json`, packageJson);
+    devkit_1.writeJsonFile(`${options.outputPath}/package.json`, packageJson);
 }
 exports.default = updatePackageJson;
 //# sourceMappingURL=update-package-json.js.map
\ No newline at end of file
LaysDragon commented 1 year ago

@simondotm Heads-up, at present iterating on Cloud Functions code is a little painful:

  • Change code
  • Run build command (watch not working)
  • Existing emulators running must be stopped as they don't like rebuilt code
  • Emulator processes don't terminate gracefully
  • Use lsof to kill processes
  • Restart emulators

Would be amazing to be able to run a watched build and emulators in one command, and have functions restart gracefully

I move the comment to #40,its more suitable for that issue

johngrimsey commented 1 year ago

Thanks @LaysDragon for your effort on this! 🙏 Will try this out next opportunity.

LaysDragon commented 1 year ago

Thanks @LaysDragon for your effort on this! 🙏 Will try this out next opportunity.

I find out the #20 problem later,I fix the watch problem but its still wont respond the library dependency update. So I use nx-watch instead eventually. 😂 Its too hard to fix that problem with a simple patch. Oh but if you don't have lib dependency,its good enough through.

simondotm commented 1 year ago

Linking to #95