ngx-zero 0.1.0

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 (79) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +194 -0
  3. package/dist/errors.d.ts +2 -0
  4. package/dist/errors.d.ts.map +1 -0
  5. package/dist/errors.js +4 -0
  6. package/dist/errors.js.map +1 -0
  7. package/dist/features.d.ts +9 -0
  8. package/dist/features.d.ts.map +1 -0
  9. package/dist/features.js +14 -0
  10. package/dist/features.js.map +1 -0
  11. package/dist/index.d.ts +12 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +8 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/inject-connection-state.d.ts +6 -0
  16. package/dist/inject-connection-state.d.ts.map +1 -0
  17. package/dist/inject-connection-state.js +41 -0
  18. package/dist/inject-connection-state.js.map +1 -0
  19. package/dist/inject-mutator.d.ts +4 -0
  20. package/dist/inject-mutator.d.ts.map +1 -0
  21. package/dist/inject-mutator.js +63 -0
  22. package/dist/inject-mutator.js.map +1 -0
  23. package/dist/inject-query.d.ts +7 -0
  24. package/dist/inject-query.d.ts.map +1 -0
  25. package/dist/inject-query.js +47 -0
  26. package/dist/inject-query.js.map +1 -0
  27. package/dist/inject-zero.d.ts +6 -0
  28. package/dist/inject-zero.d.ts.map +1 -0
  29. package/dist/inject-zero.js +16 -0
  30. package/dist/inject-zero.js.map +1 -0
  31. package/dist/instance-manager.d.ts +13 -0
  32. package/dist/instance-manager.d.ts.map +1 -0
  33. package/dist/instance-manager.js +140 -0
  34. package/dist/instance-manager.js.map +1 -0
  35. package/dist/mutator-call-tracker.d.ts +16 -0
  36. package/dist/mutator-call-tracker.d.ts.map +1 -0
  37. package/dist/mutator-call-tracker.js +53 -0
  38. package/dist/mutator-call-tracker.js.map +1 -0
  39. package/dist/mutator-ref.d.ts +35 -0
  40. package/dist/mutator-ref.d.ts.map +1 -0
  41. package/dist/mutator-ref.js +2 -0
  42. package/dist/mutator-ref.js.map +1 -0
  43. package/dist/options-diff.d.ts +6 -0
  44. package/dist/options-diff.d.ts.map +1 -0
  45. package/dist/options-diff.js +31 -0
  46. package/dist/options-diff.js.map +1 -0
  47. package/dist/provide-zero-testing.d.ts +7 -0
  48. package/dist/provide-zero-testing.d.ts.map +1 -0
  49. package/dist/provide-zero-testing.js +17 -0
  50. package/dist/provide-zero-testing.js.map +1 -0
  51. package/dist/provide-zero.d.ts +5 -0
  52. package/dist/provide-zero.d.ts.map +1 -0
  53. package/dist/provide-zero.js +12 -0
  54. package/dist/provide-zero.js.map +1 -0
  55. package/dist/query-identity.d.ts +15 -0
  56. package/dist/query-identity.d.ts.map +1 -0
  57. package/dist/query-identity.js +20 -0
  58. package/dist/query-identity.js.map +1 -0
  59. package/dist/query-ref.d.ts +27 -0
  60. package/dist/query-ref.d.ts.map +1 -0
  61. package/dist/query-ref.js +2 -0
  62. package/dist/query-ref.js.map +1 -0
  63. package/dist/query-view-controller.d.ts +48 -0
  64. package/dist/query-view-controller.d.ts.map +1 -0
  65. package/dist/query-view-controller.js +150 -0
  66. package/dist/query-view-controller.js.map +1 -0
  67. package/dist/types.d.ts +17 -0
  68. package/dist/types.d.ts.map +1 -0
  69. package/dist/types.js +2 -0
  70. package/dist/types.js.map +1 -0
  71. package/dist/utils.d.ts +11 -0
  72. package/dist/utils.d.ts.map +1 -0
  73. package/dist/utils.js +21 -0
  74. package/dist/utils.js.map +1 -0
  75. package/dist/with-bootstrap.d.ts +4 -0
  76. package/dist/with-bootstrap.d.ts.map +1 -0
  77. package/dist/with-bootstrap.js +8 -0
  78. package/dist/with-bootstrap.js.map +1 -0
  79. package/package.json +76 -0
@@ -0,0 +1,140 @@
1
+ import { computed, DestroyRef, effect, EnvironmentInjector, ErrorHandler, inject, InjectionToken, runInInjectionContext, signal, untracked, } from '@angular/core';
2
+ import { Zero } from '@rocicorp/zero';
3
+ import { ngxZeroError } from './errors.js';
4
+ import { diffZeroOptions, isExternalSource } from './options-diff.js';
5
+ import { tryCatch } from './utils.js';
6
+ export const ZERO_INSTANCE = new InjectionToken('ngx-zero/instance-manager');
7
+ export const ZERO_CONSTRUCTOR = new InjectionToken('ngx-zero/zero-constructor', { providedIn: 'root', factory: () => options => new Zero(options) });
8
+ export const ZERO_INSTANCE_HOOKS = new InjectionToken('ngx-zero/instance-hooks');
9
+ function resolveSourceFactory(source) {
10
+ return typeof source === 'function' ? source : () => source;
11
+ }
12
+ export class ZeroInstanceManager {
13
+ #injector = inject(EnvironmentInjector);
14
+ #constructZero = inject(ZERO_CONSTRUCTOR);
15
+ #featureHooks = inject(ZERO_INSTANCE_HOOKS, { optional: true }) ?? [];
16
+ #errorHandler = inject(ErrorHandler);
17
+ #sourceFactory;
18
+ #source = computed(() => runInInjectionContext(this.#injector, this.#sourceFactory));
19
+ #zeroInstance = signal(undefined);
20
+ zeroOrThrow = computed(() => {
21
+ const zero = this.#zeroInstance();
22
+ if (zero === undefined) {
23
+ throw ngxZeroError('Zero instance not found. Call `start()` first.');
24
+ }
25
+ return zero;
26
+ });
27
+ #started = false;
28
+ #rotationPending = false;
29
+ #rotationGeneration = signal(0);
30
+ #detach;
31
+ constructor(source) {
32
+ this.#sourceFactory = resolveSourceFactory(source);
33
+ inject(DestroyRef).onDestroy(() => this.#destroy());
34
+ }
35
+ start() {
36
+ if (this.#started) {
37
+ throw ngxZeroError('Zero instance manager already started.');
38
+ }
39
+ this.#started = true;
40
+ // Reconcile synchronously so component field initializers can use the
41
+ // instance; the effect reacts only to later changes and rotations.
42
+ let previousSource = this.#source();
43
+ this.#reconcile(previousSource, undefined);
44
+ effect(() => {
45
+ const source = this.#source();
46
+ this.#rotationGeneration();
47
+ if (source === previousSource && !this.#rotationPending) {
48
+ return;
49
+ }
50
+ const previous = previousSource;
51
+ previousSource = source;
52
+ untracked(() => this.#reconcile(source, previous));
53
+ }, { injector: this.#injector });
54
+ }
55
+ #connect({ auth }) {
56
+ const zero = this.#zeroInstance();
57
+ if (!zero || !auth) {
58
+ return;
59
+ }
60
+ void zero.connection.connect({ auth });
61
+ }
62
+ #reconcile(next, previous) {
63
+ const instance = this.#zeroInstance();
64
+ if (isExternalSource(next)) {
65
+ this.#rotationPending = false;
66
+ if (instance !== next.zero) {
67
+ this.#setInstance(next.zero, { isExternal: true });
68
+ }
69
+ return;
70
+ }
71
+ if (instance === undefined ||
72
+ previous === undefined ||
73
+ isExternalSource(previous) ||
74
+ this.#rotationPending) {
75
+ return this.#createInstance(next);
76
+ }
77
+ const verdict = diffZeroOptions(previous, next);
78
+ if (verdict === 'recreate') {
79
+ return this.#createInstance(next);
80
+ }
81
+ if (verdict === 'connect') {
82
+ return this.#connect(next);
83
+ }
84
+ }
85
+ #runInstanceCreatedHooks(zero) {
86
+ for (const hook of this.#featureHooks) {
87
+ runInInjectionContext(this.#injector, () => hook.onInstanceCreated?.(zero));
88
+ }
89
+ }
90
+ #createInstance(options) {
91
+ const zeroOptions = this.#prepareZeroOptions(options);
92
+ const { result: zero, error } = tryCatch(() => this.#constructZero(zeroOptions));
93
+ if (error) {
94
+ return this.#errorHandler.handleError(error);
95
+ }
96
+ this.#setInstance(zero);
97
+ }
98
+ #setInstance(zero, options = {}) {
99
+ const { isExternal = false } = options;
100
+ this.#destroy();
101
+ this.#zeroInstance.set(zero);
102
+ this.#rotationPending = false;
103
+ if (!isExternal) {
104
+ this.#detach = () => {
105
+ void zero.close();
106
+ };
107
+ this.#runInstanceCreatedHooks(zero);
108
+ }
109
+ }
110
+ #prepareZeroOptions(options) {
111
+ return {
112
+ ...options,
113
+ onClientStateNotFound: this.#onClientStateNotFound(options),
114
+ };
115
+ }
116
+ #onClientStateNotFound(options) {
117
+ return () => {
118
+ if (this.#rotationPending) {
119
+ return;
120
+ }
121
+ if (options.onClientStateNotFound) {
122
+ tryCatch(() => options.onClientStateNotFound?.());
123
+ return;
124
+ }
125
+ this.#scheduleRotation();
126
+ };
127
+ }
128
+ #scheduleRotation() {
129
+ if (this.#rotationPending) {
130
+ return;
131
+ }
132
+ this.#rotationPending = true;
133
+ this.#rotationGeneration.update(generation => generation + 1);
134
+ }
135
+ #destroy() {
136
+ this.#detach?.();
137
+ this.#detach = undefined;
138
+ }
139
+ }
140
+ //# sourceMappingURL=instance-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instance-manager.js","sourceRoot":"","sources":["../src/instance-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { type Signal } from '@angular/core';
2
+ import type { MutatorResultDetails } from '@rocicorp/zero';
3
+ import type { MutatorError } from './mutator-ref.js';
4
+ export declare class MutatorCallTracker {
5
+ #private;
6
+ readonly clientPending: Signal<boolean>;
7
+ readonly pending: Signal<boolean>;
8
+ readonly clientResult: Signal<MutatorResultDetails | undefined>;
9
+ readonly serverResult: Signal<MutatorResultDetails | undefined>;
10
+ readonly error: Signal<MutatorError | undefined>;
11
+ begin(): number;
12
+ settleClient(callId: number, details: MutatorResultDetails): void;
13
+ settleServer(callId: number, details: MutatorResultDetails): void;
14
+ destroy(): void;
15
+ }
16
+ //# sourceMappingURL=mutator-call-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutator-call-tracker.d.ts","sourceRoot":"","sources":["../src/mutator-call-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAUrD,qBAAa,kBAAkB;;IAM7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,OAAO,CAAC,CAGpC;IAEH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAG9B;IAEH,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,oBAAoB,GAAG,SAAS,CAAC,CAE7D;IAEF,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,oBAAoB,GAAG,SAAS,CAAC,CAE7D;IAEF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,YAAY,GAAG,SAAS,CAAC,CAS7C;IAEH,KAAK,IAAI,MAAM;IAQf,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,GAAG,IAAI;IAOjE,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,GAAG,IAAI;IAOjE,OAAO,IAAI,IAAI;CAOhB"}
@@ -0,0 +1,53 @@
1
+ import { computed, signal } from '@angular/core';
2
+ const IDLE = { callId: 0, client: undefined, server: undefined };
3
+ export class MutatorCallTracker {
4
+ #nextCallId = 0;
5
+ #destroyed = false;
6
+ #state = signal(IDLE);
7
+ clientPending = computed(() => {
8
+ const state = this.#state();
9
+ return state.callId !== 0 && state.client === undefined;
10
+ });
11
+ pending = computed(() => {
12
+ const state = this.#state();
13
+ return state.callId !== 0 && state.server === undefined;
14
+ });
15
+ clientResult = computed(() => this.#state().client);
16
+ serverResult = computed(() => this.#state().server);
17
+ error = computed(() => {
18
+ const state = this.#state();
19
+ if (state.client?.type === 'error') {
20
+ return state.client.error;
21
+ }
22
+ if (state.server?.type === 'error') {
23
+ return state.server.error;
24
+ }
25
+ return undefined;
26
+ });
27
+ begin() {
28
+ const callId = ++this.#nextCallId;
29
+ if (!this.#destroyed) {
30
+ this.#state.set({ callId, client: undefined, server: undefined });
31
+ }
32
+ return callId;
33
+ }
34
+ settleClient(callId, details) {
35
+ if (this.#isStale(callId)) {
36
+ return;
37
+ }
38
+ this.#state.update(state => ({ ...state, client: details }));
39
+ }
40
+ settleServer(callId, details) {
41
+ if (this.#isStale(callId)) {
42
+ return;
43
+ }
44
+ this.#state.update(state => ({ ...state, server: details }));
45
+ }
46
+ destroy() {
47
+ this.#destroyed = true;
48
+ }
49
+ #isStale(callId) {
50
+ return this.#destroyed || this.#state().callId !== callId;
51
+ }
52
+ }
53
+ //# sourceMappingURL=mutator-call-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutator-call-tracker.js","sourceRoot":"","sources":["../src/mutator-call-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAe,MAAM,eAAe,CAAC;AAU9D,MAAM,IAAI,GAAc,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AAE5E,MAAM,OAAO,kBAAkB;IAC7B,WAAW,GAAG,CAAC,CAAC;IAChB,UAAU,GAAG,KAAK,CAAC;IAEV,MAAM,GAAG,MAAM,CAAY,IAAI,CAAC,CAAC;IAEjC,aAAa,GAAoB,QAAQ,CAAC,GAAG,EAAE;QACtD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEM,OAAO,GAAoB,QAAQ,CAAC,GAAG,EAAE;QAChD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEM,YAAY,GAA6C,QAAQ,CACxE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,MAAM,CAC3B,CAAC;IAEO,YAAY,GAA6C,QAAQ,CACxE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,MAAM,CAC3B,CAAC;IAEO,KAAK,GAAqC,QAAQ,CAAC,GAAG,EAAE;QAC/D,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,OAAO,EAAE,CAAC;YACnC,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC;QAC5B,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,OAAO,EAAE,CAAC;YACnC,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC;QAC5B,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC,CAAC;IAEH,KAAK;QACH,MAAM,MAAM,GAAG,EAAE,IAAI,CAAC,WAAW,CAAC;QAClC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,YAAY,CAAC,MAAc,EAAE,OAA6B;QACxD,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED,YAAY,CAAC,MAAc,EAAE,OAA6B;QACxD,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO;QACL,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;IACzB,CAAC;IAED,QAAQ,CAAC,MAAc;QACrB,OAAO,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,MAAM,KAAK,MAAM,CAAC;IAC5D,CAAC;CACF"}
@@ -0,0 +1,35 @@
1
+ import type { Injector, Signal } from '@angular/core';
2
+ import type { MutatorResult, MutatorResultDetails, MutatorResultErrorDetails, ReadonlyJSONValue } from '@rocicorp/zero';
3
+ /** Error payload of a failed mutation phase. */
4
+ export type MutatorError = MutatorResultErrorDetails['error'];
5
+ /** Zero's (unexported) MutatorCallable parameter shape as a tuple. */
6
+ export type MutatorArgs<TInput extends ReadonlyJSONValue | undefined> = [
7
+ TInput
8
+ ] extends [undefined] ? [] : undefined extends TInput ? [args?: TInput] : [args: TInput];
9
+ /** Bound mutate() plus signals projecting the latest call's lifecycle. */
10
+ export interface MutatorRef<TInput extends ReadonlyJSONValue | undefined> {
11
+ /**
12
+ * Returned client/server promises never reject — rejections normalize to
13
+ * {type:'error', error:{type:'zero', message}}. Throws synchronously
14
+ * (state untouched) for setup errors. Safe to destructure.
15
+ */
16
+ mutate(...args: MutatorArgs<TInput>): MutatorResult;
17
+ /** True from mutate() until the latest call's optimistic apply settles. */
18
+ readonly clientPending: Signal<boolean>;
19
+ /**
20
+ * True from mutate() until the latest call's server outcome settles.
21
+ * Never settles on a local-only instance (cacheURL: null).
22
+ */
23
+ readonly pending: Signal<boolean>;
24
+ /** Latest call's optimistic outcome; undefined while idle or in flight. */
25
+ readonly clientResult: Signal<MutatorResultDetails | undefined>;
26
+ /** Latest call's authoritative outcome; undefined while idle or unconfirmed. */
27
+ readonly serverResult: Signal<MutatorResultDetails | undefined>;
28
+ /** Client error, else server error (rollback); cleared by next mutate(). */
29
+ readonly error: Signal<MutatorError | undefined>;
30
+ }
31
+ export interface InjectMutatorOptions {
32
+ /** Resolve dependencies from an explicit injection context. */
33
+ injector?: Injector;
34
+ }
35
+ //# sourceMappingURL=mutator-ref.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutator-ref.d.ts","sourceRoot":"","sources":["../src/mutator-ref.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EACpB,yBAAyB,EACzB,iBAAiB,EAClB,MAAM,gBAAgB,CAAC;AAExB,gDAAgD;AAChD,MAAM,MAAM,YAAY,GAAG,yBAAyB,CAAC,OAAO,CAAC,CAAC;AAE9D,sEAAsE;AACtE,MAAM,MAAM,WAAW,CAAC,MAAM,SAAS,iBAAiB,GAAG,SAAS,IAClE;IAAC,MAAM;CAAC,SAAS,CAAC,SAAS,CAAC,GACxB,EAAE,GACF,SAAS,SAAS,MAAM,GACtB,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,GACf,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAEvB,0EAA0E;AAC1E,MAAM,WAAW,UAAU,CAAC,MAAM,SAAS,iBAAiB,GAAG,SAAS;IACtE;;;;OAIG;IACH,MAAM,CAAC,GAAG,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,aAAa,CAAC;IAEpD,2EAA2E;IAC3E,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACxC;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAClC,2EAA2E;IAC3E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,oBAAoB,GAAG,SAAS,CAAC,CAAC;IAChE,gFAAgF;IAChF,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,oBAAoB,GAAG,SAAS,CAAC,CAAC;IAChE,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,YAAY,GAAG,SAAS,CAAC,CAAC;CAClD;AAED,MAAM,WAAW,oBAAoB;IACnC,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=mutator-ref.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutator-ref.js","sourceRoot":"","sources":["../src/mutator-ref.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ import type { ZeroOptions } from '@rocicorp/zero';
2
+ import type { ExternalZeroSource, ZeroOptionsOrExternalSource, ZeroReconcileVerdict } from './types.js';
3
+ export declare function isExternalSource(s: ZeroOptionsOrExternalSource): s is ExternalZeroSource;
4
+ export declare function diffZeroOptions(prev: ZeroOptions, next: ZeroOptions): ZeroReconcileVerdict;
5
+ export declare function diffAuth(prev: ZeroOptions['auth'], next: ZeroOptions['auth']): ZeroReconcileVerdict;
6
+ //# sourceMappingURL=options-diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options-diff.d.ts","sourceRoot":"","sources":["../src/options-diff.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EACV,kBAAkB,EAClB,2BAA2B,EAC3B,oBAAoB,EACrB,MAAM,YAAY,CAAC;AAEpB,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,2BAA2B,GAAG,CAAC,IAAI,kBAAkB,CAExF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,GAAG,oBAAoB,CAW1F;AAWD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,oBAAoB,CAanG"}
@@ -0,0 +1,31 @@
1
+ export function isExternalSource(s) {
2
+ return 'zero' in s;
3
+ }
4
+ export function diffZeroOptions(prev, next) {
5
+ for (const key of diffableKeys(prev, next)) {
6
+ const a = prev[key];
7
+ const b = next[key];
8
+ if (!Object.is(a, b)) {
9
+ return 'recreate';
10
+ }
11
+ }
12
+ return diffAuth(prev.auth, next.auth);
13
+ }
14
+ function diffableKeys(prev, next) {
15
+ const keys = new Set([...Object.keys(prev), ...Object.keys(next)]);
16
+ keys.delete('auth');
17
+ keys.delete('onClientStateNotFound');
18
+ return keys;
19
+ }
20
+ export function diffAuth(prev, next) {
21
+ const prevIsString = typeof prev === 'string';
22
+ const nextIsString = typeof next === 'string';
23
+ if (prevIsString !== nextIsString) {
24
+ return 'recreate';
25
+ }
26
+ if (nextIsString && !Object.is(prev, next)) {
27
+ return 'connect';
28
+ }
29
+ return 'noop';
30
+ }
31
+ //# sourceMappingURL=options-diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options-diff.js","sourceRoot":"","sources":["../src/options-diff.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,gBAAgB,CAAC,CAA8B;IAC7D,OAAO,MAAM,IAAI,CAAC,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAiB,EAAE,IAAiB;IAClE,KAAK,MAAM,GAAG,IAAI,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QAC3C,MAAM,CAAC,GAAI,IAAgC,CAAC,GAAG,CAAC,CAAC;QACjD,MAAM,CAAC,GAAI,IAAgC,CAAC,GAAG,CAAC,CAAC;QAEjD,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YACrB,OAAO,UAAU,CAAC;QACpB,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,YAAY,CAAC,IAAiB,EAAE,IAAiB;IACxD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAEnE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACpB,IAAI,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC;IAErC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,IAAyB,EAAE,IAAyB;IAC3E,MAAM,YAAY,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC;IAC9C,MAAM,YAAY,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC;IAE9C,IAAI,YAAY,KAAK,YAAY,EAAE,CAAC;QAClC,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,IAAI,YAAY,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QAC3C,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { EnvironmentProviders } from '@angular/core';
2
+ import type { ZeroOptions } from '@rocicorp/zero';
3
+ import type { ZeroFeature } from './features.js';
4
+ export type ZeroTestingOptions = Omit<ZeroOptions, 'cacheURL' | 'server'>;
5
+ export declare function provideZeroTesting(source: ZeroTestingOptions | (() => ZeroTestingOptions), ...features: ZeroFeature[]): EnvironmentProviders;
6
+ export declare function toTestingZeroOptions(user: ZeroTestingOptions): ZeroOptions;
7
+ //# sourceMappingURL=provide-zero-testing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provide-zero-testing.d.ts","sourceRoot":"","sources":["../src/provide-zero-testing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,QAAQ,CAAC,CAAC;AAE1E,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,kBAAkB,GAAG,CAAC,MAAM,kBAAkB,CAAC,EACvD,GAAG,QAAQ,EAAE,WAAW,EAAE,GACzB,oBAAoB,CAKtB;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,GAAG,WAAW,CAQ1E"}
@@ -0,0 +1,17 @@
1
+ import { provideZero } from './provide-zero.js';
2
+ export function provideZeroTesting(source, ...features) {
3
+ return provideZero(() => {
4
+ const user = typeof source === 'function' ? source() : source;
5
+ return toTestingZeroOptions(user);
6
+ }, ...features);
7
+ }
8
+ export function toTestingZeroOptions(user) {
9
+ return {
10
+ logLevel: 'error',
11
+ kvStore: 'mem',
12
+ ...user,
13
+ cacheURL: null,
14
+ server: null,
15
+ };
16
+ }
17
+ //# sourceMappingURL=provide-zero-testing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provide-zero-testing.js","sourceRoot":"","sources":["../src/provide-zero-testing.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAKhD,MAAM,UAAU,kBAAkB,CAChC,MAAuD,EACvD,GAAG,QAAuB;IAE1B,OAAO,WAAW,CAAC,GAAG,EAAE;QACtB,MAAM,IAAI,GAAG,OAAO,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;QAC9D,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC,EAAE,GAAG,QAAQ,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAwB;IAC3D,OAAO;QACL,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,KAAK;QACd,GAAG,IAAI;QACP,QAAQ,EAAE,IAAI;QACd,MAAM,EAAE,IAAI;KACE,CAAC;AACnB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { type EnvironmentProviders } from '@angular/core';
2
+ import { type ZeroFeature } from './features.js';
3
+ import type { ZeroInstanceOptions } from './types.js';
4
+ export declare function provideZero(source: ZeroInstanceOptions, ...features: ZeroFeature[]): EnvironmentProviders;
5
+ //# sourceMappingURL=provide-zero.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provide-zero.d.ts","sourceRoot":"","sources":["../src/provide-zero.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,eAAe,CAAC;AACvB,OAAO,EAA4B,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAE3E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,wBAAgB,WAAW,CACzB,MAAM,EAAE,mBAAmB,EAC3B,GAAG,QAAQ,EAAE,WAAW,EAAE,GACzB,oBAAoB,CAQtB"}
@@ -0,0 +1,12 @@
1
+ import { inject, makeEnvironmentProviders, provideEnvironmentInitializer, } from '@angular/core';
2
+ import { assertUniqueFeatureKinds } from './features.js';
3
+ import { ZERO_INSTANCE, ZeroInstanceManager } from './instance-manager.js';
4
+ export function provideZero(source, ...features) {
5
+ assertUniqueFeatureKinds(features);
6
+ return makeEnvironmentProviders([
7
+ ...features.flatMap(f => [...f.ɵproviders]),
8
+ { provide: ZERO_INSTANCE, useFactory: () => new ZeroInstanceManager(source) },
9
+ provideEnvironmentInitializer(() => inject(ZERO_INSTANCE).start()),
10
+ ]);
11
+ }
12
+ //# sourceMappingURL=provide-zero.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provide-zero.js","sourceRoot":"","sources":["../src/provide-zero.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,wBAAwB,EACxB,6BAA6B,GAE9B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,wBAAwB,EAAoB,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAG3E,MAAM,UAAU,WAAW,CACzB,MAA2B,EAC3B,GAAG,QAAuB;IAE1B,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IAEnC,OAAO,wBAAwB,CAAC;QAC9B,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;QAC3C,EAAE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,IAAI,mBAAmB,CAAC,MAAM,CAAC,EAAE;QAC7E,6BAA6B,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,KAAK,EAAE,CAAC;KACnE,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { AnyCustomQuery, AnyQuery, Zero } from '@rocicorp/zero';
2
+ /** Widest thunk result; the injectQuery overloads own the precise typing. */
3
+ export type AnyQueryOrRequest = AnyQuery | ReturnType<AnyCustomQuery>;
4
+ export type QueryKey = string;
5
+ /** A thunk result resolved against one Zero instance's current context. */
6
+ export interface ResolvedQuery {
7
+ readonly key: QueryKey;
8
+ readonly query: AnyQuery;
9
+ }
10
+ /**
11
+ * Resolves like `zero.materialize` does, so Zero defines identity. The key
12
+ * includes the format because `.one()` and `.limit(1)` share an AST hash.
13
+ */
14
+ export declare function resolveQuery(zero: Zero, value: AnyQueryOrRequest): ResolvedQuery;
15
+ //# sourceMappingURL=query-identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-identity.d.ts","sourceRoot":"","sources":["../src/query-identity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAQrE,6EAA6E;AAC7E,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,UAAU,CAAC,cAAc,CAAC,CAAC;AAEtE,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAE9B,2EAA2E;AAC3E,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,iBAAiB,GACvB,aAAa,CAgBf"}
@@ -0,0 +1,20 @@
1
+ import { addContextToQuery, asQueryInternals, queryInternalsTag, } from '@rocicorp/zero/bindings';
2
+ import { ngxZeroError } from './errors.js';
3
+ /**
4
+ * Resolves like `zero.materialize` does, so Zero defines identity. The key
5
+ * includes the format because `.one()` and `.limit(1)` share an AST hash.
6
+ */
7
+ export function resolveQuery(zero, value) {
8
+ const query = addContextToQuery(value, zero.context);
9
+ // An uncalled registry query passes through resolution untouched.
10
+ if (!(queryInternalsTag in query)) {
11
+ throw ngxZeroError('injectQuery() thunk must return a Query or a QueryRequest ' +
12
+ '(did you forget to call the registry query, e.g. `queries.issue.mine()`?).');
13
+ }
14
+ const internals = asQueryInternals(query);
15
+ return {
16
+ key: `${internals.hash()}:${JSON.stringify(internals.format)}`,
17
+ query,
18
+ };
19
+ }
20
+ //# sourceMappingURL=query-identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-identity.js","sourceRoot":"","sources":["../src/query-identity.ts"],"names":[],"mappings":"AACA,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAa3C;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,IAAU,EACV,KAAwB;IAExB,MAAM,KAAK,GAAG,iBAAiB,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAErD,kEAAkE;IAClE,IAAI,CAAC,CAAC,iBAAiB,IAAK,KAAgB,CAAC,EAAE,CAAC;QAC9C,MAAM,YAAY,CAChB,4DAA4D;YAC1D,4EAA4E,CAC/E,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC1C,OAAO;QACL,GAAG,EAAE,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE;QAC9D,KAAK;KACN,CAAC;AACJ,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { Injector, Signal } from '@angular/core';
2
+ import type { ErroredQuery, TTL } from '@rocicorp/zero';
3
+ /** Zero's ResultType plus 'disabled' for a thunk that returned falsy. */
4
+ export type QueryStatus = 'unknown' | 'complete' | 'error' | 'disabled';
5
+ /** TStatus lets the always-enabled overload exclude 'disabled'. */
6
+ export interface QueryRef<TData, TStatus extends QueryStatus = Exclude<QueryStatus, 'disabled'>> {
7
+ /** List queries: Row[]. `.one()` queries: Row | undefined. */
8
+ readonly data: Signal<TData>;
9
+ readonly status: Signal<TStatus>;
10
+ /** Cleared on any later successful emission or re-materialization. */
11
+ readonly error: Signal<ErroredQuery | undefined>;
12
+ /** Convenience for `status() === 'complete'`. */
13
+ readonly isComplete: Signal<boolean>;
14
+ /** Destroy and re-materialize; no-op while disabled or after host destroy. */
15
+ retry(): void;
16
+ /** Forward a TTL to the current view only — never re-materializes. */
17
+ updateTTL(ttl: TTL): void;
18
+ }
19
+ export interface InjectQueryOptions {
20
+ /** Passed to `zero.materialize(request, { ttl })` once per materialization. */
21
+ ttl?: TTL;
22
+ /** Keep previous data across an empty, unknown same-instance query change. */
23
+ keepPreviousData?: boolean;
24
+ /** Resolve dependencies from an explicit injection context. */
25
+ injector?: Injector;
26
+ }
27
+ //# sourceMappingURL=query-ref.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-ref.d.ts","sourceRoot":"","sources":["../src/query-ref.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAExD,yEAAyE;AACzE,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;AAExE,mEAAmE;AACnE,MAAM,WAAW,QAAQ,CACvB,KAAK,EACL,OAAO,SAAS,WAAW,GAAG,OAAO,CAAC,WAAW,EAAE,UAAU,CAAC;IAE9D,8DAA8D;IAC9D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACjC,sEAAsE;IACtE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,YAAY,GAAG,SAAS,CAAC,CAAC;IACjD,iDAAiD;IACjD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACrC,8EAA8E;IAC9E,KAAK,IAAI,IAAI,CAAC;IACd,sEAAsE;IACtE,SAAS,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IACjC,+EAA+E;IAC/E,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=query-ref.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-ref.js","sourceRoot":"","sources":["../src/query-ref.ts"],"names":[],"mappings":""}
@@ -0,0 +1,48 @@
1
+ import type { AnyQuery, TTL, Zero } from '@rocicorp/zero';
2
+ import type { QueryKey } from './query-identity.js';
3
+ import type { QueryStatus } from './query-ref.js';
4
+ export declare const DISABLED: unique symbol;
5
+ /** Deduped on `(zero, key)` upstream — reference equality is the fast path. */
6
+ export type QuerySpec = EnabledQuerySpec | DisabledQuerySpec;
7
+ export interface EnabledQuerySpec {
8
+ readonly zero: Zero;
9
+ readonly key: QueryKey;
10
+ /** Already resolved against `zero`'s context by resolveQuery(). */
11
+ readonly query: AnyQuery;
12
+ }
13
+ export interface DisabledQuerySpec {
14
+ readonly zero: Zero;
15
+ readonly key: typeof DISABLED;
16
+ readonly query: undefined;
17
+ }
18
+ export declare class QueryViewController {
19
+ #private;
20
+ readonly data: import("@angular/core").Signal<unknown>;
21
+ readonly status: import("@angular/core").Signal<QueryStatus>;
22
+ readonly error: import("@angular/core").Signal<{
23
+ message?: string | undefined;
24
+ details?: import("@rocicorp/zero").ReadonlyJSONValue | undefined;
25
+ error: "app";
26
+ id: string;
27
+ name: string;
28
+ } | {
29
+ details?: import("@rocicorp/zero").ReadonlyJSONValue | undefined;
30
+ error: "parse";
31
+ id: string;
32
+ name: string;
33
+ message: string;
34
+ } | undefined>;
35
+ constructor(options: {
36
+ keepPreviousData: boolean;
37
+ ttl: TTL | undefined;
38
+ });
39
+ /** Candidate-first: on a throw the prior session stays fully live. */
40
+ reconcile(spec: QuerySpec, options?: {
41
+ force?: boolean;
42
+ }): void;
43
+ /** `untracked` so it is callable from templates and effects without deps. */
44
+ retry(currentSpec: () => QuerySpec): void;
45
+ updateTTL(ttl: TTL): void;
46
+ destroy(): void;
47
+ }
48
+ //# sourceMappingURL=query-view-controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-view-controller.d.ts","sourceRoot":"","sources":["../src/query-view-controller.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,QAAQ,EAGR,GAAG,EAEH,IAAI,EACL,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGlD,eAAO,MAAM,QAAQ,EAAE,OAAO,MAAoC,CAAC;AAEnE,+EAA+E;AAC/E,MAAM,MAAM,SAAS,GAAG,gBAAgB,GAAG,iBAAiB,CAAC;AAE7D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC;IACvB,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,OAAO,QAAQ,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;CAC3B;AAeD,qBAAa,mBAAmB;;IAY9B,QAAQ,CAAC,IAAI,0CAA2B;IACxC,QAAQ,CAAC,MAAM,8CAA6B;IAC5C,QAAQ,CAAC,KAAK;;;;;;;;;;;;mBAA4B;gBAE9B,OAAO,EAAE;QACnB,gBAAgB,EAAE,OAAO,CAAC;QAC1B,GAAG,EAAE,GAAG,GAAG,SAAS,CAAC;KACtB;IAKD,sEAAsE;IACtE,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,IAAI;IAmInE,6EAA6E;IAC7E,KAAK,CAAC,WAAW,EAAE,MAAM,SAAS,GAAG,IAAI;IAczC,SAAS,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI;IAIzB,OAAO,IAAI,IAAI;CAOhB"}