@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.
Files changed (126) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/dist/js/modern/dev-tools/babel/register.js +1 -0
  3. package/dist/js/modern/dev-tools/dev-server-plugin.js +1 -2
  4. package/dist/js/modern/dev-tools/mock/getMockData.js +24 -1
  5. package/dist/js/modern/dev-tools/mock/index.js +1 -26
  6. package/dist/js/modern/dev-tools/socket-server.js +4 -2
  7. package/dist/js/modern/dev-tools/watcher/index.js +4 -7
  8. package/dist/js/modern/dev-tools/watcher/stats-cache.js +32 -20
  9. package/dist/js/modern/libs/context/context.js +6 -0
  10. package/dist/js/modern/libs/hook-api/route.js +6 -4
  11. package/dist/js/modern/libs/render/index.js +1 -0
  12. package/dist/js/modern/libs/render/reader.js +1 -2
  13. package/dist/js/modern/libs/render/ssr.js +7 -2
  14. package/dist/js/modern/libs/route/index.js +0 -1
  15. package/dist/js/modern/libs/route/matcher.js +15 -3
  16. package/dist/js/modern/libs/route/route.js +1 -0
  17. package/dist/js/modern/server/dev-server/dev-server.js +3 -0
  18. package/dist/js/modern/server/index.js +5 -4
  19. package/dist/js/modern/server/modern-server-split.js +1 -1
  20. package/dist/js/modern/server/modern-server.js +13 -34
  21. package/dist/js/modern/utils.js +39 -0
  22. package/dist/js/node/dev-tools/babel/register.js +1 -0
  23. package/dist/js/node/dev-tools/dev-server-plugin.js +1 -2
  24. package/dist/js/node/dev-tools/mock/getMockData.js +29 -2
  25. package/dist/js/node/dev-tools/mock/index.js +5 -26
  26. package/dist/js/node/dev-tools/socket-server.js +4 -2
  27. package/dist/js/node/dev-tools/watcher/index.js +7 -5
  28. package/dist/js/node/dev-tools/watcher/stats-cache.js +33 -20
  29. package/dist/js/node/libs/context/context.js +6 -0
  30. package/dist/js/node/libs/hook-api/route.js +6 -4
  31. package/dist/js/node/libs/render/index.js +1 -0
  32. package/dist/js/node/libs/render/reader.js +2 -1
  33. package/dist/js/node/libs/render/ssr.js +8 -2
  34. package/dist/js/node/libs/route/index.js +0 -1
  35. package/dist/js/node/libs/route/matcher.js +16 -3
  36. package/dist/js/node/libs/route/route.js +1 -0
  37. package/dist/js/node/server/dev-server/dev-server.js +3 -0
  38. package/dist/js/node/server/index.js +9 -6
  39. package/dist/js/node/server/modern-server-split.js +1 -1
  40. package/dist/js/node/server/modern-server.js +12 -33
  41. package/dist/js/node/utils.js +51 -2
  42. package/dist/types/dev-tools/mock/getMockData.d.ts +2 -1
  43. package/dist/types/dev-tools/socket-server.d.ts +1 -2
  44. package/dist/types/dev-tools/watcher/index.d.ts +2 -1
  45. package/dist/types/dev-tools/watcher/stats-cache.d.ts +3 -2
  46. package/dist/types/libs/context/context.d.ts +2 -0
  47. package/dist/types/libs/hook-api/route.d.ts +3 -2
  48. package/dist/types/libs/render/reader.d.ts +13 -0
  49. package/dist/types/libs/render/ssr.d.ts +1 -0
  50. package/dist/types/libs/route/matcher.d.ts +1 -1
  51. package/dist/types/libs/route/route.d.ts +1 -0
  52. package/dist/types/server/dev-server/dev-server-split.d.ts +3 -3
  53. package/dist/types/server/modern-server-split.d.ts +3 -3
  54. package/dist/types/server/modern-server.d.ts +1 -2
  55. package/dist/types/type.d.ts +6 -4
  56. package/dist/types/utils.d.ts +5 -1
  57. package/package.json +13 -12
  58. package/tests/context.test.ts +12 -1
  59. package/tests/dev.test.ts +306 -7
  60. package/tests/fixtures/mock/exist/config/mock/index.ts +11 -0
  61. package/tests/fixtures/mock/zero/config/mock/index.ts +1 -0
  62. package/tests/fixtures/pure/tsconfig.json +0 -1
  63. package/tests/fixtures/reader/index.ts +3 -0
  64. package/tests/fixtures/route-spec/dynamic.json +13 -0
  65. package/tests/fixtures/ssr/bundle.js +5 -0
  66. package/tests/fixtures/static-dir/bar.html +11 -0
  67. package/tests/fixtures/static-dir/baz/index.html +11 -0
  68. package/tests/fixtures/static-dir/foo/index.html +11 -0
  69. package/tests/fixtures/watch/a.ts +3 -0
  70. package/tests/fixtures/watch/index.ts +5 -0
  71. package/tests/fixtures/watch/stats.txt +1 -0
  72. package/tests/hook.test.ts +1 -1
  73. package/tests/render.test.ts +102 -0
  74. package/tests/route.test.ts +26 -3
  75. package/tests/utils.test.ts +35 -0
  76. package/tests/watcher.test.ts +6 -4
  77. package/src/constants.ts +0 -26
  78. package/src/dev-tools/babel/register.ts +0 -37
  79. package/src/dev-tools/dev-server-plugin.ts +0 -48
  80. package/src/dev-tools/https/global.d.ts +0 -3
  81. package/src/dev-tools/https/index.ts +0 -12
  82. package/src/dev-tools/launch-editor/index.ts +0 -29
  83. package/src/dev-tools/mock/getMockData.ts +0 -109
  84. package/src/dev-tools/mock/index.ts +0 -63
  85. package/src/dev-tools/socket-server.ts +0 -192
  86. package/src/dev-tools/watcher/dependency-tree.ts +0 -94
  87. package/src/dev-tools/watcher/index.ts +0 -81
  88. package/src/dev-tools/watcher/stats-cache.ts +0 -53
  89. package/src/index.ts +0 -16
  90. package/src/libs/context/context.ts +0 -176
  91. package/src/libs/context/index.ts +0 -7
  92. package/src/libs/hook-api/route.ts +0 -38
  93. package/src/libs/hook-api/template.ts +0 -53
  94. package/src/libs/metrics.ts +0 -15
  95. package/src/libs/proxy.ts +0 -85
  96. package/src/libs/render/cache/__tests__/cache.fun.test.ts +0 -94
  97. package/src/libs/render/cache/__tests__/cache.test.ts +0 -240
  98. package/src/libs/render/cache/__tests__/cacheable.ts +0 -44
  99. package/src/libs/render/cache/__tests__/error-configuration.ts +0 -34
  100. package/src/libs/render/cache/__tests__/matched-cache.ts +0 -88
  101. package/src/libs/render/cache/index.ts +0 -75
  102. package/src/libs/render/cache/page-caches/index.ts +0 -11
  103. package/src/libs/render/cache/page-caches/lru.ts +0 -38
  104. package/src/libs/render/cache/spr.ts +0 -301
  105. package/src/libs/render/cache/type.ts +0 -59
  106. package/src/libs/render/cache/util.ts +0 -97
  107. package/src/libs/render/index.ts +0 -78
  108. package/src/libs/render/modern/browser-list.ts +0 -7
  109. package/src/libs/render/modern/index.ts +0 -41
  110. package/src/libs/render/modern/module.d.ts +0 -4
  111. package/src/libs/render/reader.ts +0 -119
  112. package/src/libs/render/ssr.ts +0 -62
  113. package/src/libs/render/static.ts +0 -52
  114. package/src/libs/render/type.ts +0 -38
  115. package/src/libs/route/index.ts +0 -77
  116. package/src/libs/route/matcher.ts +0 -93
  117. package/src/libs/route/route.ts +0 -32
  118. package/src/libs/serve-file.ts +0 -34
  119. package/src/server/dev-server/dev-server-split.ts +0 -41
  120. package/src/server/dev-server/dev-server.ts +0 -300
  121. package/src/server/dev-server/index.ts +0 -2
  122. package/src/server/index.ts +0 -163
  123. package/src/server/modern-server-split.ts +0 -97
  124. package/src/server/modern-server.ts +0 -636
  125. package/src/type.ts +0 -88
  126. package/src/utils.ts +0 -79
@@ -5,7 +5,6 @@
5
5
  "jsx": "preserve",
6
6
  "baseUrl": "./",
7
7
  "paths": {
8
- ,
9
8
  "@shared/*": ["./shared/*"]
10
9
  }
11
10
  },
@@ -0,0 +1,3 @@
1
+ export default {
2
+ name: 'modern',
3
+ };
@@ -0,0 +1,13 @@
1
+ {
2
+ "routes": [
3
+ {
4
+ "urlPath": "/entry/:id",
5
+ "entryName": "entry",
6
+ "entryPath": "html/entry/index.html",
7
+ "isSPA": true,
8
+ "isSSR": true,
9
+ "enableModernMode": false,
10
+ "bundle": "bundles/entry.js"
11
+ }
12
+ ]
13
+ }
@@ -0,0 +1,5 @@
1
+ const { SERVER_RENDER_FUNCTION_NAME } = require('@modern-js/utils');
2
+
3
+ module.exports = {
4
+ [SERVER_RENDER_FUNCTION_NAME]: () => '<div>Modern.js</div>',
5
+ };
@@ -0,0 +1,11 @@
1
+ <html lang="en">
2
+ <head>
3
+ <meta charset="UTF-8">
4
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>bar</title>
7
+ </head>
8
+ <body>
9
+
10
+ </body>
11
+ </html>
@@ -0,0 +1,11 @@
1
+ <html lang="en">
2
+ <head>
3
+ <meta charset="UTF-8">
4
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>baz</title>
7
+ </head>
8
+ <body>
9
+
10
+ </body>
11
+ </html>
@@ -0,0 +1,11 @@
1
+ <html lang="en">
2
+ <head>
3
+ <meta charset="UTF-8">
4
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>foo</title>
7
+ </head>
8
+ <body>
9
+
10
+ </body>
11
+ </html>
@@ -0,0 +1,3 @@
1
+ export default {
2
+ name: 'a',
3
+ };
@@ -0,0 +1,5 @@
1
+ import a from './a';
2
+
3
+ export default {
4
+ a,
5
+ };
@@ -0,0 +1 @@
1
+ 1
@@ -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
+ });
@@ -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
  });
@@ -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
  });
@@ -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,3 +0,0 @@
1
- declare module 'selfsigned' {
2
- function generate(attributes: any, opt: any): { private: any; cert: any };
3
- }
@@ -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
- };