@contractspec/lib.progressive-delivery 0.0.0-canary-20260113162409

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.
package/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # @contractspec/lib.progressive-delivery
2
+
3
+ Progressive delivery primitives for ContractSpec apps. Manage canary and blue-green deployments with guardrails, integration hooks, and automatic rollback.
4
+
5
+ ## Features
6
+
7
+ - Declarative deployment strategies (canary, blue-green, hybrid)
8
+ - Stage-based traffic shifting with configurable durations
9
+ - Metric-driven guardrails (error rate, latency percentiles, throughput)
10
+ - Automatic rollback with structured events
11
+ - Event hooks for logging, auditing, and UI updates
12
+ - Works with `@contractspec/lib.observability` and feature flag pipelines
13
+
14
+ ## Quick Start
15
+
16
+ ```ts
17
+ import {
18
+ DeploymentCoordinator,
19
+ createDefaultCanaryController,
20
+ } from '@contractspec/lib.progressive-delivery';
21
+
22
+ const coordinator = new DeploymentCoordinator({
23
+ strategy,
24
+ controller: createDefaultCanaryController(strategy),
25
+ metricsProvider: fetchMetricsFromOtEL,
26
+ rollbackManager,
27
+ });
28
+
29
+ await coordinator.run();
30
+ ```
31
+
32
+ See the docs in `docs/tech/PHASE_5_ZERO_TOUCH_OPERATIONS.md` for full workflows.
@@ -0,0 +1,16 @@
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;
8
+ }
9
+ declare class CanaryAnalyzer {
10
+ private readonly defaults;
11
+ constructor(defaults: DeploymentThresholds);
12
+ evaluate(stage: CanaryStage, metrics: DeploymentMetrics): AnalysisResult;
13
+ }
14
+ //#endregion
15
+ export { AnalysisResult, CanaryAnalyzer };
16
+ //# sourceMappingURL=canary-analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canary-analyzer.d.ts","names":[],"sources":["../src/canary-analyzer.ts"],"sourcesContent":[],"mappings":";;;UAMiB,cAAA;;EAAA,OAAA,EAAA,MAAA,EAAc;EAMlB,OAAA,EAHF,iBAGgB;;AAGT,cAHL,cAAA,CAGK;EAAsB,iBAAA,QAAA;EAAoB,WAAA,CAAA,QAAA,EAFnB,oBAEmB;EAAc,QAAA,CAAA,KAAA,EAAxD,WAAwD,EAAA,OAAA,EAAlC,iBAAkC,CAAA,EAAd,cAAc"}
@@ -0,0 +1,28 @@
1
+ //#region src/canary-analyzer.ts
2
+ var CanaryAnalyzer = class {
3
+ constructor(defaults) {
4
+ this.defaults = defaults;
5
+ }
6
+ evaluate(stage, metrics) {
7
+ const thresholds = {
8
+ ...this.defaults,
9
+ ...stage.thresholds
10
+ };
11
+ const reasons = [];
12
+ if (metrics.errorRate > thresholds.errorRate) reasons.push(`errorRate ${metrics.errorRate.toFixed(4)} > ${thresholds.errorRate}`);
13
+ if (typeof thresholds.latencyP50 === "number" && metrics.latencyP50 > thresholds.latencyP50) reasons.push(`latencyP50 ${metrics.latencyP50}ms > ${thresholds.latencyP50}ms`);
14
+ if (typeof thresholds.latencyP95 === "number" && metrics.latencyP95 > thresholds.latencyP95) reasons.push(`latencyP95 ${metrics.latencyP95}ms > ${thresholds.latencyP95}ms`);
15
+ if (typeof thresholds.latencyP99 === "number" && metrics.latencyP99 > thresholds.latencyP99) reasons.push(`latencyP99 ${metrics.latencyP99}ms > ${thresholds.latencyP99}ms`);
16
+ if (typeof thresholds.throughputDrop === "number" && metrics.throughput < thresholds.throughputDrop) reasons.push(`throughput ${metrics.throughput} < ${thresholds.throughputDrop}`);
17
+ if (thresholds.customEvaluator && !thresholds.customEvaluator(metrics)) reasons.push("custom evaluator reported failure");
18
+ return {
19
+ status: reasons.length === 0 ? "pass" : "fail",
20
+ reasons,
21
+ metrics
22
+ };
23
+ }
24
+ };
25
+
26
+ //#endregion
27
+ export { CanaryAnalyzer };
28
+ //# sourceMappingURL=canary-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canary-analyzer.js","names":[],"sources":["../src/canary-analyzer.ts"],"sourcesContent":["import type {\n CanaryStage,\n DeploymentMetrics,\n DeploymentThresholds,\n} from './types';\n\nexport interface AnalysisResult {\n status: 'pass' | 'fail';\n reasons: string[];\n metrics: DeploymentMetrics;\n}\n\nexport class CanaryAnalyzer {\n constructor(private readonly defaults: DeploymentThresholds) {}\n\n evaluate(stage: CanaryStage, metrics: DeploymentMetrics): AnalysisResult {\n const thresholds = { ...this.defaults, ...stage.thresholds };\n const reasons: string[] = [];\n\n if (metrics.errorRate > thresholds.errorRate) {\n reasons.push(\n `errorRate ${metrics.errorRate.toFixed(4)} > ${thresholds.errorRate}`\n );\n }\n\n if (\n typeof thresholds.latencyP50 === 'number' &&\n metrics.latencyP50 > thresholds.latencyP50\n ) {\n reasons.push(\n `latencyP50 ${metrics.latencyP50}ms > ${thresholds.latencyP50}ms`\n );\n }\n\n if (\n typeof thresholds.latencyP95 === 'number' &&\n metrics.latencyP95 > thresholds.latencyP95\n ) {\n reasons.push(\n `latencyP95 ${metrics.latencyP95}ms > ${thresholds.latencyP95}ms`\n );\n }\n\n if (\n typeof thresholds.latencyP99 === 'number' &&\n metrics.latencyP99 > thresholds.latencyP99\n ) {\n reasons.push(\n `latencyP99 ${metrics.latencyP99}ms > ${thresholds.latencyP99}ms`\n );\n }\n\n if (\n typeof thresholds.throughputDrop === 'number' &&\n metrics.throughput < thresholds.throughputDrop\n ) {\n reasons.push(\n `throughput ${metrics.throughput} < ${thresholds.throughputDrop}`\n );\n }\n\n if (thresholds.customEvaluator && !thresholds.customEvaluator(metrics)) {\n reasons.push('custom evaluator reported failure');\n }\n\n return {\n status: reasons.length === 0 ? 'pass' : 'fail',\n reasons,\n metrics,\n };\n }\n}\n"],"mappings":";AAYA,IAAa,iBAAb,MAA4B;CAC1B,YAAY,AAAiB,UAAgC;EAAhC;;CAE7B,SAAS,OAAoB,SAA4C;EACvE,MAAM,aAAa;GAAE,GAAG,KAAK;GAAU,GAAG,MAAM;GAAY;EAC5D,MAAM,UAAoB,EAAE;AAE5B,MAAI,QAAQ,YAAY,WAAW,UACjC,SAAQ,KACN,aAAa,QAAQ,UAAU,QAAQ,EAAE,CAAC,KAAK,WAAW,YAC3D;AAGH,MACE,OAAO,WAAW,eAAe,YACjC,QAAQ,aAAa,WAAW,WAEhC,SAAQ,KACN,cAAc,QAAQ,WAAW,OAAO,WAAW,WAAW,IAC/D;AAGH,MACE,OAAO,WAAW,eAAe,YACjC,QAAQ,aAAa,WAAW,WAEhC,SAAQ,KACN,cAAc,QAAQ,WAAW,OAAO,WAAW,WAAW,IAC/D;AAGH,MACE,OAAO,WAAW,eAAe,YACjC,QAAQ,aAAa,WAAW,WAEhC,SAAQ,KACN,cAAc,QAAQ,WAAW,OAAO,WAAW,WAAW,IAC/D;AAGH,MACE,OAAO,WAAW,mBAAmB,YACrC,QAAQ,aAAa,WAAW,eAEhC,SAAQ,KACN,cAAc,QAAQ,WAAW,KAAK,WAAW,iBAClD;AAGH,MAAI,WAAW,mBAAmB,CAAC,WAAW,gBAAgB,QAAQ,CACpE,SAAQ,KAAK,oCAAoC;AAGnD,SAAO;GACL,QAAQ,QAAQ,WAAW,IAAI,SAAS;GACxC;GACA;GACD"}
@@ -0,0 +1,22 @@
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;
11
+ }
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>;
18
+ }
19
+ declare function createDefaultCanaryController(strategy: DeploymentStrategy, metricsProvider: MetricsProvider, eventBus?: DeploymentEventBus): CanaryController;
20
+ //#endregion
21
+ export { CanaryController, CanaryControllerOptions, createDefaultCanaryController };
22
+ //# sourceMappingURL=canary-controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canary-controller.d.ts","names":[],"sources":["../src/canary-controller.ts"],"sourcesContent":[],"mappings":";;;;;UAWiB,uBAAA;YACL;EADK,QAAA,EAEL,cAFK;EACL,eAAA,EAEO,eAFP;EACA,QAAA,CAAA,EAEC,kBAFD;;AAEC,cAGA,gBAAA,CAHA;EAAkB,iBAAA,OAAA;EAGlB,iBAAA,MAAgB;EAGW,WAAA,CAAA,OAAA,EAAA,uBAAA;EAO1B,YAAA,CAAA,CAAA,EAAA,WAAA,EAAA;EAIU,QAAA,CAAA,KAAA,EAAA,WAAA,CAAA,EAAc,OAAd,CAAsB,cAAtB,CAAA;;AAAc,iBAuBtB,6BAAA,CAvBsB,QAAA,EAwB1B,kBAxB0B,EAAA,eAAA,EAyBnB,eAzBmB,EAAA,QAAA,CAAA,EA0BzB,kBA1ByB,CAAA,EA0BP,gBA1BO"}
@@ -0,0 +1,66 @@
1
+ import { CanaryAnalyzer } from "./canary-analyzer.js";
2
+
3
+ //#region src/canary-controller.ts
4
+ const DEFAULT_STAGES = [
5
+ {
6
+ percentage: 1,
7
+ minDurationMs: 300 * 1e3,
8
+ label: "1%"
9
+ },
10
+ {
11
+ percentage: 10,
12
+ minDurationMs: 300 * 1e3,
13
+ label: "10%"
14
+ },
15
+ {
16
+ percentage: 50,
17
+ minDurationMs: 600 * 1e3,
18
+ label: "50%"
19
+ },
20
+ {
21
+ percentage: 100,
22
+ minDurationMs: 900 * 1e3,
23
+ label: "100%"
24
+ }
25
+ ];
26
+ var CanaryController = class {
27
+ stages;
28
+ constructor(options) {
29
+ this.options = options;
30
+ this.stages = options.strategy.stages && options.strategy.stages.length > 0 ? options.strategy.stages : DEFAULT_STAGES;
31
+ }
32
+ getStageList() {
33
+ return [...this.stages];
34
+ }
35
+ async runStage(stage) {
36
+ this.options.eventBus?.emit({
37
+ type: "stage_started",
38
+ timestamp: /* @__PURE__ */ new Date(),
39
+ payload: { stage }
40
+ });
41
+ const metrics = await this.options.metricsProvider(stage, stage.minDurationMs);
42
+ const analysis = this.options.analyzer.evaluate(stage, metrics);
43
+ this.options.eventBus?.emit({
44
+ type: analysis.status === "pass" ? "stage_passed" : "stage_failed",
45
+ timestamp: /* @__PURE__ */ new Date(),
46
+ payload: {
47
+ stage,
48
+ metrics,
49
+ analysis
50
+ }
51
+ });
52
+ return analysis;
53
+ }
54
+ };
55
+ function createDefaultCanaryController(strategy, metricsProvider, eventBus) {
56
+ return new CanaryController({
57
+ strategy,
58
+ analyzer: new CanaryAnalyzer(strategy.thresholds),
59
+ metricsProvider,
60
+ eventBus
61
+ });
62
+ }
63
+
64
+ //#endregion
65
+ export { CanaryController, createDefaultCanaryController };
66
+ //# sourceMappingURL=canary-controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canary-controller.js","names":[],"sources":["../src/canary-controller.ts"],"sourcesContent":["import { CanaryAnalyzer, type AnalysisResult } from './canary-analyzer';\nimport { DeploymentEventBus } from './events';\nimport type { CanaryStage, DeploymentStrategy, MetricsProvider } from './types';\n\nconst DEFAULT_STAGES: CanaryStage[] = [\n { percentage: 1, minDurationMs: 5 * 60 * 1000, label: '1%' },\n { percentage: 10, minDurationMs: 5 * 60 * 1000, label: '10%' },\n { percentage: 50, minDurationMs: 10 * 60 * 1000, label: '50%' },\n { percentage: 100, minDurationMs: 15 * 60 * 1000, label: '100%' },\n];\n\nexport interface CanaryControllerOptions {\n strategy: DeploymentStrategy;\n analyzer: CanaryAnalyzer;\n metricsProvider: MetricsProvider;\n eventBus?: DeploymentEventBus;\n}\n\nexport class CanaryController {\n private readonly stages: CanaryStage[];\n\n constructor(private readonly options: CanaryControllerOptions) {\n this.stages =\n options.strategy.stages && options.strategy.stages.length > 0\n ? options.strategy.stages\n : DEFAULT_STAGES;\n }\n\n getStageList() {\n return [...this.stages];\n }\n\n async runStage(stage: CanaryStage): Promise<AnalysisResult> {\n this.options.eventBus?.emit({\n type: 'stage_started',\n timestamp: new Date(),\n payload: { stage },\n });\n\n const metrics = await this.options.metricsProvider(\n stage,\n stage.minDurationMs\n );\n const analysis = this.options.analyzer.evaluate(stage, metrics);\n\n this.options.eventBus?.emit({\n type: analysis.status === 'pass' ? 'stage_passed' : 'stage_failed',\n timestamp: new Date(),\n payload: { stage, metrics, analysis },\n });\n\n return analysis;\n }\n}\n\nexport function createDefaultCanaryController(\n strategy: DeploymentStrategy,\n metricsProvider: MetricsProvider,\n eventBus?: DeploymentEventBus\n) {\n const analyzer = new CanaryAnalyzer(strategy.thresholds);\n return new CanaryController({\n strategy,\n analyzer,\n metricsProvider,\n eventBus,\n });\n}\n"],"mappings":";;;AAIA,MAAM,iBAAgC;CACpC;EAAE,YAAY;EAAG,eAAe,MAAS;EAAM,OAAO;EAAM;CAC5D;EAAE,YAAY;EAAI,eAAe,MAAS;EAAM,OAAO;EAAO;CAC9D;EAAE,YAAY;EAAI,eAAe,MAAU;EAAM,OAAO;EAAO;CAC/D;EAAE,YAAY;EAAK,eAAe,MAAU;EAAM,OAAO;EAAQ;CAClE;AASD,IAAa,mBAAb,MAA8B;CAC5B,AAAiB;CAEjB,YAAY,AAAiB,SAAkC;EAAlC;AAC3B,OAAK,SACH,QAAQ,SAAS,UAAU,QAAQ,SAAS,OAAO,SAAS,IACxD,QAAQ,SAAS,SACjB;;CAGR,eAAe;AACb,SAAO,CAAC,GAAG,KAAK,OAAO;;CAGzB,MAAM,SAAS,OAA6C;AAC1D,OAAK,QAAQ,UAAU,KAAK;GAC1B,MAAM;GACN,2BAAW,IAAI,MAAM;GACrB,SAAS,EAAE,OAAO;GACnB,CAAC;EAEF,MAAM,UAAU,MAAM,KAAK,QAAQ,gBACjC,OACA,MAAM,cACP;EACD,MAAM,WAAW,KAAK,QAAQ,SAAS,SAAS,OAAO,QAAQ;AAE/D,OAAK,QAAQ,UAAU,KAAK;GAC1B,MAAM,SAAS,WAAW,SAAS,iBAAiB;GACpD,2BAAW,IAAI,MAAM;GACrB,SAAS;IAAE;IAAO;IAAS;IAAU;GACtC,CAAC;AAEF,SAAO;;;AAIX,SAAgB,8BACd,UACA,iBACA,UACA;AAEA,QAAO,IAAI,iBAAiB;EAC1B;EACA,UAHe,IAAI,eAAe,SAAS,WAAW;EAItD;EACA;EACD,CAAC"}
@@ -0,0 +1,28 @@
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;
15
+ }
16
+ interface DeploymentRunResult {
17
+ status: 'completed' | 'rolled_back';
18
+ failedStage?: CanaryStage;
19
+ reasons?: string[];
20
+ }
21
+ declare class DeploymentCoordinator {
22
+ private readonly options;
23
+ constructor(options: DeploymentCoordinatorOptions);
24
+ run(): Promise<DeploymentRunResult>;
25
+ }
26
+ //#endregion
27
+ export { DeploymentCoordinator, DeploymentCoordinatorOptions, DeploymentRunResult };
28
+ //# sourceMappingURL=deployment-coordinator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployment-coordinator.d.ts","names":[],"sources":["../src/deployment-coordinator.ts"],"sourcesContent":[],"mappings":";;;;;;;UAMiB,4BAAA;YACL;EADK,UAAA,EAEH,gBAFG;EACL,cAAA,EAEM,cAFN;EACE,eAAA,EAEK,eAFL;EACI,iBAAA,EAAA,CAAA,KAAA,EAGP,WAHO,EAAA,KAAA,EAIP,YAJO,EAAA,GAAA,IAAA,GAKJ,OALI,CAAA,IAAA,CAAA;EACC,QAAA,CAAA,EAKN,kBALM;;AAGR,UAKM,mBAAA,CALN;EACG,MAAA,EAAA,WAAA,GAAA,aAAA;EACD,WAAA,CAAA,EAKG,WALH;EAAkB,OAAA,CAAA,EAAA,MAAA,EAAA;AAG/B;AAMa,cAAA,qBAAA,CAAqB;EACM,iBAAA,OAAA;EAEjB,WAAA,CAAA,OAAA,EAFiB,4BAEjB;EAAR,GAAA,CAAA,CAAA,EAAA,OAAA,CAAQ,mBAAR,CAAA"}
@@ -0,0 +1,47 @@
1
+ import "./canary-controller.js";
2
+
3
+ //#region src/deployment-coordinator.ts
4
+ var DeploymentCoordinator = class {
5
+ constructor(options) {
6
+ this.options = options;
7
+ }
8
+ async run() {
9
+ const stages = this.options.controller.getStageList();
10
+ for (const stage of stages) {
11
+ const split = this.options.trafficShifter.computeSplit(stage);
12
+ await this.options.applyTrafficSplit(stage, split);
13
+ const analysis = await this.options.controller.runStage(stage);
14
+ if (analysis.status === "fail") {
15
+ const action = await this.options.rollbackManager.execute(stage, analysis.reasons.join(", "));
16
+ this.options.eventBus?.emit({
17
+ type: "rolled_back",
18
+ timestamp: action.triggeredAt,
19
+ payload: {
20
+ stage,
21
+ reasons: analysis.reasons
22
+ }
23
+ });
24
+ return {
25
+ status: "rolled_back",
26
+ failedStage: stage,
27
+ reasons: analysis.reasons
28
+ };
29
+ }
30
+ }
31
+ if (this.options.strategy.mode === "blue-green") this.options.eventBus?.emit({
32
+ type: "blue_green_swapped",
33
+ timestamp: /* @__PURE__ */ new Date(),
34
+ payload: { strategy: this.options.strategy }
35
+ });
36
+ this.options.eventBus?.emit({
37
+ type: "completed",
38
+ timestamp: /* @__PURE__ */ new Date(),
39
+ payload: { strategy: this.options.strategy }
40
+ });
41
+ return { status: "completed" };
42
+ }
43
+ };
44
+
45
+ //#endregion
46
+ export { DeploymentCoordinator };
47
+ //# sourceMappingURL=deployment-coordinator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployment-coordinator.js","names":[],"sources":["../src/deployment-coordinator.ts"],"sourcesContent":["import { CanaryController } from './canary-controller';\nimport { DeploymentEventBus } from './events';\nimport { RollbackManager } from './rollback-manager';\nimport { TrafficShifter } from './traffic-shifter';\nimport type { CanaryStage, DeploymentStrategy, TrafficSplit } from './types';\n\nexport interface DeploymentCoordinatorOptions {\n strategy: DeploymentStrategy;\n controller: CanaryController;\n trafficShifter: TrafficShifter;\n rollbackManager: RollbackManager;\n applyTrafficSplit: (\n stage: CanaryStage,\n split: TrafficSplit\n ) => void | Promise<void>;\n eventBus?: DeploymentEventBus;\n}\n\nexport interface DeploymentRunResult {\n status: 'completed' | 'rolled_back';\n failedStage?: CanaryStage;\n reasons?: string[];\n}\n\nexport class DeploymentCoordinator {\n constructor(private readonly options: DeploymentCoordinatorOptions) {}\n\n async run(): Promise<DeploymentRunResult> {\n const stages = this.options.controller.getStageList();\n\n for (const stage of stages) {\n const split = this.options.trafficShifter.computeSplit(stage);\n await this.options.applyTrafficSplit(stage, split);\n\n const analysis = await this.options.controller.runStage(stage);\n if (analysis.status === 'fail') {\n const action = await this.options.rollbackManager.execute(\n stage,\n analysis.reasons.join(', ')\n );\n\n this.options.eventBus?.emit({\n type: 'rolled_back',\n timestamp: action.triggeredAt,\n payload: { stage, reasons: analysis.reasons },\n });\n\n return {\n status: 'rolled_back',\n failedStage: stage,\n reasons: analysis.reasons,\n };\n }\n }\n\n if (this.options.strategy.mode === 'blue-green') {\n this.options.eventBus?.emit({\n type: 'blue_green_swapped',\n timestamp: new Date(),\n payload: { strategy: this.options.strategy },\n });\n }\n\n this.options.eventBus?.emit({\n type: 'completed',\n timestamp: new Date(),\n payload: { strategy: this.options.strategy },\n });\n\n return { status: 'completed' };\n }\n}\n"],"mappings":";;;AAwBA,IAAa,wBAAb,MAAmC;CACjC,YAAY,AAAiB,SAAuC;EAAvC;;CAE7B,MAAM,MAAoC;EACxC,MAAM,SAAS,KAAK,QAAQ,WAAW,cAAc;AAErD,OAAK,MAAM,SAAS,QAAQ;GAC1B,MAAM,QAAQ,KAAK,QAAQ,eAAe,aAAa,MAAM;AAC7D,SAAM,KAAK,QAAQ,kBAAkB,OAAO,MAAM;GAElD,MAAM,WAAW,MAAM,KAAK,QAAQ,WAAW,SAAS,MAAM;AAC9D,OAAI,SAAS,WAAW,QAAQ;IAC9B,MAAM,SAAS,MAAM,KAAK,QAAQ,gBAAgB,QAChD,OACA,SAAS,QAAQ,KAAK,KAAK,CAC5B;AAED,SAAK,QAAQ,UAAU,KAAK;KAC1B,MAAM;KACN,WAAW,OAAO;KAClB,SAAS;MAAE;MAAO,SAAS,SAAS;MAAS;KAC9C,CAAC;AAEF,WAAO;KACL,QAAQ;KACR,aAAa;KACb,SAAS,SAAS;KACnB;;;AAIL,MAAI,KAAK,QAAQ,SAAS,SAAS,aACjC,MAAK,QAAQ,UAAU,KAAK;GAC1B,MAAM;GACN,2BAAW,IAAI,MAAM;GACrB,SAAS,EAAE,UAAU,KAAK,QAAQ,UAAU;GAC7C,CAAC;AAGJ,OAAK,QAAQ,UAAU,KAAK;GAC1B,MAAM;GACN,2BAAW,IAAI,MAAM;GACrB,SAAS,EAAE,UAAU,KAAK,QAAQ,UAAU;GAC7C,CAAC;AAEF,SAAO,EAAE,QAAQ,aAAa"}
@@ -0,0 +1,11 @@
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;
8
+ }
9
+ //#endregion
10
+ export { DeploymentEventBus };
11
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","names":[],"sources":["../src/events.ts"],"sourcesContent":[],"mappings":";;;cAEa,kBAAA;;EAAA,EAAA,CAAA,QAAA,EAGE,uBAAA,CAAA,EAAA,GAAA,GAAA,OAAA;cAKD"}
package/dist/events.js ADDED
@@ -0,0 +1,19 @@
1
+ //#region src/events.ts
2
+ var DeploymentEventBus = class {
3
+ listeners = /* @__PURE__ */ 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) try {
10
+ listener(event);
11
+ } catch (error) {
12
+ console.error("[progressive-delivery] listener error", error);
13
+ }
14
+ }
15
+ };
16
+
17
+ //#endregion
18
+ export { DeploymentEventBus };
19
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","names":[],"sources":["../src/events.ts"],"sourcesContent":["import type { DeploymentEvent, DeploymentEventListener } from './types';\n\nexport class DeploymentEventBus {\n private listeners = new Set<DeploymentEventListener>();\n\n on(listener: DeploymentEventListener) {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n emit(event: DeploymentEvent) {\n for (const listener of this.listeners) {\n try {\n listener(event);\n } catch (error) {\n console.error('[progressive-delivery] listener error', error);\n }\n }\n }\n}\n"],"mappings":";AAEA,IAAa,qBAAb,MAAgC;CAC9B,AAAQ,4BAAY,IAAI,KAA8B;CAEtD,GAAG,UAAmC;AACpC,OAAK,UAAU,IAAI,SAAS;AAC5B,eAAa,KAAK,UAAU,OAAO,SAAS;;CAG9C,KAAK,OAAwB;AAC3B,OAAK,MAAM,YAAY,KAAK,UAC1B,KAAI;AACF,YAAS,MAAM;WACR,OAAO;AACd,WAAQ,MAAM,yCAAyC,MAAM"}
@@ -0,0 +1,19 @@
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";
13
+ };
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 };
19
+ //# sourceMappingURL=feature-flags.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-flags.d.ts","names":[],"sources":["../src/feature-flags.ts"],"sourcesContent":[],"mappings":";cAAa;EAAA,SAAA,yBAWH,EAAA,2BAAA;EAEE,SAAA,uBAAuB,EAAA,yBAAgB;EAEtC,SAAA,yBAIZ,EAAA,2BAAA;EAEY,SAAA,qBAQZ,EAAA,uBAAA;;;;;;;;KAhBW,uBAAA,gBAAuC;cAEtC;cAMA"}
@@ -0,0 +1,31 @@
1
+ //#region src/feature-flags.ts
2
+ const ContractSpecFeatureFlags = {
3
+ LIFECYCLE_DETECTION_ALPHA: "lifecycle_detection_alpha",
4
+ LIFECYCLE_ADVISOR_ALPHA: "lifecycle_advisor_alpha",
5
+ LIFECYCLE_MANAGED_SERVICE: "lifecycle_managed_service",
6
+ STUDIO_VISUAL_BUILDER: "studio_visual_builder",
7
+ STUDIO_AUTO_EVOLUTION: "studio_auto_evolution",
8
+ STUDIO_BYOK: "studio_byok",
9
+ STUDIO_DEDICATED_DEPLOYMENT: "studio_dedicated_deployment",
10
+ STUDIO_INTEGRATION_HUB: "studio_integration_hub",
11
+ STUDIO_KNOWLEDGE_HUB: "studio_knowledge_hub",
12
+ STUDIO_TEMPLATES: "studio_templates"
13
+ };
14
+ const lifecycleFlags = [
15
+ ContractSpecFeatureFlags.LIFECYCLE_DETECTION_ALPHA,
16
+ ContractSpecFeatureFlags.LIFECYCLE_ADVISOR_ALPHA,
17
+ ContractSpecFeatureFlags.LIFECYCLE_MANAGED_SERVICE
18
+ ];
19
+ const studioFlags = [
20
+ ContractSpecFeatureFlags.STUDIO_VISUAL_BUILDER,
21
+ ContractSpecFeatureFlags.STUDIO_AUTO_EVOLUTION,
22
+ ContractSpecFeatureFlags.STUDIO_BYOK,
23
+ ContractSpecFeatureFlags.STUDIO_DEDICATED_DEPLOYMENT,
24
+ ContractSpecFeatureFlags.STUDIO_INTEGRATION_HUB,
25
+ ContractSpecFeatureFlags.STUDIO_KNOWLEDGE_HUB,
26
+ ContractSpecFeatureFlags.STUDIO_TEMPLATES
27
+ ];
28
+
29
+ //#endregion
30
+ export { ContractSpecFeatureFlags, lifecycleFlags, studioFlags };
31
+ //# sourceMappingURL=feature-flags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-flags.js","names":[],"sources":["../src/feature-flags.ts"],"sourcesContent":["export const ContractSpecFeatureFlags = {\n LIFECYCLE_DETECTION_ALPHA: 'lifecycle_detection_alpha',\n LIFECYCLE_ADVISOR_ALPHA: 'lifecycle_advisor_alpha',\n LIFECYCLE_MANAGED_SERVICE: 'lifecycle_managed_service',\n STUDIO_VISUAL_BUILDER: 'studio_visual_builder',\n STUDIO_AUTO_EVOLUTION: 'studio_auto_evolution',\n STUDIO_BYOK: 'studio_byok',\n STUDIO_DEDICATED_DEPLOYMENT: 'studio_dedicated_deployment',\n STUDIO_INTEGRATION_HUB: 'studio_integration_hub',\n STUDIO_KNOWLEDGE_HUB: 'studio_knowledge_hub',\n STUDIO_TEMPLATES: 'studio_templates',\n} as const;\n\nexport type ContractSpecFeatureFlag = keyof typeof ContractSpecFeatureFlags;\n\nexport const lifecycleFlags = [\n ContractSpecFeatureFlags.LIFECYCLE_DETECTION_ALPHA,\n ContractSpecFeatureFlags.LIFECYCLE_ADVISOR_ALPHA,\n ContractSpecFeatureFlags.LIFECYCLE_MANAGED_SERVICE,\n];\n\nexport const studioFlags = [\n ContractSpecFeatureFlags.STUDIO_VISUAL_BUILDER,\n ContractSpecFeatureFlags.STUDIO_AUTO_EVOLUTION,\n ContractSpecFeatureFlags.STUDIO_BYOK,\n ContractSpecFeatureFlags.STUDIO_DEDICATED_DEPLOYMENT,\n ContractSpecFeatureFlags.STUDIO_INTEGRATION_HUB,\n ContractSpecFeatureFlags.STUDIO_KNOWLEDGE_HUB,\n ContractSpecFeatureFlags.STUDIO_TEMPLATES,\n];\n"],"mappings":";AAAA,MAAa,2BAA2B;CACtC,2BAA2B;CAC3B,yBAAyB;CACzB,2BAA2B;CAC3B,uBAAuB;CACvB,uBAAuB;CACvB,aAAa;CACb,6BAA6B;CAC7B,wBAAwB;CACxB,sBAAsB;CACtB,kBAAkB;CACnB;AAID,MAAa,iBAAiB;CAC5B,yBAAyB;CACzB,yBAAyB;CACzB,yBAAyB;CAC1B;AAED,MAAa,cAAc;CACzB,yBAAyB;CACzB,yBAAyB;CACzB,yBAAyB;CACzB,yBAAyB;CACzB,yBAAyB;CACzB,yBAAyB;CACzB,yBAAyB;CAC1B"}
@@ -0,0 +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 };
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
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";
8
+
9
+ export { CanaryAnalyzer, CanaryController, ContractSpecFeatureFlags, DeploymentCoordinator, DeploymentEventBus, RollbackManager, TrafficShifter, createDefaultCanaryController, lifecycleFlags, studioFlags };
@@ -0,0 +1,15 @@
1
+ import { CanaryStage, RollbackAction } from "./types.js";
2
+
3
+ //#region src/rollback-manager.d.ts
4
+ interface RollbackManagerOptions {
5
+ rollback(stage: CanaryStage, reason: string): Promise<void> | void;
6
+ onRollback?: (action: RollbackAction) => void;
7
+ }
8
+ declare class RollbackManager {
9
+ private readonly options;
10
+ constructor(options: RollbackManagerOptions);
11
+ execute(stage: CanaryStage, reason: string): Promise<RollbackAction>;
12
+ }
13
+ //#endregion
14
+ export { RollbackManager, RollbackManagerOptions };
15
+ //# sourceMappingURL=rollback-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rollback-manager.d.ts","names":[],"sources":["../src/rollback-manager.ts"],"sourcesContent":[],"mappings":";;;UAEiB,sBAAA;kBACC,8BAA8B;EAD/B,UAAA,CAAA,EAAA,CAAA,MAAA,EAEO,cAFe,EAAA,GAAA,IAAA;;AACS,cAInC,eAAA,CAJmC;EACxB,iBAAA,OAAA;EAAc,WAAA,CAAA,OAAA,EAIE,sBAJF;EAGzB,OAAA,CAAA,KAAA,EAGU,WAHK,EAAA,MAAA,EAAA,MAAA,CAAA,EAGsB,OAHtB,CAGsB,cAHtB,CAAA"}
@@ -0,0 +1,20 @@
1
+ //#region src/rollback-manager.ts
2
+ var RollbackManager = class {
3
+ constructor(options) {
4
+ this.options = options;
5
+ }
6
+ async execute(stage, reason) {
7
+ await this.options.rollback(stage, reason);
8
+ const action = {
9
+ reason,
10
+ stage,
11
+ triggeredAt: /* @__PURE__ */ new Date()
12
+ };
13
+ this.options.onRollback?.(action);
14
+ return action;
15
+ }
16
+ };
17
+
18
+ //#endregion
19
+ export { RollbackManager };
20
+ //# sourceMappingURL=rollback-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rollback-manager.js","names":[],"sources":["../src/rollback-manager.ts"],"sourcesContent":["import type { CanaryStage, RollbackAction } from './types';\n\nexport interface RollbackManagerOptions {\n rollback(stage: CanaryStage, reason: string): Promise<void> | void;\n onRollback?: (action: RollbackAction) => void;\n}\n\nexport class RollbackManager {\n constructor(private readonly options: RollbackManagerOptions) {}\n\n async execute(stage: CanaryStage, reason: string) {\n await this.options.rollback(stage, reason);\n const action: RollbackAction = {\n reason,\n stage,\n triggeredAt: new Date(),\n };\n this.options.onRollback?.(action);\n return action;\n }\n}\n"],"mappings":";AAOA,IAAa,kBAAb,MAA6B;CAC3B,YAAY,AAAiB,SAAiC;EAAjC;;CAE7B,MAAM,QAAQ,OAAoB,QAAgB;AAChD,QAAM,KAAK,QAAQ,SAAS,OAAO,OAAO;EAC1C,MAAM,SAAyB;GAC7B;GACA;GACA,6BAAa,IAAI,MAAM;GACxB;AACD,OAAK,QAAQ,aAAa,OAAO;AACjC,SAAO"}
@@ -0,0 +1,11 @@
1
+ import { CanaryStage, DeploymentMode, TrafficSplit } from "./types.js";
2
+
3
+ //#region src/traffic-shifter.d.ts
4
+ declare class TrafficShifter {
5
+ private readonly mode;
6
+ constructor(mode: DeploymentMode);
7
+ computeSplit(stage: CanaryStage): TrafficSplit;
8
+ }
9
+ //#endregion
10
+ export { TrafficShifter };
11
+ //# sourceMappingURL=traffic-shifter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traffic-shifter.d.ts","names":[],"sources":["../src/traffic-shifter.ts"],"sourcesContent":[],"mappings":";;;cAEa,cAAA;;EAAA,WAAA,CAAA,IAAA,EACwB,cADV;EACU,YAAA,CAAA,KAAA,EAEf,WAFe,CAAA,EAED,YAFC"}
@@ -0,0 +1,24 @@
1
+ //#region src/traffic-shifter.ts
2
+ var TrafficShifter = class {
3
+ constructor(mode) {
4
+ this.mode = mode;
5
+ }
6
+ computeSplit(stage) {
7
+ if (this.mode === "blue-green") return stage.percentage >= 100 ? {
8
+ stable: 0,
9
+ candidate: 1
10
+ } : {
11
+ stable: 1,
12
+ candidate: 0
13
+ };
14
+ const candidate = Math.min(Math.max(stage.percentage / 100, 0), 1);
15
+ return {
16
+ candidate,
17
+ stable: 1 - candidate
18
+ };
19
+ }
20
+ };
21
+
22
+ //#endregion
23
+ export { TrafficShifter };
24
+ //# sourceMappingURL=traffic-shifter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traffic-shifter.js","names":[],"sources":["../src/traffic-shifter.ts"],"sourcesContent":["import type { CanaryStage, DeploymentMode, TrafficSplit } from './types';\n\nexport class TrafficShifter {\n constructor(private readonly mode: DeploymentMode) {}\n\n computeSplit(stage: CanaryStage): TrafficSplit {\n if (this.mode === 'blue-green') {\n return stage.percentage >= 100\n ? { stable: 0, candidate: 1 }\n : { stable: 1, candidate: 0 };\n }\n\n const candidate = Math.min(Math.max(stage.percentage / 100, 0), 1);\n return {\n candidate,\n stable: 1 - candidate,\n };\n }\n}\n"],"mappings":";AAEA,IAAa,iBAAb,MAA4B;CAC1B,YAAY,AAAiB,MAAsB;EAAtB;;CAE7B,aAAa,OAAkC;AAC7C,MAAI,KAAK,SAAS,aAChB,QAAO,MAAM,cAAc,MACvB;GAAE,QAAQ;GAAG,WAAW;GAAG,GAC3B;GAAE,QAAQ;GAAG,WAAW;GAAG;EAGjC,MAAM,YAAY,KAAK,IAAI,KAAK,IAAI,MAAM,aAAa,KAAK,EAAE,EAAE,EAAE;AAClE,SAAO;GACL;GACA,QAAQ,IAAI;GACb"}
@@ -0,0 +1,60 @@
1
+ //#region src/types.d.ts
2
+ type DeploymentMode = 'canary' | 'blue-green';
3
+ interface OperationTarget {
4
+ name: string;
5
+ version: number;
6
+ namespace?: string;
7
+ description?: string;
8
+ }
9
+ interface DeploymentThresholds {
10
+ /** e.g. 0.01 = 1% */
11
+ errorRate: number;
12
+ latencyP50?: number;
13
+ latencyP95?: number;
14
+ latencyP99?: number;
15
+ throughputDrop?: number;
16
+ customEvaluator?: (metrics: DeploymentMetrics) => boolean;
17
+ }
18
+ interface CanaryStage {
19
+ percentage: number;
20
+ minDurationMs: number;
21
+ holdAfterMs?: number;
22
+ /** optional override thresholds */
23
+ thresholds?: Partial<DeploymentThresholds>;
24
+ label?: string;
25
+ }
26
+ interface DeploymentStrategy {
27
+ target: OperationTarget;
28
+ mode: DeploymentMode;
29
+ stages?: CanaryStage[];
30
+ thresholds: DeploymentThresholds;
31
+ metadata?: Record<string, unknown>;
32
+ }
33
+ interface DeploymentMetrics {
34
+ errorRate: number;
35
+ latencyP50: number;
36
+ latencyP95: number;
37
+ latencyP99: number;
38
+ throughput: number;
39
+ sampleSize?: number;
40
+ timestamp?: Date;
41
+ }
42
+ type MetricsProvider = (stage: CanaryStage, windowMs: number) => Promise<DeploymentMetrics>;
43
+ interface TrafficSplit {
44
+ stable: number;
45
+ candidate: number;
46
+ }
47
+ interface RollbackAction {
48
+ reason: string;
49
+ stage: CanaryStage;
50
+ triggeredAt: Date;
51
+ }
52
+ interface DeploymentEvent<TPayload = Record<string, unknown>> {
53
+ type: 'stage_started' | 'stage_passed' | 'stage_failed' | 'rolled_back' | 'completed' | 'blue_green_swapped';
54
+ payload?: TPayload;
55
+ timestamp: Date;
56
+ }
57
+ type DeploymentEventListener = (event: DeploymentEvent) => void;
58
+ //#endregion
59
+ export { CanaryStage, DeploymentEvent, DeploymentEventListener, DeploymentMetrics, DeploymentMode, DeploymentStrategy, DeploymentThresholds, MetricsProvider, OperationTarget, RollbackAction, TrafficSplit };
60
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"sourcesContent":[],"mappings":";KAAY,cAAA;AAAA,UAEK,eAAA,CAFS;EAET,IAAA,EAAA,MAAA;EAOA,OAAA,EAAA,MAAA;EAUA,SAAA,CAAA,EAAA,MAAW;EASX,WAAA,CAAA,EAAA,MAAA;;AAET,UArBS,oBAAA,CAqBT;EACG;EACG,SAAA,EAAA,MAAA;EACD,UAAA,CAAA,EAAA,MAAA;EAAM,UAAA,CAAA,EAAA,MAAA;EAGF,UAAA,CAAA,EAAA,MAAA;EAUL,cAAA,CAAA,EAAA,MAAe;EAClB,eAAA,CAAA,EAAA,CAAA,OAAA,EA/BqB,iBA+BrB,EAAA,GAAA,OAAA;;AAEJ,UA9BY,WAAA,CA8BZ;EAAO,UAAA,EAAA,MAAA;EAEK,aAAA,EAAY,MAAA;EAKZ,WAAA,CAAA,EAAA,MAAc;EAMd;EAA2B,UAAA,CAAA,EAtC7B,OAsC6B,CAtCrB,oBAsCqB,CAAA;EAQhC,KAAA,CAAA,EAAA,MAAA;;AACK,UA3CA,kBAAA,CA2CA;EAGL,MAAA,EA7CF,eA6CE;QA5CJ;WACG;cACG;aACD;;UAGI,iBAAA;;;;;;;cAOH;;KAGF,eAAA,WACH,kCAEJ,QAAQ;UAEI,YAAA;;;;UAKA,cAAA;;SAER;eACM;;UAGE,2BAA2B;;YAQhC;aACC;;KAGD,uBAAA,WAAkC"}
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@contractspec/lib.progressive-delivery",
3
+ "version": "0.0.0-canary-20260113162409",
4
+ "type": "module",
5
+ "types": "./dist/index.d.ts",
6
+ "files": [
7
+ "dist",
8
+ "README.md"
9
+ ],
10
+ "scripts": {
11
+ "publish:pkg": "bun publish --tolerate-republish --ignore-scripts --verbose",
12
+ "publish:pkg:canary": "bun publish:pkg --tag canary",
13
+ "build": "bun build:types && bun build:bundle",
14
+ "build:bundle": "tsdown",
15
+ "build:types": "tsc --noEmit",
16
+ "dev": "bun build:bundle --watch",
17
+ "clean": "rimraf dist .turbo",
18
+ "lint": "bun lint:fix",
19
+ "lint:fix": "eslint src --fix",
20
+ "lint:check": "eslint src"
21
+ },
22
+ "peerDependencies": {
23
+ "@contractspec/lib.observability": "0.0.0-canary-20260113162409"
24
+ },
25
+ "devDependencies": {
26
+ "@contractspec/tool.tsdown": "0.0.0-canary-20260113162409",
27
+ "@contractspec/tool.typescript": "0.0.0-canary-20260113162409",
28
+ "tsdown": "^0.19.0",
29
+ "typescript": "^5.9.3"
30
+ },
31
+ "exports": {
32
+ ".": "./dist/index.js",
33
+ "./*": "./*"
34
+ },
35
+ "publishConfig": {
36
+ "access": "public",
37
+ "exports": {
38
+ ".": "./dist/index.js",
39
+ "./*": "./*"
40
+ }
41
+ }
42
+ }