Merge branch 'master' of github.com:benallfree/pockethost

This commit is contained in:
Ben Allfree 2024-05-30 11:40:21 +00:00
commit dc9f332aa7
34 changed files with 510 additions and 461 deletions

View File

@ -13,7 +13,6 @@ MOTHERSHIP_MIGRATIONS_DIR=/path/to/dist/mothership-app/migrations
MOTHERSHIP_HOOKS_DIR=/path/to/dist/mothership-app/pb_hooks
DAEMON_DATA_ROOT=/path/to/.pockethost/data
DAEMON_INITIAL_PORT_POOL_SIZE=20
PH_BIN_CACHE=/path/to/.pockethost/pbincache
PH_FTP_PORT=21
SSL_KEY=/path/to/pockethost.key
SSL_CERT=/path/to/pockethost.crt

4
.gitignore vendored
View File

@ -7,14 +7,10 @@
.idea
**/.env
**/.env.*
.pbincache
osx
pocketbase
.svelte-kit
live-data
dist
.pockethost
version-cache
// This is needed because Docker bind mounts will copy this file
src/mothership-app/pb_hooks/src/versions.js

View File

@ -9,9 +9,6 @@ build
_site
forks
// This is needed because Docker bind mounts will copy this file
src/mothership-app/pb_hooks/src/versions.js
src/mothership-app/migrations
src/mothership-app/pb_hooks/types/types.d.ts
src/instance-app/types/types.d.ts

View File

@ -17,6 +17,7 @@
"frontends",
"fullchain",
"getenv",
"gobot",
"goja",
"IPCIDR",
"jsonifiable",
@ -37,7 +38,6 @@
"opengraph",
"PASV",
"pbgo",
"pbincache",
"PBOUNCE",
"pexec",
"pocketbase",
@ -46,6 +46,7 @@
"privkey",
"rizzdown",
"Rpcs",
"semvers",
"superadmin",
"syslogd",
"tailable",

View File

@ -22,9 +22,9 @@ module.exports = {
script: 'pnpm prod:cli mothership serve',
},
{
name: `downloader`,
name: `updater`,
restart_delay: 60 * 60 * 1000, // 1 hour
script: 'pnpm prod:cli download',
script: 'pnpm prod:cli mothership update',
},
{
name: `health`,

View File

@ -23,7 +23,7 @@ Key updates in this release:
# Overview (experimental)
Here is what AI decided based on the change log (powered by [rizzdown](https://benallfree/rizzdown))...
Here is what AI decided based on the change log (powered by [rizzdown](https://github.com/benallfree/rizzdown))...
The release of PocketHost v0.11.0 introduces essential refinements designed to uplift the developer experience. The enhancement of debug logging in InstanceService presents a granular understanding of the system's inner workings. The refactoring of FTP physical and virtual directory names, together with the PocketBase (pb) launcher, contributes to elevating performance levels - a paramount advantage for restricted bandwidth environments or large projects.

View File

@ -8,7 +8,7 @@ PocketHost instances can use a custom domain (CNAME) instead of `*.pockethost.io
We recommand Cloudflare because they support [CNAME flattening](https://developers.cloudflare.com/dns/cname-flattening/) which means you can use `mydomain.com` instead of `foo.mydomain.com`.
Once you have configured your CNAME, you'll need to contact us to get it activated.
Once you have configured your CNAME, go to your PocketHost Dashboard and the Settings tab of your instance to add it (Pro feature only).
Example:

View File

@ -20,7 +20,7 @@
"buildtool": "tsx buildtool/index.ts",
"build-frontends": "concurrently 'pnpm:build:frontend:*'",
"build:frontend:dashboard": "cd frontends/dashboard && pnpm build",
"build:docker": "docker build . -t pockethost-instance:1.0.0 -t pockethost-instance:latest",
"build:docker": "cd src/services/PocketBaseService && docker build . -t pockethost-instance:1.0.0 -t pockethost-instance:latest",
"build:frontend:lander": "cd frontends/lander && pnpm build",
"build:frontend:superadmin": "cd frontends/superadmin && pnpm build",
"dev:cli": "NODE_ENV=development tsx src/cli/index.ts",
@ -69,6 +69,8 @@
"ftp-srv": "github:pockethost/ftp-srv#0fc708bae0d5d7a55ce948767f082d6fcfb2af59",
"get-port": "^6.1.2",
"glob": "^10.3.10",
"gobot": "1.0.0-alpha.40",
"gobot-pocketbase": "0.22.8-alpha.22",
"http-proxy": "^1.18.1",
"http-proxy-middleware": "^2.0.6",
"ip-cidr": "^3.1.0",
@ -78,7 +80,6 @@
"nanoid": "^5.0.2",
"node-fetch": "^3.3.2",
"node-os-utils": "^1.3.7",
"pbgo": "1.0.0-alpha.3",
"pocketbase": "^0.20.1",
"rimraf": "^5.0.5",
"semver": "^7.5.4",
@ -145,6 +146,5 @@
"tsx": "^3.14.0",
"type-fest": "^4.6.0",
"typescript": "^5.2.2"
},
"packageManager": "pnpm@9.1.2"
}
}

286
pnpm-lock.yaml generated
View File

@ -80,6 +80,12 @@ importers:
glob:
specifier: ^10.3.10
version: 10.3.10
gobot:
specifier: 1.0.0-alpha.40
version: 1.0.0-alpha.40
gobot-pocketbase:
specifier: 0.22.8-alpha.22
version: 0.22.8-alpha.22
http-proxy:
specifier: ^1.18.1
version: 1.18.1
@ -107,9 +113,6 @@ importers:
node-os-utils:
specifier: ^1.3.7
version: 1.3.7
pbgo:
specifier: 1.0.0-alpha.3
version: 1.0.0-alpha.3
pocketbase:
specifier: ^0.20.1
version: 0.20.1
@ -958,6 +961,9 @@ packages:
'@s-libs/micro-dash@16.1.0':
resolution: {integrity: sha512-GmmtRb/vNl1RxErvm/d+ITfjbo4og/CXyYdqs4vpeFrJla0uSEbXwf9aJUXYvgORQDgXV6h9tdgDY6T88FRU3Q==}
'@s-libs/micro-dash@17.1.0':
resolution: {integrity: sha512-vnrChv6KQG/kgRSNmxH0IqcGx4gYlvnmkfzuKotQNZZMBTnDZOzHYr487LPRq1Rr0ohRDuDsz6WssSolyoowQg==}
'@sindresorhus/is@4.6.0':
resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==}
engines: {node: '>=10'}
@ -1483,6 +1489,10 @@ packages:
assert-never@1.2.1:
resolution: {integrity: sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw==}
astral-regex@2.0.0:
resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==}
engines: {node: '>=8'}
async@3.2.4:
resolution: {integrity: sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==}
@ -1838,6 +1848,10 @@ packages:
resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==}
engines: {node: '>=16'}
commander@12.1.0:
resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==}
engines: {node: '>=18'}
commander@2.20.3:
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
@ -2021,6 +2035,14 @@ packages:
decode-named-character-reference@1.0.2:
resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==}
decompress-bzip2@4.0.0:
resolution: {integrity: sha512-RwEcbZWaM7F5EiYfsAXUmZ/KLEVAPjYXfGbb5bztXZQ3d5PMpXYxa/1j04QL/gjotRdmzpHh++/cxz+rNZ4AZg==}
engines: {node: '>=4'}
decompress-gz@0.0.1:
resolution: {integrity: sha512-YMdCWdxHvPplsTbV1tvr2oFJOtAFNxqVMFnKWEmePBXl+LKG5z5bFrowzc12Jzd7O29nnzI/D1M95Asx0Qa1fg==}
engines: {node: '>=4'}
decompress-response@6.0.0:
resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
engines: {node: '>=10'}
@ -2037,6 +2059,10 @@ packages:
resolution: {integrity: sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==}
engines: {node: '>=4'}
decompress-unzip@4.0.1:
resolution: {integrity: sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw==}
engines: {node: '>=4'}
decompress-unzip@https://codeload.github.com/pockethost/decompress-unzip/tar.gz/6ef397b9a2df11d39c7b26ce779e123833844751:
resolution: {tarball: https://codeload.github.com/pockethost/decompress-unzip/tar.gz/6ef397b9a2df11d39c7b26ce779e123833844751}
version: 4.0.1
@ -2400,6 +2426,9 @@ packages:
resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==}
engines: {node: '>=8.6.0'}
fast-safe-stringify@2.1.1:
resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==}
fastparse@1.1.2:
resolution: {integrity: sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==}
@ -2429,10 +2458,18 @@ packages:
resolution: {integrity: sha512-hlDw5Ev+9e883s0pwUsuuYNu4tD7GgpUnOvykjv1Gya0ZIjuKumthDRua90VUn6/nlRKAjcxLUnHNTIUWwWIiw==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
file-type@19.0.0:
resolution: {integrity: sha512-s7cxa7/leUWLiXO78DVVfBVse+milos9FitauDLG1pI7lNaJ2+5lzPnr2N24ym+84HVwJL6hVuGfgVE+ALvU8Q==}
engines: {node: '>=18'}
file-type@3.9.0:
resolution: {integrity: sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==}
engines: {node: '>=0.10.0'}
file-type@4.4.0:
resolution: {integrity: sha512-f2UbFQEk7LXgWpi5ntcO86OeA/cC80fuDDDaX/fZ2ZGel+AF7leRQqBBW1eJNiiQkrZlAoM6P+VYP5P6bOlDEQ==}
engines: {node: '>=4'}
file-type@5.2.0:
resolution: {integrity: sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==}
engines: {node: '>=4'}
@ -2479,6 +2516,10 @@ packages:
resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
find-up@7.0.0:
resolution: {integrity: sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==}
engines: {node: '>=18'}
find-versions@5.1.0:
resolution: {integrity: sha512-+iwzCJ7C5v5KgcBuueqVoNiHVoQpwiUK5XFLjf0affFTep+Wcw93tPvmb8tqujDNmzhBDPddnWV/qgWSXgq+Hg==}
engines: {node: '>=12'}
@ -2614,6 +2655,10 @@ packages:
resolution: {integrity: sha512-BrGGraKm2uPqurfGVj/z97/zv8dPleC6x9JBNRTrDNtCkkRF4rPwrQXFgL7+I+q8QSdU4ntLQX2D7KIxSy8nGw==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
get-stream@2.3.1:
resolution: {integrity: sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==}
engines: {node: '>=0.10.0'}
get-stream@3.0.0:
resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==}
engines: {node: '>=4'}
@ -2650,6 +2695,7 @@ packages:
glob@6.0.4:
resolution: {integrity: sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==}
deprecated: Glob versions prior to v9 are no longer supported
glob@7.1.6:
resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==}
@ -2683,6 +2729,14 @@ packages:
resolution: {integrity: sha512-mTCC51QFadK75MvAhrL5nPVIP291NjML1guo10Sa7Yj04tJU4V++Vgm780NIddg9etQD9D8FM67hFGqM8EE2HQ==}
engines: {node: '>= 0.2.5'}
gobot-pocketbase@0.22.8-alpha.22:
resolution: {integrity: sha512-beNLlDjonodEiNNcPIxAY4yYAzxcNC0i4KUrinYboR2KtAfbeMb0zijeswVKkZBnopDYQAWqasBEFhsFO7oiUg==}
hasBin: true
gobot@1.0.0-alpha.40:
resolution: {integrity: sha512-bV+QO3VZamsnKLH5Pqt0tFZ2CD90JT2QjQIs6tvMP1H2w8QJApbRPVkpJ4O56nXGgyj6f0udelDrsd4tm1F6CQ==}
hasBin: true
gopd@1.0.1:
resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
@ -2830,9 +2884,6 @@ packages:
engines: {node: '>=14.0.0'}
hasBin: true
immediate@3.0.6:
resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
immutable@4.3.4:
resolution: {integrity: sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==}
@ -3038,6 +3089,10 @@ packages:
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
engines: {node: '>=8'}
is-stream@4.0.1:
resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==}
engines: {node: '>=18'}
is-typedarray@1.0.0:
resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==}
@ -3128,9 +3183,6 @@ packages:
jstransformer@1.0.0:
resolution: {integrity: sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==}
jszip@3.10.1:
resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==}
junk@1.0.3:
resolution: {integrity: sha512-3KF80UaaSSxo8jVnRYtMKNGFOoVPBdkkVPsw+Ad0y4oxKXPduS6G6iHkrf69yJVff/VAaYXkV42rtZ7daJxU3w==}
engines: {node: '>=0.10.0'}
@ -3181,9 +3233,6 @@ packages:
resolution: {integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==}
engines: {node: '>=14.16'}
lie@3.3.0:
resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==}
liftoff@4.0.0:
resolution: {integrity: sha512-rMGwYF8q7g2XhG2ulBmmJgWv25qBsqRbDn5gH0+wnuyeFt7QBJlHJmtg5qEdn4pN6WVAUMgXnIxytMFRX9c1aA==}
engines: {node: '>=10.13.0'}
@ -3246,6 +3295,9 @@ packages:
lodash.throttle@4.1.1:
resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==}
lodash.truncate@4.4.2:
resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==}
lodash@4.17.21:
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
@ -3291,6 +3343,11 @@ packages:
resolution: {integrity: sha512-tFWBiv3h7z+T/tDaoxA8rqTxy1CHV6gHS//QdaH4pulbq/JuBSGgQspQQqcgnwdAx6pNI7cmvz5Sv/addzHmUg==}
engines: {node: '>=12'}
lzma-native@8.0.6:
resolution: {integrity: sha512-09xfg67mkL2Lz20PrrDeNYZxzeW7ADtpYFbwSQh9U8+76RIzx5QsJBMy8qikv3hbUPfpy6hqwxt6FcGK81g9AA==}
engines: {node: '>=10.0.0'}
hasBin: true
magic-string@0.27.0:
resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==}
engines: {node: '>=12'}
@ -3332,6 +3389,9 @@ packages:
resolution: {integrity: sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w==}
hasBin: true
markdown-table@3.0.3:
resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==}
marked@9.1.5:
resolution: {integrity: sha512-14QG3shv8Kg/xc0Yh6TNkMj90wXH9mmldi5941I2OevfJ/FQAFLEwtwU2/FfgSAOMlWHrEukWSGQf8MiVYNG2A==}
engines: {node: '>= 16'}
@ -3629,6 +3689,9 @@ packages:
resolution: {integrity: sha512-SQkEP4hmNWjlniS5zdnfIXTk1x7Ome85RDzHlTbBtzE97Gfwz/Ipw4v/Ryk20DWIy3yCNVLVlGKApCnmvYoJbA==}
engines: {node: '>=10'}
node-addon-api@3.2.1:
resolution: {integrity: sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==}
node-addon-api@4.3.0:
resolution: {integrity: sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==}
@ -3652,6 +3715,10 @@ packages:
resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
node-gyp-build@4.8.1:
resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==}
hasBin: true
node-gyp@8.4.1:
resolution: {integrity: sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==}
engines: {node: '>= 10.12.0'}
@ -3853,9 +3920,6 @@ packages:
resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==}
engines: {node: '>=14.16'}
pako@1.0.11:
resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==}
param-case@3.0.4:
resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==}
@ -3936,10 +4000,6 @@ packages:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
pbgo@1.0.0-alpha.3:
resolution: {integrity: sha512-rL4as8mm9i4rRldtJHPCaRqXBzQi/HmnkcmNf36SzVBgBvlrz9pxkkz1FQNZUpmz3qzaQxKoYwrWOEhRazWmuA==}
hasBin: true
peek-readable@5.0.0:
resolution: {integrity: sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==}
engines: {node: '>=14.16'}
@ -3968,6 +4028,14 @@ packages:
resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==}
engines: {node: '>=4'}
pinkie-promise@2.0.1:
resolution: {integrity: sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==}
engines: {node: '>=0.10.0'}
pinkie@2.0.4:
resolution: {integrity: sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==}
engines: {node: '>=0.10.0'}
pirates@4.0.6:
resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==}
engines: {node: '>= 6'}
@ -4397,6 +4465,11 @@ packages:
engines: {node: '>=10'}
hasBin: true
semver@7.6.2:
resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==}
engines: {node: '>=10'}
hasBin: true
send@0.18.0:
resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==}
engines: {node: '>= 0.8.0'}
@ -4418,9 +4491,6 @@ packages:
resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==}
engines: {node: '>= 0.4'}
setimmediate@1.0.5:
resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==}
setprototypeof@1.2.0:
resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
@ -4486,6 +4556,10 @@ packages:
resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==}
engines: {node: '>=12'}
slice-ansi@4.0.0:
resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==}
engines: {node: '>=10'}
slugify@1.6.6:
resolution: {integrity: sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==}
engines: {node: '>=8.0.0'}
@ -4735,6 +4809,10 @@ packages:
resolution: {integrity: sha512-FI6xGyKM9dRdNCrCWiEy1QhRZskDYkW+lUNAIXkFeht0/XCsSdZ7UsPANFLk0h8b+8Is6Ll8bllUNjME+XCANA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
table@6.8.2:
resolution: {integrity: sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==}
engines: {node: '>=10.0.0'}
tail@2.2.6:
resolution: {integrity: sha512-IQ6G4wK/t8VBauYiGPLx+d3fA5XjSVagjWV5SIYzvEvglbQjwEcukeYI68JOPpdydjxhZ9sIgzRlSmwSpphHyw==}
engines: {node: '>= 6.0.0'}
@ -4803,6 +4881,10 @@ packages:
resolution: {integrity: sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==}
engines: {node: '>=8.17.0'}
tmp@0.2.3:
resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==}
engines: {node: '>=14.14'}
to-buffer@1.1.1:
resolution: {integrity: sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==}
@ -4920,6 +5002,10 @@ packages:
resolution: {integrity: sha512-cSb4bPFd5qgR7qr2jYAi0hlX9n5YKK2ONKkLFkxl+v/9BvC0sOpZjBHDBSXc5lWAf5ty9oZdRXytBIHzgUcerw==}
engines: {node: '>=14.0'}
unicorn-magic@0.1.0:
resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==}
engines: {node: '>=18'}
unique-filename@1.1.1:
resolution: {integrity: sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==}
@ -5562,7 +5648,7 @@ snapshots:
'@npmcli/fs@1.1.1':
dependencies:
'@gar/promisify': 1.1.3
semver: 7.5.4
semver: 7.6.2
optional: true
'@npmcli/move-file@1.1.2':
@ -5595,6 +5681,11 @@ snapshots:
tslib: 2.6.2
utility-types: 3.10.0
'@s-libs/micro-dash@17.1.0':
dependencies:
tslib: 2.6.2
utility-types: 3.10.0
'@sindresorhus/is@4.6.0': {}
'@sindresorhus/is@5.6.0': {}
@ -6114,6 +6205,8 @@ snapshots:
assert-never@1.2.1: {}
astral-regex@2.0.0: {}
async@3.2.4: {}
asynckit@0.4.0: {}
@ -6169,7 +6262,7 @@ snapshots:
bin-version-check@5.1.0:
dependencies:
bin-version: 6.0.0
semver: 7.5.4
semver: 7.6.2
semver-truncate: 3.0.0
bin-version@6.0.0:
@ -6555,6 +6648,8 @@ snapshots:
commander@11.1.0: {}
commander@12.1.0: {}
commander@2.20.3: {}
commander@4.1.1: {}
@ -6748,6 +6843,15 @@ snapshots:
dependencies:
character-entities: 2.0.2
decompress-bzip2@4.0.0:
dependencies:
file-type: 4.4.0
seek-bzip: 1.0.6
decompress-gz@0.0.1:
dependencies:
file-type: 5.2.0
decompress-response@6.0.0:
dependencies:
mimic-response: 3.1.0
@ -6772,6 +6876,13 @@ snapshots:
file-type: 5.2.0
is-stream: 1.1.0
decompress-unzip@4.0.1:
dependencies:
file-type: 3.9.0
get-stream: 2.3.1
pify: 2.3.0
yauzl: 2.10.0
decompress-unzip@https://codeload.github.com/pockethost/decompress-unzip/tar.gz/6ef397b9a2df11d39c7b26ce779e123833844751:
dependencies:
file-type: 3.9.0
@ -7208,6 +7319,8 @@ snapshots:
merge2: 1.4.1
micromatch: 4.0.5
fast-safe-stringify@2.1.1: {}
fastparse@1.1.2: {}
fastq@1.15.0:
@ -7237,8 +7350,16 @@ snapshots:
strtok3: 7.0.0
token-types: 5.0.1
file-type@19.0.0:
dependencies:
readable-web-to-node-stream: 3.0.2
strtok3: 7.0.0
token-types: 5.0.1
file-type@3.9.0: {}
file-type@4.4.0: {}
file-type@5.2.0: {}
file-type@6.2.0: {}
@ -7293,6 +7414,12 @@ snapshots:
locate-path: 7.2.0
path-exists: 5.0.0
find-up@7.0.0:
dependencies:
locate-path: 7.2.0
path-exists: 5.0.0
unicorn-magic: 0.1.0
find-versions@5.1.0:
dependencies:
semver-regex: 4.0.5
@ -7430,6 +7557,11 @@ snapshots:
get-port@6.1.2: {}
get-stream@2.3.1:
dependencies:
object-assign: 4.1.1
pinkie-promise: 2.0.1
get-stream@3.0.0: {}
get-stream@5.2.0:
@ -7521,6 +7653,39 @@ snapshots:
glossy@0.1.7: {}
gobot-pocketbase@0.22.8-alpha.22:
dependencies:
gobot: 1.0.0-alpha.40
gobot@1.0.0-alpha.40:
dependencies:
'@s-libs/micro-dash': 17.1.0
bottleneck: 2.19.5
commander: 12.1.0
decompress: 4.2.1
decompress-bzip2: 4.0.0
decompress-gz: 0.0.1
decompress-tar: 4.1.1
decompress-tarbz2: 4.1.1
decompress-targz: 4.1.1
decompress-unzip: 4.0.1
env-paths: 3.0.0
fast-safe-stringify: 2.1.1
file-type: 19.0.0
find-up: 7.0.0
glob: 10.3.10
is-stream: 4.0.1
json-stringify-safe: 5.0.1
lzma-native: 8.0.6
markdown-table: 3.0.3
node-fetch: 3.3.2
rimraf: 5.0.5
semver: 7.6.2
table: 6.8.2
tar-stream: 1.6.2
tmp: 0.2.3
unbzip2-stream: 1.4.3
gopd@1.0.1:
dependencies:
get-intrinsic: 1.2.2
@ -7700,8 +7865,6 @@ snapshots:
dependencies:
queue: 6.0.2
immediate@3.0.6: {}
immutable@4.3.4: {}
import-fresh@3.3.0:
@ -7873,6 +8036,8 @@ snapshots:
is-stream@2.0.1: {}
is-stream@4.0.1: {}
is-typedarray@1.0.0: {}
is-unc-path@1.0.0:
@ -7944,13 +8109,6 @@ snapshots:
is-promise: 2.2.2
promise: 7.3.1
jszip@3.10.1:
dependencies:
lie: 3.3.0
pako: 1.0.11
readable-stream: 2.3.8
setimmediate: 1.0.5
junk@1.0.3: {}
keyv@4.5.4:
@ -7988,10 +8146,6 @@ snapshots:
dependencies:
package-json: 8.1.1
lie@3.3.0:
dependencies:
immediate: 3.0.6
liftoff@4.0.0:
dependencies:
extend: 3.0.2
@ -8050,6 +8204,8 @@ snapshots:
lodash.throttle@4.1.1: {}
lodash.truncate@4.4.2: {}
lodash@4.17.21: {}
log-symbols@4.1.0:
@ -8097,6 +8253,12 @@ snapshots:
luxon@3.4.3: {}
lzma-native@8.0.6:
dependencies:
node-addon-api: 3.2.1
node-gyp-build: 4.8.1
readable-stream: 3.6.2
magic-string@0.27.0:
dependencies:
'@jridgewell/sourcemap-codec': 1.4.15
@ -8157,6 +8319,8 @@ snapshots:
mdurl: 1.0.1
uc.micro: 1.0.6
markdown-table@3.0.3: {}
marked@9.1.5: {}
maximatch@0.1.0:
@ -8496,7 +8660,9 @@ snapshots:
node-abi@3.51.0:
dependencies:
semver: 7.5.4
semver: 7.6.2
node-addon-api@3.2.1: {}
node-addon-api@4.3.0: {}
@ -8516,6 +8682,8 @@ snapshots:
fetch-blob: 3.2.0
formdata-polyfill: 4.0.10
node-gyp-build@4.8.1: {}
node-gyp@8.4.1:
dependencies:
env-paths: 2.2.1
@ -8773,9 +8941,7 @@ snapshots:
got: 12.6.1
registry-auth-token: 5.0.2
registry-url: 6.0.1
semver: 7.5.4
pako@1.0.11: {}
semver: 7.6.2
param-case@3.0.4:
dependencies:
@ -8844,12 +9010,6 @@ snapshots:
path-type@4.0.0: {}
pbgo@1.0.0-alpha.3:
dependencies:
env-paths: 3.0.0
jszip: 3.10.1
node-fetch: 3.3.2
peek-readable@5.0.0: {}
pend@1.2.0: {}
@ -8870,6 +9030,12 @@ snapshots:
pify@3.0.0: {}
pinkie-promise@2.0.1:
dependencies:
pinkie: 2.0.4
pinkie@2.0.4: {}
pirates@4.0.6: {}
please-upgrade-node@3.2.0:
@ -9337,13 +9503,13 @@ snapshots:
semver-diff@4.0.0:
dependencies:
semver: 7.5.4
semver: 7.6.2
semver-regex@4.0.5: {}
semver-truncate@3.0.0:
dependencies:
semver: 7.5.4
semver: 7.6.2
semver@6.3.1: {}
@ -9351,6 +9517,8 @@ snapshots:
dependencies:
lru-cache: 6.0.0
semver@7.6.2: {}
send@0.18.0:
dependencies:
debug: 2.6.9
@ -9395,8 +9563,6 @@ snapshots:
gopd: 1.0.1
has-property-descriptors: 1.0.1
setimmediate@1.0.5: {}
setprototypeof@1.2.0: {}
sharp@0.32.6:
@ -9462,6 +9628,12 @@ snapshots:
slash@4.0.0: {}
slice-ansi@4.0.0:
dependencies:
ansi-styles: 4.3.0
astral-regex: 2.0.0
is-fullwidth-code-point: 3.0.0
slugify@1.6.6: {}
smart-buffer@4.2.0:
@ -9729,6 +9901,14 @@ snapshots:
syslog-parse@2.0.0: {}
table@6.8.2:
dependencies:
ajv: 8.12.0
lodash.truncate: 4.4.2
slice-ansi: 4.0.0
string-width: 4.2.3
strip-ansi: 6.0.1
tail@2.2.6: {}
tailwindcss@3.3.5:
@ -9842,6 +10022,8 @@ snapshots:
dependencies:
rimraf: 3.0.2
tmp@0.2.3: {}
to-buffer@1.1.1: {}
to-fast-properties@2.0.0: {}
@ -9934,6 +10116,8 @@ snapshots:
dependencies:
'@fastify/busboy': 2.0.0
unicorn-magic@0.1.0: {}
unique-filename@1.1.1:
dependencies:
unique-slug: 2.0.2

View File

@ -1,13 +0,0 @@
import { PocketbaseReleaseDownloadService } from '$services'
import { LoggerService } from '$shared'
import { discordAlert } from '$util'
export const download = async () => {
const logger = LoggerService().create(`download.ts`)
const { dbg, error, info, warn } = logger
info(`Starting`)
const { check } = PocketbaseReleaseDownloadService({})
await check().catch(discordAlert)
}

View File

@ -1,15 +0,0 @@
import { Command } from 'commander'
import { download } from './download'
type Options = {
debug: boolean
}
export const DownloadCommand = () => {
const cmd = new Command(`download`)
.description(`Download PocketBase versions`)
.action(async () => {
await download()
})
return cmd
}

View File

@ -1,4 +1,3 @@
import { PocketbaseReleaseVersionService } from '$services'
import { Command } from 'commander'
import { daemon } from './daemon'
@ -10,7 +9,6 @@ export const ServeCommand = () => {
const cmd = new Command(`serve`)
.description(`Run an edge daemon server`)
.action(async (options: Options) => {
await PocketbaseReleaseVersionService({})
await daemon()
})
return cmd

View File

@ -1,28 +1,20 @@
import {
DATA_ROOT,
DEBUG,
IS_DEV,
LS_WEBHOOK_SECRET,
mkContainerHomePath,
MOTHERSHIP_APP_DIR,
MOTHERSHIP_DATA_ROOT,
MOTHERSHIP_HOOKS_DIR,
MOTHERSHIP_MIGRATIONS_DIR,
MOTHERSHIP_NAME,
MOTHERSHIP_PORT,
MOTHERSHIP_SEMVER,
PH_VERSIONS,
mkContainerHomePath,
} from '$constants'
import {
PocketbaseReleaseVersionService,
PocketbaseService,
PortService,
} from '$services'
import { PortService } from '$services'
import { LoggerService } from '$shared'
import { gracefulExit } from '$util'
import copyfiles from 'copyfiles'
import { run } from 'pbgo'
import { GobotOptions, gobot } from 'gobot'
import { rimraf } from 'rimraf'
import { freshenPocketbaseVersions } from '../freshenPocketbaseVersions'
export type MothershipConfig = { isolate: boolean }
@ -59,66 +51,41 @@ export async function mothership(cfg: MothershipConfig) {
/** Launch central database */
info(`Serving`)
if (isolate) {
await PocketbaseReleaseVersionService({})
const pbService = await PocketbaseService({})
const { url, exitCode } = await pbService.spawn({
version: MOTHERSHIP_SEMVER(),
subdomain: MOTHERSHIP_NAME(),
instanceId: MOTHERSHIP_NAME(),
port: MOTHERSHIP_PORT(),
dev: DEBUG(),
env: {
DATA_ROOT: mkContainerHomePath(`data`),
LS_WEBHOOK_SECRET: LS_WEBHOOK_SECRET(),
},
extraBinds: [
`${DATA_ROOT()}:${mkContainerHomePath(`data`)}`,
`${MOTHERSHIP_HOOKS_DIR()}:${mkContainerHomePath(`pb_hooks`)}`,
`${PH_VERSIONS()}:${mkContainerHomePath(`pb_hooks`, `versions.js`)}`,
`${MOTHERSHIP_MIGRATIONS_DIR()}:${mkContainerHomePath(
`pb_migrations`,
)}`,
`${MOTHERSHIP_APP_DIR()}:${mkContainerHomePath(`ph_app`)}`,
],
})
info(`Mothership URL for this session is ${url}`)
exitCode.then((c) => {
gracefulExit(c)
})
} else {
await rimraf(MOTHERSHIP_DATA_ROOT(`pb_hooks`))
await _copy(MOTHERSHIP_HOOKS_DIR(`**/*`), MOTHERSHIP_DATA_ROOT(`pb_hooks`))
await _copy(PH_VERSIONS(), MOTHERSHIP_DATA_ROOT(`pb_hooks`))
await rimraf(MOTHERSHIP_DATA_ROOT(`pb_migrations`))
await _copy(
MOTHERSHIP_MIGRATIONS_DIR(`**/*`),
MOTHERSHIP_DATA_ROOT(`pb_migrations`),
)
const args = [
`serve`,
`--http`,
`0.0.0.0:${MOTHERSHIP_PORT()}`,
`--dir`,
MOTHERSHIP_DATA_ROOT(`pb_data`),
`--hooksDir`,
MOTHERSHIP_DATA_ROOT(`pb_hooks`),
`--migrationsDir`,
MOTHERSHIP_DATA_ROOT(`pb_migrations`),
`--publicDir`,
MOTHERSHIP_DATA_ROOT(`pb_public`),
]
if (IS_DEV()) {
args.push(`--dev`)
}
dbg(args)
const process = run(args, {
env: {
DATA_ROOT: DATA_ROOT(),
LS_WEBHOOK_SECRET: LS_WEBHOOK_SECRET(),
},
version: MOTHERSHIP_SEMVER(),
debug: DEBUG(),
})
const env = {
DATA_ROOT: mkContainerHomePath(`data`),
LS_WEBHOOK_SECRET: LS_WEBHOOK_SECRET(),
}
dbg(env)
await rimraf(MOTHERSHIP_DATA_ROOT(`pb_hooks`))
await _copy(MOTHERSHIP_HOOKS_DIR(`**/*`), MOTHERSHIP_DATA_ROOT(`pb_hooks`))
await rimraf(MOTHERSHIP_DATA_ROOT(`pb_migrations`))
await _copy(
MOTHERSHIP_MIGRATIONS_DIR(`**/*`),
MOTHERSHIP_DATA_ROOT(`pb_migrations`),
)
await freshenPocketbaseVersions()
const args = [
`serve`,
`--http`,
`0.0.0.0:${MOTHERSHIP_PORT()}`,
`--dir`,
MOTHERSHIP_DATA_ROOT(`pb_data`),
`--hooksDir`,
MOTHERSHIP_DATA_ROOT(`pb_hooks`),
`--migrationsDir`,
MOTHERSHIP_DATA_ROOT(`pb_migrations`),
`--publicDir`,
MOTHERSHIP_DATA_ROOT(`pb_public`),
]
if (IS_DEV()) {
args.push(`--dev`)
}
const options: Partial<GobotOptions> = {
version: MOTHERSHIP_SEMVER(),
env,
}
dbg(`args`, args)
dbg(`options`, options)
const bot = await gobot(`pocketbase`, options)
bot.run(args, { env })
}

View File

@ -0,0 +1,14 @@
import { Command } from 'commander'
import { freshenPocketbaseVersions } from '../freshenPocketbaseVersions'
type Options = {}
export const UpdateCommand = () => {
const cmd = new Command(`update`)
.description(`Update known PocketBase versions`)
.action(async (options: Options) => {
const cjs = await freshenPocketbaseVersions()
console.log(cjs)
})
return cmd
}

View File

@ -1,3 +1,7 @@
import { MOTHERSHIP_DATA_ROOT } from '$constants'
import { writeFileSync } from 'fs'
import { gobot } from 'gobot'
function compareSemVer(a: string, b: string): number {
// Consider wildcards as higher than any version number, hence represented by a large number for comparison
let splitA = a
@ -18,7 +22,7 @@ function compareSemVer(a: string, b: string): number {
return 0
}
export function expandAndSortSemVers(semvers: string[]): string[] {
function expandAndSortSemVers(semvers: string[]): string[] {
let expandedVersions = new Set<string>() // Use a set to avoid duplicates
// Helper function to add wildcard versions
@ -44,3 +48,12 @@ export function expandAndSortSemVers(semvers: string[]): string[] {
// Convert the set to an array and sort it using the custom semver comparison function
return Array.from(expandedVersions).sort(compareSemVer)
}
export async function freshenPocketbaseVersions() {
const bot = await gobot(`pocketbase`)
const rawVersions = await bot.versions()
const versions = expandAndSortSemVers(rawVersions)
const cjs = `module.exports = ${JSON.stringify(versions, null, 2)}`
writeFileSync(MOTHERSHIP_DATA_ROOT(`pb_hooks`, `versions.cjs`), cjs)
return cjs
}

View File

@ -1,5 +1,6 @@
import { Command } from 'commander'
import { ServeCommand } from './ServeCommand'
import { UpdateCommand } from './UpdateCommand'
type Options = {
debug: boolean
@ -9,5 +10,6 @@ export const MothershipCommand = () => {
const cmd = new Command(`mothership`)
.description(`Mothership commands`)
.addCommand(ServeCommand())
.addCommand(UpdateCommand())
return cmd
}

View File

@ -4,7 +4,6 @@ import { DEBUG, DefaultSettingsService, SETTINGS } from '$constants'
import { LogLevelName, LoggerService } from '$shared'
import { program } from 'commander'
import EventSource from 'eventsource'
import { DownloadCommand } from './commands/DownloadCommand'
import { EdgeCommand } from './commands/EdgeCommand'
import { FirewallCommand } from './commands/FirewallCommand'
import { HealthCommand } from './commands/HealthCommand'
@ -33,7 +32,6 @@ export const main = async () => {
.addCommand(FirewallCommand())
.addCommand(SendMailCommand())
.addCommand(ServeCommand())
.addCommand(DownloadCommand())
await program.parseAsync()
}

View File

@ -44,13 +44,14 @@ export const _MOTHERSHIP_NAME =
export const _MOTHERSHIP_APP_ROOT = (...paths: string[]) =>
join(
process.env.PH_MOTHERSHIP_APP_ROOT ||
join(_PH_PROJECT_ROOT, 'mothership-app'),
join(_PH_PROJECT_ROOT, `src`, 'mothership-app'),
...paths,
)
export const _INSTANCE_APP_ROOT = (...paths: string[]) =>
join(
process.env.PH_INSTANCE_APP_ROOT || join(_PH_PROJECT_ROOT, 'instance-app'),
process.env.PH_INSTANCE_APP_ROOT ||
join(_PH_PROJECT_ROOT, `src`, 'instance-app'),
...paths,
)
@ -67,7 +68,6 @@ export const SETTINGS = {
UPGRADE_MODE: mkBoolean(false),
PH_HOME: mkPath(_PH_HOME),
PH_VERSIONS: mkPath(join(_PH_HOME, `versions.js`), { required: false }),
PH_PROJECT_ROOT: mkPath(_PH_PROJECT_ROOT),
DEBUG: mkBoolean(_IS_DEV),
@ -95,7 +95,7 @@ export const SETTINGS = {
MOTHERSHIP_APP_DIR: mkPath(_MOTHERSHIP_APP_ROOT(`ph_app`), {
required: false,
}),
MOTHERSHIP_SEMVER: mkString(''),
MOTHERSHIP_SEMVER: mkString('*'),
MOTHERSHIP_PORT: mkNumber(8091),
INITIAL_PORT_POOL_SIZE: mkNumber(20),
@ -103,7 +103,6 @@ export const SETTINGS = {
NODE_ENV: mkString(`production`),
IS_DEV: mkBoolean(_IS_DEV),
TRACE: mkBoolean(false),
PH_BIN_CACHE: mkPath(join(_PH_HOME, '.pbincache'), { create: true }),
PH_FTP_PORT: mkNumber(21),
SSL_KEY: mkPath(join(_SSL_HOME, `${TLS_PFX}.key`)),
@ -190,7 +189,6 @@ export const instanceLogger = () => ioc.service('instanceLogger')
export const UPGRADE_MODE = () => settings().UPGRADE_MODE
export const PH_HOME = () => settings().PH_HOME
export const PH_VERSIONS = () => settings().PH_VERSIONS
export const PH_PROJECT_ROOT = () => settings().PH_PROJECT_ROOT
export const DEBUG = () => settings().DEBUG
@ -229,7 +227,6 @@ export const DATA_ROOT = () => settings().DATA_ROOT
export const NODE_ENV = () => settings().NODE_ENV
export const IS_DEV = () => settings().IS_DEV
export const TRACE = () => settings().TRACE
export const PH_BIN_CACHE = () => settings().PH_BIN_CACHE
export const PH_FTP_PORT = () => settings().PH_FTP_PORT
export const SSL_KEY = () => settings().SSL_KEY

View File

@ -8,7 +8,9 @@ routerAdd(
'/api/instance',
(c) => {
const dao = $app.dao()
const { audit, mkLog } = /** @type {Lib} */ (require(`${__hooks}/lib.js`))
const { audit, mkLog, versions } = /** @type {Lib} */ (
require(`${__hooks}/lib.js`)
)
const log = mkLog(`POST:instance`)
@ -45,8 +47,6 @@ routerAdd(
)
}
const { versions } = require(`${__hooks}/versions.js`)
const collection = dao.findCollectionByNameOrId('instances')
const record = new Record(collection)
record.set('uid', authRecord.getId())

View File

@ -1,12 +1,13 @@
/** Migrate version numbers */
onAfterBootstrap((e) => {
const dao = $app.dao()
const { audit, mkLog } = /** @type {Lib} */ (require(`${__hooks}/lib.js`))
const { audit, mkLog, versions } = /** @type {Lib} */ (
require(`${__hooks}/lib.js`)
)
const log = mkLog(`bootstrap`)
const records = dao.findRecordsByFilter(`instances`, '1=1')
const { versions } = require(`${__hooks}/versions.js`)
const unrecognized = []
records.forEach((record) => {
const v = record.get('version').trim()

View File

@ -2,8 +2,9 @@
/** Validate instance version */
onModelBeforeCreate((e) => {
const { versions } = /** @type {Lib} */ (require(`${__hooks}/lib.js`))
const dao = e.dao || $app.dao()
const { versions } = require(`${__hooks}/versions.js`)
const version = e.model.get('version')
if (!versions.includes(version)) {

View File

@ -3,7 +3,7 @@
/** Validate instance version */
onModelBeforeUpdate((e) => {
const dao = e.dao || $app.dao()
const { versions } = require(`${__hooks}/versions.js`)
const { versions } = /** @type {Lib} */ (require(`${__hooks}/lib.js`))
const version = e.model.get('version')
if (!versions.includes(version)) {

View File

@ -162,10 +162,14 @@ function removeEmptyKeys(obj) {
return sanitized
}
/** @type {Lib['versions']} */
const versions = require(`${__hooks}/versions.cjs`)
module.exports = {
audit,
processNotification,
mkLog,
enqueueNotification,
removeEmptyKeys,
versions,
}

View File

@ -102,6 +102,8 @@ routerAdd(
'POST',
'/api/signup',
(c) => {
const { versions } = /** @type {Lib} */ (require(`${__hooks}/lib.js`))
const dao = $app.dao()
const parsed = (() => {
const rawBody = readerToString(c.request().body)
@ -192,7 +194,6 @@ routerAdd(
instance.set('status', 'idle')
instance.set('notifyMaintenanceMode', true)
instance.set('syncAdmin', true)
const { versions } = require(`${__hooks}/versions.js`)
instance.set('version', versions[0])
txDao.saveRecord(instance)
} catch (e) {

View File

@ -5,7 +5,7 @@ routerAdd(
'GET',
'/api/versions',
(c) => {
const { versions } = require(`${__hooks}/versions.js`)
const { versions } = /** @type {Lib} */ (require(`${__hooks}/lib.js`))
return c.json(200, { versions })
} /* optional middlewares */,

View File

@ -0,0 +1,159 @@
module.exports = [
"0.22.*",
"0.22.12",
"0.22.11",
"0.22.10",
"0.22.9",
"0.22.8",
"0.22.7",
"0.22.6",
"0.22.5",
"0.22.4",
"0.22.3",
"0.22.2",
"0.22.1",
"0.22.0",
"0.21.*",
"0.21.3",
"0.21.2",
"0.21.1",
"0.21.0",
"0.20.*",
"0.20.7",
"0.20.6",
"0.20.5",
"0.20.4",
"0.20.3",
"0.20.2",
"0.20.1",
"0.20.0",
"0.20.0-rc3",
"0.20.0-rc2",
"0.20.0-rc",
"0.19.*",
"0.19.4",
"0.19.3",
"0.19.2",
"0.19.1",
"0.19.0",
"0.18.*",
"0.18.10",
"0.18.9",
"0.18.8",
"0.18.7",
"0.18.6",
"0.18.5",
"0.18.4",
"0.18.3",
"0.18.2",
"0.18.1",
"0.18.0",
"0.17.*",
"0.17.7",
"0.17.6",
"0.17.5",
"0.17.4",
"0.17.3",
"0.17.2",
"0.17.1",
"0.17.0",
"0.16.*",
"0.16.10",
"0.16.9",
"0.16.8",
"0.16.7",
"0.16.6",
"0.16.5",
"0.16.4",
"0.16.3",
"0.16.2",
"0.16.1",
"0.16.0",
"0.15.*",
"0.15.3",
"0.15.2",
"0.15.1",
"0.15.0",
"0.14.*",
"0.14.5",
"0.14.4",
"0.14.3",
"0.14.2",
"0.14.1",
"0.14.0",
"0.13.*",
"0.13.4",
"0.13.3",
"0.13.2",
"0.13.1",
"0.13.0",
"0.12.*",
"0.12.3",
"0.12.2",
"0.12.1",
"0.12.0",
"0.11.*",
"0.11.4",
"0.11.3",
"0.11.2",
"0.11.1",
"0.11.0",
"0.10.*",
"0.10.4",
"0.10.3",
"0.10.2",
"0.10.1",
"0.10.0",
"0.9.*",
"0.9.2",
"0.9.1",
"0.9.0",
"0.8.*",
"0.8.0",
"0.8.0-rc4",
"0.8.0-rc3",
"0.8.0-rc2",
"0.8.0-rc1",
"0.7.*",
"0.7.10",
"0.7.9",
"0.7.8",
"0.7.7",
"0.7.6",
"0.7.5",
"0.7.4",
"0.7.3",
"0.7.2",
"0.7.1",
"0.7.0",
"0.6.*",
"0.6.0",
"0.5.*",
"0.5.2",
"0.5.1",
"0.5.0",
"0.4.*",
"0.4.2",
"0.4.1",
"0.4.0",
"0.3.*",
"0.3.4",
"0.3.3",
"0.3.2",
"0.3.1",
"0.3.0",
"0.2.*",
"0.2.8",
"0.2.7",
"0.2.6",
"0.2.5",
"0.2.4",
"0.2.3",
"0.2.2",
"0.2.1",
"0.2.0",
"0.1.*",
"0.1.2",
"0.1.1",
"0.1.0"
]

View File

@ -52,4 +52,5 @@ interface Lib {
},
) => void
removeEmptyKeys: <T>(obj: T) => T
versions: string[]
}

View File

@ -457,6 +457,9 @@ export const instanceService = mkSingleton(
}
})
if (instance) {
if (!instance.cname_active) {
throw new Error(`CNAME blocked.`)
}
dbg(`${host} is a cname`)
cache.setItem(instance)
return instance

View File

@ -16,11 +16,11 @@ import { asyncExitHook, mkInternalUrl, SyslogLogger, tryFetch } from '$util'
import { map } from '@s-libs/micro-dash'
import Docker, { Container, ContainerCreateOptions } from 'dockerode'
import { existsSync } from 'fs'
import { gobot } from 'gobot'
import MemoryStream from 'memorystream'
import { gte } from 'semver'
import { EventEmitter } from 'stream'
import { AsyncReturnType } from 'type-fest'
import { PocketbaseReleaseVersionService } from '../PocketbaseReleaseVersionService'
export type Env = { [_: string]: string }
export type SpawnConfig = {
@ -54,9 +54,11 @@ export const createPocketbaseService = async (
const _serviceLogger = LoggerService().create('PocketbaseService')
const { dbg, error, warn, abort } = _serviceLogger
const { getLatestVersion, getVersion } =
await PocketbaseReleaseVersionService()
const maxVersion = getLatestVersion()
const bot = await gobot(`pocketbase`, { os: 'linux' })
const maxVersion = (await bot.versions())[0]
if (!maxVersion) {
throw new Error(`No max version found for PocketBase`)
}
const _spawn = async (cfg: SpawnConfig) => {
const cm = createCleanupManager()
@ -98,8 +100,11 @@ export const createPocketbaseService = async (
})
const _version = version || maxVersion // If _version is blank, we use the max version available
const realVersion = await getVersion(_version)
const binPath = realVersion.binPath
const realVersion = await bot.maxSatisfyingVersion(_version)
if (!realVersion) {
throw new Error(`No PocketBase version satisfying ${_version}`)
}
const binPath = await bot.getBinaryPath(realVersion)
if (!existsSync(binPath)) {
throw new Error(
`PocketBase binary (${binPath}) not found. Contact pockethost.io.`,
@ -138,7 +143,7 @@ export const createPocketbaseService = async (
Env: map(
{
...env,
DEV: dev && gte(realVersion.version, `0.20.1`),
DEV: dev && gte(realVersion, `0.20.1`),
PH_APEX_DOMAIN: APEX_DOMAIN(),
},
(v, k) => `${k}=${v}`,

View File

@ -1,128 +0,0 @@
import { PH_BIN_CACHE, PH_VERSIONS } from '$constants'
import { LoggerService, SingletonBaseConfig, mkSingleton } from '$shared'
import { downloadAndExtract, mergeConfig, smartFetch } from '$util'
import { keys } from '@s-libs/micro-dash'
import Bottleneck from 'bottleneck'
import { chmodSync, existsSync, writeFileSync } from 'fs'
import { join } from 'path'
import { rsort } from 'semver'
import { expandAndSortSemVers } from './expandAndSortSemVers'
type Release = {
url: string
tag_name: string
prerelease: string
assets: {
name: string
browser_download_url: string
}[]
}
type Releases = Release[]
export type PocketbaseReleaseDownloadServiceConfig = SingletonBaseConfig & {
onlyOne: boolean
binCachePath: string
versionsCachePath: string
}
export const PocketbaseReleaseDownloadService = mkSingleton(
(config: Partial<PocketbaseReleaseDownloadServiceConfig> = {}) => {
const { binCachePath, versionsCachePath, onlyOne } = mergeConfig(
{
binCachePath: PH_BIN_CACHE(),
versionsCachePath: PH_VERSIONS(),
onlyOne: false,
},
config,
)
const _serviceLogger = LoggerService().create(
'PocketbaseReleaseDownloadService',
)
const { dbg, info, error, warn, abort } = _serviceLogger
dbg(`Initializing`)
const osName = 'linux' // type().toLowerCase()
const cpuArchitecture = process.arch === 'x64' ? 'amd64' : process.arch
dbg({ osName, cpuArchitecture })
const binPaths: { [_: string]: string } = {}
let maxVersion = ''
const check = async () => {
info(`Fetching info for PocketBase releases...`)
let releases = await smartFetch<Releases>(
`https://api.github.com/repos/pocketbase/pocketbase/releases?per_page=100`,
join(binCachePath, `releases.json`),
)
// dbg({ releases })
type Defined<T> = Exclude<T, undefined>
type NoUndefinedProperties<T> = {
[K in keyof T]: Defined<T[K]>
}
const filteredReleases = releases
.filter((release) => !release.prerelease)
.map((release) => {
const { tag_name, assets } = release
const sanitizedTagName = tag_name.slice(1)
const path = join(binCachePath, tag_name)
const url = assets.find((v) => {
// dbg(v.name)
return v.name.includes(osName) && v.name.includes(cpuArchitecture)
})?.browser_download_url
return { url, sanitizedTagName, path }
})
.filter(
(release): release is NoUndefinedProperties<typeof release> =>
!!release.url,
)
if (filteredReleases.length === 0) return
const limiter = new Bottleneck({ maxConcurrent: 5 })
const promises = (
onlyOne ? [filteredReleases[0]!] : filteredReleases
).map((release) =>
limiter.schedule(async () => {
const { url, sanitizedTagName, path } = release
const binPath = join(path, `pocketbase`)
info(`Checking ${binPath}`)
if (existsSync(binPath)) {
chmodSync(binPath, 0o775)
} else {
info(`Downloading ${url}...`)
await downloadAndExtract(url, binPath, _serviceLogger)
}
binPaths[sanitizedTagName] = binPath
}),
)
await Promise.all(promises)
console.log(`***keys`, keys(binPaths))
const sortedSemVers = expandAndSortSemVers(keys(binPaths))
writeFileSync(
versionsCachePath,
`module.exports = ${JSON.stringify({ versions: sortedSemVers })}`,
)
info(`Saved to ${versionsCachePath}`, sortedSemVers)
if (keys(binPaths).length === 0) {
throw new Error(
`No version found, probably mismatched architecture and OS (${osName}/${cpuArchitecture})`,
)
}
maxVersion = `~${rsort(keys(binPaths))[0]}`
info(`Highest PocketBase version is ${maxVersion}`)
}
return {
check,
}
},
)

View File

@ -1,86 +0,0 @@
import { PH_BIN_CACHE } from '$constants'
import {
createTimerManager,
LoggerService,
mkSingleton,
SingletonBaseConfig,
} from '$shared'
import { mergeConfig } from '$util'
import { keys } from '@s-libs/micro-dash'
import { chmodSync, existsSync } from 'fs'
import { glob } from 'glob'
import { basename, join } from 'path'
import { maxSatisfying, rsort } from 'semver'
export type PocketbaseReleaseVersionService = SingletonBaseConfig & {
cachePath: string
checkIntervalMs: number
}
export const PocketbaseReleaseVersionService = mkSingleton(
async (config: Partial<PocketbaseReleaseVersionService> = {}) => {
const _serviceLogger = LoggerService().create(
'PocketbaseReleaseVersionService',
)
const { dbg, error, warn, abort } = _serviceLogger
dbg(`Initializing`)
const { cachePath, checkIntervalMs } = mergeConfig(
{
cachePath: PH_BIN_CACHE(),
checkIntervalMs: 1000 * 5 * 60,
},
config,
)
const binPaths: { [_: string]: string } = {}
let maxVersion = ''
const tm = createTimerManager()
const check = async () => {
const versions = await glob(join(cachePath, `v*/`))
versions.forEach((path) => {
const version = basename(path)
const sanitizedTagName = version.slice(1)
dbg(`Found a version ${sanitizedTagName}`)
const binPath = join(path, `pocketbase`)
dbg(`Checking ${binPath}`)
if (existsSync(binPath)) {
chmodSync(binPath, 0o775)
}
binPaths[sanitizedTagName] = binPath
})
maxVersion = `~${rsort(keys(binPaths))[0]}`
dbg({ maxVersion })
return true
}
await check().catch(error)
tm.repeat(check, checkIntervalMs, false)
const getLatestVersion = () => maxVersion
const getVersion = (semVer = maxVersion) => {
const version = maxSatisfying(keys(binPaths), semVer)
if (!version)
throw new Error(
`No version satisfies ${semVer} (${keys(binPaths).join(', ')})`,
)
const binPath = binPaths[version]
if (!binPath) throw new Error(`binPath for ${version} not found`)
return {
version,
binPath,
}
}
return {
getLatestVersion,
getVersion,
}
},
)

View File

@ -3,8 +3,6 @@ export * from './InstanceLoggerService'
export * from './InstanceService'
export * from './MothershipAdminClientService'
export * from './PocketBaseService'
export * from './PocketbaseReleaseDownloadService'
export * from './PocketbaseReleaseVersionService'
export * from './PortService'
export * from './ProxyService'
export * from './RealtimeLog'

View File

@ -1,47 +0,0 @@
import { Logger, singletonAsyncExecutionGuard } from '$shared'
import decompress from 'decompress'
import decompressUnzip from 'decompress-unzip'
import { chmodSync, createWriteStream } from 'fs'
import fetch from 'node-fetch'
import { dirname } from 'path'
import { assert } from './assert'
const downloadFile = async (url: string, path: string) => {
const { body } = await fetch(url)
assert(body, `Body is null`)
const fileStream = createWriteStream(path)
await new Promise<void>((resolve, reject) => {
body.pipe(fileStream)
body.on('error', reject)
fileStream.on('finish', resolve)
})
}
const _unsafe_downloadAndExtract = async (
url: string,
binPath: string,
logger: Logger,
) => {
const { dbg, info, error } = logger.create('downloadAndExtract')
dbg(`Fetching ${url}`)
const res = await fetch(url)
const { body } = res
if (!body) {
throw new Error(`Body expected for ${url}`)
}
const versionPath = dirname(binPath)
const zipPath = `${versionPath}.zip`
dbg(`Downloading ${url} to ${zipPath}`)
await downloadFile(url, zipPath)
// const tmpPath = tmpNameSync({ dir: TMP_DIR })
dbg(`Extracting ${zipPath} to ${versionPath}`)
await decompress(zipPath, versionPath, { plugins: [decompressUnzip()] })
// renameSync(tmpPath, versionPath)
chmodSync(binPath, 0o775)
}
export const downloadAndExtract = singletonAsyncExecutionGuard(
_unsafe_downloadAndExtract,
(url) => url,
)

View File

@ -3,7 +3,6 @@ export * from './Settings'
export * from './SyslogLogger'
export * from './assert'
export * from './discordAlert'
export * from './downloadAndExtract'
export * from './env'
export * from './exit'
export * from './internal'