@modern-js/plugin-data-loader 2.0.0-beta.0 → 2.0.0-beta.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.
@@ -1,8 +1,6 @@
1
1
  // eslint-disable-next-line eslint-comments/disable-enable-pair
2
-
3
2
  /* eslint-disable node/prefer-global/url */
4
3
  // eslint-disable-next-line eslint-comments/disable-enable-pair
5
-
6
4
  /* eslint-disable node/no-unsupported-features/node-builtins */
7
5
  import { compile } from 'path-to-regexp';
8
6
  export const getRequestUrl = ({
@@ -29,7 +27,6 @@ export const createRequest = (routeId, method = 'get') => {
29
27
  request,
30
28
  routeId
31
29
  });
32
-
33
30
  try {
34
31
  const res = await fetch(url, {
35
32
  method,
@@ -2,11 +2,12 @@ import path from 'path';
2
2
  import { getRouteId } from '@modern-js/utils';
3
3
  export const generateClient = ({
4
4
  basedir,
5
- filename
5
+ filename,
6
+ entryName
6
7
  }) => {
7
8
  // TODO: loader 的约定变更
8
9
  const componentPath = path.join(path.dirname(filename), 'layout.ts');
9
- const routeId = getRouteId(componentPath, basedir);
10
+ const routeId = getRouteId(componentPath, basedir, entryName);
10
11
  const requestCreatorPath = path.join(__dirname, './create-request').replace('node', 'treeshaking').replace(/\\/g, '/');
11
12
  const importCode = `
12
13
  import { createRequest } from '${requestCreatorPath}';
@@ -1,21 +1,19 @@
1
1
  // eslint-disable-next-line eslint-comments/disable-enable-pair
2
-
3
2
  /* eslint-disable @babel/no-invalid-this */
3
+
4
4
  import { generateClient } from "./generate-client";
5
5
  export default async function loader(source) {
6
6
  var _this$_compiler;
7
-
8
7
  this.cacheable();
9
8
  const target = (_this$_compiler = this._compiler) === null || _this$_compiler === void 0 ? void 0 : _this$_compiler.options.target;
10
-
11
9
  if (target === 'node') {
12
10
  return source;
13
11
  }
14
-
15
12
  const options = this.getOptions();
16
13
  const code = generateClient({
17
14
  basedir: options.routesDir,
18
- filename: this.resourcePath
15
+ filename: this.resourcePath,
16
+ entryName: options.entryName
19
17
  });
20
18
  return code;
21
19
  }
@@ -1,9 +1,6 @@
1
1
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
2
-
3
2
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
4
-
5
3
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
6
-
7
4
  import { installGlobals, writeReadableStreamToWritable, Response as NodeResponse } from '@remix-run/node';
8
5
  import { matchRoutes } from 'react-router-dom';
9
6
  // Polyfill Web Fetch API
@@ -16,23 +13,20 @@ export function isRedirectResponse(response) {
16
13
  export function isResponse(value) {
17
14
  return value != null && typeof value.status === 'number' && typeof value.statusText === 'string' && typeof value.headers === 'object' && typeof value.body !== 'undefined';
18
15
  }
19
-
20
16
  const json = (data, init = {}) => {
21
17
  const responseInit = typeof init === 'number' ? {
22
18
  status: init
23
19
  } : init;
24
20
  const headers = new Headers(responseInit.headers);
25
-
26
21
  if (!headers.has('Content-Type')) {
27
22
  headers.set('Content-Type', 'application/json; charset=utf-8');
28
23
  }
29
-
30
24
  return new NodeResponse(JSON.stringify(data), _objectSpread(_objectSpread({}, responseInit), {}, {
31
25
  headers
32
26
  }));
33
- }; // TODO: 添加 context
34
-
27
+ };
35
28
 
29
+ // TODO: 添加 context
36
30
  const callRouteLoader = async ({
37
31
  routeId,
38
32
  loader,
@@ -44,9 +38,7 @@ const callRouteLoader = async ({
44
38
  if (!loader) {
45
39
  throw new Error(`You made a ${request.method} request to ${request.url} but did not provide ` + `a default component or \`loader\` for route "${routeId}", ` + `so there is no way to handle the request.`);
46
40
  }
47
-
48
41
  let result;
49
-
50
42
  try {
51
43
  result = await loader({
52
44
  request,
@@ -56,20 +48,15 @@ const callRouteLoader = async ({
56
48
  if (!isResponse(error)) {
57
49
  throw error;
58
50
  }
59
-
60
51
  result = error;
61
52
  }
62
-
63
53
  if (result === undefined) {
64
54
  throw new Error(`You defined a loader for route "${routeId}" but didn't return ` + `anything from your \`loader\` function. Please return a value or \`null\`.`);
65
55
  }
66
-
67
56
  return isResponse(result) ? result : json(result);
68
57
  };
69
-
70
58
  const createLoaderHeaders = requestHeaders => {
71
59
  const headers = new Headers();
72
-
73
60
  for (const [key, values] of Object.entries(requestHeaders)) {
74
61
  if (values) {
75
62
  if (Array.isArray(values)) {
@@ -81,13 +68,11 @@ const createLoaderHeaders = requestHeaders => {
81
68
  }
82
69
  }
83
70
  }
84
-
85
71
  return headers;
86
72
  };
87
-
88
73
  const createLoaderRequest = context => {
89
- const origin = `${context.protocol}://${context.host}`; // eslint-disable-next-line node/no-unsupported-features/node-builtins, node/prefer-global/url
90
-
74
+ const origin = `${context.protocol}://${context.host}`;
75
+ // eslint-disable-next-line node/no-unsupported-features/node-builtins, node/prefer-global/url
91
76
  const url = new URL(context.url, origin);
92
77
  const controller = new AbortController();
93
78
  const init = {
@@ -97,34 +82,27 @@ const createLoaderRequest = context => {
97
82
  };
98
83
  return new Request(url.href, init);
99
84
  };
100
-
101
85
  const sendLoaderResponse = async (res, nodeResponse) => {
102
86
  res.statusMessage = nodeResponse.statusText;
103
87
  res.statusCode = nodeResponse.status;
104
-
105
88
  for (const [key, value] of nodeResponse.headers.entries()) {
106
89
  res.setHeader(key, value);
107
90
  }
108
-
109
91
  if (nodeResponse.body) {
110
92
  await writeReadableStreamToWritable(nodeResponse.body, res);
111
93
  } else {
112
94
  res.end();
113
95
  }
114
96
  };
115
-
116
97
  export const getPathWithoutEntry = (pathname, entryPath) => {
117
98
  if (entryPath === '/') {
118
99
  return pathname;
119
100
  }
120
-
121
101
  return pathname.replace(entryPath, '');
122
102
  };
123
-
124
103
  const matchEntry = (pathname, entries) => {
125
104
  return entries.find(entry => pathname.startsWith(entry.urlPath));
126
105
  };
127
-
128
106
  export const handleRequest = async ({
129
107
  context,
130
108
  serverRoutes,
@@ -135,48 +113,37 @@ export const handleRequest = async ({
135
113
  query
136
114
  } = context;
137
115
  const routeId = query[LOADER_SEARCH_PARAM];
138
-
139
116
  if (!routeId || method.toLowerCase() !== 'get') {
140
117
  return;
141
118
  }
142
-
143
119
  const entry = matchEntry(context.path, serverRoutes);
144
-
145
120
  if (!entry) {
146
121
  return;
147
122
  }
148
-
149
123
  const {
150
124
  routes
151
125
  } = await import(`${distDir}/loader-routes/${entry.entryName}`);
152
-
153
126
  if (!routes) {
154
127
  return;
155
128
  }
156
-
157
129
  const {
158
130
  res
159
131
  } = context;
160
132
  const pathname = getPathWithoutEntry(context.path, entry.urlPath);
161
133
  const matches = matchRoutes(routes, pathname);
162
-
163
134
  if (!matches) {
164
135
  res.statusCode = 403;
165
136
  res.end(`Route ${pathname} was not matched`);
166
137
  return;
167
138
  }
168
-
169
139
  const match = matches === null || matches === void 0 ? void 0 : matches.find(match => match.route.id === routeId);
170
-
171
140
  if (!match) {
172
141
  res.statusCode = 403;
173
142
  res.end(`Route ${routeId} does not match URL ${context.path}`);
174
143
  return;
175
144
  }
176
-
177
145
  const request = createLoaderRequest(context);
178
146
  let response;
179
-
180
147
  try {
181
148
  response = await callRouteLoader({
182
149
  loader: match.route.loader,
@@ -184,7 +151,8 @@ export const handleRequest = async ({
184
151
  params: match.params,
185
152
  request,
186
153
  loadContext: {}
187
- }); // TODO: 处理 redirect
154
+ });
155
+ // TODO: 处理 redirect
188
156
  } catch (error) {
189
157
  const message = String(error);
190
158
  response = new NodeResponse(message, {
@@ -194,7 +162,6 @@ export const handleRequest = async ({
194
162
  }
195
163
  });
196
164
  }
197
-
198
165
  sendLoaderResponse(res, response);
199
166
  };
200
167
  export default (() => ({
@@ -212,6 +179,5 @@ export default (() => ({
212
179
  });
213
180
  };
214
181
  }
215
-
216
182
  })
217
183
  }));
@@ -4,15 +4,12 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.getRequestUrl = exports.createRequest = void 0;
7
-
8
7
  var _pathToRegexp = require("path-to-regexp");
9
-
10
8
  // eslint-disable-next-line eslint-comments/disable-enable-pair
11
-
12
9
  /* eslint-disable node/prefer-global/url */
13
10
  // eslint-disable-next-line eslint-comments/disable-enable-pair
14
-
15
11
  /* eslint-disable node/no-unsupported-features/node-builtins */
12
+
16
13
  const getRequestUrl = ({
17
14
  params,
18
15
  request,
@@ -27,9 +24,7 @@ const getRequestUrl = ({
27
24
  url.searchParams.append('_loader', routeId);
28
25
  return url;
29
26
  };
30
-
31
27
  exports.getRequestUrl = getRequestUrl;
32
-
33
28
  const createRequest = (routeId, method = 'get') => {
34
29
  return async ({
35
30
  params,
@@ -40,7 +35,6 @@ const createRequest = (routeId, method = 'get') => {
40
35
  request,
41
36
  routeId
42
37
  });
43
-
44
38
  try {
45
39
  const res = await fetch(url, {
46
40
  method,
@@ -53,5 +47,4 @@ const createRequest = (routeId, method = 'get') => {
53
47
  }
54
48
  };
55
49
  };
56
-
57
50
  exports.createRequest = createRequest;
@@ -4,24 +4,18 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.generateClient = void 0;
7
-
8
7
  var _path = _interopRequireDefault(require("path"));
9
-
10
8
  var _utils = require("@modern-js/utils");
11
-
12
9
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
-
14
10
  const generateClient = ({
15
11
  basedir,
16
- filename
12
+ filename,
13
+ entryName
17
14
  }) => {
18
15
  // TODO: loader 的约定变更
19
16
  const componentPath = _path.default.join(_path.default.dirname(filename), 'layout.ts');
20
-
21
- const routeId = (0, _utils.getRouteId)(componentPath, basedir);
22
-
17
+ const routeId = (0, _utils.getRouteId)(componentPath, basedir, entryName);
23
18
  const requestCreatorPath = _path.default.join(__dirname, './create-request').replace('node', 'treeshaking').replace(/\\/g, '/');
24
-
25
19
  const importCode = `
26
20
  import { createRequest } from '${requestCreatorPath}';
27
21
  `;
@@ -35,5 +29,4 @@ const generateClient = ({
35
29
  ${requestCode}
36
30
  `;
37
31
  };
38
-
39
32
  exports.generateClient = generateClient;
@@ -4,26 +4,22 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = loader;
7
-
8
7
  var _generateClient = require("./generate-client");
9
-
10
8
  // eslint-disable-next-line eslint-comments/disable-enable-pair
11
-
12
9
  /* eslint-disable @babel/no-invalid-this */
10
+
13
11
  async function loader(source) {
14
12
  var _this$_compiler;
15
-
16
13
  this.cacheable();
17
14
  const target = (_this$_compiler = this._compiler) === null || _this$_compiler === void 0 ? void 0 : _this$_compiler.options.target;
18
-
19
15
  if (target === 'node') {
20
16
  return source;
21
17
  }
22
-
23
18
  const options = this.getOptions();
24
19
  const code = (0, _generateClient.generateClient)({
25
20
  basedir: options.routesDir,
26
- filename: this.resourcePath
21
+ filename: this.resourcePath,
22
+ entryName: options.entryName
27
23
  });
28
24
  return code;
29
25
  }
@@ -6,50 +6,37 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.handleRequest = exports.getPathWithoutEntry = exports.default = void 0;
7
7
  exports.isRedirectResponse = isRedirectResponse;
8
8
  exports.isResponse = isResponse;
9
-
10
9
  var _node = require("@remix-run/node");
11
-
12
10
  var _reactRouterDom = require("react-router-dom");
13
-
14
11
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
15
-
16
12
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
17
-
18
13
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
19
-
20
14
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
21
-
22
15
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
23
-
24
16
  // Polyfill Web Fetch API
25
17
  (0, _node.installGlobals)();
26
18
  const LOADER_SEARCH_PARAM = '_loader';
27
19
  const redirectStatusCodes = new Set([301, 302, 303, 307, 308]);
28
-
29
20
  function isRedirectResponse(response) {
30
21
  return redirectStatusCodes.has(response.status);
31
22
  }
32
-
33
23
  function isResponse(value) {
34
24
  return value != null && typeof value.status === 'number' && typeof value.statusText === 'string' && typeof value.headers === 'object' && typeof value.body !== 'undefined';
35
25
  }
36
-
37
26
  const json = (data, init = {}) => {
38
27
  const responseInit = typeof init === 'number' ? {
39
28
  status: init
40
29
  } : init;
41
30
  const headers = new Headers(responseInit.headers);
42
-
43
31
  if (!headers.has('Content-Type')) {
44
32
  headers.set('Content-Type', 'application/json; charset=utf-8');
45
33
  }
46
-
47
34
  return new _node.Response(JSON.stringify(data), _objectSpread(_objectSpread({}, responseInit), {}, {
48
35
  headers
49
36
  }));
50
- }; // TODO: 添加 context
51
-
37
+ };
52
38
 
39
+ // TODO: 添加 context
53
40
  const callRouteLoader = async ({
54
41
  routeId,
55
42
  loader,
@@ -61,9 +48,7 @@ const callRouteLoader = async ({
61
48
  if (!loader) {
62
49
  throw new Error(`You made a ${request.method} request to ${request.url} but did not provide ` + `a default component or \`loader\` for route "${routeId}", ` + `so there is no way to handle the request.`);
63
50
  }
64
-
65
51
  let result;
66
-
67
52
  try {
68
53
  result = await loader({
69
54
  request,
@@ -73,20 +58,15 @@ const callRouteLoader = async ({
73
58
  if (!isResponse(error)) {
74
59
  throw error;
75
60
  }
76
-
77
61
  result = error;
78
62
  }
79
-
80
63
  if (result === undefined) {
81
64
  throw new Error(`You defined a loader for route "${routeId}" but didn't return ` + `anything from your \`loader\` function. Please return a value or \`null\`.`);
82
65
  }
83
-
84
66
  return isResponse(result) ? result : json(result);
85
67
  };
86
-
87
68
  const createLoaderHeaders = requestHeaders => {
88
69
  const headers = new Headers();
89
-
90
70
  for (const [key, values] of Object.entries(requestHeaders)) {
91
71
  if (values) {
92
72
  if (Array.isArray(values)) {
@@ -98,13 +78,11 @@ const createLoaderHeaders = requestHeaders => {
98
78
  }
99
79
  }
100
80
  }
101
-
102
81
  return headers;
103
82
  };
104
-
105
83
  const createLoaderRequest = context => {
106
- const origin = `${context.protocol}://${context.host}`; // eslint-disable-next-line node/no-unsupported-features/node-builtins, node/prefer-global/url
107
-
84
+ const origin = `${context.protocol}://${context.host}`;
85
+ // eslint-disable-next-line node/no-unsupported-features/node-builtins, node/prefer-global/url
108
86
  const url = new URL(context.url, origin);
109
87
  const controller = new AbortController();
110
88
  const init = {
@@ -114,36 +92,28 @@ const createLoaderRequest = context => {
114
92
  };
115
93
  return new Request(url.href, init);
116
94
  };
117
-
118
95
  const sendLoaderResponse = async (res, nodeResponse) => {
119
96
  res.statusMessage = nodeResponse.statusText;
120
97
  res.statusCode = nodeResponse.status;
121
-
122
98
  for (const [key, value] of nodeResponse.headers.entries()) {
123
99
  res.setHeader(key, value);
124
100
  }
125
-
126
101
  if (nodeResponse.body) {
127
102
  await (0, _node.writeReadableStreamToWritable)(nodeResponse.body, res);
128
103
  } else {
129
104
  res.end();
130
105
  }
131
106
  };
132
-
133
107
  const getPathWithoutEntry = (pathname, entryPath) => {
134
108
  if (entryPath === '/') {
135
109
  return pathname;
136
110
  }
137
-
138
111
  return pathname.replace(entryPath, '');
139
112
  };
140
-
141
113
  exports.getPathWithoutEntry = getPathWithoutEntry;
142
-
143
114
  const matchEntry = (pathname, entries) => {
144
115
  return entries.find(entry => pathname.startsWith(entry.urlPath));
145
116
  };
146
-
147
117
  const handleRequest = async ({
148
118
  context,
149
119
  serverRoutes,
@@ -154,48 +124,37 @@ const handleRequest = async ({
154
124
  query
155
125
  } = context;
156
126
  const routeId = query[LOADER_SEARCH_PARAM];
157
-
158
127
  if (!routeId || method.toLowerCase() !== 'get') {
159
128
  return;
160
129
  }
161
-
162
130
  const entry = matchEntry(context.path, serverRoutes);
163
-
164
131
  if (!entry) {
165
132
  return;
166
133
  }
167
-
168
134
  const {
169
135
  routes
170
136
  } = await Promise.resolve(`${distDir}/loader-routes/${entry.entryName}`).then(s => _interopRequireWildcard(require(s)));
171
-
172
137
  if (!routes) {
173
138
  return;
174
139
  }
175
-
176
140
  const {
177
141
  res
178
142
  } = context;
179
143
  const pathname = getPathWithoutEntry(context.path, entry.urlPath);
180
144
  const matches = (0, _reactRouterDom.matchRoutes)(routes, pathname);
181
-
182
145
  if (!matches) {
183
146
  res.statusCode = 403;
184
147
  res.end(`Route ${pathname} was not matched`);
185
148
  return;
186
149
  }
187
-
188
150
  const match = matches === null || matches === void 0 ? void 0 : matches.find(match => match.route.id === routeId);
189
-
190
151
  if (!match) {
191
152
  res.statusCode = 403;
192
153
  res.end(`Route ${routeId} does not match URL ${context.path}`);
193
154
  return;
194
155
  }
195
-
196
156
  const request = createLoaderRequest(context);
197
157
  let response;
198
-
199
158
  try {
200
159
  response = await callRouteLoader({
201
160
  loader: match.route.loader,
@@ -203,7 +162,8 @@ const handleRequest = async ({
203
162
  params: match.params,
204
163
  request,
205
164
  loadContext: {}
206
- }); // TODO: 处理 redirect
165
+ });
166
+ // TODO: 处理 redirect
207
167
  } catch (error) {
208
168
  const message = String(error);
209
169
  response = new _node.Response(message, {
@@ -213,12 +173,9 @@ const handleRequest = async ({
213
173
  }
214
174
  });
215
175
  }
216
-
217
176
  sendLoaderResponse(res, response);
218
177
  };
219
-
220
178
  exports.handleRequest = handleRequest;
221
-
222
179
  var _default = () => ({
223
180
  name: '@modern-js/plugin-data-loader',
224
181
  setup: () => ({
@@ -234,8 +191,6 @@ var _default = () => ({
234
191
  });
235
192
  };
236
193
  }
237
-
238
194
  })
239
195
  });
240
-
241
196
  exports.default = _default;
@@ -1,16 +1,14 @@
1
1
  import _regeneratorRuntime from "@babel/runtime/helpers/esm/regeneratorRuntime";
2
2
  import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
3
3
  // eslint-disable-next-line eslint-comments/disable-enable-pair
4
-
5
4
  /* eslint-disable node/prefer-global/url */
6
5
  // eslint-disable-next-line eslint-comments/disable-enable-pair
7
-
8
6
  /* eslint-disable node/no-unsupported-features/node-builtins */
9
7
  import { compile } from 'path-to-regexp';
10
8
  export var getRequestUrl = function getRequestUrl(_ref) {
11
9
  var params = _ref.params,
12
- request = _ref.request,
13
- routeId = _ref.routeId;
10
+ request = _ref.request,
11
+ routeId = _ref.routeId;
14
12
  var url = new URL(request.url);
15
13
  var toPath = compile(url.pathname, {
16
14
  encode: encodeURIComponent
@@ -41,17 +39,14 @@ export var createRequest = function createRequest(routeId) {
41
39
  method: method,
42
40
  signal: request.signal
43
41
  });
44
-
45
42
  case 5:
46
43
  res = _context.sent;
47
44
  return _context.abrupt("return", res);
48
-
49
45
  case 9:
50
46
  _context.prev = 9;
51
47
  _context.t0 = _context["catch"](2);
52
48
  console.error(_context.t0);
53
49
  throw _context.t0;
54
-
55
50
  case 13:
56
51
  case "end":
57
52
  return _context.stop();
@@ -59,7 +54,6 @@ export var createRequest = function createRequest(routeId) {
59
54
  }
60
55
  }, _callee, null, [[2, 9]]);
61
56
  }));
62
-
63
57
  return function (_x) {
64
58
  return _ref3.apply(this, arguments);
65
59
  };
@@ -2,10 +2,11 @@ import path from 'path';
2
2
  import { getRouteId } from '@modern-js/utils';
3
3
  export var generateClient = function generateClient(_ref) {
4
4
  var basedir = _ref.basedir,
5
- filename = _ref.filename;
5
+ filename = _ref.filename,
6
+ entryName = _ref.entryName;
6
7
  // TODO: loader 的约定变更
7
8
  var componentPath = path.join(path.dirname(filename), 'layout.ts');
8
- var routeId = getRouteId(componentPath, basedir);
9
+ var routeId = getRouteId(componentPath, basedir, entryName);
9
10
  var requestCreatorPath = path.join(__dirname, './create-request').replace('node', 'treeshaking').replace(/\\/g, '/');
10
11
  var importCode = "\n import { createRequest } from '".concat(requestCreatorPath, "';\n ");
11
12
  var requestCode = "\n const loader = createRequest('".concat(routeId, "');\n export default loader;\n export { loader };\n ");
@@ -1,17 +1,15 @@
1
1
  import _regeneratorRuntime from "@babel/runtime/helpers/esm/regeneratorRuntime";
2
2
  import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
3
3
  // eslint-disable-next-line eslint-comments/disable-enable-pair
4
-
5
4
  /* eslint-disable @babel/no-invalid-this */
5
+
6
6
  import { generateClient } from "./generate-client";
7
7
  export default function loader(_x) {
8
8
  return _loader.apply(this, arguments);
9
9
  }
10
-
11
10
  function _loader() {
12
11
  _loader = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(source) {
13
12
  var _this$_compiler;
14
-
15
13
  var target, options, code;
16
14
  return _regeneratorRuntime().wrap(function _callee$(_context) {
17
15
  while (1) {
@@ -19,22 +17,19 @@ function _loader() {
19
17
  case 0:
20
18
  this.cacheable();
21
19
  target = (_this$_compiler = this._compiler) === null || _this$_compiler === void 0 ? void 0 : _this$_compiler.options.target;
22
-
23
20
  if (!(target === 'node')) {
24
21
  _context.next = 4;
25
22
  break;
26
23
  }
27
-
28
24
  return _context.abrupt("return", source);
29
-
30
25
  case 4:
31
26
  options = this.getOptions();
32
27
  code = generateClient({
33
28
  basedir: options.routesDir,
34
- filename: this.resourcePath
29
+ filename: this.resourcePath,
30
+ entryName: options.entryName
35
31
  });
36
32
  return _context.abrupt("return", code);
37
-
38
33
  case 7:
39
34
  case "end":
40
35
  return _context.stop();
@@ -16,24 +16,21 @@ export function isRedirectResponse(response) {
16
16
  export function isResponse(value) {
17
17
  return value != null && typeof value.status === 'number' && typeof value.statusText === 'string' && _typeof(value.headers) === 'object' && typeof value.body !== 'undefined';
18
18
  }
19
-
20
19
  var json = function json(data) {
21
20
  var init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
22
21
  var responseInit = typeof init === 'number' ? {
23
22
  status: init
24
23
  } : init;
25
24
  var headers = new Headers(responseInit.headers);
26
-
27
25
  if (!headers.has('Content-Type')) {
28
26
  headers.set('Content-Type', 'application/json; charset=utf-8');
29
27
  }
30
-
31
28
  return new NodeResponse(JSON.stringify(data), _objectSpread(_objectSpread({}, responseInit), {}, {
32
29
  headers: headers
33
30
  }));
34
- }; // TODO: 添加 context
35
-
31
+ };
36
32
 
33
+ // TODO: 添加 context
37
34
  var callRouteLoader = /*#__PURE__*/function () {
38
35
  var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(_ref) {
39
36
  var routeId, loader, params, request, loadContext, result;
@@ -42,14 +39,11 @@ var callRouteLoader = /*#__PURE__*/function () {
42
39
  switch (_context.prev = _context.next) {
43
40
  case 0:
44
41
  routeId = _ref.routeId, loader = _ref.loader, params = _ref.params, request = _ref.request, loadContext = _ref.loadContext;
45
-
46
42
  if (loader) {
47
43
  _context.next = 3;
48
44
  break;
49
45
  }
50
-
51
46
  throw new Error("You made a ".concat(request.method, " request to ").concat(request.url, " but did not provide ") + "a default component or `loader` for route \"".concat(routeId, "\", ") + "so there is no way to handle the request.");
52
-
53
47
  case 3:
54
48
  _context.prev = 3;
55
49
  _context.next = 6;
@@ -57,37 +51,28 @@ var callRouteLoader = /*#__PURE__*/function () {
57
51
  request: request,
58
52
  params: params
59
53
  });
60
-
61
54
  case 6:
62
55
  result = _context.sent;
63
56
  _context.next = 14;
64
57
  break;
65
-
66
58
  case 9:
67
59
  _context.prev = 9;
68
60
  _context.t0 = _context["catch"](3);
69
-
70
61
  if (isResponse(_context.t0)) {
71
62
  _context.next = 13;
72
63
  break;
73
64
  }
74
-
75
65
  throw _context.t0;
76
-
77
66
  case 13:
78
67
  result = _context.t0;
79
-
80
68
  case 14:
81
69
  if (!(result === undefined)) {
82
70
  _context.next = 16;
83
71
  break;
84
72
  }
85
-
86
73
  throw new Error("You defined a loader for route \"".concat(routeId, "\" but didn't return ") + "anything from your `loader` function. Please return a value or `null`.");
87
-
88
74
  case 16:
89
75
  return _context.abrupt("return", isResponse(result) ? result : json(result));
90
-
91
76
  case 17:
92
77
  case "end":
93
78
  return _context.stop();
@@ -95,25 +80,20 @@ var callRouteLoader = /*#__PURE__*/function () {
95
80
  }
96
81
  }, _callee, null, [[3, 9]]);
97
82
  }));
98
-
99
83
  return function callRouteLoader(_x) {
100
84
  return _ref2.apply(this, arguments);
101
85
  };
102
86
  }();
103
-
104
87
  var createLoaderHeaders = function createLoaderHeaders(requestHeaders) {
105
88
  var headers = new Headers();
106
-
107
89
  for (var _i = 0, _Object$entries = Object.entries(requestHeaders); _i < _Object$entries.length; _i++) {
108
90
  var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
109
- _key = _Object$entries$_i[0],
110
- values = _Object$entries$_i[1];
111
-
91
+ _key = _Object$entries$_i[0],
92
+ values = _Object$entries$_i[1];
112
93
  if (values) {
113
94
  if (Array.isArray(values)) {
114
95
  var _iterator = _createForOfIteratorHelper(values),
115
- _step;
116
-
96
+ _step;
117
97
  try {
118
98
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
119
99
  var value = _step.value;
@@ -129,13 +109,11 @@ var createLoaderHeaders = function createLoaderHeaders(requestHeaders) {
129
109
  }
130
110
  }
131
111
  }
132
-
133
112
  return headers;
134
113
  };
135
-
136
114
  var createLoaderRequest = function createLoaderRequest(context) {
137
- var origin = "".concat(context.protocol, "://").concat(context.host); // eslint-disable-next-line node/no-unsupported-features/node-builtins, node/prefer-global/url
138
-
115
+ var origin = "".concat(context.protocol, "://").concat(context.host);
116
+ // eslint-disable-next-line node/no-unsupported-features/node-builtins, node/prefer-global/url
139
117
  var url = new URL(context.url, origin);
140
118
  var controller = new AbortController();
141
119
  var init = {
@@ -145,11 +123,9 @@ var createLoaderRequest = function createLoaderRequest(context) {
145
123
  };
146
124
  return new Request(url.href, init);
147
125
  };
148
-
149
126
  var sendLoaderResponse = /*#__PURE__*/function () {
150
127
  var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(res, nodeResponse) {
151
128
  var _iterator2, _step2, _step2$value, _key2, value;
152
-
153
129
  return _regeneratorRuntime().wrap(function _callee2$(_context2) {
154
130
  while (1) {
155
131
  switch (_context2.prev = _context2.next) {
@@ -157,7 +133,6 @@ var sendLoaderResponse = /*#__PURE__*/function () {
157
133
  res.statusMessage = nodeResponse.statusText;
158
134
  res.statusCode = nodeResponse.status;
159
135
  _iterator2 = _createForOfIteratorHelper(nodeResponse.headers.entries());
160
-
161
136
  try {
162
137
  for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
163
138
  _step2$value = _slicedToArray(_step2.value, 2), _key2 = _step2$value[0], value = _step2$value[1];
@@ -168,22 +143,17 @@ var sendLoaderResponse = /*#__PURE__*/function () {
168
143
  } finally {
169
144
  _iterator2.f();
170
145
  }
171
-
172
146
  if (!nodeResponse.body) {
173
147
  _context2.next = 9;
174
148
  break;
175
149
  }
176
-
177
150
  _context2.next = 7;
178
151
  return writeReadableStreamToWritable(nodeResponse.body, res);
179
-
180
152
  case 7:
181
153
  _context2.next = 10;
182
154
  break;
183
-
184
155
  case 9:
185
156
  res.end();
186
-
187
157
  case 10:
188
158
  case "end":
189
159
  return _context2.stop();
@@ -191,30 +161,24 @@ var sendLoaderResponse = /*#__PURE__*/function () {
191
161
  }
192
162
  }, _callee2);
193
163
  }));
194
-
195
164
  return function sendLoaderResponse(_x2, _x3) {
196
165
  return _ref3.apply(this, arguments);
197
166
  };
198
167
  }();
199
-
200
168
  export var getPathWithoutEntry = function getPathWithoutEntry(pathname, entryPath) {
201
169
  if (entryPath === '/') {
202
170
  return pathname;
203
171
  }
204
-
205
172
  return pathname.replace(entryPath, '');
206
173
  };
207
-
208
174
  var matchEntry = function matchEntry(pathname, entries) {
209
175
  return entries.find(function (entry) {
210
176
  return pathname.startsWith(entry.urlPath);
211
177
  });
212
178
  };
213
-
214
179
  export var handleRequest = /*#__PURE__*/function () {
215
180
  var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(_ref4) {
216
181
  var context, serverRoutes, distDir, method, query, routeId, entry, _yield$import, routes, res, pathname, matches, match, request, response, message;
217
-
218
182
  return _regeneratorRuntime().wrap(function _callee3$(_context3) {
219
183
  while (1) {
220
184
  switch (_context3.prev = _context3.next) {
@@ -222,67 +186,51 @@ export var handleRequest = /*#__PURE__*/function () {
222
186
  context = _ref4.context, serverRoutes = _ref4.serverRoutes, distDir = _ref4.distDir;
223
187
  method = context.method, query = context.query;
224
188
  routeId = query[LOADER_SEARCH_PARAM];
225
-
226
189
  if (!(!routeId || method.toLowerCase() !== 'get')) {
227
190
  _context3.next = 5;
228
191
  break;
229
192
  }
230
-
231
193
  return _context3.abrupt("return");
232
-
233
194
  case 5:
234
195
  entry = matchEntry(context.path, serverRoutes);
235
-
236
196
  if (entry) {
237
197
  _context3.next = 8;
238
198
  break;
239
199
  }
240
-
241
200
  return _context3.abrupt("return");
242
-
243
201
  case 8:
244
202
  _context3.next = 10;
245
203
  return import("".concat(distDir, "/loader-routes/").concat(entry.entryName));
246
-
247
204
  case 10:
248
205
  _yield$import = _context3.sent;
249
206
  routes = _yield$import.routes;
250
-
251
207
  if (routes) {
252
208
  _context3.next = 14;
253
209
  break;
254
210
  }
255
-
256
211
  return _context3.abrupt("return");
257
-
258
212
  case 14:
259
213
  res = context.res;
260
214
  pathname = getPathWithoutEntry(context.path, entry.urlPath);
261
215
  matches = matchRoutes(routes, pathname);
262
-
263
216
  if (matches) {
264
217
  _context3.next = 21;
265
218
  break;
266
219
  }
267
-
268
220
  res.statusCode = 403;
269
221
  res.end("Route ".concat(pathname, " was not matched"));
270
222
  return _context3.abrupt("return");
271
-
272
223
  case 21:
273
224
  match = matches === null || matches === void 0 ? void 0 : matches.find(function (match) {
274
225
  return match.route.id === routeId;
275
226
  });
276
-
277
227
  if (match) {
278
228
  _context3.next = 26;
279
229
  break;
280
230
  }
281
-
282
231
  res.statusCode = 403;
283
232
  res.end("Route ".concat(routeId, " does not match URL ").concat(context.path));
284
233
  return _context3.abrupt("return");
285
-
286
234
  case 26:
287
235
  request = createLoaderRequest(context);
288
236
  _context3.prev = 27;
@@ -294,12 +242,10 @@ export var handleRequest = /*#__PURE__*/function () {
294
242
  request: request,
295
243
  loadContext: {}
296
244
  });
297
-
298
245
  case 30:
299
246
  response = _context3.sent;
300
247
  _context3.next = 37;
301
248
  break;
302
-
303
249
  case 33:
304
250
  _context3.prev = 33;
305
251
  _context3.t0 = _context3["catch"](27);
@@ -310,10 +256,8 @@ export var handleRequest = /*#__PURE__*/function () {
310
256
  'Content-Type': 'text/plain'
311
257
  }
312
258
  });
313
-
314
259
  case 37:
315
260
  sendLoaderResponse(res, response);
316
-
317
261
  case 38:
318
262
  case "end":
319
263
  return _context3.stop();
@@ -321,7 +265,6 @@ export var handleRequest = /*#__PURE__*/function () {
321
265
  }
322
266
  }, _callee3, null, [[27, 33]]);
323
267
  }));
324
-
325
268
  return function handleRequest(_x4) {
326
269
  return _ref5.apply(this, arguments);
327
270
  };
@@ -333,7 +276,7 @@ export default (function () {
333
276
  return {
334
277
  preparebeforeRouteHandler: function preparebeforeRouteHandler(_ref6) {
335
278
  var serverRoutes = _ref6.serverRoutes,
336
- distDir = _ref6.distDir;
279
+ distDir = _ref6.distDir;
337
280
  return /*#__PURE__*/function () {
338
281
  var _ref7 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(context) {
339
282
  return _regeneratorRuntime().wrap(function _callee4$(_context4) {
@@ -345,7 +288,6 @@ export default (function () {
345
288
  distDir: distDir,
346
289
  context: context
347
290
  }));
348
-
349
291
  case 1:
350
292
  case "end":
351
293
  return _context4.stop();
@@ -353,7 +295,6 @@ export default (function () {
353
295
  }
354
296
  }, _callee4);
355
297
  }));
356
-
357
298
  return function (_x5) {
358
299
  return _ref7.apply(this, arguments);
359
300
  };
@@ -1,7 +1,9 @@
1
1
  export declare const generateClient: ({
2
2
  basedir,
3
- filename
3
+ filename,
4
+ entryName
4
5
  }: {
5
6
  basedir: string;
6
7
  filename: string;
8
+ entryName: string;
7
9
  }) => string;
@@ -1,4 +1,5 @@
1
1
  import type { LoaderContext } from 'webpack';
2
2
  export default function loader(this: LoaderContext<{
3
3
  routesDir: string;
4
+ entryName: string;
4
5
  }>, source: string): Promise<string>;
@@ -14,7 +14,5 @@ export declare const handleRequest: ({
14
14
  serverRoutes: ServerRoute[];
15
15
  distDir: string;
16
16
  }) => Promise<void>;
17
-
18
17
  declare const _default: () => ServerPlugin;
19
-
20
18
  export default _default;
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "modern",
12
12
  "modern.js"
13
13
  ],
14
- "version": "2.0.0-beta.0",
14
+ "version": "2.0.0-beta.1",
15
15
  "jsnext:source": "./src/index.ts",
16
16
  "types": "./dist/types/index.d.ts",
17
17
  "main": "./dist/js/node/index.js",
@@ -40,19 +40,13 @@
40
40
  "dependencies": {
41
41
  "@babel/core": "^7.18.0",
42
42
  "@babel/runtime": "^7.18.0",
43
- "@modern-js/babel-compiler": "2.0.0-beta.0",
44
- "@modern-js/utils": "2.0.0-beta.0",
45
43
  "@remix-run/node": "^1.7.0",
46
44
  "path-to-regexp": "^6.2.0",
47
- "react-router-dom": "^6.4.2"
45
+ "react-router-dom": "^6.4.2",
46
+ "@modern-js/babel-compiler": "2.0.0-beta.1",
47
+ "@modern-js/utils": "2.0.0-beta.1"
48
48
  },
49
49
  "devDependencies": {
50
- "@modern-js/core": "2.0.0-beta.0",
51
- "@modern-js/runtime": "2.0.0-beta.0",
52
- "@modern-js/server-core": "2.0.0-beta.0",
53
- "@modern-js/types": "2.0.0-beta.0",
54
- "@scripts/build": "2.0.0-beta.0",
55
- "@scripts/jest-config": "2.0.0-beta.0",
56
50
  "@types/babel__core": "^7.1.15",
57
51
  "@types/jest": "^27",
58
52
  "@types/node": "^14",
@@ -64,7 +58,13 @@
64
58
  "ts-jest": "^27.0.5",
65
59
  "typescript": "^4",
66
60
  "webpack": "^5.74.0",
67
- "webpack-chain": "^6.5.1"
61
+ "webpack-chain": "^6.5.1",
62
+ "@modern-js/core": "2.0.0-beta.1",
63
+ "@modern-js/runtime": "2.0.0-beta.1",
64
+ "@modern-js/server-core": "2.0.0-beta.1",
65
+ "@modern-js/types": "2.0.0-beta.1",
66
+ "@scripts/build": "2.0.0-beta.1",
67
+ "@scripts/jest-config": "2.0.0-beta.1"
68
68
  },
69
69
  "sideEffects": false,
70
70
  "publishConfig": {