mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 02:11:53 +00:00
Merge branch 'integration/new-container-runtime' of github.com:Start9Labs/start-os into rebase/feat/domains
This commit is contained in:
603
container-runtime/package-lock.json
generated
603
container-runtime/package-lock.json
generated
@@ -23,14 +23,13 @@
|
||||
"@swc/cli": "^0.1.62",
|
||||
"@swc/core": "^1.3.65",
|
||||
"@types/node": "^20.11.13",
|
||||
"esbuild": "^0.20.0",
|
||||
"prettier": "^3.2.5",
|
||||
"typescript": ">5.2"
|
||||
}
|
||||
},
|
||||
"../sdk/dist": {
|
||||
"name": "@start9labs/start-sdk",
|
||||
"version": "0.4.0-rev0.lib0.rc8.beta7",
|
||||
"version": "0.4.0-rev0.lib0.rc8.beta10",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@iarna/toml": "^2.2.5",
|
||||
@@ -41,380 +40,13 @@
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.4.0",
|
||||
"jest": "^29.4.3",
|
||||
"prettier": "^3.2.5",
|
||||
"ts-jest": "^29.0.5",
|
||||
"ts-node": "^10.9.1",
|
||||
"tsx": "^4.7.1",
|
||||
"typescript": "^5.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.0.tgz",
|
||||
"integrity": "sha512-fGFDEctNh0CcSwsiRPxiaqX0P5rq+AqE0SRhYGZ4PX46Lg1FNR6oCxJghf8YgY0WQEgQuh3lErUFE4KxLeRmmw==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"aix"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.0.tgz",
|
||||
"integrity": "sha512-3bMAfInvByLHfJwYPJRlpTeaQA75n8C/QKpEaiS4HrFWFiJlNI0vzq/zCjBrhAYcPyVPG7Eo9dMrcQXuqmNk5g==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.0.tgz",
|
||||
"integrity": "sha512-aVpnM4lURNkp0D3qPoAzSG92VXStYmoVPOgXveAUoQBWRSuQzt51yvSju29J6AHPmwY1BjH49uR29oyfH1ra8Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-x64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.0.tgz",
|
||||
"integrity": "sha512-uK7wAnlRvjkCPzh8jJ+QejFyrP8ObKuR5cBIsQZ+qbMunwR8sbd8krmMbxTLSrDhiPZaJYKQAU5Y3iMDcZPhyQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.0.tgz",
|
||||
"integrity": "sha512-AjEcivGAlPs3UAcJedMa9qYg9eSfU6FnGHJjT8s346HSKkrcWlYezGE8VaO2xKfvvlZkgAhyvl06OJOxiMgOYQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-x64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.0.tgz",
|
||||
"integrity": "sha512-bsgTPoyYDnPv8ER0HqnJggXK6RyFy4PH4rtsId0V7Efa90u2+EifxytE9pZnsDgExgkARy24WUQGv9irVbTvIw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-arm64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.0.tgz",
|
||||
"integrity": "sha512-kQ7jYdlKS335mpGbMW5tEe3IrQFIok9r84EM3PXB8qBFJPSc6dpWfrtsC/y1pyrz82xfUIn5ZrnSHQQsd6jebQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-x64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.0.tgz",
|
||||
"integrity": "sha512-uG8B0WSepMRsBNVXAQcHf9+Ko/Tr+XqmK7Ptel9HVmnykupXdS4J7ovSQUIi0tQGIndhbqWLaIL/qO/cWhXKyQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.0.tgz",
|
||||
"integrity": "sha512-2ezuhdiZw8vuHf1HKSf4TIk80naTbP9At7sOqZmdVwvvMyuoDiZB49YZKLsLOfKIr77+I40dWpHVeY5JHpIEIg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.0.tgz",
|
||||
"integrity": "sha512-uTtyYAP5veqi2z9b6Gr0NUoNv9F/rOzI8tOD5jKcCvRUn7T60Bb+42NDBCWNhMjkQzI0qqwXkQGo1SY41G52nw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ia32": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.0.tgz",
|
||||
"integrity": "sha512-c88wwtfs8tTffPaoJ+SQn3y+lKtgTzyjkD8NgsyCtCmtoIC8RDL7PrJU05an/e9VuAke6eJqGkoMhJK1RY6z4w==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.0.tgz",
|
||||
"integrity": "sha512-lR2rr/128/6svngnVta6JN4gxSXle/yZEZL3o4XZ6esOqhyR4wsKyfu6qXAL04S4S5CgGfG+GYZnjFd4YiG3Aw==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-mips64el": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.0.tgz",
|
||||
"integrity": "sha512-9Sycc+1uUsDnJCelDf6ZNqgZQoK1mJvFtqf2MUz4ujTxGhvCWw+4chYfDLPepMEvVL9PDwn6HrXad5yOrNzIsQ==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ppc64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.0.tgz",
|
||||
"integrity": "sha512-CoWSaaAXOZd+CjbUTdXIJE/t7Oz+4g90A3VBCHLbfuc5yUQU/nFDLOzQsN0cdxgXd97lYW/psIIBdjzQIwTBGw==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-riscv64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.0.tgz",
|
||||
"integrity": "sha512-mlb1hg/eYRJUpv8h/x+4ShgoNLL8wgZ64SUr26KwglTYnwAWjkhR2GpoKftDbPOCnodA9t4Y/b68H4J9XmmPzA==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-s390x": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.0.tgz",
|
||||
"integrity": "sha512-fgf9ubb53xSnOBqyvWEY6ukBNRl1mVX1srPNu06B6mNsNK20JfH6xV6jECzrQ69/VMiTLvHMicQR/PgTOgqJUQ==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-x64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.0.tgz",
|
||||
"integrity": "sha512-H9Eu6MGse++204XZcYsse1yFHmRXEWgadk2N58O/xd50P9EvFMLJTQLg+lB4E1cF2xhLZU5luSWtGTb0l9UeSg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-x64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.0.tgz",
|
||||
"integrity": "sha512-lCT675rTN1v8Fo+RGrE5KjSnfY0x9Og4RN7t7lVrN3vMSjy34/+3na0q7RIfWDAj0e0rCh0OL+P88lu3Rt21MQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-x64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.0.tgz",
|
||||
"integrity": "sha512-HKoUGXz/TOVXKQ+67NhxyHv+aDSZf44QpWLa3I1lLvAwGq8x1k0T+e2HHSRvxWhfJrFxaaqre1+YyzQ99KixoA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/sunos-x64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.0.tgz",
|
||||
"integrity": "sha512-GDwAqgHQm1mVoPppGsoq4WJwT3vhnz/2N62CzhvApFD1eJyTroob30FPpOZabN+FgCjhG+AgcZyOPIkR8dfD7g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-arm64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.0.tgz",
|
||||
"integrity": "sha512-0vYsP8aC4TvMlOQYozoksiaxjlvUcQrac+muDqj1Fxy6jh9l9CZJzj7zmh8JGfiV49cYLTorFLxg7593pGldwQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-ia32": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.0.tgz",
|
||||
"integrity": "sha512-p98u4rIgfh4gdpV00IqknBD5pC84LCub+4a3MO+zjqvU5MVXOc3hqR2UgT2jI2nh3h8s9EQxmOsVI3tyzv1iFg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-x64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.0.tgz",
|
||||
"integrity": "sha512-NgJnesu1RtWihtTtXGFMU5YSE6JyyHPMxCwBZK7a6/8d31GuSo9l0Ss7w1Jw5QnKUawG6UEehs883kcXf5fYwg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@iarna/toml": {
|
||||
"version": "2.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz",
|
||||
@@ -1304,44 +936,6 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.0.tgz",
|
||||
"integrity": "sha512-6iwE3Y2RVYCME1jLpBqq7LQWK3MW6vjV2bZy6gt/WrqkY+WE74Spyc0ThAOYpMtITvnjX09CrC6ym7A/m9mebA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/aix-ppc64": "0.20.0",
|
||||
"@esbuild/android-arm": "0.20.0",
|
||||
"@esbuild/android-arm64": "0.20.0",
|
||||
"@esbuild/android-x64": "0.20.0",
|
||||
"@esbuild/darwin-arm64": "0.20.0",
|
||||
"@esbuild/darwin-x64": "0.20.0",
|
||||
"@esbuild/freebsd-arm64": "0.20.0",
|
||||
"@esbuild/freebsd-x64": "0.20.0",
|
||||
"@esbuild/linux-arm": "0.20.0",
|
||||
"@esbuild/linux-arm64": "0.20.0",
|
||||
"@esbuild/linux-ia32": "0.20.0",
|
||||
"@esbuild/linux-loong64": "0.20.0",
|
||||
"@esbuild/linux-mips64el": "0.20.0",
|
||||
"@esbuild/linux-ppc64": "0.20.0",
|
||||
"@esbuild/linux-riscv64": "0.20.0",
|
||||
"@esbuild/linux-s390x": "0.20.0",
|
||||
"@esbuild/linux-x64": "0.20.0",
|
||||
"@esbuild/netbsd-x64": "0.20.0",
|
||||
"@esbuild/openbsd-x64": "0.20.0",
|
||||
"@esbuild/sunos-x64": "0.20.0",
|
||||
"@esbuild/win32-arm64": "0.20.0",
|
||||
"@esbuild/win32-ia32": "0.20.0",
|
||||
"@esbuild/win32-x64": "0.20.0"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-plugin-resolve": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-plugin-resolve/-/esbuild-plugin-resolve-2.0.0.tgz",
|
||||
@@ -2965,167 +2559,6 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@esbuild/aix-ppc64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.0.tgz",
|
||||
"integrity": "sha512-fGFDEctNh0CcSwsiRPxiaqX0P5rq+AqE0SRhYGZ4PX46Lg1FNR6oCxJghf8YgY0WQEgQuh3lErUFE4KxLeRmmw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@esbuild/android-arm": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.0.tgz",
|
||||
"integrity": "sha512-3bMAfInvByLHfJwYPJRlpTeaQA75n8C/QKpEaiS4HrFWFiJlNI0vzq/zCjBrhAYcPyVPG7Eo9dMrcQXuqmNk5g==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@esbuild/android-arm64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.0.tgz",
|
||||
"integrity": "sha512-aVpnM4lURNkp0D3qPoAzSG92VXStYmoVPOgXveAUoQBWRSuQzt51yvSju29J6AHPmwY1BjH49uR29oyfH1ra8Q==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@esbuild/android-x64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.0.tgz",
|
||||
"integrity": "sha512-uK7wAnlRvjkCPzh8jJ+QejFyrP8ObKuR5cBIsQZ+qbMunwR8sbd8krmMbxTLSrDhiPZaJYKQAU5Y3iMDcZPhyQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@esbuild/darwin-arm64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.0.tgz",
|
||||
"integrity": "sha512-AjEcivGAlPs3UAcJedMa9qYg9eSfU6FnGHJjT8s346HSKkrcWlYezGE8VaO2xKfvvlZkgAhyvl06OJOxiMgOYQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@esbuild/darwin-x64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.0.tgz",
|
||||
"integrity": "sha512-bsgTPoyYDnPv8ER0HqnJggXK6RyFy4PH4rtsId0V7Efa90u2+EifxytE9pZnsDgExgkARy24WUQGv9irVbTvIw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@esbuild/freebsd-arm64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.0.tgz",
|
||||
"integrity": "sha512-kQ7jYdlKS335mpGbMW5tEe3IrQFIok9r84EM3PXB8qBFJPSc6dpWfrtsC/y1pyrz82xfUIn5ZrnSHQQsd6jebQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@esbuild/freebsd-x64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.0.tgz",
|
||||
"integrity": "sha512-uG8B0WSepMRsBNVXAQcHf9+Ko/Tr+XqmK7Ptel9HVmnykupXdS4J7ovSQUIi0tQGIndhbqWLaIL/qO/cWhXKyQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@esbuild/linux-arm": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.0.tgz",
|
||||
"integrity": "sha512-2ezuhdiZw8vuHf1HKSf4TIk80naTbP9At7sOqZmdVwvvMyuoDiZB49YZKLsLOfKIr77+I40dWpHVeY5JHpIEIg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@esbuild/linux-arm64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.0.tgz",
|
||||
"integrity": "sha512-uTtyYAP5veqi2z9b6Gr0NUoNv9F/rOzI8tOD5jKcCvRUn7T60Bb+42NDBCWNhMjkQzI0qqwXkQGo1SY41G52nw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@esbuild/linux-ia32": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.0.tgz",
|
||||
"integrity": "sha512-c88wwtfs8tTffPaoJ+SQn3y+lKtgTzyjkD8NgsyCtCmtoIC8RDL7PrJU05an/e9VuAke6eJqGkoMhJK1RY6z4w==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@esbuild/linux-loong64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.0.tgz",
|
||||
"integrity": "sha512-lR2rr/128/6svngnVta6JN4gxSXle/yZEZL3o4XZ6esOqhyR4wsKyfu6qXAL04S4S5CgGfG+GYZnjFd4YiG3Aw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@esbuild/linux-mips64el": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.0.tgz",
|
||||
"integrity": "sha512-9Sycc+1uUsDnJCelDf6ZNqgZQoK1mJvFtqf2MUz4ujTxGhvCWw+4chYfDLPepMEvVL9PDwn6HrXad5yOrNzIsQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@esbuild/linux-ppc64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.0.tgz",
|
||||
"integrity": "sha512-CoWSaaAXOZd+CjbUTdXIJE/t7Oz+4g90A3VBCHLbfuc5yUQU/nFDLOzQsN0cdxgXd97lYW/psIIBdjzQIwTBGw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@esbuild/linux-riscv64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.0.tgz",
|
||||
"integrity": "sha512-mlb1hg/eYRJUpv8h/x+4ShgoNLL8wgZ64SUr26KwglTYnwAWjkhR2GpoKftDbPOCnodA9t4Y/b68H4J9XmmPzA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@esbuild/linux-s390x": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.0.tgz",
|
||||
"integrity": "sha512-fgf9ubb53xSnOBqyvWEY6ukBNRl1mVX1srPNu06B6mNsNK20JfH6xV6jECzrQ69/VMiTLvHMicQR/PgTOgqJUQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@esbuild/linux-x64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.0.tgz",
|
||||
"integrity": "sha512-H9Eu6MGse++204XZcYsse1yFHmRXEWgadk2N58O/xd50P9EvFMLJTQLg+lB4E1cF2xhLZU5luSWtGTb0l9UeSg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@esbuild/netbsd-x64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.0.tgz",
|
||||
"integrity": "sha512-lCT675rTN1v8Fo+RGrE5KjSnfY0x9Og4RN7t7lVrN3vMSjy34/+3na0q7RIfWDAj0e0rCh0OL+P88lu3Rt21MQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@esbuild/openbsd-x64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.0.tgz",
|
||||
"integrity": "sha512-HKoUGXz/TOVXKQ+67NhxyHv+aDSZf44QpWLa3I1lLvAwGq8x1k0T+e2HHSRvxWhfJrFxaaqre1+YyzQ99KixoA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@esbuild/sunos-x64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.0.tgz",
|
||||
"integrity": "sha512-GDwAqgHQm1mVoPppGsoq4WJwT3vhnz/2N62CzhvApFD1eJyTroob30FPpOZabN+FgCjhG+AgcZyOPIkR8dfD7g==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@esbuild/win32-arm64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.0.tgz",
|
||||
"integrity": "sha512-0vYsP8aC4TvMlOQYozoksiaxjlvUcQrac+muDqj1Fxy6jh9l9CZJzj7zmh8JGfiV49cYLTorFLxg7593pGldwQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@esbuild/win32-ia32": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.0.tgz",
|
||||
"integrity": "sha512-p98u4rIgfh4gdpV00IqknBD5pC84LCub+4a3MO+zjqvU5MVXOc3hqR2UgT2jI2nh3h8s9EQxmOsVI3tyzv1iFg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@esbuild/win32-x64": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.0.tgz",
|
||||
"integrity": "sha512-NgJnesu1RtWihtTtXGFMU5YSE6JyyHPMxCwBZK7a6/8d31GuSo9l0Ss7w1Jw5QnKUawG6UEehs883kcXf5fYwg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@iarna/toml": {
|
||||
"version": "2.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz",
|
||||
@@ -3186,6 +2619,7 @@
|
||||
"@types/jest": "^29.4.0",
|
||||
"isomorphic-fetch": "^3.0.0",
|
||||
"jest": "^29.4.3",
|
||||
"prettier": "^3.2.5",
|
||||
"ts-jest": "^29.0.5",
|
||||
"ts-matches": "^5.4.1",
|
||||
"ts-node": "^10.9.1",
|
||||
@@ -3732,37 +3166,6 @@
|
||||
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="
|
||||
},
|
||||
"esbuild": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.0.tgz",
|
||||
"integrity": "sha512-6iwE3Y2RVYCME1jLpBqq7LQWK3MW6vjV2bZy6gt/WrqkY+WE74Spyc0ThAOYpMtITvnjX09CrC6ym7A/m9mebA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@esbuild/aix-ppc64": "0.20.0",
|
||||
"@esbuild/android-arm": "0.20.0",
|
||||
"@esbuild/android-arm64": "0.20.0",
|
||||
"@esbuild/android-x64": "0.20.0",
|
||||
"@esbuild/darwin-arm64": "0.20.0",
|
||||
"@esbuild/darwin-x64": "0.20.0",
|
||||
"@esbuild/freebsd-arm64": "0.20.0",
|
||||
"@esbuild/freebsd-x64": "0.20.0",
|
||||
"@esbuild/linux-arm": "0.20.0",
|
||||
"@esbuild/linux-arm64": "0.20.0",
|
||||
"@esbuild/linux-ia32": "0.20.0",
|
||||
"@esbuild/linux-loong64": "0.20.0",
|
||||
"@esbuild/linux-mips64el": "0.20.0",
|
||||
"@esbuild/linux-ppc64": "0.20.0",
|
||||
"@esbuild/linux-riscv64": "0.20.0",
|
||||
"@esbuild/linux-s390x": "0.20.0",
|
||||
"@esbuild/linux-x64": "0.20.0",
|
||||
"@esbuild/netbsd-x64": "0.20.0",
|
||||
"@esbuild/openbsd-x64": "0.20.0",
|
||||
"@esbuild/sunos-x64": "0.20.0",
|
||||
"@esbuild/win32-arm64": "0.20.0",
|
||||
"@esbuild/win32-ia32": "0.20.0",
|
||||
"@esbuild/win32-x64": "0.20.0"
|
||||
}
|
||||
},
|
||||
"esbuild-plugin-resolve": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-plugin-resolve/-/esbuild-plugin-resolve-2.0.0.tgz",
|
||||
|
||||
@@ -28,9 +28,15 @@ export class DockerProcedureContainer {
|
||||
await fs.mkdir(path, { recursive: true })
|
||||
const volumeMount = volumes[mount]
|
||||
if (volumeMount.type === "data") {
|
||||
await overlay.mount({ type: "volume", id: mount }, mounts[mount])
|
||||
await overlay.mount(
|
||||
{ type: "volume", id: mount, subpath: null, readonly: false },
|
||||
mounts[mount],
|
||||
)
|
||||
} else if (volumeMount.type === "assets") {
|
||||
await overlay.mount({ type: "assets", id: mount }, mounts[mount])
|
||||
await overlay.mount(
|
||||
{ type: "assets", id: mount, subpath: null },
|
||||
mounts[mount],
|
||||
)
|
||||
} else if (volumeMount.type === "certificate") {
|
||||
volumeMount
|
||||
const certChain = await effects.getSslCertificate({
|
||||
@@ -56,7 +62,7 @@ export class DockerProcedureContainer {
|
||||
location: path,
|
||||
target: {
|
||||
packageId: volumeMount["package-id"],
|
||||
path: volumeMount.path,
|
||||
subpath: volumeMount.path,
|
||||
readonly: volumeMount.readonly,
|
||||
volumeId: volumeMount["volume-id"],
|
||||
},
|
||||
|
||||
@@ -2,8 +2,7 @@ import { PolyfillEffects } from "./polyfillEffects"
|
||||
import { DockerProcedureContainer } from "./DockerProcedureContainer"
|
||||
import { SystemForEmbassy } from "."
|
||||
import { HostSystemStartOs } from "../../HostSystemStartOs"
|
||||
import { util, Daemons, types as T } from "@start9labs/start-sdk"
|
||||
import { exec } from "child_process"
|
||||
import { Daemons, T, daemons } from "@start9labs/start-sdk"
|
||||
|
||||
const EMBASSY_HEALTH_INTERVAL = 15 * 1000
|
||||
const EMBASSY_PROPERTIES_LOOP = 30 * 1000
|
||||
@@ -39,7 +38,6 @@ export class MainLoop {
|
||||
|
||||
private async constructMainEvent() {
|
||||
const { system, effects } = this
|
||||
const utils = util.createUtils(effects)
|
||||
const currentCommand: [string, ...string[]] = [
|
||||
system.manifest.main.entrypoint,
|
||||
...system.manifest.main.args,
|
||||
@@ -67,7 +65,8 @@ export class MainLoop {
|
||||
// }),
|
||||
// }
|
||||
}
|
||||
const daemon = await utils.runDaemon(
|
||||
const daemon = await daemons.runDaemon()(
|
||||
this.effects,
|
||||
this.system.manifest.main.image,
|
||||
currentCommand,
|
||||
{
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { types as T, util, EmVer, Utils } from "@start9labs/start-sdk"
|
||||
import { types as T, utils, EmVer } from "@start9labs/start-sdk"
|
||||
import * as fs from "fs/promises"
|
||||
|
||||
import { PolyfillEffects } from "./polyfillEffects"
|
||||
import { Duration, duration } from "../../../Models/Duration"
|
||||
import { System } from "../../../Interfaces/System"
|
||||
import { matchManifest, Manifest, Procedure } from "./matchManifest"
|
||||
import { matchManifest, Manifest } from "./matchManifest"
|
||||
import * as childProcess from "node:child_process"
|
||||
import { DockerProcedureContainer } from "./DockerProcedureContainer"
|
||||
import { promisify } from "node:util"
|
||||
@@ -22,6 +22,9 @@ import {
|
||||
any,
|
||||
tuple,
|
||||
number,
|
||||
anyOf,
|
||||
deferred,
|
||||
Parser,
|
||||
} from "ts-matches"
|
||||
import { HostSystemStartOs } from "../../HostSystemStartOs"
|
||||
import { JsonPath, unNestPath } from "../../../Models/JsonPath"
|
||||
@@ -37,58 +40,94 @@ const MANIFEST_LOCATION = "/usr/lib/startos/package/embassyManifest.json"
|
||||
const EMBASSY_JS_LOCATION = "/usr/lib/startos/package/embassy.js"
|
||||
const EMBASSY_POINTER_PATH_PREFIX = "/embassyConfig"
|
||||
|
||||
const matchPackagePropertyObject = object({
|
||||
value: any,
|
||||
type: literal("object"),
|
||||
description: string,
|
||||
})
|
||||
|
||||
const matchPackagePropertyString = object(
|
||||
{
|
||||
type: literal("string"),
|
||||
export type PackagePropertiesV2 = {
|
||||
[name: string]: PackagePropertyObject | PackagePropertyString
|
||||
}
|
||||
export type PackagePropertyString = {
|
||||
type: "string"
|
||||
description?: string
|
||||
value: string
|
||||
/** Let's the ui make this copyable button */
|
||||
copyable?: boolean
|
||||
/** Let the ui create a qr for this field */
|
||||
qr?: boolean
|
||||
/** Hiding the value unless toggled off for field */
|
||||
masked?: boolean
|
||||
}
|
||||
export type PackagePropertyObject = {
|
||||
value: PackagePropertiesV2
|
||||
type: "object"
|
||||
description: string
|
||||
}
|
||||
const [matchPackageProperties, setMatchPackageProperties] =
|
||||
deferred<PackagePropertiesV2>()
|
||||
const matchPackagePropertyObject: Parser<unknown, PackagePropertyObject> =
|
||||
object({
|
||||
value: matchPackageProperties,
|
||||
type: literal("object"),
|
||||
description: string,
|
||||
value: string,
|
||||
copyable: boolean,
|
||||
qr: boolean,
|
||||
masked: boolean,
|
||||
},
|
||||
["copyable", "description", "qr", "masked"],
|
||||
})
|
||||
|
||||
const matchPackagePropertyString: Parser<unknown, PackagePropertyString> =
|
||||
object(
|
||||
{
|
||||
type: literal("string"),
|
||||
description: string,
|
||||
value: string,
|
||||
copyable: boolean,
|
||||
qr: boolean,
|
||||
masked: boolean,
|
||||
},
|
||||
["copyable", "description", "qr", "masked"],
|
||||
)
|
||||
setMatchPackageProperties(
|
||||
dictionary([
|
||||
string,
|
||||
anyOf(matchPackagePropertyObject, matchPackagePropertyString),
|
||||
]),
|
||||
)
|
||||
|
||||
const matchProperties = object({
|
||||
version: literal(2),
|
||||
data: any,
|
||||
data: matchPackageProperties,
|
||||
})
|
||||
|
||||
type ExportUi = {
|
||||
value: string
|
||||
title: string
|
||||
description?: string | undefined
|
||||
masked?: boolean | undefined
|
||||
copyable?: boolean | undefined
|
||||
qr?: boolean | undefined
|
||||
values: { [key: string]: any }
|
||||
expose: { [key: string]: T.ExposeUiPathsAll }
|
||||
}
|
||||
|
||||
function propertiesToExportUi(properties: unknown): ExportUi[] {
|
||||
if (!object.test(properties)) return []
|
||||
const paths: ExportUi[] = []
|
||||
for (const key in properties) {
|
||||
const value: unknown = (properties as any)[key]
|
||||
if (matchPackagePropertyObject.test(value)) {
|
||||
paths.push(...propertiesToExportUi(value))
|
||||
function propertiesToExportUi(
|
||||
properties: PackagePropertiesV2,
|
||||
previousPath = "",
|
||||
): ExportUi {
|
||||
const exportUi: ExportUi = {
|
||||
values: {},
|
||||
expose: {},
|
||||
}
|
||||
for (const [key, value] of Object.entries(properties)) {
|
||||
const path = `${previousPath}/${key}`
|
||||
if (value.type === "object") {
|
||||
const { values, expose } = propertiesToExportUi(value.value, path)
|
||||
exportUi.values[key] = values
|
||||
exportUi.expose[key] = {
|
||||
type: "object",
|
||||
value: expose,
|
||||
description: value.description,
|
||||
}
|
||||
continue
|
||||
}
|
||||
if (!matchPackagePropertyString.test(value)) continue
|
||||
paths.push({
|
||||
value: value.value,
|
||||
title: key,
|
||||
description: value.description,
|
||||
masked: value.masked,
|
||||
copyable: value.copyable,
|
||||
qr: value.qr,
|
||||
})
|
||||
exportUi.values[key] = value.value
|
||||
exportUi.expose[key] = {
|
||||
type: "string",
|
||||
path,
|
||||
description: value.description ?? null,
|
||||
masked: value.masked ?? false,
|
||||
copyable: value.copyable ?? null,
|
||||
qr: value.qr ?? null,
|
||||
}
|
||||
}
|
||||
return paths
|
||||
return exportUi
|
||||
}
|
||||
|
||||
export class SystemForEmbassy implements System {
|
||||
@@ -455,14 +494,9 @@ export class SystemForEmbassy implements System {
|
||||
const exposeUis = propertiesToExportUi(properties.data)
|
||||
await effects.store.set<any, any>({
|
||||
path: "/properties",
|
||||
value: exposeUis.map((x) => x.value),
|
||||
})
|
||||
await effects.exposeUi({
|
||||
paths: exposeUis.map((x, i) => ({
|
||||
...x,
|
||||
path: `/properties/${i}`,
|
||||
})) as any[],
|
||||
value: exposeUis.values,
|
||||
})
|
||||
await effects.exposeUi(exposeUis.expose)
|
||||
} else if (setConfigValue.type === "script") {
|
||||
const moduleCode = this.moduleCode
|
||||
const method = moduleCode.properties
|
||||
@@ -479,14 +513,9 @@ export class SystemForEmbassy implements System {
|
||||
const exposeUis = propertiesToExportUi(properties.data)
|
||||
await effects.store.set<any, any>({
|
||||
path: "/properties",
|
||||
value: exposeUis.map((x) => x.value),
|
||||
})
|
||||
await effects.exposeUi({
|
||||
paths: exposeUis.map((x, i) => ({
|
||||
...x,
|
||||
path: `/properties/${i}`,
|
||||
})) as any[],
|
||||
value: exposeUis.values,
|
||||
})
|
||||
await effects.exposeUi(exposeUis.expose)
|
||||
}
|
||||
}
|
||||
private async health(
|
||||
@@ -991,7 +1020,6 @@ async function updateConfig(
|
||||
) {
|
||||
if (!dictionary([string, unknown]).test(spec)) return
|
||||
if (!dictionary([string, unknown]).test(mutConfigValue)) return
|
||||
const utils = util.createUtils(effects)
|
||||
for (const key in spec) {
|
||||
const specValue = spec[key]
|
||||
|
||||
@@ -1020,8 +1048,8 @@ async function updateConfig(
|
||||
if (matchPointerPackage.test(specValue)) {
|
||||
if (specValue.target === "tor-key")
|
||||
throw new Error("This service uses an unsupported target TorKey")
|
||||
const filled = await utils.serviceInterface
|
||||
.get({
|
||||
const filled = await utils
|
||||
.getServiceInterface(effects, {
|
||||
packageId: specValue["package-id"],
|
||||
id: specValue.interface,
|
||||
})
|
||||
|
||||
@@ -3,23 +3,18 @@ import * as oet from "./oldEmbassyTypes"
|
||||
import { Volume } from "../../../Models/Volume"
|
||||
import * as child_process from "child_process"
|
||||
import { promisify } from "util"
|
||||
import { util, Utils } from "@start9labs/start-sdk"
|
||||
import { Manifest } from "./matchManifest"
|
||||
import { startSdk } from "@start9labs/start-sdk"
|
||||
import { HostSystemStartOs } from "../../HostSystemStartOs"
|
||||
import "isomorphic-fetch"
|
||||
|
||||
const { createUtils } = util
|
||||
import { Manifest } from "./matchManifest"
|
||||
|
||||
const execFile = promisify(child_process.execFile)
|
||||
|
||||
export class PolyfillEffects implements oet.Effects {
|
||||
private utils: Utils<any, any>
|
||||
constructor(
|
||||
readonly effects: HostSystemStartOs,
|
||||
private manifest: Manifest,
|
||||
) {
|
||||
this.utils = createUtils(effects as any)
|
||||
}
|
||||
) {}
|
||||
async writeFile(input: {
|
||||
path: string
|
||||
volumeId: string
|
||||
@@ -99,9 +94,14 @@ export class PolyfillEffects implements oet.Effects {
|
||||
args?: string[] | undefined
|
||||
timeoutMillis?: number | undefined
|
||||
}): Promise<oet.ResultType<string>> {
|
||||
return this.utils
|
||||
.runCommand(this.manifest.main.image, [command, ...(args || [])], {})
|
||||
.then((x) => ({
|
||||
return startSdk
|
||||
.runCommand(
|
||||
this.effects,
|
||||
this.manifest.main.image,
|
||||
[command, ...(args || [])],
|
||||
{},
|
||||
)
|
||||
.then((x: any) => ({
|
||||
stderr: x.stderr.toString(),
|
||||
stdout: x.stdout.toString(),
|
||||
}))
|
||||
|
||||
4
core/startos/bindings/ActionMetadata.ts
Normal file
4
core/startos/bindings/ActionMetadata.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { AllowedStatuses } from "./AllowedStatuses";
|
||||
|
||||
export interface ActionMetadata { name: string, description: string, warning: string | null, disabled: boolean, input: {[key: string]: any}, allowedStatuses: AllowedStatuses, group: string | null, }
|
||||
@@ -1,3 +1,3 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type AllowedStatuses = "only-running" | "only-stopped" | "any" | "disabled";
|
||||
export type AllowedStatuses = "only-running" | "only-stopped" | "any";
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { DependencyKind } from "./DependencyKind";
|
||||
|
||||
export interface DependencyRequirement { id: string, kind: DependencyKind, healthChecks: string[], }
|
||||
export type DependencyRequirement = { "kind": "running", id: string, healthChecks: string[], versionSpec: string, url: string, } | { "kind": "exists", id: string, versionSpec: string, url: string, };
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { AllowedStatuses } from "./AllowedStatuses";
|
||||
import type { ActionMetadata } from "./ActionMetadata";
|
||||
|
||||
export interface ExportActionParams { name: string, description: string, id: string, input: {[key: string]: any}, allowedStatuses: AllowedStatuses, group: string | null, }
|
||||
export interface ExportActionParams { id: string, metadata: ActionMetadata, }
|
||||
|
||||
@@ -412,7 +412,7 @@ pub struct StaticDependencyInfo {
|
||||
pub icon: DataUrl<'static>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
#[serde(tag = "kind")]
|
||||
pub enum CurrentDependencyInfo {
|
||||
|
||||
@@ -385,6 +385,10 @@ impl NetService {
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_ip(&self) -> Ipv4Addr {
|
||||
self.ip.to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for NetService {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::collections::BTreeSet;
|
||||
use std::ffi::OsString;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::os::unix::process::CommandExt;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str::FromStr;
|
||||
@@ -259,16 +260,24 @@ enum AllowedStatuses {
|
||||
OnlyRunning,
|
||||
OnlyStopped,
|
||||
Any,
|
||||
Disabled,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
|
||||
#[ts(export)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct ExportActionParams {
|
||||
#[ts(type = "string")]
|
||||
id: ActionId,
|
||||
metadata: ActionMetadata,
|
||||
}
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
|
||||
#[ts(export)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct ActionMetadata {
|
||||
name: String,
|
||||
description: String,
|
||||
id: String,
|
||||
warning: Option<String>,
|
||||
disabled: bool,
|
||||
#[ts(type = "{[key: string]: any}")]
|
||||
input: Value,
|
||||
allowed_statuses: AllowedStatuses,
|
||||
@@ -335,8 +344,17 @@ async fn get_system_smtp(
|
||||
) -> Result<Value, Error> {
|
||||
todo!()
|
||||
}
|
||||
async fn get_container_ip(context: EffectContext, _: Empty) -> Result<Value, Error> {
|
||||
todo!()
|
||||
async fn get_container_ip(context: EffectContext, _: Empty) -> Result<Ipv4Addr, Error> {
|
||||
match context.0.upgrade() {
|
||||
Some(c) => {
|
||||
let net_service = c.persistent_container.net_service.lock().await;
|
||||
Ok(net_service.get_ip())
|
||||
}
|
||||
None => Err(Error::new(
|
||||
eyre!("Upgrade on Weak<ServiceActorSeed> resulted in a None variant"),
|
||||
crate::ErrorKind::NotFound,
|
||||
)),
|
||||
}
|
||||
}
|
||||
async fn get_service_port_forward(
|
||||
context: EffectContext,
|
||||
@@ -764,8 +782,8 @@ async fn get_configured(context: EffectContext, _: Empty) -> Result<Value, Error
|
||||
let package = peeked
|
||||
.as_public()
|
||||
.as_package_data()
|
||||
.as_idx(&package_id)
|
||||
.or_not_found(&package_id)?
|
||||
.as_idx(package_id)
|
||||
.or_not_found(package_id)?
|
||||
.as_status()
|
||||
.as_configured()
|
||||
.de()?;
|
||||
@@ -1069,28 +1087,39 @@ enum DependencyKind {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(rename_all = "camelCase", tag = "kind")]
|
||||
#[ts(export)]
|
||||
struct DependencyRequirement {
|
||||
#[ts(type = "string")]
|
||||
id: PackageId,
|
||||
kind: DependencyKind,
|
||||
#[serde(default)]
|
||||
#[ts(type = "string[]")]
|
||||
health_checks: BTreeSet<HealthCheckId>,
|
||||
enum DependencyRequirement {
|
||||
Running {
|
||||
#[ts(type = "string")]
|
||||
id: PackageId,
|
||||
#[ts(type = "string[]")]
|
||||
#[serde(rename = "healthChecks")]
|
||||
health_checks: BTreeSet<HealthCheckId>,
|
||||
#[serde(rename = "versionSpec")]
|
||||
version_spec: String,
|
||||
url: String,
|
||||
},
|
||||
Exists {
|
||||
#[ts(type = "string")]
|
||||
id: PackageId,
|
||||
#[serde(rename = "versionSpec")]
|
||||
version_spec: String,
|
||||
url: String,
|
||||
},
|
||||
}
|
||||
// filebrowser:exists,bitcoind:running:foo+bar+baz
|
||||
impl FromStr for DependencyRequirement {
|
||||
type Err = Error;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s.split_once(':') {
|
||||
Some((id, "e")) | Some((id, "exists")) => Ok(Self {
|
||||
Some((id, "e")) | Some((id, "exists")) => Ok(Self::Exists {
|
||||
id: id.parse()?,
|
||||
kind: DependencyKind::Exists,
|
||||
health_checks: BTreeSet::new(),
|
||||
url: "".to_string(),
|
||||
version_spec: "*".to_string(),
|
||||
}),
|
||||
Some((id, rest)) => {
|
||||
let health_checks = match rest.split_once(":") {
|
||||
let health_checks = match rest.split_once(':') {
|
||||
Some(("r", rest)) | Some(("running", rest)) => rest
|
||||
.split('+')
|
||||
.map(|id| id.parse().map_err(Error::from))
|
||||
@@ -1107,16 +1136,18 @@ impl FromStr for DependencyRequirement {
|
||||
)),
|
||||
},
|
||||
}?;
|
||||
Ok(Self {
|
||||
Ok(Self::Running {
|
||||
id: id.parse()?,
|
||||
kind: DependencyKind::Running,
|
||||
health_checks,
|
||||
url: "".to_string(),
|
||||
version_spec: "*".to_string(),
|
||||
})
|
||||
}
|
||||
None => Ok(Self {
|
||||
None => Ok(Self::Running {
|
||||
id: s.parse()?,
|
||||
kind: DependencyKind::Running,
|
||||
health_checks: BTreeSet::new(),
|
||||
url: "".to_string(),
|
||||
version_spec: "*".to_string(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
@@ -1148,23 +1179,19 @@ async fn set_dependencies(
|
||||
let dependencies = CurrentDependencies(
|
||||
dependencies
|
||||
.into_iter()
|
||||
.map(
|
||||
|DependencyRequirement {
|
||||
id,
|
||||
kind,
|
||||
health_checks,
|
||||
}| {
|
||||
(
|
||||
id,
|
||||
match kind {
|
||||
DependencyKind::Exists => CurrentDependencyInfo::Exists,
|
||||
DependencyKind::Running => {
|
||||
CurrentDependencyInfo::Running { health_checks }
|
||||
}
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
.map(|dependency| match dependency {
|
||||
DependencyRequirement::Exists {
|
||||
id,
|
||||
url,
|
||||
version_spec,
|
||||
} => (id, CurrentDependencyInfo::Exists),
|
||||
DependencyRequirement::Running {
|
||||
id,
|
||||
health_checks,
|
||||
url,
|
||||
version_spec,
|
||||
} => (id, CurrentDependencyInfo::Running { health_checks }),
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
for (dep, entry) in db.as_public_mut().as_package_data_mut().as_entries_mut()? {
|
||||
|
||||
18
sdk/lib/Dependency.ts
Normal file
18
sdk/lib/Dependency.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Checker } from "./emverLite/mod"
|
||||
|
||||
export class Dependency {
|
||||
constructor(
|
||||
readonly data:
|
||||
| {
|
||||
type: "running"
|
||||
versionSpec: Checker
|
||||
url: string
|
||||
healthChecks: string[]
|
||||
}
|
||||
| {
|
||||
type: "exists"
|
||||
versionSpec: Checker
|
||||
url: string
|
||||
},
|
||||
) {}
|
||||
}
|
||||
@@ -23,7 +23,6 @@ import {
|
||||
PackageId,
|
||||
EnsureStorePath,
|
||||
ExtractStore,
|
||||
DaemonReturned,
|
||||
ValidIfNoStupidEscape,
|
||||
} from "./types"
|
||||
import * as patterns from "./util/patterns"
|
||||
@@ -50,7 +49,11 @@ import { Uninstall, UninstallFn, setupUninstall } from "./inits/setupUninstall"
|
||||
import { setupMain } from "./mainFn"
|
||||
import { defaultTrigger } from "./trigger/defaultTrigger"
|
||||
import { changeOnFirstSuccess, cooldownTrigger } from "./trigger"
|
||||
import setupConfig, { Read, Save } from "./config/setupConfig"
|
||||
import setupConfig, {
|
||||
DependenciesReceipt,
|
||||
Read,
|
||||
Save,
|
||||
} from "./config/setupConfig"
|
||||
import {
|
||||
InterfacesReceipt,
|
||||
SetInterfaces,
|
||||
@@ -72,6 +75,9 @@ import { getStore } from "./store/getStore"
|
||||
import { CommandOptions, MountOptions, Overlay } from "./util/Overlay"
|
||||
import { splitCommand } from "./util/splitCommand"
|
||||
import { Mounts } from "./mainFn/Mounts"
|
||||
import { Dependency } from "./Dependency"
|
||||
import * as T from "./types"
|
||||
import { Checker, EmVer } from "./emverLite/mod"
|
||||
|
||||
// prettier-ignore
|
||||
type AnyNeverCond<T extends any[], Then, Else> =
|
||||
@@ -104,6 +110,20 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
}
|
||||
|
||||
build(isReady: AnyNeverCond<[Manifest, Store], "Build not ready", true>) {
|
||||
type DependencyType = {
|
||||
[K in keyof {
|
||||
[K in keyof Manifest["dependencies"]]: Manifest["dependencies"][K]["optional"] extends false
|
||||
? K
|
||||
: never
|
||||
}]: Dependency
|
||||
} & {
|
||||
[K in keyof {
|
||||
[K in keyof Manifest["dependencies"]]: Manifest["dependencies"][K]["optional"] extends true
|
||||
? K
|
||||
: never
|
||||
}]?: Dependency
|
||||
}
|
||||
|
||||
return {
|
||||
serviceInterface: {
|
||||
getOwn: <E extends Effects>(effects: E, id: ServiceInterfaceId) =>
|
||||
@@ -184,7 +204,8 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
| Config<any, never>,
|
||||
Type extends Record<string, any> = ExtractConfigType<ConfigType>,
|
||||
>(
|
||||
metaData: Omit<ActionMetadata, "input"> & {
|
||||
id: string,
|
||||
metadata: Omit<ActionMetadata, "input"> & {
|
||||
input: Config<Type, Store> | Config<Type, never>
|
||||
},
|
||||
fn: (options: {
|
||||
@@ -192,8 +213,13 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
input: Type
|
||||
}) => Promise<ActionResult>,
|
||||
) => {
|
||||
const { input, ...rest } = metaData
|
||||
return createAction<Manifest, Store, ConfigType, Type>(rest, fn, input)
|
||||
const { input, ...rest } = metadata
|
||||
return createAction<Manifest, Store, ConfigType, Type>(
|
||||
id,
|
||||
rest,
|
||||
fn,
|
||||
input,
|
||||
)
|
||||
},
|
||||
getSystemSmtp: <E extends Effects>(effects: E) =>
|
||||
removeConstType<E>()(new GetSystemSmtp(effects)),
|
||||
@@ -205,16 +231,7 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
mounts?: { path: string; options: MountOptions }[]
|
||||
},
|
||||
): Promise<{ stdout: string | Buffer; stderr: string | Buffer }> => {
|
||||
const commands = splitCommand(command)
|
||||
const overlay = await Overlay.of(effects, imageId)
|
||||
try {
|
||||
for (let mount of options.mounts || []) {
|
||||
await overlay.mount(mount.options, mount.path)
|
||||
}
|
||||
return await overlay.exec(commands)
|
||||
} finally {
|
||||
await overlay.destroy()
|
||||
}
|
||||
return runCommand<Manifest>(effects, imageId, command, options)
|
||||
},
|
||||
|
||||
createDynamicAction: <
|
||||
@@ -224,7 +241,8 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
| Config<any, never>,
|
||||
Type extends Record<string, any> = ExtractConfigType<ConfigType>,
|
||||
>(
|
||||
metaData: (options: {
|
||||
id: string,
|
||||
metadata: (options: {
|
||||
effects: Effects
|
||||
}) => MaybePromise<Omit<ActionMetadata, "input">>,
|
||||
fn: (options: {
|
||||
@@ -234,7 +252,8 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
input: Config<Type, Store> | Config<Type, never>,
|
||||
) => {
|
||||
return createAction<Manifest, Store, ConfigType, Type>(
|
||||
metaData,
|
||||
id,
|
||||
metadata,
|
||||
fn,
|
||||
input,
|
||||
)
|
||||
@@ -242,6 +261,11 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
HealthCheck: {
|
||||
of: healthCheck,
|
||||
},
|
||||
Dependency: {
|
||||
of(data: Dependency["data"]) {
|
||||
return new Dependency({ ...data })
|
||||
},
|
||||
},
|
||||
healthCheck: {
|
||||
checkPortListening,
|
||||
checkWebUrl,
|
||||
@@ -284,15 +308,51 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
Store,
|
||||
Input,
|
||||
any
|
||||
>
|
||||
> | null
|
||||
},
|
||||
) => setupDependencyConfig<Store, Input, Manifest>(config, autoConfigs),
|
||||
setupDependencies: <Input extends Record<string, any>>(
|
||||
fn: (options: {
|
||||
effects: Effects
|
||||
input: Input | null
|
||||
}) => Promise<DependencyType>,
|
||||
) => {
|
||||
return async (options: { effects: Effects; input: Input }) => {
|
||||
const dependencyType = await fn(options)
|
||||
return await options.effects.setDependencies({
|
||||
dependencies: Object.entries(dependencyType).map(
|
||||
([
|
||||
id,
|
||||
{
|
||||
data: { versionSpec, ...x },
|
||||
},
|
||||
]) => ({
|
||||
id,
|
||||
...x,
|
||||
...(x.type === "running"
|
||||
? {
|
||||
kind: "running",
|
||||
healthChecks: x.healthChecks,
|
||||
}
|
||||
: {
|
||||
kind: "exists",
|
||||
}),
|
||||
versionSpec: versionSpec.range,
|
||||
}),
|
||||
),
|
||||
})
|
||||
}
|
||||
},
|
||||
setupExports: (fn: SetupExports<Store>) => fn,
|
||||
setupInit: (
|
||||
migrations: Migrations<Manifest, Store>,
|
||||
install: Install<Manifest, Store>,
|
||||
uninstall: Uninstall<Manifest, Store>,
|
||||
setInterfaces: SetInterfaces<Manifest, Store, any, any>,
|
||||
setDependencies: (options: {
|
||||
effects: Effects
|
||||
input: any
|
||||
}) => Promise<DependenciesReceipt>,
|
||||
setupExports: SetupExports<Store>,
|
||||
) =>
|
||||
setupInit<Manifest, Store>(
|
||||
@@ -301,6 +361,7 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
uninstall,
|
||||
setInterfaces,
|
||||
setupExports,
|
||||
setDependencies,
|
||||
),
|
||||
setupInstall: (fn: InstallFn<Manifest, Store>) => Install.of(fn),
|
||||
setupInterfaces: <
|
||||
@@ -355,6 +416,9 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
spec: Spec,
|
||||
) => Config.of<Spec, Store>(spec),
|
||||
},
|
||||
Checker: {
|
||||
parse: Checker.parse,
|
||||
},
|
||||
Daemons: {
|
||||
of(config: {
|
||||
effects: Effects
|
||||
@@ -369,13 +433,17 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
LocalConfig extends Record<string, any>,
|
||||
RemoteConfig extends Record<string, any>,
|
||||
>({
|
||||
localConfig,
|
||||
remoteConfig,
|
||||
localConfigSpec,
|
||||
remoteConfigSpec,
|
||||
dependencyConfig,
|
||||
update,
|
||||
}: {
|
||||
localConfig: Config<LocalConfig, Store> | Config<LocalConfig, never>
|
||||
remoteConfig: Config<RemoteConfig, any> | Config<RemoteConfig, never>
|
||||
localConfigSpec:
|
||||
| Config<LocalConfig, Store>
|
||||
| Config<LocalConfig, never>
|
||||
remoteConfigSpec:
|
||||
| Config<RemoteConfig, any>
|
||||
| Config<RemoteConfig, never>
|
||||
dependencyConfig: (options: {
|
||||
effects: Effects
|
||||
localConfig: LocalConfig
|
||||
@@ -390,6 +458,10 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
>(dependencyConfig, update)
|
||||
},
|
||||
},
|
||||
EmVer: {
|
||||
from: EmVer.from,
|
||||
parse: EmVer.parse,
|
||||
},
|
||||
List: {
|
||||
text: List.text,
|
||||
number: List.number,
|
||||
@@ -654,3 +726,23 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function runCommand<Manifest extends SDKManifest>(
|
||||
effects: Effects,
|
||||
imageId: Manifest["images"][number],
|
||||
command: string | [string, ...string[]],
|
||||
options: CommandOptions & {
|
||||
mounts?: { path: string; options: MountOptions }[]
|
||||
},
|
||||
): Promise<{ stdout: string | Buffer; stderr: string | Buffer }> {
|
||||
const commands = splitCommand(command)
|
||||
const overlay = await Overlay.of(effects, imageId)
|
||||
try {
|
||||
for (let mount of options.mounts || []) {
|
||||
await overlay.mount(mount.options, mount.path)
|
||||
}
|
||||
return await overlay.exec(commands)
|
||||
} finally {
|
||||
await overlay.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@ export class CreatedAction<
|
||||
Type extends Record<string, any> = ExtractConfigType<ConfigType>,
|
||||
> {
|
||||
private constructor(
|
||||
public readonly myMetaData: MaybeFn<
|
||||
public readonly id: string,
|
||||
public readonly myMetadata: MaybeFn<
|
||||
Manifest,
|
||||
Store,
|
||||
Omit<ActionMetadata, "input">
|
||||
@@ -37,12 +38,14 @@ export class CreatedAction<
|
||||
| Config<any, never>,
|
||||
Type extends Record<string, any> = ExtractConfigType<ConfigType>,
|
||||
>(
|
||||
metaData: MaybeFn<Manifest, Store, Omit<ActionMetadata, "input">>,
|
||||
id: string,
|
||||
metadata: MaybeFn<Manifest, Store, Omit<ActionMetadata, "input">>,
|
||||
fn: (options: { effects: Effects; input: Type }) => Promise<ActionResult>,
|
||||
inputConfig: Config<Type, Store> | Config<Type, never>,
|
||||
) {
|
||||
return new CreatedAction<Manifest, Store, ConfigType, Type>(
|
||||
metaData,
|
||||
id,
|
||||
metadata,
|
||||
fn,
|
||||
inputConfig as Config<Type, Store>,
|
||||
)
|
||||
@@ -62,15 +65,15 @@ export class CreatedAction<
|
||||
})
|
||||
}
|
||||
|
||||
async metaData(options: { effects: Effects }) {
|
||||
if (this.myMetaData instanceof Function)
|
||||
return await this.myMetaData(options)
|
||||
return this.myMetaData
|
||||
async metadata(options: { effects: Effects }) {
|
||||
if (this.myMetadata instanceof Function)
|
||||
return await this.myMetadata(options)
|
||||
return this.myMetadata
|
||||
}
|
||||
|
||||
async ActionMetadata(options: { effects: Effects }): Promise<ActionMetadata> {
|
||||
return {
|
||||
...(await this.metaData(options)),
|
||||
...(await this.metadata(options)),
|
||||
input: await this.input.build(options),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { SDKManifest } from "../manifest/ManifestTypes"
|
||||
import { Effects, ExpectedExports } from "../types"
|
||||
import { once } from "../util/once"
|
||||
import { CreatedAction } from "./createAction"
|
||||
|
||||
export function setupActions<Manifest extends SDKManifest, Store>(
|
||||
@@ -9,8 +8,7 @@ export function setupActions<Manifest extends SDKManifest, Store>(
|
||||
const myActions = async (options: { effects: Effects }) => {
|
||||
const actions: Record<string, CreatedAction<Manifest, Store, any>> = {}
|
||||
for (const action of createdActions) {
|
||||
const actionMetadata = await action.metaData(options)
|
||||
actions[actionMetadata.id] = action
|
||||
actions[action.id] = action
|
||||
}
|
||||
return actions
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ export function setupDependencyConfig<
|
||||
Store,
|
||||
Input,
|
||||
any
|
||||
>
|
||||
> | null
|
||||
},
|
||||
): ExpectedExports.dependencyConfig {
|
||||
return autoConfigs
|
||||
|
||||
@@ -163,7 +163,7 @@ export class EmVer {
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `${this.values.join(".")}${this.extra ? `-${this.extra}` : ""}`
|
||||
return `${this.values.join(".")}${this.extra ? `-${this.extra}` : ""}` as ValidEmVer
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,6 +179,7 @@ export class Checker {
|
||||
* @returns
|
||||
*/
|
||||
static parse(range: string | Checker): Checker {
|
||||
console.log(`Parser (${range})`)
|
||||
if (range instanceof Checker) {
|
||||
return range
|
||||
}
|
||||
@@ -193,10 +194,12 @@ export class Checker {
|
||||
return new Checker((version) => {
|
||||
EmVer.from(version)
|
||||
return true
|
||||
})
|
||||
}, range)
|
||||
}
|
||||
if (range.startsWith("!!")) return Checker.parse(range.substring(2))
|
||||
if (range.startsWith("!")) {
|
||||
return Checker.parse(range.substring(1)).not()
|
||||
const tempValue = Checker.parse(range.substring(1))
|
||||
return new Checker((x) => !tempValue.check(x), range)
|
||||
}
|
||||
const starSubMatches = starSub.exec(range)
|
||||
if (starSubMatches != null) {
|
||||
@@ -210,7 +213,7 @@ export class Checker {
|
||||
!v.greaterThan(emVarUpper) &&
|
||||
!v.equals(emVarUpper)
|
||||
)
|
||||
})
|
||||
}, range)
|
||||
}
|
||||
|
||||
switch (range.substring(0, 2)) {
|
||||
@@ -219,14 +222,14 @@ export class Checker {
|
||||
return new Checker((version) => {
|
||||
const v = EmVer.from(version)
|
||||
return v.greaterThanOrEqual(emVar)
|
||||
})
|
||||
}, range)
|
||||
}
|
||||
case "<=": {
|
||||
const emVar = EmVer.parse(range.substring(2))
|
||||
return new Checker((version) => {
|
||||
const v = EmVer.from(version)
|
||||
return v.lessThanOrEqual(emVar)
|
||||
})
|
||||
}, range)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,21 +239,21 @@ export class Checker {
|
||||
return new Checker((version) => {
|
||||
const v = EmVer.from(version)
|
||||
return v.greaterThan(emVar)
|
||||
})
|
||||
}, range)
|
||||
}
|
||||
case "<": {
|
||||
const emVar = EmVer.parse(range.substring(1))
|
||||
return new Checker((version) => {
|
||||
const v = EmVer.from(version)
|
||||
return v.lessThan(emVar)
|
||||
})
|
||||
}, range)
|
||||
}
|
||||
case "=": {
|
||||
const emVar = EmVer.parse(range.substring(1))
|
||||
return new Checker((version) => {
|
||||
const v = EmVer.from(version)
|
||||
return v.equals(emVar)
|
||||
})
|
||||
}, `=${emVar.toString()}`)
|
||||
}
|
||||
}
|
||||
throw new Error("Couldn't parse range: " + range)
|
||||
@@ -261,40 +264,53 @@ export class Checker {
|
||||
* a pattern
|
||||
*/
|
||||
public readonly check: (value: ValidEmVer | EmVer) => boolean,
|
||||
private readonly _range: string,
|
||||
) {}
|
||||
|
||||
get range() {
|
||||
return this._range as ValidEmVerRange
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when we want the `and` condition with another checker
|
||||
*/
|
||||
public and(...others: (Checker | string)[]): Checker {
|
||||
return new Checker((value) => {
|
||||
if (!this.check(value)) {
|
||||
return false
|
||||
}
|
||||
for (const other of others) {
|
||||
if (!Checker.parse(other).check(value)) {
|
||||
const othersCheck = others.map(Checker.parse)
|
||||
return new Checker(
|
||||
(value) => {
|
||||
if (!this.check(value)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
for (const other of othersCheck) {
|
||||
if (!other.check(value)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
othersCheck.map((x) => x._range).join(" && "),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when we want the `or` condition with another checker
|
||||
*/
|
||||
public or(...others: (Checker | string)[]): Checker {
|
||||
return new Checker((value) => {
|
||||
if (this.check(value)) {
|
||||
return true
|
||||
}
|
||||
for (const other of others) {
|
||||
if (Checker.parse(other).check(value)) {
|
||||
const othersCheck = others.map(Checker.parse)
|
||||
return new Checker(
|
||||
(value) => {
|
||||
if (this.check(value)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
for (const other of othersCheck) {
|
||||
if (other.check(value)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
},
|
||||
othersCheck.map((x) => x._range).join(" || "),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -302,6 +318,7 @@ export class Checker {
|
||||
* @returns
|
||||
*/
|
||||
public not(): Checker {
|
||||
return new Checker((value) => !this.check(value))
|
||||
let newRange = `!${this._range}`
|
||||
return Checker.parse(newRange)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ export * as config from "./config"
|
||||
export * as configBuilder from "./config/builder"
|
||||
export * as configTypes from "./config/configTypes"
|
||||
export * as dependencyConfig from "./dependencyConfig"
|
||||
export * as daemons from "./mainFn/Daemons"
|
||||
export * as health from "./health"
|
||||
export * as healthFns from "./health/checkFns"
|
||||
export * as inits from "./inits"
|
||||
@@ -17,9 +18,10 @@ export * as mainFn from "./mainFn"
|
||||
export * as manifest from "./manifest"
|
||||
export * as toml from "@iarna/toml"
|
||||
export * as types from "./types"
|
||||
export * as util from "./util"
|
||||
export * as T from "./types"
|
||||
export * as yaml from "yaml"
|
||||
|
||||
export * as startSdk from "./StartSdk"
|
||||
export * as utils from "./util"
|
||||
export * as matches from "ts-matches"
|
||||
export * as YAML from "yaml"
|
||||
export * as TOML from "@iarna/toml"
|
||||
|
||||
@@ -3,11 +3,11 @@ import { Effects, ExposeServicePaths, ExposeUiPaths } from "../types"
|
||||
export type SetupExports<Store> = (opts: { effects: Effects }) =>
|
||||
| {
|
||||
ui: { [k: string]: ExposeUiPaths<Store> }
|
||||
services: ExposeServicePaths<Store>
|
||||
services: ExposeServicePaths<Store>["paths"]
|
||||
}
|
||||
| Promise<{
|
||||
ui: { [k: string]: ExposeUiPaths<Store> }
|
||||
services: ExposeServicePaths<Store>
|
||||
services: ExposeServicePaths<Store>["paths"]
|
||||
}>
|
||||
|
||||
export const setupExports = <Store>(fn: (opts: SetupExports<Store>) => void) =>
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import { DependenciesReceipt } from "../config/setupConfig"
|
||||
import { SetInterfaces } from "../interfaces/setupInterfaces"
|
||||
import { SDKManifest } from "../manifest/ManifestTypes"
|
||||
import { ExpectedExports, ExposeUiPaths, ExposeUiPathsAll } from "../types"
|
||||
import {
|
||||
Effects,
|
||||
ExpectedExports,
|
||||
ExposeUiPaths,
|
||||
ExposeUiPathsAll,
|
||||
} from "../types"
|
||||
import { Migrations } from "./migrations/setupMigrations"
|
||||
import { SetupExports } from "./setupExports"
|
||||
import { Install } from "./setupInstall"
|
||||
@@ -12,6 +18,10 @@ export function setupInit<Manifest extends SDKManifest, Store>(
|
||||
uninstall: Uninstall<Manifest, Store>,
|
||||
setInterfaces: SetInterfaces<Manifest, Store, any, any>,
|
||||
setupExports: SetupExports<Store>,
|
||||
setDependencies: (options: {
|
||||
effects: Effects
|
||||
input: any
|
||||
}) => Promise<DependenciesReceipt>,
|
||||
): {
|
||||
init: ExpectedExports.init
|
||||
uninit: ExpectedExports.uninit
|
||||
@@ -25,8 +35,9 @@ export function setupInit<Manifest extends SDKManifest, Store>(
|
||||
input: null,
|
||||
})
|
||||
const { services, ui } = await setupExports(opts)
|
||||
await opts.effects.exposeForDependents(services)
|
||||
await opts.effects.exposeForDependents({ paths: services })
|
||||
await opts.effects.exposeUi(forExpose(ui))
|
||||
await setDependencies({ effects: opts.effects, input: null })
|
||||
},
|
||||
uninit: async (opts) => {
|
||||
await migrations.uninit(opts)
|
||||
|
||||
@@ -43,7 +43,7 @@ type Daemon<
|
||||
|
||||
type ErrorDuplicateId<Id extends string> = `The id '${Id}' is already used`
|
||||
|
||||
const runDaemon =
|
||||
export const runDaemon =
|
||||
<Manifest extends SDKManifest>() =>
|
||||
async <A extends string>(
|
||||
effects: Effects,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { ValidEmVer } from "../emverLite/mod"
|
||||
import { ActionMetadata } from "../types"
|
||||
|
||||
export interface Container {
|
||||
/** This should be pointing to a docker container name */
|
||||
@@ -75,31 +74,13 @@ export type SDKManifest = {
|
||||
}
|
||||
|
||||
export interface ManifestDependency {
|
||||
/** The range of versions that would satisfy the dependency
|
||||
*
|
||||
* ie: >=3.4.5 <4.0.0
|
||||
*/
|
||||
version: string
|
||||
/**
|
||||
* A human readable explanation on what the dependency is used for
|
||||
*/
|
||||
description: string | null
|
||||
requirement:
|
||||
| {
|
||||
type: "opt-in"
|
||||
/**
|
||||
* The human readable explanation on how to opt-in to the dependency
|
||||
*/
|
||||
how: string
|
||||
}
|
||||
| {
|
||||
type: "opt-out"
|
||||
/**
|
||||
* The human readable explanation on how to opt-out to the dependency
|
||||
*/
|
||||
how: string
|
||||
}
|
||||
| {
|
||||
type: "required"
|
||||
}
|
||||
/**
|
||||
* Determines if the dependency is optional or not. Times that optional that are good include such situations
|
||||
* such as being able to toggle other services or to use a different service for the same purpose.
|
||||
*/
|
||||
optional: boolean
|
||||
}
|
||||
|
||||
@@ -414,8 +414,7 @@ describe("values", () => {
|
||||
dependencies: {
|
||||
remoteTest: {
|
||||
description: "",
|
||||
requirement: { how: "", type: "opt-in" },
|
||||
version: "1.0",
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
||||
@@ -35,8 +35,7 @@ export const sdk = StartSdk.of()
|
||||
dependencies: {
|
||||
remoteTest: {
|
||||
description: "",
|
||||
requirement: { how: "", type: "opt-in" },
|
||||
version: "1.0",
|
||||
optional: false,
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
||||
@@ -16,8 +16,8 @@ describe("setupDependencyConfig", () => {
|
||||
}),
|
||||
})
|
||||
const remoteTest = sdk.DependencyConfig.of({
|
||||
localConfig: testConfig,
|
||||
remoteConfig: testConfig2,
|
||||
localConfigSpec: testConfig,
|
||||
remoteConfigSpec: testConfig2,
|
||||
dependencyConfig: async ({}) => {},
|
||||
})
|
||||
sdk.setupDependencyConfig(testConfig, {
|
||||
|
||||
@@ -7,6 +7,8 @@ import { BindOptions, Scheme } from "./interfaces/Host"
|
||||
import { Daemons } from "./mainFn/Daemons"
|
||||
import { UrlString } from "./util/getServiceInterface"
|
||||
|
||||
export { SDKManifest } from "./manifest/ManifestTypes"
|
||||
|
||||
export type ExportedAction = (options: {
|
||||
effects: Effects
|
||||
input?: Record<string, unknown>
|
||||
@@ -90,7 +92,7 @@ export namespace ExpectedExports {
|
||||
/** Auto configure is used to make sure that other dependencies have the values t
|
||||
* that this service could use.
|
||||
*/
|
||||
export type dependencyConfig = Record<PackageId, DependencyConfig>
|
||||
export type dependencyConfig = Record<PackageId, DependencyConfig | null>
|
||||
}
|
||||
export type TimeMs = number
|
||||
export type VersionString = string
|
||||
@@ -161,9 +163,10 @@ export type DaemonReturned = {
|
||||
export type ActionMetadata = {
|
||||
name: string
|
||||
description: string
|
||||
id: string
|
||||
warning: string | null
|
||||
input: InputSpec
|
||||
allowedStatuses: "only-running" | "only-stopped" | "any" | "disabled"
|
||||
disabled: boolean
|
||||
allowedStatuses: "only-running" | "only-stopped" | "any"
|
||||
/**
|
||||
* So the ordering of the actions is by alphabetical order of the group, then followed by the alphabetical of the actions
|
||||
*/
|
||||
@@ -441,7 +444,7 @@ export type Effects = {
|
||||
*
|
||||
* @param options
|
||||
*/
|
||||
exportAction(options: ActionMetadata): Promise<void>
|
||||
exportAction(options: { id: string; metadata: ActionMetadata }): Promise<void>
|
||||
/**
|
||||
* Remove an action that was exported. Used problably during main or during setConfig.
|
||||
*/
|
||||
@@ -598,7 +601,8 @@ export type KnownError =
|
||||
|
||||
export type Dependency = {
|
||||
id: PackageId
|
||||
kind: DependencyKind
|
||||
versionSpec: string
|
||||
url: string
|
||||
} & ({ kind: "exists" } | { kind: "running"; healthChecks: string[] })
|
||||
export type Dependencies = Array<Dependency>
|
||||
|
||||
|
||||
@@ -7,8 +7,9 @@ import "./deepEqual"
|
||||
import "./deepMerge"
|
||||
import "./Overlay"
|
||||
import "./once"
|
||||
import { SDKManifest } from "../manifest/ManifestTypes"
|
||||
|
||||
export { GetServiceInterface, getServiceInterface } from "./getServiceInterface"
|
||||
export { getServiceInterfaces } from "./getServiceInterfaces"
|
||||
// prettier-ignore
|
||||
export type FlattenIntersection<T> =
|
||||
T extends ArrayLike<any> ? T :
|
||||
@@ -28,3 +29,5 @@ export type NoAny<A> = NeverPossible extends A
|
||||
? never
|
||||
: A
|
||||
: A
|
||||
|
||||
export { getDefaultString } from "./getDefaultString"
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { arrayOf, string } from "ts-matches"
|
||||
import { ValidIfNoStupidEscape } from "../types"
|
||||
|
||||
export const splitCommand = <A>(
|
||||
command: ValidIfNoStupidEscape<A> | [string, ...string[]],
|
||||
export const splitCommand = (
|
||||
command: string | [string, ...string[]],
|
||||
): string[] => {
|
||||
if (arrayOf(string).test(command)) return command
|
||||
return String(command)
|
||||
|
||||
9
system-images/compat/Cargo.lock
generated
9
system-images/compat/Cargo.lock
generated
@@ -2143,15 +2143,6 @@ dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "id-pool"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8d0df4d8a768821ee4aa2e0353f67125c4586f0e13adbf95b8ebbf8d8fdb344"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
|
||||
7001
web/package-lock.json
generated
7001
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -73,7 +73,7 @@
|
||||
"monaco-editor": "^0.33.0",
|
||||
"mustache": "^4.2.0",
|
||||
"ng-qrcode": "^17.0.0",
|
||||
"node-jose": "^2.1.1",
|
||||
"node-jose": "^2.2.0",
|
||||
"patch-db-client": "file:../patch-db/client",
|
||||
"pbkdf2": "^3.1.2",
|
||||
"rxjs": "^7.5.6",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<!-- color background -->
|
||||
<div class="background">
|
||||
<img
|
||||
[src]="pkg | mimeType | trustUrl"
|
||||
[src]="pkg.icon| trustUrl"
|
||||
alt="{{ pkg.manifest.title }} Icon"
|
||||
/>
|
||||
</div>
|
||||
@@ -10,7 +10,7 @@
|
||||
<div class="overlay"></div>
|
||||
<!-- icon -->
|
||||
<img
|
||||
[src]="pkg | mimeType | trustUrl"
|
||||
[src]="pkg.icon | trustUrl"
|
||||
class="icon box-shadow-lg"
|
||||
alt="{{ pkg.manifest.title }} Icon"
|
||||
/>
|
||||
|
||||
@@ -3,11 +3,10 @@ import { NgModule } from '@angular/core'
|
||||
import { RouterModule } from '@angular/router'
|
||||
import { SharedPipesModule } from '@start9labs/shared'
|
||||
import { ItemComponent } from './item.component'
|
||||
import { MimeTypePipeModule } from '../../../pipes/mime-type.pipe'
|
||||
|
||||
@NgModule({
|
||||
declarations: [ItemComponent],
|
||||
exports: [ItemComponent],
|
||||
imports: [CommonModule, RouterModule, SharedPipesModule, MimeTypePipeModule],
|
||||
imports: [CommonModule, RouterModule, SharedPipesModule],
|
||||
})
|
||||
export class ItemModule {}
|
||||
|
||||
@@ -1,22 +1,19 @@
|
||||
<div class="outer-container">
|
||||
<div class="inner-container">
|
||||
<tui-avatar class="dep-img" [src]="getImage(dep.key)"></tui-avatar>
|
||||
<tui-avatar class="dep-img" [src]="pkg['dependency-metadata'][dep.key].icon"></tui-avatar>
|
||||
<div class="wrapper-margin">
|
||||
<div class="inner-container-title">
|
||||
<span>
|
||||
{{ getTitle(dep.key) }}
|
||||
{{ pkg['dependency-metadata'][dep.key].title || dep.key }}
|
||||
</span>
|
||||
<p>
|
||||
<ng-container [ngSwitch]="dep.value.requirement.type">
|
||||
<span *ngSwitchCase="'required'">(required)</span>
|
||||
<span *ngSwitchCase="'opt-out'">(required by default)</span>
|
||||
<span *ngSwitchCase="'opt-in'">(optional)</span>
|
||||
</ng-container>
|
||||
@if (dep.value.optional) {
|
||||
<span>(optional)</span>
|
||||
} @else {
|
||||
<span>(required)</span>
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
<span class="inner-container-version">
|
||||
{{ dep.value.version | displayEmver }}
|
||||
</span>
|
||||
<span class="inner-container-description">
|
||||
{{ dep.value.description }}
|
||||
</span>
|
||||
|
||||
@@ -36,16 +36,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
&-version {
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
color: rgb(250 250 250 / 0.7);
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 1;
|
||||
}
|
||||
|
||||
&-description {
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
|
||||
@@ -14,14 +14,4 @@ export class DependenciesComponent {
|
||||
|
||||
@Input({ required: true })
|
||||
dep!: KeyValue<string, Dependency>
|
||||
|
||||
getImage(key: string): string {
|
||||
const icon = this.pkg['dependency-metadata'][key]?.icon
|
||||
// @TODO fix when registry api is updated to include mimetype in icon url
|
||||
return icon ? `data:image/png;base64,${icon}` : key.substring(0, 2)
|
||||
}
|
||||
|
||||
getTitle(key: string): string {
|
||||
return this.pkg['dependency-metadata'][key]?.title || key
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
import { NgModule, Pipe, PipeTransform } from '@angular/core'
|
||||
import { MarketplacePkg } from '../types'
|
||||
|
||||
@Pipe({
|
||||
name: 'mimeType',
|
||||
})
|
||||
export class MimeTypePipe implements PipeTransform {
|
||||
transform(pkg: MarketplacePkg): string {
|
||||
if (pkg.icon.startsWith('data:')) return pkg.icon
|
||||
|
||||
if (pkg.manifest.assets.icon) {
|
||||
switch (pkg.manifest.assets.icon.split('.').pop()) {
|
||||
case 'png':
|
||||
return `data:image/png;base64,${pkg.icon}`
|
||||
case 'jpeg':
|
||||
case 'jpg':
|
||||
return `data:image/jpeg;base64,${pkg.icon}`
|
||||
case 'gif':
|
||||
return `data:image/gif;base64,${pkg.icon}`
|
||||
case 'svg':
|
||||
return `data:image/svg+xml;base64,${pkg.icon}`
|
||||
default:
|
||||
return `data:image/png;base64,${pkg.icon}`
|
||||
}
|
||||
}
|
||||
return `data:image/png;base64,${pkg.icon}`
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
declarations: [MimeTypePipe],
|
||||
exports: [MimeTypePipe],
|
||||
})
|
||||
export class MimeTypePipeModule {}
|
||||
@@ -20,7 +20,6 @@ export * from './pages/show/screenshots/screenshots.component'
|
||||
export * from './pages/show/hero/hero.component'
|
||||
|
||||
export * from './pipes/filter-packages.pipe'
|
||||
export * from './pipes/mime-type.pipe'
|
||||
|
||||
export * from './components/store-icon/store-icon.component'
|
||||
export * from './components/store-icon/store-icon.component.module'
|
||||
|
||||
@@ -38,6 +38,7 @@ export interface MarketplacePkg {
|
||||
export interface DependencyMetadata {
|
||||
title: string
|
||||
icon: Url
|
||||
optional: boolean
|
||||
hidden: boolean
|
||||
}
|
||||
|
||||
@@ -50,9 +51,6 @@ export interface Manifest {
|
||||
short: string
|
||||
long: string
|
||||
}
|
||||
assets: {
|
||||
icon: Url // filename
|
||||
}
|
||||
replaces?: string[]
|
||||
'release-notes': string
|
||||
license: string // name of license
|
||||
@@ -70,21 +68,10 @@ export interface Manifest {
|
||||
}
|
||||
dependencies: Record<string, Dependency>
|
||||
'os-version': string
|
||||
'has-config': boolean
|
||||
}
|
||||
|
||||
export interface Dependency {
|
||||
version: string
|
||||
requirement:
|
||||
| {
|
||||
type: 'opt-in'
|
||||
how: string
|
||||
}
|
||||
| {
|
||||
type: 'opt-out'
|
||||
how: string
|
||||
}
|
||||
| {
|
||||
type: 'required'
|
||||
}
|
||||
description: string | null
|
||||
optional: boolean
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ export class ServiceInterfaceRoute {
|
||||
readonly interfaceInfo$ = inject(PatchDB<DataModel>).watch$(
|
||||
'package-data',
|
||||
this.context.packageId,
|
||||
'installed',
|
||||
'state-info',
|
||||
'interfaceInfo',
|
||||
this.context.interfaceId,
|
||||
)
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core'
|
||||
import { InstallProgress } from 'src/app/services/patch-db/data-model'
|
||||
import { packageLoadingProgress } from 'src/app/util/package-loading-progress'
|
||||
import { Progress } from 'src/app/services/patch-db/data-model'
|
||||
|
||||
@Pipe({
|
||||
name: 'installProgress',
|
||||
standalone: true,
|
||||
})
|
||||
export class InstallProgressPipe implements PipeTransform {
|
||||
transform(installProgress?: InstallProgress): number {
|
||||
return packageLoadingProgress(installProgress)?.totalProgress || 0
|
||||
export class InstallingProgressDisplayPipe implements PipeTransform {
|
||||
transform(progress: Progress): string {
|
||||
if (progress === true) return 'finalizing'
|
||||
if (progress === false || !progress.total) return 'unknown %'
|
||||
const percentage = Math.round((100 * progress.done) / progress.total)
|
||||
|
||||
return percentage < 99 ? String(percentage) + '%' : 'finalizing'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,12 +18,12 @@ import {
|
||||
MarketplacePkg,
|
||||
} from '@start9labs/marketplace'
|
||||
import { Log } from '@start9labs/shared'
|
||||
import { unionSelectKey } from '@start9labs/start-sdk/lib/config/configTypes'
|
||||
import { List } from '@start9labs/start-sdk/lib/config/builder/list'
|
||||
import { Value } from '@start9labs/start-sdk/lib/config/builder/value'
|
||||
import { Variants } from '@start9labs/start-sdk/lib/config/builder/variants'
|
||||
import { Config } from '@start9labs/start-sdk/lib/config/builder/config'
|
||||
import { configBuilderToSpec } from 'src/app/util/configBuilderToSpec'
|
||||
import { Config } from '@start9labs/start-sdk/cjs/sdk/lib/config/builder/config'
|
||||
import { Value } from '@start9labs/start-sdk/cjs/sdk/lib/config/builder/value'
|
||||
import { Variants } from '@start9labs/start-sdk/cjs/sdk/lib/config/builder/variants'
|
||||
import { List } from '@start9labs/start-sdk/cjs/sdk/lib/config/builder/list'
|
||||
import { unionSelectKey } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
||||
|
||||
export module Mock {
|
||||
export const ServerUpdated: ServerStatusInfo = {
|
||||
@@ -67,9 +67,6 @@ export module Mock {
|
||||
short: 'A Bitcoin full node by Bitcoin Core.',
|
||||
long: 'Bitcoin is a decentralized consensus protocol and settlement network.',
|
||||
},
|
||||
assets: {
|
||||
icon: 'icon.png',
|
||||
},
|
||||
replaces: ['banks', 'governments'],
|
||||
'release-notes': 'Taproot, Schnorr, and more.',
|
||||
license: 'MIT',
|
||||
@@ -86,8 +83,9 @@ export module Mock {
|
||||
start: 'Starting Bitcoin is good for your health.',
|
||||
stop: null,
|
||||
},
|
||||
'os-version': '0.2.12',
|
||||
dependencies: {},
|
||||
'os-version': '0.4.0',
|
||||
'has-config': true,
|
||||
}
|
||||
|
||||
export const MockManifestLnd: Manifest = {
|
||||
@@ -98,11 +96,7 @@ export module Mock {
|
||||
short: 'A bolt spec compliant client.',
|
||||
long: 'More info about LND. More info about LND. More info about LND.',
|
||||
},
|
||||
assets: {
|
||||
icon: 'icon.png',
|
||||
},
|
||||
'release-notes':
|
||||
'* Dual funded channels! And lots more amazing new features. Also includes several bugfixes and performance enhancements.',
|
||||
'release-notes': 'Dual funded channels!',
|
||||
license: 'MIT',
|
||||
'wrapper-repo': 'https://github.com/start9labs/lnd-wrapper',
|
||||
'upstream-repo': 'https://github.com/lightningnetwork/lnd',
|
||||
@@ -117,26 +111,19 @@ export module Mock {
|
||||
start: 'Starting LND is good for your health.',
|
||||
stop: null,
|
||||
},
|
||||
'os-version': '0.2.12',
|
||||
dependencies: {
|
||||
bitcoind: {
|
||||
version: '=0.21.0',
|
||||
description: 'LND needs bitcoin to live.',
|
||||
requirement: {
|
||||
type: 'opt-out',
|
||||
how: 'You can use an external node from your server if you prefer.',
|
||||
},
|
||||
optional: true,
|
||||
},
|
||||
'btc-rpc-proxy': {
|
||||
version: '>=0.2.2',
|
||||
description:
|
||||
'As long as Bitcoin is pruned, LND needs Bitcoin Proxy to fetch block over the P2P network.',
|
||||
requirement: {
|
||||
type: 'opt-in',
|
||||
how: `To use Proxy's user management system, go to LND config and select Bitcoin Proxy under Bitcoin config.`,
|
||||
},
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
'os-version': '0.4.0',
|
||||
'has-config': true,
|
||||
}
|
||||
|
||||
export const MockManifestBitcoinProxy: Manifest = {
|
||||
@@ -148,9 +135,6 @@ export module Mock {
|
||||
short: 'A super charger for your Bitcoin node.',
|
||||
long: 'More info about Bitcoin Proxy. More info about Bitcoin Proxy. More info about Bitcoin Proxy.',
|
||||
},
|
||||
assets: {
|
||||
icon: 'icon.png',
|
||||
},
|
||||
'release-notes': 'Even better support for Bitcoin and wallets!',
|
||||
license: 'MIT',
|
||||
'wrapper-repo': 'https://github.com/start9labs/btc-rpc-proxy-wrapper',
|
||||
@@ -165,27 +149,27 @@ export module Mock {
|
||||
start: null,
|
||||
stop: null,
|
||||
},
|
||||
'os-version': '0.2.12',
|
||||
dependencies: {
|
||||
bitcoind: {
|
||||
version: '>=0.20.0',
|
||||
description: 'Bitcoin Proxy requires a Bitcoin node.',
|
||||
requirement: {
|
||||
type: 'required',
|
||||
},
|
||||
optional: false,
|
||||
},
|
||||
},
|
||||
'os-version': '0.4.0',
|
||||
'has-config': false,
|
||||
}
|
||||
|
||||
export const BitcoinDep: DependencyMetadata = {
|
||||
title: 'Bitcoin Core',
|
||||
icon: BTC_ICON,
|
||||
optional: false,
|
||||
hidden: true,
|
||||
}
|
||||
|
||||
export const ProxyDep: DependencyMetadata = {
|
||||
title: 'Bitcoin Proxy',
|
||||
icon: PROXY_ICON,
|
||||
optional: true,
|
||||
hidden: false,
|
||||
}
|
||||
|
||||
@@ -1292,6 +1276,7 @@ export module Mock {
|
||||
},
|
||||
'dependency-config-errors': {},
|
||||
},
|
||||
actions: {}, // @TODO need mocks
|
||||
'service-interfaces': {
|
||||
ui: {
|
||||
id: 'ui',
|
||||
@@ -1508,11 +1493,6 @@ export module Mock {
|
||||
},
|
||||
},
|
||||
},
|
||||
'current-dependents': {
|
||||
lnd: {
|
||||
'health-checks': [],
|
||||
},
|
||||
},
|
||||
'current-dependencies': {},
|
||||
'dependency-info': {},
|
||||
'marketplace-url': 'https://registry.start9.com/',
|
||||
@@ -1535,6 +1515,7 @@ export module Mock {
|
||||
},
|
||||
'dependency-config-errors': {},
|
||||
},
|
||||
actions: {},
|
||||
'service-interfaces': {
|
||||
ui: {
|
||||
id: 'ui',
|
||||
@@ -1643,13 +1624,9 @@ export module Mock {
|
||||
},
|
||||
},
|
||||
},
|
||||
'current-dependents': {
|
||||
lnd: {
|
||||
'health-checks': [],
|
||||
},
|
||||
},
|
||||
'current-dependencies': {
|
||||
bitcoind: {
|
||||
versionRange: '>=26.0.0',
|
||||
'health-checks': [],
|
||||
},
|
||||
},
|
||||
@@ -1681,6 +1658,7 @@ export module Mock {
|
||||
'btc-rpc-proxy': 'Username not found',
|
||||
},
|
||||
},
|
||||
actions: {},
|
||||
'service-interfaces': {
|
||||
grpc: {
|
||||
id: 'grpc',
|
||||
@@ -1893,12 +1871,13 @@ export module Mock {
|
||||
},
|
||||
},
|
||||
},
|
||||
'current-dependents': {},
|
||||
'current-dependencies': {
|
||||
bitcoind: {
|
||||
versionRange: '>=26.0.0',
|
||||
'health-checks': [],
|
||||
},
|
||||
'btc-rpc-proxy': {
|
||||
versionRange: '>2.0.0', // @TODO
|
||||
'health-checks': [],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Dump, Revision } from 'patch-db-client'
|
||||
import { MarketplacePkg, StoreInfo, Manifest } from '@start9labs/marketplace'
|
||||
import { InputSpec } from '@start9labs/start-sdk/lib/config/configTypes'
|
||||
import {
|
||||
DataModel,
|
||||
DomainInfo,
|
||||
@@ -16,7 +15,8 @@ import {
|
||||
FollowLogsRes,
|
||||
FollowLogsReq,
|
||||
} from '@start9labs/shared'
|
||||
import { customSmtp } from '@start9labs/start-sdk/lib/config/configConstants'
|
||||
import { customSmtp } from '@start9labs/start-sdk/cjs/sdk/lib/config/configConstants'
|
||||
import { InputSpec } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
||||
|
||||
export module RR {
|
||||
// DB
|
||||
@@ -596,8 +596,8 @@ export enum NotificationLevel {
|
||||
export type NotificationData<T> = T extends 0
|
||||
? null
|
||||
: T extends 1
|
||||
? BackupReport
|
||||
: any
|
||||
? BackupReport
|
||||
: any
|
||||
|
||||
export interface BackupReport {
|
||||
server: {
|
||||
|
||||
@@ -866,7 +866,7 @@ export class MockApiService extends ApiService {
|
||||
setTimeout(async () => {
|
||||
for (let i = 0; i < ids.length; i++) {
|
||||
const id = ids[i]
|
||||
const appPath = `/package-data/${id}/installed/status/main/status`
|
||||
const appPath = `/package-data/${id}/status/main/status`
|
||||
const appPatch = [
|
||||
{
|
||||
op: PatchOp.REPLACE,
|
||||
@@ -1032,7 +1032,7 @@ export class MockApiService extends ApiService {
|
||||
const patch = [
|
||||
{
|
||||
op: PatchOp.REPLACE,
|
||||
path: `/package-data/${params.id}/installed/status/configured`,
|
||||
path: `/package-data/${params.id}/status/configured`,
|
||||
value: true,
|
||||
},
|
||||
]
|
||||
@@ -1079,7 +1079,7 @@ export class MockApiService extends ApiService {
|
||||
}
|
||||
|
||||
async startPackage(params: RR.StartPackageReq): Promise<RR.StartPackageRes> {
|
||||
const path = `/package-data/${params.id}/installed/status/main`
|
||||
const path = `/package-data/${params.id}/status/main`
|
||||
|
||||
await pauseFor(2000)
|
||||
|
||||
@@ -1128,7 +1128,7 @@ export class MockApiService extends ApiService {
|
||||
): Promise<RR.RestartPackageRes> {
|
||||
// first enact stop
|
||||
await pauseFor(2000)
|
||||
const path = `/package-data/${params.id}/installed/status/main`
|
||||
const path = `/package-data/${params.id}/status/main`
|
||||
|
||||
setTimeout(async () => {
|
||||
const patch2: Operation<any>[] = [
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { DataModel } from 'src/app/services/patch-db/data-model'
|
||||
import {
|
||||
DataModel,
|
||||
HealthResult,
|
||||
PackageMainStatus,
|
||||
PackageState,
|
||||
} from 'src/app/services/patch-db/data-model'
|
||||
import { Mock } from './api.fixures'
|
||||
|
||||
export const mockPatchData: DataModel = {
|
||||
@@ -31,18 +36,49 @@ export const mockPatchData: DataModel = {
|
||||
id: 'abcdefgh',
|
||||
version: '0.3.5.1',
|
||||
country: 'us',
|
||||
ui: {
|
||||
lanHostname: 'adjective-noun.local',
|
||||
torHostname: 'myveryownspecialtoraddress.onion',
|
||||
ipInfo: {
|
||||
eth0: {
|
||||
wireless: false,
|
||||
ipv4: '10.0.0.1',
|
||||
ipv6: 'FE80:CD00:0000:0CDE:1257:0000:211E:729CD',
|
||||
ui: [
|
||||
{
|
||||
kind: 'ip',
|
||||
networkInterfaceId: 'elan0',
|
||||
public: false,
|
||||
hostname: {
|
||||
kind: 'local',
|
||||
value: 'adjective-noun.local',
|
||||
port: null,
|
||||
sslPort: 1111,
|
||||
},
|
||||
},
|
||||
domainInfo: null,
|
||||
},
|
||||
{
|
||||
kind: 'onion',
|
||||
hostname: {
|
||||
value: 'myveryownspecialtoraddress.onion',
|
||||
port: 80,
|
||||
sslPort: 443,
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: 'ip',
|
||||
networkInterfaceId: 'elan0',
|
||||
public: false,
|
||||
hostname: {
|
||||
kind: 'ipv4',
|
||||
value: '192.168.1.5',
|
||||
port: null,
|
||||
sslPort: 1111,
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: 'ip',
|
||||
networkInterfaceId: 'elan0',
|
||||
public: false,
|
||||
hostname: {
|
||||
kind: 'ipv6',
|
||||
value: '[2001:db8:85a3:8d3:1319:8a2e:370:7348]',
|
||||
port: null,
|
||||
sslPort: 1111,
|
||||
},
|
||||
},
|
||||
],
|
||||
network: {
|
||||
domains: [],
|
||||
start9ToSubdomain: null,
|
||||
@@ -109,11 +145,49 @@ export const mockPatchData: DataModel = {
|
||||
},
|
||||
'package-data': {
|
||||
bitcoind: {
|
||||
...Mock.bitcoind,
|
||||
manifest: {
|
||||
...Mock.bitcoind.manifest,
|
||||
version: '0.19.0',
|
||||
'state-info': {
|
||||
state: PackageState.Installed,
|
||||
manifest: {
|
||||
...Mock.MockManifestBitcoind,
|
||||
version: '0.20.0',
|
||||
},
|
||||
},
|
||||
icon: '/assets/img/service-icons/bitcoind.svg',
|
||||
'last-backup': null,
|
||||
status: {
|
||||
configured: true,
|
||||
main: {
|
||||
status: PackageMainStatus.Running,
|
||||
started: '2021-06-14T20:49:17.774Z',
|
||||
health: {
|
||||
'ephemeral-health-check': {
|
||||
name: 'Ephemeral Health Check',
|
||||
result: HealthResult.Starting,
|
||||
},
|
||||
'chain-state': {
|
||||
name: 'Chain State',
|
||||
result: HealthResult.Loading,
|
||||
message: 'Bitcoin is syncing from genesis',
|
||||
},
|
||||
'p2p-interface': {
|
||||
name: 'P2P',
|
||||
result: HealthResult.Success,
|
||||
message: 'Health check successful',
|
||||
},
|
||||
'rpc-interface': {
|
||||
name: 'RPC',
|
||||
result: HealthResult.Failure,
|
||||
message: 'RPC interface unreachable.',
|
||||
},
|
||||
'unnecessary-health-check': {
|
||||
name: 'Unnecessary Health Check',
|
||||
result: HealthResult.Disabled,
|
||||
},
|
||||
},
|
||||
},
|
||||
'dependency-config-errors': {},
|
||||
},
|
||||
actions: {}, // @TODO
|
||||
'service-interfaces': {
|
||||
ui: {
|
||||
id: 'ui',
|
||||
@@ -330,22 +404,20 @@ export const mockPatchData: DataModel = {
|
||||
},
|
||||
},
|
||||
},
|
||||
'current-dependents': {
|
||||
lnd: {
|
||||
pointers: [],
|
||||
'health-checks': [],
|
||||
},
|
||||
},
|
||||
'current-dependencies': {},
|
||||
'dependency-info': {},
|
||||
'marketplace-url': 'https://registry.start9.com/',
|
||||
'developer-key': 'developer-key',
|
||||
'has-config': true,
|
||||
outboundProxy: null,
|
||||
},
|
||||
lnd: {
|
||||
...Mock.lnd,
|
||||
manifest: {
|
||||
...Mock.lnd.manifest,
|
||||
version: '0.11.0',
|
||||
'state-info': {
|
||||
state: PackageState.Installed,
|
||||
manifest: {
|
||||
...Mock.MockManifestLnd,
|
||||
version: '0.11.0',
|
||||
},
|
||||
},
|
||||
icon: '/assets/img/service-icons/lnd.png',
|
||||
'last-backup': null,
|
||||
@@ -358,6 +430,7 @@ export const mockPatchData: DataModel = {
|
||||
'btc-rpc-proxy': 'This is a config unsatisfied error',
|
||||
},
|
||||
},
|
||||
actions: {},
|
||||
'service-interfaces': {
|
||||
grpc: {
|
||||
id: 'grpc',
|
||||
@@ -568,12 +641,13 @@ export const mockPatchData: DataModel = {
|
||||
},
|
||||
},
|
||||
},
|
||||
'current-dependents': {},
|
||||
'current-dependencies': {
|
||||
bitcoind: {
|
||||
versionRange: '>=26.0.0',
|
||||
'health-checks': [],
|
||||
},
|
||||
'btc-rpc-proxy': {
|
||||
versionRange: '>2.0.0',
|
||||
'health-checks': [],
|
||||
},
|
||||
},
|
||||
@@ -589,6 +663,8 @@ export const mockPatchData: DataModel = {
|
||||
},
|
||||
'marketplace-url': 'https://registry.start9.com/',
|
||||
'developer-key': 'developer-key',
|
||||
'has-config': true,
|
||||
outboundProxy: null,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -88,19 +88,14 @@ export class DepErrorService {
|
||||
}
|
||||
}
|
||||
|
||||
const pkgManifest = pkg['state-info'].manifest
|
||||
const versionRange = pkg['current-dependencies'][depId].versionRange
|
||||
const depManifest = dep['state-info'].manifest
|
||||
|
||||
// incorrect version
|
||||
if (
|
||||
!this.emver.satisfies(
|
||||
depManifest.version,
|
||||
pkgManifest.dependencies[depId].version,
|
||||
)
|
||||
) {
|
||||
if (!this.emver.satisfies(depManifest.version, versionRange)) {
|
||||
return {
|
||||
type: DependencyErrorType.IncorrectVersion,
|
||||
expected: pkgManifest.dependencies[depId].version,
|
||||
expected: versionRange,
|
||||
received: depManifest.version,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import { InputSpec } from '@start9labs/start-sdk/lib/config/configTypes'
|
||||
import { BackupJob, ServerNotifications } from '../api/api.types'
|
||||
import { Url } from '@start9labs/shared'
|
||||
import { Manifest } from '@start9labs/marketplace'
|
||||
import { BackupJob, ServerNotifications } from '../api/api.types'
|
||||
import { customSmtp } from '@start9labs/start-sdk/lib/config/configConstants'
|
||||
import { types } from '@start9labs/start-sdk'
|
||||
import { InputSpec } from '@start9labs/start-sdk/cjs/sdk/lib/config/configTypes'
|
||||
import {
|
||||
ActionMetadata,
|
||||
HostnameInfo,
|
||||
} from '@start9labs/start-sdk/cjs/sdk/lib/types'
|
||||
import { customSmtp } from '@start9labs/start-sdk/cjs/sdk/lib/config/configConstants'
|
||||
type ServiceInterfaceWithHostInfo = types.ServiceInterfaceWithHostInfo
|
||||
|
||||
export interface DataModel {
|
||||
@@ -174,8 +178,8 @@ export type PackageDataEntry<T extends StateInfo = StateInfo> = {
|
||||
'state-info': T
|
||||
icon: Url
|
||||
status: Status
|
||||
actions: Record<string, ActionMetadata>
|
||||
'last-backup': string | null
|
||||
'current-dependents': { [id: string]: CurrentDependencyInfo }
|
||||
'current-dependencies': { [id: string]: CurrentDependencyInfo }
|
||||
'dependency-info': {
|
||||
[id: string]: {
|
||||
@@ -217,18 +221,10 @@ export enum PackageState {
|
||||
}
|
||||
|
||||
export interface CurrentDependencyInfo {
|
||||
versionRange: string
|
||||
'health-checks': string[] // array of health check IDs
|
||||
}
|
||||
|
||||
export interface Action {
|
||||
name: string
|
||||
description: string
|
||||
warning: string | null
|
||||
disabled: string | null
|
||||
'input-spec': InputSpec | null
|
||||
group: string | null
|
||||
}
|
||||
|
||||
export interface Status {
|
||||
configured: boolean
|
||||
main: MainStatus
|
||||
@@ -260,7 +256,7 @@ export interface MainStatusStarting {
|
||||
export interface MainStatusRunning {
|
||||
status: PackageMainStatus.Running
|
||||
started: string // UTC date string
|
||||
health: { [id: string]: HealthCheckResult }
|
||||
health: Record<string, HealthCheckResult>
|
||||
}
|
||||
|
||||
export interface MainStatusBackingUp {
|
||||
@@ -307,7 +303,6 @@ export interface HealthCheckResultStarting {
|
||||
|
||||
export interface HealthCheckResultDisabled {
|
||||
result: HealthResult.Disabled
|
||||
reason: string
|
||||
}
|
||||
|
||||
export interface HealthCheckResultSuccess {
|
||||
@@ -322,7 +317,7 @@ export interface HealthCheckResultLoading {
|
||||
|
||||
export interface HealthCheckResultFailure {
|
||||
result: HealthResult.Failure
|
||||
error: string
|
||||
message: string
|
||||
}
|
||||
|
||||
export type InstallingInfo = {
|
||||
|
||||
@@ -23,10 +23,7 @@ export function renderPkgStatus(
|
||||
if (pkg['state-info'].state === PackageState.Installed) {
|
||||
primary = getPrimaryStatus(pkg.status)
|
||||
dependency = getDependencyStatus(depErrors)
|
||||
health = getHealthStatus(
|
||||
pkg.status,
|
||||
!isEmptyObject(pkg['state-info'].manifest['health-checks']),
|
||||
)
|
||||
health = getHealthStatus(pkg.status)
|
||||
} else {
|
||||
primary = pkg['state-info'].state as string as PrimaryStatus
|
||||
}
|
||||
@@ -49,12 +46,16 @@ function getDependencyStatus(depErrors: PkgDependencyErrors): DependencyStatus {
|
||||
}
|
||||
|
||||
function getHealthStatus(status: Status): HealthStatus | null {
|
||||
if (status.main.status !== PackageMainStatus.Running) {
|
||||
if (status.main.status !== PackageMainStatus.Running || !status.main.health) {
|
||||
return null
|
||||
}
|
||||
|
||||
const values = Object.values(status.main.health)
|
||||
|
||||
if (values.some(h => !h.result)) {
|
||||
return HealthStatus.Waiting
|
||||
}
|
||||
|
||||
if (values.some(h => h.result === 'failure')) {
|
||||
return HealthStatus.Failure
|
||||
}
|
||||
@@ -63,7 +64,7 @@ function getHealthStatus(status: Status): HealthStatus | null {
|
||||
return HealthStatus.Loading
|
||||
}
|
||||
|
||||
if (values.some(h => !h.result || h.result === 'starting')) {
|
||||
if (values.some(h => h.result === 'starting')) {
|
||||
return HealthStatus.Starting
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ export function dryUpdate(
|
||||
Object.keys(pkg['current-dependencies'] || {}).some(
|
||||
pkgId => pkgId === id,
|
||||
) &&
|
||||
!emver.satisfies(version, getManifest(pkg).dependencies[id].version),
|
||||
!emver.satisfies(version, pkg['current-dependencies'][id].versionRange),
|
||||
)
|
||||
.map(pkg => getManifest(pkg).title)
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@ import {
|
||||
DataModel,
|
||||
InstalledState,
|
||||
InstallingState,
|
||||
Manifest,
|
||||
PackageDataEntry,
|
||||
PackageState,
|
||||
UpdatingState,
|
||||
} from 'src/app/services/patch-db/data-model'
|
||||
import { firstValueFrom } from 'rxjs'
|
||||
import { Manifest } from '@start9labs/marketplace'
|
||||
|
||||
export async function getPackage(
|
||||
patch: PatchDB<DataModel>,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { PackageDataEntry } from '../services/patch-db/data-model'
|
||||
import { getManifest } from './get-package-data'
|
||||
|
||||
export function hasCurrentDeps(pkg: PackageDataEntry): boolean {
|
||||
return !!Object.keys(pkg['current-dependents']).filter(
|
||||
depId => depId !== getManifest(pkg).id,
|
||||
).length
|
||||
export function hasCurrentDeps(
|
||||
id: string,
|
||||
pkgs: Record<string, PackageDataEntry>,
|
||||
): boolean {
|
||||
return !!Object.values(pkgs).some(pkg => !!pkg['current-dependencies'][id])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user