@modern-js/plugin-data-loader 2.4.0 → 2.5.0-alpha.0

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 (33) hide show
  1. package/dist/{js/node → cjs}/cli/create-request.js +17 -26
  2. package/dist/cjs/cli/data.js +162 -0
  3. package/dist/{js/node → cjs}/cli/generate-client.js +1 -1
  4. package/dist/{js/node → cjs}/cli/loader.js +12 -34
  5. package/dist/{js/node → cjs}/common/constants.js +0 -0
  6. package/dist/cjs/runtime/index.js +159 -0
  7. package/dist/cjs/runtime/response.js +102 -0
  8. package/dist/cjs/server/index.js +64 -0
  9. package/dist/{js/treeshaking → esm}/cli/create-request.js +41 -2
  10. package/dist/esm/cli/data.js +820 -0
  11. package/dist/{js/treeshaking → esm}/cli/generate-client.js +1 -1
  12. package/dist/{js/treeshaking → esm}/cli/loader.js +2 -2
  13. package/dist/{js/treeshaking → esm}/common/constants.js +0 -0
  14. package/dist/{js/treeshaking/server → esm/runtime}/index.js +69 -225
  15. package/dist/esm/runtime/response.js +284 -0
  16. package/dist/esm/server/index.js +176 -0
  17. package/dist/{js/modern → esm-node}/cli/create-request.js +17 -26
  18. package/dist/esm-node/cli/data.js +142 -0
  19. package/dist/{js/modern → esm-node}/cli/generate-client.js +1 -1
  20. package/dist/esm-node/cli/loader.js +18 -0
  21. package/dist/{js/modern → esm-node}/common/constants.js +0 -0
  22. package/dist/esm-node/runtime/index.js +143 -0
  23. package/dist/esm-node/runtime/response.js +79 -0
  24. package/dist/esm-node/server/index.js +40 -0
  25. package/dist/types/cli/create-request.d.ts +2 -1
  26. package/dist/types/cli/data.d.ts +6 -0
  27. package/dist/types/runtime/index.d.ts +15 -0
  28. package/dist/types/runtime/response.d.ts +2 -0
  29. package/dist/types/server/index.d.ts +0 -15
  30. package/package.json +24 -14
  31. package/dist/js/modern/cli/loader.js +0 -40
  32. package/dist/js/modern/server/index.js +0 -237
  33. package/dist/js/node/server/index.js +0 -261
File without changes
@@ -0,0 +1,143 @@
1
+ import {
2
+ installGlobals,
3
+ writeReadableStreamToWritable,
4
+ Response as NodeResponse
5
+ } from "@remix-run/node";
6
+ import {
7
+ transformNestedRoutes
8
+ } from "@modern-js/utils";
9
+ import {
10
+ createStaticHandler,
11
+ ErrorResponse,
12
+ UNSAFE_DEFERRED_SYMBOL as DEFERRED_SYMBOL
13
+ } from "@modern-js/utils/remix-router";
14
+ import { LOADER_ID_PARAM } from "../common/constants";
15
+ import { createDeferredReadableStream } from "./response";
16
+ installGlobals();
17
+ const redirectStatusCodes = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
18
+ function isRedirectResponse(status) {
19
+ return redirectStatusCodes.has(status);
20
+ }
21
+ function isResponse(value) {
22
+ return value != null && typeof value.status === "number" && typeof value.statusText === "string" && typeof value.headers === "object" && typeof value.body !== "undefined";
23
+ }
24
+ function convertModernRedirectResponse(headers) {
25
+ const newHeaders = new Headers(headers);
26
+ newHeaders.set("X-Modernjs-Redirect", headers.get("Location"));
27
+ newHeaders.delete("Location");
28
+ return new NodeResponse(null, {
29
+ status: 204,
30
+ headers: newHeaders
31
+ });
32
+ }
33
+ const createLoaderHeaders = (requestHeaders) => {
34
+ const headers = new Headers();
35
+ for (const [key, values] of Object.entries(requestHeaders)) {
36
+ if (values) {
37
+ if (Array.isArray(values)) {
38
+ for (const value of values) {
39
+ headers.append(key, value);
40
+ }
41
+ } else {
42
+ headers.set(key, values);
43
+ }
44
+ }
45
+ }
46
+ return headers;
47
+ };
48
+ const createLoaderRequest = (context) => {
49
+ const origin = `${context.protocol}://${context.host}`;
50
+ const url = new URL(context.url, origin);
51
+ const controller = new AbortController();
52
+ const init = {
53
+ method: context.method,
54
+ headers: createLoaderHeaders(context.headers),
55
+ signal: controller.signal
56
+ };
57
+ return new Request(url.href, init);
58
+ };
59
+ const sendLoaderResponse = async (res, nodeResponse) => {
60
+ res.statusMessage = nodeResponse.statusText;
61
+ res.statusCode = nodeResponse.status;
62
+ for (const [key, value] of nodeResponse.headers.entries()) {
63
+ res.setHeader(key, value);
64
+ }
65
+ if (nodeResponse.body) {
66
+ await writeReadableStreamToWritable(nodeResponse.body, res);
67
+ } else {
68
+ res.end();
69
+ }
70
+ };
71
+ const matchEntry = (pathname, entries) => {
72
+ return entries.find((entry) => pathname.startsWith(entry.urlPath));
73
+ };
74
+ const handleRequest = async ({
75
+ context,
76
+ serverRoutes,
77
+ routes
78
+ }) => {
79
+ const { method, query } = context;
80
+ const routeId = query[LOADER_ID_PARAM];
81
+ if (!routeId) {
82
+ throw new Error(`Missing parameter: ${LOADER_ID_PARAM}`);
83
+ }
84
+ if (method.toLowerCase() !== "get") {
85
+ throw new Error("Only support httpp GET method");
86
+ }
87
+ const entry = matchEntry(context.path, serverRoutes);
88
+ if (!entry) {
89
+ throw new Error("Route is not matched");
90
+ }
91
+ const dataRoutes = transformNestedRoutes(routes);
92
+ const staticHandler = createStaticHandler(dataRoutes, {
93
+ basename: entry.urlPath
94
+ });
95
+ const { res } = context;
96
+ const request = createLoaderRequest(context);
97
+ let response;
98
+ try {
99
+ response = await staticHandler.queryRoute(request, {
100
+ routeId,
101
+ requestContext: context
102
+ });
103
+ if (isResponse(response) && isRedirectResponse(response.status)) {
104
+ response = convertModernRedirectResponse(response.headers);
105
+ } else if (DEFERRED_SYMBOL in response) {
106
+ const deferredData = response[DEFERRED_SYMBOL];
107
+ const body = createDeferredReadableStream(deferredData, request.signal);
108
+ const init = deferredData.init || {};
109
+ if (init.status && isRedirectResponse(init.status)) {
110
+ if (!init.headers) {
111
+ throw new Error("redirect response includes no headers");
112
+ }
113
+ response = convertModernRedirectResponse(new Headers(init.headers));
114
+ } else {
115
+ const headers = new Headers(init.headers);
116
+ headers.set("Content-Type", "text/modernjs-deferred");
117
+ init.headers = headers;
118
+ response = new NodeResponse(body, init);
119
+ }
120
+ } else {
121
+ response = isResponse(response) ? response : new NodeResponse(JSON.stringify(response), {
122
+ headers: {
123
+ "Content-Type": "application/json; charset=utf-8"
124
+ }
125
+ });
126
+ }
127
+ } catch (error) {
128
+ const message = error instanceof ErrorResponse ? error.data : String(error);
129
+ response = new NodeResponse(message, {
130
+ status: 500,
131
+ headers: {
132
+ "Content-Type": "text/plain"
133
+ }
134
+ });
135
+ }
136
+ sendLoaderResponse(res, response);
137
+ };
138
+ export {
139
+ handleRequest,
140
+ isRedirectResponse,
141
+ isResponse,
142
+ matchEntry
143
+ };
@@ -0,0 +1,79 @@
1
+ import { TextEncoder } from "util";
2
+ import { serializeJson } from "@modern-js/utils";
3
+ function isTrackedPromise(value) {
4
+ return value != null && typeof value.then === "function" && value._tracked === true;
5
+ }
6
+ const DEFERRED_VALUE_PLACEHOLDER_PREFIX = "__deferred_promise:";
7
+ function createDeferredReadableStream(deferredData, signal) {
8
+ const encoder = new TextEncoder();
9
+ const stream = new ReadableStream({
10
+ async start(controller) {
11
+ const criticalData = {};
12
+ const preresolvedKeys = [];
13
+ for (const [key, value] of Object.entries(deferredData.data)) {
14
+ if (isTrackedPromise(value)) {
15
+ criticalData[key] = `${DEFERRED_VALUE_PLACEHOLDER_PREFIX}${key}`;
16
+ if (typeof value._data !== "undefined" || typeof value._error !== "undefined") {
17
+ preresolvedKeys.push(key);
18
+ }
19
+ } else {
20
+ criticalData[key] = value;
21
+ }
22
+ }
23
+ controller.enqueue(encoder.encode(`${JSON.stringify(criticalData)}
24
+
25
+ `));
26
+ for (const preresolvedKey of preresolvedKeys) {
27
+ enqueueTrackedPromise(
28
+ controller,
29
+ encoder,
30
+ preresolvedKey,
31
+ deferredData.data[preresolvedKey]
32
+ );
33
+ }
34
+ const unsubscribe = deferredData.subscribe((aborted, settledKey) => {
35
+ if (settledKey) {
36
+ enqueueTrackedPromise(
37
+ controller,
38
+ encoder,
39
+ settledKey,
40
+ deferredData.data[settledKey]
41
+ );
42
+ }
43
+ });
44
+ await deferredData.resolveData(signal);
45
+ unsubscribe();
46
+ controller.close();
47
+ }
48
+ });
49
+ return stream;
50
+ }
51
+ function enqueueTrackedPromise(controller, encoder, settledKey, promise) {
52
+ var _a;
53
+ if ("_error" in promise) {
54
+ const { _error } = promise;
55
+ controller.enqueue(
56
+ encoder.encode(
57
+ `error:${serializeJson({
58
+ [settledKey]: {
59
+ message: _error.message,
60
+ stack: _error.stack
61
+ }
62
+ })}
63
+
64
+ `
65
+ )
66
+ );
67
+ } else {
68
+ controller.enqueue(
69
+ encoder.encode(
70
+ `data:${JSON.stringify({ [settledKey]: (_a = promise._data) != null ? _a : null })}
71
+
72
+ `
73
+ )
74
+ );
75
+ }
76
+ }
77
+ export {
78
+ createDeferredReadableStream
79
+ };
@@ -0,0 +1,40 @@
1
+ import path from "path";
2
+ import {
3
+ MAIN_ENTRY_NAME,
4
+ SERVER_BUNDLE_DIRECTORY
5
+ } from "@modern-js/utils";
6
+ import { matchEntry } from "../runtime";
7
+ var server_default = () => ({
8
+ name: "@modern-js/plugin-data-loader",
9
+ setup: () => ({
10
+ preparebeforeRouteHandler({
11
+ serverRoutes,
12
+ distDir
13
+ }) {
14
+ return async (context) => {
15
+ const entry = matchEntry(context.path, serverRoutes);
16
+ if (!entry) {
17
+ throw new Error("Route is not matched");
18
+ }
19
+ const routesPath = path.join(
20
+ distDir,
21
+ SERVER_BUNDLE_DIRECTORY,
22
+ `${entry.entryName || MAIN_ENTRY_NAME}-server-loaders`
23
+ );
24
+ const { routes, handleRequest } = await import(routesPath);
25
+ if (!routes) {
26
+ throw new Error("Missing route info");
27
+ ;
28
+ }
29
+ return handleRequest({
30
+ serverRoutes,
31
+ context,
32
+ routes
33
+ });
34
+ };
35
+ }
36
+ })
37
+ });
38
+ export {
39
+ server_default as default
40
+ };
@@ -1,3 +1,4 @@
1
+ import { type UNSAFE_DeferredData as DeferredData } from '@modern-js/utils/remix-router';
1
2
  export declare const getRequestUrl: ({
2
3
  params,
3
4
  request,
@@ -13,4 +14,4 @@ export declare const createRequest: (routeId: string, method?: string) => ({
13
14
  }: {
14
15
  params: Record<string, string>;
15
16
  request: Request;
16
- }) => Promise<Response>;
17
+ }) => Promise<DeferredData | Response>;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * modified from https://github.com/remix-run/remix/blob/main/packages/remix-react/data.ts
3
+ * license at https://github.com/remix-run/remix/blob/main/LICENSE.md
4
+ */
5
+ import { UNSAFE_DeferredData as DeferredData } from '@modern-js/utils/remix-router';
6
+ export declare function parseDeferredReadableStream(stream: ReadableStream<Uint8Array>): Promise<DeferredData>;
@@ -0,0 +1,15 @@
1
+ import type { ModernServerContext, NestedRoute, ServerRoute } from '@modern-js/types';
2
+ import { Response as NodeResponse } from '@remix-run/node';
3
+ export type ServerContext = Pick<ModernServerContext, 'req' | 'res' | 'params' | 'headers' | 'method' | 'url' | 'host' | 'protocol' | 'origin' | 'href' | 'path' | 'query'>;
4
+ export declare function isRedirectResponse(status: number): boolean;
5
+ export declare function isResponse(value: any): value is NodeResponse;
6
+ export declare const matchEntry: (pathname: string, entries: ServerRoute[]) => ServerRoute | undefined;
7
+ export declare const handleRequest: ({
8
+ context,
9
+ serverRoutes,
10
+ routes
11
+ }: {
12
+ context: ServerContext;
13
+ serverRoutes: ServerRoute[];
14
+ routes: NestedRoute[];
15
+ }) => Promise<void>;
@@ -0,0 +1,2 @@
1
+ import { type UNSAFE_DeferredData as DeferredData } from '@modern-js/utils/remix-router';
2
+ export declare function createDeferredReadableStream(deferredData: DeferredData, signal: AbortSignal): any;
@@ -1,19 +1,4 @@
1
1
  import type { ServerPlugin } from '@modern-js/server-core';
2
- import type { ModernServerContext, ServerRoute } from '@modern-js/types';
3
- import { Response as NodeResponse } from '@remix-run/node';
4
- export type ServerContext = Pick<ModernServerContext, 'req' | 'res' | 'params' | 'headers' | 'method' | 'url' | 'host' | 'protocol' | 'origin' | 'href' | 'path' | 'query'>;
5
- export declare function isRedirectResponse(response: NodeResponse): boolean;
6
- export declare function isResponse(value: any): value is NodeResponse;
7
- export declare const getPathWithoutEntry: (pathname: string, entryPath: string) => string;
8
- export declare const handleRequest: ({
9
- context,
10
- serverRoutes,
11
- distDir
12
- }: {
13
- context: ServerContext;
14
- serverRoutes: ServerRoute[];
15
- distDir: string;
16
- }) => Promise<void>;
17
2
 
18
3
  declare const _default: () => ServerPlugin;
19
4
 
package/package.json CHANGED
@@ -11,20 +11,26 @@
11
11
  "modern",
12
12
  "modern.js"
13
13
  ],
14
- "version": "2.4.0",
14
+ "version": "2.5.0-alpha.0",
15
+ "engines": {
16
+ "node": ">=14.17.6"
17
+ },
15
18
  "jsnext:source": "./src/index.ts",
16
19
  "types": "./dist/types/index.d.ts",
17
- "main": "./dist/js/node/index.js",
18
- "module": "./dist/js/treeshaking/index.js",
19
- "jsnext:modern": "./dist/js/modern/index.js",
20
+ "main": "./dist/cjs/index.js",
21
+ "module": "./dist/esm/index.js",
20
22
  "exports": {
21
23
  "./loader": {
22
24
  "jsnext:source": "./src/cli/loader.ts",
23
- "default": "./dist/js/node/cli/loader.js"
25
+ "default": "./dist/cjs/cli/loader.js"
24
26
  },
25
27
  "./server": {
26
28
  "jsnext:source": "./src/server/index.ts",
27
- "default": "./dist/js/node/server/index.js"
29
+ "default": "./dist/cjs/server/index.js"
30
+ },
31
+ "./runtime": {
32
+ "jsnext:source": "./src/runtime/index.ts",
33
+ "default": "./dist/esm/runtime/index.js"
28
34
  }
29
35
  },
30
36
  "typesVersions": {
@@ -34,16 +40,19 @@
34
40
  ],
35
41
  "server": [
36
42
  "./dist/types/server/index.d.ts"
43
+ ],
44
+ "runtime": [
45
+ "./dist/types/runtime/index.d.ts"
37
46
  ]
38
47
  }
39
48
  },
40
49
  "dependencies": {
41
50
  "@babel/core": "^7.18.0",
42
51
  "@babel/runtime": "^7.18.0",
43
- "@remix-run/node": "^1.9.0",
52
+ "@remix-run/node": "^1.12.0",
44
53
  "path-to-regexp": "^6.2.0",
45
- "react-router-dom": "^6.6.0",
46
- "@modern-js/utils": "2.4.0"
54
+ "react-router-dom": "^6.8.1",
55
+ "@modern-js/utils": "2.5.0-alpha.0"
47
56
  },
48
57
  "devDependencies": {
49
58
  "@types/babel__core": "^7.1.15",
@@ -58,11 +67,12 @@
58
67
  "typescript": "^4",
59
68
  "webpack": "^5.75.0",
60
69
  "webpack-chain": "^6.5.1",
61
- "@modern-js/core": "2.4.0",
62
- "@modern-js/server-core": "2.4.0",
63
- "@modern-js/types": "2.4.0",
64
- "@scripts/jest-config": "2.4.0",
65
- "@scripts/build": "2.4.0"
70
+ "@modern-js/core": "2.5.0",
71
+ "@modern-js/types": "2.5.0",
72
+ "@scripts/build": "2.5.0",
73
+ "@modern-js/server-core": "2.5.0",
74
+ "@modern-js/plugin-module-babel": "2.5.0",
75
+ "@scripts/jest-config": "2.5.0"
66
76
  },
67
77
  "sideEffects": false,
68
78
  "publishConfig": {
@@ -1,40 +0,0 @@
1
- var __async = (__this, __arguments, generator) => {
2
- return new Promise((resolve, reject) => {
3
- var fulfilled = (value) => {
4
- try {
5
- step(generator.next(value));
6
- } catch (e) {
7
- reject(e);
8
- }
9
- };
10
- var rejected = (value) => {
11
- try {
12
- step(generator.throw(value));
13
- } catch (e) {
14
- reject(e);
15
- }
16
- };
17
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
18
- step((generator = generator.apply(__this, __arguments)).next());
19
- });
20
- };
21
- import { generateClient } from "./generate-client";
22
- function loader(source) {
23
- return __async(this, null, function* () {
24
- var _a;
25
- this.cacheable();
26
- const target = (_a = this._compiler) == null ? void 0 : _a.options.target;
27
- if (target === "node") {
28
- return source;
29
- }
30
- const options = this.getOptions();
31
- const code = generateClient({
32
- mapFile: options.mapFile,
33
- loaderId: options.loaderId
34
- });
35
- return code;
36
- });
37
- }
38
- export {
39
- loader as default
40
- };
@@ -1,237 +0,0 @@
1
- var __defProp = Object.defineProperty;
2
- var __defProps = Object.defineProperties;
3
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
- var __spreadValues = (a, b) => {
9
- for (var prop in b || (b = {}))
10
- if (__hasOwnProp.call(b, prop))
11
- __defNormalProp(a, prop, b[prop]);
12
- if (__getOwnPropSymbols)
13
- for (var prop of __getOwnPropSymbols(b)) {
14
- if (__propIsEnum.call(b, prop))
15
- __defNormalProp(a, prop, b[prop]);
16
- }
17
- return a;
18
- };
19
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
- var __async = (__this, __arguments, generator) => {
21
- return new Promise((resolve, reject) => {
22
- var fulfilled = (value) => {
23
- try {
24
- step(generator.next(value));
25
- } catch (e) {
26
- reject(e);
27
- }
28
- };
29
- var rejected = (value) => {
30
- try {
31
- step(generator.throw(value));
32
- } catch (e) {
33
- reject(e);
34
- }
35
- };
36
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
37
- step((generator = generator.apply(__this, __arguments)).next());
38
- });
39
- };
40
- import path from "path";
41
- import {
42
- installGlobals,
43
- writeReadableStreamToWritable,
44
- Response as NodeResponse
45
- } from "@remix-run/node";
46
- import {
47
- matchRoutes
48
- } from "react-router-dom";
49
- import { MAIN_ENTRY_NAME, SERVER_BUNDLE_DIRECTORY } from "@modern-js/utils";
50
- import { LOADER_ID_PARAM } from "../common/constants";
51
- installGlobals();
52
- const redirectStatusCodes = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
53
- function isRedirectResponse(response) {
54
- return redirectStatusCodes.has(response.status);
55
- }
56
- function isResponse(value) {
57
- return value != null && typeof value.status === "number" && typeof value.statusText === "string" && typeof value.headers === "object" && typeof value.body !== "undefined";
58
- }
59
- const json = (data, init = {}) => {
60
- const responseInit = typeof init === "number" ? { status: init } : init;
61
- const headers = new Headers(responseInit.headers);
62
- if (!headers.has("Content-Type")) {
63
- headers.set("Content-Type", "application/json; charset=utf-8");
64
- }
65
- return new NodeResponse(JSON.stringify(data), __spreadProps(__spreadValues({}, responseInit), {
66
- headers
67
- }));
68
- };
69
- const callRouteLoader = (_0) => __async(void 0, [_0], function* ({
70
- routeId,
71
- loader,
72
- params,
73
- request,
74
- loadContext
75
- }) {
76
- if (!loader) {
77
- throw new Error(
78
- `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.`
79
- );
80
- }
81
- let result;
82
- try {
83
- result = yield loader({
84
- request,
85
- params
86
- });
87
- } catch (error) {
88
- if (!isResponse(error)) {
89
- throw error;
90
- }
91
- result = error;
92
- }
93
- if (result === void 0) {
94
- throw new Error(
95
- `You defined a loader for route "${routeId}" but didn't return anything from your \`loader\` function. Please return a value or \`null\`.`
96
- );
97
- }
98
- return isResponse(result) ? result : json(result);
99
- });
100
- const createLoaderHeaders = (requestHeaders) => {
101
- const headers = new Headers();
102
- for (const [key, values] of Object.entries(requestHeaders)) {
103
- if (values) {
104
- if (Array.isArray(values)) {
105
- for (const value of values) {
106
- headers.append(key, value);
107
- }
108
- } else {
109
- headers.set(key, values);
110
- }
111
- }
112
- }
113
- return headers;
114
- };
115
- const createLoaderRequest = (context) => {
116
- const origin = `${context.protocol}://${context.host}`;
117
- const url = new URL(context.url, origin);
118
- const controller = new AbortController();
119
- const init = {
120
- method: context.method,
121
- headers: createLoaderHeaders(context.headers),
122
- signal: controller.signal
123
- };
124
- return new Request(url.href, init);
125
- };
126
- const sendLoaderResponse = (res, nodeResponse) => __async(void 0, null, function* () {
127
- res.statusMessage = nodeResponse.statusText;
128
- res.statusCode = nodeResponse.status;
129
- for (const [key, value] of nodeResponse.headers.entries()) {
130
- res.setHeader(key, value);
131
- }
132
- if (nodeResponse.body) {
133
- yield writeReadableStreamToWritable(nodeResponse.body, res);
134
- } else {
135
- res.end();
136
- }
137
- });
138
- const getPathWithoutEntry = (pathname, entryPath) => {
139
- if (entryPath === "/") {
140
- return pathname;
141
- }
142
- return pathname.replace(entryPath, "");
143
- };
144
- const matchEntry = (pathname, entries) => {
145
- return entries.find((entry) => pathname.startsWith(entry.urlPath));
146
- };
147
- const handleRequest = (_0) => __async(void 0, [_0], function* ({
148
- context,
149
- serverRoutes,
150
- distDir
151
- }) {
152
- const { method, query } = context;
153
- const routeId = query[LOADER_ID_PARAM];
154
- if (!routeId || method.toLowerCase() !== "get") {
155
- return;
156
- }
157
- const entry = matchEntry(context.path, serverRoutes);
158
- if (!entry) {
159
- return;
160
- }
161
- const routesPath = path.join(
162
- distDir,
163
- SERVER_BUNDLE_DIRECTORY,
164
- `${entry.entryName || MAIN_ENTRY_NAME}-server-loaders`
165
- );
166
- const { routes } = yield import(routesPath);
167
- if (!routes) {
168
- return;
169
- }
170
- const { res } = context;
171
- const pathname = getPathWithoutEntry(context.path, entry.urlPath);
172
- const matches = matchRoutes(routes, pathname);
173
- if (!matches) {
174
- res.statusCode = 403;
175
- res.end(`Route ${pathname} was not matched`);
176
- return;
177
- }
178
- const match = matches == null ? void 0 : matches.find((match2) => match2.route.id === routeId);
179
- if (!match) {
180
- res.statusCode = 403;
181
- res.end(`Route ${routeId} does not match URL ${context.path}`);
182
- return;
183
- }
184
- const request = createLoaderRequest(context);
185
- let response;
186
- try {
187
- response = yield callRouteLoader({
188
- loader: match.route.loader,
189
- routeId: match.route.id,
190
- params: match.params,
191
- request,
192
- loadContext: {}
193
- });
194
- if (isRedirectResponse(response)) {
195
- const headers = new Headers(response.headers);
196
- headers.set("X-Modernjs-Redirect", headers.get("Location"));
197
- headers.delete("Location");
198
- response = new NodeResponse(null, {
199
- status: 204,
200
- headers
201
- });
202
- }
203
- } catch (error) {
204
- const message = String(error);
205
- response = new NodeResponse(message, {
206
- status: 500,
207
- headers: {
208
- "Content-Type": "text/plain"
209
- }
210
- });
211
- }
212
- sendLoaderResponse(res, response);
213
- });
214
- var server_default = () => ({
215
- name: "@modern-js/plugin-data-loader",
216
- setup: () => ({
217
- preparebeforeRouteHandler({
218
- serverRoutes,
219
- distDir
220
- }) {
221
- return (context) => __async(this, null, function* () {
222
- return handleRequest({
223
- serverRoutes,
224
- distDir,
225
- context
226
- });
227
- });
228
- }
229
- })
230
- });
231
- export {
232
- server_default as default,
233
- getPathWithoutEntry,
234
- handleRequest,
235
- isRedirectResponse,
236
- isResponse
237
- };