move export to the rust side to make the interface way more clean (#5855)

* move export

Signed-off-by: Jess Frazelle <github@jessfraz.com>

testing

Signed-off-by: Jess Frazelle <github@jessfraz.com>

remove debugs

Signed-off-by: Jess Frazelle <github@jessfraz.com>

fix main

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

fices

Signed-off-by: Jess Frazelle <github@jessfraz.com>

get rid of logs

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* Convert async actions anti-pattern to fromPromise actors

* Fix tsc by removing a generic type

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* cleanup

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* cleanup

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* Update rustContext.ts

* fix

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix;

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* cleanup

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* remove weird file

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Frank Noirot <frankjohnson1993@gmail.com>
This commit is contained in:
Jess Frazelle
2025-03-18 20:25:51 -07:00
committed by GitHub
parent 3b1d1307c4
commit 859bfc7b28
20 changed files with 550 additions and 421 deletions

View File

@ -1,5 +1,4 @@
import {
emptyExecState,
errFromErrWithOutputs,
ExecState,
execStateFromRust,
@ -17,6 +16,10 @@ import { DefaultPlanes } from '@rust/kcl-lib/bindings/DefaultPlanes'
import { DefaultPlaneStr, defaultPlaneStrToKey } from 'lib/planes'
import { err } from 'lib/trap'
import { EngineCommandManager } from 'lang/std/engineConnection'
import { OutputFormat3d } from '@rust/kcl-lib/bindings/ModelingCmd'
import ModelingAppFile from './modelingAppFile'
import toast from 'react-hot-toast'
import { KclError as RustKclError } from '@rust/kcl-lib/bindings/KclError'
export default class RustContext {
private wasmInitFailed: boolean = true
@ -43,20 +46,22 @@ export default class RustContext {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.ensureWasmInit().then(async () => {
await this.create()
this.ctxInstance = await this.create()
})
}
// Create a new context instance
async create() {
async create(): Promise<Context> {
this.rustInstance = getModule()
// We need this await here, DO NOT REMOVE it even if your editor says it's
// unnecessary. The constructor of the module is async and it will not
// resolve if you don't await it.
this.ctxInstance = await new this.rustInstance.Context(
const ctxInstance = await new this.rustInstance.Context(
this.engineCommandManager,
fileSystemManager
)
return ctxInstance
}
// Execute a program.
@ -65,31 +70,26 @@ export default class RustContext {
settings: DeepPartial<Configuration>,
path?: string
): Promise<ExecState> {
await this._checkInstance()
const instance = await this._checkInstance()
if (this.ctxInstance) {
try {
const result = await this.ctxInstance.execute(
JSON.stringify(node),
path,
JSON.stringify(settings)
)
/* Set the default planes, safe to call after execute. */
const outcome = execStateFromRust(result, node)
try {
const result = await instance.execute(
JSON.stringify(node),
path,
JSON.stringify(settings)
)
/* Set the default planes, safe to call after execute. */
const outcome = execStateFromRust(result, node)
this._defaultPlanes = outcome.defaultPlanes
this._defaultPlanes = outcome.defaultPlanes
// Return the result.
return outcome
} catch (e: any) {
const err = errFromErrWithOutputs(e)
this._defaultPlanes = err.defaultPlanes
return Promise.reject(err)
}
// Return the result.
return outcome
} catch (e: any) {
const err = errFromErrWithOutputs(e)
this._defaultPlanes = err.defaultPlanes
return Promise.reject(err)
}
// You will never get here.
return Promise.reject(emptyExecState())
}
// Execute a program with in mock mode.
@ -99,28 +99,43 @@ export default class RustContext {
path?: string,
usePrevMemory?: boolean
): Promise<ExecState> {
await this._checkInstance()
const instance = await this._checkInstance()
if (this.ctxInstance) {
try {
if (usePrevMemory === undefined) {
usePrevMemory = true
}
const result = await this.ctxInstance.executeMock(
JSON.stringify(node),
path,
JSON.stringify(settings),
usePrevMemory
)
return mockExecStateFromRust(result)
} catch (e: any) {
return Promise.reject(errFromErrWithOutputs(e))
}
if (usePrevMemory === undefined) {
usePrevMemory = true
}
// You will never get here.
return Promise.reject(emptyExecState())
try {
const result = await instance.executeMock(
JSON.stringify(node),
path,
JSON.stringify(settings),
usePrevMemory
)
return mockExecStateFromRust(result)
} catch (e: any) {
return Promise.reject(errFromErrWithOutputs(e))
}
}
// Export a scene to a file.
async export(
format: DeepPartial<OutputFormat3d>,
settings: DeepPartial<Configuration>,
toastId: string
): Promise<ModelingAppFile[] | undefined> {
const instance = await this._checkInstance()
try {
return await instance.export(
JSON.stringify(format),
JSON.stringify(settings)
)
} catch (e: any) {
const parsed: RustKclError = JSON.parse(e.toString())
toast.error(parsed.msg, { id: toastId })
return
}
}
async waitForAllEngineCommands() {
@ -169,11 +184,13 @@ export default class RustContext {
}
// Helper to check if context instance exists
private async _checkInstance() {
private async _checkInstance(): Promise<Context> {
if (!this.ctxInstance) {
// Create the context instance.
await this.create()
this.ctxInstance = await this.create()
}
return this.ctxInstance
}
// Clean up resources