10 Commits

10 changed files with 1185 additions and 103 deletions

22
.vscode/launch.json vendored
View File

@@ -5,16 +5,30 @@
"version": "0.2.0",
"configurations": [
{
"type": "pwa-node",
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": [
"<node_internals>/**"
],
"env": {
"JOB": "jobs/example.json5"
"GPGPASS": "${input:gpgpass}"
},
"program": "${workspaceFolder}/index.js"
"program": "${workspaceFolder}/bin/artix-metro.mjs",
"args": [
"--job",
"jobs/kde-01.json5"
],
"outFiles": [
"${workspaceFolder}/distribution/*"
]
}
]
],
"inputs": [
{
"id": "gpgpass",
"type": "promptString",
"description": "Enter your GPG password"
}
]
}

99
completion/bash Normal file
View File

@@ -0,0 +1,99 @@
#/usr/bin/env bash
LIBDIR=${LIBDIR:-'/usr/share/artools/lib'}
_artixpkg_pkgbase() {
source "${LIBDIR}"/pkg/util.sh
ls -1 "${TREE_DIR_ARTIX}" | tr '\n' ' '
}
_artix_metro_completion() {
local cur prev comps repos autorepos comp_cword_exflag
source "${LIBDIR}"/pkg/db/db.sh 2>/dev/null
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
for ((i = COMP_CWORD - 1; i >= 0; i--)); do
if [[ ${COMP_WORDS[i]} != -* ]]; then
last_non_flag_word="${COMP_WORDS[i]}"
break
fi
done
comps=""
comp_cword_exflag=0
comp_cword_all=0
for ((i = 0; i < ${#COMP_WORDS[@]} - 1; i++)); do
word="${COMP_WORDS[i]}"
comps_all+=" $word"
((comp_cword_all++))
if [[ $word != -* ]]; then
comps+=" $word"
((comp_cword_exflag++))
fi
done
comps="${comps:1}"
repos=""
for word in "${ARTIX_DB[@]}"; do
if [[ $word != -* ]]; then
repos+=" $word"
fi
done
repos="${repos:1}"
autorepos=""
for word in "${ARTIX_DB_MAP[@]}"; do
if [[ $word != -* ]]; then
autorepos+=" $word"
fi
done
autorepos="${autorepos:1}"
case "${prev}" in
"--token")
# this flag expects a parameter
COMPREPLY=()
;;
"-j"|"--job")
compopt -o filenames
COMPREPLY=( $(compgen -f -- "$cur") )
;;
"--workspace")
COMPREPLY=( $(compgen -d -- "$cur") )
;;
"--start")
COMPREPLY=($(compgen -W "$(_artixpkg_pkgbase)" -- ${cur}))
;;
*)
local metroCommon="-h --help --start --token --workspace --increment "
case "${comps}" in
"artix-metro add"*)
case "${comp_cword_exflag}" in
2)
COMPREPLY=($(compgen -W "$metroCommon $autorepos $repos" -- ${cur}))
;;
*)
COMPREPLY=($(compgen -W "$metroCommon $(_artixpkg_pkgbase)" -- ${cur}))
;;
esac
;;
"artix-metro move"*)
case "${comp_cword_exflag}" in
2|3)
COMPREPLY=($(compgen -W "$metroCommon $autorepos $repos" -- ${cur}))
;;
*)
COMPREPLY=($(compgen -W "$metroCommon $(_artixpkg_pkgbase)" -- ${cur}))
;;
esac
;;
*)
COMPREPLY=($(compgen -W "$metroCommon -j --job add move" -- ${cur}))
;;
esac
;;
esac
}
complete -F _artix_metro_completion artix-metro

61
completion/zsh Normal file
View File

@@ -0,0 +1,61 @@
# Load necessary library files
LIBDIR=${LIBDIR:-'/usr/share/artools/lib'}
_artix_metro_completion() {
local -a metroCommon repos autorepos pkgbase
local curcontext="$curcontext" state
# Load external configurations
source "${LIBDIR}/pkg/db/db.sh" 2>/dev/null
# Common options
metroCommon=("-h" "--help" "--start" "--token" "--workspace" "--increment" "-j" "--job")
# Populate variables
repos=("${(s: :)ARTIX_DB}")
autorepos=("${(s: :)ARTIX_DB_MAP}")
pkgbase=("${(s: :)$(artix-metro --completion pkgbase)}")
# Handle command and argument contexts
_arguments -C \
'--token[Provide a token]: ' \
'-j[Specify a job]: :_files' \
'--job[Specify a job]: :_files' \
'--workspace[Specify a workspace]: :_files -/' \
'--start[Start a process]:pkgbase:(${pkgbase})' \
'1:command:(${metroCommon} add move)' \
'2:repo:(${metroCommon} ${autorepos} ${repos})' \
'*:pkgbase:->pkgbase'
# Contextual argument handling
case $state in
pkgbase)
case $words[2] in
add)
if (( CURRENT == 3 )); then
# First argument after "add" is a repo
_values "repo" "${metroCommon[@]}" "${autorepos[@]}" "${repos[@]}"
else
# Remaining arguments are pkgbase
_values "pkgbase" "${pkgbase[@]}"
fi
;;
move)
if (( CURRENT == 3 )); then
# First repo for "move"
_values "repo" "${metroCommon[@]}" "${autorepos[@]}" "${repos[@]}"
elif (( CURRENT == 4 )); then
# Second repo for "move"
_values "repo" "${metroCommon[@]}" "${autorepos[@]}" "${repos[@]}"
else
# Remaining arguments are pkgbase
_values "pkgbase" "${pkgbase[@]}"
fi
;;
esac
;;
esac
}
# Register the completion function for artix-metro
compdef _artix_metro_completion artix-metro

838
package-lock.json generated
View File

@@ -1,18 +1,19 @@
{
"name": "artix-metro",
"version": "3.0.0",
"version": "3.1.4",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "artix-metro",
"version": "3.0.0",
"version": "3.1.4",
"license": "MIT",
"dependencies": {
"artix-checkupdates": "1.0.1",
"artix-checkupdates": "1.0.2",
"cli-color": "2.0.4",
"glob": "11.0.2",
"json5": "2.2.3",
"ky": "1.7.4"
"ky": "1.8.1"
},
"bin": {
"artix-metro": "bin/artix-metro.mjs"
@@ -20,8 +21,25 @@
"devDependencies": {
"@sindresorhus/tsconfig": "7.0.0",
"@types/cli-color": "2.0.6",
"@types/node": "22.10.7",
"typescript": "5.7.3"
"@types/node": "22.15.14",
"typescript": "5.8.3"
}
},
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
"license": "ISC",
"dependencies": {
"string-width": "^5.1.2",
"string-width-cjs": "npm:string-width@^4.2.0",
"strip-ansi": "^7.0.1",
"strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
"wrap-ansi": "^8.1.0",
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@sindresorhus/tsconfig": {
@@ -45,21 +63,60 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "22.10.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.7.tgz",
"integrity": "sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==",
"version": "22.15.14",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.14.tgz",
"integrity": "sha512-BL1eyu/XWsFGTtDWOYULQEs4KR0qdtYfCxYAUYRoB7JP7h9ETYLgQTww6kH8Sj2C0pFGgrpM0XKv6/kbIzYJ1g==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.20.0"
"undici-types": "~6.21.0"
}
},
"node_modules/ansi-regex": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/ansi-styles": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/artix-checkupdates": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/artix-checkupdates/-/artix-checkupdates-1.0.1.tgz",
"integrity": "sha512-C0AxI3SfoUUekYg3ft/y4+tRjIe8uuDLvBQRSmkfNsRuBLNlEHaxhY/93JB6G4AGXp5RFLZYDnbgjakgbTLhkw==",
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/artix-checkupdates/-/artix-checkupdates-1.0.2.tgz",
"integrity": "sha512-VTLeMVysGeZ3QiLtEyWoVM8D57YyeYhYQoL3vcW9b0dZE+zhE4di80PYEFGeQzIBcCStcBFnI1uSBoAEHMVHAQ==",
"license": "MIT"
},
"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==",
"license": "MIT"
},
"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==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/cli-color": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.4.tgz",
@@ -75,6 +132,38 @@
"node": ">=0.10"
}
},
"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==",
"license": "MIT",
"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==",
"license": "MIT"
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"license": "MIT",
"dependencies": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
"which": "^2.0.1"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/d": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
@@ -84,6 +173,18 @@
"type": "^1.0.1"
}
},
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
"license": "MIT"
},
"node_modules/emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
"license": "MIT"
},
"node_modules/es5-ext": {
"version": "0.10.64",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz",
@@ -170,11 +271,80 @@
"resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz",
"integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ=="
},
"node_modules/foreground-child": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
"integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
"license": "ISC",
"dependencies": {
"cross-spawn": "^7.0.0",
"signal-exit": "^4.0.1"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/glob": {
"version": "11.0.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.2.tgz",
"integrity": "sha512-YT7U7Vye+t5fZ/QMkBFrTJ7ZQxInIUjwyAjVj84CYXqgBdv30MFUPGnBR6sQaVq6Is15wYJUsnzTuWaGRBhBAQ==",
"license": "ISC",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^4.0.1",
"minimatch": "^10.0.0",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^2.0.0"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"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==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/is-promise": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz",
"integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ=="
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"license": "ISC"
},
"node_modules/jackspeak": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz",
"integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==",
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/json5": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
@@ -187,9 +357,9 @@
}
},
"node_modules/ky": {
"version": "1.7.4",
"resolved": "https://registry.npmjs.org/ky/-/ky-1.7.4.tgz",
"integrity": "sha512-zYEr/gh7uLW2l4su11bmQ2M9xLgQLjyvx58UyNM/6nuqyWFHPX5ktMjvpev3F8QWdjSsHUpnWew4PBCswBNuMQ==",
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/ky/-/ky-1.8.1.tgz",
"integrity": "sha512-7Bp3TpsE+L+TARSnnDpk3xg8Idi8RwSLdj6CMbNWoOARIrGrbuLGusV0dYwbZOm4bB3jHNxSw8Wk/ByDqJEnDw==",
"license": "MIT",
"engines": {
"node": ">=18"
@@ -198,6 +368,15 @@
"url": "https://github.com/sindresorhus/ky?sponsor=1"
}
},
"node_modules/lru-cache": {
"version": "11.0.2",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz",
"integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==",
"license": "ISC",
"engines": {
"node": "20 || >=22"
}
},
"node_modules/lru-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz",
@@ -221,11 +400,195 @@
"timers-ext": "^0.1.7"
}
},
"node_modules/minimatch": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
"integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/next-tick": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
"integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
},
"node_modules/package-json-from-dist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
"license": "BlueOak-1.0.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==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/path-scurry": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz",
"integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==",
"license": "BlueOak-1.0.0",
"dependencies": {
"lru-cache": "^11.0.0",
"minipass": "^7.1.2"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"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==",
"license": "MIT",
"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==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
"license": "ISC",
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"license": "MIT",
"dependencies": {
"eastasianwidth": "^0.2.0",
"emoji-regex": "^9.2.2",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/string-width-cjs": {
"name": "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==",
"license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/string-width-cjs/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==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/string-width-cjs/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==",
"license": "MIT"
},
"node_modules/string-width-cjs/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==",
"license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-ansi": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"license": "MIT",
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/strip-ansi-cjs": {
"name": "strip-ansi",
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-ansi-cjs/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==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/timers-ext": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz",
@@ -241,9 +604,9 @@
"integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg=="
},
"node_modules/typescript": {
"version": "5.7.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
"integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -255,14 +618,133 @@
}
},
"node_modules/undici-types": {
"version": "6.20.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"dev": true,
"license": "MIT"
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"license": "ISC",
"dependencies": {
"isexe": "^2.0.0"
},
"bin": {
"node-which": "bin/node-which"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/wrap-ansi": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
"license": "MIT",
"dependencies": {
"ansi-styles": "^6.1.0",
"string-width": "^5.0.1",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrap-ansi-cjs": {
"name": "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==",
"license": "MIT",
"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/wrap-ansi-cjs/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==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/wrap-ansi-cjs/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==",
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/wrap-ansi-cjs/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==",
"license": "MIT"
},
"node_modules/wrap-ansi-cjs/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==",
"license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/wrap-ansi-cjs/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==",
"license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
}
},
"dependencies": {
"@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
"requires": {
"string-width": "^5.1.2",
"string-width-cjs": "npm:string-width@^4.2.0",
"strip-ansi": "^7.0.1",
"strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
"wrap-ansi": "^8.1.0",
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
}
},
"@sindresorhus/tsconfig": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/tsconfig/-/tsconfig-7.0.0.tgz",
@@ -276,18 +758,41 @@
"dev": true
},
"@types/node": {
"version": "22.10.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.7.tgz",
"integrity": "sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==",
"version": "22.15.14",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.14.tgz",
"integrity": "sha512-BL1eyu/XWsFGTtDWOYULQEs4KR0qdtYfCxYAUYRoB7JP7h9ETYLgQTww6kH8Sj2C0pFGgrpM0XKv6/kbIzYJ1g==",
"dev": true,
"requires": {
"undici-types": "~6.20.0"
"undici-types": "~6.21.0"
}
},
"ansi-regex": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="
},
"ansi-styles": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="
},
"artix-checkupdates": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/artix-checkupdates/-/artix-checkupdates-1.0.1.tgz",
"integrity": "sha512-C0AxI3SfoUUekYg3ft/y4+tRjIe8uuDLvBQRSmkfNsRuBLNlEHaxhY/93JB6G4AGXp5RFLZYDnbgjakgbTLhkw=="
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/artix-checkupdates/-/artix-checkupdates-1.0.2.tgz",
"integrity": "sha512-VTLeMVysGeZ3QiLtEyWoVM8D57YyeYhYQoL3vcW9b0dZE+zhE4di80PYEFGeQzIBcCStcBFnI1uSBoAEHMVHAQ=="
},
"balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"requires": {
"balanced-match": "^1.0.0"
}
},
"cli-color": {
"version": "2.0.4",
@@ -301,6 +806,29 @@
"timers-ext": "^0.1.7"
}
},
"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==",
"requires": {
"color-name": "~1.1.4"
}
},
"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=="
},
"cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"requires": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
"which": "^2.0.1"
}
},
"d": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
@@ -310,6 +838,16 @@
"type": "^1.0.1"
}
},
"eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
},
"emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
},
"es5-ext": {
"version": "0.10.64",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz",
@@ -393,20 +931,65 @@
}
}
},
"foreground-child": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
"integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
"requires": {
"cross-spawn": "^7.0.0",
"signal-exit": "^4.0.1"
}
},
"glob": {
"version": "11.0.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.2.tgz",
"integrity": "sha512-YT7U7Vye+t5fZ/QMkBFrTJ7ZQxInIUjwyAjVj84CYXqgBdv30MFUPGnBR6sQaVq6Is15wYJUsnzTuWaGRBhBAQ==",
"requires": {
"foreground-child": "^3.1.0",
"jackspeak": "^4.0.1",
"minimatch": "^10.0.0",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^2.0.0"
}
},
"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=="
},
"is-promise": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz",
"integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ=="
},
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
},
"jackspeak": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz",
"integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==",
"requires": {
"@isaacs/cliui": "^8.0.2"
}
},
"json5": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="
},
"ky": {
"version": "1.7.4",
"resolved": "https://registry.npmjs.org/ky/-/ky-1.7.4.tgz",
"integrity": "sha512-zYEr/gh7uLW2l4su11bmQ2M9xLgQLjyvx58UyNM/6nuqyWFHPX5ktMjvpev3F8QWdjSsHUpnWew4PBCswBNuMQ=="
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/ky/-/ky-1.8.1.tgz",
"integrity": "sha512-7Bp3TpsE+L+TARSnnDpk3xg8Idi8RwSLdj6CMbNWoOARIrGrbuLGusV0dYwbZOm4bB3jHNxSw8Wk/ByDqJEnDw=="
},
"lru-cache": {
"version": "11.0.2",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz",
"integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA=="
},
"lru-queue": {
"version": "0.1.0",
@@ -431,11 +1014,124 @@
"timers-ext": "^0.1.7"
}
},
"minimatch": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
"integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
"requires": {
"brace-expansion": "^2.0.1"
}
},
"minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="
},
"next-tick": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
"integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
},
"package-json-from-dist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="
},
"path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
},
"path-scurry": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz",
"integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==",
"requires": {
"lru-cache": "^11.0.0",
"minipass": "^7.1.2"
}
},
"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==",
"requires": {
"shebang-regex": "^3.0.0"
}
},
"shebang-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
},
"signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="
},
"string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"requires": {
"eastasianwidth": "^0.2.0",
"emoji-regex": "^9.2.2",
"strip-ansi": "^7.0.1"
}
},
"string-width-cjs": {
"version": "npm:string-width@4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"dependencies": {
"ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
},
"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=="
},
"strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"requires": {
"ansi-regex": "^5.0.1"
}
}
}
},
"strip-ansi": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"requires": {
"ansi-regex": "^6.0.1"
}
},
"strip-ansi-cjs": {
"version": "npm:strip-ansi@6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"requires": {
"ansi-regex": "^5.0.1"
},
"dependencies": {
"ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
}
}
},
"timers-ext": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz",
@@ -451,16 +1147,82 @@
"integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg=="
},
"typescript": {
"version": "5.7.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
"integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true
},
"undici-types": {
"version": "6.20.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"dev": true
},
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"requires": {
"isexe": "^2.0.0"
}
},
"wrap-ansi": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
"requires": {
"ansi-styles": "^6.1.0",
"string-width": "^5.0.1",
"strip-ansi": "^7.0.1"
}
},
"wrap-ansi-cjs": {
"version": "npm:wrap-ansi@7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"requires": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"dependencies": {
"ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
},
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"requires": {
"color-convert": "^2.0.1"
}
},
"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=="
},
"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==",
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
}
},
"strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"requires": {
"ansi-regex": "^5.0.1"
}
}
}
}
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "artix-metro",
"version": "3.0.0",
"version": "3.1.4",
"description": "Automate pushing packages to Artix",
"keywords": [
"artix",
@@ -13,7 +13,8 @@
},
"files": [
"distribution",
"bin"
"bin",
"completion"
],
"author": {
"name": "Cory Sanin",
@@ -30,15 +31,16 @@
},
"license": "MIT",
"dependencies": {
"artix-checkupdates": "1.0.1",
"artix-checkupdates": "1.0.2",
"cli-color": "2.0.4",
"ky": "1.7.4",
"json5": "2.2.3"
"ky": "1.8.1",
"json5": "2.2.3",
"glob": "11.0.2"
},
"devDependencies": {
"typescript": "5.7.3",
"typescript": "5.8.3",
"@sindresorhus/tsconfig": "7.0.0",
"@types/cli-color": "2.0.6",
"@types/node": "22.10.7"
"@types/node": "22.15.14"
}
}

View File

@@ -30,14 +30,16 @@ function removeQuotes(str: string) {
class ArtoolsConfReader {
async readConf(): Promise<ArtoolsConf> {
async readConf(silent: boolean = false): Promise<ArtoolsConf> {
const primaryLocation = path.join(os.homedir(), '.config', 'artools', 'artools-pkg.conf');
const systemConf = path.join('/', 'etc', 'artools', 'artools-pkg.conf');
try {
return await this.readConfFile(primaryLocation);
}
catch (ex) {
console.error(`artools config at "${primaryLocation}" could not be read. ${ex}\nUsing system config "${systemConf}" instead.`);
if (!silent) {
console.error(`artools config at "${primaryLocation}" could not be read. ${ex}\nUsing system config "${systemConf}" instead.`);
}
return await this.readConfFile(systemConf);
}
}

View File

@@ -1,7 +1,7 @@
import ky from 'ky';
import { snooze } from './snooze.mjs';
type CiStatus = "pending" | "success" | "error" | "failure";
type CiStatus = "pending" | "success" | "error" | "failure" | "";
interface GiteaConfig {
protocol?: string;
@@ -16,7 +16,12 @@ interface Commit {
interface Status {
sha: string;
state: CiStatus
state: CiStatus;
}
interface Hook {
active: boolean;
id: number;
}
class Gitea {
@@ -95,7 +100,43 @@ class Gitea {
}
}
async getHooks(...args: string[]): Promise<Hook[]> {
try {
let headers: HeadersInit = {};
if (this._token) {
headers['Authorization'] = `token ${this._token}`
}
const resp = await ky.get(`${this.getUrlPrefix()}/repos/${args.join('/')}/hooks`, {
headers
});
return await resp.json();
}
catch (err) {
throw err;
}
}
async sendTestWebhook(...args: string[]): Promise<void> {
try {
let headers: HeadersInit = {};
if (this._token) {
headers['Authorization'] = `token ${this._token}`
}
const hook = (await this.getHooks(...args)).find(hook => hook.active === true);
if (!hook) {
throw new Error('No active webhook found');
}
await ky.post(`${this.getUrlPrefix()}/repos/${args.join('/')}/hooks/${hook.id}/tests`, {
headers
});
}
catch (err) {
throw err;
}
}
async waitForBuild(lastHash: string, ...args: string[]): Promise<void> {
let missingStatusCount = 0;
while (true) {
let status: Status | null;
try {
@@ -108,7 +149,15 @@ class Gitea {
await snooze(30000);
continue;
}
if (status.sha !== lastHash) {
if (!status.sha && !status.state) {
if (++missingStatusCount > 3) {
console.log('No build info detected. Sending test webhook...');
missingStatusCount = 0;
await this.sendTestWebhook(...args);
}
await snooze(30000);
}
else if (status.sha !== lastHash) {
if (status.state === 'success') {
break;
}

View File

@@ -1,16 +1,24 @@
import * as fsp from 'node:fs/promises';
import * as readline from 'node:readline/promises';
import path from 'node:path';
import clc from 'cli-color';
import JSON5 from 'json5';
import { Writable } from 'stream';
import { glob } from 'glob'
import { Pusher } from './pusher.mjs';
import { isPasswordRequired } from './runCommand.mjs';
import { ArtoolsConfReader, DefaultConf } from './artoolsconf.mjs';
import type { Job, ArtixpkgRepo } from './pusher.mts';
import type { ArtoolsConf } from './artoolsconf.mts';
/**
* Prompts the user to input their GPG password via stdin
* @returns a promise that resolves the password
*/
async function getGpgPass() {
if ((process.env['SKIPGPGPASSPROMPT'] || '').toLowerCase() === 'true') {
return 'SKIP';
}
let muted = false;
let mutableStdout = new Writable({
write: function (chunk, encoding, callback) {
@@ -20,6 +28,11 @@ async function getGpgPass() {
callback();
}
});
if (! await isPasswordRequired()) {
console.log(clc.green('Looks like GPG agent is currently running and password is cached. '
+ 'If there is no timeout on your cached password, you can simply press enter.\n'
+ 'To skip this GPG password prompt next time, set $SKIPGPGPASSPROMPT to true'));
}
let rl = readline.createInterface({
input: process.stdin,
output: mutableStdout,
@@ -34,7 +47,16 @@ async function getGpgPass() {
return password;
}
async function expandGlob(workspace: string, globby: string): Promise<string[]> {
return (await glob(path.join(globby, 'README.md'), {
cwd: path.join(workspace, 'artixlinux'),
maxDepth: 2
})).map(p => path.dirname(p));
}
async function artixMetro() {
let artoolsConf: ArtoolsConf = DefaultConf;
let completion: boolean = false;
let job: Partial<Job> = {
increment: false,
packages: []
@@ -55,6 +77,29 @@ async function artixMetro() {
const iPlus = i + 1;
const args = process.argv;
switch (true) {
case (arg === '--completion') && iPlus < args.length:
const comm = args[iPlus] as string;
completion = skipOne = true;
switch (comm) {
case ('pkgbase'):
(new ArtoolsConfReader()).readConf(true).then(async (conf) => {
try {
console.log(
(await fsp.readdir(path.join(conf.workspace, 'artixlinux'), { withFileTypes: true }))
.filter(dirent => dirent.isDirectory())
.map(dirent => dirent.name).join(' '));
process.exit(0);
}
catch {
process.exit(1);
}
})
break;
default:
console.error(`command "${comm}" not recognized`)
break;
}
break;
case (arg === '--job' || arg === '-j') && iPlus < args.length:
if (jobfile) {
console.error(`multiple jobfiles provided. aborting.`);
@@ -102,6 +147,10 @@ async function artixMetro() {
}
});
if (completion) {
return;
}
if (helpFlag || (!jobfile && !job.repo)) {
console.log([
`\nUsage: artix-metro [OPTIONS] [commands]...`,
@@ -122,6 +171,13 @@ async function artixMetro() {
process.exit(0);
}
try {
artoolsConf = await (new ArtoolsConfReader()).readConf();
}
catch (ex) {
console.error(ex);
}
if (jobfile) {
try {
job = JSON5.parse((await fsp.readFile(jobfile)).toString());
@@ -132,6 +188,13 @@ async function artixMetro() {
process.exit(4);
}
}
else if (job.packages) {
const expanded: string[] = [];
for (let i = 0; i < (job.packages.length || 0); i++) {
(await expandGlob(artoolsConf.workspace, job.packages[i] as string)).forEach(p => expanded.push(p));
}
job.packages = expanded;
}
if (startPkg && job.packages) {
const startPos = job.packages.indexOf(startPkg);
@@ -139,11 +202,15 @@ async function artixMetro() {
}
})();
if (completion) {
return;
}
console.log('artix-metro - Developed by Cory Sanin\n');
let pusher = new Pusher({
gpgpass: process.env['GPGPASS'] || (await getGpgPass()) || ''
});
console.log('artix-metro\nCory Sanin\n');
}, artoolsConf);
try {
await pusher.runJob(job as Job);
@@ -156,4 +223,4 @@ async function artixMetro() {
}
export default artixMetro;
export { artixMetro };
export { artixMetro, expandGlob };

View File

@@ -4,11 +4,11 @@ import * as readline from 'node:readline/promises';
import clc from 'cli-color';
import path from 'node:path';
import os from 'node:os';
import { spawn } from 'node:child_process';
import { Checkupdates } from 'artix-checkupdates';
import { Gitea } from './gitea.mjs'
import { ArtoolsConfReader, DefaultConf } from './artoolsconf.mjs';
import { DefaultConf } from './artoolsconf.mjs';
import { snooze } from './snooze.mjs';
import { runCommand, isPasswordRequired } from './runCommand.mjs';
import type { ArtixRepo } from 'artix-checkupdates';
import type { ArtoolsConf } from './artoolsconf.mts';
@@ -26,22 +26,8 @@ interface Job extends Partial<ArtoolsConf> {
}
const PACKAGE_ORG = 'packages';
const SIGNATUREEXPIRY = 30000;//in ms
const SIGNFILE = path.join(os.tmpdir(), 'signfile');
/**
* Run a command (as a promise).
* @param command command to run
* @param args args to pass
* @returns true if success
*/
function runCommand(command: string, args: string[] = []): Promise<boolean> {
return new Promise((res, _) => {
let proc = spawn(command, args, { stdio: ['ignore', process.stdout, process.stderr] });
proc.on('exit', code => res(code === 0));
});
}
/**
* Formats text to be sent as a parameter to some command
* @param param
@@ -54,40 +40,36 @@ function escapeCommandParam(param: string) {
class Pusher {
private _gitea: Gitea | null;
private _lastSign: number = 0;
private _config: PusherConfig;
private _artools: ArtoolsConf;
private _constructed: Promise<void>;
private _createdSignfile: boolean;
constructor(config: PusherConfig = {}) {
constructor(config: PusherConfig = {}, artoolsConf: ArtoolsConf = DefaultConf) {
this._gitea = null;
this._artools = DefaultConf
this._artools = artoolsConf;
this._config = config;
this._constructed = (async () => {
try {
this._artools = await (new ArtoolsConfReader()).readConf();
this._gitea = new Gitea({
token: this._artools.giteaToken || ''
});
}
catch (ex) {
this._artools = DefaultConf
console.error(ex);
}
})();
this._createdSignfile = false;
this._gitea = new Gitea({
token: this._artools.giteaToken || ''
});
}
async refreshGpg() {
let currentTime = (new Date()).getTime();
if (this._config.gpgpass && currentTime - this._lastSign > SIGNATUREEXPIRY) {
const sshSignMode = 'SSHKEYSIGN' in process.env;
if (sshSignMode || await isPasswordRequired()) {
console.log(clc.cyan('Refreshing signature...'));
await runCommand('touch', [SIGNFILE]);
await runCommand('gpg', ['-a', '--passphrase', escapeCommandParam(this._config.gpgpass), '--batch', '--pinentry-mode', 'loopback', '--detach-sign', SIGNFILE]);
await fsp.rm(`${SIGNFILE}.asc`);
this._lastSign = currentTime;
this._createdSignfile ||= await runCommand('touch', [SIGNFILE]);
if (sshSignMode) {
await runCommand('ssh-keygen', ['-Y', 'sign', '-f', path.resolve(process.env['SSHKEYSIGN'] as string), '-n', ' git', SIGNFILE]);
}
else {
await runCommand('gpg', ['-a', '--passphrase', escapeCommandParam(this._config.gpgpass || ''), '--batch', '--pinentry-mode', 'loopback', '--detach-sign', SIGNFILE]);
}
await fsp.rm(`${SIGNFILE}.${sshSignMode ? 'sig' : 'asc'}`)
}
}
increment(pkg: string): Promise<void> {
return new Promise(async (res, _) => {
const pkgbuild = path.join(this._artools.workspace, 'artixlinux', pkg, 'PKGBUILD');
@@ -141,7 +123,6 @@ class Pusher {
}
async runJob(job: Job) {
await this._constructed;
const checkupdates = new Checkupdates();
const gitea = this._gitea as Gitea;
@@ -159,7 +140,7 @@ class Pusher {
}
console.log(clc.yellowBright('Running artix-checkupdates'));
const actionable = job.increment ? job.packages : (await (!!job.source ? checkupdates.fetchMovable() : checkupdates.fetchUpgradable())).map(res => res.basename);
const actionable = job.increment ? job.packages : (await (!!job.source ? checkupdates.fetchLooseMovable() : checkupdates.fetchUpgradable())).map(res => res.basename);
// order is IMPORTANT. Must be BLOCKING.
for (let i = 0; i < (job.packages || []).length; i++) {
@@ -214,11 +195,13 @@ class Pusher {
}
}
console.log(clc.greenBright('SUCCESS: All packages built'));
try {
await fsp.rm(SIGNFILE);
}
catch {
console.error(clc.red('failed to remove temp signfile'));
if (this._createdSignfile) {
try {
await fsp.rm(SIGNFILE);
}
catch {
console.error(clc.red('failed to remove temp signfile'));
}
}
}
}

43
src/runCommand.mts Normal file
View File

@@ -0,0 +1,43 @@
import { spawn } from 'node:child_process';
import type { SpawnOptions } from 'node:child_process';
/**
* Run a command (as a promise).
* @param command command to run
* @param args args to pass
* @returns promise that yields true if success
*/
function runCommand(command: string, args: string[] = [], stdOutToLogs: boolean = true): Promise<boolean> {
return new Promise((res, _) => {
const opts: SpawnOptions = {stdio: stdOutToLogs ? ['pipe', 'inherit', 'inherit'] : 'pipe'};
const proc = spawn(command, args, opts);
proc.on('exit', code => res(code === 0));
});
}
/**
* Check if password input is necessary for signing
* @returns promise that yieds true if password is required
*/
function isPasswordRequired(): Promise<boolean> {
return new Promise(async (res, _) => {
if (! await runCommand('gpg-agent', [], false)) {
return res(true);
}
const proc = spawn('gpg-connect-agent', ['KEYINFO --list', '/bye'], { stdio: 'pipe' });
let outputstr = '';
proc.stdout.on('data', data => {
outputstr += data.toString();
});
proc.on('exit', async () => {
const keyinfo = outputstr.split('\n').filter(l => l.includes('KEYINFO'));
res(!keyinfo.find(l => {
const tokens = l.split(' ');
return tokens[0] === 'S' && tokens[1] === 'KEYINFO' && tokens[3] === 'D' && tokens[6] === '1';
}));
});
});
}
export default runCommand;
export { runCommand, isPasswordRequired };