Skip to content

Commit

Permalink
integrating #653
Browse files Browse the repository at this point in the history
  • Loading branch information
pelikhan committed Nov 6, 2023
1 parent 9897827 commit d374900
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 39 deletions.
10 changes: 1 addition & 9 deletions cli/src/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ import {
toHex,
versionTryParse,
} from "jacdac-ts"
import { execSync } from "node:child_process"
import { BuildOptions } from "./sideprotocol"
import { readJSON5Sync } from "./jsonc"
import { execCmd } from "./exec"

// TODO should we move this to jacdac-ts and call automatically for transports?
export function setupWebsocket() {
Expand Down Expand Up @@ -216,14 +216,6 @@ function toDevsDiag(d: jdspec.Diagnostic): DevsDiagnostic {
}
}

function execCmd(cmd: string) {
try {
return execSync(cmd, { encoding: "utf-8" }).trim()
} catch {
return ""
}
}

function isGit() {
let pref = ""
for (let i = 0; i < 10; ++i) {
Expand Down
9 changes: 9 additions & 0 deletions cli/src/exec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { execSync } from "node:child_process"

export function execCmd(cmd: string) {
try {
return execSync(cmd, { encoding: "utf-8" }).trim()
} catch {
return ""
}
}
11 changes: 2 additions & 9 deletions cli/src/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
existsSync,
} from "fs-extra"
import { build } from "./build"
import { spawnSync, execSync } from "node:child_process"
import { spawnSync } from "node:child_process"
import { assert, clone, randomUInt } from "jacdac-ts"
import { addReqHandler } from "./sidedata"
import type {
Expand All @@ -32,6 +32,7 @@ import { addBoard } from "./addboard"
import { readJSON5Sync } from "./jsonc"
import { MARKETPLACE_EXTENSION_ID } from "@devicescript/interop"
import { TSDOC_TAGS } from "@devicescript/compiler"
import { execCmd } from "./exec"

const MAIN = "src/main.ts"
const GITIGNORE = ".gitignore"
Expand Down Expand Up @@ -570,14 +571,6 @@ export interface AddNpmOptions extends InitOptions {

export interface AddSettingsOptions extends InitOptions {}

export function execCmd(cmd: string) {
try {
return execSync(cmd, { encoding: "utf-8" }).trim()
} catch {
return ""
}
}

export async function addSettings(options: AddSettingsOptions) {
const files = clone(settingsFiles)
const cwd = writeFiles(".", options, files)
Expand Down
2 changes: 0 additions & 2 deletions cli/src/logging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import {
JDBus,
Packet,
PACKET_REPORT,
SRV_DEVICE_SCRIPT_MANAGER,
DeviceScriptManagerCmd,
LoggerPriority,
SRV_LOGGER,
LoggerCmd,
Expand Down
95 changes: 95 additions & 0 deletions cli/src/packageinstaller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { readFile, constants } from "node:fs/promises"
import { accessSync } from "node:fs"
import { join } from "node:path"
import { spawn } from "node:child_process"
import { isInteractive, verboseLog } from "./command"
import { PkgJson } from "@devicescript/compiler"
import { consoleBooleanAsk } from "./prompt"

function isYarnRepo(): boolean {
try {
accessSync(join(process.cwd(), "yarn.lock"), constants.R_OK)
return true
} catch {
return false
}
}

function getPackageInstallerCommand(
packageName?: string
): string[] {
if (isYarnRepo()) {
if (!packageName) return ["yarn", "install"]

return ["yarn", "add", packageName]
}

if (!packageName) return ["npm", "install"]

return ["npm", "install", "--save", "--no-workspaces", packageName]
}

async function isPackageInstalledLocally(pkgName: string): Promise<boolean> {
const pkgJsonString = await readFile(join(process.cwd(), "package.json"), {
encoding: "utf-8",
})
const pkgJson = JSON.parse(pkgJsonString) as PkgJson

return Object.keys(pkgJson.dependencies).includes(pkgName)
}

async function spawnAsyncInstaller(packageName: string) {
let resolve: () => void
let reject: () => void

const [rootCmd, ...cmdArgs] = getPackageInstallerCommand(packageName)

const installProcess = spawn(rootCmd, cmdArgs, {
cwd: process.cwd(),
env: process.env,
})

installProcess.stderr.on("data", data => {
verboseLog(`package installer process: ${data}`)
})

installProcess.on("close", code => {
verboseLog(`install process exit with code ${code}`)

if (code === 0) resolve()
else reject()
})

return new Promise((res, rej) => {
// @ts-ignore
resolve = res
reject = rej
})
}

export async function askForPackageInstallation(
pkgName: string,
installByDefault = true
) {
if (!isInteractive) return

if (await isPackageInstalledLocally(pkgName)) return

const shouldInstallPackage = await consoleBooleanAsk(
`Install package "${pkgName}"`,
installByDefault
)

if (shouldInstallPackage) {
try {
console.log(`Installing package "${pkgName}" ...`)
await spawnAsyncInstaller(pkgName)
console.log(`Package "${pkgName}" installed!`)
} catch (e) {
const installCmd = getPackageInstallerCommand(pkgName).join(" ")
console.log(
`Automatic package installation failed :( You can try to install it manually by running "${installCmd}"`
)
}
}
}
35 changes: 16 additions & 19 deletions cli/src/transport.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { log } from "./command"
import { isInteractive, log } from "./command"
import {
CONNECTION_STATE,
createNodeSPITransport,
Expand Down Expand Up @@ -27,6 +27,7 @@ import type {
SideUploadJsonFromDevice,
} from "@devicescript/interop"
import { printDmesg } from "./vmworker"
import { askForPackageInstallation } from "./packageinstaller"

export interface TransportsOptions {
usb?: boolean
Expand All @@ -40,41 +41,38 @@ export class RequireError extends Error {
}
}

interface RequireOptions {
interactive?: boolean
}

async function tryRequire(name: string, options: RequireOptions) {
async function tryRequire(name: string) {
try {
return require(name)
} catch (e) {
log(`failed to require package "${name}"`)
console.debug(e.stderr?.toString())
if (options.interactive) {
// TODO
if (isInteractive) {
await askForPackageInstallation(name)
return require(name)
}
throw new RequireError(name)
}
}

async function createSPI(options?: RequireOptions) {
async function createSPI() {
log(`adding SPI transport (requires "rpio" package)`)
// eslint-disable-next-line @typescript-eslint/no-var-requires
const RPIO = await tryRequire("rpio", options)
const RPIO = await tryRequire("rpio")
// eslint-disable-next-line @typescript-eslint/no-var-requires
const SpiDev = await tryRequire("spi-device", options)
const SpiDev = await tryRequire("spi-device")
return createNodeSPITransport(RPIO, SpiDev)
}
async function createUSB(options?: RequireOptions) {
async function createUSB() {
log(`adding USB transport (requires "usb" package)`)
const usb = await tryRequire("usb", options)
const usb = await tryRequire("usb")
const usbOptions = createNodeUSBOptions(usb.WebUSB)
return createUSBTransport(usbOptions)
}
async function createSerial(options?: RequireOptions) {
async function createSerial() {
log(`adding serial transport (requires "serialport" package)`)
// eslint-disable-next-line @typescript-eslint/no-var-requires
const sp = await tryRequire("serialport", options)
const sp = await tryRequire("serialport")
return createNodeWebSerialTransport(sp.SerialPort)
}

Expand Down Expand Up @@ -178,10 +176,9 @@ export async function connectTransport(

export async function createTransports(options: TransportsOptions) {
const transports: Transport[] = []
if (options.usb) transports.push(await createUSB({ interactive: true }))
if (options.serial)
transports.push(await createSerial({ interactive: true }))
if (options.spi) transports.push(await createSPI({ interactive: true }))
if (options.usb) transports.push(await createUSB())
if (options.serial) transports.push(await createSerial())
if (options.spi) transports.push(await createSPI())
return transports
}

Expand Down
1 change: 1 addition & 0 deletions interop/src/archconfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ export interface PkgJson {
library?: boolean
bundle?: boolean
}
dependencies?: Record<string, string>
}

export interface LocalBuildConfig {
Expand Down

0 comments on commit d374900

Please sign in to comment.