@cdmbase/wiki-browser 12.0.18-alpha.10
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/LICENSE +21 -0
- package/lib/components/Logo.d.ts +4 -0
- package/lib/components/Logo.d.ts.map +1 -0
- package/lib/components/Logo.js +16 -0
- package/lib/components/Logo.js.map +1 -0
- package/lib/components/help/SidebarSearch.d.ts +8 -0
- package/lib/components/help/SidebarSearch.d.ts.map +1 -0
- package/lib/components/help/SidebarSearch.js +111 -0
- package/lib/components/help/SidebarSearch.js.map +1 -0
- package/lib/components/help/index.d.ts +2 -0
- package/lib/components/help/index.d.ts.map +1 -0
- package/lib/components/landing/FeatureCard.d.ts +13 -0
- package/lib/components/landing/FeatureCard.d.ts.map +1 -0
- package/lib/components/landing/FeatureCard.js +85 -0
- package/lib/components/landing/FeatureCard.js.map +1 -0
- package/lib/components/landing/QuickLinkCard.d.ts +8 -0
- package/lib/components/landing/QuickLinkCard.d.ts.map +1 -0
- package/lib/components/landing/QuickLinkCard.js +26 -0
- package/lib/components/landing/QuickLinkCard.js.map +1 -0
- package/lib/components/landing/SearchInput.d.ts +10 -0
- package/lib/components/landing/SearchInput.d.ts.map +1 -0
- package/lib/components/landing/SearchInput.js +223 -0
- package/lib/components/landing/SearchInput.js.map +1 -0
- package/lib/components/landing/index.d.ts +4 -0
- package/lib/components/landing/index.d.ts.map +1 -0
- package/lib/components/welcome.d.ts +3 -0
- package/lib/components/welcome.d.ts.map +1 -0
- package/lib/compute.d.ts +4 -0
- package/lib/compute.d.ts.map +1 -0
- package/lib/compute.js +96 -0
- package/lib/compute.js.map +1 -0
- package/lib/config/env-config.d.ts +4 -0
- package/lib/config/env-config.d.ts.map +1 -0
- package/lib/config/env-config.js +7 -0
- package/lib/config/env-config.js.map +1 -0
- package/lib/docs.config.d.ts +48 -0
- package/lib/docs.config.d.ts.map +1 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -0
- package/lib/loaders/search.d.ts +1 -0
- package/lib/loaders/search.d.ts.map +1 -0
- package/lib/module.d.ts +4 -0
- package/lib/module.d.ts.map +1 -0
- package/lib/module.js +11 -0
- package/lib/module.js.map +1 -0
- package/lib/pages/ArticlePage/ArticlePage.d.ts +4 -0
- package/lib/pages/ArticlePage/ArticlePage.d.ts.map +1 -0
- package/lib/pages/ArticlePage/ArticlePage.js +222 -0
- package/lib/pages/ArticlePage/ArticlePage.js.map +1 -0
- package/lib/pages/ArticlePage/index.d.ts +3 -0
- package/lib/pages/ArticlePage/index.d.ts.map +1 -0
- package/lib/pages/ArticlePage/index.js +3 -0
- package/lib/pages/ArticlePage/index.js.map +1 -0
- package/lib/pages/CategoryCollection/CategoryCollection.d.ts +4 -0
- package/lib/pages/CategoryCollection/CategoryCollection.d.ts.map +1 -0
- package/lib/pages/CategoryCollection/CategoryCollection.js +103 -0
- package/lib/pages/CategoryCollection/CategoryCollection.js.map +1 -0
- package/lib/pages/CategoryCollection/index.d.ts +3 -0
- package/lib/pages/CategoryCollection/index.d.ts.map +1 -0
- package/lib/pages/CategoryCollection/index.js +3 -0
- package/lib/pages/CategoryCollection/index.js.map +1 -0
- package/lib/pages/Help/HelpIndex.d.ts +4 -0
- package/lib/pages/Help/HelpIndex.d.ts.map +1 -0
- package/lib/pages/Help/HelpIndex.js +44 -0
- package/lib/pages/Help/HelpIndex.js.map +1 -0
- package/lib/pages/Help/index.d.ts +4 -0
- package/lib/pages/Help/index.d.ts.map +1 -0
- package/lib/pages/Help/index.js +226 -0
- package/lib/pages/Help/index.js.map +1 -0
- package/lib/pages/Landing/index.d.ts +3 -0
- package/lib/pages/Landing/index.d.ts.map +1 -0
- package/lib/pages/Landing/index.js +281 -0
- package/lib/pages/Landing/index.js.map +1 -0
- package/lib/routes.json +2533 -0
- package/lib/seo.d.ts +22 -0
- package/lib/seo.d.ts.map +1 -0
- package/lib/slot-fill/FooterFill.d.ts +3 -0
- package/lib/slot-fill/FooterFill.d.ts.map +1 -0
- package/lib/slot-fill/FooterFill.js +18 -0
- package/lib/slot-fill/FooterFill.js.map +1 -0
- package/lib/slot-fill/LogoFill.d.ts +5 -0
- package/lib/slot-fill/LogoFill.d.ts.map +1 -0
- package/lib/slot-fill/LogoFill.js +74 -0
- package/lib/slot-fill/LogoFill.js.map +1 -0
- package/lib/slot-fill/consts.d.ts +5 -0
- package/lib/slot-fill/consts.d.ts.map +1 -0
- package/lib/slot-fill/consts.js +1 -0
- package/lib/slot-fill/consts.js.map +1 -0
- package/lib/slot-fill/index.d.ts +4 -0
- package/lib/slot-fill/index.d.ts.map +1 -0
- package/lib/templates/assets/images/add-link-frontend.png +0 -0
- package/lib/templates/assets/images/add-package-backend.png +0 -0
- package/lib/templates/assets/images/add-to-backend-module.png +0 -0
- package/lib/templates/assets/images/add-upload-client-frontend.png +0 -0
- package/lib/templates/assets/images/additional-parameters.png +0 -0
- package/lib/templates/assets/images/aeh-implementation.png +0 -0
- package/lib/templates/assets/images/aeh-usage.png +0 -0
- package/lib/templates/assets/images/apollo-client/recommendation_cache_mgmt.png +0 -0
- package/lib/templates/assets/images/app-deploy-new-version/jenkins1.PNG +0 -0
- package/lib/templates/assets/images/app-deploy-new-version/jenkins2.PNG +0 -0
- package/lib/templates/assets/images/auth-wrapper-code.png +0 -0
- package/lib/templates/assets/images/cdebase.png +0 -0
- package/lib/templates/assets/images/cdm-locales-directory.png +0 -0
- package/lib/templates/assets/images/client-settings.png +0 -0
- package/lib/templates/assets/images/codegen_file_update.png +0 -0
- package/lib/templates/assets/images/configuration.png +0 -0
- package/lib/templates/assets/images/copy-plugin.png +0 -0
- package/lib/templates/assets/images/docusaurus.png +0 -0
- package/lib/templates/assets/images/error-link.png +0 -0
- package/lib/templates/assets/images/error-sample.png +0 -0
- package/lib/templates/assets/images/extension copy.png +0 -0
- package/lib/templates/assets/images/extension.png +0 -0
- package/lib/templates/assets/images/graphql/graphql-folder-backend.png +0 -0
- package/lib/templates/assets/images/graphql/graphql-folder-with-gql.png +0 -0
- package/lib/templates/assets/images/i18n-config.png +0 -0
- package/lib/templates/assets/images/image.png +0 -0
- package/lib/templates/assets/images/logo.svg +10 -0
- package/lib/templates/assets/images/logo1.svg +1 -0
- package/lib/templates/assets/images/modify-upload-false-server.png +0 -0
- package/lib/templates/assets/images/navigation-auth-enabled.png +0 -0
- package/lib/templates/assets/images/org-dashboard-navigation.png +0 -0
- package/lib/templates/assets/images/org-navigation.png +0 -0
- package/lib/templates/assets/images/preferences_graphql_type.png +0 -0
- package/lib/templates/assets/images/provider.png +0 -0
- package/lib/templates/assets/images/route-config.png +0 -0
- package/lib/templates/assets/images/service-accounts.png +0 -0
- package/lib/templates/assets/images/source-code/source-code-environments.png +0 -0
- package/lib/templates/assets/images/source-code/source-code-organization.png +0 -0
- package/lib/templates/assets/images/spin-clone-develop-deployment/jenkins-changes.png +0 -0
- package/lib/templates/assets/images/spin-clone-develop-deployment/lerna-changes.png +0 -0
- package/lib/templates/assets/images/spin-clone-develop-deployment/root-package-json-changes.png +0 -0
- package/lib/templates/assets/images/spin-clone-develop-deployment/values-dev-changes.png +0 -0
- package/lib/templates/assets/images/sso-mappers.png +0 -0
- package/lib/templates/assets/images/sso-picture-mapper.png +0 -0
- package/lib/templates/assets/images/sso-settings.png +0 -0
- package/lib/templates/assets/images/timesheet_apollo_cache.png +0 -0
- package/lib/templates/assets/images/timesheet_query.png +0 -0
- package/lib/templates/assets/images/tutorial/docsVersionDropdown.png +0 -0
- package/lib/templates/assets/images/tutorial/localeDropdown.png +0 -0
- package/lib/templates/assets/images/unauthenticated.png +0 -0
- package/lib/templates/assets/images/undraw_docusaurus_mountain.svg +170 -0
- package/lib/templates/assets/images/undraw_docusaurus_react.svg +169 -0
- package/lib/templates/assets/images/undraw_docusaurus_tree.svg +1 -0
- package/lib/templates/assets/images/vite-plugin-config.png +0 -0
- package/lib/templates/content/docs/Generators/Project/generate-fullproject.md +12 -0
- package/lib/templates/content/docs/LLM/Logger.llm.md +194 -0
- package/lib/templates/content/docs/LLM/backend-proxies-services-llm.md +2687 -0
- package/lib/templates/content/docs/LLM/backend-service-llm.md +3384 -0
- package/lib/templates/content/docs/LLM/db_migration_llm.md +954 -0
- package/lib/templates/content/docs/LLM/frontend/REMIX-15.3-upgrade-llm.md +1245 -0
- package/lib/templates/content/docs/LLM/inngest/INNGEST_FUNCTION_DEVELOPMENT_GUIDE_LLM.md +1241 -0
- package/lib/templates/content/docs/LLM/inngest/INNGEST_NAMESPACE_LLM.md +384 -0
- package/lib/templates/content/docs/LLM/llm_workflow_namespace.md +384 -0
- package/lib/templates/content/docs/LLM/organization-components-form-llm.md +1395 -0
- package/lib/templates/content/docs/LLM/page-component-llm.md +173 -0
- package/lib/templates/content/docs/LLM/preferences-settings-llm.md +2781 -0
- package/lib/templates/content/docs/LLM/tailwind-css-llm.md +502 -0
- package/lib/templates/content/docs/UI/SchemaBasedUI.md +334 -0
- package/lib/templates/content/docs/UI/SlotFillComponent.md +334 -0
- package/lib/templates/content/docs/adminide-modules/account/auth0-login.md +31 -0
- package/lib/templates/content/docs/adminide-modules/account/index.md +14 -0
- package/lib/templates/content/docs/adminide-modules/account/keycloak-remix-setup.md +86 -0
- package/lib/templates/content/docs/adminide-modules/account/remix-auth-setup.md +79 -0
- package/lib/templates/content/docs/adminide-modules/account/various-auth-qatest.md +157 -0
- package/lib/templates/content/docs/adminide-modules/api-builders/graphql.md +906 -0
- package/lib/templates/content/docs/adminide-modules/billing/payments/index.md +14 -0
- package/lib/templates/content/docs/adminide-modules/billing/payments/stripe/index.md +14 -0
- package/lib/templates/content/docs/adminide-modules/billing/payments/stripe/settingup-stripe-locally.md +25 -0
- package/lib/templates/content/docs/adminide-modules/billing/tier-config.md +293 -0
- package/lib/templates/content/docs/adminide-modules/connectors/Connector.md +207 -0
- package/lib/templates/content/docs/adminide-modules/file-upload/index.md +16 -0
- package/lib/templates/content/docs/adminide-modules/file-upload/setup.md +435 -0
- package/lib/templates/content/docs/adminide-modules/file-upload/upload-file-using-signed-url.md +161 -0
- package/lib/templates/content/docs/adminide-modules/preferences/AddAdditionalPermissions.md +151 -0
- package/lib/templates/content/docs/adminide-modules/preferences/Configuration.md +241 -0
- package/lib/templates/content/docs/adminide-modules/preferences/Policy-Configuration.md +61 -0
- package/lib/templates/content/docs/adminide-modules/preferences/UI-components/ResourceSettingsLoader.md +319 -0
- package/lib/templates/content/docs/adminide-modules/preferences/contribute_scope_target.md +280 -0
- package/lib/templates/content/docs/adminide-modules/preferences/generate-urii.md +94 -0
- package/lib/templates/content/docs/adminide-modules/preferences/index.md +28 -0
- package/lib/templates/content/docs/adminide-modules/preferences/machine-configuration.md +157 -0
- package/lib/templates/content/docs/adminide-modules/preferences/pageSettings/generateCdecodeUri.md +1289 -0
- package/lib/templates/content/docs/adminide-modules/preferences/pageSettings/migratingFromUseSettings.md +215 -0
- package/lib/templates/content/docs/adminide-modules/preferences/permissions/Roles-Permissions.md +72 -0
- package/lib/templates/content/docs/adminide-modules/preferences/permissions/settingUserPermissions.md +139 -0
- package/lib/templates/content/docs/adminide-modules/preferences/preference-dependency.md +138 -0
- package/lib/templates/content/docs/adminide-modules/preferences/route-based-configuration.md +41 -0
- package/lib/templates/content/docs/adminide-modules/preferences/schema-configuration.md +71 -0
- package/lib/templates/content/docs/adminide-modules/preferences/supported.md +24 -0
- package/lib/templates/content/docs/adminide-modules/preferences/useSettingsLoader.md +248 -0
- package/lib/templates/content/docs/adminide-modules/project-tools/auth-providers.md +1317 -0
- package/lib/templates/content/docs/adminide-modules/project-tools/keycloak-guide.md +543 -0
- package/lib/templates/content/docs/adminide-modules/project-tools/tenant-management/tenant-based-authentication.md +846 -0
- package/lib/templates/content/docs/adminide-modules/project-tools/tenant-management/tenant-management.md +708 -0
- package/lib/templates/content/docs/adminide-modules/project-tools/tenant-management/tenants.md +1117 -0
- package/lib/templates/content/docs/chrome-extension/index.md +14 -0
- package/lib/templates/content/docs/chrome-extension/setup.md +30 -0
- package/lib/templates/content/docs/contributing/adding-package.md +23 -0
- package/lib/templates/content/docs/contributing/adding_new_modules.md +99 -0
- package/lib/templates/content/docs/contributing/architecture-updates.md +19 -0
- package/lib/templates/content/docs/contributing/avoid-using-promises-ui.md +116 -0
- package/lib/templates/content/docs/contributing/coding-guidelines.md +111 -0
- package/lib/templates/content/docs/contributing/do-and-dont.md +42 -0
- package/lib/templates/content/docs/contributing/faq.md +22 -0
- package/lib/templates/content/docs/contributing/folder-setup/browser.md +12 -0
- package/lib/templates/content/docs/contributing/folder-setup/config.md +12 -0
- package/lib/templates/content/docs/contributing/folder-setup/containers-server.md +12 -0
- package/lib/templates/content/docs/contributing/folder-setup/core.md +12 -0
- package/lib/templates/content/docs/contributing/folder-setup/graphql.md +12 -0
- package/lib/templates/content/docs/contributing/folder-setup/index.md +30 -0
- package/lib/templates/content/docs/contributing/folder-setup/module.md +12 -0
- package/lib/templates/content/docs/contributing/folder-setup/server.md +12 -0
- package/lib/templates/content/docs/contributing/folder-setup/services.md +12 -0
- package/lib/templates/content/docs/contributing/folder-setup/store.md +12 -0
- package/lib/templates/content/docs/contributing/frontend-coding.md +30 -0
- package/lib/templates/content/docs/contributing/git-subtree-sharing.md +73 -0
- package/lib/templates/content/docs/contributing/graphql-subscriptions.md +69 -0
- package/lib/templates/content/docs/contributing/how-to-contribute.md +30 -0
- package/lib/templates/content/docs/contributing/how_to_check_pure_esm.md +29 -0
- package/lib/templates/content/docs/contributing/index.md +60 -0
- package/lib/templates/content/docs/contributing/installation-issues.md +23 -0
- package/lib/templates/content/docs/contributing/keyboard-shortcut.md +131 -0
- package/lib/templates/content/docs/contributing/language/locale-support.md +12 -0
- package/lib/templates/content/docs/contributing/lerna-build-tools.md +516 -0
- package/lib/templates/content/docs/contributing/lerna-yarn-workspaces.md +95 -0
- package/lib/templates/content/docs/contributing/lint-and-formatter.md +20 -0
- package/lib/templates/content/docs/contributing/mobile-setup.md +16 -0
- package/lib/templates/content/docs/contributing/project-setup.md +233 -0
- package/lib/templates/content/docs/contributing/react/index.md +14 -0
- package/lib/templates/content/docs/contributing/react/lazy-component.md +70 -0
- package/lib/templates/content/docs/contributing/run-various-options.md +124 -0
- package/lib/templates/content/docs/contributing/schema-first-graphql-types.md +37 -0
- package/lib/templates/content/docs/contributing/source-code-organization.md +57 -0
- package/lib/templates/content/docs/contributing/staging-docker.md +88 -0
- package/lib/templates/content/docs/contributing/third-party/apollo-client-v3-tutorials.md +28 -0
- package/lib/templates/content/docs/contributing/third-party/index.md +18 -0
- package/lib/templates/content/docs/contributing/typescript-contribution.md +16 -0
- package/lib/templates/content/docs/devops/app-deploy-new-version.md +30 -0
- package/lib/templates/content/docs/devops/index.md +14 -0
- package/lib/templates/content/docs/devops/mobile-jenkins-build.md +40 -0
- package/lib/templates/content/docs/devops/versioning-the-project.md +128 -0
- package/lib/templates/content/docs/error-handler/application-error-handler.md +40 -0
- package/lib/templates/content/docs/error-handler/error-handling.md +26 -0
- package/lib/templates/content/docs/error-handler/index.md +16 -0
- package/lib/templates/content/docs/error-handler/logging-errors.md +14 -0
- package/lib/templates/content/docs/feature-api/copy-operation.md +427 -0
- package/lib/templates/content/docs/feature-api/feature-browser/assets.md +46 -0
- package/lib/templates/content/docs/feature-api/feature-browser/auth-permissions.md +12 -0
- package/lib/templates/content/docs/feature-api/feature-browser/feature.md +131 -0
- package/lib/templates/content/docs/feature-api/feature-browser/index.md +22 -0
- package/lib/templates/content/docs/feature-api/feature-browser/routes-menu.md +110 -0
- package/lib/templates/content/docs/feature-api/feature-browser/routing-convention.md +124 -0
- package/lib/templates/content/docs/feature-api/feature-browser/routing.md +338 -0
- package/lib/templates/content/docs/feature-api/feature-mobile/auth-permissions.md +20 -0
- package/lib/templates/content/docs/feature-api/feature-mobile/feature.md +130 -0
- package/lib/templates/content/docs/feature-api/feature-mobile/index.md +18 -0
- package/lib/templates/content/docs/feature-api/feature-mobile/navigation.md +187 -0
- package/lib/templates/content/docs/feature-api/feature-server/Scheduling.md +44 -0
- package/lib/templates/content/docs/feature-api/feature-server/dataloader.md +320 -0
- package/lib/templates/content/docs/feature-api/feature-server/dependency-injection.md +81 -0
- package/lib/templates/content/docs/feature-api/feature-server/feature.md +65 -0
- package/lib/templates/content/docs/feature-api/feature-server/generic-dataloader.md +135 -0
- package/lib/templates/content/docs/feature-api/feature-server/index.md +40 -0
- package/lib/templates/content/docs/feature-api/feature-server/migration.md +127 -0
- package/lib/templates/content/docs/feature-api/feature-server/mongo-model.md +72 -0
- package/lib/templates/content/docs/feature-api/feature-server/permissions.md +12 -0
- package/lib/templates/content/docs/feature-api/feature-server/policies.md +57 -0
- package/lib/templates/content/docs/feature-api/feature-server/preferences.md +57 -0
- package/lib/templates/content/docs/feature-api/feature-server/repositories.md +114 -0
- package/lib/templates/content/docs/feature-api/feature-server/resolvers.md +126 -0
- package/lib/templates/content/docs/feature-api/feature-server/rules.md +132 -0
- package/lib/templates/content/docs/feature-api/feature-server/schema.md +12 -0
- package/lib/templates/content/docs/feature-api/feature-server/services.md +102 -0
- package/lib/templates/content/docs/feature-api/feature-server/setup-resource-crud.md +359 -0
- package/lib/templates/content/docs/feature-api/index.md +18 -0
- package/lib/templates/content/docs/graphql/apolloClient-mutation.md +94 -0
- package/lib/templates/content/docs/graphql/index.md +14 -0
- package/lib/templates/content/docs/graphql/scalars.md +15 -0
- package/lib/templates/content/docs/help/index.md +14 -0
- package/lib/templates/content/docs/help/intro.md +16 -0
- package/lib/templates/content/docs/intl/ant-design-menu-translation.md +74 -0
- package/lib/templates/content/docs/intl/intl-namespace.md +129 -0
- package/lib/templates/content/docs/intl/vite-plugin-intl.md +87 -0
- package/lib/templates/content/docs/intl/webpack-plugin-intl.md +12 -0
- package/lib/templates/content/docs/intro.md +18 -0
- package/lib/templates/content/docs/knowledge/basic-fullstack.md +238 -0
- package/lib/templates/content/docs/mailing/index.md +14 -0
- package/lib/templates/content/docs/mailing/mailing-template.md +148 -0
- package/lib/templates/content/docs/mobile/App-navigation-generator.md +410 -0
- package/lib/templates/content/docs/mobile/MobileTestCases.md +264 -0
- package/lib/templates/content/docs/mobile/eas-profile-build.md +107 -0
- package/lib/templates/content/docs/mobile/expo-push-notification-setup.md +216 -0
- package/lib/templates/content/docs/mobile/index.md +14 -0
- package/lib/templates/content/docs/mobile/routes.md +83 -0
- package/lib/templates/content/docs/organization/adding-account-context.md +116 -0
- package/lib/templates/content/docs/organization/adding-org-mobile-navigation.md +22 -0
- package/lib/templates/content/docs/organization/adding-org-web-navigation.md +12 -0
- package/lib/templates/content/docs/organization/index.md +20 -0
- package/lib/templates/content/docs/organization/initialization.md +20 -0
- package/lib/templates/content/docs/organization/organization-resource-vs-resource.md +112 -0
- package/lib/templates/content/docs/remix/configuration/component-structure-best-practices.md +152 -0
- package/lib/templates/content/docs/remix/configuration/configurations.md +218 -0
- package/lib/templates/content/docs/remix/configuration/css-import-and-stylesheets.md +142 -0
- package/lib/templates/content/docs/remix/configuration/dont-subcomponent-network.md +166 -0
- package/lib/templates/content/docs/remix/configuration/generated-data-loaders.md +122 -0
- package/lib/templates/content/docs/remix/configuration/generated-resource-loaders.md +257 -0
- package/lib/templates/content/docs/remix/configuration/query-params-generator.md +216 -0
- package/lib/templates/content/docs/remix/configuration/routes-extra-icons.md +103 -0
- package/lib/templates/content/docs/remix/configuration/routes-json-advanced.md +86 -0
- package/lib/templates/content/docs/remix/configuration/routes-json-auth.md +113 -0
- package/lib/templates/content/docs/remix/configuration/routes-json-best-practices.md +55 -0
- package/lib/templates/content/docs/remix/configuration/routes-json-fields.md +79 -0
- package/lib/templates/content/docs/remix/configuration/routes-json-graphql.md +79 -0
- package/lib/templates/content/docs/remix/configuration/routes-json-index.md +112 -0
- package/lib/templates/content/docs/remix/configuration/routes-json-loaders.md +165 -0
- package/lib/templates/content/docs/remix/configuration/routes-json-middleware.md +196 -0
- package/lib/templates/content/docs/remix/configuration/routes-json-overview.md +53 -0
- package/lib/templates/content/docs/remix/data-loaders.md +43 -0
- package/lib/templates/content/docs/remix/devtools/remix-devtools.md +58 -0
- package/lib/templates/content/docs/remix/examples/changes-using-servercode.md +79 -0
- package/lib/templates/content/docs/remix/extra-icons.md +62 -0
- package/lib/templates/content/docs/remix/extra-links.md +65 -0
- package/lib/templates/content/docs/remix/generated-data-loaders.md +114 -0
- package/lib/templates/content/docs/remix/queryParamsGenerator.md +89 -0
- package/lib/templates/content/docs/remix/resources.md +16 -0
- package/lib/templates/content/docs/remix/styles.md +132 -0
- package/lib/templates/content/docs/remix/wiki.md +12 -0
- package/lib/templates/content/docs/security/auth-wrapper/auth-wrapper.md +24 -0
- package/lib/templates/content/docs/security/index.md +18 -0
- package/lib/templates/content/docs/security/secure-button-mobilenative.md +88 -0
- package/lib/templates/content/docs/security/secure-button-web.md +89 -0
- package/lib/templates/content/docs/server-side/account-customization.md +82 -0
- package/lib/templates/content/docs/server-side/apollo/caching.md +164 -0
- package/lib/templates/content/docs/server-side/backend-architecture/FINAL-DECISION.md +209 -0
- package/lib/templates/content/docs/server-side/backend-architecture/TRUE-FINAL-ARCHITECTURE.md +603 -0
- package/lib/templates/content/docs/server-side/backend-architecture/index1.md +0 -0
- package/lib/templates/content/docs/server-side/backend-coding.md +839 -0
- package/lib/templates/content/docs/server-side/e2b/manageing-template.md +197 -0
- package/lib/templates/content/docs/server-side/index.md +14 -0
- package/lib/templates/content/docs/server-side/inngest-functions-module.md +309 -0
- package/lib/templates/content/docs/server-side/listen-stripe-events.md +43 -0
- package/lib/templates/content/docs/server-side/slug-service.md +323 -0
- package/lib/templates/content/docs/tests/index.md +18 -0
- package/lib/templates/content/docs/tests/jest-test-debug-vscode.md +40 -0
- package/lib/templates/content/docs/tests/known-errors.md +116 -0
- package/lib/templates/content/docs/tests/service-test-template.md +118 -0
- package/lib/templates/content/docs/tests/test-setup.md +93 -0
- package/lib/templates/content/docs/xstate.md +23 -0
- package/lib/types.d.ts +37 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/utils/docsNavigation.d.ts +9 -0
- package/lib/utils/docsNavigation.d.ts.map +1 -0
- package/lib/utils/docsNavigation.js +37 -0
- package/lib/utils/docsNavigation.js.map +1 -0
- package/lib/utils/helpCenterUtils.d.ts +26 -0
- package/lib/utils/helpCenterUtils.d.ts.map +1 -0
- package/lib/utils/index.d.ts +3 -0
- package/lib/utils/index.d.ts.map +1 -0
- package/lib/utils/index.js +3 -0
- package/lib/utils/index.js.map +1 -0
- package/lib/utils/markdownLoader.d.ts +36 -0
- package/lib/utils/markdownLoader.d.ts.map +1 -0
- package/lib/utils/markdownLoader.js +2242 -0
- package/lib/utils/markdownLoader.js.map +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1,1245 @@
|
|
|
1
|
+
# Remix 2.15.3 Upgrade Summary - Frontend Server
|
|
2
|
+
|
|
3
|
+
## Upgrade Completed: November 2025
|
|
4
|
+
|
|
5
|
+
This document summarizes the changes made to upgrade the `yantra-stack/servers/frontend-server` to **Remix 2.15.3** with v3 future flags.
|
|
6
|
+
|
|
7
|
+
## Dependency Version Updates
|
|
8
|
+
|
|
9
|
+
As part of this upgrade, the following major dependencies were also updated:
|
|
10
|
+
|
|
11
|
+
### @common-stack packages (updated to 8.2.2-alpha.0)
|
|
12
|
+
|
|
13
|
+
| Package | Old Version | New Version |
|
|
14
|
+
| ------------------------------------ | -------------- | ----------------- |
|
|
15
|
+
| `@common-stack/env-list-loader` | 7.2.1-alpha.5 | **8.2.2-alpha.0** |
|
|
16
|
+
| `@common-stack/generate-plugin` | 7.2.1-alpha.12 | **8.2.2-alpha.0** |
|
|
17
|
+
| `@common-stack/rollup-vite-utils` | 7.2.1-alpha.11 | **8.2.2-alpha.0** |
|
|
18
|
+
| `@common-stack/cache-api-server` | 7.2.1-alpha.11 | **8.2.2-alpha.0** |
|
|
19
|
+
| `@common-stack/client-core` | 7.2.1-alpha.11 | **8.2.2-alpha.0** |
|
|
20
|
+
| `@common-stack/client-react` | 7.2.1-alpha.11 | **8.2.2-alpha.0** |
|
|
21
|
+
| `@common-stack/components-pro` | 7.2.1-alpha.11 | **8.2.2-alpha.0** |
|
|
22
|
+
| `@common-stack/core` | 7.2.1-alpha.11 | **8.2.2-alpha.0** |
|
|
23
|
+
| `@common-stack/frontend-stack-react` | 7.2.1-alpha.12 | **8.2.2-alpha.0** |
|
|
24
|
+
| `@common-stack/remix-router-redux` | 7.2.1-alpha.5 | **8.2.2-alpha.0** |
|
|
25
|
+
| `@common-stack/server-core` | 7.2.1-alpha.11 | **8.2.2-alpha.0** |
|
|
26
|
+
| `@common-stack/server-stack` | 7.2.1-alpha.12 | **8.2.2-alpha.0** |
|
|
27
|
+
| `@common-stack/store-mongo` | 7.2.1-alpha.11 | **8.2.2-alpha.0** |
|
|
28
|
+
|
|
29
|
+
### @adminide-stack packages (updated to 13.0.4-alpha.x)
|
|
30
|
+
|
|
31
|
+
| Package | Old Version | New Version |
|
|
32
|
+
| -------------------------------------------- | ---------------- | ------------------ |
|
|
33
|
+
| `@adminide-stack/account-api-server` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
|
|
34
|
+
| `@adminide-stack/extension-module-server` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
|
|
35
|
+
| `@adminide-stack/marketplace-module-server` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
|
|
36
|
+
| `@adminide-stack/platform-server` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
|
|
37
|
+
| `@adminide-stack/project-mgmt-server` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
|
|
38
|
+
| `@adminide-stack/user-auth0-server` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
|
|
39
|
+
| `@adminide-stack/account-api-browser` | 12.0.4-alpha.351 | **13.0.4-alpha.1** |
|
|
40
|
+
| `@adminide-stack/account-api-client` | 12.0.4-alpha.349 | **13.0.4-alpha.1** |
|
|
41
|
+
| `@adminide-stack/extension-module-browser` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
|
|
42
|
+
| `@adminide-stack/marketplace-module-browser` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
|
|
43
|
+
| `@adminide-stack/mongo-admin-browser` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
|
|
44
|
+
| `@adminide-stack/platform-browser` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
|
|
45
|
+
| `@adminide-stack/platform-client` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
|
|
46
|
+
| `@adminide-stack/project-mgmt-browser` | 12.0.4-alpha.351 | **13.0.4-alpha.1** |
|
|
47
|
+
| `@adminide-stack/react-shared-components` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
|
|
48
|
+
| `@adminide-stack/user-auth0-browser` | 12.0.4-alpha.349 | **13.0.4-alpha.1** |
|
|
49
|
+
|
|
50
|
+
### @admin-layout packages (updated to 12.2.1-alpha.x)
|
|
51
|
+
|
|
52
|
+
| Package | Old Version | New Version |
|
|
53
|
+
| ----------------------------------- | ---------------- | ------------------ |
|
|
54
|
+
| `@admin-layout/assets` | 12.0.16-alpha.36 | **12.2.1-alpha.0** |
|
|
55
|
+
| `@admin-layout/tailwind-design-pro` | 12.0.16-alpha.68 | **12.2.1-alpha.5** |
|
|
56
|
+
|
|
57
|
+
## Changes Applied
|
|
58
|
+
|
|
59
|
+
### 1. **Entry Client** (`src/entry.client.tsx`)
|
|
60
|
+
|
|
61
|
+
- ✅ Removed `StrictMode` wrapper from hydration
|
|
62
|
+
- ✅ Removed `CacheProvider` from `@emotion/react`
|
|
63
|
+
- ✅ Removed `createEmotionCache` import and usage
|
|
64
|
+
- ✅ Simplified hydration without emotion wrapper
|
|
65
|
+
- **Reason**: Remix 2.15.3 recommends removing StrictMode in production to avoid double-rendering issues. Emotion is no longer needed for SSR styling.
|
|
66
|
+
|
|
67
|
+
### 2. **Entry Server** (`src/entry.server.tsx`)
|
|
68
|
+
|
|
69
|
+
- ✅ Removed deprecated `abortDelay` prop from `RemixServer`
|
|
70
|
+
- ✅ Changed `ABORT_DELAY` constant to exported `streamTimeout`
|
|
71
|
+
- ✅ Removed `CacheProvider` from `@emotion/react`
|
|
72
|
+
- ✅ Removed `renderStylesToNodeStream` from `@emotion/server`
|
|
73
|
+
- ✅ Removed `createEmotionCache` import and usage
|
|
74
|
+
- ✅ Updated timeout to `streamTimeout + 1000`
|
|
75
|
+
- ✅ Simplified rendering pipeline without emotion styles
|
|
76
|
+
- **Reason**: `abortDelay` is deprecated in Remix 2.15.3, replaced by `streamTimeout` pattern. Emotion SSR is no longer needed.
|
|
77
|
+
|
|
78
|
+
### 3. **Server Configuration** (`server.js`)
|
|
79
|
+
|
|
80
|
+
- ✅ Removed `installGlobals()` - Not needed with Node.js 20+ (native `Response.json()` support)
|
|
81
|
+
- ✅ Removed unused imports: `readFileSync`, `fileURLToPath`, `dirname`, `join`
|
|
82
|
+
- ✅ Updated JSON import syntax from `JSON.parse(readFileSync(...))` to `import config from '...' with { type: 'json' }`
|
|
83
|
+
- ✅ Added `.well-known/*` handler to ignore Chrome DevTools requests
|
|
84
|
+
- **Reason**: ES2024 standard compliance (Node.js 20.10+), cleaner code
|
|
85
|
+
|
|
86
|
+
**Important**: Requires Node.js 20+ for native `Response.json()` support. Use `nvm use 22` to ensure compatibility.
|
|
87
|
+
|
|
88
|
+
### 4. **Vite Configuration** (`vite.config.ts`)
|
|
89
|
+
|
|
90
|
+
- ✅ **Removed `routes: routesConfig`** - Must use `routes.ts` file instead (v3_routeConfig flag requires this)
|
|
91
|
+
- ✅ **Removed `installGlobals()`** - Not needed with Node.js 20+ (native `Response.json()` support)
|
|
92
|
+
- ✅ Removed unused imports: `readFileSync`, `postcss`, `defineRoutesConfig`, `performCopyOperations`
|
|
93
|
+
- ✅ Updated JSON import syntax to `with` clause: `import config from './app/cde-webconfig.json' with { type: 'json' }`
|
|
94
|
+
- ✅ Added Future module declaration for `v3_singleFetch` type support
|
|
95
|
+
- ✅ Added v3 future flags:
|
|
96
|
+
```typescript
|
|
97
|
+
future: {
|
|
98
|
+
unstable_optimizeDeps: true,
|
|
99
|
+
v3_fetcherPersist: true,
|
|
100
|
+
v3_relativeSplatPath: true,
|
|
101
|
+
v3_throwAbortReason: true,
|
|
102
|
+
v3_singleFetch: true,
|
|
103
|
+
v3_lazyRouteDiscovery: true,
|
|
104
|
+
v3_routeConfig: true,
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
- ✅ Added `optimizeDeps.include` for Radix UI packages pre-bundling
|
|
108
|
+
- ✅ Added `optimizeDeps.force: true` for better dependency optimization
|
|
109
|
+
- ✅ Updated `ssr.noExternal` with more Radix UI packages for proper SSR
|
|
110
|
+
- ✅ Updated `cjsInterop` dependencies to include `@rjsf/**`, `react-timer-hook`, `@ant-design/icons`, etc.
|
|
111
|
+
- ✅ Added `worker.format: 'es'` for ES module workers
|
|
112
|
+
|
|
113
|
+
**Important**: The `routes` config option is NOT supported when a `routes.ts` file is present. You must remove `routes: routesConfig` from vite.config.ts and migrate routes to `routes.ts`.
|
|
114
|
+
|
|
115
|
+
### 5. **Route Configuration** (`src/routes.ts`)
|
|
116
|
+
|
|
117
|
+
- ✅ **NEW FILE**: Created v3 route configuration file
|
|
118
|
+
- Uses `remixRoutesOptionAdapter` for file-based routing
|
|
119
|
+
- Integrates with existing `defineRoutesConfig` from `@common-stack/rollup-vite-utils`
|
|
120
|
+
- Handles production copy operations and sync-meta.json loading
|
|
121
|
+
|
|
122
|
+
## Packages Added
|
|
123
|
+
|
|
124
|
+
**Location**: `servers/frontend-server/package.json` (devDependencies)
|
|
125
|
+
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"devDependencies": {
|
|
129
|
+
"@remix-run/dev": "~2.15.3",
|
|
130
|
+
"@remix-run/fs-routes": "~2.15.3",
|
|
131
|
+
"@remix-run/route-config": "~2.15.3",
|
|
132
|
+
"@remix-run/routes-option-adapter": "~2.15.3",
|
|
133
|
+
"@remix-run/serve": "~2.15.3"
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
These packages enable the v3 routing configuration system.
|
|
139
|
+
|
|
140
|
+
**Important**: The `@remix-run/fs-routes` package is required to prevent "Response.json is not a function" errors in Remix 2.15.3.
|
|
141
|
+
|
|
142
|
+
**Note**: These should be added to the frontend-server's package.json, NOT the root workspace package.json. This follows the pattern used in adminIde-stack.
|
|
143
|
+
|
|
144
|
+
## Files Modified
|
|
145
|
+
|
|
146
|
+
1. `src/entry.client.tsx` - Client hydration entry point
|
|
147
|
+
2. `src/entry.server.tsx` - Server rendering entry point
|
|
148
|
+
3. `server.js` - Express server configuration
|
|
149
|
+
4. `vite.config.ts` - Vite build configuration
|
|
150
|
+
5. `src/routes.ts` - **NEW**: v3 route configuration
|
|
151
|
+
6. `src/root.tsx` - Updated to match adminide-stack (imports, data function, Layout updates)
|
|
152
|
+
|
|
153
|
+
## Additional Configuration Updates
|
|
154
|
+
|
|
155
|
+
### Root `package.json` Updates
|
|
156
|
+
|
|
157
|
+
- Added `@common-stack/codegen-zod`: `^8.2.2-alpha.0` to devDependencies
|
|
158
|
+
- Added `zod`: `^4.0.0` to resolutions
|
|
159
|
+
- Added `postcss`: `^8.5.1` to resolutions
|
|
160
|
+
- Updated `prettier`: `^2.7.1` → `^3.4.0`
|
|
161
|
+
|
|
162
|
+
### `cdecode-config.json` Updates
|
|
163
|
+
|
|
164
|
+
- Added Zod schema generation configuration
|
|
165
|
+
- Added `generated-zod-schemas.ts` output with `@common-stack/codegen-zod/graphql` plugin
|
|
166
|
+
- Added `serviceSchemas` configuration for service schema generation
|
|
167
|
+
- Added hook for running `generateAllServiceSchemas.js` after codegen
|
|
168
|
+
- Simplified schema/document paths to use `%discoveredSchemas%` and `%discoveredDocuments%`
|
|
169
|
+
|
|
170
|
+
### `src/root.tsx` Updates (matching adminide-stack)
|
|
171
|
+
|
|
172
|
+
- Changed import from `json` to `data` from `@remix-run/react`
|
|
173
|
+
- Added `useLoaderData`, `useRouteError` imports
|
|
174
|
+
- Changed `ErrorBoundary` to use `ApplicationErrorHandler, RemixErrorBoundary as ErrorBoundary` from `@admin-layout/tailwind-ui`
|
|
175
|
+
- Added error handling for settings loader with try/catch block
|
|
176
|
+
- Renamed loader data variable to `loaderData` with proper typing `{ locale: any; __ENV__?: any }`
|
|
177
|
+
- Added fallback `|| 'en'` for locale
|
|
178
|
+
- Updated `__ENV__` serialization with `|| {}` for safety
|
|
179
|
+
- Added Symbol.observable polyfill in `<head>` section (CRITICAL: must load before other scripts)
|
|
180
|
+
- Wrapped `App` component with `ApplicationErrorHandler` component
|
|
181
|
+
|
|
182
|
+
## Verification Steps
|
|
183
|
+
|
|
184
|
+
1. ✅ TypeScript compilation: No errors
|
|
185
|
+
2. ✅ Package installation: Both routing packages installed successfully
|
|
186
|
+
3. ✅ Syntax validation: All files pass linting
|
|
187
|
+
4. ✅ Future flags: All 6 v3 flags enabled
|
|
188
|
+
|
|
189
|
+
## Next Steps
|
|
190
|
+
|
|
191
|
+
1. **Install dependencies**:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
# From the root of yantra-stack
|
|
195
|
+
yarn
|
|
196
|
+
|
|
197
|
+
# Then run the dependency update script to ensure all deps are aligned
|
|
198
|
+
node tools/update-dependencies.mjs
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
2. **Test the application**:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
cd servers/frontend-server
|
|
205
|
+
yarn dev
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
3. **Verify routing**:
|
|
209
|
+
- Ensure all routes load correctly
|
|
210
|
+
- Check for any console warnings/errors
|
|
211
|
+
- Test navigation between routes
|
|
212
|
+
|
|
213
|
+
4. **Monitor for issues**:
|
|
214
|
+
- Check for hydration mismatches
|
|
215
|
+
- Verify SSR works correctly
|
|
216
|
+
- Test dynamic route loading
|
|
217
|
+
|
|
218
|
+
## References
|
|
219
|
+
|
|
220
|
+
- Main upgrade guide: `/common-stack/REMIX_2.15.3_UPGRADE_GUIDE.md`
|
|
221
|
+
- Remix 2.15.3 release notes: https://github.com/remix-run/remix/releases/tag/remix%402.15.3
|
|
222
|
+
- Future flags documentation: https://remix.run/docs/en/v2/start/future-flags
|
|
223
|
+
|
|
224
|
+
## Compatibility Requirements
|
|
225
|
+
|
|
226
|
+
**Node.js Version**: 20+ required (22 recommended)
|
|
227
|
+
|
|
228
|
+
- Use `nvm use 22` before running the application
|
|
229
|
+
- Node.js 20+ has native `Response.json()` support, eliminating the need for `installGlobals()`
|
|
230
|
+
|
|
231
|
+
**Minimum Package Versions** (from main upgrade guide):
|
|
232
|
+
|
|
233
|
+
- `common-stack`: 8.2.2-alpha.0 or greater
|
|
234
|
+
- `adminide-stack`: 13.0.4-alpha.0 or greater
|
|
235
|
+
- `admin-layout`: 12.2.1-alpha.0 or greater
|
|
236
|
+
|
|
237
|
+
All packages must be updated to these minimum versions to ensure compatibility.
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Docker Configuration Updates
|
|
242
|
+
|
|
243
|
+
### `Dockerfile` Updates
|
|
244
|
+
|
|
245
|
+
The Dockerfile must be updated to use Node.js 22 base image:
|
|
246
|
+
|
|
247
|
+
```dockerfile
|
|
248
|
+
# Before
|
|
249
|
+
FROM node:20-alpine AS base
|
|
250
|
+
|
|
251
|
+
# After
|
|
252
|
+
FROM node:22-alpine AS base
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
**All Dockerfile stages must use Node.js 22:**
|
|
256
|
+
|
|
257
|
+
```dockerfile
|
|
258
|
+
# Build stage
|
|
259
|
+
FROM node:22-alpine AS builder
|
|
260
|
+
|
|
261
|
+
# Production stage
|
|
262
|
+
FROM node:22-alpine AS production
|
|
263
|
+
|
|
264
|
+
# Development stage (if applicable)
|
|
265
|
+
FROM node:22-alpine AS development
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
**Reason**: Node.js 22+ is required for:
|
|
269
|
+
|
|
270
|
+
- Native `Response.json()` support (eliminates need for `installGlobals()`)
|
|
271
|
+
- ES2024 `import ... with { type: 'json' }` syntax support
|
|
272
|
+
- Remix 2.15.3 v3 future flags compatibility
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## Jenkins Configuration Updates
|
|
277
|
+
|
|
278
|
+
### `Jenkinsfile` Updates
|
|
279
|
+
|
|
280
|
+
- ✅ Updated `NODEJS_TOOL_VERSION` default to `nodejs22` (was `nodejs20`)
|
|
281
|
+
- ✅ Added `nodejs24` as an option for future compatibility
|
|
282
|
+
|
|
283
|
+
```groovy
|
|
284
|
+
choice choices: ['nodejs22', 'nodejs20', 'nodejs24'], description: 'Choose NodeJS version', name: 'NODEJS_TOOL_VERSION'
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Jenkins Build Configuration
|
|
288
|
+
|
|
289
|
+
Ensure all Jenkins build pipelines use Node.js 22:
|
|
290
|
+
|
|
291
|
+
```groovy
|
|
292
|
+
// In Jenkinsfile or pipeline script
|
|
293
|
+
tools {
|
|
294
|
+
nodejs 'nodejs22'
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Or using nvm
|
|
298
|
+
stages {
|
|
299
|
+
stage('Setup') {
|
|
300
|
+
steps {
|
|
301
|
+
sh 'nvm use 22'
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
**Reason**: Node.js 22+ is required for native `Response.json()` support in Remix 2.15.3.
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## CRITICAL: Loader Migration (`json` → `data`)
|
|
312
|
+
|
|
313
|
+
### Breaking Change in Remix 2.15.3
|
|
314
|
+
|
|
315
|
+
With `v3_singleFetch` future flag enabled, all loaders must migrate from using `json()` to `data()`:
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
// ❌ OLD - Will cause issues with v3_singleFetch
|
|
319
|
+
import { json } from '@remix-run/react';
|
|
320
|
+
|
|
321
|
+
export const loader = async () => {
|
|
322
|
+
return json({ message: 'Hello' });
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
// ✅ NEW - Required for Remix 2.15.3
|
|
326
|
+
import { data } from '@remix-run/react';
|
|
327
|
+
|
|
328
|
+
export const loader = async () => {
|
|
329
|
+
return data({ message: 'Hello' });
|
|
330
|
+
};
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Files That Need Migration
|
|
334
|
+
|
|
335
|
+
Search your codebase for all files using `json` from `@remix-run/react` or `@remix-run/node`:
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
# Find all files using json import
|
|
339
|
+
grep -r "import.*json.*from '@remix-run" --include="*.tsx" --include="*.ts" packages/ servers/
|
|
340
|
+
|
|
341
|
+
# Find all files using json() in loaders
|
|
342
|
+
grep -r "return json(" --include="*.tsx" --include="*.ts" packages/ servers/
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### Common Locations to Check
|
|
346
|
+
|
|
347
|
+
1. **Route files** (`routes/*.tsx`)
|
|
348
|
+
2. **Root layout** (`root.tsx`)
|
|
349
|
+
3. **Package route modules** (e.g., `packages/*/browser/src/routes/*.tsx`)
|
|
350
|
+
4. **Server loaders** (any file with `loader` export)
|
|
351
|
+
5. **Action handlers** (any file with `action` export)
|
|
352
|
+
|
|
353
|
+
### Migration Pattern
|
|
354
|
+
|
|
355
|
+
```typescript
|
|
356
|
+
// Before
|
|
357
|
+
import { json, useLoaderData } from '@remix-run/react';
|
|
358
|
+
|
|
359
|
+
export const loader = async ({ request, context, params }) => {
|
|
360
|
+
const data = await fetchData();
|
|
361
|
+
return json(
|
|
362
|
+
{ data },
|
|
363
|
+
{
|
|
364
|
+
headers: {
|
|
365
|
+
'Cache-Control': 'max-age=300',
|
|
366
|
+
},
|
|
367
|
+
},
|
|
368
|
+
);
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
// After
|
|
372
|
+
import { data, useLoaderData } from '@remix-run/react';
|
|
373
|
+
|
|
374
|
+
export const loader = async ({ request, context, params }) => {
|
|
375
|
+
const result = await fetchData();
|
|
376
|
+
return data(
|
|
377
|
+
{ data: result },
|
|
378
|
+
{
|
|
379
|
+
headers: [['Cache-Control', 'max-age=300']],
|
|
380
|
+
},
|
|
381
|
+
);
|
|
382
|
+
};
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### Headers Format Change
|
|
386
|
+
|
|
387
|
+
Note that headers format also changes with `data()`:
|
|
388
|
+
|
|
389
|
+
```typescript
|
|
390
|
+
// ❌ OLD with json() - Object format
|
|
391
|
+
return json(data, {
|
|
392
|
+
headers: {
|
|
393
|
+
'Cache-Control': 'max-age=300',
|
|
394
|
+
'Set-Cookie': cookie,
|
|
395
|
+
},
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
// ✅ NEW with data() - Array of tuples format
|
|
399
|
+
return data(result, {
|
|
400
|
+
headers: [
|
|
401
|
+
['Cache-Control', 'max-age=300'],
|
|
402
|
+
['Set-Cookie', cookie],
|
|
403
|
+
],
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
// ✅ With conditional headers
|
|
407
|
+
return data(result, {
|
|
408
|
+
headers: [['Cache-Control', 'max-age=300'], cookie ? ['Set-Cookie', cookie] : null].filter(Boolean) as [
|
|
409
|
+
string,
|
|
410
|
+
string,
|
|
411
|
+
][],
|
|
412
|
+
});
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
### Packages Requiring Loader Updates
|
|
416
|
+
|
|
417
|
+
The following packages commonly have loaders that need migration:
|
|
418
|
+
|
|
419
|
+
| Package | Files to Check |
|
|
420
|
+
| -------------------------------------------- | ---------------- |
|
|
421
|
+
| `@adminide-stack/account-api-browser` | Route loaders |
|
|
422
|
+
| `@adminide-stack/platform-browser` | Route loaders |
|
|
423
|
+
| `@adminide-stack/project-mgmt-browser` | Route loaders |
|
|
424
|
+
| `@adminide-stack/user-auth0-browser` | Route loaders |
|
|
425
|
+
| `@adminide-stack/extension-module-browser` | Route loaders |
|
|
426
|
+
| `@adminide-stack/marketplace-module-browser` | Route loaders |
|
|
427
|
+
| `@admin-layout/client` | Settings loaders |
|
|
428
|
+
| Local `packages/*/browser` | All route files |
|
|
429
|
+
|
|
430
|
+
### Verification
|
|
431
|
+
|
|
432
|
+
After migration, verify no `json` imports remain:
|
|
433
|
+
|
|
434
|
+
```bash
|
|
435
|
+
# Should return no results
|
|
436
|
+
grep -r "import.*{ json" --include="*.tsx" --include="*.ts" packages/ servers/ | grep -v "node_modules"
|
|
437
|
+
|
|
438
|
+
# Also check for json from @remix-run/node
|
|
439
|
+
grep -r "json.*from '@remix-run/node'" --include="*.tsx" --include="*.ts" packages/ servers/ | grep -v "node_modules"
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
---
|
|
443
|
+
|
|
444
|
+
## Complete File Contents
|
|
445
|
+
|
|
446
|
+
### `server.js`
|
|
447
|
+
|
|
448
|
+
```javascript
|
|
449
|
+
import express from 'express';
|
|
450
|
+
import compression from 'compression';
|
|
451
|
+
import { createRequestHandler } from '@remix-run/express';
|
|
452
|
+
import './env.js';
|
|
453
|
+
import { performCopyOperations } from '@common-stack/rollup-vite-utils/lib/preStartup/configLoader/configLoader.js';
|
|
454
|
+
import config from './app/cde-webconfig.json' with { type: 'json' };
|
|
455
|
+
|
|
456
|
+
Object.keys(config.buildConfig).forEach((key) => {
|
|
457
|
+
global[key] = config.buildConfig[key];
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
const startServer = async () => {
|
|
461
|
+
await performCopyOperations(config);
|
|
462
|
+
|
|
463
|
+
const { corsMiddleware } = await import(
|
|
464
|
+
`./${config.commonPaths.appPath}/${config.commonPaths.frontendStackPath}/backend/middlewares/cors.js`
|
|
465
|
+
);
|
|
466
|
+
const { containerMiddleware } = await import(
|
|
467
|
+
`./${config.commonPaths.appPath}/${config.commonPaths.frontendStackPath}/backend/middlewares/container.js`
|
|
468
|
+
);
|
|
469
|
+
const { loadContext } = await import(
|
|
470
|
+
`./${config.commonPaths.appPath}/${config.commonPaths.frontendStackPath}/load-context.server.js`
|
|
471
|
+
);
|
|
472
|
+
|
|
473
|
+
const viteDevServer =
|
|
474
|
+
process.env.NODE_ENV === 'production'
|
|
475
|
+
? undefined
|
|
476
|
+
: await import('vite').then((vite) => {
|
|
477
|
+
return vite.createServer({
|
|
478
|
+
server: { middlewareMode: true },
|
|
479
|
+
});
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
const remixHandler = createRequestHandler({
|
|
483
|
+
getLoadContext: loadContext,
|
|
484
|
+
build: viteDevServer
|
|
485
|
+
? () => viteDevServer.ssrLoadModule('virtual:remix/server-build')
|
|
486
|
+
: await import('./build/server/index.js'),
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
const app = express();
|
|
490
|
+
|
|
491
|
+
app.use(compression());
|
|
492
|
+
app.disable('x-powered-by');
|
|
493
|
+
|
|
494
|
+
if (viteDevServer) {
|
|
495
|
+
app.use(viteDevServer.middlewares);
|
|
496
|
+
} else {
|
|
497
|
+
app.use('/assets', express.static('build/client/assets', { immutable: true, maxAge: '1y' }));
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
app.use(express.static('build/client', { maxAge: '1h' }));
|
|
501
|
+
|
|
502
|
+
app.use(corsMiddleware);
|
|
503
|
+
app.options('*', corsMiddleware);
|
|
504
|
+
|
|
505
|
+
// Ignore Chrome DevTools and other well-known requests
|
|
506
|
+
app.get('/.well-known/*', (req, res) => {
|
|
507
|
+
res.status(404).json({ error: 'Not found' });
|
|
508
|
+
});
|
|
509
|
+
app.use(async (req, res, next) => {
|
|
510
|
+
let isAssetRequest = (url) =>
|
|
511
|
+
/\.[jt]sx?$/.test(url) ||
|
|
512
|
+
/@id\/__x00__virtual:/.test(url) ||
|
|
513
|
+
/@vite\/client/.test(url) ||
|
|
514
|
+
/node_modules\/vite\/dist\/client\/env/.test(url);
|
|
515
|
+
|
|
516
|
+
if (isAssetRequest(req.url)) {
|
|
517
|
+
next();
|
|
518
|
+
} else {
|
|
519
|
+
return await containerMiddleware(req, res, async () => {
|
|
520
|
+
return remixHandler(req, res, next);
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
const port = process.env.PORT || 3000;
|
|
526
|
+
app.listen(port, () => console.log(`Express server listening at http://localhost:${port}`));
|
|
527
|
+
};
|
|
528
|
+
|
|
529
|
+
startServer().catch((err) => {
|
|
530
|
+
console.error('Failed to start server:', err);
|
|
531
|
+
});
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
### `vite.config.ts`
|
|
535
|
+
|
|
536
|
+
```typescript
|
|
537
|
+
import { defineConfig, ConfigEnv, UserConfig } from 'vite';
|
|
538
|
+
import { vitePlugin as remix } from '@remix-run/dev';
|
|
539
|
+
import { dirname, resolve } from 'path';
|
|
540
|
+
import { fileURLToPath } from 'url';
|
|
541
|
+
// import { remixDevTools } from 'remix-development-tools';
|
|
542
|
+
import tsconfigPaths from 'vite-tsconfig-paths';
|
|
543
|
+
import { i18nInternationalizationPlugin } from '@common-stack/rollup-vite-utils/lib/vite-plugins/i18n-internationalization-plugin.js';
|
|
544
|
+
// import { visualizer } from 'rollup-plugin-visualizer';
|
|
545
|
+
import { loadEnvConfig } from '@common-stack/rollup-vite-utils/lib/preStartup/configLoader/envLoader.js';
|
|
546
|
+
import { cjsInterop } from 'vite-plugin-cjs-interop';
|
|
547
|
+
import { mergeWith } from 'lodash-es';
|
|
548
|
+
import config from './app/cde-webconfig.json' with { type: 'json' };
|
|
549
|
+
|
|
550
|
+
declare module '@remix-run/node' {
|
|
551
|
+
// or cloudflare, deno, etc.
|
|
552
|
+
interface Future {
|
|
553
|
+
v3_singleFetch: true;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
const directoryName = dirname(fileURLToPath(import.meta.url));
|
|
558
|
+
|
|
559
|
+
export default defineConfig(async ({ isSsrBuild }: ConfigEnv): Promise<UserConfig> => {
|
|
560
|
+
console.log('--- IS SSR BUILD:', isSsrBuild);
|
|
561
|
+
|
|
562
|
+
// Load environment variables from dotenv or other config
|
|
563
|
+
const dotEnvResult = loadEnvConfig(directoryName);
|
|
564
|
+
|
|
565
|
+
// Define environment variables for Vite
|
|
566
|
+
const envVariables = {
|
|
567
|
+
__ENV__: JSON.stringify(dotEnvResult?.parsed),
|
|
568
|
+
__SERVER__: true,
|
|
569
|
+
__CLIENT__: false,
|
|
570
|
+
...Object.fromEntries(
|
|
571
|
+
Object.entries(config.buildConfig).map(([key, value]) => [
|
|
572
|
+
key,
|
|
573
|
+
typeof value === 'string' ? `"${value.replace(/\\/g, '\\\\')}"` : value,
|
|
574
|
+
]),
|
|
575
|
+
),
|
|
576
|
+
};
|
|
577
|
+
|
|
578
|
+
// Vite configuration
|
|
579
|
+
const viteConfig = {
|
|
580
|
+
define: envVariables,
|
|
581
|
+
ssr: {
|
|
582
|
+
// Keep small client-only libraries bundled, including all @radix-ui packages
|
|
583
|
+
// to ensure proper CommonJS to ESM interop handled by cjsInterop plugin
|
|
584
|
+
noExternal: [
|
|
585
|
+
'react-datepicker',
|
|
586
|
+
/^@radix-ui\//,
|
|
587
|
+
'@radix-ui/react-slot',
|
|
588
|
+
'@radix-ui/react-primitive',
|
|
589
|
+
'@radix-ui/react-compose-refs',
|
|
590
|
+
'@radix-ui/react-context',
|
|
591
|
+
'@radix-ui/react-collection',
|
|
592
|
+
'@radix-ui/react-separator',
|
|
593
|
+
],
|
|
594
|
+
},
|
|
595
|
+
plugins: [
|
|
596
|
+
// remixDevTools({
|
|
597
|
+
// server: {
|
|
598
|
+
// logs: {
|
|
599
|
+
// cookies: true,
|
|
600
|
+
// defer: true,
|
|
601
|
+
// actions: true,
|
|
602
|
+
// loaders: true,
|
|
603
|
+
// cache: true,
|
|
604
|
+
// siteClear: true,
|
|
605
|
+
// },
|
|
606
|
+
// },
|
|
607
|
+
// }),
|
|
608
|
+
i18nInternationalizationPlugin({
|
|
609
|
+
folderName: 'cdm-locales',
|
|
610
|
+
packages: [...config.modules, ...config.i18n.packages],
|
|
611
|
+
namespaceResolution: 'basename' as any,
|
|
612
|
+
}),
|
|
613
|
+
// visualizer({
|
|
614
|
+
// open: true,
|
|
615
|
+
// filename: 'bundle-analysis.html',
|
|
616
|
+
// }),
|
|
617
|
+
cjsInterop({
|
|
618
|
+
dependencies: [
|
|
619
|
+
'@rjsf/**',
|
|
620
|
+
'react-timer-hook',
|
|
621
|
+
'rc-util/lib/hooks/useMergedState.js',
|
|
622
|
+
'@ant-design/icons',
|
|
623
|
+
'rc-picker',
|
|
624
|
+
'@monaco-editor/loader',
|
|
625
|
+
'react-google-calendar-api',
|
|
626
|
+
'@apollo/client',
|
|
627
|
+
],
|
|
628
|
+
}),
|
|
629
|
+
remix({
|
|
630
|
+
appDirectory: 'src',
|
|
631
|
+
// routes: routesConfig, // Removed - using routes.ts instead
|
|
632
|
+
future: {
|
|
633
|
+
unstable_optimizeDeps: true,
|
|
634
|
+
v3_fetcherPersist: true,
|
|
635
|
+
v3_relativeSplatPath: true,
|
|
636
|
+
v3_throwAbortReason: true,
|
|
637
|
+
v3_lazyRouteDiscovery: true,
|
|
638
|
+
v3_singleFetch: true,
|
|
639
|
+
v3_routeConfig: true,
|
|
640
|
+
},
|
|
641
|
+
}),
|
|
642
|
+
tsconfigPaths({ ignoreConfigErrors: true }),
|
|
643
|
+
],
|
|
644
|
+
optimizeDeps: {
|
|
645
|
+
include: [
|
|
646
|
+
'@radix-ui/react-slot',
|
|
647
|
+
'@radix-ui/react-compose-refs',
|
|
648
|
+
'@radix-ui/react-primitive',
|
|
649
|
+
'@radix-ui/react-collection',
|
|
650
|
+
'@radix-ui/react-dialog',
|
|
651
|
+
'@radix-ui/react-select',
|
|
652
|
+
'@radix-ui/react-alert-dialog',
|
|
653
|
+
'@radix-ui/react-popover',
|
|
654
|
+
'@radix-ui/react-tooltip',
|
|
655
|
+
'@radix-ui/react-context-menu',
|
|
656
|
+
],
|
|
657
|
+
esbuildOptions: {
|
|
658
|
+
target: 'esnext',
|
|
659
|
+
},
|
|
660
|
+
force: true, // Force dependency optimization on every build
|
|
661
|
+
},
|
|
662
|
+
build: {
|
|
663
|
+
target: 'esnext',
|
|
664
|
+
rollupOptions: {
|
|
665
|
+
output: {
|
|
666
|
+
// Ensure that worker files are properly bundled
|
|
667
|
+
format: 'es',
|
|
668
|
+
},
|
|
669
|
+
},
|
|
670
|
+
},
|
|
671
|
+
resolve: {
|
|
672
|
+
alias: {
|
|
673
|
+
'@app': resolve(directoryName, 'app'),
|
|
674
|
+
'@src': resolve(directoryName, 'src'),
|
|
675
|
+
},
|
|
676
|
+
},
|
|
677
|
+
worker: {
|
|
678
|
+
format: 'es', // Use ES modules format for workers
|
|
679
|
+
plugins: () => [], // Return an empty array of plugins
|
|
680
|
+
},
|
|
681
|
+
};
|
|
682
|
+
|
|
683
|
+
// Deep merge custom Vite config from config.json
|
|
684
|
+
// to merge Arrays properly need to concat.
|
|
685
|
+
const result = mergeWith(config.viteConfig, viteConfig, (objValue, srcValue) => {
|
|
686
|
+
if (Array.isArray(objValue)) {
|
|
687
|
+
return objValue.concat(srcValue);
|
|
688
|
+
}
|
|
689
|
+
});
|
|
690
|
+
return result as UserConfig;
|
|
691
|
+
});
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
### `src/routes.ts`
|
|
695
|
+
|
|
696
|
+
```typescript
|
|
697
|
+
import { type RouteConfig } from '@remix-run/route-config';
|
|
698
|
+
import { remixRoutesOptionAdapter } from '@remix-run/routes-option-adapter';
|
|
699
|
+
import { dirname, resolve } from 'path';
|
|
700
|
+
import { fileURLToPath } from 'url';
|
|
701
|
+
import { defineRoutesConfig } from '@common-stack/rollup-vite-utils/lib/vite-wrappers/json-wrappers.js';
|
|
702
|
+
import { performCopyOperations } from '@common-stack/rollup-vite-utils/lib/preStartup/configLoader/configLoader.js';
|
|
703
|
+
import config from '../app/cde-webconfig.json' with { type: 'json' };
|
|
704
|
+
|
|
705
|
+
const directoryName = dirname(fileURLToPath(import.meta.url));
|
|
706
|
+
|
|
707
|
+
export default remixRoutesOptionAdapter(async (defineRoutes) => {
|
|
708
|
+
if (process.env.NODE_ENV === 'production') {
|
|
709
|
+
await performCopyOperations(config);
|
|
710
|
+
}
|
|
711
|
+
let metaJson = null;
|
|
712
|
+
try {
|
|
713
|
+
metaJson = await import('../app/sync-meta.json');
|
|
714
|
+
} catch {
|
|
715
|
+
console.warn('No sync-meta.json found, continuing without metadata.');
|
|
716
|
+
}
|
|
717
|
+
return defineRoutes((routeFn) => {
|
|
718
|
+
defineRoutesConfig(
|
|
719
|
+
routeFn,
|
|
720
|
+
{
|
|
721
|
+
routesFileName: 'routes.json',
|
|
722
|
+
packages: config.modules,
|
|
723
|
+
paths: config.paths,
|
|
724
|
+
iconsRepository: config?.iconsRepository,
|
|
725
|
+
rootPath: resolve(directoryName, '../../..'),
|
|
726
|
+
settings: {
|
|
727
|
+
_useFutureCommonPackage: true,
|
|
728
|
+
},
|
|
729
|
+
},
|
|
730
|
+
metaJson,
|
|
731
|
+
);
|
|
732
|
+
});
|
|
733
|
+
}) satisfies RouteConfig;
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
### `src/entry.client.tsx`
|
|
737
|
+
|
|
738
|
+
```tsx
|
|
739
|
+
/**
|
|
740
|
+
* By default, Remix will handle hydrating your app on the client for you.
|
|
741
|
+
* You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
|
|
742
|
+
* For more information, see https://remix.run/file-conventions/entry.client
|
|
743
|
+
*/
|
|
744
|
+
import * as React from 'react';
|
|
745
|
+
import 'reflect-metadata';
|
|
746
|
+
import { RemixBrowser } from '@remix-run/react';
|
|
747
|
+
import { startTransition, StrictMode } from 'react';
|
|
748
|
+
import { hydrateRoot } from 'react-dom/client';
|
|
749
|
+
import { ApolloProvider } from '@apollo/client/index.js';
|
|
750
|
+
import { SlotFillProvider, removeUniversalPortals } from '@common-stack/components-pro';
|
|
751
|
+
import { InversifyProvider } from '@common-stack/client-react';
|
|
752
|
+
import { Provider as ReduxProvider } from 'react-redux';
|
|
753
|
+
import i18next from 'i18next';
|
|
754
|
+
import { I18nextProvider, initReactI18next } from 'react-i18next';
|
|
755
|
+
import LanguageDetector from 'i18next-browser-languagedetector';
|
|
756
|
+
import Backend from 'i18next-http-backend';
|
|
757
|
+
// @ts-ignore
|
|
758
|
+
import { getInitialNamespaces } from 'remix-i18next/client';
|
|
759
|
+
// @ts-ignore
|
|
760
|
+
import { createReduxStore } from '@app/frontend-stack-react/config/redux-config.js';
|
|
761
|
+
// @ts-ignore
|
|
762
|
+
import { createClientContainer } from '@app/frontend-stack-react/config/client.service';
|
|
763
|
+
// @ts-ignore
|
|
764
|
+
import clientModules from '@app/frontend-stack-react/modules.js';
|
|
765
|
+
// @ts-ignore
|
|
766
|
+
import config from '@app/cde-webconfig.json';
|
|
767
|
+
|
|
768
|
+
const { apolloClient: client, container, serviceFunc } = createClientContainer();
|
|
769
|
+
const { store } = createReduxStore(client, serviceFunc(), container);
|
|
770
|
+
|
|
771
|
+
(window as any).__remixStore = store;
|
|
772
|
+
removeUniversalPortals((window as any).__SLOT_FILLS__ || []);
|
|
773
|
+
|
|
774
|
+
async function hydrate() {
|
|
775
|
+
if (!i18next.isInitialized && config.i18n.enabled) {
|
|
776
|
+
await i18next
|
|
777
|
+
.use(initReactI18next)
|
|
778
|
+
.use(LanguageDetector)
|
|
779
|
+
.use(Backend)
|
|
780
|
+
.init({
|
|
781
|
+
fallbackLng: config.i18n.fallbackLng,
|
|
782
|
+
defaultNS: config.i18n.defaultNS,
|
|
783
|
+
react: config.i18n.react,
|
|
784
|
+
supportedLngs: config.i18n.supportedLngs,
|
|
785
|
+
backend: config.i18n.backend,
|
|
786
|
+
ns: getInitialNamespaces(),
|
|
787
|
+
detection: {
|
|
788
|
+
order: ['htmlTag'],
|
|
789
|
+
caches: [],
|
|
790
|
+
},
|
|
791
|
+
});
|
|
792
|
+
}
|
|
793
|
+
startTransition(() => {
|
|
794
|
+
hydrateRoot(
|
|
795
|
+
document,
|
|
796
|
+
<I18nextProvider i18n={i18next}>
|
|
797
|
+
<ReduxProvider store={store}>
|
|
798
|
+
<SlotFillProvider>
|
|
799
|
+
<InversifyProvider container={container} modules={clientModules}>
|
|
800
|
+
<ApolloProvider client={client}>
|
|
801
|
+
<RemixBrowser />
|
|
802
|
+
</ApolloProvider>
|
|
803
|
+
</InversifyProvider>
|
|
804
|
+
</SlotFillProvider>
|
|
805
|
+
</ReduxProvider>
|
|
806
|
+
</I18nextProvider>,
|
|
807
|
+
);
|
|
808
|
+
});
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
if (window.requestIdleCallback) {
|
|
812
|
+
window.requestIdleCallback(hydrate);
|
|
813
|
+
} else {
|
|
814
|
+
// Safari doesn't support requestIdleCallback
|
|
815
|
+
// https://caniuse.com/requestidlecallback
|
|
816
|
+
window.setTimeout(hydrate, 1);
|
|
817
|
+
}
|
|
818
|
+
```
|
|
819
|
+
|
|
820
|
+
### `src/entry.server.tsx`
|
|
821
|
+
|
|
822
|
+
```tsx
|
|
823
|
+
/**
|
|
824
|
+
* By default, Remix will handle generating the HTTP Response for you.
|
|
825
|
+
* You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
|
|
826
|
+
* For more information, see https://remix.run/file-conventions/entry.server
|
|
827
|
+
*/
|
|
828
|
+
import * as React from 'react';
|
|
829
|
+
import 'reflect-metadata';
|
|
830
|
+
(global as any).__CLIENT__ = false;
|
|
831
|
+
(global as any).__SERVER__ = true;
|
|
832
|
+
import { PassThrough, Transform } from 'node:stream';
|
|
833
|
+
import type { EntryContext } from '@remix-run/node';
|
|
834
|
+
import { createReadableStreamFromReadable } from '@remix-run/node';
|
|
835
|
+
import { RemixServer } from '@remix-run/react';
|
|
836
|
+
import { isbot } from 'isbot';
|
|
837
|
+
import { ApolloProvider } from '@apollo/client/index.js';
|
|
838
|
+
import { SlotFillProvider } from '@common-stack/components-pro';
|
|
839
|
+
import { InversifyProvider } from '@common-stack/client-react';
|
|
840
|
+
import { renderToPipeableStream } from 'react-dom/server';
|
|
841
|
+
import { Provider as ReduxProvider } from 'react-redux';
|
|
842
|
+
import { LOCATION_CHANGE } from '@common-stack/remix-router-redux';
|
|
843
|
+
import serialize from 'serialize-javascript';
|
|
844
|
+
import { createInstance } from 'i18next';
|
|
845
|
+
import { I18nextProvider, initReactI18next } from 'react-i18next';
|
|
846
|
+
import Backend from 'i18next-fs-backend';
|
|
847
|
+
import { resolve } from 'node:path';
|
|
848
|
+
// @ts-ignore
|
|
849
|
+
import { i18nextInstance as i18next } from '@app/frontend-stack-react/i18n-localization/i18next.server.js';
|
|
850
|
+
import config from '@app/cde-webconfig.json';
|
|
851
|
+
// @ts-ignore
|
|
852
|
+
import type { IAppLoadContext } from '@common-stack/client-core';
|
|
853
|
+
|
|
854
|
+
// Reject/cancel all pending promises after 5 seconds
|
|
855
|
+
export const streamTimeout = 5000;
|
|
856
|
+
|
|
857
|
+
class ConstantsTransform extends Transform {
|
|
858
|
+
_fills: string[];
|
|
859
|
+
_apolloState: any;
|
|
860
|
+
_reduxState: any;
|
|
861
|
+
_styleSheet: string;
|
|
862
|
+
|
|
863
|
+
constructor(fills: string[], apolloState: any, reduxState: any, styleSheet: any) {
|
|
864
|
+
super();
|
|
865
|
+
this._fills = fills;
|
|
866
|
+
this._apolloState = apolloState;
|
|
867
|
+
this._reduxState = reduxState;
|
|
868
|
+
this._styleSheet = styleSheet;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
_transform(chunk, encoding, callback) {
|
|
872
|
+
let transformedChunk = chunk.toString();
|
|
873
|
+
|
|
874
|
+
if (transformedChunk.includes('[__APOLLO_STATE__]')) {
|
|
875
|
+
transformedChunk = transformedChunk.replace(
|
|
876
|
+
'[__APOLLO_STATE__]',
|
|
877
|
+
serialize(this._apolloState, { isJSON: true }),
|
|
878
|
+
);
|
|
879
|
+
}
|
|
880
|
+
if (transformedChunk.includes('[__PRELOADED_STATE__]')) {
|
|
881
|
+
transformedChunk = transformedChunk.replace(
|
|
882
|
+
'[__PRELOADED_STATE__]',
|
|
883
|
+
serialize(this._reduxState, { isJSON: true }),
|
|
884
|
+
);
|
|
885
|
+
}
|
|
886
|
+
if (transformedChunk.includes('[__SLOT_FILLS__]')) {
|
|
887
|
+
transformedChunk = transformedChunk.replace('[__SLOT_FILLS__]', serialize(this._fills, { isJSON: true }));
|
|
888
|
+
}
|
|
889
|
+
if (transformedChunk.includes('[__STYLESHEET__]')) {
|
|
890
|
+
transformedChunk = transformedChunk.replace('[__STYLESHEET__]', this._styleSheet);
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
callback(null, transformedChunk);
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
export default async function handleRequest(
|
|
898
|
+
request: Request,
|
|
899
|
+
responseStatusCode: number,
|
|
900
|
+
responseHeaders: Headers,
|
|
901
|
+
remixContext: EntryContext,
|
|
902
|
+
// This is ignored so we can keep it in the template for visibility. Feel
|
|
903
|
+
// free to delete this parameter in your app if you're not using it!
|
|
904
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
905
|
+
loadContext: IAppLoadContext,
|
|
906
|
+
) {
|
|
907
|
+
const instance = createInstance();
|
|
908
|
+
const lng = await i18next.getLocale(request);
|
|
909
|
+
const ns = i18next.getRouteNamespaces(remixContext);
|
|
910
|
+
|
|
911
|
+
// First, we create a new instance of i18next so every request will have a
|
|
912
|
+
// completely unique instance and not share any state.
|
|
913
|
+
if (config.i18n.enabled) {
|
|
914
|
+
await instance
|
|
915
|
+
.use(initReactI18next) // Tell our instance to use react-i18next
|
|
916
|
+
.use(Backend) // Setup our backend.init({
|
|
917
|
+
.init({
|
|
918
|
+
fallbackLng: config.i18n.fallbackLng,
|
|
919
|
+
defaultNS: config.i18n.defaultNS,
|
|
920
|
+
react: config.i18n.react,
|
|
921
|
+
supportedLngs: config.i18n.supportedLngs,
|
|
922
|
+
lng, // The locale we detected above
|
|
923
|
+
ns, // The namespaces the routes about to render want to use
|
|
924
|
+
backend: {
|
|
925
|
+
loadPath: resolve(config.i18n.backend.loadServerPath),
|
|
926
|
+
},
|
|
927
|
+
});
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
return isbot(request.headers.get('user-agent') || '')
|
|
931
|
+
? handleBotRequest(request, responseStatusCode, responseHeaders, remixContext, loadContext, instance)
|
|
932
|
+
: handleBrowserRequest(request, responseStatusCode, responseHeaders, remixContext, loadContext, instance);
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
function handleBotRequest(
|
|
936
|
+
request: Request,
|
|
937
|
+
responseStatusCode: number,
|
|
938
|
+
responseHeaders: Headers,
|
|
939
|
+
remixContext: EntryContext,
|
|
940
|
+
loadContext: IAppLoadContext,
|
|
941
|
+
i18nInstance: i18next,
|
|
942
|
+
) {
|
|
943
|
+
return new Promise((resolve, reject) => {
|
|
944
|
+
let shellRendered = false;
|
|
945
|
+
const { pipe, abort } = renderToPipeableStream(
|
|
946
|
+
<I18nextProvider i18n={i18nInstance}>
|
|
947
|
+
<RemixServer context={remixContext} url={request.url} />
|
|
948
|
+
</I18nextProvider>,
|
|
949
|
+
{
|
|
950
|
+
onAllReady() {
|
|
951
|
+
shellRendered = true;
|
|
952
|
+
const body = new PassThrough();
|
|
953
|
+
const stream = createReadableStreamFromReadable(body);
|
|
954
|
+
|
|
955
|
+
responseHeaders.set('Content-Type', 'text/html');
|
|
956
|
+
|
|
957
|
+
resolve(
|
|
958
|
+
new Response(stream, {
|
|
959
|
+
headers: responseHeaders,
|
|
960
|
+
status: responseStatusCode,
|
|
961
|
+
}),
|
|
962
|
+
);
|
|
963
|
+
|
|
964
|
+
pipe(body);
|
|
965
|
+
},
|
|
966
|
+
onShellError(error: unknown) {
|
|
967
|
+
reject(error);
|
|
968
|
+
},
|
|
969
|
+
onError(error: unknown) {
|
|
970
|
+
responseStatusCode = 500;
|
|
971
|
+
// Log streaming rendering errors from inside the shell. Don't log
|
|
972
|
+
// errors encountered during initial shell rendering since they'll
|
|
973
|
+
// reject and get logged in handleDocumentRequest.
|
|
974
|
+
if (shellRendered) {
|
|
975
|
+
console.error(error);
|
|
976
|
+
}
|
|
977
|
+
},
|
|
978
|
+
},
|
|
979
|
+
);
|
|
980
|
+
|
|
981
|
+
setTimeout(abort, streamTimeout + 1000);
|
|
982
|
+
});
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
function handleBrowserRequest(
|
|
986
|
+
request: Request,
|
|
987
|
+
responseStatusCode: number,
|
|
988
|
+
responseHeaders: Headers,
|
|
989
|
+
remixContext: EntryContext,
|
|
990
|
+
loadContext: IAppLoadContext,
|
|
991
|
+
i18nInstance: i18next,
|
|
992
|
+
) {
|
|
993
|
+
return new Promise((resolve, reject) => {
|
|
994
|
+
let shellRendered = false;
|
|
995
|
+
const slotFillContext = { fills: {} };
|
|
996
|
+
const { modules: clientModules, container, apolloClient: client, store } = loadContext;
|
|
997
|
+
|
|
998
|
+
const { pathname, search, hash } = new URL(request.url);
|
|
999
|
+
store.dispatch({
|
|
1000
|
+
type: LOCATION_CHANGE,
|
|
1001
|
+
payload: { location: { pathname, search, hash }, action: 'POP' },
|
|
1002
|
+
});
|
|
1003
|
+
|
|
1004
|
+
const { pipe, abort } = renderToPipeableStream(
|
|
1005
|
+
(
|
|
1006
|
+
<I18nextProvider i18n={i18nInstance}>
|
|
1007
|
+
<ReduxProvider store={store}>
|
|
1008
|
+
<SlotFillProvider context={slotFillContext}>
|
|
1009
|
+
<InversifyProvider container={container} modules={clientModules as any}>
|
|
1010
|
+
<ApolloProvider client={client}>
|
|
1011
|
+
<RemixServer context={remixContext} url={request.url} />
|
|
1012
|
+
</ApolloProvider>
|
|
1013
|
+
</InversifyProvider>
|
|
1014
|
+
</SlotFillProvider>
|
|
1015
|
+
</ReduxProvider>
|
|
1016
|
+
</I18nextProvider>
|
|
1017
|
+
) as any,
|
|
1018
|
+
{
|
|
1019
|
+
onShellReady() {
|
|
1020
|
+
shellRendered = true;
|
|
1021
|
+
const body = new PassThrough();
|
|
1022
|
+
const stream = createReadableStreamFromReadable(body);
|
|
1023
|
+
const apolloState = { ...client.extract() };
|
|
1024
|
+
const reduxState = { ...store.getState() };
|
|
1025
|
+
const fills = Object.keys(slotFillContext.fills);
|
|
1026
|
+
const styleSheet = '';
|
|
1027
|
+
|
|
1028
|
+
const transform = new ConstantsTransform(fills, apolloState, reduxState, styleSheet);
|
|
1029
|
+
|
|
1030
|
+
responseHeaders.set('Content-Type', 'text/html');
|
|
1031
|
+
|
|
1032
|
+
resolve(
|
|
1033
|
+
new Response(stream, {
|
|
1034
|
+
headers: responseHeaders,
|
|
1035
|
+
status: responseStatusCode,
|
|
1036
|
+
}),
|
|
1037
|
+
);
|
|
1038
|
+
|
|
1039
|
+
pipe(transform).pipe(body);
|
|
1040
|
+
},
|
|
1041
|
+
onShellError(error: unknown) {
|
|
1042
|
+
reject(error);
|
|
1043
|
+
},
|
|
1044
|
+
onError(error: unknown) {
|
|
1045
|
+
responseStatusCode = 500;
|
|
1046
|
+
// Log streaming rendering errors from inside the shell. Don't log
|
|
1047
|
+
// errors encountered during initial shell rendering since they'll
|
|
1048
|
+
// reject and get logged in handleDocumentRequest.
|
|
1049
|
+
if (shellRendered) {
|
|
1050
|
+
console.error(error);
|
|
1051
|
+
}
|
|
1052
|
+
reject(error);
|
|
1053
|
+
},
|
|
1054
|
+
},
|
|
1055
|
+
);
|
|
1056
|
+
|
|
1057
|
+
setTimeout(abort, streamTimeout + 1000);
|
|
1058
|
+
});
|
|
1059
|
+
}
|
|
1060
|
+
```
|
|
1061
|
+
|
|
1062
|
+
### `src/root.tsx`
|
|
1063
|
+
|
|
1064
|
+
```tsx
|
|
1065
|
+
import 'reflect-metadata';
|
|
1066
|
+
import * as React from 'react';
|
|
1067
|
+
import {
|
|
1068
|
+
Links,
|
|
1069
|
+
Meta,
|
|
1070
|
+
Outlet,
|
|
1071
|
+
Scripts,
|
|
1072
|
+
ScrollRestoration,
|
|
1073
|
+
useLoaderData,
|
|
1074
|
+
useRouteError,
|
|
1075
|
+
useRouteLoaderData,
|
|
1076
|
+
data,
|
|
1077
|
+
} from '@remix-run/react';
|
|
1078
|
+
// @ts-ignore
|
|
1079
|
+
import publicEnv from '@src/config/public-config';
|
|
1080
|
+
import { PluginArea } from '@common-stack/client-react';
|
|
1081
|
+
import { subscribeReduxRouter } from '@common-stack/remix-router-redux';
|
|
1082
|
+
import { ApplicationErrorHandler, RemixErrorBoundary as ErrorBoundary } from '@admin-layout/tailwind-ui';
|
|
1083
|
+
// @ts-ignore
|
|
1084
|
+
import clientModules, { plugins } from '@app/frontend-stack-react/modules.js';
|
|
1085
|
+
// @ts-ignore
|
|
1086
|
+
import { useChangeLanguage } from 'remix-i18next/react';
|
|
1087
|
+
import { useTranslation } from 'react-i18next';
|
|
1088
|
+
// @ts-ignore
|
|
1089
|
+
import { i18nextInstance as i18next } from '@app/frontend-stack-react/i18n-localization/i18next.server.js';
|
|
1090
|
+
import { LayoutCookieProvider } from '@admin-layout/client';
|
|
1091
|
+
import { settingsLoaderUtil } from '@admin-layout/client/lib/components/UpdateSettings/UpdateSettings.server';
|
|
1092
|
+
import type { IAppLoadContext } from '@common-stack/client-core';
|
|
1093
|
+
import type { IResourceParams } from '@common-stack/core';
|
|
1094
|
+
import { FillRenderProvider, PluginsLoader } from '@common-stack/components-pro';
|
|
1095
|
+
|
|
1096
|
+
// eslint-disable-next-line import/no-unresolved
|
|
1097
|
+
import styles from '../tailwind.css?url';
|
|
1098
|
+
|
|
1099
|
+
export const links = () => [{ rel: 'stylesheet', href: styles }];
|
|
1100
|
+
|
|
1101
|
+
export const loader = async ({
|
|
1102
|
+
request,
|
|
1103
|
+
context,
|
|
1104
|
+
params,
|
|
1105
|
+
}: {
|
|
1106
|
+
request: Request;
|
|
1107
|
+
context: IAppLoadContext;
|
|
1108
|
+
params: IResourceParams;
|
|
1109
|
+
}) => {
|
|
1110
|
+
// Fetch settings with error handling - don't let settings failures break the app
|
|
1111
|
+
let settingsResponse: any = {};
|
|
1112
|
+
try {
|
|
1113
|
+
settingsResponse =
|
|
1114
|
+
(await settingsLoaderUtil({
|
|
1115
|
+
request,
|
|
1116
|
+
context,
|
|
1117
|
+
params,
|
|
1118
|
+
})) || {};
|
|
1119
|
+
} catch (error) {
|
|
1120
|
+
console.error('❌ Failed to load settings, using defaults:', error);
|
|
1121
|
+
// Continue without settings - the app should still work
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
const [locale] = await Promise.all([i18next.getLocale(request)]);
|
|
1125
|
+
const loadedPlugins = await PluginsLoader(plugins, { request, context, params });
|
|
1126
|
+
return data(
|
|
1127
|
+
{
|
|
1128
|
+
__ENV__: publicEnv,
|
|
1129
|
+
locale,
|
|
1130
|
+
settings: settingsResponse?.settings || {},
|
|
1131
|
+
loadedPlugins,
|
|
1132
|
+
},
|
|
1133
|
+
{
|
|
1134
|
+
headers: [
|
|
1135
|
+
['Cache-Control', 'max-age=300, s-maxage=600'],
|
|
1136
|
+
settingsResponse?.setCookie ? ['Set-Cookie', settingsResponse.setCookie] : null,
|
|
1137
|
+
].filter(Boolean) as [string, string][],
|
|
1138
|
+
},
|
|
1139
|
+
);
|
|
1140
|
+
};
|
|
1141
|
+
|
|
1142
|
+
export const handle = {
|
|
1143
|
+
i18n: ['common', 'translations', 'projects'],
|
|
1144
|
+
};
|
|
1145
|
+
|
|
1146
|
+
export const shouldRevalidate = () => false;
|
|
1147
|
+
|
|
1148
|
+
export function Layout({ children }: { children: React.ReactNode }) {
|
|
1149
|
+
// useLoaderData is for happy paths with Error boundary it will fail
|
|
1150
|
+
// https://github.com/remix-run/remix/issues/8951#issuecomment-1973321870
|
|
1151
|
+
const loaderData = useRouteLoaderData<{ locale: any; __ENV__?: any }>('root');
|
|
1152
|
+
const locale = loaderData?.locale || 'en';
|
|
1153
|
+
|
|
1154
|
+
const { i18n } = useTranslation();
|
|
1155
|
+
|
|
1156
|
+
useChangeLanguage(locale);
|
|
1157
|
+
|
|
1158
|
+
React.useEffect(() => {
|
|
1159
|
+
subscribeReduxRouter({ store: (window as any).__remixStore, router: window.__remixRouter } as any);
|
|
1160
|
+
}, []);
|
|
1161
|
+
|
|
1162
|
+
const getConstants = () => {
|
|
1163
|
+
if (typeof window === 'undefined') {
|
|
1164
|
+
return (
|
|
1165
|
+
<>
|
|
1166
|
+
<script
|
|
1167
|
+
dangerouslySetInnerHTML={{
|
|
1168
|
+
__html: `window.__ENV__ = ${JSON.stringify((loaderData as any)?.__ENV__ || {})}`,
|
|
1169
|
+
}}
|
|
1170
|
+
/>
|
|
1171
|
+
<script
|
|
1172
|
+
src="https://cdnjs.cloudflare.com/ajax/libs/reflect-metadata/0.1.13/Reflect.min.js"
|
|
1173
|
+
integrity="sha512-jvbPH2TH5BSZumEfOJZn9IV+5bSwwN+qG4dvthYe3KCGC3/9HmxZ4phADbt9Pfcp+XSyyfc2vGZ/RMsSUZ9tbQ=="
|
|
1174
|
+
crossOrigin="anonymous"
|
|
1175
|
+
referrerPolicy="no-referrer"
|
|
1176
|
+
></script>
|
|
1177
|
+
<script>window.__APOLLO_STATE__=[__APOLLO_STATE__]</script>
|
|
1178
|
+
<script>window.__PRELOADED_STATE__=[__PRELOADED_STATE__]</script>
|
|
1179
|
+
<script>window.__SLOT_FILLS__=[__SLOT_FILLS__]</script>
|
|
1180
|
+
<script
|
|
1181
|
+
dangerouslySetInnerHTML={{
|
|
1182
|
+
__html: `if (global === undefined) { var global = window; }`,
|
|
1183
|
+
}}
|
|
1184
|
+
/>
|
|
1185
|
+
</>
|
|
1186
|
+
);
|
|
1187
|
+
}
|
|
1188
|
+
return null;
|
|
1189
|
+
};
|
|
1190
|
+
|
|
1191
|
+
return (
|
|
1192
|
+
<html lang={locale} dir={i18n.dir()}>
|
|
1193
|
+
<head>
|
|
1194
|
+
<meta charSet="utf-8" />
|
|
1195
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
1196
|
+
{/* CRITICAL: Load Symbol.observable polyfill BEFORE any other scripts */}
|
|
1197
|
+
<script
|
|
1198
|
+
dangerouslySetInnerHTML={{
|
|
1199
|
+
__html: `
|
|
1200
|
+
(function() {
|
|
1201
|
+
if (typeof Symbol !== 'undefined' && typeof Symbol.for === 'function') {
|
|
1202
|
+
if (!Symbol.observable) {
|
|
1203
|
+
Symbol.observable = Symbol.for('observable');
|
|
1204
|
+
}
|
|
1205
|
+
console.log('[Symbol.observable polyfill] Loaded in head:', Symbol.observable);
|
|
1206
|
+
}
|
|
1207
|
+
})();
|
|
1208
|
+
`,
|
|
1209
|
+
}}
|
|
1210
|
+
/>
|
|
1211
|
+
<Meta />
|
|
1212
|
+
<Links />
|
|
1213
|
+
{typeof window === 'undefined' ? `[__STYLESHEET__]` : ''}
|
|
1214
|
+
</head>
|
|
1215
|
+
<body>
|
|
1216
|
+
<PluginArea />
|
|
1217
|
+
<FillRenderProvider>{clientModules.getWrappedRoot(children)}</FillRenderProvider>
|
|
1218
|
+
<ScrollRestoration />
|
|
1219
|
+
<Scripts />
|
|
1220
|
+
{getConstants()}
|
|
1221
|
+
</body>
|
|
1222
|
+
</html>
|
|
1223
|
+
);
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
export default function App() {
|
|
1227
|
+
return (
|
|
1228
|
+
<ApplicationErrorHandler plugins={plugins}>
|
|
1229
|
+
<LayoutCookieProvider>
|
|
1230
|
+
<Outlet />
|
|
1231
|
+
</LayoutCookieProvider>
|
|
1232
|
+
</ApplicationErrorHandler>
|
|
1233
|
+
);
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
export { ErrorBoundary };
|
|
1237
|
+
```
|
|
1238
|
+
|
|
1239
|
+
---
|
|
1240
|
+
|
|
1241
|
+
**Upgrade Date**: November 2025
|
|
1242
|
+
**Remix Version**: 2.15.3
|
|
1243
|
+
**Branch**: `feat/remix-2.15.3`
|
|
1244
|
+
**Commit**: `690f644d3f112b1c52b709fbc2d77e5181a1e75c`
|
|
1245
|
+
**Status**: ✅ Complete
|