@aiao/rxdb-angular 0.0.7 → 0.0.9

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.
Files changed (42) hide show
  1. package/LICENSE +21 -0
  2. package/fesm2022/aiao-rxdb-angular.mjs +423 -0
  3. package/fesm2022/aiao-rxdb-angular.mjs.map +1 -0
  4. package/package.json +26 -13
  5. package/types/aiao-rxdb-angular.d.ts +222 -0
  6. package/eslint.config.mjs +0 -58
  7. package/ng-package.json +0 -7
  8. package/project.json +0 -48
  9. package/src/InfiniteScrollingList.ts +0 -123
  10. package/src/devtools/devtools.html +0 -99
  11. package/src/devtools/devtools.interface.ts +0 -3
  12. package/src/devtools/devtools.scss +0 -49
  13. package/src/devtools/devtools.spec.ts +0 -30
  14. package/src/devtools/devtools.ts +0 -207
  15. package/src/devtools/entity-table-item.ts +0 -47
  16. package/src/devtools/entity-table-tools.html +0 -56
  17. package/src/devtools/entity-table-tools.scss +0 -8
  18. package/src/devtools/entity-table-tools.ts +0 -153
  19. package/src/devtools/event-tools.html +0 -15
  20. package/src/devtools/event-tools.scss +0 -18
  21. package/src/devtools/event-tools.ts +0 -45
  22. package/src/devtools/scroll-advanced-calc.service.ts +0 -41
  23. package/src/devtools/settings.html +0 -46
  24. package/src/devtools/settings.scss +0 -19
  25. package/src/devtools/settings.ts +0 -122
  26. package/src/hooks.ts +0 -307
  27. package/src/index.ts +0 -7
  28. package/src/rxdb-change-detector.directive.spec.ts +0 -94
  29. package/src/rxdb-change-detector.directive.ts +0 -35
  30. package/src/rxdb.provider.ts +0 -13
  31. package/src/rxdb.service.spec.ts +0 -31
  32. package/src/rxdb.service.ts +0 -35
  33. package/src/test-setup.ts +0 -14
  34. package/src/use-action.spec.ts +0 -88
  35. package/src/use-action.ts +0 -20
  36. package/src/use-state.spec.ts +0 -105
  37. package/src/use-state.ts +0 -28
  38. package/tsconfig.json +0 -33
  39. package/tsconfig.lib.json +0 -42
  40. package/tsconfig.lib.prod.json +0 -10
  41. package/tsconfig.spec.json +0 -23
  42. package/vite.config.mts +0 -55
@@ -1,122 +0,0 @@
1
- import { RxDB, RxDBEvent } from '@aiao/rxdb';
2
- import {
3
- ChangeDetectionStrategy,
4
- Component,
5
- inject,
6
- output,
7
- signal,
8
- TemplateRef,
9
- viewChild,
10
- ViewContainerRef
11
- } from '@angular/core';
12
- import { LucideAngularModule, PanelBottom, PanelLeft, PanelRight } from 'lucide-angular';
13
-
14
- interface FileEntry {
15
- name: string;
16
- path: string;
17
- type: 'file' | 'directory';
18
- handle: FileSystemDirectoryHandle | FileSystemFileHandle;
19
- }
20
-
21
- @Component({
22
- selector: 'rxdb-settings',
23
- imports: [LucideAngularModule],
24
- changeDetection: ChangeDetectionStrategy.OnPush,
25
- styleUrls: ['./settings.scss'],
26
- templateUrl: './settings.html'
27
- })
28
- export class RxDBSettings {
29
- #viewContainerRef = inject(ViewContainerRef);
30
- #rxdb = inject(RxDB);
31
-
32
- protected readonly PanelLeft = PanelLeft;
33
- protected readonly PanelBottom = PanelBottom;
34
- protected readonly PanelRight = PanelRight;
35
-
36
- messageTmp = viewChild<TemplateRef<any>>('message');
37
-
38
- $events = signal<RxDBEvent[]>([]);
39
-
40
- sideChange = output<'right' | 'left' | 'bottom'>();
41
-
42
- async delete_db() {
43
- try {
44
- await this.#rxdb.disconnectAll();
45
- } catch {
46
- //
47
- }
48
-
49
- try {
50
- const root = await navigator.storage.getDirectory();
51
- const files = await this.listAllFiles(root, 1);
52
- for (const entry of files) {
53
- if (entry.type === 'file') {
54
- await root.removeEntry(entry.name, { recursive: true });
55
- }
56
- }
57
- await this.clean_indexedDB();
58
- localStorage.clear();
59
- // 使用 baseURI 跳转回首页,避免在子路由刷新时因服务器配置问题导致 404 fallback 到主站
60
- window.location.href = document.baseURI;
61
- } catch (error: Error | any) {
62
- if (error && error.name === 'NoModificationAllowedError') {
63
- const ref = this.#viewContainerRef.createEmbeddedView<{ message: string }>(this.messageTmp()!, {
64
- message: '关闭数据库失败,请检查是否在多个浏览器 tab 中打开页面'
65
- });
66
- setTimeout(() => {
67
- ref.destroy();
68
- }, 3000);
69
- }
70
- console.error(error);
71
- }
72
- }
73
-
74
- async clean_indexedDB() {
75
- const dbList = indexedDB.databases ? await indexedDB.databases() : [];
76
- if (dbList.length) {
77
- await Promise.all(
78
- dbList.map(({ name }) => {
79
- return new Promise<void>((resolve, reject) => {
80
- const request = indexedDB.deleteDatabase(name!);
81
- request.onsuccess = () => resolve();
82
- request.onerror = () => reject(request.error);
83
- request.onblocked = () => resolve();
84
- });
85
- })
86
- );
87
- }
88
- }
89
-
90
- async listAllFiles(
91
- directoryHandle: FileSystemDirectoryHandle | any,
92
- maxDeep = Number.MAX_SAFE_INTEGER,
93
- path = '',
94
- currentDeep = 1
95
- ) {
96
- const entries: FileEntry[] = [];
97
- for await (const [name, handle] of directoryHandle) {
98
- const entryPath = path ? `${path}/${name}` : name;
99
- if (handle.kind === 'file') {
100
- entries.push({
101
- name: name,
102
- path: entryPath,
103
- type: 'file',
104
- handle: handle
105
- });
106
- } else if (handle.kind === 'directory') {
107
- entries.push({
108
- name: name,
109
- path: entryPath,
110
- type: 'directory',
111
- handle: handle
112
- });
113
-
114
- if (currentDeep < maxDeep) {
115
- const subEntries = await this.listAllFiles(handle, maxDeep, entryPath, currentDeep + 1);
116
- entries.push(...subEntries);
117
- }
118
- }
119
- }
120
- return entries;
121
- }
122
- }
package/src/hooks.ts DELETED
@@ -1,307 +0,0 @@
1
- import { EntityStaticType, EntityType, TreeEntityType } from '@aiao/rxdb';
2
- import { GraphEntityType } from '@aiao/rxdb-plugin-graph';
3
- import { isFunction } from '@aiao/utils';
4
- import { effect, Signal, signal } from '@angular/core';
5
- import { toLazySignal } from 'ngxtension/to-lazy-signal';
6
- import { Observable, Subscriber, Subscription } from 'rxjs';
7
-
8
- type UseOptions<T> = T | (() => T);
9
-
10
- export interface RxDBResource<T> {
11
- /**
12
- * 资源的值
13
- */
14
- readonly value: Signal<T>;
15
- /**
16
- * 资源的错误
17
- */
18
- readonly error: Signal<Error | undefined>;
19
- /**
20
- * 资源的加载状态
21
- */
22
- readonly isLoading: Signal<boolean>;
23
- /**
24
- * 资源是否为空
25
- */
26
- readonly isEmpty: Signal<boolean | undefined>;
27
- /**
28
- * 资源是否有值
29
- */
30
- readonly hasValue: Signal<boolean>;
31
- }
32
-
33
- export const useRepositoryQuery = <T extends EntityType, RT>(
34
- EntityType: T,
35
- method: string,
36
- defaultValue: any,
37
- options: UseOptions<any>
38
- ): RxDBResource<RT> => {
39
- let _observer: Subscriber<any>;
40
- let sub: Subscription;
41
-
42
- const _has_sub = signal<boolean>(false);
43
- const _refresh = signal<number>(0);
44
-
45
- const _eff = effect(() => {
46
- if (_has_sub() === false) return;
47
- // re-run when refresh is called or options change
48
- _refresh();
49
- const opt = isFunction(options) ? options() : options;
50
- if (sub) sub.unsubscribe();
51
- // reset state for a new request
52
- isLoading.set(true);
53
- error.set(undefined);
54
- hasValue.set(false);
55
- isEmpty.set(undefined);
56
- // 优化:使用 Record<string, any> 替代 any,以提高类型安全性
57
- const func = (EntityType as unknown as Record<string, any>)[method];
58
- sub =
59
- func &&
60
- func(opt).subscribe({
61
- next: (d: any) => {
62
- isLoading.set(false);
63
- hasValue.set(true);
64
- if (Array.isArray(d)) {
65
- isEmpty.set(d.length === 0);
66
- } else if (d == null) {
67
- // null/undefined treated as empty
68
- isEmpty.set(true);
69
- } else {
70
- isEmpty.set(false);
71
- }
72
- _observer.next(d);
73
- },
74
- error: (e: any) => {
75
- isLoading.set(false);
76
- error.set(e);
77
- },
78
- complete: () => {
79
- // ensure loading is false even if observable completes without next
80
- isLoading.set(false);
81
- }
82
- });
83
- });
84
- const ob = new Observable<RT>(observer => {
85
- _has_sub.set(true);
86
- _observer = observer;
87
- _observer.next(defaultValue);
88
- return () => {
89
- _eff.destroy();
90
- sub?.unsubscribe();
91
- };
92
- });
93
-
94
- const value = toLazySignal<RT>(ob, {
95
- initialValue: defaultValue
96
- }) as Signal<RT>;
97
- const error = signal<Error | undefined>(undefined);
98
- const isLoading = signal<boolean>(false);
99
- const hasValue = signal<boolean>(false);
100
- const isEmpty = signal<boolean | undefined>(undefined);
101
- return {
102
- value,
103
- error,
104
- isLoading,
105
- isEmpty,
106
- hasValue
107
- };
108
- };
109
-
110
- /*
111
- * Repository
112
- */
113
-
114
- /**
115
- * 通过 ID 获取单个实体
116
- *
117
- * @param EntityType 实体类
118
- * @param options 实体 ID 或查询参数对象
119
- * @returns 返回包含实体的资源 signal
120
- *
121
- * @example
122
- * ```typescript
123
- * const user = useGet(User, 'user-1');
124
- * ```
125
- */
126
- export const useGet = <T extends EntityType>(EntityType: T, options: UseOptions<EntityStaticType<T, 'getOptions'>>) =>
127
- useRepositoryQuery<T, InstanceType<T>>(EntityType, 'get', undefined, options);
128
-
129
- /**
130
- * 查找第一个匹配条件的实体
131
- *
132
- * @param EntityType 实体类
133
- * @param options 查询参数(where、排序等)
134
- * @returns 返回包含实体的资源 signal
135
- */
136
- export const useFindOne = <T extends EntityType>(
137
- EntityType: T,
138
- options: UseOptions<EntityStaticType<T, 'findOneOptions'>>
139
- ) => useRepositoryQuery<T, InstanceType<T> | undefined>(EntityType, 'findOne', undefined, options);
140
-
141
- /**
142
- * 查找匹配的实体,未找到则抛出错误
143
- *
144
- * @param EntityType 实体类
145
- * @param options 查询参数
146
- * @returns 返回包含实体的资源 signal
147
- */
148
- export const useFindOneOrFail = <T extends EntityType>(
149
- EntityType: T,
150
- options: UseOptions<EntityStaticType<T, 'findOneOrFailOptions'>>
151
- ) => useRepositoryQuery<T, InstanceType<T>>(EntityType, 'findOneOrFail', undefined, options);
152
-
153
- /**
154
- * 查找符合条件的多个实体
155
- *
156
- * @param EntityType 实体类
157
- * @param options 查询参数
158
- * @returns 返回包含实体数组的资源 signal
159
- */
160
- export const useFind = <T extends EntityType>(EntityType: T, options: UseOptions<EntityStaticType<T, 'findOptions'>>) =>
161
- useRepositoryQuery<T, InstanceType<T>[]>(EntityType, 'find', [], options);
162
-
163
- /**
164
- * 使用游标分页查找实体
165
- *
166
- * @param EntityType 实体类
167
- * @param options 游标参数
168
- * @returns 返回包含实体数组的资源 signal
169
- */
170
- export const useFindByCursor = <T extends EntityType>(
171
- EntityType: T,
172
- options: UseOptions<EntityStaticType<T, 'findByCursorOptions'>>
173
- ) => useRepositoryQuery<T, InstanceType<T>[]>(EntityType, 'findByCursor', [], options);
174
-
175
- /**
176
- * 查找全部实体
177
- *
178
- * @param EntityType 实体类
179
- * @param options 查询参数
180
- * @returns 返回包含全部实体的资源 signal
181
- */
182
- export const useFindAll = <T extends EntityType>(
183
- EntityType: T,
184
- options: UseOptions<EntityStaticType<T, 'findAllOptions'>>
185
- ) => useRepositoryQuery<T, InstanceType<T>[]>(EntityType, 'findAll', [], options);
186
-
187
- /**
188
- * 统计满足条件的实体数量
189
- *
190
- * @param EntityType 实体类
191
- * @param options 查询参数
192
- * @returns 返回包含数量的资源 signal
193
- */
194
- export const useCount = <T extends EntityType>(
195
- EntityType: T,
196
- options: UseOptions<EntityStaticType<T, 'countOptions'>>
197
- ) => useRepositoryQuery<T, number>(EntityType, 'count', undefined, options);
198
-
199
- /*
200
- * TreeRepository
201
- */
202
-
203
- /**
204
- * 查找树结构中的所有子孙实体
205
- *
206
- * @param EntityType 实体类
207
- * @param options 树查询参数(entityId、深度等)
208
- * @returns 返回包含子孙实体的资源 signal
209
- */
210
- export const useFindDescendants = <T extends TreeEntityType>(
211
- EntityType: T,
212
- options: UseOptions<EntityStaticType<T, 'findTreeOptions'>>
213
- ) => useRepositoryQuery<T, InstanceType<T>[]>(EntityType, 'findDescendants', [], options);
214
-
215
- /**
216
- * 统计树结构中的子孙数量
217
- *
218
- * @param EntityType 实体类
219
- * @param options 树查询参数
220
- * @returns 返回包含数量的资源 signal
221
- */
222
- export const useCountDescendants = <T extends TreeEntityType>(
223
- EntityType: T,
224
- options: UseOptions<EntityStaticType<T, 'findTreeOptions'>>
225
- ) => useRepositoryQuery<T, number>(EntityType, 'countDescendants', undefined, options);
226
-
227
- /**
228
- * 查找树结构中的所有祖先实体
229
- *
230
- * @param EntityType 实体类
231
- * @param options 树查询参数
232
- * @returns 返回包含祖先实体的资源 signal
233
- */
234
- export const useFindAncestors = <T extends TreeEntityType>(
235
- EntityType: T,
236
- options: UseOptions<EntityStaticType<T, 'findTreeOptions'>>
237
- ) => useRepositoryQuery<T, InstanceType<T>[]>(EntityType, 'findAncestors', [], options);
238
-
239
- /**
240
- * 统计树结构中的祖先数量
241
- *
242
- * @param EntityType 实体类
243
- * @param options 树查询参数
244
- * @returns 返回包含数量的资源 signal
245
- */
246
- export const useCountAncestors = <T extends TreeEntityType>(
247
- EntityType: T,
248
- options: UseOptions<EntityStaticType<T, 'findTreeOptions'>>
249
- ) => useRepositoryQuery<T, number>(EntityType, 'countAncestors', undefined, options);
250
-
251
- /*
252
- * GraphRepository
253
- */
254
-
255
- /**
256
- * 查找图结构中的邻接实体
257
- *
258
- * @param EntityType 实体类
259
- * @param options 图查询参数(entityId、方向、层级等)
260
- * @returns 返回包含邻居实体的资源 signal
261
- *
262
- * @example
263
- * ```typescript
264
- * const friends = useGraphNeighbors(User, {
265
- * entityId: 'user-1',
266
- * direction: 'out',
267
- * level: 1
268
- * });
269
- * ```
270
- */
271
- export const useGraphNeighbors = <T extends GraphEntityType>(
272
- EntityType: T,
273
- options: UseOptions<EntityStaticType<T, 'findNeighborsOptions'>>
274
- ) => useRepositoryQuery<T, InstanceType<T>[]>(EntityType, 'findNeighbors', [], options);
275
-
276
- /**
277
- * 统计图结构中的邻接数量
278
- *
279
- * @param EntityType 实体类
280
- * @param options 图查询参数
281
- * @returns 返回包含数量的资源 signal
282
- */
283
- export const useCountNeighbors = <T extends GraphEntityType>(
284
- EntityType: T,
285
- options: UseOptions<EntityStaticType<T, 'findNeighborsOptions'>>
286
- ) => useRepositoryQuery<T, number>(EntityType, 'countNeighbors', 0, options);
287
-
288
- /**
289
- * 查找图结构中两个实体之间的路径
290
- *
291
- * @param EntityType 实体类
292
- * @param options 路径查询参数(fromId、toId、最大深度等)
293
- * @returns 返回包含路径的资源 signal
294
- *
295
- * @example
296
- * ```typescript
297
- * const paths = useGraphPaths(User, {
298
- * fromId: 'user-1',
299
- * toId: 'user-2',
300
- * maxDepth: 5
301
- * });
302
- * ```
303
- */
304
- export const useGraphPaths = <T extends GraphEntityType>(
305
- EntityType: T,
306
- options: UseOptions<EntityStaticType<T, 'findPathsOptions'>>
307
- ) => useRepositoryQuery<T, any[]>(EntityType, 'findPaths', [], options);
package/src/index.ts DELETED
@@ -1,7 +0,0 @@
1
- export * from './hooks';
2
- export * from './InfiniteScrollingList';
3
- export { RxDBEntityChangeDirective } from './rxdb-change-detector.directive';
4
- export { provideRxDB } from './rxdb.provider';
5
- export * from './rxdb.service';
6
- export * from './use-action';
7
- export * from './use-state';
@@ -1,94 +0,0 @@
1
- import { ChangeDetectionStrategy, Component, provideZonelessChangeDetection } from '@angular/core';
2
- import { TestBed } from '@angular/core/testing';
3
- import { Subject } from 'rxjs';
4
- import { beforeEach, describe, expect, it, vi } from 'vitest';
5
- import { RxDBEntityChangeDirective } from './rxdb-change-detector.directive';
6
-
7
- // Mock entity type
8
- const mockEntity = {
9
- id: 'test-1',
10
- name: 'Test Entity'
11
- };
12
-
13
- const mockPatchesSubject = new Subject();
14
-
15
- // Mock getEntityStatus
16
- vi.mock('@aiao/rxdb', () => ({
17
- getEntityStatus: vi.fn(() => ({
18
- patches$: mockPatchesSubject.asObservable()
19
- }))
20
- }));
21
-
22
- @Component({
23
- // eslint-disable-next-line @angular-eslint/component-selector
24
- selector: 'test-component',
25
- standalone: true,
26
- imports: [RxDBEntityChangeDirective],
27
- template: '<div [rxdbChangeDetector]="entity"></div>',
28
- changeDetection: ChangeDetectionStrategy.OnPush
29
- })
30
- class TestComponent {
31
- entity = mockEntity;
32
- }
33
-
34
- describe('RxDBEntityChangeDirective', () => {
35
- beforeEach(() => {
36
- TestBed.configureTestingModule({
37
- providers: [provideZonelessChangeDetection()]
38
- });
39
- });
40
-
41
- it('should create directive', () => {
42
- const fixture = TestBed.createComponent(TestComponent);
43
- expect(fixture).toBeDefined();
44
- });
45
-
46
- it('should subscribe to patches$ on initialization', () => {
47
- const fixture = TestBed.createComponent(TestComponent);
48
- fixture.detectChanges();
49
-
50
- // Verify component was created successfully with the directive
51
- expect(fixture.componentInstance).toBeDefined();
52
-
53
- // 指令应该已经设置了订阅
54
- // Testing the actual subscription behavior requires more complex mocking
55
- });
56
-
57
- it('should handle debounceTime input', () => {
58
- @Component({
59
- // eslint-disable-next-line @angular-eslint/component-selector
60
- selector: 'test-debounce',
61
- standalone: true,
62
- imports: [RxDBEntityChangeDirective],
63
- template: '<div [rxdbChangeDetector]="entity" [debounceTime]="100"></div>',
64
- changeDetection: ChangeDetectionStrategy.OnPush
65
- })
66
- class TestDebounceComponent {
67
- entity = mockEntity;
68
- }
69
-
70
- const fixture = TestBed.createComponent(TestDebounceComponent);
71
- fixture.detectChanges();
72
-
73
- expect(fixture.componentInstance).toBeDefined();
74
- });
75
-
76
- it('should handle auditTime input', () => {
77
- @Component({
78
- // eslint-disable-next-line @angular-eslint/component-selector
79
- selector: 'test-audit',
80
- standalone: true,
81
- imports: [RxDBEntityChangeDirective],
82
- template: '<div [rxdbChangeDetector]="entity" [auditTime]="50"></div>',
83
- changeDetection: ChangeDetectionStrategy.OnPush
84
- })
85
- class TestAuditComponent {
86
- entity = mockEntity;
87
- }
88
-
89
- const fixture = TestBed.createComponent(TestAuditComponent);
90
- fixture.detectChanges();
91
-
92
- expect(fixture.componentInstance).toBeDefined();
93
- });
94
- });
@@ -1,35 +0,0 @@
1
- import { EntityType, getEntityStatus } from '@aiao/rxdb';
2
- import { ChangeDetectorRef, DestroyRef, Directive, effect, inject, input } from '@angular/core';
3
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
- import { auditTime, debounceTime, Subscription } from 'rxjs';
5
-
6
- /**
7
- * RxDB 实体变化指令
8
- * 如果你使用了 `changeDetection: ChangeDetectionStrategy.OnPush`
9
- * 那么正在输入的变化不会触发 angular 渲染机制,使用这个指令可以实现实时渲染
10
- *
11
- * @example
12
- * 当修改实体时,需要在多个地方预览修改变化时,可以使用这个指令
13
- */
14
- @Directive({ selector: '[rxdbChangeDetector]' })
15
- export class RxDBEntityChangeDirective {
16
- #destroyRef = inject(DestroyRef);
17
- #changeDetectorRef = inject(ChangeDetectorRef);
18
- #sub?: Subscription;
19
- public readonly rxdbChangeDetector = input<InstanceType<EntityType>>();
20
- public readonly debounceTime = input<number>(0);
21
- public readonly auditTime = input<number>(0);
22
-
23
- constructor() {
24
- effect(() => {
25
- const rxdbChange = this.rxdbChangeDetector();
26
- const dt = this.debounceTime();
27
- const at = this.auditTime();
28
- const status = getEntityStatus(rxdbChange);
29
- this.#sub?.unsubscribe();
30
- this.#sub = status.patches$
31
- .pipe(takeUntilDestroyed(this.#destroyRef), debounceTime(dt), auditTime(at))
32
- .subscribe(() => this.#changeDetectorRef.markForCheck());
33
- });
34
- }
35
- }
@@ -1,13 +0,0 @@
1
- import { RxDB } from '@aiao/rxdb';
2
- import { makeEnvironmentProviders } from '@angular/core';
3
-
4
- /**
5
- * RxDB 配置
6
- */
7
- export const provideRxDB = (useFactory?: () => RxDB) =>
8
- makeEnvironmentProviders([
9
- {
10
- provide: RxDB,
11
- useFactory
12
- }
13
- ]);
@@ -1,31 +0,0 @@
1
- import { provideZonelessChangeDetection } from '@angular/core';
2
- import { TestBed } from '@angular/core/testing';
3
- import { beforeEach, describe, expect, it } from 'vitest';
4
- import { RxDBService } from './rxdb.service';
5
-
6
- describe('RxDBService', () => {
7
- let service: RxDBService;
8
-
9
- beforeEach(() => {
10
- TestBed.configureTestingModule({
11
- providers: [provideZonelessChangeDetection(), RxDBService]
12
- });
13
- service = TestBed.inject(RxDBService);
14
- });
15
-
16
- it('should be created', () => {
17
- expect(service).toBeDefined();
18
- });
19
-
20
- it('should not throw when closing devtools if not open', () => {
21
- expect(() => service.closeDevTools()).not.toThrow();
22
- });
23
-
24
- it('should not throw when setting theme if devtools not open', () => {
25
- expect(() => service.setDevToolsTheme('dark')).not.toThrow();
26
- });
27
-
28
- // Note: Tests for devtools loading are skipped because they require
29
- // full RxDB setup with database connections, which is better tested
30
- // in integration tests with actual Angular applications.
31
- });
@@ -1,35 +0,0 @@
1
- import { ComponentRef, Injectable, ViewContainerRef } from '@angular/core';
2
- import { RxDBDevtools } from './devtools/devtools';
3
- import { RxDBDevToolsOptions } from './devtools/devtools.interface';
4
-
5
- @Injectable({
6
- providedIn: 'root'
7
- })
8
- export class RxDBService {
9
- #componentRef?: ComponentRef<RxDBDevtools>;
10
-
11
- async devtools(view: ViewContainerRef, options?: RxDBDevToolsOptions) {
12
- if (this.#componentRef) {
13
- this.closeDevTools();
14
- return;
15
- }
16
- const { RxDBDevtools } = await import('./devtools/devtools.js');
17
- const componentRef = view.createComponent(RxDBDevtools);
18
- this.#componentRef = componentRef;
19
- componentRef.setInput('componentRef', componentRef);
20
- if (options) {
21
- if (options.theme) this.setDevToolsTheme(options.theme);
22
- }
23
- componentRef.onDestroy(() => {
24
- this.#componentRef = undefined;
25
- });
26
- }
27
-
28
- closeDevTools() {
29
- this.#componentRef?.instance.close_rxdb_devtools();
30
- }
31
-
32
- setDevToolsTheme(theme: 'light' | 'dark') {
33
- this.#componentRef?.setInput('theme', theme);
34
- }
35
- }
package/src/test-setup.ts DELETED
@@ -1,14 +0,0 @@
1
- import '@angular/compiler';
2
-
3
- import { getTestBed } from '@angular/core/testing';
4
- import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing';
5
-
6
- const testBed = getTestBed();
7
- if (!testBed.platform) {
8
- testBed.initTestEnvironment(BrowserTestingModule, platformBrowserTesting());
9
- }
10
-
11
- import { afterEach } from 'vitest';
12
- afterEach(() => {
13
- getTestBed().resetTestingModule();
14
- });