Fixup machine-api

This commit is contained in:
49lf
2024-08-08 15:56:25 -04:00
parent c653fc541f
commit 7bacbf4f37
9 changed files with 100 additions and 32 deletions

3
interface.d.ts vendored
View File

@ -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 {

View File

@ -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",

View File

@ -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
}
>

View File

@ -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

View File

@ -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,
})
})

View File

@ -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()
// 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()
}
}

View File

@ -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 = ''

View File

@ -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)
})
})
})

View File

@ -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"