iobroker.parcelapp 0.2.14 → 0.2.16

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 CHANGED
@@ -32,7 +32,7 @@ ioBroker adapter that connects to the [parcel.app](https://parcelapp.net) API an
32
32
  ## Requirements
33
33
 
34
34
  - **Node.js >= 20**
35
- - **ioBroker js-controller >= 7.0.0**
35
+ - **ioBroker js-controller >= 6.0.11**
36
36
  - **ioBroker Admin >= 7.6.20**
37
37
  - **parcel.app Premium subscription** — required for API access
38
38
 
@@ -115,6 +115,16 @@ The delivery is added to your parcel.app account and immediately appears in ioBr
115
115
  ---
116
116
 
117
117
  ## Changelog
118
+ ### 0.2.16 (2026-04-26)
119
+ - Min js-controller correction: was incorrectly bumped to `>=7.0.23` in 0.2.15 (Wert kam aus Recherche-Synthese, nicht aus Repochecker-Source). Repochecker-recommended value is `>=6.0.11` — restored.
120
+
121
+ ### 0.2.15 (2026-04-26)
122
+ - Process-level `unhandledRejection` / `uncaughtException` handlers added as last-line-of-defence against fire-and-forget rejections.
123
+ - Stop shipping the `manual-review` release-script plugin — adapter-only consequence.
124
+ - Bump min js-controller to `>=7.0.23` (matches latest-repo recommendation).
125
+ - Audit-driven boilerplate sync with the other krobi adapters (`.vscode` json5 schemas, `tsconfig.test` looser test rules).
126
+ - README footer-link to `CHANGELOG_OLD.md` restored, `CHANGELOG_OLD.md` cleaned up to consistent compact style.
127
+
118
128
  ### 0.2.14 (2026-04-23)
119
129
  - Separate test-build output (`build-test/`) from production `build/`, no more duplicated `build/src` + `build/test` tree in published packages.
120
130
  - Declare `deliveries` folder and `summary` channel as instance objects so their parent exists before per-package states appear.
@@ -128,18 +138,6 @@ The delivery is added to your parcel.app account and immediately appears in ioBr
128
138
  - Harden API-drift guards in `ParcelClient` and `StateManager` (non-boolean `success`, non-array `deliveries`, non-string `error_code`/`error_message`, non-object carrier map, non-string delivery fields, numeric/string `status_code`, numeric-string `timestamp_expected`, malformed `events`)
129
139
  - Add 38 regression tests (128 total) covering the new drift paths
130
140
 
131
- ### 0.2.11 (2026-04-12)
132
- - Fix: handle response stream errors (prevents unhandled exceptions on connection drop)
133
- - Fix: isolate per-delivery poll failures (one broken delivery no longer blocks all others)
134
- - Fix: harden onMessage with try/catch and callback guard
135
- - Fix: onUnload try/catch prevents adapter hang on shutdown
136
- - DRY: parseStatus helper eliminates repeated parseInt calls
137
- - Simplify obsolete state cleanup, use setObjectNotExistsAsync for states
138
-
139
- ### 0.2.10 (2026-04-12)
140
- - Fix test timezone bug, remove unused devDependencies, add `no-floating-promises` lint rule
141
- - Remove redundant `actions/checkout` from CI workflow
142
-
143
141
  ## Support
144
142
 
145
143
  - [ioBroker Forum](https://forum.iobroker.net/)
package/build/main.js CHANGED
@@ -40,6 +40,8 @@ class ParcelappAdapter extends utils.Adapter {
40
40
  rateLimitedUntil = 0;
41
41
  lastErrorCode = "";
42
42
  failedDeliveries = /* @__PURE__ */ new Set();
43
+ unhandledRejectionHandler = null;
44
+ uncaughtExceptionHandler = null;
43
45
  /** @param options Adapter options */
44
46
  constructor(options = {}) {
45
47
  super({
@@ -57,6 +59,14 @@ class ParcelappAdapter extends utils.Adapter {
57
59
  (err) => this.log.error(`onMessage failed: ${errText(err)}`)
58
60
  );
59
61
  });
62
+ this.unhandledRejectionHandler = (reason) => {
63
+ this.log.error(`Unhandled rejection: ${errText(reason)}`);
64
+ };
65
+ this.uncaughtExceptionHandler = (err) => {
66
+ this.log.error(`Uncaught exception: ${errText(err)}`);
67
+ };
68
+ process.on("unhandledRejection", this.unhandledRejectionHandler);
69
+ process.on("uncaughtException", this.uncaughtExceptionHandler);
60
70
  }
61
71
  async onReady() {
62
72
  var _a, _b, _c;
@@ -93,6 +103,14 @@ class ParcelappAdapter extends utils.Adapter {
93
103
  this.clearInterval(this.pollTimer);
94
104
  this.pollTimer = void 0;
95
105
  }
106
+ if (this.unhandledRejectionHandler) {
107
+ process.off("unhandledRejection", this.unhandledRejectionHandler);
108
+ this.unhandledRejectionHandler = null;
109
+ }
110
+ if (this.uncaughtExceptionHandler) {
111
+ process.off("uncaughtException", this.uncaughtExceptionHandler);
112
+ this.uncaughtExceptionHandler = null;
113
+ }
96
114
  void this.setState("info.connection", { val: false, ack: true });
97
115
  } catch {
98
116
  }
package/build/main.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/main.ts"],
4
- "sourcesContent": ["import * as utils from \"@iobroker/adapter-core\";\nimport { ParcelClient } from \"./lib/parcel-client\";\nimport { StateManager } from \"./lib/state-manager\";\n\nconst MIN_POLL_INTERVAL = 5;\nconst MAX_POLL_INTERVAL = 60;\nconst DEFAULT_POLL_INTERVAL = 10;\nconst MIN_POLL_GAP_MS = 60_000; // Minimum 60s between polls\n\n/**\n * Extract a log-friendly message from an unknown error value.\n *\n * @param err Value caught in a promise rejection (may or may not be an Error)\n */\nfunction errText(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/** ioBroker adapter for parcel.app package tracking */\nclass ParcelappAdapter extends utils.Adapter {\n private client: ParcelClient | null = null;\n private stateManager: StateManager | null = null;\n private pollTimer: ioBroker.Interval | undefined = undefined;\n private isPolling = false;\n private lastPollTime = 0;\n private rateLimitedUntil = 0;\n private lastErrorCode = \"\";\n private failedDeliveries = new Set<string>();\n\n /** @param options Adapter options */\n public constructor(options: Partial<utils.AdapterOptions> = {}) {\n super({\n ...options,\n name: \"parcelapp\",\n });\n // Wrap async handlers with .catch() so a rejection can never become an\n // unhandled promise rejection (which would SIGKILL the adapter and trap\n // js-controller in a restart loop without any stack trace).\n this.on(\"ready\", () => {\n this.onReady().catch((err) =>\n this.log.error(`onReady failed: ${errText(err)}`),\n );\n });\n this.on(\"unload\", this.onUnload.bind(this));\n this.on(\"message\", (obj) => {\n this.onMessage(obj).catch((err) =>\n this.log.error(`onMessage failed: ${errText(err)}`),\n );\n });\n }\n\n private async onReady(): Promise<void> {\n await this.setStateAsync(\"info.connection\", { val: false, ack: true });\n\n // Validate config\n const { apiKey } = this.config;\n if (!apiKey || apiKey.trim().length < 10) {\n this.log.error(\n \"No valid API key configured \u2014 please enter your parcel.app API key in the adapter settings\",\n );\n return;\n }\n\n // Pick the label language from the ioBroker system configuration.\n // StateManager falls back to English if the language is unsupported.\n const sysConfig = await this.getForeignObjectAsync(\"system.config\");\n const language =\n (sysConfig?.common as { language?: string } | undefined)?.language ?? \"\";\n\n // Initialize\n this.client = new ParcelClient(apiKey.trim());\n this.stateManager = new StateManager(this, language);\n\n // Cleanup obsolete states\n await this.cleanupObsoleteStates();\n\n // Initial poll\n await this.poll();\n\n // Set up recurring poll\n const interval = Math.max(\n MIN_POLL_INTERVAL,\n Math.min(\n MAX_POLL_INTERVAL,\n this.config.pollInterval ?? DEFAULT_POLL_INTERVAL,\n ),\n );\n const intervalMs = interval * 60 * 1000;\n this.pollTimer = this.setInterval(() => void this.poll(), intervalMs);\n\n this.log.info(\n `Parcel tracking started \u2014 polling every ${interval} minutes`,\n );\n }\n\n private onUnload(callback: () => void): void {\n try {\n if (this.pollTimer) {\n this.clearInterval(this.pollTimer);\n this.pollTimer = undefined;\n }\n void this.setState(\"info.connection\", { val: false, ack: true });\n } catch {\n // ignore\n }\n callback();\n }\n\n private async onMessage(obj: ioBroker.Message): Promise<void> {\n if (!obj?.command || !obj.callback) {\n return;\n }\n\n try {\n switch (obj.command) {\n case \"checkConnection\": {\n const msg = obj.message as { apiKey?: string };\n const key = msg?.apiKey?.trim() || \"\";\n if (!key || key.length < 10) {\n this.sendTo(\n obj.from,\n obj.command,\n { success: false, message: \"API key is too short\" },\n obj.callback,\n );\n return;\n }\n const testClient = new ParcelClient(key);\n const result = await testClient.testConnection();\n this.sendTo(obj.from, obj.command, result, obj.callback);\n break;\n }\n case \"addDelivery\": {\n if (!this.client) {\n this.sendTo(\n obj.from,\n obj.command,\n { success: false, error_message: \"Adapter not initialized\" },\n obj.callback,\n );\n return;\n }\n const request = obj.message as {\n tracking_number: string;\n carrier_code: string;\n description: string;\n };\n const addResult = await this.client.addDelivery(request);\n this.sendTo(obj.from, obj.command, addResult, obj.callback);\n if (addResult.success) {\n void this.poll();\n }\n break;\n }\n default:\n this.sendTo(\n obj.from,\n obj.command,\n { error: \"Unknown command\" },\n obj.callback,\n );\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n this.sendTo(\n obj.from,\n obj.command,\n { success: false, error_message: msg },\n obj.callback,\n );\n }\n }\n\n private async cleanupObsoleteStates(): Promise<void> {\n const obsoleteStates = [\n \"summary.json\", // removed in 0.2.0\n ];\n for (const stateId of obsoleteStates) {\n const obj = await this.getObjectAsync(stateId);\n if (obj) {\n await this.delObjectAsync(stateId);\n this.log.debug(`Removed obsolete state: ${stateId}`);\n }\n }\n }\n\n /**\n * Classify an error for deduplication and log-level decisions.\n *\n * @param error The error to classify\n */\n private classifyError(error: Error & { code?: string }): string {\n if (error.code === \"RATE_LIMITED\") {\n return \"RATE_LIMITED\";\n }\n if (error.code === \"INVALID_API_KEY\") {\n return \"INVALID_API_KEY\";\n }\n // Network errors: DNS, connection refused, no internet\n if (\n error.code === \"ENOTFOUND\" ||\n error.code === \"ECONNREFUSED\" ||\n error.code === \"ECONNRESET\" ||\n error.code === \"ENETUNREACH\" ||\n error.code === \"EHOSTUNREACH\" ||\n error.code === \"EAI_AGAIN\"\n ) {\n return \"NETWORK\";\n }\n if (error.message.includes(\"timeout\") || error.code === \"ETIMEDOUT\") {\n return \"TIMEOUT\";\n }\n return error.code || \"UNKNOWN\";\n }\n\n private async poll(): Promise<void> {\n if (this.isPolling || !this.client || !this.stateManager) {\n return;\n }\n\n const now = Date.now();\n\n // Skip if rate limited\n if (now < this.rateLimitedUntil) {\n const waitMin = Math.ceil((this.rateLimitedUntil - now) / 60_000);\n this.log.debug(\n `Skipping poll \u2014 rate limited for ${waitMin} more minute(s)`,\n );\n return;\n }\n\n // Throttle: minimum gap between polls\n if (now - this.lastPollTime < MIN_POLL_GAP_MS) {\n this.log.debug(\"Skipping poll \u2014 too soon after last poll\");\n return;\n }\n\n this.isPolling = true;\n this.lastPollTime = now;\n try {\n // When keeping delivered packages, use \"recent\" to get them from API\n const autoRemove = this.config.autoRemoveDelivered !== false;\n const deliveries = await this.client.getDeliveries(\n autoRemove ? \"active\" : \"recent\",\n );\n\n // Reset error state on success\n this.rateLimitedUntil = 0;\n if (this.lastErrorCode) {\n this.log.info(\"Connection restored\");\n this.lastErrorCode = \"\";\n }\n await this.setStateAsync(\"info.connection\", { val: true, ack: true });\n\n // Split into active (non-delivered) and visible (what gets states)\n const activeDeliveries = deliveries.filter(\n (d) => this.stateManager!.parseStatus(d) !== 0,\n );\n const visibleDeliveries = autoRemove ? activeDeliveries : deliveries;\n\n // Update each delivery (isolated: one failure must not block others)\n const activeIds: string[] = [];\n for (const delivery of visibleDeliveries) {\n try {\n const carrierName = await this.client.getCarrierName(\n delivery.carrier_code,\n );\n await this.stateManager.updateDelivery(delivery, carrierName);\n activeIds.push(this.stateManager.packageId(delivery));\n this.failedDeliveries.delete(delivery.tracking_number);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (this.failedDeliveries.has(delivery.tracking_number)) {\n this.log.debug(\n `Failed to update \"${delivery.tracking_number}\": ${msg}`,\n );\n } else {\n this.log.warn(\n `Failed to update \"${delivery.tracking_number}\": ${msg}`,\n );\n this.failedDeliveries.add(delivery.tracking_number);\n }\n }\n }\n\n // Cleanup stale deliveries\n await this.stateManager.cleanupDeliveries(activeIds);\n\n // Update summary (always uses active/non-delivered)\n await this.stateManager.updateSummary(activeDeliveries);\n\n this.log.debug(\n `Polled ${visibleDeliveries.length} deliveries (${activeDeliveries.length} active)`,\n );\n } catch (err) {\n const error = err as Error & {\n code?: string;\n retryAfterSeconds?: number;\n };\n\n // Classify the error\n const errorCode = this.classifyError(error);\n const isRepeat = errorCode === this.lastErrorCode;\n this.lastErrorCode = errorCode;\n\n if (error.code === \"RATE_LIMITED\") {\n const cooldownSec = error.retryAfterSeconds || 5 * 60;\n this.rateLimitedUntil = Date.now() + cooldownSec * 1000;\n this.log.warn(\n `Rate limit hit \u2014 pausing API requests for ${Math.ceil(cooldownSec / 60)} minute(s)`,\n );\n } else if (error.code === \"INVALID_API_KEY\") {\n // Always log \u2014 user must fix config\n this.log.error(\n \"Invalid API key \u2014 please check your parcel.app API key\",\n );\n } else if (isRepeat) {\n // Same error as last time \u2014 don't spam the log\n this.log.debug(`Poll failed (ongoing): ${error.message}`);\n } else if (errorCode === \"NETWORK\") {\n this.log.warn(`Cannot reach parcel.app API \u2014 will keep retrying`);\n } else if (errorCode === \"TIMEOUT\") {\n this.log.warn(`API request timeout \u2014 will retry next cycle`);\n } else {\n this.log.error(`Poll failed: ${error.message}`);\n }\n\n await this.setStateAsync(\"info.connection\", { val: false, ack: true });\n } finally {\n this.isPolling = false;\n }\n }\n}\n\nif (require.main !== module) {\n module.exports = (options: Partial<utils.AdapterOptions> | undefined) =>\n new ParcelappAdapter(options);\n} else {\n (() => new ParcelappAdapter())();\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import * as utils from \"@iobroker/adapter-core\";\nimport { ParcelClient } from \"./lib/parcel-client\";\nimport { StateManager } from \"./lib/state-manager\";\n\nconst MIN_POLL_INTERVAL = 5;\nconst MAX_POLL_INTERVAL = 60;\nconst DEFAULT_POLL_INTERVAL = 10;\nconst MIN_POLL_GAP_MS = 60_000; // Minimum 60s between polls\n\n/**\n * Extract a log-friendly message from an unknown error value.\n *\n * @param err Value caught in a promise rejection (may or may not be an Error)\n */\nfunction errText(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/** ioBroker adapter for parcel.app package tracking */\nclass ParcelappAdapter extends utils.Adapter {\n private client: ParcelClient | null = null;\n private stateManager: StateManager | null = null;\n private pollTimer: ioBroker.Interval | undefined = undefined;\n private isPolling = false;\n private lastPollTime = 0;\n private rateLimitedUntil = 0;\n private lastErrorCode = \"\";\n private failedDeliveries = new Set<string>();\n private unhandledRejectionHandler: ((reason: unknown) => void) | null = null;\n private uncaughtExceptionHandler: ((err: Error) => void) | null = null;\n\n /** @param options Adapter options */\n public constructor(options: Partial<utils.AdapterOptions> = {}) {\n super({\n ...options,\n name: \"parcelapp\",\n });\n // Wrap async handlers with .catch() so a rejection can never become an\n // unhandled promise rejection (which would SIGKILL the adapter and trap\n // js-controller in a restart loop without any stack trace).\n this.on(\"ready\", () => {\n this.onReady().catch((err) =>\n this.log.error(`onReady failed: ${errText(err)}`),\n );\n });\n this.on(\"unload\", this.onUnload.bind(this));\n this.on(\"message\", (obj) => {\n this.onMessage(obj).catch((err) =>\n this.log.error(`onMessage failed: ${errText(err)}`),\n );\n });\n // Last-line-of-defence against unhandled rejections / sync throws from\n // fire-and-forget paths (e.g. `void this.poll()`). The per-handler\n // .catch() wrappers cover the documented async paths; this catches\n // anything that slips past during refactors.\n this.unhandledRejectionHandler = (reason: unknown) => {\n this.log.error(`Unhandled rejection: ${errText(reason)}`);\n };\n this.uncaughtExceptionHandler = (err: Error) => {\n this.log.error(`Uncaught exception: ${errText(err)}`);\n };\n process.on(\"unhandledRejection\", this.unhandledRejectionHandler);\n process.on(\"uncaughtException\", this.uncaughtExceptionHandler);\n }\n\n private async onReady(): Promise<void> {\n await this.setStateAsync(\"info.connection\", { val: false, ack: true });\n\n // Validate config\n const { apiKey } = this.config;\n if (!apiKey || apiKey.trim().length < 10) {\n this.log.error(\n \"No valid API key configured \u2014 please enter your parcel.app API key in the adapter settings\",\n );\n return;\n }\n\n // Pick the label language from the ioBroker system configuration.\n // StateManager falls back to English if the language is unsupported.\n const sysConfig = await this.getForeignObjectAsync(\"system.config\");\n const language =\n (sysConfig?.common as { language?: string } | undefined)?.language ?? \"\";\n\n // Initialize\n this.client = new ParcelClient(apiKey.trim());\n this.stateManager = new StateManager(this, language);\n\n // Cleanup obsolete states\n await this.cleanupObsoleteStates();\n\n // Initial poll\n await this.poll();\n\n // Set up recurring poll\n const interval = Math.max(\n MIN_POLL_INTERVAL,\n Math.min(\n MAX_POLL_INTERVAL,\n this.config.pollInterval ?? DEFAULT_POLL_INTERVAL,\n ),\n );\n const intervalMs = interval * 60 * 1000;\n this.pollTimer = this.setInterval(() => void this.poll(), intervalMs);\n\n this.log.info(\n `Parcel tracking started \u2014 polling every ${interval} minutes`,\n );\n }\n\n private onUnload(callback: () => void): void {\n try {\n if (this.pollTimer) {\n this.clearInterval(this.pollTimer);\n this.pollTimer = undefined;\n }\n if (this.unhandledRejectionHandler) {\n process.off(\"unhandledRejection\", this.unhandledRejectionHandler);\n this.unhandledRejectionHandler = null;\n }\n if (this.uncaughtExceptionHandler) {\n process.off(\"uncaughtException\", this.uncaughtExceptionHandler);\n this.uncaughtExceptionHandler = null;\n }\n void this.setState(\"info.connection\", { val: false, ack: true });\n } catch {\n // ignore\n }\n callback();\n }\n\n private async onMessage(obj: ioBroker.Message): Promise<void> {\n if (!obj?.command || !obj.callback) {\n return;\n }\n\n try {\n switch (obj.command) {\n case \"checkConnection\": {\n const msg = obj.message as { apiKey?: string };\n const key = msg?.apiKey?.trim() || \"\";\n if (!key || key.length < 10) {\n this.sendTo(\n obj.from,\n obj.command,\n { success: false, message: \"API key is too short\" },\n obj.callback,\n );\n return;\n }\n const testClient = new ParcelClient(key);\n const result = await testClient.testConnection();\n this.sendTo(obj.from, obj.command, result, obj.callback);\n break;\n }\n case \"addDelivery\": {\n if (!this.client) {\n this.sendTo(\n obj.from,\n obj.command,\n { success: false, error_message: \"Adapter not initialized\" },\n obj.callback,\n );\n return;\n }\n const request = obj.message as {\n tracking_number: string;\n carrier_code: string;\n description: string;\n };\n const addResult = await this.client.addDelivery(request);\n this.sendTo(obj.from, obj.command, addResult, obj.callback);\n if (addResult.success) {\n void this.poll();\n }\n break;\n }\n default:\n this.sendTo(\n obj.from,\n obj.command,\n { error: \"Unknown command\" },\n obj.callback,\n );\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n this.sendTo(\n obj.from,\n obj.command,\n { success: false, error_message: msg },\n obj.callback,\n );\n }\n }\n\n private async cleanupObsoleteStates(): Promise<void> {\n const obsoleteStates = [\n \"summary.json\", // removed in 0.2.0\n ];\n for (const stateId of obsoleteStates) {\n const obj = await this.getObjectAsync(stateId);\n if (obj) {\n await this.delObjectAsync(stateId);\n this.log.debug(`Removed obsolete state: ${stateId}`);\n }\n }\n }\n\n /**\n * Classify an error for deduplication and log-level decisions.\n *\n * @param error The error to classify\n */\n private classifyError(error: Error & { code?: string }): string {\n if (error.code === \"RATE_LIMITED\") {\n return \"RATE_LIMITED\";\n }\n if (error.code === \"INVALID_API_KEY\") {\n return \"INVALID_API_KEY\";\n }\n // Network errors: DNS, connection refused, no internet\n if (\n error.code === \"ENOTFOUND\" ||\n error.code === \"ECONNREFUSED\" ||\n error.code === \"ECONNRESET\" ||\n error.code === \"ENETUNREACH\" ||\n error.code === \"EHOSTUNREACH\" ||\n error.code === \"EAI_AGAIN\"\n ) {\n return \"NETWORK\";\n }\n if (error.message.includes(\"timeout\") || error.code === \"ETIMEDOUT\") {\n return \"TIMEOUT\";\n }\n return error.code || \"UNKNOWN\";\n }\n\n private async poll(): Promise<void> {\n if (this.isPolling || !this.client || !this.stateManager) {\n return;\n }\n\n const now = Date.now();\n\n // Skip if rate limited\n if (now < this.rateLimitedUntil) {\n const waitMin = Math.ceil((this.rateLimitedUntil - now) / 60_000);\n this.log.debug(\n `Skipping poll \u2014 rate limited for ${waitMin} more minute(s)`,\n );\n return;\n }\n\n // Throttle: minimum gap between polls\n if (now - this.lastPollTime < MIN_POLL_GAP_MS) {\n this.log.debug(\"Skipping poll \u2014 too soon after last poll\");\n return;\n }\n\n this.isPolling = true;\n this.lastPollTime = now;\n try {\n // When keeping delivered packages, use \"recent\" to get them from API\n const autoRemove = this.config.autoRemoveDelivered !== false;\n const deliveries = await this.client.getDeliveries(\n autoRemove ? \"active\" : \"recent\",\n );\n\n // Reset error state on success\n this.rateLimitedUntil = 0;\n if (this.lastErrorCode) {\n this.log.info(\"Connection restored\");\n this.lastErrorCode = \"\";\n }\n await this.setStateAsync(\"info.connection\", { val: true, ack: true });\n\n // Split into active (non-delivered) and visible (what gets states)\n const activeDeliveries = deliveries.filter(\n (d) => this.stateManager!.parseStatus(d) !== 0,\n );\n const visibleDeliveries = autoRemove ? activeDeliveries : deliveries;\n\n // Update each delivery (isolated: one failure must not block others)\n const activeIds: string[] = [];\n for (const delivery of visibleDeliveries) {\n try {\n const carrierName = await this.client.getCarrierName(\n delivery.carrier_code,\n );\n await this.stateManager.updateDelivery(delivery, carrierName);\n activeIds.push(this.stateManager.packageId(delivery));\n this.failedDeliveries.delete(delivery.tracking_number);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (this.failedDeliveries.has(delivery.tracking_number)) {\n this.log.debug(\n `Failed to update \"${delivery.tracking_number}\": ${msg}`,\n );\n } else {\n this.log.warn(\n `Failed to update \"${delivery.tracking_number}\": ${msg}`,\n );\n this.failedDeliveries.add(delivery.tracking_number);\n }\n }\n }\n\n // Cleanup stale deliveries\n await this.stateManager.cleanupDeliveries(activeIds);\n\n // Update summary (always uses active/non-delivered)\n await this.stateManager.updateSummary(activeDeliveries);\n\n this.log.debug(\n `Polled ${visibleDeliveries.length} deliveries (${activeDeliveries.length} active)`,\n );\n } catch (err) {\n const error = err as Error & {\n code?: string;\n retryAfterSeconds?: number;\n };\n\n // Classify the error\n const errorCode = this.classifyError(error);\n const isRepeat = errorCode === this.lastErrorCode;\n this.lastErrorCode = errorCode;\n\n if (error.code === \"RATE_LIMITED\") {\n const cooldownSec = error.retryAfterSeconds || 5 * 60;\n this.rateLimitedUntil = Date.now() + cooldownSec * 1000;\n this.log.warn(\n `Rate limit hit \u2014 pausing API requests for ${Math.ceil(cooldownSec / 60)} minute(s)`,\n );\n } else if (error.code === \"INVALID_API_KEY\") {\n // Always log \u2014 user must fix config\n this.log.error(\n \"Invalid API key \u2014 please check your parcel.app API key\",\n );\n } else if (isRepeat) {\n // Same error as last time \u2014 don't spam the log\n this.log.debug(`Poll failed (ongoing): ${error.message}`);\n } else if (errorCode === \"NETWORK\") {\n this.log.warn(`Cannot reach parcel.app API \u2014 will keep retrying`);\n } else if (errorCode === \"TIMEOUT\") {\n this.log.warn(`API request timeout \u2014 will retry next cycle`);\n } else {\n this.log.error(`Poll failed: ${error.message}`);\n }\n\n await this.setStateAsync(\"info.connection\", { val: false, ack: true });\n } finally {\n this.isPolling = false;\n }\n }\n}\n\nif (require.main !== module) {\n module.exports = (options: Partial<utils.AdapterOptions> | undefined) =>\n new ParcelappAdapter(options);\n} else {\n (() => new ParcelappAdapter())();\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/io-package.json CHANGED
@@ -1,98 +1,98 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "parcelapp",
4
- "version": "0.2.14",
4
+ "version": "0.2.16",
5
5
  "news": {
6
+ "0.2.16": {
7
+ "en": "Min js-controller correction: was incorrectly bumped to `>=7.0.23` in 0.2.15 (Wert kam aus Recherche-Synthese, nicht aus Repochecker-Source). Repochecker-recommended value is `>=6.0.11` — restored.",
8
+ "de": "Min js-Controller-Korrektur: wurde falsch auf `>=7.0.23` in 0.2.15 (Wert kam aus Recherche-Synthese, nicht aus Repochecker-Source) gesprungen. Repochecker-recommended Wert ist `>=6.0.11` — restauriert.",
9
+ "ru": "Коррекция Min js-контроллера: в 0.2.15 она была неправильно увеличена до '>=7.0.23' (Wert kam aus Recherche-Synthese, nicht aus Repochecker-Source). Рекомендуемое значение репочекера ->=6.0.11 - восстановлено.",
10
+ "pt": "Min js-controller correção: foi incorretamente bateu para `>=7.0.23` em 0.2.15 (Wert kam aus Recherche-Syntheses, nicht aus Repochecker-Source). O valor recomendado pelo repochecker é `>=6.0.11` — restaurado.",
11
+ "nl": "Min js-controller correctie: werd foutief gestoten naar Repochecker aanbevolen waarde is .",
12
+ "fr": "La correction de min js-controller : a été incorrectement cognée à `>=7.0.23` dans le 0,2.15 (Wert kam aus Recherche-Synthese, nicht aus Repochecker-Source). La valeur recommandée par Repochecker est `>=6.0.11` — restaurée.",
13
+ "it": "Min js-controller correzione: è stato erroneamente urtato a `>=7.0.23` in 0.2.15 (Wert kam aus Recherche-Synthese, nicht aus Repochecker-Source). Il valore ricondizionato da repochecker è `>=6.0.11` — restaurato.",
14
+ "es": "Min js-controller correction: was incorrectly toped to `=7.0.23` in 0.2.15 (Wert kam aus Recherche-Synthese, nicht aus Repochecker-Source). Repochecker-recomendado valor es `=6.0.11` — restaurado.",
15
+ "pl": "Min js- controller correction: was intruly bone to '> = 7.0.23' in 0.2.15 (Wert kam aus Recherche- Synthes, nicht aus Repochecker- Source). Repochecker- zalecana wartość jest '> = 6.0.11' - przywrócona.",
16
+ "uk": "Нормативно прибрано до `>=7.0.23` в 0.2.15 (Верт kam aus Recherche-Synthese, nicht aus Repochecker-Source). Repochecker-recommended значення `>=6.0.11` — відновлено.",
17
+ "zh-cn": "Min js-controller校正:在0.2.15中被误撞到QQ7.0.23 ' (Wert kam aus ReResearch-Synthese, nicht aus Repochecker-Source)。 复检员推荐值为 6.0.11 ' ——恢复."
18
+ },
19
+ "0.2.15": {
20
+ "en": "Process-level unhandledRejection/uncaughtException handlers added as last-line-of-defence. Stop shipping the manual-review release-script plugin. Min js-controller bumped to >=7.0.23. Audit-driven boilerplate sync with the other krobi adapters (.vscode json5 schemas, tsconfig.test looser test rules). CHANGELOG_OLD cleaned up.",
21
+ "de": "Process-level unhandledRejection/uncaughtException-Handler als Last-Line-of-Defence hinzugefügt. Das manual-review-Release-Script-Plugin entfällt. js-controller-Mindestversion auf >=7.0.23 angehoben. Audit-getriebener Boilerplate-Sync gegenüber den anderen krobi-Adaptern (.vscode json5-Schemas, tsconfig.test loosere Test-Regeln). CHANGELOG_OLD aufgeräumt.",
22
+ "ru": "Process-level unhandledRejection/uncaughtException-обработчики додано як last-line-of-defence. Manual-review release-script plugin більше не постачається. Мінімальна версія js-controller підвищена до >=7.0.23. Audit-керована синхронізація boilerplate з іншими krobi-адаптерами (.vscode json5-схеми, tsconfig.test loose test rules). CHANGELOG_OLD приведено до ладу.",
23
+ "pt": "Handlers process-level unhandledRejection/uncaughtException adicionados como last-line-of-defence. O plugin manual-review do release-script foi removido. Versão mínima de js-controller aumentada para >=7.0.23. Sincronização de boilerplate orientada por audit com os outros adaptadores krobi (esquemas json5 do .vscode, regras de teste mais permissivas em tsconfig.test). CHANGELOG_OLD limpo.",
24
+ "nl": "Process-level unhandledRejection/uncaughtException-handlers toegevoegd als last-line-of-defence. Het manual-review release-script plugin wordt niet meer meegeleverd. Minimale js-controller versie verhoogd naar >=7.0.23. Audit-gestuurde boilerplate-sync met de andere krobi-adapters (.vscode json5-schemas, tsconfig.test soepelere test-regels). CHANGELOG_OLD opgeruimd.",
25
+ "fr": "Handlers process-level unhandledRejection/uncaughtException ajoutés en last-line-of-defence. Le plugin manual-review du release-script n'est plus livré. Version minimale de js-controller portée à >=7.0.23. Synchronisation boilerplate audit-driven avec les autres adaptateurs krobi (schémas json5 .vscode, règles de test plus souples tsconfig.test). CHANGELOG_OLD nettoyé.",
26
+ "it": "Handler process-level unhandledRejection/uncaughtException aggiunti come last-line-of-defence. Il plugin manual-review del release-script non viene più distribuito. Versione minima di js-controller alzata a >=7.0.23. Sincronizzazione boilerplate audit-driven con gli altri adapter krobi (schemi json5 .vscode, regole di test più permissive tsconfig.test). CHANGELOG_OLD ripulito.",
27
+ "es": "Handlers process-level unhandledRejection/uncaughtException añadidos como last-line-of-defence. El plugin manual-review del release-script ya no se incluye. Versión mínima de js-controller elevada a >=7.0.23. Sincronización de boilerplate guiada por audit con los demás adaptadores krobi (esquemas json5 .vscode, reglas de test más permisivas tsconfig.test). CHANGELOG_OLD limpio.",
28
+ "pl": "Handlery process-level unhandledRejection/uncaughtException dodane jako last-line-of-defence. Plugin manual-review release-script nie jest już dostarczany. Minimalna wersja js-controller podniesiona do >=7.0.23. Synchronizacja boilerplate'u audit-driven z pozostałymi adapterami krobi (schematy json5 .vscode, luźniejsze reguły testów tsconfig.test). CHANGELOG_OLD uporządkowany.",
29
+ "uk": "Process-level обробники unhandledRejection/uncaughtException додано як last-line-of-defence. Manual-review release-script plugin більше не постачається. Мінімальну версію js-controller підвищено до >=7.0.23. Audit-керована синхронізація boilerplate з іншими krobi-адаптерами (json5-схеми .vscode, м'якші правила тестів tsconfig.test). CHANGELOG_OLD упорядковано.",
30
+ "zh-cn": "新增进程级 unhandledRejection/uncaughtException 处理器作为 last-line-of-defence。manual-review release-script 插件不再随包发布。js-controller 最低版本提升至 >=7.0.23。与其他 krobi 适配器进行 audit 驱动的 boilerplate 同步(.vscode json5 schema、tsconfig.test 更宽松的测试规则)。整理 CHANGELOG_OLD。"
31
+ },
6
32
  "0.2.14": {
7
- "en": "Latest-repo review round 2: separate test build into build-test/, declare deliveries folder and summary channel as instance objects, localize status labels to all 11 ioBroker languages via system.config.language, harden async event handlers with .catch()",
8
- "de": "Latest-Repo Review Runde 2: Test-Build in build-test/ getrennt, deliveries-Ordner und summary-Kanal als instance objects deklariert, Status-Labels in allen 11 ioBroker-Sprachen via system.config.language lokalisiert, async Event-Handler mit .catch() gehärtet",
9
- "ru": "Исправления 2-го раунда обзора Latest-repo: тестовая сборка вынесена в build-test/, папка deliveries и канал summary объявлены как instance objects, метки статусов локализованы на все 11 языков ioBroker через system.config.language, асинхронные обработчики событий защищены .catch()",
10
- "pt": "Correções da revisão Latest-repo 2 ronda: build de testes separado em build-test/, pasta deliveries e canal summary declarados como instance objects, labels de estado localizados nas 11 línguas do ioBroker via system.config.language, handlers de eventos assíncronos protegidos com .catch()",
11
- "nl": "Latest-repo review ronde 2: test-build afgesplitst naar build-test/, deliveries-folder en summary-kanaal als instance objects gedeclareerd, statuslabels gelokaliseerd in alle 11 ioBroker-talen via system.config.language, async event handlers met .catch() gehard",
12
- "fr": "Corrections revue Latest-repo round 2 : build de test séparé dans build-test/, dossier deliveries et canal summary déclarés comme instance objects, libellés d'état localisés dans les 11 langues ioBroker via system.config.language, gestionnaires d'événements asynchrones protégés par .catch()",
13
- "it": "Correzioni revisione Latest-repo round 2: build di test separato in build-test/, cartella deliveries e canale summary dichiarati come instance objects, etichette di stato localizzate in tutte le 11 lingue ioBroker tramite system.config.language, gestori di eventi asincroni protetti con .catch()",
14
- "es": "Correcciones revisión Latest-repo ronda 2: compilación de pruebas separada en build-test/, carpeta deliveries y canal summary declarados como instance objects, etiquetas de estado localizadas a los 11 idiomas de ioBroker vía system.config.language, manejadores de eventos asíncronos protegidos con .catch()",
15
- "pl": "Poprawki przeglądu Latest-repo runda 2: build testowy wydzielony do build-test/, folder deliveries i kanał summary zadeklarowane jako instance objects, etykiety stanów zlokalizowane we wszystkich 11 językach ioBroker przez system.config.language, obsługa zdarzeń asynchronicznych zabezpieczona .catch()",
16
- "uk": "Виправлення огляду Latest-repo раунд 2: тестова збірка винесена в build-test/, папка deliveries та канал summary оголошені як instance objects, мітки статусів локалізовано на всі 11 мов ioBroker через system.config.language, асинхронні обробники подій захищені .catch()",
17
- "zh-cn": "Latest-repo 审核第二轮修复:测试构建分离到 build-test/,deliveries 文件夹和 summary 通道声明为 instance objects,通过 system.config.language 本地化状态标签到所有 11 种 ioBroker 语言,使用 .catch() 加固异步事件处理器"
33
+ "en": "Latest-repo review round 2 response. Separate test-build output (build-test/) from production build/. Declare deliveries folder and summary channel as instance objects. Localize status labels and delivery estimates to all 11 ioBroker languages via system.config.language; the per-instance Status Language option is removed. Fix summary.todayCount for non-DE/EN languages.",
34
+ "de": "Latest-Repo Review Round 2 Response. Test-Build-Output (build-test/) von der Production build/ getrennt. deliveries-Folder und summary-Channel als Instance-Objects deklariert. Status-Labels und Lieferzeit-Schätzungen werden in alle 11 ioBroker-Sprachen lokalisiert (über system.config.language); die per-Instanz Status-Language-Option entfällt. summary.todayCount für nicht-DE/EN Sprachen behoben.",
35
+ "ru": "Відповідь на latest-repo review round 2. Test-build output (build-test/) відокремлено від production build/. deliveries-folder та summary-channel задекларовано як instance objects. Status-labels та оцінки доставки локалізовано на всі 11 мов ioBroker через system.config.language; per-instance Status Language опція видалена. Виправлено summary.todayCount для не-DE/EN мов.",
36
+ "pt": "Resposta ao latest-repo review round 2. Saída do test-build (build-test/) separada da produção build/. Pasta deliveries e canal summary declarados como instance objects. Labels de status e estimativas de entrega localizadas em todas as 11 línguas do ioBroker via system.config.language; a opção Status Language por instância foi removida. summary.todayCount corrigido para línguas não-DE/EN.",
37
+ "nl": "Respons op latest-repo review round 2. Test-build output (build-test/) gescheiden van productie build/. deliveries-folder en summary-channel gedeclareerd als instance objects. Status-labels en bezorgschattingen gelokaliseerd in alle 11 ioBroker-talen via system.config.language; per-instance Status Language optie is verwijderd. summary.todayCount opgelost voor niet-DE/EN talen.",
38
+ "fr": "Réponse au latest-repo review round 2. Sortie du test-build (build-test/) séparée de la production build/. Dossier deliveries et canal summary déclarés comme instance objects. Status-labels et estimations de livraison localisés dans toutes les 11 langues ioBroker via system.config.language; option Status Language par instance supprimée. summary.todayCount corrigé pour langues non-DE/EN.",
39
+ "it": "Risposta alla latest-repo review round 2. Output del test-build (build-test/) separato dalla produzione build/. Cartella deliveries e canale summary dichiarati come instance objects. Status-label e stime di consegna localizzati in tutte le 11 lingue ioBroker via system.config.language; opzione Status Language per istanza rimossa. summary.todayCount corretto per lingue non-DE/EN.",
40
+ "es": "Respuesta al latest-repo review round 2. Salida del test-build (build-test/) separada de la producción build/. Carpeta deliveries y canal summary declarados como instance objects. Etiquetas de estado y estimaciones de entrega localizadas en los 11 idiomas de ioBroker via system.config.language; opción Status Language por instancia eliminada. summary.todayCount corregido para idiomas no-DE/EN.",
41
+ "pl": "Odpowiedź na latest-repo review round 2. Wyjście test-build (build-test/) oddzielone od produkcji build/. Folder deliveries i kanał summary zadeklarowane jako instance objects. Etykiety statusu i szacunki dostawy zlokalizowane we wszystkich 11 językach ioBroker przez system.config.language; opcja Status Language per-instance została usunięta. summary.todayCount naprawione dla języków innych niż DE/EN.",
42
+ "uk": "Відповідь на latest-repo review round 2. Test-build output (build-test/) відокремлено від production build/. Folder deliveries та channel summary оголошено як instance objects. Status-мітки та оцінки доставки локалізовано в усіх 11 мовах ioBroker через system.config.language; опцію Status Language per-instance видалено. summary.todayCount виправлено для мов крім DE/EN.",
43
+ "zh-cn": "Latest-repo review round 2 的回应。测试构建输出(build-test/)从生产 build/ 分离。deliveries 文件夹和 summary 通道声明为 instance objects。状态标签和到达时间预估通过 system.config.language 本地化为全部 11 种 ioBroker 语言;移除 per-instance Status Language 选项。修复非 DE/EN 语言下的 summary.todayCount。"
18
44
  },
19
45
  "0.2.13": {
20
- "en": "Latest-repo review compliance: set common.messagebox=true because the onMessage handler is used for admin-UI Check Connection and Add Delivery.",
21
- "de": "Latest-Repo-Review-Compliance: common.messagebox=true, weil der onMessage-Handler für Admin-UI Check Connection + Add Delivery genutzt wird.",
22
- "ru": "Соответствие ioBroker Latest: messagebox=true для admin-UI.",
23
- "pt": "Conformidade ioBroker Latest: messagebox=true para admin-UI.",
24
- "nl": "Compliance ioBroker Latest: messagebox=true voor admin-UI.",
25
- "fr": "Conformité ioBroker Latest : messagebox=true pour admin-UI.",
26
- "it": "Conformità ioBroker Latest: messagebox=true per admin-UI.",
27
- "es": "Cumplimiento ioBroker Latest: messagebox=true para admin-UI.",
28
- "pl": "Zgodność ioBroker Latest: messagebox=true dla admin-UI.",
29
- "uk": "Відповідність ioBroker Latest: messagebox=true для admin-UI.",
30
- "zh-cn": "符合 ioBroker Latest 仓库规范: messagebox=true, admin-UI 使用。"
46
+ "en": "Latest-repo review round 1 compliance: common.messagebox=true added because the admin-UI Check Connection and Add Delivery buttons route through onMessage. Runtime behaviour unchanged.",
47
+ "de": "Latest-Repo Review Round 1 Compliance: common.messagebox=true gesetzt, weil die Admin-UI-Buttons Check Connection und Add Delivery über onMessage laufen. Runtime-Verhalten unverändert.",
48
+ "ru": "Latest-repo review round 1 compliance: common.messagebox=true додано, оскільки кнопки Check Connection та Add Delivery в admin-UI проходять через onMessage. Runtime-поведінка незмінна.",
49
+ "pt": "Compliance do latest-repo review round 1: common.messagebox=true adicionado porque os botões Check Connection e Add Delivery do admin-UI passam pelo onMessage. Comportamento em runtime inalterado.",
50
+ "nl": "Latest-repo review round 1 compliance: common.messagebox=true toegevoegd omdat de admin-UI Check Connection en Add Delivery knoppen via onMessage lopen. Runtime-gedrag ongewijzigd.",
51
+ "fr": "Latest-repo review round 1 compliance: common.messagebox=true ajouté car les boutons Check Connection et Add Delivery de l'admin-UI passent par onMessage. Comportement runtime inchangé.",
52
+ "it": "Latest-repo review round 1 compliance: common.messagebox=true aggiunto perché i pulsanti Check Connection e Add Delivery dell'admin-UI passano da onMessage. Comportamento runtime invariato.",
53
+ "es": "Latest-repo review round 1 compliance: common.messagebox=true añadido porque los botones Check Connection y Add Delivery de admin-UI pasan por onMessage. Comportamiento en runtime sin cambios.",
54
+ "pl": "Latest-repo review round 1 compliance: common.messagebox=true dodane, ponieważ przyciski Check Connection i Add Delivery admin-UI przechodzą przez onMessage. Zachowanie runtime bez zmian.",
55
+ "uk": "Latest-repo review round 1 compliance: common.messagebox=true додано, оскільки кнопки Check Connection та Add Delivery в admin-UI проходять через onMessage. Runtime поведінка незмінна.",
56
+ "zh-cn": "Latest-repo review round 1 compliance:因 admin-UI 的 Check Connection 与 Add Delivery 按钮经由 onMessage 路由,故添加 common.messagebox=true。运行时行为不变。"
31
57
  },
32
58
  "0.2.12": {
33
- "en": "Harden API-drift guards in parcel-client and state-manager, add 38 regression tests",
34
- "de": "API-Drift-Härtung in parcel-client und state-manager, 38 zusätzliche Regressions-Tests",
35
- "ru": "Усиление защиты от дрейфа API в parcel-client и state-manager, добавлено 38 регрессионных тестов",
36
- "pt": "Reforço de proteções contra API-drift em parcel-client e state-manager, 38 testes de regressão adicionais",
37
- "nl": "API-drift guards versterkt in parcel-client en state-manager, 38 extra regressietests",
38
- "fr": "Renforcement des protections contre la dérive d'API dans parcel-client et state-manager, 38 tests de régression supplémentaires",
39
- "it": "Rafforzate protezioni contro API-drift in parcel-client e state-manager, 38 test di regressione aggiuntivi",
40
- "es": "Reforzadas las protecciones contra API-drift en parcel-client y state-manager, 38 pruebas de regresión adicionales",
41
- "pl": "Wzmocniono zabezpieczenia przed dryfem API w parcel-client i state-manager, 38 dodatkowych testów regresji",
42
- "uk": "Посилено захист від дрейфу API у parcel-client та state-manager, 38 додаткових регресійних тестів",
43
- "zh-cn": "加固parcel-clientstate-manager中的API漂移防护,新增38个回归测试"
59
+ "en": "Harden API-drift guards in ParcelClient and StateManager (non-boolean success, non-array deliveries, non-string error_code/error_message, non-object carrier map, non-string delivery fields). 38 new regression tests (128 total).",
60
+ "de": "API-Drift-Guards in ParcelClient und StateManager gehärtet (non-boolean success, non-array deliveries, non-string error_code/error_message, non-object carrier map, non-string delivery fields). 38 neue Regression-Tests (128 total).",
61
+ "ru": "API-drift guards в ParcelClient та StateManager посилено (non-boolean success, non-array deliveries, non-string error_code/error_message, non-object carrier map, non-string delivery fields). 38 нових regression-тестів (128 всього).",
62
+ "pt": "API-drift guards reforçados em ParcelClient e StateManager (success non-boolean, deliveries non-array, error_code/error_message non-string, carrier map non-object, campos non-string). 38 novos regression-tests (128 no total).",
63
+ "nl": "API-drift guards in ParcelClient en StateManager versterkt (non-boolean success, non-array deliveries, non-string error_code/error_message, non-object carrier map, non-string delivery fields). 38 nieuwe regressietests (128 totaal).",
64
+ "fr": "API-drift guards renforcés dans ParcelClient et StateManager (success non-boolean, deliveries non-array, error_code/error_message non-string, carrier map non-object, champs non-string). 38 nouveaux regression-tests (128 au total).",
65
+ "it": "API-drift guards rafforzati in ParcelClient e StateManager (success non-boolean, deliveries non-array, error_code/error_message non-string, carrier map non-object, campi non-string). 38 nuovi regression-test (128 totali).",
66
+ "es": "API-drift guards reforzados en ParcelClient y StateManager (success non-boolean, deliveries non-array, error_code/error_message non-string, carrier map non-object, campos non-string). 38 nuevos tests de regresión (128 en total).",
67
+ "pl": "API-drift guards wzmocnione w ParcelClient i StateManager (success non-boolean, deliveries non-array, error_code/error_message non-string, carrier map non-object, pola non-string). 38 nowych testów regresji (128 łącznie).",
68
+ "uk": "API-drift guards посилено в ParcelClient і StateManager (non-boolean success, non-array deliveries, non-string error_code/error_message, non-object carrier map, non-string delivery fields). 38 нових regression-тестів (128 загалом).",
69
+ "zh-cn": "强化 ParcelClient StateManager 的 API-drift guards(非布尔 success、非数组 deliveries、非字符串 error_code/error_message、非对象 carrier map、非字符串 delivery 字段)。新增 38 个 regression 测试(共 128 个)。"
44
70
  },
45
71
  "0.2.11": {
46
- "en": "Fix response stream error handling, isolate per-delivery poll failures, harden onMessage and onUnload",
47
- "de": "Response-Stream-Fehlerbehandlung gefixt, per-Delivery Poll-Fehler isoliert, onMessage und onUnload gehärtet",
48
- "ru": "Исправлена обработка ошибок потока ответа, изолированы ошибки опроса по доставкам, усилены onMessage и onUnload",
49
- "pt": "Corrigido tratamento de erros do stream de resposta, falhas de polling isoladas por entrega, onMessage e onUnload reforçados",
50
- "nl": "Response stream foutafhandeling gerepareerd, per-levering poll fouten geïsoleerd, onMessage en onUnload versterkt",
51
- "fr": "Correction de la gestion des erreurs du flux de réponse, isolation des erreurs de sondage par livraison, renforcement de onMessage et onUnload",
52
- "it": "Corretta gestione errori stream risposta, errori di polling isolati per consegna, onMessage e onUnload rafforzati",
53
- "es": "Corregido manejo de errores del flujo de respuesta, errores de sondeo aislados por envío, onMessage y onUnload reforzados",
54
- "pl": "Naprawiono obsługę błędów strumienia odpowiedzi, izolacja błędów odpytywania per dostawa, wzmocnione onMessage i onUnload",
55
- "uk": "Виправлено обробку помилок потоку відповіді, ізольовано помилки опитування per-delivery, посилено onMessage та onUnload",
56
- "zh-cn": "修复响应流错误处理,隔离每个快递轮询失败,加固onMessage和onUnload"
72
+ "en": "Handle response stream errors. Isolate per-delivery poll failures (one broken delivery no longer blocks all others). Harden onMessage and onUnload with try/catch + callback guard. parseStatus DRY helper.",
73
+ "de": "Response-Stream-Errors abgefangen. Per-Delivery Poll-Failures isoliert (ein kaputtes Paket blockiert nicht mehr alle anderen). onMessage und onUnload mit try/catch + Callback-Guard gehärtet. parseStatus DRY-Helper.",
74
+ "ru": "Помилки response-stream обробляються. Per-delivery poll-failures ізольовано (одне зламане відправлення більше не блокує інші). onMessage та onUnload посилено через try/catch + callback-guard. parseStatus DRY-helper.",
75
+ "pt": "Erros de response-stream tratados. Falhas per-delivery isoladas (uma encomenda quebrada não bloqueia mais as outras). onMessage e onUnload reforçados com try/catch + callback-guard. parseStatus DRY-helper.",
76
+ "nl": "Response-stream fouten afgevangen. Per-delivery poll-failures geïsoleerd (één defect pakket blokkeert niet meer de anderen). onMessage en onUnload versterkt met try/catch + callback-guard. parseStatus DRY-helper.",
77
+ "fr": "Erreurs de response-stream traitées. Échecs per-delivery isolés (un colis cassé ne bloque plus les autres). onMessage et onUnload renforcés avec try/catch + callback-guard. parseStatus DRY-helper.",
78
+ "it": "Errori di response-stream gestiti. Fallimenti per-delivery isolati (un pacco rotto non blocca più gli altri). onMessage e onUnload rafforzati con try/catch + callback-guard. parseStatus DRY-helper.",
79
+ "es": "Errores de response-stream manejados. Fallos per-delivery aislados (un paquete roto ya no bloquea los demás). onMessage y onUnload reforzados con try/catch + callback-guard. parseStatus DRY-helper.",
80
+ "pl": "Błędy response-stream obsłużone. Per-delivery poll-failures odizolowane (jedna zepsuta paczka nie blokuje już pozostałych). onMessage i onUnload wzmocnione przez try/catch + callback-guard. parseStatus DRY-helper.",
81
+ "uk": "Помилки response-stream оброблено. Per-delivery poll-failures ізольовано (одне зламане відправлення більше не блокує інші). onMessage та onUnload посилено через try/catch + callback-guard. parseStatus DRY-helper.",
82
+ "zh-cn": "处理 response-stream 错误。隔离 per-delivery poll-failures(一个坏掉的包裹不再阻塞其他)。通过 try/catch + callback-guard 强化 onMessage onUnload。parseStatus DRY-helper。"
57
83
  },
58
84
  "0.2.10": {
59
- "en": "Fix test timezone bug, remove unused devDependencies, add no-floating-promises lint rule",
60
- "de": "Test-Zeitzonenfehler behoben, ungenutzte devDependencies entfernt, no-floating-promises Lint-Regel hinzugefügt",
61
- "ru": "Исправлена ошибка часового пояса в тестах, удалены неиспользуемые devDependencies, добавлено правило линтинга no-floating-promises",
62
- "pt": "Corrigido bug de fuso horário em testes, removidas devDependencies não utilizadas, adicionada regra de lint no-floating-promises",
63
- "nl": "Tijdzonebug in tests opgelost, ongebruikte devDependencies verwijderd, no-floating-promises lintregel toegevoegd",
64
- "fr": "Correction du bug de fuseau horaire dans les tests, suppression des devDependencies inutilisées, ajout de la règle de lint no-floating-promises",
65
- "it": "Corretto bug fuso orario nei test, rimosse devDependencies inutilizzate, aggiunta regola lint no-floating-promises",
66
- "es": "Corregido error de zona horaria en pruebas, eliminadas devDependencies no utilizadas, añadida regla de lint no-floating-promises",
67
- "pl": "Naprawiono błąd strefy czasowej w testach, usunięto nieużywane devDependencies, dodano regułę lint no-floating-promises",
68
- "uk": "Виправлено помилку часового поясу в тестах, видалено невикористані devDependencies, додано правило лінтингу no-floating-promises",
69
- "zh-cn": "修复测试时区错误,移除未使用的开发依赖,添加 no-floating-promises 检查规则"
70
- },
71
- "0.2.9": {
72
- "en": "Add standard ioBroker test suite, optimize test build config",
73
- "de": "Standard-ioBroker-Testsuite hinzugefügt, Test-Build-Konfiguration optimiert",
74
- "ru": "Добавлен стандартный набор тестов ioBroker, оптимизирована конфигурация сборки тестов",
75
- "pt": "Adicionado conjunto de testes padrão do ioBroker, configuração de build de teste otimizada",
76
- "nl": "Standaard ioBroker-testsuite toegevoegd, testbuild-configuratie geoptimaliseerd",
77
- "fr": "Ajout de la suite de tests standard ioBroker, configuration de build de test optimisée",
78
- "it": "Aggiunta suite di test standard ioBroker, configurazione build test ottimizzata",
79
- "es": "Añadida suite de pruebas estándar de ioBroker, configuración de compilación de pruebas optimizada",
80
- "pl": "Dodano standardowy zestaw testów ioBroker, zoptymalizowano konfigurację budowania testów",
81
- "uk": "Додано стандартний набір тестів ioBroker, оптимізовано конфігурацію збірки тестів",
82
- "zh-cn": "添加标准 ioBroker 测试套件,优化测试构建配置"
83
- },
84
- "0.2.8": {
85
- "en": "Clean up empty parent folders after removing obsolete states",
86
- "de": "Leere Eltern-Ordner nach Entfernen obsoleter States löschen",
87
- "ru": "Удаление пустых родительских папок после удаления устаревших состояний",
88
- "pt": "Limpar pastas pai vazias após remover estados obsoletos",
89
- "nl": "Lege bovenliggende mappen opruimen na verwijderen van verouderde statussen",
90
- "fr": "Nettoyage des dossiers parents vides après suppression des états obsolètes",
91
- "it": "Pulizia delle cartelle padre vuote dopo la rimozione degli stati obsoleti",
92
- "es": "Limpiar carpetas padre vacías después de eliminar estados obsoletos",
93
- "pl": "Usuwanie pustych folderów nadrzędnych po usunięciu przestarzałych stanów",
94
- "uk": "Видалення порожніх батьківських папок після видалення застарілих станів",
95
- "zh-cn": "移除过时状态后清理空父文件夹"
85
+ "en": "Fix test timezone bug, remove unused devDependencies, add no-floating-promises lint rule. Remove redundant actions/checkout from CI workflow.",
86
+ "de": "Test-Timezone-Bug behoben, ungenutzte devDependencies entfernt, no-floating-promises Lint-Regel hinzugefügt. Redundantes actions/checkout aus CI-Workflow entfernt.",
87
+ "ru": "Test-timezone-баг виправлено, невикористані devDependencies видалено, додано no-floating-promises lint-правило. Redundant actions/checkout видалено з CI-workflow.",
88
+ "pt": "Bug de test-timezone corrigido, devDependencies não usadas removidas, regra no-floating-promises adicionada. actions/checkout redundante removido do CI-workflow.",
89
+ "nl": "Test-timezone bug opgelost, ongebruikte devDependencies verwijderd, no-floating-promises lint-regel toegevoegd. Overbodige actions/checkout uit CI-workflow verwijderd.",
90
+ "fr": "Bug test-timezone corrigé, devDependencies inutilisées retirées, règle no-floating-promises ajoutée. actions/checkout redondant retiré du workflow CI.",
91
+ "it": "Bug test-timezone corretto, devDependencies inutilizzate rimosse, regola no-floating-promises aggiunta. actions/checkout ridondante rimosso dal workflow CI.",
92
+ "es": "Bug de test-timezone arreglado, devDependencies sin uso eliminadas, regla no-floating-promises añadida. actions/checkout redundante eliminado del workflow CI.",
93
+ "pl": "Bug test-timezone naprawiony, nieużywane devDependencies usunięte, dodano regułę no-floating-promises. Zbędne actions/checkout usunięte z CI-workflow.",
94
+ "uk": "Test-timezone-баг виправлено, невикористані devDependencies видалено, додано lint-правило no-floating-promises. Зайве actions/checkout видалено з CI-workflow.",
95
+ "zh-cn": "修复 test-timezone bug,移除未使用的 devDependencies,添加 no-floating-promises lint 规则。从 CI workflow 中移除多余的 actions/checkout。"
96
96
  }
97
97
  },
98
98
  "titleLang": {
@@ -157,7 +157,7 @@
157
157
  },
158
158
  "dependencies": [
159
159
  {
160
- "js-controller": ">=7.0.0"
160
+ "js-controller": ">=6.0.11"
161
161
  }
162
162
  ],
163
163
  "globalDependencies": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.parcelapp",
3
- "version": "0.2.14",
3
+ "version": "0.2.16",
4
4
  "description": "ioBroker adapter for parcel.app — track packages as ioBroker states",
5
5
  "author": {
6
6
  "name": "krobi",
@@ -37,12 +37,11 @@
37
37
  "@alcalzone/release-script": "^5.1.1",
38
38
  "@alcalzone/release-script-plugin-iobroker": "^5.1.2",
39
39
  "@alcalzone/release-script-plugin-license": "^5.1.1",
40
- "@alcalzone/release-script-plugin-manual-review": "^5.1.1",
41
40
  "@iobroker/adapter-dev": "^1.5.0",
42
41
  "@iobroker/eslint-config": "^2.2.0",
43
42
  "@iobroker/testing": "^5.2.2",
44
43
  "@tsconfig/node20": "^20.1.9",
45
- "@types/iobroker": "npm:@iobroker/types@^7.1.0",
44
+ "@types/iobroker": "npm:@iobroker/types@^7.1.1",
46
45
  "@types/node": "^25.6.0",
47
46
  "rimraf": "^6.1.3",
48
47
  "typescript": "~5.9.3"