fix: new structure for web vs desktop vs react machine provider code
This commit is contained in:
0
src/components/Providers/SystemIOProviderWeb.tsx
Normal file
0
src/components/Providers/SystemIOProviderWeb.tsx
Normal file
@ -5,13 +5,16 @@ import { createSettings } from '@src/lib/settings/initialSettings'
|
|||||||
import { authMachine } from '@src/machines/authMachine'
|
import { authMachine } from '@src/machines/authMachine'
|
||||||
import { ACTOR_IDS } from '@src/machines/machineConstants'
|
import { ACTOR_IDS } from '@src/machines/machineConstants'
|
||||||
import { settingsMachine } from '@src/machines/settingsMachine'
|
import { settingsMachine } from '@src/machines/settingsMachine'
|
||||||
import { systemIOMachine, SystemIOMachineEvents } from "@src/machines/systemIOMachine"
|
import { SystemIOMachineEvents } from "@src/machines/systemIO/utils"
|
||||||
|
import { systemIOMachineWeb} from "@src/machines/systemIO/systemIOMachineWeb"
|
||||||
|
import { systemIOMachineDesktop} from "@src/machines/systemIO/systemIOMachineDesktop"
|
||||||
|
import { systemIOMachine} from "@src/machines/systemIO/systemIOMachine"
|
||||||
|
|
||||||
const { AUTH, SETTINGS, SYSTEM_IO } = ACTOR_IDS
|
const { AUTH, SETTINGS, SYSTEM_IO } = ACTOR_IDS
|
||||||
const appMachineActors = {
|
const appMachineActors = {
|
||||||
[AUTH]: authMachine,
|
[AUTH]: authMachine,
|
||||||
[SETTINGS]: settingsMachine,
|
[SETTINGS]: settingsMachine,
|
||||||
[SYSTEM_IO]: systemIOMachine
|
[SYSTEM_IO]: systemIOMachineDesktop
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
const appMachine = setup({
|
const appMachine = setup({
|
||||||
|
87
src/machines/systemIO/systemIOMachine.ts
Normal file
87
src/machines/systemIO/systemIOMachine.ts
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import { setup, fromPromise, assign, assertEvent} from 'xstate'
|
||||||
|
import { DEFAULT_PROJECT_NAME } from "@src/lib/constants"
|
||||||
|
import type { Project } from '@src/lib/project'
|
||||||
|
import {SystemIOMachineEvents, SystemIOMachineActions, SystemIOMachineActors, SystemIOMachineStates, NO_PROJECT_DIRECTORY, SystemIOContext} from "@src/machines/systemIO/utils"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles any system level I/O for folders and files
|
||||||
|
* This machine will be initializes once within the applications runtime
|
||||||
|
* and exist for the entire life cycle of the application and able to be access
|
||||||
|
* at a global level.
|
||||||
|
*/
|
||||||
|
export const systemIOMachine = setup({
|
||||||
|
types: {
|
||||||
|
context: {} as SystemIOContext,
|
||||||
|
events: {} as
|
||||||
|
| { type: SystemIOMachineEvents.readFoldersFromProjectDirectory; data: {} }
|
||||||
|
| { type: SystemIOMachineEvents.done_readFoldersFromProjectDirectory; data: {}, output: Project[] }
|
||||||
|
| { type: SystemIOMachineEvents.setProjectDirectoryPath; data: {requestedProjectDirectoryPath: string}}
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
[SystemIOMachineActions.setFolders]: assign({
|
||||||
|
folders:({event})=>{
|
||||||
|
assertEvent(event, SystemIOMachineEvents.done_readFoldersFromProjectDirectory)
|
||||||
|
return event.output
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
[SystemIOMachineActions.setProjectDirectoryPath]: assign({
|
||||||
|
projectDirectoryPath:({event})=>{
|
||||||
|
assertEvent(event, SystemIOMachineEvents.setProjectDirectoryPath)
|
||||||
|
return event.data.requestedProjectDirectoryPath
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
actors: {
|
||||||
|
[SystemIOMachineActors.readFoldersFromProjectDirectory]: fromPromise(async ({input:context}:{input:SystemIOContext}) => {
|
||||||
|
return []
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}).createMachine({
|
||||||
|
initial:SystemIOMachineStates.idle,
|
||||||
|
// Remember, this machine and change its projectDirectory at any point
|
||||||
|
// '' will be no project directory, aka clear this machine out!
|
||||||
|
// To be the aboslute root of someones computer we should take the string of path.resolve() in node.js which is different for each OS
|
||||||
|
context: () => ({
|
||||||
|
folders: [],
|
||||||
|
defaultProjectFolderName: DEFAULT_PROJECT_NAME,
|
||||||
|
projectDirectoryPath: NO_PROJECT_DIRECTORY,
|
||||||
|
hasListedProjects: false
|
||||||
|
}),
|
||||||
|
states: {
|
||||||
|
[SystemIOMachineStates.idle]: {
|
||||||
|
on: {
|
||||||
|
// on can be an action
|
||||||
|
[SystemIOMachineEvents.readFoldersFromProjectDirectory]:SystemIOMachineStates.readingFolders,
|
||||||
|
[SystemIOMachineEvents.setProjectDirectoryPath]:{
|
||||||
|
target: SystemIOMachineStates.readingFolders,
|
||||||
|
actions: [
|
||||||
|
SystemIOMachineActions.setProjectDirectoryPath
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[SystemIOMachineStates.readingFolders]: {
|
||||||
|
invoke: {
|
||||||
|
id: SystemIOMachineActors.readFoldersFromProjectDirectory,
|
||||||
|
src: SystemIOMachineActors.readFoldersFromProjectDirectory,
|
||||||
|
input: ({context}) => {
|
||||||
|
return context
|
||||||
|
},
|
||||||
|
onDone: {
|
||||||
|
target: SystemIOMachineStates.idle,
|
||||||
|
actions: [
|
||||||
|
SystemIOMachineActions.setFolders
|
||||||
|
]
|
||||||
|
},
|
||||||
|
onError: {
|
||||||
|
target: SystemIOMachineStates.idle,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
// Watcher handler
|
||||||
|
// look at projectDirectory useEffect then send this event if it changes or if we need to do this?
|
||||||
|
// The handler needs to live somewhere... aka the provider?
|
47
src/machines/systemIO/systemIOMachineDesktop.ts
Normal file
47
src/machines/systemIO/systemIOMachineDesktop.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import { SystemIOMachineEvents, SystemIOMachineActors, SystemIOContext, NO_PROJECT_DIRECTORY} from "@src/machines/systemIO/utils"
|
||||||
|
import { systemIOMachine} from "@src/machines/systemIO/systemIOMachine"
|
||||||
|
import { setup, fromPromise, assign, assertEvent} from 'xstate'
|
||||||
|
import { mkdirOrNOOP, getProjectInfo } from "@src/lib/desktop"
|
||||||
|
import type { Project } from '@src/lib/project'
|
||||||
|
|
||||||
|
export const systemIOMachineDesktop = systemIOMachine.provide({
|
||||||
|
actors: {
|
||||||
|
[SystemIOMachineActors.readFoldersFromProjectDirectory]: fromPromise(async ({input:context}:{input:SystemIOContext}) => {
|
||||||
|
const projects = []
|
||||||
|
const projectDirectoryPath = context.projectDirectoryPath
|
||||||
|
if (projectDirectoryPath === NO_PROJECT_DIRECTORY) {
|
||||||
|
// TODO
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
await mkdirOrNOOP(projectDirectoryPath)
|
||||||
|
// Gotcha: readdir will list all folders at this project directory even if you do not have readwrite access on the directory path
|
||||||
|
const entries = await window.electron.readdir(projectDirectoryPath)
|
||||||
|
const { value: canReadWriteProjectDirectory } = await window.electron.canReadWriteDirectory(projectDirectoryPath)
|
||||||
|
|
||||||
|
for (let entry of entries) {
|
||||||
|
// Skip directories that start with a dot
|
||||||
|
if (entry.startsWith('.')) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const projectPath = window.electron.path.join(projectDirectoryPath, entry)
|
||||||
|
|
||||||
|
// if it's not a directory ignore.
|
||||||
|
// Gotcha: statIsDirectory will work even if you do not have read write permissions on the project path
|
||||||
|
const isDirectory = await window.electron.statIsDirectory(projectPath)
|
||||||
|
if (!isDirectory) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const project : Project = await getProjectInfo(projectPath)
|
||||||
|
if (
|
||||||
|
project.kcl_file_count === 0 &&
|
||||||
|
project.readWriteAccess &&
|
||||||
|
canReadWriteProjectDirectory
|
||||||
|
) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
projects.push(project)
|
||||||
|
}
|
||||||
|
return projects
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
14
src/machines/systemIO/systemIOMachineWeb.ts
Normal file
14
src/machines/systemIO/systemIOMachineWeb.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { SystemIOMachineEvents, SystemIOMachineActors, SystemIOContext} from "@src/machines/systemIO/utils"
|
||||||
|
import { systemIOMachine} from "@src/machines/systemIO/systemIOMachine"
|
||||||
|
import { setup, fromPromise, assign, assertEvent} from 'xstate'
|
||||||
|
import type { Project } from '@src/lib/project'
|
||||||
|
|
||||||
|
export const systemIOMachineWeb = systemIOMachine.provide({
|
||||||
|
actors: {
|
||||||
|
[SystemIOMachineActors.readFoldersFromProjectDirectory]: fromPromise(async ({input:context}:{input:SystemIOContext}) => {
|
||||||
|
const projects: Project[] = []
|
||||||
|
console.log('nothing!')
|
||||||
|
return projects
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
40
src/machines/systemIO/utils.ts
Normal file
40
src/machines/systemIO/utils.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import type { Project } from '@src/lib/project'
|
||||||
|
|
||||||
|
export enum SystemIOMachineActors {
|
||||||
|
readFoldersFromProjectDirectory = "read folders from project directory",
|
||||||
|
setProjectDirectoryPath = "set project directory path"
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum SystemIOMachineStates {
|
||||||
|
idle = "idle",
|
||||||
|
readingFolders = "readingFolders",
|
||||||
|
settingProjectDirectoryPath = "settingProjectDirectoryPath"
|
||||||
|
}
|
||||||
|
|
||||||
|
const donePrefix = 'xstate.done.actor.'
|
||||||
|
|
||||||
|
export enum SystemIOMachineEvents {
|
||||||
|
readFoldersFromProjectDirectory = "read folders from project directory",
|
||||||
|
done_readFoldersFromProjectDirectory = donePrefix + "read folders from project directory",
|
||||||
|
setProjectDirectoryPath = "set project directory path",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum SystemIOMachineActions {
|
||||||
|
setFolders = "set folders",
|
||||||
|
setProjectDirectoryPath = "set project directory path"
|
||||||
|
}
|
||||||
|
|
||||||
|
export const NO_PROJECT_DIRECTORY = ''
|
||||||
|
|
||||||
|
export type SystemIOContext = {
|
||||||
|
// Only store folders under the projectDirectory, do not maintain folders outside this directory
|
||||||
|
folders: Project[],
|
||||||
|
// For this machines runtime, this is the default string when creating a project
|
||||||
|
// A project is defined by creating a folder at the one level below the working project directory
|
||||||
|
defaultProjectFolderName:string,
|
||||||
|
// working project directory that stores all the project folders
|
||||||
|
projectDirectoryPath: string,
|
||||||
|
// has the application gone through the initialiation of systemIOMachine at least once.
|
||||||
|
// this is required to prevent chokidar from spamming invalid events during initialization.
|
||||||
|
hasListedProjects: boolean
|
||||||
|
}
|
@ -29,7 +29,7 @@ export enum SystemIOMachineActions {
|
|||||||
|
|
||||||
const NO_PROJECT_DIRECTORY = ''
|
const NO_PROJECT_DIRECTORY = ''
|
||||||
|
|
||||||
type SystemIOContext = {
|
export type SystemIOContext = {
|
||||||
// Only store folders under the projectDirectory, do not maintain folders outside this directory
|
// Only store folders under the projectDirectory, do not maintain folders outside this directory
|
||||||
folders: Project[],
|
folders: Project[],
|
||||||
// For this machines runtime, this is the default string when creating a project
|
// For this machines runtime, this is the default string when creating a project
|
||||||
|
Reference in New Issue
Block a user