Skip to content

Commit

Permalink
bad sketches dont block run (#471)
Browse files Browse the repository at this point in the history
* Add try catch when initializing user code

* refactor error handling

* update comment

---------

Co-authored-by: Alex Kempton <alex@funwithtriangles.net>
  • Loading branch information
cale-bradbury and funwithtriangles authored Dec 9, 2024
1 parent 0920ff4 commit 7e98aad
Showing 3 changed files with 71 additions and 39 deletions.
26 changes: 20 additions & 6 deletions packages/engine/src/HedronEngine.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { listenToStore } from './storeListener'
import { importSketchModule } from './importSketchModule'
import { Result } from './types'
import { stripForSave } from '@utils/stripForSave'
import { Renderer } from '@world/Renderer'
import { SketchManager } from '@world/SketchManager'
import { createDebugScene } from '@world/debugScene'
import { EngineData } from '@store/types'
import { EngineData, SketchModuleItem } from '@store/types'
import { getSketchesOfModuleId } from '@store/selectors/getSketchesOfModuleId'
import { createEngineStore, EngineStore } from '@store/engineStore'

@@ -42,21 +43,34 @@ export class HedronEngine {
this.store.setState({ isSketchModulesReady: true })
}

public async addSketchModule(moduleId: string) {
public async addSketchModule(moduleId: string): Promise<Result<SketchModuleItem>> {
if (!this.sketchesUrl) throw new Error('Sketches URL not ready')

const moduleItem = await importSketchModule(this.sketchesUrl, moduleId)
const result = await importSketchModule(this.sketchesUrl, moduleId)

if (!result.success) {
// TODO: Show UI error here (engine needs to have some "error" state slice)
return result
}

const moduleItem = result.data
this.store.getState().setSketchModuleItem(moduleItem)

return moduleItem
return result
}

public removeSketchModule = async (moduleId: string): Promise<void> => {
this.store.getState().deleteSketchModule(moduleId)
}

public async reimportSketchModuleAndReloadSketches(moduleId: string) {
const moduleItem = await this.addSketchModule(moduleId)
public async reimportSketchModuleAndReloadSketches(moduleId: string): Promise<void> {
const result = await this.addSketchModule(moduleId)

if (!result.success) {
return
}

const moduleItem = result.data

const sketchesToRefresh = getSketchesOfModuleId(this.store.getState(), moduleId)

81 changes: 48 additions & 33 deletions packages/engine/src/importSketchModule.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,61 @@
import { Result } from './types'
import { SketchConfig, SketchModule, SketchModuleItem } from '@store/types'
import { createUniqueId } from '@utils/createUniqueId'

export const importSketchModule = async (
baseUrl: string,
moduleId: string,
): Promise<SketchModuleItem> => {
const cacheBust = createUniqueId()
): Promise<Result<SketchModuleItem>> => {
try {
const cacheBust = createUniqueId()

// Get the sketch module
const sketchPath = `${baseUrl}/${moduleId}/index.js?${cacheBust}`
if ((await fetch(sketchPath)).status !== 200) {
return Promise.reject(`Sketch module not found: ${sketchPath}`)
}
const sketchModule = await import(/* @vite-ignore */ sketchPath)
const module: SketchModule = sketchModule.default
// Get the sketch module
const sketchPath = `${baseUrl}/${moduleId}/index.js?${cacheBust}`
if ((await fetch(sketchPath)).status !== 200) {
return Promise.reject(`Sketch module not found: ${sketchPath}`)
}
const sketchModule = await import(/* @vite-ignore */ sketchPath)
const module: SketchModule = sketchModule.default

// Get the sketch config
const configPath = `${baseUrl}/${moduleId}/config.js?${cacheBust}`
let config: SketchConfig
if ((await fetch(configPath)).status !== 200) {
// No config file found
// Try instancing the sketch, and call getConfig() on it
const tempModule = new module()
config = tempModule.getConfig?.()
if (!config) {
return Promise.reject(
`Sketch config not found: ${configPath} and no valid getConfig() function found in sketch`,
)
// Get the sketch config
const configPath = `${baseUrl}/${moduleId}/config.js?${cacheBust}`
let config: SketchConfig
if ((await fetch(configPath)).status !== 200) {
// No config file found
// Try instancing the sketch, and call getConfig() on it
const tempModule = new module()
config = tempModule.getConfig?.()
if (!config) {
return Promise.reject(
`Sketch config not found: ${configPath} and no valid getConfig() function found in sketch`,
)
}
} else {
const configModule = await import(/* @vite-ignore */ configPath)
config = configModule.default
}
} else {
const configModule = await import(/* @vite-ignore */ configPath)
config = configModule.default
}

// A config could be missing a title, but it is a required parameter
if (!config.title) {
config.title = moduleId
}
// A config could be missing a title, but it is a required parameter
if (!config.title) {
config.title = moduleId
}

return {
success: true,
error: undefined,
data: {
moduleId,
config,
module,
},
}
} catch (error) {
console.error(error)

return {
moduleId,
config,
module,
return {
data: undefined,
success: false,
error: `[HEDRON] Sketch module failed to import: ${moduleId}`,
}
}
}
3 changes: 3 additions & 0 deletions packages/engine/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export type Result<T> =
| { success: true; data: T; error: undefined }
| { success: false; error: string; data: undefined }

0 comments on commit 7e98aad

Please sign in to comment.