Compare commits
3 Commits
94b0eb4dad
...
15a8ff29e6
| Author | SHA1 | Date | |
|---|---|---|---|
| 15a8ff29e6 | |||
| 35309db59b | |||
| d9b4a5cc37 |
|
|
@ -1,24 +0,0 @@
|
||||||
{
|
|
||||||
"name": "pluto",
|
|
||||||
"module": "src/server.tsx",
|
|
||||||
"type": "module",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
|
||||||
"start": "bun src/server.tsx",
|
|
||||||
"runner": "env NODE_ENV=production bun run src/runner.ts",
|
|
||||||
"prod": "env NODE_ENV=production bun src/server.tsx",
|
|
||||||
"dev": "env BUN_HOT=1 bun --hot src/server.tsx",
|
|
||||||
"deploy": "./scripts/deploy.sh",
|
|
||||||
"push": "./scripts/deploy.sh",
|
|
||||||
"remote:install": "./scripts/remote-install.sh",
|
|
||||||
"remote:start": "./scripts/remote-start.sh",
|
|
||||||
"remote:stop": "./scripts/remote-stop.sh",
|
|
||||||
"remote:restart": "./scripts/remote-restart.sh"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"typescript": "^5"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"kleur": "^4.1.5"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"extends": "../tsconfig.json",
|
|
||||||
"include": ["./**/*"]
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Show the webapps hosted on this NOSEputer.
|
// Show the webapps hosted on this NOSEputer.
|
||||||
|
|
||||||
import { $ } from "bun"
|
import { $ } from "bun"
|
||||||
import { apps } from "app/src/webapp"
|
import { apps } from "@/webapp"
|
||||||
|
|
||||||
const devMode = process.env.NODE_ENV !== "production"
|
const devMode = process.env.NODE_ENV !== "production"
|
||||||
|
|
||||||
|
|
@ -4,12 +4,12 @@ import { escapeHTML } from "bun"
|
||||||
import { readdirSync } from "fs"
|
import { readdirSync } from "fs"
|
||||||
import { join, extname } from "path"
|
import { join, extname } from "path"
|
||||||
|
|
||||||
import type { CommandOutput } from "app/src/shared/types"
|
import type { CommandOutput } from "@/shared/types"
|
||||||
import { NOSE_WWW } from "app/src/config"
|
import { NOSE_WWW } from "@/config"
|
||||||
import { isBinaryFile } from "app/src/utils"
|
import { isBinaryFile } from "@/utils"
|
||||||
import { highlight } from "../lib/highlight"
|
|
||||||
import { projectName, projectDir } from "@/project"
|
import { projectName, projectDir } from "@/project"
|
||||||
import { sessionGet } from "@/session"
|
import { sessionGet } from "@/session"
|
||||||
|
import { highlight } from "../lib/highlight"
|
||||||
|
|
||||||
export default async function (path: string) {
|
export default async function (path: string) {
|
||||||
const project = projectName()
|
const project = projectName()
|
||||||
|
|
@ -3,10 +3,10 @@
|
||||||
import { readdirSync } from "fs"
|
import { readdirSync } from "fs"
|
||||||
import { join, extname } from "path"
|
import { join, extname } from "path"
|
||||||
|
|
||||||
import type { CommandOutput } from "app/src/shared/types"
|
import type { CommandOutput } from "@/shared/types"
|
||||||
import { NOSE_WWW } from "app/src/config"
|
import { NOSE_WWW } from "@/config"
|
||||||
import { isBinaryFile } from "app/src/utils"
|
import { isBinaryFile } from "@/utils"
|
||||||
import { countChar } from "app/src/shared/utils"
|
import { countChar } from "@/shared/utils"
|
||||||
import { projectName, projectDir } from "@/project"
|
import { projectName, projectDir } from "@/project"
|
||||||
import { sessionGet } from "@/session"
|
import { sessionGet } from "@/session"
|
||||||
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
//
|
//
|
||||||
// Show some debugging information.
|
// Show some debugging information.
|
||||||
|
|
||||||
import { NOSE_STARTED, NOSE_SYS, NOSE_DIR, GIT_SHA } from "@/config"
|
import { NOSE_STARTED, NOSE_SYS_BIN, NOSE_DIR, GIT_SHA } from "@/config"
|
||||||
|
|
||||||
export default function () {
|
export default function () {
|
||||||
return [
|
return [
|
||||||
|
|
@ -12,7 +12,7 @@ export default function () {
|
||||||
`USER=${process.env.USER || "(none)"}`,
|
`USER=${process.env.USER || "(none)"}`,
|
||||||
`PWD=${process.env.PWD || "(none)"}`,
|
`PWD=${process.env.PWD || "(none)"}`,
|
||||||
`NOSE_STARTED=${NOSE_STARTED}`,
|
`NOSE_STARTED=${NOSE_STARTED}`,
|
||||||
`NOSE_SYS=${NOSE_SYS}`,
|
`NOSE_SYS_BIN=${NOSE_SYS_BIN}`,
|
||||||
`NOSE_DIR=${NOSE_DIR}`,
|
`NOSE_DIR=${NOSE_DIR}`,
|
||||||
`GIT_SHA=${GIT_SHA.slice(0, 8)}`,
|
`GIT_SHA=${GIT_SHA.slice(0, 8)}`,
|
||||||
].join("\n")
|
].join("\n")
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Load a project so you can work on it.
|
// Load a project so you can work on it.
|
||||||
|
|
||||||
import { apps } from "app/src/webapp"
|
import { apps } from "@/webapp"
|
||||||
import { sessionGet } from "@/session"
|
import { sessionGet } from "@/session"
|
||||||
|
|
||||||
export default function (project: string) {
|
export default function (project: string) {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Look around.
|
// Look around.
|
||||||
|
|
||||||
import { readdirSync } from "fs"
|
import { readdirSync } from "fs"
|
||||||
import { NOSE_WWW } from "app/src/config"
|
import { NOSE_WWW } from "@/config"
|
||||||
import { projectName, projectDir } from "@/project"
|
import { projectName, projectDir } from "@/project"
|
||||||
import { sessionGet } from "@/session"
|
import { sessionGet } from "@/session"
|
||||||
|
|
||||||
|
|
@ -2,10 +2,9 @@
|
||||||
//
|
//
|
||||||
// Essentially `mkdir -p`.
|
// Essentially `mkdir -p`.
|
||||||
|
|
||||||
import { mkdirSync } from "fs"
|
import { mkdirSync, readdirSync } from "fs"
|
||||||
import { join } from "path"
|
import { join } from "path"
|
||||||
import { projectDir } from "@/project"
|
import { projectDir } from "@/project"
|
||||||
import { readdirSync } from "fs"
|
|
||||||
import { sessionGet } from "@/session"
|
import { sessionGet } from "@/session"
|
||||||
|
|
||||||
export default async function (path: string) {
|
export default async function (path: string) {
|
||||||
|
|
@ -4,10 +4,9 @@
|
||||||
|
|
||||||
import { mkdirSync, writeFileSync } from "fs"
|
import { mkdirSync, writeFileSync } from "fs"
|
||||||
import { join } from "path"
|
import { join } from "path"
|
||||||
|
import { apps } from "@/webapp"
|
||||||
import { apps } from "app/src/webapp"
|
import { NOSE_WWW } from "@/config"
|
||||||
import { NOSE_WWW } from "app/src/config"
|
import { isDir } from "@/utils"
|
||||||
import { isDir } from "app/src/utils"
|
|
||||||
|
|
||||||
import load from "./load"
|
import load from "./load"
|
||||||
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Show the projects on this NOSEputer.
|
// Show the projects on this NOSEputer.
|
||||||
|
|
||||||
import { apps } from "app/src/webapp"
|
import { apps } from "@/webapp"
|
||||||
import { sessionGet } from "@/session"
|
import { sessionGet } from "@/session"
|
||||||
|
|
||||||
export default function () {
|
export default function () {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Share a webapp with the public internet.
|
// Share a webapp with the public internet.
|
||||||
|
|
||||||
import { apps } from "app/src/webapp"
|
import { apps } from "@/webapp"
|
||||||
import { connectSneaker, sneakers, sneakerUrl } from "app/src/sneaker"
|
import { connectSneaker, sneakers, sneakerUrl } from "@/sneaker"
|
||||||
|
|
||||||
export default async function (app: string) {
|
export default async function (app: string) {
|
||||||
if (!app) {
|
if (!app) {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Stop sharing a webapp with the public internet.
|
// Stop sharing a webapp with the public internet.
|
||||||
|
|
||||||
import { apps } from "app/src/webapp"
|
import { apps } from "@/webapp"
|
||||||
import { disconnectSneaker, sneakers } from "app/src/sneaker"
|
import { disconnectSneaker, sneakers } from "@/sneaker"
|
||||||
|
|
||||||
export default async function (app: string) {
|
export default async function (app: string) {
|
||||||
if (!app) {
|
if (!app) {
|
||||||
0
global.d.ts → nose/global.d.ts
vendored
0
global.d.ts → nose/global.d.ts
vendored
39
nose/tsconfig.json
Normal file
39
nose/tsconfig.json
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
// Environment setup & latest features
|
||||||
|
"lib": [
|
||||||
|
"ESNext",
|
||||||
|
"DOM"
|
||||||
|
],
|
||||||
|
"target": "ESNext",
|
||||||
|
"module": "Preserve",
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"jsxImportSource": "hono/jsx",
|
||||||
|
"allowJs": true,
|
||||||
|
// Bundler mode
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"noEmit": true,
|
||||||
|
// Best practices
|
||||||
|
"strict": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noUncheckedIndexedAccess": true,
|
||||||
|
"noImplicitOverride": true,
|
||||||
|
// Some stricter flags (disabled by default)
|
||||||
|
"noUnusedLocals": false,
|
||||||
|
"noUnusedParameters": false,
|
||||||
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@utils": [
|
||||||
|
"/home/nose/.nose/src/utils.tsx"
|
||||||
|
],
|
||||||
|
"@/*": [
|
||||||
|
"/home/nose/.nose/src/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
nose/www/chris/pub/burger.png
Normal file
BIN
nose/www/chris/pub/burger.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
24
nose/www/chris/pub/index.html
Normal file
24
nose/www/chris/pub/index.html
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>chris!</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<link href="/main.css" rel="stylesheet" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="tile text">
|
||||||
|
<div class="text-content">
|
||||||
|
<h1>@defunkt</h1>
|
||||||
|
<p>This is my website. I am Chris.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tile burger">
|
||||||
|
<img src="burger.png" alt="Burger" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
27
nose/www/chris/pub/main.css
Normal file
27
nose/www/chris/pub/main.css
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tile {
|
||||||
|
flex: 1;
|
||||||
|
/* equal width columns */
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-content {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.burger img {
|
||||||
|
max-width: 90%;
|
||||||
|
max-height: 90%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
BIN
nose/www/corey/pub/hotdog.png
Normal file
BIN
nose/www/corey/pub/hotdog.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 150 KiB |
15
nose/www/corey/pub/index.html
Normal file
15
nose/www/corey/pub/index.html
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>corey</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>@probablycorey</h1>
|
||||||
|
<p>This is my website. I am Corey.</p>
|
||||||
|
<img src="/hotdog.png" />
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
2
nose/www/hello/index.ts
Normal file
2
nose/www/hello/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
export default () =>
|
||||||
|
"hiya"
|
||||||
14
nose/www/hello/pub/index.html
Normal file
14
nose/www/hello/pub/index.html
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>Hello</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>Wolfie Man</h1>
|
||||||
|
<p>Toy Rivian Truck</p>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
49
package.json
49
package.json
|
|
@ -1,29 +1,24 @@
|
||||||
{
|
{
|
||||||
"name": "nose-pluto",
|
"name": "pluto",
|
||||||
"private": true,
|
"module": "src/server.tsx",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"workspaces": [
|
"private": true,
|
||||||
"app"
|
"scripts": {
|
||||||
],
|
"start": "bun src/server.tsx",
|
||||||
"scripts": {
|
"runner": "env NODE_ENV=production bun run src/runner.ts",
|
||||||
"runner": "bun run --cwd ./app runner",
|
"prod": "env NODE_ENV=production bun src/server.tsx",
|
||||||
"dev": "bun run --cwd ./app dev",
|
"dev": "env BUN_HOT=1 bun --hot src/server.tsx",
|
||||||
"start": "bun run --cwd ./app start",
|
"deploy": "./scripts/deploy.sh",
|
||||||
"push": "bun run --cwd ./app push",
|
"push": "./scripts/deploy.sh",
|
||||||
"remote:install": "bun run --cwd ./app remote:install",
|
"remote:install": "./scripts/remote-install.sh",
|
||||||
"remote:start": "bun run --cwd ./app remote:start",
|
"remote:start": "./scripts/remote-start.sh",
|
||||||
"remote:stop": "bun run --cwd ./app remote:stop",
|
"remote:stop": "./scripts/remote-stop.sh",
|
||||||
"remote:restart": "bun run --cwd ./app remote:restart"
|
"remote:restart": "./scripts/remote-restart.sh"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"peerDependencies": {
|
||||||
"hono": "^4.9.7"
|
"typescript": "^5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"dependencies": {
|
||||||
"@types/bun": "latest"
|
"kleur": "^4.1.5"
|
||||||
},
|
|
||||||
"alias": {
|
|
||||||
"@nose": "./app/src/helpers.tsx",
|
|
||||||
"@config": "./app/src/config.ts",
|
|
||||||
"@/*": "./app/src/*"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,5 +3,5 @@
|
||||||
# It isn't enough to modify this yet.
|
# It isn't enough to modify this yet.
|
||||||
# You also need to manually update the nose-pluto.service file.
|
# You also need to manually update the nose-pluto.service file.
|
||||||
HOST="${HOST:-nose@nose-pluto.local}"
|
HOST="${HOST:-nose@nose-pluto.local}"
|
||||||
DEST="${DEST:-~/nose}"
|
DEST="${DEST:-~/.nose}"
|
||||||
REPO="${REPO:-https://git.nose.space/defunkt/nose-pluto}"
|
REPO="${REPO:-https://git.nose.space/defunkt/nose-pluto}"
|
||||||
|
|
@ -3,10 +3,10 @@ set -e
|
||||||
|
|
||||||
# Get absolute path of this script’s directory
|
# Get absolute path of this script’s directory
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
ROOT_DIR="$SCRIPT_DIR/../.."
|
ROOT_DIR="$SCRIPT_DIR/.."
|
||||||
|
|
||||||
# Run deploy + config with absolute paths
|
# Run deploy + config with absolute paths
|
||||||
source "$ROOT_DIR/app/scripts/config.sh"
|
source "$ROOT_DIR/scripts/config.sh"
|
||||||
|
|
||||||
# Make sure we're up-to-date
|
# Make sure we're up-to-date
|
||||||
git push origin main
|
git push origin main
|
||||||
|
|
@ -5,9 +5,10 @@ Wants=network-online.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
User=nose
|
User=nose
|
||||||
WorkingDirectory=/home/nose/nose/app
|
WorkingDirectory=/home/nose/.nose/
|
||||||
Environment=PORT=80
|
Environment=PORT=80
|
||||||
Environment=NODE_ENV=production
|
Environment=NODE_ENV=production
|
||||||
|
Environment=NOSE_DIR=/home/nose/nose/
|
||||||
ExecStart=/home/nose/.bun/bin/bun start
|
ExecStart=/home/nose/.bun/bin/bun start
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=1
|
RestartSec=1
|
||||||
|
|
@ -3,10 +3,10 @@ set -e
|
||||||
|
|
||||||
# Get absolute path of this script’s directory
|
# Get absolute path of this script’s directory
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
ROOT_DIR="$SCRIPT_DIR/../.."
|
ROOT_DIR="$SCRIPT_DIR/.."
|
||||||
|
|
||||||
# Run deploy + config with absolute paths
|
# Run deploy + config with absolute paths
|
||||||
source "$ROOT_DIR/app/scripts/config.sh"
|
source "$ROOT_DIR/scripts/config.sh"
|
||||||
|
|
||||||
# Run remote install on the target
|
# Run remote install on the target
|
||||||
ssh "$HOST" "git clone $REPO $DEST && cd $DEST && ./app/scripts/install.sh && sudo systemctl start nose-pluto.service"
|
ssh "$HOST" "git clone $REPO $DEST && cd $DEST && ./scripts/install.sh && sudo systemctl start nose-pluto.service"
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
ROOT_DIR="$SCRIPT_DIR/../.."
|
ROOT_DIR="$SCRIPT_DIR/.."
|
||||||
|
|
||||||
source "$ROOT_DIR/app/scripts/config.sh"
|
source "$ROOT_DIR/scripts/config.sh"
|
||||||
|
|
||||||
ssh "$HOST" "sudo systemctl restart nose-pluto.service"
|
ssh "$HOST" "sudo systemctl restart nose-pluto.service"
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
ROOT_DIR="$SCRIPT_DIR/../.."
|
ROOT_DIR="$SCRIPT_DIR/.."
|
||||||
|
|
||||||
source "$ROOT_DIR/app/scripts/config.sh"
|
source "$ROOT_DIR/scripts/config.sh"
|
||||||
|
|
||||||
ssh "$HOST" "sudo systemctl start nose-pluto.service"
|
ssh "$HOST" "sudo systemctl start nose-pluto.service"
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
ROOT_DIR="$SCRIPT_DIR/../.."
|
ROOT_DIR="$SCRIPT_DIR/.."
|
||||||
|
|
||||||
source "$ROOT_DIR/app/scripts/config.sh"
|
source "$ROOT_DIR/scripts/config.sh"
|
||||||
|
|
||||||
ssh "$HOST" "sudo systemctl stop nose-pluto.service"
|
ssh "$HOST" "sudo systemctl stop nose-pluto.service"
|
||||||
|
|
@ -9,14 +9,9 @@ import { sendAll } from "./websocket"
|
||||||
import { expectDir } from "./utils"
|
import { expectDir } from "./utils"
|
||||||
import { NOSE_SYS_BIN, NOSE_BIN } from "./config"
|
import { NOSE_SYS_BIN, NOSE_BIN } from "./config"
|
||||||
|
|
||||||
const sysCmdWatcher = watch(NOSE_SYS_BIN, async (event, filename) =>
|
export function initCommands() {
|
||||||
sendAll({ type: "commands", data: await commands() })
|
startWatchers()
|
||||||
)
|
}
|
||||||
|
|
||||||
expectDir(NOSE_BIN)
|
|
||||||
const usrCmdWatcher = watch(NOSE_BIN, async (event, filename) => {
|
|
||||||
sendAll({ type: "commands", data: await commands() })
|
|
||||||
})
|
|
||||||
|
|
||||||
export async function commands(): Promise<string[]> {
|
export async function commands(): Promise<string[]> {
|
||||||
return (await findCommands(NOSE_SYS_BIN)).concat(await findCommands(NOSE_BIN))
|
return (await findCommands(NOSE_SYS_BIN)).concat(await findCommands(NOSE_BIN))
|
||||||
|
|
@ -46,9 +41,22 @@ export function commandExists(cmd: string): boolean {
|
||||||
return commandPath(cmd) !== undefined
|
return commandPath(cmd) !== undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function commandSource(name: string): Promise<string> {
|
export async function commandSource(name: string): Promise<string> {
|
||||||
const path = commandPath(name)
|
const path = commandPath(name)
|
||||||
if (!path) return ""
|
if (!path) return ""
|
||||||
return Bun.file(path).text()
|
return Bun.file(path).text()
|
||||||
|
}
|
||||||
|
|
||||||
|
let sysCmdWatcher
|
||||||
|
let usrCmdWatcher
|
||||||
|
function startWatchers() {
|
||||||
|
expectDir(NOSE_BIN)
|
||||||
|
|
||||||
|
sysCmdWatcher = watch(NOSE_SYS_BIN, async (event, filename) =>
|
||||||
|
sendAll({ type: "commands", data: await commands() })
|
||||||
|
)
|
||||||
|
|
||||||
|
usrCmdWatcher = watch(NOSE_BIN, async (event, filename) => {
|
||||||
|
sendAll({ type: "commands", data: await commands() })
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import { resolve, join } from "node:path"
|
|
||||||
import { $ } from "bun"
|
import { $ } from "bun"
|
||||||
|
import { resolve, join } from "path"
|
||||||
|
import { untilde } from "./utils"
|
||||||
|
|
||||||
export const NOSE_ICON = ` ͡° ͜ʖ ͡°`
|
export const NOSE_ICON = ` ͡° ͜ʖ ͡°`
|
||||||
|
|
||||||
export const NOSE_SYS = resolve("./nose")
|
export const NOSE_SYS_BIN = resolve("./bin")
|
||||||
export const NOSE_SYS_BIN = join(NOSE_SYS, "bin")
|
|
||||||
|
|
||||||
export const NOSE_DIR = resolve("..")
|
export const NOSE_DIR = resolve(untilde(process.env.NOSE_DIR || "./nose"))
|
||||||
export const NOSE_BIN = join(NOSE_DIR, "bin")
|
export const NOSE_BIN = join(NOSE_DIR, "bin")
|
||||||
export const NOSE_WWW = join(NOSE_DIR, "www")
|
export const NOSE_WWW = join(NOSE_DIR, "www")
|
||||||
|
|
||||||
|
|
@ -19,6 +19,7 @@ export async function initDNS() {
|
||||||
if (process.env.NODE_ENV !== "production") return
|
if (process.env.NODE_ENV !== "production") return
|
||||||
dnsInit = true
|
dnsInit = true
|
||||||
|
|
||||||
|
startWatcher()
|
||||||
apps().forEach(publishAppDNS)
|
apps().forEach(publishAppDNS)
|
||||||
|
|
||||||
const signals = ["SIGINT", "SIGTERM"]
|
const signals = ["SIGINT", "SIGTERM"]
|
||||||
|
|
@ -41,15 +42,17 @@ export function publishAppDNS(app: string) {
|
||||||
return dnsEntries[app]
|
return dnsEntries[app]
|
||||||
}
|
}
|
||||||
|
|
||||||
// exit process with error if no WWW dir
|
let wwwWatcher
|
||||||
expectDir(NOSE_WWW)
|
function startWatcher() {
|
||||||
|
expectDir(NOSE_WWW)
|
||||||
|
|
||||||
const wwwWatcher = watch(NOSE_WWW, (event, filename) => {
|
wwwWatcher = watch(NOSE_WWW, (event, filename) => {
|
||||||
const www = apps()
|
const www = apps()
|
||||||
www.forEach(publishAppDNS)
|
www.forEach(publishAppDNS)
|
||||||
for (const name in dnsEntries)
|
for (const name in dnsEntries)
|
||||||
if (!www.includes(name)) {
|
if (!www.includes(name)) {
|
||||||
dnsEntries[name].kill("SIGTERM")
|
dnsEntries[name].kill("SIGTERM")
|
||||||
delete dnsEntries[name]
|
delete dnsEntries[name]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
14
src/nosedir.ts
Normal file
14
src/nosedir.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
////
|
||||||
|
// Creates ~/nose if it doesn't exist
|
||||||
|
|
||||||
|
import { $ } from "bun"
|
||||||
|
import { NOSE_DIR } from "./config"
|
||||||
|
import { isDir } from "./utils"
|
||||||
|
|
||||||
|
// Make NOSE_DIR if it doesn't exist
|
||||||
|
export async function initNoseDir() {
|
||||||
|
if (isDir(NOSE_DIR)) return
|
||||||
|
|
||||||
|
await $`cp -r ./nose ${NOSE_DIR}`
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -7,7 +7,7 @@ import { prettyJSON } from "hono/pretty-json"
|
||||||
import color from "kleur"
|
import color from "kleur"
|
||||||
|
|
||||||
import type { Message } from "./shared/types"
|
import type { Message } from "./shared/types"
|
||||||
import { NOSE_ICON, NOSE_BIN, NOSE_WWW, NOSE_DATA } from "./config"
|
import { NOSE_ICON, NOSE_BIN, NOSE_WWW, NOSE_DATA, NOSE_DIR } from "./config"
|
||||||
import { transpile, isFile, tilde } from "./utils"
|
import { transpile, isFile, tilde } from "./utils"
|
||||||
import { serveApp } from "./webapp"
|
import { serveApp } from "./webapp"
|
||||||
import { initDNS } from "./dns"
|
import { initDNS } from "./dns"
|
||||||
|
|
@ -18,6 +18,8 @@ import { Layout } from "./html/layout"
|
||||||
import { Terminal } from "./html/terminal"
|
import { Terminal } from "./html/terminal"
|
||||||
import { dispatchMessage } from "./dispatch"
|
import { dispatchMessage } from "./dispatch"
|
||||||
import { initSneakers, disconnectSneakers } from "./sneaker"
|
import { initSneakers, disconnectSneakers } from "./sneaker"
|
||||||
|
import { initNoseDir } from "./nosedir"
|
||||||
|
import { initCommands } from "./commands"
|
||||||
|
|
||||||
//
|
//
|
||||||
// Hono setup
|
// Hono setup
|
||||||
|
|
@ -155,9 +157,12 @@ if (process.env.NODE_ENV === "production") {
|
||||||
|
|
||||||
console.log(color.cyan(NOSE_ICON))
|
console.log(color.cyan(NOSE_ICON))
|
||||||
console.log(color.blue("NOSE_DATA:"), color.yellow(tilde(NOSE_DATA)))
|
console.log(color.blue("NOSE_DATA:"), color.yellow(tilde(NOSE_DATA)))
|
||||||
|
console.log(color.blue("NOSE_DIR:"), color.yellow(tilde(NOSE_DIR)))
|
||||||
console.log(color.blue("NOSE_BIN:"), color.yellow(tilde(NOSE_BIN)))
|
console.log(color.blue("NOSE_BIN:"), color.yellow(tilde(NOSE_BIN)))
|
||||||
console.log(color.blue("NOSE_WWW:"), color.yellow(tilde(NOSE_WWW)))
|
console.log(color.blue("NOSE_WWW:"), color.yellow(tilde(NOSE_WWW)))
|
||||||
|
|
||||||
|
await initNoseDir()
|
||||||
|
initCommands()
|
||||||
initSneakers()
|
initSneakers()
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
// with the public internet. It requires a sneaker server, usually hosted by us.
|
// with the public internet. It requires a sneaker server, usually hosted by us.
|
||||||
|
|
||||||
import nose from "./server"
|
import nose from "./server"
|
||||||
import { clearState, setState, getState } from "app/src/state"
|
import { clearState, setState, getState } from "./state"
|
||||||
|
|
||||||
const SNEAKER_URL = "nose.space"
|
const SNEAKER_URL = "nose.space"
|
||||||
const SNEAKER_TLS = true
|
const SNEAKER_TLS = true
|
||||||
|
|
@ -3,16 +3,23 @@
|
||||||
|
|
||||||
import { statSync } from "fs"
|
import { statSync } from "fs"
|
||||||
import { basename } from "path"
|
import { basename } from "path"
|
||||||
import { stat } from "node:fs/promises"
|
import { stat } from "fs/promises"
|
||||||
|
|
||||||
import { NOSE_ICON } from "./config"
|
// Convert /Users/$USER or /home/$USER to ~ for simplicity
|
||||||
|
export function tilde(path: string): string {
|
||||||
|
return path.replace(new RegExp(`/(Users|home)/${process.env.USER}`), "~")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert ~ to /Users/$USER or /home/$USER for simplicity
|
||||||
|
export function untilde(path: string): string {
|
||||||
|
const prefix = process.platform === 'darwin' ? 'Users' : 'home'
|
||||||
|
return path.replace("~", `/${prefix}/${process.env.USER}`)
|
||||||
|
}
|
||||||
|
|
||||||
// End the process with an instructive error if a directory doesn't exist.
|
// End the process with an instructive error if a directory doesn't exist.
|
||||||
export function expectDir(path: string) {
|
export function expectDir(path: string) {
|
||||||
if (!isDir(path)) {
|
if (!isDir(path)) {
|
||||||
console.error(NOSE_ICON)
|
console.error(`No ${basename(path)} directory detected.`)
|
||||||
console.error(`No ${basename(path)} directory detected. Please run:`)
|
|
||||||
console.error("\tmkdir -p", path)
|
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -70,11 +77,6 @@ export async function isBinaryFile(path: string): Promise<boolean> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert /Users/$USER or /home/$USER to ~ for simplicity
|
|
||||||
export function tilde(path: string): string {
|
|
||||||
return path.replace(new RegExp(`/(Users|home)/${process.env.USER}`), "~")
|
|
||||||
}
|
|
||||||
|
|
||||||
const transpiler = new Bun.Transpiler({ loader: 'tsx' })
|
const transpiler = new Bun.Transpiler({ loader: 'tsx' })
|
||||||
const transpileCache: Record<string, string> = {}
|
const transpileCache: Record<string, string> = {}
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user