@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,839 @@
|
|
|
1
|
+
# CDEBase GraphQL Development Guide
|
|
2
|
+
|
|
3
|
+
## Introduction to Schema-First Development
|
|
4
|
+
|
|
5
|
+
This guide outlines the complete workflow for developing GraphQL features in the CDEBase Account Module using a schema-first approach with GraphQL Code Generator (codegen). We'll follow the Organization entity as our example throughout each layer of implementation.
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
1. [Schema Definition](#1-schema-definition)
|
|
10
|
+
2. [Type Generation](#2-type-generation)
|
|
11
|
+
3. [Database Models](#3-database-models)
|
|
12
|
+
4. [Repositories](#4-repositories)
|
|
13
|
+
5. [Services](#5-services)
|
|
14
|
+
6. [Templates & Interfaces](#6-templates--interfaces)
|
|
15
|
+
7. [Dependency Injection](#7-dependency-injection)
|
|
16
|
+
8. [Complete Example Walkthrough](#8-complete-example-walkthrough)
|
|
17
|
+
|
|
18
|
+
## 1. Schema Definition
|
|
19
|
+
|
|
20
|
+
Schema-first development starts with defining your GraphQL schema. This is the contract between your client and server.
|
|
21
|
+
|
|
22
|
+
### Key Components in GraphQL Schemas
|
|
23
|
+
|
|
24
|
+
- **Types:** Define the structure of your data
|
|
25
|
+
- **Queries:** Read operations
|
|
26
|
+
- **Mutations:** Write operations
|
|
27
|
+
- **Interfaces:** Shared structures
|
|
28
|
+
- **Enums:** Predefined sets of values
|
|
29
|
+
|
|
30
|
+
### MongoDB-Specific Directives
|
|
31
|
+
|
|
32
|
+
The CDEBase framework uses special directives for MongoDB schema generation:
|
|
33
|
+
|
|
34
|
+
- \`@entity\`: Marks a type as a MongoDB collection
|
|
35
|
+
- \`@entity(embedded: true)\`: Marks a type as an embedded document
|
|
36
|
+
- \`@column\`: Marks a field as a MongoDB column
|
|
37
|
+
- \`@column(overrideType: "type")\`: Specifies MongoDB type override
|
|
38
|
+
|
|
39
|
+
### Example: Organization Schema
|
|
40
|
+
|
|
41
|
+
```graphql
|
|
42
|
+
"""
|
|
43
|
+
Organization: A company or group with members and teams.
|
|
44
|
+
"""
|
|
45
|
+
type Organization @entity {
|
|
46
|
+
"""
|
|
47
|
+
Unique identifier for the organization
|
|
48
|
+
"""
|
|
49
|
+
id: ID! @id
|
|
50
|
+
|
|
51
|
+
"""
|
|
52
|
+
Organization name (used as identifier)
|
|
53
|
+
"""
|
|
54
|
+
name: String! @column
|
|
55
|
+
|
|
56
|
+
"""
|
|
57
|
+
Display title
|
|
58
|
+
"""
|
|
59
|
+
title: String @column
|
|
60
|
+
|
|
61
|
+
"""
|
|
62
|
+
Organization description
|
|
63
|
+
"""
|
|
64
|
+
description: String @column
|
|
65
|
+
|
|
66
|
+
# More fields...
|
|
67
|
+
|
|
68
|
+
"""
|
|
69
|
+
Organization status
|
|
70
|
+
"""
|
|
71
|
+
status: OrganizationStatus @column
|
|
72
|
+
|
|
73
|
+
members: [OrganizationMember] @column(overrideType: "ObjectId[]")
|
|
74
|
+
|
|
75
|
+
# More fields with MongoDB type overrides
|
|
76
|
+
createdAt: DateTime! @column(overrideType: "Date")
|
|
77
|
+
updatedAt: DateTime! @column(overrideType: "Date")
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
# Input types for operations
|
|
81
|
+
input OrganizationCreateRequest {
|
|
82
|
+
name: String
|
|
83
|
+
title: String
|
|
84
|
+
description: String
|
|
85
|
+
# ...other fields
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
# Define queries and mutations
|
|
89
|
+
extend type Query {
|
|
90
|
+
organizations: [Organization] @addAccountContext
|
|
91
|
+
getUserOrganizations(userId: String): [Organization] @addAccountContext
|
|
92
|
+
# ...other queries
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
extend type Mutation {
|
|
96
|
+
createOrganization(organization: OrganizationCreateRequest!): Organization @addAccountContext
|
|
97
|
+
removeOrganization(organization: OrganizationRemoveRequest!): Boolean @addAccountContext
|
|
98
|
+
# ...other mutations
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Common MongoDB Type Overrides
|
|
103
|
+
|
|
104
|
+
- \`ObjectId\`: \`@column(overrideType: "ObjectId")\`
|
|
105
|
+
- \`Date\`: \`@column(overrideType: "Date")\`
|
|
106
|
+
- \`Array of ObjectIds\`: \`@column(overrideType: "[ObjectId]")\`
|
|
107
|
+
- \`Embedded documents\`: \`@column(overrideType: "[EmbeddedType]")\`
|
|
108
|
+
- \`Any type\`: \`@column(overrideType: "any")\`
|
|
109
|
+
|
|
110
|
+
## 2. Type Generation
|
|
111
|
+
|
|
112
|
+
After defining your GraphQL schema, generate TypeScript types using GraphQL Code Generator.
|
|
113
|
+
|
|
114
|
+
### Configuration in codegen.ts
|
|
115
|
+
|
|
116
|
+
The project uses a configuration file at the root called \`codegen.ts\`:
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
const config = {
|
|
120
|
+
overwrite: true,
|
|
121
|
+
schema: [
|
|
122
|
+
// Schema locations...
|
|
123
|
+
'packages-modules/account-api/server/src/**/*.graphql',
|
|
124
|
+
// More locations...
|
|
125
|
+
],
|
|
126
|
+
generates: {
|
|
127
|
+
'packages/common/src/generated/generated-models.ts': {
|
|
128
|
+
// Configurations...
|
|
129
|
+
plugins: [
|
|
130
|
+
'typescript',
|
|
131
|
+
'typescript-operations',
|
|
132
|
+
'typescript-resolvers',
|
|
133
|
+
'typescript-mongodb', // MongoDB specific generation
|
|
134
|
+
],
|
|
135
|
+
config: {
|
|
136
|
+
dbTypeSuffix: 'Model', // Adds 'Model' suffix to DB types
|
|
137
|
+
typesPrefix: 'I', // Adds 'I' prefix to interfaces
|
|
138
|
+
// More config options...
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Running Type Generation
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
yarn generateGraphql
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
This generates TypeScript interfaces in \`packages/common/src/generated/generated-models.ts\`, which are then used throughout the application.
|
|
152
|
+
|
|
153
|
+
### Generated Types for Organization
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
// Generated from GraphQL schema
|
|
157
|
+
export interface IOrganizationModel {
|
|
158
|
+
__typename?: 'Organization';
|
|
159
|
+
id: string;
|
|
160
|
+
name: string;
|
|
161
|
+
title?: Maybe<string>;
|
|
162
|
+
description?: Maybe<string>;
|
|
163
|
+
members?: Maybe<Array<Maybe<IOrganizationMemberModel>>>;
|
|
164
|
+
status?: Maybe<OrganizationStatus>;
|
|
165
|
+
createdAt: Date;
|
|
166
|
+
updatedAt: Date;
|
|
167
|
+
// Additional fields...
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## 3. Database Models
|
|
172
|
+
|
|
173
|
+
With the generated types, create Mongoose models in \`store/models/\`.
|
|
174
|
+
|
|
175
|
+
### Organization Model Example
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
// packages-modules/account-api/server/src/store/models/organization-model.ts
|
|
179
|
+
import { Schema, Connection } from 'mongoose';
|
|
180
|
+
import { IOrganizationModel, OrganizationStatus } from 'common/server';
|
|
181
|
+
|
|
182
|
+
const OrganizationSchema = new Schema<IOrganizationModel>({
|
|
183
|
+
name: { type: Schema.Types.String, unique: true, required: true, index: true },
|
|
184
|
+
title: { type: Schema.Types.String },
|
|
185
|
+
description: { type: Schema.Types.String },
|
|
186
|
+
members: [{ type: Schema.Types.ObjectId, ref: 'organizationMember' }],
|
|
187
|
+
createdAt: { type: Schema.Types.Date, default: Date.now },
|
|
188
|
+
updatedAt: { type: Schema.Types.Date, default: Date.now },
|
|
189
|
+
status: {
|
|
190
|
+
type: Schema.Types.String,
|
|
191
|
+
enum: Object.values(OrganizationStatus),
|
|
192
|
+
default: OrganizationStatus.Active,
|
|
193
|
+
index: true,
|
|
194
|
+
},
|
|
195
|
+
// Other fields...
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// Add virtual property for 'id'
|
|
199
|
+
OrganizationSchema.virtual('id').get(function () {
|
|
200
|
+
return (this as any)._id.toHexString();
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
// Configure JSON serialization
|
|
204
|
+
OrganizationSchema.set('toJSON', { virtuals: true });
|
|
205
|
+
OrganizationSchema.set('toObject', { virtuals: true });
|
|
206
|
+
|
|
207
|
+
// Export a function that creates and returns the model
|
|
208
|
+
export const OrganizationModelFunc = (db: Connection) => db.model('organization', OrganizationSchema);
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Key Points for Models
|
|
212
|
+
|
|
213
|
+
1. Use the generated interfaces (\`IOrganizationModel\`) directly
|
|
214
|
+
2. Define schema using Mongoose's \`Schema.Types.\*\` syntax
|
|
215
|
+
3. Add virtual \`id\` property that maps to MongoDB's \`\_id\`
|
|
216
|
+
4. Configure proper serialization with \`toJSON\` and \`toObject\`
|
|
217
|
+
5. Export a function that takes a \`Connection\` and returns the compiled model
|
|
218
|
+
|
|
219
|
+
## 4. Repositories
|
|
220
|
+
|
|
221
|
+
Repositories handle data access logic and extend \`BaseRepository\` from \`@common-stack/store-mongo\`.
|
|
222
|
+
|
|
223
|
+
### Repository Interface
|
|
224
|
+
|
|
225
|
+
First, define the repository interface in \`templates/repositories/\`:
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
// packages-modules/account-api/server/src/templates/repositories/OrganizationRepository.ts.template
|
|
229
|
+
import {
|
|
230
|
+
ApplicationRoles,
|
|
231
|
+
IOrganizationCreateRequest,
|
|
232
|
+
IOrganizationModel,
|
|
233
|
+
IBaseMongoRepository,
|
|
234
|
+
// More imports...
|
|
235
|
+
} from 'common/server';
|
|
236
|
+
|
|
237
|
+
export interface IOrganizationRepository extends IBaseMongoRepository<IOrganizationModel> {
|
|
238
|
+
/**
|
|
239
|
+
* Creates a new organization
|
|
240
|
+
*
|
|
241
|
+
* @param {IOrganizationCreateRequest} organization - Organization creation parameters
|
|
242
|
+
* @returns {Promise<AsDomainType<IOrganizationModel>>} The created organization
|
|
243
|
+
*/
|
|
244
|
+
createOrganization(organization: IOrganizationCreateRequest): Promise<AsDomainType<IOrganizationModel>>;
|
|
245
|
+
|
|
246
|
+
// Additional methods with detailed documentation...
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Repository Implementation
|
|
251
|
+
|
|
252
|
+
Then implement the repository in \`store/repositories/\`:
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
// packages-modules/account-api/server/src/store/repositories/organization-repository.ts
|
|
256
|
+
import { CdmLogger } from '@cdm-logger/core';
|
|
257
|
+
import { inject, injectable, optional } from 'inversify';
|
|
258
|
+
import { BaseMongoRepository } from '@common-stack/store-mongo';
|
|
259
|
+
import mongoose, { Types } from 'mongoose';
|
|
260
|
+
import {
|
|
261
|
+
IOrganizationRepository,
|
|
262
|
+
IOrganizationModel,
|
|
263
|
+
// More imports...
|
|
264
|
+
} from 'common/server';
|
|
265
|
+
import { OrganizationModelFunc } from '../models';
|
|
266
|
+
|
|
267
|
+
@injectable()
|
|
268
|
+
export class OrganizationRepository extends BaseMongoRepository<IOrganizationModel> implements IOrganizationRepository {
|
|
269
|
+
constructor(
|
|
270
|
+
@inject('MongoDBConnection')
|
|
271
|
+
db: mongoose.Connection,
|
|
272
|
+
@inject('Logger')
|
|
273
|
+
logger: CdmLogger.ILogger,
|
|
274
|
+
@inject('MongoOptions')
|
|
275
|
+
@optional()
|
|
276
|
+
options?: any,
|
|
277
|
+
) {
|
|
278
|
+
super(OrganizationModelFunc, db, logger, options);
|
|
279
|
+
this.logger = logger.child({ className: 'OrganizationRepository' });
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
public async createOrganization(
|
|
283
|
+
newOrganization: IOrganizationCreateRequest,
|
|
284
|
+
): Promise<AsDomainType<IOrganizationModel>> {
|
|
285
|
+
this.logger.trace('createOrganization with params (%j)', newOrganization);
|
|
286
|
+
const result = await this.model.create(newOrganization);
|
|
287
|
+
return (result as AsDomainType<IOrganizationModel>) || null;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Implement additional methods...
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Key Points for Repositories
|
|
295
|
+
|
|
296
|
+
1. Use \`@injectable()\` to enable dependency injection
|
|
297
|
+
2. Extend \`BaseMongoRepository<IOrganizationModel>\`
|
|
298
|
+
3. Pass the model function to the super constructor
|
|
299
|
+
4. Use appropriate logging with child logger
|
|
300
|
+
5. Keep repositories focused on data access only (no business logic)
|
|
301
|
+
6. Use \`AsDomainType<T>\` for return types to ensure proper typing
|
|
302
|
+
|
|
303
|
+
## 5. Services
|
|
304
|
+
|
|
305
|
+
Services contain business logic and orchestrate operations across repositories.
|
|
306
|
+
|
|
307
|
+
### Service Interface
|
|
308
|
+
|
|
309
|
+
First, define the service interface in \`templates/services/\`:
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
// packages-modules/account-api/server/src/templates/services/OrganizationService.ts.template
|
|
313
|
+
import {
|
|
314
|
+
IOrganizationModel,
|
|
315
|
+
IOrganizationCreateRequest,
|
|
316
|
+
IBaseService,
|
|
317
|
+
// More imports...
|
|
318
|
+
} from 'common/server';
|
|
319
|
+
|
|
320
|
+
export interface IOrganizationService extends IBaseService<IOrganizationModel> {
|
|
321
|
+
/**
|
|
322
|
+
* Creates a new organization
|
|
323
|
+
*
|
|
324
|
+
* @param organization - Organization creation request
|
|
325
|
+
* @param userContext - User context
|
|
326
|
+
* @returns The created organization
|
|
327
|
+
*/
|
|
328
|
+
createOrganization(
|
|
329
|
+
organization: IOrganizationCreateRequest,
|
|
330
|
+
userContext?: IUserContext,
|
|
331
|
+
): Promise<AsDomainType<IOrganizationModel>>;
|
|
332
|
+
|
|
333
|
+
// Additional methods with detailed documentation...
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Service Implementation
|
|
338
|
+
|
|
339
|
+
Then implement the service in \`services/\`:
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
// packages-modules/account-api/server/src/services/OrganizationService.ts
|
|
343
|
+
import { inject, injectable } from 'inversify';
|
|
344
|
+
import { CdmLogger } from '@cdm-logger/core';
|
|
345
|
+
import { BaseService2 } from '@common-stack/store-mongo';
|
|
346
|
+
import {
|
|
347
|
+
IOrganizationService,
|
|
348
|
+
IOrganizationModel,
|
|
349
|
+
SERVER_TYPES,
|
|
350
|
+
// More imports...
|
|
351
|
+
} from 'common/server';
|
|
352
|
+
|
|
353
|
+
@injectable()
|
|
354
|
+
export class OrganizationService2 extends BaseService2<IOrganizationModel> implements IOrganizationService {
|
|
355
|
+
private logger: CdmLogger.ILogger;
|
|
356
|
+
|
|
357
|
+
constructor(
|
|
358
|
+
@inject(SERVER_TYPES.IOrganizationRepository)
|
|
359
|
+
protected organizationRepository: IOrganizationRepository,
|
|
360
|
+
@inject(SERVER_TYPES.IAccountRepository)
|
|
361
|
+
protected accountRepository: IAccountRepository,
|
|
362
|
+
@inject('Logger')
|
|
363
|
+
logger: CdmLogger.ILogger,
|
|
364
|
+
// Other dependencies...
|
|
365
|
+
) {
|
|
366
|
+
super(organizationRepository);
|
|
367
|
+
this.logger = logger.child({ className: 'OrganizationService2' });
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
public async createOrganization(
|
|
371
|
+
organization: IOrganizationCreateRequest,
|
|
372
|
+
userContext?: IUserContext,
|
|
373
|
+
): Promise<AsDomainType<IOrganizationModel>> {
|
|
374
|
+
try {
|
|
375
|
+
if (!organization.name) {
|
|
376
|
+
throw new Error('Organization name is required');
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
const createdOrganization = await this.organizationRepository.createOrganization(organization);
|
|
380
|
+
|
|
381
|
+
if (!createdOrganization) {
|
|
382
|
+
throw new Error('Failed to create organization');
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
if (userContext) {
|
|
386
|
+
// Add the creating user as a member with Owner role
|
|
387
|
+
await this.addOrgMember(createdOrganization.name, userContext.accountId, [ApplicationRoles.Owner]);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// Fire creation event if needed
|
|
391
|
+
// this.onOrganizationCreated.fire({ ... });
|
|
392
|
+
|
|
393
|
+
return createdOrganization;
|
|
394
|
+
} catch (error) {
|
|
395
|
+
this.logger.error('Error creating organization: %o', error?.message);
|
|
396
|
+
throw error;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Implement additional methods...
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### Key Points for Services
|
|
405
|
+
|
|
406
|
+
1. Use \`@injectable()\` to enable dependency injection
|
|
407
|
+
2. Extend \`BaseService2<IOrganizationModel>\`
|
|
408
|
+
3. Inject repositories and other dependencies
|
|
409
|
+
4. Include proper error handling and logging
|
|
410
|
+
5. Implement business logic and orchestration between repositories
|
|
411
|
+
6. Use \`try/catch\` blocks to handle errors gracefully
|
|
412
|
+
|
|
413
|
+
## 6. Templates & Interfaces
|
|
414
|
+
|
|
415
|
+
Templates define contracts for repositories and services, ensuring consistent implementation.
|
|
416
|
+
|
|
417
|
+
### Organization Repository Template
|
|
418
|
+
|
|
419
|
+
```typescript
|
|
420
|
+
// packages-modules/account-api/server/src/templates/repositories/OrganizationRepository.ts.template
|
|
421
|
+
export interface IOrganizationRepository extends IBaseMongoRepository<IOrganizationModel> {
|
|
422
|
+
// Method signatures with detailed documentation
|
|
423
|
+
createOrganization(organization: IOrganizationCreateRequest): Promise<AsDomainType<IOrganizationModel>>;
|
|
424
|
+
findOrganizationById(id: string): Promise<AsDomainType<IOrganizationModel> | null>;
|
|
425
|
+
// More methods...
|
|
426
|
+
}
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### Organization Service Template
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
// packages-modules/account-api/server/src/templates/services/OrganizationService.ts.template
|
|
433
|
+
export interface IOrganizationService extends IBaseService<IOrganizationModel> {
|
|
434
|
+
// Method signatures with detailed documentation
|
|
435
|
+
createOrganization(
|
|
436
|
+
organization: IOrganizationCreateRequest,
|
|
437
|
+
userContext?: IUserContext,
|
|
438
|
+
): Promise<AsDomainType<IOrganizationModel>>;
|
|
439
|
+
// More methods...
|
|
440
|
+
}
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
### Constants Template for Dependency Injection
|
|
444
|
+
|
|
445
|
+
```typescript
|
|
446
|
+
// packages-modules/account-api/server/src/templates/constants/SERVER_TYPES.ts.template
|
|
447
|
+
export const SERVER_TYPES = {
|
|
448
|
+
IOrganizationRepository: Symbol('IOrganizationRepository'),
|
|
449
|
+
IOrganizationService: Symbol('IOrganizationService'),
|
|
450
|
+
// More symbols...
|
|
451
|
+
};
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
## 7. Dependency Injection
|
|
455
|
+
|
|
456
|
+
CDEBase uses InversifyJS for dependency injection.
|
|
457
|
+
|
|
458
|
+
### Container Module
|
|
459
|
+
|
|
460
|
+
```typescript
|
|
461
|
+
// packages-modules/account-api/server/src/containers/module.ts
|
|
462
|
+
import { ContainerModule, interfaces } from 'inversify';
|
|
463
|
+
import { SERVER_TYPES } from 'common/server';
|
|
464
|
+
import { OrganizationRepository } from '../store/repositories/organization-repository';
|
|
465
|
+
import { OrganizationService2 } from '../services/OrganizationService';
|
|
466
|
+
|
|
467
|
+
export const accountsModule = new ContainerModule((bind: interfaces.Bind) => {
|
|
468
|
+
// Bind repositories
|
|
469
|
+
bind(SERVER_TYPES.IOrganizationRepository).to(OrganizationRepository).inSingletonScope();
|
|
470
|
+
|
|
471
|
+
// Bind services
|
|
472
|
+
bind(SERVER_TYPES.IOrganizationService).to(OrganizationService2).inSingletonScope();
|
|
473
|
+
|
|
474
|
+
// More bindings...
|
|
475
|
+
});
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
## 8. Complete Example Walkthrough
|
|
479
|
+
|
|
480
|
+
Let's walk through creating a complete feature, from schema to service:
|
|
481
|
+
|
|
482
|
+
### 1. Define the GraphQL Schema
|
|
483
|
+
|
|
484
|
+
```graphql
|
|
485
|
+
# packages-modules/account-api/server/src/graphql/schema/organization.graphql
|
|
486
|
+
"""
|
|
487
|
+
Organization: A company or group with members and teams.
|
|
488
|
+
"""
|
|
489
|
+
type Organization @entity {
|
|
490
|
+
id: ID! @id
|
|
491
|
+
name: String! @column
|
|
492
|
+
title: String @column
|
|
493
|
+
description: String @column
|
|
494
|
+
members: [OrganizationMember] @column(overrideType: "ObjectId[]")
|
|
495
|
+
createdAt: DateTime! @column(overrideType: "Date")
|
|
496
|
+
updatedAt: DateTime! @column(overrideType: "Date")
|
|
497
|
+
status: OrganizationStatus @column
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
input OrganizationCreateRequest {
|
|
501
|
+
name: String
|
|
502
|
+
title: String
|
|
503
|
+
description: String
|
|
504
|
+
# More fields...
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
extend type Query {
|
|
508
|
+
organizations: [Organization] @addAccountContext
|
|
509
|
+
getOrganizationDetail(where: OrgDetailWhere!): Organization!
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
extend type Mutation {
|
|
513
|
+
createOrganization(organization: OrganizationCreateRequest!): Organization @addAccountContext
|
|
514
|
+
}
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
### 2. Generate TypeScript Types
|
|
518
|
+
|
|
519
|
+
Run the code generator:
|
|
520
|
+
|
|
521
|
+
```bash
|
|
522
|
+
yarn generateGraphql
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
This generates TypeScript interfaces in \`packages/common/src/generated/generated-models.ts\`:
|
|
526
|
+
|
|
527
|
+
```typescript
|
|
528
|
+
export interface IOrganizationModel {
|
|
529
|
+
id: string;
|
|
530
|
+
name: string;
|
|
531
|
+
title?: Maybe<string>;
|
|
532
|
+
description?: Maybe<string>;
|
|
533
|
+
members?: Maybe<Array<Maybe<IOrganizationMemberModel>>>;
|
|
534
|
+
createdAt: Date;
|
|
535
|
+
updatedAt: Date;
|
|
536
|
+
status?: Maybe<OrganizationStatus>;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
export interface IOrganizationCreateRequest {
|
|
540
|
+
name?: Maybe<string>;
|
|
541
|
+
title?: Maybe<string>;
|
|
542
|
+
description?: Maybe<string>;
|
|
543
|
+
// More fields...
|
|
544
|
+
}
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
### 3. Create the Mongoose Model
|
|
548
|
+
|
|
549
|
+
```typescript
|
|
550
|
+
// packages-modules/account-api/server/src/store/models/organization-model.ts
|
|
551
|
+
import { Schema, Connection } from 'mongoose';
|
|
552
|
+
import { IOrganizationModel, OrganizationStatus } from 'common/server';
|
|
553
|
+
|
|
554
|
+
const OrganizationSchema = new Schema<IOrganizationModel>({
|
|
555
|
+
name: { type: Schema.Types.String, unique: true, required: true, index: true },
|
|
556
|
+
title: { type: Schema.Types.String },
|
|
557
|
+
description: { type: Schema.Types.String },
|
|
558
|
+
members: [{ type: Schema.Types.ObjectId, ref: 'organizationMember' }],
|
|
559
|
+
createdAt: { type: Schema.Types.Date, default: Date.now },
|
|
560
|
+
updatedAt: { type: Schema.Types.Date, default: Date.now },
|
|
561
|
+
status: {
|
|
562
|
+
type: Schema.Types.String,
|
|
563
|
+
enum: Object.values(OrganizationStatus),
|
|
564
|
+
default: OrganizationStatus.Active,
|
|
565
|
+
},
|
|
566
|
+
});
|
|
567
|
+
|
|
568
|
+
OrganizationSchema.virtual('id').get(function () {
|
|
569
|
+
return (this as any)._id.toHexString();
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
OrganizationSchema.set('toJSON', { virtuals: true });
|
|
573
|
+
OrganizationSchema.set('toObject', { virtuals: true });
|
|
574
|
+
|
|
575
|
+
export const OrganizationModelFunc = (db: Connection) => db.model('organization', OrganizationSchema);
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
### 4. Define the Repository Interface
|
|
579
|
+
|
|
580
|
+
```typescript
|
|
581
|
+
// packages-modules/account-api/server/src/templates/repositories/OrganizationRepository.ts.template
|
|
582
|
+
import { IOrganizationCreateRequest, IOrganizationModel, IBaseMongoRepository, AsDomainType } from 'common/server';
|
|
583
|
+
|
|
584
|
+
export interface IOrganizationRepository extends IBaseMongoRepository<IOrganizationModel> {
|
|
585
|
+
createOrganization(organization: IOrganizationCreateRequest): Promise<AsDomainType<IOrganizationModel>>;
|
|
586
|
+
findOrganizationById(id: string): Promise<AsDomainType<IOrganizationModel> | null>;
|
|
587
|
+
findOrganizationByName(orgName: string): Promise<AsDomainType<IOrganizationModel> | null>;
|
|
588
|
+
// More methods...
|
|
589
|
+
}
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
### 5. Implement the Repository
|
|
593
|
+
|
|
594
|
+
```typescript
|
|
595
|
+
// packages-modules/account-api/server/src/store/repositories/organization-repository.ts
|
|
596
|
+
import { CdmLogger } from '@cdm-logger/core';
|
|
597
|
+
import { inject, injectable, optional } from 'inversify';
|
|
598
|
+
import { BaseMongoRepository } from '@common-stack/store-mongo';
|
|
599
|
+
import mongoose, { Types } from 'mongoose';
|
|
600
|
+
import { IOrganizationRepository, IOrganizationModel, IOrganizationCreateRequest, AsDomainType } from 'common/server';
|
|
601
|
+
import { OrganizationModelFunc } from '../models';
|
|
602
|
+
|
|
603
|
+
@injectable()
|
|
604
|
+
export class OrganizationRepository extends BaseMongoRepository<IOrganizationModel> implements IOrganizationRepository {
|
|
605
|
+
constructor(
|
|
606
|
+
@inject('MongoDBConnection')
|
|
607
|
+
db: mongoose.Connection,
|
|
608
|
+
@inject('Logger')
|
|
609
|
+
logger: CdmLogger.ILogger,
|
|
610
|
+
@inject('MongoOptions')
|
|
611
|
+
@optional()
|
|
612
|
+
options?: any,
|
|
613
|
+
) {
|
|
614
|
+
super(OrganizationModelFunc, db, logger, options);
|
|
615
|
+
this.logger = logger.child({ className: 'OrganizationRepository' });
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
public async createOrganization(
|
|
619
|
+
newOrganization: IOrganizationCreateRequest,
|
|
620
|
+
): Promise<AsDomainType<IOrganizationModel>> {
|
|
621
|
+
this.logger.trace('createOrganization with params (%j)', newOrganization);
|
|
622
|
+
const result = await this.model.create(newOrganization);
|
|
623
|
+
return (result as AsDomainType<IOrganizationModel>) || null;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
public async findOrganizationByName(orgName: string) {
|
|
627
|
+
const result = await this.model.findOne({ name: orgName }).exec();
|
|
628
|
+
return result?.toObject<AsDomainType<IOrganizationModel>>() || null;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
public async findOrganizationById(id: string) {
|
|
632
|
+
try {
|
|
633
|
+
if (!Types.ObjectId.isValid(id)) {
|
|
634
|
+
throw new Error('Invalid organization ID format');
|
|
635
|
+
}
|
|
636
|
+
const objectId = new Types.ObjectId(id);
|
|
637
|
+
const result = await this.model.findById(objectId).exec();
|
|
638
|
+
return (result as AsDomainType<IOrganizationModel>) || null;
|
|
639
|
+
} catch (error) {
|
|
640
|
+
this.logger.error('Error finding organization by ID:', error);
|
|
641
|
+
throw error;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
// Implement additional methods...
|
|
646
|
+
}
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
### 6. Define the Service Interface
|
|
650
|
+
|
|
651
|
+
```typescript
|
|
652
|
+
// packages-modules/account-api/server/src/templates/services/OrganizationService.ts.template
|
|
653
|
+
import {
|
|
654
|
+
IOrganizationModel,
|
|
655
|
+
IOrganizationCreateRequest,
|
|
656
|
+
IBaseService,
|
|
657
|
+
IUserContext,
|
|
658
|
+
AsDomainType,
|
|
659
|
+
} from 'common/server';
|
|
660
|
+
|
|
661
|
+
export interface IOrganizationService extends IBaseService<IOrganizationModel> {
|
|
662
|
+
createOrganization(
|
|
663
|
+
organization: IOrganizationCreateRequest,
|
|
664
|
+
userContext?: IUserContext,
|
|
665
|
+
): Promise<AsDomainType<IOrganizationModel>>;
|
|
666
|
+
|
|
667
|
+
getOrganization(id: string): Promise<AsDomainType<IOrganizationModel>>;
|
|
668
|
+
getOrganizationByName(name: string): Promise<AsDomainType<IOrganizationModel> | null>;
|
|
669
|
+
// More methods...
|
|
670
|
+
}
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
### 7. Implement the Service
|
|
674
|
+
|
|
675
|
+
```typescript
|
|
676
|
+
// packages-modules/account-api/server/src/services/OrganizationService.ts
|
|
677
|
+
import { inject, injectable } from 'inversify';
|
|
678
|
+
import { CdmLogger } from '@cdm-logger/core';
|
|
679
|
+
import { BaseService2 } from '@common-stack/store-mongo';
|
|
680
|
+
import {
|
|
681
|
+
IOrganizationService,
|
|
682
|
+
IOrganizationModel,
|
|
683
|
+
IOrganizationCreateRequest,
|
|
684
|
+
IUserContext,
|
|
685
|
+
SERVER_TYPES,
|
|
686
|
+
IOrganizationRepository,
|
|
687
|
+
AsDomainType,
|
|
688
|
+
ApplicationRoles,
|
|
689
|
+
} from 'common/server';
|
|
690
|
+
|
|
691
|
+
@injectable()
|
|
692
|
+
export class OrganizationService2 extends BaseService2<IOrganizationModel> implements IOrganizationService {
|
|
693
|
+
private logger: CdmLogger.ILogger;
|
|
694
|
+
|
|
695
|
+
constructor(
|
|
696
|
+
@inject(SERVER_TYPES.IOrganizationRepository)
|
|
697
|
+
protected organizationRepository: IOrganizationRepository,
|
|
698
|
+
@inject('Logger')
|
|
699
|
+
logger: CdmLogger.ILogger,
|
|
700
|
+
) {
|
|
701
|
+
super(organizationRepository);
|
|
702
|
+
this.logger = logger.child({ className: 'OrganizationService2' });
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
public async createOrganization(
|
|
706
|
+
organization: IOrganizationCreateRequest,
|
|
707
|
+
userContext?: IUserContext,
|
|
708
|
+
): Promise<AsDomainType<IOrganizationModel>> {
|
|
709
|
+
try {
|
|
710
|
+
if (!organization.name) {
|
|
711
|
+
throw new Error('Organization name is required');
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
const createdOrganization = await this.organizationRepository.createOrganization(organization);
|
|
715
|
+
|
|
716
|
+
if (!createdOrganization) {
|
|
717
|
+
throw new Error('Failed to create organization');
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
if (userContext) {
|
|
721
|
+
// Add the creating user as a member with Owner role
|
|
722
|
+
await this.addOrgMember(createdOrganization.name, userContext.accountId, [ApplicationRoles.Owner]);
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
return createdOrganization;
|
|
726
|
+
} catch (error) {
|
|
727
|
+
this.logger.error('Error creating organization: %o', error?.message);
|
|
728
|
+
throw error;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
public async getOrganization(id: string): Promise<AsDomainType<IOrganizationModel>> {
|
|
733
|
+
try {
|
|
734
|
+
const organization = await this.organizationRepository.findOrganizationById(id);
|
|
735
|
+
|
|
736
|
+
if (!organization) {
|
|
737
|
+
throw new Error(\`Organization with ID \${id} not found\`);
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
return organization;
|
|
741
|
+
} catch (error) {
|
|
742
|
+
this.logger.error('Error getting organization: %o', error);
|
|
743
|
+
throw error;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
public async getOrganizationByName(name: string): Promise<AsDomainType<IOrganizationModel> | null> {
|
|
748
|
+
try {
|
|
749
|
+
if (!name) {
|
|
750
|
+
this.logger.warn('Empty organization name provided');
|
|
751
|
+
return null;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
return await this.organizationRepository.findOrganizationByName(name);
|
|
755
|
+
} catch (error) {
|
|
756
|
+
this.logger.error('Error getting organization by name: %o', error);
|
|
757
|
+
return null;
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
// Implement additional methods...
|
|
762
|
+
}
|
|
763
|
+
```
|
|
764
|
+
|
|
765
|
+
### 8. Register in the Dependency Injection Container
|
|
766
|
+
|
|
767
|
+
```typescript
|
|
768
|
+
// packages-modules/account-api/server/src/containers/module.ts
|
|
769
|
+
import { ContainerModule, interfaces } from 'inversify';
|
|
770
|
+
import { SERVER_TYPES } from 'common/server';
|
|
771
|
+
import { OrganizationRepository } from '../store/repositories/organization-repository';
|
|
772
|
+
import { OrganizationService2 } from '../services/OrganizationService';
|
|
773
|
+
|
|
774
|
+
export const accountsModule = new ContainerModule((bind: interfaces.Bind) => {
|
|
775
|
+
// Bind repositories
|
|
776
|
+
bind(SERVER_TYPES.IOrganizationRepository).to(OrganizationRepository).inSingletonScope();
|
|
777
|
+
|
|
778
|
+
// Bind services
|
|
779
|
+
bind(SERVER_TYPES.IOrganizationService).to(OrganizationService2).inSingletonScope();
|
|
780
|
+
});
|
|
781
|
+
```
|
|
782
|
+
|
|
783
|
+
### 9. Create GraphQL Resolvers
|
|
784
|
+
|
|
785
|
+
```typescript
|
|
786
|
+
// packages-modules/account-api/server/src/graphql/resolvers/organization-resolver.ts
|
|
787
|
+
import { IResolvers } from 'common/server';
|
|
788
|
+
|
|
789
|
+
export const resolvers: IResolvers = {
|
|
790
|
+
Query: {
|
|
791
|
+
organizations: async (_, args, context) => {
|
|
792
|
+
return context.organizationService.getAll();
|
|
793
|
+
},
|
|
794
|
+
getOrganizationDetail: async (_, { where }, context) => {
|
|
795
|
+
if (where.id) {
|
|
796
|
+
return context.organizationService.getOrganization(where.id);
|
|
797
|
+
} else if (where.name) {
|
|
798
|
+
const org = await context.organizationService.getOrganizationByName(where.name);
|
|
799
|
+
if (!org) {
|
|
800
|
+
throw new Error(\`Organization \${where.name} not found\`);
|
|
801
|
+
}
|
|
802
|
+
return org;
|
|
803
|
+
}
|
|
804
|
+
throw new Error('Either id or name must be provided');
|
|
805
|
+
},
|
|
806
|
+
},
|
|
807
|
+
Mutation: {
|
|
808
|
+
createOrganization: async (_, { organization }, context) => {
|
|
809
|
+
return context.organizationService.createOrganization(
|
|
810
|
+
organization,
|
|
811
|
+
context.userContext
|
|
812
|
+
);
|
|
813
|
+
},
|
|
814
|
+
},
|
|
815
|
+
};
|
|
816
|
+
```
|
|
817
|
+
|
|
818
|
+
## Conclusion
|
|
819
|
+
|
|
820
|
+
Following this schema-first approach with GraphQL and codegen streamlines your development process in the CDEBase Account Module:
|
|
821
|
+
|
|
822
|
+
1. Define GraphQL schema with MongoDB directives
|
|
823
|
+
2. Generate TypeScript types with \`yarn generateGraphql\`
|
|
824
|
+
3. Create Mongoose models using the generated interfaces
|
|
825
|
+
4. Define repository interfaces in templates
|
|
826
|
+
5. Implement repositories extending BaseMongoRepository
|
|
827
|
+
6. Define service interfaces in templates
|
|
828
|
+
7. Implement services extending BaseService
|
|
829
|
+
8. Register in the dependency injection container
|
|
830
|
+
9. Create GraphQL resolvers that use your services
|
|
831
|
+
|
|
832
|
+
This approach ensures type safety throughout your application, from GraphQL schemas to MongoDB models to service implementations, maintaining a consistent contract between your API and data layers.`;
|
|
833
|
+
|
|
834
|
+
// Create blob and download
|
|
835
|
+
const blob = new Blob([markdownContent], { type: 'text/markdown' });
|
|
836
|
+
const url = window.URL.createObjectURL(blob);
|
|
837
|
+
const a = document.createElement('a');
|
|
838
|
+
a.href = url;
|
|
839
|
+
a.download =
|