@donotdev/crud 0.0.7 → 0.0.9
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/dist/CrudService.d.ts +6 -54
- package/dist/CrudService.d.ts.map +1 -1
- package/dist/CrudService.js +1 -1
- package/dist/CrudStore.d.ts +1 -94
- package/dist/CrudStore.d.ts.map +1 -1
- package/dist/adapters/FirestoreAdapter.d.ts +3 -1
- package/dist/adapters/FirestoreAdapter.d.ts.map +1 -1
- package/dist/adapters/FirestoreAdapter.js +1 -1
- package/dist/adapters/FunctionsAdapter.d.ts +8 -1
- package/dist/adapters/FunctionsAdapter.d.ts.map +1 -1
- package/dist/adapters/FunctionsAdapter.js +1 -1
- package/dist/builtinFieldTypes.d.ts.map +1 -1
- package/dist/builtinFieldTypes.js +1 -1
- package/dist/components/EntityCardList.d.ts +5 -3
- package/dist/components/EntityCardList.d.ts.map +1 -1
- package/dist/components/EntityCardList.js +1 -1
- package/dist/components/EntityDisplayRenderer.d.ts +3 -3
- package/dist/components/EntityDisplayRenderer.d.ts.map +1 -1
- package/dist/components/EntityDisplayRenderer.js +1 -1
- package/dist/components/EntityFilters.d.ts +43 -0
- package/dist/components/EntityFilters.d.ts.map +1 -0
- package/dist/components/EntityFilters.js +1 -0
- package/dist/components/EntityFormRenderer.d.ts +22 -1
- package/dist/components/EntityFormRenderer.d.ts.map +1 -1
- package/dist/components/EntityFormRenderer.js +1 -1
- package/dist/components/EntityList.d.ts +12 -6
- package/dist/components/EntityList.d.ts.map +1 -1
- package/dist/components/EntityList.js +1 -1
- package/dist/components/FormFieldRenderer.d.ts.map +1 -1
- package/dist/components/controlled/complex/ControlledAddressField.d.ts +3 -0
- package/dist/components/controlled/complex/ControlledAddressField.d.ts.map +1 -1
- package/dist/components/controlled/complex/ControlledDateField.d.ts +3 -0
- package/dist/components/controlled/complex/ControlledDateField.d.ts.map +1 -1
- package/dist/components/controlled/complex/ControlledGeoPointField.d.ts +3 -0
- package/dist/components/controlled/complex/ControlledGeoPointField.d.ts.map +1 -1
- package/dist/components/controlled/complex/ControlledMapField.d.ts +3 -0
- package/dist/components/controlled/complex/ControlledMapField.d.ts.map +1 -1
- package/dist/components/controlled/complex/ControlledMultiInputField.d.ts +3 -0
- package/dist/components/controlled/complex/ControlledMultiInputField.d.ts.map +1 -1
- package/dist/components/controlled/complex/ControlledRichTextField.d.ts +3 -0
- package/dist/components/controlled/complex/ControlledRichTextField.d.ts.map +1 -1
- package/dist/components/controlled/complex/ControlledTimestampField.d.ts +3 -0
- package/dist/components/controlled/complex/ControlledTimestampField.d.ts.map +1 -1
- package/dist/components/controlled/complex/index.d.ts.map +1 -1
- package/dist/components/controlled/file/ControlledDocumentField.d.ts +3 -0
- package/dist/components/controlled/file/ControlledDocumentField.d.ts.map +1 -1
- package/dist/components/controlled/file/ControlledFileField.d.ts +3 -0
- package/dist/components/controlled/file/ControlledFileField.d.ts.map +1 -1
- package/dist/components/controlled/file/ControlledImageField.d.ts +3 -0
- package/dist/components/controlled/file/ControlledImageField.d.ts.map +1 -1
- package/dist/components/controlled/file/ControlledMultiDocumentField.d.ts +3 -0
- package/dist/components/controlled/file/ControlledMultiDocumentField.d.ts.map +1 -1
- package/dist/components/controlled/file/ControlledMultiFileField.d.ts +3 -0
- package/dist/components/controlled/file/ControlledMultiFileField.d.ts.map +1 -1
- package/dist/components/controlled/file/ControlledMultiImageField.d.ts +3 -0
- package/dist/components/controlled/file/ControlledMultiImageField.d.ts.map +1 -1
- package/dist/components/controlled/file/index.d.ts.map +1 -1
- package/dist/components/controlled/index.d.ts +4 -0
- package/dist/components/controlled/index.d.ts.map +1 -1
- package/dist/components/controlled/input/ControlledCheckboxField.d.ts +3 -0
- package/dist/components/controlled/input/ControlledCheckboxField.d.ts.map +1 -1
- package/dist/components/controlled/input/ControlledCheckboxField.js +1 -1
- package/dist/components/controlled/input/ControlledGdprConsentField.d.ts +8 -0
- package/dist/components/controlled/input/ControlledGdprConsentField.d.ts.map +1 -0
- package/dist/components/controlled/input/ControlledGdprConsentField.js +1 -0
- package/dist/components/controlled/input/ControlledNumberField.d.ts +3 -0
- package/dist/components/controlled/input/ControlledNumberField.d.ts.map +1 -1
- package/dist/components/controlled/input/ControlledPasswordField.d.ts +3 -0
- package/dist/components/controlled/input/ControlledPasswordField.d.ts.map +1 -1
- package/dist/components/controlled/input/ControlledPhoneField.d.ts +3 -0
- package/dist/components/controlled/input/ControlledPhoneField.d.ts.map +1 -1
- package/dist/components/controlled/input/ControlledRangeField.d.ts +3 -0
- package/dist/components/controlled/input/ControlledRangeField.d.ts.map +1 -1
- package/dist/components/controlled/input/ControlledSwitchField.d.ts +3 -0
- package/dist/components/controlled/input/ControlledSwitchField.d.ts.map +1 -1
- package/dist/components/controlled/input/ControlledTextField.d.ts +3 -0
- package/dist/components/controlled/input/ControlledTextField.d.ts.map +1 -1
- package/dist/components/controlled/input/ControlledTextareaField.d.ts +3 -0
- package/dist/components/controlled/input/ControlledTextareaField.d.ts.map +1 -1
- package/dist/components/controlled/input/index.d.ts +1 -0
- package/dist/components/controlled/input/index.d.ts.map +1 -1
- package/dist/components/controlled/input/index.js +1 -1
- package/dist/components/controlled/select/ControlledComboboxField.d.ts +4 -0
- package/dist/components/controlled/select/ControlledComboboxField.d.ts.map +1 -1
- package/dist/components/controlled/select/ControlledDropdownField.d.ts +4 -0
- package/dist/components/controlled/select/ControlledDropdownField.d.ts.map +1 -1
- package/dist/components/controlled/select/ControlledMultiDropdownField.d.ts +4 -0
- package/dist/components/controlled/select/ControlledMultiDropdownField.d.ts.map +1 -1
- package/dist/components/controlled/select/ControlledRadioField.d.ts +4 -0
- package/dist/components/controlled/select/ControlledRadioField.d.ts.map +1 -1
- package/dist/components/controlled/select/ControlledYearField.d.ts +9 -0
- package/dist/components/controlled/select/ControlledYearField.d.ts.map +1 -0
- package/dist/components/controlled/select/ControlledYearField.js +1 -0
- package/dist/components/controlled/select/index.d.ts +1 -0
- package/dist/components/controlled/select/index.d.ts.map +1 -1
- package/dist/components/controlled/select/index.js +1 -1
- package/dist/components/controlled/types.d.ts +6 -0
- package/dist/components/controlled/types.d.ts.map +1 -1
- package/dist/components/form/fields/CheckboxFieldComponent.d.ts +3 -3
- package/dist/components/form/fields/CheckboxFieldComponent.d.ts.map +1 -1
- package/dist/components/form/fields/DocumentFieldComponent.d.ts.map +1 -1
- package/dist/components/form/fields/FileFieldComponent.d.ts.map +1 -1
- package/dist/components/form/fields/GdprConsentFieldComponent.d.ts +26 -0
- package/dist/components/form/fields/GdprConsentFieldComponent.d.ts.map +1 -0
- package/dist/components/form/fields/GdprConsentFieldComponent.js +1 -0
- package/dist/components/form/fields/ImageFieldComponent.d.ts +4 -3
- package/dist/components/form/fields/ImageFieldComponent.d.ts.map +1 -1
- package/dist/components/form/fields/ImageFieldComponent.js +1 -1
- package/dist/components/form/fields/PhoneNumberComponent.d.ts.map +1 -1
- package/dist/components/form/fields/PhoneNumberComponent.js +1 -1
- package/dist/components/form/fields/RichTextComponent.d.ts +2 -21
- package/dist/components/form/fields/RichTextComponent.d.ts.map +1 -1
- package/dist/components/form/fields/TextAreaComponent.d.ts.map +1 -1
- package/dist/components/form/fields/TextAreaComponent.js +1 -1
- package/dist/components/form/fields/index.d.ts +3 -1
- package/dist/components/form/fields/index.d.ts.map +1 -1
- package/dist/components/form/fields/index.js +1 -1
- package/dist/components/form/fields/internal/TiptapEditor.d.ts +1 -1
- package/dist/components/form/fields/internal/TiptapEditor.d.ts.map +1 -1
- package/dist/components/form/fields/types.d.ts +33 -0
- package/dist/components/form/fields/types.d.ts.map +1 -0
- package/dist/components/form/fields/types.js +0 -0
- package/dist/components/form/internal/ImageViewerDialog.d.ts +2 -1
- package/dist/components/form/internal/ImageViewerDialog.d.ts.map +1 -1
- package/dist/components/form/internal/ImageViewerDialog.js +1 -1
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +1 -1
- package/dist/contexts/UploadContext.d.ts.map +1 -1
- package/dist/forms/hooks/useEntityForm.d.ts.map +1 -1
- package/dist/forms/hooks/useEntityForm.js +1 -1
- package/dist/forms/index.d.ts +2 -2
- package/dist/forms/index.d.ts.map +1 -1
- package/dist/forms/index.js +1 -1
- package/dist/forms/types.d.ts +15 -0
- package/dist/forms/types.d.ts.map +1 -1
- package/dist/forms/utils/index.d.ts +0 -2
- package/dist/forms/utils/index.d.ts.map +1 -1
- package/dist/forms/utils/index.js +1 -1
- package/dist/forms/utils/validateEntity.js +1 -1
- package/dist/hooks/useFileUpload.d.ts +1 -1
- package/dist/hooks/useFileUpload.d.ts.map +1 -1
- package/dist/hooks/useFileUpload.js +1 -1
- package/dist/hooks/useFormNavigationGuard.d.ts +34 -0
- package/dist/hooks/useFormNavigationGuard.d.ts.map +1 -0
- package/dist/hooks/useFormNavigationGuard.js +1 -0
- package/dist/hooks/useUnsavedChangesWarning.d.ts +51 -0
- package/dist/hooks/useUnsavedChangesWarning.d.ts.map +1 -0
- package/dist/hooks/useUnsavedChangesWarning.js +1 -0
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/stores/FormStore.d.ts +17 -0
- package/dist/stores/FormStore.d.ts.map +1 -1
- package/dist/stores/FormStore.js +1 -1
- package/dist/stores/index.d.ts +1 -1
- package/dist/stores/index.d.ts.map +1 -1
- package/dist/stores/index.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types.d.ts +167 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +0 -0
- package/dist/useCrud.d.ts +1 -2
- package/dist/useCrud.d.ts.map +1 -1
- package/dist/useCrud.js +1 -1
- package/dist/useCrudCardList.d.ts.map +1 -1
- package/dist/useCrudCardList.js +1 -1
- package/dist/useCrudList.d.ts +7 -0
- package/dist/useCrudList.d.ts.map +1 -1
- package/dist/useCrudList.js +1 -1
- package/dist/utils/fileStorage.d.ts +1 -1
- package/dist/utils/fileStorage.d.ts.map +1 -1
- package/dist/utils/imageStorage.d.ts +1 -1
- package/dist/utils/imageStorage.d.ts.map +1 -1
- package/dist/utils/imageUtils.d.ts +1 -1
- package/dist/utils/imageUtils.d.ts.map +1 -1
- package/dist/utils/mergeWithOptimistic.d.ts +1 -1
- package/dist/utils/mergeWithOptimistic.d.ts.map +1 -1
- package/dist/utils/uploadValidation.d.ts +1 -1
- package/dist/utils/uploadValidation.d.ts.map +1 -1
- package/package.json +17 -11
- package/dist/forms/utils/optionHelpers.d.ts +0 -54
- package/dist/forms/utils/optionHelpers.d.ts.map +0 -1
- package/dist/forms/utils/optionHelpers.js +0 -1
package/dist/CrudService.d.ts
CHANGED
|
@@ -1,56 +1,8 @@
|
|
|
1
1
|
import type { dndevSchema, QueryClient } from '@donotdev/core';
|
|
2
|
+
import type { BackendType, CrudStoreApi, CrudServiceInterface, CacheOptions } from './types';
|
|
2
3
|
import type { QueryOptions } from './adapters/FirestoreAdapter';
|
|
3
|
-
import type {
|
|
4
|
-
|
|
5
|
-
type CrudStoreApi = {
|
|
6
|
-
getState: () => CrudState & CrudActions;
|
|
7
|
-
};
|
|
8
|
-
/** Cache options for read operations */
|
|
9
|
-
export interface CacheOptions {
|
|
10
|
-
/** Bypass cache and fetch directly from adapter */
|
|
11
|
-
noCache?: boolean;
|
|
12
|
-
/** Custom stale time in ms (default: Infinity) */
|
|
13
|
-
staleTime?: number;
|
|
14
|
-
}
|
|
15
|
-
export type { QueryOptions };
|
|
16
|
-
export interface CrudServiceInterface {
|
|
17
|
-
initialize(backend: BackendType): Promise<void>;
|
|
18
|
-
setStore(store: CrudStoreApi): void;
|
|
19
|
-
/** Schema accepts unknown since OperationSchemas stores dndevSchema<unknown>. T is for return type. */
|
|
20
|
-
getListQueryOptions<T>(collection: string, queryOptions: QueryOptions, schema: dndevSchema<unknown>, cacheOptions?: CacheOptions, schemaType?: 'list' | 'listCard'): {
|
|
21
|
-
queryKey: readonly string[];
|
|
22
|
-
queryFn: () => Promise<T[]>;
|
|
23
|
-
staleTime: number;
|
|
24
|
-
};
|
|
25
|
-
/** Schema accepts unknown since OperationSchemas stores dndevSchema<unknown>. T is for return type. */
|
|
26
|
-
getDocQueryOptions<T>(collection: string, id: string, schema: dndevSchema<unknown>, cacheOptions?: CacheOptions): {
|
|
27
|
-
queryKey: readonly string[];
|
|
28
|
-
queryFn: () => Promise<T | null>;
|
|
29
|
-
staleTime: number;
|
|
30
|
-
};
|
|
31
|
-
get<T>(collection: string, id: string, schema: dndevSchema<T>, options?: CacheOptions): Promise<T | null>;
|
|
32
|
-
query<T>(collection: string, options: QueryOptions, schema: dndevSchema<T>, cacheOptions?: CacheOptions, schemaType?: 'list' | 'listCard'): Promise<T[]>;
|
|
33
|
-
set<T>(collection: string, id: string, data: T, schema: dndevSchema<T>): Promise<void>;
|
|
34
|
-
update<T>(collection: string, id: string, data: Partial<T>): Promise<void>;
|
|
35
|
-
delete(collection: string, id: string): Promise<void>;
|
|
36
|
-
add<T>(collection: string, data: T, schema: dndevSchema<T>): Promise<string>;
|
|
37
|
-
subscribe<T>(collection: string, id: string, callback: (data: T | null, error?: Error) => void, schema: dndevSchema<T>): () => void;
|
|
38
|
-
subscribeToCollection<T>(collection: string, options: QueryOptions, callback: (data: T[], error?: Error) => void, schema: dndevSchema<T>): () => void;
|
|
39
|
-
/** Add with optimistic update - shows item immediately, confirms/rolls back after server */
|
|
40
|
-
addOptimistic<T extends {
|
|
41
|
-
id?: string;
|
|
42
|
-
}>(collection: string, data: T, schema: dndevSchema<T>): Promise<T & {
|
|
43
|
-
id: string;
|
|
44
|
-
}>;
|
|
45
|
-
/** Update with optimistic update - shows change immediately, confirms/rolls back after server */
|
|
46
|
-
updateOptimistic<T>(collection: string, id: string, data: Partial<T>, schema: dndevSchema<T>): Promise<T>;
|
|
47
|
-
/** Delete with optimistic update - hides item immediately, confirms/restores after server */
|
|
48
|
-
deleteOptimistic(collection: string, id: string): Promise<void>;
|
|
49
|
-
/** Invalidate all cached queries for a collection */
|
|
50
|
-
invalidateCollection(collection: string): Promise<void>;
|
|
51
|
-
/** Get the shared QueryClient instance from @donotdev/hooks */
|
|
52
|
-
getQueryClient(): QueryClient;
|
|
53
|
-
}
|
|
4
|
+
import type { PaginatedQueryResult } from './adapters/FunctionsAdapter';
|
|
5
|
+
export type { QueryOptions, CacheOptions };
|
|
54
6
|
/**
|
|
55
7
|
* Complete CRUD orchestrator with TanStack Query caching
|
|
56
8
|
*
|
|
@@ -65,7 +17,7 @@ declare class CrudService implements CrudServiceInterface {
|
|
|
65
17
|
setStore(store: CrudStoreApi): void;
|
|
66
18
|
initialize(backend: BackendType): Promise<void>;
|
|
67
19
|
/**
|
|
68
|
-
* Get shared QueryClient instance from @donotdev/
|
|
20
|
+
* Get shared QueryClient instance from @donotdev/core.
|
|
69
21
|
* Uses singleton on client, new instance per request on server (SSR-safe).
|
|
70
22
|
*/
|
|
71
23
|
getQueryClient(): QueryClient;
|
|
@@ -76,7 +28,7 @@ declare class CrudService implements CrudServiceInterface {
|
|
|
76
28
|
*/
|
|
77
29
|
getListQueryOptions<T>(collection: string, queryOptions: QueryOptions, schema: dndevSchema<unknown>, cacheOptions?: CacheOptions, schemaType?: 'list' | 'listCard'): {
|
|
78
30
|
queryKey: readonly ["crud", string, "query", "list" | "listCard", string];
|
|
79
|
-
queryFn: () => Promise<T
|
|
31
|
+
queryFn: () => Promise<PaginatedQueryResult<T>>;
|
|
80
32
|
staleTime: number;
|
|
81
33
|
};
|
|
82
34
|
/**
|
|
@@ -106,7 +58,7 @@ declare class CrudService implements CrudServiceInterface {
|
|
|
106
58
|
get<T>(collection: string, id: string, schema: dndevSchema<T>, options?: CacheOptions): Promise<T | null>;
|
|
107
59
|
/** Internal: fetch from adapter with store updates */
|
|
108
60
|
private _getFromAdapter;
|
|
109
|
-
query<T>(collection: string, options: QueryOptions, schema: dndevSchema<T>, cacheOptions?: CacheOptions, schemaType?: 'list' | 'listCard'): Promise<T
|
|
61
|
+
query<T>(collection: string, options: QueryOptions, schema: dndevSchema<T>, cacheOptions?: CacheOptions, schemaType?: 'list' | 'listCard'): Promise<PaginatedQueryResult<T>>;
|
|
110
62
|
/** Internal: query from adapter with store updates */
|
|
111
63
|
private _queryFromAdapter;
|
|
112
64
|
set<T>(collection: string, id: string, data: T, schema: dndevSchema<T>): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CrudService.d.ts","sourceRoot":"","sources":["../src/CrudService.ts"],"names":[],"mappings":"AA6BA,
|
|
1
|
+
{"version":3,"file":"CrudService.d.ts","sourceRoot":"","sources":["../src/CrudService.ts"],"names":[],"mappings":"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"}
|
package/dist/CrudService.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{toast as f}from"@donotdev/components";import{createSingleton as
|
|
1
|
+
import{toast as f}from"@donotdev/components";import{createSingleton as g,handleError as o,getQueryClient as y}from"@donotdev/core";import{FirestoreAdapter as w}from"./adapters/FirestoreAdapter";import{FunctionsAdapter as S}from"./adapters/FunctionsAdapter";const n=1/0,A=1e3*60*30;class m{adapter=null;backend=null;store=null;setStore(t){this.store=t}async initialize(t){if(!(this.backend===t&&this.adapter)){if(this.backend=t,t==="functions")this.adapter=new S;else if(t==="firestore")this.adapter=new w;else throw new Error(`Unknown backend: ${t}`);this.store&&(this.store.getState().setBackend(t),this.store.getState().setCrudService(this))}}getQueryClient(){return y()}getListQueryOptions(t,e,s,i,r="list"){const a=this.adapter,h=()=>this.initialize("firestore");return{queryKey:["crud",t,"query",r,JSON.stringify(e)],queryFn:async()=>{if(a||await h(),!this.adapter)throw new Error("Adapter not initialized");return this.adapter.query(t,e,s)},staleTime:i?.staleTime??n}}getDocQueryOptions(t,e,s,i){const r=this.adapter,a=()=>this.initialize("firestore");return{queryKey:["crud",t,"get",e],queryFn:async()=>{if(r||await a(),!this.adapter)throw new Error("Adapter not initialized");return this.adapter.get(t,e,s)},staleTime:i?.staleTime??n}}_updateGetCache(t,e,s,i){const r=this.getQueryClient(),a=["crud",t,"get",e];i==="delete"?r.removeQueries({queryKey:a}):(i==="update"||i==="add")&&s&&r.setQueryData(a,h=>h?{...h,...s}:s)}_updateListCaches(t,e,s,i){const r=this.getQueryClient();this._updateGetCache(t,e,s,i),r.setQueriesData({queryKey:["crud",t]},a=>Array.isArray(a)?i==="delete"?a.filter(h=>h.id!==e):i==="add"&&s?[...a,{...s,id:e}]:i==="update"&&s&&a.some(u=>u.id===e)?a.map(u=>u.id===e?{...u,...s}:u):a:a)}async invalidateCollection(t){await this.getQueryClient().invalidateQueries({queryKey:["crud",t]})}async get(t,e,s,i){if(this.adapter||await this.initialize("firestore"),i?.noCache)return this._getFromAdapter(t,e,s);this.store&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));try{return await this.getQueryClient().fetchQuery({queryKey:["crud",t,"get",e],queryFn:()=>this._getFromAdapter(t,e,s,!1),staleTime:i?.staleTime??n})}catch(r){const a=o(r,{userMessage:`Failed to fetch ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,a),a}finally{this.store&&this.store.getState().setLoading(t,!1)}}async _getFromAdapter(t,e,s,i=!0){this.store&&i&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));try{if(!this.adapter)throw new Error("Adapter not initialized");const r=await this.adapter.get(t,e,s);return this.store&&r&&this.store.getState().setData(t,e,r),r}catch(r){const a=o(r,{userMessage:`Failed to fetch ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,a),a}finally{this.store&&i&&this.store.getState().setLoading(t,!1)}}async query(t,e,s,i,r="list"){if(this.adapter||await this.initialize("firestore"),i?.noCache)return this._queryFromAdapter(t,e,s);this.store&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));try{const h=await this.getQueryClient().fetchQuery({queryKey:["crud",t,"query",r,JSON.stringify(e)],queryFn:()=>this._queryFromAdapter(t,e,s,!1),staleTime:i?.staleTime??n});if(this.store&&h.items){const u=[];for(const d of h.items){const p=d;p.id&&u.push({id:p.id,data:d})}u.length>0&&this.store.getState().setDataBatch(t,u)}return h}catch(a){const h=o(a,{userMessage:`Failed to query ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,h),h}finally{this.store&&this.store.getState().setLoading(t,!1)}}async _queryFromAdapter(t,e,s,i=!0){this.store&&i&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));try{if(!this.adapter)throw new Error("Adapter not initialized");return await this.adapter.query(t,e,s)}catch(r){const a=o(r,{userMessage:`Failed to query ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,a),a}finally{this.store&&i&&this.store.getState().setLoading(t,!1)}}async set(t,e,s,i){this.adapter||await this.initialize("firestore"),this.store&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));const r=this.store?.getState().getData(t,e);this.store&&this.store.getState().updateOptimistic(t,e,s,r);try{if(!this.adapter)throw new Error("Adapter not initialized");await this.adapter.set(t,e,s,i),this.store&&(this.store.getState().confirmUpdate(t,e),this.store.getState().setData(t,e,s)),this._updateListCaches(t,e,s,"update"),f("success",`${t} saved successfully`)}catch(a){this.store&&this.store.getState().rejectUpdate(t,e);const h=o(a,{userMessage:`Failed to save ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,h),h}finally{this.store&&this.store.getState().setLoading(t,!1)}}async update(t,e,s){this.adapter||await this.initialize("firestore"),this.store&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));let i=null;this.store&&(i=this.store.getState().getData(t,e));const r=i?{...i,...s}:{...s,id:e};this.store&&i&&this.store.getState().updateOptimistic(t,e,r,i);try{if(!this.adapter)throw new Error("Adapter not initialized");await this.adapter.update(t,e,s),this.store&&(this.store.getState().confirmUpdate(t,e),this.store.getState().setData(t,e,r)),this._updateListCaches(t,e,r,"update"),f("success",`${t} updated successfully`)}catch(a){this.store&&this.store.getState().rejectUpdate(t,e);const h=o(a,{userMessage:`Failed to update ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,h),h}finally{this.store&&this.store.getState().setLoading(t,!1)}}async delete(t,e){this.adapter||await this.initialize("firestore"),this.store&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));const s=this.store?.getState().getData(t,e);this.store&&s&&this.store.getState().deleteOptimistic(t,e,s);try{if(!this.adapter)throw new Error("Adapter not initialized");await this.adapter.delete(t,e),this.store&&this.store.getState().confirmDelete(t,e),this._updateListCaches(t,e,null,"delete"),f("success",`${t} deleted successfully`)}catch(i){this.store&&this.store.getState().rejectDelete(t,e);const r=o(i,{userMessage:`Failed to delete ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,r),r}finally{this.store&&this.store.getState().setLoading(t,!1)}}async add(t,e,s){this.adapter||await this.initialize("firestore"),this.store&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));const i=`temp_${crypto.randomUUID()}`;this.store&&this.store.getState().addOptimistic(t,i,{...e,id:i});try{if(!this.adapter)throw new Error("Adapter not initialized");const r=await this.adapter.add(t,e,s);return this.store&&this.store.getState().confirmOptimistic(t,i,r,{...e,id:r}),this._updateListCaches(t,r,{...e,id:r},"add"),f("success",`${t} created successfully`),r}catch(r){this.store&&this.store.getState().rejectOptimistic(t,i);const a=o(r,{userMessage:`Failed to create ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,a),a}finally{this.store&&this.store.getState().setLoading(t,!1)}}subscribe(t,e,s,i){this.adapter||this.initialize("firestore").catch(()=>{});try{return this.adapter?this.adapter.subscribe(t,e,(r,a)=>{r&&this.store&&this.store.getState().setData(t,e,r),r&&this.getQueryClient().setQueryData(["crud",t,"get",e],r),s(r,a)},i):(s(null,new Error("Adapter not initialized")),()=>{})}catch(r){return s(null,o(r)),()=>{}}}subscribeToCollection(t,e,s,i){this.adapter||this.initialize("firestore").catch(()=>{});try{return this.adapter?this.adapter.subscribeToCollection(t,e,(r,a)=>{if(r&&this.store){const h=[];for(const u of r){const d=u;d.id&&h.push({id:d.id,data:u})}h.length>0&&this.store.getState().setDataBatch(t,h)}r&&this.getQueryClient().setQueryData(["crud",t,"query",JSON.stringify(e)],r),s(r,a)},i):(s([],new Error("Adapter not initialized")),()=>{})}catch(r){return s([],o(r)),()=>{}}}async addOptimistic(t,e,s){this.adapter||await this.initialize("firestore");const i=`temp_${crypto.randomUUID()}`,r={...e,id:i,_optimistic:!0};this.store&&this.store.getState().addOptimistic(t,i,r);try{if(!this.adapter)throw new Error("Adapter not initialized");const a=await this.adapter.add(t,e,s),h={...e,id:a};return this.store&&this.store.getState().confirmOptimistic(t,i,a,h),this._updateListCaches(t,a,h,"add"),f("success",`${t} created successfully`),h}catch(a){throw this.store&&this.store.getState().rejectOptimistic(t,i),o(a,{userMessage:`Failed to create ${t}`,showNotification:!0})}}async updateOptimistic(t,e,s,i){this.adapter||await this.initialize("firestore");let r=null;this.store&&(r=this.store.getState().getData(t,e));const a=r?{...r,...s,_optimistic:!0}:{...s,id:e,_optimistic:!0};this.store&&r&&this.store.getState().updateOptimistic(t,e,a,r);try{if(!this.adapter)throw new Error("Adapter not initialized");return await this.adapter.update(t,e,s),this.store&&(this.store.getState().confirmUpdate(t,e),this.store.getState().setData(t,e,{...a,_optimistic:void 0})),this._updateListCaches(t,e,a,"update"),f("success",`${t} updated successfully`),a}catch(h){throw this.store&&this.store.getState().rejectUpdate(t,e),o(h,{userMessage:`Failed to update ${t}`,showNotification:!0})}}async deleteOptimistic(t,e){this.adapter||await this.initialize("firestore");let s=null;this.store&&(s=this.store.getState().getData(t,e)),this.store&&s&&this.store.getState().deleteOptimistic(t,e,s);try{if(!this.adapter)throw new Error("Adapter not initialized");await this.adapter.delete(t,e),this.store&&this.store.getState().confirmDelete(t,e),this._updateListCaches(t,e,null,"delete"),f("success",`${t} deleted successfully`)}catch(i){throw this.store&&this.store.getState().rejectDelete(t,e),o(i,{userMessage:`Failed to delete ${t}`,showNotification:!0})}}}const F=g(()=>new m);export{F as getCrudService};
|
package/dist/CrudStore.d.ts
CHANGED
|
@@ -1,97 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
/**
|
|
3
|
-
* Backend type for CRUD operations
|
|
4
|
-
*
|
|
5
|
-
* @version 0.0.1
|
|
6
|
-
* @since 0.0.1
|
|
7
|
-
* @author AMBROISE PARK Consulting
|
|
8
|
-
*/
|
|
9
|
-
export type BackendType = 'functions' | 'firestore';
|
|
10
|
-
/**
|
|
11
|
-
* Optimistic operation status
|
|
12
|
-
*/
|
|
13
|
-
export type OptimisticStatus = 'pending' | 'confirmed' | 'failed';
|
|
14
|
-
/**
|
|
15
|
-
* Optimistic operation metadata
|
|
16
|
-
*/
|
|
17
|
-
export interface OptimisticMeta {
|
|
18
|
-
tempId: string;
|
|
19
|
-
originalData: unknown | null;
|
|
20
|
-
status: OptimisticStatus;
|
|
21
|
-
operation: 'add' | 'update' | 'delete';
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* CRUD store state interface
|
|
25
|
-
*
|
|
26
|
-
* @version 0.0.2
|
|
27
|
-
* @since 0.0.1
|
|
28
|
-
* @author AMBROISE PARK Consulting
|
|
29
|
-
*/
|
|
30
|
-
export interface CrudState {
|
|
31
|
-
backend: BackendType | null;
|
|
32
|
-
crudService: CrudServiceInterface | null;
|
|
33
|
-
collections: Record<string, {
|
|
34
|
-
loading: boolean;
|
|
35
|
-
error: Error | null;
|
|
36
|
-
data: Record<string, unknown>;
|
|
37
|
-
lastUpdated: number;
|
|
38
|
-
/** Optimistic operation metadata keyed by document id */
|
|
39
|
-
optimistic: Record<string, OptimisticMeta>;
|
|
40
|
-
}>;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* CRUD store actions interface
|
|
44
|
-
*
|
|
45
|
-
* @version 0.0.2
|
|
46
|
-
* @since 0.0.1
|
|
47
|
-
* @author AMBROISE PARK Consulting
|
|
48
|
-
*/
|
|
49
|
-
export interface CrudActions {
|
|
50
|
-
setCrudService: (service: CrudServiceInterface) => void;
|
|
51
|
-
setBackend: (backend: BackendType) => void;
|
|
52
|
-
setLoading: (collection: string, loading: boolean) => void;
|
|
53
|
-
setError: (collection: string, error: Error | null) => void;
|
|
54
|
-
setData: (collection: string, id: string, data: unknown) => void;
|
|
55
|
-
/** Batch update multiple documents in a single state update (performance) */
|
|
56
|
-
setDataBatch: (collection: string, items: Array<{
|
|
57
|
-
id: string;
|
|
58
|
-
data: unknown;
|
|
59
|
-
}>) => void;
|
|
60
|
-
removeData: (collection: string, id: string) => void;
|
|
61
|
-
clearCollection: (collection: string) => void;
|
|
62
|
-
clearError: (collection: string) => void;
|
|
63
|
-
/** Add item optimistically (before server confirms) */
|
|
64
|
-
addOptimistic: (collection: string, tempId: string, data: unknown) => void;
|
|
65
|
-
/** Confirm optimistic add - replace temp item with real item */
|
|
66
|
-
confirmOptimistic: (collection: string, tempId: string, realId: string, realData: unknown) => void;
|
|
67
|
-
/** Reject optimistic add - remove temp item */
|
|
68
|
-
rejectOptimistic: (collection: string, tempId: string) => void;
|
|
69
|
-
/** Update item optimistically */
|
|
70
|
-
updateOptimistic: (collection: string, id: string, data: unknown, originalData: unknown) => void;
|
|
71
|
-
/** Confirm optimistic update */
|
|
72
|
-
confirmUpdate: (collection: string, id: string) => void;
|
|
73
|
-
/** Reject optimistic update - restore original data */
|
|
74
|
-
rejectUpdate: (collection: string, id: string) => void;
|
|
75
|
-
/** Delete item optimistically (hide but keep for rollback) */
|
|
76
|
-
deleteOptimistic: (collection: string, id: string, originalData: unknown) => void;
|
|
77
|
-
/** Confirm optimistic delete - remove completely */
|
|
78
|
-
confirmDelete: (collection: string, id: string) => void;
|
|
79
|
-
/** Reject optimistic delete - restore item */
|
|
80
|
-
rejectDelete: (collection: string, id: string) => void;
|
|
81
|
-
getLoading: (collection: string) => boolean;
|
|
82
|
-
getError: (collection: string) => Error | null;
|
|
83
|
-
getData: (collection: string, id: string) => unknown | null;
|
|
84
|
-
/** Check if item is optimistic (not yet confirmed by server) */
|
|
85
|
-
isOptimistic: (collection: string, id: string) => boolean;
|
|
86
|
-
/** Get optimistic status for an item */
|
|
87
|
-
getOptimisticStatus: (collection: string, id: string) => OptimisticStatus | null;
|
|
88
|
-
/** Get all items in collection (including optimistic, excluding deleted) */
|
|
89
|
-
getCollectionData: (collection: string) => Array<{
|
|
90
|
-
id: string;
|
|
91
|
-
data: unknown;
|
|
92
|
-
isOptimistic: boolean;
|
|
93
|
-
}>;
|
|
94
|
-
}
|
|
1
|
+
import type { CrudState, CrudActions } from './types';
|
|
95
2
|
/**
|
|
96
3
|
* CRUD store hook for accessing CRUD state and actions
|
|
97
4
|
*
|
package/dist/CrudStore.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CrudStore.d.ts","sourceRoot":"","sources":["../src/CrudStore.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"CrudStore.d.ts","sourceRoot":"","sources":["../src/CrudStore.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAIV,SAAS,EACT,WAAW,EAEZ,MAAM,SAAS,CAAC;AAQjB;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,iIAoevB,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { dndevSchema } from '@donotdev/core';
|
|
2
2
|
import { type Unsubscribe, type FirestoreError } from '@donotdev/firebase';
|
|
3
|
+
import type { PaginatedQueryResult } from './FunctionsAdapter';
|
|
3
4
|
/**
|
|
4
5
|
* Firestore query operators
|
|
5
6
|
*/
|
|
@@ -22,6 +23,7 @@ export interface QueryOptions {
|
|
|
22
23
|
direction?: 'asc' | 'desc';
|
|
23
24
|
}>;
|
|
24
25
|
limit?: number;
|
|
26
|
+
startAfterId?: string;
|
|
25
27
|
}
|
|
26
28
|
/**
|
|
27
29
|
* Subscription callback for document subscriptions
|
|
@@ -56,7 +58,7 @@ export declare class FirestoreAdapter {
|
|
|
56
58
|
update<T>(collectionName: string, id: string, data: Partial<T>): Promise<void>;
|
|
57
59
|
delete(collectionName: string, id: string): Promise<void>;
|
|
58
60
|
add<T>(collectionName: string, data: T, schema: dndevSchema<T>): Promise<string>;
|
|
59
|
-
query<T>(collectionName: string, options: QueryOptions, schema: dndevSchema<unknown>): Promise<T
|
|
61
|
+
query<T>(collectionName: string, options: QueryOptions, schema: dndevSchema<unknown>): Promise<PaginatedQueryResult<T>>;
|
|
60
62
|
subscribe<T>(collectionName: string, id: string, callback: SubscriptionCallback<T>, schema: dndevSchema<unknown>): Unsubscribe;
|
|
61
63
|
subscribeToCollection<T>(collectionName: string, options: QueryOptions, callback: CollectionSubscriptionCallback<T>, schema: dndevSchema<unknown>): Unsubscribe;
|
|
62
64
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FirestoreAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/FirestoreAdapter.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,
|
|
1
|
+
{"version":3,"file":"FirestoreAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/FirestoreAdapter.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAsBL,KAAK,WAAW,EAChB,KAAK,cAAc,EACpB,MAAM,oBAAoB,CAAC;AAO5B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE/D;;GAEG;AACH,MAAM,MAAM,iBAAiB,GACzB,IAAI,GACJ,IAAI,GACJ,GAAG,GACH,IAAI,GACJ,GAAG,GACH,IAAI,GACJ,gBAAgB,GAChB,IAAI,GACJ,QAAQ,CAAC;AAEb;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,iBAAiB,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC9E,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,CAAC,CAAC,IAAI,CACpC,IAAI,EAAE,CAAC,GAAG,IAAI,EACd,KAAK,CAAC,EAAE,cAAc,KACnB,IAAI,CAAC;AACV;;;;;;GAMG;AACH,MAAM,MAAM,8BAA8B,CAAC,CAAC,IAAI,CAC9C,IAAI,EAAE,CAAC,EAAE,EACT,KAAK,CAAC,EAAE,cAAc,KACnB,IAAI,CAAC;AAEV;;;;;;;GAOG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,SAAS,CAAwB;IAEzC,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,gBAAgB;IAKlB,GAAG,CAAC,CAAC,EACT,cAAc,EAAE,MAAM,EACtB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,GAC3B,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IA2Bd,GAAG,CAAC,CAAC,EACT,cAAc,EAAE,MAAM,EACtB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,CAAC,EACP,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GACrB,OAAO,CAAC,IAAI,CAAC;IAYV,MAAM,CAAC,CAAC,EACZ,cAAc,EAAE,MAAM,EACtB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GACf,OAAO,CAAC,IAAI,CAAC;IAWV,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUzD,GAAG,CAAC,CAAC,EACT,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,CAAC,EACP,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GACrB,OAAO,CAAC,MAAM,CAAC;IA+CZ,KAAK,CAAC,CAAC,EACX,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,GAC3B,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC;IA6FnC,SAAS,CAAC,CAAC,EACT,cAAc,EAAE,MAAM,EACtB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,oBAAoB,CAAC,CAAC,CAAC,EACjC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,GAC3B,WAAW;IA8Bd,qBAAqB,CAAC,CAAC,EACrB,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,8BAA8B,CAAC,CAAC,CAAC,EAC3C,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,GAC3B,WAAW;CAgDf"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as
|
|
1
|
+
import*as u from"valibot";import{handleError as F}from"@donotdev/core";import{getFirestore as B,getFirebaseSDK as C,doc as h,getDoc as w,getDocs as E,setDoc as v,updateDoc as V,deleteDoc as z,addDoc as M,collection as L,query as A,where as D,orderBy as R,limit as I,startAfter as S,onSnapshot as q}from"@donotdev/firebase";import{transformFirestoreData as y,prepareForFirestore as m}from"@donotdev/firebase";class U{firestore;ensureFirestore(){if(this.firestore)return!0;try{return this.firestore=B(),!0}catch{return!1}}getCollectionRef(o){return!this.ensureFirestore()||!this.firestore?null:L(this.firestore,o)}async get(o,e,t){if(!this.ensureFirestore()||!this.firestore)return null;try{const i=h(this.firestore,o,e),r=await w(i);if(!r.exists())return null;let s=r.data();return s=y(s),{...u.parse(t,s),id:e}}catch(i){return F(i,{context:{operation:"FirestoreAdapter.get",collection:o,docId:e},severity:"warning"}),null}}async set(o,e,t,i){if(!(!this.ensureFirestore()||!this.firestore))try{u.parse(i,t);const r=h(this.firestore,o,e),s=m(t);await v(r,s)}catch(r){throw r}}async update(o,e,t){if(!(!this.ensureFirestore()||!this.firestore))try{const i=h(this.firestore,o,e),r=m(t);await V(i,r)}catch(i){throw i}}async delete(o,e){if(!(!this.ensureFirestore()||!this.firestore))try{const t=h(this.firestore,o,e);await z(t)}catch(t){throw t}}async add(o,e,t){if(!this.ensureFirestore())return"";try{u.parse(t,e);const i=this.getCollectionRef(o);if(!i)return"";const r=new Date().toISOString(),s=C().getCurrentUser()?.uid||"anonymous",c={...e,createdAt:r,updatedAt:r,createdById:s,updatedById:s},a=m(c);return(await M(i,a)).id}catch(i){throw i}}async query(o,e,t){if(!this.ensureFirestore())return{items:[]};const i=this.getCollectionRef(o);if(!i)return{items:[]};try{const r=[];if(e.where)for(const n of e.where)r.push(D(n.field,n.operator,n.value));if(e.orderBy)for(const n of e.orderBy)r.push(R(n.field,n.direction||"asc"));if(e.startAfterId){const n=await w(h(i,e.startAfterId));n.exists()&&r.push(S(n))}const s=e.limit?e.limit+1:void 0;s&&r.push(I(s));const c=A(i,...r),a=await E(c),d=[];let p=null;a.forEach(n=>{try{let l=n.data();if(!l)return;l=y(l);const x=u.parse(t,l);d.push({...x,id:n.id}),p=n.id}catch(l){F(l,{context:{operation:"FirestoreAdapter.query.parse",docId:n.id,collection:o},showNotification:!1})}});const f=s?d.length>(e.limit||0):!1;return{items:f?d.slice(0,e.limit):d,hasMore:f,lastVisible:p,total:void 0}}catch(r){throw F(r,{context:{operation:"FirestoreAdapter.query",collection:o,options:e}}),r}}subscribe(o,e,t,i){if(!this.ensureFirestore()||!this.firestore)return()=>{};const r=h(this.firestore,o,e);return q(r,s=>{try{if(!s.exists()){t(null);return}let c=s.data();c=y(c);const a=u.parse(i,c);t({...a,id:e})}catch(c){t(null,c)}},s=>{t(null,s)})}subscribeToCollection(o,e,t,i){if(!this.ensureFirestore())return()=>{};const r=this.getCollectionRef(o);if(!r)return()=>{};try{const s=[];if(e.where)for(const a of e.where)s.push(D(a.field,a.operator,a.value));if(e.orderBy)for(const a of e.orderBy)s.push(R(a.field,a.direction||"asc"));e.limit&&s.push(I(e.limit));const c=A(r,...s);return q(c,a=>{try{const d=[];a.forEach(p=>{let f=p.data();f=y(f);const g=u.parse(i,f);d.push({...g,id:p.id})}),t(d)}catch(d){t([],d)}},a=>{t([],a)})}catch(s){return t([],s),()=>{}}}}export{U as FirestoreAdapter};
|
|
@@ -17,6 +17,13 @@ export interface FunctionsQueryOptions {
|
|
|
17
17
|
direction?: 'asc' | 'desc';
|
|
18
18
|
}>;
|
|
19
19
|
limit?: number;
|
|
20
|
+
startAfterId?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface PaginatedQueryResult<T> {
|
|
23
|
+
items: T[];
|
|
24
|
+
total?: number;
|
|
25
|
+
hasMore?: boolean;
|
|
26
|
+
lastVisible?: string | null;
|
|
20
27
|
}
|
|
21
28
|
/**
|
|
22
29
|
* Functions backend adapter
|
|
@@ -37,7 +44,7 @@ export declare class FunctionsAdapter {
|
|
|
37
44
|
update<T>(collectionName: string, id: string, data: Partial<T>): Promise<void>;
|
|
38
45
|
delete(collectionName: string, id: string): Promise<void>;
|
|
39
46
|
add<T>(collectionName: string, data: T, schema: dndevSchema<T>): Promise<string>;
|
|
40
|
-
query<T>(collectionName: string, options: FunctionsQueryOptions, schema: dndevSchema<unknown>): Promise<T
|
|
47
|
+
query<T>(collectionName: string, options: FunctionsQueryOptions, schema: dndevSchema<unknown>): Promise<PaginatedQueryResult<T>>;
|
|
41
48
|
listCard<T>(collectionName: string, options: FunctionsQueryOptions, schema: dndevSchema<T>): Promise<T[]>;
|
|
42
49
|
subscribe<T>(): () => void;
|
|
43
50
|
subscribeToCollection<T>(): () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FunctionsAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/FunctionsAdapter.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGlD;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,GAAG,CAAC;QAAC,KAAK,EAAE,GAAG,CAAA;KAAE,CAAC,CAAC;IAC5D,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"FunctionsAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/FunctionsAdapter.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGlD;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,GAAG,CAAC;QAAC,KAAK,EAAE,GAAG,CAAA;KAAE,CAAC,CAAC;IAC5D,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB,CAAC,CAAC;IACrC,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED;;;;;;;;GAQG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,MAAM,CAAS;;YAOT,eAAe;IAUvB,GAAG,CAAC,CAAC,EACT,cAAc,EAAE,MAAM,EACtB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,GAC3B,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAed,GAAG,CAAC,CAAC,EACT,cAAc,EAAE,MAAM,EACtB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,CAAC,EACP,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GACrB,OAAO,CAAC,IAAI,CAAC;IAeV,MAAM,CAAC,CAAC,EACZ,cAAc,EAAE,MAAM,EACtB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GACf,OAAO,CAAC,IAAI,CAAC;IAcV,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAczD,GAAG,CAAC,CAAC,EACT,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,CAAC,EACP,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GACrB,OAAO,CAAC,MAAM,CAAC;IAgBZ,KAAK,CAAC,CAAC,EACX,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,qBAAqB,EAC9B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,GAC3B,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC;IAwD7B,QAAQ,CAAC,CAAC,EACd,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,qBAAqB,EAC9B,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GACrB,OAAO,CAAC,CAAC,EAAE,CAAC;IAgDf,SAAS,CAAC,CAAC,KAAK,MAAM,IAAI;IAM1B,qBAAqB,CAAC,CAAC,KAAK,MAAM,IAAI;CAKvC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{httpsCallable as
|
|
1
|
+
import{httpsCallable as i}from"firebase/functions";import*as u from"valibot";import{getPlatformEnvVar as l}from"@donotdev/core";import{getFirebaseFunctions as f}from"@donotdev/firebase";class F{functions;region;constructor(){this.region=l("FIREBASE_FUNCTIONS_REGION")||"europe-west1"}async ensureFunctions(){if(this.functions)return!0;try{return this.functions=await f(this.region),!0}catch{return!1}}async get(a,t,n){if(!await this.ensureFunctions())return null;try{const r=`get_${a}`;return(await i(this.functions,r)({id:t})).data}catch(r){throw r}}async set(a,t,n,r){if(await this.ensureFunctions())try{u.parse(r,n);const e=`update_${a}`;await i(this.functions,e)({id:t,payload:n})}catch(e){throw e}}async update(a,t,n){if(await this.ensureFunctions())try{const r=`update_${a}`;await i(this.functions,r)({id:t,payload:n})}catch(r){throw r}}async delete(a,t){if(await this.ensureFunctions())try{const n=`delete_${a}`;await i(this.functions,n)({id:t})}catch(n){throw n}}async add(a,t,n){if(!await this.ensureFunctions())return"";try{u.parse(n,t);const r=`create_${a}`;return(await i(this.functions,r)({payload:t})).data.id}catch(r){throw r}}async query(a,t,n){if(!await this.ensureFunctions())return{items:[]};try{const r=`list_${a}`,e={};t.where&&(e.where=t.where.map(s=>[s.field,s.operator,s.value])),t.orderBy&&(e.orderBy=t.orderBy.map(s=>[s.field,s.direction||"asc"])),t.limit&&(e.limit=t.limit),t.startAfterId&&(e.startAfterId=t.startAfterId);const c=await i(this.functions,r)(e);return{items:c.data.items,total:c.data.count,hasMore:c.data.hasMore,lastVisible:c.data.lastVisible}}catch(r){throw r}}async listCard(a,t,n){if(!await this.ensureFunctions())return[];try{const r=`listCard_${a}`,e={};return t.where&&(e.where=t.where.map(s=>[s.field,s.operator,s.value])),t.orderBy&&(e.orderBy=t.orderBy.map(s=>[s.field,s.direction||"asc"])),t.limit&&(e.limit=t.limit),(await i(this.functions,r)(e)).data.items}catch(r){throw r}}subscribe(){throw new Error("Subscriptions are not supported with Functions backend. Use Firestore backend for real-time features.")}subscribeToCollection(){throw new Error("Subscriptions are not supported with Functions backend. Use Firestore backend for real-time features.")}}export{F as FunctionsAdapter};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builtinFieldTypes.d.ts","sourceRoot":"","sources":["../src/builtinFieldTypes.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"builtinFieldTypes.d.ts","sourceRoot":"","sources":["../src/builtinFieldTypes.tsx"],"names":[],"mappings":"AA2KA;;;;;;GAMG;AACH,wBAAgB,yBAAyB,IAAI,IAAI,CA6GhD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as s}from"react/jsx-runtime";import{ControlledCheckboxField as g,ControlledComboboxField as
|
|
1
|
+
"use client";import{jsx as s}from"react/jsx-runtime";import{ControlledCheckboxField as g,ControlledComboboxField as F,ControlledDateField as C,ControlledDropdownField as f,ControlledFileField as h,ControlledMultiFileField as b,ControlledDocumentField as x,ControlledMultiDocumentField as v,ControlledGeoPointField as T,ControlledImageField as U,ControlledMapField as w,ControlledMultiDropdownField as y,ControlledMultiInputField as R,ControlledNumberField as p,ControlledPasswordField as M,ControlledPhoneField as k,ControlledRangeField as D,ControlledRadioField as A,ControlledTextField as d,ControlledTextareaField as B,ControlledRichTextField as I,ControlledTimestampField as P,ControlledAddressField as j,ControlledSwitchField as G,ControlledMultiImageField as H,ControlledGdprConsentField as S}from"./components/controlled";import{AvatarFieldComponent as N,BadgeFieldComponent as Y,ButtonFieldComponent as c,HiddenFieldComponent as _,TextAreaComponent as q,RichTextComponent as z,TextFieldComponent as E}from"./components/form/fields";import{getFieldRegistry as J}from"./FieldRegistry";const K=e=>{const{name:t,value:o,onChange:r,error:n,t:i,config:l,...a}=e;return s(N,{config:l,value:o,onChange:r,error:!!n,helperText:n||void 0,t:i,...l.options,...a})},L=e=>{const{name:t,value:o,onChange:r,error:n,t:i,config:l,...a}=e;return s(Y,{config:l,value:o,onChange:r,error:!!n,helperText:n||void 0,t:i,...l.options,...a})},O=e=>{const{name:t,label:o,onChange:r,config:n}=e;return s(c,{label:o||t,type:"submit",onClick:()=>r(void 0),...n.options})},Q=e=>{const{name:t,label:o,onChange:r,config:n}=e;return s(c,{label:o||t,type:"reset",onClick:()=>r(void 0),...n.options})},V=e=>{const{name:t,value:o}=e;return s(_,{name:t,value:o})},W=e=>{const{name:t,label:o,value:r,onChange:n,error:i,config:l}=e;return s(q,{label:o||t,value:r,onChange:n,error:i||void 0,...l.options})},X=e=>{const{name:t,label:o,value:r,onChange:n,error:i,config:l}=e;return s(z,{label:o||t,value:r,onChange:n,error:i||void 0,...l.options})},m=e=>{const{name:t,label:o,value:r,onChange:n,error:i,config:l}=e;return s(E,{label:o||t,value:r,onChange:n,error:i||void 0,...l.options})};let u=!1;function Z(){if(u)return;u=!0;const e=J();e.registerComponent("text",d,m),e.registerComponent("email",d,m),e.registerComponent("url",d,m),e.registerComponent("color",d,m),e.registerComponent("textarea",B,W),e.registerComponent("richtext",I,X),e.registerComponent("password",M),e.registerComponent("number",p),e.registerComponent("range",D),e.registerComponent("year",p),e.registerComponent("boolean",g),e.registerComponent("checkbox",g),e.registerComponent("gdprConsent",S),e.registerComponent("switch",G),e.registerComponent("date",C),e.registerComponent("datetime-local",C),e.registerComponent("time",C),e.registerComponent("week",C),e.registerComponent("month",C),e.registerComponent("timestamp",P),e.registerComponent("file",h),e.registerComponent("files",b),e.registerComponent("document",x),e.registerComponent("documents",v),e.registerComponent("image",U),e.registerComponent("images",H),e.registerComponent("geopoint",T),e.registerComponent("address",j),e.registerComponent("map",w),e.registerComponent("array",R),e.registerComponent("select",f),e.registerComponent("combobox",F),e.registerComponent("multiselect",y),e.registerComponent("radio",A),e.registerComponent("tel",k),e.registerComponent("avatar",d,K),e.registerComponent("badge",d,L),e.registerComponent("hidden",d,V),e.registerComponent("submit",d,O),e.registerComponent("reset",d,Q)}Z();export{Z as registerBuiltinFieldTypes};
|
|
@@ -2,14 +2,16 @@ import type { Entity } from '@donotdev/core';
|
|
|
2
2
|
export interface EntityCardListProps {
|
|
3
3
|
/** The entity definition */
|
|
4
4
|
entity: Entity;
|
|
5
|
-
/**
|
|
6
|
-
onView
|
|
5
|
+
/** View handler - called when card is clicked */
|
|
6
|
+
onView: (id: string) => void;
|
|
7
7
|
/** Grid columns (responsive) - defaults to [1, 2, 3, 4] */
|
|
8
8
|
cols?: number | [number, number, number, number];
|
|
9
9
|
/** Cache stale time is ms - defaults to 30 mins */
|
|
10
10
|
staleTime?: number;
|
|
11
11
|
/** Optional filter function to filter items client-side */
|
|
12
12
|
filter?: (item: any) => boolean;
|
|
13
|
+
/** Hide filters section (default: false) */
|
|
14
|
+
hideFilters?: boolean;
|
|
13
15
|
}
|
|
14
16
|
/**
|
|
15
17
|
* Entity Card List Component - Card grid view for public/user-facing browsing
|
|
@@ -23,5 +25,5 @@ export interface EntityCardListProps {
|
|
|
23
25
|
* - Default routing: `/${entity.collection}/${id}` for view
|
|
24
26
|
*/
|
|
25
27
|
export declare function EntityCardList({ entity, onView, cols, staleTime, // 30 minutes default cache
|
|
26
|
-
filter, }: EntityCardListProps): import("react/jsx-runtime").JSX.Element;
|
|
28
|
+
filter, hideFilters, }: EntityCardListProps): import("react/jsx-runtime").JSX.Element;
|
|
27
29
|
//# sourceMappingURL=EntityCardList.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityCardList.d.ts","sourceRoot":"","sources":["../../src/components/EntityCardList.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"EntityCardList.d.ts","sourceRoot":"","sources":["../../src/components/EntityCardList.tsx"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAO7C,MAAM,WAAW,mBAAmB;IAClC,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACjD,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC;IAChC,4CAA4C;IAC5C,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,MAAM,EACN,IAAmB,EACnB,SAA0B,EAAE,2BAA2B;AACvD,MAAM,EACN,WAAmB,GACpB,EAAE,mBAAmB,2CAkOrB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as
|
|
1
|
+
"use client";import{jsx as r,jsxs as f,Fragment as _}from"react/jsx-runtime";import{useMemo as m,useCallback as k,useState as D}from"react";import{Grid as E,Card as R,Stack as v,Text as g,Section as w}from"@donotdev/components";import{useTranslation as y}from"@donotdev/core";import{translateFieldLabel as B}from"../forms/utils";import{useCrudCardList as G}from"../useCrudCardList";import{formatValue as M}from"./DisplayFieldRenderer";import{EntityFilters as q,matchesFilter as z}from"./EntityFilters";function N({entity:t,onView:j,cols:L=[1,2,3,4],staleTime:O=1e3*60*30,filter:h,hideFilters:T=!1}){const{data:$,loading:A}=G(t,{staleTime:O}),p=$?.items||[],[d,I]=D({}),V=k(e=>Object.keys(d).length===0?!0:Object.entries(d).every(([l,s])=>{const i=e[l],a=t.fields[l]?.type||"text";return z(i,s,a)}),[d,t.fields]),n=m(()=>{let e=p;return e=e.filter(V),h&&(e=e.filter(h)),e},[p,V,h]),{t:F}=y(t.namespace),{t:o}=y("crud"),U=k(e=>{j(e)},[j]),c=m(()=>{const e=t.listCardFields??t.listFields;return e&&e.length>0?e:Object.keys(t.fields).slice(0,4)},[t.listCardFields,t.listFields,t.fields]),u=m(()=>{const e=c.filter(s=>{const i=t.fields[s];return i?.type==="image"||i?.type==="images"});return e.length>0?e[0]:Object.keys(t.fields).filter(s=>{const i=t.fields[s];return i?.type==="image"||i?.type==="images"})[0]||null},[c,t.fields]),x=m(()=>c.filter(e=>e!==u),[c,u]),S=F("name",{defaultValue:t.name});return f(_,{children:[!T&&r(w,{title:o("filters.title",{entity:S,defaultValue:`Browse ${S} - Filters`}),collapsible:!0,defaultOpen:!0,children:r(q,{entity:t,data:p,filters:d,onFiltersChange:I,fieldsToFilter:t.listCardFields})}),r(w,{title:A?o("results.title.fetching",{defaultValue:"Fetching..."}):o("results.title.count",{count:n.length,defaultValue:n.length===1?"Found 1 occurrence":`Found ${n.length} occurrences`}),collapsible:!0,defaultOpen:!0,children:n.length===0?f(v,{align:"center",justify:"center",gap:"medium",style:{padding:"var(--gap-3xl)",textAlign:"center"},children:[r(g,{level:"h3",style:{color:"var(--muted-foreground)"},children:o("emptyState.title",{defaultValue:`No ${t.name.toLowerCase()} found`})}),r(g,{style:{color:"var(--muted-foreground)"},children:o("emptyState.description",{defaultValue:`No ${t.name.toLowerCase()} available at this time.`})})]}):r(E,{cols:L,gap:"medium",children:n.map(e=>{const l=u?e[u]:null,s=l?typeof l=="string"?l:l?.url||l?.thumbUrl||Array.isArray(l)&&l[0]?.url||l[0]?.thumbUrl||l[0]:null,i=x[0],C=i?e[i]:e.id;return r(R,{title:String(C||""),clickable:!0,onClick:()=>U(e.id),elevated:!0,children:f(v,{direction:"column",gap:"medium",children:[s&&r("div",{style:{width:"100%",aspectRatio:"16/9",borderRadius:"var(--radius-md)",overflow:"hidden",backgroundColor:"var(--muted)"},children:r("img",{src:s,alt:String(C||""),style:{width:"100%",height:"100%",objectFit:"cover"}})}),r(v,{direction:"column",gap:"tight",children:x.slice(1,4).map(a=>{const b=t.fields[a];return b?f("div",{children:[r(g,{level:"small",variant:"muted",children:B(a,b,F)}),r(g,{children:M(e[a],b,F,{compact:!0})})]},a):null})})]})},e.id)})})})]})}export{N as EntityCardList};
|
|
@@ -2,8 +2,8 @@ import type { Entity, UserRole } from '@donotdev/core';
|
|
|
2
2
|
export interface EntityDisplayRendererProps<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
3
3
|
/** Entity definition - pass the full entity from defineEntity() */
|
|
4
4
|
entity: Entity;
|
|
5
|
-
/** Entity ID to fetch
|
|
6
|
-
id
|
|
5
|
+
/** Entity ID to fetch */
|
|
6
|
+
id: string;
|
|
7
7
|
/** Translation function (optional - auto-generated if not provided) */
|
|
8
8
|
t?: (key: string, options?: Record<string, unknown>) => string;
|
|
9
9
|
/** Additional CSS classes */
|
|
@@ -38,6 +38,6 @@ export interface EntityDisplayRendererProps<T extends Record<string, unknown> =
|
|
|
38
38
|
* <EntityDisplayRenderer entity={carEntity} id={carId} />
|
|
39
39
|
* ```
|
|
40
40
|
*/
|
|
41
|
-
export declare function EntityDisplayRenderer<T extends Record<string, unknown> = Record<string, unknown>>({ entity, id
|
|
41
|
+
export declare function EntityDisplayRenderer<T extends Record<string, unknown> = Record<string, unknown>>({ entity, id, t, className, backend, loadingMessage, notFoundMessage, viewerRole, }: EntityDisplayRendererProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
42
42
|
export default EntityDisplayRenderer;
|
|
43
43
|
//# sourceMappingURL=EntityDisplayRenderer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityDisplayRenderer.d.ts","sourceRoot":"","sources":["../../src/components/EntityDisplayRenderer.tsx"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"EntityDisplayRenderer.d.ts","sourceRoot":"","sources":["../../src/components/EntityDisplayRenderer.tsx"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAKvD,MAAM,WAAW,0BAA0B,CACzC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAE3D,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,uEAAuE;IACvE,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC;IAC/D,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qBAAqB;IACrB,OAAO,CAAC,EAAE,WAAW,GAAG,WAAW,CAAC;IACpC,6BAA6B;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,+BAA+B;IAC/B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,QAAQ,CAAC;CACvB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACnC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3D,EACA,MAAM,EACN,EAAE,EACF,CAAC,EACD,SAAc,EACd,OAAqB,EACrB,cAAc,EACd,eAAe,EACf,UAAoB,GACrB,EAAE,0BAA0B,CAAC,CAAC,CAAC,2CAgM/B;AAED,eAAe,qBAAqB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as
|
|
1
|
+
"use client";import{jsx as n,jsxs as O}from"react/jsx-runtime";import{useEffect as _,useState as m,useMemo as I}from"react";import{Stack as p,Spinner as M}from"@donotdev/components";import{useTranslation as v,isFieldVisible as R}from"@donotdev/core";import{DisplayFieldRenderer as T}from"./DisplayFieldRenderer";import{useCrud as $}from"../useCrud";function q({entity:i,id:o,t:E,className:f="",backend:b="functions",loadingMessage:j,notFoundMessage:x,viewerRole:g="guest"}){const{get:d,loading:F,data:A,error:S,isAvailable:y}=$(i,{backend:b}),[D,u]=m(!1),[V,s]=m(null),[k,c]=m(null),{t:w}=v(i.namespace),{t:h}=v("crud"),z=E||w;_(()=>{if(!o){c(null),s(null),u(!1);return}if(!y||!d)return;let t=!1;return u(!0),s(null),d(o).then(r=>{t||(u(!1),r?(c(r),s(null)):(c(null),s(new Error("Entity not found"))))}).catch(r=>{t||(u(!1),s(r instanceof Error?r:new Error(String(r))),c(null))}),()=>{t=!0}},[o,d,y]);const l=A||k,a=S||V,C=F||D||!o,L=I(()=>l?Object.entries(i.fields).filter(([t,r])=>{if(!R(r.visibility,g)||r.visibility==="hidden")return!1;const e=l[t];return!(e==null||typeof e=="string"&&e.trim()===""||Array.isArray(e)&&e.length===0||typeof e=="object"&&!Array.isArray(e)&&e!==null&&Object.keys(e).length===0)}):[],[i.fields,g,l]);return C?n("div",{style:{position:"relative",width:"100%",gridColumn:"1 / -1",display:"contents"},className:f,children:n(M,{overlay:!0,"aria-label":j||h("form.loading",{defaultValue:"Loading..."})})}):a||!l?n(p,{align:"center",justify:"center",gap:"medium",style:{padding:"var(--gap-3xl)",textAlign:"center"},className:f,children:O(p,{direction:"column",gap:"tight",children:[n("h3",{style:{color:"var(--muted-foreground)"},children:x||h("errors.notFound",{defaultValue:`${i.name} not found`})}),a&&n("p",{style:{color:"var(--destructive)",fontSize:"var(--font-size-sm)"},children:a instanceof Error?a.message:String(a)})]})}):n(p,{direction:"column",gap:"medium",className:f,children:L.map(([t,r])=>n(T,{name:t,config:r,value:l[t],t:z},t))})}var Q=q;export{q as EntityDisplayRenderer,Q as default};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Entity } from '@donotdev/core';
|
|
2
|
+
/**
|
|
3
|
+
* Shared filter utility - checks if an item matches a filter value
|
|
4
|
+
*
|
|
5
|
+
* Pattern for null/undefined handling:
|
|
6
|
+
* - MIN / undefined → Only show items with defined values >= MIN (exclude null/undefined)
|
|
7
|
+
* - undefined / MAX → Show items with value <= MAX OR null/undefined (include null/undefined)
|
|
8
|
+
* - MIN / MAX → Show items with MIN <= value <= MAX (exclude null/undefined)
|
|
9
|
+
*/
|
|
10
|
+
export declare function matchesFilter(itemValue: any, filterValue: string | {
|
|
11
|
+
min?: string;
|
|
12
|
+
max?: string;
|
|
13
|
+
}, fieldType: string): boolean;
|
|
14
|
+
export interface EntityFiltersProps<T = any> {
|
|
15
|
+
/** The entity definition */
|
|
16
|
+
entity: Entity;
|
|
17
|
+
/** Data array to extract unique values and min/max from */
|
|
18
|
+
data: T[];
|
|
19
|
+
/** Current filter values */
|
|
20
|
+
filters: Record<string, string | {
|
|
21
|
+
min?: string;
|
|
22
|
+
max?: string;
|
|
23
|
+
}>;
|
|
24
|
+
/** Callback when filters change */
|
|
25
|
+
onFiltersChange: (filters: Record<string, string | {
|
|
26
|
+
min?: string;
|
|
27
|
+
max?: string;
|
|
28
|
+
}>) => void;
|
|
29
|
+
/** Optional: Specific fields to show filters for (defaults to all entity fields) */
|
|
30
|
+
fieldsToFilter?: string[];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Entity Filters Component - Auto-generates filter UI based on entity field types
|
|
34
|
+
*
|
|
35
|
+
* Features:
|
|
36
|
+
* - String/Select fields: Combobox with unique values
|
|
37
|
+
* - Number fields: Min/Max inputs + Slider (2 rows)
|
|
38
|
+
* - Date fields: Min/Max date pickers + shortcuts (2 rows)
|
|
39
|
+
* - Filters wrap naturally with flex-wrap
|
|
40
|
+
* - Clear individual filters or all filters
|
|
41
|
+
*/
|
|
42
|
+
export declare function EntityFilters<T extends Record<string, any> = Record<string, any>>({ entity, data, filters, onFiltersChange, fieldsToFilter, }: EntityFiltersProps<T>): import("react/jsx-runtime").JSX.Element | null;
|
|
43
|
+
//# sourceMappingURL=EntityFilters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EntityFilters.d.ts","sourceRoot":"","sources":["../../src/components/EntityFilters.tsx"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAI7C;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,GAAG,EACd,WAAW,EAAE,MAAM,GAAG;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,EACpD,SAAS,EAAE,MAAM,GAChB,OAAO,CA8FT;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC,GAAG,GAAG;IACzC,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjE,mCAAmC;IACnC,eAAe,EAAE,CACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,KAC7D,IAAI,CAAC;IACV,oFAAoF;IACpF,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACnD,EACA,MAAM,EACN,IAAI,EACJ,OAAO,EACP,eAAe,EACf,cAAc,GACf,EAAE,kBAAkB,CAAC,CAAC,CAAC,kDA8evB"}
|