@atlaspack/reporter-dev-server 2.14.22 → 2.14.24
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/CHANGELOG.md +18 -0
- package/lib/Server.js +0 -13
- package/lib/ServerDataProvider.js +1 -0
- package/lib/StaticServerDataProvider.js +58 -0
- package/lib/launch-editor.d.js +1 -0
- package/lib/types/ServerDataProvider.d.ts +33 -0
- package/lib/types/StaticServerDataProvider.d.ts +23 -0
- package/lib/types/types.d.ts +34 -0
- package/lib/types.js +1 -0
- package/package.json +13 -8
- package/src/Server.ts +0 -7
- package/src/ServerDataProvider.ts +34 -0
- package/src/StaticServerDataProvider.ts +72 -0
- package/src/launch-editor.d.ts +4 -0
- package/src/types.ts +46 -0
- package/test/StaticServerDataProvider.test.ts +131 -0
- /package/lib/{HMRServer.d.ts → types/HMRServer.d.ts} +0 -0
- /package/lib/{Server.d.ts → types/Server.d.ts} +0 -0
- /package/lib/{ServerReporter.d.ts → types/ServerReporter.d.ts} +0 -0
- /package/lib/{serverErrors.d.ts → types/serverErrors.d.ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @atlaspack/reporter-dev-server
|
|
2
2
|
|
|
3
|
+
## 2.14.24
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies []:
|
|
8
|
+
- @atlaspack/utils@2.18.1
|
|
9
|
+
- @atlaspack/plugin@2.14.24
|
|
10
|
+
- @atlaspack/types@2.15.14
|
|
11
|
+
|
|
12
|
+
## 2.14.23
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- Updated dependencies [[`23d561e`](https://github.com/atlassian-labs/atlaspack/commit/23d561e51e68b0c38fd1ff4e4fb173e5e7b01cf2)]:
|
|
17
|
+
- @atlaspack/utils@2.18.0
|
|
18
|
+
- @atlaspack/types@2.15.13
|
|
19
|
+
- @atlaspack/plugin@2.14.23
|
|
20
|
+
|
|
3
21
|
## 2.14.22
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/lib/Server.js
CHANGED
|
@@ -88,16 +88,6 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e;
|
|
|
88
88
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
89
89
|
// @ts-expect-error TS2307
|
|
90
90
|
|
|
91
|
-
// @ts-expect-error TS7016
|
|
92
|
-
|
|
93
|
-
// @ts-expect-error TS7016
|
|
94
|
-
|
|
95
|
-
// @ts-expect-error TS7016
|
|
96
|
-
|
|
97
|
-
// @ts-expect-error TS7016
|
|
98
|
-
|
|
99
|
-
// @ts-expect-error TS7016
|
|
100
|
-
|
|
101
91
|
function setHeaders(res) {
|
|
102
92
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
103
93
|
res.setHeader('Access-Control-Allow-Methods', 'GET, HEAD, PUT, PATCH, POST, DELETE');
|
|
@@ -425,13 +415,10 @@ class Server {
|
|
|
425
415
|
}
|
|
426
416
|
};
|
|
427
417
|
const app = (0, _connect().default)();
|
|
428
|
-
// @ts-expect-error TS7006
|
|
429
418
|
app.use((req, res, next) => {
|
|
430
419
|
setHeaders(res);
|
|
431
420
|
next();
|
|
432
421
|
});
|
|
433
|
-
|
|
434
|
-
// @ts-expect-error TS7006
|
|
435
422
|
app.use((req, res, next) => {
|
|
436
423
|
if (req.url === '/__parcel_healthcheck') {
|
|
437
424
|
res.statusCode = 200;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.StaticServerDataProvider = void 0;
|
|
7
|
+
function _path() {
|
|
8
|
+
const data = _interopRequireDefault(require("path"));
|
|
9
|
+
_path = function () {
|
|
10
|
+
return data;
|
|
11
|
+
};
|
|
12
|
+
return data;
|
|
13
|
+
}
|
|
14
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
|
+
/**
|
|
16
|
+
* An implementation of ServerDataProvider provides data from a direct `bundleGraph`
|
|
17
|
+
* and `requestBundle` function.
|
|
18
|
+
*/
|
|
19
|
+
class StaticServerDataProvider {
|
|
20
|
+
bundleGraph = null;
|
|
21
|
+
requestBundleFn = null;
|
|
22
|
+
constructor(distDir) {
|
|
23
|
+
this.distDir = distDir;
|
|
24
|
+
}
|
|
25
|
+
getHTMLBundleFilePaths() {
|
|
26
|
+
var _this$bundleGraph;
|
|
27
|
+
return ((_this$bundleGraph = this.bundleGraph) === null || _this$bundleGraph === void 0 ? void 0 : _this$bundleGraph.getBundles().filter(b => _path().default.posix.extname(b.name) === '.html').map(b => _path().default.relative(this.distDir, b.filePath))) ?? [];
|
|
28
|
+
}
|
|
29
|
+
async requestBundle(requestedPath) {
|
|
30
|
+
var _this$bundleGraph2;
|
|
31
|
+
const bundle = (_this$bundleGraph2 = this.bundleGraph) === null || _this$bundleGraph2 === void 0 ? void 0 : _this$bundleGraph2.getBundles().find(b => {
|
|
32
|
+
const relativePath = _path().default.relative(this.distDir, b.filePath);
|
|
33
|
+
return relativePath === requestedPath;
|
|
34
|
+
});
|
|
35
|
+
if (!bundle) {
|
|
36
|
+
return 'not-found';
|
|
37
|
+
}
|
|
38
|
+
if (!this.requestBundleFn) {
|
|
39
|
+
return 'not-found';
|
|
40
|
+
}
|
|
41
|
+
await this.requestBundleFn(bundle);
|
|
42
|
+
return 'requested';
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Update the provider with the latest bundle graph and request function.
|
|
47
|
+
*
|
|
48
|
+
* This should be called after every successful build so that subsequent requests operate on fresh data.
|
|
49
|
+
*
|
|
50
|
+
* @param bundleGraph The most recent bundle graph representing the output of a build.
|
|
51
|
+
* @param requestBundleFn Function that will be called to (re)build a specific bundle on demand.
|
|
52
|
+
*/
|
|
53
|
+
update(bundleGraph, requestBundleFn) {
|
|
54
|
+
this.bundleGraph = bundleGraph;
|
|
55
|
+
this.requestBundleFn = requestBundleFn;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.StaticServerDataProvider = StaticServerDataProvider;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API the dev-server requires from the main application.
|
|
3
|
+
*
|
|
4
|
+
* This interface is used to provide data to the dev-server from the main application.
|
|
5
|
+
* It is used to get the list of HTML bundles and to request a bundle to be rebuilt.
|
|
6
|
+
*/
|
|
7
|
+
export interface ServerDataProvider {
|
|
8
|
+
/**
|
|
9
|
+
* Return relative file paths for every HTML bundle in the current build output.
|
|
10
|
+
*
|
|
11
|
+
* The returned paths are relative to the distribution directory on disk and
|
|
12
|
+
* can therefore be used as HTTP request targets by the dev-server.
|
|
13
|
+
*
|
|
14
|
+
* @returns List of `.html` bundle paths. If no bundle graph is available yet,
|
|
15
|
+
* an empty array should be returned.
|
|
16
|
+
*/
|
|
17
|
+
getHTMLBundleFilePaths(): string[];
|
|
18
|
+
/**
|
|
19
|
+
* Attempt to (re)build the bundle that corresponds to the given request path.
|
|
20
|
+
*
|
|
21
|
+
* If a bundle matching `requestedPath` exists and a request handler has been
|
|
22
|
+
* provided, the implementation should trigger a rebuild and resolve the
|
|
23
|
+
* promise with "requested". Otherwise the promise must resolve with
|
|
24
|
+
* "not-found".
|
|
25
|
+
*
|
|
26
|
+
* @param requestedPath Path (relative to the distribution directory) that
|
|
27
|
+
* identifies the bundle file requested by the browser.
|
|
28
|
+
* @returns A promise that resolves to:
|
|
29
|
+
* - "requested" when the build has been successfully triggered, or
|
|
30
|
+
* - "not-found" when the bundle cannot be handled by the provider.
|
|
31
|
+
*/
|
|
32
|
+
requestBundle(requestedPath: string): Promise<'requested' | 'not-found'>;
|
|
33
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { BundleGraph, PackagedBundle, BuildSuccessEvent } from '@atlaspack/types';
|
|
2
|
+
import { ServerDataProvider } from './ServerDataProvider';
|
|
3
|
+
/**
|
|
4
|
+
* An implementation of ServerDataProvider provides data from a direct `bundleGraph`
|
|
5
|
+
* and `requestBundle` function.
|
|
6
|
+
*/
|
|
7
|
+
export declare class StaticServerDataProvider implements ServerDataProvider {
|
|
8
|
+
private distDir;
|
|
9
|
+
private bundleGraph;
|
|
10
|
+
private requestBundleFn;
|
|
11
|
+
constructor(distDir: string);
|
|
12
|
+
getHTMLBundleFilePaths(): string[];
|
|
13
|
+
requestBundle(requestedPath: string): Promise<'requested' | 'not-found'>;
|
|
14
|
+
/**
|
|
15
|
+
* Update the provider with the latest bundle graph and request function.
|
|
16
|
+
*
|
|
17
|
+
* This should be called after every successful build so that subsequent requests operate on fresh data.
|
|
18
|
+
*
|
|
19
|
+
* @param bundleGraph The most recent bundle graph representing the output of a build.
|
|
20
|
+
* @param requestBundleFn Function that will be called to (re)build a specific bundle on demand.
|
|
21
|
+
*/
|
|
22
|
+
update(bundleGraph: BundleGraph<PackagedBundle>, requestBundleFn: (bundle: PackagedBundle) => Promise<BuildSuccessEvent>): void;
|
|
23
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ServerOptions, PluginLogger, HMROptions, HTTPSOptions, FilePath, PackageManager } from '@atlaspack/types';
|
|
2
|
+
import type { FileSystem } from '@atlaspack/fs';
|
|
3
|
+
import type { HTTPServer } from '@atlaspack/utils';
|
|
4
|
+
import { IncomingMessage, ServerResponse } from 'http';
|
|
5
|
+
interface HTTPRequest extends IncomingMessage {
|
|
6
|
+
originalUrl?: string;
|
|
7
|
+
}
|
|
8
|
+
export type Request = HTTPRequest;
|
|
9
|
+
export type Response = ServerResponse;
|
|
10
|
+
export type DevServerOptions = ServerOptions & {
|
|
11
|
+
projectRoot: string;
|
|
12
|
+
publicUrl: string;
|
|
13
|
+
cacheDir: string;
|
|
14
|
+
inputFS: FileSystem;
|
|
15
|
+
outputFS: FileSystem;
|
|
16
|
+
logger: PluginLogger;
|
|
17
|
+
hmrOptions?: HMROptions | null | undefined;
|
|
18
|
+
packageManager: PackageManager;
|
|
19
|
+
};
|
|
20
|
+
export type ServerError = Error & {
|
|
21
|
+
code: string;
|
|
22
|
+
};
|
|
23
|
+
export type HMRServerOptions = {
|
|
24
|
+
devServer?: HTTPServer;
|
|
25
|
+
addMiddleware?: (handler: (req: Request, res: Response) => boolean) => void;
|
|
26
|
+
port: number;
|
|
27
|
+
host?: string | null | undefined;
|
|
28
|
+
logger: PluginLogger;
|
|
29
|
+
https?: HTTPSOptions | boolean;
|
|
30
|
+
cacheDir: FilePath;
|
|
31
|
+
inputFS: FileSystem;
|
|
32
|
+
outputFS: FileSystem;
|
|
33
|
+
};
|
|
34
|
+
export {};
|
package/lib/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaspack/reporter-dev-server",
|
|
3
|
-
"version": "2.14.
|
|
3
|
+
"version": "2.14.24",
|
|
4
4
|
"description": "Blazing fast, zero configuration web application bundler",
|
|
5
5
|
"license": "(MIT OR Apache-2.0)",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
},
|
|
14
14
|
"main": "./lib/ServerReporter.js",
|
|
15
15
|
"source": "./src/ServerReporter.ts",
|
|
16
|
-
"types": "./lib/ServerReporter.d.ts",
|
|
16
|
+
"types": "./lib/types/ServerReporter.d.ts",
|
|
17
17
|
"engines": {
|
|
18
18
|
"node": ">= 16.0.0"
|
|
19
19
|
},
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@atlaspack/plugin": "2.14.
|
|
30
|
-
"@atlaspack/utils": "2.
|
|
31
|
-
"@atlaspack/types": "2.15.
|
|
29
|
+
"@atlaspack/plugin": "2.14.24",
|
|
30
|
+
"@atlaspack/utils": "2.18.1",
|
|
31
|
+
"@atlaspack/types": "2.15.14",
|
|
32
32
|
"connect": "^3.7.0",
|
|
33
33
|
"ejs": "^3.1.6",
|
|
34
34
|
"fresh": "^0.5.2",
|
|
@@ -40,9 +40,14 @@
|
|
|
40
40
|
"ws": "^7.0.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@atlaspack/babel-preset": "2.14.2"
|
|
43
|
+
"@atlaspack/babel-preset": "2.14.2",
|
|
44
|
+
"@types/connect": "^3.4.38",
|
|
45
|
+
"@types/ejs": "^3.1.5",
|
|
46
|
+
"@types/fresh": "^0.5.3",
|
|
47
|
+
"@types/serve-handler": "^6.1.4"
|
|
44
48
|
},
|
|
45
49
|
"scripts": {
|
|
46
|
-
"check-ts": "tsc --emitDeclarationOnly --rootDir src"
|
|
50
|
+
"check-ts": "tsc --emitDeclarationOnly --rootDir src",
|
|
51
|
+
"build:lib": "gulp build --gulpfile ../../../gulpfile.js --cwd ."
|
|
47
52
|
}
|
|
48
|
-
}
|
|
53
|
+
}
|
package/src/Server.ts
CHANGED
|
@@ -24,17 +24,12 @@ import {
|
|
|
24
24
|
} from '@atlaspack/utils';
|
|
25
25
|
import serverErrors from './serverErrors';
|
|
26
26
|
import fs from 'fs';
|
|
27
|
-
// @ts-expect-error TS7016
|
|
28
27
|
import ejs from 'ejs';
|
|
29
|
-
// @ts-expect-error TS7016
|
|
30
28
|
import connect from 'connect';
|
|
31
|
-
// @ts-expect-error TS7016
|
|
32
29
|
import serveHandler from 'serve-handler';
|
|
33
30
|
import {createProxyMiddleware} from 'http-proxy-middleware';
|
|
34
31
|
import {URL, URLSearchParams} from 'url';
|
|
35
|
-
// @ts-expect-error TS7016
|
|
36
32
|
import launchEditor from 'launch-editor';
|
|
37
|
-
// @ts-expect-error TS7016
|
|
38
33
|
import fresh from 'fresh';
|
|
39
34
|
|
|
40
35
|
export function setHeaders(res: Response) {
|
|
@@ -504,13 +499,11 @@ export default class Server {
|
|
|
504
499
|
};
|
|
505
500
|
|
|
506
501
|
const app = connect();
|
|
507
|
-
// @ts-expect-error TS7006
|
|
508
502
|
app.use((req, res, next) => {
|
|
509
503
|
setHeaders(res);
|
|
510
504
|
next();
|
|
511
505
|
});
|
|
512
506
|
|
|
513
|
-
// @ts-expect-error TS7006
|
|
514
507
|
app.use((req, res, next) => {
|
|
515
508
|
if (req.url === '/__parcel_healthcheck') {
|
|
516
509
|
res.statusCode = 200;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API the dev-server requires from the main application.
|
|
3
|
+
*
|
|
4
|
+
* This interface is used to provide data to the dev-server from the main application.
|
|
5
|
+
* It is used to get the list of HTML bundles and to request a bundle to be rebuilt.
|
|
6
|
+
*/
|
|
7
|
+
export interface ServerDataProvider {
|
|
8
|
+
/**
|
|
9
|
+
* Return relative file paths for every HTML bundle in the current build output.
|
|
10
|
+
*
|
|
11
|
+
* The returned paths are relative to the distribution directory on disk and
|
|
12
|
+
* can therefore be used as HTTP request targets by the dev-server.
|
|
13
|
+
*
|
|
14
|
+
* @returns List of `.html` bundle paths. If no bundle graph is available yet,
|
|
15
|
+
* an empty array should be returned.
|
|
16
|
+
*/
|
|
17
|
+
getHTMLBundleFilePaths(): string[];
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Attempt to (re)build the bundle that corresponds to the given request path.
|
|
21
|
+
*
|
|
22
|
+
* If a bundle matching `requestedPath` exists and a request handler has been
|
|
23
|
+
* provided, the implementation should trigger a rebuild and resolve the
|
|
24
|
+
* promise with "requested". Otherwise the promise must resolve with
|
|
25
|
+
* "not-found".
|
|
26
|
+
*
|
|
27
|
+
* @param requestedPath Path (relative to the distribution directory) that
|
|
28
|
+
* identifies the bundle file requested by the browser.
|
|
29
|
+
* @returns A promise that resolves to:
|
|
30
|
+
* - "requested" when the build has been successfully triggered, or
|
|
31
|
+
* - "not-found" when the bundle cannot be handled by the provider.
|
|
32
|
+
*/
|
|
33
|
+
requestBundle(requestedPath: string): Promise<'requested' | 'not-found'>;
|
|
34
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
BundleGraph,
|
|
3
|
+
PackagedBundle,
|
|
4
|
+
BuildSuccessEvent,
|
|
5
|
+
} from '@atlaspack/types';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
|
|
8
|
+
import {ServerDataProvider} from './ServerDataProvider';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* An implementation of ServerDataProvider provides data from a direct `bundleGraph`
|
|
12
|
+
* and `requestBundle` function.
|
|
13
|
+
*/
|
|
14
|
+
export class StaticServerDataProvider implements ServerDataProvider {
|
|
15
|
+
private distDir: string;
|
|
16
|
+
|
|
17
|
+
private bundleGraph: BundleGraph<PackagedBundle> | null = null;
|
|
18
|
+
|
|
19
|
+
private requestBundleFn:
|
|
20
|
+
| ((bundle: PackagedBundle) => Promise<BuildSuccessEvent>)
|
|
21
|
+
| null = null;
|
|
22
|
+
|
|
23
|
+
constructor(distDir: string) {
|
|
24
|
+
this.distDir = distDir;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
getHTMLBundleFilePaths(): string[] {
|
|
28
|
+
return (
|
|
29
|
+
this.bundleGraph
|
|
30
|
+
?.getBundles()
|
|
31
|
+
.filter((b) => path.posix.extname(b.name) === '.html')
|
|
32
|
+
.map((b) => path.relative(this.distDir, b.filePath)) ?? []
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async requestBundle(
|
|
37
|
+
requestedPath: string,
|
|
38
|
+
): Promise<'requested' | 'not-found'> {
|
|
39
|
+
const bundle = this.bundleGraph?.getBundles().find((b) => {
|
|
40
|
+
const relativePath = path.relative(this.distDir, b.filePath);
|
|
41
|
+
return relativePath === requestedPath;
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
if (!bundle) {
|
|
45
|
+
return 'not-found';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (!this.requestBundleFn) {
|
|
49
|
+
return 'not-found';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
await this.requestBundleFn(bundle);
|
|
53
|
+
|
|
54
|
+
return 'requested';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Update the provider with the latest bundle graph and request function.
|
|
59
|
+
*
|
|
60
|
+
* This should be called after every successful build so that subsequent requests operate on fresh data.
|
|
61
|
+
*
|
|
62
|
+
* @param bundleGraph The most recent bundle graph representing the output of a build.
|
|
63
|
+
* @param requestBundleFn Function that will be called to (re)build a specific bundle on demand.
|
|
64
|
+
*/
|
|
65
|
+
update(
|
|
66
|
+
bundleGraph: BundleGraph<PackagedBundle>,
|
|
67
|
+
requestBundleFn: (bundle: PackagedBundle) => Promise<BuildSuccessEvent>,
|
|
68
|
+
) {
|
|
69
|
+
this.bundleGraph = bundleGraph;
|
|
70
|
+
this.requestBundleFn = requestBundleFn;
|
|
71
|
+
}
|
|
72
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ServerOptions,
|
|
3
|
+
PluginLogger,
|
|
4
|
+
HMROptions,
|
|
5
|
+
HTTPSOptions,
|
|
6
|
+
FilePath,
|
|
7
|
+
PackageManager,
|
|
8
|
+
} from '@atlaspack/types';
|
|
9
|
+
import type {FileSystem} from '@atlaspack/fs';
|
|
10
|
+
import type {HTTPServer} from '@atlaspack/utils';
|
|
11
|
+
import {IncomingMessage, ServerResponse} from 'http';
|
|
12
|
+
|
|
13
|
+
interface HTTPRequest extends IncomingMessage {
|
|
14
|
+
originalUrl?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type Request = HTTPRequest;
|
|
18
|
+
export type Response = ServerResponse;
|
|
19
|
+
|
|
20
|
+
export type DevServerOptions = ServerOptions & {
|
|
21
|
+
projectRoot: string;
|
|
22
|
+
publicUrl: string;
|
|
23
|
+
cacheDir: string;
|
|
24
|
+
inputFS: FileSystem;
|
|
25
|
+
outputFS: FileSystem;
|
|
26
|
+
logger: PluginLogger;
|
|
27
|
+
hmrOptions?: HMROptions | null | undefined;
|
|
28
|
+
packageManager: PackageManager;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// TODO: Figure out if there is a node.js type that could be imported with a complete ServerError
|
|
32
|
+
export type ServerError = Error & {
|
|
33
|
+
code: string;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export type HMRServerOptions = {
|
|
37
|
+
devServer?: HTTPServer;
|
|
38
|
+
addMiddleware?: (handler: (req: Request, res: Response) => boolean) => void;
|
|
39
|
+
port: number;
|
|
40
|
+
host?: string | null | undefined;
|
|
41
|
+
logger: PluginLogger;
|
|
42
|
+
https?: HTTPSOptions | boolean;
|
|
43
|
+
cacheDir: FilePath;
|
|
44
|
+
inputFS: FileSystem;
|
|
45
|
+
outputFS: FileSystem;
|
|
46
|
+
};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import assert from 'assert';
|
|
2
|
+
import sinon from 'sinon';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
import {StaticServerDataProvider} from '../src/StaticServerDataProvider';
|
|
6
|
+
|
|
7
|
+
type MockBundle = {
|
|
8
|
+
name: string;
|
|
9
|
+
filePath: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
describe('StaticServerDataProvider', () => {
|
|
13
|
+
describe('getHTMLBundleFilePaths', () => {
|
|
14
|
+
it('returns an empty array when no bundleGraph is set', () => {
|
|
15
|
+
const provider = new StaticServerDataProvider('/dist');
|
|
16
|
+
assert.deepStrictEqual(provider.getHTMLBundleFilePaths(), []);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('filters only .html bundles and returns relative paths', () => {
|
|
20
|
+
const distDir = path.resolve('/project/dist');
|
|
21
|
+
const provider = new StaticServerDataProvider(distDir);
|
|
22
|
+
|
|
23
|
+
const bundles: MockBundle[] = [
|
|
24
|
+
{
|
|
25
|
+
name: 'index.html',
|
|
26
|
+
filePath: path.join(distDir, 'index.html'),
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'app.js',
|
|
30
|
+
filePath: path.join(distDir, 'app.js'),
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'about/index.html',
|
|
34
|
+
filePath: path.join(distDir, 'about', 'index.html'),
|
|
35
|
+
},
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
const bundleGraphMock = {
|
|
39
|
+
getBundles: () => bundles,
|
|
40
|
+
} as any;
|
|
41
|
+
|
|
42
|
+
// We don't care about requestBundleFn for this test, provide a noop.
|
|
43
|
+
provider.update(bundleGraphMock, () => Promise.resolve({} as any));
|
|
44
|
+
|
|
45
|
+
const htmlPaths = provider.getHTMLBundleFilePaths().sort();
|
|
46
|
+
assert.deepStrictEqual(htmlPaths, ['about/index.html', 'index.html']);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe('requestBundle', () => {
|
|
51
|
+
it('returns "not-found" when no bundleGraph is set', async () => {
|
|
52
|
+
const provider = new StaticServerDataProvider('/dist');
|
|
53
|
+
const result = await provider.requestBundle('index.html');
|
|
54
|
+
assert.strictEqual(result, 'not-found');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('returns "not-found" when the bundle is not present in the graph', async () => {
|
|
58
|
+
const distDir = '/dist';
|
|
59
|
+
const bundles: MockBundle[] = [
|
|
60
|
+
{name: 'index.html', filePath: path.join(distDir, 'index.html')},
|
|
61
|
+
];
|
|
62
|
+
const bundleGraphMock = {
|
|
63
|
+
getBundles: () => bundles,
|
|
64
|
+
} as any;
|
|
65
|
+
|
|
66
|
+
const provider = new StaticServerDataProvider(distDir);
|
|
67
|
+
provider.update(bundleGraphMock, () => Promise.resolve({} as any));
|
|
68
|
+
|
|
69
|
+
const result = await provider.requestBundle('missing.html');
|
|
70
|
+
assert.strictEqual(result, 'not-found');
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('returns "not-found" when requestBundleFn is not set', async () => {
|
|
74
|
+
const distDir = '/dist';
|
|
75
|
+
const bundles: MockBundle[] = [
|
|
76
|
+
{name: 'index.html', filePath: path.join(distDir, 'index.html')},
|
|
77
|
+
];
|
|
78
|
+
const provider = new StaticServerDataProvider(distDir);
|
|
79
|
+
// Directly assign bundleGraph without a requestBundleFn
|
|
80
|
+
(provider as any).bundleGraph = {getBundles: () => bundles} as any;
|
|
81
|
+
|
|
82
|
+
const result = await provider.requestBundle('index.html');
|
|
83
|
+
assert.strictEqual(result, 'not-found');
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('calls requestBundleFn and returns "requested" for a matching bundle', async () => {
|
|
87
|
+
const distDir = '/dist';
|
|
88
|
+
const bundles: MockBundle[] = [
|
|
89
|
+
{name: 'index.html', filePath: path.join(distDir, 'index.html')},
|
|
90
|
+
];
|
|
91
|
+
const bundleGraphMock = {
|
|
92
|
+
getBundles: () => bundles,
|
|
93
|
+
} as any;
|
|
94
|
+
|
|
95
|
+
const requestBundleFn = sinon.stub().resolves();
|
|
96
|
+
|
|
97
|
+
const provider = new StaticServerDataProvider(distDir);
|
|
98
|
+
provider.update(bundleGraphMock, requestBundleFn);
|
|
99
|
+
|
|
100
|
+
const result = await provider.requestBundle('index.html');
|
|
101
|
+
|
|
102
|
+
assert.strictEqual(result, 'requested');
|
|
103
|
+
sinon.assert.calledOnce(requestBundleFn);
|
|
104
|
+
sinon.assert.calledWithExactly(requestBundleFn, bundles[0]);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('handles nested bundle paths correctly', async () => {
|
|
108
|
+
const distDir = '/dist';
|
|
109
|
+
const bundles: MockBundle[] = [
|
|
110
|
+
{
|
|
111
|
+
name: 'nested/index.html',
|
|
112
|
+
filePath: path.join(distDir, 'nested', 'index.html'),
|
|
113
|
+
},
|
|
114
|
+
];
|
|
115
|
+
const bundleGraphMock = {
|
|
116
|
+
getBundles: () => bundles,
|
|
117
|
+
} as any;
|
|
118
|
+
|
|
119
|
+
const requestBundleFn = sinon.stub().resolves();
|
|
120
|
+
|
|
121
|
+
const provider = new StaticServerDataProvider(distDir);
|
|
122
|
+
provider.update(bundleGraphMock, requestBundleFn);
|
|
123
|
+
|
|
124
|
+
const result = await provider.requestBundle('nested/index.html');
|
|
125
|
+
|
|
126
|
+
assert.strictEqual(result, 'requested');
|
|
127
|
+
sinon.assert.calledOnce(requestBundleFn);
|
|
128
|
+
sinon.assert.calledWithExactly(requestBundleFn, bundles[0]);
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
});
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|