mates-fullstack 1.0.0-beta.1

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.
Files changed (202) hide show
  1. package/README.md +311 -0
  2. package/dist/arctic-auth.d.ts +101 -0
  3. package/dist/arctic-auth.d.ts.map +1 -0
  4. package/dist/arctic-auth.js +538 -0
  5. package/dist/arctic-auth.js.map +1 -0
  6. package/dist/asset-manifest.d.ts +14 -0
  7. package/dist/asset-manifest.d.ts.map +1 -0
  8. package/dist/asset-manifest.js +102 -0
  9. package/dist/asset-manifest.js.map +1 -0
  10. package/dist/browser.d.ts +18 -0
  11. package/dist/browser.d.ts.map +1 -0
  12. package/dist/browser.js +25 -0
  13. package/dist/browser.js.map +1 -0
  14. package/dist/build-esbuild.d.ts +29 -0
  15. package/dist/build-esbuild.d.ts.map +1 -0
  16. package/dist/build-esbuild.js +699 -0
  17. package/dist/build-esbuild.js.map +1 -0
  18. package/dist/build-prod.d.ts +126 -0
  19. package/dist/build-prod.d.ts.map +1 -0
  20. package/dist/build-prod.js +1014 -0
  21. package/dist/build-prod.js.map +1 -0
  22. package/dist/cli-new.d.ts +14 -0
  23. package/dist/cli-new.d.ts.map +1 -0
  24. package/dist/cli-new.js +637 -0
  25. package/dist/cli-new.js.map +1 -0
  26. package/dist/client.d.ts +43 -0
  27. package/dist/client.d.ts.map +1 -0
  28. package/dist/client.js +130 -0
  29. package/dist/client.js.map +1 -0
  30. package/dist/cors.d.ts +16 -0
  31. package/dist/cors.d.ts.map +1 -0
  32. package/dist/cors.js +60 -0
  33. package/dist/cors.js.map +1 -0
  34. package/dist/ctx.d.ts +78 -0
  35. package/dist/ctx.d.ts.map +1 -0
  36. package/dist/ctx.js +280 -0
  37. package/dist/ctx.js.map +1 -0
  38. package/dist/dev-watcher.d.ts +23 -0
  39. package/dist/dev-watcher.d.ts.map +1 -0
  40. package/dist/dev-watcher.js +136 -0
  41. package/dist/dev-watcher.js.map +1 -0
  42. package/dist/docs-generator.d.ts +69 -0
  43. package/dist/docs-generator.d.ts.map +1 -0
  44. package/dist/docs-generator.js +557 -0
  45. package/dist/docs-generator.js.map +1 -0
  46. package/dist/docs-page.d.ts +20 -0
  47. package/dist/docs-page.d.ts.map +1 -0
  48. package/dist/docs-page.js +1152 -0
  49. package/dist/docs-page.js.map +1 -0
  50. package/dist/download.d.ts +78 -0
  51. package/dist/download.d.ts.map +1 -0
  52. package/dist/download.js +202 -0
  53. package/dist/download.js.map +1 -0
  54. package/dist/env-loader.d.ts +76 -0
  55. package/dist/env-loader.d.ts.map +1 -0
  56. package/dist/env-loader.js +213 -0
  57. package/dist/env-loader.js.map +1 -0
  58. package/dist/errors.d.ts +146 -0
  59. package/dist/errors.d.ts.map +1 -0
  60. package/dist/errors.js +386 -0
  61. package/dist/errors.js.map +1 -0
  62. package/dist/head.d.ts +31 -0
  63. package/dist/head.d.ts.map +1 -0
  64. package/dist/head.js +245 -0
  65. package/dist/head.js.map +1 -0
  66. package/dist/index.d.ts +30 -0
  67. package/dist/index.d.ts.map +1 -0
  68. package/dist/index.js +30 -0
  69. package/dist/index.js.map +1 -0
  70. package/dist/internal-prefixes.d.ts +16 -0
  71. package/dist/internal-prefixes.d.ts.map +1 -0
  72. package/dist/internal-prefixes.js +16 -0
  73. package/dist/internal-prefixes.js.map +1 -0
  74. package/dist/internal.d.ts +25 -0
  75. package/dist/internal.d.ts.map +1 -0
  76. package/dist/internal.js +25 -0
  77. package/dist/internal.js.map +1 -0
  78. package/dist/jwt.d.ts +166 -0
  79. package/dist/jwt.d.ts.map +1 -0
  80. package/dist/jwt.js +261 -0
  81. package/dist/jwt.js.map +1 -0
  82. package/dist/log.d.ts +44 -0
  83. package/dist/log.d.ts.map +1 -0
  84. package/dist/log.js +66 -0
  85. package/dist/log.js.map +1 -0
  86. package/dist/logger.d.ts +76 -0
  87. package/dist/logger.d.ts.map +1 -0
  88. package/dist/logger.js +138 -0
  89. package/dist/logger.js.map +1 -0
  90. package/dist/main-runner.d.ts +59 -0
  91. package/dist/main-runner.d.ts.map +1 -0
  92. package/dist/main-runner.js +157 -0
  93. package/dist/main-runner.js.map +1 -0
  94. package/dist/mates-auth.d.ts +82 -0
  95. package/dist/mates-auth.d.ts.map +1 -0
  96. package/dist/mates-auth.js +323 -0
  97. package/dist/mates-auth.js.map +1 -0
  98. package/dist/middleware.d.ts +30 -0
  99. package/dist/middleware.d.ts.map +1 -0
  100. package/dist/middleware.js +67 -0
  101. package/dist/middleware.js.map +1 -0
  102. package/dist/project-resolver.d.ts +102 -0
  103. package/dist/project-resolver.d.ts.map +1 -0
  104. package/dist/project-resolver.js +271 -0
  105. package/dist/project-resolver.js.map +1 -0
  106. package/dist/rate-limit.d.ts +37 -0
  107. package/dist/rate-limit.d.ts.map +1 -0
  108. package/dist/rate-limit.js +109 -0
  109. package/dist/rate-limit.js.map +1 -0
  110. package/dist/redirect.d.ts +84 -0
  111. package/dist/redirect.d.ts.map +1 -0
  112. package/dist/redirect.js +105 -0
  113. package/dist/redirect.js.map +1 -0
  114. package/dist/renderer.d.ts +91 -0
  115. package/dist/renderer.d.ts.map +1 -0
  116. package/dist/renderer.js +630 -0
  117. package/dist/renderer.js.map +1 -0
  118. package/dist/request-logger.d.ts +12 -0
  119. package/dist/request-logger.d.ts.map +1 -0
  120. package/dist/request-logger.js +55 -0
  121. package/dist/request-logger.js.map +1 -0
  122. package/dist/rest.d.ts +25 -0
  123. package/dist/rest.d.ts.map +1 -0
  124. package/dist/rest.js +93 -0
  125. package/dist/rest.js.map +1 -0
  126. package/dist/router.d.ts +71 -0
  127. package/dist/router.d.ts.map +1 -0
  128. package/dist/router.js +222 -0
  129. package/dist/router.js.map +1 -0
  130. package/dist/rpc-registry.d.ts +84 -0
  131. package/dist/rpc-registry.d.ts.map +1 -0
  132. package/dist/rpc-registry.js +271 -0
  133. package/dist/rpc-registry.js.map +1 -0
  134. package/dist/rpc-runner.d.ts +82 -0
  135. package/dist/rpc-runner.d.ts.map +1 -0
  136. package/dist/rpc-runner.js +564 -0
  137. package/dist/rpc-runner.js.map +1 -0
  138. package/dist/sanitize.d.ts +61 -0
  139. package/dist/sanitize.d.ts.map +1 -0
  140. package/dist/sanitize.js +193 -0
  141. package/dist/sanitize.js.map +1 -0
  142. package/dist/security-headers.d.ts +114 -0
  143. package/dist/security-headers.d.ts.map +1 -0
  144. package/dist/security-headers.js +121 -0
  145. package/dist/security-headers.js.map +1 -0
  146. package/dist/server-fn.d.ts +323 -0
  147. package/dist/server-fn.d.ts.map +1 -0
  148. package/dist/server-fn.js +373 -0
  149. package/dist/server-fn.js.map +1 -0
  150. package/dist/server-public.d.ts +13 -0
  151. package/dist/server-public.d.ts.map +1 -0
  152. package/dist/server-public.js +12 -0
  153. package/dist/server-public.js.map +1 -0
  154. package/dist/server-timeout.d.ts +38 -0
  155. package/dist/server-timeout.d.ts.map +1 -0
  156. package/dist/server-timeout.js +46 -0
  157. package/dist/server-timeout.js.map +1 -0
  158. package/dist/server.d.ts +100 -0
  159. package/dist/server.d.ts.map +1 -0
  160. package/dist/server.js +1218 -0
  161. package/dist/server.js.map +1 -0
  162. package/dist/socket-router.d.ts +153 -0
  163. package/dist/socket-router.d.ts.map +1 -0
  164. package/dist/socket-router.js +612 -0
  165. package/dist/socket-router.js.map +1 -0
  166. package/dist/sso.d.ts +90 -0
  167. package/dist/sso.d.ts.map +1 -0
  168. package/dist/sso.js +261 -0
  169. package/dist/sso.js.map +1 -0
  170. package/dist/ssr-context.d.ts +49 -0
  171. package/dist/ssr-context.d.ts.map +1 -0
  172. package/dist/ssr-context.js +85 -0
  173. package/dist/ssr-context.js.map +1 -0
  174. package/dist/ssr-globals.d.ts +32 -0
  175. package/dist/ssr-globals.d.ts.map +1 -0
  176. package/dist/ssr-globals.js +1010 -0
  177. package/dist/ssr-globals.js.map +1 -0
  178. package/dist/ssr-template.d.ts +73 -0
  179. package/dist/ssr-template.d.ts.map +1 -0
  180. package/dist/ssr-template.js +507 -0
  181. package/dist/ssr-template.js.map +1 -0
  182. package/dist/stack-mapper.d.ts +25 -0
  183. package/dist/stack-mapper.d.ts.map +1 -0
  184. package/dist/stack-mapper.js +139 -0
  185. package/dist/stack-mapper.js.map +1 -0
  186. package/dist/stream.d.ts +89 -0
  187. package/dist/stream.d.ts.map +1 -0
  188. package/dist/stream.js +299 -0
  189. package/dist/stream.js.map +1 -0
  190. package/dist/upload.d.ts +69 -0
  191. package/dist/upload.d.ts.map +1 -0
  192. package/dist/upload.js +110 -0
  193. package/dist/upload.js.map +1 -0
  194. package/dist/validate.d.ts +58 -0
  195. package/dist/validate.d.ts.map +1 -0
  196. package/dist/validate.js +89 -0
  197. package/dist/validate.js.map +1 -0
  198. package/dist/verify-package.d.ts +3 -0
  199. package/dist/verify-package.d.ts.map +1 -0
  200. package/dist/verify-package.js +128 -0
  201. package/dist/verify-package.js.map +1 -0
  202. package/package.json +79 -0
package/dist/jwt.js ADDED
@@ -0,0 +1,261 @@
1
+ /**
2
+ * mates-fullstack — jwt.ts
3
+ *
4
+ * Zero-dependency JWT implementation using Node.js built-in crypto.
5
+ * Supports HS256 (HMAC-SHA256) — the right choice for tokens you
6
+ * both sign and verify yourself.
7
+ *
8
+ * For asymmetric algorithms (RS256, ES256) or third-party JWKS verification
9
+ * (Google, Auth0, GitHub), use the `jose` package instead.
10
+ *
11
+ * Usage in server/main.ts or server/helpers/auth.ts:
12
+ *
13
+ * import { jwt } from "mates-fullstack";
14
+ *
15
+ * const tokens = jwt(process.env.JWT_SECRET!);
16
+ *
17
+ * // Sign
18
+ * const token = await tokens.sign({ sub: "user_123", role: "admin" });
19
+ *
20
+ * // Verify
21
+ * const payload = await tokens.verify(token);
22
+ * if (!payload) throw new AuthError("Invalid token");
23
+ *
24
+ * // Decode without verifying (e.g. to read sub before re-validating)
25
+ * const claims = jwt.decode(token);
26
+ *
27
+ * API:
28
+ * jwt(secret, options?) → bound instance for sign/verify/refresh
29
+ * jwt.decode(token) → decode payload without verifying
30
+ * jwt.isExpired(token) → check expiry without verifying signature
31
+ *
32
+ * Bound instance:
33
+ * .sign(payload, options?) → Promise<string>
34
+ * .verify(token) → Promise<JwtPayload | null>
35
+ * .refresh(token, options?) → Promise<string | null> (rotate with same claims)
36
+ * .decode(token) → JwtPayload | null (no signature check)
37
+ */
38
+ import crypto from "node:crypto";
39
+ // ─── Static helpers ───────────────────────────────────────────────────────────
40
+ /**
41
+ * Decode a JWT without verifying the signature.
42
+ * Safe to call on untrusted tokens — never throws.
43
+ */
44
+ function decodeToken(token) {
45
+ try {
46
+ const parts = token.split(".");
47
+ if (parts.length !== 3)
48
+ return null;
49
+ const payloadB64 = parts[1]
50
+ .replace(/-/g, "+")
51
+ .replace(/_/g, "/");
52
+ const json = Buffer.from(payloadB64, "base64").toString("utf-8");
53
+ return JSON.parse(json);
54
+ }
55
+ catch {
56
+ return null;
57
+ }
58
+ }
59
+ /**
60
+ * Check if a token is expired without verifying the signature.
61
+ * Returns true if expired or malformed.
62
+ */
63
+ function isTokenExpired(token, clockSkewSeconds = 0) {
64
+ const payload = decodeToken(token);
65
+ if (!payload)
66
+ return true;
67
+ if (!payload.exp)
68
+ return false; // no expiry = never expires
69
+ return payload.exp < Math.floor(Date.now() / 1000) - clockSkewSeconds;
70
+ }
71
+ // ─── jwt() factory ────────────────────────────────────────────────────────────
72
+ /**
73
+ * Create a bound JWT instance for signing and verifying tokens.
74
+ *
75
+ * @param secret - The secret key string. Use a long random string in production.
76
+ * Minimum 32 characters recommended.
77
+ * @param defaults - Default options applied to all sign() calls.
78
+ *
79
+ * @example
80
+ * const tokens = jwt(process.env.JWT_SECRET!);
81
+ * const tokens = jwt(process.env.JWT_SECRET!, { expiresIn: "7d" });
82
+ */
83
+ export function jwt(secret, defaults = {}) {
84
+ if (!secret || secret.length < 8) {
85
+ throw new Error("[mates-fullstack] jwt: secret must be at least 8 characters. " +
86
+ "Use a long random string in production (32+ characters recommended).");
87
+ }
88
+ const secretKey = Buffer.from(secret, "utf-8");
89
+ // ── Internal sign ──────────────────────────────────────────────────────────
90
+ function _sign(payload, options = {}) {
91
+ const merged = { ...defaults, ...options };
92
+ const now = Math.floor(Date.now() / 1000);
93
+ // Build claims — strip reserved fields from user payload to avoid conflicts
94
+ const { iat: _iat, exp: _exp, nbf: _nbf, iss: _iss, aud: _aud, jti: _jti, ...userClaims } = payload;
95
+ const claims = {
96
+ ...userClaims,
97
+ iat: now,
98
+ };
99
+ // Expiry — omit exp claim entirely when expiresIn is false
100
+ if (merged.expiresIn !== false) {
101
+ const expiresIn = merged.expiresIn ?? "1h";
102
+ claims.exp = now + _parseDuration(expiresIn);
103
+ }
104
+ // Not-before
105
+ if (merged.notBefore !== undefined) {
106
+ claims.nbf = now + _parseDuration(merged.notBefore);
107
+ }
108
+ // Issuer / audience
109
+ if (merged.issuer)
110
+ claims.iss = merged.issuer;
111
+ if (merged.audience)
112
+ claims.aud = merged.audience;
113
+ // JWT ID
114
+ if (merged.includeJti) {
115
+ claims.jti = crypto.randomUUID();
116
+ }
117
+ const header = _base64url(JSON.stringify({ alg: "HS256", typ: "JWT" }));
118
+ const body = _base64url(JSON.stringify(claims));
119
+ const signingInput = `${header}.${body}`;
120
+ const signature = crypto
121
+ .createHmac("sha256", secretKey)
122
+ .update(signingInput)
123
+ .digest("base64url");
124
+ return `${signingInput}.${signature}`;
125
+ }
126
+ // ── Internal verify ────────────────────────────────────────────────────────
127
+ function _verify(token, options = {}) {
128
+ try {
129
+ const parts = token.split(".");
130
+ if (parts.length !== 3)
131
+ return null;
132
+ const [header, payload, signature] = parts;
133
+ // Recompute expected signature
134
+ const expected = crypto
135
+ .createHmac("sha256", secretKey)
136
+ .update(`${header}.${payload}`)
137
+ .digest("base64url");
138
+ // Timing-safe comparison — prevents timing-based attacks
139
+ const sigBuf = Buffer.from(signature);
140
+ const expBuf = Buffer.from(expected);
141
+ if (sigBuf.length !== expBuf.length)
142
+ return null;
143
+ if (!crypto.timingSafeEqual(sigBuf, expBuf))
144
+ return null;
145
+ // Decode payload
146
+ const claims = JSON.parse(Buffer.from(payload.replace(/-/g, "+").replace(/_/g, "/"), "base64").toString("utf-8"));
147
+ const now = Math.floor(Date.now() / 1000);
148
+ const skew = options.clockSkew ?? 0;
149
+ // Check expiry
150
+ if (claims.exp !== undefined && claims.exp < now - skew) {
151
+ return null; // expired
152
+ }
153
+ // Check not-before
154
+ if (claims.nbf !== undefined && claims.nbf > now + skew) {
155
+ return null; // not yet valid
156
+ }
157
+ // Check issuer
158
+ if (options.issuer && claims.iss !== options.issuer) {
159
+ return null;
160
+ }
161
+ // Check audience
162
+ if (options.audience) {
163
+ const aud = Array.isArray(claims.aud)
164
+ ? claims.aud
165
+ : claims.aud ? [claims.aud] : [];
166
+ if (!aud.includes(options.audience))
167
+ return null;
168
+ }
169
+ return claims;
170
+ }
171
+ catch {
172
+ return null;
173
+ }
174
+ }
175
+ // ── Public instance ────────────────────────────────────────────────────────
176
+ return {
177
+ async sign(payload, options) {
178
+ return _sign(payload, options);
179
+ },
180
+ async verify(token, options) {
181
+ return _verify(token, options);
182
+ },
183
+ async refresh(token, options) {
184
+ const payload = _verify(token, options);
185
+ if (!payload)
186
+ return null;
187
+ // Strip timing claims — sign() will set fresh ones
188
+ const { iat: _iat, exp: _exp, nbf: _nbf, jti: _jti, ...claims } = payload;
189
+ return _sign(claims, options);
190
+ },
191
+ decode(token) {
192
+ return decodeToken(token);
193
+ },
194
+ };
195
+ }
196
+ // ─── Static methods on jwt ────────────────────────────────────────────────────
197
+ /**
198
+ * Decode a JWT without verifying the signature.
199
+ * Static — no secret needed.
200
+ *
201
+ * @example
202
+ * const claims = jwt.decode(token);
203
+ * console.log(claims?.sub);
204
+ */
205
+ jwt.decode = decodeToken;
206
+ /**
207
+ * Check if a token is expired without verifying the signature.
208
+ * Static — no secret needed.
209
+ *
210
+ * @example
211
+ * if (jwt.isExpired(token)) { ... }
212
+ * if (jwt.isExpired(token, 30)) { ... } // 30 second clock skew tolerance
213
+ */
214
+ jwt.isExpired = isTokenExpired;
215
+ // ─── Duration parser ──────────────────────────────────────────────────────────
216
+ /**
217
+ * Parse a duration string or number into seconds.
218
+ *
219
+ * Supported formats:
220
+ * 30 → 30 seconds
221
+ * "30" → 30 seconds
222
+ * "30s" → 30 seconds
223
+ * "15m" → 900 seconds
224
+ * "1h" → 3600 seconds
225
+ * "7d" → 604800 seconds
226
+ * "2w" → 1209600 seconds
227
+ *
228
+ * Throws on unrecognized formats.
229
+ */
230
+ function _parseDuration(value) {
231
+ if (typeof value === "number")
232
+ return value;
233
+ const str = String(value).trim();
234
+ // Pure number string
235
+ if (/^\d+$/.test(str))
236
+ return parseInt(str, 10);
237
+ const match = str.match(/^(\d+(?:\.\d+)?)\s*(s|m|h|d|w)$/i);
238
+ if (!match) {
239
+ throw new Error(`[mates-fullstack] jwt: invalid duration "${value}". ` +
240
+ `Use a number (seconds) or a string like "15m", "1h", "7d", "2w".`);
241
+ }
242
+ const amount = parseFloat(match[1]);
243
+ const unit = match[2].toLowerCase();
244
+ const multipliers = {
245
+ s: 1,
246
+ m: 60,
247
+ h: 3600,
248
+ d: 86400,
249
+ w: 604800,
250
+ };
251
+ return Math.floor(amount * multipliers[unit]);
252
+ }
253
+ // ─── base64url helper ─────────────────────────────────────────────────────────
254
+ function _base64url(str) {
255
+ return Buffer.from(str, "utf-8")
256
+ .toString("base64")
257
+ .replace(/\+/g, "-")
258
+ .replace(/\//g, "_")
259
+ .replace(/=/g, "");
260
+ }
261
+ //# sourceMappingURL=jwt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt.js","sourceRoot":"","sources":["../src/jwt.ts"],"names":[],"mappings":"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"}
package/dist/log.d.ts ADDED
@@ -0,0 +1,44 @@
1
+ /**
2
+ * mates-fullstack — log.ts
3
+ *
4
+ * Minimal internal logger for the mates-fullstack server process.
5
+ *
6
+ * Rules:
7
+ * - dev mode → messages printed to console (devex)
8
+ * - prod mode → complete silence from the framework
9
+ *
10
+ * This module only runs in Node.js (server-side). It reads process.env.NODE_ENV
11
+ * which the CLI sets before anything else imports.
12
+ *
13
+ * For client + server isomorphic isDev() use `isDev` from "mates" directly.
14
+ * It is also re-exported from "mates-fullstack" for convenience.
15
+ *
16
+ * User code controls production logging via onResponse / onResponse hooks.
17
+ */
18
+ /**
19
+ * Returns true when running in development mode.
20
+ *
21
+ * Server-side (Node.js): reads process.env.NODE_ENV set by the CLI.
22
+ *
23
+ * For isomorphic usage (browser + server), import isDev from "mates" instead —
24
+ * it checks import.meta.env.NODE_ENV in the browser (statically replaced at
25
+ * build time by esbuild) and process.env.NODE_ENV on the server.
26
+ */
27
+ export declare function isDev(): boolean;
28
+ /** Log an informational message. Dev only. */
29
+ export declare function devLog(msg: string, ...args: unknown[]): void;
30
+ /** Log a warning. Dev only. */
31
+ export declare function devWarn(msg: string, ...args: unknown[]): void;
32
+ /** Log an error. Dev only. */
33
+ export declare function devError(msg: string, ...args: unknown[]): void;
34
+ /**
35
+ * Log a fatal error that is about to terminate the process.
36
+ * Always printed regardless of NODE_ENV — the process is dying anyway.
37
+ */
38
+ export declare function fatalError(msg: string, ...args: unknown[]): void;
39
+ /**
40
+ * Log a startup message (port, paths, etc.).
41
+ * Dev only — production processes should not emit startup noise.
42
+ */
43
+ export declare function startupLog(msg: string): void;
44
+ //# sourceMappingURL=log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH;;;;;;;;GAQG;AACH,wBAAgB,KAAK,IAAI,OAAO,CAE/B;AAID,8CAA8C;AAC9C,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAG5D;AAED,+BAA+B;AAC/B,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAG7D;AAED,8BAA8B;AAC9B,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAG9D;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAEhE;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAG5C"}
package/dist/log.js ADDED
@@ -0,0 +1,66 @@
1
+ /**
2
+ * mates-fullstack — log.ts
3
+ *
4
+ * Minimal internal logger for the mates-fullstack server process.
5
+ *
6
+ * Rules:
7
+ * - dev mode → messages printed to console (devex)
8
+ * - prod mode → complete silence from the framework
9
+ *
10
+ * This module only runs in Node.js (server-side). It reads process.env.NODE_ENV
11
+ * which the CLI sets before anything else imports.
12
+ *
13
+ * For client + server isomorphic isDev() use `isDev` from "mates" directly.
14
+ * It is also re-exported from "mates-fullstack" for convenience.
15
+ *
16
+ * User code controls production logging via onResponse / onResponse hooks.
17
+ */
18
+ // ─── isDev ────────────────────────────────────────────────────────────────────
19
+ /**
20
+ * Returns true when running in development mode.
21
+ *
22
+ * Server-side (Node.js): reads process.env.NODE_ENV set by the CLI.
23
+ *
24
+ * For isomorphic usage (browser + server), import isDev from "mates" instead —
25
+ * it checks import.meta.env.NODE_ENV in the browser (statically replaced at
26
+ * build time by esbuild) and process.env.NODE_ENV on the server.
27
+ */
28
+ export function isDev() {
29
+ return process.env.NODE_ENV !== "production";
30
+ }
31
+ // ─── Internal logging helpers ─────────────────────────────────────────────────
32
+ /** Log an informational message. Dev only. */
33
+ export function devLog(msg, ...args) {
34
+ if (!isDev())
35
+ return;
36
+ console.log(`[mates] ${msg}`, ...args);
37
+ }
38
+ /** Log a warning. Dev only. */
39
+ export function devWarn(msg, ...args) {
40
+ if (!isDev())
41
+ return;
42
+ console.warn(`[mates] ${msg}`, ...args);
43
+ }
44
+ /** Log an error. Dev only. */
45
+ export function devError(msg, ...args) {
46
+ if (!isDev())
47
+ return;
48
+ console.error(`[mates] ${msg}`, ...args);
49
+ }
50
+ /**
51
+ * Log a fatal error that is about to terminate the process.
52
+ * Always printed regardless of NODE_ENV — the process is dying anyway.
53
+ */
54
+ export function fatalError(msg, ...args) {
55
+ console.error(`[mates] ${msg}`, ...args);
56
+ }
57
+ /**
58
+ * Log a startup message (port, paths, etc.).
59
+ * Dev only — production processes should not emit startup noise.
60
+ */
61
+ export function startupLog(msg) {
62
+ if (!isDev())
63
+ return;
64
+ console.log(`[mates] ${msg}`);
65
+ }
66
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,iFAAiF;AAEjF;;;;;;;;GAQG;AACH,MAAM,UAAU,KAAK;IACnB,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC;AAC/C,CAAC;AAED,iFAAiF;AAEjF,8CAA8C;AAC9C,MAAM,UAAU,MAAM,CAAC,GAAW,EAAE,GAAG,IAAe;IACpD,IAAI,CAAC,KAAK,EAAE;QAAE,OAAO;IACrB,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;AACzC,CAAC;AAED,+BAA+B;AAC/B,MAAM,UAAU,OAAO,CAAC,GAAW,EAAE,GAAG,IAAe;IACrD,IAAI,CAAC,KAAK,EAAE;QAAE,OAAO;IACrB,OAAO,CAAC,IAAI,CAAC,WAAW,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;AAC1C,CAAC;AAED,8BAA8B;AAC9B,MAAM,UAAU,QAAQ,CAAC,GAAW,EAAE,GAAG,IAAe;IACtD,IAAI,CAAC,KAAK,EAAE;QAAE,OAAO;IACrB,OAAO,CAAC,KAAK,CAAC,WAAW,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,GAAG,IAAe;IACxD,OAAO,CAAC,KAAK,CAAC,WAAW,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,IAAI,CAAC,KAAK,EAAE;QAAE,OAAO;IACrB,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,EAAE,CAAC,CAAC;AAChC,CAAC"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * mates-ssr — logger.ts
3
+ *
4
+ * Structured logger for production deployments.
5
+ *
6
+ * In development: pretty-prints with colors and timestamps.
7
+ * In production: outputs newline-delimited JSON (NDJSON) for
8
+ * CloudWatch, Datadog, Loki, and other log aggregators.
9
+ *
10
+ * Log levels: debug < info < warn < error
11
+ * Default level: "info" in production, "debug" in development.
12
+ *
13
+ * Request IDs: every log within a request carries the same request_id
14
+ * for tracing a request through the logs.
15
+ *
16
+ * Usage:
17
+ * import { logger } from "mates-ssr";
18
+ * logger.info("User logged in", { userId: auth.sub });
19
+ * logger.error("DB query failed", { query, error: err.message });
20
+ *
21
+ * Request-scoped (carries request_id automatically):
22
+ * const log = logger.withRequest(req);
23
+ * log.info("Processing upload", { filename });
24
+ */
25
+ export type LogLevel = "debug" | "info" | "warn" | "error";
26
+ export type LogFormat = "pretty" | "json";
27
+ export interface LogEntry {
28
+ ts: string;
29
+ level: LogLevel;
30
+ msg: string;
31
+ request_id?: string;
32
+ [key: string]: unknown;
33
+ }
34
+ export interface LoggerConfig {
35
+ /**
36
+ * Minimum log level to output.
37
+ * @default "debug" in dev, "info" in production
38
+ */
39
+ level?: LogLevel;
40
+ /**
41
+ * Output format.
42
+ * @default "pretty" in dev, "json" in production
43
+ */
44
+ format?: LogFormat;
45
+ /**
46
+ * Service name — included in every log entry (useful in multi-service setups).
47
+ */
48
+ service?: string;
49
+ }
50
+ export declare function configureLogger(config: LoggerConfig): void;
51
+ export interface Logger {
52
+ debug(msg: string, fields?: Record<string, unknown>): void;
53
+ info(msg: string, fields?: Record<string, unknown>): void;
54
+ warn(msg: string, fields?: Record<string, unknown>): void;
55
+ error(msg: string, fields?: Record<string, unknown>): void;
56
+ /** Create a child logger that includes request_id on every entry */
57
+ withRequest(requestId: string): Logger;
58
+ /** Create a child logger with additional default fields */
59
+ withFields(fields: Record<string, unknown>): Logger;
60
+ }
61
+ /** The global logger instance. Use this throughout your app. */
62
+ export declare const logger: Logger;
63
+ /**
64
+ * Generate a short random request ID for tracing.
65
+ * 8 hex chars — enough to correlate logs within a request, low collision risk.
66
+ */
67
+ export declare function generateRequestId(): string;
68
+ /**
69
+ * Log an incoming request. Call at the start of request handling.
70
+ */
71
+ export declare function logRequest(req: Request, requestId: string, clientIp: string): void;
72
+ /**
73
+ * Log an outgoing response. Call just before sending.
74
+ */
75
+ export declare function logResponse(req: Request, res: Response, requestId: string, startTime: number): void;
76
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAC3D,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE1C,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,QAAQ,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA2BD,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAI1D;AAsDD,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC3D,IAAI,CAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC3D,IAAI,CAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC3D,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC3D,oEAAoE;IACpE,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IACvC,2DAA2D;IAC3D,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC;CACrD;AAgBD,gEAAgE;AAChE,eAAO,MAAM,MAAM,QAAe,CAAC;AAInC;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAI1C;AAED;;GAEG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,OAAO,EACZ,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,IAAI,CAQN;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,IAAI,CAaN"}
package/dist/logger.js ADDED
@@ -0,0 +1,138 @@
1
+ /**
2
+ * mates-ssr — logger.ts
3
+ *
4
+ * Structured logger for production deployments.
5
+ *
6
+ * In development: pretty-prints with colors and timestamps.
7
+ * In production: outputs newline-delimited JSON (NDJSON) for
8
+ * CloudWatch, Datadog, Loki, and other log aggregators.
9
+ *
10
+ * Log levels: debug < info < warn < error
11
+ * Default level: "info" in production, "debug" in development.
12
+ *
13
+ * Request IDs: every log within a request carries the same request_id
14
+ * for tracing a request through the logs.
15
+ *
16
+ * Usage:
17
+ * import { logger } from "mates-ssr";
18
+ * logger.info("User logged in", { userId: auth.sub });
19
+ * logger.error("DB query failed", { query, error: err.message });
20
+ *
21
+ * Request-scoped (carries request_id automatically):
22
+ * const log = logger.withRequest(req);
23
+ * log.info("Processing upload", { filename });
24
+ */
25
+ const LEVELS = {
26
+ debug: 0,
27
+ info: 1,
28
+ warn: 2,
29
+ error: 3,
30
+ };
31
+ const LEVEL_COLORS = {
32
+ debug: "\x1b[90m", // gray
33
+ info: "\x1b[36m", // cyan
34
+ warn: "\x1b[33m", // yellow
35
+ error: "\x1b[31m", // red
36
+ };
37
+ const RESET = "\x1b[0m";
38
+ const BOLD = "\x1b[1m";
39
+ const isProd = process.env.NODE_ENV === "production";
40
+ // ─── Module-level config ──────────────────────────────────────────────────────
41
+ let _minLevel = isProd ? "info" : "debug";
42
+ let _format = isProd ? "json" : "pretty";
43
+ let _service = "mates-ssr";
44
+ export function configureLogger(config) {
45
+ if (config.level)
46
+ _minLevel = config.level;
47
+ if (config.format)
48
+ _format = config.format;
49
+ if (config.service)
50
+ _service = config.service;
51
+ }
52
+ // ─── Core write ───────────────────────────────────────────────────────────────
53
+ function write(level, msg, fields, requestId) {
54
+ if (LEVELS[level] < LEVELS[_minLevel])
55
+ return;
56
+ const entry = {
57
+ ts: new Date().toISOString(),
58
+ level,
59
+ msg,
60
+ ...(requestId && { request_id: requestId }),
61
+ ...(_service && { service: _service }),
62
+ ...(fields ?? {}),
63
+ };
64
+ if (_format === "json") {
65
+ // NDJSON — one JSON object per line
66
+ // CloudWatch, Datadog, Loki all parse this automatically
67
+ process.stdout.write(JSON.stringify(entry) + "\n");
68
+ return;
69
+ }
70
+ // Pretty format for development
71
+ const color = LEVEL_COLORS[level];
72
+ const ts = entry.ts.replace("T", " ").replace("Z", "").slice(0, 23);
73
+ const lvl = level.toUpperCase().padEnd(5);
74
+ const rid = requestId ? ` \x1b[90m[${requestId.slice(0, 8)}]\x1b[0m` : "";
75
+ // Format extra fields
76
+ const extra = fields && Object.keys(fields).length > 0
77
+ ? " " + Object.entries(fields)
78
+ .map(([k, v]) => `\x1b[90m${k}=\x1b[0m${JSON.stringify(v)}`)
79
+ .join(" ")
80
+ : "";
81
+ if (level === "error") {
82
+ process.stderr.write(` ${color}${BOLD}${lvl}${RESET} \x1b[90m${ts}${RESET}${rid} ${msg}${extra}\n`);
83
+ }
84
+ else {
85
+ process.stdout.write(` ${color}${lvl}${RESET} \x1b[90m${ts}${RESET}${rid} ${msg}${extra}\n`);
86
+ }
87
+ }
88
+ function makeLogger(requestId, defaultFields) {
89
+ return {
90
+ debug: (msg, fields) => write("debug", msg, { ...defaultFields, ...fields }, requestId),
91
+ info: (msg, fields) => write("info", msg, { ...defaultFields, ...fields }, requestId),
92
+ warn: (msg, fields) => write("warn", msg, { ...defaultFields, ...fields }, requestId),
93
+ error: (msg, fields) => write("error", msg, { ...defaultFields, ...fields }, requestId),
94
+ withRequest: (rid) => makeLogger(rid, defaultFields),
95
+ withFields: (fields) => makeLogger(requestId, { ...defaultFields, ...fields }),
96
+ };
97
+ }
98
+ /** The global logger instance. Use this throughout your app. */
99
+ export const logger = makeLogger();
100
+ // ─── Request logging middleware ───────────────────────────────────────────────
101
+ /**
102
+ * Generate a short random request ID for tracing.
103
+ * 8 hex chars — enough to correlate logs within a request, low collision risk.
104
+ */
105
+ export function generateRequestId() {
106
+ const bytes = new Uint8Array(8);
107
+ crypto.getRandomValues(bytes);
108
+ return Array.from(bytes).map(b => b.toString(16).padStart(2, "0")).join("").slice(0, 12);
109
+ }
110
+ /**
111
+ * Log an incoming request. Call at the start of request handling.
112
+ */
113
+ export function logRequest(req, requestId, clientIp) {
114
+ const url = new URL(req.url);
115
+ logger.withRequest(requestId).info("→ request", {
116
+ method: req.method,
117
+ path: url.pathname,
118
+ ip: clientIp,
119
+ ua: req.headers.get("user-agent")?.slice(0, 80) ?? undefined,
120
+ });
121
+ }
122
+ /**
123
+ * Log an outgoing response. Call just before sending.
124
+ */
125
+ export function logResponse(req, res, requestId, startTime) {
126
+ const url = new URL(req.url);
127
+ const ms = (performance.now() - startTime).toFixed(1);
128
+ const lvl = res.status >= 500 ? "error"
129
+ : res.status >= 400 ? "warn"
130
+ : "info";
131
+ logger.withRequest(requestId)[lvl]("← response", {
132
+ method: req.method,
133
+ path: url.pathname,
134
+ status: res.status,
135
+ ms: Number(ms),
136
+ });
137
+ }
138
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AA8BH,MAAM,MAAM,GAA6B;IACvC,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;CACT,CAAC;AAEF,MAAM,YAAY,GAA6B;IAC7C,KAAK,EAAE,UAAU,EAAE,OAAO;IAC1B,IAAI,EAAG,UAAU,EAAE,OAAO;IAC1B,IAAI,EAAG,UAAU,EAAE,SAAS;IAC5B,KAAK,EAAE,UAAU,EAAE,MAAM;CAC1B,CAAC;AAEF,MAAM,KAAK,GAAG,SAAS,CAAC;AACxB,MAAM,IAAI,GAAI,SAAS,CAAC;AAExB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC;AAErD,iFAAiF;AAEjF,IAAI,SAAS,GAAa,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;AACpD,IAAI,OAAO,GAAe,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;AACrD,IAAI,QAAQ,GAAc,WAAW,CAAC;AAEtC,MAAM,UAAU,eAAe,CAAC,MAAoB;IAClD,IAAI,MAAM,CAAC,KAAK;QAAI,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC;IAC7C,IAAI,MAAM,CAAC,MAAM;QAAG,OAAO,GAAK,MAAM,CAAC,MAAM,CAAC;IAC9C,IAAI,MAAM,CAAC,OAAO;QAAE,QAAQ,GAAI,MAAM,CAAC,OAAO,CAAC;AACjD,CAAC;AAED,iFAAiF;AAEjF,SAAS,KAAK,CACZ,KAAe,EACf,GAAW,EACX,MAAgC,EAChC,SAAkB;IAElB,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC;QAAE,OAAO;IAE9C,MAAM,KAAK,GAAa;QACtB,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAC5B,KAAK;QACL,GAAG;QACH,GAAG,CAAC,SAAS,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;QAC3C,GAAG,CAAC,QAAQ,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;QACtC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC;KAClB,CAAC;IAEF,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvB,oCAAoC;QACpC,yDAAyD;QACzD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;QACnD,OAAO;IACT,CAAC;IAED,gCAAgC;IAChC,MAAM,KAAK,GAAI,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,EAAE,GAAO,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACxE,MAAM,GAAG,GAAM,KAAK,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAM,SAAS,CAAC,CAAC,CAAC,aAAa,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;IAE7E,sBAAsB;IACtB,MAAM,KAAK,GAAG,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC;QACpD,CAAC,CAAC,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;aACzB,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;aAC3D,IAAI,CAAC,GAAG,CAAC;QACd,CAAC,CAAC,EAAE,CAAC;IAEP,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;QACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,KAAK,KAAK,GAAG,IAAI,GAAG,GAAG,GAAG,KAAK,YAAY,EAAE,GAAG,KAAK,GAAG,GAAG,IAAI,GAAG,GAAG,KAAK,IAAI,CAC/E,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,KAAK,KAAK,GAAG,GAAG,GAAG,KAAK,YAAY,EAAE,GAAG,KAAK,GAAG,GAAG,IAAI,GAAG,GAAG,KAAK,IAAI,CACxE,CAAC;IACJ,CAAC;AACH,CAAC;AAeD,SAAS,UAAU,CACjB,SAAkB,EAClB,aAAuC;IAEvC,OAAO;QACL,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,GAAG,aAAa,EAAE,GAAG,MAAM,EAAE,EAAE,SAAS,CAAC;QACvF,IAAI,EAAG,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAG,GAAG,EAAE,EAAE,GAAG,aAAa,EAAE,GAAG,MAAM,EAAE,EAAE,SAAS,CAAC;QACvF,IAAI,EAAG,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAG,GAAG,EAAE,EAAE,GAAG,aAAa,EAAE,GAAG,MAAM,EAAE,EAAE,SAAS,CAAC;QACvF,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,GAAG,aAAa,EAAE,GAAG,MAAM,EAAE,EAAE,SAAS,CAAC;QACvF,WAAW,EAAE,CAAC,GAAG,EAAK,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,aAAa,CAAC;QACvD,UAAU,EAAG,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,SAAS,EAAE,EAAE,GAAG,aAAa,EAAE,GAAG,MAAM,EAAE,CAAC;KAChF,CAAC;AACJ,CAAC;AAED,gEAAgE;AAChE,MAAM,CAAC,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;AAEnC,iFAAiF;AAEjF;;;GAGG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;IAChC,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAC9B,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC3F,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CACxB,GAAY,EACZ,SAAiB,EACjB,QAAgB;IAEhB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE;QAC9C,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,IAAI,EAAE,GAAG,CAAC,QAAQ;QAClB,EAAE,EAAE,QAAQ;QACZ,EAAE,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,SAAS;KAC7D,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CACzB,GAAY,EACZ,GAAa,EACb,SAAiB,EACjB,SAAiB;IAEjB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,EAAE,GAAI,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACvD,MAAM,GAAG,GAAa,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,OAAO;QAC/C,CAAC,CAAC,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,MAAM;YAC5B,CAAC,CAAC,MAAM,CAAC;IAEX,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE;QAC/C,MAAM,EAAG,GAAG,CAAC,MAAM;QACnB,IAAI,EAAK,GAAG,CAAC,QAAQ;QACrB,MAAM,EAAG,GAAG,CAAC,MAAM;QACnB,EAAE,EAAO,MAAM,CAAC,EAAE,CAAC;KACpB,CAAC,CAAC;AACL,CAAC"}