@guren/server 1.0.0-rc.9 → 1.1.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.
Files changed (70) hide show
  1. package/dist/{Application-DtWDHXr1.d.ts → Application-BnsyCKXY.d.ts} +79 -8
  2. package/dist/AuthManager-SfhCNkAU.d.ts +79 -0
  3. package/dist/{BroadcastManager-AkIWUGJo.d.ts → BroadcastManager-CGWl9rUO.d.ts} +5 -0
  4. package/dist/{ConsoleKernel-CqCVrdZs.d.ts → ConsoleKernel-BDtBETjm.d.ts} +1 -1
  5. package/dist/{Gate-CNkBYf8m.d.ts → Gate-CynjZCtS.d.ts} +5 -0
  6. package/dist/{I18nManager-Dtgzsf5n.d.ts → I18nManager-BiSoczfV.d.ts} +6 -1
  7. package/dist/McpServiceProvider-JW6PDVMD.js +7 -0
  8. package/dist/api-token-BSSCLlFW.d.ts +541 -0
  9. package/dist/auth/index.d.ts +9 -327
  10. package/dist/auth/index.js +59 -6684
  11. package/dist/authorization/index.d.ts +2 -2
  12. package/dist/authorization/index.js +19 -604
  13. package/dist/broadcasting/index.d.ts +2 -2
  14. package/dist/broadcasting/index.js +12 -895
  15. package/dist/cache/index.js +8 -809
  16. package/dist/chunk-2T6JN4VR.js +1563 -0
  17. package/dist/chunk-44F7JQ7I.js +950 -0
  18. package/dist/chunk-74HTZG3V.js +331 -0
  19. package/dist/chunk-A3ISJVEV.js +598 -0
  20. package/dist/chunk-CSDKWLFD.js +652 -0
  21. package/dist/chunk-CSRQTEQA.js +839 -0
  22. package/dist/chunk-DAQKYKLH.js +182 -0
  23. package/dist/chunk-EDRGAM6G.js +647 -0
  24. package/dist/chunk-EGU5KB7V.js +818 -0
  25. package/dist/chunk-H32L2NE3.js +372 -0
  26. package/dist/chunk-HKQSAFSN.js +837 -0
  27. package/dist/chunk-IOTWFHZU.js +558 -0
  28. package/dist/chunk-ONSDE37A.js +125 -0
  29. package/dist/chunk-QH4NUKSV.js +255 -0
  30. package/dist/chunk-QQKTH5KX.js +114 -0
  31. package/dist/chunk-R2TCP7D7.js +409 -0
  32. package/dist/chunk-SIP34GBE.js +380 -0
  33. package/dist/chunk-THSX7OOR.js +454 -0
  34. package/dist/chunk-UY3AZSYL.js +14 -0
  35. package/dist/chunk-VT5KRDPH.js +134 -0
  36. package/dist/chunk-WJJ5CTNI.js +907 -0
  37. package/dist/chunk-WVY45EIW.js +359 -0
  38. package/dist/chunk-ZRBLZY3M.js +462 -0
  39. package/dist/client-CKXJLsTe.d.ts +232 -0
  40. package/dist/email-verification-CAeArjui.d.ts +327 -0
  41. package/dist/encryption/index.js +48 -556
  42. package/dist/errors-JOOPDDQ6.js +34 -0
  43. package/dist/events/index.js +14 -316
  44. package/dist/health/index.js +12 -367
  45. package/dist/i18n/index.d.ts +2 -2
  46. package/dist/i18n/index.js +14 -583
  47. package/dist/index.d.ts +37 -239
  48. package/dist/index.js +2931 -19222
  49. package/dist/lambda/index.d.ts +9 -7
  50. package/dist/lambda/index.js +4 -9
  51. package/dist/logging/index.js +12 -545
  52. package/dist/mail/index.d.ts +29 -1
  53. package/dist/mail/index.js +15 -684
  54. package/dist/mcp/index.d.ts +7 -5
  55. package/dist/mcp/index.js +5 -378
  56. package/dist/notifications/index.d.ts +8 -6
  57. package/dist/notifications/index.js +13 -730
  58. package/dist/queue/index.d.ts +37 -7
  59. package/dist/queue/index.js +22 -940
  60. package/dist/redis/index.d.ts +366 -0
  61. package/dist/redis/index.js +597 -0
  62. package/dist/runtime/index.d.ts +8 -6
  63. package/dist/runtime/index.js +26 -244
  64. package/dist/scheduling/index.js +14 -822
  65. package/dist/storage/index.d.ts +1 -0
  66. package/dist/storage/index.js +6 -824
  67. package/dist/vite/index.d.ts +2 -2
  68. package/dist/vite/index.js +5 -1
  69. package/package.json +15 -7
  70. package/dist/api-token-JOif2CtG.d.ts +0 -1792
@@ -0,0 +1,454 @@
1
+ import {
2
+ HttpException
3
+ } from "./chunk-DAQKYKLH.js";
4
+
5
+ // src/errors/error-page.ts
6
+ function escapeHtml(value) {
7
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
8
+ }
9
+ function renderErrorPage(statusCode, message) {
10
+ const title = STATUS_TITLES[statusCode] ?? "Error";
11
+ const description = escapeHtml(
12
+ message ?? STATUS_DESCRIPTIONS[statusCode] ?? "An unexpected error occurred."
13
+ );
14
+ return `<!DOCTYPE html>
15
+ <html lang="en">
16
+ <head>
17
+ <meta charset="utf-8">
18
+ <meta name="viewport" content="width=device-width, initial-scale=1">
19
+ <title>${statusCode} ${title}</title>
20
+ <style>
21
+ * { margin: 0; padding: 0; box-sizing: border-box; }
22
+ body {
23
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
24
+ min-height: 100vh;
25
+ display: flex;
26
+ align-items: center;
27
+ justify-content: center;
28
+ background: #fafaf9;
29
+ color: #1c1917;
30
+ }
31
+ .container { text-align: center; padding: 2rem; }
32
+ .status { font-size: 6rem; font-weight: 700; color: #d6d3d1; line-height: 1; }
33
+ .title { font-size: 1.5rem; font-weight: 600; margin-top: 1rem; }
34
+ .description { color: #78716c; margin-top: 0.5rem; max-width: 28rem; }
35
+ .home-link {
36
+ display: inline-block; margin-top: 2rem; padding: 0.625rem 1.5rem;
37
+ background: #1c1917; color: #fff; border-radius: 0.375rem;
38
+ text-decoration: none; font-size: 0.875rem; font-weight: 500;
39
+ }
40
+ .home-link:hover { background: #292524; }
41
+ </style>
42
+ </head>
43
+ <body>
44
+ <div class="container">
45
+ <div class="status">${statusCode}</div>
46
+ <h1 class="title">${title}</h1>
47
+ <p class="description">${description}</p>
48
+ <a href="/" class="home-link">Go Home</a>
49
+ </div>
50
+ </body>
51
+ </html>`;
52
+ }
53
+ var STATUS_TITLES = {
54
+ 400: "Bad Request",
55
+ 401: "Unauthorized",
56
+ 403: "Forbidden",
57
+ 404: "Not Found",
58
+ 405: "Method Not Allowed",
59
+ 408: "Request Timeout",
60
+ 419: "Page Expired",
61
+ 422: "Unprocessable Entity",
62
+ 429: "Too Many Requests",
63
+ 500: "Server Error",
64
+ 502: "Bad Gateway",
65
+ 503: "Service Unavailable",
66
+ 504: "Gateway Timeout"
67
+ };
68
+ var STATUS_DESCRIPTIONS = {
69
+ 400: "The request could not be understood by the server.",
70
+ 401: "You need to sign in to access this page.",
71
+ 403: "You do not have permission to access this page.",
72
+ 404: "The page you are looking for could not be found.",
73
+ 405: "The request method is not supported for this page.",
74
+ 419: "Your session has expired. Please refresh and try again.",
75
+ 422: "The submitted data was invalid.",
76
+ 429: "You are making too many requests. Please slow down.",
77
+ 500: "Something went wrong on our end. Please try again later.",
78
+ 502: "The server received an invalid response from an upstream server.",
79
+ 503: "The service is temporarily unavailable. Please try again later.",
80
+ 504: "The server did not receive a timely response from an upstream server."
81
+ };
82
+
83
+ // src/errors/ExceptionHandler.ts
84
+ var ExceptionHandler = class {
85
+ /**
86
+ * Exception reporters.
87
+ */
88
+ reporters = [];
89
+ /**
90
+ * Exception renderers.
91
+ */
92
+ renderers = [];
93
+ /**
94
+ * Exception classes to not report.
95
+ */
96
+ dontReportClasses = [];
97
+ /**
98
+ * Handler options.
99
+ */
100
+ options;
101
+ constructor(options = {}) {
102
+ this.options = options;
103
+ }
104
+ /**
105
+ * Register an exception reporter.
106
+ * Reporters are called for every exception (unless in dontReport list).
107
+ */
108
+ report(callback) {
109
+ this.reporters.push(callback);
110
+ return this;
111
+ }
112
+ /**
113
+ * Register a custom renderer for an exception type.
114
+ */
115
+ render(errorClass, renderer) {
116
+ this.renderers.push({
117
+ errorClass,
118
+ renderer
119
+ });
120
+ return this;
121
+ }
122
+ /**
123
+ * Add an exception class to the don't report list.
124
+ */
125
+ dontReport(errorClass) {
126
+ this.dontReportClasses.push(errorClass);
127
+ return this;
128
+ }
129
+ /**
130
+ * Check if debug mode is enabled.
131
+ */
132
+ shouldShowDetails() {
133
+ if (this.options.isDebug) {
134
+ return this.options.isDebug();
135
+ }
136
+ if (this.options.debug !== void 0) {
137
+ return this.options.debug;
138
+ }
139
+ return process.env.NODE_ENV !== "production";
140
+ }
141
+ /**
142
+ * Handle an exception.
143
+ */
144
+ async handle(error, ctx) {
145
+ await this.reportException(error);
146
+ return this.renderException(error, ctx);
147
+ }
148
+ /**
149
+ * Report an exception to all reporters.
150
+ */
151
+ async reportException(error) {
152
+ if (this.shouldNotReport(error)) {
153
+ return;
154
+ }
155
+ for (const reporter of this.reporters) {
156
+ try {
157
+ await reporter(error);
158
+ } catch (reporterError) {
159
+ console.error("Exception reporter failed:", reporterError);
160
+ }
161
+ }
162
+ }
163
+ /**
164
+ * Check if an exception should not be reported.
165
+ */
166
+ shouldNotReport(error) {
167
+ return this.dontReportClasses.some(
168
+ (errorClass) => this.matchesErrorClass(error, errorClass)
169
+ );
170
+ }
171
+ matchesErrorClass(error, errorClass) {
172
+ const errorClassName = errorClass.name;
173
+ const errorName = error.name;
174
+ const constructorName = error.constructor?.name;
175
+ return error instanceof errorClass || errorName === errorClassName || constructorName === errorClassName;
176
+ }
177
+ /**
178
+ * Render an exception to a response.
179
+ */
180
+ async renderException(error, ctx) {
181
+ for (const { errorClass, renderer } of this.renderers) {
182
+ if (this.matchesErrorClass(error, errorClass)) {
183
+ return renderer(error, ctx);
184
+ }
185
+ }
186
+ return this.renderDefaultException(error, ctx);
187
+ }
188
+ /**
189
+ * Default exception rendering.
190
+ */
191
+ renderDefaultException(error, ctx) {
192
+ const debug = this.shouldShowDetails();
193
+ if (HttpException.isHttpException(error)) {
194
+ const { status, body: body2 } = error.toResponse(debug);
195
+ if (this.wantsHtmlResponse(ctx) && !debug) {
196
+ return ctx.html(renderErrorPage(status, body2.message), status);
197
+ }
198
+ return ctx.json(body2, status);
199
+ }
200
+ const statusCode = "statusCode" in error && typeof error.statusCode === "number" ? error.statusCode : 500;
201
+ const body = {
202
+ message: statusCode < 500 || debug ? error.message : "Internal Server Error"
203
+ };
204
+ if (debug) {
205
+ body.exception = error.name;
206
+ body.stack = error.stack;
207
+ }
208
+ if (this.wantsHtmlResponse(ctx) && !debug) {
209
+ return ctx.html(renderErrorPage(statusCode, body.message), statusCode);
210
+ }
211
+ return ctx.json(body, statusCode);
212
+ }
213
+ /**
214
+ * Determine whether the request expects an HTML response.
215
+ * Returns false for Inertia, XHR, and JSON API requests so they
216
+ * continue to receive JSON error payloads.
217
+ */
218
+ wantsHtmlResponse(ctx) {
219
+ if (!ctx?.req?.header) return false;
220
+ const accept = ctx.req.header("accept") ?? "";
221
+ const isJsonRequest = accept.includes("application/json") || ctx.req.header("x-requested-with") === "XMLHttpRequest" || ctx.req.header("x-inertia") === "true";
222
+ return !isJsonRequest && accept.includes("text/html");
223
+ }
224
+ /**
225
+ * Create middleware for exception handling.
226
+ */
227
+ middleware() {
228
+ return async (ctx, next) => {
229
+ try {
230
+ return await next();
231
+ } catch (error) {
232
+ const response = error instanceof Error ? await this.handle(error, ctx) : await this.handle(new Error(String(error)), ctx);
233
+ ctx.res = response;
234
+ return response;
235
+ }
236
+ };
237
+ }
238
+ };
239
+ function createExceptionHandler(options) {
240
+ return new ExceptionHandler(options);
241
+ }
242
+ var globalExceptionHandler = null;
243
+ function setExceptionHandler(handler) {
244
+ globalExceptionHandler = handler;
245
+ }
246
+ function getExceptionHandler() {
247
+ if (!globalExceptionHandler) {
248
+ throw new Error(
249
+ "ExceptionHandler not initialized. Call setExceptionHandler() first."
250
+ );
251
+ }
252
+ return globalExceptionHandler;
253
+ }
254
+ function abort(statusCode, message, errors) {
255
+ throw new HttpException(statusCode, message ?? "Error", errors);
256
+ }
257
+ function abortIf(condition, statusCode, message) {
258
+ if (condition) {
259
+ abort(statusCode, message);
260
+ }
261
+ }
262
+ function abortUnless(condition, statusCode, message) {
263
+ if (!condition) {
264
+ abort(statusCode, message);
265
+ }
266
+ }
267
+
268
+ // src/errors/exceptions/ValidationException.ts
269
+ var ValidationException = class _ValidationException extends HttpException {
270
+ constructor(errors, message = "The given data was invalid.") {
271
+ super(422, message, errors);
272
+ this.name = "ValidationException";
273
+ }
274
+ /**
275
+ * Create from Zod error.
276
+ */
277
+ static fromZodError(zodError) {
278
+ const errors = {};
279
+ for (const issue of zodError.issues) {
280
+ const path = issue.path.join(".");
281
+ if (!errors[path]) {
282
+ errors[path] = [];
283
+ }
284
+ errors[path].push(issue.message);
285
+ }
286
+ return new _ValidationException(errors);
287
+ }
288
+ /**
289
+ * Get errors for a specific field.
290
+ */
291
+ getFieldErrors(field) {
292
+ return this.errors?.[field] ?? [];
293
+ }
294
+ /**
295
+ * Check if a field has errors.
296
+ */
297
+ hasFieldError(field) {
298
+ return (this.errors?.[field]?.length ?? 0) > 0;
299
+ }
300
+ /**
301
+ * Get the first error for a field.
302
+ */
303
+ getFirstError(field) {
304
+ return this.errors?.[field]?.[0] ?? null;
305
+ }
306
+ /**
307
+ * Get all error messages as a flat array.
308
+ */
309
+ getAllMessages() {
310
+ if (!this.errors) return [];
311
+ return Object.values(this.errors).flat();
312
+ }
313
+ /**
314
+ * Create a ValidationException from a plain messages object.
315
+ *
316
+ * Useful for business-logic validation (e.g. duplicate email checks)
317
+ * where Zod is not involved.
318
+ *
319
+ * @example
320
+ * ```typescript
321
+ * throw ValidationException.withMessages({ email: 'Email already registered' })
322
+ * throw ValidationException.withMessages({ email: ['Must be unique', 'Must be corporate'] })
323
+ * ```
324
+ */
325
+ static withMessages(messages) {
326
+ const errors = {};
327
+ for (const [key, value] of Object.entries(messages)) {
328
+ errors[key] = Array.isArray(value) ? value : [value];
329
+ }
330
+ return new _ValidationException(errors);
331
+ }
332
+ };
333
+
334
+ // src/errors/exceptions/AuthorizationException.ts
335
+ var AuthorizationException = class _AuthorizationException extends HttpException {
336
+ /**
337
+ * The action that was attempted.
338
+ */
339
+ action;
340
+ /**
341
+ * The resource that was being accessed.
342
+ */
343
+ resource;
344
+ constructor(message = "This action is unauthorized.", action, resource) {
345
+ super(403, message);
346
+ this.name = "AuthorizationException";
347
+ this.action = action;
348
+ this.resource = resource;
349
+ }
350
+ /**
351
+ * Create exception for a specific action and resource.
352
+ */
353
+ static forAction(action, resource) {
354
+ const message = resource ? `You are not authorized to ${action} this ${resource}.` : `You are not authorized to ${action}.`;
355
+ return new _AuthorizationException(message, action, resource);
356
+ }
357
+ /**
358
+ * Deny access to a resource.
359
+ */
360
+ static deny(resource) {
361
+ const message = resource ? `Access to ${resource} denied.` : "Access denied.";
362
+ return new _AuthorizationException(message, "access", resource);
363
+ }
364
+ };
365
+
366
+ // src/errors/exceptions/NotFoundHttpException.ts
367
+ var NotFoundHttpException = class _NotFoundHttpException extends HttpException {
368
+ /**
369
+ * The type of resource that was not found.
370
+ */
371
+ resourceType;
372
+ /**
373
+ * The ID of the resource that was not found.
374
+ */
375
+ resourceId;
376
+ constructor(message = "Not Found", resourceType, resourceId) {
377
+ super(404, message);
378
+ this.name = "NotFoundHttpException";
379
+ this.resourceType = resourceType;
380
+ this.resourceId = resourceId;
381
+ }
382
+ /**
383
+ * Create exception for a model not found.
384
+ */
385
+ static forModel(model, id) {
386
+ return new _NotFoundHttpException(
387
+ `${model} with ID ${id} not found.`,
388
+ model,
389
+ id
390
+ );
391
+ }
392
+ /**
393
+ * Create exception for a route not found.
394
+ */
395
+ static forRoute(path) {
396
+ return new _NotFoundHttpException(`Route ${path} not found.`, "Route");
397
+ }
398
+ /**
399
+ * Create exception for a resource not found.
400
+ */
401
+ static forResource(resource) {
402
+ return new _NotFoundHttpException(`${resource} not found.`, resource);
403
+ }
404
+ };
405
+
406
+ // src/errors/exceptions/MethodNotAllowedException.ts
407
+ var MethodNotAllowedException = class _MethodNotAllowedException extends HttpException {
408
+ /**
409
+ * The HTTP method that was attempted.
410
+ */
411
+ method;
412
+ /**
413
+ * The allowed HTTP methods.
414
+ */
415
+ allowedMethods;
416
+ constructor(method, allowedMethods, message) {
417
+ const defaultMessage = method ? `Method ${method} is not allowed.` : "Method Not Allowed";
418
+ super(405, message ?? defaultMessage);
419
+ this.name = "MethodNotAllowedException";
420
+ this.method = method;
421
+ this.allowedMethods = allowedMethods;
422
+ }
423
+ /**
424
+ * Get the Allow header value.
425
+ */
426
+ getAllowHeader() {
427
+ return this.allowedMethods?.join(", ") ?? "";
428
+ }
429
+ /**
430
+ * Create exception with method details.
431
+ */
432
+ static forMethod(method, allowedMethods) {
433
+ return new _MethodNotAllowedException(
434
+ method,
435
+ allowedMethods,
436
+ `Method ${method} not allowed. Allowed methods: ${allowedMethods.join(", ")}`
437
+ );
438
+ }
439
+ };
440
+
441
+ export {
442
+ ValidationException,
443
+ renderErrorPage,
444
+ ExceptionHandler,
445
+ createExceptionHandler,
446
+ setExceptionHandler,
447
+ getExceptionHandler,
448
+ abort,
449
+ abortIf,
450
+ abortUnless,
451
+ AuthorizationException,
452
+ NotFoundHttpException,
453
+ MethodNotAllowedException
454
+ };
@@ -0,0 +1,14 @@
1
+ // src/redis/client.ts
2
+ import Redis from "ioredis";
3
+ function createRedisClient(options = {}) {
4
+ const { url, ...redisOptions } = options;
5
+ if (url) {
6
+ return new Redis(url, redisOptions);
7
+ }
8
+ return new Redis(redisOptions);
9
+ }
10
+
11
+ export {
12
+ Redis,
13
+ createRedisClient
14
+ };
@@ -0,0 +1,134 @@
1
+ // src/container/ServiceProvider.ts
2
+ var ServiceProvider = class {
3
+ constructor(container) {
4
+ this.container = container;
5
+ }
6
+ /**
7
+ * Whether this provider should be deferred.
8
+ * Deferred providers are only loaded when one of their provided services is requested.
9
+ */
10
+ static deferred = false;
11
+ /**
12
+ * The services provided by this provider (for deferred loading).
13
+ */
14
+ static provides = [];
15
+ /**
16
+ * Get the services provided by the provider.
17
+ */
18
+ provides() {
19
+ return this.constructor.provides;
20
+ }
21
+ /**
22
+ * Check if this provider is deferred.
23
+ */
24
+ isDeferred() {
25
+ return this.constructor.deferred;
26
+ }
27
+ };
28
+ var ProviderManager = class {
29
+ constructor(container) {
30
+ this.container = container;
31
+ }
32
+ providers = [];
33
+ registered = /* @__PURE__ */ new Set();
34
+ booted = /* @__PURE__ */ new Set();
35
+ deferredProviders = /* @__PURE__ */ new Map();
36
+ allBooted = false;
37
+ /**
38
+ * Register a provider.
39
+ */
40
+ register(providerOrClass) {
41
+ if (this.allBooted) {
42
+ const name = providerOrClass instanceof ServiceProvider ? providerOrClass.constructor.name : providerOrClass.name;
43
+ throw new Error(
44
+ `Cannot register provider "${name}" after bootAll() has been called. Register all providers before booting the application.`
45
+ );
46
+ }
47
+ const provider = providerOrClass instanceof ServiceProvider ? providerOrClass : new providerOrClass(this.container);
48
+ if (provider.isDeferred()) {
49
+ for (const service of provider.provides()) {
50
+ this.deferredProviders.set(service, provider);
51
+ }
52
+ } else {
53
+ this.providers.push(provider);
54
+ }
55
+ return this;
56
+ }
57
+ /**
58
+ * Register multiple providers.
59
+ */
60
+ registerMany(providers) {
61
+ for (const provider of providers) {
62
+ this.register(provider);
63
+ }
64
+ return this;
65
+ }
66
+ /**
67
+ * Register all non-deferred providers.
68
+ */
69
+ async registerAll() {
70
+ for (const provider of this.providers) {
71
+ if (!this.registered.has(provider)) {
72
+ await provider.register();
73
+ this.registered.add(provider);
74
+ }
75
+ }
76
+ }
77
+ /**
78
+ * Boot all registered providers.
79
+ */
80
+ async bootAll() {
81
+ for (const provider of this.providers) {
82
+ if (!this.booted.has(provider) && this.registered.has(provider)) {
83
+ await provider.boot?.();
84
+ this.booted.add(provider);
85
+ }
86
+ }
87
+ this.allBooted = true;
88
+ if (this.deferredProviders.size > 0) {
89
+ this.container.deferredProviderLoader = (service) => this.loadDeferredProvider(service);
90
+ }
91
+ }
92
+ /**
93
+ * Load a deferred provider for a service.
94
+ */
95
+ async loadDeferredProvider(service) {
96
+ const provider = this.deferredProviders.get(service);
97
+ if (!provider) return;
98
+ if (!this.registered.has(provider)) {
99
+ await provider.register();
100
+ this.registered.add(provider);
101
+ this.providers.push(provider);
102
+ }
103
+ if (!this.booted.has(provider)) {
104
+ await provider.boot?.();
105
+ this.booted.add(provider);
106
+ }
107
+ for (const providedService of provider.provides()) {
108
+ this.deferredProviders.delete(providedService);
109
+ }
110
+ }
111
+ /**
112
+ * Check if a service is provided by a deferred provider.
113
+ */
114
+ isDeferredService(service) {
115
+ return this.deferredProviders.has(service);
116
+ }
117
+ /**
118
+ * Get all registered providers.
119
+ */
120
+ getProviders() {
121
+ return [...this.providers];
122
+ }
123
+ /**
124
+ * Get all deferred services.
125
+ */
126
+ getDeferredServices() {
127
+ return Array.from(this.deferredProviders.keys());
128
+ }
129
+ };
130
+
131
+ export {
132
+ ServiceProvider,
133
+ ProviderManager
134
+ };