@@ -2,7 +2,7 @@ const { fileExists, scanForSubDirsWithPackageJson } = require("./helpers/fs");
22const { join } = require ( "path" ) ;
33const { exec } = require ( "child_process" ) ;
44const { promisify } = require ( "util" ) ;
5- const { writeFile, mkdir } = require ( "fs/promises" ) ;
5+ const { writeFile, mkdir, readFile } = require ( "fs/promises" ) ;
66const { availableParallelism } = require ( "os" ) ;
77const asyncPool = require ( "./helpers/asyncPool" ) ;
88const execAsync = promisify ( exec ) ;
@@ -45,7 +45,9 @@ async function main() {
4545async function installDependencies ( folder ) {
4646 console . log ( `Installing dependencies for ${ folder } ` ) ;
4747
48- const cmd = process . env . CI ? "npm ci" : "npm install" ;
48+ // Don't run potentially unsafe scripts during installation
49+ const flags = "--ignore-scripts" ;
50+ const cmd = process . env . CI ? `npm ci ${ flags } ` : `npm install ${ flags } ` ;
4951
5052 try {
5153 await execAsync ( cmd , {
@@ -55,6 +57,7 @@ async function installDependencies(folder) {
5557 AIKIDO_SKIP_INSTALL : "true" ,
5658 } ,
5759 } ) ;
60+ await rebuildNativePackages ( folder ) ;
5861 console . log ( `Installed dependencies for ${ folder } ` ) ;
5962 } catch ( error ) {
6063 console . error ( `Failed to install dependencies for ${ folder } ` ) ;
@@ -63,6 +66,81 @@ async function installDependencies(folder) {
6366 }
6467}
6568
69+ /**
70+ * We need to manually rebuild native packages (the ones we trust)
71+ * Because we installed dependencies with --ignore-scripts flag
72+ */
73+ async function rebuildNativePackages ( folder ) {
74+ const packageJsonPath = join ( projectRoot , folder , "package.json" ) ;
75+
76+ if ( ! ( await fileExists ( packageJsonPath ) ) ) {
77+ return ;
78+ }
79+
80+ const buffer = await readFile ( packageJsonPath , "utf-8" ) ;
81+ const pkg = JSON . parse ( buffer ) ;
82+ const allDeps = new Set ( [
83+ ...Object . keys ( pkg . dependencies ?? { } ) ,
84+ ...Object . keys ( pkg . devDependencies ?? { } ) ,
85+ ] ) ;
86+ const nativePackages = [ "sqlite3" , "better-sqlite3" ] ;
87+ const packagesToRebuild = nativePackages . filter ( ( pkgName ) =>
88+ allDeps . has ( pkgName )
89+ ) ;
90+
91+ if ( packagesToRebuild . length > 0 ) {
92+ console . log (
93+ `Rebuilding native packages for ${ folder } : ${ packagesToRebuild . join ( ", " ) } `
94+ ) ;
95+
96+ for ( const pkgName of packagesToRebuild ) {
97+ const packagePath = join ( projectRoot , folder , "node_modules" , pkgName ) ;
98+
99+ if ( pkgName === "sqlite3" ) {
100+ try {
101+ await execAsync ( "../.bin/prebuild-install -r napi" , {
102+ cwd : packagePath ,
103+ } ) ;
104+ } catch ( error ) {
105+ console . error (
106+ `❌ prebuild-install failed for ${ pkgName } in ${ folder } : ${ error . message } `
107+ ) ;
108+ try {
109+ await execAsync ( "node-gyp rebuild" , {
110+ cwd : packagePath ,
111+ } ) ;
112+ } catch ( error ) {
113+ console . error (
114+ `❌ node-gyp rebuild failed for ${ pkgName } in ${ folder } : ${ error . message } `
115+ ) ;
116+ }
117+ }
118+ }
119+
120+ if ( pkgName === "better-sqlite3" ) {
121+ try {
122+ await execAsync ( "../.bin/prebuild-install" , {
123+ cwd : packagePath ,
124+ } ) ;
125+ } catch ( error ) {
126+ console . error (
127+ `❌ prebuild-install failed for ${ pkgName } in ${ folder } : ${ error . message } `
128+ ) ;
129+ try {
130+ await execAsync ( "node-gyp rebuild --release" , {
131+ cwd : packagePath ,
132+ } ) ;
133+ } catch ( error ) {
134+ console . error (
135+ `❌ node-gyp rebuild failed for ${ pkgName } in ${ folder } : ${ error . message } `
136+ ) ;
137+ }
138+ }
139+ }
140+ }
141+ }
142+ }
143+
66144/**
67145 * Prepare the build directory
68146 */
0 commit comments