@docusaurus/core 3.10.1-canary-6640 → 3.10.1-canary-6642

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.
@@ -109,6 +109,9 @@ async function createCLIProgram({ cli, cliArgs, siteDir, config, }) {
109
109
  .option('--no-open', 'do not open page in the browser (default: false)')
110
110
  .option('--poll [interval]', 'use polling rather than watching for reload (default: false). Can specify a poll interval in milliseconds', normalizePollValue)
111
111
  .option('--no-minify', 'build website without minimizing JS bundles (default: false)')
112
+ .option('--https', 'serve the dev site over HTTPS using a self-signed cert (default: false). Preferred over the HTTPS=true env var. Implied when both --ssl-cert and --ssl-key are provided.')
113
+ .option('--ssl-cert <path>', 'path to a TLS certificate file (implies HTTPS). Preferred over the SSL_CRT_FILE env var; CLI takes precedence if both are set.')
114
+ .option('--ssl-key <path>', 'path to a TLS private key file (implies HTTPS). Preferred over the SSL_KEY_FILE env var; CLI takes precedence if both are set.')
112
115
  .action(start_1.start);
113
116
  cli
114
117
  .command('serve [siteDir]')
@@ -11,5 +11,8 @@ export type StartCLIOptions = HostPortOptions & Pick<LoadContextParams, 'locale'
11
11
  open?: boolean;
12
12
  poll?: boolean | number;
13
13
  minify?: boolean;
14
+ https?: true;
15
+ sslCert?: string;
16
+ sslKey?: string;
14
17
  };
15
18
  export declare function start(siteDirParam?: string, cliOptions?: Partial<StartCLIOptions>): Promise<void>;
@@ -42,7 +42,11 @@ function registerWebpackE2ETestHook(compiler) {
42
42
  async function createDevServerConfig({ cliOptions, props, host, port, }) {
43
43
  const { baseUrl, siteDir, siteConfig } = props;
44
44
  const pollingOptions = (0, watcher_1.createPollingOptions)(cliOptions);
45
- const httpsConfig = await (0, getHttpsConfig_1.default)();
45
+ const httpsConfig = await (0, getHttpsConfig_1.default)({
46
+ https: cliOptions.https,
47
+ sslCert: cliOptions.sslCert,
48
+ sslKey: cliOptions.sslKey,
49
+ });
46
50
  // https://webpack.js.org/configuration/dev-server
47
51
  return {
48
52
  hot: cliOptions.hotOnly ? 'only' : true,
@@ -4,7 +4,13 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- export default function getHttpsConfig(): Promise<boolean | {
7
+ type HttpsConfigOptions = {
8
+ https: boolean;
9
+ sslCert: string;
10
+ sslKey: string;
11
+ };
12
+ export default function getHttpsConfig(options?: Partial<HttpsConfigOptions>): Promise<boolean | {
8
13
  cert: Buffer;
9
14
  key: Buffer;
10
15
  }>;
16
+ export {};
@@ -13,48 +13,109 @@ const path_1 = tslib_1.__importDefault(require("path"));
13
13
  const crypto_1 = tslib_1.__importDefault(require("crypto"));
14
14
  const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
15
15
  // Ensure the certificate and key provided are valid and if not
16
- // throw an easy to debug error
17
- function validateKeyAndCerts({ cert, key, keyFile, crtFile, }) {
18
- let encrypted;
16
+ // throw an easy to debug error.
17
+ //
18
+ // Works for any key type (RSA, ECDSA, EdDSA, ...) — parses both PEMs and
19
+ // checks that the public key embedded in the cert matches the public key
20
+ // derived from the private key.
21
+ function validateKeyAndCerts({ cert, key }) {
22
+ let certPublicKey;
19
23
  try {
20
- // publicEncrypt will throw an error with an invalid cert
21
- encrypted = crypto_1.default.publicEncrypt(cert, Buffer.from('test'));
24
+ certPublicKey = new crypto_1.default.X509Certificate(cert.content).publicKey;
22
25
  }
23
- catch (err) {
24
- logger_1.default.error `The certificate path=${crtFile} is invalid.`;
25
- throw err;
26
+ catch (error) {
27
+ throw new Error(logger_1.default.interpolate `The certificate path=${cert.path} is invalid.`, { cause: error });
26
28
  }
29
+ let keyPublicKey;
27
30
  try {
28
- // privateDecrypt will throw an error with an invalid key
29
- crypto_1.default.privateDecrypt(key, encrypted);
31
+ keyPublicKey = crypto_1.default.createPublicKey(crypto_1.default.createPrivateKey(key.content));
30
32
  }
31
- catch (err) {
32
- logger_1.default.error `The certificate key path=${keyFile} is invalid.`;
33
- throw err;
33
+ catch (error) {
34
+ throw new Error(logger_1.default.interpolate `The certificate key path=${key.path} is invalid.`, { cause: error });
34
35
  }
36
+ if (!certPublicKey.equals(keyPublicKey)) {
37
+ throw new Error(logger_1.default.interpolate `The certificate path=${cert.path} and key path=${key.path} do not match.`);
38
+ }
39
+ }
40
+ function getExplicitHttps(options) {
41
+ return (options.https ??
42
+ (typeof process.env.DOCUSAURUS_HTTPS !== 'undefined'
43
+ ? process.env.DOCUSAURUS_HTTPS == 'true'
44
+ : undefined) ??
45
+ (typeof process.env.HTTPS !== 'undefined'
46
+ ? process.env.HTTPS == 'true'
47
+ : undefined));
48
+ }
49
+ async function readCryptoFile(filepath, source) {
50
+ if (!(await fs_extra_1.default.pathExists(filepath))) {
51
+ throw new Error(logger_1.default.interpolate `You specified ${source}, but file at path path=${filepath} can't be found.`);
52
+ }
53
+ try {
54
+ return {
55
+ path: filepath,
56
+ source,
57
+ content: await fs_extra_1.default.readFile(filepath),
58
+ };
59
+ }
60
+ catch (error) {
61
+ throw new Error(logger_1.default.interpolate `You specified ${source}, but file at path path=${filepath} can't be read.`, { cause: error });
62
+ }
63
+ }
64
+ function getCert(options, cwd) {
65
+ if (options.sslCert) {
66
+ return readCryptoFile(path_1.default.resolve(cwd, options.sslCert), 'CLI arg --ssl-cert');
67
+ }
68
+ if (process.env.DOCUSAURUS_SSL_CRT_FILE) {
69
+ return readCryptoFile(path_1.default.resolve(cwd, process.env.DOCUSAURUS_SSL_CRT_FILE), 'env DOCUSAURUS_SSL_CRT_FILE');
70
+ }
71
+ if (process.env.SSL_CRT_FILE) {
72
+ return readCryptoFile(path_1.default.resolve(cwd, process.env.SSL_CRT_FILE), 'env SSL_CRT_FILE');
73
+ }
74
+ return null;
75
+ }
76
+ function getKeyFile(options, cwd) {
77
+ if (options.sslKey) {
78
+ return readCryptoFile(path_1.default.resolve(cwd, options.sslKey), 'CLI arg --ssl-key');
79
+ }
80
+ if (process.env.DOCUSAURUS_SSL_KEY_FILE) {
81
+ return readCryptoFile(path_1.default.resolve(cwd, process.env.DOCUSAURUS_SSL_KEY_FILE), 'env DOCUSAURUS_SSL_KEY_FILE');
82
+ }
83
+ if (process.env.SSL_KEY_FILE) {
84
+ return readCryptoFile(path_1.default.resolve(cwd, process.env.SSL_KEY_FILE), 'env SSL_KEY_FILE');
85
+ }
86
+ return null;
35
87
  }
36
- // Read file and throw an error if it doesn't exist
37
- async function readEnvFile(file, type) {
38
- if (!(await fs_extra_1.default.pathExists(file))) {
39
- throw new Error(`You specified ${type} in your env, but the file "${file}" can't be found.`);
88
+ function ensureCertKeyBothProvided(cert, key) {
89
+ if ((cert || key) && !(cert && key)) {
90
+ const fileProvided = (cert ?? key);
91
+ throw new Error(logger_1.default.interpolate `HTTPS support require proving a certificate and key at the same time.
92
+ You only provided a ${cert ? 'certificate' : 'key'} (with ${fileProvided.source}) at path path=${fileProvided.path}.`);
40
93
  }
41
- return fs_extra_1.default.readFile(file);
42
94
  }
43
95
  // Get the https config
44
- // Return cert files if provided in env, otherwise just true or false
45
- async function getHttpsConfig() {
46
- const appDirectory = await fs_extra_1.default.realpath(process.cwd());
47
- const { SSL_CRT_FILE, SSL_KEY_FILE, HTTPS } = process.env;
48
- const isHttps = HTTPS === 'true';
49
- if (isHttps && SSL_CRT_FILE && SSL_KEY_FILE) {
50
- const crtFile = path_1.default.resolve(appDirectory, SSL_CRT_FILE);
51
- const keyFile = path_1.default.resolve(appDirectory, SSL_KEY_FILE);
52
- const config = {
53
- cert: await readEnvFile(crtFile, 'SSL_CRT_FILE'),
54
- key: await readEnvFile(keyFile, 'SSL_KEY_FILE'),
96
+ // Return cert files if provided via CLI or env, otherwise just true or false.
97
+ // CLI options take precedence over env vars.
98
+ async function getHttpsConfig(options = {}) {
99
+ const cwd = await fs_extra_1.default.realpath(process.cwd());
100
+ const [cert, key] = await Promise.all([
101
+ getCert(options, cwd),
102
+ getKeyFile(options, cwd),
103
+ ]);
104
+ // Providing both cert/key implies HTTPS
105
+ const inferredHttps = !!(cert && key);
106
+ const https = getExplicitHttps(options) ?? inferredHttps;
107
+ if (https && cert && key) {
108
+ validateKeyAndCerts({
109
+ cert,
110
+ key,
111
+ });
112
+ return {
113
+ cert: cert.content,
114
+ key: key.content,
55
115
  };
56
- validateKeyAndCerts({ ...config, keyFile, crtFile });
57
- return config;
58
116
  }
59
- return isHttps;
117
+ ensureCertKeyBothProvided(cert, key);
118
+ // Apparently we can have https without cert/key (historical)
119
+ // although I don't know how this works 🤷‍♂️
120
+ return https;
60
121
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@docusaurus/core",
3
3
  "description": "Easy to Maintain Open Source Documentation Websites",
4
- "version": "3.10.1-canary-6640",
4
+ "version": "3.10.1-canary-6642",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -33,13 +33,13 @@
33
33
  "url": "https://github.com/facebook/docusaurus/issues"
34
34
  },
35
35
  "dependencies": {
36
- "@docusaurus/babel": "3.10.1-canary-6640",
37
- "@docusaurus/bundler": "3.10.1-canary-6640",
38
- "@docusaurus/logger": "3.10.1-canary-6640",
39
- "@docusaurus/mdx-loader": "3.10.1-canary-6640",
40
- "@docusaurus/utils": "3.10.1-canary-6640",
41
- "@docusaurus/utils-common": "3.10.1-canary-6640",
42
- "@docusaurus/utils-validation": "3.10.1-canary-6640",
36
+ "@docusaurus/babel": "3.10.1-canary-6642",
37
+ "@docusaurus/bundler": "3.10.1-canary-6642",
38
+ "@docusaurus/logger": "3.10.1-canary-6642",
39
+ "@docusaurus/mdx-loader": "3.10.1-canary-6642",
40
+ "@docusaurus/utils": "3.10.1-canary-6642",
41
+ "@docusaurus/utils-common": "3.10.1-canary-6642",
42
+ "@docusaurus/utils-validation": "3.10.1-canary-6642",
43
43
  "boxen": "^6.2.1",
44
44
  "chalk": "^4.1.2",
45
45
  "chokidar": "^3.5.3",
@@ -77,8 +77,8 @@
77
77
  "webpack-merge": "^6.0.1"
78
78
  },
79
79
  "devDependencies": {
80
- "@docusaurus/module-type-aliases": "3.10.1-canary-6640",
81
- "@docusaurus/types": "3.10.1-canary-6640",
80
+ "@docusaurus/module-type-aliases": "3.10.1-canary-6642",
81
+ "@docusaurus/types": "3.10.1-canary-6642",
82
82
  "@total-typescript/shoehorn": "^0.1.2",
83
83
  "@types/detect-port": "^1.3.3",
84
84
  "@types/react-dom": "^19.2.3",
@@ -104,5 +104,5 @@
104
104
  "engines": {
105
105
  "node": ">=24.14"
106
106
  },
107
- "gitHead": "cdd938e63e34bb1fb016ef7f9c25e01ab60bf6e4"
107
+ "gitHead": "07f8b9714f5a0c554a615d3d23e0e411ef4ef465"
108
108
  }