@hazeljs/predictive-scaling 2.0.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 (71) hide show
  1. package/README.md +172 -0
  2. package/dist/__tests__/ai-forecast.test.d.ts +2 -0
  3. package/dist/__tests__/ai-forecast.test.d.ts.map +1 -0
  4. package/dist/__tests__/ai-forecast.test.js +15 -0
  5. package/dist/__tests__/decorators.test.d.ts +2 -0
  6. package/dist/__tests__/decorators.test.d.ts.map +1 -0
  7. package/dist/__tests__/decorators.test.js +48 -0
  8. package/dist/__tests__/duration.test.d.ts +2 -0
  9. package/dist/__tests__/duration.test.d.ts.map +1 -0
  10. package/dist/__tests__/duration.test.js +10 -0
  11. package/dist/__tests__/forecast-engine.test.d.ts +2 -0
  12. package/dist/__tests__/forecast-engine.test.d.ts.map +1 -0
  13. package/dist/__tests__/forecast-engine.test.js +25 -0
  14. package/dist/__tests__/index.test.d.ts +2 -0
  15. package/dist/__tests__/index.test.d.ts.map +1 -0
  16. package/dist/__tests__/index.test.js +23 -0
  17. package/dist/__tests__/operations-stack.test.d.ts +2 -0
  18. package/dist/__tests__/operations-stack.test.d.ts.map +1 -0
  19. package/dist/__tests__/operations-stack.test.js +35 -0
  20. package/dist/__tests__/predictive-scaler.test.d.ts +2 -0
  21. package/dist/__tests__/predictive-scaler.test.d.ts.map +1 -0
  22. package/dist/__tests__/predictive-scaler.test.js +46 -0
  23. package/dist/__tests__/prometheus-collector.test.d.ts +2 -0
  24. package/dist/__tests__/prometheus-collector.test.d.ts.map +1 -0
  25. package/dist/__tests__/prometheus-collector.test.js +47 -0
  26. package/dist/__tests__/replica-calculator.test.d.ts +2 -0
  27. package/dist/__tests__/replica-calculator.test.d.ts.map +1 -0
  28. package/dist/__tests__/replica-calculator.test.js +28 -0
  29. package/dist/decorators/index.d.ts +20 -0
  30. package/dist/decorators/index.d.ts.map +1 -0
  31. package/dist/decorators/index.js +83 -0
  32. package/dist/events/event-scaling-registry.d.ts +16 -0
  33. package/dist/events/event-scaling-registry.d.ts.map +1 -0
  34. package/dist/events/event-scaling-registry.js +38 -0
  35. package/dist/forecast/ai-forecast-provider.d.ts +18 -0
  36. package/dist/forecast/ai-forecast-provider.d.ts.map +1 -0
  37. package/dist/forecast/ai-forecast-provider.js +60 -0
  38. package/dist/forecast/forecast-engine.d.ts +12 -0
  39. package/dist/forecast/forecast-engine.d.ts.map +1 -0
  40. package/dist/forecast/forecast-engine.js +114 -0
  41. package/dist/index.d.ts +18 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +62 -0
  44. package/dist/integrations/operations-stack.d.ts +22 -0
  45. package/dist/integrations/operations-stack.d.ts.map +1 -0
  46. package/dist/integrations/operations-stack.js +43 -0
  47. package/dist/integrations/prometheus.d.ts +7 -0
  48. package/dist/integrations/prometheus.d.ts.map +1 -0
  49. package/dist/integrations/prometheus.js +12 -0
  50. package/dist/integrations/self-healing.d.ts +21 -0
  51. package/dist/integrations/self-healing.d.ts.map +1 -0
  52. package/dist/integrations/self-healing.js +27 -0
  53. package/dist/metrics/metrics-store.d.ts +15 -0
  54. package/dist/metrics/metrics-store.d.ts.map +1 -0
  55. package/dist/metrics/metrics-store.js +40 -0
  56. package/dist/metrics/prometheus-collector.d.ts +30 -0
  57. package/dist/metrics/prometheus-collector.d.ts.map +1 -0
  58. package/dist/metrics/prometheus-collector.js +85 -0
  59. package/dist/scaling/predictive-scaler.d.ts +24 -0
  60. package/dist/scaling/predictive-scaler.d.ts.map +1 -0
  61. package/dist/scaling/predictive-scaler.js +143 -0
  62. package/dist/scaling/replica-calculator.d.ts +13 -0
  63. package/dist/scaling/replica-calculator.d.ts.map +1 -0
  64. package/dist/scaling/replica-calculator.js +56 -0
  65. package/dist/types/index.d.ts +86 -0
  66. package/dist/types/index.d.ts.map +1 -0
  67. package/dist/types/index.js +5 -0
  68. package/dist/utils/duration.d.ts +6 -0
  69. package/dist/utils/duration.d.ts.map +1 -0
  70. package/dist/utils/duration.js +28 -0
  71. package/package.json +68 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-scaling-registry.d.ts","sourceRoot":"","sources":["../../src/events/event-scaling-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAE/C,MAAM,WAAW,oBAAqB,SAAQ,mBAAmB;IAC/D,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,CAAC,MAAM,CAA6C;IAElE,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,IAAI;IAMlE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,oBAAoB,EAAE;IAIjD,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,oBAAoB,EAAE;IAY9D,MAAM,CAAC,KAAK,IAAI,IAAI;CAGrB;AAED,wBAAgB,2BAA2B,CACzC,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,mBAAmB,GAC3B,MAAM,CAIR"}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EventScalingRegistry = void 0;
4
+ exports.calculateEventBoostReplicas = calculateEventBoostReplicas;
5
+ /**
6
+ * Registry for event-driven predictive scaling triggers.
7
+ */
8
+ class EventScalingRegistry {
9
+ static register(scope, options) {
10
+ const existing = this.events.get(scope) ?? [];
11
+ existing.push({ ...options, scope });
12
+ this.events.set(scope, existing);
13
+ }
14
+ static get(scope) {
15
+ return [...(this.events.get(scope) ?? [])];
16
+ }
17
+ static findMatching(eventName) {
18
+ const matches = [];
19
+ for (const registrations of this.events.values()) {
20
+ for (const registration of registrations) {
21
+ if (registration.events.includes(eventName)) {
22
+ matches.push(registration);
23
+ }
24
+ }
25
+ }
26
+ return matches;
27
+ }
28
+ static reset() {
29
+ this.events.clear();
30
+ }
31
+ }
32
+ exports.EventScalingRegistry = EventScalingRegistry;
33
+ EventScalingRegistry.events = new Map();
34
+ function calculateEventBoostReplicas(currentReplicas, options) {
35
+ const factor = options.scaleFactor ?? 2;
36
+ const maxScale = options.maxScale ?? 100;
37
+ return Math.min(maxScale, Math.max(currentReplicas, Math.ceil(currentReplicas * factor)));
38
+ }
@@ -0,0 +1,18 @@
1
+ import { ForecastProvider, ForecastResult, MetricName, MetricSample } from '../types';
2
+ export interface AILlmForecastClient {
3
+ complete(messages: Array<{
4
+ role: 'system' | 'user';
5
+ content: string;
6
+ }>): Promise<string>;
7
+ }
8
+ /**
9
+ * Optional LLM-based forecast hook (Phase 2 bridge for @hazeljs/ai).
10
+ */
11
+ export declare function createAIForecastProvider(client: AILlmForecastClient): ForecastProvider;
12
+ export declare class ForecastEngine {
13
+ private readonly model;
14
+ private readonly provider?;
15
+ constructor(model?: import('../types').ForecastModel, provider?: ForecastProvider | undefined);
16
+ forecast(metric: MetricName, samples: MetricSample[], horizonMs: number): Promise<ForecastResult>;
17
+ }
18
+ //# sourceMappingURL=ai-forecast-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-forecast-provider.d.ts","sourceRoot":"","sources":["../../src/forecast/ai-forecast-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGtF,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC1F;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,mBAAmB,GAAG,gBAAgB,CAuCtF;AAED,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;gBADT,KAAK,GAAE,OAAO,UAAU,EAAE,aAAsC,EAChE,QAAQ,CAAC,EAAE,gBAAgB,YAAA;IAGxC,QAAQ,CACZ,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,YAAY,EAAE,EACvB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,cAAc,CAAC;CAU3B"}
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ForecastEngine = void 0;
4
+ exports.createAIForecastProvider = createAIForecastProvider;
5
+ const forecast_engine_1 = require("./forecast-engine");
6
+ /**
7
+ * Optional LLM-based forecast hook (Phase 2 bridge for @hazeljs/ai).
8
+ */
9
+ function createAIForecastProvider(client) {
10
+ return {
11
+ async forecast(metric, samples, horizonMs) {
12
+ const prompt = [
13
+ 'Predict the next metric value as JSON: {"predictedValue": number, "confidence": 0-1}',
14
+ `Metric: ${metric}`,
15
+ `HorizonMs: ${horizonMs}`,
16
+ `Samples: ${JSON.stringify(samples.slice(-50))}`,
17
+ ].join('\n');
18
+ const content = await client.complete([
19
+ {
20
+ role: 'system',
21
+ content: 'You are a time-series forecasting assistant. Respond with JSON only.',
22
+ },
23
+ { role: 'user', content: prompt },
24
+ ]);
25
+ try {
26
+ const parsed = JSON.parse(content.trim());
27
+ if (typeof parsed.predictedValue !== 'number') {
28
+ return null;
29
+ }
30
+ return {
31
+ metric,
32
+ predictedValue: parsed.predictedValue,
33
+ confidence: typeof parsed.confidence === 'number' ? parsed.confidence : 0.6,
34
+ horizonMs,
35
+ model: 'ai',
36
+ at: Date.now(),
37
+ };
38
+ }
39
+ catch {
40
+ return null;
41
+ }
42
+ },
43
+ };
44
+ }
45
+ class ForecastEngine {
46
+ constructor(model = 'time-series-forecast', provider) {
47
+ this.model = model;
48
+ this.provider = provider;
49
+ }
50
+ async forecast(metric, samples, horizonMs) {
51
+ if (this.provider) {
52
+ const aiResult = await this.provider.forecast(metric, samples, horizonMs);
53
+ if (aiResult) {
54
+ return aiResult;
55
+ }
56
+ }
57
+ return (0, forecast_engine_1.runForecastModel)(this.model, metric, samples, horizonMs);
58
+ }
59
+ }
60
+ exports.ForecastEngine = ForecastEngine;
@@ -0,0 +1,12 @@
1
+ import { ForecastModel, ForecastResult, MetricName, MetricSample } from '../types';
2
+ /**
3
+ * Holt's linear exponential smoothing for short-horizon demand forecasting.
4
+ */
5
+ export declare function forecastExponentialSmoothing(metric: MetricName, samples: MetricSample[], horizonMs: number, alpha?: number, beta?: number): ForecastResult;
6
+ /**
7
+ * Hour-of-week seasonal multiplier based on historical samples.
8
+ */
9
+ export declare function forecastSeasonalPattern(metric: MetricName, samples: MetricSample[], horizonMs: number): ForecastResult;
10
+ export declare function combineForecasts(forecasts: ForecastResult[]): ForecastResult | null;
11
+ export declare function runForecastModel(model: ForecastModel, metric: MetricName, samples: MetricSample[], horizonMs: number): ForecastResult;
12
+ //# sourceMappingURL=forecast-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forecast-engine.d.ts","sourceRoot":"","sources":["../../src/forecast/forecast-engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAEnF;;GAEG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,YAAY,EAAE,EACvB,SAAS,EAAE,MAAM,EACjB,KAAK,SAAO,EACZ,IAAI,SAAO,GACV,cAAc,CA+ChB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,YAAY,EAAE,EACvB,SAAS,EAAE,MAAM,GAChB,cAAc,CAgChB;AAMD,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,cAAc,EAAE,GAAG,cAAc,GAAG,IAAI,CAkBnF;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,YAAY,EAAE,EACvB,SAAS,EAAE,MAAM,GAChB,cAAc,CAgBhB"}
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.forecastExponentialSmoothing = forecastExponentialSmoothing;
4
+ exports.forecastSeasonalPattern = forecastSeasonalPattern;
5
+ exports.combineForecasts = combineForecasts;
6
+ exports.runForecastModel = runForecastModel;
7
+ /**
8
+ * Holt's linear exponential smoothing for short-horizon demand forecasting.
9
+ */
10
+ function forecastExponentialSmoothing(metric, samples, horizonMs, alpha = 0.35, beta = 0.15) {
11
+ if (samples.length < 2) {
12
+ const latest = samples[samples.length - 1]?.value ?? 0;
13
+ return {
14
+ metric,
15
+ predictedValue: latest,
16
+ confidence: 0.3,
17
+ horizonMs,
18
+ model: 'exponential-smoothing',
19
+ at: Date.now(),
20
+ };
21
+ }
22
+ const sorted = [...samples].sort((a, b) => a.timestamp - b.timestamp);
23
+ let level = sorted[0].value;
24
+ let trend = sorted[1].value - sorted[0].value;
25
+ for (let i = 1; i < sorted.length; i++) {
26
+ const value = sorted[i].value;
27
+ const prevLevel = level;
28
+ level = alpha * value + (1 - alpha) * (level + trend);
29
+ trend = beta * (level - prevLevel) + (1 - beta) * trend;
30
+ }
31
+ const last = sorted[sorted.length - 1];
32
+ const dt = Math.max(1, last.timestamp - sorted[0].timestamp);
33
+ const steps = Math.max(1, horizonMs / (dt / Math.max(1, sorted.length - 1)));
34
+ const predictedValue = Math.max(0, level + trend * steps);
35
+ const residuals = sorted.slice(1).map((sample, index) => {
36
+ const expected = level;
37
+ return Math.abs(sample.value - expected);
38
+ });
39
+ const avgResidual = residuals.length === 0
40
+ ? 0
41
+ : residuals.reduce((sum, value) => sum + value, 0) / residuals.length;
42
+ const confidence = clampConfidence(1 - avgResidual / Math.max(1, level));
43
+ return {
44
+ metric,
45
+ predictedValue,
46
+ confidence,
47
+ horizonMs,
48
+ model: 'exponential-smoothing',
49
+ at: Date.now(),
50
+ };
51
+ }
52
+ /**
53
+ * Hour-of-week seasonal multiplier based on historical samples.
54
+ */
55
+ function forecastSeasonalPattern(metric, samples, horizonMs) {
56
+ const now = Date.now();
57
+ const targetTime = now + horizonMs;
58
+ const targetHour = new Date(targetTime).getUTCHours();
59
+ const targetDow = new Date(targetTime).getUTCDay();
60
+ const buckets = new Map();
61
+ for (const sample of samples) {
62
+ const date = new Date(sample.timestamp);
63
+ const key = `${date.getUTCDay()}-${date.getUTCHours()}`;
64
+ const bucket = buckets.get(key) ?? [];
65
+ bucket.push(sample.value);
66
+ buckets.set(key, bucket);
67
+ }
68
+ const key = `${targetDow}-${targetHour}`;
69
+ const bucketValues = buckets.get(key) ?? samples.map((sample) => sample.value);
70
+ const predictedValue = bucketValues.reduce((sum, value) => sum + value, 0) / Math.max(1, bucketValues.length);
71
+ const globalAvg = samples.reduce((sum, sample) => sum + sample.value, 0) / Math.max(1, samples.length);
72
+ const confidence = clampConfidence(bucketValues.length / Math.max(3, samples.length / 24));
73
+ return {
74
+ metric,
75
+ predictedValue: predictedValue || globalAvg,
76
+ confidence,
77
+ horizonMs,
78
+ model: 'seasonal-pattern',
79
+ at: Date.now(),
80
+ };
81
+ }
82
+ function clampConfidence(value) {
83
+ return Math.min(1, Math.max(0, value));
84
+ }
85
+ function combineForecasts(forecasts) {
86
+ if (forecasts.length === 0) {
87
+ return null;
88
+ }
89
+ const totalWeight = forecasts.reduce((sum, forecast) => sum + forecast.confidence, 0) || 1;
90
+ const predictedValue = forecasts.reduce((sum, forecast) => sum + forecast.predictedValue * forecast.confidence, 0) /
91
+ totalWeight;
92
+ const confidence = forecasts.reduce((sum, forecast) => sum + forecast.confidence, 0) / forecasts.length;
93
+ return {
94
+ ...forecasts[0],
95
+ predictedValue,
96
+ confidence,
97
+ model: 'time-series-forecast',
98
+ };
99
+ }
100
+ function runForecastModel(model, metric, samples, horizonMs) {
101
+ switch (model) {
102
+ case 'seasonal-pattern':
103
+ return forecastSeasonalPattern(metric, samples, horizonMs);
104
+ case 'time-series-forecast':
105
+ return (combineForecasts([
106
+ forecastExponentialSmoothing(metric, samples, horizonMs),
107
+ forecastSeasonalPattern(metric, samples, horizonMs),
108
+ ]) ?? forecastExponentialSmoothing(metric, samples, horizonMs));
109
+ case 'exponential-smoothing':
110
+ case 'ai':
111
+ default:
112
+ return forecastExponentialSmoothing(metric, samples, horizonMs);
113
+ }
114
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @hazeljs/predictive-scaling
3
+ * Predictive auto-scaling for HazelJS microservices
4
+ */
5
+ export * from './types';
6
+ export { MetricsStore } from './metrics/metrics-store';
7
+ export { parseDuration, clamp } from './utils/duration';
8
+ export { forecastExponentialSmoothing, forecastSeasonalPattern, combineForecasts, runForecastModel, } from './forecast/forecast-engine';
9
+ export { ForecastEngine, createAIForecastProvider, AILlmForecastClient, } from './forecast/ai-forecast-provider';
10
+ export { calculateTargetReplicas, decideScaling } from './scaling/replica-calculator';
11
+ export { PredictiveScaler, createPredictiveScaler } from './scaling/predictive-scaler';
12
+ export { EventScalingRegistry, calculateEventBoostReplicas, RegisteredScaleEvent, } from './events/event-scaling-registry';
13
+ export { PredictiveScaling, ScalePredict, ScaleOnEvent, getPredictiveScaler, startPredictiveScaling, stopPredictiveScaling, emitScalingEvent, } from './decorators';
14
+ export { adaptSelfHealingScalingClient, InMemoryScalingClient } from './integrations/self-healing';
15
+ export { PrometheusMetricsCollector, PrometheusQueryConfig, PrometheusQueryResult, createPrometheusMetricsCollector, } from './metrics/prometheus-collector';
16
+ export { attachPrometheusCollector } from './integrations/prometheus';
17
+ export { createOperationsStack, OperationsStack, OperationsStackOptions, } from './integrations/operations-stack';
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,SAAS,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,EACL,4BAA4B,EAC5B,uBAAuB,EACvB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,cAAc,EACd,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,uBAAuB,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAEvF,OAAO,EACL,oBAAoB,EACpB,2BAA2B,EAC3B,oBAAoB,GACrB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,6BAA6B,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAEnG,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,EACrB,gCAAgC,GACjC,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAEtE,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,sBAAsB,GACvB,MAAM,iCAAiC,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ /**
3
+ * @hazeljs/predictive-scaling
4
+ * Predictive auto-scaling for HazelJS microservices
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
18
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
19
+ };
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.createOperationsStack = exports.attachPrometheusCollector = exports.createPrometheusMetricsCollector = exports.PrometheusMetricsCollector = exports.InMemoryScalingClient = exports.adaptSelfHealingScalingClient = exports.emitScalingEvent = exports.stopPredictiveScaling = exports.startPredictiveScaling = exports.getPredictiveScaler = exports.ScaleOnEvent = exports.ScalePredict = exports.PredictiveScaling = exports.calculateEventBoostReplicas = exports.EventScalingRegistry = exports.createPredictiveScaler = exports.PredictiveScaler = exports.decideScaling = exports.calculateTargetReplicas = exports.createAIForecastProvider = exports.ForecastEngine = exports.runForecastModel = exports.combineForecasts = exports.forecastSeasonalPattern = exports.forecastExponentialSmoothing = exports.clamp = exports.parseDuration = exports.MetricsStore = void 0;
22
+ __exportStar(require("./types"), exports);
23
+ var metrics_store_1 = require("./metrics/metrics-store");
24
+ Object.defineProperty(exports, "MetricsStore", { enumerable: true, get: function () { return metrics_store_1.MetricsStore; } });
25
+ var duration_1 = require("./utils/duration");
26
+ Object.defineProperty(exports, "parseDuration", { enumerable: true, get: function () { return duration_1.parseDuration; } });
27
+ Object.defineProperty(exports, "clamp", { enumerable: true, get: function () { return duration_1.clamp; } });
28
+ var forecast_engine_1 = require("./forecast/forecast-engine");
29
+ Object.defineProperty(exports, "forecastExponentialSmoothing", { enumerable: true, get: function () { return forecast_engine_1.forecastExponentialSmoothing; } });
30
+ Object.defineProperty(exports, "forecastSeasonalPattern", { enumerable: true, get: function () { return forecast_engine_1.forecastSeasonalPattern; } });
31
+ Object.defineProperty(exports, "combineForecasts", { enumerable: true, get: function () { return forecast_engine_1.combineForecasts; } });
32
+ Object.defineProperty(exports, "runForecastModel", { enumerable: true, get: function () { return forecast_engine_1.runForecastModel; } });
33
+ var ai_forecast_provider_1 = require("./forecast/ai-forecast-provider");
34
+ Object.defineProperty(exports, "ForecastEngine", { enumerable: true, get: function () { return ai_forecast_provider_1.ForecastEngine; } });
35
+ Object.defineProperty(exports, "createAIForecastProvider", { enumerable: true, get: function () { return ai_forecast_provider_1.createAIForecastProvider; } });
36
+ var replica_calculator_1 = require("./scaling/replica-calculator");
37
+ Object.defineProperty(exports, "calculateTargetReplicas", { enumerable: true, get: function () { return replica_calculator_1.calculateTargetReplicas; } });
38
+ Object.defineProperty(exports, "decideScaling", { enumerable: true, get: function () { return replica_calculator_1.decideScaling; } });
39
+ var predictive_scaler_1 = require("./scaling/predictive-scaler");
40
+ Object.defineProperty(exports, "PredictiveScaler", { enumerable: true, get: function () { return predictive_scaler_1.PredictiveScaler; } });
41
+ Object.defineProperty(exports, "createPredictiveScaler", { enumerable: true, get: function () { return predictive_scaler_1.createPredictiveScaler; } });
42
+ var event_scaling_registry_1 = require("./events/event-scaling-registry");
43
+ Object.defineProperty(exports, "EventScalingRegistry", { enumerable: true, get: function () { return event_scaling_registry_1.EventScalingRegistry; } });
44
+ Object.defineProperty(exports, "calculateEventBoostReplicas", { enumerable: true, get: function () { return event_scaling_registry_1.calculateEventBoostReplicas; } });
45
+ var decorators_1 = require("./decorators");
46
+ Object.defineProperty(exports, "PredictiveScaling", { enumerable: true, get: function () { return decorators_1.PredictiveScaling; } });
47
+ Object.defineProperty(exports, "ScalePredict", { enumerable: true, get: function () { return decorators_1.ScalePredict; } });
48
+ Object.defineProperty(exports, "ScaleOnEvent", { enumerable: true, get: function () { return decorators_1.ScaleOnEvent; } });
49
+ Object.defineProperty(exports, "getPredictiveScaler", { enumerable: true, get: function () { return decorators_1.getPredictiveScaler; } });
50
+ Object.defineProperty(exports, "startPredictiveScaling", { enumerable: true, get: function () { return decorators_1.startPredictiveScaling; } });
51
+ Object.defineProperty(exports, "stopPredictiveScaling", { enumerable: true, get: function () { return decorators_1.stopPredictiveScaling; } });
52
+ Object.defineProperty(exports, "emitScalingEvent", { enumerable: true, get: function () { return decorators_1.emitScalingEvent; } });
53
+ var self_healing_1 = require("./integrations/self-healing");
54
+ Object.defineProperty(exports, "adaptSelfHealingScalingClient", { enumerable: true, get: function () { return self_healing_1.adaptSelfHealingScalingClient; } });
55
+ Object.defineProperty(exports, "InMemoryScalingClient", { enumerable: true, get: function () { return self_healing_1.InMemoryScalingClient; } });
56
+ var prometheus_collector_1 = require("./metrics/prometheus-collector");
57
+ Object.defineProperty(exports, "PrometheusMetricsCollector", { enumerable: true, get: function () { return prometheus_collector_1.PrometheusMetricsCollector; } });
58
+ Object.defineProperty(exports, "createPrometheusMetricsCollector", { enumerable: true, get: function () { return prometheus_collector_1.createPrometheusMetricsCollector; } });
59
+ var prometheus_1 = require("./integrations/prometheus");
60
+ Object.defineProperty(exports, "attachPrometheusCollector", { enumerable: true, get: function () { return prometheus_1.attachPrometheusCollector; } });
61
+ var operations_stack_1 = require("./integrations/operations-stack");
62
+ Object.defineProperty(exports, "createOperationsStack", { enumerable: true, get: function () { return operations_stack_1.createOperationsStack; } });
@@ -0,0 +1,22 @@
1
+ import { HealingCoordinator } from '@hazeljs/self-healing';
2
+ import type { SelfHealingModuleOptions } from '@hazeljs/self-healing';
3
+ import { PredictiveScaler } from '../scaling/predictive-scaler';
4
+ import { PrometheusMetricsCollector, PrometheusQueryConfig } from '../metrics/prometheus-collector';
5
+ import { PredictiveScalingOptions } from '../types';
6
+ export interface OperationsStackOptions {
7
+ healing?: SelfHealingModuleOptions;
8
+ scaling: PredictiveScalingOptions;
9
+ prometheus?: PrometheusQueryConfig;
10
+ }
11
+ export interface OperationsStack {
12
+ healing: HealingCoordinator;
13
+ scaler: PredictiveScaler;
14
+ prometheus?: PrometheusMetricsCollector;
15
+ start(): void;
16
+ stop(): void;
17
+ }
18
+ /**
19
+ * Production stack: reactive self-healing + proactive predictive scaling (+ optional Prometheus feed).
20
+ */
21
+ export declare function createOperationsStack(options: OperationsStackOptions): OperationsStack;
22
+ //# sourceMappingURL=operations-stack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations-stack.d.ts","sourceRoot":"","sources":["../../src/integrations/operations-stack.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AACrF,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAGtE,OAAO,EAA0B,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACxF,OAAO,EAAE,0BAA0B,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACpG,OAAO,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAEpD,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,wBAAwB,CAAC;IACnC,OAAO,EAAE,wBAAwB,CAAC;IAClC,UAAU,CAAC,EAAE,qBAAqB,CAAC;CACpC;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,kBAAkB,CAAC;IAC5B,MAAM,EAAE,gBAAgB,CAAC;IACzB,UAAU,CAAC,EAAE,0BAA0B,CAAC;IACxC,KAAK,IAAI,IAAI,CAAC;IACd,IAAI,IAAI,IAAI,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB,GAAG,eAAe,CAwCtF"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createOperationsStack = createOperationsStack;
4
+ const self_healing_1 = require("@hazeljs/self-healing");
5
+ const prometheus_1 = require("./prometheus");
6
+ const self_healing_2 = require("./self-healing");
7
+ const predictive_scaler_1 = require("../scaling/predictive-scaler");
8
+ /**
9
+ * Production stack: reactive self-healing + proactive predictive scaling (+ optional Prometheus feed).
10
+ */
11
+ function createOperationsStack(options) {
12
+ const healing = (0, self_healing_1.createHealingCoordinator)(options.healing ?? {});
13
+ const scalingClient = options.scaling.hpa.client ??
14
+ (options.healing?.kubernetes?.hpa?.client
15
+ ? (0, self_healing_2.adaptSelfHealingScalingClient)(options.healing.kubernetes.hpa.client)
16
+ : undefined);
17
+ if (!scalingClient) {
18
+ throw new Error('Operations stack requires scaling.hpa.client or healing.kubernetes.hpa.client');
19
+ }
20
+ const scaler = (0, predictive_scaler_1.createPredictiveScaler)({
21
+ ...options.scaling,
22
+ hpa: {
23
+ ...options.scaling.hpa,
24
+ client: scalingClient,
25
+ },
26
+ });
27
+ const prometheus = options.prometheus
28
+ ? (0, prometheus_1.attachPrometheusCollector)(scaler, options.prometheus)
29
+ : undefined;
30
+ return {
31
+ healing,
32
+ scaler,
33
+ prometheus,
34
+ start() {
35
+ scaler.start();
36
+ prometheus?.start();
37
+ },
38
+ stop() {
39
+ scaler.stop();
40
+ prometheus?.stop();
41
+ },
42
+ };
43
+ }
@@ -0,0 +1,7 @@
1
+ import { PrometheusMetricsCollector, PrometheusQueryConfig } from '../metrics/prometheus-collector';
2
+ import { PredictiveScaler } from '../scaling/predictive-scaler';
3
+ /**
4
+ * Attach Prometheus polling to a predictive scaler metrics store.
5
+ */
6
+ export declare function attachPrometheusCollector(scaler: PredictiveScaler, config: PrometheusQueryConfig): PrometheusMetricsCollector;
7
+ //# sourceMappingURL=prometheus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prometheus.d.ts","sourceRoot":"","sources":["../../src/integrations/prometheus.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACpG,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEhE;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,qBAAqB,GAC5B,0BAA0B,CAI5B"}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.attachPrometheusCollector = attachPrometheusCollector;
4
+ const prometheus_collector_1 = require("../metrics/prometheus-collector");
5
+ /**
6
+ * Attach Prometheus polling to a predictive scaler metrics store.
7
+ */
8
+ function attachPrometheusCollector(scaler, config) {
9
+ return new prometheus_collector_1.PrometheusMetricsCollector(config, (sample) => {
10
+ scaler.recordMetric(sample.metric, sample.value, sample.timestamp);
11
+ });
12
+ }
@@ -0,0 +1,21 @@
1
+ import { KubernetesScalingClient } from '../types';
2
+ type SelfHealingScalingClient = {
3
+ getHpaMinReplicas(hpa: string, namespace: string): Promise<number>;
4
+ setHpaMinReplicas(hpa: string, namespace: string, minReplicas: number): Promise<void>;
5
+ };
6
+ /**
7
+ * Bridge scaling clients exported by @hazeljs/self-healing.
8
+ */
9
+ export declare function adaptSelfHealingScalingClient(client: SelfHealingScalingClient): KubernetesScalingClient;
10
+ export declare class InMemoryScalingClient implements KubernetesScalingClient {
11
+ readonly updates: Array<{
12
+ hpa: string;
13
+ namespace: string;
14
+ minReplicas: number;
15
+ }>;
16
+ private readonly state;
17
+ getHpaMinReplicas(hpa: string, namespace: string): Promise<number>;
18
+ setHpaMinReplicas(hpa: string, namespace: string, minReplicas: number): Promise<void>;
19
+ }
20
+ export {};
21
+ //# sourceMappingURL=self-healing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"self-healing.d.ts","sourceRoot":"","sources":["../../src/integrations/self-healing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAEnD,KAAK,wBAAwB,GAAG;IAC9B,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACnE,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvF,CAAC;AAEF;;GAEG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,wBAAwB,GAC/B,uBAAuB,CAMzB;AAED,qBAAa,qBAAsB,YAAW,uBAAuB;IACnE,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAM;IACtF,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA6B;IAE7C,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIlE,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAI5F"}
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InMemoryScalingClient = void 0;
4
+ exports.adaptSelfHealingScalingClient = adaptSelfHealingScalingClient;
5
+ /**
6
+ * Bridge scaling clients exported by @hazeljs/self-healing.
7
+ */
8
+ function adaptSelfHealingScalingClient(client) {
9
+ return {
10
+ getHpaMinReplicas: (hpa, namespace) => client.getHpaMinReplicas(hpa, namespace),
11
+ setHpaMinReplicas: (hpa, namespace, minReplicas) => client.setHpaMinReplicas(hpa, namespace, minReplicas),
12
+ };
13
+ }
14
+ class InMemoryScalingClient {
15
+ constructor() {
16
+ this.updates = [];
17
+ this.state = new Map();
18
+ }
19
+ async getHpaMinReplicas(hpa, namespace) {
20
+ return this.state.get(`${namespace}/${hpa}`) ?? 2;
21
+ }
22
+ async setHpaMinReplicas(hpa, namespace, minReplicas) {
23
+ this.state.set(`${namespace}/${hpa}`, minReplicas);
24
+ this.updates.push({ hpa, namespace, minReplicas });
25
+ }
26
+ }
27
+ exports.InMemoryScalingClient = InMemoryScalingClient;
@@ -0,0 +1,15 @@
1
+ import { MetricName, MetricSample } from '../types';
2
+ /**
3
+ * Ring-buffer time series store per metric.
4
+ */
5
+ export declare class MetricsStore {
6
+ private readonly maxSamples;
7
+ private readonly series;
8
+ constructor(maxSamples?: number);
9
+ record(metric: MetricName, value: number, timestamp?: number): MetricSample;
10
+ getSamples(metric: MetricName): MetricSample[];
11
+ getLatest(metric: MetricName): MetricSample | undefined;
12
+ metrics(): MetricName[];
13
+ clear(metric?: MetricName): void;
14
+ }
15
+ //# sourceMappingURL=metrics-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics-store.d.ts","sourceRoot":"","sources":["../../src/metrics/metrics-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAEpD;;GAEG;AACH,qBAAa,YAAY;IAGX,OAAO,CAAC,QAAQ,CAAC,UAAU;IAFvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyC;gBAEnC,UAAU,SAAM;IAE7C,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,SAAa,GAAG,YAAY;IAa/E,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,YAAY,EAAE;IAI9C,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,YAAY,GAAG,SAAS;IAKvD,OAAO,IAAI,UAAU,EAAE;IAIvB,KAAK,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,IAAI;CAOjC"}
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MetricsStore = void 0;
4
+ /**
5
+ * Ring-buffer time series store per metric.
6
+ */
7
+ class MetricsStore {
8
+ constructor(maxSamples = 500) {
9
+ this.maxSamples = maxSamples;
10
+ this.series = new Map();
11
+ }
12
+ record(metric, value, timestamp = Date.now()) {
13
+ const sample = { metric, value, timestamp };
14
+ const history = this.series.get(metric) ?? [];
15
+ history.push(sample);
16
+ if (history.length > this.maxSamples) {
17
+ history.shift();
18
+ }
19
+ this.series.set(metric, history);
20
+ return sample;
21
+ }
22
+ getSamples(metric) {
23
+ return [...(this.series.get(metric) ?? [])];
24
+ }
25
+ getLatest(metric) {
26
+ const history = this.series.get(metric);
27
+ return history?.[history.length - 1];
28
+ }
29
+ metrics() {
30
+ return [...this.series.keys()];
31
+ }
32
+ clear(metric) {
33
+ if (metric) {
34
+ this.series.delete(metric);
35
+ return;
36
+ }
37
+ this.series.clear();
38
+ }
39
+ }
40
+ exports.MetricsStore = MetricsStore;
@@ -0,0 +1,30 @@
1
+ import { MetricName } from '../types';
2
+ export interface PrometheusQueryConfig {
3
+ /** Prometheus server base URL, e.g. https://prometheus.example.com */
4
+ baseUrl: string;
5
+ /** PromQL per predictive-scaling metric name */
6
+ queries: Partial<Record<MetricName, string>>;
7
+ pollIntervalMs?: number;
8
+ timeoutMs?: number;
9
+ fetchImpl?: typeof fetch;
10
+ }
11
+ export interface PrometheusQueryResult {
12
+ metric: MetricName;
13
+ value: number;
14
+ timestamp: number;
15
+ }
16
+ /**
17
+ * Polls Prometheus and ingests scalar query results into a callback.
18
+ */
19
+ export declare class PrometheusMetricsCollector {
20
+ private readonly config;
21
+ private readonly onSample;
22
+ private interval;
23
+ constructor(config: PrometheusQueryConfig, onSample: (sample: PrometheusQueryResult) => void);
24
+ pollOnce(): Promise<PrometheusQueryResult[]>;
25
+ start(): void;
26
+ stop(): void;
27
+ private queryMetric;
28
+ }
29
+ export declare function createPrometheusMetricsCollector(config: PrometheusQueryConfig, onSample: (sample: PrometheusQueryResult) => void): PrometheusMetricsCollector;
30
+ //# sourceMappingURL=prometheus-collector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prometheus-collector.d.ts","sourceRoot":"","sources":["../../src/metrics/prometheus-collector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,MAAM,WAAW,qBAAqB;IACpC,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAWD;;GAEG;AACH,qBAAa,0BAA0B;IAInC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAJ3B,OAAO,CAAC,QAAQ,CAA+C;gBAG5C,MAAM,EAAE,qBAAqB,EAC7B,QAAQ,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,IAAI;IAG9D,QAAQ,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC;IAkBlD,KAAK,IAAI,IAAI;IAiBb,IAAI,IAAI,IAAI;YAOE,WAAW;CAwC1B;AAED,wBAAgB,gCAAgC,CAC9C,MAAM,EAAE,qBAAqB,EAC7B,QAAQ,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,IAAI,GAChD,0BAA0B,CAE5B"}