@rebasepro/plugin-insights 0.3.0 → 0.5.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.
Files changed (36) hide show
  1. package/README.md +115 -0
  2. package/dist/common/src/collections/default-collections.d.ts +5 -8
  3. package/dist/common/src/data/query_builder.d.ts +6 -2
  4. package/dist/common/src/util/permissions.d.ts +14 -6
  5. package/dist/core/src/components/LoginView/LoginView.d.ts +9 -1
  6. package/dist/core/src/components/common/types.d.ts +3 -3
  7. package/dist/core/src/hooks/data/useCollectionFetch.d.ts +12 -1
  8. package/dist/index.es.js +215 -164
  9. package/dist/index.es.js.map +1 -1
  10. package/dist/index.umd.js +215 -164
  11. package/dist/index.umd.js.map +1 -1
  12. package/dist/plugin-insights/src/components/InsightWidget.d.ts +2 -2
  13. package/dist/plugin-insights/src/components/InsightWidgetSkeleton.d.ts +3 -1
  14. package/dist/plugin-insights/src/components/InsightsScorecardView.d.ts +3 -1
  15. package/dist/types/src/controllers/auth.d.ts +2 -2
  16. package/dist/types/src/controllers/client.d.ts +25 -40
  17. package/dist/types/src/controllers/data.d.ts +21 -3
  18. package/dist/types/src/controllers/data_driver.d.ts +5 -0
  19. package/dist/types/src/controllers/email.d.ts +2 -0
  20. package/dist/types/src/types/auth_adapter.d.ts +3 -56
  21. package/dist/types/src/types/backend.d.ts +38 -3
  22. package/dist/types/src/types/backend_hooks.d.ts +2 -17
  23. package/dist/types/src/types/collections.d.ts +30 -6
  24. package/dist/types/src/types/entity_views.d.ts +19 -28
  25. package/dist/types/src/types/properties.d.ts +9 -15
  26. package/dist/types/src/types/user_management_delegate.d.ts +16 -53
  27. package/dist/types/src/users/index.d.ts +0 -1
  28. package/dist/types/src/users/user.d.ts +0 -1
  29. package/dist/ui/src/components/Card.d.ts +2 -3
  30. package/dist/ui/src/components/FilterChip.d.ts +2 -10
  31. package/dist/ui/src/components/VirtualTable/VirtualTableProps.d.ts +8 -2
  32. package/package.json +4 -4
  33. package/src/components/InsightWidget.tsx +33 -4
  34. package/src/components/InsightWidgetSkeleton.tsx +7 -1
  35. package/src/components/InsightsScorecardView.tsx +4 -1
  36. package/dist/types/src/users/roles.d.ts +0 -14
package/README.md ADDED
@@ -0,0 +1,115 @@
1
+ # @rebasepro/plugin-insights
2
+
3
+ Scorecard and KPI widget plugin for the Rebase admin panel.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @rebasepro/plugin-insights
9
+ ```
10
+
11
+ **Peer dependencies:** `react >= 19.0.0`, `react-dom >= 19.0.0`
12
+
13
+ ## What This Package Does
14
+
15
+ This plugin injects data-driven scorecard widgets into the Rebase admin UI. You define insight definitions with custom `data()` callbacks — use the Rebase SDK, call a custom function, or hit any external API. The plugin handles caching, rendering, and slot injection.
16
+
17
+ Widgets appear in three locations automatically:
18
+
19
+ - **Home page header** — KPI overview cards via the `home.children.start` slot
20
+ - **Collection list view** — Inline scorecards below the title, above the data list via `collection.insights`
21
+ - **Home page cards** — Compact metrics auto-extracted from collection insights via `home.card.insight`
22
+
23
+ Collection-level insights are the single source of truth: define once under `collections.<slug>`, and they render both in the collection view and on the home card.
24
+
25
+ ## Key Exports
26
+
27
+ | Export | Type | Description |
28
+ |---|---|---|
29
+ | `useInsightsPlugin` | Hook | Creates the plugin from an `InsightsPluginConfig`. Returns a `RebasePlugin` |
30
+ | `InsightsPluginConfig` | Type | Top-level config: `insights` (home + collections) and optional `cacheTTL` |
31
+ | `InsightDefinition` | Type | Single insight: `id`, `title`, `data()` callback, `scorecard` config |
32
+ | `InsightDataResult` | Type | Return type of `data()`: `{ rows: DataRow[] }` |
33
+ | `DataRow` | Type | `Record<string, string \| number \| boolean \| null>` |
34
+ | `ScorecardConfig` | Type | Field mapping for value, comparison, icon, dateRange |
35
+ | `ScorecardFormat` | Type | Number formatting: style (decimal/currency/percent), notation, currency, decimals, showSign |
36
+ | `InsightsProvider` | Component | React context provider (injected automatically by the plugin) |
37
+ | `useInsightsEngine` | Hook | Access the insights engine from context (advanced) |
38
+ | `InsightsCache` | Class | TTL-based cache for insight data (advanced) |
39
+ | `useInsightsData` | Hook | Fetch and cache data for a specific insight (advanced) |
40
+ | `InsightsScorecardView` | Component | Renders a scorecard from data + config (custom layouts) |
41
+ | `InsightWidget` | Component | Single insight widget container (custom layouts) |
42
+ | `InsightWidgetSkeleton` | Component | Loading placeholder for insight widgets |
43
+
44
+ ### `InsightsPluginConfig`
45
+
46
+ | Prop | Type | Default | Description |
47
+ |---|---|---|---|
48
+ | `insights.home` | `InsightDefinition[]` | — | Insights shown at the top of the home page |
49
+ | `insights.collections` | `Record<string, InsightDefinition[]>` | — | Insights per collection slug |
50
+ | `cacheTTL` | `number` | `60_000` | Cache TTL in milliseconds |
51
+
52
+ ### `ScorecardConfig`
53
+
54
+ | Prop | Type | Description |
55
+ |---|---|---|
56
+ | `value.field` | `string` | Column name from data rows for the main value |
57
+ | `value.format` | `ScorecardFormat` | Number formatting options |
58
+ | `comparison.field` | `string` | Column name for comparison/delta value |
59
+ | `comparison.format` | `ScorecardFormat` | Formatting for comparison |
60
+ | `comparison.intent` | `"increase_is_good" \| "decrease_is_good"` | Controls green/red coloring |
61
+ | `icon` | `string` | Icon key (e.g., `"shopping_cart"`) |
62
+ | `dateRange` | `string` | Label text (e.g., `"Last 30 days"`) |
63
+
64
+ ## Quick Start
65
+
66
+ ```tsx
67
+ import { useInsightsPlugin } from "@rebasepro/plugin-insights";
68
+
69
+ const insightsPlugin = useInsightsPlugin({
70
+ cacheTTL: 120_000,
71
+ insights: {
72
+ home: [
73
+ {
74
+ id: "revenue",
75
+ title: "Revenue",
76
+ data: async () => {
77
+ const res = await fetch("/api/analytics/revenue");
78
+ return { rows: [await res.json()] };
79
+ },
80
+ scorecard: {
81
+ value: { field: "total", format: { style: "currency", currency: "USD", notation: "compact" } },
82
+ comparison: { field: "delta_pct", format: { style: "percent", decimals: 1 }, intent: "increase_is_good" },
83
+ icon: "attach_money",
84
+ dateRange: "Last 30 days"
85
+ }
86
+ }
87
+ ],
88
+ collections: {
89
+ orders: [
90
+ {
91
+ id: "total_orders",
92
+ title: "Total Orders",
93
+ data: async () => {
94
+ const count = await rebaseClient.data.orders.count();
95
+ return { rows: [{ total: count }] };
96
+ },
97
+ scorecard: {
98
+ value: { field: "total", format: { style: "decimal", notation: "compact" } },
99
+ icon: "shopping_cart"
100
+ }
101
+ }
102
+ ]
103
+ }
104
+ }
105
+ });
106
+
107
+ // Pass to your Rebase app:
108
+ <RebaseFirebaseApp plugins={[insightsPlugin]} />
109
+ ```
110
+
111
+ ## Related Packages
112
+
113
+ - `@rebasepro/core` — Core framework providing the plugin system
114
+ - `@rebasepro/types` — Shared types (`RebasePlugin`, `SlotContribution`)
115
+ - `@rebasepro/ui` — UI components used by insight widgets
@@ -1,12 +1,9 @@
1
- import { PostgresCollection } from "@rebasepro/types";
1
+ import type { PostgresCollection } from "@rebasepro/types";
2
2
  /**
3
- * Default users collection definition.
3
+ * Default users collection.
4
4
  *
5
- * Shared between the admin UI (for navigation/display) and the backend
6
- * (for schema generation). Both consumers prepend this to the developer's
7
- * collections array and rely on generic slug-based deduplication
8
- * (Map keyed by slug, last-write-wins) so that developer-defined
9
- * collections with the same slug override this default — no hardcoded
10
- * string checks required.
5
+ * Prepended to the developer's collections array by the admin and server.
6
+ * Slug-based dedup (Map keyed by slug, last-write-wins) lets developers
7
+ * override by defining their own collection with `slug: "users"`.
11
8
  */
12
9
  export declare const defaultUsersCollection: PostgresCollection;
@@ -1,4 +1,7 @@
1
- import { FindResponse, CollectionAccessor, QueryBuilderInterface, FilterOperator } from "@rebasepro/types";
1
+ import { FindResponse, CollectionAccessor, QueryBuilderInterface, FilterOperator, LogicalCondition, WhereValue, FilterCondition } from "@rebasepro/types";
2
+ export declare function or(...conditions: (FilterCondition | LogicalCondition)[]): LogicalCondition;
3
+ export declare function and(...conditions: (FilterCondition | LogicalCondition)[]): LogicalCondition;
4
+ export declare function cond(column: string, operator: FilterOperator, value: unknown): FilterCondition;
2
5
  export declare class QueryBuilder<M extends Record<string, unknown> = Record<string, unknown>> implements QueryBuilderInterface<M> {
3
6
  private collection;
4
7
  private params;
@@ -8,7 +11,8 @@ export declare class QueryBuilder<M extends Record<string, unknown> = Record<str
8
11
  * @example
9
12
  * client.collection('users').where('age', '>=', 18).find()
10
13
  */
11
- where(column: keyof M & string, operator: FilterOperator, value: unknown): this;
14
+ where<K extends keyof M & string>(column: K, operator: FilterOperator, value: WhereValue<M[K]>): this;
15
+ where(logicalCondition: LogicalCondition): this;
12
16
  /**
13
17
  * Order the results by a specific column.
14
18
  * @example
@@ -1,6 +1,14 @@
1
- import { AuthController, Entity, EntityCollection, User } from "@rebasepro/types";
2
- export declare function checkOperation<M extends Record<string, unknown>, USER extends User>(collection: EntityCollection<M>, authController: AuthController<USER>, entity: Entity<M> | null, targetOperation: "select" | "insert" | "update" | "delete"): boolean;
3
- export declare function canReadCollection<M extends Record<string, unknown>, USER extends User>(collection: EntityCollection<M>, authController: AuthController<USER>): boolean;
4
- export declare function canEditEntity<M extends Record<string, unknown>, USER extends User>(collection: EntityCollection<M>, authController: AuthController<USER>, path: string, entity: Entity<M> | null): boolean;
5
- export declare function canCreateEntity<M extends Record<string, unknown>, USER extends User>(collection: EntityCollection<M>, authController: AuthController<USER>, path: string, entity: Entity<M> | null): boolean;
6
- export declare function canDeleteEntity<M extends Record<string, unknown>, USER extends User>(collection: EntityCollection<M>, authController: AuthController<USER>, path: string, entity: Entity<M> | null): boolean;
1
+ import { Entity, EntityCollection, User } from "@rebasepro/types";
2
+ /**
3
+ * Minimal auth context for permission checking.
4
+ * Only requires the user object avoids forcing callers to construct
5
+ * a full AuthController just to check permissions.
6
+ */
7
+ export interface AuthContext<USER extends User = User> {
8
+ user: USER | null;
9
+ }
10
+ export declare function checkOperation<M extends Record<string, unknown>, USER extends User>(collection: EntityCollection<M>, authContext: AuthContext<USER>, entity: Entity<M> | null, targetOperation: "select" | "insert" | "update" | "delete"): boolean;
11
+ export declare function canReadCollection<M extends Record<string, unknown>, USER extends User>(collection: EntityCollection<M>, authContext: AuthContext<USER>): boolean;
12
+ export declare function canEditEntity<M extends Record<string, unknown>, USER extends User>(collection: EntityCollection<M>, authContext: AuthContext<USER>, path: string, entity: Entity<M> | null): boolean;
13
+ export declare function canCreateEntity<M extends Record<string, unknown>, USER extends User>(collection: EntityCollection<M>, authContext: AuthContext<USER>, path: string, entity: Entity<M> | null): boolean;
14
+ export declare function canDeleteEntity<M extends Record<string, unknown>, USER extends User>(collection: EntityCollection<M>, authContext: AuthContext<USER>, path: string, entity: Entity<M> | null): boolean;
@@ -92,10 +92,18 @@ export interface LoginViewProps {
92
92
  * If not set, derived from `authController.capabilities.registration`.
93
93
  */
94
94
  registrationEnabled?: boolean;
95
+ /**
96
+ * Pre-fill the email field (e.g. for demo or testing environments).
97
+ */
98
+ defaultEmail?: string;
99
+ /**
100
+ * Pre-fill the password field (e.g. for demo or testing environments).
101
+ */
102
+ defaultPassword?: string;
95
103
  }
96
104
  /**
97
105
  * Generic login view component that works with any AuthControllerExtended.
98
106
  * Feature-detects capabilities to show/hide login methods.
99
107
  * @group Core
100
108
  */
101
- export declare function LoginView({ logo, authController, noUserComponent, disableSignupScreen, disabled, notAllowedError, googleClientId, githubClientId, linkedinClientId, title, subtitle, needsSetup, registrationEnabled, additionalComponent }: LoginViewProps): import("react/jsx-runtime").JSX.Element;
109
+ export declare function LoginView({ logo, authController, noUserComponent, disableSignupScreen, disabled, notAllowedError, googleClientId, githubClientId, linkedinClientId, title, subtitle, needsSetup, registrationEnabled, additionalComponent, defaultEmail, defaultPassword }: LoginViewProps): import("react/jsx-runtime").JSX.Element;
@@ -1,4 +1,4 @@
1
- import type { Property } from "@rebasepro/types";
1
+ import type { Property, Entity } from "@rebasepro/types";
2
2
  import { CollectionSize, SelectedCellProps } from "@rebasepro/types";
3
3
  export type EntityCollectionTableController<M extends Record<string, unknown>> = {
4
4
  /**
@@ -26,7 +26,7 @@ export type EntityCollectionTableController<M extends Record<string, unknown>> =
26
26
  * Callback used when the value of a cell has changed.
27
27
  * @param params
28
28
  */
29
- onValueChange?: (params: OnCellValueChangeParams<unknown, M>) => void;
29
+ onValueChange?: (params: OnCellValueChangeParams<unknown, Entity<M>>) => void;
30
30
  /**
31
31
  * Size of the elements in the collection
32
32
  */
@@ -56,7 +56,7 @@ export type UniqueFieldValidator = (props: {
56
56
  * Callback when a cell has changed in a table
57
57
  * @group Collection components
58
58
  */
59
- export type OnCellValueChange<T, M extends Record<string, unknown>> = (params: OnCellValueChangeParams<T, M>) => Promise<void> | void;
59
+ export type OnCellValueChange<T, M extends Record<string, unknown>> = (params: OnCellValueChangeParams<T, Entity<M>>) => Promise<void> | void;
60
60
  /**
61
61
  * @group Collection components
62
62
  */
@@ -16,6 +16,14 @@ export interface CollectionFetchProps<M extends Record<string, any>> {
16
16
  * Number of entities to fetch
17
17
  */
18
18
  itemCount?: number;
19
+ /**
20
+ * Number of items to skip
21
+ */
22
+ offset?: number;
23
+ /**
24
+ * Page number (1-indexed), alternative to offset
25
+ */
26
+ page?: number;
19
27
  /**
20
28
  * Filter the fetched data by the property
21
29
  */
@@ -37,6 +45,7 @@ export interface CollectionFetchResult<M extends Record<string, any>> {
37
45
  dataLoading: boolean;
38
46
  noMoreToLoad: boolean;
39
47
  dataLoadingError?: Error;
48
+ totalCount?: number;
40
49
  }
41
50
  /**
42
51
  * This hook is used to fetch collections using a given collection
@@ -45,7 +54,9 @@ export interface CollectionFetchResult<M extends Record<string, any>> {
45
54
  * @param filterValues
46
55
  * @param sortBy
47
56
  * @param itemCount
57
+ * @param offset
58
+ * @param page
48
59
  * @param searchString
49
60
  * @group Hooks and utilities
50
61
  */
51
- export declare function useCollectionFetch<M extends Record<string, any>, USER extends User>({ path, collection, filterValues, sortBy, itemCount, searchString }: CollectionFetchProps<M>): CollectionFetchResult<M>;
62
+ export declare function useCollectionFetch<M extends Record<string, any>, USER extends User>({ path, collection, filterValues, sortBy, itemCount, offset, page, searchString }: CollectionFetchProps<M>): CollectionFetchResult<M>;