@fireproof/core 0.20.0-dev-preview-58 → 0.20.0-dev-preview-61
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/deno.json +1 -1
- package/index.cjs +90 -91
- package/index.cjs.map +1 -1
- package/index.js +12 -13
- package/index.js.map +1 -1
- package/metafile-cjs.json +1 -1
- package/metafile-esm.json +1 -1
- package/package.json +2 -2
- package/react/index.cjs +59 -70
- package/react/index.cjs.map +1 -1
- package/react/index.d.cts +13 -41
- package/react/index.d.ts +13 -41
- package/react/index.js +58 -69
- package/react/index.js.map +1 -1
- package/react/metafile-cjs.json +1 -1
- package/react/metafile-esm.json +1 -1
- package/tests/fireproof/attachable.test.ts +1 -2
- package/tests/fireproof/crdt.test.ts +14 -4
- package/tests/react/{useFireproof.test.tsx → use-fireproof.test.tsx} +92 -13
package/react/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/react/index.ts","../../../src/react/useFireproof.ts","../../../src/react/useDocument.ts","../../../src/react/useLiveQuery.ts","../../../src/react/useAllDocs.ts","../../../src/react/useChanges.ts","../../../src/react/img-file.ts"],"sourcesContent":["export {\n type TLUseDocument,\n /** @deprecated Use return values from useFireproof('dbname') instead. Top level usage will be removed in future versions. */\n useDocument,\n} from \"./useDocument.js\";\nexport { FireproofCtx, type UseFireproof, useFireproof, type LiveQueryResult, type UseDocumentResult } from \"./useFireproof.js\";\nexport {\n type TLUseLiveQuery,\n /** @deprecated Use return values from useFireproof('dbname') instead. Top level usage will be removed in future versions. */\n useLiveQuery,\n} from \"./useLiveQuery.js\";\nexport {\n type TLUseAllDocs,\n /** @deprecated Use return values from useFireproof('dbname') instead. Top level usage will be removed in future versions. */\n useAllDocs,\n} from \"./useAllDocs.js\";\nexport {\n type TLUseChanges,\n /** @deprecated Use return values from useFireproof('dbname') instead. Top level usage will be removed in future versions. */\n useChanges,\n} from \"./useChanges.js\";\n\nexport * from \"./img-file.js\";\n","import type {\n ConfigOpts,\n DocFragment,\n DocResponse,\n DocSet,\n DocTypes,\n DocWithId,\n IndexKeyType,\n IndexRow,\n MapFn,\n QueryOpts,\n Database,\n} from \"@fireproof/core\";\nimport { fireproof } from \"@fireproof/core\";\nimport { useCallback, useEffect, useMemo, useState, useRef } from \"react\";\nimport type { AllDocsQueryOpts, ChangesOptions, ClockHead } from \"@fireproof/core\";\n\nexport interface LiveQueryResult<T extends DocTypes, K extends IndexKeyType, R extends DocFragment = T> {\n readonly docs: DocWithId<T>[];\n readonly rows: IndexRow<K, T, R>[];\n /** @internal */\n readonly length: number;\n /** @internal */\n map<U>(callbackfn: (value: DocWithId<T>, index: number, array: DocWithId<T>[]) => U): U[];\n /** @internal */\n filter(predicate: (value: DocWithId<T>, index: number, array: DocWithId<T>[]) => boolean): DocWithId<T>[];\n /** @internal */\n forEach(callbackfn: (value: DocWithId<T>, index: number, array: DocWithId<T>[]) => void): void;\n /** @internal */\n [Symbol.iterator](): Iterator<DocWithId<T>>;\n}\n\nexport type UseLiveQuery = <T extends DocTypes, K extends IndexKeyType = string, R extends DocFragment = T>(\n mapFn: string | MapFn<T>,\n query?: QueryOpts<K>,\n initialRows?: IndexRow<K, T, R>[],\n) => LiveQueryResult<T, K, R>;\n\nexport interface AllDocsResult<T extends DocTypes> {\n readonly docs: DocWithId<T>[];\n}\n\nexport interface ChangesResult<T extends DocTypes> {\n readonly docs: DocWithId<T>[];\n}\n\nexport type UseAllDocs = <T extends DocTypes>(query?: AllDocsQueryOpts) => AllDocsResult<T>;\n\nexport type UseChanges = <T extends DocTypes>(since: ClockHead, opts: ChangesOptions) => ChangesResult<T>;\n\ninterface UpdateDocFnOptions {\n readonly replace?: boolean;\n readonly reset?: boolean;\n}\n\ntype UpdateDocFn<T extends DocTypes> = (newDoc?: DocSet<T>, options?: UpdateDocFnOptions) => void;\n\ntype StoreDocFn<T extends DocTypes> = (existingDoc?: DocWithId<T>) => Promise<DocResponse>;\n\ntype DeleteDocFn<T extends DocTypes> = (existingDoc?: DocWithId<T>) => Promise<DocResponse>;\n\ntype UseDocumentResultTuple<T extends DocTypes> = [DocWithId<T>, UpdateDocFn<T>, StoreDocFn<T>, DeleteDocFn<T>];\n\ninterface UseDocumentResultObject<T extends DocTypes> {\n doc: DocWithId<T>;\n merge: (newDoc: Partial<T>) => void;\n replace: (newDoc: T) => void;\n reset: () => void;\n refresh: () => Promise<void>;\n save: StoreDocFn<T>;\n remove: DeleteDocFn<T>;\n submit: (e?: Event) => Promise<void>;\n}\n\nexport type UseDocumentResult<T extends DocTypes> = UseDocumentResultObject<T> & UseDocumentResultTuple<T>;\n\nexport type UseDocumentInitialDocOrFn<T extends DocTypes> = DocSet<T> | (() => DocSet<T>);\nexport type UseDocument = <T extends DocTypes>(initialDocOrFn: UseDocumentInitialDocOrFn<T>) => UseDocumentResult<T>;\n\nexport interface UseFireproof {\n readonly database: Database;\n /**\n * ## Summary\n *\n * React hook that provides the ability to create/update/save new Fireproof documents into your custom Fireproof database.\n * The creation occurs when you do not pass in an `_id` as part of your initial document -- the database will assign a new\n * one when you call the provided `save` handler. The hook also provides generics support so you can inline your custom type into\n * the invocation to receive type-safety and auto-complete support in your IDE.\n *\n * ## Usage\n *\n * ```tsx\n * const todo = useDocument<Todo>({\n * text: '',\n * date: Date.now(),\n * completed: false\n * })\n * // Access via object properties\n * todo.doc // The current document\n * todo.merge({ completed: true }) // Update specific fields\n * todo.replace({ text: 'new', date: Date.now(), completed: false }) // Replace entire doc\n * todo.save() // Save changes\n * todo.remove() // Delete document\n * todo.reset() // Reset to initial state\n * todo.refresh() // Refresh from database\n *\n * // Or use tuple destructuring for legacy compatibility\n * const [doc, updateDoc, saveDoc, removeDoc] = todo\n * ```\n *\n * ## Overview\n *\n * Changes made via remote sync peers, or other members of your cloud replica group will appear automatically\n * when you use the `useLiveQuery` and `useDocument` APIs. By default, Fireproof stores data in the browser's\n * local storage.\n */\n readonly useDocument: UseDocument;\n /**\n * ## Summary\n * React hook that provides access to live query results, enabling real-time updates in your app.\n *\n * ## Usage\n * ```tsx\n * const result = useLiveQuery(\"date\"); // using string key\n * const result = useLiveQuery('date', { limit: 10, descending: true }) // key + options\n * const result = useLiveQuery<CustomType>(\"date\"); // using generics\n * const result = useLiveQuery((doc) => doc.date)); // using map function\n * ```\n *\n * ## Overview\n * Changes made via remote sync peers, or other members of your cloud replica group will appear automatically\n * when you use the `useLiveQuery` and `useDocument` APIs. By default, Fireproof stores data in the browser's\n * local storage.\n */\n readonly useLiveQuery: UseLiveQuery;\n /**\n * ## Summary\n * React hook that provides access to all documents in the database, sorted by `_id`.\n *\n * ## Usage\n * ```tsx\n * const result = useAllDocs({ limit: 10, descending: true }); // with options\n * const result = useAllDocs(); // without options\n * ```\n *\n * ## Overview\n * Changes made via remote sync peers, or other members of your cloud replica group will appear automatically\n * when you use the `useAllDocs` and `useDocument` APIs. By default, Fireproof stores data in the browser's\n * local storage.\n */\n readonly useAllDocs: UseAllDocs;\n /**\n * ## Summary\n * React hook that provides access to all new documents in the database added since the last time the changes was called\n *\n * ## Usage\n * ```tsx\n * const result = useChanges(prevresult.clock,{limit:10}); // with options\n * const result = useChanges(); // without options\n * ```\n *\n * ## Overview\n * Changes made via remote sync peers, or other members of your cloud replica group will appear automatically\n * when you use the `useAllDocs`, `useChanges` and `useDocument` APIs. By default, Fireproof stores data in the browser's\n * local storage.\n */\n readonly useChanges: UseChanges;\n}\n\n/**\n * @deprecated Use the `useFireproof` hook instead\n */\nexport const FireproofCtx = {} as UseFireproof;\n\nfunction deepClone<T>(value: T): T {\n if (typeof structuredClone !== \"undefined\") {\n return structuredClone(value);\n } else {\n // Fallback if structuredClone is not available (older browsers, older Node versions, etc.)\n return JSON.parse(JSON.stringify(value));\n }\n}\n\n/**\n *\n * ## Summary\n *\n * React hook to create a custom-named Fireproof database and provides the utility hooks to query against it.\n *\n * ## Usage\n * ```tsx\n * const { database, useLiveQuery, useDocument } = useFireproof(\"dbname\");\n * const { database, useLiveQuery, useDocument } = useFireproof(\"dbname\", { ...options });\n * ```\n *\n * ## Overview\n *\n * TL;DR: Only use this hook if you need to configure a database name other than the default `useFireproof`.\n *\n * For most applications, using the `useLiveQuery` or `useDocument` hooks exported from `use-fireproof` should\n * suffice for the majority of use-cases. Under the hood, they act against a database named `useFireproof` instantiated with\n * default configurations. However, if you need to do a custom database setup or configure a database name more to your liking\n * than the default `useFireproof`, then use `useFireproof` as it exists for that purpose. It will provide you with the\n * custom database accessor and *lexically scoped* versions of `useLiveQuery` and `useDocument` that act against said\n * custom database.\n *\n */\nexport function useFireproof(name: string | Database = \"useFireproof\", config: ConfigOpts = {}): UseFireproof {\n const database = typeof name === \"string\" ? fireproof(name, config) : name;\n\n const updateHappenedRef = useRef(false);\n\n function useDocument<T extends DocTypes>(initialDocOrFn?: UseDocumentInitialDocOrFn<T>): UseDocumentResult<T> {\n let initialDoc: DocSet<T>;\n if (typeof initialDocOrFn === \"function\") {\n initialDoc = initialDocOrFn();\n } else {\n initialDoc = initialDocOrFn ?? ({} as T);\n }\n\n const originalInitialDoc = useMemo(() => deepClone({ ...initialDoc }), []);\n\n const [doc, setDoc] = useState(initialDoc);\n\n const refresh = useCallback(async () => {\n const gotDoc = doc._id ? await database.get<T>(doc._id).catch(() => initialDoc) : initialDoc;\n setDoc(gotDoc);\n }, [doc._id]);\n\n const save: StoreDocFn<T> = useCallback(\n async (existingDoc) => {\n updateHappenedRef.current = false;\n const toSave = existingDoc ?? doc;\n const res = await database.put(toSave);\n\n if (!updateHappenedRef.current && !doc._id && !existingDoc) {\n setDoc((d) => ({ ...d, _id: res.id }));\n }\n\n return res;\n },\n [doc],\n );\n\n const remove: DeleteDocFn<T> = useCallback(\n async (existingDoc) => {\n const id = existingDoc?._id ?? doc._id;\n if (!id) throw database.logger.Error().Msg(`Document must have an _id to be removed`).AsError();\n const gotDoc = await database.get<T>(id).catch(() => undefined);\n if (!gotDoc) throw database.logger.Error().Str(\"id\", id).Msg(`Document not found`).AsError();\n const res = await database.del(id);\n setDoc(initialDoc);\n return res;\n },\n [doc, initialDoc],\n );\n\n // New granular update methods\n const merge = useCallback((newDoc: Partial<T>) => {\n updateHappenedRef.current = true;\n setDoc((prev) => ({ ...prev, ...newDoc }));\n }, []);\n\n const replace = useCallback((newDoc: T) => {\n updateHappenedRef.current = true;\n setDoc(newDoc);\n }, []);\n\n const reset = useCallback(() => {\n updateHappenedRef.current = true;\n setDoc({ ...originalInitialDoc });\n }, [originalInitialDoc]);\n\n // Legacy-compatible updateDoc\n const updateDoc = useCallback(\n (newDoc?: DocSet<T>, opts = { replace: false, reset: false }) => {\n if (!newDoc) {\n return opts.reset ? reset() : refresh();\n }\n return opts.replace ? replace(newDoc as T) : merge(newDoc);\n },\n [refresh, reset, replace, merge],\n );\n\n useEffect(() => {\n if (!doc._id) return;\n return database.subscribe((changes) => {\n if (updateHappenedRef.current) {\n return;\n }\n if (changes.find((c) => c._id === doc._id)) {\n void refresh();\n }\n }, true);\n }, [doc._id, refresh]);\n\n useEffect(() => {\n void refresh();\n }, [refresh]);\n\n const submit = useCallback(\n async (e?: Event) => {\n if (e?.preventDefault) e.preventDefault();\n await save();\n reset();\n },\n [save, reset],\n );\n\n // Primary Object API with both new and legacy methods\n const apiObject = {\n doc: { ...doc } as DocWithId<T>,\n merge,\n replace,\n reset,\n refresh,\n save,\n remove,\n submit,\n };\n\n // Make the object properly iterable\n const tuple = [{ ...doc }, updateDoc, save, remove, reset, refresh];\n Object.assign(apiObject, tuple);\n Object.defineProperty(apiObject, Symbol.iterator, {\n enumerable: false,\n value: function* () {\n yield* tuple;\n },\n });\n\n return apiObject as UseDocumentResult<T>;\n }\n\n function useLiveQuery<T extends DocTypes, K extends IndexKeyType = string, R extends DocFragment = T>(\n mapFn: MapFn<T> | string,\n query = {},\n initialRows: IndexRow<K, T, R>[] = [],\n ): LiveQueryResult<T, K, R> {\n const [result, setResult] = useState<LiveQueryResult<T, K, R>>(() => {\n const docs = initialRows.map((r) => r.doc).filter((r): r is DocWithId<T> => !!r);\n return {\n rows: initialRows,\n docs,\n length: docs.length,\n map: (fn) => docs.map(fn),\n filter: (fn) => docs.filter(fn),\n forEach: (fn) => docs.forEach(fn),\n [Symbol.iterator]: () => docs[Symbol.iterator](),\n };\n });\n\n const queryString = useMemo(() => JSON.stringify(query), [query]);\n const mapFnString = useMemo(() => mapFn.toString(), [mapFn]);\n\n const refreshRows = useCallback(async () => {\n const res = await database.query<K, T, R>(mapFn, query);\n const docs = res.rows.map((r) => r.doc as DocWithId<T>).filter((r): r is DocWithId<T> => !!r);\n setResult({\n ...res,\n docs,\n length: docs.length,\n map: (fn) => docs.map(fn),\n filter: (fn) => docs.filter(fn),\n forEach: (fn) => docs.forEach(fn),\n [Symbol.iterator]: () => docs[Symbol.iterator](),\n });\n }, [mapFnString, queryString]);\n\n useEffect(() => {\n refreshRows(); // Initial data fetch\n return database.subscribe(refreshRows);\n }, [refreshRows]);\n\n return result;\n }\n\n function useAllDocs<T extends DocTypes>(query: AllDocsQueryOpts = {}): AllDocsResult<T> {\n const [result, setResult] = useState<AllDocsResult<T>>({\n docs: [],\n });\n\n const queryString = useMemo(() => JSON.stringify(query), [query]);\n\n const refreshRows = useCallback(async () => {\n const res = await database.allDocs<T>(query);\n setResult({ ...res, docs: res.rows.map((r) => r.value as DocWithId<T>) });\n }, [queryString]);\n\n useEffect(() => {\n refreshRows(); // Initial data fetch\n return database.subscribe(refreshRows);\n }, [refreshRows]);\n\n return result;\n }\n\n function useChanges<T extends DocTypes>(since: ClockHead = [], opts: ChangesOptions = {}): ChangesResult<T> {\n const [result, setResult] = useState<ChangesResult<T>>({\n docs: [],\n });\n\n const queryString = useMemo(() => JSON.stringify(opts), [opts]);\n\n const refreshRows = useCallback(async () => {\n const res = await database.changes<T>(since, opts);\n setResult({ ...res, docs: res.rows.map((r) => r.value as DocWithId<T>) });\n }, [since, queryString]);\n\n useEffect(() => {\n refreshRows(); // Initial data fetch\n return database.subscribe(refreshRows);\n }, [refreshRows]);\n\n return result;\n }\n\n return { database, useLiveQuery, useDocument, useAllDocs, useChanges };\n}\n","import { Database, DocTypes, DocWithId } from \"@fireproof/core\";\n\nimport { UseDocument, UseDocumentResult, useFireproof } from \"./useFireproof.js\";\n\nexport interface TLUseDocument {\n <T extends DocTypes>(initialDoc: DocWithId<T>): UseDocumentResult<T>;\n database: Database;\n}\n\nfunction topLevelUseDocument(...args: Parameters<UseDocument>) {\n const { useDocument, database } = useFireproof();\n (topLevelUseDocument as TLUseDocument).database = database;\n return useDocument(...args);\n}\n\n/**\n * ## Summary\n *\n * React hook that provides the ability to create and manage Fireproof documents. The creation occurs when\n * you do not pass in an `_id` as part of your initial document -- the database will assign a new one when\n * you call the provided `save` handler.\n *\n * ## Usage\n *\n * ```tsx\n * const todo = useDocument({\n * text: '',\n * date: Date.now(),\n * completed: false\n * })\n * // Access via object properties\n * todo.doc // The current document\n * todo.merge({ completed: true }) // Update specific fields\n * todo.replace({ text: 'new', date: Date.now(), completed: false }) // Replace entire doc\n * todo.save() // Save changes\n * todo.remove() // Delete document\n * todo.reset() // Reset to initial state\n * todo.refresh() // Refresh from database\n * ```\n *\n * ### Create document with custom ID\n * Custom IDs let you create predictable document identifiers for data that has\n * a natural unique key, like userIds or email addresses. This makes it easy to\n * look up and update specific documents without having to query for them first.\n * For example, storing user profiles by customerId:\n *\n * ```tsx\n * const profile = useDocument({\n * _id: `${props.customerId}-profile`, // Predictable ID based on customerId\n * name: \"\",\n * company: \"\",\n * startedAt: Date.now()\n * })\n * ```\n *\n * ## API\n *\n * - `doc`: The current document state\n * - `merge(newDoc)`: Merge new properties into the document\n * - `replace(newDoc)`: Replace the entire document\n * - `reset()`: Reset to initial state\n * - `refresh()`: Refresh from database\n * - `save()`: Save changes to the document\n * - `remove()`: Delete the document\n *\n * ## Overview\n * Changes made via remote sync peers, or other members of your cloud replica group will appear automatically\n * when you use the `useLiveQuery` and `useDocument` APIs. By default, Fireproof stores data in the browser's\n * local storage.\n */\nexport const useDocument = topLevelUseDocument as TLUseDocument;\n","import { Database, DocFragment, DocTypes, IndexKeyType } from \"@fireproof/core\";\n\nimport { LiveQueryResult, useFireproof, UseLiveQuery } from \"./useFireproof.js\";\n\nexport interface TLUseLiveQuery {\n <T extends DocTypes, K extends IndexKeyType, R extends DocFragment = T>(\n ...args: Parameters<UseLiveQuery>\n ): LiveQueryResult<T, K, R>;\n database: Database;\n}\n\nfunction topLevelUseLiveQuery(...args: Parameters<UseLiveQuery>) {\n const { useLiveQuery, database } = useFireproof();\n (topLevelUseLiveQuery as TLUseLiveQuery).database = database;\n return useLiveQuery(...args);\n}\n\n/**\n * ## Summary\n * React hook that provides access to live query results, enabling real-time updates in your app. This uses\n * the default database named \"useFireproof\" under the hood which you can also access via the `database` accessor.\n *\n * ## Usage\n * ```tsx\n * const results = useLiveQuery(\"date\"); // using string\n * const results = useLiveQuery((doc) => doc.date)); // using map function\n * const database = useLiveQuery.database; // underlying \"useFireproof\" database accessor\n * ```\n *\n * ## Overview\n * Changes made via remote sync peers, or other members of your cloud replica group will appear automatically\n * when you use the `useLiveQuery` and `useDocument` APIs. By default, Fireproof stores data in the browser's\n * local storage.\n */\nexport const useLiveQuery = topLevelUseLiveQuery as TLUseLiveQuery;\n","import { Database, DocTypes } from \"@fireproof/core\";\n\nimport { AllDocsResult, useFireproof, UseAllDocs } from \"./useFireproof.js\";\n\nexport interface TLUseAllDocs {\n <T extends DocTypes>(...args: Parameters<UseAllDocs>): AllDocsResult<T>;\n database: Database;\n}\n\nfunction topLevelUseAllDocs(...args: Parameters<UseAllDocs>) {\n const { useAllDocs, database } = useFireproof();\n (topLevelUseAllDocs as TLUseAllDocs).database = database;\n return useAllDocs(...args);\n}\n\n/**\n * ## Summary\n * React hook that provides access to all documents in the database, sorted by `_id`.\n *\n * ## Usage\n * ```tsx\n * const result = useAllDocs({ limit: 10, descending: true }); // with options\n * const result = useAllDocs(); // without options\n * const database = useAllDocs.database; // underlying \"useFireproof\" database accessor\n * ```\n *\n * ## Overview\n * Changes made via remote sync peers, or other members of your cloud replica group will appear automatically\n * when you use the `useAllDocs` and `useDocument` APIs. By default, Fireproof stores data in the browser's\n * local storage.\n */\nexport const useAllDocs = topLevelUseAllDocs as TLUseAllDocs;\n","import { DocTypes, Database } from \"@fireproof/core\";\n\nimport { ChangesResult, useFireproof, UseChanges } from \"./useFireproof.js\";\n\nexport interface TLUseChanges {\n <T extends DocTypes>(...args: Parameters<UseChanges>): ChangesResult<T>;\n database: Database;\n}\n\nfunction topLevelUseChanges(...args: Parameters<UseChanges>) {\n const { useChanges, database } = useFireproof();\n (topLevelUseChanges as TLUseChanges).database = database;\n return useChanges(...args);\n}\n\n/**\n * ## Summary\n * React hook that provides access to all new documents in the database added since the last time the changes was called\n *\n * ## Usage\n * ```tsx\n * const result = useChanges(prevresult.clock,{limit:10}); // with options\n * const result = useChanges(); // without options\n * const database = useChanges.database; // underlying \"useFireproof\" database accessor\n * ```\n *\n * ## Overview\n * Changes made via remote sync peers, or other members of your cloud replica group will appear automatically\n * when you use the `useAllDocs`, `useChanges` and `useDocument` APIs. By default, Fireproof stores data in the browser's\n * local storage.\n */\nexport const useChanges = topLevelUseChanges as TLUseChanges;\n","import { DocFileMeta } from \"@fireproof/core\";\nimport React, { useState, useEffect, ImgHTMLAttributes } from \"react\";\n\nconst { URL } = globalThis;\n\n// Union type to support both direct File objects and metadata objects\ntype FileType = File | DocFileMeta;\n\ninterface ImgFileProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, \"src\"> {\n file?: FileType;\n /**\n * @deprecated Use 'file' instead. This is for internal use only to support legacy code.\n * @internal\n */\n meta?: FileType;\n}\n\n// Helper function to determine if the object is a File-like object\nfunction isFile(obj: FileType): obj is File {\n return \"type\" in obj && \"size\" in obj && \"stream\" in obj && typeof obj.stream === \"function\";\n}\n\n// Helper function to determine if the object is a DocFileMeta\nfunction isFileMeta(obj: FileType): obj is DocFileMeta {\n return \"type\" in obj && \"size\" in obj && \"file\" in obj && typeof obj.file === \"function\";\n}\n\nexport function ImgFile({ file, meta, ...imgProps }: ImgFileProps) {\n const [imgDataUrl, setImgDataUrl] = useState(\"\");\n\n // Use meta as fallback if file is not provided (for backward compatibility)\n const fileData = file || meta;\n\n useEffect(() => {\n if (!fileData) return;\n\n const loadFile = async () => {\n let fileObj: File | null = null;\n let fileType = \"\";\n\n switch (true) {\n case isFile(fileData):\n fileObj = fileData;\n fileType = fileData.type;\n break;\n case isFileMeta(fileData):\n fileType = fileData.type;\n fileObj = (await fileData.file?.()) || null;\n break;\n }\n\n if (fileObj && /image/.test(fileType)) {\n const src = URL.createObjectURL(fileObj);\n setImgDataUrl(src);\n return () => URL.revokeObjectURL(src);\n }\n };\n\n let isMounted = true;\n let cleanup: (() => void) | undefined;\n\n loadFile().then((result) => {\n if (isMounted) {\n cleanup = result;\n } else if (result) {\n result();\n }\n });\n\n return () => {\n isMounted = false;\n if (cleanup) cleanup();\n };\n }, [fileData]);\n\n return imgDataUrl\n ? React.createElement(\"img\", {\n src: imgDataUrl,\n ...imgProps,\n })\n : null;\n}\n\nexport default ImgFile;\n"],"mappings":"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","names":["useDocument","useLiveQuery","useAllDocs","useChanges","useDocument","useLiveQuery","useAllDocs","useChanges","import_react","React"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/react/index.ts","../../../src/react/use-fireproof.ts","../../../src/react/use-document.ts","../../../src/react/utils.ts","../../../src/react/use-live-query.ts","../../../src/react/use-all-docs.ts","../../../src/react/use-changes.ts","../../../src/react/img-file.ts"],"sourcesContent":["export { FireproofCtx, useFireproof } from \"./use-fireproof.js\";\nexport * from \"./types.js\";\nexport * from \"./img-file.js\";\n","import type { ConfigOpts, Database } from \"@fireproof/core\";\nimport { fireproof } from \"@fireproof/core\";\nimport type { UseFireproof } from \"./types.js\";\nimport { createUseDocument } from \"./use-document.js\";\nimport { createUseLiveQuery } from \"./use-live-query.js\";\nimport { createUseAllDocs } from \"./use-all-docs.js\";\nimport { createUseChanges } from \"./use-changes.js\";\n\n/**\n * @deprecated Use the `useFireproof` hook instead\n */\nexport const FireproofCtx = {} as UseFireproof;\n\n/**\n *\n * ## Summary\n *\n * React hook to create a custom-named Fireproof database and provides the utility hooks to query against it.\n *\n * ## Usage\n * ```tsx\n * const { database, useLiveQuery, useDocument } = useFireproof(\"dbname\");\n * const { database, useLiveQuery, useDocument } = useFireproof(\"dbname\", { ...options });\n * ```\n *\n * ## Overview\n *\n * TL;DR: Only use this hook if you need to configure a database name other than the default `useFireproof`.\n *\n * For most applications, using the `useLiveQuery` or `useDocument` hooks exported from `use-fireproof` should\n * suffice for the majority of use-cases. Under the hood, they act against a database named `useFireproof` instantiated with\n * default configurations. However, if you need to do a custom database setup or configure a database name more to your liking\n * than the default `useFireproof`, then use `useFireproof` as it exists for that purpose. It will provide you with the\n * custom database accessor and *lexically scoped* versions of `useLiveQuery` and `useDocument` that act against said\n * custom database.\n *\n */\nexport function useFireproof(name: string | Database = \"useFireproof\", config: ConfigOpts = {}): UseFireproof {\n const database = typeof name === \"string\" ? fireproof(name, config) : name;\n\n const useDocument = createUseDocument(database);\n const useLiveQuery = createUseLiveQuery(database);\n const useAllDocs = createUseAllDocs(database);\n const useChanges = createUseChanges(database);\n\n return { database, useLiveQuery, useDocument, useAllDocs, useChanges };\n}\n\n// Export types\nexport type {\n LiveQueryResult,\n UseDocumentResult,\n AllDocsResult,\n ChangesResult,\n UseDocument,\n UseLiveQuery,\n UseAllDocs,\n UseChanges,\n UseFireproof,\n} from \"./types.js\";\n","import { useCallback, useEffect, useMemo, useState, useRef } from \"react\";\nimport type { DocSet, DocTypes, DocWithId, Database } from \"@fireproof/core\";\nimport { deepClone } from \"./utils.js\";\nimport type { DeleteDocFn, StoreDocFn, UseDocumentInitialDocOrFn, UseDocumentResult } from \"./types.js\";\n\n/**\n * Implementation of the useDocument hook\n */\nexport function createUseDocument(database: Database) {\n const updateHappenedRef = useRef(false);\n\n return function useDocument<T extends DocTypes>(initialDocOrFn?: UseDocumentInitialDocOrFn<T>): UseDocumentResult<T> {\n let initialDoc: DocSet<T>;\n if (typeof initialDocOrFn === \"function\") {\n initialDoc = initialDocOrFn();\n } else {\n initialDoc = initialDocOrFn ?? ({} as T);\n }\n\n const originalInitialDoc = useMemo(() => deepClone({ ...initialDoc }), []);\n\n const [doc, setDoc] = useState(initialDoc);\n\n const refresh = useCallback(async () => {\n const gotDoc = doc._id ? await database.get<T>(doc._id).catch(() => initialDoc) : initialDoc;\n setDoc(gotDoc);\n }, [doc._id]);\n\n const save: StoreDocFn<T> = useCallback(\n async (existingDoc) => {\n updateHappenedRef.current = false;\n const toSave = existingDoc ?? doc;\n const res = await database.put(toSave);\n\n if (!updateHappenedRef.current && !doc._id && !existingDoc) {\n setDoc((d) => ({ ...d, _id: res.id }));\n }\n\n return res;\n },\n [doc],\n );\n\n const remove: DeleteDocFn<T> = useCallback(\n async (existingDoc) => {\n const id = existingDoc?._id ?? doc._id;\n if (!id) throw database.logger.Error().Msg(`Document must have an _id to be removed`).AsError();\n const gotDoc = await database.get<T>(id).catch(() => undefined);\n if (!gotDoc) throw database.logger.Error().Str(\"id\", id).Msg(`Document not found`).AsError();\n const res = await database.del(id);\n setDoc(initialDoc);\n return res;\n },\n [doc, initialDoc],\n );\n\n // New granular update methods\n const merge = useCallback((newDoc: Partial<T>) => {\n updateHappenedRef.current = true;\n setDoc((prev) => ({ ...prev, ...newDoc }));\n }, []);\n\n const replace = useCallback((newDoc: T) => {\n updateHappenedRef.current = true;\n setDoc(newDoc);\n }, []);\n\n const reset = useCallback(() => {\n updateHappenedRef.current = true;\n setDoc({ ...originalInitialDoc });\n }, [originalInitialDoc]);\n\n // Legacy-compatible updateDoc\n const updateDoc = useCallback(\n (newDoc?: DocSet<T>, opts = { replace: false, reset: false }) => {\n if (!newDoc) {\n return opts.reset ? reset() : refresh();\n }\n return opts.replace ? replace(newDoc as T) : merge(newDoc);\n },\n [refresh, reset, replace, merge],\n );\n\n useEffect(() => {\n if (!doc._id) return;\n return database.subscribe((changes) => {\n if (updateHappenedRef.current) {\n return;\n }\n if (changes.find((c) => c._id === doc._id)) {\n void refresh();\n }\n }, true);\n }, [doc._id, refresh]);\n\n useEffect(() => {\n void refresh();\n }, [refresh]);\n\n const submit = useCallback(\n async (e?: Event) => {\n if (e?.preventDefault) e.preventDefault();\n await save();\n reset();\n },\n [save, reset],\n );\n\n // Primary Object API with both new and legacy methods\n const apiObject = {\n doc: { ...doc } as DocWithId<T>,\n merge,\n replace,\n reset,\n refresh,\n save,\n remove,\n submit,\n };\n\n // Make the object properly iterable\n const tuple = [{ ...doc }, updateDoc, save, remove, reset, refresh];\n Object.assign(apiObject, tuple);\n Object.defineProperty(apiObject, Symbol.iterator, {\n enumerable: false,\n value: function* () {\n yield* tuple;\n },\n });\n\n return apiObject as UseDocumentResult<T>;\n };\n}\n","/**\n * Deep clone a value\n */\nexport function deepClone<T>(value: T): T {\n return (structuredClone ?? ((v: T) => JSON.parse(JSON.stringify(v))))(value);\n}\n","import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport type { DocFragment, DocTypes, DocWithId, IndexKeyType, IndexRow, MapFn, Database } from \"@fireproof/core\";\nimport type { LiveQueryResult } from \"./types.js\";\n\n/**\n * Implementation of the useLiveQuery hook\n */\nexport function createUseLiveQuery(database: Database) {\n return function useLiveQuery<T extends DocTypes, K extends IndexKeyType = string, R extends DocFragment = T>(\n mapFn: MapFn<T> | string,\n query = {},\n initialRows: IndexRow<K, T, R>[] = [],\n ): LiveQueryResult<T, K, R> {\n const [result, setResult] = useState<LiveQueryResult<T, K, R>>(() => {\n const docs = initialRows.map((r) => r.doc).filter((r): r is DocWithId<T> => !!r);\n return {\n rows: initialRows,\n docs,\n length: docs.length,\n map: <U>(fn: (value: DocWithId<T>, index: number, array: DocWithId<T>[]) => U) => docs.map(fn),\n filter: (fn: (value: DocWithId<T>, index: number, array: DocWithId<T>[]) => boolean) => docs.filter(fn),\n forEach: (fn: (value: DocWithId<T>, index: number, array: DocWithId<T>[]) => void) => docs.forEach(fn),\n [Symbol.iterator]: () => docs[Symbol.iterator](),\n } as LiveQueryResult<T, K, R>;\n });\n\n const queryString = useMemo(() => JSON.stringify(query), [query]);\n const mapFnString = useMemo(() => mapFn.toString(), [mapFn]);\n\n const refreshRows = useCallback(async () => {\n const res = await database.query<K, T, R>(mapFn, query);\n const docs = res.rows.map((r) => r.doc as DocWithId<T>).filter((r): r is DocWithId<T> => !!r);\n setResult({\n ...res,\n docs,\n length: docs.length,\n map: <U>(fn: (value: DocWithId<T>, index: number, array: DocWithId<T>[]) => U) => docs.map(fn),\n filter: (fn: (value: DocWithId<T>, index: number, array: DocWithId<T>[]) => boolean) => docs.filter(fn),\n forEach: (fn: (value: DocWithId<T>, index: number, array: DocWithId<T>[]) => void) => docs.forEach(fn),\n [Symbol.iterator]: () => docs[Symbol.iterator](),\n } as LiveQueryResult<T, K, R>);\n }, [mapFnString, queryString]);\n\n useEffect(() => {\n refreshRows(); // Initial data fetch\n return database.subscribe(refreshRows);\n }, [refreshRows]);\n\n return result;\n };\n}\n","import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport type { AllDocsQueryOpts, DocTypes, DocWithId, Database } from \"@fireproof/core\";\nimport type { AllDocsResult } from \"./types.js\";\n\n/**\n * Implementation of the useAllDocs hook\n */\nexport function createUseAllDocs(database: Database) {\n return function useAllDocs<T extends DocTypes>(query: AllDocsQueryOpts = {}): AllDocsResult<T> {\n const [result, setResult] = useState<AllDocsResult<T>>({\n docs: [],\n });\n\n const queryString = useMemo(() => JSON.stringify(query), [query]);\n\n const refreshRows = useCallback(async () => {\n const res = await database.allDocs<T>(query);\n setResult({ ...res, docs: res.rows.map((r) => r.value as DocWithId<T>) });\n }, [queryString]);\n\n useEffect(() => {\n refreshRows(); // Initial data fetch\n return database.subscribe(refreshRows);\n }, [refreshRows]);\n\n return result;\n };\n}\n","import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport type { ChangesOptions, ClockHead, DocTypes, DocWithId, Database } from \"@fireproof/core\";\nimport type { ChangesResult } from \"./types.js\";\n\n/**\n * Implementation of the useChanges hook\n */\nexport function createUseChanges(database: Database) {\n return function useChanges<T extends DocTypes>(since: ClockHead = [], opts: ChangesOptions = {}): ChangesResult<T> {\n const [result, setResult] = useState<ChangesResult<T>>({\n docs: [],\n });\n\n const queryString = useMemo(() => JSON.stringify(opts), [opts]);\n\n const refreshRows = useCallback(async () => {\n const res = await database.changes<T>(since, opts);\n setResult({ ...res, docs: res.rows.map((r) => r.value as DocWithId<T>) });\n }, [since, queryString]);\n\n useEffect(() => {\n refreshRows(); // Initial data fetch\n return database.subscribe(refreshRows);\n }, [refreshRows]);\n\n return result;\n };\n}\n","import { DocFileMeta } from \"@fireproof/core\";\nimport React, { useState, useEffect, ImgHTMLAttributes } from \"react\";\n\nconst { URL } = globalThis;\n\n// Union type to support both direct File objects and metadata objects\ntype FileType = File | DocFileMeta;\n\ninterface ImgFileProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, \"src\"> {\n file?: FileType;\n /**\n * @deprecated Use 'file' instead. This is for internal use only to support legacy code.\n * @internal\n */\n meta?: FileType;\n}\n\n// Helper function to determine if the object is a File-like object\nfunction isFile(obj: FileType): obj is File {\n return \"type\" in obj && \"size\" in obj && \"stream\" in obj && typeof obj.stream === \"function\";\n}\n\n// Helper function to determine if the object is a DocFileMeta\nfunction isFileMeta(obj: FileType): obj is DocFileMeta {\n return \"type\" in obj && \"size\" in obj && \"file\" in obj && typeof obj.file === \"function\";\n}\n\nexport function ImgFile({ file, meta, ...imgProps }: ImgFileProps) {\n const [imgDataUrl, setImgDataUrl] = useState(\"\");\n\n // Use meta as fallback if file is not provided (for backward compatibility)\n const fileData = file || meta;\n\n useEffect(() => {\n if (!fileData) return;\n\n const loadFile = async () => {\n let fileObj: File | null = null;\n let fileType = \"\";\n\n switch (true) {\n case isFile(fileData):\n fileObj = fileData;\n fileType = fileData.type;\n break;\n case isFileMeta(fileData):\n fileType = fileData.type;\n fileObj = (await fileData.file?.()) || null;\n break;\n }\n\n if (fileObj && /image/.test(fileType)) {\n const src = URL.createObjectURL(fileObj);\n setImgDataUrl(src);\n return () => URL.revokeObjectURL(src);\n }\n };\n\n let isMounted = true;\n let cleanup: (() => void) | undefined;\n\n loadFile().then((result) => {\n if (isMounted) {\n cleanup = result;\n } else if (result) {\n result();\n }\n });\n\n return () => {\n isMounted = false;\n if (cleanup) cleanup();\n };\n }, [fileData]);\n\n return imgDataUrl\n ? React.createElement(\"img\", {\n src: imgDataUrl,\n ...imgProps,\n })\n : null;\n}\n\nexport default ImgFile;\n"],"mappings":"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","names":["import_react","import_react","import_react","import_react","React"]}
|
package/react/index.d.cts
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Database, DocTypes, DocSet, DocWithId, DocResponse, IndexKeyType, DocFragment, MapFn, QueryOpts, IndexRow, AllDocsQueryOpts, ClockHead, ChangesOptions, ConfigOpts, DocFileMeta } from '@fireproof/core';
|
|
2
2
|
import React, { ImgHTMLAttributes } from 'react';
|
|
3
3
|
|
|
4
4
|
interface LiveQueryResult<T extends DocTypes, K extends IndexKeyType, R extends DocFragment = T> {
|
|
5
5
|
readonly docs: DocWithId<T>[];
|
|
6
6
|
readonly rows: IndexRow<K, T, R>[];
|
|
7
|
-
readonly length: number;
|
|
8
|
-
map<U>(callbackfn: (value: DocWithId<T>, index: number, array: DocWithId<T>[]) => U): U[];
|
|
9
|
-
filter(predicate: (value: DocWithId<T>, index: number, array: DocWithId<T>[]) => boolean): DocWithId<T>[];
|
|
10
|
-
forEach(callbackfn: (value: DocWithId<T>, index: number, array: DocWithId<T>[]) => void): void;
|
|
11
|
-
[Symbol.iterator](): Iterator<DocWithId<T>>;
|
|
12
7
|
}
|
|
13
8
|
type UseLiveQuery = <T extends DocTypes, K extends IndexKeyType = string, R extends DocFragment = T>(mapFn: string | MapFn<T>, query?: QueryOpts<K>, initialRows?: IndexRow<K, T, R>[]) => LiveQueryResult<T, K, R>;
|
|
14
9
|
interface AllDocsResult<T extends DocTypes> {
|
|
@@ -20,22 +15,22 @@ interface ChangesResult<T extends DocTypes> {
|
|
|
20
15
|
type UseAllDocs = <T extends DocTypes>(query?: AllDocsQueryOpts) => AllDocsResult<T>;
|
|
21
16
|
type UseChanges = <T extends DocTypes>(since: ClockHead, opts: ChangesOptions) => ChangesResult<T>;
|
|
22
17
|
interface UpdateDocFnOptions {
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
replace?: boolean;
|
|
19
|
+
reset?: boolean;
|
|
25
20
|
}
|
|
26
21
|
type UpdateDocFn<T extends DocTypes> = (newDoc?: DocSet<T>, options?: UpdateDocFnOptions) => void;
|
|
27
22
|
type StoreDocFn<T extends DocTypes> = (existingDoc?: DocWithId<T>) => Promise<DocResponse>;
|
|
28
23
|
type DeleteDocFn<T extends DocTypes> = (existingDoc?: DocWithId<T>) => Promise<DocResponse>;
|
|
29
24
|
type UseDocumentResultTuple<T extends DocTypes> = [DocWithId<T>, UpdateDocFn<T>, StoreDocFn<T>, DeleteDocFn<T>];
|
|
30
25
|
interface UseDocumentResultObject<T extends DocTypes> {
|
|
31
|
-
doc: DocWithId<T>;
|
|
32
|
-
merge
|
|
33
|
-
replace
|
|
34
|
-
reset
|
|
35
|
-
refresh
|
|
36
|
-
save:
|
|
37
|
-
remove:
|
|
38
|
-
submit
|
|
26
|
+
readonly doc: DocWithId<T>;
|
|
27
|
+
merge(newDoc: Partial<T>): void;
|
|
28
|
+
replace(newDoc: T): void;
|
|
29
|
+
reset(): void;
|
|
30
|
+
refresh(): Promise<void>;
|
|
31
|
+
save(existingDoc?: DocWithId<T>): Promise<DocResponse>;
|
|
32
|
+
remove(existingDoc?: DocWithId<T>): Promise<DocResponse>;
|
|
33
|
+
submit(e?: Event): Promise<void>;
|
|
39
34
|
}
|
|
40
35
|
type UseDocumentResult<T extends DocTypes> = UseDocumentResultObject<T> & UseDocumentResultTuple<T>;
|
|
41
36
|
type UseDocumentInitialDocOrFn<T extends DocTypes> = DocSet<T> | (() => DocSet<T>);
|
|
@@ -47,33 +42,10 @@ interface UseFireproof {
|
|
|
47
42
|
readonly useAllDocs: UseAllDocs;
|
|
48
43
|
readonly useChanges: UseChanges;
|
|
49
44
|
}
|
|
45
|
+
|
|
50
46
|
declare const FireproofCtx: UseFireproof;
|
|
51
47
|
declare function useFireproof(name?: string | Database, config?: ConfigOpts): UseFireproof;
|
|
52
48
|
|
|
53
|
-
interface TLUseDocument {
|
|
54
|
-
<T extends DocTypes>(initialDoc: DocWithId<T>): UseDocumentResult<T>;
|
|
55
|
-
database: Database;
|
|
56
|
-
}
|
|
57
|
-
declare const useDocument: TLUseDocument;
|
|
58
|
-
|
|
59
|
-
interface TLUseLiveQuery {
|
|
60
|
-
<T extends DocTypes, K extends IndexKeyType, R extends DocFragment = T>(...args: Parameters<UseLiveQuery>): LiveQueryResult<T, K, R>;
|
|
61
|
-
database: Database;
|
|
62
|
-
}
|
|
63
|
-
declare const useLiveQuery: TLUseLiveQuery;
|
|
64
|
-
|
|
65
|
-
interface TLUseAllDocs {
|
|
66
|
-
<T extends DocTypes>(...args: Parameters<UseAllDocs>): AllDocsResult<T>;
|
|
67
|
-
database: Database;
|
|
68
|
-
}
|
|
69
|
-
declare const useAllDocs: TLUseAllDocs;
|
|
70
|
-
|
|
71
|
-
interface TLUseChanges {
|
|
72
|
-
<T extends DocTypes>(...args: Parameters<UseChanges>): ChangesResult<T>;
|
|
73
|
-
database: Database;
|
|
74
|
-
}
|
|
75
|
-
declare const useChanges: TLUseChanges;
|
|
76
|
-
|
|
77
49
|
type FileType = File | DocFileMeta;
|
|
78
50
|
interface ImgFileProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, "src"> {
|
|
79
51
|
file?: FileType;
|
|
@@ -360,5 +332,5 @@ declare function ImgFile({ file, meta, ...imgProps }: ImgFileProps): React.Detai
|
|
|
360
332
|
src: string;
|
|
361
333
|
}, HTMLElement> | null;
|
|
362
334
|
|
|
363
|
-
export { FireproofCtx, ImgFile, type LiveQueryResult, type
|
|
335
|
+
export { type AllDocsResult, type ChangesResult, type DeleteDocFn, FireproofCtx, ImgFile, type LiveQueryResult, type StoreDocFn, type UpdateDocFn, type UpdateDocFnOptions, type UseAllDocs, type UseChanges, type UseDocument, type UseDocumentInitialDocOrFn, type UseDocumentResult, type UseDocumentResultObject, type UseDocumentResultTuple, type UseFireproof, type UseLiveQuery, useFireproof };
|
|
364
336
|
declare module '@fireproof/core/react'
|
package/react/index.d.ts
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Database, DocTypes, DocSet, DocWithId, DocResponse, IndexKeyType, DocFragment, MapFn, QueryOpts, IndexRow, AllDocsQueryOpts, ClockHead, ChangesOptions, ConfigOpts, DocFileMeta } from '@fireproof/core';
|
|
2
2
|
import React, { ImgHTMLAttributes } from 'react';
|
|
3
3
|
|
|
4
4
|
interface LiveQueryResult<T extends DocTypes, K extends IndexKeyType, R extends DocFragment = T> {
|
|
5
5
|
readonly docs: DocWithId<T>[];
|
|
6
6
|
readonly rows: IndexRow<K, T, R>[];
|
|
7
|
-
readonly length: number;
|
|
8
|
-
map<U>(callbackfn: (value: DocWithId<T>, index: number, array: DocWithId<T>[]) => U): U[];
|
|
9
|
-
filter(predicate: (value: DocWithId<T>, index: number, array: DocWithId<T>[]) => boolean): DocWithId<T>[];
|
|
10
|
-
forEach(callbackfn: (value: DocWithId<T>, index: number, array: DocWithId<T>[]) => void): void;
|
|
11
|
-
[Symbol.iterator](): Iterator<DocWithId<T>>;
|
|
12
7
|
}
|
|
13
8
|
type UseLiveQuery = <T extends DocTypes, K extends IndexKeyType = string, R extends DocFragment = T>(mapFn: string | MapFn<T>, query?: QueryOpts<K>, initialRows?: IndexRow<K, T, R>[]) => LiveQueryResult<T, K, R>;
|
|
14
9
|
interface AllDocsResult<T extends DocTypes> {
|
|
@@ -20,22 +15,22 @@ interface ChangesResult<T extends DocTypes> {
|
|
|
20
15
|
type UseAllDocs = <T extends DocTypes>(query?: AllDocsQueryOpts) => AllDocsResult<T>;
|
|
21
16
|
type UseChanges = <T extends DocTypes>(since: ClockHead, opts: ChangesOptions) => ChangesResult<T>;
|
|
22
17
|
interface UpdateDocFnOptions {
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
replace?: boolean;
|
|
19
|
+
reset?: boolean;
|
|
25
20
|
}
|
|
26
21
|
type UpdateDocFn<T extends DocTypes> = (newDoc?: DocSet<T>, options?: UpdateDocFnOptions) => void;
|
|
27
22
|
type StoreDocFn<T extends DocTypes> = (existingDoc?: DocWithId<T>) => Promise<DocResponse>;
|
|
28
23
|
type DeleteDocFn<T extends DocTypes> = (existingDoc?: DocWithId<T>) => Promise<DocResponse>;
|
|
29
24
|
type UseDocumentResultTuple<T extends DocTypes> = [DocWithId<T>, UpdateDocFn<T>, StoreDocFn<T>, DeleteDocFn<T>];
|
|
30
25
|
interface UseDocumentResultObject<T extends DocTypes> {
|
|
31
|
-
doc: DocWithId<T>;
|
|
32
|
-
merge
|
|
33
|
-
replace
|
|
34
|
-
reset
|
|
35
|
-
refresh
|
|
36
|
-
save:
|
|
37
|
-
remove:
|
|
38
|
-
submit
|
|
26
|
+
readonly doc: DocWithId<T>;
|
|
27
|
+
merge(newDoc: Partial<T>): void;
|
|
28
|
+
replace(newDoc: T): void;
|
|
29
|
+
reset(): void;
|
|
30
|
+
refresh(): Promise<void>;
|
|
31
|
+
save(existingDoc?: DocWithId<T>): Promise<DocResponse>;
|
|
32
|
+
remove(existingDoc?: DocWithId<T>): Promise<DocResponse>;
|
|
33
|
+
submit(e?: Event): Promise<void>;
|
|
39
34
|
}
|
|
40
35
|
type UseDocumentResult<T extends DocTypes> = UseDocumentResultObject<T> & UseDocumentResultTuple<T>;
|
|
41
36
|
type UseDocumentInitialDocOrFn<T extends DocTypes> = DocSet<T> | (() => DocSet<T>);
|
|
@@ -47,33 +42,10 @@ interface UseFireproof {
|
|
|
47
42
|
readonly useAllDocs: UseAllDocs;
|
|
48
43
|
readonly useChanges: UseChanges;
|
|
49
44
|
}
|
|
45
|
+
|
|
50
46
|
declare const FireproofCtx: UseFireproof;
|
|
51
47
|
declare function useFireproof(name?: string | Database, config?: ConfigOpts): UseFireproof;
|
|
52
48
|
|
|
53
|
-
interface TLUseDocument {
|
|
54
|
-
<T extends DocTypes>(initialDoc: DocWithId<T>): UseDocumentResult<T>;
|
|
55
|
-
database: Database;
|
|
56
|
-
}
|
|
57
|
-
declare const useDocument: TLUseDocument;
|
|
58
|
-
|
|
59
|
-
interface TLUseLiveQuery {
|
|
60
|
-
<T extends DocTypes, K extends IndexKeyType, R extends DocFragment = T>(...args: Parameters<UseLiveQuery>): LiveQueryResult<T, K, R>;
|
|
61
|
-
database: Database;
|
|
62
|
-
}
|
|
63
|
-
declare const useLiveQuery: TLUseLiveQuery;
|
|
64
|
-
|
|
65
|
-
interface TLUseAllDocs {
|
|
66
|
-
<T extends DocTypes>(...args: Parameters<UseAllDocs>): AllDocsResult<T>;
|
|
67
|
-
database: Database;
|
|
68
|
-
}
|
|
69
|
-
declare const useAllDocs: TLUseAllDocs;
|
|
70
|
-
|
|
71
|
-
interface TLUseChanges {
|
|
72
|
-
<T extends DocTypes>(...args: Parameters<UseChanges>): ChangesResult<T>;
|
|
73
|
-
database: Database;
|
|
74
|
-
}
|
|
75
|
-
declare const useChanges: TLUseChanges;
|
|
76
|
-
|
|
77
49
|
type FileType = File | DocFileMeta;
|
|
78
50
|
interface ImgFileProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, "src"> {
|
|
79
51
|
file?: FileType;
|
|
@@ -360,5 +332,5 @@ declare function ImgFile({ file, meta, ...imgProps }: ImgFileProps): React.Detai
|
|
|
360
332
|
src: string;
|
|
361
333
|
}, HTMLElement> | null;
|
|
362
334
|
|
|
363
|
-
export { FireproofCtx, ImgFile, type LiveQueryResult, type
|
|
335
|
+
export { type AllDocsResult, type ChangesResult, type DeleteDocFn, FireproofCtx, ImgFile, type LiveQueryResult, type StoreDocFn, type UpdateDocFn, type UpdateDocFnOptions, type UseAllDocs, type UseChanges, type UseDocument, type UseDocumentInitialDocOrFn, type UseDocumentResult, type UseDocumentResultObject, type UseDocumentResultTuple, type UseFireproof, type UseLiveQuery, useFireproof };
|
|
364
336
|
declare module '@fireproof/core/react'
|
package/react/index.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
// src/react/
|
|
1
|
+
// src/react/use-fireproof.ts
|
|
2
2
|
import { fireproof } from "@fireproof/core";
|
|
3
|
+
|
|
4
|
+
// src/react/use-document.ts
|
|
3
5
|
import { useCallback, useEffect, useMemo, useState, useRef } from "react";
|
|
4
|
-
|
|
6
|
+
|
|
7
|
+
// src/react/utils.ts
|
|
5
8
|
function deepClone(value) {
|
|
6
|
-
|
|
7
|
-
return structuredClone(value);
|
|
8
|
-
} else {
|
|
9
|
-
return JSON.parse(JSON.stringify(value));
|
|
10
|
-
}
|
|
9
|
+
return (structuredClone ?? ((v) => JSON.parse(JSON.stringify(v))))(value);
|
|
11
10
|
}
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
|
|
12
|
+
// src/react/use-document.ts
|
|
13
|
+
function createUseDocument(database) {
|
|
14
14
|
const updateHappenedRef = useRef(false);
|
|
15
|
-
function
|
|
15
|
+
return function useDocument(initialDocOrFn) {
|
|
16
16
|
let initialDoc;
|
|
17
17
|
if (typeof initialDocOrFn === "function") {
|
|
18
18
|
initialDoc = initialDocOrFn();
|
|
@@ -111,9 +111,14 @@ function useFireproof(name = "useFireproof", config = {}) {
|
|
|
111
111
|
}
|
|
112
112
|
});
|
|
113
113
|
return apiObject;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// src/react/use-live-query.ts
|
|
118
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo2, useState as useState2 } from "react";
|
|
119
|
+
function createUseLiveQuery(database) {
|
|
120
|
+
return function useLiveQuery(mapFn, query = {}, initialRows = []) {
|
|
121
|
+
const [result, setResult] = useState2(() => {
|
|
117
122
|
const docs = initialRows.map((r) => r.doc).filter((r) => !!r);
|
|
118
123
|
return {
|
|
119
124
|
rows: initialRows,
|
|
@@ -125,9 +130,9 @@ function useFireproof(name = "useFireproof", config = {}) {
|
|
|
125
130
|
[Symbol.iterator]: () => docs[Symbol.iterator]()
|
|
126
131
|
};
|
|
127
132
|
});
|
|
128
|
-
const queryString =
|
|
129
|
-
const mapFnString =
|
|
130
|
-
const refreshRows =
|
|
133
|
+
const queryString = useMemo2(() => JSON.stringify(query), [query]);
|
|
134
|
+
const mapFnString = useMemo2(() => mapFn.toString(), [mapFn]);
|
|
135
|
+
const refreshRows = useCallback2(async () => {
|
|
131
136
|
const res = await database.query(mapFn, query);
|
|
132
137
|
const docs = res.rows.map((r) => r.doc).filter((r) => !!r);
|
|
133
138
|
setResult({
|
|
@@ -140,79 +145,67 @@ function useFireproof(name = "useFireproof", config = {}) {
|
|
|
140
145
|
[Symbol.iterator]: () => docs[Symbol.iterator]()
|
|
141
146
|
});
|
|
142
147
|
}, [mapFnString, queryString]);
|
|
143
|
-
|
|
148
|
+
useEffect2(() => {
|
|
144
149
|
refreshRows();
|
|
145
150
|
return database.subscribe(refreshRows);
|
|
146
151
|
}, [refreshRows]);
|
|
147
152
|
return result;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// src/react/use-all-docs.ts
|
|
157
|
+
import { useCallback as useCallback3, useEffect as useEffect3, useMemo as useMemo3, useState as useState3 } from "react";
|
|
158
|
+
function createUseAllDocs(database) {
|
|
159
|
+
return function useAllDocs(query = {}) {
|
|
160
|
+
const [result, setResult] = useState3({
|
|
151
161
|
docs: []
|
|
152
162
|
});
|
|
153
|
-
const queryString =
|
|
154
|
-
const refreshRows =
|
|
163
|
+
const queryString = useMemo3(() => JSON.stringify(query), [query]);
|
|
164
|
+
const refreshRows = useCallback3(async () => {
|
|
155
165
|
const res = await database.allDocs(query);
|
|
156
166
|
setResult({ ...res, docs: res.rows.map((r) => r.value) });
|
|
157
167
|
}, [queryString]);
|
|
158
|
-
|
|
168
|
+
useEffect3(() => {
|
|
159
169
|
refreshRows();
|
|
160
170
|
return database.subscribe(refreshRows);
|
|
161
171
|
}, [refreshRows]);
|
|
162
172
|
return result;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// src/react/use-changes.ts
|
|
177
|
+
import { useCallback as useCallback4, useEffect as useEffect4, useMemo as useMemo4, useState as useState4 } from "react";
|
|
178
|
+
function createUseChanges(database) {
|
|
179
|
+
return function useChanges(since = [], opts = {}) {
|
|
180
|
+
const [result, setResult] = useState4({
|
|
166
181
|
docs: []
|
|
167
182
|
});
|
|
168
|
-
const queryString =
|
|
169
|
-
const refreshRows =
|
|
183
|
+
const queryString = useMemo4(() => JSON.stringify(opts), [opts]);
|
|
184
|
+
const refreshRows = useCallback4(async () => {
|
|
170
185
|
const res = await database.changes(since, opts);
|
|
171
186
|
setResult({ ...res, docs: res.rows.map((r) => r.value) });
|
|
172
187
|
}, [since, queryString]);
|
|
173
|
-
|
|
188
|
+
useEffect4(() => {
|
|
174
189
|
refreshRows();
|
|
175
190
|
return database.subscribe(refreshRows);
|
|
176
191
|
}, [refreshRows]);
|
|
177
192
|
return result;
|
|
178
|
-
}
|
|
179
|
-
return { database, useLiveQuery: useLiveQuery2, useDocument: useDocument2, useAllDocs: useAllDocs2, useChanges: useChanges2 };
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// src/react/useDocument.ts
|
|
183
|
-
function topLevelUseDocument(...args) {
|
|
184
|
-
const { useDocument: useDocument2, database } = useFireproof();
|
|
185
|
-
topLevelUseDocument.database = database;
|
|
186
|
-
return useDocument2(...args);
|
|
187
|
-
}
|
|
188
|
-
var useDocument = topLevelUseDocument;
|
|
189
|
-
|
|
190
|
-
// src/react/useLiveQuery.ts
|
|
191
|
-
function topLevelUseLiveQuery(...args) {
|
|
192
|
-
const { useLiveQuery: useLiveQuery2, database } = useFireproof();
|
|
193
|
-
topLevelUseLiveQuery.database = database;
|
|
194
|
-
return useLiveQuery2(...args);
|
|
195
|
-
}
|
|
196
|
-
var useLiveQuery = topLevelUseLiveQuery;
|
|
197
|
-
|
|
198
|
-
// src/react/useAllDocs.ts
|
|
199
|
-
function topLevelUseAllDocs(...args) {
|
|
200
|
-
const { useAllDocs: useAllDocs2, database } = useFireproof();
|
|
201
|
-
topLevelUseAllDocs.database = database;
|
|
202
|
-
return useAllDocs2(...args);
|
|
193
|
+
};
|
|
203
194
|
}
|
|
204
|
-
var useAllDocs = topLevelUseAllDocs;
|
|
205
195
|
|
|
206
|
-
// src/react/
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
196
|
+
// src/react/use-fireproof.ts
|
|
197
|
+
var FireproofCtx = {};
|
|
198
|
+
function useFireproof(name = "useFireproof", config = {}) {
|
|
199
|
+
const database = typeof name === "string" ? fireproof(name, config) : name;
|
|
200
|
+
const useDocument = createUseDocument(database);
|
|
201
|
+
const useLiveQuery = createUseLiveQuery(database);
|
|
202
|
+
const useAllDocs = createUseAllDocs(database);
|
|
203
|
+
const useChanges = createUseChanges(database);
|
|
204
|
+
return { database, useLiveQuery, useDocument, useAllDocs, useChanges };
|
|
211
205
|
}
|
|
212
|
-
var useChanges = topLevelUseChanges;
|
|
213
206
|
|
|
214
207
|
// src/react/img-file.ts
|
|
215
|
-
import React, { useState as
|
|
208
|
+
import React, { useState as useState5, useEffect as useEffect5 } from "react";
|
|
216
209
|
var { URL } = globalThis;
|
|
217
210
|
function isFile(obj) {
|
|
218
211
|
return "type" in obj && "size" in obj && "stream" in obj && typeof obj.stream === "function";
|
|
@@ -221,9 +214,9 @@ function isFileMeta(obj) {
|
|
|
221
214
|
return "type" in obj && "size" in obj && "file" in obj && typeof obj.file === "function";
|
|
222
215
|
}
|
|
223
216
|
function ImgFile({ file, meta, ...imgProps }) {
|
|
224
|
-
const [imgDataUrl, setImgDataUrl] =
|
|
217
|
+
const [imgDataUrl, setImgDataUrl] = useState5("");
|
|
225
218
|
const fileData = file || meta;
|
|
226
|
-
|
|
219
|
+
useEffect5(() => {
|
|
227
220
|
if (!fileData) return;
|
|
228
221
|
const loadFile = async () => {
|
|
229
222
|
let fileObj = null;
|
|
@@ -266,10 +259,6 @@ function ImgFile({ file, meta, ...imgProps }) {
|
|
|
266
259
|
export {
|
|
267
260
|
FireproofCtx,
|
|
268
261
|
ImgFile,
|
|
269
|
-
|
|
270
|
-
useChanges,
|
|
271
|
-
useDocument,
|
|
272
|
-
useFireproof,
|
|
273
|
-
useLiveQuery
|
|
262
|
+
useFireproof
|
|
274
263
|
};
|
|
275
264
|
//# sourceMappingURL=index.js.map
|