@enyo-energy/energy-app-sdk 1.34.0 → 1.36.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.
- package/README.md +142 -1
- package/dist/cjs/energy-app-package-definition.d.cts +82 -0
- package/dist/cjs/energy-app-permission.type.cjs +2 -0
- package/dist/cjs/energy-app-permission.type.d.cts +3 -1
- package/dist/cjs/energy-app.cjs +29 -0
- package/dist/cjs/energy-app.d.cts +27 -0
- package/dist/cjs/enyo-energy-app-sdk.cjs +2 -0
- package/dist/cjs/enyo-energy-app-sdk.d.cts +9 -1
- package/dist/cjs/implementations/energy-manager-settings/energy-manager-settings-validators.cjs +2 -1
- package/dist/cjs/implementations/subscriptions/define-subscription-plan.cjs +86 -0
- package/dist/cjs/implementations/subscriptions/define-subscription-plan.d.cts +70 -0
- package/dist/cjs/implementations/subscriptions/in-memory-subscriptions.cjs +94 -0
- package/dist/cjs/implementations/subscriptions/in-memory-subscriptions.d.cts +72 -0
- package/dist/cjs/implementations/subscriptions/subscription-plan-validators.cjs +191 -0
- package/dist/cjs/implementations/subscriptions/subscription-plan-validators.d.cts +71 -0
- package/dist/cjs/index.cjs +7 -0
- package/dist/cjs/index.d.cts +7 -0
- package/dist/cjs/packages/energy-app-subscriptions.cjs +2 -0
- package/dist/cjs/packages/energy-app-subscriptions.d.cts +77 -0
- package/dist/cjs/packages/energy-app-webhook.cjs +2 -0
- package/dist/cjs/packages/energy-app-webhook.d.cts +72 -0
- package/dist/cjs/types/enyo-data-bus-value.d.cts +5 -0
- package/dist/cjs/types/enyo-energy-manager-settings.cjs +12 -2
- package/dist/cjs/types/enyo-energy-manager-settings.d.cts +44 -2
- package/dist/cjs/types/enyo-notification.d.cts +19 -1
- package/dist/cjs/types/enyo-subscription.cjs +52 -0
- package/dist/cjs/types/enyo-subscription.d.cts +150 -0
- package/dist/cjs/types/enyo-webhook.cjs +8 -0
- package/dist/cjs/types/enyo-webhook.d.cts +35 -0
- package/dist/cjs/version.cjs +1 -1
- package/dist/cjs/version.d.cts +1 -1
- package/dist/energy-app-package-definition.d.ts +82 -0
- package/dist/energy-app-permission.type.d.ts +3 -1
- package/dist/energy-app-permission.type.js +2 -0
- package/dist/energy-app.d.ts +27 -0
- package/dist/energy-app.js +29 -0
- package/dist/enyo-energy-app-sdk.d.ts +9 -1
- package/dist/enyo-energy-app-sdk.js +2 -0
- package/dist/implementations/energy-manager-settings/energy-manager-settings-validators.js +2 -1
- package/dist/implementations/subscriptions/define-subscription-plan.d.ts +70 -0
- package/dist/implementations/subscriptions/define-subscription-plan.js +80 -0
- package/dist/implementations/subscriptions/in-memory-subscriptions.d.ts +72 -0
- package/dist/implementations/subscriptions/in-memory-subscriptions.js +90 -0
- package/dist/implementations/subscriptions/subscription-plan-validators.d.ts +71 -0
- package/dist/implementations/subscriptions/subscription-plan-validators.js +185 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +7 -0
- package/dist/packages/energy-app-subscriptions.d.ts +77 -0
- package/dist/packages/energy-app-subscriptions.js +1 -0
- package/dist/packages/energy-app-webhook.d.ts +72 -0
- package/dist/packages/energy-app-webhook.js +1 -0
- package/dist/types/enyo-data-bus-value.d.ts +5 -0
- package/dist/types/enyo-energy-manager-settings.d.ts +44 -2
- package/dist/types/enyo-energy-manager-settings.js +12 -2
- package/dist/types/enyo-notification.d.ts +19 -1
- package/dist/types/enyo-subscription.d.ts +150 -0
- package/dist/types/enyo-subscription.js +49 -0
- package/dist/types/enyo-webhook.d.ts +35 -0
- package/dist/types/enyo-webhook.js +5 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -186,6 +186,8 @@ The SDK exposes several layered building blocks. Pick the one that matches the k
|
|
|
186
186
|
| Query historical timeseries (PV, battery, meter, …) | [`useTimeseries()`](#usetimeseries-energyapptimeseries) |
|
|
187
187
|
| Read site location (zip or coordinates) | [`useLocation()`](#uselocation-energyapplocation) |
|
|
188
188
|
| Read grid connection point (fuse, phases, max power, charger limit) | [`useGridConnectionPoint()`](#usegridconnectionpoint-energyappgridconnectionpoint) |
|
|
189
|
+
| Receive webhooks from third-party services (one URL per app, parsed JSON body) | [`useWebhook()`](#usewebhook-energyappwebhook) |
|
|
190
|
+
| Sell one-time, monthly or yearly plans and check which ones the device has | [`useSubscriptions()`](#usesubscriptions-energyappsubscriptions) / [Subscription Plans](#subscription-plans) |
|
|
189
191
|
| Retrieve secrets from the developer org secret store | [`useSecretManager()`](#usesecretmanager-energyappsecretmanager) |
|
|
190
192
|
| Submit energy-manager diagnostics | [`useDiagnostics()`](#usediagnostics-energyappdiagnostics) |
|
|
191
193
|
| Register a weather / PV / dynamic-price forecast provider | [`useWeatherForecasting()`](#useweatherforecasting-energyappweatherforecasting) / [`usePvForecasting()`](#usepvforecasting-energyapppvforecasting) / [`useDynamicPriceForecast()`](#usedynamicpriceforecast-energyappdynamicpriceforecast) |
|
|
@@ -242,6 +244,7 @@ energyApp.onShutdown(async () => {
|
|
|
242
244
|
- `running`: App is functioning normally
|
|
243
245
|
- `configuration-required`: App needs user configuration
|
|
244
246
|
- `internet-connection-required`: App needs internet connectivity
|
|
247
|
+
- `subscription-required`: App needs a subscription plan; the host shows the plans declared in the package definition
|
|
245
248
|
|
|
246
249
|
### Package Definition
|
|
247
250
|
|
|
@@ -384,6 +387,7 @@ Energy Apps use a granular permissions system to control access to system resour
|
|
|
384
387
|
- **`Wifi`**: List known WiFi SSIDs
|
|
385
388
|
- **`Udp`**: Bind UDP sockets and exchange datagrams
|
|
386
389
|
- **`ChildProcess`**: Spawn child processes from the runtime
|
|
390
|
+
- **`Webhook`**: Receive webhooks posted to the app's endpoint on the enyo API
|
|
387
391
|
|
|
388
392
|
#### Data & Domain Permissions
|
|
389
393
|
|
|
@@ -401,6 +405,7 @@ Energy Apps use a granular permissions system to control access to system resour
|
|
|
401
405
|
- **`EpexSpotPrices`**: Read EPEX SPOT day-ahead wholesale market prices
|
|
402
406
|
- **`GridFeeRegister`** / **`GridFeeUse`**: Publish / resolve dynamic grid fees (time-variable network charges)
|
|
403
407
|
- **`CommandLog`**: Record and read back the commands apps issued to appliances
|
|
408
|
+
- **`Subscriptions`**: Read the subscriptions bought for the app on this device
|
|
404
409
|
|
|
405
410
|
#### Site & Identity Permissions
|
|
406
411
|
|
|
@@ -1653,6 +1658,7 @@ A closed, SDK-defined set of user-facing controls the active energy manager hono
|
|
|
1653
1658
|
| `BatteryPvPriorityTargetSocPercent` | number \| `null`, **%** target the battery is charged to from PV before other surplus consumers (absent / `null` = disabled) |
|
|
1654
1659
|
| `BatteryDischargeBlockAboveHomeConsumptionW` | number \| `null`, **W** home consumption above which the battery may not discharge (absent / `null` = disabled) |
|
|
1655
1660
|
| `HeatpumpControl` | boolean |
|
|
1661
|
+
| `HeatpumpEcoModeInExpensiveTimes` | boolean, off by default — switch the heat pump to its eco setpoint while electricity is expensive |
|
|
1656
1662
|
| `HeatingRodControl` | boolean |
|
|
1657
1663
|
| `HeatingRodMode` | `pv-surplus-only` \| `boost` |
|
|
1658
1664
|
| `HeatingRodBatteryDischargeSocLimitPercent` | number \| `null`, **%** floor the battery may feed the heating rod down to (absent / `null` = disabled) |
|
|
@@ -1706,7 +1712,8 @@ Three things to get right:
|
|
|
1706
1712
|
- **The heating rod may draw from the battery only down to a floor, and only when asked.** `HeatingRodBatteryDischargeSocLimitPercent` (`80` = the rod may use the battery while it holds more than 80 %) is disabled while absent or `null`. It applies under both heating rod modes — under `pv-surplus-only` the battery above the floor counts as supply alongside PV, still never a grid import. It needs `batteryControl` to be enforced, and should not lie below `BatteryPvPriorityTargetSocPercent`; the validator warns on both. A consumer held back by it carries the command reason `BatteryPvPriority` (category `PvSurplus`) with `context.batteryPvPriority.targetSocPercent` and `socPercent`.
|
|
1707
1713
|
- **The battery can be blocked from discharging under a heavy load.** `BatteryDischargeBlockAboveHomeConsumptionW` (`11000` = no discharge while the house draws more than 11 kW) keeps a sauna or an oven from emptying the battery in minutes. It is in **watts** — the validator warns below 100 W, which catches a kW value. Home consumption means the household plus every appliance the energy manager does **not** track — the same quantity as `homeConsumptionW` in the home consumption timeseries. Tracked appliances (wallbox, heat pump, heating rod, …) and the battery's own charging are excluded, so a charging car alone never trips the block. The block wins over the EV and heating rod discharge permissions; charging is unaffected. Disabled while absent or `null`. A battery held by it carries `HomeConsumptionHigh` with `context.batteryDischargeBlock.thresholdW` and `powerW` set to the current consumption.
|
|
1708
1714
|
- **Grid-optimised EV charging is about the grid, not the bill.** `GridOptimizedEvCharging` adds no charge mode. It only affects `cost-optimized` sessions while the tariff is static or time-of-use (no effect under a dynamic one): the grid energy PV does not cover is placed in the hours with the lowest EPEX spot price before the deadline — the spot price as a proxy for grid load — instead of as late as possible or in the tariff's cheap windows. PV still comes first, the deadline still holds, and a session's price ceiling still applies against the customer's own tariff. On a time-of-use tariff a low-load hour can be a more expensive one; that is the trade the owner opts into.
|
|
1709
|
-
- **
|
|
1715
|
+
- **Eco mode in expensive times switches setpoints, not temperatures.** `HeatpumpEcoModeInExpensiveTimes` (needs `heatpumpControl`) lets the energy manager send `HeatpumpProgramSwitchV3` with `mode: Eco` to every zone listing `eco` in `supportedProgramModes` while the tariff is expensive, and `mode: Program` once it is not. The user's own eco temperature applies (`programModeTemperaturesC`); the energy manager only chooses *when*. "Expensive" comes from the consumption tariff — the dearest slots under a dynamic tariff, the high-price windows under a time-of-use one; under a static tariff the setting has no effect, as it has on heat pumps without `ProgramSwitch`. Each such switch carries `ElectricityPriceAboveThreshold` (category `EnergyPrice`) with `electricityPricePerKwh`.
|
|
1716
|
+
- **Sixteen settings are gated by another** (`heatingRodMode` needs `heatingRodControl`, `priceLimitCtPerKwh` only applies under `priceLimitMode: 'ct-per-kwh'`, …). The tree is exported as `ENERGY_MANAGER_SETTING_DEPENDENCIES`, with two helpers over it: `getEnergyManagerSettingDependency(setting)` returns the direct gate and the value it must hold (or `null` for an ungated root), and `isEnergyManagerSettingActive(setting, values)` walks the whole chain — the gates are now two deep, so a Wh budget is live only when the mode is `fixed-wh` *and* battery control is on.
|
|
1710
1717
|
- **`priceLimitCtPerKwh` is in cents**, unlike the SDK's machine-readable price fields (`electricityPricePerKwh`, EUR/kWh). Divide by 100 when comparing. `validateEnergyManagerSettingsState()` warns on values outside a plausible ct band, which catches the mix-up.
|
|
1711
1718
|
- **A price ceiling is one mode plus its parameter**, the same shape as the battery-to-EV one. `PriceLimitMode` picks how the ceiling is expressed — an absolute `ct-per-kwh` or a relative `cheapest-share` — and each value is read only under its own mode; the mode being absent means no ceiling at all. A relative ceiling ranks the price intervals *known* for the day and treats the cheapest `n` % as importable (the same rule as the `cheapest-share-of-day` automation trigger), so its effective threshold moves when tomorrow's prices publish — re-evaluate it rather than resolving it once.
|
|
1712
1719
|
|
|
@@ -2247,6 +2254,68 @@ const failures = await commandLog.getCommands({
|
|
|
2247
2254
|
|
|
2248
2255
|
Requires the `CommandLog` permission.
|
|
2249
2256
|
|
|
2257
|
+
#### `useWebhook(): EnergyAppWebhook`
|
|
2258
|
+
|
|
2259
|
+
Receive webhooks from a vendor cloud. Apps run behind NAT on the hub, so every app gets **one** public
|
|
2260
|
+
endpoint on the enyo API instead; whatever JSON body is POSTed to it is forwarded to the app as a parsed object.
|
|
2261
|
+
|
|
2262
|
+
```typescript
|
|
2263
|
+
const webhook = energyApp.useWebhook();
|
|
2264
|
+
|
|
2265
|
+
const url = await webhook.getWebhookUrl(); // stable per app installation
|
|
2266
|
+
await vendorApi.subscribe({ callbackUrl: url });
|
|
2267
|
+
|
|
2268
|
+
const listenerId = webhook.listenForWebhook<VendorEvent>(async (event) => {
|
|
2269
|
+
// event: { webhookRequestId, source, receivedAtIso, body } — source defaults to 'custom-webhook'
|
|
2270
|
+
await handleVendorEvent(event.body); // already parsed JSON
|
|
2271
|
+
});
|
|
2272
|
+
```
|
|
2273
|
+
|
|
2274
|
+
- **One endpoint per app.** Several event types share the same URL; tell them apart by the body.
|
|
2275
|
+
- **The body is already parsed.** `body` is the JSON object the caller sent. The type parameter is an
|
|
2276
|
+
assertion, not validation — check the fields you rely on.
|
|
2277
|
+
- **At-least-once delivery.** A call may be forwarded more than once and order is not guaranteed —
|
|
2278
|
+
deduplicate on `webhookRequestId`.
|
|
2279
|
+
|
|
2280
|
+
Requires the `Webhook` permission.
|
|
2281
|
+
|
|
2282
|
+
#### `useSubscriptions(): EnergyAppSubscriptions`
|
|
2283
|
+
|
|
2284
|
+
Read the subscriptions a customer bought for this app **on this device**. The plans and their prices are
|
|
2285
|
+
declared in the package definition (see [Subscription Plans](#subscription-plans)); enyo handles checkout,
|
|
2286
|
+
billing, renewal and cancellation. The app never starts a purchase — it reads the result and reacts to it.
|
|
2287
|
+
|
|
2288
|
+
```typescript
|
|
2289
|
+
import { isPlanActive } from '@enyo-energy/energy-app-sdk';
|
|
2290
|
+
|
|
2291
|
+
const subscriptions = energyApp.useSubscriptions();
|
|
2292
|
+
|
|
2293
|
+
// On boot: read the current state.
|
|
2294
|
+
applyPlan(isPlanActive(await subscriptions.getSubscriptions(), 'premium'));
|
|
2295
|
+
|
|
2296
|
+
// Afterwards: purchases, renewals, cancellations, failed payments and expiry.
|
|
2297
|
+
subscriptions.listenForSubscriptionChanges(async ({ subscription, previousStatus }) => {
|
|
2298
|
+
// previousStatus is undefined for a new subscription
|
|
2299
|
+
applyPlan(isPlanActive(await subscriptions.getSubscriptions(), 'premium'));
|
|
2300
|
+
});
|
|
2301
|
+
```
|
|
2302
|
+
|
|
2303
|
+
- **Use `isPlanActive()` / `isSubscriptionActive()`** instead of comparing statuses yourself. `trialing`, `active`,
|
|
2304
|
+
`cancelled-until-period-end` and `grace` count as active; `expired` does not.
|
|
2305
|
+
- **`getSubscriptions()` returns expired subscriptions too**, so the app can tell "never bought" from "expired".
|
|
2306
|
+
- **The listener does not replay the current state.** Call `getSubscriptions()` on boot.
|
|
2307
|
+
- **Works offline.** The host keeps the last known state on the device and reports time-based changes (end of
|
|
2308
|
+
trial, grace or paid period) without a connection.
|
|
2309
|
+
- **Fall back safely.** When a plan stops being active, release any control over appliances instead of leaving
|
|
2310
|
+
them in the last commanded state.
|
|
2311
|
+
- **Point the user to an offer** with a notification target `{ type: 'subscription-offer', planKey: 'premium' }`,
|
|
2312
|
+
or set `EnergyAppStateEnum.SubscriptionRequired` when the whole app needs a plan.
|
|
2313
|
+
|
|
2314
|
+
For tests, `InMemorySubscriptions` implements the same interface; `upsertSubscription()` plays the part of enyo
|
|
2315
|
+
and notifies the listeners.
|
|
2316
|
+
|
|
2317
|
+
Requires the `Subscriptions` permission.
|
|
2318
|
+
|
|
2250
2319
|
### Operational Utilities
|
|
2251
2320
|
|
|
2252
2321
|
#### `useOnboardingV2(): EnergyAppOnboardingV2`
|
|
@@ -2855,6 +2924,77 @@ It checks that names are unique slugs, that paths stay inside the package and ca
|
|
|
2855
2924
|
extension, and that any declared MIME type is well formed; two names pointing at one
|
|
2856
2925
|
path is a warning.
|
|
2857
2926
|
|
|
2927
|
+
## Subscription Plans
|
|
2928
|
+
|
|
2929
|
+
Sell a one-time purchase or a monthly or yearly subscription for the whole app or for parts of it. Declare the plans, **including their prices**,
|
|
2930
|
+
in the package definition. The enyo CLI reads them during `enyo release`; enyo offers them to the customer and
|
|
2931
|
+
handles checkout, VAT, invoices, renewal and cancellation. Subscriptions belong to the **device** the app runs on.
|
|
2932
|
+
|
|
2933
|
+
```typescript
|
|
2934
|
+
import {
|
|
2935
|
+
defineEnergyAppPackage,
|
|
2936
|
+
defineSubscriptionPlan,
|
|
2937
|
+
EnergyAppPermissionTypeEnum,
|
|
2938
|
+
EnyoCurrencyEnum,
|
|
2939
|
+
EnyoSubscriptionPaymentIntervalEnum,
|
|
2940
|
+
validatePackageSubscriptionPlans
|
|
2941
|
+
} from '@enyo-energy/energy-app-sdk';
|
|
2942
|
+
|
|
2943
|
+
const packageDef = defineEnergyAppPackage({
|
|
2944
|
+
// ...
|
|
2945
|
+
permissions: [EnergyAppPermissionTypeEnum.Subscriptions /* , ... */],
|
|
2946
|
+
subscriptionPlans: [
|
|
2947
|
+
defineSubscriptionPlan({
|
|
2948
|
+
planKey: 'premium',
|
|
2949
|
+
paymentInterval: EnyoSubscriptionPaymentIntervalEnum.Yearly,
|
|
2950
|
+
prices: [{ amountWithoutTax: 41.18, currency: EnyoCurrencyEnum.EUR }],
|
|
2951
|
+
trialDays: 30,
|
|
2952
|
+
storeEntry: [
|
|
2953
|
+
{
|
|
2954
|
+
language: 'en',
|
|
2955
|
+
title: 'Premium',
|
|
2956
|
+
shortDescription: 'Optimises your heat pump with dynamic prices.',
|
|
2957
|
+
benefits: ['Dynamic price optimisation', 'Heat pump boost']
|
|
2958
|
+
},
|
|
2959
|
+
{
|
|
2960
|
+
language: 'de',
|
|
2961
|
+
title: 'Premium',
|
|
2962
|
+
shortDescription: 'Optimiert deine Wärmepumpe mit dynamischen Preisen.',
|
|
2963
|
+
benefits: ['Optimierung nach dynamischen Preisen', 'Wärmepumpen-Boost']
|
|
2964
|
+
}
|
|
2965
|
+
]
|
|
2966
|
+
})
|
|
2967
|
+
]
|
|
2968
|
+
});
|
|
2969
|
+
```
|
|
2970
|
+
|
|
2971
|
+
| Field | Meaning |
|
|
2972
|
+
|---|---|
|
|
2973
|
+
| `planKey` | Kebab-case slug, unique in the package. Subscriptions refer to the plan by it — treat it as an API. |
|
|
2974
|
+
| `paymentInterval` | `one-time`, `monthly` or `yearly`. One-time purchases never renew and stay `active` until refunded. |
|
|
2975
|
+
| `prices` | One net price per currency. `amountWithoutTax` is always the **total for one interval** — per month, per year, or the single one-time amount — in the currency (not cent), at most two decimals; enyo adds VAT. |
|
|
2976
|
+
| `trialDays` | Optional free trial in days. Not allowed for `one-time` plans. |
|
|
2977
|
+
| `storeEntry` | Title, short description and optional benefits; `de` and `en` are required. |
|
|
2978
|
+
| `internalComment` | Optional note, never shown to users. |
|
|
2979
|
+
|
|
2980
|
+
What a plan unlocks is decided by the app: check `isPlanActive(subscriptions, planKey)` at runtime (see
|
|
2981
|
+
[`useSubscriptions()`](#usesubscriptions-energyappsubscriptions)).
|
|
2982
|
+
|
|
2983
|
+
**A price change needs a new release** and only applies to new purchases — running subscriptions keep the price
|
|
2984
|
+
they were bought at.
|
|
2985
|
+
|
|
2986
|
+
Validate the plans before releasing:
|
|
2987
|
+
|
|
2988
|
+
```typescript
|
|
2989
|
+
const { ok, errors } = validatePackageSubscriptionPlans(packageDef);
|
|
2990
|
+
// or: assertValidPackageSubscriptionPlans(packageDef) — throws PackageSubscriptionPlansValidationError
|
|
2991
|
+
```
|
|
2992
|
+
|
|
2993
|
+
It checks that plan keys are unique slugs, that the payment interval is known, that every plan has at least one
|
|
2994
|
+
positive price per currency with at most two decimals, that `trialDays` is a positive whole number and not set on a
|
|
2995
|
+
`one-time` plan, that `de` and
|
|
2996
|
+
`en` store entries exist, and that the package requests the `Subscriptions` permission.
|
|
2997
|
+
|
|
2858
2998
|
## Printable Manual Setup Guide
|
|
2859
2999
|
|
|
2860
3000
|
A package can declare **one optional** onboarding guide (v2) as static data in its package
|
|
@@ -3216,6 +3356,7 @@ Switches one heating circuit or DHW zone to its **comfort** or **eco** setpoint
|
|
|
3216
3356
|
- **One zone per message**, answered with a plain `CommandAcknowledgeV1`.
|
|
3217
3357
|
- **Ending and safety net.** `mode: Program` ends a switch (idempotent). A switch to comfort or eco holds until `untilIso` (at most `HEATPUMP_PROGRAM_SWITCH_MAX_MINUTES` = 30 min ahead); the energy manager re-sends about every 15 min while it should hold. When `untilIso` passes without a newer message, the base class calls `handleHeatpumpProgramSwitch` with `mode: Program` and `cause: HeatpumpProgramSwitchCauseEnum.Expired` — so after a restart of either side a zone is back on its program within 30 min, and the app stores nothing.
|
|
3218
3358
|
- **Alongside `HeatpumpControlV3`.** The two run side by side: the mode sets the base, an action raises above it (eco 20 °C + room action +1 K = 21 °C).
|
|
3359
|
+
- **Owner's consent for price-driven eco.** An energy manager switches zones to eco for price reasons only while the general setting `heatpumpEcoModeInExpensiveTimes` (and `heatpumpControl`) is `true` — see [General settings](#general-settings).
|
|
3219
3360
|
- **Validation** (run by the base class before the handler, or `validateHeatpumpProgramSwitch(data, metadata)` directly): target `Room` / `Dhw`, a known mode, a valid `untilIso` for comfort / eco (`Rejected`); `ProgramSwitch` declared and the mode listed for the zone (`NotSupported`); a known zone index (`Rejected`).
|
|
3220
3361
|
|
|
3221
3362
|
#### HeatpumpFlexibilityAnnouncementV3
|
|
@@ -2,6 +2,7 @@ import { EnergyAppPermissionType } from "./energy-app-permission.type.cjs";
|
|
|
2
2
|
import { EnergyAppModelFeatureEnum } from "./energy-app-model-feature.enum.cjs";
|
|
3
3
|
import type { EnyoFileTranslation } from "./types/enyo-file.cjs";
|
|
4
4
|
import type { EnyoOnboardingV2Guide } from "./types/enyo-onboarding-v2.cjs";
|
|
5
|
+
import type { EnyoSubscriptionPaymentInterval, EnyoSubscriptionPrice } from "./types/enyo-subscription.cjs";
|
|
5
6
|
export type EnergyAppPackageLanguage = 'de' | 'en';
|
|
6
7
|
export declare enum EnergyAppPackageCategory {
|
|
7
8
|
Inverter = "inverter",
|
|
@@ -281,6 +282,74 @@ export interface EnergyAppPackageStoreEntry {
|
|
|
281
282
|
/** Detailed description of the package functionality */
|
|
282
283
|
description: string;
|
|
283
284
|
}
|
|
285
|
+
/**
|
|
286
|
+
* Localized store information for one subscription plan. Shown by enyo on the
|
|
287
|
+
* offer and checkout screens and in the customer's subscription overview.
|
|
288
|
+
*/
|
|
289
|
+
export interface EnergyAppPackageSubscriptionPlanStoreEntry {
|
|
290
|
+
/** Language code for this store entry */
|
|
291
|
+
language: EnergyAppPackageLanguage;
|
|
292
|
+
/** Display name of the plan, e.g. `'Premium'` */
|
|
293
|
+
title: string;
|
|
294
|
+
/** One sentence describing what the plan unlocks */
|
|
295
|
+
shortDescription: string;
|
|
296
|
+
/** Optional list of benefits, shown as bullet points on the offer screen */
|
|
297
|
+
benefits?: string[];
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* A subscription plan an Energy App package sells, declared in
|
|
301
|
+
* {@link EnergyAppPackageDefinition.subscriptionPlans}.
|
|
302
|
+
*
|
|
303
|
+
* A plan can unlock the whole app or only parts of it — the app decides that
|
|
304
|
+
* in its own code by checking whether the plan is active (see
|
|
305
|
+
* {@link EnergyAppSubscriptions}). enyo handles checkout, billing, renewal and
|
|
306
|
+
* cancellation; the plan only describes what is sold and at which price.
|
|
307
|
+
*
|
|
308
|
+
* The enyo CLI reads the plans at release time. A price change therefore
|
|
309
|
+
* requires a new release, and only applies to new purchases: running
|
|
310
|
+
* subscriptions keep the price they were bought at.
|
|
311
|
+
*
|
|
312
|
+
* @example
|
|
313
|
+
* ```typescript
|
|
314
|
+
* defineSubscriptionPlan({
|
|
315
|
+
* planKey: 'premium',
|
|
316
|
+
* paymentInterval: EnyoSubscriptionPaymentIntervalEnum.Yearly,
|
|
317
|
+
* prices: [{amountWithoutTax: 41.18, currency: EnyoCurrencyEnum.EUR}],
|
|
318
|
+
* trialDays: 30,
|
|
319
|
+
* storeEntry: [
|
|
320
|
+
* {language: 'en', title: 'Premium', shortDescription: 'Optimises your heat pump with dynamic prices.'},
|
|
321
|
+
* {language: 'de', title: 'Premium', shortDescription: 'Optimiert deine Wärmepumpe mit dynamischen Preisen.'}
|
|
322
|
+
* ]
|
|
323
|
+
* })
|
|
324
|
+
* ```
|
|
325
|
+
*/
|
|
326
|
+
export interface EnergyAppPackageSubscriptionPlan {
|
|
327
|
+
/**
|
|
328
|
+
* Stable, app-chosen key for this plan: a kebab-case slug, unique within
|
|
329
|
+
* the package. Subscriptions refer to the plan by this key, so treat it as
|
|
330
|
+
* an API — renaming it disconnects every existing subscription from the
|
|
331
|
+
* app's checks.
|
|
332
|
+
*/
|
|
333
|
+
planKey: string;
|
|
334
|
+
/** How often the plan is paid for: `one-time`, `monthly` or `yearly`. */
|
|
335
|
+
paymentInterval: EnyoSubscriptionPaymentInterval;
|
|
336
|
+
/**
|
|
337
|
+
* Net price, one entry per currency. At least one entry is required. The
|
|
338
|
+
* amount is always the total for one interval: per month for `monthly`,
|
|
339
|
+
* per year for `yearly`, and the single amount for `one-time`.
|
|
340
|
+
*/
|
|
341
|
+
prices: EnyoSubscriptionPrice[];
|
|
342
|
+
/**
|
|
343
|
+
* Optional length of a free trial in days. The customer is charged for the
|
|
344
|
+
* first time when the trial ends, unless they cancelled before. Not
|
|
345
|
+
* allowed for `one-time` plans.
|
|
346
|
+
*/
|
|
347
|
+
trialDays?: number;
|
|
348
|
+
/** Localized store information. Entries for `de` and `en` are required. */
|
|
349
|
+
storeEntry: EnergyAppPackageSubscriptionPlanStoreEntry[];
|
|
350
|
+
/** Optional internal note explaining this plan; never shown to users. */
|
|
351
|
+
internalComment?: string;
|
|
352
|
+
}
|
|
284
353
|
/**
|
|
285
354
|
* Defines a permission entry for an Energy App package.
|
|
286
355
|
* Contains the permission type and an internal comment explaining its usage.
|
|
@@ -800,6 +869,19 @@ export interface EnergyAppPackageDefinition {
|
|
|
800
869
|
* Omit the field for packages that have no manual setup to document.
|
|
801
870
|
*/
|
|
802
871
|
onboardingGuide?: EnyoOnboardingV2Guide;
|
|
872
|
+
/**
|
|
873
|
+
* Subscription plans this package sells, including their prices. The enyo
|
|
874
|
+
* CLI reads them at release time; enyo offers them to the customer and
|
|
875
|
+
* handles checkout, billing, renewal and cancellation.
|
|
876
|
+
*
|
|
877
|
+
* Subscriptions belong to the device the app runs on. The app reads them
|
|
878
|
+
* at runtime through {@link EnergyAppSubscriptions}, which requires the
|
|
879
|
+
* `Subscriptions` permission. Validate the declarations with
|
|
880
|
+
* `validatePackageSubscriptionPlans()` before publishing.
|
|
881
|
+
*
|
|
882
|
+
* Omit for packages that are free.
|
|
883
|
+
*/
|
|
884
|
+
subscriptionPlans?: EnergyAppPackageSubscriptionPlan[];
|
|
803
885
|
}
|
|
804
886
|
/**
|
|
805
887
|
* Defines an Energy App package with automatic SDK version injection.
|
|
@@ -67,4 +67,6 @@ var EnergyAppPermissionTypeEnum;
|
|
|
67
67
|
EnergyAppPermissionTypeEnum["CommandLog"] = "CommandLog";
|
|
68
68
|
EnergyAppPermissionTypeEnum["Calibration"] = "Calibration";
|
|
69
69
|
EnergyAppPermissionTypeEnum["VehicleIntegration"] = "VehicleIntegration";
|
|
70
|
+
EnergyAppPermissionTypeEnum["Webhook"] = "Webhook";
|
|
71
|
+
EnergyAppPermissionTypeEnum["Subscriptions"] = "Subscriptions";
|
|
70
72
|
})(EnergyAppPermissionTypeEnum || (exports.EnergyAppPermissionTypeEnum = EnergyAppPermissionTypeEnum = {}));
|
|
@@ -62,7 +62,9 @@ export declare enum EnergyAppPermissionTypeEnum {
|
|
|
62
62
|
GridFeeUse = "GridFeeUse",
|
|
63
63
|
CommandLog = "CommandLog",
|
|
64
64
|
Calibration = "Calibration",
|
|
65
|
-
VehicleIntegration = "VehicleIntegration"
|
|
65
|
+
VehicleIntegration = "VehicleIntegration",
|
|
66
|
+
Webhook = "Webhook",
|
|
67
|
+
Subscriptions = "Subscriptions"
|
|
66
68
|
}
|
|
67
69
|
/**
|
|
68
70
|
* String union of every permission name, derived from
|
package/dist/cjs/energy-app.cjs
CHANGED
|
@@ -523,6 +523,35 @@ class EnergyApp {
|
|
|
523
523
|
useCascade() {
|
|
524
524
|
return this.energyAppSdk.useCascade();
|
|
525
525
|
}
|
|
526
|
+
/**
|
|
527
|
+
* Gets the Webhook API for receiving webhooks from third-party services.
|
|
528
|
+
*
|
|
529
|
+
* Every app has exactly one webhook endpoint on the enyo API. Read its URL
|
|
530
|
+
* with `getWebhookUrl()`, hand it to the vendor, and every JSON body posted
|
|
531
|
+
* to it is forwarded as a parsed object to the listeners registered with
|
|
532
|
+
* `listenForWebhook()`.
|
|
533
|
+
* @returns The Webhook API instance
|
|
534
|
+
* @throws {EnergyAppPermissionNotGrantedError} If the `Webhook`
|
|
535
|
+
* permission is not granted.
|
|
536
|
+
*/
|
|
537
|
+
useWebhook() {
|
|
538
|
+
return this.energyAppSdk.useWebhook();
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Gets the Subscriptions API for reading the subscriptions a customer
|
|
542
|
+
* bought for this app on this device.
|
|
543
|
+
*
|
|
544
|
+
* The plans and their prices are declared in the package definition;
|
|
545
|
+
* enyo handles checkout, billing, renewal and cancellation. The app reads
|
|
546
|
+
* the result with `getSubscriptions()` and reacts to purchases, renewals,
|
|
547
|
+
* cancellations and expiry with `listenForSubscriptionChanges()`.
|
|
548
|
+
* @returns The Subscriptions API instance
|
|
549
|
+
* @throws {EnergyAppPermissionNotGrantedError} If the `Subscriptions`
|
|
550
|
+
* permission is not granted.
|
|
551
|
+
*/
|
|
552
|
+
useSubscriptions() {
|
|
553
|
+
return this.energyAppSdk.useSubscriptions();
|
|
554
|
+
}
|
|
526
555
|
/**
|
|
527
556
|
* Gets the current SDK version.
|
|
528
557
|
* @returns The semantic version string of the SDK
|
|
@@ -51,6 +51,8 @@ import { EnergyAppEpexSpotPrice } from "./packages/energy-app-epex-spot-price.cj
|
|
|
51
51
|
import { EnergyAppGridFee } from "./packages/energy-app-grid-fee.cjs";
|
|
52
52
|
import { EnergyAppCommandLog } from "./packages/energy-app-command-log.cjs";
|
|
53
53
|
import { EnergyAppCascade } from "./packages/energy-app-cascade.cjs";
|
|
54
|
+
import { EnergyAppWebhook } from "./packages/energy-app-webhook.cjs";
|
|
55
|
+
import { EnergyAppSubscriptions } from "./packages/energy-app-subscriptions.cjs";
|
|
54
56
|
import { UseFetchOptions } from "./types/enyo-fetch.cjs";
|
|
55
57
|
/**
|
|
56
58
|
* Concrete implementation of {@link EnyoEnergyAppSdk} that delegates every call
|
|
@@ -442,6 +444,31 @@ export declare class EnergyApp implements EnyoEnergyAppSdk {
|
|
|
442
444
|
* called method is not granted.
|
|
443
445
|
*/
|
|
444
446
|
useCascade(): EnergyAppCascade;
|
|
447
|
+
/**
|
|
448
|
+
* Gets the Webhook API for receiving webhooks from third-party services.
|
|
449
|
+
*
|
|
450
|
+
* Every app has exactly one webhook endpoint on the enyo API. Read its URL
|
|
451
|
+
* with `getWebhookUrl()`, hand it to the vendor, and every JSON body posted
|
|
452
|
+
* to it is forwarded as a parsed object to the listeners registered with
|
|
453
|
+
* `listenForWebhook()`.
|
|
454
|
+
* @returns The Webhook API instance
|
|
455
|
+
* @throws {EnergyAppPermissionNotGrantedError} If the `Webhook`
|
|
456
|
+
* permission is not granted.
|
|
457
|
+
*/
|
|
458
|
+
useWebhook(): EnergyAppWebhook;
|
|
459
|
+
/**
|
|
460
|
+
* Gets the Subscriptions API for reading the subscriptions a customer
|
|
461
|
+
* bought for this app on this device.
|
|
462
|
+
*
|
|
463
|
+
* The plans and their prices are declared in the package definition;
|
|
464
|
+
* enyo handles checkout, billing, renewal and cancellation. The app reads
|
|
465
|
+
* the result with `getSubscriptions()` and reacts to purchases, renewals,
|
|
466
|
+
* cancellations and expiry with `listenForSubscriptionChanges()`.
|
|
467
|
+
* @returns The Subscriptions API instance
|
|
468
|
+
* @throws {EnergyAppPermissionNotGrantedError} If the `Subscriptions`
|
|
469
|
+
* permission is not granted.
|
|
470
|
+
*/
|
|
471
|
+
useSubscriptions(): EnergyAppSubscriptions;
|
|
445
472
|
/**
|
|
446
473
|
* Gets the current SDK version.
|
|
447
474
|
* @returns The semantic version string of the SDK
|
|
@@ -9,4 +9,6 @@ var EnergyAppStateEnum;
|
|
|
9
9
|
EnergyAppStateEnum["ConfigurationRequired"] = "configuration-required";
|
|
10
10
|
/** This state tells the user that an internet connection of the system is required which blocks the energy app from running*/
|
|
11
11
|
EnergyAppStateEnum["InternetConnectionRequired"] = "internet-connection-required";
|
|
12
|
+
/** This state tells the user that a subscription plan is required which blocks the energy app from running. The host shows the plans declared in the package definition. */
|
|
13
|
+
EnergyAppStateEnum["SubscriptionRequired"] = "subscription-required";
|
|
12
14
|
})(EnergyAppStateEnum || (exports.EnergyAppStateEnum = EnergyAppStateEnum = {}));
|
|
@@ -50,6 +50,8 @@ import { EnergyAppEpexSpotPrice } from "./packages/energy-app-epex-spot-price.cj
|
|
|
50
50
|
import { EnergyAppGridFee } from "./packages/energy-app-grid-fee.cjs";
|
|
51
51
|
import { EnergyAppCommandLog } from "./packages/energy-app-command-log.cjs";
|
|
52
52
|
import { EnergyAppCascade } from "./packages/energy-app-cascade.cjs";
|
|
53
|
+
import { EnergyAppWebhook } from "./packages/energy-app-webhook.cjs";
|
|
54
|
+
import { EnergyAppSubscriptions } from "./packages/energy-app-subscriptions.cjs";
|
|
53
55
|
import { UseFetchOptions } from "./types/enyo-fetch.cjs";
|
|
54
56
|
export declare enum EnergyAppStateEnum {
|
|
55
57
|
Launching = "launching",
|
|
@@ -57,7 +59,9 @@ export declare enum EnergyAppStateEnum {
|
|
|
57
59
|
/** This state tells the user that a configuration is required which blocks the energy app from running*/
|
|
58
60
|
ConfigurationRequired = "configuration-required",
|
|
59
61
|
/** This state tells the user that an internet connection of the system is required which blocks the energy app from running*/
|
|
60
|
-
InternetConnectionRequired = "internet-connection-required"
|
|
62
|
+
InternetConnectionRequired = "internet-connection-required",
|
|
63
|
+
/** This state tells the user that a subscription plan is required which blocks the energy app from running. The host shows the plans declared in the package definition. */
|
|
64
|
+
SubscriptionRequired = "subscription-required"
|
|
61
65
|
}
|
|
62
66
|
/**
|
|
63
67
|
* Main API interface for enyo Energy App packages.
|
|
@@ -184,4 +188,8 @@ export interface EnyoEnergyAppSdk {
|
|
|
184
188
|
useCommandLog: () => EnergyAppCommandLog;
|
|
185
189
|
/** Get the Cascade API for the meter behind the primary meter: whether it is active, which appliances are behind it, and its own electricity tariff, prices and grid fee */
|
|
186
190
|
useCascade: () => EnergyAppCascade;
|
|
191
|
+
/** Get the Webhook API for reading this app's single webhook URL on the enyo API and receiving the raw JSON bodies posted to it */
|
|
192
|
+
useWebhook: () => EnergyAppWebhook;
|
|
193
|
+
/** Get the Subscriptions API for reading the subscriptions bought for this app on this device and listening for new or changed subscriptions */
|
|
194
|
+
useSubscriptions: () => EnergyAppSubscriptions;
|
|
187
195
|
}
|
package/dist/cjs/implementations/energy-manager-settings/energy-manager-settings-validators.cjs
CHANGED
|
@@ -208,7 +208,8 @@ function validateEnergyManagerSettingsState(state) {
|
|
|
208
208
|
const values = state.values ?? {};
|
|
209
209
|
// ── value formats ──────────────────────────────────────────────────────
|
|
210
210
|
for (const key of ['batteryControl', 'batteryChargeFromGrid', 'heatpumpControl',
|
|
211
|
-
'
|
|
211
|
+
'heatpumpEcoModeInExpensiveTimes', 'heatingRodControl', 'chargerControl',
|
|
212
|
+
'gridOptimizedEvCharging']) {
|
|
212
213
|
if (values[key] !== undefined && typeof values[key] !== 'boolean') {
|
|
213
214
|
errors.push(`\`${key}\` must be a boolean when set.`);
|
|
214
215
|
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Authoring and runtime helpers for subscription plans
|
|
4
|
+
* ({@link EnergyAppPackageDefinition.subscriptionPlans}).
|
|
5
|
+
*
|
|
6
|
+
* `defineSubscriptionPlan()` is an identity helper that type-checks a plan
|
|
7
|
+
* where it is written — mirroring `definePublicFile()` and
|
|
8
|
+
* `defineFirmwareFile()`. `isSubscriptionActive()` and `isPlanActive()` hold
|
|
9
|
+
* the single rule for which subscription statuses grant access, so every app
|
|
10
|
+
* applies it the same way.
|
|
11
|
+
*
|
|
12
|
+
* Pair with `validatePackageSubscriptionPlans()`
|
|
13
|
+
* (`./subscription-plan-validators.ts`) to fail fast before publishing.
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.ACTIVE_SUBSCRIPTION_STATUSES = void 0;
|
|
17
|
+
exports.defineSubscriptionPlan = defineSubscriptionPlan;
|
|
18
|
+
exports.isSubscriptionActive = isSubscriptionActive;
|
|
19
|
+
exports.isPlanActive = isPlanActive;
|
|
20
|
+
const enyo_subscription_js_1 = require("../../types/enyo-subscription.cjs");
|
|
21
|
+
/**
|
|
22
|
+
* Subscription statuses in which the customer may use what a plan unlocks.
|
|
23
|
+
*
|
|
24
|
+
* A cancelled subscription stays usable until its paid period ends, and a
|
|
25
|
+
* subscription whose renewal payment failed stays usable during the grace
|
|
26
|
+
* period.
|
|
27
|
+
*/
|
|
28
|
+
exports.ACTIVE_SUBSCRIPTION_STATUSES = [
|
|
29
|
+
enyo_subscription_js_1.EnyoSubscriptionStatusEnum.Trialing,
|
|
30
|
+
enyo_subscription_js_1.EnyoSubscriptionStatusEnum.Active,
|
|
31
|
+
enyo_subscription_js_1.EnyoSubscriptionStatusEnum.CancelledUntilPeriodEnd,
|
|
32
|
+
enyo_subscription_js_1.EnyoSubscriptionStatusEnum.Grace,
|
|
33
|
+
];
|
|
34
|
+
/**
|
|
35
|
+
* Identity helper that type-checks a subscription plan at definition time
|
|
36
|
+
* (mirrors `defineEnergyAppPackage`). Prefer this over a bare object literal so
|
|
37
|
+
* mistakes surface where the plan is written.
|
|
38
|
+
*
|
|
39
|
+
* @param plan - The subscription plan to declare.
|
|
40
|
+
* @returns The same plan, typed as {@link EnergyAppPackageSubscriptionPlan}.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* defineSubscriptionPlan({
|
|
45
|
+
* planKey: 'premium',
|
|
46
|
+
* paymentInterval: EnyoSubscriptionPaymentIntervalEnum.Yearly,
|
|
47
|
+
* prices: [{amountWithoutTax: 41.18, currency: EnyoCurrencyEnum.EUR}],
|
|
48
|
+
* storeEntry: [
|
|
49
|
+
* {language: 'en', title: 'Premium', shortDescription: 'Optimises your heat pump with dynamic prices.'},
|
|
50
|
+
* {language: 'de', title: 'Premium', shortDescription: 'Optimiert deine Wärmepumpe mit dynamischen Preisen.'}
|
|
51
|
+
* ]
|
|
52
|
+
* })
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
function defineSubscriptionPlan(plan) {
|
|
56
|
+
return plan;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Tests whether a subscription currently grants access, i.e. whether its
|
|
60
|
+
* status is one of {@link ACTIVE_SUBSCRIPTION_STATUSES}.
|
|
61
|
+
*
|
|
62
|
+
* @param subscription - The subscription to check.
|
|
63
|
+
* @returns True when the customer may use what the subscription's plan unlocks.
|
|
64
|
+
*/
|
|
65
|
+
function isSubscriptionActive(subscription) {
|
|
66
|
+
return exports.ACTIVE_SUBSCRIPTION_STATUSES.includes(subscription.status);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Tests whether the customer has an active subscription for a plan.
|
|
70
|
+
*
|
|
71
|
+
* @param subscriptions - The subscriptions, as returned by
|
|
72
|
+
* {@link EnergyAppSubscriptions.getSubscriptions}.
|
|
73
|
+
* @param planKey - The {@link EnergyAppPackageSubscriptionPlan.planKey} to check.
|
|
74
|
+
* @returns True when at least one subscription for the plan is active.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```typescript
|
|
78
|
+
* const subscriptions = await energyApp.useSubscriptions().getSubscriptions();
|
|
79
|
+
* if (isPlanActive(subscriptions, 'premium')) {
|
|
80
|
+
* enableOptimisation();
|
|
81
|
+
* }
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
function isPlanActive(subscriptions, planKey) {
|
|
85
|
+
return subscriptions.some(subscription => subscription.planKey === planKey && isSubscriptionActive(subscription));
|
|
86
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authoring and runtime helpers for subscription plans
|
|
3
|
+
* ({@link EnergyAppPackageDefinition.subscriptionPlans}).
|
|
4
|
+
*
|
|
5
|
+
* `defineSubscriptionPlan()` is an identity helper that type-checks a plan
|
|
6
|
+
* where it is written — mirroring `definePublicFile()` and
|
|
7
|
+
* `defineFirmwareFile()`. `isSubscriptionActive()` and `isPlanActive()` hold
|
|
8
|
+
* the single rule for which subscription statuses grant access, so every app
|
|
9
|
+
* applies it the same way.
|
|
10
|
+
*
|
|
11
|
+
* Pair with `validatePackageSubscriptionPlans()`
|
|
12
|
+
* (`./subscription-plan-validators.ts`) to fail fast before publishing.
|
|
13
|
+
*/
|
|
14
|
+
import type { EnergyAppPackageSubscriptionPlan } from '../../energy-app-package-definition.cjs';
|
|
15
|
+
import { EnyoSubscription, EnyoSubscriptionStatus } from '../../types/enyo-subscription.cjs';
|
|
16
|
+
/**
|
|
17
|
+
* Subscription statuses in which the customer may use what a plan unlocks.
|
|
18
|
+
*
|
|
19
|
+
* A cancelled subscription stays usable until its paid period ends, and a
|
|
20
|
+
* subscription whose renewal payment failed stays usable during the grace
|
|
21
|
+
* period.
|
|
22
|
+
*/
|
|
23
|
+
export declare const ACTIVE_SUBSCRIPTION_STATUSES: readonly EnyoSubscriptionStatus[];
|
|
24
|
+
/**
|
|
25
|
+
* Identity helper that type-checks a subscription plan at definition time
|
|
26
|
+
* (mirrors `defineEnergyAppPackage`). Prefer this over a bare object literal so
|
|
27
|
+
* mistakes surface where the plan is written.
|
|
28
|
+
*
|
|
29
|
+
* @param plan - The subscription plan to declare.
|
|
30
|
+
* @returns The same plan, typed as {@link EnergyAppPackageSubscriptionPlan}.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* defineSubscriptionPlan({
|
|
35
|
+
* planKey: 'premium',
|
|
36
|
+
* paymentInterval: EnyoSubscriptionPaymentIntervalEnum.Yearly,
|
|
37
|
+
* prices: [{amountWithoutTax: 41.18, currency: EnyoCurrencyEnum.EUR}],
|
|
38
|
+
* storeEntry: [
|
|
39
|
+
* {language: 'en', title: 'Premium', shortDescription: 'Optimises your heat pump with dynamic prices.'},
|
|
40
|
+
* {language: 'de', title: 'Premium', shortDescription: 'Optimiert deine Wärmepumpe mit dynamischen Preisen.'}
|
|
41
|
+
* ]
|
|
42
|
+
* })
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function defineSubscriptionPlan(plan: EnergyAppPackageSubscriptionPlan): EnergyAppPackageSubscriptionPlan;
|
|
46
|
+
/**
|
|
47
|
+
* Tests whether a subscription currently grants access, i.e. whether its
|
|
48
|
+
* status is one of {@link ACTIVE_SUBSCRIPTION_STATUSES}.
|
|
49
|
+
*
|
|
50
|
+
* @param subscription - The subscription to check.
|
|
51
|
+
* @returns True when the customer may use what the subscription's plan unlocks.
|
|
52
|
+
*/
|
|
53
|
+
export declare function isSubscriptionActive(subscription: EnyoSubscription): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Tests whether the customer has an active subscription for a plan.
|
|
56
|
+
*
|
|
57
|
+
* @param subscriptions - The subscriptions, as returned by
|
|
58
|
+
* {@link EnergyAppSubscriptions.getSubscriptions}.
|
|
59
|
+
* @param planKey - The {@link EnergyAppPackageSubscriptionPlan.planKey} to check.
|
|
60
|
+
* @returns True when at least one subscription for the plan is active.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* const subscriptions = await energyApp.useSubscriptions().getSubscriptions();
|
|
65
|
+
* if (isPlanActive(subscriptions, 'premium')) {
|
|
66
|
+
* enableOptimisation();
|
|
67
|
+
* }
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export declare function isPlanActive(subscriptions: EnyoSubscription[], planKey: string): boolean;
|