Compare commits

...

10 Commits

Author SHA1 Message Date
Jacob Nguyen
2caa8b0f21 a 2025-03-10 00:57:04 -05:00
jacoobes
fb41e33aa6 fix 2025-02-07 21:25:09 -06:00
Jacob Nguyen
b3c5a9e050 Update cleanup.ts 2025-02-07 21:19:31 -06:00
Jacob Nguyen
d566178315 Create cleanup.ts 2025-02-07 21:17:15 -06:00
Jacob Nguyen
64c6c08a01 Update sern.ts 2025-02-07 21:16:22 -06:00
Jacob Nguyen
1f25aa64b9 plock
Some checks failed
Continuous Delivery / Publishing Dev (push) Has been cancelled
NPM / Publish / test-and-publish (push) Has been cancelled
2025-02-07 01:45:57 -06:00
Jacob Nguyen
7cddee30aa lock 2025-02-07 01:44:49 -06:00
renovate[bot]
e7286eee9f chore(deps): lock file maintenance (#331)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-07 01:43:27 -06:00
Jacob Nguyen
a67450328e fuckyarn 2025-02-07 00:50:17 -06:00
Jacob Nguyen
47401f46a3 Update README.md
Some checks failed
NPM / Publish / test-and-publish (push) Has been cancelled
2025-02-03 11:47:49 -06:00
9 changed files with 136 additions and 4188 deletions

View File

@@ -13,9 +13,9 @@ jobs:
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3
- uses: actions/setup-node@1a4442cacd436585916779262731d5b162bc6ec7 # v3
with:
node-version: 17
- run: yarn --immutable
- run: yarn build:prod
node-version: 18
- run: npm i
- run: npm run build:prod
- uses: JS-DevTools/npm-publish@0f451a94170d1699fd50710966d48fb26194d939 # v1
with:
token: ${{ secrets.NPM_TOKEN }}

View File

@@ -24,6 +24,5 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm install -g yarn
- run: yarn install
- run: yarn test
- run: npm install
- run: npm run test

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +0,0 @@
enableGlobalCache: true
nodeLinker: node-modules
yarnPath: .yarn/releases/yarn-3.5.1.cjs

View File

@@ -7,6 +7,7 @@
<div align="center" styles="margin-top: 10px">
<img src="https://img.shields.io/badge/open-source-brightgreen" />
<img src="https://img.shields.io/badge/built_with-sern-pink?labelColor=%230C3478&color=%23ed5087&link=https%3A%2F%2Fsern.dev"/>
<a href="https://www.npmjs.com/package/@sern/handler"><img src="https://img.shields.io/npm/v/@sern/handler?maxAge=3600" alt="NPM version" /></a>
<a href="https://www.npmjs.com/package/@sern/handler"><img src="https://img.shields.io/npm/dt/@sern/handler?maxAge=3600" alt="NPM downloads" /></a>
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/license-MIT-brightgreen" alt="License MIT" /></a>
@@ -43,6 +44,11 @@ export default commandModule({
```
</details>
# Show off your sern Discord Bot!
## Badge
- Copy this and add it to your [README.md](https://img.shields.io/badge/built_with-sern-pink?labelColor=%230C3478&color=%23ed5087&link=https%3A%2F%2Fsern.dev)
<img src="https://img.shields.io/badge/built_with-sern-pink?labelColor=%230C3478&color=%23ed5087&link=https%3A%2F%2Fsern.dev">
## 🤖 Bots Using sern
- [Community Bot](https://github.com/sern-handler/sern-community) - The community bot for our [Discord server](https://sern.dev/discord).
@@ -57,6 +63,8 @@ export default commandModule({
It is **highly encouraged** to use the [command line interface](https://github.com/sern-handler/cli) for your project. Don't forget to view it.
## 🔗 Links
- [Official Documentation and Guide](https://sern.dev)

View File

@@ -36,7 +36,7 @@
"author": "SernDevs",
"license": "MIT",
"dependencies": {
"@sern/ioc": "^1.1.0",
"@sern/ioc": "^1.1.2",
"callsites": "^3.1.0",
"cron": "^3.1.7",
"deepmerge": "^4.3.1"
@@ -47,8 +47,8 @@
"@types/node-cron": "^3.0.11",
"@typescript-eslint/eslint-plugin": "5.58.0",
"@typescript-eslint/parser": "5.59.1",
"discord.js": "^14.15.3",
"eslint": "8.39.0",
"discord.js": "^14.14.1",
"eslint": "9.0.0",
"typescript": "5.0.2",
"vitest": "^1.6.0"
},

111
src/cleanup.ts Normal file
View File

@@ -0,0 +1,111 @@
// It's this package but without default console log / error https://github.com/trevorr/async-cleanup
/** A possibly asynchronous function invoked with the process is about to exit. */
export type CleanupListener = () => void | Promise<void>;
let cleanupListeners: Set<CleanupListener> | undefined;
/** Registers a new cleanup listener. Adding the same listener more than once has no effect. */
export function addCleanupListener(listener: CleanupListener): void {
// Install exit listeners on initial cleanup listener
if (!cleanupListeners) {
installExitListeners();
cleanupListeners = new Set();
}
cleanupListeners.add(listener);
}
/** Removes an existing cleanup listener, and returns whether the listener was registered. */
export function removeCleanupListener(listener: CleanupListener): boolean {
return cleanupListeners != null && cleanupListeners.delete(listener);
}
/** Executes all cleanup listeners and then exits the process. Call this instead of `process.exit` to ensure all listeners are fully executed. */
export async function exitAfterCleanup(code = 0): Promise<never> {
await executeCleanupListeners();
process.exit(code);
}
/** Executes all cleanup listeners and then kills the process with the given signal. */
export async function killAfterCleanup(signal: ExitSignal): Promise<void> {
await executeCleanupListeners();
process.kill(process.pid, signal);
}
async function executeCleanupListeners(): Promise<void> {
if (cleanupListeners) {
// Remove exit listeners to restore normal event handling
uninstallExitListeners();
// Clear cleanup listeners to reset state for testing
const listeners = cleanupListeners;
cleanupListeners = undefined;
// Call listeners in order added with async listeners running concurrently
const promises: Promise<void>[] = [];
for (const listener of listeners) {
try {
const promise = listener();
if (promise) promises.push(promise);
} catch (err) {
// console.error("Uncaught exception during cleanup", err);
}
}
// Wait for all listeners to complete and log any rejections
const results = await Promise.allSettled(promises);
for (const result of results) {
if (result.status === "rejected") {
console.error("Unhandled rejection during cleanup", result.reason);
}
}
}
}
function beforeExitListener(code: number): void {
// console.log(`Exiting with code ${code} due to empty event loop`);
void exitAfterCleanup(code);
}
function uncaughtExceptionListener(error: Error): void {
// console.error("Exiting with code 1 due to uncaught exception", error);
void exitAfterCleanup(1);
}
function signalListener(signal: ExitSignal): void {
// console.log(`Exiting due to signal ${signal}`);
void killAfterCleanup(signal);
}
// Listenable signals that terminate the process by default
// (except SIGQUIT, which generates a core dump and should not trigger cleanup)
// See https://nodejs.org/api/process.html#signal-events
const listenedSignals = [
"SIGBREAK", // Ctrl-Break on Windows
"SIGHUP", // Parent terminal closed
"SIGINT", // Terminal interrupt, usually by Ctrl-C
"SIGTERM", // Graceful termination
"SIGUSR2", // Used by Nodemon
] as const;
/** Signals that can terminate the process. */
export type ExitSignal =
| typeof listenedSignals[number]
| "SIGKILL"
| "SIGQUIT"
| "SIGSTOP";
function installExitListeners(): void {
process.on("beforeExit", beforeExitListener);
process.on("uncaughtException", uncaughtExceptionListener);
listenedSignals.forEach((signal) => process.on(signal, signalListener));
}
function uninstallExitListeners(): void {
process.removeListener("beforeExit", beforeExitListener);
process.removeListener("uncaughtException", uncaughtExceptionListener);
listenedSignals.forEach((signal) =>
process.removeListener(signal, signalListener)
);
}

View File

@@ -14,6 +14,7 @@ import { presenceHandler } from './handlers/presence';
import type { Payload, UnpackedDependencies, Wrapper } from './types/utility';
import type { Presence} from './core/presences';
import { registerTasks } from './handlers/tasks';
import { addCleanupListener } from './cleanup';
/**
@@ -76,5 +77,12 @@ export function init(maybeWrapper: Wrapper = { commands: "./dist/commands" }) {
})
.catch(err => { throw err });
interactionHandler(deps, maybeWrapper.defaultPrefix);
messageHandler(deps, maybeWrapper.defaultPrefix)
messageHandler(deps, maybeWrapper.defaultPrefix);
addCleanupListener(async () => {
const duration = ((performance.now() - startTime) / 1000).toFixed(2)
deps['@sern/logger']?.info({ 'message': 'sern is shutting down after '+duration +" seconds" })
await useContainerRaw().disposeAll();
});
}

3300
yarn.lock

File diff suppressed because it is too large Load Diff