@athosjs/pro 0.1.4-alpha

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 (94) hide show
  1. package/README.md +518 -0
  2. package/bootstrap.cjs +107 -0
  3. package/bootstrap.cjs.map +1 -0
  4. package/bootstrap.d.ts +8 -0
  5. package/bootstrap.d.ts.map +1 -0
  6. package/bootstrap.js +103 -0
  7. package/bootstrap.js.map +1 -0
  8. package/core/athos-application.cjs +362 -0
  9. package/core/athos-application.cjs.map +1 -0
  10. package/core/athos-application.d.ts +17 -0
  11. package/core/athos-application.d.ts.map +1 -0
  12. package/core/athos-application.js +357 -0
  13. package/core/athos-application.js.map +1 -0
  14. package/core/discovery.cjs +47 -0
  15. package/core/discovery.cjs.map +1 -0
  16. package/core/discovery.d.ts +6 -0
  17. package/core/discovery.d.ts.map +1 -0
  18. package/core/discovery.js +45 -0
  19. package/core/discovery.js.map +1 -0
  20. package/core/i18n.cjs +12 -0
  21. package/core/i18n.cjs.map +1 -0
  22. package/core/i18n.d.ts +4 -0
  23. package/core/i18n.d.ts.map +1 -0
  24. package/core/i18n.js +10 -0
  25. package/core/i18n.js.map +1 -0
  26. package/core/pipeline.cjs +251 -0
  27. package/core/pipeline.cjs.map +1 -0
  28. package/core/pipeline.d.ts +11 -0
  29. package/core/pipeline.d.ts.map +1 -0
  30. package/core/pipeline.js +246 -0
  31. package/core/pipeline.js.map +1 -0
  32. package/core/router-initializer.cjs +158 -0
  33. package/core/router-initializer.cjs.map +1 -0
  34. package/core/router-initializer.d.ts +26 -0
  35. package/core/router-initializer.d.ts.map +1 -0
  36. package/core/router-initializer.js +156 -0
  37. package/core/router-initializer.js.map +1 -0
  38. package/core/scanner.cjs +141 -0
  39. package/core/scanner.cjs.map +1 -0
  40. package/core/scanner.d.ts +7 -0
  41. package/core/scanner.d.ts.map +1 -0
  42. package/core/scanner.js +139 -0
  43. package/core/scanner.js.map +1 -0
  44. package/experimental.cjs +23 -0
  45. package/experimental.cjs.map +1 -0
  46. package/experimental.d.ts +9 -0
  47. package/experimental.d.ts.map +1 -0
  48. package/experimental.js +5 -0
  49. package/experimental.js.map +1 -0
  50. package/functions.cjs +67 -0
  51. package/functions.cjs.map +1 -0
  52. package/functions.d.ts +10 -0
  53. package/functions.d.ts.map +1 -0
  54. package/functions.js +62 -0
  55. package/functions.js.map +1 -0
  56. package/http-profile.cjs +48 -0
  57. package/http-profile.cjs.map +1 -0
  58. package/http-profile.d.ts +6 -0
  59. package/http-profile.d.ts.map +1 -0
  60. package/http-profile.js +44 -0
  61. package/http-profile.js.map +1 -0
  62. package/index.cjs +281 -0
  63. package/index.cjs.map +1 -0
  64. package/index.d.ts +23 -0
  65. package/index.d.ts.map +1 -0
  66. package/index.js +23 -0
  67. package/index.js.map +1 -0
  68. package/observability.cjs +191 -0
  69. package/observability.cjs.map +1 -0
  70. package/observability.d.ts +8 -0
  71. package/observability.d.ts.map +1 -0
  72. package/observability.js +188 -0
  73. package/observability.js.map +1 -0
  74. package/package.json +42 -0
  75. package/policies.cjs +30 -0
  76. package/policies.cjs.map +1 -0
  77. package/policies.d.ts +21 -0
  78. package/policies.d.ts.map +1 -0
  79. package/policies.js +27 -0
  80. package/policies.js.map +1 -0
  81. package/resilience.cjs +280 -0
  82. package/resilience.cjs.map +1 -0
  83. package/resilience.d.ts +6 -0
  84. package/resilience.d.ts.map +1 -0
  85. package/resilience.js +276 -0
  86. package/resilience.js.map +1 -0
  87. package/security.cjs +142 -0
  88. package/security.cjs.map +1 -0
  89. package/security.d.ts +11 -0
  90. package/security.d.ts.map +1 -0
  91. package/security.js +136 -0
  92. package/security.js.map +1 -0
  93. package/types.d.ts +3 -0
  94. package/types.d.ts.map +1 -0
@@ -0,0 +1,188 @@
1
+ import { ATHOS_STATE_KEYS } from '@athosjs/constants';
2
+ import { ATHOS_LOGGER_TOKEN, ATHOS_TELEMETRY_SINK_TOKEN } from '@athosjs/observability';
3
+
4
+ function attachProObservability(application, options = {}) {
5
+ if (options.enabled === false && !options.logger && !options.telemetrySink) {
6
+ return application;
7
+ }
8
+ const hooks = createProObservabilityHooks(application.kernel, options);
9
+ if (Object.keys(hooks).length === 0) {
10
+ return application;
11
+ }
12
+ application.hooks(hooks);
13
+ return application;
14
+ }
15
+ function createProObservabilityHooks(kernel, options = {}) {
16
+ const logger = resolveLogger(kernel, options);
17
+ const telemetrySink = resolveTelemetrySink(kernel, options);
18
+ if (!logger && !telemetrySink) {
19
+ return {};
20
+ }
21
+ const emitTelemetry = createBufferedTelemetryEmitter(telemetrySink, logger, options.maxPendingTelemetryEvents ?? 1024);
22
+ const logRequests = options.logRequests ?? "errors";
23
+ const sampleRate = normalizeSampleRate(options.sampleRate);
24
+ const alwaysSampleErrors = options.alwaysSampleErrors ?? true;
25
+ return {
26
+ onRequest (context) {
27
+ const hasLogger = logRequests === "all" && logger;
28
+ const willSample = sampleRate > 0 && telemetrySink;
29
+ if (!hasLogger && !willSample) return;
30
+ if (willSample && sampleRate < 1 && Math.random() > sampleRate) return;
31
+ const attributes = createBaseRequestAttributes(context);
32
+ if (willSample) {
33
+ emitTelemetry({
34
+ name: "http.request.started",
35
+ timestamp: Date.now(),
36
+ attributes
37
+ });
38
+ }
39
+ if (hasLogger) {
40
+ logger.info(formatRequestLog("started", attributes));
41
+ }
42
+ },
43
+ onResponse (context, response) {
44
+ const hasLogger = logRequests === "all" && logger;
45
+ const willSample = sampleRate > 0 && telemetrySink;
46
+ if (!hasLogger && !willSample) return;
47
+ if (willSample && sampleRate < 1 && Math.random() > sampleRate) return;
48
+ const metrics = context.state.get(ATHOS_STATE_KEYS.HTTP_REQUEST_METRICS);
49
+ const attributes = {
50
+ requestId: context.request.requestId,
51
+ method: context.originalRequest.method,
52
+ path: context.originalRequest.path,
53
+ status: response.status
54
+ };
55
+ if (metrics) {
56
+ if (metrics.durationMs !== undefined) attributes.durationMs = metrics.durationMs;
57
+ if (metrics.bodyBytes !== undefined) attributes.bodyBytes = metrics.bodyBytes;
58
+ if (metrics.aborted !== undefined) attributes.aborted = metrics.aborted;
59
+ }
60
+ attributes.phase = context.execution.phase;
61
+ if (willSample) {
62
+ emitTelemetry({
63
+ name: "http.request.completed",
64
+ timestamp: Date.now(),
65
+ attributes
66
+ });
67
+ }
68
+ if (hasLogger) {
69
+ logger.info(formatRequestLog("completed", attributes));
70
+ }
71
+ },
72
+ onError (context, error) {
73
+ const hasLogger = logRequests !== "none" && logger;
74
+ const willSample = sampleRate > 0 || alwaysSampleErrors;
75
+ if (!hasLogger && !willSample) return;
76
+ const havenError = error;
77
+ const attributes = {
78
+ requestId: context.request.requestId,
79
+ method: context.originalRequest.method,
80
+ path: context.originalRequest.path,
81
+ status: havenError?.status,
82
+ code: havenError?.code
83
+ };
84
+ if (willSample) {
85
+ const event = {
86
+ name: "http.request.failed",
87
+ timestamp: Date.now(),
88
+ level: "error",
89
+ attributes
90
+ };
91
+ if (shouldSampleEvent(event, sampleRate, alwaysSampleErrors)) {
92
+ emitTelemetry(event);
93
+ }
94
+ }
95
+ if (hasLogger) {
96
+ logger.error(formatRequestLog("failed", attributes));
97
+ }
98
+ }
99
+ };
100
+ }
101
+ function normalizeSampleRate(value) {
102
+ if (value === undefined) {
103
+ return 1;
104
+ }
105
+ if (Number.isNaN(value) || value < 0) {
106
+ return 0;
107
+ }
108
+ if (value > 1) {
109
+ return 1;
110
+ }
111
+ return value;
112
+ }
113
+ function shouldSampleEvent(event, sampleRate, alwaysSampleErrors) {
114
+ if (alwaysSampleErrors && event.level === "error") {
115
+ return true;
116
+ }
117
+ if (sampleRate >= 1) {
118
+ return true;
119
+ }
120
+ if (sampleRate <= 0) {
121
+ return false;
122
+ }
123
+ return deterministicSample(event) < sampleRate;
124
+ }
125
+ function resolveLogger(kernel, options) {
126
+ if (options.logger) {
127
+ return options.logger;
128
+ }
129
+ if (kernel.services.has(ATHOS_LOGGER_TOKEN)) {
130
+ return kernel.services.resolve(ATHOS_LOGGER_TOKEN);
131
+ }
132
+ return undefined;
133
+ }
134
+ function resolveTelemetrySink(kernel, options) {
135
+ if (options.telemetrySink) {
136
+ return options.telemetrySink;
137
+ }
138
+ if (kernel.services.has(ATHOS_TELEMETRY_SINK_TOKEN)) {
139
+ return kernel.services.resolve(ATHOS_TELEMETRY_SINK_TOKEN);
140
+ }
141
+ return undefined;
142
+ }
143
+ function createBufferedTelemetryEmitter(sink, logger, maxPendingTelemetryEvents) {
144
+ if (!sink) {
145
+ return ()=>undefined;
146
+ }
147
+ return (event)=>{
148
+ if (sink.emitBatch) {
149
+ sink.emitBatch([
150
+ event
151
+ ]);
152
+ } else {
153
+ sink.emit(event);
154
+ }
155
+ };
156
+ }
157
+ function createBaseRequestAttributes(context) {
158
+ return {
159
+ requestId: context.request.requestId,
160
+ method: context.originalRequest.method,
161
+ path: context.originalRequest.path,
162
+ ...context.route?.operationId ? {
163
+ operationId: context.route.operationId
164
+ } : {},
165
+ phase: context.execution.phase
166
+ };
167
+ }
168
+ function formatRequestLog(stage, attributes) {
169
+ return `[${stage}] ${attributes.method} ${attributes.path} (${attributes.requestId})`;
170
+ }
171
+ function deterministicSample(event) {
172
+ const seed = [
173
+ event.name,
174
+ event.level ?? "info",
175
+ String(event.attributes?.requestId ?? ""),
176
+ String(event.attributes?.path ?? ""),
177
+ String(event.timestamp)
178
+ ].join("|");
179
+ let hash = 2166136261;
180
+ for(let index = 0; index < seed.length; index += 1){
181
+ hash ^= seed.charCodeAt(index);
182
+ hash = Math.imul(hash, 16777619);
183
+ }
184
+ return (hash >>> 0) / 0xffffffff;
185
+ }
186
+
187
+ export { attachProObservability, createProObservabilityHooks };
188
+ //# sourceMappingURL=observability.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observability.js","sources":["../../../packages/pro/src/observability.ts"],"sourcesContent":["import { ATHOS_STATE_KEYS } from \"@athosjs/constants\";\nimport type { ApplicationKernel } from \"@athosjs/core\";\nimport type { HttpContext, HttpHooks, HttpRequestMetrics } from \"@athosjs/http\";\nimport type { HttpApplication } from \"@athosjs/http/experimental\";\nimport {\n\ttype ExecutionTelemetryEvent,\n\ttype ExecutionTelemetrySink,\n\tATHOS_LOGGER_TOKEN,\n\tATHOS_TELEMETRY_SINK_TOKEN,\n\ttype AthosLogger,\n} from \"@athosjs/observability\";\nimport type { ProObservabilityOptions } from \"@athosjs/types/pro\";\n\nexport type { ProObservabilityOptions };\n\nexport function attachProObservability(\n\tapplication: HttpApplication,\n\toptions: ProObservabilityOptions = {},\n): HttpApplication {\n\tif (options.enabled === false && !options.logger && !options.telemetrySink) {\n\t\treturn application;\n\t}\n\tconst hooks = createProObservabilityHooks(application.kernel, options);\n\tif (Object.keys(hooks).length === 0) {\n\t\treturn application;\n\t}\n\tapplication.hooks(hooks);\n\treturn application;\n}\n\nexport function createProObservabilityHooks(\n\tkernel: ApplicationKernel,\n\toptions: ProObservabilityOptions = {},\n): HttpHooks {\n\tconst logger = resolveLogger(kernel, options);\n\tconst telemetrySink = resolveTelemetrySink(kernel, options);\n\tif (!logger && !telemetrySink) {\n\t\treturn {};\n\t}\n\tconst emitTelemetry = createBufferedTelemetryEmitter(\n\t\ttelemetrySink,\n\t\tlogger,\n\t\toptions.maxPendingTelemetryEvents ?? 1024,\n\t);\n\tconst logRequests = options.logRequests ?? \"errors\";\n\tconst sampleRate = normalizeSampleRate(options.sampleRate);\n\tconst alwaysSampleErrors = options.alwaysSampleErrors ?? true;\n\n\treturn {\n\t\tonRequest(context: HttpContext): void {\n\t\t\tconst hasLogger = logRequests === \"all\" && logger;\n\t\t\tconst willSample = sampleRate > 0 && telemetrySink;\n\n\t\t\tif (!hasLogger && !willSample) return;\n\n\t\t\tif (willSample && sampleRate < 1 && Math.random() > sampleRate) return;\n\n\t\t\tconst attributes = createBaseRequestAttributes(context);\n\n\t\t\tif (willSample) {\n\t\t\t\temitTelemetry({\n\t\t\t\t\tname: \"http.request.started\",\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\tattributes,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (hasLogger) {\n\t\t\t\tlogger.info(formatRequestLog(\"started\", attributes));\n\t\t\t}\n\t\t},\n\t\tonResponse(context: HttpContext, response): void {\n\t\t\tconst hasLogger = logRequests === \"all\" && logger;\n\t\t\tconst willSample = sampleRate > 0 && telemetrySink;\n\n\t\t\tif (!hasLogger && !willSample) return;\n\n\t\t\tif (willSample && sampleRate < 1 && Math.random() > sampleRate) return;\n\n\t\t\tconst metrics = (context.state as { get<T>(k: string | symbol): T | undefined }).get<HttpRequestMetrics>(\n\t\t\t\tATHOS_STATE_KEYS.HTTP_REQUEST_METRICS,\n\t\t\t);\n\t\t\tconst attributes: Record<string, unknown> = {\n\t\t\t\trequestId: context.request.requestId,\n\t\t\t\tmethod: context.originalRequest.method,\n\t\t\t\tpath: context.originalRequest.path,\n\t\t\t\tstatus: response.status,\n\t\t\t};\n\t\t\tif (metrics) {\n\t\t\t\tif (metrics.durationMs !== undefined) attributes.durationMs = metrics.durationMs;\n\t\t\t\tif (metrics.bodyBytes !== undefined) attributes.bodyBytes = metrics.bodyBytes;\n\t\t\t\tif (metrics.aborted !== undefined) attributes.aborted = metrics.aborted;\n\t\t\t}\n\t\t\tattributes.phase = context.execution.phase;\n\n\t\t\tif (willSample) {\n\t\t\t\temitTelemetry({\n\t\t\t\t\tname: \"http.request.completed\",\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\tattributes,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (hasLogger) {\n\t\t\t\tlogger.info(formatRequestLog(\"completed\", attributes));\n\t\t\t}\n\t\t},\n\t\tonError(context: HttpContext, error: unknown): void {\n\t\t\tconst hasLogger = logRequests !== \"none\" && logger;\n\t\t\tconst willSample = sampleRate > 0 || alwaysSampleErrors;\n\n\t\t\tif (!hasLogger && !willSample) return;\n\n\t\t\tconst havenError = error as Record<string, unknown>;\n\t\t\tconst attributes = {\n\t\t\t\trequestId: context.request.requestId,\n\t\t\t\tmethod: context.originalRequest.method,\n\t\t\t\tpath: context.originalRequest.path,\n\t\t\t\tstatus: havenError?.status,\n\t\t\t\tcode: havenError?.code,\n\t\t\t};\n\n\t\t\tif (willSample) {\n\t\t\t\tconst event: ExecutionTelemetryEvent = {\n\t\t\t\t\tname: \"http.request.failed\",\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\tlevel: \"error\",\n\t\t\t\t\tattributes,\n\t\t\t\t};\n\t\t\t\tif (shouldSampleEvent(event, sampleRate, alwaysSampleErrors)) {\n\t\t\t\t\temitTelemetry(event);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (hasLogger) {\n\t\t\t\tlogger.error(formatRequestLog(\"failed\", attributes));\n\t\t\t}\n\t\t},\n\t};\n}\n\nfunction normalizeSampleRate(value: number | undefined): number {\n\tif (value === undefined) {\n\t\treturn 1;\n\t}\n\n\tif (Number.isNaN(value) || value < 0) {\n\t\treturn 0;\n\t}\n\n\tif (value > 1) {\n\t\treturn 1;\n\t}\n\n\treturn value;\n}\n\nfunction shouldSampleEvent(event: ExecutionTelemetryEvent, sampleRate: number, alwaysSampleErrors: boolean): boolean {\n\tif (alwaysSampleErrors && event.level === \"error\") {\n\t\treturn true;\n\t}\n\n\tif (sampleRate >= 1) {\n\t\treturn true;\n\t}\n\n\tif (sampleRate <= 0) {\n\t\treturn false;\n\t}\n\n\treturn deterministicSample(event) < sampleRate;\n}\n\nfunction resolveLogger(kernel: ApplicationKernel, options: ProObservabilityOptions): AthosLogger | undefined {\n\tif (options.logger) {\n\t\treturn options.logger as AthosLogger;\n\t}\n\n\tif (kernel.services.has(ATHOS_LOGGER_TOKEN)) {\n\t\treturn kernel.services.resolve(ATHOS_LOGGER_TOKEN);\n\t}\n\n\treturn undefined;\n}\n\nfunction resolveTelemetrySink(\n\tkernel: ApplicationKernel,\n\toptions: ProObservabilityOptions,\n): ExecutionTelemetrySink | undefined {\n\tif (options.telemetrySink) {\n\t\treturn options.telemetrySink as ExecutionTelemetrySink;\n\t}\n\n\tif (kernel.services.has(ATHOS_TELEMETRY_SINK_TOKEN)) {\n\t\treturn kernel.services.resolve(ATHOS_TELEMETRY_SINK_TOKEN);\n\t}\n\n\treturn undefined;\n}\n\nfunction createBufferedTelemetryEmitter(\n\tsink: ExecutionTelemetrySink | undefined,\n\tlogger: AthosLogger | undefined,\n\tmaxPendingTelemetryEvents: number,\n): (event: ExecutionTelemetryEvent) => void {\n\tif (!sink) {\n\t\treturn () => undefined;\n\t}\n\n\treturn (event: ExecutionTelemetryEvent) => {\n\t\tif (sink.emitBatch) {\n\t\t\tsink.emitBatch([event]);\n\t\t} else {\n\t\t\tsink.emit(event);\n\t\t}\n\t};\n}\n\nasync function flushTelemetryQueue(\n\tsink: ExecutionTelemetrySink,\n\tevents: readonly ExecutionTelemetryEvent[],\n\tlogger?: AthosLogger,\n): Promise<void> {\n\ttry {\n\t\tif (sink.emitBatch) {\n\t\t\tawait sink.emitBatch(events);\n\t\t} else {\n\t\t\tfor (const event of events) {\n\t\t\t\tawait sink.emit(event);\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\tlogger?.warn(\n\t\t\t\"Failed to flush telemetry batch.\",\n\t\t\terror instanceof Error ? error.message : String(error),\n\t\t\t`events: ${events.length}`,\n\t\t);\n\t}\n}\n\nfunction createBaseRequestAttributes(context: HttpContext): Record<string, unknown> {\n\treturn {\n\t\trequestId: context.request.requestId,\n\t\tmethod: context.originalRequest.method,\n\t\tpath: context.originalRequest.path,\n\t\t...(context.route?.operationId ? { operationId: context.route.operationId } : {}),\n\t\tphase: context.execution.phase,\n\t};\n}\n\nfunction formatRequestLog(stage: string, attributes: Record<string, unknown>): string {\n\treturn `[${stage}] ${attributes.method} ${attributes.path} (${attributes.requestId})`;\n}\n\nfunction deterministicSample(event: ExecutionTelemetryEvent): number {\n\tconst seed = [\n\t\tevent.name,\n\t\tevent.level ?? \"info\",\n\t\tString(event.attributes?.requestId ?? \"\"),\n\t\tString(event.attributes?.path ?? \"\"),\n\t\tString(event.timestamp),\n\t].join(\"|\");\n\tlet hash = 2166136261;\n\n\tfor (let index = 0; index < seed.length; index += 1) {\n\t\thash ^= seed.charCodeAt(index);\n\t\thash = Math.imul(hash, 16777619);\n\t}\n\n\treturn (hash >>> 0) / 0xffffffff;\n}\n"],"names":["attachProObservability","application","options","enabled","logger","telemetrySink","hooks","createProObservabilityHooks","kernel","Object","keys","length","resolveLogger","resolveTelemetrySink","emitTelemetry","createBufferedTelemetryEmitter","maxPendingTelemetryEvents","logRequests","sampleRate","normalizeSampleRate","alwaysSampleErrors","onRequest","context","hasLogger","willSample","Math","random","attributes","createBaseRequestAttributes","name","timestamp","Date","now","info","formatRequestLog","onResponse","response","metrics","state","get","ATHOS_STATE_KEYS","HTTP_REQUEST_METRICS","requestId","request","method","originalRequest","path","status","durationMs","undefined","bodyBytes","aborted","phase","execution","onError","error","havenError","code","event","level","shouldSampleEvent","value","Number","isNaN","deterministicSample","services","has","ATHOS_LOGGER_TOKEN","resolve","ATHOS_TELEMETRY_SINK_TOKEN","sink","emitBatch","emit","route","operationId","stage","seed","String","join","hash","index","charCodeAt","imul"],"mappings":";;;AAeO,SAASA,sBAAAA,CACfC,WAA4B,EAC5BC,OAAAA,GAAmC,EAAE,EAAA;IAErC,IAAIA,OAAAA,CAAQC,OAAO,KAAK,KAAA,IAAS,CAACD,OAAAA,CAAQE,MAAM,IAAI,CAACF,OAAAA,CAAQG,aAAa,EAAE;QAC3E,OAAOJ,WAAAA;AACR,IAAA;AACA,IAAA,MAAMK,KAAAA,GAAQC,2BAAAA,CAA4BN,WAAAA,CAAYO,MAAM,EAAEN,OAAAA,CAAAA;AAC9D,IAAA,IAAIO,OAAOC,IAAI,CAACJ,KAAAA,CAAAA,CAAOK,MAAM,KAAK,CAAA,EAAG;QACpC,OAAOV,WAAAA;AACR,IAAA;AACAA,IAAAA,WAAAA,CAAYK,KAAK,CAACA,KAAAA,CAAAA;IAClB,OAAOL,WAAAA;AACR;AAEO,SAASM,2BAAAA,CACfC,MAAyB,EACzBN,OAAAA,GAAmC,EAAE,EAAA;IAErC,MAAME,MAAAA,GAASQ,cAAcJ,MAAAA,EAAQN,OAAAA,CAAAA;IACrC,MAAMG,aAAAA,GAAgBQ,qBAAqBL,MAAAA,EAAQN,OAAAA,CAAAA;IACnD,IAAI,CAACE,MAAAA,IAAU,CAACC,aAAAA,EAAe;AAC9B,QAAA,OAAO,EAAC;AACT,IAAA;AACA,IAAA,MAAMS,gBAAgBC,8BAAAA,CACrBV,aAAAA,EACAD,MAAAA,EACAF,OAAAA,CAAQc,yBAAyB,IAAI,IAAA,CAAA;IAEtC,MAAMC,WAAAA,GAAcf,OAAAA,CAAQe,WAAW,IAAI,QAAA;IAC3C,MAAMC,UAAAA,GAAaC,mBAAAA,CAAoBjB,OAAAA,CAAQgB,UAAU,CAAA;IACzD,MAAME,kBAAAA,GAAqBlB,OAAAA,CAAQkB,kBAAkB,IAAI,IAAA;IAEzD,OAAO;AACNC,QAAAA,SAAAA,CAAAA,CAAUC,OAAoB,EAAA;YAC7B,MAAMC,SAAAA,GAAYN,gBAAgB,KAAA,IAASb,MAAAA;YAC3C,MAAMoB,UAAAA,GAAaN,aAAa,CAAA,IAAKb,aAAAA;YAErC,IAAI,CAACkB,SAAAA,IAAa,CAACC,UAAAA,EAAY;AAE/B,YAAA,IAAIA,cAAcN,UAAAA,GAAa,CAAA,IAAKO,IAAAA,CAAKC,MAAM,KAAKR,UAAAA,EAAY;AAEhE,YAAA,MAAMS,aAAaC,2BAAAA,CAA4BN,OAAAA,CAAAA;AAE/C,YAAA,IAAIE,UAAAA,EAAY;gBACfV,aAAAA,CAAc;oBACbe,IAAAA,EAAM,sBAAA;AACNC,oBAAAA,SAAAA,EAAWC,KAAKC,GAAG,EAAA;AACnBL,oBAAAA;AACD,iBAAA,CAAA;AACD,YAAA;AAEA,YAAA,IAAIJ,SAAAA,EAAW;gBACdnB,MAAAA,CAAO6B,IAAI,CAACC,gBAAAA,CAAiB,SAAA,EAAWP,UAAAA,CAAAA,CAAAA;AACzC,YAAA;AACD,QAAA,CAAA;QACAQ,UAAAA,CAAAA,CAAWb,OAAoB,EAAEc,QAAQ,EAAA;YACxC,MAAMb,SAAAA,GAAYN,gBAAgB,KAAA,IAASb,MAAAA;YAC3C,MAAMoB,UAAAA,GAAaN,aAAa,CAAA,IAAKb,aAAAA;YAErC,IAAI,CAACkB,SAAAA,IAAa,CAACC,UAAAA,EAAY;AAE/B,YAAA,IAAIA,cAAcN,UAAAA,GAAa,CAAA,IAAKO,IAAAA,CAAKC,MAAM,KAAKR,UAAAA,EAAY;YAEhE,MAAMmB,OAAAA,GAAU,OAACf,CAAQgB,KAAK,CAAmDC,GAAG,CACnFC,iBAAiBC,oBAAoB,CAAA;AAEtC,YAAA,MAAMd,UAAAA,GAAsC;gBAC3Ce,SAAAA,EAAWpB,OAAAA,CAAQqB,OAAO,CAACD,SAAS;gBACpCE,MAAAA,EAAQtB,OAAAA,CAAQuB,eAAe,CAACD,MAAM;gBACtCE,IAAAA,EAAMxB,OAAAA,CAAQuB,eAAe,CAACC,IAAI;AAClCC,gBAAAA,MAAAA,EAAQX,SAASW;AAClB,aAAA;AACA,YAAA,IAAIV,OAAAA,EAAS;gBACZ,IAAIA,OAAAA,CAAQW,UAAU,KAAKC,SAAAA,EAAWtB,WAAWqB,UAAU,GAAGX,QAAQW,UAAU;gBAChF,IAAIX,OAAAA,CAAQa,SAAS,KAAKD,SAAAA,EAAWtB,WAAWuB,SAAS,GAAGb,QAAQa,SAAS;gBAC7E,IAAIb,OAAAA,CAAQc,OAAO,KAAKF,SAAAA,EAAWtB,WAAWwB,OAAO,GAAGd,QAAQc,OAAO;AACxE,YAAA;AACAxB,YAAAA,UAAAA,CAAWyB,KAAK,GAAG9B,OAAAA,CAAQ+B,SAAS,CAACD,KAAK;AAE1C,YAAA,IAAI5B,UAAAA,EAAY;gBACfV,aAAAA,CAAc;oBACbe,IAAAA,EAAM,wBAAA;AACNC,oBAAAA,SAAAA,EAAWC,KAAKC,GAAG,EAAA;AACnBL,oBAAAA;AACD,iBAAA,CAAA;AACD,YAAA;AAEA,YAAA,IAAIJ,SAAAA,EAAW;gBACdnB,MAAAA,CAAO6B,IAAI,CAACC,gBAAAA,CAAiB,WAAA,EAAaP,UAAAA,CAAAA,CAAAA;AAC3C,YAAA;AACD,QAAA,CAAA;QACA2B,OAAAA,CAAAA,CAAQhC,OAAoB,EAAEiC,KAAc,EAAA;YAC3C,MAAMhC,SAAAA,GAAYN,gBAAgB,MAAA,IAAUb,MAAAA;YAC5C,MAAMoB,UAAAA,GAAaN,aAAa,CAAA,IAAKE,kBAAAA;YAErC,IAAI,CAACG,SAAAA,IAAa,CAACC,UAAAA,EAAY;AAE/B,YAAA,MAAMgC,UAAAA,GAAaD,KAAAA;AACnB,YAAA,MAAM5B,UAAAA,GAAa;gBAClBe,SAAAA,EAAWpB,OAAAA,CAAQqB,OAAO,CAACD,SAAS;gBACpCE,MAAAA,EAAQtB,OAAAA,CAAQuB,eAAe,CAACD,MAAM;gBACtCE,IAAAA,EAAMxB,OAAAA,CAAQuB,eAAe,CAACC,IAAI;AAClCC,gBAAAA,MAAAA,EAAQS,UAAAA,EAAYT,MAAAA;AACpBU,gBAAAA,IAAAA,EAAMD,UAAAA,EAAYC;AACnB,aAAA;AAEA,YAAA,IAAIjC,UAAAA,EAAY;AACf,gBAAA,MAAMkC,KAAAA,GAAiC;oBACtC7B,IAAAA,EAAM,qBAAA;AACNC,oBAAAA,SAAAA,EAAWC,KAAKC,GAAG,EAAA;oBACnB2B,KAAAA,EAAO,OAAA;AACPhC,oBAAAA;AACD,iBAAA;gBACA,IAAIiC,iBAAAA,CAAkBF,KAAAA,EAAOxC,UAAAA,EAAYE,kBAAAA,CAAAA,EAAqB;oBAC7DN,aAAAA,CAAc4C,KAAAA,CAAAA;AACf,gBAAA;AACD,YAAA;AAEA,YAAA,IAAInC,SAAAA,EAAW;gBACdnB,MAAAA,CAAOmD,KAAK,CAACrB,gBAAAA,CAAiB,QAAA,EAAUP,UAAAA,CAAAA,CAAAA;AACzC,YAAA;AACD,QAAA;AACD,KAAA;AACD;AAEA,SAASR,oBAAoB0C,KAAyB,EAAA;AACrD,IAAA,IAAIA,UAAUZ,SAAAA,EAAW;QACxB,OAAO,CAAA;AACR,IAAA;AAEA,IAAA,IAAIa,MAAAA,CAAOC,KAAK,CAACF,KAAAA,CAAAA,IAAUA,QAAQ,CAAA,EAAG;QACrC,OAAO,CAAA;AACR,IAAA;AAEA,IAAA,IAAIA,QAAQ,CAAA,EAAG;QACd,OAAO,CAAA;AACR,IAAA;IAEA,OAAOA,KAAAA;AACR;AAEA,SAASD,iBAAAA,CAAkBF,KAA8B,EAAExC,UAAkB,EAAEE,kBAA2B,EAAA;AACzG,IAAA,IAAIA,kBAAAA,IAAsBsC,KAAAA,CAAMC,KAAK,KAAK,OAAA,EAAS;QAClD,OAAO,IAAA;AACR,IAAA;AAEA,IAAA,IAAIzC,cAAc,CAAA,EAAG;QACpB,OAAO,IAAA;AACR,IAAA;AAEA,IAAA,IAAIA,cAAc,CAAA,EAAG;QACpB,OAAO,KAAA;AACR,IAAA;AAEA,IAAA,OAAO8C,oBAAoBN,KAAAA,CAAAA,GAASxC,UAAAA;AACrC;AAEA,SAASN,aAAAA,CAAcJ,MAAyB,EAAEN,OAAgC,EAAA;IACjF,IAAIA,OAAAA,CAAQE,MAAM,EAAE;AACnB,QAAA,OAAOF,QAAQE,MAAM;AACtB,IAAA;AAEA,IAAA,IAAII,MAAAA,CAAOyD,QAAQ,CAACC,GAAG,CAACC,kBAAAA,CAAAA,EAAqB;AAC5C,QAAA,OAAO3D,MAAAA,CAAOyD,QAAQ,CAACG,OAAO,CAACD,kBAAAA,CAAAA;AAChC,IAAA;IAEA,OAAOlB,SAAAA;AACR;AAEA,SAASpC,oBAAAA,CACRL,MAAyB,EACzBN,OAAgC,EAAA;IAEhC,IAAIA,OAAAA,CAAQG,aAAa,EAAE;AAC1B,QAAA,OAAOH,QAAQG,aAAa;AAC7B,IAAA;AAEA,IAAA,IAAIG,MAAAA,CAAOyD,QAAQ,CAACC,GAAG,CAACG,0BAAAA,CAAAA,EAA6B;AACpD,QAAA,OAAO7D,MAAAA,CAAOyD,QAAQ,CAACG,OAAO,CAACC,0BAAAA,CAAAA;AAChC,IAAA;IAEA,OAAOpB,SAAAA;AACR;AAEA,SAASlC,8BAAAA,CACRuD,IAAwC,EACxClE,MAA+B,EAC/BY,yBAAiC,EAAA;AAEjC,IAAA,IAAI,CAACsD,IAAAA,EAAM;AACV,QAAA,OAAO,IAAMrB,SAAAA;AACd,IAAA;AAEA,IAAA,OAAO,CAACS,KAAAA,GAAAA;QACP,IAAIY,IAAAA,CAAKC,SAAS,EAAE;AACnBD,YAAAA,IAAAA,CAAKC,SAAS,CAAC;AAACb,gBAAAA;AAAM,aAAA,CAAA;QACvB,CAAA,MAAO;AACNY,YAAAA,IAAAA,CAAKE,IAAI,CAACd,KAAAA,CAAAA;AACX,QAAA;AACD,IAAA,CAAA;AACD;AAwBA,SAAS9B,4BAA4BN,OAAoB,EAAA;IACxD,OAAO;QACNoB,SAAAA,EAAWpB,OAAAA,CAAQqB,OAAO,CAACD,SAAS;QACpCE,MAAAA,EAAQtB,OAAAA,CAAQuB,eAAe,CAACD,MAAM;QACtCE,IAAAA,EAAMxB,OAAAA,CAAQuB,eAAe,CAACC,IAAI;QAClC,GAAIxB,OAAAA,CAAQmD,KAAK,EAAEC,WAAAA,GAAc;YAAEA,WAAAA,EAAapD,OAAAA,CAAQmD,KAAK,CAACC;AAAY,SAAA,GAAI,EAAE;QAChFtB,KAAAA,EAAO9B,OAAAA,CAAQ+B,SAAS,CAACD;AAC1B,KAAA;AACD;AAEA,SAASlB,gBAAAA,CAAiByC,KAAa,EAAEhD,UAAmC,EAAA;IAC3E,OAAO,CAAC,CAAC,EAAEgD,KAAAA,CAAM,EAAE,EAAEhD,UAAAA,CAAWiB,MAAM,CAAC,CAAC,EAAEjB,UAAAA,CAAWmB,IAAI,CAAC,EAAE,EAAEnB,WAAWe,SAAS,CAAC,CAAC,CAAC;AACtF;AAEA,SAASsB,oBAAoBN,KAA8B,EAAA;AAC1D,IAAA,MAAMkB,IAAAA,GAAO;AACZlB,QAAAA,KAAAA,CAAM7B,IAAI;AACV6B,QAAAA,KAAAA,CAAMC,KAAK,IAAI,MAAA;QACfkB,MAAAA,CAAOnB,KAAAA,CAAM/B,UAAU,EAAEe,SAAAA,IAAa,EAAA,CAAA;QACtCmC,MAAAA,CAAOnB,KAAAA,CAAM/B,UAAU,EAAEmB,IAAAA,IAAQ,EAAA,CAAA;AACjC+B,QAAAA,MAAAA,CAAOnB,MAAM5B,SAAS;AACtB,KAAA,CAACgD,IAAI,CAAC,GAAA,CAAA;AACP,IAAA,IAAIC,IAAAA,GAAO,UAAA;IAEX,IAAK,IAAIC,QAAQ,CAAA,EAAGA,KAAAA,GAAQJ,KAAKjE,MAAM,EAAEqE,SAAS,CAAA,CAAG;QACpDD,IAAAA,IAAQH,IAAAA,CAAKK,UAAU,CAACD,KAAAA,CAAAA;QACxBD,IAAAA,GAAOtD,IAAAA,CAAKyD,IAAI,CAACH,IAAAA,EAAM,QAAA,CAAA;AACxB,IAAA;AAEA,IAAA,OAAO,CAACA,IAAAA,KAAS,CAAA,IAAK,UAAA;AACvB;;;;"}
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@athosjs/pro",
3
+ "version": "0.1.4-alpha",
4
+ "private": false,
5
+ "type": "module",
6
+ "description": "Opinionated pro product assembly for Athos",
7
+ "homepage": "https://athosjs-3695tqux2-neversonsilvas-projects.vercel.app",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/neverson-silva/athosjs.git"
11
+ },
12
+ "main": "./index.js",
13
+ "module": "./index.js",
14
+ "types": "./index.d.ts",
15
+ "exports": {
16
+ ".": {
17
+ "types": "./index.d.ts",
18
+ "import": "./index.js",
19
+ "require": "./index.js",
20
+ "default": "./index.js"
21
+ },
22
+ "./experimental": {
23
+ "types": "./experimental.d.ts",
24
+ "import": "./experimental.js",
25
+ "require": "./experimental.js",
26
+ "default": "./experimental.js"
27
+ }
28
+ },
29
+ "dependencies": {
30
+ "@athosjs/openapi": "0.1.4-alpha",
31
+ "@athosjs/http": "0.1.4-alpha",
32
+ "@athosjs/i18n": "0.1.4-alpha",
33
+ "@athosjs/core": "0.1.4-alpha",
34
+ "@athosjs/metadata": "0.1.4-alpha",
35
+ "@athosjs/runtime": "0.1.4-alpha",
36
+ "@athosjs/config": "0.1.4-alpha",
37
+ "@athosjs/observability": "0.1.4-alpha",
38
+ "@athosjs/constants": "0.1.4-alpha",
39
+ "@athosjs/di": "0.1.4-alpha",
40
+ "@athosjs/module": "0.1.4-alpha"
41
+ }
42
+ }
package/policies.cjs ADDED
@@ -0,0 +1,30 @@
1
+ 'use strict';
2
+
3
+ var metadata = require('@athosjs/metadata');
4
+
5
+ const USE_POLICY_METADATA_KEY = Symbol("athos:pro:usePolicy");
6
+ /**
7
+ * Attaches a policy class to a route handler.
8
+ *
9
+ * The policy is resolved from the DI container and its `check()` method
10
+ * is called before the route handler runs.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * @Controller()
15
+ * export class AdminController {
16
+ * @UsePolicy(AuthPolicy)
17
+ * @Get("/admin")
18
+ * getAdmin() { ... }
19
+ * }
20
+ * ```
21
+ */ function UsePolicy(policyClass) {
22
+ return (target, propertyKey, descriptor)=>{
23
+ metadata.defineMetadata(target.constructor, USE_POLICY_METADATA_KEY, policyClass, propertyKey);
24
+ return descriptor;
25
+ };
26
+ }
27
+
28
+ exports.USE_POLICY_METADATA_KEY = USE_POLICY_METADATA_KEY;
29
+ exports.UsePolicy = UsePolicy;
30
+ //# sourceMappingURL=policies.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policies.cjs","sources":["../../../packages/pro/src/policies.ts"],"sourcesContent":["import { defineMetadata } from \"@athosjs/metadata\";\n\nexport const USE_POLICY_METADATA_KEY = Symbol(\"athos:pro:usePolicy\");\n\n/**\n * Attaches a policy class to a route handler.\n *\n * The policy is resolved from the DI container and its `check()` method\n * is called before the route handler runs.\n *\n * @example\n * ```ts\n * @Controller()\n * export class AdminController {\n * @UsePolicy(AuthPolicy)\n * @Get(\"/admin\")\n * getAdmin() { ... }\n * }\n * ```\n */\nexport function UsePolicy(\n\tpolicyClass: new (...args: never[]) => { check(context: unknown): boolean | Promise<boolean> },\n): MethodDecorator {\n\treturn (target, propertyKey, descriptor) => {\n\t\tdefineMetadata(target.constructor, USE_POLICY_METADATA_KEY, policyClass, propertyKey);\n\t\treturn descriptor;\n\t};\n}\n"],"names":["USE_POLICY_METADATA_KEY","Symbol","UsePolicy","policyClass","target","propertyKey","descriptor","defineMetadata"],"mappings":";;;;AAEO,MAAMA,uBAAAA,GAA0BC,MAAAA,CAAO,qBAAA;AAE9C;;;;;;;;;;;;;;;IAgBO,SAASC,SAAAA,CACfC,WAA8F,EAAA;IAE9F,OAAO,CAACC,QAAQC,WAAAA,EAAaC,UAAAA,GAAAA;AAC5BC,QAAAA,uBAAAA,CAAeH,MAAAA,CAAO,WAAW,EAAEJ,uBAAAA,EAAyBG,WAAAA,EAAaE,WAAAA,CAAAA;QACzE,OAAOC,UAAAA;AACR,IAAA,CAAA;AACD;;;;;"}
package/policies.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ export declare const USE_POLICY_METADATA_KEY: unique symbol;
2
+ /**
3
+ * Attaches a policy class to a route handler.
4
+ *
5
+ * The policy is resolved from the DI container and its `check()` method
6
+ * is called before the route handler runs.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * @Controller()
11
+ * export class AdminController {
12
+ * @UsePolicy(AuthPolicy)
13
+ * @Get("/admin")
14
+ * getAdmin() { ... }
15
+ * }
16
+ * ```
17
+ */
18
+ export declare function UsePolicy(policyClass: new (...args: never[]) => {
19
+ check(context: unknown): boolean | Promise<boolean>;
20
+ }): MethodDecorator;
21
+ //# sourceMappingURL=policies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policies.d.ts","sourceRoot":"","sources":["../../../../../../packages/pro/src/policies.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,uBAAuB,eAAgC,CAAC;AAErE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CACxB,WAAW,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK;IAAE,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CAAE,GAC5F,eAAe,CAKjB"}
package/policies.js ADDED
@@ -0,0 +1,27 @@
1
+ import { defineMetadata } from '@athosjs/metadata';
2
+
3
+ const USE_POLICY_METADATA_KEY = Symbol("athos:pro:usePolicy");
4
+ /**
5
+ * Attaches a policy class to a route handler.
6
+ *
7
+ * The policy is resolved from the DI container and its `check()` method
8
+ * is called before the route handler runs.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * @Controller()
13
+ * export class AdminController {
14
+ * @UsePolicy(AuthPolicy)
15
+ * @Get("/admin")
16
+ * getAdmin() { ... }
17
+ * }
18
+ * ```
19
+ */ function UsePolicy(policyClass) {
20
+ return (target, propertyKey, descriptor)=>{
21
+ defineMetadata(target.constructor, USE_POLICY_METADATA_KEY, policyClass, propertyKey);
22
+ return descriptor;
23
+ };
24
+ }
25
+
26
+ export { USE_POLICY_METADATA_KEY, UsePolicy };
27
+ //# sourceMappingURL=policies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policies.js","sources":["../../../packages/pro/src/policies.ts"],"sourcesContent":["import { defineMetadata } from \"@athosjs/metadata\";\n\nexport const USE_POLICY_METADATA_KEY = Symbol(\"athos:pro:usePolicy\");\n\n/**\n * Attaches a policy class to a route handler.\n *\n * The policy is resolved from the DI container and its `check()` method\n * is called before the route handler runs.\n *\n * @example\n * ```ts\n * @Controller()\n * export class AdminController {\n * @UsePolicy(AuthPolicy)\n * @Get(\"/admin\")\n * getAdmin() { ... }\n * }\n * ```\n */\nexport function UsePolicy(\n\tpolicyClass: new (...args: never[]) => { check(context: unknown): boolean | Promise<boolean> },\n): MethodDecorator {\n\treturn (target, propertyKey, descriptor) => {\n\t\tdefineMetadata(target.constructor, USE_POLICY_METADATA_KEY, policyClass, propertyKey);\n\t\treturn descriptor;\n\t};\n}\n"],"names":["USE_POLICY_METADATA_KEY","Symbol","UsePolicy","policyClass","target","propertyKey","descriptor","defineMetadata"],"mappings":";;AAEO,MAAMA,uBAAAA,GAA0BC,MAAAA,CAAO,qBAAA;AAE9C;;;;;;;;;;;;;;;IAgBO,SAASC,SAAAA,CACfC,WAA8F,EAAA;IAE9F,OAAO,CAACC,QAAQC,WAAAA,EAAaC,UAAAA,GAAAA;AAC5BC,QAAAA,cAAAA,CAAeH,MAAAA,CAAO,WAAW,EAAEJ,uBAAAA,EAAyBG,WAAAA,EAAaE,WAAAA,CAAAA;QACzE,OAAOC,UAAAA;AACR,IAAA,CAAA;AACD;;;;"}
package/resilience.cjs ADDED
@@ -0,0 +1,280 @@
1
+ 'use strict';
2
+
3
+ var constants = require('@athosjs/constants');
4
+ var core = require('@athosjs/core');
5
+
6
+ function createConcurrencyLimiter(options) {
7
+ if (options.maxConcurrency < 1) {
8
+ throw core.createAthosError(constants.ATHOS_ERROR_CODES.OPERATION_OVERLOADED, "Concurrency limiter requires maxConcurrency to be greater than zero.");
9
+ }
10
+ const queue = [];
11
+ let queueOffset = 0;
12
+ let activeCount = 0;
13
+ let pendingCount = 0;
14
+ const pump = ()=>{
15
+ while(activeCount < options.maxConcurrency && pendingCount > 0){
16
+ const next = queue[queueOffset];
17
+ queue[queueOffset] = undefined;
18
+ queueOffset++;
19
+ if (!next) {
20
+ continue;
21
+ }
22
+ pendingCount -= 1;
23
+ if (queueOffset > 1000) {
24
+ queue.splice(0, queueOffset);
25
+ queueOffset = 0;
26
+ }
27
+ runEntry(next);
28
+ }
29
+ };
30
+ const runEntry = (entry)=>{
31
+ if (entry.signal && entry.abortHandler) {
32
+ entry.signal.removeEventListener("abort", entry.abortHandler);
33
+ entry.abortHandler = undefined;
34
+ }
35
+ if (entry.signal?.aborted) {
36
+ entry.reject(createOverloadedAbortError("Queued operation was aborted before execution."));
37
+ pump();
38
+ return;
39
+ }
40
+ activeCount += 1;
41
+ const result = entry.operation(entry.signal);
42
+ if (result instanceof Promise) {
43
+ result.then(entry.resolve, entry.reject).finally(()=>{
44
+ activeCount -= 1;
45
+ pump();
46
+ });
47
+ } else {
48
+ try {
49
+ entry.resolve(result);
50
+ } catch (e) {
51
+ entry.reject(e);
52
+ } finally{
53
+ activeCount -= 1;
54
+ pump();
55
+ }
56
+ }
57
+ };
58
+ return {
59
+ get activeCount () {
60
+ return activeCount;
61
+ },
62
+ get pendingCount () {
63
+ return pendingCount;
64
+ },
65
+ run (operation, runOptions = {}) {
66
+ if (runOptions.signal?.aborted) {
67
+ return Promise.reject(createOverloadedAbortError("Operation was aborted before entering the limiter."));
68
+ }
69
+ if (activeCount < options.maxConcurrency) {
70
+ return new Promise((resolve, reject)=>{
71
+ runEntry({
72
+ operation,
73
+ signal: runOptions.signal,
74
+ resolve,
75
+ reject
76
+ });
77
+ });
78
+ }
79
+ const maxQueueSize = options.maxQueueSize ?? Number.POSITIVE_INFINITY;
80
+ if (pendingCount >= maxQueueSize) {
81
+ return Promise.reject(core.createAthosError(constants.ATHOS_ERROR_CODES.OPERATION_OVERLOADED, "Concurrency limiter queue is full.", {
82
+ details: {
83
+ activeCount,
84
+ pendingCount,
85
+ maxConcurrency: options.maxConcurrency,
86
+ maxQueueSize
87
+ }
88
+ }));
89
+ }
90
+ return new Promise((resolve, reject)=>{
91
+ const entry = {
92
+ operation,
93
+ signal: runOptions.signal,
94
+ resolve,
95
+ reject
96
+ };
97
+ if (runOptions.signal) {
98
+ const onAbort = ()=>{
99
+ const idx = queue.indexOf(entry, queueOffset);
100
+ if (idx !== -1) {
101
+ queue[idx] = undefined;
102
+ pendingCount -= 1;
103
+ runOptions.signal?.removeEventListener("abort", onAbort);
104
+ entry.abortHandler = undefined;
105
+ reject(createOverloadedAbortError("Queued operation was aborted."));
106
+ }
107
+ };
108
+ entry.abortHandler = onAbort;
109
+ runOptions.signal.addEventListener("abort", onAbort, {
110
+ once: true
111
+ });
112
+ }
113
+ queue.push(entry);
114
+ pendingCount += 1;
115
+ });
116
+ }
117
+ };
118
+ }
119
+ function createCircuitBreaker(options) {
120
+ if (options.failureThreshold < 1) {
121
+ throw core.createAthosError(constants.ATHOS_ERROR_CODES.OPERATION_CIRCUIT_OPEN, "Circuit breaker requires failureThreshold to be greater than zero.");
122
+ }
123
+ let state = "closed";
124
+ let failureCount = 0;
125
+ let openedAt;
126
+ let halfOpenAttempts = 0;
127
+ const moveToOpen = ()=>{
128
+ state = "open";
129
+ openedAt = Date.now();
130
+ halfOpenAttempts = 0;
131
+ };
132
+ const moveToClosed = ()=>{
133
+ state = "closed";
134
+ failureCount = 0;
135
+ openedAt = undefined;
136
+ halfOpenAttempts = 0;
137
+ };
138
+ const moveToHalfOpenIfReady = ()=>{
139
+ if (state === "open" && openedAt !== undefined && Date.now() - openedAt >= options.resetAfterMs) {
140
+ state = "half-open";
141
+ halfOpenAttempts = 0;
142
+ }
143
+ };
144
+ return {
145
+ get state () {
146
+ moveToHalfOpenIfReady();
147
+ return state;
148
+ },
149
+ get failureCount () {
150
+ return failureCount;
151
+ },
152
+ get openedAt () {
153
+ return openedAt;
154
+ },
155
+ async execute (operation, runOptions = {}) {
156
+ moveToHalfOpenIfReady();
157
+ if (state === "open") {
158
+ throw core.createAthosError(constants.ATHOS_ERROR_CODES.OPERATION_CIRCUIT_OPEN, "Circuit breaker is open.", {
159
+ details: {
160
+ openedAt,
161
+ resetAfterMs: options.resetAfterMs
162
+ }
163
+ });
164
+ }
165
+ if (state === "half-open") {
166
+ const allowedAttempts = options.halfOpenMaxAttempts ?? 1;
167
+ if (halfOpenAttempts >= allowedAttempts) {
168
+ throw core.createAthosError(constants.ATHOS_ERROR_CODES.OPERATION_CIRCUIT_OPEN, "Circuit breaker half-open probe limit reached.", {
169
+ details: {
170
+ openedAt,
171
+ allowedAttempts
172
+ }
173
+ });
174
+ }
175
+ halfOpenAttempts += 1;
176
+ }
177
+ try {
178
+ const result = await operation(runOptions.signal);
179
+ moveToClosed();
180
+ return result;
181
+ } catch (error) {
182
+ failureCount += 1;
183
+ if (state === "half-open" || failureCount >= options.failureThreshold) {
184
+ moveToOpen();
185
+ }
186
+ throw error;
187
+ }
188
+ }
189
+ };
190
+ }
191
+ function createResilientExecutor(options = {}) {
192
+ return {
193
+ async execute (operation, runOptions = {}) {
194
+ const attempt = (signal)=>{
195
+ const result = options.timeoutMs ? withTimeout((timeoutSignal)=>operation(timeoutSignal), options.timeoutMs, signal) : operation(signal);
196
+ return result instanceof Promise ? result : Promise.resolve(result);
197
+ };
198
+ const executeWithBreaker = (signal)=>{
199
+ if (options.circuitBreaker) {
200
+ return options.circuitBreaker.execute((breakerSignal)=>attempt(breakerSignal), {
201
+ ...signal === undefined ? {} : {
202
+ signal
203
+ }
204
+ });
205
+ }
206
+ return attempt(signal);
207
+ };
208
+ if (options.limiter) {
209
+ return options.limiter.run((limiterSignal)=>executeWithBreaker(limiterSignal), runOptions);
210
+ }
211
+ return executeWithBreaker(runOptions.signal);
212
+ }
213
+ };
214
+ }
215
+ function withTimeout(operation, timeoutMs, upstreamSignal) {
216
+ if (timeoutMs <= 0) {
217
+ return Promise.reject(core.createAthosError(constants.ATHOS_ERROR_CODES.OPERATION_TIMEOUT, "Operation timeout must be greater than zero."));
218
+ }
219
+ if (upstreamSignal?.aborted) {
220
+ return Promise.reject(upstreamSignal.reason || new Error("Aborted"));
221
+ }
222
+ const controller = new AbortController();
223
+ const detach = upstreamSignal ? forwardAbort(upstreamSignal, controller) : undefined;
224
+ return new Promise((resolve, reject)=>{
225
+ let settled = false;
226
+ const timeout = setTimeout(()=>{
227
+ if (settled) return;
228
+ settled = true;
229
+ controller.abort();
230
+ reject(core.createAthosError(constants.ATHOS_ERROR_CODES.OPERATION_TIMEOUT, "Operation timed out.", {
231
+ details: {
232
+ timeoutMs
233
+ }
234
+ }));
235
+ }, timeoutMs);
236
+ const cleanup = (err)=>{
237
+ if (settled) return;
238
+ settled = true;
239
+ clearTimeout(timeout);
240
+ if (detach) detach();
241
+ if (err) reject(err);
242
+ };
243
+ try {
244
+ const res = operation(controller.signal);
245
+ if (res instanceof Promise) {
246
+ res.then((val)=>{
247
+ cleanup();
248
+ resolve(val);
249
+ }, cleanup);
250
+ } else {
251
+ cleanup();
252
+ resolve(res);
253
+ }
254
+ } catch (e) {
255
+ cleanup(e);
256
+ }
257
+ });
258
+ }
259
+ function forwardAbort(signal, controller) {
260
+ if (!signal) {
261
+ return ()=>undefined;
262
+ }
263
+ if (signal.aborted) {
264
+ controller.abort();
265
+ return ()=>undefined;
266
+ }
267
+ const onAbort = ()=>controller.abort();
268
+ signal.addEventListener("abort", onAbort, {
269
+ once: true
270
+ });
271
+ return ()=>signal.removeEventListener("abort", onAbort);
272
+ }
273
+ function createOverloadedAbortError(message) {
274
+ return core.createAthosError(constants.ATHOS_ERROR_CODES.OPERATION_OVERLOADED, message);
275
+ }
276
+
277
+ exports.createCircuitBreaker = createCircuitBreaker;
278
+ exports.createConcurrencyLimiter = createConcurrencyLimiter;
279
+ exports.createResilientExecutor = createResilientExecutor;
280
+ //# sourceMappingURL=resilience.cjs.map