summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--README.md219
-rw-r--r--flake.lock27
-rw-r--r--flake.nix58
-rw-r--r--js/.eslintrc.yml128
-rw-r--r--js/.gitignore4
-rw-r--r--js/.ts-for-girrc.js7
-rw-r--r--js/gjs/application.ts51
-rw-r--r--js/gjs/astal.ts37
-rw-r--r--js/gjs/widgets.ts60
-rw-r--r--js/node/application.ts51
-rw-r--r--js/node/astal.ts38
-rw-r--r--js/node/widgets.ts63
-rw-r--r--js/package-lock.json4038
-rw-r--r--js/package.json20
-rwxr-xr-xjs/sample.gjs.js43
-rwxr-xr-xjs/sample.node.js49
-rw-r--r--js/src/application.ts28
-rw-r--r--js/src/astalify.ts213
-rw-r--r--js/src/binding.ts78
-rw-r--r--js/src/process.ts83
-rw-r--r--js/src/time.ts27
-rw-r--r--js/src/variable.ts250
-rw-r--r--js/tsconfig.json23
-rw-r--r--lua/astal/application.lua76
-rw-r--r--lua/astal/binding.lua65
-rw-r--r--lua/astal/init.lua30
-rw-r--r--lua/astal/process.lua93
-rw-r--r--lua/astal/time.lua27
-rw-r--r--lua/astal/variable.lua270
-rw-r--r--lua/astal/widget.lua123
-rwxr-xr-xlua/sample.lua81
-rw-r--r--lua/stylua.toml3
-rw-r--r--meson-install.sh16
-rw-r--r--meson.build17
-rw-r--r--meson_options.txt2
-rw-r--r--python/.gitignore1
-rw-r--r--python/astal/__init__.py16
-rw-r--r--python/astal/application.py62
-rw-r--r--python/astal/binding.py33
-rw-r--r--python/astal/variable.py100
-rw-r--r--python/astal/widget.py65
-rw-r--r--python/pyproject.toml14
-rw-r--r--python/ruff.toml62
-rwxr-xr-xpython/sample.py31
-rw-r--r--src/astal.vala171
-rw-r--r--src/client.vala.in79
-rw-r--r--src/meson.build85
-rw-r--r--src/process.vala126
-rw-r--r--src/time.vala68
-rw-r--r--src/variable.vala190
-rw-r--r--src/widget/box.vala60
-rw-r--r--src/widget/button.vala35
-rw-r--r--src/widget/centerbox.vala35
-rw-r--r--src/widget/circularprogress.vala174
-rw-r--r--src/widget/eventbox.vala39
-rw-r--r--src/widget/icon.vala87
-rw-r--r--src/widget/widget.vala132
-rw-r--r--src/widget/window.vala136
-rw-r--r--version1
60 files changed, 8205 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f047207
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+build/
+result
+.cache/
+test.sh
+tmp/
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..76c7ee1
--- /dev/null
+++ b/README.md
@@ -0,0 +1,219 @@
+# libastal
+
+> [!WARNING]
+> WIP: everything is subject to change
+
+The main goal of this project is to further abstract gtk bindings in higher level
+languages with custom state management mechanisms namely in javascript (gjs, node),
+lua (lua-lgi) and python (pygobject)
+
+libastal, which is the library written in Vala, comes with
+a few widgets built on top of gtk3 and
+tools to execute external binaries and store their output
+it also comes with a builtin cli client
+
+## Developing
+
+first install libastal or enter nix shell
+
+```bash
+bash meson-install.sh # non nix
+nix develop .#astal # nix
+```
+
+python and lua should be stright forward, have a look at sample.py and sample.lua
+
+for javascript do
+
+```bash
+cd js
+npm i
+npm run types
+npm run build -- --watch
+```
+
+## Gtk abstractions
+
+`Variable` and `Binding` objects and a function that turns widget constructors
+into ones that can take `Binding` objects as parameters are added ontop of gtk bindings
+this mechanism takes care of all state management one would need
+
+This works the same in js/lua/python, its just demonstrated in js
+
+```javascript
+// this example will work with Variable<string>
+// but it can take any type of value
+const v = Variable("value")
+ .poll(1000, "some-executable on $PATH")
+ .poll(1000, ["some-executable", "with", "args"])
+ .poll(1000, () => "some-function")
+ .watch("some-executable")
+ .watch(["some-executable", "with", "args"])
+ .observe(someGObject, "signal", (...args) => "some output")
+ .observe([[gobj1, "signal"], [gobj2, "signal"]], (...args) => "some output")
+ .onError(console.error) // when the script fails
+ .onDropped(() => "clean-up") // cleanup resources if needed on drop() or GC
+
+Button({
+ label: bind(v),
+ label: bind(v).as(v => "transformed"),
+ label: v(t => "transformed"), // shorthand for the above
+
+ // in ags we have Service.bind("prop")
+ // here we will do this, since gobject implementations
+ // will come from Vala code and not js
+ label: bind(anyGObject, "one-of-its-prop").as(prop => "transformed"),
+
+ // event handlers
+ on_signalname(self, ...args) { print(self, args) },
+
+ // setup prop is still here, but should be rarely needed
+ setup(self) {
+ self.hook(v, (self) => print(self))
+ self.hook(gobject, "signal", (self) => print(self))
+ }
+})
+
+// some additional Variable and Binding methods
+v.stop_poll()
+v.start_poll()
+
+v.stop_watch()
+v.start_watch()
+
+v.get()
+v.set("new-value")
+
+const unsub = v.subscribe(value => console.log(value))
+unsub() // to unsubscribe
+
+const b = bind(v)
+b.get()
+// note that its value cannot be set through a Binding
+// if you want to, you are doing something wrong
+
+// same subscribe mechanism
+const unsub = b.subscribe(value => console.log(value))
+unsub()
+
+const derived = Variable.derive([v, b], (vval, bval) => {
+ return "can take a list of Variable | Binding"
+})
+
+v.drop() // dispose when no longer needed
+
+// handle cli client
+App.start({
+ instanceName: "my-instance",
+ responseHandler(msg, response) {
+ console.log("message from cli", msg)
+ response("hi")
+ }
+})
+```
+
+after `App.start` is called, it will open a socket, which can be used
+with the cli client that comes with libastal
+
+```bash
+astal --instance-name my-instance "message was sent from cli"
+```
+
+## Lower level languages
+
+As said before, the main goal is to make js/lua/python dx better, but libastal
+can be used in **any** language that has bindings for glib/gtk.
+`Binding` is not implemented in Vala, but in each language, because
+they are language specific, and it doesn't make much sense for lower
+level languages as they usually don't have a way to declaratively build
+layouts. Subclassed widgets and `Variable` can still be used, but they will
+need to be hooked **imperatively**. For languages like rust/go/c++
+you will mostly benefit from the other libraries (called `Service` in ags).
+I can also recommend using [blueprint](https://jwestman.pages.gitlab.gnome.org/blueprint-compiler/)
+which lets you define layouts declaratively and hook functionality in your
+preferred language.
+
+I am open to add support for any other language if it makes sense,
+but if using blueprint makes more sense, I would rather maintain
+templates and examples instead to get started with development.
+
+## Goals
+
+- libastal
+ - Variables
+ - [x] poll (interval, string)
+ - [x] pollv (interval, string[])
+ - [x] pollfn (interval, closure)
+ - [x] watch (string)
+ - [x] watchv (string[])
+ - [ ] ?observe (object, signal, closure)
+ - Time
+ - [x] interval
+ - [x] timeout
+ - [x] idle
+ - [x] now signal
+ - Process
+ - [x] exec: string, error as Error
+ - [x] execAsync: proc, stdout, stderr signal
+ - [x] subprocess: proc, stdout, stderr signal
+ - app instance with a socket: Application
+ - [x] gtk settings as props
+ - [x] window getters
+ - [x] include cli client
+ - few additional widgets
+ - [x] window widget with gtk-layer-shell
+ - [x] box with children prop
+ - [ ] button with abstract signals for button-event
+ - [ ] ?custom calendar like gtk4
+ - [x] centerbox
+ - [ ] circularprogress
+ - [ ] eventbox
+ - [ ] icon
+ - [ ] overlay
+ - [ ] scrollable/viewport
+ - [ ] slider
+ - [ ] stack, shown, children setter
+ - widgets with no additional behaviour only for the sake of it
+ - [ ] ?drawingarea
+ - [ ] ?entry
+ - [ ] ?fixed
+ - [ ] ?flowbox
+ - [ ] ?label
+ - [ ] ?levelbar
+ - [ ] ?revealer
+ - [ ] ?switch
+ - widget prop setters
+ - [x] css
+ - [x] class-names
+ - [x] cursor
+ - [ ] click-through
+
+- language bindings
+ - Binding for Variable and any GObject `bind(gobject, property).as(transform)`
+ - .hook() for widgets
+ - setup prop for widgets
+ - constructor overrides to take bindings
+ - override default `visible` for widgets to true
+ - wrap Variable in native object to make sure no GValue crashes
+ - Variable.observe for signals
+ - Variable.derive that takes either Variables or Bindings
+
+## Help needed
+
+- packaging
+ - I am not familiar with python or lua ecosystem at all how should they be distributed?
+- node-gtk promise issue
+- python types
+ - I don't know much python, and quite honestly I hate python
+
+## TODO
+
+- docs
+- consider moving each language into separate repo
+ - I want to keep these at one place until I'm sure all of them works as expected
+- support jsx
+- make sure conventions like the casing of names are followed for each language
+ - I constantly switched between 4 languages they might be off
+
+- port services from ags into Vala
+ - and add more
diff --git a/flake.lock b/flake.lock
new file mode 100644
index 0000000..df4c399
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,27 @@
+{
+ "nodes": {
+ "nixpkgs": {
+ "locked": {
+ "lastModified": 1715266358,
+ "narHash": "sha256-doPgfj+7FFe9rfzWo1siAV2mVCasW+Bh8I1cToAXEE4=",
+ "owner": "nixos",
+ "repo": "nixpkgs",
+ "rev": "f1010e0469db743d14519a1efd37e23f8513d714",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nixos",
+ "ref": "nixos-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "root": {
+ "inputs": {
+ "nixpkgs": "nixpkgs"
+ }
+ }
+ },
+ "root": "root",
+ "version": 7
+}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..79d8180
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,58 @@
+{
+ inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
+
+ outputs = { self, nixpkgs }:
+ let
+ version = builtins.replaceStrings ["\n"] [""] (builtins.readFile ./version);
+ system = "x86_64-linux";
+ pkgs = import nixpkgs { inherit system; };
+
+ nativeBuildInputs = with pkgs; [
+ wrapGAppsHook
+ gobject-introspection
+ meson
+ pkg-config
+ ninja
+ vala
+ ];
+
+ buildInputs = with pkgs; [
+ glib
+ gtk3
+ gtk-layer-shell
+ ];
+ in {
+ packages.${system} = rec {
+ default = astal;
+ astal = pkgs.stdenv.mkDerivation {
+ inherit nativeBuildInputs buildInputs;
+ pname = "astal";
+ version = version;
+ src = ./.;
+ outputs = ["out" "dev"];
+ };
+ };
+
+ devShells.${system} = let
+ inputs = with pkgs; buildInputs ++ [
+ (lua.withPackages(ps: [ps.lgi]))
+ (python3.withPackages(ps: [ps.pygobject3]))
+ gjs
+ deno
+ nodejs
+ ];
+ in {
+ default = pkgs.mkShell {
+ inherit nativeBuildInputs;
+ buildInputs = inputs;
+ };
+ astal = pkgs.mkShell {
+ inherit nativeBuildInputs;
+ buildInputs = inputs ++ [
+ self.packages.${system}.astal
+ pkgs.playerctl # FIXME: just for demo
+ ];
+ };
+ };
+ };
+}
diff --git a/js/.eslintrc.yml b/js/.eslintrc.yml
new file mode 100644
index 0000000..6eeee79
--- /dev/null
+++ b/js/.eslintrc.yml
@@ -0,0 +1,128 @@
+env:
+ es2021: true
+extends:
+ - "eslint:recommended"
+ - "plugin:@typescript-eslint/recommended"
+parser: "@typescript-eslint/parser"
+parserOptions:
+ ecmaVersion: 2022
+ sourceType: "module"
+ project: "./tsconfig.json"
+ warnOnUnsupportedTypeScriptVersion: false
+root: true
+ignorePatterns:
+ - example/
+ - types/
+ - gi-types/
+ - _build/
+ - build/
+ - result/
+plugins:
+ - "@typescript-eslint"
+rules:
+ "@typescript-eslint/ban-ts-comment": error
+ "@typescript-eslint/no-non-null-assertion": off
+ "@typescript-eslint/no-explicit-any": off
+ "@typescript-eslint/no-unused-vars":
+ - error
+ - varsIgnorePattern: (^unused|_$)
+ argsIgnorePattern: ^(unused|_)
+ "@typescript-eslint/no-empty-interface": off
+ "@typescript-eslint/no-namespace": off
+ "@typescript-eslint/prefer-namespace-keyword": off
+ "@typescript-eslint/ban-types": off
+
+ arrow-parens:
+ - error
+ - as-needed
+ comma-dangle:
+ - error
+ - always-multiline
+ comma-spacing:
+ - error
+ - before: false
+ after: true
+ comma-style:
+ - error
+ - last
+ curly:
+ - error
+ - multi-or-nest
+ - consistent
+ dot-location:
+ - error
+ - property
+ eol-last:
+ - error
+ indent:
+ - error
+ - 4
+ - SwitchCase: 1
+ keyword-spacing:
+ - error
+ - before: true
+ lines-between-class-members:
+ - error
+ - always
+ - exceptAfterSingleLine: true
+ padded-blocks:
+ - error
+ - never
+ - allowSingleLineBlocks: false
+ prefer-const:
+ - error
+ quotes:
+ - error
+ - double
+ - avoidEscape: true
+ semi:
+ - error
+ - never
+ nonblock-statement-body-position:
+ - error
+ - below
+ no-trailing-spaces:
+ - error
+ no-useless-escape:
+ - off
+ max-len:
+ - error
+ - code: 100
+
+ func-call-spacing:
+ - error
+ array-bracket-spacing:
+ - error
+ space-before-function-paren:
+ - error
+ - anonymous: never
+ named: never
+ asyncArrow: ignore
+ space-before-blocks:
+ - error
+ key-spacing:
+ - error
+ object-curly-spacing:
+ - error
+ - always
+
+globals:
+ pkg: readonly
+ ARGV: readonly
+ Debugger: readonly
+ GIRepositoryGType: readonly
+ globalThis: readonly
+ imports: readonly
+ Intl: readonly
+ log: readonly
+ logError: readonly
+ print: readonly
+ printerr: readonly
+ window: readonly
+ TextEncoder: readonly
+ TextDecoder: readonly
+ console: readonly
+ setTimeout: readonly
+ setInterval: readonly
+ clearTimeout: readonly
+ clearInterval: readonly
diff --git a/js/.gitignore b/js/.gitignore
new file mode 100644
index 0000000..3ab63b7
--- /dev/null
+++ b/js/.gitignore
@@ -0,0 +1,4 @@
+node_modules
+result
+@girs/
+dist/
diff --git a/js/.ts-for-girrc.js b/js/.ts-for-girrc.js
new file mode 100644
index 0000000..aa5c124
--- /dev/null
+++ b/js/.ts-for-girrc.js
@@ -0,0 +1,7 @@
+export default {
+ "verbose": true,
+ "environments": ["gjs", "node"],
+ "outdir": "@girs",
+ "package": true,
+ "generateAlias": true,
+}
diff --git a/js/gjs/application.ts b/js/gjs/application.ts
new file mode 100644
index 0000000..32dcda7
--- /dev/null
+++ b/js/gjs/application.ts
@@ -0,0 +1,51 @@
+import Astal from "gi://Astal"
+import GObject from "gi://GObject"
+import Gio from "gi://Gio"
+import { RequestHandler, Config, runJS } from "../src/application.js"
+
+// @ts-expect-error missing types
+// https://github.com/gjsify/ts-for-gir/issues/164
+import { setConsoleLogDomain } from "console"
+import { exit, programArgs } from "system"
+
+class AstalJS extends Astal.Application {
+ static { GObject.registerClass(this) }
+
+ eval = runJS
+ requestHandler?: RequestHandler
+
+ vfunc_response(msg: string, conn: Gio.SocketConnection): void {
+ if (typeof this.requestHandler === "function") {
+ this.requestHandler(msg, response => {
+ Astal.write_sock(conn, response, (_, res) =>
+ Astal.write_sock_finish(res),
+ )
+ })
+ } else {
+ super.vfunc_response(msg, conn)
+ }
+ }
+
+ start({ requestHandler, css, hold, ...cfg }: Config = {}, callback?: (args: string[]) => void) {
+ Object.assign(this, cfg)
+ setConsoleLogDomain(this.instanceName)
+
+ this.requestHandler = requestHandler
+ this.connect("activate", () => callback?.(programArgs))
+ if (!this.acquire_socket()) {
+ print(`Astal instance "${this.instanceName}" already running`)
+ exit(1)
+ }
+
+ if (css)
+ this.apply_css(css, false)
+
+ hold ??= true
+ if (hold)
+ this.hold()
+
+ this.runAsync([])
+ }
+}
+
+export const App = new AstalJS
diff --git a/js/gjs/astal.ts b/js/gjs/astal.ts
new file mode 100644
index 0000000..0665498
--- /dev/null
+++ b/js/gjs/astal.ts
@@ -0,0 +1,37 @@
+import Astal from "gi://Astal"
+import Time from "../src/time.js"
+import Process from "../src/process.js"
+import * as variable from "../src/variable.js"
+
+const { interval, timeout, idle } = Time(Astal.Time)
+const { subprocess, exec, execAsync } = Process({
+ defaultOut: print,
+ defaultErr: console.error,
+ exec: Astal.Process.exec,
+ execv: Astal.Process.execv,
+ execAsync: Astal.Process.exec_async,
+ execAsyncv: Astal.Process.exec_asyncv,
+ subprocess: Astal.Process.subprocess,
+ subprocessv: Astal.Process.subprocessv,
+})
+
+variable.config.defaultErrHandler = print
+variable.config.execAsync = execAsync
+variable.config.subprocess = subprocess
+variable.config.interval = interval
+variable.config.VariableBase = Astal.VariableBase
+Object.freeze(variable.config)
+
+export { subprocess, exec, execAsync }
+export { interval, timeout, idle }
+export { bind } from "../src/binding.js"
+export { Variable } from "../src/variable.js"
+export * as Widget from "./widgets.js"
+export { App } from "./application.js"
+
+// for convinience
+export { default as GLib } from "gi://GLib?version=2.0"
+export { default as Gtk } from "gi://Gtk?version=3.0"
+export { default as Gio } from "gi://Gio?version=2.0"
+export { default as GObject } from "gi://GObject?version=2.0"
+export { default as Astal } from "gi://Astal?version=0.1"
diff --git a/js/gjs/widgets.ts b/js/gjs/widgets.ts
new file mode 100644
index 0000000..29af9a2
--- /dev/null
+++ b/js/gjs/widgets.ts
@@ -0,0 +1,60 @@
+/* eslint-disable max-len */
+import Gtk from "gi://Gtk"
+import Astal from "gi://Astal"
+import { kebabify } from "../src/binding.js"
+import proxy, { type ConstructProps, type Widget } from "../src/astalify.js"
+
+const proxify = proxy(Gtk,
+ prop => `set_${kebabify(prop).replaceAll("-", "_")}`,
+ {
+ cssGetter: Astal.widget_get_css,
+ cssSetter: Astal.widget_set_css,
+ classGetter: Astal.widget_get_class_names,
+ classSetter: Astal.widget_set_class_names,
+ cursorGetter: Astal.widget_get_cursor,
+ cursorSetter: Astal.widget_set_cursor,
+ })
+
+export function astalify<
+ C extends typeof Gtk.Widget,
+ P extends Record<string, any>,
+ N extends string = "Widget",
+>(klass: C) {
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ type Astal<N> = Omit<C, "new"> & {
+ new(props?: P, ...children: Gtk.Widget[]): Widget<C>
+ (props?: P, ...children: Gtk.Widget[]): Widget<C>
+ }
+
+ return proxify(klass) as unknown as Astal<N>
+}
+
+// Label
+export const Label = astalify<typeof Gtk.Label, LabelProps, "Label">(Gtk.Label)
+export type LabelProps = ConstructProps<typeof Gtk.Label, Gtk.Label.ConstructorProperties>
+
+// Icon
+export const Icon = astalify<typeof Astal.Icon, IconProps, "Icon">(Astal.Icon)
+export type IconProps = ConstructProps<typeof Astal.Icon, Astal.Icon.ConstructorProperties>
+
+// Button
+export const Button = astalify<typeof Astal.Button, ButtonProps, "Button">(Astal.Button)
+export type ButtonProps = ConstructProps<typeof Astal.Button, Astal.Button.ConstructorProperties, {
+ onClicked: (self: Widget<typeof Astal.Button>) => void
+}>
+
+// Window
+export const Window = astalify<typeof Astal.Window, WindowProps, "Window">(Astal.Window)
+export type WindowProps = ConstructProps<typeof Astal.Window, Astal.Window.ConstructorProperties>
+
+// Box
+export const Box = astalify<typeof Astal.Box, BoxProps, "Box">(Astal.Box)
+export type BoxProps = ConstructProps<typeof Astal.Box, Astal.Box.ConstructorProperties>
+
+// CenterBox
+export const CenterBox = astalify<typeof Astal.CenterBox, CenterBoxProps, "CenterBox">(Astal.CenterBox)
+export type CenterBoxProps = ConstructProps<typeof Astal.CenterBox, Astal.CenterBox.ConstructorProperties>
+
+// EventBox
+export const EventBox = astalify<typeof Astal.EventBox, EventBoxProps, "EventBox">(Astal.EventBox)
+export type EventBoxProps = ConstructProps<typeof Astal.EventBox, Astal.EventBox.ConstructorProperties>
diff --git a/js/node/application.ts b/js/node/application.ts
new file mode 100644
index 0000000..875c1c8
--- /dev/null
+++ b/js/node/application.ts
@@ -0,0 +1,51 @@
+import gi from "node-gtk"
+import { RequestHandler, Config, runJS } from "../src/application.js"
+const Astal = gi.require("Astal", "0.1")
+
+class AstalJS extends Astal.Application {
+ static GTypeName = "AstalJS"
+ static { gi.registerClass(this) }
+
+ eval = runJS
+ requestHandler?: RequestHandler
+
+ vfunc_response(msg: string, conn: any): void {
+ if (typeof this.requestHandler === "function") {
+ this.requestHandler(msg, response => {
+ Astal.writeSock(conn, response, (_, res) =>
+ Astal.writeSockFinish(res),
+ )
+ })
+ } else {
+ // @ts-expect-error missing type
+ super.vfunc_response(msg, conn)
+ }
+ }
+
+ start(
+ { requestHandler, css, ...cfg }: Omit<Config, "hold"> = {},
+ callback?: (args: string[]) => any,
+ ) {
+ Object.assign(this, cfg)
+
+ this.requestHandler = requestHandler
+ this.on("activate", () => {
+ callback?.(process.argv)
+ })
+
+ if (!this.acquireSocket()) {
+ console.error(`Astal instance "${this.instanceName}" already running`)
+ process.exit()
+ }
+
+ if (css)
+ this.applyCss(css, false)
+
+ // FIXME: promises never resolve
+ // https://github.com/romgrk/node-gtk/issues/121
+ // https://gitlab.gnome.org/GNOME/gjs/-/issues/468
+ App.run([])
+ }
+}
+
+export const App = new AstalJS
diff --git a/js/node/astal.ts b/js/node/astal.ts
new file mode 100644
index 0000000..9560a81
--- /dev/null
+++ b/js/node/astal.ts
@@ -0,0 +1,38 @@
+import gi from "node-gtk"
+import Time from "../src/time.js"
+import Process from "../src/process.js"
+import * as variable from "../src/variable.js"
+const Astal = gi.require("Astal", "0.1")
+
+const { interval, timeout, idle } = Time(Astal.Time)
+const { subprocess, exec, execAsync } = Process({
+ defaultOut: console.log,
+ defaultErr: console.error,
+ exec: Astal.Process.exec,
+ execv: Astal.Process.execv,
+ execAsync: Astal.Process.execAsync,
+ execAsyncv: Astal.Process.execAsyncv,
+ subprocess: Astal.Process.subprocess,
+ subprocessv: Astal.Process.subprocessv,
+})
+
+variable.config.defaultErrHandler = console.log
+variable.config.execAsync = execAsync
+variable.config.subprocess = subprocess
+variable.config.interval = interval
+variable.config.VariableBase = Astal.VariableBase
+Object.freeze(variable.config)
+
+export { subprocess, exec, execAsync }
+export { interval, timeout, idle }
+export { bind } from "../src/binding.js"
+export { Variable } from "../src/variable.js"
+export * as Widget from "./widgets.js"
+export { App } from "./application.js"
+
+// for convinience
+export const GLib = gi.require("GLib", "2.0")
+export const Gtk = gi.require("Gtk", "3.0")
+export const Gio = gi.require("Gio", "2.0")
+export const GObject = gi.require("GObject", "2.0")
+export { Astal, gi }
diff --git a/js/node/widgets.ts b/js/node/widgets.ts
new file mode 100644
index 0000000..914821d
--- /dev/null
+++ b/js/node/widgets.ts
@@ -0,0 +1,63 @@
+/* eslint-disable max-len */
+import gi from "node-gtk"
+import proxy, { type ConstructProps, type Widget } from "../src/astalify.js"
+import type GtkT from "@girs/node-gtk-3.0/node-gtk-3.0"
+import type AstalT from "@girs/node-astal-0.1/node-astal-0.1"
+
+const Astal = gi.require("Astal", "0.1")
+const Gtk = gi.require("Gtk", "3.0")
+
+const proxify = proxy(Gtk,
+ prop => `set${prop.charAt(0).toUpperCase() + prop.slice(1)}`,
+ {
+ cssGetter: Astal.widgetGetCss,
+ cssSetter: Astal.widgetSetCss,
+ classGetter: Astal.widgetGetClassNames,
+ classSetter: Astal.widgetSetClassNames,
+ cursorGetter: Astal.widgetGetCursor,
+ cursorSetter: Astal.widgetSetCursor,
+ })
+
+export function astalify<
+ C extends typeof Gtk.Widget,
+ P extends Record<string, any>,
+ N extends string = "Widget",
+>(klass: C) {
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ type Astal<N> = Omit<C, "new"> & {
+ new(props: P, ...children: GtkT.Widget[]): Widget<C>
+ (props: P, ...children: GtkT.Widget[]): Widget<C>
+ }
+
+ return proxify(klass) as unknown as Astal<N>
+}
+
+// Label
+export const Label = astalify<typeof Gtk.Label, LabelProps, "Label">(Gtk.Label)
+export type LabelProps = ConstructProps<typeof Gtk.Label, GtkT.Label.ConstructorProperties>
+
+// Icon
+export const Icon = astalify<typeof Astal.Icon, IconProps, "Icon">(Astal.Icon)
+export type IconProps = ConstructProps<typeof Astal.Icon, AstalT.Icon.ConstructorProperties>
+
+// Button
+export const Button = astalify<typeof Astal.Button, ButtonProps, "Button">(Astal.Button)
+export type ButtonProps = ConstructProps<typeof Astal.Button, AstalT.Button.ConstructorProperties, {
+ onClicked: (self: Widget<typeof Astal.Button>) => void
+}>
+
+// Window
+export const Window = astalify<typeof Astal.Window, WindowProps, "Window">(Astal.Window)
+export type WindowProps = ConstructProps<typeof Astal.Window, AstalT.Window.ConstructorProperties>
+
+// Box
+export const Box = astalify<typeof Astal.Box, BoxProps, "Box">(Astal.Box)
+export type BoxProps = ConstructProps<typeof Astal.Box, AstalT.Box.ConstructorProperties>
+
+// CenterBox
+export const CenterBox = astalify<typeof Astal.CenterBox, CenterBoxProps, "CenterBox">(Astal.CenterBox)
+export type CenterBoxProps = ConstructProps<typeof Astal.CenterBox, AstalT.CenterBox.ConstructorProperties>
+
+// EventBox
+export const EventBox = astalify<typeof Astal.EventBox, EventBoxProps, "EventBox">(Astal.EventBox)
+export type EventBoxProps = ConstructProps<typeof Astal.EventBox, AstalT.EventBox.ConstructorProperties>
diff --git a/js/package-lock.json b/js/package-lock.json
new file mode 100644
index 0000000..a902b72
--- /dev/null
+++ b/js/package-lock.json
@@ -0,0 +1,4038 @@
+{
+ "name": "js",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "dependencies": {
+ "node-gtk": "^0.14.0",
+ "typescript": "^5.1.0"
+ },
+ "devDependencies": {
+ "@ts-for-gir/cli": "^3.3.0",
+ "@types/node": "^20.12.12",
+ "@typescript-eslint/eslint-plugin": "^5.33.0",
+ "@typescript-eslint/parser": "^5.33.0",
+ "esbuild": "^0.20.2",
+ "eslint": "^8.42.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.24.2",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz",
+ "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/highlight": "^7.24.2",
+ "picocolors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz",
+ "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight": {
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.5.tgz",
+ "integrity": "sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.24.5",
+ "chalk": "^2.4.2",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true
+ },
+ "node_modules/@babel/highlight/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz",
+ "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz",
+ "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz",
+ "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz",
+ "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz",
+ "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz",
+ "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz",
+ "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz",
+ "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz",
+ "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz",
+ "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz",
+ "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz",
+ "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz",
+ "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz",
+ "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz",
+ "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz",
+ "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz",
+ "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz",
+ "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz",
+ "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz",
+ "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz",
+ "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz",
+ "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz",
+ "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
+ "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.10.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
+ "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
+ "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.6.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
+ "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@gar/promisify": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
+ "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw=="
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.11.14",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
+ "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
+ "dev": true,
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^2.0.2",
+ "debug": "^4.3.1",
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
+ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
+ "dev": true
+ },
+ "node_modules/@inquirer/figures": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.1.tgz",
+ "integrity": "sha512-mtup3wVKia3ZwULPHcbs4Mor8Voi+iIXEWD7wCNbIO6lYR62oPCTQyrddi5OMYVXHzeCSoneZwJuS8sBvlEwDw==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@ljharb/through": {
+ "version": "2.3.13",
+ "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.13.tgz",
+ "integrity": "sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/@mapbox/node-pre-gyp": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
+ "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==",
+ "dependencies": {
+ "detect-libc": "^2.0.0",
+ "https-proxy-agent": "^5.0.0",
+ "make-dir": "^3.1.0",
+ "node-fetch": "^2.6.7",
+ "nopt": "^5.0.0",
+ "npmlog": "^5.0.1",
+ "rimraf": "^3.0.2",
+ "semver": "^7.3.5",
+ "tar": "^6.1.11"
+ },
+ "bin": {
+ "node-pre-gyp": "bin/node-pre-gyp"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@npmcli/fs": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz",
+ "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==",
+ "dependencies": {
+ "@gar/promisify": "^1.1.3",
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@npmcli/move-file": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz",
+ "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==",
+ "deprecated": "This functionality has been moved to @npmcli/fs",
+ "dependencies": {
+ "mkdirp": "^1.0.4",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@tootallnate/once": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
+ "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@ts-for-gir/cli": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@ts-for-gir/cli/-/cli-3.3.0.tgz",
+ "integrity": "sha512-X8AhFhkEGzTakcXLbndiWxJuvdFceJrV71e+z/wy3xO5yKHL+fCqsq+Tw46RbZ8tquLqKPkh0TAUNZH6BLDR1A==",
+ "dev": true,
+ "dependencies": {
+ "@ts-for-gir/generator-base": "^3.3.0",
+ "@ts-for-gir/generator-html-doc": "^3.3.0",
+ "@ts-for-gir/generator-typescript": "^3.3.0",
+ "@ts-for-gir/lib": "^3.3.0",
+ "colorette": "^2.0.20",
+ "cosmiconfig": "^9.0.0",
+ "inquirer": "^9.2.16",
+ "tiny-glob": "^0.2.9",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "ts-for-gir": "lib/start.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@ts-for-gir/generator-base": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@ts-for-gir/generator-base/-/generator-base-3.3.0.tgz",
+ "integrity": "sha512-EACUJCUcly03SE8fYa/WqToTqGNxHBrqdOLpgIjmmlRaoHkYnwYFKKcI5O0+EsFOS5r4WbtisRVRj3uMnTK9pw==",
+ "dev": true,
+ "dependencies": {
+ "@ts-for-gir/lib": "^3.3.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@ts-for-gir/generator-html-doc": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@ts-for-gir/generator-html-doc/-/generator-html-doc-3.3.0.tgz",
+ "integrity": "sha512-DAOb3mu8xHlgBqkms9soMUy2HHFqYIrv55eU3xzTej/ZJRArDmd5f8ziXYLMva+TeYgQFhZnTr9ksIvsaAhvZA==",
+ "dev": true,
+ "dependencies": {
+ "@ts-for-gir/generator-base": "^3.3.0",
+ "@ts-for-gir/lib": "^3.3.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@ts-for-gir/generator-typescript": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@ts-for-gir/generator-typescript/-/generator-typescript-3.3.0.tgz",
+ "integrity": "sha512-kQl0eSarkb8/eWx9yA+G0ekQLXdUjBIvON1Gb6urCbGPz0EnvnqAu1CVh1nRie9E+lt2TO/YEThZj98KOzxXCg==",
+ "dev": true,
+ "dependencies": {
+ "@ts-for-gir/generator-base": "^3.3.0",
+ "@ts-for-gir/lib": "^3.3.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@ts-for-gir/lib": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@ts-for-gir/lib/-/lib-3.3.0.tgz",
+ "integrity": "sha512-GMJmNHka/qUJTTH6eLLGTPEd1cm68gq6PjW6Qan6ohz1WIu3tj0aP++hCBkUkmzYLHSj88/oLVPdHMuO5EQmew==",
+ "dev": true,
+ "dependencies": {
+ "colorette": "^2.0.20",
+ "ejs": "^3.1.9",
+ "fast-xml-parser": "^4.3.6",
+ "lodash": "^4.17.21"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true
+ },
+ "node_modules/@types/node": {
+ "version": "20.12.12",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz",
+ "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==",
+ "dev": true,
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
+ },
+ "node_modules/@types/semver": {
+ "version": "7.5.8",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz",
+ "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==",
+ "dev": true
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz",
+ "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.4.0",
+ "@typescript-eslint/scope-manager": "5.62.0",
+ "@typescript-eslint/type-utils": "5.62.0",
+ "@typescript-eslint/utils": "5.62.0",
+ "debug": "^4.3.4",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "natural-compare-lite": "^1.4.0",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^5.0.0",
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz",
+ "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "5.62.0",
+ "@typescript-eslint/types": "5.62.0",
+ "@typescript-eslint/typescript-estree": "5.62.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz",
+ "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.62.0",
+ "@typescript-eslint/visitor-keys": "5.62.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz",
+ "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "5.62.0",
+ "@typescript-eslint/utils": "5.62.0",
+ "debug": "^4.3.4",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "*"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz",
+ "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz",
+ "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.62.0",
+ "@typescript-eslint/visitor-keys": "5.62.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz",
+ "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@types/json-schema": "^7.0.9",
+ "@types/semver": "^7.3.12",
+ "@typescript-eslint/scope-manager": "5.62.0",
+ "@typescript-eslint/types": "5.62.0",
+ "@typescript-eslint/typescript-estree": "5.62.0",
+ "eslint-scope": "^5.1.1",
+ "semver": "^7.3.7"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz",
+ "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.62.0",
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
+ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
+ "dev": true
+ },
+ "node_modules/abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
+ },
+ "node_modules/acorn": {
+ "version": "8.11.3",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
+ "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/agentkeepalive": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz",
+ "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==",
+ "dependencies": {
+ "humanize-ms": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ }
+ },
+ "node_modules/aggregate-error": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+ "dependencies": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-escapes/node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/aproba": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
+ "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ=="
+ },
+ "node_modules/are-we-there-yet": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
+ "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
+ "dependencies": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^3.6.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/async": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz",
+ "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==",
+ "dev": true
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "dev": true,
+ "dependencies": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
+ "node_modules/cacache": {
+ "version": "16.1.3",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz",
+ "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==",
+ "dependencies": {
+ "@npmcli/fs": "^2.1.0",
+ "@npmcli/move-file": "^2.0.0",
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.1.0",
+ "glob": "^8.0.1",
+ "infer-owner": "^1.0.4",
+ "lru-cache": "^7.7.1",
+ "minipass": "^3.1.6",
+ "minipass-collect": "^1.0.2",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "mkdirp": "^1.0.4",
+ "p-map": "^4.0.0",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^3.0.2",
+ "ssri": "^9.0.0",
+ "tar": "^6.1.11",
+ "unique-filename": "^2.0.0"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/cacache/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/cacache/node_modules/glob": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
+ "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/cacache/node_modules/minimatch": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
+ "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
+ "dev": true,
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chardet": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
+ "dev": true
+ },
+ "node_modules/chownr": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/clean-stack": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "dev": true,
+ "dependencies": {
+ "restore-cursor": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cli-spinners": {
+ "version": "2.9.2",
+ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
+ "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-width": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz",
+ "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/cliui/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/clone": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+ "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/color-support": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
+ "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
+ "bin": {
+ "color-support": "bin.js"
+ }
+ },
+ "node_modules/colorette": {
+ "version": "2.0.20",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
+ "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
+ "dev": true
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
+ },
+ "node_modules/console-control-strings": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+ "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="
+ },
+ "node_modules/cosmiconfig": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz",
+ "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==",
+ "dev": true,
+ "dependencies": {
+ "env-paths": "^2.2.1",
+ "import-fresh": "^3.3.0",
+ "js-yaml": "^4.1.0",
+ "parse-json": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/d-fischer"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.9.5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "node_modules/defaults": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
+ "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
+ "dev": true,
+ "dependencies": {
+ "clone": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "dev": true,
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/delegates": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="
+ },
+ "node_modules/detect-libc": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
+ "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/ejs": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
+ "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==",
+ "dev": true,
+ "dependencies": {
+ "jake": "^10.8.5"
+ },
+ "bin": {
+ "ejs": "bin/cli.js"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ },
+ "node_modules/encoding": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
+ "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
+ "optional": true,
+ "dependencies": {
+ "iconv-lite": "^0.6.2"
+ }
+ },
+ "node_modules/encoding/node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "optional": true,
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/env-paths": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
+ "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/err-code": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
+ "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA=="
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
+ "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.2.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
+ "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.20.2",
+ "@esbuild/android-arm": "0.20.2",
+ "@esbuild/android-arm64": "0.20.2",
+ "@esbuild/android-x64": "0.20.2",
+ "@esbuild/darwin-arm64": "0.20.2",
+ "@esbuild/darwin-x64": "0.20.2",
+ "@esbuild/freebsd-arm64": "0.20.2",
+ "@esbuild/freebsd-x64": "0.20.2",
+ "@esbuild/linux-arm": "0.20.2",
+ "@esbuild/linux-arm64": "0.20.2",
+ "@esbuild/linux-ia32": "0.20.2",
+ "@esbuild/linux-loong64": "0.20.2",
+ "@esbuild/linux-mips64el": "0.20.2",
+ "@esbuild/linux-ppc64": "0.20.2",
+ "@esbuild/linux-riscv64": "0.20.2",
+ "@esbuild/linux-s390x": "0.20.2",
+ "@esbuild/linux-x64": "0.20.2",
+ "@esbuild/netbsd-x64": "0.20.2",
+ "@esbuild/openbsd-x64": "0.20.2",
+ "@esbuild/sunos-x64": "0.20.2",
+ "@esbuild/win32-arm64": "0.20.2",
+ "@esbuild/win32-ia32": "0.20.2",
+ "@esbuild/win32-x64": "0.20.2"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
+ "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
+ "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.4",
+ "@eslint/js": "8.57.0",
+ "@humanwhocodes/config-array": "^0.11.14",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "@ungap/structured-clone": "^1.2.0",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/eslint-scope": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/espree": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+ "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esquery/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/exponential-backoff": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz",
+ "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw=="
+ },
+ "node_modules/external-editor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
+ "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
+ "dev": true,
+ "dependencies": {
+ "chardet": "^0.7.0",
+ "iconv-lite": "^0.4.24",
+ "tmp": "^0.0.33"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
+ "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "node_modules/fast-xml-parser": {
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.6.tgz",
+ "integrity": "sha512-M2SovcRxD4+vC493Uc2GZVcZaj66CCJhWurC4viynVSTvrpErCShNcDz1lAho6n9REQKvL/ll4A4/fw6Y9z8nw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ },
+ {
+ "type": "paypal",
+ "url": "https://paypal.me/naturalintelligence"
+ }
+ ],
+ "dependencies": {
+ "strnum": "^1.0.5"
+ },
+ "bin": {
+ "fxparser": "src/cli/cli.js"
+ }
+ },
+ "node_modules/fastq": {
+ "version": "1.17.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
+ "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/filelist": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
+ "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
+ "dev": true,
+ "dependencies": {
+ "minimatch": "^5.0.1"
+ }
+ },
+ "node_modules/filelist/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/filelist/node_modules/minimatch": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
+ "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
+ "dev": true,
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.3",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
+ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
+ "dev": true
+ },
+ "node_modules/fs-minipass": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+ "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gauge": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz",
+ "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
+ "dependencies": {
+ "aproba": "^1.0.3 || ^2.0.0",
+ "color-support": "^1.1.2",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.1",
+ "object-assign": "^4.1.1",
+ "signal-exit": "^3.0.0",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1",
+ "wide-align": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true,
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
+ "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
+ "dev": true,
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "hasown": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globalyzer": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz",
+ "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==",
+ "dev": true
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globrex": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz",
+ "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==",
+ "dev": true
+ },
+ "node_modules/gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+ "dev": true,
+ "dependencies": {
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
+ "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-unicode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+ "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ=="
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/http-cache-semantics": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
+ "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ=="
+ },
+ "node_modules/http-proxy-agent": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
+ "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==",
+ "dependencies": {
+ "@tootallnate/once": "2",
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/humanize-ms": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
+ "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
+ "dependencies": {
+ "ms": "^2.0.0"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/ignore": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
+ "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/infer-owner": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
+ "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A=="
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "node_modules/inquirer": {
+ "version": "9.2.21",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.21.tgz",
+ "integrity": "sha512-c/dwDruM1FtzeISV+xMHm+JZTmhpmgWPEZI2bU3+Fwu5MhbAX0zMHHxj5warNfttE5NUID3aijrFUpDc2yBvcA==",
+ "dev": true,
+ "dependencies": {
+ "@inquirer/figures": "^1.0.1",
+ "@ljharb/through": "^2.3.13",
+ "ansi-escapes": "^4.3.2",
+ "chalk": "^5.3.0",
+ "cli-cursor": "^3.1.0",
+ "cli-width": "^4.1.0",
+ "external-editor": "^3.1.0",
+ "lodash": "^4.17.21",
+ "mute-stream": "1.0.0",
+ "ora": "^5.4.1",
+ "run-async": "^3.0.0",
+ "rxjs": "^7.8.1",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^6.2.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/inquirer/node_modules/chalk": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
+ "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
+ "dev": true,
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/ip-address": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
+ "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
+ "dependencies": {
+ "jsbn": "1.1.0",
+ "sprintf-js": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "dev": true
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-interactive": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
+ "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-lambda": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
+ "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ=="
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+ },
+ "node_modules/jake": {
+ "version": "10.9.1",
+ "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.1.tgz",
+ "integrity": "sha512-61btcOHNnLnsOdtLgA5efqQWjnSi/vow5HbI7HMdKKWqvrKR1bLK3BPlJn9gcSaP2ewuamUSMB5XEy76KUIS2w==",
+ "dev": true,
+ "dependencies": {
+ "async": "^3.2.3",
+ "chalk": "^4.0.2",
+ "filelist": "^1.0.4",
+ "minimatch": "^3.1.2"
+ },
+ "bin": {
+ "jake": "bin/cli.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsbn": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
+ "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "dev": true
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "dev": true
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
+ },
+ "node_modules/lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="
+ },
+ "node_modules/lodash.isequal": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+ "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "node_modules/lodash.snakecase": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz",
+ "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw=="
+ },
+ "node_modules/log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/make-dir": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "dependencies": {
+ "semver": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/make-dir/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/make-fetch-happen": {
+ "version": "10.2.1",
+ "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz",
+ "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==",
+ "dependencies": {
+ "agentkeepalive": "^4.2.1",
+ "cacache": "^16.1.0",
+ "http-cache-semantics": "^4.1.0",
+ "http-proxy-agent": "^5.0.0",
+ "https-proxy-agent": "^5.0.0",
+ "is-lambda": "^1.0.1",
+ "lru-cache": "^7.7.1",
+ "minipass": "^3.1.6",
+ "minipass-collect": "^1.0.2",
+ "minipass-fetch": "^2.0.3",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "negotiator": "^0.6.3",
+ "promise-retry": "^2.0.1",
+ "socks-proxy-agent": "^7.0.0",
+ "ssri": "^9.0.0"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-collect": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
+ "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minipass-fetch": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz",
+ "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==",
+ "dependencies": {
+ "minipass": "^3.1.6",
+ "minipass-sized": "^1.0.3",
+ "minizlib": "^2.1.2"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ },
+ "optionalDependencies": {
+ "encoding": "^0.1.13"
+ }
+ },
+ "node_modules/minipass-flush": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
+ "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minipass-pipeline": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
+ "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-sized": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz",
+ "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minizlib": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+ "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+ "dependencies": {
+ "minipass": "^3.0.0",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "node_modules/mute-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz",
+ "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==",
+ "dev": true,
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/nan": {
+ "version": "2.19.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.19.0.tgz",
+ "integrity": "sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw=="
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "node_modules/natural-compare-lite": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
+ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
+ "dev": true
+ },
+ "node_modules/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/node-gtk": {
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/node-gtk/-/node-gtk-0.14.0.tgz",
+ "integrity": "sha512-QSdmdPE+mVwiEPyelbY9Kzo8ZxWCQl0SER8DFysyuIBoYVNXzKpuxfRIVYuVi/SDmsoAXLddyGZ4bJq9VhvD2A==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@mapbox/node-pre-gyp": "^1.0.10",
+ "lodash.camelcase": "4.3.0",
+ "lodash.isequal": "4.5.0",
+ "lodash.snakecase": "^4.1.1",
+ "nan": "^2.17.0",
+ "node-gyp": "^9.3.1",
+ "remove-trailing-spaces": "^1.0.7",
+ "unindent": "^2.0.0"
+ }
+ },
+ "node_modules/node-gyp": {
+ "version": "9.4.1",
+ "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz",
+ "integrity": "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==",
+ "dependencies": {
+ "env-paths": "^2.2.0",
+ "exponential-backoff": "^3.1.1",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.2.6",
+ "make-fetch-happen": "^10.0.3",
+ "nopt": "^6.0.0",
+ "npmlog": "^6.0.0",
+ "rimraf": "^3.0.2",
+ "semver": "^7.3.5",
+ "tar": "^6.1.2",
+ "which": "^2.0.2"
+ },
+ "bin": {
+ "node-gyp": "bin/node-gyp.js"
+ },
+ "engines": {
+ "node": "^12.13 || ^14.13 || >=16"
+ }
+ },
+ "node_modules/node-gyp/node_modules/are-we-there-yet": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz",
+ "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==",
+ "dependencies": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^3.6.0"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/node-gyp/node_modules/gauge": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz",
+ "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==",
+ "dependencies": {
+ "aproba": "^1.0.3 || ^2.0.0",
+ "color-support": "^1.1.3",
+ "console-control-strings": "^1.1.0",
+ "has-unicode": "^2.0.1",
+ "signal-exit": "^3.0.7",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1",
+ "wide-align": "^1.1.5"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/node-gyp/node_modules/nopt": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz",
+ "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==",
+ "dependencies": {
+ "abbrev": "^1.0.0"
+ },
+ "bin": {
+ "nopt": "bin/nopt.js"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/node-gyp/node_modules/npmlog": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz",
+ "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==",
+ "dependencies": {
+ "are-we-there-yet": "^3.0.0",
+ "console-control-strings": "^1.1.0",
+ "gauge": "^4.0.3",
+ "set-blocking": "^2.0.0"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/nopt": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
+ "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
+ "dependencies": {
+ "abbrev": "1"
+ },
+ "bin": {
+ "nopt": "bin/nopt.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/npmlog": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
+ "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
+ "dependencies": {
+ "are-we-there-yet": "^2.0.0",
+ "console-control-strings": "^1.1.0",
+ "gauge": "^3.0.0",
+ "set-blocking": "^2.0.0"
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/ora": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
+ "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
+ "dev": true,
+ "dependencies": {
+ "bl": "^4.1.0",
+ "chalk": "^4.1.0",
+ "cli-cursor": "^3.1.0",
+ "cli-spinners": "^2.5.0",
+ "is-interactive": "^1.0.0",
+ "is-unicode-supported": "^0.1.0",
+ "log-symbols": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "wcwidth": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-map": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+ "dependencies": {
+ "aggregate-error": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
+ "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==",
+ "dev": true
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/promise-inflight": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+ "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g=="
+ },
+ "node_modules/promise-retry": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
+ "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
+ "dependencies": {
+ "err-code": "^2.0.2",
+ "retry": "^0.12.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/remove-trailing-spaces": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/remove-trailing-spaces/-/remove-trailing-spaces-1.0.8.tgz",
+ "integrity": "sha512-O3vsMYfWighyFbTd8hk8VaSj9UAGENxAtX+//ugIst2RMk5e03h6RoIS+0ylsFxY1gvmPuAY/PO4It+gPEeySA=="
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "dev": true,
+ "dependencies": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/run-async": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz",
+ "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/rxjs": {
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
+ "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "devOptional": true
+ },
+ "node_modules/semver": {
+ "version": "7.6.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
+ "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="
+ },
+ "node_modules/set-function-length": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+ "dev": true,
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/smart-buffer": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
+ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
+ "engines": {
+ "node": ">= 6.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks": {
+ "version": "2.8.3",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
+ "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==",
+ "dependencies": {
+ "ip-address": "^9.0.5",
+ "smart-buffer": "^4.2.0"
+ },
+ "engines": {
+ "node": ">= 10.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks-proxy-agent": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz",
+ "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==",
+ "dependencies": {
+ "agent-base": "^6.0.2",
+ "debug": "^4.3.3",
+ "socks": "^2.6.2"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
+ "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="
+ },
+ "node_modules/ssri": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz",
+ "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==",
+ "dependencies": {
+ "minipass": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/strnum": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
+ "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==",
+ "dev": true
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tar": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
+ "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
+ "dependencies": {
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.0.0",
+ "minipass": "^5.0.0",
+ "minizlib": "^2.1.1",
+ "mkdirp": "^1.0.3",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/tar/node_modules/minipass": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
+ "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "node_modules/tiny-glob": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz",
+ "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==",
+ "dev": true,
+ "dependencies": {
+ "globalyzer": "0.1.0",
+ "globrex": "^0.1.2"
+ }
+ },
+ "node_modules/tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "dev": true,
+ "dependencies": {
+ "os-tmpdir": "~1.0.2"
+ },
+ "engines": {
+ "node": ">=0.6.0"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
+ },
+ "node_modules/tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
+ "dev": true
+ },
+ "node_modules/tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^1.8.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ },
+ "peerDependencies": {
+ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
+ }
+ },
+ "node_modules/tsutils/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.4.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
+ "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "5.26.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
+ "dev": true
+ },
+ "node_modules/unindent": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unindent/-/unindent-2.0.0.tgz",
+ "integrity": "sha512-Mo5gKmshwTR3b2BwCSMish/UuwTqP5W7TIRa88HQTydH+07HhkOCE1P6HZ4lSxJS5klEqXFnhlZSxkxbBOMk4Q=="
+ },
+ "node_modules/unique-filename": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz",
+ "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==",
+ "dependencies": {
+ "unique-slug": "^3.0.0"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/unique-slug": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz",
+ "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==",
+ "dependencies": {
+ "imurmurhash": "^0.1.4"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+ },
+ "node_modules/wcwidth": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
+ "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
+ "dev": true,
+ "dependencies": {
+ "defaults": "^1.0.3"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/wide-align": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
+ "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
+ "dependencies": {
+ "string-width": "^1.0.2 || 2 || 3 || 4"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ },
+ "node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dev": true,
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ }
+}
diff --git a/js/package.json b/js/package.json
new file mode 100644
index 0000000..b8d0a65
--- /dev/null
+++ b/js/package.json
@@ -0,0 +1,20 @@
+{
+ "type": "module",
+ "dependencies": {
+ "node-gtk": "^0.14.0",
+ "typescript": "^5.1.0"
+ },
+ "devDependencies": {
+ "@ts-for-gir/cli": "^3.3.0",
+ "@types/node": "^20.12.12",
+ "@typescript-eslint/eslint-plugin": "^5.33.0",
+ "@typescript-eslint/parser": "^5.33.0",
+ "esbuild": "^0.20.2",
+ "eslint": "^8.42.0"
+ },
+ "scripts": {
+ "lint": "eslint .",
+ "build": "tsc",
+ "types": "ts-for-gir generate"
+ }
+}
diff --git a/js/sample.gjs.js b/js/sample.gjs.js
new file mode 100755
index 0000000..c435c14
--- /dev/null
+++ b/js/sample.gjs.js
@@ -0,0 +1,43 @@
+#!/usr/bin/env -S gjs -m
+import { Variable, App, Widget, Astal, bind } from "../js/dist/gjs/astal.js"
+import Playerctl from "gi://Playerctl"
+
+// state
+const player = Playerctl.Player.new("spotify")
+const date = Variable("").poll(1000, "date")
+const title = Variable(player.get_title()).observe(player, "metadata", () => player.get_title())
+
+// ui
+function Bar(monitor) {
+ return Widget.Window(
+ {
+ monitor,
+ application: App,
+ exclusivity: Astal.Exclusivity.EXCLUSIVE,
+ anchor: Astal.WindowAnchor.BOTTOM |
+ Astal.WindowAnchor.LEFT |
+ Astal.WindowAnchor.RIGHT
+ },
+ Widget.CenterBox({
+ startWidget: Widget.Label({
+ label: date(l => `Current date: ${l}`),
+ }),
+ endWidget: Widget.Label({
+ label: bind(title).as(t => `Title: ${t}`)
+ }),
+ })
+ )
+}
+
+// main
+App.start({
+ requestHandler(msg, res) {
+ switch (msg) {
+ case "inspector": return res(App.inspector())
+ case "quit": return res(App.quit())
+ default: return App.eval(msg).then(res).catch(console.error)
+ }
+ }
+}, () => {
+ Bar(0)
+})
diff --git a/js/sample.node.js b/js/sample.node.js
new file mode 100755
index 0000000..f7ee70d
--- /dev/null
+++ b/js/sample.node.js
@@ -0,0 +1,49 @@
+#!/usr/bin/env node
+import { Variable, App, Widget, Astal, bind, gi } from "../js/dist/node/astal.js"
+const Playerctl = gi.require("Playerctl", "2.0")
+
+// state
+const player = Playerctl.Player.new("spotify")
+const title = Variable(player.getTitle()).observe(player, "metadata", () => player.getTitle())
+const date = Variable("")
+ // FIXME: doesn't work because promises don't resolve
+ // .poll(1000, "date")
+ // FIXME: don't know why but this doesn't work either
+ // .watch("bash -c 'while true; do date; sleep 1; done'")
+ // this does
+ .poll(1000, Date)
+
+// ui
+function Bar(monitor) {
+ return Widget.Window(
+ {
+ monitor,
+ application: App,
+ exclusivity: Astal.Exclusivity.EXCLUSIVE,
+ anchor: Astal.WindowAnchor.BOTTOM |
+ Astal.WindowAnchor.LEFT |
+ Astal.WindowAnchor.RIGHT
+ },
+ Widget.CenterBox({
+ startWidget: Widget.Label({
+ label: date(l => `Current date: ${l}`),
+ }),
+ endWidget: Widget.Label({
+ label: bind(title).as(t => `Title: ${t}`)
+ }),
+ })
+ )
+}
+
+// main
+App.start({
+ requestHandler(msg, res) {
+ switch (msg) {
+ case "inspector": return res(App.inspector())
+ case "quit": return res(App.quit())
+ default: return App.eval(msg).then(res).catch(console.error)
+ }
+ }
+}, () => {
+ Bar(0)
+})
diff --git a/js/src/application.ts b/js/src/application.ts
new file mode 100644
index 0000000..10f840e
--- /dev/null
+++ b/js/src/application.ts
@@ -0,0 +1,28 @@
+export type RequestHandler = {
+ (request: string, res: (response: string) => void): void
+}
+
+export type Config = Partial<{
+ instanceName: string
+ gtkTheme: string
+ iconTheme: string
+ cursorTheme: string
+ css: string
+ requestHandler: RequestHandler
+ hold: boolean
+}>
+
+export function runJS(body: string): Promise<any> {
+ return new Promise((res, rej) => {
+ try {
+ const fn = Function(`return (async function() {
+ ${body.includes(";") ? body : `return ${body};`}
+ })`)
+ fn()()
+ .then(res)
+ .catch(rej)
+ } catch (error) {
+ rej(error)
+ }
+ })
+}
diff --git a/js/src/astalify.ts b/js/src/astalify.ts
new file mode 100644
index 0000000..bc24db6
--- /dev/null
+++ b/js/src/astalify.ts
@@ -0,0 +1,213 @@
+import Binding, { kebabify, type Connectable, type Subscribable } from "./binding.js"
+
+export type Widget<C extends { new(...args: any): any }> = InstanceType<C> & {
+ className: string
+ css: string
+ cursor: Cursor
+ hook(
+ object: Connectable,
+ signal: string,
+ callback: (self: Widget<C>, ...args: any[]) => void,
+ ): Widget<C>
+ hook(
+ object: Subscribable,
+ callback: (self: Widget<C>, ...args: any[]) => void,
+ ): Widget<C>
+}
+
+export default function <G extends { Bin: any, Container: any, Widget: any }>(
+ Gtk: G,
+ setter: (prop: string) => `set${string}`,
+ Astal: {
+ cssSetter: (w: any, css: string) => void,
+ cssGetter: (w: any) => string | null,
+ classSetter: (w: any, name: string[]) => void,
+ classGetter: (w: any) => string[],
+ cursorSetter: (w: any, cursor: string) => void,
+ cursorGetter: (w: any) => string | null,
+ },
+) {
+ function hook(
+ self: any,
+ object: Connectable | Subscribable,
+ signalOrCallback: string | ((self: any, ...args: any[]) => void),
+ callback?: (self: any, ...args: any[]) => void,
+ ) {
+ if (typeof object.connect === "function" && callback) {
+ const id = object.connect(signalOrCallback, (_: any, ...args: unknown[]) => {
+ callback(self, ...args)
+ })
+ self.connect("destroy", () => {
+ (object.disconnect as Connectable["disconnect"])(id)
+ })
+ }
+
+ else if (typeof object.subscribe === "function" && typeof signalOrCallback === "function") {
+ const unsub = object.subscribe((...args: unknown[]) => {
+ signalOrCallback(self, ...args)
+ })
+ self.connect("destroy", unsub)
+ }
+
+ return self
+ }
+
+ function setChild(parent: any, child: any) {
+ if (parent instanceof Gtk.Bin) {
+ if (parent.get_child())
+ parent.remove(parent.get_child()!)
+ }
+ if (parent instanceof Gtk.Container)
+ parent.add(child)
+ }
+
+ function ctor(self: any, config: any, ...children: any[]) {
+ const { setup, child, ...props } = config
+ props.visible ??= true
+
+ const bindings = Object.keys(props).reduce((acc: any, prop) => {
+ if (props[prop] instanceof Binding) {
+ const bind = [prop, props[prop]]
+ prop === "child"
+ ? setChild(self, props[prop].get())
+ : self[setter(prop)](props[prop].get())
+
+ delete props[prop]
+ return [...acc, bind]
+ }
+ return acc
+ }, [])
+
+ const onHandlers = Object.keys(props).reduce((acc: any, key) => {
+ if (key.startsWith("on")) {
+ const sig = kebabify(key).split("-").slice(1).join("-")
+ const handler = [sig, props[key]]
+ delete props[key]
+ return [...acc, handler]
+ }
+ return acc
+ }, [])
+
+ Object.assign(self, props)
+ Object.assign(self, {
+ hook(obj: any, sig: any, callback: any) {
+ return hook(self, obj, sig, callback)
+ },
+ })
+
+ if (child instanceof Binding) {
+ setChild(self, child.get())
+ self.connect("destroy", child.subscribe(v => {
+ setChild(self, v)
+ }))
+ } else if (self instanceof Gtk.Container && child instanceof Gtk.Widget) {
+ self.add(child)
+ }
+
+ for (const [signal, callback] of onHandlers)
+ self.connect(signal, callback)
+
+ if (self instanceof Gtk.Container && children) {
+ for (const child of children)
+ self.add(child)
+ }
+
+ for (const [prop, bind] of bindings) {
+ self.connect("destroy", bind.subscribe((v: any) => {
+ self[`${setter(prop)}`](v)
+ }))
+ }
+
+ setup?.(self)
+ return self
+ }
+
+ return function proxify<
+ C extends { new(...args: any[]): any },
+ >(klass: C) {
+ Object.defineProperty(klass.prototype, "className", {
+ get() { return Astal.classGetter(this).join(" ") },
+ set(v) { Astal.classSetter(this, v.split(/\s+/)) },
+ })
+
+ Object.defineProperty(klass.prototype, "css", {
+ get() { return Astal.cssGetter(this) },
+ set(v) { Astal.cssSetter(this, v) },
+ })
+
+ Object.defineProperty(klass.prototype, "cursor", {
+ get() { return Astal.cursorGetter(this) },
+ set(v) { Astal.cursorSetter(this, v) },
+ })
+
+ const proxy = new Proxy(klass, {
+ construct(_, [conf, ...children]) {
+ const self = new klass
+ return ctor(self, conf, ...children)
+ },
+ apply(_t, _a, [conf, ...children]) {
+ const self = new klass
+ return ctor(self, conf, ...children)
+ },
+ })
+
+ return proxy
+ }
+}
+
+
+type BindableProps<T> = {
+ [K in keyof T]: Binding<NonNullable<T[K]>> | T[K];
+}
+
+export type ConstructProps<
+ Self extends { new(...args: any[]): any },
+ Props = unknown,
+ Signals = unknown
+> = {
+ [Key in `on${string}`]: (self: Widget<Self>) => unknown
+} & Partial<Signals> & BindableProps<Props & {
+ className?: string
+ css?: string
+ cursor?: string
+}> & {
+ onDestroy?: (self: Widget<Self>) => unknown
+ onDraw?: (self: Widget<Self>) => unknown
+ setup?: (self: Widget<Self>) => void
+}
+
+type Cursor =
+ | "default"
+ | "help"
+ | "pointer"
+ | "context-menu"
+ | "progress"
+ | "wait"
+ | "cell"
+ | "crosshair"
+ | "text"
+ | "vertical-text"
+ | "alias"
+ | "copy"
+ | "no-drop"
+ | "move"
+ | "not-allowed"
+ | "grab"
+ | "grabbing"
+ | "all-scroll"
+ | "col-resize"
+ | "row-resize"
+ | "n-resize"
+ | "e-resize"
+ | "s-resize"
+ | "w-resize"
+ | "ne-resize"
+ | "nw-resize"
+ | "sw-resize"
+ | "se-resize"
+ | "ew-resize"
+ | "ns-resize"
+ | "nesw-resize"
+ | "nwse-resize"
+ | "zoom-in"
+ | "zoom-out"
diff --git a/js/src/binding.ts b/js/src/binding.ts
new file mode 100644
index 0000000..a8b6d55
--- /dev/null
+++ b/js/src/binding.ts
@@ -0,0 +1,78 @@
+export const kebabify = (str: string) => str
+ .replace(/([a-z])([A-Z])/g, "$1-$2")
+ .replaceAll("_", "-")
+ .toLowerCase()
+
+export interface Subscribable<T = unknown> {
+ subscribe(callback: () => void): () => void
+ get(): T
+ [key: string]: any
+}
+
+export interface Connectable {
+ connect(signal: string, callback: (...args: any[]) => unknown): number
+ disconnect(id: number): void
+ [key: string]: any
+}
+
+export default class Binding<Value> {
+ private emitter: Subscribable<Value> | Connectable
+ private prop?: string
+ private transformFn = (v: any) => v
+
+ static bind<
+ T extends Connectable,
+ P extends keyof T,
+ >(object: T, property: P): Binding<T[P]>
+
+ static bind<T>(object: Subscribable<T>): Binding<T>
+
+ static bind(emitter: Connectable | Subscribable, prop?: string) {
+ return new Binding(emitter, prop)
+ }
+
+ private constructor(emitter: Connectable | Subscribable<Value>, prop?: string) {
+ this.emitter = emitter
+ this.prop = prop && kebabify(prop)
+ }
+
+ toString() {
+ return `Binding<${this.emitter}${this.prop ? `, "${this.prop}"` : ""}>`
+ }
+
+ as<T>(fn: (v: Value) => T): Binding<T> {
+ const bind = new Binding(this.emitter, this.prop)
+ bind.transformFn = (v: Value) => fn(this.transformFn(v))
+ return bind as unknown as Binding<T>
+ }
+
+ get(): Value {
+ if (typeof this.emitter.get === "function")
+ return this.transformFn(this.emitter.get())
+
+ if (typeof this.prop === "string")
+ return this.transformFn(this.emitter[this.prop])
+
+ throw Error("can not get value of binding")
+ }
+
+ subscribe(callback: (value: Value) => void): () => void {
+ if (typeof this.emitter.subscribe === "function") {
+ return this.emitter.subscribe(() => {
+ callback(this.get())
+ })
+ }
+ else if (typeof this.emitter.connect === "function") {
+ const signal = `notify::${this.prop}`
+ const id = this.emitter.connect(signal, () => {
+ callback(this.get())
+ })
+ return () => {
+ (this.emitter.disconnect as Connectable["disconnect"])(id)
+ }
+ }
+ throw Error(`${this.emitter} is not bindable`)
+ }
+}
+
+export const { bind } = Binding
diff --git a/js/src/process.ts b/js/src/process.ts
new file mode 100644
index 0000000..537aba8
--- /dev/null
+++ b/js/src/process.ts
@@ -0,0 +1,83 @@
+type Proc = {
+ connect(sig: "stdout" | "stderr", fn: (_: any, out: string) => void): number
+}
+
+type Config<P extends Proc> = {
+ defaultOut(stdout: string): void
+ defaultErr(stdout: string): void
+ subprocess(cmd: string): P
+ subprocessv(cmd: string[]): P
+ exec(cmd: string): string | null
+ execv(cmd: string[]): string | null
+ execAsync(cmd: string): P
+ execAsyncv(cmd: string[]): P
+}
+
+type Args<Out = void, Err = void> = {
+ cmd: string | string[],
+ out?: (stdout: string) => Out,
+ err?: (stderr: string) => Err,
+}
+
+export default function <P extends Proc>(config: Config<P>) {
+ function args<O, E>(argsOrCmd: Args | string | string[], onOut: O, onErr: E) {
+ const params = Array.isArray(argsOrCmd) || typeof argsOrCmd === "string"
+ return {
+ cmd: params ? argsOrCmd : argsOrCmd.cmd,
+ err: params ? onErr : argsOrCmd.err || onErr,
+ out: params ? onOut : argsOrCmd.out || onOut,
+ }
+ }
+
+ function subprocess(args: Args): P
+ function subprocess(
+ cmd: string | string[],
+ onOut?: (stdout: string) => void,
+ onErr?: (stderr: string) => void,
+ ): P
+ function subprocess(
+ argsOrCmd: Args | string | string[],
+ onOut: (stdout: string) => void = config.defaultOut,
+ onErr: (stderr: string) => void = config.defaultErr,
+ ) {
+ const { cmd, err, out } = args(argsOrCmd, onOut, onErr)
+ const proc = Array.isArray(cmd)
+ ? config.subprocessv(cmd)
+ : config.subprocess(cmd)
+
+ proc.connect("stdout", (_, stdout: string) => out(stdout))
+ proc.connect("stderr", (_, stderr: string) => err(stderr))
+ return proc
+ }
+
+ function exec<Out = string, Err = string>(
+ args: Args<Out, Err>
+ ): Out | Err
+ function exec<Out = string, Err = string>(
+ cmd: string | string[],
+ onOut?: (stdout: string) => Out,
+ onErr?: (stderr: string) => Err,
+ ): Out | Err
+ function exec<Out = string, Err = string>(
+ argsOrCmd: Args<Out, Err> | string | string[],
+ onOut: (stdout: string) => Out = out => out as Out,
+ onErr: (stderr: string) => Err = out => out as Err,
+ ): Out | Err {
+ const { cmd, err, out } = args(argsOrCmd, onOut, onErr)
+ return Array.isArray(cmd)
+ ? out(config.execv(cmd)!) as Out
+ : err(config.exec(cmd)!) as Err
+ }
+
+ function execAsync(cmd: string | string[]): Promise<string> {
+ const proc = Array.isArray(cmd)
+ ? config.execAsyncv(cmd)
+ : config.execAsync(cmd)
+ return new Promise((resolve, reject) => {
+ proc.connect("stdout", (_, out: string) => resolve(out))
+ proc.connect("stderr", (_, err: string) => reject(err))
+ })
+ }
+
+ return { subprocess, exec, execAsync }
+}
diff --git a/js/src/time.ts b/js/src/time.ts
new file mode 100644
index 0000000..ce98c9a
--- /dev/null
+++ b/js/src/time.ts
@@ -0,0 +1,27 @@
+interface Time {
+ connect(sig: "now", fn: () => void): number
+ cancel(): void
+}
+
+export default function Time<T extends Time>(Time: {
+ interval(interval: number, closure: any): T
+ timeout(timeout: number, closure: any): T
+ idle(closure: any): T
+}) {
+ function interval(interval: number, callback: () => void) {
+ const t = Time.interval(interval, null)
+ t.connect("now", callback)
+ return t
+ }
+ function timeout(timeout: number, callback: () => void) {
+ const t = Time.timeout(timeout, null)
+ t.connect("now", callback)
+ return t
+ }
+ function idle(callback: () => void) {
+ const t = Time.idle(null)
+ t.connect("now", callback)
+ return t
+ }
+ return { interval, timeout, idle }
+}
diff --git a/js/src/variable.ts b/js/src/variable.ts
new file mode 100644
index 0000000..1d4e07f
--- /dev/null
+++ b/js/src/variable.ts
@@ -0,0 +1,250 @@
+import Binding, { type Connectable } from "./binding.js"
+
+type VariableBase = {
+ emit(sig: "error" | "changed" | "dropped", ...args: any[]): void
+ connect(sig: "error" | "changed" | "dropped", fn: (...args: any[]) => void): number
+ disconnect(id: number): void
+ runDispose?(): void // node, deno
+ run_dispose?(): void // gjs
+}
+
+type VariableBaseCtor = {
+ new(): VariableBase
+}
+
+type Time = any
+type Process = any
+
+type Config = {
+ defaultErrHandler(err: any): void
+ VariableBase: VariableBaseCtor
+ interval(n: number, fn: () => void): Time
+ execAsync(cmd: string | string[]): Promise<string>
+ subprocess(args: {
+ cmd: string | string[],
+ out: (s: string) => void,
+ err: (s: string) => void
+ }): Process
+}
+
+// @ts-expect-error missing values
+export const config: Config = {}
+
+class VariableWrapper<T> extends Function {
+ private variable!: VariableBase
+ private errHandler? = config.defaultErrHandler
+
+ private _value: T
+ private _poll?: Time
+ private _watch?: Process
+
+ private pollInterval = 1000
+ private pollExec?: string[] | string
+ private pollTransform?: (stdout: string, prev: T) => T
+ private pollFn?: (prev: T) => T | Promise<T>
+
+ private watchTransform?: (stdout: string, prev: T) => T
+ private watchExec?: string[] | string
+
+ constructor(init: T) {
+ super()
+ this._value = init
+ this.variable = new config.VariableBase
+ this.variable.connect("dropped", () => {
+ this.stopWatch()
+ this.stopPoll()
+ })
+ this.variable.connect("error", (_, err) => this.errHandler?.(err))
+ return new Proxy(this, {
+ apply: (target, _, args) => target._call(args[0]),
+ })
+ }
+
+ private _call<R = T>(transform?: (value: T) => R): Binding<R> {
+ const b = Binding.bind(this)
+ return transform ? b.as(transform) : b as unknown as Binding<R>
+ }
+
+ toString() {
+ return String(`Variable<${this.get()}>`)
+ }
+
+ get(): T { return this._value }
+ set(value: T) {
+ if (value !== this._value) {
+ this._value = value
+ this.variable.emit("changed")
+ }
+ }
+
+ startPoll() {
+ if (this._poll)
+ return
+
+ if (this.pollFn) {
+ this._poll = config.interval(this.pollInterval, () => {
+ const v = this.pollFn!(this.get())
+ if (v instanceof Promise) {
+ v.then(v => this.set(v))
+ .catch(err => this.variable.emit("error", err))
+ } else {
+ this.set(v)
+ }
+ })
+ } else if (this.pollExec) {
+ this._poll = config.interval(this.pollInterval, () => {
+ config.execAsync(this.pollExec!)
+ .then(v => this.set(this.pollTransform!(v, this.get())))
+ .catch(err => this.variable.emit("error", err))
+ })
+ }
+ }
+
+ startWatch() {
+ if (this._watch)
+ return
+
+ this._watch = config.subprocess({
+ cmd: this.watchExec!,
+ out: out => this.set(this.watchTransform!(out, this.get())),
+ err: err => this.variable.emit("error", err),
+ })
+ }
+
+ stopPoll() {
+ this._poll?.cancel()
+ delete this._poll
+ }
+
+ stopWatch() {
+ this._watch?.kill()
+ delete this._watch
+ }
+
+ isPolling() { return !!this._poll }
+ isWatching() { return !!this._watch }
+
+ drop() {
+ this.variable.emit("dropped")
+ this.variable.runDispose?.()
+ this.variable.run_dispose?.()
+ }
+
+ onDropped(callback: () => void) {
+ this.variable.connect("dropped", callback)
+ return this as unknown as Variable<T>
+ }
+
+ onError(callback: (err: string) => void) {
+ delete this.errHandler
+ this.variable.connect("error", (_, err) => callback(err))
+ return this as unknown as Variable<T>
+ }
+
+ subscribe(callback: (value: T) => void) {
+ const id = this.variable.connect("changed", () => {
+ callback(this.get())
+ })
+ return () => this.variable.disconnect(id)
+ }
+
+ poll(
+ interval: number,
+ exec: string | string[],
+ transform?: (stdout: string, prev: T) => T
+ ): Variable<T>
+
+ poll(
+ interval: number,
+ callback: (prev: T) => T | Promise<T>
+ ): Variable<T>
+
+ poll(
+ interval: number,
+ exec: string | string[] | ((prev: T) => T | Promise<T>),
+ transform: (stdout: string, prev: T) => T = out => out as T,
+ ) {
+ this.stopPoll()
+ this.pollInterval = interval
+ this.pollTransform = transform
+ if (typeof exec === "function") {
+ this.pollFn = exec
+ delete this.pollExec
+ } else {
+ this.pollExec = exec
+ delete this.pollFn
+ }
+ this.startPoll()
+ return this as unknown as Variable<T>
+ }
+
+ watch(
+ exec: string | string[],
+ transform: (stdout: string, prev: T) => T = out => out as T,
+ ) {
+ this.stopWatch()
+ this.watchExec = exec
+ this.watchTransform = transform
+ this.startWatch()
+ return this as unknown as Variable<T>
+ }
+
+ observe(
+ objs: Array<[obj: Connectable, signal: string]>,
+ callback: (...args: any[]) => T): Variable<T>
+
+ observe(
+ obj: Connectable,
+ signal: string,
+ callback: (...args: any[]) => T): Variable<T>
+
+ observe(
+ objs: Connectable | Array<[obj: Connectable, signal: string]>,
+ sigOrFn: string | ((...args: any[]) => T),
+ callback?: (...args: any[]) => T,
+ ) {
+ const f = typeof sigOrFn === "function" ? sigOrFn : callback ?? (() => this.get())
+ const set = (_: Connectable, ...args: any[]) => this.set(f(...args))
+
+ if (Array.isArray(objs)) {
+ for (const obj of objs) {
+ const [o, s] = obj
+ o.connect(s, set)
+ }
+ } else {
+ if (typeof sigOrFn === "string")
+ objs.connect(sigOrFn, set)
+ }
+
+ return this as unknown as Variable<T>
+ }
+
+ static derive<V,
+ const Deps extends Array<Variable<any> | Binding<any>>,
+ Args extends {
+ [K in keyof Deps]: Deps[K] extends Variable<infer T>
+ ? T : Deps[K] extends Binding<infer T> ? T : never
+ },
+ >(deps: Deps, fn: (...args: Args) => V) {
+ const update = () => fn(...deps.map(d => d.get()) as Args)
+ const derived = new Variable(update())
+ const unsubs = deps.map(dep => dep.subscribe(() => derived.set(update())))
+ derived.onDropped(() => unsubs.map(unsub => unsub()))
+ return derived
+ }
+}
+
+export interface Variable<T> extends Omit<VariableWrapper<T>, "bind"> {
+ <R>(transform: (value: T) => R): Binding<R>
+ (): Binding<T>
+}
+
+export const Variable = new Proxy(VariableWrapper as any, {
+ apply: (_t, _a, args) => new VariableWrapper(args[0]),
+}) as {
+ derive: typeof VariableWrapper["derive"]
+ <T>(init: T): Variable<T>
+ new <T>(init: T): Variable<T>
+}
+
+export default Variable
diff --git a/js/tsconfig.json b/js/tsconfig.json
new file mode 100644
index 0000000..9517ea8
--- /dev/null
+++ b/js/tsconfig.json
@@ -0,0 +1,23 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "module": "ES2022",
+ "lib": [
+ "ES2022"
+ ],
+ "outDir": "dist",
+ "strict": true,
+ "moduleResolution": "node",
+ "baseUrl": ".",
+ "skipLibCheck": true,
+ "forceConsistentCasingInFileNames": true,
+ "declaration": true,
+ "allowSyntheticDefaultImports": true
+ },
+ "include": [
+ "./@girs",
+ "./src",
+ "./gjs",
+ "./node"
+ ]
+}
diff --git a/lua/astal/application.lua b/lua/astal/application.lua
new file mode 100644
index 0000000..6146e33
--- /dev/null
+++ b/lua/astal/application.lua
@@ -0,0 +1,76 @@
+local lgi = require("lgi")
+local Astal = lgi.require("Astal", "0.1")
+
+local AstalLua = Astal.Application:derive("AstalLua")
+local request_handler
+
+function AstalLua:do_request(msg, conn)
+ if type(request_handler) == "function" then
+ request_handler(msg, function(request)
+ Astal.write_sock(conn, request, function(_, res)
+ Astal.write_sock_finish(res)
+ end)
+ end)
+ else
+ Astal.Application.do_request(self, msg, conn)
+ end
+end
+
+local app = AstalLua()
+
+---@class StartConfig
+---@field instance_name? string
+---@field gtk_theme? string
+---@field icon_theme? string
+---@field cursor_theme? string
+---@field css? string
+---@field hold? boolean
+---@field request_handler? fun(msg: string, response: fun(res: string))
+
+---@param config StartConfig | nil
+---@param callback function | nil
+function Astal.Application:start(config, callback)
+ if config == nil then
+ config = {}
+ end
+
+ if config.hold == nil then
+ config.hold = true
+ end
+
+ request_handler = config.request_handler
+
+ if config.css then
+ self:apply_css(config.css)
+ end
+ if config.instance_name then
+ self.instance_name = config.instance_name
+ end
+ if config.gtk_theme then
+ self.gtk_theme = config.gtk_theme
+ end
+ if config.icon_theme then
+ self.icon_theme = config.icon_theme
+ end
+ if config.cursor_theme then
+ self.cursor_theme = config.cursor_theme
+ end
+
+ app.on_activate = function()
+ if config.hold then
+ self:hold()
+ end
+ if type(callback) == "function" then
+ callback()
+ end
+ end
+
+ if not app:acquire_socket() then
+ print('Astal instance "' .. app.instance_name .. '" is already running')
+ os.exit(1)
+ end
+
+ self:run(nil)
+end
+
+return app
diff --git a/lua/astal/binding.lua b/lua/astal/binding.lua
new file mode 100644
index 0000000..264986b
--- /dev/null
+++ b/lua/astal/binding.lua
@@ -0,0 +1,65 @@
+local lgi = require("lgi")
+local GObject = lgi.require("GObject", "2.0")
+
+---@class Binding
+---@field emitter object
+---@field property? string
+---@field transformFn function
+local Binding = {}
+
+---@param emitter object
+---@param property? string
+---@return Binding
+function Binding.new(emitter, property)
+ return setmetatable({
+ emitter = emitter,
+ property = property,
+ transformFn = function(v)
+ return v
+ end,
+ }, Binding)
+end
+
+function Binding:__tostring()
+ local str = "Binding<" .. tostring(self:get())
+ if self.property ~= nil then
+ str = str .. ", " .. self.property
+ end
+ return str .. ">"
+end
+
+function Binding:get()
+ if type(self.emitter.get) == "function" then
+ return self.transformFn(self.emitter:get())
+ end
+ return self.transformFn(self.emitter[self.property])
+end
+
+---@param transform fun(value: any): any
+---@return Binding
+function Binding:as(transform)
+ local b = Binding.new(self.emitter, self.property)
+ b.transformFn = function(v)
+ return transform(self.transformFn(v))
+ end
+ return b
+end
+
+---@param callback fun(value: any)
+---@return function
+function Binding:subscribe(callback)
+ if type(self.emitter.subscribe) == "function" then
+ return self.emitter:subscribe(function()
+ callback(self:get())
+ end)
+ end
+ local id = self.emitter.on_notify:connect(function()
+ callback(self:get())
+ end, self.property, false)
+ return function()
+ GObject.signal_handler_disconnect(self.emitter, id)
+ end
+end
+
+Binding.__index = Binding
+return Binding
diff --git a/lua/astal/init.lua b/lua/astal/init.lua
new file mode 100644
index 0000000..c247533
--- /dev/null
+++ b/lua/astal/init.lua
@@ -0,0 +1,30 @@
+local lgi = require("lgi")
+local Astal = lgi.require("Astal", "0.1")
+local Gtk = lgi.require("Gtk", "3.0")
+local GObject = lgi.require("GObject", "2.0")
+local Widget = require("astal.widget")
+local Variable = require("astal.variable")
+local Binding = require("astal.binding")
+local App = require("astal.application")
+local Process = require("astal.process")
+local Time = require("astal.time")
+
+return {
+ App = App,
+ Variable = Variable,
+ Widget = Widget,
+ bind = Binding.new,
+ interval = Time.interval,
+ timeout = Time.timeout,
+ idle = Time.idle,
+ subprocess = Process.subprocess,
+ exec = Process.exec,
+ exec_async = Process.exec_async,
+
+ Astal = Astal,
+ Gtk = Gtk,
+ GObject = GObject,
+ GLib = lgi.require("GLib", "2.0"),
+ Gio = lgi.require("Gio", "2.0"),
+ require = lgi.require,
+}
diff --git a/lua/astal/process.lua b/lua/astal/process.lua
new file mode 100644
index 0000000..804fd0f
--- /dev/null
+++ b/lua/astal/process.lua
@@ -0,0 +1,93 @@
+local lgi = require("lgi")
+local Astal = lgi.require("Astal", "0.1")
+
+local M = {}
+
+local defualt_proc_args = function(on_stdout, on_stderr)
+ if on_stdout == nil then
+ on_stdout = function(out)
+ io.stdout:write(tostring(out) .. "\n")
+ return tostring(out)
+ end
+ end
+
+ if on_stderr == nil then
+ on_stderr = function(err)
+ io.stderr:write(tostring(err) .. "\n")
+ return tostring(err)
+ end
+ end
+
+ return on_stdout, on_stderr
+end
+
+---@param commandline string | string[]
+---@param on_stdout? fun(out: string): nil
+---@param on_stderr? fun(err: string): nil
+---@return { kill: function } | nil proc
+function M.subprocess(commandline, on_stdout, on_stderr)
+ local out, err = defualt_proc_args(on_stdout, on_stderr)
+ local proc, fail
+ if type(commandline) == "table" then
+ proc, fail = Astal.Process.subprocessv(commandline)
+ else
+ proc, fail = Astal.Process.subprocess(commandline)
+ end
+ if fail ~= nil then
+ err(fail)
+ return nil
+ end
+ proc.on_stdout = function(_, str)
+ out(str)
+ end
+ proc.on_stderr = function(_, str)
+ err(str)
+ end
+ return proc
+end
+
+---@generic T
+---@param commandline string | string[]
+---@param on_stdout? fun(out: string): T
+---@param on_stderr? fun(err: string): T
+---@return T
+function M.exec(commandline, on_stdout, on_stderr)
+ local out, err = defualt_proc_args(on_stdout, on_stderr)
+ local stdout, stderr
+ if type(commandline) == "table" then
+ stdout, stderr = Astal.Process.execv(commandline)
+ else
+ stdout, stderr = Astal.Process.exec(commandline)
+ end
+ if stderr then
+ return err(stderr)
+ end
+ return out(stdout)
+end
+
+---@param commandline string | string[]
+---@param on_stdout? fun(out: string): nil
+---@param on_stderr? fun(err: string): nil
+---@return { kill: function } | nil proc
+function M.exec_async(commandline, on_stdout, on_stderr)
+ local out, err = defualt_proc_args(on_stdout, on_stderr)
+ local proc, fail
+ if type(commandline) == "table" then
+ proc, fail = Astal.Process.exec_asyncv(commandline)
+ else
+ proc, fail = Astal.Process.exec_async(commandline)
+ end
+ if fail ~= nil then
+ err(fail)
+ return nil
+ end
+ proc.on_stdout = function(_, str)
+ out(str)
+ end
+ proc.on_stderr = function(_, str)
+ err(str)
+ end
+ return proc
+end
+
+return M
diff --git a/lua/astal/time.lua b/lua/astal/time.lua
new file mode 100644
index 0000000..f4e2b81
--- /dev/null
+++ b/lua/astal/time.lua
@@ -0,0 +1,27 @@
+local lgi = require("lgi")
+local Astal = lgi.require("Astal", "0.1")
+local GObject = lgi.require("GObject", "2.0")
+
+local M = {}
+
+---@param interval number
+---@param fn function
+---@return { cancel: function, on_now: function }
+function M.interval(interval, fn)
+ return Astal.Time.interval(interval, GObject.Closure(fn))
+end
+
+---@param timeout number
+---@param fn function
+---@return { cancel: function, on_now: function }
+function M.timeout(timeout, fn)
+ return Astal.Time.timeout(timeout, GObject.Closure(fn))
+end
+
+---@param fn function
+---@return { cancel: function, on_now: function }
+function M.idle(fn)
+ return Astal.Time.idle(GObject.Closure(fn))
+end
+
+return M
diff --git a/lua/astal/variable.lua b/lua/astal/variable.lua
new file mode 100644
index 0000000..baa2d69
--- /dev/null
+++ b/lua/astal/variable.lua
@@ -0,0 +1,270 @@
+local lgi = require("lgi")
+local Astal = lgi.require("Astal", "0.1")
+local GObject = lgi.require("GObject", "2.0")
+local Binding = require("astal.binding")
+local Time = require("astal.time")
+local Process = require("astal.process")
+
+---@class Variable
+---@field private variable object
+---@field private err_handler? function
+---@field private _value any
+---@field private _poll? object
+---@field private _watch? object
+---@field private poll_interval number
+---@field private poll_exec? string[] | string
+---@field private poll_transform? fun(next: any, prev: any): any
+---@field private poll_fn? function
+---@field private watch_transform? fun(next: any, prev: any): any
+---@field private watch_exec? string[] | string
+local Variable = {}
+Variable.__index = Variable
+
+---@param value any
+---@return Variable
+function Variable.new(value)
+ local v = Astal.VariableBase()
+ local variable = setmetatable({
+ variable = v,
+ _value = value,
+ }, Variable)
+ v.on_dropped = function()
+ variable:stop_watch()
+ variable:stop_watch()
+ end
+ v.on_error = function(_, err)
+ if variable.err_handler then
+ variable.err_handler(err)
+ end
+ end
+ return variable
+end
+
+---@param transform function
+---@return Binding
+function Variable:__call(transform)
+ if transform == nil then
+ transform = function(v)
+ return v
+ end
+ return Binding.new(self)
+ end
+ return Binding.new(self):as(transform)
+end
+
+function Variable:__tostring()
+ return "Variable<" .. tostring(self:get()) .. ">"
+end
+
+function Variable:get()
+ return self._value or nil
+end
+
+function Variable:set(value)
+ if value ~= self:get() then
+ self._value = value
+ self.variable:emit_changed()
+ end
+end
+
+function Variable:start_poll()
+ if self._poll ~= nil then
+ return
+ end
+
+ if self.poll_fn then
+ self._poll = Time.interval(self.poll_interval, function()
+ self:set(self.poll_fn(self:get()))
+ end)
+ elseif self.poll_exec then
+ self._poll = Time.interval(self.poll_interval, function()
+ Process.exec_async(self.poll_exec, function(out)
+ self:set(self.poll_transform(out, self:get()))
+ end, function(err)
+ self.variable.emit_error(err)
+ end)
+ end)
+ end
+end
+
+function Variable:start_watch()
+ if self._watch then
+ return
+ end
+
+ self._watch = Process.subprocess(self.watch_exec, function(out)
+ self:set(self.watch_transform(out, self:get()))
+ end, function(err)
+ self.variable.emit_error(err)
+ end)
+end
+
+function Variable:stop_poll()
+ if self._poll then
+ self._poll.cancel()
+ end
+ self._poll = nil
+end
+
+function Variable:stop_watch()
+ if self._watch then
+ self._watch.kill()
+ end
+ self._watch = nil
+end
+
+function Variable:is_polling()
+ return self._poll ~= nil
+end
+
+function Variable:is_watching()
+ return self._watch ~= nil
+end
+
+function Variable:drop()
+ self.variable.emit_dropped()
+ self.variable.run_dispose()
+end
+
+---@param callback function
+---@return Variable
+function Variable:on_dropped(callback)
+ self.variable.on_dropped = callback
+ return self
+end
+
+---@param callback function
+---@return Variable
+function Variable:on_error(callback)
+ self.err_handler = nil
+ self.variable.on_eror = function(_, err)
+ callback(err)
+ end
+ return self
+end
+
+---@param callback fun(value: any)
+---@return function
+function Variable:subscribe(callback)
+ local id = self.variable.on_changed:connect(function()
+ callback(self:get())
+ end)
+ return function()
+ GObject.signal_handler_disconnect(self.variable, id)
+ end
+end
+
+---@param interval number
+---@param exec string | string[] | function
+---@param transform? fun(next: any, prev: any): any
+function Variable:poll(interval, exec, transform)
+ if transform == nil then
+ transform = function(next)
+ return next
+ end
+ end
+ self:stop_poll()
+ self.poll_interval = interval
+ self.poll_transform = transform
+
+ if type(exec) == "function" then
+ self.poll_fn = exec
+ self.poll_exec = nil
+ else
+ self.poll_exec = exec
+ self.poll_fn = nil
+ end
+ self:start_poll()
+ return self
+end
+
+---@param exec string | string[]
+---@param transform? fun(next: any, prev: any): any
+function Variable:watch(exec, transform)
+ if transform == nil then
+ transform = function(next)
+ return next
+ end
+ end
+ self:stop_poll()
+ self.watch_exec = exec
+ self.watch_transform = transform
+ self:start_watch()
+ return self
+end
+
+---@param object object | table[]
+---@param sigOrFn string | fun(...): any
+---@param callback fun(...): any
+---@return Variable
+function Variable:observe(object, sigOrFn, callback)
+ local f
+ if type(sigOrFn) == "function" then
+ f = sigOrFn
+ elseif type(callback) == "function" then
+ f = callback
+ else
+ f = function()
+ return self:get()
+ end
+ end
+ local set = function(_, ...)
+ self:set(f(...))
+ end
+
+ if type(sigOrFn) == "string" then
+ object["on_" .. sigOrFn]:connect(set)
+ else
+ for _, obj in ipairs(object) do
+ obj[1]["on_" .. obj[2]]:connect(set)
+ end
+ end
+ return self
+end
+
+---@param deps Variable | (Binding | Variable)[]
+---@param transform fun(...): any
+---@return Variable
+function Variable.derive(deps, transform)
+ if getmetatable(deps) == Variable then
+ local var = Variable.new(transform(deps:get()))
+ deps:subscribe(function(v)
+ var:set(transform(v))
+ end)
+ return var
+ end
+
+ for i, var in ipairs(deps) do
+ if getmetatable(var) == Variable then
+ deps[i] = Binding.new(var)
+ end
+ end
+
+ local update = function()
+ local params = {}
+ for _, binding in ipairs(deps) do
+ table.insert(params, binding:get())
+ end
+ return transform(table.unpack(params))
+ end
+
+ local var = Variable.new(update())
+
+ local unsubs = {}
+ for _, b in ipairs(deps) do
+ table.insert(unsubs, b:subscribe(update))
+ end
+
+ var.variable.on_dropped = function()
+ for _, unsub in ipairs(unsubs) do
+ var:set(unsub())
+ end
+ end
+ return var
+end
+
+return setmetatable(Variable, {
+ __call = function(_, v)
+ return Variable.new(v)
+ end,
+})
diff --git a/lua/astal/widget.lua b/lua/astal/widget.lua
new file mode 100644
index 0000000..ade000e
--- /dev/null
+++ b/lua/astal/widget.lua
@@ -0,0 +1,123 @@
+local lgi = require("lgi")
+local Astal = lgi.require("Astal", "0.1")
+local Gtk = lgi.require("Gtk", "3.0")
+local GObject = lgi.require("GObject", "2.0")
+local Binding = require("astal.binding")
+
+local function filter(tbl, fn)
+ local copy = {}
+ for key, value in pairs(tbl) do
+ if fn(value, key) then
+ copy[key] = value
+ end
+ end
+ return copy
+end
+
+Gtk.Widget._attribute.css = {
+ get = Astal.widget_get_css,
+ set = Astal.widget_set_css,
+}
+
+Gtk.Widget._attribute.class_name = {
+ get = function(self)
+ local result = ""
+ local strings = Astal.widget_set_class_names(self)
+ for i, str in ipairs(strings) do
+ result = result .. str
+ if i < #strings then
+ result = result .. " "
+ end
+ end
+ return result
+ end,
+ set = function(self, class_name)
+ local names = {}
+ for word in class_name:gmatch("%S+") do
+ table.insert(names, word)
+ end
+ Astal.widget_set_class_names(self, names)
+ end,
+}
+
+Gtk.Widget._attribute.cursor = {
+ get = Astal.widget_get_cursor,
+ set = Astal.widget_set_cursor,
+}
+
+Astal.Box._attribute.children = {
+ get = Astal.Box.get_children,
+ set = Astal.Box.set_children,
+}
+
+local function astalify(ctor)
+ function ctor:hook(object, signalOrCallback, callback)
+ if type(object.subscribe) == "function" then
+ local unsub = object.subscribe(function(...)
+ signalOrCallback(self, ...)
+ end)
+ self.on_destroy = unsub
+ return
+ end
+ local id = object["on_" .. signalOrCallback](function(_, ...)
+ callback(self, ...)
+ end)
+ self.on_destroy = function()
+ GObject.signal_handler_disconnect(object, id)
+ end
+ end
+
+ return function(tbl)
+ local bindings = {}
+ local setup = tbl.setup
+
+ local visible
+ if type(tbl.visible) == "boolean" then
+ visible = tbl.visible
+ else
+ visible = true
+ end
+
+ local props = filter(tbl, function(_, key)
+ return key ~= "visible" and key ~= "setup"
+ end)
+
+ for prop, value in pairs(props) do
+ if getmetatable(value) == Binding then
+ bindings[prop] = value
+ props[prop] = value:get()
+ end
+ end
+
+ local widget = ctor(props)
+
+ for prop, binding in pairs(bindings) do
+ widget.on_destroy = binding:subscribe(function(v)
+ widget[prop] = v
+ end)
+ end
+
+ widget.visible = visible
+ if type(setup) == "function" then
+ setup(widget)
+ end
+ return widget
+ end
+end
+
+local Widget = {
+ astalify = astalify,
+ Box = astalify(Astal.Box),
+ Button = astalify(Astal.Button),
+ CenterBox = astalify(Astal.CenterBox),
+ Label = astalify(Gtk.Label),
+ Icon = astalify(Astal.Icon),
+ Window = astalify(Astal.Window),
+ EventBox = astalify(Astal.EventBox),
+}
+
+return setmetatable(Widget, {
+ __call = function(_, ctor)
+ return astalify(ctor)
+ end,
+})
diff --git a/lua/sample.lua b/lua/sample.lua
new file mode 100755
index 0000000..2c76af6
--- /dev/null
+++ b/lua/sample.lua
@@ -0,0 +1,81 @@
+#!/usr/bin/env lua
+-- imports
+local astal = require("astal.init")
+local Widget, Variable, App, bind = astal.Widget, astal.Variable, astal.App, astal.bind
+
+-- state
+local player = astal.require("Playerctl").Player.new("spotify")
+
+local title = Variable(player:get_title()):observe(player, "metadata", function()
+ return player:get_title()
+end)
+
+local rnd = Variable(1):poll(1000, function()
+ return math.random(1, 10)
+end)
+
+-- ui
+local Bar = function(monitor)
+ return Widget.Window({
+ application = App,
+ id = "bar",
+ name = "bar",
+ monitor = monitor,
+ anchor = astal.Astal.WindowAnchor.BOTTOM
+ + astal.Astal.WindowAnchor.LEFT
+ + astal.Astal.WindowAnchor.RIGHT,
+ exclusivity = "EXCLUSIVE",
+
+ Widget.CenterBox({
+ class_name = "bar",
+ start_widget = Widget.Label({
+ valign = "CENTER",
+ label = "Welcome to Astal.lua",
+ }),
+ center_widget = Widget.Box({
+ children = bind(rnd):as(function(n)
+ local children = {}
+ for i = 1, n, 1 do
+ table.insert(
+ children,
+ Widget.Button({
+ label = tostring(i),
+ on_clicked = function()
+ print(i)
+ end,
+ })
+ )
+ end
+ return children
+ end),
+ }),
+ end_widget = Widget.Label({
+ valign = "CENTER",
+ label = bind(title),
+ }),
+ }),
+ })
+end
+
+-- css
+local css = [[
+.bar button {
+ color: blue;
+}
+]]
+
+-- main
+App:start({
+ request_handler = function(msg, res)
+ if msg == "quit" then
+ os.exit(0)
+ end
+ if msg == "inspector" then
+ res(App:inspector())
+ end
+ res("hi")
+ end,
+ css = css,
+}, function()
+ Bar(0)
+end)
diff --git a/lua/stylua.toml b/lua/stylua.toml
new file mode 100644
index 0000000..d4a4951
--- /dev/null
+++ b/lua/stylua.toml
@@ -0,0 +1,3 @@
+indent_type = "Spaces"
+indent_width = 4
+column_width = 100
diff --git a/meson-install.sh b/meson-install.sh
new file mode 100644
index 0000000..0e6b258
--- /dev/null
+++ b/meson-install.sh
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+
+meson setup \
+ --prefix /usr \
+ --libexecdir lib \
+ --sbindir bin \
+ --buildtype plain \
+ --auto-features enabled \
+ --wrap-mode nodownload \
+ -D b_lto=false \
+ -D b_pie=true \
+ -D python.bytecompile=1 \
+ --wipe \
+ build
+
+meson install -C build
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..63de369
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,17 @@
+project(
+ 'astal',
+ 'vala',
+ 'c',
+ version: run_command('cat', join_paths(meson.project_source_root(), 'version')).stdout().strip(),
+ meson_version: '>= 0.62.0',
+ default_options: [
+ 'warning_level=2',
+ 'werror=false',
+ 'c_std=gnu11',
+ ],
+)
+
+# math
+add_project_arguments(['-X', '-lm'], language: 'vala')
+
+subdir('src')
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 0000000..8eff355
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,2 @@
+option('typelib', type: 'boolean', value: true, description: 'Needed files for runtime bindings')
+option('cli_client', type: 'boolean', value: true, description: 'Minimal cli client for Astal applications')
diff --git a/python/.gitignore b/python/.gitignore
new file mode 100644
index 0000000..c18dd8d
--- /dev/null
+++ b/python/.gitignore
@@ -0,0 +1 @@
+__pycache__/
diff --git a/python/astal/__init__.py b/python/astal/__init__.py
new file mode 100644
index 0000000..c679c4a
--- /dev/null
+++ b/python/astal/__init__.py
@@ -0,0 +1,16 @@
+import gi
+
+gi.require_version("Astal", "0.1")
+gi.require_version("Gtk", "3.0")
+gi.require_version("GLib", "2.0")
+gi.require_version("Gio", "2.0")
+gi.require_version("GObject", "2.0")
+from gi.repository import Astal, Gtk, GLib, Gio, GObject
+from .application import App
+from .variable import Variable
+from .binding import Binding
+from . import widget as Widget
+
+bind = Binding
+
+__all__ = ["App", "Variable", "Widget" "bind", "Astal", "Gtk", "GLib", "Gio", "GObject"]
diff --git a/python/astal/application.py b/python/astal/application.py
new file mode 100644
index 0000000..3eb1a4f
--- /dev/null
+++ b/python/astal/application.py
@@ -0,0 +1,62 @@
+from collections.abc import Callable
+from gi.repository import Astal, Gio
+
+RequestHandler = Callable[[str, Callable[[str], None]], None]
+
+
+class _Application(Astal.Application):
+ def __init__(self) -> None:
+ super().__init__()
+ self.request_handler: RequestHandler | None = None
+
+ def do_response(self, msg: str, conn: Gio.SocketConnection) -> None:
+ if self.request_handler:
+ self.request_handler(
+ msg,
+ lambda response: Astal.write_sock(
+ conn,
+ response,
+ lambda _, res: Astal.write_sock_finish(res),
+ ),
+ )
+ else:
+ super().do_response(msg, conn)
+
+ def start(
+ self,
+ instance_name: str | None = None,
+ gtk_theme: str | None = None,
+ icon_theme: str | None = None,
+ cursor_theme: str | None = None,
+ css: str | None = None,
+ hold: bool | None = True,
+ request_handler: RequestHandler | None = None,
+ callback: Callable | None = None,
+ ) -> None:
+ if request_handler:
+ self.request_handler = request_handler
+ if hold:
+ self.hold()
+ if instance_name:
+ self.instance_name = instance_name
+ if gtk_theme:
+ self.gtk_theme = gtk_theme
+ if icon_theme:
+ self.icon_theme = icon_theme
+ if cursor_theme:
+ self.cursor_theme = icon_theme
+ if css:
+ self.apply_css(css, False)
+ if not self.acquire_socket():
+ print(f"Astal instance {self.instance_name} already running")
+ return
+
+ def on_activate(app):
+ if callback:
+ callback()
+
+ self.connect("activate", on_activate)
+ self.run()
+
+
+App = _Application()
diff --git a/python/astal/binding.py b/python/astal/binding.py
new file mode 100644
index 0000000..0fe1b6c
--- /dev/null
+++ b/python/astal/binding.py
@@ -0,0 +1,33 @@
+import re
+
+
+def kebabify(string):
+ return re.sub(r"([a-z])([A-Z])", r"\1-\2", string).replace("_", "-").lower()
+
+
+class Binding:
+ def __init__(self, emitter, prop=None):
+ self.emitter = emitter
+ self.prop = kebabify(prop) if prop else None
+ self.transform_fn = lambda v: v
+
+ def __str__(self):
+ return f"Binding<{self.emitter}{', ' + self.prop if self.prop else ''}>"
+
+ def as_(self, fn):
+ bind = Binding(self.emitter, self.prop)
+ bind.transform_fn = lambda v: fn(self.transform_fn(v))
+ return bind
+
+ def get(self):
+ if hasattr(self.emitter, "get") and callable(self.emitter.get):
+ return self.transform_fn(self.emitter.get())
+
+ return self.transform_fn(self.emitter[f"get_{self.prop}"]())
+
+ def subscribe(self, callback):
+ if hasattr(self.emitter, "subscribe") and callable(self.emitter.subscribe):
+ return self.emitter.subscribe(lambda _: callback(self.get()))
+
+ i = self.emitter.connect(f"notify::{self.prop}", lambda: callback(self.get()))
+ return lambda: self.emitter.disconnect(i)
diff --git a/python/astal/variable.py b/python/astal/variable.py
new file mode 100644
index 0000000..3b6a71d
--- /dev/null
+++ b/python/astal/variable.py
@@ -0,0 +1,100 @@
+from gi.repository import Astal
+
+from .binding import Binding
+
+
+class Variable:
+ def __init__(self, init):
+ v = Astal.Variable.new(init)
+ self._variable = v
+ self._err_handler = print
+ v.connect("error", lambda _, err: self._err_handler(err) if self._err_handler else None)
+
+ def __call__(self, transform=None):
+ if transform:
+ return Binding(self).as_(transform)
+
+ return Binding(self)
+
+ def __str__(self):
+ return f"Variable<{self.get()}>"
+
+ def get(self):
+ return self._variable.get_value()
+
+ def set(self, value):
+ return self._variable.set_value(value)
+
+ def watch(self, cmd):
+ if isinstance(cmd, str):
+ self._variable.watch(cmd)
+ elif isinstance(cmd, list):
+ self._variable.watchv(cmd)
+ return self
+
+ def poll(self, interval, cmd):
+ if isinstance(cmd, str):
+ self._variable.poll(interval, cmd)
+ elif isinstance(cmd, list):
+ self._variable.pollv(interval, cmd)
+ else:
+ self._variable.pollfn(interval, cmd)
+ return self
+
+ def start_watch(self):
+ self._variable.start_watch()
+
+ def start_poll(self):
+ self._variable.start_poll()
+
+ def stop_watch(self):
+ self._variable.stop_watch()
+
+ def stop_poll(self):
+ self._variable.stop_poll()
+
+ def drop(self):
+ self._variable.emit_dropped()
+ self._variable.run_dispose()
+
+ def on_dropped(self, callback):
+ self._variable.connect("dropped", lambda _: callback())
+ return self
+
+ def on_error(self, callback):
+ self._err_handler = None
+ self._variable.connect("error", lambda _, e: callback(e))
+ return self
+
+ def subscribe(self, callback):
+ s = self._variable.connect("changed", lambda _: callback(self.get()))
+ return lambda: self._variable.disconnect(s)
+
+ def observe(self, objs, sigOrFn, callback=None):
+ if callable(sigOrFn):
+ f = sigOrFn
+ elif callable(callback):
+ f = callback
+ else:
+ f = lambda *_: self.get()
+
+ def setter(_, *args):
+ self.set(f(*args))
+
+ if isinstance(objs, list):
+ for obj in objs:
+ obj[0].connect(obj[1], setter)
+ elif isinstance(sigOrFn, str):
+ objs.connect(sigOrFn, setter)
+
+ return self
+
+ @staticmethod
+ def derive(deps, fn):
+ def update():
+ return fn(*[d.get() for d in deps])
+
+ derived = Variable(update())
+ unsubs = [dep.subscribe(lambda _: derived.set(update())) for dep in deps]
+ derived.on_dropped(lambda: ([unsub() for unsub in unsubs]))
+ return derived
diff --git a/python/astal/widget.py b/python/astal/widget.py
new file mode 100644
index 0000000..7070e8f
--- /dev/null
+++ b/python/astal/widget.py
@@ -0,0 +1,65 @@
+from gi.repository import Astal, Gtk
+from .binding import Binding
+
+
+def set_child(self, child):
+ if isinstance(self, Gtk.Bin):
+ self.remove(self.get_child())
+ if isinstance(self, Gtk.Container):
+ self.add(child)
+
+
+def astalify(ctor):
+ ctor.set_css = Astal.widget_set_css
+ ctor.get_css = Astal.widget_get_css
+
+ ctor.set_class_name = lambda self, names: Astal.widget_set_class_names(self, names.split())
+ ctor.get_class_name = lambda self: " ".join(Astal.widget_set_class_names(self))
+
+ ctor.set_cursor = Astal.widget_set_cursor
+ ctor.get_cursor = Astal.widget_get_cursor
+
+ def widget(**kwargs):
+ args = {}
+ bindings = {}
+ handlers = {}
+ setup = None
+ if not hasattr(kwargs, "visible"):
+ kwargs["visible"] = True
+
+ for key, value in kwargs.items():
+ if key == "setup":
+ setup = value
+ if isinstance(value, Binding):
+ bindings[key] = value
+ if key.startswith("on_"):
+ handlers[key] = value
+ else:
+ args[key] = value
+
+ self = ctor(**args)
+
+ for key, value in bindings.items():
+ setter = getattr(self, f"set_{key}")
+ setter(value.get())
+ unsub = value.subscribe(setter)
+ self.connect("destroy", lambda _: unsub())
+
+ for key, value in handlers.items():
+ self.connect(key.replace("on_", ""), value)
+
+ if setup:
+ setup(self)
+
+ return self
+
+ return widget
+
+
+Window = astalify(Astal.Window)
+Box = astalify(Astal.Box)
+Button = astalify(Astal.Button)
+CenterBox = astalify(Astal.CenterBox)
+Label = astalify(Gtk.Label)
+Icon = astalify(Astal.Icon)
+EventBox = astalify(Astal.EventBox)
diff --git a/python/pyproject.toml b/python/pyproject.toml
new file mode 100644
index 0000000..2103286
--- /dev/null
+++ b/python/pyproject.toml
@@ -0,0 +1,14 @@
+[tool.poetry]
+name = "astal.py"
+version = "0.1.0"
+description = ""
+authors = []
+
+[tool.poetry.dependencies]
+python = "^3.11"
+gengir = "^1.0.2"
+
+
+[build-system]
+requires = ["poetry-core"]
+build-backend = "poetry.core.masonry.api"
diff --git a/python/ruff.toml b/python/ruff.toml
new file mode 100644
index 0000000..a6bedc2
--- /dev/null
+++ b/python/ruff.toml
@@ -0,0 +1,62 @@
+target-version = "py311"
+
+exclude = [
+ ".bzr",
+ ".direnv",
+ ".eggs",
+ ".git",
+ ".git-rewrite",
+ ".hg",
+ ".ipynb_checkpoints",
+ ".mypy_cache",
+ ".nox",
+ ".pants.d",
+ ".pyenv",
+ ".pytest_cache",
+ ".pytype",
+ ".ruff_cache",
+ ".svn",
+ ".tox",
+ ".venv",
+ ".vscode",
+ "__pypackages__",
+ "_build",
+ "buck-out",
+ "build",
+ "dist",
+ "node_modules",
+ "site-packages",
+ "venv",
+]
+
+line-length = 100
+indent-width = 4
+
+[lint]
+select = ["ALL"]
+ignore = ["D", "ANN101", "ERA", "ANN"]
+
+# Allow fix for all enabled rules (when `--fix`) is provided.
+fixable = ["ALL"]
+unfixable = []
+
+# Allow unused variables when underscore-prefixed.
+dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
+
+[format]
+quote-style = "double"
+indent-style = "space"
+
+# Like Black, respect magic trailing commas.
+skip-magic-trailing-comma = false
+
+# Like Black, automatically detect the appropriate line ending.
+line-ending = "auto"
+
+# Enable auto-formatting of code examples in docstrings. Markdown,
+# reStructuredText code/literal blocks and doctests are all supported.
+docstring-code-format = false
+
+# Set the line length limit used when formatting code snippets in
+# docstrings.
+docstring-code-line-length = "dynamic"
diff --git a/python/sample.py b/python/sample.py
new file mode 100755
index 0000000..af09ce2
--- /dev/null
+++ b/python/sample.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python3
+import gi
+
+gi.require_version("Playerctl", "2.0")
+
+from gi.repository import Playerctl
+from astal import App, Astal, Variable, Widget, bind
+
+player = Playerctl.Player.new("spotify")
+v = Variable(player.get_title()).observe(player, "metadata", lambda *_: player.get_title())
+
+
+def Bar(monitor):
+ return Widget.Window(
+ anchor=Astal.WindowAnchor.BOTTOM | Astal.WindowAnchor.LEFT | Astal.WindowAnchor.RIGHT,
+ monitor=monitor,
+ exclusivity=Astal.Exclusivity.EXCLUSIVE,
+ child=Widget.CenterBox(
+ start_widget=Widget.Label(
+ label="Welcome to Astal.py!",
+ ),
+ end_widget=Widget.Label(label=v()),
+ ),
+ )
+
+
+def start():
+ Bar(0)
+
+
+App.start(callback=start)
diff --git a/src/astal.vala b/src/astal.vala
new file mode 100644
index 0000000..e9d1484
--- /dev/null
+++ b/src/astal.vala
@@ -0,0 +1,171 @@
+namespace Astal {
+public class Application : Gtk.Application {
+ public signal void request (string request);
+ private List<Gtk.CssProvider> css_providers;
+ private SocketService service;
+ private string socket;
+
+ public string instance_name { get; construct set; }
+
+ public List<Gtk.Window> windows {
+ get { return get_windows(); }
+ }
+
+ public Gtk.Settings settings {
+ get { return Gtk.Settings.get_default(); }
+ }
+
+ public Gdk.Screen screen {
+ get { return Gdk.Screen.get_default(); }
+ }
+
+ public string gtk_theme {
+ owned get { return settings.gtk_theme_name; }
+ set { settings.gtk_theme_name = value; }
+ }
+
+ public string icon_theme {
+ owned get { return settings.gtk_icon_theme_name; }
+ set { settings.gtk_icon_theme_name = value; }
+ }
+
+ public string cursor_theme {
+ owned get { return settings.gtk_cursor_theme_name; }
+ set { settings.gtk_cursor_theme_name = value; }
+ }
+
+ public void reset_css() {
+ foreach(var provider in css_providers) {
+ Gtk.StyleContext.remove_provider_for_screen(screen, provider);
+ css_providers.remove_all(provider);
+ }
+ }
+
+ public void inspector() {
+ Gtk.Window.set_interactive_debugging(true);
+ }
+
+ public Gtk.Window get_window(string name) throws WindowError {
+ foreach(var win in windows) {
+ if (win.name == name)
+ return win;
+ }
+
+ throw new WindowError.NO_WINDOW_WITH_NAME(name);
+ }
+
+ public void apply_css(string style, bool reset = false) throws Error {
+ var provider = new Gtk.CssProvider();
+
+ if (reset)
+ reset_css();
+
+ if (FileUtils.test(style, FileTest.EXISTS))
+ provider.load_from_path(style);
+ else
+ provider.load_from_data(style);
+
+ Gtk.StyleContext.add_provider_for_screen(
+ screen, provider, Gtk.STYLE_PROVIDER_PRIORITY_USER);
+
+ css_providers.append(provider);
+ }
+
+ private async void _socket_request(SocketConnection conn) {
+ string message = yield read_sock(conn);
+ request(message.strip());
+ response(message.strip(), conn);
+ }
+
+ public virtual void response(string msg, SocketConnection conn) {
+ write_sock.begin(conn, "missing response implementation on ".concat(application_id));
+ }
+
+ /**
+ * should be called before `run()`
+ * the return value indicates if instance is already running
+ */
+ public bool acquire_socket() {
+ socket = GLib.Environment.get_user_runtime_dir().concat(
+ "/",
+ instance_name,
+ ".sock");
+
+ if (FileUtils.test(socket, GLib.FileTest.EXISTS)) {
+ info("socket %s exists", socket);
+ return false;
+ }
+
+ try {
+ SocketAddress _;
+ service = new SocketService();
+ service.add_address(
+ new UnixSocketAddress(socket),
+ SocketType.STREAM,
+ SocketProtocol.DEFAULT,
+ null,
+ out _);
+
+ service.incoming.connect((conn) => {
+ _socket_request.begin(conn);
+ return false;
+ });
+
+ info("socket acquired: %s\n", socket);
+ return true;
+ } catch (Error err) {
+ critical("could not acquire socket %s\n", application_id);
+ critical(err.message);
+ return false;
+ }
+ }
+
+ construct {
+ if (instance_name == null)
+ instance_name = "astal";
+
+ if (application_id == null)
+ application_id = "io.Astal.".concat(instance_name);
+
+ shutdown.connect(() => {
+ if (FileUtils.test(socket, GLib.FileTest.EXISTS)){
+ try {
+ File.new_for_path(socket).delete(null);
+ } catch (Error err) {
+ warning(err.message);
+ }
+ }
+ });
+
+ SourceFunc close = () => { quit(); };
+ Unix.signal_add(1, close, Priority.HIGH);
+ Unix.signal_add(2, close, Priority.HIGH);
+ Unix.signal_add(15, close, Priority.HIGH);
+ }
+}
+
+public errordomain WindowError {
+ NO_WINDOW_WITH_NAME
+}
+
+public async string read_sock(SocketConnection conn) {
+ try {
+ var stream = new DataInputStream(conn.input_stream);
+ size_t size;
+ return yield stream.read_upto_async("\x04", -1, Priority.DEFAULT, null, out size);
+ } catch (Error err) {
+ critical(err.message);
+ return err.message;
+ }
+}
+
+public async void write_sock(SocketConnection conn, string response) {
+ try {
+ yield conn.output_stream.write_async(
+ response.concat("\x04").data,
+ Priority.DEFAULT);
+ } catch (Error err) {
+ critical(err.message);
+ }
+}
+}
diff --git a/src/client.vala.in b/src/client.vala.in
new file mode 100644
index 0000000..82a99a4
--- /dev/null
+++ b/src/client.vala.in
@@ -0,0 +1,79 @@
+private static bool version;
+private static bool help;
+private static string? instance_name;
+
+private const GLib.OptionEntry[] options = {
+ { "version", 'v', OptionFlags.NONE, OptionArg.NONE, ref version, null, null },
+ { "help", 'h', OptionFlags.NONE, OptionArg.NONE, ref help, null, null },
+ { "instance-name", 'i', OptionFlags.NONE, OptionArg.STRING, ref instance_name, null, null },
+ { null },
+};
+
+async int main(string[] argv) {
+ try {
+ var opts = new OptionContext();
+ opts.add_main_entries(options, null);
+ opts.set_help_enabled(false);
+ opts.set_ignore_unknown_options(false);
+ opts.parse(ref argv);
+ } catch (OptionError err) {
+ printerr (err.message);
+ return 1;
+ }
+
+ if (help) {
+ print("Client for the socket of an Astal.Application instance\n\n");
+ print("Usage:\n");
+ print(" %s [flags] message\n\n", argv[0]);
+ print("Flags:\n");
+ print(" -h, --help Print this help and exit\n");
+ print(" -v, --version Print version number and exit\n");
+ print(" -i, --instance-name Instance name of the Astal instance\n");
+ return 0;
+ }
+
+ if (version) {
+ print("@VERSION@");
+ return 0;
+ }
+
+ if (instance_name == null)
+ instance_name = "astal";
+
+ var request = "";
+ for (var i = 1; i < argv.length; ++i) {
+ request = request.concat(" ", argv[i]);
+ }
+
+ var client = new SocketClient();
+ var rundir = GLib.Environment.get_user_runtime_dir();
+ var socket = rundir.concat("/", instance_name, ".sock");
+
+ try {
+ var conn = client.connect(new UnixSocketAddress(socket), null);
+
+ try {
+ yield conn.output_stream.write_async(
+ request.concat("\x04").data,
+ Priority.DEFAULT);
+ } catch (Error err) {
+ printerr("could not write to app '%s'", instance_name);
+ }
+
+ var stream = new DataInputStream(conn.input_stream);
+ size_t size;
+
+ try {
+ var res = yield stream.read_upto_async("\x04", -1, Priority.DEFAULT, null, out size);
+ if (res != null)
+ print("%s", res);
+ } catch (Error err) {
+ printerr(err.message);
+ }
+ } catch (Error err) {
+ printerr("could not connect to app '%s'", instance_name);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/src/meson.build b/src/meson.build
new file mode 100644
index 0000000..2227075
--- /dev/null
+++ b/src/meson.build
@@ -0,0 +1,85 @@
+version_split = meson.project_version().split('.')
+api_version = version_split[0] + '.' + version_split[1]
+astal_gir = 'Astal-' + api_version + '.gir'
+astal_typelib = 'Astal-' + api_version + '.typelib'
+astal_so = 'libastal.so.' + meson.project_version()
+
+deps = [
+ dependency('glib-2.0'),
+ dependency('gio-unix-2.0'),
+ dependency('gobject-2.0'),
+ dependency('gio-2.0'),
+ dependency('gtk+-3.0'),
+ dependency('gdk-pixbuf-2.0'),
+ dependency('gtk-layer-shell-0'),
+]
+
+sources = files(
+ 'widget/box.vala',
+ 'widget/button.vala',
+ 'widget/centerbox.vala',
+ 'widget/eventbox.vala',
+ 'widget/icon.vala',
+ # 'widget/circularprogress.vala', # TODO: math lib -X -lm
+ 'widget/widget.vala',
+ 'widget/window.vala',
+ 'astal.vala',
+ 'process.vala',
+ 'time.vala',
+ 'variable.vala',
+)
+
+libastal = library(
+ meson.project_name(),
+ sources,
+ dependencies: deps,
+ vala_header: meson.project_name() + '.h',
+ vala_vapi: meson.project_name() + '.vapi',
+ vala_gir: astal_gir,
+ version: meson.project_version(),
+ install: true,
+ install_dir: [true, true, true, true],
+)
+
+import('pkgconfig').generate(
+ description: 'libastal',
+ libraries: libastal,
+ name: meson.project_name(),
+ filebase: meson.project_name() + '-' + api_version,
+ version: meson.project_version(),
+ subdirs: meson.project_name(),
+ requires: 'gio-2.0',
+ install_dir: get_option('libdir') / 'pkgconfig',
+)
+
+if get_option('typelib')
+ custom_target(
+ astal_typelib,
+ command: [
+ find_program('g-ir-compiler'),
+ '--output', '@OUTPUT@',
+ '--shared-library', get_option('prefix') / get_option('libdir') / '@PLAINNAME@',
+ meson.current_build_dir() / astal_gir,
+ ],
+ input: libastal,
+ output: astal_typelib,
+ depends: libastal,
+ install: true,
+ install_dir: get_option('libdir') / 'girepository-1.0',
+ )
+endif
+
+if get_option('cli_client')
+ executable(
+ meson.project_name(),
+ configure_file(
+ input: 'client.vala.in',
+ output: 'client.vala',
+ configuration: {
+ 'VERSION': meson.project_version(),
+ },
+ ),
+ dependencies: deps,
+ install: true,
+ )
+endif
diff --git a/src/process.vala b/src/process.vala
new file mode 100644
index 0000000..6e63264
--- /dev/null
+++ b/src/process.vala
@@ -0,0 +1,126 @@
+namespace Astal {
+public class Process : Object {
+ private void read_stream(DataInputStream stream, bool err) {
+ stream.read_line_utf8_async.begin(Priority.DEFAULT, null, (_, res) => {
+ try {
+ var output = stream.read_line_utf8_async.end(res);
+ if (output != null) {
+ if (err)
+ stdout(output.strip());
+ else
+ stderr(output.strip());
+
+ read_stream(stream, err);
+ }
+ } catch (Error err) {
+ printerr("%s\n", err.message);
+ }
+ });
+ }
+
+ private DataInputStream out_stream;
+ private DataInputStream err_stream;
+ private DataOutputStream in_stream;
+ private Subprocess process;
+ public string[] argv { construct; get; }
+
+ public signal void stdout (string out);
+ public signal void stderr (string err);
+
+ public void kill() {
+ process.force_exit();
+ }
+
+ public void write(string in) throws Error {
+ in_stream.put_string(in);
+ }
+
+ public void write_async(string in) {
+ in_stream.write_all_async.begin(
+ in.data,
+ Priority.DEFAULT, null, (_, res) => {
+ try {
+ in_stream.write_all_async.end(res, null);
+ } catch (Error err) {
+ printerr("%s\n", err.message);
+ }
+ }
+ );
+ }
+
+ public Process.subprocessv(string[] cmd) throws Error {
+ Object(argv: cmd);
+ process = new Subprocess.newv(cmd,
+ SubprocessFlags.STDIN_PIPE |
+ SubprocessFlags.STDERR_PIPE |
+ SubprocessFlags.STDOUT_PIPE
+ );
+ out_stream = new DataInputStream(process.get_stdout_pipe());
+ err_stream = new DataInputStream(process.get_stderr_pipe());
+ in_stream = new DataOutputStream(process.get_stdin_pipe());
+ read_stream(out_stream, true);
+ read_stream(err_stream, false);
+ }
+
+ public static Process subprocess(string cmd) throws Error {
+ string[] argv;
+ Shell.parse_argv(cmd, out argv);
+ return new Process.subprocessv(argv);
+ }
+
+ public static string execv(string[] cmd) throws Error {
+ var process = new Subprocess.newv(
+ cmd,
+ SubprocessFlags.STDERR_PIPE |
+ SubprocessFlags.STDOUT_PIPE
+ );
+
+ string err_str, out_str;
+ process.communicate_utf8(null, null, out out_str, out err_str);
+ var success = process.get_successful();
+ process.dispose();
+ if (success)
+ return out_str.strip();
+ else
+ throw new ProcessError.FAILED(err_str.strip());
+ }
+
+ public static string exec(string cmd) throws Error {
+ string[] argv;
+ Shell.parse_argv(cmd, out argv);
+ return Process.execv(argv);
+ }
+
+ public Process.exec_asyncv(string[] cmd) throws Error {
+ Object(argv: cmd);
+ process = new Subprocess.newv(cmd,
+ SubprocessFlags.STDERR_PIPE |
+ SubprocessFlags.STDOUT_PIPE
+ );
+
+ process.communicate_utf8_async.begin(null, null, (_, res) => {
+ string err_str, out_str;
+ try {
+ process.communicate_utf8_async.end(res, out out_str, out err_str);
+ if (process.get_successful())
+ stdout(out_str.strip());
+ else
+ stderr(err_str.strip());
+ } catch (Error err) {
+ printerr("%s\n", err.message);
+ } finally {
+ dispose();
+ }
+ });
+ }
+
+ public static Process exec_async(string cmd) throws Error {
+ string[] argv;
+ Shell.parse_argv(cmd, out argv);
+ return new Process.exec_asyncv(argv);
+ }
+}
+errordomain ProcessError {
+ FAILED
+}
+}
diff --git a/src/time.vala b/src/time.vala
new file mode 100644
index 0000000..05ffff9
--- /dev/null
+++ b/src/time.vala
@@ -0,0 +1,68 @@
+namespace Astal {
+public class Time : Object {
+ public signal void now ();
+ public signal void cancelled ();
+ private Cancellable cancellable;
+ private uint timeout_id;
+
+ construct {
+ cancellable = new Cancellable();
+ cancellable.cancelled.connect(() => {
+ Source.remove(timeout_id);
+ cancelled();
+ dispose();
+ });
+ }
+
+ private void connect_closure(Closure? closure) {
+ if (closure == null)
+ return;
+
+ now.connect(() => {
+ Value ret = Value(Type.POINTER); // void
+ closure.invoke(ref ret, {});
+ });
+ }
+
+ public Time.interval_prio(uint interval, int prio = Priority.DEFAULT, Closure? fn) {
+ connect_closure(fn);
+ Idle.add_once(() => now());
+ timeout_id = Timeout.add(interval, () => {
+ now();
+ return Source.CONTINUE;
+ }, prio);
+ }
+
+ public Time.timeout_prio(uint timeout, int prio = Priority.DEFAULT, Closure? fn) {
+ connect_closure(fn);
+ timeout_id = Timeout.add(timeout, () => {
+ now();
+ return Source.REMOVE;
+ }, prio);
+ }
+
+ public Time.idle_prio(int prio = Priority.DEFAULT_IDLE, Closure? fn) {
+ connect_closure(fn);
+ timeout_id = Idle.add(() => {
+ now();
+ return Source.REMOVE;
+ }, prio);
+ }
+
+ public static Time interval(uint interval, Closure? fn) {
+ return new Time.interval_prio(interval, Priority.DEFAULT, fn);
+ }
+
+ public static Time timeout(uint timeout, Closure? fn) {
+ return new Time.timeout_prio(timeout, Priority.DEFAULT, fn);
+ }
+
+ public static Time idle(Closure? fn) {
+ return new Time.idle_prio(Priority.DEFAULT_IDLE, fn);
+ }
+
+ public void cancel() {
+ cancellable.cancel();
+ }
+}
+}
diff --git a/src/variable.vala b/src/variable.vala
new file mode 100644
index 0000000..e1d6414
--- /dev/null
+++ b/src/variable.vala
@@ -0,0 +1,190 @@
+namespace Astal {
+public class VariableBase : Object {
+ public signal void changed ();
+ public signal void dropped ();
+ public signal void error (string err);
+
+ // lua-lgi crashes when using its emitting mechanism
+ public void emit_changed() { changed(); }
+ public void emit_dropped() { dropped(); }
+ public void emit_error(string err) { this.error(err); }
+
+ ~VariableBase() {
+ dropped();
+ }
+}
+
+public class Variable : VariableBase {
+ public Value value { owned get; set; }
+
+ private uint poll_id = 0;
+ private Process? watch_proc;
+
+ private uint poll_interval { get; set; default = 1000; }
+ private string[] poll_exec { get; set; }
+ private Closure? poll_transform { get; set; }
+ private Closure? poll_fn { get; set; }
+
+ private Closure? watch_transform { get; set; }
+ private string[] watch_exec { get; set; }
+
+ public Variable(Value init) {
+ Object(value: init);
+ }
+
+ public Variable poll(
+ uint interval,
+ string exec,
+ Closure? transform
+ ) throws Error {
+ string[] argv;
+ Shell.parse_argv(exec, out argv);
+ return pollv(interval, argv, transform);
+ }
+
+ public Variable pollv(
+ uint interval,
+ string[] execv,
+ Closure? transform
+ ) throws Error {
+ if (is_polling())
+ stop_poll();
+
+ poll_interval = interval;
+ poll_exec = execv;
+ poll_transform = transform;
+ poll_fn = null;
+ start_poll();
+ return this;
+ }
+
+ public Variable pollfn(
+ uint interval,
+ Closure fn
+ ) throws Error {
+ if (is_polling())
+ stop_poll();
+
+ poll_interval = interval;
+ poll_fn = fn;
+ poll_exec = null;
+ start_poll();
+ return this;
+ }
+
+ public Variable watch(
+ string exec,
+ Closure? transform
+ ) throws Error {
+ string[] argv;
+ Shell.parse_argv(exec, out argv);
+ return watchv(argv, transform);
+ }
+
+ public Variable watchv(
+ string[] execv,
+ Closure? transform
+ ) throws Error {
+ if (is_watching())
+ stop_watch();
+
+ watch_exec = execv;
+ watch_transform = transform;
+ start_watch();
+ return this;
+ }
+
+ construct {
+ notify["value"].connect(() => changed());
+ dropped.connect(() => {
+ if (is_polling())
+ stop_poll();
+
+ if (is_watching())
+ stop_watch();
+ });
+ }
+
+ private void set_closure(string val, Closure? transform) {
+ if (transform != null) {
+ var str = Value(typeof(string));
+ str.set_string(val);
+
+ var ret_val = Value(this.value.type());
+ transform.invoke(ref ret_val, { str, this.value });
+ this.value = ret_val;
+ }
+ else {
+ if (this.value.type() == Type.STRING && this.value.get_string() == val)
+ return;
+
+ var str = Value(typeof(string));
+ str.set_string(val);
+ this.value = str;
+ }
+ }
+
+ private void set_fn() {
+ var ret_val = Value(this.value.type());
+ poll_fn.invoke(ref ret_val, { this.value });
+ this.value = ret_val;
+ }
+
+ public void start_poll() throws Error {
+ return_if_fail(poll_id == 0);
+
+ if (poll_fn != null) {
+ set_fn();
+ poll_id = Timeout.add(poll_interval, () => {
+ set_fn();
+ return Source.CONTINUE;
+ }, Priority.DEFAULT);
+ }
+ if (poll_exec != null) {
+ var proc = new Process.exec_asyncv(poll_exec);
+ proc.stdout.connect((str) => set_closure(str, poll_transform));
+ proc.stderr.connect((str) => this.error(str));
+ poll_id = Timeout.add(poll_interval, () => {
+ try {
+ proc = new Process.exec_asyncv(poll_exec);
+ proc.stdout.connect((str) => set_closure(str, poll_transform));
+ proc.stderr.connect((str) => this.error(str));
+ return Source.CONTINUE;
+ } catch (Error err) {
+ printerr("%s\n", err.message);
+ poll_id = 0;
+ return Source.REMOVE;
+ }
+ }, Priority.DEFAULT);
+ }
+ }
+
+ public void start_watch() throws Error {
+ return_if_fail(watch_proc == null);
+ return_if_fail(watch_exec != null);
+
+ watch_proc = new Process.subprocessv(watch_exec);
+ watch_proc.stdout.connect((str) => set_closure(str, watch_transform));
+ watch_proc.stderr.connect((str) => this.error(str));
+ }
+
+ public void stop_poll() {
+ return_if_fail(poll_id != 0);
+ Source.remove(poll_id);
+ poll_id = 0;
+ }
+
+ public void stop_watch() {
+ return_if_fail(watch_proc != null);
+ watch_proc.kill();
+ watch_proc = null;
+ }
+
+ public bool is_polling() { return poll_id > 0; }
+ public bool is_watching() { return watch_proc != null; }
+
+ ~Variable() {
+ dropped();
+ }
+}
+}
diff --git a/src/widget/box.vala b/src/widget/box.vala
new file mode 100644
index 0000000..482948d
--- /dev/null
+++ b/src/widget/box.vala
@@ -0,0 +1,60 @@
+namespace Astal {
+public class Box : Gtk.Box {
+ public bool vertical {
+ get { return orientation == Gtk.Orientation.VERTICAL; }
+ set { orientation = value ? Gtk.Orientation.VERTICAL : Gtk.Orientation.HORIZONTAL; }
+ }
+
+ public List<weak Gtk.Widget> children {
+ set { _set_children(value); }
+ owned get { return get_children(); }
+ }
+
+ public new Gtk.Widget child {
+ owned get { return _get_child(); }
+ set { _set_child(value); }
+ }
+
+ construct {
+ notify["orientation"].connect(() => {
+ notify_property("vertical");
+ });
+ }
+
+ private void _set_child(Gtk.Widget child) {
+ var list = new List<weak Gtk.Widget>();
+ list.append(child);
+ _set_children(list);
+ }
+
+ private Gtk.Widget? _get_child() {
+ foreach(var child in get_children())
+ return child;
+
+ return null;
+ }
+
+ private void _set_children(List<weak Gtk.Widget> arr) {
+ foreach(var child in get_children())
+ remove(child);
+
+ foreach(var child in arr)
+ add(child);
+ }
+
+ public Box(bool vertical, List<weak Gtk.Widget> children) {
+ this.vertical = vertical;
+ _set_children(children);
+ }
+
+ public Box.newh(List<weak Gtk.Widget> children) {
+ this.vertical = false;
+ _set_children(children);
+ }
+
+ public Box.newv(List<weak Gtk.Widget> children) {
+ this.vertical = true;
+ _set_children(children);
+ }
+}
+}
diff --git a/src/widget/button.vala b/src/widget/button.vala
new file mode 100644
index 0000000..601733f
--- /dev/null
+++ b/src/widget/button.vala
@@ -0,0 +1,35 @@
+namespace Astal {
+public class Button : Gtk.Button {
+ public signal void hover (Gdk.EventCrossing event);
+ public signal void hover_lost (Gdk.EventCrossing event);
+ public signal void click (Gdk.EventButton event);
+ public signal void click_release (Gdk.EventButton event);
+
+ construct {
+ add_events(Gdk.EventMask.SCROLL_MASK);
+ add_events(Gdk.EventMask.SMOOTH_SCROLL_MASK);
+
+ enter_notify_event.connect((self, event) => {
+ if (event.window == self.get_window() &&
+ event.detail != Gdk.NotifyType.INFERIOR) {
+ hover(event);
+ }
+ });
+
+ leave_notify_event.connect((self, event) => {
+ if (event.window == self.get_window() &&
+ event.detail != Gdk.NotifyType.INFERIOR) {
+ hover_lost(event);
+ }
+ });
+
+ button_press_event.connect((event) => {
+ click(event);
+ });
+
+ button_release_event.connect((event) => {
+ click_release(event);
+ });
+ }
+}
+}
diff --git a/src/widget/centerbox.vala b/src/widget/centerbox.vala
new file mode 100644
index 0000000..5f41600
--- /dev/null
+++ b/src/widget/centerbox.vala
@@ -0,0 +1,35 @@
+namespace Astal {
+public class CenterBox : Gtk.Box {
+ public bool vertical {
+ get { return orientation == Gtk.Orientation.VERTICAL; }
+ set { orientation = value ? Gtk.Orientation.VERTICAL : Gtk.Orientation.HORIZONTAL; }
+ }
+
+ private Gtk.Widget _start_widget;
+ public Gtk.Widget start_widget {
+ get { return _start_widget; }
+ set {
+ if (_start_widget != null)
+ remove(_start_widget);
+
+ pack_start(value, true, true, 0);
+ }
+ }
+
+ private Gtk.Widget _end_widget;
+ public Gtk.Widget end_widget {
+ get { return _end_widget; }
+ set {
+ if (_end_widget != null)
+ remove(_end_widget);
+
+ pack_end(value, true, true, 0);
+ }
+ }
+
+ public Gtk.Widget center_widget {
+ get { return get_center_widget(); }
+ set { set_center_widget(value); }
+ }
+}
+}
diff --git a/src/widget/circularprogress.vala b/src/widget/circularprogress.vala
new file mode 100644
index 0000000..e96c4de
--- /dev/null
+++ b/src/widget/circularprogress.vala
@@ -0,0 +1,174 @@
+namespace Astal {
+public class CircularProgress : Gtk.Bin {
+ public new Gtk.Widget child { get; set; }
+ public double start_at { get; set; }
+ public double end_at { get; set; }
+ public double value { get; set; }
+ public bool inverted { get; set; }
+ public bool rounded { get; set; }
+
+ construct {
+ notify["start-at"].connect(queue_draw);
+ notify["end-at"].connect(queue_draw);
+ notify["value"].connect(queue_draw);
+ notify["inverted"].connect(queue_draw);
+ notify["rounded"].connect(queue_draw);
+ notify["child"].connect(queue_draw);
+ }
+
+ static construct {
+ set_css_name("circular-progress");
+ }
+
+
+ public new void get_preferred_height(out int minh, out int nath) {
+ var val = get_style_context().get_property("min-height", Gtk.StateFlags.NORMAL);
+ if (val.get_int() <= 0) {
+ minh = 40;
+ nath = 40;
+ }
+
+ minh = val.get_int();
+ nath = val.get_int();
+ }
+
+ public new void get_preferred_width(out int minw, out int natw) {
+ var val = get_style_context().get_property("min-width", Gtk.StateFlags.NORMAL);
+ if (val.get_int() <= 0) {
+ minw = 40;
+ natw = 40;
+ }
+
+ minw = val.get_int();
+ natw = val.get_int();
+ }
+
+ private double _to_radian(double percentage) {
+ percentage = Math.floor(percentage * 100);
+ return (percentage / 100) * (2 * Math.PI);
+ }
+
+ private bool _is_full_circle(double start, double end, double epsilon = 1e-10) {
+ // Ensure that start and end are between 0 and 1
+ start = (start % 1 + 1) % 1;
+ end = (end % 1 + 1) % 1;
+
+ // Check if the difference between start and end is close to 1
+ return Math.fabs(start - end) <= epsilon;
+ }
+
+ private double _map_arc_value_to_range(double start, double end, double value) {
+ // Ensure that start and end are between 0 and 1
+ start = (start % 1 + 1) % 1;
+ end = (end % 1 + 1) % 1;
+
+ // Calculate the length of the arc
+ var arcLength = end - start;
+ if (arcLength < 0)
+ arcLength += 1; // Adjust for circular representation
+
+ // Calculate the position on the arc based on the percentage value
+ var position = start + (arcLength * value);
+
+ // Ensure the position is between 0 and 1
+ position = (position % 1 + 1) % 1;
+
+ return position;
+ }
+
+ private double _min(double[] arr) {
+ double min = arr[0];
+ foreach(var i in arr)
+ if (min > i) min = i;
+ return min;
+ }
+
+ private double _max(double[] arr) {
+ double max = arr[0];
+ foreach(var i in arr)
+ if (max < i) max = i;
+ return max;
+ }
+
+ public new bool draw(Cairo.Context cr) {
+ Gtk.Allocation allocation;
+ get_allocation(out allocation);
+
+ var styles = get_style_context();
+ var width = allocation.width;
+ var height = allocation.height;
+ var thickness = styles.get_property("font-size", Gtk.StateFlags.NORMAL).get_double();
+ var margin = styles.get_margin(Gtk.StateFlags.NORMAL);
+ var fg = styles.get_color(Gtk.StateFlags.NORMAL);
+ var bg = styles.get_background_color(Gtk.StateFlags.NORMAL);
+
+ var bg_stroke = thickness + _min({margin.bottom, margin.top, margin.left, margin.right});
+ var fg_stroke = thickness;
+ var radius = _min({width, height}) / 2.0 - _max({bg_stroke, fg_stroke}) / 2.0;
+ var center_x = width / 2;
+ var center_y = height / 2;
+
+ var start_background = _to_radian(this.start_at);
+ var end_background = _to_radian(this.end_at);
+ var ranged_value = this.value + this.start_at;
+
+ var is_circle = _is_full_circle(this.start_at, this.end_at);
+
+ if (is_circle) {
+ // Redefine endDraw in radius to create an accurate full circle
+ end_background = start_background + 2 * Math.PI;
+ } else {
+ // Range the value for the arc shape
+ ranged_value = _map_arc_value_to_range(
+ this.start_at,
+ this.end_at,
+ this.value
+ );
+ }
+
+ var to = _to_radian(ranged_value);
+ double start_progress, end_progress;
+
+ if (this.inverted) {
+ start_progress = (2 * Math.PI - to) - start_background;
+ end_progress = (2 * Math.PI - start_background) - start_background;
+ } else {
+ start_progress = start_background;
+ end_progress = to;
+ }
+
+ // Draw background
+ cr.set_source_rgba(bg.red, bg.green, bg.blue, bg.alpha);
+ cr.arc(center_x, center_y, radius, start_background, end_background);
+
+ cr.set_line_width(bg_stroke);
+ cr.stroke();
+
+ // Draw progress
+ cr.set_source_rgba(fg.red, fg.green, fg.blue, fg.alpha);
+ cr.arc(center_x, center_y, radius, start_progress, end_progress);
+ cr.set_line_width(fg_stroke);
+ cr.stroke();
+
+ // Draw rounded ends
+ if (this.rounded) {
+ var start_x = center_x + Math.cos(start_background);
+ var start_y = center_y + Math.cos(start_background);
+ var end_x = center_x + Math.cos(to) * radius;
+ var end_y = center_y + Math.cos(to) * radius;
+ cr.set_line_width(0);
+ cr.arc(start_x, start_y, fg_stroke / 2, 0, 0 - 0.01);
+ cr.fill();
+ cr.arc(end_x, end_y, fg_stroke / 2, 0, 0 - 0.01);
+ cr.fill();
+ }
+
+ if (this.child != null) {
+ this.child.size_allocate(allocation);
+ this.propagate_draw(this.child, cr);
+ }
+
+ return true;
+ }
+}
+}
diff --git a/src/widget/eventbox.vala b/src/widget/eventbox.vala
new file mode 100644
index 0000000..de04a32
--- /dev/null
+++ b/src/widget/eventbox.vala
@@ -0,0 +1,39 @@
+namespace Astal {
+public class EventBox : Gtk.EventBox {
+ public signal void hover (Gdk.EventCrossing event);
+ public signal void hover_lost (Gdk.EventCrossing event);
+ public signal void click (Gdk.EventButton event);
+ public signal void click_release (Gdk.EventButton event);
+
+ construct {
+ add_events(Gdk.EventMask.SCROLL_MASK);
+ add_events(Gdk.EventMask.SMOOTH_SCROLL_MASK);
+
+ enter_notify_event.connect((self, event) => {
+ if (event.window == self.get_window() &&
+ event.detail != Gdk.NotifyType.INFERIOR) {
+ this.set_state_flags(Gtk.StateFlags.PRELIGHT, false);
+ hover(event);
+ }
+ });
+
+ leave_notify_event.connect((self, event) => {
+ if (event.window == self.get_window() &&
+ event.detail != Gdk.NotifyType.INFERIOR) {
+ this.unset_state_flags(Gtk.StateFlags.PRELIGHT);
+ hover_lost(event);
+ }
+ });
+
+ button_press_event.connect((event) => {
+ // TODO: abstract event for easier use
+ click(event);
+ });
+
+ button_release_event.connect((event) => {
+ // TODO: abstract event for easier use
+ click_release(event);
+ });
+ }
+}
+}
diff --git a/src/widget/icon.vala b/src/widget/icon.vala
new file mode 100644
index 0000000..fc493da
--- /dev/null
+++ b/src/widget/icon.vala
@@ -0,0 +1,87 @@
+namespace Astal {
+public Gtk.IconInfo? lookup_icon(string icon) {
+ var theme = Gtk.IconTheme.get_default();
+ return theme.lookup_icon(icon, 16, Gtk.IconLookupFlags.USE_BUILTIN);
+}
+
+public class Icon : Gtk.Image {
+ private IconType type = IconType.NAMED;
+ private double size { get; set; default = 14; }
+
+ public new Gdk.Pixbuf pixbuf { get; set; }
+ public string icon { get; set; default = ""; }
+
+ private void display_icon() {
+ switch(type) {
+ case IconType.NAMED:
+ icon_name = icon;
+ pixel_size = (int)size;
+ break;
+ case IconType.FILE:
+ try {
+ var pb = new Gdk.Pixbuf.from_file_at_size(
+ icon,
+ (int)size * scale_factor,
+ (int)size * scale_factor
+ );
+ var cs = Gdk.cairo_surface_create_from_pixbuf(pb, 0, this.get_window());
+ set_from_surface(cs);
+ } catch (Error err) {
+ printerr(err.message);
+ }
+ break;
+ case IconType.PIXBUF:
+ var pb_scaled = pixbuf.scale_simple(
+ (int)size * scale_factor,
+ (int)size * scale_factor,
+ Gdk.InterpType.BILINEAR
+ );
+ if (pb_scaled != null) {
+ var cs = Gdk.cairo_surface_create_from_pixbuf(pb_scaled, 0, this.get_window());
+ set_from_surface(cs);
+ }
+ break;
+ }
+ }
+
+ construct {
+ notify["icon"].connect(() => {
+ if(FileUtils.test(icon, GLib.FileTest.EXISTS))
+ type = IconType.FILE;
+ else if (lookup_icon(icon) != null)
+ type = IconType.NAMED;
+ else {
+ type = IconType.NAMED;
+ warning("cannot assign %s as icon, "+
+ "it is not a file nor a named icon", icon);
+ }
+ display_icon();
+ });
+
+ notify["pixbuf"].connect(() => {
+ type = IconType.PIXBUF;
+ display_icon();
+ });
+
+ size_allocate.connect(() => {
+ size = get_style_context()
+ .get_property("font-size", Gtk.StateFlags.NORMAL).get_double();
+
+ display_icon();
+ });
+
+ get_style_context().changed.connect(() => {
+ size = get_style_context()
+ .get_property("font-size", Gtk.StateFlags.NORMAL).get_double();
+
+ display_icon();
+ });
+ }
+}
+
+private enum IconType {
+ NAMED,
+ FILE,
+ PIXBUF,
+}
+}
diff --git a/src/widget/widget.vala b/src/widget/widget.vala
new file mode 100644
index 0000000..de34c6d
--- /dev/null
+++ b/src/widget/widget.vala
@@ -0,0 +1,132 @@
+namespace Astal {
+private class Css {
+ private static HashTable<Gtk.Widget, Gtk.CssProvider> _providers;
+ public static HashTable<Gtk.Widget, Gtk.CssProvider> providers {
+ get {
+ if (_providers == null) {
+ _providers = new HashTable<Gtk.Widget, Gtk.CssProvider>(
+ (w) => (uint)w,
+ (a, b) => a == b);
+ }
+
+ return _providers;
+ }
+ }
+}
+
+private void remove_provider(Gtk.Widget widget) {
+ var providers = Css.providers;
+
+ if (providers.contains(widget)) {
+ var p = providers.get(widget);
+ widget.get_style_context().remove_provider(p);
+ providers.remove(widget);
+ p.dispose();
+ }
+}
+
+public void widget_set_css(Gtk.Widget widget, string css) {
+ var providers = Css.providers;
+
+ if (providers.contains(widget)) {
+ remove_provider(widget);
+ } else {
+ widget.destroy.connect(() => {
+ remove_provider(widget);
+ });
+ }
+
+ var style = !css.contains("{") || !css.contains("}")
+ ? "* { ".concat(css, "}") : css;
+
+ var p = new Gtk.CssProvider();
+ widget.get_style_context()
+ .add_provider(p, Gtk.STYLE_PROVIDER_PRIORITY_USER);
+
+ try {
+ p.load_from_data(style, style.length);
+ providers.set(widget, p);
+ } catch (Error err) {
+ warning(err.message);
+ }
+}
+
+public string widget_get_css(Gtk.Widget widget) {
+ var providers = Css.providers;
+
+ if (providers.contains(widget))
+ return providers.get(widget).to_string();
+
+ return "";
+}
+
+public void widget_set_class_names(Gtk.Widget widget, string[] class_names) {
+ foreach (var name in widget_get_class_names(widget))
+ widget_toggle_class_name(widget, name, false);
+
+ foreach (var name in class_names)
+ widget_toggle_class_name(widget, name, true);
+}
+
+public List<weak string> widget_get_class_names(Gtk.Widget widget) {
+ return widget.get_style_context().list_classes();
+}
+
+public void widget_toggle_class_name(Gtk.Widget widget,
+ string class_name,
+ bool condition) {
+ var c = widget.get_style_context();
+ if (condition)
+ c.add_class(class_name);
+ else
+ c.remove_class(class_name);
+}
+
+private class Cursor {
+ private static HashTable<Gtk.Widget, string> _cursors;
+ public static HashTable<Gtk.Widget, string> cursors {
+ get {
+ if (_cursors == null) {
+ _cursors = new HashTable<Gtk.Widget, string>(
+ (w) => (uint)w,
+ (a, b) => a == b);
+ }
+ return _cursors;
+ }
+ }
+}
+
+private void widget_setup_cursor(Gtk.Widget widget) {
+ widget.add_events(Gdk.EventMask.ENTER_NOTIFY_MASK);
+ widget.add_events(Gdk.EventMask.LEAVE_NOTIFY_MASK);
+ widget.enter_notify_event.connect(() => {
+ widget.get_window().set_cursor(
+ new Gdk.Cursor.from_name(
+ Gdk.Display.get_default(),
+ Cursor.cursors.get(widget)));
+ return false;
+ });
+ widget.leave_notify_event.connect(() => {
+ widget.get_window().set_cursor(
+ new Gdk.Cursor.from_name(
+ Gdk.Display.get_default(),
+ "default"));
+ return false;
+ });
+ widget.destroy.connect(() => {
+ if (Cursor.cursors.contains(widget))
+ Cursor.cursors.remove(widget);
+ });
+}
+
+public void widget_set_cursor(Gtk.Widget widget, string cursor) {
+ if (!Cursor.cursors.contains(widget))
+ widget_setup_cursor(widget);
+
+ Cursor.cursors.set(widget, cursor);
+}
+
+public string widget_get_cursor(Gtk.Widget widget) {
+ return Cursor.cursors.get(widget);
+}
+}
diff --git a/src/widget/window.vala b/src/widget/window.vala
new file mode 100644
index 0000000..1faaf7b
--- /dev/null
+++ b/src/widget/window.vala
@@ -0,0 +1,136 @@
+using GtkLayerShell;
+
+namespace Astal {
+public enum WindowAnchor {
+ NONE = 0,
+ TOP = 1,
+ RIGHT = 2,
+ LEFT = 4,
+ BOTTOM = 8,
+}
+
+public enum Exclusivity {
+ NORMAL,
+ EXCLUSIVE,
+ IGNORE,
+}
+
+public enum Layer {
+ TOP = GtkLayerShell.Layer.TOP,
+ OVERLAY = GtkLayerShell.Layer.OVERLAY,
+ BOTTOM = GtkLayerShell.Layer.BOTTOM,
+ BACKGROUND = GtkLayerShell.Layer.BACKGROUND,
+}
+
+public enum Keymode {
+ NONE = GtkLayerShell.KeyboardMode.NONE,
+ ON_DEMAND = GtkLayerShell.KeyboardMode.ON_DEMAND,
+ EXCLUSIVE = GtkLayerShell.KeyboardMode.EXCLUSIVE,
+}
+
+public class Window : Gtk.Window {
+ construct {
+ height_request = 1;
+ width_request = 1;
+ init_for_window(this);
+ set_namespace(this, name);
+ notify["name"].connect(() => set_namespace(this, name));
+ }
+
+ public int anchor {
+ set {
+ set_anchor(this, Edge.TOP, WindowAnchor.TOP in value);
+ set_anchor(this, Edge.BOTTOM, WindowAnchor.BOTTOM in value);
+ set_anchor(this, Edge.LEFT, WindowAnchor.LEFT in value);
+ set_anchor(this, Edge.RIGHT, WindowAnchor.RIGHT in value);
+ }
+ get {
+ var a = WindowAnchor.NONE;
+ if (get_anchor(this, Edge.TOP))
+ a = a | WindowAnchor.TOP;
+
+ if (get_anchor(this, Edge.RIGHT))
+ a = a | WindowAnchor.RIGHT;
+
+ if (get_anchor(this, Edge.LEFT))
+ a = a | WindowAnchor.LEFT;
+
+ if (get_anchor(this, Edge.BOTTOM))
+ a = a | WindowAnchor.BOTTOM;
+
+ return a;
+ }
+ }
+
+ public Exclusivity exclusivity {
+ set {
+ switch (value) {
+ case Exclusivity.NORMAL:
+ set_exclusive_zone(this, 0);
+ break;
+ case Exclusivity.EXCLUSIVE:
+ auto_exclusive_zone_enable (this);
+ break;
+ case Exclusivity.IGNORE:
+ set_exclusive_zone(this, -1);
+ break;
+ }
+ }
+ get {
+ if (auto_exclusive_zone_is_enabled (this))
+ return Exclusivity.EXCLUSIVE;
+
+ if (get_exclusive_zone(this) == -1)
+ return Exclusivity.IGNORE;
+
+ return Exclusivity.NORMAL;
+ }
+ }
+
+ public Layer layer {
+ get { return (Layer)get_layer(this); }
+ set { set_layer(this, (GtkLayerShell.Layer)value); }
+ }
+
+ public Keymode keymode {
+ set { set_keyboard_mode(this, (GtkLayerShell.KeyboardMode)value); }
+ get { return (Keymode)get_keyboard_mode(this); }
+ }
+
+ public Gdk.Monitor gdkmonitor {
+ set { set_monitor (this, value); }
+ get { return get_monitor(this); }
+ }
+
+ /**
+ * CAUTION: the id might not be the same mapped by the compositor
+ * to reset and let the compositor map it pass a negative number
+ */
+ public int monitor {
+ set {
+ if (value < 0)
+ set_monitor(this, (Gdk.Monitor)null);
+
+ var m = Gdk.Display.get_default().get_monitor(value);
+ set_monitor(this, m);
+ }
+ get {
+ var m = get_monitor(this);
+ var d = Gdk.Display.get_default();
+ for (var i = 0; i < d.get_n_monitors(); ++i) {
+ if (m == d.get_monitor(i))
+ return i;
+ }
+
+ return -1;
+ }
+ }
+}
+
+/**
+ * CAUTION: the id might not be the same mapped by the compositor
+ */
+public uint get_num_monitors() {
+ return Gdk.Display.get_default().get_n_monitors();
+}
+}
diff --git a/version b/version
new file mode 100644
index 0000000..6e8bf73
--- /dev/null
+++ b/version
@@ -0,0 +1 @@
+0.1.0