asasvirtuais 2.2.2 → 2.2.5
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/package.json +1 -1
- package/packages/indexed-interface.tsx +15 -0
- package/packages/react-interface.tsx +37 -117
package/package.json
CHANGED
|
@@ -31,6 +31,21 @@ export function indexedInterface<Schema extends DatabaseSchema>(
|
|
|
31
31
|
|
|
32
32
|
const db = new Dexie(dbName)
|
|
33
33
|
|
|
34
|
+
|
|
35
|
+
// Dynamically define the database schema for Dexie from the Zod schema.
|
|
36
|
+
// It marks 'id' as the primary key and indexes all other top-level readable fields.
|
|
37
|
+
const dexieSchema = Object.fromEntries(
|
|
38
|
+
Object.keys(schema).map(tableName => {
|
|
39
|
+
const fields = Object.keys(schema[tableName].readable.shape)
|
|
40
|
+
// 'id' is the primary key, the rest are indexed fields.
|
|
41
|
+
const indexedFields = fields.filter(f => f !== 'id').join(', ')
|
|
42
|
+
return [tableName, `id, ${indexedFields}`]
|
|
43
|
+
})
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
db.version(1).stores(dexieSchema)
|
|
47
|
+
|
|
48
|
+
|
|
34
49
|
type GenericReadable = z.infer<Schema[keyof Schema]['readable']>
|
|
35
50
|
type GenericWritable = z.infer<Schema[keyof Schema]['writable']>
|
|
36
51
|
|
|
@@ -8,73 +8,11 @@ import { FieldsProvider, useFields } from './fields'
|
|
|
8
8
|
|
|
9
9
|
export function useDatabaseProvider() {
|
|
10
10
|
|
|
11
|
-
const [interfaces, setInterfaces] = useState<Record<string, ReturnType<typeof
|
|
12
|
-
const [indexes, setIndexes] = useState<Record<string, {
|
|
13
|
-
[table: string]: { [id: string]: any }
|
|
14
|
-
}>>({})
|
|
15
|
-
|
|
16
|
-
const set = useCallback((table: string, ...params: any[]) => {
|
|
17
|
-
setIndexes(prev => ({
|
|
18
|
-
[table]: {
|
|
19
|
-
...prev[table],
|
|
20
|
-
...Object.fromEntries(params.map(data => ([(data as any & { id: string} ).id, data])))
|
|
21
|
-
}
|
|
22
|
-
}))
|
|
23
|
-
}, [])
|
|
24
|
-
const unset = useCallback((table: string, ...params: any[]) => {
|
|
25
|
-
setIndexes(prev => ({
|
|
26
|
-
[table]: {
|
|
27
|
-
...prev[table],
|
|
28
|
-
...Object.fromEntries(params.map(data => ([(data as any & { id: string} ).id, data])))
|
|
29
|
-
}
|
|
30
|
-
}))
|
|
31
|
-
}, [])
|
|
11
|
+
const [interfaces, setInterfaces] = useState<Record<string, ReturnType<typeof useTableProvider<any>>>>({})
|
|
32
12
|
|
|
33
13
|
return {
|
|
34
14
|
interfaces,
|
|
35
15
|
setInterfaces,
|
|
36
|
-
indexes,
|
|
37
|
-
set,
|
|
38
|
-
unset,
|
|
39
|
-
setIndexes,
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function useTableIndex<TSchema extends TableSchema>(table: string, schema: TSchema) {
|
|
44
|
-
const { indexes, setIndexes } = useDatabase()
|
|
45
|
-
const index = useMemo(() => indexes[table], [indexes, table])
|
|
46
|
-
const array = useMemo(() => Object.values(index || {}) as z.infer<TSchema['readable']>[], [index])
|
|
47
|
-
function set(...params: z.infer<TSchema['readable'] >[]) {
|
|
48
|
-
setIndexes(prev => ({
|
|
49
|
-
[table]: {
|
|
50
|
-
...prev[table],
|
|
51
|
-
...Object.fromEntries(params.map(data => ([(data as z.infer<TSchema['readable']> & { id: string} ).id, data])))
|
|
52
|
-
},
|
|
53
|
-
...prev,
|
|
54
|
-
}))
|
|
55
|
-
}
|
|
56
|
-
function unset(...params: z.infer<TSchema['readable']>[]) {
|
|
57
|
-
setIndexes(prev => {
|
|
58
|
-
const tableIndex = prev[table] || {}
|
|
59
|
-
const newIndex = { ...tableIndex }
|
|
60
|
-
for (const data of params) {
|
|
61
|
-
const id = (data as z.infer<TSchema['readable']> & { id: string} ).id
|
|
62
|
-
if (newIndex[id])
|
|
63
|
-
delete newIndex[id]
|
|
64
|
-
}
|
|
65
|
-
return {
|
|
66
|
-
[table]: {
|
|
67
|
-
...newIndex,
|
|
68
|
-
},
|
|
69
|
-
...prev,
|
|
70
|
-
}
|
|
71
|
-
})
|
|
72
|
-
}
|
|
73
|
-
return {
|
|
74
|
-
index,
|
|
75
|
-
array,
|
|
76
|
-
set,
|
|
77
|
-
unset,
|
|
78
16
|
}
|
|
79
17
|
}
|
|
80
18
|
|
|
@@ -83,12 +21,12 @@ export const [DatabaseProvider, useDatabase] = createContextFromHook(useDatabase
|
|
|
83
21
|
export function useTableInterface<TSchema extends TableSchema>(table: string, schema: TSchema) {
|
|
84
22
|
const { interfaces } = useDatabase()
|
|
85
23
|
|
|
86
|
-
const
|
|
24
|
+
const module = interfaces[table] as ReturnType<typeof useTableProvider<TSchema>> | undefined
|
|
87
25
|
|
|
88
|
-
if (!
|
|
26
|
+
if (!module)
|
|
89
27
|
throw new Error(`Table "${table}" is not defined in the database schema.`)
|
|
90
28
|
|
|
91
|
-
return
|
|
29
|
+
return module
|
|
92
30
|
}
|
|
93
31
|
|
|
94
32
|
export type TableProviderProps<TSchema extends TableSchema> = {
|
|
@@ -98,10 +36,23 @@ export type TableProviderProps<TSchema extends TableSchema> = {
|
|
|
98
36
|
asAbove?: Record<string, z.infer<TSchema['readable']>>
|
|
99
37
|
}
|
|
100
38
|
|
|
101
|
-
export function
|
|
102
|
-
|
|
103
|
-
|
|
39
|
+
export function useTableProvider<TSchema extends TableSchema>({
|
|
40
|
+
table,
|
|
41
|
+
schema,
|
|
42
|
+
interface: { find, list, create, update, remove },
|
|
43
|
+
asAbove,
|
|
44
|
+
}: TableProviderProps<TSchema>) {
|
|
45
|
+
|
|
46
|
+
type Readable = z.infer<TSchema['readable']>
|
|
47
|
+
|
|
48
|
+
const index = useIndex<Readable>({ ...(asAbove ?? {}) })
|
|
49
|
+
|
|
50
|
+
useEffect(function soBelow() {
|
|
51
|
+
index.setIndex((prev) => ({ ...prev, ...asAbove }))
|
|
52
|
+
}, [])
|
|
53
|
+
|
|
104
54
|
return {
|
|
55
|
+
...index,
|
|
105
56
|
find: useAsyncAction(((props) => find({ ...props, table }).then(res => {
|
|
106
57
|
index.set(res)
|
|
107
58
|
return res
|
|
@@ -125,49 +76,12 @@ export function useInterface<TSchema extends TableSchema>(table: string, schema:
|
|
|
125
76
|
}
|
|
126
77
|
}
|
|
127
78
|
|
|
128
|
-
export function useTableProvider<TSchema extends TableSchema>({
|
|
129
|
-
table,
|
|
130
|
-
schema,
|
|
131
|
-
interface: tableInterface,
|
|
132
|
-
asAbove,
|
|
133
|
-
}: TableProviderProps<TSchema>) {
|
|
134
|
-
|
|
135
|
-
type Readable = z.infer<TSchema['readable']>
|
|
136
|
-
|
|
137
|
-
const index = useIndex<Readable>({ ...(asAbove ?? {}) })
|
|
138
|
-
|
|
139
|
-
useEffect(function soBelow() {
|
|
140
|
-
index.setIndex((prev) => ({ ...prev, ...asAbove }))
|
|
141
|
-
}, [])
|
|
142
|
-
|
|
143
|
-
const methods = useInterface<TSchema>(table, schema, tableInterface, index)
|
|
144
|
-
|
|
145
|
-
const { interfaces, setInterfaces, indexes, setIndexes } = useDatabase()
|
|
146
|
-
|
|
147
|
-
useEffect(() => {
|
|
148
|
-
setInterfaces(prev => ({
|
|
149
|
-
[table]: methods,
|
|
150
|
-
...prev,
|
|
151
|
-
}))
|
|
152
|
-
}, [])
|
|
153
|
-
|
|
154
|
-
return {
|
|
155
|
-
...methods,
|
|
156
|
-
...index
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
79
|
const TableContext = createContext<ReturnType<typeof useTableProvider<any>> | undefined>(undefined)
|
|
161
80
|
|
|
162
|
-
export function TableProvider<TSchema extends TableSchema>({children, ...props}: React.PropsWithChildren<TableProviderProps<TSchema>>) {
|
|
81
|
+
export function TableProvider<TSchema extends TableSchema>({ children, ...props }: React.PropsWithChildren<TableProviderProps<TSchema>>) {
|
|
163
82
|
|
|
164
83
|
const context = useTableProvider(props)
|
|
165
84
|
|
|
166
|
-
const { interfaces, setInterfaces, indexes, setIndexes } = useDatabase()
|
|
167
|
-
|
|
168
|
-
if (! interfaces[props.table])
|
|
169
|
-
return null
|
|
170
|
-
|
|
171
85
|
return (
|
|
172
86
|
<TableContext.Provider value={context}>
|
|
173
87
|
{children}
|
|
@@ -175,13 +89,18 @@ export function TableProvider<TSchema extends TableSchema>({children, ...props}:
|
|
|
175
89
|
)
|
|
176
90
|
}
|
|
177
91
|
|
|
92
|
+
export function TableConsumer<TSchema extends TableSchema>({ children }: { children: React.ReactNode | ((props: ReturnType<typeof useTableProvider<TSchema>>) => React.ReactNode) }) {
|
|
93
|
+
const context = useContext(TableContext)
|
|
94
|
+
if (!context) throw new Error('TableConsumer must be used within a TableProvider.')
|
|
95
|
+
return (
|
|
96
|
+
<>
|
|
97
|
+
{typeof children === 'function' ? children(context) : children}
|
|
98
|
+
</>
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
|
|
178
102
|
export function useTable<TSchema extends TableSchema>(table: string, schema: TSchema) {
|
|
179
|
-
|
|
180
|
-
const index = useTableIndex(table, schema)
|
|
181
|
-
return {
|
|
182
|
-
...methods,
|
|
183
|
-
...index,
|
|
184
|
-
}
|
|
103
|
+
return useContext(TableContext) as ReturnType<typeof useTableProvider<TSchema>>
|
|
185
104
|
}
|
|
186
105
|
|
|
187
106
|
export function CreateForm<TSchema extends TableSchema>({ table, schema, defaults, onSuccess, children }: {
|
|
@@ -341,7 +260,7 @@ export function useUpdateForm<TSchema extends TableSchema>(schema: TSchema) {
|
|
|
341
260
|
}
|
|
342
261
|
}
|
|
343
262
|
|
|
344
|
-
export function useFiltersForm
|
|
263
|
+
export function useFiltersForm<TSchema extends TableSchema>(schema: TSchema) {
|
|
345
264
|
return {
|
|
346
265
|
...useFields<z.infer<TSchema['readable']>>(),
|
|
347
266
|
...useAction<z.infer<TSchema['readable']>,
|
|
@@ -359,15 +278,16 @@ export function useSingleProvider<TSchema extends TableSchema>({
|
|
|
359
278
|
table: string
|
|
360
279
|
schema: TSchema
|
|
361
280
|
}) {
|
|
362
|
-
const { find } = useTableInterface(table, schema)
|
|
363
|
-
const { index } = useTableIndex<TSchema>(table, schema)
|
|
281
|
+
const { find, index } = useTableInterface(table, schema)
|
|
364
282
|
const [single, setSingle] = useState<z.infer<TSchema['readable']>>(
|
|
365
|
-
|
|
283
|
+
// @ts-expect-error
|
|
284
|
+
() => index[table][id]
|
|
366
285
|
)
|
|
367
286
|
useEffect(() => {
|
|
368
287
|
if (!single) find.trigger({ id }).then(setSingle)
|
|
369
288
|
}, [])
|
|
370
289
|
useEffect(() => {
|
|
290
|
+
// @ts-expect-error
|
|
371
291
|
setSingle(index[table][id as keyof typeof index])
|
|
372
292
|
}, [index[table][id as keyof typeof index]])
|
|
373
293
|
return {
|