UNPKG

react-on-rails

Version:

react-on-rails JavaScript for react_on_rails Ruby gem

212 lines 10.6 kB
import * as Authenticity from "../Authenticity.js"; import buildConsoleReplay, { consoleReplay } from "../buildConsoleReplay.js"; import reactHydrateOrRender from "../reactHydrateOrRender.js"; import createReactOutput from "../createReactOutput.js"; import componentRegistrationMetric from "../componentRegistrationMetric.js"; import { buildRootErrorCallbackOptions, getRootErrorHandlers, resetRootErrorHandlers, setRootErrorHandlers, } from "../rootErrorHandlers.js"; const DEFAULT_OPTIONS = { traceTurbolinks: false, turbo: false, debugMode: false, logComponentRegistration: false, }; /** * Creates the core capability containing all base ReactOnRails methods. * These are the methods that exist in every bundle variant (client, full, node, RSC). */ export function createCoreCapability(registries) { const { ComponentRegistry, StoreRegistry } = registries; return { options: {}, isRSCBundle: false, // =================================================================== // STABLE METHOD IMPLEMENTATIONS - Core package implementations // =================================================================== authenticityToken() { return Authenticity.authenticityToken(); }, authenticityHeaders(otherHeaders = {}) { return Authenticity.authenticityHeaders(otherHeaders); }, reactHydrateOrRender(domNode, reactElement, hydrate) { // The component name is unknown on this low-level path; the dom id still ties errors to a mount. const rootErrorCallbackOptions = buildRootErrorCallbackOptions({ domNodeId: domNode.id || undefined }, hydrate); return reactHydrateOrRender(domNode, reactElement, hydrate, rootErrorCallbackOptions); }, setOptions(newOptions) { const { traceTurbolinks, turbo, debugMode, logComponentRegistration, rootErrorHandlers, ...rest } = newOptions; if (typeof traceTurbolinks !== 'undefined') { this.options.traceTurbolinks = traceTurbolinks; } if (typeof turbo !== 'undefined') { this.options.turbo = turbo; } if (typeof debugMode !== 'undefined') { this.options.debugMode = debugMode; if (debugMode) { console.log('[ReactOnRails] Debug mode enabled'); } } if (typeof logComponentRegistration !== 'undefined') { this.options.logComponentRegistration = logComponentRegistration; if (logComponentRegistration) { console.log('[ReactOnRails] Component registration logging enabled'); } } if (Object.prototype.hasOwnProperty.call(newOptions, 'rootErrorHandlers')) { // Validates and merges the handlers per key (partial updates keep previously registered // callbacks); warns when the React runtime cannot support them. Store the merged result so // `option('rootErrorHandlers')` reflects the effective registration. if (typeof rootErrorHandlers === 'undefined') { resetRootErrorHandlers(); this.options.rootErrorHandlers = undefined; } else { setRootErrorHandlers(rootErrorHandlers); this.options.rootErrorHandlers = getRootErrorHandlers(); } } if (Object.keys(rest).length > 0) { throw new Error(`Invalid options passed to ReactOnRails.options: ${JSON.stringify(rest)}`); } }, option(key) { return this.options[key]; }, buildConsoleReplay() { return buildConsoleReplay(); }, getConsoleReplayScript() { return consoleReplay(); }, resetOptions() { this.options = { ...DEFAULT_OPTIONS }; resetRootErrorHandlers(); }, // =================================================================== // REGISTRY METHOD IMPLEMENTATIONS - Using provided registries // =================================================================== register(components) { if (this.options.debugMode || this.options.logComponentRegistration) { // Use performance.now() if available, otherwise fallback to Date.now() const perf = typeof performance !== 'undefined' ? performance : { now: () => Date.now() }; const startTime = perf.now(); const componentNames = Object.keys(components); console.log(`[ReactOnRails] Registering ${componentNames.length} component(s): ${componentNames.join(', ')}`); ComponentRegistry.register(components); const endTime = perf.now(); console.log(`[ReactOnRails] Component registration completed in ${(endTime - startTime).toFixed(2)}ms`); // Log individual component details if in full debug mode if (this.options.debugMode) { componentNames.forEach((name) => { const component = components[name]; const registrationMetric = componentRegistrationMetric(component); console.log(`[ReactOnRails] ✅ Registered: ${name} (${registrationMetric.value} ${registrationMetric.label})`); }); } } else { ComponentRegistry.register(components); } }, registerStore(stores) { this.registerStoreGenerators(stores); }, registerStoreGenerators(storeGenerators) { if (!storeGenerators) { throw new Error('Called ReactOnRails.registerStoreGenerators with a null or undefined, rather than ' + 'an Object with keys being the store names and the values are the store generators.'); } StoreRegistry.register(storeGenerators); }, getStore(name, throwIfMissing = true) { return StoreRegistry.getStore(name, throwIfMissing); }, getStoreGenerator(name) { return StoreRegistry.getStoreGenerator(name); }, setStore(name, store) { StoreRegistry.setStore(name, store); }, clearHydratedStores() { StoreRegistry.clearHydratedStores(); }, clearStoreGenerators() { StoreRegistry.clearStoreGenerators(); }, getComponent(name) { return ComponentRegistry.get(name); }, registeredComponents() { return ComponentRegistry.components(); }, storeGenerators() { return StoreRegistry.storeGenerators(); }, stores() { return StoreRegistry.stores(); }, render(name, props, domNodeId, hydrate) { const componentObj = ComponentRegistry.get(name); const reactElement = createReactOutput({ componentObj, props, domNodeId }); return reactHydrateOrRender(document.getElementById(domNodeId), reactElement, hydrate, buildRootErrorCallbackOptions({ componentName: name || undefined, domNodeId: domNodeId || undefined }, hydrate)); }, // =================================================================== // SSR STUBS — overridden by createSSRCapability() in full/node bundles // =================================================================== // eslint-disable-next-line @typescript-eslint/no-explicit-any serverRenderReactComponent(...args) { void args; throw new Error('serverRenderReactComponent is not available in the client bundle. Import "react-on-rails" server-side.'); }, // eslint-disable-next-line @typescript-eslint/no-explicit-any handleError(...args) { void args; throw new Error('handleError is not available in the client bundle. Import "react-on-rails" server-side.'); }, // eslint-disable-next-line @typescript-eslint/no-explicit-any prepareRenderResult(...args) { void args; throw new Error('prepareRenderResult is not available in the client bundle. Import "react-on-rails" server-side.'); }, // =================================================================== // PRO STUBS — overridden by Pro capabilities in react-on-rails-pro // =================================================================== getOrWaitForComponent() { throw new Error('getOrWaitForComponent requires the react-on-rails-pro package.'); }, getOrWaitForStore() { throw new Error('getOrWaitForStore requires the react-on-rails-pro package.'); }, getOrWaitForStoreGenerator() { throw new Error('getOrWaitForStoreGenerator requires the react-on-rails-pro package.'); }, reactOnRailsStoreLoaded() { throw new Error('reactOnRailsStoreLoaded requires the react-on-rails-pro package.'); }, isServerStreamingSupported() { throw new Error('isServerStreamingSupported requires the react-on-rails-pro package.'); }, // eslint-disable-next-line @typescript-eslint/no-explicit-any streamServerRenderedReactComponent(...args) { void args; throw new Error('streamServerRenderedReactComponent requires the react-on-rails-pro package.'); }, // eslint-disable-next-line @typescript-eslint/no-explicit-any serverRenderRSCReactComponent(...args) { void args; throw new Error('serverRenderRSCReactComponent requires the react-on-rails-pro package.'); }, // eslint-disable-next-line @typescript-eslint/no-explicit-any addAsyncPropsCapabilityToComponentProps(...args) { void args; throw new Error('addAsyncPropsCapabilityToComponentProps requires the react-on-rails-pro package.'); }, // eslint-disable-next-line @typescript-eslint/no-explicit-any getOrCreateAsyncPropsManager(...args) { void args; throw new Error('getOrCreateAsyncPropsManager requires the react-on-rails-pro package.'); }, }; } //# sourceMappingURL=core.js.map