@modern-js/plugin-data-loader 2.69.5 → 3.0.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 (47) hide show
  1. package/dist/cjs/cli/createRequest.js +122 -141
  2. package/dist/cjs/cli/data.js +129 -148
  3. package/dist/cjs/cli/generateClient.js +52 -52
  4. package/dist/cjs/cli/loader.js +63 -62
  5. package/dist/cjs/common/constants.js +41 -31
  6. package/dist/cjs/runtime/errors.js +84 -89
  7. package/dist/cjs/runtime/index.js +143 -155
  8. package/dist/cjs/runtime/response.js +66 -77
  9. package/dist/esm/cli/createRequest.mjs +93 -0
  10. package/dist/esm/cli/data.mjs +111 -0
  11. package/dist/esm/cli/generateClient.mjs +22 -0
  12. package/dist/esm/cli/loader.mjs +34 -0
  13. package/dist/esm/common/constants.mjs +4 -0
  14. package/dist/esm/runtime/errors.mjs +52 -0
  15. package/dist/esm/runtime/index.mjs +114 -0
  16. package/dist/esm/runtime/response.mjs +42 -0
  17. package/dist/esm-node/cli/createRequest.mjs +93 -0
  18. package/dist/esm-node/cli/data.mjs +111 -0
  19. package/dist/esm-node/cli/generateClient.mjs +22 -0
  20. package/dist/esm-node/cli/loader.mjs +34 -0
  21. package/dist/esm-node/common/constants.mjs +4 -0
  22. package/dist/esm-node/runtime/errors.mjs +52 -0
  23. package/dist/esm-node/runtime/index.mjs +114 -0
  24. package/dist/esm-node/runtime/response.mjs +42 -0
  25. package/dist/types/cli/createRequest.d.ts +1 -2
  26. package/dist/types/cli/loader.d.ts +2 -2
  27. package/dist/types/runtime/errors.d.ts +1 -1
  28. package/dist/types/runtime/response.d.ts +1 -1
  29. package/package.json +22 -26
  30. package/rslib.config.mts +4 -0
  31. package/rstest.config.ts +18 -0
  32. package/dist/esm/cli/createRequest.js +0 -297
  33. package/dist/esm/cli/data.js +0 -491
  34. package/dist/esm/cli/generateClient.js +0 -21
  35. package/dist/esm/cli/loader.js +0 -93
  36. package/dist/esm/common/constants.js +0 -8
  37. package/dist/esm/runtime/errors.js +0 -90
  38. package/dist/esm/runtime/index.js +0 -191
  39. package/dist/esm/runtime/response.js +0 -107
  40. package/dist/esm-node/cli/createRequest.js +0 -126
  41. package/dist/esm-node/cli/data.js +0 -140
  42. package/dist/esm-node/cli/generateClient.js +0 -32
  43. package/dist/esm-node/cli/loader.js +0 -47
  44. package/dist/esm-node/common/constants.js +0 -8
  45. package/dist/esm-node/runtime/errors.js +0 -75
  46. package/dist/esm-node/runtime/index.js +0 -142
  47. package/dist/esm-node/runtime/response.js +0 -63
@@ -1,47 +0,0 @@
1
- import { promisify } from "util";
2
- import { logger } from "@modern-js/utils/logger";
3
- import { generateClient } from "./generateClient";
4
- async function loader(source) {
5
- var _this__compiler;
6
- this.cacheable();
7
- const target = (_this__compiler = this._compiler) === null || _this__compiler === void 0 ? void 0 : _this__compiler.options.target;
8
- const shouldSkip = (compileTarget) => {
9
- return target === compileTarget || Array.isArray(target) && target.includes(compileTarget);
10
- };
11
- if (shouldSkip("node") || shouldSkip("webworker") || shouldSkip("async-node")) {
12
- return source;
13
- }
14
- const { resourceQuery } = this;
15
- const options = resourceQuery.slice(1).split("&").reduce((pre, cur) => {
16
- const [key, value] = cur.split("=");
17
- if (key && value) {
18
- pre[key] = value === "true" ? true : value === "false" ? false : value;
19
- }
20
- return pre;
21
- }, {});
22
- if (!options.loaderId || options.retain) {
23
- return source;
24
- }
25
- if (options.clientData) {
26
- const readFile = promisify(this.fs.readFile);
27
- try {
28
- const clientDataPath = this.resourcePath.includes(".loader.") ? this.resourcePath.replace(".loader.", ".data.client.") : this.resourcePath.replace(".data.", ".data.client.");
29
- this.addDependency(clientDataPath);
30
- const clientDataContent = await readFile(clientDataPath);
31
- return clientDataContent;
32
- } catch (error) {
33
- if (process.env.NODE_ENV === "development") {
34
- logger.error(`Failed to read the clientData file ${options.clientData}`);
35
- }
36
- }
37
- }
38
- const code = generateClient({
39
- inline: options.inline,
40
- action: options.action,
41
- routeId: options.routeId
42
- });
43
- return code;
44
- }
45
- export {
46
- loader as default
47
- };
@@ -1,8 +0,0 @@
1
- const LOADER_ID_PARAM = "__loader";
2
- const DIRECT_PARAM = "__ssrDirect";
3
- const CONTENT_TYPE_DEFERRED = "text/modernjs-deferred";
4
- export {
5
- CONTENT_TYPE_DEFERRED,
6
- DIRECT_PARAM,
7
- LOADER_ID_PARAM
8
- };
@@ -1,75 +0,0 @@
1
- import { isRouteErrorResponse } from "@modern-js/runtime-utils/remix-router";
2
- function sanitizeError(error) {
3
- if (error instanceof Error && process.env.NODE_ENV !== "development" && process.env.NODE_ENV !== "test") {
4
- const sanitized = new Error(error.message || "Unexpected Server Error");
5
- sanitized.stack = void 0;
6
- return sanitized;
7
- }
8
- return error;
9
- }
10
- function sanitizeErrors(errors) {
11
- return Object.entries(errors).reduce((acc, [routeId, error]) => {
12
- return Object.assign(acc, {
13
- [routeId]: sanitizeError(error)
14
- });
15
- }, {});
16
- }
17
- function serializeError(error) {
18
- const sanitized = sanitizeError(error);
19
- return {
20
- message: sanitized.message,
21
- stack: sanitized.stack
22
- };
23
- }
24
- function serializeErrors(errors) {
25
- if (!errors) {
26
- return null;
27
- }
28
- const entries = Object.entries(errors);
29
- const serialized = {};
30
- for (const [key, val] of entries) {
31
- if (isRouteErrorResponse(val)) {
32
- serialized[key] = {
33
- ...val,
34
- __type: "RouteErrorResponse"
35
- };
36
- } else if (val instanceof Error) {
37
- const sanitized = sanitizeError(val);
38
- serialized[key] = {
39
- message: sanitized.message,
40
- stack: sanitized.stack,
41
- __type: "Error",
42
- // If this is a subclass (i.e., ReferenceError), send up the type so we
43
- // can re-create the same type during hydration. This will only apply
44
- // in dev mode since all production errors are sanitized to normal
45
- // Error instances
46
- ...sanitized.name !== "Error" ? {
47
- __subType: sanitized.name
48
- } : {}
49
- };
50
- } else {
51
- serialized[key] = val;
52
- }
53
- }
54
- return serialized;
55
- }
56
- function errorResponseToJson(errorResponse) {
57
- return Response.json(
58
- // @ts-expect-error This is "private" from users but intended for internal use
59
- serializeError(errorResponse.error || new Error("Unexpected Server Error")),
60
- {
61
- status: errorResponse.status,
62
- statusText: errorResponse.statusText,
63
- headers: {
64
- "X-Modernjs-Error": "yes"
65
- }
66
- }
67
- );
68
- }
69
- export {
70
- errorResponseToJson,
71
- sanitizeError,
72
- sanitizeErrors,
73
- serializeError,
74
- serializeErrors
75
- };
@@ -1,142 +0,0 @@
1
- import { transformNestedRoutes } from "@modern-js/runtime-utils/browser";
2
- import { createRequestContext, reporterCtx } from "@modern-js/runtime-utils/node";
3
- import { storage } from "@modern-js/runtime-utils/node";
4
- import { DEFERRED_SYMBOL, createStaticHandler, isRouteErrorResponse } from "@modern-js/runtime-utils/remix-router";
5
- import { matchEntry } from "@modern-js/runtime-utils/server";
6
- import { time } from "@modern-js/runtime-utils/time";
7
- import { parseHeaders } from "@modern-js/runtime-utils/universal/request";
8
- import { isPlainObject } from "@modern-js/utils/lodash";
9
- import { LOADER_REPORTER_NAME } from "@modern-js/utils/universal/constants";
10
- import { CONTENT_TYPE_DEFERRED, LOADER_ID_PARAM } from "../common/constants";
11
- import { errorResponseToJson, serializeError } from "./errors";
12
- import { createDeferredReadableStream } from "./response";
13
- const redirectStatusCodes = /* @__PURE__ */ new Set([
14
- 301,
15
- 302,
16
- 303,
17
- 307,
18
- 308
19
- ]);
20
- function isRedirectResponse(status) {
21
- return redirectStatusCodes.has(status);
22
- }
23
- function isResponse(value) {
24
- return value != null && typeof value.status === "number" && typeof value.statusText === "string" && typeof value.headers === "object" && typeof value.body !== "undefined";
25
- }
26
- function convertModernRedirectResponse(headers, basename) {
27
- const newHeaders = new Headers(headers);
28
- let redirectUrl = headers.get("Location");
29
- if (basename !== "/") {
30
- redirectUrl = redirectUrl.replace(basename, "");
31
- }
32
- newHeaders.set("X-Modernjs-Redirect", redirectUrl);
33
- newHeaders.delete("Location");
34
- return new Response(null, {
35
- status: 204,
36
- headers: newHeaders
37
- });
38
- }
39
- function hasFileExtension(pathname) {
40
- const lastSegment = pathname.split("/").pop() || "";
41
- const dotIndex = lastSegment.lastIndexOf(".");
42
- if (dotIndex === -1) {
43
- return false;
44
- }
45
- const extension = lastSegment.substring(dotIndex).toLowerCase();
46
- return extension !== ".html";
47
- }
48
- const handleRequest = async ({ request, serverRoutes, routes: routesConfig, context, onTiming }) => {
49
- const url = new URL(request.url);
50
- const routeId = url.searchParams.get(LOADER_ID_PARAM);
51
- if (hasFileExtension(url.pathname)) {
52
- return;
53
- }
54
- const entry = matchEntry(url.pathname, serverRoutes);
55
- if (!routeId || !entry) {
56
- return;
57
- }
58
- const basename = entry.urlPath;
59
- const end = time();
60
- const { reporter, loaderContext, monitors } = context;
61
- const headersData = parseHeaders(request);
62
- const activeDeferreds = /* @__PURE__ */ new Map();
63
- return storage.run({
64
- headers: headersData,
65
- monitors,
66
- request,
67
- activeDeferreds
68
- }, async () => {
69
- const routes = transformNestedRoutes(routesConfig);
70
- const { queryRoute } = createStaticHandler(routes, {
71
- basename
72
- });
73
- const requestContext = createRequestContext(loaderContext);
74
- requestContext.set(reporterCtx, reporter);
75
- let response;
76
- try {
77
- response = await queryRoute(request, {
78
- routeId,
79
- requestContext
80
- });
81
- if (isResponse(response) && isRedirectResponse(response.status)) {
82
- response = convertModernRedirectResponse(response.headers, basename);
83
- } else if (isPlainObject(response) && (DEFERRED_SYMBOL in response || activeDeferreds.get(routeId))) {
84
- let deferredData;
85
- if (DEFERRED_SYMBOL in response) {
86
- deferredData = response[DEFERRED_SYMBOL];
87
- } else {
88
- deferredData = activeDeferreds.get(routeId);
89
- }
90
- const body = createDeferredReadableStream(
91
- // @ts-ignore
92
- deferredData,
93
- request.signal
94
- );
95
- const init = deferredData.init || {};
96
- if (init.status && isRedirectResponse(init.status)) {
97
- if (!init.headers) {
98
- throw new Error("redirect response includes no headers");
99
- }
100
- response = convertModernRedirectResponse(new Headers(init.headers), basename);
101
- } else {
102
- const headers = new Headers(init.headers);
103
- headers.set("Content-Type", `${CONTENT_TYPE_DEFERRED}; charset=UTF-8`);
104
- init.headers = headers;
105
- response = new Response(body, init);
106
- }
107
- } else {
108
- response = isResponse(response) ? response : new Response(JSON.stringify(response), {
109
- headers: {
110
- "Content-Type": "application/json; charset=utf-8"
111
- }
112
- });
113
- }
114
- const cost = end();
115
- response.headers.set("X-Modernjs-Response", "yes");
116
- onTiming === null || onTiming === void 0 ? void 0 : onTiming(`${LOADER_REPORTER_NAME}-navigation`, cost);
117
- } catch (error) {
118
- if (isResponse(error)) {
119
- error.headers.set("X-Modernjs-Catch", "yes");
120
- response = error;
121
- } else if (isRouteErrorResponse(error)) {
122
- response = errorResponseToJson(error);
123
- } else {
124
- const errorInstance = error instanceof Error || error instanceof DOMException ? error : new Error("Unexpected Server Error");
125
- response = new Response(JSON.stringify(serializeError(errorInstance)), {
126
- status: 500,
127
- headers: {
128
- "X-Modernjs-Error": "yes",
129
- "Content-Type": "application/json"
130
- }
131
- });
132
- }
133
- }
134
- return response;
135
- });
136
- };
137
- export {
138
- handleRequest,
139
- hasFileExtension,
140
- isRedirectResponse,
141
- isResponse
142
- };
@@ -1,63 +0,0 @@
1
- import { TextEncoder } from "util";
2
- import { serializeJson } from "@modern-js/runtime-utils/node";
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(controller, encoder, preresolvedKey, deferredData.data[preresolvedKey]);
28
- }
29
- const unsubscribe = deferredData.subscribe((aborted, settledKey) => {
30
- if (settledKey) {
31
- enqueueTrackedPromise(controller, encoder, settledKey, deferredData.data[settledKey]);
32
- }
33
- });
34
- await deferredData.resolveData(signal);
35
- unsubscribe();
36
- controller.close();
37
- }
38
- });
39
- return stream;
40
- }
41
- function enqueueTrackedPromise(controller, encoder, settledKey, promise) {
42
- if ("_error" in promise) {
43
- const { _error } = promise;
44
- controller.enqueue(encoder.encode(`error:${serializeJson({
45
- [settledKey]: {
46
- message: _error.message,
47
- stack: _error.stack
48
- }
49
- })}
50
-
51
- `));
52
- } else {
53
- var _promise__data;
54
- controller.enqueue(encoder.encode(`data:${JSON.stringify({
55
- [settledKey]: (_promise__data = promise._data) !== null && _promise__data !== void 0 ? _promise__data : null
56
- })}
57
-
58
- `));
59
- }
60
- }
61
- export {
62
- createDeferredReadableStream
63
- };