@modern-js/server 1.3.1-beta.0 → 1.4.1
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 +68 -0
- package/dist/js/modern/dev-tools/babel/register.js +1 -0
- package/dist/js/modern/dev-tools/dev-server-plugin.js +1 -2
- package/dist/js/modern/dev-tools/mock/getMockData.js +24 -1
- package/dist/js/modern/dev-tools/mock/index.js +1 -26
- package/dist/js/modern/dev-tools/socket-server.js +4 -2
- package/dist/js/modern/dev-tools/watcher/index.js +4 -7
- package/dist/js/modern/dev-tools/watcher/stats-cache.js +32 -20
- package/dist/js/modern/libs/context/context.js +6 -0
- package/dist/js/modern/libs/hook-api/route.js +6 -4
- package/dist/js/modern/libs/render/index.js +1 -0
- package/dist/js/modern/libs/render/reader.js +1 -2
- package/dist/js/modern/libs/render/ssr.js +7 -2
- package/dist/js/modern/libs/route/index.js +0 -1
- package/dist/js/modern/libs/route/matcher.js +15 -3
- package/dist/js/modern/libs/route/route.js +1 -0
- package/dist/js/modern/server/dev-server/dev-server.js +3 -0
- package/dist/js/modern/server/index.js +5 -4
- package/dist/js/modern/server/modern-server-split.js +1 -1
- package/dist/js/modern/server/modern-server.js +13 -34
- package/dist/js/modern/utils.js +39 -0
- package/dist/js/node/dev-tools/babel/register.js +1 -0
- package/dist/js/node/dev-tools/dev-server-plugin.js +1 -2
- package/dist/js/node/dev-tools/mock/getMockData.js +29 -2
- package/dist/js/node/dev-tools/mock/index.js +5 -26
- package/dist/js/node/dev-tools/socket-server.js +4 -2
- package/dist/js/node/dev-tools/watcher/index.js +7 -5
- package/dist/js/node/dev-tools/watcher/stats-cache.js +33 -20
- package/dist/js/node/libs/context/context.js +6 -0
- package/dist/js/node/libs/hook-api/route.js +6 -4
- package/dist/js/node/libs/render/index.js +1 -0
- package/dist/js/node/libs/render/reader.js +2 -1
- package/dist/js/node/libs/render/ssr.js +8 -2
- package/dist/js/node/libs/route/index.js +0 -1
- package/dist/js/node/libs/route/matcher.js +16 -3
- package/dist/js/node/libs/route/route.js +1 -0
- package/dist/js/node/server/dev-server/dev-server.js +3 -0
- package/dist/js/node/server/index.js +9 -6
- package/dist/js/node/server/modern-server-split.js +1 -1
- package/dist/js/node/server/modern-server.js +12 -33
- package/dist/js/node/utils.js +51 -2
- package/dist/types/dev-tools/mock/getMockData.d.ts +2 -1
- package/dist/types/dev-tools/socket-server.d.ts +1 -2
- package/dist/types/dev-tools/watcher/index.d.ts +2 -1
- package/dist/types/dev-tools/watcher/stats-cache.d.ts +3 -2
- package/dist/types/libs/context/context.d.ts +2 -0
- package/dist/types/libs/hook-api/route.d.ts +3 -2
- package/dist/types/libs/render/reader.d.ts +13 -0
- package/dist/types/libs/render/ssr.d.ts +1 -0
- package/dist/types/libs/route/matcher.d.ts +1 -1
- package/dist/types/libs/route/route.d.ts +1 -0
- package/dist/types/server/dev-server/dev-server-split.d.ts +3 -3
- package/dist/types/server/modern-server-split.d.ts +3 -3
- package/dist/types/server/modern-server.d.ts +1 -2
- package/dist/types/type.d.ts +6 -4
- package/dist/types/utils.d.ts +5 -1
- package/package.json +13 -12
- package/tests/context.test.ts +12 -1
- package/tests/dev.test.ts +306 -7
- package/tests/fixtures/mock/exist/config/mock/index.ts +11 -0
- package/tests/fixtures/mock/zero/config/mock/index.ts +1 -0
- package/tests/fixtures/pure/tsconfig.json +0 -1
- package/tests/fixtures/reader/index.ts +3 -0
- package/tests/fixtures/route-spec/dynamic.json +13 -0
- package/tests/fixtures/ssr/bundle.js +5 -0
- package/tests/fixtures/static-dir/bar.html +11 -0
- package/tests/fixtures/static-dir/baz/index.html +11 -0
- package/tests/fixtures/static-dir/foo/index.html +11 -0
- package/tests/fixtures/watch/a.ts +3 -0
- package/tests/fixtures/watch/index.ts +5 -0
- package/tests/fixtures/watch/stats.txt +1 -0
- package/tests/hook.test.ts +1 -1
- package/tests/render.test.ts +102 -0
- package/tests/route.test.ts +26 -3
- package/tests/utils.test.ts +35 -0
- package/tests/watcher.test.ts +6 -4
- package/src/constants.ts +0 -26
- package/src/dev-tools/babel/register.ts +0 -37
- package/src/dev-tools/dev-server-plugin.ts +0 -48
- package/src/dev-tools/https/global.d.ts +0 -3
- package/src/dev-tools/https/index.ts +0 -12
- package/src/dev-tools/launch-editor/index.ts +0 -29
- package/src/dev-tools/mock/getMockData.ts +0 -109
- package/src/dev-tools/mock/index.ts +0 -63
- package/src/dev-tools/socket-server.ts +0 -192
- package/src/dev-tools/watcher/dependency-tree.ts +0 -94
- package/src/dev-tools/watcher/index.ts +0 -81
- package/src/dev-tools/watcher/stats-cache.ts +0 -53
- package/src/index.ts +0 -16
- package/src/libs/context/context.ts +0 -176
- package/src/libs/context/index.ts +0 -7
- package/src/libs/hook-api/route.ts +0 -38
- package/src/libs/hook-api/template.ts +0 -53
- package/src/libs/metrics.ts +0 -15
- package/src/libs/proxy.ts +0 -85
- package/src/libs/render/cache/__tests__/cache.fun.test.ts +0 -94
- package/src/libs/render/cache/__tests__/cache.test.ts +0 -240
- package/src/libs/render/cache/__tests__/cacheable.ts +0 -44
- package/src/libs/render/cache/__tests__/error-configuration.ts +0 -34
- package/src/libs/render/cache/__tests__/matched-cache.ts +0 -88
- package/src/libs/render/cache/index.ts +0 -75
- package/src/libs/render/cache/page-caches/index.ts +0 -11
- package/src/libs/render/cache/page-caches/lru.ts +0 -38
- package/src/libs/render/cache/spr.ts +0 -301
- package/src/libs/render/cache/type.ts +0 -59
- package/src/libs/render/cache/util.ts +0 -97
- package/src/libs/render/index.ts +0 -78
- package/src/libs/render/modern/browser-list.ts +0 -7
- package/src/libs/render/modern/index.ts +0 -41
- package/src/libs/render/modern/module.d.ts +0 -4
- package/src/libs/render/reader.ts +0 -119
- package/src/libs/render/ssr.ts +0 -62
- package/src/libs/render/static.ts +0 -52
- package/src/libs/render/type.ts +0 -38
- package/src/libs/route/index.ts +0 -77
- package/src/libs/route/matcher.ts +0 -93
- package/src/libs/route/route.ts +0 -32
- package/src/libs/serve-file.ts +0 -34
- package/src/server/dev-server/dev-server-split.ts +0 -41
- package/src/server/dev-server/dev-server.ts +0 -300
- package/src/server/dev-server/index.ts +0 -2
- package/src/server/index.ts +0 -163
- package/src/server/modern-server-split.ts +0 -97
- package/src/server/modern-server.ts +0 -636
- package/src/type.ts +0 -88
- package/src/utils.ts +0 -79
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1
|
package/tests/hook.test.ts
CHANGED
|
@@ -10,7 +10,7 @@ describe('test hook api', () => {
|
|
|
10
10
|
manager.reset(spec.routes);
|
|
11
11
|
const matcher = manager.match('/home');
|
|
12
12
|
|
|
13
|
-
const routeAPI = createRouteAPI(matcher!, manager);
|
|
13
|
+
const routeAPI = createRouteAPI(matcher!, manager, '');
|
|
14
14
|
expect(routeAPI.cur().entryName).toBe('home');
|
|
15
15
|
expect(routeAPI.get('entry')?.entryPath).toBe('html/entry/index.html');
|
|
16
16
|
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { render } from '../src/libs/render/ssr';
|
|
3
|
+
import { handleDirectory } from '../src/libs/render/static';
|
|
4
|
+
import { LruReader } from '../src/libs/render/reader';
|
|
5
|
+
|
|
6
|
+
describe('test render function', () => {
|
|
7
|
+
test('should return content correctly ', async () => {
|
|
8
|
+
const renderResult = await render(
|
|
9
|
+
{
|
|
10
|
+
params: {},
|
|
11
|
+
pathname: '/foo',
|
|
12
|
+
host: 'localhost:8080',
|
|
13
|
+
query: {},
|
|
14
|
+
url: 'localhost:8080/foo',
|
|
15
|
+
cookieMap: {},
|
|
16
|
+
headers: {},
|
|
17
|
+
} as any,
|
|
18
|
+
{
|
|
19
|
+
urlPath: '/foo',
|
|
20
|
+
bundle: 'bundle.js',
|
|
21
|
+
distDir: path.join(__dirname, 'fixtures', 'ssr'),
|
|
22
|
+
template: 'tpl.html',
|
|
23
|
+
entryName: 'foo',
|
|
24
|
+
staticGenerate: false,
|
|
25
|
+
} as any,
|
|
26
|
+
{
|
|
27
|
+
extendSSRContext: () => {
|
|
28
|
+
// empty
|
|
29
|
+
},
|
|
30
|
+
} as any,
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
expect(renderResult.content).toMatch('Modern.js');
|
|
34
|
+
expect(renderResult.contentType).toMatch('text/html; charset=utf-8');
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('should handle directory for .html correctly', async () => {
|
|
38
|
+
const entryPath = path.join(__dirname, 'fixtures', 'static-dir');
|
|
39
|
+
|
|
40
|
+
const res1 = await handleDirectory(
|
|
41
|
+
{
|
|
42
|
+
path: '/modern/bar',
|
|
43
|
+
} as any,
|
|
44
|
+
entryPath,
|
|
45
|
+
'/modern',
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
expect(res1?.content.toString()).toMatch('bar');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test('should handle directory for index.html correctly', async () => {
|
|
52
|
+
const entryPath = path.join(__dirname, 'fixtures', 'static-dir');
|
|
53
|
+
|
|
54
|
+
const res1 = await handleDirectory(
|
|
55
|
+
{
|
|
56
|
+
path: '/modern/foo',
|
|
57
|
+
} as any,
|
|
58
|
+
entryPath,
|
|
59
|
+
'/modern',
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
expect(res1?.content.toString()).toMatch('foo');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test('should handle directory for /index.html correctly', async () => {
|
|
66
|
+
const entryPath = path.join(__dirname, 'fixtures', 'static-dir');
|
|
67
|
+
|
|
68
|
+
const res1 = await handleDirectory(
|
|
69
|
+
{
|
|
70
|
+
path: '/modern/baz/',
|
|
71
|
+
} as any,
|
|
72
|
+
entryPath,
|
|
73
|
+
'/modern',
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
expect(res1?.content.toString()).toMatch('baz');
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test('should reader work correctly', async () => {
|
|
80
|
+
const reader = new LruReader();
|
|
81
|
+
const dir = path.join(__dirname, 'fixtures', 'reader');
|
|
82
|
+
|
|
83
|
+
const nullRes = await reader.read(path.join(dir, 'foo.ts'));
|
|
84
|
+
expect(nullRes).toBeNull();
|
|
85
|
+
|
|
86
|
+
const dirRes = await reader.read(path.join(dir, 'test-dir'));
|
|
87
|
+
expect(dirRes).toBeNull();
|
|
88
|
+
|
|
89
|
+
const res = await reader.read(path.join(dir, 'index.ts'));
|
|
90
|
+
expect(res).not.toBeNull();
|
|
91
|
+
expect(res?.content.toString()).toMatch('modern');
|
|
92
|
+
|
|
93
|
+
const res1 = await reader.read(path.join(dir, 'index.ts'));
|
|
94
|
+
expect(res1).not.toBeNull();
|
|
95
|
+
expect(res1?.content.toString()).toMatch('modern');
|
|
96
|
+
|
|
97
|
+
reader.update();
|
|
98
|
+
const res2 = await reader.read(path.join(dir, 'index.ts'));
|
|
99
|
+
expect(res2).not.toBeNull();
|
|
100
|
+
expect(res2?.content.toString()).toMatch('modern');
|
|
101
|
+
});
|
|
102
|
+
});
|
package/tests/route.test.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { RouteMatchManager, RouteMatcher } from '../src/libs/route';
|
|
2
2
|
import spec from './fixtures/route-spec/index.json';
|
|
3
|
+
import dynamic from './fixtures/route-spec/dynamic.json';
|
|
3
4
|
|
|
4
5
|
describe('test route', () => {
|
|
5
6
|
describe('test route matcher', () => {
|
|
@@ -12,7 +13,7 @@ describe('test route', () => {
|
|
|
12
13
|
expect(matcher.urlMatcher).toBeUndefined();
|
|
13
14
|
|
|
14
15
|
const { isSSR, isApi, isSPA, urlPath, entryName, entryPath } =
|
|
15
|
-
matcher.generate();
|
|
16
|
+
matcher.generate('');
|
|
16
17
|
|
|
17
18
|
expect(isSSR).toBeTruthy();
|
|
18
19
|
expect(isApi).toBeFalsy();
|
|
@@ -38,11 +39,11 @@ describe('test route', () => {
|
|
|
38
39
|
|
|
39
40
|
const matchedByEntry = manager.matchEntry('home');
|
|
40
41
|
expect(matchedByEntry).toBeDefined();
|
|
41
|
-
expect(matchedByEntry?.generate().entryName).toBe('home');
|
|
42
|
+
expect(matchedByEntry?.generate('').entryName).toBe('home');
|
|
42
43
|
|
|
43
44
|
const matchedByUrl = manager.match('/entry');
|
|
44
45
|
expect(matchedByUrl).toBeDefined();
|
|
45
|
-
expect(matchedByUrl?.generate().entryName).toBe('entry');
|
|
46
|
+
expect(matchedByUrl?.generate('').entryName).toBe('entry');
|
|
46
47
|
|
|
47
48
|
const SSRUrlBundles = manager.getBundles();
|
|
48
49
|
expect(SSRUrlBundles).toEqual(['bundles/entry.js', 'bundles/home.js']);
|
|
@@ -50,5 +51,27 @@ describe('test route', () => {
|
|
|
50
51
|
manager.reset([]);
|
|
51
52
|
expect(manager.matchers.length).toBe(0);
|
|
52
53
|
});
|
|
54
|
+
|
|
55
|
+
test('should manager work correctly with dynamic spec', async () => {
|
|
56
|
+
const manager = new RouteMatchManager();
|
|
57
|
+
expect(manager.matchers.length).toBe(0);
|
|
58
|
+
manager.reset(dynamic.routes);
|
|
59
|
+
expect(manager.matchers.length).toBe(1);
|
|
60
|
+
|
|
61
|
+
const matched = manager.match('/entry/001');
|
|
62
|
+
expect(matched).toBeDefined();
|
|
63
|
+
const route = matched?.generate('/entry/001');
|
|
64
|
+
expect(route?.entryName).toBe('entry');
|
|
65
|
+
expect(route?.params).toEqual({ id: '001' });
|
|
66
|
+
|
|
67
|
+
const matchedWithTrail = manager.match('/entry/001/a');
|
|
68
|
+
expect(matchedWithTrail).toBeDefined();
|
|
69
|
+
const routeWithTrail = matchedWithTrail?.generate('/entry/001/a');
|
|
70
|
+
expect(routeWithTrail?.entryName).toBe('entry');
|
|
71
|
+
expect(routeWithTrail?.params).toEqual({ id: '001' });
|
|
72
|
+
|
|
73
|
+
const miss = manager.match('/entry');
|
|
74
|
+
expect(miss).toBeUndefined();
|
|
75
|
+
});
|
|
53
76
|
});
|
|
54
77
|
});
|
package/tests/utils.test.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { compile } from 'path-to-regexp';
|
|
1
2
|
import {
|
|
2
3
|
noop,
|
|
3
4
|
mergeExtension,
|
|
4
5
|
toMessage,
|
|
5
6
|
createErrorDocument,
|
|
6
7
|
createMiddlewareCollecter,
|
|
8
|
+
getStaticReg,
|
|
7
9
|
} from '../src/utils';
|
|
8
10
|
|
|
9
11
|
describe('test server utils', () => {
|
|
@@ -68,4 +70,37 @@ describe('test server utils', () => {
|
|
|
68
70
|
expect(after.api).toEqual([middleware]);
|
|
69
71
|
});
|
|
70
72
|
});
|
|
73
|
+
|
|
74
|
+
test('should return full path', () => {
|
|
75
|
+
const fn = compile('/home/:id', { encode: encodeURIComponent });
|
|
76
|
+
expect(fn({ id: 2 })).toBe('/home/2');
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
describe('test create static reg', () => {
|
|
80
|
+
test('should test static path correctly', () => {
|
|
81
|
+
const reg = getStaticReg();
|
|
82
|
+
expect(reg.test('/static')).toBeTruthy();
|
|
83
|
+
expect(reg.test('/upload')).toBeTruthy();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test('should test custom static path correctly', () => {
|
|
87
|
+
const reg = getStaticReg({
|
|
88
|
+
cssPath: 'static-css',
|
|
89
|
+
});
|
|
90
|
+
expect(reg.test('/static-css')).toBeTruthy();
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test('should test favicon path correctly', () => {
|
|
94
|
+
const reg = getStaticReg({
|
|
95
|
+
favicon: 'index.icon',
|
|
96
|
+
faviconByEntries: {
|
|
97
|
+
foo: 'foo.icon',
|
|
98
|
+
baz: 'baz.icon',
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
expect(reg.test('/index.icon')).toBeTruthy();
|
|
102
|
+
expect(reg.test('/foo.icon')).toBeTruthy();
|
|
103
|
+
expect(reg.test('/baz.icon')).toBeTruthy();
|
|
104
|
+
});
|
|
105
|
+
});
|
|
71
106
|
});
|
package/tests/watcher.test.ts
CHANGED
|
@@ -20,7 +20,6 @@ describe('watcher', () => {
|
|
|
20
20
|
fs.removeSync(serverDir);
|
|
21
21
|
}
|
|
22
22
|
const writeFiles = () => {
|
|
23
|
-
fs.mkdirSync(serverDir);
|
|
24
23
|
fs.writeFileSync(
|
|
25
24
|
path.normalize(path.join(serverDir, 'index.js')),
|
|
26
25
|
'test',
|
|
@@ -32,6 +31,8 @@ describe('watcher', () => {
|
|
|
32
31
|
fs.removeSync(serverDir);
|
|
33
32
|
};
|
|
34
33
|
|
|
34
|
+
fs.mkdirSync(serverDir);
|
|
35
|
+
|
|
35
36
|
watcher.listen(
|
|
36
37
|
[`${serverDir}/**/*`],
|
|
37
38
|
{
|
|
@@ -61,9 +62,6 @@ describe('watcher', () => {
|
|
|
61
62
|
}
|
|
62
63
|
|
|
63
64
|
const writeFiles = () => {
|
|
64
|
-
fs.mkdirSync(path.normalize(path.join(apiDir, 'typings')), {
|
|
65
|
-
recursive: true,
|
|
66
|
-
});
|
|
67
65
|
fs.writeFileSync(
|
|
68
66
|
path.normalize(path.join(apiDir, 'typings/index.js')),
|
|
69
67
|
'test',
|
|
@@ -75,6 +73,10 @@ describe('watcher', () => {
|
|
|
75
73
|
fs.removeSync(apiDir);
|
|
76
74
|
};
|
|
77
75
|
|
|
76
|
+
fs.mkdirSync(path.normalize(path.join(apiDir, 'typings')), {
|
|
77
|
+
recursive: true,
|
|
78
|
+
});
|
|
79
|
+
|
|
78
80
|
watcher.listen(
|
|
79
81
|
[`${apiDir}/**/*`],
|
|
80
82
|
{
|
package/src/constants.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
export const AGGRED_DIR = {
|
|
2
|
-
mock: 'config/mock',
|
|
3
|
-
server: 'server',
|
|
4
|
-
api: 'api',
|
|
5
|
-
shared: 'shared',
|
|
6
|
-
lambda: 'lambda',
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export enum ApiServerMode {
|
|
10
|
-
func = 'function',
|
|
11
|
-
frame = 'framework',
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const ERROR_DIGEST = {
|
|
15
|
-
INIT: 'Server init error',
|
|
16
|
-
ENOTF: 'Page could not be found',
|
|
17
|
-
WARMUP: 'SSR warmup failed',
|
|
18
|
-
EINTER: 'Internal server error',
|
|
19
|
-
ERENDER: 'SSR render failed',
|
|
20
|
-
EMICROINJ: 'Get micro-frontend info failed',
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export const ERROR_PAGE_TEXT: Record<number, string> = {
|
|
24
|
-
404: 'This page could not be found.',
|
|
25
|
-
500: 'Internal Server Error.',
|
|
26
|
-
};
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import { resolveBabelConfig } from '@modern-js/server-utils';
|
|
3
|
-
import { ModernServerOptions } from '../../type';
|
|
4
|
-
|
|
5
|
-
const registerDirs = ['./api', './server', './config/mock', './shared'];
|
|
6
|
-
|
|
7
|
-
export const enableRegister = (
|
|
8
|
-
projectRoot: string,
|
|
9
|
-
config: ModernServerOptions['config'],
|
|
10
|
-
) => {
|
|
11
|
-
const TS_CONFIG_FILENAME = `tsconfig.json`;
|
|
12
|
-
const tsconfigPath = path.resolve(projectRoot, TS_CONFIG_FILENAME);
|
|
13
|
-
|
|
14
|
-
const babelConfig = resolveBabelConfig(projectRoot, config, {
|
|
15
|
-
tsconfigPath,
|
|
16
|
-
syntax: 'es6+',
|
|
17
|
-
type: 'commonjs',
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
return require('@babel/register')({
|
|
21
|
-
...babelConfig,
|
|
22
|
-
only: [
|
|
23
|
-
function (filePath: string) {
|
|
24
|
-
// TODO: wait params
|
|
25
|
-
if (filePath.includes(`node_modules${path.sep}.modern-js`)) {
|
|
26
|
-
return true;
|
|
27
|
-
}
|
|
28
|
-
return registerDirs.some(registerDir =>
|
|
29
|
-
filePath.startsWith(path.join(projectRoot, registerDir)),
|
|
30
|
-
);
|
|
31
|
-
},
|
|
32
|
-
],
|
|
33
|
-
extensions: ['.js', '.ts'],
|
|
34
|
-
babelrc: false,
|
|
35
|
-
root: projectRoot,
|
|
36
|
-
});
|
|
37
|
-
};
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import Webpack from 'webpack';
|
|
2
|
-
import { DevServerOptions } from '../type';
|
|
3
|
-
|
|
4
|
-
const { EntryPlugin } = Webpack;
|
|
5
|
-
export default class DevServerPlugin {
|
|
6
|
-
private readonly options: DevServerOptions;
|
|
7
|
-
|
|
8
|
-
constructor(options: DevServerOptions) {
|
|
9
|
-
this.options = options;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
apply(compiler: Webpack.Compiler) {
|
|
13
|
-
const { options } = this;
|
|
14
|
-
|
|
15
|
-
const host = `&host=${options.client.host || 'localhost'}`;
|
|
16
|
-
const path = `&path=${options.client.path}`;
|
|
17
|
-
const port = `&port=${options.client.port}`;
|
|
18
|
-
|
|
19
|
-
// Todo @songzhenwei
|
|
20
|
-
const clientEntry = `${require.resolve(
|
|
21
|
-
'@modern-js/hmr-client',
|
|
22
|
-
)}?${host}${path}${port}`;
|
|
23
|
-
const hotEntry = require.resolve('webpack/hot/dev-server');
|
|
24
|
-
const additionalEntries = [clientEntry, hotEntry];
|
|
25
|
-
|
|
26
|
-
// use a hook to add entries if available
|
|
27
|
-
for (const additionalEntry of additionalEntries) {
|
|
28
|
-
new EntryPlugin(compiler.context, additionalEntry, {
|
|
29
|
-
name: undefined,
|
|
30
|
-
}).apply(compiler);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Todo remove, client must inject.
|
|
34
|
-
const compilerOptions = compiler.options;
|
|
35
|
-
compilerOptions.plugins = compilerOptions.plugins || [];
|
|
36
|
-
if (
|
|
37
|
-
hotEntry &&
|
|
38
|
-
!compilerOptions.plugins.find(
|
|
39
|
-
p => p.constructor === Webpack.HotModuleReplacementPlugin,
|
|
40
|
-
)
|
|
41
|
-
) {
|
|
42
|
-
// apply the HMR plugin, if it didn't exist before.
|
|
43
|
-
const plugin = new Webpack.HotModuleReplacementPlugin();
|
|
44
|
-
|
|
45
|
-
plugin.apply(compiler);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import * as devcert from 'devcert';
|
|
2
|
-
|
|
3
|
-
export const genHttpsOptions = async (userOptions: any) => {
|
|
4
|
-
const httpsOptions = userOptions === true ? {} : userOptions;
|
|
5
|
-
|
|
6
|
-
if (!httpsOptions.key || !httpsOptions.cert) {
|
|
7
|
-
const selfsign = await devcert.certificateFor(['localhost']);
|
|
8
|
-
return selfsign;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
return httpsOptions;
|
|
12
|
-
};
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { LAUNCH_EDITOR_ENDPOINT, logger } from '@modern-js/utils';
|
|
2
|
-
import { ModernServerContext } from '../../libs/context';
|
|
3
|
-
import { NextFunction } from '../../type';
|
|
4
|
-
|
|
5
|
-
export const createLaunchEditorHandler =
|
|
6
|
-
// eslint-disable-next-line consistent-return
|
|
7
|
-
() => (ctx: ModernServerContext, next: NextFunction) => {
|
|
8
|
-
if (ctx.url.startsWith(LAUNCH_EDITOR_ENDPOINT)) {
|
|
9
|
-
const { filename, line = 1, column = 1 } = ctx.query;
|
|
10
|
-
if (!filename) {
|
|
11
|
-
ctx.status = 500;
|
|
12
|
-
ctx.res.end(
|
|
13
|
-
`launch-editor-middleware: required query param "filename" is missing.`,
|
|
14
|
-
);
|
|
15
|
-
} else {
|
|
16
|
-
require('launch-editor')(
|
|
17
|
-
`${filename as string}:${line as string}:${column as string}`,
|
|
18
|
-
'code',
|
|
19
|
-
(file: string, errorMessage: string) => {
|
|
20
|
-
logger.error(`Launch ${file} in editor failed.\n${errorMessage}`);
|
|
21
|
-
},
|
|
22
|
-
);
|
|
23
|
-
ctx.status = 200;
|
|
24
|
-
ctx.res.end();
|
|
25
|
-
}
|
|
26
|
-
} else {
|
|
27
|
-
return next();
|
|
28
|
-
}
|
|
29
|
-
};
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { IncomingMessage, ServerResponse } from 'http';
|
|
2
|
-
import { compatRequire } from '@modern-js/utils';
|
|
3
|
-
import { NextFunction } from '../../type';
|
|
4
|
-
import { ModernServerContext } from '../../libs/context';
|
|
5
|
-
|
|
6
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
7
|
-
const VALID_METHODS = ['get', 'post', 'put', 'delete', 'patch'];
|
|
8
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
9
|
-
const BODY_PARSED_METHODS = ['post', 'put', 'delete', 'patch'];
|
|
10
|
-
|
|
11
|
-
export type MockConfig = Record<
|
|
12
|
-
string,
|
|
13
|
-
| {
|
|
14
|
-
data: any;
|
|
15
|
-
}
|
|
16
|
-
| ((
|
|
17
|
-
req: IncomingMessage,
|
|
18
|
-
res: ServerResponse,
|
|
19
|
-
next: NextFunction,
|
|
20
|
-
) => Promise<void>)
|
|
21
|
-
>;
|
|
22
|
-
|
|
23
|
-
export type MockApi = {
|
|
24
|
-
method: string;
|
|
25
|
-
path: string;
|
|
26
|
-
handler: ReturnType<
|
|
27
|
-
typeof createFunctionDataHandler | typeof createStaticDataHandler
|
|
28
|
-
>;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const createFunctionDataHandler =
|
|
32
|
-
(
|
|
33
|
-
method: string,
|
|
34
|
-
handler: (
|
|
35
|
-
req: IncomingMessage,
|
|
36
|
-
res: ServerResponse,
|
|
37
|
-
next: NextFunction,
|
|
38
|
-
) => void,
|
|
39
|
-
) =>
|
|
40
|
-
async (context: ModernServerContext, next: NextFunction) => {
|
|
41
|
-
const { req, res } = context;
|
|
42
|
-
return handler(req, res, next);
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const createStaticDataHandler =
|
|
46
|
-
(method: string, handler: Record<string, any>) =>
|
|
47
|
-
(context: ModernServerContext) => {
|
|
48
|
-
const { res } = context;
|
|
49
|
-
res.setHeader('Content-Type', 'application/json');
|
|
50
|
-
res.end(JSON.stringify(handler));
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
const allowTypes = ['object', 'function'];
|
|
54
|
-
const normalizeConfig = (mockConfig: MockConfig) =>
|
|
55
|
-
Object.keys(mockConfig).reduce((acc, key) => {
|
|
56
|
-
const handler = mockConfig[key];
|
|
57
|
-
const type = typeof handler;
|
|
58
|
-
|
|
59
|
-
if (!allowTypes.includes(type)) {
|
|
60
|
-
throw new Error(
|
|
61
|
-
`mock value of ${key} should be object or function, but got ${type}`,
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const meta = parseKey(key);
|
|
66
|
-
if (type === 'object') {
|
|
67
|
-
acc.push({
|
|
68
|
-
...meta,
|
|
69
|
-
handler: createStaticDataHandler(meta.method, handler),
|
|
70
|
-
});
|
|
71
|
-
} else {
|
|
72
|
-
acc.push({
|
|
73
|
-
...meta,
|
|
74
|
-
handler: createFunctionDataHandler(meta.method, handler as any),
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return acc;
|
|
79
|
-
}, [] as MockApi[]);
|
|
80
|
-
|
|
81
|
-
const _blank = ' ';
|
|
82
|
-
const parseKey = (key: string) => {
|
|
83
|
-
// 'Method /pathname' | '/pathname'
|
|
84
|
-
const splited = key.split(_blank).filter(Boolean);
|
|
85
|
-
if (splited.length > 1) {
|
|
86
|
-
const [method, pathname] = splited;
|
|
87
|
-
return {
|
|
88
|
-
method: method.toLowerCase(),
|
|
89
|
-
path: pathname,
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// default return get method
|
|
94
|
-
return {
|
|
95
|
-
method: 'get',
|
|
96
|
-
path: key,
|
|
97
|
-
};
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
export default (filepath: string) => {
|
|
101
|
-
const mockModule = compatRequire(filepath);
|
|
102
|
-
|
|
103
|
-
if (!mockModule) {
|
|
104
|
-
throw new Error(`Mock file ${filepath} parsed failed!`);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const data = normalizeConfig(mockModule);
|
|
108
|
-
return data;
|
|
109
|
-
};
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import { fs } from '@modern-js/utils';
|
|
3
|
-
import { match } from 'path-to-regexp';
|
|
4
|
-
import { NextFunction } from '../../type';
|
|
5
|
-
import { ModernServerContext } from '../../libs/context';
|
|
6
|
-
import { AGGRED_DIR } from '../../constants';
|
|
7
|
-
import getMockData, { MockApi } from './getMockData';
|
|
8
|
-
|
|
9
|
-
const getMatched = (context: ModernServerContext, mockApiList: MockApi[]) => {
|
|
10
|
-
const { path: targetPathname, method: targetMethod } = context;
|
|
11
|
-
|
|
12
|
-
const matched = mockApiList.find(mockApi => {
|
|
13
|
-
const { method, path: pathname } = mockApi;
|
|
14
|
-
if (method.toLowerCase() === targetMethod.toLowerCase()) {
|
|
15
|
-
return match(pathname, {
|
|
16
|
-
encode: encodeURI,
|
|
17
|
-
decode: decodeURIComponent,
|
|
18
|
-
})(targetPathname);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return false;
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
return matched;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export const createMockHandler = ({ pwd }: { pwd: string }) => {
|
|
28
|
-
const exts = ['.ts', '.js'];
|
|
29
|
-
let filepath = '';
|
|
30
|
-
|
|
31
|
-
for (const ext of exts) {
|
|
32
|
-
const maybeMatch = path.join(pwd, `${AGGRED_DIR.mock}/index${ext}`);
|
|
33
|
-
if (fs.existsSync(maybeMatch)) {
|
|
34
|
-
filepath = maybeMatch;
|
|
35
|
-
break;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (!filepath) {
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const apiList = getMockData(filepath);
|
|
44
|
-
if (!apiList || apiList.length === 0) {
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return async (context: ModernServerContext, next: NextFunction) => {
|
|
49
|
-
const { res } = context;
|
|
50
|
-
const matched = getMatched(context, apiList);
|
|
51
|
-
|
|
52
|
-
if (!matched) {
|
|
53
|
-
return next();
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (matched) {
|
|
57
|
-
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
58
|
-
return matched.handler(context, next);
|
|
59
|
-
} else {
|
|
60
|
-
return next();
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
};
|