@softwear/latestcollectioncore 1.0.186 → 1.0.188

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/dist/index.d.ts CHANGED
@@ -14,6 +14,7 @@ export { default as hasOnlyDigits } from './hasOnlyDigits';
14
14
  export { default as imageBinder } from './imageBinder';
15
15
  export { default as isean13 } from './isean13';
16
16
  export { default as pivotTable } from './pivotTable';
17
+ export { default as projectObject } from './projectObject';
17
18
  export { default as reports, genPDF } from './reports';
18
19
  export { default as round2 } from './round2';
19
20
  export { default as sizeToMap } from './sizeToMap';
package/dist/index.js CHANGED
@@ -17,7 +17,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
17
17
  return (mod && mod.__esModule) ? mod : { "default": mod };
18
18
  };
19
19
  Object.defineProperty(exports, "__esModule", { value: true });
20
- exports.isAxiosError = exports.exponentialDelay = exports.axiosRetry = exports.createAxiosInstance = exports.lcAxios = exports.transaction = exports.sizeToMap = exports.round2 = exports.genPDF = exports.reports = exports.pivotTable = exports.isean13 = exports.imageBinder = exports.hasOnlyDigits = exports.hashBrand = exports.getPreferedPropertyMappings = exports.getBrandName = exports.findMetaBrandSetting = exports.findSkuByBarcode = exports.ensureImpliedProperties = exports.ensureArray = exports.edifact = exports.ean13 = exports.deepCopy = exports.buildPropertyMappingFn = exports.articleStatus = void 0;
20
+ exports.isAxiosError = exports.exponentialDelay = exports.axiosRetry = exports.createAxiosInstance = exports.lcAxios = exports.transaction = exports.sizeToMap = exports.round2 = exports.genPDF = exports.reports = exports.projectObject = exports.pivotTable = exports.isean13 = exports.imageBinder = exports.hasOnlyDigits = exports.hashBrand = exports.getPreferedPropertyMappings = exports.getBrandName = exports.findMetaBrandSetting = exports.findSkuByBarcode = exports.ensureImpliedProperties = exports.ensureArray = exports.edifact = exports.ean13 = exports.deepCopy = exports.buildPropertyMappingFn = exports.articleStatus = void 0;
21
21
  var articleStatus_1 = require("./articleStatus");
22
22
  Object.defineProperty(exports, "articleStatus", { enumerable: true, get: function () { return __importDefault(articleStatus_1).default; } });
23
23
  var buildPropertyMappingFn_1 = require("./buildPropertyMappingFn");
@@ -50,6 +50,8 @@ var isean13_1 = require("./isean13");
50
50
  Object.defineProperty(exports, "isean13", { enumerable: true, get: function () { return __importDefault(isean13_1).default; } });
51
51
  var pivotTable_1 = require("./pivotTable");
52
52
  Object.defineProperty(exports, "pivotTable", { enumerable: true, get: function () { return __importDefault(pivotTable_1).default; } });
53
+ var projectObject_1 = require("./projectObject");
54
+ Object.defineProperty(exports, "projectObject", { enumerable: true, get: function () { return __importDefault(projectObject_1).default; } });
53
55
  var reports_1 = require("./reports");
54
56
  Object.defineProperty(exports, "reports", { enumerable: true, get: function () { return __importDefault(reports_1).default; } });
55
57
  Object.defineProperty(exports, "genPDF", { enumerable: true, get: function () { return reports_1.genPDF; } });
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Whitelist projection: builds a new object from a deep-cloned copy of `source`,
3
+ * copying only the listed property names (nested values are cloned with `source`).
4
+ */
5
+ export default function projectObject<K extends string>(source: unknown, keys: readonly K[]): Record<K, unknown>;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const deepCopy_1 = __importDefault(require("./deepCopy"));
7
+ /**
8
+ * Whitelist projection: builds a new object from a deep-cloned copy of `source`,
9
+ * copying only the listed property names (nested values are cloned with `source`).
10
+ */
11
+ function projectObject(source, keys) {
12
+ const out = {};
13
+ if (source == null)
14
+ return out;
15
+ if (typeof source !== 'object')
16
+ return out;
17
+ const tmp = (0, deepCopy_1.default)(source);
18
+ for (const k of keys) {
19
+ out[k] = tmp[k];
20
+ }
21
+ return out;
22
+ }
23
+ exports.default = projectObject;
package/dist/reports.js CHANGED
@@ -16,13 +16,13 @@ exports.genPDF = void 0;
16
16
  const jspdf_1 = require("jspdf");
17
17
  const date_fns_1 = require("date-fns");
18
18
  const deepCopy_1 = __importDefault(require("./deepCopy"));
19
- /** Measurement uses context `currentPageNumber` (1-based). Rendering normalizes jsPDF’s internal 0-based page index to 1-based so overlap rules match `pageNumber` fields. */
19
+ /** Measurement uses context `currentPageNumber` (1-based). Rendering uses jsPDF’s `getCurrentPageInfo().pageNumber`, which is already 1-based (first page is 1). */
20
20
  function getCurrentPageNumber(doc, context) {
21
21
  var _a;
22
22
  if (context.mode === 'measurement') {
23
23
  return (_a = context.currentPageNumber) !== null && _a !== void 0 ? _a : 1;
24
24
  }
25
- return doc.getCurrentPageInfo().pageNumber + 1;
25
+ return doc.getCurrentPageInfo().pageNumber;
26
26
  }
27
27
  // We have to declare some functions that will be called by other functions but also have to call those other functions
28
28
  // We overwrite the function definition as soon as those other functions have been declared
@@ -507,9 +507,14 @@ addObjectToPDF = function (originX, originY, doc, object, printBuffer, paperSize
507
507
  const layoutXtenths = originX + object.x;
508
508
  const layoutYtenths = originY + object.y;
509
509
  const rawPrintOnlyAtStartOffset = printOnlyAtStartContainersOffset !== null && printOnlyAtStartContainersOffset !== void 0 ? printOnlyAtStartContainersOffset : 0;
510
- const effectivePrintOnlyAtStartContainersOffset = containerChain.length === 0 && rawPrintOnlyAtStartOffset > 0 && getCurrentPageNumber(doc, context) === 1 ? rawPrintOnlyAtStartOffset : 0;
510
+ /** Must consult current page on every read: `addPage` can move to page 2+ mid-invocation while this call stays open. */
511
+ const effectivePrintOnlyAtStartContainersOffsetNow = () => containerChain.length === 0 &&
512
+ rawPrintOnlyAtStartOffset > 0 &&
513
+ getCurrentPageNumber(doc, context) === 1
514
+ ? rawPrintOnlyAtStartOffset
515
+ : 0;
511
516
  const x = layoutXtenths / 10;
512
- const y = (layoutYtenths + effectivePrintOnlyAtStartContainersOffset) / 10;
517
+ const y = (layoutYtenths + effectivePrintOnlyAtStartContainersOffsetNow()) / 10;
513
518
  const width = object.width / 10;
514
519
  const height = object.height / 10;
515
520
  // Keep track of the lower righthandside of all objects in this container
@@ -530,7 +535,7 @@ addObjectToPDF = function (originX, originY, doc, object, printBuffer, paperSize
530
535
  }
531
536
  const nrContainers = source.length;
532
537
  let originX = layoutXtenths;
533
- let originY = layoutYtenths + effectivePrintOnlyAtStartContainersOffset;
538
+ let originY = layoutYtenths + effectivePrintOnlyAtStartContainersOffsetNow();
534
539
  for (let containerIndex = 0; containerIndex < nrContainers; containerIndex++) {
535
540
  const newContainerChain = containerChain.filter(function () {
536
541
  return true;
@@ -542,7 +547,8 @@ addObjectToPDF = function (originX, originY, doc, object, printBuffer, paperSize
542
547
  if (useOrphanCheck && (object.pageBreak || originY + minHeightMm > paperSize.height - paperSize.footerHeight)) {
543
548
  // We ran out of paper
544
549
  originX = layoutXtenths;
545
- originY = layoutYtenths + effectivePrintOnlyAtStartContainersOffset;
550
+ // Continuation sheets must not reuse the page-1-only overlap bump: addPage hasn't run yet so getCurrentPageNumber is still 1.
551
+ originY = layoutYtenths;
546
552
  const newOrigin = addPage(originX, originY, doc, layout, rootPrintBuffer, paperSize, options, newContainerChain, context);
547
553
  originX = newOrigin.originX;
548
554
  originY = newOrigin.originY;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softwear/latestcollectioncore",
3
- "version": "1.0.186",
3
+ "version": "1.0.188",
4
4
  "description": "Core functions for LatestCollections applications",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/index.ts CHANGED
@@ -14,6 +14,7 @@ export { default as hasOnlyDigits } from './hasOnlyDigits'
14
14
  export { default as imageBinder } from './imageBinder'
15
15
  export { default as isean13 } from './isean13'
16
16
  export { default as pivotTable } from './pivotTable'
17
+ export { default as projectObject } from './projectObject'
17
18
  export { default as reports, genPDF } from './reports'
18
19
  export { default as round2 } from './round2'
19
20
  export { default as sizeToMap } from './sizeToMap'
@@ -0,0 +1,16 @@
1
+ import deepCopy from './deepCopy'
2
+
3
+ /**
4
+ * Whitelist projection: builds a new object from a deep-cloned copy of `source`,
5
+ * copying only the listed property names (nested values are cloned with `source`).
6
+ */
7
+ export default function projectObject<K extends string>(source: unknown, keys: readonly K[]): Record<K, unknown> {
8
+ const out = {} as Record<K, unknown>
9
+ if (source == null) return out
10
+ if (typeof source !== 'object') return out
11
+ const tmp = deepCopy(source) as Record<string, unknown>
12
+ for (const k of keys) {
13
+ out[k] = tmp[k]
14
+ }
15
+ return out
16
+ }
package/src/reports.ts CHANGED
@@ -50,12 +50,12 @@ interface RenderContext {
50
50
  defaultFontFamily?: string
51
51
  }
52
52
 
53
- /** Measurement uses context `currentPageNumber` (1-based). Rendering normalizes jsPDF’s internal 0-based page index to 1-based so overlap rules match `pageNumber` fields. */
53
+ /** Measurement uses context `currentPageNumber` (1-based). Rendering uses jsPDF’s `getCurrentPageInfo().pageNumber`, which is already 1-based (first page is 1). */
54
54
  function getCurrentPageNumber(doc: jsPDF, context: RenderContext): number {
55
55
  if (context.mode === 'measurement') {
56
56
  return context.currentPageNumber ?? 1
57
57
  }
58
- return doc.getCurrentPageInfo().pageNumber + 1
58
+ return doc.getCurrentPageInfo().pageNumber
59
59
  }
60
60
 
61
61
  // We have to declare some functions that will be called by other functions but also have to call those other functions
@@ -585,11 +585,16 @@ addObjectToPDF = function (
585
585
  const layoutXtenths = originX + object.x
586
586
  const layoutYtenths = originY + object.y
587
587
  const rawPrintOnlyAtStartOffset = printOnlyAtStartContainersOffset ?? 0
588
- const effectivePrintOnlyAtStartContainersOffset =
589
- containerChain.length === 0 && rawPrintOnlyAtStartOffset > 0 && getCurrentPageNumber(doc, context) === 1 ? rawPrintOnlyAtStartOffset : 0
588
+ /** Must consult current page on every read: `addPage` can move to page 2+ mid-invocation while this call stays open. */
589
+ const effectivePrintOnlyAtStartContainersOffsetNow = (): number =>
590
+ containerChain.length === 0 &&
591
+ rawPrintOnlyAtStartOffset > 0 &&
592
+ getCurrentPageNumber(doc, context) === 1
593
+ ? rawPrintOnlyAtStartOffset
594
+ : 0
590
595
 
591
596
  const x = layoutXtenths / 10
592
- const y = (layoutYtenths + effectivePrintOnlyAtStartContainersOffset) / 10
597
+ const y = (layoutYtenths + effectivePrintOnlyAtStartContainersOffsetNow()) / 10
593
598
  const width = object.width / 10
594
599
  const height = object.height / 10
595
600
  // Keep track of the lower righthandside of all objects in this container
@@ -613,7 +618,7 @@ addObjectToPDF = function (
613
618
  const nrContainers = source.length
614
619
 
615
620
  let originX = layoutXtenths
616
- let originY = layoutYtenths + effectivePrintOnlyAtStartContainersOffset
621
+ let originY = layoutYtenths + effectivePrintOnlyAtStartContainersOffsetNow()
617
622
 
618
623
  for (let containerIndex = 0; containerIndex < nrContainers; containerIndex++) {
619
624
  const newContainerChain = containerChain.filter(function () {
@@ -626,7 +631,8 @@ addObjectToPDF = function (
626
631
  if (useOrphanCheck && (object.pageBreak || originY + minHeightMm > paperSize.height - paperSize.footerHeight)) {
627
632
  // We ran out of paper
628
633
  originX = layoutXtenths
629
- originY = layoutYtenths + effectivePrintOnlyAtStartContainersOffset
634
+ // Continuation sheets must not reuse the page-1-only overlap bump: addPage hasn't run yet so getCurrentPageNumber is still 1.
635
+ originY = layoutYtenths
630
636
  const newOrigin = addPage(originX, originY, doc, layout, rootPrintBuffer, paperSize, options, newContainerChain, context)
631
637
  originX = newOrigin.originX
632
638
  originY = newOrigin.originY
@@ -0,0 +1,25 @@
1
+ const { deepCopy, projectObject } = require('../dist/index')
2
+
3
+ describe('projectObject', function () {
4
+ it('returns an empty object for null/undefined', function () {
5
+ expect(projectObject(null, ['a'])).toEqual({})
6
+ expect(projectObject(undefined, ['a'])).toEqual({})
7
+ })
8
+ it('returns an empty object for non-object primitives', function () {
9
+ expect(projectObject('x', ['a'])).toEqual({})
10
+ expect(projectObject(1, ['a'])).toEqual({})
11
+ })
12
+ it('copies only listed keys from a deep-cloned source', function () {
13
+ const src = { id: '1', name: 'n', extra: 'drop', nest: { x: 1 } }
14
+ const p = projectObject(src, ['id', 'nest'])
15
+ expect(p).toEqual({ id: '1', nest: { x: 1 } })
16
+ expect(p.nest).not.toBe(src.nest)
17
+ expect(deepCopy(src.nest)).toEqual(p.nest)
18
+ })
19
+ it('does not mutate the original when copying nested data', function () {
20
+ const src = { a: { b: 1 } }
21
+ const p = projectObject(src, ['a'])
22
+ p.a.b = 2
23
+ expect(src.a.b).toBe(1)
24
+ })
25
+ })