Most FS functions work now

This commit is contained in:
49lf
2024-07-30 15:58:27 -04:00
parent 397eb9bf5a
commit 1a1e358238
23 changed files with 235 additions and 138 deletions

View File

@ -1,12 +1,11 @@
import { Models } from '@kittycad/lib'
import { Configuration } from 'wasm-lib/kcl/bindings/Configuration'
import { ProjectConfiguration } from 'wasm-lib/kcl/bindings/ProjectConfiguration'
import { Project } from 'wasm-lib/kcl/bindings/Project'
import { FileEntry } from 'wasm-lib/kcl/bindings/FileEntry'
import { ProjectState } from 'wasm-lib/kcl/bindings/ProjectState'
import { ProjectRoute } from 'wasm-lib/kcl/bindings/ProjectRoute'
import { components } from './machine-api'
import { isDesktop } from './isDesktop'
import { SaveSettingsPayload } from 'lib/settings/settingsUtils'
import {
defaultAppSettings,
@ -17,7 +16,6 @@ import {
export {
parseProjectRoute,
} from 'lang/wasm'
import { SaveSettingsPayload } from 'lib/settings/settingsUtils'
const DEFAULT_HOST = 'https://api.zoo.dev'
const SETTINGS_FILE_NAME = 'settings.toml'
@ -25,7 +23,6 @@ const PROJECT_SETTINGS_FILE_NAME = 'project.toml'
const PROJECT_FOLDER = 'zoo-modeling-app-projects'
const DEFAULT_PROJECT_KCL_FILE = "main.kcl"
// List machines on the local network.
export async function listMachines(): Promise<{
[key: string]: components['schemas']['Machine']
@ -43,15 +40,32 @@ export async function renameProjectDirectory(
projectPath: string,
newName: string
): Promise<string> {
debugger
}
export async function showInFolder(path: string | undefined): Promise<void> {
if (!path) {
console.error('path is undefined cannot call desktop showInFolder')
return
if (!newName) {
return Promise.reject(new Error(`New name for project cannot be empty`))
}
debugger
try { await window.electron.stat(projectPath) }
catch (e) {
if (e === 'ENOENT') {
return Promise.reject(new Error(`Path ${projectPath} is not a directory`))
}
}
// Make sure the new name does not exist.
const newPath = window.electron.path.join(projectPath.split('/').slice(0, -1).join('/'), newName)
try {
await window.electron.stat(newPath)
// If we get here it means the stat succeeded and there's a file already
// with the same name...
return Promise.reject(new Error(`Path ${newPath} already exists, cannot rename to an existing path`))
} catch (e) {
// Otherwise if it failed and the failure is "it doesnt exist" then rename it!
if (e === 'ENOENT') {
await window.electron.rename(projectPath, newPath)
return newPath
}
}
return Promise.reject(new Error('Unreachable'))
}
export async function ensureProjectDirectoryExists(
@ -62,7 +76,7 @@ export async function ensureProjectDirectoryExists(
await window.electron.stat(projectDir)
} catch (e) {
if (e === 'ENOENT') {
window.electron.mkdir(projectDir, { recursive: true }, (e) => {
await window.electron.mkdir(projectDir, { recursive: true }, (e) => {
console.log(e)
})
}
@ -92,7 +106,7 @@ export async function createNewProjectDirectory(
await window.electron.stat(projectDir)
} catch (e) {
if (e === 'ENOENT') {
window.electron.mkdir(projectDir, { recursive: true })
await window.electron.mkdir(projectDir, { recursive: true })
}
}
@ -101,17 +115,16 @@ export async function createNewProjectDirectory(
DEFAULT_PROJECT_KCL_FILE
)
await window.electron.writeFile(projectFile, initialCode ?? '')
const metadata = await window.electron.stat(projectFile)
return {
file: {
path: projectDir,
name: projectName,
// We don't need to recursively get all files in the project directory.
// Because we just created it and it's empty.
children: undefined,
},
path: projectDir,
name: projectName,
// We don't need to recursively get all files in the project directory.
// Because we just created it and it's empty.
children: undefined,
default_file: projectFile,
metadata: undefined /* TODO */,
metadata,
kcl_file_count: 1,
directory_count: 0,
}
@ -120,6 +133,9 @@ export async function createNewProjectDirectory(
export async function listProjects(
configuration?: Partial<SaveSettingsPayload>
): Promise<Project[]> {
if (configuration === undefined) {
configuration = await readAppSettingsFile()
}
const projectDir = await ensureProjectDirectoryExists(configuration)
const projects = []
const entries = await window.electron.readdir(projectDir)
@ -140,7 +156,7 @@ export async function listProjects(
const IMPORT_FILE_EXTENSIONS = [
// TODO Use ImportFormat enum
"stp", "glb", "fbxb", "kcl"
];
]
const isRelevantFile = (filename: string): boolean => IMPORT_FILE_EXTENSIONS.some(
(ext) => filename.endsWith('.' + ext))
@ -157,13 +173,13 @@ const collectAllFilesRecursiveFrom = async (path: string) => {
// Make sure the path is a directory.
const isPathDir = await window.electron.statIsDirectory(path)
if (!isPathDir) {
return Promise.reject(new Error(`Path ${path} is not a directory`));
return Promise.reject(new Error(`Path ${path} is not a directory`))
}
const pathParts = path.split('/')
let entry = /* FileEntry */ {
name: pathParts.slice(-1)[0],
path: pathParts.slice(0, -1).join('/'),
path,
children: [],
}
@ -185,9 +201,9 @@ const collectAllFilesRecursiveFrom = async (path: string) => {
if (!isRelevantFile(ePath)) { continue }
children.push(/* FileEntry */ {
name: e,
path: ePath.split('/').slice(0, -1).join('/'),
path: ePath,
children: undefined,
});
})
}
}
@ -199,13 +215,13 @@ const collectAllFilesRecursiveFrom = async (path: string) => {
const getDefaultKclFileForDir = async (projectDir, file) => {
// Make sure the dir is a directory.
const isFileEntryDir = await window.electron.statIsDirectory(file.path)
const isFileEntryDir = await window.electron.statIsDirectory(projectDir)
if (!isFileEntryDir) {
return Promise.reject(new Error(`Path ${file.path} is not a directory`))
return Promise.reject(new Error(`Path ${projectDir} is not a directory`))
}
let defaultFilePath = window.electron.path.join(file.path, DEFAULT_PROJECT_KCL_FILE)
try { await window.eletron.stat(defaultFilePath) }
let defaultFilePath = window.electron.path.join(projectDir, DEFAULT_PROJECT_KCL_FILE)
try { await window.electron.stat(defaultFilePath) }
catch (e) {
if (e === 'ENOENT') {
// Find a kcl file in the directory.
@ -213,7 +229,7 @@ const getDefaultKclFileForDir = async (projectDir, file) => {
for (let entry of file.children) {
if (entry.name.endsWith(".kcl")) {
return window.electron.path.join(projectDir, entry.name)
} else if (entry.children.is_some()) {
} else if (entry.children.length > 0) {
// Recursively find a kcl file in the directory.
return getDefaultKclFileForDir(entry.path, entry)
}
@ -228,7 +244,7 @@ const getDefaultKclFileForDir = async (projectDir, file) => {
}
const kclFileCount = (file /* fileEntry */) => {
let count = 0;
let count = 0
if (file.children) {
for (let entry of file.children) {
if (entry.name.endsWith(".kcl")) {
@ -263,40 +279,37 @@ export async function getProjectInfo(
try { await window.electron.stat(projectPath) }
catch (e) {
if (e === 'ENOENT') {
return Promise.reject(new Error(`Project directory does not exist: ${project_path}`));
return Promise.reject(new Error(`Project directory does not exist: ${project_path}`))
}
}
// Make sure it is a directory.
const projectPathIsDir = await window.electron.statIsDirectory(projectPath)
if (!projectPathIsDir) {
return Promise.reject(new Error(`Project path is not a directory: ${project_path}`));
return Promise.reject(new Error(`Project path is not a directory: ${project_path}`))
}
let walked = await collectAllFilesRecursiveFrom(projectPath)
let default_file = await getDefaultKclFileForDir(projectPath, walked)
const metadata = await window.electron.stat(projectPath)
let project = /* FileEntry */ {
file: walked,
metadata: undefined,
...walked,
metadata,
kcl_file_count: 0,
directory_count: 0,
default_file,
};
}
// Populate the number of KCL files in the project.
project.kcl_file_count = kclFileCount(project.file)
project.kcl_file_count = kclFileCount(project)
//Populate the number of directories in the project.
project.directory_count = directoryCount(project.file)
project.directory_count = directoryCount(project)
return project
}
export async function readDirRecursive(path: string): Promise<FileEntry[]> {
debugger
}
// Write project settings file.
export async function writeProjectSettingsFile({
projectPath,
@ -320,8 +333,8 @@ const getAppSettingsFilePath = async () => {
await window.electron.stat(fullPath)
} catch (e) {
// File/path doesn't exist
if (e.code === 'ENOENT') {
window.electron.mkdir(fullPath, { recursive: true })
if (e === 'ENOENT') {
await window.electron.mkdir(fullPath, { recursive: true })
}
}
return window.electron.path.join(fullPath, SETTINGS_FILE_NAME)
@ -331,8 +344,8 @@ const getProjectSettingsFilePath = async (projectPath: string) => {
try {
await window.electron.stat(projectPath)
} catch (e) {
if (e.code === 'ENOENT') {
window.electron.mkdir(projectPath, { recursive: true })
if (e === 'ENOENT') {
await window.electron.mkdir(projectPath, { recursive: true })
}
}
return window.electron.path.join(projectPath, PROJECT_SETTINGS_FILE_NAME)
@ -419,7 +432,7 @@ export const getUser = async (
}
// Use kittycad library to fetch the user info from /user/me
if (baseurl != DEFAULT_HOST) {
if (baseurl !== DEFAULT_HOST) {
// The TypeScript generated library uses environment variables for this
// because it was intended for NodeJS.
window.electron.process.env.BASE_URL(baseurl)