diff --git a/example/src/docs/recipes/custom_datasource/custom_datasource.tsx b/example/src/docs/recipes/custom_datasource/custom_datasource.tsx new file mode 100644 index 000000000..5f4b0a426 --- /dev/null +++ b/example/src/docs/recipes/custom_datasource/custom_datasource.tsx @@ -0,0 +1,67 @@ +import { + CMSType, + DataSource, + DeleteEntityProps, + Entity, + FetchCollectionProps, + FetchEntityProps, + ResolvedProperty, + SaveEntityProps, + useFirestoreDataSource +} from "firecms"; +import { FirebaseApp } from "firebase/app"; + +type CustomDataSourceProps = { firebaseApp?: FirebaseApp }; + +/** + * This is an example of a custom data source. + * It is a React Hook that returns a {@link DataSource} object. + * @param firebaseApp + */ +export function useCustomDatasource({ firebaseApp }: CustomDataSourceProps): DataSource { + + const firestoreDataSource = useFirestoreDataSource({ + firebaseApp + }); + + return { + fetchCollection(props: FetchCollectionProps): Promise[]> { + if (props.path === "your_path_custom") { + // make your custom http call and return your Entities + } + return firestoreDataSource.fetchCollection(props); + }, + fetchEntity(props: FetchEntityProps): Promise | undefined> { + if (props.path === "your_path_custom") { + // make your custom http call and return your Entities + } + return firestoreDataSource.fetchEntity(props); + }, + saveEntity(props: SaveEntityProps): Promise> { + if (props.path === "your_path_custom") { + // make your custom http call and return your Entities + } + return firestoreDataSource.saveEntity(props); + }, + deleteEntity(props: DeleteEntityProps): Promise { + return firestoreDataSource.deleteEntity(props); + }, + checkUniqueField(path: string, name: string, value: any, property: ResolvedProperty, entityId?: string): Promise { + return firestoreDataSource.checkUniqueField(path, name, value, property, entityId); + }, + generateEntityId(path: string) { + return firestoreDataSource.generateEntityId(path); + }, + countEntities(path: string): Promise { + return firestoreDataSource.countEntities(path); + } + } +} diff --git a/lib/src/core/FireCMS.tsx b/lib/src/core/FireCMS.tsx index 339fe0465..761d7fb94 100644 --- a/lib/src/core/FireCMS.tsx +++ b/lib/src/core/FireCMS.tsx @@ -20,8 +20,7 @@ import { import { FireCMSContextInstance, useFireCMSContext, - useModeController, - useSnackbarController + useModeController } from "../hooks"; import { CenteredView, ErrorView } from "./components"; import { StorageSourceContext } from "./contexts/StorageSourceContext"; @@ -44,10 +43,15 @@ const DEFAULT_COLLECTION_PATH = "/c"; * If you are using independent components of the CMS * you need to wrap them with this main component, so the internal hooks work. * + * This is the main component of FireCMS. It acts as the provider of all the + * internal contexts and hooks. + * + * You only need to use this component if you are building a custom app. + * In most cases you can just use the {@link FirebaseCMSApp} component. + * * @constructor * @category Core */ - export function FireCMS(props: FireCMSProps) { const modeController = useModeController(); diff --git a/website/docs/recipes/custom_datasource.mdx b/website/docs/recipes/custom_datasource.mdx new file mode 100644 index 000000000..eb311e2a9 --- /dev/null +++ b/website/docs/recipes/custom_datasource.mdx @@ -0,0 +1,58 @@ +--- +id: custom_datasource +title: Use a custom data source +sidebar_label: Custom data source +--- + +FireCMS is based on the idea of **declarative** data sources. This means that +you can define your collections and entities in a declarative way, and FireCMS +will take care of the rest. We provide a default datasource that works with +Firestore, but you can also use your own data sources. + +## Custom data sources + +FireCMS allows you to use your own data sources. This is useful if you want to +use FireCMS with a different database, or if you want to use a different +Firestore instance. + +Data sources are implemented as objects that implement the +[`DataSource`](./api/interfaces/DataSource) interface. + +Since FireCMS is a CMS based on React, you can use the hooks provided by FireCMS to +develop your own data sources. + +The default datasource is implemented in the [`useFirestoreDataSource`](./api/functions/useFirestoreDataSource) +hook. You can call this hook from your own data source to get the default +implementation and extend it. When defining your own data source, you need +to implement all the methods defined in the [`DataSource`](./api/interfaces/DataSource) +interface. + +## Example custom datasource + +Let's define a custom data source that will allow us to override the default +implementation when fetching and saving data for a specific path only: + +import CodeBlock from "@theme/CodeBlock"; +import CustomDataSource + from "!!raw-loader!firecms-example/src/docs/recipes/custom_datasource/custom_datasource"; + +{CustomDataSource} + +## Using a custom data source + +Once you have defined your custom data source, you can use it in your +custom [`FireCMS`](./api/interfaces/FireCMS) instance (keep in mind that you can't use a +custom data source with `FirebaseCMSApp`). + +You will need to create a custom app, and use your custom data source when +creating the `FireCMS` instance. + +Check the [Custom CMS app](../custom_cms_app) instructions to learn how to create a custom app. +Replace the `useFirestoreDataSource` hook with your custom data source. + +:::tip +You can also customise in the same way the other components used internally by +FireCMS. +::: + + diff --git a/website/sidebars.js b/website/sidebars.js index fcd9ccc18..adf96c3ea 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -92,9 +92,9 @@ module.exports = { label: "Recipes", collapsed: false, items: [ - // 'recipes/recipes_index', "recipes/building_a_blog", "recipes/copy_entity", + "recipes/custom_datasource", "recipes/documents_as_subcollections", ] },