11import { mkdirSync , statSync , writeFileSync , existsSync } from 'fs'
22import fs_extra from 'fs-extra' ;
33
4- const { copySync} = fs_extra ;
4+ const { copySync, mkdirpSync } = fs_extra ;
55
66import Store from 'electron-store'
77import { promisify } from 'util'
88import { join } from 'path'
99import { app } from 'electron'
10- import { execFile , spawn } from 'child_process'
10+ import { execFile , spawn , spawnSync } from 'child_process'
1111import state from "./state.js" ;
1212import getPort , { portNumbers } from 'get-port' ;
1313import { ProcessResult } from "./ProcessResult.js" ;
1414
1515const storagePath = join ( app . getPath ( 'userData' ) , 'storage' )
1616const databasePath = join ( app . getPath ( 'userData' ) , 'database' )
1717const databaseFile = join ( databasePath , 'database.sqlite' )
18+ const bootstrapCache = join ( app . getPath ( 'userData' ) , 'bootstrap' , 'cache' )
1819const argumentEnv = getArgumentEnv ( ) ;
1920const appPath = getAppPath ( ) ;
2021
22+ mkdirpSync ( bootstrapCache ) ;
23+
24+ function runningProdVersion ( ) {
25+ //TODO: Check if the app is running the production version
26+ return existsSync ( join ( appPath , 'build' , '__nativephp_app_bundle' ) )
27+ }
28+
2129function runningSecureBuild ( ) {
2230 return existsSync ( join ( appPath , 'build' , '__nativephp_app_bundle' ) )
2331}
@@ -105,6 +113,35 @@ function callPhp(args, options, phpIniSettings = {}) {
105113 ) ;
106114}
107115
116+ function callPhpSync ( args , options , phpIniSettings = { } ) {
117+
118+ if ( args [ 0 ] === 'artisan' && runningSecureBuild ( ) ) {
119+ args . unshift ( join ( appPath , 'build' , '__nativephp_app_bundle' ) ) ;
120+ }
121+
122+ let iniSettings = Object . assign ( getDefaultPhpIniSettings ( ) , phpIniSettings ) ;
123+
124+ Object . keys ( iniSettings ) . forEach ( key => {
125+ args . unshift ( '-d' , `${ key } =${ iniSettings [ key ] } ` ) ;
126+ } ) ;
127+
128+ if ( parseInt ( process . env . SHELL_VERBOSITY ) > 0 ) {
129+ console . log ( 'Calling PHP' , state . php , args ) ;
130+ }
131+
132+ return spawnSync (
133+ state . php ,
134+ args ,
135+ {
136+ cwd : options . cwd ,
137+ env : {
138+ ...process . env ,
139+ ...options . env
140+ }
141+ }
142+ ) ;
143+ }
144+
108145function getArgumentEnv ( ) {
109146 const envArgs = process . argv . filter ( arg => arg . startsWith ( '--env.' ) ) ;
110147
@@ -164,8 +201,37 @@ function getPath(name: string) {
164201 }
165202}
166203
167- function getDefaultEnvironmentVariables ( secret , apiPort ) {
168- return {
204+ // Define an interface for the environment variables
205+ interface EnvironmentVariables {
206+ APP_ENV : string ;
207+ APP_DEBUG : string ;
208+ LARAVEL_STORAGE_PATH : string ;
209+ NATIVEPHP_STORAGE_PATH : string ;
210+ NATIVEPHP_DATABASE_PATH : string ;
211+ NATIVEPHP_API_URL : string ;
212+ NATIVEPHP_RUNNING : string ;
213+ NATIVEPHP_SECRET : string ;
214+ NATIVEPHP_USER_HOME_PATH : string ;
215+ NATIVEPHP_APP_DATA_PATH : string ;
216+ NATIVEPHP_USER_DATA_PATH : string ;
217+ NATIVEPHP_DESKTOP_PATH : string ;
218+ NATIVEPHP_DOCUMENTS_PATH : string ;
219+ NATIVEPHP_DOWNLOADS_PATH : string ;
220+ NATIVEPHP_MUSIC_PATH : string ;
221+ NATIVEPHP_PICTURES_PATH : string ;
222+ NATIVEPHP_VIDEOS_PATH : string ;
223+ NATIVEPHP_RECENT_PATH : string ;
224+ // Cache variables
225+ APP_SERVICES_CACHE ?: string ;
226+ APP_PACKAGES_CACHE ?: string ;
227+ APP_CONFIG_CACHE ?: string ;
228+ APP_ROUTES_CACHE ?: string ;
229+ APP_EVENTS_CACHE ?: string ;
230+ }
231+
232+ function getDefaultEnvironmentVariables ( secret , apiPort ) : EnvironmentVariables {
233+ // Base variables with string values (no null values)
234+ let variables : EnvironmentVariables = {
169235 APP_ENV : process . env . NODE_ENV === 'development' ? 'local' : 'production' ,
170236 APP_DEBUG : process . env . NODE_ENV === 'development' ? 'true' : 'false' ,
171237 LARAVEL_STORAGE_PATH : storagePath ,
@@ -185,6 +251,17 @@ function getDefaultEnvironmentVariables(secret, apiPort) {
185251 NATIVEPHP_VIDEOS_PATH : getPath ( 'videos' ) ,
186252 NATIVEPHP_RECENT_PATH : getPath ( 'recent' ) ,
187253 } ;
254+
255+ // Only add cache paths if in production mode
256+ if ( runningProdVersion ( ) ) {
257+ variables . APP_SERVICES_CACHE = join ( bootstrapCache , 'services.php' ) ;
258+ variables . APP_PACKAGES_CACHE = join ( bootstrapCache , 'packages.php' ) ;
259+ variables . APP_CONFIG_CACHE = join ( bootstrapCache , 'config.php' ) ;
260+ variables . APP_ROUTES_CACHE = join ( bootstrapCache , 'routes.php' ) ;
261+ variables . APP_EVENTS_CACHE = join ( bootstrapCache , 'events.php' ) ;
262+ }
263+
264+ return variables ;
188265}
189266
190267function getDefaultPhpIniSettings ( ) {
@@ -217,13 +294,21 @@ function serveApp(secret, apiPort, phpIniSettings): Promise<ProcessResult> {
217294 // Make sure the storage path is linked - as people can move the app around, we
218295 // need to run this every time the app starts
219296 if ( ! runningSecureBuild ( ) ) {
220- callPhp ( [ 'artisan' , 'storage:link' , '--force' ] , phpOptions , phpIniSettings )
297+ callPhpSync ( [ 'artisan' , 'storage:link' , '--force' ] , phpOptions , phpIniSettings )
298+ }
299+
300+ // Cache the project
301+ if ( runningProdVersion ( ) ) {
302+ console . log ( 'Caching view and routes...' ) ;
303+ // TODO: once per version
304+ callPhpSync ( [ 'artisan' , 'optimize' ] , phpOptions , phpIniSettings )
221305 }
222306
223307 // Migrate the database
224308 if ( shouldMigrateDatabase ( store ) ) {
225309 console . log ( 'Migrating database...' )
226- callPhp ( [ 'artisan' , 'migrate' , '--force' ] , phpOptions , phpIniSettings )
310+ callPhpSync ( [ 'artisan' , 'migrate' , '--force' ] , phpOptions , phpIniSettings )
311+ // TODO: fail if callPhp fails and don't store migrated version
227312 store . set ( 'migrated_version' , app . getVersion ( ) )
228313 }
229314
0 commit comments