@modern-js/core 1.0.0-alpha.3

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 (83) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/LICENSE +21 -0
  3. package/README.md +32 -0
  4. package/bin/modern-js.js +18 -0
  5. package/dist/js/modern/config/defaults.js +102 -0
  6. package/dist/js/modern/config/index.js +104 -0
  7. package/dist/js/modern/config/mergeConfig.js +20 -0
  8. package/dist/js/modern/config/schema/deploy.js +34 -0
  9. package/dist/js/modern/config/schema/index.js +104 -0
  10. package/dist/js/modern/config/schema/output.js +147 -0
  11. package/dist/js/modern/config/schema/server.js +167 -0
  12. package/dist/js/modern/config/schema/source.js +59 -0
  13. package/dist/js/modern/config/schema/tools.js +33 -0
  14. package/dist/js/modern/context.js +25 -0
  15. package/dist/js/modern/index.js +137 -0
  16. package/dist/js/modern/initWatcher.js +51 -0
  17. package/dist/js/modern/loadEnv.js +12 -0
  18. package/dist/js/modern/loadPlugins.js +66 -0
  19. package/dist/js/modern/utils/commander.js +19 -0
  20. package/dist/js/modern/utils/repeatKeyWarning.js +18 -0
  21. package/dist/js/node/config/defaults.js +109 -0
  22. package/dist/js/node/config/index.js +142 -0
  23. package/dist/js/node/config/mergeConfig.js +32 -0
  24. package/dist/js/node/config/schema/deploy.js +43 -0
  25. package/dist/js/node/config/schema/index.js +126 -0
  26. package/dist/js/node/config/schema/output.js +156 -0
  27. package/dist/js/node/config/schema/server.js +176 -0
  28. package/dist/js/node/config/schema/source.js +68 -0
  29. package/dist/js/node/config/schema/tools.js +40 -0
  30. package/dist/js/node/context.js +52 -0
  31. package/dist/js/node/index.js +212 -0
  32. package/dist/js/node/initWatcher.js +72 -0
  33. package/dist/js/node/loadEnv.js +28 -0
  34. package/dist/js/node/loadPlugins.js +76 -0
  35. package/dist/js/node/utils/commander.js +35 -0
  36. package/dist/js/node/utils/repeatKeyWarning.js +31 -0
  37. package/dist/types/config/defaults.d.ts +27 -0
  38. package/dist/types/config/index.d.ts +125 -0
  39. package/dist/types/config/mergeConfig.d.ts +29 -0
  40. package/dist/types/config/schema/deploy.d.ts +33 -0
  41. package/dist/types/config/schema/index.d.ts +474 -0
  42. package/dist/types/config/schema/output.d.ts +146 -0
  43. package/dist/types/config/schema/server.d.ts +179 -0
  44. package/dist/types/config/schema/source.d.ts +58 -0
  45. package/dist/types/config/schema/tools.d.ts +33 -0
  46. package/dist/types/context.d.ts +20 -0
  47. package/dist/types/index.d.ts +86 -0
  48. package/dist/types/initWatcher.d.ts +4 -0
  49. package/dist/types/loadEnv.d.ts +1 -0
  50. package/dist/types/loadPlugins.d.ts +16 -0
  51. package/dist/types/utils/commander.d.ts +7 -0
  52. package/dist/types/utils/repeatKeyWarning.d.ts +3 -0
  53. package/modern.config.js +13 -0
  54. package/package.json +73 -0
  55. package/src/config/defaults.ts +104 -0
  56. package/src/config/index.ts +296 -0
  57. package/src/config/mergeConfig.ts +68 -0
  58. package/src/config/schema/deploy.ts +23 -0
  59. package/src/config/schema/index.ts +111 -0
  60. package/src/config/schema/output.ts +66 -0
  61. package/src/config/schema/server.ts +105 -0
  62. package/src/config/schema/source.ts +34 -0
  63. package/src/config/schema/tools.ts +15 -0
  64. package/src/context.ts +46 -0
  65. package/src/index.ts +240 -0
  66. package/src/initWatcher.ts +81 -0
  67. package/src/loadEnv.ts +21 -0
  68. package/src/loadPlugins.ts +81 -0
  69. package/src/types.d.ts +0 -0
  70. package/src/utils/commander.ts +22 -0
  71. package/src/utils/repeatKeyWarning.ts +29 -0
  72. package/tests/fixtures/load-plugin/not-found/package.json +3 -0
  73. package/tests/fixtures/load-plugin/not-found/test-plugin-a.js +1 -0
  74. package/tests/fixtures/load-plugin/user-plugins/package.json +3 -0
  75. package/tests/fixtures/load-plugin/user-plugins/test-plugin-a.js +1 -0
  76. package/tests/fixtures/load-plugin/user-plugins/test-plugin-b.js +3 -0
  77. package/tests/loadEnv.test.ts +100 -0
  78. package/tests/loadPlugin.test.ts +29 -0
  79. package/tests/mergeConfig.test.ts +78 -0
  80. package/tests/repeatKeyWarning.test.ts +68 -0
  81. package/tests/schema.test.ts +109 -0
  82. package/tests/tsconfig.json +13 -0
  83. package/tsconfig.json +14 -0
@@ -0,0 +1,100 @@
1
+ import path from 'path';
2
+ import fs from 'fs';
3
+ import { exec } from 'child_process';
4
+ import { loadEnv } from '@/loadEnv';
5
+
6
+ const fixture = path.resolve(__dirname, './fixtures/load-env');
7
+
8
+ fs.mkdirSync(fixture);
9
+
10
+ const createFixtures = (
11
+ dir: string,
12
+ files: {
13
+ name: string;
14
+ content: string;
15
+ }[],
16
+ ) => {
17
+ fs.mkdirSync(path.join(fixture, dir));
18
+ for (const { name, content } of files) {
19
+ fs.writeFileSync(path.join(fixture, dir, name), content, 'utf8');
20
+ }
21
+ };
22
+
23
+ describe('load environment variables', () => {
24
+ const defaultEnv = process.env;
25
+
26
+ beforeEach(() => (process.env = { ...defaultEnv }));
27
+
28
+ afterAll(() => {
29
+ process.env = { ...defaultEnv };
30
+ exec(`rm -rf ${fixture}`);
31
+ });
32
+
33
+ test(`support .env file`, () => {
34
+ createFixtures('base', [
35
+ {
36
+ name: '.env',
37
+ content: `DB_HOST=localhost
38
+ DB_USER=root
39
+ DB_PASS=root
40
+ `,
41
+ },
42
+ ]);
43
+ loadEnv(path.join(fixture, 'base'));
44
+
45
+ expect(process.env.DB_HOST).toBe('localhost');
46
+
47
+ expect(process.env.DB_USER).toBe('root');
48
+
49
+ expect(process.env.DB_PASS).toBe('root');
50
+ });
51
+
52
+ test(`support "environment" .env file`, () => {
53
+ createFixtures('environment', [
54
+ {
55
+ name: '.env',
56
+ content: `DB_HOST=localhost
57
+ DB_USER=root
58
+ DB_PASS=root
59
+ `,
60
+ },
61
+ {
62
+ name: '.env.production',
63
+ content: `DB_HOST=localhost
64
+ DB_USER=root-local-dev
65
+ `,
66
+ },
67
+ ]);
68
+
69
+ process.env.NODE_ENV = 'production';
70
+
71
+ loadEnv(path.join(fixture, 'environment'));
72
+
73
+ expect(process.env.DB_HOST).toBe('localhost');
74
+
75
+ expect(process.env.DB_USER).toBe('root-local-dev');
76
+
77
+ expect(process.env.DB_PASS).toBe('root');
78
+
79
+ delete process.env.NODE_ENV;
80
+ });
81
+
82
+ test(`support dotenv-expand`, () => {
83
+ createFixtures('expand', [
84
+ {
85
+ name: '.env',
86
+ content: `DB_HOST=localhost
87
+ DB_USER=\${DB_HOST}001
88
+ DB_PASS=root
89
+ `,
90
+ },
91
+ ]);
92
+ loadEnv(path.join(fixture, 'expand'));
93
+
94
+ expect(process.env.DB_HOST).toBe('localhost');
95
+
96
+ expect(process.env.DB_USER).toBe('localhost001');
97
+
98
+ expect(process.env.DB_PASS).toBe('root');
99
+ });
100
+ });
@@ -0,0 +1,29 @@
1
+ import path from 'path';
2
+ import { loadPlugins } from '@/loadPlugins';
3
+
4
+ describe('load plugins', () => {
5
+ test('should load user plugin successfully', () => {
6
+ const fixture = path.resolve(
7
+ __dirname,
8
+ './fixtures/load-plugin/user-plugins',
9
+ );
10
+
11
+ const plugins = loadPlugins(fixture, [
12
+ { cli: path.join(fixture, './test-plugin-a.js') },
13
+ { server: './test-plugin-b' },
14
+ ]);
15
+
16
+ expect(plugins).toEqual([
17
+ { cli: { name: 'a' } },
18
+ { server: { name: 'b' } },
19
+ ]);
20
+ });
21
+
22
+ test(`should throw error when plugin not found `, () => {
23
+ const fixture = path.resolve(__dirname, './fixtures/load-plugin/not-found');
24
+
25
+ expect(() => {
26
+ loadPlugins(fixture, [{ cli: './test-plugin-a' }, { cli: './plugin-b' }]);
27
+ }).toThrowError(/^Can not find plugin /);
28
+ });
29
+ });
@@ -0,0 +1,78 @@
1
+ import { mergeConfig } from '@/config/mergeConfig';
2
+
3
+ describe('load plugins', () => {
4
+ test('should replace property deeply', () => {
5
+ expect(
6
+ mergeConfig([
7
+ {
8
+ source: { disableDefaultEntries: false },
9
+ output: { polyfill: 'usage' },
10
+ },
11
+ {
12
+ source: { disableDefaultEntries: true },
13
+ output: { polyfill: 'entry' },
14
+ },
15
+ ]),
16
+ ).toEqual({
17
+ source: { disableDefaultEntries: true },
18
+ output: { polyfill: 'entry' },
19
+ });
20
+ });
21
+
22
+ test(`should set value when property value is undefined `, () => {
23
+ expect(
24
+ mergeConfig([
25
+ { source: { entries: { app: './App.tsx' } } },
26
+ { source: { entries: { app2: './src/App2.tsx' } } },
27
+ { server: { baseUrl: './a' } },
28
+ ]),
29
+ ).toEqual({
30
+ source: {
31
+ entries: {
32
+ app: './App.tsx',
33
+ app2: './src/App2.tsx',
34
+ },
35
+ },
36
+ server: { baseUrl: './a' },
37
+ });
38
+ });
39
+
40
+ test(`should merge array value`, () => {
41
+ expect(
42
+ mergeConfig([
43
+ { source: { envVars: ['a', 'b'] } },
44
+ { source: { globalVars: { A: '1' } } },
45
+ {
46
+ source: {
47
+ disableDefaultEntries: true,
48
+ envVars: ['c', 'd'],
49
+ globalVars: { B: '2' },
50
+ },
51
+ },
52
+ ]),
53
+ ).toEqual({
54
+ source: {
55
+ disableDefaultEntries: true,
56
+ envVars: ['a', 'b', 'c', 'd'],
57
+ globalVars: {
58
+ A: '1',
59
+ B: '2',
60
+ },
61
+ },
62
+ });
63
+ });
64
+
65
+ test(`should merge function and object value`, () => {
66
+ const config = mergeConfig([
67
+ { source: { alias: { a: 'b' } } },
68
+ { source: { alias: () => ({ c: 'd' }) } },
69
+ { tools: { webpack: () => ({}) } },
70
+ ]);
71
+ expect(Array.isArray(config.source.alias)).toBe(true);
72
+ expect(config?.source?.alias?.length).toBe(2);
73
+ expect(typeof (config.source.alias as Array<any>)[1]).toBe('function');
74
+
75
+ expect(Array.isArray(config.tools.webpack)).toBe(true);
76
+ expect(config.tools.webpack?.length).toBe(1);
77
+ });
78
+ });
@@ -0,0 +1,68 @@
1
+ import { repeatKeyWarning } from '@/utils/repeatKeyWarning';
2
+ import { UserConfig } from '@/config';
3
+
4
+ jest.spyOn(process, 'exit').mockImplementation();
5
+
6
+ describe('check repeated keys in user config', () => {
7
+ test(`should exit with error`, () => {
8
+ expect(() => {
9
+ repeatKeyWarning(
10
+ {
11
+ type: 'object',
12
+ properties: {
13
+ a: {
14
+ type: 'object',
15
+ properties: {
16
+ b: {
17
+ type: 'object',
18
+ properties: { c: { type: ['boolean', 'object'] } },
19
+ },
20
+ },
21
+ },
22
+ },
23
+ },
24
+ { a: { b: { c: true } } } as UserConfig,
25
+ { a: { b: { c: false } } } as UserConfig,
26
+ );
27
+ }).toThrowError(
28
+ 'The same configuration a.b.c exists in modern.config.js and package.json.',
29
+ );
30
+ });
31
+
32
+ test(`should exit succcessfully`, () => {
33
+ expect(
34
+ repeatKeyWarning(
35
+ {
36
+ type: 'object',
37
+ properties: {
38
+ a: {
39
+ type: 'object',
40
+ properties: { b: { type: 'string' } },
41
+ },
42
+ },
43
+ c: {
44
+ type: 'object',
45
+ proeperties: {
46
+ d: {
47
+ type: 'object',
48
+ properties: { e: { type: 'string' } },
49
+ },
50
+ f: { type: 'string' },
51
+ },
52
+ },
53
+ },
54
+ {
55
+ a: { b: 'name' },
56
+ c: { d: { e: 's' } },
57
+ } as UserConfig,
58
+ {
59
+ a: {},
60
+ c: {
61
+ d: {},
62
+ f: 'ss',
63
+ },
64
+ } as UserConfig,
65
+ ),
66
+ ).toBeUndefined();
67
+ });
68
+ });
@@ -0,0 +1,109 @@
1
+ import { patchSchema, traverseSchema } from '@/config/schema';
2
+
3
+ describe('patch schemas', () => {
4
+ test('should add schema succcessfully', () => {
5
+ const schema = patchSchema([
6
+ {
7
+ target: 'foo',
8
+ schema: { type: 'string' },
9
+ },
10
+ {
11
+ target: 'deploy.microFrontend.foo',
12
+ schema: { type: 'number' },
13
+ },
14
+ ]);
15
+
16
+ expect(schema.properties).toHaveProperty('foo');
17
+
18
+ expect(
19
+ schema.properties.deploy.properties.microFrontend.properties,
20
+ ).toHaveProperty('foo');
21
+ });
22
+
23
+ test('should throw error when node is undefined', () => {
24
+ expect(() => {
25
+ patchSchema([
26
+ {
27
+ target: 'deploy.a.foo',
28
+ schema: { type: 'string' },
29
+ },
30
+ ]);
31
+ }).toThrowError(/^add schema deploy\.a error$/);
32
+ });
33
+
34
+ test(`should throw error on empty target property`, () => {
35
+ expect(() => {
36
+ patchSchema([
37
+ {
38
+ target: '',
39
+ schema: { type: 'object' },
40
+ },
41
+ ]);
42
+ }).toThrowError('should return target property in plugin schema.');
43
+ });
44
+
45
+ test(`support schema array in one schema`, () => {
46
+ const schema = patchSchema([
47
+ [
48
+ {
49
+ target: 'foo',
50
+ schema: { type: 'string' },
51
+ },
52
+ {
53
+ target: 'tools.foo',
54
+ schema: { type: 'number' },
55
+ },
56
+ ],
57
+ {
58
+ target: 'bar',
59
+ schema: { type: 'string' },
60
+ },
61
+ ]);
62
+
63
+ expect(schema.properties).toHaveProperty('foo');
64
+ expect(schema.properties).toHaveProperty('bar');
65
+ expect(schema.properties.tools.properties).toHaveProperty('foo');
66
+ });
67
+ });
68
+
69
+ describe(`traverse schema`, () => {
70
+ test(`should return all avaliable keys of current schema`, () => {
71
+ const schema = {
72
+ type: 'object',
73
+ properties: {
74
+ source: {
75
+ type: 'object',
76
+ properties: { alias: { type: ['object', 'function'] } },
77
+ },
78
+ a: {
79
+ type: 'object',
80
+ properties: {
81
+ b: {
82
+ type: 'object',
83
+ properties: { c: { type: 'object' } },
84
+ },
85
+ d: { type: 'string' },
86
+ },
87
+ },
88
+ runtime: {
89
+ type: 'object',
90
+ properties: {
91
+ router: { type: ['object', 'boolean'] },
92
+ state: { type: ['object', 'boolean'] },
93
+ },
94
+ },
95
+ runtimeByEntries: { patternProperties: { '^$': { type: 'string' } } },
96
+ dev: { type: ['function', 'string'] },
97
+ },
98
+ };
99
+ expect(traverseSchema(schema as any)).toEqual([
100
+ 'source.alias',
101
+ 'a.b.c',
102
+ 'a.d',
103
+ 'runtime.router',
104
+ 'runtime.state',
105
+ 'runtimeByEntries',
106
+ 'dev',
107
+ ]);
108
+ });
109
+ });
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "@modern-js/tsconfig/base",
3
+ "compilerOptions": {
4
+ "declaration": false,
5
+ "jsx": "preserve",
6
+ "baseUrl": "./",
7
+ "isolatedModules": true,
8
+ "esModuleInterop": true,
9
+ "paths": {
10
+ "@/*": ["../src/*"]
11
+ }
12
+ }
13
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "extends": "@modern-js/tsconfig/base",
3
+ "compilerOptions": {
4
+ "declaration": false,
5
+ "jsx": "preserve",
6
+ "baseUrl": "./",
7
+ "isolatedModules": true,
8
+ "esModuleInterop": true,
9
+ "paths": {
10
+ "@/*": ["./src/*"]
11
+ }
12
+ },
13
+ "include": ["src"]
14
+ }