iobroker.parcelapp 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,219 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var i18n_states_exports = {};
20
+ __export(i18n_states_exports, {
21
+ STATE_NAMES: () => STATE_NAMES,
22
+ tName: () => tName
23
+ });
24
+ module.exports = __toCommonJS(i18n_states_exports);
25
+ const STATE_NAMES = {
26
+ // ──────── Per-delivery states ────────
27
+ carrier: {
28
+ en: "Carrier",
29
+ de: "Versanddienst",
30
+ ru: "\u041F\u0435\u0440\u0435\u0432\u043E\u0437\u0447\u0438\u043A",
31
+ pt: "Transportadora",
32
+ nl: "Vervoerder",
33
+ fr: "Transporteur",
34
+ it: "Corriere",
35
+ es: "Transportista",
36
+ pl: "Przewo\u017Anik",
37
+ uk: "\u041F\u0435\u0440\u0435\u0432\u0456\u0437\u043D\u0438\u043A",
38
+ "zh-cn": "\u627F\u8FD0\u5546"
39
+ },
40
+ status: {
41
+ en: "Status",
42
+ de: "Status",
43
+ ru: "\u0421\u0442\u0430\u0442\u0443\u0441",
44
+ pt: "Estado",
45
+ nl: "Status",
46
+ fr: "\xC9tat",
47
+ it: "Stato",
48
+ es: "Estado",
49
+ pl: "Status",
50
+ uk: "\u0421\u0442\u0430\u0442\u0443\u0441",
51
+ "zh-cn": "\u72B6\u6001"
52
+ },
53
+ statusCode: {
54
+ en: "Status Code",
55
+ de: "Status-Code",
56
+ ru: "\u041A\u043E\u0434 \u0441\u0442\u0430\u0442\u0443\u0441\u0430",
57
+ pt: "C\xF3digo de estado",
58
+ nl: "Statuscode",
59
+ fr: "Code d'\xE9tat",
60
+ it: "Codice di stato",
61
+ es: "C\xF3digo de estado",
62
+ pl: "Kod statusu",
63
+ uk: "\u041A\u043E\u0434 \u0441\u0442\u0430\u0442\u0443\u0441\u0443",
64
+ "zh-cn": "\u72B6\u6001\u4EE3\u7801"
65
+ },
66
+ description: {
67
+ en: "Description",
68
+ de: "Beschreibung",
69
+ ru: "\u041E\u043F\u0438\u0441\u0430\u043D\u0438\u0435",
70
+ pt: "Descri\xE7\xE3o",
71
+ nl: "Beschrijving",
72
+ fr: "Description",
73
+ it: "Descrizione",
74
+ es: "Descripci\xF3n",
75
+ pl: "Opis",
76
+ uk: "\u041E\u043F\u0438\u0441",
77
+ "zh-cn": "\u63CF\u8FF0"
78
+ },
79
+ trackingNumber: {
80
+ en: "Tracking Number",
81
+ de: "Sendungsnummer",
82
+ ru: "\u0422\u0440\u0435\u043A-\u043D\u043E\u043C\u0435\u0440",
83
+ pt: "N\xFAmero de rastreio",
84
+ nl: "Trackingnummer",
85
+ fr: "Num\xE9ro de suivi",
86
+ it: "Numero di tracciamento",
87
+ es: "N\xFAmero de seguimiento",
88
+ pl: "Numer \u015Bledzenia",
89
+ uk: "\u041D\u043E\u043C\u0435\u0440 \u0432\u0456\u0434\u0441\u0442\u0435\u0436\u0435\u043D\u043D\u044F",
90
+ "zh-cn": "\u8FFD\u8E2A\u53F7"
91
+ },
92
+ extraInfo: {
93
+ en: "Extra Information",
94
+ de: "Zusatz-Information",
95
+ ru: "\u0414\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044F",
96
+ pt: "Informa\xE7\xE3o adicional",
97
+ nl: "Extra informatie",
98
+ fr: "Informations suppl\xE9mentaires",
99
+ it: "Informazioni aggiuntive",
100
+ es: "Informaci\xF3n adicional",
101
+ pl: "Dodatkowe informacje",
102
+ uk: "\u0414\u043E\u0434\u0430\u0442\u043A\u043E\u0432\u0430 \u0456\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0456\u044F",
103
+ "zh-cn": "\u9644\u52A0\u4FE1\u606F"
104
+ },
105
+ deliveryWindow: {
106
+ en: "Delivery Window",
107
+ de: "Zustellfenster",
108
+ ru: "\u041E\u043A\u043D\u043E \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438",
109
+ pt: "Janela de entrega",
110
+ nl: "Bezorgvenster",
111
+ fr: "Cr\xE9neau de livraison",
112
+ it: "Finestra di consegna",
113
+ es: "Ventana de entrega",
114
+ pl: "Okno dostawy",
115
+ uk: "\u0412\u0456\u043A\u043D\u043E \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438",
116
+ "zh-cn": "\u6D3E\u9001\u65F6\u6BB5"
117
+ },
118
+ deliveryEstimate: {
119
+ en: "Delivery Estimate",
120
+ de: "Voraussichtliche Zustellung",
121
+ ru: "\u041E\u0436\u0438\u0434\u0430\u0435\u043C\u0430\u044F \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0430",
122
+ pt: "Previs\xE3o de entrega",
123
+ nl: "Verwachte bezorging",
124
+ fr: "Livraison estim\xE9e",
125
+ it: "Consegna prevista",
126
+ es: "Entrega estimada",
127
+ pl: "Szacowana dostawa",
128
+ uk: "\u041E\u0447\u0456\u043A\u0443\u0432\u0430\u043D\u0430 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0430",
129
+ "zh-cn": "\u9884\u8BA1\u9001\u8FBE"
130
+ },
131
+ lastEvent: {
132
+ en: "Last Event",
133
+ de: "Letztes Ereignis",
134
+ ru: "\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0435 \u0441\u043E\u0431\u044B\u0442\u0438\u0435",
135
+ pt: "\xDAltimo evento",
136
+ nl: "Laatste gebeurtenis",
137
+ fr: "Dernier \xE9v\xE9nement",
138
+ it: "Ultimo evento",
139
+ es: "\xDAltimo evento",
140
+ pl: "Ostatnie zdarzenie",
141
+ uk: "\u041E\u0441\u0442\u0430\u043D\u043D\u044F \u043F\u043E\u0434\u0456\u044F",
142
+ "zh-cn": "\u6700\u8FD1\u4E8B\u4EF6"
143
+ },
144
+ lastLocation: {
145
+ en: "Last Location",
146
+ de: "Letzter Standort",
147
+ ru: "\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0435 \u043C\u0435\u0441\u0442\u043E\u043F\u043E\u043B\u043E\u0436\u0435\u043D\u0438\u0435",
148
+ pt: "\xDAltima localiza\xE7\xE3o",
149
+ nl: "Laatste locatie",
150
+ fr: "Dernier emplacement",
151
+ it: "Ultima posizione",
152
+ es: "\xDAltima ubicaci\xF3n",
153
+ pl: "Ostatnia lokalizacja",
154
+ uk: "\u041E\u0441\u0442\u0430\u043D\u043D\u0454 \u043C\u0456\u0441\u0446\u0435\u0437\u043D\u0430\u0445\u043E\u0434\u0436\u0435\u043D\u043D\u044F",
155
+ "zh-cn": "\u6700\u8FD1\u4F4D\u7F6E"
156
+ },
157
+ lastUpdated: {
158
+ en: "Last Updated",
159
+ de: "Zuletzt aktualisiert",
160
+ ru: "\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0435 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0435",
161
+ pt: "\xDAltima atualiza\xE7\xE3o",
162
+ nl: "Laatst bijgewerkt",
163
+ fr: "Derni\xE8re mise \xE0 jour",
164
+ it: "Ultimo aggiornamento",
165
+ es: "\xDAltima actualizaci\xF3n",
166
+ pl: "Ostatnia aktualizacja",
167
+ uk: "\u041E\u0441\u0442\u0430\u043D\u043D\u0454 \u043E\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044F",
168
+ "zh-cn": "\u6700\u540E\u66F4\u65B0"
169
+ },
170
+ // ──────── Summary states ────────
171
+ activeCount: {
172
+ en: "Active Deliveries",
173
+ de: "Aktive Sendungen",
174
+ ru: "\u0410\u043A\u0442\u0438\u0432\u043D\u044B\u0435 \u043F\u043E\u0441\u044B\u043B\u043A\u0438",
175
+ pt: "Entregas ativas",
176
+ nl: "Actieve zendingen",
177
+ fr: "Livraisons actives",
178
+ it: "Spedizioni attive",
179
+ es: "Env\xEDos activos",
180
+ pl: "Aktywne przesy\u0142ki",
181
+ uk: "\u0410\u043A\u0442\u0438\u0432\u043D\u0456 \u0432\u0456\u0434\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u043D\u044F",
182
+ "zh-cn": "\u6D3B\u52A8\u4E2D\u7684\u5305\u88F9"
183
+ },
184
+ todayCount: {
185
+ en: "Deliveries Today",
186
+ de: "Sendungen heute",
187
+ ru: "\u0414\u043E\u0441\u0442\u0430\u0432\u043A\u0438 \u0441\u0435\u0433\u043E\u0434\u043D\u044F",
188
+ pt: "Entregas hoje",
189
+ nl: "Zendingen vandaag",
190
+ fr: "Livraisons aujourd'hui",
191
+ it: "Spedizioni di oggi",
192
+ es: "Entregas de hoy",
193
+ pl: "Dostawy dzisiaj",
194
+ uk: "\u0414\u043E\u0441\u0442\u0430\u0432\u043A\u0438 \u0441\u044C\u043E\u0433\u043E\u0434\u043D\u0456",
195
+ "zh-cn": "\u4ECA\u65E5\u9001\u8FBE"
196
+ },
197
+ summaryDeliveryWindow: {
198
+ en: "Combined Delivery Window",
199
+ de: "Kombiniertes Zustellfenster",
200
+ ru: "\u041E\u0431\u044A\u0435\u0434\u0438\u043D\u0451\u043D\u043D\u043E\u0435 \u043E\u043A\u043D\u043E \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438",
201
+ pt: "Janela de entrega combinada",
202
+ nl: "Gecombineerd bezorgvenster",
203
+ fr: "Cr\xE9neau de livraison combin\xE9",
204
+ it: "Finestra di consegna combinata",
205
+ es: "Ventana de entrega combinada",
206
+ pl: "\u0141\u0105czne okno dostawy",
207
+ uk: "\u041E\u0431'\u0454\u0434\u043D\u0430\u043D\u0435 \u0432\u0456\u043A\u043D\u043E \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438",
208
+ "zh-cn": "\u5408\u5E76\u6D3E\u9001\u65F6\u6BB5"
209
+ }
210
+ };
211
+ function tName(key) {
212
+ return STATE_NAMES[key];
213
+ }
214
+ // Annotate the CommonJS export names for ESM import in node:
215
+ 0 && (module.exports = {
216
+ STATE_NAMES,
217
+ tName
218
+ });
219
+ //# sourceMappingURL=i18n-states.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/lib/i18n-states.ts"],
4
+ "sourcesContent": ["/**\n * Localized state names for parcel deliveries in 11 ioBroker system languages.\n *\n * ioBroker accepts plain strings or `{ en, de, ... }` translation objects for\n * `common.name`. Admin, vis and the Object-Browser pick the user's language\n * automatically \u2014 we just hand them the object.\n *\n * No adapter-side language lookup needed (different from `i18n-logs.ts`,\n * where we have to pick at log-emit time because `this.log.info(...)` takes\n * a single string).\n */\n\ntype Lang = \"en\" | \"de\" | \"ru\" | \"pt\" | \"nl\" | \"fr\" | \"it\" | \"es\" | \"pl\" | \"uk\" | \"zh-cn\";\n\n/** Translation object as ioBroker expects it. */\nexport type StateName = Record<Lang, string>;\n\n/** State / channel display names (`common.name`). */\nexport const STATE_NAMES: Record<string, StateName> = {\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 Per-delivery states \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n carrier: {\n en: \"Carrier\",\n de: \"Versanddienst\",\n ru: \"\u041F\u0435\u0440\u0435\u0432\u043E\u0437\u0447\u0438\u043A\",\n pt: \"Transportadora\",\n nl: \"Vervoerder\",\n fr: \"Transporteur\",\n it: \"Corriere\",\n es: \"Transportista\",\n pl: \"Przewo\u017Anik\",\n uk: \"\u041F\u0435\u0440\u0435\u0432\u0456\u0437\u043D\u0438\u043A\",\n \"zh-cn\": \"\u627F\u8FD0\u5546\",\n },\n status: {\n en: \"Status\",\n de: \"Status\",\n ru: \"\u0421\u0442\u0430\u0442\u0443\u0441\",\n pt: \"Estado\",\n nl: \"Status\",\n fr: \"\u00C9tat\",\n it: \"Stato\",\n es: \"Estado\",\n pl: \"Status\",\n uk: \"\u0421\u0442\u0430\u0442\u0443\u0441\",\n \"zh-cn\": \"\u72B6\u6001\",\n },\n statusCode: {\n en: \"Status Code\",\n de: \"Status-Code\",\n ru: \"\u041A\u043E\u0434 \u0441\u0442\u0430\u0442\u0443\u0441\u0430\",\n pt: \"C\u00F3digo de estado\",\n nl: \"Statuscode\",\n fr: \"Code d'\u00E9tat\",\n it: \"Codice di stato\",\n es: \"C\u00F3digo de estado\",\n pl: \"Kod statusu\",\n uk: \"\u041A\u043E\u0434 \u0441\u0442\u0430\u0442\u0443\u0441\u0443\",\n \"zh-cn\": \"\u72B6\u6001\u4EE3\u7801\",\n },\n description: {\n en: \"Description\",\n de: \"Beschreibung\",\n ru: \"\u041E\u043F\u0438\u0441\u0430\u043D\u0438\u0435\",\n pt: \"Descri\u00E7\u00E3o\",\n nl: \"Beschrijving\",\n fr: \"Description\",\n it: \"Descrizione\",\n es: \"Descripci\u00F3n\",\n pl: \"Opis\",\n uk: \"\u041E\u043F\u0438\u0441\",\n \"zh-cn\": \"\u63CF\u8FF0\",\n },\n trackingNumber: {\n en: \"Tracking Number\",\n de: \"Sendungsnummer\",\n ru: \"\u0422\u0440\u0435\u043A-\u043D\u043E\u043C\u0435\u0440\",\n pt: \"N\u00FAmero de rastreio\",\n nl: \"Trackingnummer\",\n fr: \"Num\u00E9ro de suivi\",\n it: \"Numero di tracciamento\",\n es: \"N\u00FAmero de seguimiento\",\n pl: \"Numer \u015Bledzenia\",\n uk: \"\u041D\u043E\u043C\u0435\u0440 \u0432\u0456\u0434\u0441\u0442\u0435\u0436\u0435\u043D\u043D\u044F\",\n \"zh-cn\": \"\u8FFD\u8E2A\u53F7\",\n },\n extraInfo: {\n en: \"Extra Information\",\n de: \"Zusatz-Information\",\n ru: \"\u0414\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044F\",\n pt: \"Informa\u00E7\u00E3o adicional\",\n nl: \"Extra informatie\",\n fr: \"Informations suppl\u00E9mentaires\",\n it: \"Informazioni aggiuntive\",\n es: \"Informaci\u00F3n adicional\",\n pl: \"Dodatkowe informacje\",\n uk: \"\u0414\u043E\u0434\u0430\u0442\u043A\u043E\u0432\u0430 \u0456\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0456\u044F\",\n \"zh-cn\": \"\u9644\u52A0\u4FE1\u606F\",\n },\n deliveryWindow: {\n en: \"Delivery Window\",\n de: \"Zustellfenster\",\n ru: \"\u041E\u043A\u043D\u043E \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\",\n pt: \"Janela de entrega\",\n nl: \"Bezorgvenster\",\n fr: \"Cr\u00E9neau de livraison\",\n it: \"Finestra di consegna\",\n es: \"Ventana de entrega\",\n pl: \"Okno dostawy\",\n uk: \"\u0412\u0456\u043A\u043D\u043E \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\",\n \"zh-cn\": \"\u6D3E\u9001\u65F6\u6BB5\",\n },\n deliveryEstimate: {\n en: \"Delivery Estimate\",\n de: \"Voraussichtliche Zustellung\",\n ru: \"\u041E\u0436\u0438\u0434\u0430\u0435\u043C\u0430\u044F \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0430\",\n pt: \"Previs\u00E3o de entrega\",\n nl: \"Verwachte bezorging\",\n fr: \"Livraison estim\u00E9e\",\n it: \"Consegna prevista\",\n es: \"Entrega estimada\",\n pl: \"Szacowana dostawa\",\n uk: \"\u041E\u0447\u0456\u043A\u0443\u0432\u0430\u043D\u0430 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0430\",\n \"zh-cn\": \"\u9884\u8BA1\u9001\u8FBE\",\n },\n lastEvent: {\n en: \"Last Event\",\n de: \"Letztes Ereignis\",\n ru: \"\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0435 \u0441\u043E\u0431\u044B\u0442\u0438\u0435\",\n pt: \"\u00DAltimo evento\",\n nl: \"Laatste gebeurtenis\",\n fr: \"Dernier \u00E9v\u00E9nement\",\n it: \"Ultimo evento\",\n es: \"\u00DAltimo evento\",\n pl: \"Ostatnie zdarzenie\",\n uk: \"\u041E\u0441\u0442\u0430\u043D\u043D\u044F \u043F\u043E\u0434\u0456\u044F\",\n \"zh-cn\": \"\u6700\u8FD1\u4E8B\u4EF6\",\n },\n lastLocation: {\n en: \"Last Location\",\n de: \"Letzter Standort\",\n ru: \"\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0435 \u043C\u0435\u0441\u0442\u043E\u043F\u043E\u043B\u043E\u0436\u0435\u043D\u0438\u0435\",\n pt: \"\u00DAltima localiza\u00E7\u00E3o\",\n nl: \"Laatste locatie\",\n fr: \"Dernier emplacement\",\n it: \"Ultima posizione\",\n es: \"\u00DAltima ubicaci\u00F3n\",\n pl: \"Ostatnia lokalizacja\",\n uk: \"\u041E\u0441\u0442\u0430\u043D\u043D\u0454 \u043C\u0456\u0441\u0446\u0435\u0437\u043D\u0430\u0445\u043E\u0434\u0436\u0435\u043D\u043D\u044F\",\n \"zh-cn\": \"\u6700\u8FD1\u4F4D\u7F6E\",\n },\n lastUpdated: {\n en: \"Last Updated\",\n de: \"Zuletzt aktualisiert\",\n ru: \"\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0435 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0435\",\n pt: \"\u00DAltima atualiza\u00E7\u00E3o\",\n nl: \"Laatst bijgewerkt\",\n fr: \"Derni\u00E8re mise \u00E0 jour\",\n it: \"Ultimo aggiornamento\",\n es: \"\u00DAltima actualizaci\u00F3n\",\n pl: \"Ostatnia aktualizacja\",\n uk: \"\u041E\u0441\u0442\u0430\u043D\u043D\u0454 \u043E\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044F\",\n \"zh-cn\": \"\u6700\u540E\u66F4\u65B0\",\n },\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 Summary states \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n activeCount: {\n en: \"Active Deliveries\",\n de: \"Aktive Sendungen\",\n ru: \"\u0410\u043A\u0442\u0438\u0432\u043D\u044B\u0435 \u043F\u043E\u0441\u044B\u043B\u043A\u0438\",\n pt: \"Entregas ativas\",\n nl: \"Actieve zendingen\",\n fr: \"Livraisons actives\",\n it: \"Spedizioni attive\",\n es: \"Env\u00EDos activos\",\n pl: \"Aktywne przesy\u0142ki\",\n uk: \"\u0410\u043A\u0442\u0438\u0432\u043D\u0456 \u0432\u0456\u0434\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u043D\u044F\",\n \"zh-cn\": \"\u6D3B\u52A8\u4E2D\u7684\u5305\u88F9\",\n },\n todayCount: {\n en: \"Deliveries Today\",\n de: \"Sendungen heute\",\n ru: \"\u0414\u043E\u0441\u0442\u0430\u0432\u043A\u0438 \u0441\u0435\u0433\u043E\u0434\u043D\u044F\",\n pt: \"Entregas hoje\",\n nl: \"Zendingen vandaag\",\n fr: \"Livraisons aujourd'hui\",\n it: \"Spedizioni di oggi\",\n es: \"Entregas de hoy\",\n pl: \"Dostawy dzisiaj\",\n uk: \"\u0414\u043E\u0441\u0442\u0430\u0432\u043A\u0438 \u0441\u044C\u043E\u0433\u043E\u0434\u043D\u0456\",\n \"zh-cn\": \"\u4ECA\u65E5\u9001\u8FBE\",\n },\n summaryDeliveryWindow: {\n en: \"Combined Delivery Window\",\n de: \"Kombiniertes Zustellfenster\",\n ru: \"\u041E\u0431\u044A\u0435\u0434\u0438\u043D\u0451\u043D\u043D\u043E\u0435 \u043E\u043A\u043D\u043E \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\",\n pt: \"Janela de entrega combinada\",\n nl: \"Gecombineerd bezorgvenster\",\n fr: \"Cr\u00E9neau de livraison combin\u00E9\",\n it: \"Finestra di consegna combinata\",\n es: \"Ventana de entrega combinada\",\n pl: \"\u0141\u0105czne okno dostawy\",\n uk: \"\u041E\u0431'\u0454\u0434\u043D\u0430\u043D\u0435 \u0432\u0456\u043A\u043D\u043E \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\",\n \"zh-cn\": \"\u5408\u5E76\u6D3E\u9001\u65F6\u6BB5\",\n },\n};\n\n/**\n * Translation object for a state name. Pass into `common.name`; ioBroker\n * Admin/vis/Object-Browser localizes automatically.\n *\n * @param key Translation key in {@link STATE_NAMES}.\n */\nexport function tName(key: keyof typeof STATE_NAMES): StateName {\n return STATE_NAMES[key];\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkBO,MAAM,cAAyC;AAAA;AAAA,EAEpD,SAAS;AAAA,IACP,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AAAA,EACA,QAAQ;AAAA,IACN,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AAAA,EACA,YAAY;AAAA,IACV,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AAAA,EACA,aAAa;AAAA,IACX,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AAAA,EACA,gBAAgB;AAAA,IACd,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AAAA,EACA,WAAW;AAAA,IACT,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AAAA,EACA,gBAAgB;AAAA,IACd,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AAAA,EACA,kBAAkB;AAAA,IAChB,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AAAA,EACA,WAAW;AAAA,IACT,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AAAA,EACA,cAAc;AAAA,IACZ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AAAA,EACA,aAAa;AAAA,IACX,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AAAA;AAAA,EAGA,aAAa;AAAA,IACX,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AAAA,EACA,YAAY;AAAA,IACV,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AAAA,EACA,uBAAuB;AAAA,IACrB,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AACF;AAQO,SAAS,MAAM,KAA0C;AAC9D,SAAO,YAAY,GAAG;AACxB;",
6
+ "names": []
7
+ }
@@ -32,21 +32,9 @@ __export(parcel_client_exports, {
32
32
  });
33
33
  module.exports = __toCommonJS(parcel_client_exports);
34
34
  var https = __toESM(require("node:https"));
35
+ var import_coerce = require("./coerce");
35
36
  const API_BASE = "https://api.parcel.app/external";
36
37
  const REQUEST_TIMEOUT = 15e3;
37
- function isTrueish(v) {
38
- if (typeof v === "boolean") {
39
- return v;
40
- }
41
- if (typeof v === "number") {
42
- return v === 1;
43
- }
44
- if (typeof v === "string") {
45
- const s = v.toLowerCase();
46
- return s === "true" || s === "1";
47
- }
48
- return false;
49
- }
50
38
  class ParcelClient {
51
39
  apiKey;
52
40
  carrierCache = null;
@@ -66,7 +54,7 @@ class ParcelClient {
66
54
  err.code = "API_ERROR";
67
55
  throw err;
68
56
  }
69
- if (!isTrueish(response.success)) {
57
+ if (!(0, import_coerce.isTrueish)(response.success)) {
70
58
  const rawCode = typeof response.error_code === "string" ? response.error_code : "";
71
59
  const rawMsg = typeof response.error_message === "string" ? response.error_message : "";
72
60
  const code = rawCode || rawMsg || "UNKNOWN";
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/parcel-client.ts"],
4
- "sourcesContent": ["import * as https from \"node:https\";\nimport type { ParcelApiResponse, ParcelDelivery, AddDeliveryRequest, AddDeliveryResponse, CarrierMap } from \"./types\";\n\nconst API_BASE = \"https://api.parcel.app/external\";\nconst REQUEST_TIMEOUT = 15_000;\n\n/**\n * Coerce API-drift boolean responses. parcel.app should return a real boolean\n * for `success`, but the guard accepts common string/number encodings too.\n *\n * @param v Value to interpret as a success flag\n */\nfunction isTrueish(v: unknown): boolean {\n if (typeof v === \"boolean\") {\n return v;\n }\n if (typeof v === \"number\") {\n return v === 1;\n }\n if (typeof v === \"string\") {\n const s = v.toLowerCase();\n return s === \"true\" || s === \"1\";\n }\n return false;\n}\n\n/** HTTP client for the parcel.app API */\nexport class ParcelClient {\n private apiKey: string;\n private carrierCache: CarrierMap | null = null;\n\n /** @param apiKey The parcel.app API key */\n constructor(apiKey: string) {\n this.apiKey = apiKey;\n }\n\n /**\n * Fetch deliveries from parcel.app.\n *\n * @param filterMode Filter active or recent deliveries\n */\n async getDeliveries(filterMode: \"active\" | \"recent\" = \"active\"): Promise<ParcelDelivery[]> {\n const response = await this.request<ParcelApiResponse>(\"GET\", `/deliveries/?filter_mode=${filterMode}`, true);\n\n // API-drift guard: response may be null or a non-object\n if (!response || typeof response !== \"object\") {\n const err = new Error(\"API error: malformed response\") as Error & {\n code: string;\n };\n err.code = \"API_ERROR\";\n throw err;\n }\n\n if (!isTrueish(response.success)) {\n const rawCode = typeof response.error_code === \"string\" ? response.error_code : \"\";\n const rawMsg = typeof response.error_message === \"string\" ? response.error_message : \"\";\n const code = rawCode || rawMsg || \"UNKNOWN\";\n const err = new Error(`API error: ${rawMsg || code}`) as Error & {\n code: string;\n };\n err.code = rawCode === \"INVALID_API_KEY\" ? \"INVALID_API_KEY\" : \"API_ERROR\";\n throw err;\n }\n\n // API-drift guard: deliveries must be an array\n return Array.isArray(response.deliveries) ? response.deliveries : [];\n }\n\n /**\n * Add a new delivery to parcel.app.\n *\n * @param delivery The delivery to add\n */\n async addDelivery(delivery: AddDeliveryRequest): Promise<AddDeliveryResponse> {\n return this.request<AddDeliveryResponse>(\"POST\", \"/add-delivery/\", true, delivery);\n }\n\n /** Get carrier names (cached after first call) */\n async getCarrierNames(): Promise<CarrierMap> {\n if (this.carrierCache) {\n return this.carrierCache;\n }\n\n try {\n const raw = await this.request<unknown>(\"GET\", \"/supported_carriers.json\", false);\n // API-drift guard: must be a plain object (not null, array, or primitive)\n if (raw && typeof raw === \"object\" && !Array.isArray(raw)) {\n this.carrierCache = raw as CarrierMap;\n } else {\n return {};\n }\n } catch {\n // Return empty map but don't cache it \u2014 allow retry next time\n return {};\n }\n\n return this.carrierCache;\n }\n\n /**\n * Resolve a carrier code to a display name.\n *\n * @param carrierCode The carrier code from API\n */\n async getCarrierName(carrierCode: unknown): Promise<string> {\n // API-drift guard: non-string codes fall back to \"UNKNOWN\"\n if (typeof carrierCode !== \"string\" || carrierCode.length === 0) {\n return \"UNKNOWN\";\n }\n const carriers = await this.getCarrierNames();\n const mapped = carriers[carrierCode];\n return typeof mapped === \"string\" && mapped.length > 0 ? mapped : carrierCode.toUpperCase();\n }\n\n /** Test if the API key is valid */\n async testConnection(): Promise<{ success: boolean; message: string }> {\n try {\n await this.getDeliveries(\"active\");\n return { success: true, message: \"Connection successful\" };\n } catch (err) {\n const error = err as Error & { code?: string };\n if (error.code === \"INVALID_API_KEY\") {\n return { success: false, message: \"Invalid API key\" };\n }\n return { success: false, message: error.message };\n }\n }\n\n /**\n * Execute an HTTP request against the parcel.app API.\n *\n * @param method HTTP method\n * @param path API path\n * @param authenticated Whether to send the API key\n * @param body Optional request body\n */\n private request<T>(method: string, path: string, authenticated: boolean, body?: unknown): Promise<T> {\n return new Promise((resolve, reject) => {\n const url = new URL(`${API_BASE}${path}`);\n\n const headers: Record<string, string> = {};\n if (authenticated) {\n headers[\"api-key\"] = this.apiKey;\n }\n if (body) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n const options: https.RequestOptions = {\n hostname: url.hostname,\n port: url.port || 443,\n path: url.pathname + url.search,\n method,\n headers,\n timeout: REQUEST_TIMEOUT,\n };\n\n const req = https.request(options, res => {\n const chunks: Buffer[] = [];\n\n res.on(\"error\", err => reject(err));\n res.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n res.on(\"end\", () => {\n const raw = Buffer.concat(chunks).toString(\"utf-8\");\n\n if (res.statusCode && (res.statusCode < 200 || res.statusCode >= 300)) {\n if (res.statusCode === 429) {\n const retryAfter = parseInt(res.headers[\"retry-after\"] || \"\", 10);\n const err = new Error(\"Rate limit exceeded\") as Error & {\n code: string;\n retryAfterSeconds: number;\n };\n err.code = \"RATE_LIMITED\";\n // Use Retry-After header or default to 5 minutes\n err.retryAfterSeconds = retryAfter > 0 ? retryAfter : 5 * 60;\n reject(err);\n return;\n }\n const err = new Error(`HTTP ${res.statusCode}: ${res.statusMessage}`) as Error & { code: string };\n err.code = res.statusCode === 401 || res.statusCode === 403 ? \"INVALID_API_KEY\" : \"HTTP_ERROR\";\n reject(err);\n return;\n }\n\n try {\n resolve(JSON.parse(raw) as T);\n } catch {\n reject(new Error(`JSON parse error: ${raw.substring(0, 200)}`));\n }\n });\n });\n\n req.on(\"timeout\", () => {\n req.destroy();\n reject(new Error(\"Request timeout\"));\n });\n\n req.on(\"error\", err => reject(err));\n\n if (body) {\n req.write(JSON.stringify(body));\n }\n req.end();\n });\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import * as https from \"node:https\";\nimport { isTrueish } from \"./coerce\";\nimport type { ParcelApiResponse, ParcelDelivery, AddDeliveryRequest, AddDeliveryResponse, CarrierMap } from \"./types\";\n\nconst API_BASE = \"https://api.parcel.app/external\";\nconst REQUEST_TIMEOUT = 15_000;\n\n/** HTTP client for the parcel.app API */\nexport class ParcelClient {\n private apiKey: string;\n private carrierCache: CarrierMap | null = null;\n\n /** @param apiKey The parcel.app API key */\n constructor(apiKey: string) {\n this.apiKey = apiKey;\n }\n\n /**\n * Fetch deliveries from parcel.app.\n *\n * @param filterMode Filter active or recent deliveries\n */\n async getDeliveries(filterMode: \"active\" | \"recent\" = \"active\"): Promise<ParcelDelivery[]> {\n const response = await this.request<ParcelApiResponse>(\"GET\", `/deliveries/?filter_mode=${filterMode}`, true);\n\n // API-drift guard: response may be null or a non-object\n if (!response || typeof response !== \"object\") {\n const err = new Error(\"API error: malformed response\") as Error & {\n code: string;\n };\n err.code = \"API_ERROR\";\n throw err;\n }\n\n if (!isTrueish(response.success)) {\n const rawCode = typeof response.error_code === \"string\" ? response.error_code : \"\";\n const rawMsg = typeof response.error_message === \"string\" ? response.error_message : \"\";\n const code = rawCode || rawMsg || \"UNKNOWN\";\n const err = new Error(`API error: ${rawMsg || code}`) as Error & {\n code: string;\n };\n err.code = rawCode === \"INVALID_API_KEY\" ? \"INVALID_API_KEY\" : \"API_ERROR\";\n throw err;\n }\n\n // API-drift guard: deliveries must be an array\n return Array.isArray(response.deliveries) ? response.deliveries : [];\n }\n\n /**\n * Add a new delivery to parcel.app.\n *\n * @param delivery The delivery to add\n */\n async addDelivery(delivery: AddDeliveryRequest): Promise<AddDeliveryResponse> {\n return this.request<AddDeliveryResponse>(\"POST\", \"/add-delivery/\", true, delivery);\n }\n\n /** Get carrier names (cached after first call) */\n async getCarrierNames(): Promise<CarrierMap> {\n if (this.carrierCache) {\n return this.carrierCache;\n }\n\n try {\n const raw = await this.request<unknown>(\"GET\", \"/supported_carriers.json\", false);\n // API-drift guard: must be a plain object (not null, array, or primitive)\n if (raw && typeof raw === \"object\" && !Array.isArray(raw)) {\n this.carrierCache = raw as CarrierMap;\n } else {\n return {};\n }\n } catch {\n // Return empty map but don't cache it \u2014 allow retry next time\n return {};\n }\n\n return this.carrierCache;\n }\n\n /**\n * Resolve a carrier code to a display name.\n *\n * @param carrierCode The carrier code from API\n */\n async getCarrierName(carrierCode: unknown): Promise<string> {\n // API-drift guard: non-string codes fall back to \"UNKNOWN\"\n if (typeof carrierCode !== \"string\" || carrierCode.length === 0) {\n return \"UNKNOWN\";\n }\n const carriers = await this.getCarrierNames();\n const mapped = carriers[carrierCode];\n return typeof mapped === \"string\" && mapped.length > 0 ? mapped : carrierCode.toUpperCase();\n }\n\n /** Test if the API key is valid */\n async testConnection(): Promise<{ success: boolean; message: string }> {\n try {\n await this.getDeliveries(\"active\");\n return { success: true, message: \"Connection successful\" };\n } catch (err) {\n const error = err as Error & { code?: string };\n if (error.code === \"INVALID_API_KEY\") {\n return { success: false, message: \"Invalid API key\" };\n }\n return { success: false, message: error.message };\n }\n }\n\n /**\n * Execute an HTTP request against the parcel.app API.\n *\n * @param method HTTP method\n * @param path API path\n * @param authenticated Whether to send the API key\n * @param body Optional request body\n */\n private request<T>(method: string, path: string, authenticated: boolean, body?: unknown): Promise<T> {\n return new Promise((resolve, reject) => {\n const url = new URL(`${API_BASE}${path}`);\n\n const headers: Record<string, string> = {};\n if (authenticated) {\n headers[\"api-key\"] = this.apiKey;\n }\n if (body) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n const options: https.RequestOptions = {\n hostname: url.hostname,\n port: url.port || 443,\n path: url.pathname + url.search,\n method,\n headers,\n timeout: REQUEST_TIMEOUT,\n };\n\n const req = https.request(options, res => {\n const chunks: Buffer[] = [];\n\n res.on(\"error\", err => reject(err));\n res.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n res.on(\"end\", () => {\n const raw = Buffer.concat(chunks).toString(\"utf-8\");\n\n if (res.statusCode && (res.statusCode < 200 || res.statusCode >= 300)) {\n if (res.statusCode === 429) {\n const retryAfter = parseInt(res.headers[\"retry-after\"] || \"\", 10);\n const err = new Error(\"Rate limit exceeded\") as Error & {\n code: string;\n retryAfterSeconds: number;\n };\n err.code = \"RATE_LIMITED\";\n // Use Retry-After header or default to 5 minutes\n err.retryAfterSeconds = retryAfter > 0 ? retryAfter : 5 * 60;\n reject(err);\n return;\n }\n const err = new Error(`HTTP ${res.statusCode}: ${res.statusMessage}`) as Error & { code: string };\n err.code = res.statusCode === 401 || res.statusCode === 403 ? \"INVALID_API_KEY\" : \"HTTP_ERROR\";\n reject(err);\n return;\n }\n\n try {\n resolve(JSON.parse(raw) as T);\n } catch {\n reject(new Error(`JSON parse error: ${raw.substring(0, 200)}`));\n }\n });\n });\n\n req.on(\"timeout\", () => {\n req.destroy();\n reject(new Error(\"Request timeout\"));\n });\n\n req.on(\"error\", err => reject(err));\n\n if (body) {\n req.write(JSON.stringify(body));\n }\n req.end();\n });\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAAuB;AACvB,oBAA0B;AAG1B,MAAM,WAAW;AACjB,MAAM,kBAAkB;AAGjB,MAAM,aAAa;AAAA,EAChB;AAAA,EACA,eAAkC;AAAA;AAAA,EAG1C,YAAY,QAAgB;AAC1B,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,cAAc,aAAkC,UAAqC;AACzF,UAAM,WAAW,MAAM,KAAK,QAA2B,OAAO,4BAA4B,UAAU,IAAI,IAAI;AAG5G,QAAI,CAAC,YAAY,OAAO,aAAa,UAAU;AAC7C,YAAM,MAAM,IAAI,MAAM,+BAA+B;AAGrD,UAAI,OAAO;AACX,YAAM;AAAA,IACR;AAEA,QAAI,KAAC,yBAAU,SAAS,OAAO,GAAG;AAChC,YAAM,UAAU,OAAO,SAAS,eAAe,WAAW,SAAS,aAAa;AAChF,YAAM,SAAS,OAAO,SAAS,kBAAkB,WAAW,SAAS,gBAAgB;AACrF,YAAM,OAAO,WAAW,UAAU;AAClC,YAAM,MAAM,IAAI,MAAM,cAAc,UAAU,IAAI,EAAE;AAGpD,UAAI,OAAO,YAAY,oBAAoB,oBAAoB;AAC/D,YAAM;AAAA,IACR;AAGA,WAAO,MAAM,QAAQ,SAAS,UAAU,IAAI,SAAS,aAAa,CAAC;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,YAAY,UAA4D;AAC5E,WAAO,KAAK,QAA6B,QAAQ,kBAAkB,MAAM,QAAQ;AAAA,EACnF;AAAA;AAAA,EAGA,MAAM,kBAAuC;AAC3C,QAAI,KAAK,cAAc;AACrB,aAAO,KAAK;AAAA,IACd;AAEA,QAAI;AACF,YAAM,MAAM,MAAM,KAAK,QAAiB,OAAO,4BAA4B,KAAK;AAEhF,UAAI,OAAO,OAAO,QAAQ,YAAY,CAAC,MAAM,QAAQ,GAAG,GAAG;AACzD,aAAK,eAAe;AAAA,MACtB,OAAO;AACL,eAAO,CAAC;AAAA,MACV;AAAA,IACF,QAAQ;AAEN,aAAO,CAAC;AAAA,IACV;AAEA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,eAAe,aAAuC;AAE1D,QAAI,OAAO,gBAAgB,YAAY,YAAY,WAAW,GAAG;AAC/D,aAAO;AAAA,IACT;AACA,UAAM,WAAW,MAAM,KAAK,gBAAgB;AAC5C,UAAM,SAAS,SAAS,WAAW;AACnC,WAAO,OAAO,WAAW,YAAY,OAAO,SAAS,IAAI,SAAS,YAAY,YAAY;AAAA,EAC5F;AAAA;AAAA,EAGA,MAAM,iBAAiE;AACrE,QAAI;AACF,YAAM,KAAK,cAAc,QAAQ;AACjC,aAAO,EAAE,SAAS,MAAM,SAAS,wBAAwB;AAAA,IAC3D,SAAS,KAAK;AACZ,YAAM,QAAQ;AACd,UAAI,MAAM,SAAS,mBAAmB;AACpC,eAAO,EAAE,SAAS,OAAO,SAAS,kBAAkB;AAAA,MACtD;AACA,aAAO,EAAE,SAAS,OAAO,SAAS,MAAM,QAAQ;AAAA,IAClD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,QAAW,QAAgB,MAAc,eAAwB,MAA4B;AACnG,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,YAAM,MAAM,IAAI,IAAI,GAAG,QAAQ,GAAG,IAAI,EAAE;AAExC,YAAM,UAAkC,CAAC;AACzC,UAAI,eAAe;AACjB,gBAAQ,SAAS,IAAI,KAAK;AAAA,MAC5B;AACA,UAAI,MAAM;AACR,gBAAQ,cAAc,IAAI;AAAA,MAC5B;AAEA,YAAM,UAAgC;AAAA,QACpC,UAAU,IAAI;AAAA,QACd,MAAM,IAAI,QAAQ;AAAA,QAClB,MAAM,IAAI,WAAW,IAAI;AAAA,QACzB;AAAA,QACA;AAAA,QACA,SAAS;AAAA,MACX;AAEA,YAAM,MAAM,MAAM,QAAQ,SAAS,SAAO;AACxC,cAAM,SAAmB,CAAC;AAE1B,YAAI,GAAG,SAAS,SAAO,OAAO,GAAG,CAAC;AAClC,YAAI,GAAG,QAAQ,CAAC,UAAkB,OAAO,KAAK,KAAK,CAAC;AACpD,YAAI,GAAG,OAAO,MAAM;AAClB,gBAAM,MAAM,OAAO,OAAO,MAAM,EAAE,SAAS,OAAO;AAElD,cAAI,IAAI,eAAe,IAAI,aAAa,OAAO,IAAI,cAAc,MAAM;AACrE,gBAAI,IAAI,eAAe,KAAK;AAC1B,oBAAM,aAAa,SAAS,IAAI,QAAQ,aAAa,KAAK,IAAI,EAAE;AAChE,oBAAMA,OAAM,IAAI,MAAM,qBAAqB;AAI3C,cAAAA,KAAI,OAAO;AAEX,cAAAA,KAAI,oBAAoB,aAAa,IAAI,aAAa,IAAI;AAC1D,qBAAOA,IAAG;AACV;AAAA,YACF;AACA,kBAAM,MAAM,IAAI,MAAM,QAAQ,IAAI,UAAU,KAAK,IAAI,aAAa,EAAE;AACpE,gBAAI,OAAO,IAAI,eAAe,OAAO,IAAI,eAAe,MAAM,oBAAoB;AAClF,mBAAO,GAAG;AACV;AAAA,UACF;AAEA,cAAI;AACF,oBAAQ,KAAK,MAAM,GAAG,CAAM;AAAA,UAC9B,QAAQ;AACN,mBAAO,IAAI,MAAM,qBAAqB,IAAI,UAAU,GAAG,GAAG,CAAC,EAAE,CAAC;AAAA,UAChE;AAAA,QACF,CAAC;AAAA,MACH,CAAC;AAED,UAAI,GAAG,WAAW,MAAM;AACtB,YAAI,QAAQ;AACZ,eAAO,IAAI,MAAM,iBAAiB,CAAC;AAAA,MACrC,CAAC;AAED,UAAI,GAAG,SAAS,SAAO,OAAO,GAAG,CAAC;AAElC,UAAI,MAAM;AACR,YAAI,MAAM,KAAK,UAAU,IAAI,CAAC;AAAA,MAChC;AACA,UAAI,IAAI;AAAA,IACV,CAAC;AAAA,EACH;AACF;",
6
6
  "names": ["err"]
7
7
  }
@@ -22,17 +22,12 @@ __export(state_manager_exports, {
22
22
  resolveLanguage: () => resolveLanguage
23
23
  });
24
24
  module.exports = __toCommonJS(state_manager_exports);
25
+ var import_coerce = require("./coerce");
26
+ var import_i18n_states = require("./i18n-states");
25
27
  var import_types = require("./types");
26
28
  const TRACKABLE_STATUSES = /* @__PURE__ */ new Set([2, 4, 8]);
27
- function coerceNumber(v) {
28
- if (typeof v === "number" && Number.isFinite(v)) {
29
- return v;
30
- }
31
- if (typeof v === "string" && v.length > 0) {
32
- const n = parseFloat(v);
33
- return Number.isFinite(n) ? n : null;
34
- }
35
- return null;
29
+ function asName(name) {
30
+ return name;
36
31
  }
37
32
  const ESTIMATE_LABELS = {
38
33
  de: {
@@ -111,6 +106,14 @@ function resolveLanguage(language) {
111
106
  class StateManager {
112
107
  adapter;
113
108
  language;
109
+ /**
110
+ * Cache of state IDs that have already passed `setObjectNotExistsAsync`.
111
+ * Skips repeat DB lookups on the hot path — each poll touches ~11 states
112
+ * per delivery, and most deliveries see no schema change between polls.
113
+ * On `cleanupDeliveries`, IDs of removed packages are dropped so a re-add
114
+ * triggers a fresh creation.
115
+ */
116
+ createdIds = /* @__PURE__ */ new Set();
114
117
  /**
115
118
  * @param adapter The ioBroker adapter instance
116
119
  * @param language Language code from system.config.language (falls back to English)
@@ -183,35 +186,53 @@ class StateManager {
183
186
  const labels = import_types.STATUS_LABELS[this.language];
184
187
  const statusText = labels[statusCode] || `Unknown (${statusCode})`;
185
188
  await Promise.all([
186
- this.createAndSet(`${devicePath}.carrier`, "Carrier", "string", "text", carrierName),
187
- this.createAndSet(`${devicePath}.status`, "Status", "string", "text", statusText),
188
- this.createAndSet(`${devicePath}.statusCode`, "Status Code", "number", "value", statusCode),
189
- this.createAndSet(`${devicePath}.description`, "Description", "string", "text", description),
190
- this.createAndSet(`${devicePath}.trackingNumber`, "Tracking Number", "string", "text", trackingNumber),
191
- this.createAndSet(`${devicePath}.extraInfo`, "Extra Information", "string", "text", extraInfo),
189
+ this.createAndSet(`${devicePath}.carrier`, asName((0, import_i18n_states.tName)("carrier")), "string", "text", carrierName),
190
+ this.createAndSet(`${devicePath}.status`, asName((0, import_i18n_states.tName)("status")), "string", "text", statusText),
191
+ this.createAndSet(`${devicePath}.statusCode`, asName((0, import_i18n_states.tName)("statusCode")), "number", "value", statusCode),
192
+ this.createAndSet(`${devicePath}.description`, asName((0, import_i18n_states.tName)("description")), "string", "text", description),
193
+ this.createAndSet(
194
+ `${devicePath}.trackingNumber`,
195
+ asName((0, import_i18n_states.tName)("trackingNumber")),
196
+ "string",
197
+ "text",
198
+ trackingNumber
199
+ ),
200
+ this.createAndSet(`${devicePath}.extraInfo`, asName((0, import_i18n_states.tName)("extraInfo")), "string", "text", extraInfo),
192
201
  this.createAndSet(
193
202
  `${devicePath}.deliveryWindow`,
194
- "Delivery Window",
203
+ asName((0, import_i18n_states.tName)("deliveryWindow")),
195
204
  "string",
196
205
  "text",
197
206
  this.calculateDeliveryWindow(delivery, statusCode)
198
207
  ),
199
208
  this.createAndSet(
200
209
  `${devicePath}.deliveryEstimate`,
201
- "Delivery Estimate",
210
+ asName((0, import_i18n_states.tName)("deliveryEstimate")),
202
211
  "string",
203
212
  "text",
204
213
  this.calculateDeliveryEstimate(delivery, statusCode)
205
214
  ),
206
- this.createAndSet(`${devicePath}.lastEvent`, "Last Event", "string", "text", this.formatLastEvent(delivery)),
215
+ this.createAndSet(
216
+ `${devicePath}.lastEvent`,
217
+ asName((0, import_i18n_states.tName)("lastEvent")),
218
+ "string",
219
+ "text",
220
+ this.formatLastEvent(delivery)
221
+ ),
207
222
  this.createAndSet(
208
223
  `${devicePath}.lastLocation`,
209
- "Last Location",
224
+ asName((0, import_i18n_states.tName)("lastLocation")),
210
225
  "string",
211
226
  "text",
212
227
  this.extractLastLocation(delivery)
213
228
  ),
214
- this.createAndSet(`${devicePath}.lastUpdated`, "Last Updated", "string", "date", (/* @__PURE__ */ new Date()).toISOString())
229
+ this.createAndSet(
230
+ `${devicePath}.lastUpdated`,
231
+ asName((0, import_i18n_states.tName)("lastUpdated")),
232
+ "string",
233
+ "date",
234
+ (/* @__PURE__ */ new Date()).toISOString()
235
+ )
215
236
  ]);
216
237
  }
217
238
  /**
@@ -223,11 +244,17 @@ class StateManager {
223
244
  async updateSummary(activeDeliveries) {
224
245
  const todayDeliveries = activeDeliveries.filter((d) => this.isToday(d, this.parseStatus(d)));
225
246
  await Promise.all([
226
- this.createAndSet("summary.activeCount", "Active Deliveries", "number", "value", activeDeliveries.length),
227
- this.createAndSet("summary.todayCount", "Deliveries Today", "number", "value", todayDeliveries.length),
247
+ this.createAndSet(
248
+ "summary.activeCount",
249
+ asName((0, import_i18n_states.tName)("activeCount")),
250
+ "number",
251
+ "value",
252
+ activeDeliveries.length
253
+ ),
254
+ this.createAndSet("summary.todayCount", asName((0, import_i18n_states.tName)("todayCount")), "number", "value", todayDeliveries.length),
228
255
  this.createAndSet(
229
256
  "summary.deliveryWindow",
230
- "Combined Delivery Window",
257
+ asName((0, import_i18n_states.tName)("summaryDeliveryWindow")),
231
258
  "string",
232
259
  "text",
233
260
  this.calculateCombinedWindow(todayDeliveries)
@@ -250,6 +277,11 @@ class StateManager {
250
277
  if (relativeId.startsWith("deliveries.") && !activeSet.has(relativeId)) {
251
278
  await this.adapter.delObjectAsync(relativeId, { recursive: true });
252
279
  this.adapter.log.debug(`Removed stale delivery: ${relativeId}`);
280
+ for (const id of this.createdIds) {
281
+ if (id === relativeId || id.startsWith(`${relativeId}.`)) {
282
+ this.createdIds.delete(id);
283
+ }
284
+ }
253
285
  }
254
286
  }
255
287
  }
@@ -264,7 +296,7 @@ class StateManager {
264
296
  return "";
265
297
  }
266
298
  const formatTime = (timestamp) => {
267
- const ts = coerceNumber(timestamp);
299
+ const ts = (0, import_coerce.coerceFiniteNumber)(timestamp);
268
300
  if (ts === null || ts <= 0) {
269
301
  return null;
270
302
  }
@@ -293,7 +325,7 @@ class StateManager {
293
325
  return null;
294
326
  }
295
327
  let expectedDate = null;
296
- const ts = coerceNumber(delivery.timestamp_expected);
328
+ const ts = (0, import_coerce.coerceFiniteNumber)(delivery.timestamp_expected);
297
329
  if (ts !== null && ts > 0) {
298
330
  expectedDate = new Date(ts * 1e3);
299
331
  } else if (typeof delivery.date_expected === "string" && delivery.date_expected.length > 0) {
@@ -404,20 +436,25 @@ class StateManager {
404
436
  return `${times[0].start} - ${times[times.length - 1].end}`;
405
437
  }
406
438
  /**
407
- * Create/extend a read-only state and set its value.
439
+ * Create/extend a read-only state and set its value. Skips the
440
+ * `setObjectNotExistsAsync` round-trip once the ID is in the cache —
441
+ * states are static after first creation; only the value changes per poll.
408
442
  *
409
443
  * @param id State ID relative to adapter namespace
410
- * @param name Display name
444
+ * @param name Display name (translation object or plain string)
411
445
  * @param type Value type
412
446
  * @param role ioBroker role
413
447
  * @param val Value to set
414
448
  */
415
449
  async createAndSet(id, name, type, role, val) {
416
- await this.adapter.setObjectNotExistsAsync(id, {
417
- type: "state",
418
- common: { name, type, role, read: true, write: false },
419
- native: {}
420
- });
450
+ if (!this.createdIds.has(id)) {
451
+ await this.adapter.setObjectNotExistsAsync(id, {
452
+ type: "state",
453
+ common: { name, type, role, read: true, write: false },
454
+ native: {}
455
+ });
456
+ this.createdIds.add(id);
457
+ }
421
458
  await this.adapter.setStateAsync(id, { val, ack: true });
422
459
  }
423
460
  }