Compare commits

..

1 Commits
1.3.2 ... sort

Author SHA1 Message Date
79552b90a3 Sort non managed stack to the end 2023-12-03 21:19:53 +08:00
14 changed files with 82 additions and 172 deletions

View File

@ -1,3 +1,4 @@
title: "❓ Ask for help"
labels: [help] labels: [help]
body: body:
- type: checkboxes - type: checkboxes

View File

@ -1,3 +1,4 @@
title: 🚀 Feature Request
labels: [feature-request] labels: [feature-request]
body: body:
- type: checkboxes - type: checkboxes

View File

@ -1,14 +1,14 @@
name: "⚠️ Ask for help (Please go to the \"Discussions\" tab to submit a Help Request)" name: " Ask for help"
description: "⚠️ Please go to the \"Discussions\" tab to submit a Help Request" description: "Please go to the Discussions tab to submit a Help Request"
body: body:
- type: markdown - type: markdown
attributes: attributes:
value: | value: |
⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ Please go to https://github.com/louislam/dockge/discussions/new?category=ask-for-help Please go to https://github.com/louislam/dockge/discussions/new?category=ask-for-help
- type: checkboxes - type: checkboxes
id: no-duplicate-issues id: no-duplicate-issues
attributes: attributes:
label: "Issues are for bug reports only, please go to the \"Discussions\" tab to submit a Feature Request" label: "Issues are for bug reports only"
options: options:
- label: "I understand" - label: "I understand"
required: true required: true

View File

@ -1,14 +1,14 @@
name: 🚀 Feature Request (Please go to the "Discussions" tab to submit a Feature Request) name: 🚀 Feature Request
description: "⚠️ Please go to the \"Discussions\" tab to submit a Feature Request" description: "Please go to the Discussions tab to submit a Feature Request"
body: body:
- type: markdown - type: markdown
attributes: attributes:
value: | value: |
⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ Please go to https://github.com/louislam/dockge/discussions/new?category=ask-for-help Please go to https://github.com/louislam/dockge/discussions/new?category=feature-request
- type: checkboxes - type: checkboxes
id: no-duplicate-issues id: no-duplicate-issues
attributes: attributes:
label: "Issues are for bug reports only, please go to the \"Discussions\" tab to submit a Feature Request" label: "Issues are for bug reports only"
options: options:
- label: "I understand" - label: "I understand"
required: true required: true

View File

@ -29,11 +29,9 @@ import { Stack } from "./stack";
import { Cron } from "croner"; import { Cron } from "croner";
import gracefulShutdown from "http-graceful-shutdown"; import gracefulShutdown from "http-graceful-shutdown";
import User from "./models/user"; import User from "./models/user";
import childProcessAsync from "promisify-child-process"; import childProcess from "child_process";
import { Terminal } from "./terminal"; import { Terminal } from "./terminal";
import "dotenv/config";
export class DockgeServer { export class DockgeServer {
app : Express; app : Express;
httpServer : http.Server; httpServer : http.Server;
@ -485,7 +483,7 @@ export class DockgeServer {
return jwtSecretBean; return jwtSecretBean;
} }
async sendStackList(useCache = false) { sendStackList(useCache = false) {
let roomList = this.io.sockets.adapter.rooms.keys(); let roomList = this.io.sockets.adapter.rooms.keys();
let map : Map<string, object> | undefined; let map : Map<string, object> | undefined;
@ -496,7 +494,7 @@ export class DockgeServer {
// Get the list only if there is a room // Get the list only if there is a room
if (!map) { if (!map) {
map = new Map(); map = new Map();
let stackList = await Stack.getStackList(this, useCache); let stackList = Stack.getStackList(this, useCache);
for (let [ stackName, stack ] of stackList) { for (let [ stackName, stack ] of stackList) {
map.set(stackName, stack.toSimpleJSON()); map.set(stackName, stack.toSimpleJSON());
@ -512,8 +510,8 @@ export class DockgeServer {
} }
} }
async sendStackStatusList() { sendStackStatusList() {
let statusList = await Stack.getStatusList(); let statusList = Stack.getStatusList();
let roomList = this.io.sockets.adapter.rooms.keys(); let roomList = this.io.sockets.adapter.rooms.keys();
@ -531,15 +529,8 @@ export class DockgeServer {
} }
} }
async getDockerNetworkList() : Promise<string[]> { getDockerNetworkList() : string[] {
let res = await childProcessAsync.spawn("docker", [ "network", "ls", "--format", "{{.Name}}" ], { let res = childProcess.spawnSync("docker", [ "network", "ls", "--format", "{{.Name}}" ]);
encoding: "utf-8",
});
if (!res.stdout) {
return [];
}
let list = res.stdout.toString().split("\n"); let list = res.stdout.toString().split("\n");
// Remove empty string item // Remove empty string item

View File

@ -12,7 +12,7 @@ export class DockerSocketHandler extends SocketHandler {
socket.on("deployStack", async (name : unknown, composeYAML : unknown, composeENV : unknown, isAdd : unknown, callback) => { socket.on("deployStack", async (name : unknown, composeYAML : unknown, composeENV : unknown, isAdd : unknown, callback) => {
try { try {
checkLogin(socket); checkLogin(socket);
const stack = await this.saveStack(socket, server, name, composeYAML, composeENV, isAdd); const stack = this.saveStack(socket, server, name, composeYAML, composeENV, isAdd);
await stack.deploy(socket); await stack.deploy(socket);
server.sendStackList(); server.sendStackList();
callback({ callback({
@ -45,7 +45,7 @@ export class DockerSocketHandler extends SocketHandler {
if (typeof(name) !== "string") { if (typeof(name) !== "string") {
throw new ValidationError("Name must be a string"); throw new ValidationError("Name must be a string");
} }
const stack = await Stack.getStack(server, name); const stack = Stack.getStack(server, name);
try { try {
await stack.delete(socket); await stack.delete(socket);
@ -65,7 +65,7 @@ export class DockerSocketHandler extends SocketHandler {
} }
}); });
socket.on("getStack", async (stackName : unknown, callback) => { socket.on("getStack", (stackName : unknown, callback) => {
try { try {
checkLogin(socket); checkLogin(socket);
@ -73,7 +73,7 @@ export class DockerSocketHandler extends SocketHandler {
throw new ValidationError("Stack name must be a string"); throw new ValidationError("Stack name must be a string");
} }
const stack = await Stack.getStack(server, stackName); const stack = Stack.getStack(server, stackName);
if (stack.isManagedByDockge) { if (stack.isManagedByDockge) {
stack.joinCombinedTerminal(socket); stack.joinCombinedTerminal(socket);
@ -111,7 +111,7 @@ export class DockerSocketHandler extends SocketHandler {
throw new ValidationError("Stack name must be a string"); throw new ValidationError("Stack name must be a string");
} }
const stack = await Stack.getStack(server, stackName); const stack = Stack.getStack(server, stackName);
await stack.start(socket); await stack.start(socket);
callback({ callback({
ok: true, ok: true,
@ -135,7 +135,7 @@ export class DockerSocketHandler extends SocketHandler {
throw new ValidationError("Stack name must be a string"); throw new ValidationError("Stack name must be a string");
} }
const stack = await Stack.getStack(server, stackName); const stack = Stack.getStack(server, stackName);
await stack.stop(socket); await stack.stop(socket);
callback({ callback({
ok: true, ok: true,
@ -156,7 +156,7 @@ export class DockerSocketHandler extends SocketHandler {
throw new ValidationError("Stack name must be a string"); throw new ValidationError("Stack name must be a string");
} }
const stack = await Stack.getStack(server, stackName); const stack = Stack.getStack(server, stackName);
await stack.restart(socket); await stack.restart(socket);
callback({ callback({
ok: true, ok: true,
@ -177,7 +177,7 @@ export class DockerSocketHandler extends SocketHandler {
throw new ValidationError("Stack name must be a string"); throw new ValidationError("Stack name must be a string");
} }
const stack = await Stack.getStack(server, stackName); const stack = Stack.getStack(server, stackName);
await stack.update(socket); await stack.update(socket);
callback({ callback({
ok: true, ok: true,
@ -198,7 +198,7 @@ export class DockerSocketHandler extends SocketHandler {
throw new ValidationError("Stack name must be a string"); throw new ValidationError("Stack name must be a string");
} }
const stack = await Stack.getStack(server, stackName); const stack = Stack.getStack(server, stackName);
await stack.down(socket); await stack.down(socket);
callback({ callback({
ok: true, ok: true,
@ -219,7 +219,7 @@ export class DockerSocketHandler extends SocketHandler {
throw new ValidationError("Stack name must be a string"); throw new ValidationError("Stack name must be a string");
} }
const stack = await Stack.getStack(server, stackName, true); const stack = Stack.getStack(server, stackName, true);
const serviceStatusList = Object.fromEntries(await stack.getServiceStatusList()); const serviceStatusList = Object.fromEntries(await stack.getServiceStatusList());
callback({ callback({
ok: true, ok: true,
@ -234,7 +234,7 @@ export class DockerSocketHandler extends SocketHandler {
socket.on("getDockerNetworkList", async (callback) => { socket.on("getDockerNetworkList", async (callback) => {
try { try {
checkLogin(socket); checkLogin(socket);
const dockerNetworkList = await server.getDockerNetworkList(); const dockerNetworkList = server.getDockerNetworkList();
callback({ callback({
ok: true, ok: true,
dockerNetworkList, dockerNetworkList,
@ -264,7 +264,7 @@ export class DockerSocketHandler extends SocketHandler {
}); });
} }
async saveStack(socket : DockgeSocket, server : DockgeServer, name : unknown, composeYAML : unknown, composeENV : unknown, isAdd : unknown) : Promise<Stack> { saveStack(socket : DockgeSocket, server : DockgeServer, name : unknown, composeYAML : unknown, composeENV : unknown, isAdd : unknown) : Stack {
// Check types // Check types
if (typeof(name) !== "string") { if (typeof(name) !== "string") {
throw new ValidationError("Name must be a string"); throw new ValidationError("Name must be a string");
@ -280,7 +280,7 @@ export class DockerSocketHandler extends SocketHandler {
} }
const stack = new Stack(server, name, composeYAML, composeENV, false); const stack = new Stack(server, name, composeYAML, composeENV, false);
await stack.save(isAdd); stack.save(isAdd);
return stack; return stack;
} }

View File

@ -101,7 +101,7 @@ export class TerminalSocketHandler extends SocketHandler {
log.debug("interactiveTerminal", "Service name: " + serviceName); log.debug("interactiveTerminal", "Service name: " + serviceName);
// Get stack // Get stack
const stack = await Stack.getStack(server, stackName); const stack = Stack.getStack(server, stackName);
stack.joinContainerTerminal(socket, serviceName, shell); stack.joinContainerTerminal(socket, serviceName, shell);
callback({ callback({
@ -151,7 +151,7 @@ export class TerminalSocketHandler extends SocketHandler {
throw new ValidationError("Stack name must be a string."); throw new ValidationError("Stack name must be a string.");
} }
const stack = await Stack.getStack(server, stackName); const stack = Stack.getStack(server, stackName);
await stack.leaveCombinedTerminal(socket); await stack.leaveCombinedTerminal(socket);
callback({ callback({

View File

@ -1,8 +1,8 @@
import { DockgeServer } from "./dockge-server"; import { DockgeServer } from "./dockge-server";
import fs, { promises as fsAsync } from "fs"; import fs from "fs";
import { log } from "./log"; import { log } from "./log";
import yaml from "yaml"; import yaml from "yaml";
import { DockgeSocket, fileExists, ValidationError } from "./util-server"; import { DockgeSocket, ValidationError } from "./util-server";
import path from "path"; import path from "path";
import { import {
COMBINED_TERMINAL_COLS, COMBINED_TERMINAL_COLS,
@ -16,7 +16,7 @@ import {
UNKNOWN UNKNOWN
} from "./util-common"; } from "./util-common";
import { InteractiveTerminal, Terminal } from "./terminal"; import { InteractiveTerminal, Terminal } from "./terminal";
import childProcessAsync from "promisify-child-process"; import childProcess from "child_process";
export class Stack { export class Stack {
@ -72,15 +72,11 @@ export class Stack {
/** /**
* Get the status of the stack from `docker compose ps --format json` * Get the status of the stack from `docker compose ps --format json`
*/ */
async ps() : Promise<object> { ps() : object {
let res = await childProcessAsync.spawn("docker", [ "compose", "ps", "--format", "json" ], { let res = childProcess.execSync("docker compose ps --format json", {
cwd: this.path, cwd: this.path
encoding: "utf-8",
}); });
if (!res.stdout) { return JSON.parse(res.toString());
return {};
}
return JSON.parse(res.stdout.toString());
} }
get isManagedByDockge() : boolean { get isManagedByDockge() : boolean {
@ -99,15 +95,6 @@ export class Stack {
// Check YAML format // Check YAML format
yaml.parse(this.composeYAML); yaml.parse(this.composeYAML);
let lines = this.composeENV.split("\n");
// Check if the .env is able to pass docker-compose
// Prevent "setenv: The parameter is incorrect"
// It only happens when there is one line and it doesn't contain "="
if (lines.length === 1 && !lines[0].includes("=") && lines[0].length > 0) {
throw new ValidationError("Invalid .env format");
}
} }
get composeYAML() : string { get composeYAML() : string {
@ -155,35 +142,29 @@ export class Stack {
* Save the stack to the disk * Save the stack to the disk
* @param isAdd * @param isAdd
*/ */
async save(isAdd : boolean) { save(isAdd : boolean) {
this.validate(); this.validate();
let dir = this.path; let dir = this.path;
// Check if the name is used if isAdd // Check if the name is used if isAdd
if (isAdd) { if (isAdd) {
if (await fileExists(dir)) { if (fs.existsSync(dir)) {
throw new ValidationError("Stack name already exists"); throw new ValidationError("Stack name already exists");
} }
// Create the stack folder // Create the stack folder
await fsAsync.mkdir(dir); fs.mkdirSync(dir);
} else { } else {
if (!await fileExists(dir)) { if (!fs.existsSync(dir)) {
throw new ValidationError("Stack not found"); throw new ValidationError("Stack not found");
} }
} }
// Write or overwrite the compose.yaml // Write or overwrite the compose.yaml
await fsAsync.writeFile(path.join(dir, this._composeFileName), this.composeYAML); fs.writeFileSync(path.join(dir, this._composeFileName), this.composeYAML);
const envPath = path.join(dir, ".env");
// Write or overwrite the .env // Write or overwrite the .env
// If .env is not existing and the composeENV is empty, we don't need to write it fs.writeFileSync(path.join(dir, ".env"), this.composeENV);
if (await fileExists(envPath) || this.composeENV.trim() !== "") {
await fsAsync.writeFile(envPath, this.composeENV);
}
} }
async deploy(socket? : DockgeSocket) : Promise<number> { async deploy(socket? : DockgeSocket) : Promise<number> {
@ -203,7 +184,7 @@ export class Stack {
} }
// Remove the stack folder // Remove the stack folder
await fsAsync.rm(this.path, { fs.rmSync(this.path, {
recursive: true, recursive: true,
force: true force: true
}); });
@ -211,8 +192,8 @@ export class Stack {
return exitCode; return exitCode;
} }
async updateStatus() { updateStatus() {
let statusList = await Stack.getStatusList(); let statusList = Stack.getStatusList();
let status = statusList.get(this.name); let status = statusList.get(this.name);
if (status) { if (status) {
@ -222,7 +203,7 @@ export class Stack {
} }
} }
static async getStackList(server : DockgeServer, useCacheForManaged = false) : Promise<Map<string, Stack>> { static getStackList(server : DockgeServer, useCacheForManaged = false) : Map<string, Stack> {
let stacksDir = server.stacksDir; let stacksDir = server.stacksDir;
let stackList : Map<string, Stack>; let stackList : Map<string, Stack>;
@ -233,16 +214,16 @@ export class Stack {
stackList = new Map<string, Stack>(); stackList = new Map<string, Stack>();
// Scan the stacks directory, and get the stack list // Scan the stacks directory, and get the stack list
let filenameList = await fsAsync.readdir(stacksDir); let filenameList = fs.readdirSync(stacksDir);
for (let filename of filenameList) { for (let filename of filenameList) {
try { try {
// Check if it is a directory // Check if it is a directory
let stat = await fsAsync.stat(path.join(stacksDir, filename)); let stat = fs.statSync(path.join(stacksDir, filename));
if (!stat.isDirectory()) { if (!stat.isDirectory()) {
continue; continue;
} }
let stack = await this.getStack(server, filename); let stack = this.getStack(server, filename);
stack._status = CREATED_FILE; stack._status = CREATED_FILE;
stackList.set(filename, stack); stackList.set(filename, stack);
} catch (e) { } catch (e) {
@ -257,15 +238,8 @@ export class Stack {
} }
// Get status from docker compose ls // Get status from docker compose ls
let res = await childProcessAsync.spawn("docker", [ "compose", "ls", "--all", "--format", "json" ], { let res = childProcess.execSync("docker compose ls --all --format json");
encoding: "utf-8", let composeList = JSON.parse(res.toString());
});
if (!res.stdout) {
return stackList;
}
let composeList = JSON.parse(res.stdout.toString());
for (let composeStack of composeList) { for (let composeStack of composeList) {
let stack = stackList.get(composeStack.Name); let stack = stackList.get(composeStack.Name);
@ -291,18 +265,11 @@ export class Stack {
* Get the status list, it will be used to update the status of the stacks * Get the status list, it will be used to update the status of the stacks
* Not all status will be returned, only the stack that is deployed or created to `docker compose` will be returned * Not all status will be returned, only the stack that is deployed or created to `docker compose` will be returned
*/ */
static async getStatusList() : Promise<Map<string, number>> { static getStatusList() : Map<string, number> {
let statusList = new Map<string, number>(); let statusList = new Map<string, number>();
let res = await childProcessAsync.spawn("docker", [ "compose", "ls", "--all", "--format", "json" ], { let res = childProcess.execSync("docker compose ls --all --format json");
encoding: "utf-8", let composeList = JSON.parse(res.toString());
});
if (!res.stdout) {
return statusList;
}
let composeList = JSON.parse(res.stdout.toString());
for (let composeStack of composeList) { for (let composeStack of composeList) {
statusList.set(composeStack.Name, this.statusConvert(composeStack.Status)); statusList.set(composeStack.Name, this.statusConvert(composeStack.Status));
@ -330,13 +297,13 @@ export class Stack {
} }
} }
static async getStack(server: DockgeServer, stackName: string, skipFSOperations = false) : Promise<Stack> { static getStack(server: DockgeServer, stackName: string, skipFSOperations = false) : Stack {
let dir = path.join(server.stacksDir, stackName); let dir = path.join(server.stacksDir, stackName);
if (!skipFSOperations) { if (!skipFSOperations) {
if (!await fileExists(dir) || !(await fsAsync.stat(dir)).isDirectory()) { if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) {
// Maybe it is a stack managed by docker compose directly // Maybe it is a stack managed by docker compose directly
let stackList = await this.getStackList(server, true); let stackList = this.getStackList(server, true);
let stack = stackList.get(stackName); let stack = stackList.get(stackName);
if (stack) { if (stack) {
@ -407,7 +374,7 @@ export class Stack {
} }
// If the stack is not running, we don't need to restart it // If the stack is not running, we don't need to restart it
await this.updateStatus(); this.updateStatus();
log.debug("update", "Status: " + this.status); log.debug("update", "Status: " + this.status);
if (this.status !== RUNNING) { if (this.status !== RUNNING) {
return exitCode; return exitCode;
@ -455,17 +422,11 @@ export class Stack {
async getServiceStatusList() { async getServiceStatusList() {
let statusList = new Map<string, number>(); let statusList = new Map<string, number>();
try { let res = childProcess.spawnSync("docker", [ "compose", "ps", "--format", "json" ], {
let res = await childProcessAsync.spawn("docker", [ "compose", "ps", "--format", "json" ], {
cwd: this.path, cwd: this.path,
encoding: "utf-8",
}); });
if (!res.stdout) { let lines = res.stdout.toString().split("\n");
return statusList;
}
let lines = res.stdout?.toString().split("\n");
for (let line of lines) { for (let line of lines) {
try { try {
@ -480,10 +441,5 @@ export class Stack {
} }
return statusList; return statusList;
} catch (e) {
log.error("getServiceStatusList", e);
return statusList;
}
} }
} }

View File

@ -5,7 +5,6 @@ import { log } from "./log";
import { ERROR_TYPE_VALIDATION } from "./util-common"; import { ERROR_TYPE_VALIDATION } from "./util-common";
import { R } from "redbean-node"; import { R } from "redbean-node";
import { verifyPassword } from "./password-hash"; import { verifyPassword } from "./password-hash";
import fs from "fs";
export interface JWTDecoded { export interface JWTDecoded {
username : string; username : string;
@ -83,9 +82,3 @@ export async function doubleCheckPassword(socket : DockgeSocket, currentPassword
return user; return user;
} }
export function fileExists(file : string) {
return fs.promises.access(file, fs.constants.F_OK)
.then(() => true)
.catch(() => false);
}

View File

@ -12,7 +12,7 @@
"registry": "Registro", "registry": "Registro",
"compose": "Compose", "compose": "Compose",
"addFirstStackMsg": "Componi il tuo primo stack!", "addFirstStackMsg": "Componi il tuo primo stack!",
"stackName": "Nome dello stack", "stackName" : "Nome dello stack",
"deployStack": "Deploy", "deployStack": "Deploy",
"deleteStack": "Cancella", "deleteStack": "Cancella",
"stopStack": "Stop", "stopStack": "Stop",
@ -23,7 +23,7 @@
"editStack": "Modifica", "editStack": "Modifica",
"discardStack": "Annulla", "discardStack": "Annulla",
"saveStackDraft": "Salva", "saveStackDraft": "Salva",
"notAvailableShort": "N/D", "notAvailableShort" : "N/D",
"deleteStackMsg": "Sei sicuro di voler eliminare questo stack?", "deleteStackMsg": "Sei sicuro di voler eliminare questo stack?",
"stackNotManagedByDockgeMsg": "Questo stack non è gestito da Dockge.", "stackNotManagedByDockgeMsg": "Questo stack non è gestito da Dockge.",
"primaryHostname": "Hostname primario", "primaryHostname": "Hostname primario",
@ -91,11 +91,5 @@
"Allowed commands:": "Comandi permessi:", "Allowed commands:": "Comandi permessi:",
"Internal Networks": "Reti interne", "Internal Networks": "Reti interne",
"External Networks": "Reti esterne", "External Networks": "Reti esterne",
"No External Networks": "Nessuna rete esterna", "No External Networks": "Nessuna rete esterna"
"reverseProxyMsg1": "Utilizzando un proxy inverso?",
"reverseProxyMsg2": "Controlla come configurarlo per WebSocket",
"Cannot connect to the socket server.": "Impossibile connettersi al server socket.",
"connecting...": "Connessione al server socket…",
"extra": "Extra",
"reconnecting...": "Riconnessione…"
} }

View File

@ -17,7 +17,7 @@
"editStack": "編集", "editStack": "編集",
"discardStack": "破棄", "discardStack": "破棄",
"saveStackDraft": "保存", "saveStackDraft": "保存",
"stackNotManagedByDockgeMsg": "このスタックはDockgeによって管理されていません。", "stackNotManagedByDockgeMsg": "このスタックはDockageによって管理されていません。",
"general": "一般", "general": "一般",
"scanFolder": "スタックフォルダをスキャン", "scanFolder": "スタックフォルダをスキャン",
"dockerImage": "イメージ", "dockerImage": "イメージ",

View File

@ -90,13 +90,5 @@
"Allowed commands:": "허용된 명령어:", "Allowed commands:": "허용된 명령어:",
"Internal Networks": "내부 네트워크", "Internal Networks": "내부 네트워크",
"External Networks": "외부 네트워크", "External Networks": "외부 네트워크",
"No External Networks": "외부 네트워크 없음", "No External Networks": "외부 네트워크 없음"
"reverseProxyMsg2": "여기서 WebSocket을 위한 설정을 확인해 보세요",
"downStack": "정지 & Down",
"reverseProxyMsg1": "리버스 프록시를 사용하고 계신가요?",
"Cannot connect to the socket server.": "소켓 서버에 연결하지 못했습니다.",
"connecting...": "소켓 서버에 연결하는 중…",
"extra": "기타",
"url": "URL | URL",
"reconnecting...": "재연결 중…"
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "dockge", "name": "dockge",
"version": "1.3.2", "version": "1.2.0",
"type": "module", "type": "module",
"engines": { "engines": {
"node": ">= 18.0.0 && <= 18.17.1" "node": ">= 18.0.0 && <= 18.17.1"
@ -33,7 +33,6 @@
"composerize": "~1.4.1", "composerize": "~1.4.1",
"croner": "~7.0.5", "croner": "~7.0.5",
"dayjs": "~1.11.10", "dayjs": "~1.11.10",
"dotenv": "~16.3.1",
"express": "~4.18.2", "express": "~4.18.2",
"express-static-gzip": "~2.1.7", "express-static-gzip": "~2.1.7",
"http-graceful-shutdown": "~3.1.13", "http-graceful-shutdown": "~3.1.13",
@ -42,7 +41,6 @@
"knex": "~2.5.1", "knex": "~2.5.1",
"limiter-es6-compat": "~2.1.2", "limiter-es6-compat": "~2.1.2",
"mysql2": "~3.6.3", "mysql2": "~3.6.3",
"promisify-child-process": "~4.1.2",
"redbean-node": "~0.3.3", "redbean-node": "~0.3.3",
"socket.io": "~4.7.2", "socket.io": "~4.7.2",
"socket.io-client": "~4.7.2", "socket.io-client": "~4.7.2",

16
pnpm-lock.yaml generated
View File

@ -32,9 +32,6 @@ dependencies:
dayjs: dayjs:
specifier: ~1.11.10 specifier: ~1.11.10
version: 1.11.10 version: 1.11.10
dotenv:
specifier: ~16.3.1
version: 16.3.1
express: express:
specifier: ~4.18.2 specifier: ~4.18.2
version: 4.18.2 version: 4.18.2
@ -59,9 +56,6 @@ dependencies:
mysql2: mysql2:
specifier: ~3.6.3 specifier: ~3.6.3
version: 3.6.3 version: 3.6.3
promisify-child-process:
specifier: ~4.1.2
version: 4.1.2
redbean-node: redbean-node:
specifier: ~0.3.3 specifier: ~0.3.3
version: 0.3.3(mysql2@3.6.3) version: 0.3.3(mysql2@3.6.3)
@ -2157,11 +2151,6 @@ packages:
esutils: 2.0.3 esutils: 2.0.3
dev: true dev: true
/dotenv@16.3.1:
resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==}
engines: {node: '>=12'}
dev: false
/eastasianwidth@0.2.0: /eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
dev: false dev: false
@ -3898,11 +3887,6 @@ packages:
dev: false dev: false
optional: true optional: true
/promisify-child-process@4.1.2:
resolution: {integrity: sha512-APnkIgmaHNJpkAn7k+CrJSi9WMuff5ctYFbD0CO2XIPkM8yO7d/ShouU2clywbpHV/DUsyc4bpJCsNgddNtx4g==}
engines: {node: '>=8'}
dev: false
/proxy-addr@2.0.7: /proxy-addr@2.0.7:
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
engines: {node: '>= 0.10'} engines: {node: '>= 0.10'}