@stone-js/use-react 0.1.0 → 0.2.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.
- package/README.md +2 -2
- package/dist/browser.js +1790 -0
- package/dist/index.d.ts +356 -351
- package/dist/index.js +433 -590
- package/package.json +11 -5
package/dist/index.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import { isNotEmpty, isEmpty, InitializationError, isMetaClassModule, isMetaFactoryModule, isFunctionModule, isObjectLikeModule, isFunction,
|
|
1
|
+
import { isNotEmpty, isEmpty, InitializationError, isMetaClassModule, isMetaFactoryModule, isFunctionModule, isObjectLikeModule, isFunction, mergeBlueprints, stoneBlueprint, classDecoratorLegacyWrapper, setMetadata, methodDecoratorLegacyWrapper, addMetadata, LIFECYCLE_HOOK_KEY, hasMetadata, getMetadata, isMatchedAdapter, Logger, addBlueprint } from '@stone-js/core';
|
|
2
2
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
3
|
import { renderToString } from 'react-dom/server';
|
|
4
|
-
import { createContext, StrictMode,
|
|
4
|
+
import { createContext, StrictMode, useState, useEffect, useContext } from 'react';
|
|
5
5
|
import { createRoot, hydrateRoot } from 'react-dom/client';
|
|
6
|
-
import { OutgoingHttpResponse, RedirectResponse, MetaStaticFileMiddleware, MetaCompressionMiddleware } from '@stone-js/http-core';
|
|
7
|
-
import { OutgoingBrowserResponse, RedirectBrowserResponse } from '@stone-js/browser-core';
|
|
8
6
|
import { Config } from '@stone-js/config';
|
|
9
|
-
import { GET,
|
|
10
|
-
import {
|
|
7
|
+
import { GET, NODE_CONSOLE_PLATFORM, Router, RouteEvent } from '@stone-js/router';
|
|
8
|
+
import { OutgoingHttpResponse, RedirectResponse, MetaStaticFileMiddleware, MetaCompressionMiddleware } from '@stone-js/http-core';
|
|
11
9
|
|
|
12
10
|
/**
|
|
13
11
|
* Stone DOM Attribute.
|
|
@@ -486,7 +484,7 @@ const htmlTemplate = (blueprint) => {
|
|
|
486
484
|
* @returns True if the application is running on the server side, false otherwise.
|
|
487
485
|
*/
|
|
488
486
|
function isSSR() {
|
|
489
|
-
return
|
|
487
|
+
return typeof window === 'undefined';
|
|
490
488
|
}
|
|
491
489
|
/**
|
|
492
490
|
* Execute the handler.
|
|
@@ -552,11 +550,11 @@ function getBrowserContent(app, component, layout, snapshot, head) {
|
|
|
552
550
|
* @param container - The service container.
|
|
553
551
|
* @param event - The incoming browser event.
|
|
554
552
|
* @param head - The head context.
|
|
555
|
-
* @returns
|
|
553
|
+
* @returns The server response content as a string.
|
|
556
554
|
*/
|
|
557
|
-
|
|
555
|
+
function getServerContent(component, data, container, event, head) {
|
|
558
556
|
const html = renderToString(component).concat('\n<!--app-html-->');
|
|
559
|
-
const template =
|
|
557
|
+
const template = htmlTemplate(container.make('blueprint'));
|
|
560
558
|
const snapshot = snapshotResponse(event, container, data).concat('\n<!--app-head-->');
|
|
561
559
|
return applyHeadContextToHtmlString(head ?? {}, template)
|
|
562
560
|
.replace('<!--app-html-->', html)
|
|
@@ -712,49 +710,6 @@ class ReactRuntime {
|
|
|
712
710
|
*/
|
|
713
711
|
const MetaReactRuntime = { module: ReactRuntime, isClass: true, alias: 'reactRuntime', singleton: true };
|
|
714
712
|
|
|
715
|
-
/**
|
|
716
|
-
* Class representing an UseReactBrowserErrorHandler.
|
|
717
|
-
*
|
|
718
|
-
* Adapter level error handler for React applications.
|
|
719
|
-
*/
|
|
720
|
-
class UseReactBrowserErrorHandler {
|
|
721
|
-
logger;
|
|
722
|
-
blueprint;
|
|
723
|
-
/**
|
|
724
|
-
* Create an UseReactBrowserErrorHandler.
|
|
725
|
-
*
|
|
726
|
-
* @param options - UseReactBrowserErrorHandler options.
|
|
727
|
-
*/
|
|
728
|
-
constructor({ blueprint }) {
|
|
729
|
-
this.blueprint = blueprint;
|
|
730
|
-
this.logger = Logger.getInstance();
|
|
731
|
-
}
|
|
732
|
-
/**
|
|
733
|
-
* Handle an error.
|
|
734
|
-
*
|
|
735
|
-
* @param error - The error to handle.
|
|
736
|
-
* @param context - The context of the adapter.
|
|
737
|
-
* @returns The raw response.
|
|
738
|
-
*/
|
|
739
|
-
async handle(error, context) {
|
|
740
|
-
this.logger.error(error.message, { error });
|
|
741
|
-
return context
|
|
742
|
-
.rawResponseBuilder
|
|
743
|
-
.add('render', async () => await this.renderError(error, context));
|
|
744
|
-
}
|
|
745
|
-
/**
|
|
746
|
-
* Get the error body.
|
|
747
|
-
*
|
|
748
|
-
* @param error - The error to handle.
|
|
749
|
-
* @returns The error body.
|
|
750
|
-
*/
|
|
751
|
-
async renderError(error, context) {
|
|
752
|
-
const app = await buildAdapterErrorComponent(this.blueprint, context, error.statusCode ?? 500, error);
|
|
753
|
-
// Render the component
|
|
754
|
-
renderReactApp(app, this.blueprint);
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
|
|
758
713
|
/**
|
|
759
714
|
* A useReact event handler for processing incoming events
|
|
760
715
|
* For single event handler.
|
|
@@ -797,6 +752,34 @@ class UseReactEventHandler {
|
|
|
797
752
|
}
|
|
798
753
|
}
|
|
799
754
|
|
|
755
|
+
/**
|
|
756
|
+
* Class representing an UseReactUseReactKernelErrorHandler.
|
|
757
|
+
*
|
|
758
|
+
* Kernel level error handler for React applications.
|
|
759
|
+
*/
|
|
760
|
+
class UseReactKernelErrorHandler {
|
|
761
|
+
blueprint;
|
|
762
|
+
/**
|
|
763
|
+
* Create an UseReactUseReactKernelErrorHandler.
|
|
764
|
+
*
|
|
765
|
+
* @param options - UseReactUseReactKernelErrorHandler options.
|
|
766
|
+
*/
|
|
767
|
+
constructor({ blueprint }) {
|
|
768
|
+
this.blueprint = blueprint;
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Handle an error.
|
|
772
|
+
*
|
|
773
|
+
* @param error - The error to handle.
|
|
774
|
+
* @returns The outgoing http response.
|
|
775
|
+
*/
|
|
776
|
+
handle(error) {
|
|
777
|
+
const metavalue = this.blueprint.get(`stone.useReact.errorPages.${String(error?.name)}`) ??
|
|
778
|
+
this.blueprint.get('stone.useReact.errorPages.default', {});
|
|
779
|
+
return { content: { ...metavalue, error }, statusCode: error?.statusCode ?? 500 };
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
|
|
800
783
|
/**
|
|
801
784
|
* Prepare the page to render.
|
|
802
785
|
*
|
|
@@ -819,7 +802,7 @@ async function preparePage(event, response, container, snapshot) {
|
|
|
819
802
|
const component = await buildPageComponent(event, container, componentType, data, response.statusCode);
|
|
820
803
|
const appComponent = await buildAppComponent(event, container, componentType, layout, data, response.statusCode);
|
|
821
804
|
response.setContent(isSSR()
|
|
822
|
-
?
|
|
805
|
+
? getServerContent(appComponent, snapshotData, container, event, head)
|
|
823
806
|
: getBrowserContent(appComponent, component, layout, snapshot, head));
|
|
824
807
|
}
|
|
825
808
|
/**
|
|
@@ -845,7 +828,7 @@ async function prepareErrorPage(event, response, container, snapshot) {
|
|
|
845
828
|
const component = await buildPageComponent(event, container, componentType, data, response.statusCode, error);
|
|
846
829
|
const appComponent = await buildAppComponent(event, container, componentType, layout, data, response.statusCode, error);
|
|
847
830
|
response.setContent(isSSR()
|
|
848
|
-
?
|
|
831
|
+
? getServerContent(appComponent, snapshotData, container, event, head)
|
|
849
832
|
: getBrowserContent(appComponent, component, layout, snapshot, head));
|
|
850
833
|
}
|
|
851
834
|
/**
|
|
@@ -888,108 +871,6 @@ async function onPreparingResponse({ event, response, container }) {
|
|
|
888
871
|
}
|
|
889
872
|
}
|
|
890
873
|
|
|
891
|
-
/**
|
|
892
|
-
* Class representing an UseReactUseReactKernelErrorHandler.
|
|
893
|
-
*
|
|
894
|
-
* Kernel level error handler for React applications.
|
|
895
|
-
*/
|
|
896
|
-
class UseReactKernelErrorHandler {
|
|
897
|
-
blueprint;
|
|
898
|
-
/**
|
|
899
|
-
* Create an UseReactUseReactKernelErrorHandler.
|
|
900
|
-
*
|
|
901
|
-
* @param options - UseReactUseReactKernelErrorHandler options.
|
|
902
|
-
*/
|
|
903
|
-
constructor({ blueprint }) {
|
|
904
|
-
this.blueprint = blueprint;
|
|
905
|
-
}
|
|
906
|
-
/**
|
|
907
|
-
* Handle an error.
|
|
908
|
-
*
|
|
909
|
-
* @param error - The error to handle.
|
|
910
|
-
* @returns The outgoing http response.
|
|
911
|
-
*/
|
|
912
|
-
handle(error) {
|
|
913
|
-
const metavalue = this.blueprint.get(`stone.useReact.errorPages.${String(error?.name)}`) ??
|
|
914
|
-
this.blueprint.get('stone.useReact.errorPages.default', {});
|
|
915
|
-
return { content: { ...metavalue, error }, statusCode: error?.statusCode ?? 500 };
|
|
916
|
-
}
|
|
917
|
-
}
|
|
918
|
-
|
|
919
|
-
/**
|
|
920
|
-
* Create an UseReact response.
|
|
921
|
-
*
|
|
922
|
-
* @param options - The options for creating the response.
|
|
923
|
-
* @returns The React response.
|
|
924
|
-
*/
|
|
925
|
-
const reactResponse = async (options) => {
|
|
926
|
-
if (isNotEmpty(options) &&
|
|
927
|
-
(isNotEmpty(options.url) ||
|
|
928
|
-
(isNotEmpty(options.content) && isNotEmpty(options.content.redirect)))) {
|
|
929
|
-
return await reactRedirectResponse(options);
|
|
930
|
-
}
|
|
931
|
-
return import.meta.env.SSR
|
|
932
|
-
? OutgoingHttpResponse.create(options)
|
|
933
|
-
: OutgoingBrowserResponse.create(options);
|
|
934
|
-
};
|
|
935
|
-
/**
|
|
936
|
-
* Create an UseReact redirect response.
|
|
937
|
-
*
|
|
938
|
-
* @param options - The options for creating the response.
|
|
939
|
-
* @returns The React redirect response.
|
|
940
|
-
*/
|
|
941
|
-
const reactRedirectResponse = async (options) => {
|
|
942
|
-
return import.meta.env.SSR
|
|
943
|
-
? RedirectResponse.create({ statusCode: 302, ...options })
|
|
944
|
-
: RedirectBrowserResponse.create({ statusCode: 302, ...options });
|
|
945
|
-
};
|
|
946
|
-
|
|
947
|
-
/**
|
|
948
|
-
* Class representing an UseReactServerErrorHandler.
|
|
949
|
-
*
|
|
950
|
-
* Adapter level error handler for React applications.
|
|
951
|
-
*/
|
|
952
|
-
class UseReactServerErrorHandler {
|
|
953
|
-
logger;
|
|
954
|
-
blueprint;
|
|
955
|
-
/**
|
|
956
|
-
* Create an UseReactServerErrorHandler.
|
|
957
|
-
*
|
|
958
|
-
* @param options - UseReactServerErrorHandler options.
|
|
959
|
-
*/
|
|
960
|
-
constructor({ blueprint }) {
|
|
961
|
-
this.blueprint = blueprint;
|
|
962
|
-
this.logger = Logger.getInstance();
|
|
963
|
-
}
|
|
964
|
-
/**
|
|
965
|
-
* Handle an error.
|
|
966
|
-
*
|
|
967
|
-
* @param error - The error to handle.
|
|
968
|
-
* @param context - The context of the adapter.
|
|
969
|
-
* @returns The raw response.
|
|
970
|
-
*/
|
|
971
|
-
async handle(error, context) {
|
|
972
|
-
this.logger.error(error.message, { error });
|
|
973
|
-
return context
|
|
974
|
-
.rawResponseBuilder
|
|
975
|
-
.add('statusCode', error.statusCode ?? 500)
|
|
976
|
-
.add('headers', new Headers({ 'Content-Type': 'text/html' }))
|
|
977
|
-
.add('body', await this.getErrorBody(error, context));
|
|
978
|
-
}
|
|
979
|
-
/**
|
|
980
|
-
* Get the error body.
|
|
981
|
-
*
|
|
982
|
-
* @param error - The error to handle.
|
|
983
|
-
* @returns The error body.
|
|
984
|
-
*/
|
|
985
|
-
async getErrorBody(error, context) {
|
|
986
|
-
const statusCode = error.statusCode ?? 500;
|
|
987
|
-
const template = await htmlTemplate(this.blueprint);
|
|
988
|
-
const ClientApp = await buildAdapterErrorComponent(this.blueprint, context, statusCode, error);
|
|
989
|
-
return template.replace('<!--app-html-->', renderToString(ClientApp));
|
|
990
|
-
}
|
|
991
|
-
}
|
|
992
|
-
|
|
993
874
|
/**
|
|
994
875
|
* Use React Service Provider.
|
|
995
876
|
*/
|
|
@@ -1058,6 +939,60 @@ function defineAdapterErrorPage(module, options) {
|
|
|
1058
939
|
};
|
|
1059
940
|
}
|
|
1060
941
|
|
|
942
|
+
/**
|
|
943
|
+
* Default blueprint for a React-based Stone.js application.
|
|
944
|
+
*
|
|
945
|
+
* - Defines middleware, lifecycle hooks, and the default HTML template path.
|
|
946
|
+
*/
|
|
947
|
+
const internalUseReactBlueprint = {
|
|
948
|
+
stone: {
|
|
949
|
+
useReact: {},
|
|
950
|
+
services: [MetaReactRuntime],
|
|
951
|
+
providers: [MetaUseReactServiceProvider]
|
|
952
|
+
}
|
|
953
|
+
};
|
|
954
|
+
|
|
955
|
+
/**
|
|
956
|
+
* Defines a Stone React app using a factory-based or class-based main handler.
|
|
957
|
+
*
|
|
958
|
+
* @param moduleOrOptions - A factory function or class constructor for the main page.
|
|
959
|
+
* @param optionsOrBlueprints - Optional application-level configuration.
|
|
960
|
+
* @param maybeBlueprints - Additional blueprints to merge.
|
|
961
|
+
* @returns A fully merged Stone blueprint.
|
|
962
|
+
*/
|
|
963
|
+
function defineStoneReactApp(moduleOrOptions = {}, optionsOrBlueprints, maybeBlueprints) {
|
|
964
|
+
let module;
|
|
965
|
+
let options = {};
|
|
966
|
+
let blueprints = [];
|
|
967
|
+
// Pattern: defineStoneReactApp(handler, options?, blueprints?)
|
|
968
|
+
if (isFunctionModule(moduleOrOptions)) {
|
|
969
|
+
module = moduleOrOptions;
|
|
970
|
+
if (isObjectLikeModule(optionsOrBlueprints)) {
|
|
971
|
+
options = optionsOrBlueprints;
|
|
972
|
+
blueprints = Array.isArray(maybeBlueprints) ? maybeBlueprints : [];
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
else if (isObjectLikeModule(moduleOrOptions)) { // Pattern: defineStoneReactApp(options, blueprints?)
|
|
976
|
+
options = moduleOrOptions;
|
|
977
|
+
blueprints = Array.isArray(optionsOrBlueprints) ? optionsOrBlueprints : [];
|
|
978
|
+
}
|
|
979
|
+
const stonePart = {
|
|
980
|
+
...options,
|
|
981
|
+
useReact: {
|
|
982
|
+
...options.useReact
|
|
983
|
+
}
|
|
984
|
+
};
|
|
985
|
+
if (isNotEmpty(module)) {
|
|
986
|
+
stonePart.useReact.componentEventHandler = {
|
|
987
|
+
module,
|
|
988
|
+
isComponent: true,
|
|
989
|
+
isClass: options.isClass,
|
|
990
|
+
isFactory: options.isClass !== true
|
|
991
|
+
};
|
|
992
|
+
}
|
|
993
|
+
return mergeBlueprints(stoneBlueprint, internalUseReactBlueprint, ...blueprints, { stone: stonePart });
|
|
994
|
+
}
|
|
995
|
+
|
|
1061
996
|
/**
|
|
1062
997
|
* Utility function to define a page.
|
|
1063
998
|
*
|
|
@@ -1164,136 +1099,194 @@ const REACT_ADAPTER_ERROR_PAGE_KEY = Symbol.for('ReactAdapterErrorPage');
|
|
|
1164
1099
|
const STONE_REACT_APP_KEY = Symbol.for('StoneReactApp');
|
|
1165
1100
|
|
|
1166
1101
|
/**
|
|
1167
|
-
*
|
|
1102
|
+
* A class decorator for defining a class as a React Handler layout.
|
|
1103
|
+
*
|
|
1104
|
+
* @param options - Configuration options for the layout definition.
|
|
1105
|
+
* @returns A method decorator to be applied to a class method.
|
|
1106
|
+
*
|
|
1107
|
+
* @example
|
|
1108
|
+
* ```typescript
|
|
1109
|
+
* import { AdapterErrorPage } from '@stone-js/use-react';
|
|
1110
|
+
*
|
|
1111
|
+
* @AdapterErrorPage({ error: 'UserNotFoundError' })
|
|
1112
|
+
* class UserAdapterErrorPage {
|
|
1113
|
+
* render({ error }) {
|
|
1114
|
+
* return <h1>User name: {error.message}</h1>;
|
|
1115
|
+
* }
|
|
1116
|
+
* }
|
|
1117
|
+
* ```
|
|
1168
1118
|
*/
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
* @param {blueprint} options - Options for creating the BrowserResponseMiddleware.
|
|
1176
|
-
*/
|
|
1177
|
-
constructor({ blueprint }) {
|
|
1178
|
-
this.blueprint = blueprint;
|
|
1179
|
-
this.isRendered = blueprint.has('stone.useReact.reactRoot');
|
|
1180
|
-
}
|
|
1181
|
-
/**
|
|
1182
|
-
* Handles the outgoing response, processes it, and invokes the next middleware in the pipeline.
|
|
1183
|
-
*
|
|
1184
|
-
* @param context - The adapter context containing the raw event, execution context, and other data.
|
|
1185
|
-
* @param next - The next middleware to be invoked in the pipeline.
|
|
1186
|
-
* @returns A promise resolving to the processed context.
|
|
1187
|
-
* @throws {NodeHttpAdapterError} If required components are missing in the context.
|
|
1188
|
-
*/
|
|
1189
|
-
async handle(context, next) {
|
|
1190
|
-
const rawResponseBuilder = await next(context);
|
|
1191
|
-
this.ensureValidContext(context, rawResponseBuilder);
|
|
1192
|
-
return rawResponseBuilder.add('render', async () => await this.renderComponent(context.outgoingResponse));
|
|
1193
|
-
}
|
|
1194
|
-
/**
|
|
1195
|
-
* Ensures the context and response builder have the required components.
|
|
1196
|
-
*/
|
|
1197
|
-
ensureValidContext(context, rawResponseBuilder) {
|
|
1198
|
-
if (context.rawEvent === undefined ||
|
|
1199
|
-
context.incomingEvent === undefined ||
|
|
1200
|
-
context.outgoingResponse === undefined ||
|
|
1201
|
-
rawResponseBuilder?.add === undefined) {
|
|
1202
|
-
throw new UseReactError('The context is missing required components.');
|
|
1203
|
-
}
|
|
1204
|
-
}
|
|
1205
|
-
/**
|
|
1206
|
-
* Renders the provided React content.
|
|
1207
|
-
*
|
|
1208
|
-
* @param response - The response object.
|
|
1209
|
-
*/
|
|
1210
|
-
async renderComponent(response) {
|
|
1211
|
-
if (isEmpty(response)) {
|
|
1212
|
-
throw new UseReactError('No response provided for rendering.');
|
|
1213
|
-
}
|
|
1214
|
-
const content = response.content;
|
|
1215
|
-
const targetUrl = response.targetUrl;
|
|
1216
|
-
if (isNotEmpty(targetUrl)) {
|
|
1217
|
-
return this.handleRedirect(targetUrl);
|
|
1218
|
-
}
|
|
1219
|
-
if (isNotEmpty(content?.head)) {
|
|
1220
|
-
applyHeadContextToDom(document, content.head);
|
|
1221
|
-
}
|
|
1222
|
-
if (content?.ssr === true && !this.isRendered && isNotEmpty(content?.app)) {
|
|
1223
|
-
return this.hydrateReactApp(content.app);
|
|
1224
|
-
}
|
|
1225
|
-
if (isNotEmpty(content?.app) && (!this.isRendered || content?.fullRender === true)) {
|
|
1226
|
-
return this.renderReactApp(content.app);
|
|
1227
|
-
}
|
|
1228
|
-
if (isNotEmpty(content?.component)) {
|
|
1229
|
-
return await this.dispatchComponentToOutlet(content.component);
|
|
1230
|
-
}
|
|
1231
|
-
throw new UseReactError('Invalid content provided for rendering.');
|
|
1232
|
-
}
|
|
1233
|
-
/**
|
|
1234
|
-
* Handles navigation redirection.
|
|
1235
|
-
*
|
|
1236
|
-
* @param path - The path to redirect to.
|
|
1237
|
-
*/
|
|
1238
|
-
handleRedirect(path) {
|
|
1239
|
-
window.history.pushState({ path }, '', path);
|
|
1240
|
-
window.dispatchEvent(new Event(NAVIGATION_EVENT));
|
|
1241
|
-
}
|
|
1242
|
-
/**
|
|
1243
|
-
* Hydrates the React app when SSR is enabled.
|
|
1244
|
-
*
|
|
1245
|
-
* @param app - The React app to hydrate.
|
|
1246
|
-
*/
|
|
1247
|
-
hydrateReactApp(app) {
|
|
1248
|
-
hydrateReactApp(app, this.blueprint);
|
|
1249
|
-
}
|
|
1250
|
-
/**
|
|
1251
|
-
* Renders the React app.
|
|
1252
|
-
*
|
|
1253
|
-
* @param app - The React app to render.
|
|
1254
|
-
*/
|
|
1255
|
-
renderReactApp(app) {
|
|
1256
|
-
renderReactApp(app, this.blueprint);
|
|
1257
|
-
}
|
|
1258
|
-
/**
|
|
1259
|
-
* Dispatches a component to the layout outlet when no layout is defined.
|
|
1260
|
-
*
|
|
1261
|
-
* @param component - The component to dispatch.
|
|
1262
|
-
*/
|
|
1263
|
-
async dispatchComponentToOutlet(component) {
|
|
1264
|
-
window.dispatchEvent(new CustomEvent(STONE_PAGE_EVENT_OUTLET, { detail: component }));
|
|
1265
|
-
}
|
|
1266
|
-
}
|
|
1119
|
+
const AdapterErrorPage = (options) => {
|
|
1120
|
+
return classDecoratorLegacyWrapper((_target, context) => {
|
|
1121
|
+
setMetadata(context, REACT_ADAPTER_ERROR_PAGE_KEY, { ...options, isClass: true });
|
|
1122
|
+
});
|
|
1123
|
+
};
|
|
1124
|
+
|
|
1267
1125
|
/**
|
|
1268
|
-
*
|
|
1126
|
+
* A class decorator for defining a class as a React Handler layout.
|
|
1127
|
+
*
|
|
1128
|
+
* @param options - Configuration options for the layout definition.
|
|
1129
|
+
* @returns A method decorator to be applied to a class method.
|
|
1130
|
+
*
|
|
1131
|
+
* @example
|
|
1132
|
+
* ```typescript
|
|
1133
|
+
* import { ErrorPage } from '@stone-js/use-react';
|
|
1134
|
+
*
|
|
1135
|
+
* @ErrorPage({ error: 'UserNotFoundError' })
|
|
1136
|
+
* class UserErrorPage {
|
|
1137
|
+
* render({ error }) {
|
|
1138
|
+
* return <h1>User name: {error.message}</h1>;
|
|
1139
|
+
* }
|
|
1140
|
+
* }
|
|
1141
|
+
* ```
|
|
1269
1142
|
*/
|
|
1270
|
-
const
|
|
1143
|
+
const ErrorPage = (options) => {
|
|
1144
|
+
return classDecoratorLegacyWrapper((_target, context) => {
|
|
1145
|
+
setMetadata(context, REACT_ERROR_PAGE_KEY, { ...options, isClass: true });
|
|
1146
|
+
});
|
|
1147
|
+
};
|
|
1271
1148
|
|
|
1272
1149
|
/**
|
|
1273
|
-
*
|
|
1150
|
+
* A class decorator for defining a class as a React Page route action.
|
|
1151
|
+
* Uses the `Match` decorator internally to register the route with the HTTP `GET` method.
|
|
1274
1152
|
*
|
|
1275
|
-
* @param
|
|
1276
|
-
* @
|
|
1277
|
-
* @returns The updated blueprint or a promise resolving to it.
|
|
1153
|
+
* @param options - Configuration options for the route definition, excluding the `methods` property.
|
|
1154
|
+
* @returns A method decorator to be applied to a class method.
|
|
1278
1155
|
*
|
|
1279
1156
|
* @example
|
|
1280
1157
|
* ```typescript
|
|
1281
|
-
*
|
|
1158
|
+
* import { Page } from '@stone-js/use-react';
|
|
1159
|
+
*
|
|
1160
|
+
* @Page('/user-profile')
|
|
1161
|
+
* class UserPage {
|
|
1162
|
+
* handle({ event }): Record<string, string> {
|
|
1163
|
+
* return { name: 'Jane Doe' };
|
|
1164
|
+
* }
|
|
1165
|
+
*
|
|
1166
|
+
* render({ data }) {
|
|
1167
|
+
* return <h1>User name: {data.name}</h1>;
|
|
1168
|
+
* }
|
|
1169
|
+
* }
|
|
1282
1170
|
* ```
|
|
1283
1171
|
*/
|
|
1284
|
-
const
|
|
1285
|
-
|
|
1286
|
-
context
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1172
|
+
const Page = (path, options = {}) => {
|
|
1173
|
+
return classDecoratorLegacyWrapper((target, context) => {
|
|
1174
|
+
setMetadata(context, REACT_PAGE_KEY, {
|
|
1175
|
+
...options,
|
|
1176
|
+
path,
|
|
1177
|
+
method: GET,
|
|
1178
|
+
methods: [],
|
|
1179
|
+
handler: { isClass: true, isComponent: true, layout: options.layout, module: target }
|
|
1180
|
+
});
|
|
1181
|
+
});
|
|
1182
|
+
};
|
|
1183
|
+
|
|
1184
|
+
/**
|
|
1185
|
+
* A class decorator for defining a class as a React Page layout.
|
|
1186
|
+
*
|
|
1187
|
+
* @param options - Configuration options for the layout definition.
|
|
1188
|
+
* @returns A method decorator to be applied to a class method.
|
|
1189
|
+
*
|
|
1190
|
+
* @example
|
|
1191
|
+
* ```typescript
|
|
1192
|
+
* import { PageLayout } from '@stone-js/use-react';
|
|
1193
|
+
*
|
|
1194
|
+
* @PageLayout({ name: 'UserPageLayout' })
|
|
1195
|
+
* class UserPageLayout {
|
|
1196
|
+
* render({ data }) {
|
|
1197
|
+
* return <h1>User name: {data.name}</h1>;
|
|
1198
|
+
* }
|
|
1199
|
+
* }
|
|
1200
|
+
* ```
|
|
1201
|
+
*/
|
|
1202
|
+
const PageLayout = (options) => {
|
|
1203
|
+
return classDecoratorLegacyWrapper((_target, context) => {
|
|
1204
|
+
setMetadata(context, REACT_PAGE_LAYOUT_KEY, { ...options, isClass: true });
|
|
1205
|
+
});
|
|
1206
|
+
};
|
|
1207
|
+
|
|
1208
|
+
/**
|
|
1209
|
+
* Hook decorator to mark a method as a lifecycle hook
|
|
1210
|
+
* And automatically add it to the global lifecycle hook registry.
|
|
1211
|
+
*
|
|
1212
|
+
* @example
|
|
1213
|
+
* ```typescript
|
|
1214
|
+
* class MyClass {
|
|
1215
|
+
* // ...
|
|
1216
|
+
* @Hook('onPreparingPage')
|
|
1217
|
+
* onPreparingPage () {}
|
|
1218
|
+
* }
|
|
1219
|
+
* ```
|
|
1220
|
+
*
|
|
1221
|
+
* @param name - The name of the lifecycle hook.
|
|
1222
|
+
* @returns A class decorator function that sets the metadata using the provided options.
|
|
1223
|
+
*/
|
|
1224
|
+
const Hook = (name) => {
|
|
1225
|
+
return methodDecoratorLegacyWrapper((_target, context) => {
|
|
1226
|
+
addMetadata(context, LIFECYCLE_HOOK_KEY, { name, method: context.name });
|
|
1227
|
+
});
|
|
1228
|
+
};
|
|
1229
|
+
|
|
1230
|
+
/**
|
|
1231
|
+
* Decorator to set the status code of the response.
|
|
1232
|
+
*
|
|
1233
|
+
* @param statusCode - The status code of the response.
|
|
1234
|
+
* @param headers - The headers for the response.
|
|
1235
|
+
* @returns A method decorator.
|
|
1236
|
+
*
|
|
1237
|
+
* @example
|
|
1238
|
+
* ```typescript
|
|
1239
|
+
* import { Page, PageStatus } from '@stone-js/use-react';
|
|
1240
|
+
*
|
|
1241
|
+
* @Page('/user-profile')
|
|
1242
|
+
* class UserPage {
|
|
1243
|
+
* @PageStatus()
|
|
1244
|
+
* handle() {
|
|
1245
|
+
* return { name: 'John Doe' };
|
|
1246
|
+
* }
|
|
1247
|
+
* }
|
|
1248
|
+
* ```
|
|
1249
|
+
*/
|
|
1250
|
+
const PageStatus = (statusCode = 200, headers = {}) => {
|
|
1251
|
+
return methodDecoratorLegacyWrapper((target, _context) => {
|
|
1252
|
+
return async function (...args) {
|
|
1253
|
+
const content = await target.apply(this, args);
|
|
1254
|
+
return { content, statusCode, headers };
|
|
1255
|
+
};
|
|
1256
|
+
});
|
|
1291
1257
|
};
|
|
1258
|
+
|
|
1292
1259
|
/**
|
|
1293
|
-
*
|
|
1260
|
+
* Decorator to create a snapshot of the current data.
|
|
1261
|
+
*
|
|
1262
|
+
* @param name - The name of the snapshot.
|
|
1263
|
+
* @returns A method decorator.
|
|
1264
|
+
*
|
|
1265
|
+
* @example
|
|
1266
|
+
* ```typescript
|
|
1267
|
+
* import { Service } from '@stone-js/core';
|
|
1268
|
+
* import { Snapshot } from '@stone-js/use-react';
|
|
1294
1269
|
*
|
|
1295
|
-
*
|
|
1296
|
-
*
|
|
1270
|
+
* @Service({ alias: 'userService' })
|
|
1271
|
+
* class UserService {
|
|
1272
|
+
* @Snapshot()
|
|
1273
|
+
* showProfile() {
|
|
1274
|
+
* return { name: 'John Doe' };
|
|
1275
|
+
* }
|
|
1276
|
+
* }
|
|
1277
|
+
* ```
|
|
1278
|
+
*/
|
|
1279
|
+
const Snapshot = (name) => {
|
|
1280
|
+
return methodDecoratorLegacyWrapper((target, context) => {
|
|
1281
|
+
return async function (...args) {
|
|
1282
|
+
name = name ?? `${String(Object.getPrototypeOf(this).constructor.name)}.${String(context.name)}`;
|
|
1283
|
+
return await ReactRuntime.instance?.snapshot(name, () => target.apply(this, args));
|
|
1284
|
+
};
|
|
1285
|
+
});
|
|
1286
|
+
};
|
|
1287
|
+
|
|
1288
|
+
/**
|
|
1289
|
+
* Blueprint middleware to dynamically set lifecycle hooks for react.
|
|
1297
1290
|
*
|
|
1298
1291
|
* @param context - The configuration context containing modules and blueprint.
|
|
1299
1292
|
* @param next - The next pipeline function to continue processing.
|
|
@@ -1301,14 +1294,18 @@ const SetUseReactHooksMiddleware = (context, next) => {
|
|
|
1301
1294
|
*
|
|
1302
1295
|
* @example
|
|
1303
1296
|
* ```typescript
|
|
1304
|
-
*
|
|
1297
|
+
* SetUseReactHooksMiddleware(context, next)
|
|
1305
1298
|
* ```
|
|
1306
1299
|
*/
|
|
1307
|
-
const
|
|
1308
|
-
|
|
1309
|
-
|
|
1300
|
+
const SetUseReactHooksMiddleware = (context, next) => {
|
|
1301
|
+
const currentPlatform = context.blueprint.get('stone.adapter.platform', '');
|
|
1302
|
+
const ignorePlatforms = context.blueprint.get('stone.useReact.ignorePlatforms', []);
|
|
1303
|
+
if (!ignorePlatforms.includes(currentPlatform)) {
|
|
1304
|
+
context
|
|
1305
|
+
.blueprint
|
|
1306
|
+
.add('stone.lifecycleHooks.onPreparingResponse', [onPreparingResponse]);
|
|
1310
1307
|
}
|
|
1311
|
-
return
|
|
1308
|
+
return next(context);
|
|
1312
1309
|
};
|
|
1313
1310
|
/**
|
|
1314
1311
|
* Blueprint middleware to process and register kernel error page definitions from modules.
|
|
@@ -1347,80 +1344,6 @@ const SetReactKernelErrorPageMiddleware = (context, next) => {
|
|
|
1347
1344
|
});
|
|
1348
1345
|
return next(context);
|
|
1349
1346
|
};
|
|
1350
|
-
/**
|
|
1351
|
-
* Blueprint middleware to process and register adapter error page definitions from modules.
|
|
1352
|
-
*
|
|
1353
|
-
* @param context - The configuration context containing modules and blueprint.
|
|
1354
|
-
* @param next - The next pipeline function to continue processing.
|
|
1355
|
-
* @returns The updated blueprint or a promise resolving to it.
|
|
1356
|
-
*
|
|
1357
|
-
* @example
|
|
1358
|
-
* ```typescript
|
|
1359
|
-
* SetReactAdapterErrorPageMiddleware(context, next)
|
|
1360
|
-
* ```
|
|
1361
|
-
*/
|
|
1362
|
-
const SetReactAdapterErrorPageMiddleware = (context, next) => {
|
|
1363
|
-
const UseReactAdapterErrorHandler = import.meta.env.SSR
|
|
1364
|
-
? UseReactServerErrorHandler
|
|
1365
|
-
: UseReactBrowserErrorHandler;
|
|
1366
|
-
context
|
|
1367
|
-
.blueprint
|
|
1368
|
-
.set('stone.adapter.errorHandlers.default', { module: UseReactAdapterErrorHandler, isClass: true });
|
|
1369
|
-
context
|
|
1370
|
-
.modules
|
|
1371
|
-
.filter(module => hasMetadata(module, REACT_ADAPTER_ERROR_PAGE_KEY))
|
|
1372
|
-
.forEach(module => {
|
|
1373
|
-
const { error, layout, adapterAlias, platform } = getMetadata(module, REACT_ADAPTER_ERROR_PAGE_KEY, { error: 'default' });
|
|
1374
|
-
if (isMatchedAdapter(context.blueprint, platform, adapterAlias)) {
|
|
1375
|
-
Array(error).flat().forEach(name => {
|
|
1376
|
-
context
|
|
1377
|
-
.blueprint
|
|
1378
|
-
.set(`stone.useReact.adapterErrorPages.${name}`, { isClass: true, layout, module });
|
|
1379
|
-
});
|
|
1380
|
-
}
|
|
1381
|
-
});
|
|
1382
|
-
// Process both eager and lazy loaded error pages
|
|
1383
|
-
Object
|
|
1384
|
-
.keys(context.blueprint.get('stone.useReact.adapterErrorPages', {}))
|
|
1385
|
-
.forEach((name) => {
|
|
1386
|
-
context
|
|
1387
|
-
.blueprint
|
|
1388
|
-
.set(`stone.adapter.errorHandlers.${name}`, { module: UseReactAdapterErrorHandler, isClass: true });
|
|
1389
|
-
});
|
|
1390
|
-
return next(context);
|
|
1391
|
-
};
|
|
1392
|
-
/**
|
|
1393
|
-
* Blueprint middleware to set StaticFileMiddleware for SSR adapter.
|
|
1394
|
-
*
|
|
1395
|
-
* @param context - The configuration context containing modules and blueprint.
|
|
1396
|
-
* @param next - The next pipeline function to continue processing.
|
|
1397
|
-
* @returns The updated blueprint or a promise resolving to it.
|
|
1398
|
-
*
|
|
1399
|
-
* @example
|
|
1400
|
-
* ```typescript
|
|
1401
|
-
* SetSSRStaticFileMiddleware(context, next)
|
|
1402
|
-
* ```
|
|
1403
|
-
*/
|
|
1404
|
-
const SetSSRStaticFileMiddleware = async (context, next) => {
|
|
1405
|
-
import.meta.env.SSR && context.blueprint.add('stone.kernel.middleware', [MetaStaticFileMiddleware]);
|
|
1406
|
-
return await next(context);
|
|
1407
|
-
};
|
|
1408
|
-
/**
|
|
1409
|
-
* Blueprint middleware to set CompressionMiddleware for SSR adapter.
|
|
1410
|
-
*
|
|
1411
|
-
* @param context - The configuration context containing modules and blueprint.
|
|
1412
|
-
* @param next - The next pipeline function to continue processing.
|
|
1413
|
-
* @returns The updated blueprint or a promise resolving to it.
|
|
1414
|
-
*
|
|
1415
|
-
* @example
|
|
1416
|
-
* ```typescript
|
|
1417
|
-
* SetSSRCompressionMiddleware(context, next)
|
|
1418
|
-
* ```
|
|
1419
|
-
*/
|
|
1420
|
-
const SetSSRCompressionMiddleware = async (context, next) => {
|
|
1421
|
-
import.meta.env.SSR && context.blueprint.add('stone.kernel.middleware', [MetaCompressionMiddleware]);
|
|
1422
|
-
return await next(context);
|
|
1423
|
-
};
|
|
1424
1347
|
/**
|
|
1425
1348
|
* Blueprint middleware to process and register route definitions from modules.
|
|
1426
1349
|
*
|
|
@@ -1492,267 +1415,187 @@ async function SetUseReactEventHandlerMiddleware(context, next) {
|
|
|
1492
1415
|
}
|
|
1493
1416
|
return blueprint;
|
|
1494
1417
|
}
|
|
1418
|
+
|
|
1495
1419
|
/**
|
|
1496
|
-
*
|
|
1420
|
+
* Sets the error handler for the React adapter and registers error pages.
|
|
1497
1421
|
*
|
|
1498
|
-
*
|
|
1499
|
-
*
|
|
1422
|
+
* @param errorHandler - The error handler to set for the React adapter.
|
|
1423
|
+
* @param context - The blueprint context containing modules and blueprint.
|
|
1424
|
+
* @returns The updated blueprint context with the error handler and error pages set.
|
|
1500
1425
|
*/
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1426
|
+
function setUseReactAdapterErrorHandler(errorHandler, context) {
|
|
1427
|
+
context
|
|
1428
|
+
.blueprint
|
|
1429
|
+
.set('stone.adapter.errorHandlers.default', { module: errorHandler, isClass: true });
|
|
1430
|
+
context
|
|
1431
|
+
.modules
|
|
1432
|
+
.filter(module => hasMetadata(module, REACT_ADAPTER_ERROR_PAGE_KEY))
|
|
1433
|
+
.forEach(module => {
|
|
1434
|
+
const { error, layout, adapterAlias, platform } = getMetadata(module, REACT_ADAPTER_ERROR_PAGE_KEY, { error: 'default' });
|
|
1435
|
+
if (isMatchedAdapter(context.blueprint, platform, adapterAlias)) {
|
|
1436
|
+
Array(error).flat().forEach(name => {
|
|
1437
|
+
context
|
|
1438
|
+
.blueprint
|
|
1439
|
+
.set(`stone.useReact.adapterErrorPages.${name}`, { isClass: true, layout, module });
|
|
1440
|
+
});
|
|
1441
|
+
}
|
|
1442
|
+
});
|
|
1443
|
+
// Process both eager and lazy loaded error pages
|
|
1444
|
+
Object
|
|
1445
|
+
.keys(context.blueprint.get('stone.useReact.adapterErrorPages', {}))
|
|
1446
|
+
.forEach((name) => {
|
|
1447
|
+
context
|
|
1448
|
+
.blueprint
|
|
1449
|
+
.set(`stone.adapter.errorHandlers.${name}`, { module: errorHandler, isClass: true });
|
|
1450
|
+
});
|
|
1451
|
+
return context;
|
|
1452
|
+
}
|
|
1512
1453
|
|
|
1513
1454
|
/**
|
|
1514
|
-
*
|
|
1455
|
+
* Create an UseReact response.
|
|
1515
1456
|
*
|
|
1516
|
-
* -
|
|
1457
|
+
* @param options - The options for creating the response.
|
|
1458
|
+
* @returns The React response.
|
|
1517
1459
|
*/
|
|
1518
|
-
const
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
},
|
|
1524
|
-
services: [MetaReactRuntime],
|
|
1525
|
-
providers: [MetaUseReactServiceProvider]
|
|
1460
|
+
const reactResponse = (options) => {
|
|
1461
|
+
if (isNotEmpty(options) &&
|
|
1462
|
+
(isNotEmpty(options.url) ||
|
|
1463
|
+
(isNotEmpty(options.content) && isNotEmpty(options.content.redirect)))) {
|
|
1464
|
+
return reactRedirectResponse(options);
|
|
1526
1465
|
}
|
|
1466
|
+
return OutgoingHttpResponse.create(options);
|
|
1467
|
+
};
|
|
1468
|
+
/**
|
|
1469
|
+
* Create an UseReact redirect response.
|
|
1470
|
+
*
|
|
1471
|
+
* @param options - The options for creating the response.
|
|
1472
|
+
* @returns The React redirect response.
|
|
1473
|
+
*/
|
|
1474
|
+
const reactRedirectResponse = (options) => {
|
|
1475
|
+
return RedirectResponse.create({ statusCode: 302, ...options });
|
|
1527
1476
|
};
|
|
1528
1477
|
|
|
1529
1478
|
/**
|
|
1530
|
-
*
|
|
1479
|
+
* Class representing an UseReactServerErrorHandler.
|
|
1531
1480
|
*
|
|
1532
|
-
*
|
|
1533
|
-
* @param optionsOrBlueprints - Optional application-level configuration.
|
|
1534
|
-
* @param maybeBlueprints - Additional blueprints to merge.
|
|
1535
|
-
* @returns A fully merged Stone blueprint.
|
|
1481
|
+
* Adapter level error handler for React applications.
|
|
1536
1482
|
*/
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1483
|
+
class UseReactServerErrorHandler {
|
|
1484
|
+
logger;
|
|
1485
|
+
blueprint;
|
|
1486
|
+
/**
|
|
1487
|
+
* Create an UseReactServerErrorHandler.
|
|
1488
|
+
*
|
|
1489
|
+
* @param options - UseReactServerErrorHandler options.
|
|
1490
|
+
*/
|
|
1491
|
+
constructor({ blueprint }) {
|
|
1492
|
+
this.blueprint = blueprint;
|
|
1493
|
+
this.logger = Logger.getInstance();
|
|
1548
1494
|
}
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1495
|
+
/**
|
|
1496
|
+
* Handle an error.
|
|
1497
|
+
*
|
|
1498
|
+
* @param error - The error to handle.
|
|
1499
|
+
* @param context - The context of the adapter.
|
|
1500
|
+
* @returns The raw response.
|
|
1501
|
+
*/
|
|
1502
|
+
async handle(error, context) {
|
|
1503
|
+
this.logger.error(error.message, { error });
|
|
1504
|
+
return context
|
|
1505
|
+
.rawResponseBuilder
|
|
1506
|
+
.add('statusCode', error.statusCode ?? 500)
|
|
1507
|
+
.add('headers', new Headers({ 'Content-Type': 'text/html' }))
|
|
1508
|
+
.add('body', await this.getErrorBody(error, context));
|
|
1552
1509
|
}
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
isFactory: options.isClass !== true
|
|
1565
|
-
};
|
|
1510
|
+
/**
|
|
1511
|
+
* Get the error body.
|
|
1512
|
+
*
|
|
1513
|
+
* @param error - The error to handle.
|
|
1514
|
+
* @returns The error body.
|
|
1515
|
+
*/
|
|
1516
|
+
async getErrorBody(error, context) {
|
|
1517
|
+
const statusCode = error.statusCode ?? 500;
|
|
1518
|
+
const template = htmlTemplate(this.blueprint);
|
|
1519
|
+
const ClientApp = await buildAdapterErrorComponent(this.blueprint, context, statusCode, error);
|
|
1520
|
+
return template.replace('<!--app-html-->', renderToString(ClientApp));
|
|
1566
1521
|
}
|
|
1567
|
-
return mergeBlueprints(stoneBlueprint, useReactBlueprint, ...blueprints, { stone: stonePart });
|
|
1568
1522
|
}
|
|
1569
1523
|
|
|
1570
1524
|
/**
|
|
1571
|
-
*
|
|
1525
|
+
* Blueprint middleware to process and register adapter error page definitions from modules.
|
|
1572
1526
|
*
|
|
1573
|
-
* @param
|
|
1574
|
-
* @
|
|
1527
|
+
* @param context - The configuration context containing modules and blueprint.
|
|
1528
|
+
* @param next - The next pipeline function to continue processing.
|
|
1529
|
+
* @returns The updated blueprint or a promise resolving to it.
|
|
1575
1530
|
*
|
|
1576
1531
|
* @example
|
|
1577
1532
|
* ```typescript
|
|
1578
|
-
*
|
|
1579
|
-
*
|
|
1580
|
-
* @AdapterErrorPage({ error: 'UserNotFoundError' })
|
|
1581
|
-
* class UserAdapterErrorPage {
|
|
1582
|
-
* render({ error }) {
|
|
1583
|
-
* return <h1>User name: {error.message}</h1>;
|
|
1584
|
-
* }
|
|
1585
|
-
* }
|
|
1533
|
+
* SetReactAdapterErrorPageMiddleware(context, next)
|
|
1586
1534
|
* ```
|
|
1587
1535
|
*/
|
|
1588
|
-
const
|
|
1589
|
-
return
|
|
1590
|
-
setMetadata(context, REACT_ADAPTER_ERROR_PAGE_KEY, { ...options, isClass: true });
|
|
1591
|
-
});
|
|
1536
|
+
const SetReactAdapterErrorPageMiddleware = (context, next) => {
|
|
1537
|
+
return next(setUseReactAdapterErrorHandler(UseReactServerErrorHandler, context));
|
|
1592
1538
|
};
|
|
1593
|
-
|
|
1594
1539
|
/**
|
|
1595
|
-
*
|
|
1596
|
-
*
|
|
1597
|
-
* @param options - Configuration options for the layout definition.
|
|
1598
|
-
* @returns A method decorator to be applied to a class method.
|
|
1599
|
-
*
|
|
1600
|
-
* @example
|
|
1601
|
-
* ```typescript
|
|
1602
|
-
* import { ErrorPage } from '@stone-js/use-react';
|
|
1540
|
+
* Blueprint middleware to set StaticFileMiddleware for SSR adapter.
|
|
1603
1541
|
*
|
|
1604
|
-
* @
|
|
1605
|
-
*
|
|
1606
|
-
*
|
|
1607
|
-
* return <h1>User name: {error.message}</h1>;
|
|
1608
|
-
* }
|
|
1609
|
-
* }
|
|
1610
|
-
* ```
|
|
1611
|
-
*/
|
|
1612
|
-
const ErrorPage = (options) => {
|
|
1613
|
-
return classDecoratorLegacyWrapper((_target, context) => {
|
|
1614
|
-
setMetadata(context, REACT_ERROR_PAGE_KEY, { ...options, isClass: true });
|
|
1615
|
-
});
|
|
1616
|
-
};
|
|
1617
|
-
|
|
1618
|
-
/**
|
|
1619
|
-
* Hook decorator to mark a method as a lifecycle hook
|
|
1620
|
-
* And automatically add it to the global lifecycle hook registry.
|
|
1542
|
+
* @param context - The configuration context containing modules and blueprint.
|
|
1543
|
+
* @param next - The next pipeline function to continue processing.
|
|
1544
|
+
* @returns The updated blueprint or a promise resolving to it.
|
|
1621
1545
|
*
|
|
1622
1546
|
* @example
|
|
1623
1547
|
* ```typescript
|
|
1624
|
-
*
|
|
1625
|
-
* // ...
|
|
1626
|
-
* @Hook('onPreparingPage')
|
|
1627
|
-
* onPreparingPage () {}
|
|
1628
|
-
* }
|
|
1548
|
+
* SetSSRStaticFileMiddleware(context, next)
|
|
1629
1549
|
* ```
|
|
1630
|
-
*
|
|
1631
|
-
* @param name - The name of the lifecycle hook.
|
|
1632
|
-
* @returns A class decorator function that sets the metadata using the provided options.
|
|
1633
1550
|
*/
|
|
1634
|
-
const
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
});
|
|
1551
|
+
const SetSSRStaticFileMiddleware = async (context, next) => {
|
|
1552
|
+
context.blueprint.add('stone.kernel.middleware', [MetaStaticFileMiddleware]);
|
|
1553
|
+
return await next(context);
|
|
1638
1554
|
};
|
|
1639
|
-
|
|
1640
1555
|
/**
|
|
1641
|
-
*
|
|
1642
|
-
* Uses the `Match` decorator internally to register the route with the HTTP `GET` method.
|
|
1556
|
+
* Blueprint middleware to set CompressionMiddleware for SSR adapter.
|
|
1643
1557
|
*
|
|
1644
|
-
* @param
|
|
1645
|
-
* @
|
|
1558
|
+
* @param context - The configuration context containing modules and blueprint.
|
|
1559
|
+
* @param next - The next pipeline function to continue processing.
|
|
1560
|
+
* @returns The updated blueprint or a promise resolving to it.
|
|
1646
1561
|
*
|
|
1647
1562
|
* @example
|
|
1648
1563
|
* ```typescript
|
|
1649
|
-
*
|
|
1650
|
-
*
|
|
1651
|
-
* @Page('/user-profile')
|
|
1652
|
-
* class UserPage {
|
|
1653
|
-
* handle({ event }): Record<string, string> {
|
|
1654
|
-
* return { name: 'Jane Doe' };
|
|
1655
|
-
* }
|
|
1656
|
-
*
|
|
1657
|
-
* render({ data }) {
|
|
1658
|
-
* return <h1>User name: {data.name}</h1>;
|
|
1659
|
-
* }
|
|
1660
|
-
* }
|
|
1564
|
+
* SetSSRCompressionMiddleware(context, next)
|
|
1661
1565
|
* ```
|
|
1662
1566
|
*/
|
|
1663
|
-
const
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
...options,
|
|
1667
|
-
path,
|
|
1668
|
-
method: GET,
|
|
1669
|
-
methods: [],
|
|
1670
|
-
handler: { isClass: true, isComponent: true, layout: options.layout, module: target }
|
|
1671
|
-
});
|
|
1672
|
-
});
|
|
1567
|
+
const SetSSRCompressionMiddleware = async (context, next) => {
|
|
1568
|
+
context.blueprint.add('stone.kernel.middleware', [MetaCompressionMiddleware]);
|
|
1569
|
+
return await next(context);
|
|
1673
1570
|
};
|
|
1674
|
-
|
|
1675
1571
|
/**
|
|
1676
|
-
*
|
|
1677
|
-
*
|
|
1678
|
-
* @param options - Configuration options for the layout definition.
|
|
1679
|
-
* @returns A method decorator to be applied to a class method.
|
|
1680
|
-
*
|
|
1681
|
-
* @example
|
|
1682
|
-
* ```typescript
|
|
1683
|
-
* import { PageLayout } from '@stone-js/use-react';
|
|
1572
|
+
* Configuration for react processing middleware.
|
|
1684
1573
|
*
|
|
1685
|
-
*
|
|
1686
|
-
*
|
|
1687
|
-
* render({ data }) {
|
|
1688
|
-
* return <h1>User name: {data.name}</h1>;
|
|
1689
|
-
* }
|
|
1690
|
-
* }
|
|
1691
|
-
* ```
|
|
1574
|
+
* This array defines a list of middleware pipes, each with a `pipe` function and a `priority`.
|
|
1575
|
+
* These pipes are executed in the order of their priority values, with lower values running first.
|
|
1692
1576
|
*/
|
|
1693
|
-
const
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
}
|
|
1697
|
-
}
|
|
1577
|
+
const metaServerUseReactBlueprintMiddleware = [
|
|
1578
|
+
{ module: SetSSRStaticFileMiddleware, priority: 10 },
|
|
1579
|
+
{ module: SetUseReactHooksMiddleware, priority: 10 },
|
|
1580
|
+
{ module: SetSSRCompressionMiddleware, priority: 10 },
|
|
1581
|
+
{ module: SetReactPageLayoutMiddleware, priority: 10 },
|
|
1582
|
+
{ module: SetUseReactEventHandlerMiddleware, priority: 2 },
|
|
1583
|
+
{ module: SetReactKernelErrorPageMiddleware, priority: 10 },
|
|
1584
|
+
{ module: SetReactAdapterErrorPageMiddleware, priority: 10 },
|
|
1585
|
+
{ module: SetReactRouteDefinitionsMiddleware, priority: 10 }
|
|
1586
|
+
];
|
|
1698
1587
|
|
|
1699
1588
|
/**
|
|
1700
|
-
*
|
|
1701
|
-
*
|
|
1702
|
-
* @param statusCode - The status code of the response.
|
|
1703
|
-
* @param headers - The headers for the response.
|
|
1704
|
-
* @returns A method decorator.
|
|
1705
|
-
*
|
|
1706
|
-
* @example
|
|
1707
|
-
* ```typescript
|
|
1708
|
-
* import { Page, PageStatus } from '@stone-js/use-react';
|
|
1709
|
-
*
|
|
1710
|
-
* @Page('/user-profile')
|
|
1711
|
-
* class UserPage {
|
|
1712
|
-
* @PageStatus()
|
|
1713
|
-
* handle() {
|
|
1714
|
-
* return { name: 'John Doe' };
|
|
1715
|
-
* }
|
|
1716
|
-
* }
|
|
1717
|
-
* ```
|
|
1589
|
+
* Middleware for the React blueprint.
|
|
1718
1590
|
*/
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
return async function (...args) {
|
|
1722
|
-
const content = await target.apply(this, args);
|
|
1723
|
-
return { content, statusCode, headers };
|
|
1724
|
-
};
|
|
1725
|
-
});
|
|
1726
|
-
};
|
|
1727
|
-
|
|
1591
|
+
internalUseReactBlueprint.stone.useReact.ignorePlatforms = [NODE_CONSOLE_PLATFORM];
|
|
1592
|
+
internalUseReactBlueprint.stone.blueprint = { middleware: metaServerUseReactBlueprintMiddleware };
|
|
1728
1593
|
/**
|
|
1729
|
-
*
|
|
1730
|
-
*
|
|
1731
|
-
* @param name - The name of the snapshot.
|
|
1732
|
-
* @returns A method decorator.
|
|
1733
|
-
*
|
|
1734
|
-
* @example
|
|
1735
|
-
* ```typescript
|
|
1736
|
-
* import { Service } from '@stone-js/core';
|
|
1737
|
-
* import { Snapshot } from '@stone-js/use-react';
|
|
1594
|
+
* Default blueprint for a React-based Stone.js application.
|
|
1738
1595
|
*
|
|
1739
|
-
*
|
|
1740
|
-
* class UserService {
|
|
1741
|
-
* @Snapshot()
|
|
1742
|
-
* showProfile() {
|
|
1743
|
-
* return { name: 'John Doe' };
|
|
1744
|
-
* }
|
|
1745
|
-
* }
|
|
1746
|
-
* ```
|
|
1596
|
+
* - Defines middleware, lifecycle hooks, and the default HTML template path.
|
|
1747
1597
|
*/
|
|
1748
|
-
const
|
|
1749
|
-
return methodDecoratorLegacyWrapper((target, context) => {
|
|
1750
|
-
return async function (...args) {
|
|
1751
|
-
name = name ?? `${String(Object.getPrototypeOf(this).constructor.name)}.${String(context.name)}`;
|
|
1752
|
-
return await ReactRuntime.instance?.snapshot(name, () => target.apply(this, args));
|
|
1753
|
-
};
|
|
1754
|
-
});
|
|
1755
|
-
};
|
|
1598
|
+
const useReactBlueprint = internalUseReactBlueprint;
|
|
1756
1599
|
|
|
1757
1600
|
/**
|
|
1758
1601
|
* UseReact decorator.
|
|
@@ -1781,6 +1624,33 @@ const StoneClient = ({ children }) => {
|
|
|
1781
1624
|
return isClient() ? jsx(Fragment, { children: children }) : jsx(Fragment, {});
|
|
1782
1625
|
};
|
|
1783
1626
|
|
|
1627
|
+
/**
|
|
1628
|
+
* A dynamic rendering component that updates its content based on a global event.
|
|
1629
|
+
*
|
|
1630
|
+
* - Listens for `stone:inject:react-page:outlet` and updates its view when triggered.
|
|
1631
|
+
* - Uses `useState` to manage the currently displayed content.
|
|
1632
|
+
* - Automatically cleans up event listeners on unmount.
|
|
1633
|
+
*
|
|
1634
|
+
* This component enables dynamic content updates within a Stone.js application.
|
|
1635
|
+
*
|
|
1636
|
+
* @param options - The options to create the Stone Outlet.
|
|
1637
|
+
* @returns The Stone Outlet component.
|
|
1638
|
+
*/
|
|
1639
|
+
const StoneOutlet = ({ children }) => {
|
|
1640
|
+
const [currentView, setCurrentView] = useState(children);
|
|
1641
|
+
useEffect(() => {
|
|
1642
|
+
const eventName = STONE_PAGE_EVENT_OUTLET;
|
|
1643
|
+
const handleEvent = (e) => {
|
|
1644
|
+
if (isNotEmpty(e) && isNotEmpty(e.detail)) {
|
|
1645
|
+
setCurrentView(e.detail);
|
|
1646
|
+
}
|
|
1647
|
+
};
|
|
1648
|
+
window.addEventListener(eventName, handleEvent);
|
|
1649
|
+
return () => window.removeEventListener(eventName, handleEvent);
|
|
1650
|
+
}, []);
|
|
1651
|
+
return jsx("div", { "data-stone-outlet": 'true', children: currentView });
|
|
1652
|
+
};
|
|
1653
|
+
|
|
1784
1654
|
/**
|
|
1785
1655
|
* Internal link component using Stone.js router.
|
|
1786
1656
|
*/
|
|
@@ -1818,33 +1688,6 @@ const StoneLink = (props) => {
|
|
|
1818
1688
|
return props.external === true ? jsx(ExternalLink, { ...props }) : jsx(InternalLink, { ...props });
|
|
1819
1689
|
};
|
|
1820
1690
|
|
|
1821
|
-
/**
|
|
1822
|
-
* A dynamic rendering component that updates its content based on a global event.
|
|
1823
|
-
*
|
|
1824
|
-
* - Listens for `stone:inject:react-page:outlet` and updates its view when triggered.
|
|
1825
|
-
* - Uses `useState` to manage the currently displayed content.
|
|
1826
|
-
* - Automatically cleans up event listeners on unmount.
|
|
1827
|
-
*
|
|
1828
|
-
* This component enables dynamic content updates within a Stone.js application.
|
|
1829
|
-
*
|
|
1830
|
-
* @param options - The options to create the Stone Outlet.
|
|
1831
|
-
* @returns The Stone Outlet component.
|
|
1832
|
-
*/
|
|
1833
|
-
const StoneOutlet = ({ children }) => {
|
|
1834
|
-
const [currentView, setCurrentView] = useState(children);
|
|
1835
|
-
useEffect(() => {
|
|
1836
|
-
const eventName = STONE_PAGE_EVENT_OUTLET;
|
|
1837
|
-
const handleEvent = (e) => {
|
|
1838
|
-
if (isNotEmpty(e) && isNotEmpty(e.detail)) {
|
|
1839
|
-
setCurrentView(e.detail);
|
|
1840
|
-
}
|
|
1841
|
-
};
|
|
1842
|
-
window.addEventListener(eventName, handleEvent);
|
|
1843
|
-
return () => window.removeEventListener(eventName, handleEvent);
|
|
1844
|
-
}, []);
|
|
1845
|
-
return jsx("div", { "data-stone-outlet": 'true', children: currentView });
|
|
1846
|
-
};
|
|
1847
|
-
|
|
1848
1691
|
/**
|
|
1849
1692
|
* Stone Server.
|
|
1850
1693
|
* This component is used to wrap content
|
|
@@ -1856,4 +1699,4 @@ const StoneServer = ({ children }) => {
|
|
|
1856
1699
|
return isServer() ? jsx(Fragment, { children: children }) : jsx(Fragment, {});
|
|
1857
1700
|
};
|
|
1858
1701
|
|
|
1859
|
-
export { AdapterErrorPage,
|
|
1702
|
+
export { AdapterErrorPage, ErrorPage, Hook, MetaReactRuntime, MetaUseReactServiceProvider, Page, PageLayout, PageStatus, REACT_ADAPTER_ERROR_PAGE_KEY, REACT_ERROR_PAGE_KEY, REACT_PAGE_KEY, REACT_PAGE_LAYOUT_KEY, ReactRuntime, STONE_DOM_ATTR, STONE_PAGE_EVENT_OUTLET, STONE_REACT_APP_KEY, STONE_SNAPSHOT, SetReactAdapterErrorPageMiddleware, SetReactKernelErrorPageMiddleware, SetReactPageLayoutMiddleware, SetReactRouteDefinitionsMiddleware, SetSSRCompressionMiddleware, SetSSRStaticFileMiddleware, SetUseReactEventHandlerMiddleware, SetUseReactHooksMiddleware, Snapshot, StoneClient, StoneContext, StoneError, StoneLink, StoneOutlet, StonePage, StoneServer, UseReact, UseReactError, UseReactEventHandler, UseReactKernelErrorHandler, UseReactServerErrorHandler, UseReactServiceProvider, applyHeadContextToDom, applyHeadContextToHtmlString, applyMeta, buildAdapterErrorComponent, buildAppComponent, buildLayoutComponent, buildPageComponent, defineAdapterErrorPage, defineErrorPage, definePage, definePageLayout, defineStoneReactApp, executeHandler, executeHooks, getAppRootElement, getBrowserContent, getResponseSnapshot, getServerContent, htmlTemplate, hydrateReactApp, internalUseReactBlueprint, isClient, isSSR, isServer, metaServerUseReactBlueprintMiddleware, onPreparingResponse, prepareErrorPage, prepareFallbackErrorPage, preparePage, reactRedirectResponse, reactResponse, renderReactApp, renderStoneSnapshot, resolveComponent, resolveLazyComponent, setUseReactAdapterErrorHandler, snapshotResponse, useReactBlueprint };
|