Almost fixed all type erorrs

This commit is contained in:
49lf
2024-08-01 14:29:41 -04:00
parent 7496f8a9db
commit dc8a5f8a12
18 changed files with 85 additions and 95 deletions

View File

@ -101,7 +101,10 @@ const router = createBrowserRouter([
<Outlet /> <Outlet />
<App /> <App />
<CommandBar /> <CommandBar />
{!isDesktop() && import.meta.env.PROD && <DownloadAppBanner />} {
// @ts-ignore
!isDesktop() && import.meta.env.PROD && <DownloadAppBanner />
}
</ModelingMachineProvider> </ModelingMachineProvider>
<WasmErrBanner /> <WasmErrBanner />
</FileMachineProvider> </FileMachineProvider>

View File

@ -137,7 +137,9 @@ export const FileMachineProvider = ({
await window.electron.rename(oldPath, newPath) await window.electron.rename(oldPath, newPath)
if (!file) { return Promise.reject(new Error('file is not defined')) } if (!file) {
return Promise.reject(new Error('file is not defined'))
}
const currentFilePath = window.electron.path.join(file.path, file.name) const currentFilePath = window.electron.path.join(file.path, file.name)
if (oldPath === currentFilePath && project?.path) { if (oldPath === currentFilePath && project?.path) {

View File

@ -142,7 +142,9 @@ function HelpMenuItem({
{as === 'a' ? ( {as === 'a' ? (
<a <a
{...(props as React.ComponentProps<'a'>)} {...(props as React.ComponentProps<'a'>)}
onClick={openExternalBrowserIfDesktop((props as React.ComponentProps<'a'>).href)} onClick={openExternalBrowserIfDesktop(
(props as React.ComponentProps<'a'>).href
)}
className={`no-underline text-inherit ${baseClassName} ${className}`} className={`no-underline text-inherit ${baseClassName} ${className}`}
> >
{children} {children}

View File

@ -26,7 +26,10 @@ export function LowerRightControls({
const isPlayWright = window?.localStorage.getItem('playwright') === 'true' const isPlayWright = window?.localStorage.getItem('playwright') === 'true'
async function reportbug(event: { preventDefault: () => void, stopPropagation: () => void }) { async function reportbug(event: {
preventDefault: () => void
stopPropagation: () => void
}) {
event?.preventDefault() event?.preventDefault()
event?.stopPropagation() event?.stopPropagation()

View File

@ -114,7 +114,7 @@ function ProjectCard({
<span className="px-2 text-chalkboard-60 text-xs"> <span className="px-2 text-chalkboard-60 text-xs">
Edited{' '} Edited{' '}
{project.metadata && project.metadata.modified {project.metadata && project.metadata.modified
? getDisplayedTime(project.metadata.modified.toString()) ? getDisplayedTime(parseInt(project.metadata.modified))
: 'never'} : 'never'}
</span> </span>
</div> </div>

View File

@ -196,7 +196,9 @@ export const AllSettingsFields = forwardRef(
projectPath ? decodeURIComponent(projectPath) : undefined projectPath ? decodeURIComponent(projectPath) : undefined
) )
const finalPath = paths[searchParamTab] const finalPath = paths[searchParamTab]
if (!finalPath) { return new Error('finalPath undefined') } if (!finalPath) {
return new Error('finalPath undefined')
}
window.electron.showInFolder(finalPath) window.electron.showInFolder(finalPath)
}} }}
iconStart={{ iconStart={{

View File

@ -1,15 +1,28 @@
// env vars were centralised so they could be mocked in jest // env vars were centralised so they could be mocked in jest
// but isn't needed anymore with vite, so is now just a convention // but isn't needed anymore with vite, so is now just a convention
// Even though we transpile to a module system that supports import, the
// typescript checker doesn't know that, so it's causing problems
// to properly type check anything with "import.meta". I've tried for a good
// hour to fix this but nothing has worked. This is the pain the JS ecosystem
// gets for like 6 different module systems.
// @ts-ignore
export const VITE_KC_API_WS_MODELING_URL = import.meta.env export const VITE_KC_API_WS_MODELING_URL = import.meta.env
.VITE_KC_API_WS_MODELING_URL .VITE_KC_API_WS_MODELING_URL
// @ts-ignore
export const VITE_KC_API_BASE_URL = import.meta.env.VITE_KC_API_BASE_URL export const VITE_KC_API_BASE_URL = import.meta.env.VITE_KC_API_BASE_URL
// @ts-ignore
export const VITE_KC_SITE_BASE_URL = import.meta.env.VITE_KC_SITE_BASE_URL export const VITE_KC_SITE_BASE_URL = import.meta.env.VITE_KC_SITE_BASE_URL
// @ts-ignore
export const VITE_KC_CONNECTION_TIMEOUT_MS = import.meta.env export const VITE_KC_CONNECTION_TIMEOUT_MS = import.meta.env
.VITE_KC_CONNECTION_TIMEOUT_MS .VITE_KC_CONNECTION_TIMEOUT_MS
// @ts-ignore
export const VITE_KC_DEV_TOKEN = import.meta.env.VITE_KC_DEV_TOKEN as export const VITE_KC_DEV_TOKEN = import.meta.env.VITE_KC_DEV_TOKEN as
| string | string
| undefined | undefined
// @ts-ignore
export const TEST = import.meta.env.TEST export const TEST = import.meta.env.TEST
// @ts-ignore
export const DEV = import.meta.env.DEV export const DEV = import.meta.env.DEV
export const CI = import.meta.env.CI export const CI = import.meta.env.CI

View File

@ -1,14 +1,14 @@
import { isDesktop } from 'lib/isDesktop' import { isDesktop } from 'lib/isDesktop'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
export type Platform = 'macos' | 'windows' | 'linux' export type Platform = 'macos' | 'windows' | 'linux' | ''
export default function usePlatform() { export default function usePlatform() {
const [platformName, setPlatformName] = useState<Platform | ''>('') const [platformName, setPlatformName] = useState<Platform>('')
useEffect(() => { useEffect(() => {
async function getPlatform() { async function getPlatform() {
setPlatformName(window.electron.platform) setPlatformName((window.electron.platform ?? '') as Platform)
} }
if (isDesktop()) { if (isDesktop()) {

View File

@ -121,7 +121,7 @@ export default class CodeManager {
this._currentFilePath && this._currentFilePath &&
window.electron window.electron
.writeFile(this._currentFilePath, this.code ?? '') .writeFile(this._currentFilePath, this.code ?? '')
.catch((err) => { .catch((err: Error) => {
// TODO: add tracing per GH issue #254 (https://github.com/KittyCAD/modeling-app/issues/254) // TODO: add tracing per GH issue #254 (https://github.com/KittyCAD/modeling-app/issues/254)
console.error('error saving file', err) console.error('error saving file', err)
toast.error('Error saving file, please check file permissions') toast.error('Error saving file, please check file permissions')

View File

@ -23,9 +23,7 @@ import {
configurationToSettingsPayload, configurationToSettingsPayload,
projectConfigurationToSettingsPayload, projectConfigurationToSettingsPayload,
} from 'lib/settings/settingsUtils' } from 'lib/settings/settingsUtils'
import { import { SaveSettingsPayload } from 'lib/settings/settingsTypes'
SaveSettingsPayload,
} from 'lib/settings/settingsTypes'
import { KCLError } from './errors' import { KCLError } from './errors'
import { KclError as RustKclError } from '../wasm-lib/kcl/bindings/KclError' import { KclError as RustKclError } from '../wasm-lib/kcl/bindings/KclError'
import { EngineCommandManager } from './std/engineConnection' import { EngineCommandManager } from './std/engineConnection'
@ -589,7 +587,7 @@ export function parseProjectSettings(
} }
export function parseProjectRoute( export function parseProjectRoute(
configuration: Configuration, configuration: Partial<SaveSettingsPayload>,
route_str: string route_str: string
): ProjectRoute | Error { ): ProjectRoute | Error {
return parse_project_route(JSON.stringify(configuration), route_str) return parse_project_route(JSON.stringify(configuration), route_str)

View File

@ -6,6 +6,7 @@ import { ProjectState } from 'wasm-lib/kcl/bindings/ProjectState'
import { ProjectRoute } from 'wasm-lib/kcl/bindings/ProjectRoute' import { ProjectRoute } from 'wasm-lib/kcl/bindings/ProjectRoute'
import { components } from './machine-api' import { components } from './machine-api'
import { isDesktop } from './isDesktop' import { isDesktop } from './isDesktop'
import { FileEntry } from 'wasm-lib/kcl/bindings/FileEntry'
import { SaveSettingsPayload } from 'lib/settings/settingsUtils' import { SaveSettingsPayload } from 'lib/settings/settingsUtils'
import { import {
@ -79,7 +80,9 @@ export async function ensureProjectDirectoryExists(
config: Partial<SaveSettingsPayload> config: Partial<SaveSettingsPayload>
): Promise<string | undefined> { ): Promise<string | undefined> {
const projectDir = config.app?.projectDirectory const projectDir = config.app?.projectDirectory
if (!projectDir) { return Promise.reject(new Error('projectDir is falsey')) } if (!projectDir) {
return Promise.reject(new Error('projectDir is falsey'))
}
try { try {
await window.electron.stat(projectDir) await window.electron.stat(projectDir)
} catch (e) { } catch (e) {
@ -106,7 +109,9 @@ export async function createNewProjectDirectory(
return Promise.reject('Project name cannot be empty.') return Promise.reject('Project name cannot be empty.')
} }
if (!mainDir) { return Promise.reject(new Error('mainDir is falsey')) } if (!mainDir) {
return Promise.reject(new Error('mainDir is falsey'))
}
const projectDir = window.electron.path.join(mainDir, projectName) const projectDir = window.electron.path.join(mainDir, projectName)
try { try {
@ -129,7 +134,7 @@ export async function createNewProjectDirectory(
name: projectName, name: projectName,
// We don't need to recursively get all files in the project directory. // We don't need to recursively get all files in the project directory.
// Because we just created it and it's empty. // Because we just created it and it's empty.
children: undefined, children: null,
default_file: projectFile, default_file: projectFile,
metadata, metadata,
kcl_file_count: 1, kcl_file_count: 1,
@ -194,7 +199,7 @@ const collectAllFilesRecursiveFrom = async (path: string) => {
} }
const pathParts = path.split('/') const pathParts = path.split('/')
let entry = /* FileEntry */ { let entry: FileEntry = {
name: pathParts.slice(-1)[0], name: pathParts.slice(-1)[0],
path, path,
children: [], children: [],
@ -256,7 +261,7 @@ const getDefaultKclFileForDir = async (projectDir: string, file: FileEntry) => {
for (let entry of file.children) { for (let entry of file.children) {
if (entry.name.endsWith('.kcl')) { if (entry.name.endsWith('.kcl')) {
return window.electron.path.join(projectDir, entry.name) return window.electron.path.join(projectDir, entry.name)
} else if (entry.children.length > 0) { } else if (entry.children?.length > 0) {
// Recursively find a kcl file in the directory. // Recursively find a kcl file in the directory.
return getDefaultKclFileForDir(entry.path, entry) return getDefaultKclFileForDir(entry.path, entry)
} }
@ -275,7 +280,7 @@ const getDefaultKclFileForDir = async (projectDir: string, file: FileEntry) => {
return defaultFilePath return defaultFilePath
} }
const kclFileCount = (file /* fileEntry */) => { const kclFileCount = (file: FileEntry) => {
let count = 0 let count = 0
if (file.children) { if (file.children) {
for (let entry of file.children) { for (let entry of file.children) {
@ -291,7 +296,7 @@ const kclFileCount = (file /* fileEntry */) => {
} }
/// Populate the number of directories in the project. /// Populate the number of directories in the project.
const directoryCount = (file /* FileEntry */) => { const directoryCount = (file: FileEntry) => {
let count = 0 let count = 0
if (file.children) { if (file.children) {
for (let entry of file.children) { for (let entry of file.children) {
@ -330,7 +335,9 @@ export async function getProjectInfo(projectPath: string): Promise<Project> {
let project = { let project = {
...walked, ...walked,
// We need to map from node fs.Stats to FileMetadata // We need to map from node fs.Stats to FileMetadata
metadata: metadata.map((data: { mtimeMs: number }) => ({ modified: data.mtimeMs })), metadata: metadata.map((data: { mtimeMs: number }) => ({
modified: data.mtimeMs,
})),
kcl_file_count: 0, kcl_file_count: 0,
directory_count: 0, directory_count: 0,
default_file, default_file,
@ -346,15 +353,12 @@ export async function getProjectInfo(projectPath: string): Promise<Project> {
} }
// Write project settings file. // Write project settings file.
export async function writeProjectSettingsFile({ export async function writeProjectSettingsFile(
projectPath, projectPath: string,
configuration, configuration: Partial<SaveSettingsPayload>,
}: { ): Promise<void> {
projectPath: string
configuration: Partial<SaveSettingsPayload>
}): Promise<void> {
const projectSettingsFilePath = await getProjectSettingsFilePath(projectPath) const projectSettingsFilePath = await getProjectSettingsFilePath(projectPath)
const tomlStr = tomlStringify(configuration) const tomlStr = tomlStringify({ settings: configuration })
if (err(tomlStr)) return Promise.reject(tomlStr) if (err(tomlStr)) return Promise.reject(tomlStr)
return window.electron.writeFile(projectSettingsFilePath, tomlStr) return window.electron.writeFile(projectSettingsFilePath, tomlStr)
} }
@ -419,6 +423,7 @@ export const readAppSettingsFile = async () => {
} catch (e) { } catch (e) {
if (e === 'ENOENT') { if (e === 'ENOENT') {
const config = defaultAppSettings() const config = defaultAppSettings()
if (!config.app) { return Promise.reject(new Error('config.app is falsey')) }
config.app.projectDirectory = await getInitialDefaultDir() config.app.projectDirectory = await getInitialDefaultDir()
return config return config
} }
@ -432,7 +437,7 @@ export const writeAppSettingsFile = async (
config: Partial<SaveSettingsPayload> config: Partial<SaveSettingsPayload>
) => { ) => {
const appSettingsFilePath = await getAppSettingsFilePath() const appSettingsFilePath = await getAppSettingsFilePath()
const tomlStr = tomlStringify(config) const tomlStr = tomlStringify({ settings: config })
if (err(tomlStr)) return Promise.reject(tomlStr) if (err(tomlStr)) return Promise.reject(tomlStr)
return window.electron.writeFile(appSettingsFilePath, tomlStr) return window.electron.writeFile(appSettingsFilePath, tomlStr)
} }

View File

@ -5,6 +5,7 @@ import { Configuration } from 'wasm-lib/kcl/bindings/Configuration'
import { ProjectRoute } from 'wasm-lib/kcl/bindings/ProjectRoute' import { ProjectRoute } from 'wasm-lib/kcl/bindings/ProjectRoute'
import { parseProjectRoute, readAppSettingsFile } from './desktop' import { parseProjectRoute, readAppSettingsFile } from './desktop'
import { readLocalStorageAppSettingsFile } from './settings/settingsUtils' import { readLocalStorageAppSettingsFile } from './settings/settingsUtils'
import { SaveSettingsPayload } from './settings/settingsTypes'
import { err } from 'lib/trap' import { err } from 'lib/trap'
const prependRoutes = const prependRoutes =
@ -33,7 +34,7 @@ export const BROWSER_PATH = `%2F${BROWSER_PROJECT_NAME}%2F${BROWSER_FILE_NAME}${
export async function getProjectMetaByRouteId( export async function getProjectMetaByRouteId(
id?: string, id?: string,
configuration?: Configuration | Error configuration?: Partial<SaveSettingsPayload> | Error
): Promise<ProjectRoute | undefined> { ): Promise<ProjectRoute | undefined> {
if (!id) return undefined if (!id) return undefined

View File

@ -118,14 +118,14 @@ export const fileLoader: LoaderFunction = async (
fileSystemManager.dir = project_path fileSystemManager.dir = project_path
const defaultProjectData = { const defaultProjectData = {
name: project_name || 'unnamed', name: project_name || 'unnamed',
path: project_path, path: project_path,
children: [], children: [],
kcl_file_count: 0, kcl_file_count: 0,
directory_count: 0, directory_count: 0,
metadata: null, metadata: null,
default_file: project_path, default_file: project_path,
} }
const projectData: IndexLoaderData = { const projectData: IndexLoaderData = {
code, code,

View File

@ -63,9 +63,7 @@ export class Setting<T = unknown> {
return this._user return this._user
} }
set user(v: T | undefined) { set user(v: T | undefined) {
this._user = v !== undefined this._user = v !== undefined ? (this.validate(v) ? v : this._user) : v
? this.validate(v) ? v : this._user
: v
this.current = this.resolve() this.current = this.resolve()
} }
/** /**
@ -75,9 +73,7 @@ export class Setting<T = unknown> {
return this._project return this._project
} }
set project(v: T | undefined) { set project(v: T | undefined) {
this._project = v !== undefined this._project = v !== undefined ? (this.validate(v) ? v : this._project) : v
? this.validate(v) ? v : this._project
: v
this.current = this.resolve() this.current = this.resolve()
} }
/** /**

View File

@ -105,7 +105,7 @@ function localStorageProjectSettingsPath() {
return '/' + BROWSER_PROJECT_NAME + '/project.toml' return '/' + BROWSER_PROJECT_NAME + '/project.toml'
} }
export function readLocalStorageAppSettingsFile(): Configuration | Error { export function readLocalStorageAppSettingsFile(): Partial<SaveSettingsPayload> | Error {
// TODO: Remove backwards compatibility after a few releases. // TODO: Remove backwards compatibility after a few releases.
let stored = let stored =
localStorage.getItem(localStorageAppSettingsPath()) ?? localStorage.getItem(localStorageAppSettingsPath()) ??
@ -129,7 +129,9 @@ export function readLocalStorageAppSettingsFile(): Configuration | Error {
} }
} }
function readLocalStorageProjectSettingsFile(): Partial<SaveSettingsPayload> | Error { function readLocalStorageProjectSettingsFile():
| Partial<SaveSettingsPayload>
| Error {
// TODO: Remove backwards compatibility after a few releases. // TODO: Remove backwards compatibility after a few releases.
let stored = localStorage.getItem(localStorageProjectSettingsPath()) ?? '' let stored = localStorage.getItem(localStorageProjectSettingsPath()) ?? ''
@ -151,8 +153,8 @@ function readLocalStorageProjectSettingsFile(): Partial<SaveSettingsPayload> | E
} }
export interface AppSettings { export interface AppSettings {
settings: ReturnType<typeof createSettings> settings: ReturnType<typeof createSettings>,
configuration: Configuration configuration: Partial<SaveSettingsPayload>
} }
export async function loadAndValidateSettings( export async function loadAndValidateSettings(
@ -204,10 +206,10 @@ export async function saveSettings(
if (err(tomlString)) return if (err(tomlString)) return
// Parse this as a Configuration. // Parse this as a Configuration.
const appSettings = { settings: parseAppSettings(tomlString) } const appSettings = parseAppSettings(tomlString)
if (err(appSettings)) return if (err(appSettings)) return
const tomlString2 = tomlStringify(appSettings) const tomlString2 = tomlStringify({ settings: appSettings })
if (err(tomlString2)) return if (err(tomlString2)) return
// Write the app settings. // Write the app settings.
@ -237,10 +239,10 @@ export async function saveSettings(
// Write the project settings. // Write the project settings.
if (onDesktop) { if (onDesktop) {
await writeProjectSettingsFile({ await writeProjectSettingsFile(
projectPath, projectPath,
configuration: { settings: projectSettings }, projectSettings,
}) )
} else { } else {
localStorage.setItem(localStorageProjectSettingsPath(), tomlStr) localStorage.setItem(localStorageProjectSettingsPath(), tomlStr)
} }

View File

@ -6,6 +6,7 @@ import { VITE_KC_API_BASE_URL, VITE_KC_DEV_TOKEN } from 'env'
import { getUser as getUserDesktop } from 'lib/desktop' import { getUser as getUserDesktop } from 'lib/desktop'
const SKIP_AUTH = const SKIP_AUTH =
// @ts-ignore
import.meta.env.VITE_KC_SKIP_AUTH === 'true' && import.meta.env.DEV import.meta.env.VITE_KC_SKIP_AUTH === 'true' && import.meta.env.DEV
const LOCAL_USER: Models['User_type'] = { const LOCAL_USER: Models['User_type'] = {

View File

@ -15,7 +15,8 @@ import { KeybindingsSectionsList } from 'components/Settings/KeybindingsSections
import { isDesktop } from 'lib/isDesktop' import { isDesktop } from 'lib/isDesktop'
export const APP_VERSION = isDesktop() export const APP_VERSION = isDesktop()
? import.meta.env.PACKAGE_VERSION || 'unknown' ? // @ts-ignore
import.meta.env.PACKAGE_VERSION || 'unknown'
: 'main' : 'main'
export const Settings = () => { export const Settings = () => {

View File

@ -1,39 +0,0 @@
{
"compilerOptions": {
"baseUrl": "src",
"paths": {
"@kittycad/codemirror-lsp-client": [
"../packages/codemirror-lsp-client/src/index.ts"
],
"/*": ["src/*"]
},
"types": [
"vite/client",
"@types/wicg-file-system-access",
"node",
"@wdio/globals/types",
"mocha",
"@lezer/generator"
],
"target": "esnext",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"sourceMap": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "commonjs",
"moduleResolution": "node",
"resolveJsonModule": true,
"composite": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["src", "e2e", "packages", "./*.ts", "package.json"],
"exclude": ["node_modules", "./*.grammar"],
"references": [{ "path": "./tsconfig.node.json" }]
}