@tanstack/angular-db 0.1.36 → 0.1.37

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.
@@ -11,6 +11,11 @@ function injectLiveQuery(opts) {
11
11
  return opts;
12
12
  }
13
13
  if (typeof opts === `function`) {
14
+ const queryBuilder = new db.BaseQueryBuilder();
15
+ const result = opts(queryBuilder);
16
+ if (result === void 0 || result === null) {
17
+ return null;
18
+ }
14
19
  return db.createLiveQueryCollection({
15
20
  query: opts,
16
21
  startSync: true,
@@ -21,6 +26,11 @@ function injectLiveQuery(opts) {
21
26
  if (isReactiveQueryOptions) {
22
27
  const { params, query } = opts;
23
28
  const currentParams = params();
29
+ const queryBuilder = new db.BaseQueryBuilder();
30
+ const result = query({ params: currentParams, q: queryBuilder });
31
+ if (result === void 0 || result === null) {
32
+ return null;
33
+ }
24
34
  return db.createLiveQueryCollection({
25
35
  query: (q) => query({ params: currentParams, q }),
26
36
  startSync: true,
@@ -34,7 +44,9 @@ function injectLiveQuery(opts) {
34
44
  });
35
45
  const state = core.signal(/* @__PURE__ */ new Map());
36
46
  const data = core.signal([]);
37
- const status = core.signal(`idle`);
47
+ const status = core.signal(
48
+ collection() ? `idle` : `disabled`
49
+ );
38
50
  const syncDataFromCollection = (currentCollection) => {
39
51
  const newState = new Map(currentCollection.entries());
40
52
  const newData = Array.from(currentCollection.values());
@@ -50,6 +62,10 @@ function injectLiveQuery(opts) {
50
62
  core.effect((onCleanup) => {
51
63
  const currentCollection = collection();
52
64
  if (!currentCollection) {
65
+ status.set(`disabled`);
66
+ state.set(/* @__PURE__ */ new Map());
67
+ data.set([]);
68
+ cleanup();
53
69
  return;
54
70
  }
55
71
  cleanup();
@@ -76,7 +92,7 @@ function injectLiveQuery(opts) {
76
92
  collection,
77
93
  status,
78
94
  isLoading: core.computed(() => status() === `loading`),
79
- isReady: core.computed(() => status() === `ready`),
95
+ isReady: core.computed(() => status() === `ready` || status() === `disabled`),
80
96
  isIdle: core.computed(() => status() === `idle`),
81
97
  isError: core.computed(() => status() === `error`),
82
98
  isCleanedUp: core.computed(() => status() === `cleaned-up`)
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../src/index.ts"],"sourcesContent":["import {\n DestroyRef,\n assertInInjectionContext,\n computed,\n effect,\n inject,\n signal,\n} from \"@angular/core\"\nimport { createLiveQueryCollection } from \"@tanstack/db\"\nimport type {\n ChangeMessage,\n Collection,\n CollectionStatus,\n Context,\n GetResult,\n InitialQueryBuilder,\n LiveQueryCollectionConfig,\n QueryBuilder,\n} from \"@tanstack/db\"\nimport type { Signal } from \"@angular/core\"\n\n/**\n * The result of calling `injectLiveQuery`.\n * Contains reactive signals for the query state and data.\n */\nexport interface InjectLiveQueryResult<\n TResult extends object = any,\n TKey extends string | number = string | number,\n TUtils extends Record<string, any> = {},\n> {\n /** A signal containing the complete state map of results keyed by their ID */\n state: Signal<Map<TKey, TResult>>\n /** A signal containing the results as an array */\n data: Signal<Array<TResult>>\n /** A signal containing the underlying collection instance */\n collection: Signal<Collection<TResult, TKey, TUtils>>\n /** A signal containing the current status of the collection */\n status: Signal<CollectionStatus>\n /** A signal indicating whether the collection is currently loading */\n isLoading: Signal<boolean>\n /** A signal indicating whether the collection is ready */\n isReady: Signal<boolean>\n /** A signal indicating whether the collection is idle */\n isIdle: Signal<boolean>\n /** A signal indicating whether the collection has an error */\n isError: Signal<boolean>\n /** A signal indicating whether the collection has been cleaned up */\n isCleanedUp: Signal<boolean>\n}\n\nexport function injectLiveQuery<\n TContext extends Context,\n TParams extends any,\n>(options: {\n params: () => TParams\n query: (args: {\n params: TParams\n q: InitialQueryBuilder\n }) => QueryBuilder<TContext>\n}): InjectLiveQueryResult<GetResult<TContext>>\nexport function injectLiveQuery<TContext extends Context>(\n queryFn: (q: InitialQueryBuilder) => QueryBuilder<TContext>\n): InjectLiveQueryResult<GetResult<TContext>>\nexport function injectLiveQuery<TContext extends Context>(\n config: LiveQueryCollectionConfig<TContext>\n): InjectLiveQueryResult<GetResult<TContext>>\nexport function injectLiveQuery<\n TResult extends object,\n TKey extends string | number,\n TUtils extends Record<string, any>,\n>(\n liveQueryCollection: Collection<TResult, TKey, TUtils>\n): InjectLiveQueryResult<TResult, TKey, TUtils>\nexport function injectLiveQuery(opts: any) {\n assertInInjectionContext(injectLiveQuery)\n const destroyRef = inject(DestroyRef)\n\n const collection = computed(() => {\n // Check if it's an existing collection\n const isExistingCollection =\n opts &&\n typeof opts === `object` &&\n typeof opts.subscribeChanges === `function` &&\n typeof opts.startSyncImmediate === `function` &&\n typeof opts.id === `string`\n\n if (isExistingCollection) {\n return opts\n }\n\n if (typeof opts === `function`) {\n return createLiveQueryCollection({\n query: opts,\n startSync: true,\n gcTime: 0,\n })\n }\n\n // Check if it's reactive query options\n const isReactiveQueryOptions =\n opts &&\n typeof opts === `object` &&\n typeof opts.query === `function` &&\n typeof opts.params === `function`\n\n if (isReactiveQueryOptions) {\n const { params, query } = opts\n const currentParams = params()\n return createLiveQueryCollection({\n query: (q) => query({ params: currentParams, q }),\n startSync: true,\n gcTime: 0,\n })\n }\n\n // Handle LiveQueryCollectionConfig objects\n if (opts && typeof opts === `object` && typeof opts.query === `function`) {\n return createLiveQueryCollection(opts)\n }\n\n throw new Error(`Invalid options provided to injectLiveQuery`)\n })\n\n const state = signal(new Map<string | number, any>())\n const data = signal<Array<any>>([])\n const status = signal<CollectionStatus>(`idle`)\n\n const syncDataFromCollection = (\n currentCollection: Collection<any, any, any>\n ) => {\n const newState = new Map(currentCollection.entries())\n const newData = Array.from(currentCollection.values())\n\n state.set(newState)\n data.set(newData)\n status.set(currentCollection.status)\n }\n\n let unsub: (() => void) | null = null\n const cleanup = () => {\n unsub?.()\n unsub = null\n }\n\n effect((onCleanup) => {\n const currentCollection = collection()\n\n if (!currentCollection) {\n return\n }\n\n cleanup()\n\n // Initialize immediately with current state\n syncDataFromCollection(currentCollection)\n\n // Start sync if idle\n if (currentCollection.status === `idle`) {\n currentCollection.startSyncImmediate()\n // Update status after starting sync\n status.set(currentCollection.status)\n }\n\n // Subscribe to changes\n const subscription = currentCollection.subscribeChanges(\n (_: Array<ChangeMessage<any>>) => {\n syncDataFromCollection(currentCollection)\n }\n )\n unsub = subscription.unsubscribe.bind(subscription)\n\n // Handle ready state\n currentCollection.onFirstReady(() => {\n status.set(currentCollection.status)\n })\n\n onCleanup(cleanup)\n })\n\n destroyRef.onDestroy(cleanup)\n\n return {\n state,\n data,\n collection,\n status,\n isLoading: computed(() => status() === `loading`),\n isReady: computed(() => status() === `ready`),\n isIdle: computed(() => status() === `idle`),\n isError: computed(() => status() === `error`),\n isCleanedUp: computed(() => status() === `cleaned-up`),\n }\n}\n"],"names":["assertInInjectionContext","inject","DestroyRef","computed","createLiveQueryCollection","signal","effect"],"mappings":";;;;AAyEO,SAAS,gBAAgB,MAAW;AACzCA,OAAAA,yBAAyB,eAAe;AACxC,QAAM,aAAaC,KAAAA,OAAOC,eAAU;AAEpC,QAAM,aAAaC,KAAAA,SAAS,MAAM;AAEhC,UAAM,uBACJ,QACA,OAAO,SAAS,YAChB,OAAO,KAAK,qBAAqB,cACjC,OAAO,KAAK,uBAAuB,cACnC,OAAO,KAAK,OAAO;AAErB,QAAI,sBAAsB;AACxB,aAAO;AAAA,IACT;AAEA,QAAI,OAAO,SAAS,YAAY;AAC9B,aAAOC,6BAA0B;AAAA,QAC/B,OAAO;AAAA,QACP,WAAW;AAAA,QACX,QAAQ;AAAA,MAAA,CACT;AAAA,IACH;AAGA,UAAM,yBACJ,QACA,OAAO,SAAS,YAChB,OAAO,KAAK,UAAU,cACtB,OAAO,KAAK,WAAW;AAEzB,QAAI,wBAAwB;AAC1B,YAAM,EAAE,QAAQ,MAAA,IAAU;AAC1B,YAAM,gBAAgB,OAAA;AACtB,aAAOA,6BAA0B;AAAA,QAC/B,OAAO,CAAC,MAAM,MAAM,EAAE,QAAQ,eAAe,GAAG;AAAA,QAChD,WAAW;AAAA,QACX,QAAQ;AAAA,MAAA,CACT;AAAA,IACH;AAGA,QAAI,QAAQ,OAAO,SAAS,YAAY,OAAO,KAAK,UAAU,YAAY;AACxE,aAAOA,GAAAA,0BAA0B,IAAI;AAAA,IACvC;AAEA,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC/D,CAAC;AAED,QAAM,QAAQC,KAAAA,OAAO,oBAAI,KAA2B;AACpD,QAAM,OAAOA,KAAAA,OAAmB,EAAE;AAClC,QAAM,SAASA,KAAAA,OAAyB,MAAM;AAE9C,QAAM,yBAAyB,CAC7B,sBACG;AACH,UAAM,WAAW,IAAI,IAAI,kBAAkB,SAAS;AACpD,UAAM,UAAU,MAAM,KAAK,kBAAkB,QAAQ;AAErD,UAAM,IAAI,QAAQ;AAClB,SAAK,IAAI,OAAO;AAChB,WAAO,IAAI,kBAAkB,MAAM;AAAA,EACrC;AAEA,MAAI,QAA6B;AACjC,QAAM,UAAU,MAAM;AACpB,YAAA;AACA,YAAQ;AAAA,EACV;AAEAC,OAAAA,OAAO,CAAC,cAAc;AACpB,UAAM,oBAAoB,WAAA;AAE1B,QAAI,CAAC,mBAAmB;AACtB;AAAA,IACF;AAEA,YAAA;AAGA,2BAAuB,iBAAiB;AAGxC,QAAI,kBAAkB,WAAW,QAAQ;AACvC,wBAAkB,mBAAA;AAElB,aAAO,IAAI,kBAAkB,MAAM;AAAA,IACrC;AAGA,UAAM,eAAe,kBAAkB;AAAA,MACrC,CAAC,MAAiC;AAChC,+BAAuB,iBAAiB;AAAA,MAC1C;AAAA,IAAA;AAEF,YAAQ,aAAa,YAAY,KAAK,YAAY;AAGlD,sBAAkB,aAAa,MAAM;AACnC,aAAO,IAAI,kBAAkB,MAAM;AAAA,IACrC,CAAC;AAED,cAAU,OAAO;AAAA,EACnB,CAAC;AAED,aAAW,UAAU,OAAO;AAE5B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAWH,KAAAA,SAAS,MAAM,OAAA,MAAa,SAAS;AAAA,IAChD,SAASA,KAAAA,SAAS,MAAM,OAAA,MAAa,OAAO;AAAA,IAC5C,QAAQA,KAAAA,SAAS,MAAM,OAAA,MAAa,MAAM;AAAA,IAC1C,SAASA,KAAAA,SAAS,MAAM,OAAA,MAAa,OAAO;AAAA,IAC5C,aAAaA,KAAAA,SAAS,MAAM,OAAA,MAAa,YAAY;AAAA,EAAA;AAEzD;;"}
1
+ {"version":3,"file":"index.cjs","sources":["../../src/index.ts"],"sourcesContent":["import {\n DestroyRef,\n assertInInjectionContext,\n computed,\n effect,\n inject,\n signal,\n} from \"@angular/core\"\nimport { BaseQueryBuilder, createLiveQueryCollection } from \"@tanstack/db\"\nimport type {\n ChangeMessage,\n Collection,\n CollectionStatus,\n Context,\n GetResult,\n InitialQueryBuilder,\n LiveQueryCollectionConfig,\n QueryBuilder,\n} from \"@tanstack/db\"\nimport type { Signal } from \"@angular/core\"\n\n/**\n * The result of calling `injectLiveQuery`.\n * Contains reactive signals for the query state and data.\n */\nexport interface InjectLiveQueryResult<\n TResult extends object = any,\n TKey extends string | number = string | number,\n TUtils extends Record<string, any> = {},\n> {\n /** A signal containing the complete state map of results keyed by their ID */\n state: Signal<Map<TKey, TResult>>\n /** A signal containing the results as an array */\n data: Signal<Array<TResult>>\n /** A signal containing the underlying collection instance (null for disabled queries) */\n collection: Signal<Collection<TResult, TKey, TUtils> | null>\n /** A signal containing the current status of the collection */\n status: Signal<CollectionStatus | `disabled`>\n /** A signal indicating whether the collection is currently loading */\n isLoading: Signal<boolean>\n /** A signal indicating whether the collection is ready */\n isReady: Signal<boolean>\n /** A signal indicating whether the collection is idle */\n isIdle: Signal<boolean>\n /** A signal indicating whether the collection has an error */\n isError: Signal<boolean>\n /** A signal indicating whether the collection has been cleaned up */\n isCleanedUp: Signal<boolean>\n}\n\nexport function injectLiveQuery<\n TContext extends Context,\n TParams extends any,\n>(options: {\n params: () => TParams\n query: (args: {\n params: TParams\n q: InitialQueryBuilder\n }) => QueryBuilder<TContext>\n}): InjectLiveQueryResult<GetResult<TContext>>\nexport function injectLiveQuery<\n TContext extends Context,\n TParams extends any,\n>(options: {\n params: () => TParams\n query: (args: {\n params: TParams\n q: InitialQueryBuilder\n }) => QueryBuilder<TContext> | undefined | null\n}): InjectLiveQueryResult<GetResult<TContext>>\nexport function injectLiveQuery<TContext extends Context>(\n queryFn: (q: InitialQueryBuilder) => QueryBuilder<TContext>\n): InjectLiveQueryResult<GetResult<TContext>>\nexport function injectLiveQuery<TContext extends Context>(\n queryFn: (q: InitialQueryBuilder) => QueryBuilder<TContext> | undefined | null\n): InjectLiveQueryResult<GetResult<TContext>>\nexport function injectLiveQuery<TContext extends Context>(\n config: LiveQueryCollectionConfig<TContext>\n): InjectLiveQueryResult<GetResult<TContext>>\nexport function injectLiveQuery<\n TResult extends object,\n TKey extends string | number,\n TUtils extends Record<string, any>,\n>(\n liveQueryCollection: Collection<TResult, TKey, TUtils>\n): InjectLiveQueryResult<TResult, TKey, TUtils>\nexport function injectLiveQuery(opts: any) {\n assertInInjectionContext(injectLiveQuery)\n const destroyRef = inject(DestroyRef)\n\n const collection = computed(() => {\n // Check if it's an existing collection\n const isExistingCollection =\n opts &&\n typeof opts === `object` &&\n typeof opts.subscribeChanges === `function` &&\n typeof opts.startSyncImmediate === `function` &&\n typeof opts.id === `string`\n\n if (isExistingCollection) {\n return opts\n }\n\n if (typeof opts === `function`) {\n // Check if query function returns null/undefined (disabled query)\n const queryBuilder = new BaseQueryBuilder() as InitialQueryBuilder\n const result = opts(queryBuilder)\n\n if (result === undefined || result === null) {\n // Disabled query - return null\n return null\n }\n\n return createLiveQueryCollection({\n query: opts,\n startSync: true,\n gcTime: 0,\n })\n }\n\n // Check if it's reactive query options\n const isReactiveQueryOptions =\n opts &&\n typeof opts === `object` &&\n typeof opts.query === `function` &&\n typeof opts.params === `function`\n\n if (isReactiveQueryOptions) {\n const { params, query } = opts\n const currentParams = params()\n\n // Check if query function returns null/undefined (disabled query)\n const queryBuilder = new BaseQueryBuilder() as InitialQueryBuilder\n const result = query({ params: currentParams, q: queryBuilder })\n\n if (result === undefined || result === null) {\n // Disabled query - return null\n return null\n }\n\n return createLiveQueryCollection({\n query: (q) => query({ params: currentParams, q }),\n startSync: true,\n gcTime: 0,\n })\n }\n\n // Handle LiveQueryCollectionConfig objects\n if (opts && typeof opts === `object` && typeof opts.query === `function`) {\n return createLiveQueryCollection(opts)\n }\n\n throw new Error(`Invalid options provided to injectLiveQuery`)\n })\n\n const state = signal(new Map<string | number, any>())\n const data = signal<Array<any>>([])\n const status = signal<CollectionStatus | `disabled`>(\n collection() ? `idle` : `disabled`\n )\n\n const syncDataFromCollection = (\n currentCollection: Collection<any, any, any>\n ) => {\n const newState = new Map(currentCollection.entries())\n const newData = Array.from(currentCollection.values())\n\n state.set(newState)\n data.set(newData)\n status.set(currentCollection.status)\n }\n\n let unsub: (() => void) | null = null\n const cleanup = () => {\n unsub?.()\n unsub = null\n }\n\n effect((onCleanup) => {\n const currentCollection = collection()\n\n // Handle null collection (disabled query)\n if (!currentCollection) {\n status.set(`disabled` as const)\n state.set(new Map())\n data.set([])\n cleanup()\n return\n }\n\n cleanup()\n\n // Initialize immediately with current state\n syncDataFromCollection(currentCollection)\n\n // Start sync if idle\n if (currentCollection.status === `idle`) {\n currentCollection.startSyncImmediate()\n // Update status after starting sync\n status.set(currentCollection.status)\n }\n\n // Subscribe to changes\n const subscription = currentCollection.subscribeChanges(\n (_: Array<ChangeMessage<any>>) => {\n syncDataFromCollection(currentCollection)\n }\n )\n unsub = subscription.unsubscribe.bind(subscription)\n\n // Handle ready state\n currentCollection.onFirstReady(() => {\n status.set(currentCollection.status)\n })\n\n onCleanup(cleanup)\n })\n\n destroyRef.onDestroy(cleanup)\n\n return {\n state,\n data,\n collection,\n status,\n isLoading: computed(() => status() === `loading`),\n isReady: computed(() => status() === `ready` || status() === `disabled`),\n isIdle: computed(() => status() === `idle`),\n isError: computed(() => status() === `error`),\n isCleanedUp: computed(() => status() === `cleaned-up`),\n }\n}\n"],"names":["assertInInjectionContext","inject","DestroyRef","computed","BaseQueryBuilder","createLiveQueryCollection","signal","effect"],"mappings":"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"}
@@ -9,10 +9,10 @@ export interface InjectLiveQueryResult<TResult extends object = any, TKey extend
9
9
  state: Signal<Map<TKey, TResult>>;
10
10
  /** A signal containing the results as an array */
11
11
  data: Signal<Array<TResult>>;
12
- /** A signal containing the underlying collection instance */
13
- collection: Signal<Collection<TResult, TKey, TUtils>>;
12
+ /** A signal containing the underlying collection instance (null for disabled queries) */
13
+ collection: Signal<Collection<TResult, TKey, TUtils> | null>;
14
14
  /** A signal containing the current status of the collection */
15
- status: Signal<CollectionStatus>;
15
+ status: Signal<CollectionStatus | `disabled`>;
16
16
  /** A signal indicating whether the collection is currently loading */
17
17
  isLoading: Signal<boolean>;
18
18
  /** A signal indicating whether the collection is ready */
@@ -31,6 +31,14 @@ export declare function injectLiveQuery<TContext extends Context, TParams extend
31
31
  q: InitialQueryBuilder;
32
32
  }) => QueryBuilder<TContext>;
33
33
  }): InjectLiveQueryResult<GetResult<TContext>>;
34
+ export declare function injectLiveQuery<TContext extends Context, TParams extends any>(options: {
35
+ params: () => TParams;
36
+ query: (args: {
37
+ params: TParams;
38
+ q: InitialQueryBuilder;
39
+ }) => QueryBuilder<TContext> | undefined | null;
40
+ }): InjectLiveQueryResult<GetResult<TContext>>;
34
41
  export declare function injectLiveQuery<TContext extends Context>(queryFn: (q: InitialQueryBuilder) => QueryBuilder<TContext>): InjectLiveQueryResult<GetResult<TContext>>;
42
+ export declare function injectLiveQuery<TContext extends Context>(queryFn: (q: InitialQueryBuilder) => QueryBuilder<TContext> | undefined | null): InjectLiveQueryResult<GetResult<TContext>>;
35
43
  export declare function injectLiveQuery<TContext extends Context>(config: LiveQueryCollectionConfig<TContext>): InjectLiveQueryResult<GetResult<TContext>>;
36
44
  export declare function injectLiveQuery<TResult extends object, TKey extends string | number, TUtils extends Record<string, any>>(liveQueryCollection: Collection<TResult, TKey, TUtils>): InjectLiveQueryResult<TResult, TKey, TUtils>;
@@ -9,10 +9,10 @@ export interface InjectLiveQueryResult<TResult extends object = any, TKey extend
9
9
  state: Signal<Map<TKey, TResult>>;
10
10
  /** A signal containing the results as an array */
11
11
  data: Signal<Array<TResult>>;
12
- /** A signal containing the underlying collection instance */
13
- collection: Signal<Collection<TResult, TKey, TUtils>>;
12
+ /** A signal containing the underlying collection instance (null for disabled queries) */
13
+ collection: Signal<Collection<TResult, TKey, TUtils> | null>;
14
14
  /** A signal containing the current status of the collection */
15
- status: Signal<CollectionStatus>;
15
+ status: Signal<CollectionStatus | `disabled`>;
16
16
  /** A signal indicating whether the collection is currently loading */
17
17
  isLoading: Signal<boolean>;
18
18
  /** A signal indicating whether the collection is ready */
@@ -31,6 +31,14 @@ export declare function injectLiveQuery<TContext extends Context, TParams extend
31
31
  q: InitialQueryBuilder;
32
32
  }) => QueryBuilder<TContext>;
33
33
  }): InjectLiveQueryResult<GetResult<TContext>>;
34
+ export declare function injectLiveQuery<TContext extends Context, TParams extends any>(options: {
35
+ params: () => TParams;
36
+ query: (args: {
37
+ params: TParams;
38
+ q: InitialQueryBuilder;
39
+ }) => QueryBuilder<TContext> | undefined | null;
40
+ }): InjectLiveQueryResult<GetResult<TContext>>;
34
41
  export declare function injectLiveQuery<TContext extends Context>(queryFn: (q: InitialQueryBuilder) => QueryBuilder<TContext>): InjectLiveQueryResult<GetResult<TContext>>;
42
+ export declare function injectLiveQuery<TContext extends Context>(queryFn: (q: InitialQueryBuilder) => QueryBuilder<TContext> | undefined | null): InjectLiveQueryResult<GetResult<TContext>>;
35
43
  export declare function injectLiveQuery<TContext extends Context>(config: LiveQueryCollectionConfig<TContext>): InjectLiveQueryResult<GetResult<TContext>>;
36
44
  export declare function injectLiveQuery<TResult extends object, TKey extends string | number, TUtils extends Record<string, any>>(liveQueryCollection: Collection<TResult, TKey, TUtils>): InjectLiveQueryResult<TResult, TKey, TUtils>;
package/dist/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { assertInInjectionContext, inject, DestroyRef, computed, signal, effect } from "@angular/core";
2
- import { createLiveQueryCollection } from "@tanstack/db";
2
+ import { BaseQueryBuilder, createLiveQueryCollection } from "@tanstack/db";
3
3
  function injectLiveQuery(opts) {
4
4
  assertInInjectionContext(injectLiveQuery);
5
5
  const destroyRef = inject(DestroyRef);
@@ -9,6 +9,11 @@ function injectLiveQuery(opts) {
9
9
  return opts;
10
10
  }
11
11
  if (typeof opts === `function`) {
12
+ const queryBuilder = new BaseQueryBuilder();
13
+ const result = opts(queryBuilder);
14
+ if (result === void 0 || result === null) {
15
+ return null;
16
+ }
12
17
  return createLiveQueryCollection({
13
18
  query: opts,
14
19
  startSync: true,
@@ -19,6 +24,11 @@ function injectLiveQuery(opts) {
19
24
  if (isReactiveQueryOptions) {
20
25
  const { params, query } = opts;
21
26
  const currentParams = params();
27
+ const queryBuilder = new BaseQueryBuilder();
28
+ const result = query({ params: currentParams, q: queryBuilder });
29
+ if (result === void 0 || result === null) {
30
+ return null;
31
+ }
22
32
  return createLiveQueryCollection({
23
33
  query: (q) => query({ params: currentParams, q }),
24
34
  startSync: true,
@@ -32,7 +42,9 @@ function injectLiveQuery(opts) {
32
42
  });
33
43
  const state = signal(/* @__PURE__ */ new Map());
34
44
  const data = signal([]);
35
- const status = signal(`idle`);
45
+ const status = signal(
46
+ collection() ? `idle` : `disabled`
47
+ );
36
48
  const syncDataFromCollection = (currentCollection) => {
37
49
  const newState = new Map(currentCollection.entries());
38
50
  const newData = Array.from(currentCollection.values());
@@ -48,6 +60,10 @@ function injectLiveQuery(opts) {
48
60
  effect((onCleanup) => {
49
61
  const currentCollection = collection();
50
62
  if (!currentCollection) {
63
+ status.set(`disabled`);
64
+ state.set(/* @__PURE__ */ new Map());
65
+ data.set([]);
66
+ cleanup();
51
67
  return;
52
68
  }
53
69
  cleanup();
@@ -74,7 +90,7 @@ function injectLiveQuery(opts) {
74
90
  collection,
75
91
  status,
76
92
  isLoading: computed(() => status() === `loading`),
77
- isReady: computed(() => status() === `ready`),
93
+ isReady: computed(() => status() === `ready` || status() === `disabled`),
78
94
  isIdle: computed(() => status() === `idle`),
79
95
  isError: computed(() => status() === `error`),
80
96
  isCleanedUp: computed(() => status() === `cleaned-up`)
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/index.ts"],"sourcesContent":["import {\n DestroyRef,\n assertInInjectionContext,\n computed,\n effect,\n inject,\n signal,\n} from \"@angular/core\"\nimport { createLiveQueryCollection } from \"@tanstack/db\"\nimport type {\n ChangeMessage,\n Collection,\n CollectionStatus,\n Context,\n GetResult,\n InitialQueryBuilder,\n LiveQueryCollectionConfig,\n QueryBuilder,\n} from \"@tanstack/db\"\nimport type { Signal } from \"@angular/core\"\n\n/**\n * The result of calling `injectLiveQuery`.\n * Contains reactive signals for the query state and data.\n */\nexport interface InjectLiveQueryResult<\n TResult extends object = any,\n TKey extends string | number = string | number,\n TUtils extends Record<string, any> = {},\n> {\n /** A signal containing the complete state map of results keyed by their ID */\n state: Signal<Map<TKey, TResult>>\n /** A signal containing the results as an array */\n data: Signal<Array<TResult>>\n /** A signal containing the underlying collection instance */\n collection: Signal<Collection<TResult, TKey, TUtils>>\n /** A signal containing the current status of the collection */\n status: Signal<CollectionStatus>\n /** A signal indicating whether the collection is currently loading */\n isLoading: Signal<boolean>\n /** A signal indicating whether the collection is ready */\n isReady: Signal<boolean>\n /** A signal indicating whether the collection is idle */\n isIdle: Signal<boolean>\n /** A signal indicating whether the collection has an error */\n isError: Signal<boolean>\n /** A signal indicating whether the collection has been cleaned up */\n isCleanedUp: Signal<boolean>\n}\n\nexport function injectLiveQuery<\n TContext extends Context,\n TParams extends any,\n>(options: {\n params: () => TParams\n query: (args: {\n params: TParams\n q: InitialQueryBuilder\n }) => QueryBuilder<TContext>\n}): InjectLiveQueryResult<GetResult<TContext>>\nexport function injectLiveQuery<TContext extends Context>(\n queryFn: (q: InitialQueryBuilder) => QueryBuilder<TContext>\n): InjectLiveQueryResult<GetResult<TContext>>\nexport function injectLiveQuery<TContext extends Context>(\n config: LiveQueryCollectionConfig<TContext>\n): InjectLiveQueryResult<GetResult<TContext>>\nexport function injectLiveQuery<\n TResult extends object,\n TKey extends string | number,\n TUtils extends Record<string, any>,\n>(\n liveQueryCollection: Collection<TResult, TKey, TUtils>\n): InjectLiveQueryResult<TResult, TKey, TUtils>\nexport function injectLiveQuery(opts: any) {\n assertInInjectionContext(injectLiveQuery)\n const destroyRef = inject(DestroyRef)\n\n const collection = computed(() => {\n // Check if it's an existing collection\n const isExistingCollection =\n opts &&\n typeof opts === `object` &&\n typeof opts.subscribeChanges === `function` &&\n typeof opts.startSyncImmediate === `function` &&\n typeof opts.id === `string`\n\n if (isExistingCollection) {\n return opts\n }\n\n if (typeof opts === `function`) {\n return createLiveQueryCollection({\n query: opts,\n startSync: true,\n gcTime: 0,\n })\n }\n\n // Check if it's reactive query options\n const isReactiveQueryOptions =\n opts &&\n typeof opts === `object` &&\n typeof opts.query === `function` &&\n typeof opts.params === `function`\n\n if (isReactiveQueryOptions) {\n const { params, query } = opts\n const currentParams = params()\n return createLiveQueryCollection({\n query: (q) => query({ params: currentParams, q }),\n startSync: true,\n gcTime: 0,\n })\n }\n\n // Handle LiveQueryCollectionConfig objects\n if (opts && typeof opts === `object` && typeof opts.query === `function`) {\n return createLiveQueryCollection(opts)\n }\n\n throw new Error(`Invalid options provided to injectLiveQuery`)\n })\n\n const state = signal(new Map<string | number, any>())\n const data = signal<Array<any>>([])\n const status = signal<CollectionStatus>(`idle`)\n\n const syncDataFromCollection = (\n currentCollection: Collection<any, any, any>\n ) => {\n const newState = new Map(currentCollection.entries())\n const newData = Array.from(currentCollection.values())\n\n state.set(newState)\n data.set(newData)\n status.set(currentCollection.status)\n }\n\n let unsub: (() => void) | null = null\n const cleanup = () => {\n unsub?.()\n unsub = null\n }\n\n effect((onCleanup) => {\n const currentCollection = collection()\n\n if (!currentCollection) {\n return\n }\n\n cleanup()\n\n // Initialize immediately with current state\n syncDataFromCollection(currentCollection)\n\n // Start sync if idle\n if (currentCollection.status === `idle`) {\n currentCollection.startSyncImmediate()\n // Update status after starting sync\n status.set(currentCollection.status)\n }\n\n // Subscribe to changes\n const subscription = currentCollection.subscribeChanges(\n (_: Array<ChangeMessage<any>>) => {\n syncDataFromCollection(currentCollection)\n }\n )\n unsub = subscription.unsubscribe.bind(subscription)\n\n // Handle ready state\n currentCollection.onFirstReady(() => {\n status.set(currentCollection.status)\n })\n\n onCleanup(cleanup)\n })\n\n destroyRef.onDestroy(cleanup)\n\n return {\n state,\n data,\n collection,\n status,\n isLoading: computed(() => status() === `loading`),\n isReady: computed(() => status() === `ready`),\n isIdle: computed(() => status() === `idle`),\n isError: computed(() => status() === `error`),\n isCleanedUp: computed(() => status() === `cleaned-up`),\n }\n}\n"],"names":[],"mappings":";;AAyEO,SAAS,gBAAgB,MAAW;AACzC,2BAAyB,eAAe;AACxC,QAAM,aAAa,OAAO,UAAU;AAEpC,QAAM,aAAa,SAAS,MAAM;AAEhC,UAAM,uBACJ,QACA,OAAO,SAAS,YAChB,OAAO,KAAK,qBAAqB,cACjC,OAAO,KAAK,uBAAuB,cACnC,OAAO,KAAK,OAAO;AAErB,QAAI,sBAAsB;AACxB,aAAO;AAAA,IACT;AAEA,QAAI,OAAO,SAAS,YAAY;AAC9B,aAAO,0BAA0B;AAAA,QAC/B,OAAO;AAAA,QACP,WAAW;AAAA,QACX,QAAQ;AAAA,MAAA,CACT;AAAA,IACH;AAGA,UAAM,yBACJ,QACA,OAAO,SAAS,YAChB,OAAO,KAAK,UAAU,cACtB,OAAO,KAAK,WAAW;AAEzB,QAAI,wBAAwB;AAC1B,YAAM,EAAE,QAAQ,MAAA,IAAU;AAC1B,YAAM,gBAAgB,OAAA;AACtB,aAAO,0BAA0B;AAAA,QAC/B,OAAO,CAAC,MAAM,MAAM,EAAE,QAAQ,eAAe,GAAG;AAAA,QAChD,WAAW;AAAA,QACX,QAAQ;AAAA,MAAA,CACT;AAAA,IACH;AAGA,QAAI,QAAQ,OAAO,SAAS,YAAY,OAAO,KAAK,UAAU,YAAY;AACxE,aAAO,0BAA0B,IAAI;AAAA,IACvC;AAEA,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC/D,CAAC;AAED,QAAM,QAAQ,OAAO,oBAAI,KAA2B;AACpD,QAAM,OAAO,OAAmB,EAAE;AAClC,QAAM,SAAS,OAAyB,MAAM;AAE9C,QAAM,yBAAyB,CAC7B,sBACG;AACH,UAAM,WAAW,IAAI,IAAI,kBAAkB,SAAS;AACpD,UAAM,UAAU,MAAM,KAAK,kBAAkB,QAAQ;AAErD,UAAM,IAAI,QAAQ;AAClB,SAAK,IAAI,OAAO;AAChB,WAAO,IAAI,kBAAkB,MAAM;AAAA,EACrC;AAEA,MAAI,QAA6B;AACjC,QAAM,UAAU,MAAM;AACpB,YAAA;AACA,YAAQ;AAAA,EACV;AAEA,SAAO,CAAC,cAAc;AACpB,UAAM,oBAAoB,WAAA;AAE1B,QAAI,CAAC,mBAAmB;AACtB;AAAA,IACF;AAEA,YAAA;AAGA,2BAAuB,iBAAiB;AAGxC,QAAI,kBAAkB,WAAW,QAAQ;AACvC,wBAAkB,mBAAA;AAElB,aAAO,IAAI,kBAAkB,MAAM;AAAA,IACrC;AAGA,UAAM,eAAe,kBAAkB;AAAA,MACrC,CAAC,MAAiC;AAChC,+BAAuB,iBAAiB;AAAA,MAC1C;AAAA,IAAA;AAEF,YAAQ,aAAa,YAAY,KAAK,YAAY;AAGlD,sBAAkB,aAAa,MAAM;AACnC,aAAO,IAAI,kBAAkB,MAAM;AAAA,IACrC,CAAC;AAED,cAAU,OAAO;AAAA,EACnB,CAAC;AAED,aAAW,UAAU,OAAO;AAE5B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW,SAAS,MAAM,OAAA,MAAa,SAAS;AAAA,IAChD,SAAS,SAAS,MAAM,OAAA,MAAa,OAAO;AAAA,IAC5C,QAAQ,SAAS,MAAM,OAAA,MAAa,MAAM;AAAA,IAC1C,SAAS,SAAS,MAAM,OAAA,MAAa,OAAO;AAAA,IAC5C,aAAa,SAAS,MAAM,OAAA,MAAa,YAAY;AAAA,EAAA;AAEzD;"}
1
+ {"version":3,"file":"index.js","sources":["../../src/index.ts"],"sourcesContent":["import {\n DestroyRef,\n assertInInjectionContext,\n computed,\n effect,\n inject,\n signal,\n} from \"@angular/core\"\nimport { BaseQueryBuilder, createLiveQueryCollection } from \"@tanstack/db\"\nimport type {\n ChangeMessage,\n Collection,\n CollectionStatus,\n Context,\n GetResult,\n InitialQueryBuilder,\n LiveQueryCollectionConfig,\n QueryBuilder,\n} from \"@tanstack/db\"\nimport type { Signal } from \"@angular/core\"\n\n/**\n * The result of calling `injectLiveQuery`.\n * Contains reactive signals for the query state and data.\n */\nexport interface InjectLiveQueryResult<\n TResult extends object = any,\n TKey extends string | number = string | number,\n TUtils extends Record<string, any> = {},\n> {\n /** A signal containing the complete state map of results keyed by their ID */\n state: Signal<Map<TKey, TResult>>\n /** A signal containing the results as an array */\n data: Signal<Array<TResult>>\n /** A signal containing the underlying collection instance (null for disabled queries) */\n collection: Signal<Collection<TResult, TKey, TUtils> | null>\n /** A signal containing the current status of the collection */\n status: Signal<CollectionStatus | `disabled`>\n /** A signal indicating whether the collection is currently loading */\n isLoading: Signal<boolean>\n /** A signal indicating whether the collection is ready */\n isReady: Signal<boolean>\n /** A signal indicating whether the collection is idle */\n isIdle: Signal<boolean>\n /** A signal indicating whether the collection has an error */\n isError: Signal<boolean>\n /** A signal indicating whether the collection has been cleaned up */\n isCleanedUp: Signal<boolean>\n}\n\nexport function injectLiveQuery<\n TContext extends Context,\n TParams extends any,\n>(options: {\n params: () => TParams\n query: (args: {\n params: TParams\n q: InitialQueryBuilder\n }) => QueryBuilder<TContext>\n}): InjectLiveQueryResult<GetResult<TContext>>\nexport function injectLiveQuery<\n TContext extends Context,\n TParams extends any,\n>(options: {\n params: () => TParams\n query: (args: {\n params: TParams\n q: InitialQueryBuilder\n }) => QueryBuilder<TContext> | undefined | null\n}): InjectLiveQueryResult<GetResult<TContext>>\nexport function injectLiveQuery<TContext extends Context>(\n queryFn: (q: InitialQueryBuilder) => QueryBuilder<TContext>\n): InjectLiveQueryResult<GetResult<TContext>>\nexport function injectLiveQuery<TContext extends Context>(\n queryFn: (q: InitialQueryBuilder) => QueryBuilder<TContext> | undefined | null\n): InjectLiveQueryResult<GetResult<TContext>>\nexport function injectLiveQuery<TContext extends Context>(\n config: LiveQueryCollectionConfig<TContext>\n): InjectLiveQueryResult<GetResult<TContext>>\nexport function injectLiveQuery<\n TResult extends object,\n TKey extends string | number,\n TUtils extends Record<string, any>,\n>(\n liveQueryCollection: Collection<TResult, TKey, TUtils>\n): InjectLiveQueryResult<TResult, TKey, TUtils>\nexport function injectLiveQuery(opts: any) {\n assertInInjectionContext(injectLiveQuery)\n const destroyRef = inject(DestroyRef)\n\n const collection = computed(() => {\n // Check if it's an existing collection\n const isExistingCollection =\n opts &&\n typeof opts === `object` &&\n typeof opts.subscribeChanges === `function` &&\n typeof opts.startSyncImmediate === `function` &&\n typeof opts.id === `string`\n\n if (isExistingCollection) {\n return opts\n }\n\n if (typeof opts === `function`) {\n // Check if query function returns null/undefined (disabled query)\n const queryBuilder = new BaseQueryBuilder() as InitialQueryBuilder\n const result = opts(queryBuilder)\n\n if (result === undefined || result === null) {\n // Disabled query - return null\n return null\n }\n\n return createLiveQueryCollection({\n query: opts,\n startSync: true,\n gcTime: 0,\n })\n }\n\n // Check if it's reactive query options\n const isReactiveQueryOptions =\n opts &&\n typeof opts === `object` &&\n typeof opts.query === `function` &&\n typeof opts.params === `function`\n\n if (isReactiveQueryOptions) {\n const { params, query } = opts\n const currentParams = params()\n\n // Check if query function returns null/undefined (disabled query)\n const queryBuilder = new BaseQueryBuilder() as InitialQueryBuilder\n const result = query({ params: currentParams, q: queryBuilder })\n\n if (result === undefined || result === null) {\n // Disabled query - return null\n return null\n }\n\n return createLiveQueryCollection({\n query: (q) => query({ params: currentParams, q }),\n startSync: true,\n gcTime: 0,\n })\n }\n\n // Handle LiveQueryCollectionConfig objects\n if (opts && typeof opts === `object` && typeof opts.query === `function`) {\n return createLiveQueryCollection(opts)\n }\n\n throw new Error(`Invalid options provided to injectLiveQuery`)\n })\n\n const state = signal(new Map<string | number, any>())\n const data = signal<Array<any>>([])\n const status = signal<CollectionStatus | `disabled`>(\n collection() ? `idle` : `disabled`\n )\n\n const syncDataFromCollection = (\n currentCollection: Collection<any, any, any>\n ) => {\n const newState = new Map(currentCollection.entries())\n const newData = Array.from(currentCollection.values())\n\n state.set(newState)\n data.set(newData)\n status.set(currentCollection.status)\n }\n\n let unsub: (() => void) | null = null\n const cleanup = () => {\n unsub?.()\n unsub = null\n }\n\n effect((onCleanup) => {\n const currentCollection = collection()\n\n // Handle null collection (disabled query)\n if (!currentCollection) {\n status.set(`disabled` as const)\n state.set(new Map())\n data.set([])\n cleanup()\n return\n }\n\n cleanup()\n\n // Initialize immediately with current state\n syncDataFromCollection(currentCollection)\n\n // Start sync if idle\n if (currentCollection.status === `idle`) {\n currentCollection.startSyncImmediate()\n // Update status after starting sync\n status.set(currentCollection.status)\n }\n\n // Subscribe to changes\n const subscription = currentCollection.subscribeChanges(\n (_: Array<ChangeMessage<any>>) => {\n syncDataFromCollection(currentCollection)\n }\n )\n unsub = subscription.unsubscribe.bind(subscription)\n\n // Handle ready state\n currentCollection.onFirstReady(() => {\n status.set(currentCollection.status)\n })\n\n onCleanup(cleanup)\n })\n\n destroyRef.onDestroy(cleanup)\n\n return {\n state,\n data,\n collection,\n status,\n isLoading: computed(() => status() === `loading`),\n isReady: computed(() => status() === `ready` || status() === `disabled`),\n isIdle: computed(() => status() === `idle`),\n isError: computed(() => status() === `error`),\n isCleanedUp: computed(() => status() === `cleaned-up`),\n }\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tanstack/angular-db",
3
3
  "description": "Angular integration for @tanstack/db",
4
- "version": "0.1.36",
4
+ "version": "0.1.37",
5
5
  "author": "Ethan McDaniel",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -16,7 +16,7 @@
16
16
  "typescript"
17
17
  ],
18
18
  "dependencies": {
19
- "@tanstack/db": "0.5.10"
19
+ "@tanstack/db": "0.5.11"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@angular/common": "^19.2.15",
package/src/index.ts CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  inject,
7
7
  signal,
8
8
  } from "@angular/core"
9
- import { createLiveQueryCollection } from "@tanstack/db"
9
+ import { BaseQueryBuilder, createLiveQueryCollection } from "@tanstack/db"
10
10
  import type {
11
11
  ChangeMessage,
12
12
  Collection,
@@ -32,10 +32,10 @@ export interface InjectLiveQueryResult<
32
32
  state: Signal<Map<TKey, TResult>>
33
33
  /** A signal containing the results as an array */
34
34
  data: Signal<Array<TResult>>
35
- /** A signal containing the underlying collection instance */
36
- collection: Signal<Collection<TResult, TKey, TUtils>>
35
+ /** A signal containing the underlying collection instance (null for disabled queries) */
36
+ collection: Signal<Collection<TResult, TKey, TUtils> | null>
37
37
  /** A signal containing the current status of the collection */
38
- status: Signal<CollectionStatus>
38
+ status: Signal<CollectionStatus | `disabled`>
39
39
  /** A signal indicating whether the collection is currently loading */
40
40
  isLoading: Signal<boolean>
41
41
  /** A signal indicating whether the collection is ready */
@@ -58,9 +58,22 @@ export function injectLiveQuery<
58
58
  q: InitialQueryBuilder
59
59
  }) => QueryBuilder<TContext>
60
60
  }): InjectLiveQueryResult<GetResult<TContext>>
61
+ export function injectLiveQuery<
62
+ TContext extends Context,
63
+ TParams extends any,
64
+ >(options: {
65
+ params: () => TParams
66
+ query: (args: {
67
+ params: TParams
68
+ q: InitialQueryBuilder
69
+ }) => QueryBuilder<TContext> | undefined | null
70
+ }): InjectLiveQueryResult<GetResult<TContext>>
61
71
  export function injectLiveQuery<TContext extends Context>(
62
72
  queryFn: (q: InitialQueryBuilder) => QueryBuilder<TContext>
63
73
  ): InjectLiveQueryResult<GetResult<TContext>>
74
+ export function injectLiveQuery<TContext extends Context>(
75
+ queryFn: (q: InitialQueryBuilder) => QueryBuilder<TContext> | undefined | null
76
+ ): InjectLiveQueryResult<GetResult<TContext>>
64
77
  export function injectLiveQuery<TContext extends Context>(
65
78
  config: LiveQueryCollectionConfig<TContext>
66
79
  ): InjectLiveQueryResult<GetResult<TContext>>
@@ -89,6 +102,15 @@ export function injectLiveQuery(opts: any) {
89
102
  }
90
103
 
91
104
  if (typeof opts === `function`) {
105
+ // Check if query function returns null/undefined (disabled query)
106
+ const queryBuilder = new BaseQueryBuilder() as InitialQueryBuilder
107
+ const result = opts(queryBuilder)
108
+
109
+ if (result === undefined || result === null) {
110
+ // Disabled query - return null
111
+ return null
112
+ }
113
+
92
114
  return createLiveQueryCollection({
93
115
  query: opts,
94
116
  startSync: true,
@@ -106,6 +128,16 @@ export function injectLiveQuery(opts: any) {
106
128
  if (isReactiveQueryOptions) {
107
129
  const { params, query } = opts
108
130
  const currentParams = params()
131
+
132
+ // Check if query function returns null/undefined (disabled query)
133
+ const queryBuilder = new BaseQueryBuilder() as InitialQueryBuilder
134
+ const result = query({ params: currentParams, q: queryBuilder })
135
+
136
+ if (result === undefined || result === null) {
137
+ // Disabled query - return null
138
+ return null
139
+ }
140
+
109
141
  return createLiveQueryCollection({
110
142
  query: (q) => query({ params: currentParams, q }),
111
143
  startSync: true,
@@ -123,7 +155,9 @@ export function injectLiveQuery(opts: any) {
123
155
 
124
156
  const state = signal(new Map<string | number, any>())
125
157
  const data = signal<Array<any>>([])
126
- const status = signal<CollectionStatus>(`idle`)
158
+ const status = signal<CollectionStatus | `disabled`>(
159
+ collection() ? `idle` : `disabled`
160
+ )
127
161
 
128
162
  const syncDataFromCollection = (
129
163
  currentCollection: Collection<any, any, any>
@@ -145,7 +179,12 @@ export function injectLiveQuery(opts: any) {
145
179
  effect((onCleanup) => {
146
180
  const currentCollection = collection()
147
181
 
182
+ // Handle null collection (disabled query)
148
183
  if (!currentCollection) {
184
+ status.set(`disabled` as const)
185
+ state.set(new Map())
186
+ data.set([])
187
+ cleanup()
149
188
  return
150
189
  }
151
190
 
@@ -185,7 +224,7 @@ export function injectLiveQuery(opts: any) {
185
224
  collection,
186
225
  status,
187
226
  isLoading: computed(() => status() === `loading`),
188
- isReady: computed(() => status() === `ready`),
227
+ isReady: computed(() => status() === `ready` || status() === `disabled`),
189
228
  isIdle: computed(() => status() === `idle`),
190
229
  isError: computed(() => status() === `error`),
191
230
  isCleanedUp: computed(() => status() === `cleaned-up`),