lieko-express 0.0.10 → 0.0.12

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.
@@ -1,293 +1,161 @@
1
- declare namespace Lieko {
2
- type PlainObject = Record<string, any>;
1
+ declare module "lieko-express" {
2
+ import { IncomingMessage, ServerResponse } from "http";
3
3
 
4
- // Extract params from a path string like "/user/:id/books/:bookId"
5
- type ExtractRouteParams<Path extends string> =
6
- Path extends `${string}:${infer Param}/${infer Rest}`
7
- ? { [k in Param | keyof ExtractRouteParams<Rest>]: string }
8
- : Path extends `${string}:${infer Param}`
9
- ? { [k in Param]: string }
10
- : Record<string, never>;
4
+ // -------------------------------
5
+ // Request Extensions
6
+ // -------------------------------
7
+ interface LiekoRequest extends IncomingMessage {
8
+ app: any;
11
9
 
12
- // -------------- Request / Response types --------------
13
- // Minimal subset of http.IncomingMessage / http.ServerResponse for typings
14
- interface RequestBase {
15
- method: string;
16
- url: string;
17
- headers: Record<string, string | undefined>;
18
- // populated by the framework:
10
+ // Passport fields
11
+ user?: any;
12
+ session?: any;
13
+
14
+ // Auth helpers
15
+ logout(callback?: (err: any) => void): Promise<void> | void;
16
+
17
+ // URL helpers
18
+ originalUrl: string;
19
+ params: Record<string, string>;
19
20
  query: Record<string, any>;
20
- params: Record<string, any>;
21
21
  body: any;
22
22
  files: Record<string, any>;
23
- ip?: string;
24
- _bodySize?: number;
25
- _startTime?: bigint;
26
- // raw Node objects (optional)
27
- raw?: any;
28
- }
29
-
30
- interface ResponseBase {
31
- status(code: number): this;
32
- json(data: any): void;
33
- send(data: any): void;
34
- text(data: string): void;
35
-
36
- // headers helpers
37
- setHeader(name: string, value: string | number): void;
38
- set(name: string | Record<string, string | number>, value?: string | number): void;
39
- header(name: string, value: string | number): void;
40
- getHeader(name: string): string | number | string[] | undefined;
41
- removeHeader(name: string): void;
42
- headersSent?: boolean;
43
-
44
- // redirect helpers
45
- redirect(url: string): void;
46
- redirect(status: number, url: string): void;
47
-
48
- // streaming (optional)
49
- write?(chunk: any): void;
50
- end?(chunk?: any): void;
51
- }
52
-
53
- // Extended Lieko Request and Response with framework helpers
54
- interface Request<
55
- Params extends Record<string, any> = Record<string, any>,
56
- Query extends Record<string, any> = Record<string, any>,
57
- Body = any
58
- > extends RequestBase {
59
- params: Params;
60
- query: Query;
61
- body: Body;
62
- files: Record<string, {
63
- filename: string;
64
- tempFilePath?: string;
65
- data?: Buffer;
66
- contentType?: string;
67
- size?: number;
68
- }>;
69
- }
70
-
71
- interface Response extends ResponseBase {
72
- // Rich helpers provided by Lieko
73
- ok(data?: any, message?: string): void;
74
- success: (data?: any, message?: string) => void;
75
- created(data?: any, message?: string): void;
76
- noContent(): void;
77
- accepted(data?: any, message?: string): void;
78
-
79
- badRequest(message?: string, details?: any): void;
80
- unauthorized(message?: string, details?: any): void;
81
- forbidden(message?: string, details?: any): void;
82
- notFound(message?: string, details?: any): void;
83
- error(message?: string, status?: number, details?: any): void;
84
- fail: (message?: string, status?: number, details?: any) => void;
85
- serverError(message?: string, details?: any): void;
86
-
87
- // convenience helpers sometimes provided
88
- paginated?(items: any[], total: number, message?: string): void;
89
- html?(html: string, status?: number): void;
90
-
91
- // short alias
92
- statusCode?: number;
93
- }
94
-
95
- // -------------- Handler / Middleware --------------
96
- type Handler<
97
- Params extends Record<string, any> = Record<string, any>,
98
- Query extends Record<string, any> = Record<string, any>,
99
- Body = any
100
- > = (req: Request<Params, Query, Body>, res: Response, next?: (err?: any) => void) => any | Promise<any>;
101
-
102
- // -------------- CORS / BodyParser options --------------
103
- interface CorsOptions {
104
- enabled?: boolean;
105
- origin?: "*" | string | string[]; // supports wildcard like https://*.example.com
106
- methods?: string[]; // allowed methods
107
- headers?: string[]; // allowed headers
108
- exposedHeaders?: string[];
109
- credentials?: boolean;
110
- maxAge?: number;
111
- debug?: boolean;
112
- strictOrigin?: boolean; // 403 if origin not allowed
113
- allowPrivateNetwork?: boolean; // Access-Control-Allow-Private-Network
114
- }
115
-
116
- interface JsonBodyOptions {
117
- limit?: string; // e.g. "10mb"
118
- strict?: boolean;
119
- }
120
-
121
- interface UrlencodedOptions {
122
- limit?: string;
123
- extended?: boolean;
124
- }
125
-
126
- interface MultipartOptions {
127
- limit?: string;
128
- tempDir?: string;
129
- }
23
+ xhr: boolean;
24
+
25
+ // IP helpers
26
+ ip: {
27
+ raw: string | null;
28
+ ipv4: string | null;
29
+ ipv6: string | null;
30
+ display: string;
31
+ };
32
+ ips: string[];
130
33
 
131
- interface BodyParserOptions {
132
- json?: JsonBodyOptions;
133
- urlencoded?: UrlencodedOptions;
134
- multipart?: MultipartOptions;
135
- }
34
+ protocol: string;
35
+ secure: boolean;
36
+ hostname: string;
37
+ subdomains: string[];
136
38
 
137
- // -------------- Validation / Schema (loose typing to match runtime) --------------
138
- // The framework has a validation system — keep it flexible (user can extend)
139
- type ValidatorFn = (value: any, field: string, data: any) => { field: string; message: string; type: string } | null;
39
+ get(name: string): string | undefined;
40
+ header(name: string): string | undefined;
140
41
 
141
- interface Validators {
142
- required(message?: string): ValidatorFn;
143
- requiredTrue(message?: string): ValidatorFn;
144
- optional(): ValidatorFn;
145
- string(message?: string): ValidatorFn;
146
- number(message?: string): ValidatorFn;
147
- boolean(message?: string): ValidatorFn;
148
- integer(message?: string): ValidatorFn;
149
- positive(message?: string): ValidatorFn;
150
- negative(message?: string): ValidatorFn;
151
- email(message?: string): ValidatorFn;
152
- min(minValue: number, message?: string): ValidatorFn;
153
- max(maxValue: number, message?: string): ValidatorFn;
154
- length(n: number, message?: string): ValidatorFn;
155
- minLength(minLength: number, message?: string): ValidatorFn;
156
- maxLength(maxLength: number, message?: string): ValidatorFn;
157
- pattern(regex: RegExp, message?: string): ValidatorFn;
158
- oneOf(allowedValues: any[], message?: string): ValidatorFn;
159
- notOneOf(values: any[], message?: string): ValidatorFn;
160
- custom(validatorFn: (value: any, data: any) => boolean, message?: string): ValidatorFn;
161
- equal(expectedValue: any, message?: string): ValidatorFn;
162
- mustBeTrue(message?: string): ValidatorFn;
163
- mustBeFalse(message?: string): ValidatorFn;
164
- date(message?: string): ValidatorFn;
165
- before(limit: string | Date, message?: string): ValidatorFn;
166
- after(limit: string | Date, message?: string): ValidatorFn;
167
- startsWith(prefix: string, message?: string): ValidatorFn;
168
- endsWith(suffix: string, message?: string): ValidatorFn;
169
- }
42
+ accepts(types: string | string[]): string | false;
43
+ acceptsLanguages(langs: string | string[]): string | false;
44
+ acceptsCharsets(charsets: string | string[]): string | false;
45
+ acceptsEncodings(enc: string | string[]): string | false;
170
46
 
171
- class Schema {
172
- constructor(rules: Record<string, ValidatorFn[]>);
173
- rules: Record<string, ValidatorFn[]>;
174
- fields: Record<string, ValidatorFn[]>;
175
- validate(data: Record<string, any>): true | never;
47
+ is(type: string): boolean;
176
48
  }
177
49
 
178
- function validate(schema: Schema): Handler;
179
-
180
- function validatePartial(schema: Schema): Handler;
50
+ // -------------------------------
51
+ // Response Extensions
52
+ // -------------------------------
53
+ interface LiekoResponse extends ServerResponse {
54
+ app: any;
55
+ locals: Record<string, any>;
181
56
 
182
- // -------------- Routes / Options --------------
183
- interface Route {
184
- method: string;
185
- path: string;
186
- handler: Handler;
187
- middlewares: Handler[];
188
- pattern: RegExp;
189
- groupChain: any[];
190
- }
191
-
192
- // -------------- App interface --------------
193
- interface App {
194
- // route methods (typed path param extraction)
195
- get<Path extends string, Q = any, B = any>(
196
- path: Path,
197
- ...handlers: Handler<ExtractRouteParams<Path>, Q, B>[]
198
- ): this;
199
-
200
- post<Path extends string, Q = any, B = any>(
201
- path: Path,
202
- ...handlers: Handler<ExtractRouteParams<Path>, Q, B>[]
203
- ): this;
204
-
205
- put<Path extends string, Q = any, B = any>(
206
- path: Path,
207
- ...handlers: Handler<ExtractRouteParams<Path>, Q, B>[]
57
+ status(code: number): this;
58
+ set(name: string, value: string): this;
59
+ header(name: string, value: string): this;
60
+ type(mime: string): this;
61
+
62
+ json(data: any): this;
63
+ send(data: any): this;
64
+ html(html: string, status?: number): this;
65
+
66
+ redirect(url: string, status?: number): this;
67
+
68
+ ok(data: any, message?: string): this;
69
+ success(data: any, message?: string): this;
70
+ created(data: any, message?: string): this;
71
+ noContent(): this;
72
+ accepted(data?: any, message?: string): this;
73
+ paginated(items: any[], total: number, message?: string): this;
74
+
75
+ // Cookie helpers
76
+ cookie(
77
+ name: string,
78
+ value: string,
79
+ options?: {
80
+ path?: string;
81
+ httpOnly?: boolean;
82
+ secure?: boolean;
83
+ sameSite?: "lax" | "strict" | "none";
84
+ maxAge?: number;
85
+ expires?: Date;
86
+ domain?: string;
87
+ }
208
88
  ): this;
209
89
 
210
- patch<Path extends string, Q = any, B = any>(
211
- path: Path,
212
- ...handlers: Handler<ExtractRouteParams<Path>, Q, B>[]
90
+ clearCookie(
91
+ name: string,
92
+ options?: {
93
+ path?: string;
94
+ httpOnly?: boolean;
95
+ secure?: boolean;
96
+ sameSite?: "lax" | "strict" | "none";
97
+ }
213
98
  ): this;
214
99
 
215
- delete<Path extends string, Q = any, B = any>(
216
- path: Path,
217
- ...handlers: Handler<ExtractRouteParams<Path>, Q, B>[]
218
- ): this;
100
+ error(obj: any): this;
101
+ fail(obj: any): this;
102
+ badRequest(msg?: string): this;
103
+ unauthorized(msg?: string): this;
104
+ forbidden(msg?: string): this;
105
+ notFound(msg?: string): this;
106
+ serverError(msg?: string): this;
107
+ }
219
108
 
220
- all<Path extends string, Q = any, B = any>(
221
- path: Path,
222
- ...handlers: Handler<ExtractRouteParams<Path>, Q, B>[]
109
+ // -------------------------------
110
+ // Handler Types
111
+ // -------------------------------
112
+ type LiekoHandler = (
113
+ req: LiekoRequest,
114
+ res: LiekoResponse,
115
+ next: (err?: any) => void
116
+ ) => any;
117
+
118
+ type LiekoErrorHandler = (
119
+ err: any,
120
+ req: LiekoRequest,
121
+ res: LiekoResponse,
122
+ next: (err?: any) => void
123
+ ) => any;
124
+
125
+ // -------------------------------
126
+ // Router / App Class
127
+ // -------------------------------
128
+ class LiekoExpress {
129
+ constructor();
130
+
131
+ get(path: string, ...handlers: LiekoHandler[]): this;
132
+ post(path: string, ...handlers: LiekoHandler[]): this;
133
+ put(path: string, ...handlers: LiekoHandler[]): this;
134
+ patch(path: string, ...handlers: LiekoHandler[]): this;
135
+ delete(path: string, ...handlers: LiekoHandler[]): this;
136
+ all(path: string, ...handlers: LiekoHandler[]): this;
137
+
138
+ use(mw: LiekoHandler): this;
139
+ use(path: string, mw: LiekoHandler): this;
140
+ use(path: string, router: LiekoExpress): this;
141
+ use(path: string, mw: LiekoHandler, router: LiekoExpress): this;
142
+
143
+ group(
144
+ basePath: string,
145
+ ...middlewares: LiekoHandler[]
223
146
  ): this;
224
147
 
225
- // middleware
226
- use(handler: Handler | App): this;
227
- use(path: string, handler: Handler | App): this;
148
+ errorHandler(handler: LiekoErrorHandler): this;
149
+ notFound(handler: LiekoHandler): this;
228
150
 
229
- // grouping
230
- group(basePath: string, callback: (group: App) => void): this;
151
+ set(name: string, value: any): this;
152
+ get(setting: string): any;
231
153
 
232
- // CORS
233
- cors(options?: Partial<CorsOptions>): Handler;
234
-
235
- // body parser
236
- bodyParser: {
237
- json(options?: JsonBodyOptions): Handler;
238
- urlencoded(options?: UrlencodedOptions): Handler;
239
- multipart(options?: MultipartOptions): Handler;
240
- };
241
-
242
- // static files
243
- static(root: string, options?: { maxAge?: number; index?: string }): Handler;
244
-
245
- // error handler
246
- error(res: Response, obj: any): void;
247
-
248
- // settings
249
- set(key: string, value: any): this;
250
- get(key: string): any;
251
-
252
- // debug
253
- debug(value?: boolean | string): this;
254
-
255
- // utilities
256
- listRoutes(): { method: string; path: string | string[]; middlewares: number }[];
257
- printRoutes(): void;
258
-
259
- // server control
260
154
  listen(port: number, host?: string, callback?: () => void): any;
261
- listen(...args: any[]): any;
262
- }
263
-
264
- // -------------- Factory / Constructor --------------
265
- interface ConstructorOptions {
266
- // initial options
267
- cors?: Partial<CorsOptions>;
268
- bodyParser?: Partial<BodyParserOptions>;
269
- trustProxy?: boolean | string | string[];
270
- debug?: boolean;
271
- allowTrailingSlash?: boolean;
272
- strictTrailingSlash?: boolean;
273
- // other global options
274
- [key: string]: any;
275
155
  }
276
156
 
277
- interface LiekoStatic {
278
- (opts?: ConstructorOptions): App;
157
+ function Lieko(): LiekoExpress;
158
+ function Router(): LiekoExpress;
279
159
 
280
- // expose helpers statically if present in runtime
281
- Router: () => App;
282
- Schema: typeof Schema;
283
- schema: (...args: any[]) => Schema;
284
- validators: Validators;
285
- validate: typeof validate;
286
- validatePartial: (schema: Schema) => Handler;
287
- ValidationError: typeof ValidationError;
288
- static: (root: string, options?: { maxAge?: number; index?: string }) => Handler;
289
- }
160
+ export = Lieko;
290
161
  }
291
-
292
- declare const Lieko: Lieko.LiekoStatic;
293
- export = Lieko;
package/lieko-express.js CHANGED
@@ -78,7 +78,7 @@ class LiekoExpress {
78
78
  }
79
79
 
80
80
  let regexStr = pattern
81
- .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
81
+ .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
82
82
  .replace(/\\\*/g, '.*');
83
83
 
84
84
  regexStr = '^' + regexStr + '$';
@@ -912,7 +912,8 @@ ${cyan} (req, res, next) => {
912
912
 
913
913
  async _handleRequest(req, res) {
914
914
  if (this._isExcluded(req.url.split('?')[0])) {
915
- return res.status(404).end();
915
+ res.statusCode = 404;
916
+ return res.end();
916
917
  }
917
918
 
918
919
  this._enhanceRequest(req);
@@ -1199,6 +1200,26 @@ ${cyan} (req, res, next) => {
1199
1200
  if (t === 'multipart') return ct.includes('multipart');
1200
1201
  return false;
1201
1202
  };
1203
+
1204
+ /**
1205
+ * Passport-compatible logout (Passport 0.6+ / 0.7)
1206
+ * This ensures logout(cb) always calls cb(null) and never overwrites Express res
1207
+ */
1208
+ req.logout = function logout(callback) {
1209
+ req.user = null;
1210
+
1211
+ // Remove passport session field if it exists
1212
+ if (req.session && req.session.passport) {
1213
+ delete req.session.passport;
1214
+ }
1215
+
1216
+ // Passport v0.6+ expects async logout
1217
+ if (typeof callback === "function") {
1218
+ return callback(null);
1219
+ }
1220
+
1221
+ return Promise.resolve();
1222
+ };
1202
1223
  }
1203
1224
 
1204
1225
  _enhanceResponse(req, res) {
@@ -1477,6 +1498,54 @@ ${cyan} (req, res, next) => {
1477
1498
  return res.status(500).error(msg);
1478
1499
  };
1479
1500
 
1501
+ res.cookie = (name, value, options = {}) => {
1502
+ const opts = {
1503
+ path: '/',
1504
+ httpOnly: true,
1505
+ secure: req.secure || false,
1506
+ sameSite: 'lax',
1507
+ maxAge: null,
1508
+ expires: null,
1509
+ ...options
1510
+ };
1511
+
1512
+ let cookie = `${name}=${encodeURIComponent(value)}`;
1513
+
1514
+ if (opts.maxAge) cookie += `; Max-Age=${Math.floor(opts.maxAge / 1000)}`;
1515
+ if (opts.expires) cookie += `; Expires=${opts.expires.toUTCString()}`;
1516
+ cookie += `; Path=${opts.path}`;
1517
+ if (opts.domain) cookie += `; Domain=${opts.domain}`;
1518
+ if (opts.httpOnly) cookie += '; HttpOnly';
1519
+ if (opts.secure) cookie += '; Secure';
1520
+ if (opts.sameSite) cookie += `; SameSite=${opts.sameSite}`;
1521
+
1522
+ res.setHeader('Set-Cookie', cookie);
1523
+ return res;
1524
+ };
1525
+
1526
+ res.clearCookie = (name, options = {}) => {
1527
+ if (responseSent) return res;
1528
+
1529
+ const opts = {
1530
+ path: '/',
1531
+ httpOnly: true,
1532
+ secure: req.secure || false,
1533
+ sameSite: 'lax',
1534
+ ...options
1535
+ };
1536
+
1537
+ const cookieValue = `${name}=; Max-Age=0; Expires=${new Date(0).toUTCString()}; Path=${opts.path}`;
1538
+
1539
+ let header = cookieValue;
1540
+
1541
+ if (opts.httpOnly) header += '; HttpOnly';
1542
+ if (opts.secure) header += '; Secure';
1543
+ if (opts.sameSite && opts.sameSite !== 'none') header += `; SameSite=${opts.sameSite}`;
1544
+
1545
+ res.setHeader('Set-Cookie', header);
1546
+ return res;
1547
+ };
1548
+
1480
1549
  const originalEnd = res.end.bind(res);
1481
1550
 
1482
1551
  res.end = (...args) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lieko-express",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/eiwSrvt/lieko-express"