@opentermsarchive/engine 2.2.1 → 2.2.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opentermsarchive/engine",
3
- "version": "2.2.1",
3
+ "version": "2.2.2",
4
4
  "description": "Tracks and makes visible changes to the terms of online services",
5
5
  "homepage": "https://opentermsarchive.org",
6
6
  "bugs": {
@@ -99,7 +99,7 @@
99
99
  "simple-git": "^3.8.0",
100
100
  "swagger-jsdoc": "^6.2.8",
101
101
  "swagger-ui-express": "^5.0.0",
102
- "winston": "^3.3.3",
102
+ "winston": "^3.9.0",
103
103
  "winston-mail": "^2.0.0"
104
104
  },
105
105
  "devDependencies": {
@@ -28,7 +28,7 @@ const alignedWithColorsAndTime = combine(
28
28
  }),
29
29
  );
30
30
 
31
- const consoleTransport = new winston.transports.Console(({ silent: process.env.NODE_ENV === 'test' }));
31
+ const consoleTransport = new winston.transports.Console({ silent: process.env.NODE_ENV === 'test' });
32
32
 
33
33
  const transports = [consoleTransport];
34
34
 
@@ -36,6 +36,17 @@ const logger = winston.createLogger({
36
36
  format: alignedWithColorsAndTime,
37
37
  transports,
38
38
  rejectionHandlers: transports,
39
+ exitOnError: true,
40
+ });
41
+
42
+ logger.on('error', err => {
43
+ if ('smtp' in err) { // Check if err has an `smtp` property, even if it's undefined
44
+ logger.warn({ message: `Uncaught exception from SMTP mailer detected and treated as an operational error; process will continue running:\n${err.stack}` });
45
+
46
+ return; // Prevent process exit
47
+ }
48
+
49
+ return process.exit(1); // Exit process for other errors
39
50
  });
40
51
 
41
52
  if (config.get('@opentermsarchive/engine.logger.sendMailOnError')) {
@@ -51,7 +62,6 @@ if (config.get('@opentermsarchive/engine.logger.sendMailOnError')) {
51
62
  ssl: true,
52
63
  timeout: 30 * 1000,
53
64
  formatter: args => args[Object.getOwnPropertySymbols(args)[1]], // Returns the full error message, the same visible in the console. It is referenced in the argument object with a Symbol of which we do not have the reference but we know it is the second one.
54
- exitOnError: true,
55
65
  };
56
66
 
57
67
  transports.push(new winston.transports.Mail({
@@ -67,14 +77,15 @@ if (config.get('@opentermsarchive/engine.logger.sendMailOnError')) {
67
77
  subject: `[OTA] Inaccessible content — ${os.hostname()}`,
68
78
  }));
69
79
  }
70
-
71
- logger.configure({
72
- transports,
73
- rejectionHandlers: transports,
74
- });
75
80
  }
76
81
  }
77
82
 
83
+ logger.configure({
84
+ transports,
85
+ rejectionHandlers: transports,
86
+ exitOnError: true,
87
+ });
88
+
78
89
  let recordedSnapshotsCount;
79
90
  let recordedVersionsCount;
80
91
 
@@ -1,95 +0,0 @@
1
- import { parser as keepAChangelogParser } from 'keep-a-changelog';
2
- import semver from 'semver';
3
-
4
- import ChangelogValidationError from './changelogValidationError.js';
5
-
6
- export default class Changelog {
7
- static NO_CODE_CHANGES_REGEX = /^_No code changes were made in this release(.+)_$/m;
8
- static FUNDER_REGEX = /^> Development of this release was (?:supported|made on a volunteer basis) by (.+)\.$/m;
9
- static UNRELEASED_REGEX = /## Unreleased[ ]+\[(major|minor|patch)\]/i;
10
- static CHANGESET_LINK_REGEX = /^_Full changeset and discussions: (.+)._$/m;
11
- static CHANGESET_LINK_TEMPLATE = PRNumber => `_Full changeset and discussions: [#${PRNumber}](https://github.com/OpenTermsArchive/engine/pull/${PRNumber})._`;
12
- static CHANGELOG_INTRO = 'All changes that impact users of this module are documented in this file, in the [Common Changelog](https://common-changelog.org) format with some additional specifications defined in the CONTRIBUTING file. This codebase adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).';
13
-
14
- constructor(rawContent) {
15
- this.rawContent = rawContent;
16
- this.changelog = keepAChangelogParser(this.rawContent);
17
- this.changelog.description = Changelog.CHANGELOG_INTRO;
18
- this.changelog.format = 'markdownlint';
19
- this.releaseType = this.extractReleaseType();
20
- }
21
-
22
- extractReleaseType() {
23
- const match = this.rawContent.match(Changelog.UNRELEASED_REGEX);
24
-
25
- if (match && match[1]) {
26
- return match[1].toLowerCase();
27
- }
28
-
29
- return null;
30
- }
31
-
32
- cleanUnreleased() {
33
- const index = this.changelog.releases.findIndex(release => !release.version);
34
-
35
- this.changelog.releases.splice(index, 1);
36
- }
37
-
38
- getVersionContent(version) {
39
- const release = this.changelog.findRelease(version);
40
-
41
- if (!release) {
42
- throw new Error(`Version ${version} not found in changelog`);
43
- }
44
-
45
- return release.toString(this.changelog);
46
- }
47
-
48
- release(PRNumber) {
49
- const unreleased = this.changelog.findRelease();
50
-
51
- if (!unreleased) {
52
- throw new Error('Missing "Unreleased" section');
53
- }
54
-
55
- const latestVersion = semver.maxSatisfying(this.changelog.releases.map(release => release.version), '*');
56
- const newVersion = semver.inc(latestVersion, this.releaseType);
57
-
58
- unreleased.setVersion(newVersion);
59
- unreleased.date = new Date();
60
-
61
- if (PRNumber && !Changelog.CHANGESET_LINK_REGEX.test(unreleased.description)) {
62
- unreleased.description = `${Changelog.CHANGESET_LINK_TEMPLATE(PRNumber)}\n\n${unreleased.description}`;
63
- }
64
- }
65
-
66
- validateUnreleased() {
67
- const unreleased = this.changelog.findRelease();
68
- const errors = [];
69
-
70
- if (!unreleased) {
71
- errors.push(new Error('Missing "Unreleased" section'));
72
- throw new ChangelogValidationError(errors);
73
- }
74
-
75
- if (!this.releaseType) {
76
- errors.push(new Error('Invalid or missing release type for "Unreleased" section. Please ensure the section contains a valid release type (major, minor, or patch)'));
77
- }
78
-
79
- if (!Changelog.FUNDER_REGEX.test(unreleased.description)) {
80
- errors.push(new Error('Missing funder in the "Unreleased" section'));
81
- }
82
-
83
- if (!Changelog.NO_CODE_CHANGES_REGEX.test(unreleased.description) && (!unreleased.changes || Array.from(unreleased.changes.values()).every(change => !change.length))) {
84
- errors.push(new Error('Missing or malformed changes in the "Unreleased" section'));
85
- }
86
-
87
- if (errors.length) {
88
- throw new ChangelogValidationError(errors);
89
- }
90
- }
91
-
92
- toString() {
93
- return this.changelog.toString();
94
- }
95
- }
@@ -1,144 +0,0 @@
1
- import fs from 'fs/promises';
2
- import path from 'path';
3
- import { fileURLToPath } from 'url';
4
-
5
- import { expect } from 'chai';
6
-
7
- import Changelog from './changelog.js';
8
- import ChangelogValidationError from './changelogValidationError.js';
9
-
10
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
11
-
12
- describe('Changelog', () => {
13
- let changelog;
14
-
15
- describe('#releaseType', () => {
16
- context('with a properly formed changelog', () => {
17
- it('returns the correct release type', async () => {
18
- changelog = new Changelog(await fs.readFile(path.resolve(__dirname, './fixtures/changelog.md'), 'UTF-8'));
19
- expect(changelog.releaseType).to.equal('major');
20
- });
21
- });
22
-
23
- context('when "Unreleased" section does not exist', () => {
24
- it('returns null', async () => {
25
- changelog = new Changelog(await fs.readFile(path.resolve(__dirname, './fixtures/changelog-without-unreleased.md'), 'UTF-8'));
26
- expect(changelog.releaseType).to.be.null;
27
- });
28
- });
29
- context('when "Unreleased" section has a malformed release type', () => {
30
- it('returns null', async () => {
31
- changelog = new Changelog(await fs.readFile(path.resolve(__dirname, './fixtures/changelog-with-unreleased-malformed.md'), 'UTF-8'));
32
- expect(changelog.releaseType).to.be.null;
33
- });
34
- });
35
- });
36
-
37
- describe('#getVersionContent', () => {
38
- context('when getting an exisiting version', () => {
39
- it('returns the content of the specified version', async () => {
40
- changelog = new Changelog(await fs.readFile(path.resolve(__dirname, './fixtures/changelog.md'), 'UTF-8'));
41
- const versionContent = changelog.getVersionContent('0.0.1');
42
-
43
- expect(versionContent).to.equal(`## 0.0.1 - 2024-02-20
44
-
45
- _Full changeset and discussions: #122._
46
-
47
- > Development of this release was made on a volunteer basis by a contributor.
48
-
49
- ### Added
50
-
51
- - Initial release`);
52
- });
53
- });
54
-
55
- context('when getting a non-existing version', () => {
56
- it('throws an error', () => {
57
- expect(() => changelog.getVersionContent('2.0.0')).to.throw(Error);
58
- });
59
- });
60
- });
61
-
62
- describe('#cleanUnreleased', () => {
63
- context('when "Unreleased" section exists', () => {
64
- it('removes the section', async () => {
65
- changelog = new Changelog(await fs.readFile(path.resolve(__dirname, './fixtures/changelog-with-unreleased-no-release.md'), 'UTF-8'));
66
- changelog.cleanUnreleased();
67
- const updatedChangelog = changelog.toString();
68
-
69
- expect(updatedChangelog).to.not.include('## Unreleased');
70
- });
71
- });
72
-
73
- context('when "Unreleased" section does not exist', () => {
74
- it('does not throw any error', async () => {
75
- changelog = new Changelog(await fs.readFile(path.resolve(__dirname, './fixtures/changelog-without-unreleased.md'), 'UTF-8'));
76
- expect(() => changelog.cleanUnreleased()).to.not.throw();
77
- });
78
- });
79
- });
80
-
81
- describe('#release', () => {
82
- context('with a properly formed changelog', () => {
83
- it('returns an updated version of the changelog', async () => {
84
- changelog = new Changelog(await fs.readFile(path.resolve(__dirname, './fixtures/changelog.md'), 'UTF-8'));
85
- changelog.release();
86
- let expectedResult = await fs.readFile(path.resolve(__dirname, './fixtures/changelog-released.md'), 'UTF-8');
87
-
88
- expectedResult = expectedResult.replace('<DATE_OF_THE_DAY_PLACEHOLDER>', `${new Date().getFullYear()}-${String(new Date().getMonth() + 1).padStart(2, '0')}-${String(new Date().getDate()).padStart(2, '0')}`);
89
- expect(changelog.toString()).to.equal(expectedResult);
90
- });
91
- });
92
-
93
- context('when there is a validation error on the "Unreleased" section', () => {
94
- it('throws an error', async () => {
95
- changelog = new Changelog(await fs.readFile(path.resolve(__dirname, './fixtures/changelog-without-unreleased.md'), 'UTF-8'));
96
- expect(() => changelog.release(124)).to.throw(Error, 'Missing "Unreleased" section');
97
- });
98
- });
99
- });
100
-
101
- describe('#validateUnreleased', () => {
102
- context('with a properly formed "Unreleased" section', () => {
103
- it('does not throw any error', async () => {
104
- changelog = new Changelog(await fs.readFile(path.resolve(__dirname, './fixtures/changelog.md'), 'UTF-8'));
105
- expect(() => changelog.validateUnreleased()).to.not.throw();
106
- });
107
- });
108
-
109
- context('when "Unreleased" section is missing', () => {
110
- it('throws a ChangelogValidationError error with proper message', async () => {
111
- changelog = new Changelog(await fs.readFile(path.resolve(__dirname, './fixtures/changelog-without-unreleased.md'), 'UTF-8'));
112
- expect(() => changelog.validateUnreleased()).to.throw(ChangelogValidationError, 'Missing "Unreleased" section');
113
- });
114
- });
115
-
116
- context('when release type is invalid or missing', () => {
117
- it('throws a ChangelogValidationError error with proper message', async () => {
118
- changelog = new Changelog(await fs.readFile(path.resolve(__dirname, './fixtures/changelog-with-unreleased-malformed.md'), 'UTF-8'));
119
- expect(() => changelog.validateUnreleased()).to.throw(ChangelogValidationError, 'Invalid or missing release type for "Unreleased" section. Please ensure the section contains a valid release type (major, minor, or patch)');
120
- });
121
- });
122
-
123
- context('when funder is missing', () => {
124
- it('throws a ChangelogValidationError error with proper message', async () => {
125
- changelog = new Changelog(await fs.readFile(path.resolve(__dirname, './fixtures/changelog-without-funder.md'), 'UTF-8'));
126
- expect(() => changelog.validateUnreleased()).to.throw(ChangelogValidationError, 'Missing funder in the "Unreleased" section');
127
- });
128
- });
129
-
130
- context('when changes are missing', () => {
131
- it('throws a ChangelogValidationError error with proper message', async () => {
132
- changelog = new Changelog(await fs.readFile(path.resolve(__dirname, './fixtures/changelog-without-changes.md'), 'UTF-8'));
133
- expect(() => changelog.validateUnreleased()).to.throw(ChangelogValidationError, 'Missing or malformed changes in the "Unreleased" section');
134
- });
135
- });
136
-
137
- context('when changes are malformed', () => {
138
- it('throws a ChangelogValidationError error with proper message', async () => {
139
- changelog = new Changelog(await fs.readFile(path.resolve(__dirname, './fixtures/changelog-without-changes.md'), 'UTF-8'));
140
- expect(() => changelog.validateUnreleased()).to.throw(ChangelogValidationError, 'Missing or malformed changes in the "Unreleased" section');
141
- });
142
- });
143
- });
144
- });
@@ -1,9 +0,0 @@
1
- export default class ChangelogValidationError extends Error {
2
- constructor(errorOrErrors) {
3
- const errors = [].concat(errorOrErrors);
4
-
5
- super(`Invalid Unreleased section:${`\n - ${errors.join('\n - ')}`}`);
6
- this.name = 'ChangelogValidationError';
7
- this.errors = errors;
8
- }
9
- }
@@ -1,23 +0,0 @@
1
- # Changelog
2
-
3
- All changes that impact users of this module are documented in this file, in the [Common Changelog](https://common-changelog.org) format with some additional specifications defined in the CONTRIBUTING file. This codebase adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
-
5
- ## 1.0.0 - <DATE_OF_THE_DAY_PLACEHOLDER>
6
-
7
- _Full changeset and discussions: #123._
8
-
9
- > Development of this release was supported by a funder.
10
-
11
- ### Added
12
-
13
- - New feature 1
14
-
15
- ## 0.0.1 - 2024-02-20
16
-
17
- _Full changeset and discussions: #122._
18
-
19
- > Development of this release was made on a volunteer basis by a contributor.
20
-
21
- ### Added
22
-
23
- - Initial release
@@ -1,21 +0,0 @@
1
- # Changelog
2
-
3
- All changes that impact users of this module are documented in this file, in the [Common Changelog](https://common-changelog.org) format with some additional specifications defined in the CONTRIBUTING file. This codebase adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
-
5
- ## Unreleased [major]
6
-
7
- _Full changeset and discussions: #123._
8
-
9
- > Development of this release was supported by a funder.
10
-
11
- - New feature 1
12
-
13
- ## 0.0.1 - 2024-02-20
14
-
15
- _Full changeset and discussions: #122._
16
-
17
- > Development of this release was supported by a funder.
18
-
19
- ### Added
20
-
21
- - Initial release
@@ -1,23 +0,0 @@
1
- # Changelog
2
-
3
- All changes that impact users of this module are documented in this file, in the [Common Changelog](https://common-changelog.org) format with some additional specifications defined in the CONTRIBUTING file. This codebase adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
-
5
- ## Unreleased major
6
-
7
- _Full changeset and discussions: #123._
8
-
9
- > Development of this release was supported by a funder.
10
-
11
- ### Added
12
-
13
- - New feature 1
14
-
15
- ## 0.0.1 - 2024-02-20
16
-
17
- _Full changeset and discussions: #122._
18
-
19
- > Development of this release was supported by a funder.
20
-
21
- ### Added
22
-
23
- - Initial release
@@ -1,21 +0,0 @@
1
- # Changelog
2
-
3
- All changes that impact users of this module are documented in this file, in the [Common Changelog](https://common-changelog.org) format with some additional specifications defined in the CONTRIBUTING file. This codebase adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
-
5
- ## Unreleased [no-release]
6
-
7
- _Modifications made in this changeset do not alter its behavior or functionality from the perspective of the end user or other interacting systems. It does not add new features, do not enhance existing features, or alter the behavior of the software in a way that affects its use._
8
-
9
- ### Added
10
-
11
- - New feature 1
12
-
13
- ## 0.0.1 - 2024-02-20
14
-
15
- _Full changeset and discussions: #122._
16
-
17
- > Development of this release was supported by a funder.
18
-
19
- ### Added
20
-
21
- - Initial release
@@ -1,19 +0,0 @@
1
- # Changelog
2
-
3
- All changes that impact users of this module are documented in this file, in the [Common Changelog](https://common-changelog.org) format with some additional specifications defined in the CONTRIBUTING file. This codebase adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
-
5
- ## Unreleased [major]
6
-
7
- _Full changeset and discussions: #123._
8
-
9
- > Development of this release was supported by a funder.
10
-
11
- ## 0.0.1 - 2024-02-20
12
-
13
- _Full changeset and discussions: #122._
14
-
15
- > Development of this release was supported by a funder.
16
-
17
- ### Added
18
-
19
- - Initial release
@@ -1,21 +0,0 @@
1
- # Changelog
2
-
3
- All changes that impact users of this module are documented in this file, in the [Common Changelog](https://common-changelog.org) format with some additional specifications defined in the CONTRIBUTING file. This codebase adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
-
5
- ## Unreleased [major]
6
-
7
- _Full changeset and discussions: #123._
8
-
9
- ### Added
10
-
11
- - New feature 1
12
-
13
- ## 0.0.1 - 2024-02-20
14
-
15
- _Full changeset and discussions: #122._
16
-
17
- > Development of this release was supported by a funder.
18
-
19
- ### Added
20
-
21
- - Initial release
@@ -1,13 +0,0 @@
1
- # Changelog
2
-
3
- All changes that impact users of this module are documented in this file, in the [Common Changelog](https://common-changelog.org) format with some additional specifications defined in the CONTRIBUTING file. This codebase adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
-
5
- ## 0.0.1 - 2024-02-20
6
-
7
- _Full changeset and discussions: #122._
8
-
9
- > Development of this release was supported by a funder.
10
-
11
- ### Added
12
-
13
- - Initial release
@@ -1,23 +0,0 @@
1
- # Changelog
2
-
3
- All changes that impact users of this module are documented in this file, in the [Common Changelog](https://common-changelog.org) format with some additional specifications defined in the CONTRIBUTING file. This codebase adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
-
5
- ## Unreleased [major]
6
-
7
- _Full changeset and discussions: #123._
8
-
9
- > Development of this release was supported by a funder.
10
-
11
- ### Added
12
-
13
- - New feature 1
14
-
15
- ## 0.0.1 - 2024-02-20
16
-
17
- _Full changeset and discussions: #122._
18
-
19
- > Development of this release was made on a volunteer basis by a contributor.
20
-
21
- ### Added
22
-
23
- - Initial release
@@ -1,59 +0,0 @@
1
- #! /usr/bin/env node
2
-
3
- import fs from 'fs/promises';
4
- import path from 'path';
5
- import { fileURLToPath } from 'url';
6
-
7
- import { program } from 'commander';
8
-
9
- import Changelog from './changelog.js';
10
-
11
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
12
-
13
- program
14
- .name('changelog')
15
- .description('A command-line utility for managing the changelog file')
16
- .option('--validate', 'Validate the changelog, ensuring it follows the expected format and contains required information')
17
- .option('--release [PRNumber]', 'Convert the Unreleased section into a new release in the changelog, optionally linking to a pull request with the provided PRNumber')
18
- .option('--clean-unreleased', 'Remove the Unreleased section')
19
- .option('--get-release-type', 'Get the release type of the Unreleased section in the changelog')
20
- .option('--get-version-content <version>', 'Get the content of the given version in the changelog');
21
-
22
- const options = program.parse(process.argv).opts();
23
-
24
- let changelog;
25
-
26
- const CHANGELOG_PATH = path.resolve(__dirname, '../../CHANGELOG.md');
27
- const ENCODING = 'UTF-8';
28
-
29
- try {
30
- const changelogContent = await fs.readFile(CHANGELOG_PATH, ENCODING);
31
-
32
- changelog = new Changelog(changelogContent);
33
- } catch (error) {
34
- console.log(error.message);
35
- }
36
-
37
- if (options.validate) {
38
- changelog.validateUnreleased();
39
- }
40
-
41
- if (options.getReleaseType) {
42
- process.stdout.write(changelog.releaseType || 'No release type found');
43
- }
44
-
45
- if (options.getVersionContent) {
46
- process.stdout.write(changelog.getVersionContent(options.getVersionContent));
47
- }
48
-
49
- if (options.release) {
50
- const PRNumber = typeof options.release == 'boolean' ? null : options.release;
51
-
52
- changelog.release(PRNumber);
53
- await fs.writeFile(CHANGELOG_PATH, changelog.toString(), ENCODING);
54
- }
55
-
56
- if (options.cleanUnreleased) {
57
- changelog.cleanUnreleased();
58
- await fs.writeFile(CHANGELOG_PATH, changelog.toString(), ENCODING);
59
- }