@fireproof/core 0.20.4-dev-preview-2 → 0.20.4-dev-preview-4
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/index.cjs +4 -2
- package/index.cjs.map +1 -1
- package/index.js +4 -2
- package/index.js.map +1 -1
- package/metafile-cjs.json +1 -1
- package/metafile-esm.json +1 -1
- package/package.json +1 -1
- package/react/index.cjs +10 -2
- package/react/index.cjs.map +1 -1
- package/react/index.js +10 -2
- package/react/index.js.map +1 -1
- package/react/metafile-cjs.json +1 -1
- package/react/metafile-esm.json +1 -1
- package/tests/react/use-document-with-nonexistent-id.test.tsx +113 -0
package/react/index.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../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":["import type { ConfigOpts, Database } from \"@fireproof/core\";\nimport { fireproof } from \"@fireproof/core\";\nimport { useMemo } from \"react\";\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 *\n */\nexport function useFireproof(name: string | Database = \"useFireproof\", config: ConfigOpts = {}): UseFireproof {\n // Use useMemo to ensure stable references across renders\n return useMemo(() => {\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 }, [name, JSON.stringify(config)]); // Only recreate if name or stringified config changes\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 return function useDocument<T extends DocTypes>(initialDocOrFn?: UseDocumentInitialDocOrFn<T>): UseDocumentResult<T> {\n const updateHappenedRef = useRef(false);\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 docs: initialRows.map((r) => r.doc).filter((r): r is DocWithId<T> => !!r),\n rows: initialRows,\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 setResult({\n docs: res.rows.map((r) => r.doc).filter((r): r is DocWithId<T> => !!r),\n rows: res.rows,\n });\n }, [database, mapFnString, queryString]);\n\n useEffect(() => {\n refreshRows();\n const unsubscribe = database.subscribe(refreshRows);\n return () => {\n unsubscribe();\n };\n }, [database, 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({\n ...res,\n docs: res.rows.map((r) => r.value as DocWithId<T>),\n });\n }, [database, queryString]);\n\n useEffect(() => {\n refreshRows();\n const unsubscribe = database.subscribe(refreshRows);\n return () => {\n unsubscribe();\n };\n }, [database, 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":";AACA,SAAS,iBAAiB;AAC1B,SAAS,WAAAA,gBAAe;;;ACFxB,SAAS,aAAa,WAAW,SAAS,UAAU,cAAc;;;ACG3D,SAAS,UAAa,OAAa;AACxC,UAAQ,oBAAoB,CAAC,MAAS,KAAK,MAAM,KAAK,UAAU,CAAC,CAAC,IAAI,KAAK;AAC7E;;;ADGO,SAAS,kBAAkB,UAAoB;AACpD,SAAO,SAAS,YAAgC,gBAAqE;AACnH,UAAM,oBAAoB,OAAO,KAAK;AACtC,QAAI;AACJ,QAAI,OAAO,mBAAmB,YAAY;AACxC,mBAAa,eAAe;AAAA,IAC9B,OAAO;AACL,mBAAa,kBAAmB,CAAC;AAAA,IACnC;AAEA,UAAM,qBAAqB,QAAQ,MAAM,UAAU,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;AAEzE,UAAM,CAAC,KAAK,MAAM,IAAI,SAAS,UAAU;AAEzC,UAAM,UAAU,YAAY,YAAY;AACtC,YAAM,SAAS,IAAI,MAAM,MAAM,SAAS,IAAO,IAAI,GAAG,EAAE,MAAM,MAAM,UAAU,IAAI;AAClF,aAAO,MAAM;AAAA,IACf,GAAG,CAAC,IAAI,GAAG,CAAC;AAEZ,UAAM,OAAsB;AAAA,MAC1B,OAAO,gBAAgB;AACrB,0BAAkB,UAAU;AAC5B,cAAM,SAAS,eAAe;AAC9B,cAAM,MAAM,MAAM,SAAS,IAAI,MAAM;AAErC,YAAI,CAAC,kBAAkB,WAAW,CAAC,IAAI,OAAO,CAAC,aAAa;AAC1D,iBAAO,CAAC,OAAO,EAAE,GAAG,GAAG,KAAK,IAAI,GAAG,EAAE;AAAA,QACvC;AAEA,eAAO;AAAA,MACT;AAAA,MACA,CAAC,GAAG;AAAA,IACN;AAEA,UAAM,SAAyB;AAAA,MAC7B,OAAO,gBAAgB;AACrB,cAAM,KAAK,aAAa,OAAO,IAAI;AACnC,YAAI,CAAC,GAAI,OAAM,SAAS,OAAO,MAAM,EAAE,IAAI,yCAAyC,EAAE,QAAQ;AAC9F,cAAM,SAAS,MAAM,SAAS,IAAO,EAAE,EAAE,MAAM,MAAM,MAAS;AAC9D,YAAI,CAAC,OAAQ,OAAM,SAAS,OAAO,MAAM,EAAE,IAAI,MAAM,EAAE,EAAE,IAAI,oBAAoB,EAAE,QAAQ;AAC3F,cAAM,MAAM,MAAM,SAAS,IAAI,EAAE;AACjC,eAAO,UAAU;AACjB,eAAO;AAAA,MACT;AAAA,MACA,CAAC,KAAK,UAAU;AAAA,IAClB;AAGA,UAAM,QAAQ,YAAY,CAAC,WAAuB;AAChD,wBAAkB,UAAU;AAC5B,aAAO,CAAC,UAAU,EAAE,GAAG,MAAM,GAAG,OAAO,EAAE;AAAA,IAC3C,GAAG,CAAC,CAAC;AAEL,UAAM,UAAU,YAAY,CAAC,WAAc;AACzC,wBAAkB,UAAU;AAC5B,aAAO,MAAM;AAAA,IACf,GAAG,CAAC,CAAC;AAEL,UAAM,QAAQ,YAAY,MAAM;AAC9B,wBAAkB,UAAU;AAC5B,aAAO,EAAE,GAAG,mBAAmB,CAAC;AAAA,IAClC,GAAG,CAAC,kBAAkB,CAAC;AAGvB,UAAM,YAAY;AAAA,MAChB,CAAC,QAAoB,OAAO,EAAE,SAAS,OAAO,OAAO,MAAM,MAAM;AAC/D,YAAI,CAAC,QAAQ;AACX,iBAAO,KAAK,QAAQ,MAAM,IAAI,QAAQ;AAAA,QACxC;AACA,eAAO,KAAK,UAAU,QAAQ,MAAW,IAAI,MAAM,MAAM;AAAA,MAC3D;AAAA,MACA,CAAC,SAAS,OAAO,SAAS,KAAK;AAAA,IACjC;AAEA,cAAU,MAAM;AACd,UAAI,CAAC,IAAI,IAAK;AACd,aAAO,SAAS,UAAU,CAAC,YAAY;AACrC,YAAI,kBAAkB,SAAS;AAC7B;AAAA,QACF;AACA,YAAI,QAAQ,KAAK,CAAC,MAAM,EAAE,QAAQ,IAAI,GAAG,GAAG;AAC1C,eAAK,QAAQ;AAAA,QACf;AAAA,MACF,GAAG,IAAI;AAAA,IACT,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC;AAErB,cAAU,MAAM;AACd,WAAK,QAAQ;AAAA,IACf,GAAG,CAAC,OAAO,CAAC;AAEZ,UAAM,SAAS;AAAA,MACb,OAAO,MAAc;AACnB,YAAI,GAAG,eAAgB,GAAE,eAAe;AACxC,cAAM,KAAK;AACX,cAAM;AAAA,MACR;AAAA,MACA,CAAC,MAAM,KAAK;AAAA,IACd;AAGA,UAAM,YAAY;AAAA,MAChB,KAAK,EAAE,GAAG,IAAI;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAGA,UAAM,QAAQ,CAAC,EAAE,GAAG,IAAI,GAAG,WAAW,MAAM,QAAQ,OAAO,OAAO;AAClE,WAAO,OAAO,WAAW,KAAK;AAC9B,WAAO,eAAe,WAAW,OAAO,UAAU;AAAA,MAChD,YAAY;AAAA,MACZ,OAAO,aAAa;AAClB,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT;AACF;;;AEnIA,SAAS,eAAAC,cAAa,aAAAC,YAAW,WAAAC,UAAS,YAAAC,iBAAgB;AAOnD,SAAS,mBAAmB,UAAoB;AACrD,SAAO,SAAS,aACd,OACA,QAAQ,CAAC,GACT,cAAmC,CAAC,GACV;AAC1B,UAAM,CAAC,QAAQ,SAAS,IAAIA,UAAmC;AAAA,MAC7D,MAAM,YAAY,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,MAAyB,CAAC,CAAC,CAAC;AAAA,MACxE,MAAM;AAAA,IACR,CAAC;AAED,UAAM,cAAcD,SAAQ,MAAM,KAAK,UAAU,KAAK,GAAG,CAAC,KAAK,CAAC;AAChE,UAAM,cAAcA,SAAQ,MAAM,MAAM,SAAS,GAAG,CAAC,KAAK,CAAC;AAE3D,UAAM,cAAcF,aAAY,YAAY;AAC1C,YAAM,MAAM,MAAM,SAAS,MAAe,OAAO,KAAK;AACtD,gBAAU;AAAA,QACR,MAAM,IAAI,KAAK,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,MAAyB,CAAC,CAAC,CAAC;AAAA,QACrE,MAAM,IAAI;AAAA,MACZ,CAAC;AAAA,IACH,GAAG,CAAC,UAAU,aAAa,WAAW,CAAC;AAEvC,IAAAC,WAAU,MAAM;AACd,kBAAY;AACZ,YAAM,cAAc,SAAS,UAAU,WAAW;AAClD,aAAO,MAAM;AACX,oBAAY;AAAA,MACd;AAAA,IACF,GAAG,CAAC,UAAU,WAAW,CAAC;AAE1B,WAAO;AAAA,EACT;AACF;;;ACvCA,SAAS,eAAAG,cAAa,aAAAC,YAAW,WAAAC,UAAS,YAAAC,iBAAgB;AAOnD,SAAS,iBAAiB,UAAoB;AACnD,SAAO,SAAS,WAA+B,QAA0B,CAAC,GAAqB;AAC7F,UAAM,CAAC,QAAQ,SAAS,IAAIA,UAA2B;AAAA,MACrD,MAAM,CAAC;AAAA,IACT,CAAC;AAED,UAAM,cAAcD,SAAQ,MAAM,KAAK,UAAU,KAAK,GAAG,CAAC,KAAK,CAAC;AAEhE,UAAM,cAAcF,aAAY,YAAY;AAC1C,YAAM,MAAM,MAAM,SAAS,QAAW,KAAK;AAC3C,gBAAU;AAAA,QACR,GAAG;AAAA,QACH,MAAM,IAAI,KAAK,IAAI,CAAC,MAAM,EAAE,KAAqB;AAAA,MACnD,CAAC;AAAA,IACH,GAAG,CAAC,UAAU,WAAW,CAAC;AAE1B,IAAAC,WAAU,MAAM;AACd,kBAAY;AACZ,YAAM,cAAc,SAAS,UAAU,WAAW;AAClD,aAAO,MAAM;AACX,oBAAY;AAAA,MACd;AAAA,IACF,GAAG,CAAC,UAAU,WAAW,CAAC;AAE1B,WAAO;AAAA,EACT;AACF;;;ACjCA,SAAS,eAAAG,cAAa,aAAAC,YAAW,WAAAC,UAAS,YAAAC,iBAAgB;AAOnD,SAAS,iBAAiB,UAAoB;AACnD,SAAO,SAAS,WAA+B,QAAmB,CAAC,GAAG,OAAuB,CAAC,GAAqB;AACjH,UAAM,CAAC,QAAQ,SAAS,IAAIA,UAA2B;AAAA,MACrD,MAAM,CAAC;AAAA,IACT,CAAC;AAED,UAAM,cAAcD,SAAQ,MAAM,KAAK,UAAU,IAAI,GAAG,CAAC,IAAI,CAAC;AAE9D,UAAM,cAAcF,aAAY,YAAY;AAC1C,YAAM,MAAM,MAAM,SAAS,QAAW,OAAO,IAAI;AACjD,gBAAU,EAAE,GAAG,KAAK,MAAM,IAAI,KAAK,IAAI,CAAC,MAAM,EAAE,KAAqB,EAAE,CAAC;AAAA,IAC1E,GAAG,CAAC,OAAO,WAAW,CAAC;AAEvB,IAAAC,WAAU,MAAM;AACd,kBAAY;AACZ,aAAO,SAAS,UAAU,WAAW;AAAA,IACvC,GAAG,CAAC,WAAW,CAAC;AAEhB,WAAO;AAAA,EACT;AACF;;;ALfO,IAAM,eAAe,CAAC;AAgBtB,SAAS,aAAa,OAA0B,gBAAgB,SAAqB,CAAC,GAAiB;AAE5G,SAAOG,SAAQ,MAAM;AACnB,UAAM,WAAW,OAAO,SAAS,WAAW,UAAU,MAAM,MAAM,IAAI;AAEtE,UAAM,cAAc,kBAAkB,QAAQ;AAC9C,UAAM,eAAe,mBAAmB,QAAQ;AAChD,UAAM,aAAa,iBAAiB,QAAQ;AAC5C,UAAM,aAAa,iBAAiB,QAAQ;AAE5C,WAAO,EAAE,UAAU,cAAc,aAAa,YAAY,WAAW;AAAA,EACvE,GAAG,CAAC,MAAM,KAAK,UAAU,MAAM,CAAC,CAAC;AACnC;;;AMvCA,OAAO,SAAS,YAAAC,WAAU,aAAAC,kBAAoC;AAE9D,IAAM,EAAE,IAAI,IAAI;AAehB,SAAS,OAAO,KAA4B;AAC1C,SAAO,UAAU,OAAO,UAAU,OAAO,YAAY,OAAO,OAAO,IAAI,WAAW;AACpF;AAGA,SAAS,WAAW,KAAmC;AACrD,SAAO,UAAU,OAAO,UAAU,OAAO,UAAU,OAAO,OAAO,IAAI,SAAS;AAChF;AAEO,SAAS,QAAQ,EAAE,MAAM,MAAM,GAAG,SAAS,GAAiB;AACjE,QAAM,CAAC,YAAY,aAAa,IAAID,UAAS,EAAE;AAG/C,QAAM,WAAW,QAAQ;AAEzB,EAAAC,WAAU,MAAM;AACd,QAAI,CAAC,SAAU;AAEf,UAAM,WAAW,YAAY;AAC3B,UAAI,UAAuB;AAC3B,UAAI,WAAW;AAEf,cAAQ,MAAM;AAAA,QACZ,KAAK,OAAO,QAAQ;AAClB,oBAAU;AACV,qBAAW,SAAS;AACpB;AAAA,QACF,KAAK,WAAW,QAAQ;AACtB,qBAAW,SAAS;AACpB,oBAAW,MAAM,SAAS,OAAO,KAAM;AACvC;AAAA,MACJ;AAEA,UAAI,WAAW,QAAQ,KAAK,QAAQ,GAAG;AACrC,cAAM,MAAM,IAAI,gBAAgB,OAAO;AACvC,sBAAc,GAAG;AACjB,eAAO,MAAM,IAAI,gBAAgB,GAAG;AAAA,MACtC;AAAA,IACF;AAEA,QAAI,YAAY;AAChB,QAAI;AAEJ,aAAS,EAAE,KAAK,CAAC,WAAW;AAC1B,UAAI,WAAW;AACb,kBAAU;AAAA,MACZ,WAAW,QAAQ;AACjB,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,WAAO,MAAM;AACX,kBAAY;AACZ,UAAI,QAAS,SAAQ;AAAA,IACvB;AAAA,EACF,GAAG,CAAC,QAAQ,CAAC;AAEb,SAAO,aACH,MAAM,cAAc,OAAO;AAAA,IACzB,KAAK;AAAA,IACL,GAAG;AAAA,EACL,CAAC,IACD;AACN;","names":["useMemo","useCallback","useEffect","useMemo","useState","useCallback","useEffect","useMemo","useState","useCallback","useEffect","useMemo","useState","useMemo","useState","useEffect"]}
|
1
|
+
{"version":3,"sources":["../../../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":["import type { ConfigOpts, Database } from \"@fireproof/core\";\nimport { fireproof } from \"@fireproof/core\";\nimport { useMemo } from \"react\";\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 *\n */\nexport function useFireproof(name: string | Database = \"useFireproof\", config: ConfigOpts = {}): UseFireproof {\n // Use useMemo to ensure stable references across renders\n return useMemo(() => {\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 }, [name, JSON.stringify(config)]); // Only recreate if name or stringified config changes\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 return function useDocument<T extends DocTypes>(initialDocOrFn?: UseDocumentInitialDocOrFn<T>): UseDocumentResult<T> {\n const updateHappenedRef = useRef(false);\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 if (doc._id) {\n try {\n const gotDoc = await database.get<T>(doc._id);\n setDoc(gotDoc);\n } catch {\n setDoc(initialDoc);\n }\n } else {\n setDoc(initialDoc);\n }\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 docs: initialRows.map((r) => r.doc).filter((r): r is DocWithId<T> => !!r),\n rows: initialRows,\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 setResult({\n docs: res.rows.map((r) => r.doc).filter((r): r is DocWithId<T> => !!r),\n rows: res.rows,\n });\n }, [database, mapFnString, queryString]);\n\n useEffect(() => {\n refreshRows();\n const unsubscribe = database.subscribe(refreshRows);\n return () => {\n unsubscribe();\n };\n }, [database, 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({\n ...res,\n docs: res.rows.map((r) => r.value as DocWithId<T>),\n });\n }, [database, queryString]);\n\n useEffect(() => {\n refreshRows();\n const unsubscribe = database.subscribe(refreshRows);\n return () => {\n unsubscribe();\n };\n }, [database, 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":["useMemo","useCallback","useEffect","useMemo","useState","useCallback","useEffect","useMemo","useState","useCallback","useEffect","useMemo","useState","useMemo","useState","useEffect"]}
|
package/react/metafile-cjs.json
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"inputs":{"src/react/utils.ts":{"bytes":156,"imports":[],"format":"esm"},"src/react/use-document.ts":{"bytes":
|
1
|
+
{"inputs":{"src/react/utils.ts":{"bytes":156,"imports":[],"format":"esm"},"src/react/use-document.ts":{"bytes":4064,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/react/utils.ts","kind":"import-statement","original":"./utils.js"}],"format":"esm"},"src/react/use-live-query.ts":{"bytes":1403,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/react/use-all-docs.ts":{"bytes":1021,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/react/use-changes.ts":{"bytes":974,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/react/use-fireproof.ts":{"bytes":1719,"imports":[{"path":"@fireproof/core","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/react/use-document.ts","kind":"import-statement","original":"./use-document.js"},{"path":"src/react/use-live-query.ts","kind":"import-statement","original":"./use-live-query.js"},{"path":"src/react/use-all-docs.ts","kind":"import-statement","original":"./use-all-docs.js"},{"path":"src/react/use-changes.ts","kind":"import-statement","original":"./use-changes.js"}],"format":"esm"},"src/react/types.ts":{"bytes":2407,"imports":[],"format":"esm"},"src/react/img-file.ts":{"bytes":2248,"imports":[{"path":"@fireproof/core","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/react/index.ts":{"bytes":124,"imports":[{"path":"src/react/use-fireproof.ts","kind":"import-statement","original":"./use-fireproof.js"},{"path":"src/react/types.ts","kind":"import-statement","original":"./types.js"},{"path":"src/react/img-file.ts","kind":"import-statement","original":"./img-file.js"}],"format":"esm"}},"outputs":{"dist/fireproof-core/react/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":18726},"dist/fireproof-core/react/index.cjs":{"imports":[{"path":"@fireproof/core","kind":"require-call","external":true},{"path":"react","kind":"require-call","external":true},{"path":"react","kind":"require-call","external":true},{"path":"react","kind":"require-call","external":true},{"path":"react","kind":"require-call","external":true},{"path":"react","kind":"require-call","external":true},{"path":"react","kind":"require-call","external":true}],"exports":[],"entryPoint":"src/react/index.ts","inputs":{"src/react/index.ts":{"bytesInOutput":197},"src/react/use-fireproof.ts":{"bytesInOutput":634},"src/react/use-document.ts":{"bytesInOutput":3565},"src/react/utils.ts":{"bytesInOutput":107},"src/react/use-live-query.ts":{"bytesInOutput":993},"src/react/use-all-docs.ts":{"bytesInOutput":765},"src/react/use-changes.ts":{"bytesInOutput":679},"src/react/img-file.ts":{"bytesInOutput":1499}},"bytes":10120}}}
|
package/react/metafile-esm.json
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"inputs":{"src/react/utils.ts":{"bytes":156,"imports":[],"format":"esm"},"src/react/use-document.ts":{"bytes":
|
1
|
+
{"inputs":{"src/react/utils.ts":{"bytes":156,"imports":[],"format":"esm"},"src/react/use-document.ts":{"bytes":4064,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/react/utils.ts","kind":"import-statement","original":"./utils.js"}],"format":"esm"},"src/react/use-live-query.ts":{"bytes":1403,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/react/use-all-docs.ts":{"bytes":1021,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/react/use-changes.ts":{"bytes":974,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/react/use-fireproof.ts":{"bytes":1719,"imports":[{"path":"@fireproof/core","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/react/use-document.ts","kind":"import-statement","original":"./use-document.js"},{"path":"src/react/use-live-query.ts","kind":"import-statement","original":"./use-live-query.js"},{"path":"src/react/use-all-docs.ts","kind":"import-statement","original":"./use-all-docs.js"},{"path":"src/react/use-changes.ts","kind":"import-statement","original":"./use-changes.js"}],"format":"esm"},"src/react/types.ts":{"bytes":2407,"imports":[],"format":"esm"},"src/react/img-file.ts":{"bytes":2248,"imports":[{"path":"@fireproof/core","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/react/index.ts":{"bytes":124,"imports":[{"path":"src/react/use-fireproof.ts","kind":"import-statement","original":"./use-fireproof.js"},{"path":"src/react/types.ts","kind":"import-statement","original":"./types.js"},{"path":"src/react/img-file.ts","kind":"import-statement","original":"./img-file.js"}],"format":"esm"}},"outputs":{"dist/fireproof-core/react/index.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":18766},"dist/fireproof-core/react/index.js":{"imports":[{"path":"@fireproof/core","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true}],"exports":["FireproofCtx","ImgFile","useFireproof"],"entryPoint":"src/react/index.ts","inputs":{"src/react/use-fireproof.ts":{"bytesInOutput":605},"src/react/use-document.ts":{"bytesInOutput":3369},"src/react/utils.ts":{"bytesInOutput":107},"src/react/use-live-query.ts":{"bytesInOutput":987},"src/react/use-all-docs.ts":{"bytesInOutput":777},"src/react/use-changes.ts":{"bytesInOutput":691},"src/react/index.ts":{"bytesInOutput":0},"src/react/img-file.ts":{"bytesInOutput":1476}},"bytes":8327}}}
|
@@ -0,0 +1,113 @@
|
|
1
|
+
import { renderHook, waitFor } from "@testing-library/react";
|
2
|
+
import { describe, expect, it, beforeEach, afterEach } from "vitest";
|
3
|
+
import { fireproof, useFireproof } from "use-fireproof";
|
4
|
+
import type { Database, UseDocumentResult } from "use-fireproof";
|
5
|
+
|
6
|
+
const TEST_TIMEOUT = 45000;
|
7
|
+
|
8
|
+
// Define a type for user settings
|
9
|
+
interface TestTypeDoc {
|
10
|
+
_id?: string;
|
11
|
+
testField?: string;
|
12
|
+
theme?: string;
|
13
|
+
notifications?: boolean;
|
14
|
+
language?: string;
|
15
|
+
}
|
16
|
+
|
17
|
+
describe("HOOK: useDocument with non-existent ID", () => {
|
18
|
+
const dbName = "useDocumentWithNonExistentId";
|
19
|
+
let db: Database;
|
20
|
+
let settingsResult: UseDocumentResult<TestTypeDoc>;
|
21
|
+
let database: ReturnType<typeof useFireproof>["database"];
|
22
|
+
let useDocument: ReturnType<typeof useFireproof>["useDocument"];
|
23
|
+
const testId = "test_settings";
|
24
|
+
|
25
|
+
beforeEach(async () => {
|
26
|
+
db = fireproof(dbName);
|
27
|
+
|
28
|
+
// Make sure the document doesn't exist
|
29
|
+
try {
|
30
|
+
const doc = await db.get(testId);
|
31
|
+
if (doc) {
|
32
|
+
// Use put with _deleted flag instead of delete
|
33
|
+
await db.put({ _id: testId, _deleted: true });
|
34
|
+
}
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
36
|
+
} catch (_) {
|
37
|
+
// Document doesn't exist, which is what we want
|
38
|
+
}
|
39
|
+
|
40
|
+
renderHook(() => {
|
41
|
+
const result = useFireproof(dbName);
|
42
|
+
database = result.database;
|
43
|
+
useDocument = result.useDocument;
|
44
|
+
settingsResult = useDocument<TestTypeDoc>({ _id: testId, testField: "test" });
|
45
|
+
});
|
46
|
+
});
|
47
|
+
|
48
|
+
it(
|
49
|
+
"should initialize with the provided _id even if document doesn't exist",
|
50
|
+
async () => {
|
51
|
+
// eslint-disable-next-line no-console
|
52
|
+
console.log("Initial document state:", JSON.stringify(settingsResult.doc));
|
53
|
+
// eslint-disable-next-line no-console
|
54
|
+
console.log("Document state properties:", Object.keys(settingsResult));
|
55
|
+
|
56
|
+
// Try to refresh the document to see if we get the error
|
57
|
+
try {
|
58
|
+
// eslint-disable-next-line no-console
|
59
|
+
console.log("Attempting to refresh document...");
|
60
|
+
await settingsResult.refresh();
|
61
|
+
} catch (error) {
|
62
|
+
// eslint-disable-next-line no-console
|
63
|
+
console.log("Error during refresh:", error);
|
64
|
+
}
|
65
|
+
|
66
|
+
await waitFor(() => {
|
67
|
+
// eslint-disable-next-line no-console
|
68
|
+
console.log("After waitFor - document state:", JSON.stringify(settingsResult.doc));
|
69
|
+
// eslint-disable-next-line no-console
|
70
|
+
console.log("After waitFor - document state properties:", Object.keys(settingsResult));
|
71
|
+
|
72
|
+
expect(settingsResult.doc._id).toBe(testId);
|
73
|
+
expect(settingsResult.doc.testField).toBe("test");
|
74
|
+
// Other properties should be undefined
|
75
|
+
expect(settingsResult.doc.theme).toBeUndefined();
|
76
|
+
expect(settingsResult.doc.notifications).toBeUndefined();
|
77
|
+
expect(settingsResult.doc.language).toBeUndefined();
|
78
|
+
});
|
79
|
+
|
80
|
+
// Try to get the document directly from the database
|
81
|
+
try {
|
82
|
+
// eslint-disable-next-line no-console
|
83
|
+
console.log("Attempting to get document from DB...");
|
84
|
+
const docFromDb = await db.get(testId);
|
85
|
+
// eslint-disable-next-line no-console
|
86
|
+
console.log("Document from DB:", docFromDb);
|
87
|
+
} catch (error) {
|
88
|
+
// eslint-disable-next-line no-console
|
89
|
+
console.log("Error getting document from DB:", error);
|
90
|
+
}
|
91
|
+
|
92
|
+
// Try to save the document and see what happens
|
93
|
+
try {
|
94
|
+
// eslint-disable-next-line no-console
|
95
|
+
console.log("Attempting to save document...");
|
96
|
+
await settingsResult.save();
|
97
|
+
// eslint-disable-next-line no-console
|
98
|
+
console.log("Document saved successfully");
|
99
|
+
} catch (error) {
|
100
|
+
// eslint-disable-next-line no-console
|
101
|
+
console.log("Error saving document:", error);
|
102
|
+
}
|
103
|
+
},
|
104
|
+
TEST_TIMEOUT,
|
105
|
+
);
|
106
|
+
|
107
|
+
afterEach(async () => {
|
108
|
+
await db.close();
|
109
|
+
await db.destroy();
|
110
|
+
await database?.close();
|
111
|
+
await database?.destroy();
|
112
|
+
});
|
113
|
+
});
|