From 6818177e919b727997f94bcbd24060159d2420f7 Mon Sep 17 00:00:00 2001
From: Jan Kowalleck <jan.kowalleck@gmail.com>
Date: Sat, 10 Sep 2022 12:00:13 +0200
Subject: [PATCH 1/2] use rollup to build `esm` and `cjs`

Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
---
 .github/workflows/nodejs.yml                  |   4 +-
 .npmignore                                    |   2 +
 .../{index.js => index.cjs}                   |   2 +-
 libs/universal-node-xml/package.json          |   9 ++
 .../stringifiers/{helpers.js => helpers.cjs}  |   0
 .../{xmlbuilder2.js => xmlbuilder2.cjs}       |   2 +-
 ...lbuilder2.spec.js => xmlbuilder2.spec.cjs} |   2 +-
 package-lock.json                             | 140 +++++++++++++++++-
 package.json                                  |   9 +-
 rollup.config.js                              |  54 +++++++
 src/resources.node.ts                         |  30 ++--
 src/serialize/xmlSerializer.node.ts           |   3 +-
 tsconfig.base.json                            | 108 ++++++++++++++
 tsconfig.json                                 | 107 +------------
 tsconfig.node.json                            |   5 +-
 tsconfig.web.json                             |   8 +-
 16 files changed, 346 insertions(+), 139 deletions(-)
 rename libs/universal-node-xml/{index.js => index.cjs} (95%)
 create mode 100644 libs/universal-node-xml/package.json
 rename libs/universal-node-xml/stringifiers/{helpers.js => helpers.cjs} (100%)
 rename libs/universal-node-xml/stringifiers/{xmlbuilder2.js => xmlbuilder2.cjs} (96%)
 rename libs/universal-node-xml/stringifiers/{xmlbuilder2.spec.js => xmlbuilder2.spec.cjs} (98%)
 create mode 100644 rollup.config.js
 create mode 100644 tsconfig.base.json

diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml
index daf3f4ebe..c5731b11e 100644
--- a/.github/workflows/nodejs.yml
+++ b/.github/workflows/nodejs.yml
@@ -2,7 +2,7 @@
 
 name: Node CI
 
-on: 
+on:
   push:
     branches: [ main ]
   pull_request:
@@ -78,7 +78,7 @@ jobs:
           - "16"      # active LTS
           - "14"
           - "14.0.0"  # lowest supported
-        os: 
+        os:
           - ubuntu-latest
           - macos-latest
           - windows-latest
diff --git a/.npmignore b/.npmignore
index add453b08..a0452c0ca 100644
--- a/.npmignore
+++ b/.npmignore
@@ -160,9 +160,11 @@ dist
 # TypeScript source files are intended to be shipped,
 # as they provide definition context and typing for downstream users.
 # The compiler configs are shipped, so downstream users can inherit from them.
+# So the result is a mix of binary- and source-distribution.
 !/src/
 !/tsconfig.*
 !/webpack.*
+!/rollup.*
 
 /test/
 /tests/
diff --git a/libs/universal-node-xml/index.js b/libs/universal-node-xml/index.cjs
similarity index 95%
rename from libs/universal-node-xml/index.js
rename to libs/universal-node-xml/index.cjs
index aa6e88b53..fe34f0307 100644
--- a/libs/universal-node-xml/index.js
+++ b/libs/universal-node-xml/index.cjs
@@ -27,7 +27,7 @@ module.exports.stringify = undefined
 let possibleStringifier
 for (const file of possibleStringifiers) {
   try {
-    possibleStringifier = require(`./stringifiers/${file}`)
+    possibleStringifier = require(`./stringifiers/${file}.cjs`)
     if (typeof possibleStringifier === 'function') {
       module.exports.stringify = possibleStringifier
       break
diff --git a/libs/universal-node-xml/package.json b/libs/universal-node-xml/package.json
new file mode 100644
index 000000000..3134a5b36
--- /dev/null
+++ b/libs/universal-node-xml/package.json
@@ -0,0 +1,9 @@
+{
+  "private": true,
+  "type": "commonjs",
+  "main": "./index.cjs",
+  "types": "./index.d.ts",
+  "optionalDependencies": {
+    "xmlbuilder2": "^3.0.2"
+  }
+}
diff --git a/libs/universal-node-xml/stringifiers/helpers.js b/libs/universal-node-xml/stringifiers/helpers.cjs
similarity index 100%
rename from libs/universal-node-xml/stringifiers/helpers.js
rename to libs/universal-node-xml/stringifiers/helpers.cjs
diff --git a/libs/universal-node-xml/stringifiers/xmlbuilder2.js b/libs/universal-node-xml/stringifiers/xmlbuilder2.cjs
similarity index 96%
rename from libs/universal-node-xml/stringifiers/xmlbuilder2.js
rename to libs/universal-node-xml/stringifiers/xmlbuilder2.cjs
index 0832bfaa3..661b52387 100644
--- a/libs/universal-node-xml/stringifiers/xmlbuilder2.js
+++ b/libs/universal-node-xml/stringifiers/xmlbuilder2.cjs
@@ -19,7 +19,7 @@ Copyright (c) OWASP Foundation. All Rights Reserved.
 */
 
 const { create } = require('xmlbuilder2')
-const { getNS, makeIndent } = require('./helpers')
+const { getNS, makeIndent } = require('./helpers.cjs')
 
 module.exports = typeof create === 'function'
   ? stringify
diff --git a/libs/universal-node-xml/stringifiers/xmlbuilder2.spec.js b/libs/universal-node-xml/stringifiers/xmlbuilder2.spec.cjs
similarity index 98%
rename from libs/universal-node-xml/stringifiers/xmlbuilder2.spec.js
rename to libs/universal-node-xml/stringifiers/xmlbuilder2.spec.cjs
index 5fb83a566..619e4b2eb 100644
--- a/libs/universal-node-xml/stringifiers/xmlbuilder2.spec.js
+++ b/libs/universal-node-xml/stringifiers/xmlbuilder2.spec.cjs
@@ -21,7 +21,7 @@ Copyright (c) OWASP Foundation. All Rights Reserved.
 const assert = require('assert')
 const { suite, test } = require('mocha')
 
-const stringify = require('./xmlbuilder2')
+const stringify = require('./xmlbuilder2.cjs')
 
 suite('stringify with xmlbuilder2', () => {
   assert.strictEqual(typeof stringify, 'function')
diff --git a/package-lock.json b/package-lock.json
index bfd4d6b51..d21e15176 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,6 +12,7 @@
         "packageurl-js": ">=0.0.6 <0.0.8 || ^1"
       },
       "devDependencies": {
+        "@rollup/plugin-typescript": "^8.5.0",
         "@types/mocha": "^9.1.1",
         "@types/node": ">=14",
         "@types/webpack": "^5.28.0",
@@ -21,7 +22,9 @@
         "eslint-plugin-simple-import-sort": "^8.0.0",
         "mocha": "10.0.0",
         "npm-run-all": "^4.1.5",
+        "rollup": "^2.79.0",
         "ts-loader": "9.3.1",
+        "tslib": "^2.4.0",
         "typescript": "4.8.2",
         "webpack": "5.74.0",
         "webpack-cli": "4.10.0",
@@ -250,6 +253,52 @@
         "node": ">=8.0"
       }
     },
+    "node_modules/@rollup/plugin-typescript": {
+      "version": "8.5.0",
+      "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.5.0.tgz",
+      "integrity": "sha512-wMv1/scv0m/rXx21wD2IsBbJFba8wGF3ErJIr6IKRfRj49S85Lszbxb4DCo8iILpluTjk2GAAu9CoZt4G3ppgQ==",
+      "dev": true,
+      "dependencies": {
+        "@rollup/pluginutils": "^3.1.0",
+        "resolve": "^1.17.0"
+      },
+      "engines": {
+        "node": ">=8.0.0"
+      },
+      "peerDependencies": {
+        "rollup": "^2.14.0",
+        "tslib": "*",
+        "typescript": ">=3.7.0"
+      },
+      "peerDependenciesMeta": {
+        "tslib": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@rollup/pluginutils": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
+      "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
+      "dev": true,
+      "dependencies": {
+        "@types/estree": "0.0.39",
+        "estree-walker": "^1.0.1",
+        "picomatch": "^2.2.2"
+      },
+      "engines": {
+        "node": ">= 8.0.0"
+      },
+      "peerDependencies": {
+        "rollup": "^1.20.0||^2.0.0"
+      }
+    },
+    "node_modules/@rollup/pluginutils/node_modules/@types/estree": {
+      "version": "0.0.39",
+      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
+      "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
+      "dev": true
+    },
     "node_modules/@types/eslint": {
       "version": "8.4.6",
       "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.6.tgz",
@@ -1814,6 +1863,12 @@
         "node": ">=4.0"
       }
     },
+    "node_modules/estree-walker": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
+      "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
+      "dev": true
+    },
     "node_modules/esutils": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
@@ -3661,6 +3716,21 @@
         "url": "https://github.com/sponsors/isaacs"
       }
     },
+    "node_modules/rollup": {
+      "version": "2.79.0",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.0.tgz",
+      "integrity": "sha512-x4KsrCgwQ7ZJPcFA/SUu6QVcYlO7uRLfLAy0DSA4NS2eG8japdbpM50ToH7z4iObodRYOJ0soneF0iaQRJ6zhA==",
+      "dev": true,
+      "bin": {
+        "rollup": "dist/bin/rollup"
+      },
+      "engines": {
+        "node": ">=10.0.0"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.2"
+      }
+    },
     "node_modules/run-parallel": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -4093,9 +4163,9 @@
       }
     },
     "node_modules/tslib": {
-      "version": "1.14.1",
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
-      "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
+      "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
       "dev": true
     },
     "node_modules/tsutils": {
@@ -4113,6 +4183,12 @@
         "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
       }
     },
+    "node_modules/tsutils/node_modules/tslib": {
+      "version": "1.14.1",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+      "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+      "dev": true
+    },
     "node_modules/type-check": {
       "version": "0.4.0",
       "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -4695,6 +4771,35 @@
       "integrity": "sha512-T8TbSnGsxo6TDBJx/Sgv/BlVJL3tshxZP7Aq5R1mSnM5OcHY2dQaxLMu2+E8u3gN0MLOzdjurqN4ZRVuzQycOQ==",
       "dev": true
     },
+    "@rollup/plugin-typescript": {
+      "version": "8.5.0",
+      "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.5.0.tgz",
+      "integrity": "sha512-wMv1/scv0m/rXx21wD2IsBbJFba8wGF3ErJIr6IKRfRj49S85Lszbxb4DCo8iILpluTjk2GAAu9CoZt4G3ppgQ==",
+      "dev": true,
+      "requires": {
+        "@rollup/pluginutils": "^3.1.0",
+        "resolve": "^1.17.0"
+      }
+    },
+    "@rollup/pluginutils": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
+      "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
+      "dev": true,
+      "requires": {
+        "@types/estree": "0.0.39",
+        "estree-walker": "^1.0.1",
+        "picomatch": "^2.2.2"
+      },
+      "dependencies": {
+        "@types/estree": {
+          "version": "0.0.39",
+          "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
+          "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
+          "dev": true
+        }
+      }
+    },
     "@types/eslint": {
       "version": "8.4.6",
       "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.6.tgz",
@@ -5852,6 +5957,12 @@
       "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
       "dev": true
     },
+    "estree-walker": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
+      "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
+      "dev": true
+    },
     "esutils": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
@@ -7197,6 +7308,15 @@
         "glob": "^7.1.3"
       }
     },
+    "rollup": {
+      "version": "2.79.0",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.0.tgz",
+      "integrity": "sha512-x4KsrCgwQ7ZJPcFA/SUu6QVcYlO7uRLfLAy0DSA4NS2eG8japdbpM50ToH7z4iObodRYOJ0soneF0iaQRJ6zhA==",
+      "dev": true,
+      "requires": {
+        "fsevents": "~2.3.2"
+      }
+    },
     "run-parallel": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -7494,9 +7614,9 @@
       }
     },
     "tslib": {
-      "version": "1.14.1",
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
-      "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
+      "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
       "dev": true
     },
     "tsutils": {
@@ -7506,6 +7626,14 @@
       "dev": true,
       "requires": {
         "tslib": "^1.8.1"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "1.14.1",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+          "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+          "dev": true
+        }
       }
     },
     "type-check": {
diff --git a/package.json b/package.json
index 1bb611f90..51897831f 100644
--- a/package.json
+++ b/package.json
@@ -45,6 +45,7 @@
     "xmlbuilder2": "^3.0.2"
   },
   "devDependencies": {
+    "@rollup/plugin-typescript": "^8.5.0",
     "@types/mocha": "^9.1.1",
     "@types/node": ">=14",
     "@types/webpack": "^5.28.0",
@@ -54,7 +55,9 @@
     "eslint-plugin-simple-import-sort": "^8.0.0",
     "mocha": "10.0.0",
     "npm-run-all": "^4.1.5",
+    "rollup": "^2.79.0",
     "ts-loader": "9.3.1",
+    "tslib": "^2.4.0",
     "typescript": "4.8.2",
     "webpack": "5.74.0",
     "webpack-cli": "4.10.0",
@@ -62,8 +65,8 @@
   },
   "browser": "./dist.web/lib.js",
   "types": "./src/index.node.ts",
-  "main": "./dist.node/index.node.js",
-  "exports": "./dist.node/index.node.js",
+  "main": "./dist.node/lib.cjs",
+  "module": "./dist.node/lib.mjs",
   "directories": {
     "doc": "./docs",
     "src": "./src",
@@ -77,7 +80,7 @@
     "lint": "tsc --noEmit",
     "build": "run-p --aggregate-output -l build:*",
     "prebuild:node": "node -r fs -e 'fs.rmSync(\"dist.node\",{recursive:true,force:true})'",
-    "build:node": "tsc -b ./tsconfig.node.json",
+    "build:node": "rollup -c rollup.config.js",
     "prebuild:web": "node -r fs -e 'fs.rmSync(\"dist.web\",{recursive:true,force:true})'",
     "build:web": "webpack build",
     "cs-fix": "eslint --fix .",
diff --git a/rollup.config.js b/rollup.config.js
new file mode 100644
index 000000000..8c609267e
--- /dev/null
+++ b/rollup.config.js
@@ -0,0 +1,54 @@
+const typescript = require('@rollup/plugin-typescript')
+
+/**
+ * @see {@link https://rollupjs.org}
+ * @type {import('rollup').RollupOptions}
+ */
+module.exports = {
+  input: 'src/index.node.ts',
+  external: [
+    // region own shipped
+    /\.\/(?:libs|res)\//,
+    // endregion own shipped
+    // region externals dependencies
+    'packageurl-js'
+    // endregion externals dependencies
+  ],
+  treeshake: false,
+  output: [
+    {
+      file: 'dist.node/lib.cjs',
+      format: 'cjs',
+      strict: true,
+      sourcemap: false,
+      compact: true
+    },
+    {
+      file: 'dist.node/lib.dev.cjs',
+      format: 'cjs',
+      strict: true,
+      sourcemap: true,
+      compact: false
+    },
+    {
+      file: 'dist.node/lib.mjs',
+      format: 'esm',
+      strict: true,
+      sourcemap: false,
+      compact: true
+    },
+    {
+      file: 'dist.node/lib.dev.mjs',
+      format: 'esm',
+      strict: true,
+      sourcemap: true,
+      compact: false
+    }
+  ],
+  plugins: [
+    typescript({
+      tsconfig: 'tsconfig.node.json',
+      sourceMap: true
+    })
+  ]
+}
diff --git a/src/resources.node.ts b/src/resources.node.ts
index a67030a79..dd0ac88c7 100644
--- a/src/resources.node.ts
+++ b/src/resources.node.ts
@@ -17,43 +17,43 @@ SPDX-License-Identifier: Apache-2.0
 Copyright (c) OWASP Foundation. All Rights Reserved.
 */
 
-import path from 'path'
+import { resolve } from 'path'
 
 import { Version } from './spec'
 
 /** @internal */
-export const ROOT = path.resolve(__dirname, '..', 'res')
+export const ROOT = resolve(__dirname, '..', 'res')
 
 /** @internal */
 export const FILES = Object.freeze({
   CDX: Object.freeze({
     XML_SCHEMA: Object.freeze(Object.fromEntries([
-      [Version.v1dot0, path.resolve(ROOT, 'bom-1.0.SNAPSHOT.xsd')],
-      [Version.v1dot1, path.resolve(ROOT, 'bom-1.1.SNAPSHOT.xsd')],
-      [Version.v1dot2, path.resolve(ROOT, 'bom-1.2.SNAPSHOT.xsd')],
-      [Version.v1dot3, path.resolve(ROOT, 'bom-1.3.SNAPSHOT.xsd')],
-      [Version.v1dot4, path.resolve(ROOT, 'bom-1.4.SNAPSHOT.xsd')]
+      [Version.v1dot0, resolve(ROOT, 'bom-1.0.SNAPSHOT.xsd')],
+      [Version.v1dot1, resolve(ROOT, 'bom-1.1.SNAPSHOT.xsd')],
+      [Version.v1dot2, resolve(ROOT, 'bom-1.2.SNAPSHOT.xsd')],
+      [Version.v1dot3, resolve(ROOT, 'bom-1.3.SNAPSHOT.xsd')],
+      [Version.v1dot4, resolve(ROOT, 'bom-1.4.SNAPSHOT.xsd')]
     ]) as { [key in Version]?: string }),
     JSON_SCHEMA: Object.freeze(Object.fromEntries([
       // v1.0 is not defined in JSON
       // v1.1 is not defined in JSON
-      [Version.v1dot2, path.resolve(ROOT, 'bom-1.2.SNAPSHOT.schema.json')],
-      [Version.v1dot3, path.resolve(ROOT, 'bom-1.3.SNAPSHOT.schema.json')],
-      [Version.v1dot4, path.resolve(ROOT, 'bom-1.4.SNAPSHOT.schema.json')]
+      [Version.v1dot2, resolve(ROOT, 'bom-1.2.SNAPSHOT.schema.json')],
+      [Version.v1dot3, resolve(ROOT, 'bom-1.3.SNAPSHOT.schema.json')],
+      [Version.v1dot4, resolve(ROOT, 'bom-1.4.SNAPSHOT.schema.json')]
     ]) as { [key in Version]?: string }),
     JSON_STRICT_SCHEMA: Object.freeze(Object.fromEntries([
       // v1.0 is not defined in JSON
       // v1.1 is not defined in JSON
-      [Version.v1dot2, path.resolve(ROOT, 'bom-1.2-strict.SNAPSHOT.schema.json')],
-      [Version.v1dot3, path.resolve(ROOT, 'bom-1.3-strict.SNAPSHOT.schema.json')]
+      [Version.v1dot2, resolve(ROOT, 'bom-1.2-strict.SNAPSHOT.schema.json')],
+      [Version.v1dot3, resolve(ROOT, 'bom-1.3-strict.SNAPSHOT.schema.json')]
       // v1.4 is already strict - no special file here
     ]) as { [key in Version]?: string })
   }),
   SPDX: Object.freeze({
-    XML_SCHEMA: path.resolve(ROOT, 'spdx.SNAPSHOT.xsd'),
-    JSON_SCHEMA: path.resolve(ROOT, 'spdx.SNAPSHOT.schema.json')
+    XML_SCHEMA: resolve(ROOT, 'spdx.SNAPSHOT.xsd'),
+    JSON_SCHEMA: resolve(ROOT, 'spdx.SNAPSHOT.schema.json')
   }),
   JSF: Object.freeze({
-    JSON_SCHEMA: path.resolve(ROOT, 'jsf-0.82.SNAPSHOT.schema.json')
+    JSON_SCHEMA: resolve(ROOT, 'jsf-0.82.SNAPSHOT.schema.json')
   })
 })
diff --git a/src/serialize/xmlSerializer.node.ts b/src/serialize/xmlSerializer.node.ts
index b548cb443..8f54b333a 100644
--- a/src/serialize/xmlSerializer.node.ts
+++ b/src/serialize/xmlSerializer.node.ts
@@ -17,7 +17,8 @@ SPDX-License-Identifier: Apache-2.0
 Copyright (c) OWASP Foundation. All Rights Reserved.
 */
 
-import { stringifyFallback } from '../../libs/universal-node-xml'
+// @ts-ignore
+import { stringifyFallback } from '../../libs/universal-node-xml/index.cjs'
 import { SerializerOptions } from './types'
 import { SimpleXml } from './xml/types'
 import { XmlBaseSerializer } from './xmlBaseSerializer'
diff --git a/tsconfig.base.json b/tsconfig.base.json
new file mode 100644
index 000000000..302d74b59
--- /dev/null
+++ b/tsconfig.base.json
@@ -0,0 +1,108 @@
+{
+  "$schema": "https://json.schemastore.org/tsconfig",
+  "compilerOptions": {
+    /* Visit https://aka.ms/tsconfig.resolveJsonModule to read more about this file */
+
+    /* Projects */
+    // "incremental": true,                              /* Enable incremental compilation */
+    // "composite": true,                                /* Enable constraints that allow a TypeScript project to be used with project references. */
+    // "tsBuildInfoFile": "./",                          /* Specify the folder for .tsbuildinfo incremental compilation files. */
+    // "disableSourceOfProjectReferenceRedirect": true,  /* Disable preferring source files instead of declaration files when referencing composite projects */
+    // "disableSolutionSearching": true,                 /* Opt a project out of multi-project reference checking when editing. */
+    // "disableReferencedProjectLoad": true,             /* Reduce the number of projects loaded automatically by TypeScript. */
+
+    /* Language and Environment */
+    /* check compat: https://node.green/ */
+    "target": "ES2020",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
+    // "lib": [],                                        /* Specify a set of bundled library declaration files that describe the target runtime environment. */
+    // "jsx": "preserve",                                /* Specify what JSX code is generated. */
+    // "experimentalDecorators": true,                   /* Enable experimental support for TC39 stage 2 draft decorators. */
+    // "emitDecoratorMetadata": true,                    /* Emit design-type metadata for decorated declarations in source files. */
+    // "jsxFactory": "",                                 /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
+    // "jsxFragmentFactory": "",                         /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
+    // "jsxImportSource": "",                            /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
+    // "reactNamespace": "",                             /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
+    // "noLib": true,                                    /* Disable including any library files, including the default lib.d.ts. */
+    // "useDefineForClassFields": true,                  /* Emit ECMAScript-standard-compliant class fields. */
+
+    /* Modules */
+    /* check compat: https://node.green/ */
+    "module": "CommonJS",                                /* Specify what module code is generated. */
+    "rootDir": "src",                               /* Specify the root folder within your source files. */
+    "moduleResolution": "Node",                       /* Specify how TypeScript looks up a file from a given module specifier. */
+    // "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */
+    // "paths": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */
+    // "rootDirs": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */
+    // "typeRoots": [],                                  /* Specify multiple folders that act like `./node_modules/@types`. */
+    // "types": [],                                      /* Specify type package names to be included without being referenced in a source file. */
+    // "allowUmdGlobalAccess": true,                     /* Allow accessing UMD globals from modules. */
+    "resolveJsonModule": true,                        /* Enable importing .json files */
+    // "noResolve": true,                                /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
+
+    /* JavaScript Support */
+    "allowJs": false,                                  /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
+    // "checkJs": true,                                  /* Enable error reporting in type-checked JavaScript files. */
+    // "maxNodeModuleJsDepth": 1,                        /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
+
+    /* Emit */
+    "declaration": false,                              /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
+    // "declarationMap": true,                           /* Create sourcemaps for d.ts files. */
+    // "emitDeclarationOnly": true,                      /* Only output d.ts files and not JavaScript files. */
+    "sourceMap": true,                                /* Create source map files for emitted JavaScript files. */
+    // "outFile": "./",                                  /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
+    // "outDir": "./dist/",                                   /* Specify an output folder for all emitted files. */
+    "removeComments": true,                           /* Disable emitting comments. */
+    // "noEmit": true,                                   /* Disable emitting files from a compilation. */
+    // "importHelpers": true,                            /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
+    // "importsNotUsedAsValues": "remove",               /* Specify emit/checking behavior for imports that are only used for types */
+    // "downlevelIteration": true,                       /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
+    // "sourceRoot": "",                                 /* Specify the root path for debuggers to find the reference source code. */
+    // "mapRoot": "",                                    /* Specify the location where debugger should locate map files instead of generated locations. */
+    // "inlineSourceMap": true,                          /* Include sourcemap files inside the emitted JavaScript. */
+    // "inlineSources": true,                            /* Include source code in the sourcemaps inside the emitted JavaScript. */
+    // "emitBOM": true,                                  /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
+    "newLine": "lf",                                /* Set the newline character for emitting files. */
+    "stripInternal": false,                            /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
+    // "noEmitHelpers": true,                            /* Disable generating custom helper functions like `__extends` in compiled output. */
+    // "noEmitOnError": true,                            /* Disable emitting files if any type checking errors are reported. */
+    // "preserveConstEnums": true,                       /* Disable erasing `const enum` declarations in generated code. */
+    // "declarationDir": "./",                           /* Specify the output directory for generated declaration files. */
+    // "preserveValueImports": true,                     /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
+
+    /* Interop Constraints */
+    "isolatedModules": true,                          /* Ensure that each file can be safely transpiled without relying on other imports. */
+    "allowSyntheticDefaultImports": true,             /* Allow 'import x from y' when a module doesn't have a default export. */
+    "esModuleInterop": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */
+    // "preserveSymlinks": true,                         /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
+    "forceConsistentCasingInFileNames": true,            /* Ensure that casing is correct in imports. */
+
+    /* Type Checking */
+    "strict": true,                                      /* Enable all strict type-checking options. */
+    "noImplicitAny": true,                            /* Enable error reporting for expressions and declarations with an implied `any` type.. */
+    "strictNullChecks": true,                         /* When type checking, take into account `null` and `undefined`. */
+    "strictFunctionTypes": true,                      /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
+    "strictBindCallApply": true,                      /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
+    "strictPropertyInitialization": true,             /* Check for class properties that are declared but not set in the constructor. */
+    "noImplicitThis": true,                           /* Enable error reporting when `this` is given the type `any`. */
+    // "useUnknownInCatchVariables": true,               /* Type catch clause variables as 'unknown' instead of 'any'. */
+    "alwaysStrict": true,                             /* Ensure 'use strict' is always emitted. */
+    "noUnusedLocals": true,                           /* Enable error reporting when a local variables aren't read. */
+    // "noUnusedParameters": true,                       /* Raise an error when a function parameter isn't read */
+    // "exactOptionalPropertyTypes": true,               /* Interpret optional property types as written, rather than adding 'undefined'. */
+    "noImplicitReturns": true,                        /* Enable error reporting for codepaths that do not explicitly return in a function. */
+    "noFallthroughCasesInSwitch": true,               /* Enable error reporting for fallthrough cases in switch statements. */
+    // "noUncheckedIndexedAccess": true,                 /* Include 'undefined' in index signature results */
+    "noImplicitOverride": true,                       /* Ensure overriding members in derived classes are marked with an override modifier. */
+    // "noPropertyAccessFromIndexSignature": true,       /* Enforces using indexed accessors for keys declared using an indexed type */
+    // "allowUnusedLabels": true,                        /* Disable error reporting for unused labels. */
+    "allowUnreachableCode": false,                     /* Disable error reporting for unreachable code. */
+
+    /* Completeness */
+    "skipDefaultLibCheck": false,                      /* Skip type checking .d.ts files that are included with TypeScript. */
+    "skipLibCheck": false                                 /* Skip type checking all .d.ts files. */
+  },
+  "exclude": [
+    "node_modules",
+    "**/*.spec.ts", "**/*.test.ts"
+  ]
+}
diff --git a/tsconfig.json b/tsconfig.json
index 302d74b59..316211fc0 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,108 +1,5 @@
 {
   "$schema": "https://json.schemastore.org/tsconfig",
-  "compilerOptions": {
-    /* Visit https://aka.ms/tsconfig.resolveJsonModule to read more about this file */
-
-    /* Projects */
-    // "incremental": true,                              /* Enable incremental compilation */
-    // "composite": true,                                /* Enable constraints that allow a TypeScript project to be used with project references. */
-    // "tsBuildInfoFile": "./",                          /* Specify the folder for .tsbuildinfo incremental compilation files. */
-    // "disableSourceOfProjectReferenceRedirect": true,  /* Disable preferring source files instead of declaration files when referencing composite projects */
-    // "disableSolutionSearching": true,                 /* Opt a project out of multi-project reference checking when editing. */
-    // "disableReferencedProjectLoad": true,             /* Reduce the number of projects loaded automatically by TypeScript. */
-
-    /* Language and Environment */
-    /* check compat: https://node.green/ */
-    "target": "ES2020",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
-    // "lib": [],                                        /* Specify a set of bundled library declaration files that describe the target runtime environment. */
-    // "jsx": "preserve",                                /* Specify what JSX code is generated. */
-    // "experimentalDecorators": true,                   /* Enable experimental support for TC39 stage 2 draft decorators. */
-    // "emitDecoratorMetadata": true,                    /* Emit design-type metadata for decorated declarations in source files. */
-    // "jsxFactory": "",                                 /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
-    // "jsxFragmentFactory": "",                         /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
-    // "jsxImportSource": "",                            /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
-    // "reactNamespace": "",                             /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
-    // "noLib": true,                                    /* Disable including any library files, including the default lib.d.ts. */
-    // "useDefineForClassFields": true,                  /* Emit ECMAScript-standard-compliant class fields. */
-
-    /* Modules */
-    /* check compat: https://node.green/ */
-    "module": "CommonJS",                                /* Specify what module code is generated. */
-    "rootDir": "src",                               /* Specify the root folder within your source files. */
-    "moduleResolution": "Node",                       /* Specify how TypeScript looks up a file from a given module specifier. */
-    // "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */
-    // "paths": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */
-    // "rootDirs": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */
-    // "typeRoots": [],                                  /* Specify multiple folders that act like `./node_modules/@types`. */
-    // "types": [],                                      /* Specify type package names to be included without being referenced in a source file. */
-    // "allowUmdGlobalAccess": true,                     /* Allow accessing UMD globals from modules. */
-    "resolveJsonModule": true,                        /* Enable importing .json files */
-    // "noResolve": true,                                /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
-
-    /* JavaScript Support */
-    "allowJs": false,                                  /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
-    // "checkJs": true,                                  /* Enable error reporting in type-checked JavaScript files. */
-    // "maxNodeModuleJsDepth": 1,                        /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
-
-    /* Emit */
-    "declaration": false,                              /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
-    // "declarationMap": true,                           /* Create sourcemaps for d.ts files. */
-    // "emitDeclarationOnly": true,                      /* Only output d.ts files and not JavaScript files. */
-    "sourceMap": true,                                /* Create source map files for emitted JavaScript files. */
-    // "outFile": "./",                                  /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
-    // "outDir": "./dist/",                                   /* Specify an output folder for all emitted files. */
-    "removeComments": true,                           /* Disable emitting comments. */
-    // "noEmit": true,                                   /* Disable emitting files from a compilation. */
-    // "importHelpers": true,                            /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
-    // "importsNotUsedAsValues": "remove",               /* Specify emit/checking behavior for imports that are only used for types */
-    // "downlevelIteration": true,                       /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
-    // "sourceRoot": "",                                 /* Specify the root path for debuggers to find the reference source code. */
-    // "mapRoot": "",                                    /* Specify the location where debugger should locate map files instead of generated locations. */
-    // "inlineSourceMap": true,                          /* Include sourcemap files inside the emitted JavaScript. */
-    // "inlineSources": true,                            /* Include source code in the sourcemaps inside the emitted JavaScript. */
-    // "emitBOM": true,                                  /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
-    "newLine": "lf",                                /* Set the newline character for emitting files. */
-    "stripInternal": false,                            /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
-    // "noEmitHelpers": true,                            /* Disable generating custom helper functions like `__extends` in compiled output. */
-    // "noEmitOnError": true,                            /* Disable emitting files if any type checking errors are reported. */
-    // "preserveConstEnums": true,                       /* Disable erasing `const enum` declarations in generated code. */
-    // "declarationDir": "./",                           /* Specify the output directory for generated declaration files. */
-    // "preserveValueImports": true,                     /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
-
-    /* Interop Constraints */
-    "isolatedModules": true,                          /* Ensure that each file can be safely transpiled without relying on other imports. */
-    "allowSyntheticDefaultImports": true,             /* Allow 'import x from y' when a module doesn't have a default export. */
-    "esModuleInterop": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */
-    // "preserveSymlinks": true,                         /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
-    "forceConsistentCasingInFileNames": true,            /* Ensure that casing is correct in imports. */
-
-    /* Type Checking */
-    "strict": true,                                      /* Enable all strict type-checking options. */
-    "noImplicitAny": true,                            /* Enable error reporting for expressions and declarations with an implied `any` type.. */
-    "strictNullChecks": true,                         /* When type checking, take into account `null` and `undefined`. */
-    "strictFunctionTypes": true,                      /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
-    "strictBindCallApply": true,                      /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
-    "strictPropertyInitialization": true,             /* Check for class properties that are declared but not set in the constructor. */
-    "noImplicitThis": true,                           /* Enable error reporting when `this` is given the type `any`. */
-    // "useUnknownInCatchVariables": true,               /* Type catch clause variables as 'unknown' instead of 'any'. */
-    "alwaysStrict": true,                             /* Ensure 'use strict' is always emitted. */
-    "noUnusedLocals": true,                           /* Enable error reporting when a local variables aren't read. */
-    // "noUnusedParameters": true,                       /* Raise an error when a function parameter isn't read */
-    // "exactOptionalPropertyTypes": true,               /* Interpret optional property types as written, rather than adding 'undefined'. */
-    "noImplicitReturns": true,                        /* Enable error reporting for codepaths that do not explicitly return in a function. */
-    "noFallthroughCasesInSwitch": true,               /* Enable error reporting for fallthrough cases in switch statements. */
-    // "noUncheckedIndexedAccess": true,                 /* Include 'undefined' in index signature results */
-    "noImplicitOverride": true,                       /* Ensure overriding members in derived classes are marked with an override modifier. */
-    // "noPropertyAccessFromIndexSignature": true,       /* Enforces using indexed accessors for keys declared using an indexed type */
-    // "allowUnusedLabels": true,                        /* Disable error reporting for unused labels. */
-    "allowUnreachableCode": false,                     /* Disable error reporting for unreachable code. */
-
-    /* Completeness */
-    "skipDefaultLibCheck": false,                      /* Skip type checking .d.ts files that are included with TypeScript. */
-    "skipLibCheck": false                                 /* Skip type checking all .d.ts files. */
-  },
-  "exclude": [
-    "node_modules",
-    "**/*.spec.ts", "**/*.test.ts"
-  ]
+  "extends": "./tsconfig.base.json",
+  /* ground for IDE and other non-context-aware envs */
 }
diff --git a/tsconfig.node.json b/tsconfig.node.json
index 04eb6fc78..85c44e44d 100644
--- a/tsconfig.node.json
+++ b/tsconfig.node.json
@@ -1,8 +1,9 @@
 {
   "$schema": "https://json.schemastore.org/tsconfig",
-  "extends": "./tsconfig.json",
+  "extends": "./tsconfig.base.json",
   "files": ["src/index.node.ts"],
   "compilerOptions": {
-    "outDir": "./dist.node/"
+    "importHelpers": true,                            /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
   }
+  /* ground for rollup */
 }
diff --git a/tsconfig.web.json b/tsconfig.web.json
index 417454f8b..e3821a78e 100644
--- a/tsconfig.web.json
+++ b/tsconfig.web.json
@@ -1,5 +1,9 @@
 {
   "$schema": "https://json.schemastore.org/tsconfig",
-  "extends": "./tsconfig.json",
-  "files": ["src/index.web.ts"]
+  "extends": "./tsconfig.base.json",
+  "files": ["src/index.web.ts"],
+  "compilerOptions": {
+    "importHelpers": true,                            /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
+  }
+  /* ground for webpack */
 }

From 1e4ce26971e652f86562933467f74c84535ed6b7 Mon Sep 17 00:00:00 2001
From: Jan Kowalleck <jan.kowalleck@gmail.com>
Date: Sat, 10 Sep 2022 12:54:17 +0200
Subject: [PATCH 2/2] test with ESM

Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
---
 ...rs.FromNodePackageJson.ComponentBuilder.test.mjs} | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)
 rename tests/integration/{Builders.FromNodePackageJson.ComponentBuilder.test.js => Builders.FromNodePackageJson.ComponentBuilder.test.mjs} (91%)

diff --git a/tests/integration/Builders.FromNodePackageJson.ComponentBuilder.test.js b/tests/integration/Builders.FromNodePackageJson.ComponentBuilder.test.mjs
similarity index 91%
rename from tests/integration/Builders.FromNodePackageJson.ComponentBuilder.test.js
rename to tests/integration/Builders.FromNodePackageJson.ComponentBuilder.test.mjs
index 76a0acfcd..816f92865 100644
--- a/tests/integration/Builders.FromNodePackageJson.ComponentBuilder.test.js
+++ b/tests/integration/Builders.FromNodePackageJson.ComponentBuilder.test.mjs
@@ -18,15 +18,17 @@ SPDX-License-Identifier: Apache-2.0
 Copyright (c) OWASP Foundation. All Rights Reserved.
 */
 
-const assert = require('assert')
-const { suite, test } = require('mocha')
+import * as assert from 'assert'
+import { suite, test } from 'mocha'
 
-const {
+import {
   Enums,
   Models,
   Factories,
-  Builders: { FromNodePackageJson: { ComponentBuilder } }
-} = require('../../')
+  Builders
+} from '../../dist.node/lib.mjs'
+
+const ComponentBuilder = Builders.FromNodePackageJson
 
 suite('Builders.FromNodePackageJson.ComponentBuilder', () => {
   const salt = Math.random()