@je-es/server 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +295 -75
- package/dist/main.cjs +4 -4
- package/dist/main.cjs.map +1 -1
- package/dist/main.d.cts +89 -8
- package/dist/main.d.ts +89 -8
- package/dist/main.js +4 -4
- package/dist/main.js.map +1 -1
- package/package.json +49 -57
package/dist/main.d.ts
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
export { blob, check, foreignKey, index, integer, numeric, primaryKey, real, sqliteTable, text, uniqueIndex } from 'drizzle-orm/sqlite-core';
|
|
2
|
-
export { Many, One, and, asc, between, desc, eq, exists, gt, gte, ilike, inArray, isNotNull, isNull, like, lt, lte, ne, not, notBetween, notExists, notInArray, or, relations, sql } from 'drizzle-orm';
|
|
3
|
-
|
|
4
1
|
declare class Router {
|
|
5
2
|
private routes;
|
|
6
3
|
private regexRoutes;
|
|
@@ -122,11 +119,9 @@ declare class Logger$1 {
|
|
|
122
119
|
}
|
|
123
120
|
|
|
124
121
|
interface DatabaseConfig {
|
|
125
|
-
type? : 'bun-sql' // default
|
|
126
122
|
name? : string
|
|
127
|
-
connection : string
|
|
128
|
-
schema? : any
|
|
129
|
-
poolSize? : number
|
|
123
|
+
connection : string // File path or ':memory:'
|
|
124
|
+
schema? : Record<string, any>
|
|
130
125
|
timeout? : number
|
|
131
126
|
}
|
|
132
127
|
|
|
@@ -257,6 +252,92 @@ declare class Logger$1 {
|
|
|
257
252
|
}
|
|
258
253
|
}
|
|
259
254
|
|
|
255
|
+
type ColumnType = 'INTEGER' | 'TEXT' | 'REAL' | 'BLOB' | 'NUMERIC';
|
|
256
|
+
type SqlValue = string | number | boolean | null | Uint8Array;
|
|
257
|
+
interface ColumnDefinition {
|
|
258
|
+
name: string;
|
|
259
|
+
type: ColumnType;
|
|
260
|
+
primaryKey?: boolean;
|
|
261
|
+
autoIncrement?: boolean;
|
|
262
|
+
notNull?: boolean;
|
|
263
|
+
unique?: boolean;
|
|
264
|
+
default?: SqlValue;
|
|
265
|
+
references?: {
|
|
266
|
+
table: string;
|
|
267
|
+
column: string;
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
interface TableSchema {
|
|
271
|
+
name: string;
|
|
272
|
+
columns: ColumnDefinition[];
|
|
273
|
+
indexes?: {
|
|
274
|
+
name: string;
|
|
275
|
+
columns: string[];
|
|
276
|
+
unique?: boolean;
|
|
277
|
+
}[];
|
|
278
|
+
}
|
|
279
|
+
interface WhereCondition {
|
|
280
|
+
column: string;
|
|
281
|
+
operator: '=' | '!=' | '>' | '<' | '>=' | '<=' | 'LIKE' | 'IN' | 'IS NULL' | 'IS NOT NULL';
|
|
282
|
+
value?: SqlValue | SqlValue[];
|
|
283
|
+
}
|
|
284
|
+
interface QueryBuilder {
|
|
285
|
+
select: (columns?: string[]) => QueryBuilder;
|
|
286
|
+
from: (table: string) => QueryBuilder;
|
|
287
|
+
where: (condition: WhereCondition | WhereCondition[]) => QueryBuilder;
|
|
288
|
+
and: (condition: WhereCondition) => QueryBuilder;
|
|
289
|
+
or: (condition: WhereCondition) => QueryBuilder;
|
|
290
|
+
orderBy: (column: string, direction?: 'ASC' | 'DESC') => QueryBuilder;
|
|
291
|
+
limit: (count: number) => QueryBuilder;
|
|
292
|
+
offset: (count: number) => QueryBuilder;
|
|
293
|
+
insert: (table: string, data: Record<string, SqlValue>) => QueryBuilder;
|
|
294
|
+
update: (table: string, data: Record<string, SqlValue>) => QueryBuilder;
|
|
295
|
+
delete: (table: string) => QueryBuilder;
|
|
296
|
+
execute: () => any[];
|
|
297
|
+
executeOne: () => any | null;
|
|
298
|
+
executeRaw: (sql: string, params?: SqlValue[]) => any[];
|
|
299
|
+
raw: (sql: string, params?: SqlValue[]) => QueryBuilder;
|
|
300
|
+
}
|
|
301
|
+
declare class DB {
|
|
302
|
+
private db;
|
|
303
|
+
private schemas;
|
|
304
|
+
private currentQuery;
|
|
305
|
+
private currentParams;
|
|
306
|
+
constructor(path?: string);
|
|
307
|
+
close(): void;
|
|
308
|
+
defineSchema(schema: TableSchema): void;
|
|
309
|
+
getSchema(tableName: string): TableSchema | undefined;
|
|
310
|
+
listTables(): string[];
|
|
311
|
+
dropTable(tableName: string): void;
|
|
312
|
+
query(): QueryBuilder;
|
|
313
|
+
find(table: string, conditions: Record<string, SqlValue>): any[];
|
|
314
|
+
findOne(table: string, conditions: Record<string, SqlValue>): any | null;
|
|
315
|
+
findById(table: string, id: number | string): any | null;
|
|
316
|
+
all(table: string): any[];
|
|
317
|
+
insert(table: string, data: Record<string, SqlValue>): any;
|
|
318
|
+
update(table: string, id: number | string, data: Record<string, SqlValue>): any | null;
|
|
319
|
+
delete(table: string, id: number | string): boolean;
|
|
320
|
+
transaction(callback: (db: DB) => void): void;
|
|
321
|
+
exec(sql: string): void;
|
|
322
|
+
raw(sql: string, params?: SqlValue[]): any[];
|
|
323
|
+
rawOne(sql: string, params?: SqlValue[]): any | null;
|
|
324
|
+
private reset;
|
|
325
|
+
private createQueryBuilder;
|
|
326
|
+
private generateCreateTableSQL;
|
|
327
|
+
}
|
|
328
|
+
declare function table(name: string, columns: ColumnDefinition[]): TableSchema;
|
|
329
|
+
declare function column(name: string, type: ColumnType): ColumnDefinition;
|
|
330
|
+
declare function integer(name: string): ColumnDefinition;
|
|
331
|
+
declare function text(name: string): ColumnDefinition;
|
|
332
|
+
declare function real(name: string): ColumnDefinition;
|
|
333
|
+
declare function blob(name: string): ColumnDefinition;
|
|
334
|
+
declare function numeric(name: string): ColumnDefinition;
|
|
335
|
+
declare function primaryKey(col: ColumnDefinition, autoIncrement?: boolean): ColumnDefinition;
|
|
336
|
+
declare function notNull(col: ColumnDefinition): ColumnDefinition;
|
|
337
|
+
declare function unique(col: ColumnDefinition): ColumnDefinition;
|
|
338
|
+
declare function defaultValue(col: ColumnDefinition, value: SqlValue): ColumnDefinition;
|
|
339
|
+
declare function references(col: ColumnDefinition, table: string, column: string): ColumnDefinition;
|
|
340
|
+
|
|
260
341
|
declare function server(config?: ServerConfig): ServerInstance;
|
|
261
342
|
|
|
262
|
-
export { type AppContext, AppError, type AppMiddleware, type AuthConfig, type CookieOptions, type CorsConfig, type CsrfConfig, type DatabaseConfig, DatabaseError, type HelmetConfig, type HttpMethod, Logger$1 as Logger, type RateLimitConfig, RateLimitError, type RouteDefinition, type RouteHandler, Router, type SecurityConfig, SecurityManager, type ServerConfig, type ServerInstance, TimeoutError, ValidationError, server as default, server };
|
|
343
|
+
export { type AppContext, AppError, type AppMiddleware, type AuthConfig, type ColumnDefinition, type ColumnType, type CookieOptions, type CorsConfig, type CsrfConfig, DB, type DatabaseConfig, DatabaseError, type HelmetConfig, type HttpMethod, Logger$1 as Logger, type QueryBuilder, type RateLimitConfig, RateLimitError, type RouteDefinition, type RouteHandler, Router, type SecurityConfig, SecurityManager, type ServerConfig, type ServerInstance, type SqlValue, type TableSchema, TimeoutError, ValidationError, type WhereCondition, blob, column, server as default, defaultValue, integer, notNull, numeric, primaryKey, real, references, server, table, text, unique };
|
package/dist/main.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
${JSON.stringify(
|
|
1
|
+
import {Database}from'bun:sqlite';import ce from'crypto';var q=class{constructor(e=":memory:"){this.schemas=new Map;this.currentQuery="";this.currentParams=[];this.db=new Database(e),this.db.exec("PRAGMA foreign_keys = ON");}close(){this.db.close();}defineSchema(e){this.schemas.set(e.name,e);let r=this.generateCreateTableSQL(e);if(this.db.exec(r),e.indexes)for(let t of e.indexes){let a=`CREATE ${t.unique?"UNIQUE":""} INDEX IF NOT EXISTS ${t.name} ON ${e.name} (${t.columns.join(", ")})`;this.db.exec(a);}}getSchema(e){return this.schemas.get(e)}listTables(){return this.db.query("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'").all().map(r=>r.name)}dropTable(e){this.db.exec(`DROP TABLE IF EXISTS ${e}`),this.schemas.delete(e);}query(){return this.reset(),this.createQueryBuilder()}find(e,r){let t=Object.entries(r).map(([n,a])=>({column:n,operator:"=",value:a}));return this.query().select().from(e).where(t).execute()}findOne(e,r){return this.query().select().from(e).where(Object.entries(r).map(([t,n])=>({column:t,operator:"=",value:n}))).limit(1).executeOne()}findById(e,r){return this.findOne(e,{id:r})}all(e){return this.query().select().from(e).execute()}insert(e,r){this.query().insert(e,r).execute();let t=this.db.query("SELECT last_insert_rowid() as id").get();return this.findById(e,t.id)}update(e,r,t){return this.query().update(e,t).where({column:"id",operator:"=",value:r}).execute(),this.findById(e,r)}delete(e,r){this.query().delete(e).where({column:"id",operator:"=",value:r}).execute();return true}transaction(e){this.db.exec("BEGIN TRANSACTION");try{e(this),this.db.exec("COMMIT");}catch(r){throw this.db.exec("ROLLBACK"),r}}exec(e){this.db.exec(e);}raw(e,r=[]){return this.db.query(e).all(...r)}rawOne(e,r=[]){return this.db.query(e).get(...r)}reset(){this.currentQuery="",this.currentParams=[];}createQueryBuilder(){let e={_select:["*"],_from:"",_where:[],_orderBy:"",_limit:null,_offset:null,_isInsert:false,_isUpdate:false,_isDelete:false,_insertData:null,_updateData:null},r=this;return e.select=function(t){return this._select=t||["*"],this},e.from=function(t){return this._from=t,this},e.where=function(t){let a=(Array.isArray(t)?t:[t]).map(u=>{if(u.operator==="IS NULL"||u.operator==="IS NOT NULL")return `${u.column} ${u.operator}`;if(u.operator==="IN"&&Array.isArray(u.value)){let i=u.value.map(()=>"?").join(", ");return u.value.forEach(p=>{r.currentParams.push(p);}),`${u.column} IN (${i})`}else return r.currentParams.push(u.value),`${u.column} ${u.operator} ?`});return this._where.push(...a),this},e.and=function(t){return this.where(t)},e.or=function(t){if(t.operator==="IS NULL"||t.operator==="IS NOT NULL")this._where.push(`OR ${t.column} ${t.operator}`);else if(t.operator==="IN"&&Array.isArray(t.value)){let n=t.value.map(()=>"?").join(", ");t.value.forEach(a=>{r.currentParams.push(a);}),this._where.push(`OR ${t.column} IN (${n})`);}else r.currentParams.push(t.value),this._where.push(`OR ${t.column} ${t.operator} ?`);return this},e.orderBy=function(t,n="ASC"){return this._orderBy=`ORDER BY ${t} ${n}`,this},e.limit=function(t){return this._limit=t,this},e.offset=function(t){return this._offset=t,this},e.insert=function(t,n){return this._isInsert=true,this._from=t,this._insertData=n,this},e.update=function(t,n){return this._isUpdate=true,this._from=t,this._updateData=n,this},e.delete=function(t){return this._isDelete=true,this._from=t,this},e.raw=function(t,n=[]){return r.currentQuery=t,r.currentParams=n,this},e.execute=function(){let t="";if(this._isInsert&&this._insertData){let u=Object.keys(this._insertData),i=u.map(()=>"?").join(", ");t=`INSERT INTO ${this._from} (${u.join(", ")}) VALUES (${i})`,r.currentParams=Object.values(this._insertData);}else if(this._isUpdate&&this._updateData){let u=Object.keys(this._updateData).map(p=>`${p} = ?`),i=Object.values(this._updateData);r.currentParams=[...i,...r.currentParams],t=`UPDATE ${this._from} SET ${u.join(", ")}`,this._where.length>0&&(t+=` WHERE ${this._where.join(" AND ")}`);}else this._isDelete?(t=`DELETE FROM ${this._from}`,this._where.length>0&&(t+=` WHERE ${this._where.join(" AND ")}`)):(t=`SELECT ${this._select.join(", ")} FROM ${this._from}`,this._where.length>0&&(t+=` WHERE ${this._where.join(" AND ")}`),this._orderBy&&(t+=` ${this._orderBy}`),this._limit!==null&&(t+=` LIMIT ${this._limit}`),this._offset!==null&&(t+=` OFFSET ${this._offset}`));!t&&r.currentQuery&&(t=r.currentQuery);let a=r.db.query(t).all(...r.currentParams);return r.reset(),a},e.executeOne=function(){let t=this.execute();return t.length>0?t[0]:null},e.executeRaw=function(t,n=[]){return r.db.query(t).all(...n)},e}generateCreateTableSQL(e){let r=e.columns.map(t=>{let n=`${t.name} ${t.type}`;return t.primaryKey&&(n+=" PRIMARY KEY",t.autoIncrement&&(n+=" AUTOINCREMENT")),t.notNull&&!t.primaryKey&&(n+=" NOT NULL"),t.unique&&(n+=" UNIQUE"),t.default!==void 0&&(typeof t.default=="string"?n+=` DEFAULT '${t.default}'`:t.default===null?n+=" DEFAULT NULL":n+=` DEFAULT ${t.default}`),t.references&&(n+=` REFERENCES ${t.references.table}(${t.references.column})`),n});return `CREATE TABLE IF NOT EXISTS ${e.name} (${r.join(", ")})`}};function Y(s,e){return {name:s,columns:e}}function Z(s,e){return {name:s,type:e}}function ee(s){return {name:s,type:"INTEGER"}}function te(s){return {name:s,type:"TEXT"}}function re(s){return {name:s,type:"REAL"}}function ne(s){return {name:s,type:"BLOB"}}function se(s){return {name:s,type:"NUMERIC"}}function oe(s,e=false){return {...s,primaryKey:true,autoIncrement:e}}function ie(s){return {...s,notNull:true}}function ae(s){return {...s,unique:true}}function ue(s,e){return {...s,default:e}}function le(s,e,r){return {...s,references:{table:e,column:r}}}var _=class{constructor(){this.routes=new Map;this.regexRoutes=[];}match(e,r){let t=`${e}:${r}`;if(this.routes.has(t))return {handler:this.routes.get(t),params:{}};for(let n of this.regexRoutes)if(n.method===e){let a=r.match(n.pattern);if(a?.groups)return {handler:n.handler,params:a.groups}}return null}getAll(){let e=Array.from(this.routes.entries()).map(([t,n])=>{let a=t.indexOf(":"),u=t.substring(0,a),i=t.substring(a+1);return {method:u,path:i,handler:n}}),r=this.regexRoutes.map(t=>{let n=t.key.indexOf(":");return {method:t.method,path:t.key.substring(n+1),handler:t.handler}});return [...e,...r]}clear(){this.routes.clear(),this.regexRoutes=[];}remove(e,r){let t=`${e}:${r}`;if(this.routes.has(t))return this.routes.delete(t),true;let n=this.regexRoutes.findIndex(a=>a.key===t);return n>=0?(this.regexRoutes.splice(n,1),true):false}register(e,r,t,n={}){let a=`${e}:${r}`;if(r.includes(":")){let u=this.pathToRegex(r),i=this.regexRoutes.findIndex(b=>b.key===a),p={pattern:u,method:e,handler:t,key:a};i>=0?this.regexRoutes[i]=p:this.regexRoutes.push(p);}else this.routes.set(a,t);}pathToRegex(e){let t=e.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/:(\w+)/g,"(?<$1>[^/]+)");return new RegExp(`^${t}$`)}};var N=class{constructor(){this.rateLimitStore=new Map;this.csrfTokens=new Map;this.requestLog=new Map;this.MAX_REQUEST_LOG_SIZE=1e3;}checkRateLimit(e,r,t){let n=Date.now(),a=this.rateLimitStore.get(e);return a?n<a.reset?a.count>=r?false:(a.count++,true):(this.rateLimitStore.set(e,{count:1,reset:n+t}),true):(this.rateLimitStore.set(e,{count:1,reset:n+t}),true)}cleanupRateLimit(){let e=Date.now();for(let[r,t]of this.rateLimitStore.entries())e>t.reset&&this.rateLimitStore.delete(r);}generateCsrfToken(e,r=36e5){let t=ce.randomBytes(32).toString("hex");return this.csrfTokens.set(t,{sessionId:e,expires:Date.now()+r}),t}validateCsrfToken(e,r){let t=this.csrfTokens.get(e);return t?Date.now()>t.expires?(this.csrfTokens.delete(e),false):t.sessionId===r?(this.csrfTokens.delete(e),true):false:false}cleanupCsrfTokens(){let e=Date.now();for(let[r,t]of this.csrfTokens.entries())e>t.expires&&this.csrfTokens.delete(r);}sanitizeHtml(e){return e?e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/"):""}sanitizeSql(e){return e?e.replace(/\\/g,"\\\\").replace(/;/g,"").replace(/'/g,"''").replace(/"/g,'\\"').replace(/\x00/g,""):""}logRequest(e,r,t,n,a,u){if(this.requestLog.set(e,{timestamp:new Date().toISOString(),method:r,path:t,ip:n,status:a,duration:u}),this.requestLog.size>this.MAX_REQUEST_LOG_SIZE){let{value:i}=this.requestLog.keys().next()||{value:null};i&&this.requestLog.delete(i);}}getRequestLog(e){return this.requestLog.get(e)}getAllRequestLogs(){return Array.from(this.requestLog.values())}clearAll(){this.rateLimitStore.clear(),this.csrfTokens.clear(),this.requestLog.clear();}getStats(){return {rateLimitEntries:this.rateLimitStore.size,csrfTokens:this.csrfTokens.size,requestLogs:this.requestLog.size}}};var $=class{constructor(e="info",r=false){this.level=1;this.pretty=false;this.levels={debug:0,info:1,warn:2,error:3,fatal:4};this.level=this.levels[e]??1,this.pretty=r;}debug(e,r){this.log("debug",this.levels.debug,e,r);}info(e,r){this.log("info",this.levels.info,e,r);}warn(e,r){this.log("warn",this.levels.warn,e,r);}error(e,r){this.log("error",this.levels.error,e,r);}fatal(e,r){this.log("fatal",this.levels.fatal,e,r),process.env.NODE_ENV;}log(e,r,t,n){if(r<this.level)return;let a=new Date().toISOString(),u=t??{},i={timestamp:a,level:e.toUpperCase(),message:n||"No message",...u},p=this.pretty?`[${a}] ${e.toUpperCase()} ${n||"No message"}
|
|
2
|
+
${JSON.stringify(u,null,2)}`:JSON.stringify(i);e==="error"||e==="fatal"?console.error(p):e==="warn"?console.warn(p):console.log(p);}};var w=class extends Error{constructor(r,t=500,n){super(r);this.message=r;this.statusCode=t;this.code=n;this.name="AppError";}},E=class extends w{constructor(r,t){super(r,400,"VALIDATION_ERROR");this.issues=t;this.name="ValidationError";}},W=class extends w{constructor(e){super(e,500,"DATABASE_ERROR"),this.name="DatabaseError";}},k=class extends w{constructor(e="Request timeout"){super(e,408,"TIMEOUT_ERROR"),this.name="TimeoutError";}},G=class extends w{constructor(e="Too many requests"){super(e,429,"RATE_LIMIT_ERROR"),this.name="RateLimitError";}};var P=new N,L=new _;function de(s={}){let e=s.port||3e3,r=s.hostname||"localhost",t=s.maxRequestSize||10*1024*1024,n=s.requestTimeout||3e4,a=s.gracefulShutdownTimeout||1e4,u=typeof s.logging=="object"?s.logging:{},i=s.logging?new $(u.level||"info",u.pretty):null,p=new Map,b=[],x=new Set,T=setInterval(()=>{P.cleanupRateLimit(),P.cleanupCsrfTokens();},120*1e3);async function c(o){let m=Date.now(),l=crypto.randomUUID(),R=new URL(o.url).pathname,A=o.method.toUpperCase(),f=he(o);x.add(l);try{let y=o.headers.get("content-length");if(y&&parseInt(y)>t)return i?.warn({requestId:l,size:y,ip:f},"Request too large"),new Response(JSON.stringify({error:"Payload too large"}),{status:413,headers:{"Content-Type":"application/json"}});let I=fe(o,s);if(A==="OPTIONS")return new Response(null,{status:204,headers:I});if(s.security&&typeof s.security=="object"&&s.security.rateLimit){let C=typeof s.security.rateLimit=="object"?s.security.rateLimit:{},v=C.max||100,j=C.windowMs||6e4,F=C.keyGenerator?C.keyGenerator({request:o,ip:f}):f;if(!P.checkRateLimit(F,v,j))return i?.warn({requestId:l,ip:f,key:F},"Rate limit exceeded"),new Response(JSON.stringify({error:C.message||"Too many requests"}),{status:429,headers:{"Content-Type":"application/json"}})}let M=null;["POST","PUT","PATCH"].includes(A)&&(M=await ge(o,i,t));let H=p.get("default"),B=L.match(A,R);if(!B){let C=X(o,{},H,i,l);return i?.warn({requestId:l,method:A,path:R,ip:f},"Route not found"),C.json({error:"Not Found",path:R},404)}let U=X(o,B.params||{},H,i,l);U.body=M,U.request=o;let Q=new AbortController,K=new Promise((C,v)=>{let j=setTimeout(()=>{Q.abort(),v(new k("Request timeout"));},n);Q.signal.addEventListener("abort",()=>clearTimeout(j));}),D=await Promise.race([B.handler(U),K]),S=new Headers(D.headers);I.forEach((C,v)=>{S.has(v)||S.set(v,C);}),S.set("X-Request-ID",l),S.set("X-Content-Type-Options","nosniff"),S.set("X-Frame-Options","DENY"),S.set("X-XSS-Protection","1; mode=block"),S.set("Referrer-Policy","strict-origin-when-cross-origin");let z=Date.now()-m;return P.logRequest(l,A,R,f,D.status,z),i?.info({requestId:l,method:A,path:R,status:D.status,duration:z,ip:f},"Request completed"),new Response(D.body,{status:D.status,headers:S})}catch(y){if(y instanceof w)return i?.warn({error:y.message,requestId:l,ip:f},`App error: ${y.message}`),new Response(JSON.stringify({error:y.message,code:y.code,requestId:l}),{status:y.statusCode,headers:{"Content-Type":"application/json"}});i?.error({error:String(y),requestId:l,ip:f},"Unhandled error");let I=process.env.NODE_ENV==="production"?"Internal Server Error":y.message;return new Response(JSON.stringify({error:I,requestId:l}),{status:500,headers:{"Content-Type":"application/json"}})}finally{x.delete(l);}}let d={method:"GET",path:"/health",handler:o=>o.json({status:"healthy",timestamp:new Date().toISOString(),uptime:process.uptime(),activeRequests:x.size})},g={method:"GET",path:"/readiness",handler:o=>{let m=p.size>0,l=m||p.size===0;return o.json({ready:l,checks:{database:m?"connected":"not configured",activeRequests:x.size},timestamp:new Date().toISOString()},l?200:503)}};s.routes&&s.routes.forEach(o=>{b.push(o),(Array.isArray(o.method)?o.method:[o.method]).forEach(l=>{L.register(l,o.path,o.handler,o);});}),b.push(d,g),L.register("GET","/health",d.handler,d),L.register("GET","/readiness",g.handler,g);let h=null,V={app:null,logger:i,db:p,bunServer:null,async start(){if(s.database){let m=Array.isArray(s.database)?s.database:[s.database];for(let l of m){let O=l.name||"default";try{if(typeof l.connection=="string"){let R=new q(l.connection);if(l.schema&&typeof l.schema=="object")for(let[A,f]of Object.entries(l.schema))f&&typeof f=="object"&&R.defineSchema(f);p.set(O,R),i?.info({name:O,connection:l.connection},"\u2705 Database connected");}else throw new Error(`Database connection must be a string path (got ${typeof l.connection})`)}catch(R){throw i?.error({error:String(R),name:O},"Failed to connect to database"),R}}}h=Bun.serve({port:e,hostname:r,fetch:c}),V.bunServer=h;let o=`http://${r}:${e}`;console.log(`\u2192 URL: ${o}
|
|
3
3
|
\u2192 Environment: ${process.env.NODE_ENV||"development"}
|
|
4
4
|
\u2192 Routes: ${b.length.toString()}
|
|
5
|
-
\u2192 Database: ${
|
|
5
|
+
\u2192 Database: ${p.size>0?"\u2705 Connected":"\u274C None"}
|
|
6
6
|
\u2192 Security: ${s.security?"\u2705 ENABLED":"\u274C Disabled"}
|
|
7
7
|
|
|
8
8
|
\u{1F50D} Health: ${o}/health
|
|
9
9
|
\u{1F50D} Ready: ${o}/readiness
|
|
10
|
-
`),
|
|
10
|
+
`),i?.info({url:o},"Server started");},async stop(){if(i?.info("Stopping server..."),x.size>0){i?.info({count:x.size},"Waiting for active requests...");let o=Date.now()+a;for(;x.size>0&&Date.now()<o;)await new Promise(m=>setTimeout(m,100));x.size>0&&i?.warn({count:x.size},"Force closing with active requests");}if(clearInterval(T),s.onShutdown)try{await s.onShutdown();}catch(o){i?.error({error:String(o)},"Error in shutdown handler");}for(let[o,m]of p.entries())try{m&&typeof m.close=="function"&&m.close(),i?.info({name:o},"Database closed");}catch(l){i?.error({error:String(l),name:o},"Error closing database");}h&&(h.stop(),i?.info("Bun server stopped")),i?.info("Server stopped successfully");},addRoute(o){b.push(o),(Array.isArray(o.method)?o.method:[o.method]).forEach(l=>{L.register(l,o.path,o.handler,o);}),i?.info({method:o.method,path:o.path},"Route added");},getRoutes(){return b}};return V}async function ge(s,e,r){let t=s.headers.get("content-type")||"";try{if(t.includes("application/json")){let n=await s.text();if(n.length>r)throw new E("Payload too large");if(!n.trim())return {};try{return JSON.parse(n)}catch(a){throw e?.warn({error:String(a),bodyPreview:n.substring(0,100)},"Invalid JSON in request body"),new E("Invalid JSON in request body")}}if(t.includes("application/x-www-form-urlencoded")){let n=await s.text();if(n.length>r)throw new E("Payload too large");return Object.fromEntries(new URLSearchParams(n))}if(t.includes("multipart/form-data"))return await s.formData()}catch(n){throw n instanceof E?n:(e?.error({error:String(n)},"Error parsing request body"),new E("Failed to parse request body"))}return {}}function me(s){let e=new Map;if(!s)return e;let r=s.split(";");for(let t of r){let[n,...a]=t.trim().split("=");if(n){let u=a.join("=");e.set(n,u?decodeURIComponent(u):"");}}return e}function X(s,e,r,t,n){let a=new URL(s.url),u=Object.fromEntries(a.searchParams),i=s.headers,p=200,b=new Map,x=me(i.get("cookie")||""),T={request:s,params:e,query:u,headers:i,db:r,logger:t,requestId:n,get statusCode(){return p},set statusCode(c){p=c;},body:null,json(c,d){return new Response(JSON.stringify(c),{status:d??p,headers:{"Content-Type":"application/json",...this._setCookieHeaders()}})},text(c,d){return new Response(c,{status:d??p,headers:{"Content-Type":"text/plain",...this._setCookieHeaders()}})},html(c,d){return new Response(c,{status:d??p,headers:{"Content-Type":"text/html; charset=utf-8",...this._setCookieHeaders()}})},redirect(c,d=302){return new Response(null,{status:d,headers:{Location:c,...this._setCookieHeaders()}})},file(c,d="application/octet-stream"){let g=Bun.file(c);return new Response(g,{headers:{"Content-Type":d,...this._setCookieHeaders()}})},setCookie(c,d,g={}){let h=`${c}=${encodeURIComponent(d)}`;return g.maxAge!==void 0&&(h+=`; Max-Age=${g.maxAge}`),g.expires&&(h+=`; Expires=${g.expires.toUTCString()}`),g.path&&(h+=`; Path=${g.path}`),g.domain&&(h+=`; Domain=${g.domain}`),g.secure&&(h+="; Secure"),g.httpOnly&&(h+="; HttpOnly"),g.sameSite&&(h+=`; SameSite=${g.sameSite}`),b.set(c,h),T},getCookie(c){return x.get(c)},deleteCookie(c,d={}){return T.setCookie(c,"",{...d,maxAge:0,path:d.path||"/"})},setHeader(c,d){return i.set(c,d),T},getHeader(c){return i.get(c)||void 0},status(c){return p=c,T},_setCookieHeaders(){let c={};return b.size>0&&(c["Set-Cookie"]=Array.from(b.values())),c}};return T}function he(s){let e=s.headers.get("x-forwarded-for");if(e)return e.split(",").map(n=>n.trim())[0]||"unknown";let r=s.headers.get("x-real-ip");return r||"unknown"}function fe(s,e){let r=new Headers;if(!e.security||typeof e.security!="object"||!e.security.cors)return r;let t=typeof e.security.cors=="object"?e.security.cors:{},n=s.headers.get("Origin");if(n){typeof t.origin=="function"?t.origin(n)&&r.set("Access-Control-Allow-Origin",n):Array.isArray(t.origin)?t.origin.includes(n)&&r.set("Access-Control-Allow-Origin",n):typeof t.origin=="string"?r.set("Access-Control-Allow-Origin",t.origin):r.set("Access-Control-Allow-Origin",n);let a=t.methods||["GET","POST","PUT","DELETE","PATCH","OPTIONS"];r.set("Access-Control-Allow-Methods",a.join(", "));let u=t.allowedHeaders||["Content-Type","Authorization","X-Requested-With"];r.set("Access-Control-Allow-Headers",u.join(", ")),t.credentials&&r.set("Access-Control-Allow-Credentials","true"),t.maxAge&&r.set("Access-Control-Max-Age",t.maxAge.toString());}return r}var ve=de;export{w as AppError,q as DB,W as DatabaseError,$ as Logger,G as RateLimitError,_ as Router,N as SecurityManager,k as TimeoutError,E as ValidationError,ne as blob,Z as column,ve as default,ue as defaultValue,ee as integer,ie as notNull,se as numeric,oe as primaryKey,re as real,le as references,de as server,Y as table,te as text,ae as unique};//# sourceMappingURL=main.js.map
|
|
11
11
|
//# sourceMappingURL=main.js.map
|