Fixup machine-api
This commit is contained in:
		
							
								
								
									
										3
									
								
								interface.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								interface.d.ts
									
									
									
									
										vendored
									
									
								
							@ -2,6 +2,7 @@ import fs from 'node:fs/promises'
 | 
			
		||||
import path from 'path'
 | 
			
		||||
import { dialog, shell } from 'electron'
 | 
			
		||||
import kittycad from '@kittycad/lib'
 | 
			
		||||
import { MachinesListing } from 'lib/machineManager'
 | 
			
		||||
 | 
			
		||||
export interface IElectronAPI {
 | 
			
		||||
  open: typeof dialog.showOpenDialog
 | 
			
		||||
@ -34,6 +35,8 @@ export interface IElectronAPI {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  kittycad
 | 
			
		||||
  listMachines: () => Promise<MachinesListing>
 | 
			
		||||
  getMachineApiIp: () => Promise<string | null>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
declare global {
 | 
			
		||||
 | 
			
		||||
@ -35,6 +35,7 @@
 | 
			
		||||
    "@tweenjs/tween.js": "^23.1.1",
 | 
			
		||||
    "@xstate/inspect": "^0.8.0",
 | 
			
		||||
    "@xstate/react": "^3.2.2",
 | 
			
		||||
    "bonjour-service": "^1.2.1",
 | 
			
		||||
    "codemirror": "^6.0.1",
 | 
			
		||||
    "decamelize": "^6.0.0",
 | 
			
		||||
    "electron-squirrel-startup": "^1.0.1",
 | 
			
		||||
 | 
			
		||||
@ -92,7 +92,7 @@ export function LowerRightControls({
 | 
			
		||||
        <Link
 | 
			
		||||
          to={
 | 
			
		||||
            location.pathname.includes(paths.FILE)
 | 
			
		||||
              ? (filePath + paths.SETTINGS + '?tab=project')
 | 
			
		||||
              ? filePath + paths.SETTINGS + '?tab=project'
 | 
			
		||||
              : paths.HOME + paths.SETTINGS
 | 
			
		||||
          }
 | 
			
		||||
        >
 | 
			
		||||
 | 
			
		||||
@ -23,23 +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']
 | 
			
		||||
}> {
 | 
			
		||||
  console.log("STUB")
 | 
			
		||||
  return {}
 | 
			
		||||
  // let machines: string = await invoke<string>('list_machines')
 | 
			
		||||
  // return JSON.parse(machines)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get the machine-api ip address.
 | 
			
		||||
export async function getMachineApiIp(): Promise<string | null> {
 | 
			
		||||
  console.log("STUB")
 | 
			
		||||
  return null
 | 
			
		||||
  // return await invoke<string | null>('get_machine_api_ip')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function renameProjectDirectory(
 | 
			
		||||
  projectPath: string,
 | 
			
		||||
  newName: string
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,8 @@ import { ipcRenderer, contextBridge } from 'electron'
 | 
			
		||||
import path from 'path'
 | 
			
		||||
import fs from 'node:fs/promises'
 | 
			
		||||
import packageJson from '../../package.json'
 | 
			
		||||
import { components } from 'lib/machine-api'
 | 
			
		||||
import { MachinesListing } from 'lib/machineManager'
 | 
			
		||||
 | 
			
		||||
const open = (args: any) => ipcRenderer.invoke('dialog.showOpenDialog', args)
 | 
			
		||||
const save = (args: any) => ipcRenderer.invoke('dialog.showSaveDialog', args)
 | 
			
		||||
@ -36,6 +38,18 @@ const exposeProcessEnv = (varName: string) => {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// We could probably do this from the renderer side, but I fear CORS will
 | 
			
		||||
// bite our butts.
 | 
			
		||||
const listMachines = async (): Promise<MachinesListing> => {
 | 
			
		||||
  const machineApi = await ipcRenderer.invoke('find_machine_api')
 | 
			
		||||
  if (!machineApi) return {}
 | 
			
		||||
 | 
			
		||||
  return fetch(`http://${machineApi}/machines`).then((resp) => resp.json())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const getMachineApiIp = async (): Promise<String | null> =>
 | 
			
		||||
  ipcRenderer.invoke('find_machine_api')
 | 
			
		||||
 | 
			
		||||
import('@kittycad/lib').then((kittycad) => {
 | 
			
		||||
  contextBridge.exposeInMainWorld('electron', {
 | 
			
		||||
    login,
 | 
			
		||||
@ -70,5 +84,7 @@ import('@kittycad/lib').then((kittycad) => {
 | 
			
		||||
    kittycad: {
 | 
			
		||||
      users: kittycad.users,
 | 
			
		||||
    },
 | 
			
		||||
    listMachines,
 | 
			
		||||
    getMachineApiIp,
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
@ -1,12 +1,13 @@
 | 
			
		||||
import { isDesktop } from './isDesktop'
 | 
			
		||||
import { components } from './machine-api'
 | 
			
		||||
import { getMachineApiIp, listMachines } from './desktop'
 | 
			
		||||
 | 
			
		||||
export type MachinesListing = {
 | 
			
		||||
  [key: string]: components['schemas']['Machine']
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class MachineManager {
 | 
			
		||||
  private _isDesktop: boolean = isDesktop()
 | 
			
		||||
  private _machines: {
 | 
			
		||||
    [key: string]: components['schemas']['Machine']
 | 
			
		||||
  } = {}
 | 
			
		||||
  private _machines: MachinesListing = {}
 | 
			
		||||
  private _machineApiIp: string | null = null
 | 
			
		||||
  private _currentMachine: components['schemas']['Machine'] | null = null
 | 
			
		||||
 | 
			
		||||
@ -24,15 +25,21 @@ export class MachineManager {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Start a background job to update the machines every ten seconds.
 | 
			
		||||
    setInterval(() => {
 | 
			
		||||
      this.updateMachineApiIp()
 | 
			
		||||
      this.updateMachines()
 | 
			
		||||
    }, 10000)
 | 
			
		||||
    // If MDNS is already watching, this timeout will wait until it's done to trigger the
 | 
			
		||||
    // finding again.
 | 
			
		||||
    let timeoutId = undefined
 | 
			
		||||
    const timeoutLoop = () => {
 | 
			
		||||
      clearTimeout(timeoutId)
 | 
			
		||||
      timeoutId = setTimeout(async () => {
 | 
			
		||||
        await this.updateMachineApiIp()
 | 
			
		||||
        await this.updateMachines()
 | 
			
		||||
        timeoutLoop()
 | 
			
		||||
      }, 10000)
 | 
			
		||||
    }
 | 
			
		||||
    timeoutLoop()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get machines(): {
 | 
			
		||||
    [key: string]: components['schemas']['Machine']
 | 
			
		||||
  } {
 | 
			
		||||
  get machines(): MachinesListing {
 | 
			
		||||
    return this._machines
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -57,7 +64,7 @@ export class MachineManager {
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this._machines = await listMachines()
 | 
			
		||||
    this._machines = await window.electron.listMachines()
 | 
			
		||||
    console.log('Machines:', this._machines)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -66,7 +73,7 @@ export class MachineManager {
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this._machineApiIp = await getMachineApiIp()
 | 
			
		||||
    this._machineApiIp = await window.electron.getMachineApiIp()
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -83,7 +83,8 @@ export const fileLoader: LoaderFunction = async (
 | 
			
		||||
  const isBrowserProject = params.id === decodeURIComponent(BROWSER_PATH)
 | 
			
		||||
 | 
			
		||||
  if (!isBrowserProject && projectPathData) {
 | 
			
		||||
    const { project_name, project_path, current_file_name, current_file_path } = projectPathData
 | 
			
		||||
    const { project_name, project_path, current_file_name, current_file_path } =
 | 
			
		||||
      projectPathData
 | 
			
		||||
 | 
			
		||||
    const urlObj = new URL(routerData.request.url)
 | 
			
		||||
    let code = ''
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										24
									
								
								src/main.ts
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								src/main.ts
									
									
									
									
									
								
							@ -6,6 +6,7 @@ import { app, BrowserWindow, ipcMain, dialog, shell } from 'electron'
 | 
			
		||||
import path from 'path'
 | 
			
		||||
import fs from 'node:fs/promises'
 | 
			
		||||
import { Issuer } from 'openid-client'
 | 
			
		||||
import { Bonjour, Service } from 'bonjour-service'
 | 
			
		||||
 | 
			
		||||
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
 | 
			
		||||
if (require('electron-squirrel-startup')) {
 | 
			
		||||
@ -72,6 +73,10 @@ app.on('window-all-closed', () => {
 | 
			
		||||
// Some APIs can only be used after this event occurs.
 | 
			
		||||
app.on('ready', createWindow)
 | 
			
		||||
 | 
			
		||||
// For now there is no good reason to separate these out to another file(s)
 | 
			
		||||
// There is just not enough code to warrant it and further abstracts everything
 | 
			
		||||
// which is already quite abstracted
 | 
			
		||||
 | 
			
		||||
ipcMain.handle('app.getPath', (event, data) => {
 | 
			
		||||
  return app.getPath(data)
 | 
			
		||||
})
 | 
			
		||||
@ -137,3 +142,22 @@ ipcMain.handle('login', async (event, host) => {
 | 
			
		||||
 | 
			
		||||
  return tokenSet.access_token
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
const SERVICE_NAME = '_machine-api._tcp.local.'
 | 
			
		||||
 | 
			
		||||
ipcMain.handle('find_machine_api', () => {
 | 
			
		||||
  const timeoutAfterMs = 5000
 | 
			
		||||
  return new Promise((resolve, reject) => {
 | 
			
		||||
    // if it takes too long reject this promise
 | 
			
		||||
    setTimeout(() => resolve(null), timeoutAfterMs)
 | 
			
		||||
    const bonjourEt = new Bonjour({}, (error: Error) => {
 | 
			
		||||
      console.log('An issue with Bonjour services was encountered!')
 | 
			
		||||
      console.error(error)
 | 
			
		||||
      resolve(null)
 | 
			
		||||
    })
 | 
			
		||||
    console.log('Looking for machine API...')
 | 
			
		||||
    bonjourEt.find({ type: SERVICE_NAME }, (service: Service) => {
 | 
			
		||||
      resolve(service.fqdn)
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										33
									
								
								yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								yarn.lock
									
									
									
									
									
								
							@ -1981,6 +1981,11 @@
 | 
			
		||||
    ts-node "^10.9.1"
 | 
			
		||||
    tslib "~2.4"
 | 
			
		||||
 | 
			
		||||
"@leichtgewicht/ip-codec@^2.0.1":
 | 
			
		||||
  version "2.0.5"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz#4fc56c15c580b9adb7dc3c333a134e540b44bfb1"
 | 
			
		||||
  integrity sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==
 | 
			
		||||
 | 
			
		||||
"@lezer/common@^1.0.0", "@lezer/common@^1.1.0":
 | 
			
		||||
  version "1.2.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@lezer/common/-/common-1.2.1.tgz#198b278b7869668e1bebbe687586e12a42731049"
 | 
			
		||||
@ -3333,6 +3338,14 @@ body-parser@1.20.2:
 | 
			
		||||
    type-is "~1.6.18"
 | 
			
		||||
    unpipe "1.0.0"
 | 
			
		||||
 | 
			
		||||
bonjour-service@^1.2.1:
 | 
			
		||||
  version "1.2.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.2.1.tgz#eb41b3085183df3321da1264719fbada12478d02"
 | 
			
		||||
  integrity sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    fast-deep-equal "^3.1.3"
 | 
			
		||||
    multicast-dns "^7.2.5"
 | 
			
		||||
 | 
			
		||||
boolean@^3.0.1:
 | 
			
		||||
  version "3.2.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.2.0.tgz#9e5294af4e98314494cbb17979fa54ca159f116b"
 | 
			
		||||
@ -4052,6 +4065,13 @@ dlv@^1.1.3:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79"
 | 
			
		||||
  integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==
 | 
			
		||||
 | 
			
		||||
dns-packet@^5.2.2:
 | 
			
		||||
  version "5.6.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.6.1.tgz#ae888ad425a9d1478a0674256ab866de1012cf2f"
 | 
			
		||||
  integrity sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@leichtgewicht/ip-codec" "^2.0.1"
 | 
			
		||||
 | 
			
		||||
doctrine@^2.1.0:
 | 
			
		||||
  version "2.1.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
 | 
			
		||||
@ -6596,6 +6616,14 @@ ms@2.1.3, ms@^2.0.0, ms@^2.1.1:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
 | 
			
		||||
  integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
 | 
			
		||||
 | 
			
		||||
multicast-dns@^7.2.5:
 | 
			
		||||
  version "7.2.5"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.5.tgz#77eb46057f4d7adbd16d9290fa7299f6fa64cced"
 | 
			
		||||
  integrity sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    dns-packet "^5.2.2"
 | 
			
		||||
    thunky "^1.0.2"
 | 
			
		||||
 | 
			
		||||
mz@^2.7.0:
 | 
			
		||||
  version "2.7.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
 | 
			
		||||
@ -8452,6 +8480,11 @@ three@^0.166.1:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/three/-/three-0.166.1.tgz#322cfc48fff4e751cd47d61fd1558c387d098d7c"
 | 
			
		||||
  integrity sha512-LtuafkKHHzm61AQA1be2MAYIw1IjmhOUxhBa0prrLpEMWbV7ijvxCRHjSgHPGp2493wLBzwKV46tA9nivLEgKg==
 | 
			
		||||
 | 
			
		||||
thunky@^1.0.2:
 | 
			
		||||
  version "1.1.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d"
 | 
			
		||||
  integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==
 | 
			
		||||
 | 
			
		||||
tiny-each-async@2.0.3:
 | 
			
		||||
  version "2.0.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/tiny-each-async/-/tiny-each-async-2.0.3.tgz#8ebbbfd6d6295f1370003fbb37162afe5a0a51d1"
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user