At implementing login and getUser

This commit is contained in:
49lf
2024-07-24 21:37:29 -04:00
parent 0b454939b3
commit 118ac33ebe
16 changed files with 264 additions and 176 deletions

View File

@ -60,6 +60,9 @@ root.render(
reportWebVitals()
const runTauriUpdater = async () => {
console.log('STUB: @pierre')
return
try {
const update = await check()
if (update && update.available) {

View File

@ -15,14 +15,16 @@ class FileSystemManager {
}
async join(dir: string, path: string): Promise<string> {
return window.electron.ipcRenderer.invoke('join', [dir, path]);
return window.electron.ipcRenderer.invoke('join', [dir, path])
}
async readFile(path: string): Promise<Uint8Array | void> {
// Using local file system only works from desktop.
if (!isDesktop()) {
return Promise.reject(
new Error('This function can only be called from the desktop application')
new Error(
'This function can only be called from the desktop application'
)
)
}
@ -39,7 +41,9 @@ class FileSystemManager {
// Using local file system only works from desktop.
if (!isDesktop()) {
return Promise.reject(
new Error('This function can only be called from the desktop application')
new Error(
'This function can only be called from the desktop application'
)
)
}
@ -56,7 +60,9 @@ class FileSystemManager {
// Using local file system only works from desktop.
if (!isDesktop()) {
return Promise.reject(
new Error('This function can only be called from the desktop application')
new Error(
'This function can only be called from the desktop application'
)
)
}
@ -65,7 +71,8 @@ class FileSystemManager {
return Promise.reject(new Error(`Error joining dir: ${error}`))
})
.then((filepath) => {
return window.electron.ipcRenderer.invoke('readdir', [filepath])
return window.electron.ipcRenderer
.invoke('readdir', [filepath])
.catch((error) => {
return Promise.reject(new Error(`Error reading dir: ${error}`))
})

View File

@ -17,6 +17,7 @@ import init, {
parse_project_settings,
default_project_settings,
parse_project_route,
serialize_project_settings,
} from '../wasm-lib/pkg/wasm_lib'
import { KCLError } from './errors'
import { KclError as RustKclError } from '../wasm-lib/kcl/bindings/KclError'
@ -558,7 +559,7 @@ export function tomlStringify(toml: any): string | Error {
return toml_stringify(JSON.stringify(toml))
}
export function defaultAppSettings(): Configuration | Error {
export function defaultAppSettings(): Configuration {
return default_app_settings()
}
@ -582,3 +583,79 @@ export function parseProjectRoute(
): ProjectRoute | Error {
return parse_project_route(JSON.stringify(configuration), route_str)
}
const DEFAULT_HOST = 'https://api.zoo.dev'
const SETTINGS_FILE_NAME = 'settings.toml'
const PROJECT_SETTINGS_FILE_NAME = 'project.toml'
const PROJECT_FOLDER = 'zoo-modeling-app-projects'
const getAppSettingsFilePath = async () => {
const appConfig = await window.electron.getPath('appData')
const fullPath = window.electron.path.join(
appConfig,
window.electron.packageJson.name
)
try {
await window.electron.exists(fullPath)
} catch (e) {
// File/path doesn't exist
if (e.code === 'ENOENT') {
window.electron.mkdir(fullPath, { recursive: true })
}
}
return window.electron.path.join(fullPath, SETTINGS_FILE_NAME)
}
const getInitialDefaultDir = async () => {
const dir = await window.electron.getPath('documents')
return window.electron.path.join(dir, PROJECT_FOLDER)
}
export const readAppSettingsFile = async () => {
let settingsPath = await getAppSettingsFilePath()
try {
await window.electron.exists(settingsPath)
} catch (e) {
if (e === 'ENOENT') {
const config = defaultAppSettings()
config.settings.project.directory = await getInitialDefaultDir()
console.log(config)
return config
}
}
const configToml = await window.electron.readFile(settingsPath)
const configObj = parseProjectSettings(configStr)
return configObj
}
export const writeAppSettingsFile = async () => {
debugger
console.log("STUB")
}
let appStateStore = undefined
export const getState = async (): Promise<ProjectState | undefined> => {
return Promise.resolve(appStateStore)
}
export const setState = async (
state: ProjectState | undefined
): Promise<void> => {
appStateStore = state
}
const initializeProjectDirectory = () => {
debugger
console.log('STUB')
}
export const login = () => {
debugger
console.log('STUB')
}
export const getUser = (token: string, host: string) => {
debugger
console.log("STUB")
}

View File

@ -8,21 +8,14 @@ import { ProjectRoute } from 'wasm-lib/kcl/bindings/ProjectRoute'
import { components } from './machine-api'
import { isDesktop } from './isDesktop'
// Get the app state from desktop.
export async function getState(): Promise<ProjectState | undefined> {
if (!isDesktop()) {
return undefined
}
return await window.electron.ipcRenderer.invoke('get_state')
}
// Set the app state in desktop.
export async function setState(state: ProjectState | undefined): Promise<void> {
if (!isDesktop()) {
return
}
return window.electron.ipcRenderer.invoke('set_state', { state })
}
export {
readAppSettingsFile,
writeAppSettingsFile,
getState,
setState,
getUser,
login,
} from 'lang/wasm'
// List machines on the local network.
export async function listMachines(): Promise<{
@ -41,21 +34,18 @@ export async function renameProjectDirectory(
projectPath: string,
newName: string
): Promise<string> {
return window.electron.ipcRenderer.invoke<string>('rename_project_directory', { projectPath, newName })
return window.electron.ipcRenderer.invoke<string>(
'rename_project_directory',
{ projectPath, newName }
)
}
// Get the initial default dir for holding all projects.
export async function getInitialDefaultDir(): Promise<string> {
if (!isDesktop()) {
return ''
}
return invoke<string>('get_initial_default_dir')
return window.electron.getInitialDefaultDir()
}
export async function showInFolder(path: string | undefined): Promise<void> {
if (!isDesktop()) {
return
}
if (!path) {
console.error('path is undefined cannot call desktop showInFolder')
return
@ -64,14 +54,20 @@ export async function showInFolder(path: string | undefined): Promise<void> {
}
export async function initializeProjectDirectory(
settings: Configuration
config: Configuration
): Promise<string | undefined> {
if (!isDesktop()) {
return undefined
}
return window.electron.ipcRenderer.invoke('initialize_project_directory', {
configuration: settings,
const projectDir = config.settings.project.directory
try {
await window.electron.exists(projectDir)
} catch (e) {
if (e === 'ENOENT') {
window.electron.mkdir(projectDir, { recursive: true }, (e) => {
console.log(e)
})
}
}
return projectDir
}
export async function createNewProjectDirectory(
@ -92,10 +88,13 @@ export async function createNewProjectDirectory(
export async function listProjects(
configuration?: Configuration
): Promise<Project[]> {
if (!configuration) {
configuration = await readAppSettingsFile()
const projectDir = await initializeProjectDirectory(configuration)
const projects = []
const entries = await window.electron.readdir(projectDir)
for (let entry of entries) {
// Ignore directories
console.log(entry)
}
return window.electron.ipcRenderer.invoke('list_projects', { configuration })
}
export async function getProjectInfo(
@ -111,10 +110,6 @@ export async function getProjectInfo(
})
}
export async function login(host: string): Promise<string> {
return window.electron.ipcRenderer.invoke('login', { host })
}
export async function parseProjectRoute(
configuration: Configuration,
route: string
@ -125,40 +120,10 @@ export async function parseProjectRoute(
})
}
export async function getUser(
token: string | undefined,
host: string
): Promise<Models['User_type'] | Record<'error_code', unknown> | void> {
if (!token) {
console.error('token is undefined cannot call desktop getUser')
return
}
return window.electron.ipcRenderer.invoke>(
'get_user',
{
token: token,
hostname: host,
}
).catch((err) => console.error('error from Tauri getUser', err))
}
export async function readDirRecursive(path: string): Promise<FileEntry[]> {
return window.electron.ipcRenderer.invoke('read_dir_recursive', { path })
}
// Read the contents of the app settings.
export async function readAppSettingsFile(): Promise<Configuration> {
return window.electron.ipcRenderer.invoke('read_app_settings_file')
}
// Write the contents of the app settings.
export async function writeAppSettingsFile(
settings: Configuration
): Promise<void> {
return window.electron.ipcRenderer.invoke('write_app_settings_file', { configuration: settings })
}
// Read project settings file.
export async function readProjectSettingsFile(
projectPath: string

View File

@ -1,19 +1,25 @@
import { contextBridge } from 'electron'
import { ipcRenderer, contextBridge } from 'electron'
import path from 'path'
import fs from 'node:fs'
import fs from 'node:fs/promises'
import packageJson from '../../package.json'
// All these functions call into lib/electron since many require filesystem
// access, and the second half is the original tauri code also stored app
// state on the "desktop" side.
const readFile = (path: string) => fs.readFile(path, 'utf-8')
const readdir = (path: string) => fs.readdir(path, 'utf-8')
const exists = (path: string) =>
new Promise((resolve, reject) =>
fs.stat(path, (err, data) => {
if (err) return reject(err.code)
return resolve(data)
})
)
const getPath = async (name: string) => ipcRenderer.invoke('app.getPath', name)
const DEFAULT_HOST = "https://api.zoo.dev"
const SETTINGS_FILE_NAME = "settings.toml"
const PROJECT_SETTINGS_FILE_NAME = "project.toml"
const PROJECT_FOLDER = "zoo-modeling-app-projects"
contextBridge.exposeInMainWorld("fs", {
readFile(p: string) { return fs.readFile(p, 'utf-8') },
readdir(p: string) { return fs.readdir(p, 'utf-8') },
join() { return path.join(...arguments) },
exists(p: string) { fs.exists(p) },
contextBridge.exposeInMainWorld('electron', {
readFile,
readdir,
path,
exists,
mkdir: fs.mkdir,
getPath,
packageJson,
})

View File

@ -1,5 +1,5 @@
// https://github.com/electron/electron/issues/2288#issuecomment-337858978
// Thank you
export function isDesktop(): boolean {
return navigator.userAgent.toLowerCase().indexOf("electron") > -1;
return navigator.userAgent.toLowerCase().indexOf('electron') > -1
}

View File

@ -192,7 +192,8 @@ export function createSettings() {
description: 'The directory to save and load projects from',
hideOnLevel: 'project',
hideOnPlatform: 'web',
validate: (v) => typeof v === 'string' && (v.length > 0 || !isDesktop()),
validate: (v) =>
typeof v === 'string' && (v.length > 0 || !isDesktop()),
Component: ({ value, updateValue }) => {
const inputRef = useRef<HTMLInputElement>(null)
return (

View File

@ -161,10 +161,8 @@ export async function loadAndValidateSettings(
const settings = createSettings()
const onDesktop = isDesktop()
if (!onDesktop) {
// Make sure we have wasm initialized.
await initPromise
}
// Load the app settings from the file system or localStorage.
const appSettings = onDesktop

View File

@ -1,4 +1,12 @@
import toast from 'react-hot-toast'
let toast = undefined
try {
global
} catch (e) {
import('react-hot-toast').then((_toast) => {
toast = _toast
})
}
type ExcludeErr<T> = Exclude<T, Error>

View File

@ -3,7 +3,7 @@ import { Models } from '@kittycad/lib'
import withBaseURL from '../lib/withBaseURL'
import { isDesktop } from 'lib/isDesktop'
import { VITE_KC_API_BASE_URL, VITE_KC_DEV_TOKEN } from 'env'
import { getUser as getUserTauri } from 'lib/desktop'
import { getUser as getUserDesktop } from 'lib/desktop'
const SKIP_AUTH =
import.meta.env.VITE_KC_SKIP_AUTH === 'true' && import.meta.env.DEV
@ -146,7 +146,7 @@ async function getUser(context: UserContext) {
})
.then((res) => res.json())
.catch((err) => console.error('error from Browser getUser', err))
: getUserTauri(context.token, VITE_KC_API_BASE_URL)
: getUserDesktop(context.token, VITE_KC_API_BASE_URL)
const user = await userPromise

View File

@ -1,7 +1,8 @@
// Some of the following was taken from bits and pieces of the vite-typescript
// template that ElectronJS provides.
import { app, BrowserWindow } from 'electron'
import { Configuration } from 'wasm-lib/kcl/bindings/Configuration'
import { app, BrowserWindow, ipcMain } from 'electron'
import path from 'path'
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
@ -17,8 +18,8 @@ const createWindow = () => {
nodeIntegration: false, // do not give the application implicit system access
contextIsolation: true, // expose system functions in preload
sandbox: false, // expose nodejs in preload
preload: path.join(__dirname, "./preload.js")
}
preload: path.join(__dirname, './preload.js'),
},
})
// and load the index.html of the app.
@ -48,3 +49,6 @@ app.on('window-all-closed', () => {
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)
ipcMain.handle('app.getPath', (event, data) => {
return app.getPath(data)
})

View File

@ -2589,6 +2589,17 @@ dependencies = [
"serde_derive",
]
[[package]]
name = "serde-wasm-bindgen"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b"
dependencies = [
"js-sys",
"serde",
"wasm-bindgen",
]
[[package]]
name = "serde_bytes"
version = "0.11.14"
@ -3625,6 +3636,8 @@ dependencies = [
"kittycad",
"pretty_assertions",
"reqwest",
"serde",
"serde-wasm-bindgen",
"serde_json",
"tokio",
"toml",

View File

@ -16,6 +16,8 @@ gloo-utils = "0.2.0"
kcl-lib = { path = "kcl" }
kittycad.workspace = true
serde_json = "1.0.122"
serde_json = "1.0.122"
serde-wasm-bindgen = "0.6.5"
tokio = { version = "1.39.2", features = ["sync"] }
toml = "0.8.19"
uuid = { version = "1.10.0", features = ["v4", "js", "serde"] }

View File

@ -19,7 +19,7 @@ const DEFAULT_PROJECT_NAME_TEMPLATE: &str = "project-$nnn";
#[serde(rename_all = "snake_case")]
pub struct Configuration {
/// The settings for the modeling app.
#[serde(default, skip_serializing_if = "is_default")]
#[serde(default)]
#[validate(nested)]
pub settings: Settings,
}
@ -183,23 +183,23 @@ impl Configuration {
#[serde(rename_all = "snake_case")]
pub struct Settings {
/// The settings for the modeling app.
#[serde(default, skip_serializing_if = "is_default")]
#[serde(default)]
#[validate(nested)]
pub app: AppSettings,
/// Settings that affect the behavior while modeling.
#[serde(default, skip_serializing_if = "is_default")]
#[serde(default)]
#[validate(nested)]
pub modeling: ModelingSettings,
/// Settings that affect the behavior of the KCL text editor.
#[serde(default, alias = "textEditor", skip_serializing_if = "is_default")]
#[serde(default, alias = "textEditor")]
#[validate(nested)]
pub text_editor: TextEditorSettings,
/// Settings that affect the behavior of project management.
#[serde(default, alias = "projects", skip_serializing_if = "is_default")]
#[serde(default, alias = "projects")]
#[validate(nested)]
pub project: ProjectSettings,
/// Settings that affect the behavior of the command bar.
#[serde(default, alias = "commandBar", skip_serializing_if = "is_default")]
#[serde(default, alias = "commandBar")]
#[validate(nested)]
pub command_bar: CommandBarSettings,
}
@ -212,11 +212,11 @@ pub struct Settings {
#[serde(rename_all = "snake_case")]
pub struct AppSettings {
/// The settings for the appearance of the app.
#[serde(default, skip_serializing_if = "is_default")]
#[serde(default)]
#[validate(nested)]
pub appearance: AppearanceSettings,
/// The onboarding status of the app.
#[serde(default, alias = "onboardingStatus", skip_serializing_if = "is_default")]
#[serde(default, alias = "onboardingStatus")]
pub onboarding_status: OnboardingStatus,
/// Backwards compatible project directory setting.
#[serde(default, alias = "projectDirectory", skip_serializing_if = "Option::is_none")]
@ -232,10 +232,10 @@ pub struct AppSettings {
pub enable_ssao: Option<bool>,
/// Permanently dismiss the banner warning to download the desktop app.
/// This setting only applies to the web app. And is temporary until we have Linux support.
#[serde(default, alias = "dismissWebBanner", skip_serializing_if = "is_default")]
#[serde(default, alias = "dismissWebBanner")]
pub dismiss_web_banner: bool,
/// When the user is idle, and this is true, the stream will be torn down.
#[serde(default, alias = "streamIdleMode", skip_serializing_if = "is_default")]
#[serde(default, alias = "streamIdleMode")]
stream_idle_mode: bool,
}
@ -275,10 +275,10 @@ impl From<FloatOrInt> for AppColor {
#[serde(rename_all = "snake_case")]
pub struct AppearanceSettings {
/// The overall theme of the app.
#[serde(default, skip_serializing_if = "is_default")]
#[serde(default)]
pub theme: AppTheme,
/// The hue of the primary theme color for the app.
#[serde(default, skip_serializing_if = "is_default")]
#[serde(default)]
#[validate(nested)]
pub color: AppColor,
}
@ -367,23 +367,23 @@ impl From<AppTheme> for kittycad::types::Color {
#[ts(export)]
pub struct ModelingSettings {
/// The default unit to use in modeling dimensions.
#[serde(default, alias = "defaultUnit", skip_serializing_if = "is_default")]
#[serde(default, alias = "defaultUnit")]
pub base_unit: UnitLength,
/// The controls for how to navigate the 3D view.
#[serde(default, alias = "mouseControls", skip_serializing_if = "is_default")]
#[serde(default, alias = "mouseControls")]
pub mouse_controls: MouseControlType,
/// Highlight edges of 3D objects?
#[serde(default, alias = "highlightEdges", skip_serializing_if = "is_default")]
#[serde(default, alias = "highlightEdges")]
pub highlight_edges: DefaultTrue,
/// Whether to show the debug panel, which lets you see various states
/// of the app to aid in development.
#[serde(default, alias = "showDebugPanel", skip_serializing_if = "is_default")]
#[serde(default, alias = "showDebugPanel")]
pub show_debug_panel: bool,
/// Whether or not Screen Space Ambient Occlusion (SSAO) is enabled.
#[serde(default, skip_serializing_if = "is_default")]
#[serde(default)]
pub enable_ssao: DefaultTrue,
/// Whether or not to show a scale grid in the 3D modeling view
#[serde(default, alias = "showScaleGrid", skip_serializing_if = "is_default")]
#[serde(default, alias = "showScaleGrid")]
pub show_scale_grid: bool,
}
@ -492,10 +492,10 @@ pub enum MouseControlType {
#[ts(export)]
pub struct TextEditorSettings {
/// Whether to wrap text in the editor or overflow with scroll.
#[serde(default, alias = "textWrapping", skip_serializing_if = "is_default")]
#[serde(default, alias = "textWrapping")]
pub text_wrapping: DefaultTrue,
/// Whether to make the cursor blink in the editor.
#[serde(default, alias = "blinkingCursor", skip_serializing_if = "is_default")]
#[serde(default, alias = "blinkingCursor")]
pub blinking_cursor: DefaultTrue,
}
@ -505,10 +505,10 @@ pub struct TextEditorSettings {
#[ts(export)]
pub struct ProjectSettings {
/// The directory to save and load projects from.
#[serde(default, skip_serializing_if = "is_default")]
#[serde(default)]
pub directory: std::path::PathBuf,
/// The default project name to use when creating a new project.
#[serde(default, alias = "defaultProjectName", skip_serializing_if = "is_default")]
#[serde(default, alias = "defaultProjectName")]
pub default_project_name: ProjectNameTemplate,
}
@ -541,7 +541,7 @@ impl From<String> for ProjectNameTemplate {
#[ts(export)]
pub struct CommandBarSettings {
/// Whether to include settings in the command bar.
#[serde(default, alias = "includeSettings", skip_serializing_if = "is_default")]
#[serde(default, alias = "includeSettings")]
pub include_settings: DefaultTrue,
}

View File

@ -6,8 +6,9 @@ use std::{
};
use futures::stream::TryStreamExt;
use gloo_utils::format::JsValueSerdeExt;
use kcl_lib::{coredump::CoreDump, engine::EngineManager, executor::ExecutorSettings};
use kcl_lib::{coredump::CoreDump, engine::EngineManager, executor::ExecutorSettings, lint::checks};
use serde::{Deserialize, Serialize};
use serde_wasm_bindgen;
use tower_lsp::{LspService, Server};
use wasm_bindgen::prelude::*;
@ -54,14 +55,13 @@ pub async fn execute_wasm(
};
let memory = ctx.run(&program, Some(memory)).await.map_err(String::from)?;
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
// gloo-serialize crate instead.
JsValue::from_serde(&memory).map_err(|e| e.to_string())
serde_wasm_bindgen::to_value(&memory).map_err(|e| e.to_string())
}
// wasm_bindgen wrapper for execute
#[wasm_bindgen]
pub async fn kcl_lint(program_str: &str) -> Result<JsValue, String> {
pub async fn kcl_lint(program_str: &str) -> Result<JsValue, JsValue> {
console_error_panic_hook::set_once();
let program: kcl_lib::ast::types::Program = serde_json::from_str(program_str).map_err(|e| e.to_string())?;
@ -70,7 +70,7 @@ pub async fn kcl_lint(program_str: &str) -> Result<JsValue, String> {
findings.push(discovered_finding);
}
Ok(JsValue::from_serde(&findings).map_err(|e| e.to_string())?)
Ok(serde_wasm_bindgen::to_value(&findings)?)
}
// wasm_bindgen wrapper for creating default planes
@ -89,9 +89,7 @@ pub async fn make_default_planes(
.await
.map_err(String::from)?;
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
// gloo-serialize crate instead.
JsValue::from_serde(&default_planes).map_err(|e| e.to_string())
serde_wasm_bindgen::to_value(&default_planes).map_err(|e| e.to_string())
}
// wasm_bindgen wrapper for modifying the grid
@ -143,9 +141,7 @@ pub async fn modify_ast_for_sketch_wasm(
.await
.map_err(String::from)?;
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
// gloo-serialize crate instead.
JsValue::from_serde(&program).map_err(|e| e.to_string())
serde_wasm_bindgen::to_value(&program).map_err(|e| e.to_string())
}
#[wasm_bindgen]
@ -161,7 +157,7 @@ pub fn deserialize_files(data: &[u8]) -> Result<JsValue, JsError> {
}
if let Some(kittycad::types::OkWebSocketResponseData::Export { files }) = ws_resp.resp {
return Ok(JsValue::from_serde(&files)?);
return Ok(serde_wasm_bindgen::to_value(&files)?);
}
Err(JsError::new(&format!("Invalid response type, got: {:?}", ws_resp)))
@ -174,7 +170,7 @@ pub fn lexer_wasm(js: &str) -> Result<JsValue, JsError> {
console_error_panic_hook::set_once();
let tokens = kcl_lib::token::lexer(js).map_err(JsError::from)?;
Ok(JsValue::from_serde(&tokens)?)
Ok(serde_wasm_bindgen::to_value(&tokens)?)
}
#[wasm_bindgen]
@ -184,9 +180,7 @@ pub fn parse_wasm(js: &str) -> Result<JsValue, String> {
let tokens = kcl_lib::token::lexer(js).map_err(String::from)?;
let parser = kcl_lib::parser::Parser::new(tokens);
let program = parser.ast().map_err(String::from)?;
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
// gloo-serialize crate instead.
JsValue::from_serde(&program).map_err(|e| e.to_string())
serde_wasm_bindgen::to_value(&program).map_err(|e| e.to_string())
}
// wasm_bindgen wrapper for recast
@ -200,7 +194,7 @@ pub fn recast_wasm(json_str: &str) -> Result<JsValue, JsError> {
// Use the default options until we integrate into the UI the ability to change them.
let result = program.recast(&Default::default(), 0);
Ok(JsValue::from_serde(&result)?)
Ok(serde_wasm_bindgen::to_value(&result)?)
}
#[wasm_bindgen]
@ -481,9 +475,7 @@ pub fn program_memory_init() -> Result<JsValue, String> {
let memory = kcl_lib::executor::ProgramMemory::default();
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
// gloo-serialize crate instead.
JsValue::from_serde(&memory).map_err(|e| e.to_string())
serde_wasm_bindgen::to_value(&memory).map_err(|e| e.to_string())
}
/// Get a coredump.
@ -494,9 +486,7 @@ pub async fn coredump(core_dump_manager: kcl_lib::coredump::wasm::CoreDumpManage
let core_dumper = kcl_lib::coredump::wasm::CoreDumper::new(core_dump_manager);
let dump = core_dumper.dump().await.map_err(|e| e.to_string())?;
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
// gloo-serialize crate instead.
JsValue::from_serde(&dump).map_err(|e| e.to_string())
serde_wasm_bindgen::to_value(&dump).map_err(|e| e.to_string())
}
/// Get the default app settings.
@ -505,10 +495,9 @@ pub fn default_app_settings() -> Result<JsValue, String> {
console_error_panic_hook::set_once();
let settings = kcl_lib::settings::types::Configuration::default();
web_sys::console::log(&js_sys::Array::of1(&JsValue::from_str(&format!("{:?}", settings))));
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
// gloo-serialize crate instead.
JsValue::from_serde(&settings).map_err(|e| e.to_string())
serde_wasm_bindgen::to_value(&settings).map_err(|e| e.to_string())
}
/// Parse the app settings.
@ -519,9 +508,7 @@ pub fn parse_app_settings(toml_str: &str) -> Result<JsValue, String> {
let settings = kcl_lib::settings::types::Configuration::backwards_compatible_toml_parse(&toml_str)
.map_err(|e| e.to_string())?;
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
// gloo-serialize crate instead.
JsValue::from_serde(&settings).map_err(|e| e.to_string())
serde_wasm_bindgen::to_value(&settings).map_err(|e| e.to_string())
}
/// Get the default project settings.
@ -531,12 +518,10 @@ pub fn default_project_settings() -> Result<JsValue, String> {
let settings = kcl_lib::settings::types::project::ProjectConfiguration::default();
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
// gloo-serialize crate instead.
JsValue::from_serde(&settings).map_err(|e| e.to_string())
serde_wasm_bindgen::to_value(&settings).map_err(|e| e.to_string())
}
/// Parse the project settings.
/// Parse (deserialize) the project settings.
#[wasm_bindgen]
pub fn parse_project_settings(toml_str: &str) -> Result<JsValue, String> {
console_error_panic_hook::set_once();
@ -544,9 +529,17 @@ pub fn parse_project_settings(toml_str: &str) -> Result<JsValue, String> {
let settings = kcl_lib::settings::types::project::ProjectConfiguration::backwards_compatible_toml_parse(&toml_str)
.map_err(|e| e.to_string())?;
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
// gloo-serialize crate instead.
JsValue::from_serde(&settings).map_err(|e| e.to_string())
serde_wasm_bindgen::to_value(&settings).map_err(|e| e.to_string())
}
/// Serialize the project settings.
#[wasm_bindgen]
pub fn serialize_project_settings(val: JsValue) -> Result<JsValue, String> {
console_error_panic_hook::set_once();
let config: kcl_lib::settings::types::Configuration = serde_wasm_bindgen::from_value(val).map_err(|e| e.to_string())?;
let toml_str = toml::to_string_pretty(&config).map_err(|e| e.to_string())?;
serde_wasm_bindgen::to_value(&toml_str).map_err(|e| e.to_string())
}
/// Parse the project route.
@ -560,7 +553,5 @@ pub fn parse_project_route(configuration: &str, route: &str) -> Result<JsValue,
let route =
kcl_lib::settings::types::file::ProjectRoute::from_route(&configuration, route).map_err(|e| e.to_string())?;
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
// gloo-serialize crate instead.
JsValue::from_serde(&route).map_err(|e| e.to_string())
serde_wasm_bindgen::to_value(&route).map_err(|e| e.to_string())
}

View File

@ -1,29 +1,42 @@
import type { ConfigEnv, UserConfig } from 'vite'
import { defineConfig, mergeConfig } from 'vite'
import { getBuildConfig, external, pluginHotRestart } from './vite.base.config'
import { configDefaults } from 'vitest/config'
import viteTsconfigPaths from 'vite-tsconfig-paths'
import {
getBuildConfig,
getBuildDefine,
external,
pluginHotRestart,
} from './vite.base.config'
// https://vitejs.dev/config
export default defineConfig((env) => {
const forgeEnv = env as ConfigEnv<'build'>
const { forgeConfigSelf } = forgeEnv
const define = getBuildDefine(forgeEnv)
const { root, mode, forgeConfigSelf } = forgeEnv
const config: UserConfig = {
root,
mode,
base: './',
build: {
lib: {
entry: forgeConfigSelf.entry!,
fileName: () => '[name].js',
formats: ['cjs'],
},
rollupOptions: {
external,
// Preload scripts may contain Web assets, so use the `build.rollupOptions.input` instead `build.lib.entry`.
input: forgeConfigSelf.entry!,
output: {
format: 'cjs',
// It should not be split chunks.
inlineDynamicImports: true,
entryFileNames: '[name].js',
chunkFileNames: '[name].js',
assetFileNames: '[name].[ext]',
},
},
resolve: {
// Load the Node.js entry.
mainFields: ['module', 'jsnext:main', 'jsnext'],
},
plugins: [pluginHotRestart('reload'), viteTsconfigPaths()],
plugins: [pluginHotRestart('restart'), viteTsconfigPaths()],
worker: {
plugins: () => [viteTsconfigPaths()],
},
define,
}
return mergeConfig(getBuildConfig(forgeEnv), config)