@buenojs/bueno 0.8.3 → 0.8.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.
Files changed (218) hide show
  1. package/README.md +136 -16
  2. package/dist/cli/{index.js → bin.js} +3036 -1421
  3. package/dist/container/index.js +250 -0
  4. package/dist/context/index.js +219 -0
  5. package/dist/database/index.js +493 -0
  6. package/dist/frontend/index.js +7697 -0
  7. package/dist/health/index.js +364 -0
  8. package/dist/i18n/index.js +345 -0
  9. package/dist/index.js +11043 -6482
  10. package/dist/jobs/index.js +819 -0
  11. package/dist/lock/index.js +367 -0
  12. package/dist/logger/index.js +281 -0
  13. package/dist/metrics/index.js +289 -0
  14. package/dist/middleware/index.js +77 -0
  15. package/dist/migrations/index.js +571 -0
  16. package/dist/modules/index.js +3346 -0
  17. package/dist/notification/index.js +484 -0
  18. package/dist/observability/index.js +331 -0
  19. package/dist/openapi/index.js +776 -0
  20. package/dist/orm/index.js +1356 -0
  21. package/dist/router/index.js +886 -0
  22. package/dist/rpc/index.js +691 -0
  23. package/dist/schema/index.js +400 -0
  24. package/dist/telemetry/index.js +595 -0
  25. package/dist/template/index.js +640 -0
  26. package/dist/templates/index.js +640 -0
  27. package/dist/testing/index.js +1111 -0
  28. package/dist/types/index.js +60 -0
  29. package/package.json +121 -27
  30. package/src/cache/index.ts +2 -1
  31. package/src/cli/bin.ts +2 -2
  32. package/src/cli/commands/build.ts +183 -165
  33. package/src/cli/commands/dev.ts +96 -89
  34. package/src/cli/commands/generate.ts +142 -111
  35. package/src/cli/commands/help.ts +20 -16
  36. package/src/cli/commands/index.ts +3 -6
  37. package/src/cli/commands/migration.ts +124 -105
  38. package/src/cli/commands/new.ts +392 -438
  39. package/src/cli/commands/start.ts +81 -79
  40. package/src/cli/core/args.ts +68 -50
  41. package/src/cli/core/console.ts +89 -95
  42. package/src/cli/core/index.ts +4 -4
  43. package/src/cli/core/prompt.ts +65 -62
  44. package/src/cli/core/spinner.ts +23 -20
  45. package/src/cli/index.ts +46 -38
  46. package/src/cli/templates/database/index.ts +61 -0
  47. package/src/cli/templates/database/mysql.ts +14 -0
  48. package/src/cli/templates/database/none.ts +16 -0
  49. package/src/cli/templates/database/postgresql.ts +14 -0
  50. package/src/cli/templates/database/sqlite.ts +14 -0
  51. package/src/cli/templates/deploy.ts +29 -26
  52. package/src/cli/templates/docker.ts +41 -30
  53. package/src/cli/templates/frontend/index.ts +63 -0
  54. package/src/cli/templates/frontend/none.ts +17 -0
  55. package/src/cli/templates/frontend/react.ts +140 -0
  56. package/src/cli/templates/frontend/solid.ts +134 -0
  57. package/src/cli/templates/frontend/svelte.ts +131 -0
  58. package/src/cli/templates/frontend/vue.ts +130 -0
  59. package/src/cli/templates/generators/index.ts +339 -0
  60. package/src/cli/templates/generators/types.ts +56 -0
  61. package/src/cli/templates/index.ts +35 -2
  62. package/src/cli/templates/project/api.ts +81 -0
  63. package/src/cli/templates/project/default.ts +140 -0
  64. package/src/cli/templates/project/fullstack.ts +111 -0
  65. package/src/cli/templates/project/index.ts +95 -0
  66. package/src/cli/templates/project/minimal.ts +45 -0
  67. package/src/cli/templates/project/types.ts +94 -0
  68. package/src/cli/templates/project/website.ts +263 -0
  69. package/src/cli/utils/fs.ts +55 -41
  70. package/src/cli/utils/index.ts +3 -2
  71. package/src/cli/utils/strings.ts +47 -33
  72. package/src/cli/utils/version.ts +47 -0
  73. package/src/config/env-validation.ts +100 -0
  74. package/src/config/env.ts +169 -41
  75. package/src/config/index.ts +28 -20
  76. package/src/config/loader.ts +25 -16
  77. package/src/config/merge.ts +21 -10
  78. package/src/config/types.ts +545 -25
  79. package/src/config/validation.ts +215 -7
  80. package/src/container/forward-ref.ts +22 -22
  81. package/src/container/index.ts +34 -12
  82. package/src/context/index.ts +11 -1
  83. package/src/database/index.ts +7 -190
  84. package/src/database/orm/builder.ts +457 -0
  85. package/src/database/orm/casts/index.ts +130 -0
  86. package/src/database/orm/casts/types.ts +25 -0
  87. package/src/database/orm/compiler.ts +304 -0
  88. package/src/database/orm/hooks/index.ts +114 -0
  89. package/src/database/orm/index.ts +61 -0
  90. package/src/database/orm/model-registry.ts +59 -0
  91. package/src/database/orm/model.ts +821 -0
  92. package/src/database/orm/relationships/base.ts +146 -0
  93. package/src/database/orm/relationships/belongs-to-many.ts +179 -0
  94. package/src/database/orm/relationships/belongs-to.ts +56 -0
  95. package/src/database/orm/relationships/has-many.ts +45 -0
  96. package/src/database/orm/relationships/has-one.ts +41 -0
  97. package/src/database/orm/relationships/index.ts +11 -0
  98. package/src/database/orm/scopes/index.ts +55 -0
  99. package/src/events/__tests__/event-system.test.ts +235 -0
  100. package/src/events/config.ts +238 -0
  101. package/src/events/example-usage.ts +185 -0
  102. package/src/events/index.ts +278 -0
  103. package/src/events/manager.ts +385 -0
  104. package/src/events/registry.ts +182 -0
  105. package/src/events/types.ts +124 -0
  106. package/src/frontend/api-routes.ts +65 -23
  107. package/src/frontend/bundler.ts +76 -34
  108. package/src/frontend/console-client.ts +2 -2
  109. package/src/frontend/console-stream.ts +94 -38
  110. package/src/frontend/dev-server.ts +94 -46
  111. package/src/frontend/file-router.ts +61 -19
  112. package/src/frontend/frameworks/index.ts +37 -10
  113. package/src/frontend/frameworks/react.ts +10 -8
  114. package/src/frontend/frameworks/solid.ts +11 -9
  115. package/src/frontend/frameworks/svelte.ts +15 -9
  116. package/src/frontend/frameworks/vue.ts +13 -11
  117. package/src/frontend/hmr-client.ts +12 -10
  118. package/src/frontend/hmr.ts +146 -103
  119. package/src/frontend/index.ts +14 -5
  120. package/src/frontend/islands.ts +41 -22
  121. package/src/frontend/isr.ts +59 -37
  122. package/src/frontend/layout.ts +36 -21
  123. package/src/frontend/ssr/react.ts +74 -27
  124. package/src/frontend/ssr/solid.ts +54 -20
  125. package/src/frontend/ssr/svelte.ts +48 -14
  126. package/src/frontend/ssr/vue.ts +50 -18
  127. package/src/frontend/ssr.ts +83 -39
  128. package/src/frontend/types.ts +91 -56
  129. package/src/health/index.ts +21 -9
  130. package/src/i18n/engine.ts +305 -0
  131. package/src/i18n/index.ts +38 -0
  132. package/src/i18n/loader.ts +218 -0
  133. package/src/i18n/middleware.ts +164 -0
  134. package/src/i18n/negotiator.ts +162 -0
  135. package/src/i18n/types.ts +158 -0
  136. package/src/index.ts +179 -27
  137. package/src/jobs/drivers/memory.ts +315 -0
  138. package/src/jobs/drivers/redis.ts +459 -0
  139. package/src/jobs/index.ts +30 -0
  140. package/src/jobs/queue.ts +281 -0
  141. package/src/jobs/types.ts +295 -0
  142. package/src/jobs/worker.ts +380 -0
  143. package/src/logger/index.ts +1 -3
  144. package/src/logger/transports/index.ts +62 -22
  145. package/src/metrics/index.ts +25 -16
  146. package/src/migrations/index.ts +9 -0
  147. package/src/modules/filters.ts +13 -17
  148. package/src/modules/guards.ts +49 -26
  149. package/src/modules/index.ts +409 -298
  150. package/src/modules/interceptors.ts +58 -20
  151. package/src/modules/lazy.ts +11 -19
  152. package/src/modules/lifecycle.ts +15 -7
  153. package/src/modules/metadata.ts +15 -5
  154. package/src/modules/pipes.ts +94 -72
  155. package/src/notification/channels/base.ts +68 -0
  156. package/src/notification/channels/email.ts +105 -0
  157. package/src/notification/channels/push.ts +104 -0
  158. package/src/notification/channels/sms.ts +105 -0
  159. package/src/notification/channels/whatsapp.ts +104 -0
  160. package/src/notification/index.ts +48 -0
  161. package/src/notification/service.ts +354 -0
  162. package/src/notification/types.ts +344 -0
  163. package/src/observability/__tests__/observability.test.ts +483 -0
  164. package/src/observability/breadcrumbs.ts +114 -0
  165. package/src/observability/index.ts +136 -0
  166. package/src/observability/interceptor.ts +85 -0
  167. package/src/observability/service.ts +303 -0
  168. package/src/observability/trace.ts +37 -0
  169. package/src/observability/types.ts +196 -0
  170. package/src/openapi/__tests__/decorators.test.ts +335 -0
  171. package/src/openapi/__tests__/document-builder.test.ts +285 -0
  172. package/src/openapi/__tests__/route-scanner.test.ts +334 -0
  173. package/src/openapi/__tests__/schema-generator.test.ts +275 -0
  174. package/src/openapi/decorators.ts +328 -0
  175. package/src/openapi/document-builder.ts +274 -0
  176. package/src/openapi/index.ts +112 -0
  177. package/src/openapi/metadata.ts +112 -0
  178. package/src/openapi/route-scanner.ts +289 -0
  179. package/src/openapi/schema-generator.ts +256 -0
  180. package/src/openapi/swagger-module.ts +166 -0
  181. package/src/openapi/types.ts +398 -0
  182. package/src/orm/index.ts +10 -0
  183. package/src/rpc/index.ts +3 -1
  184. package/src/schema/index.ts +9 -0
  185. package/src/security/index.ts +15 -6
  186. package/src/ssg/index.ts +9 -8
  187. package/src/telemetry/index.ts +76 -22
  188. package/src/template/index.ts +7 -0
  189. package/src/templates/engine.ts +224 -0
  190. package/src/templates/index.ts +9 -0
  191. package/src/templates/loader.ts +331 -0
  192. package/src/templates/renderers/markdown.ts +212 -0
  193. package/src/templates/renderers/simple.ts +269 -0
  194. package/src/templates/types.ts +154 -0
  195. package/src/testing/index.ts +100 -27
  196. package/src/types/optional-deps.d.ts +347 -187
  197. package/src/validation/index.ts +92 -2
  198. package/src/validation/schemas.ts +536 -0
  199. package/tests/integration/fullstack.test.ts +4 -4
  200. package/tests/unit/database.test.ts +2 -72
  201. package/tests/unit/env-validation.test.ts +166 -0
  202. package/tests/unit/events.test.ts +910 -0
  203. package/tests/unit/i18n.test.ts +455 -0
  204. package/tests/unit/jobs.test.ts +493 -0
  205. package/tests/unit/notification.test.ts +988 -0
  206. package/tests/unit/observability.test.ts +453 -0
  207. package/tests/unit/orm/builder.test.ts +323 -0
  208. package/tests/unit/orm/casts.test.ts +179 -0
  209. package/tests/unit/orm/compiler.test.ts +220 -0
  210. package/tests/unit/orm/eager-loading.test.ts +285 -0
  211. package/tests/unit/orm/hooks.test.ts +191 -0
  212. package/tests/unit/orm/model.test.ts +373 -0
  213. package/tests/unit/orm/relationships.test.ts +303 -0
  214. package/tests/unit/orm/scopes.test.ts +74 -0
  215. package/tests/unit/templates-simple.test.ts +53 -0
  216. package/tests/unit/templates.test.ts +454 -0
  217. package/tests/unit/validation.test.ts +18 -24
  218. package/tsconfig.json +11 -3
@@ -0,0 +1,367 @@
1
+ // @bun
2
+ var __defProp = Object.defineProperty;
3
+ var __export = (target, all) => {
4
+ for (var name in all)
5
+ __defProp(target, name, {
6
+ get: all[name],
7
+ enumerable: true,
8
+ configurable: true,
9
+ set: (newValue) => all[name] = () => newValue
10
+ });
11
+ };
12
+ var __legacyDecorateClassTS = function(decorators, target, key, desc) {
13
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
14
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
15
+ r = Reflect.decorate(decorators, target, key, desc);
16
+ else
17
+ for (var i = decorators.length - 1;i >= 0; i--)
18
+ if (d = decorators[i])
19
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
20
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
21
+ };
22
+ var __legacyMetadataTS = (k, v) => {
23
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
24
+ return Reflect.metadata(k, v);
25
+ };
26
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
27
+ var __require = import.meta.require;
28
+
29
+ // src/lock/index.ts
30
+ var sharedLockStore = new Map;
31
+ var cleanupInterval = null;
32
+ function ensureCleanup() {
33
+ if (!cleanupInterval) {
34
+ cleanupInterval = setInterval(() => {
35
+ const now = Date.now();
36
+ for (const [key, lock] of sharedLockStore.entries()) {
37
+ if (now >= lock.expiresAt) {
38
+ sharedLockStore.delete(key);
39
+ }
40
+ }
41
+ }, 1e4);
42
+ }
43
+ }
44
+
45
+ class MemoryLockDriver {
46
+ constructor() {
47
+ ensureCleanup();
48
+ }
49
+ async acquire(key, value, ttl) {
50
+ const now = Date.now();
51
+ const existing = sharedLockStore.get(key);
52
+ if (existing && now < existing.expiresAt) {
53
+ return false;
54
+ }
55
+ sharedLockStore.set(key, {
56
+ value,
57
+ expiresAt: now + ttl
58
+ });
59
+ return true;
60
+ }
61
+ async release(key, value) {
62
+ const lock = sharedLockStore.get(key);
63
+ if (lock && lock.value === value) {
64
+ sharedLockStore.delete(key);
65
+ return true;
66
+ }
67
+ return false;
68
+ }
69
+ async extend(key, value, ttl) {
70
+ const lock = sharedLockStore.get(key);
71
+ if (lock && lock.value === value) {
72
+ const now = Date.now();
73
+ if (now >= lock.expiresAt) {
74
+ return false;
75
+ }
76
+ lock.expiresAt = now + ttl;
77
+ return true;
78
+ }
79
+ return false;
80
+ }
81
+ async isValid(key, value) {
82
+ const lock = sharedLockStore.get(key);
83
+ const now = Date.now();
84
+ return lock !== undefined && lock.value === value && now < lock.expiresAt;
85
+ }
86
+ async getTTL(key, value) {
87
+ const lock = sharedLockStore.get(key);
88
+ const now = Date.now();
89
+ if (!lock || lock.value !== value) {
90
+ return -1;
91
+ }
92
+ const remaining = lock.expiresAt - now;
93
+ return remaining > 0 ? remaining : -1;
94
+ }
95
+ destroy() {}
96
+ }
97
+
98
+ class RedisLockDriver {
99
+ client = null;
100
+ url;
101
+ _isConnected = false;
102
+ releaseScript = `
103
+ if redis.call("get", KEYS[1]) == ARGV[1] then
104
+ return redis.call("del", KEYS[1])
105
+ else
106
+ return 0
107
+ end
108
+ `;
109
+ extendScript = `
110
+ if redis.call("get", KEYS[1]) == ARGV[1] then
111
+ return redis.call("pexpire", KEYS[1], ARGV[2])
112
+ else
113
+ return 0
114
+ end
115
+ `;
116
+ constructor(url) {
117
+ this.url = url;
118
+ }
119
+ async connect() {
120
+ try {
121
+ const { RedisClient } = await Promise.resolve(globalThis.Bun);
122
+ this.client = new RedisClient(this.url);
123
+ this._isConnected = true;
124
+ } catch (error) {
125
+ throw new Error(`Failed to connect to Redis: ${error instanceof Error ? error.message : String(error)}`);
126
+ }
127
+ }
128
+ async disconnect() {
129
+ const client = this.client;
130
+ if (client?.close) {
131
+ await client.close();
132
+ }
133
+ this._isConnected = false;
134
+ this.client = null;
135
+ }
136
+ get isConnected() {
137
+ return this._isConnected;
138
+ }
139
+ async acquire(key, value, ttl) {
140
+ const client = this.client;
141
+ const result = await client.set(key, value, { nx: true, px: ttl });
142
+ return result === "OK";
143
+ }
144
+ async release(key, value) {
145
+ const client = this.client;
146
+ const result = await client.eval(this.releaseScript, [key], [value]);
147
+ return result === 1;
148
+ }
149
+ async extend(key, value, ttl) {
150
+ const client = this.client;
151
+ const result = await client.eval(this.extendScript, [key], [value, String(ttl)]);
152
+ return result === 1;
153
+ }
154
+ async isValid(key, value) {
155
+ const client = this.client;
156
+ const stored = await client.get(key);
157
+ return stored === value;
158
+ }
159
+ async getTTL(key, value) {
160
+ const client = this.client;
161
+ const stored = await client.get(key);
162
+ if (stored !== value) {
163
+ return -1;
164
+ }
165
+ return client.pttl(key);
166
+ }
167
+ }
168
+
169
+ class DistributedLock {
170
+ driver;
171
+ driverType;
172
+ keyPrefix;
173
+ defaultTTL;
174
+ defaultRetryCount;
175
+ defaultRetryDelay;
176
+ _isConnected = false;
177
+ constructor(config = {}) {
178
+ this.driverType = config.driver ?? "memory";
179
+ this.keyPrefix = config.keyPrefix ?? "lock:";
180
+ this.defaultTTL = config.defaultTTL ?? 30000;
181
+ this.defaultRetryCount = config.retryCount ?? 3;
182
+ this.defaultRetryDelay = config.retryDelay ?? 200;
183
+ if (this.driverType === "redis" && config.url) {
184
+ this.driver = new RedisLockDriver(config.url);
185
+ } else {
186
+ this.driver = new MemoryLockDriver;
187
+ this._isConnected = true;
188
+ }
189
+ }
190
+ async connect() {
191
+ if (this.driver instanceof RedisLockDriver) {
192
+ await this.driver.connect();
193
+ }
194
+ this._isConnected = true;
195
+ }
196
+ async disconnect() {
197
+ if (this.driver instanceof RedisLockDriver) {
198
+ await this.driver.disconnect();
199
+ } else {
200
+ this.driver.destroy();
201
+ }
202
+ this._isConnected = false;
203
+ }
204
+ get isConnected() {
205
+ return this._isConnected;
206
+ }
207
+ getDriverType() {
208
+ return this.driverType;
209
+ }
210
+ generateLockValue() {
211
+ const bytes = new Uint8Array(16);
212
+ crypto.getRandomValues(bytes);
213
+ return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
214
+ }
215
+ async tryAcquire(key, value, ttl) {
216
+ return this.driver.acquire(key, value, ttl);
217
+ }
218
+ async acquire(key, options = {}) {
219
+ const fullKey = this.keyPrefix + key;
220
+ const ttl = options.ttl ?? this.defaultTTL;
221
+ const retryCount = options.retryCount ?? this.defaultRetryCount;
222
+ const retryDelay = options.retryDelay ?? this.defaultRetryDelay;
223
+ const value = this.generateLockValue();
224
+ let acquired = false;
225
+ let attempts = 0;
226
+ while (!acquired && attempts <= retryCount) {
227
+ acquired = await this.tryAcquire(fullKey, value, ttl);
228
+ if (!acquired && attempts < retryCount) {
229
+ await this.sleep(retryDelay);
230
+ }
231
+ attempts++;
232
+ }
233
+ const acquiredAt = Date.now();
234
+ return {
235
+ acquired,
236
+ key: fullKey,
237
+ value,
238
+ release: async () => {
239
+ if (!acquired)
240
+ return false;
241
+ return this.driver.release(fullKey, value);
242
+ },
243
+ extend: async (newTTL) => {
244
+ if (!acquired)
245
+ return false;
246
+ return this.driver.extend(fullKey, value, newTTL ?? ttl);
247
+ },
248
+ isValid: async () => {
249
+ if (!acquired)
250
+ return false;
251
+ return this.driver.isValid(fullKey, value);
252
+ },
253
+ getRemainingTTL: async () => {
254
+ if (!acquired)
255
+ return -1;
256
+ return this.driver.getTTL(fullKey, value);
257
+ }
258
+ };
259
+ }
260
+ async withLock(key, fn, options = {}) {
261
+ const lock = await this.acquire(key, options);
262
+ if (!lock.acquired) {
263
+ throw new LockAcquireError(`Failed to acquire lock: ${key}`);
264
+ }
265
+ try {
266
+ return await fn(lock);
267
+ } finally {
268
+ await lock.release();
269
+ }
270
+ }
271
+ async withAutoExtend(key, fn, options = {}) {
272
+ const lock = await this.acquire(key, options);
273
+ if (!lock.acquired) {
274
+ throw new LockAcquireError(`Failed to acquire lock: ${key}`);
275
+ }
276
+ const ttl = options.ttl ?? this.defaultTTL;
277
+ const extendInterval = ttl * 0.7;
278
+ let extendTimer = null;
279
+ let completed = false;
280
+ extendTimer = setInterval(async () => {
281
+ if (!completed) {
282
+ const remaining = await lock.getRemainingTTL();
283
+ if (remaining > 0 && remaining < extendInterval) {
284
+ await lock.extend(ttl);
285
+ }
286
+ }
287
+ }, extendInterval);
288
+ try {
289
+ const result = await fn(lock);
290
+ completed = true;
291
+ return result;
292
+ } finally {
293
+ if (extendTimer) {
294
+ clearInterval(extendTimer);
295
+ }
296
+ await lock.release();
297
+ }
298
+ }
299
+ async tryLock(key, options = {}) {
300
+ return this.acquire(key, { ...options, retryCount: 0 });
301
+ }
302
+ async isLocked(key) {
303
+ const fullKey = this.keyPrefix + key;
304
+ const value = this.generateLockValue();
305
+ const acquired = await this.driver.acquire(fullKey, value, 1);
306
+ if (acquired) {
307
+ await this.driver.release(fullKey, value);
308
+ return false;
309
+ }
310
+ return true;
311
+ }
312
+ async forceRelease(key) {
313
+ const fullKey = this.keyPrefix + key;
314
+ const value = this.generateLockValue();
315
+ await this.driver.release(fullKey, value);
316
+ }
317
+ sleep(ms) {
318
+ return new Promise((resolve) => setTimeout(resolve, ms));
319
+ }
320
+ }
321
+
322
+ class LockAcquireError extends Error {
323
+ constructor(message) {
324
+ super(message);
325
+ this.name = "LockAcquireError";
326
+ }
327
+ }
328
+
329
+ class LockTimeoutError extends Error {
330
+ constructor(message) {
331
+ super(message);
332
+ this.name = "LockTimeoutError";
333
+ }
334
+ }
335
+ function createDistributedLock(config) {
336
+ return new DistributedLock(config);
337
+ }
338
+ function createRedisLock(url, options) {
339
+ return new DistributedLock({ driver: "redis", url, ...options });
340
+ }
341
+ function createMemoryLock() {
342
+ return new DistributedLock({ driver: "memory" });
343
+ }
344
+ var defaultLock = null;
345
+ function getDefaultLock() {
346
+ if (!defaultLock) {
347
+ defaultLock = new DistributedLock({ driver: "memory" });
348
+ }
349
+ return defaultLock;
350
+ }
351
+ function setDefaultLock(lock) {
352
+ defaultLock = lock;
353
+ }
354
+ async function lock(key, fn, options) {
355
+ return getDefaultLock().withLock(key, async () => fn(), options);
356
+ }
357
+ export {
358
+ setDefaultLock,
359
+ lock,
360
+ getDefaultLock,
361
+ createRedisLock,
362
+ createMemoryLock,
363
+ createDistributedLock,
364
+ LockTimeoutError,
365
+ LockAcquireError,
366
+ DistributedLock
367
+ };
@@ -0,0 +1,281 @@
1
+ // @bun
2
+ var __defProp = Object.defineProperty;
3
+ var __export = (target, all) => {
4
+ for (var name in all)
5
+ __defProp(target, name, {
6
+ get: all[name],
7
+ enumerable: true,
8
+ configurable: true,
9
+ set: (newValue) => all[name] = () => newValue
10
+ });
11
+ };
12
+ var __legacyDecorateClassTS = function(decorators, target, key, desc) {
13
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
14
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
15
+ r = Reflect.decorate(decorators, target, key, desc);
16
+ else
17
+ for (var i = decorators.length - 1;i >= 0; i--)
18
+ if (d = decorators[i])
19
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
20
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
21
+ };
22
+ var __legacyMetadataTS = (k, v) => {
23
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
24
+ return Reflect.metadata(k, v);
25
+ };
26
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
27
+ var __require = import.meta.require;
28
+
29
+ // src/logger/index.ts
30
+ var LOG_LEVELS = {
31
+ debug: 0,
32
+ info: 1,
33
+ warn: 2,
34
+ error: 3,
35
+ fatal: 4
36
+ };
37
+
38
+ class Logger {
39
+ level;
40
+ pretty;
41
+ timestamp;
42
+ context;
43
+ output;
44
+ constructor(config = {}) {
45
+ this.level = config.level ?? "info";
46
+ this.pretty = config.pretty ?? true;
47
+ this.timestamp = config.timestamp ?? true;
48
+ this.context = config.context ?? {};
49
+ if (typeof config.output === "function") {
50
+ this.output = config.output;
51
+ } else if (config.output === "stdout") {
52
+ this.output = (entry) => console.log(this.serialize(entry));
53
+ } else {
54
+ this.output = (entry) => {
55
+ if (this.pretty) {
56
+ this.prettyPrint(entry);
57
+ } else {
58
+ console.log(this.serialize(entry));
59
+ }
60
+ };
61
+ }
62
+ }
63
+ shouldLog(level) {
64
+ return LOG_LEVELS[level] >= LOG_LEVELS[this.level];
65
+ }
66
+ serialize(entry) {
67
+ return JSON.stringify(entry);
68
+ }
69
+ prettyPrint(entry) {
70
+ const timestamp = entry.timestamp;
71
+ const levelColors = {
72
+ debug: "\x1B[36m",
73
+ info: "\x1B[32m",
74
+ warn: "\x1B[33m",
75
+ error: "\x1B[31m",
76
+ fatal: "\x1B[35m"
77
+ };
78
+ const reset = "\x1B[0m";
79
+ const color = levelColors[entry.level];
80
+ let output = `${timestamp} ${color}[${entry.level.toUpperCase()}]${reset} ${entry.message}`;
81
+ if (entry.context && Object.keys(entry.context).length > 0) {
82
+ output += ` ${reset}\x1B[90m${JSON.stringify(entry.context)}\x1B[0m`;
83
+ }
84
+ if (entry.duration !== undefined) {
85
+ output += ` \x1B[90m(${entry.duration}ms)\x1B[0m`;
86
+ }
87
+ if (entry.error) {
88
+ output += `
89
+ \x1B[31m${entry.error.name}: ${entry.error.message}\x1B[0m`;
90
+ if (entry.error.stack) {
91
+ output += `
92
+ \x1B[90m${entry.error.stack}\x1B[0m`;
93
+ }
94
+ }
95
+ switch (entry.level) {
96
+ case "error":
97
+ case "fatal":
98
+ console.error(output);
99
+ break;
100
+ case "warn":
101
+ console.warn(output);
102
+ break;
103
+ default:
104
+ console.log(output);
105
+ }
106
+ }
107
+ createEntry(level, message, context, error) {
108
+ const entry = {
109
+ level,
110
+ message,
111
+ timestamp: this.timestamp ? new Date().toISOString() : "",
112
+ ...this.context
113
+ };
114
+ if (context) {
115
+ entry.context = context;
116
+ }
117
+ if (error) {
118
+ entry.error = {
119
+ name: error.name,
120
+ message: error.message,
121
+ stack: error.stack
122
+ };
123
+ }
124
+ return entry;
125
+ }
126
+ debug(message, context) {
127
+ if (!this.shouldLog("debug"))
128
+ return;
129
+ this.output(this.createEntry("debug", message, context));
130
+ }
131
+ info(message, context) {
132
+ if (!this.shouldLog("info"))
133
+ return;
134
+ this.output(this.createEntry("info", message, context));
135
+ }
136
+ warn(message, context) {
137
+ if (!this.shouldLog("warn"))
138
+ return;
139
+ this.output(this.createEntry("warn", message, context));
140
+ }
141
+ error(message, error, context) {
142
+ if (!this.shouldLog("error"))
143
+ return;
144
+ const err = error instanceof Error ? error : undefined;
145
+ this.output(this.createEntry("error", message, context, err));
146
+ }
147
+ fatal(message, error, context) {
148
+ if (!this.shouldLog("fatal"))
149
+ return;
150
+ const err = error instanceof Error ? error : undefined;
151
+ this.output(this.createEntry("fatal", message, context, err));
152
+ }
153
+ child(context) {
154
+ return new Logger({
155
+ level: this.level,
156
+ pretty: this.pretty,
157
+ timestamp: this.timestamp,
158
+ context: { ...this.context, ...context },
159
+ output: this.output
160
+ });
161
+ }
162
+ setLevel(level) {
163
+ this.level = level;
164
+ }
165
+ addContext(context) {
166
+ Object.assign(this.context, context);
167
+ }
168
+ async time(label, fn) {
169
+ const start = Date.now();
170
+ try {
171
+ const result = await fn();
172
+ this.debug(`${label} completed`, { duration: Date.now() - start });
173
+ return result;
174
+ } catch (error) {
175
+ this.error(`${label} failed`, error, { duration: Date.now() - start });
176
+ throw error;
177
+ }
178
+ }
179
+ startTimer(label) {
180
+ const start = Date.now();
181
+ return () => {
182
+ const duration = Date.now() - start;
183
+ this.debug(`${label}`, { duration });
184
+ return duration;
185
+ };
186
+ }
187
+ }
188
+ function createRequestLogger(logger) {
189
+ return async (ctx, next) => {
190
+ const context = ctx;
191
+ const start = Date.now();
192
+ const requestId = context.getHeader("x-request-id") || crypto.randomUUID();
193
+ context.set("requestId", requestId);
194
+ const requestContext = {
195
+ requestId,
196
+ method: context.method,
197
+ path: context.path,
198
+ query: context.url?.search,
199
+ ip: context.ip,
200
+ userAgent: context.getHeader("user-agent")
201
+ };
202
+ logger.info("Request started", requestContext);
203
+ try {
204
+ const response = await next();
205
+ const duration = Date.now() - start;
206
+ const responseContext = {
207
+ ...requestContext,
208
+ statusCode: response?.status ?? 200,
209
+ duration
210
+ };
211
+ logger.info("Request completed", responseContext);
212
+ return response;
213
+ } catch (error) {
214
+ const duration = Date.now() - start;
215
+ logger.error("Request failed", error, {
216
+ ...requestContext,
217
+ duration
218
+ });
219
+ throw error;
220
+ }
221
+ };
222
+ }
223
+
224
+ class PerformanceLogger {
225
+ logger;
226
+ metrics = new Map;
227
+ constructor(logger) {
228
+ this.logger = logger;
229
+ }
230
+ record(name, value) {
231
+ if (!this.metrics.has(name)) {
232
+ this.metrics.set(name, []);
233
+ }
234
+ this.metrics.get(name)?.push(value);
235
+ }
236
+ stats(name) {
237
+ const values = this.metrics.get(name);
238
+ if (!values || values.length === 0)
239
+ return null;
240
+ const sorted = [...values].sort((a, b) => a - b);
241
+ const count = sorted.length;
242
+ const min = sorted[0];
243
+ const max = sorted[count - 1];
244
+ const avg = sorted.reduce((a, b) => a + b, 0) / count;
245
+ const p99Index = Math.floor(count * 0.99);
246
+ const p99 = sorted[p99Index];
247
+ return { count, min, max, avg, p99 };
248
+ }
249
+ logMetrics() {
250
+ for (const [name] of this.metrics) {
251
+ const stats = this.stats(name);
252
+ if (stats) {
253
+ this.logger.info(`Metric: ${name}`, stats);
254
+ }
255
+ }
256
+ }
257
+ clear() {
258
+ this.metrics.clear();
259
+ }
260
+ }
261
+ var defaultLogger = null;
262
+ function getLogger() {
263
+ if (!defaultLogger) {
264
+ defaultLogger = new Logger;
265
+ }
266
+ return defaultLogger;
267
+ }
268
+ function setLogger(logger) {
269
+ defaultLogger = logger;
270
+ }
271
+ function createLogger(config) {
272
+ return new Logger(config);
273
+ }
274
+ export {
275
+ setLogger,
276
+ getLogger,
277
+ createRequestLogger,
278
+ createLogger,
279
+ PerformanceLogger,
280
+ Logger
281
+ };