🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@igosprojects/rivet-ws

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@igosprojects/rivet-ws - npm Package Compare versions

Comparing version
1.0.1
to
1.0.2
+3
dist/plugin.d.ts
import type { RivetPlugin } from '@igosprojects/rivet';
export declare const WSPlugin: RivetPlugin;
//# sourceMappingURL=plugin.d.ts.map
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAIvD,eAAO,MAAM,QAAQ,EAAE,WAiCtB,CAAC"}
"use strict";
/*
This file is licensed under the MIT license, the terms must be followed!
Copyright(c) 2026 EyeDev
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.WSPlugin = void 0;
const ws_1 = require("ws");
exports.WSPlugin = {
name: 'logging',
version: '1.0.0',
install: function (app) {
console.log('Started WS plugin!');
const WSRoutes = new Map();
// Add WS function to app
app.ws = (path, handler) => {
WSRoutes.set(path, handler);
return app;
};
// Start WS server(no port, handles HTTP upgrades)
const wss = new ws_1.WebSocketServer({ noServer: true });
// Hook into server creation
app.OnServerCreate((server) => {
server.on('upgrade', (req, socket, head) => {
const url = req.url?.split('?')[0] || '/';
const handler = WSRoutes.get(url);
if (handler) {
wss.handleUpgrade(req, socket, head, (ws) => {
handler(ws, req);
});
}
else {
socket.destroy();
}
});
});
},
};
//# sourceMappingURL=plugin.js.map
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":";AAAA;;;EAGE;;;AAEF,2BAAqC;AAKxB,QAAA,QAAQ,GAAgB;IACjC,IAAI,EAAE,SAAS;IACf,OAAO,EAAE,OAAO;IAChB,OAAO,EAAE,UAAU,GAAQ;QACvB,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAElC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAmD,CAAC;QAE5E,yBAAyB;QACzB,GAAG,CAAC,EAAE,GAAG,CAAC,IAAY,EAAE,OAAgD,EAAE,EAAE;YACxE,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC5B,OAAO,GAAG,CAAC;QACf,CAAC,CAAC;QAEF,kDAAkD;QAClD,MAAM,GAAG,GAAG,IAAI,oBAAe,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QAEpD,4BAA4B;QAC5B,GAAG,CAAC,cAAc,CAAC,CAAC,MAAW,EAAE,EAAE;YAC/B,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAoB,EAAE,MAAc,EAAE,IAAY,EAAE,EAAE;gBACxE,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;gBAC1C,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBAElC,IAAI,OAAO,EAAE,CAAC;oBACV,GAAG,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE;wBACxC,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;oBACrB,CAAC,CAAC,CAAC;gBACP,CAAC;qBAAM,CAAC;oBACJ,MAAM,CAAC,OAAO,EAAE,CAAC;gBACrB,CAAC;YACL,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC;CACJ,CAAC"}
{
"hoistPattern": [
"*"
],
"included": {
"dependencies": true,
"devDependencies": true,
"optionalDependencies": true
},
"injectedDeps": {},
"layoutVersion": 5,
"hoistedLocations": {
"@igosprojects/rivet@1.0.6": [
"node_modules\\@igosprojects\\rivet"
]
},
"nodeLinker": "hoisted",
"packageManager": "pnpm@10.33.0",
"pendingBuilds": [],
"publicHoistPattern": [],
"prunedAt": "Sat, 30 May 2026 12:39:12 GMT",
"registries": {
"default": "https://registry.npmjs.org/",
"@jsr": "https://npm.jsr.io/"
},
"skipped": [],
"storeDir": "C:\\Users\\Igor\\AppData\\Local\\pnpm\\store\\v10",
"virtualStoreDir": "E:\\Igor\\rivet-ws\\test\\node_modules\\.pnpm",
"virtualStoreDirMaxLength": 60
}
{
"lastValidatedTimestamp": 1780145917139,
"projects": {},
"pnpmfiles": [],
"settings": {
"autoInstallPeers": true,
"dedupeDirectDeps": false,
"dedupeInjectedDeps": true,
"dedupePeerDependents": true,
"dedupePeers": false,
"dev": true,
"excludeLinksFromLockfile": false,
"hoistPattern": [
"*"
],
"hoistWorkspacePackages": true,
"injectWorkspacePackages": false,
"linkWorkspacePackages": false,
"nodeLinker": "hoisted",
"optional": true,
"peersSuffixMaxLength": 1000,
"preferWorkspacePackages": false,
"production": true,
"publicHoistPattern": []
},
"filteredInstall": false
}
lockfileVersion: '9.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
importers:
.:
dependencies:
'@igosprojects/rivet':
specifier: ^1.0.6
version: 1.0.6
packages:
'@igosprojects/rivet@1.0.6':
resolution: {integrity: sha512-LhkQRwKrSEOGvC5cd/LFmlKH1Gbz4J7nMD7qug+xzOavdiSfqxseRDRt1u4YnHApsB4XJDEQ/SRF/HSjSgivig==}
snapshots:
'@igosprojects/rivet@1.0.6': {}
import type { RivetResponse, CorsOptions } from './types';
export declare function AddCORSHeader(res: RivetResponse, options?: CorsOptions): void;
export declare function HandlePreflight(req: any, res: RivetResponse): boolean;
//# sourceMappingURL=cors.d.ts.map
{"version":3,"file":"cors.d.ts","sourceRoot":"","sources":["../src/cors.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAU1D,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,GAAE,WAAgC,QAgB1F;AAGD,wBAAgB,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,aAAa,GAAG,OAAO,CAOrE"}
"use strict";
/*
This file is licensed under the MIT license, the terms must be followed!
Copyright(c) 2026 EyeDev
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.AddCORSHeader = AddCORSHeader;
exports.HandlePreflight = HandlePreflight;
const DefaultCorsOptions = {
origin: '*',
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
headers: ['Content-Type', 'Authorization'],
credentials: false,
};
// Adds the needed CORS tags to the response header
function AddCORSHeader(res, options = DefaultCorsOptions) {
const opts = { ...DefaultCorsOptions, ...options };
// Origin
const origin = Array.isArray(opts.origin) ? opts.origin.join(', ') : opts.origin;
res.setHeader('Access-Control-Allow-Origin', origin || '*');
// Headers
if (opts.headers) {
res.setHeader('Access-Control-Allow-Headers', opts.headers.join(', '));
}
// Credentials
if (opts.credentials) {
res.setHeader('Access-Control-Allow-Credentials', 'true');
}
}
// Handles preflight request sent by browsers
function HandlePreflight(req, res) {
if (req.method === 'OPTIONS') {
res.writeHead(204); // 204: No content
res.end();
return true;
}
return false;
}
//# sourceMappingURL=cors.js.map
{"version":3,"file":"cors.js","sourceRoot":"","sources":["../src/cors.ts"],"names":[],"mappings":";AAAA;;;EAGE;;AAcF,sCAgBC;AAGD,0CAOC;AAlCD,MAAM,kBAAkB,GAAgB;IACpC,MAAM,EAAE,GAAG;IACX,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC;IAC7D,OAAO,EAAE,CAAC,cAAc,EAAE,eAAe,CAAC;IAC1C,WAAW,EAAE,KAAK;CACrB,CAAC;AAEF,mDAAmD;AACnD,SAAgB,aAAa,CAAC,GAAkB,EAAE,UAAuB,kBAAkB;IACvF,MAAM,IAAI,GAAG,EAAE,GAAG,kBAAkB,EAAE,GAAG,OAAO,EAAE,CAAC;IAEnD,SAAS;IACT,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;IACjF,GAAG,CAAC,SAAS,CAAC,6BAA6B,EAAE,MAAM,IAAI,GAAG,CAAC,CAAC;IAE5D,UAAU;IACV,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3E,CAAC;IAED,cAAc;IACd,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,GAAG,CAAC,SAAS,CAAC,kCAAkC,EAAE,MAAM,CAAC,CAAC;IAC9D,CAAC;AACL,CAAC;AAED,6CAA6C;AAC7C,SAAgB,eAAe,CAAC,GAAQ,EAAE,GAAkB;IACxD,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC3B,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,kBAAkB;QACtC,GAAG,CAAC,GAAG,EAAE,CAAC;QACV,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC"}
export { Rivet } from './rivet';
export type { RivetResponse, RivetPlugin } from './types';
//# sourceMappingURL=index.d.ts.map
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC"}
"use strict";
/*
This file is licensed under the MIT license, the terms must be followed!
Copyright(c) 2026 EyeDev
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.Rivet = void 0;
var rivet_1 = require("./rivet");
Object.defineProperty(exports, "Rivet", { enumerable: true, get: function () { return rivet_1.Rivet; } });
//# sourceMappingURL=index.js.map
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;EAGE;;;AAEF,iCAAgC;AAAvB,8FAAA,KAAK,OAAA"}
export declare function GetMimeType(filePath: string): string;
//# sourceMappingURL=mime.d.ts.map
{"version":3,"file":"mime.d.ts","sourceRoot":"","sources":["../src/mime.ts"],"names":[],"mappings":"AAMA,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAgBpD"}
"use strict";
/*
This file is licensed under the MIT license, the terms must be followed!
Copyright(c) 2026 EyeDev
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.GetMimeType = GetMimeType;
// Returns the MIME type of any file
function GetMimeType(filePath) {
const ext = filePath.split('.').pop()?.toLowerCase() || '';
const mimeTypes = {
html: 'text/html',
css: 'text/css',
js: 'application/javascript',
json: 'application/json',
png: 'image/png',
jpg: 'image/jpeg',
jpeg: 'image/jpeg',
gif: 'image/gif',
svg: 'image/svg+xml',
txt: 'text/plain',
pdf: 'application/pdf',
};
return mimeTypes[ext] || 'application/octet-stream';
}
//# sourceMappingURL=mime.js.map
{"version":3,"file":"mime.js","sourceRoot":"","sources":["../src/mime.ts"],"names":[],"mappings":";AAAA;;;EAGE;;AAGF,kCAgBC;AAjBD,oCAAoC;AACpC,SAAgB,WAAW,CAAC,QAAgB;IACxC,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IAC3D,MAAM,SAAS,GAA2B;QACtC,IAAI,EAAE,WAAW;QACjB,GAAG,EAAE,UAAU;QACf,EAAE,EAAE,wBAAwB;QAC5B,IAAI,EAAE,kBAAkB;QACxB,GAAG,EAAE,WAAW;QAChB,GAAG,EAAE,YAAY;QACjB,IAAI,EAAE,YAAY;QAClB,GAAG,EAAE,WAAW;QAChB,GAAG,EAAE,eAAe;QACpB,GAAG,EAAE,YAAY;QACjB,GAAG,EAAE,iBAAiB;KACzB,CAAC;IACF,OAAO,SAAS,CAAC,GAAG,CAAC,IAAI,0BAA0B,CAAC;AACxD,CAAC"}
import type { RivetPlugin } from '../types';
export declare const LoggingPlugin: RivetPlugin;
//# sourceMappingURL=logging.d.ts.map
{"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../../src/plugins/logging.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAc,MAAM,UAAU,CAAC;AAExD,eAAO,MAAM,aAAa,EAAE,WAmB3B,CAAC"}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LoggingPlugin = void 0;
exports.LoggingPlugin = {
name: 'logging',
version: '1.0.0',
install(app) {
app.UseMiddleware((req, res, next) => {
const start = Date.now();
const method = req.method;
const url = req.url;
console.log(`${method} ${url}`);
// Use 'finish' event instead of overriding end
res.once('finish', () => {
const duration = Date.now() - start;
console.log(`${method} ${url} - ${duration}ms`);
});
next();
});
},
};
//# sourceMappingURL=logging.js.map
{"version":3,"file":"logging.js","sourceRoot":"","sources":["../../src/plugins/logging.ts"],"names":[],"mappings":";;;AAEa,QAAA,aAAa,GAAgB;IACtC,IAAI,EAAE,SAAS;IACf,OAAO,EAAE,OAAO;IAChB,OAAO,CAAC,GAAG;QACP,GAAG,CAAC,aAAa,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;YACjC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACzB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;YAC1B,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;YACpB,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,IAAI,GAAG,EAAE,CAAC,CAAC;YAEhC,+CAA+C;YAC/C,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE;gBACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;gBACpC,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,IAAI,GAAG,MAAM,QAAQ,IAAI,CAAC,CAAC;YACpD,CAAC,CAAC,CAAC;YAEH,IAAI,EAAE,CAAC;QACX,CAAC,CAAC,CAAC;IACP,CAAC;CACJ,CAAC"}
import { RivetResponse } from './types';
export declare function InjectResponseHelpers(res: RivetResponse): void;
//# sourceMappingURL=response.d.ts.map
{"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../src/response.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGxC,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAsC9D"}
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.InjectResponseHelpers = InjectResponseHelpers;
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const mime_1 = require("./mime");
function InjectResponseHelpers(res) {
res.send = (data) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(String(data));
};
res.json = (data) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(data));
};
res.SendFile = (filePath, contentType) => {
const fullPath = path_1.default.resolve(filePath);
if (!fullPath.startsWith(process.cwd())) {
res.writeHead(403, { 'Content-Type': 'text/plain' });
res.end('403: Forbidden');
return;
}
fs_1.default.access(fullPath, fs_1.default.constants.R_OK, (err) => {
if (err) {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404: File not found');
return;
}
const mimeType = contentType || (0, mime_1.GetMimeType)(fullPath);
const stream = fs_1.default.createReadStream(fullPath);
res.writeHead(200, { 'Content-Type': mimeType });
stream.pipe(res);
stream.on('error', () => {
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end('500: Internal Server Error');
});
});
};
}
//# sourceMappingURL=response.js.map
{"version":3,"file":"response.js","sourceRoot":"","sources":["../src/response.ts"],"names":[],"mappings":";;;;;AAKA,sDAsCC;AA3CD,4CAAoB;AACpB,gDAAwB;AAExB,iCAAqC;AAErC,SAAgB,qBAAqB,CAAC,GAAkB;IACpD,GAAG,CAAC,IAAI,GAAG,CAAC,IAAS,EAAE,EAAE;QACrB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC,CAAC;QACrD,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1B,CAAC,CAAC;IAEF,GAAG,CAAC,IAAI,GAAG,CAAC,IAAS,EAAE,EAAE;QACrB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IAClC,CAAC,CAAC;IAEF,GAAG,CAAC,QAAQ,GAAG,CAAC,QAAgB,EAAE,WAAoB,EAAE,EAAE;QACtD,MAAM,QAAQ,GAAG,cAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAExC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;YACtC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC,CAAC;YACrD,GAAG,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;YAC1B,OAAO;QACX,CAAC;QAED,YAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,YAAE,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE;YAC3C,IAAI,GAAG,EAAE,CAAC;gBACN,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC,CAAC;gBACrD,GAAG,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;gBAC/B,OAAO;YACX,CAAC;YAED,MAAM,QAAQ,GAAG,WAAW,IAAI,IAAA,kBAAW,EAAC,QAAQ,CAAC,CAAC;YACtD,MAAM,MAAM,GAAG,YAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;YAC7C,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,CAAC;YACjD,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAEjB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBACpB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC,CAAC;gBACrD,GAAG,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;YAC1C,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;AACN,CAAC"}
import type { RivetResponse, RouteHandlers, CorsOptions, RivetPlugin, Middleware } from './types';
import type { IncomingMessage } from 'http';
export declare class Rivet {
private plugins;
private middlewares;
private server;
routes: {
GET: RouteHandlers;
POST: RouteHandlers;
PUT: RouteHandlers;
DELETE: RouteHandlers;
};
constructor();
private corsOptions;
private serverCallbacks;
cors(options: CorsOptions): this;
start(port: number, callback?: () => void): void;
UseMiddleware(middleware: Middleware): this;
OnServerCreate(callback: (server: any) => void): void;
use(plugin: RivetPlugin): this;
private ParsePath;
get(path: string, handler: Function): void;
post(path: string, handler: Function): void;
OnRequest(req: IncomingMessage, res: RivetResponse): Promise<void>;
HandleRoute(req: IncomingMessage, res: RivetResponse): Promise<void>;
static(prefix: string, directory: string): void;
}
//# sourceMappingURL=rivet.d.ts.map
{"version":3,"file":"rivet.d.ts","sourceRoot":"","sources":["../src/rivet.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAKlG,OAAO,KAAK,EAAE,eAAe,EAA0B,MAAM,MAAM,CAAC;AAkDpE,qBAAa,KAAK;IACd,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,WAAW,CAAoB;IAEvC,OAAO,CAAC,MAAM,CAAuB;IACrC,MAAM,EAAE;QACJ,GAAG,EAAE,aAAa,CAAC;QACnB,IAAI,EAAE,aAAa,CAAC;QACpB,GAAG,EAAE,aAAa,CAAC;QACnB,MAAM,EAAE,aAAa,CAAC;KACzB,CAAC;;IAYF,OAAO,CAAC,WAAW,CAAmB;IACtC,OAAO,CAAC,eAAe,CAAoC;IAG3D,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAMhC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,IAAI;IAchD,aAAa,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI;IAM3C,cAAc,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI;IAM9C,GAAG,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IAO9B,OAAO,CAAC,SAAS;IAkBjB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,IAAI;IAU1C,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,IAAI;IAUrC,SAAS,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBlE,WAAW,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IA8E1E,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;CAgBlD"}
"use strict";
/*
This file is licensed under the MIT license, the terms must be followed!
Copyright(c) 2026 EyeDev
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Rivet = void 0;
const http_1 = __importDefault(require("http"));
const response_1 = require("./response");
const cors_1 = require("./cors");
const static_1 = require("./static");
// Parses the request body
async function ParseBody(req) {
return new Promise((resolve, reject) => {
const chunks = [];
req.on('data', (chunk) => {
chunks.push(chunk);
});
req.on('end', () => {
const body = Buffer.concat(chunks).toString();
// No body
if (!body) {
resolve({});
return;
}
// Check content type
const contentType = req.headers['content-type'] || '';
if (contentType.includes('application/json')) {
try {
resolve(JSON.parse(body));
}
catch (e) {
resolve({});
}
}
else if (contentType.includes('application/x-www-form-urlencoded')) {
// Parse form data: "name=Alice&age=30" → { name: "Alice", age: "30" }
const params = new URLSearchParams(body);
const result = {};
params.forEach((value, key) => {
result[key] = value;
});
resolve(result);
}
else {
// Plain text
resolve(body);
}
});
req.on('error', (err) => {
reject(err);
});
});
}
// Main library class
class Rivet {
constructor() {
this.plugins = [];
this.middlewares = [];
this.server = null;
this.corsOptions = {};
this.serverCallbacks = [];
// Route function handlers are defined in here
this.routes = {
GET: {},
POST: {},
PUT: {},
DELETE: {},
};
}
// Allows editing of CORS options before the server is started, or while its running
cors(options) {
this.corsOptions = { ...this.corsOptions, ...options };
return this;
}
// Starts the HTTP server and serves on the provided port
start(port, callback) {
this.server = http_1.default.createServer((req, res) => {
this.OnRequest(req, res);
});
this.serverCallbacks.forEach(cb => cb(this.server)); // Call the callbacks
this.server.listen(port, () => {
console.log(`Rivet fastened on ${port}`);
callback?.();
});
}
// Registers new middleware to run every request
UseMiddleware(middleware) {
this.middlewares.push(middleware);
return this;
}
// Registers a callback to be called when the server starts
OnServerCreate(callback) {
this.serverCallbacks.push(callback);
if (this.server)
callback(this.server);
}
// Registers a plugin
use(plugin) {
plugin.install(this); // Call the install function
this.plugins.push(plugin);
return this;
}
// Parses a path and returns the regex and parameters
ParsePath(path) {
const paramNames = [];
// Replace :param with regex capture groups
const regexPattern = path.replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, (_, paramName) => {
paramNames.push(paramName);
return '([^/]+)'; // Capture anything except slash
});
console.log('Path:', path, '→ Regex:', regexPattern); // Debug
// Create regex that matches exactly
const regex = new RegExp(`^${regexPattern}$`);
return { regex, paramNames };
}
// Registers a new GET handler
get(path, handler) {
const { regex, paramNames } = this.ParsePath(path);
this.routes.GET[path] = {
handler,
params: paramNames,
regex,
};
}
// Registers a new POST handler
post(path, handler) {
const { regex, paramNames } = this.ParsePath(path);
this.routes.POST[path] = {
handler,
params: paramNames,
regex,
};
}
// Called when the server recives an request
async OnRequest(req, res) {
// Run all the middleware
let index = 0;
const next = async () => {
if (index < this.middlewares.length) {
const middleware = this.middlewares[index++];
await middleware(req, res, next);
}
else {
await this.HandleRoute(req, res);
}
};
await next();
}
// Called when after middleware runs
async HandleRoute(req, res) {
// Always apply CORS headers
(0, cors_1.AddCORSHeader)(res, this.corsOptions);
// Handle preflight
if ((0, cors_1.HandlePreflight)(req, res))
return;
const method = req.method; // Get the HTTP method
const url = req.url?.split('?')[0] || '/'; // Get the URL and strip the query params
// Parse query parameters
const urlObj = new URL(req.url || '/', `http://${req.headers.host || 'localhost'}`);
const query = Object.fromEntries(urlObj.searchParams);
req.query = query;
// Parse body for POST, PUT, PATCH requests
if (method === 'POST' || method === 'PUT') {
try {
const body = await ParseBody(req);
req.body = body;
}
catch (err) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Invalid request body' }));
return;
}
}
const methodRoutes = this.routes[method];
if (!methodRoutes) {
res.writeHead(405, { 'Content-Type': 'text/plain' });
res.end('405: Method Not Allowed');
return;
}
// Try exact match first (fast path)
let route = methodRoutes[url];
let params = {};
// If no exact match, try regex
if (!route) {
for (const [pattern, r] of Object.entries(methodRoutes)) {
if (pattern.endsWith('*'))
continue; // Check if "/*" or such
const match = url.match(r.regex);
if (match) {
route = r;
// Extract params from capture groups
r.params.forEach((paramName, index) => {
params[paramName] = match[index + 1];
});
break;
}
}
}
// If still no match, try wildcard (static files)
if (!route) {
for (const [pattern, r] of Object.entries(methodRoutes)) {
if (pattern.endsWith('*') && url.startsWith(pattern.slice(0, -1))) {
route = r;
break;
}
}
}
// If a handler was registered, call it
if (route && route.handler) {
(0, response_1.InjectResponseHelpers)(res); // Injects response helpers into the res object
req.params = params;
await route.handler(req, res); // Now finnaly, call the handler
}
else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404: Page not found!');
}
}
// Serves a static directory on the server
static(prefix, directory) {
const StaticHandler = (0, static_1.ServeStatic)(directory);
// Register a catch-all handler for this prefix
this.routes.GET[`${prefix}*`] = {
handler: async (req, res) => {
const served = await StaticHandler(req, res);
if (!served) {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404: File not found!');
}
},
params: [],
regex: new RegExp(`^${prefix}.*$`),
};
}
}
exports.Rivet = Rivet;
//# sourceMappingURL=rivet.js.map
{"version":3,"file":"rivet.js","sourceRoot":"","sources":["../src/rivet.ts"],"names":[],"mappings":"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"}
import { IncomingMessage, ServerResponse } from 'http';
export declare function ServeStatic(rootDir: string): (req: IncomingMessage, res: ServerResponse) => Promise<boolean>;
//# sourceMappingURL=static.d.ts.map
{"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../src/static.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAIvD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,IAGzB,KAAK,eAAe,EAAE,KAAK,cAAc,KAAG,OAAO,CAAC,OAAO,CAAC,CAyC7E"}
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ServeStatic = ServeStatic;
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const mime_1 = require("./mime");
// Serves the contents of a folder as static files on the server
function ServeStatic(rootDir) {
const absoluteRoot = path_1.default.resolve(rootDir);
return async (req, res) => {
const url = req.url?.split('?')[0] || '/';
// Convert URL to file path
let filePath = path_1.default.join(absoluteRoot, url);
// Security: prevent directory traversal
if (!filePath.startsWith(absoluteRoot)) {
return false;
}
// Check if file exists
try {
const stat = await fs_1.default.promises.stat(filePath);
if (stat.isDirectory()) {
// Try index.html, if its there make it so the root returns index.html
filePath = path_1.default.join(filePath, 'index.html');
try {
await fs_1.default.promises.stat(filePath);
}
catch {
return false; // No index.html
}
}
// Serve the file
const mimeType = (0, mime_1.GetMimeType)(filePath);
const stream = fs_1.default.createReadStream(filePath);
res.writeHead(200, { 'Content-Type': mimeType });
stream.pipe(res);
stream.on('error', () => {
res.writeHead(500);
res.end();
});
return true;
}
catch {
return false; // File not found
}
};
}
//# sourceMappingURL=static.js.map
{"version":3,"file":"static.js","sourceRoot":"","sources":["../src/static.ts"],"names":[],"mappings":";;;;;AAMA,kCA4CC;AAlDD,4CAAoB;AACpB,gDAAwB;AAExB,iCAAqC;AAErC,gEAAgE;AAChE,SAAgB,WAAW,CAAC,OAAe;IACvC,MAAM,YAAY,GAAG,cAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAE3C,OAAO,KAAK,EAAE,GAAoB,EAAE,GAAmB,EAAoB,EAAE;QACzE,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;QAE1C,2BAA2B;QAC3B,IAAI,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;QAE5C,wCAAwC;QACxC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YACrC,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,uBAAuB;QACvB,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,YAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAE9C,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBACrB,sEAAsE;gBACtE,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;gBAC7C,IAAI,CAAC;oBACD,MAAM,YAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACrC,CAAC;gBAAC,MAAM,CAAC;oBACL,OAAO,KAAK,CAAC,CAAC,gBAAgB;gBAClC,CAAC;YACL,CAAC;YAED,iBAAiB;YACjB,MAAM,QAAQ,GAAG,IAAA,kBAAW,EAAC,QAAQ,CAAC,CAAC;YACvC,MAAM,MAAM,GAAG,YAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;YAC7C,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,CAAC;YACjD,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAEjB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBACpB,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;gBACnB,GAAG,CAAC,GAAG,EAAE,CAAC;YACd,CAAC,CAAC,CAAC;YAEH,OAAO,IAAI,CAAC;QAChB,CAAC;QAAC,MAAM,CAAC;YACL,OAAO,KAAK,CAAC,CAAC,iBAAiB;QACnC,CAAC;IACL,CAAC,CAAC;AACN,CAAC"}
import { ServerResponse, IncomingMessage } from 'node:http';
import type { Rivet } from './rivet';
export type Route = {
handler: Function;
params: string[];
regex: RegExp;
};
export type RouteHandlers = {
[key: string]: Route;
};
export type RivetResponse = ServerResponse & {
send: (data: any) => void;
json: (data: any) => void;
SendFile: (filePath: string, contentType?: string) => void;
};
export interface CorsOptions {
origin?: string | string[];
methods?: string[];
headers?: string[];
credentials?: boolean;
}
export interface RivetPlugin {
name: string;
version?: string;
install(app: Rivet): void | Promise<void>;
}
export type Middleware = (req: IncomingMessage, res: RivetResponse, next: () => void) => void;
//# sourceMappingURL=types.d.ts.map
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGrC,MAAM,MAAM,KAAK,GAAG;IAChB,OAAO,EAAE,QAAQ,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACjB,CAAC;AAGF,MAAM,MAAM,aAAa,GAAG;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC;CACxB,CAAC;AAGF,MAAM,MAAM,aAAa,GAAG,cAAc,GAAG;IACzC,IAAI,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAC1B,IAAI,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAC1B,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9D,CAAC;AAEF,MAAM,WAAW,WAAW;IACxB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C;AAED,MAAM,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC"}
"use strict";
/*
This file is licensed under the MIT license, the terms must be followed!
Copyright(c) 2026 EyeDev
*/
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=types.js.map
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;;EAGE"}
MIT License
Copyright (c) 2026 IgosProjects
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
{
"name": "@igosprojects/rivet",
"version": "1.0.6",
"description": "Rivet is a small server framework for NodeJS",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist",
"src",
"README.md",
"LICENSE"
],
"keywords": [
"rivet"
],
"author": "EyeDev",
"license": "MIT",
"devDependencies": {
"@types/node": "^25.9.1",
"prettier": "^3.8.3",
"ts-node": "^10.9.2",
"typescript": "^6.0.3"
},
"repository": {
"type": "git",
"url": "git+https://github.com/IgosProjects/rivet.git"
},
"bugs": {
"url": "https://github.com/IgosProjects/rivet/issues"
},
"homepage": "https://github.com/IgosProjects/rivet#readme",
"scripts": {
"build": "tsc",
"dev": "tsc --watch",
"test": "echo \"Error: no test specified\" && exit 1",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"format:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\""
}
}
# Rivet
![Version](https://img.shields.io/github/package-json/v/IgosProjects/rivet)
![License](https://img.shields.io/github/license/IgosProjects/rivet)
![TypeScript](https://img.shields.io/github/languages/top/IgosProjects/rivet)
![Lines](https://img.shields.io/tokei/lines/github/IgosProjects/rivet)
Rivet is a small Typescript based server platform for NodeJS, it is a Express inspired library for servers
# Installing
To install Rivet you will need to have an NPM project setup, if not run the necessary commands.
Then you can run this command to install rivet:```npm install @igosprojects/rivet```
# Usage
To use Rivet you first need to install it using your package manager(look at [Installing](#installing)).
## Creating a basic server
To create a basic server you will need to initilize Rivet, and start the server. The following code does just that:
```ts
import { IncomingMessage } from 'node:http';
import { Rivet, RivetResponse } from '@igosprojects/rivet';
const app = new Rivet();
// This function is called when the route "/" is called
app.get('/', (req: IncomingMessage, res: RivetResponse) => {
res.send("hi!");
});
app.start(3000);
```
## Serving static files
Rivet supports serving static files and folders, to do so you can use the ```app.static``` function after initilizing the server.
For example this code will serve the public directory next to the file:
```ts
import { Rivet } from '@igosprojects/rivet';
const app = new Rivet();
app.static("/", "./public");
app.start(3000);
```
## Reading parameters(/:id)
Rivet can read parameters passed on the URL bar, to do that you can use the ```req.params``` option for that.
To read the parameters you can do: ```const { paramname } = req.params;```, now paramname is equal to the parameter if it was passed in.
To register routes with parameters you shouldnt register ```/users``` but instead ```/users/:id``` otherwise it wont work!
/*
This file is licensed under the MIT license, the terms must be followed!
Copyright(c) 2026 EyeDev
*/
// This file handles CORS on the server side, it is used for security
import type { RivetResponse, CorsOptions } from './types';
const DefaultCorsOptions: CorsOptions = {
origin: '*',
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
headers: ['Content-Type', 'Authorization'],
credentials: false,
};
// Adds the needed CORS tags to the response header
export function AddCORSHeader(res: RivetResponse, options: CorsOptions = DefaultCorsOptions) {
const opts = { ...DefaultCorsOptions, ...options };
// Origin
const origin = Array.isArray(opts.origin) ? opts.origin.join(', ') : opts.origin;
res.setHeader('Access-Control-Allow-Origin', origin || '*');
// Headers
if (opts.headers) {
res.setHeader('Access-Control-Allow-Headers', opts.headers.join(', '));
}
// Credentials
if (opts.credentials) {
res.setHeader('Access-Control-Allow-Credentials', 'true');
}
}
// Handles preflight request sent by browsers
export function HandlePreflight(req: any, res: RivetResponse): boolean {
if (req.method === 'OPTIONS') {
res.writeHead(204); // 204: No content
res.end();
return true;
}
return false;
}
/*
This file is licensed under the MIT license, the terms must be followed!
Copyright(c) 2026 EyeDev
*/
export { Rivet } from './rivet';
export type { RivetResponse, RivetPlugin } from './types';
/*
This file is licensed under the MIT license, the terms must be followed!
Copyright(c) 2026 EyeDev
*/
// Returns the MIME type of any file
export function GetMimeType(filePath: string): string {
const ext = filePath.split('.').pop()?.toLowerCase() || '';
const mimeTypes: Record<string, string> = {
html: 'text/html',
css: 'text/css',
js: 'application/javascript',
json: 'application/json',
png: 'image/png',
jpg: 'image/jpeg',
jpeg: 'image/jpeg',
gif: 'image/gif',
svg: 'image/svg+xml',
txt: 'text/plain',
pdf: 'application/pdf',
};
return mimeTypes[ext] || 'application/octet-stream';
}
import type { RivetPlugin, Middleware } from '../types';
export const LoggingPlugin: RivetPlugin = {
name: 'logging',
version: '1.0.0',
install(app) {
app.UseMiddleware((req, res, next) => {
const start = Date.now();
const method = req.method;
const url = req.url;
console.log(`${method} ${url}`);
// Use 'finish' event instead of overriding end
res.once('finish', () => {
const duration = Date.now() - start;
console.log(`${method} ${url} - ${duration}ms`);
});
next();
});
},
};
import fs from 'fs';
import path from 'path';
import { RivetResponse } from './types';
import { GetMimeType } from './mime';
export function InjectResponseHelpers(res: RivetResponse): void {
res.send = (data: any) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(String(data));
};
res.json = (data: any) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(data));
};
res.SendFile = (filePath: string, contentType?: string) => {
const fullPath = path.resolve(filePath);
if (!fullPath.startsWith(process.cwd())) {
res.writeHead(403, { 'Content-Type': 'text/plain' });
res.end('403: Forbidden');
return;
}
fs.access(fullPath, fs.constants.R_OK, (err) => {
if (err) {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404: File not found');
return;
}
const mimeType = contentType || GetMimeType(fullPath);
const stream = fs.createReadStream(fullPath);
res.writeHead(200, { 'Content-Type': mimeType });
stream.pipe(res);
stream.on('error', () => {
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end('500: Internal Server Error');
});
});
};
}
/*
This file is licensed under the MIT license, the terms must be followed!
Copyright(c) 2026 EyeDev
*/
import http from 'http';
import type { RivetResponse, RouteHandlers, CorsOptions, RivetPlugin, Middleware } from './types';
import { InjectResponseHelpers } from './response';
import { AddCORSHeader, HandlePreflight } from './cors';
import { ServeStatic } from './static';
import type { IncomingMessage, Server, ServerResponse } from 'http';
// Parses the request body
async function ParseBody(req: IncomingMessage): Promise<any> {
return new Promise((resolve, reject) => {
const chunks: Buffer[] = [];
req.on('data', (chunk) => {
chunks.push(chunk);
});
req.on('end', () => {
const body = Buffer.concat(chunks).toString();
// No body
if (!body) {
resolve({});
return;
}
// Check content type
const contentType = req.headers['content-type'] || '';
if (contentType.includes('application/json')) {
try {
resolve(JSON.parse(body));
} catch (e) {
resolve({});
}
} else if (contentType.includes('application/x-www-form-urlencoded')) {
// Parse form data: "name=Alice&age=30" → { name: "Alice", age: "30" }
const params = new URLSearchParams(body);
const result: Record<string, string> = {};
params.forEach((value, key) => {
result[key] = value;
});
resolve(result);
} else {
// Plain text
resolve(body);
}
});
req.on('error', (err) => {
reject(err);
});
});
}
// Main library class
export class Rivet {
private plugins: RivetPlugin[] = [];
private middlewares: Middleware[] = [];
private server: Server | null = null;
routes: {
GET: RouteHandlers;
POST: RouteHandlers;
PUT: RouteHandlers;
DELETE: RouteHandlers;
};
constructor() {
// Route function handlers are defined in here
this.routes = {
GET: {},
POST: {},
PUT: {},
DELETE: {},
};
}
private corsOptions: CorsOptions = {};
private serverCallbacks: Array<(server: any) => void> = [];
// Allows editing of CORS options before the server is started, or while its running
cors(options: CorsOptions): this {
this.corsOptions = { ...this.corsOptions, ...options };
return this;
}
// Starts the HTTP server and serves on the provided port
start(port: number, callback?: () => void): void {
this.server = http.createServer((req: IncomingMessage, res: ServerResponse) => {
this.OnRequest(req, res as RivetResponse);
});
this.serverCallbacks.forEach(cb => cb(this.server)); // Call the callbacks
this.server.listen(port, () => {
console.log(`Rivet fastened on ${port}`);
callback?.();
});
}
// Registers new middleware to run every request
UseMiddleware(middleware: Middleware): this {
this.middlewares.push(middleware);
return this;
}
// Registers a callback to be called when the server starts
OnServerCreate(callback: (server: any) => void) {
this.serverCallbacks.push(callback);
if (this.server) callback(this.server);
}
// Registers a plugin
use(plugin: RivetPlugin): this {
plugin.install(this); // Call the install function
this.plugins.push(plugin);
return this;
}
// Parses a path and returns the regex and parameters
private ParsePath(path: string): { regex: RegExp; paramNames: string[] } {
const paramNames: string[] = [];
// Replace :param with regex capture groups
const regexPattern = path.replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, (_, paramName) => {
paramNames.push(paramName);
return '([^/]+)'; // Capture anything except slash
});
console.log('Path:', path, '→ Regex:', regexPattern); // Debug
// Create regex that matches exactly
const regex = new RegExp(`^${regexPattern}$`);
return { regex, paramNames };
}
// Registers a new GET handler
get(path: string, handler: Function): void {
const { regex, paramNames } = this.ParsePath(path);
this.routes.GET[path] = {
handler,
params: paramNames,
regex,
};
}
// Registers a new POST handler
post(path: string, handler: Function): void {
const { regex, paramNames } = this.ParsePath(path);
this.routes.POST[path] = {
handler,
params: paramNames,
regex,
};
}
// Called when the server recives an request
async OnRequest(req: IncomingMessage, res: RivetResponse): Promise<void> {
// Run all the middleware
let index = 0;
const next = async () => {
if (index < this.middlewares.length) {
const middleware = this.middlewares[index++];
await middleware(req, res, next);
} else {
await this.HandleRoute(req, res);
}
};
await next();
}
// Called when after middleware runs
async HandleRoute(req: IncomingMessage, res: RivetResponse): Promise<void> {
// Always apply CORS headers
AddCORSHeader(res, this.corsOptions);
// Handle preflight
if (HandlePreflight(req, res)) return;
const method = req.method as keyof typeof this.routes; // Get the HTTP method
const url = req.url?.split('?')[0] || '/'; // Get the URL and strip the query params
// Parse query parameters
const urlObj = new URL(req.url || '/', `http://${req.headers.host || 'localhost'}`);
const query = Object.fromEntries(urlObj.searchParams);
(req as any).query = query;
// Parse body for POST, PUT, PATCH requests
if (method === 'POST' || method === 'PUT') {
try {
const body = await ParseBody(req);
(req as any).body = body;
} catch (err) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Invalid request body' }));
return;
}
}
const methodRoutes = this.routes[method];
if (!methodRoutes) {
res.writeHead(405, { 'Content-Type': 'text/plain' });
res.end('405: Method Not Allowed');
return;
}
// Try exact match first (fast path)
let route = methodRoutes[url];
let params: Record<string, string> = {};
// If no exact match, try regex
if (!route) {
for (const [pattern, r] of Object.entries(methodRoutes)) {
if (pattern.endsWith('*')) continue; // Check if "/*" or such
const match = url.match(r.regex);
if (match) {
route = r;
// Extract params from capture groups
r.params.forEach((paramName, index) => {
params[paramName] = match[index + 1];
});
break;
}
}
}
// If still no match, try wildcard (static files)
if (!route) {
for (const [pattern, r] of Object.entries(methodRoutes)) {
if (pattern.endsWith('*') && url.startsWith(pattern.slice(0, -1))) {
route = r;
break;
}
}
}
// If a handler was registered, call it
if (route && route.handler) {
InjectResponseHelpers(res); // Injects response helpers into the res object
(req as any).params = params;
await route.handler(req, res); // Now finnaly, call the handler
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404: Page not found!');
}
}
// Serves a static directory on the server
static(prefix: string, directory: string): void {
const StaticHandler = ServeStatic(directory);
// Register a catch-all handler for this prefix
this.routes.GET[`${prefix}*`] = {
handler: async (req: IncomingMessage, res: RivetResponse) => {
const served = await StaticHandler(req, res);
if (!served) {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404: File not found!');
}
},
params: [],
regex: new RegExp(`^${prefix}.*$`),
};
}
}
import fs from 'fs';
import path from 'path';
import { IncomingMessage, ServerResponse } from 'http';
import { GetMimeType } from './mime';
// Serves the contents of a folder as static files on the server
export function ServeStatic(rootDir: string) {
const absoluteRoot = path.resolve(rootDir);
return async (req: IncomingMessage, res: ServerResponse): Promise<boolean> => {
const url = req.url?.split('?')[0] || '/';
// Convert URL to file path
let filePath = path.join(absoluteRoot, url);
// Security: prevent directory traversal
if (!filePath.startsWith(absoluteRoot)) {
return false;
}
// Check if file exists
try {
const stat = await fs.promises.stat(filePath);
if (stat.isDirectory()) {
// Try index.html, if its there make it so the root returns index.html
filePath = path.join(filePath, 'index.html');
try {
await fs.promises.stat(filePath);
} catch {
return false; // No index.html
}
}
// Serve the file
const mimeType = GetMimeType(filePath);
const stream = fs.createReadStream(filePath);
res.writeHead(200, { 'Content-Type': mimeType });
stream.pipe(res);
stream.on('error', () => {
res.writeHead(500);
res.end();
});
return true;
} catch {
return false; // File not found
}
};
}
/*
This file is licensed under the MIT license, the terms must be followed!
Copyright(c) 2026 EyeDev
*/
import { ServerResponse, IncomingMessage } from 'node:http';
import type { Rivet } from './rivet';
// New route type, replaced old simple one
export type Route = {
handler: Function;
params: string[]; // Store param names like ['id', 'name']
regex: RegExp; // Converted regex for matching
};
// Route handler type
export type RouteHandlers = {
[key: string]: Route; // Changed from Function to Route
};
// HTTP response type
export type RivetResponse = ServerResponse & {
send: (data: any) => void;
json: (data: any) => void;
SendFile: (filePath: string, contentType?: string) => void;
};
export interface CorsOptions {
origin?: string | string[];
methods?: string[];
headers?: string[];
credentials?: boolean;
}
export interface RivetPlugin {
name: string;
version?: string;
install(app: Rivet): void | Promise<void>;
}
export type Middleware = (req: IncomingMessage, res: RivetResponse, next: () => void) => void;
lockfileVersion: '9.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
importers:
.:
dependencies:
'@igosprojects/rivet':
specifier: ^1.0.6
version: 1.0.6
packages:
'@igosprojects/rivet@1.0.6':
resolution: {integrity: sha512-LhkQRwKrSEOGvC5cd/LFmlKH1Gbz4J7nMD7qug+xzOavdiSfqxseRDRt1u4YnHApsB4XJDEQ/SRF/HSjSgivig==}
snapshots:
'@igosprojects/rivet@1.0.6': {}
+6
-1
{
"name": "@igosprojects/rivet-ws",
"version": "1.0.1",
"version": "1.0.2",
"description": "WebSocket plugin for @igosprojects/rivet",
"main": "index.js",
"files": [
"src",
"test",
"dist"
],
"keywords": [

@@ -7,0 +12,0 @@ "rivet"

-8
module.exports = {
semi: true,
singleQuote: true,
trailingComma: 'es5',
tabWidth: 4,
printWidth: 100,
arrowParens: 'always',
};
// tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": ["ES2020"],
"outDir": "./dist",
"rootDir": "./src",
"declaration": true, // generates .d.ts files for TypeScript users
"declarationMap": true, // helps with editor go-to-definition
"sourceMap": true, // debugging
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"types": ["node"]
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}