@contractspec/lib.progressive-delivery 11.0.0 → 13.0.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.
@@ -0,0 +1,208 @@
1
+ // src/events.ts
2
+ class DeploymentEventBus {
3
+ listeners = new Set;
4
+ on(listener) {
5
+ this.listeners.add(listener);
6
+ return () => this.listeners.delete(listener);
7
+ }
8
+ emit(event) {
9
+ for (const listener of this.listeners) {
10
+ try {
11
+ listener(event);
12
+ } catch (error) {
13
+ console.error("[progressive-delivery] listener error", error);
14
+ }
15
+ }
16
+ }
17
+ }
18
+ // src/traffic-shifter.ts
19
+ class TrafficShifter {
20
+ mode;
21
+ constructor(mode) {
22
+ this.mode = mode;
23
+ }
24
+ computeSplit(stage) {
25
+ if (this.mode === "blue-green") {
26
+ return stage.percentage >= 100 ? { stable: 0, candidate: 1 } : { stable: 1, candidate: 0 };
27
+ }
28
+ const candidate = Math.min(Math.max(stage.percentage / 100, 0), 1);
29
+ return {
30
+ candidate,
31
+ stable: 1 - candidate
32
+ };
33
+ }
34
+ }
35
+ // src/canary-analyzer.ts
36
+ class CanaryAnalyzer {
37
+ defaults;
38
+ constructor(defaults) {
39
+ this.defaults = defaults;
40
+ }
41
+ evaluate(stage, metrics) {
42
+ const thresholds = { ...this.defaults, ...stage.thresholds };
43
+ const reasons = [];
44
+ if (metrics.errorRate > thresholds.errorRate) {
45
+ reasons.push(`errorRate ${metrics.errorRate.toFixed(4)} > ${thresholds.errorRate}`);
46
+ }
47
+ if (typeof thresholds.latencyP50 === "number" && metrics.latencyP50 > thresholds.latencyP50) {
48
+ reasons.push(`latencyP50 ${metrics.latencyP50}ms > ${thresholds.latencyP50}ms`);
49
+ }
50
+ if (typeof thresholds.latencyP95 === "number" && metrics.latencyP95 > thresholds.latencyP95) {
51
+ reasons.push(`latencyP95 ${metrics.latencyP95}ms > ${thresholds.latencyP95}ms`);
52
+ }
53
+ if (typeof thresholds.latencyP99 === "number" && metrics.latencyP99 > thresholds.latencyP99) {
54
+ reasons.push(`latencyP99 ${metrics.latencyP99}ms > ${thresholds.latencyP99}ms`);
55
+ }
56
+ if (typeof thresholds.throughputDrop === "number" && metrics.throughput < thresholds.throughputDrop) {
57
+ reasons.push(`throughput ${metrics.throughput} < ${thresholds.throughputDrop}`);
58
+ }
59
+ if (thresholds.customEvaluator && !thresholds.customEvaluator(metrics)) {
60
+ reasons.push("custom evaluator reported failure");
61
+ }
62
+ return {
63
+ status: reasons.length === 0 ? "pass" : "fail",
64
+ reasons,
65
+ metrics
66
+ };
67
+ }
68
+ }
69
+ // src/canary-controller.ts
70
+ var DEFAULT_STAGES = [
71
+ { percentage: 1, minDurationMs: 5 * 60 * 1000, label: "1%" },
72
+ { percentage: 10, minDurationMs: 5 * 60 * 1000, label: "10%" },
73
+ { percentage: 50, minDurationMs: 10 * 60 * 1000, label: "50%" },
74
+ { percentage: 100, minDurationMs: 15 * 60 * 1000, label: "100%" }
75
+ ];
76
+
77
+ class CanaryController {
78
+ options;
79
+ stages;
80
+ constructor(options) {
81
+ this.options = options;
82
+ this.stages = options.strategy.stages && options.strategy.stages.length > 0 ? options.strategy.stages : DEFAULT_STAGES;
83
+ }
84
+ getStageList() {
85
+ return [...this.stages];
86
+ }
87
+ async runStage(stage) {
88
+ this.options.eventBus?.emit({
89
+ type: "stage_started",
90
+ timestamp: new Date,
91
+ payload: { stage }
92
+ });
93
+ const metrics = await this.options.metricsProvider(stage, stage.minDurationMs);
94
+ const analysis = this.options.analyzer.evaluate(stage, metrics);
95
+ this.options.eventBus?.emit({
96
+ type: analysis.status === "pass" ? "stage_passed" : "stage_failed",
97
+ timestamp: new Date,
98
+ payload: { stage, metrics, analysis }
99
+ });
100
+ return analysis;
101
+ }
102
+ }
103
+ function createDefaultCanaryController(strategy, metricsProvider, eventBus) {
104
+ const analyzer = new CanaryAnalyzer(strategy.thresholds);
105
+ return new CanaryController({
106
+ strategy,
107
+ analyzer,
108
+ metricsProvider,
109
+ eventBus
110
+ });
111
+ }
112
+ // src/rollback-manager.ts
113
+ class RollbackManager {
114
+ options;
115
+ constructor(options) {
116
+ this.options = options;
117
+ }
118
+ async execute(stage, reason) {
119
+ await this.options.rollback(stage, reason);
120
+ const action = {
121
+ reason,
122
+ stage,
123
+ triggeredAt: new Date
124
+ };
125
+ this.options.onRollback?.(action);
126
+ return action;
127
+ }
128
+ }
129
+ // src/deployment-coordinator.ts
130
+ class DeploymentCoordinator {
131
+ options;
132
+ constructor(options) {
133
+ this.options = options;
134
+ }
135
+ async run() {
136
+ const stages = this.options.controller.getStageList();
137
+ for (const stage of stages) {
138
+ const split = this.options.trafficShifter.computeSplit(stage);
139
+ await this.options.applyTrafficSplit(stage, split);
140
+ const analysis = await this.options.controller.runStage(stage);
141
+ if (analysis.status === "fail") {
142
+ const action = await this.options.rollbackManager.execute(stage, analysis.reasons.join(", "));
143
+ this.options.eventBus?.emit({
144
+ type: "rolled_back",
145
+ timestamp: action.triggeredAt,
146
+ payload: { stage, reasons: analysis.reasons }
147
+ });
148
+ return {
149
+ status: "rolled_back",
150
+ failedStage: stage,
151
+ reasons: analysis.reasons
152
+ };
153
+ }
154
+ }
155
+ if (this.options.strategy.mode === "blue-green") {
156
+ this.options.eventBus?.emit({
157
+ type: "blue_green_swapped",
158
+ timestamp: new Date,
159
+ payload: { strategy: this.options.strategy }
160
+ });
161
+ }
162
+ this.options.eventBus?.emit({
163
+ type: "completed",
164
+ timestamp: new Date,
165
+ payload: { strategy: this.options.strategy }
166
+ });
167
+ return { status: "completed" };
168
+ }
169
+ }
170
+ // src/feature-flags.ts
171
+ var ContractSpecFeatureFlags = {
172
+ LIFECYCLE_DETECTION_ALPHA: "lifecycle_detection_alpha",
173
+ LIFECYCLE_ADVISOR_ALPHA: "lifecycle_advisor_alpha",
174
+ LIFECYCLE_MANAGED_SERVICE: "lifecycle_managed_service",
175
+ STUDIO_VISUAL_BUILDER: "studio_visual_builder",
176
+ STUDIO_AUTO_EVOLUTION: "studio_auto_evolution",
177
+ STUDIO_BYOK: "studio_byok",
178
+ STUDIO_DEDICATED_DEPLOYMENT: "studio_dedicated_deployment",
179
+ STUDIO_INTEGRATION_HUB: "studio_integration_hub",
180
+ STUDIO_KNOWLEDGE_HUB: "studio_knowledge_hub",
181
+ STUDIO_TEMPLATES: "studio_templates"
182
+ };
183
+ var lifecycleFlags = [
184
+ ContractSpecFeatureFlags.LIFECYCLE_DETECTION_ALPHA,
185
+ ContractSpecFeatureFlags.LIFECYCLE_ADVISOR_ALPHA,
186
+ ContractSpecFeatureFlags.LIFECYCLE_MANAGED_SERVICE
187
+ ];
188
+ var studioFlags = [
189
+ ContractSpecFeatureFlags.STUDIO_VISUAL_BUILDER,
190
+ ContractSpecFeatureFlags.STUDIO_AUTO_EVOLUTION,
191
+ ContractSpecFeatureFlags.STUDIO_BYOK,
192
+ ContractSpecFeatureFlags.STUDIO_DEDICATED_DEPLOYMENT,
193
+ ContractSpecFeatureFlags.STUDIO_INTEGRATION_HUB,
194
+ ContractSpecFeatureFlags.STUDIO_KNOWLEDGE_HUB,
195
+ ContractSpecFeatureFlags.STUDIO_TEMPLATES
196
+ ];
197
+ export {
198
+ studioFlags,
199
+ lifecycleFlags,
200
+ createDefaultCanaryController,
201
+ TrafficShifter,
202
+ RollbackManager,
203
+ DeploymentEventBus,
204
+ DeploymentCoordinator,
205
+ ContractSpecFeatureFlags,
206
+ CanaryController,
207
+ CanaryAnalyzer
208
+ };
@@ -1,16 +1,12 @@
1
- import { CanaryStage, DeploymentMetrics, DeploymentThresholds } from "./types.js";
2
-
3
- //#region src/canary-analyzer.d.ts
4
- interface AnalysisResult {
5
- status: 'pass' | 'fail';
6
- reasons: string[];
7
- metrics: DeploymentMetrics;
1
+ import type { CanaryStage, DeploymentMetrics, DeploymentThresholds } from './types';
2
+ export interface AnalysisResult {
3
+ status: 'pass' | 'fail';
4
+ reasons: string[];
5
+ metrics: DeploymentMetrics;
8
6
  }
9
- declare class CanaryAnalyzer {
10
- private readonly defaults;
11
- constructor(defaults: DeploymentThresholds);
12
- evaluate(stage: CanaryStage, metrics: DeploymentMetrics): AnalysisResult;
7
+ export declare class CanaryAnalyzer {
8
+ private readonly defaults;
9
+ constructor(defaults: DeploymentThresholds);
10
+ evaluate(stage: CanaryStage, metrics: DeploymentMetrics): AnalysisResult;
13
11
  }
14
- //#endregion
15
- export { AnalysisResult, CanaryAnalyzer };
16
12
  //# sourceMappingURL=canary-analyzer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"canary-analyzer.d.ts","names":[],"sources":["../src/canary-analyzer.ts"],"mappings":";;;UAMiB,cAAA;EACf,MAAA;EACA,OAAA;EACA,OAAA,EAAS,iBAAA;AAAA;AAAA,cAGE,cAAA;EAAA,iBACkB,QAAA;cAAA,QAAA,EAAU,oBAAA;EAEvC,QAAA,CAAS,KAAA,EAAO,WAAA,EAAa,OAAA,EAAS,iBAAA,GAAoB,cAAA;AAAA"}
1
+ {"version":3,"file":"canary-analyzer.d.ts","sourceRoot":"","sources":["../src/canary-analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,iBAAiB,EACjB,oBAAoB,EACrB,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,iBAAiB,CAAC;CAC5B;AAED,qBAAa,cAAc;IACb,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,oBAAoB;IAE3D,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,iBAAiB,GAAG,cAAc;CAwDzE"}
@@ -1,22 +1,18 @@
1
- import { CanaryStage, DeploymentStrategy, MetricsProvider } from "./types.js";
2
- import { DeploymentEventBus } from "./events.js";
3
- import { AnalysisResult, CanaryAnalyzer } from "./canary-analyzer.js";
4
-
5
- //#region src/canary-controller.d.ts
6
- interface CanaryControllerOptions {
7
- strategy: DeploymentStrategy;
8
- analyzer: CanaryAnalyzer;
9
- metricsProvider: MetricsProvider;
10
- eventBus?: DeploymentEventBus;
1
+ import { CanaryAnalyzer, type AnalysisResult } from './canary-analyzer';
2
+ import { DeploymentEventBus } from './events';
3
+ import type { CanaryStage, DeploymentStrategy, MetricsProvider } from './types';
4
+ export interface CanaryControllerOptions {
5
+ strategy: DeploymentStrategy;
6
+ analyzer: CanaryAnalyzer;
7
+ metricsProvider: MetricsProvider;
8
+ eventBus?: DeploymentEventBus;
11
9
  }
12
- declare class CanaryController {
13
- private readonly options;
14
- private readonly stages;
15
- constructor(options: CanaryControllerOptions);
16
- getStageList(): CanaryStage[];
17
- runStage(stage: CanaryStage): Promise<AnalysisResult>;
10
+ export declare class CanaryController {
11
+ private readonly options;
12
+ private readonly stages;
13
+ constructor(options: CanaryControllerOptions);
14
+ getStageList(): CanaryStage[];
15
+ runStage(stage: CanaryStage): Promise<AnalysisResult>;
18
16
  }
19
- declare function createDefaultCanaryController(strategy: DeploymentStrategy, metricsProvider: MetricsProvider, eventBus?: DeploymentEventBus): CanaryController;
20
- //#endregion
21
- export { CanaryController, CanaryControllerOptions, createDefaultCanaryController };
17
+ export declare function createDefaultCanaryController(strategy: DeploymentStrategy, metricsProvider: MetricsProvider, eventBus?: DeploymentEventBus): CanaryController;
22
18
  //# sourceMappingURL=canary-controller.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"canary-controller.d.ts","names":[],"sources":["../src/canary-controller.ts"],"mappings":";;;;;UAWiB,uBAAA;EACf,QAAA,EAAU,kBAAA;EACV,QAAA,EAAU,cAAA;EACV,eAAA,EAAiB,eAAA;EACjB,QAAA,GAAW,kBAAA;AAAA;AAAA,cAGA,gBAAA;EAAA,iBAGkB,OAAA;EAAA,iBAFZ,MAAA;cAEY,OAAA,EAAS,uBAAA;EAOtC,YAAA,CAAA,GAAY,WAAA;EAIN,QAAA,CAAS,KAAA,EAAO,WAAA,GAAc,OAAA,CAAQ,cAAA;AAAA;AAAA,iBAuB9B,6BAAA,CACd,QAAA,EAAU,kBAAA,EACV,eAAA,EAAiB,eAAA,EACjB,QAAA,GAAW,kBAAA,GAAkB,gBAAA"}
1
+ {"version":3,"file":"canary-controller.d.ts","sourceRoot":"","sources":["../src/canary-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAShF,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,QAAQ,EAAE,cAAc,CAAC;IACzB,eAAe,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC/B;AAED,qBAAa,gBAAgB;IAGf,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;gBAEV,OAAO,EAAE,uBAAuB;IAO7D,YAAY;IAIN,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC;CAqB5D;AAED,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,kBAAkB,EAC5B,eAAe,EAAE,eAAe,EAChC,QAAQ,CAAC,EAAE,kBAAkB,oBAS9B"}
@@ -1,28 +1,24 @@
1
- import { CanaryStage, DeploymentStrategy, TrafficSplit } from "./types.js";
2
- import { DeploymentEventBus } from "./events.js";
3
- import { TrafficShifter } from "./traffic-shifter.js";
4
- import { CanaryController } from "./canary-controller.js";
5
- import { RollbackManager } from "./rollback-manager.js";
6
-
7
- //#region src/deployment-coordinator.d.ts
8
- interface DeploymentCoordinatorOptions {
9
- strategy: DeploymentStrategy;
10
- controller: CanaryController;
11
- trafficShifter: TrafficShifter;
12
- rollbackManager: RollbackManager;
13
- applyTrafficSplit: (stage: CanaryStage, split: TrafficSplit) => void | Promise<void>;
14
- eventBus?: DeploymentEventBus;
1
+ import { CanaryController } from './canary-controller';
2
+ import { DeploymentEventBus } from './events';
3
+ import { RollbackManager } from './rollback-manager';
4
+ import { TrafficShifter } from './traffic-shifter';
5
+ import type { CanaryStage, DeploymentStrategy, TrafficSplit } from './types';
6
+ export interface DeploymentCoordinatorOptions {
7
+ strategy: DeploymentStrategy;
8
+ controller: CanaryController;
9
+ trafficShifter: TrafficShifter;
10
+ rollbackManager: RollbackManager;
11
+ applyTrafficSplit: (stage: CanaryStage, split: TrafficSplit) => void | Promise<void>;
12
+ eventBus?: DeploymentEventBus;
15
13
  }
16
- interface DeploymentRunResult {
17
- status: 'completed' | 'rolled_back';
18
- failedStage?: CanaryStage;
19
- reasons?: string[];
14
+ export interface DeploymentRunResult {
15
+ status: 'completed' | 'rolled_back';
16
+ failedStage?: CanaryStage;
17
+ reasons?: string[];
20
18
  }
21
- declare class DeploymentCoordinator {
22
- private readonly options;
23
- constructor(options: DeploymentCoordinatorOptions);
24
- run(): Promise<DeploymentRunResult>;
19
+ export declare class DeploymentCoordinator {
20
+ private readonly options;
21
+ constructor(options: DeploymentCoordinatorOptions);
22
+ run(): Promise<DeploymentRunResult>;
25
23
  }
26
- //#endregion
27
- export { DeploymentCoordinator, DeploymentCoordinatorOptions, DeploymentRunResult };
28
24
  //# sourceMappingURL=deployment-coordinator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"deployment-coordinator.d.ts","names":[],"sources":["../src/deployment-coordinator.ts"],"mappings":";;;;;;;UAMiB,4BAAA;EACf,QAAA,EAAU,kBAAA;EACV,UAAA,EAAY,gBAAA;EACZ,cAAA,EAAgB,cAAA;EAChB,eAAA,EAAiB,eAAA;EACjB,iBAAA,GACE,KAAA,EAAO,WAAA,EACP,KAAA,EAAO,YAAA,YACG,OAAA;EACZ,QAAA,GAAW,kBAAA;AAAA;AAAA,UAGI,mBAAA;EACf,MAAA;EACA,WAAA,GAAc,WAAA;EACd,OAAA;AAAA;AAAA,cAGW,qBAAA;EAAA,iBACkB,OAAA;cAAA,OAAA,EAAS,4BAAA;EAEhC,GAAA,CAAA,GAAO,OAAA,CAAQ,mBAAA;AAAA"}
1
+ {"version":3,"file":"deployment-coordinator.d.ts","sourceRoot":"","sources":["../src/deployment-coordinator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE7E,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,UAAU,EAAE,gBAAgB,CAAC;IAC7B,cAAc,EAAE,cAAc,CAAC;IAC/B,eAAe,EAAE,eAAe,CAAC;IACjC,iBAAiB,EAAE,CACjB,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,YAAY,KAChB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC/B;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,WAAW,GAAG,aAAa,CAAC;IACpC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,qBAAa,qBAAqB;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,4BAA4B;IAE5D,GAAG,IAAI,OAAO,CAAC,mBAAmB,CAAC;CA4C1C"}
package/dist/events.d.ts CHANGED
@@ -1,11 +1,7 @@
1
- import { DeploymentEvent, DeploymentEventListener } from "./types.js";
2
-
3
- //#region src/events.d.ts
4
- declare class DeploymentEventBus {
5
- private listeners;
6
- on(listener: DeploymentEventListener): () => boolean;
7
- emit(event: DeploymentEvent): void;
1
+ import type { DeploymentEvent, DeploymentEventListener } from './types';
2
+ export declare class DeploymentEventBus {
3
+ private listeners;
4
+ on(listener: DeploymentEventListener): () => boolean;
5
+ emit(event: DeploymentEvent): void;
8
6
  }
9
- //#endregion
10
- export { DeploymentEventBus };
11
7
  //# sourceMappingURL=events.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","names":[],"sources":["../src/events.ts"],"mappings":";;;cAEa,kBAAA;EAAA,QACH,SAAA;EAER,EAAA,CAAG,QAAA,EAAU,uBAAA;EAKb,IAAA,CAAK,KAAA,EAAO,eAAA;AAAA"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAExE,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,SAAS,CAAsC;IAEvD,EAAE,CAAC,QAAQ,EAAE,uBAAuB;IAKpC,IAAI,CAAC,KAAK,EAAE,eAAe;CAS5B"}
@@ -1,19 +1,16 @@
1
- //#region src/feature-flags.d.ts
2
- declare const ContractSpecFeatureFlags: {
3
- readonly LIFECYCLE_DETECTION_ALPHA: "lifecycle_detection_alpha";
4
- readonly LIFECYCLE_ADVISOR_ALPHA: "lifecycle_advisor_alpha";
5
- readonly LIFECYCLE_MANAGED_SERVICE: "lifecycle_managed_service";
6
- readonly STUDIO_VISUAL_BUILDER: "studio_visual_builder";
7
- readonly STUDIO_AUTO_EVOLUTION: "studio_auto_evolution";
8
- readonly STUDIO_BYOK: "studio_byok";
9
- readonly STUDIO_DEDICATED_DEPLOYMENT: "studio_dedicated_deployment";
10
- readonly STUDIO_INTEGRATION_HUB: "studio_integration_hub";
11
- readonly STUDIO_KNOWLEDGE_HUB: "studio_knowledge_hub";
12
- readonly STUDIO_TEMPLATES: "studio_templates";
1
+ export declare const ContractSpecFeatureFlags: {
2
+ readonly LIFECYCLE_DETECTION_ALPHA: "lifecycle_detection_alpha";
3
+ readonly LIFECYCLE_ADVISOR_ALPHA: "lifecycle_advisor_alpha";
4
+ readonly LIFECYCLE_MANAGED_SERVICE: "lifecycle_managed_service";
5
+ readonly STUDIO_VISUAL_BUILDER: "studio_visual_builder";
6
+ readonly STUDIO_AUTO_EVOLUTION: "studio_auto_evolution";
7
+ readonly STUDIO_BYOK: "studio_byok";
8
+ readonly STUDIO_DEDICATED_DEPLOYMENT: "studio_dedicated_deployment";
9
+ readonly STUDIO_INTEGRATION_HUB: "studio_integration_hub";
10
+ readonly STUDIO_KNOWLEDGE_HUB: "studio_knowledge_hub";
11
+ readonly STUDIO_TEMPLATES: "studio_templates";
13
12
  };
14
- type ContractSpecFeatureFlag = keyof typeof ContractSpecFeatureFlags;
15
- declare const lifecycleFlags: ("lifecycle_detection_alpha" | "lifecycle_advisor_alpha" | "lifecycle_managed_service")[];
16
- declare const studioFlags: ("studio_visual_builder" | "studio_auto_evolution" | "studio_byok" | "studio_dedicated_deployment" | "studio_integration_hub" | "studio_knowledge_hub" | "studio_templates")[];
17
- //#endregion
18
- export { ContractSpecFeatureFlag, ContractSpecFeatureFlags, lifecycleFlags, studioFlags };
13
+ export type ContractSpecFeatureFlag = keyof typeof ContractSpecFeatureFlags;
14
+ export declare const lifecycleFlags: ("lifecycle_detection_alpha" | "lifecycle_advisor_alpha" | "lifecycle_managed_service")[];
15
+ export declare const studioFlags: ("studio_visual_builder" | "studio_auto_evolution" | "studio_byok" | "studio_dedicated_deployment" | "studio_integration_hub" | "studio_knowledge_hub" | "studio_templates")[];
19
16
  //# sourceMappingURL=feature-flags.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"feature-flags.d.ts","names":[],"sources":["../src/feature-flags.ts"],"mappings":";cAAa,wBAAA;EAAA;;;;;;;;;;;KAaD,uBAAA,gBAAuC,wBAAA;AAAA,cAEtC,cAAA;AAAA,cAMA,WAAA"}
1
+ {"version":3,"file":"feature-flags.d.ts","sourceRoot":"","sources":["../src/feature-flags.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,wBAAwB;;;;;;;;;;;CAW3B,CAAC;AAEX,MAAM,MAAM,uBAAuB,GAAG,MAAM,OAAO,wBAAwB,CAAC;AAE5E,eAAO,MAAM,cAAc,2FAI1B,CAAC;AAEF,eAAO,MAAM,WAAW,gLAQvB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { CanaryStage, DeploymentEvent, DeploymentEventListener, DeploymentMetrics, DeploymentMode, DeploymentStrategy, DeploymentThresholds, MetricsProvider, OperationTarget, RollbackAction, TrafficSplit } from "./types.js";
2
- import { DeploymentEventBus } from "./events.js";
3
- import { TrafficShifter } from "./traffic-shifter.js";
4
- import { AnalysisResult, CanaryAnalyzer } from "./canary-analyzer.js";
5
- import { CanaryController, CanaryControllerOptions, createDefaultCanaryController } from "./canary-controller.js";
6
- import { RollbackManager, RollbackManagerOptions } from "./rollback-manager.js";
7
- import { DeploymentCoordinator, DeploymentCoordinatorOptions, DeploymentRunResult } from "./deployment-coordinator.js";
8
- import { ContractSpecFeatureFlag, ContractSpecFeatureFlags, lifecycleFlags, studioFlags } from "./feature-flags.js";
9
- export { AnalysisResult, CanaryAnalyzer, CanaryController, CanaryControllerOptions, CanaryStage, ContractSpecFeatureFlag, ContractSpecFeatureFlags, DeploymentCoordinator, DeploymentCoordinatorOptions, DeploymentEvent, DeploymentEventBus, DeploymentEventListener, DeploymentMetrics, DeploymentMode, DeploymentRunResult, DeploymentStrategy, DeploymentThresholds, MetricsProvider, OperationTarget, RollbackAction, RollbackManager, RollbackManagerOptions, TrafficShifter, TrafficSplit, createDefaultCanaryController, lifecycleFlags, studioFlags };
1
+ export * from './types';
2
+ export * from './events';
3
+ export * from './traffic-shifter';
4
+ export * from './canary-analyzer';
5
+ export * from './canary-controller';
6
+ export * from './rollback-manager';
7
+ export * from './deployment-coordinator';
8
+ export * from './feature-flags';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -1,9 +1,209 @@
1
- import { DeploymentEventBus } from "./events.js";
2
- import { TrafficShifter } from "./traffic-shifter.js";
3
- import { CanaryAnalyzer } from "./canary-analyzer.js";
4
- import { CanaryController, createDefaultCanaryController } from "./canary-controller.js";
5
- import { RollbackManager } from "./rollback-manager.js";
6
- import { DeploymentCoordinator } from "./deployment-coordinator.js";
7
- import { ContractSpecFeatureFlags, lifecycleFlags, studioFlags } from "./feature-flags.js";
1
+ // @bun
2
+ // src/events.ts
3
+ class DeploymentEventBus {
4
+ listeners = new Set;
5
+ on(listener) {
6
+ this.listeners.add(listener);
7
+ return () => this.listeners.delete(listener);
8
+ }
9
+ emit(event) {
10
+ for (const listener of this.listeners) {
11
+ try {
12
+ listener(event);
13
+ } catch (error) {
14
+ console.error("[progressive-delivery] listener error", error);
15
+ }
16
+ }
17
+ }
18
+ }
19
+ // src/traffic-shifter.ts
20
+ class TrafficShifter {
21
+ mode;
22
+ constructor(mode) {
23
+ this.mode = mode;
24
+ }
25
+ computeSplit(stage) {
26
+ if (this.mode === "blue-green") {
27
+ return stage.percentage >= 100 ? { stable: 0, candidate: 1 } : { stable: 1, candidate: 0 };
28
+ }
29
+ const candidate = Math.min(Math.max(stage.percentage / 100, 0), 1);
30
+ return {
31
+ candidate,
32
+ stable: 1 - candidate
33
+ };
34
+ }
35
+ }
36
+ // src/canary-analyzer.ts
37
+ class CanaryAnalyzer {
38
+ defaults;
39
+ constructor(defaults) {
40
+ this.defaults = defaults;
41
+ }
42
+ evaluate(stage, metrics) {
43
+ const thresholds = { ...this.defaults, ...stage.thresholds };
44
+ const reasons = [];
45
+ if (metrics.errorRate > thresholds.errorRate) {
46
+ reasons.push(`errorRate ${metrics.errorRate.toFixed(4)} > ${thresholds.errorRate}`);
47
+ }
48
+ if (typeof thresholds.latencyP50 === "number" && metrics.latencyP50 > thresholds.latencyP50) {
49
+ reasons.push(`latencyP50 ${metrics.latencyP50}ms > ${thresholds.latencyP50}ms`);
50
+ }
51
+ if (typeof thresholds.latencyP95 === "number" && metrics.latencyP95 > thresholds.latencyP95) {
52
+ reasons.push(`latencyP95 ${metrics.latencyP95}ms > ${thresholds.latencyP95}ms`);
53
+ }
54
+ if (typeof thresholds.latencyP99 === "number" && metrics.latencyP99 > thresholds.latencyP99) {
55
+ reasons.push(`latencyP99 ${metrics.latencyP99}ms > ${thresholds.latencyP99}ms`);
56
+ }
57
+ if (typeof thresholds.throughputDrop === "number" && metrics.throughput < thresholds.throughputDrop) {
58
+ reasons.push(`throughput ${metrics.throughput} < ${thresholds.throughputDrop}`);
59
+ }
60
+ if (thresholds.customEvaluator && !thresholds.customEvaluator(metrics)) {
61
+ reasons.push("custom evaluator reported failure");
62
+ }
63
+ return {
64
+ status: reasons.length === 0 ? "pass" : "fail",
65
+ reasons,
66
+ metrics
67
+ };
68
+ }
69
+ }
70
+ // src/canary-controller.ts
71
+ var DEFAULT_STAGES = [
72
+ { percentage: 1, minDurationMs: 5 * 60 * 1000, label: "1%" },
73
+ { percentage: 10, minDurationMs: 5 * 60 * 1000, label: "10%" },
74
+ { percentage: 50, minDurationMs: 10 * 60 * 1000, label: "50%" },
75
+ { percentage: 100, minDurationMs: 15 * 60 * 1000, label: "100%" }
76
+ ];
8
77
 
9
- export { CanaryAnalyzer, CanaryController, ContractSpecFeatureFlags, DeploymentCoordinator, DeploymentEventBus, RollbackManager, TrafficShifter, createDefaultCanaryController, lifecycleFlags, studioFlags };
78
+ class CanaryController {
79
+ options;
80
+ stages;
81
+ constructor(options) {
82
+ this.options = options;
83
+ this.stages = options.strategy.stages && options.strategy.stages.length > 0 ? options.strategy.stages : DEFAULT_STAGES;
84
+ }
85
+ getStageList() {
86
+ return [...this.stages];
87
+ }
88
+ async runStage(stage) {
89
+ this.options.eventBus?.emit({
90
+ type: "stage_started",
91
+ timestamp: new Date,
92
+ payload: { stage }
93
+ });
94
+ const metrics = await this.options.metricsProvider(stage, stage.minDurationMs);
95
+ const analysis = this.options.analyzer.evaluate(stage, metrics);
96
+ this.options.eventBus?.emit({
97
+ type: analysis.status === "pass" ? "stage_passed" : "stage_failed",
98
+ timestamp: new Date,
99
+ payload: { stage, metrics, analysis }
100
+ });
101
+ return analysis;
102
+ }
103
+ }
104
+ function createDefaultCanaryController(strategy, metricsProvider, eventBus) {
105
+ const analyzer = new CanaryAnalyzer(strategy.thresholds);
106
+ return new CanaryController({
107
+ strategy,
108
+ analyzer,
109
+ metricsProvider,
110
+ eventBus
111
+ });
112
+ }
113
+ // src/rollback-manager.ts
114
+ class RollbackManager {
115
+ options;
116
+ constructor(options) {
117
+ this.options = options;
118
+ }
119
+ async execute(stage, reason) {
120
+ await this.options.rollback(stage, reason);
121
+ const action = {
122
+ reason,
123
+ stage,
124
+ triggeredAt: new Date
125
+ };
126
+ this.options.onRollback?.(action);
127
+ return action;
128
+ }
129
+ }
130
+ // src/deployment-coordinator.ts
131
+ class DeploymentCoordinator {
132
+ options;
133
+ constructor(options) {
134
+ this.options = options;
135
+ }
136
+ async run() {
137
+ const stages = this.options.controller.getStageList();
138
+ for (const stage of stages) {
139
+ const split = this.options.trafficShifter.computeSplit(stage);
140
+ await this.options.applyTrafficSplit(stage, split);
141
+ const analysis = await this.options.controller.runStage(stage);
142
+ if (analysis.status === "fail") {
143
+ const action = await this.options.rollbackManager.execute(stage, analysis.reasons.join(", "));
144
+ this.options.eventBus?.emit({
145
+ type: "rolled_back",
146
+ timestamp: action.triggeredAt,
147
+ payload: { stage, reasons: analysis.reasons }
148
+ });
149
+ return {
150
+ status: "rolled_back",
151
+ failedStage: stage,
152
+ reasons: analysis.reasons
153
+ };
154
+ }
155
+ }
156
+ if (this.options.strategy.mode === "blue-green") {
157
+ this.options.eventBus?.emit({
158
+ type: "blue_green_swapped",
159
+ timestamp: new Date,
160
+ payload: { strategy: this.options.strategy }
161
+ });
162
+ }
163
+ this.options.eventBus?.emit({
164
+ type: "completed",
165
+ timestamp: new Date,
166
+ payload: { strategy: this.options.strategy }
167
+ });
168
+ return { status: "completed" };
169
+ }
170
+ }
171
+ // src/feature-flags.ts
172
+ var ContractSpecFeatureFlags = {
173
+ LIFECYCLE_DETECTION_ALPHA: "lifecycle_detection_alpha",
174
+ LIFECYCLE_ADVISOR_ALPHA: "lifecycle_advisor_alpha",
175
+ LIFECYCLE_MANAGED_SERVICE: "lifecycle_managed_service",
176
+ STUDIO_VISUAL_BUILDER: "studio_visual_builder",
177
+ STUDIO_AUTO_EVOLUTION: "studio_auto_evolution",
178
+ STUDIO_BYOK: "studio_byok",
179
+ STUDIO_DEDICATED_DEPLOYMENT: "studio_dedicated_deployment",
180
+ STUDIO_INTEGRATION_HUB: "studio_integration_hub",
181
+ STUDIO_KNOWLEDGE_HUB: "studio_knowledge_hub",
182
+ STUDIO_TEMPLATES: "studio_templates"
183
+ };
184
+ var lifecycleFlags = [
185
+ ContractSpecFeatureFlags.LIFECYCLE_DETECTION_ALPHA,
186
+ ContractSpecFeatureFlags.LIFECYCLE_ADVISOR_ALPHA,
187
+ ContractSpecFeatureFlags.LIFECYCLE_MANAGED_SERVICE
188
+ ];
189
+ var studioFlags = [
190
+ ContractSpecFeatureFlags.STUDIO_VISUAL_BUILDER,
191
+ ContractSpecFeatureFlags.STUDIO_AUTO_EVOLUTION,
192
+ ContractSpecFeatureFlags.STUDIO_BYOK,
193
+ ContractSpecFeatureFlags.STUDIO_DEDICATED_DEPLOYMENT,
194
+ ContractSpecFeatureFlags.STUDIO_INTEGRATION_HUB,
195
+ ContractSpecFeatureFlags.STUDIO_KNOWLEDGE_HUB,
196
+ ContractSpecFeatureFlags.STUDIO_TEMPLATES
197
+ ];
198
+ export {
199
+ studioFlags,
200
+ lifecycleFlags,
201
+ createDefaultCanaryController,
202
+ TrafficShifter,
203
+ RollbackManager,
204
+ DeploymentEventBus,
205
+ DeploymentCoordinator,
206
+ ContractSpecFeatureFlags,
207
+ CanaryController,
208
+ CanaryAnalyzer
209
+ };