@powerhousedao/reactor-browser 6.1.0-dev.0 → 6.1.0-dev.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{index-Ce4S7Kk1.d.ts → index-ZltD7u5Z.d.ts} +2 -2
- package/dist/{index-Ce4S7Kk1.d.ts.map → index-ZltD7u5Z.d.ts.map} +1 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +59 -10
- package/dist/index.js.map +1 -1
- package/dist/{relational-jwreqDwz.js → relational-4_LVwp8p.js} +2 -2
- package/dist/relational-4_LVwp8p.js.map +1 -0
- package/dist/src/analytics/index.d.ts +1 -1
- package/dist/src/analytics/index.js +1 -1
- package/dist/src/analytics/index.js.map +1 -1
- package/dist/src/relational/index.d.ts +1 -1
- package/dist/src/relational/index.js +1 -1
- package/package.json +9 -9
- package/dist/relational-jwreqDwz.js.map +0 -1
|
@@ -49,7 +49,7 @@ const isRelationNotExistError = (error) => {
|
|
|
49
49
|
const errorMessage = error instanceof Error ? error.message : typeof error === "string" ? error : String(error);
|
|
50
50
|
return errorMessage.toLowerCase().includes("relation") && errorMessage.toLowerCase().includes("does not exist");
|
|
51
51
|
};
|
|
52
|
-
function useRelationalQuery(ProcessorClass, driveId, queryCallback, parameters,
|
|
52
|
+
function useRelationalQuery(ProcessorClass, driveId, queryCallback, parameters, _options) {
|
|
53
53
|
const [result, setResult] = useState(null);
|
|
54
54
|
const [queryLoading, setQueryLoading] = useState(true);
|
|
55
55
|
const [error, setError] = useState(void 0);
|
|
@@ -120,4 +120,4 @@ function createProcessorQuery(ProcessorClass) {
|
|
|
120
120
|
//#endregion
|
|
121
121
|
export { useRelationalQuery as n, useRelationalDb as r, createProcessorQuery as t };
|
|
122
122
|
|
|
123
|
-
//# sourceMappingURL=relational-
|
|
123
|
+
//# sourceMappingURL=relational-4_LVwp8p.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relational-4_LVwp8p.js","names":[],"sources":["../src/pglite/usePGlite.ts","../src/relational/hooks/useRelationalDb.ts","../src/relational/hooks/useRelationalQuery.ts","../src/relational/utils/createProcessorQuery.ts"],"sourcesContent":["import type { PGliteWithLive } from \"@electric-sql/pglite/live\";\nimport { useEffect, useState } from \"react\";\n\nexport const PGLITE_UPDATE_EVENT = \"ph:pglite-update\";\n\nexport interface PGliteState {\n db: PGliteWithLive | null;\n isLoading: boolean;\n error: Error | null;\n}\n\nconst defaultPGliteState: PGliteState = {\n db: null,\n isLoading: true,\n error: null,\n};\n\nexport const usePGliteDB = () => {\n const [state, setState] = useState<PGliteState>(\n () => window.powerhouse?.pglite ?? defaultPGliteState,\n );\n\n useEffect(() => {\n const handlePgliteUpdate = () =>\n setState(window.powerhouse?.pglite ?? defaultPGliteState);\n\n window.addEventListener(PGLITE_UPDATE_EVENT, handlePgliteUpdate);\n\n return () =>\n window.removeEventListener(PGLITE_UPDATE_EVENT, handlePgliteUpdate);\n }, []);\n\n return state;\n};\n\nexport const useSetPGliteDB = () => {\n const setPGliteState = (pglite: Partial<PGliteState>) => {\n const currentPowerhouse = window.powerhouse ?? {};\n const currentPGliteState = window.powerhouse?.pglite ?? defaultPGliteState;\n\n window.powerhouse = {\n ...currentPowerhouse,\n pglite: {\n ...currentPGliteState,\n ...pglite,\n },\n };\n window.dispatchEvent(new CustomEvent(PGLITE_UPDATE_EVENT));\n };\n\n return setPGliteState;\n};\n\nexport const usePGlite = () => {\n const pglite = usePGliteDB();\n const setPGlite = useSetPGliteDB();\n\n return [pglite, setPGlite];\n};\n","import type { PGlite } from \"@electric-sql/pglite\";\nimport type { LiveNamespace, PGliteWithLive } from \"@electric-sql/pglite/live\";\nimport { createRelationalDb } from \"@powerhousedao/reactor\";\nimport type { IRelationalDb as IRelationalDbCore } from \"@powerhousedao/shared/processors\";\nimport { Kysely } from \"kysely\";\nimport { PGliteDialect } from \"kysely-pglite-dialect\";\nimport { useMemo } from \"react\";\nimport { usePGliteDB } from \"../../pglite/usePGlite.js\";\n\n// Type for Relational DB instance enhanced with live capabilities\nexport type RelationalDbWithLive<Schema> = IRelationalDbCore<Schema> & {\n live: LiveNamespace;\n};\n\ninterface IRelationalDbState<Schema> {\n db: RelationalDbWithLive<Schema> | null;\n isLoading: boolean;\n error: Error | null;\n}\n\n// Custom initializer that creates enhanced Kysely instance with live capabilities\nfunction createRelationalDbWithLive<Schema>(\n pgliteInstance: PGliteWithLive,\n): RelationalDbWithLive<Schema> {\n const baseDb = new Kysely<Schema>({\n dialect: new PGliteDialect(pgliteInstance as unknown as PGlite),\n });\n const relationalDb = createRelationalDb(baseDb);\n\n // Inject the live namespace with proper typing\n const relationalDBWithLive =\n relationalDb as unknown as RelationalDbWithLive<Schema>;\n relationalDBWithLive.live = pgliteInstance.live;\n\n return relationalDBWithLive;\n}\n\nexport const useRelationalDb = <Schema>(): IRelationalDbState<Schema> => {\n const pglite = usePGliteDB();\n\n const relationalDb = useMemo<IRelationalDbState<Schema>>(() => {\n if (!pglite.db || pglite.isLoading || pglite.error) {\n return {\n db: null,\n isLoading: pglite.isLoading,\n error: pglite.error,\n };\n }\n\n const db = createRelationalDbWithLive<Schema>(pglite.db);\n\n return {\n db,\n isLoading: false,\n error: null,\n };\n }, [pglite]);\n\n return relationalDb;\n};\n","import type { LiveQueryResults } from \"@electric-sql/pglite/live\";\nimport type {\n IRelationalQueryBuilder,\n RelationalDbProcessorClass,\n} from \"@powerhousedao/shared/processors\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { useRelationalDb } from \"./useRelationalDb.js\";\n\nexport type QueryCallbackReturnType = {\n sql: string;\n parameters?: readonly unknown[];\n};\n\nexport type useRelationalQueryOptions = {\n // Whether to hash the namespace to avoid namespace size limit. True by default\n hashNamespace?: boolean;\n};\n\nconst MAX_RETRIES = 5;\nconst RETRY_DELAY = 200;\n\nconst isRelationNotExistError = (error: unknown): boolean => {\n const errorMessage =\n error instanceof Error\n ? error.message\n : typeof error === \"string\"\n ? error\n : String(error);\n\n return (\n errorMessage.toLowerCase().includes(\"relation\") &&\n errorMessage.toLowerCase().includes(\"does not exist\")\n );\n};\n\ntype LiveQueryType = {\n unsubscribe: () => void;\n};\n\nexport function useRelationalQuery<Schema, T = unknown, TParams = undefined>(\n ProcessorClass: RelationalDbProcessorClass<Schema>,\n driveId: string,\n queryCallback: (\n db: IRelationalQueryBuilder<Schema>,\n parameters?: TParams,\n ) => QueryCallbackReturnType,\n parameters?: TParams,\n _options?: useRelationalQueryOptions,\n) {\n const [result, setResult] = useState<LiveQueryResults<T> | null>(null);\n const [queryLoading, setQueryLoading] = useState(true);\n const [error, setError] = useState<Error | undefined>(undefined);\n const retryCount = useRef(0);\n const retryTimeoutRef = useRef<NodeJS.Timeout>(null);\n\n const relationalDb = useRelationalDb<Schema>();\n\n const executeLiveQuery = async (\n sql: string,\n queryParameters: readonly unknown[] | undefined,\n retryAttempt = 0,\n ): Promise<LiveQueryType | null> => {\n if (!relationalDb.db) {\n return null;\n }\n\n try {\n const live = await relationalDb.db.live.query<T>(\n sql,\n queryParameters ? [...queryParameters] : [],\n (result) => {\n setResult(result);\n setQueryLoading(false);\n retryCount.current = 0; // Reset retry count on success\n },\n );\n\n return live as LiveQueryType;\n } catch (err: unknown) {\n if (isRelationNotExistError(err) && retryAttempt < MAX_RETRIES) {\n return new Promise((resolve) => {\n retryTimeoutRef.current = setTimeout(() => {\n resolve(executeLiveQuery(sql, queryParameters, retryAttempt + 1));\n }, RETRY_DELAY);\n });\n }\n\n setQueryLoading(false);\n setError(err instanceof Error ? err : new Error(String(err)));\n return null;\n }\n };\n\n useEffect(() => {\n setError(undefined);\n setQueryLoading(true);\n retryCount.current = 0;\n\n if (!relationalDb.db) {\n return;\n }\n\n // Use the processor helper to obtain a typed namespaced query builder\n const db = ProcessorClass.query(driveId, relationalDb.db);\n\n const compiledQuery = queryCallback(db, parameters);\n const { sql, parameters: queryParameters } = compiledQuery;\n\n const liveQueryPromise = executeLiveQuery(sql, queryParameters);\n\n return () => {\n if (retryTimeoutRef.current) {\n clearTimeout(retryTimeoutRef.current);\n }\n void liveQueryPromise.then((live) => {\n if (live?.unsubscribe) {\n live.unsubscribe();\n }\n });\n };\n }, [relationalDb.db, ProcessorClass, driveId, queryCallback, parameters]);\n\n return {\n isLoading: relationalDb.isLoading || queryLoading,\n error: error || relationalDb.error,\n result,\n } as const;\n}\n","import type { LiveQueryResults } from \"@electric-sql/pglite/live\";\nimport type {\n QueryCallbackReturnType,\n useRelationalQueryOptions,\n} from \"@powerhousedao/reactor-browser\";\nimport type {\n IRelationalQueryBuilder,\n RelationalDbProcessorClass,\n} from \"@powerhousedao/shared/processors\";\nimport type { CompiledQuery } from \"kysely\";\nimport deepEqual from \"lodash.isequal\";\nimport { useCallback, useMemo, useRef } from \"react\";\nimport { useRelationalQuery } from \"../hooks/useRelationalQuery.js\";\n\n// Custom hook for parameter memoization\nfunction useStableParams<T>(params: T): T {\n const prevParamsRef = useRef<T>(null);\n\n return useMemo(() => {\n if (!deepEqual(prevParamsRef.current, params)) {\n prevParamsRef.current = params;\n }\n return prevParamsRef.current as T;\n }, [params]);\n}\n\nexport function createProcessorQuery<TSchema>(\n ProcessorClass: RelationalDbProcessorClass<TSchema>,\n) {\n // Overload for queries without parameters\n function useQuery<\n TQueryBuilder extends (\n db: IRelationalQueryBuilder<TSchema>,\n ) => QueryCallbackReturnType,\n >(\n driveId: string,\n queryCallback: TQueryBuilder,\n ): {\n isLoading: boolean;\n error: Error | null;\n result: LiveQueryResults<\n ReturnType<TQueryBuilder> extends CompiledQuery<infer R> ? R : any\n > | null;\n };\n\n // Overload for queries with parameters\n function useQuery<\n TParams,\n TQueryBuilder extends (\n db: IRelationalQueryBuilder<TSchema>,\n parameters: TParams,\n ) => QueryCallbackReturnType,\n >(\n driveId: string,\n queryCallback: TQueryBuilder,\n parameters: TParams,\n options?: useRelationalQueryOptions,\n ): {\n isLoading: boolean;\n error: Error | null;\n result: LiveQueryResults<\n ReturnType<TQueryBuilder> extends CompiledQuery<infer R> ? R : any\n > | null;\n };\n\n function useQuery<\n TParams,\n TQueryBuilder extends (\n db: IRelationalQueryBuilder<TSchema>,\n parameters?: TParams,\n ) => QueryCallbackReturnType,\n >(\n driveId: string,\n queryCallback: TQueryBuilder,\n parameters?: TParams,\n options?: useRelationalQueryOptions,\n ): {\n isLoading: boolean;\n error: Error | null;\n result: LiveQueryResults<\n ReturnType<TQueryBuilder> extends CompiledQuery<infer R> ? R : any\n > | null;\n } {\n type InferredResult =\n ReturnType<TQueryBuilder> extends CompiledQuery<infer R> ? R : any;\n\n // Automatically memoize parameters using deep comparison\n const stableParams = useStableParams(parameters);\n\n // Memoize the callback to prevent infinite loops, updating when parameters change\n const memoizedCallback = useCallback(queryCallback, [stableParams]);\n\n return useRelationalQuery<TSchema, InferredResult, TParams>(\n ProcessorClass,\n driveId,\n memoizedCallback,\n stableParams,\n options,\n ) as {\n isLoading: boolean;\n error: Error | null;\n result: LiveQueryResults<InferredResult> | null;\n };\n }\n\n return useQuery;\n}\n"],"mappings":"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"}
|
|
@@ -31,7 +31,7 @@ type AnalyticsProviderProps = BaseAnalyticsProviderProps & ({
|
|
|
31
31
|
declare function AnalyticsProvider({
|
|
32
32
|
children,
|
|
33
33
|
queryClient,
|
|
34
|
-
...
|
|
34
|
+
..._props
|
|
35
35
|
}: AnalyticsProviderProps): react_jsx_runtime0.JSX.Element;
|
|
36
36
|
declare function useAnalyticsEngine(): AnalyticsQueryEngine | undefined;
|
|
37
37
|
declare function useAnalyticsEngineAsync(): _tanstack_react_query0.UseQueryResult<AnalyticsQueryEngine, Error>;
|
|
@@ -62,7 +62,7 @@ function CreateAnalyticsStore() {
|
|
|
62
62
|
}, []);
|
|
63
63
|
return null;
|
|
64
64
|
}
|
|
65
|
-
function AnalyticsProvider({ children, queryClient = defaultQueryClient, ...
|
|
65
|
+
function AnalyticsProvider({ children, queryClient = defaultQueryClient, ..._props }) {
|
|
66
66
|
return /* @__PURE__ */ jsxs(QueryClientProvider, {
|
|
67
67
|
client: queryClient,
|
|
68
68
|
children: [/* @__PURE__ */ jsx(CreateAnalyticsStore, {}), children]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/analytics/context.tsx","../../../src/analytics/hooks/analytics-query.ts","../../../src/analytics/hooks/timeline-items.ts","../../../src/analytics/hooks/document-timeline.ts"],"sourcesContent":["import type { AnalyticsQueryEngine } from \"@powerhousedao/analytics-engine-core\";\nimport {\n QueryClient,\n QueryClientProvider,\n useMutation,\n useQuery,\n useQueryClient,\n useSuspenseQuery,\n} from \"@tanstack/react-query\";\nimport { childLogger } from \"document-model\";\nimport type { PropsWithChildren } from \"react\";\nimport { useEffect } from \"react\";\nimport { getGlobal } from \"../global/core.js\";\nimport type { CreateStoreOptions } from \"./store.js\";\nimport { getAnalyticsStore } from \"./store.js\";\n\nconst logger = childLogger([\"reactor-browser\", \"analytics\", \"provider\"]);\n\nconst defaultQueryClient = new QueryClient();\n\nexport const analyticsOptionsKey = [\"analytics\", \"options\"] as const;\nexport const analyticsStoreKey = [\"analytics\", \"store\"] as const;\nexport const analyticsEngineKey = [\"analytics\", \"engine\"] as const;\n\nexport function useAnalyticsStoreOptions() {\n return useQuery<CreateStoreOptions | undefined>({\n queryKey: analyticsOptionsKey,\n }).data;\n}\n\nexport function useCreateAnalyticsStore(options?: CreateStoreOptions) {\n const queryClient = useQueryClient();\n useEffect(() => {\n queryClient.setQueryDefaults(analyticsOptionsKey, {\n queryFn: () => options,\n staleTime: Infinity,\n gcTime: Infinity,\n });\n }, [queryClient, options]);\n\n return useMutation({\n mutationFn: async () => {\n const store = getAnalyticsStore();\n queryClient.setQueryDefaults(analyticsStoreKey, {\n queryFn: () => store,\n staleTime: Infinity,\n gcTime: Infinity,\n });\n return store;\n },\n });\n}\n\nexport function useAnalyticsStoreQuery(options?: CreateStoreOptions) {\n return useSuspenseQuery({\n queryKey: [analyticsStoreKey, options],\n queryFn: () => getAnalyticsStore(),\n retry: true,\n });\n}\n\nexport function useAnalyticsStore(options?: CreateStoreOptions) {\n const store = useAnalyticsStoreQuery(options);\n return store.data;\n}\n\nexport function useAnalyticsStoreAsync(options?: CreateStoreOptions) {\n return useQuery({\n queryKey: [analyticsStoreKey, options],\n queryFn: () => getAnalyticsStore(),\n retry: true,\n throwOnError: false,\n });\n}\n\ninterface BaseAnalyticsProviderProps extends PropsWithChildren {\n /**\n * Custom QueryClient instance\n * @default undefined\n */\n queryClient?: QueryClient;\n}\n\ntype AnalyticsProviderProps = BaseAnalyticsProviderProps &\n (\n | {\n options?: CreateStoreOptions;\n }\n | {\n databaseName?: string;\n }\n );\n\nfunction CreateAnalyticsStore() {\n const { mutate } = useCreateAnalyticsStore();\n\n useEffect(() => {\n mutate();\n }, []);\n\n return null;\n}\n\nexport function AnalyticsProvider({\n children,\n queryClient = defaultQueryClient,\n ...props\n}: AnalyticsProviderProps) {\n return (\n <QueryClientProvider client={queryClient}>\n <CreateAnalyticsStore />\n {children}\n </QueryClientProvider>\n );\n}\n\nexport function useAnalyticsEngine(): AnalyticsQueryEngine | undefined {\n return useSuspenseQuery({\n queryKey: analyticsEngineKey,\n queryFn: async () => {\n const globalAnalytics = getGlobal(\"analytics\");\n if (!globalAnalytics) {\n throw new Error(\"No analytics store available\");\n }\n return (await globalAnalytics).engine;\n },\n retry: false,\n }).data;\n}\n\nexport function useAnalyticsEngineAsync() {\n return useQuery({\n queryKey: analyticsEngineKey,\n queryFn: async () => {\n const globalAnalytics = getGlobal(\"analytics\");\n if (!globalAnalytics) {\n throw new Error(\"No analytics store available\");\n }\n return (await globalAnalytics).engine;\n },\n retry: false,\n });\n}\n","import type {\n AnalyticsQuery,\n AnalyticsQueryEngine,\n AnalyticsSeries,\n AnalyticsSeriesInput,\n AnalyticsSeriesQuery,\n GroupedPeriodResults,\n IAnalyticsStore,\n} from \"@powerhousedao/analytics-engine-core\";\nimport { AnalyticsPath } from \"@powerhousedao/analytics-engine-core\";\nimport type {\n UseMutationOptions,\n UseQueryOptions,\n UseQueryResult,\n} from \"@tanstack/react-query\";\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useEffect } from \"react\";\nimport {\n useAnalyticsEngineAsync,\n useAnalyticsStoreAsync,\n useAnalyticsStoreOptions,\n} from \"../context.js\";\nimport { getAnalyticsStore } from \"../store.js\";\n\nfunction useAnalyticsQueryWrapper<TQueryFnData = unknown, TData = TQueryFnData>(\n options: Omit<UseQueryOptions<TQueryFnData, Error, TData>, \"queryFn\"> & {\n queryFn: (analytics: {\n store: IAnalyticsStore;\n engine: AnalyticsQueryEngine;\n }) => Promise<TQueryFnData> | TQueryFnData;\n },\n) {\n const { queryFn, ...queryOptions } = options;\n const { data: store } = useAnalyticsStoreAsync();\n const { data: engine } = useAnalyticsEngineAsync();\n const enabled =\n \"enabled\" in queryOptions ? queryOptions.enabled : !!store && !!engine;\n\n return useQuery({\n ...queryOptions,\n enabled,\n queryFn: async () => {\n if (!store || !engine) {\n throw new Error(\n \"No analytics store available. Use within an AnalyticsProvider.\",\n );\n }\n return await queryFn({ store, engine });\n },\n });\n}\n\nfunction useAnalyticsMutationWrapper<TVariables, TData>(\n options: Omit<UseMutationOptions<TData, Error, TVariables>, \"mutationFn\"> & {\n mutationFn: (\n variables: TVariables,\n context: {\n store: IAnalyticsStore;\n },\n ) => Promise<TData> | TData;\n },\n) {\n const { mutationFn, ...mutationOptions } = options;\n const storeOptions = useAnalyticsStoreOptions();\n\n return useMutation({\n ...mutationOptions,\n mutationFn: async (value: TVariables) => {\n let store: IAnalyticsStore | null = null;\n try {\n store = await getAnalyticsStore();\n } catch (e) {\n console.error(e);\n }\n\n if (!store) {\n throw new Error(\n \"No analytics store available. Use within an AnalyticsProvider.\",\n );\n }\n return await mutationFn(value, { store });\n },\n });\n}\n\nexport type UseAnalyticsQueryOptions<TData = GroupedPeriodResults> = Omit<\n UseQueryOptions<GroupedPeriodResults, Error, TData>,\n \"queryKey\" | \"queryFn\"\n> & {\n sources?: AnalyticsPath[];\n};\n\nexport type UseAnalyticsQueryResult<TData = GroupedPeriodResults> =\n UseQueryResult<TData>;\n\nconst DEBOUNCE_INTERVAL = 200;\n\nexport function useAnalyticsQuery<TData = GroupedPeriodResults>(\n query: AnalyticsQuery,\n options?: UseAnalyticsQueryOptions<TData>,\n): UseAnalyticsQueryResult<TData> {\n const { data: store } = useAnalyticsStoreAsync();\n const queryClient = useQueryClient();\n const sources = options?.sources ?? [];\n\n const result = useAnalyticsQueryWrapper({\n queryKey: [\"analytics\", \"query\", query],\n queryFn: ({ engine }) => engine.execute(query),\n ...options,\n });\n\n useEffect(() => {\n if (!sources.length || !store) {\n return;\n }\n\n const subscriptions = new Array<() => void>();\n // Debounce invalidateQueries so it's not called too frequently\n let invalidateTimeout: ReturnType<typeof setTimeout> | null = null;\n const debouncedInvalidate = () => {\n if (invalidateTimeout) clearTimeout(invalidateTimeout);\n invalidateTimeout = setTimeout(() => {\n queryClient\n .invalidateQueries({\n queryKey: [\"analytics\", \"query\", query],\n })\n .catch((e) => {\n console.error(e);\n });\n }, DEBOUNCE_INTERVAL);\n };\n\n sources.forEach((path) => {\n const unsub = store.subscribeToSource(path, debouncedInvalidate);\n subscriptions.push(unsub);\n });\n\n // Unsubscribes from store when component unmounts or dependencies change\n return () => {\n subscriptions.forEach((unsub) => unsub());\n };\n }, [query, store, sources]);\n\n return result;\n}\n\nexport type UseAnalyticsSeriesOptions = Omit<\n UseQueryOptions<AnalyticsSeries[], Error, AnalyticsSeries[]>,\n \"queryKey\" | \"queryFn\"\n>;\n\nexport function useAnalyticsSeries(\n query: AnalyticsSeriesQuery,\n options?: UseAnalyticsSeriesOptions,\n) {\n return useAnalyticsQueryWrapper({\n queryKey: [\"analytics\", \"series\", query],\n queryFn: ({ store }) => store.getMatchingSeries(query),\n ...options,\n });\n}\n\nexport type UseAddSeriesValueOptions = Omit<\n UseMutationOptions<void, Error, AnalyticsSeriesInput>,\n \"mutationKey\" | \"mutationFn\"\n>;\n\nexport function useAddSeriesValue(options?: UseAddSeriesValueOptions) {\n return useAnalyticsMutationWrapper({\n mutationKey: [\"analytics\", \"addSeries\"],\n mutationFn: async (value, { store }) => {\n return await store.addSeriesValue(value);\n },\n ...options,\n });\n}\n\nexport type UseClearSeriesBySourceOptions = Omit<\n UseMutationOptions<\n number,\n Error,\n { source: AnalyticsPath; cleanUpDimensions?: boolean }\n >,\n \"mutationKey\" | \"mutationFn\"\n>;\n\nexport function useClearSeriesBySource(\n options?: UseClearSeriesBySourceOptions,\n) {\n return useAnalyticsMutationWrapper({\n mutationKey: [\"analytics\", \"clearSeries\"],\n mutationFn: async ({ source, cleanUpDimensions }, { store }) => {\n return store.clearSeriesBySource(source, cleanUpDimensions);\n },\n ...options,\n });\n}\n\nexport type UseClearEmptyAnalyticsDimensionsOptions = Omit<\n UseMutationOptions<number>,\n \"mutationKey\" | \"mutationFn\"\n>;\n\nexport function useClearEmptyAnalyticsDimensions(\n options?: UseClearEmptyAnalyticsDimensionsOptions,\n) {\n return useAnalyticsMutationWrapper({\n mutationKey: [\"analytics\", \"clearEmptyDimensions\"],\n mutationFn: async (_, { store }) => {\n return store.clearEmptyAnalyticsDimensions();\n },\n ...options,\n });\n}\n\nexport type UseAddSeriesValuesOptions = Omit<\n UseMutationOptions<void, Error, AnalyticsSeriesInput[]>,\n \"mutationKey\" | \"mutationFn\"\n>;\n\nexport function useAddSeriesValues(options?: UseAddSeriesValuesOptions) {\n return useAnalyticsMutationWrapper({\n mutationKey: [\"analytics\", \"addSeriesValues\"],\n mutationFn: async (values, { store }) => {\n return store.addSeriesValues(values);\n },\n ...options,\n });\n}\n\nexport type UseGetDimensionsOptions<TData> = Omit<\n UseQueryOptions<any, Error, TData>,\n \"queryKey\" | \"queryFn\"\n>;\n\nexport function useGetDimensions<TData = any>(\n options?: UseGetDimensionsOptions<TData>,\n) {\n return useAnalyticsQueryWrapper({\n queryKey: [\"analytics\", \"dimensions\"],\n queryFn: ({ store }) => store.getDimensions(),\n ...options,\n });\n}\n\nexport type UseMatchingSeriesOptions = Omit<\n UseQueryOptions<AnalyticsSeries[], Error, AnalyticsSeries[]>,\n \"queryKey\" | \"queryFn\"\n>;\n\nexport function useMatchingSeries(\n query: AnalyticsSeriesQuery,\n options?: UseMatchingSeriesOptions,\n) {\n const result = useAnalyticsQueryWrapper({\n queryKey: [\"analytics\", \"matchingSeries\", query],\n queryFn: ({ store }) => store.getMatchingSeries(query),\n ...options,\n });\n\n return result;\n}\n\nexport type UseQuerySourcesOptions = Omit<\n UseQueryOptions<AnalyticsPath[] | undefined>,\n \"queryKey\" | \"queryFn\"\n>;\n\nexport function useQuerySources(\n query: AnalyticsSeriesQuery,\n options?: UseQuerySourcesOptions,\n) {\n const { data: matchingSeries } = useMatchingSeries(query);\n\n return useQuery({\n queryKey: [\"analytics\", \"sources\", query],\n queryFn: () => {\n if (!matchingSeries?.length) {\n return [];\n }\n const uniqueSources = [\n ...new Set(matchingSeries.map((s) => s.source.toString())),\n ];\n return uniqueSources.map((source) => AnalyticsPath.fromString(source));\n },\n enabled: !!matchingSeries,\n ...options,\n });\n}\n","import type { GroupedPeriodResults } from \"@powerhousedao/analytics-engine-core\";\nimport {\n AnalyticsGranularity,\n AnalyticsPath,\n} from \"@powerhousedao/analytics-engine-core\";\nimport { DateTime } from \"luxon\";\nimport type { UseAnalyticsQueryResult } from \"./analytics-query.js\";\nimport { useAnalyticsQuery } from \"./analytics-query.js\";\n\nconst getBarSize = (value: number) => {\n if (value <= 0) return 0;\n if (value > 0 && value <= 50) return 1;\n if (value > 50 && value <= 100) return 2;\n if (value > 100 && value <= 250) return 3;\n return 4;\n};\n\n// Define types for our timeline items\ntype BarItem = {\n id: string;\n type: \"bar\";\n addSize: 0 | 1 | 2 | 3 | 4;\n delSize: 0 | 1 | 2 | 3 | 4;\n additions: number;\n deletions: number;\n timestampUtcMs: string;\n startDate: Date;\n endDate: Date;\n revision?: number;\n};\n\ntype DividerItem = {\n id: string;\n type: \"divider\";\n revision?: number;\n startDate?: Date;\n endDate?: Date;\n};\n\ntype TimelineItem = BarItem | DividerItem;\n\nfunction addItemsDividers(items: BarItem[]): TimelineItem[] {\n if (!items.length) return [];\n\n const result: TimelineItem[] = [];\n items.forEach((item, index) => {\n result.push(item);\n\n // Check if there's a next item and if they're not in consecutive hours\n if (index < items.length - 1) {\n const currentDate = new Date(item.startDate);\n const nextDate = new Date(items[index + 1].startDate);\n\n const currentHour = currentDate.getHours();\n const nextHour = nextDate.getHours();\n\n // Get day parts (without time) for comparison\n const currentDay = currentDate.toDateString();\n const nextDay = nextDate.toDateString();\n\n // If different days or non-consecutive hours on the same day\n if (\n currentDay !== nextDay ||\n (currentDay === nextDay && Math.abs(nextHour - currentHour) > 1)\n ) {\n result.push({\n id: `divider-${item.id}-${items[index + 1].id}`,\n type: \"divider\" as const,\n revision: 0,\n });\n }\n }\n });\n\n return result;\n}\n\nfunction metricsToItems(metrics: GroupedPeriodResults): TimelineItem[] {\n if (!metrics) return [];\n\n const items = metrics\n .sort((a, b) => {\n const aDate = new Date(a.start as unknown as Date);\n const bDate = new Date(b.start as unknown as Date);\n return aDate.getTime() - bDate.getTime();\n })\n .filter((result) => {\n return result.rows.every((row) => row.value > 0);\n })\n .map((result) => {\n const { additions, deletions } = result.rows.reduce(\n (acc, row) => {\n if (\n (row.dimensions.changes.path as unknown as string) ===\n \"ph/diff/changes/add\"\n ) {\n acc.additions += row.value;\n } else if (\n (row.dimensions.changes.path as unknown as string) ===\n \"ph/diff/changes/remove\"\n ) {\n acc.deletions += row.value;\n }\n return acc;\n },\n { additions: 0, deletions: 0 },\n );\n\n const startDate = new Date(result.start as unknown as Date);\n\n return {\n id: startDate.toISOString(),\n type: \"bar\" as const,\n addSize: getBarSize(additions),\n delSize: getBarSize(deletions),\n additions,\n deletions,\n timestampUtcMs: startDate.toISOString(),\n startDate: startDate,\n endDate: new Date(result.end as unknown as Date),\n revision: 0,\n } as const;\n });\n\n return addItemsDividers(items);\n}\n\nexport type UseTimelineItemsResult = UseAnalyticsQueryResult<TimelineItem[]>;\n\nexport const useTimelineItems = (\n documentId?: string,\n startTimestamp?: string,\n driveId?: string,\n): UseTimelineItemsResult => {\n const start = startTimestamp\n ? DateTime.fromISO(startTimestamp)\n : DateTime.now().startOf(\"day\");\n\n return useAnalyticsQuery<TimelineItem[]>(\n {\n start,\n end: DateTime.now().endOf(\"day\"),\n granularity: AnalyticsGranularity.Hourly,\n metrics: [\"Count\"],\n select: {\n changes: [AnalyticsPath.fromString(`ph/diff/changes`)],\n document: [AnalyticsPath.fromString(`ph/diff/document/${documentId}`)],\n },\n lod: {\n changes: 4,\n },\n },\n {\n sources: [AnalyticsPath.fromString(`ph/diff/${driveId}/${documentId}`)],\n select: metricsToItems,\n },\n );\n};\n","import { useDocumentById } from \"../../hooks/document-by-id.js\";\nimport { useTimelineItems } from \"./timeline-items.js\";\n\nexport function useDocumentTimeline(documentId?: string) {\n const [document] = useDocumentById(documentId);\n\n const id = document?.header.id;\n const createdAt = document?.header.createdAtUtcIso;\n const timelineItems = useTimelineItems(id, createdAt);\n\n return timelineItems.data || [];\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/analytics/context.tsx","../../../src/analytics/hooks/analytics-query.ts","../../../src/analytics/hooks/timeline-items.ts","../../../src/analytics/hooks/document-timeline.ts"],"sourcesContent":["import type { AnalyticsQueryEngine } from \"@powerhousedao/analytics-engine-core\";\nimport {\n QueryClient,\n QueryClientProvider,\n useMutation,\n useQuery,\n useQueryClient,\n useSuspenseQuery,\n} from \"@tanstack/react-query\";\nimport { childLogger } from \"document-model\";\nimport type { PropsWithChildren } from \"react\";\nimport { useEffect } from \"react\";\nimport { getGlobal } from \"../global/core.js\";\nimport type { CreateStoreOptions } from \"./store.js\";\nimport { getAnalyticsStore } from \"./store.js\";\n\nconst _logger = childLogger([\"reactor-browser\", \"analytics\", \"provider\"]);\n\nconst defaultQueryClient = new QueryClient();\n\nexport const analyticsOptionsKey = [\"analytics\", \"options\"] as const;\nexport const analyticsStoreKey = [\"analytics\", \"store\"] as const;\nexport const analyticsEngineKey = [\"analytics\", \"engine\"] as const;\n\nexport function useAnalyticsStoreOptions() {\n return useQuery<CreateStoreOptions | undefined>({\n queryKey: analyticsOptionsKey,\n }).data;\n}\n\nexport function useCreateAnalyticsStore(options?: CreateStoreOptions) {\n const queryClient = useQueryClient();\n useEffect(() => {\n queryClient.setQueryDefaults(analyticsOptionsKey, {\n queryFn: () => options,\n staleTime: Infinity,\n gcTime: Infinity,\n });\n }, [queryClient, options]);\n\n return useMutation({\n mutationFn: async () => {\n const store = getAnalyticsStore();\n queryClient.setQueryDefaults(analyticsStoreKey, {\n queryFn: () => store,\n staleTime: Infinity,\n gcTime: Infinity,\n });\n return store;\n },\n });\n}\n\nexport function useAnalyticsStoreQuery(options?: CreateStoreOptions) {\n return useSuspenseQuery({\n queryKey: [analyticsStoreKey, options],\n queryFn: () => getAnalyticsStore(),\n retry: true,\n });\n}\n\nexport function useAnalyticsStore(options?: CreateStoreOptions) {\n const store = useAnalyticsStoreQuery(options);\n return store.data;\n}\n\nexport function useAnalyticsStoreAsync(options?: CreateStoreOptions) {\n return useQuery({\n queryKey: [analyticsStoreKey, options],\n queryFn: () => getAnalyticsStore(),\n retry: true,\n throwOnError: false,\n });\n}\n\ninterface BaseAnalyticsProviderProps extends PropsWithChildren {\n /**\n * Custom QueryClient instance\n * @default undefined\n */\n queryClient?: QueryClient;\n}\n\ntype AnalyticsProviderProps = BaseAnalyticsProviderProps &\n (\n | {\n options?: CreateStoreOptions;\n }\n | {\n databaseName?: string;\n }\n );\n\nfunction CreateAnalyticsStore() {\n const { mutate } = useCreateAnalyticsStore();\n\n useEffect(() => {\n mutate();\n }, []);\n\n return null;\n}\n\nexport function AnalyticsProvider({\n children,\n queryClient = defaultQueryClient,\n ..._props\n}: AnalyticsProviderProps) {\n return (\n <QueryClientProvider client={queryClient}>\n <CreateAnalyticsStore />\n {children}\n </QueryClientProvider>\n );\n}\n\nexport function useAnalyticsEngine(): AnalyticsQueryEngine | undefined {\n return useSuspenseQuery({\n queryKey: analyticsEngineKey,\n queryFn: async () => {\n const globalAnalytics = getGlobal(\"analytics\");\n if (!globalAnalytics) {\n throw new Error(\"No analytics store available\");\n }\n return (await globalAnalytics).engine;\n },\n retry: false,\n }).data;\n}\n\nexport function useAnalyticsEngineAsync() {\n return useQuery({\n queryKey: analyticsEngineKey,\n queryFn: async () => {\n const globalAnalytics = getGlobal(\"analytics\");\n if (!globalAnalytics) {\n throw new Error(\"No analytics store available\");\n }\n return (await globalAnalytics).engine;\n },\n retry: false,\n });\n}\n","import type {\n AnalyticsQuery,\n AnalyticsQueryEngine,\n AnalyticsSeries,\n AnalyticsSeriesInput,\n AnalyticsSeriesQuery,\n GroupedPeriodResults,\n IAnalyticsStore,\n} from \"@powerhousedao/analytics-engine-core\";\nimport { AnalyticsPath } from \"@powerhousedao/analytics-engine-core\";\nimport type {\n UseMutationOptions,\n UseQueryOptions,\n UseQueryResult,\n} from \"@tanstack/react-query\";\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useEffect } from \"react\";\nimport {\n useAnalyticsEngineAsync,\n useAnalyticsStoreAsync,\n useAnalyticsStoreOptions,\n} from \"../context.js\";\nimport { getAnalyticsStore } from \"../store.js\";\n\nfunction useAnalyticsQueryWrapper<TQueryFnData = unknown, TData = TQueryFnData>(\n options: Omit<UseQueryOptions<TQueryFnData, Error, TData>, \"queryFn\"> & {\n queryFn: (analytics: {\n store: IAnalyticsStore;\n engine: AnalyticsQueryEngine;\n }) => Promise<TQueryFnData> | TQueryFnData;\n },\n) {\n const { queryFn, ...queryOptions } = options;\n const { data: store } = useAnalyticsStoreAsync();\n const { data: engine } = useAnalyticsEngineAsync();\n const enabled =\n \"enabled\" in queryOptions ? queryOptions.enabled : !!store && !!engine;\n\n return useQuery({\n ...queryOptions,\n enabled,\n queryFn: async () => {\n if (!store || !engine) {\n throw new Error(\n \"No analytics store available. Use within an AnalyticsProvider.\",\n );\n }\n return await queryFn({ store, engine });\n },\n });\n}\n\nfunction useAnalyticsMutationWrapper<TVariables, TData>(\n options: Omit<UseMutationOptions<TData, Error, TVariables>, \"mutationFn\"> & {\n mutationFn: (\n variables: TVariables,\n context: {\n store: IAnalyticsStore;\n },\n ) => Promise<TData> | TData;\n },\n) {\n const { mutationFn, ...mutationOptions } = options;\n const _storeOptions = useAnalyticsStoreOptions();\n\n return useMutation({\n ...mutationOptions,\n mutationFn: async (value: TVariables) => {\n let store: IAnalyticsStore | null = null;\n try {\n store = await getAnalyticsStore();\n } catch (e) {\n console.error(e);\n }\n\n if (!store) {\n throw new Error(\n \"No analytics store available. Use within an AnalyticsProvider.\",\n );\n }\n return await mutationFn(value, { store });\n },\n });\n}\n\nexport type UseAnalyticsQueryOptions<TData = GroupedPeriodResults> = Omit<\n UseQueryOptions<GroupedPeriodResults, Error, TData>,\n \"queryKey\" | \"queryFn\"\n> & {\n sources?: AnalyticsPath[];\n};\n\nexport type UseAnalyticsQueryResult<TData = GroupedPeriodResults> =\n UseQueryResult<TData>;\n\nconst DEBOUNCE_INTERVAL = 200;\n\nexport function useAnalyticsQuery<TData = GroupedPeriodResults>(\n query: AnalyticsQuery,\n options?: UseAnalyticsQueryOptions<TData>,\n): UseAnalyticsQueryResult<TData> {\n const { data: store } = useAnalyticsStoreAsync();\n const queryClient = useQueryClient();\n const sources = options?.sources ?? [];\n\n const result = useAnalyticsQueryWrapper({\n queryKey: [\"analytics\", \"query\", query],\n queryFn: ({ engine }) => engine.execute(query),\n ...options,\n });\n\n useEffect(() => {\n if (!sources.length || !store) {\n return;\n }\n\n const subscriptions = new Array<() => void>();\n // Debounce invalidateQueries so it's not called too frequently\n let invalidateTimeout: ReturnType<typeof setTimeout> | null = null;\n const debouncedInvalidate = () => {\n if (invalidateTimeout) clearTimeout(invalidateTimeout);\n invalidateTimeout = setTimeout(() => {\n queryClient\n .invalidateQueries({\n queryKey: [\"analytics\", \"query\", query],\n })\n .catch((e) => {\n console.error(e);\n });\n }, DEBOUNCE_INTERVAL);\n };\n\n sources.forEach((path) => {\n const unsub = store.subscribeToSource(path, debouncedInvalidate);\n subscriptions.push(unsub);\n });\n\n // Unsubscribes from store when component unmounts or dependencies change\n return () => {\n subscriptions.forEach((unsub) => unsub());\n };\n }, [query, store, sources]);\n\n return result;\n}\n\nexport type UseAnalyticsSeriesOptions = Omit<\n UseQueryOptions<AnalyticsSeries[], Error, AnalyticsSeries[]>,\n \"queryKey\" | \"queryFn\"\n>;\n\nexport function useAnalyticsSeries(\n query: AnalyticsSeriesQuery,\n options?: UseAnalyticsSeriesOptions,\n) {\n return useAnalyticsQueryWrapper({\n queryKey: [\"analytics\", \"series\", query],\n queryFn: ({ store }) => store.getMatchingSeries(query),\n ...options,\n });\n}\n\nexport type UseAddSeriesValueOptions = Omit<\n UseMutationOptions<void, Error, AnalyticsSeriesInput>,\n \"mutationKey\" | \"mutationFn\"\n>;\n\nexport function useAddSeriesValue(options?: UseAddSeriesValueOptions) {\n return useAnalyticsMutationWrapper({\n mutationKey: [\"analytics\", \"addSeries\"],\n mutationFn: async (value, { store }) => {\n return await store.addSeriesValue(value);\n },\n ...options,\n });\n}\n\nexport type UseClearSeriesBySourceOptions = Omit<\n UseMutationOptions<\n number,\n Error,\n { source: AnalyticsPath; cleanUpDimensions?: boolean }\n >,\n \"mutationKey\" | \"mutationFn\"\n>;\n\nexport function useClearSeriesBySource(\n options?: UseClearSeriesBySourceOptions,\n) {\n return useAnalyticsMutationWrapper({\n mutationKey: [\"analytics\", \"clearSeries\"],\n mutationFn: async ({ source, cleanUpDimensions }, { store }) => {\n return store.clearSeriesBySource(source, cleanUpDimensions);\n },\n ...options,\n });\n}\n\nexport type UseClearEmptyAnalyticsDimensionsOptions = Omit<\n UseMutationOptions<number>,\n \"mutationKey\" | \"mutationFn\"\n>;\n\nexport function useClearEmptyAnalyticsDimensions(\n options?: UseClearEmptyAnalyticsDimensionsOptions,\n) {\n return useAnalyticsMutationWrapper({\n mutationKey: [\"analytics\", \"clearEmptyDimensions\"],\n mutationFn: async (_, { store }) => {\n return store.clearEmptyAnalyticsDimensions();\n },\n ...options,\n });\n}\n\nexport type UseAddSeriesValuesOptions = Omit<\n UseMutationOptions<void, Error, AnalyticsSeriesInput[]>,\n \"mutationKey\" | \"mutationFn\"\n>;\n\nexport function useAddSeriesValues(options?: UseAddSeriesValuesOptions) {\n return useAnalyticsMutationWrapper({\n mutationKey: [\"analytics\", \"addSeriesValues\"],\n mutationFn: async (values, { store }) => {\n return store.addSeriesValues(values);\n },\n ...options,\n });\n}\n\nexport type UseGetDimensionsOptions<TData> = Omit<\n UseQueryOptions<any, Error, TData>,\n \"queryKey\" | \"queryFn\"\n>;\n\nexport function useGetDimensions<TData = any>(\n options?: UseGetDimensionsOptions<TData>,\n) {\n return useAnalyticsQueryWrapper({\n queryKey: [\"analytics\", \"dimensions\"],\n queryFn: ({ store }) => store.getDimensions(),\n ...options,\n });\n}\n\nexport type UseMatchingSeriesOptions = Omit<\n UseQueryOptions<AnalyticsSeries[], Error, AnalyticsSeries[]>,\n \"queryKey\" | \"queryFn\"\n>;\n\nexport function useMatchingSeries(\n query: AnalyticsSeriesQuery,\n options?: UseMatchingSeriesOptions,\n) {\n const result = useAnalyticsQueryWrapper({\n queryKey: [\"analytics\", \"matchingSeries\", query],\n queryFn: ({ store }) => store.getMatchingSeries(query),\n ...options,\n });\n\n return result;\n}\n\nexport type UseQuerySourcesOptions = Omit<\n UseQueryOptions<AnalyticsPath[] | undefined>,\n \"queryKey\" | \"queryFn\"\n>;\n\nexport function useQuerySources(\n query: AnalyticsSeriesQuery,\n options?: UseQuerySourcesOptions,\n) {\n const { data: matchingSeries } = useMatchingSeries(query);\n\n return useQuery({\n queryKey: [\"analytics\", \"sources\", query],\n queryFn: () => {\n if (!matchingSeries?.length) {\n return [];\n }\n const uniqueSources = [\n ...new Set(matchingSeries.map((s) => s.source.toString())),\n ];\n return uniqueSources.map((source) => AnalyticsPath.fromString(source));\n },\n enabled: !!matchingSeries,\n ...options,\n });\n}\n","import type { GroupedPeriodResults } from \"@powerhousedao/analytics-engine-core\";\nimport {\n AnalyticsGranularity,\n AnalyticsPath,\n} from \"@powerhousedao/analytics-engine-core\";\nimport { DateTime } from \"luxon\";\nimport type { UseAnalyticsQueryResult } from \"./analytics-query.js\";\nimport { useAnalyticsQuery } from \"./analytics-query.js\";\n\nconst getBarSize = (value: number) => {\n if (value <= 0) return 0;\n if (value > 0 && value <= 50) return 1;\n if (value > 50 && value <= 100) return 2;\n if (value > 100 && value <= 250) return 3;\n return 4;\n};\n\n// Define types for our timeline items\ntype BarItem = {\n id: string;\n type: \"bar\";\n addSize: 0 | 1 | 2 | 3 | 4;\n delSize: 0 | 1 | 2 | 3 | 4;\n additions: number;\n deletions: number;\n timestampUtcMs: string;\n startDate: Date;\n endDate: Date;\n revision?: number;\n};\n\ntype DividerItem = {\n id: string;\n type: \"divider\";\n revision?: number;\n startDate?: Date;\n endDate?: Date;\n};\n\ntype TimelineItem = BarItem | DividerItem;\n\nfunction addItemsDividers(items: BarItem[]): TimelineItem[] {\n if (!items.length) return [];\n\n const result: TimelineItem[] = [];\n items.forEach((item, index) => {\n result.push(item);\n\n // Check if there's a next item and if they're not in consecutive hours\n if (index < items.length - 1) {\n const currentDate = new Date(item.startDate);\n const nextDate = new Date(items[index + 1].startDate);\n\n const currentHour = currentDate.getHours();\n const nextHour = nextDate.getHours();\n\n // Get day parts (without time) for comparison\n const currentDay = currentDate.toDateString();\n const nextDay = nextDate.toDateString();\n\n // If different days or non-consecutive hours on the same day\n if (\n currentDay !== nextDay ||\n (currentDay === nextDay && Math.abs(nextHour - currentHour) > 1)\n ) {\n result.push({\n id: `divider-${item.id}-${items[index + 1].id}`,\n type: \"divider\" as const,\n revision: 0,\n });\n }\n }\n });\n\n return result;\n}\n\nfunction metricsToItems(metrics: GroupedPeriodResults): TimelineItem[] {\n if (!metrics) return [];\n\n const items = metrics\n .sort((a, b) => {\n const aDate = new Date(a.start as unknown as Date);\n const bDate = new Date(b.start as unknown as Date);\n return aDate.getTime() - bDate.getTime();\n })\n .filter((result) => {\n return result.rows.every((row) => row.value > 0);\n })\n .map((result) => {\n const { additions, deletions } = result.rows.reduce(\n (acc, row) => {\n if (\n (row.dimensions.changes.path as unknown as string) ===\n \"ph/diff/changes/add\"\n ) {\n acc.additions += row.value;\n } else if (\n (row.dimensions.changes.path as unknown as string) ===\n \"ph/diff/changes/remove\"\n ) {\n acc.deletions += row.value;\n }\n return acc;\n },\n { additions: 0, deletions: 0 },\n );\n\n const startDate = new Date(result.start as unknown as Date);\n\n return {\n id: startDate.toISOString(),\n type: \"bar\" as const,\n addSize: getBarSize(additions),\n delSize: getBarSize(deletions),\n additions,\n deletions,\n timestampUtcMs: startDate.toISOString(),\n startDate: startDate,\n endDate: new Date(result.end as unknown as Date),\n revision: 0,\n } as const;\n });\n\n return addItemsDividers(items);\n}\n\nexport type UseTimelineItemsResult = UseAnalyticsQueryResult<TimelineItem[]>;\n\nexport const useTimelineItems = (\n documentId?: string,\n startTimestamp?: string,\n driveId?: string,\n): UseTimelineItemsResult => {\n const start = startTimestamp\n ? DateTime.fromISO(startTimestamp)\n : DateTime.now().startOf(\"day\");\n\n return useAnalyticsQuery<TimelineItem[]>(\n {\n start,\n end: DateTime.now().endOf(\"day\"),\n granularity: AnalyticsGranularity.Hourly,\n metrics: [\"Count\"],\n select: {\n changes: [AnalyticsPath.fromString(`ph/diff/changes`)],\n document: [AnalyticsPath.fromString(`ph/diff/document/${documentId}`)],\n },\n lod: {\n changes: 4,\n },\n },\n {\n sources: [AnalyticsPath.fromString(`ph/diff/${driveId}/${documentId}`)],\n select: metricsToItems,\n },\n );\n};\n","import { useDocumentById } from \"../../hooks/document-by-id.js\";\nimport { useTimelineItems } from \"./timeline-items.js\";\n\nexport function useDocumentTimeline(documentId?: string) {\n const [document] = useDocumentById(documentId);\n\n const id = document?.header.id;\n const createdAt = document?.header.createdAtUtcIso;\n const timelineItems = useTimelineItems(id, createdAt);\n\n return timelineItems.data || [];\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as RelationalDbWithLive, i as useRelationalQueryOptions, n as QueryCallbackReturnType, o as useRelationalDb, r as useRelationalQuery, t as createProcessorQuery } from "../../index-
|
|
1
|
+
import { a as RelationalDbWithLive, i as useRelationalQueryOptions, n as QueryCallbackReturnType, o as useRelationalDb, r as useRelationalQuery, t as createProcessorQuery } from "../../index-ZltD7u5Z.js";
|
|
2
2
|
export { QueryCallbackReturnType, RelationalDbWithLive, createProcessorQuery, useRelationalDb, useRelationalQuery, useRelationalQueryOptions };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as useRelationalQuery, r as useRelationalDb, t as createProcessorQuery } from "../../relational-
|
|
1
|
+
import { n as useRelationalQuery, r as useRelationalDb, t as createProcessorQuery } from "../../relational-4_LVwp8p.js";
|
|
2
2
|
export { createProcessorQuery, useRelationalDb, useRelationalQuery };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@powerhousedao/reactor-browser",
|
|
3
|
-
"version": "6.1.0-dev.
|
|
3
|
+
"version": "6.1.0-dev.10",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -54,13 +54,13 @@
|
|
|
54
54
|
"remeda": "2.33.7",
|
|
55
55
|
"slug": "^11.0.0",
|
|
56
56
|
"zod": "4.3.6",
|
|
57
|
-
"@powerhousedao/analytics-engine-browser": "6.1.0-dev.
|
|
58
|
-
"@powerhousedao/analytics-engine-core": "6.1.0-dev.
|
|
59
|
-
"@powerhousedao/reactor": "6.1.0-dev.
|
|
60
|
-
"@powerhousedao/shared": "6.1.0-dev.
|
|
61
|
-
"@powerhousedao/reactor-drive": "6.1.0-dev.
|
|
62
|
-
"@renown/sdk": "6.1.0-dev.
|
|
63
|
-
"document-model": "6.1.0-dev.
|
|
57
|
+
"@powerhousedao/analytics-engine-browser": "6.1.0-dev.10",
|
|
58
|
+
"@powerhousedao/analytics-engine-core": "6.1.0-dev.10",
|
|
59
|
+
"@powerhousedao/reactor": "6.1.0-dev.10",
|
|
60
|
+
"@powerhousedao/shared": "6.1.0-dev.10",
|
|
61
|
+
"@powerhousedao/reactor-drive": "6.1.0-dev.10",
|
|
62
|
+
"@renown/sdk": "6.1.0-dev.10",
|
|
63
|
+
"document-model": "6.1.0-dev.10"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
66
|
"@electric-sql/pglite": "0.3.15",
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"fast-deep-equal": "3.1.3",
|
|
81
81
|
"graphql": "^16",
|
|
82
82
|
"graphql-tag": "^2",
|
|
83
|
-
"playwright": "1.
|
|
83
|
+
"playwright": "1.60.0",
|
|
84
84
|
"react": "19.2.6",
|
|
85
85
|
"react-dom": "19.2.6",
|
|
86
86
|
"tsdown": "0.21.1",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"relational-jwreqDwz.js","names":[],"sources":["../src/pglite/usePGlite.ts","../src/relational/hooks/useRelationalDb.ts","../src/relational/hooks/useRelationalQuery.ts","../src/relational/utils/createProcessorQuery.ts"],"sourcesContent":["import type { PGliteWithLive } from \"@electric-sql/pglite/live\";\nimport { useEffect, useState } from \"react\";\n\nexport const PGLITE_UPDATE_EVENT = \"ph:pglite-update\";\n\nexport interface PGliteState {\n db: PGliteWithLive | null;\n isLoading: boolean;\n error: Error | null;\n}\n\nconst defaultPGliteState: PGliteState = {\n db: null,\n isLoading: true,\n error: null,\n};\n\nexport const usePGliteDB = () => {\n const [state, setState] = useState<PGliteState>(\n () => window.powerhouse?.pglite ?? defaultPGliteState,\n );\n\n useEffect(() => {\n const handlePgliteUpdate = () =>\n setState(window.powerhouse?.pglite ?? defaultPGliteState);\n\n window.addEventListener(PGLITE_UPDATE_EVENT, handlePgliteUpdate);\n\n return () =>\n window.removeEventListener(PGLITE_UPDATE_EVENT, handlePgliteUpdate);\n }, []);\n\n return state;\n};\n\nexport const useSetPGliteDB = () => {\n const setPGliteState = (pglite: Partial<PGliteState>) => {\n const currentPowerhouse = window.powerhouse ?? {};\n const currentPGliteState = window.powerhouse?.pglite ?? defaultPGliteState;\n\n window.powerhouse = {\n ...currentPowerhouse,\n pglite: {\n ...currentPGliteState,\n ...pglite,\n },\n };\n window.dispatchEvent(new CustomEvent(PGLITE_UPDATE_EVENT));\n };\n\n return setPGliteState;\n};\n\nexport const usePGlite = () => {\n const pglite = usePGliteDB();\n const setPGlite = useSetPGliteDB();\n\n return [pglite, setPGlite];\n};\n","import type { PGlite } from \"@electric-sql/pglite\";\nimport type { LiveNamespace, PGliteWithLive } from \"@electric-sql/pglite/live\";\nimport { createRelationalDb } from \"@powerhousedao/reactor\";\nimport type { IRelationalDb as IRelationalDbCore } from \"@powerhousedao/shared/processors\";\nimport { Kysely } from \"kysely\";\nimport { PGliteDialect } from \"kysely-pglite-dialect\";\nimport { useMemo } from \"react\";\nimport { usePGliteDB } from \"../../pglite/usePGlite.js\";\n\n// Type for Relational DB instance enhanced with live capabilities\nexport type RelationalDbWithLive<Schema> = IRelationalDbCore<Schema> & {\n live: LiveNamespace;\n};\n\ninterface IRelationalDbState<Schema> {\n db: RelationalDbWithLive<Schema> | null;\n isLoading: boolean;\n error: Error | null;\n}\n\n// Custom initializer that creates enhanced Kysely instance with live capabilities\nfunction createRelationalDbWithLive<Schema>(\n pgliteInstance: PGliteWithLive,\n): RelationalDbWithLive<Schema> {\n const baseDb = new Kysely<Schema>({\n dialect: new PGliteDialect(pgliteInstance as unknown as PGlite),\n });\n const relationalDb = createRelationalDb(baseDb);\n\n // Inject the live namespace with proper typing\n const relationalDBWithLive =\n relationalDb as unknown as RelationalDbWithLive<Schema>;\n relationalDBWithLive.live = pgliteInstance.live;\n\n return relationalDBWithLive;\n}\n\nexport const useRelationalDb = <Schema>(): IRelationalDbState<Schema> => {\n const pglite = usePGliteDB();\n\n const relationalDb = useMemo<IRelationalDbState<Schema>>(() => {\n if (!pglite.db || pglite.isLoading || pglite.error) {\n return {\n db: null,\n isLoading: pglite.isLoading,\n error: pglite.error,\n };\n }\n\n const db = createRelationalDbWithLive<Schema>(pglite.db);\n\n return {\n db,\n isLoading: false,\n error: null,\n };\n }, [pglite]);\n\n return relationalDb;\n};\n","import type { LiveQueryResults } from \"@electric-sql/pglite/live\";\nimport type {\n IRelationalQueryBuilder,\n RelationalDbProcessorClass,\n} from \"@powerhousedao/shared/processors\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { useRelationalDb } from \"./useRelationalDb.js\";\n\nexport type QueryCallbackReturnType = {\n sql: string;\n parameters?: readonly unknown[];\n};\n\nexport type useRelationalQueryOptions = {\n // Whether to hash the namespace to avoid namespace size limit. True by default\n hashNamespace?: boolean;\n};\n\nconst MAX_RETRIES = 5;\nconst RETRY_DELAY = 200;\n\nconst isRelationNotExistError = (error: unknown): boolean => {\n const errorMessage =\n error instanceof Error\n ? error.message\n : typeof error === \"string\"\n ? error\n : String(error);\n\n return (\n errorMessage.toLowerCase().includes(\"relation\") &&\n errorMessage.toLowerCase().includes(\"does not exist\")\n );\n};\n\ntype LiveQueryType = {\n unsubscribe: () => void;\n};\n\nexport function useRelationalQuery<Schema, T = unknown, TParams = undefined>(\n ProcessorClass: RelationalDbProcessorClass<Schema>,\n driveId: string,\n queryCallback: (\n db: IRelationalQueryBuilder<Schema>,\n parameters?: TParams,\n ) => QueryCallbackReturnType,\n parameters?: TParams,\n options?: useRelationalQueryOptions,\n) {\n const [result, setResult] = useState<LiveQueryResults<T> | null>(null);\n const [queryLoading, setQueryLoading] = useState(true);\n const [error, setError] = useState<Error | undefined>(undefined);\n const retryCount = useRef(0);\n const retryTimeoutRef = useRef<NodeJS.Timeout>(null);\n\n const relationalDb = useRelationalDb<Schema>();\n\n const executeLiveQuery = async (\n sql: string,\n queryParameters: readonly unknown[] | undefined,\n retryAttempt = 0,\n ): Promise<LiveQueryType | null> => {\n if (!relationalDb.db) {\n return null;\n }\n\n try {\n const live = await relationalDb.db.live.query<T>(\n sql,\n queryParameters ? [...queryParameters] : [],\n (result) => {\n setResult(result);\n setQueryLoading(false);\n retryCount.current = 0; // Reset retry count on success\n },\n );\n\n return live as LiveQueryType;\n } catch (err: unknown) {\n if (isRelationNotExistError(err) && retryAttempt < MAX_RETRIES) {\n return new Promise((resolve) => {\n retryTimeoutRef.current = setTimeout(() => {\n resolve(executeLiveQuery(sql, queryParameters, retryAttempt + 1));\n }, RETRY_DELAY);\n });\n }\n\n setQueryLoading(false);\n setError(err instanceof Error ? err : new Error(String(err)));\n return null;\n }\n };\n\n useEffect(() => {\n setError(undefined);\n setQueryLoading(true);\n retryCount.current = 0;\n\n if (!relationalDb.db) {\n return;\n }\n\n // Use the processor helper to obtain a typed namespaced query builder\n const db = ProcessorClass.query(driveId, relationalDb.db);\n\n const compiledQuery = queryCallback(db, parameters);\n const { sql, parameters: queryParameters } = compiledQuery;\n\n const liveQueryPromise = executeLiveQuery(sql, queryParameters);\n\n return () => {\n if (retryTimeoutRef.current) {\n clearTimeout(retryTimeoutRef.current);\n }\n void liveQueryPromise.then((live) => {\n if (live?.unsubscribe) {\n live.unsubscribe();\n }\n });\n };\n }, [relationalDb.db, ProcessorClass, driveId, queryCallback, parameters]);\n\n return {\n isLoading: relationalDb.isLoading || queryLoading,\n error: error || relationalDb.error,\n result,\n } as const;\n}\n","import type { LiveQueryResults } from \"@electric-sql/pglite/live\";\nimport type {\n QueryCallbackReturnType,\n useRelationalQueryOptions,\n} from \"@powerhousedao/reactor-browser\";\nimport type {\n IRelationalQueryBuilder,\n RelationalDbProcessorClass,\n} from \"@powerhousedao/shared/processors\";\nimport type { CompiledQuery } from \"kysely\";\nimport deepEqual from \"lodash.isequal\";\nimport { useCallback, useMemo, useRef } from \"react\";\nimport { useRelationalQuery } from \"../hooks/useRelationalQuery.js\";\n\n// Custom hook for parameter memoization\nfunction useStableParams<T>(params: T): T {\n const prevParamsRef = useRef<T>(null);\n\n return useMemo(() => {\n if (!deepEqual(prevParamsRef.current, params)) {\n prevParamsRef.current = params;\n }\n return prevParamsRef.current as T;\n }, [params]);\n}\n\nexport function createProcessorQuery<TSchema>(\n ProcessorClass: RelationalDbProcessorClass<TSchema>,\n) {\n // Overload for queries without parameters\n function useQuery<\n TQueryBuilder extends (\n db: IRelationalQueryBuilder<TSchema>,\n ) => QueryCallbackReturnType,\n >(\n driveId: string,\n queryCallback: TQueryBuilder,\n ): {\n isLoading: boolean;\n error: Error | null;\n result: LiveQueryResults<\n ReturnType<TQueryBuilder> extends CompiledQuery<infer R> ? R : any\n > | null;\n };\n\n // Overload for queries with parameters\n function useQuery<\n TParams,\n TQueryBuilder extends (\n db: IRelationalQueryBuilder<TSchema>,\n parameters: TParams,\n ) => QueryCallbackReturnType,\n >(\n driveId: string,\n queryCallback: TQueryBuilder,\n parameters: TParams,\n options?: useRelationalQueryOptions,\n ): {\n isLoading: boolean;\n error: Error | null;\n result: LiveQueryResults<\n ReturnType<TQueryBuilder> extends CompiledQuery<infer R> ? R : any\n > | null;\n };\n\n function useQuery<\n TParams,\n TQueryBuilder extends (\n db: IRelationalQueryBuilder<TSchema>,\n parameters?: TParams,\n ) => QueryCallbackReturnType,\n >(\n driveId: string,\n queryCallback: TQueryBuilder,\n parameters?: TParams,\n options?: useRelationalQueryOptions,\n ): {\n isLoading: boolean;\n error: Error | null;\n result: LiveQueryResults<\n ReturnType<TQueryBuilder> extends CompiledQuery<infer R> ? R : any\n > | null;\n } {\n type InferredResult =\n ReturnType<TQueryBuilder> extends CompiledQuery<infer R> ? R : any;\n\n // Automatically memoize parameters using deep comparison\n const stableParams = useStableParams(parameters);\n\n // Memoize the callback to prevent infinite loops, updating when parameters change\n const memoizedCallback = useCallback(queryCallback, [stableParams]);\n\n return useRelationalQuery<TSchema, InferredResult, TParams>(\n ProcessorClass,\n driveId,\n memoizedCallback,\n stableParams,\n options,\n ) as {\n isLoading: boolean;\n error: Error | null;\n result: LiveQueryResults<InferredResult> | null;\n };\n }\n\n return useQuery;\n}\n"],"mappings":"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"}
|