diff --git a/Package.resolved b/Package.resolved index ed2a7b3..db40f48 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,25 +1,23 @@ { - "object": { - "pins": [ - { - "package": "Aperture", - "repositoryURL": "https://github.com/wulkano/Aperture", - "state": { - "branch": null, - "revision": "ddfb0fc1b3c789339dd5fd9296ba8076d292611c", - "version": "2.0.1" - } - }, - { - "package": "swift-argument-parser", - "repositoryURL": "https://github.com/apple/swift-argument-parser", - "state": { - "branch": null, - "revision": "82905286cc3f0fa8adc4674bf49437cab65a8373", - "version": "1.1.1" - } + "pins" : [ + { + "identity" : "aperture", + "kind" : "remoteSourceControl", + "location" : "https://github.com/wulkano/Aperture", + "state" : { + "revision" : "ddfb0fc1b3c789339dd5fd9296ba8076d292611c", + "version" : "2.0.1" } - ] - }, - "version": 1 + }, + { + "identity" : "swift-argument-parser", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-argument-parser", + "state" : { + "revision" : "46989693916f56d1186bd59ac15124caef896560", + "version" : "1.3.1" + } + } + ], + "version" : 2 } diff --git a/Package.swift b/Package.swift index 0d1eee6..8a9be6f 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.5 +// swift-tools-version:5.9 import PackageDescription let package = Package( @@ -16,7 +16,7 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/wulkano/Aperture", from: "2.0.1"), - .package(url: "https://github.com/apple/swift-argument-parser", from: "1.1.1") + .package(url: "https://github.com/apple/swift-argument-parser", from: "1.3.1") ], targets: [ .executableTarget( diff --git a/Sources/ApertureCLI/ApertureCLI.swift b/Sources/ApertureCLI/ApertureCLI.swift index 42cb181..94fb4d7 100644 --- a/Sources/ApertureCLI/ApertureCLI.swift +++ b/Sources/ApertureCLI/ApertureCLI.swift @@ -3,170 +3,170 @@ import Aperture import ArgumentParser enum OutEvent: String, CaseIterable, ExpressibleByArgument { - case onStart - case onFileReady - case onPause - case onResume - case onFinish + case onStart + case onFileReady + case onPause + case onResume + case onFinish } enum InEvent: String, CaseIterable, ExpressibleByArgument { - case pause - case resume - case isPaused - case onPause + case pause + case resume + case isPaused + case onPause } extension CaseIterable { - static var asCommaSeparatedList: String { - allCases.map { "\($0)" }.joined(separator: ", ") - } + static var asCommaSeparatedList: String { + allCases.map { "\($0)" }.joined(separator: ", ") + } } @main struct ApertureCLI: ParsableCommand { - static let configuration = CommandConfiguration( - commandName: "aperture", - subcommands: [ - List.self, - Record.self, - Events.self - ] - ) + static let configuration = CommandConfiguration( + commandName: "aperture", + subcommands: [ + List.self, + Record.self, + Events.self + ] + ) } extension ApertureCLI { - struct List: ParsableCommand { - static let configuration = CommandConfiguration( - subcommands: [ - Screens.self, - AudioDevices.self - ] - ) - } - - struct Record: ParsableCommand { - static let configuration = CommandConfiguration(abstract: "Start a recording with the given options.") - - @Option(name: .shortAndLong, help: "The ID to use for this process") - var processId = "main" - - @Argument(help: "Stringified JSON object with options passed to Aperture") - var options: String - - mutating func run() throws { - try record(options, processId: processId) - } - } - - struct Events: ParsableCommand { - static let configuration = CommandConfiguration( - subcommands: [ - Send.self, - Listen.self, - ListenAll.self - ] - ) - } + struct List: ParsableCommand { + static let configuration = CommandConfiguration( + subcommands: [ + Screens.self, + AudioDevices.self + ] + ) + } + + struct Record: ParsableCommand { + static let configuration = CommandConfiguration(abstract: "Start a recording with the given options.") + + @Option(name: .shortAndLong, help: "The ID to use for this process") + var processId = "main" + + @Argument(help: "Stringified JSON object with options passed to Aperture") + var options: String + + mutating func run() throws { + try record(options, processId: processId) + } + } + + struct Events: ParsableCommand { + static let configuration = CommandConfiguration( + subcommands: [ + Send.self, + Listen.self, + ListenAll.self + ] + ) + } } extension ApertureCLI.List { - struct Screens: ParsableCommand { - static let configuration = CommandConfiguration(abstract: "List available screens.") - - mutating func run() throws { - // Uses stderr because of unrelated stuff being outputted on stdout. - print(try toJson(Aperture.Devices.screen().map { ["id": $0.id, "name": $0.name] }), to: .standardError) - } - } - - struct AudioDevices: ParsableCommand { - static let configuration = CommandConfiguration(abstract: "List available audio devices.") - - mutating func run() throws { - // Uses stderr because of unrelated stuff being outputted on stdout. - print(try toJson(Aperture.Devices.audio().map { ["id": $0.id, "name": $0.name] }), to: .standardError) - } - } + struct Screens: ParsableCommand { + static let configuration = CommandConfiguration(abstract: "List available screens.") + + mutating func run() throws { + // Uses stderr because of unrelated stuff being outputted on stdout. + print(try toJson(Aperture.Devices.screen().map { ["id": $0.id, "name": $0.name] }), to: .standardError) + } + } + + struct AudioDevices: ParsableCommand { + static let configuration = CommandConfiguration(abstract: "List available audio devices.") + + mutating func run() throws { + // Uses stderr because of unrelated stuff being outputted on stdout. + print(try toJson(Aperture.Devices.audio().map { ["id": $0.id, "name": $0.name] }), to: .standardError) + } + } } extension ApertureCLI.Events { - struct Send: ParsableCommand { - static let configuration = CommandConfiguration(abstract: "Send an event to the given process.") - - @Flag(inversion: .prefixedNo, help: "Wait for event to be received") - var wait = true - - @Option(name: .shortAndLong, help: "The ID of the target process") - var processId = "main" - - @Argument(help: "Name of the event to send. Can be one of:\n\(InEvent.asCommaSeparatedList)") - var event: InEvent - - @Argument(help: "Data to pass to the event") - var data: String? - - mutating func run() { - ApertureEvents.sendEvent(processId: processId, event: event.rawValue, data: data) { notification in - if let data = notification.data { - print(data) - } - - Foundation.exit(0) - } - - if wait { - RunLoop.main.run() - } - } - } - - struct Listen: ParsableCommand { - static let configuration = CommandConfiguration(abstract: "Listen to an outcoming event for the given process.") - - @Flag(help: "Exit after receiving the event once") - var exit = false - - @Option(name: .shortAndLong, help: "The ID of the target process") - var processId = "main" - - @Argument(help: "Name of the event to listen for. Can be one of:\n\(OutEvent.asCommaSeparatedList)") - var event: OutEvent - - func run() { - _ = ApertureEvents.answerEvent(processId: processId, event: event.rawValue) { notification in - if let data = notification.data { - print(data) - } - - if exit { - notification.answer() - Foundation.exit(0) - } - } - - RunLoop.main.run() - } - } - - struct ListenAll: ParsableCommand { - static let configuration = CommandConfiguration(abstract: "Listen to all outcoming events for the given process.") - - @Option(name: .shortAndLong, help: "The ID of the target process") - var processId = "main" - - func run() { - for event in OutEvent.allCases { - _ = ApertureEvents.answerEvent(processId: processId, event: event.rawValue) { notification in - if let data = notification.data { - print("\(event) \(data)") - } else { - print(event) - } - } - } - - RunLoop.main.run() - } - } + struct Send: ParsableCommand { + static let configuration = CommandConfiguration(abstract: "Send an event to the given process.") + + @Flag(inversion: .prefixedNo, help: "Wait for event to be received") + var wait = true + + @Option(name: .shortAndLong, help: "The ID of the target process") + var processId = "main" + + @Argument(help: "Name of the event to send. Can be one of:\n\(InEvent.asCommaSeparatedList)") + var event: InEvent + + @Argument(help: "Data to pass to the event") + var data: String? + + mutating func run() { + ApertureEvents.sendEvent(processId: processId, event: event.rawValue, data: data) { notification in + if let data = notification.data { + print(data) + } + + Foundation.exit(0) + } + + if wait { + RunLoop.main.run() + } + } + } + + struct Listen: ParsableCommand { + static let configuration = CommandConfiguration(abstract: "Listen to an outcoming event for the given process.") + + @Flag(help: "Exit after receiving the event once") + var exit = false + + @Option(name: .shortAndLong, help: "The ID of the target process") + var processId = "main" + + @Argument(help: "Name of the event to listen for. Can be one of:\n\(OutEvent.asCommaSeparatedList)") + var event: OutEvent + + func run() { + _ = ApertureEvents.answerEvent(processId: processId, event: event.rawValue) { notification in + if let data = notification.data { + print(data) + } + + if exit { + notification.answer() + Foundation.exit(0) + } + } + + RunLoop.main.run() + } + } + + struct ListenAll: ParsableCommand { + static let configuration = CommandConfiguration(abstract: "Listen to all outcoming events for the given process.") + + @Option(name: .shortAndLong, help: "The ID of the target process") + var processId = "main" + + func run() { + for event in OutEvent.allCases { + _ = ApertureEvents.answerEvent(processId: processId, event: event.rawValue) { notification in + if let data = notification.data { + print("\(event) \(data)") + } else { + print(event) + } + } + } + + RunLoop.main.run() + } + } } diff --git a/Sources/ApertureCLI/Utilities.swift b/Sources/ApertureCLI/Utilities.swift index 3d397fe..4033527 100644 --- a/Sources/ApertureCLI/Utilities.swift +++ b/Sources/ApertureCLI/Utilities.swift @@ -2,165 +2,170 @@ import Foundation // MARK: - SignalHandler struct SignalHandler { - struct Signal: Hashable { - static let hangup = Signal(rawValue: SIGHUP) - static let interrupt = Signal(rawValue: SIGINT) - static let quit = Signal(rawValue: SIGQUIT) - static let abort = Signal(rawValue: SIGABRT) - static let kill = Signal(rawValue: SIGKILL) - static let alarm = Signal(rawValue: SIGALRM) - static let termination = Signal(rawValue: SIGTERM) - static let userDefined1 = Signal(rawValue: SIGUSR1) - static let userDefined2 = Signal(rawValue: SIGUSR2) + typealias CSignalHandler = @convention(c) (Int32) -> Void + typealias SignalHandler = (Signal) -> Void + + private static var handlers = [Signal: [SignalHandler]]() + + private static var cHandler: CSignalHandler = { rawSignal in + let signal = Signal(rawValue: rawSignal) + + guard let signalHandlers = handlers[signal] else { + return + } + + for handler in signalHandlers { + handler(signal) + } + } /** - Signals that cause the process to exit. + Handle some signals */ - static let exitSignals = [ - hangup, - interrupt, - quit, - abort, - alarm, - termination - ] - - let rawValue: Int32 - init(rawValue: Int32) { - self.rawValue = rawValue + static func handle(signals: [Signal], handler: @escaping SignalHandler) { + for signal in signals { + // Since Swift has no way of running code on "struct creation", we need to initialize here… + if handlers[signal] == nil { + handlers[signal] = [] + } + + handlers[signal]?.append(handler) + + var signalAction = sigaction( + __sigaction_u: unsafeBitCast(cHandler, to: __sigaction_u.self), + sa_mask: 0, + sa_flags: 0 + ) + + _ = withUnsafePointer(to: &signalAction) { pointer in + sigaction(signal.rawValue, pointer, nil) + } + } } - } - typealias CSignalHandler = @convention(c) (Int32) -> Void - typealias SignalHandler = (Signal) -> Void - - private static var handlers = [Signal: [SignalHandler]]() - - private static var cHandler: CSignalHandler = { rawSignal in - let signal = Signal(rawValue: rawSignal) + /** + Raise a signal. + */ + static func raise(signal: Signal) { + _ = Darwin.raise(signal.rawValue) + } - guard let signalHandlers = handlers[signal] else { - return + /** + Ignore a signal. + */ + static func ignore(signal: Signal) { + _ = Darwin.signal(signal.rawValue, SIG_IGN) } - for handler in signalHandlers { - handler(signal) + /** + Restore default signal handling. + */ + static func restore(signal: Signal) { + _ = Darwin.signal(signal.rawValue, SIG_DFL) } - } +} -/** -Handle some signals -*/ - static func handle(signals: [Signal], handler: @escaping SignalHandler) { - for signal in signals { - // Since Swift has no way of running code on "struct creation", we need to initialize here… - if handlers[signal] == nil { - handlers[signal] = [] - } - handlers[signal]?.append(handler) - - var signalAction = sigaction( - __sigaction_u: unsafeBitCast(cHandler, to: __sigaction_u.self), - sa_mask: 0, - sa_flags: 0 - ) - - _ = withUnsafePointer(to: &signalAction) { pointer in - sigaction(signal.rawValue, pointer, nil) - } +extension SignalHandler { + struct Signal: Hashable { + static let hangup = Signal(rawValue: SIGHUP) + static let interrupt = Signal(rawValue: SIGINT) + static let quit = Signal(rawValue: SIGQUIT) + static let abort = Signal(rawValue: SIGABRT) + static let kill = Signal(rawValue: SIGKILL) + static let alarm = Signal(rawValue: SIGALRM) + static let termination = Signal(rawValue: SIGTERM) + static let userDefined1 = Signal(rawValue: SIGUSR1) + static let userDefined2 = Signal(rawValue: SIGUSR2) + + /** + Signals that cause the process to exit. + */ + static let exitSignals = [ + hangup, + interrupt, + quit, + abort, + alarm, + termination + ] + + let rawValue: Int32 + + init(rawValue: Int32) { + self.rawValue = rawValue + } } - } - - /** - Raise a signal. - */ - static func raise(signal: Signal) { - _ = Darwin.raise(signal.rawValue) - } - - /** - Ignore a signal. - */ - static func ignore(signal: Signal) { - _ = Darwin.signal(signal.rawValue, SIG_IGN) - } - - /** - Restore default signal handling. - */ - static func restore(signal: Signal) { - _ = Darwin.signal(signal.rawValue, SIG_DFL) - } } -extension Array where Element == SignalHandler.Signal { - static let exitSignals = SignalHandler.Signal.exitSignals +extension [SignalHandler.Signal] { + static let exitSignals = SignalHandler.Signal.exitSignals } // MARK: - // MARK: - CLI utils extension FileHandle: TextOutputStream { - public func write(_ string: String) { - write(string.data(using: .utf8)!) - } + public func write(_ string: String) { + write(string.data(using: .utf8)!) + } } enum CLI { - static var standardInput = FileHandle.standardInput - static var standardOutput = FileHandle.standardOutput - static var standardError = FileHandle.standardError + static var standardInput = FileHandle.standardInput + static var standardOutput = FileHandle.standardOutput + static var standardError = FileHandle.standardError - static let arguments = Array(CommandLine.arguments.dropFirst(1)) + static let arguments = Array(CommandLine.arguments.dropFirst(1)) } extension CLI { - private static let once = Once() + private static let once = Once() + + /** + Called when the process exits, either normally or forced (through signals). - /** - Called when the process exits, either normally or forced (through signals). + When this is set, it's up to you to exit the process. + */ + static var onExit: (() -> Void)? { - When this is set, it's up to you to exit the process. - */ - static var onExit: (() -> Void)? { didSet { - guard let exitHandler = onExit else { - return - } + guard let exitHandler = onExit else { + return + } - let handler = { - once.run(exitHandler) - } + let handler = { + once.run(exitHandler) + } - atexit_b { - handler() - } + atexit_b { + handler() + } - SignalHandler.handle(signals: .exitSignals) { _ in - handler() - } + SignalHandler.handle(signals: .exitSignals) { _ in + handler() + } + } } - } - - /** - Called when the process is being forced (through signals) to exit. - When this is set, it's up to you to exit the process. - */ - static var onForcedExit: ((SignalHandler.Signal) -> Void)? { - didSet { - guard let exitHandler = onForcedExit else { - return - } + /** + Called when the process is being forced (through signals) to exit. - SignalHandler.handle(signals: .exitSignals, handler: exitHandler) + When this is set, it's up to you to exit the process. + */ + static var onForcedExit: ((SignalHandler.Signal) -> Void)? { + didSet { + guard let exitHandler = onForcedExit else { + return + } + + SignalHandler.handle(signals: .exitSignals, handler: exitHandler) + } } - } } enum PrintOutputTarget { - case standardOutput - case standardError + case standardOutput + case standardError } /** @@ -169,27 +174,27 @@ Make `print()` accept an array of items. Since Swift doesn't support spreading... */ private func print( - _ items: [Any], - separator: String = " ", - terminator: String = "\n", - to output: inout Target + _ items: [Any], + separator: String = " ", + terminator: String = "\n", + to output: inout Target ) where Target: TextOutputStream { - let item = items.map { "\($0)" }.joined(separator: separator) - Swift.print(item, terminator: terminator, to: &output) + let item = items.map { "\($0)" }.joined(separator: separator) + Swift.print(item, terminator: terminator, to: &output) } func print( - _ items: Any..., - separator: String = " ", - terminator: String = "\n", - to output: PrintOutputTarget = .standardOutput + _ items: Any..., + separator: String = " ", + terminator: String = "\n", + to output: PrintOutputTarget = .standardOutput ) { - switch output { - case .standardOutput: + switch output { + case .standardOutput: print(items, separator: separator, terminator: terminator) - case .standardError: + case .standardError: print(items, separator: separator, terminator: terminator, to: &CLI.standardError) - } + } } // MARK: - @@ -205,53 +210,53 @@ func synchronized(lock: AnyObject, closure: () throws -> T) rethrows -> T { } final class Once { - private var hasRun = false + private var hasRun = false - /** - Executes the given closure only once (thread-safe) + /** + Executes the given closure only once (thread-safe) - ``` - final class Foo { + ``` + final class Foo { private let once = Once() func bar() { - once.run { + once.run { print("Called only once") - } + } + } } - } - - let foo = Foo() - foo.bar() - foo.bar() - ``` - */ - func run(_ closure: () -> Void) { - synchronized(lock: self) { - guard !hasRun else { - return - } - - hasRun = true - closure() + + let foo = Foo() + foo.bar() + foo.bar() + ``` + */ + func run(_ closure: () -> Void) { + synchronized(lock: self) { + guard !hasRun else { + return + } + + hasRun = true + closure() + } } - } } extension Data { - func jsonDecoded() throws -> T { - try JSONDecoder().decode(T.self, from: self) - } + func jsonDecoded() throws -> T { + try JSONDecoder().decode(T.self, from: self) + } } extension String { - func jsonDecoded() throws -> T { - try data(using: .utf8)!.jsonDecoded() - } + func jsonDecoded() throws -> T { + try data(using: .utf8)!.jsonDecoded() + } } func toJson(_ data: T) throws -> String { - let json = try JSONSerialization.data(withJSONObject: data) - return String(data: json, encoding: .utf8)! + let json = try JSONSerialization.data(withJSONObject: data) + return String(data: json, encoding: .utf8)! } // MARK: - diff --git a/Sources/ApertureCLI/notifications.swift b/Sources/ApertureCLI/notifications.swift index 4637e22..d26769e 100644 --- a/Sources/ApertureCLI/notifications.swift +++ b/Sources/ApertureCLI/notifications.swift @@ -22,8 +22,8 @@ final class ApertureNotification { isAnswered = true guard - let responseIdentifier: String = getField("responseIdentifier") - else { + let responseIdentifier: String = getField("responseIdentifier") + else { return } @@ -48,7 +48,7 @@ enum ApertureEvents { event: String, using handler: @escaping (ApertureNotification) -> Void ) -> NSObjectProtocol { - DistributedNotificationCenter.default().addObserver( + DistributedNotificationCenter.default().addObserver( forName: .init(ApertureNotification.notificationName(forEvent: event, processId: processId)), object: nil, queue: nil @@ -59,7 +59,7 @@ enum ApertureEvents { if !apertureNotification.isAnswered { apertureNotification.answer() } - } + } } static func sendEvent( @@ -78,7 +78,6 @@ enum ApertureEvents { } var observer: AnyObject? - observer = DistributedNotificationCenter.default().addObserver( forName: .init(responseIdentifier), object: nil, @@ -104,10 +103,10 @@ enum ApertureEvents { using callback: @escaping (ApertureNotification) -> Void ) { sendEvent( - processId: processId, - event: event, - data: nil, - using: callback + processId: processId, + event: event, + data: nil, + using: callback ) } @@ -117,9 +116,9 @@ enum ApertureEvents { data: Any? = nil ) { sendEvent( - processId: processId, - event: event, - data: data + processId: processId, + event: event, + data: data ) { _ in } } } diff --git a/example.js b/example.js index 395940d..8e62318 100644 --- a/example.js +++ b/example.js @@ -1,6 +1,11 @@ import fs from 'node:fs'; import timers from 'node:timers/promises'; -import {recorder, screens, audioDevices, videoCodecs} from './index.js'; +import { + recorder, + screens, + audioDevices, + videoCodecs, +} from './index.js'; async function main() { console.log('Screens:', await screens()); diff --git a/index.js b/index.js index b03bbd4..65bdda6 100644 --- a/index.js +++ b/index.js @@ -6,15 +6,15 @@ import {execa} from 'execa'; import {temporaryFile} from 'tempy'; import {assertMacOSVersionGreaterThanOrEqualTo} from 'macos-version'; import fileUrl from 'file-url'; -import electronUtil from 'electron-util/node.js'; +import {fixPathForAsarUnpack} from 'electron-util/node'; import delay from 'delay'; const log = debuglog('aperture'); const getRandomId = () => Math.random().toString(36).slice(2, 15); -const __dirname = path.dirname(url.fileURLToPath(import.meta.url)); +const dirname_ = path.dirname(url.fileURLToPath(import.meta.url)); // Workaround for https://github.com/electron/electron/issues/9459 -const BIN = path.join(electronUtil.fixPathForAsarUnpack(__dirname), 'aperture'); +const BINARY = path.join(fixPathForAsarUnpack(dirname_), 'aperture'); const supportsHevcHardwareEncoding = (() => { const cpuModel = os.cpus()[0].model; @@ -138,7 +138,7 @@ class Recorder { return this.tmpPath; })(); - this.recorder = execa(BIN, [ + this.recorder = execa(BINARY, [ 'record', '--process-id', this.processId, @@ -157,7 +157,7 @@ class Recorder { } async waitForEvent(name, parse) { - const {stdout} = await execa(BIN, [ + const {stdout} = await execa(BINARY, [ 'events', 'listen', '--process-id', @@ -172,7 +172,7 @@ class Recorder { } async sendEvent(name, parse) { - const {stdout} = await execa(BIN, [ + const {stdout} = await execa(BINARY, [ 'events', 'send', '--process-id', @@ -225,27 +225,29 @@ class Recorder { export const recorder = new Recorder(); +const removeWarnings = string => string.split('\n').filter(line => !line.includes('] WARNING:')).join('\n'); + export const screens = async () => { - const {stderr} = await execa(BIN, ['list', 'screens']); + const {stderr} = await execa(BINARY, ['list', 'screens']); try { - return JSON.parse(stderr); - } catch { - return stderr; + return JSON.parse(removeWarnings(stderr)); + } catch (error) { + throw new Error(stderr, {cause: error}); } }; export const audioDevices = async () => { - const {stderr} = await execa(BIN, ['list', 'audio-devices']); + const {stderr} = await execa(BINARY, ['list', 'audio-devices']); try { - return JSON.parse(stderr); - } catch { - return stderr; + return JSON.parse(removeWarnings(stderr)); + } catch (error) { + throw new Error(stderr, {cause: error}); } }; -const codecs = new Map([ +export const videoCodecs = new Map([ ['h264', 'H264'], ['hevc', 'HEVC'], ['proRes422', 'Apple ProRes 422'], @@ -253,7 +255,5 @@ const codecs = new Map([ ]); if (!supportsHevcHardwareEncoding) { - codecs.delete('hevc'); + videoCodecs.delete('hevc'); } - -export const videoCodecs = codecs; diff --git a/index.test-d.ts b/index.test-d.ts index a63b7d1..d199919 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -1,6 +1,14 @@ import {expectType, expectError} from 'tsd'; -import type {Recorder, Screen, AudioDevice, VideoCodec} from './index.js'; -import {recorder, audioDevices, screens, videoCodecs} from './index.js'; +import { + recorder, + audioDevices, + screens, + videoCodecs, + type Recorder, + type Screen, + type AudioDevice, + type VideoCodec, +} from './index.js'; expectType(recorder); diff --git a/package.json b/package.json index 7249786..1cdddbb 100644 --- a/package.json +++ b/package.json @@ -25,17 +25,17 @@ ], "dependencies": { "delay": "^6.0.0", - "electron-util": "^0.17.2", + "electron-util": "^0.18.1", "execa": "^8.0.1", "file-url": "^4.0.0", "macos-version": "^6.0.0", "tempy": "^3.1.0" }, "devDependencies": { - "ava": "^5.3.1", - "file-type": "^18.7.0", - "read-chunk": "^4.0.0", + "ava": "^6.1.2", + "file-type": "^19.0.0", + "read-chunk": "^4.0.3", "tsd": "^0.30.7", - "xo": "^0.56.0" + "xo": "^0.58.0" } } diff --git a/test.js b/test.js index 6bc4b25..f060969 100644 --- a/test.js +++ b/test.js @@ -3,7 +3,12 @@ import test from 'ava'; import delay from 'delay'; import {fileTypeFromBuffer} from 'file-type'; import {readChunk} from 'read-chunk'; -import {recorder, audioDevices, screens, videoCodecs} from './index.js'; +import { + recorder, + audioDevices, + screens, + videoCodecs, +} from './index.js'; test('returns audio devices', async t => { const devices = await audioDevices();