@enyo-energy/energy-app-sdk 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +211 -1
  2. package/dist/cjs/energy-app-package-definition.cjs +1 -0
  3. package/dist/cjs/energy-app-package-definition.d.cts +1 -0
  4. package/dist/cjs/energy-app-permission.type.cjs +2 -0
  5. package/dist/cjs/energy-app-permission.type.d.cts +3 -1
  6. package/dist/cjs/energy-app.cjs +16 -0
  7. package/dist/cjs/energy-app.d.cts +15 -0
  8. package/dist/cjs/enyo-energy-app-sdk.d.cts +3 -0
  9. package/dist/cjs/implementations/pricing/compose-electricity-prices.cjs +218 -0
  10. package/dist/cjs/implementations/pricing/compose-electricity-prices.d.cts +100 -0
  11. package/dist/cjs/implementations/pricing/price-component-validators.cjs +295 -0
  12. package/dist/cjs/implementations/pricing/price-component-validators.d.cts +90 -0
  13. package/dist/cjs/implementations/pricing/price-schedule-resolver.cjs +182 -0
  14. package/dist/cjs/implementations/pricing/price-schedule-resolver.d.cts +95 -0
  15. package/dist/cjs/index.cjs +7 -0
  16. package/dist/cjs/index.d.cts +7 -0
  17. package/dist/cjs/packages/energy-app-electricity-tariff.d.cts +34 -1
  18. package/dist/cjs/packages/energy-app-grid-fee.cjs +2 -0
  19. package/dist/cjs/packages/energy-app-grid-fee.d.cts +181 -0
  20. package/dist/cjs/types/enyo-electricity-tariff.cjs +33 -1
  21. package/dist/cjs/types/enyo-electricity-tariff.d.cts +161 -4
  22. package/dist/cjs/types/enyo-grid-fee.cjs +15 -0
  23. package/dist/cjs/types/enyo-grid-fee.d.cts +129 -0
  24. package/dist/cjs/types/enyo-price-composition.cjs +15 -0
  25. package/dist/cjs/types/enyo-price-composition.d.cts +126 -0
  26. package/dist/cjs/types/enyo-price-schedule.cjs +45 -0
  27. package/dist/cjs/types/enyo-price-schedule.d.cts +137 -0
  28. package/dist/cjs/version.cjs +1 -1
  29. package/dist/cjs/version.d.cts +1 -1
  30. package/dist/energy-app-package-definition.d.ts +1 -0
  31. package/dist/energy-app-package-definition.js +1 -0
  32. package/dist/energy-app-permission.type.d.ts +3 -1
  33. package/dist/energy-app-permission.type.js +2 -0
  34. package/dist/energy-app.d.ts +15 -0
  35. package/dist/energy-app.js +16 -0
  36. package/dist/enyo-energy-app-sdk.d.ts +3 -0
  37. package/dist/implementations/pricing/compose-electricity-prices.d.ts +100 -0
  38. package/dist/implementations/pricing/compose-electricity-prices.js +212 -0
  39. package/dist/implementations/pricing/price-component-validators.d.ts +90 -0
  40. package/dist/implementations/pricing/price-component-validators.js +285 -0
  41. package/dist/implementations/pricing/price-schedule-resolver.d.ts +95 -0
  42. package/dist/implementations/pricing/price-schedule-resolver.js +175 -0
  43. package/dist/index.d.ts +7 -0
  44. package/dist/index.js +7 -0
  45. package/dist/packages/energy-app-electricity-tariff.d.ts +34 -1
  46. package/dist/packages/energy-app-grid-fee.d.ts +181 -0
  47. package/dist/packages/energy-app-grid-fee.js +1 -0
  48. package/dist/types/enyo-electricity-tariff.d.ts +161 -4
  49. package/dist/types/enyo-electricity-tariff.js +32 -0
  50. package/dist/types/enyo-grid-fee.d.ts +129 -0
  51. package/dist/types/enyo-grid-fee.js +12 -0
  52. package/dist/types/enyo-price-composition.d.ts +126 -0
  53. package/dist/types/enyo-price-composition.js +12 -0
  54. package/dist/types/enyo-price-schedule.d.ts +137 -0
  55. package/dist/types/enyo-price-schedule.js +42 -0
  56. package/dist/version.d.ts +1 -1
  57. package/dist/version.js +1 -1
  58. package/package.json +1 -1
@@ -0,0 +1,95 @@
1
+ import { EnyoPriceSchedule, EnyoResolvedPriceEntry } from '../../types/enyo-price-schedule.cjs';
2
+ /**
3
+ * Length of one resolved interval, in minutes. Matches the resolution of
4
+ * `useElectricityPrices().getPrices()` so resolved schedules can be combined
5
+ * with a price series interval by interval.
6
+ */
7
+ export declare const PRICE_SCHEDULE_INTERVAL_MINUTES = 15;
8
+ /**
9
+ * Wall-clock calendar fields of an instant, as seen in a specific time zone.
10
+ */
11
+ export interface ZonedDateParts {
12
+ /** Full year, e.g. `2026`. */
13
+ year: number;
14
+ /** Month, `1` = January … `12` = December. */
15
+ month: number;
16
+ /** Day of the month, starting at `1`. */
17
+ day: number;
18
+ /** Day of the week, `0` = Sunday … `6` = Saturday. */
19
+ weekday: number;
20
+ /** Hour in 24-hour notation, `0`–`23`. */
21
+ hour: number;
22
+ /** Minute, `0`–`59`. */
23
+ minute: number;
24
+ /** Minutes since local midnight (`hour * 60 + minute`). */
25
+ minutesOfDay: number;
26
+ }
27
+ /**
28
+ * Projects an instant onto the wall clock of a time zone.
29
+ *
30
+ * Uses `Intl.DateTimeFormat`, so daylight-saving transitions are handled by the
31
+ * platform's time zone database without pulling in a dependency.
32
+ *
33
+ * @param date - The instant to project
34
+ * @param timezone - IANA time zone identifier, e.g. `'Europe/Berlin'`
35
+ * @returns The wall-clock calendar fields of `date` in `timezone`
36
+ * @throws {RangeError} If `timezone` is not a valid IANA identifier
37
+ */
38
+ export declare function getZonedDateParts(date: Date, timezone: string): ZonedDateParts;
39
+ /**
40
+ * Parses an `HH:mm` wall-clock time into minutes since midnight.
41
+ *
42
+ * @param value - Time in 24-hour `HH:mm` notation, e.g. `'22:00'`
43
+ * @returns Minutes since midnight, or `null` when the value is malformed
44
+ */
45
+ export declare function parseTimeOfDay(value: string): number | null;
46
+ /**
47
+ * Rounds an instant down to the start of its 15-minute interval.
48
+ *
49
+ * @param timestampMs - Epoch milliseconds
50
+ * @returns Epoch milliseconds of the interval start
51
+ */
52
+ export declare function floorToInterval(timestampMs: number): number;
53
+ /**
54
+ * Options for {@link resolvePriceSchedule}.
55
+ */
56
+ export interface ResolvePriceScheduleOptions {
57
+ /** Start of the range to resolve, in ISO format (inclusive). */
58
+ fromIso: string;
59
+ /** End of the range to resolve, in ISO format (exclusive). */
60
+ untilIso: string;
61
+ /** IANA time zone the schedule's wall-clock times are expressed in. */
62
+ timezone: string;
63
+ /** Optional start of the component's validity in ISO format (inclusive). */
64
+ validFromIso?: string;
65
+ /** Optional end of the component's validity in ISO format (exclusive). */
66
+ validUntilIso?: string;
67
+ }
68
+ /**
69
+ * Expands a price schedule into a flat 15-minute series over a time range.
70
+ *
71
+ * The range start is rounded down to the enclosing 15-minute interval. Intervals
72
+ * no window covers resolve to `amountPerKwh: 0`; intervals outside the
73
+ * component's validity window are omitted entirely, so an empty result means
74
+ * "this component does not apply here" rather than "it is free here".
75
+ *
76
+ * Windows are evaluated in array order and the first match wins — schedules are
77
+ * expected to be overlap-free, which the validators enforce at registration
78
+ * time.
79
+ *
80
+ * @param schedule - The schedule to expand
81
+ * @param options - Range, time zone and optional validity bounds
82
+ * @returns Resolved entries sorted ascending by `timestampIso`
83
+ *
84
+ * @example
85
+ * ```typescript
86
+ * const entries = resolvePriceSchedule(
87
+ * {
88
+ * type: EnyoPriceScheduleTypeEnum.Recurring,
89
+ * windows: [{ startTimeOfDay: '22:00', endTimeOfDay: '06:00', amountPerKwh: 0.05 }],
90
+ * },
91
+ * { fromIso: '2026-09-02T00:00:00Z', untilIso: '2026-09-03T00:00:00Z', timezone: 'Europe/Berlin' },
92
+ * );
93
+ * ```
94
+ */
95
+ export declare function resolvePriceSchedule(schedule: EnyoPriceSchedule, options: ResolvePriceScheduleOptions): EnyoResolvedPriceEntry[];
@@ -152,3 +152,10 @@ __exportStar(require("./packages/energy-app-epex-spot-price.cjs"), exports);
152
152
  __exportStar(require("./types/enyo-automation.cjs"), exports);
153
153
  __exportStar(require("./packages/energy-app-automation.cjs"), exports);
154
154
  __exportStar(require("./implementations/automation/automation-validators.cjs"), exports);
155
+ __exportStar(require("./types/enyo-price-schedule.cjs"), exports);
156
+ __exportStar(require("./types/enyo-grid-fee.cjs"), exports);
157
+ __exportStar(require("./types/enyo-price-composition.cjs"), exports);
158
+ __exportStar(require("./packages/energy-app-grid-fee.cjs"), exports);
159
+ __exportStar(require("./implementations/pricing/price-schedule-resolver.cjs"), exports);
160
+ __exportStar(require("./implementations/pricing/price-component-validators.cjs"), exports);
161
+ __exportStar(require("./implementations/pricing/compose-electricity-prices.cjs"), exports);
@@ -136,3 +136,10 @@ export * from './packages/energy-app-epex-spot-price.cjs';
136
136
  export * from './types/enyo-automation.cjs';
137
137
  export * from './packages/energy-app-automation.cjs';
138
138
  export * from './implementations/automation/automation-validators.cjs';
139
+ export * from './types/enyo-price-schedule.cjs';
140
+ export * from './types/enyo-grid-fee.cjs';
141
+ export * from './types/enyo-price-composition.cjs';
142
+ export * from './packages/energy-app-grid-fee.cjs';
143
+ export * from './implementations/pricing/price-schedule-resolver.cjs';
144
+ export * from './implementations/pricing/price-component-validators.cjs';
145
+ export * from './implementations/pricing/compose-electricity-prices.cjs';
@@ -1,4 +1,4 @@
1
- import { EnyoElectricityTariff, EnyoElectricityTariffWithDefault } from "../types/enyo-electricity-tariff.cjs";
1
+ import { EnyoElectricityTariff, EnyoElectricityTariffWithDefault, EnyoTariffChangeEvent } from "../types/enyo-electricity-tariff.cjs";
2
2
  /**
3
3
  * Interface for managing electricity tariffs.
4
4
  * Provides methods to register, retrieve, and remove electricity tariffs
@@ -60,4 +60,37 @@ export interface EnergyAppElectricityTariff {
60
60
  * @returns Promise that resolves to the full updated tariff with its default indicator
61
61
  */
62
62
  updateTariff(id: string, attributes: Partial<Omit<EnyoElectricityTariff, 'id'>>): Promise<EnyoElectricityTariffWithDefault>;
63
+ /**
64
+ * Registers a listener invoked whenever any tariff is registered, updated
65
+ * or removed, or whenever a different tariff becomes the system default.
66
+ *
67
+ * Listeners see changes made by every energy app on the system, not just
68
+ * this one — filter on {@link EnyoTariffChangeEvent.tariffId} when only one
69
+ * tariff matters. This is the signal to recompose prices: a changed grid fee
70
+ * link, an added or expired bonus, or a new default tariff all invalidate a
71
+ * previously composed price series.
72
+ *
73
+ * Requires the `ElectricityTariff` permission.
74
+ *
75
+ * @param listener - Callback invoked with the tariff change event
76
+ * @returns A unique listener id that can be passed to {@link offTariffChanged}
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * const listenerId = tariffs.onTariffChanged(async event => {
81
+ * if (event.changeType === EnyoTariffChangeTypeEnum.Removed) return;
82
+ * await recomposePrices(event.tariff);
83
+ * });
84
+ * // later
85
+ * tariffs.offTariffChanged(listenerId);
86
+ * ```
87
+ */
88
+ onTariffChanged(listener: (event: EnyoTariffChangeEvent) => void | Promise<void>): string;
89
+ /**
90
+ * Removes a previously registered tariff change listener. If the listener id
91
+ * is unknown, this operation is a no-op.
92
+ *
93
+ * @param listenerId - The id returned from {@link onTariffChanged}
94
+ */
95
+ offTariffChanged(listenerId: string): void;
63
96
  }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,181 @@
1
+ import { EnyoDynamicGridFee, EnyoDynamicGridFeeFilter, EnyoDynamicGridFeeRegistration, EnyoDynamicGridFeeSeries, EnyoGridFeeChangeEvent } from '../types/enyo-grid-fee.cjs';
2
+ import { EnyoAbsolutePriceWindow } from '../types/enyo-price-schedule.cjs';
3
+ /**
4
+ * Interface for publishing and consuming dynamic grid fees (network charges).
5
+ *
6
+ * Any energy app can act as a producer by registering a grid fee — typically an
7
+ * app that knows the local grid operator's tariff sheet or fetches a published
8
+ * series — and any energy app can act as a consumer by resolving that fee for a
9
+ * time range with {@link getDynamicGridFees}.
10
+ *
11
+ * Publishing requires the `GridFeeRegister` permission; consuming requires
12
+ * `GridFeeUse`.
13
+ *
14
+ * A grid fee describes the site's **grid connection**, not a supplier contract:
15
+ * it is registered and resolved independently of any tariff, and the same fee
16
+ * applies whichever supplier the site buys from.
17
+ *
18
+ * **Nothing here is applied to a price automatically.** The host never folds a
19
+ * grid fee into {@link EnergyAppEnergyPrices.getPrices}, because provider APIs
20
+ * differ: some already return grid-fee-inclusive prices, some do not. The app
21
+ * that owns the tariff knows which is the case — it declares it via the
22
+ * tariff's `priceComposition` and composes the effective price itself with
23
+ * `composeElectricityPrices()`.
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * // Producer: a §14a EnWG module 3 HT/NT network charge
28
+ * const gridFee = energyApp.useGridFee();
29
+ * await gridFee.registerGridFee({
30
+ * id: 'dso-hd-2026',
31
+ * name: 'Netzentgelt HT/NT 2026',
32
+ * gridOperator: 'Netze BW',
33
+ * currency: EnyoCurrencyEnum.EUR,
34
+ * timezone: 'Europe/Berlin',
35
+ * appliesTo: EnyoPriceAppliesToEnum.Consumption,
36
+ * moduleThreeCompliant: true,
37
+ * schedule: {
38
+ * type: EnyoPriceScheduleTypeEnum.Recurring,
39
+ * windows: [
40
+ * { startTimeOfDay: '06:00', endTimeOfDay: '22:00', amountPerKwh: 0.0912 },
41
+ * { startTimeOfDay: '22:00', endTimeOfDay: '06:00', amountPerKwh: 0.0431 },
42
+ * ],
43
+ * },
44
+ * });
45
+ *
46
+ * // Consumer: resolve it for the next 24 hours
47
+ * const fees = await gridFee.getDynamicGridFees({
48
+ * fromIso: new Date().toISOString(),
49
+ * untilIso: new Date(Date.now() + 86_400_000).toISOString(),
50
+ * });
51
+ * ```
52
+ */
53
+ export interface EnergyAppGridFee {
54
+ /**
55
+ * Registers a new dynamic grid fee or updates an existing one. Uses upsert
56
+ * logic based on `id` — if a fee with the same id already exists it is
57
+ * replaced, otherwise a new one is created.
58
+ *
59
+ * Requires the `GridFeeRegister` permission.
60
+ *
61
+ * @param registration - The grid fee to register, including its schedule
62
+ * @returns Promise that resolves to the stored grid fee, including the host-assigned `publishedAtIso`
63
+ */
64
+ registerGridFee(registration: EnyoDynamicGridFeeRegistration): Promise<EnyoDynamicGridFee>;
65
+ /**
66
+ * Partially updates a registered grid fee. Only the provided attributes are
67
+ * modified; all other fields remain unchanged.
68
+ *
69
+ * Requires the `GridFeeRegister` permission.
70
+ *
71
+ * @param id - The unique identifier of the grid fee to update
72
+ * @param attributes - A partial set of grid fee fields to update (excluding `id`)
73
+ * @returns Promise that resolves to the full updated grid fee
74
+ */
75
+ updateGridFee(id: string, attributes: Partial<Omit<EnyoDynamicGridFeeRegistration, 'id'>>): Promise<EnyoDynamicGridFee>;
76
+ /**
77
+ * Removes a registered grid fee. {@link getDynamicGridFees} resolves to
78
+ * `null` for it afterwards. If the fee does not exist, this operation is a
79
+ * no-op.
80
+ *
81
+ * Requires the `GridFeeRegister` permission.
82
+ *
83
+ * @param id - The unique identifier of the grid fee to remove
84
+ * @returns Promise that resolves when the grid fee has been removed
85
+ */
86
+ removeGridFee(id: string): Promise<void>;
87
+ /**
88
+ * Retrieves all registered grid fees across all energy apps on the system.
89
+ *
90
+ * Requires the `GridFeeUse` permission.
91
+ *
92
+ * @returns Promise that resolves to an array of all registered grid fees
93
+ */
94
+ listGridFees(): Promise<EnyoDynamicGridFee[]>;
95
+ /**
96
+ * Retrieves a single registered grid fee by its id, or `null` when no fee
97
+ * with that id exists.
98
+ *
99
+ * Requires the `GridFeeUse` permission.
100
+ *
101
+ * @param id - The unique identifier of the grid fee
102
+ * @returns Promise that resolves to the grid fee, or `null`
103
+ */
104
+ getGridFee(id: string): Promise<EnyoDynamicGridFee | null>;
105
+ /**
106
+ * Replaces the absolute windows of a grid fee whose schedule is
107
+ * {@link EnyoPriceScheduleTypeEnum.Absolute}. Use this for fees the grid
108
+ * operator publishes as a dated series (for example day-ahead), where the
109
+ * schedule changes far more often than the fee's metadata.
110
+ *
111
+ * Windows must not overlap and are stored sorted ascending by `startIso`.
112
+ * Publishing replaces the previously stored windows in full.
113
+ *
114
+ * Requires the `GridFeeRegister` permission.
115
+ *
116
+ * @param id - The unique identifier of the registered grid fee
117
+ * @param windows - The complete set of absolute windows to store
118
+ * @returns Promise that resolves when the windows have been stored and change listeners dispatched
119
+ */
120
+ publishGridFeeWindows(id: string, windows: EnyoAbsolutePriceWindow[]): Promise<void>;
121
+ /**
122
+ * Resolves a dynamic grid fee to a flat **15-minute series** over the
123
+ * requested range — the same resolution
124
+ * {@link EnergyAppEnergyPrices.getPrices} uses, so both series can be
125
+ * combined interval by interval.
126
+ *
127
+ * The fee is selected by `gridFeeId` or `meteringPointId`; with no selector
128
+ * the grid fee that applies to this device is used. Grid fees are **not**
129
+ * bound to a tariff — a network charge is a property of the grid connection,
130
+ * and the same fee applies no matter which supplier the site buys from.
131
+ * Returns `null` when no fee matches the selector.
132
+ *
133
+ * Intervals no window covers resolve to `feePerKwh: 0`, and intervals
134
+ * outside the fee's `validFromIso` / `validUntilIso` window are omitted.
135
+ *
136
+ * Requires the `GridFeeUse` permission.
137
+ *
138
+ * @param filter - The time range and the selector identifying which fee to resolve
139
+ * @returns Promise that resolves to the 15-minute fee series, or `null` when no fee applies
140
+ *
141
+ * @example
142
+ * ```typescript
143
+ * const fees = await gridFee.getDynamicGridFees({
144
+ * fromIso: '2026-09-02T00:00:00Z',
145
+ * untilIso: '2026-09-03T00:00:00Z',
146
+ * });
147
+ * fees?.entries.forEach(e => console.log(e.timestampIso, e.feePerKwh));
148
+ * ```
149
+ */
150
+ getDynamicGridFees(filter: EnyoDynamicGridFeeFilter): Promise<EnyoDynamicGridFeeSeries | null>;
151
+ /**
152
+ * Registers a listener invoked whenever any grid fee is registered, updated
153
+ * or removed — including when its absolute windows are republished.
154
+ *
155
+ * Use it to recompute composed prices without polling: a grid operator that
156
+ * publishes a new day-ahead series mid-day changes the cost of every future
157
+ * interval.
158
+ *
159
+ * Requires the `GridFeeUse` permission.
160
+ *
161
+ * @param listener - Callback invoked with the change event
162
+ * @returns A unique listener id that can be passed to {@link offGridFeeChanged}
163
+ *
164
+ * @example
165
+ * ```typescript
166
+ * const id = gridFee.onGridFeeChanged(async event => {
167
+ * if (event.gridFeeId === myFeeId) await recomputePrices();
168
+ * });
169
+ * // later
170
+ * gridFee.offGridFeeChanged(id);
171
+ * ```
172
+ */
173
+ onGridFeeChanged(listener: (event: EnyoGridFeeChangeEvent) => void | Promise<void>): string;
174
+ /**
175
+ * Removes a previously registered grid fee change listener. If the listener
176
+ * id is unknown, this operation is a no-op.
177
+ *
178
+ * @param listenerId - The id returned from {@link onGridFeeChanged}
179
+ */
180
+ offGridFeeChanged(listenerId: string): void;
181
+ }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ElectricityTariffTypeEnum = void 0;
3
+ exports.EnyoTariffChangeTypeEnum = exports.GridFeeModeEnum = exports.ElectricityTariffTypeEnum = void 0;
4
4
  /**
5
5
  * Enum representing the type of electricity tariff pricing model
6
6
  */
@@ -13,3 +13,35 @@ var ElectricityTariffTypeEnum;
13
13
  /** Price changes dynamically based on market conditions */
14
14
  ElectricityTariffTypeEnum["Dynamic"] = "dynamic";
15
15
  })(ElectricityTariffTypeEnum || (exports.ElectricityTariffTypeEnum = ElectricityTariffTypeEnum = {}));
16
+ /**
17
+ * How the grid fee (network charge) of a tariff is determined.
18
+ */
19
+ var GridFeeModeEnum;
20
+ (function (GridFeeModeEnum) {
21
+ /**
22
+ * A single constant fee per kWh, carried by the tariff itself
23
+ * (see {@link DynamicTariffData.gridFeePerKwh}).
24
+ */
25
+ GridFeeModeEnum["Static"] = "static";
26
+ /**
27
+ * A time-dependent fee, read from the grid fee API with
28
+ * `useGridFee().getDynamicGridFees()`. The tariff only declares *that* the
29
+ * fee is time-dependent — which fee applies is a property of the site's grid
30
+ * connection, not of the tariff.
31
+ */
32
+ GridFeeModeEnum["Dynamic"] = "dynamic";
33
+ })(GridFeeModeEnum || (exports.GridFeeModeEnum = GridFeeModeEnum = {}));
34
+ /**
35
+ * What happened to a tariff registration.
36
+ */
37
+ var EnyoTariffChangeTypeEnum;
38
+ (function (EnyoTariffChangeTypeEnum) {
39
+ /** A new tariff was registered. */
40
+ EnyoTariffChangeTypeEnum["Registered"] = "registered";
41
+ /** An existing tariff's attributes, grid fee link or bonuses changed. */
42
+ EnyoTariffChangeTypeEnum["Updated"] = "updated";
43
+ /** A tariff was removed. */
44
+ EnyoTariffChangeTypeEnum["Removed"] = "removed";
45
+ /** A different tariff became the system default. */
46
+ EnyoTariffChangeTypeEnum["DefaultChanged"] = "default-changed";
47
+ })(EnyoTariffChangeTypeEnum || (exports.EnyoTariffChangeTypeEnum = EnyoTariffChangeTypeEnum = {}));
@@ -1,3 +1,4 @@
1
+ import { EnyoPriceAppliesToEnum, EnyoPriceSchedule } from './enyo-price-schedule.cjs';
1
2
  /**
2
3
  * Enum representing the type of electricity tariff pricing model
3
4
  */
@@ -9,10 +10,119 @@ export declare enum ElectricityTariffTypeEnum {
9
10
  /** Price changes dynamically based on market conditions */
10
11
  Dynamic = "dynamic"
11
12
  }
13
+ /**
14
+ * How the grid fee (network charge) of a tariff is determined.
15
+ */
16
+ export declare enum GridFeeModeEnum {
17
+ /**
18
+ * A single constant fee per kWh, carried by the tariff itself
19
+ * (see {@link DynamicTariffData.gridFeePerKwh}).
20
+ */
21
+ Static = "static",
22
+ /**
23
+ * A time-dependent fee, read from the grid fee API with
24
+ * `useGridFee().getDynamicGridFees()`. The tariff only declares *that* the
25
+ * fee is time-dependent — which fee applies is a property of the site's grid
26
+ * connection, not of the tariff.
27
+ */
28
+ Dynamic = "dynamic"
29
+ }
30
+ /**
31
+ * Declares how the grid fee (network charge) that applies alongside a tariff is
32
+ * determined.
33
+ *
34
+ * Mixed into every tariff pricing shape: a fixed energy price combined with
35
+ * time-variable network charges (e.g. §14a EnWG module 3) is just as real a
36
+ * product as a spot-market tariff, so the declaration is not exclusive to
37
+ * dynamic tariffs.
38
+ *
39
+ * A grid fee itself is **not** bound to a tariff — it belongs to the site's grid
40
+ * connection and is registered and resolved through `useGridFee()` independently.
41
+ * The tariff only says whether its grid fee is a constant it carries itself or a
42
+ * time-dependent one to be read from that API.
43
+ *
44
+ * The grid fee is never applied automatically. Energy apps read the fee and
45
+ * compose the effective price themselves — see `composeElectricityPrices()`.
46
+ */
47
+ export interface TariffGridFeeConfig {
48
+ /**
49
+ * How the grid fee is determined. Defaults to {@link GridFeeModeEnum.Static}
50
+ * when omitted, so tariffs registered before this field existed keep their
51
+ * previous behaviour.
52
+ *
53
+ * {@link GridFeeModeEnum.Dynamic} must not be combined with
54
+ * `priceComposition.includesGridFee === true` — a fee already contained in
55
+ * the tariff's prices must not be added again.
56
+ */
57
+ gridFeeMode?: GridFeeModeEnum;
58
+ }
59
+ /**
60
+ * Declares which cost components are **already contained** in the prices this
61
+ * tariff yields.
62
+ *
63
+ * Provider APIs differ: some return all-in prices with network charges, levies
64
+ * and taxes baked in, others return the pure energy price. Consumers must never
65
+ * add a component that is already included — this declaration is what makes the
66
+ * difference machine-readable instead of tribal knowledge.
67
+ *
68
+ * When omitted, prices are treated as **energy price only**.
69
+ */
70
+ export interface TariffPriceCompositionInfo {
71
+ /** `true` when the tariff's prices already contain the grid fee. */
72
+ includesGridFee: boolean;
73
+ /** `true` when the tariff's prices already contain taxes and levies. */
74
+ includesTaxesAndLevies?: boolean;
75
+ /** `true` when the tariff's prices already have its bonuses applied. */
76
+ includesBonuses?: boolean;
77
+ }
78
+ /**
79
+ * A time-dependent discount granted on top of a tariff, expressed in currency
80
+ * per kWh — for example "5 ct/kWh cheaper between 22:00 and 06:00" or a
81
+ * promotional rebate that runs for a fixed number of months.
82
+ *
83
+ * A tariff may carry several bonuses. Amounts in {@link schedule} are positive
84
+ * magnitudes and are **subtracted** from the price.
85
+ *
86
+ * Consumption-quota bonuses ("the first 100 kWh each month are free") are not
87
+ * expressible here — they require consumption accounting that this model
88
+ * deliberately does not carry.
89
+ */
90
+ export interface EnyoTariffBonus {
91
+ /** Unique identifier of the bonus within its tariff. */
92
+ id: string;
93
+ /** Human-readable name shown to the user, e.g. `'Nachtbonus'`. */
94
+ name: string;
95
+ /**
96
+ * When and how much the discount is. Amounts are positive and subtracted
97
+ * from the price.
98
+ */
99
+ schedule: EnyoPriceSchedule;
100
+ /**
101
+ * IANA time zone the schedule's wall-clock times are expressed in, e.g.
102
+ * `'Europe/Berlin'`.
103
+ */
104
+ timezone: string;
105
+ /** Whether the bonus applies to consumption, feed-in, or both. */
106
+ appliesTo: EnyoPriceAppliesToEnum;
107
+ /** Optional start of the bonus's validity in ISO format (inclusive). */
108
+ validFromIso?: string;
109
+ /** Optional end of the bonus's validity in ISO format (exclusive). */
110
+ validUntilIso?: string;
111
+ /**
112
+ * When `true`, this bonus suppresses every lower-priority bonus in the
113
+ * intervals it covers instead of stacking with them.
114
+ */
115
+ exclusive?: boolean;
116
+ /**
117
+ * Ranking used to pick between competing exclusive bonuses — higher wins.
118
+ * Defaults to `0`.
119
+ */
120
+ priority?: number;
121
+ }
12
122
  /**
13
123
  * Pricing data for a static (fixed-price) electricity tariff
14
124
  */
15
- export interface StaticTariffData {
125
+ export interface StaticTariffData extends TariffGridFeeConfig {
16
126
  /** Price per kWh for consumption */
17
127
  pricePerKwh: number;
18
128
  /** Currency code (ISO 4217, e.g., 'EUR', 'USD') */
@@ -21,8 +131,15 @@ export interface StaticTariffData {
21
131
  /**
22
132
  * Pricing data for a dynamic electricity tariff
23
133
  */
24
- export interface DynamicTariffData {
25
- /** Price per kWh for grid fees */
134
+ export interface DynamicTariffData extends TariffGridFeeConfig {
135
+ /**
136
+ * Constant price per kWh for grid fees.
137
+ *
138
+ * @deprecated Set {@link TariffGridFeeConfig.gridFeeMode} to
139
+ * {@link GridFeeModeEnum.Dynamic} and read the fee from
140
+ * `useGridFee().getDynamicGridFees()` instead. Still honoured as the
141
+ * constant fallback while `gridFeeMode` is Static or omitted.
142
+ */
26
143
  gridFeePerKwh?: number;
27
144
  /** Currency code (ISO 4217, e.g., 'EUR', 'USD') */
28
145
  currency: string;
@@ -39,7 +156,7 @@ export interface TimeVariableScheduleEntry {
39
156
  /**
40
157
  * Pricing data for a time-variable electricity tariff
41
158
  */
42
- export interface TimeVariableTariffData {
159
+ export interface TimeVariableTariffData extends TariffGridFeeConfig {
43
160
  /** Schedule of time-based price entries */
44
161
  schedule: TimeVariableScheduleEntry[];
45
162
  /** Currency code (ISO 4217, e.g., 'EUR', 'USD') */
@@ -67,6 +184,17 @@ export interface EnyoElectricityTariff {
67
184
  dynamicTariffData?: DynamicTariffData;
68
185
  /** Optional external tariff id for easy identification */
69
186
  externalTariffId?: string;
187
+ /**
188
+ * Optional declaration of which cost components the tariff's prices already
189
+ * contain. Omitted means "energy price only".
190
+ */
191
+ priceComposition?: TariffPriceCompositionInfo;
192
+ /**
193
+ * Optional discounts granted on top of this tariff. Several bonuses may
194
+ * apply at the same time — overlapping bonuses stack additively unless one
195
+ * of them is {@link EnyoTariffBonus.exclusive}.
196
+ */
197
+ bonuses?: EnyoTariffBonus[];
70
198
  }
71
199
  /**
72
200
  * Tariff registration data extended with default indicator.
@@ -76,3 +204,32 @@ export interface EnyoElectricityTariffWithDefault extends EnyoElectricityTariff
76
204
  /** Indicates whether this tariff is the system default */
77
205
  defaultTariff: boolean;
78
206
  }
207
+ /**
208
+ * What happened to a tariff registration.
209
+ */
210
+ export declare enum EnyoTariffChangeTypeEnum {
211
+ /** A new tariff was registered. */
212
+ Registered = "registered",
213
+ /** An existing tariff's attributes, grid fee link or bonuses changed. */
214
+ Updated = "updated",
215
+ /** A tariff was removed. */
216
+ Removed = "removed",
217
+ /** A different tariff became the system default. */
218
+ DefaultChanged = "default-changed"
219
+ }
220
+ /**
221
+ * Event delivered to listeners registered via
222
+ * {@link EnergyAppElectricityTariff.onTariffChanged}.
223
+ */
224
+ export interface EnyoTariffChangeEvent {
225
+ /** What happened. */
226
+ changeType: EnyoTariffChangeTypeEnum;
227
+ /** Identifier of the affected tariff. */
228
+ tariffId: string;
229
+ /**
230
+ * The tariff after the change, or `null` when it was removed. For
231
+ * {@link EnyoTariffChangeTypeEnum.DefaultChanged} this is the tariff that
232
+ * became the new default.
233
+ */
234
+ tariff: EnyoElectricityTariffWithDefault | null;
235
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EnyoGridFeeChangeTypeEnum = void 0;
4
+ /**
5
+ * What happened to a grid fee registration.
6
+ */
7
+ var EnyoGridFeeChangeTypeEnum;
8
+ (function (EnyoGridFeeChangeTypeEnum) {
9
+ /** A new grid fee was registered. */
10
+ EnyoGridFeeChangeTypeEnum["Registered"] = "registered";
11
+ /** An existing grid fee's attributes or schedule changed. */
12
+ EnyoGridFeeChangeTypeEnum["Updated"] = "updated";
13
+ /** A grid fee was removed. */
14
+ EnyoGridFeeChangeTypeEnum["Removed"] = "removed";
15
+ })(EnyoGridFeeChangeTypeEnum || (exports.EnyoGridFeeChangeTypeEnum = EnyoGridFeeChangeTypeEnum = {}));