diff --git a/interface.d.ts b/interface.d.ts new file mode 100644 index 000000000..8db226161 --- /dev/null +++ b/interface.d.ts @@ -0,0 +1,38 @@ +import fs from 'node:fs/promises' +import path from 'path' +import { dialog, shell } from 'electron' + +export interface IElectronAPI { + open: typeof dialog.showOpenDialog + save: typeof dialog.showSaveDialog + openExternal: typeof shell.openExternal + showInFolder: typeof shell.showItemInFolder + login: (host: string) => Promise + platform: typeof process.env.platform + arch: typeof process.env.arch + version: typeof process.env.version + readFile: (path: string) => ReturnType + writeFile: (path: string, data: string | Uint8Array) => ReturnType + readdir: (path: string) => ReturnType + getPath: (name: string) => Promise + rm: typeof fs.rm + stat: (path: string) => ReturnType + statIsDirectory: (path: string) => Promise + path: typeof path, + mkdir: typeof fs.mkdir, + rename: (prev: string, next: string) => typeof fs.rename, + packageJson: { + name: string, + }, + process: { + env: { + BASE_URL: (value?: string) => string, + } + } +} + +declare global { + interface Window { + electron: IElectronAPI + } +} diff --git a/src/lang/std/fileSystemManager.ts b/src/lang/std/fileSystemManager.ts index 1f8e73811..1196d6b69 100644 --- a/src/lang/std/fileSystemManager.ts +++ b/src/lang/std/fileSystemManager.ts @@ -32,8 +32,8 @@ class FileSystemManager { .catch((error) => { return Promise.reject(new Error(`Error reading file: ${error}`)) }) - .then((file) => { - return window.electron.readFile(filepath) + .then((filePath) => { + return window.electron.readFile(filePath) }) } diff --git a/src/lib/coredump.ts b/src/lib/coredump.ts index 0ffb0f957..1d1169faf 100644 --- a/src/lib/coredump.ts +++ b/src/lib/coredump.ts @@ -65,10 +65,10 @@ export class CoreDumpManager { getOsInfo(): Promise { if (this.isDesktop()) { const osinfo: OsInfo = { - platform: window.electron.platform, - arch: window.electron.arch, + platform: window.electron.platform ?? null, + arch: window.electron.arch ?? null, browser: 'desktop', - version: window.electron.version, + version: window.electron.version ?? null, } return new Promise((resolve) => resolve(JSON.stringify(osinfo))) // (lf94) I'm not sure if this comment is specific to tauri or just desktop... diff --git a/src/lib/desktop.ts b/src/lib/desktop.ts index 6ed465104..8c83ca532 100644 --- a/src/lib/desktop.ts +++ b/src/lib/desktop.ts @@ -82,9 +82,7 @@ export async function ensureProjectDirectoryExists( await window.electron.stat(projectDir) } catch (e) { if (e === 'ENOENT') { - await window.electron.mkdir(projectDir, { recursive: true }, (e) => { - console.log(e) - }) + await window.electron.mkdir(projectDir, { recursive: true }) } } @@ -389,7 +387,7 @@ export const getInitialDefaultDir = async () => { export const readProjectSettingsFile = async ( projectPath: string -): ProjectConfiguration => { +): Promise => { let settingsPath = await getProjectSettingsFilePath(projectPath) // Check if this file exists. @@ -398,7 +396,7 @@ export const readProjectSettingsFile = async ( } catch (e) { if (e === 'ENOENT') { // Return the default configuration. - return {} + return { settings: {} } } } @@ -446,7 +444,7 @@ export const setState = async ( export const getUser = async ( token: string, hostname: string -): Models['User_type'] => { +): Promise => { // Use the host passed in if it's set. // Otherwise, use the default host. const host = !hostname ? DEFAULT_HOST : hostname diff --git a/src/lib/electron.ts b/src/lib/electron.ts index 2103e0516..8ab37e0f1 100644 --- a/src/lib/electron.ts +++ b/src/lib/electron.ts @@ -8,11 +8,11 @@ const save = (args: any) => ipcRenderer.invoke('dialog.showSaveDialog', args) const openExternal = (url: any) => ipcRenderer.invoke('shell.openExternal', url) const showInFolder = (path: string) => ipcRenderer.invoke('shell.showItemInFolder', path) -const login = (host: string) => ipcRenderer.invoke('login', host) +const login = (host: string): Promise => ipcRenderer.invoke('login', host) const readFile = (path: string) => fs.readFile(path, 'utf-8') const rename = (prev: string, next: string) => fs.rename(prev, next) -const writeFile = (path: string, data: string) => +const writeFile = (path: string, data: string | Uint8Array) => fs.writeFile(path, data, 'utf-8') const readdir = (path: string) => fs.readdir(path, 'utf-8') const stat = (path: string) => diff --git a/src/lib/openWindow.ts b/src/lib/openWindow.ts index 882ea085e..bb0302200 100644 --- a/src/lib/openWindow.ts +++ b/src/lib/openWindow.ts @@ -1,9 +1,11 @@ import { isDesktop } from 'lib/isDesktop' -export const openExternalBrowserIfDesktop = (to) => - function (e) { +export const openExternalBrowserIfDesktop = (to?: string) => + function (e: Event) { if (isDesktop()) { - window.electron.openExternal(to || e.currentTarget.href) + // Ignoring because currentTarget could be a few different things + // @ts-ignore + window.electron.openExternal(to || e.currentTarget?.href) e.preventDefault() e.stopPropagation() return false diff --git a/src/lib/paths.ts b/src/lib/paths.ts index 3e3fad8cf..7a47137d1 100644 --- a/src/lib/paths.ts +++ b/src/lib/paths.ts @@ -47,6 +47,11 @@ export async function getProjectMetaByRouteId( if (err(configuration)) return Promise.reject(configuration) + // Should not be possible but I guess logically it could be + if (configuration === undefined) { + return Promise.reject(new Error('No configuration found')) + } + const route = parseProjectRoute(configuration, id) if (err(route)) return Promise.reject(route) diff --git a/src/lib/routeLoaders.ts b/src/lib/routeLoaders.ts index a1b01884d..7f371d839 100644 --- a/src/lib/routeLoaders.ts +++ b/src/lib/routeLoaders.ts @@ -86,7 +86,7 @@ export const fileLoader: LoaderFunction = async ( const { project_name, project_path, current_file_name, current_file_path } = projectPathData - const urlObj = URL.parse(routerData.request.url) + const urlObj = new URL(routerData.request.url) let code = '' if (!urlObj.pathname.endsWith('/settings')) { @@ -120,7 +120,7 @@ export const fileLoader: LoaderFunction = async ( const projectData: IndexLoaderData = { code, project: isDesktop() - ? await getProjectInfo(project_path, configuration) + ? await getProjectInfo(project_path) : { name: project_name, path: project_path, @@ -131,8 +131,8 @@ export const fileLoader: LoaderFunction = async ( default_file: project_path, }, file: { - name: current_file_name, - path: current_file_path?.split('/').slice(0, -1).join('/'), + name: current_file_name || '', + path: current_file_path?.split('/').slice(0, -1).join('/') ?? '', children: [], }, } diff --git a/src/lib/settings/initialSettings.tsx b/src/lib/settings/initialSettings.tsx index 0f1da6234..296fbcd94 100644 --- a/src/lib/settings/initialSettings.tsx +++ b/src/lib/settings/initialSettings.tsx @@ -62,7 +62,7 @@ export class Setting { get user(): T | undefined { return this._user } - set user(v: T) { + set user(v: T | undefined) { this._user = this.validate(v) ? v : this._user this.current = this.resolve() } diff --git a/src/machines/authMachine.ts b/src/machines/authMachine.ts index 4d4344a12..a4832be5b 100644 --- a/src/machines/authMachine.ts +++ b/src/machines/authMachine.ts @@ -146,7 +146,7 @@ async function getUser(context: UserContext) { }) .then((res) => res.json()) .catch((err) => console.error('error from Browser getUser', err)) - : getUserDesktop(context.token, VITE_KC_API_BASE_URL) + : getUserDesktop(context.token ?? '', VITE_KC_API_BASE_URL) const user = await userPromise diff --git a/src/main.ts b/src/main.ts index 84732ef5f..41b392bb2 100644 --- a/src/main.ts +++ b/src/main.ts @@ -4,6 +4,7 @@ import { Configuration } from 'wasm-lib/kcl/bindings/Configuration' import { app, BrowserWindow, ipcMain, dialog, shell } from 'electron' import path from 'path' +import fs from 'node:fs/promises' import { Issuer } from 'openid-client' // Handle creating/removing shortcuts on Windows when installing/uninstalling. @@ -71,8 +72,9 @@ ipcMain.handle('shell.openExternal', (event, data) => { }) ipcMain.handle('login', async (event, host) => { - console.log('Logging in...') // Do an OAuth 2.0 Device Authorization Grant dance to get a token. + // We quiet ts because we are not using this in the standard way. + // @ts-ignore const issuer = new Issuer({ device_authorization_endpoint: `${host}/oauth2/device/auth`, token_endpoint: `${host}/oauth2/device/token`, @@ -103,9 +105,9 @@ ipcMain.handle('login', async (event, host) => { if (process.env.TEMP) { temp = process.env.TEMP } - let path = path.join(temp, 'kittycad_user_code') - console.log(`Writing to ${path}`) - await fs.writeFile(path, handle.user_code) + let tmpkcuc = path.join(temp, 'kittycad_user_code') + console.log(`Writing to ${tmpkcuc}`) + await fs.writeFile(tmpkcuc, handle.user_code) } else { shell.openExternal(handle.verification_uri_complete) } diff --git a/src/wasm-lib/kcl/src/settings/types/file.rs b/src/wasm-lib/kcl/src/settings/types/file.rs index eb3cf3200..88fcf6120 100644 --- a/src/wasm-lib/kcl/src/settings/types/file.rs +++ b/src/wasm-lib/kcl/src/settings/types/file.rs @@ -913,7 +913,7 @@ mod tests { .unwrap(); assert_eq!(state.project.file.name, name); - assert_eq!(state.project.path, tmp_project_dir.display().to_string()); + assert_eq!(state.project.file.path, tmp_project_dir.display().to_string()); assert_eq!( state.current_file, Some(tmp_project_dir.join("main.kcl").display().to_string()) @@ -938,7 +938,7 @@ mod tests { .unwrap(); assert_eq!(state.project.file.name, name); - assert_eq!(state.project.path, tmp_project_dir.display().to_string()); + assert_eq!(state.project.file.path, tmp_project_dir.display().to_string()); assert_eq!( state.current_file, Some(tmp_project_dir.join("main.kcl").display().to_string()) @@ -963,7 +963,7 @@ mod tests { .unwrap(); assert_eq!(state.project.file.name, name); - assert_eq!(state.project.path, tmp_project_dir.display().to_string()); + assert_eq!(state.project.file.path, tmp_project_dir.display().to_string()); assert_eq!( state.current_file, Some(tmp_project_dir.join("main.kcl").display().to_string()) @@ -988,7 +988,7 @@ mod tests { .unwrap(); assert_eq!(state.project.file.name, name); - assert_eq!(state.project.path, tmp_project_dir.display().to_string()); + assert_eq!(state.project.file.path, tmp_project_dir.display().to_string()); assert_eq!( state.current_file, Some(tmp_project_dir.join("thing.kcl").display().to_string()) @@ -1013,7 +1013,7 @@ mod tests { .unwrap(); assert_eq!(state.project.file.name, name); - assert_eq!(state.project.path, tmp_project_dir.display().to_string()); + assert_eq!(state.project.file.path, tmp_project_dir.display().to_string()); assert_eq!( state.current_file, Some(tmp_project_dir.join("model.obj.kcl").display().to_string()) diff --git a/src/wasm-lib/kcl/src/settings/types/mod.rs b/src/wasm-lib/kcl/src/settings/types/mod.rs index f68cb7043..20254584d 100644 --- a/src/wasm-lib/kcl/src/settings/types/mod.rs +++ b/src/wasm-lib/kcl/src/settings/types/mod.rs @@ -967,9 +967,9 @@ color = 1567.4"#; .await .unwrap(); - assert_eq!(project.name, project_name); + assert_eq!(project.file.name, project_name); assert_eq!( - project.path, + project.file.path, settings .settings .project @@ -981,7 +981,7 @@ color = 1567.4"#; assert_eq!(project.directory_count, 0); assert_eq!( project.default_file, - std::path::Path::new(&project.path) + std::path::Path::new(&project.file.path) .join(super::DEFAULT_PROJECT_KCL_FILE) .to_string_lossy() ); @@ -1017,9 +1017,9 @@ color = 1567.4"#; .await .unwrap(); - assert_eq!(project.name, project_name); + assert_eq!(project.file.name, project_name); assert_eq!( - project.path, + project.file.path, settings .settings .project @@ -1031,7 +1031,7 @@ color = 1567.4"#; assert_eq!(project.directory_count, 0); assert_eq!( project.default_file, - std::path::Path::new(&project.path) + std::path::Path::new(&project.file.path) .join(super::DEFAULT_PROJECT_KCL_FILE) .to_string_lossy() ); @@ -1057,8 +1057,8 @@ color = 1567.4"#; let projects = settings.list_projects().await.unwrap(); assert_eq!(projects.len(), 1); - assert_eq!(projects[0].name, project_name); - assert_eq!(projects[0].path, project.path); + assert_eq!(projects[0].file.name, project_name); + assert_eq!(projects[0].file.path, project.file.path); assert_eq!(projects[0].kcl_file_count, 1); assert_eq!(projects[0].directory_count, 0); assert_eq!(projects[0].default_file, project.default_file); @@ -1084,8 +1084,8 @@ color = 1567.4"#; let projects = settings.list_projects().await.unwrap(); assert_eq!(projects.len(), 1); - assert_eq!(projects[0].name, project_name); - assert_eq!(projects[0].path, project.path); + assert_eq!(projects[0].file.name, project_name); + assert_eq!(projects[0].file.path, project.file.path); assert_eq!(projects[0].kcl_file_count, 1); assert_eq!(projects[0].directory_count, 0); assert_eq!(projects[0].default_file, project.default_file); @@ -1111,8 +1111,8 @@ color = 1567.4"#; let projects = settings.list_projects().await.unwrap(); assert_eq!(projects.len(), 1); - assert_eq!(projects[0].name, project_name); - assert_eq!(projects[0].path, project.path); + assert_eq!(projects[0].file.name, project_name); + assert_eq!(projects[0].file.path, project.file.path); assert_eq!(projects[0].kcl_file_count, 1); assert_eq!(projects[0].directory_count, 0); assert_eq!(projects[0].default_file, project.default_file); @@ -1138,8 +1138,8 @@ color = 1567.4"#; let projects = settings.list_projects().await.unwrap(); assert_eq!(projects.len(), 1); - assert_eq!(projects[0].name, project_name); - assert_eq!(projects[0].path, project.path); + assert_eq!(projects[0].file.name, project_name); + assert_eq!(projects[0].file.path, project.file.path); assert_eq!(projects[0].kcl_file_count, 1); assert_eq!(projects[0].directory_count, 0); assert_eq!(projects[0].default_file, project.default_file); diff --git a/src/wasm-lib/src/wasm.rs b/src/wasm-lib/src/wasm.rs index 939c9bae2..2a5830bb0 100644 --- a/src/wasm-lib/src/wasm.rs +++ b/src/wasm-lib/src/wasm.rs @@ -7,7 +7,6 @@ use std::{ use futures::stream::TryStreamExt; 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::*; diff --git a/tsconfig.json b/tsconfig.json index 48366613a..61d9a1c8e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -33,7 +33,7 @@ "noEmit": true, "jsx": "react-jsx" }, - "include": ["src", "e2e", "packages", "./*.ts"], + "include": ["src", "e2e", "packages", "./*.ts", "package.json"], "exclude": ["node_modules", "./*.grammar"], "references": [{ "path": "./tsconfig.node.json" }] }