@izak0s/mplusqapi-node 1.1.0 → 1.1.1

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
@@ -177,22 +177,28 @@ The same field name (e.g. `priceIncl`) can be a `string` on one type and a `numb
177
177
 
178
178
  ### Dates
179
179
 
180
- `SoapMplusDateTime` response fields are deserialized to `Date` objects. Pass `Date` objects for request fields that accept dates.
180
+ The API has two date structs, handled differently:
181
181
 
182
- The API sends/expects **wall-clock** date structs (year/mon/day/hour/min/sec) with no embedded offset on date-only fields. These are interpreted in the client's configured `timezone` (default `Europe/Amsterdam`) when converting to/from JS `Date` (which is an absolute UTC instant):
182
+ **`SoapMplusDateTime`** (full timestamp) carries its own UTC offset (`timezone`, in minutes). Deserialized to an exact `Date` using that offset, independent of host or config:
183
183
 
184
184
  ```typescript
185
- const client = new MplusKassaClient({ /* ...host/port/auth... */, timezone: 'Europe/Amsterdam' });
185
+ // struct { year:2026, mon:6, day:12, hour:13, min:45, sec:30, timezone:120 }
186
+ // -> 2026-06-12T11:45:30.000Z (exact instant; +120 min == +02:00)
187
+ ```
188
+
189
+ If a `SoapMplusDateTime` ever omits its offset, the client's configured `timezone` (default `Europe/Amsterdam`) is used as a fallback to interpret the wall-clock. The configured zone is also used when **serializing** outbound timestamps (to fill `timezone`/`isdst`).
186
190
 
187
- // financialDate "2018-06-18" deserializes to midnight Amsterdam time,
188
- // i.e. the instant 2018-06-17T22:00:00.000Z (summer, +02:00).
189
- // Print it in the configured zone to see the intended calendar date:
190
- console.log(order.financialDate?.toLocaleDateString('nl-NL', { timeZone: 'Europe/Amsterdam' }));
191
+ **`SoapMplusDate`** (calendar date, e.g. `financialDate`) has only day/mon/year, no time and no offset. Deserialized to **UTC midnight**, so it reads as the intended calendar date with no off-by-one:
192
+
193
+ ```typescript
194
+ // struct { year:2018, mon:6, day:18 } -> 2018-06-18T00:00:00.000Z
195
+ order.financialDate?.toISOString().slice(0, 10); // '2018-06-18'
196
+ order.financialDate?.getUTCDate(); // 18
191
197
  ```
192
198
 
193
- A `Date` logged directly prints in UTC, so a local midnight shows as `...T22:00:00.000Z` the previous day that's correct, just rendered in UTC. Format with the matching `timeZone` to avoid confusion.
199
+ > Read date-only fields with the **UTC** accessors (`getUTCFullYear/Month/Date`) or `.toISOString().slice(0, 10)` not `getDate()`/`toLocaleDateString()`, which shift by your host's zone. When **sending** a date-only field, build a UTC-midnight `Date`: `new Date('2018-06-18')` or `new Date(Date.UTC(y, m - 1, d))`.
194
200
 
195
- > **Note:** the timezone is process-wide — constructing multiple clients with different `timezone` values in one process is not supported. `setTimeZone(tz)` / `getTimeZone()` are also exported for direct control.
201
+ > **Note:** the configured `timezone` is process-wide — constructing multiple clients with different `timezone` values in one process is not supported. `setTimeZone(tz)` / `getTimeZone()` are also exported for direct control.
196
202
 
197
203
  ### List fields
198
204
 
@@ -279,7 +285,7 @@ npm version patch # or minor / major — bumps package.json, commits, tags
279
285
  git push --follow-tags
280
286
  ```
281
287
 
282
- The tag triggers `.github/workflows/publish.yml`: gate on `npm run check`, publish to npm via [trusted publishing](https://docs.npmjs.com/trusted-publishers) (OIDC, no token), and create a GitHub release with generated notes. The workflow refuses to publish if the tag doesn't match `package.json`.
288
+ The tag triggers `.github/workflows/publish.yml`: it first runs the full CI workflow (lint, build, type-check, tests across the Node matrix, pack check) as a gate, then — only if CI passes — publishes to npm via [trusted publishing](https://docs.npmjs.com/trusted-publishers) (OIDC, no token) and creates a GitHub release with generated notes. The workflow refuses to publish if the tag doesn't match `package.json`.
283
289
 
284
290
  ### Run the example
285
291
 
package/dist/index.js CHANGED
@@ -218,30 +218,26 @@ function serializeDateTime(elemName, value) {
218
218
  return `<${NS_PREFIX}:${elemName}><${NS_PREFIX}:sec>${p.sec}</${NS_PREFIX}:sec><${NS_PREFIX}:min>${p.min}</${NS_PREFIX}:min><${NS_PREFIX}:hour>${p.hour}</${NS_PREFIX}:hour><${NS_PREFIX}:day>${p.day}</${NS_PREFIX}:day><${NS_PREFIX}:mon>${p.mon}</${NS_PREFIX}:mon><${NS_PREFIX}:year>${p.year}</${NS_PREFIX}:year><${NS_PREFIX}:isdst>${isDstAt(value.getTime(), tz)}</${NS_PREFIX}:isdst><${NS_PREFIX}:timezone>${tzOffset}</${NS_PREFIX}:timezone></${NS_PREFIX}:${elemName}>`;
219
219
  }
220
220
  function serializeDate(elemName, value) {
221
- const p = zonedPartsOf(value, activeTimeZone);
222
- return `<${NS_PREFIX}:${elemName}><${NS_PREFIX}:day>${p.day}</${NS_PREFIX}:day><${NS_PREFIX}:mon>${p.mon}</${NS_PREFIX}:mon><${NS_PREFIX}:year>${p.year}</${NS_PREFIX}:year></${NS_PREFIX}:${elemName}>`;
221
+ return `<${NS_PREFIX}:${elemName}><${NS_PREFIX}:day>${value.getUTCDate()}</${NS_PREFIX}:day><${NS_PREFIX}:mon>${value.getUTCMonth() + 1}</${NS_PREFIX}:mon><${NS_PREFIX}:year>${value.getUTCFullYear()}</${NS_PREFIX}:year></${NS_PREFIX}:${elemName}>`;
223
222
  }
224
223
  function deserializeDateTime(obj) {
225
- return zonedToUtc(
226
- Number(obj["year"]),
227
- Number(obj["mon"]),
228
- Number(obj["day"]),
229
- Number(obj["hour"]),
230
- Number(obj["min"]),
231
- Number(obj["sec"]),
232
- activeTimeZone
233
- );
224
+ const year = Number(obj["year"]);
225
+ const mon = Number(obj["mon"]);
226
+ const day = Number(obj["day"]);
227
+ const hour = Number(obj["hour"]);
228
+ const min = Number(obj["min"]);
229
+ const sec = Number(obj["sec"]);
230
+ const tzRaw = obj["timezone"];
231
+ if (tzRaw !== void 0 && tzRaw !== null && tzRaw !== "") {
232
+ const offsetMin = Number(tzRaw);
233
+ if (!Number.isNaN(offsetMin)) {
234
+ return new Date(Date.UTC(year, mon - 1, day, hour, min, sec) - offsetMin * 6e4);
235
+ }
236
+ }
237
+ return zonedToUtc(year, mon, day, hour, min, sec, activeTimeZone);
234
238
  }
235
239
  function deserializeDate(obj) {
236
- return zonedToUtc(
237
- Number(obj["year"]),
238
- Number(obj["mon"]),
239
- Number(obj["day"]),
240
- 0,
241
- 0,
242
- 0,
243
- activeTimeZone
244
- );
240
+ return new Date(Date.UTC(Number(obj["year"]), Number(obj["mon"]) - 1, Number(obj["day"])));
245
241
  }
246
242
  function toArray(val) {
247
243
  if (val === void 0 || val === null) return [];
package/dist/index.mjs CHANGED
@@ -172,30 +172,26 @@ function serializeDateTime(elemName, value) {
172
172
  return `<${NS_PREFIX}:${elemName}><${NS_PREFIX}:sec>${p.sec}</${NS_PREFIX}:sec><${NS_PREFIX}:min>${p.min}</${NS_PREFIX}:min><${NS_PREFIX}:hour>${p.hour}</${NS_PREFIX}:hour><${NS_PREFIX}:day>${p.day}</${NS_PREFIX}:day><${NS_PREFIX}:mon>${p.mon}</${NS_PREFIX}:mon><${NS_PREFIX}:year>${p.year}</${NS_PREFIX}:year><${NS_PREFIX}:isdst>${isDstAt(value.getTime(), tz)}</${NS_PREFIX}:isdst><${NS_PREFIX}:timezone>${tzOffset}</${NS_PREFIX}:timezone></${NS_PREFIX}:${elemName}>`;
173
173
  }
174
174
  function serializeDate(elemName, value) {
175
- const p = zonedPartsOf(value, activeTimeZone);
176
- return `<${NS_PREFIX}:${elemName}><${NS_PREFIX}:day>${p.day}</${NS_PREFIX}:day><${NS_PREFIX}:mon>${p.mon}</${NS_PREFIX}:mon><${NS_PREFIX}:year>${p.year}</${NS_PREFIX}:year></${NS_PREFIX}:${elemName}>`;
175
+ return `<${NS_PREFIX}:${elemName}><${NS_PREFIX}:day>${value.getUTCDate()}</${NS_PREFIX}:day><${NS_PREFIX}:mon>${value.getUTCMonth() + 1}</${NS_PREFIX}:mon><${NS_PREFIX}:year>${value.getUTCFullYear()}</${NS_PREFIX}:year></${NS_PREFIX}:${elemName}>`;
177
176
  }
178
177
  function deserializeDateTime(obj) {
179
- return zonedToUtc(
180
- Number(obj["year"]),
181
- Number(obj["mon"]),
182
- Number(obj["day"]),
183
- Number(obj["hour"]),
184
- Number(obj["min"]),
185
- Number(obj["sec"]),
186
- activeTimeZone
187
- );
178
+ const year = Number(obj["year"]);
179
+ const mon = Number(obj["mon"]);
180
+ const day = Number(obj["day"]);
181
+ const hour = Number(obj["hour"]);
182
+ const min = Number(obj["min"]);
183
+ const sec = Number(obj["sec"]);
184
+ const tzRaw = obj["timezone"];
185
+ if (tzRaw !== void 0 && tzRaw !== null && tzRaw !== "") {
186
+ const offsetMin = Number(tzRaw);
187
+ if (!Number.isNaN(offsetMin)) {
188
+ return new Date(Date.UTC(year, mon - 1, day, hour, min, sec) - offsetMin * 6e4);
189
+ }
190
+ }
191
+ return zonedToUtc(year, mon, day, hour, min, sec, activeTimeZone);
188
192
  }
189
193
  function deserializeDate(obj) {
190
- return zonedToUtc(
191
- Number(obj["year"]),
192
- Number(obj["mon"]),
193
- Number(obj["day"]),
194
- 0,
195
- 0,
196
- 0,
197
- activeTimeZone
198
- );
194
+ return new Date(Date.UTC(Number(obj["year"]), Number(obj["mon"]) - 1, Number(obj["day"])));
199
195
  }
200
196
  function toArray(val) {
201
197
  if (val === void 0 || val === null) return [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@izak0s/mplusqapi-node",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "TypeScript client for the MplusKASSA SOAP API",
5
5
  "homepage": "https://github.com/izak0s/mplusqapi-node#readme",
6
6
  "bugs": {