triva 0.0.1 → 0.3.0

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/lib/cache.js ADDED
@@ -0,0 +1,112 @@
1
+ /*!
2
+ * Triva - Cache Manager with Database Adapters
3
+ * Copyright (c) 2026 Kris Powers
4
+ * License MIT
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ import { createAdapter } from './db-adapters.js';
10
+
11
+ /* ---------------- Cache Manager ---------------- */
12
+ class CacheManager {
13
+ constructor() {
14
+ this.adapter = null;
15
+ this.config = {
16
+ enabled: true,
17
+ type: 'memory',
18
+ retention: 10 * 60 * 1000, // 10 minutes default
19
+ limit: 100000
20
+ };
21
+ }
22
+
23
+ async configure(options = {}) {
24
+ this.config = {
25
+ ...this.config,
26
+ enabled: options.cache_data !== false,
27
+ type: options.cache_type || options.type || 'memory',
28
+ retention: options.cache_retention || options.retention || this.config.retention,
29
+ limit: options.cache_limit || options.limit || this.config.limit
30
+ };
31
+
32
+ // Create adapter
33
+ try {
34
+ const adapterConfig = options.database || options.db || {};
35
+ this.adapter = createAdapter(this.config.type, adapterConfig);
36
+ await this.adapter.connect();
37
+ } catch (error) {
38
+ console.error('❌ Cache adapter error:', error.message);
39
+ throw error;
40
+ }
41
+
42
+ return this;
43
+ }
44
+
45
+ async get(key) {
46
+ if (!this.config.enabled || !this.adapter) return null;
47
+ return await this.adapter.get(key);
48
+ }
49
+
50
+ async set(key, value, ttl = null) {
51
+ if (!this.config.enabled || !this.adapter) return false;
52
+ const actualTtl = ttl !== null ? ttl : this.config.retention;
53
+ return await this.adapter.set(key, value, actualTtl);
54
+ }
55
+
56
+ async delete(key) {
57
+ if (!this.adapter) return false;
58
+ return await this.adapter.delete(key);
59
+ }
60
+
61
+ async has(key) {
62
+ if (!this.adapter) return false;
63
+ return await this.adapter.has(key);
64
+ }
65
+
66
+ async clear() {
67
+ if (!this.adapter) return 0;
68
+ return await this.adapter.clear();
69
+ }
70
+
71
+ async keys(pattern = null) {
72
+ if (!this.adapter) return [];
73
+ return await this.adapter.keys(pattern);
74
+ }
75
+
76
+ async size() {
77
+ if (!this.adapter) return 0;
78
+ const allKeys = await this.adapter.keys();
79
+ return allKeys.length;
80
+ }
81
+
82
+ async stats() {
83
+ const size = await this.size();
84
+
85
+ return {
86
+ size,
87
+ maxSize: this.config.limit,
88
+ active: size,
89
+ config: {
90
+ enabled: this.config.enabled,
91
+ type: this.config.type,
92
+ retention: this.config.retention,
93
+ limit: this.config.limit
94
+ }
95
+ };
96
+ }
97
+
98
+ shutdown() {
99
+ if (this.adapter) {
100
+ this.adapter.disconnect();
101
+ }
102
+ }
103
+ }
104
+
105
+ /* ---------------- Export Singleton ---------------- */
106
+ const cache = new CacheManager();
107
+
108
+ function configCache(options) {
109
+ return cache.configure(options);
110
+ }
111
+
112
+ export { cache, configCache, CacheManager };
@@ -0,0 +1,114 @@
1
+ /*!
2
+ * Triva - Cookie Parser
3
+ * Copyright (c) 2026 Kris Powers
4
+ * License MIT
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ /* ---------------- Cookie Parsing ---------------- */
10
+ function parseCookies(cookieHeader) {
11
+ if (!cookieHeader) return {};
12
+
13
+ const cookies = {};
14
+
15
+ cookieHeader.split(';').forEach(cookie => {
16
+ const parts = cookie.trim().split('=');
17
+ const key = parts[0];
18
+ const value = parts.slice(1).join('='); // Handle values with '=' in them
19
+
20
+ if (key) {
21
+ try {
22
+ // Decode URI components
23
+ cookies[key] = decodeURIComponent(value);
24
+ } catch (e) {
25
+ // If decode fails, use raw value
26
+ cookies[key] = value;
27
+ }
28
+ }
29
+ });
30
+
31
+ return cookies;
32
+ }
33
+
34
+ /* ---------------- Cookie Serialization ---------------- */
35
+ function serializeCookie(name, value, options = {}) {
36
+ let cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
37
+
38
+ if (options.maxAge) {
39
+ cookie += `; Max-Age=${options.maxAge}`;
40
+ }
41
+
42
+ if (options.expires) {
43
+ const expires = options.expires instanceof Date
44
+ ? options.expires.toUTCString()
45
+ : new Date(options.expires).toUTCString();
46
+ cookie += `; Expires=${expires}`;
47
+ }
48
+
49
+ if (options.domain) {
50
+ cookie += `; Domain=${options.domain}`;
51
+ }
52
+
53
+ if (options.path) {
54
+ cookie += `; Path=${options.path}`;
55
+ } else {
56
+ cookie += `; Path=/`;
57
+ }
58
+
59
+ if (options.secure) {
60
+ cookie += `; Secure`;
61
+ }
62
+
63
+ if (options.httpOnly) {
64
+ cookie += `; HttpOnly`;
65
+ }
66
+
67
+ if (options.sameSite) {
68
+ const sameSite = typeof options.sameSite === 'string'
69
+ ? options.sameSite
70
+ : (options.sameSite === true ? 'Strict' : 'Lax');
71
+ cookie += `; SameSite=${sameSite}`;
72
+ }
73
+
74
+ return cookie;
75
+ }
76
+
77
+ /* ---------------- Cookie Parser Middleware ---------------- */
78
+ function cookieParser(secret) {
79
+ return (req, res, next) => {
80
+ // Parse cookies from request
81
+ const cookieHeader = req.headers.cookie;
82
+ req.cookies = parseCookies(cookieHeader);
83
+
84
+ // Add cookie helper methods to response
85
+ res.cookie = (name, value, options = {}) => {
86
+ const cookie = serializeCookie(name, value, options);
87
+
88
+ // Handle multiple Set-Cookie headers
89
+ const existing = res.getHeader('Set-Cookie');
90
+ if (existing) {
91
+ const cookies = Array.isArray(existing) ? existing : [existing];
92
+ cookies.push(cookie);
93
+ res.setHeader('Set-Cookie', cookies);
94
+ } else {
95
+ res.setHeader('Set-Cookie', cookie);
96
+ }
97
+
98
+ return res;
99
+ };
100
+
101
+ res.clearCookie = (name, options = {}) => {
102
+ const clearOptions = {
103
+ ...options,
104
+ expires: new Date(0),
105
+ maxAge: -1
106
+ };
107
+ return res.cookie(name, '', clearOptions);
108
+ };
109
+
110
+ next();
111
+ };
112
+ }
113
+
114
+ export { parseCookies, serializeCookie, cookieParser };