@rebasepro/types 0.0.1-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +174 -0
- package/dist/components/EntityFormActionsProps.d.ts +17 -0
- package/dist/components/EntityFormProps.d.ts +46 -0
- package/dist/components/PropertyPreviewProps.d.ts +50 -0
- package/dist/components/formex.d.ts +40 -0
- package/dist/components/index.d.ts +3 -0
- package/dist/controllers/analytics_controller.d.ts +7 -0
- package/dist/controllers/auth.d.ts +73 -0
- package/dist/controllers/customization_controller.d.ts +50 -0
- package/dist/controllers/datasource.d.ts +179 -0
- package/dist/controllers/dialogs_controller.d.ts +36 -0
- package/dist/controllers/index.d.ts +11 -0
- package/dist/controllers/local_config_persistence.d.ts +20 -0
- package/dist/controllers/navigation.d.ts +262 -0
- package/dist/controllers/side_dialogs_controller.d.ts +67 -0
- package/dist/controllers/side_entity_controller.d.ts +90 -0
- package/dist/controllers/snackbar.d.ts +24 -0
- package/dist/controllers/storage.d.ts +173 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.es.js +113 -0
- package/dist/index.es.js.map +1 -0
- package/dist/index.umd.js +117 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/rebase_context.d.ts +91 -0
- package/dist/types/backend.d.ts +254 -0
- package/dist/types/chips.d.ts +5 -0
- package/dist/types/collections.d.ts +887 -0
- package/dist/types/entities.d.ts +140 -0
- package/dist/types/entity_actions.d.ts +98 -0
- package/dist/types/entity_callbacks.d.ts +173 -0
- package/dist/types/entity_link_builder.d.ts +7 -0
- package/dist/types/entity_overrides.d.ts +5 -0
- package/dist/types/export_import.d.ts +21 -0
- package/dist/types/fields.d.ts +221 -0
- package/dist/types/index.d.ts +19 -0
- package/dist/types/locales.d.ts +4 -0
- package/dist/types/modify_collections.d.ts +5 -0
- package/dist/types/plugins.d.ts +276 -0
- package/dist/types/properties.d.ts +1103 -0
- package/dist/types/property_config.d.ts +68 -0
- package/dist/types/rebase.d.ts +180 -0
- package/dist/types/relations.d.ts +336 -0
- package/dist/types/user_management_delegate.d.ts +78 -0
- package/dist/types/websockets.d.ts +33 -0
- package/dist/users/index.d.ts +2 -0
- package/dist/users/roles.d.ts +22 -0
- package/dist/users/user.d.ts +42 -0
- package/package.json +137 -0
- package/src/components/EntityFormActionsProps.tsx +18 -0
- package/src/components/EntityFormProps.tsx +52 -0
- package/src/components/PropertyPreviewProps.tsx +61 -0
- package/src/components/formex.tsx +46 -0
- package/src/components/index.ts +3 -0
- package/src/controllers/analytics_controller.tsx +57 -0
- package/src/controllers/auth.tsx +94 -0
- package/src/controllers/customization_controller.tsx +61 -0
- package/src/controllers/datasource.ts +218 -0
- package/src/controllers/dialogs_controller.tsx +37 -0
- package/src/controllers/index.ts +11 -0
- package/src/controllers/local_config_persistence.tsx +22 -0
- package/src/controllers/navigation.ts +317 -0
- package/src/controllers/side_dialogs_controller.tsx +82 -0
- package/src/controllers/side_entity_controller.tsx +104 -0
- package/src/controllers/snackbar.ts +29 -0
- package/src/controllers/storage.ts +196 -0
- package/src/index.ts +5 -0
- package/src/rebase_context.tsx +122 -0
- package/src/types/backend.ts +385 -0
- package/src/types/chips.ts +46 -0
- package/src/types/collections.ts +1013 -0
- package/src/types/entities.ts +207 -0
- package/src/types/entity_actions.tsx +118 -0
- package/src/types/entity_callbacks.ts +217 -0
- package/src/types/entity_link_builder.ts +8 -0
- package/src/types/entity_overrides.tsx +6 -0
- package/src/types/export_import.ts +26 -0
- package/src/types/fields.tsx +298 -0
- package/src/types/index.ts +20 -0
- package/src/types/locales.ts +81 -0
- package/src/types/modify_collections.tsx +6 -0
- package/src/types/plugins.tsx +328 -0
- package/src/types/properties.ts +1270 -0
- package/src/types/property_config.tsx +93 -0
- package/src/types/rebase.tsx +211 -0
- package/src/types/relations.ts +351 -0
- package/src/types/user_management_delegate.ts +98 -0
- package/src/types/websockets.ts +37 -0
- package/src/users/index.ts +2 -0
- package/src/users/roles.ts +33 -0
- package/src/users/user.ts +46 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 Rebase
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://rebase.pro/img/dark_mode.webp" alt="Intro video" style="max-width: 100%;"/>
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://rebase.pro">
|
|
7
|
+
<img src="https://rebase.pro/img/logo_small.png" width="240px" alt="Rebase logo" />
|
|
8
|
+
</a>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<h1 align="center">Rebase</h1>
|
|
12
|
+
<h3 align="center">Awesome Firebase/MongoDB-based headless CMS</h3>
|
|
13
|
+
<p align="center"><a href="https://demo.rebase.pro">Live demo</a></p>
|
|
14
|
+
|
|
15
|
+
<br />
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
[](https://www.npmjs.com/package/rebase) [](https://standardjs.com)
|
|
19
|
+
|
|
20
|
+
Designed by developers for developers, Rebase is a headless CMS and admin panel
|
|
21
|
+
that seamlessly integrates with **Firebase and Firestore** by default, but is
|
|
22
|
+
also
|
|
23
|
+
compatible with any backend.
|
|
24
|
+
|
|
25
|
+
Effortlessly generate **CRUD views** based on your configuration. Rebase is
|
|
26
|
+
simple
|
|
27
|
+
to set up for standard cases and easy to extend and customize for more specific
|
|
28
|
+
needs.
|
|
29
|
+
|
|
30
|
+
Built to produce collection and form views that naturally align with the
|
|
31
|
+
collection/document model, Rebase covers a wide range of basic and advanced use
|
|
32
|
+
cases. With extensibility in mind, it's easy to create your own views or modify
|
|
33
|
+
existing ones.
|
|
34
|
+
|
|
35
|
+
Rebase does **not impose any data structure** restrictions, ensuring a smooth,
|
|
36
|
+
out-of-the-box experience for any project.
|
|
37
|
+
|
|
38
|
+
### Core technologies
|
|
39
|
+
|
|
40
|
+
Rebase is based on this great technologies:
|
|
41
|
+
|
|
42
|
+
- Typescript
|
|
43
|
+
- Tailwind CSS
|
|
44
|
+
- Firebase SDK 10
|
|
45
|
+
- React + React Router 6
|
|
46
|
+
|
|
47
|
+
### Quickstart
|
|
48
|
+
|
|
49
|
+
The easiest way to get going is to check our quickstart guide! You will just
|
|
50
|
+
need to follow some quick steps:
|
|
51
|
+
|
|
52
|
+
https://rebase.pro/docs
|
|
53
|
+
|
|
54
|
+
### Demo
|
|
55
|
+
|
|
56
|
+
Check the demo with all the core functionalities.
|
|
57
|
+
|
|
58
|
+
https://demo.rebase.pro
|
|
59
|
+
|
|
60
|
+
> You can modify the data, but it gets periodically restored.
|
|
61
|
+
|
|
62
|
+
### Changelog
|
|
63
|
+
|
|
64
|
+
https://rebase.pro/docs/changelog
|
|
65
|
+
|
|
66
|
+
## Features
|
|
67
|
+
|
|
68
|
+
Rebase has been meticulously crafted to make it incredibly easy for developers
|
|
69
|
+
to build a CMS/admin tool while offering an excellent data editing experience
|
|
70
|
+
and a user-friendly interface for marketers and content managers.
|
|
71
|
+
|
|
72
|
+
### 🏓 Exceptional Spreadsheet View
|
|
73
|
+
|
|
74
|
+
We've developed a highly efficient windowed **spreadsheet view** for
|
|
75
|
+
collections, allowing inline editing for most common fields, as well as popup
|
|
76
|
+
views for other cases and your custom field implementations.
|
|
77
|
+
|
|
78
|
+
Featuring **real-time** support, Rebase is perfect for apps that require
|
|
79
|
+
constant updates. It also supports **text search** (through an external provider
|
|
80
|
+
like Algolia, if using Firestore), **filtering and sorting**, and **exporting**
|
|
81
|
+
data.
|
|
82
|
+
|
|
83
|
+
### ✨ Robust Forms
|
|
84
|
+
|
|
85
|
+

|
|
86
|
+
|
|
87
|
+
When editing an entity, Rebase offers a nested system of side dialogs for
|
|
88
|
+
navigating through **subcollections** and accessing custom views (such as custom
|
|
89
|
+
forms or blog previews). This functionality can also be accessed
|
|
90
|
+
programmatically using the `useSideEntityController` hook.
|
|
91
|
+
|
|
92
|
+
Rebase includes **over 20 built-in fields** with numerous customization and
|
|
93
|
+
validation options. The components have been carefully designed for an
|
|
94
|
+
outstanding user experience, including advanced features like **references** to
|
|
95
|
+
other collections, **markdown**, and **array reordering**.
|
|
96
|
+
|
|
97
|
+
For unsupported use cases, create your own **custom field** as a React
|
|
98
|
+
component.
|
|
99
|
+
|
|
100
|
+
Rebase also supports **conditional fields** in forms, allowing you to define
|
|
101
|
+
rules for active fields based on your logic.
|
|
102
|
+
|
|
103
|
+
### 👮 Authentication, Permissions, and Role System
|
|
104
|
+
|
|
105
|
+
Define which navigation views users can see and the operations (create, edit,
|
|
106
|
+
delete) they can perform based on your role system. You can even configure this
|
|
107
|
+
on a per-entity or collection level.
|
|
108
|
+
|
|
109
|
+
By default, Rebase supports all Firebase authorization mechanisms, but you can
|
|
110
|
+
implement your own.
|
|
111
|
+
|
|
112
|
+
### 🏹 Relational Support
|
|
113
|
+
|
|
114
|
+
Define references to entities in other collections and benefit from the
|
|
115
|
+
integrated reference fields and shortcuts.
|
|
116
|
+
|
|
117
|
+
You can also define subcollections at the entity level for nesting data in a
|
|
118
|
+
collection/document/collection model.
|
|
119
|
+
|
|
120
|
+
### 🆒 Real-Time Data
|
|
121
|
+
|
|
122
|
+
Every view in the CMS supports real-time data, making it suitable for displaying
|
|
123
|
+
constantly updated information.
|
|
124
|
+
|
|
125
|
+
Forms also support this feature, with any modified value in the database being
|
|
126
|
+
updated in any open form view as long as it hasn't been touched by the user.
|
|
127
|
+
This enables advanced cases where a Cloud Function is triggered after saving an
|
|
128
|
+
entity, modifying some values, and requiring real-time updates.
|
|
129
|
+
|
|
130
|
+
### 🗂️ File Storage
|
|
131
|
+
|
|
132
|
+
Rebase supports uploading files to Firebase Storage out of the box and provides
|
|
133
|
+
specific fields for handling single and multiple file uploads, as well as
|
|
134
|
+
reordering.
|
|
135
|
+
|
|
136
|
+
You can replace the Firebase Storage implementation with your own.
|
|
137
|
+
|
|
138
|
+
## Included example
|
|
139
|
+
|
|
140
|
+
You can access the code for the demo project under
|
|
141
|
+
[`example`](https://github.com/Rebaseco/rebase/tree/master/example). It includes
|
|
142
|
+
every feature provided by this CMS.
|
|
143
|
+
|
|
144
|
+
Keep in mind you need to update the dependencies in that project if you want to
|
|
145
|
+
use it as it is, without linking it to the library source code. More details in
|
|
146
|
+
its README
|
|
147
|
+
|
|
148
|
+
## Contact and support
|
|
149
|
+
|
|
150
|
+
If you need general support, you can open a GitHub issue.
|
|
151
|
+
|
|
152
|
+
Do you need consulting setting up your Firestore-based CMS in no time? We are
|
|
153
|
+
happy to help!
|
|
154
|
+
`hello@rebase.pro`
|
|
155
|
+
|
|
156
|
+
## Development
|
|
157
|
+
|
|
158
|
+
If you would like to make changes to the source, feel free to submit a PR!
|
|
159
|
+
|
|
160
|
+
When developing, the core library can be found under `lib`.
|
|
161
|
+
There is an example project in the folder `example`.
|
|
162
|
+
|
|
163
|
+
In order to run the project, you need to create a file
|
|
164
|
+
called `firebase_config.ts`
|
|
165
|
+
in `example/src`.
|
|
166
|
+
|
|
167
|
+
That file needs to export a valid Firebase config, that you can get
|
|
168
|
+
from your Firebase console when creating a webapp for your project.
|
|
169
|
+
|
|
170
|
+
Then simply run `yarn` and `yarn dev`
|
|
171
|
+
|
|
172
|
+
## License
|
|
173
|
+
|
|
174
|
+
MIT © [Rebase](https://github.com/Rebaseco)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Entity, EntityCollection, FormContext } from "../types";
|
|
2
|
+
import { FormexController } from "./formex";
|
|
3
|
+
export interface EntityFormActionsProps {
|
|
4
|
+
path: string;
|
|
5
|
+
collection: EntityCollection;
|
|
6
|
+
entity?: Entity;
|
|
7
|
+
layout: "bottom" | "side";
|
|
8
|
+
savingError?: Error;
|
|
9
|
+
formex: FormexController<any>;
|
|
10
|
+
disabled: boolean;
|
|
11
|
+
status: "new" | "existing" | "copy";
|
|
12
|
+
pluginActions: React.ReactNode[];
|
|
13
|
+
openEntityMode: "side_panel" | "full_screen";
|
|
14
|
+
showDefaultActions?: boolean;
|
|
15
|
+
navigateBack: () => void;
|
|
16
|
+
formContext: FormContext;
|
|
17
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Entity, EntityCollection, EntityCustomViewParams, EntityStatus, FormContext } from "../types";
|
|
2
|
+
import { FormexController } from "./formex";
|
|
3
|
+
import { EntityFormActionsProps } from "./EntityFormActionsProps";
|
|
4
|
+
export type EntityFormProps<M extends Record<string, any>> = {
|
|
5
|
+
path: string;
|
|
6
|
+
fullIdPath?: string;
|
|
7
|
+
collection: EntityCollection<M>;
|
|
8
|
+
entityId?: string | number;
|
|
9
|
+
entity?: Entity<M>;
|
|
10
|
+
databaseId?: string;
|
|
11
|
+
onIdChange?: (id: string | number) => void;
|
|
12
|
+
onValuesModified?: (modified: boolean, values: M) => void;
|
|
13
|
+
onSaved?: (params: OnUpdateParams) => void;
|
|
14
|
+
initialDirtyValues?: Partial<M>;
|
|
15
|
+
onFormContextReady?: (formContext: FormContext) => void;
|
|
16
|
+
forceActionsAtTheBottom?: boolean;
|
|
17
|
+
className?: string;
|
|
18
|
+
initialStatus: EntityStatus;
|
|
19
|
+
onStatusChange?: (status: EntityStatus) => void;
|
|
20
|
+
onEntityChange?: (entity: Entity<M>) => void;
|
|
21
|
+
formex?: FormexController<M>;
|
|
22
|
+
openEntityMode?: "side_panel" | "full_screen";
|
|
23
|
+
/**
|
|
24
|
+
* If true, the form will be disabled and no actions will be available
|
|
25
|
+
*/
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Include the copy and delete actions in the form
|
|
29
|
+
*/
|
|
30
|
+
showDefaultActions?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Display the entity path in the form
|
|
33
|
+
*/
|
|
34
|
+
showEntityPath?: boolean;
|
|
35
|
+
EntityFormActionsComponent?: React.FC<EntityFormActionsProps>;
|
|
36
|
+
Builder?: React.ComponentType<EntityCustomViewParams<M>>;
|
|
37
|
+
children?: React.ReactNode;
|
|
38
|
+
};
|
|
39
|
+
export type OnUpdateParams = {
|
|
40
|
+
entity: Entity<any>;
|
|
41
|
+
status: EntityStatus;
|
|
42
|
+
path: string;
|
|
43
|
+
entityId?: string | number;
|
|
44
|
+
selectedTab?: string;
|
|
45
|
+
collection: EntityCollection<any>;
|
|
46
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { InferPropertyType, Property } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* @group Preview components
|
|
4
|
+
*/
|
|
5
|
+
export type PreviewSize = "small" | "medium" | "large";
|
|
6
|
+
/**
|
|
7
|
+
* @group Preview components
|
|
8
|
+
*/
|
|
9
|
+
export interface PropertyPreviewProps<P extends Property, CustomProps = unknown> {
|
|
10
|
+
/**
|
|
11
|
+
* Name of the property
|
|
12
|
+
*/
|
|
13
|
+
propertyKey?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Current value of the property, inferred from the property schema P
|
|
16
|
+
*/
|
|
17
|
+
value: InferPropertyType<P>;
|
|
18
|
+
/**
|
|
19
|
+
* Property this display is related to, now strongly typed to P
|
|
20
|
+
*/
|
|
21
|
+
property: P;
|
|
22
|
+
/**
|
|
23
|
+
* Desired size of the preview, depending on the context.
|
|
24
|
+
*/
|
|
25
|
+
size: PreviewSize;
|
|
26
|
+
/**
|
|
27
|
+
* Max height assigned to the preview, depending on the context.
|
|
28
|
+
* It may be undefined if unlimited.
|
|
29
|
+
*/
|
|
30
|
+
height?: number;
|
|
31
|
+
/**
|
|
32
|
+
* Max height width to the preview, depending on the context.
|
|
33
|
+
* It may be undefined if unlimited.
|
|
34
|
+
*/
|
|
35
|
+
width?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Additional properties set by the developer
|
|
38
|
+
*/
|
|
39
|
+
customProps?: CustomProps;
|
|
40
|
+
/**
|
|
41
|
+
* If the preview should be interactive or not.
|
|
42
|
+
* This applies only to videos.
|
|
43
|
+
*/
|
|
44
|
+
interactive?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* If true, image previews will fill their container completely.
|
|
47
|
+
* Only applies to image type properties.
|
|
48
|
+
*/
|
|
49
|
+
fill?: boolean;
|
|
50
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React, { FormEvent } from "react";
|
|
2
|
+
export type FormexController<T extends object> = {
|
|
3
|
+
values: T;
|
|
4
|
+
initialValues: T;
|
|
5
|
+
setValues: (values: T) => void;
|
|
6
|
+
setFieldValue: (key: string, value: unknown, shouldValidate?: boolean) => void;
|
|
7
|
+
touched: Record<string, boolean>;
|
|
8
|
+
setFieldTouched: (key: string, touched: boolean, shouldValidate?: boolean) => void;
|
|
9
|
+
setTouched: (touched: Record<string, boolean>) => void;
|
|
10
|
+
dirty: boolean;
|
|
11
|
+
setDirty: (dirty: boolean) => void;
|
|
12
|
+
setSubmitCount: (submitCount: number) => void;
|
|
13
|
+
errors: Record<string, string>;
|
|
14
|
+
setFieldError: (key: string, error?: string) => void;
|
|
15
|
+
handleChange: (event: React.SyntheticEvent) => void;
|
|
16
|
+
handleBlur: (event: React.FocusEvent) => void;
|
|
17
|
+
handleSubmit: (event?: FormEvent<HTMLFormElement>) => void;
|
|
18
|
+
validate: () => void;
|
|
19
|
+
resetForm: (props?: FormexResetProps<T>) => void;
|
|
20
|
+
submitCount: number;
|
|
21
|
+
isSubmitting: boolean;
|
|
22
|
+
setSubmitting: (isSubmitting: boolean) => void;
|
|
23
|
+
isValidating: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* The version of the form. This is incremented every time the form is reset
|
|
26
|
+
* or the form is submitted.
|
|
27
|
+
*/
|
|
28
|
+
version: number;
|
|
29
|
+
debugId?: string;
|
|
30
|
+
undo: () => void;
|
|
31
|
+
redo: () => void;
|
|
32
|
+
canUndo: boolean;
|
|
33
|
+
canRedo: boolean;
|
|
34
|
+
};
|
|
35
|
+
export type FormexResetProps<T extends object> = {
|
|
36
|
+
values?: T;
|
|
37
|
+
submitCount?: number;
|
|
38
|
+
errors?: Record<string, string>;
|
|
39
|
+
touched?: Record<string, boolean>;
|
|
40
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type AnalyticsController = {
|
|
2
|
+
/**
|
|
3
|
+
* Callback used to get analytics events from the CMS
|
|
4
|
+
*/
|
|
5
|
+
onAnalyticsEvent?: (event: CMSAnalyticsEvent, data?: object) => void;
|
|
6
|
+
};
|
|
7
|
+
export type CMSAnalyticsEvent = "entity_click" | "entity_click_from_reference" | "reference_selection_clear" | "reference_selection_toggle" | "reference_selected_single" | "reference_selection_new_entity" | "edit_entity_clicked" | "entity_edited" | "new_entity_click" | "new_entity_saved" | "copy_entity_click" | "entity_copied" | "single_delete_dialog_open" | "multiple_delete_dialog_open" | "single_entity_deleted" | "multiple_entities_deleted" | "drawer_navigate_to_home" | "drawer_navigate_to_collection" | "drawer_navigate_to_view" | "home_navigate_to_collection" | "home_favorite_navigate_to_collection" | "home_navigate_to_view" | "home_navigate_to_admin_view" | "home_favorite_navigate_to_view" | "home_move_card" | "home_move_group" | "home_drop_new_group" | "collection_inline_editing" | "view_mode_changed" | "kanban_card_moved" | "kanban_column_reorder" | "kanban_property_changed" | "kanban_new_entity_in_column" | "kanban_backfill_order" | "card_view_entity_click" | "unmapped_event";
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { DataSource } from "./datasource";
|
|
2
|
+
import { StorageSource } from "./storage";
|
|
3
|
+
import { Role, User } from "../users";
|
|
4
|
+
/**
|
|
5
|
+
* Controller for retrieving the logged user or performing auth related operations.
|
|
6
|
+
* Note that if you are implementing your AuthController, you probably will want
|
|
7
|
+
* to do it as the result of a hook.
|
|
8
|
+
* @group Hooks and utilities
|
|
9
|
+
*/
|
|
10
|
+
export type AuthController<USER extends User = any, ExtraData = unknown> = {
|
|
11
|
+
/**
|
|
12
|
+
* The user currently logged in
|
|
13
|
+
* The values can be: the user object, null if they skipped login
|
|
14
|
+
*/
|
|
15
|
+
user: USER | null;
|
|
16
|
+
/**
|
|
17
|
+
* Initial loading flag. It is used not to display the login screen
|
|
18
|
+
* when the app first loads, and it has not been checked whether the user
|
|
19
|
+
* is logged in or not.
|
|
20
|
+
*/
|
|
21
|
+
initialLoading?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Loading flag. It is used to display a loading screen when the user is
|
|
24
|
+
* logging in or out.
|
|
25
|
+
*/
|
|
26
|
+
authLoading: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Sign out
|
|
29
|
+
*/
|
|
30
|
+
signOut: () => Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Error initializing the authentication
|
|
33
|
+
*/
|
|
34
|
+
authError?: unknown;
|
|
35
|
+
/**
|
|
36
|
+
* Error dispatched by the auth provider
|
|
37
|
+
*/
|
|
38
|
+
authProviderError?: unknown;
|
|
39
|
+
/**
|
|
40
|
+
* You can use this method to retrieve the auth token for the current user.
|
|
41
|
+
*/
|
|
42
|
+
getAuthToken: () => Promise<string>;
|
|
43
|
+
/**
|
|
44
|
+
* Has the user skipped the login process
|
|
45
|
+
*/
|
|
46
|
+
loginSkipped: boolean;
|
|
47
|
+
extra: ExtraData;
|
|
48
|
+
setExtra: (extra: ExtraData) => void;
|
|
49
|
+
setUser?: (user: USER | null) => void;
|
|
50
|
+
setUserRoles?: (roles: Role[]) => void;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Implement this function to allow access to specific users.
|
|
54
|
+
* @group Hooks and utilities
|
|
55
|
+
*/
|
|
56
|
+
export type Authenticator<USER extends User = User> = (props: {
|
|
57
|
+
/**
|
|
58
|
+
* Logged-in user or null
|
|
59
|
+
*/
|
|
60
|
+
user: USER | null;
|
|
61
|
+
/**
|
|
62
|
+
* AuthController
|
|
63
|
+
*/
|
|
64
|
+
authController: AuthController<USER>;
|
|
65
|
+
/**
|
|
66
|
+
* Connector to your database, e.g. your Firestore database
|
|
67
|
+
*/
|
|
68
|
+
dataSource: DataSource;
|
|
69
|
+
/**
|
|
70
|
+
* Used storage implementation
|
|
71
|
+
*/
|
|
72
|
+
storageSource: StorageSource;
|
|
73
|
+
}) => boolean | Promise<boolean>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { EntityAction, EntityCustomView, EntityLinkBuilder, RebasePlugin, Locale, PropertyConfig } from "../types";
|
|
3
|
+
export type CustomizationController = {
|
|
4
|
+
/**
|
|
5
|
+
* Builder for generating utility links for entities
|
|
6
|
+
*/
|
|
7
|
+
entityLinkBuilder?: EntityLinkBuilder;
|
|
8
|
+
/**
|
|
9
|
+
* Use plugins to modify the behaviour of the CMS.
|
|
10
|
+
*/
|
|
11
|
+
plugins?: RebasePlugin[];
|
|
12
|
+
/**
|
|
13
|
+
* List of additional custom views for entities.
|
|
14
|
+
* You can use the key to reference the custom view in
|
|
15
|
+
* the `entityViews` prop of a collection.
|
|
16
|
+
*
|
|
17
|
+
* You can also define an entity view from the UI.
|
|
18
|
+
*/
|
|
19
|
+
entityViews?: EntityCustomView[];
|
|
20
|
+
/**
|
|
21
|
+
* List of actions that can be performed on entities.
|
|
22
|
+
* These actions are displayed in the entity view and in the collection view.
|
|
23
|
+
* You can later reuse these actions in the `entityActions` prop of a collection,
|
|
24
|
+
* by specifying the `key` of the action.
|
|
25
|
+
*/
|
|
26
|
+
entityActions?: EntityAction[];
|
|
27
|
+
/**
|
|
28
|
+
* Format of the dates in the CMS.
|
|
29
|
+
* Defaults to 'MMMM dd, yyyy, HH:mm:ss'
|
|
30
|
+
*/
|
|
31
|
+
dateTimeFormat?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Locale of the CMS, currently only affecting dates
|
|
34
|
+
*/
|
|
35
|
+
locale?: Locale;
|
|
36
|
+
/**
|
|
37
|
+
* Record of custom form fields to be used in the CMS.
|
|
38
|
+
* You can use the key to reference the custom field in
|
|
39
|
+
* the `propertyConfig` prop of a property in a collection.
|
|
40
|
+
*/
|
|
41
|
+
propertyConfigs: Record<string, PropertyConfig>;
|
|
42
|
+
components?: {
|
|
43
|
+
/**
|
|
44
|
+
* Component to render when a reference is missing
|
|
45
|
+
*/
|
|
46
|
+
missingReference?: React.ComponentType<{
|
|
47
|
+
path: string;
|
|
48
|
+
}>;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { Entity, EntityCollection, EntityStatus, EntityValues, FilterValues, TableColumnInfo } from "../types";
|
|
2
|
+
import { RebaseContext } from "../rebase_context";
|
|
3
|
+
/**
|
|
4
|
+
* @group Datasource
|
|
5
|
+
*/
|
|
6
|
+
export interface FetchEntityProps<M extends Record<string, any> = any> {
|
|
7
|
+
path: string;
|
|
8
|
+
entityId: string | number;
|
|
9
|
+
databaseId?: string;
|
|
10
|
+
collection?: EntityCollection<M, any>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* @group Datasource
|
|
14
|
+
*/
|
|
15
|
+
export type ListenEntityProps<M extends Record<string, any> = any> = FetchEntityProps<M> & {
|
|
16
|
+
onUpdate: (entity: Entity<M> | null) => void;
|
|
17
|
+
onError?: (error: Error) => void;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* @group Datasource
|
|
21
|
+
*/
|
|
22
|
+
export interface FetchCollectionProps<M extends Record<string, any> = any> {
|
|
23
|
+
path: string;
|
|
24
|
+
collection?: EntityCollection<M>;
|
|
25
|
+
filter?: FilterValues<Extract<keyof M, string>>;
|
|
26
|
+
limit?: number;
|
|
27
|
+
startAfter?: unknown;
|
|
28
|
+
orderBy?: string;
|
|
29
|
+
searchString?: string;
|
|
30
|
+
order?: "desc" | "asc";
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* @group Datasource
|
|
34
|
+
*/
|
|
35
|
+
export type ListenCollectionProps<M extends Record<string, any> = any> = FetchCollectionProps<M> & {
|
|
36
|
+
onUpdate: (entities: Entity<M>[]) => void;
|
|
37
|
+
onError?: (error: Error) => void;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* @group Datasource
|
|
41
|
+
*/
|
|
42
|
+
export interface SaveEntityProps<M extends Record<string, any> = any> {
|
|
43
|
+
path: string;
|
|
44
|
+
values: Partial<EntityValues<M>>;
|
|
45
|
+
entityId?: string | number;
|
|
46
|
+
previousValues?: Partial<EntityValues<M>>;
|
|
47
|
+
collection?: EntityCollection<M>;
|
|
48
|
+
status: EntityStatus;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* @group Datasource
|
|
52
|
+
*/
|
|
53
|
+
export interface DeleteEntityProps<M extends Record<string, any> = any> {
|
|
54
|
+
entity: Entity<M>;
|
|
55
|
+
collection?: EntityCollection<M>;
|
|
56
|
+
}
|
|
57
|
+
export type FilterCombinationValidProps = {
|
|
58
|
+
path: string;
|
|
59
|
+
databaseId?: string;
|
|
60
|
+
collection: EntityCollection<any>;
|
|
61
|
+
filterValues: FilterValues<any>;
|
|
62
|
+
sortBy?: [string, "asc" | "desc"];
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Component in charge of communicating with the data source.
|
|
66
|
+
* @group Datasource
|
|
67
|
+
*/
|
|
68
|
+
export interface DataSource {
|
|
69
|
+
/**
|
|
70
|
+
* Key that identifies this data source
|
|
71
|
+
*/
|
|
72
|
+
key?: string;
|
|
73
|
+
/**
|
|
74
|
+
* If the data source has been initialised
|
|
75
|
+
*/
|
|
76
|
+
initialised?: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Fetch data from a collection
|
|
79
|
+
* @param props
|
|
80
|
+
* @return Promise of entities
|
|
81
|
+
* @see useCollectionFetch if you need this functionality implemented as a hook
|
|
82
|
+
*/
|
|
83
|
+
fetchCollection<M extends Record<string, any> = any>(props: FetchCollectionProps<M>): Promise<Entity<M>[]>;
|
|
84
|
+
/**
|
|
85
|
+
* Listen to a collection in a given path. If you don't implement this method
|
|
86
|
+
* `fetchCollection` will be used instead, with no real time updates.
|
|
87
|
+
* @param props
|
|
88
|
+
* @return Function to cancel subscription
|
|
89
|
+
* @see useCollectionFetch if you need this functionality implemented as a hook
|
|
90
|
+
*/
|
|
91
|
+
listenCollection?<M extends Record<string, any> = any>(props: ListenCollectionProps<M>): () => void;
|
|
92
|
+
/**
|
|
93
|
+
* Retrieve an entity given a path and a collection
|
|
94
|
+
* @param props
|
|
95
|
+
*/
|
|
96
|
+
fetchEntity<M extends Record<string, any> = any>(props: FetchEntityProps<M>): Promise<Entity<M> | undefined>;
|
|
97
|
+
/**
|
|
98
|
+
* Get realtime updates on one entity.
|
|
99
|
+
* @param props
|
|
100
|
+
* @return Function to cancel subscription
|
|
101
|
+
*/
|
|
102
|
+
listenEntity?<M extends Record<string, any> = any>(props: ListenEntityProps<M>): () => void;
|
|
103
|
+
/**
|
|
104
|
+
* Save entity to the specified path
|
|
105
|
+
* @param props
|
|
106
|
+
*/
|
|
107
|
+
saveEntity<M extends Record<string, any> = any>(props: SaveEntityProps<M>): Promise<Entity<M>>;
|
|
108
|
+
/**
|
|
109
|
+
* Delete an entity
|
|
110
|
+
* @param props
|
|
111
|
+
* @return was the whole deletion flow successful
|
|
112
|
+
*/
|
|
113
|
+
deleteEntity<M extends Record<string, any> = any>(props: DeleteEntityProps<M>): Promise<void>;
|
|
114
|
+
/**
|
|
115
|
+
* Check if the given property is unique in the given collection
|
|
116
|
+
* @param path Collection path
|
|
117
|
+
* @param name of the property
|
|
118
|
+
* @param value
|
|
119
|
+
* @param entityId
|
|
120
|
+
* @param collection
|
|
121
|
+
* @return `true` if there are no other fields besides the given entity
|
|
122
|
+
*/
|
|
123
|
+
checkUniqueField(path: string, name: string, value: unknown, entityId?: string | number, collection?: EntityCollection): Promise<boolean>;
|
|
124
|
+
/**
|
|
125
|
+
* Count the number of entities in a collection
|
|
126
|
+
*/
|
|
127
|
+
countEntities?<M extends Record<string, any> = any>(props: FetchCollectionProps<M>): Promise<number>;
|
|
128
|
+
/**
|
|
129
|
+
* Check if the given filter combination is valid
|
|
130
|
+
* @param props
|
|
131
|
+
*/
|
|
132
|
+
isFilterCombinationValid?(props: Omit<FilterCombinationValidProps, "collection"> & {
|
|
133
|
+
databaseId?: string;
|
|
134
|
+
}): boolean;
|
|
135
|
+
/**
|
|
136
|
+
* Get the object to generate the current time in the datasource
|
|
137
|
+
*/
|
|
138
|
+
currentTime?: () => unknown;
|
|
139
|
+
delegateToCMSModel?: (data: unknown) => unknown;
|
|
140
|
+
cmsToDelegateModel?: (data: unknown) => unknown;
|
|
141
|
+
initTextSearch?: (props: {
|
|
142
|
+
context: RebaseContext;
|
|
143
|
+
path: string;
|
|
144
|
+
databaseId?: string;
|
|
145
|
+
collection: EntityCollection;
|
|
146
|
+
parentCollectionIds?: string[];
|
|
147
|
+
}) => Promise<boolean>;
|
|
148
|
+
/**
|
|
149
|
+
* Execute raw SQL (if supported by the datasource)
|
|
150
|
+
*/
|
|
151
|
+
executeSql?(sql: string, options?: {
|
|
152
|
+
database?: string;
|
|
153
|
+
role?: string;
|
|
154
|
+
}): Promise<Record<string, unknown>[]>;
|
|
155
|
+
/**
|
|
156
|
+
* Fetch the available databases (if supported by the datasource)
|
|
157
|
+
*/
|
|
158
|
+
fetchAvailableDatabases?(): Promise<string[]>;
|
|
159
|
+
/**
|
|
160
|
+
* Fetch the available roles (if supported by the datasource)
|
|
161
|
+
*/
|
|
162
|
+
fetchAvailableRoles?(): Promise<string[]>;
|
|
163
|
+
/**
|
|
164
|
+
* Fetch the current database name (if supported by the datasource)
|
|
165
|
+
*/
|
|
166
|
+
fetchCurrentDatabase?(): Promise<string | undefined>;
|
|
167
|
+
/**
|
|
168
|
+
* Fetch database tables not yet mapped to a collection (if supported)
|
|
169
|
+
*/
|
|
170
|
+
fetchUnmappedTables?(mappedPaths?: string[]): Promise<string[]>;
|
|
171
|
+
/**
|
|
172
|
+
* Fetch column metadata for a given table (if supported)
|
|
173
|
+
*/
|
|
174
|
+
fetchTableColumns?(tableName: string): Promise<TableColumnInfo[]>;
|
|
175
|
+
/**
|
|
176
|
+
* Flag to indicate if the datasource delegate has requested the initialization of the text search index
|
|
177
|
+
*/
|
|
178
|
+
needsInitTextSearch?: boolean;
|
|
179
|
+
}
|