1
1
'use client' ;
2
2
3
- import { ProcessedFileType , type NextJsProjectValidation , type ProcessedFile } from '@/app/projects/types' ;
4
- import { api } from '@/trpc/react' ;
5
- import { Routes } from '@/utils/constants' ;
6
- import { CodeProvider , createCodeProviderClient , Provider } from '@onlook/code-provider' ;
3
+ import type { ReactNode } from 'react' ;
4
+ import { createContext , useContext , useState } from 'react' ;
5
+ import { useRouter } from 'next/navigation' ;
6
+
7
+ import type { Provider } from '@onlook/code-provider' ;
8
+ import { CodeProvider , createCodeProviderClient } from '@onlook/code-provider' ;
7
9
import { NEXT_JS_FILE_EXTENSIONS , SandboxTemplates , Templates } from '@onlook/constants' ;
8
10
import { RouterType } from '@onlook/models' ;
9
11
import { generate , getAstFromContent , injectPreloadScript } from '@onlook/parser' ;
10
12
import { isRootLayoutFile , isTargetFile } from '@onlook/utility' ;
11
- import { useRouter } from 'next/navigation' ;
12
- import type { ReactNode } from 'react' ;
13
- import { createContext , useContext , useState } from 'react' ;
13
+
14
+ import type { NextJsProjectValidation , ProcessedFile } from '@/app/projects/types' ;
15
+ import { ProcessedFileType } from '@/app/projects/types' ;
16
+ import { api } from '@/trpc/react' ;
17
+ import { Routes } from '@/utils/constants' ;
14
18
15
19
export interface Project {
16
20
name : string ;
@@ -44,7 +48,11 @@ const ProjectCreationContext = createContext<ProjectCreationContextValue | undef
44
48
export function detectPortFromPackageJson ( packageJsonFile : ProcessedFile | undefined ) : number {
45
49
const defaultPort = 3000 ;
46
50
47
- if ( ! packageJsonFile || typeof packageJsonFile . content !== 'string' || packageJsonFile . type !== ProcessedFileType . TEXT ) {
51
+ if (
52
+ ! packageJsonFile ||
53
+ typeof packageJsonFile . content !== 'string' ||
54
+ packageJsonFile . type !== ProcessedFileType . TEXT
55
+ ) {
48
56
return defaultPort ;
49
57
}
50
58
@@ -80,10 +88,7 @@ interface ProjectCreationProviderProps {
80
88
totalSteps : number ;
81
89
}
82
90
83
- export const ProjectCreationProvider = ( {
84
- children,
85
- totalSteps,
86
- } : ProjectCreationProviderProps ) => {
91
+ export const ProjectCreationProvider = ( { children, totalSteps } : ProjectCreationProviderProps ) => {
87
92
const router = useRouter ( ) ;
88
93
const [ currentStep , setCurrentStep ] = useState ( 0 ) ;
89
94
const [ projectData , setProjectDataState ] = useState < Partial < Project > > ( {
@@ -116,7 +121,7 @@ export const ProjectCreationProvider = ({
116
121
}
117
122
118
123
const packageJsonFile = projectData . files . find (
119
- ( f ) => f . path . endsWith ( 'package.json' ) && f . type === ProcessedFileType . TEXT
124
+ ( f ) => f . path . endsWith ( 'package.json' ) && f . type === ProcessedFileType . TEXT ,
120
125
) ;
121
126
122
127
const template = SandboxTemplates [ Templates . BLANK ] ;
@@ -176,32 +181,38 @@ export const ProjectCreationProvider = ({
176
181
const validateNextJsProject = async (
177
182
files : ProcessedFile [ ] ,
178
183
) : Promise < NextJsProjectValidation > => {
179
- const packageJsonFile = files . find ( ( f ) => f . path . endsWith ( 'package.json' ) && f . type === ProcessedFileType . TEXT ) ;
184
+ const packageJsonFile = files . find (
185
+ ( f ) => f . path . endsWith ( 'package.json' ) && f . type === ProcessedFileType . TEXT ,
186
+ ) ;
180
187
181
- if ( ! packageJsonFile ) {
188
+ if ( ! packageJsonFile ?. content || typeof packageJsonFile . content !== 'string' ) {
182
189
return { isValid : false , error : 'No package.json found' } ;
183
190
}
184
191
185
192
try {
186
- const packageJson = JSON . parse ( packageJsonFile . content as string ) ;
187
- const hasNext = packageJson . dependencies ?. next || packageJson . devDependencies ?. next ;
193
+ const packageJson = JSON . parse ( packageJsonFile . content ) as Record < string , unknown > ;
194
+ const dependencies = packageJson . dependencies as Record < string , string > | undefined ;
195
+ const devDependencies = packageJson . devDependencies as
196
+ | Record < string , string >
197
+ | undefined ;
198
+ const hasNext = dependencies ?. next ?? devDependencies ?. next ;
188
199
if ( ! hasNext ) {
189
200
return { isValid : false , error : 'Next.js not found in dependencies' } ;
190
201
}
191
202
192
- const hasReact = packageJson . dependencies ?. react || packageJson . devDependencies ?. react ;
203
+ const hasReact = dependencies ?. react ?? devDependencies ?. react ;
193
204
if ( ! hasReact ) {
194
205
return { isValid : false , error : 'React not found in dependencies' } ;
195
206
}
196
207
197
208
let routerType : RouterType = RouterType . PAGES ;
198
209
199
- const hasAppLayout = files . some (
200
- ( f ) => isTargetFile ( f . path , {
210
+ const hasAppLayout = files . some ( ( f ) =>
211
+ isTargetFile ( f . path , {
201
212
fileName : 'layout' ,
202
213
targetExtensions : NEXT_JS_FILE_EXTENSIONS ,
203
214
potentialPaths : [ 'app' , 'src/app' ] ,
204
- } )
215
+ } ) ,
205
216
) ;
206
217
207
218
if ( hasAppLayout ) {
@@ -226,7 +237,6 @@ export const ProjectCreationProvider = ({
226
237
}
227
238
} ;
228
239
229
-
230
240
const nextStep = ( ) => {
231
241
if ( currentStep < totalSteps - 2 ) {
232
242
// -2 because we have 2 final steps
@@ -235,7 +245,7 @@ export const ProjectCreationProvider = ({
235
245
} else {
236
246
// This is the final step, so we should finalize the project
237
247
setCurrentStep ( ( prev ) => prev + 1 ) ;
238
- finalizeProject ( ) ;
248
+ void finalizeProject ( ) ;
239
249
}
240
250
} ;
241
251
@@ -260,7 +270,7 @@ export const ProjectCreationProvider = ({
260
270
261
271
const retry = ( ) => {
262
272
setError ( null ) ;
263
- finalizeProject ( ) ;
273
+ void finalizeProject ( ) ;
264
274
} ;
265
275
266
276
const cancel = ( ) => {
@@ -323,10 +333,7 @@ export const uploadToSandbox = async (files: ProcessedFile[], provider: Provider
323
333
const modifiedAst = injectPreloadScript ( ast ) ;
324
334
content = generate ( modifiedAst , { } , content ) . code ;
325
335
} catch ( parseError ) {
326
- console . warn (
327
- 'Failed to add script config to layout.tsx:' ,
328
- parseError ,
329
- ) ;
336
+ console . warn ( 'Failed to add script config to layout.tsx:' , parseError ) ;
330
337
}
331
338
}
332
339
await provider . writeFile ( {
0 commit comments