첫 커밋: 로컬 프로젝트 업로드

This commit is contained in:
2026-06-10 15:51:34 +09:00
commit 6a8dbeb2e9
1211 changed files with 312864 additions and 0 deletions

View File

@@ -0,0 +1,144 @@
#!/usr/bin/env sh
set -eu
app_env="$(printf '%s' "${APP_ENV:-development}" | tr '[:upper:]' '[:lower:]')"
if [ -z "${VITE_ADMIN_PUBLIC_URL:-}" ] && [ -n "${ADMINFRONT_URL:-}" ]; then
export VITE_ADMIN_PUBLIC_URL="$ADMINFRONT_URL"
fi
if [ -z "${VITE_ADMIN_PUBLIC_URL:-}" ] && [ -n "${ADMINFRONT_CALLBACK_URLS:-}" ]; then
first_admin_callback="${ADMINFRONT_CALLBACK_URLS%%,*}"
case "$first_admin_callback" in
http://*/auth/callback | https://*/auth/callback)
export VITE_ADMIN_PUBLIC_URL="${first_admin_callback%/auth/callback}"
;;
esac
fi
case "$app_env" in
production|prod|stage|staging)
mode="production"
;;
*)
mode="development"
;;
esac
if [ "${1:-}" = "--print-admin-public-url" ]; then
printf '%s\n' "${VITE_ADMIN_PUBLIC_URL:-}"
exit 0
fi
if [ "${1:-}" = "--print-mode" ]; then
printf '%s\n' "$mode"
exit 0
fi
ensure_frontend_dependencies() {
APP_PACKAGE_NAME="adminfront"
# Detect workspace root
if [ -f "/workspace/pnpm-workspace.yaml" ]; then
WORKSPACE_ROOT="/workspace"
elif [ -f "../../pnpm-workspace.yaml" ]; then
WORKSPACE_ROOT="../.."
else
WORKSPACE_ROOT=""
fi
# Manage dependencies from the real workspace tree if possible, otherwise use current dir.
if [ -n "$WORKSPACE_ROOT" ]; then
WORKSPACE_DIR="$WORKSPACE_ROOT"
LOCK_FILE="$WORKSPACE_ROOT/pnpm-lock.yaml"
COMMON_PACKAGE_FILE="$WORKSPACE_ROOT/common/package.json"
INSTALL_CMD="cd $WORKSPACE_ROOT && CI=true pnpm install --filter ${APP_PACKAGE_NAME}... --frozen-lockfile --ignore-scripts"
elif [ -f "pnpm-lock.yaml" ]; then
WORKSPACE_DIR="."
LOCK_FILE="pnpm-lock.yaml"
COMMON_PACKAGE_FILE="/workspace/common/package.json"
INSTALL_CMD="CI=true pnpm install --frozen-lockfile --ignore-scripts"
else
WORKSPACE_DIR="."
LOCK_FILE="package-lock.json"
COMMON_PACKAGE_FILE="/workspace/common/package.json"
INSTALL_CMD="npm ci"
fi
if [ ! -f "$WORKSPACE_DIR/package.json" ]; then
return 0
fi
lock_mode=""
lock_file="$WORKSPACE_DIR/.baron-deps-install.lock"
acquire_install_lock() {
if command -v flock >/dev/null 2>&1; then
lock_mode="flock"
exec 9>"$lock_file"
flock 9
trap 'release_install_lock' EXIT INT TERM
return 0
fi
lock_mode="mkdir"
while ! mkdir "$lock_file" 2>/dev/null; do
sleep 1
done
trap 'release_install_lock' EXIT INT TERM
}
release_install_lock() {
trap - EXIT INT TERM
if [ "$lock_mode" = "flock" ]; then
flock -u 9 || true
exec 9>&-
return 0
fi
if [ "$lock_mode" = "mkdir" ]; then
rmdir "$lock_file" >/dev/null 2>&1 || true
fi
}
if command -v sha256sum >/dev/null 2>&1; then
deps_hash="$(sha256sum "$WORKSPACE_DIR/package.json" "$LOCK_FILE" "$COMMON_PACKAGE_FILE" package.json 2>/dev/null | sha256sum | awk '{print $1}')"
else
deps_hash="$(cksum "$WORKSPACE_DIR/package.json" "$LOCK_FILE" "$COMMON_PACKAGE_FILE" package.json 2>/dev/null | cksum | awk '{print $1}')"
fi
deps_stamp="node_modules/.baron-deps-hash"
installed_hash="$(cat "$deps_stamp" 2>/dev/null || true)"
if [ "$installed_hash" != "$deps_hash" ]; then
echo "Installing frontend dependencies..."
acquire_install_lock
if command -v sha256sum >/dev/null 2>&1; then
deps_hash="$(sha256sum "$WORKSPACE_DIR/package.json" "$LOCK_FILE" "$COMMON_PACKAGE_FILE" package.json 2>/dev/null | sha256sum | awk '{print $1}')"
else
deps_hash="$(cksum "$WORKSPACE_DIR/package.json" "$LOCK_FILE" "$COMMON_PACKAGE_FILE" package.json 2>/dev/null | cksum | awk '{print $1}')"
fi
installed_hash="$(cat "$deps_stamp" 2>/dev/null || true)"
if [ "$installed_hash" = "$deps_hash" ]; then
release_install_lock
return 0
fi
eval "$INSTALL_CMD"
mkdir -p node_modules
printf '%s\n' "$deps_hash" > "$deps_stamp"
release_install_lock
fi
}
ensure_frontend_dependencies
if [ "$mode" = "production" ]; then
echo "Running in production mode with custom static server..."
export ADMINFRONT_BUILD_OUT_DIR="${ADMINFRONT_BUILD_OUT_DIR:-/tmp/baron-sso-adminfront-dist}"
exec sh -c "npm run build && node ./scripts/serve-prod.mjs"
fi
echo "Running in development mode..."
exec npm run dev -- --host 0.0.0.0

View File

@@ -0,0 +1,160 @@
import { readFile, stat } from "node:fs/promises";
import { createServer } from "node:http";
import { extname, join, normalize, resolve } from "node:path";
import { fileURLToPath } from "node:url";
const _rootDir = fileURLToPath(new URL("..", import.meta.url));
const distDir = resolve(
process.env.ADMINFRONT_BUILD_OUT_DIR ?? "/tmp/baron-sso-adminfront-dist",
);
const host = process.env.HOST ?? "0.0.0.0";
const port = Number(process.env.PORT ?? process.env.ADMINFRONT_PORT ?? 5173);
const backendTarget = new URL(
process.env.API_PROXY_TARGET || "http://localhost:3000",
);
const contentTypes = {
".css": "text/css; charset=utf-8",
".html": "text/html; charset=utf-8",
".js": "application/javascript; charset=utf-8",
".json": "application/json; charset=utf-8",
".map": "application/json; charset=utf-8",
".mjs": "application/javascript; charset=utf-8",
".svg": "image/svg+xml",
};
function getContentType(filePath) {
return (
contentTypes[extname(filePath).toLowerCase()] ?? "application/octet-stream"
);
}
function sendJson(res, statusCode, body) {
res.writeHead(statusCode, {
"Content-Type": "application/json; charset=utf-8",
"Cache-Control": "no-store",
});
res.end(JSON.stringify(body));
}
function toSafePath(pathname) {
const decoded = decodeURIComponent(pathname);
const relative = decoded.replace(/^\/+/, "");
const safe = normalize(relative).replace(/^(\.\.(?:[\\/]|$))+/, "");
return join(distDir, safe);
}
async function tryReadFile(filePath) {
try {
return await readFile(filePath);
} catch {
return null;
}
}
async function proxyToBackend(req, res, pathname, search) {
const target = new URL(pathname + search, backendTarget);
const headers = new Headers();
for (const [key, value] of Object.entries(req.headers)) {
if (!value) continue;
if (key === "host" || key === "content-length" || key === "connection") {
continue;
}
if (Array.isArray(value)) {
headers.set(key, value.join(", "));
continue;
}
headers.set(key, value);
}
const hasBody = !["GET", "HEAD"].includes(req.method ?? "GET");
const response = await fetch(target, {
method: req.method,
headers,
body: hasBody ? req : undefined,
duplex: hasBody ? "half" : undefined,
});
const responseHeaders = new Headers(response.headers);
responseHeaders.delete("content-length");
responseHeaders.delete("transfer-encoding");
responseHeaders.delete("connection");
res.writeHead(response.status, Object.fromEntries(responseHeaders.entries()));
if (req.method === "HEAD") {
res.end();
return;
}
const arrayBuffer = await response.arrayBuffer();
res.end(Buffer.from(arrayBuffer));
}
async function serveStatic(req, res, pathname) {
const indexPath = join(distDir, "index.html");
const filePath = toSafePath(pathname);
let resolvedPath = filePath;
try {
const fileStat = await stat(resolvedPath);
if (fileStat.isDirectory()) {
resolvedPath = join(resolvedPath, "index.html");
}
} catch {
resolvedPath = indexPath;
}
let body = await tryReadFile(resolvedPath);
if (!body) {
body = await tryReadFile(indexPath);
resolvedPath = indexPath;
}
if (!body) {
sendJson(res, 500, { error: "dist_not_found" });
return;
}
res.writeHead(200, {
"Content-Type": getContentType(resolvedPath),
"Cache-Control": resolvedPath.endsWith("index.html")
? "no-cache"
: "public, max-age=31536000, immutable",
});
if (req.method === "HEAD") {
res.end();
return;
}
res.end(body);
}
createServer(async (req, res) => {
try {
const url = new URL(
req.url ?? "/",
`http://${req.headers.host ?? "localhost"}`,
);
const { pathname, search } = url;
if (pathname === "/api" || pathname.startsWith("/api/")) {
await proxyToBackend(req, res, pathname, search);
return;
}
const normalizedPath = pathname === "/" ? "/index.html" : pathname;
await serveStatic(req, res, normalizedPath);
} catch (error) {
sendJson(res, 500, {
error: "internal_server_error",
message: error instanceof Error ? error.message : String(error),
});
}
}).listen(port, host, () => {
console.log(
`Adminfront production server listening on http://${host}:${port}`,
);
});