bpmnlint 11.12.1 → 11.13.0

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.
Files changed (47) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +203 -203
  3. package/bin/bpmnlint.js +437 -437
  4. package/config/all.js +38 -37
  5. package/config/correctness.js +12 -12
  6. package/config/recommended.js +29 -29
  7. package/lib/index.js +4 -4
  8. package/lib/linter.js +542 -542
  9. package/lib/resolver/helper.js +12 -12
  10. package/lib/resolver/node-resolver.js +135 -135
  11. package/lib/resolver/static-resolver.js +47 -47
  12. package/lib/support/compile-config.js +200 -200
  13. package/lib/test-rule.js +107 -107
  14. package/lib/testers/helper.js +72 -72
  15. package/lib/testers/rule-tester.d.ts +36 -36
  16. package/lib/testers/rule-tester.js +146 -146
  17. package/lib/traverse.js +56 -56
  18. package/lib/types.d.ts +80 -80
  19. package/package.json +74 -73
  20. package/rules/ad-hoc-sub-process.js +43 -43
  21. package/rules/conditional-event.js +51 -51
  22. package/rules/conditional-flows.js +57 -57
  23. package/rules/end-event-required.js +45 -45
  24. package/rules/event-based-gateway.js +44 -44
  25. package/rules/event-sub-process-typed-start-event.js +43 -43
  26. package/rules/fake-join.js +40 -40
  27. package/rules/global.js +145 -145
  28. package/rules/helper.js +123 -123
  29. package/rules/label-required.js +75 -75
  30. package/rules/link-event.js +106 -106
  31. package/rules/no-bpmndi.js +157 -157
  32. package/rules/no-complex-gateway.js +2 -2
  33. package/rules/no-disconnected.js +82 -82
  34. package/rules/no-duplicate-sequence-flows.js +69 -69
  35. package/rules/no-gateway-join-fork.js +35 -35
  36. package/rules/no-implicit-end.js +98 -98
  37. package/rules/no-implicit-split.js +55 -55
  38. package/rules/no-implicit-start.js +69 -69
  39. package/rules/no-inclusive-gateway.js +2 -2
  40. package/rules/no-overlapping-elements.js +196 -196
  41. package/rules/single-blank-start-event.js +47 -47
  42. package/rules/single-event-definition.js +33 -33
  43. package/rules/standard-size.js +235 -0
  44. package/rules/start-event-required.js +45 -45
  45. package/rules/sub-process-blank-start-event.js +43 -43
  46. package/rules/superfluous-gateway.js +36 -36
  47. package/rules/superfluous-termination.js +70 -70
package/bin/bpmnlint.js CHANGED
@@ -1,438 +1,438 @@
1
1
  #!/usr/bin/env node
2
-
3
- const { readFile } = require('node:fs/promises');
4
- const { writeFileSync, existsSync } = require('node:fs');
5
- const { resolve: resolvePath } = require('node:path');
6
-
7
- const mri = require('mri');
8
- const colors = require('ansi-colors');
9
-
10
- colors.enabled = require('color-support').hasBasic;
11
-
12
- const {
13
- red,
14
- yellow,
15
- underline,
16
- bold,
17
- magenta
18
- } = colors;
19
-
20
- const tinyGlob = require('tiny-glob');
21
-
22
- // @ts-expect-error 'missing <bpmn-moddle> types'
23
- const { BpmnModdle } = require('bpmn-moddle');
24
-
25
- const Linter = require('../lib/linter');
26
- const NodeResolver = require('../lib/resolver/node-resolver');
27
- const { createScopedRequire } = require('../lib/resolver/helper');
28
-
29
- const Table = require('cli-table');
30
-
31
- const pluralize = require('pluralize');
32
-
33
- const { pathStringify } = require('@bpmn-io/moddle-utils');
34
-
35
- /**
36
- * @typedef { import('../lib/types').ModdleElement } ModdleElement
37
- * @typedef { Error & { element: ModdleElement } } BPMNImportWarning
38
- */
39
-
40
- const CONFIG_NAME = '.bpmnlintrc';
41
-
42
- const DEFAULT_CONFIG_CONTENTS = `{
43
- "extends": "bpmnlint:recommended"
44
- }`;
45
-
46
- const HELP_STRING = `
47
- Usage
48
- $ bpmnlint diagram.bpmn
49
-
50
- Options
51
- --config, -c Path to configuration file. It overrides .bpmnlintrc if present
52
- --init Generate a .bpmnlintrc file in the current working directory
53
- --max-warnings Number of warnings to trigger nonzero exit code - default: -1
54
-
55
- Examples
56
- $ bpmnlint ./invoice.bpmn
57
- $ bpmnlint --max-warnings=0 '*.bpmn'
58
- $ bpmnlint --init
59
-
60
- `;
61
-
62
-
63
- function boldRed(str) {
64
- return bold(red(str));
65
- }
66
-
67
- function boldYellow(str) {
68
- return bold(yellow(str));
69
- }
70
-
71
- function glob(files) {
72
- return Promise.all(
73
- files.map(
74
- file => tinyGlob(file, { dot: true })
75
- )
76
- ).then(files => [].concat(...files));
77
- }
78
-
79
- /**
80
- * Reads XML form path and return moddle object
81
- *
82
- * @param {string} diagramXML
83
- * @param {BpmnModdle.BPMNModdle} moddle
84
- *
85
- * @return { Promise<{ moddleElement: any; warnings: Error[], error?: Error }> } parseResult
86
- */
87
- async function parseDiagram(diagramXML, moddle) {
88
-
89
- try {
90
- const {
91
- rootElement: moddleElement,
92
- warnings = []
93
- } = await moddle.fromXML(diagramXML);
94
-
95
- return {
96
- moddleElement,
97
- warnings
98
- };
99
- } catch (error) {
100
-
101
- const {
102
-
103
- // @ts-expect-error
104
- warnings = []
105
- } = error;
106
-
107
- return {
108
-
109
- // @ts-expect-error
110
- error,
111
- warnings
112
- };
113
- }
114
- }
115
-
116
- const categoryMap = {
117
- warn: 'warning'
118
- };
119
-
120
- /**
121
- * Logs a formatted message
122
- */
123
- function tableEntry(report) {
124
- let {
125
- category,
126
- id = '',
127
- message,
128
- name = '',
129
- path
130
- } = report;
131
-
132
- if (path) {
133
- id = `${ id }#${ pathStringify(path) }`;
134
- }
135
-
136
- const color = category === 'error' ? red : yellow;
137
-
138
- return [ id, color(categoryMap[ category ] || category), message, name ];
139
- }
140
-
141
- function createTable() {
142
- return new Table({
143
- chars: {
144
- 'top': '',
145
- 'top-mid': '',
146
- 'top-left': '',
147
- 'top-right': '',
148
- 'bottom': '',
149
- 'bottom-mid': '',
150
- 'bottom-left': '',
151
- 'bottom-right': '',
152
- 'left': ' ',
153
- 'left-mid': '',
154
- 'mid': '',
155
- 'mid-mid': '',
156
- 'right': '',
157
- 'right-mid': '',
158
- 'middle': ' '
159
- },
160
- style: {
161
- 'padding-left': 0,
162
- 'padding-right': 0
163
- }
164
- });
165
- }
166
-
167
- function errorAndExit(...args) {
168
- console.error(...args);
169
-
170
- process.exit(1);
171
- }
172
-
173
- function showVersionAndExit() {
174
- console.log(require('../package.json').version);
175
-
176
- process.exit(0);
177
- }
178
-
179
- function infoAndExit(...args) {
180
- console.log(...args);
181
-
182
- process.exit(0);
183
- }
184
-
185
- /**
186
- * Prints lint results to the console
187
- *
188
- * @param {String} filePath
189
- * @param {Object} results
190
- */
191
- function printReports(filePath, results) {
192
-
193
- let errorCount = 0;
194
- let warningCount = 0;
195
-
196
- const table = createTable();
197
-
198
- Object.entries(results).forEach(function([ name, reports ]) {
199
-
200
- reports.forEach(function(report) {
201
-
202
- const {
203
- category,
204
- id,
205
- message,
206
- name: reportName
207
- } = report;
208
-
209
- table.push(tableEntry({
210
- category,
211
- id,
212
- message,
213
- name: reportName || name
214
- }));
215
-
216
- if (category === 'error') {
217
- errorCount++;
218
- } else {
219
- warningCount++;
220
- }
221
- });
222
- });
223
-
224
- const problemCount = warningCount + errorCount;
225
-
226
- if (problemCount) {
227
- console.log();
228
- console.log(underline(resolvePath(filePath)));
229
- console.log(table.toString());
230
- }
231
-
232
- return {
233
- errorCount,
234
- warningCount
235
- };
236
- }
237
-
238
- async function lintDiagram(diagramPath, config, moddle) {
239
-
240
- let diagramXML;
241
-
242
- try {
243
- diagramXML = await readFile(resolvePath(diagramPath), 'utf-8');
244
- } catch (error) {
245
- throw errorAndExit(`Error: Failed to read ${diagramPath}\n\n%s`, /** @type { Error } */ (error).message);
246
- }
247
-
248
-
249
- const {
250
- error: importError,
251
- warnings: importWarnings,
252
- moddleElement
253
- } = await parseDiagram(diagramXML, moddle);
254
-
255
- if (importError) {
256
- return printReports(diagramPath, {
257
- '': [
258
- {
259
- message: 'Parse error: ' + importError.message,
260
- category: 'error'
261
- }
262
- ]
263
- });
264
- }
265
-
266
- const importReports = importWarnings.length ? {
267
- '': importWarnings.map(function(warning) {
268
-
269
- const {
270
- element,
271
- message
272
- } = /** @type { BPMNImportWarning } */ (warning);
273
-
274
- const id = element && element.id;
275
-
276
- return {
277
- id,
278
- message: 'Import warning: ' + message.split(/\n/)[0],
279
- category: 'error'
280
- };
281
- })
282
- } : {};
283
-
284
- try {
285
- const linter = new Linter({
286
- config,
287
- resolver: new NodeResolver()
288
- });
289
-
290
- const lintReports = await linter.lint(moddleElement);
291
-
292
- const allResults = {
293
- ...importReports,
294
- ...lintReports
295
- };
296
-
297
- return printReports(diagramPath, allResults);
298
- } catch (e) {
299
- throw errorAndExit(e);
300
- }
301
- }
302
-
303
- async function lint(files, config, maxWarnings) {
304
-
305
- let errorCount = 0;
306
- let warningCount = 0;
307
-
308
- console.log();
309
-
310
- const moddle = createModdle(config);
311
-
312
- for (let i = 0; i < files.length; i++) {
313
- let results = await lintDiagram(files[i], config, moddle);
314
-
315
- errorCount += results.errorCount;
316
- warningCount += results.warningCount;
317
- }
318
-
319
- const problemCount = errorCount + warningCount;
320
-
321
- if (problemCount) {
322
-
323
- const color = warningCount ? boldYellow : boldRed;
324
-
325
- console.log();
326
- console.log(color(
327
- `✖ ${problemCount} ${pluralize('problem', problemCount)} (${errorCount} ${pluralize('error', errorCount)}, ${warningCount} ${pluralize('warning', warningCount)})`
328
- ));
329
- }
330
-
331
- if (errorCount || (maxWarnings !== -1 && warningCount > maxWarnings)) {
332
- process.exit(1);
333
- }
334
-
335
- }
336
-
337
- async function run() {
338
-
339
- const {
340
- help,
341
- init,
342
- version,
343
- config: configOverridePath,
344
- 'max-warnings': maxWarnings,
345
- _: files
346
- } = mri(process.argv.slice(2), {
347
- string: [ 'config' ],
348
- alias: {
349
- c: 'config'
350
- },
351
- default: {
352
- 'max-warnings': -1
353
- }
354
- });
355
-
356
- if (version) {
357
- return showVersionAndExit();
358
- }
359
-
360
- if (help) {
361
- return infoAndExit(HELP_STRING);
362
- }
363
-
364
- if (init) {
365
- if (existsSync(CONFIG_NAME)) {
366
- throw errorAndExit('Not overriding existing .bpmnlintrc');
367
- }
368
-
369
- writeFileSync(CONFIG_NAME, DEFAULT_CONFIG_CONTENTS, 'utf8');
370
-
371
- throw infoAndExit(`Created ${magenta(CONFIG_NAME)} file`);
372
- }
373
-
374
- if (files.length === 0) {
375
- throw errorAndExit('Error: bpmn file path missing');
376
- }
377
-
378
- const configPath = configOverridePath || CONFIG_NAME;
379
-
380
- let configString, config;
381
-
382
- try {
383
- configString = await readFile(configPath, 'utf-8');
384
- } catch (error) {
385
-
386
- const message = (
387
- configOverridePath
388
- ? `Error: Could not read ${ magenta(configOverridePath) }`
389
- : `Error: Could not locate local ${ magenta(CONFIG_NAME) } file. Create one via
390
-
391
- ${magenta('bpmnlint --init')}
392
-
393
- Learn more about configuring bpmnlint: https://github.com/bpmn-io/bpmnlint#configuration`
394
- );
395
-
396
- throw errorAndExit(message);
397
- }
398
-
399
- try {
400
- config = JSON.parse(configString);
401
- } catch (error) {
402
- throw errorAndExit('Error: Could not parse %s\n\n%s', configPath, /** @type { Error } */ (error).message);
403
- }
404
-
405
- const actualFiles = await glob(files);
406
-
407
- return lint(actualFiles, config, maxWarnings);
408
- }
409
-
410
- run().catch(errorAndExit);
411
-
412
- /**
413
- * Create moddle instance with extensions from the config.
414
- *
415
- * @param {object} config
416
- * @returns {BpmnModdle.BPMNModdle}
417
- */
418
- function createModdle(config) {
419
- const scopedRequire = createScopedRequire(process.cwd());
420
-
421
- const options = config.moddleExtensions || {};
422
-
423
- for (const key in options) {
424
- const extension = options[key];
425
-
426
- try {
427
- options[key] = scopedRequire(extension);
428
- } catch (error) {
429
- errorAndExit('Error: Could not load moddle extension <%s> from %s\n\n', key, extension, /** @type { Error } */ (error).message);
430
- }
431
- }
432
-
433
- try {
434
- return new BpmnModdle(options);
435
- } catch (error) {
436
- errorAndExit('Error: Could not create moddle instance\n\n%s', /** @type { Error } */ (error).message);
437
- }
438
- }
2
+
3
+ const { readFile } = require('node:fs/promises');
4
+ const { writeFileSync, existsSync } = require('node:fs');
5
+ const { resolve: resolvePath } = require('node:path');
6
+
7
+ const mri = require('mri');
8
+ const colors = require('ansi-colors');
9
+
10
+ colors.enabled = require('color-support').hasBasic;
11
+
12
+ const {
13
+ red,
14
+ yellow,
15
+ underline,
16
+ bold,
17
+ magenta
18
+ } = colors;
19
+
20
+ const tinyGlob = require('tiny-glob');
21
+
22
+ // @ts-expect-error 'missing <bpmn-moddle> types'
23
+ const { BpmnModdle } = require('bpmn-moddle');
24
+
25
+ const Linter = require('../lib/linter');
26
+ const NodeResolver = require('../lib/resolver/node-resolver');
27
+ const { createScopedRequire } = require('../lib/resolver/helper');
28
+
29
+ const Table = require('cli-table');
30
+
31
+ const pluralize = require('pluralize');
32
+
33
+ const { pathStringify } = require('@bpmn-io/moddle-utils');
34
+
35
+ /**
36
+ * @typedef { import('../lib/types').ModdleElement } ModdleElement
37
+ * @typedef { Error & { element: ModdleElement } } BPMNImportWarning
38
+ */
39
+
40
+ const CONFIG_NAME = '.bpmnlintrc';
41
+
42
+ const DEFAULT_CONFIG_CONTENTS = `{
43
+ "extends": "bpmnlint:recommended"
44
+ }`;
45
+
46
+ const HELP_STRING = `
47
+ Usage
48
+ $ bpmnlint diagram.bpmn
49
+
50
+ Options
51
+ --config, -c Path to configuration file. It overrides .bpmnlintrc if present
52
+ --init Generate a .bpmnlintrc file in the current working directory
53
+ --max-warnings Number of warnings to trigger nonzero exit code - default: -1
54
+
55
+ Examples
56
+ $ bpmnlint ./invoice.bpmn
57
+ $ bpmnlint --max-warnings=0 '*.bpmn'
58
+ $ bpmnlint --init
59
+
60
+ `;
61
+
62
+
63
+ function boldRed(str) {
64
+ return bold(red(str));
65
+ }
66
+
67
+ function boldYellow(str) {
68
+ return bold(yellow(str));
69
+ }
70
+
71
+ function glob(files) {
72
+ return Promise.all(
73
+ files.map(
74
+ file => tinyGlob(file, { dot: true })
75
+ )
76
+ ).then(files => [].concat(...files));
77
+ }
78
+
79
+ /**
80
+ * Reads XML form path and return moddle object
81
+ *
82
+ * @param {string} diagramXML
83
+ * @param {BpmnModdle.BPMNModdle} moddle
84
+ *
85
+ * @return { Promise<{ moddleElement: any; warnings: Error[], error?: Error }> } parseResult
86
+ */
87
+ async function parseDiagram(diagramXML, moddle) {
88
+
89
+ try {
90
+ const {
91
+ rootElement: moddleElement,
92
+ warnings = []
93
+ } = await moddle.fromXML(diagramXML);
94
+
95
+ return {
96
+ moddleElement,
97
+ warnings
98
+ };
99
+ } catch (error) {
100
+
101
+ const {
102
+
103
+ // @ts-expect-error
104
+ warnings = []
105
+ } = error;
106
+
107
+ return {
108
+
109
+ // @ts-expect-error
110
+ error,
111
+ warnings
112
+ };
113
+ }
114
+ }
115
+
116
+ const categoryMap = {
117
+ warn: 'warning'
118
+ };
119
+
120
+ /**
121
+ * Logs a formatted message
122
+ */
123
+ function tableEntry(report) {
124
+ let {
125
+ category,
126
+ id = '',
127
+ message,
128
+ name = '',
129
+ path
130
+ } = report;
131
+
132
+ if (path) {
133
+ id = `${ id }#${ pathStringify(path) }`;
134
+ }
135
+
136
+ const color = category === 'error' ? red : yellow;
137
+
138
+ return [ id, color(categoryMap[ category ] || category), message, name ];
139
+ }
140
+
141
+ function createTable() {
142
+ return new Table({
143
+ chars: {
144
+ 'top': '',
145
+ 'top-mid': '',
146
+ 'top-left': '',
147
+ 'top-right': '',
148
+ 'bottom': '',
149
+ 'bottom-mid': '',
150
+ 'bottom-left': '',
151
+ 'bottom-right': '',
152
+ 'left': ' ',
153
+ 'left-mid': '',
154
+ 'mid': '',
155
+ 'mid-mid': '',
156
+ 'right': '',
157
+ 'right-mid': '',
158
+ 'middle': ' '
159
+ },
160
+ style: {
161
+ 'padding-left': 0,
162
+ 'padding-right': 0
163
+ }
164
+ });
165
+ }
166
+
167
+ function errorAndExit(...args) {
168
+ console.error(...args);
169
+
170
+ process.exit(1);
171
+ }
172
+
173
+ function showVersionAndExit() {
174
+ console.log(require('../package.json').version);
175
+
176
+ process.exit(0);
177
+ }
178
+
179
+ function infoAndExit(...args) {
180
+ console.log(...args);
181
+
182
+ process.exit(0);
183
+ }
184
+
185
+ /**
186
+ * Prints lint results to the console
187
+ *
188
+ * @param {String} filePath
189
+ * @param {Object} results
190
+ */
191
+ function printReports(filePath, results) {
192
+
193
+ let errorCount = 0;
194
+ let warningCount = 0;
195
+
196
+ const table = createTable();
197
+
198
+ Object.entries(results).forEach(function([ name, reports ]) {
199
+
200
+ reports.forEach(function(report) {
201
+
202
+ const {
203
+ category,
204
+ id,
205
+ message,
206
+ name: reportName
207
+ } = report;
208
+
209
+ table.push(tableEntry({
210
+ category,
211
+ id,
212
+ message,
213
+ name: reportName || name
214
+ }));
215
+
216
+ if (category === 'error') {
217
+ errorCount++;
218
+ } else {
219
+ warningCount++;
220
+ }
221
+ });
222
+ });
223
+
224
+ const problemCount = warningCount + errorCount;
225
+
226
+ if (problemCount) {
227
+ console.log();
228
+ console.log(underline(resolvePath(filePath)));
229
+ console.log(table.toString());
230
+ }
231
+
232
+ return {
233
+ errorCount,
234
+ warningCount
235
+ };
236
+ }
237
+
238
+ async function lintDiagram(diagramPath, config, moddle) {
239
+
240
+ let diagramXML;
241
+
242
+ try {
243
+ diagramXML = await readFile(resolvePath(diagramPath), 'utf-8');
244
+ } catch (error) {
245
+ throw errorAndExit(`Error: Failed to read ${diagramPath}\n\n%s`, /** @type { Error } */ (error).message);
246
+ }
247
+
248
+
249
+ const {
250
+ error: importError,
251
+ warnings: importWarnings,
252
+ moddleElement
253
+ } = await parseDiagram(diagramXML, moddle);
254
+
255
+ if (importError) {
256
+ return printReports(diagramPath, {
257
+ '': [
258
+ {
259
+ message: 'Parse error: ' + importError.message,
260
+ category: 'error'
261
+ }
262
+ ]
263
+ });
264
+ }
265
+
266
+ const importReports = importWarnings.length ? {
267
+ '': importWarnings.map(function(warning) {
268
+
269
+ const {
270
+ element,
271
+ message
272
+ } = /** @type { BPMNImportWarning } */ (warning);
273
+
274
+ const id = element && element.id;
275
+
276
+ return {
277
+ id,
278
+ message: 'Import warning: ' + message.split(/\n/)[0],
279
+ category: 'error'
280
+ };
281
+ })
282
+ } : {};
283
+
284
+ try {
285
+ const linter = new Linter({
286
+ config,
287
+ resolver: new NodeResolver()
288
+ });
289
+
290
+ const lintReports = await linter.lint(moddleElement);
291
+
292
+ const allResults = {
293
+ ...importReports,
294
+ ...lintReports
295
+ };
296
+
297
+ return printReports(diagramPath, allResults);
298
+ } catch (e) {
299
+ throw errorAndExit(e);
300
+ }
301
+ }
302
+
303
+ async function lint(files, config, maxWarnings) {
304
+
305
+ let errorCount = 0;
306
+ let warningCount = 0;
307
+
308
+ console.log();
309
+
310
+ const moddle = createModdle(config);
311
+
312
+ for (let i = 0; i < files.length; i++) {
313
+ let results = await lintDiagram(files[i], config, moddle);
314
+
315
+ errorCount += results.errorCount;
316
+ warningCount += results.warningCount;
317
+ }
318
+
319
+ const problemCount = errorCount + warningCount;
320
+
321
+ if (problemCount) {
322
+
323
+ const color = warningCount ? boldYellow : boldRed;
324
+
325
+ console.log();
326
+ console.log(color(
327
+ `✖ ${problemCount} ${pluralize('problem', problemCount)} (${errorCount} ${pluralize('error', errorCount)}, ${warningCount} ${pluralize('warning', warningCount)})`
328
+ ));
329
+ }
330
+
331
+ if (errorCount || (maxWarnings !== -1 && warningCount > maxWarnings)) {
332
+ process.exit(1);
333
+ }
334
+
335
+ }
336
+
337
+ async function run() {
338
+
339
+ const {
340
+ help,
341
+ init,
342
+ version,
343
+ config: configOverridePath,
344
+ 'max-warnings': maxWarnings,
345
+ _: files
346
+ } = mri(process.argv.slice(2), {
347
+ string: [ 'config' ],
348
+ alias: {
349
+ c: 'config'
350
+ },
351
+ default: {
352
+ 'max-warnings': -1
353
+ }
354
+ });
355
+
356
+ if (version) {
357
+ return showVersionAndExit();
358
+ }
359
+
360
+ if (help) {
361
+ return infoAndExit(HELP_STRING);
362
+ }
363
+
364
+ if (init) {
365
+ if (existsSync(CONFIG_NAME)) {
366
+ throw errorAndExit('Not overriding existing .bpmnlintrc');
367
+ }
368
+
369
+ writeFileSync(CONFIG_NAME, DEFAULT_CONFIG_CONTENTS, 'utf8');
370
+
371
+ throw infoAndExit(`Created ${magenta(CONFIG_NAME)} file`);
372
+ }
373
+
374
+ if (files.length === 0) {
375
+ throw errorAndExit('Error: bpmn file path missing');
376
+ }
377
+
378
+ const configPath = configOverridePath || CONFIG_NAME;
379
+
380
+ let configString, config;
381
+
382
+ try {
383
+ configString = await readFile(configPath, 'utf-8');
384
+ } catch (error) {
385
+
386
+ const message = (
387
+ configOverridePath
388
+ ? `Error: Could not read ${ magenta(configOverridePath) }`
389
+ : `Error: Could not locate local ${ magenta(CONFIG_NAME) } file. Create one via
390
+
391
+ ${magenta('bpmnlint --init')}
392
+
393
+ Learn more about configuring bpmnlint: https://github.com/bpmn-io/bpmnlint#configuration`
394
+ );
395
+
396
+ throw errorAndExit(message);
397
+ }
398
+
399
+ try {
400
+ config = JSON.parse(configString);
401
+ } catch (error) {
402
+ throw errorAndExit('Error: Could not parse %s\n\n%s', configPath, /** @type { Error } */ (error).message);
403
+ }
404
+
405
+ const actualFiles = await glob(files);
406
+
407
+ return lint(actualFiles, config, maxWarnings);
408
+ }
409
+
410
+ run().catch(errorAndExit);
411
+
412
+ /**
413
+ * Create moddle instance with extensions from the config.
414
+ *
415
+ * @param {object} config
416
+ * @returns {BpmnModdle.BPMNModdle}
417
+ */
418
+ function createModdle(config) {
419
+ const scopedRequire = createScopedRequire(process.cwd());
420
+
421
+ const options = config.moddleExtensions || {};
422
+
423
+ for (const key in options) {
424
+ const extension = options[key];
425
+
426
+ try {
427
+ options[key] = scopedRequire(extension);
428
+ } catch (error) {
429
+ errorAndExit('Error: Could not load moddle extension <%s> from %s\n\n', key, extension, /** @type { Error } */ (error).message);
430
+ }
431
+ }
432
+
433
+ try {
434
+ return new BpmnModdle(options);
435
+ } catch (error) {
436
+ errorAndExit('Error: Could not create moddle instance\n\n%s', /** @type { Error } */ (error).message);
437
+ }
438
+ }