Repository: railwayapp/nixpacks (rust)

Issue:
node provider: Install additional packages if `node-gyp` is detected
When `node-gyp` is detected as a dependency, install additional packages such as
- `gccStdenv`
- `python39`

`node-gyp` requires these packages to be available in order to build native packages.

https://github.com/nodejs/node-gyp#on-unix

Pull request description:
Install additional packages when node-gyp or node-pre-gyp packages are present
<!-- Thanks for sending a pull request! -->
<!-- Please add a useful description explaining what this PR does -->

This PR fixes #603. We should add support for building `canvas` from source. See issue #604 regarding that.

<!-- PR Checklist  -->
<!-- - [ ] Tests are added/updated if needed  -->
<!-- - [ ] Docs are updated if needed  -->


Patch:
diff --git a/.cargo/config b/.cargo/config
new file mode 100644
index 0000000..0d4bc40
--- /dev/null
+++ b/.cargo/config
@@ -0,0 +1,2 @@
+[alias]
+generate_plan_test = "test --package nixpacks --lib --test generate_plan_tests"
\ No newline at end of file
diff --git a/examples/node-canvas/index.js b/examples/node-canvas/index.js
index e8e31fe..4e96657 100644
--- a/examples/node-canvas/index.js
+++ b/examples/node-canvas/index.js
@@ -1,2 +1,11 @@
-require("canvas");
-console.log("Hello from Node canvas");
+const canvas = require('canvas');
+
+const box = canvas.createCanvas(100, 100);
+
+const fs = require('fs')
+const out = fs.createWriteStream(__dirname + '/test.png')
+const stream = box.createPNGStream()
+stream.pipe(out)
+out.on('finish', () =>  console.log('The PNG file was created.'))
+
+console.log("Hello from Node canvas")
\ No newline at end of file
diff --git a/src/providers/node/mod.rs b/src/providers/node/mod.rs
index 3bd24f2..7464209 100644
--- a/src/providers/node/mod.rs
+++ b/src/providers/node/mod.rs
@@ -73,8 +73,24 @@ impl Provider for NodeProvider {
                 "libxshmfence1".to_string(),
                 "libglu1".to_string(),
             ]);
-        } else if NodeProvider::uses_node_dependency(app, "canvas") {
+        }
+
+        if NodeProvider::uses_node_dependency(app, "canvas") {
             setup.add_pkgs_libs(vec!["libuuid".to_string(), "libGL".to_string()]);
+            setup.add_apt_pkgs(vec![
+                "build-essential".into(),
+                "libcairo2-dev".into(),
+                "libpango1.0-dev".into(),
+                "libjpeg-dev".into(),
+                "libgif-dev".into(),
+                "librsvg2-dev".into(),
+            ]);
+        }
+
+        if NodeProvider::uses_node_dependency(app, "node-gyp")
+            || NodeProvider::uses_node_dependency(app, "node-pre-gyp")
+        {
+            setup.add_nix_pkgs(&[Pkg::new("python39"), Pkg::new("gccStdenv")]);
         }
 
         // Install


Test patch:
diff --git a/tests/snapshots/generate_plan_tests__node_canvas.snap b/tests/snapshots/generate_plan_tests__node_canvas.snap
index ca61444..981f5b3 100644
--- a/tests/snapshots/generate_plan_tests__node_canvas.snap
+++ b/tests/snapshots/generate_plan_tests__node_canvas.snap
@@ -40,7 +40,9 @@ expression: plan
       "name": "setup",
       "nixPkgs": [
         "nodejs-16_x",
-        "npm-8_x"
+        "npm-8_x",
+        "python39",
+        "gccStdenv"
       ],
       "nixLibs": [
         "libuuid",
@@ -49,7 +51,15 @@ expression: plan
       "nixOverlays": [
         "https://github.com/railwayapp/nix-npm-overlay/archive/main.tar.gz"
       ],
-      "nixpkgsArchive": "[archive]"
+      "nixpkgsArchive": "[archive]",
+      "aptPkgs": [
+        "build-essential",
+        "libcairo2-dev",
+        "libpango1.0-dev",
+        "libjpeg-dev",
+        "libgif-dev",
+        "librsvg2-dev"
+      ]
     }
   },
   "start": {
diff --git a/tests/snapshots/generate_plan_tests__node_nx.snap b/tests/snapshots/generate_plan_tests__node_nx.snap
index 48768ed..3b4c6b1 100644
--- a/tests/snapshots/generate_plan_tests__node_nx.snap
+++ b/tests/snapshots/generate_plan_tests__node_nx.snap
@@ -45,7 +45,9 @@ expression: plan
       "name": "setup",
       "nixPkgs": [
         "nodejs-16_x",
-        "npm-8_x"
+        "npm-8_x",
+        "python39",
+        "gccStdenv"
       ],
       "nixLibs": [
         "libuuid",
@@ -54,7 +56,15 @@ expression: plan
       "nixOverlays": [
         "https://github.com/railwayapp/nix-npm-overlay/archive/main.tar.gz"
       ],
-      "nixpkgsArchive": "[archive]"
+      "nixpkgsArchive": "[archive]",
+      "aptPkgs": [
+        "build-essential",
+        "libcairo2-dev",
+        "libpango1.0-dev",
+        "libjpeg-dev",
+        "libgif-dev",
+        "librsvg2-dev"
+      ]
     }
   },
   "start": {
diff --git a/tests/snapshots/generate_plan_tests__node_yarn_berry.snap b/tests/snapshots/generate_plan_tests__node_yarn_berry.snap
index 0838564..99adcda 100644
--- a/tests/snapshots/generate_plan_tests__node_yarn_berry.snap
+++ b/tests/snapshots/generate_plan_tests__node_yarn_berry.snap
@@ -43,7 +43,9 @@ expression: plan
       "name": "setup",
       "nixPkgs": [
         "nodejs-16_x",
-        "yarn-1_x"
+        "yarn-1_x",
+        "python39",
+        "gccStdenv"
       ],
       "nixOverlays": [
         "https://github.com/railwayapp/nix-npm-overlay/archive/main.tar.gz"