2025-04-09 09:46:30 -05:00
|
|
|
import { DEFAULT_PROJECT_NAME } from '@src/lib/constants'
|
2025-04-07 13:27:34 -05:00
|
|
|
import type { Project } from '@src/lib/project'
|
2025-04-14 11:56:28 -06:00
|
|
|
import type { SystemIOContext } from '@src/machines/systemIO/utils'
|
2025-04-09 09:46:30 -05:00
|
|
|
import {
|
|
|
|
NO_PROJECT_DIRECTORY,
|
|
|
|
SystemIOMachineActions,
|
|
|
|
SystemIOMachineActors,
|
|
|
|
SystemIOMachineEvents,
|
|
|
|
SystemIOMachineStates,
|
|
|
|
} from '@src/machines/systemIO/utils'
|
|
|
|
import { assertEvent, assign, fromPromise, setup } from 'xstate'
|
2025-04-07 13:27:34 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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
|
2025-04-09 09:46:30 -05:00
|
|
|
| {
|
|
|
|
type: SystemIOMachineEvents.readFoldersFromProjectDirectory
|
|
|
|
}
|
|
|
|
| {
|
|
|
|
type: SystemIOMachineEvents.done_readFoldersFromProjectDirectory
|
|
|
|
output: Project[]
|
|
|
|
}
|
|
|
|
| {
|
|
|
|
type: SystemIOMachineEvents.setProjectDirectoryPath
|
|
|
|
data: { requestedProjectDirectoryPath: string }
|
|
|
|
}
|
|
|
|
| {
|
2025-04-14 12:59:20 -06:00
|
|
|
type: SystemIOMachineEvents.navigateToProject
|
2025-04-09 09:46:30 -05:00
|
|
|
data: { requestedProjectName: string }
|
2025-04-14 15:04:07 -06:00
|
|
|
}
|
2025-04-14 12:59:20 -06:00
|
|
|
| {
|
|
|
|
type: SystemIOMachineEvents.navigateToFile
|
2025-04-14 15:04:07 -06:00
|
|
|
data: { requestedProjectName: string; requestedFileName: string }
|
|
|
|
}
|
|
|
|
| {
|
|
|
|
type: SystemIOMachineEvents.createProject
|
|
|
|
data: { requestedProjectName: string }
|
2025-04-14 16:07:17 -06:00
|
|
|
}
|
2025-04-14 15:04:07 -06:00
|
|
|
| {
|
|
|
|
type: SystemIOMachineEvents.renameProject
|
2025-04-14 16:07:17 -06:00
|
|
|
data: { requestedProjectName: string; projectName: string }
|
|
|
|
}
|
2025-04-14 15:32:43 -06:00
|
|
|
| {
|
|
|
|
type: SystemIOMachineEvents.deleteProject
|
2025-04-14 16:07:17 -06:00
|
|
|
data: { requestedProjectName: string }
|
2025-04-14 16:45:38 -06:00
|
|
|
}
|
|
|
|
| {
|
|
|
|
type: SystemIOMachineEvents.createKCLFile
|
|
|
|
data: {
|
|
|
|
requestedProjectName: string
|
|
|
|
requestedFileName: string
|
|
|
|
requestedCode: string
|
|
|
|
}
|
2025-04-15 10:30:52 -06:00
|
|
|
}
|
|
|
|
| {
|
|
|
|
type: SystemIOMachineEvents.setDefaultProjectFolderName
|
|
|
|
data: { requestedDefaultProjectFolderName: string }
|
2025-04-14 16:07:17 -06:00
|
|
|
},
|
2025-04-07 13:27:34 -05:00
|
|
|
},
|
|
|
|
actions: {
|
|
|
|
[SystemIOMachineActions.setFolders]: assign({
|
2025-04-09 09:46:30 -05:00
|
|
|
folders: ({ event }) => {
|
|
|
|
assertEvent(
|
|
|
|
event,
|
|
|
|
SystemIOMachineEvents.done_readFoldersFromProjectDirectory
|
|
|
|
)
|
2025-04-07 13:27:34 -05:00
|
|
|
return event.output
|
2025-04-09 09:46:30 -05:00
|
|
|
},
|
2025-04-07 13:27:34 -05:00
|
|
|
}),
|
|
|
|
[SystemIOMachineActions.setProjectDirectoryPath]: assign({
|
2025-04-09 09:46:30 -05:00
|
|
|
projectDirectoryPath: ({ event }) => {
|
2025-04-07 13:27:34 -05:00
|
|
|
assertEvent(event, SystemIOMachineEvents.setProjectDirectoryPath)
|
|
|
|
return event.data.requestedProjectDirectoryPath
|
2025-04-09 09:46:30 -05:00
|
|
|
},
|
|
|
|
}),
|
|
|
|
[SystemIOMachineActions.setRequestedProjectName]: assign({
|
|
|
|
requestedProjectName: ({ event }) => {
|
2025-04-14 12:59:20 -06:00
|
|
|
assertEvent(event, SystemIOMachineEvents.navigateToProject)
|
2025-04-14 11:56:28 -06:00
|
|
|
return { name: event.data.requestedProjectName }
|
2025-04-09 14:47:54 -06:00
|
|
|
},
|
|
|
|
}),
|
2025-04-14 12:59:20 -06:00
|
|
|
[SystemIOMachineActions.setRequestedFileName]: assign({
|
|
|
|
requestedFileName: ({ event }) => {
|
|
|
|
assertEvent(event, SystemIOMachineEvents.navigateToFile)
|
2025-04-14 15:04:07 -06:00
|
|
|
return {
|
|
|
|
project: event.data.requestedProjectName,
|
|
|
|
file: event.data.requestedFileName,
|
|
|
|
}
|
2025-04-14 12:59:20 -06:00
|
|
|
},
|
|
|
|
}),
|
2025-04-15 10:30:52 -06:00
|
|
|
[SystemIOMachineActions.setDefaultProjectFolderName]: assign({
|
|
|
|
defaultProjectFolderName: ({ event }) => {
|
|
|
|
assertEvent(event, SystemIOMachineEvents.setDefaultProjectFolderName)
|
|
|
|
return event.data.requestedDefaultProjectFolderName
|
|
|
|
},
|
|
|
|
}),
|
2025-04-07 13:27:34 -05:00
|
|
|
},
|
|
|
|
actors: {
|
2025-04-09 09:46:30 -05:00
|
|
|
[SystemIOMachineActors.readFoldersFromProjectDirectory]: fromPromise(
|
|
|
|
async ({ input: context }: { input: SystemIOContext }) => {
|
2025-04-14 16:07:17 -06:00
|
|
|
const folders: Project[] = []
|
|
|
|
return folders
|
2025-04-09 09:46:30 -05:00
|
|
|
}
|
|
|
|
),
|
2025-04-14 15:04:07 -06:00
|
|
|
[SystemIOMachineActors.createProject]: fromPromise(
|
|
|
|
async ({
|
2025-04-14 16:07:17 -06:00
|
|
|
input: { context, requestedProjectName },
|
2025-04-14 15:04:07 -06:00
|
|
|
}: {
|
2025-04-14 16:07:17 -06:00
|
|
|
input: { context: SystemIOContext; requestedProjectName: string }
|
2025-04-14 15:04:07 -06:00
|
|
|
}) => {}
|
|
|
|
),
|
2025-04-14 15:32:43 -06:00
|
|
|
[SystemIOMachineActors.deleteProject]: fromPromise(
|
|
|
|
async ({
|
2025-04-14 16:07:17 -06:00
|
|
|
input: { context, requestedProjectName },
|
|
|
|
}: {
|
|
|
|
input: { context: SystemIOContext; requestedProjectName: string }
|
|
|
|
}) => {}
|
|
|
|
),
|
|
|
|
[SystemIOMachineActors.renameProject]: fromPromise(
|
|
|
|
async ({
|
|
|
|
input: { context, requestedProjectName, projectName },
|
2025-04-14 15:32:43 -06:00
|
|
|
}: {
|
2025-04-14 16:07:17 -06:00
|
|
|
input: {
|
|
|
|
context: SystemIOContext
|
|
|
|
requestedProjectName: string
|
|
|
|
projectName: string
|
|
|
|
}
|
2025-04-14 15:32:43 -06:00
|
|
|
}) => {}
|
|
|
|
),
|
2025-04-14 16:45:38 -06:00
|
|
|
[SystemIOMachineActors.createKCLFile]: fromPromise(
|
|
|
|
async ({
|
|
|
|
input,
|
|
|
|
}: {
|
|
|
|
input: {
|
|
|
|
context: SystemIOContext
|
|
|
|
requestedProjectName: string
|
|
|
|
requestedFileName: string
|
|
|
|
requestedCode: string
|
2025-04-15 10:30:52 -06:00
|
|
|
|
|
|
|
}
|
2025-04-14 16:45:38 -06:00
|
|
|
}) => {}
|
|
|
|
),
|
2025-04-09 09:46:30 -05:00
|
|
|
},
|
2025-04-07 13:27:34 -05:00
|
|
|
}).createMachine({
|
2025-04-09 09:46:30 -05:00
|
|
|
initial: SystemIOMachineStates.idle,
|
2025-04-07 13:27:34 -05:00
|
|
|
// 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,
|
2025-04-09 09:46:30 -05:00
|
|
|
hasListedProjects: false,
|
2025-04-14 11:56:28 -06:00
|
|
|
requestedProjectName: { name: NO_PROJECT_DIRECTORY },
|
2025-04-14 15:04:07 -06:00
|
|
|
requestedFileName: {
|
|
|
|
project: NO_PROJECT_DIRECTORY,
|
|
|
|
file: NO_PROJECT_DIRECTORY,
|
|
|
|
},
|
2025-04-07 13:27:34 -05:00
|
|
|
}),
|
|
|
|
states: {
|
|
|
|
[SystemIOMachineStates.idle]: {
|
|
|
|
on: {
|
|
|
|
// on can be an action
|
2025-04-15 07:41:22 -06:00
|
|
|
[SystemIOMachineEvents.readFoldersFromProjectDirectory]: {
|
|
|
|
target: SystemIOMachineStates.readingFolders,
|
|
|
|
},
|
2025-04-09 09:46:30 -05:00
|
|
|
[SystemIOMachineEvents.setProjectDirectoryPath]: {
|
2025-04-07 13:27:34 -05:00
|
|
|
target: SystemIOMachineStates.readingFolders,
|
2025-04-09 09:46:30 -05:00
|
|
|
actions: [SystemIOMachineActions.setProjectDirectoryPath],
|
|
|
|
},
|
2025-04-14 12:59:20 -06:00
|
|
|
[SystemIOMachineEvents.navigateToProject]: {
|
2025-04-09 09:46:30 -05:00
|
|
|
actions: [SystemIOMachineActions.setRequestedProjectName],
|
|
|
|
},
|
2025-04-14 12:59:20 -06:00
|
|
|
[SystemIOMachineEvents.navigateToFile]: {
|
|
|
|
actions: [SystemIOMachineActions.setRequestedFileName],
|
|
|
|
},
|
2025-04-14 15:04:07 -06:00
|
|
|
[SystemIOMachineEvents.createProject]: {
|
|
|
|
target: SystemIOMachineStates.creatingProject,
|
|
|
|
},
|
|
|
|
[SystemIOMachineEvents.renameProject]: {
|
|
|
|
target: SystemIOMachineStates.renamingProject,
|
|
|
|
},
|
2025-04-14 15:32:43 -06:00
|
|
|
[SystemIOMachineEvents.deleteProject]: {
|
|
|
|
target: SystemIOMachineStates.deletingProject,
|
|
|
|
},
|
2025-04-14 16:45:38 -06:00
|
|
|
[SystemIOMachineEvents.createKCLFile]: {
|
|
|
|
target: SystemIOMachineStates.creatingKCLFile,
|
|
|
|
},
|
2025-04-15 10:30:52 -06:00
|
|
|
[SystemIOMachineEvents.setDefaultProjectFolderName]: {
|
|
|
|
actions: [SystemIOMachineActions.setDefaultProjectFolderName],
|
|
|
|
},
|
2025-04-09 09:46:30 -05:00
|
|
|
},
|
2025-04-07 13:27:34 -05:00
|
|
|
},
|
|
|
|
[SystemIOMachineStates.readingFolders]: {
|
|
|
|
invoke: {
|
|
|
|
id: SystemIOMachineActors.readFoldersFromProjectDirectory,
|
|
|
|
src: SystemIOMachineActors.readFoldersFromProjectDirectory,
|
2025-04-09 09:46:30 -05:00
|
|
|
input: ({ context }) => {
|
2025-04-07 13:27:34 -05:00
|
|
|
return context
|
|
|
|
},
|
|
|
|
onDone: {
|
|
|
|
target: SystemIOMachineStates.idle,
|
2025-04-09 09:46:30 -05:00
|
|
|
actions: [SystemIOMachineActions.setFolders],
|
2025-04-07 13:27:34 -05:00
|
|
|
},
|
|
|
|
onError: {
|
|
|
|
target: SystemIOMachineStates.idle,
|
2025-04-09 09:46:30 -05:00
|
|
|
},
|
|
|
|
},
|
2025-04-07 13:27:34 -05:00
|
|
|
},
|
2025-04-14 15:04:07 -06:00
|
|
|
[SystemIOMachineStates.creatingProject]: {
|
|
|
|
invoke: {
|
|
|
|
id: SystemIOMachineActors.createProject,
|
|
|
|
src: SystemIOMachineActors.createProject,
|
|
|
|
input: ({ context, event }) => {
|
|
|
|
assertEvent(event, SystemIOMachineEvents.createProject)
|
|
|
|
return {
|
|
|
|
context,
|
|
|
|
requestedProjectName: event.data.requestedProjectName,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
onDone: {
|
|
|
|
target: SystemIOMachineStates.readingFolders,
|
|
|
|
},
|
|
|
|
onError: {
|
|
|
|
target: SystemIOMachineStates.idle,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
[SystemIOMachineStates.renamingProject]: {
|
|
|
|
invoke: {
|
|
|
|
id: SystemIOMachineActors.renameProject,
|
|
|
|
src: SystemIOMachineActors.renameProject,
|
|
|
|
input: ({ context, event }) => {
|
|
|
|
assertEvent(event, SystemIOMachineEvents.renameProject)
|
|
|
|
return {
|
|
|
|
context,
|
|
|
|
requestedProjectName: event.data.requestedProjectName,
|
2025-04-14 16:07:17 -06:00
|
|
|
projectName: event.data.projectName,
|
2025-04-14 15:04:07 -06:00
|
|
|
}
|
|
|
|
},
|
|
|
|
onDone: {
|
|
|
|
target: SystemIOMachineStates.readingFolders,
|
|
|
|
},
|
|
|
|
onError: {
|
|
|
|
target: SystemIOMachineStates.idle,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2025-04-14 15:32:43 -06:00
|
|
|
[SystemIOMachineStates.deletingProject]: {
|
|
|
|
invoke: {
|
|
|
|
id: SystemIOMachineActors.deleteProject,
|
|
|
|
src: SystemIOMachineActors.deleteProject,
|
|
|
|
input: ({ context, event }) => {
|
|
|
|
assertEvent(event, SystemIOMachineEvents.deleteProject)
|
|
|
|
return {
|
|
|
|
context,
|
|
|
|
requestedProjectName: event.data.requestedProjectName,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
onDone: {
|
|
|
|
target: SystemIOMachineStates.readingFolders,
|
|
|
|
},
|
|
|
|
onError: {
|
|
|
|
target: SystemIOMachineStates.idle,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2025-04-14 16:45:38 -06:00
|
|
|
[SystemIOMachineStates.creatingKCLFile]: {
|
|
|
|
invoke: {
|
|
|
|
id: SystemIOMachineActors.createKCLFile,
|
|
|
|
src: SystemIOMachineActors.createKCLFile,
|
|
|
|
input: ({ context, event }) => {
|
|
|
|
assertEvent(event, SystemIOMachineEvents.createKCLFile)
|
|
|
|
return {
|
|
|
|
context,
|
|
|
|
requestedProjectName: event.data.requestedProjectName,
|
|
|
|
requestedFileName: event.data.requestedFileName,
|
|
|
|
requestedCode: event.data.requestedCode,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
onDone: {
|
|
|
|
target: SystemIOMachineStates.idle,
|
|
|
|
},
|
|
|
|
onError: {
|
|
|
|
target: SystemIOMachineStates.idle,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2025-04-09 09:46:30 -05:00
|
|
|
},
|
2025-04-07 13:27:34 -05:00
|
|
|
})
|
|
|
|
|
|
|
|
// 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?
|