feat(deploy): run shared toolkit socket
Lint and Build Checks / Lint, Test, and Build (push) Failing after 364h2m28s

This commit is contained in:
2026-06-24 15:35:08 -05:00
parent 47567589e4
commit 79d36c4e2d
15 changed files with 443 additions and 95 deletions
+41
View File
@@ -0,0 +1,41 @@
# Toolkit Socket
The Toolkit socket is a local/shared Socket.IO authoring server for browser-only Toolkit workflows.
## Local Development
```bash
npm run dev:toolkit
curl http://127.0.0.1:5174/health
```
Default local settings:
- host: `127.0.0.1`
- port: `5174`
- CORS origin: `http://127.0.0.1:5173`
## Shared Deployment
The deployed browser app at `http://bone-kingdom.tabitha.tealthrone/` connects to:
```text
http://bone-kingdom.tabitha.tealthrone:5174
```
Woodpecker restarts this socket from the shared repo workspace with:
```bash
TOOLKIT_SOCKET_HOST=0.0.0.0 \
TOOLKIT_SOCKET_PORT=5174 \
TOOLKIT_SOCKET_CORS_ORIGIN='http://127.0.0.1:5173,http://localhost:5173,http://bone-kingdom.tabitha.tealthrone' \
sh scripts/deploy/restart-toolkit-socket.sh
```
Running from the repo workspace is intentional. Toolkit edits made from the deployed browser update the same source files used during development:
- `src/data/toolkit/*.json`
- `src/assets/images/uploads/`
- `src/assets/music/uploads/`
The deploy script syncs socket code and scripts, but uses `--ignore-existing` for Toolkit JSON and uploaded assets so live content edits are not overwritten by routine deploys.
+49 -21
View File
@@ -3,6 +3,7 @@ import 'dotenv/config';
import { watch } from 'node:fs';
import { mkdir, writeFile } from 'node:fs/promises';
import { createServer } from 'node:http';
import { createRequire } from 'node:module';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
@@ -11,6 +12,8 @@ import { Server } from 'socket.io';
import contentStore from './contentStore.cjs';
const repositoryRoot = fileURLToPath(new URL('..', import.meta.url));
const require = createRequire(import.meta.url);
const packageJson = require('../package.json');
const defaultWebOrigin = 'http://127.0.0.1:5173';
const host = process.env.TOOLKIT_SOCKET_HOST ?? '127.0.0.1';
const port = Number.parseInt(process.env.TOOLKIT_SOCKET_PORT ?? '5174', 10);
@@ -25,29 +28,46 @@ if (Number.isNaN(port)) {
throw new Error('TOOLKIT_SOCKET_PORT must be a valid number.');
}
const socketHealthStartedAt = Date.now();
const socketHealthStartedAtIso = new Date(socketHealthStartedAt).toISOString();
function createSocketHealthPayload() {
return {
ok: true,
service: 'blb-toolkit-socket',
version: packageJson.version,
startedAt: socketHealthStartedAtIso,
timestamp: new Date().toISOString(),
uptimeSeconds: Math.max(
0,
Math.round((Date.now() - socketHealthStartedAt) / 1000),
),
};
}
function writeJsonResponse(response, statusCode, body) {
response.writeHead(statusCode, {
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Methods': 'GET, HEAD, OPTIONS',
'Access-Control-Allow-Origin': '*',
'Cache-Control': 'no-store',
'Content-Type': 'application/json',
});
response.end(`${JSON.stringify(body)}\n`);
}
const httpServer = createServer((request, response) => {
if (request.url === '/health') {
response.writeHead(200, {
'Content-Type': 'application/json',
});
response.end(
JSON.stringify({
ok: true,
service: 'blb-toolkit-socket',
}),
);
const pathname = request.url?.split('?')[0];
if (pathname === '/health') {
writeJsonResponse(response, 200, createSocketHealthPayload());
return;
}
response.writeHead(404, {
'Content-Type': 'application/json',
writeJsonResponse(response, 404, {
ok: false,
service: 'blb-toolkit-socket',
});
response.end(
JSON.stringify({
ok: false,
service: 'blb-toolkit-socket',
}),
);
});
const io = new Server(httpServer, {
@@ -73,7 +93,9 @@ const assetUploadConfig = {
};
function getErrorMessage(error) {
return error instanceof Error ? error.message : 'Unknown toolkit content error.';
return error instanceof Error
? error.message
: 'Unknown toolkit content error.';
}
function createContentError(resource, error) {
@@ -237,7 +259,10 @@ io.on('connection', socket => {
const resource = payload?.resource;
try {
const changedContent = await createContentRecord(resource, payload?.record);
const changedContent = await createContentRecord(
resource,
payload?.record,
);
respond?.({
ok: true,
@@ -259,7 +284,10 @@ io.on('connection', socket => {
const resource = payload?.resource;
try {
const changedContent = await updateContentRecord(resource, payload?.record);
const changedContent = await updateContentRecord(
resource,
payload?.record,
);
respond?.({
ok: true,