@mermaid-js/mermaid-cli 11.12.0 → 11.14.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.
@@ -0,0 +1,91 @@
1
+ /**
2
+ * @import puppeteer from 'puppeteer';
3
+ */
4
+
5
+ import { readFile, realpath } from 'node:fs/promises'
6
+ import path from 'node:path'
7
+ import url from 'node:url'
8
+
9
+ /**
10
+ * Puppeteer doesn't allow importing ESM modules from `file://` URLs.
11
+ * We don't want to create a dummy http server to serve ESM modules
12
+ * (since that would cause issues with ports/firewalls), so this module
13
+ * instead intercepts dummy `https://mermaid-cli-intercept.invalid` requests.
14
+ */
15
+ export class Interceptor {
16
+ #INTERCEPT_ORIGIN = 'https://mermaid-cli-intercept.invalid'
17
+
18
+ /**
19
+ * Set of allowed file directories that can be intercepted.
20
+ *
21
+ * This is used to prevent arbitrary file access through the intercept mechanism.
22
+ *
23
+ * Make sure to use `realpath` to resolve any symlinks.
24
+ *
25
+ * @type {Set<string>}
26
+ */
27
+ #allowedDirs = new Set()
28
+
29
+ /**
30
+ * @param {URL | `file://${string}`} fileUrl - File URL
31
+ */
32
+ async fileUrlToInterceptUrl (fileUrl) {
33
+ fileUrl = new URL(fileUrl)
34
+ if (fileUrl.protocol !== 'file:') {
35
+ throw new Error(`Invalid file URL: ${fileUrl}`)
36
+ }
37
+ this.#allowedDirs.add(path.dirname(await realpath(url.fileURLToPath(fileUrl))))
38
+ return `${this.#INTERCEPT_ORIGIN}${fileUrl.pathname}`
39
+ }
40
+
41
+ /**
42
+ *
43
+ * @param {URL | string} interceptUrl
44
+ * @throws {Error} If the URL is not a valid intercept URL
45
+ */
46
+ async interceptUrlToFileUrl (interceptUrl) {
47
+ interceptUrl = new URL(interceptUrl)
48
+ if (interceptUrl.origin !== this.#INTERCEPT_ORIGIN) {
49
+ throw new Error(`Invalid intercept URL: ${interceptUrl}`)
50
+ }
51
+ const fileUrl = new URL(interceptUrl.href.slice(this.#INTERCEPT_ORIGIN.length), 'file://')
52
+ const filePath = await realpath(url.fileURLToPath(fileUrl))
53
+ if (![...this.#allowedDirs].some(dir => path.relative(filePath, dir).startsWith('..'))) {
54
+ throw new Error(`Intercept URL is not in an allowed directory: ${interceptUrl}`)
55
+ }
56
+ return fileUrl
57
+ }
58
+
59
+ /**
60
+ * @param {puppeteer.HTTPRequest} request - The intercepted request
61
+ */
62
+ async #interceptRequestHandler (request) {
63
+ try {
64
+ if (request.url().startsWith(this.#INTERCEPT_ORIGIN)) {
65
+ const fileUrl = await this.interceptUrlToFileUrl(request.url())
66
+ return request.respond({
67
+ status: 200,
68
+ headers: {
69
+ 'Access-Control-Allow-Origin': '*'
70
+ },
71
+ contentType: 'application/javascript',
72
+ body: await readFile(fileUrl)
73
+ })
74
+ }
75
+ } catch (error) {
76
+ console.error(`Error handling intercept request for ${request.url()}:`, error)
77
+ request.abort()
78
+ }
79
+ request.continue()
80
+ }
81
+
82
+ /**
83
+ * Intercepts requests to `https://mermaid-cli-intercept.invalid`
84
+ * and serves the corresponding file content.
85
+ *
86
+ * @return {puppeteer.Handler<puppeteer.HTTPRequest>}
87
+ */
88
+ get interceptRequestHandler () {
89
+ return this.#interceptRequestHandler.bind(this)
90
+ }
91
+ }
package/src/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '11.12.0'
1
+ export const version = '11.14.0'