@@ -145,7 +145,7 @@ public async Task<string> BuildAsync(string projectDir, string outputPath, bool
145145 CopyDirectory ( srcDir , Path . Combine ( publishPath , "src" ) ) ;
146146 }
147147
148- // Copy server files (.js files in root)
148+ // Copy server/entry files (.js/.ts files in root)
149149 foreach ( var jsFile in Directory . GetFiles ( projectDir , "*.js" ) )
150150 {
151151 File . Copy ( jsFile , Path . Combine ( publishPath , Path . GetFileName ( jsFile ) ) ) ;
@@ -155,6 +155,17 @@ public async Task<string> BuildAsync(string projectDir, string outputPath, bool
155155 File . Copy ( tsFile , Path . Combine ( publishPath , Path . GetFileName ( tsFile ) ) ) ;
156156 }
157157
158+ var distDir = Path . Combine ( projectDir , "dist" ) ;
159+ if ( Directory . Exists ( distDir ) )
160+ {
161+ _logger . LogInformation ( "Found dist folder, copying to publish output..." ) ;
162+ CopyDirectory ( distDir , Path . Combine ( publishPath , "dist" ) ) ;
163+ }
164+ else
165+ {
166+ _logger . LogInformation ( "No dist folder found in project; relying on Oryx build (if configured) to produce runtime output." ) ;
167+ }
168+
158169 // Create .deployment file to force Oryx build during Azure deployment
159170 await CreateDeploymentFile ( publishPath ) ;
160171
@@ -166,6 +177,11 @@ public async Task<OryxManifest> CreateManifestAsync(string projectDir, string pu
166177 _logger . LogInformation ( "Creating Oryx manifest for Node.js..." ) ;
167178
168179 var packageJsonPath = Path . Combine ( projectDir , "package.json" ) ;
180+ if ( ! File . Exists ( packageJsonPath ) )
181+ {
182+ throw new FileNotFoundException ( "package.json not found in project directory" ) ;
183+ }
184+
169185 var packageJson = await File . ReadAllTextAsync ( packageJsonPath ) ;
170186
171187 // Parse package.json to detect start command and version
@@ -177,8 +193,7 @@ public async Task<OryxManifest> CreateManifestAsync(string projectDir, string pu
177193 if ( root . TryGetProperty ( "engines" , out var engines ) &&
178194 engines . TryGetProperty ( "node" , out var nodeVersionProp ) )
179195 {
180- var versionString = nodeVersionProp . GetString ( ) ?? "18" ;
181- // Extract major version (e.g., "18.x" -> "18")
196+ var versionString = nodeVersionProp . GetString ( ) ?? "20" ;
182197 var match = System . Text . RegularExpressions . Regex . Match ( versionString , @"(\d+)" ) ;
183198 if ( match . Success )
184199 {
@@ -192,7 +207,13 @@ public async Task<OryxManifest> CreateManifestAsync(string projectDir, string pu
192207 if ( root . TryGetProperty ( "scripts" , out var scripts ) &&
193208 scripts . TryGetProperty ( "start" , out var startScript ) )
194209 {
195- startCommand = startScript . GetString ( ) ?? startCommand ;
210+ var scriptValue = startScript . GetString ( ) ;
211+ if ( ! string . IsNullOrWhiteSpace ( scriptValue ) )
212+ {
213+ // Use the script literally, same as package.json
214+ startCommand = scriptValue ;
215+ }
216+
196217 _logger . LogInformation ( "Detected start command from package.json: {Command}" , startCommand ) ;
197218 }
198219 else if ( root . TryGetProperty ( "main" , out var mainProp ) )
@@ -203,34 +224,47 @@ public async Task<OryxManifest> CreateManifestAsync(string projectDir, string pu
203224 }
204225 else
205226 {
206- // Look for common entry point files
227+ // Look for common entry point files under publish path
207228 var commonEntryPoints = new [ ] { "server.js" , "app.js" , "index.js" , "main.js" } ;
208229 foreach ( var entryPoint in commonEntryPoints )
209230 {
210231 if ( File . Exists ( Path . Combine ( publishPath , entryPoint ) ) )
211232 {
212233 startCommand = $ "node { entryPoint } ";
213- _logger . LogInformation ( "Detected entry point: {Command}" , startCommand ) ;
234+ _logger . LogInformation ( "Detected entry point in publish folder : {Command}" , startCommand ) ;
214235 break ;
215236 }
216237 }
217238 }
218239
219- var buildCommand = "npm run build" ;
220- var hasBuildScript = scripts . TryGetProperty ( "build" , out var buildScript ) ;
221- if ( hasBuildScript )
240+ // Detect build command – strictly Node
241+ string buildCommand = "" ;
242+ bool buildRequired = false ;
243+
244+ if ( root . TryGetProperty ( "scripts" , out var scriptsForBuild ) &&
245+ scriptsForBuild . TryGetProperty ( "build" , out var buildScript ) )
246+ {
247+ var buildValue = buildScript . GetString ( ) ;
248+ if ( ! string . IsNullOrWhiteSpace ( buildValue ) )
249+ {
250+ // We always call through npm so it picks up the script from package.json
251+ buildCommand = "npm run build" ;
252+ buildRequired = true ;
253+ _logger . LogInformation ( "Detected build script; using Oryx build command: {Command}" , buildCommand ) ;
254+ }
255+ }
256+ else
222257 {
223- buildCommand = buildScript . GetString ( ) ?? buildCommand ;
224- _logger . LogInformation ( "Detected build command from package.json: {Command}" , buildCommand ) ;
258+ _logger . LogInformation ( "No build script found; Oryx will only run npm install." ) ;
225259 }
226260
227261 return new OryxManifest
228262 {
229263 Platform = "nodejs" ,
230264 Version = nodeVersion ,
231265 Command = startCommand ,
232- BuildCommand = hasBuildScript ? buildCommand : "" ,
233- BuildRequired = hasBuildScript
266+ BuildCommand = buildCommand ,
267+ BuildRequired = buildRequired
234268 } ;
235269 }
236270
0 commit comments