aboutsummaryrefslogtreecommitdiff
path: root/linux/home/.config/ags/service/nix.ts
blob: 3bde9fcd1e25c39894162bec404978ff64915c07 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import icons from "lib/icons"
import { bash, dependencies } from "lib/utils"
import options from "options"

const CACHE = `${Utils.CACHE_DIR}/nixpkgs`
const PREFIX = "legacyPackages.x86_64-linux."
const MAX = options.launcher.nix.max
const nixpkgs = options.launcher.nix.pkgs

export type Nixpkg = {
    name: string
    description: string
    pname: string
    version: string
}

class Nix extends Service {
    static {
        Service.register(this, {}, {
            "available": ["boolean", "r"],
            "ready": ["boolean", "rw"],
        })
    }

    #db: { [name: string]: Nixpkg } = {}
    #ready = true

    private set ready(r: boolean) {
        this.#ready = r
        this.changed("ready")
    }

    get db() { return this.#db }
    get ready() { return this.#ready }
    get available() { return Utils.exec("which nix") }

    constructor() {
        super()
        if (!this.available)
            return this

        this.#updateList()
        nixpkgs.connect("changed", this.#updateList)
    }

    query = async (filter: string) => {
        if (!dependencies("fzf", "nix") || !this.#ready)
            return [] as string[]

        return bash(`cat ${CACHE} | fzf -f ${filter} -e | head -n ${MAX} `)
            .then(str => str.split("\n").filter(i => i))
    }

    nix(cmd: string, bin: string, args: string) {
        return Utils.execAsync(`nix ${cmd} ${nixpkgs}#${bin} --impure ${args}`)
    }

    run = async (input: string) => {
        if (!dependencies("nix"))
            return

        try {
            const [bin, ...args] = input.trim().split(/\s+/)

            this.ready = false
            await this.nix("shell", bin, "--command sh -c 'exit'")
            this.ready = true

            this.nix("run", bin, ["--", ...args].join(" "))
        } catch (err) {
            if (typeof err === "string")
                Utils.notify("NixRun Error", err, icons.nix.nix)
            else
                logError(err)
        } finally {
            this.ready = true
        }
    }

    #updateList = async () => {
        if (!dependencies("nix"))
            return

        this.ready = false
        this.#db = {}

        // const search = await bash(`nix search ${nixpkgs} --json`)
        const search = ""
        if (!search) {
            this.ready = true
            return
        }

        const json = Object.entries(JSON.parse(search) as {
            [name: string]: Nixpkg
        })

        for (const [pkg, info] of json) {
            const name = pkg.replace(PREFIX, "")
            this.#db[name] = { ...info, name }
        }

        const list = Object.keys(this.#db).join("\n")
        await Utils.writeFile(list, CACHE)
        this.ready = true
    }
}

export default new Nix