0

I'm building a small app in node.js that uses execa to read print statements coming from a compiled Swift application. The idea is similar to Sindre Sorhus' (who else!?) do-not-disturb

Although I'm no Swift-programmer, I put together a pretty straightforward solution. The binary is compiled by running swift build --configuration=release from the CL to be used in a node-app. It also compiles fine (without the CLI-part) in a Swift playground from XCode and I can see the correct print statements coming in.

import Cocoa

var isLocked:Bool = false

DistributedNotificationCenter.default().addObserver(forName: .init("com.apple.isScreenLocked"), object: nil, queue: nil) { notification in
    print("Screen is locked")
    isLocked = true
}

DistributedNotificationCenter.default().addObserver(forName: .init("com.apple.isScreenUnlocked"), object: nil, queue: nil) { notification in
    print("Screen is unlocked")
    isLocked = false
}

struct CLI {
    static var standardInput = FileHandle.standardInput
    static var standardOutput = FileHandle.standardOutput
    static var standardError = FileHandle.standardError
    static let arguments = Array(CommandLine.arguments.dropFirst(1))
}

switch CLI.arguments.first {
case "status":
    print(isLocked)
default:
    print("Unsupported command", to: .standardError)
    exit(1)
}

// Some other functions omitted for brevity

Now, when I run the code below from Node.js, everything seems to be working fine. However for some reason, the observer doesn't receive the notification.

'use strict';
const execa = require('execa');
const electronUtil = require('electron-util/node');

const binary = path.join(electronUtil.fixPathForAsarUnpack(__dirname), 'IsLockedOrNot');

setInterval(async () => {
    const {stdout} = await execa(binary, ['status']);
    console.log(stdout) // keeps logging false, also when screen is locked
}, 1000)

Does anyone have any idea WHY the notifications are not being received in this scenario? I tried various things, like explicitly disabling sleep mode shell.exec('sudo pmset -a disablesleep 1')and compiling the app with the --disable-sandbox flag. No luck however until know..

Maarten
  • 635
  • 2
  • 8
  • 22

1 Answers1

0

Use spawn from the base child_process library not execa, make sure you are following stdout, and the most important part for nodejs and swift is that you flush the buffer after every line. Otherwise you have to wait for the program to die before you receive any output. Use "import Darwin.C" and "fflush(stdout)" after every "print" where you want a 'newline'

Andres
  • 106
  • 4