pocketbase-react 0.1.0 → 0.1.2

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 (97) hide show
  1. package/CHANGELOG.md +4 -1
  2. package/README.md +15 -0
  3. package/dist/pocketbase-react.js +492 -0
  4. package/dist/pocketbase-react.min.js +1 -0
  5. package/{dist/esm → es}/context/Pocketbase.d.ts +1 -3
  6. package/es/context/Pocketbase.js +28 -0
  7. package/{dist/cjs → es}/context/client.d.ts +1 -1
  8. package/es/context/client.js +8 -0
  9. package/{dist/cjs → es}/context/content.d.ts +0 -0
  10. package/es/context/content.js +67 -0
  11. package/{dist/cjs → es}/context/index.d.ts +0 -0
  12. package/es/context/index.js +3 -0
  13. package/{dist/cjs → es}/hooks/index.d.ts +0 -0
  14. package/es/hooks/index.js +2 -0
  15. package/{dist/cjs → es}/hooks/useAppContent.d.ts +1 -1
  16. package/es/hooks/useAppContent.js +26 -0
  17. package/es/hooks/useClientContext.d.ts +2 -0
  18. package/es/hooks/useClientContext.js +9 -0
  19. package/{dist/cjs → es}/index.d.ts +0 -0
  20. package/{dist/esm/index.d.ts → es/index.js} +1 -1
  21. package/{dist/cjs → es}/interfaces/Record.d.ts +1 -1
  22. package/es/interfaces/Record.js +1 -0
  23. package/{dist/cjs → es}/interfaces/index.d.ts +0 -0
  24. package/es/interfaces/index.js +1 -0
  25. package/es/store/actions/index.d.ts +2 -0
  26. package/es/store/actions/index.js +2 -0
  27. package/es/store/actions/records.d.ts +9 -0
  28. package/es/store/actions/records.js +39 -0
  29. package/{dist/cjs → es}/store/index.d.ts +0 -0
  30. package/{dist/esm/store/index.d.ts → es/store/index.js} +1 -1
  31. package/{dist/cjs → es}/store/reducers/index.d.ts +2 -2
  32. package/es/store/reducers/index.js +5 -0
  33. package/{dist/cjs → es}/store/reducers/records.d.ts +2 -3
  34. package/es/store/reducers/records.js +71 -0
  35. package/{dist/cjs → es}/store/store.d.ts +1 -1
  36. package/es/store/store.js +46 -0
  37. package/{dist/cjs → es}/store/types/index.d.ts +0 -0
  38. package/es/store/types/index.js +6 -0
  39. package/lib/context/Pocketbase.js +49 -0
  40. package/lib/context/client.js +21 -0
  41. package/lib/context/content.js +83 -0
  42. package/lib/context/index.js +42 -0
  43. package/lib/hooks/index.js +29 -0
  44. package/lib/hooks/useAppContent.js +38 -0
  45. package/lib/hooks/useClientContext.js +15 -0
  46. package/lib/index.js +55 -0
  47. package/lib/interfaces/Record.js +1 -0
  48. package/lib/interfaces/index.js +16 -0
  49. package/lib/store/actions/index.js +12 -0
  50. package/lib/store/actions/records.js +58 -0
  51. package/lib/store/index.js +55 -0
  52. package/lib/store/reducers/index.js +13 -0
  53. package/lib/store/reducers/records.js +85 -0
  54. package/lib/store/store.js +63 -0
  55. package/lib/store/types/index.js +16 -0
  56. package/package.json +94 -35
  57. package/src/context/Pocketbase.tsx +43 -0
  58. package/src/context/client.tsx +14 -0
  59. package/src/context/content.tsx +88 -0
  60. package/{dist/esm/context/index.d.ts → src/context/index.ts} +0 -0
  61. package/src/hooks/index.ts +2 -0
  62. package/src/hooks/useAppContent.ts +28 -0
  63. package/src/hooks/useClientContext.ts +11 -0
  64. package/src/index.ts +4 -0
  65. package/src/interfaces/Record.ts +10 -0
  66. package/src/interfaces/index.ts +1 -0
  67. package/src/store/actions/index.tsx +3 -0
  68. package/src/store/actions/records.tsx +54 -0
  69. package/src/store/index.ts +4 -0
  70. package/src/store/reducers/index.tsx +12 -0
  71. package/src/store/reducers/records.tsx +78 -0
  72. package/src/store/store.tsx +67 -0
  73. package/src/store/types/index.ts +14 -0
  74. package/dist/cjs/EventSource.d.ts +0 -1
  75. package/dist/cjs/context/Pocketbase.d.ts +0 -15
  76. package/dist/cjs/hooks/useClientContext.d.ts +0 -2
  77. package/dist/cjs/index.js +0 -3477
  78. package/dist/cjs/index.js.map +0 -1
  79. package/dist/cjs/store/actions/index.d.ts +0 -2
  80. package/dist/cjs/store/actions/records.d.ts +0 -11
  81. package/dist/esm/EventSource.d.ts +0 -1
  82. package/dist/esm/context/client.d.ts +0 -8
  83. package/dist/esm/context/content.d.ts +0 -16
  84. package/dist/esm/hooks/index.d.ts +0 -2
  85. package/dist/esm/hooks/useAppContent.d.ts +0 -12
  86. package/dist/esm/hooks/useClientContext.d.ts +0 -2
  87. package/dist/esm/index.js +0 -3432
  88. package/dist/esm/index.js.map +0 -1
  89. package/dist/esm/interfaces/Record.d.ts +0 -10
  90. package/dist/esm/interfaces/index.d.ts +0 -1
  91. package/dist/esm/store/actions/index.d.ts +0 -2
  92. package/dist/esm/store/actions/records.d.ts +0 -11
  93. package/dist/esm/store/reducers/index.d.ts +0 -8
  94. package/dist/esm/store/reducers/records.d.ts +0 -12
  95. package/dist/esm/store/store.d.ts +0 -27
  96. package/dist/esm/store/types/index.d.ts +0 -7
  97. package/dist/index.d.ts +0 -128
@@ -0,0 +1,88 @@
1
+ import * as store from '../store/store';
2
+ import * as React from 'react';
3
+ import { createContext, useEffect } from 'react';
4
+ import { useClientContext } from '../hooks/useClientContext';
5
+ import { Record } from '../interfaces/Record';
6
+ import { recordsAction } from '../store/actions';
7
+
8
+ interface ContentActions {
9
+ subscribe: (collectionName: string) => Promise<void>;
10
+ unsubscribe: (collectionName?: string) => void;
11
+ fetch: (collectionName: string) => Promise<void>;
12
+ create: (collectionName: string, record: {}) => Promise<void>;
13
+ update: (collectionName: string, recordId: string, record: {}) => Promise<void>;
14
+ delete: (collectionName: string, recordId: string) => Promise<void>;
15
+ }
16
+
17
+ export const ContentContext = createContext<ContentActions | null>(null);
18
+
19
+ export type ContentProviderProps = {
20
+ children: React.ReactNode;
21
+ collections?: string[];
22
+ };
23
+
24
+ interface MessageData {
25
+ action: string;
26
+ record: Record;
27
+ }
28
+
29
+ export const ContentProvider = (props: ContentProviderProps) => {
30
+ const client = useClientContext();
31
+ const dispatch = store.useAppDispatch;
32
+ const [collections, _] = React.useState<string[]>(props.collections || []);
33
+
34
+ const actions: ContentActions = {
35
+ subscribe: async (collectionName: string) => {
36
+ // save local that collectionName should be subscribed
37
+ await client?.realtime.subscribe(collectionName, (event: MessageData) => {
38
+ switch (event.action) {
39
+ case 'create':
40
+ dispatch(recordsAction.addRecord(collectionName, event.record));
41
+ break;
42
+ case 'update':
43
+ dispatch(recordsAction.updateRecord(collectionName, event.record));
44
+ break;
45
+ case 'delete':
46
+ dispatch(recordsAction.deleteRecord(collectionName, event.record));
47
+ break;
48
+ default:
49
+ break;
50
+ }
51
+ });
52
+ },
53
+ unsubscribe: (collectionName?: string) => {
54
+ if (collectionName) {
55
+ client?.realtime.unsubscribe(collectionName);
56
+ } else {
57
+ client?.realtime.unsubscribe();
58
+ }
59
+ },
60
+ fetch: async (collectionName: string) => {
61
+ const records = await client?.records.getFullList(collectionName, 200);
62
+ dispatch(recordsAction.setRecords(collectionName, records as Record[]));
63
+ },
64
+ create: async (collectionName: string, record: {}) => {
65
+ await client?.records.create(collectionName, record);
66
+ },
67
+ update: async (collectionName: string, recordId: string, record: {}) => {
68
+ await client?.records.update(collectionName, recordId, record);
69
+ },
70
+ delete: async (collectionName: string, recordId: string) => {
71
+ await client?.records.delete(collectionName, recordId);
72
+ },
73
+ };
74
+
75
+ useEffect(() => {
76
+ if (collections) {
77
+ collections.forEach((collectionName) => {
78
+ actions.fetch(collectionName);
79
+ actions.subscribe(collectionName);
80
+ });
81
+ }
82
+ return () => actions.unsubscribe();
83
+ }, [collections]);
84
+
85
+ return (
86
+ <ContentContext.Provider value={actions}>{props.children}</ContentContext.Provider>
87
+ );
88
+ };
@@ -0,0 +1,2 @@
1
+ export * from './useAppContent';
2
+ export * from './useClientContext';
@@ -0,0 +1,28 @@
1
+ import { useContext, useEffect } from 'react';
2
+ import * as store from '../store';
3
+ import { ContentContext } from '../context';
4
+ import { Record } from '../interfaces/Record';
5
+
6
+ export function useAppContent<T extends Record>(
7
+ collectionName: string,
8
+ initialFetch: boolean = false
9
+ ) {
10
+ const records = (store.useAppSelector((state) => state.reducer.records[collectionName]) ?? []) as T[];
11
+ const context = useContext(ContentContext);
12
+
13
+ useEffect(() => {
14
+ if (initialFetch) {
15
+ context?.fetch(collectionName);
16
+ }
17
+ }, [collectionName, initialFetch]);
18
+
19
+ const actions = {
20
+ subscribe: async () => await context?.subscribe(collectionName),
21
+ unsubscribe: () => context?.unsubscribe(collectionName),
22
+ refetch: async () => await context?.fetch(collectionName),
23
+ create: async (record: {}) => await context?.create(collectionName, record),
24
+ update: async (id: string, record: {}) => await context?.update(collectionName, id, record),
25
+ delete: async (id: string) => await context?.delete(collectionName, id),
26
+ };
27
+ return { records, actions };
28
+ }
@@ -0,0 +1,11 @@
1
+ import { useContext } from 'react';
2
+ import { ClientContext } from '../context';
3
+
4
+ const useClientContext = () => {
5
+ const context = useContext(ClientContext);
6
+
7
+ return context;
8
+ };
9
+
10
+
11
+ export { useClientContext };
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from './hooks';
2
+ export * from './interfaces';
3
+ export * from './context';
4
+ export * from './store';
@@ -0,0 +1,10 @@
1
+ export interface Record {
2
+ id?: string;
3
+ created?: string;
4
+ updated?: string;
5
+ '@collectionId'?: string;
6
+ '@collectionName'?: string;
7
+ '@expand'?: Expand;
8
+ }
9
+
10
+ export interface Expand {}
@@ -0,0 +1 @@
1
+ export * from './Record';
@@ -0,0 +1,3 @@
1
+ import * as recordsAction from './records';
2
+
3
+ export { recordsAction };
@@ -0,0 +1,54 @@
1
+ import { Record } from '../../interfaces/Record';
2
+ import { RecordAction } from '../reducers/records';
3
+ import * as ReduxType from '../types';
4
+
5
+ const setRecords = (key: string, payload: Record[]) =>
6
+ ({
7
+ type: ReduxType.SET_RECORDS,
8
+ key,
9
+ payload,
10
+ } as RecordAction);
11
+
12
+ const addRecord = (key: string, payload: Record) =>
13
+ ({
14
+ type: ReduxType.ADD_RECORD,
15
+ key,
16
+ payload,
17
+ } as RecordAction);
18
+
19
+ const addRecords = (key: string, payload: Record[]) =>
20
+ ({
21
+ type: ReduxType.ADD_RECORDS,
22
+ key,
23
+ payload,
24
+ } as RecordAction);
25
+
26
+ const deleteRecord = (key: string, payload: Record) =>
27
+ ({
28
+ type: ReduxType.DELETE_RECORD,
29
+ key,
30
+ payload,
31
+ } as RecordAction);
32
+
33
+ const deleteRecords = (key: string, payload: Record[]) =>
34
+ ({
35
+ type: ReduxType.DELETE_RECORDS,
36
+ key,
37
+ payload,
38
+ } as RecordAction);
39
+
40
+ const updateRecord = (key: string, payload: Record) =>
41
+ ({
42
+ type: ReduxType.UPDATE_RECORD,
43
+ key,
44
+ payload,
45
+ } as RecordAction);
46
+
47
+ export {
48
+ setRecords,
49
+ addRecord,
50
+ addRecords,
51
+ deleteRecord,
52
+ deleteRecords,
53
+ updateRecord,
54
+ };
@@ -0,0 +1,4 @@
1
+ export * from './actions';
2
+ export * from './reducers';
3
+ export * from './types';
4
+ export * from './store';
@@ -0,0 +1,12 @@
1
+ import { combineReducers } from 'redux';
2
+ import { records } from './records';
3
+
4
+ export const appReducer = combineReducers({
5
+ records: records,
6
+ });
7
+
8
+ interface AppReducer {
9
+ records: ReturnType<typeof appReducer>;
10
+ }
11
+
12
+ export type State = AppReducer;
@@ -0,0 +1,78 @@
1
+ import { Record } from '../../interfaces/Record';
2
+ import * as ReduxType from '../types';
3
+
4
+ export interface ReduxRecord {
5
+ [key: string]: Record[];
6
+ }
7
+
8
+ export type RecordAction = {
9
+ type: ReduxType.Types;
10
+ key: string;
11
+ payload: null | Record | Record[];
12
+ };
13
+
14
+ function appendRecord(record: Record, records: Record[]): Record[] {
15
+ return [...records, record];
16
+ }
17
+
18
+ function appendRecords(recordsToAppend: Record[], records: Record[]): Record[] {
19
+ return [...records, ...recordsToAppend];
20
+ }
21
+
22
+ function updateRecord(record: Record, records: Record[]): Record[] {
23
+ return records.map((r) => {
24
+ if (r.id === record.id) {
25
+ return record;
26
+ }
27
+ return r;
28
+ });
29
+ }
30
+
31
+ function deleteRecord(record: Record, records: Record[]): Record[] {
32
+ return records.filter((r) => r.id !== record.id);
33
+ }
34
+
35
+ function deleteRecords(recordsToDelete: Record[], records: Record[]): Record[] {
36
+ return records.filter((r) => !recordsToDelete.includes(r));
37
+ }
38
+
39
+ export const records = (state: ReduxRecord = {}, action: RecordAction) => {
40
+ const list = state[action.key] ?? [];
41
+
42
+ switch (action.type) {
43
+ case ReduxType.SET_RECORDS:
44
+ if (Array.isArray(action.payload)) {
45
+ return {
46
+ ...state,
47
+ [action.key]: action.payload,
48
+ };
49
+ }
50
+ case ReduxType.ADD_RECORD:
51
+ return {
52
+ ...state,
53
+ [action.key]: appendRecord(action.payload as Record, list),
54
+ };
55
+ case ReduxType.ADD_RECORDS:
56
+ return {
57
+ ...state,
58
+ [action.key]: appendRecords(action.payload as Record[], list),
59
+ };
60
+ case ReduxType.DELETE_RECORD:
61
+ return {
62
+ ...state,
63
+ [action.key]: deleteRecord(action.payload as Record, list),
64
+ };
65
+ case ReduxType.DELETE_RECORDS:
66
+ return {
67
+ ...state,
68
+ [action.key]: deleteRecords(action.payload as Record[], list),
69
+ };
70
+ case ReduxType.UPDATE_RECORD:
71
+ return {
72
+ ...state,
73
+ [action.key]: updateRecord(action.payload as Record, list),
74
+ };
75
+ default:
76
+ return state;
77
+ }
78
+ };
@@ -0,0 +1,67 @@
1
+ import { combineReducers, configureStore } from '@reduxjs/toolkit';
2
+ import { persistStore, persistReducer } from 'redux-persist';
3
+ import { TypedUseSelectorHook, useSelector } from 'react-redux';
4
+ import { appReducer } from './reducers';
5
+ import thunk from 'redux-thunk';
6
+ import { RecordAction } from './reducers/records';
7
+ import AsyncStorage from '@react-native-async-storage/async-storage';
8
+
9
+ interface Storage {
10
+ getItem(key: string, ...args: Array<any>): any;
11
+ setItem(key: string, value: any, ...args: Array<any>): any;
12
+ removeItem(key: string, ...args: Array<any>): any;
13
+ }
14
+
15
+
16
+ const CustomStorage: Storage = {
17
+ getItem: async (_key: string, ..._args: Array<any>) => {
18
+ if (typeof document !== 'undefined') {
19
+ console.log("I'm on the web!")
20
+ return localStorage.getItem(_key);
21
+ }
22
+ else if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {
23
+ console.log("I'm in react-native")
24
+ return await AsyncStorage.getItem(_key);
25
+ }
26
+ },
27
+ setItem: async (_key: string, _value: any, ..._args: Array<any>) => {
28
+ if (typeof document !== 'undefined') {
29
+ return localStorage.setItem(_key, _value);
30
+ }
31
+ else if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {
32
+ return await AsyncStorage.setItem(_key, _value);
33
+ }
34
+ },
35
+ removeItem: async (_key: string, ..._args: Array<any>) => {
36
+ if (typeof document !== 'undefined') {
37
+ return localStorage.removeItem(_key);
38
+ }
39
+ else if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {
40
+ return await AsyncStorage.removeItem(_key);
41
+ }
42
+ },
43
+ };
44
+
45
+ export const persistConfig = {
46
+ key: 'root',
47
+ storage: CustomStorage
48
+ };
49
+
50
+ const reducer = combineReducers({
51
+ reducer: persistReducer(persistConfig, appReducer),
52
+ });
53
+
54
+ const store = configureStore({
55
+ reducer,
56
+ middleware: [thunk],
57
+ });
58
+
59
+ type AppDispatch = typeof store.dispatch<RecordAction>;
60
+ const useAppDispatch = store.dispatch;
61
+ type RootState = ReturnType<typeof store.getState>;
62
+ const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
63
+
64
+
65
+ const persistor = persistStore(store);
66
+
67
+ export { AppDispatch, RootState, useAppDispatch, useAppSelector, store, persistor };
@@ -0,0 +1,14 @@
1
+ export const SET_RECORDS = 'SET_RECORDS';
2
+ export const ADD_RECORD = 'ADD_RECORD';
3
+ export const ADD_RECORDS = 'ADD_RECORDS';
4
+ export const UPDATE_RECORD = 'UPDATE_RECORD';
5
+ export const DELETE_RECORD = 'DELETE_RECORD';
6
+ export const DELETE_RECORDS = 'DELETE_RECORDS';
7
+
8
+ export type Types =
9
+ | typeof SET_RECORDS
10
+ | typeof ADD_RECORD
11
+ | typeof ADD_RECORDS
12
+ | typeof UPDATE_RECORD
13
+ | typeof DELETE_RECORD
14
+ | typeof DELETE_RECORDS;
@@ -1 +0,0 @@
1
- declare var Source: any;
@@ -1,15 +0,0 @@
1
- import * as React from 'react';
2
- import PocketBase from 'pocketbase/dist/pocketbase.cjs';
3
- import { AsyncStorageStatic } from '@react-native-async-storage/async-storage';
4
- export declare const PocketbaseContext: React.Context<PocketBase | null>;
5
- export declare type PocketbaseProviderProps = {
6
- children: React.ReactNode;
7
- serverURL: string;
8
- credentials: {
9
- username: string;
10
- password: string;
11
- };
12
- initialCollections?: string[];
13
- storage: AsyncStorageStatic;
14
- };
15
- export declare const Pocketbase: (props: PocketbaseProviderProps) => JSX.Element | null;
@@ -1,2 +0,0 @@
1
- declare const _default: () => import("pocketbase/dist/pocketbase.cjs").default | null;
2
- export default _default;