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